@eddyskywalker/dsh-chatgpt-subscription 0.46.1 → 0.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/README.md +22 -1
  3. package/lib/client.js +2639 -571
  4. package/lib/client.js.map +1 -1
  5. package/lib/index.js +15598 -5902
  6. package/lib/plan-mode-pipeline.js +419 -0
  7. package/lib/plan-mode.js +783 -0
  8. package/lib/tool-result-pruner.js +400 -0
  9. package/lib/types/client/hub/brand-icons.d.ts +1 -1
  10. package/lib/types/client/hub/brand-icons.d.ts.map +1 -1
  11. package/lib/types/client/hub/brand-svg.d.ts +4 -0
  12. package/lib/types/client/hub/brand-svg.d.ts.map +1 -1
  13. package/lib/types/client/hub/providers.d.ts.map +1 -1
  14. package/lib/types/client/index.d.ts +2 -0
  15. package/lib/types/client/index.d.ts.map +1 -1
  16. package/lib/types/client/locales-ru/index.d.ts.map +1 -1
  17. package/lib/types/client/locales-ru/progress-updates.d.ts.map +1 -1
  18. package/lib/types/client/locales-ru/workbuddy.d.ts +10 -0
  19. package/lib/types/client/locales-ru/workbuddy.d.ts.map +1 -0
  20. package/lib/types/client/progress-updates/locales.d.ts +23 -5
  21. package/lib/types/client/progress-updates/locales.d.ts.map +1 -1
  22. package/lib/types/client/progress-updates/settings-binding.d.ts +13 -1
  23. package/lib/types/client/progress-updates/settings-binding.d.ts.map +1 -1
  24. package/lib/types/client/progress-updates/settings-section.d.ts +1 -1
  25. package/lib/types/client/progress-updates/settings-section.d.ts.map +1 -1
  26. package/lib/types/client/workbuddy/WorkBuddyComposerQuota.d.ts +34 -0
  27. package/lib/types/client/workbuddy/WorkBuddyComposerQuota.d.ts.map +1 -0
  28. package/lib/types/client/workbuddy/WorkBuddySection.d.ts +91 -0
  29. package/lib/types/client/workbuddy/WorkBuddySection.d.ts.map +1 -0
  30. package/lib/types/client/workbuddy/locales.d.ts +768 -0
  31. package/lib/types/client/workbuddy/locales.d.ts.map +1 -0
  32. package/lib/types/client/workbuddy/styles.d.ts +21 -0
  33. package/lib/types/client/workbuddy/styles.d.ts.map +1 -0
  34. package/lib/types/client/workbuddy/useWorkBuddySection.d.ts +149 -0
  35. package/lib/types/client/workbuddy/useWorkBuddySection.d.ts.map +1 -0
  36. package/lib/types/compat.d.ts +1 -1
  37. package/lib/types/entry-plan-mode-pipeline.d.ts +206 -0
  38. package/lib/types/entry-plan-mode-pipeline.d.ts.map +1 -0
  39. package/lib/types/entry-plan-mode.d.ts +353 -0
  40. package/lib/types/entry-plan-mode.d.ts.map +1 -0
  41. package/lib/types/entry-tool-result-pruner.d.ts +255 -0
  42. package/lib/types/entry-tool-result-pruner.d.ts.map +1 -0
  43. package/lib/types/host/agent-preset.d.ts.map +1 -1
  44. package/lib/types/host/cache-warmup/contracts.d.ts +5 -1
  45. package/lib/types/host/cache-warmup/contracts.d.ts.map +1 -1
  46. package/lib/types/host/cache-warmup/install.d.ts.map +1 -1
  47. package/lib/types/host/cache-warmup/projection.d.ts.map +1 -1
  48. package/lib/types/host/cache-warmup/retrieval-intent.d.ts +18 -0
  49. package/lib/types/host/cache-warmup/retrieval-intent.d.ts.map +1 -0
  50. package/lib/types/host/cache-warmup/settings.d.ts +9 -2
  51. package/lib/types/host/cache-warmup/settings.d.ts.map +1 -1
  52. package/lib/types/host/common/capabilities.d.ts.map +1 -1
  53. package/lib/types/host/common/model-request-control.d.ts +1 -1
  54. package/lib/types/host/common/model-request-control.d.ts.map +1 -1
  55. package/lib/types/host/common/request-diagnostics.d.ts +1 -1
  56. package/lib/types/host/common/request-diagnostics.d.ts.map +1 -1
  57. package/lib/types/host/compaction-policy-guard.d.ts +58 -0
  58. package/lib/types/host/compaction-policy-guard.d.ts.map +1 -0
  59. package/lib/types/host/compaction-prompt.d.ts +129 -0
  60. package/lib/types/host/compaction-prompt.d.ts.map +1 -0
  61. package/lib/types/host/plan-mode-cache-guard.d.ts +16 -0
  62. package/lib/types/host/plan-mode-cache-guard.d.ts.map +1 -0
  63. package/lib/types/host/preset-sync.d.ts.map +1 -1
  64. package/lib/types/host/ptc-sdk-cache-guard.d.ts +80 -0
  65. package/lib/types/host/ptc-sdk-cache-guard.d.ts.map +1 -0
  66. package/lib/types/host/tool-result-pruner-guard.d.ts +34 -0
  67. package/lib/types/host/tool-result-pruner-guard.d.ts.map +1 -0
  68. package/lib/types/host/workbuddy/account-pool.d.ts +389 -0
  69. package/lib/types/host/workbuddy/account-pool.d.ts.map +1 -0
  70. package/lib/types/host/workbuddy/adapter.d.ts +249 -0
  71. package/lib/types/host/workbuddy/adapter.d.ts.map +1 -0
  72. package/lib/types/host/workbuddy/atrest.d.ts +98 -0
  73. package/lib/types/host/workbuddy/atrest.d.ts.map +1 -0
  74. package/lib/types/host/workbuddy/checkin.d.ts +150 -0
  75. package/lib/types/host/workbuddy/checkin.d.ts.map +1 -0
  76. package/lib/types/host/workbuddy/client.d.ts +214 -0
  77. package/lib/types/host/workbuddy/client.d.ts.map +1 -0
  78. package/lib/types/host/workbuddy/dsml.d.ts +55 -0
  79. package/lib/types/host/workbuddy/dsml.d.ts.map +1 -0
  80. package/lib/types/host/workbuddy/guardrails.d.ts +111 -0
  81. package/lib/types/host/workbuddy/guardrails.d.ts.map +1 -0
  82. package/lib/types/host/workbuddy/identity.d.ts +71 -0
  83. package/lib/types/host/workbuddy/identity.d.ts.map +1 -0
  84. package/lib/types/host/workbuddy/mapper.d.ts +238 -0
  85. package/lib/types/host/workbuddy/mapper.d.ts.map +1 -0
  86. package/lib/types/host/workbuddy/model-catalog.d.ts +217 -0
  87. package/lib/types/host/workbuddy/model-catalog.d.ts.map +1 -0
  88. package/lib/types/host/workbuddy/oauth.d.ts +47 -0
  89. package/lib/types/host/workbuddy/oauth.d.ts.map +1 -0
  90. package/lib/types/host/workbuddy/outbound-identity.d.ts +139 -0
  91. package/lib/types/host/workbuddy/outbound-identity.d.ts.map +1 -0
  92. package/lib/types/host/workbuddy/routes.d.ts +56 -0
  93. package/lib/types/host/workbuddy/routes.d.ts.map +1 -0
  94. package/lib/types/host/workbuddy/token-store.d.ts +370 -0
  95. package/lib/types/host/workbuddy/token-store.d.ts.map +1 -0
  96. package/lib/types/host/workbuddy/types.d.ts +179 -0
  97. package/lib/types/host/workbuddy/types.d.ts.map +1 -0
  98. package/lib/types/index.d.ts +35 -0
  99. package/lib/types/index.d.ts.map +1 -1
  100. package/lib/types/shared/workbuddy-contracts.d.ts +531 -0
  101. package/lib/types/shared/workbuddy-contracts.d.ts.map +1 -0
  102. package/package.json +14 -2
  103. package/presets/dispatch/README.md +57 -3
  104. package/presets/dispatch/agent.cordis.yml +63 -3
