@zhachory1/mewrite-ai 0.65.3
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/README.md +1330 -0
- package/dist/api-registry.d.ts +20 -0
- package/dist/api-registry.d.ts.map +1 -0
- package/dist/api-registry.js +44 -0
- package/dist/api-registry.js.map +1 -0
- package/dist/bedrock-provider.d.ts +5 -0
- package/dist/bedrock-provider.d.ts.map +1 -0
- package/dist/bedrock-provider.js +6 -0
- package/dist/bedrock-provider.js.map +1 -0
- package/dist/cache/__tests__/compaction.test.d.ts +2 -0
- package/dist/cache/__tests__/compaction.test.d.ts.map +1 -0
- package/dist/cache/__tests__/compaction.test.js +100 -0
- package/dist/cache/__tests__/compaction.test.js.map +1 -0
- package/dist/cache/__tests__/layers.test.d.ts +2 -0
- package/dist/cache/__tests__/layers.test.d.ts.map +1 -0
- package/dist/cache/__tests__/layers.test.js +71 -0
- package/dist/cache/__tests__/layers.test.js.map +1 -0
- package/dist/cache/__tests__/policy.test.d.ts +2 -0
- package/dist/cache/__tests__/policy.test.d.ts.map +1 -0
- package/dist/cache/__tests__/policy.test.js +79 -0
- package/dist/cache/__tests__/policy.test.js.map +1 -0
- package/dist/cache/__tests__/tool-serializer.test.d.ts +2 -0
- package/dist/cache/__tests__/tool-serializer.test.d.ts.map +1 -0
- package/dist/cache/__tests__/tool-serializer.test.js +64 -0
- package/dist/cache/__tests__/tool-serializer.test.js.map +1 -0
- package/dist/cache/compaction.d.ts +30 -0
- package/dist/cache/compaction.d.ts.map +1 -0
- package/dist/cache/compaction.js +50 -0
- package/dist/cache/compaction.js.map +1 -0
- package/dist/cache/index.d.ts +5 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +5 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/layers.d.ts +17 -0
- package/dist/cache/layers.d.ts.map +1 -0
- package/dist/cache/layers.js +48 -0
- package/dist/cache/layers.js.map +1 -0
- package/dist/cache/policy.d.ts +40 -0
- package/dist/cache/policy.d.ts.map +1 -0
- package/dist/cache/policy.js +50 -0
- package/dist/cache/policy.js.map +1 -0
- package/dist/cache/tool-serializer.d.ts +8 -0
- package/dist/cache/tool-serializer.d.ts.map +1 -0
- package/dist/cache/tool-serializer.js +35 -0
- package/dist/cache/tool-serializer.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +116 -0
- package/dist/cli.js.map +1 -0
- package/dist/env-api-keys.d.ts +27 -0
- package/dist/env-api-keys.d.ts.map +1 -0
- package/dist/env-api-keys.js +223 -0
- package/dist/env-api-keys.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/models.d.ts +34 -0
- package/dist/models.d.ts.map +1 -0
- package/dist/models.generated.d.ts +14370 -0
- package/dist/models.generated.d.ts.map +1 -0
- package/dist/models.generated.js +14181 -0
- package/dist/models.generated.js.map +1 -0
- package/dist/models.js +140 -0
- package/dist/models.js.map +1 -0
- package/dist/oauth.d.ts +2 -0
- package/dist/oauth.d.ts.map +1 -0
- package/dist/oauth.js +2 -0
- package/dist/oauth.js.map +1 -0
- package/dist/providers/amazon-bedrock.d.ts +20 -0
- package/dist/providers/amazon-bedrock.d.ts.map +1 -0
- package/dist/providers/amazon-bedrock.js +651 -0
- package/dist/providers/amazon-bedrock.js.map +1 -0
- package/dist/providers/anthropic-capabilities.d.ts +65 -0
- package/dist/providers/anthropic-capabilities.d.ts.map +1 -0
- package/dist/providers/anthropic-capabilities.js +155 -0
- package/dist/providers/anthropic-capabilities.js.map +1 -0
- package/dist/providers/anthropic-discovery.d.ts +49 -0
- package/dist/providers/anthropic-discovery.d.ts.map +1 -0
- package/dist/providers/anthropic-discovery.js +218 -0
- package/dist/providers/anthropic-discovery.js.map +1 -0
- package/dist/providers/anthropic.d.ts +40 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +766 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/azure-openai-responses.d.ts +15 -0
- package/dist/providers/azure-openai-responses.d.ts.map +1 -0
- package/dist/providers/azure-openai-responses.js +176 -0
- package/dist/providers/azure-openai-responses.js.map +1 -0
- package/dist/providers/faux.d.ts +56 -0
- package/dist/providers/faux.d.ts.map +1 -0
- package/dist/providers/faux.js +367 -0
- package/dist/providers/faux.js.map +1 -0
- package/dist/providers/github-copilot-headers.d.ts +8 -0
- package/dist/providers/github-copilot-headers.d.ts.map +1 -0
- package/dist/providers/github-copilot-headers.js +29 -0
- package/dist/providers/github-copilot-headers.js.map +1 -0
- package/dist/providers/google-gemini-cli.d.ts +74 -0
- package/dist/providers/google-gemini-cli.d.ts.map +1 -0
- package/dist/providers/google-gemini-cli.js +776 -0
- package/dist/providers/google-gemini-cli.js.map +1 -0
- package/dist/providers/google-shared.d.ts +65 -0
- package/dist/providers/google-shared.d.ts.map +1 -0
- package/dist/providers/google-shared.js +312 -0
- package/dist/providers/google-shared.js.map +1 -0
- package/dist/providers/google-vertex.d.ts +15 -0
- package/dist/providers/google-vertex.d.ts.map +1 -0
- package/dist/providers/google-vertex.js +419 -0
- package/dist/providers/google-vertex.js.map +1 -0
- package/dist/providers/google.d.ts +13 -0
- package/dist/providers/google.d.ts.map +1 -0
- package/dist/providers/google.js +374 -0
- package/dist/providers/google.js.map +1 -0
- package/dist/providers/mistral.d.ts +22 -0
- package/dist/providers/mistral.d.ts.map +1 -0
- package/dist/providers/mistral.js +501 -0
- package/dist/providers/mistral.js.map +1 -0
- package/dist/providers/openai-codex-responses.d.ts +9 -0
- package/dist/providers/openai-codex-responses.d.ts.map +1 -0
- package/dist/providers/openai-codex-responses.js +741 -0
- package/dist/providers/openai-codex-responses.js.map +1 -0
- package/dist/providers/openai-completions.d.ts +15 -0
- package/dist/providers/openai-completions.d.ts.map +1 -0
- package/dist/providers/openai-completions.js +753 -0
- package/dist/providers/openai-completions.js.map +1 -0
- package/dist/providers/openai-responses-shared.d.ts +17 -0
- package/dist/providers/openai-responses-shared.d.ts.map +1 -0
- package/dist/providers/openai-responses-shared.js +470 -0
- package/dist/providers/openai-responses-shared.js.map +1 -0
- package/dist/providers/openai-responses.d.ts +13 -0
- package/dist/providers/openai-responses.d.ts.map +1 -0
- package/dist/providers/openai-responses.js +190 -0
- package/dist/providers/openai-responses.js.map +1 -0
- package/dist/providers/register-builtins.d.ts +38 -0
- package/dist/providers/register-builtins.d.ts.map +1 -0
- package/dist/providers/register-builtins.js +261 -0
- package/dist/providers/register-builtins.js.map +1 -0
- package/dist/providers/simple-options.d.ts +8 -0
- package/dist/providers/simple-options.d.ts.map +1 -0
- package/dist/providers/simple-options.js +35 -0
- package/dist/providers/simple-options.js.map +1 -0
- package/dist/providers/transform-messages.d.ts +8 -0
- package/dist/providers/transform-messages.d.ts.map +1 -0
- package/dist/providers/transform-messages.js +155 -0
- package/dist/providers/transform-messages.js.map +1 -0
- package/dist/registry/fetcher.d.ts +26 -0
- package/dist/registry/fetcher.d.ts.map +1 -0
- package/dist/registry/fetcher.js +69 -0
- package/dist/registry/fetcher.js.map +1 -0
- package/dist/registry/index.d.ts +8 -0
- package/dist/registry/index.d.ts.map +1 -0
- package/dist/registry/index.js +8 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/registry/loader.d.ts +38 -0
- package/dist/registry/loader.d.ts.map +1 -0
- package/dist/registry/loader.js +90 -0
- package/dist/registry/loader.js.map +1 -0
- package/dist/registry/merger.d.ts +21 -0
- package/dist/registry/merger.d.ts.map +1 -0
- package/dist/registry/merger.js +90 -0
- package/dist/registry/merger.js.map +1 -0
- package/dist/registry/schema.d.ts +130 -0
- package/dist/registry/schema.d.ts.map +1 -0
- package/dist/registry/schema.js +103 -0
- package/dist/registry/schema.js.map +1 -0
- package/dist/stream.d.ts +8 -0
- package/dist/stream.d.ts.map +1 -0
- package/dist/stream.js +27 -0
- package/dist/stream.js.map +1 -0
- package/dist/types.d.ts +296 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/event-stream.d.ts +21 -0
- package/dist/utils/event-stream.d.ts.map +1 -0
- package/dist/utils/event-stream.js +81 -0
- package/dist/utils/event-stream.js.map +1 -0
- package/dist/utils/hash.d.ts +3 -0
- package/dist/utils/hash.d.ts.map +1 -0
- package/dist/utils/hash.js +14 -0
- package/dist/utils/hash.js.map +1 -0
- package/dist/utils/json-parse.d.ts +9 -0
- package/dist/utils/json-parse.d.ts.map +1 -0
- package/dist/utils/json-parse.js +29 -0
- package/dist/utils/json-parse.js.map +1 -0
- package/dist/utils/oauth/anthropic.d.ts +25 -0
- package/dist/utils/oauth/anthropic.d.ts.map +1 -0
- package/dist/utils/oauth/anthropic.js +336 -0
- package/dist/utils/oauth/anthropic.js.map +1 -0
- package/dist/utils/oauth/github-copilot.d.ts +30 -0
- package/dist/utils/oauth/github-copilot.d.ts.map +1 -0
- package/dist/utils/oauth/github-copilot.js +293 -0
- package/dist/utils/oauth/github-copilot.js.map +1 -0
- package/dist/utils/oauth/google-antigravity.d.ts +26 -0
- package/dist/utils/oauth/google-antigravity.d.ts.map +1 -0
- package/dist/utils/oauth/google-antigravity.js +376 -0
- package/dist/utils/oauth/google-antigravity.js.map +1 -0
- package/dist/utils/oauth/google-gemini-cli.d.ts +26 -0
- package/dist/utils/oauth/google-gemini-cli.d.ts.map +1 -0
- package/dist/utils/oauth/google-gemini-cli.js +482 -0
- package/dist/utils/oauth/google-gemini-cli.js.map +1 -0
- package/dist/utils/oauth/index.d.ts +61 -0
- package/dist/utils/oauth/index.d.ts.map +1 -0
- package/dist/utils/oauth/index.js +131 -0
- package/dist/utils/oauth/index.js.map +1 -0
- package/dist/utils/oauth/oauth-page.d.ts +3 -0
- package/dist/utils/oauth/oauth-page.d.ts.map +1 -0
- package/dist/utils/oauth/oauth-page.js +105 -0
- package/dist/utils/oauth/oauth-page.js.map +1 -0
- package/dist/utils/oauth/openai-codex.d.ts +34 -0
- package/dist/utils/oauth/openai-codex.d.ts.map +1 -0
- package/dist/utils/oauth/openai-codex.js +374 -0
- package/dist/utils/oauth/openai-codex.js.map +1 -0
- package/dist/utils/oauth/pkce.d.ts +13 -0
- package/dist/utils/oauth/pkce.d.ts.map +1 -0
- package/dist/utils/oauth/pkce.js +31 -0
- package/dist/utils/oauth/pkce.js.map +1 -0
- package/dist/utils/oauth/types.d.ts +49 -0
- package/dist/utils/oauth/types.d.ts.map +1 -0
- package/dist/utils/oauth/types.js +2 -0
- package/dist/utils/oauth/types.js.map +1 -0
- package/dist/utils/overflow.d.ts +53 -0
- package/dist/utils/overflow.d.ts.map +1 -0
- package/dist/utils/overflow.js +132 -0
- package/dist/utils/overflow.js.map +1 -0
- package/dist/utils/sanitize-unicode.d.ts +22 -0
- package/dist/utils/sanitize-unicode.d.ts.map +1 -0
- package/dist/utils/sanitize-unicode.js +26 -0
- package/dist/utils/sanitize-unicode.js.map +1 -0
- package/dist/utils/typebox-helpers.d.ts +17 -0
- package/dist/utils/typebox-helpers.d.ts.map +1 -0
- package/dist/utils/typebox-helpers.js +21 -0
- package/dist/utils/typebox-helpers.js.map +1 -0
- package/dist/utils/validation.d.ts +18 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +80 -0
- package/dist/utils/validation.js.map +1 -0
- package/package.json +129 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// T-050, T-051, T-052: cache-aware middle-drop trimming with N-recent-turn floor
|
|
2
|
+
// + deterministic stable summary block.
|
|
3
|
+
/** Deterministic summary bytes derived from dropped turns. */
|
|
4
|
+
export function summarize(dropped) {
|
|
5
|
+
const indices = dropped.map((t) => t.index).join(",");
|
|
6
|
+
const totalBytes = dropped.reduce((acc, t) => acc + t.bytes.length, 0);
|
|
7
|
+
return `<compact ${dropped.length} turns [${indices}], ${totalBytes} bytes>`;
|
|
8
|
+
}
|
|
9
|
+
/** Middle-drop: keep [0..pivot] as a placeholder floor and [tail - recentFloor..tail];
|
|
10
|
+
* drop the middle span and replace with a stable summary. */
|
|
11
|
+
export function trimMiddle(turns, config) {
|
|
12
|
+
if (turns.length <= config.recentFloor + 1) {
|
|
13
|
+
return {
|
|
14
|
+
kept: turns,
|
|
15
|
+
summary: { index: -1, bytes: "" },
|
|
16
|
+
droppedCount: 0,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
const tail = turns.slice(turns.length - config.recentFloor);
|
|
20
|
+
const middle = turns.slice(0, turns.length - config.recentFloor);
|
|
21
|
+
const summary = {
|
|
22
|
+
index: middle[middle.length - 1].index + 0.5,
|
|
23
|
+
bytes: summarize(middle),
|
|
24
|
+
};
|
|
25
|
+
return {
|
|
26
|
+
kept: [summary, ...tail],
|
|
27
|
+
summary,
|
|
28
|
+
droppedCount: middle.length,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export class KeepaliveScheduler {
|
|
32
|
+
lastPingMs = 0;
|
|
33
|
+
lastActivityMs = 0;
|
|
34
|
+
tick(now, config) {
|
|
35
|
+
if (!config.enabled || config.retention === "none")
|
|
36
|
+
return "skip";
|
|
37
|
+
if (now - this.lastActivityMs > config.intervalMs * 2)
|
|
38
|
+
return "shutoff";
|
|
39
|
+
if (now - this.lastPingMs >= config.intervalMs) {
|
|
40
|
+
this.lastPingMs = now;
|
|
41
|
+
return "ping";
|
|
42
|
+
}
|
|
43
|
+
return "skip";
|
|
44
|
+
}
|
|
45
|
+
markActivity(now) {
|
|
46
|
+
this.lastActivityMs = now;
|
|
47
|
+
this.lastPingMs = now;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=compaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compaction.js","sourceRoot":"","sources":["../../src/cache/compaction.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,wCAAwC;AAkBxC,8DAA8D;AAC9D,MAAM,UAAU,SAAS,CAAC,OAAe,EAAU;IAClD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACtD,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACvE,OAAO,YAAY,OAAO,CAAC,MAAM,WAAW,OAAO,MAAM,UAAU,SAAS,CAAC;AAAA,CAC7E;AAED;8DAC8D;AAC9D,MAAM,UAAU,UAAU,CAAC,KAAa,EAAE,MAAkB,EAAc;IACzE,IAAI,KAAK,CAAC,MAAM,IAAI,MAAM,CAAC,WAAW,GAAG,CAAC,EAAE,CAAC;QAC5C,OAAO;YACN,IAAI,EAAE,KAAK;YACX,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE;YACjC,YAAY,EAAE,CAAC;SACf,CAAC;IACH,CAAC;IACD,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;IAC5D,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;IACjE,MAAM,OAAO,GAAS;QACrB,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,GAAG;QAC5C,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC;KACxB,CAAC;IACF,OAAO;QACN,IAAI,EAAE,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC;QACxB,OAAO;QACP,YAAY,EAAE,MAAM,CAAC,MAAM;KAC3B,CAAC;AAAA,CACF;AASD,MAAM,OAAO,kBAAkB;IACtB,UAAU,GAAG,CAAC,CAAC;IACf,cAAc,GAAG,CAAC,CAAC;IAE3B,IAAI,CAAC,GAAW,EAAE,MAAuB,EAA+B;QACvE,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,SAAS,KAAK,MAAM;YAAE,OAAO,MAAM,CAAC;QAClE,IAAI,GAAG,GAAG,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC,UAAU,GAAG,CAAC;YAAE,OAAO,SAAS,CAAC;QACxE,IAAI,GAAG,GAAG,IAAI,CAAC,UAAU,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;YAChD,IAAI,CAAC,UAAU,GAAG,GAAG,CAAC;YACtB,OAAO,MAAM,CAAC;QACf,CAAC;QACD,OAAO,MAAM,CAAC;IAAA,CACd;IAED,YAAY,CAAC,GAAW,EAAQ;QAC/B,IAAI,CAAC,cAAc,GAAG,GAAG,CAAC;QAC1B,IAAI,CAAC,UAAU,GAAG,GAAG,CAAC;IAAA,CACtB;CACD","sourcesContent":["// T-050, T-051, T-052: cache-aware middle-drop trimming with N-recent-turn floor\n// + deterministic stable summary block.\n\nexport interface Turn {\n\tindex: number;\n\tbytes: string;\n}\n\nexport interface TrimConfig {\n\t/** Keep the most recent N turns untouched. */\n\trecentFloor: number;\n}\n\nexport interface TrimResult {\n\tkept: Turn[];\n\tsummary: Turn;\n\tdroppedCount: number;\n}\n\n/** Deterministic summary bytes derived from dropped turns. */\nexport function summarize(dropped: Turn[]): string {\n\tconst indices = dropped.map((t) => t.index).join(\",\");\n\tconst totalBytes = dropped.reduce((acc, t) => acc + t.bytes.length, 0);\n\treturn `<compact ${dropped.length} turns [${indices}], ${totalBytes} bytes>`;\n}\n\n/** Middle-drop: keep [0..pivot] as a placeholder floor and [tail - recentFloor..tail];\n * drop the middle span and replace with a stable summary. */\nexport function trimMiddle(turns: Turn[], config: TrimConfig): TrimResult {\n\tif (turns.length <= config.recentFloor + 1) {\n\t\treturn {\n\t\t\tkept: turns,\n\t\t\tsummary: { index: -1, bytes: \"\" },\n\t\t\tdroppedCount: 0,\n\t\t};\n\t}\n\tconst tail = turns.slice(turns.length - config.recentFloor);\n\tconst middle = turns.slice(0, turns.length - config.recentFloor);\n\tconst summary: Turn = {\n\t\tindex: middle[middle.length - 1].index + 0.5,\n\t\tbytes: summarize(middle),\n\t};\n\treturn {\n\t\tkept: [summary, ...tail],\n\t\tsummary,\n\t\tdroppedCount: middle.length,\n\t};\n}\n\n// T-053, T-054: opt-in keepalive pings with idle shutoff.\nexport interface KeepaliveConfig {\n\tintervalMs: number;\n\tretention: \"long\" | \"short\" | \"none\";\n\tenabled: boolean;\n}\n\nexport class KeepaliveScheduler {\n\tprivate lastPingMs = 0;\n\tprivate lastActivityMs = 0;\n\n\ttick(now: number, config: KeepaliveConfig): \"ping\" | \"shutoff\" | \"skip\" {\n\t\tif (!config.enabled || config.retention === \"none\") return \"skip\";\n\t\tif (now - this.lastActivityMs > config.intervalMs * 2) return \"shutoff\";\n\t\tif (now - this.lastPingMs >= config.intervalMs) {\n\t\t\tthis.lastPingMs = now;\n\t\t\treturn \"ping\";\n\t\t}\n\t\treturn \"skip\";\n\t}\n\n\tmarkActivity(now: number): void {\n\t\tthis.lastActivityMs = now;\n\t\tthis.lastPingMs = now;\n\t}\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cache/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC","sourcesContent":["export * from \"./compaction.js\";\nexport * from \"./layers.js\";\nexport * from \"./policy.js\";\nexport * from \"./tool-serializer.js\";\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cache/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC","sourcesContent":["export * from \"./compaction.js\";\nexport * from \"./layers.js\";\nexport * from \"./policy.js\";\nexport * from \"./tool-serializer.js\";\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type CacheLayer, type CachePolicy, type LayeredPayload } from "./policy.js";
|
|
2
|
+
import { type ToolSchema } from "./tool-serializer.js";
|
|
3
|
+
export interface AssembleInput {
|
|
4
|
+
tools: ToolSchema[];
|
|
5
|
+
system: string;
|
|
6
|
+
project?: string;
|
|
7
|
+
messages: string[];
|
|
8
|
+
policy: CachePolicy;
|
|
9
|
+
}
|
|
10
|
+
/** Produce the canonical 4-layer payload. Non-breakpoint providers
|
|
11
|
+
* still receive the same 4 blocks (just without breakpoint flags). */
|
|
12
|
+
export declare function assembleLayered(input: AssembleInput): LayeredPayload;
|
|
13
|
+
export declare function layerBytes(payload: LayeredPayload, layer: CacheLayer): string;
|
|
14
|
+
export declare function layerHash(payload: LayeredPayload, layer: CacheLayer): string;
|
|
15
|
+
export declare function layersInOrder(payload: LayeredPayload): CacheLayer[];
|
|
16
|
+
export declare function canonicalOrder(): readonly CacheLayer[];
|
|
17
|
+
//# sourceMappingURL=layers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layers.d.ts","sourceRoot":"","sources":["../../src/cache/layers.ts"],"names":[],"mappings":"AAEA,OAAO,EAEN,KAAK,UAAU,EACf,KAAK,WAAW,EAEhB,KAAK,cAAc,EAEnB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAwB,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAE7E,MAAM,WAAW,aAAa;IAC7B,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,EAAE,WAAW,CAAC;CACpB;AAED;uEACuE;AACvE,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,GAAG,cAAc,CA2BpE;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,UAAU,GAAG,MAAM,CAG7E;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,UAAU,GAAG,MAAM,CAE5E;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,UAAU,EAAE,CAEnE;AAED,wBAAgB,cAAc,IAAI,SAAS,UAAU,EAAE,CAEtD","sourcesContent":["// T-002: Assemble tools/system/project/messages layers in strict order.\nimport { createHash } from \"node:crypto\";\nimport {\n\tCACHE_LAYER_ORDER,\n\ttype CacheLayer,\n\ttype CachePolicy,\n\ttype LayerBlock,\n\ttype LayeredPayload,\n\tvalidateLayers,\n} from \"./policy.js\";\nimport { serializeToolSchemas, type ToolSchema } from \"./tool-serializer.js\";\n\nexport interface AssembleInput {\n\ttools: ToolSchema[];\n\tsystem: string;\n\tproject?: string;\n\tmessages: string[];\n\tpolicy: CachePolicy;\n}\n\n/** Produce the canonical 4-layer payload. Non-breakpoint providers\n * still receive the same 4 blocks (just without breakpoint flags). */\nexport function assembleLayered(input: AssembleInput): LayeredPayload {\n\tconst layers: LayerBlock[] = [];\n\tlayers.push({\n\t\tlayer: \"tools\",\n\t\tbytes: serializeToolSchemas(input.tools),\n\t\tbreakpoint: input.policy.supportsBreakpoints,\n\t});\n\tlayers.push({\n\t\tlayer: \"system\",\n\t\tbytes: input.system,\n\t\tbreakpoint: input.policy.supportsBreakpoints,\n\t});\n\tif (input.project !== undefined) {\n\t\tlayers.push({\n\t\t\tlayer: \"project\",\n\t\t\tbytes: input.project,\n\t\t\tbreakpoint: input.policy.supportsBreakpoints,\n\t\t});\n\t}\n\tlayers.push({\n\t\tlayer: \"messages\",\n\t\tbytes: JSON.stringify(input.messages),\n\t\t// messages layer: one breakpoint at the tail on breakpoint providers\n\t\tbreakpoint: input.policy.supportsBreakpoints,\n\t});\n\tvalidateLayers(layers);\n\treturn { layers, policy: input.policy };\n}\n\nexport function layerBytes(payload: LayeredPayload, layer: CacheLayer): string {\n\tconst block = payload.layers.find((l) => l.layer === layer);\n\treturn block ? block.bytes : \"\";\n}\n\nexport function layerHash(payload: LayeredPayload, layer: CacheLayer): string {\n\treturn createHash(\"sha256\").update(layerBytes(payload, layer)).digest(\"hex\");\n}\n\nexport function layersInOrder(payload: LayeredPayload): CacheLayer[] {\n\treturn payload.layers.map((l) => l.layer);\n}\n\nexport function canonicalOrder(): readonly CacheLayer[] {\n\treturn CACHE_LAYER_ORDER;\n}\n"]}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// T-002: Assemble tools/system/project/messages layers in strict order.
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { CACHE_LAYER_ORDER, validateLayers, } from "./policy.js";
|
|
4
|
+
import { serializeToolSchemas } from "./tool-serializer.js";
|
|
5
|
+
/** Produce the canonical 4-layer payload. Non-breakpoint providers
|
|
6
|
+
* still receive the same 4 blocks (just without breakpoint flags). */
|
|
7
|
+
export function assembleLayered(input) {
|
|
8
|
+
const layers = [];
|
|
9
|
+
layers.push({
|
|
10
|
+
layer: "tools",
|
|
11
|
+
bytes: serializeToolSchemas(input.tools),
|
|
12
|
+
breakpoint: input.policy.supportsBreakpoints,
|
|
13
|
+
});
|
|
14
|
+
layers.push({
|
|
15
|
+
layer: "system",
|
|
16
|
+
bytes: input.system,
|
|
17
|
+
breakpoint: input.policy.supportsBreakpoints,
|
|
18
|
+
});
|
|
19
|
+
if (input.project !== undefined) {
|
|
20
|
+
layers.push({
|
|
21
|
+
layer: "project",
|
|
22
|
+
bytes: input.project,
|
|
23
|
+
breakpoint: input.policy.supportsBreakpoints,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
layers.push({
|
|
27
|
+
layer: "messages",
|
|
28
|
+
bytes: JSON.stringify(input.messages),
|
|
29
|
+
// messages layer: one breakpoint at the tail on breakpoint providers
|
|
30
|
+
breakpoint: input.policy.supportsBreakpoints,
|
|
31
|
+
});
|
|
32
|
+
validateLayers(layers);
|
|
33
|
+
return { layers, policy: input.policy };
|
|
34
|
+
}
|
|
35
|
+
export function layerBytes(payload, layer) {
|
|
36
|
+
const block = payload.layers.find((l) => l.layer === layer);
|
|
37
|
+
return block ? block.bytes : "";
|
|
38
|
+
}
|
|
39
|
+
export function layerHash(payload, layer) {
|
|
40
|
+
return createHash("sha256").update(layerBytes(payload, layer)).digest("hex");
|
|
41
|
+
}
|
|
42
|
+
export function layersInOrder(payload) {
|
|
43
|
+
return payload.layers.map((l) => l.layer);
|
|
44
|
+
}
|
|
45
|
+
export function canonicalOrder() {
|
|
46
|
+
return CACHE_LAYER_ORDER;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=layers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layers.js","sourceRoot":"","sources":["../../src/cache/layers.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EACN,iBAAiB,EAKjB,cAAc,GACd,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,oBAAoB,EAAmB,MAAM,sBAAsB,CAAC;AAU7E;uEACuE;AACvE,MAAM,UAAU,eAAe,CAAC,KAAoB,EAAkB;IACrE,MAAM,MAAM,GAAiB,EAAE,CAAC;IAChC,MAAM,CAAC,IAAI,CAAC;QACX,KAAK,EAAE,OAAO;QACd,KAAK,EAAE,oBAAoB,CAAC,KAAK,CAAC,KAAK,CAAC;QACxC,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,mBAAmB;KAC5C,CAAC,CAAC;IACH,MAAM,CAAC,IAAI,CAAC;QACX,KAAK,EAAE,QAAQ;QACf,KAAK,EAAE,KAAK,CAAC,MAAM;QACnB,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,mBAAmB;KAC5C,CAAC,CAAC;IACH,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QACjC,MAAM,CAAC,IAAI,CAAC;YACX,KAAK,EAAE,SAAS;YAChB,KAAK,EAAE,KAAK,CAAC,OAAO;YACpB,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,mBAAmB;SAC5C,CAAC,CAAC;IACJ,CAAC;IACD,MAAM,CAAC,IAAI,CAAC;QACX,KAAK,EAAE,UAAU;QACjB,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC;QACrC,qEAAqE;QACrE,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,mBAAmB;KAC5C,CAAC,CAAC;IACH,cAAc,CAAC,MAAM,CAAC,CAAC;IACvB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;AAAA,CACxC;AAED,MAAM,UAAU,UAAU,CAAC,OAAuB,EAAE,KAAiB,EAAU;IAC9E,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC;IAC5D,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AAAA,CAChC;AAED,MAAM,UAAU,SAAS,CAAC,OAAuB,EAAE,KAAiB,EAAU;IAC7E,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAAA,CAC7E;AAED,MAAM,UAAU,aAAa,CAAC,OAAuB,EAAgB;IACpE,OAAO,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AAAA,CAC1C;AAED,MAAM,UAAU,cAAc,GAA0B;IACvD,OAAO,iBAAiB,CAAC;AAAA,CACzB","sourcesContent":["// T-002: Assemble tools/system/project/messages layers in strict order.\nimport { createHash } from \"node:crypto\";\nimport {\n\tCACHE_LAYER_ORDER,\n\ttype CacheLayer,\n\ttype CachePolicy,\n\ttype LayerBlock,\n\ttype LayeredPayload,\n\tvalidateLayers,\n} from \"./policy.js\";\nimport { serializeToolSchemas, type ToolSchema } from \"./tool-serializer.js\";\n\nexport interface AssembleInput {\n\ttools: ToolSchema[];\n\tsystem: string;\n\tproject?: string;\n\tmessages: string[];\n\tpolicy: CachePolicy;\n}\n\n/** Produce the canonical 4-layer payload. Non-breakpoint providers\n * still receive the same 4 blocks (just without breakpoint flags). */\nexport function assembleLayered(input: AssembleInput): LayeredPayload {\n\tconst layers: LayerBlock[] = [];\n\tlayers.push({\n\t\tlayer: \"tools\",\n\t\tbytes: serializeToolSchemas(input.tools),\n\t\tbreakpoint: input.policy.supportsBreakpoints,\n\t});\n\tlayers.push({\n\t\tlayer: \"system\",\n\t\tbytes: input.system,\n\t\tbreakpoint: input.policy.supportsBreakpoints,\n\t});\n\tif (input.project !== undefined) {\n\t\tlayers.push({\n\t\t\tlayer: \"project\",\n\t\t\tbytes: input.project,\n\t\t\tbreakpoint: input.policy.supportsBreakpoints,\n\t\t});\n\t}\n\tlayers.push({\n\t\tlayer: \"messages\",\n\t\tbytes: JSON.stringify(input.messages),\n\t\t// messages layer: one breakpoint at the tail on breakpoint providers\n\t\tbreakpoint: input.policy.supportsBreakpoints,\n\t});\n\tvalidateLayers(layers);\n\treturn { layers, policy: input.policy };\n}\n\nexport function layerBytes(payload: LayeredPayload, layer: CacheLayer): string {\n\tconst block = payload.layers.find((l) => l.layer === layer);\n\treturn block ? block.bytes : \"\";\n}\n\nexport function layerHash(payload: LayeredPayload, layer: CacheLayer): string {\n\treturn createHash(\"sha256\").update(layerBytes(payload, layer)).digest(\"hex\");\n}\n\nexport function layersInOrder(payload: LayeredPayload): CacheLayer[] {\n\treturn payload.layers.map((l) => l.layer);\n}\n\nexport function canonicalOrder(): readonly CacheLayer[] {\n\treturn CACHE_LAYER_ORDER;\n}\n"]}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Usage } from "../types.js";
|
|
2
|
+
export type CacheLayer = "tools" | "system" | "project" | "messages";
|
|
3
|
+
export declare const CACHE_LAYER_ORDER: readonly CacheLayer[];
|
|
4
|
+
export type CacheRetention = "long" | "short" | "none";
|
|
5
|
+
export interface LayerBlock {
|
|
6
|
+
layer: CacheLayer;
|
|
7
|
+
/** Canonical UTF-8 bytes that form the layer's stable prefix. */
|
|
8
|
+
bytes: string;
|
|
9
|
+
/** At most one breakpoint per layer on breakpoint-capable providers. */
|
|
10
|
+
breakpoint?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface CachePolicy {
|
|
13
|
+
retention: CacheRetention;
|
|
14
|
+
/** If true, the provider supports explicit breakpoints (Anthropic-style). */
|
|
15
|
+
supportsBreakpoints: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface LayeredPayload {
|
|
18
|
+
layers: LayerBlock[];
|
|
19
|
+
policy: CachePolicy;
|
|
20
|
+
}
|
|
21
|
+
export declare function defaultPolicy(): CachePolicy;
|
|
22
|
+
export interface CacheUsageReport {
|
|
23
|
+
cachedInputTokens: number;
|
|
24
|
+
cacheWriteTokens: number;
|
|
25
|
+
uncachedInputTokens: number;
|
|
26
|
+
}
|
|
27
|
+
export declare function totalInputTokens(u: CacheUsageReport): number;
|
|
28
|
+
export interface RetentionResolveContext {
|
|
29
|
+
roleDefault: CacheRetention;
|
|
30
|
+
/** CLI flag --cache=long|short|none overrides role default. */
|
|
31
|
+
cliFlag?: CacheRetention;
|
|
32
|
+
/** CaveKit phase override takes precedence over role default but
|
|
33
|
+
* is still overridden by an explicit CLI flag. */
|
|
34
|
+
cavekitPhaseOverride?: CacheRetention;
|
|
35
|
+
}
|
|
36
|
+
export declare function resolveRetention(ctx: RetentionResolveContext): CacheRetention;
|
|
37
|
+
/** Enforce R1: at most one breakpoint per layer, layers in canonical order. */
|
|
38
|
+
export declare function validateLayers(layers: LayerBlock[]): void;
|
|
39
|
+
export declare function usageToCacheReport(usage: Usage): CacheUsageReport;
|
|
40
|
+
//# sourceMappingURL=policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../src/cache/policy.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,GAAG,UAAU,CAAC;AAErE,eAAO,MAAM,iBAAiB,EAAE,SAAS,UAAU,EAAwD,CAAC;AAE5G,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAEvD,MAAM,WAAW,UAAU;IAC1B,KAAK,EAAE,UAAU,CAAC;IAClB,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC3B,SAAS,EAAE,cAAc,CAAC;IAC1B,6EAA6E;IAC7E,mBAAmB,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,cAAc;IAC9B,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,MAAM,EAAE,WAAW,CAAC;CACpB;AAED,wBAAgB,aAAa,IAAI,WAAW,CAE3C;AAGD,MAAM,WAAW,gBAAgB;IAChC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;CAC5B;AAED,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAE5D;AAGD,MAAM,WAAW,uBAAuB;IACvC,WAAW,EAAE,cAAc,CAAC;IAC5B,+DAA+D;IAC/D,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB;uDACmD;IACnD,oBAAoB,CAAC,EAAE,cAAc,CAAC;CACtC;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,uBAAuB,GAAG,cAAc,CAI7E;AAED,+EAA+E;AAC/E,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,IAAI,CAyBzD;AAGD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,GAAG,gBAAgB,CAMjE","sourcesContent":["// T-001: CachePolicy shape + layered breakpoint ordering contract.\n// T-003: Single breakpoint per layer, layer isolation invariant.\nimport type { Usage } from \"../types.js\";\n\nexport type CacheLayer = \"tools\" | \"system\" | \"project\" | \"messages\";\n\nexport const CACHE_LAYER_ORDER: readonly CacheLayer[] = [\"tools\", \"system\", \"project\", \"messages\"] as const;\n\nexport type CacheRetention = \"long\" | \"short\" | \"none\";\n\nexport interface LayerBlock {\n\tlayer: CacheLayer;\n\t/** Canonical UTF-8 bytes that form the layer's stable prefix. */\n\tbytes: string;\n\t/** At most one breakpoint per layer on breakpoint-capable providers. */\n\tbreakpoint?: boolean;\n}\n\nexport interface CachePolicy {\n\tretention: CacheRetention;\n\t/** If true, the provider supports explicit breakpoints (Anthropic-style). */\n\tsupportsBreakpoints: boolean;\n}\n\nexport interface LayeredPayload {\n\tlayers: LayerBlock[];\n\tpolicy: CachePolicy;\n}\n\nexport function defaultPolicy(): CachePolicy {\n\treturn { retention: \"short\", supportsBreakpoints: false };\n}\n\n// T-044, T-046: unified token-usage shape exposed by every adapter.\nexport interface CacheUsageReport {\n\tcachedInputTokens: number;\n\tcacheWriteTokens: number;\n\tuncachedInputTokens: number;\n}\n\nexport function totalInputTokens(u: CacheUsageReport): number {\n\treturn u.cachedInputTokens + u.uncachedInputTokens;\n}\n\n// T-047, T-048, T-049: per-call retention resolution.\nexport interface RetentionResolveContext {\n\troleDefault: CacheRetention;\n\t/** CLI flag --cache=long|short|none overrides role default. */\n\tcliFlag?: CacheRetention;\n\t/** CaveKit phase override takes precedence over role default but\n\t * is still overridden by an explicit CLI flag. */\n\tcavekitPhaseOverride?: CacheRetention;\n}\n\nexport function resolveRetention(ctx: RetentionResolveContext): CacheRetention {\n\tif (ctx.cliFlag) return ctx.cliFlag;\n\tif (ctx.cavekitPhaseOverride) return ctx.cavekitPhaseOverride;\n\treturn ctx.roleDefault;\n}\n\n/** Enforce R1: at most one breakpoint per layer, layers in canonical order. */\nexport function validateLayers(layers: LayerBlock[]): void {\n\tconst seen = new Set<CacheLayer>();\n\tfor (const block of layers) {\n\t\tif (seen.has(block.layer)) {\n\t\t\tthrow new Error(`cache: duplicate layer ${block.layer}`);\n\t\t}\n\t\tseen.add(block.layer);\n\t}\n\tconst order = layers.map((l) => CACHE_LAYER_ORDER.indexOf(l.layer));\n\tfor (let i = 1; i < order.length; i++) {\n\t\tif (order[i] < order[i - 1]) {\n\t\t\tthrow new Error(`cache: layers out of canonical order: ${layers.map((l) => l.layer).join(\",\")}`);\n\t\t}\n\t}\n\tconst breakpointsPerLayer = new Map<CacheLayer, number>();\n\tfor (const block of layers) {\n\t\tif (block.breakpoint) {\n\t\t\tbreakpointsPerLayer.set(block.layer, (breakpointsPerLayer.get(block.layer) ?? 0) + 1);\n\t\t}\n\t}\n\tfor (const [layer, count] of breakpointsPerLayer) {\n\t\tif (count > 1) {\n\t\t\tthrow new Error(`cache: layer ${layer} has ${count} breakpoints, max 1`);\n\t\t}\n\t}\n}\n\n// T-041/T-042: convert provider Usage to CacheUsageReport.\nexport function usageToCacheReport(usage: Usage): CacheUsageReport {\n\treturn {\n\t\tcachedInputTokens: usage.cacheRead,\n\t\tcacheWriteTokens: usage.cacheWrite,\n\t\tuncachedInputTokens: Math.max(0, usage.input),\n\t};\n}\n"]}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export const CACHE_LAYER_ORDER = ["tools", "system", "project", "messages"];
|
|
2
|
+
export function defaultPolicy() {
|
|
3
|
+
return { retention: "short", supportsBreakpoints: false };
|
|
4
|
+
}
|
|
5
|
+
export function totalInputTokens(u) {
|
|
6
|
+
return u.cachedInputTokens + u.uncachedInputTokens;
|
|
7
|
+
}
|
|
8
|
+
export function resolveRetention(ctx) {
|
|
9
|
+
if (ctx.cliFlag)
|
|
10
|
+
return ctx.cliFlag;
|
|
11
|
+
if (ctx.cavekitPhaseOverride)
|
|
12
|
+
return ctx.cavekitPhaseOverride;
|
|
13
|
+
return ctx.roleDefault;
|
|
14
|
+
}
|
|
15
|
+
/** Enforce R1: at most one breakpoint per layer, layers in canonical order. */
|
|
16
|
+
export function validateLayers(layers) {
|
|
17
|
+
const seen = new Set();
|
|
18
|
+
for (const block of layers) {
|
|
19
|
+
if (seen.has(block.layer)) {
|
|
20
|
+
throw new Error(`cache: duplicate layer ${block.layer}`);
|
|
21
|
+
}
|
|
22
|
+
seen.add(block.layer);
|
|
23
|
+
}
|
|
24
|
+
const order = layers.map((l) => CACHE_LAYER_ORDER.indexOf(l.layer));
|
|
25
|
+
for (let i = 1; i < order.length; i++) {
|
|
26
|
+
if (order[i] < order[i - 1]) {
|
|
27
|
+
throw new Error(`cache: layers out of canonical order: ${layers.map((l) => l.layer).join(",")}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const breakpointsPerLayer = new Map();
|
|
31
|
+
for (const block of layers) {
|
|
32
|
+
if (block.breakpoint) {
|
|
33
|
+
breakpointsPerLayer.set(block.layer, (breakpointsPerLayer.get(block.layer) ?? 0) + 1);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
for (const [layer, count] of breakpointsPerLayer) {
|
|
37
|
+
if (count > 1) {
|
|
38
|
+
throw new Error(`cache: layer ${layer} has ${count} breakpoints, max 1`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// T-041/T-042: convert provider Usage to CacheUsageReport.
|
|
43
|
+
export function usageToCacheReport(usage) {
|
|
44
|
+
return {
|
|
45
|
+
cachedInputTokens: usage.cacheRead,
|
|
46
|
+
cacheWriteTokens: usage.cacheWrite,
|
|
47
|
+
uncachedInputTokens: Math.max(0, usage.input),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../../src/cache/policy.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,MAAM,iBAAiB,GAA0B,CAAC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,CAAU,CAAC;AAuB5G,MAAM,UAAU,aAAa,GAAgB;IAC5C,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,mBAAmB,EAAE,KAAK,EAAE,CAAC;AAAA,CAC1D;AASD,MAAM,UAAU,gBAAgB,CAAC,CAAmB,EAAU;IAC7D,OAAO,CAAC,CAAC,iBAAiB,GAAG,CAAC,CAAC,mBAAmB,CAAC;AAAA,CACnD;AAYD,MAAM,UAAU,gBAAgB,CAAC,GAA4B,EAAkB;IAC9E,IAAI,GAAG,CAAC,OAAO;QAAE,OAAO,GAAG,CAAC,OAAO,CAAC;IACpC,IAAI,GAAG,CAAC,oBAAoB;QAAE,OAAO,GAAG,CAAC,oBAAoB,CAAC;IAC9D,OAAO,GAAG,CAAC,WAAW,CAAC;AAAA,CACvB;AAED,+EAA+E;AAC/E,MAAM,UAAU,cAAc,CAAC,MAAoB,EAAQ;IAC1D,MAAM,IAAI,GAAG,IAAI,GAAG,EAAc,CAAC;IACnC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC5B,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,0BAA0B,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;QAC1D,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IACpE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,IAAI,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,yCAAyC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClG,CAAC;IACF,CAAC;IACD,MAAM,mBAAmB,GAAG,IAAI,GAAG,EAAsB,CAAC;IAC1D,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;YACtB,mBAAmB,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,mBAAmB,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACvF,CAAC;IACF,CAAC;IACD,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,mBAAmB,EAAE,CAAC;QAClD,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,gBAAgB,KAAK,QAAQ,KAAK,qBAAqB,CAAC,CAAC;QAC1E,CAAC;IACF,CAAC;AAAA,CACD;AAED,2DAA2D;AAC3D,MAAM,UAAU,kBAAkB,CAAC,KAAY,EAAoB;IAClE,OAAO;QACN,iBAAiB,EAAE,KAAK,CAAC,SAAS;QAClC,gBAAgB,EAAE,KAAK,CAAC,UAAU;QAClC,mBAAmB,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC;KAC7C,CAAC;AAAA,CACF","sourcesContent":["// T-001: CachePolicy shape + layered breakpoint ordering contract.\n// T-003: Single breakpoint per layer, layer isolation invariant.\nimport type { Usage } from \"../types.js\";\n\nexport type CacheLayer = \"tools\" | \"system\" | \"project\" | \"messages\";\n\nexport const CACHE_LAYER_ORDER: readonly CacheLayer[] = [\"tools\", \"system\", \"project\", \"messages\"] as const;\n\nexport type CacheRetention = \"long\" | \"short\" | \"none\";\n\nexport interface LayerBlock {\n\tlayer: CacheLayer;\n\t/** Canonical UTF-8 bytes that form the layer's stable prefix. */\n\tbytes: string;\n\t/** At most one breakpoint per layer on breakpoint-capable providers. */\n\tbreakpoint?: boolean;\n}\n\nexport interface CachePolicy {\n\tretention: CacheRetention;\n\t/** If true, the provider supports explicit breakpoints (Anthropic-style). */\n\tsupportsBreakpoints: boolean;\n}\n\nexport interface LayeredPayload {\n\tlayers: LayerBlock[];\n\tpolicy: CachePolicy;\n}\n\nexport function defaultPolicy(): CachePolicy {\n\treturn { retention: \"short\", supportsBreakpoints: false };\n}\n\n// T-044, T-046: unified token-usage shape exposed by every adapter.\nexport interface CacheUsageReport {\n\tcachedInputTokens: number;\n\tcacheWriteTokens: number;\n\tuncachedInputTokens: number;\n}\n\nexport function totalInputTokens(u: CacheUsageReport): number {\n\treturn u.cachedInputTokens + u.uncachedInputTokens;\n}\n\n// T-047, T-048, T-049: per-call retention resolution.\nexport interface RetentionResolveContext {\n\troleDefault: CacheRetention;\n\t/** CLI flag --cache=long|short|none overrides role default. */\n\tcliFlag?: CacheRetention;\n\t/** CaveKit phase override takes precedence over role default but\n\t * is still overridden by an explicit CLI flag. */\n\tcavekitPhaseOverride?: CacheRetention;\n}\n\nexport function resolveRetention(ctx: RetentionResolveContext): CacheRetention {\n\tif (ctx.cliFlag) return ctx.cliFlag;\n\tif (ctx.cavekitPhaseOverride) return ctx.cavekitPhaseOverride;\n\treturn ctx.roleDefault;\n}\n\n/** Enforce R1: at most one breakpoint per layer, layers in canonical order. */\nexport function validateLayers(layers: LayerBlock[]): void {\n\tconst seen = new Set<CacheLayer>();\n\tfor (const block of layers) {\n\t\tif (seen.has(block.layer)) {\n\t\t\tthrow new Error(`cache: duplicate layer ${block.layer}`);\n\t\t}\n\t\tseen.add(block.layer);\n\t}\n\tconst order = layers.map((l) => CACHE_LAYER_ORDER.indexOf(l.layer));\n\tfor (let i = 1; i < order.length; i++) {\n\t\tif (order[i] < order[i - 1]) {\n\t\t\tthrow new Error(`cache: layers out of canonical order: ${layers.map((l) => l.layer).join(\",\")}`);\n\t\t}\n\t}\n\tconst breakpointsPerLayer = new Map<CacheLayer, number>();\n\tfor (const block of layers) {\n\t\tif (block.breakpoint) {\n\t\t\tbreakpointsPerLayer.set(block.layer, (breakpointsPerLayer.get(block.layer) ?? 0) + 1);\n\t\t}\n\t}\n\tfor (const [layer, count] of breakpointsPerLayer) {\n\t\tif (count > 1) {\n\t\t\tthrow new Error(`cache: layer ${layer} has ${count} breakpoints, max 1`);\n\t\t}\n\t}\n}\n\n// T-041/T-042: convert provider Usage to CacheUsageReport.\nexport function usageToCacheReport(usage: Usage): CacheUsageReport {\n\treturn {\n\t\tcachedInputTokens: usage.cacheRead,\n\t\tcacheWriteTokens: usage.cacheWrite,\n\t\tuncachedInputTokens: Math.max(0, usage.input),\n\t};\n}\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface ToolSchema {
|
|
2
|
+
name: string;
|
|
3
|
+
description?: string;
|
|
4
|
+
parameters?: unknown;
|
|
5
|
+
}
|
|
6
|
+
export declare function serializeToolSchemas(tools: ToolSchema[]): string;
|
|
7
|
+
export declare function toolSchemaHash(tools: ToolSchema[]): string;
|
|
8
|
+
//# sourceMappingURL=tool-serializer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-serializer.d.ts","sourceRoot":"","sources":["../../src/cache/tool-serializer.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,UAAU;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AAwBD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,MAAM,CAQhE;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,MAAM,CAE1D","sourcesContent":["// T-004: Deterministic alphabetically-sorted tool schema serializer.\n// T-006: Per-tool description edits isolate to tools-layer hash; strip paths/timestamps.\nimport { createHash } from \"node:crypto\";\n\nexport interface ToolSchema {\n\tname: string;\n\tdescription?: string;\n\tparameters?: unknown;\n}\n\nconst ISO_TIMESTAMP_RE = /\\b\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:?\\d{2})?\\b/g;\nconst ABSOLUTE_PATH_RE = /(?:\\/(?:Users|home|tmp|var|opt)\\/[^\\s\"'`]+)/g;\n\nfunction scrub(text: string): string {\n\treturn text.replace(ISO_TIMESTAMP_RE, \"<ts>\").replace(ABSOLUTE_PATH_RE, \"<path>\");\n}\n\nfunction sortKeysDeep(value: unknown): unknown {\n\tif (value === null || typeof value !== \"object\") {\n\t\treturn typeof value === \"string\" ? scrub(value) : value;\n\t}\n\tif (Array.isArray(value)) {\n\t\treturn value.map(sortKeysDeep);\n\t}\n\tconst obj = value as Record<string, unknown>;\n\tconst sorted: Record<string, unknown> = {};\n\tfor (const key of Object.keys(obj).sort()) {\n\t\tsorted[key] = sortKeysDeep(obj[key]);\n\t}\n\treturn sorted;\n}\n\nexport function serializeToolSchemas(tools: ToolSchema[]): string {\n\tconst sorted = [...tools].sort((a, b) => a.name.localeCompare(b.name));\n\tconst normalized = sorted.map((tool) => ({\n\t\tdescription: tool.description ? scrub(tool.description) : \"\",\n\t\tname: tool.name,\n\t\tparameters: sortKeysDeep(tool.parameters ?? {}),\n\t}));\n\treturn JSON.stringify(normalized);\n}\n\nexport function toolSchemaHash(tools: ToolSchema[]): string {\n\treturn createHash(\"sha256\").update(serializeToolSchemas(tools)).digest(\"hex\");\n}\n"]}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// T-004: Deterministic alphabetically-sorted tool schema serializer.
|
|
2
|
+
// T-006: Per-tool description edits isolate to tools-layer hash; strip paths/timestamps.
|
|
3
|
+
import { createHash } from "node:crypto";
|
|
4
|
+
const ISO_TIMESTAMP_RE = /\b\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:?\d{2})?\b/g;
|
|
5
|
+
const ABSOLUTE_PATH_RE = /(?:\/(?:Users|home|tmp|var|opt)\/[^\s"'`]+)/g;
|
|
6
|
+
function scrub(text) {
|
|
7
|
+
return text.replace(ISO_TIMESTAMP_RE, "<ts>").replace(ABSOLUTE_PATH_RE, "<path>");
|
|
8
|
+
}
|
|
9
|
+
function sortKeysDeep(value) {
|
|
10
|
+
if (value === null || typeof value !== "object") {
|
|
11
|
+
return typeof value === "string" ? scrub(value) : value;
|
|
12
|
+
}
|
|
13
|
+
if (Array.isArray(value)) {
|
|
14
|
+
return value.map(sortKeysDeep);
|
|
15
|
+
}
|
|
16
|
+
const obj = value;
|
|
17
|
+
const sorted = {};
|
|
18
|
+
for (const key of Object.keys(obj).sort()) {
|
|
19
|
+
sorted[key] = sortKeysDeep(obj[key]);
|
|
20
|
+
}
|
|
21
|
+
return sorted;
|
|
22
|
+
}
|
|
23
|
+
export function serializeToolSchemas(tools) {
|
|
24
|
+
const sorted = [...tools].sort((a, b) => a.name.localeCompare(b.name));
|
|
25
|
+
const normalized = sorted.map((tool) => ({
|
|
26
|
+
description: tool.description ? scrub(tool.description) : "",
|
|
27
|
+
name: tool.name,
|
|
28
|
+
parameters: sortKeysDeep(tool.parameters ?? {}),
|
|
29
|
+
}));
|
|
30
|
+
return JSON.stringify(normalized);
|
|
31
|
+
}
|
|
32
|
+
export function toolSchemaHash(tools) {
|
|
33
|
+
return createHash("sha256").update(serializeToolSchemas(tools)).digest("hex");
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=tool-serializer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-serializer.js","sourceRoot":"","sources":["../../src/cache/tool-serializer.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,yFAAyF;AACzF,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAQzC,MAAM,gBAAgB,GAAG,2EAA2E,CAAC;AACrG,MAAM,gBAAgB,GAAG,8CAA8C,CAAC;AAExE,SAAS,KAAK,CAAC,IAAY,EAAU;IACpC,OAAO,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,gBAAgB,EAAE,QAAQ,CAAC,CAAC;AAAA,CAClF;AAED,SAAS,YAAY,CAAC,KAAc,EAAW;IAC9C,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACjD,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACzD,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAChC,CAAC;IACD,MAAM,GAAG,GAAG,KAAgC,CAAC;IAC7C,MAAM,MAAM,GAA4B,EAAE,CAAC;IAC3C,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QAC3C,MAAM,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,MAAM,CAAC;AAAA,CACd;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAmB,EAAU;IACjE,MAAM,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACvE,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACxC,WAAW,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE;QAC5D,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,UAAU,EAAE,YAAY,CAAC,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC;KAC/C,CAAC,CAAC,CAAC;IACJ,OAAO,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;AAAA,CAClC;AAED,MAAM,UAAU,cAAc,CAAC,KAAmB,EAAU;IAC3D,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAAA,CAC9E","sourcesContent":["// T-004: Deterministic alphabetically-sorted tool schema serializer.\n// T-006: Per-tool description edits isolate to tools-layer hash; strip paths/timestamps.\nimport { createHash } from \"node:crypto\";\n\nexport interface ToolSchema {\n\tname: string;\n\tdescription?: string;\n\tparameters?: unknown;\n}\n\nconst ISO_TIMESTAMP_RE = /\\b\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:?\\d{2})?\\b/g;\nconst ABSOLUTE_PATH_RE = /(?:\\/(?:Users|home|tmp|var|opt)\\/[^\\s\"'`]+)/g;\n\nfunction scrub(text: string): string {\n\treturn text.replace(ISO_TIMESTAMP_RE, \"<ts>\").replace(ABSOLUTE_PATH_RE, \"<path>\");\n}\n\nfunction sortKeysDeep(value: unknown): unknown {\n\tif (value === null || typeof value !== \"object\") {\n\t\treturn typeof value === \"string\" ? scrub(value) : value;\n\t}\n\tif (Array.isArray(value)) {\n\t\treturn value.map(sortKeysDeep);\n\t}\n\tconst obj = value as Record<string, unknown>;\n\tconst sorted: Record<string, unknown> = {};\n\tfor (const key of Object.keys(obj).sort()) {\n\t\tsorted[key] = sortKeysDeep(obj[key]);\n\t}\n\treturn sorted;\n}\n\nexport function serializeToolSchemas(tools: ToolSchema[]): string {\n\tconst sorted = [...tools].sort((a, b) => a.name.localeCompare(b.name));\n\tconst normalized = sorted.map((tool) => ({\n\t\tdescription: tool.description ? scrub(tool.description) : \"\",\n\t\tname: tool.name,\n\t\tparameters: sortKeysDeep(tool.parameters ?? {}),\n\t}));\n\treturn JSON.stringify(normalized);\n}\n\nexport function toolSchemaHash(tools: ToolSchema[]): string {\n\treturn createHash(\"sha256\").update(serializeToolSchemas(tools)).digest(\"hex\");\n}\n"]}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"","sourcesContent":["#!/usr/bin/env node\n\nimport { createInterface } from \"node:readline\";\nimport { existsSync, readFileSync, writeFileSync } from \"fs\";\nimport { getOAuthProvider, getOAuthProviders } from \"./utils/oauth/index.js\";\nimport type { OAuthCredentials, OAuthProviderId } from \"./utils/oauth/types.js\";\n\nconst AUTH_FILE = \"auth.json\";\nconst PROVIDERS = getOAuthProviders();\n\nfunction prompt(rl: ReturnType<typeof createInterface>, question: string): Promise<string> {\n\treturn new Promise((resolve) => rl.question(question, resolve));\n}\n\nfunction loadAuth(): Record<string, { type: \"oauth\" } & OAuthCredentials> {\n\tif (!existsSync(AUTH_FILE)) return {};\n\ttry {\n\t\treturn JSON.parse(readFileSync(AUTH_FILE, \"utf-8\"));\n\t} catch {\n\t\treturn {};\n\t}\n}\n\nfunction saveAuth(auth: Record<string, { type: \"oauth\" } & OAuthCredentials>): void {\n\twriteFileSync(AUTH_FILE, JSON.stringify(auth, null, 2), \"utf-8\");\n}\n\nasync function login(providerId: OAuthProviderId): Promise<void> {\n\tconst provider = getOAuthProvider(providerId);\n\tif (!provider) {\n\t\tconsole.error(`Unknown provider: ${providerId}`);\n\t\tprocess.exit(1);\n\t}\n\n\tconst rl = createInterface({ input: process.stdin, output: process.stdout });\n\tconst promptFn = (msg: string) => prompt(rl, `${msg} `);\n\n\ttry {\n\t\tconst credentials = await provider.login({\n\t\t\tonAuth: (info) => {\n\t\t\t\tconsole.log(`\\nOpen this URL in your browser:\\n${info.url}`);\n\t\t\t\tif (info.instructions) console.log(info.instructions);\n\t\t\t\tconsole.log();\n\t\t\t},\n\t\t\tonPrompt: async (p) => {\n\t\t\t\treturn await promptFn(`${p.message}${p.placeholder ? ` (${p.placeholder})` : \"\"}:`);\n\t\t\t},\n\t\t\tonProgress: (msg) => console.log(msg),\n\t\t});\n\n\t\tconst auth = loadAuth();\n\t\tauth[providerId] = { type: \"oauth\", ...credentials };\n\t\tsaveAuth(auth);\n\n\t\tconsole.log(`\\nCredentials saved to ${AUTH_FILE}`);\n\t} finally {\n\t\trl.close();\n\t}\n}\n\nasync function main(): Promise<void> {\n\tconst args = process.argv.slice(2);\n\tconst command = args[0];\n\n\tif (!command || command === \"help\" || command === \"--help\" || command === \"-h\") {\n\t\tconst providerList = PROVIDERS.map((p) => ` ${p.id.padEnd(20)} ${p.name}`).join(\"\\n\");\n\t\tconsole.log(`Usage: npx @zhachory1/mewrite-ai <command> [provider]\n\nCommands:\n login [provider] Login to an OAuth provider\n list List available providers\n\nProviders:\n${providerList}\n\nExamples:\n npx @zhachory1/mewrite-ai login # interactive provider selection\n npx @zhachory1/mewrite-ai login anthropic # login to specific provider\n npx @zhachory1/mewrite-ai list # list providers\n`);\n\t\treturn;\n\t}\n\n\tif (command === \"list\") {\n\t\tconsole.log(\"Available OAuth providers:\\n\");\n\t\tfor (const p of PROVIDERS) {\n\t\t\tconsole.log(` ${p.id.padEnd(20)} ${p.name}`);\n\t\t}\n\t\treturn;\n\t}\n\n\tif (command === \"login\") {\n\t\tlet provider = args[1] as OAuthProviderId | undefined;\n\n\t\tif (!provider) {\n\t\t\tconst rl = createInterface({ input: process.stdin, output: process.stdout });\n\t\t\tconsole.log(\"Select a provider:\\n\");\n\t\t\tfor (let i = 0; i < PROVIDERS.length; i++) {\n\t\t\t\tconsole.log(` ${i + 1}. ${PROVIDERS[i].name}`);\n\t\t\t}\n\t\t\tconsole.log();\n\n\t\t\tconst choice = await prompt(rl, `Enter number (1-${PROVIDERS.length}): `);\n\t\t\trl.close();\n\n\t\t\tconst index = parseInt(choice, 10) - 1;\n\t\t\tif (index < 0 || index >= PROVIDERS.length) {\n\t\t\t\tconsole.error(\"Invalid selection\");\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t\tprovider = PROVIDERS[index].id;\n\t\t}\n\n\t\tif (!PROVIDERS.some((p) => p.id === provider)) {\n\t\t\tconsole.error(`Unknown provider: ${provider}`);\n\t\t\tconsole.error(`Use 'npx @zhachory1/mewrite-ai list' to see available providers`);\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tconsole.log(`Logging in to ${provider}...`);\n\t\tawait login(provider);\n\t\treturn;\n\t}\n\n\tconsole.error(`Unknown command: ${command}`);\n\tconsole.error(`Use 'npx @zhachory1/mewrite-ai --help' for usage`);\n\tprocess.exit(1);\n}\n\nmain().catch((err) => {\n\tconsole.error(\"Error:\", err.message);\n\tprocess.exit(1);\n});\n"]}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createInterface } from "node:readline";
|
|
3
|
+
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
4
|
+
import { getOAuthProvider, getOAuthProviders } from "./utils/oauth/index.js";
|
|
5
|
+
const AUTH_FILE = "auth.json";
|
|
6
|
+
const PROVIDERS = getOAuthProviders();
|
|
7
|
+
function prompt(rl, question) {
|
|
8
|
+
return new Promise((resolve) => rl.question(question, resolve));
|
|
9
|
+
}
|
|
10
|
+
function loadAuth() {
|
|
11
|
+
if (!existsSync(AUTH_FILE))
|
|
12
|
+
return {};
|
|
13
|
+
try {
|
|
14
|
+
return JSON.parse(readFileSync(AUTH_FILE, "utf-8"));
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return {};
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function saveAuth(auth) {
|
|
21
|
+
writeFileSync(AUTH_FILE, JSON.stringify(auth, null, 2), "utf-8");
|
|
22
|
+
}
|
|
23
|
+
async function login(providerId) {
|
|
24
|
+
const provider = getOAuthProvider(providerId);
|
|
25
|
+
if (!provider) {
|
|
26
|
+
console.error(`Unknown provider: ${providerId}`);
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
30
|
+
const promptFn = (msg) => prompt(rl, `${msg} `);
|
|
31
|
+
try {
|
|
32
|
+
const credentials = await provider.login({
|
|
33
|
+
onAuth: (info) => {
|
|
34
|
+
console.log(`\nOpen this URL in your browser:\n${info.url}`);
|
|
35
|
+
if (info.instructions)
|
|
36
|
+
console.log(info.instructions);
|
|
37
|
+
console.log();
|
|
38
|
+
},
|
|
39
|
+
onPrompt: async (p) => {
|
|
40
|
+
return await promptFn(`${p.message}${p.placeholder ? ` (${p.placeholder})` : ""}:`);
|
|
41
|
+
},
|
|
42
|
+
onProgress: (msg) => console.log(msg),
|
|
43
|
+
});
|
|
44
|
+
const auth = loadAuth();
|
|
45
|
+
auth[providerId] = { type: "oauth", ...credentials };
|
|
46
|
+
saveAuth(auth);
|
|
47
|
+
console.log(`\nCredentials saved to ${AUTH_FILE}`);
|
|
48
|
+
}
|
|
49
|
+
finally {
|
|
50
|
+
rl.close();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async function main() {
|
|
54
|
+
const args = process.argv.slice(2);
|
|
55
|
+
const command = args[0];
|
|
56
|
+
if (!command || command === "help" || command === "--help" || command === "-h") {
|
|
57
|
+
const providerList = PROVIDERS.map((p) => ` ${p.id.padEnd(20)} ${p.name}`).join("\n");
|
|
58
|
+
console.log(`Usage: npx @zhachory1/mewrite-ai <command> [provider]
|
|
59
|
+
|
|
60
|
+
Commands:
|
|
61
|
+
login [provider] Login to an OAuth provider
|
|
62
|
+
list List available providers
|
|
63
|
+
|
|
64
|
+
Providers:
|
|
65
|
+
${providerList}
|
|
66
|
+
|
|
67
|
+
Examples:
|
|
68
|
+
npx @zhachory1/mewrite-ai login # interactive provider selection
|
|
69
|
+
npx @zhachory1/mewrite-ai login anthropic # login to specific provider
|
|
70
|
+
npx @zhachory1/mewrite-ai list # list providers
|
|
71
|
+
`);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (command === "list") {
|
|
75
|
+
console.log("Available OAuth providers:\n");
|
|
76
|
+
for (const p of PROVIDERS) {
|
|
77
|
+
console.log(` ${p.id.padEnd(20)} ${p.name}`);
|
|
78
|
+
}
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (command === "login") {
|
|
82
|
+
let provider = args[1];
|
|
83
|
+
if (!provider) {
|
|
84
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
85
|
+
console.log("Select a provider:\n");
|
|
86
|
+
for (let i = 0; i < PROVIDERS.length; i++) {
|
|
87
|
+
console.log(` ${i + 1}. ${PROVIDERS[i].name}`);
|
|
88
|
+
}
|
|
89
|
+
console.log();
|
|
90
|
+
const choice = await prompt(rl, `Enter number (1-${PROVIDERS.length}): `);
|
|
91
|
+
rl.close();
|
|
92
|
+
const index = parseInt(choice, 10) - 1;
|
|
93
|
+
if (index < 0 || index >= PROVIDERS.length) {
|
|
94
|
+
console.error("Invalid selection");
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
provider = PROVIDERS[index].id;
|
|
98
|
+
}
|
|
99
|
+
if (!PROVIDERS.some((p) => p.id === provider)) {
|
|
100
|
+
console.error(`Unknown provider: ${provider}`);
|
|
101
|
+
console.error(`Use 'npx @zhachory1/mewrite-ai list' to see available providers`);
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
console.log(`Logging in to ${provider}...`);
|
|
105
|
+
await login(provider);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
console.error(`Unknown command: ${command}`);
|
|
109
|
+
console.error(`Use 'npx @zhachory1/mewrite-ai --help' for usage`);
|
|
110
|
+
process.exit(1);
|
|
111
|
+
}
|
|
112
|
+
main().catch((err) => {
|
|
113
|
+
console.error("Error:", err.message);
|
|
114
|
+
process.exit(1);
|
|
115
|
+
});
|
|
116
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAG7E,MAAM,SAAS,GAAG,WAAW,CAAC;AAC9B,MAAM,SAAS,GAAG,iBAAiB,EAAE,CAAC;AAEtC,SAAS,MAAM,CAAC,EAAsC,EAAE,QAAgB,EAAmB;IAC1F,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;AAAA,CAChE;AAED,SAAS,QAAQ,GAAyD;IACzE,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,EAAE,CAAC;IACtC,IAAI,CAAC;QACJ,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;IACrD,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,EAAE,CAAC;IACX,CAAC;AAAA,CACD;AAED,SAAS,QAAQ,CAAC,IAA0D,EAAQ;IACnF,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AAAA,CACjE;AAED,KAAK,UAAU,KAAK,CAAC,UAA2B,EAAiB;IAChE,MAAM,QAAQ,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAC9C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,qBAAqB,UAAU,EAAE,CAAC,CAAC;QACjD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC;IAED,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7E,MAAM,QAAQ,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,GAAG,GAAG,CAAC,CAAC;IAExD,IAAI,CAAC;QACJ,MAAM,WAAW,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC;YACxC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC;gBACjB,OAAO,CAAC,GAAG,CAAC,qCAAqC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;gBAC7D,IAAI,IAAI,CAAC,YAAY;oBAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;gBACtD,OAAO,CAAC,GAAG,EAAE,CAAC;YAAA,CACd;YACD,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;gBACtB,OAAO,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;YAAA,CACpF;YACD,UAAU,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;SACrC,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;QACxB,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,WAAW,EAAE,CAAC;QACrD,QAAQ,CAAC,IAAI,CAAC,CAAC;QAEf,OAAO,CAAC,GAAG,CAAC,0BAA0B,SAAS,EAAE,CAAC,CAAC;IACpD,CAAC;YAAS,CAAC;QACV,EAAE,CAAC,KAAK,EAAE,CAAC;IACZ,CAAC;AAAA,CACD;AAED,KAAK,UAAU,IAAI,GAAkB;IACpC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAExB,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,MAAM,IAAI,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QAChF,MAAM,YAAY,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvF,OAAO,CAAC,GAAG,CAAC;;;;;;;EAOZ,YAAY;;;;;;CAMb,CAAC,CAAC;QACD,OAAO;IACR,CAAC;IAED,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QACxB,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;QAC5C,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;YAC3B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC/C,CAAC;QACD,OAAO;IACR,CAAC;IAED,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;QACzB,IAAI,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAgC,CAAC;QAEtD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACf,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;YAC7E,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;YACpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YACjD,CAAC;YACD,OAAO,CAAC,GAAG,EAAE,CAAC;YAEd,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,EAAE,EAAE,mBAAmB,SAAS,CAAC,MAAM,KAAK,CAAC,CAAC;YAC1E,EAAE,CAAC,KAAK,EAAE,CAAC;YAEX,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;YACvC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,IAAI,SAAS,CAAC,MAAM,EAAE,CAAC;gBAC5C,OAAO,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;gBACnC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACjB,CAAC;YACD,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QAChC,CAAC;QAED,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,EAAE,CAAC;YAC/C,OAAO,CAAC,KAAK,CAAC,qBAAqB,QAAQ,EAAE,CAAC,CAAC;YAC/C,OAAO,CAAC,KAAK,CAAC,iEAAiE,CAAC,CAAC;YACjF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjB,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,iBAAiB,QAAQ,KAAK,CAAC,CAAC;QAC5C,MAAM,KAAK,CAAC,QAAQ,CAAC,CAAC;QACtB,OAAO;IACR,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAC;IAC7C,OAAO,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAC;IAClE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAAA,CAChB;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC;IACrB,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAAA,CAChB,CAAC,CAAC","sourcesContent":["#!/usr/bin/env node\n\nimport { createInterface } from \"node:readline\";\nimport { existsSync, readFileSync, writeFileSync } from \"fs\";\nimport { getOAuthProvider, getOAuthProviders } from \"./utils/oauth/index.js\";\nimport type { OAuthCredentials, OAuthProviderId } from \"./utils/oauth/types.js\";\n\nconst AUTH_FILE = \"auth.json\";\nconst PROVIDERS = getOAuthProviders();\n\nfunction prompt(rl: ReturnType<typeof createInterface>, question: string): Promise<string> {\n\treturn new Promise((resolve) => rl.question(question, resolve));\n}\n\nfunction loadAuth(): Record<string, { type: \"oauth\" } & OAuthCredentials> {\n\tif (!existsSync(AUTH_FILE)) return {};\n\ttry {\n\t\treturn JSON.parse(readFileSync(AUTH_FILE, \"utf-8\"));\n\t} catch {\n\t\treturn {};\n\t}\n}\n\nfunction saveAuth(auth: Record<string, { type: \"oauth\" } & OAuthCredentials>): void {\n\twriteFileSync(AUTH_FILE, JSON.stringify(auth, null, 2), \"utf-8\");\n}\n\nasync function login(providerId: OAuthProviderId): Promise<void> {\n\tconst provider = getOAuthProvider(providerId);\n\tif (!provider) {\n\t\tconsole.error(`Unknown provider: ${providerId}`);\n\t\tprocess.exit(1);\n\t}\n\n\tconst rl = createInterface({ input: process.stdin, output: process.stdout });\n\tconst promptFn = (msg: string) => prompt(rl, `${msg} `);\n\n\ttry {\n\t\tconst credentials = await provider.login({\n\t\t\tonAuth: (info) => {\n\t\t\t\tconsole.log(`\\nOpen this URL in your browser:\\n${info.url}`);\n\t\t\t\tif (info.instructions) console.log(info.instructions);\n\t\t\t\tconsole.log();\n\t\t\t},\n\t\t\tonPrompt: async (p) => {\n\t\t\t\treturn await promptFn(`${p.message}${p.placeholder ? ` (${p.placeholder})` : \"\"}:`);\n\t\t\t},\n\t\t\tonProgress: (msg) => console.log(msg),\n\t\t});\n\n\t\tconst auth = loadAuth();\n\t\tauth[providerId] = { type: \"oauth\", ...credentials };\n\t\tsaveAuth(auth);\n\n\t\tconsole.log(`\\nCredentials saved to ${AUTH_FILE}`);\n\t} finally {\n\t\trl.close();\n\t}\n}\n\nasync function main(): Promise<void> {\n\tconst args = process.argv.slice(2);\n\tconst command = args[0];\n\n\tif (!command || command === \"help\" || command === \"--help\" || command === \"-h\") {\n\t\tconst providerList = PROVIDERS.map((p) => ` ${p.id.padEnd(20)} ${p.name}`).join(\"\\n\");\n\t\tconsole.log(`Usage: npx @zhachory1/mewrite-ai <command> [provider]\n\nCommands:\n login [provider] Login to an OAuth provider\n list List available providers\n\nProviders:\n${providerList}\n\nExamples:\n npx @zhachory1/mewrite-ai login # interactive provider selection\n npx @zhachory1/mewrite-ai login anthropic # login to specific provider\n npx @zhachory1/mewrite-ai list # list providers\n`);\n\t\treturn;\n\t}\n\n\tif (command === \"list\") {\n\t\tconsole.log(\"Available OAuth providers:\\n\");\n\t\tfor (const p of PROVIDERS) {\n\t\t\tconsole.log(` ${p.id.padEnd(20)} ${p.name}`);\n\t\t}\n\t\treturn;\n\t}\n\n\tif (command === \"login\") {\n\t\tlet provider = args[1] as OAuthProviderId | undefined;\n\n\t\tif (!provider) {\n\t\t\tconst rl = createInterface({ input: process.stdin, output: process.stdout });\n\t\t\tconsole.log(\"Select a provider:\\n\");\n\t\t\tfor (let i = 0; i < PROVIDERS.length; i++) {\n\t\t\t\tconsole.log(` ${i + 1}. ${PROVIDERS[i].name}`);\n\t\t\t}\n\t\t\tconsole.log();\n\n\t\t\tconst choice = await prompt(rl, `Enter number (1-${PROVIDERS.length}): `);\n\t\t\trl.close();\n\n\t\t\tconst index = parseInt(choice, 10) - 1;\n\t\t\tif (index < 0 || index >= PROVIDERS.length) {\n\t\t\t\tconsole.error(\"Invalid selection\");\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t\tprovider = PROVIDERS[index].id;\n\t\t}\n\n\t\tif (!PROVIDERS.some((p) => p.id === provider)) {\n\t\t\tconsole.error(`Unknown provider: ${provider}`);\n\t\t\tconsole.error(`Use 'npx @zhachory1/mewrite-ai list' to see available providers`);\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tconsole.log(`Logging in to ${provider}...`);\n\t\tawait login(provider);\n\t\treturn;\n\t}\n\n\tconsole.error(`Unknown command: ${command}`);\n\tconsole.error(`Use 'npx @zhachory1/mewrite-ai --help' for usage`);\n\tprocess.exit(1);\n}\n\nmain().catch((err) => {\n\tconsole.error(\"Error:\", err.message);\n\tprocess.exit(1);\n});\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { KnownProvider } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Get API key for provider from known environment variables, e.g. OPENAI_API_KEY.
|
|
4
|
+
*
|
|
5
|
+
* Will not return API keys for providers that require OAuth tokens.
|
|
6
|
+
*/
|
|
7
|
+
export declare function getEnvApiKey(provider: KnownProvider): string | undefined;
|
|
8
|
+
export declare function getEnvApiKey(provider: string): string | undefined;
|
|
9
|
+
export declare const ENV_VAR_BY_PROVIDER: Record<string, string>;
|
|
10
|
+
export type ProviderAuthKind = "env" | "oauth" | "file" | "needs-region" | "missing";
|
|
11
|
+
export interface ProviderAuthStatus {
|
|
12
|
+
kind: ProviderAuthKind;
|
|
13
|
+
/** Short user-facing hint, e.g. "set XAI_API_KEY" or "/login anthropic". */
|
|
14
|
+
hint?: string;
|
|
15
|
+
/** The env var name this provider would use, if any. */
|
|
16
|
+
envVar?: string;
|
|
17
|
+
/** True when the agent can dispatch a request right now without further setup. */
|
|
18
|
+
configured: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Describe how a provider authenticates and whether the user is set up for it.
|
|
22
|
+
*
|
|
23
|
+
* The UI uses this to badge providers (`✓` / `🔑` / `✗` / `⚙`) and surface
|
|
24
|
+
* actionable hints without having to know about every provider's idiosyncrasies.
|
|
25
|
+
*/
|
|
26
|
+
export declare function getProviderAuthStatus(provider: string): ProviderAuthStatus;
|
|
27
|
+
//# sourceMappingURL=env-api-keys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env-api-keys.d.ts","sourceRoot":"","sources":["../src/env-api-keys.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAgChD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,GAAG,SAAS,CAAC;AAC1E,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;AAuEnE,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAkBtD,CAAC;AAUF,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,OAAO,GAAG,MAAM,GAAG,cAAc,GAAG,SAAS,CAAC;AAErF,MAAM,WAAW,kBAAkB;IAClC,IAAI,EAAE,gBAAgB,CAAC;IACvB,4EAA4E;IAC5E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kFAAkF;IAClF,UAAU,EAAE,OAAO,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,CAwF1E","sourcesContent":["// NEVER convert to top-level imports - breaks browser/Vite builds (web-ui)\nlet _existsSync: typeof import(\"node:fs\").existsSync | null = null;\nlet _homedir: typeof import(\"node:os\").homedir | null = null;\nlet _join: typeof import(\"node:path\").join | null = null;\n\ntype DynamicImport = (specifier: string) => Promise<unknown>;\n\nconst dynamicImport: DynamicImport = (specifier) => import(specifier);\nconst NODE_FS_SPECIFIER = \"node:\" + \"fs\";\nconst NODE_OS_SPECIFIER = \"node:\" + \"os\";\nconst NODE_PATH_SPECIFIER = \"node:\" + \"path\";\n\n// Eagerly load in Node.js/Bun environment only\nif (typeof process !== \"undefined\" && (process.versions?.node || process.versions?.bun)) {\n\tdynamicImport(NODE_FS_SPECIFIER).then((m) => {\n\t\t_existsSync = (m as typeof import(\"node:fs\")).existsSync;\n\t});\n\tdynamicImport(NODE_OS_SPECIFIER).then((m) => {\n\t\t_homedir = (m as typeof import(\"node:os\")).homedir;\n\t});\n\tdynamicImport(NODE_PATH_SPECIFIER).then((m) => {\n\t\t_join = (m as typeof import(\"node:path\")).join;\n\t});\n}\n\nimport type { KnownProvider } from \"./types.js\";\n\nlet cachedVertexAdcCredentialsExists: boolean | null = null;\n\nfunction hasVertexAdcCredentials(): boolean {\n\tif (cachedVertexAdcCredentialsExists === null) {\n\t\t// If node modules haven't loaded yet (async import race at startup),\n\t\t// return false WITHOUT caching so the next call retries once they're ready.\n\t\t// Only cache false permanently in a browser environment where fs is never available.\n\t\tif (!_existsSync || !_homedir || !_join) {\n\t\t\tconst isNode = typeof process !== \"undefined\" && (process.versions?.node || process.versions?.bun);\n\t\t\tif (!isNode) {\n\t\t\t\t// Definitively in a browser — safe to cache false permanently\n\t\t\t\tcachedVertexAdcCredentialsExists = false;\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\n\t\t// Check GOOGLE_APPLICATION_CREDENTIALS env var first (standard way)\n\t\tconst gacPath = process.env.GOOGLE_APPLICATION_CREDENTIALS;\n\t\tif (gacPath) {\n\t\t\tcachedVertexAdcCredentialsExists = _existsSync(gacPath);\n\t\t} else {\n\t\t\t// Fall back to default ADC path (lazy evaluation)\n\t\t\tcachedVertexAdcCredentialsExists = _existsSync(\n\t\t\t\t_join(_homedir(), \".config\", \"gcloud\", \"application_default_credentials.json\"),\n\t\t\t);\n\t\t}\n\t}\n\treturn cachedVertexAdcCredentialsExists;\n}\n\n/**\n * Get API key for provider from known environment variables, e.g. OPENAI_API_KEY.\n *\n * Will not return API keys for providers that require OAuth tokens.\n */\nexport function getEnvApiKey(provider: KnownProvider): string | undefined;\nexport function getEnvApiKey(provider: string): string | undefined;\nexport function getEnvApiKey(provider: any): string | undefined {\n\t// Fall back to environment variables\n\tif (provider === \"github-copilot\") {\n\t\treturn process.env.COPILOT_GITHUB_TOKEN || process.env.GH_TOKEN || process.env.GITHUB_TOKEN;\n\t}\n\n\t// ANTHROPIC_OAUTH_TOKEN takes precedence over ANTHROPIC_API_KEY\n\tif (provider === \"anthropic\") {\n\t\treturn process.env.ANTHROPIC_OAUTH_TOKEN || process.env.ANTHROPIC_API_KEY;\n\t}\n\n\t// Vertex AI supports either an explicit API key or Application Default Credentials\n\t// Auth is configured via `gcloud auth application-default login`\n\tif (provider === \"google-vertex\") {\n\t\tif (process.env.GOOGLE_CLOUD_API_KEY) {\n\t\t\treturn process.env.GOOGLE_CLOUD_API_KEY;\n\t\t}\n\n\t\tconst hasCredentials = hasVertexAdcCredentials();\n\t\tconst hasProject = !!(process.env.GOOGLE_CLOUD_PROJECT || process.env.GCLOUD_PROJECT);\n\t\tconst hasLocation = !!process.env.GOOGLE_CLOUD_LOCATION;\n\n\t\tif (hasCredentials && hasProject && hasLocation) {\n\t\t\treturn \"<authenticated>\";\n\t\t}\n\t}\n\n\tif (provider === \"amazon-bedrock\") {\n\t\t// Amazon Bedrock supports multiple credential sources:\n\t\t// 1. AWS_PROFILE - named profile from ~/.aws/credentials\n\t\t// 2. AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY - standard IAM keys\n\t\t// 3. AWS_BEARER_TOKEN_BEDROCK - Bedrock API keys (bearer token)\n\t\t// 4. AWS_CONTAINER_CREDENTIALS_RELATIVE_URI - ECS task roles\n\t\t// 5. AWS_CONTAINER_CREDENTIALS_FULL_URI - ECS task roles (full URI)\n\t\t// 6. AWS_WEB_IDENTITY_TOKEN_FILE - IRSA (IAM Roles for Service Accounts)\n\t\tif (\n\t\t\tprocess.env.AWS_PROFILE ||\n\t\t\t(process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY) ||\n\t\t\tprocess.env.AWS_BEARER_TOKEN_BEDROCK ||\n\t\t\tprocess.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI ||\n\t\t\tprocess.env.AWS_CONTAINER_CREDENTIALS_FULL_URI ||\n\t\t\tprocess.env.AWS_WEB_IDENTITY_TOKEN_FILE\n\t\t) {\n\t\t\treturn \"<authenticated>\";\n\t\t}\n\t}\n\n\tconst envMap: Record<string, string> = {\n\t\topenai: \"OPENAI_API_KEY\",\n\t\t\"azure-openai-responses\": \"AZURE_OPENAI_API_KEY\",\n\t\tgoogle: \"GEMINI_API_KEY\",\n\t\tgroq: \"GROQ_API_KEY\",\n\t\tcerebras: \"CEREBRAS_API_KEY\",\n\t\txai: \"XAI_API_KEY\",\n\t\topenrouter: \"OPENROUTER_API_KEY\",\n\t\t\"vercel-ai-gateway\": \"AI_GATEWAY_API_KEY\",\n\t\tzai: \"ZAI_API_KEY\",\n\t\tmistral: \"MISTRAL_API_KEY\",\n\t\tminimax: \"MINIMAX_API_KEY\",\n\t\t\"minimax-cn\": \"MINIMAX_CN_API_KEY\",\n\t\thuggingface: \"HF_TOKEN\",\n\t\topencode: \"OPENCODE_API_KEY\",\n\t\t\"opencode-go\": \"OPENCODE_API_KEY\",\n\t\t\"kimi-coding\": \"KIMI_API_KEY\",\n\t};\n\n\tconst envVar = envMap[provider];\n\treturn envVar ? process.env[envVar] : undefined;\n}\n\nexport const ENV_VAR_BY_PROVIDER: Record<string, string> = {\n\topenai: \"OPENAI_API_KEY\",\n\t\"azure-openai-responses\": \"AZURE_OPENAI_API_KEY\",\n\tanthropic: \"ANTHROPIC_API_KEY\",\n\tgoogle: \"GEMINI_API_KEY\",\n\tgroq: \"GROQ_API_KEY\",\n\tcerebras: \"CEREBRAS_API_KEY\",\n\txai: \"XAI_API_KEY\",\n\topenrouter: \"OPENROUTER_API_KEY\",\n\t\"vercel-ai-gateway\": \"AI_GATEWAY_API_KEY\",\n\tzai: \"ZAI_API_KEY\",\n\tmistral: \"MISTRAL_API_KEY\",\n\tminimax: \"MINIMAX_API_KEY\",\n\t\"minimax-cn\": \"MINIMAX_CN_API_KEY\",\n\thuggingface: \"HF_TOKEN\",\n\topencode: \"OPENCODE_API_KEY\",\n\t\"opencode-go\": \"OPENCODE_API_KEY\",\n\t\"kimi-coding\": \"KIMI_API_KEY\",\n};\n\nconst OAUTH_PROVIDERS = new Set([\n\t\"anthropic\",\n\t\"github-copilot\",\n\t\"google-gemini-cli\",\n\t\"google-antigravity\",\n\t\"openai-codex\",\n]);\n\nexport type ProviderAuthKind = \"env\" | \"oauth\" | \"file\" | \"needs-region\" | \"missing\";\n\nexport interface ProviderAuthStatus {\n\tkind: ProviderAuthKind;\n\t/** Short user-facing hint, e.g. \"set XAI_API_KEY\" or \"/login anthropic\". */\n\thint?: string;\n\t/** The env var name this provider would use, if any. */\n\tenvVar?: string;\n\t/** True when the agent can dispatch a request right now without further setup. */\n\tconfigured: boolean;\n}\n\n/**\n * Describe how a provider authenticates and whether the user is set up for it.\n *\n * The UI uses this to badge providers (`✓` / `🔑` / `✗` / `⚙`) and surface\n * actionable hints without having to know about every provider's idiosyncrasies.\n */\nexport function getProviderAuthStatus(provider: string): ProviderAuthStatus {\n\tif (provider === \"github-copilot\") {\n\t\tconst token = process.env.COPILOT_GITHUB_TOKEN || process.env.GH_TOKEN || process.env.GITHUB_TOKEN;\n\t\tif (token) return { kind: \"env\", configured: true, envVar: \"GITHUB_TOKEN\" };\n\t\treturn {\n\t\t\tkind: \"oauth\",\n\t\t\tconfigured: false,\n\t\t\thint: \"/login github-copilot\",\n\t\t\tenvVar: \"GITHUB_TOKEN\",\n\t\t};\n\t}\n\n\tif (provider === \"anthropic\") {\n\t\tif (process.env.ANTHROPIC_OAUTH_TOKEN) {\n\t\t\treturn { kind: \"oauth\", configured: true, envVar: \"ANTHROPIC_OAUTH_TOKEN\" };\n\t\t}\n\t\tif (process.env.ANTHROPIC_API_KEY) {\n\t\t\treturn { kind: \"env\", configured: true, envVar: \"ANTHROPIC_API_KEY\" };\n\t\t}\n\t\treturn {\n\t\t\tkind: \"missing\",\n\t\t\tconfigured: false,\n\t\t\thint: \"set ANTHROPIC_API_KEY or /login anthropic\",\n\t\t\tenvVar: \"ANTHROPIC_API_KEY\",\n\t\t};\n\t}\n\n\tif (provider === \"google-vertex\") {\n\t\tif (process.env.GOOGLE_CLOUD_API_KEY) {\n\t\t\treturn { kind: \"env\", configured: true, envVar: \"GOOGLE_CLOUD_API_KEY\" };\n\t\t}\n\t\tconst hasCredentials = hasVertexAdcCredentials();\n\t\tconst hasProject = !!(process.env.GOOGLE_CLOUD_PROJECT || process.env.GCLOUD_PROJECT);\n\t\tconst hasLocation = !!process.env.GOOGLE_CLOUD_LOCATION;\n\t\tif (hasCredentials && hasProject && hasLocation) {\n\t\t\treturn { kind: \"file\", configured: true };\n\t\t}\n\t\treturn {\n\t\t\tkind: \"file\",\n\t\t\tconfigured: false,\n\t\t\thint: \"run `gcloud auth application-default login` and set GOOGLE_CLOUD_PROJECT/LOCATION\",\n\t\t};\n\t}\n\n\tif (provider === \"amazon-bedrock\") {\n\t\tconst hasCreds =\n\t\t\tprocess.env.AWS_PROFILE ||\n\t\t\t(process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY) ||\n\t\t\tprocess.env.AWS_BEARER_TOKEN_BEDROCK ||\n\t\t\tprocess.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI ||\n\t\t\tprocess.env.AWS_CONTAINER_CREDENTIALS_FULL_URI ||\n\t\t\tprocess.env.AWS_WEB_IDENTITY_TOKEN_FILE;\n\t\tif (!hasCreds) {\n\t\t\treturn {\n\t\t\t\tkind: \"missing\",\n\t\t\t\tconfigured: false,\n\t\t\t\thint: \"set AWS_PROFILE or AWS_ACCESS_KEY_ID/SECRET\",\n\t\t\t};\n\t\t}\n\t\t// Region is required for Bedrock. AWS SDK looks at AWS_REGION/AWS_DEFAULT_REGION\n\t\t// or the profile's `region`. We don't read the profile here; the env signal is\n\t\t// the cheap reliable check.\n\t\tif (!(process.env.AWS_REGION || process.env.AWS_DEFAULT_REGION)) {\n\t\t\treturn {\n\t\t\t\tkind: \"needs-region\",\n\t\t\t\tconfigured: false,\n\t\t\t\thint: \"set AWS_REGION (or configure profile region)\",\n\t\t\t};\n\t\t}\n\t\treturn { kind: \"file\", configured: true };\n\t}\n\n\tif (OAUTH_PROVIDERS.has(provider)) {\n\t\treturn {\n\t\t\tkind: \"oauth\",\n\t\t\tconfigured: false,\n\t\t\thint: `/login ${provider}`,\n\t\t};\n\t}\n\n\tconst envVar = ENV_VAR_BY_PROVIDER[provider];\n\tif (envVar) {\n\t\tconst value = process.env[envVar];\n\t\tif (value) return { kind: \"env\", configured: true, envVar };\n\t\treturn { kind: \"missing\", configured: false, hint: `set ${envVar}`, envVar };\n\t}\n\n\treturn { kind: \"missing\", configured: false, hint: \"no known auth source\" };\n}\n"]}
|