@code-yeongyu/senpi 2026.8.27 → 2026.8.28

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.
Files changed (103) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/core/credential-accounts.d.ts +31 -0
  3. package/dist/core/credential-accounts.d.ts.map +1 -0
  4. package/dist/core/credential-accounts.js +125 -0
  5. package/dist/core/credential-accounts.js.map +1 -0
  6. package/dist/core/extensions/builtin/account/index.d.ts +9 -0
  7. package/dist/core/extensions/builtin/account/index.d.ts.map +1 -0
  8. package/dist/core/extensions/builtin/account/index.js +69 -0
  9. package/dist/core/extensions/builtin/account/index.js.map +1 -0
  10. package/dist/core/extensions/builtin/imagegen/index.d.ts.map +1 -1
  11. package/dist/core/extensions/builtin/imagegen/index.js +10 -3
  12. package/dist/core/extensions/builtin/imagegen/index.js.map +1 -1
  13. package/dist/core/extensions/builtin/index.d.ts.map +1 -1
  14. package/dist/core/extensions/builtin/index.js +4 -0
  15. package/dist/core/extensions/builtin/index.js.map +1 -1
  16. package/dist/main.d.ts.map +1 -1
  17. package/dist/main.js +12 -1
  18. package/dist/main.js.map +1 -1
  19. package/dist/modes/app-server/server/account.d.ts.map +1 -1
  20. package/dist/modes/app-server/server/account.js +5 -5
  21. package/dist/modes/app-server/server/account.js.map +1 -1
  22. package/dist/modes/interactive/components/footer.d.ts +11 -3
  23. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  24. package/dist/modes/interactive/components/footer.js +31 -1
  25. package/dist/modes/interactive/components/footer.js.map +1 -1
  26. package/dist/modes/interactive/grok/chrome.d.ts +4 -4
  27. package/dist/modes/interactive/grok/chrome.d.ts.map +1 -1
  28. package/dist/modes/interactive/grok/chrome.js.map +1 -1
  29. package/dist/modes/interactive/grok/footer.d.ts +3 -3
  30. package/dist/modes/interactive/grok/footer.d.ts.map +1 -1
  31. package/dist/modes/interactive/grok/footer.js.map +1 -1
  32. package/dist/modes/interactive/interactive-host-runtime.d.ts +16 -1
  33. package/dist/modes/interactive/interactive-host-runtime.d.ts.map +1 -1
  34. package/dist/modes/interactive/interactive-host-runtime.js +36 -9
  35. package/dist/modes/interactive/interactive-host-runtime.js.map +1 -1
  36. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  37. package/dist/modes/interactive/interactive-mode.js +19 -13
  38. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  39. package/dist/modes/rpc/connection-handler.d.ts.map +1 -1
  40. package/dist/modes/rpc/connection-handler.js +12 -5
  41. package/dist/modes/rpc/connection-handler.js.map +1 -1
  42. package/dist/modes/rpc/rpc-client.d.ts +16 -3
  43. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  44. package/dist/modes/rpc/rpc-client.js +43 -5
  45. package/dist/modes/rpc/rpc-client.js.map +1 -1
  46. package/dist/modes/rpc/rpc-types.d.ts +4 -1
  47. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  48. package/dist/modes/rpc/rpc-types.js.map +1 -1
  49. package/dist/modes/rpc/session-command-router.d.ts.map +1 -1
  50. package/dist/modes/rpc/session-command-router.js +12 -4
  51. package/dist/modes/rpc/session-command-router.js.map +1 -1
  52. package/dist/modes/rpc/session-registry.d.ts +9 -0
  53. package/dist/modes/rpc/session-registry.d.ts.map +1 -1
  54. package/dist/modes/rpc/session-registry.js +31 -3
  55. package/dist/modes/rpc/session-registry.js.map +1 -1
  56. package/docs/providers.md +48 -0
  57. package/docs/rpc.md +6 -4
  58. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +14 -0
  59. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  60. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/context-manager.ts +13 -1
  61. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/inline-worker.ts +15 -1
  62. package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/py/transport.ts +14 -1
  63. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/edit.d.ts.map +1 -1
  64. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/edit.js +20 -4
  65. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/edit.js.map +1 -1
  66. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/index.d.ts +1 -1
  67. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/index.d.ts.map +1 -1
  68. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/index.js.map +1 -1
  69. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/post-mutate.d.ts +21 -0
  70. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/post-mutate.d.ts.map +1 -0
  71. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/post-mutate.js +27 -0
  72. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/post-mutate.js.map +1 -0
  73. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/tool-context.d.ts +24 -0
  74. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/tool-context.d.ts.map +1 -1
  75. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/tool-context.js.map +1 -1
  76. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/write.d.ts.map +1 -1
  77. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/write.js +7 -2
  78. package/node_modules/@earendil-works/pi-agent-core/dist/harness/tools/write.js.map +1 -1
  79. package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
  80. package/node_modules/@earendil-works/pi-ai/dist/auth/credential-store.d.ts +2 -1
  81. package/node_modules/@earendil-works/pi-ai/dist/auth/credential-store.d.ts.map +1 -1
  82. package/node_modules/@earendil-works/pi-ai/dist/auth/credential-store.js +2 -1
  83. package/node_modules/@earendil-works/pi-ai/dist/auth/credential-store.js.map +1 -1
  84. package/node_modules/@earendil-works/pi-ai/dist/auth/types.d.ts +3 -2
  85. package/node_modules/@earendil-works/pi-ai/dist/auth/types.d.ts.map +1 -1
  86. package/node_modules/@earendil-works/pi-ai/dist/auth/types.js.map +1 -1
  87. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  88. package/node_modules/@earendil-works/pi-ai/dist/providers/data/alibaba-token-plan.json +1 -1
  89. package/node_modules/@earendil-works/pi-ai/dist/providers/data/fireworks.json +1 -1
  90. package/node_modules/@earendil-works/pi-ai/dist/providers/data/github-copilot.json +1 -1
  91. package/node_modules/@earendil-works/pi-ai/dist/providers/data/nvidia.json +1 -1
  92. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openai-codex.json +1 -1
  93. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openai.json +1 -1
  94. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  95. package/node_modules/@earendil-works/pi-ai/dist/providers/data/qwen-token-plan-cn.json +1 -1
  96. package/node_modules/@earendil-works/pi-ai/dist/providers/data/qwen-token-plan.json +1 -1
  97. package/node_modules/@earendil-works/pi-ai/dist/providers/data/together.json +1 -1
  98. package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
  99. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  100. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  101. package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
  102. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  103. package/package.json +7 -7
