@myagentroam/agent 0.9.159 → 0.9.160

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 (128) hide show
  1. package/dist/agent-core/extensions/agents.d.ts +69 -0
  2. package/dist/agent-core/extensions/agents.js +160 -0
  3. package/dist/agent-core/extensions/contracts.d.ts +260 -0
  4. package/dist/agent-core/extensions/contracts.js +1 -0
  5. package/dist/agent-core/extensions/data.d.ts +84 -0
  6. package/dist/agent-core/extensions/data.js +83 -0
  7. package/dist/agent-core/extensions/environment.d.ts +27 -0
  8. package/dist/agent-core/extensions/environment.js +52 -0
  9. package/dist/agent-core/extensions/files.d.ts +64 -0
  10. package/dist/agent-core/extensions/files.js +26 -0
  11. package/dist/agent-core/extensions/hooks.d.ts +32 -0
  12. package/dist/agent-core/extensions/hooks.js +135 -0
  13. package/dist/agent-core/extensions/manager.d.ts +39 -0
  14. package/dist/agent-core/extensions/manager.js +458 -0
  15. package/dist/agent-core/extensions/mcp.d.ts +99 -0
  16. package/dist/agent-core/extensions/mcp.js +433 -0
  17. package/dist/agent-core/extensions/model-request.d.ts +60 -0
  18. package/dist/agent-core/extensions/model-request.js +167 -0
  19. package/dist/agent-core/extensions/model-stream.d.ts +9 -0
  20. package/dist/agent-core/extensions/model-stream.js +101 -0
  21. package/dist/agent-core/extensions/models.d.ts +43 -0
  22. package/dist/agent-core/extensions/models.js +1 -0
  23. package/dist/agent-core/extensions/network.d.ts +32 -0
  24. package/dist/agent-core/extensions/network.js +97 -0
  25. package/dist/agent-core/extensions/operation.d.ts +29 -0
  26. package/dist/agent-core/extensions/operation.js +98 -0
  27. package/dist/agent-core/extensions/processes.d.ts +52 -0
  28. package/dist/agent-core/extensions/processes.js +283 -0
  29. package/dist/agent-core/extensions/prompt-composition.d.ts +24 -0
  30. package/dist/agent-core/extensions/prompt-composition.js +106 -0
  31. package/dist/agent-core/extensions/prompt-input.d.ts +23 -0
  32. package/dist/agent-core/extensions/prompt-input.js +46 -0
  33. package/dist/agent-core/extensions/resources.d.ts +27 -0
  34. package/dist/agent-core/extensions/resources.js +221 -0
  35. package/dist/agent-core/extensions/services.d.ts +31 -0
  36. package/dist/agent-core/extensions/services.js +61 -0
  37. package/dist/agent-core/extensions/session-input.d.ts +151 -0
  38. package/dist/agent-core/extensions/session-input.js +351 -0
  39. package/dist/agent-core/extensions/session-messages.d.ts +41 -0
  40. package/dist/agent-core/extensions/session-messages.js +76 -0
  41. package/dist/agent-core/extensions/session.d.ts +68 -0
  42. package/dist/agent-core/extensions/session.js +593 -0
  43. package/dist/agent-core/extensions/settings.d.ts +59 -0
  44. package/dist/agent-core/extensions/settings.js +115 -0
  45. package/dist/agent-core/extensions/store.d.ts +10 -0
  46. package/dist/agent-core/extensions/store.js +131 -0
  47. package/dist/agent-core/extensions/tools.d.ts +61 -0
  48. package/dist/agent-core/extensions/tools.js +266 -0
  49. package/dist/agent-core/host/contracts.d.ts +25 -0
  50. package/dist/agent-core/host/local-agent-host.d.ts +10 -1
  51. package/dist/agent-core/host/local-agent-host.js +132 -20
  52. package/dist/agent-core/host/local-file-access.d.ts +30 -0
  53. package/dist/agent-core/host/local-file-access.js +107 -0
  54. package/dist/agent-core/host/local-network-access.d.ts +6 -0
  55. package/dist/agent-core/host/local-network-access.js +97 -0
  56. package/dist/agent-core/host/local-process-executor.d.ts +5 -1
  57. package/dist/agent-core/host/local-session-environment.d.ts +18 -0
  58. package/dist/agent-core/host/local-session-environment.js +102 -0
  59. package/dist/agent-core/model/anthropic-messages.js +73 -23
  60. package/dist/agent-core/model/contracts.d.ts +12 -0
  61. package/dist/agent-core/model/openai-responses.js +73 -12
  62. package/dist/agent-core/model/text-blocks.d.ts +7 -0
  63. package/dist/agent-core/model/text-blocks.js +40 -0
  64. package/dist/agent-core/prompts/index.d.ts +6 -2
  65. package/dist/agent-core/prompts/index.js +38 -24
  66. package/dist/agent-core/runtime/context/gc-tokens.js +6 -1
  67. package/dist/agent-core/runtime/context/normalize.js +21 -1
  68. package/dist/agent-core/runtime/context/projection.js +35 -1
  69. package/dist/agent-core/runtime/context/request-budget.js +5 -2
  70. package/dist/agent-core/runtime/context/restore.d.ts +5 -0
  71. package/dist/agent-core/runtime/context/restore.js +47 -4
  72. package/dist/agent-core/runtime/context/usage.js +2 -3
  73. package/dist/agent-core/runtime/contracts.d.ts +2 -0
  74. package/dist/agent-core/runtime/execution.js +5 -2
  75. package/dist/agent-core/sdk/agent.js +177 -40
  76. package/dist/agent-core/sdk/extension-agents.d.ts +9 -0
  77. package/dist/agent-core/sdk/extension-agents.js +51 -0
  78. package/dist/agent-core/sdk/extension-models.d.ts +13 -0
  79. package/dist/agent-core/sdk/extension-models.js +128 -0
  80. package/dist/agent-core/sdk/extension-session.d.ts +30 -0
  81. package/dist/agent-core/sdk/extension-session.js +103 -0
  82. package/dist/agent-core/sdk/extension-tools.d.ts +16 -0
  83. package/dist/agent-core/sdk/extension-tools.js +126 -0
  84. package/dist/agent-core/sdk/session.d.ts +26 -2
  85. package/dist/agent-core/sdk/session.js +1215 -506
  86. package/dist/agent-core/sdk/types.d.ts +3 -0
  87. package/dist/agent-core/session/context-gc-checkpoint.js +1 -1
  88. package/dist/agent-core/session/jsonl-store.d.ts +28 -8
  89. package/dist/agent-core/session/jsonl-store.js +124 -84
  90. package/dist/agent-core/session/types.d.ts +4 -1
  91. package/dist/agent-core/storage/file-lock.d.ts +4 -0
  92. package/dist/agent-core/storage/file-lock.js +83 -0
  93. package/dist/agent-core/subagent/contracts.d.ts +11 -1
  94. package/dist/agent-core/subagent/scheduler.d.ts +8 -0
  95. package/dist/agent-core/subagent/session-controller.d.ts +22 -1
  96. package/dist/agent-core/subagent/session-controller.js +355 -98
  97. package/dist/agent-core/tools/agent/agent-start.d.ts +1 -1
  98. package/dist/agent-core/tools/code-mode/cells.js +5 -15
  99. package/dist/agent-core/tools/code-mode/dispatch.d.ts +1 -0
  100. package/dist/agent-core/tools/code-mode/dispatch.js +13 -1
  101. package/dist/agent-core/tools/code-mode/index.js +1 -2
  102. package/dist/agent-core/tools/code-mode/observations.d.ts +5 -0
  103. package/dist/agent-core/tools/code-mode/observations.js +16 -5
  104. package/dist/agent-core/tools/code-mode/quickjs-engine.js +10 -5
  105. package/dist/agent-core/tools/execution.d.ts +11 -2
  106. package/dist/agent-core/tools/execution.js +58 -21
  107. package/dist/agent-core/tools/input.d.ts +2 -0
  108. package/dist/agent-core/tools/input.js +36 -0
  109. package/dist/agent-core/tools/local/apply-patch.js +21 -17
  110. package/dist/agent-core/tools/local/exec.d.ts +4 -4
  111. package/dist/agent-core/tools/local/exec.js +234 -62
  112. package/dist/agent-core/tools/local/registry.d.ts +6 -0
  113. package/dist/agent-core/tools/local/registry.js +60 -9
  114. package/dist/agent-core/tools/mcp/catalog.d.ts +6 -2
  115. package/dist/agent-core/tools/mcp/catalog.js +4 -4
  116. package/dist/agent-core/tools/mcp/history.js +2 -2
  117. package/dist/agent-core/tools/mcp/tool-search.d.ts +3 -1
  118. package/dist/agent-core/tools/mcp/tool-search.js +2 -2
  119. package/dist/agent-core/tools/output-projection.d.ts +3 -1
  120. package/dist/agent-core/tools/output-projection.js +11 -2
  121. package/dist/agent-core/tools/runtime-context.d.ts +1 -0
  122. package/dist/agent-core/tools/runtime.d.ts +3 -1
  123. package/dist/agent-core/tools/runtime.js +22 -7
  124. package/dist/agent-core/tools/scheduler.d.ts +2 -0
  125. package/dist/agent-core/tools/scheduler.js +43 -6
  126. package/dist/index.d.ts +21 -0
  127. package/dist/sandbox/linux/bubblewrap-sandbox-executor.js +5 -2
  128. package/package.json +1 -1
