@code-yeongyu/senpi 2026.9.3-2 → 2026.9.3-3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/dist/core/extensions/builtin/claude-sdk-oauth/auth-lane.d.ts.map +1 -1
  3. package/dist/core/extensions/builtin/claude-sdk-oauth/auth-lane.js +6 -1
  4. package/dist/core/extensions/builtin/claude-sdk-oauth/auth-lane.js.map +1 -1
  5. package/dist/core/extensions/builtin/claude-sdk-oauth/errors.d.ts +1 -1
  6. package/dist/core/extensions/builtin/claude-sdk-oauth/errors.d.ts.map +1 -1
  7. package/dist/core/extensions/builtin/claude-sdk-oauth/errors.js +6 -0
  8. package/dist/core/extensions/builtin/claude-sdk-oauth/errors.js.map +1 -1
  9. package/dist/core/extensions/builtin/claude-sdk-oauth/guidance.d.ts.map +1 -1
  10. package/dist/core/extensions/builtin/claude-sdk-oauth/guidance.js +2 -0
  11. package/dist/core/extensions/builtin/claude-sdk-oauth/guidance.js.map +1 -1
  12. package/dist/core/extensions/builtin/claude-sdk-oauth/session-binding.d.ts +2 -2
  13. package/dist/core/extensions/builtin/claude-sdk-oauth/session-binding.d.ts.map +1 -1
  14. package/dist/core/extensions/builtin/claude-sdk-oauth/session-binding.js +30 -24
  15. package/dist/core/extensions/builtin/claude-sdk-oauth/session-binding.js.map +1 -1
  16. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry-wiring.d.ts.map +1 -1
  17. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry-wiring.js +31 -13
  18. package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry-wiring.js.map +1 -1
  19. package/dist/core/extensions/builtin/claude-sdk-oauth/session-sync.d.ts.map +1 -1
  20. package/dist/core/extensions/builtin/claude-sdk-oauth/session-sync.js +1 -0
  21. package/dist/core/extensions/builtin/claude-sdk-oauth/session-sync.js.map +1 -1
  22. package/dist/core/extensions/builtin/claude-sdk-oauth/stream-protocol.d.ts +1 -1
  23. package/dist/core/extensions/builtin/claude-sdk-oauth/stream-protocol.d.ts.map +1 -1
  24. package/dist/core/extensions/builtin/claude-sdk-oauth/tools.d.ts +11 -3
  25. package/dist/core/extensions/builtin/claude-sdk-oauth/tools.d.ts.map +1 -1
  26. package/dist/core/extensions/builtin/claude-sdk-oauth/tools.js +12 -3
  27. package/dist/core/extensions/builtin/claude-sdk-oauth/tools.js.map +1 -1
  28. package/dist/core/extensions/builtin/gpt-account.d.ts +3 -0
  29. package/dist/core/extensions/builtin/gpt-account.d.ts.map +1 -0
  30. package/dist/core/extensions/builtin/gpt-account.js +115 -0
  31. package/dist/core/extensions/builtin/gpt-account.js.map +1 -0
  32. package/dist/core/extensions/builtin/index.d.ts.map +1 -1
  33. package/dist/core/extensions/builtin/index.js +2 -0
  34. package/dist/core/extensions/builtin/index.js.map +1 -1
  35. package/dist/modes/print-mode.d.ts.map +1 -1
  36. package/dist/modes/print-mode.js +9 -0
  37. package/dist/modes/print-mode.js.map +1 -1
  38. package/dist/modes/rpc/connection-handler.d.ts +2 -0
  39. package/dist/modes/rpc/connection-handler.d.ts.map +1 -1
  40. package/dist/modes/rpc/connection-handler.js +58 -2
  41. package/dist/modes/rpc/connection-handler.js.map +1 -1
  42. package/dist/modes/rpc/custom-capability.d.ts +5 -0
  43. package/dist/modes/rpc/custom-capability.d.ts.map +1 -1
  44. package/dist/modes/rpc/custom-capability.js +5 -0
  45. package/dist/modes/rpc/custom-capability.js.map +1 -1
  46. package/dist/modes/rpc/media-placeholders.d.ts +49 -0
  47. package/dist/modes/rpc/media-placeholders.d.ts.map +1 -0
  48. package/dist/modes/rpc/media-placeholders.js +151 -0
  49. package/dist/modes/rpc/media-placeholders.js.map +1 -0
  50. package/dist/modes/rpc/multi-session-host.js +3 -0
  51. package/dist/modes/rpc/multi-session-host.js.map +1 -1
  52. package/dist/modes/rpc/rpc-client.d.ts +8 -0
  53. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  54. package/dist/modes/rpc/rpc-client.js +11 -0
  55. package/dist/modes/rpc/rpc-client.js.map +1 -1
  56. package/dist/modes/rpc/rpc-types.d.ts +23 -1
  57. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  58. package/dist/modes/rpc/rpc-types.js +1 -0
  59. package/dist/modes/rpc/rpc-types.js.map +1 -1
  60. package/dist/modes/rpc/session-command-router.d.ts.map +1 -1
  61. package/dist/modes/rpc/session-command-router.js +2 -1
  62. package/dist/modes/rpc/session-command-router.js.map +1 -1
  63. package/dist/modes/rpc/session-event-fanout.d.ts +13 -2
  64. package/dist/modes/rpc/session-event-fanout.d.ts.map +1 -1
  65. package/dist/modes/rpc/session-event-fanout.js +36 -12
  66. package/dist/modes/rpc/session-event-fanout.js.map +1 -1
  67. package/dist/modes/rpc/session-event-writer.d.ts +3 -1
  68. package/dist/modes/rpc/session-event-writer.d.ts.map +1 -1
  69. package/dist/modes/rpc/session-event-writer.js +23 -13
  70. package/dist/modes/rpc/session-event-writer.js.map +1 -1
  71. package/dist/modes/rpc/socket-event-fanout.d.ts +8 -1
  72. package/dist/modes/rpc/socket-event-fanout.d.ts.map +1 -1
  73. package/dist/modes/rpc/socket-event-fanout.js +32 -9
  74. package/dist/modes/rpc/socket-event-fanout.js.map +1 -1
  75. package/docs/rpc.md +73 -0
  76. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +12 -0
  77. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  78. package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
  79. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.d.ts +11 -3
  80. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.d.ts.map +1 -1
  81. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.js +32 -6
  82. package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.js.map +1 -1
  83. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  84. package/node_modules/@earendil-works/pi-ai/dist/providers/data/nvidia.json +1 -1
  85. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  86. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  87. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  88. package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
  89. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  90. package/package.json +7 -7
package/CHANGELOG.md CHANGED
@@ -20,6 +20,37 @@
20
20
 
21
21
  ### Removed
22
22
 