@@ -1 +1 @@
1
- {"version":3,"file":"edit.js","sourceRoot":"","sources":["../../../src/harness/tools/edit.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Static, Type } from \"typebox\";\nimport type { AgentHarnessTool, FileError } from \"../types.ts\";\nimport {\n\tapplyEditsToNormalizedContent,\n\tdetectLineEnding,\n\ttype Edit,\n\tgenerateDiffString,\n\tgenerateUnifiedPatch,\n\tnormalizeToLF,\n\trestoreLineEndings,\n\tstripBom,\n} from \"./edit-diff.ts\";\nimport { withFileMutationQueue } from \"./file-mutation-queue.ts\";\nimport { resolveToolPath } from \"./path-utils.ts\";\nimport type { ExecutionToolContext } from \"./tool-context.ts\";\n\nconst replaceEditSchema = Type.Object(\n\t{\n\t\toldText: Type.String({\n\t\t\tdescription:\n\t\t\t\t\"Exact text for one targeted replacement. It must be unique in the original file and must not overlap with any other edits[].oldText in the same call.\",\n\t\t}),\n\t\tnewText: Type.String({ description: \"Replacement text for this targeted edit.\" }),\n\t},\n\t{},\n);\n\nconst editSchema = Type.Object(\n\t{\n\t\tpath: Type.String({ description: \"Path to the file to edit (relative or absolute)\" }),\n\t\tedits: Type.Array(replaceEditSchema, {\n\t\t\tdescription:\n\t\t\t\t\"One or more targeted replacements. Each edit is matched against the original file, not incrementally. Do not include overlapping or nested edits. If two changes touch the same block or nearby lines, merge them into one edit instead.\",\n\t\t}),\n\t},\n\t{},\n);\n\nexport type EditToolInput = Static<typeof editSchema>;\ntype LegacyEditToolInput = EditToolInput & { oldText?: unknown; newText?: unknown };\ntype SingleEditInput = { oldText: string; newText: string };\n\nfunction isSingleEditInput(value: unknown): value is SingleEditInput {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) return false;\n\tconst edit = value as Record<string, unknown>;\n\treturn typeof edit.oldText === \"string\" && typeof edit.newText === \"string\";\n}\n\nexport interface EditToolDetails {\n\tdiff: string;\n\tpatch: string;\n\tfirstChangedLine?: number;\n}\n\nfunction prepareEditArguments(input: unknown): EditToolInput {\n\tif (!input || typeof input !== \"object\") return input as EditToolInput;\n\tconst args = input as Record<string, unknown>;\n\tif (typeof args.edits === \"string\") {\n\t\ttry {\n\t\t\tconst parsed: unknown = JSON.parse(args.edits);\n\t\t\tif (Array.isArray(parsed)) {\n\t\t\t\targs.edits = parsed;\n\t\t\t} else if (isSingleEditInput(parsed)) {\n\t\t\t\targs.edits = [parsed];\n\t\t\t}\n\t\t} catch {}\n\t} else if (isSingleEditInput(args.edits)) {\n\t\targs.edits = [args.edits];\n\t}\n\n\tconst legacy = args as LegacyEditToolInput;\n\tif (typeof legacy.oldText !== \"string\" || typeof legacy.newText !== \"string\") return args as EditToolInput;\n\tconst edits = Array.isArray(legacy.edits) ? [...legacy.edits] : [];\n\tedits.push({ oldText: legacy.oldText, newText: legacy.newText });\n\tconst { oldText: _oldText, newText: _newText, ...rest } = legacy;\n\treturn { ...rest, edits } as EditToolInput;\n}\n\nfunction validateEditInput(input: EditToolInput): { path: string; edits: Edit[] } {\n\tif (!Array.isArray(input.edits) || input.edits.length === 0) {\n\t\tthrow new Error(\"Edit tool input is invalid. edits must contain at least one replacement.\");\n\t}\n\treturn { path: input.path, edits: input.edits };\n}\n\nfunction editAccessError(path: string, error: FileError): Error {\n\treturn new Error(`Could not edit file: ${path}. Error code: ${error.code}.`, { cause: error });\n}\n\nexport function createEditTool<TContext extends ExecutionToolContext = ExecutionToolContext>(): AgentHarnessTool<\n\tTContext,\n\ttypeof editSchema,\n\tEditToolDetails | undefined\n> {\n\treturn {\n\t\tname: \"edit\",\n\t\tlabel: \"edit\",\n\t\tdescription:\n\t\t\t\"Edit a single file using exact text replacement. Every edits[].oldText must match a unique, non-overlapping region of the original file. If two changes affect the same block or nearby lines, merge them into one edit instead of emitting overlapping edits. Do not include large unchanged regions just to connect distant changes.\",\n\t\tparameters: editSchema,\n\t\tprepareArguments: prepareEditArguments,\n\t\tasync execute(_toolCallId, input, signal, _onUpdate, { env }) {\n\t\t\tconst { path, edits } = validateEditInput(input);\n\t\t\tconst absolutePath = await resolveToolPath(env, path, signal);\n\t\t\treturn withFileMutationQueue(env, absolutePath, async () => {\n\t\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\t\t\tconst info = await env.fileInfo(absolutePath, signal);\n\t\t\t\tif (!info.ok) throw editAccessError(path, info.error);\n\t\t\t\tif (info.value.kind !== \"file\" && info.value.kind !== \"symlink\") {\n\t\t\t\t\tthrow new Error(`Could not edit file: ${path}. Path is not a file.`);\n\t\t\t\t}\n\n\t\t\t\tconst readResult = await env.readTextFile(absolutePath, signal);\n\t\t\t\tif (!readResult.ok) throw editAccessError(path, readResult.error);\n\t\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\n\t\t\t\tconst { bom, text: content } = stripBom(readResult.value);\n\t\t\t\tconst originalEnding = detectLineEnding(content);\n\t\t\t\tconst normalizedContent = normalizeToLF(content);\n\t\t\t\tconst { baseContent, newContent } = applyEditsToNormalizedContent(normalizedContent, edits, path);\n\t\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\n\t\t\t\tconst finalContent = bom + restoreLineEndings(newContent, originalEnding);\n\t\t\t\tconst writeResult = await env.writeFile(absolutePath, finalContent, signal);\n\t\t\t\tif (!writeResult.ok) throw editAccessError(path, writeResult.error);\n\t\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\n\t\t\t\tconst diffResult = generateDiffString(baseContent, newContent);\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `Successfully replaced ${edits.length} block(s) in ${path}.` }],\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\tdiff: diffResult.diff,\n\t\t\t\t\t\tpatch: generateUnifiedPatch(path, baseContent, newContent),\n\t\t\t\t\t\tfirstChangedLine: diffResult.firstChangedLine,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t});\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"edit.js","sourceRoot":"","sources":["../../../src/harness/tools/edit.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Static, Type } from \"typebox\";\nimport type { AgentHarnessTool, FileError } from \"../types.ts\";\nimport {\n\tapplyEditsToNormalizedContent,\n\tdetectLineEnding,\n\ttype Edit,\n\tgenerateDiffString,\n\tgenerateUnifiedPatch,\n\tnormalizeToLF,\n\trestoreLineEndings,\n\tstripBom,\n} from \"./edit-diff.ts\";\nimport { withFileMutationQueue } from \"./file-mutation-queue.ts\";\nimport { resolveToolPath } from \"./path-utils.ts\";\nimport { appendPostMutateNote, runPostMutate } from \"./post-mutate.ts\";\nimport type { ExecutionToolContext } from \"./tool-context.ts\";\n\nconst replaceEditSchema = Type.Object(\n\t{\n\t\toldText: Type.String({\n\t\t\tdescription:\n\t\t\t\t\"Exact text for one targeted replacement. It must be unique in the original file and must not overlap with any other edits[].oldText in the same call.\",\n\t\t}),\n\t\tnewText: Type.String({ description: \"Replacement text for this targeted edit.\" }),\n\t},\n\t{},\n);\n\nconst editSchema = Type.Object(\n\t{\n\t\tpath: Type.String({ description: \"Path to the file to edit (relative or absolute)\" }),\n\t\tedits: Type.Array(replaceEditSchema, {\n\t\t\tdescription:\n\t\t\t\t\"One or more targeted replacements. Each edit is matched against the original file, not incrementally. Do not include overlapping or nested edits. If two changes touch the same block or nearby lines, merge them into one edit instead.\",\n\t\t}),\n\t},\n\t{},\n);\n\nexport type EditToolInput = Static<typeof editSchema>;\ntype LegacyEditToolInput = EditToolInput & { oldText?: unknown; newText?: unknown };\ntype SingleEditInput = { oldText: string; newText: string };\n\nfunction isSingleEditInput(value: unknown): value is SingleEditInput {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) return false;\n\tconst edit = value as Record<string, unknown>;\n\treturn typeof edit.oldText === \"string\" && typeof edit.newText === \"string\";\n}\n\nexport interface EditToolDetails {\n\tdiff: string;\n\tpatch: string;\n\tfirstChangedLine?: number;\n}\n\nfunction prepareEditArguments(input: unknown): EditToolInput {\n\tif (!input || typeof input !== \"object\") return input as EditToolInput;\n\tconst args = input as Record<string, unknown>;\n\tif (typeof args.edits === \"string\") {\n\t\ttry {\n\t\t\tconst parsed: unknown = JSON.parse(args.edits);\n\t\t\tif (Array.isArray(parsed)) {\n\t\t\t\targs.edits = parsed;\n\t\t\t} else if (isSingleEditInput(parsed)) {\n\t\t\t\targs.edits = [parsed];\n\t\t\t}\n\t\t} catch {}\n\t} else if (isSingleEditInput(args.edits)) {\n\t\targs.edits = [args.edits];\n\t}\n\n\tconst legacy = args as LegacyEditToolInput;\n\tif (typeof legacy.oldText !== \"string\" || typeof legacy.newText !== \"string\") return args as EditToolInput;\n\tconst edits = Array.isArray(legacy.edits) ? [...legacy.edits] : [];\n\tedits.push({ oldText: legacy.oldText, newText: legacy.newText });\n\tconst { oldText: _oldText, newText: _newText, ...rest } = legacy;\n\treturn { ...rest, edits } as EditToolInput;\n}\n\nfunction validateEditInput(input: EditToolInput): { path: string; edits: Edit[] } {\n\tif (!Array.isArray(input.edits) || input.edits.length === 0) {\n\t\tthrow new Error(\"Edit tool input is invalid. edits must contain at least one replacement.\");\n\t}\n\treturn { path: input.path, edits: input.edits };\n}\n\nfunction editAccessError(path: string, error: FileError): Error {\n\treturn new Error(`Could not edit file: ${path}. Error code: ${error.code}.`, { cause: error });\n}\n\nexport function createEditTool<TContext extends ExecutionToolContext = ExecutionToolContext>(): AgentHarnessTool<\n\tTContext,\n\ttypeof editSchema,\n\tEditToolDetails | undefined\n> {\n\treturn {\n\t\tname: \"edit\",\n\t\tlabel: \"edit\",\n\t\tdescription:\n\t\t\t\"Edit a single file using exact text replacement. Every edits[].oldText must match a unique, non-overlapping region of the original file. If two changes affect the same block or nearby lines, merge them into one edit instead of emitting overlapping edits. Do not include large unchanged regions just to connect distant changes.\",\n\t\tparameters: editSchema,\n\t\tprepareArguments: prepareEditArguments,\n\t\tasync execute(_toolCallId, input, signal, _onUpdate, { env, postMutate }) {\n\t\t\tconst { path, edits } = validateEditInput(input);\n\t\t\tconst absolutePath = await resolveToolPath(env, path, signal);\n\t\t\treturn withFileMutationQueue(env, absolutePath, async () => {\n\t\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\t\t\tconst info = await env.fileInfo(absolutePath, signal);\n\t\t\t\tif (!info.ok) throw editAccessError(path, info.error);\n\t\t\t\tif (info.value.kind !== \"file\" && info.value.kind !== \"symlink\") {\n\t\t\t\t\tthrow new Error(`Could not edit file: ${path}. Path is not a file.`);\n\t\t\t\t}\n\n\t\t\t\tconst readResult = await env.readTextFile(absolutePath, signal);\n\t\t\t\tif (!readResult.ok) throw editAccessError(path, readResult.error);\n\t\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\n\t\t\t\tconst { bom, text: content } = stripBom(readResult.value);\n\t\t\t\tconst originalEnding = detectLineEnding(content);\n\t\t\t\tconst normalizedContent = normalizeToLF(content);\n\t\t\t\tconst { baseContent, newContent } = applyEditsToNormalizedContent(normalizedContent, edits, path);\n\t\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\n\t\t\t\tconst finalContent = bom + restoreLineEndings(newContent, originalEnding);\n\t\t\t\tconst writeResult = await env.writeFile(absolutePath, finalContent, signal);\n\t\t\t\tif (!writeResult.ok) throw editAccessError(path, writeResult.error);\n\t\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\n\t\t\t\tconst outcome = await runPostMutate(postMutate, { tool: \"edit\", path: absolutePath, signal });\n\t\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\n\t\t\t\tlet committedContent = newContent;\n\t\t\t\tlet rereadNote: string | undefined;\n\t\t\t\tif (outcome.fileMayHaveChanged) {\n\t\t\t\t\tconst postMutateRead = await env.readTextFile(absolutePath, signal);\n\t\t\t\t\t// The edit itself already landed, so an unreadable file is the hook's doing, not a\n\t\t\t\t\t// failed edit. Report it as a note rather than an error that misattributes the failure.\n\t\t\t\t\tif (postMutateRead.ok) committedContent = normalizeToLF(stripBom(postMutateRead.value).text);\n\t\t\t\t\telse\n\t\t\t\t\t\trereadNote = `postMutate left the file unreadable: ${postMutateRead.error.code}. Reported diff describes the edit before the hook ran.`;\n\t\t\t\t}\n\n\t\t\t\tconst diffResult = generateDiffString(baseContent, committedContent);\n\t\t\t\tconst text = appendPostMutateNote(\n\t\t\t\t\t`Successfully replaced ${edits.length} block(s) in ${path}.`,\n\t\t\t\t\toutcome.note,\n\t\t\t\t\trereadNote,\n\t\t\t\t);\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text }],\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\tdiff: diffResult.diff,\n\t\t\t\t\t\tpatch: generateUnifiedPatch(path, baseContent, committedContent),\n\t\t\t\t\t\tfirstChangedLine: diffResult.firstChangedLine,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t});\n\t\t},\n\t};\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  export { type BashExecution, type BashPrepare, type BashToolDetails, type BashToolInput, type BashToolOptions, createBashTool, } from "./bash.ts";
2
2
  export { createEditTool, type EditToolDetails, type EditToolInput, } from "./edit.ts";
3
3
  export { createReadTool, type ReadImageProcessor, type ReadImageProcessorResult, type ReadToolDetails, type ReadToolInput, type ReadToolOptions, } from "./read.ts";
4
- export type { ExecutionToolContext } from "./tool-context.ts";
4
+ export type { ExecutionToolContext, PostMutateContext, PostMutateHook, PostMutateResult, } from "./tool-context.ts";
5
5
  export { createWriteTool, type WriteToolInput } from "./write.ts";
6
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/harness/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,cAAc,GACd,MAAM,WAAW,CAAC;AACnB,OAAO,EACN,cAAc,EACd,KAAK,eAAe,EACpB,KAAK,aAAa,GAClB,MAAM,WAAW,CAAC;AACnB,OAAO,EACN,cAAc,EACd,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,EAC7B,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,eAAe,GACpB,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/harness/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,cAAc,GACd,MAAM,WAAW,CAAC;AACnB,OAAO,EACN,cAAc,EACd,KAAK,eAAe,EACpB,KAAK,aAAa,GAClB,MAAM,WAAW,CAAC;AACnB,OAAO,EACN,cAAc,EACd,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,EAC7B,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,eAAe,GACpB,MAAM,WAAW,CAAC;AACnB,YAAY,EACX,oBAAoB,EACpB,iBAAiB,EACjB,cAAc,EACd,gBAAgB,GAChB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,YAAY,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/harness/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAMN,cAAc,GACd,MAAM,WAAW,CAAC;AACnB,OAAO,EACN,cAAc,GAGd,MAAM,WAAW,CAAC;AACnB,OAAO,EACN,cAAc,GAMd,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,eAAe,EAAuB,MAAM,YAAY,CAAC","sourcesContent":["export {\n\ttype BashExecution,\n\ttype BashPrepare,\n\ttype BashToolDetails,\n\ttype BashToolInput,\n\ttype BashToolOptions,\n\tcreateBashTool,\n} from \"./bash.ts\";\nexport {\n\tcreateEditTool,\n\ttype EditToolDetails,\n\ttype EditToolInput,\n} from \"./edit.ts\";\nexport {\n\tcreateReadTool,\n\ttype ReadImageProcessor,\n\ttype ReadImageProcessorResult,\n\ttype ReadToolDetails,\n\ttype ReadToolInput,\n\ttype ReadToolOptions,\n} from \"./read.ts\";\nexport type { ExecutionToolContext } from \"./tool-context.ts\";\nexport { createWriteTool, type WriteToolInput } from \"./write.ts\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/harness/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAMN,cAAc,GACd,MAAM,WAAW,CAAC;AACnB,OAAO,EACN,cAAc,GAGd,MAAM,WAAW,CAAC;AACnB,OAAO,EACN,cAAc,GAMd,MAAM,WAAW,CAAC;AAOnB,OAAO,EAAE,eAAe,EAAuB,MAAM,YAAY,CAAC","sourcesContent":["export {\n\ttype BashExecution,\n\ttype BashPrepare,\n\ttype BashToolDetails,\n\ttype BashToolInput,\n\ttype BashToolOptions,\n\tcreateBashTool,\n} from \"./bash.ts\";\nexport {\n\tcreateEditTool,\n\ttype EditToolDetails,\n\ttype EditToolInput,\n} from \"./edit.ts\";\nexport {\n\tcreateReadTool,\n\ttype ReadImageProcessor,\n\ttype ReadImageProcessorResult,\n\ttype ReadToolDetails,\n\ttype ReadToolInput,\n\ttype ReadToolOptions,\n} from \"./read.ts\";\nexport type {\n\tExecutionToolContext,\n\tPostMutateContext,\n\tPostMutateHook,\n\tPostMutateResult,\n} from \"./tool-context.ts\";\nexport { createWriteTool, type WriteToolInput } from \"./write.ts\";\n"]}
@@ -0,0 +1,21 @@
1
+ import type { PostMutateContext, PostMutateHook } from "./tool-context.ts";
2
+ /** Result of running a `postMutate` hook, with hook failures degraded to a warning note. */
3
+ export interface PostMutateOutcome {
4
+ /**
5
+ * Whether the file may differ from the bytes the tool itself wrote. True when the hook reported
6
+ * a change, and also when the hook rejected — a hook that fails midway can leave the file
7
+ * partially rewritten, so callers must re-read rather than trust their own bytes.
8
+ */
9
+ fileMayHaveChanged: boolean;
10
+ note?: string;
11
+ }
12
+ /**
13
+ * Run a `postMutate` hook after a write has already landed on disk.
14
+ *
15
+ * The write is committed by the time the hook runs, so a rejecting hook must not fail the tool
16
+ * call and lose that result. Hook failures are reported as an appended warning note instead.
17
+ */
18
+ export declare function runPostMutate(hook: PostMutateHook | undefined, input: PostMutateContext): Promise<PostMutateOutcome>;
19
+ /** Append any `postMutate` notes to tool result text, one per line, skipping absent ones. */
20
+ export declare function appendPostMutateNote(text: string, ...notes: Array<string | undefined>): string;
21
+ //# sourceMappingURL=post-mutate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post-mutate.d.ts","sourceRoot":"","sources":["../../../src/harness/tools/post-mutate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAoB,MAAM,mBAAmB,CAAC;AAE7F,4FAA4F;AAC5F,MAAM,WAAW,iBAAiB;IACjC;;;;OAIG;IACH,kBAAkB,EAAE,OAAO,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;CACd;AAID;;;;;GAKG;AACH,wBAAsB,aAAa,CAClC,IAAI,EAAE,cAAc,GAAG,SAAS,EAChC,KAAK,EAAE,iBAAiB,GACtB,OAAO,CAAC,iBAAiB,CAAC,CAS5B;AAED,6FAA6F;AAC7F,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC,GAAG,MAAM,CAE9F"}
@@ -0,0 +1,27 @@
1
+ const NO_CHANGE = { fileMayHaveChanged: false };
2
+ /**
3
+ * Run a `postMutate` hook after a write has already landed on disk.
4
+ *
5
+ * The write is committed by the time the hook runs, so a rejecting hook must not fail the tool
6
+ * call and lose that result. Hook failures are reported as an appended warning note instead.
7
+ */
8
+ export async function runPostMutate(hook, input) {
9
+ if (!hook)
10
+ return NO_CHANGE;
11
+ let result;
12
+ try {
13
+ result = await hook(input);
14
+ }
15
+ catch (error) {
16
+ return { fileMayHaveChanged: true, note: `postMutate hook failed: ${errorMessage(error)}` };
17
+ }
18
+ return { fileMayHaveChanged: result.changed, note: result.note };
19
+ }
20
+ /** Append any `postMutate` notes to tool result text, one per line, skipping absent ones. */
21
+ export function appendPostMutateNote(text, ...notes) {
22
+ return [text, ...notes.filter((note) => note !== undefined)].join("\n");
23
+ }
24
+ function errorMessage(error) {
25
+ return error instanceof Error ? error.message : String(error);
26
+ }
27
+ //# sourceMappingURL=post-mutate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post-mutate.js","sourceRoot":"","sources":["../../../src/harness/tools/post-mutate.ts"],"names":[],"mappings":"AAaA,MAAM,SAAS,GAAsB,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC;AAEnE;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAClC,IAAgC,EAChC,KAAwB;IAExB,IAAI,CAAC,IAAI;QAAE,OAAO,SAAS,CAAC;IAC5B,IAAI,MAAwB,CAAC;IAC7B,IAAI,CAAC;QACJ,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,OAAO,EAAE,kBAAkB,EAAE,IAAI,EAAE,IAAI,EAAE,2BAA2B,YAAY,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;IAC7F,CAAC;IACD,OAAO,EAAE,kBAAkB,EAAE,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;AAClE,CAAC;AAED,6FAA6F;AAC7F,MAAM,UAAU,oBAAoB,CAAC,IAAY,EAAE,GAAG,KAAgC;IACrF,OAAO,CAAC,IAAI,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACzE,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IACnC,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC/D,CAAC","sourcesContent":["import type { PostMutateContext, PostMutateHook, PostMutateResult } from \"./tool-context.ts\";\n\n/** Result of running a `postMutate` hook, with hook failures degraded to a warning note. */\nexport interface PostMutateOutcome {\n\t/**\n\t * Whether the file may differ from the bytes the tool itself wrote. True when the hook reported\n\t * a change, and also when the hook rejected — a hook that fails midway can leave the file\n\t * partially rewritten, so callers must re-read rather than trust their own bytes.\n\t */\n\tfileMayHaveChanged: boolean;\n\tnote?: string;\n}\n\nconst NO_CHANGE: PostMutateOutcome = { fileMayHaveChanged: false };\n\n/**\n * Run a `postMutate` hook after a write has already landed on disk.\n *\n * The write is committed by the time the hook runs, so a rejecting hook must not fail the tool\n * call and lose that result. Hook failures are reported as an appended warning note instead.\n */\nexport async function runPostMutate(\n\thook: PostMutateHook | undefined,\n\tinput: PostMutateContext,\n): Promise<PostMutateOutcome> {\n\tif (!hook) return NO_CHANGE;\n\tlet result: PostMutateResult;\n\ttry {\n\t\tresult = await hook(input);\n\t} catch (error) {\n\t\treturn { fileMayHaveChanged: true, note: `postMutate hook failed: ${errorMessage(error)}` };\n\t}\n\treturn { fileMayHaveChanged: result.changed, note: result.note };\n}\n\n/** Append any `postMutate` notes to tool result text, one per line, skipping absent ones. */\nexport function appendPostMutateNote(text: string, ...notes: Array<string | undefined>): string {\n\treturn [text, ...notes.filter((note) => note !== undefined)].join(\"\\n\");\n}\n\nfunction errorMessage(error: unknown): string {\n\treturn error instanceof Error ? error.message : String(error);\n}\n"]}
@@ -1,6 +1,30 @@
1
1
  import type { ExecutionEnv } from "../types.ts";
