@songsid/agend 2.3.2-beta.1 → 2.3.2-beta.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/THIRD_PARTY_NOTICES.md +40 -0
- package/dist/agent-cli.js +69 -2
- package/dist/agent-cli.js.map +1 -1
- package/dist/agent-endpoint.js +11 -0
- package/dist/agent-endpoint.js.map +1 -1
- package/dist/agent-whats-new.js +3 -0
- package/dist/agent-whats-new.js.map +1 -1
- package/dist/antigravity-usage-scan.d.ts +58 -0
- package/dist/antigravity-usage-scan.js +257 -0
- package/dist/antigravity-usage-scan.js.map +1 -0
- package/dist/antigravity-usage-worker.d.ts +1 -0
- package/dist/antigravity-usage-worker.js +10 -0
- package/dist/antigravity-usage-worker.js.map +1 -0
- package/dist/auth-api.js +4 -0
- package/dist/auth-api.js.map +1 -1
- package/dist/backend/kiro-classic-archive.d.ts +52 -0
- package/dist/backend/kiro-classic-archive.js +444 -0
- package/dist/backend/kiro-classic-archive.js.map +1 -0
- package/dist/backend/kiro-identity.d.ts +83 -0
- package/dist/backend/kiro-identity.js +144 -0
- package/dist/backend/kiro-identity.js.map +1 -1
- package/dist/backend/kiro-migration-verify.d.ts +10 -0
- package/dist/backend/kiro-migration-verify.js +52 -0
- package/dist/backend/kiro-migration-verify.js.map +1 -0
- package/dist/backend/kiro-retired-model.d.ts +62 -0
- package/dist/backend/kiro-retired-model.js +160 -0
- package/dist/backend/kiro-retired-model.js.map +1 -0
- package/dist/backend/kiro-v2-store-worker.js +21 -1
- package/dist/backend/kiro-v2-store-worker.js.map +1 -1
- package/dist/backend/kiro-v2-store.d.ts +8 -0
- package/dist/backend/kiro-v2-store.js.map +1 -1
- package/dist/backend/kiro.d.ts +169 -2
- package/dist/backend/kiro.js +703 -28
- package/dist/backend/kiro.js.map +1 -1
- package/dist/backend/types.d.ts +108 -0
- package/dist/backend/types.js +9 -0
- package/dist/backend/types.js.map +1 -1
- package/dist/backend-signin-guide.d.ts +1 -0
- package/dist/backend-signin-guide.js +9 -0
- package/dist/backend-signin-guide.js.map +1 -0
- package/dist/backend-signin-pending.d.ts +10 -0
- package/dist/backend-signin-pending.js +44 -0
- package/dist/backend-signin-pending.js.map +1 -0
- package/dist/browser-backend-signins.d.ts +56 -0
- package/dist/browser-backend-signins.js +189 -0
- package/dist/browser-backend-signins.js.map +1 -0
- package/dist/cache-ledger.d.ts +38 -2
- package/dist/cache-ledger.js +133 -8
- package/dist/cache-ledger.js.map +1 -1
- package/dist/cache-prices.d.ts +2 -1
- package/dist/cache-prices.js +5 -2
- package/dist/cache-prices.js.map +1 -1
- package/dist/cache-service.d.ts +68 -0
- package/dist/cache-service.js +355 -13
- package/dist/cache-service.js.map +1 -1
- package/dist/channel/adapters/discord.d.ts +11 -0
- package/dist/channel/adapters/discord.js +71 -14
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/ipc-timeouts.js +3 -0
- package/dist/channel/ipc-timeouts.js.map +1 -1
- package/dist/channel/mcp-tools.js +41 -2
- package/dist/channel/mcp-tools.js.map +1 -1
- package/dist/channel/tool-router.js +2 -1
- package/dist/channel/tool-router.js.map +1 -1
- package/dist/classic-channel-manager.d.ts +11 -0
- package/dist/classic-channel-manager.js +39 -1
- package/dist/classic-channel-manager.js.map +1 -1
- package/dist/cli.js +54 -2
- package/dist/cli.js.map +1 -1
- package/dist/config-validator.d.ts +7 -1
- package/dist/config-validator.js +55 -10
- package/dist/config-validator.js.map +1 -1
- package/dist/config.d.ts +19 -0
- package/dist/config.js +33 -1
- package/dist/config.js.map +1 -1
- package/dist/cpu-quota.d.ts +23 -0
- package/dist/cpu-quota.js +86 -0
- package/dist/cpu-quota.js.map +1 -0
- package/dist/daemon.d.ts +68 -0
- package/dist/daemon.js +448 -26
- package/dist/daemon.js.map +1 -1
- package/dist/dashboard-permissions.d.ts +31 -6
- package/dist/dashboard-permissions.js +84 -9
- package/dist/dashboard-permissions.js.map +1 -1
- package/dist/doctor.js +2 -1
- package/dist/doctor.js.map +1 -1
- package/dist/fleet-control-audit.d.ts +1 -1
- package/dist/fleet-control-audit.js +3 -0
- package/dist/fleet-control-audit.js.map +1 -1
- package/dist/fleet-manager.d.ts +133 -2
- package/dist/fleet-manager.js +905 -94
- package/dist/fleet-manager.js.map +1 -1
- package/dist/forged-envelope-scan.d.ts +9 -0
- package/dist/forged-envelope-scan.js +30 -5
- package/dist/forged-envelope-scan.js.map +1 -1
- package/dist/general-knowledge/skills/credential-profiles/SKILL.md +5 -2
- package/dist/general-knowledge/skills/kiro-engine-migration/SKILL.md +24 -1
- package/dist/general-knowledge/skills/web-appearance/SKILL.canvas-worker-off.md +49 -1
- package/dist/general-knowledge/skills/web-appearance/SKILL.md +49 -1
- package/dist/general-knowledge/skills/web-dashboard/SKILL.canvas-worker-off.md +47 -9
- package/dist/general-knowledge/skills/web-dashboard/SKILL.md +54 -11
- package/dist/instance-config-impact.js +10 -5
- package/dist/instance-config-impact.js.map +1 -1
- package/dist/instance-lifecycle.d.ts +23 -0
- package/dist/instance-lifecycle.js +62 -12
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/kiro-db-reader.d.ts +5 -0
- package/dist/kiro-db-reader.js +18 -0
- package/dist/kiro-db-reader.js.map +1 -1
- package/dist/kiro-engine-status.d.ts +2 -0
- package/dist/kiro-engine-status.js +9 -0
- package/dist/kiro-engine-status.js.map +1 -1
- package/dist/kiro-migrate.d.ts +60 -0
- package/dist/kiro-migrate.js +160 -0
- package/dist/kiro-migrate.js.map +1 -0
- package/dist/kiro-session-proof.d.ts +41 -0
- package/dist/kiro-session-proof.js +89 -0
- package/dist/kiro-session-proof.js.map +1 -0
- package/dist/kiro-transcript-lane.d.ts +2 -0
- package/dist/kiro-transcript-lane.js.map +1 -1
- package/dist/kiro-transcript-worker.js +1 -0
- package/dist/kiro-transcript-worker.js.map +1 -1
- package/dist/kiro-tui-forensic.d.ts +12 -0
- package/dist/kiro-tui-forensic.js +110 -0
- package/dist/kiro-tui-forensic.js.map +1 -0
- package/dist/kiro-usage-run.d.ts +7 -0
- package/dist/kiro-usage-run.js +39 -0
- package/dist/kiro-usage-run.js.map +1 -0
- package/dist/kiro-usage-scan.d.ts +49 -0
- package/dist/kiro-usage-scan.js +223 -0
- package/dist/kiro-usage-scan.js.map +1 -0
- package/dist/kiro-usage-worker.d.ts +1 -0
- package/dist/kiro-usage-worker.js +10 -0
- package/dist/kiro-usage-worker.js.map +1 -0
- package/dist/kiro-usage.d.ts +58 -0
- package/dist/kiro-usage.js +310 -0
- package/dist/kiro-usage.js.map +1 -0
- package/dist/locale.js +230 -8
- package/dist/locale.js.map +1 -1
- package/dist/log-service.js +1 -1
- package/dist/log-service.js.map +1 -1
- package/dist/login-url.d.ts +4 -0
- package/dist/login-url.js +22 -0
- package/dist/login-url.js.map +1 -0
- package/dist/needs-you-hub.d.ts +2 -1
- package/dist/needs-you-hub.js +1 -1
- package/dist/needs-you-hub.js.map +1 -1
- package/dist/needs-you.d.ts +10 -2
- package/dist/needs-you.js +10 -2
- package/dist/needs-you.js.map +1 -1
- package/dist/notice-delivery.d.ts +16 -0
- package/dist/notice-delivery.js +35 -0
- package/dist/notice-delivery.js.map +1 -0
- package/dist/office-share-page.d.ts +16 -0
- package/dist/office-share-page.js +85 -0
- package/dist/office-share-page.js.map +1 -0
- package/dist/office-share-service.d.ts +91 -0
- package/dist/office-share-service.js +176 -0
- package/dist/office-share-service.js.map +1 -0
- package/dist/office-share.d.ts +268 -0
- package/dist/office-share.js +574 -0
- package/dist/office-share.js.map +1 -0
- package/dist/opencode-usage-scan.d.ts +28 -0
- package/dist/opencode-usage-scan.js +92 -0
- package/dist/opencode-usage-scan.js.map +1 -0
- package/dist/opencode-usage-worker.d.ts +1 -0
- package/dist/opencode-usage-worker.js +10 -0
- package/dist/opencode-usage-worker.js.map +1 -0
- package/dist/outbound-handlers.js +22 -2
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/outbound-schemas.d.ts +65 -2
- package/dist/outbound-schemas.js +56 -2
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/public-web-gateway.js +7 -1
- package/dist/public-web-gateway.js.map +1 -1
- package/dist/quickstart-api.js +13 -2
- package/dist/quickstart-api.js.map +1 -1
- package/dist/quickstart.js +2 -1
- package/dist/quickstart.js.map +1 -1
- package/dist/remote-card-answer.d.ts +83 -0
- package/dist/remote-card-answer.js +208 -0
- package/dist/remote-card-answer.js.map +1 -0
- package/dist/remote-card-prompt.d.ts +38 -0
- package/dist/remote-card-prompt.js +86 -0
- package/dist/remote-card-prompt.js.map +1 -0
- package/dist/reply-triggers.d.ts +2 -0
- package/dist/reply-triggers.js +3 -0
- package/dist/reply-triggers.js.map +1 -0
- package/dist/settings-api.d.ts +2 -0
- package/dist/settings-api.js +41 -16
- package/dist/settings-api.js.map +1 -1
- package/dist/settings-change.js +20 -14
- package/dist/settings-change.js.map +1 -1
- package/dist/settings-effect.js +7 -1
- package/dist/settings-effect.js.map +1 -1
- package/dist/settings-instance-patch.js +4 -1
- package/dist/settings-instance-patch.js.map +1 -1
- package/dist/setup-form.d.ts +1 -1
- package/dist/setup-form.js +55 -6
- package/dist/setup-form.js.map +1 -1
- package/dist/setup-host.d.ts +9 -0
- package/dist/setup-host.js +127 -6
- package/dist/setup-host.js.map +1 -1
- package/dist/setup-signin-assets.d.ts +2 -0
- package/dist/setup-signin-assets.js +6 -0
- package/dist/setup-signin-assets.js.map +1 -0
- package/dist/setup-wizard.js +2 -0
- package/dist/setup-wizard.js.map +1 -1
- package/dist/structured-signin-transport.d.ts +8 -0
- package/dist/structured-signin-transport.js +79 -0
- package/dist/structured-signin-transport.js.map +1 -0
- package/dist/structured-signin.d.ts +131 -0
- package/dist/structured-signin.js +388 -0
- package/dist/structured-signin.js.map +1 -0
- package/dist/tool-permissions.js +29 -0
- package/dist/tool-permissions.js.map +1 -1
- package/dist/topic-commands.js +6 -2
- package/dist/topic-commands.js.map +1 -1
- package/dist/transcript-sources.d.ts +27 -2
- package/dist/transcript-sources.js +104 -40
- package/dist/transcript-sources.js.map +1 -1
- package/dist/turn-reply-guard.d.ts +1 -1
- package/dist/turn-reply-guard.js +1 -1
- package/dist/turn-reply-guard.js.map +1 -1
- package/dist/types.d.ts +33 -8
- package/dist/ui/backend-signin.js +63 -10
- package/dist/ui/chat-store.js +3 -2
- package/dist/ui/chat-strings.js +4 -4
- package/dist/ui/fleet-office-editor.js +68 -11
- package/dist/ui/fleet-office-layout.js +110 -35
- package/dist/ui/fleet-office-model.js +6 -3
- package/dist/ui/fleet-office-overview.js +167 -0
- package/dist/ui/fleet-office-pack.d.ts +13 -3
- package/dist/ui/fleet-office-pack.js +214 -24
- package/dist/ui/fleet-office-skin.js +98 -23
- package/dist/ui/fleet-office-store.js +82 -5
- package/dist/ui/fleet-office-view.js +5 -4
- package/dist/ui/fleet-office-zones.js +232 -21
- package/dist/ui/fleet-office.js +549 -186
- package/dist/ui/fleet-usage.js +19 -15
- package/dist/ui/office-share-dialog.js +145 -0
- package/dist/ui/office-share-page.js +164 -0
- package/dist/ui/panel-chat.js +22 -3
- package/dist/ui/panel-log.js +4 -4
- package/dist/ui/panel-needs.js +5 -5
- package/dist/ui/panel-settings.js +38 -12
- package/dist/ui/settings-dialogs.js +8 -1
- package/dist/ui/settings-guests.js +17 -7
- package/dist/ui/settings-model.js +22 -6
- package/dist/ui/settings-registry.js +4 -0
- package/dist/ui/settings-strings.js +18 -2
- package/dist/ui/shared/app-i18n.js +4 -2
- package/dist/ui/shared/app-shell.js +14 -6
- package/dist/ui/shared/app-stream.js +2 -1
- package/dist/ui/shared/app.css +85 -4
- package/dist/ui/shared/office/cozy.png +0 -0
- package/dist/ui/shared/side-panel.js +95 -0
- package/dist/ui/structured-signin.js +115 -0
- package/dist/usage-report.d.ts +20 -0
- package/dist/usage-report.js +54 -17
- package/dist/usage-report.js.map +1 -1
- package/dist/usage-rollup.d.ts +9 -1
- package/dist/usage-rollup.js +20 -4
- package/dist/usage-rollup.js.map +1 -1
- package/dist/web-api.d.ts +23 -1
- package/dist/web-api.js +292 -3
- package/dist/web-api.js.map +1 -1
- package/dist/web-auth.js +1 -1
- package/dist/web-auth.js.map +1 -1
- package/dist/web-backend-login.d.ts +1 -7
- package/dist/web-backend-login.js +2 -24
- package/dist/web-backend-login.js.map +1 -1
- package/dist/web-office-acts.d.ts +173 -0
- package/dist/web-office-acts.js +285 -0
- package/dist/web-office-acts.js.map +1 -0
- package/dist/web-office-pack-read.d.ts +35 -0
- package/dist/web-office-pack-read.js +252 -0
- package/dist/web-office-pack-read.js.map +1 -0
- package/dist/web-office-pack-tools.d.ts +232 -0
- package/dist/web-office-pack-tools.js +754 -0
- package/dist/web-office-pack-tools.js.map +1 -0
- package/dist/web-office-skins.d.ts +71 -6
- package/dist/web-office-skins.js +321 -35
- package/dist/web-office-skins.js.map +1 -1
- package/dist/web-office-store.d.ts +5 -2
- package/dist/web-office-store.js +69 -10
- package/dist/web-office-store.js.map +1 -1
- package/dist/web-settings-patch.d.ts +2 -1
- package/dist/web-settings-patch.js +4 -1
- package/dist/web-settings-patch.js.map +1 -1
- package/dist/working-recovery.d.ts +2 -2
- package/dist/working-recovery.js +43 -8
- package/dist/working-recovery.js.map +1 -1
- package/dist/working-state-journal.d.ts +2 -0
- package/dist/working-state-journal.js +16 -1
- package/dist/working-state-journal.js.map +1 -1
- package/package.json +3 -2
- package/templates/windows-shortcuts.ps1 +155 -140
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/** Non-secret onboarding hints. Never used as proof that credentials work. */
|
|
2
|
+
import { closeSync, constants, fstatSync, openSync, readSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { atomicWriteFileSync } from "./atomic-write.js";
|
|
5
|
+
export const ONBOARDING_BACKENDS = ["kiro-cli", "claude-code", "codex", "antigravity"];
|
|
6
|
+
export function onboardingBackends(value) {
|
|
7
|
+
if (!Array.isArray(value) || value.length > 4 || value.some(v => typeof v !== "string"
|
|
8
|
+
|| !ONBOARDING_BACKENDS.includes(v)))
|
|
9
|
+
return null;
|
|
10
|
+
return [...new Set(value)];
|
|
11
|
+
}
|
|
12
|
+
export function readPendingBackendSignIns(dataDir) {
|
|
13
|
+
const empty = { version: 1, selected: [], pending: [] };
|
|
14
|
+
let fd;
|
|
15
|
+
try {
|
|
16
|
+
fd = openSync(join(dataDir, "backend-signin-pending.json"), constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0));
|
|
17
|
+
const stat = fstatSync(fd);
|
|
18
|
+
if (!stat.isFile() || stat.size > 4096 || (process.getuid && stat.uid !== process.getuid()) || (stat.mode & 0o077))
|
|
19
|
+
return empty;
|
|
20
|
+
const buffer = Buffer.alloc(4097);
|
|
21
|
+
const size = readSync(fd, buffer, 0, buffer.length, 0);
|
|
22
|
+
if (size > 4096)
|
|
23
|
+
return empty;
|
|
24
|
+
const parsed = JSON.parse(buffer.subarray(0, size).toString("utf8"));
|
|
25
|
+
const selected = onboardingBackends(parsed.selected), pending = onboardingBackends(parsed.pending);
|
|
26
|
+
if (parsed.version !== 1 || !selected || !pending || pending.some(v => !selected.includes(v)))
|
|
27
|
+
return empty;
|
|
28
|
+
return { version: 1, selected, pending };
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return empty;
|
|
32
|
+
}
|
|
33
|
+
finally {
|
|
34
|
+
if (fd !== undefined)
|
|
35
|
+
closeSync(fd);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export function writePendingBackendSignIns(dataDir, value) {
|
|
39
|
+
const selected = onboardingBackends(value.selected), pending = onboardingBackends(value.pending);
|
|
40
|
+
if (!selected || !pending || pending.some(v => !selected.includes(v)))
|
|
41
|
+
throw new Error("invalid_signin_checklist");
|
|
42
|
+
atomicWriteFileSync(join(dataDir, "backend-signin-pending.json"), JSON.stringify({ version: 1, selected, pending }) + "\n", { mode: 0o600 });
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=backend-signin-pending.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend-signin-pending.js","sourceRoot":"","sources":["../src/backend-signin-pending.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/** Shared pre-fleet/dashboard orchestration. Contains no fleet or HTTP authority. */
|
|
2
|
+
import { type StructuredBackend, type SignInAction, type StructuredSignInTransport, type StructuredSignInView } from "./structured-signin.js";
|
|
3
|
+
import { LoginWindowLock } from "./login-window-lock.js";
|
|
4
|
+
import type { AuthCheckResult } from "./login-flows.js";
|
|
5
|
+
import { type OnboardingBackend } from "./backend-signin-pending.js";
|
|
6
|
+
export interface BrowserBackendSignInDeps {
|
|
7
|
+
dataDir: string;
|
|
8
|
+
selected?: readonly OnboardingBackend[];
|
|
9
|
+
current(owner: object): boolean;
|
|
10
|
+
installed(): Promise<readonly string[]>;
|
|
11
|
+
checkAuth(backend: StructuredBackend): Promise<AuthCheckResult>;
|
|
12
|
+
checkConsoleAuth?(): Promise<AuthCheckResult>;
|
|
13
|
+
transport(backend: StructuredBackend): StructuredSignInTransport;
|
|
14
|
+
lock?: LoginWindowLock;
|
|
15
|
+
changed?(event: {
|
|
16
|
+
backend: StructuredBackend;
|
|
17
|
+
phase: string;
|
|
18
|
+
reason?: string;
|
|
19
|
+
}, owner: object, launched: boolean): void;
|
|
20
|
+
}
|
|
21
|
+
export interface BrowserBackendSignInSnapshot {
|
|
22
|
+
selected: OnboardingBackend[];
|
|
23
|
+
pending: OnboardingBackend[];
|
|
24
|
+
skipped: OnboardingBackend[];
|
|
25
|
+
states: Partial<Record<OnboardingBackend, AuthCheckResult | "console_only" | "not_installed">>;
|
|
26
|
+
login: StructuredSignInView | null;
|
|
27
|
+
ready: boolean;
|
|
28
|
+
}
|
|
29
|
+
export declare class BrowserBackendSignIns {
|
|
30
|
+
private readonly deps;
|
|
31
|
+
private record;
|
|
32
|
+
private readonly skipped;
|
|
33
|
+
private readonly states;
|
|
34
|
+
private readonly lock;
|
|
35
|
+
private run;
|
|
36
|
+
private closed;
|
|
37
|
+
private refreshInFlight;
|
|
38
|
+
private refreshed;
|
|
39
|
+
private checklistRevision;
|
|
40
|
+
constructor(deps: BrowserBackendSignInDeps);
|
|
41
|
+
private current;
|
|
42
|
+
private terminal;
|
|
43
|
+
get activeBackend(): StructuredBackend | null;
|
|
44
|
+
private loginMayWrite;
|
|
45
|
+
get ready(): boolean;
|
|
46
|
+
private persist;
|
|
47
|
+
snapshot(owner: object): BrowserBackendSignInSnapshot;
|
|
48
|
+
refresh(owner: object, force?: boolean): Promise<BrowserBackendSignInSnapshot>;
|
|
49
|
+
select(owner: object, values: unknown): Promise<BrowserBackendSignInSnapshot>;
|
|
50
|
+
begin(owner: object, backend: string, relogin?: boolean): Promise<BrowserBackendSignInSnapshot>;
|
|
51
|
+
input(owner: object, id: string, revision: number, action: SignInAction): Promise<BrowserBackendSignInSnapshot>;
|
|
52
|
+
cancel(owner: object): Promise<BrowserBackendSignInSnapshot>;
|
|
53
|
+
skip(owner: object, backend: string): Promise<BrowserBackendSignInSnapshot>;
|
|
54
|
+
/** False means a credential writer may still exist: the caller must not hand over. */
|
|
55
|
+
close(): Promise<boolean>;
|
|
56
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/** Shared pre-fleet/dashboard orchestration. Contains no fleet or HTTP authority. */
|
|
2
|
+
import { StructuredSignIn, structuredSignInSupported } from "./structured-signin.js";
|
|
3
|
+
import { LoginWindowLock } from "./login-window-lock.js";
|
|
4
|
+
import { onboardingBackends, readPendingBackendSignIns, writePendingBackendSignIns } from "./backend-signin-pending.js";
|
|
5
|
+
export class BrowserBackendSignIns {
|
|
6
|
+
deps;
|
|
7
|
+
record;
|
|
8
|
+
skipped = new Set();
|
|
9
|
+
states = {};
|
|
10
|
+
lock;
|
|
11
|
+
run = null;
|
|
12
|
+
closed = false;
|
|
13
|
+
refreshInFlight = null;
|
|
14
|
+
refreshed = false;
|
|
15
|
+
checklistRevision = 0;
|
|
16
|
+
constructor(deps) {
|
|
17
|
+
this.deps = deps;
|
|
18
|
+
const old = readPendingBackendSignIns(deps.dataDir);
|
|
19
|
+
const selected = onboardingBackends(deps.selected ? [...deps.selected] : old.selected);
|
|
20
|
+
if (!selected)
|
|
21
|
+
throw new Error("invalid_signin_checklist");
|
|
22
|
+
// Probes, not an old record, decide which credentials can be reused.
|
|
23
|
+
this.record = { version: 1, selected, pending: [...selected] };
|
|
24
|
+
this.lock = deps.lock ?? new LoginWindowLock();
|
|
25
|
+
}
|
|
26
|
+
current(owner) { return !this.closed && this.deps.current(owner); }
|
|
27
|
+
terminal(run) {
|
|
28
|
+
if (!run)
|
|
29
|
+
return true;
|
|
30
|
+
const view = run.session.view(run.owner);
|
|
31
|
+
// A parser may report failed before its async cleanup finishes. Only the
|
|
32
|
+
// final safe reason (or done) proves that finish has settled the writer.
|
|
33
|
+
return view.phase === "done" || (view.phase === "failed" && !!view.reason);
|
|
34
|
+
}
|
|
35
|
+
get activeBackend() { return this.run && !this.terminal(this.run) ? this.run.backend : null; }
|
|
36
|
+
loginMayWrite(backend) {
|
|
37
|
+
return this.lock.current?.backend === backend || (this.run?.backend === backend
|
|
38
|
+
&& (!this.terminal(this.run) || this.run.session.view(this.run.owner).reason === "cleanup_failed"));
|
|
39
|
+
}
|
|
40
|
+
get ready() {
|
|
41
|
+
return this.terminal(this.run) && this.run?.session.view(this.run.owner).reason !== "cleanup_failed"
|
|
42
|
+
&& this.record.pending.every(backend => this.skipped.has(backend));
|
|
43
|
+
}
|
|
44
|
+
persist() { writePendingBackendSignIns(this.deps.dataDir, this.record); }
|
|
45
|
+
snapshot(owner) {
|
|
46
|
+
if (!this.current(owner))
|
|
47
|
+
throw new Error("signin_session_expired");
|
|
48
|
+
return { selected: [...this.record.selected], pending: [...this.record.pending], skipped: [...this.skipped],
|
|
49
|
+
states: { ...this.states }, login: this.run?.session.view(owner) ?? null, ready: this.ready };
|
|
50
|
+
}
|
|
51
|
+
async refresh(owner, force = false) {
|
|
52
|
+
if (!this.current(owner))
|
|
53
|
+
throw new Error("signin_session_expired");
|
|
54
|
+
do {
|
|
55
|
+
if ((!this.refreshed || force) && !this.refreshInFlight) {
|
|
56
|
+
const revision = this.checklistRevision, selected = [...this.record.selected];
|
|
57
|
+
const current = () => this.current(owner) && revision === this.checklistRevision;
|
|
58
|
+
this.refreshInFlight = (async () => {
|
|
59
|
+
const installed = await this.deps.installed();
|
|
60
|
+
if (!current())
|
|
61
|
+
return;
|
|
62
|
+
const checked = {};
|
|
63
|
+
for (const backend of selected) {
|
|
64
|
+
const status = !installed.includes(backend) ? "not_installed" : this.loginMayWrite(backend) ? "unknown"
|
|
65
|
+
: structuredSignInSupported(backend) ? await this.deps.checkAuth(backend)
|
|
66
|
+
: await this.deps.checkConsoleAuth?.() === "valid" ? "valid" : "console_only";
|
|
67
|
+
if (!current())
|
|
68
|
+
return;
|
|
69
|
+
checked[backend] = status;
|
|
70
|
+
}
|
|
71
|
+
// Publish the whole scan only while it still owns this checklist.
|
|
72
|
+
Object.assign(this.states, checked);
|
|
73
|
+
this.record.pending = selected.filter(backend => checked[backend] !== "valid");
|
|
74
|
+
this.persist();
|
|
75
|
+
this.refreshed = true;
|
|
76
|
+
})().finally(() => { this.refreshInFlight = null; });
|
|
77
|
+
}
|
|
78
|
+
force = false;
|
|
79
|
+
await this.refreshInFlight;
|
|
80
|
+
if (!this.current(owner))
|
|
81
|
+
throw new Error("signin_session_expired");
|
|
82
|
+
// A select or completed login superseded the scan: join one fresh scan.
|
|
83
|
+
} while (!this.refreshed);
|
|
84
|
+
return this.snapshot(owner);
|
|
85
|
+
}
|
|
86
|
+
async select(owner, values) {
|
|
87
|
+
if (!this.current(owner))
|
|
88
|
+
throw new Error("signin_session_expired");
|
|
89
|
+
const selected = onboardingBackends(values);
|
|
90
|
+
if (!selected)
|
|
91
|
+
throw new Error("invalid_signin_checklist");
|
|
92
|
+
if (this.run && !selected.includes(this.run.backend))
|
|
93
|
+
await this.cancel(owner);
|
|
94
|
+
if (!this.current(owner))
|
|
95
|
+
throw new Error("signin_session_expired");
|
|
96
|
+
this.checklistRevision++;
|
|
97
|
+
for (const backend of this.record.selected)
|
|
98
|
+
if (!selected.includes(backend))
|
|
99
|
+
delete this.states[backend];
|
|
100
|
+
const prior = this.record.selected;
|
|
101
|
+
this.record = { version: 1, selected, pending: selected.filter(backend => !prior.includes(backend) || this.record.pending.includes(backend)) };
|
|
102
|
+
this.persist();
|
|
103
|
+
this.refreshed = false;
|
|
104
|
+
return this.refresh(owner);
|
|
105
|
+
}
|
|
106
|
+
async begin(owner, backend, relogin = false) {
|
|
107
|
+
if (!this.current(owner))
|
|
108
|
+
throw new Error("signin_session_expired");
|
|
109
|
+
if (!structuredSignInSupported(backend) || !this.record.selected.includes(backend))
|
|
110
|
+
throw new Error("signin_console_only");
|
|
111
|
+
if (this.run?.session.view(this.run.owner).reason === "cleanup_failed")
|
|
112
|
+
throw new Error("signin_cleanup_failed");
|
|
113
|
+
if (this.run && !this.terminal(this.run))
|
|
114
|
+
return this.snapshot(owner); // refresh/double click joins
|
|
115
|
+
const session = new StructuredSignIn(backend, owner, {
|
|
116
|
+
lock: this.lock, current: () => this.current(owner), transport: this.deps.transport(backend),
|
|
117
|
+
checkAuth: () => this.deps.checkAuth(backend),
|
|
118
|
+
changed: event => {
|
|
119
|
+
if ((event.phase === "done" || (event.phase === "failed" && event.reason))
|
|
120
|
+
&& this.current(owner) && this.run?.session === session) {
|
|
121
|
+
this.checklistRevision++;
|
|
122
|
+
this.refreshed = false;
|
|
123
|
+
this.states[backend] = event.phase === "done" ? "valid" : "unknown";
|
|
124
|
+
this.record.pending = event.phase === "done" ? this.record.pending.filter(value => value !== backend)
|
|
125
|
+
: [...new Set([...this.record.pending, backend])];
|
|
126
|
+
this.persist();
|
|
127
|
+
}
|
|
128
|
+
this.deps.changed?.(event, owner, session.launched);
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
const run = { session, owner, backend };
|
|
132
|
+
this.run = run; // reserve before the installed await
|
|
133
|
+
this.checklistRevision++;
|
|
134
|
+
this.refreshed = false;
|
|
135
|
+
this.record.pending = [...new Set([...this.record.pending, backend])];
|
|
136
|
+
this.skipped.delete(backend);
|
|
137
|
+
this.persist();
|
|
138
|
+
const installed = await this.deps.installed();
|
|
139
|
+
if (!this.current(owner) || this.run !== run) {
|
|
140
|
+
await session.cancel();
|
|
141
|
+
throw new Error("signin_session_expired");
|
|
142
|
+
}
|
|
143
|
+
if (!installed.includes(backend)) {
|
|
144
|
+
await session.cancel();
|
|
145
|
+
this.states[backend] = "not_installed";
|
|
146
|
+
return this.snapshot(owner);
|
|
147
|
+
}
|
|
148
|
+
await session.start(relogin);
|
|
149
|
+
return this.snapshot(owner);
|
|
150
|
+
}
|
|
151
|
+
async input(owner, id, revision, action) {
|
|
152
|
+
if (!this.current(owner) || !this.run || this.run.owner !== owner)
|
|
153
|
+
throw new Error("signin_session_expired");
|
|
154
|
+
const result = await this.run.session.action(owner, id, revision, action);
|
|
155
|
+
if (result !== "accepted")
|
|
156
|
+
throw new Error(`signin_action_${result}`);
|
|
157
|
+
return this.snapshot(owner);
|
|
158
|
+
}
|
|
159
|
+
async cancel(owner) {
|
|
160
|
+
if (!this.current(owner))
|
|
161
|
+
throw new Error("signin_session_expired");
|
|
162
|
+
const run = this.run;
|
|
163
|
+
if (run)
|
|
164
|
+
await run.session.cancel();
|
|
165
|
+
if (run?.session.view(owner).reason === "cleanup_failed")
|
|
166
|
+
throw new Error("signin_cleanup_failed");
|
|
167
|
+
return this.snapshot(owner);
|
|
168
|
+
}
|
|
169
|
+
async skip(owner, backend) {
|
|
170
|
+
if (!this.current(owner) || !this.record.selected.includes(backend))
|
|
171
|
+
throw new Error("invalid_signin_checklist");
|
|
172
|
+
if (this.run?.backend === backend)
|
|
173
|
+
await this.cancel(owner);
|
|
174
|
+
if (!this.current(owner))
|
|
175
|
+
throw new Error("signin_session_expired");
|
|
176
|
+
this.skipped.add(backend);
|
|
177
|
+
this.persist();
|
|
178
|
+
return this.snapshot(owner);
|
|
179
|
+
}
|
|
180
|
+
/** False means a credential writer may still exist: the caller must not hand over. */
|
|
181
|
+
async close() {
|
|
182
|
+
this.closed = true;
|
|
183
|
+
const run = this.run;
|
|
184
|
+
if (run)
|
|
185
|
+
await run.session.cancel();
|
|
186
|
+
return run?.session.view(run.owner).reason !== "cleanup_failed";
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=browser-backend-signins.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-backend-signins.js","sourceRoot":"","sources":["../src/browser-backend-signins.ts"],"names":[],"mappings":"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"}
|
package/dist/cache-ledger.d.ts
CHANGED
|
@@ -13,12 +13,13 @@
|
|
|
13
13
|
* cache_creation: { ephemeral_5m_input_tokens, ephemeral_1h_input_tokens }, output_tokens }. A message spans several
|
|
14
14
|
* lines (one per content block) carrying the same id and usage: counted once.
|
|
15
15
|
* - Codex (0.160): `event_msg` `token_count` with `info.last_token_usage` { input_tokens (cached included),
|
|
16
|
-
* cached_input_tokens, cache_write_input_tokens, output_tokens }. The write field exists but was 0 in every one of
|
|
16
|
+
* cached_input_tokens, cache_write_input_tokens, output_tokens, reasoning_output_tokens (a part of output_tokens) }. The write field exists but was 0 in every one of
|
|
17
17
|
* 38,551 real events on GPT-5.6+ models — so a write is estimated as the request's uncached input unless a real
|
|
18
18
|
* write count shows up. The model comes from the preceding `turn_context`.
|
|
19
19
|
*/
|
|
20
20
|
import { type ScanLine } from "./cache-scan.js";
|
|
21
|
-
|
|
21
|
+
/** The reader: Claude Code, Codex, Grok, Muse, OpenCode and Antigravity are measured; Kiro is estimated (#2122 §10). */
|
|
22
|
+
export type TranscriptKind = "claude" | "codex" | "kiro" | "grok" | "muse" | "opencode" | "antigravity";
|
|
22
23
|
/** One model request, as the transcript records it. */
|
|
23
24
|
export interface Turn {
|
|
24
25
|
t: number;
|
|
@@ -32,6 +33,12 @@ export interface Turn {
|
|
|
32
33
|
/** An OpenAI cache write as recorded (null: not recorded, 0 included when the field is absent). */
|
|
33
34
|
write: number | null;
|
|
34
35
|
output: number;
|
|
36
|
+
/** The part of `output` the CLI reports as reasoning (Codex `reasoning_output_tokens`); absent or 0 where none is. */
|
|
37
|
+
reasoning?: number;
|
|
38
|
+
/** The model requests this record covers (a Kiro turn's `total_request_count`, Grok's `modelCalls`); absent: one. */
|
|
39
|
+
requests?: number;
|
|
40
|
+
/** What the CLI itself reported the request cost, USD (Grok's `costUsdTicks` × 1e-10); absent: not reported. */
|
|
41
|
+
cost?: number;
|
|
35
42
|
}
|
|
36
43
|
/** Gap histogram edges, seconds: ≤5 min, ≤30 min, ≤1 h, ≤2 h, ≤6 h, ≤24 h, longer. */
|
|
37
44
|
export declare const GAP_EDGES: readonly [300, 1800, 3600, 7200, 21600, 86400];
|
|
@@ -52,6 +59,14 @@ export interface HourAgg {
|
|
|
52
59
|
m: Record<string, HourTotals>;
|
|
53
60
|
g: number[];
|
|
54
61
|
src?: Record<string, Record<string, HourTotals>>;
|
|
62
|
+
/**
|
|
63
|
+
* #2122 §10.3: reasoning tokens, by source and model key — the part of `output` a CLI reports as reasoning (Codex). Kept
|
|
64
|
+
* beside the totals, never as an 8th entry: a published reader keeps only 7-entry totals and would drop the hour (Fable
|
|
65
|
+
* #2604 P1); an older version that rewrites the ledger drops only this.
|
|
66
|
+
*/
|
|
67
|
+
rs?: Record<string, Record<string, number>>;
|
|
68
|
+
/** #2122 §10.2: the cost a CLI reported (USD), by source and model key — beside the totals, as `rs`. */
|
|
69
|
+
cs?: Record<string, Record<string, number>>;
|
|
55
70
|
}
|
|
56
71
|
/** A source of an hour's totals: the reader that read them and the profile it read them under. */
|
|
57
72
|
export declare const sourceKey: (reader: TranscriptKind, profile: string) => string;
|
|
@@ -85,6 +100,9 @@ export interface FileCursor {
|
|
|
85
100
|
total?: number;
|
|
86
101
|
/** Claude: ids of the last messages counted (one message spans several lines). */
|
|
87
102
|
ids?: string[];
|
|
103
|
+
/** Kiro (kiro-usage-scan.ts): what the source looked like when read, and the time of the last turn counted. */
|
|
104
|
+
sig?: string;
|
|
105
|
+
after?: number;
|
|
88
106
|
}
|
|
89
107
|
export interface Ledger {
|
|
90
108
|
v: 2;
|
|
@@ -119,3 +137,21 @@ export declare function pruneLedger(ledger: Ledger, cutoff: number, foldedThroug
|
|
|
119
137
|
export declare function claudeLine(line: ScanLine, file: FileCursor): Turn | null;
|
|
120
138
|
/** The turn a Codex rollout line records, or null. A `turn_context` line updates the file's model. */
|
|
121
139
|
export declare function codexLine(line: ScanLine, file: FileCursor): Turn | null;
|
|
140
|
+
/**
|
|
141
|
+
* #2122 §10 step 3: the turns a Grok `updates.jsonl` line records — a `turn_completed` update's `usage`, one turn per
|
|
142
|
+
* model in its `modelUsage` (else the whole usage under `_meta.modelId`). Real counts, per turn (not cumulative):
|
|
143
|
+
* `inputTokens` includes the cache reads and writes, `reasoningTokens` is a part of `outputTokens` (totalTokens = input +
|
|
144
|
+
* output, checked on the host's 1.0.x sessions), `modelCalls` the requests, `costUsdTicks` × 1e-10 the cost grok
|
|
145
|
+
* reported. A turn already counted (its `prompt_id`, kept in `file.ids`) is not counted again.
|
|
146
|
+
*/
|
|
147
|
+
export declare function grokLine(line: ScanLine, file: FileCursor): Turn[];
|
|
148
|
+
/**
|
|
149
|
+
* #2122 §10 step 4: the turn a Muse `session.jsonl` line records — a `runtime.session` event `model_completed` with its
|
|
150
|
+
* `usage`. Real counts, one per model call, read as tokscale reads them (sessions/muse.rs at 669fdaee):
|
|
151
|
+
* - `input_tokens` includes the cache reads — `cache_read_tokens`, else (absent, not 0) the older `cached_tokens` — and
|
|
152
|
+
* `cache_write_tokens` is apart; `reasoning_tokens` is a part of `output_tokens`;
|
|
153
|
+
* - the call's time is its start: `recorded_at` (when it completed; µs, ms or s) less a positive `duration_ms`;
|
|
154
|
+
* - a call replayed into the file (the same stream, sequence, model and counts) is counted once (`file.ids`).
|
|
155
|
+
* Only `model_completed` counts: a workflow's aggregate events would count a child's calls twice.
|
|
156
|
+
*/
|
|
157
|
+
export declare function museLine(line: ScanLine, file: FileCursor): Turn | null;
|
package/dist/cache-ledger.js
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* cache_creation: { ephemeral_5m_input_tokens, ephemeral_1h_input_tokens }, output_tokens }. A message spans several
|
|
14
14
|
* lines (one per content block) carrying the same id and usage: counted once.
|
|
15
15
|
* - Codex (0.160): `event_msg` `token_count` with `info.last_token_usage` { input_tokens (cached included),
|
|
16
|
-
* cached_input_tokens, cache_write_input_tokens, output_tokens }. The write field exists but was 0 in every one of
|
|
16
|
+
* cached_input_tokens, cache_write_input_tokens, output_tokens, reasoning_output_tokens (a part of output_tokens) }. The write field exists but was 0 in every one of
|
|
17
17
|
* 38,551 real events on GPT-5.6+ models — so a write is estimated as the request's uncached input unless a real
|
|
18
18
|
* write count shows up. The model comes from the preceding `turn_context`.
|
|
19
19
|
*/
|
|
@@ -48,7 +48,7 @@ export function reviveLedger(raw) {
|
|
|
48
48
|
m[mk] = tot;
|
|
49
49
|
const src = dict();
|
|
50
50
|
for (const [sk, sm] of Object.entries(v.src ?? {})) {
|
|
51
|
-
if (!/^(?:claude|codex):.{1,120}$/s.test(sk) || !sm || typeof sm !== "object")
|
|
51
|
+
if (!/^(?:claude|codex|kiro|grok|muse|opencode|antigravity):.{1,120}$/s.test(sk) || !sm || typeof sm !== "object")
|
|
52
52
|
continue;
|
|
53
53
|
const into = dict();
|
|
54
54
|
for (const [mk, tot] of Object.entries(sm))
|
|
@@ -56,7 +56,23 @@ export function reviveLedger(raw) {
|
|
|
56
56
|
into[mk] = tot;
|
|
57
57
|
src[sk] = into;
|
|
58
58
|
}
|
|
59
|
-
|
|
59
|
+
// Beside the totals, by source and model key: only for a total that exists, only positive and finite.
|
|
60
|
+
const beside = (raw) => {
|
|
61
|
+
const out = dict();
|
|
62
|
+
for (const [sk, sm] of Object.entries((raw && typeof raw === "object" ? raw : {}))) {
|
|
63
|
+
if (!src[sk] || !sm || typeof sm !== "object")
|
|
64
|
+
continue;
|
|
65
|
+
const into = dict();
|
|
66
|
+
for (const [mk, n] of Object.entries(sm))
|
|
67
|
+
if (typeof n === "number" && Number.isFinite(n) && n > 0 && src[sk][mk])
|
|
68
|
+
into[mk] = n;
|
|
69
|
+
if (Object.keys(into).length)
|
|
70
|
+
out[sk] = into;
|
|
71
|
+
}
|
|
72
|
+
return out;
|
|
73
|
+
};
|
|
74
|
+
const rs = beside(v.rs), cs = beside(v.cs);
|
|
75
|
+
l.hours[k] = { m, g: v.g, ...(Object.keys(src).length ? { src } : {}), ...(Object.keys(rs).length ? { rs } : {}), ...(Object.keys(cs).length ? { cs } : {}) };
|
|
60
76
|
}
|
|
61
77
|
if (Array.isArray(r.gaps))
|
|
62
78
|
l.gaps = r.gaps.filter((g) => Array.isArray(g) && g.length === 9);
|
|
@@ -98,7 +114,7 @@ export function addTurn(ledger, file, turn, cutoff, profile) {
|
|
|
98
114
|
const hour = ledger.hours[hk] ??= { m: dict(), g: new Array(GAP_BUCKETS).fill(0) };
|
|
99
115
|
const mk = modelKey(turn.model, turn.prompt);
|
|
100
116
|
const bump = (tot) => {
|
|
101
|
-
tot[0] += 1;
|
|
117
|
+
tot[0] += turn.requests ?? 1;
|
|
102
118
|
tot[1] += turn.uncached;
|
|
103
119
|
tot[2] += turn.read;
|
|
104
120
|
tot[3] += turn.write5m;
|
|
@@ -108,9 +124,19 @@ export function addTurn(ledger, file, turn, cutoff, profile) {
|
|
|
108
124
|
};
|
|
109
125
|
bump(hour.m[mk] ??= [0, 0, 0, 0, 0, 0, 0]);
|
|
110
126
|
// #2122: and under its source — the reader that read it (this file's kind) and the profile it was read under.
|
|
111
|
-
const
|
|
127
|
+
const sk = sourceKey(file.kind, profile ?? "unknown");
|
|
128
|
+
const src = (hour.src ??= dict())[sk] ??= dict();
|
|
112
129
|
bump(src[mk] ??= [0, 0, 0, 0, 0, 0, 0]);
|
|
113
|
-
if (
|
|
130
|
+
if (turn.reasoning) {
|
|
131
|
+
const rs = (hour.rs ??= dict())[sk] ??= dict();
|
|
132
|
+
rs[mk] = (rs[mk] ?? 0) + turn.reasoning;
|
|
133
|
+
}
|
|
134
|
+
if (turn.cost) {
|
|
135
|
+
const cs = (hour.cs ??= dict())[sk] ??= dict();
|
|
136
|
+
cs[mk] = (cs[mk] ?? 0) + turn.cost;
|
|
137
|
+
}
|
|
138
|
+
// Only Claude and Codex are in the cache analysis (Kiro's turns are estimates; the others' analysis is not built).
|
|
139
|
+
if (!prev || (file.kind !== "claude" && file.kind !== "codex"))
|
|
114
140
|
return;
|
|
115
141
|
const gap = (turn.t - prev.t) / 1000;
|
|
116
142
|
if (!(gap >= 0))
|
|
@@ -243,8 +269,107 @@ export function codexLine(line, file) {
|
|
|
243
269
|
const t = Date.parse(d.timestamp);
|
|
244
270
|
if (!Number.isFinite(t))
|
|
245
271
|
return null;
|
|
246
|
-
const input = num(u.input_tokens), read = Math.min(num(u.cached_input_tokens), input);
|
|
272
|
+
const input = num(u.input_tokens), read = Math.min(num(u.cached_input_tokens), input), output = num(u.output_tokens);
|
|
247
273
|
const write = typeof u.cache_write_input_tokens === "number" ? Math.min(num(u.cache_write_input_tokens), input - read) : null;
|
|
248
|
-
|
|
274
|
+
// Reasoning is counted inside output_tokens (total_tokens = input + output): kept as its part, capped at output.
|
|
275
|
+
return { t, model: file.model ?? "unknown", prompt: input, uncached: input - read - (write ?? 0), read, write5m: 0, write1h: 0, write, output, reasoning: Math.min(num(u.reasoning_output_tokens), output) };
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* #2122 §10 step 3: the turns a Grok `updates.jsonl` line records — a `turn_completed` update's `usage`, one turn per
|
|
279
|
+
* model in its `modelUsage` (else the whole usage under `_meta.modelId`). Real counts, per turn (not cumulative):
|
|
280
|
+
* `inputTokens` includes the cache reads and writes, `reasoningTokens` is a part of `outputTokens` (totalTokens = input +
|
|
281
|
+
* output, checked on the host's 1.0.x sessions), `modelCalls` the requests, `costUsdTicks` × 1e-10 the cost grok
|
|
282
|
+
* reported. A turn already counted (its `prompt_id`, kept in `file.ids`) is not counted again.
|
|
283
|
+
*/
|
|
284
|
+
export function grokLine(line, file) {
|
|
285
|
+
if (!("whole" in line) || line.whole.indexOf("\"turn_completed\"") === -1)
|
|
286
|
+
return [];
|
|
287
|
+
let d;
|
|
288
|
+
try {
|
|
289
|
+
d = JSON.parse(line.whole.toString("utf8"));
|
|
290
|
+
}
|
|
291
|
+
catch {
|
|
292
|
+
return [];
|
|
293
|
+
}
|
|
294
|
+
const u = d.params?.update, meta = d.params?._meta;
|
|
295
|
+
if (!u || u.sessionUpdate !== "turn_completed" || !u.usage || typeof u.usage !== "object")
|
|
296
|
+
return [];
|
|
297
|
+
const id = typeof u.prompt_id === "string" ? u.prompt_id : typeof meta?.eventId === "string" ? meta.eventId : undefined;
|
|
298
|
+
if (id && file.ids?.includes(id))
|
|
299
|
+
return [];
|
|
300
|
+
const ms = typeof meta?.agentTimestampMs === "number" ? meta.agentTimestampMs : typeof d.timestamp === "number" ? d.timestamp * 1000 : NaN;
|
|
301
|
+
if (!Number.isFinite(ms))
|
|
302
|
+
return [];
|
|
303
|
+
const usage = u.usage;
|
|
304
|
+
const perModel = usage.modelUsage && typeof usage.modelUsage === "object" && Object.keys(usage.modelUsage).length
|
|
305
|
+
? Object.entries(usage.modelUsage)
|
|
306
|
+
: [[typeof meta?.modelId === "string" ? meta.modelId : "unknown", usage]];
|
|
307
|
+
const out = [];
|
|
308
|
+
for (const [model, mu] of perModel) {
|
|
309
|
+
if (!mu || typeof mu !== "object")
|
|
310
|
+
continue;
|
|
311
|
+
const input = num(mu.inputTokens), read = Math.min(num(mu.cachedReadTokens), input), write = Math.min(num(mu.cacheCreationTokens), input - read);
|
|
312
|
+
const output = num(mu.outputTokens), ticks = num(mu.costUsdTicks);
|
|
313
|
+
if (!input && !output)
|
|
314
|
+
continue;
|
|
315
|
+
out.push({ t: ms, model, prompt: input, uncached: input - read - write, read, write5m: 0, write1h: 0, write, output,
|
|
316
|
+
reasoning: Math.min(num(mu.reasoningTokens), output), requests: Math.max(1, Math.round(num(mu.modelCalls))), ...(ticks ? { cost: ticks * 1e-10 } : {}) });
|
|
317
|
+
}
|
|
318
|
+
if (id && out.length)
|
|
319
|
+
file.ids = [...(file.ids ?? []).slice(-15), id];
|
|
320
|
+
return out;
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* #2122 §10 step 4: the turn a Muse `session.jsonl` line records — a `runtime.session` event `model_completed` with its
|
|
324
|
+
* `usage`. Real counts, one per model call, read as tokscale reads them (sessions/muse.rs at 669fdaee):
|
|
325
|
+
* - `input_tokens` includes the cache reads — `cache_read_tokens`, else (absent, not 0) the older `cached_tokens` — and
|
|
326
|
+
* `cache_write_tokens` is apart; `reasoning_tokens` is a part of `output_tokens`;
|
|
327
|
+
* - the call's time is its start: `recorded_at` (when it completed; µs, ms or s) less a positive `duration_ms`;
|
|
328
|
+
* - a call replayed into the file (the same stream, sequence, model and counts) is counted once (`file.ids`).
|
|
329
|
+
* Only `model_completed` counts: a workflow's aggregate events would count a child's calls twice.
|
|
330
|
+
*/
|
|
331
|
+
export function museLine(line, file) {
|
|
332
|
+
if (!("whole" in line) || line.whole.indexOf("\"model_completed\"") === -1)
|
|
333
|
+
return null;
|
|
334
|
+
let d;
|
|
335
|
+
try {
|
|
336
|
+
d = JSON.parse(line.whole.toString("utf8"));
|
|
337
|
+
}
|
|
338
|
+
catch {
|
|
339
|
+
return null;
|
|
340
|
+
}
|
|
341
|
+
const e = d.payload?.event;
|
|
342
|
+
if (d.payload_type !== "runtime.session" || !e || e.kind !== "model_completed" || !e.usage || typeof e.usage !== "object")
|
|
343
|
+
return null;
|
|
344
|
+
const ended = museMs(d.recorded_at);
|
|
345
|
+
if (ended === null)
|
|
346
|
+
return null;
|
|
347
|
+
const u = e.usage;
|
|
348
|
+
const present = (v) => typeof v === "number" && Number.isFinite(v);
|
|
349
|
+
const input = num(u.input_tokens), read = Math.min(num(present(u.cache_read_tokens) ? u.cache_read_tokens : u.cached_tokens), input);
|
|
350
|
+
const write = present(u.cache_write_tokens) ? num(u.cache_write_tokens) : null;
|
|
351
|
+
const output = num(u.output_tokens), reasoning = Math.min(num(u.reasoning_tokens), output);
|
|
352
|
+
if (!input && !output && !write)
|
|
353
|
+
return null;
|
|
354
|
+
const model = typeof e.model === "string" && e.model ? e.model : "unknown";
|
|
355
|
+
const id = `${typeof d.stream?.id === "string" ? d.stream.id : ""}:${present(d.sequence) ? d.sequence : ""}:${model}:${input}:${output}:${read}:${write ?? 0}:${reasoning}`;
|
|
356
|
+
if (file.ids?.includes(id))
|
|
357
|
+
return null;
|
|
358
|
+
file.ids = [...(file.ids ?? []).slice(-63), id];
|
|
359
|
+
const duration = num(e.duration_ms);
|
|
360
|
+
return { t: duration && ended - duration > 0 ? ended - duration : ended, model, prompt: input + (write ?? 0), uncached: input - read, read,
|
|
361
|
+
write5m: 0, write1h: 0, write, output, reasoning };
|
|
362
|
+
}
|
|
363
|
+
/** Muse's `recorded_at` as milliseconds: it writes microseconds; milliseconds and seconds are read too (as tokscale does). */
|
|
364
|
+
function museMs(raw) {
|
|
365
|
+
if (typeof raw !== "number" || !Number.isFinite(raw))
|
|
366
|
+
return null;
|
|
367
|
+
if (raw >= 1e15)
|
|
368
|
+
return Math.floor(raw / 1000);
|
|
369
|
+
if (raw >= 1e12)
|
|
370
|
+
return raw;
|
|
371
|
+
if (raw >= 1e9)
|
|
372
|
+
return raw * 1000;
|
|
373
|
+
return null;
|
|
249
374
|
}
|
|
250
375
|
//# sourceMappingURL=cache-ledger.js.map
|