源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,371 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
createAgentStatusController,
|
||||
selectAgentStatusControllerSnapshot,
|
||||
type AgentStatusSource,
|
||||
type AgentStatusStreamObserver
|
||||
} from "./AgentStatusController";
|
||||
|
||||
describe("createAgentStatusController", () => {
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(1_000_000);
|
||||
});
|
||||
|
||||
it("publishes loading immediately and accepts the bounded snapshot/refresh sequence", () => {
|
||||
let observer: AgentStatusStreamObserver | null = null;
|
||||
const source: AgentStatusSource = {
|
||||
open: (_query, nextObserver) => {
|
||||
observer = nextObserver;
|
||||
return vi.fn();
|
||||
}
|
||||
};
|
||||
const controller = createAgentStatusController({ source });
|
||||
|
||||
controller.open({
|
||||
scopeKey: "local:codex",
|
||||
agentSessionId: "session-1",
|
||||
reason: "slash-status"
|
||||
});
|
||||
expect(controller.getSnapshot()).toMatchObject({
|
||||
phase: "loading",
|
||||
isRefreshing: true,
|
||||
value: null
|
||||
});
|
||||
|
||||
observer!.onFrame({
|
||||
kind: "snapshot",
|
||||
value: {
|
||||
agentSessionId: "session-1",
|
||||
contextState: "available",
|
||||
contextWindow: { usedTokens: 120, totalTokens: 1_000 },
|
||||
limitsState: "available",
|
||||
limitsCapturedAtUnixMs: 999_000,
|
||||
limitsStale: true,
|
||||
quotas: []
|
||||
}
|
||||
});
|
||||
expect(controller.getSnapshot()).toMatchObject({
|
||||
phase: "ready",
|
||||
isRefreshing: true,
|
||||
value: { limitsStale: true }
|
||||
});
|
||||
|
||||
observer!.onFrame({
|
||||
kind: "refreshed",
|
||||
value: {
|
||||
agentSessionId: "session-1",
|
||||
contextState: "available",
|
||||
contextWindow: { usedTokens: 130, totalTokens: 1_000 },
|
||||
limitsState: "available",
|
||||
limitsCapturedAtUnixMs: 1_000_000,
|
||||
limitsStale: false,
|
||||
quotas: [{ quotaType: "session", percentRemaining: 80 }]
|
||||
}
|
||||
});
|
||||
observer!.onComplete();
|
||||
expect(controller.getSnapshot()).toMatchObject({
|
||||
phase: "ready",
|
||||
isRefreshing: false,
|
||||
errorCode: null,
|
||||
value: {
|
||||
limitsStale: false,
|
||||
quotas: [{ quotaType: "session", percentRemaining: 80 }]
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("cancels the visible request at 30 seconds and fences late owner results", () => {
|
||||
let observer: AgentStatusStreamObserver | null = null;
|
||||
const unsubscribe = vi.fn();
|
||||
const controller = createAgentStatusController({
|
||||
source: {
|
||||
open: (_query, nextObserver) => {
|
||||
observer = nextObserver;
|
||||
return unsubscribe;
|
||||
}
|
||||
}
|
||||
});
|
||||
controller.open({ scopeKey: "shared:1", reason: "slash-status" });
|
||||
|
||||
vi.advanceTimersByTime(30_000);
|
||||
expect(controller.getSnapshot()).toMatchObject({
|
||||
phase: "error",
|
||||
isRefreshing: false,
|
||||
errorCode: "timeout"
|
||||
});
|
||||
expect(unsubscribe).toHaveBeenCalledOnce();
|
||||
|
||||
observer!.onFrame({
|
||||
kind: "refreshed",
|
||||
value: {
|
||||
agentSessionId: null,
|
||||
contextState: "unavailable",
|
||||
contextWindow: null,
|
||||
limitsState: "available",
|
||||
limitsCapturedAtUnixMs: 1_030_000,
|
||||
quotas: []
|
||||
}
|
||||
});
|
||||
observer!.onComplete();
|
||||
expect(controller.getSnapshot()).toMatchObject({
|
||||
phase: "error",
|
||||
isRefreshing: false,
|
||||
errorCode: "timeout",
|
||||
value: null
|
||||
});
|
||||
});
|
||||
|
||||
it("fences closed and replaced requests from late writes", () => {
|
||||
const observers: AgentStatusStreamObserver[] = [];
|
||||
const unsubscribes: ReturnType<typeof vi.fn>[] = [];
|
||||
const controller = createAgentStatusController({
|
||||
source: {
|
||||
open: (_query, observer) => {
|
||||
observers.push(observer);
|
||||
const unsubscribe = vi.fn();
|
||||
unsubscribes.push(unsubscribe);
|
||||
return unsubscribe;
|
||||
}
|
||||
}
|
||||
});
|
||||
controller.open({ scopeKey: "local:a", reason: "slash-status" });
|
||||
controller.open({ scopeKey: "local:b", reason: "slash-status" });
|
||||
expect(unsubscribes[0]).toHaveBeenCalledOnce();
|
||||
|
||||
observers[0]!.onFrame({
|
||||
kind: "snapshot",
|
||||
value: {
|
||||
contextState: "unavailable",
|
||||
limitsState: "available",
|
||||
quotas: [{ quotaType: "weekly", percentRemaining: 1 }]
|
||||
}
|
||||
});
|
||||
expect(controller.getSnapshot().query?.scopeKey).toBe("local:b");
|
||||
expect(controller.getSnapshot().value).toBeNull();
|
||||
|
||||
controller.close();
|
||||
observers[1]!.onFrame({
|
||||
kind: "snapshot",
|
||||
value: {
|
||||
contextState: "unavailable",
|
||||
limitsState: "available",
|
||||
quotas: [{ quotaType: "weekly", percentRemaining: 2 }]
|
||||
}
|
||||
});
|
||||
expect(controller.getSnapshot().value).toBeNull();
|
||||
});
|
||||
|
||||
it("fences terminal streams and cleans up synchronous completion", () => {
|
||||
let observer: AgentStatusStreamObserver | null = null;
|
||||
const unsubscribe = vi.fn();
|
||||
const controller = createAgentStatusController({
|
||||
source: {
|
||||
open: (_query, nextObserver) => {
|
||||
observer = nextObserver;
|
||||
nextObserver.onComplete();
|
||||
return unsubscribe;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
controller.open({ scopeKey: "local:codex", reason: "slash-status" });
|
||||
expect(unsubscribe).toHaveBeenCalledOnce();
|
||||
expect(controller.getSnapshot()).toMatchObject({
|
||||
phase: "error",
|
||||
isRefreshing: false,
|
||||
errorCode: "unavailable",
|
||||
value: null
|
||||
});
|
||||
|
||||
observer!.onFrame({
|
||||
kind: "refreshed",
|
||||
value: {
|
||||
contextState: "unavailable",
|
||||
limitsState: "available",
|
||||
quotas: [{ quotaType: "weekly", percentRemaining: 99 }]
|
||||
}
|
||||
});
|
||||
expect(controller.getSnapshot().value).toBeNull();
|
||||
});
|
||||
|
||||
it("selects status only for the exact target and caller-visible session", () => {
|
||||
const snapshot = {
|
||||
query: {
|
||||
scopeKey: "shared-agent:one",
|
||||
agentSessionId: "binding-1",
|
||||
reason: "slash-status" as const
|
||||
},
|
||||
value: {
|
||||
contextState: "available" as const,
|
||||
limitsState: "available" as const,
|
||||
quotas: []
|
||||
},
|
||||
phase: "ready" as const,
|
||||
isRefreshing: false,
|
||||
errorCode: null
|
||||
};
|
||||
|
||||
expect(
|
||||
selectAgentStatusControllerSnapshot(snapshot, {
|
||||
scopeKey: "shared-agent:one",
|
||||
agentSessionId: "binding-1"
|
||||
})
|
||||
).toBe(snapshot);
|
||||
expect(
|
||||
selectAgentStatusControllerSnapshot(snapshot, {
|
||||
scopeKey: "shared-agent:two",
|
||||
agentSessionId: "binding-1"
|
||||
}).phase
|
||||
).toBe("idle");
|
||||
expect(
|
||||
selectAgentStatusControllerSnapshot(snapshot, {
|
||||
scopeKey: "shared-agent:one",
|
||||
agentSessionId: "binding-2"
|
||||
}).value
|
||||
).toBeNull();
|
||||
expect(
|
||||
selectAgentStatusControllerSnapshot(snapshot, {
|
||||
scopeKey: "shared-agent:one",
|
||||
agentSessionId: "binding-1",
|
||||
reasons: ["agent-config"]
|
||||
}).phase
|
||||
).toBe("idle");
|
||||
});
|
||||
|
||||
it("retains snapshots for one hour and debounces forced refresh for five seconds", () => {
|
||||
let call = 0;
|
||||
const open = vi.fn<AgentStatusSource["open"]>((_query, observer) => {
|
||||
call++;
|
||||
if (call === 1) {
|
||||
observer.onFrame({
|
||||
kind: "snapshot",
|
||||
value: {
|
||||
contextState: "unavailable",
|
||||
limitsState: "available",
|
||||
limitsCapturedAtUnixMs: Date.now(),
|
||||
quotas: []
|
||||
}
|
||||
});
|
||||
observer.onComplete();
|
||||
}
|
||||
return vi.fn();
|
||||
});
|
||||
const controller = createAgentStatusController({ source: { open } });
|
||||
const query = {
|
||||
scopeKey: "local:codex",
|
||||
reason: "agent-config" as const,
|
||||
forceRefresh: true
|
||||
};
|
||||
|
||||
controller.open(query);
|
||||
controller.open(query);
|
||||
expect(open).toHaveBeenCalledOnce();
|
||||
|
||||
vi.advanceTimersByTime(5_000);
|
||||
controller.open(query);
|
||||
expect(open).toHaveBeenCalledTimes(2);
|
||||
expect(controller.getSnapshot().value).not.toBeNull();
|
||||
|
||||
controller.close();
|
||||
vi.advanceTimersByTime(60 * 60_000 + 1);
|
||||
controller.open({ ...query, forceRefresh: false });
|
||||
expect(controller.getSnapshot()).toMatchObject({
|
||||
phase: "loading",
|
||||
value: null
|
||||
});
|
||||
});
|
||||
|
||||
it("retains the last value but reports a zero-frame refresh as unavailable", () => {
|
||||
const observers: AgentStatusStreamObserver[] = [];
|
||||
const controller = createAgentStatusController({
|
||||
source: {
|
||||
open: (_query, observer) => {
|
||||
observers.push(observer);
|
||||
return vi.fn();
|
||||
}
|
||||
}
|
||||
});
|
||||
const query = { scopeKey: "local:codex", reason: "agent-config" as const };
|
||||
|
||||
controller.open(query);
|
||||
observers[0]!.onFrame({
|
||||
kind: "refreshed",
|
||||
value: {
|
||||
contextState: "unavailable",
|
||||
limitsState: "available",
|
||||
quotas: []
|
||||
}
|
||||
});
|
||||
observers[0]!.onComplete();
|
||||
controller.open(query);
|
||||
expect(controller.getSnapshot()).toMatchObject({
|
||||
phase: "ready",
|
||||
isRefreshing: true,
|
||||
errorCode: null,
|
||||
value: { limitsState: "available" }
|
||||
});
|
||||
|
||||
observers[1]!.onComplete();
|
||||
expect(controller.getSnapshot()).toMatchObject({
|
||||
phase: "ready",
|
||||
isRefreshing: false,
|
||||
errorCode: "unavailable",
|
||||
value: { limitsState: "available" }
|
||||
});
|
||||
});
|
||||
|
||||
it("rejects frames for another session and invalid frame sequences", () => {
|
||||
const observers: AgentStatusStreamObserver[] = [];
|
||||
const controller = createAgentStatusController({
|
||||
source: {
|
||||
open: (_query, observer) => {
|
||||
observers.push(observer);
|
||||
return vi.fn();
|
||||
}
|
||||
}
|
||||
});
|
||||
controller.open({
|
||||
scopeKey: "shared-agent:one",
|
||||
agentSessionId: "binding-1",
|
||||
reason: "slash-status"
|
||||
});
|
||||
observers[0]!.onFrame({
|
||||
kind: "refreshed",
|
||||
value: {
|
||||
agentSessionId: "binding-other",
|
||||
contextState: "available",
|
||||
limitsState: "available",
|
||||
quotas: []
|
||||
}
|
||||
});
|
||||
expect(controller.getSnapshot()).toMatchObject({
|
||||
phase: "error",
|
||||
errorCode: "unavailable",
|
||||
value: null
|
||||
});
|
||||
|
||||
controller.open({ scopeKey: "local:codex", reason: "agent-config" });
|
||||
observers[1]!.onFrame({
|
||||
kind: "refreshed",
|
||||
value: {
|
||||
contextState: "unavailable",
|
||||
limitsState: "available",
|
||||
quotas: []
|
||||
}
|
||||
});
|
||||
observers[1]!.onFrame({
|
||||
kind: "refreshed",
|
||||
value: {
|
||||
contextState: "unavailable",
|
||||
limitsState: "available",
|
||||
quotas: []
|
||||
}
|
||||
});
|
||||
expect(controller.getSnapshot()).toMatchObject({
|
||||
phase: "ready",
|
||||
errorCode: "unavailable",
|
||||
value: { limitsState: "available" }
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user