@claxedo/agent-runtime-contract 0.8.0 → 0.10.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 (65) hide show
  1. package/README.md +27 -9
  2. package/dist/agent-runtime-event.d.ts +975 -0
  3. package/dist/availability.d.ts +3 -4
  4. package/dist/background-work.d.ts +10 -0
  5. package/dist/claims.d.ts +2 -0
  6. package/dist/connections.d.ts +66 -1
  7. package/dist/content.d.ts +72 -15
  8. package/dist/credential-broker-errors.d.ts +4 -0
  9. package/dist/custom-provider-headers.d.ts +12 -0
  10. package/dist/d1-bookmarks.d.ts +39 -0
  11. package/dist/daemon-ownership-snapshot.d.ts +40 -0
  12. package/dist/diagnostics.d.ts +24 -0
  13. package/dist/elicitation-pattern-worker.d.ts +6 -0
  14. package/dist/elicitation-pattern-worker.mjs +17 -0
  15. package/dist/elicitation-validation.d.ts +23 -0
  16. package/dist/elicitation.d.ts +51 -0
  17. package/dist/errors.d.ts +8 -1
  18. package/dist/event-cursor.d.ts +19 -0
  19. package/dist/events.d.ts +146 -216
  20. package/dist/files.d.ts +2 -0
  21. package/dist/first-turn-error.d.ts +12 -0
  22. package/dist/goals.d.ts +28 -0
  23. package/dist/harness-permission-modes.d.ts +76 -0
  24. package/dist/harness-table.d.ts +66 -4
  25. package/dist/harnesses.d.ts +19 -1
  26. package/dist/ids.d.ts +4 -0
  27. package/dist/index.d.ts +46 -1
  28. package/dist/index.mjs +2814 -95
  29. package/dist/mcp-app.d.ts +24 -0
  30. package/dist/message-page.d.ts +101 -0
  31. package/dist/permissions.d.ts +47 -0
  32. package/dist/pi-providers.d.ts +36 -0
  33. package/dist/prompt-title.d.ts +2 -0
  34. package/dist/provider-projection.d.ts +166 -0
  35. package/dist/raw-harness-event.d.ts +7 -0
  36. package/dist/recovery/actions.d.ts +20 -0
  37. package/dist/recovery/budgets.d.ts +16 -0
  38. package/dist/recovery/facts.d.ts +37 -0
  39. package/dist/recovery/operations.d.ts +66 -0
  40. package/dist/recovery/outcomes.d.ts +48 -0
  41. package/dist/recovery/payload-line.d.ts +19 -0
  42. package/dist/recovery/postconditions.d.ts +18 -0
  43. package/dist/recovery/requests.d.ts +44 -0
  44. package/dist/recovery/targets.d.ts +55 -0
  45. package/dist/recovery/validation.d.ts +9 -0
  46. package/dist/runtime-content.d.ts +34 -0
  47. package/dist/session-handoff.d.ts +4 -0
  48. package/dist/session-titles.d.ts +14 -0
  49. package/dist/sessions.d.ts +183 -5
  50. package/dist/stream-heartbeat.d.ts +11 -0
  51. package/dist/subagents.d.ts +92 -0
  52. package/dist/tool-header.d.ts +13 -0
  53. package/dist/tool-names.d.ts +5 -0
  54. package/dist/transcript-notice.d.ts +28 -0
  55. package/dist/turn-account.d.ts +26 -0
  56. package/dist/turn-error-classes.d.ts +10 -0
  57. package/dist/turn-fold.d.ts +111 -0
  58. package/dist/turn-fold.mjs +414 -0
  59. package/dist/turn-message-ids.d.ts +16 -0
  60. package/dist/turn-outline.d.ts +37 -0
  61. package/dist/turn-page.d.ts +58 -0
  62. package/dist/usage-streams.d.ts +19 -0
  63. package/dist/vendor-body.d.ts +31 -0
  64. package/dist/vendor-providers.d.ts +11 -0
  65. package/package.json +17 -3
package/dist/events.d.ts CHANGED
@@ -1,5 +1,16 @@
1
1
  import type { AgentConfigOption, AgentContentPart, AgentMessageInfo, AgentPermission, AgentQuestion, AgentSnapshotFileDiff, AgentTodo } from "./content";
