@ai-devkit/agent-manager 0.34.0 → 0.36.0
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/dist/AgentManager.d.ts +2 -0
- package/dist/AgentManager.d.ts.map +1 -1
- package/dist/AgentManager.js +25 -0
- package/dist/AgentManager.js.map +1 -1
- package/dist/__tests__/AgentManager.test.js +74 -0
- package/dist/__tests__/AgentManager.test.js.map +1 -1
- package/dist/__tests__/adapters/AntigravityCliAdapter.test.js +381 -0
- package/dist/__tests__/adapters/AntigravityCliAdapter.test.js.map +1 -0
- package/dist/__tests__/adapters/ClaudeCodeAdapter.test.js +28 -0
- package/dist/__tests__/adapters/ClaudeCodeAdapter.test.js.map +1 -1
- package/dist/__tests__/adapters/CodexAdapter.test.js +7 -0
- package/dist/__tests__/adapters/CodexAdapter.test.js.map +1 -1
- package/dist/__tests__/adapters/KiroAdapter.test.js +607 -0
- package/dist/__tests__/adapters/KiroAdapter.test.js.map +1 -0
- package/dist/__tests__/capacity/claude.test.js +485 -0
- package/dist/__tests__/capacity/claude.test.js.map +1 -0
- package/dist/__tests__/capacity/openai.test.js +672 -0
- package/dist/__tests__/capacity/openai.test.js.map +1 -0
- package/dist/__tests__/capacity/wham.test.js +144 -0
- package/dist/__tests__/capacity/wham.test.js.map +1 -0
- package/dist/__tests__/providers/copilot/CopilotAdapter.test.js +18 -0
- package/dist/__tests__/providers/copilot/CopilotAdapter.test.js.map +1 -1
- package/dist/__tests__/providers/gemini/GeminiCliAdapter.test.js +36 -0
- package/dist/__tests__/providers/gemini/GeminiCliAdapter.test.js.map +1 -1
- package/dist/__tests__/providers/grok/GrokAgentMapper.test.js +56 -0
- package/dist/__tests__/providers/grok/GrokAgentMapper.test.js.map +1 -0
- package/dist/__tests__/{adapters → providers/grok}/GrokCliAdapter.test.js +19 -6
- package/dist/__tests__/providers/grok/GrokCliAdapter.test.js.map +1 -0
- package/dist/__tests__/providers/grok/GrokSessionLocator.test.js +133 -0
- package/dist/__tests__/providers/grok/GrokSessionLocator.test.js.map +1 -0
- package/dist/__tests__/providers/opencode/OpenCodeAdapter.test.js +24 -0
- package/dist/__tests__/providers/opencode/OpenCodeAdapter.test.js.map +1 -1
- package/dist/__tests__/providers/pi/PiAdapter.test.js +30 -0
- package/dist/__tests__/providers/pi/PiAdapter.test.js.map +1 -1
- package/dist/__tests__/utils/agents.test.js +6 -0
- package/dist/__tests__/utils/agents.test.js.map +1 -1
- package/dist/__tests__/utils/session.test.js +18 -1
- package/dist/__tests__/utils/session.test.js.map +1 -1
- package/dist/adapters/AgentAdapter.d.ts +9 -1
- package/dist/adapters/AgentAdapter.d.ts.map +1 -1
- package/dist/adapters/AgentAdapter.js.map +1 -1
- package/dist/adapters/AntigravityCliAdapter.d.ts +57 -0
- package/dist/adapters/AntigravityCliAdapter.d.ts.map +1 -0
- package/dist/adapters/AntigravityCliAdapter.js +273 -0
- package/dist/adapters/AntigravityCliAdapter.js.map +1 -0
- package/dist/adapters/KiroAdapter.d.ts +46 -0
- package/dist/adapters/KiroAdapter.d.ts.map +1 -0
- package/dist/adapters/KiroAdapter.js +344 -0
- package/dist/adapters/KiroAdapter.js.map +1 -0
- package/dist/adapters/index.d.ts +3 -1
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +3 -1
- package/dist/adapters/index.js.map +1 -1
- package/dist/capacity/claude.d.ts +17 -0
- package/dist/capacity/claude.d.ts.map +1 -0
- package/dist/capacity/claude.js +271 -0
- package/dist/capacity/claude.js.map +1 -0
- package/dist/capacity/codex.d.ts +1 -2
- package/dist/capacity/codex.d.ts.map +1 -1
- package/dist/capacity/codex.js +5 -47
- package/dist/capacity/codex.js.map +1 -1
- package/dist/capacity/index.d.ts +11 -0
- package/dist/capacity/index.d.ts.map +1 -1
- package/dist/capacity/index.js +17 -0
- package/dist/capacity/index.js.map +1 -1
- package/dist/capacity/openai.d.ts +48 -0
- package/dist/capacity/openai.d.ts.map +1 -0
- package/dist/capacity/openai.js +312 -0
- package/dist/capacity/openai.js.map +1 -0
- package/dist/capacity/wham.d.ts +16 -0
- package/dist/capacity/wham.d.ts.map +1 -0
- package/dist/capacity/wham.js +66 -0
- package/dist/capacity/wham.js.map +1 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/providers/claude/ClaudeCodeAdapter.d.ts +2 -0
- package/dist/providers/claude/ClaudeCodeAdapter.d.ts.map +1 -1
- package/dist/providers/claude/ClaudeCodeAdapter.js +22 -19
- package/dist/providers/claude/ClaudeCodeAdapter.js.map +1 -1
- package/dist/providers/claude/ClaudeSessionLocator.d.ts +4 -0
- package/dist/providers/claude/ClaudeSessionLocator.d.ts.map +1 -1
- package/dist/providers/claude/ClaudeSessionLocator.js +18 -1
- package/dist/providers/claude/ClaudeSessionLocator.js.map +1 -1
- package/dist/providers/codex/CodexAdapter.d.ts +1 -0
- package/dist/providers/codex/CodexAdapter.d.ts.map +1 -1
- package/dist/providers/codex/CodexAdapter.js +8 -0
- package/dist/providers/codex/CodexAdapter.js.map +1 -1
- package/dist/providers/copilot/CopilotAdapter.d.ts +2 -0
- package/dist/providers/copilot/CopilotAdapter.d.ts.map +1 -1
- package/dist/providers/copilot/CopilotAdapter.js +24 -9
- package/dist/providers/copilot/CopilotAdapter.js.map +1 -1
- package/dist/providers/copilot/CopilotSessionLocator.d.ts +1 -0
- package/dist/providers/copilot/CopilotSessionLocator.d.ts.map +1 -1
- package/dist/providers/copilot/CopilotSessionLocator.js +9 -1
- package/dist/providers/copilot/CopilotSessionLocator.js.map +1 -1
- package/dist/providers/gemini/GeminiCliAdapter.d.ts +1 -0
- package/dist/providers/gemini/GeminiCliAdapter.d.ts.map +1 -1
- package/dist/providers/gemini/GeminiCliAdapter.js +9 -0
- package/dist/providers/gemini/GeminiCliAdapter.js.map +1 -1
- package/dist/providers/grok/GrokAgentMapper.d.ts +14 -0
- package/dist/providers/grok/GrokAgentMapper.d.ts.map +1 -0
- package/dist/providers/grok/GrokAgentMapper.js +36 -0
- package/dist/providers/grok/GrokAgentMapper.js.map +1 -0
- package/dist/providers/grok/GrokCliAdapter.d.ts +36 -0
- package/dist/providers/grok/GrokCliAdapter.d.ts.map +1 -0
- package/dist/providers/grok/GrokCliAdapter.js +98 -0
- package/dist/providers/grok/GrokCliAdapter.js.map +1 -0
- package/dist/providers/grok/GrokSessionLocator.d.ts +62 -0
- package/dist/providers/grok/GrokSessionLocator.d.ts.map +1 -0
- package/dist/providers/grok/GrokSessionLocator.js +140 -0
- package/dist/providers/grok/GrokSessionLocator.js.map +1 -0
- package/dist/providers/grok/GrokSessionParser.d.ts +54 -0
- package/dist/providers/grok/GrokSessionParser.d.ts.map +1 -0
- package/dist/providers/grok/GrokSessionParser.js +122 -0
- package/dist/providers/grok/GrokSessionParser.js.map +1 -0
- package/dist/providers/opencode/OpenCodeAdapter.d.ts +1 -0
- package/dist/providers/opencode/OpenCodeAdapter.d.ts.map +1 -1
- package/dist/providers/opencode/OpenCodeAdapter.js +3 -0
- package/dist/providers/opencode/OpenCodeAdapter.js.map +1 -1
- package/dist/providers/opencode/OpenCodeSessionLocator.d.ts +2 -0
- package/dist/providers/opencode/OpenCodeSessionLocator.d.ts.map +1 -1
- package/dist/providers/opencode/OpenCodeSessionLocator.js +31 -12
- package/dist/providers/opencode/OpenCodeSessionLocator.js.map +1 -1
- package/dist/providers/pi/PiAdapter.d.ts +1 -0
- package/dist/providers/pi/PiAdapter.d.ts.map +1 -1
- package/dist/providers/pi/PiAdapter.js +10 -0
- package/dist/providers/pi/PiAdapter.js.map +1 -1
- package/dist/providers/pi/PiSessionLocator.d.ts +1 -0
- package/dist/providers/pi/PiSessionLocator.d.ts.map +1 -1
- package/dist/providers/pi/PiSessionLocator.js +8 -1
- package/dist/providers/pi/PiSessionLocator.js.map +1 -1
- package/dist/readiness/AgentReadiness.d.ts +1 -1
- package/dist/readiness/AgentReadiness.d.ts.map +1 -1
- package/dist/readiness/AgentReadiness.js.map +1 -1
- package/dist/runtime/ManagedAgentRuntime.js +3 -1
- package/dist/runtime/ManagedAgentRuntime.js.map +1 -1
- package/dist/runtime/herdr/HerdrAgentDiscovery.js +10 -0
- package/dist/runtime/herdr/HerdrAgentDiscovery.js.map +1 -1
- package/dist/utils/agents.d.ts +1 -1
- package/dist/utils/agents.d.ts.map +1 -1
- package/dist/utils/agents.js +11 -0
- package/dist/utils/agents.js.map +1 -1
- package/dist/utils/session.d.ts +2 -0
- package/dist/utils/session.d.ts.map +1 -1
- package/dist/utils/session.js +3 -0
- package/dist/utils/session.js.map +1 -1
- package/package.json +1 -1
- package/src/AgentManager.ts +34 -0
- package/src/__tests__/AgentManager.test.ts +60 -0
- package/src/__tests__/adapters/AntigravityCliAdapter.test.ts +324 -0
- package/src/__tests__/adapters/ClaudeCodeAdapter.test.ts +23 -0
- package/src/__tests__/adapters/CodexAdapter.test.ts +7 -0
- package/src/__tests__/adapters/KiroAdapter.test.ts +534 -0
- package/src/__tests__/capacity/claude.test.ts +467 -0
- package/src/__tests__/capacity/fixtures/claude-credentials.json +7 -0
- package/src/__tests__/capacity/fixtures/claude-usage-malformed.json +1 -0
- package/src/__tests__/capacity/fixtures/claude-usage-partial.json +15 -0
- package/src/__tests__/capacity/fixtures/claude-usage.json +63 -0
- package/src/__tests__/capacity/fixtures/openai-auth.json +6 -0
- package/src/__tests__/capacity/fixtures/openai-codex-auth.json +9 -0
- package/src/__tests__/capacity/fixtures/openai-usage-completions.json +67 -0
- package/src/__tests__/capacity/fixtures/openai-usage-responses.json +20 -0
- package/src/__tests__/capacity/fixtures/wham-usage.json +32 -0
- package/src/__tests__/capacity/openai.test.ts +570 -0
- package/src/__tests__/capacity/wham.test.ts +104 -0
- package/src/__tests__/providers/copilot/CopilotAdapter.test.ts +12 -0
- package/src/__tests__/providers/gemini/GeminiCliAdapter.test.ts +21 -0
- package/src/__tests__/providers/grok/GrokAgentMapper.test.ts +57 -0
- package/src/__tests__/{adapters → providers/grok}/GrokCliAdapter.test.ts +18 -9
- package/src/__tests__/providers/grok/GrokSessionLocator.test.ts +106 -0
- package/src/__tests__/providers/opencode/OpenCodeAdapter.test.ts +18 -0
- package/src/__tests__/providers/pi/PiAdapter.test.ts +15 -0
- package/src/__tests__/utils/agents.test.ts +7 -0
- package/src/__tests__/utils/session.test.ts +11 -1
- package/src/adapters/AgentAdapter.ts +11 -0
- package/src/adapters/AntigravityCliAdapter.ts +356 -0
- package/src/adapters/KiroAdapter.ts +456 -0
- package/src/adapters/index.ts +3 -1
- package/src/capacity/claude.ts +313 -0
- package/src/capacity/codex.ts +25 -134
- package/src/capacity/index.ts +33 -4
- package/src/capacity/openai.ts +361 -0
- package/src/capacity/wham.ts +84 -0
- package/src/index.ts +11 -2
- package/src/providers/claude/ClaudeCodeAdapter.ts +28 -23
- package/src/providers/claude/ClaudeSessionLocator.ts +20 -0
- package/src/providers/codex/CodexAdapter.ts +8 -0
- package/src/providers/copilot/CopilotAdapter.ts +26 -10
- package/src/providers/copilot/CopilotSessionLocator.ts +7 -1
- package/src/providers/gemini/GeminiCliAdapter.ts +8 -0
- package/src/providers/grok/GrokAgentMapper.ts +41 -0
- package/src/providers/grok/GrokCliAdapter.ts +125 -0
- package/src/providers/grok/GrokSessionLocator.ts +179 -0
- package/src/providers/grok/GrokSessionParser.ts +166 -0
- package/src/providers/opencode/OpenCodeAdapter.ts +4 -0
- package/src/providers/opencode/OpenCodeSessionLocator.ts +43 -15
- package/src/providers/pi/PiAdapter.ts +12 -0
- package/src/providers/pi/PiSessionLocator.ts +16 -1
- package/src/readiness/AgentReadiness.ts +4 -1
- package/src/runtime/ManagedAgentRuntime.ts +2 -0
- package/src/runtime/herdr/HerdrAgentDiscovery.ts +5 -1
- package/src/utils/agents.ts +11 -1
- package/src/utils/session.ts +11 -0
- package/dist/__tests__/adapters/GrokCliAdapter.test.js.map +0 -1
- package/dist/adapters/GrokCliAdapter.d.ts +0 -80
- package/dist/adapters/GrokCliAdapter.d.ts.map +0 -1
- package/dist/adapters/GrokCliAdapter.js +0 -310
- package/dist/adapters/GrokCliAdapter.js.map +0 -1
- package/src/adapters/GrokCliAdapter.ts +0 -408
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { CapacityReport } from "./types.js";
|
|
2
|
+
export type OpenAiUsageBucket = {
|
|
3
|
+
startMs: number;
|
|
4
|
+
tokens: number;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Resolved OpenAI credential: a platform API key (env or Pi `openai` entry)
|
|
8
|
+
* or the OAuth login Pi stores as `openai-codex` for ChatGPT-backed access.
|
|
9
|
+
*/
|
|
10
|
+
export type OpenAiCredential = {
|
|
11
|
+
kind: "platform";
|
|
12
|
+
key: string;
|
|
13
|
+
} | {
|
|
14
|
+
kind: "oauth";
|
|
15
|
+
access: string;
|
|
16
|
+
accountId: string;
|
|
17
|
+
expiresMs: number | null;
|
|
18
|
+
};
|
|
19
|
+
export type OpenAiCredentialOptions = {
|
|
20
|
+
env?: NodeJS.ProcessEnv;
|
|
21
|
+
readFile?: (path: string, encoding: BufferEncoding) => Promise<string>;
|
|
22
|
+
};
|
|
23
|
+
export type OpenAiProbeOptions = OpenAiCredentialOptions & {
|
|
24
|
+
checkedAt: string;
|
|
25
|
+
fetch?: typeof globalThis.fetch;
|
|
26
|
+
timeoutMs?: number;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Resolves the OpenAI credential in priority order: `OPENAI_API_KEY` env,
|
|
30
|
+
* then the Pi `openai` platform-key entry, then the Pi `openai-codex` OAuth
|
|
31
|
+
* login written by `pi login` (no manual setup required).
|
|
32
|
+
*/
|
|
33
|
+
export declare function resolveOpenAiCredential(options?: OpenAiCredentialOptions): Promise<OpenAiCredential>;
|
|
34
|
+
export declare function resolveOpenAiApiKey(options?: OpenAiCredentialOptions): Promise<string>;
|
|
35
|
+
/**
|
|
36
|
+
* Maps one OpenAI Usage API payload (day buckets of per-model token counts)
|
|
37
|
+
* into summed UTC-day buckets. Entries without a numeric
|
|
38
|
+
* aggregation_timestamp are skipped because they cannot be placed in time.
|
|
39
|
+
*/
|
|
40
|
+
export declare function parseOpenAiUsage(raw: unknown): OpenAiUsageBucket[];
|
|
41
|
+
/**
|
|
42
|
+
* Builds the capacity report from merged day buckets: trailing-7-day and
|
|
43
|
+
* current-UTC-day token usage. The platform is pay-as-you-go and exposes no
|
|
44
|
+
* queryable limit, so windows report consumption only — no faked percentages.
|
|
45
|
+
*/
|
|
46
|
+
export declare function buildOpenAiReport(buckets: OpenAiUsageBucket[], checkedAt: string): CapacityReport;
|
|
47
|
+
export declare function probeOpenAiCapacity(options: OpenAiProbeOptions): Promise<CapacityReport>;
|
|
48
|
+
//# sourceMappingURL=openai.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/capacity/openai.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAkB,MAAM,YAAY,CAAC;AAYjE,MAAM,MAAM,iBAAiB,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAGpE;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GACxB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAEnF,MAAM,MAAM,uBAAuB,GAAG;IACpC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CACxE,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,uBAAuB,GAAG;IACzD,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AA2CF;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,gBAAgB,CAAC,CAuB3B;AAED,wBAAsB,mBAAmB,CAAC,OAAO,GAAE,uBAA4B,GAAG,OAAO,CAAC,MAAM,CAAC,CAIhG;AAaD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,iBAAiB,EAAE,CAUlE;AAkBD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,iBAAiB,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,cAAc,CAmCjG;AAyDD,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,cAAc,CAAC,CAgB9F"}
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { parseWhamUsage } from "./wham.js";
|
|
5
|
+
const OPENAI_USAGE_BASE_URL = "https://api.openai.com/v1/organization/usage";
|
|
6
|
+
const OPENAI_MODELS_URL = "https://api.openai.com/v1/models";
|
|
7
|
+
const WHAM_USAGE_URL = "https://chatgpt.com/backend-api/wham/usage";
|
|
8
|
+
const OPENAI_USAGE_ENDPOINTS = [
|
|
9
|
+
"completions",
|
|
10
|
+
"responses"
|
|
11
|
+
];
|
|
12
|
+
const USAGE_WINDOW_DAYS = 7;
|
|
13
|
+
const DAY_MS = 24 * 60 * 60 * 1000;
|
|
14
|
+
const MISSING_API_KEY_MESSAGE = "OpenAI credentials not found; set OPENAI_API_KEY, configure the Pi openai provider, or log in to OpenAI via Pi";
|
|
15
|
+
const EPOCH_MS_FLOOR = 1e12;
|
|
16
|
+
function record(value) {
|
|
17
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
18
|
+
}
|
|
19
|
+
function nonEmptyText(value) {
|
|
20
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
21
|
+
}
|
|
22
|
+
function finiteNumber(value) {
|
|
23
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
24
|
+
}
|
|
25
|
+
/** Pi stores `expires` in epoch milliseconds, codex-style tokens use seconds. */ function toEpochMs(value) {
|
|
26
|
+
const raw = finiteNumber(value);
|
|
27
|
+
if (raw === null || raw <= 0) return null;
|
|
28
|
+
return raw > EPOCH_MS_FLOOR ? raw : raw * 1000;
|
|
29
|
+
}
|
|
30
|
+
async function readPiAuthRoot(options) {
|
|
31
|
+
const env = options.env ?? process.env;
|
|
32
|
+
const authPath = join(env.HOME || homedir(), ".pi", "agent", "auth.json");
|
|
33
|
+
let parsed;
|
|
34
|
+
try {
|
|
35
|
+
const contents = await (options.readFile ?? readFile)(authPath, "utf8");
|
|
36
|
+
const root = record(JSON.parse(contents));
|
|
37
|
+
if (!root) throw new Error("invalid");
|
|
38
|
+
parsed = root;
|
|
39
|
+
} catch (error) {
|
|
40
|
+
if (record(error)?.code === "ENOENT") {
|
|
41
|
+
throw new Error(MISSING_API_KEY_MESSAGE);
|
|
42
|
+
}
|
|
43
|
+
throw new Error("OpenAI Pi auth file is malformed");
|
|
44
|
+
}
|
|
45
|
+
return parsed;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Resolves the OpenAI credential in priority order: `OPENAI_API_KEY` env,
|
|
49
|
+
* then the Pi `openai` platform-key entry, then the Pi `openai-codex` OAuth
|
|
50
|
+
* login written by `pi login` (no manual setup required).
|
|
51
|
+
*/ export async function resolveOpenAiCredential(options = {}) {
|
|
52
|
+
const env = options.env ?? process.env;
|
|
53
|
+
const environmentKey = nonEmptyText(env.OPENAI_API_KEY);
|
|
54
|
+
if (environmentKey) return {
|
|
55
|
+
kind: "platform",
|
|
56
|
+
key: environmentKey
|
|
57
|
+
};
|
|
58
|
+
const parsed = await readPiAuthRoot(options);
|
|
59
|
+
const platform = record(parsed.openai);
|
|
60
|
+
if (platform) {
|
|
61
|
+
const key = platform.type === "api_key" ? nonEmptyText(platform.key) : null;
|
|
62
|
+
if (!key) {
|
|
63
|
+
throw new Error("OpenAI Pi auth file has a malformed openai credential");
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
kind: "platform",
|
|
67
|
+
key
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
const oauth = record(parsed["openai-codex"]);
|
|
71
|
+
const access = oauth?.type === "oauth" ? nonEmptyText(oauth.access) : null;
|
|
72
|
+
const accountId = nonEmptyText(oauth?.accountId);
|
|
73
|
+
if (oauth && access && accountId) {
|
|
74
|
+
return {
|
|
75
|
+
kind: "oauth",
|
|
76
|
+
access,
|
|
77
|
+
accountId,
|
|
78
|
+
expiresMs: toEpochMs(oauth.expires)
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
throw new Error(MISSING_API_KEY_MESSAGE);
|
|
82
|
+
}
|
|
83
|
+
export async function resolveOpenAiApiKey(options = {}) {
|
|
84
|
+
const credential = await resolveOpenAiCredential(options);
|
|
85
|
+
if (credential.kind === "platform") return credential.key;
|
|
86
|
+
throw new Error(MISSING_API_KEY_MESSAGE);
|
|
87
|
+
}
|
|
88
|
+
function bucketTokens(value) {
|
|
89
|
+
const results = Array.isArray(value) ? value : [];
|
|
90
|
+
return results.reduce((total, entry)=>total + (finiteNumber(record(entry)?.input_tokens) ?? 0) + (finiteNumber(record(entry)?.output_tokens) ?? 0), 0);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Maps one OpenAI Usage API payload (day buckets of per-model token counts)
|
|
94
|
+
* into summed UTC-day buckets. Entries without a numeric
|
|
95
|
+
* aggregation_timestamp are skipped because they cannot be placed in time.
|
|
96
|
+
*/ export function parseOpenAiUsage(raw) {
|
|
97
|
+
const data = record(raw)?.data;
|
|
98
|
+
if (!Array.isArray(data)) throw new Error("Invalid OpenAI usage response");
|
|
99
|
+
const buckets = [];
|
|
100
|
+
for (const entry of data){
|
|
101
|
+
const seconds = finiteNumber(record(entry)?.aggregation_timestamp);
|
|
102
|
+
if (seconds === null) continue;
|
|
103
|
+
buckets.push({
|
|
104
|
+
startMs: seconds * 1000,
|
|
105
|
+
tokens: bucketTokens(record(entry)?.results)
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
return buckets;
|
|
109
|
+
}
|
|
110
|
+
function openAiCapacityReport(windows, checkedAt, authenticated) {
|
|
111
|
+
return {
|
|
112
|
+
harness: "pi",
|
|
113
|
+
provider: "openai",
|
|
114
|
+
generatedAt: checkedAt,
|
|
115
|
+
authenticated,
|
|
116
|
+
available: windows.length > 0 ? "yes" : "unknown",
|
|
117
|
+
windows,
|
|
118
|
+
creditsRemaining: null
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Builds the capacity report from merged day buckets: trailing-7-day and
|
|
123
|
+
* current-UTC-day token usage. The platform is pay-as-you-go and exposes no
|
|
124
|
+
* queryable limit, so windows report consumption only — no faked percentages.
|
|
125
|
+
*/ export function buildOpenAiReport(buckets, checkedAt) {
|
|
126
|
+
const nowMs = Date.parse(checkedAt);
|
|
127
|
+
const todayStartMs = Math.floor(nowMs / DAY_MS) * DAY_MS;
|
|
128
|
+
const weekStartMs = todayStartMs - (USAGE_WINDOW_DAYS - 1) * DAY_MS;
|
|
129
|
+
let todayTokens = 0;
|
|
130
|
+
let weekTokens = 0;
|
|
131
|
+
for (const bucket of buckets){
|
|
132
|
+
if (bucket.startMs === todayStartMs) todayTokens += bucket.tokens;
|
|
133
|
+
if (bucket.startMs >= weekStartMs) weekTokens += bucket.tokens;
|
|
134
|
+
}
|
|
135
|
+
const windows = [
|
|
136
|
+
{
|
|
137
|
+
id: "openai:tokens:today",
|
|
138
|
+
label: "Tokens · today (UTC)",
|
|
139
|
+
limitType: "TOKENS_LIMIT",
|
|
140
|
+
durationMinutes: 24 * 60,
|
|
141
|
+
usedPercent: null,
|
|
142
|
+
resetsAt: new Date(todayStartMs + DAY_MS).toISOString(),
|
|
143
|
+
total: null,
|
|
144
|
+
current: todayTokens,
|
|
145
|
+
remaining: null
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
id: "openai:tokens:week",
|
|
149
|
+
label: "Tokens · 7 days",
|
|
150
|
+
limitType: "TOKENS_LIMIT",
|
|
151
|
+
durationMinutes: USAGE_WINDOW_DAYS * 24 * 60,
|
|
152
|
+
usedPercent: null,
|
|
153
|
+
resetsAt: null,
|
|
154
|
+
total: null,
|
|
155
|
+
current: weekTokens,
|
|
156
|
+
remaining: null
|
|
157
|
+
}
|
|
158
|
+
];
|
|
159
|
+
return openAiCapacityReport(windows, checkedAt, true);
|
|
160
|
+
}
|
|
161
|
+
async function fetchUsage(context) {
|
|
162
|
+
const fetcher = context.fetch ?? globalThis.fetch;
|
|
163
|
+
const endSeconds = Math.floor(Date.parse(context.checkedAt) / 1000);
|
|
164
|
+
const startSeconds = endSeconds - USAGE_WINDOW_DAYS * 24 * 60 * 60;
|
|
165
|
+
const query = `start_time=${startSeconds}&end_time=${endSeconds}`;
|
|
166
|
+
const payloads = [];
|
|
167
|
+
for (const endpoint of OPENAI_USAGE_ENDPOINTS){
|
|
168
|
+
const controller = new AbortController();
|
|
169
|
+
const timer = setTimeout(()=>controller.abort(), context.timeoutMs ?? 5000);
|
|
170
|
+
let response;
|
|
171
|
+
try {
|
|
172
|
+
response = await fetcher(`${OPENAI_USAGE_BASE_URL}/${endpoint}?${query}`, {
|
|
173
|
+
method: "GET",
|
|
174
|
+
headers: {
|
|
175
|
+
Authorization: `Bearer ${context.key}`
|
|
176
|
+
},
|
|
177
|
+
signal: controller.signal
|
|
178
|
+
});
|
|
179
|
+
} catch {
|
|
180
|
+
throw new Error("OpenAI usage request failed");
|
|
181
|
+
} finally{
|
|
182
|
+
clearTimeout(timer);
|
|
183
|
+
}
|
|
184
|
+
if (response.status === 401) return null;
|
|
185
|
+
if (response.status === 403) return response.status;
|
|
186
|
+
if (response.status !== 200) {
|
|
187
|
+
throw new Error(`OpenAI usage request failed: HTTP ${response.status}`);
|
|
188
|
+
}
|
|
189
|
+
try {
|
|
190
|
+
payloads.push(await response.json());
|
|
191
|
+
} catch {
|
|
192
|
+
throw new Error("OpenAI usage response is not valid JSON");
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return payloads;
|
|
196
|
+
}
|
|
197
|
+
async function verifyKey(context) {
|
|
198
|
+
const fetcher = context.fetch ?? globalThis.fetch;
|
|
199
|
+
const controller = new AbortController();
|
|
200
|
+
const timer = setTimeout(()=>controller.abort(), context.timeoutMs ?? 5000);
|
|
201
|
+
try {
|
|
202
|
+
const response = await fetcher(OPENAI_MODELS_URL, {
|
|
203
|
+
method: "GET",
|
|
204
|
+
headers: {
|
|
205
|
+
Authorization: `Bearer ${context.key}`
|
|
206
|
+
},
|
|
207
|
+
signal: controller.signal
|
|
208
|
+
});
|
|
209
|
+
return response.status !== 401;
|
|
210
|
+
} catch {
|
|
211
|
+
throw new Error("OpenAI usage request failed");
|
|
212
|
+
} finally{
|
|
213
|
+
clearTimeout(timer);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
export async function probeOpenAiCapacity(options) {
|
|
217
|
+
const credential = await resolveOpenAiCredential(options);
|
|
218
|
+
if (credential.kind === "oauth") {
|
|
219
|
+
return probeOpenAiOauthCapacity(credential, options);
|
|
220
|
+
}
|
|
221
|
+
const probe = {
|
|
222
|
+
...options,
|
|
223
|
+
key: credential.key
|
|
224
|
+
};
|
|
225
|
+
const result = await fetchUsage(probe);
|
|
226
|
+
if (result === null) {
|
|
227
|
+
return openAiCapacityReport([], options.checkedAt, false);
|
|
228
|
+
}
|
|
229
|
+
if (typeof result === "number") {
|
|
230
|
+
const authenticated = await verifyKey(probe);
|
|
231
|
+
return openAiCapacityReport([], options.checkedAt, authenticated);
|
|
232
|
+
}
|
|
233
|
+
const buckets = result.flatMap(parseOpenAiUsage);
|
|
234
|
+
return buildOpenAiReport(buckets, options.checkedAt);
|
|
235
|
+
}
|
|
236
|
+
/** Mirrors codex.ts: JWT `exp` (epoch seconds) as expiry fallback. */ function jwtExpiryMs(token) {
|
|
237
|
+
const part = token.split(".")[1];
|
|
238
|
+
if (!part) return null;
|
|
239
|
+
try {
|
|
240
|
+
const exp = finiteNumber(record(JSON.parse(Buffer.from(part, "base64url").toString("utf8")))?.exp);
|
|
241
|
+
return exp === null ? null : exp * 1000;
|
|
242
|
+
} catch {
|
|
243
|
+
return null;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
function oauthExpired(credential, nowMs) {
|
|
247
|
+
const expiryMs = credential.expiresMs ?? jwtExpiryMs(credential.access);
|
|
248
|
+
return expiryMs !== null && expiryMs <= nowMs;
|
|
249
|
+
}
|
|
250
|
+
async function fetchWhamUsage(credential, options) {
|
|
251
|
+
const fetcher = options.fetch ?? globalThis.fetch;
|
|
252
|
+
const controller = new AbortController();
|
|
253
|
+
const timer = setTimeout(()=>controller.abort(), options.timeoutMs ?? 5000);
|
|
254
|
+
let response;
|
|
255
|
+
try {
|
|
256
|
+
response = await fetcher(WHAM_USAGE_URL, {
|
|
257
|
+
method: "GET",
|
|
258
|
+
headers: {
|
|
259
|
+
Authorization: `Bearer ${credential.access}`,
|
|
260
|
+
"ChatGPT-Account-Id": credential.accountId
|
|
261
|
+
},
|
|
262
|
+
signal: controller.signal
|
|
263
|
+
});
|
|
264
|
+
} catch {
|
|
265
|
+
throw new Error("OpenAI usage request failed");
|
|
266
|
+
} finally{
|
|
267
|
+
clearTimeout(timer);
|
|
268
|
+
}
|
|
269
|
+
if (response.status === 401 || response.status === 403) return null;
|
|
270
|
+
if (response.status !== 200) {
|
|
271
|
+
throw new Error(`OpenAI usage request failed: HTTP ${response.status}`);
|
|
272
|
+
}
|
|
273
|
+
try {
|
|
274
|
+
return await response.json();
|
|
275
|
+
} catch {
|
|
276
|
+
throw new Error("OpenAI usage response is not valid JSON");
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* OAuth path for Pi's OpenAI login: consumes the same wham/usage endpoint as
|
|
281
|
+
* the codex harness. Stale logins are never fetched (no refresh, matching
|
|
282
|
+
* codex.ts); they render as authenticated-but-stale instead.
|
|
283
|
+
*/ async function probeOpenAiOauthCapacity(credential, options) {
|
|
284
|
+
const staleReport = {
|
|
285
|
+
harness: "pi",
|
|
286
|
+
provider: "openai",
|
|
287
|
+
generatedAt: options.checkedAt,
|
|
288
|
+
authenticated: true,
|
|
289
|
+
available: "unknown",
|
|
290
|
+
windows: [],
|
|
291
|
+
creditsRemaining: null
|
|
292
|
+
};
|
|
293
|
+
const nowMs = Date.parse(options.checkedAt);
|
|
294
|
+
if (Number.isNaN(nowMs) || oauthExpired(credential, nowMs)) return staleReport;
|
|
295
|
+
const raw = await fetchWhamUsage(credential, options);
|
|
296
|
+
if (raw === null) {
|
|
297
|
+
return {
|
|
298
|
+
...staleReport,
|
|
299
|
+
authenticated: false
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
const snapshot = parseWhamUsage(raw);
|
|
303
|
+
const hasUsage = snapshot.windows.some((window)=>window.usedPercent !== null);
|
|
304
|
+
return {
|
|
305
|
+
...staleReport,
|
|
306
|
+
available: hasUsage ? "yes" : "unknown",
|
|
307
|
+
windows: snapshot.windows,
|
|
308
|
+
creditsRemaining: snapshot.creditsRemaining
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
//# sourceMappingURL=openai.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/capacity/openai.ts"],"sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { parseWhamUsage } from \"./wham.js\";\nimport type { CapacityReport, CapacityWindow } from \"./types.js\";\n\nconst OPENAI_USAGE_BASE_URL = \"https://api.openai.com/v1/organization/usage\";\nconst OPENAI_MODELS_URL = \"https://api.openai.com/v1/models\";\nconst WHAM_USAGE_URL = \"https://chatgpt.com/backend-api/wham/usage\";\nconst OPENAI_USAGE_ENDPOINTS = [\"completions\", \"responses\"] as const;\nconst USAGE_WINDOW_DAYS = 7;\nconst DAY_MS = 24 * 60 * 60 * 1000;\nconst MISSING_API_KEY_MESSAGE =\n \"OpenAI credentials not found; set OPENAI_API_KEY, configure the Pi openai provider, or log in to OpenAI via Pi\";\nconst EPOCH_MS_FLOOR = 1e12;\n\nexport type OpenAiUsageBucket = { startMs: number; tokens: number };\ntype UnknownRecord = Record<string, unknown>;\n\n/**\n * Resolved OpenAI credential: a platform API key (env or Pi `openai` entry)\n * or the OAuth login Pi stores as `openai-codex` for ChatGPT-backed access.\n */\nexport type OpenAiCredential =\n | { kind: \"platform\"; key: string }\n | { kind: \"oauth\"; access: string; accountId: string; expiresMs: number | null };\n\nexport type OpenAiCredentialOptions = {\n env?: NodeJS.ProcessEnv;\n readFile?: (path: string, encoding: BufferEncoding) => Promise<string>;\n};\n\nexport type OpenAiProbeOptions = OpenAiCredentialOptions & {\n checkedAt: string;\n fetch?: typeof globalThis.fetch;\n timeoutMs?: number;\n};\ntype OpenAiRequestContext = OpenAiProbeOptions & { key: string };\ntype OAuthCredential = Extract<OpenAiCredential, { kind: \"oauth\" }>;\n\nfunction record(value: unknown): UnknownRecord | null {\n return value !== null && typeof value === \"object\" && !Array.isArray(value)\n ? (value as UnknownRecord)\n : null;\n}\n\nfunction nonEmptyText(value: unknown): string | null {\n return typeof value === \"string\" && value.trim() ? value.trim() : null;\n}\n\nfunction finiteNumber(value: unknown): number | null {\n return typeof value === \"number\" && Number.isFinite(value) ? value : null;\n}\n\n/** Pi stores `expires` in epoch milliseconds, codex-style tokens use seconds. */\nfunction toEpochMs(value: unknown): number | null {\n const raw = finiteNumber(value);\n if (raw === null || raw <= 0) return null;\n return raw > EPOCH_MS_FLOOR ? raw : raw * 1000;\n}\n\nasync function readPiAuthRoot(options: OpenAiCredentialOptions): Promise<UnknownRecord> {\n const env = options.env ?? process.env;\n const authPath = join(env.HOME || homedir(), \".pi\", \"agent\", \"auth.json\");\n let parsed: UnknownRecord;\n try {\n const contents = await (options.readFile ?? readFile)(authPath, \"utf8\");\n const root = record(JSON.parse(contents));\n if (!root) throw new Error(\"invalid\");\n parsed = root;\n } catch (error) {\n if (record(error)?.code === \"ENOENT\") {\n throw new Error(MISSING_API_KEY_MESSAGE);\n }\n throw new Error(\"OpenAI Pi auth file is malformed\");\n }\n return parsed;\n}\n\n/**\n * Resolves the OpenAI credential in priority order: `OPENAI_API_KEY` env,\n * then the Pi `openai` platform-key entry, then the Pi `openai-codex` OAuth\n * login written by `pi login` (no manual setup required).\n */\nexport async function resolveOpenAiCredential(\n options: OpenAiCredentialOptions = {},\n): Promise<OpenAiCredential> {\n const env = options.env ?? process.env;\n const environmentKey = nonEmptyText(env.OPENAI_API_KEY);\n if (environmentKey) return { kind: \"platform\", key: environmentKey };\n\n const parsed = await readPiAuthRoot(options);\n\n const platform = record(parsed.openai);\n if (platform) {\n const key = platform.type === \"api_key\" ? nonEmptyText(platform.key) : null;\n if (!key) {\n throw new Error(\"OpenAI Pi auth file has a malformed openai credential\");\n }\n return { kind: \"platform\", key };\n }\n\n const oauth = record(parsed[\"openai-codex\"]);\n const access = oauth?.type === \"oauth\" ? nonEmptyText(oauth.access) : null;\n const accountId = nonEmptyText(oauth?.accountId);\n if (oauth && access && accountId) {\n return { kind: \"oauth\", access, accountId, expiresMs: toEpochMs(oauth.expires) };\n }\n throw new Error(MISSING_API_KEY_MESSAGE);\n}\n\nexport async function resolveOpenAiApiKey(options: OpenAiCredentialOptions = {}): Promise<string> {\n const credential = await resolveOpenAiCredential(options);\n if (credential.kind === \"platform\") return credential.key;\n throw new Error(MISSING_API_KEY_MESSAGE);\n}\n\nfunction bucketTokens(value: unknown): number {\n const results = Array.isArray(value) ? value : [];\n return results.reduce(\n (total, entry) =>\n total +\n (finiteNumber(record(entry)?.input_tokens) ?? 0) +\n (finiteNumber(record(entry)?.output_tokens) ?? 0),\n 0,\n );\n}\n\n/**\n * Maps one OpenAI Usage API payload (day buckets of per-model token counts)\n * into summed UTC-day buckets. Entries without a numeric\n * aggregation_timestamp are skipped because they cannot be placed in time.\n */\nexport function parseOpenAiUsage(raw: unknown): OpenAiUsageBucket[] {\n const data = record(raw)?.data;\n if (!Array.isArray(data)) throw new Error(\"Invalid OpenAI usage response\");\n const buckets: OpenAiUsageBucket[] = [];\n for (const entry of data) {\n const seconds = finiteNumber(record(entry)?.aggregation_timestamp);\n if (seconds === null) continue;\n buckets.push({ startMs: seconds * 1000, tokens: bucketTokens(record(entry)?.results) });\n }\n return buckets;\n}\n\nfunction openAiCapacityReport(\n windows: CapacityWindow[],\n checkedAt: string,\n authenticated: boolean,\n): CapacityReport {\n return {\n harness: \"pi\",\n provider: \"openai\",\n generatedAt: checkedAt,\n authenticated,\n available: windows.length > 0 ? \"yes\" : \"unknown\",\n windows,\n creditsRemaining: null,\n };\n}\n\n/**\n * Builds the capacity report from merged day buckets: trailing-7-day and\n * current-UTC-day token usage. The platform is pay-as-you-go and exposes no\n * queryable limit, so windows report consumption only — no faked percentages.\n */\nexport function buildOpenAiReport(buckets: OpenAiUsageBucket[], checkedAt: string): CapacityReport {\n const nowMs = Date.parse(checkedAt);\n const todayStartMs = Math.floor(nowMs / DAY_MS) * DAY_MS;\n const weekStartMs = todayStartMs - (USAGE_WINDOW_DAYS - 1) * DAY_MS;\n let todayTokens = 0;\n let weekTokens = 0;\n for (const bucket of buckets) {\n if (bucket.startMs === todayStartMs) todayTokens += bucket.tokens;\n if (bucket.startMs >= weekStartMs) weekTokens += bucket.tokens;\n }\n const windows: CapacityWindow[] = [\n {\n id: \"openai:tokens:today\",\n label: \"Tokens · today (UTC)\",\n limitType: \"TOKENS_LIMIT\",\n durationMinutes: 24 * 60,\n usedPercent: null,\n resetsAt: new Date(todayStartMs + DAY_MS).toISOString(),\n total: null,\n current: todayTokens,\n remaining: null,\n },\n {\n id: \"openai:tokens:week\",\n label: \"Tokens · 7 days\",\n limitType: \"TOKENS_LIMIT\",\n durationMinutes: USAGE_WINDOW_DAYS * 24 * 60,\n usedPercent: null,\n resetsAt: null,\n total: null,\n current: weekTokens,\n remaining: null,\n },\n ];\n return openAiCapacityReport(windows, checkedAt, true);\n}\n\nasync function fetchUsage(context: OpenAiRequestContext): Promise<unknown[] | number | null> {\n const fetcher = context.fetch ?? globalThis.fetch;\n const endSeconds = Math.floor(Date.parse(context.checkedAt) / 1000);\n const startSeconds = endSeconds - USAGE_WINDOW_DAYS * 24 * 60 * 60;\n const query = `start_time=${startSeconds}&end_time=${endSeconds}`;\n const payloads: unknown[] = [];\n for (const endpoint of OPENAI_USAGE_ENDPOINTS) {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), context.timeoutMs ?? 5000);\n let response: Response;\n try {\n response = await fetcher(`${OPENAI_USAGE_BASE_URL}/${endpoint}?${query}`, {\n method: \"GET\",\n headers: {\n Authorization: `Bearer ${context.key}`,\n },\n signal: controller.signal,\n });\n } catch {\n throw new Error(\"OpenAI usage request failed\");\n } finally {\n clearTimeout(timer);\n }\n if (response.status === 401) return null;\n if (response.status === 403) return response.status;\n if (response.status !== 200) {\n throw new Error(`OpenAI usage request failed: HTTP ${response.status}`);\n }\n try {\n payloads.push(await response.json());\n } catch {\n throw new Error(\"OpenAI usage response is not valid JSON\");\n }\n }\n return payloads;\n}\n\nasync function verifyKey(context: OpenAiRequestContext): Promise<boolean> {\n const fetcher = context.fetch ?? globalThis.fetch;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), context.timeoutMs ?? 5000);\n try {\n const response = await fetcher(OPENAI_MODELS_URL, {\n method: \"GET\",\n headers: { Authorization: `Bearer ${context.key}` },\n signal: controller.signal,\n });\n return response.status !== 401;\n } catch {\n throw new Error(\"OpenAI usage request failed\");\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function probeOpenAiCapacity(options: OpenAiProbeOptions): Promise<CapacityReport> {\n const credential = await resolveOpenAiCredential(options);\n if (credential.kind === \"oauth\") {\n return probeOpenAiOauthCapacity(credential, options);\n }\n const probe: OpenAiProbeOptions & { key: string } = { ...options, key: credential.key };\n const result = await fetchUsage(probe);\n if (result === null) {\n return openAiCapacityReport([], options.checkedAt, false);\n }\n if (typeof result === \"number\") {\n const authenticated = await verifyKey(probe);\n return openAiCapacityReport([], options.checkedAt, authenticated);\n }\n const buckets = result.flatMap(parseOpenAiUsage);\n return buildOpenAiReport(buckets, options.checkedAt);\n}\n\n/** Mirrors codex.ts: JWT `exp` (epoch seconds) as expiry fallback. */\nfunction jwtExpiryMs(token: string): number | null {\n const part = token.split(\".\")[1];\n if (!part) return null;\n try {\n const exp = finiteNumber(\n record(JSON.parse(Buffer.from(part, \"base64url\").toString(\"utf8\")))?.exp,\n );\n return exp === null ? null : exp * 1000;\n } catch {\n return null;\n }\n}\n\nfunction oauthExpired(credential: OAuthCredential, nowMs: number): boolean {\n const expiryMs = credential.expiresMs ?? jwtExpiryMs(credential.access);\n return expiryMs !== null && expiryMs <= nowMs;\n}\n\nasync function fetchWhamUsage(\n credential: OAuthCredential,\n options: OpenAiProbeOptions,\n): Promise<unknown | null> {\n const fetcher = options.fetch ?? globalThis.fetch;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), options.timeoutMs ?? 5000);\n let response: Response;\n try {\n response = await fetcher(WHAM_USAGE_URL, {\n method: \"GET\",\n headers: {\n Authorization: `Bearer ${credential.access}`,\n \"ChatGPT-Account-Id\": credential.accountId,\n },\n signal: controller.signal,\n });\n } catch {\n throw new Error(\"OpenAI usage request failed\");\n } finally {\n clearTimeout(timer);\n }\n if (response.status === 401 || response.status === 403) return null;\n if (response.status !== 200) {\n throw new Error(`OpenAI usage request failed: HTTP ${response.status}`);\n }\n try {\n return await response.json();\n } catch {\n throw new Error(\"OpenAI usage response is not valid JSON\");\n }\n}\n\n/**\n * OAuth path for Pi's OpenAI login: consumes the same wham/usage endpoint as\n * the codex harness. Stale logins are never fetched (no refresh, matching\n * codex.ts); they render as authenticated-but-stale instead.\n */\nasync function probeOpenAiOauthCapacity(\n credential: OAuthCredential,\n options: OpenAiProbeOptions,\n): Promise<CapacityReport> {\n const staleReport: CapacityReport = {\n harness: \"pi\",\n provider: \"openai\",\n generatedAt: options.checkedAt,\n authenticated: true,\n available: \"unknown\",\n windows: [],\n creditsRemaining: null,\n };\n const nowMs = Date.parse(options.checkedAt);\n if (Number.isNaN(nowMs) || oauthExpired(credential, nowMs)) return staleReport;\n const raw = await fetchWhamUsage(credential, options);\n if (raw === null) {\n return { ...staleReport, authenticated: false };\n }\n const snapshot = parseWhamUsage(raw);\n const hasUsage = snapshot.windows.some((window) => window.usedPercent !== null);\n return {\n ...staleReport,\n available: hasUsage ? \"yes\" : \"unknown\",\n windows: snapshot.windows,\n creditsRemaining: snapshot.creditsRemaining,\n };\n}\n"],"names":["readFile","homedir","join","parseWhamUsage","OPENAI_USAGE_BASE_URL","OPENAI_MODELS_URL","WHAM_USAGE_URL","OPENAI_USAGE_ENDPOINTS","USAGE_WINDOW_DAYS","DAY_MS","MISSING_API_KEY_MESSAGE","EPOCH_MS_FLOOR","record","value","Array","isArray","nonEmptyText","trim","finiteNumber","Number","isFinite","toEpochMs","raw","readPiAuthRoot","options","env","process","authPath","HOME","parsed","contents","root","JSON","parse","Error","error","code","resolveOpenAiCredential","environmentKey","OPENAI_API_KEY","kind","key","platform","openai","type","oauth","access","accountId","expiresMs","expires","resolveOpenAiApiKey","credential","bucketTokens","results","reduce","total","entry","input_tokens","output_tokens","parseOpenAiUsage","data","buckets","seconds","aggregation_timestamp","push","startMs","tokens","openAiCapacityReport","windows","checkedAt","authenticated","harness","provider","generatedAt","available","length","creditsRemaining","buildOpenAiReport","nowMs","Date","todayStartMs","Math","floor","weekStartMs","todayTokens","weekTokens","bucket","id","label","limitType","durationMinutes","usedPercent","resetsAt","toISOString","current","remaining","fetchUsage","context","fetcher","fetch","globalThis","endSeconds","startSeconds","query","payloads","endpoint","controller","AbortController","timer","setTimeout","abort","timeoutMs","response","method","headers","Authorization","signal","clearTimeout","status","json","verifyKey","probeOpenAiCapacity","probeOpenAiOauthCapacity","probe","result","flatMap","jwtExpiryMs","token","part","split","exp","Buffer","from","toString","oauthExpired","expiryMs","fetchWhamUsage","staleReport","isNaN","snapshot","hasUsage","some","window"],"mappings":"AAAA,SAASA,QAAQ,QAAQ,mBAAmB;AAC5C,SAASC,OAAO,QAAQ,UAAU;AAClC,SAASC,IAAI,QAAQ,YAAY;AACjC,SAASC,cAAc,QAAQ,YAAY;AAG3C,MAAMC,wBAAwB;AAC9B,MAAMC,oBAAoB;AAC1B,MAAMC,iBAAiB;AACvB,MAAMC,yBAAyB;IAAC;IAAe;CAAY;AAC3D,MAAMC,oBAAoB;AAC1B,MAAMC,SAAS,KAAK,KAAK,KAAK;AAC9B,MAAMC,0BACJ;AACF,MAAMC,iBAAiB;AA0BvB,SAASC,OAAOC,KAAc;IAC5B,OAAOA,UAAU,QAAQ,OAAOA,UAAU,YAAY,CAACC,MAAMC,OAAO,CAACF,SAChEA,QACD;AACN;AAEA,SAASG,aAAaH,KAAc;IAClC,OAAO,OAAOA,UAAU,YAAYA,MAAMI,IAAI,KAAKJ,MAAMI,IAAI,KAAK;AACpE;AAEA,SAASC,aAAaL,KAAc;IAClC,OAAO,OAAOA,UAAU,YAAYM,OAAOC,QAAQ,CAACP,SAASA,QAAQ;AACvE;AAEA,+EAA+E,GAC/E,SAASQ,UAAUR,KAAc;IAC/B,MAAMS,MAAMJ,aAAaL;IACzB,IAAIS,QAAQ,QAAQA,OAAO,GAAG,OAAO;IACrC,OAAOA,MAAMX,iBAAiBW,MAAMA,MAAM;AAC5C;AAEA,eAAeC,eAAeC,OAAgC;IAC5D,MAAMC,MAAMD,QAAQC,GAAG,IAAIC,QAAQD,GAAG;IACtC,MAAME,WAAWzB,KAAKuB,IAAIG,IAAI,IAAI3B,WAAW,OAAO,SAAS;IAC7D,IAAI4B;IACJ,IAAI;QACF,MAAMC,WAAW,MAAM,AAACN,CAAAA,QAAQxB,QAAQ,IAAIA,QAAO,EAAG2B,UAAU;QAChE,MAAMI,OAAOnB,OAAOoB,KAAKC,KAAK,CAACH;QAC/B,IAAI,CAACC,MAAM,MAAM,IAAIG,MAAM;QAC3BL,SAASE;IACX,EAAE,OAAOI,OAAO;QACd,IAAIvB,OAAOuB,QAAQC,SAAS,UAAU;YACpC,MAAM,IAAIF,MAAMxB;QAClB;QACA,MAAM,IAAIwB,MAAM;IAClB;IACA,OAAOL;AACT;AAEA;;;;CAIC,GACD,OAAO,eAAeQ,wBACpBb,UAAmC,CAAC,CAAC;IAErC,MAAMC,MAAMD,QAAQC,GAAG,IAAIC,QAAQD,GAAG;IACtC,MAAMa,iBAAiBtB,aAAaS,IAAIc,cAAc;IACtD,IAAID,gBAAgB,OAAO;QAAEE,MAAM;QAAYC,KAAKH;IAAe;IAEnE,MAAMT,SAAS,MAAMN,eAAeC;IAEpC,MAAMkB,WAAW9B,OAAOiB,OAAOc,MAAM;IACrC,IAAID,UAAU;QACZ,MAAMD,MAAMC,SAASE,IAAI,KAAK,YAAY5B,aAAa0B,SAASD,GAAG,IAAI;QACvE,IAAI,CAACA,KAAK;YACR,MAAM,IAAIP,MAAM;QAClB;QACA,OAAO;YAAEM,MAAM;YAAYC;QAAI;IACjC;IAEA,MAAMI,QAAQjC,OAAOiB,MAAM,CAAC,eAAe;IAC3C,MAAMiB,SAASD,OAAOD,SAAS,UAAU5B,aAAa6B,MAAMC,MAAM,IAAI;IACtE,MAAMC,YAAY/B,aAAa6B,OAAOE;IACtC,IAAIF,SAASC,UAAUC,WAAW;QAChC,OAAO;YAAEP,MAAM;YAASM;YAAQC;YAAWC,WAAW3B,UAAUwB,MAAMI,OAAO;QAAE;IACjF;IACA,MAAM,IAAIf,MAAMxB;AAClB;AAEA,OAAO,eAAewC,oBAAoB1B,UAAmC,CAAC,CAAC;IAC7E,MAAM2B,aAAa,MAAMd,wBAAwBb;IACjD,IAAI2B,WAAWX,IAAI,KAAK,YAAY,OAAOW,WAAWV,GAAG;IACzD,MAAM,IAAIP,MAAMxB;AAClB;AAEA,SAAS0C,aAAavC,KAAc;IAClC,MAAMwC,UAAUvC,MAAMC,OAAO,CAACF,SAASA,QAAQ,EAAE;IACjD,OAAOwC,QAAQC,MAAM,CACnB,CAACC,OAAOC,QACND,QACCrC,CAAAA,aAAaN,OAAO4C,QAAQC,iBAAiB,CAAA,IAC7CvC,CAAAA,aAAaN,OAAO4C,QAAQE,kBAAkB,CAAA,GACjD;AAEJ;AAEA;;;;CAIC,GACD,OAAO,SAASC,iBAAiBrC,GAAY;IAC3C,MAAMsC,OAAOhD,OAAOU,MAAMsC;IAC1B,IAAI,CAAC9C,MAAMC,OAAO,CAAC6C,OAAO,MAAM,IAAI1B,MAAM;IAC1C,MAAM2B,UAA+B,EAAE;IACvC,KAAK,MAAML,SAASI,KAAM;QACxB,MAAME,UAAU5C,aAAaN,OAAO4C,QAAQO;QAC5C,IAAID,YAAY,MAAM;QACtBD,QAAQG,IAAI,CAAC;YAAEC,SAASH,UAAU;YAAMI,QAAQd,aAAaxC,OAAO4C,QAAQH;QAAS;IACvF;IACA,OAAOQ;AACT;AAEA,SAASM,qBACPC,OAAyB,EACzBC,SAAiB,EACjBC,aAAsB;IAEtB,OAAO;QACLC,SAAS;QACTC,UAAU;QACVC,aAAaJ;QACbC;QACAI,WAAWN,QAAQO,MAAM,GAAG,IAAI,QAAQ;QACxCP;QACAQ,kBAAkB;IACpB;AACF;AAEA;;;;CAIC,GACD,OAAO,SAASC,kBAAkBhB,OAA4B,EAAEQ,SAAiB;IAC/E,MAAMS,QAAQC,KAAK9C,KAAK,CAACoC;IACzB,MAAMW,eAAeC,KAAKC,KAAK,CAACJ,QAAQrE,UAAUA;IAClD,MAAM0E,cAAcH,eAAe,AAACxE,CAAAA,oBAAoB,CAAA,IAAKC;IAC7D,IAAI2E,cAAc;IAClB,IAAIC,aAAa;IACjB,KAAK,MAAMC,UAAUzB,QAAS;QAC5B,IAAIyB,OAAOrB,OAAO,KAAKe,cAAcI,eAAeE,OAAOpB,MAAM;QACjE,IAAIoB,OAAOrB,OAAO,IAAIkB,aAAaE,cAAcC,OAAOpB,MAAM;IAChE;IACA,MAAME,UAA4B;QAChC;YACEmB,IAAI;YACJC,OAAO;YACPC,WAAW;YACXC,iBAAiB,KAAK;YACtBC,aAAa;YACbC,UAAU,IAAIb,KAAKC,eAAevE,QAAQoF,WAAW;YACrDtC,OAAO;YACPuC,SAASV;YACTW,WAAW;QACb;QACA;YACER,IAAI;YACJC,OAAO;YACPC,WAAW;YACXC,iBAAiBlF,oBAAoB,KAAK;YAC1CmF,aAAa;YACbC,UAAU;YACVrC,OAAO;YACPuC,SAAST;YACTU,WAAW;QACb;KACD;IACD,OAAO5B,qBAAqBC,SAASC,WAAW;AAClD;AAEA,eAAe2B,WAAWC,OAA6B;IACrD,MAAMC,UAAUD,QAAQE,KAAK,IAAIC,WAAWD,KAAK;IACjD,MAAME,aAAapB,KAAKC,KAAK,CAACH,KAAK9C,KAAK,CAACgE,QAAQ5B,SAAS,IAAI;IAC9D,MAAMiC,eAAeD,aAAa7F,oBAAoB,KAAK,KAAK;IAChE,MAAM+F,QAAQ,CAAC,WAAW,EAAED,aAAa,UAAU,EAAED,YAAY;IACjE,MAAMG,WAAsB,EAAE;IAC9B,KAAK,MAAMC,YAAYlG,uBAAwB;QAC7C,MAAMmG,aAAa,IAAIC;QACvB,MAAMC,QAAQC,WAAW,IAAMH,WAAWI,KAAK,IAAIb,QAAQc,SAAS,IAAI;QACxE,IAAIC;QACJ,IAAI;YACFA,WAAW,MAAMd,QAAQ,GAAG9F,sBAAsB,CAAC,EAAEqG,SAAS,CAAC,EAAEF,OAAO,EAAE;gBACxEU,QAAQ;gBACRC,SAAS;oBACPC,eAAe,CAAC,OAAO,EAAElB,QAAQxD,GAAG,EAAE;gBACxC;gBACA2E,QAAQV,WAAWU,MAAM;YAC3B;QACF,EAAE,OAAM;YACN,MAAM,IAAIlF,MAAM;QAClB,SAAU;YACRmF,aAAaT;QACf;QACA,IAAII,SAASM,MAAM,KAAK,KAAK,OAAO;QACpC,IAAIN,SAASM,MAAM,KAAK,KAAK,OAAON,SAASM,MAAM;QACnD,IAAIN,SAASM,MAAM,KAAK,KAAK;YAC3B,MAAM,IAAIpF,MAAM,CAAC,kCAAkC,EAAE8E,SAASM,MAAM,EAAE;QACxE;QACA,IAAI;YACFd,SAASxC,IAAI,CAAC,MAAMgD,SAASO,IAAI;QACnC,EAAE,OAAM;YACN,MAAM,IAAIrF,MAAM;QAClB;IACF;IACA,OAAOsE;AACT;AAEA,eAAegB,UAAUvB,OAA6B;IACpD,MAAMC,UAAUD,QAAQE,KAAK,IAAIC,WAAWD,KAAK;IACjD,MAAMO,aAAa,IAAIC;IACvB,MAAMC,QAAQC,WAAW,IAAMH,WAAWI,KAAK,IAAIb,QAAQc,SAAS,IAAI;IACxE,IAAI;QACF,MAAMC,WAAW,MAAMd,QAAQ7F,mBAAmB;YAChD4G,QAAQ;YACRC,SAAS;gBAAEC,eAAe,CAAC,OAAO,EAAElB,QAAQxD,GAAG,EAAE;YAAC;YAClD2E,QAAQV,WAAWU,MAAM;QAC3B;QACA,OAAOJ,SAASM,MAAM,KAAK;IAC7B,EAAE,OAAM;QACN,MAAM,IAAIpF,MAAM;IAClB,SAAU;QACRmF,aAAaT;IACf;AACF;AAEA,OAAO,eAAea,oBAAoBjG,OAA2B;IACnE,MAAM2B,aAAa,MAAMd,wBAAwBb;IACjD,IAAI2B,WAAWX,IAAI,KAAK,SAAS;QAC/B,OAAOkF,yBAAyBvE,YAAY3B;IAC9C;IACA,MAAMmG,QAA8C;QAAE,GAAGnG,OAAO;QAAEiB,KAAKU,WAAWV,GAAG;IAAC;IACtF,MAAMmF,SAAS,MAAM5B,WAAW2B;IAChC,IAAIC,WAAW,MAAM;QACnB,OAAOzD,qBAAqB,EAAE,EAAE3C,QAAQ6C,SAAS,EAAE;IACrD;IACA,IAAI,OAAOuD,WAAW,UAAU;QAC9B,MAAMtD,gBAAgB,MAAMkD,UAAUG;QACtC,OAAOxD,qBAAqB,EAAE,EAAE3C,QAAQ6C,SAAS,EAAEC;IACrD;IACA,MAAMT,UAAU+D,OAAOC,OAAO,CAAClE;IAC/B,OAAOkB,kBAAkBhB,SAASrC,QAAQ6C,SAAS;AACrD;AAEA,oEAAoE,GACpE,SAASyD,YAAYC,KAAa;IAChC,MAAMC,OAAOD,MAAME,KAAK,CAAC,IAAI,CAAC,EAAE;IAChC,IAAI,CAACD,MAAM,OAAO;IAClB,IAAI;QACF,MAAME,MAAMhH,aACVN,OAAOoB,KAAKC,KAAK,CAACkG,OAAOC,IAAI,CAACJ,MAAM,aAAaK,QAAQ,CAAC,WAAWH;QAEvE,OAAOA,QAAQ,OAAO,OAAOA,MAAM;IACrC,EAAE,OAAM;QACN,OAAO;IACT;AACF;AAEA,SAASI,aAAanF,UAA2B,EAAE2B,KAAa;IAC9D,MAAMyD,WAAWpF,WAAWH,SAAS,IAAI8E,YAAY3E,WAAWL,MAAM;IACtE,OAAOyF,aAAa,QAAQA,YAAYzD;AAC1C;AAEA,eAAe0D,eACbrF,UAA2B,EAC3B3B,OAA2B;IAE3B,MAAM0E,UAAU1E,QAAQ2E,KAAK,IAAIC,WAAWD,KAAK;IACjD,MAAMO,aAAa,IAAIC;IACvB,MAAMC,QAAQC,WAAW,IAAMH,WAAWI,KAAK,IAAItF,QAAQuF,SAAS,IAAI;IACxE,IAAIC;IACJ,IAAI;QACFA,WAAW,MAAMd,QAAQ5F,gBAAgB;YACvC2G,QAAQ;YACRC,SAAS;gBACPC,eAAe,CAAC,OAAO,EAAEhE,WAAWL,MAAM,EAAE;gBAC5C,sBAAsBK,WAAWJ,SAAS;YAC5C;YACAqE,QAAQV,WAAWU,MAAM;QAC3B;IACF,EAAE,OAAM;QACN,MAAM,IAAIlF,MAAM;IAClB,SAAU;QACRmF,aAAaT;IACf;IACA,IAAII,SAASM,MAAM,KAAK,OAAON,SAASM,MAAM,KAAK,KAAK,OAAO;IAC/D,IAAIN,SAASM,MAAM,KAAK,KAAK;QAC3B,MAAM,IAAIpF,MAAM,CAAC,kCAAkC,EAAE8E,SAASM,MAAM,EAAE;IACxE;IACA,IAAI;QACF,OAAO,MAAMN,SAASO,IAAI;IAC5B,EAAE,OAAM;QACN,MAAM,IAAIrF,MAAM;IAClB;AACF;AAEA;;;;CAIC,GACD,eAAewF,yBACbvE,UAA2B,EAC3B3B,OAA2B;IAE3B,MAAMiH,cAA8B;QAClClE,SAAS;QACTC,UAAU;QACVC,aAAajD,QAAQ6C,SAAS;QAC9BC,eAAe;QACfI,WAAW;QACXN,SAAS,EAAE;QACXQ,kBAAkB;IACpB;IACA,MAAME,QAAQC,KAAK9C,KAAK,CAACT,QAAQ6C,SAAS;IAC1C,IAAIlD,OAAOuH,KAAK,CAAC5D,UAAUwD,aAAanF,YAAY2B,QAAQ,OAAO2D;IACnE,MAAMnH,MAAM,MAAMkH,eAAerF,YAAY3B;IAC7C,IAAIF,QAAQ,MAAM;QAChB,OAAO;YAAE,GAAGmH,WAAW;YAAEnE,eAAe;QAAM;IAChD;IACA,MAAMqE,WAAWxI,eAAemB;IAChC,MAAMsH,WAAWD,SAASvE,OAAO,CAACyE,IAAI,CAAC,CAACC,SAAWA,OAAOnD,WAAW,KAAK;IAC1E,OAAO;QACL,GAAG8C,WAAW;QACd/D,WAAWkE,WAAW,QAAQ;QAC9BxE,SAASuE,SAASvE,OAAO;QACzBQ,kBAAkB+D,SAAS/D,gBAAgB;IAC7C;AACF"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { CapacityWindow } from "./types.js";
|
|
2
|
+
type WhamUsageSnapshot = {
|
|
3
|
+
windows: CapacityWindow[];
|
|
4
|
+
creditsRemaining: number | null;
|
|
5
|
+
};
|
|
6
|
+
export declare function resetTime(value: unknown): string | null;
|
|
7
|
+
export declare function safeIdentifier(value: unknown): string | null;
|
|
8
|
+
export declare function toRateWindow(value: unknown, id: string, label: string): CapacityWindow | null;
|
|
9
|
+
/**
|
|
10
|
+
* Parses the chatgpt.com backend wham/usage payload shared by every
|
|
11
|
+
* OAuth-backed OpenAI consumer (codex harness and pi login) into generic
|
|
12
|
+
* capacity windows plus the credit balance.
|
|
13
|
+
*/
|
|
14
|
+
export declare function parseWhamUsage(raw: unknown): WhamUsageSnapshot;
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=wham.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wham.d.ts","sourceRoot":"","sources":["../../src/capacity/wham.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,KAAK,iBAAiB,GAAG;IACvB,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC,CAAC;AAkBF,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAMvD;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAK5D;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAY7F;AAgBD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,iBAAiB,CAY9D"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
function record(value) {
|
|
2
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
3
|
+
}
|
|
4
|
+
function finiteNumber(value) {
|
|
5
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
6
|
+
}
|
|
7
|
+
function nonEmptyText(value) {
|
|
8
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
9
|
+
}
|
|
10
|
+
export function resetTime(value) {
|
|
11
|
+
const seconds = finiteNumber(value);
|
|
12
|
+
if (seconds !== null) return new Date(seconds * 1000).toISOString();
|
|
13
|
+
if (typeof value === "string" && !Number.isNaN(Date.parse(value))) return new Date(value).toISOString();
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
export function safeIdentifier(value) {
|
|
17
|
+
const candidate = nonEmptyText(value);
|
|
18
|
+
if (!candidate || !/^[a-z][a-z0-9_-]{0,63}$/i.test(candidate)) return null;
|
|
19
|
+
if (/(?:account|token|secret|key)[_-]?\d{6,}/i.test(candidate)) return null;
|
|
20
|
+
return candidate;
|
|
21
|
+
}
|
|
22
|
+
export function toRateWindow(value, id, label) {
|
|
23
|
+
const input = record(value);
|
|
24
|
+
if (!input) return null;
|
|
25
|
+
const used = finiteNumber(input.used_percent);
|
|
26
|
+
const seconds = finiteNumber(input.limit_window_seconds);
|
|
27
|
+
return {
|
|
28
|
+
id,
|
|
29
|
+
label,
|
|
30
|
+
durationMinutes: seconds === null ? null : seconds / 60,
|
|
31
|
+
usedPercent: used,
|
|
32
|
+
resetsAt: resetTime(input.reset_at)
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function extraWindows(value) {
|
|
36
|
+
if (!Array.isArray(value)) return [];
|
|
37
|
+
return value.flatMap((entry, index)=>{
|
|
38
|
+
const limit = record(entry);
|
|
39
|
+
if (!limit) return [];
|
|
40
|
+
const scope = safeIdentifier(limit.limit_name) ?? `extra-${index + 1}`;
|
|
41
|
+
const windows = record(limit.rate_limit) ?? limit;
|
|
42
|
+
return [
|
|
43
|
+
toRateWindow(windows.primary_window, `${scope}:primary`, `${scope} primary`),
|
|
44
|
+
toRateWindow(windows.secondary_window, `${scope}:secondary`, `${scope} secondary`)
|
|
45
|
+
].filter((window)=>window !== null);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Parses the chatgpt.com backend wham/usage payload shared by every
|
|
50
|
+
* OAuth-backed OpenAI consumer (codex harness and pi login) into generic
|
|
51
|
+
* capacity windows plus the credit balance.
|
|
52
|
+
*/ export function parseWhamUsage(raw) {
|
|
53
|
+
const response = record(raw) ?? {};
|
|
54
|
+
const limits = record(response.rate_limit) ?? {};
|
|
55
|
+
const credits = record(response.credits) ?? {};
|
|
56
|
+
return {
|
|
57
|
+
windows: [
|
|
58
|
+
toRateWindow(limits.primary_window, "session", "Session"),
|
|
59
|
+
toRateWindow(limits.secondary_window, "weekly", "Weekly"),
|
|
60
|
+
...extraWindows(response.additional_rate_limits)
|
|
61
|
+
].filter((window)=>window !== null),
|
|
62
|
+
creditsRemaining: finiteNumber(credits.balance)
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
//# sourceMappingURL=wham.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/capacity/wham.ts"],"sourcesContent":["import type { CapacityWindow } from \"./types.js\";\n\ntype WhamUsageSnapshot = {\n windows: CapacityWindow[];\n creditsRemaining: number | null;\n};\n\ntype UnknownRecord = Record<string, unknown>;\n\nfunction record(value: unknown): UnknownRecord | null {\n return value !== null && typeof value === \"object\" && !Array.isArray(value)\n ? (value as UnknownRecord)\n : null;\n}\n\nfunction finiteNumber(value: unknown): number | null {\n return typeof value === \"number\" && Number.isFinite(value) ? value : null;\n}\n\nfunction nonEmptyText(value: unknown): string | null {\n return typeof value === \"string\" && value.length > 0 ? value : null;\n}\n\nexport function resetTime(value: unknown): string | null {\n const seconds = finiteNumber(value);\n if (seconds !== null) return new Date(seconds * 1000).toISOString();\n if (typeof value === \"string\" && !Number.isNaN(Date.parse(value)))\n return new Date(value).toISOString();\n return null;\n}\n\nexport function safeIdentifier(value: unknown): string | null {\n const candidate = nonEmptyText(value);\n if (!candidate || !/^[a-z][a-z0-9_-]{0,63}$/i.test(candidate)) return null;\n if (/(?:account|token|secret|key)[_-]?\\d{6,}/i.test(candidate)) return null;\n return candidate;\n}\n\nexport function toRateWindow(value: unknown, id: string, label: string): CapacityWindow | null {\n const input = record(value);\n if (!input) return null;\n const used = finiteNumber(input.used_percent);\n const seconds = finiteNumber(input.limit_window_seconds);\n return {\n id,\n label,\n durationMinutes: seconds === null ? null : seconds / 60,\n usedPercent: used,\n resetsAt: resetTime(input.reset_at),\n };\n}\n\nfunction extraWindows(value: unknown): CapacityWindow[] {\n if (!Array.isArray(value)) return [];\n return value.flatMap((entry, index) => {\n const limit = record(entry);\n if (!limit) return [];\n const scope = safeIdentifier(limit.limit_name) ?? `extra-${index + 1}`;\n const windows = record(limit.rate_limit) ?? limit;\n return [\n toRateWindow(windows.primary_window, `${scope}:primary`, `${scope} primary`),\n toRateWindow(windows.secondary_window, `${scope}:secondary`, `${scope} secondary`),\n ].filter((window): window is CapacityWindow => window !== null);\n });\n}\n\n/**\n * Parses the chatgpt.com backend wham/usage payload shared by every\n * OAuth-backed OpenAI consumer (codex harness and pi login) into generic\n * capacity windows plus the credit balance.\n */\nexport function parseWhamUsage(raw: unknown): WhamUsageSnapshot {\n const response = record(raw) ?? {};\n const limits = record(response.rate_limit) ?? {};\n const credits = record(response.credits) ?? {};\n return {\n windows: [\n toRateWindow(limits.primary_window, \"session\", \"Session\"),\n toRateWindow(limits.secondary_window, \"weekly\", \"Weekly\"),\n ...extraWindows(response.additional_rate_limits),\n ].filter((window): window is CapacityWindow => window !== null),\n creditsRemaining: finiteNumber(credits.balance),\n };\n}\n"],"names":["record","value","Array","isArray","finiteNumber","Number","isFinite","nonEmptyText","length","resetTime","seconds","Date","toISOString","isNaN","parse","safeIdentifier","candidate","test","toRateWindow","id","label","input","used","used_percent","limit_window_seconds","durationMinutes","usedPercent","resetsAt","reset_at","extraWindows","flatMap","entry","index","limit","scope","limit_name","windows","rate_limit","primary_window","secondary_window","filter","window","parseWhamUsage","raw","response","limits","credits","additional_rate_limits","creditsRemaining","balance"],"mappings":"AASA,SAASA,OAAOC,KAAc;IAC5B,OAAOA,UAAU,QAAQ,OAAOA,UAAU,YAAY,CAACC,MAAMC,OAAO,CAACF,SAChEA,QACD;AACN;AAEA,SAASG,aAAaH,KAAc;IAClC,OAAO,OAAOA,UAAU,YAAYI,OAAOC,QAAQ,CAACL,SAASA,QAAQ;AACvE;AAEA,SAASM,aAAaN,KAAc;IAClC,OAAO,OAAOA,UAAU,YAAYA,MAAMO,MAAM,GAAG,IAAIP,QAAQ;AACjE;AAEA,OAAO,SAASQ,UAAUR,KAAc;IACtC,MAAMS,UAAUN,aAAaH;IAC7B,IAAIS,YAAY,MAAM,OAAO,IAAIC,KAAKD,UAAU,MAAME,WAAW;IACjE,IAAI,OAAOX,UAAU,YAAY,CAACI,OAAOQ,KAAK,CAACF,KAAKG,KAAK,CAACb,SACxD,OAAO,IAAIU,KAAKV,OAAOW,WAAW;IACpC,OAAO;AACT;AAEA,OAAO,SAASG,eAAed,KAAc;IAC3C,MAAMe,YAAYT,aAAaN;IAC/B,IAAI,CAACe,aAAa,CAAC,2BAA2BC,IAAI,CAACD,YAAY,OAAO;IACtE,IAAI,2CAA2CC,IAAI,CAACD,YAAY,OAAO;IACvE,OAAOA;AACT;AAEA,OAAO,SAASE,aAAajB,KAAc,EAAEkB,EAAU,EAAEC,KAAa;IACpE,MAAMC,QAAQrB,OAAOC;IACrB,IAAI,CAACoB,OAAO,OAAO;IACnB,MAAMC,OAAOlB,aAAaiB,MAAME,YAAY;IAC5C,MAAMb,UAAUN,aAAaiB,MAAMG,oBAAoB;IACvD,OAAO;QACLL;QACAC;QACAK,iBAAiBf,YAAY,OAAO,OAAOA,UAAU;QACrDgB,aAAaJ;QACbK,UAAUlB,UAAUY,MAAMO,QAAQ;IACpC;AACF;AAEA,SAASC,aAAa5B,KAAc;IAClC,IAAI,CAACC,MAAMC,OAAO,CAACF,QAAQ,OAAO,EAAE;IACpC,OAAOA,MAAM6B,OAAO,CAAC,CAACC,OAAOC;QAC3B,MAAMC,QAAQjC,OAAO+B;QACrB,IAAI,CAACE,OAAO,OAAO,EAAE;QACrB,MAAMC,QAAQnB,eAAekB,MAAME,UAAU,KAAK,CAAC,MAAM,EAAEH,QAAQ,GAAG;QACtE,MAAMI,UAAUpC,OAAOiC,MAAMI,UAAU,KAAKJ;QAC5C,OAAO;YACLf,aAAakB,QAAQE,cAAc,EAAE,GAAGJ,MAAM,QAAQ,CAAC,EAAE,GAAGA,MAAM,QAAQ,CAAC;YAC3EhB,aAAakB,QAAQG,gBAAgB,EAAE,GAAGL,MAAM,UAAU,CAAC,EAAE,GAAGA,MAAM,UAAU,CAAC;SAClF,CAACM,MAAM,CAAC,CAACC,SAAqCA,WAAW;IAC5D;AACF;AAEA;;;;CAIC,GACD,OAAO,SAASC,eAAeC,GAAY;IACzC,MAAMC,WAAW5C,OAAO2C,QAAQ,CAAC;IACjC,MAAME,SAAS7C,OAAO4C,SAASP,UAAU,KAAK,CAAC;IAC/C,MAAMS,UAAU9C,OAAO4C,SAASE,OAAO,KAAK,CAAC;IAC7C,OAAO;QACLV,SAAS;YACPlB,aAAa2B,OAAOP,cAAc,EAAE,WAAW;YAC/CpB,aAAa2B,OAAON,gBAAgB,EAAE,UAAU;eAC7CV,aAAae,SAASG,sBAAsB;SAChD,CAACP,MAAM,CAAC,CAACC,SAAqCA,WAAW;QAC1DO,kBAAkB5C,aAAa0C,QAAQG,OAAO;IAChD;AACF"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
export { AgentManager, AgentNotRunningError } from "./AgentManager.js";
|
|
2
|
-
export { getCodexCapacityReport, getZaiCapacityReport } from "./capacity/index.js";
|
|
3
|
-
export type { CapacityProbeOptions, CapacityReport, CapacityWindow, ZaiCapacityOptions, } from "./capacity/index.js";
|
|
2
|
+
export { getClaudeCapacityReport, getCodexCapacityReport, getOpenAiCapacityReport, getZaiCapacityReport, } from "./capacity/index.js";
|
|
3
|
+
export type { ClaudeCapacityOptions, CapacityProbeOptions, CapacityReport, CapacityWindow, OpenAiCapacityOptions, ZaiCapacityOptions, } from "./capacity/index.js";
|
|
4
4
|
export { getAgentReadinessReport, getAgentReadinessReports, worstReadinessStatus, } from "./readiness/AgentReadiness.js";
|
|
5
5
|
export type { AgentReadinessOptions, AgentReadinessReport, AuthReadinessCheck, BuiltInSkillsReadinessCheck, DirectoryReadinessCheck, ExecutableReadinessCheck, IntegrationReadinessCheck, ReadinessAgentType, ReadinessAuthState, ReadinessCheck, ReadinessStatus, } from "./readiness/AgentReadiness.js";
|
|
6
6
|
export { ClaudeCodeAdapter } from "./providers/claude/ClaudeCodeAdapter.js";
|
|
7
7
|
export { CodexAdapter } from "./providers/codex/CodexAdapter.js";
|
|
8
8
|
export { CopilotAdapter } from "./providers/copilot/CopilotAdapter.js";
|
|
9
9
|
export { GeminiCliAdapter } from "./providers/gemini/GeminiCliAdapter.js";
|
|
10
|
-
export { GrokCliAdapter } from "./
|
|
10
|
+
export { GrokCliAdapter } from "./providers/grok/GrokCliAdapter.js";
|
|
11
|
+
export { AntigravityCliAdapter } from "./adapters/AntigravityCliAdapter.js";
|
|
12
|
+
export { KiroAdapter } from "./adapters/KiroAdapter.js";
|
|
11
13
|
export { OpenCodeAdapter } from "./providers/opencode/OpenCodeAdapter.js";
|
|
12
14
|
export { PiAdapter } from "./providers/pi/PiAdapter.js";
|
|
13
15
|
export { AgentStatus } from "./adapters/AgentAdapter.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EACL,uBAAuB,EACvB,sBAAsB,EACtB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,qBAAqB,EACrB,oBAAoB,EACpB,cAAc,EACd,cAAc,EACd,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,uBAAuB,EACvB,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,+BAA+B,CAAC;AACvC,YAAY,EACV,qBAAqB,EACrB,oBAAoB,EACpB,kBAAkB,EAClB,2BAA2B,EAC3B,uBAAuB,EACvB,wBAAwB,EACxB,yBAAyB,EACzB,kBAAkB,EAClB,kBAAkB,EAClB,cAAc,EACd,eAAe,GAChB,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAC;AAC1E,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAC1E,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,YAAY,EACV,YAAY,EACZ,SAAS,EACT,SAAS,EACT,WAAW,EACX,mBAAmB,EACnB,cAAc,EACd,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AACxF,YAAY,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEpD,YAAY,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAChF,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,wCAAwC,CAAC;AAChD,YAAY,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAC;AAE7E,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,mBAAmB,EACnB,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,oBAAoB,EACpB,aAAa,EACb,oBAAoB,EACpB,cAAc,GACf,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,YAAY,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAC5F,OAAO,EACL,UAAU,EACV,SAAS,EACT,UAAU,EACV,eAAe,EACf,oBAAoB,EACpB,mBAAmB,EACnB,wBAAwB,EACxB,4BAA4B,EAC5B,0BAA0B,EAC1B,4BAA4B,EAC5B,2BAA2B,GAC5B,MAAM,kCAAkC,CAAC;AAC1C,YAAY,EACV,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEzE,YAAY,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,qBAAqB,EACrB,yBAAyB,EACzB,2BAA2B,EAC3B,6BAA6B,EAC7B,gBAAgB,EAChB,eAAe,EACf,YAAY,GACb,MAAM,2BAA2B,CAAC;AACnC,YAAY,EACV,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,GAChB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,YAAY,EACV,uBAAuB,EACvB,6BAA6B,EAC7B,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,uBAAuB,EAAE,MAAM,uDAAuD,CAAC;AAChG,YAAY,EACV,8BAA8B,EAC9B,qBAAqB,GACtB,MAAM,uDAAuD,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,4CAA4C,CAAC;AAC3E,YAAY,EAAE,oBAAoB,EAAE,MAAM,4CAA4C,CAAC;AACvF,OAAO,EAAE,gBAAgB,EAAE,MAAM,+CAA+C,CAAC;AACjF,YAAY,EACV,uBAAuB,EACvB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,+CAA+C,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,qDAAqD,CAAC;AAC7F,YAAY,EACV,6BAA6B,EAC7B,oBAAoB,GACrB,MAAM,qDAAqD,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,sCAAsC,CAAC;AAClE,YAAY,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AACxE,YAAY,EACV,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,+CAA+C,CAAC;AACpF,YAAY,EACV,0BAA0B,EAC1B,iBAAiB,GAClB,MAAM,+CAA+C,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
export { AgentManager, AgentNotRunningError } from "./AgentManager.js";
|
|
2
|
-
export { getCodexCapacityReport, getZaiCapacityReport } from "./capacity/index.js";
|
|
2
|
+
export { getClaudeCapacityReport, getCodexCapacityReport, getOpenAiCapacityReport, getZaiCapacityReport } from "./capacity/index.js";
|
|
3
3
|
export { getAgentReadinessReport, getAgentReadinessReports, worstReadinessStatus } from "./readiness/AgentReadiness.js";
|
|
4
4
|
export { ClaudeCodeAdapter } from "./providers/claude/ClaudeCodeAdapter.js";
|
|
5
5
|
export { CodexAdapter } from "./providers/codex/CodexAdapter.js";
|
|
6
6
|
export { CopilotAdapter } from "./providers/copilot/CopilotAdapter.js";
|
|
7
7
|
export { GeminiCliAdapter } from "./providers/gemini/GeminiCliAdapter.js";
|
|
8
|
-
export { GrokCliAdapter } from "./
|
|
8
|
+
export { GrokCliAdapter } from "./providers/grok/GrokCliAdapter.js";
|
|
9
|
+
export { AntigravityCliAdapter } from "./adapters/AntigravityCliAdapter.js";
|
|
10
|
+
export { KiroAdapter } from "./adapters/KiroAdapter.js";
|
|
9
11
|
export { OpenCodeAdapter } from "./providers/opencode/OpenCodeAdapter.js";
|
|
10
12
|
export { PiAdapter } from "./providers/pi/PiAdapter.js";
|
|
11
13
|
export { AgentStatus } from "./adapters/AgentAdapter.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export { AgentManager, AgentNotRunningError } from \"./AgentManager.js\";\nexport {
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export { AgentManager, AgentNotRunningError } from \"./AgentManager.js\";\nexport {\n getClaudeCapacityReport,\n getCodexCapacityReport,\n getOpenAiCapacityReport,\n getZaiCapacityReport,\n} from \"./capacity/index.js\";\nexport type {\n ClaudeCapacityOptions,\n CapacityProbeOptions,\n CapacityReport,\n CapacityWindow,\n OpenAiCapacityOptions,\n ZaiCapacityOptions,\n} from \"./capacity/index.js\";\nexport {\n getAgentReadinessReport,\n getAgentReadinessReports,\n worstReadinessStatus,\n} from \"./readiness/AgentReadiness.js\";\nexport type {\n AgentReadinessOptions,\n AgentReadinessReport,\n AuthReadinessCheck,\n BuiltInSkillsReadinessCheck,\n DirectoryReadinessCheck,\n ExecutableReadinessCheck,\n IntegrationReadinessCheck,\n ReadinessAgentType,\n ReadinessAuthState,\n ReadinessCheck,\n ReadinessStatus,\n} from \"./readiness/AgentReadiness.js\";\n\nexport { ClaudeCodeAdapter } from \"./providers/claude/ClaudeCodeAdapter.js\";\nexport { CodexAdapter } from \"./providers/codex/CodexAdapter.js\";\nexport { CopilotAdapter } from \"./providers/copilot/CopilotAdapter.js\";\nexport { GeminiCliAdapter } from \"./providers/gemini/GeminiCliAdapter.js\";\nexport { GrokCliAdapter } from \"./providers/grok/GrokCliAdapter.js\";\nexport { AntigravityCliAdapter } from \"./adapters/AntigravityCliAdapter.js\";\nexport { KiroAdapter } from \"./adapters/KiroAdapter.js\";\nexport { OpenCodeAdapter } from \"./providers/opencode/OpenCodeAdapter.js\";\nexport { PiAdapter } from \"./providers/pi/PiAdapter.js\";\nexport { AgentStatus } from \"./adapters/AgentAdapter.js\";\nexport type {\n AgentAdapter,\n AgentType,\n AgentInfo,\n ProcessInfo,\n ConversationMessage,\n SessionSummary,\n ListSessionsOptions,\n AgentDetectionContext,\n} from \"./adapters/AgentAdapter.js\";\n\nexport { TerminalFocusManager, TerminalType } from \"./terminal/TerminalFocusManager.js\";\nexport type { TerminalLocation } from \"./terminal/TerminalFocusManager.js\";\nexport { TtyWriter } from \"./terminal/TtyWriter.js\";\n\nexport type { AgentManagerOptions, ListAgentsOptions } from \"./AgentManager.js\";\nexport {\n extractHerdrAgentPanes,\n fetchHerdrAgentPanes,\n findMatchingHerdrPane,\n herdrPaneToRuntimeRef,\n} from \"./runtime/herdr/HerdrAgentDiscovery.js\";\nexport type { HerdrAgentPane } from \"./runtime/herdr/HerdrAgentDiscovery.js\";\n\nexport {\n AgentRegistry,\n RenameNotFoundError,\n RenameConflictError,\n AGENT_RUNTIME_PROVIDERS,\n parseTmuxRuntimeRef,\n} from \"./utils/AgentRegistry.js\";\nexport type {\n AgentRegistryOptions,\n RegistryEntry,\n AgentRuntimeProvider,\n TmuxRuntimeRef,\n} from \"./utils/AgentRegistry.js\";\nexport { TmuxManager } from \"./terminal/TmuxManager.js\";\nexport type { AgentRuntimeAvailability, InteractiveAgentRuntime } from \"./runtime/types.js\";\nexport {\n startAgent,\n stopAgent,\n focusAgent,\n sendAgentPrompt,\n TmuxUnavailableError,\n AgentNameInUseError,\n AgentPidPollTimeoutError,\n AgentRuntimeUnavailableError,\n AgentTerminalNotFoundError,\n DEFAULT_PID_POLL_INTERVAL_MS,\n DEFAULT_PID_POLL_TIMEOUT_MS,\n} from \"./runtime/ManagedAgentRuntime.js\";\nexport type {\n FocusAgentDeps,\n StartAgentDeps,\n StartAgentOptions,\n StopAgentDeps,\n StopAgentResult,\n FocusAgentResult,\n SendAgentPromptDeps,\n} from \"./runtime/ManagedAgentRuntime.js\";\nexport { AGENTS } from \"./utils/agents.js\";\nexport type { AgentConfig, StartableAgentType } from \"./utils/agents.js\";\n\nexport type { AgentRequest } from \"./utils/agent-requests.js\";\nexport {\n getAgentRequestPath,\n readLatestAgentRequest,\n writeAgentRequest,\n} from \"./utils/agent-requests.js\";\n\nexport {\n AGENT_MODES,\n DurableAgentError,\n DurableAgentBusyError,\n DurableAgentNotFoundError,\n DurableAgentRepositoryError,\n DurableAgentNameConflictError,\n ClaudePrintError,\n CodexPrintError,\n PiPrintError,\n} from \"./durable/DurableAgent.js\";\nexport type {\n DurableAgent,\n DurableAgentBase,\n ClaudeDurableAgent,\n CodexDurableAgent,\n PiDurableAgent,\n DurableProvider,\n CodexPrintErrorCode,\n DurableAgentState,\n DurableSessionHealth,\n DurableRunStatus,\n DurableActiveRun,\n DurableLastResult,\n PiPrintErrorCode,\n ProcessIdentity,\n} from \"./durable/DurableAgent.js\";\nexport { DurableAgentRepository } from \"./durable/DurableAgentRepository.js\";\nexport type {\n CreateDurableAgentInput,\n DurableAgentRepositoryOptions,\n ProcessInspector,\n DurableRunCompletion,\n} from \"./durable/DurableAgentRepository.js\";\nexport { ClaudePrintAgentService } from \"./providers/claude/durable/ClaudePrintAgentService.js\";\nexport type {\n ClaudePrintAgentServiceOptions,\n ClaudePrintSendResult,\n} from \"./providers/claude/durable/ClaudePrintAgentService.js\";\nexport { CodexCliProbe } from \"./providers/codex/durable/CodexCliProbe.js\";\nexport type { CodexCliProbeOptions } from \"./providers/codex/durable/CodexCliProbe.js\";\nexport { CodexPrintRunner } from \"./providers/codex/durable/CodexPrintRunner.js\";\nexport type {\n CodexPrintRunnerOptions,\n CodexPrintRunRequest,\n CodexPrintRunResult,\n} from \"./providers/codex/durable/CodexPrintRunner.js\";\nexport { CodexPrintAgentService } from \"./providers/codex/durable/CodexPrintAgentService.js\";\nexport type {\n CodexPrintAgentServiceOptions,\n CodexPrintSendResult,\n} from \"./providers/codex/durable/CodexPrintAgentService.js\";\nexport { PiCliProbe } from \"./providers/pi/durable/PiCliProbe.js\";\nexport type { PiCliProbeOptions } from \"./providers/pi/durable/PiCliProbe.js\";\nexport { PiPrintRunner } from \"./providers/pi/durable/PiPrintRunner.js\";\nexport type {\n PiPrintRunnerOptions,\n PiPrintRunRequest,\n PiPrintRunResult,\n} from \"./providers/pi/durable/PiPrintRunner.js\";\nexport { PiPrintAgentService } from \"./providers/pi/durable/PiPrintAgentService.js\";\nexport type {\n PiPrintAgentServiceOptions,\n PiPrintSendResult,\n} from \"./providers/pi/durable/PiPrintAgentService.js\";\n"],"names":["AgentManager","AgentNotRunningError","getClaudeCapacityReport","getCodexCapacityReport","getOpenAiCapacityReport","getZaiCapacityReport","getAgentReadinessReport","getAgentReadinessReports","worstReadinessStatus","ClaudeCodeAdapter","CodexAdapter","CopilotAdapter","GeminiCliAdapter","GrokCliAdapter","AntigravityCliAdapter","KiroAdapter","OpenCodeAdapter","PiAdapter","AgentStatus","TerminalFocusManager","TerminalType","TtyWriter","extractHerdrAgentPanes","fetchHerdrAgentPanes","findMatchingHerdrPane","herdrPaneToRuntimeRef","AgentRegistry","RenameNotFoundError","RenameConflictError","AGENT_RUNTIME_PROVIDERS","parseTmuxRuntimeRef","TmuxManager","startAgent","stopAgent","focusAgent","sendAgentPrompt","TmuxUnavailableError","AgentNameInUseError","AgentPidPollTimeoutError","AgentRuntimeUnavailableError","AgentTerminalNotFoundError","DEFAULT_PID_POLL_INTERVAL_MS","DEFAULT_PID_POLL_TIMEOUT_MS","AGENTS","getAgentRequestPath","readLatestAgentRequest","writeAgentRequest","AGENT_MODES","DurableAgentError","DurableAgentBusyError","DurableAgentNotFoundError","DurableAgentRepositoryError","DurableAgentNameConflictError","ClaudePrintError","CodexPrintError","PiPrintError","DurableAgentRepository","ClaudePrintAgentService","CodexCliProbe","CodexPrintRunner","CodexPrintAgentService","PiCliProbe","PiPrintRunner","PiPrintAgentService"],"mappings":"AAAA,SAASA,YAAY,EAAEC,oBAAoB,QAAQ,oBAAoB;AACvE,SACEC,uBAAuB,EACvBC,sBAAsB,EACtBC,uBAAuB,EACvBC,oBAAoB,QACf,sBAAsB;AAS7B,SACEC,uBAAuB,EACvBC,wBAAwB,EACxBC,oBAAoB,QACf,gCAAgC;AAevC,SAASC,iBAAiB,QAAQ,0CAA0C;AAC5E,SAASC,YAAY,QAAQ,oCAAoC;AACjE,SAASC,cAAc,QAAQ,wCAAwC;AACvE,SAASC,gBAAgB,QAAQ,yCAAyC;AAC1E,SAASC,cAAc,QAAQ,qCAAqC;AACpE,SAASC,qBAAqB,QAAQ,sCAAsC;AAC5E,SAASC,WAAW,QAAQ,4BAA4B;AACxD,SAASC,eAAe,QAAQ,0CAA0C;AAC1E,SAASC,SAAS,QAAQ,8BAA8B;AACxD,SAASC,WAAW,QAAQ,6BAA6B;AAYzD,SAASC,oBAAoB,EAAEC,YAAY,QAAQ,qCAAqC;AAExF,SAASC,SAAS,QAAQ,0BAA0B;AAGpD,SACEC,sBAAsB,EACtBC,oBAAoB,EACpBC,qBAAqB,EACrBC,qBAAqB,QAChB,yCAAyC;AAGhD,SACEC,aAAa,EACbC,mBAAmB,EACnBC,mBAAmB,EACnBC,uBAAuB,EACvBC,mBAAmB,QACd,2BAA2B;AAOlC,SAASC,WAAW,QAAQ,4BAA4B;AAExD,SACEC,UAAU,EACVC,SAAS,EACTC,UAAU,EACVC,eAAe,EACfC,oBAAoB,EACpBC,mBAAmB,EACnBC,wBAAwB,EACxBC,4BAA4B,EAC5BC,0BAA0B,EAC1BC,4BAA4B,EAC5BC,2BAA2B,QACtB,mCAAmC;AAU1C,SAASC,MAAM,QAAQ,oBAAoB;AAI3C,SACEC,mBAAmB,EACnBC,sBAAsB,EACtBC,iBAAiB,QACZ,4BAA4B;AAEnC,SACEC,WAAW,EACXC,iBAAiB,EACjBC,qBAAqB,EACrBC,yBAAyB,EACzBC,2BAA2B,EAC3BC,6BAA6B,EAC7BC,gBAAgB,EAChBC,eAAe,EACfC,YAAY,QACP,4BAA4B;AAiBnC,SAASC,sBAAsB,QAAQ,sCAAsC;AAO7E,SAASC,uBAAuB,QAAQ,wDAAwD;AAKhG,SAASC,aAAa,QAAQ,6CAA6C;AAE3E,SAASC,gBAAgB,QAAQ,gDAAgD;AAMjF,SAASC,sBAAsB,QAAQ,sDAAsD;AAK7F,SAASC,UAAU,QAAQ,uCAAuC;AAElE,SAASC,aAAa,QAAQ,0CAA0C;AAMxE,SAASC,mBAAmB,QAAQ,gDAAgD"}
|
|
@@ -25,5 +25,7 @@ export declare class ClaudeCodeAdapter implements AgentAdapter {
|
|
|
25
25
|
verbose?: boolean;
|
|
26
26
|
}): ConversationMessage[];
|
|
27
27
|
listSessions(opts?: ListSessionsOptions): Promise<SessionSummary[]>;
|
|
28
|
+
findSessionsById(sessionId: string): Promise<SessionSummary[]>;
|
|
29
|
+
private toSessionSummary;
|
|
28
30
|
}
|
|
29
31
|
//# sourceMappingURL=ClaudeCodeAdapter.d.ts.map
|