2
+ /** Mutation that triggered a `postMutate` hook run. */
3
+ export interface PostMutateContext {
4
+ /** Tool that performed the mutation. */
5
+ tool: "write" | "edit";
6
+ /** Absolute path of the file that was just written. */
7
+ path: string;
8
+ /** Abort signal of the originating tool call, when the caller supplied one. */
9
+ signal?: AbortSignal;
10
+ }
11
+ /** Outcome reported by a `postMutate` hook. */
12
+ export interface PostMutateResult {
13
+ /** Whether the hook itself rewrote the file after the tool's own write landed. */
14
+ changed: boolean;
15
+ /** Single-line note appended to the tool result text. */
16
+ note?: string;
17
+ }
18
+ /** Hook invoked inside the file mutation queue, immediately after a tool write succeeds. */
19
+ export type PostMutateHook = (input: PostMutateContext) => Promise<PostMutateResult>;
2
20
  /** Filesystem and shell context required by the built-in execution tools. */
3
21
  export interface ExecutionToolContext {
4
22
  env: ExecutionEnv;
23
+ /**
24
+ * Optional post-write hook (formatting, codegen, normalization). It runs inside the same
25
+ * mutation-queue slot as the write it follows, so the file cannot be mutated in between.
26
+ * A rejecting hook never discards the landed write; the tool appends a warning note instead.
27
+ */
28
+ postMutate?: PostMutateHook;
5
29
  }
6
30
  //# sourceMappingURL=tool-context.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tool-context.d.ts","sourceRoot":"","sources":["../../../src/harness/tools/tool-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,6EAA6E;AAC7E,MAAM,WAAW,oBAAoB;IACpC,GAAG,EAAE,YAAY,CAAC;CAClB"}