2
2
  import type { AgentRuntimeStatus } from "./availability";
3
+ import type { BackgroundWork } from "./background-work";
4
+ import type { AgentRuntimeHealth, ConnectionRuntimeStatus } from "./connections";
5
+ import type { AgentSubagentUpdate, RuntimeGoalSnapshot } from "./subagents";
6
+ import type { TurnAccount } from "./turn-account";
7
+ /**
8
+ * Provider-reported token categories for one turn observation.
9
+ *
10
+ * `null` means the provider did not report the category. This is deliberately
11
+ * different from a reported zero: metering consumers must never manufacture a
12
+ * measured zero for an unknown category.
13
+ */
3
14
  export type RuntimeTokenUsage = {
4
15
  input: number | null;
5
16
  output: number | null;
@@ -7,13 +18,36 @@ export type RuntimeTokenUsage = {
7
18
  cache: {
8
19
  read: number | null;
9
20
  write: number | null;
21
+ /**
22
+ * The part of `write` held in the one-hour cache, which Anthropic bills at
23
+ * 2x input instead of the five-minute 1.25x. Absent where the provider
24
+ * reports no split; a write with no split is a five-minute write.
25
+ */
26
+ write1h?: number | null;
10
27
  };
11
28
  };
12
29
  export type RuntimeUsageObservation = {
30
+ /** Whether this observation replaces prior usage in its scope or adds to it. */
13
31
  kind: "cumulative" | "delta";
32
+ /**
33
+ * One independent stream of usage within the turn — a provider thread's own
34
+ * turn, a subagent's requests. A cumulative observation replaces only its
35
+ * scope's running total, and the turn's usage is the sum over every scope,
36
+ * so two streams that land on one turn never overwrite each other. Absent is
37
+ * the turn's own stream.
38
+ */
39
+ scope?: string;
14
40
  tokens: RuntimeTokenUsage;
41
+ /**
42
+ * The model id the provider reports having served these requests with, where
43
+ * it names one. A session's configured model can be an alias (`opus[1m]`)
44
+ * that no price list carries.
45
+ */
46
+ model?: string;
47
+ /** Provider-native ordering data when the source exposes it. */
15
48
  sequence?: number;
16
49
  providerObservationId?: string;
50
+ /** Provider-native session/thread identity used only for local overlap classification. */
17
51
  nativeSessionId?: string;
18
52
  observedAt?: number;
19
53
  };
@@ -59,11 +93,27 @@ export type AgentPresentationEvent = {
59
93
  field: string;
60
94
  delta: string;
61
95
  };
62
- } | {
96
+ }
97
+ /** These text and reasoning parts belong to a response the harness withdrew; they keep their content and gain `retracted`. */
98
+ | {
99
+ id: string;
100
+ type: "message.part.retracted";
101
+ properties: {
102
+ sessionID: string;
103
+ reason: string;
104
+ parts: Array<{
105
+ messageID: string;
106
+ partID: string;
107
+ }>;
108
+ };
109
+ }
110
+ /** `cancelled` marks the message a stopped turn ended on; the runtime records that turn as cancelled from it. */
111
+ | {
63
112
  type: "message.completed";
64
113
  properties: {
65
114
  sessionID: string;
66
115
  messageID: string;
116
+ cancelled?: true;
67
117
  };
68
118
  } | {
69
119
  id: string;
@@ -75,7 +125,19 @@ export type AgentPresentationEvent = {
75
125
  properties: {
76
126
  sessionID: string;
77
127
  requestID: string;
128
+ } & ({
78
129
  reply: "once" | "always" | "reject";
130
+ optionId?: never;
131
+ } | {
132
+ optionId: string;
133
+ reply?: never;
134
+ });
135
+ } | {
136
+ id: string;
137
+ type: "permission.expired";
138
+ properties: {
139
+ sessionID: string;
140
+ requestID: string;
79
141
  };
80
142
  } | {
81
143
  id: string;
@@ -96,6 +158,13 @@ export type AgentPresentationEvent = {
96
158
  sessionID: string;
97
159
  requestID: string;
98
160
  };
161
+ } | {
162
+ id: string;
163
+ type: "question.expired";
164
+ properties: {
165
+ sessionID: string;
166
+ requestID: string;
167
+ };
99
168
  } | {
100
169
  id: string;
101
170
  type: "todo.updated";
@@ -110,11 +179,19 @@ export type AgentPresentationEvent = {
110
179
  sessionID: string;
111
180
  status: AgentRuntimeStatus;
112
181
  };
113
- } | {
182
+ }
183
+ /**
184
+ * `lastTurn` is on the one frame that ends a turn, the `session.idle` (completed or cancelled) or
185
+ * `session.error` (failed) that `RuntimeStore.finishTurn` returns beside the `turn.finish` it journals:
186
+ * that outcome's status and `completedAt`, which the session's read and its list row then carry.
187
+ * A `session.error` raised outside a turn's end, such as a refused prompt admission, carries none.
188
+ */
189
+ | {
114
190
  id: string;
115
191
  type: "session.idle";
116
192
  properties: {
117
193
  sessionID: string;
194
+ lastTurn?: import("./sessions").SessionLastTurn;
118
195
  };
119
196
  } | {
120
197
  id: string;
@@ -127,6 +204,7 @@ export type AgentPresentationEvent = {
127
204
  message?: string;
128
205
  };
129
206
  };
207
+ lastTurn?: import("./sessions").SessionLastTurn;
130
208
  };