23
+ ## [2026.9.3-3] - 2026-09-03
24
+
25
+ ### Added
26
+
27
+ - `/gpt-account` manages OpenAI Codex OAuth accounts the way `/claude-account` manages claude-sdk-oauth ones: `add` runs an interactive Codex login and stores the new account beside the existing ones, `remove <name>`, `pin <name>` and `unpin` select which account is used, and the bare command lists every stored account with its source, availability and pin state without printing token material.
28
+ - RPC clients that send `media_placeholders` in `set_client_info` now receive inline tool-result images as `image_ref` placeholders shaped with `mimeType`, `byteLength` and a `{ toolCallId, contentIndex }` reference, and can retrieve an omitted image through the `get_media` command; default clients remain byte-identical, while classic stdio mode is not covered. This prevented inline image tool results from overflowing a desktop client's socket queue.
29
+
30
+ ### Changed
31
+
32
+ ### Fixed
33
+ - Claude SDK OAuth restart continuity now persists from the compaction-aware active context, survives goal-continuation metadata and a resident entry closing before `message_end`, and therefore avoids flattening and re-sending an oversized full transcript after restart.
34
+
35
+ - Multi-session RPC socket clients no longer lose assistant text when they fall behind: a queued `message_update` snapshot superseded by a newer one is now delivered in its delta-only form instead of being replaced, so `text_delta` streams stay lossless the way the stdout path already was. A stalled omo-desktop reader had lost a 411-character window and rendered a message that started mid-word.
36
+ - A multi-session RPC socket whose per-connection event queue overflows is now closed (after the `overflow` record), instead of being left open while the host silently dropped every later record and command response for it; the client reconnects and resyncs. The overflow is reported to stderr with the queued/incoming/max byte counts and a preview of the offending record, and the default per-connection cap rises from 4 MiB to 64 MiB, which four inline image tool results had exceeded in one burst.
37
+ - `/gpt-account remove` (and every other account-removal path) now leaves the remaining account actually in use. Removing the account the stored credential's top-level fields projected used to keep those fields pointing at the deleted account's tokens, and a provider left with one account does not enter credential rotation, so requests kept authenticating as the removed account; the surviving account's material is now projected onto those fields.
38
+ - Claude SDK OAuth classifies Fable-style "requires usage credits" failures as a non-retryable entitlement instead of a rate limit, so the account is not blocked for 60s and AgentSession can fall through to the next model ([#709](https://github.com/code-yeongyu/senpi/issues/709)).
39
+ - Print mode (`-p` / `--mode json`) now writes a stderr notice when retry fallback substitutes a model, so silent wrong-model answers are visible without corrupting JSON stdout ([oh-my-openagent#7626](https://github.com/code-yeongyu/oh-my-openagent/issues/7626)).
40
+ - Claude SDK OAuth host-tool denial now states that Senpi executes the tool on the host and returns the result as the next user message, so models no longer treat "Do not retry with other tools; end the turn." as a failure ([#784](https://github.com/code-yeongyu/senpi/issues/784), [oh-my-openagent#7115](https://github.com/code-yeongyu/oh-my-openagent/issues/7115)).
41
+ - Claude SDK OAuth no longer falls back to the host `claude` CLI login when a managed lane is selected and its account pool is empty: `oauth-slots` and `config-dir` now fail with `No Claude SDK OAuth accounts configured for the managed lane` instead of silently answering with ambient credentials after `/logout`. The ambient lane (no `tokenInjection` and no stored accounts) is unchanged.
42
+ ### New Features
43
+
44
+ ### Breaking Changes
45
+
46
+ ### Added
47
+
48
+ ### Changed
49
+
50
+ ### Fixed
51
+
52
+ ### Removed
53
+
23
54
  ## [2026.9.3-2] - 2026-09-03
24
55
 
25
56
  ### Added
@@ -1 +1 @@
1
- {"version":3,"file":"auth-lane.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/claude-sdk-oauth/auth-lane.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAM7D,OAAO,EACN,KAAK,WAAW,EAMhB,KAAK,aAAa,EAClB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,KAAK,yBAAyB,EAAyB,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAMlH,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,KAAK,EAAE,8BAA8B,EAAE,4BAA4B,EAAE,MAAM,eAAe,CAAC;AAElG,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAC;AAEvE,eAAO,MAAM,kBAAkB,QAAa,CAAC;AAE7C,KAAK,gBAAgB,GAAG;IACvB,WAAW,EAAE,MAAM,eAAe,CAAC;IACnC,GAAG,EAAE,MAAM,MAAM,CAAC,UAAU,CAAC;IAC7B,WAAW,EAAE,MAAM,MAAM,CAAC;IAC1B,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,SAAS,EAAE,aAAa,CAAC;CACzB,CAAC;AAiBF,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAElF;AAED,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAED,YAAY,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAEnE,MAAM,MAAM,uBAAuB,GAAG;IACrC,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC1C,KAAK,EAAE,QAAQ,CAAC;IAChB,YAAY,EAAE,CAAC,IAAI,EAAE,4BAA4B,KAAK,OAAO,CAAC;IAC9D,gBAAgB,EAAE,8BAA8B,CAAC;IACjD,kGAAkG;IAClG,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0FAA0F;IAC1F,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC;IAChD,aAAa,CAAC,EAAE,CACf,KAAK,EAAE,yBAAyB,KAC5B,iBAAiB,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC,CAAC;CAC5E,CAAC;AAUF,wBAAgB,oBAAoB,CACnC,QAAQ,EAAE,8BAA8B,EACxC,QAAQ,EAAE,SAAS,WAAW,EAAE,GAC9B,4BAA4B,CAE9B;AAkFD,2GAA2G;AAC3G,wBAAuB,iBAAiB,CAAC,KAAK,EAAE,uBAAuB,GAAG,cAAc,CAAC,UAAU,CAAC,CAwDnG"}
1
+ {"version":3,"file":"auth-lane.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/claude-sdk-oauth/auth-lane.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAM7D,OAAO,EACN,KAAK,WAAW,EAMhB,KAAK,aAAa,EAClB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,KAAK,yBAAyB,EAAyB,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAMlH,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,KAAK,EAAE,8BAA8B,EAAE,4BAA4B,EAAE,MAAM,eAAe,CAAC;AAElG,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAC;AAEvE,eAAO,MAAM,kBAAkB,QAAa,CAAC;AAO7C,KAAK,gBAAgB,GAAG;IACvB,WAAW,EAAE,MAAM,eAAe,CAAC;IACnC,GAAG,EAAE,MAAM,MAAM,CAAC,UAAU,CAAC;IAC7B,WAAW,EAAE,MAAM,MAAM,CAAC;IAC1B,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,SAAS,EAAE,aAAa,CAAC;CACzB,CAAC;AAiBF,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAElF;AAED,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAED,YAAY,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAEnE,MAAM,MAAM,uBAAuB,GAAG;IACrC,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC1C,KAAK,EAAE,QAAQ,CAAC;IAChB,YAAY,EAAE,CAAC,IAAI,EAAE,4BAA4B,KAAK,OAAO,CAAC;IAC9D,gBAAgB,EAAE,8BAA8B,CAAC;IACjD,kGAAkG;IAClG,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0FAA0F;IAC1F,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC;IAChD,aAAa,CAAC,EAAE,CACf,KAAK,EAAE,yBAAyB,KAC5B,iBAAiB,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC,CAAC;CAC5E,CAAC;AAUF,wBAAgB,oBAAoB,CACnC,QAAQ,EAAE,8BAA8B,EACxC,QAAQ,EAAE,SAAS,WAAW,EAAE,GAC9B,4BAA4B,CAE9B;AAmFD,2GAA2G;AAC3G,wBAAuB,iBAAiB,CAAC,KAAK,EAAE,uBAAuB,GAAG,cAAc,CAAC,UAAU,CAAC,CAwDnG"}
@@ -13,6 +13,9 @@ import { runFailover } from "./failover.js";
13
13
  import { refusalError } from "./refusal.js";
14
14
  export { CLAUDE_SDK_OAUTH_PROVIDER_ID } from "./account-management.js";
15
15
  export const EXPIRING_WITHIN_MS = 5 * 60_000;
16
+ /** A managed lane with an empty pool must refuse rather than spawn the SDK against ambient host credentials. */
17
+ const NO_MANAGED_ACCOUNTS_ERROR = "authentication_failed: No Claude SDK OAuth accounts configured for the managed lane; " +
18
+ "run /login claude-sdk-oauth or set CLAUDE_CODE_OAUTH_TOKEN";
16
19
  async function refreshWithAnthropicOAuth(refresh, signal) {
17
20
  const oauth = await loadAnthropicOAuth();
18
21
  const credential = await oauth.refresh({ type: "oauth", access: "", refresh, expires: 0 }, signal);
@@ -46,8 +49,10 @@ async function managedPool(settings, requestEnvironment) {
46
49
  }
47
50
  const configuredLane = resolveEffectiveLane(settings, accounts);
48
51
  const lane = configuredLane === "config-dir" && hasRequestOauthToken(requestEnvironment) ? "oauth-slots" : configuredLane;
49
- if (lane === "ambient" || accounts.length === 0)
52
+ if (lane === "ambient")
50
53
  return undefined;
54
+ if (accounts.length === 0)
55
+ throw new Error(NO_MANAGED_ACCOUNTS_ERROR);
51
56
  const stored = credential?.type === "oauth" ? credential : undefined;
52
57
  return { accounts, environment, lane, pinnedAccount: settings.pinnedAccount ?? stored?.pinned, store };
53
58
  }
@@ -1 +1 @@
1
- {"version":3,"file":"auth-lane.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/claude-sdk-oauth/auth-lane.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CredentialStore } from \"@earendil-works/pi-ai\";\nimport { loadAnthropicOAuth } from \"@earendil-works/pi-ai/oauth\";\nimport { getAgentDir } from \"../../../../config.ts\";\nimport { AuthStorage } from \"../../../auth-storage.ts\";\nimport { emitProviderAccountFailover, emitProviderAccountsChanged } from \"./account-events.ts\";\nimport { CLAUDE_SDK_OAUTH_PROVIDER_ID } from \"./account-management.ts\";\nimport {\n\ttype AccountSlot,\n\ttype ClaudeSdkOauthCredential,\n\temptyCredential,\n\tenvSlotToken,\n\tlistAccounts,\n\trefreshSlot,\n\ttype SlotRefresher,\n} from \"./accounts.ts\";\nimport { selectAccount } from \"./affinity.ts\";\nimport { type AuthenticatedAttemptInput, createAttemptMessages, type RetainableAttempt } from \"./auth-attempt.ts\";\nimport { hasRequestOauthToken, mergeRequestAuthEnvironment, stripManagedAuthEnvironment } from \"./auth-environment.ts\";\nimport { writeConfigDirCredential } from \"./config-dir-credentials.ts\";\nimport { classifySdkError, sdkAssistantFailure, sdkResultFailure } from \"./errors.ts\";\nimport { runFailover } from \"./failover.ts\";\nimport { refusalError } from \"./refusal.ts\";\nimport type { Options, SDKMessage, SdkQuery } from \"./sdk-boundary.ts\";\nimport type { ClaudeSdkOauthProviderSettings, ClaudeSdkOauthTokenInjection } from \"./settings.ts\";\n\nexport { CLAUDE_SDK_OAUTH_PROVIDER_ID } from \"./account-management.ts\";\n\nexport const EXPIRING_WITHIN_MS = 5 * 60_000;\n\ntype AuthLaneBoundary = {\n\tcreateStore: () => CredentialStore;\n\tenv: () => NodeJS.ProcessEnv;\n\tgetAgentDir: () => string;\n\tnow: () => number;\n\trefresher: SlotRefresher;\n};\n\nasync function refreshWithAnthropicOAuth(refresh: string, signal: AbortSignal) {\n\tconst oauth = await loadAnthropicOAuth();\n\tconst credential = await oauth.refresh({ type: \"oauth\", access: \"\", refresh, expires: 0 }, signal);\n\treturn { access: credential.access, refresh: credential.refresh, expires: credential.expires };\n}\n\nconst defaultBoundary: AuthLaneBoundary = {\n\tcreateStore: () => AuthStorage.create(),\n\tenv: () => process.env,\n\tgetAgentDir,\n\tnow: () => Date.now(),\n\trefresher: refreshWithAnthropicOAuth,\n};\nlet activeBoundary = defaultBoundary;\n\nexport function overrideAuthLaneBoundary(override: Partial<AuthLaneBoundary>): void {\n\tactiveBoundary = { ...activeBoundary, ...override };\n}\n\nexport function resetAuthLaneBoundary(): void {\n\tactiveBoundary = defaultBoundary;\n}\n\nexport type { AuthenticatedAttemptInput } from \"./auth-attempt.ts\";\n\nexport type AuthenticatedQueryInput = {\n\tprompt: Parameters<SdkQuery>[0][\"prompt\"];\n\tquery: SdkQuery;\n\tbuildOptions: (lane: ClaudeSdkOauthTokenInjection) => Options;\n\tproviderSettings: ClaudeSdkOauthProviderSettings;\n\t/** Effective request auth environment; overrides the host for account discovery and SDK spawn. */\n\tenv?: Record<string, string>;\n\tsignal?: AbortSignal;\n\tsessionId?: string;\n\t/** Request-scoped CLI pin; takes precedence over persistent settings and account pins. */\n\tpinnedAccount?: string;\n\tonQuery?: (query: ReturnType<SdkQuery>) => void;\n\tcreateAttempt?: (\n\t\tinput: AuthenticatedAttemptInput,\n\t) => RetainableAttempt<SDKMessage> | Promise<RetainableAttempt<SDKMessage>>;\n};\n\ntype ManagedPool = {\n\taccounts: AccountSlot[];\n\tenvironment: NodeJS.ProcessEnv;\n\tlane: Exclude<ClaudeSdkOauthTokenInjection, \"ambient\">;\n\tpinnedAccount?: string;\n\tstore: CredentialStore;\n};\n\nexport function resolveEffectiveLane(\n\tsettings: ClaudeSdkOauthProviderSettings,\n\taccounts: readonly AccountSlot[],\n): ClaudeSdkOauthTokenInjection {\n\treturn settings.tokenInjection ?? (accounts.length > 0 ? \"oauth-slots\" : \"ambient\");\n}\n\nasync function managedPool(\n\tsettings: ClaudeSdkOauthProviderSettings,\n\trequestEnvironment?: Record<string, string>,\n): Promise<ManagedPool | undefined> {\n\tconst store = activeBoundary.createStore();\n\tlet credential = await store.read(CLAUDE_SDK_OAUTH_PROVIDER_ID);\n\tconst environment = mergeRequestAuthEnvironment(activeBoundary.env(), requestEnvironment);\n\tlet accounts = listAccounts(\n\t\t(credential as ClaudeSdkOauthCredential | undefined) ?? emptyCredential(),\n\t\t(name) => environment[name],\n\t);\n\tif (!credential && accounts.length > 0) {\n\t\tcredential = await store.modify(CLAUDE_SDK_OAUTH_PROVIDER_ID, async () => emptyCredential());\n\t\taccounts = listAccounts(\n\t\t\t(credential as ClaudeSdkOauthCredential) ?? emptyCredential(),\n\t\t\t(name) => environment[name],\n\t\t);\n\t}\n\tconst configuredLane = resolveEffectiveLane(settings, accounts);\n\tconst lane =\n\t\tconfiguredLane === \"config-dir\" && hasRequestOauthToken(requestEnvironment) ? \"oauth-slots\" : configuredLane;\n\tif (lane === \"ambient\" || accounts.length === 0) return undefined;\n\tconst stored = credential?.type === \"oauth\" ? (credential as ClaudeSdkOauthCredential) : undefined;\n\treturn { accounts, environment, lane, pinnedAccount: settings.pinnedAccount ?? stored?.pinned, store };\n}\n\nasync function prepareSlot(\n\tpool: ManagedPool,\n\tselected: AccountSlot,\n\tsignal: AbortSignal,\n): Promise<Record<string, string | undefined>> {\n\tconst environment = pool.environment;\n\tconst slot = selected;\n\tif (slot.source !== \"env\" && activeBoundary.now() >= slot.expires - EXPIRING_WITHIN_MS) {\n\t\ttry {\n\t\t\tconst refreshed = await refreshSlot(\n\t\t\t\tpool.store,\n\t\t\t\tCLAUDE_SDK_OAUTH_PROVIDER_ID,\n\t\t\t\tslot.name,\n\t\t\t\tactiveBoundary.refresher,\n\t\t\t\tsignal,\n\t\t\t\t(expires) => activeBoundary.now() >= expires - EXPIRING_WITHIN_MS,\n\t\t\t);\n\t\t\tconst credential = refreshed?.type === \"oauth\" ? (refreshed as ClaudeSdkOauthCredential) : undefined;\n\t\t\tconst updated = listAccounts(credential ?? emptyCredential(), (name) => environment[name]).find(\n\t\t\t\t(candidate) => candidate.name === slot.name,\n\t\t\t);\n\t\t\tif (!updated) throw new Error(\"selected account disappeared during refresh\");\n\t\t\tObject.assign(slot, updated);\n\t\t} catch (error) {\n\t\t\tconst detail = error instanceof Error ? error.message : String(error);\n\t\t\tconst classification = classifySdkError(detail);\n\t\t\tthrow new Error(\n\t\t\t\tclassification.kind === \"other\" && classification.retryable\n\t\t\t\t\t? `server_error: ${detail}`\n\t\t\t\t\t: `authentication_failed: ${detail}`,\n\t\t\t);\n\t\t}\n\t}\n\tconst access = slot.source === \"env\" ? envSlotToken((name) => environment[name], slot.name) : slot.access;\n\tif (!access) throw new Error(\"authentication_failed: selected OAuth token is unavailable\");\n\tconst childEnvironment = stripManagedAuthEnvironment(environment);\n\tif (pool.lane === \"oauth-slots\") return { ...childEnvironment, CLAUDE_CODE_OAUTH_TOKEN: access };\n\tconst directory = writeConfigDirCredential(activeBoundary.getAgentDir(), slot, access);\n\treturn { ...childEnvironment, CLAUDE_CONFIG_DIR: directory };\n}\n\nfunction sdkFailure(message: SDKMessage): unknown | undefined {\n\tconst refusal = refusalError(message);\n\tif (refusal) return refusal;\n\tif (message.type === \"assistant\") return sdkAssistantFailure(message);\n\tif (message.type === \"result\") return sdkResultFailure(message);\n\treturn undefined;\n}\n\nfunction visibleSdkMessage(message: SDKMessage): boolean {\n\tif (message.type !== \"stream_event\") return false;\n\treturn /^(?:content_block_start|content_block_delta|content_block_stop)$/.test(message.event.type);\n}\n\n/** Resolves managed OAuth immediately before each subprocess spawn and retries only pre-delta failures. */\nexport async function* queryWithAuthLane(input: AuthenticatedQueryInput): AsyncGenerator<SDKMessage> {\n\tconst signal = input.signal ?? new AbortController().signal;\n\tconst pool = await managedPool(input.providerSettings, input.env);\n\tif (!pool) {\n\t\tconst options = input.buildOptions(\"ambient\");\n\t\tconst parentEnvironment = mergeRequestAuthEnvironment(activeBoundary.env(), input.env);\n\t\tconst ambientEnvironment: Record<string, string | undefined> = { ...parentEnvironment };\n\t\tfor (const name of Object.keys(ambientEnvironment)) {\n\t\t\tif (name.startsWith(\"SENPI_\")) delete ambientEnvironment[name];\n\t\t}\n\t\toptions.env = ambientEnvironment;\n\t\tyield* await createAttemptMessages(input, {\n\t\t\taccountName: \"ambient\",\n\t\t\taccounts: [],\n\t\t\tauthLane: \"ambient\",\n\t\t\toptions,\n\t\t});\n\t\treturn;\n\t}\n\tyield* runFailover({\n\t\taccounts: pool.accounts,\n\t\tselectFn: (accounts) =>\n\t\t\tselectAccount(accounts, {\n\t\t\t\tsessionId: input.sessionId,\n\t\t\t\tpinnedAccount: input.pinnedAccount ?? pool.pinnedAccount,\n\t\t\t\tnow: activeBoundary.now(),\n\t\t\t}),\n\t\trunAttempt: async (slot) => {\n\t\t\tconst options = input.buildOptions(pool.lane);\n\t\t\tconst accounts = pool.accounts.map((account) => ({ ...account }));\n\t\t\toptions.env = await prepareSlot(pool, slot, signal);\n\t\t\treturn createAttemptMessages(input, {\n\t\t\t\taccountName: slot.name,\n\t\t\t\taccounts,\n\t\t\t\tauthLane: pool.lane,\n\t\t\t\toptions,\n\t\t\t});\n\t\t},\n\t\tclassify: classifySdkError,\n\t\tstore: pool.store,\n\t\tproviderId: CLAUDE_SDK_OAUTH_PROVIDER_ID,\n\t\tnow: activeBoundary.now,\n\t\terrorFromEvent: sdkFailure,\n\t\tisVisibleDelta: visibleSdkMessage,\n\t\tonFailover: ({ account, nextAccount, classification }) => {\n\t\t\temitProviderAccountsChanged(CLAUDE_SDK_OAUTH_PROVIDER_ID);\n\t\t\tif (nextAccount) {\n\t\t\t\temitProviderAccountFailover(\n\t\t\t\t\tCLAUDE_SDK_OAUTH_PROVIDER_ID,\n\t\t\t\t\taccount.name,\n\t\t\t\t\tnextAccount.name,\n\t\t\t\t\tclassification.kind,\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t});\n}\n"]}
1
+ {"version":3,"file":"auth-lane.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/claude-sdk-oauth/auth-lane.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CredentialStore } from \"@earendil-works/pi-ai\";\nimport { loadAnthropicOAuth } from \"@earendil-works/pi-ai/oauth\";\nimport { getAgentDir } from \"../../../../config.ts\";\nimport { AuthStorage } from \"../../../auth-storage.ts\";\nimport { emitProviderAccountFailover, emitProviderAccountsChanged } from \"./account-events.ts\";\nimport { CLAUDE_SDK_OAUTH_PROVIDER_ID } from \"./account-management.ts\";\nimport {\n\ttype AccountSlot,\n\ttype ClaudeSdkOauthCredential,\n\temptyCredential,\n\tenvSlotToken,\n\tlistAccounts,\n\trefreshSlot,\n\ttype SlotRefresher,\n} from \"./accounts.ts\";\nimport { selectAccount } from \"./affinity.ts\";\nimport { type AuthenticatedAttemptInput, createAttemptMessages, type RetainableAttempt } from \"./auth-attempt.ts\";\nimport { hasRequestOauthToken, mergeRequestAuthEnvironment, stripManagedAuthEnvironment } from \"./auth-environment.ts\";\nimport { writeConfigDirCredential } from \"./config-dir-credentials.ts\";\nimport { classifySdkError, sdkAssistantFailure, sdkResultFailure } from \"./errors.ts\";\nimport { runFailover } from \"./failover.ts\";\nimport { refusalError } from \"./refusal.ts\";\nimport type { Options, SDKMessage, SdkQuery } from \"./sdk-boundary.ts\";\nimport type { ClaudeSdkOauthProviderSettings, ClaudeSdkOauthTokenInjection } from \"./settings.ts\";\n\nexport { CLAUDE_SDK_OAUTH_PROVIDER_ID } from \"./account-management.ts\";\n\nexport const EXPIRING_WITHIN_MS = 5 * 60_000;\n\n/** A managed lane with an empty pool must refuse rather than spawn the SDK against ambient host credentials. */\nconst NO_MANAGED_ACCOUNTS_ERROR =\n\t\"authentication_failed: No Claude SDK OAuth accounts configured for the managed lane; \" +\n\t\"run /login claude-sdk-oauth or set CLAUDE_CODE_OAUTH_TOKEN\";\n\ntype AuthLaneBoundary = {\n\tcreateStore: () => CredentialStore;\n\tenv: () => NodeJS.ProcessEnv;\n\tgetAgentDir: () => string;\n\tnow: () => number;\n\trefresher: SlotRefresher;\n};\n\nasync function refreshWithAnthropicOAuth(refresh: string, signal: AbortSignal) {\n\tconst oauth = await loadAnthropicOAuth();\n\tconst credential = await oauth.refresh({ type: \"oauth\", access: \"\", refresh, expires: 0 }, signal);\n\treturn { access: credential.access, refresh: credential.refresh, expires: credential.expires };\n}\n\nconst defaultBoundary: AuthLaneBoundary = {\n\tcreateStore: () => AuthStorage.create(),\n\tenv: () => process.env,\n\tgetAgentDir,\n\tnow: () => Date.now(),\n\trefresher: refreshWithAnthropicOAuth,\n};\nlet activeBoundary = defaultBoundary;\n\nexport function overrideAuthLaneBoundary(override: Partial<AuthLaneBoundary>): void {\n\tactiveBoundary = { ...activeBoundary, ...override };\n}\n\nexport function resetAuthLaneBoundary(): void {\n\tactiveBoundary = defaultBoundary;\n}\n\nexport type { AuthenticatedAttemptInput } from \"./auth-attempt.ts\";\n\nexport type AuthenticatedQueryInput = {\n\tprompt: Parameters<SdkQuery>[0][\"prompt\"];\n\tquery: SdkQuery;\n\tbuildOptions: (lane: ClaudeSdkOauthTokenInjection) => Options;\n\tproviderSettings: ClaudeSdkOauthProviderSettings;\n\t/** Effective request auth environment; overrides the host for account discovery and SDK spawn. */\n\tenv?: Record<string, string>;\n\tsignal?: AbortSignal;\n\tsessionId?: string;\n\t/** Request-scoped CLI pin; takes precedence over persistent settings and account pins. */\n\tpinnedAccount?: string;\n\tonQuery?: (query: ReturnType<SdkQuery>) => void;\n\tcreateAttempt?: (\n\t\tinput: AuthenticatedAttemptInput,\n\t) => RetainableAttempt<SDKMessage> | Promise<RetainableAttempt<SDKMessage>>;\n};\n\ntype ManagedPool = {\n\taccounts: AccountSlot[];\n\tenvironment: NodeJS.ProcessEnv;\n\tlane: Exclude<ClaudeSdkOauthTokenInjection, \"ambient\">;\n\tpinnedAccount?: string;\n\tstore: CredentialStore;\n};\n\nexport function resolveEffectiveLane(\n\tsettings: ClaudeSdkOauthProviderSettings,\n\taccounts: readonly AccountSlot[],\n): ClaudeSdkOauthTokenInjection {\n\treturn settings.tokenInjection ?? (accounts.length > 0 ? \"oauth-slots\" : \"ambient\");\n}\n\nasync function managedPool(\n\tsettings: ClaudeSdkOauthProviderSettings,\n\trequestEnvironment?: Record<string, string>,\n): Promise<ManagedPool | undefined> {\n\tconst store = activeBoundary.createStore();\n\tlet credential = await store.read(CLAUDE_SDK_OAUTH_PROVIDER_ID);\n\tconst environment = mergeRequestAuthEnvironment(activeBoundary.env(), requestEnvironment);\n\tlet accounts = listAccounts(\n\t\t(credential as ClaudeSdkOauthCredential | undefined) ?? emptyCredential(),\n\t\t(name) => environment[name],\n\t);\n\tif (!credential && accounts.length > 0) {\n\t\tcredential = await store.modify(CLAUDE_SDK_OAUTH_PROVIDER_ID, async () => emptyCredential());\n\t\taccounts = listAccounts(\n\t\t\t(credential as ClaudeSdkOauthCredential) ?? emptyCredential(),\n\t\t\t(name) => environment[name],\n\t\t);\n\t}\n\tconst configuredLane = resolveEffectiveLane(settings, accounts);\n\tconst lane =\n\t\tconfiguredLane === \"config-dir\" && hasRequestOauthToken(requestEnvironment) ? \"oauth-slots\" : configuredLane;\n\tif (lane === \"ambient\") return undefined;\n\tif (accounts.length === 0) throw new Error(NO_MANAGED_ACCOUNTS_ERROR);\n\tconst stored = credential?.type === \"oauth\" ? (credential as ClaudeSdkOauthCredential) : undefined;\n\treturn { accounts, environment, lane, pinnedAccount: settings.pinnedAccount ?? stored?.pinned, store };\n}\n\nasync function prepareSlot(\n\tpool: ManagedPool,\n\tselected: AccountSlot,\n\tsignal: AbortSignal,\n): Promise<Record<string, string | undefined>> {\n\tconst environment = pool.environment;\n\tconst slot = selected;\n\tif (slot.source !== \"env\" && activeBoundary.now() >= slot.expires - EXPIRING_WITHIN_MS) {\n\t\ttry {\n\t\t\tconst refreshed = await refreshSlot(\n\t\t\t\tpool.store,\n\t\t\t\tCLAUDE_SDK_OAUTH_PROVIDER_ID,\n\t\t\t\tslot.name,\n\t\t\t\tactiveBoundary.refresher,\n\t\t\t\tsignal,\n\t\t\t\t(expires) => activeBoundary.now() >= expires - EXPIRING_WITHIN_MS,\n\t\t\t);\n\t\t\tconst credential = refreshed?.type === \"oauth\" ? (refreshed as ClaudeSdkOauthCredential) : undefined;\n\t\t\tconst updated = listAccounts(credential ?? emptyCredential(), (name) => environment[name]).find(\n\t\t\t\t(candidate) => candidate.name === slot.name,\n\t\t\t);\n\t\t\tif (!updated) throw new Error(\"selected account disappeared during refresh\");\n\t\t\tObject.assign(slot, updated);\n\t\t} catch (error) {\n\t\t\tconst detail = error instanceof Error ? error.message : String(error);\n\t\t\tconst classification = classifySdkError(detail);\n\t\t\tthrow new Error(\n\t\t\t\tclassification.kind === \"other\" && classification.retryable\n\t\t\t\t\t? `server_error: ${detail}`\n\t\t\t\t\t: `authentication_failed: ${detail}`,\n\t\t\t);\n\t\t}\n\t}\n\tconst access = slot.source === \"env\" ? envSlotToken((name) => environment[name], slot.name) : slot.access;\n\tif (!access) throw new Error(\"authentication_failed: selected OAuth token is unavailable\");\n\tconst childEnvironment = stripManagedAuthEnvironment(environment);\n\tif (pool.lane === \"oauth-slots\") return { ...childEnvironment, CLAUDE_CODE_OAUTH_TOKEN: access };\n\tconst directory = writeConfigDirCredential(activeBoundary.getAgentDir(), slot, access);\n\treturn { ...childEnvironment, CLAUDE_CONFIG_DIR: directory };\n}\n\nfunction sdkFailure(message: SDKMessage): unknown | undefined {\n\tconst refusal = refusalError(message);\n\tif (refusal) return refusal;\n\tif (message.type === \"assistant\") return sdkAssistantFailure(message);\n\tif (message.type === \"result\") return sdkResultFailure(message);\n\treturn undefined;\n}\n\nfunction visibleSdkMessage(message: SDKMessage): boolean {\n\tif (message.type !== \"stream_event\") return false;\n\treturn /^(?:content_block_start|content_block_delta|content_block_stop)$/.test(message.event.type);\n}\n\n/** Resolves managed OAuth immediately before each subprocess spawn and retries only pre-delta failures. */\nexport async function* queryWithAuthLane(input: AuthenticatedQueryInput): AsyncGenerator<SDKMessage> {\n\tconst signal = input.signal ?? new AbortController().signal;\n\tconst pool = await managedPool(input.providerSettings, input.env);\n\tif (!pool) {\n\t\tconst options = input.buildOptions(\"ambient\");\n\t\tconst parentEnvironment = mergeRequestAuthEnvironment(activeBoundary.env(), input.env);\n\t\tconst ambientEnvironment: Record<string, string | undefined> = { ...parentEnvironment };\n\t\tfor (const name of Object.keys(ambientEnvironment)) {\n\t\t\tif (name.startsWith(\"SENPI_\")) delete ambientEnvironment[name];\n\t\t}\n\t\toptions.env = ambientEnvironment;\n\t\tyield* await createAttemptMessages(input, {\n\t\t\taccountName: \"ambient\",\n\t\t\taccounts: [],\n\t\t\tauthLane: \"ambient\",\n\t\t\toptions,\n\t\t});\n\t\treturn;\n\t}\n\tyield* runFailover({\n\t\taccounts: pool.accounts,\n\t\tselectFn: (accounts) =>\n\t\t\tselectAccount(accounts, {\n\t\t\t\tsessionId: input.sessionId,\n\t\t\t\tpinnedAccount: input.pinnedAccount ?? pool.pinnedAccount,\n\t\t\t\tnow: activeBoundary.now(),\n\t\t\t}),\n\t\trunAttempt: async (slot) => {\n\t\t\tconst options = input.buildOptions(pool.lane);\n\t\t\tconst accounts = pool.accounts.map((account) => ({ ...account }));\n\t\t\toptions.env = await prepareSlot(pool, slot, signal);\n\t\t\treturn createAttemptMessages(input, {\n\t\t\t\taccountName: slot.name,\n\t\t\t\taccounts,\n\t\t\t\tauthLane: pool.lane,\n\t\t\t\toptions,\n\t\t\t});\n\t\t},\n\t\tclassify: classifySdkError,\n\t\tstore: pool.store,\n\t\tproviderId: CLAUDE_SDK_OAUTH_PROVIDER_ID,\n\t\tnow: activeBoundary.now,\n\t\terrorFromEvent: sdkFailure,\n\t\tisVisibleDelta: visibleSdkMessage,\n\t\tonFailover: ({ account, nextAccount, classification }) => {\n\t\t\temitProviderAccountsChanged(CLAUDE_SDK_OAUTH_PROVIDER_ID);\n\t\t\tif (nextAccount) {\n\t\t\t\temitProviderAccountFailover(\n\t\t\t\t\tCLAUDE_SDK_OAUTH_PROVIDER_ID,\n\t\t\t\t\taccount.name,\n\t\t\t\t\tnextAccount.name,\n\t\t\t\t\tclassification.kind,\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t});\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import type { SDKMessage } from "./sdk-boundary.ts";
2
- export type SdkErrorKind = "rate_limit" | "overloaded" | "auth_error" | "billing" | "org_not_allowed" | "other";
2
+ export type SdkErrorKind = "rate_limit" | "overloaded" | "auth_error" | "billing" | "org_not_allowed" | "entitlement" | "other";
3
3
  export type SdkErrorClassification = {
4
4
  kind: SdkErrorKind;
5
5
  retryable: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/claude-sdk-oauth/errors.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,MAAM,YAAY,GAAG,YAAY,GAAG,YAAY,GAAG,YAAY,GAAG,SAAS,GAAG,iBAAiB,GAAG,OAAO,CAAC;AAEhH,MAAM,MAAM,sBAAsB,GAAG;IACpC,IAAI,EAAE,YAAY,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;CACnB,CAAC;AAmCF,MAAM,MAAM,cAAc,GAAG,OAAO,CAAC,UAAU,EAAE;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC,CAAC,OAAO,CAAC,CAAC;AAE9E,sFAAsF;AACtF,qBAAa,gBAAiB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,KAAK,EAAE,cAAc,GAAG,SAAS,CAAC;gBAE/B,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,GAAG,SAAS;CAK9D;AAED,mGAAmG;AACnG,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,GAAG,SAAS,CAIhF;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,EAAE;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC,GAAG,gBAAgB,GAAG,SAAS,CAe/G;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,EAAE;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,CAAC,GAAG,KAAK,GAAG,SAAS,CAY1G;AAED,0FAA0F;AAC1F,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,sBAAsB,CAkCvE"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/claude-sdk-oauth/errors.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,MAAM,YAAY,GACrB,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,SAAS,GACT,iBAAiB,GACjB,aAAa,GACb,OAAO,CAAC;AAEX,MAAM,MAAM,sBAAsB,GAAG;IACpC,IAAI,EAAE,YAAY,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;CACnB,CAAC;AAmCF,MAAM,MAAM,cAAc,GAAG,OAAO,CAAC,UAAU,EAAE;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC,CAAC,OAAO,CAAC,CAAC;AAE9E,sFAAsF;AACtF,qBAAa,gBAAiB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,KAAK,EAAE,cAAc,GAAG,SAAS,CAAC;gBAE/B,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,GAAG,SAAS;CAK9D;AAED,mGAAmG;AACnG,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,GAAG,SAAS,CAIhF;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,EAAE;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC,GAAG,gBAAgB,GAAG,SAAS,CAe/G;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,EAAE;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,CAAC,GAAG,KAAK,GAAG,SAAS,CAY1G;AAED,0FAA0F;AAC1F,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,sBAAsB,CAwCvE"}
@@ -105,6 +105,12 @@ export function classifySdkError(error) {
105
105
  if (/\binvalid_grant\b|\binvalid_token\b|\b(?:http\s*)?401\b|\bunauthorized\b/.test(text)) {
106
106
  return { kind: "auth_error", retryable: true };
107
107
  }
108
+ // Fable 5 and similar models are not in the subscription; Claude Code asks
109
+ // for usage credits. That is an account entitlement, not a 60s rate limit:
110
+ // blocking the only account would also block Opus fallback on it.
111
+ if (/\brequires usage credits\b|\/usage-credits\b|\bcredits_required\b/.test(text)) {
112
+ return { kind: "entitlement", retryable: false };
113
+ }
108
114
  return OTHER_ERROR;
109
115
  }
110
116
  //# sourceMappingURL=errors.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/claude-sdk-oauth/errors.ts"],"names":[],"mappings":"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","sourcesContent":["import type { SDKAssistantMessageError } from \"@anthropic-ai/claude-agent-sdk\";\nimport type { SDKMessage } from \"./sdk-boundary.ts\";\n\nexport type SdkErrorKind = \"rate_limit\" | \"overloaded\" | \"auth_error\" | \"billing\" | \"org_not_allowed\" | \"other\";\n\nexport type SdkErrorClassification = {\n\tkind: SdkErrorKind;\n\tretryable: boolean;\n};\n\nconst SDK_ERROR_CLASSIFICATIONS: Partial<Record<SDKAssistantMessageError, SdkErrorClassification>> = {\n\tauthentication_failed: { kind: \"auth_error\", retryable: true },\n\toauth_org_not_allowed: { kind: \"org_not_allowed\", retryable: true },\n\tbilling_error: { kind: \"billing\", retryable: true },\n\trate_limit: { kind: \"rate_limit\", retryable: true },\n\toverloaded: { kind: \"overloaded\", retryable: true },\n\tinvalid_request: { kind: \"other\", retryable: false },\n\tserver_error: { kind: \"other\", retryable: true },\n\taccount_on_hold: { kind: \"billing\", retryable: true },\n\tmodel_not_found: { kind: \"other\", retryable: false },\n\tmax_output_tokens: { kind: \"other\", retryable: false },\n};\n\nconst OTHER_ERROR: SdkErrorClassification = { kind: \"other\", retryable: false };\n\nfunction record(value: unknown): Record<string, unknown> | undefined {\n\treturn value !== null && typeof value === \"object\" && !Array.isArray(value)\n\t\t? (value as Record<string, unknown>)\n\t\t: undefined;\n}\n\nfunction errorText(error: unknown): string {\n\tif (typeof error === \"string\") return error;\n\tif (error instanceof Error) return error.message;\n\tconst value = record(error);\n\tif (!value) return String(error);\n\tconst message = value.message;\n\tif (typeof message === \"string\") return message;\n\tconst code = value.error;\n\tif (typeof code === \"string\") return code;\n\treturn String(error);\n}\n\nexport type SdkResultUsage = Extract<SDKMessage, { type: \"result\" }>[\"usage\"];\n\n/** A failed SDK result keeps the usage it billed so every lane can account for it. */\nexport class SdkResultFailure extends Error {\n\treadonly usage: SdkResultUsage | undefined;\n\n\tconstructor(message: string, usage: SdkResultUsage | undefined) {\n\t\tsuper(message);\n\t\tthis.name = \"SdkResultFailure\";\n\t\tthis.usage = usage;\n\t}\n}\n\n/** The usage carried by a failed SDK result, looking through failover's classification wrapper. */\nexport function sdkResultFailureUsage(error: unknown): SdkResultUsage | undefined {\n\tif (error instanceof SdkResultFailure) return error.usage;\n\tconst wrapped = record(error)?.original;\n\treturn wrapped instanceof SdkResultFailure ? wrapped.usage : undefined;\n}\n\nexport function sdkResultFailure(message: Extract<SDKMessage, { type: \"result\" }>): SdkResultFailure | undefined {\n\tif (message.subtype === \"success\" && message.is_error !== true) return undefined;\n\tconst errors = \"errors\" in message && Array.isArray(message.errors) ? message.errors : [];\n\tconst firstError = errors.find((error): error is string => typeof error === \"string\" && error.length > 0);\n\tconst resultText = \"result\" in message && typeof message.result === \"string\" ? message.result.trim() : \"\";\n\tconst detail =\n\t\tfirstError ??\n\t\t(message.is_error === true && resultText ? resultText : undefined) ??\n\t\t`Claude Code ${message.subtype}`;\n\tconst status =\n\t\t\"api_error_status\" in message && message.api_error_status != null ? `HTTP ${message.api_error_status}` : \"\";\n\tconst reason =\n\t\t\"terminal_reason\" in message && typeof message.terminal_reason === \"string\" ? message.terminal_reason : \"\";\n\tconst suffix = [status, reason].filter(Boolean).join(\", \");\n\treturn new SdkResultFailure(suffix ? `${detail} (${suffix})` : detail, message.usage);\n}\n\nexport function sdkAssistantFailure(message: Extract<SDKMessage, { type: \"assistant\" }>): Error | undefined {\n\tif (!message.error) return undefined;\n\tconst content = message.message.content;\n\tconst text = (\n\t\ttypeof content === \"string\"\n\t\t\t? content\n\t\t\t: content\n\t\t\t\t\t.filter((block) => block.type === \"text\" && \"text\" in block && typeof block.text === \"string\")\n\t\t\t\t\t.map((block) => (\"text\" in block && typeof block.text === \"string\" ? block.text : \"\"))\n\t\t\t\t\t.join(\" \")\n\t).trim();\n\treturn new Error(text ? (message.error === \"unknown\" ? text : `${text} (${message.error})`) : message.error);\n}\n\n/** Classifies Claude SDK OAuth error codes and HTTP-shaped fallback text in one place. */\nexport function classifySdkError(error: unknown): SdkErrorClassification {\n\tconst text = errorText(error).toLowerCase();\n\tif (\n\t\t/\\b(enotfound|eai_again|econnreset|econnrefused|etimedout|enetunreach|ehostunreach|und_err_connect_timeout|und_err_socket)\\b|fetch failed|socket hang up|connection reset by peer/.test(\n\t\t\ttext,\n\t\t)\n\t) {\n\t\treturn { kind: \"other\", retryable: true };\n\t}\n\tfor (const [code, classification] of Object.entries(SDK_ERROR_CLASSIFICATIONS)) {\n\t\tif (new RegExp(`\\\\b${code}\\\\b`).test(text)) return classification ?? OTHER_ERROR;\n\t}\n\tif (/\\b(?:http\\s*)?429\\b|too many requests|rate[ _-]?limit/.test(text)) {\n\t\treturn { kind: \"rate_limit\", retryable: true };\n\t}\n\t// Claude Code signals subscription exhaustion two ways, neither of which\n\t// carries an SDK error code or HTTP status:\n\t// - `terminal_reason: \"blocking_limit\"` / `\"rapid_refill_breaker\"` on a\n\t// result message (surfaced by auth-lane's sdkFailure)\n\t// - prose in `errors[0]`, e.g. \"You've hit your weekly limit · resets 5am\n\t// (Asia/Seoul)\" and the 5-hour/daily equivalents\n\t// Without these branches both classify as non-retryable \"other\", so the\n\t// exhausted account is never blocked and a pool never rotates past it.\n\tif (/\\bblocking_limit\\b|\\brapid_refill_breaker\\b/.test(text)) {\n\t\treturn { kind: \"rate_limit\", retryable: true };\n\t}\n\tif (/\\b(?:hit|reached|exceeded)\\b[^.]*\\blimit\\b|\\b(?:weekly|daily|hourly|usage)\\s+limit\\b/.test(text)) {\n\t\treturn { kind: \"rate_limit\", retryable: true };\n\t}\n\tif (/\\b(?:http\\s*)?529\\b|overloaded/.test(text)) return { kind: \"overloaded\", retryable: true };\n\tif (/\\binvalid_grant\\b|\\binvalid_token\\b|\\b(?:http\\s*)?401\\b|\\bunauthorized\\b/.test(text)) {\n\t\treturn { kind: \"auth_error\", retryable: true };\n\t}\n\treturn OTHER_ERROR;\n}\n"]}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/claude-sdk-oauth/errors.ts"],"names":[],"mappings":"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","sourcesContent":["import type { SDKAssistantMessageError } from \"@anthropic-ai/claude-agent-sdk\";\nimport type { SDKMessage } from \"./sdk-boundary.ts\";\n\nexport type SdkErrorKind =\n\t| \"rate_limit\"\n\t| \"overloaded\"\n\t| \"auth_error\"\n\t| \"billing\"\n\t| \"org_not_allowed\"\n\t| \"entitlement\"\n\t| \"other\";\n\nexport type SdkErrorClassification = {\n\tkind: SdkErrorKind;\n\tretryable: boolean;\n};\n\nconst SDK_ERROR_CLASSIFICATIONS: Partial<Record<SDKAssistantMessageError, SdkErrorClassification>> = {\n\tauthentication_failed: { kind: \"auth_error\", retryable: true },\n\toauth_org_not_allowed: { kind: \"org_not_allowed\", retryable: true },\n\tbilling_error: { kind: \"billing\", retryable: true },\n\trate_limit: { kind: \"rate_limit\", retryable: true },\n\toverloaded: { kind: \"overloaded\", retryable: true },\n\tinvalid_request: { kind: \"other\", retryable: false },\n\tserver_error: { kind: \"other\", retryable: true },\n\taccount_on_hold: { kind: \"billing\", retryable: true },\n\tmodel_not_found: { kind: \"other\", retryable: false },\n\tmax_output_tokens: { kind: \"other\", retryable: false },\n};\n\nconst OTHER_ERROR: SdkErrorClassification = { kind: \"other\", retryable: false };\n\nfunction record(value: unknown): Record<string, unknown> | undefined {\n\treturn value !== null && typeof value === \"object\" && !Array.isArray(value)\n\t\t? (value as Record<string, unknown>)\n\t\t: undefined;\n}\n\nfunction errorText(error: unknown): string {\n\tif (typeof error === \"string\") return error;\n\tif (error instanceof Error) return error.message;\n\tconst value = record(error);\n\tif (!value) return String(error);\n\tconst message = value.message;\n\tif (typeof message === \"string\") return message;\n\tconst code = value.error;\n\tif (typeof code === \"string\") return code;\n\treturn String(error);\n}\n\nexport type SdkResultUsage = Extract<SDKMessage, { type: \"result\" }>[\"usage\"];\n\n/** A failed SDK result keeps the usage it billed so every lane can account for it. */\nexport class SdkResultFailure extends Error {\n\treadonly usage: SdkResultUsage | undefined;\n\n\tconstructor(message: string, usage: SdkResultUsage | undefined) {\n\t\tsuper(message);\n\t\tthis.name = \"SdkResultFailure\";\n\t\tthis.usage = usage;\n\t}\n}\n\n/** The usage carried by a failed SDK result, looking through failover's classification wrapper. */\nexport function sdkResultFailureUsage(error: unknown): SdkResultUsage | undefined {\n\tif (error instanceof SdkResultFailure) return error.usage;\n\tconst wrapped = record(error)?.original;\n\treturn wrapped instanceof SdkResultFailure ? wrapped.usage : undefined;\n}\n\nexport function sdkResultFailure(message: Extract<SDKMessage, { type: \"result\" }>): SdkResultFailure | undefined {\n\tif (message.subtype === \"success\" && message.is_error !== true) return undefined;\n\tconst errors = \"errors\" in message && Array.isArray(message.errors) ? message.errors : [];\n\tconst firstError = errors.find((error): error is string => typeof error === \"string\" && error.length > 0);\n\tconst resultText = \"result\" in message && typeof message.result === \"string\" ? message.result.trim() : \"\";\n\tconst detail =\n\t\tfirstError ??\n\t\t(message.is_error === true && resultText ? resultText : undefined) ??\n\t\t`Claude Code ${message.subtype}`;\n\tconst status =\n\t\t\"api_error_status\" in message && message.api_error_status != null ? `HTTP ${message.api_error_status}` : \"\";\n\tconst reason =\n\t\t\"terminal_reason\" in message && typeof message.terminal_reason === \"string\" ? message.terminal_reason : \"\";\n\tconst suffix = [status, reason].filter(Boolean).join(\", \");\n\treturn new SdkResultFailure(suffix ? `${detail} (${suffix})` : detail, message.usage);\n}\n\nexport function sdkAssistantFailure(message: Extract<SDKMessage, { type: \"assistant\" }>): Error | undefined {\n\tif (!message.error) return undefined;\n\tconst content = message.message.content;\n\tconst text = (\n\t\ttypeof content === \"string\"\n\t\t\t? content\n\t\t\t: content\n\t\t\t\t\t.filter((block) => block.type === \"text\" && \"text\" in block && typeof block.text === \"string\")\n\t\t\t\t\t.map((block) => (\"text\" in block && typeof block.text === \"string\" ? block.text : \"\"))\n\t\t\t\t\t.join(\" \")\n\t).trim();\n\treturn new Error(text ? (message.error === \"unknown\" ? text : `${text} (${message.error})`) : message.error);\n}\n\n/** Classifies Claude SDK OAuth error codes and HTTP-shaped fallback text in one place. */\nexport function classifySdkError(error: unknown): SdkErrorClassification {\n\tconst text = errorText(error).toLowerCase();\n\tif (\n\t\t/\\b(enotfound|eai_again|econnreset|econnrefused|etimedout|enetunreach|ehostunreach|und_err_connect_timeout|und_err_socket)\\b|fetch failed|socket hang up|connection reset by peer/.test(\n\t\t\ttext,\n\t\t)\n\t) {\n\t\treturn { kind: \"other\", retryable: true };\n\t}\n\tfor (const [code, classification] of Object.entries(SDK_ERROR_CLASSIFICATIONS)) {\n\t\tif (new RegExp(`\\\\b${code}\\\\b`).test(text)) return classification ?? OTHER_ERROR;\n\t}\n\tif (/\\b(?:http\\s*)?429\\b|too many requests|rate[ _-]?limit/.test(text)) {\n\t\treturn { kind: \"rate_limit\", retryable: true };\n\t}\n\t// Claude Code signals subscription exhaustion two ways, neither of which\n\t// carries an SDK error code or HTTP status:\n\t// - `terminal_reason: \"blocking_limit\"` / `\"rapid_refill_breaker\"` on a\n\t// result message (surfaced by auth-lane's sdkFailure)\n\t// - prose in `errors[0]`, e.g. \"You've hit your weekly limit · resets 5am\n\t// (Asia/Seoul)\" and the 5-hour/daily equivalents\n\t// Without these branches both classify as non-retryable \"other\", so the\n\t// exhausted account is never blocked and a pool never rotates past it.\n\tif (/\\bblocking_limit\\b|\\brapid_refill_breaker\\b/.test(text)) {\n\t\treturn { kind: \"rate_limit\", retryable: true };\n\t}\n\tif (/\\b(?:hit|reached|exceeded)\\b[^.]*\\blimit\\b|\\b(?:weekly|daily|hourly|usage)\\s+limit\\b/.test(text)) {\n\t\treturn { kind: \"rate_limit\", retryable: true };\n\t}\n\tif (/\\b(?:http\\s*)?529\\b|overloaded/.test(text)) return { kind: \"overloaded\", retryable: true };\n\tif (/\\binvalid_grant\\b|\\binvalid_token\\b|\\b(?:http\\s*)?401\\b|\\bunauthorized\\b/.test(text)) {\n\t\treturn { kind: \"auth_error\", retryable: true };\n\t}\n\t// Fable 5 and similar models are not in the subscription; Claude Code asks\n\t// for usage credits. That is an account entitlement, not a 60s rate limit:\n\t// blocking the only account would also block Opus fallback on it.\n\tif (/\\brequires usage credits\\b|\\/usage-credits\\b|\\bcredits_required\\b/.test(text)) {\n\t\treturn { kind: \"entitlement\", retryable: false };\n\t}\n\treturn OTHER_ERROR;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"guidance.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/claude-sdk-oauth/guidance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIhD,wBAAgB,iBAAiB,CAAC,sBAAsB,EAAE,OAAO,GAAG,MAAM,CAazE;AAED,wBAAgB,0BAA0B,CAAC,gBAAgB,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAWvF;AAED,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAa/E;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,GAAG,SAAS,CAWvE;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAK5E;AAED,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,UAAU,GAAG,eAAe,CAAC;AAErE,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAM7F;AAID,wBAAgB,4BAA4B,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAMrE;AAED,wBAAgB,+BAA+B,CAAC,OAAO,EAAE;IACxD,IAAI,EAAE,gBAAgB,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CAClB,GAAG,MAAM,GAAG,SAAS,CAqBrB"}
1
+ {"version":3,"file":"guidance.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/claude-sdk-oauth/guidance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIhD,wBAAgB,iBAAiB,CAAC,sBAAsB,EAAE,OAAO,GAAG,MAAM,CAazE;AAED,wBAAgB,0BAA0B,CAAC,gBAAgB,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAWvF;AAED,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAa/E;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,GAAG,SAAS,CAavE;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAK5E;AAED,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,UAAU,GAAG,eAAe,CAAC;AAErE,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAM7F;AAID,wBAAgB,4BAA4B,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAMrE;AAED,wBAAgB,+BAA+B,CAAC,OAAO,EAAE;IACxD,IAAI,EAAE,gBAAgB,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CAClB,GAAG,MAAM,GAAG,SAAS,CAqBrB"}
@@ -40,6 +40,8 @@ export function sdkErrorGuidance(kind) {
40
40
  return "The selected Claude account has a billing problem. Check the plan at claude.com or switch accounts with /claude-account pin <name>.";
41
41
  case "auth_error":
42
42
  return `The account's OAuth token was rejected. Re-run /login ${PROVIDER} to refresh it, or remove the account with /claude-account remove <name>.`;
43
+ case "entitlement":
44
+ return "This model needs usage credits on the selected Claude account (it is not included in the subscription). Switch models with /model, enable usage credits at claude.com, or pick another account with /claude-account pin <name>.";
43
45
  default:
44
46
  return undefined;
45
47
  }
@@ -1 +1 @@
1
- {"version":3,"file":"guidance.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/claude-sdk-oauth/guidance.ts"],"names":[],"mappings":"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","sourcesContent":["import type { SdkErrorKind } from \"./errors.ts\";\n\nconst PROVIDER = \"claude-sdk-oauth\";\n\nexport function noAccountGuidance(hasAnthropicCredential: boolean): string {\n\tconst lines = [\n\t\t`No Claude account configured for ${PROVIDER}.`,\n\t\t` /login ${PROVIDER} - sign in with your Claude Pro/Max subscription`,\n\t];\n\tif (hasAnthropicCredential) {\n\t\tlines.push(\" (your existing Anthropic OAuth login will be offered as an import)\");\n\t}\n\tlines.push(\n\t\t\" Or set CLAUDE_CODE_OAUTH_TOKEN (and _2.._N for more accounts),\",\n\t\t\" or log in with the claude CLI for ambient auth.\",\n\t);\n\treturn lines.join(\"\\n\");\n}\n\nexport function allAccountsBlockedGuidance(soonestUnblockAt: number | undefined): string {\n\tconst eta =\n\t\tsoonestUnblockAt !== undefined && Number.isFinite(soonestUnblockAt)\n\t\t\t? new Date(soonestUnblockAt).toISOString()\n\t\t\t: \"after re-login\";\n\treturn [\n\t\t`All Claude accounts for ${PROVIDER} are currently blocked (rate limit or auth errors).`,\n\t\t` Soonest automatic retry: ${eta}.`,\n\t\t` /claude-account list - inspect account states`,\n\t\t` /login ${PROVIDER} - add another account`,\n\t].join(\"\\n\");\n}\n\nexport function claudeCodeVersionFloorGuidance(text: string): string | undefined {\n\tconst floor = /does not support this model; version (\\S+?) or newer is required|claude_code_version_too_old/i.exec(\n\t\ttext,\n\t);\n\tif (floor) {\n\t\tconst target =\n\t\t\tfloor[1] === undefined ? \"a newer Claude Code\" : `Claude Code ${floor[1].replace(/[.,;:]+$/, \"\")} or newer`;\n\t\treturn `The bundled Claude Code binary is too old for this model. Update senpi/omo (it ships a newer @anthropic-ai/claude-agent-sdk) or set CLAUDE_CODE_EXECUTABLE to ${target} binary.`;\n\t}\n\tif (/\\bmodel_not_found\\b|unrecognized_model|not found for provider/i.test(text)) {\n\t\treturn \"The bundled Claude Code binary does not know this model id; update senpi/omo or set CLAUDE_CODE_EXECUTABLE to a newer Claude Code binary.\";\n\t}\n\treturn undefined;\n}\n\nexport function sdkErrorGuidance(kind: SdkErrorKind): string | undefined {\n\tswitch (kind) {\n\t\tcase \"org_not_allowed\":\n\t\t\treturn \"This organization's policy disallows subscription OAuth use here. Use an API key (ANTHROPIC_API_KEY) or an account from an allowed organization.\";\n\t\tcase \"billing\":\n\t\t\treturn \"The selected Claude account has a billing problem. Check the plan at claude.com or switch accounts with /claude-account pin <name>.\";\n\t\tcase \"auth_error\":\n\t\t\treturn `The account's OAuth token was rejected. Re-run /login ${PROVIDER} to refresh it, or remove the account with /claude-account remove <name>.`;\n\t\tdefault:\n\t\t\treturn undefined;\n\t}\n}\n\nexport function missingBinaryGuidance(platform: string, arch: string): string {\n\treturn [\n\t\t`Claude native binary not found for ${platform}-${arch}.`,\n\t\t\"Reinstall @anthropic-ai/claude-agent-sdk without --omit=optional, or set CLAUDE_CODE_EXECUTABLE.\",\n\t].join(\"\\n\");\n}\n\nexport type SystemPromptMode = \"full\" | \"override\" | \"preset-append\";\n\nexport function overrideSystemPromptGuidance(path: string | undefined, reason: string): string {\n\tconst target = path === undefined ? \"systemPromptFile\" : `systemPromptFile \"${path}\"`;\n\treturn [\n\t\t`Claude SDK OAuth override prompt could not load ${target}: ${reason}.`,\n\t\t'Set claudeSdkOauthProvider.systemPromptFile to a readable, non-empty UTF-8 prompt file, or select systemPromptMode \"full\".',\n\t].join(\" \");\n}\n\nconst armedSessions = new Set<string>();\n\nexport function resetPresetAppendDeprecation(sessionId?: string): void {\n\tif (sessionId !== undefined) {\n\t\tarmedSessions.delete(sessionId);\n\t} else {\n\t\tarmedSessions.clear();\n\t}\n}\n\nexport function presetAppendDeprecationGuidance(options: {\n\tmode: SystemPromptMode;\n\tconflict?: boolean;\n\tsessionId: string;\n}): string | undefined {\n\tif (armedSessions.has(options.sessionId)) {\n\t\treturn undefined;\n\t}\n\tconst isDeprecated = options.mode === \"preset-append\";\n\tif (!options.conflict && !isDeprecated) {\n\t\treturn undefined;\n\t}\n\tarmedSessions.add(options.sessionId);\n\tconst parts: string[] = [];\n\tif (isDeprecated) {\n\t\tparts.push(\n\t\t\t\"preset-append system-prompt mode is deprecated; \" +\n\t\t\t\t\"`full` mode delivers the complete senpi system prompt; \" +\n\t\t\t\t\"preset-append will be removed after one release.\",\n\t\t);\n\t}\n\tif (options.conflict) {\n\t\tparts.push(\"systemPromptMode wins.\");\n\t}\n\treturn parts.join(\" \");\n}\n"]}
1
+ {"version":3,"file":"guidance.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/claude-sdk-oauth/guidance.ts"],"names":[],"mappings":"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","sourcesContent":["import type { SdkErrorKind } from \"./errors.ts\";\n\nconst PROVIDER = \"claude-sdk-oauth\";\n\nexport function noAccountGuidance(hasAnthropicCredential: boolean): string {\n\tconst lines = [\n\t\t`No Claude account configured for ${PROVIDER}.`,\n\t\t` /login ${PROVIDER} - sign in with your Claude Pro/Max subscription`,\n\t];\n\tif (hasAnthropicCredential) {\n\t\tlines.push(\" (your existing Anthropic OAuth login will be offered as an import)\");\n\t}\n\tlines.push(\n\t\t\" Or set CLAUDE_CODE_OAUTH_TOKEN (and _2.._N for more accounts),\",\n\t\t\" or log in with the claude CLI for ambient auth.\",\n\t);\n\treturn lines.join(\"\\n\");\n}\n\nexport function allAccountsBlockedGuidance(soonestUnblockAt: number | undefined): string {\n\tconst eta =\n\t\tsoonestUnblockAt !== undefined && Number.isFinite(soonestUnblockAt)\n\t\t\t? new Date(soonestUnblockAt).toISOString()\n\t\t\t: \"after re-login\";\n\treturn [\n\t\t`All Claude accounts for ${PROVIDER} are currently blocked (rate limit or auth errors).`,\n\t\t` Soonest automatic retry: ${eta}.`,\n\t\t` /claude-account list - inspect account states`,\n\t\t` /login ${PROVIDER} - add another account`,\n\t].join(\"\\n\");\n}\n\nexport function claudeCodeVersionFloorGuidance(text: string): string | undefined {\n\tconst floor = /does not support this model; version (\\S+?) or newer is required|claude_code_version_too_old/i.exec(\n\t\ttext,\n\t);\n\tif (floor) {\n\t\tconst target =\n\t\t\tfloor[1] === undefined ? \"a newer Claude Code\" : `Claude Code ${floor[1].replace(/[.,;:]+$/, \"\")} or newer`;\n\t\treturn `The bundled Claude Code binary is too old for this model. Update senpi/omo (it ships a newer @anthropic-ai/claude-agent-sdk) or set CLAUDE_CODE_EXECUTABLE to ${target} binary.`;\n\t}\n\tif (/\\bmodel_not_found\\b|unrecognized_model|not found for provider/i.test(text)) {\n\t\treturn \"The bundled Claude Code binary does not know this model id; update senpi/omo or set CLAUDE_CODE_EXECUTABLE to a newer Claude Code binary.\";\n\t}\n\treturn undefined;\n}\n\nexport function sdkErrorGuidance(kind: SdkErrorKind): string | undefined {\n\tswitch (kind) {\n\t\tcase \"org_not_allowed\":\n\t\t\treturn \"This organization's policy disallows subscription OAuth use here. Use an API key (ANTHROPIC_API_KEY) or an account from an allowed organization.\";\n\t\tcase \"billing\":\n\t\t\treturn \"The selected Claude account has a billing problem. Check the plan at claude.com or switch accounts with /claude-account pin <name>.\";\n\t\tcase \"auth_error\":\n\t\t\treturn `The account's OAuth token was rejected. Re-run /login ${PROVIDER} to refresh it, or remove the account with /claude-account remove <name>.`;\n\t\tcase \"entitlement\":\n\t\t\treturn \"This model needs usage credits on the selected Claude account (it is not included in the subscription). Switch models with /model, enable usage credits at claude.com, or pick another account with /claude-account pin <name>.\";\n\t\tdefault:\n\t\t\treturn undefined;\n\t}\n}\n\nexport function missingBinaryGuidance(platform: string, arch: string): string {\n\treturn [\n\t\t`Claude native binary not found for ${platform}-${arch}.`,\n\t\t\"Reinstall @anthropic-ai/claude-agent-sdk without --omit=optional, or set CLAUDE_CODE_EXECUTABLE.\",\n\t].join(\"\\n\");\n}\n\nexport type SystemPromptMode = \"full\" | \"override\" | \"preset-append\";\n\nexport function overrideSystemPromptGuidance(path: string | undefined, reason: string): string {\n\tconst target = path === undefined ? \"systemPromptFile\" : `systemPromptFile \"${path}\"`;\n\treturn [\n\t\t`Claude SDK OAuth override prompt could not load ${target}: ${reason}.`,\n\t\t'Set claudeSdkOauthProvider.systemPromptFile to a readable, non-empty UTF-8 prompt file, or select systemPromptMode \"full\".',\n\t].join(\" \");\n}\n\nconst armedSessions = new Set<string>();\n\nexport function resetPresetAppendDeprecation(sessionId?: string): void {\n\tif (sessionId !== undefined) {\n\t\tarmedSessions.delete(sessionId);\n\t} else {\n\t\tarmedSessions.clear();\n\t}\n}\n\nexport function presetAppendDeprecationGuidance(options: {\n\tmode: SystemPromptMode;\n\tconflict?: boolean;\n\tsessionId: string;\n}): string | undefined {\n\tif (armedSessions.has(options.sessionId)) {\n\t\treturn undefined;\n\t}\n\tconst isDeprecated = options.mode === \"preset-append\";\n\tif (!options.conflict && !isDeprecated) {\n\t\treturn undefined;\n\t}\n\tarmedSessions.add(options.sessionId);\n\tconst parts: string[] = [];\n\tif (isDeprecated) {\n\t\tparts.push(\n\t\t\t\"preset-append system-prompt mode is deprecated; \" +\n\t\t\t\t\"`full` mode delivers the complete senpi system prompt; \" +\n\t\t\t\t\"preset-append will be removed after one release.\",\n\t\t);\n\t}\n\tif (options.conflict) {\n\t\tparts.push(\"systemPromptMode wins.\");\n\t}\n\treturn parts.join(\" \");\n}\n"]}
@@ -39,8 +39,8 @@ export type BindingEntryState = {
39
39
  * absent sent-stream.
40
40
  */
41
41
  export declare function storedBindingFromEntry(entry: BindingEntryState, hashes: readonly string[], anchor: StoredBindingAnchor): StoredBinding;
42
- /** Hashes for the user/toolResult messages the persisted branch already carries. */
43
- export declare function sentHashesFromBranch(branch: readonly BranchEntry[]): string[];
42
+ /** Persist a completed turn whose resident registry entry closed before `message_end`. */
43
+ export declare function storedBindingFromBinding(binding: ContinuityBinding, hashes: readonly string[], anchor: StoredBindingAnchor): StoredBinding | undefined;
44
44
  export declare function bindingFromStoredBranch(branch: readonly BranchEntry[], stored: StoredBinding): ContinuityBinding | undefined;
45
45
  export {};
46
46
  //# sourceMappingURL=session-binding.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"session-binding.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/claude-sdk-oauth/session-binding.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAEhE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAG/D,eAAO,MAAM,kBAAkB,6BAA6B,CAAC;AAC7D,eAAO,MAAM,cAAc;;;CAA8C,CAAC;AAE1E,MAAM,MAAM,mBAAmB,GAAG;IACjC,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,KAAK,WAAW,GAAG;IAClB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IACjC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC/B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,oBAAoB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC3D,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACrC,KAAK,EAAE,iBAAiB,EACxB,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,MAAM,EAAE,mBAAmB,GACzB,aAAa,CAgBf;AAED,oFAAoF;AACpF,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,GAAG,MAAM,EAAE,CAW7E;AASD,wBAAgB,uBAAuB,CACtC,MAAM,EAAE,SAAS,WAAW,EAAE,EAC9B,MAAM,EAAE,aAAa,GACnB,iBAAiB,GAAG,SAAS,CAe/B"}
1
+ {"version":3,"file":"session-binding.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/claude-sdk-oauth/session-binding.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAEhE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAG/D,eAAO,MAAM,kBAAkB,6BAA6B,CAAC;AAC7D,eAAO,MAAM,cAAc;;;CAA8C,CAAC;AAE1E,MAAM,MAAM,mBAAmB,GAAG;IACjC,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,KAAK,WAAW,GAAG;IAClB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IACjC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC/B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,oBAAoB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC3D,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACrC,KAAK,EAAE,iBAAiB,EACxB,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,MAAM,EAAE,mBAAmB,GACzB,aAAa,CAgBf;AAED,0FAA0F;AAC1F,wBAAgB,wBAAwB,CACvC,OAAO,EAAE,iBAAiB,EAC1B,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,MAAM,EAAE,mBAAmB,GACzB,aAAa,GAAG,SAAS,CAsB3B;AAED,wBAAgB,uBAAuB,CACtC,MAAM,EAAE,SAAS,WAAW,EAAE,EAC9B,MAAM,EAAE,aAAa,GACnB,iBAAiB,GAAG,SAAS,CAe/B"}
@@ -1,5 +1,6 @@
1
+ import { GOAL_CONTINUATION_MESSAGE_TYPE } from "../../../messages.js";
1
2
  import { assistantContentHash } from "./session-commit-boundary.js";
2
- import { isTransmittedMessage, sentHashPrefixDigest, sentMessageHashes } from "./session-sync.js";
3
+ import { sentHashPrefixDigest } from "./session-sync.js";
3
4
  export const BINDING_ENTRY_TYPE = "claude-sdk-oauth-binding";
4
5
  export const BINDING_MARKER = { schemaVersion: 2, marker: true };
5
6
  /**
@@ -26,29 +27,31 @@ export function storedBindingFromEntry(entry, hashes, anchor) {
26
27
  toolsetHash: entry.toolsetHash,
27
28
  };
28
29
  }
29
- /** Hashes for the user/toolResult messages the persisted branch already carries. */
30
- export function sentHashesFromBranch(branch) {
31
- // This walk is not compaction-aware, but admission compares against the
32
- // compaction-truncated context. Anchoring across a boundary would inflate
33
- // sentCount and flatten every later restart, so decline to anchor instead.
34
- if (branch.some((entry) => entry.type === "compaction"))
35
- return [];
36
- const messages = [];
37
- for (const entry of branch) {
38
- if (entry.type !== "message")
39
- continue;
40
- if (isSentMessage(entry.message))
41
- messages.push(entry.message);
42
- }
43
- return sentMessageHashes(messages);
44
- }
45
- function isSentMessage(value) {
46
- if (typeof value !== "object" || value === null)
47
- return false;
48
- if (!("role" in value) || typeof value.role !== "string" || !("content" in value))
49
- return false;
50
- // Same selection rule the context path uses, so the digests cannot diverge.
51
- return isTransmittedMessage(value);
30
+ /** Persist a completed turn whose resident registry entry closed before `message_end`. */
31
+ export function storedBindingFromBinding(binding, hashes, anchor) {
32
+ if (binding.sdkSessionIdConfirmed === false)
33
+ return undefined;
34
+ if (binding.sentCount !== hashes.length)
35
+ return undefined;
36
+ const expectedDigest = sentHashPrefixDigest(hashes);
37
+ const bindingDigest = binding.sentPrefixHash ?? (binding.sentHashes.length > 0 ? sentHashPrefixDigest(binding.sentHashes) : undefined);
38
+ if (bindingDigest === undefined || bindingDigest !== expectedDigest)
39
+ return undefined;
40
+ return {
41
+ schemaVersion: 1,
42
+ sessionPath: anchor.sessionPath,
43
+ sessionId: anchor.sessionId,
44
+ markerEntryId: anchor.markerEntryId,
45
+ sdkSessionId: binding.sdkSessionId,
46
+ sentCount: hashes.length,
47
+ sentPrefixHash: sentHashPrefixDigest(hashes),
48
+ assistantContentHash: anchor.assistantContentHash,
49
+ lastAssistantUuid: binding.lastAssistantUuid,
50
+ accountName: binding.accountName,
51
+ modelId: binding.modelId,
52
+ systemPromptHash: binding.systemPromptHash,
53
+ toolsetHash: binding.toolsetHash,
54
+ };
52
55
  }
53
56
  export function bindingFromStoredBranch(branch, stored) {
54
57
  const markerIndex = newestBindingEntryIndex(branch);
@@ -78,10 +81,13 @@ const SAFE_BINDING_SUFFIX_TYPES = new Set([
78
81
  "senpi.hooks.stop-output",
79
82
  "pi-rules.scan",
80
83
  "rule-activation",
84
+ "goal-cache-warmup",
81
85
  ]);
82
86
  function isSafeBindingSuffix(entry) {
83
87
  if (entry.type === "label")
84
88
  return true;
89
+ if (entry.type === "custom_message")
90
+ return entry.customType === GOAL_CONTINUATION_MESSAGE_TYPE;
85
91
  return entry.type === "custom" && entry.customType !== undefined && SAFE_BINDING_SUFFIX_TYPES.has(entry.customType);
86
92
  }
87
93
  function newestBindingEntryIndex(branch) {
@@ -1 +1 @@
1
- {"version":3,"file":"session-binding.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/claude-sdk-oauth/session-binding.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AssistantMessage } from \"@earendil-works/pi-ai\";\nimport type { StoredBinding } from \"./session-binding-store.ts\";\nimport { assistantContentHash } from \"./session-commit-boundary.ts\";\nimport type { ContinuityBinding } from \"./session-reattach.ts\";\nimport { isTransmittedMessage, type SentMessage, sentHashPrefixDigest, sentMessageHashes } from \"./session-sync.ts\";\n\nexport const BINDING_ENTRY_TYPE = \"claude-sdk-oauth-binding\";\nexport const BINDING_MARKER = { schemaVersion: 2, marker: true } as const;\n\nexport type BindingInvalidation = {\n\treadonly schemaVersion: 1;\n\treadonly invalidated: true;\n\treadonly reason: string;\n};\n\ntype BranchEntry = {\n\treadonly id?: string;\n\treadonly type: string;\n\treadonly customType?: string;\n\treadonly data?: unknown;\n\treadonly message?: unknown;\n};\n\nexport type StoredBindingAnchor = {\n\treadonly sessionPath: string;\n\treadonly sessionId: string;\n\treadonly markerEntryId: string;\n\treadonly assistantContentHash: string;\n};\n\nexport type BindingEntryState = {\n\treadonly sdkSessionId: string;\n\treadonly accountName: string;\n\treadonly modelId: string;\n\treadonly systemPromptHash: string;\n\treadonly toolsetHash: string;\n\treadonly assistantUuidByIndex: ReadonlyMap<number, string>;\n};\n\n/**\n * The record is derived from the registry entry plus the hashes the branch\n * actually carries, never from the process binding map: that map holds the\n * previous turn's state while `message_end` runs (and only a prefix digest right\n * after a restart), so reading it would anchor this turn's marker to a stale or\n * absent sent-stream.\n */\nexport function storedBindingFromEntry(\n\tentry: BindingEntryState,\n\thashes: readonly string[],\n\tanchor: StoredBindingAnchor,\n): StoredBinding {\n\treturn {\n\t\tschemaVersion: 1,\n\t\tsessionPath: anchor.sessionPath,\n\t\tsessionId: anchor.sessionId,\n\t\tmarkerEntryId: anchor.markerEntryId,\n\t\tsdkSessionId: entry.sdkSessionId,\n\t\tsentCount: hashes.length,\n\t\tsentPrefixHash: sentHashPrefixDigest(hashes),\n\t\tassistantContentHash: anchor.assistantContentHash,\n\t\tlastAssistantUuid: entry.assistantUuidByIndex.get(hashes.length) ?? null,\n\t\taccountName: entry.accountName,\n\t\tmodelId: entry.modelId,\n\t\tsystemPromptHash: entry.systemPromptHash,\n\t\ttoolsetHash: entry.toolsetHash,\n\t};\n}\n\n/** Hashes for the user/toolResult messages the persisted branch already carries. */\nexport function sentHashesFromBranch(branch: readonly BranchEntry[]): string[] {\n\t// This walk is not compaction-aware, but admission compares against the\n\t// compaction-truncated context. Anchoring across a boundary would inflate\n\t// sentCount and flatten every later restart, so decline to anchor instead.\n\tif (branch.some((entry) => entry.type === \"compaction\")) return [];\n\tconst messages: SentMessage[] = [];\n\tfor (const entry of branch) {\n\t\tif (entry.type !== \"message\") continue;\n\t\tif (isSentMessage(entry.message)) messages.push(entry.message);\n\t}\n\treturn sentMessageHashes(messages);\n}\n\nfunction isSentMessage(value: unknown): value is SentMessage {\n\tif (typeof value !== \"object\" || value === null) return false;\n\tif (!(\"role\" in value) || typeof value.role !== \"string\" || !(\"content\" in value)) return false;\n\t// Same selection rule the context path uses, so the digests cannot diverge.\n\treturn isTransmittedMessage(value as { role: string });\n}\n\nexport function bindingFromStoredBranch(\n\tbranch: readonly BranchEntry[],\n\tstored: StoredBinding,\n): ContinuityBinding | undefined {\n\tconst markerIndex = newestBindingEntryIndex(branch);\n\tif (markerIndex < 0) return undefined;\n\tconst marker = branch[markerIndex];\n\tif (\n\t\tmarker?.id !== stored.markerEntryId ||\n\t\t!isBindingMarker(marker.data) ||\n\t\t!branch.slice(markerIndex + 2).every(isSafeBindingSuffix)\n\t) {\n\t\treturn undefined;\n\t}\n\tconst committedAssistant = branch[markerIndex + 1]?.message;\n\tif (!isAssistantMessage(committedAssistant)) return undefined;\n\tif (assistantContentHash(committedAssistant) !== stored.assistantContentHash) return undefined;\n\treturn bindingFromStored(stored);\n}\n\n/**\n * Display-only metadata the co-resident builtins append after the committed\n * assistant (stop-hook state/diagnostics/output, rule activations, rule scans).\n * None participates in the sent stream, so none can shift the prefix digest.\n */\nconst SAFE_BINDING_SUFFIX_TYPES: ReadonlySet<string> = new Set([\n\t\"senpi.hooks.stop-state\",\n\t\"senpi.hooks.stop-diagnostics\",\n\t\"senpi.hooks.stop-output\",\n\t\"pi-rules.scan\",\n\t\"rule-activation\",\n]);\n\nfunction isSafeBindingSuffix(entry: BranchEntry): boolean {\n\tif (entry.type === \"label\") return true;\n\treturn entry.type === \"custom\" && entry.customType !== undefined && SAFE_BINDING_SUFFIX_TYPES.has(entry.customType);\n}\n\nfunction newestBindingEntryIndex(branch: readonly BranchEntry[]): number {\n\tfor (let index = branch.length - 1; index >= 0; index -= 1) {\n\t\tconst entry = branch[index];\n\t\tif (entry?.type === \"custom\" && entry.customType === BINDING_ENTRY_TYPE) return index;\n\t}\n\treturn -1;\n}\n\nfunction isBindingMarker(value: unknown): boolean {\n\tif (typeof value !== \"object\" || value === null) return false;\n\treturn \"schemaVersion\" in value && value.schemaVersion === 2 && \"marker\" in value && value.marker === true;\n}\n\nfunction isAssistantMessage(value: unknown): value is AssistantMessage {\n\tif (typeof value !== \"object\" || value === null) return false;\n\treturn (\n\t\t\"role\" in value &&\n\t\tvalue.role === \"assistant\" &&\n\t\t\"api\" in value &&\n\t\ttypeof value.api === \"string\" &&\n\t\t\"provider\" in value &&\n\t\ttypeof value.provider === \"string\" &&\n\t\t\"model\" in value &&\n\t\ttypeof value.model === \"string\" &&\n\t\t\"content\" in value &&\n\t\tArray.isArray(value.content)\n\t);\n}\n\nfunction bindingFromStored(stored: StoredBinding): ContinuityBinding {\n\treturn {\n\t\tsenpiSessionId: stored.sessionId,\n\t\tsdkSessionId: stored.sdkSessionId,\n\t\tsentCount: stored.sentCount,\n\t\tsentHashes: [],\n\t\tsentPrefixHash: stored.sentPrefixHash,\n\t\tlastAssistantUuid: stored.lastAssistantUuid,\n\t\tassistantUuidByIndex: stored.lastAssistantUuid === null ? [] : [[stored.sentCount, stored.lastAssistantUuid]],\n\t\taccountName: stored.accountName,\n\t\tmodelId: stored.modelId,\n\t\tsystemPromptHash: stored.systemPromptHash,\n\t\ttoolsetHash: stored.toolsetHash,\n\t};\n}\n"]}
1
+ {"version":3,"file":"session-binding.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/claude-sdk-oauth/session-binding.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AssistantMessage } from \"@earendil-works/pi-ai\";\nimport { GOAL_CONTINUATION_MESSAGE_TYPE } from \"../../../messages.ts\";\nimport type { StoredBinding } from \"./session-binding-store.ts\";\nimport { assistantContentHash } from \"./session-commit-boundary.ts\";\nimport type { ContinuityBinding } from \"./session-reattach.ts\";\nimport { sentHashPrefixDigest } from \"./session-sync.ts\";\n\nexport const BINDING_ENTRY_TYPE = \"claude-sdk-oauth-binding\";\nexport const BINDING_MARKER = { schemaVersion: 2, marker: true } as const;\n\nexport type BindingInvalidation = {\n\treadonly schemaVersion: 1;\n\treadonly invalidated: true;\n\treadonly reason: string;\n};\n\ntype BranchEntry = {\n\treadonly id?: string;\n\treadonly type: string;\n\treadonly customType?: string;\n\treadonly data?: unknown;\n\treadonly message?: unknown;\n};\n\nexport type StoredBindingAnchor = {\n\treadonly sessionPath: string;\n\treadonly sessionId: string;\n\treadonly markerEntryId: string;\n\treadonly assistantContentHash: string;\n};\n\nexport type BindingEntryState = {\n\treadonly sdkSessionId: string;\n\treadonly accountName: string;\n\treadonly modelId: string;\n\treadonly systemPromptHash: string;\n\treadonly toolsetHash: string;\n\treadonly assistantUuidByIndex: ReadonlyMap<number, string>;\n};\n\n/**\n * The record is derived from the registry entry plus the hashes the branch\n * actually carries, never from the process binding map: that map holds the\n * previous turn's state while `message_end` runs (and only a prefix digest right\n * after a restart), so reading it would anchor this turn's marker to a stale or\n * absent sent-stream.\n */\nexport function storedBindingFromEntry(\n\tentry: BindingEntryState,\n\thashes: readonly string[],\n\tanchor: StoredBindingAnchor,\n): StoredBinding {\n\treturn {\n\t\tschemaVersion: 1,\n\t\tsessionPath: anchor.sessionPath,\n\t\tsessionId: anchor.sessionId,\n\t\tmarkerEntryId: anchor.markerEntryId,\n\t\tsdkSessionId: entry.sdkSessionId,\n\t\tsentCount: hashes.length,\n\t\tsentPrefixHash: sentHashPrefixDigest(hashes),\n\t\tassistantContentHash: anchor.assistantContentHash,\n\t\tlastAssistantUuid: entry.assistantUuidByIndex.get(hashes.length) ?? null,\n\t\taccountName: entry.accountName,\n\t\tmodelId: entry.modelId,\n\t\tsystemPromptHash: entry.systemPromptHash,\n\t\ttoolsetHash: entry.toolsetHash,\n\t};\n}\n\n/** Persist a completed turn whose resident registry entry closed before `message_end`. */\nexport function storedBindingFromBinding(\n\tbinding: ContinuityBinding,\n\thashes: readonly string[],\n\tanchor: StoredBindingAnchor,\n): StoredBinding | undefined {\n\tif (binding.sdkSessionIdConfirmed === false) return undefined;\n\tif (binding.sentCount !== hashes.length) return undefined;\n\tconst expectedDigest = sentHashPrefixDigest(hashes);\n\tconst bindingDigest =\n\t\tbinding.sentPrefixHash ?? (binding.sentHashes.length > 0 ? sentHashPrefixDigest(binding.sentHashes) : undefined);\n\tif (bindingDigest === undefined || bindingDigest !== expectedDigest) return undefined;\n\treturn {\n\t\tschemaVersion: 1,\n\t\tsessionPath: anchor.sessionPath,\n\t\tsessionId: anchor.sessionId,\n\t\tmarkerEntryId: anchor.markerEntryId,\n\t\tsdkSessionId: binding.sdkSessionId,\n\t\tsentCount: hashes.length,\n\t\tsentPrefixHash: sentHashPrefixDigest(hashes),\n\t\tassistantContentHash: anchor.assistantContentHash,\n\t\tlastAssistantUuid: binding.lastAssistantUuid,\n\t\taccountName: binding.accountName,\n\t\tmodelId: binding.modelId,\n\t\tsystemPromptHash: binding.systemPromptHash,\n\t\ttoolsetHash: binding.toolsetHash,\n\t};\n}\n\nexport function bindingFromStoredBranch(\n\tbranch: readonly BranchEntry[],\n\tstored: StoredBinding,\n): ContinuityBinding | undefined {\n\tconst markerIndex = newestBindingEntryIndex(branch);\n\tif (markerIndex < 0) return undefined;\n\tconst marker = branch[markerIndex];\n\tif (\n\t\tmarker?.id !== stored.markerEntryId ||\n\t\t!isBindingMarker(marker.data) ||\n\t\t!branch.slice(markerIndex + 2).every(isSafeBindingSuffix)\n\t) {\n\t\treturn undefined;\n\t}\n\tconst committedAssistant = branch[markerIndex + 1]?.message;\n\tif (!isAssistantMessage(committedAssistant)) return undefined;\n\tif (assistantContentHash(committedAssistant) !== stored.assistantContentHash) return undefined;\n\treturn bindingFromStored(stored);\n}\n\n/**\n * Display-only metadata the co-resident builtins append after the committed\n * assistant (stop-hook state/diagnostics/output, rule activations, rule scans).\n * None participates in the sent stream, so none can shift the prefix digest.\n */\nconst SAFE_BINDING_SUFFIX_TYPES: ReadonlySet<string> = new Set([\n\t\"senpi.hooks.stop-state\",\n\t\"senpi.hooks.stop-diagnostics\",\n\t\"senpi.hooks.stop-output\",\n\t\"pi-rules.scan\",\n\t\"rule-activation\",\n\t\"goal-cache-warmup\",\n]);\n\nfunction isSafeBindingSuffix(entry: BranchEntry): boolean {\n\tif (entry.type === \"label\") return true;\n\tif (entry.type === \"custom_message\") return entry.customType === GOAL_CONTINUATION_MESSAGE_TYPE;\n\treturn entry.type === \"custom\" && entry.customType !== undefined && SAFE_BINDING_SUFFIX_TYPES.has(entry.customType);\n}\n\nfunction newestBindingEntryIndex(branch: readonly BranchEntry[]): number {\n\tfor (let index = branch.length - 1; index >= 0; index -= 1) {\n\t\tconst entry = branch[index];\n\t\tif (entry?.type === \"custom\" && entry.customType === BINDING_ENTRY_TYPE) return index;\n\t}\n\treturn -1;\n}\n\nfunction isBindingMarker(value: unknown): boolean {\n\tif (typeof value !== \"object\" || value === null) return false;\n\treturn \"schemaVersion\" in value && value.schemaVersion === 2 && \"marker\" in value && value.marker === true;\n}\n\nfunction isAssistantMessage(value: unknown): value is AssistantMessage {\n\tif (typeof value !== \"object\" || value === null) return false;\n\treturn (\n\t\t\"role\" in value &&\n\t\tvalue.role === \"assistant\" &&\n\t\t\"api\" in value &&\n\t\ttypeof value.api === \"string\" &&\n\t\t\"provider\" in value &&\n\t\ttypeof value.provider === \"string\" &&\n\t\t\"model\" in value &&\n\t\ttypeof value.model === \"string\" &&\n\t\t\"content\" in value &&\n\t\tArray.isArray(value.content)\n\t);\n}\n\nfunction bindingFromStored(stored: StoredBinding): ContinuityBinding {\n\treturn {\n\t\tsenpiSessionId: stored.sessionId,\n\t\tsdkSessionId: stored.sdkSessionId,\n\t\tsentCount: stored.sentCount,\n\t\tsentHashes: [],\n\t\tsentPrefixHash: stored.sentPrefixHash,\n\t\tlastAssistantUuid: stored.lastAssistantUuid,\n\t\tassistantUuidByIndex: stored.lastAssistantUuid === null ? [] : [[stored.sentCount, stored.lastAssistantUuid]],\n\t\taccountName: stored.accountName,\n\t\tmodelId: stored.modelId,\n\t\tsystemPromptHash: stored.systemPromptHash,\n\t\ttoolsetHash: stored.toolsetHash,\n\t};\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"session-registry-wiring.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/claude-sdk-oauth/session-registry-wiring.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,gBAAgB,CAAC;AAyDrE,wBAAgB,uBAAuB,CACtC,EAAE,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC,GACvE,IAAI,CAqGN"}
1
+ {"version":3,"file":"session-registry-wiring.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/claude-sdk-oauth/session-registry-wiring.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,gBAAgB,CAAC;AAyDrE,wBAAgB,uBAAuB,CACtC,EAAE,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC,GACvE,IAAI,CAkHN"}
@@ -1,10 +1,11 @@
1
+ import { convertToLlm } from "../../../messages.js";
1
2
  import { CLAUDE_SDK_OAUTH_PROVIDER_ID } from "./account-management.js";
2
- import { BINDING_ENTRY_TYPE, BINDING_MARKER, bindingFromStoredBranch, sentHashesFromBranch, storedBindingFromEntry, } from "./session-binding.js";
3
+ import { BINDING_ENTRY_TYPE, BINDING_MARKER, bindingFromStoredBranch, storedBindingFromBinding, storedBindingFromEntry, } from "./session-binding.js";
3
4
  import { deleteStoredBinding, readStoredBinding, writeStoredBinding } from "./session-binding-store.js";
4
5
  import { AssistantCommitBoundary, assistantContentHash, isResidentAssistant, isTerminalFailure, } from "./session-commit-boundary.js";
5
- import { bindingFromEntry, forgetBinding, rememberBinding } from "./session-reattach.js";
6
+ import { bindingFromEntry, forgetBinding, getBinding, rememberBinding } from "./session-reattach.js";
6
7
  import { closeSession, getSession, recordBranchInfo, recordPendingFork, switchSessionModel, } from "./session-registry.js";
7
- import { sentHashesForEntry } from "./session-sync.js";
8
+ import { sentHashesForEntry, sentMessageHashes, sentMessages } from "./session-sync.js";
8
9
  const commitBoundary = new AssistantCommitBoundary();
9
10
  function persistBindingInvalidation(pi, reason) {
10
11
  pi.appendEntry?.(BINDING_ENTRY_TYPE, { schemaVersion: 1, invalidated: true, reason });
@@ -102,13 +103,15 @@ export function registerSessionRegistry(pi) {
102
103
  return;
103
104
  const sessionId = ctx.sessionManager.getSessionId();
104
105
  const entry = getSession(sessionId);
105
- if (!entry)
106
+ const binding = getBinding(sessionId);
107
+ const modelId = entry?.modelId ?? binding?.modelId;
108
+ if (!modelId)
106
109
  return;
107
110
  if (isTerminalFailure(event.message)) {
108
111
  commitBoundary.forget(sessionId);
109
112
  return;
110
113
  }
111
- const outcome = commitBoundary.commit(sessionId, event.message, entry.modelId);
114
+ const outcome = commitBoundary.commit(sessionId, event.message, modelId);
112
115
  if (outcome === "rewritten") {
113
116
  recordPendingFork(sessionId, "assistant_rewritten");
114
117
  await invalidateBinding(pi, ctx, "assistant_rewritten");
@@ -120,19 +123,34 @@ export function registerSessionRegistry(pi) {
120
123
  const sessionFile = ctx.sessionManager.getSessionFile?.();
121
124
  if (!sessionFile || !pi.appendEntry)
122
125
  return;
123
- const hashes = sentHashesFromBranch(ctx.sessionManager.getBranch());
124
- if (hashes.length === 0)
126
+ const context = ctx.sessionManager.buildSessionContext();
127
+ const hashes = sentMessageHashes(sentMessages({ ...context, messages: convertToLlm(context.messages) }));
128
+ const committedAssistantHash = assistantContentHash(event.message);
129
+ const recordFor = (markerEntryId) => {
130
+ const anchor = {
131
+ sessionPath: sessionFile,
132
+ sessionId,
133
+ markerEntryId,
134
+ assistantContentHash: committedAssistantHash,
135
+ };
136
+ return entry
137
+ ? storedBindingFromEntry(entry, hashes, anchor)
138
+ : binding
139
+ ? storedBindingFromBinding(binding, hashes, anchor)
140
+ : undefined;
141
+ };
142
+ // Validate before touching the branch: a rejected closed-entry fallback must
143
+ // not leave a marker-only entry that retires the still-valid older sidecar.
144
+ if (!recordFor("pending"))
125
145
  return;
126
146
  pi.appendEntry(BINDING_ENTRY_TYPE, BINDING_MARKER);
127
147
  const markerEntryId = ctx.sessionManager.getLeafId();
128
148
  if (!markerEntryId)
129
149
  return;
130
- await writeStoredBinding(sessionFile, storedBindingFromEntry(entry, hashes, {
131
- sessionPath: sessionFile,
132
- sessionId,
133
- markerEntryId,
134
- assistantContentHash: assistantContentHash(event.message),
135
- }));
150
+ const stored = recordFor(markerEntryId);
151
+ if (!stored)
152
+ return;
153
+ await writeStoredBinding(sessionFile, stored);
136
154
  });
137
155
  pi.on("session_shutdown", (event, ctx) => {
138
156
  closeSession(ctx.sessionManager.getSessionId(), event.reason);