1
+ {"version":3,"file":"tool-context.d.ts","sourceRoot":"","sources":["../../../src/harness/tools/tool-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,uDAAuD;AACvD,MAAM,WAAW,iBAAiB;IACjC,wCAAwC;IACxC,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC;IACvB,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,MAAM,CAAC,EAAE,WAAW,CAAC;CACrB;AAED,+CAA+C;AAC/C,MAAM,WAAW,gBAAgB;IAChC,kFAAkF;IAClF,OAAO,EAAE,OAAO,CAAC;IACjB,yDAAyD;IACzD,IAAI,CAAC,EAAE,MAAM,CAAC;CACd;AAED,4FAA4F;AAC5F,MAAM,MAAM,cAAc,GAAG,CAAC,KAAK,EAAE,iBAAiB,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;AAErF,6EAA6E;AAC7E,MAAM,WAAW,oBAAoB;IACpC,GAAG,EAAE,YAAY,CAAC;IAClB;;;;OAIG;IACH,UAAU,CAAC,EAAE,cAAc,CAAC;CAC5B"}
@@ -1 +1 @@
1
- {"version":3,"file":"tool-context.js","sourceRoot":"","sources":["../../../src/harness/tools/tool-context.ts"],"names":[],"mappings":"","sourcesContent":["import type { ExecutionEnv } from \"../types.ts\";\n\n/** Filesystem and shell context required by the built-in execution tools. */\nexport interface ExecutionToolContext {\n\tenv: ExecutionEnv;\n}\n"]}
1
+ {"version":3,"file":"tool-context.js","sourceRoot":"","sources":["../../../src/harness/tools/tool-context.ts"],"names":[],"mappings":"","sourcesContent":["import type { ExecutionEnv } from \"../types.ts\";\n\n/** Mutation that triggered a `postMutate` hook run. */\nexport interface PostMutateContext {\n\t/** Tool that performed the mutation. */\n\ttool: \"write\" | \"edit\";\n\t/** Absolute path of the file that was just written. */\n\tpath: string;\n\t/** Abort signal of the originating tool call, when the caller supplied one. */\n\tsignal?: AbortSignal;\n}\n\n/** Outcome reported by a `postMutate` hook. */\nexport interface PostMutateResult {\n\t/** Whether the hook itself rewrote the file after the tool's own write landed. */\n\tchanged: boolean;\n\t/** Single-line note appended to the tool result text. */\n\tnote?: string;\n}\n\n/** Hook invoked inside the file mutation queue, immediately after a tool write succeeds. */\nexport type PostMutateHook = (input: PostMutateContext) => Promise<PostMutateResult>;\n\n/** Filesystem and shell context required by the built-in execution tools. */\nexport interface ExecutionToolContext {\n\tenv: ExecutionEnv;\n\t/**\n\t * Optional post-write hook (formatting, codegen, normalization). It runs inside the same\n\t * mutation-queue slot as the write it follows, so the file cannot be mutated in between.\n\t * A rejecting hook never discards the landed write; the tool appends a warning note instead.\n\t */\n\tpostMutate?: PostMutateHook;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../../src/harness/tools/write.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAIpD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAE9D,QAAA,MAAM,WAAW;;;EAGf,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,WAAW,CAAC,CAAC;AAExD,wBAAgB,eAAe,CAAC,QAAQ,SAAS,oBAAoB,GAAG,oBAAoB,KAAK,gBAAgB,CAChH,QAAQ,EACR,OAAO,WAAW,EAClB,SAAS,CACT,CAoBA"}
1
+ {"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../../src/harness/tools/write.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAKpD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAE9D,QAAA,MAAM,WAAW;;;EAGf,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,WAAW,CAAC,CAAC;AAExD,wBAAgB,eAAe,CAAC,QAAQ,SAAS,oBAAoB,GAAG,oBAAoB,KAAK,gBAAgB,CAChH,QAAQ,EACR,OAAO,WAAW,EAClB,SAAS,CACT,CAuBA"}
@@ -2,6 +2,7 @@ import { Type } from "typebox";
2
2
  import { getOrThrow } from "../types.js";
3
3
  import { withFileMutationQueue } from "./file-mutation-queue.js";
4
4
  import { resolveToolPath } from "./path-utils.js";
5
+ import { appendPostMutateNote, runPostMutate } from "./post-mutate.js";
5
6
  const writeSchema = Type.Object({
6
7
  path: Type.String({ description: "Path to the file to write (relative or absolute)" }),
7
8
  content: Type.String({ description: "Content to write to the file" }),
@@ -12,7 +13,7 @@ export function createWriteTool() {
12
13
  label: "write",
13
14
  description: "Write content to a file. Creates the file if it doesn't exist, overwrites if it does. Automatically creates parent directories.",
14
15
  parameters: writeSchema,
15
- async execute(_toolCallId, { path, content }, signal, _onUpdate, { env }) {
16
+ async execute(_toolCallId, { path, content }, signal, _onUpdate, { env, postMutate }) {
16
17
  const absolutePath = await resolveToolPath(env, path, signal);
17
18
  return withFileMutationQueue(env, absolutePath, async () => {
18
19
  if (signal?.aborted)
@@ -20,8 +21,12 @@ export function createWriteTool() {
20
21
  getOrThrow(await env.writeFile(absolutePath, content, signal));
21
22
  if (signal?.aborted)
22
23
  throw new Error("Operation aborted");
24
+ const outcome = await runPostMutate(postMutate, { tool: "write", path: absolutePath, signal });
25
+ if (signal?.aborted)
26
+ throw new Error("Operation aborted");
27
+ const text = appendPostMutateNote(`Successfully wrote ${content.length} bytes to ${path}`, outcome.note);
23
28
  return {
24
- content: [{ type: "text", text: `Successfully wrote ${content.length} bytes to ${path}` }],
29
+ content: [{ type: "text", text }],
25
30
  details: undefined,
26
31
  };
27
32
  });
@@ -1 +1 @@
1
- {"version":3,"file":"write.js","sourceRoot":"","sources":["../../../src/harness/tools/write.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,IAAI,EAAE,MAAM,SAAS,CAAC;AAE5C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAGlD,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC;IAC/B,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,kDAAkD,EAAE,CAAC;IACtF,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,8BAA8B,EAAE,CAAC;CACrE,CAAC,CAAC;AAIH,MAAM,UAAU,eAAe;IAK9B,OAAO;QACN,IAAI,EAAE,OAAO;QACb,KAAK,EAAE,OAAO;QACd,WAAW,EACV,iIAAiI;QAClI,UAAU,EAAE,WAAW;QACvB,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,GAAG,EAAE;YACvE,MAAM,YAAY,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;YAC9D,OAAO,qBAAqB,CAAC,GAAG,EAAE,YAAY,EAAE,KAAK,IAAI,EAAE;gBAC1D,IAAI,MAAM,EAAE,OAAO;oBAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;gBAC1D,UAAU,CAAC,MAAM,GAAG,CAAC,SAAS,CAAC,YAAY,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;gBAC/D,IAAI,MAAM,EAAE,OAAO;oBAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;gBAC1D,OAAO;oBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,sBAAsB,OAAO,CAAC,MAAM,aAAa,IAAI,EAAE,EAAE,CAAC;oBAC1F,OAAO,EAAE,SAAS;iBAClB,CAAC;YACH,CAAC,CAAC,CAAC;QACJ,CAAC;KACD,CAAC;AACH,CAAC","sourcesContent":["import { type Static, Type } from \"typebox\";\nimport type { AgentHarnessTool } from \"../types.ts\";\nimport { getOrThrow } from \"../types.ts\";\nimport { withFileMutationQueue } from \"./file-mutation-queue.ts\";\nimport { resolveToolPath } from \"./path-utils.ts\";\nimport type { ExecutionToolContext } from \"./tool-context.ts\";\n\nconst writeSchema = Type.Object({\n\tpath: Type.String({ description: \"Path to the file to write (relative or absolute)\" }),\n\tcontent: Type.String({ description: \"Content to write to the file\" }),\n});\n\nexport type WriteToolInput = Static<typeof writeSchema>;\n\nexport function createWriteTool<TContext extends ExecutionToolContext = ExecutionToolContext>(): AgentHarnessTool<\n\tTContext,\n\ttypeof writeSchema,\n\tundefined\n> {\n\treturn {\n\t\tname: \"write\",\n\t\tlabel: \"write\",\n\t\tdescription:\n\t\t\t\"Write content to a file. Creates the file if it doesn't exist, overwrites if it does. Automatically creates parent directories.\",\n\t\tparameters: writeSchema,\n\t\tasync execute(_toolCallId, { path, content }, signal, _onUpdate, { env }) {\n\t\t\tconst absolutePath = await resolveToolPath(env, path, signal);\n\t\t\treturn withFileMutationQueue(env, absolutePath, async () => {\n\t\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\t\t\tgetOrThrow(await env.writeFile(absolutePath, content, signal));\n\t\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `Successfully wrote ${content.length} bytes to ${path}` }],\n\t\t\t\t\tdetails: undefined,\n\t\t\t\t};\n\t\t\t});\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"write.js","sourceRoot":"","sources":["../../../src/harness/tools/write.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,IAAI,EAAE,MAAM,SAAS,CAAC;AAE5C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGvE,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC;IAC/B,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,kDAAkD,EAAE,CAAC;IACtF,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,8BAA8B,EAAE,CAAC;CACrE,CAAC,CAAC;AAIH,MAAM,UAAU,eAAe;IAK9B,OAAO;QACN,IAAI,EAAE,OAAO;QACb,KAAK,EAAE,OAAO;QACd,WAAW,EACV,iIAAiI;QAClI,UAAU,EAAE,WAAW;QACvB,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE;YACnF,MAAM,YAAY,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;YAC9D,OAAO,qBAAqB,CAAC,GAAG,EAAE,YAAY,EAAE,KAAK,IAAI,EAAE;gBAC1D,IAAI,MAAM,EAAE,OAAO;oBAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;gBAC1D,UAAU,CAAC,MAAM,GAAG,CAAC,SAAS,CAAC,YAAY,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;gBAC/D,IAAI,MAAM,EAAE,OAAO;oBAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;gBAC1D,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC,CAAC;gBAC/F,IAAI,MAAM,EAAE,OAAO;oBAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;gBAC1D,MAAM,IAAI,GAAG,oBAAoB,CAAC,sBAAsB,OAAO,CAAC,MAAM,aAAa,IAAI,EAAE,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;gBACzG,OAAO;oBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;oBACjC,OAAO,EAAE,SAAS;iBAClB,CAAC;YACH,CAAC,CAAC,CAAC;QACJ,CAAC;KACD,CAAC;AACH,CAAC","sourcesContent":["import { type Static, Type } from \"typebox\";\nimport type { AgentHarnessTool } from \"../types.ts\";\nimport { getOrThrow } from \"../types.ts\";\nimport { withFileMutationQueue } from \"./file-mutation-queue.ts\";\nimport { resolveToolPath } from \"./path-utils.ts\";\nimport { appendPostMutateNote, runPostMutate } from \"./post-mutate.ts\";\nimport type { ExecutionToolContext } from \"./tool-context.ts\";\n\nconst writeSchema = Type.Object({\n\tpath: Type.String({ description: \"Path to the file to write (relative or absolute)\" }),\n\tcontent: Type.String({ description: \"Content to write to the file\" }),\n});\n\nexport type WriteToolInput = Static<typeof writeSchema>;\n\nexport function createWriteTool<TContext extends ExecutionToolContext = ExecutionToolContext>(): AgentHarnessTool<\n\tTContext,\n\ttypeof writeSchema,\n\tundefined\n> {\n\treturn {\n\t\tname: \"write\",\n\t\tlabel: \"write\",\n\t\tdescription:\n\t\t\t\"Write content to a file. Creates the file if it doesn't exist, overwrites if it does. Automatically creates parent directories.\",\n\t\tparameters: writeSchema,\n\t\tasync execute(_toolCallId, { path, content }, signal, _onUpdate, { env, postMutate }) {\n\t\t\tconst absolutePath = await resolveToolPath(env, path, signal);\n\t\t\treturn withFileMutationQueue(env, absolutePath, async () => {\n\t\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\t\t\tgetOrThrow(await env.writeFile(absolutePath, content, signal));\n\t\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\t\t\tconst outcome = await runPostMutate(postMutate, { tool: \"write\", path: absolutePath, signal });\n\t\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\t\t\tconst text = appendPostMutateNote(`Successfully wrote ${content.length} bytes to ${path}`, outcome.note);\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text }],\n\t\t\t\t\tdetails: undefined,\n\t\t\t\t};\n\t\t\t});\n\t\t},\n\t};\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@earendil-works/pi-agent-core",
3
- "version": "2026.8.27",
3
+ "version": "2026.8.28",
4
4
  "description": "General-purpose agent with transport abstraction, state management, and attachment support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -35,8 +35,8 @@
35
35
  "prepublishOnly": "npm run build"
36
36
  },
37
37
  "dependencies": {
38
- "@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.8.27",
39
- "@earendil-works/pi-telemetry": "npm:@code-yeongyu/senpi-telemetry@2026.8.27",
38
+ "@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.8.28",
39
+ "@earendil-works/pi-telemetry": "npm:@code-yeongyu/senpi-telemetry@2026.8.28",
40
40
  "diff": "9.0.0",
41
41
  "ignore": "7.0.6",
42
42
  "typebox": "1.3.18",
@@ -1,7 +1,8 @@
1
1
  import type { AuthOperationOptions, Credential, CredentialInfo, CredentialStore } from "./types.ts";
2
2
  /**
3
3
  * Default in-memory credential store. Apps inject persistent stores.
4
- * Keyed by `Provider.id`, one credential per provider; see `CredentialStore`.
4
+ * Keyed by `Provider.id`, one entry per provider (possibly a pooled one);
5
+ * see `CredentialStore`.
5
6
  * Writes are serialized per provider through a promise chain.
6
7
  */
7
8
  export declare class InMemoryCredentialStore implements CredentialStore {
@@ -1 +1 @@
1
- {"version":3,"file":"credential-store.d.ts","sourceRoot":"","sources":["../../src/auth/credential-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,UAAU,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAEpG;;;;GAIG;AACH,qBAAa,uBAAwB,YAAW,eAAe;IAC9D,OAAO,CAAC,WAAW,CAAiC;IACpD,OAAO,CAAC,MAAM,CAAuC;IAErD,8FAA8F;IAC9F,OAAO,CAAC,OAAO;IAgBT,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAKzF,IAAI,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,SAAS,cAAc,EAAE,CAAC;IAK9E,MAAM,CACL,UAAU,EAAE,MAAM,EAClB,EAAE,EAAE,CAAC,OAAO,EAAE,UAAU,GAAG,SAAS,KAAK,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,EACxE,OAAO,CAAC,EAAE,oBAAoB,GAC5B,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAclC,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;CASzE"}
1
+ {"version":3,"file":"credential-store.d.ts","sourceRoot":"","sources":["../../src/auth/credential-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,UAAU,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAEpG;;;;;GAKG;AACH,qBAAa,uBAAwB,YAAW,eAAe;IAC9D,OAAO,CAAC,WAAW,CAAiC;IACpD,OAAO,CAAC,MAAM,CAAuC;IAErD,8FAA8F;IAC9F,OAAO,CAAC,OAAO;IAgBT,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAKzF,IAAI,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,SAAS,cAAc,EAAE,CAAC;IAK9E,MAAM,CACL,UAAU,EAAE,MAAM,EAClB,EAAE,EAAE,CAAC,OAAO,EAAE,UAAU,GAAG,SAAS,KAAK,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,EACxE,OAAO,CAAC,EAAE,oBAAoB,GAC5B,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAclC,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;CASzE"}
@@ -1,7 +1,8 @@
1
1
  import { operationSignal, raceWithAbortSignal } from "../utils/abort.js";
2
2
  /**
3
3
  * Default in-memory credential store. Apps inject persistent stores.
4
- * Keyed by `Provider.id`, one credential per provider; see `CredentialStore`.
4
+ * Keyed by `Provider.id`, one entry per provider (possibly a pooled one);
5
+ * see `CredentialStore`.
5
6
  * Writes are serialized per provider through a promise chain.
6
7
  */
7
8
  export class InMemoryCredentialStore {
@@ -1 +1 @@
1
- {"version":3,"file":"credential-store.js","sourceRoot":"","sources":["../../src/auth/credential-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAGzE;;;;GAIG;AACH,MAAM,OAAO,uBAAuB;IAApC;QACS,gBAAW,GAAG,IAAI,GAAG,EAAsB,CAAC;QAC5C,WAAM,GAAG,IAAI,GAAG,EAA4B,CAAC;IAwDtD,CAAC;IAtDA,8FAA8F;IACtF,OAAO,CAAI,UAAkB,EAAE,IAAsB,EAAE,OAA8B;QAC5F,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAChD,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QAClE,MAAM,MAAM,GAAG,CAAC,KAAK,IAAI,EAAE;YAC1B,MAAM,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YAC/B,MAAM,CAAC,cAAc,EAAE,CAAC;YACxB,OAAO,IAAI,EAAE,CAAC;QACf,CAAC,CAAC,EAAE,CAAC;QACL,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACpC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QAClC,KAAK,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE;YACnB,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,IAAI;gBAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAC1E,CAAC,CAAC,CAAC;QACH,OAAO,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,UAAkB,EAAE,OAA8B;QAC5D,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;QAClC,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,OAA8B;QACxC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;QAClC,OAAO,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,EAAE,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACzG,CAAC;IAED,MAAM,CACL,UAAkB,EAClB,EAAwE,EACxE,OAA8B;QAE9B,OAAO,IAAI,CAAC,OAAO,CAClB,UAAU,EACV,KAAK,IAAI,EAAE;YACV,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YACjD,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,CAAC;YAC/B,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;YAClC,IAAI,IAAI,KAAK,SAAS;gBAAE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;YAC/D,OAAO,IAAI,IAAI,OAAO,CAAC;QACxB,CAAC,EACD,OAAO,CACP,CAAC;IACH,CAAC;IAED,MAAM,CAAC,UAAkB,EAAE,OAA8B;QACxD,OAAO,IAAI,CAAC,OAAO,CAClB,UAAU,EACV,KAAK,IAAI,EAAE;YACV,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QACrC,CAAC,EACD,OAAO,CACP,CAAC;IACH,CAAC;CACD","sourcesContent":["import { operationSignal, raceWithAbortSignal } from \"../utils/abort.ts\";\nimport type { AuthOperationOptions, Credential, CredentialInfo, CredentialStore } from \"./types.ts\";\n\n/**\n * Default in-memory credential store. Apps inject persistent stores.\n * Keyed by `Provider.id`, one credential per provider; see `CredentialStore`.\n * Writes are serialized per provider through a promise chain.\n */\nexport class InMemoryCredentialStore implements CredentialStore {\n\tprivate credentials = new Map<string, Credential>();\n\tprivate chains = new Map<string, Promise<unknown>>();\n\n\t/** Serialize tasks per provider id without releasing the chain before active work settles. */\n\tprivate enqueue<T>(providerId: string, task: () => Promise<T>, options?: AuthOperationOptions): Promise<T> {\n\t\tconst signal = operationSignal(options?.signal);\n\t\tconst previous = this.chains.get(providerId) ?? Promise.resolve();\n\t\tconst queued = (async () => {\n\t\t\tawait previous.catch(() => {});\n\t\t\tsignal.throwIfAborted();\n\t\t\treturn task();\n\t\t})();\n\t\tconst tail = queued.catch(() => {});\n\t\tthis.chains.set(providerId, tail);\n\t\tvoid tail.then(() => {\n\t\t\tif (this.chains.get(providerId) === tail) this.chains.delete(providerId);\n\t\t});\n\t\treturn raceWithAbortSignal(queued, signal);\n\t}\n\n\tasync read(providerId: string, options?: AuthOperationOptions): Promise<Credential | undefined> {\n\t\toptions?.signal?.throwIfAborted();\n\t\treturn this.credentials.get(providerId);\n\t}\n\n\tasync list(options?: AuthOperationOptions): Promise<readonly CredentialInfo[]> {\n\t\toptions?.signal?.throwIfAborted();\n\t\treturn [...this.credentials].map(([providerId, credential]) => ({ providerId, type: credential.type }));\n\t}\n\n\tmodify(\n\t\tproviderId: string,\n\t\tfn: (current: Credential | undefined) => Promise<Credential | undefined>,\n\t\toptions?: AuthOperationOptions,\n\t): Promise<Credential | undefined> {\n\t\treturn this.enqueue(\n\t\t\tproviderId,\n\t\t\tasync () => {\n\t\t\t\tconst current = this.credentials.get(providerId);\n\t\t\t\tconst next = await fn(current);\n\t\t\t\toptions?.signal?.throwIfAborted();\n\t\t\t\tif (next !== undefined) this.credentials.set(providerId, next);\n\t\t\t\treturn next ?? current;\n\t\t\t},\n\t\t\toptions,\n\t\t);\n\t}\n\n\tdelete(providerId: string, options?: AuthOperationOptions): Promise<void> {\n\t\treturn this.enqueue(\n\t\t\tproviderId,\n\t\t\tasync () => {\n\t\t\t\tthis.credentials.delete(providerId);\n\t\t\t},\n\t\t\toptions,\n\t\t);\n\t}\n}\n"]}
1
+ {"version":3,"file":"credential-store.js","sourceRoot":"","sources":["../../src/auth/credential-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAGzE;;;;;GAKG;AACH,MAAM,OAAO,uBAAuB;IAApC;QACS,gBAAW,GAAG,IAAI,GAAG,EAAsB,CAAC;QAC5C,WAAM,GAAG,IAAI,GAAG,EAA4B,CAAC;IAwDtD,CAAC;IAtDA,8FAA8F;IACtF,OAAO,CAAI,UAAkB,EAAE,IAAsB,EAAE,OAA8B;QAC5F,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAChD,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QAClE,MAAM,MAAM,GAAG,CAAC,KAAK,IAAI,EAAE;YAC1B,MAAM,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YAC/B,MAAM,CAAC,cAAc,EAAE,CAAC;YACxB,OAAO,IAAI,EAAE,CAAC;QACf,CAAC,CAAC,EAAE,CAAC;QACL,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACpC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QAClC,KAAK,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE;YACnB,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,IAAI;gBAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAC1E,CAAC,CAAC,CAAC;QACH,OAAO,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,UAAkB,EAAE,OAA8B;QAC5D,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;QAClC,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,OAA8B;QACxC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;QAClC,OAAO,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,EAAE,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACzG,CAAC;IAED,MAAM,CACL,UAAkB,EAClB,EAAwE,EACxE,OAA8B;QAE9B,OAAO,IAAI,CAAC,OAAO,CAClB,UAAU,EACV,KAAK,IAAI,EAAE;YACV,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YACjD,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,CAAC;YAC/B,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;YAClC,IAAI,IAAI,KAAK,SAAS;gBAAE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;YAC/D,OAAO,IAAI,IAAI,OAAO,CAAC;QACxB,CAAC,EACD,OAAO,CACP,CAAC;IACH,CAAC;IAED,MAAM,CAAC,UAAkB,EAAE,OAA8B;QACxD,OAAO,IAAI,CAAC,OAAO,CAClB,UAAU,EACV,KAAK,IAAI,EAAE;YACV,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QACrC,CAAC,EACD,OAAO,CACP,CAAC;IACH,CAAC;CACD","sourcesContent":["import { operationSignal, raceWithAbortSignal } from \"../utils/abort.ts\";\nimport type { AuthOperationOptions, Credential, CredentialInfo, CredentialStore } from \"./types.ts\";\n\n/**\n * Default in-memory credential store. Apps inject persistent stores.\n * Keyed by `Provider.id`, one entry per provider (possibly a pooled one);\n * see `CredentialStore`.\n * Writes are serialized per provider through a promise chain.\n */\nexport class InMemoryCredentialStore implements CredentialStore {\n\tprivate credentials = new Map<string, Credential>();\n\tprivate chains = new Map<string, Promise<unknown>>();\n\n\t/** Serialize tasks per provider id without releasing the chain before active work settles. */\n\tprivate enqueue<T>(providerId: string, task: () => Promise<T>, options?: AuthOperationOptions): Promise<T> {\n\t\tconst signal = operationSignal(options?.signal);\n\t\tconst previous = this.chains.get(providerId) ?? Promise.resolve();\n\t\tconst queued = (async () => {\n\t\t\tawait previous.catch(() => {});\n\t\t\tsignal.throwIfAborted();\n\t\t\treturn task();\n\t\t})();\n\t\tconst tail = queued.catch(() => {});\n\t\tthis.chains.set(providerId, tail);\n\t\tvoid tail.then(() => {\n\t\t\tif (this.chains.get(providerId) === tail) this.chains.delete(providerId);\n\t\t});\n\t\treturn raceWithAbortSignal(queued, signal);\n\t}\n\n\tasync read(providerId: string, options?: AuthOperationOptions): Promise<Credential | undefined> {\n\t\toptions?.signal?.throwIfAborted();\n\t\treturn this.credentials.get(providerId);\n\t}\n\n\tasync list(options?: AuthOperationOptions): Promise<readonly CredentialInfo[]> {\n\t\toptions?.signal?.throwIfAborted();\n\t\treturn [...this.credentials].map(([providerId, credential]) => ({ providerId, type: credential.type }));\n\t}\n\n\tmodify(\n\t\tproviderId: string,\n\t\tfn: (current: Credential | undefined) => Promise<Credential | undefined>,\n\t\toptions?: AuthOperationOptions,\n\t): Promise<Credential | undefined> {\n\t\treturn this.enqueue(\n\t\t\tproviderId,\n\t\t\tasync () => {\n\t\t\t\tconst current = this.credentials.get(providerId);\n\t\t\t\tconst next = await fn(current);\n\t\t\t\toptions?.signal?.throwIfAborted();\n\t\t\t\tif (next !== undefined) this.credentials.set(providerId, next);\n\t\t\t\treturn next ?? current;\n\t\t\t},\n\t\t\toptions,\n\t\t);\n\t}\n\n\tdelete(providerId: string, options?: AuthOperationOptions): Promise<void> {\n\t\treturn this.enqueue(\n\t\t\tproviderId,\n\t\t\tasync () => {\n\t\t\t\tthis.credentials.delete(providerId);\n\t\t\t},\n\t\t\toptions,\n\t\t);\n\t}\n}\n"]}
@@ -40,8 +40,9 @@ export interface AuthOperationOptions {
40
40
  signal?: AbortSignal;
41
41
  }
42
42
  /**
43
- * App-owned credential storage, keyed by `Provider.id`, one credential per
44
- * provider. `modify` is the only write path, so every mutation is a
43
+ * App-owned credential storage, keyed by `Provider.id`, one entry per
44
+ * provider; an entry may pool sibling slots under `accounts` while its flat
45
+ * fields remain a valid credential. `modify` is the only write path, so every mutation is a
45
46
  * serialized read-modify-write; `Models.getAuth()` runs OAuth refresh inside
46
47
  * `modify` so concurrent requests cannot double-refresh a rotated token. The
47
48
  * app persists a credential after login via
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEhE;;;GAGG;AACH,MAAM,WAAW,SAAS;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,SAAS,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,WAAW,CAAC;CAClB;AAED,kEAAkE;AAClE,MAAM,WAAW,gBAAgB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACvB;AAED,yCAAyC;AACzC,MAAM,WAAW,eAAgB,SAAQ,gBAAgB;IACxD,IAAI,EAAE,OAAO,CAAC;CACd;AAED,gFAAgF;AAChF,MAAM,MAAM,UAAU,GAAG,gBAAgB,GAAG,eAAe,CAAC;AAE5D,qEAAqE;AACrE,MAAM,WAAW,cAAc;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;CACzB;AAED,uEAAuE;AACvE,MAAM,WAAW,oBAAoB;IACpC,MAAM,CAAC,EAAE,WAAW,CAAC;CACrB;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,eAAe;IAC/B;;;OAGG;IACH,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;IAE1F;;;OAGG;IACH,IAAI,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,SAAS,cAAc,EAAE,CAAC,CAAC;IAEzE;;;;;;;OAOG;IACH,MAAM,CACL,UAAU,EAAE,MAAM,EAClB,EAAE,EAAE,CAAC,OAAO,EAAE,UAAU,GAAG,SAAS,KAAK,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,EACxE,OAAO,CAAC,EAAE,oBAAoB,GAC5B,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;IAEnC,qFAAqF;IACrF,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1E;AAED,iFAAiF;AACjF,MAAM,WAAW,WAAW;IAC3B,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAC/C,qFAAqF;IACrF,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC3C;AAED,4CAA4C;AAC5C,MAAM,WAAW,UAAU;IAC1B,IAAI,EAAE,SAAS,CAAC;IAChB,+FAA+F;IAC/F,GAAG,CAAC,EAAE,WAAW,CAAC;IAClB,8FAA8F;IAC9F,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,SAAS;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC;CAC1B;AAED,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;AAE3C;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG;IAAE,MAAM,CAAC,EAAE,WAAW,CAAA;CAAE,GAAG,CACjD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GACzD;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,SAAS;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAAE,GAC5G;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAChE,CAAC;AAEF,MAAM,WAAW,YAAY;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,SAAS,GAClB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,SAAS,YAAY,EAAE,CAAA;CAAE,GAClE;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,GACxD;IACA,IAAI,EAAE,aAAa,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CACzB,GACD;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzC;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC/B,MAAM,CAAC,EAAE,WAAW,CAAC;IAErB,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C,MAAM,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;CAC/B;AAED,uEAAuE;AACvE,MAAM,MAAM,uBAAuB,GAAG,eAAe,GAAG;IAAE,MAAM,EAAE,WAAW,CAAA;CAAE,CAAC;AAEhF;;;GAGG;AACH,MAAM,WAAW,UAAU;IAC1B,8CAA8C;IAC9C,IAAI,EAAE,MAAM,CAAC;IAEb,qFAAqF;IACrF,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB,8EAA8E;IAC9E,KAAK,CAAC,CAAC,WAAW,EAAE,uBAAuB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAExE;;;;OAIG;IACH,KAAK,CAAC,CAAC,KAAK,EAAE;QACb,GAAG,EAAE,WAAW,CAAC;QACjB,UAAU,CAAC,EAAE,gBAAgB,CAAC;QAC9B,MAAM,EAAE,WAAW,CAAC;KACpB,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;IAEnC;;;;;OAKG;IACH,OAAO,CAAC,KAAK,EAAE;QACd,GAAG,EAAE,WAAW,CAAC;QACjB,UAAU,CAAC,EAAE,gBAAgB,CAAC;QAC9B,MAAM,EAAE,WAAW,CAAC;KACpB,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;CACpC;AAED;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACzB,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IAEb,oFAAoF;IACpF,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB,6FAA6F;IAC7F,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,KAAK,CAAC,WAAW,EAAE,uBAAuB,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IAEtE;;;OAGG;IACH,OAAO,CAAC,UAAU,EAAE,eAAe,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IAEpF;;;;;OAKG;IACH,KAAK,CAAC,CAAC,KAAK,EAAE;QACb,GAAG,EAAE,WAAW,CAAC;QACjB,UAAU,CAAC,EAAE,eAAe,CAAC;QAC7B,MAAM,EAAE,WAAW,CAAC;KACpB,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;IAEnC;;;;OAIG;IACH,MAAM,CAAC,UAAU,EAAE,eAAe,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;CACxD;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC5B,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,KAAK,CAAC,EAAE,SAAS,CAAC;CAClB"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { ProviderEnv, ProviderHeaders } from \"../types.ts\";\n\n/**\n * Request auth for a single model request. If a value cannot be expressed as\n * `apiKey`, `headers`, or `baseUrl`, it is provider config, not auth.\n */\nexport interface ModelAuth {\n\tapiKey?: string;\n\theaders?: ProviderHeaders;\n\tbaseUrl?: string;\n}\n\n/**\n * Stored api-key credential. `env` holds provider-scoped environment/config\n * values such as Cloudflare account/gateway ids.\n */\nexport interface ApiKeyCredential {\n\ttype: \"api_key\";\n\tkey?: string;\n\tenv?: ProviderEnv;\n}\n\n/** OAuth token data returned by extension compatibility flows. */\nexport interface OAuthCredentials {\n\trefresh: string;\n\taccess: string;\n\texpires: number;\n\t[key: string]: unknown;\n}\n\n/** Stored canonical OAuth credential. */\nexport interface OAuthCredential extends OAuthCredentials {\n\ttype: \"oauth\";\n}\n\n/** One type-tagged credential per provider — the shape of today's auth.json. */\nexport type Credential = ApiKeyCredential | OAuthCredential;\n\n/** Non-secret credential metadata for account/status enumeration. */\nexport interface CredentialInfo {\n\tproviderId: string;\n\ttype: Credential[\"type\"];\n}\n\n/** Optional cancellation for public auth and credential operations. */\nexport interface AuthOperationOptions {\n\tsignal?: AbortSignal;\n}\n\n/**\n * App-owned credential storage, keyed by `Provider.id`, one credential per\n * provider. `modify` is the only write path, so every mutation is a\n * serialized read-modify-write; `Models.getAuth()` runs OAuth refresh inside\n * `modify` so concurrent requests cannot double-refresh a rotated token. The\n * app persists a credential after login via\n * `modify(provider.id, async () => credential)`. Login/logout orchestration\n * is app-owned.\n *\n * Error semantics: `read` resolves `undefined` for missing entries. Methods\n * reject only on storage failure; `Models` wraps such rejections in\n * `ModelsError` with code \"auth\". Best-effort stores that serve an in-memory\n * view and record persistence errors internally (like coding-agent's\n * AuthStorage) are valid implementations.\n */\nexport interface CredentialStore {\n\t/**\n\t * Read the stored credential, possibly expired. Display/status use;\n\t * resolved request auth comes from `Models.getAuth()`.\n\t */\n\tread(providerId: string, options?: AuthOperationOptions): Promise<Credential | undefined>;\n\n\t/**\n\t * List stored credential metadata without resolving or exposing secrets.\n\t * Implementations must not execute configured API-key commands while listing.\n\t */\n\tlist(options?: AuthOperationOptions): Promise<readonly CredentialInfo[]>;\n\n\t/**\n\t * Serialized write — the only write path. `fn` sees the current credential\n\t * because correct writes (refresh, login-during-refresh) depend on it;\n\t * return the new credential, or undefined to leave the entry unchanged.\n\t * Mutual exclusion per provider id, cross-process too where the backing\n\t * store supports it (e.g. a file lock). Resolves with the post-write\n\t * credential. Rejections from `fn` propagate.\n\t */\n\tmodify(\n\t\tproviderId: string,\n\t\tfn: (current: Credential | undefined) => Promise<Credential | undefined>,\n\t\toptions?: AuthOperationOptions,\n\t): Promise<Credential | undefined>;\n\n\t/** Remove a credential (logout). Implementations serialize this against `modify`. */\n\tdelete(providerId: string, options?: AuthOperationOptions): Promise<void>;\n}\n\n/** Environment access for auth resolution. Injectable for tests and browsers. */\nexport interface AuthContext {\n\tenv(name: string): Promise<string | undefined>;\n\t/** Check whether a file exists. Supports a leading `~`. Always false in browsers. */\n\tfileExists(path: string): Promise<boolean>;\n}\n\n/** Result of resolving auth for a model. */\nexport interface AuthResult {\n\tauth: ModelAuth;\n\t/** Provider-scoped environment/config values resolved from credentials and ambient context. */\n\tenv?: ProviderEnv;\n\t/** Human-readable label for status UI: \"ANTHROPIC_API_KEY\", \"OAuth\", \"~/.aws/credentials\". */\n\tsource?: string;\n}\n\nexport interface AuthCheck {\n\tsource?: string;\n\ttype: \"api_key\" | \"oauth\";\n}\n\nexport type AuthType = \"api_key\" | \"oauth\";\n\n/**\n * Prompt shown to the user during login. `signal` lets the flow cancel a\n * pending prompt when an out-of-band event resolves the step, e.g. a\n * `manual_code` prompt raced against a callback server, aborted when the\n * callback wins.\n */\nexport type AuthPrompt = { signal?: AbortSignal } & (\n\t| { type: \"text\"; message: string; placeholder?: string }\n\t| { type: \"secret\"; message: string; placeholder?: string }\n\t| { type: \"select\"; message: string; options: readonly { id: string; label: string; description?: string }[] }\n\t| { type: \"manual_code\"; message: string; placeholder?: string }\n);\n\nexport interface AuthInfoLink {\n\turl: string;\n\tlabel?: string;\n}\n\nexport type AuthEvent =\n\t| { type: \"info\"; message: string; links?: readonly AuthInfoLink[] }\n\t| { type: \"auth_url\"; url: string; instructions?: string }\n\t| {\n\t\t\ttype: \"device_code\";\n\t\t\tuserCode: string;\n\t\t\tverificationUri: string;\n\t\t\tintervalSeconds?: number;\n\t\t\texpiresInSeconds?: number;\n\t }\n\t| { type: \"progress\"; message: string };\n\n/**\n * Login interaction callbacks serving both api-key and OAuth flows.\n *\n * `prompt()` returns the entered/selected string (`select` returns the option\n * id). Rejects on cancel/abort. `signal` aborts the whole login flow;\n * per-prompt cancellation uses `AuthPrompt.signal`.\n */\nexport interface AuthInteraction {\n\tsignal?: AbortSignal;\n\n\tprompt(prompt: AuthPrompt): Promise<string>;\n\tnotify(event: AuthEvent): void;\n}\n\n/** Normalized interaction passed to provider login implementations. */\nexport type ProviderAuthInteraction = AuthInteraction & { signal: AbortSignal };\n\n/**\n * Api-key auth: stored key/provider env plus ambient sources (env vars, AWS\n * profiles, ADC files). Ambient-only providers omit `login`.\n */\nexport interface ApiKeyAuth {\n\t/** Display name, e.g. \"Anthropic API key\". */\n\tname: string;\n\n\t/** Ambient compatibility adapter that must not outrank a stored OAuth credential. */\n\tambientOnly?: boolean;\n\n\t/** Interactive setup (prompt for key/provider env). Absent = ambient-only. */\n\tlogin?(interaction: ProviderAuthInteraction): Promise<ApiKeyCredential>;\n\n\t/**\n\t * Optional side-effect-free availability check. Use this when `resolve()` may\n\t * execute commands or perform other request-time work. Missing means Models\n\t * checks availability by resolving auth.\n\t */\n\tcheck?(input: {\n\t\tctx: AuthContext;\n\t\tcredential?: ApiKeyCredential;\n\t\tsignal: AbortSignal;\n\t}): Promise<AuthCheck | undefined>;\n\n\t/**\n\t * Resolve auth from the stored credential and/or ambient sources, merging\n\t * per field (`credential.key ?? env(\"...\")`, `credential.env?.NAME ?? env(\"...\")`).\n\t * undefined = not configured. Resolution is provider-scoped; model-specific\n\t * endpoint preparation happens after auth has been resolved.\n\t */\n\tresolve(input: {\n\t\tctx: AuthContext;\n\t\tcredential?: ApiKeyCredential;\n\t\tsignal: AbortSignal;\n\t}): Promise<AuthResult | undefined>;\n}\n\n/**\n * OAuth auth. The `refresh`/`toAuth` split lets `Models` own the locked\n * refresh pattern: `refresh` produces a credential, `toAuth` derives request\n * auth from whatever credential ends up stored.\n */\nexport interface OAuthAuth {\n\t/** Display name, e.g. \"Anthropic (Claude Pro/Max)\". */\n\tname: string;\n\n\t/** Whether access through this auth method is backed by a provider subscription. */\n\tisSubscription?: boolean;\n\n\t/** Selector label for the OAuth login option, e.g. \"Sign in with SuperGrok or X Premium\". */\n\tloginLabel?: string;\n\n\tlogin(interaction: ProviderAuthInteraction): Promise<OAuthCredential>;\n\n\t/**\n\t * Exchange the refresh token. Network call; throws on failure\n\t * (invalid_grant etc.). `Models` runs this under the store lock.\n\t */\n\trefresh(credential: OAuthCredential, signal: AbortSignal): Promise<OAuthCredential>;\n\n\t/**\n\t * Optional side-effect-free availability check, mirroring `ApiKeyAuth.check`.\n\t * Supply this when a stored OAuth credential does not by itself imply the\n\t * provider is usable — for example a sentinel envelope that carries zero\n\t * accounts. When absent, any stored OAuth credential counts as configured.\n\t */\n\tcheck?(input: {\n\t\tctx: AuthContext;\n\t\tcredential?: OAuthCredential;\n\t\tsignal: AbortSignal;\n\t}): Promise<AuthCheck | undefined>;\n\n\t/**\n\t * Side-effect-free derivation of request auth from a valid credential.\n\t * Covers per-credential baseUrl (GitHub Copilot). Async so lazy wrappers\n\t * can load the implementation on first use.\n\t */\n\ttoAuth(credential: OAuthCredential): Promise<ModelAuth>;\n}\n\n/**\n * Provider auth. At least one of `apiKey`/`oauth` must be present: even\n * ambient-credential providers and keyless local servers provide `apiKey`\n * auth whose `resolve()` reports whether the provider is configured.\n */\nexport interface ProviderAuth {\n\tapiKey?: ApiKeyAuth;\n\toauth?: OAuthAuth;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { ProviderEnv, ProviderHeaders } from \"../types.ts\";\n\n/**\n * Request auth for a single model request. If a value cannot be expressed as\n * `apiKey`, `headers`, or `baseUrl`, it is provider config, not auth.\n */\nexport interface ModelAuth {\n\tapiKey?: string;\n\theaders?: ProviderHeaders;\n\tbaseUrl?: string;\n}\n\n/**\n * Stored api-key credential. `env` holds provider-scoped environment/config\n * values such as Cloudflare account/gateway ids.\n */\nexport interface ApiKeyCredential {\n\ttype: \"api_key\";\n\tkey?: string;\n\tenv?: ProviderEnv;\n}\n\n/** OAuth token data returned by extension compatibility flows. */\nexport interface OAuthCredentials {\n\trefresh: string;\n\taccess: string;\n\texpires: number;\n\t[key: string]: unknown;\n}\n\n/** Stored canonical OAuth credential. */\nexport interface OAuthCredential extends OAuthCredentials {\n\ttype: \"oauth\";\n}\n\n/** One type-tagged credential per provider — the shape of today's auth.json. */\nexport type Credential = ApiKeyCredential | OAuthCredential;\n\n/** Non-secret credential metadata for account/status enumeration. */\nexport interface CredentialInfo {\n\tproviderId: string;\n\ttype: Credential[\"type\"];\n}\n\n/** Optional cancellation for public auth and credential operations. */\nexport interface AuthOperationOptions {\n\tsignal?: AbortSignal;\n}\n\n/**\n * App-owned credential storage, keyed by `Provider.id`, one entry per\n * provider; an entry may pool sibling slots under `accounts` while its flat\n * fields remain a valid credential. `modify` is the only write path, so every mutation is a\n * serialized read-modify-write; `Models.getAuth()` runs OAuth refresh inside\n * `modify` so concurrent requests cannot double-refresh a rotated token. The\n * app persists a credential after login via\n * `modify(provider.id, async () => credential)`. Login/logout orchestration\n * is app-owned.\n *\n * Error semantics: `read` resolves `undefined` for missing entries. Methods\n * reject only on storage failure; `Models` wraps such rejections in\n * `ModelsError` with code \"auth\". Best-effort stores that serve an in-memory\n * view and record persistence errors internally (like coding-agent's\n * AuthStorage) are valid implementations.\n */\nexport interface CredentialStore {\n\t/**\n\t * Read the stored credential, possibly expired. Display/status use;\n\t * resolved request auth comes from `Models.getAuth()`.\n\t */\n\tread(providerId: string, options?: AuthOperationOptions): Promise<Credential | undefined>;\n\n\t/**\n\t * List stored credential metadata without resolving or exposing secrets.\n\t * Implementations must not execute configured API-key commands while listing.\n\t */\n\tlist(options?: AuthOperationOptions): Promise<readonly CredentialInfo[]>;\n\n\t/**\n\t * Serialized write — the only write path. `fn` sees the current credential\n\t * because correct writes (refresh, login-during-refresh) depend on it;\n\t * return the new credential, or undefined to leave the entry unchanged.\n\t * Mutual exclusion per provider id, cross-process too where the backing\n\t * store supports it (e.g. a file lock). Resolves with the post-write\n\t * credential. Rejections from `fn` propagate.\n\t */\n\tmodify(\n\t\tproviderId: string,\n\t\tfn: (current: Credential | undefined) => Promise<Credential | undefined>,\n\t\toptions?: AuthOperationOptions,\n\t): Promise<Credential | undefined>;\n\n\t/** Remove a credential (logout). Implementations serialize this against `modify`. */\n\tdelete(providerId: string, options?: AuthOperationOptions): Promise<void>;\n}\n\n/** Environment access for auth resolution. Injectable for tests and browsers. */\nexport interface AuthContext {\n\tenv(name: string): Promise<string | undefined>;\n\t/** Check whether a file exists. Supports a leading `~`. Always false in browsers. */\n\tfileExists(path: string): Promise<boolean>;\n}\n\n/** Result of resolving auth for a model. */\nexport interface AuthResult {\n\tauth: ModelAuth;\n\t/** Provider-scoped environment/config values resolved from credentials and ambient context. */\n\tenv?: ProviderEnv;\n\t/** Human-readable label for status UI: \"ANTHROPIC_API_KEY\", \"OAuth\", \"~/.aws/credentials\". */\n\tsource?: string;\n}\n\nexport interface AuthCheck {\n\tsource?: string;\n\ttype: \"api_key\" | \"oauth\";\n}\n\nexport type AuthType = \"api_key\" | \"oauth\";\n\n/**\n * Prompt shown to the user during login. `signal` lets the flow cancel a\n * pending prompt when an out-of-band event resolves the step, e.g. a\n * `manual_code` prompt raced against a callback server, aborted when the\n * callback wins.\n */\nexport type AuthPrompt = { signal?: AbortSignal } & (\n\t| { type: \"text\"; message: string; placeholder?: string }\n\t| { type: \"secret\"; message: string; placeholder?: string }\n\t| { type: \"select\"; message: string; options: readonly { id: string; label: string; description?: string }[] }\n\t| { type: \"manual_code\"; message: string; placeholder?: string }\n);\n\nexport interface AuthInfoLink {\n\turl: string;\n\tlabel?: string;\n}\n\nexport type AuthEvent =\n\t| { type: \"info\"; message: string; links?: readonly AuthInfoLink[] }\n\t| { type: \"auth_url\"; url: string; instructions?: string }\n\t| {\n\t\t\ttype: \"device_code\";\n\t\t\tuserCode: string;\n\t\t\tverificationUri: string;\n\t\t\tintervalSeconds?: number;\n\t\t\texpiresInSeconds?: number;\n\t }\n\t| { type: \"progress\"; message: string };\n\n/**\n * Login interaction callbacks serving both api-key and OAuth flows.\n *\n * `prompt()` returns the entered/selected string (`select` returns the option\n * id). Rejects on cancel/abort. `signal` aborts the whole login flow;\n * per-prompt cancellation uses `AuthPrompt.signal`.\n */\nexport interface AuthInteraction {\n\tsignal?: AbortSignal;\n\n\tprompt(prompt: AuthPrompt): Promise<string>;\n\tnotify(event: AuthEvent): void;\n}\n\n/** Normalized interaction passed to provider login implementations. */\nexport type ProviderAuthInteraction = AuthInteraction & { signal: AbortSignal };\n\n/**\n * Api-key auth: stored key/provider env plus ambient sources (env vars, AWS\n * profiles, ADC files). Ambient-only providers omit `login`.\n */\nexport interface ApiKeyAuth {\n\t/** Display name, e.g. \"Anthropic API key\". */\n\tname: string;\n\n\t/** Ambient compatibility adapter that must not outrank a stored OAuth credential. */\n\tambientOnly?: boolean;\n\n\t/** Interactive setup (prompt for key/provider env). Absent = ambient-only. */\n\tlogin?(interaction: ProviderAuthInteraction): Promise<ApiKeyCredential>;\n\n\t/**\n\t * Optional side-effect-free availability check. Use this when `resolve()` may\n\t * execute commands or perform other request-time work. Missing means Models\n\t * checks availability by resolving auth.\n\t */\n\tcheck?(input: {\n\t\tctx: AuthContext;\n\t\tcredential?: ApiKeyCredential;\n\t\tsignal: AbortSignal;\n\t}): Promise<AuthCheck | undefined>;\n\n\t/**\n\t * Resolve auth from the stored credential and/or ambient sources, merging\n\t * per field (`credential.key ?? env(\"...\")`, `credential.env?.NAME ?? env(\"...\")`).\n\t * undefined = not configured. Resolution is provider-scoped; model-specific\n\t * endpoint preparation happens after auth has been resolved.\n\t */\n\tresolve(input: {\n\t\tctx: AuthContext;\n\t\tcredential?: ApiKeyCredential;\n\t\tsignal: AbortSignal;\n\t}): Promise<AuthResult | undefined>;\n}\n\n/**\n * OAuth auth. The `refresh`/`toAuth` split lets `Models` own the locked\n * refresh pattern: `refresh` produces a credential, `toAuth` derives request\n * auth from whatever credential ends up stored.\n */\nexport interface OAuthAuth {\n\t/** Display name, e.g. \"Anthropic (Claude Pro/Max)\". */\n\tname: string;\n\n\t/** Whether access through this auth method is backed by a provider subscription. */\n\tisSubscription?: boolean;\n\n\t/** Selector label for the OAuth login option, e.g. \"Sign in with SuperGrok or X Premium\". */\n\tloginLabel?: string;\n\n\tlogin(interaction: ProviderAuthInteraction): Promise<OAuthCredential>;\n\n\t/**\n\t * Exchange the refresh token. Network call; throws on failure\n\t * (invalid_grant etc.). `Models` runs this under the store lock.\n\t */\n\trefresh(credential: OAuthCredential, signal: AbortSignal): Promise<OAuthCredential>;\n\n\t/**\n\t * Optional side-effect-free availability check, mirroring `ApiKeyAuth.check`.\n\t * Supply this when a stored OAuth credential does not by itself imply the\n\t * provider is usable — for example a sentinel envelope that carries zero\n\t * accounts. When absent, any stored OAuth credential counts as configured.\n\t */\n\tcheck?(input: {\n\t\tctx: AuthContext;\n\t\tcredential?: OAuthCredential;\n\t\tsignal: AbortSignal;\n\t}): Promise<AuthCheck | undefined>;\n\n\t/**\n\t * Side-effect-free derivation of request auth from a valid credential.\n\t * Covers per-credential baseUrl (GitHub Copilot). Async so lazy wrappers\n\t * can load the implementation on first use.\n\t */\n\ttoAuth(credential: OAuthCredential): Promise<ModelAuth>;\n}\n\n/**\n * Provider auth. At least one of `apiKey`/`oauth` must be present: even\n * ambient-credential providers and keyless local servers provide `apiKey`\n * auth whose `resolve()` reports whether the provider is configured.\n */\nexport interface ProviderAuth {\n\tapiKey?: ApiKeyAuth;\n\toauth?: OAuthAuth;\n}\n"]}
@@ -1 +1 @@
1
- {"schemaVersion":3,"generatedAt":"2026-08-27T08:16:35.016Z","structureHash":"29b0db0752c5e09bcafff27967ded4cfacf086f62a1078e552ec01dea62598b4","files":{"alibaba-token-plan.json":"f50ed32b9cbf506cec10fea687e629a96d48faef751c20bfbc5cba95eae0a824","amazon-bedrock.json":"ae73999e8fffa9dc1683f0c94c8648f6d48d0a3d6d519a3d28886e903a8325e0","ant-ling.json":"4979fe79d99ed97382d7ce40170c6132e932e77906de1eb54464c042e7d63633","anthropic.json":"8c1136a83a3b1ff0e61ab461ee221b1de7680784e774a60e1520af14a44bb0f1","azure-openai-responses.json":"37d12c5cbfc29bfd9a802a0516f5d3209320bd4aa8ef9cd7c219af208244afa3","baseten.json":"13e74fc464f37293aef8c56a4aa908448598913abbdd9393527f02dad1418e62","cerebras.json":"38272a7525d6680c71bb4bb3c4085e871768b400832e2013b0e7fd92f8fd4f05","cloudflare-ai-gateway.json":"5a3251ef587da66da49d0bd9e3557f8d2dd597f53bc5ab7b456b87e7667e19b1","cloudflare-workers-ai.json":"ebdb4faeacc7d77e701fb02d068512c5e620792fa5204dc37d376f5f0c6fbf70","deepseek.json":"e3106724723fd82d48a3ff685da9908a3a7b7b4fd84cc3cfe97a6a23067b6029","fireworks.json":"2c85d89cd04288b15ff8a23af5eba72779cae9221f4bcfed1720ce6d41629fcc","github-copilot.json":"b89b04b844bdae6c794d63ba159dfd01c3954ddb550ecb76e1a50c7802f1f63d","google-vertex.json":"fb7586fc955da7b7d7d11d641954f496fbbb42cf3e4cbba66d7116ea3b37d5ed","google.json":"b5572904165d37ab594eafc3ab7f29774e35747b5dd211144ec01532db9217c1","groq.json":"f1eb899453e70b5e4479fe6eb78869ee99121fa6d4a019a5a05ab42d2ada8992","huggingface.json":"e39ede613cf4585a053a8c9fd215ab5f963796d60782ad26b2df9300d0523ab4","kimi-coding.json":"88150f8970f83e17968b02f3b33fac803b96ebf1474e76437689b7d0f1b69363","minimax-cn.json":"65d37e55a6d9585855f94b3fb7739308d107fe248ebd9e1001d1c5d4606ad2c4","minimax.json":"c7dc5765995ae77242916430929c7cc9a782589f7e483e13f7e01663190d028e","mistral.json":"e3a109306644bf2f2fa38fece50b2d3ce1dbe3b87b1f1b9e2d70cce7eb5c0ea1","moonshotai-cn.json":"dbf1b71ee36812fe64b014177ff455809a8dd852bbbd584422645beb85635127","moonshotai.json":"2d7518b4769e97ac900366175c8b60ff86a02675bb6f6cc2fffcc6761fda6faa","nvidia.json":"692d2a610e5ee1c5513c559a0eb49925cef079b0b061460768e94f7ff9659dcc","openai-codex.json":"bcf30d89ae124004ed3b0d38958faa46674c7531f531f4f5588992d6354b291d","openai.json":"9400053a1f5968768ec3ee3e40ea6aa4f62c376cf98a059017df0344d21e2e59","opencode-go.json":"be63da6351f54b4cf88397ee96fe39fabda6809214a72a6b3f50205e147b473c","opencode.json":"97e196d19dfd5c972dd8ac0ef425761fde850f647bcbd3b247f110c760485c3f","opengateway.json":"1702a5df9877110c4d71a6ff3760cd10b378bfbd32d6322c05ce59dc1cc0f8e4","openrouter.json":"db1ec99980457f24fac6a22356242a37feb8ae181c8bc936c250dad0b97c4d7c","qwen-token-plan-cn.json":"700cb41cdee4c0ae2a5159eb3ab43f4cedc9d43e87c6fd1bcd410d71431f9856","qwen-token-plan-individual.json":"5649fd4075ada766ec65a7a162cd65f096a7ecc29960ace04b2e6a6a4a995a41","qwen-token-plan.json":"f85715f7f2023a162c47d1a84ba73747e2580d0a9aa33799b3232ce19527c1ab","together.json":"f7c9ba0441c1cbb8af41aaea3cfaa12559e1235a7335898e705d5918dc308c97","vercel-ai-gateway.json":"0173d5b9ee473efd2c8f8976653340761c7845b745f3a67afb13b16b90ecdaae","xai.json":"9973aae022723732b8a7ea12107e6fb8b3f1d0e087ec6bbc2ee18f0820595e19","xiaomi-token-plan-ams.json":"568b9992cf320536a65826e26a414afa5c0d17f083a01af4bd96658d9dd3e705","xiaomi-token-plan-cn.json":"c423857d0bbb0b126394eaf1ebb2a91bf2d1193cc5a4fe77843ff0f4536a0a80","xiaomi-token-plan-sgp.json":"008f1eb41037e93c5ae478f12815cd67bac1978f131ffefa602775bb60b63fea","xiaomi.json":"37acf451bb4364bdca2ecea6b7d962590d9974a87e80cfe34bb800be6a95c13b","zai-coding-cn.json":"b3fe0a69833cb573ee73fa4ed3f620732b3193fc32f5433d2fa9971c2f5ce299","zai.json":"6634870e983bdae76dddbf2e721e972fbc4b5974467b4b99edaab5bd9c1c1e3f"}}
1
+ {"schemaVersion":3,"generatedAt":"2026-08-28T04:47:27.504Z","structureHash":"5bb4a74acb1571e6d5e8cbbeff36369f200a78449b05c3ee68e5b6d49755ab5e","files":{"alibaba-token-plan.json":"9f9e8f88b1faa2e4134a0d8bcda600531d4d044d64b7ec3d2373f1db46dcf452","amazon-bedrock.json":"ae73999e8fffa9dc1683f0c94c8648f6d48d0a3d6d519a3d28886e903a8325e0","ant-ling.json":"4979fe79d99ed97382d7ce40170c6132e932e77906de1eb54464c042e7d63633","anthropic.json":"8c1136a83a3b1ff0e61ab461ee221b1de7680784e774a60e1520af14a44bb0f1","azure-openai-responses.json":"37d12c5cbfc29bfd9a802a0516f5d3209320bd4aa8ef9cd7c219af208244afa3","baseten.json":"13e74fc464f37293aef8c56a4aa908448598913abbdd9393527f02dad1418e62","cerebras.json":"38272a7525d6680c71bb4bb3c4085e871768b400832e2013b0e7fd92f8fd4f05","cloudflare-ai-gateway.json":"5a3251ef587da66da49d0bd9e3557f8d2dd597f53bc5ab7b456b87e7667e19b1","cloudflare-workers-ai.json":"ebdb4faeacc7d77e701fb02d068512c5e620792fa5204dc37d376f5f0c6fbf70","deepseek.json":"e3106724723fd82d48a3ff685da9908a3a7b7b4fd84cc3cfe97a6a23067b6029","fireworks.json":"f1d0e31cd57167e24be469fff31929ec18ec6eb6a761295832282b056264d9f2","github-copilot.json":"61dec9e46df61a9b0bf6c7618651f97bfa9ae609d4c216b5725f014942ca3001","google-vertex.json":"fb7586fc955da7b7d7d11d641954f496fbbb42cf3e4cbba66d7116ea3b37d5ed","google.json":"b5572904165d37ab594eafc3ab7f29774e35747b5dd211144ec01532db9217c1","groq.json":"f1eb899453e70b5e4479fe6eb78869ee99121fa6d4a019a5a05ab42d2ada8992","huggingface.json":"e39ede613cf4585a053a8c9fd215ab5f963796d60782ad26b2df9300d0523ab4","kimi-coding.json":"88150f8970f83e17968b02f3b33fac803b96ebf1474e76437689b7d0f1b69363","minimax-cn.json":"65d37e55a6d9585855f94b3fb7739308d107fe248ebd9e1001d1c5d4606ad2c4","minimax.json":"c7dc5765995ae77242916430929c7cc9a782589f7e483e13f7e01663190d028e","mistral.json":"e3a109306644bf2f2fa38fece50b2d3ce1dbe3b87b1f1b9e2d70cce7eb5c0ea1","moonshotai-cn.json":"dbf1b71ee36812fe64b014177ff455809a8dd852bbbd584422645beb85635127","moonshotai.json":"2d7518b4769e97ac900366175c8b60ff86a02675bb6f6cc2fffcc6761fda6faa","nvidia.json":"8456358498bb363f23ee735992d9a7eb7344a81c251b772d702cb58b2494da94","openai-codex.json":"4e4afe2929b2b20a751f2453b219deae4e5b9fd85e147bd0403601f183cfc15f","openai.json":"b014fb0676fec97264eb13b367b0ed73b99915f45410a3dd9a7397a0360c2a4b","opencode-go.json":"be63da6351f54b4cf88397ee96fe39fabda6809214a72a6b3f50205e147b473c","opencode.json":"97e196d19dfd5c972dd8ac0ef425761fde850f647bcbd3b247f110c760485c3f","opengateway.json":"1702a5df9877110c4d71a6ff3760cd10b378bfbd32d6322c05ce59dc1cc0f8e4","openrouter.json":"958eb80c4e8de049a286830609614c8af3df13c7ee5fbc0450d68292aa3f8077","qwen-token-plan-cn.json":"e62dde34edb603376a1dc60b2a74a9c2605b9e81d81df55cc259796c45aa4793","qwen-token-plan-individual.json":"5649fd4075ada766ec65a7a162cd65f096a7ecc29960ace04b2e6a6a4a995a41","qwen-token-plan.json":"fe914313157ff41ab2f71977f0fdcfedb3a8a205d1092e3180f6799e5d7942fd","together.json":"c2b03c476d6b4d4059ed18a80f34d274c754dc84fe2591ae79fe2986512f2a51","vercel-ai-gateway.json":"2eb686c1d98a4573cf3d394a490c159303346bf704ffb10475202a7f27429749","xai.json":"9973aae022723732b8a7ea12107e6fb8b3f1d0e087ec6bbc2ee18f0820595e19","xiaomi-token-plan-ams.json":"568b9992cf320536a65826e26a414afa5c0d17f083a01af4bd96658d9dd3e705","xiaomi-token-plan-cn.json":"c423857d0bbb0b126394eaf1ebb2a91bf2d1193cc5a4fe77843ff0f4536a0a80","xiaomi-token-plan-sgp.json":"008f1eb41037e93c5ae478f12815cd67bac1978f131ffefa602775bb60b63fea","xiaomi.json":"37acf451bb4364bdca2ecea6b7d962590d9974a87e80cfe34bb800be6a95c13b","zai-coding-cn.json":"b3fe0a69833cb573ee73fa4ed3f620732b3193fc32f5433d2fa9971c2f5ce299","zai.json":"6634870e983bdae76dddbf2e721e972fbc4b5974467b4b99edaab5bd9c1c1e3f"}}
@@ -1 +1 @@
1
- {"openai-completions":{"MiniMax-M2.5":{"id":"MiniMax-M2.5","name":"MiniMax-M2.5","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":196608,"maxTokens":32768},"deepseek-v3.2":{"id":"deepseek-v3.2","name":"DeepSeek V3.2","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":131072,"maxTokens":65536},"deepseek-v4-flash":{"id":"deepseek-v4-flash","name":"DeepSeek V4 Flash","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":1000000,"maxTokens":384000,"thinkingLevelMap":{"minimal":null,"low":null,"medium":null,"high":"high","max":"max"}},"deepseek-v4-flash-0731":{"id":"deepseek-v4-flash-0731","name":"DeepSeek V4 Flash 0731","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":1000000,"maxTokens":384000,"thinkingLevelMap":{"minimal":null,"low":null,"medium":null,"high":"high","max":"max"}},"deepseek-v4-pro":{"id":"deepseek-v4-pro","name":"DeepSeek V4 Pro","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":1000000,"maxTokens":384000,"thinkingLevelMap":{"minimal":null,"low":null,"medium":null,"high":"high","max":"max"}},"deepseek-v4-pro-0813":{"id":"deepseek-v4-pro-0813","name":"DeepSeek V4 Pro 0813","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":1000000,"maxTokens":384000,"thinkingLevelMap":{"minimal":null,"low":null,"medium":null,"high":"high","max":"max"}},"glm-5":{"id":"glm-5","name":"GLM-5","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":202752,"maxTokens":16384},"glm-5.1":{"id":"glm-5.1","name":"GLM-5.1","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":202752,"maxTokens":128000},"glm-5.2":{"id":"glm-5.2","name":"GLM-5.2","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":1000000,"maxTokens":131072},"kimi-k2.5":{"id":"kimi-k2.5","name":"Kimi K2.5","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","thinkingFormat":"deepseek","supportsReasoningEffort":false},"reasoning":true,"input":["text","image"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":262144,"maxTokens":98304},"kimi-k2.6":{"id":"kimi-k2.6","name":"Kimi K2.6","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","thinkingFormat":"deepseek","supportsReasoningEffort":false},"reasoning":true,"input":["text","image"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":262144,"maxTokens":262144},"kimi-k2.7-code":{"id":"kimi-k2.7-code","name":"Kimi K2.7 Code","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","thinkingFormat":"deepseek","supportsReasoningEffort":false},"reasoning":true,"input":["text","image"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":262144,"maxTokens":262144},"qwen3.6-flash":{"id":"qwen3.6-flash","name":"Qwen3.6 Flash","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","thinkingFormat":"qwen"},"reasoning":true,"input":["text","image"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":1000000,"maxTokens":65536},"qwen3.6-plus":{"id":"qwen3.6-plus","name":"Qwen3.6 Plus","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","thinkingFormat":"qwen"},"reasoning":true,"input":["text","image"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":1000000,"maxTokens":65536},"qwen3.7-max":{"id":"qwen3.7-max","name":"Qwen3.7 Max","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","thinkingFormat":"qwen"},"reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":1000000,"maxTokens":131072},"qwen3.7-plus":{"id":"qwen3.7-plus","name":"Qwen3.7 Plus","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","thinkingFormat":"qwen"},"reasoning":true,"input":["text","image"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":1000000,"maxTokens":65536},"qwen3.8-max":{"id":"qwen3.8-max","name":"Qwen3.8 Max","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","thinkingFormat":"qwen"},"reasoning":true,"input":["text","image"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":1000000,"maxTokens":131072},"qwen3.8-max-preview":{"id":"qwen3.8-max-preview","name":"Qwen3.8 Max Preview","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","thinkingFormat":"qwen"},"reasoning":true,"input":["text","image"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":1000000,"maxTokens":131072}}}
1
+ {"openai-completions":{"MiniMax-M2.5":{"id":"MiniMax-M2.5","name":"MiniMax-M2.5","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":196608,"maxTokens":32768},"deepseek-v3.2":{"id":"deepseek-v3.2","name":"DeepSeek V3.2","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":131072,"maxTokens":65536},"deepseek-v4-flash":{"id":"deepseek-v4-flash","name":"DeepSeek V4 Flash","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":1000000,"maxTokens":384000,"thinkingLevelMap":{"minimal":null,"low":null,"medium":null,"high":"high","max":"max"}},"deepseek-v4-flash-0731":{"id":"deepseek-v4-flash-0731","name":"DeepSeek V4 Flash 0731","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":1000000,"maxTokens":384000,"thinkingLevelMap":{"minimal":null,"low":null,"medium":null,"high":"high","max":"max"}},"deepseek-v4-pro":{"id":"deepseek-v4-pro","name":"DeepSeek V4 Pro","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":1000000,"maxTokens":384000,"thinkingLevelMap":{"minimal":null,"low":null,"medium":null,"high":"high","max":"max"}},"deepseek-v4-pro-0813":{"id":"deepseek-v4-pro-0813","name":"DeepSeek V4 Pro 0813","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":1000000,"maxTokens":384000,"thinkingLevelMap":{"minimal":null,"low":null,"medium":null,"high":"high","max":"max"}},"glm-5":{"id":"glm-5","name":"GLM-5","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":202752,"maxTokens":16384},"glm-5.1":{"id":"glm-5.1","name":"GLM-5.1","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":202752,"maxTokens":128000},"glm-5.2":{"id":"glm-5.2","name":"GLM-5.2","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":1000000,"maxTokens":131072},"kimi-k2.5":{"id":"kimi-k2.5","name":"Kimi K2.5","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","thinkingFormat":"deepseek","supportsReasoningEffort":false},"reasoning":true,"input":["text","image"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":262144,"maxTokens":98304},"kimi-k2.6":{"id":"kimi-k2.6","name":"Kimi K2.6","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","thinkingFormat":"deepseek","supportsReasoningEffort":false},"reasoning":true,"input":["text","image"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":262144,"maxTokens":262144},"kimi-k2.7-code":{"id":"kimi-k2.7-code","name":"Kimi K2.7 Code","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","thinkingFormat":"deepseek","supportsReasoningEffort":false},"reasoning":true,"input":["text","image"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":262144,"maxTokens":262144},"qwen3.6-flash":{"id":"qwen3.6-flash","name":"Qwen3.6 Flash","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","thinkingFormat":"qwen"},"reasoning":true,"input":["text","image"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":1000000,"maxTokens":65536},"qwen3.6-plus":{"id":"qwen3.6-plus","name":"Qwen3.6 Plus","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","thinkingFormat":"qwen"},"reasoning":true,"input":["text","image"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":1000000,"maxTokens":65536},"qwen3.7-max":{"id":"qwen3.7-max","name":"Qwen3.7 Max","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","thinkingFormat":"qwen"},"reasoning":true,"input":["text"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":1000000,"maxTokens":131072},"qwen3.7-plus":{"id":"qwen3.7-plus","name":"Qwen3.7 Plus","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","thinkingFormat":"qwen"},"reasoning":true,"input":["text","image"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":1000000,"maxTokens":65536},"qwen3.8-flash":{"id":"qwen3.8-flash","name":"Qwen3.8 Flash","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","thinkingFormat":"qwen"},"reasoning":true,"input":["text","image"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":1000000,"maxTokens":131072},"qwen3.8-max":{"id":"qwen3.8-max","name":"Qwen3.8 Max","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","thinkingFormat":"qwen"},"reasoning":true,"input":["text","image"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":1000000,"maxTokens":131072},"qwen3.8-max-preview":{"id":"qwen3.8-max-preview","name":"Qwen3.8 Max Preview","api":"openai-completions","provider":"alibaba-token-plan","baseUrl":"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1","compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","thinkingFormat":"qwen"},"reasoning":true,"input":["text","image"],"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0},"contextWindow":1000000,"maxTokens":131072}}}