@@ -0,0 +1,71 @@
1
+ /**
2
+ * WorkBuddy account identity, resolved from the credential itself.
3
+ *
4
+ * The defect this exists to prevent: {@link workBuddyAccountId} falls back to
5
+ * `nickname` when no uid is present, and the browser-login response carries the
6
+ * display name but no uid — so signing in to an account that the IDE already
7
+ * holds produced `intl:<e-mail>` from the login while the very same account
8
+ * scanned from the IDE's own `*.info` file produced `intl:<uuid>`. Two ids
9
+ * meant two pool rows, two entries in `/accounts` and two cards for one
10
+ * account, which is exactly what users reported as "the same account appears
11
+ * twice". The same fallback is why a credential that carried no display name at
12
+ * all was labelled "账号 1".
13
+ *
14
+ * A display name is not an identity. The access token is a Keycloak JWT whose
15
+ * `sub` is the account's stable uid on both deployments (measured against a
16
+ * live domestic and international token), so the identity is read from there
17
+ * and the file's or response's own fields are used only for what the token
18
+ * cannot supply.
19
+ */
20
+ import type { WorkBuddyCredentials } from './token-store.ts';
21
+ /** Identity facts a token or a login response can state about one account. */
22
+ export interface WorkBuddyTokenIdentity {
23
+ uid?: string;
24
+ nickname?: string;
25
+ uin?: string;
26
+ enterpriseId?: string;
27
+ }
28
+ /**
29
+ * Decode a JWT's payload without verifying it.
30
+ *
31
+ * Nothing here is a security decision: the claims only name the account so the
32
+ * plugin can tell two credentials apart. The token is still validated by the
33
+ * gateway on every request, so an unverified claim cannot grant anything — it
34
+ * can at most make two accounts look alike, which the request path would then
35
+ * reject on its own.
36
+ *
37
+ * Returns null for an opaque or malformed token rather than throwing: a
38
+ * non-JWT access token is a legitimate shape this route must keep working with.
39
+ */
40
+ export declare function decodeAccessTokenClaims(accessToken: string): Record<string, unknown> | null;
41
+ /** Read the identity facts one decoded claim set states. */
42
+ export declare function identityFromClaims(claims: Record<string, unknown>): WorkBuddyTokenIdentity;
43
+ /** Identity facts an access token states, or an empty object when it states none. */
44
+ export declare function identityFromAccessToken(accessToken: string): WorkBuddyTokenIdentity;
45
+ /**
46
+ * Whether a credential names its own account.
47
+ *
48
+ * {@link workBuddyAccountId} falls back to the auth domain, which is a property
49
+ * of the deployment rather than of the account: two accounts on one deployment
50
+ * would share it. A credential that states no uid, UIN or display name
51
+ * therefore has no identity to derive, and a caller holding a meaningful key
52
+ * already — a row the pool stored under one — must keep it instead of
53
+ * replacing it with a domain-derived key.
54
+ */
55
+ export declare function hasStableIdentity(credentials: Pick<WorkBuddyCredentials, 'uid' | 'uin' | 'nickname'>): boolean;
56
+ /**
57
+ * Backfill a credential's identity from its own access token.
58
+ *
59
+ * The token's `sub` is the account's uid, so it wins over a stored value that
60
+ * disagrees with it: that stored value can only have come from the login path
61
+ * that promoted a display name into `uid`, which is the record this function
62
+ * exists to heal. The displaced value is kept as the nickname when nothing else
63
+ * names the account, so a healed row still reads as something a person
64
+ * recognizes instead of an opaque uuid.
65
+ *
66
+ * Every other field is only filled in when the credential does not state it:
67
+ * what the IDE's file or the login response already records is not second
68
+ * guessed from a token.
69
+ */
70
+ export declare function withResolvedIdentity<T extends WorkBuddyCredentials>(credentials: T): T;
71
+ //# sourceMappingURL=identity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../../../src/host/workbuddy/identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AAE5D,8EAA8E;AAC9E,MAAM,WAAW,sBAAsB;IACrC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAaD;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAa3F;AAED,4DAA4D;AAC5D,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,sBAAsB,CAoB1F;AAED,qFAAqF;AACrF,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,sBAAsB,CAGnF;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,IAAI,CAAC,oBAAoB,EAAE,KAAK,GAAG,KAAK,GAAG,UAAU,CAAC,GAAG,OAAO,CAI9G;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,oBAAoB,EAAE,WAAW,EAAE,CAAC,GAAG,CAAC,CA2BtF"}
@@ -0,0 +1,238 @@
1
+ /**
2
+ * Wire mapping for the WorkBuddy / CodeBuddy subscription chat endpoint.
3
+ *
4
+ * The endpoint is OpenAI Chat Completions shaped, but with three measured
5
+ * deviations from the OpenAI default that this module exists to absorb:
6
+ *
7
+ * 1. **Stream only.** `stream: false` answers 400 `code 11101`. The request
8
+ * builder therefore always sends `stream: true`, and there is no
9
+ * non-streaming code path to keep in sync.
10
+ * 2. **A leading system message is mandatory on the international backend.**
11
+ * A request whose first message is a user turn answers 400 `code 11128`
12
+ * ("first message is not system prompt"). {@link buildChatRequest} injects
13
+ * one when the caller supplied none, so a hand-built one-shot request cannot
14
+ * trip this. Note that the same code is also the gateway's channel-verification
15
+ * refusal (`msg: "conversation id missing"`), which the conversation header
16
+ * group this route sends is what satisfies — see `conversationHeaders` in
17
+ * `client.ts`. A history that is already correct can still answer 11128 for
18
+ * that second reason, so the code alone does not implicate the messages.
19
+ * 3. **Reasoning rides `delta.reasoning_content`,** not OpenAI's
20
+ * `reasoning_summary`, and is emitted as its own DSH reasoning block.
21
+ */
22
+ import { type OutboundContentBlock, type GenerateOptions, type StreamChunk } from '../common/llm-compat.ts';
23
+ import { MAX_REQUEST_IMAGE_BYTES, NO_RESOLVED_IMAGES, SUPPORTED_IMAGE_MEDIA_TYPES, attachmentLabel, imageBlockToInline, offloadOldestRequestImages, requestImageTargetOrOriginal, resolveRequestImages, unavailableImageText, type AttachmentImageReader, type ResolvedRequestImage, type ResolvedRequestImages } from '../common/request-images.ts';
24
+ import { stripMetaSchema } from '../common/tool-schema.ts';
25
+ export declare function sanitizeText(text: string): string;
26
+ /**
27
+ * The system prompt every request must open with.
28
+ *
29
+ * The international backend rejects a request whose first message is not a
30
+ * system turn, so this stands in when the caller supplies no prompt at all. It
31
+ * is deliberately neutral: it must not change model behaviour beyond satisfying
32
+ * the shape check.
33
+ */
34
+ declare const IMPLICIT_SYSTEM_PROMPT = "You are a helpful assistant.";
35
+ /**
36
+ * The image seam is the SHARED kernel's, not this route's own.
37
+ *
38
+ * The old copy here carried a private 12 MB budget while the shared kernel
39
+ * bounds a request at {@link MAX_REQUEST_IMAGE_BYTES} (1.5 MB), and the adapter
40
+ * answered no `imageRequestTarget` at all — so the harness downscaled for a
41
+ * ceiling this mapper never applied, and the body could still exceed the one
42
+ * the kernel had already paid for. Re-exporting the kernel here keeps the
43
+ * projection, the budget and the target a single number.
44
+ *
45
+ * What stays route-specific is only what the WIRE shape needs ({@link
46
+ * MAX_REQUEST_IMAGE_BYTES} is imported for the doc link and the tests that pin
47
+ * it): the chat and Messages builders both consume the same resolution.
48
+ */
49
+ export { MAX_REQUEST_IMAGE_BYTES, NO_RESOLVED_IMAGES, SUPPORTED_IMAGE_MEDIA_TYPES, attachmentLabel, imageBlockToInline, offloadOldestRequestImages, requestImageTargetOrOriginal, resolveRequestImages, unavailableImageText, stripMetaSchema, };
50
+ export type { AttachmentImageReader, ResolvedRequestImage, ResolvedRequestImages };
51
+ /**
52
+ * Build one `/v2/chat/completions` body.
53
+ *
54
+ * Always `stream: true`: the endpoint rejects a non-streaming request outright
55
+ * (400 `code 11101`), so there is no second shape to produce.
56
+ */
57
+ export declare function buildChatRequest(options: GenerateOptions, images?: ResolvedRequestImages): Record<string, unknown>;
58
+ interface PendingToolCall {
59
+ blockIndex: number;
60
+ id: string;
61
+ name: string;
62
+ arguments: string;
63
+ started: boolean;
64
+ }
65
+ export interface WorkBuddyStreamState {
66
+ blocks: OutboundContentBlock[];
67
+ current: {
68
+ index: number;
69
+ type: 'text' | 'reasoning';
70
+ text: string;
71
+ } | null;
72
+ /** wire tool index -> accumulating call. */
73
+ toolCalls: Map<number, PendingToolCall>;
74
+ hasContent: boolean;
75
+ hasToolCall: boolean;
76
+ finishReason: string | null;
77
+ /** The `[DONE]` sentinel arrived. */
78
+ done: boolean;
79
+ /** Terminal chunks were already emitted. */
80
+ finished: boolean;
81
+ inputTokens: number;
82
+ outputTokens: number;
83
+ cacheReadTokens: number;
84
+ cacheWriteTokens: number;
85
+ reasoningTokens: number;
86
+ sawUsage: boolean;
87
+ /**
88
+ * Text held back while it may still turn into a printed tool call.
89
+ *
90
+ * `holding` is set once a `<` that could open a call region was seen; the
91
+ * buffer then grows until the region closes (or the cap is hit), and is
92
+ * resolved into prose or calls exactly once.
93
+ */
94
+ printed: {
95
+ pending: string;
96
+ holding: boolean;
97
+ };
98
+ }
99
+ export declare function createStreamState(): WorkBuddyStreamState;
100
+ /** Feed one SSE line from `/v2/chat/completions`. */
101
+ export declare function processStreamLine(line: string, state: WorkBuddyStreamState): StreamChunk[];
102
+ /** Flush every open block, then emit usage and the terminal finish. */
103
+ export declare function closeStream(state: WorkBuddyStreamState): StreamChunk[];
104
+ /**
105
+ * A stream that ends without a terminal event is truncated, not complete.
106
+ *
107
+ * The endpoint always terminates with either `finish_reason` or `[DONE]`, so
108
+ * their absence means the connection dropped mid-answer and the partial text
109
+ * must not be presented as a finished reply.
110
+ */
111
+ export declare function assertStreamComplete(state: WorkBuddyStreamState): void;
112
+ /** Whether one 11128 body is the channel refusal a system move can repair. */
113
+ export declare function isChannelRefusal11128(detail: string): boolean;
114
+ /**
115
+ * What a chat's system prompt is known by.
116
+ *
117
+ * The key is the system TEXT, not the conversation: one agent refused once must
118
+ * not pay the refusal again on its next conversation, which is a different
119
+ * message list with the same opening. A body whose system text is already the
120
+ * neutral default has nothing to move, so it keys as the empty string.
121
+ */
122
+ export declare function chatSystemKey(body: unknown): string;
123
+ /**
124
+ * Move a chat's system prompt into the first user turn, in INSTRUCTIONS tags,
125
+ * and leave the neutral default in the leading system position.
126
+ *
127
+ * A system message LATER in the history becomes a user message where it stands:
128
+ * the gateway refuses those too, and the position is meaningful to the model, so
129
+ * it is rewritten rather than lifted out and merged. String content is prefixed
130
+ * with the tagged text and a blank line; block content gets one extra leading
131
+ * text part, which is what keeps images and tool parts exactly where they were.
132
+ *
133
+ * Returns the new body as JSON, or NULL when there is nothing to move — a caller
134
+ * that gets null must not retry, because the second request would be the first
135
+ * one again.
136
+ */
137
+ export declare function relocateSystemToInstructions(body: unknown): string | null;
138
+ /**
139
+ * The id one USER SEND is known by, for the request-id header family.
140
+ *
141
+ * Derived from the harness history rather than from a clock or a counter: every
142
+ * tool step of one send appends to the history AFTER the user's own last
143
+ * message, so the same key is computed for all of them, and the user's next
144
+ * message is what changes it. Tool-result turns are skipped because they are the
145
+ * harness answering the model, not the user speaking — including them would give
146
+ * each tool step its own id, which is the behaviour this exists to prevent.
147
+ *
148
+ * Empty when there is no user turn to name, which the caller reads as "make a
149
+ * fresh id for this request" (config probes, compactions, and one-shot calls).
150
+ */
151
+ export declare function userTurnKey(options: GenerateOptions): string;
152
+ /**
153
+ * `anthropic-version` the Messages surface requires.
154
+ *
155
+ * Sent for every Messages request: without it the endpoint answers 400 rather
156
+ * than falling back to a default, so it is a protocol requirement and not a
157
+ * feature negotiation.
158
+ */
159
+ export declare const ANTHROPIC_VERSION = "2023-06-01";
160
+ /**
161
+ * Thinking control the Messages surface takes.
162
+ *
163
+ * Not the chat endpoint's `reasoning_effort`: Messages asks for thinking
164
+ * (`thinking.type: 'adaptive'`) and expresses the LEVEL in
165
+ * `output_config.effort`. Sending the chat spelling here is what made an
166
+ * effort pick do nothing, and 'max' is a legal level of this ladder, so it is
167
+ * carried verbatim rather than filtered through the chat ladder.
168
+ */
169
+ export declare const MESSAGES_THINKING_FIELD = "thinking";
170
+ export declare const MESSAGES_EFFORT_FIELD = "output_config";
171
+ export interface MessagesRequestOptions {
172
+ /** Durable user images resolved for this request. */
173
+ images?: ResolvedRequestImages;
174
+ /** Effort ladder the gateway catalog declares for this model; empty = no thinking. */
175
+ efforts?: readonly string[];
176
+ /** Effort the caller picked, carried verbatim (no chat-ladder filtering). */
177
+ effort?: string;
178
+ /** Output cap to use when the caller names none. */
179
+ defaultMaxTokens?: number;
180
+ }
181
+ /**
182
+ * Build one `/v1/messages` body.
183
+ *
184
+ * `stream: true` is mandatory: the adapter reads every response as SSE, and a
185
+ * non-streaming answer is one JSON document with no `data:` lines, no
186
+ * `message_stop` and no `stop_reason`.
187
+ *
188
+ * The system prompt travels as the top-level `system` string — the surface has
189
+ * a field for it, so the chat endpoint's "the first message must be a system
190
+ * turn" requirement does not exist here and no relocation is ever needed.
191
+ */
192
+ export declare function buildMessagesRequest(options: GenerateOptions, request?: MessagesRequestOptions): Record<string, unknown>;
193
+ interface MessagesTextBlock {
194
+ index: number;
195
+ kind: 'text' | 'reasoning';
196
+ text: string;
197
+ }
198
+ interface MessagesToolCall {
199
+ index: number;
200
+ id: string;
201
+ name: string;
202
+ arguments: string;
203
+ }
204
+ export interface MessagesStreamState {
205
+ blocks: OutboundContentBlock[];
206
+ /** wire content index -> open text or reasoning block. */
207
+ open: Map<number, MessagesTextBlock>;
208
+ /** wire content index -> accumulating tool call. */
209
+ toolCalls: Map<number, MessagesToolCall>;
210
+ hasContent: boolean;
211
+ hasToolCall: boolean;
212
+ finishReason: string | null;
213
+ sawMessageStart: boolean;
214
+ sawMessageStop: boolean;
215
+ sawUsage: boolean;
216
+ inputTokens: number;
217
+ outputTokens: number;
218
+ cacheReadTokens: number;
219
+ cacheWriteTokens: number;
220
+ reasoningTokens: number;
221
+ finished: boolean;
222
+ }
223
+ export declare function createMessagesStreamState(): MessagesStreamState;
224
+ /** Flush every open block, then emit usage and the terminal finish. */
225
+ export declare function closeMessagesStream(state: MessagesStreamState): StreamChunk[];
226
+ /** A stream that ends without `message_stop` is truncated, not complete. */
227
+ export declare function assertMessagesStreamComplete(state: MessagesStreamState): void;
228
+ /**
229
+ * Feed one SSE line from `/v1/messages`.
230
+ *
231
+ * Both fragments of one event arrive as two lines (`event:` then `data:`), so
232
+ * the parser keys on `data:` alone and ignores the event name: the JSON payload
233
+ * carries its own `type`, which is the same discriminator and cannot disagree
234
+ * with the label above it.
235
+ */
236
+ export declare function processMessagesStreamLine(line: string, state: MessagesStreamState): StreamChunk[];
237
+ export { IMPLICIT_SYSTEM_PROMPT };
238
+ //# sourceMappingURL=mapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapper.d.ts","sourceRoot":"","sources":["../../../../src/host/workbuddy/mapper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,217 @@
1
+ /**
2
+ * Model catalog for the WorkBuddy / CodeBuddy subscription.
3
+ *
4
+ * The subscription exposes no `/v1/models`-style listing on the chat host
5
+ * (that path answers 404), but the gateway does publish an **authoritative
6
+ * catalog** at `GET /v3/config`, which the official CLI reads at startup. That
7
+ * payload carries each model's real context window, output cap, image support,
8
+ * and the exact reasoning ladder it accepts — so this route prefers the live
9
+ * catalog and keeps the table below only as an offline fallback.
10
+ *
11
+ * The fallback is a verbatim transcription of a live `/v3/config` read, not
12
+ * hand-written guesses: an earlier revision of this file guessed context
13
+ * windows from vendor marketing and was wrong in both directions (`glm-5.3`
14
+ * and `kimi-k3` are 1M, not 200K/256K).
15
+ *
16
+ * One entry serves both regions, so a model the regions disagree about needs a
17
+ * merged figure. The rule is asymmetric on purpose: the **larger maximum** is
18
+ * kept, while the **served default** and the **output cap** take the **smaller**
19
+ * of the two. Over-declaring either one is a hard failure — DSH would send a
20
+ * request the gateway rejects — whereas under-declaring only compresses a
21
+ * conversation earlier than needed, and both remain overridable per model from
22
+ * the settings card. Measured disagreements (`glm-5.3-flash`, `glm-5.3`,
23
+ * `glm-5.2`, `kimi-k2.8-preview` served 300000/48000/48000/32000 by intl
24
+ * against 1000000/64000/64000/64000 by cn) are reconciled that way.
25
+ *
26
+ * The regions also do not serve the same ids. intl added `glm-5.3-flash` and
27
+ * keeps `gemini-3.5-flash`, `kimi-k3` and the `*-model` aliases to itself; cn
28
+ * keeps `glm-5.3-flash`, `kimi-k3-1` and its own `-x` variants.
29
+ *
30
+ * `regions` is a routing fact, not a preference: asking a region for a model it
31
+ * does not serve answers 400 `code 11102`.
32
+ *
33
+ * A second `code 11102` source was measured and is deliberately NOT filtered
34
+ * out here: the gateway lists models the *current account* is not entitled to
35
+ * call (on a free plan, `glm-5.0`, `glm-4.7`, `glm-4.6`, `glm-4.6v`,
36
+ * `kimi-k2-thinking`, `hy4-preview-x` and `minimax-m2.5` all advertise a context
37
+ * window and then answer 11102). Those entries are kept because the gating is
38
+ * per-account, not per-model — a paid plan may serve them — and because the
39
+ * shipped default selection excludes them anyway. The adapter's failure message
40
+ * names this case so a user knows to pick another model rather than to retry.
41
+ *
42
+ * `credits` is the consumption multiplier the same payload publishes as a
43
+ * string (`x0.79 credits` on cn, `x6.67` on intl), stored here in the bare
44
+ * numeric form the settings card renders. It is kept per region because the two
45
+ * backends do not always agree — measured 2026-10-09, `deepseek-v4.1-flash`
46
+ * is `0.11` on cn against `0.00` on intl — and a key is written only for a
47
+ * region that actually published one (every `gpt-5.x` and `gpt-6-astra` is
48
+ * intl-only, the `minimax` and `glm-5.0`/`glm-4.x` rows carry no intl key).
49
+ * An empty string (`default-model`) means no rate was declared at all, so that
50
+ * row has no `credits` field rather than a zeroed one: a guessed rate on a
51
+ * spend figure is worse than a missing one.
52
+ *
53
+ * `reasoningEfforts` carries the ladder a model accepts, transcribed from the
54
+ * gateway's own declaration. `/v3/config` uses two shapes and they were once
55
+ * conflated, in opposite directions: a lone `{ effort: 'high' }` (no
56
+ * `supportedEfforts`) first became a one-entry ladder, which rejected a
57
+ * caller's explicit `low`; widening it to every level this route can name then
58
+ * advertised `minimal`/`xhigh` on a model that has three. Such a model accepts
59
+ * exactly `low`/`high`/`max` (measured on `deepseek-v4.1-flash`), the same
60
+ * three the gateway declares explicitly for `glm-5.3-flash` and
61
+ * `kimi-k2.8-preview`, and routes any other value into the nearest of them.
62
+ */
63
+ import type { WorkBuddyModelCredits, WorkBuddyRegion } from '../../shared/workbuddy-contracts.ts';
64
+ export interface WorkBuddyModelEntry {
65
+ id: string;
66
+ name: string;
67
+ /**
68
+ * Context length the gateway serves **by default** for this model.
69
+ *
70
+ * This route sends no explicit context-length parameter, so this is the
71
+ * figure DSH's compaction and overflow decisions must use. It is not always
72
+ * the model's maximum: the gateway reports both (for example
73
+ * `deepseek-v4.1-flash` serves 300000 by default and allows 1000000).
74
+ */
75
+ contextWindow: number;
76
+ /** Largest context length the model accepts when one is requested. */
77
+ maxContextWindow: number;
78
+ /** Output cap requested when the caller omits one. */
79
+ maxTokens: number;
80
+ /** Regions whose backend serves this id. */
81
+ regions: readonly WorkBuddyRegion[];
82
+ /**
83
+ * Consumption multiplier per region, as `/v3/config` publishes it.
84
+ *
85
+ * Optional on purpose: the multiplier is the one field the gateway may omit
86
+ * for a model it otherwise describes (`default-model` ships an empty string),
87
+ * so every catalog literal in this repo — test fixtures and the live parser
88
+ * alike — must stay valid without it. Absent therefore means "nothing usable
89
+ * was published", never "zero": `x0.00` is a real declaration and is kept.
90
+ */
91
+ credits?: WorkBuddyModelCredits;
92
+ /** Whether the model accepts image input. */
93
+ supportsImage: boolean;
94
+ /** Reasoning ladder the model accepts; empty for a non-reasoning model. */
95
+ reasoningEfforts: readonly string[];
96
+ /** Level this route selects when the caller names none. */
97
+ defaultReasoningEffort: string | null;
98
+ /** Whether the model can be asked to skip thinking entirely. */
99
+ canDisableThinking: boolean;
100
+ /** One-line note shown beside the model in the settings card. */
101
+ description: string;
102
+ }
103
+ /**
104
+ * Models the gateway serves but does not publish in `/v3/config`.
105
+ *
106
+ * The catalog is a published list, not the served one: measured on the
107
+ * international backend, `gpt-6-sol`, `gpt-6-luna` and `gemini-3.8-flash` all
108
+ * answer a normal streaming completion with 200 while being absent from
109
+ * `/v3/config` entirely, and a reachable gateway *replaces* the shipped table
110
+ * with that list. Without these rows the picker would simply never show them, so
111
+ * they are declared here and merged into a live catalog too
112
+ * ({@link withUnpublishedModels}) rather than living in the fallback alone.
113
+ *
114
+ * What each row records, and how it was established, differs by field:
115
+ *
116
+ * - **Existence, the reasoning ladder, image support** were measured against the
117
+ * live endpoint, not inferred from the name. A rejected level answers 400
118
+ * `code 11133` with `extError` `400002`; `gpt-6-sol` takes exactly the ladder
119
+ * `gpt-6-astra` publishes (`minimal` refused, `low`/`medium`/`high`/`xhigh`/
120
+ * `max` accepted) and both accept a 1x1 PNG.
121
+ * - **Context window, output cap and `canDisableThinking` are inherited from the
122
+ * published sibling in the same family** — `gpt-6-astra` for `gpt-6-sol` and
123
+ * `gpt-6-luna`, `gemini-3.5-flash` for `gemini-3.8-flash`. They are marked
124
+ * here rather than measured because the gateway publishes nothing for these
125
+ * ids and offers no cheap way to read the real figure: it accepts a
126
+ * `max_tokens` larger than any published window (even for `gpt-6-astra`, whose
127
+ * own catalog caps at 128000), so the number is neither enforced nor
128
+ * discoverable from the request side.
129
+ *
130
+ * Every field stays overridable per model from the settings card, and an
131
+ * inherited window errs low rather than high: over-declaring overflows the
132
+ * gateway mid-session, while under-declaring only compresses earlier.
133
+ */
134
+ export declare const UNPUBLISHED_MODELS: readonly WorkBuddyModelEntry[];
135
+ /**
136
+ * Offline fallback catalog, transcribed from a live `/v3/config` read.
137
+ *
138
+ * Used when the gateway cannot be reached (first run before sign-in, or a
139
+ * network failure); a reachable gateway always wins.
140
+ */
141
+ export declare const FALLBACK_MODELS: readonly WorkBuddyModelEntry[];
142
+ /**
143
+ * Models the picker offers on a fresh install.
144
+ *
145
+ * Deliberately short: the catalog holds every id the subscription serves, and
146
+ * the picker is far more usable with the handful of general-purpose models. The
147
+ * card lets a user add the rest, and a first-run default expands to everything
148
+ * the account's region can actually call.
149
+ */
150
+ export declare const DEFAULT_VISIBLE_MODEL_IDS: readonly string[];
151
+ /** Every id the fallback knows, in declaration order. */
152
+ export declare const WORKBUDDY_MODEL_IDS: readonly string[];
153
+ /**
154
+ * Add the served-but-unpublished models to a live `/v3/config` catalog.
155
+ *
156
+ * A reachable gateway replaces the shipped table with the list it publishes, so
157
+ * a model it serves without listing ({@link UNPUBLISHED_MODELS}) would drop out
158
+ * of the picker the moment the catalog loads. Merging here keeps it offered.
159
+ *
160
+ * A published entry always wins: the gateway is the authority on anything it
161
+ * does describe, so these rows only fill ids the payload is silent about.
162
+ */
163
+ export declare function withUnpublishedModels(catalog: readonly WorkBuddyModelEntry[], region: WorkBuddyRegion): WorkBuddyModelEntry[];
164
+ /**
165
+ * Resolve one entry from a catalog.
166
+ *
167
+ * An unknown id resolves to a synthetic text-only entry rather than the first
168
+ * catalog row: reporting a real model's capabilities for an id it does not
169
+ * describe would mis-declare image support and route a request to a 400.
170
+ */
171
+ export declare function resolveWorkBuddyModel(id: string, catalog?: readonly WorkBuddyModelEntry[]): WorkBuddyModelEntry;
172
+ /** Whether one catalog knows this exact id. */
173
+ export declare function isWorkBuddyModelId(id: unknown, catalog?: readonly WorkBuddyModelEntry[]): id is string;
174
+ /** The vendor family one model belongs to. */
175
+ export declare function workBuddyModelVendor(id: string): string;
176
+ /**
177
+ * Group a list so every vendor's models sit together.
178
+ *
179
+ * Families appear in the order their first model does — the catalog decides
180
+ * which vendor leads, not this function — and each family is ordered newest
181
+ * generation first.
182
+ */
183
+ export declare function groupWorkBuddyModelsByVendor<T extends {
184
+ id: string;
185
+ }>(models: readonly T[]): T[];
186
+ /**
187
+ * Models an account in `region` can actually call, grouped by vendor.
188
+ *
189
+ * Grouped here rather than in the settings card because this is also what the
190
+ * request path resolves against: one ordering rule, so the picker and the
191
+ * adapter can never disagree about which models a region offers.
192
+ */
193
+ export declare function modelsForRegion(region: WorkBuddyRegion, catalog?: readonly WorkBuddyModelEntry[]): WorkBuddyModelEntry[];
194
+ /** Whether one model accepts image input. */
195
+ export declare function workBuddyModelSupportsImage(id: string, catalog?: readonly WorkBuddyModelEntry[]): boolean;
196
+ /**
197
+ * Reasoning ladder one model accepts, plus `none` when its trace can be turned off.
198
+ *
199
+ * The ladder in the catalog is what the model ACCEPTS, so `none` never appears
200
+ * in it; `canDisableThinking` is the separate statement that switching thinking
201
+ * off is allowed, and this is the single place that turns it into the one level
202
+ * the picker can offer. Callers that need the ladder alone read the entry.
203
+ */
204
+ export declare function workBuddyReasoningEfforts(id: string, catalog?: readonly WorkBuddyModelEntry[]): readonly string[];
205
+ /**
206
+ * Consumption multiplier per region one model publishes.
207
+ *
208
+ * Read through {@link resolveWorkBuddyModel} like the other accessors, so an id
209
+ * no catalog describes reports `{}` — "no rate published" rather than a rate
210
+ * of zero.
211
+ */
212
+ export declare function workBuddyModelCredits(id: string, catalog?: readonly WorkBuddyModelEntry[]): WorkBuddyModelCredits;
213
+ /** Output cap requested when the caller omits one. */
214
+ export declare function maxOutputTokensFor(id: string, catalog?: readonly WorkBuddyModelEntry[]): number;
215
+ /** Context window assumed when no override is saved. */
216
+ export declare function defaultContextWindowFor(id: string, catalog?: readonly WorkBuddyModelEntry[]): number;
217
+ //# sourceMappingURL=model-catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-catalog.d.ts","sourceRoot":"","sources":["../../../../src/host/workbuddy/model-catalog.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ import { FileCredentialStore, type WorkBuddyCredentials } from './token-store.ts';
2
+ import { type WorkBuddyTokenIdentity } from './identity.ts';
3
+ import type { WorkBuddyRegion } from '../../shared/workbuddy-contracts.ts';
4
+ export type WorkBuddyLoginStatus = 'idle' | 'pending' | 'complete' | 'error';
5
+ export interface WorkBuddyLoginFlowState {
6
+ status: WorkBuddyLoginStatus;
7
+ region?: WorkBuddyRegion;
8
+ authUrl?: string;
9
+ progress?: string;
10
+ accountId?: string;
11
+ startedAt?: number;
12
+ completedAt?: number;
13
+ error?: string;
14
+ }
15
+ export declare function getWebLoginStatus(): WorkBuddyLoginFlowState;
16
+ export declare function resetWebLogin(): void;
17
+ export interface WorkBuddyLoginAttempt {
18
+ state: string;
19
+ authUrl: string;
20
+ region: WorkBuddyRegion;
21
+ domain: string;
22
+ }
23
+ export declare function requestLoginState(region: WorkBuddyRegion, fetchFn?: typeof fetch, signal?: AbortSignal): Promise<WorkBuddyLoginAttempt>;
24
+ /** Parse the successful token-poll shape while accepting the two observed wrappers. */
25
+ export declare function parseLoginCredential(payload: unknown, attempt: WorkBuddyLoginAttempt): WorkBuddyCredentials | null;
26
+ export declare function pollLogin(attempt: WorkBuddyLoginAttempt, fetchFn?: typeof fetch, signal?: AbortSignal): Promise<WorkBuddyCredentials | null>;
27
+ /** Where a completed sign-in is written; the default is this line's own store. */
28
+ export interface WorkBuddyLoginOptions {
29
+ /**
30
+ * Persist the completed credential.
31
+ *
32
+ * The account pool owns routing, so it is what a completed sign-in must reach;
33
+ * the default writes to the credential store alone, which is what a caller
34
+ * running without a pool needs.
35
+ */
36
+ onSave?: (credentials: WorkBuddyCredentials) => Promise<unknown>;
37
+ /**
38
+ * Resolve the signed-in account's identity before it is saved.
39
+ *
40
+ * The token response does not say which account it belongs to, so the default
41
+ * reads it from the account endpoint; a test can replace this, and a caller
42
+ * that already knows the identity can skip the extra request.
43
+ */
44
+ resolveIdentity?: (credentials: WorkBuddyCredentials) => Promise<WorkBuddyTokenIdentity | null>;
45
+ }
46
+ export declare function beginWebLogin(store: FileCredentialStore, region: WorkBuddyRegion, fetchFn?: typeof fetch, options?: WorkBuddyLoginOptions): Promise<WorkBuddyLoginFlowState>;
47
+ //# sourceMappingURL=oauth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../../../src/host/workbuddy/oauth.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,mBAAmB,EAAsB,KAAK,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AACrG,OAAO,EAAwB,KAAK,sBAAsB,EAAE,MAAM,eAAe,CAAA;AAEjF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAA;AAE1E,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,OAAO,CAAA;AAE5E,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,oBAAoB,CAAA;IAC5B,MAAM,CAAC,EAAE,eAAe,CAAA;IACxB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAKD,wBAAgB,iBAAiB,IAAI,uBAAuB,CAE3D;AAED,wBAAgB,aAAa,IAAI,IAAI,CAIpC;AA0CD,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,eAAe,CAAA;IACvB,MAAM,EAAE,MAAM,CAAA;CACf;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,eAAe,EACvB,OAAO,GAAE,OAAO,KAAa,EAC7B,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,qBAAqB,CAAC,CAwBhC;AAED,uFAAuF;AACvF,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,qBAAqB,GAAG,oBAAoB,GAAG,IAAI,CAoClH;AAED,wBAAsB,SAAS,CAC7B,OAAO,EAAE,qBAAqB,EAC9B,OAAO,GAAE,OAAO,KAAa,EAC7B,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CActC;AAED,kFAAkF;AAClF,MAAM,WAAW,qBAAqB;IACpC;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,oBAAoB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IAChE;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,CAAC,WAAW,EAAE,oBAAoB,KAAK,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAAA;CAChG;AA8BD,wBAAsB,aAAa,CACjC,KAAK,EAAE,mBAAmB,EAC1B,MAAM,EAAE,eAAe,EACvB,OAAO,GAAE,OAAO,KAAa,EAC7B,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,uBAAuB,CAAC,CAuClC"}