@robota-sdk/agent-session 3.0.0-beta.83 → 3.0.0-beta.84
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +38 -0
- package/README.md +200 -157
- package/dist/node/index.cjs +7 -7
- package/dist/node/index.d.cts +436 -361
- package/dist/node/index.d.cts.map +1 -1
- package/dist/node/index.d.ts +436 -361
- package/dist/node/index.d.ts.map +1 -1
- package/dist/node/index.js +9 -9
- package/dist/node/index.js.map +1 -1
- package/package.json +7 -7
package/dist/node/index.d.cts
CHANGED
|
@@ -1,76 +1,5 @@
|
|
|
1
|
-
import { IAIProvider, IContextWindowState, IEventService, IHistoryEntry, IHookTypeExecutor, IResponseFormatConfig, IRunTraceContext, ISpinner, ISubprocessTraceEnv, ITerminalOutput, IToolExecutionContext, IToolExecutionResult, IToolResultSpillStore, IToolSchema, IToolWithEventService, IUserInteraction, Robota, TBackgroundPermissionPolicy, TModelEffort, TModelEffortSelection, TPermissionMode, TSessionEndReason, TToolArgs, TToolChoice, TToolParameters, TUniversalMessage, TUniversalValue } from "@robota-sdk/agent-core";
|
|
2
|
-
import { ICompactEvent, IInteractiveSessionRecord, IInteractiveSessionRecord as IInteractiveSessionRecord$1, IInteractiveSessionRecord as ISessionRecord, IInteractiveSessionStore, IInteractiveSessionStore as IInteractiveSessionStore$1, IInteractiveSessionStore as ISessionStore, IPromptHistoryBlock, IPromptHistoryEntry, IPromptHistoryReadOptions, IPromptHistorySource, IPromptHistoryWriter, ISessionListEntry, ISessionRecordDecodeIssue, TCompactTrigger, TPermissionResultValue, TSessionLoadOutcome } from "@robota-sdk/agent-interface-session";
|
|
3
|
-
//#region src/turn-claim.d.ts
|
|
4
|
-
/**
|
|
5
|
-
* Thrown when a turn is started on a session that is already running one. RUNTIME-003.
|
|
6
|
-
*
|
|
7
|
-
* A distinct type rather than a bare `Error`, because the point of giving the session a claim is to
|
|
8
|
-
* let consumers STOP maintaining their own busy flags — and a consumer that has to regex-match an
|
|
9
|
-
* error message to tell "busy, retry later" apart from a provider failure has not been given
|
|
10
|
-
* anything it can act on. Follows `CompactionError`, this package's existing precedent.
|
|
11
|
-
*/
|
|
12
|
-
declare class SessionBusyError extends Error {
|
|
13
|
-
/** Always `true`: the caller can run this turn later; nothing about the session is broken. */
|
|
14
|
-
readonly recoverable = true;
|
|
15
|
-
constructor(message: string);
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* The identity of the turn a session is currently running. RUNTIME-003.
|
|
19
|
-
*
|
|
20
|
-
* A session used to express "is something running?" as a bare `AbortController | null` field that
|
|
21
|
-
* `run()` overwrote on entry. That field was doing three jobs at once — cancellation channel, busy
|
|
22
|
-
* flag, and turn identity — and it could only do them for ONE turn, so a second concurrent `run()`
|
|
23
|
-
* orphaned the first: `abort()` reached only whichever turn held the field, and the first turn to
|
|
24
|
-
* finish cleared it in its `finally`, making `abort()` on the survivor a silent no-op. `isRunning()`
|
|
25
|
-
* read the same field, so it answered about whichever turn happened to own it. That is why consumers
|
|
26
|
-
* of this library grew their own busy flags rather than trusting it.
|
|
27
|
-
*
|
|
28
|
-
* The fix is to give the unit of work an OWNER. A claim is taken synchronously, it belongs to the
|
|
29
|
-
* caller that took it, and ONLY that caller releases it.
|
|
30
|
-
*
|
|
31
|
-
* REFUSAL, not pre-emption. A session is a single conversation: two turns interleaving on it produce
|
|
32
|
-
* a history neither of them wrote, and silently cancelling the first would discard work the caller
|
|
33
|
-
* never asked to abandon. `claim()` throws {@link SessionBusyError}, whose message names the three
|
|
34
|
-
* ways forward.
|
|
35
|
-
*/
|
|
36
|
-
declare class TurnClaim {
|
|
37
|
-
private controller;
|
|
38
|
-
/**
|
|
39
|
-
* Take the claim for a new turn, or throw if one is already held.
|
|
40
|
-
*
|
|
41
|
-
* MUST be called before the first `await` in the turn — a check that yields first is not a claim,
|
|
42
|
-
* it is a TOCTOU window, and two callers can pass it in the same tick.
|
|
43
|
-
*
|
|
44
|
-
* @throws {SessionBusyError} if a turn is already running, INCLUDING one that has been aborted but
|
|
45
|
-
* has not finished unwinding. See {@link abort} for why that case is not an exception.
|
|
46
|
-
*/
|
|
47
|
-
claim(): AbortController;
|
|
48
|
-
/**
|
|
49
|
-
* Release the claim — but only if `controller` is still the one holding it.
|
|
50
|
-
*
|
|
51
|
-
* The ownership check is what stops the original defect from reappearing in a new shape: a turn
|
|
52
|
-
* that released unconditionally in its `finally` could free a claim a LATER turn already took, and
|
|
53
|
-
* `isRunning()` would then report idle while a turn was in flight.
|
|
54
|
-
*/
|
|
55
|
-
release(controller: AbortController): void;
|
|
56
|
-
/**
|
|
57
|
-
* Signal the running turn to stop. Idempotent; a no-op if nothing is running.
|
|
58
|
-
*
|
|
59
|
-
* This does NOT release the claim, and that is deliberate. An earlier version cleared it here, so
|
|
60
|
-
* `isRunning()` answered `false` the instant `abort()` returned — while the aborted turn was still
|
|
61
|
-
* unwinding, still able to write history and finish tool calls. A new `run()` could then claim the
|
|
62
|
-
* session and interleave with it: exactly the two-turns-on-one-session defect RUNTIME-003 is
|
|
63
|
-
* about, just moved behind the abort boundary. Review of the first draft caught it.
|
|
64
|
-
*
|
|
65
|
-
* A turn is not over when it is asked to stop; it is over when it has stopped. The claim is
|
|
66
|
-
* therefore held until the owning turn's `finally` releases it, and until then `isRunning()` says
|
|
67
|
-
* `true` and a further `run()` is refused. Cancel and restart is `abort()`, then AWAIT the turn,
|
|
68
|
-
* then `run()` — which is what every caller in this repo already does.
|
|
69
|
-
*/
|
|
70
|
-
abort(): void;
|
|
71
|
-
isRunning(): boolean;
|
|
72
|
-
}
|
|
73
|
-
//#endregion
|
|
1
|
+
import { IAIProvider, IContextWindowState, IEventService, IExecutionJournal, IHistoryEntry, IHookTypeExecutor, IRecoverableExecutionJournal, IResponseFormatConfig, IResumeExecutionOptions, IRunTraceContext, ISpinner, ISubprocessTraceEnv, ITerminalOutput, IToolExecutionContext, IToolExecutionResult, IToolResultSpillStore, IToolSchema, IToolWaitRequest, IToolWithEventService, IUserInteraction, Robota, TBackgroundPermissionPolicy, TModelEffort, TModelEffortSelection, TPermissionMode, TSessionEndReason, TToolArgs, TToolChoice, TToolParameters, TUniversalMessage, TUniversalValue } from "@robota-sdk/agent-core";
|
|
2
|
+
import { ICompactEvent, IInteractiveSessionRecord, IInteractiveSessionRecord as IInteractiveSessionRecord$1, IInteractiveSessionRecord as ISessionRecord, IInteractiveSessionStore, IInteractiveSessionStore as IInteractiveSessionStore$1, IInteractiveSessionStore as ISessionStore, IPromptHistoryBlock, IPromptHistoryEntry, IPromptHistoryReadOptions, IPromptHistorySource, IPromptHistoryWriter, ISessionListEntry, ISessionRecordDecodeIssue, TCompactTrigger, TPermissionRequester, TPermissionResultValue, TSessionLoadOutcome } from "@robota-sdk/agent-interface-session";
|
|
74
3
|
//#region src/context-window-tracker.d.ts
|
|
75
4
|
/** Auto-compact when context usage reaches this fraction */
|
|
76
5
|
declare const AUTO_COMPACT_THRESHOLD = 0.835;
|
|
@@ -102,60 +31,6 @@ declare class ContextWindowTracker {
|
|
|
102
31
|
reset(): void;
|
|
103
32
|
}
|
|
104
33
|
//#endregion
|
|
105
|
-
//#region src/auto-mode-gate.d.ts
|
|
106
|
-
/** The call the classifier judges. */
|
|
107
|
-
interface IClassifiedCall {
|
|
108
|
-
readonly toolName: string;
|
|
109
|
-
readonly toolArgs: TToolArgs;
|
|
110
|
-
readonly cwd: string;
|
|
111
|
-
}
|
|
112
|
-
interface IClassifierVerdict {
|
|
113
|
-
readonly decision: 'allow' | 'block';
|
|
114
|
-
/** Short, for the model and the user: which rule, and why. */
|
|
115
|
-
readonly reason: string;
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* Judges one call. `undefined` means no usable verdict (an error, a refusal, output that does not
|
|
119
|
-
* parse): the call is not run. It counts toward a run of refusals, so a classifier that cannot
|
|
120
|
-
* answer hands the decision to a person instead of refusing every call.
|
|
121
|
-
*/
|
|
122
|
-
interface IPermissionClassifier {
|
|
123
|
-
classify(call: IClassifiedCall, signal?: AbortSignal): Promise<IClassifierVerdict | undefined>;
|
|
124
|
-
}
|
|
125
|
-
/** Refusals in a row (blocks or unusable verdicts), and blocks in the session, that pause the mode. */
|
|
126
|
-
declare const CONSECUTIVE_BLOCK_LIMIT = 3;
|
|
127
|
-
declare const TOTAL_BLOCK_LIMIT = 20;
|
|
128
|
-
/** `reason` is for the user (`/permissions`); `message` is what the model is told. */
|
|
129
|
-
type TAutoModeJudgement = {
|
|
130
|
-
readonly kind: 'allow';
|
|
131
|
-
} | {
|
|
132
|
-
readonly kind: 'block';
|
|
133
|
-
readonly reason: string;
|
|
134
|
-
readonly message: string;
|
|
135
|
-
} | {
|
|
136
|
-
readonly kind: 'unusable';
|
|
137
|
-
readonly reason: string;
|
|
138
|
-
readonly message: string;
|
|
139
|
-
};
|
|
140
|
-
declare class AutoModeGate {
|
|
141
|
-
private readonly classifier;
|
|
142
|
-
private consecutive;
|
|
143
|
-
private total;
|
|
144
|
-
private paused;
|
|
145
|
-
/** Calls a person allowed to be retried once after the classifier blocked them. */
|
|
146
|
-
private readonly retries;
|
|
147
|
-
constructor(classifier: IPermissionClassifier);
|
|
148
|
-
/** The mode asks a person until one approves. */
|
|
149
|
-
isPaused(): boolean;
|
|
150
|
-
/** A person approved while paused: the classifier decides again. */
|
|
151
|
-
resume(): void;
|
|
152
|
-
/** Let this exact call through once, without the classifier. */
|
|
153
|
-
grantRetry(toolName: string, toolArgs: TToolArgs): void;
|
|
154
|
-
/** Consume a retry grant for this exact call, if there is one. */
|
|
155
|
-
takeRetry(toolName: string, toolArgs: TToolArgs): boolean;
|
|
156
|
-
judge(call: IClassifiedCall, signal?: AbortSignal): Promise<TAutoModeJudgement>;
|
|
157
|
-
}
|
|
158
|
-
//#endregion
|
|
159
34
|
//#region src/session-log-reference-types.d.ts
|
|
160
35
|
/**
|
|
161
36
|
* Leaf type module for {@link IExternalPayloadReference}.
|
|
@@ -243,6 +118,60 @@ declare class SilentSessionLogger implements ISessionLogger {
|
|
|
243
118
|
log(): void;
|
|
244
119
|
}
|
|
245
120
|
//#endregion
|
|
121
|
+
//#region src/auto-mode-gate.d.ts
|
|
122
|
+
/** The call the classifier judges. */
|
|
123
|
+
interface IClassifiedCall {
|
|
124
|
+
readonly toolName: string;
|
|
125
|
+
readonly toolArgs: TToolArgs;
|
|
126
|
+
readonly cwd: string;
|
|
127
|
+
}
|
|
128
|
+
interface IClassifierVerdict {
|
|
129
|
+
readonly decision: 'allow' | 'block';
|
|
130
|
+
/** Short, for the model and the user: which rule, and why. */
|
|
131
|
+
readonly reason: string;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Judges one call. `undefined` means no usable verdict (an error, a refusal, output that does not
|
|
135
|
+
* parse): the call is not run. It counts toward a run of refusals, so a classifier that cannot
|
|
136
|
+
* answer hands the decision to a person instead of refusing every call.
|
|
137
|
+
*/
|
|
138
|
+
interface IPermissionClassifier {
|
|
139
|
+
classify(call: IClassifiedCall, signal?: AbortSignal): Promise<IClassifierVerdict | undefined>;
|
|
140
|
+
}
|
|
141
|
+
/** Refusals in a row (blocks or unusable verdicts), and blocks in the session, that pause the mode. */
|
|
142
|
+
declare const CONSECUTIVE_BLOCK_LIMIT = 3;
|
|
143
|
+
declare const TOTAL_BLOCK_LIMIT = 20;
|
|
144
|
+
/** `reason` is for the user (`/permissions`); `message` is what the model is told. */
|
|
145
|
+
type TAutoModeJudgement = {
|
|
146
|
+
readonly kind: 'allow';
|
|
147
|
+
} | {
|
|
148
|
+
readonly kind: 'block';
|
|
149
|
+
readonly reason: string;
|
|
150
|
+
readonly message: string;
|
|
151
|
+
} | {
|
|
152
|
+
readonly kind: 'unusable';
|
|
153
|
+
readonly reason: string;
|
|
154
|
+
readonly message: string;
|
|
155
|
+
};
|
|
156
|
+
declare class AutoModeGate {
|
|
157
|
+
private readonly classifier;
|
|
158
|
+
private consecutive;
|
|
159
|
+
private total;
|
|
160
|
+
private paused;
|
|
161
|
+
/** Calls a person allowed to be retried once after the classifier blocked them. */
|
|
162
|
+
private readonly retries;
|
|
163
|
+
constructor(classifier: IPermissionClassifier);
|
|
164
|
+
/** The mode asks a person until one approves. */
|
|
165
|
+
isPaused(): boolean;
|
|
166
|
+
/** A person approved while paused: the classifier decides again. */
|
|
167
|
+
resume(): void;
|
|
168
|
+
/** Let this exact call through once, without the classifier. */
|
|
169
|
+
grantRetry(toolName: string, toolArgs: TToolArgs): void;
|
|
170
|
+
/** Consume a retry grant for this exact call, if there is one. */
|
|
171
|
+
takeRetry(toolName: string, toolArgs: TToolArgs): boolean;
|
|
172
|
+
judge(call: IClassifiedCall, signal?: AbortSignal): Promise<TAutoModeJudgement>;
|
|
173
|
+
}
|
|
174
|
+
//#endregion
|
|
246
175
|
//#region src/permission-types.d.ts
|
|
247
176
|
/** The part of a sandbox client the permission gate consults. */
|
|
248
177
|
interface ICommandSandboxApproval {
|
|
@@ -264,11 +193,26 @@ interface ICommandSandboxApproval {
|
|
|
264
193
|
* local settings; the storage location is owned by the consuming layer (via `onProjectAllowTool`)
|
|
265
194
|
*/
|
|
266
195
|
type TPermissionResult = TPermissionResultValue;
|
|
196
|
+
/**
|
|
197
|
+
* Issue #3288 §1: context a caller MAY attach to a permission ask beyond the call itself.
|
|
198
|
+
*
|
|
199
|
+
* `requester` says WHO is asking, when it is not the person's own turn — a background agent's tool
|
|
200
|
+
* call forwarded to the person, say — so a surface can show "Background agent X wants to …" instead
|
|
201
|
+
* of an unattributed prompt. `signal` cancels the ASK itself (not the tool call): a background task
|
|
202
|
+
* that is stopped or whose child process exits while a person has not yet answered must not leave
|
|
203
|
+
* that answer parked forever, so aborting it here settles the parked prompt denied and dismisses it
|
|
204
|
+
* on every attached surface — the same fail-closed direction `checkPermission`'s own `signal` denies
|
|
205
|
+
* on. Both fields are optional so every existing 2-arg handler stays a valid implementation.
|
|
206
|
+
*/
|
|
207
|
+
interface IPermissionAskContext {
|
|
208
|
+
readonly requester?: TPermissionRequester;
|
|
209
|
+
readonly signal?: AbortSignal;
|
|
210
|
+
}
|
|
267
211
|
/**
|
|
268
212
|
* Custom permission handler — called when a tool needs user approval.
|
|
269
213
|
* Returns true to allow, false to deny, or 'allow-session' to remember for the session.
|
|
270
214
|
*/
|
|
271
|
-
type TPermissionHandler = (toolName: string, toolArgs: TToolArgs) => Promise<TPermissionResult>;
|
|
215
|
+
type TPermissionHandler = (toolName: string, toolArgs: TToolArgs, context?: IPermissionAskContext) => Promise<TPermissionResult>;
|
|
272
216
|
interface IPermissionEnforcerOptions {
|
|
273
217
|
sessionId: string;
|
|
274
218
|
cwd: string;
|
|
@@ -326,20 +270,340 @@ interface IPermissionEnforcerOptions {
|
|
|
326
270
|
* an ask-everything flag and the task's own lists to the one evaluator, so `deny`/`preapproved`/
|
|
327
271
|
* `inherit-allowlist` still bind under a permissive mode. Absent → no policy constraints.
|
|
328
272
|
*/
|
|
329
|
-
permissionPolicy?: TBackgroundPermissionPolicy;
|
|
273
|
+
permissionPolicy?: TBackgroundPermissionPolicy;
|
|
274
|
+
/**
|
|
275
|
+
* CORE-025: the task's OWN declared allow/deny rules (distinct from the parent session's `config.permissions`
|
|
276
|
+
* which `inherit-allowlist` inherits). `preapproved` consults these.
|
|
277
|
+
*/
|
|
278
|
+
taskPermissions?: {
|
|
279
|
+
allow?: readonly string[];
|
|
280
|
+
deny?: readonly string[];
|
|
281
|
+
};
|
|
282
|
+
/**
|
|
283
|
+
* Judges, in `auto` mode, the calls the mode would otherwise ask a person about. Absent → the
|
|
284
|
+
* session cannot enter `auto`.
|
|
285
|
+
*/
|
|
286
|
+
permissionClassifier?: IPermissionClassifier;
|
|
287
|
+
}
|
|
288
|
+
//#endregion
|
|
289
|
+
//#region src/session-types.d.ts
|
|
290
|
+
/** Options for graceful session shutdown. */
|
|
291
|
+
interface ISessionShutdownOptions {
|
|
292
|
+
reason?: TSessionEndReason;
|
|
293
|
+
}
|
|
294
|
+
/** Options for constructing a Session */
|
|
295
|
+
interface ISessionOptions {
|
|
296
|
+
/** Pre-constructed tools to register with the agent */
|
|
297
|
+
tools: IToolWithEventService[];
|
|
298
|
+
/**
|
|
299
|
+
* Applies to a tool added after construction (`Session.addTools`) the wrappers the assembler
|
|
300
|
+
* applied to `tools`, so a late tool is held to the same safety policy as one present from the
|
|
301
|
+
* start. The permission gate is applied by the session itself either way.
|
|
302
|
+
*/
|
|
303
|
+
wrapAddedTools?: (tools: IToolWithEventService[]) => IToolWithEventService[];
|
|
304
|
+
/** Pre-constructed AI provider */
|
|
305
|
+
provider: IAIProvider;
|
|
306
|
+
/** Pre-built system message string */
|
|
307
|
+
systemMessage: string;
|
|
308
|
+
/** Terminal I/O for permission prompts */
|
|
309
|
+
terminal: ITerminalOutput;
|
|
310
|
+
/**
|
|
311
|
+
* The session's execution root. REQUIRED — ARCH-010.
|
|
312
|
+
*
|
|
313
|
+
* This field did not exist. `Session` read `process.cwd()` in its constructor and that ambient
|
|
314
|
+
* value became the session's identity everywhere it matters: every hook input,
|
|
315
|
+
* `CLAUDE_PROJECT_DIR`, `PermissionEnforcer`'s root, and the persisted record. Meanwhile the
|
|
316
|
+
* subagent spawn contract has always declared `cwd` REQUIRED — and the in-process runner passed
|
|
317
|
+
* none, because there was no option to pass it to. A session that cannot be told where it runs
|
|
318
|
+
* silently runs wherever the process happens to be, which for a subagent is not its own workspace.
|
|
319
|
+
*
|
|
320
|
+
* A caller that genuinely means "this process's directory" passes `process.cwd()` where a reader
|
|
321
|
+
* can see the decision.
|
|
322
|
+
*/
|
|
323
|
+
cwd: string;
|
|
324
|
+
/** Permission and hook configuration */
|
|
325
|
+
permissions?: {
|
|
326
|
+
allow: string[];
|
|
327
|
+
deny: string[];
|
|
328
|
+
ask?: string[];
|
|
329
|
+
};
|
|
330
|
+
/**
|
|
331
|
+
* ARCH-040 Group C (issue #1934): the permission rules BEFORE any preset contributed.
|
|
332
|
+
*
|
|
333
|
+
* Passed rather than inferred. `permissions` above already has the startup preset's patterns baked
|
|
334
|
+
* in, so an enforcer that captured its own base from it on the first live `/preset` would keep the
|
|
335
|
+
* FIRST preset's allowlist forever — the accumulation the replace rule exists to prevent, arriving
|
|
336
|
+
* through the base instead of through the merge. Absent ⇒ no preset contributed and the two are
|
|
337
|
+
* the same.
|
|
338
|
+
*/
|
|
339
|
+
presetFreePermissions?: {
|
|
340
|
+
allow: readonly string[];
|
|
341
|
+
deny: readonly string[];
|
|
342
|
+
};
|
|
343
|
+
hooks?: Record<string, unknown>;
|
|
344
|
+
/** Initial permission mode */
|
|
345
|
+
permissionMode?: TPermissionMode;
|
|
346
|
+
/**
|
|
347
|
+
* CORE-025: background/subagent task permission policy. Resolved BEFORE the session-mode gate, so
|
|
348
|
+
* `deny`/`preapproved`/`inherit-allowlist` override even a permissive `permissionMode`. Absent on a normal
|
|
349
|
+
* interactive session (mode gate alone). Set by `createSubagentSession` from the spawn request.
|
|
350
|
+
*/
|
|
351
|
+
permissionPolicy?: TBackgroundPermissionPolicy;
|
|
352
|
+
/** CORE-025: the task's OWN allow/deny lists (what `preapproved` consults; distinct from `permissions`). */
|
|
353
|
+
taskPermissions?: {
|
|
354
|
+
allow?: readonly string[];
|
|
355
|
+
deny?: readonly string[];
|
|
356
|
+
};
|
|
357
|
+
/**
|
|
358
|
+
* Injected "ask the user" port (CMD-005): forwarded into the agent config so model-invoked tools
|
|
359
|
+
* (AskUserQuestion) can solicit a structured answer. Absent in headless/automation sessions.
|
|
360
|
+
*/
|
|
361
|
+
ask?: IUserInteraction['ask'];
|
|
362
|
+
/** Default trust level — used to derive permissionMode if not given */
|
|
363
|
+
defaultTrustLevel?: 'safe' | 'moderate' | 'full';
|
|
364
|
+
/** Active preset id selected at startup (PRESET-011 runtime state). Defaults to 'default'. */
|
|
365
|
+
activePresetId?: string;
|
|
366
|
+
/**
|
|
367
|
+
* Whether subagent dispatch is allowed for this session (PRESET-016 runtime gate). Defaults to
|
|
368
|
+
* true (current behavior). Only meaningful when the agent runtime was built at assembly.
|
|
369
|
+
*/
|
|
370
|
+
enableParallelSubagents?: boolean;
|
|
371
|
+
/** Model name (for context window sizing and Robota config) */
|
|
372
|
+
model?: string;
|
|
373
|
+
/** Provider idle timeout in milliseconds for each model call */
|
|
374
|
+
providerTimeout?: number;
|
|
375
|
+
/** Maximum number of agentic turns per run() call. Undefined = unlimited. */
|
|
376
|
+
maxTurns?: number;
|
|
377
|
+
/** Optional session store for persistence */
|
|
378
|
+
sessionStore?: IInteractiveSessionStore$1;
|
|
379
|
+
/** Override session ID (used when resuming a session to reuse the original ID) */
|
|
380
|
+
sessionId?: string;
|
|
381
|
+
/** Custom permission handler (overrides terminal-based prompts, used by Ink UI) */
|
|
382
|
+
permissionHandler?: TPermissionHandler;
|
|
383
|
+
/** The OS sandbox the shell tools run under, which may let a confined command skip the prompt. */
|
|
384
|
+
commandSandbox?: ICommandSandboxApproval;
|
|
385
|
+
/** Decides for `auto` mode. Without one the session refuses that mode. */
|
|
386
|
+
permissionClassifier?: IPermissionClassifier;
|
|
387
|
+
/** Called when the user selects "allow for project" — persists the tool pattern to project settings. */
|
|
388
|
+
onProjectAllowTool?: (toolName: string) => void;
|
|
389
|
+
/** Callback for text deltas — enables streaming text to the UI in real-time */
|
|
390
|
+
onTextDelta?: (delta: string) => void;
|
|
391
|
+
/** Callback when context window usage is refreshed */
|
|
392
|
+
onContextUpdate?: (state: IContextWindowState) => void;
|
|
393
|
+
/** Custom prompt-for-approval function (injected from CLI) */
|
|
394
|
+
promptForApproval?: (terminal: ITerminalOutput, toolName: string, toolArgs: TToolArgs) => Promise<TPermissionResult>;
|
|
395
|
+
/** Callback when a tool starts or finishes execution — enables real-time tool display in UI */
|
|
396
|
+
onToolExecution?: (event: {
|
|
397
|
+
type: 'start' | 'end';
|
|
398
|
+
toolName: string;
|
|
399
|
+
toolArgs?: TToolArgs;
|
|
400
|
+
success?: boolean;
|
|
401
|
+
denied?: boolean;
|
|
402
|
+
toolResultData?: string;
|
|
403
|
+
executionId?: string;
|
|
404
|
+
}) => void;
|
|
405
|
+
/** Callback when context is compacted */
|
|
406
|
+
onCompact?: (summary: string) => void;
|
|
407
|
+
/** Callback with structured compaction metadata */
|
|
408
|
+
onCompactEvent?: (event: ICompactEvent) => void;
|
|
409
|
+
/** Instructions to include in the compaction prompt (e.g. from project context files) */
|
|
410
|
+
compactInstructions?: string;
|
|
411
|
+
/**
|
|
412
|
+
* Replaces the base instruction template of the compaction summarization prompt
|
|
413
|
+
* (default: `DEFAULT_COMPACTION_PROMPT`, a domain-neutral template). Lets the consuming
|
|
414
|
+
* layer own the compaction prompt wording entirely.
|
|
415
|
+
*/
|
|
416
|
+
compactionBasePrompt?: string;
|
|
417
|
+
/**
|
|
418
|
+
* Concrete remediation wording for the core's hard-capacity notice, forwarded to the Robota
|
|
419
|
+
* agent config as `IAgentConfig.contextCapacityHint`. The zero-dependency core emits a
|
|
420
|
+
* product-neutral default; a surface tier that owns a real remediation command (e.g. a
|
|
421
|
+
* `/compact` slash command) injects its own actionable hint here. Absent ⇒ the neutral
|
|
422
|
+
* `DEFAULT_CONTEXT_CAPACITY_HINT` applies.
|
|
423
|
+
*/
|
|
424
|
+
contextCapacityHint?: string;
|
|
425
|
+
/** Override context max tokens (otherwise derived from model name) */
|
|
426
|
+
contextMaxTokens?: number;
|
|
427
|
+
/** Auto-compact threshold as a 0-1 fraction. Set false to disable automatic compaction. */
|
|
428
|
+
autoCompactThreshold?: TAutoCompactThreshold;
|
|
429
|
+
/** Session logger — injected for pluggable session event logging. */
|
|
430
|
+
sessionLogger?: ISessionLogger;
|
|
431
|
+
/** Host-projected transcript path for hook compatibility; never inferred from a record store. */
|
|
432
|
+
transcriptPath?: string;
|
|
433
|
+
/** Additional hook type executors (e.g. prompt, agent) beyond the core defaults. */
|
|
434
|
+
hookTypeExecutors?: IHookTypeExecutor[];
|
|
435
|
+
/** Name reported to the Robota agent config. Defaults to 'agent' if not provided. */
|
|
436
|
+
agentName?: string;
|
|
437
|
+
/**
|
|
438
|
+
* Request structured output from the provider for this session. Issue #2056: the agent config's
|
|
439
|
+
* own shape (`json_schema` included), so a schema request reaches the provider intact.
|
|
440
|
+
*/
|
|
441
|
+
responseFormat?: IResponseFormatConfig;
|
|
442
|
+
/**
|
|
443
|
+
* Reasoning-effort selection threaded to the Robota agent config and provider boundary.
|
|
444
|
+
* When unset, Core preserves provider-default selection as `auto`.
|
|
445
|
+
*/
|
|
446
|
+
effort?: TModelEffortSelection;
|
|
447
|
+
/**
|
|
448
|
+
* ARCH-040: sampling temperature and output cap, threaded to the agent config at CONSTRUCTION.
|
|
449
|
+
*
|
|
450
|
+
* The live `/preset` path has always applied both through `applyModelOptions`, and startup applied
|
|
451
|
+
* neither — so one session held two answers for the same preset depending on WHEN it was chosen,
|
|
452
|
+
* which is what `effort` did before ARCH-013 stage 1 fixed it. `maxOutputTokens` maps to the
|
|
453
|
+
* agent's `maxTokens` channel, the same name `applyModelOptions` already writes.
|
|
454
|
+
*/
|
|
455
|
+
temperature?: number;
|
|
456
|
+
maxOutputTokens?: number;
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* The per-TURN options a caller may attach to one `Session.run()`.
|
|
460
|
+
*
|
|
461
|
+
* Both are optional and independent, and both are absent on the dominant path, so they are spread
|
|
462
|
+
* as a group rather than tested one at a time at each call site.
|
|
463
|
+
*/
|
|
464
|
+
interface ISessionRunOptions {
|
|
465
|
+
/** Awaited core model/tool and automatic-compaction journal for this turn. */
|
|
466
|
+
executionJournal?: IExecutionJournal;
|
|
467
|
+
/** Cancellation belongs to this submission and remains linked until execution settles. */
|
|
468
|
+
signal?: AbortSignal;
|
|
469
|
+
/**
|
|
470
|
+
* SELFHOST-008 P3: a transient system-role block for THIS turn's provider request only. Never
|
|
471
|
+
* written to the conversation store.
|
|
472
|
+
*/
|
|
473
|
+
ephemeralSystemContext?: string;
|
|
474
|
+
/**
|
|
475
|
+
* PEER-007 (issue #1915): display attribution for the stored user message — who drove this turn.
|
|
476
|
+
* Never an authorization input (issue #1809).
|
|
477
|
+
*/
|
|
478
|
+
driverId?: string;
|
|
479
|
+
/** Where this turn came from, stored beside `driverId` on the user message. Display only. */
|
|
480
|
+
turnSource?: string;
|
|
481
|
+
/** Run-scoped model tool directive; 'none' remains in force for this turn only. */
|
|
482
|
+
toolChoice?: TToolChoice;
|
|
483
|
+
/**
|
|
484
|
+
* A message from another agent session started this turn. The reply to that session exists only
|
|
485
|
+
* here, and the provider's hosted tools are withheld because no permission step can decide them;
|
|
486
|
+
* every other call is decided by the session's ordinary permissions.
|
|
487
|
+
*/
|
|
488
|
+
peerTurn?: boolean;
|
|
489
|
+
/** Host-owned trusted trace context for this turn's provider calls (agent-core `IRunOptions`). */
|
|
490
|
+
traceContext?: IRunTraceContext;
|
|
491
|
+
}
|
|
492
|
+
interface IProviderCallTraceObservation {
|
|
493
|
+
readonly callId?: string;
|
|
494
|
+
readonly round: number;
|
|
495
|
+
readonly startedAt: string;
|
|
496
|
+
readonly endedAt: string;
|
|
497
|
+
readonly outcome: 'success' | 'failure' | 'interrupted';
|
|
498
|
+
readonly disposition?: 'invoked' | 'cache-hit' | 'preflight-refused';
|
|
499
|
+
readonly providerId?: string;
|
|
500
|
+
readonly modelId?: string;
|
|
501
|
+
readonly usageProvenance?: 'complete' | 'partial' | 'absent';
|
|
502
|
+
readonly promptTokens?: number;
|
|
503
|
+
readonly completionTokens?: number;
|
|
504
|
+
readonly totalTokens?: number;
|
|
505
|
+
/** Present only for an invoked call whose adapter attested one; never fabricated. */
|
|
506
|
+
readonly providerRequestId?: string;
|
|
507
|
+
}
|
|
508
|
+
//#endregion
|
|
509
|
+
//#region src/session-resume.d.ts
|
|
510
|
+
type TSessionResumeOptions = Pick<IResumeExecutionOptions, 'executionId' | 'journal' | 'signal' | 'traceContext'>;
|
|
511
|
+
//#endregion
|
|
512
|
+
//#region src/session-recoverable.d.ts
|
|
513
|
+
interface ISessionRecoverableRunOptions extends ISessionRunOptions {
|
|
514
|
+
executionJournal: IRecoverableExecutionJournal;
|
|
515
|
+
}
|
|
516
|
+
type TSessionRecoverableResumeOptions = TSessionResumeOptions & Pick<IResumeExecutionOptions, 'toolResponses'>;
|
|
517
|
+
type TSessionExecutionResult = {
|
|
518
|
+
status: 'completed';
|
|
519
|
+
response: string;
|
|
520
|
+
} | {
|
|
521
|
+
status: 'waiting';
|
|
522
|
+
requests: readonly IToolWaitRequest[];
|
|
523
|
+
};
|
|
524
|
+
/**
|
|
525
|
+
* A journaled execution whose round is open in history — parked on saved waits, or stopped by a
|
|
526
|
+
* failure — so the Session accepts no new input until it is resumed or abandoned. `requests` are
|
|
527
|
+
* the saved waits whose effect has not been admitted; empty when a failure left the round open.
|
|
528
|
+
*/
|
|
529
|
+
interface ISessionPendingExecution {
|
|
530
|
+
executionId: string;
|
|
531
|
+
requests: readonly IToolWaitRequest[];
|
|
532
|
+
}
|
|
533
|
+
//#endregion
|
|
534
|
+
//#region src/turn-claim.d.ts
|
|
535
|
+
/**
|
|
536
|
+
* Thrown when a turn is started on a session that is already running one. RUNTIME-003.
|
|
537
|
+
*
|
|
538
|
+
* A distinct type rather than a bare `Error`, because the point of giving the session a claim is to
|
|
539
|
+
* let consumers STOP maintaining their own busy flags — and a consumer that has to regex-match an
|
|
540
|
+
* error message to tell "busy, retry later" apart from a provider failure has not been given
|
|
541
|
+
* anything it can act on. Follows `CompactionError`, this package's existing precedent.
|
|
542
|
+
*/
|
|
543
|
+
declare class SessionBusyError extends Error {
|
|
544
|
+
/** Always `true`: the caller can run this turn later; nothing about the session is broken. */
|
|
545
|
+
readonly recoverable = true;
|
|
546
|
+
constructor(message: string);
|
|
547
|
+
}
|
|
548
|
+
/**
|
|
549
|
+
* The identity of the turn a session is currently running. RUNTIME-003.
|
|
550
|
+
*
|
|
551
|
+
* A session used to express "is something running?" as a bare `AbortController | null` field that
|
|
552
|
+
* `run()` overwrote on entry. That field was doing three jobs at once — cancellation channel, busy
|
|
553
|
+
* flag, and turn identity — and it could only do them for ONE turn, so a second concurrent `run()`
|
|
554
|
+
* orphaned the first: `abort()` reached only whichever turn held the field, and the first turn to
|
|
555
|
+
* finish cleared it in its `finally`, making `abort()` on the survivor a silent no-op. `isRunning()`
|
|
556
|
+
* read the same field, so it answered about whichever turn happened to own it. That is why consumers
|
|
557
|
+
* of this library grew their own busy flags rather than trusting it.
|
|
558
|
+
*
|
|
559
|
+
* The fix is to give the unit of work an OWNER. A claim is taken synchronously, it belongs to the
|
|
560
|
+
* caller that took it, and ONLY that caller releases it.
|
|
561
|
+
*
|
|
562
|
+
* REFUSAL, not pre-emption. A session is a single conversation: two turns interleaving on it produce
|
|
563
|
+
* a history neither of them wrote, and silently cancelling the first would discard work the caller
|
|
564
|
+
* never asked to abandon. `claim()` throws {@link SessionBusyError}, whose message names the three
|
|
565
|
+
* ways forward.
|
|
566
|
+
*/
|
|
567
|
+
declare class TurnClaim {
|
|
568
|
+
private controller;
|
|
569
|
+
private settlement;
|
|
570
|
+
private settle;
|
|
571
|
+
/** Resolves when the currently claimed turn has finished unwinding. */
|
|
572
|
+
get drained(): Promise<void>;
|
|
573
|
+
/**
|
|
574
|
+
* Take the claim for a new turn, or throw if one is already held.
|
|
575
|
+
*
|
|
576
|
+
* MUST be called before the first `await` in the turn — a check that yields first is not a claim,
|
|
577
|
+
* it is a TOCTOU window, and two callers can pass it in the same tick.
|
|
578
|
+
*
|
|
579
|
+
* @throws {SessionBusyError} if a turn is already running, INCLUDING one that has been aborted but
|
|
580
|
+
* has not finished unwinding. See {@link abort} for why that case is not an exception.
|
|
581
|
+
*/
|
|
582
|
+
claim(): AbortController;
|
|
330
583
|
/**
|
|
331
|
-
*
|
|
332
|
-
*
|
|
584
|
+
* Release the claim — but only if `controller` is still the one holding it.
|
|
585
|
+
*
|
|
586
|
+
* The ownership check is what stops the original defect from reappearing in a new shape: a turn
|
|
587
|
+
* that released unconditionally in its `finally` could free a claim a LATER turn already took, and
|
|
588
|
+
* `isRunning()` would then report idle while a turn was in flight.
|
|
333
589
|
*/
|
|
334
|
-
|
|
335
|
-
allow?: readonly string[];
|
|
336
|
-
deny?: readonly string[];
|
|
337
|
-
};
|
|
590
|
+
release(controller: AbortController): void;
|
|
338
591
|
/**
|
|
339
|
-
*
|
|
340
|
-
*
|
|
592
|
+
* Signal the running turn to stop. Idempotent; a no-op if nothing is running.
|
|
593
|
+
*
|
|
594
|
+
* This does NOT release the claim, and that is deliberate. An earlier version cleared it here, so
|
|
595
|
+
* `isRunning()` answered `false` the instant `abort()` returned — while the aborted turn was still
|
|
596
|
+
* unwinding, still able to write history and finish tool calls. A new `run()` could then claim the
|
|
597
|
+
* session and interleave with it: exactly the two-turns-on-one-session defect RUNTIME-003 is
|
|
598
|
+
* about, just moved behind the abort boundary. Review of the first draft caught it.
|
|
599
|
+
*
|
|
600
|
+
* A turn is not over when it is asked to stop; it is over when it has stopped. The claim is
|
|
601
|
+
* therefore held until the owning turn's `finally` releases it, and until then `isRunning()` says
|
|
602
|
+
* `true` and a further `run()` is refused. Cancel and restart is `abort()`, then AWAIT the turn,
|
|
603
|
+
* then `run()` — which is what every caller in this repo already does.
|
|
341
604
|
*/
|
|
342
|
-
|
|
605
|
+
abort(): void;
|
|
606
|
+
isRunning(): boolean;
|
|
343
607
|
}
|
|
344
608
|
//#endregion
|
|
345
609
|
//#region src/permission-denial-log.d.ts
|
|
@@ -391,13 +655,14 @@ declare class PermissionEnforcer {
|
|
|
391
655
|
private readonly denials;
|
|
392
656
|
/** A turn a peer's message started is in progress: the one place the reply to that peer exists. */
|
|
393
657
|
private peerTurn;
|
|
658
|
+
private checkpointedApprovals;
|
|
394
659
|
private readonly autoMode?;
|
|
395
660
|
constructor(options: IPermissionEnforcerOptions);
|
|
396
661
|
/**
|
|
397
662
|
* Start a turn, which a peer's message started when `peerTurn` is true. That decides only whether
|
|
398
663
|
* the reply to the peer exists; every other call is decided exactly as in any turn.
|
|
399
664
|
*/
|
|
400
|
-
beginTurn(peerTurn: boolean): void;
|
|
665
|
+
beginTurn(peerTurn: boolean, checkpointedApprovals?: boolean): void;
|
|
401
666
|
/** End the turn; the reply to a peer is gone until the next peer turn begins. */
|
|
402
667
|
endTurn(): void;
|
|
403
668
|
/** Whether `auto` mode can run here: it needs a classifier to decide for it. */
|
|
@@ -476,6 +741,7 @@ declare class PermissionEnforcer {
|
|
|
476
741
|
checkDelegatedToolCall(toolName: string, toolParameters: TToolParameters, signal?: AbortSignal): Promise<boolean>;
|
|
477
742
|
/** {@link checkPermission}, keeping the reason a refusal carries for the model. */
|
|
478
743
|
private decidePermission;
|
|
744
|
+
private evaluateToolPermission;
|
|
479
745
|
private decideInAutoMode;
|
|
480
746
|
/**
|
|
481
747
|
* The human-approval path: session-scoped allow list → custom handler → injected approval fn → fail-closed
|
|
@@ -668,224 +934,6 @@ declare abstract class SessionBase {
|
|
|
668
934
|
clearHistory(): void;
|
|
669
935
|
}
|
|
670
936
|
//#endregion
|
|
671
|
-
//#region src/session-types.d.ts
|
|
672
|
-
/** Options for graceful session shutdown. */
|
|
673
|
-
interface ISessionShutdownOptions {
|
|
674
|
-
reason?: TSessionEndReason;
|
|
675
|
-
}
|
|
676
|
-
/** Options for constructing a Session */
|
|
677
|
-
interface ISessionOptions {
|
|
678
|
-
/** Pre-constructed tools to register with the agent */
|
|
679
|
-
tools: IToolWithEventService[];
|
|
680
|
-
/**
|
|
681
|
-
* Applies to a tool added after construction (`Session.addTools`) the wrappers the assembler
|
|
682
|
-
* applied to `tools`, so a late tool is held to the same safety policy as one present from the
|
|
683
|
-
* start. The permission gate is applied by the session itself either way.
|
|
684
|
-
*/
|
|
685
|
-
wrapAddedTools?: (tools: IToolWithEventService[]) => IToolWithEventService[];
|
|
686
|
-
/** Pre-constructed AI provider */
|
|
687
|
-
provider: IAIProvider;
|
|
688
|
-
/** Pre-built system message string */
|
|
689
|
-
systemMessage: string;
|
|
690
|
-
/** Terminal I/O for permission prompts */
|
|
691
|
-
terminal: ITerminalOutput;
|
|
692
|
-
/**
|
|
693
|
-
* The session's execution root. REQUIRED — ARCH-010.
|
|
694
|
-
*
|
|
695
|
-
* This field did not exist. `Session` read `process.cwd()` in its constructor and that ambient
|
|
696
|
-
* value became the session's identity everywhere it matters: every hook input,
|
|
697
|
-
* `CLAUDE_PROJECT_DIR`, `PermissionEnforcer`'s root, and the persisted record. Meanwhile the
|
|
698
|
-
* subagent spawn contract has always declared `cwd` REQUIRED — and the in-process runner passed
|
|
699
|
-
* none, because there was no option to pass it to. A session that cannot be told where it runs
|
|
700
|
-
* silently runs wherever the process happens to be, which for a subagent is not its own workspace.
|
|
701
|
-
*
|
|
702
|
-
* A caller that genuinely means "this process's directory" passes `process.cwd()` where a reader
|
|
703
|
-
* can see the decision.
|
|
704
|
-
*/
|
|
705
|
-
cwd: string;
|
|
706
|
-
/** Permission and hook configuration */
|
|
707
|
-
permissions?: {
|
|
708
|
-
allow: string[];
|
|
709
|
-
deny: string[];
|
|
710
|
-
ask?: string[];
|
|
711
|
-
};
|
|
712
|
-
/**
|
|
713
|
-
* ARCH-040 Group C (issue #1934): the permission rules BEFORE any preset contributed.
|
|
714
|
-
*
|
|
715
|
-
* Passed rather than inferred. `permissions` above already has the startup preset's patterns baked
|
|
716
|
-
* in, so an enforcer that captured its own base from it on the first live `/preset` would keep the
|
|
717
|
-
* FIRST preset's allowlist forever — the accumulation the replace rule exists to prevent, arriving
|
|
718
|
-
* through the base instead of through the merge. Absent ⇒ no preset contributed and the two are
|
|
719
|
-
* the same.
|
|
720
|
-
*/
|
|
721
|
-
presetFreePermissions?: {
|
|
722
|
-
allow: readonly string[];
|
|
723
|
-
deny: readonly string[];
|
|
724
|
-
};
|
|
725
|
-
hooks?: Record<string, unknown>;
|
|
726
|
-
/** Initial permission mode */
|
|
727
|
-
permissionMode?: TPermissionMode;
|
|
728
|
-
/**
|
|
729
|
-
* CORE-025: background/subagent task permission policy. Resolved BEFORE the session-mode gate, so
|
|
730
|
-
* `deny`/`preapproved`/`inherit-allowlist` override even a permissive `permissionMode`. Absent on a normal
|
|
731
|
-
* interactive session (mode gate alone). Set by `createSubagentSession` from the spawn request.
|
|
732
|
-
*/
|
|
733
|
-
permissionPolicy?: TBackgroundPermissionPolicy;
|
|
734
|
-
/** CORE-025: the task's OWN allow/deny lists (what `preapproved` consults; distinct from `permissions`). */
|
|
735
|
-
taskPermissions?: {
|
|
736
|
-
allow?: readonly string[];
|
|
737
|
-
deny?: readonly string[];
|
|
738
|
-
};
|
|
739
|
-
/**
|
|
740
|
-
* Injected "ask the user" port (CMD-005): forwarded into the agent config so model-invoked tools
|
|
741
|
-
* (AskUserQuestion) can solicit a structured answer. Absent in headless/automation sessions.
|
|
742
|
-
*/
|
|
743
|
-
ask?: IUserInteraction['ask'];
|
|
744
|
-
/** Default trust level — used to derive permissionMode if not given */
|
|
745
|
-
defaultTrustLevel?: 'safe' | 'moderate' | 'full';
|
|
746
|
-
/** Active preset id selected at startup (PRESET-011 runtime state). Defaults to 'default'. */
|
|
747
|
-
activePresetId?: string;
|
|
748
|
-
/**
|
|
749
|
-
* Whether subagent dispatch is allowed for this session (PRESET-016 runtime gate). Defaults to
|
|
750
|
-
* true (current behavior). Only meaningful when the agent runtime was built at assembly.
|
|
751
|
-
*/
|
|
752
|
-
enableParallelSubagents?: boolean;
|
|
753
|
-
/** Model name (for context window sizing and Robota config) */
|
|
754
|
-
model?: string;
|
|
755
|
-
/** Provider idle timeout in milliseconds for each model call */
|
|
756
|
-
providerTimeout?: number;
|
|
757
|
-
/** Maximum number of agentic turns per run() call. Undefined = unlimited. */
|
|
758
|
-
maxTurns?: number;
|
|
759
|
-
/** Optional session store for persistence */
|
|
760
|
-
sessionStore?: IInteractiveSessionStore$1;
|
|
761
|
-
/** Override session ID (used when resuming a session to reuse the original ID) */
|
|
762
|
-
sessionId?: string;
|
|
763
|
-
/** Custom permission handler (overrides terminal-based prompts, used by Ink UI) */
|
|
764
|
-
permissionHandler?: TPermissionHandler;
|
|
765
|
-
/** The OS sandbox the shell tools run under, which may let a confined command skip the prompt. */
|
|
766
|
-
commandSandbox?: ICommandSandboxApproval;
|
|
767
|
-
/** Decides for `auto` mode. Without one the session refuses that mode. */
|
|
768
|
-
permissionClassifier?: IPermissionClassifier;
|
|
769
|
-
/** Called when the user selects "allow for project" — persists the tool pattern to project settings. */
|
|
770
|
-
onProjectAllowTool?: (toolName: string) => void;
|
|
771
|
-
/** Callback for text deltas — enables streaming text to the UI in real-time */
|
|
772
|
-
onTextDelta?: (delta: string) => void;
|
|
773
|
-
/** Callback when context window usage is refreshed */
|
|
774
|
-
onContextUpdate?: (state: IContextWindowState) => void;
|
|
775
|
-
/** Custom prompt-for-approval function (injected from CLI) */
|
|
776
|
-
promptForApproval?: (terminal: ITerminalOutput, toolName: string, toolArgs: TToolArgs) => Promise<TPermissionResult>;
|
|
777
|
-
/** Callback when a tool starts or finishes execution — enables real-time tool display in UI */
|
|
778
|
-
onToolExecution?: (event: {
|
|
779
|
-
type: 'start' | 'end';
|
|
780
|
-
toolName: string;
|
|
781
|
-
toolArgs?: TToolArgs;
|
|
782
|
-
success?: boolean;
|
|
783
|
-
denied?: boolean;
|
|
784
|
-
toolResultData?: string;
|
|
785
|
-
executionId?: string;
|
|
786
|
-
}) => void;
|
|
787
|
-
/** Callback when context is compacted */
|
|
788
|
-
onCompact?: (summary: string) => void;
|
|
789
|
-
/** Callback with structured compaction metadata */
|
|
790
|
-
onCompactEvent?: (event: ICompactEvent) => void;
|
|
791
|
-
/** Instructions to include in the compaction prompt (e.g. from project context files) */
|
|
792
|
-
compactInstructions?: string;
|
|
793
|
-
/**
|
|
794
|
-
* Replaces the base instruction template of the compaction summarization prompt
|
|
795
|
-
* (default: `DEFAULT_COMPACTION_PROMPT`, a domain-neutral template). Lets the consuming
|
|
796
|
-
* layer own the compaction prompt wording entirely.
|
|
797
|
-
*/
|
|
798
|
-
compactionBasePrompt?: string;
|
|
799
|
-
/**
|
|
800
|
-
* Concrete remediation wording for the core's hard-capacity notice, forwarded to the Robota
|
|
801
|
-
* agent config as `IAgentConfig.contextCapacityHint`. The zero-dependency core emits a
|
|
802
|
-
* product-neutral default; a surface tier that owns a real remediation command (e.g. a
|
|
803
|
-
* `/compact` slash command) injects its own actionable hint here. Absent ⇒ the neutral
|
|
804
|
-
* `DEFAULT_CONTEXT_CAPACITY_HINT` applies.
|
|
805
|
-
*/
|
|
806
|
-
contextCapacityHint?: string;
|
|
807
|
-
/** Override context max tokens (otherwise derived from model name) */
|
|
808
|
-
contextMaxTokens?: number;
|
|
809
|
-
/** Auto-compact threshold as a 0-1 fraction. Set false to disable automatic compaction. */
|
|
810
|
-
autoCompactThreshold?: TAutoCompactThreshold;
|
|
811
|
-
/** Session logger — injected for pluggable session event logging. */
|
|
812
|
-
sessionLogger?: ISessionLogger;
|
|
813
|
-
/** Host-projected transcript path for hook compatibility; never inferred from a record store. */
|
|
814
|
-
transcriptPath?: string;
|
|
815
|
-
/** Additional hook type executors (e.g. prompt, agent) beyond the core defaults. */
|
|
816
|
-
hookTypeExecutors?: IHookTypeExecutor[];
|
|
817
|
-
/** Name reported to the Robota agent config. Defaults to 'agent' if not provided. */
|
|
818
|
-
agentName?: string;
|
|
819
|
-
/**
|
|
820
|
-
* Request structured output from the provider for this session. Issue #2056: the agent config's
|
|
821
|
-
* own shape (`json_schema` included), so a schema request reaches the provider intact.
|
|
822
|
-
*/
|
|
823
|
-
responseFormat?: IResponseFormatConfig;
|
|
824
|
-
/**
|
|
825
|
-
* Reasoning-effort selection threaded to the Robota agent config and provider boundary.
|
|
826
|
-
* When unset, Core preserves provider-default selection as `auto`.
|
|
827
|
-
*/
|
|
828
|
-
effort?: TModelEffortSelection;
|
|
829
|
-
/**
|
|
830
|
-
* ARCH-040: sampling temperature and output cap, threaded to the agent config at CONSTRUCTION.
|
|
831
|
-
*
|
|
832
|
-
* The live `/preset` path has always applied both through `applyModelOptions`, and startup applied
|
|
833
|
-
* neither — so one session held two answers for the same preset depending on WHEN it was chosen,
|
|
834
|
-
* which is what `effort` did before ARCH-013 stage 1 fixed it. `maxOutputTokens` maps to the
|
|
835
|
-
* agent's `maxTokens` channel, the same name `applyModelOptions` already writes.
|
|
836
|
-
*/
|
|
837
|
-
temperature?: number;
|
|
838
|
-
maxOutputTokens?: number;
|
|
839
|
-
}
|
|
840
|
-
/**
|
|
841
|
-
* The per-TURN options a caller may attach to one `Session.run()`.
|
|
842
|
-
*
|
|
843
|
-
* Both are optional and independent, and both are absent on the dominant path, so they are spread
|
|
844
|
-
* as a group rather than tested one at a time at each call site.
|
|
845
|
-
*/
|
|
846
|
-
interface ISessionRunOptions {
|
|
847
|
-
/** Cancellation belongs to this submission and remains linked until execution settles. */
|
|
848
|
-
signal?: AbortSignal;
|
|
849
|
-
/**
|
|
850
|
-
* SELFHOST-008 P3: a transient system-role block for THIS turn's provider request only. Never
|
|
851
|
-
* written to the conversation store.
|
|
852
|
-
*/
|
|
853
|
-
ephemeralSystemContext?: string;
|
|
854
|
-
/**
|
|
855
|
-
* PEER-007 (issue #1915): display attribution for the stored user message — who drove this turn.
|
|
856
|
-
* Never an authorization input (issue #1809).
|
|
857
|
-
*/
|
|
858
|
-
driverId?: string;
|
|
859
|
-
/** Where this turn came from, stored beside `driverId` on the user message. Display only. */
|
|
860
|
-
turnSource?: string;
|
|
861
|
-
/** Run-scoped model tool directive; 'none' remains in force for this turn only. */
|
|
862
|
-
toolChoice?: TToolChoice;
|
|
863
|
-
/**
|
|
864
|
-
* A message from another agent session started this turn. The reply to that session exists only
|
|
865
|
-
* here, and the provider's hosted tools are withheld because no permission step can decide them;
|
|
866
|
-
* every other call is decided by the session's ordinary permissions.
|
|
867
|
-
*/
|
|
868
|
-
peerTurn?: boolean;
|
|
869
|
-
/** Host-owned trusted trace context for this turn's provider calls (agent-core `IRunOptions`). */
|
|
870
|
-
traceContext?: IRunTraceContext;
|
|
871
|
-
}
|
|
872
|
-
interface IProviderCallTraceObservation {
|
|
873
|
-
readonly callId?: string;
|
|
874
|
-
readonly round: number;
|
|
875
|
-
readonly startedAt: string;
|
|
876
|
-
readonly endedAt: string;
|
|
877
|
-
readonly outcome: 'success' | 'failure' | 'interrupted';
|
|
878
|
-
readonly disposition?: 'invoked' | 'cache-hit' | 'preflight-refused';
|
|
879
|
-
readonly providerId?: string;
|
|
880
|
-
readonly modelId?: string;
|
|
881
|
-
readonly usageProvenance?: 'complete' | 'partial' | 'absent';
|
|
882
|
-
readonly promptTokens?: number;
|
|
883
|
-
readonly completionTokens?: number;
|
|
884
|
-
readonly totalTokens?: number;
|
|
885
|
-
/** Present only for an invoked call whose adapter attested one; never fabricated. */
|
|
886
|
-
readonly providerRequestId?: string;
|
|
887
|
-
}
|
|
888
|
-
//#endregion
|
|
889
937
|
//#region src/session.d.ts
|
|
890
938
|
/** Wraps a Robota agent with project context, permission state, and optional persistence. */
|
|
891
939
|
declare class Session extends SessionBase {
|
|
@@ -926,6 +974,8 @@ declare class Session extends SessionBase {
|
|
|
926
974
|
/** The last tool change; the next one waits for it. */
|
|
927
975
|
private toolChange;
|
|
928
976
|
private shuttingDown;
|
|
977
|
+
/** Set while a journaled execution's round is open in history; cleared once it settles or is abandoned. */
|
|
978
|
+
private pendingExecution?;
|
|
929
979
|
private shutdownPromise;
|
|
930
980
|
/** Stdout collected from SessionStart hooks, injected on first run(). */
|
|
931
981
|
private sessionStartStdout;
|
|
@@ -938,6 +988,22 @@ declare class Session extends SessionBase {
|
|
|
938
988
|
* REJECTS with `SessionBusyError` if a turn is in flight — RUNTIME-003; see `turn-claim.ts`.
|
|
939
989
|
*/
|
|
940
990
|
run(message: string, rawInput?: string, options?: ISessionRunOptions): Promise<string>;
|
|
991
|
+
/** Run with durable approval requests instead of a live approval Promise. */
|
|
992
|
+
runRecoverable(message: string, options: ISessionRecoverableRunOptions, rawInput?: string): Promise<TSessionExecutionResult>;
|
|
993
|
+
private runTurn;
|
|
994
|
+
/** Resume the original Session execution under current permissions without submitting input. */
|
|
995
|
+
resume(options: TSessionResumeOptions): Promise<string>;
|
|
996
|
+
/** Recheck current permissions and continue exact journaled responses without another input. */
|
|
997
|
+
resumeRecoverable(options: TSessionRecoverableResumeOptions): Promise<TSessionExecutionResult>;
|
|
998
|
+
private resumeTurn;
|
|
999
|
+
/** The execution blocking new input, if any: parked on saved waits, or left open by a failure. */
|
|
1000
|
+
getPendingExecution(): ISessionPendingExecution | undefined;
|
|
1001
|
+
/**
|
|
1002
|
+
* Give up a pending execution so the Session accepts new input. Nothing runs and nothing is
|
|
1003
|
+
* journaled: calls its parked round left open are closed in history as failed, and the journal's
|
|
1004
|
+
* records stay with the host. Resuming the execution afterwards is refused as a history conflict.
|
|
1005
|
+
*/
|
|
1006
|
+
abandonPendingExecution(executionId: string): void;
|
|
941
1007
|
/**
|
|
942
1008
|
* Make tools available from the next turn on — for a capability that became usable mid-session,
|
|
943
1009
|
* such as an MCP server connected after its sign-in. Each goes through the same wrappers and
|
|
@@ -973,7 +1039,7 @@ declare class Session extends SessionBase {
|
|
|
973
1039
|
*/
|
|
974
1040
|
shutdown(options?: ISessionShutdownOptions): Promise<void>;
|
|
975
1041
|
swapProvider(newProvider: IAIProvider, model: string): void;
|
|
976
|
-
compact(instructions?: string, trigger?: TCompactTrigger, signal?: AbortSignal): Promise<void>;
|
|
1042
|
+
compact(instructions?: string, trigger?: TCompactTrigger, signal?: AbortSignal, executionJournal?: IExecutionJournal): Promise<void>;
|
|
977
1043
|
/** `hookTraceEnv` reaches PreCompact only for a compaction inside a prompt (see `executeRun`). */
|
|
978
1044
|
private compactWith;
|
|
979
1045
|
private buildRunContext;
|
|
@@ -1038,7 +1104,7 @@ declare class CompactionOrchestrator {
|
|
|
1038
1104
|
* @throws {CompactionError} when `history` is empty, or when the provider returns a non-string or
|
|
1039
1105
|
* empty summary — callers must leave the conversation history untouched in every such case
|
|
1040
1106
|
*/
|
|
1041
|
-
compact(provider: IAIProvider, history: TUniversalMessage[], instructions?: string, signal?: AbortSignal, trigger?: TCompactTrigger, hookTraceEnv?: ISubprocessTraceEnv): Promise<string>;
|
|
1107
|
+
compact(provider: IAIProvider, history: TUniversalMessage[], instructions?: string, signal?: AbortSignal, trigger?: TCompactTrigger, hookTraceEnv?: ISubprocessTraceEnv, executionJournal?: IExecutionJournal): Promise<string>;
|
|
1042
1108
|
/** Build the compaction prompt from conversation history */
|
|
1043
1109
|
private buildCompactionPrompt;
|
|
1044
1110
|
}
|
|
@@ -1554,16 +1620,25 @@ declare class CheckpointTree {
|
|
|
1554
1620
|
}
|
|
1555
1621
|
//#endregion
|
|
1556
1622
|
//#region src/session-record-codec/decode-outcome.d.ts
|
|
1557
|
-
/**
|
|
1623
|
+
/**
|
|
1624
|
+
* What a decode of a persisted session record can conclude.
|
|
1625
|
+
*
|
|
1626
|
+
* `corrupt` and `unsupported` carry an optional `cwd`: a best-effort, untyped read of the raw value
|
|
1627
|
+
* for a plain `cwd` string, taken even though the rest of the value failed full decode. It exists so
|
|
1628
|
+
* a caller that only wants to know which workspace an unreadable record belongs to — never its
|
|
1629
|
+
* content — is not forced to treat every one of them as workspace-unknown.
|
|
1630
|
+
*/
|
|
1558
1631
|
type TSessionRecordDecodeOutcome = {
|
|
1559
1632
|
readonly status: 'valid';
|
|
1560
1633
|
readonly record: IInteractiveSessionRecord$1;
|
|
1561
1634
|
} | {
|
|
1562
1635
|
readonly status: 'corrupt';
|
|
1563
1636
|
readonly issues: readonly ISessionRecordDecodeIssue[];
|
|
1637
|
+
readonly cwd?: string;
|
|
1564
1638
|
} | {
|
|
1565
1639
|
readonly status: 'unsupported';
|
|
1566
1640
|
readonly schemaVersion: number | undefined;
|
|
1641
|
+
readonly cwd?: string;
|
|
1567
1642
|
};
|
|
1568
1643
|
//#endregion
|
|
1569
1644
|
//#region src/session-record-codec/record-decoder.d.ts
|
|
@@ -1618,5 +1693,5 @@ declare function decodeInteractiveSessionRecord(value: unknown): TSessionRecordD
|
|
|
1618
1693
|
*/
|
|
1619
1694
|
declare function decodeVersionedInteractiveSessionRecord(value: unknown): TSessionRecordDecodeOutcome;
|
|
1620
1695
|
//#endregion
|
|
1621
|
-
export { AUTO_COMPACT_THRESHOLD, AutoModeGate, CONSECUTIVE_BLOCK_LIMIT, CheckpointTree, CompactionError, CompactionOrchestrator, ContextWindowTracker, DEFAULT_COMPACTION_PROMPT, DEFAULT_PROMPT_HISTORY_BLOCK_BYTES, FileSessionLogger, type ICheckpointNode, type IClassifiedCall, type IClassifierVerdict, type ICommandSandboxApproval, type IExternalPayloadReference, type IExternalPayloadSink, type IExternalPayloadSource, type IFileSessionLoggerOptions, type IInteractiveSessionRecord, type IInteractiveSessionStore, INTERACTIVE_SESSION_RECORD_KEYS, type INodePromptHistoryFileOptions, type INodeToolResultSpillStoreOptions, type IPermissionClassifier, type IPermissionDenial, type IProviderCallTraceObservation, type IProviderEventKey, type ISerializeSessionArtifactOptions, type ISessionLogEntry, type ISessionLogLine, type ISessionLogLoadOptions, type ISessionLogPayloadResolutionErrorMetadata, type ISessionLogPayloadResolutionOptions, type ISessionLogSink, type ISessionLogSource, type ISessionLogger, type ISessionOptions, type ISessionRecord, type ISessionReplayRecord, type ISessionReplayValidationIssue, type ISessionReplayValidationResult, type ISessionRunOptions, type ISessionShutdownOptions, type ISessionStore, type ISpinner, type ITerminalOutput, type IToolEventKey, type IVersionedInteractiveSessionRecord, NodeExternalPayloadSource, NodePromptHistoryFile, NodeSessionLogSink, NodeSessionLogSource, NodeSessionStore, NodeToolResultSpillStore, PermissionEnforcer, SENSITIVE_KEY_PATTERN, SESSION_LOG_EVENT, SESSION_LOG_SCHEMA_VERSION, SESSION_RECORD_ENVELOPE_VERSION, Session, SessionBusyError, SessionLogDecodeError, SessionLogPayloadResolutionError, SilentSessionLogger, type TAutoCompactThreshold, type TAutoModeJudgement, type TDecodedSessionLogEntry, TOTAL_BLOCK_LIMIT, type TPermissionDenialReason, type TPermissionHandler, type TPermissionResult, type TScrubbableValue, type TSessionLogData, type TSessionLogDecodeErrorCode, type TSessionLogEventName, type TSessionLogPayloadResolutionErrorCode, type TSessionLogValue, type TSessionRecordDecodeOutcome, type TToolResultSpillErrorCode, ToolResultSpillError, TurnClaim, assertSafeSessionId, consentScopeFor, createSessionLogExternalPayloadReference, decodeInteractiveSessionRecord, decodeSessionLogEntries, decodeVersionedInteractiveSessionRecord, deserializeSessionArtifact, formatConversationEntries, isSafeSessionId, isSensitiveKey, isSessionLogEvent, loadSessionLogEntries, parsePromptHistoryLine, replaySessionLogEntries, resolveSessionLogExternalPayloads, scrubSensitiveKeys, serializeSessionArtifact, validateSessionReplayLogEntries };
|
|
1696
|
+
export { AUTO_COMPACT_THRESHOLD, AutoModeGate, CONSECUTIVE_BLOCK_LIMIT, CheckpointTree, CompactionError, CompactionOrchestrator, ContextWindowTracker, DEFAULT_COMPACTION_PROMPT, DEFAULT_PROMPT_HISTORY_BLOCK_BYTES, FileSessionLogger, type ICheckpointNode, type IClassifiedCall, type IClassifierVerdict, type ICommandSandboxApproval, type IExternalPayloadReference, type IExternalPayloadSink, type IExternalPayloadSource, type IFileSessionLoggerOptions, type IInteractiveSessionRecord, type IInteractiveSessionStore, INTERACTIVE_SESSION_RECORD_KEYS, type INodePromptHistoryFileOptions, type INodeToolResultSpillStoreOptions, type IPermissionAskContext, type IPermissionClassifier, type IPermissionDenial, type IProviderCallTraceObservation, type IProviderEventKey, type ISerializeSessionArtifactOptions, type ISessionLogEntry, type ISessionLogLine, type ISessionLogLoadOptions, type ISessionLogPayloadResolutionErrorMetadata, type ISessionLogPayloadResolutionOptions, type ISessionLogSink, type ISessionLogSource, type ISessionLogger, type ISessionOptions, type ISessionPendingExecution, type ISessionRecord, type ISessionRecoverableRunOptions, type ISessionReplayRecord, type ISessionReplayValidationIssue, type ISessionReplayValidationResult, type ISessionRunOptions, type ISessionShutdownOptions, type ISessionStore, type ISpinner, type ITerminalOutput, type IToolEventKey, type IVersionedInteractiveSessionRecord, NodeExternalPayloadSource, NodePromptHistoryFile, NodeSessionLogSink, NodeSessionLogSource, NodeSessionStore, NodeToolResultSpillStore, PermissionEnforcer, SENSITIVE_KEY_PATTERN, SESSION_LOG_EVENT, SESSION_LOG_SCHEMA_VERSION, SESSION_RECORD_ENVELOPE_VERSION, Session, SessionBusyError, SessionLogDecodeError, SessionLogPayloadResolutionError, SilentSessionLogger, type TAutoCompactThreshold, type TAutoModeJudgement, type TDecodedSessionLogEntry, TOTAL_BLOCK_LIMIT, type TPermissionDenialReason, type TPermissionHandler, type TPermissionRequester, type TPermissionResult, type TScrubbableValue, type TSessionExecutionResult, type TSessionLogData, type TSessionLogDecodeErrorCode, type TSessionLogEventName, type TSessionLogPayloadResolutionErrorCode, type TSessionLogValue, type TSessionRecordDecodeOutcome, type TSessionRecoverableResumeOptions, type TSessionResumeOptions, type TToolResultSpillErrorCode, ToolResultSpillError, TurnClaim, assertSafeSessionId, consentScopeFor, createSessionLogExternalPayloadReference, decodeInteractiveSessionRecord, decodeSessionLogEntries, decodeVersionedInteractiveSessionRecord, deserializeSessionArtifact, formatConversationEntries, isSafeSessionId, isSensitiveKey, isSessionLogEvent, loadSessionLogEntries, parsePromptHistoryLine, replaySessionLogEntries, resolveSessionLogExternalPayloads, scrubSensitiveKeys, serializeSessionArtifact, validateSessionReplayLogEntries };
|
|
1622
1697
|
//# sourceMappingURL=index.d.cts.map
|