131
209
  } | {
132
210
  id: string;
@@ -160,6 +238,12 @@ export type AgentPresentationEvent = {
160
238
  sessionID: string;
161
239
  options: AgentConfigOption[];
162
240
  };
241
+ } | {
242
+ type: "session.commands";
243
+ properties: {
244
+ sessionID: string;
245
+ commands: import("./sessions").AgentSessionCommand[];
246
+ };
163
247
  } | {
164
248
  type: "session.usage";
165
249
  properties: {
@@ -172,6 +256,27 @@ export type AgentPresentationEvent = {
172
256
  amount: number;
173
257
  currency: string;
174
258
  };
259
+ account?: TurnAccount;
260
+ };
261
+ } | {
262
+ id?: string;
263
+ type: "subagent.updated";
264
+ properties: {
265
+ sessionID: string;
266
+ update: AgentSubagentUpdate;
267
+ };
268
+ } | {
269
+ id?: string;
270
+ type: "goal.updated";
271
+ properties: {
272
+ sessionID: string;
273
+ goal: RuntimeGoalSnapshot;
274
+ };
275
+ } | {
276
+ id?: string;
277
+ type: "goal.cleared";
278
+ properties: {
279
+ sessionID: string;
175
280
  };
176
281
  } | {
177
282
  id?: string;
@@ -201,6 +306,35 @@ export type AgentPresentationEvent = {
201
306
  } | {
202
307
  type: "server.heartbeat";
203
308
  properties: Record<string, unknown>;
309
+ }
310
+ /** `parentID` names a subsession, whose deletion leaves the visible session count alone. */
311
+ | {
312
+ type: "session.deleted";
313
+ properties: {
314
+ info: {
315
+ id: string;
316
+ directory: string;
317
+ parentID?: string;
318
+ };
319
+ };
320
+ }
321
+ /** Whether the session's harness runs work outside any turn; live state pushed when it changes and never journaled. */
322
+ | {
323
+ type: "session.background-work";
324
+ properties: {
325
+ sessionID: string;
326
+ } & BackgroundWork;
327
+ }
328
+ /** A session's harness health and its connection's state, pushed when either changes. */
329
+ | {
330
+ type: "harness.health";
331
+ properties: {
332
+ sessionID: string;
333
+ harnessHealth: AgentRuntimeHealth;
334
+ connectionState?: ConnectionRuntimeStatus & {
335
+ connectionId: string;
336
+ };
337
+ };
204
338
  };
205
339
  export type AgentPresentationEventType = AgentPresentationEvent["type"];
206
340
  export declare const AGENT_PRESENTATION_EVENT_TYPE_REGISTRY: {
@@ -209,12 +343,15 @@ export declare const AGENT_PRESENTATION_EVENT_TYPE_REGISTRY: {
209
343
  "message.part.updated": true;
210
344
  "message.part.removed": true;
211
345
  "message.part.delta": true;
346
+ "message.part.retracted": true;
212
347
  "message.completed": true;
213
348
  "permission.asked": true;
214
349
  "permission.replied": true;
350
+ "permission.expired": true;
215
351
  "question.asked": true;
216
352
  "question.replied": true;
217
353
  "question.rejected": true;
354
+ "question.expired": true;
218
355
  "todo.updated": true;
219
356
  "session.status": true;
220
357
  "session.idle": true;
@@ -224,10 +361,17 @@ export declare const AGENT_PRESENTATION_EVENT_TYPE_REGISTRY: {
224
361
  "session.compacted": true;
225
362
  "session.agent": true;
226
363
  "session.config": true;
364
+ "session.commands": true;
227
365
  "session.usage": true;
366
+ "subagent.updated": true;
367
+ "goal.updated": true;
368
+ "goal.cleared": true;
228
369
  "runtime.diagnostic": true;
229
370
  "server.connected": true;
230
371
  "server.heartbeat": true;
372
+ "session.deleted": true;
373
+ "harness.health": true;
374
+ "session.background-work": true;
231
375
  };
232
376
  /** Sound because the registry is `satisfies Record<AgentPresentationEventType, true>`: its keys are exactly the union. */
233
377
  export declare function isAgentPresentationEventType(value: string): value is AgentPresentationEventType;
@@ -236,12 +380,6 @@ export type AgentEventEnvelope<Event extends AgentPresentationEvent = AgentPrese
236
380
  directory: string;
237
381
  payload: Event;
238
382
  };
239
- export type RawHarnessEvent = {
240
- source: string;
241
- method?: string;
242
- payload: unknown;
243
- receivedAt?: number;
244
- };
245
383
  export type RuntimeQuestion = {
246
384
  text: string;
247
385
  options?: string[];
@@ -250,211 +388,3 @@ export type RuntimeQuestion = {
250
388
  multiple?: boolean;
251
389
  custom?: boolean;
252
390
  };
253
- export type AgentRuntimeEvent = ({
254
- harness?: string;
255
- threadId?: string;
256
- raw?: RawHarnessEvent;
257
- diagnostics?: Array<{
258
- code: string;
259
- message: string;
260
- severity: "debug" | "info" | "warn" | "error";
261
- details?: Record<string, unknown>;
262
- }>;
263
- }) & ({
264
- type: "text-delta";
265
- delta: string;
266
- } | {
267
- type: "thinking-delta";
268
- delta: string;
269
- } | {
270
- type: "user-message-delta";
271
- messageId?: string;
272
- content: Record<string, unknown> & {
273
- type: string;
274
- };
275
- } | {
276
- type: "tool-start";
277
- toolCallId: string;
278
- toolName: string;
279
- kind?: string;
280
- display?: Record<string, unknown>;
281
- metadata?: Record<string, unknown>;
282
- } | {
283
- type: "tool-input";
284
- toolCallId: string;
285
- input: unknown;
286
- display?: Record<string, unknown>;
287
- metadata?: Record<string, unknown>;
288
- } | {
289
- type: "tool-status";
290
- toolCallId: string;
291
- status: "pending" | "running" | "completed" | "failed";
292
- display?: Record<string, unknown>;
293
- metadata?: Record<string, unknown>;
294
- } | {
295
- type: "tool-content";
296
- toolCallId: string;
297
- content: Record<string, unknown> & {
298
- type: string;
299
- };
300
- display?: Record<string, unknown>;
301
- metadata?: Record<string, unknown>;
302
- } | {
303
- type: "tool-output";
304
- toolCallId: string;
305
- output: unknown;
306
- display?: Record<string, unknown>;
307
- metadata?: Record<string, unknown>;
308
- } | {
309
- type: "tool-error";
310
- toolCallId: string;
311
- error: string;
312
- display?: Record<string, unknown>;
313
- metadata?: Record<string, unknown>;
314
- } | {
315
- type: "file-diff";
316
- toolCallId?: string;
317
- path: string;
318
- oldText?: string;
319
- newText: string;
320
- } | {
321
- type: "step-start";
322
- newMessageId: string;
323
- } | {
324
- type: "permission-request";
325
- requestId: string;
326
- tool: string;
327
- paths: string[];
328
- } | {
329
- type: "question";
330
- requestId: string;
331
- questions: RuntimeQuestion[];
332
- } | {
333
- type: "question-answered";
334
- requestId: string;
335
- answers: Record<string, string | string[]>;
336
- } | {
337
- type: "proposed-plan-delta";
338
- delta: string;
339
- } | {
340
- type: "proposed-plan-complete";
341
- planMarkdown: string;
342
- } | {
343
- type: "todo-update";
344
- todos: Array<{
345
- id: string;
346
- description: string;
347
- status: string;
348
- priority?: string;
349
- }>;
350
- } | {
351
- type: "session-status";
352
- status: "busy" | "idle" | "error" | "recovering";
353
- } | {
354
- type: "session-compaction";
355
- phase: "started" | "completed";
356
- reason?: string;
357
- summary?: string;
358
- metadata?: Record<string, unknown>;
359
- } | {
360
- type: "harness-notice";
361
- code: string;
362
- message: string;
363
- severity?: "debug" | "info" | "warn" | "error";
364
- details?: unknown;
365
- } | {
366
- type: "auth-status";
367
- status: "authenticated" | "unauthenticated" | "unknown";
368
- authMode?: string | null;
369
- planType?: string | null;
370
- metadata?: Record<string, unknown>;
371
- } | {
372
- type: "rate-limit";
373
- status: "ok" | "limited";
374
- usedPercent?: number;
375
- resetsAt?: number | null;
376
- windowDurationMins?: number | null;
377
- limitId?: string | null;
378
- limitName?: string | null;
379
- reason?: string | null;
380
- metadata?: Record<string, unknown>;
381
- } | {
382
- type: "mcp-server-status";
383
- serverName: string;
384
- status: "starting" | "ready" | "failed" | "cancelled";
385
- error?: string | null;
386
- } | {
387
- type: "subagent-updated";
388
- subagentKey: string;
389
- revision: number;
390
- [key: string]: unknown;
391
- } | {
392
- type: "finish";
393
- sessionId: string;
394
- } | {
395
- type: "error";
396
- error: string;
397
- } | {
398
- type: "image-delta" | "audio-delta" | "thinking-audio-delta";
399
- mimeType: string;
400
- data: string;
401
- } | {
402
- type: "resource-link-delta" | "thinking-resource-link-delta";
403
- uri: string;
404
- name: string;
405
- mimeType?: string;
406
- title?: string;
407
- } | {
408
- type: "resource-delta";
409
- resource: unknown;
410
- channel: "assistant" | "thinking";
411
- } | {
412
- type: "tool-location";
413
- toolCallId: string;
414
- locations: Array<{
415
- path: string;
416
- line?: number;
417
- }>;
418
- } | {
419
- type: "tool-terminal";
420
- toolCallId: string;
421
- terminalId: string;
422
- } | {
423
- type: "available-commands-update";
424
- commands: Array<{
425
- name: string;
426
- description?: string;
427
- input?: unknown;
428
- }>;
429
- } | {
430
- type: "session-agent";
431
- agentId: string;
432
- } | {
433
- type: "config-update";
434
- options: AgentConfigOption[];
435
- } | {
436
- type: "session-info";
437
- title?: string | null;
438
- updatedAt?: string | null;
439
- parentID?: string;
440
- } | {
441
- type: "session-title";
442
- title: string;
443
- } | {
444
- type: "usage";
445
- contextSize: number;
446
- contextUsed: number;
447
- observation?: RuntimeUsageObservation;
448
- cost?: {
449
- amount: number;
450
- currency: string;
451
- };
452
- } | {
453
- type: "diagnostic";
454
- diagnostic: {
455
- code: string;
456
- message: string;
457
- severity: "debug" | "info" | "warn" | "error";
458
- details?: unknown;
459
- };
460
- });
package/dist/files.d.ts CHANGED
@@ -50,3 +50,5 @@ export type AgentPresentationProvider = {
50
50
  export declare function isAgentReviewFileDiff(value: unknown): value is AgentReviewFileDiff;
51
51
  /** Coerce an unknown payload (array, single diff, or keyed object) into a diff list. */
52
52
  export declare function agentReviewFileDiffList(value: unknown): AgentReviewFileDiff[];
53
+ /** The file content `value` holds, or `undefined` when it is not one; a malformed patch is dropped, not fatal. */
54
+ export declare function parseAgentFileContent(value: unknown): AgentFileContent | undefined;
@@ -0,0 +1,12 @@
1
+ import type { FirstTurnErrorClass } from "./turn-error-classes";
2
+ import type { TurnAccount } from "./turn-account";
3
+ export declare function classifyFirstTurnError(error: unknown): FirstTurnErrorClass;
4
+ /** `errorClass` is the transport's structured class; the message is read only without one. */
5
+ export declare function firstTurnErrorData(message: string, facts?: {
6
+ errorClass?: FirstTurnErrorClass;
7
+ account?: TurnAccount;
8
+ }): {
9
+ message: string;
10
+ firstTurnErrorClass: "credential" | "egress" | "harness" | "model" | "rate_limit" | "session" | "unknown" | "usage_limit" | "workspace";
11
+ account?: TurnAccount | undefined;
12
+ };
@@ -0,0 +1,28 @@
1
+ import type { RuntimeGoalSnapshot } from "./subagents";
2
+ export type AgentGoalStartInput = {
3
+ objective: string;
4
+ };
5
+ export type AgentGoalMutationFailure = {
6
+ ok: false;
7
+ status: "unsupported" | "unavailable" | "not_found" | "conflict" | "failed";
8
+ message: string;
9
+ };
10
+ export type AgentGoalMutationResult<Goal extends RuntimeGoalSnapshot | null = RuntimeGoalSnapshot | null> = {
11
+ ok: true;
12
+ goal: Goal;
13
+ } | AgentGoalMutationFailure;
14
+ export type GoalAction = "pause" | "resume" | "delete";
15
+ export type GoalRecovery = "reconcile" | "blocked";
16
+ export type GoalOptionalField = "tokenBudget" | "tokensUsed" | "timeUsedSeconds" | "iteration" | "lastReason";
17
+ export type GoalCapabilities = {
18
+ /** Whether this adapter contains a real Goal implementation. */
19
+ implemented: boolean;
20
+ /** Whether that implementation can be used in the current session/runtime. */
21
+ available: boolean;
22
+ unavailableReason?: string;
23
+ actions: readonly GoalAction[];
24
+ /** Whether authoritative state can be reconciled after reconnect/reload. */
25
+ recovery: GoalRecovery;
26
+ /** Optional snapshot fields this implementation may report without fabrication. */
27
+ optionalFields: readonly GoalOptionalField[];
28
+ };
@@ -0,0 +1,76 @@
1
+ import type { AgentPermissionMode } from "./permissions";
2
+ /**
3
+ * When a change lands. `next-session` is a harness whose options are read only
4
+ * when its agent is created, and that cannot recreate the agent in front of
5
+ * the user. `immediate` uses a live session control.
6
+ */
7
+ export type PermissionModesApplyFrom = "immediate" | "next-turn" | "next-session";
8
+ export type HarnessPermissionModes = {
9
+ modes: readonly AgentPermissionMode[];
10
+ appliesFrom: PermissionModesApplyFrom;
11
+ /**
12
+ * The mode a session runs under before anyone has chosen, as the transport
13
+ * launches it. Absent where the harness's own configuration decides instead,
14
+ * so a session that chose nothing names no mode.
15
+ */
16
+ defaultModeId?: string;
17
+ };
18
+ /**
19
+ * Claude's `PermissionMode` union, with the SDK's OWN descriptions copied from
20
+ * its doc comment (`sdk.d.ts`) so the picker never paraphrases.
21
+ *
22
+ * `plan` and `dontAsk` carry no rung. `plan` executes nothing and `dontAsk`
23
+ * DENIES rather than allows, so neither sits on an allow-more ladder at all.
24
+ * `acceptEdits` carries none either: it still prompts for every command.
25
+ *
26
+ * `immediate`: streaming queries acknowledge `setPermissionMode()` without
27
+ * restarting the active turn.
28
+ */
29
+ export declare const CLAUDE_PERMISSION_MODES: {
30
+ modes: AgentPermissionMode[];
31
+ appliesFrom: "immediate";
32
+ defaultModeId: string;
33
+ };
34
+ /**
35
+ * Cursor's two `LocalAgentOptions` booleans, presented as the combinations that
36
+ * mean something.
37
+ *
38
+ * `next-turn`: both fields are read by `Agent.create` and `Agent.resume`, and
39
+ * the per-send `LocalSendOptions` carries only `force` and `customTools`, so a
40
+ * change closes the session's agent and the next turn resumes it with the new
41
+ * options.
42
+ *
43
+ * No default: with nothing chosen the transport passes no sandbox options and
44
+ * Cursor's own configured defaults decide. A sandboxed mode needs Cursor's
45
+ * `cursorsandbox` binary, which the SDK refuses to run without.
46
+ *
47
+ * `force` is deliberately NOT mapped to a rung. It expires a wedged run after a
48
+ * crashed CLI — a recovery flag, not a permission control — and treating it as
49
+ * "full access" would hand a destructive-sounding label to something that does
50
+ * not grant anything.
51
+ */
52
+ export declare const CURSOR_PERMISSION_MODES: {
53
+ modes: AgentPermissionMode[];
54
+ appliesFrom: "next-turn";
55
+ };
56
+ /**
57
+ * Codex approval policy + sandbox pairs. `auto` here is the strongest `auto` of
58
+ * any harness: `on-request` with a workspace-write sandbox means in-workspace
59
+ * commands run unprompted and the boundary is enforced by the OS
60
+ * (seatbelt/landlock), not by an allowlist.
61
+ */
62
+ export declare const CODEX_PERMISSION_MODES: {
63
+ modes: AgentPermissionMode[];
64
+ appliesFrom: "next-turn";
65
+ defaultModeId: string;
66
+ };
67
+ /**
68
+ * Pi asks before nothing on its own. `ask` routes each write, edit, bash and
69
+ * MCP call through Claxedo's broker from a `beforeTool` hook; `full` runs them
70
+ * unasked, as Pi itself does.
71
+ */
72
+ export declare const PI_PERMISSION_MODES: {
73
+ modes: AgentPermissionMode[];
74
+ appliesFrom: "next-turn";
75
+ defaultModeId: string;
76
+ };
@@ -9,6 +9,8 @@
9
9
  * not another — and a provider id missing from a list loses its login without
10
10
  * anything failing.
11
11
  */
12
+ import { type HarnessPermissionModes } from "./harness-permission-modes";
13
+ import { type SessionHarness } from "./harnesses";
12
14
  export declare const HARNESS_IDS: readonly ["claude", "codex", "cursor"];
13
15
  export type HarnessId = (typeof HARNESS_IDS)[number];
14
16
  type HarnessRecord = {
@@ -21,10 +23,11 @@ type HarnessRecord = {
21
23
  * fallback.
22
24
  *
23
25
  * The order is load-bearing at both ends. A connect card stores under
24
- * `connectProvider`, and `harnessProjection` takes the first of these ids a
25
- * projection map holds — so a Claude turn binds through `claude-sdk` when one
26
- * is selected and through a plain `anthropic` key when it is not, and a list
27
- * that stopped at the aliases would drop that key.
26
+ * `connectProvider`, and the harness's `selectedProviderProjection` takes
27
+ * the first of these ids whose projection is available, else the first held
28
+ * — so a Claude turn binds through `claude-sdk` when its account can be used
29
+ * and through a plain `anthropic` key when it cannot, and a list that
30
+ * stopped at the aliases would drop that key.
28
31
  */
29
32
  providerIds: readonly string[];
30
33
  /** The provider id a sign-in for this harness is stored against. */
@@ -42,9 +45,41 @@ type HarnessRecord = {
42
45
  * an `Agent.create` argument and refuses a turn however signed in the CLI is.
43
46
  */
44
47
  machineLoginServes: readonly string[];
48
+ permissionModes: HarnessPermissionModes;
49
+ /**
50
+ * The model row a session that stored no model runs on, where the harness
51
+ * declares one without asking its live catalog. Absent on codex: an unnamed
52
+ * model is the app-server's own configured default, which only `model/list`
53
+ * reports.
54
+ */
55
+ defaultModelId?: string;
45
56
  };
46
57
  export declare const HARNESS_TABLE: Readonly<Record<HarnessId, HarnessRecord>>;
47
58
  export declare function isHarnessId(value: string): value is HarnessId;
59
+ /** The name every surface writes for a native harness: the product's own for the table's, the catalog's for the engines. */
60
+ export declare function harnessProductLabel(id: string): string | undefined;
61
+ /**
62
+ * The permission modes a session's harness declares: a table harness's, and
63
+ * Pi's, which Claxedo's own hook enforces. Undefined for an ACP connection,
64
+ * whose agent reports its own list, and for a native harness with no mode
65
+ * surface.
66
+ */
67
+ export declare function declaredPermissionModes(harness: SessionHarness): HarnessPermissionModes | undefined;
68
+ /**
69
+ * The mode a session runs under: the stored one while its harness still offers
70
+ * it, else the harness's declared default, or none where the harness's own
71
+ * configuration decides. A harness the table does not describe runs what was
72
+ * stored, or nothing that anyone chose.
73
+ */
74
+ export declare function effectivePermissionModeId(harness: SessionHarness, stored: string | null | undefined): string | null;
75
+ /** The model a session runs on: the stored one, else the row its harness declares as default. */
76
+ export declare function effectiveSessionModel(harness: SessionHarness, stored: {
77
+ providerID: string;
78
+ modelID: string;
79
+ } | undefined): {
80
+ providerID: string;
81
+ modelID: string;
82
+ } | undefined;
48
83
  /**
49
84
  * The harness a provider id belongs to, where one does. Every other provider id
50
85
  * names a vendor an engine can run rather than a harness's own login, and has
@@ -53,4 +88,31 @@ export declare function isHarnessId(value: string): value is HarnessId;
53
88
  export declare function harnessForProviderId(id: string): HarnessId | undefined;
54
89
  /** The bindings a harness resolves its own auth through: everything but the vendor id. */
55
90
  export declare function harnessBindingIds(harness: HarnessId): string[];
91
+ /**
92
+ * Every stored provider id whose row can stand in for one vendor, the vendor's
93
+ * own id first and the harness logins behind it.
94
+ *
95
+ * A subscription connected for Claude Code is an Anthropic login and nothing
96
+ * about it is Claude Code's alone — the broker sends it to the same origin and
97
+ * the same paths an Anthropic key goes to, differing only in the header it
98
+ * rides in. So Pi, which runs Anthropic models and sends a subscription's own
99
+ * headers, resolves it here instead of asking for the account a second time.
100
+ * OpenCode's engine does not: it is handed rows under their stored ids and its
101
+ * Anthropic provider speaks only an API key.
102
+ *
103
+ * The vendor leads, which is the opposite of the order a harness's
104
+ * `selectedProviderProjection` reads. Both are right about their own question: Claude Code asked which
105
+ * login to run ITSELF on and its own binding is the answer, while an engine
106
+ * borrowing the vendor spends the key that was pasted for the vendor before it
107
+ * reaches for a subscription that belongs to another product. The engine's
108
+ * overlay precedence already resolved a tie this way, and two orders for one
109
+ * question is how they would come to disagree.
110
+ *
111
+ * Structure only. Whether a candidate can be bound at all is the broker's
112
+ * answer (a provider with no destination row has no binding), and whether this
113
+ * vendor's binding can spend a given form is the caller's: a ChatGPT plan and
114
+ * an OpenAI key reach different origins, so an engine provider that means the
115
+ * key must not take the plan.
116
+ */
117
+ export declare function vendorCredentialProviderIds(vendorProvider: string): string[];
56
118
  export {};