@@ -0,0 +1,351 @@
1
+ import { AsyncLocalStorage } from 'node:async_hooks';
2
+ import { randomUUID } from 'node:crypto';
3
+ import { MarAgentError } from '../error.js';
4
+ import { captureCorePromptInput } from './prompt-input.js';
5
+ const physicalCommits = new WeakMap();
6
+ /** Internal writer evidence survives errors after commit, without settling the operation early. */
7
+ export function recordSessionInputCommit(entry, outcome) {
8
+ const previous = physicalCommits.get(entry);
9
+ const committed = {
10
+ ...previous,
11
+ ...outcome,
12
+ changed: !!previous?.changed || outcome.changed,
13
+ modelChanged: !!previous?.modelChanged || (outcome.modelChanged ?? outcome.changed)
14
+ };
15
+ physicalCommits.set(entry, committed);
16
+ entry.receipt = {
17
+ ...entry.receipt,
18
+ changed: committed.changed,
19
+ ...(committed.recordId === undefined ? {} : { recordId: committed.recordId }),
20
+ ...(committed.executionId === undefined ? {} : { executionId: committed.executionId })
21
+ };
22
+ }
23
+ /** One Session FIFO shared by native writes and the existing parent mailbox. No model loop. */
24
+ export class SessionInputCoordinator {
25
+ diagnose;
26
+ #pending = [];
27
+ #records = [];
28
+ #current = new AsyncLocalStorage();
29
+ #sequence = 0;
30
+ #closed = false;
31
+ #draining;
32
+ #settled = new Map();
33
+ constructor(diagnose = () => { }) {
34
+ this.diagnose = diagnose;
35
+ }
36
+ get hasPending() {
37
+ return this.#pending.length > 0;
38
+ }
39
+ get hasBoundaryPending() {
40
+ const head = this.#pending.find((entry) => entry.receipt.status !== 'cancelled' && !entry.source.signal.aborted);
41
+ return !!head && (head.request.kind !== 'submit' || head.request.input.delivery !== 'idle');
42
+ }
43
+ get executing() {
44
+ return this.#current.getStore()?.receipt.status === 'in-progress';
45
+ }
46
+ currentCompact() {
47
+ const entry = this.#current.getStore();
48
+ return entry?.request.kind === 'compact' && entry.receipt.status === 'in-progress'
49
+ ? Object.freeze({ ...entry.receipt })
50
+ : undefined;
51
+ }
52
+ inspect() {
53
+ return this.#records.map((entry) => Object.freeze({ ...entry.receipt }));
54
+ }
55
+ async performAppend(input, call, action, leaf) {
56
+ const entry = this.#record({ kind: 'append', input }, call, action, 'accepted');
57
+ await this.#execute(entry, call, leaf);
58
+ return Object.freeze({ ...entry.receipt });
59
+ }
60
+ /** SDK manual/automatic compaction shares the same active receipt as queued compaction. */
61
+ recordCompactCommit(outcome) {
62
+ const entry = this.#current.getStore();
63
+ if (!entry || entry.request.kind !== 'compact')
64
+ throw new MarAgentError('MAR_AGENT_SESSION_INPUT_INVALID', 'No active compaction owns this commit.');
65
+ recordSessionInputCommit(entry, outcome);
66
+ }
67
+ async performCompact(input, call, action) {
68
+ const existing = this.currentCompact() ? this.#current.getStore() : undefined;
69
+ const entry = existing ??
70
+ this.accept({ kind: 'compact', input }, call, (request, effective, next) => next(request, effective), 'queued');
71
+ if (!existing) {
72
+ this.#pending.splice(this.#pending.indexOf(entry), 1);
73
+ entry.receipt = {
74
+ ...entry.receipt,
75
+ status: 'in-progress',
76
+ ...(call.executionId ? { executionId: call.executionId } : {})
77
+ };
78
+ }
79
+ const commit = (outcome) => {
80
+ entry.receipt = {
81
+ ...entry.receipt,
82
+ changed: !!entry.receipt.changed || outcome.changed,
83
+ ...(outcome.executionId ? { executionId: outcome.executionId } : {})
84
+ };
85
+ };
86
+ try {
87
+ const outcome = await this.#current.run(entry, () => action(commit));
88
+ if (!existing)
89
+ this.#finish(entry, 'completed', {
90
+ ...outcome,
91
+ changed: !!entry.receipt.changed || outcome.changed
92
+ });
93
+ return outcome;
94
+ }
95
+ catch (error) {
96
+ if (!existing)
97
+ this.#finish(entry, call.signal.aborted ? 'cancelled' : 'failed', undefined, error instanceof MarAgentError ? error.code : 'MAR_AGENT_SESSION_INPUT_FAILED');
98
+ throw error;
99
+ }
100
+ finally {
101
+ if (!existing)
102
+ physicalCommits.delete(entry);
103
+ }
104
+ }
105
+ accept(request, source, action, status, parentMessage) {
106
+ const entry = this.#record(request, source, action, status, parentMessage);
107
+ this.#pending.push(entry);
108
+ return entry;
109
+ }
110
+ handled(input, call, value) {
111
+ const entry = this.#record({ kind: 'submit', input }, call, (request, effective, next) => next(request, effective), 'accepted');
112
+ this.#finish(entry, 'handled', { changed: false });
113
+ if (value !== undefined)
114
+ entry.receipt = { ...entry.receipt, handledValue: value };
115
+ return Object.freeze({ ...entry.receipt });
116
+ }
117
+ #record(request, source, action, status, parentMessage) {
118
+ if (this.#closed)
119
+ throw new MarAgentError('MAR_AGENT_SESSION_INPUT_CLOSED', 'Session input coordinator is closed.');
120
+ source.signal.throwIfAborted();
121
+ validateCoreSessionRequest(request);
122
+ let complete;
123
+ let started;
124
+ const entry = {
125
+ request: structuredClone(request),
126
+ source,
127
+ action,
128
+ receipt: {
129
+ operationId: source.operationId || randomUUID(),
130
+ sequence: ++this.#sequence,
131
+ kind: request.kind,
132
+ status,
133
+ ...(source.ownerInstanceId ? { ownerInstanceId: source.ownerInstanceId } : {}),
134
+ ...(source.extensionId ? { extensionId: source.extensionId } : {}),
135
+ ...(source.parentOperationId ? { parentOperationId: source.parentOperationId } : {})
136
+ },
137
+ ...(parentMessage === undefined ? {} : { parentMessage }),
138
+ started: new Promise((resolve) => {
139
+ started = resolve;
140
+ }),
141
+ start: () => started(),
142
+ terminal: new Promise((resolve) => {
143
+ complete = resolve;
144
+ }),
145
+ complete: () => {
146
+ source.signal.removeEventListener('abort', abort);
147
+ started();
148
+ complete();
149
+ }
150
+ };
151
+ const abort = () => {
152
+ if (entry.receipt.status === 'queued' || entry.receipt.status === 'accepted')
153
+ this.#finish(entry, 'cancelled');
154
+ };
155
+ source.signal.addEventListener('abort', abort, { once: true });
156
+ this.#records.push(entry);
157
+ this.#trim();
158
+ return entry;
159
+ }
160
+ drain(leaf, execution, limit = Number.POSITIVE_INFINITY) {
161
+ if (this.#draining)
162
+ return this.executing ? Promise.resolve(false) : this.#draining;
163
+ this.#draining = (async () => {
164
+ let changed = false;
165
+ let consumed = 0;
166
+ while (this.#pending.length && consumed++ < limit) {
167
+ const head = this.#pending[0];
168
+ // An idle prompt is a new Turn, not a mailbox delivery into the active Turn.
169
+ // Preserve the single FIFO: entries behind it cannot overtake it.
170
+ if (execution &&
171
+ head.request.kind === 'submit' &&
172
+ head.request.input.delivery === 'idle' &&
173
+ !head.source.signal.aborted &&
174
+ head.receipt.status !== 'cancelled')
175
+ break;
176
+ const entry = this.#pending.shift();
177
+ if (entry.receipt.status === 'cancelled' || entry.source.signal.aborted) {
178
+ this.#finish(entry, 'cancelled');
179
+ continue;
180
+ }
181
+ const { executionId: _oldExecution, turnId: _oldTurn, ...identity } = entry.source;
182
+ const call = Object.freeze({
183
+ ...identity,
184
+ signal: execution
185
+ ? AbortSignal.any([entry.source.signal, execution.signal])
186
+ : entry.source.signal,
187
+ ...(execution ? { executionId: execution.executionId, turnId: execution.turnId } : {})
188
+ });
189
+ const applied = await this.#execute(entry, call, leaf);
190
+ changed ||= applied;
191
+ }
192
+ return changed;
193
+ })().finally(() => {
194
+ this.#draining = undefined;
195
+ });
196
+ return this.#draining;
197
+ }
198
+ async #execute(entry, call, leaf) {
199
+ entry.receipt = {
200
+ ...entry.receipt,
201
+ status: 'in-progress',
202
+ ...(call.executionId ? { executionId: call.executionId } : {})
203
+ };
204
+ let changed = false;
205
+ let effects = 0;
206
+ let committed;
207
+ try {
208
+ const outcome = await this.#current.run(entry, () => entry.action(entry.request, call, async (request, effective) => {
209
+ validateCoreSessionRequest(request);
210
+ effective.signal.throwIfAborted();
211
+ const returned = await leaf(entry, request, effective);
212
+ const outcome = physicalCommits.get(entry) ?? returned;
213
+ effects++;
214
+ committed = { ...outcome, changed: !!committed?.changed || outcome.changed };
215
+ changed ||= outcome.modelChanged ?? outcome.changed;
216
+ return outcome;
217
+ }));
218
+ const physical = physicalCommits.get(entry);
219
+ if (physical) {
220
+ committed = physical;
221
+ changed ||= physical.modelChanged ?? physical.changed;
222
+ }
223
+ else if (!effects)
224
+ changed ||= outcome.modelChanged ?? outcome.changed;
225
+ this.#finish(entry, (committed ?? outcome).handled && !committed?.changed
226
+ ? 'handled'
227
+ : effects || physical
228
+ ? entry.request.kind === 'submit'
229
+ ? 'committed'
230
+ : entry.request.kind === 'append'
231
+ ? 'committed'
232
+ : 'completed'
233
+ : 'handled', committed ?? outcome);
234
+ }
235
+ catch (error) {
236
+ committed = physicalCommits.get(entry) ?? committed;
237
+ changed ||= (committed?.modelChanged ?? committed?.changed) || !!entry.receipt.changed;
238
+ this.#finish(entry, call.signal.aborted ? 'cancelled' : 'failed', committed, error instanceof MarAgentError ? error.code : 'MAR_AGENT_SESSION_INPUT_FAILED');
239
+ }
240
+ finally {
241
+ physicalCommits.delete(entry);
242
+ }
243
+ return changed;
244
+ }
245
+ async idle() {
246
+ await this.#draining;
247
+ await Promise.all(this.#records
248
+ .filter((entry) => entry.receipt.status === 'in-progress')
249
+ .map((entry) => entry.terminal));
250
+ }
251
+ async retire(instanceId) {
252
+ if (!instanceId)
253
+ this.#closed = true;
254
+ const owned = this.#records.filter((entry) => !instanceId || entry.source.ownerInstanceId === instanceId);
255
+ for (const entry of owned)
256
+ if (entry.receipt.status === 'queued' || entry.receipt.status === 'accepted')
257
+ this.#finish(entry, 'cancelled');
258
+ await Promise.all(owned.filter((entry) => entry.receipt.status === 'in-progress').map((entry) => entry.terminal));
259
+ }
260
+ startExecution(entry, executionId) {
261
+ entry.receipt = { ...entry.receipt, executionId };
262
+ entry.start();
263
+ }
264
+ settleExecution(executionId, status) {
265
+ this.#settled.set(executionId, status);
266
+ if (this.#settled.size > 200)
267
+ this.#settled.delete(this.#settled.keys().next().value);
268
+ for (const entry of this.#records)
269
+ if (entry.request.kind === 'submit' &&
270
+ entry.receipt.executionId === executionId &&
271
+ entry.receipt.status === 'committed')
272
+ entry.receipt = { ...entry.receipt, status };
273
+ this.#trim();
274
+ }
275
+ #finish(entry, status, outcome, errorCode) {
276
+ entry.receipt = {
277
+ ...entry.receipt,
278
+ status,
279
+ ...(outcome
280
+ ? {
281
+ changed: outcome.changed,
282
+ ...(outcome.recordId === undefined ? {} : { recordId: outcome.recordId }),
283
+ ...(outcome.executionId ? { executionId: outcome.executionId } : {})
284
+ }
285
+ : {}),
286
+ ...(errorCode ? { errorCode } : {})
287
+ };
288
+ if (status === 'committed' && entry.request.kind === 'submit' && entry.receipt.executionId) {
289
+ const settled = this.#settled.get(entry.receipt.executionId);
290
+ if (settled)
291
+ entry.receipt = { ...entry.receipt, status: settled };
292
+ }
293
+ entry.complete();
294
+ if (status === 'failed')
295
+ this.diagnose(Object.freeze({ ...entry.receipt }));
296
+ this.#trim();
297
+ }
298
+ #trim() {
299
+ while (this.#records.length > 200) {
300
+ const index = this.#records.findIndex((entry) => !['queued', 'accepted', 'in-progress'].includes(entry.receipt.status) &&
301
+ !(entry.receipt.status === 'committed' && entry.request.kind === 'submit'));
302
+ if (index === -1)
303
+ break;
304
+ this.#records.splice(index, 1);
305
+ }
306
+ }
307
+ }
308
+ export function validateCoreSessionRequest(request) {
309
+ if (request?.kind === 'submit')
310
+ captureCorePromptInput(request.input);
311
+ if (!request ||
312
+ !request.input ||
313
+ !['append', 'submit', 'compact'].includes(request.kind) ||
314
+ (request.kind === 'append' &&
315
+ (typeof request.input.content !== 'string' ||
316
+ 'agentId' in request.input ||
317
+ (request.input.delivery !== undefined &&
318
+ request.input.delivery !== 'boundary' &&
319
+ request.input.delivery !== 'immediate') ||
320
+ (request.input.visibility !== undefined &&
321
+ request.input.visibility !== 'model' &&
322
+ request.input.visibility !== 'transcript') ||
323
+ (request.input.textBlocks !== undefined &&
324
+ (!Array.isArray(request.input.textBlocks) ||
325
+ !Array.from(request.input.textBlocks).every((block) => block && typeof block.text === 'string') ||
326
+ request.input.textBlocks.map((block) => block.text).join('') !==
327
+ request.input.content)) ||
328
+ (request.input.attribution !== undefined &&
329
+ typeof request.input.attribution !== 'string'))) ||
330
+ (request.kind === 'submit' &&
331
+ (typeof request.input.text !== 'string' ||
332
+ (!request.input.text.trim() && request.input.modelText === undefined) ||
333
+ (request.input.delivery !== undefined &&
334
+ request.input.delivery !== 'boundary' &&
335
+ request.input.delivery !== 'idle') ||
336
+ (request.input.waitFor !== undefined &&
337
+ request.input.waitFor !== 'admission' &&
338
+ request.input.waitFor !== 'start' &&
339
+ request.input.waitFor !== 'commit') ||
340
+ (request.input.modelText !== undefined && typeof request.input.modelText !== 'string') ||
341
+ (request.input.context !== undefined &&
342
+ (!Array.isArray(request.input.context) ||
343
+ !request.input.context.every((text) => typeof text === 'string'))) ||
344
+ (request.input.provenance !== undefined && typeof request.input.provenance !== 'string') ||
345
+ (request.input.modelAttribution !== undefined &&
346
+ request.input.modelAttribution !== 'none'))) ||
347
+ (request.kind === 'compact' &&
348
+ request.input.focus !== undefined &&
349
+ typeof request.input.focus !== 'string'))
350
+ throw new MarAgentError('MAR_AGENT_SESSION_INPUT_INVALID', 'Session input is invalid.');
351
+ }
@@ -0,0 +1,41 @@
1
+ import type { ModelMessage } from '../model/contracts.js';
2
+ import type { CoreModelMessage } from './model-request.js';
3
+ export interface CoreSessionMessagesInput {
4
+ readonly view?: 'model' | 'conversation' | 'request';
5
+ readonly agentId?: string;
6
+ readonly includeImages?: boolean;
7
+ readonly cursor?: string;
8
+ readonly limit?: number;
9
+ }
10
+ /** Read-only persisted context, not additional writable model-request fields. */
11
+ export type CoreSessionMessage = Extract<CoreModelMessage, {
12
+ readonly role: 'opaque';
13
+ }> | (Exclude<CoreModelMessage, {
14
+ readonly role: 'opaque';
15
+ }> & {
16
+ readonly contextKind?: 'environment';
17
+ readonly inputMode?: ModelMessage['inputMode'];
18
+ readonly calls?: ModelMessage['calls'];
19
+ readonly observations?: ModelMessage['observations'];
20
+ readonly toolSearchTools?: ModelMessage['toolSearchTools'];
21
+ readonly toolOutcome?: {
22
+ readonly isError: boolean;
23
+ readonly result?: unknown;
24
+ };
25
+ readonly modelIsError?: boolean;
26
+ });
27
+ export interface CoreSessionMessages {
28
+ readonly messages: readonly CoreSessionMessage[];
29
+ readonly nextCursor?: string;
30
+ }
31
+ export declare function normalizeSessionMessagesInput(input: CoreSessionMessagesInput): Readonly<{
32
+ view: "model" | "request" | "conversation";
33
+ agentId: string | undefined;
34
+ includeImages: boolean;
35
+ cursor: number;
36
+ limit: number;
37
+ }>;
38
+ export declare function sessionMessagesPage(messages: readonly ModelMessage[], input: ReturnType<typeof normalizeSessionMessagesInput>, outcomes?: WeakMap<ModelMessage, {
39
+ readonly isError: boolean;
40
+ readonly result?: unknown;
41
+ }>): CoreSessionMessages;
@@ -0,0 +1,76 @@
1
+ import { MarAgentError } from '../error.js';
2
+ import { ExtensionRequestBridge } from './model-request.js';
3
+ export function normalizeSessionMessagesInput(input) {
4
+ if (!input ||
5
+ typeof input !== 'object' ||
6
+ Array.isArray(input) ||
7
+ (input.view !== undefined &&
8
+ input.view !== 'model' &&
9
+ input.view !== 'conversation' &&
10
+ input.view !== 'request') ||
11
+ (input.agentId !== undefined && (typeof input.agentId !== 'string' || !input.agentId)) ||
12
+ (input.includeImages !== undefined && typeof input.includeImages !== 'boolean') ||
13
+ (input.limit !== undefined && typeof input.limit !== 'number') ||
14
+ (input.cursor !== undefined && typeof input.cursor !== 'string'))
15
+ throw invalidInput();
16
+ const cursor = input.cursor === undefined ? 0 : Number(input.cursor);
17
+ const limit = input.limit ?? 100;
18
+ if (!Number.isSafeInteger(cursor) || cursor < 0 || !Number.isSafeInteger(limit) || limit <= 0)
19
+ throw invalidInput();
20
+ return Object.freeze({
21
+ view: input.view ?? 'model',
22
+ agentId: input.agentId,
23
+ includeImages: input.includeImages ?? false,
24
+ cursor,
25
+ limit
26
+ });
27
+ }
28
+ export function sessionMessagesPage(messages, input, outcomes) {
29
+ const selected = input.view === 'conversation'
30
+ ? messages.filter((message) => message.role !== 'provider' &&
31
+ message.contextKind !== 'environment' &&
32
+ message.contextKind !== 'private')
33
+ : messages;
34
+ // A private non-Provider record receives the same opaque treatment as Provider context.
35
+ const neutral = selected.map((message) => message.contextKind === 'private' ? { role: 'provider', content: '' } : message);
36
+ const view = new ExtensionRequestBridge('', { system: '', messages: neutral, tools: [] }).view
37
+ .messages;
38
+ const enriched = view.map((message, index) => {
39
+ if (message.role === 'opaque')
40
+ return message;
41
+ const original = selected[index];
42
+ const { images, ...text } = message;
43
+ return {
44
+ ...text,
45
+ ...(input.includeImages && images !== undefined ? { images } : {}),
46
+ ...(original.contextKind === 'environment' ? { contextKind: 'environment' } : {}),
47
+ ...(original.inputMode !== undefined ? { inputMode: original.inputMode } : {}),
48
+ ...(original.isError === undefined ? {} : { modelIsError: original.isError }),
49
+ ...(outcomes?.has(original) ? { toolOutcome: structuredClone(outcomes.get(original)) } : {}),
50
+ ...(original.calls !== undefined ? { calls: structuredClone(original.calls) } : {}),
51
+ ...(original.observations !== undefined
52
+ ? { observations: structuredClone(original.observations) }
53
+ : {}),
54
+ ...(original.toolSearchTools !== undefined
55
+ ? { toolSearchTools: structuredClone(original.toolSearchTools) }
56
+ : {})
57
+ };
58
+ });
59
+ return freeze({
60
+ messages: enriched.slice(input.cursor, input.cursor + input.limit),
61
+ ...(input.cursor + input.limit < enriched.length
62
+ ? { nextCursor: String(input.cursor + input.limit) }
63
+ : {})
64
+ });
65
+ }
66
+ function invalidInput() {
67
+ return new MarAgentError('MAR_AGENT_SESSION_INPUT_INVALID', 'Message view, target, media selection, cursor or limit is invalid.');
68
+ }
69
+ function freeze(value) {
70
+ if (value && typeof value === 'object' && !Object.isFrozen(value)) {
71
+ for (const child of Object.values(value))
72
+ freeze(child);
73
+ Object.freeze(value);
74
+ }
75
+ return value;
76
+ }
@@ -0,0 +1,68 @@
1
+ import type { ToolCall, ToolExecutionResult } from '../tools/contracts.js';
2
+ import type { CoreDomainFacts, CoreDomainOperations, CoreExtensionDiagnostic, CorePromptSection, CoreRuntimeExtension, CoreSessionExtensionContext, CoreCapabilitySnapshot } from './contracts.js';
3
+ import { ExtensionHooks } from './hooks.js';
4
+ import { type CorePromptComposition } from './prompt-composition.js';
5
+ import type { CoreModelEvent } from './model-stream.js';
6
+ import type { ModelTextBlock } from '../model/contracts.js';
7
+ import { ExtensionMcp } from './mcp.js';
8
+ import { type CoreAgentsBackend } from './agents.js';
9
+ import type { SubagentController } from '../subagent/contracts.js';
10
+ import type { CoreHostExtensionPorts } from '../host/contracts.js';
11
+ import { ExtensionOperations, type CoreOperationContext } from './operation.js';
12
+ import { ExtensionResourceScope } from './resources.js';
13
+ import { ExtensionServices } from './services.js';
14
+ import { ExtensionTools, type CoreToolBinding, type CoreToolRef, type CoreToolInvocation, type CoreToolCheck } from './tools.js';
15
+ import type { CoreModelsBackend } from './models.js';
16
+ import { type CoreCheckpointBackend } from './data.js';
17
+ import type { CoreSessionBackend } from './session-input.js';
18
+ /** Session-local definitions and facades; SDK supplies real Host sources for each operation. */
19
+ export declare class ExtensionSession {
20
+ #private;
21
+ readonly id: string;
22
+ readonly epoch: number;
23
+ readonly operations: ExtensionOperations;
24
+ readonly capabilities: CoreCapabilitySnapshot;
25
+ readonly diagnose: (diagnostic: CoreExtensionDiagnostic) => void;
26
+ readonly baseTools: (context?: CoreOperationContext) => readonly CoreToolBinding[];
27
+ readonly models?: CoreModelsBackend | undefined;
28
+ readonly checkpoint?: CoreCheckpointBackend | undefined;
29
+ readonly sessionBackend?: CoreSessionBackend | undefined;
30
+ readonly hostPorts?: CoreHostExtensionPorts | undefined;
31
+ readonly agentsBackend?: CoreAgentsBackend | undefined;
32
+ readonly allowTool: (name: string, definition?: CoreToolBinding['definition']) => boolean;
33
+ readonly scheduleTool: <T>(definition: CoreToolBinding['definition'], run: () => Promise<T>) => Promise<T>;
34
+ isEnding: boolean;
35
+ readonly mcp: ExtensionMcp;
36
+ readonly tools: ExtensionTools;
37
+ readonly hooks: ExtensionHooks<CoreDomainOperations, CoreDomainFacts>;
38
+ readonly services: ExtensionServices;
39
+ readonly scopes: ExtensionResourceScope[];
40
+ /** The SDK calls this after admission, outside the composition manager's serial lane. */
41
+ ready(call: CoreOperationContext): Promise<void>;
42
+ assertLive(): void;
43
+ retire(): void;
44
+ get hasReferences(): boolean;
45
+ pin(): () => void;
46
+ private get toolFrame();
47
+ withTools<T>(bindings: ReadonlyMap<string, CoreToolBinding>, schedule: <Value>(definition: CoreToolBinding['definition'], run: () => Promise<Value>) => Promise<Value>, run: () => T): T;
48
+ constructor(id: string, epoch: number, agentServices: ExtensionServices, operations: ExtensionOperations, capabilities: CoreCapabilitySnapshot, diagnose: (diagnostic: CoreExtensionDiagnostic) => void, baseTools?: (context?: CoreOperationContext) => readonly CoreToolBinding[], models?: CoreModelsBackend | undefined, checkpoint?: CoreCheckpointBackend | undefined, sessionBackend?: CoreSessionBackend | undefined, hostPorts?: CoreHostExtensionPorts | undefined, agentsBackend?: CoreAgentsBackend | undefined, allowTool?: (name: string, definition?: CoreToolBinding['definition']) => boolean, scheduleTool?: <T>(definition: CoreToolBinding['definition'], run: () => Promise<T>) => Promise<T>);
49
+ context(extension: CoreRuntimeExtension, scope: ExtensionResourceScope): CoreSessionExtensionContext;
50
+ toolRef(binding: CoreToolBinding): CoreToolRef;
51
+ capture(context?: CoreOperationContext, includeStaged?: boolean, base?: readonly CoreToolBinding[]): ReadonlyMap<string, CoreToolBinding>;
52
+ sections(): readonly CorePromptSection[];
53
+ bindAgents(controller: SubagentController): SubagentController;
54
+ modelEvent(event: CoreModelEvent, call: CoreOperationContext): Promise<CoreModelEvent | undefined>;
55
+ composeSections(input: CorePromptComposition, call: CoreOperationContext): Promise<CorePromptComposition>;
56
+ compose(system: string | CorePromptComposition, call: CoreOperationContext): Promise<string>;
57
+ composeModelSystem(system: string | CorePromptComposition, call: CoreOperationContext): Promise<{
58
+ text: string;
59
+ blocks?: readonly ModelTextBlock[];
60
+ }>;
61
+ invoke(call: ToolCall, context: CoreOperationContext, snapshot?: ReadonlyMap<string, CoreToolBinding>): Promise<ToolExecutionResult>;
62
+ private assertToolAvailable;
63
+ private toolAttempt;
64
+ check(call: CoreToolInvocation, context: CoreOperationContext): CoreToolCheck;
65
+ invocationSnapshot(call: CoreToolInvocation, context: CoreOperationContext): ReadonlyMap<string, CoreToolBinding>;
66
+ activate(): void;
67
+ dispose(): Promise<void>;
68
+ }