@myagentroam/agent 0.9.159 → 0.9.161

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 (130) 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-limits.d.ts +0 -1
  106. package/dist/agent-core/tools/execution-limits.js +0 -1
  107. package/dist/agent-core/tools/execution.d.ts +11 -2
  108. package/dist/agent-core/tools/execution.js +58 -21
  109. package/dist/agent-core/tools/input.d.ts +2 -0
  110. package/dist/agent-core/tools/input.js +36 -0
  111. package/dist/agent-core/tools/local/apply-patch.js +21 -17
  112. package/dist/agent-core/tools/local/exec.d.ts +4 -4
  113. package/dist/agent-core/tools/local/exec.js +242 -63
  114. package/dist/agent-core/tools/local/registry.d.ts +6 -0
  115. package/dist/agent-core/tools/local/registry.js +60 -9
  116. package/dist/agent-core/tools/mcp/catalog.d.ts +6 -2
  117. package/dist/agent-core/tools/mcp/catalog.js +4 -4
  118. package/dist/agent-core/tools/mcp/history.js +2 -2
  119. package/dist/agent-core/tools/mcp/tool-search.d.ts +3 -1
  120. package/dist/agent-core/tools/mcp/tool-search.js +2 -2
  121. package/dist/agent-core/tools/output-projection.d.ts +3 -1
  122. package/dist/agent-core/tools/output-projection.js +11 -2
  123. package/dist/agent-core/tools/runtime-context.d.ts +1 -0
  124. package/dist/agent-core/tools/runtime.d.ts +3 -1
  125. package/dist/agent-core/tools/runtime.js +22 -7
  126. package/dist/agent-core/tools/scheduler.d.ts +2 -0
  127. package/dist/agent-core/tools/scheduler.js +43 -6
  128. package/dist/index.d.ts +21 -0
  129. package/dist/sandbox/linux/bubblewrap-sandbox-executor.js +5 -2
  130. package/package.json +1 -1
@@ -0,0 +1,27 @@
1
+ import type { CoreOperationContext } from './operation.js';
2
+ import type { CoreDomainFacts, CoreDomainOperations } from './contracts.js';
3
+ import type { ExtensionHooks } from './hooks.js';
4
+ export interface CoreEnvironmentKey {
5
+ readonly key: string;
6
+ readonly signal?: AbortSignal;
7
+ }
8
+ export interface CoreEnvironmentSet extends CoreEnvironmentKey {
9
+ readonly value?: string;
10
+ }
11
+ export interface CoreEnvironmentChange {
12
+ readonly changed: boolean;
13
+ }
14
+ export interface CoreEnvironmentApi {
15
+ get(input: CoreEnvironmentKey): Promise<string | undefined>;
16
+ set(input: CoreEnvironmentSet): Promise<CoreEnvironmentChange>;
17
+ }
18
+ export interface CoreEnvironmentBackend {
19
+ get(input: CoreEnvironmentKey, call: CoreOperationContext): Promise<string | undefined>;
20
+ set(input: CoreEnvironmentSet, call: CoreOperationContext): Promise<CoreEnvironmentChange>;
21
+ }
22
+ export interface CoreEnvironmentCompletion {
23
+ readonly operation: 'get' | 'set';
24
+ readonly changed?: boolean;
25
+ }
26
+ export declare function validateEnvironmentInput(input: CoreEnvironmentKey): void;
27
+ export declare function bindCoreEnvironment(backend: CoreEnvironmentBackend, run: <Value>(operation: (call: CoreOperationContext) => Promise<Value>, signal?: AbortSignal) => Promise<Value>, hooks: ExtensionHooks<CoreDomainOperations, CoreDomainFacts>): CoreEnvironmentApi;
@@ -0,0 +1,52 @@
1
+ import { MarAgentError } from '../error.js';
2
+ export function validateEnvironmentInput(input) {
3
+ if (!input ||
4
+ typeof input.key !== 'string' ||
5
+ !input.key ||
6
+ input.key.includes('=') ||
7
+ input.key.includes('\0') ||
8
+ ('value' in input &&
9
+ input.value !== undefined &&
10
+ (typeof input.value !== 'string' || input.value.includes('\0'))))
11
+ throw new MarAgentError('MAR_AGENT_ENVIRONMENT_INPUT_INVALID', 'Environment variable input is invalid.');
12
+ }
13
+ export function bindCoreEnvironment(backend, run, hooks) {
14
+ return {
15
+ get: async (input) => {
16
+ input = { ...input };
17
+ validateEnvironmentInput(input);
18
+ return run((call) => hooks.invoke('environment.get', input, call, async (input, effective) => {
19
+ validateEnvironmentInput(input);
20
+ if (typeof backend.get !== 'function')
21
+ throw unavailable('get');
22
+ const value = await backend.get({ ...input }, effective);
23
+ if (value !== undefined && typeof value !== 'string')
24
+ throw invalidResult();
25
+ await hooks.emit('environment.completed', { operation: 'get' }, effective);
26
+ return value;
27
+ }), input.signal);
28
+ },
29
+ set: async (input) => {
30
+ input = { ...input };
31
+ validateEnvironmentInput(input);
32
+ return run((call) => hooks.invoke('environment.set', input, call, async (input, effective) => {
33
+ validateEnvironmentInput(input);
34
+ if (typeof backend.set !== 'function')
35
+ throw unavailable('set');
36
+ const output = await backend.set({ ...input }, effective);
37
+ const changed = output?.changed;
38
+ if (typeof changed !== 'boolean')
39
+ throw invalidResult();
40
+ const result = { changed };
41
+ await hooks.emit('environment.completed', { operation: 'set', ...result }, effective);
42
+ return result;
43
+ }), input.signal);
44
+ }
45
+ };
46
+ }
47
+ function unavailable(operation) {
48
+ return new MarAgentError('MAR_AGENT_HOST_PORT_UNAVAILABLE', 'Native environment port is unavailable.', { details: { operation } });
49
+ }
50
+ function invalidResult() {
51
+ return new MarAgentError('MAR_AGENT_ENVIRONMENT_OUTPUT_INVALID', 'Native environment result is invalid.');
52
+ }
@@ -0,0 +1,64 @@
1
+ import type { CoreOperationContext } from './operation.js';
2
+ import type { CoreDomainFacts, CoreDomainOperations } from './contracts.js';
3
+ import type { ExtensionHooks } from './hooks.js';
4
+ export type CoreFileType = 'file' | 'directory' | 'symlink' | 'other';
5
+ export interface CoreFilePath {
6
+ readonly path: string;
7
+ }
8
+ export interface CoreFileInfo {
9
+ readonly path: string;
10
+ readonly type: CoreFileType;
11
+ readonly size: number;
12
+ readonly modifiedAtMs: number;
13
+ readonly createdAtMs: number;
14
+ }
15
+ export interface CoreFileEntry {
16
+ readonly name: string;
17
+ readonly type: CoreFileType;
18
+ }
19
+ export interface CoreFileWrite extends CoreFilePath {
20
+ readonly bytes: Uint8Array;
21
+ readonly createParents?: boolean;
22
+ }
23
+ export interface CoreFileRemove extends CoreFilePath {
24
+ readonly recursive?: boolean;
25
+ readonly force?: boolean;
26
+ }
27
+ export interface CoreFileTransfer {
28
+ readonly from: string;
29
+ readonly to: string;
30
+ }
31
+ export interface CoreFilesApi {
32
+ read(input: CoreFilePath): Promise<Uint8Array>;
33
+ write(input: CoreFileWrite): Promise<{
34
+ readonly bytesWritten: number;
35
+ }>;
36
+ stat(input: CoreFilePath): Promise<CoreFileInfo>;
37
+ list(input: CoreFilePath): Promise<readonly CoreFileEntry[]>;
38
+ mkdir(input: CoreFilePath & {
39
+ readonly recursive?: boolean;
40
+ }): Promise<void>;
41
+ remove(input: CoreFileRemove): Promise<void>;
42
+ move(input: CoreFileTransfer): Promise<void>;
43
+ copy(input: CoreFileTransfer): Promise<void>;
44
+ }
45
+ type Input<Name extends keyof CoreFilesApi> = Parameters<CoreFilesApi[Name]>[0];
46
+ type Output<Name extends keyof CoreFilesApi> = Awaited<ReturnType<CoreFilesApi[Name]>>;
47
+ export type CoreFilesBackend = {
48
+ [Name in keyof CoreFilesApi]: (input: Input<Name>, call: CoreOperationContext) => Promise<Output<Name>>;
49
+ };
50
+ export type CoreFileOperations = {
51
+ [Name in keyof CoreFilesApi as `files.${Name}`]: {
52
+ input: Input<Name>;
53
+ output: Output<Name>;
54
+ };
55
+ };
56
+ export type CoreFileCompletion = {
57
+ [Name in keyof CoreFilesApi]: {
58
+ readonly operation: Name;
59
+ readonly input: Input<Name>;
60
+ readonly output: Output<Name>;
61
+ };
62
+ }[keyof CoreFilesApi];
63
+ export declare function bindCoreFiles(backend: CoreFilesBackend, run: <Value>(operation: (call: CoreOperationContext) => Promise<Value>) => Promise<Value>, hooks: ExtensionHooks<CoreDomainOperations, CoreDomainFacts>): CoreFilesApi;
64
+ export {};
@@ -0,0 +1,26 @@
1
+ import { MarAgentError } from '../error.js';
2
+ export function bindCoreFiles(backend, run, hooks) {
3
+ const invoke = (name, input) => run((call) => {
4
+ const handler = backend[name];
5
+ if (typeof handler !== 'function')
6
+ throw new MarAgentError('MAR_AGENT_HOST_PORT_UNAVAILABLE', 'Native file port is unavailable.', { details: { operation: name } });
7
+ return hooks.invoke(`files.${name}`, input, call, async (input, effective) => {
8
+ const factInput = input && 'bytes' in input && input.bytes instanceof Uint8Array
9
+ ? { ...input, bytes: new Uint8Array(input.bytes) }
10
+ : { ...input };
11
+ const output = await handler.call(backend, input, effective);
12
+ await hooks.emit('files.completed', { operation: name, input: factInput, output }, effective);
13
+ return output;
14
+ });
15
+ });
16
+ return {
17
+ read: (input) => invoke('read', input),
18
+ write: (input) => invoke('write', input),
19
+ stat: (input) => invoke('stat', input),
20
+ list: (input) => invoke('list', input),
21
+ mkdir: (input) => invoke('mkdir', input),
22
+ remove: (input) => invoke('remove', input),
23
+ move: (input) => invoke('move', input),
24
+ copy: (input) => invoke('copy', input)
25
+ };
26
+ }
@@ -0,0 +1,32 @@
1
+ import type { CoreCallbackRunner, CoreOperationContext } from './operation.js';
2
+ import type { CoreResourceRegistration } from './resources.js';
3
+ import { ExtensionResourceScope } from './resources.js';
4
+ export interface CoreHookOptions {
5
+ readonly reentry?: 'skip-active' | 'allow';
6
+ }
7
+ export interface CoreHookDiagnostic {
8
+ readonly code: 'MAR_AGENT_EXTENSION_OBSERVER_FAILED';
9
+ readonly operationId: string;
10
+ }
11
+ export type CoreInterceptor<Input, Output> = (input: Input, call: CoreOperationContext, next: (input: Input) => Promise<Output>) => Output | Promise<Output>;
12
+ /** Typed domain chains with per-dispatch snapshots and async-ancestor reentry tracking. */
13
+ export declare class ExtensionHooks<Operations extends {
14
+ [Key in keyof Operations]: {
15
+ input: unknown;
16
+ output: unknown;
17
+ };
18
+ }, Facts extends object> {
19
+ #private;
20
+ readonly diagnose: (diagnostic: CoreHookDiagnostic) => void;
21
+ readonly callback: CoreCallbackRunner;
22
+ constructor(diagnose?: (diagnostic: CoreHookDiagnostic) => void, callback?: CoreCallbackRunner);
23
+ /** Internal physical callback ingress; unrelated dispatch must not inherit reentry suppression. */
24
+ independent<Value>(run: () => Value): Value;
25
+ /** Avoid materializing public views when no active interceptor can consume them. */
26
+ hasInterceptors(key: keyof Operations): boolean;
27
+ intercept<Key extends keyof Operations>(owner: ExtensionResourceScope, key: Key, handler: CoreInterceptor<Operations[Key]['input'], Operations[Key]['output']>, options?: CoreHookOptions): CoreResourceRegistration;
28
+ observe<Key extends keyof Facts>(owner: ExtensionResourceScope, key: Key, handler: (fact: Facts[Key], call: CoreOperationContext) => void | Promise<void>, options?: CoreHookOptions): CoreResourceRegistration;
29
+ invoke<Key extends keyof Operations>(key: Key, input: Operations[Key]['input'], call: CoreOperationContext, leaf: (input: Operations[Key]['input'], call: CoreOperationContext) => Promise<Operations[Key]['output']>): Promise<Operations[Key]['output']>;
30
+ hasObservers<Key extends keyof Facts>(key: Key): boolean;
31
+ emit<Key extends keyof Facts>(key: Key, fact: Facts[Key], call: CoreOperationContext, settled?: boolean): Promise<void>;
32
+ }
@@ -0,0 +1,135 @@
1
+ import { AsyncLocalStorage } from 'node:async_hooks';
2
+ /** Typed domain chains with per-dispatch snapshots and async-ancestor reentry tracking. */
3
+ export class ExtensionHooks {
4
+ diagnose;
5
+ callback;
6
+ #interceptors = new Map();
7
+ #observers = new Map();
8
+ #active = new AsyncLocalStorage();
9
+ constructor(diagnose = () => { }, callback = async (call, run) => run(call)) {
10
+ this.diagnose = diagnose;
11
+ this.callback = callback;
12
+ }
13
+ /** Internal physical callback ingress; unrelated dispatch must not inherit reentry suppression. */
14
+ independent(run) {
15
+ return this.#active.run([], run);
16
+ }
17
+ /** Avoid materializing public views when no active interceptor can consume them. */
18
+ hasInterceptors(key) {
19
+ return this.#interceptors.get(key)?.some((entry) => entry.owner.state === 'ACTIVE') ?? false;
20
+ }
21
+ intercept(owner, key, handler, options = {}) {
22
+ const entry = {
23
+ owner,
24
+ handler: handler,
25
+ reentry: options.reentry ?? 'skip-active'
26
+ };
27
+ const entries = this.#interceptors.get(key) ?? [];
28
+ const registration = owner.effect(() => () => {
29
+ const index = entries.indexOf(entry);
30
+ if (index !== -1)
31
+ entries.splice(index, 1);
32
+ });
33
+ entries.push(entry);
34
+ this.#interceptors.set(key, entries);
35
+ return registration;
36
+ }
37
+ observe(owner, key, handler, options = {}) {
38
+ const entry = {
39
+ owner,
40
+ handler: handler,
41
+ reentry: options.reentry ?? 'skip-active'
42
+ };
43
+ const entries = this.#observers.get(key) ?? [];
44
+ const registration = owner.effect(() => () => {
45
+ const index = entries.indexOf(entry);
46
+ if (index !== -1)
47
+ entries.splice(index, 1);
48
+ });
49
+ entries.push(entry);
50
+ this.#observers.set(key, entries);
51
+ return registration;
52
+ }
53
+ async invoke(key, input, call, leaf) {
54
+ call.signal.throwIfAborted();
55
+ const snapshot = [...(this.#interceptors.get(key) ?? [])].filter((entry) => entry.owner.state === 'ACTIVE');
56
+ const dispatch = async (index, value, signal) => {
57
+ signal.throwIfAborted();
58
+ const entry = snapshot[index];
59
+ if (!entry)
60
+ return leaf(value, Object.freeze({ ...call, signal }));
61
+ const ancestors = this.#active.getStore() ?? [];
62
+ if (entry.reentry === 'skip-active' &&
63
+ ancestors.some((frame) => frame.active && frame.entry === entry))
64
+ return dispatch(index + 1, value, signal);
65
+ return entry.owner.run(async (signal) => {
66
+ const frame = { entry, active: true };
67
+ return this.#active.run([...ancestors, frame], async () => {
68
+ const controller = new AbortController();
69
+ const effectiveSignal = AbortSignal.any([signal, controller.signal]);
70
+ const pending = new Set();
71
+ try {
72
+ return await this.callback(Object.freeze({ ...call, signal: effectiveSignal }), (effective) => entry.handler(value, effective, (nextValue) => {
73
+ const result = dispatch(index + 1, nextValue, effective.signal);
74
+ const settled = result.then(() => undefined, () => undefined);
75
+ pending.add(settled);
76
+ void settled.then(() => pending.delete(settled));
77
+ return result;
78
+ }));
79
+ }
80
+ catch (error) {
81
+ controller.abort();
82
+ throw error;
83
+ }
84
+ finally {
85
+ while (pending.size)
86
+ await Promise.all([...pending]);
87
+ frame.active = false;
88
+ }
89
+ });
90
+ }, signal);
91
+ };
92
+ return (await dispatch(0, input, call.signal));
93
+ }
94
+ hasObservers(key) {
95
+ return (this.#observers.get(key) ?? []).some((entry) => entry.owner.state === 'ACTIVE');
96
+ }
97
+ async emit(key, fact, call, settled = false) {
98
+ const snapshot = [...(this.#observers.get(key) ?? [])].filter((entry) => entry.owner.state === 'ACTIVE');
99
+ for (const entry of snapshot) {
100
+ if (!settled)
101
+ call.signal.throwIfAborted();
102
+ const ancestors = this.#active.getStore() ?? [];
103
+ if (entry.reentry === 'skip-active' &&
104
+ ancestors.some((frame) => frame.active && frame.entry === entry))
105
+ continue;
106
+ try {
107
+ // Each observer gets its own copy, never writable authoritative state or another observer's view.
108
+ await entry.owner.run(async (signal) => {
109
+ const frame = { entry, active: true };
110
+ await this.#active.run([...ancestors, frame], async () => {
111
+ try {
112
+ await this.callback(Object.freeze({ ...call, signal: AbortSignal.any([signal, call.signal]) }), (effective) => entry.handler(structuredClone(fact), effective), settled);
113
+ }
114
+ finally {
115
+ frame.active = false;
116
+ }
117
+ });
118
+ }, settled ? undefined : call.signal);
119
+ }
120
+ catch {
121
+ if (!settled)
122
+ call.signal.throwIfAborted();
123
+ try {
124
+ this.diagnose({
125
+ code: 'MAR_AGENT_EXTENSION_OBSERVER_FAILED',
126
+ operationId: call.operationId
127
+ });
128
+ }
129
+ catch {
130
+ /* A diagnostic sink must not change an already completed fact. */
131
+ }
132
+ }
133
+ }
134
+ }
135
+ }
@@ -0,0 +1,39 @@
1
+ import type { CoreCapabilitySnapshot, CoreExtensionDiagnostic, CoreExtensionSource, CoreRuntimeExtension } from './contracts.js';
2
+ import { ExtensionOperations, type CoreOperationContext } from './operation.js';
3
+ import { ExtensionSession } from './session.js';
4
+ import type { CoreToolBinding } from './tools.js';
5
+ import type { CoreModelsBackend } from './models.js';
6
+ import type { CoreCheckpointBackend } from './data.js';
7
+ import type { CoreSessionBackend } from './session-input.js';
8
+ import type { CoreHostExtensionPorts } from '../host/contracts.js';
9
+ import { type CoreAgentsBackend } from './agents.js';
10
+ export interface ExtensionManagerOptions {
11
+ readonly hostPorts?: CoreHostExtensionPorts;
12
+ readonly extensions: readonly CoreRuntimeExtension[] | CoreExtensionSource;
13
+ readonly capabilities: readonly string[];
14
+ readonly busyExcept: (sessionId: string) => boolean;
15
+ readonly baseTools?: (sessionId: string, context?: Pick<CoreOperationContext, 'executionId'>) => readonly CoreToolBinding[];
16
+ readonly models?: CoreModelsBackend;
17
+ readonly checkpoint?: CoreCheckpointBackend;
18
+ readonly sessionBackend?: (sessionId: string) => CoreSessionBackend | undefined;
19
+ readonly agentsBackend?: (sessionId: string) => CoreAgentsBackend | undefined;
20
+ readonly allowTool?: (sessionId: string, name: string, definition?: CoreToolBinding['definition']) => boolean;
21
+ readonly scheduleTool?: (sessionId: string) => ExtensionSession['scheduleTool'];
22
+ }
23
+ /** Agent admission coordinates a single composition generation, never parallel replacement loops. */
24
+ export declare class ExtensionManager {
25
+ #private;
26
+ readonly options: ExtensionManagerOptions;
27
+ readonly operations: ExtensionOperations;
28
+ readonly capabilities: CoreCapabilitySnapshot;
29
+ constructor(options: ExtensionManagerOptions);
30
+ diagnostics(): readonly CoreExtensionDiagnostic[];
31
+ session(id: string): ExtensionSession | undefined;
32
+ get revision(): string | undefined;
33
+ hasReferences(): boolean;
34
+ prepare(sessionId: string, signal: AbortSignal, baseTools?: readonly CoreToolBinding[], refresh?: boolean): Promise<ExtensionSession>;
35
+ clearSession(id: string): Promise<void>;
36
+ endSession(id: string, reason: 'clear' | 'other', resumable?: boolean): Promise<void>;
37
+ retireSession(id: string): void;
38
+ dispose(): Promise<void>;
39
+ }