@nifrajs/coding-agent 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/EXTENSIONS.md +25 -0
- package/PERFORMANCE.md +19 -0
- package/README.md +69 -0
- package/REGISTRY.md +15 -0
- package/SECURITY.md +32 -0
- package/dist/approvals.d.ts +70 -0
- package/dist/approvals.d.ts.map +1 -0
- package/dist/approvals.js +174 -0
- package/dist/approvals.js.map +1 -0
- package/dist/capabilities.d.ts +20 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/capabilities.js +49 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/cli.d.ts +24 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +380 -0
- package/dist/cli.js.map +1 -0
- package/dist/context.d.ts +17 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +66 -0
- package/dist/context.js.map +1 -0
- package/dist/deployment-adapters.d.ts +40 -0
- package/dist/deployment-adapters.d.ts.map +1 -0
- package/dist/deployment-adapters.js +147 -0
- package/dist/deployment-adapters.js.map +1 -0
- package/dist/diff.d.ts +17 -0
- package/dist/diff.d.ts.map +1 -0
- package/dist/diff.js +61 -0
- package/dist/diff.js.map +1 -0
- package/dist/errors.d.ts +9 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +35 -0
- package/dist/errors.js.map +1 -0
- package/dist/extensions.d.ts +104 -0
- package/dist/extensions.d.ts.map +1 -0
- package/dist/extensions.js +284 -0
- package/dist/extensions.js.map +1 -0
- package/dist/handoffs.d.ts +97 -0
- package/dist/handoffs.d.ts.map +1 -0
- package/dist/handoffs.js +199 -0
- package/dist/handoffs.js.map +1 -0
- package/dist/healing.d.ts +56 -0
- package/dist/healing.d.ts.map +1 -0
- package/dist/healing.js +54 -0
- package/dist/healing.js.map +1 -0
- package/dist/host.d.ts +61 -0
- package/dist/host.d.ts.map +1 -0
- package/dist/host.js +369 -0
- package/dist/host.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/isolated-worker.d.ts +2 -0
- package/dist/isolated-worker.d.ts.map +1 -0
- package/dist/isolated-worker.js +155 -0
- package/dist/isolated-worker.js.map +1 -0
- package/dist/isolated.d.ts +52 -0
- package/dist/isolated.d.ts.map +1 -0
- package/dist/isolated.js +293 -0
- package/dist/isolated.js.map +1 -0
- package/dist/native.d.ts +92 -0
- package/dist/native.d.ts.map +1 -0
- package/dist/native.js +339 -0
- package/dist/native.js.map +1 -0
- package/dist/orchestration/artifact-port.d.ts +30 -0
- package/dist/orchestration/artifact-port.d.ts.map +1 -0
- package/dist/orchestration/artifact-port.js +59 -0
- package/dist/orchestration/artifact-port.js.map +1 -0
- package/dist/orchestration/catalog.d.ts +71 -0
- package/dist/orchestration/catalog.d.ts.map +1 -0
- package/dist/orchestration/catalog.js +46 -0
- package/dist/orchestration/catalog.js.map +1 -0
- package/dist/orchestration/compile.d.ts +59 -0
- package/dist/orchestration/compile.d.ts.map +1 -0
- package/dist/orchestration/compile.js +268 -0
- package/dist/orchestration/compile.js.map +1 -0
- package/dist/orchestration/dispatch.d.ts +115 -0
- package/dist/orchestration/dispatch.d.ts.map +1 -0
- package/dist/orchestration/dispatch.js +220 -0
- package/dist/orchestration/dispatch.js.map +1 -0
- package/dist/orchestration/durable-jobs.d.ts +35 -0
- package/dist/orchestration/durable-jobs.d.ts.map +1 -0
- package/dist/orchestration/durable-jobs.js +273 -0
- package/dist/orchestration/durable-jobs.js.map +1 -0
- package/dist/orchestration/effect-key.d.ts +23 -0
- package/dist/orchestration/effect-key.d.ts.map +1 -0
- package/dist/orchestration/effect-key.js +24 -0
- package/dist/orchestration/effect-key.js.map +1 -0
- package/dist/orchestration/evidence-store.d.ts +75 -0
- package/dist/orchestration/evidence-store.d.ts.map +1 -0
- package/dist/orchestration/evidence-store.js +183 -0
- package/dist/orchestration/evidence-store.js.map +1 -0
- package/dist/orchestration/hash.d.ts +12 -0
- package/dist/orchestration/hash.d.ts.map +1 -0
- package/dist/orchestration/hash.js +43 -0
- package/dist/orchestration/hash.js.map +1 -0
- package/dist/orchestration/host.d.ts +121 -0
- package/dist/orchestration/host.d.ts.map +1 -0
- package/dist/orchestration/host.js +334 -0
- package/dist/orchestration/host.js.map +1 -0
- package/dist/orchestration/index.d.ts +20 -0
- package/dist/orchestration/index.d.ts.map +1 -0
- package/dist/orchestration/index.js +19 -0
- package/dist/orchestration/index.js.map +1 -0
- package/dist/orchestration/policy.d.ts +63 -0
- package/dist/orchestration/policy.d.ts.map +1 -0
- package/dist/orchestration/policy.js +80 -0
- package/dist/orchestration/policy.js.map +1 -0
- package/dist/orchestration/recovery.d.ts +87 -0
- package/dist/orchestration/recovery.d.ts.map +1 -0
- package/dist/orchestration/recovery.js +197 -0
- package/dist/orchestration/recovery.js.map +1 -0
- package/dist/orchestration/tracer.d.ts +31 -0
- package/dist/orchestration/tracer.d.ts.map +1 -0
- package/dist/orchestration/tracer.js +141 -0
- package/dist/orchestration/tracer.js.map +1 -0
- package/dist/plans.d.ts +35 -0
- package/dist/plans.d.ts.map +1 -0
- package/dist/plans.js +63 -0
- package/dist/plans.js.map +1 -0
- package/dist/presets.d.ts +10 -0
- package/dist/presets.d.ts.map +1 -0
- package/dist/presets.js +70 -0
- package/dist/presets.js.map +1 -0
- package/dist/process.d.ts +6 -0
- package/dist/process.d.ts.map +1 -0
- package/dist/process.js +42 -0
- package/dist/process.js.map +1 -0
- package/dist/registry.d.ts +37 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +51 -0
- package/dist/registry.js.map +1 -0
- package/dist/replay.d.ts +24 -0
- package/dist/replay.d.ts.map +1 -0
- package/dist/replay.js +154 -0
- package/dist/replay.js.map +1 -0
- package/dist/rpc.d.ts +51 -0
- package/dist/rpc.d.ts.map +1 -0
- package/dist/rpc.js +412 -0
- package/dist/rpc.js.map +1 -0
- package/dist/session-migration.d.ts +59 -0
- package/dist/session-migration.d.ts.map +1 -0
- package/dist/session-migration.js +315 -0
- package/dist/session-migration.js.map +1 -0
- package/dist/sessions.d.ts +74 -0
- package/dist/sessions.d.ts.map +1 -0
- package/dist/sessions.js +222 -0
- package/dist/sessions.js.map +1 -0
- package/dist/subagents.d.ts +51 -0
- package/dist/subagents.d.ts.map +1 -0
- package/dist/subagents.js +141 -0
- package/dist/subagents.js.map +1 -0
- package/dist/tools.d.ts +13 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +37 -0
- package/dist/tools.js.map +1 -0
- package/dist/ui.d.ts +42 -0
- package/dist/ui.d.ts.map +1 -0
- package/dist/ui.js +93 -0
- package/dist/ui.js.map +1 -0
- package/dist/verification.d.ts +34 -0
- package/dist/verification.d.ts.map +1 -0
- package/dist/verification.js +91 -0
- package/dist/verification.js.map +1 -0
- package/dist/workflows.d.ts +98 -0
- package/dist/workflows.d.ts.map +1 -0
- package/dist/workflows.js +174 -0
- package/dist/workflows.js.map +1 -0
- package/package.json +84 -0
- package/src/approvals.ts +249 -0
- package/src/capabilities.ts +74 -0
- package/src/cli.ts +405 -0
- package/src/context.ts +81 -0
- package/src/deployment-adapters.ts +181 -0
- package/src/diff.ts +80 -0
- package/src/errors.ts +46 -0
- package/src/extensions.ts +402 -0
- package/src/handoffs.ts +299 -0
- package/src/healing.ts +93 -0
- package/src/host.ts +465 -0
- package/src/index.ts +165 -0
- package/src/isolated-worker.ts +177 -0
- package/src/isolated.ts +344 -0
- package/src/native.ts +478 -0
- package/src/orchestration/artifact-port.ts +75 -0
- package/src/orchestration/catalog.ts +102 -0
- package/src/orchestration/compile.ts +373 -0
- package/src/orchestration/dispatch.ts +383 -0
- package/src/orchestration/durable-jobs.ts +374 -0
- package/src/orchestration/effect-key.ts +35 -0
- package/src/orchestration/evidence-store.ts +233 -0
- package/src/orchestration/hash.ts +43 -0
- package/src/orchestration/host.ts +445 -0
- package/src/orchestration/index.ts +131 -0
- package/src/orchestration/policy.ts +116 -0
- package/src/orchestration/recovery.ts +271 -0
- package/src/orchestration/tracer.ts +177 -0
- package/src/plans.ts +105 -0
- package/src/presets.ts +90 -0
- package/src/process.ts +47 -0
- package/src/registry.ts +80 -0
- package/src/replay.ts +190 -0
- package/src/rpc.ts +598 -0
- package/src/session-migration.ts +401 -0
- package/src/sessions.ts +303 -0
- package/src/subagents.ts +210 -0
- package/src/tools.ts +52 -0
- package/src/ui.ts +137 -0
- package/src/verification.ts +133 -0
- package/src/workflows.ts +279 -0
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
2
|
+
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
3
|
+
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
4
|
+
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
5
|
+
});
|
|
6
|
+
}
|
|
7
|
+
return path;
|
|
8
|
+
};
|
|
9
|
+
import { existsSync, realpathSync } from "node:fs";
|
|
10
|
+
import { join, relative, resolve } from "node:path";
|
|
11
|
+
import { WorkflowRunner, } from "./workflows.js";
|
|
12
|
+
/** Discover only project-local extension files; no home-directory or dependency scan is implicit. */
|
|
13
|
+
export async function discoverExtensions(cwd) {
|
|
14
|
+
const directory = resolve(cwd, ".nifra/extensions");
|
|
15
|
+
if (!existsSync(directory))
|
|
16
|
+
return Object.freeze([]);
|
|
17
|
+
const roots = [];
|
|
18
|
+
for await (const path of new Bun.Glob("**/*").scan({ cwd: directory, dot: false })) {
|
|
19
|
+
if (/\.(?:ts|tsx|js|jsx)$/.test(path))
|
|
20
|
+
roots.push(join(".nifra/extensions", path));
|
|
21
|
+
}
|
|
22
|
+
return Object.freeze(roots.sort());
|
|
23
|
+
}
|
|
24
|
+
/** Parse an extension without activating it. This is a fast syntax gate before staging. */
|
|
25
|
+
export async function validateExtensionModule(path) {
|
|
26
|
+
const source = await Bun.file(path).text();
|
|
27
|
+
const loader = /\.tsx?$/.test(path) ? "tsx" : "js";
|
|
28
|
+
try {
|
|
29
|
+
new Bun.Transpiler({ loader }).transformSync(source);
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
throw new Error(`extension validation failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Transactional TypeScript extension loader for the Nifra-native backend.
|
|
37
|
+
*
|
|
38
|
+
* This loader only activates explicitly supplied files. It never scans a project implicitly and it
|
|
39
|
+
* leaves the previous extension graph intact when a staged reload fails.
|
|
40
|
+
*/
|
|
41
|
+
export class ExtensionHost {
|
|
42
|
+
options;
|
|
43
|
+
active = [];
|
|
44
|
+
commands = new Map();
|
|
45
|
+
tools = new Map();
|
|
46
|
+
workflows = new Map();
|
|
47
|
+
subagents = new Map();
|
|
48
|
+
providers = new Map();
|
|
49
|
+
handlers = new Map();
|
|
50
|
+
revision = "0";
|
|
51
|
+
constructor(options) {
|
|
52
|
+
this.options = Object.freeze({
|
|
53
|
+
...options,
|
|
54
|
+
roots: Object.freeze([...options.roots]),
|
|
55
|
+
trustedCapabilities: Object.freeze([...(options.trustedCapabilities ?? [])]),
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
get extensions() {
|
|
59
|
+
return this.active;
|
|
60
|
+
}
|
|
61
|
+
get currentRevision() {
|
|
62
|
+
return this.revision;
|
|
63
|
+
}
|
|
64
|
+
get availableCommands() {
|
|
65
|
+
return Object.freeze([...this.commands.keys()].sort());
|
|
66
|
+
}
|
|
67
|
+
get availableTools() {
|
|
68
|
+
return Object.freeze([...this.tools.values()]);
|
|
69
|
+
}
|
|
70
|
+
get availableWorkflows() {
|
|
71
|
+
return Object.freeze([...this.workflows.keys()].sort());
|
|
72
|
+
}
|
|
73
|
+
get availableSubagents() {
|
|
74
|
+
return Object.freeze([...this.subagents.values()]);
|
|
75
|
+
}
|
|
76
|
+
get availableProviders() {
|
|
77
|
+
return Object.freeze([...this.providers.values()]);
|
|
78
|
+
}
|
|
79
|
+
async reload() {
|
|
80
|
+
let pathError;
|
|
81
|
+
const paths = this.options.roots
|
|
82
|
+
.map((root) => resolve(this.options.cwd, root))
|
|
83
|
+
.filter((path) => {
|
|
84
|
+
if (!isWithin(this.options.cwd, path)) {
|
|
85
|
+
pathError = `extension path escapes project root: ${path}`;
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
if (!existsSync(path))
|
|
89
|
+
return false;
|
|
90
|
+
try {
|
|
91
|
+
if (!isWithin(this.options.cwd, realpathSync(path))) {
|
|
92
|
+
pathError = `extension path escapes project root: ${path}`;
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
pathError = `extension path could not be resolved: ${path}`;
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
const next = [];
|
|
103
|
+
const nextCommands = new Map();
|
|
104
|
+
const nextTools = new Map();
|
|
105
|
+
const nextWorkflows = new Map();
|
|
106
|
+
const nextSubagents = new Map();
|
|
107
|
+
const nextProviders = new Map();
|
|
108
|
+
const nextHandlers = new Map();
|
|
109
|
+
try {
|
|
110
|
+
if (pathError !== undefined)
|
|
111
|
+
throw new Error(pathError);
|
|
112
|
+
for (const path of paths) {
|
|
113
|
+
await this.options.validate?.(path);
|
|
114
|
+
const loaded = await this.loadOne(path, nextCommands, nextTools, nextWorkflows, nextSubagents, nextProviders, nextHandlers);
|
|
115
|
+
next.push(loaded);
|
|
116
|
+
}
|
|
117
|
+
const previous = this.active;
|
|
118
|
+
this.active = Object.freeze(next);
|
|
119
|
+
this.commands = nextCommands;
|
|
120
|
+
this.tools = nextTools;
|
|
121
|
+
this.workflows = nextWorkflows;
|
|
122
|
+
this.subagents = nextSubagents;
|
|
123
|
+
this.providers = nextProviders;
|
|
124
|
+
this.handlers = nextHandlers;
|
|
125
|
+
this.revision = `${Date.now().toString(36)}-${next.length}`;
|
|
126
|
+
for (const extension of previous) {
|
|
127
|
+
try {
|
|
128
|
+
await extension.dispose?.();
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
this.options.onError?.({ path: extension.path, error });
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
revision: this.revision,
|
|
136
|
+
loaded: Object.freeze(next.map((extension) => extension.id)),
|
|
137
|
+
disabled: [],
|
|
138
|
+
rolledBack: false,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
for (const extension of next.reverse()) {
|
|
143
|
+
try {
|
|
144
|
+
await extension.dispose?.();
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
/* staged cleanup is best effort */
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
151
|
+
this.options.onError?.({ path: paths[next.length] ?? this.options.cwd, error });
|
|
152
|
+
return {
|
|
153
|
+
revision: this.revision,
|
|
154
|
+
loaded: Object.freeze(this.active.map((extension) => extension.id)),
|
|
155
|
+
disabled: Object.freeze(paths.slice(next.length)),
|
|
156
|
+
rolledBack: true,
|
|
157
|
+
error: message,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
async close() {
|
|
162
|
+
const active = this.active;
|
|
163
|
+
this.active = [];
|
|
164
|
+
this.commands = new Map();
|
|
165
|
+
this.tools = new Map();
|
|
166
|
+
this.workflows = new Map();
|
|
167
|
+
this.subagents = new Map();
|
|
168
|
+
this.providers = new Map();
|
|
169
|
+
this.handlers = new Map();
|
|
170
|
+
for (const extension of active)
|
|
171
|
+
await extension.dispose?.();
|
|
172
|
+
}
|
|
173
|
+
command(name) {
|
|
174
|
+
return this.commands.get(name);
|
|
175
|
+
}
|
|
176
|
+
tool(name) {
|
|
177
|
+
return this.tools.get(name);
|
|
178
|
+
}
|
|
179
|
+
workflow(name) {
|
|
180
|
+
return this.workflows.get(name);
|
|
181
|
+
}
|
|
182
|
+
subagent(name) {
|
|
183
|
+
return this.subagents.get(name);
|
|
184
|
+
}
|
|
185
|
+
provider(name) {
|
|
186
|
+
return this.providers.get(name);
|
|
187
|
+
}
|
|
188
|
+
async runWorkflow(name, options = {}) {
|
|
189
|
+
const workflow = this.workflows.get(name);
|
|
190
|
+
if (workflow === undefined)
|
|
191
|
+
throw new Error(`unknown extension workflow: ${name}`);
|
|
192
|
+
const step = await workflow(this.context());
|
|
193
|
+
return new WorkflowRunner(options).run(step);
|
|
194
|
+
}
|
|
195
|
+
async emit(event, payload) {
|
|
196
|
+
for (const handler of this.handlers.get(event) ?? [])
|
|
197
|
+
await handler(payload, this.context());
|
|
198
|
+
}
|
|
199
|
+
async loadOne(path, commands, tools, workflows, subagents, providers, handlers) {
|
|
200
|
+
const module = (await import(__rewriteRelativeImportExtension(`${path}?revision=${Date.now()}-${Math.random()}`)));
|
|
201
|
+
if (typeof module.default !== "function")
|
|
202
|
+
throw new Error(`extension ${path} has no default factory`);
|
|
203
|
+
const capabilities = Object.freeze([...(module.capabilities ?? [])]);
|
|
204
|
+
const trusted = new Set(this.options.trustedCapabilities ?? []);
|
|
205
|
+
const denied = capabilities.find((capability) => !trusted.has(capability));
|
|
206
|
+
if (denied !== undefined)
|
|
207
|
+
throw new Error(`extension ${path} requires untrusted capability: ${denied}`);
|
|
208
|
+
const context = this.context(commands, tools, workflows, subagents, providers, handlers);
|
|
209
|
+
const result = await module.default(context);
|
|
210
|
+
return Object.freeze({
|
|
211
|
+
id: module.id ?? path,
|
|
212
|
+
path,
|
|
213
|
+
capabilities,
|
|
214
|
+
...(result &&
|
|
215
|
+
typeof result === "object" &&
|
|
216
|
+
"dispose" in result &&
|
|
217
|
+
typeof result.dispose === "function"
|
|
218
|
+
? { dispose: result.dispose }
|
|
219
|
+
: {}),
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
context(commands = this.commands, tools = this.tools, workflows = this.workflows, subagents = this.subagents, providers = this.providers, handlers = this.handlers) {
|
|
223
|
+
return {
|
|
224
|
+
cwd: this.options.cwd,
|
|
225
|
+
registerCommand: (name, handler) => {
|
|
226
|
+
if (!/^[a-z][a-z0-9._-]{0,63}$/.test(name))
|
|
227
|
+
throw new Error(`invalid extension command: ${name}`);
|
|
228
|
+
if (commands.has(name))
|
|
229
|
+
throw new Error(`duplicate extension command: ${name}`);
|
|
230
|
+
commands.set(name, handler);
|
|
231
|
+
},
|
|
232
|
+
registerTool: (tool) => {
|
|
233
|
+
if (!/^[a-z][a-z0-9._-]{0,63}$/.test(tool.name))
|
|
234
|
+
throw new Error(`invalid extension tool: ${tool.name}`);
|
|
235
|
+
if (tools.has(tool.name))
|
|
236
|
+
throw new Error(`duplicate extension tool: ${tool.name}`);
|
|
237
|
+
const denied = (tool.capabilities ?? []).find((capability) => !(this.options.trustedCapabilities ?? []).includes(capability));
|
|
238
|
+
if (denied !== undefined)
|
|
239
|
+
throw new Error(`extension tool ${tool.name} requires untrusted capability: ${denied}`);
|
|
240
|
+
tools.set(tool.name, tool);
|
|
241
|
+
},
|
|
242
|
+
registerWorkflow: (name, workflow) => {
|
|
243
|
+
if (!/^[a-z][a-z0-9._-]{0,63}$/.test(name))
|
|
244
|
+
throw new Error(`invalid extension workflow: ${name}`);
|
|
245
|
+
if (workflows.has(name))
|
|
246
|
+
throw new Error(`duplicate extension workflow: ${name}`);
|
|
247
|
+
workflows.set(name, workflow);
|
|
248
|
+
},
|
|
249
|
+
registerSubagent: (role) => {
|
|
250
|
+
if (!/^[a-z][a-z0-9._-]{0,63}$/.test(role.name))
|
|
251
|
+
throw new Error(`invalid extension subagent: ${role.name}`);
|
|
252
|
+
if (subagents.has(role.name))
|
|
253
|
+
throw new Error(`duplicate extension subagent: ${role.name}`);
|
|
254
|
+
subagents.set(role.name, Object.freeze({ ...role }));
|
|
255
|
+
},
|
|
256
|
+
registerProvider: (provider) => {
|
|
257
|
+
if (!/^[a-z][a-z0-9._-]{0,63}$/.test(provider.name))
|
|
258
|
+
throw new Error(`invalid extension provider: ${provider.name}`);
|
|
259
|
+
if (providers.has(provider.name))
|
|
260
|
+
throw new Error(`duplicate extension provider: ${provider.name}`);
|
|
261
|
+
providers.set(provider.name, Object.freeze({ ...provider }));
|
|
262
|
+
},
|
|
263
|
+
on: (event, handler) => {
|
|
264
|
+
if (!/^[a-z][a-z0-9._-]{0,63}$/.test(event))
|
|
265
|
+
throw new Error(`invalid extension event: ${event}`);
|
|
266
|
+
const current = handlers.get(event) ?? [];
|
|
267
|
+
handlers.set(event, [...current, handler]);
|
|
268
|
+
},
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
function isWithin(root, candidate) {
|
|
273
|
+
const canonical = (path) => {
|
|
274
|
+
try {
|
|
275
|
+
return realpathSync(path);
|
|
276
|
+
}
|
|
277
|
+
catch {
|
|
278
|
+
return resolve(path);
|
|
279
|
+
}
|
|
280
|
+
};
|
|
281
|
+
const relativePath = relative(canonical(root), canonical(candidate));
|
|
282
|
+
return relativePath === "" || (!relativePath.startsWith("..") && !relativePath.includes("/.."));
|
|
283
|
+
}
|
|
284
|
+
//# sourceMappingURL=extensions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extensions.js","sourceRoot":"","sources":["../src/extensions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Handoff coordinator: the typed state machine for a delegated boundary within a run.
|
|
3
|
+
*
|
|
4
|
+
* This sits beside {@link ApprovalManager} rather than inside it. An approval answers a yes/no gate;
|
|
5
|
+
* a handoff moves ownership of a paused node between roles (open, optionally assign an owner, then
|
|
6
|
+
* accept, decline, resolve, expire, or cancel). The coordinator composes an {@link ApprovalManager}
|
|
7
|
+
* when a handoff also needs a yes/no gate, so existing approval semantics are extended, never
|
|
8
|
+
* weakened.
|
|
9
|
+
*
|
|
10
|
+
* Every boundary is addressed by a content-free {@link DecisionCoordinate}. A decision that names a
|
|
11
|
+
* different run, node, capability, or request id fails `identity_mismatch`; one carrying a superseded
|
|
12
|
+
* child vector fails `stale_vector`; one arriving at or past expiry expires the boundary closed and
|
|
13
|
+
* fails `expired`; one whose transition is absent from the {@link nextHandoffState} table fails
|
|
14
|
+
* `illegal_transition`; and one that would let a non-owner act on an assigned boundary fails
|
|
15
|
+
* `authority_expanded`. Nothing here stores or returns a prompt, a free-text reason, tool data, or a
|
|
16
|
+
* payload - only structural coordinates and a state.
|
|
17
|
+
*/
|
|
18
|
+
import { type DecisionCoordinate, type HandoffLifecycleState } from "@nifrajs/agent-protocol";
|
|
19
|
+
import type { ApprovalManager } from "./approvals.js";
|
|
20
|
+
import { ChildVectorTracker } from "./orchestration/policy.js";
|
|
21
|
+
/** Stable, content-free reasons the coordinator refuses a handoff request or decision. */
|
|
22
|
+
export type HandoffRejection = "unknown_boundary" | "identity_mismatch" | "stale_vector" | "expired" | "illegal_transition" | "authority_expanded" | "duplicate" | "invalid_handoff";
|
|
23
|
+
/** Thrown on any refused handoff operation. `code` is the machine-addressable reason. */
|
|
24
|
+
export declare class HandoffError extends Error {
|
|
25
|
+
readonly code: HandoffRejection;
|
|
26
|
+
constructor(code: HandoffRejection);
|
|
27
|
+
}
|
|
28
|
+
/** Content-free projection of one handoff boundary for a list/inspect view. */
|
|
29
|
+
export interface HandoffView {
|
|
30
|
+
readonly requestId: string;
|
|
31
|
+
readonly runId: string;
|
|
32
|
+
readonly nodeId: string;
|
|
33
|
+
readonly capability: string;
|
|
34
|
+
readonly vector: number;
|
|
35
|
+
readonly expiresAt: number;
|
|
36
|
+
readonly state: HandoffLifecycleState;
|
|
37
|
+
/** Opaque origin role. */
|
|
38
|
+
readonly from: string;
|
|
39
|
+
/** Opaque owner role once assigned. */
|
|
40
|
+
readonly to?: string;
|
|
41
|
+
}
|
|
42
|
+
export interface OpenHandoffInput {
|
|
43
|
+
readonly runId: string;
|
|
44
|
+
readonly nodeId: string;
|
|
45
|
+
readonly capability: string;
|
|
46
|
+
readonly requestId: string;
|
|
47
|
+
/** Opaque origin role. */
|
|
48
|
+
readonly from: string;
|
|
49
|
+
/** Milliseconds until the boundary expires closed. Falls back to the coordinator default. */
|
|
50
|
+
readonly expiresInMs?: number;
|
|
51
|
+
/** When true, a paired approval is opened on the composed {@link ApprovalManager}, if present. */
|
|
52
|
+
readonly requireApproval?: boolean;
|
|
53
|
+
readonly sessionId?: string;
|
|
54
|
+
}
|
|
55
|
+
/** A decision against a live boundary. The coordinate must match the boundary exactly. */
|
|
56
|
+
export interface HandoffDecision {
|
|
57
|
+
readonly coordinate: DecisionCoordinate;
|
|
58
|
+
/** Owner role to assign (for `assign`) or the actor claiming to own the boundary (accept/resolve). */
|
|
59
|
+
readonly by?: string;
|
|
60
|
+
}
|
|
61
|
+
export interface HandoffCoordinatorOptions {
|
|
62
|
+
readonly vectors?: ChildVectorTracker;
|
|
63
|
+
readonly approvals?: ApprovalManager;
|
|
64
|
+
readonly defaultTtlMs?: number;
|
|
65
|
+
readonly maxPending?: number;
|
|
66
|
+
/** Injectable clock (epoch ms). Defaults to {@link Date.now}. */
|
|
67
|
+
readonly now?: () => number;
|
|
68
|
+
}
|
|
69
|
+
export declare class HandoffCoordinator {
|
|
70
|
+
private readonly vectors;
|
|
71
|
+
private readonly approvals;
|
|
72
|
+
private readonly defaultTtlMs;
|
|
73
|
+
private readonly maxPending;
|
|
74
|
+
private readonly now;
|
|
75
|
+
private readonly records;
|
|
76
|
+
constructor(options?: HandoffCoordinatorOptions);
|
|
77
|
+
/** Open a pending handoff. Allocates the run's next monotonic child vector. */
|
|
78
|
+
open(input: OpenHandoffInput): HandoffView;
|
|
79
|
+
/** Every boundary, or - with `activeOnly` - just those still awaiting a decision. */
|
|
80
|
+
list(activeOnly?: boolean): readonly HandoffView[];
|
|
81
|
+
/** Inspect one boundary by request id, or `undefined` when unknown. */
|
|
82
|
+
inspect(requestId: string): HandoffView | undefined;
|
|
83
|
+
assign(decision: HandoffDecision): HandoffView;
|
|
84
|
+
accept(decision: HandoffDecision): HandoffView;
|
|
85
|
+
decline(decision: HandoffDecision): HandoffView;
|
|
86
|
+
/** Resolve a boundary, resuming exactly the one matching paused node. */
|
|
87
|
+
resolve(decision: HandoffDecision): HandoffView;
|
|
88
|
+
expire(decision: HandoffDecision): HandoffView;
|
|
89
|
+
cancel(decision: HandoffDecision): HandoffView;
|
|
90
|
+
private drive;
|
|
91
|
+
private settle;
|
|
92
|
+
private settleApproval;
|
|
93
|
+
private isTerminal;
|
|
94
|
+
private activeCount;
|
|
95
|
+
private view;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=handoffs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handoffs.d.ts","sourceRoot":"","sources":["../src/handoffs.ts"],"names":[],"mappings":"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"}
|
package/dist/handoffs.js
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Handoff coordinator: the typed state machine for a delegated boundary within a run.
|
|
3
|
+
*
|
|
4
|
+
* This sits beside {@link ApprovalManager} rather than inside it. An approval answers a yes/no gate;
|
|
5
|
+
* a handoff moves ownership of a paused node between roles (open, optionally assign an owner, then
|
|
6
|
+
* accept, decline, resolve, expire, or cancel). The coordinator composes an {@link ApprovalManager}
|
|
7
|
+
* when a handoff also needs a yes/no gate, so existing approval semantics are extended, never
|
|
8
|
+
* weakened.
|
|
9
|
+
*
|
|
10
|
+
* Every boundary is addressed by a content-free {@link DecisionCoordinate}. A decision that names a
|
|
11
|
+
* different run, node, capability, or request id fails `identity_mismatch`; one carrying a superseded
|
|
12
|
+
* child vector fails `stale_vector`; one arriving at or past expiry expires the boundary closed and
|
|
13
|
+
* fails `expired`; one whose transition is absent from the {@link nextHandoffState} table fails
|
|
14
|
+
* `illegal_transition`; and one that would let a non-owner act on an assigned boundary fails
|
|
15
|
+
* `authority_expanded`. Nothing here stores or returns a prompt, a free-text reason, tool data, or a
|
|
16
|
+
* payload - only structural coordinates and a state.
|
|
17
|
+
*/
|
|
18
|
+
import { coordinateIsFresh, coordinatesMatch, nextHandoffState, } from "@nifrajs/agent-protocol";
|
|
19
|
+
import { ChildVectorTracker } from "./orchestration/policy.js";
|
|
20
|
+
const ID_TOKEN = /^[A-Za-z0-9._:-]{1,128}$/;
|
|
21
|
+
/** Thrown on any refused handoff operation. `code` is the machine-addressable reason. */
|
|
22
|
+
export class HandoffError extends Error {
|
|
23
|
+
code;
|
|
24
|
+
constructor(code) {
|
|
25
|
+
super(`handoff: ${code}`);
|
|
26
|
+
this.code = code;
|
|
27
|
+
this.name = "HandoffError";
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const DEFAULT_TTL_MS = 5 * 60_000;
|
|
31
|
+
const DEFAULT_MAX_PENDING = 64;
|
|
32
|
+
export class HandoffCoordinator {
|
|
33
|
+
vectors;
|
|
34
|
+
approvals;
|
|
35
|
+
defaultTtlMs;
|
|
36
|
+
maxPending;
|
|
37
|
+
now;
|
|
38
|
+
records = new Map();
|
|
39
|
+
constructor(options = {}) {
|
|
40
|
+
this.vectors = options.vectors ?? new ChildVectorTracker();
|
|
41
|
+
this.approvals = options.approvals;
|
|
42
|
+
this.defaultTtlMs = options.defaultTtlMs ?? DEFAULT_TTL_MS;
|
|
43
|
+
this.maxPending = options.maxPending ?? DEFAULT_MAX_PENDING;
|
|
44
|
+
this.now = options.now ?? Date.now;
|
|
45
|
+
if (!Number.isSafeInteger(this.defaultTtlMs) || this.defaultTtlMs < 1)
|
|
46
|
+
throw new RangeError("handoff: defaultTtlMs must be positive");
|
|
47
|
+
if (!Number.isSafeInteger(this.maxPending) || this.maxPending < 1)
|
|
48
|
+
throw new RangeError("handoff: maxPending must be positive");
|
|
49
|
+
}
|
|
50
|
+
/** Open a pending handoff. Allocates the run's next monotonic child vector. */
|
|
51
|
+
open(input) {
|
|
52
|
+
if (!ID_TOKEN.test(input.runId) ||
|
|
53
|
+
!ID_TOKEN.test(input.nodeId) ||
|
|
54
|
+
!ID_TOKEN.test(input.requestId) ||
|
|
55
|
+
!input.capability ||
|
|
56
|
+
input.capability.length > 128 ||
|
|
57
|
+
!input.from ||
|
|
58
|
+
input.from.length > 128)
|
|
59
|
+
throw new HandoffError("invalid_handoff");
|
|
60
|
+
if (this.records.has(input.requestId))
|
|
61
|
+
throw new HandoffError("duplicate");
|
|
62
|
+
if (this.activeCount() >= this.maxPending)
|
|
63
|
+
throw new HandoffError("invalid_handoff");
|
|
64
|
+
const ttl = input.expiresInMs ?? this.defaultTtlMs;
|
|
65
|
+
if (!Number.isSafeInteger(ttl) || ttl < 1)
|
|
66
|
+
throw new HandoffError("invalid_handoff");
|
|
67
|
+
const coordinate = Object.freeze({
|
|
68
|
+
runId: input.runId,
|
|
69
|
+
nodeId: input.nodeId,
|
|
70
|
+
capability: input.capability,
|
|
71
|
+
requestId: input.requestId,
|
|
72
|
+
vector: this.vectors.open(input.runId),
|
|
73
|
+
expiresAt: this.now() + ttl,
|
|
74
|
+
});
|
|
75
|
+
const record = {
|
|
76
|
+
coordinate,
|
|
77
|
+
state: "pending",
|
|
78
|
+
from: input.from,
|
|
79
|
+
to: undefined,
|
|
80
|
+
sessionId: input.sessionId,
|
|
81
|
+
requireApproval: input.requireApproval === true,
|
|
82
|
+
};
|
|
83
|
+
this.records.set(input.requestId, record);
|
|
84
|
+
if (record.requireApproval && this.approvals !== undefined)
|
|
85
|
+
void this.approvals.offer({
|
|
86
|
+
id: input.requestId,
|
|
87
|
+
sessionId: input.sessionId ?? input.runId,
|
|
88
|
+
action: "handoff",
|
|
89
|
+
capability: input.capability,
|
|
90
|
+
});
|
|
91
|
+
return this.view(record);
|
|
92
|
+
}
|
|
93
|
+
/** Every boundary, or - with `activeOnly` - just those still awaiting a decision. */
|
|
94
|
+
list(activeOnly = false) {
|
|
95
|
+
const views = [];
|
|
96
|
+
for (const record of this.records.values()) {
|
|
97
|
+
if (activeOnly && this.isTerminal(record.state))
|
|
98
|
+
continue;
|
|
99
|
+
views.push(this.view(record));
|
|
100
|
+
}
|
|
101
|
+
return Object.freeze(views);
|
|
102
|
+
}
|
|
103
|
+
/** Inspect one boundary by request id, or `undefined` when unknown. */
|
|
104
|
+
inspect(requestId) {
|
|
105
|
+
const record = this.records.get(requestId);
|
|
106
|
+
return record === undefined ? undefined : this.view(record);
|
|
107
|
+
}
|
|
108
|
+
assign(decision) {
|
|
109
|
+
if (decision.by === undefined || !decision.by || decision.by.length > 128)
|
|
110
|
+
throw new HandoffError("invalid_handoff");
|
|
111
|
+
return this.drive("assign", decision, decision.by);
|
|
112
|
+
}
|
|
113
|
+
accept(decision) {
|
|
114
|
+
return this.drive("accept", decision);
|
|
115
|
+
}
|
|
116
|
+
decline(decision) {
|
|
117
|
+
return this.drive("decline", decision);
|
|
118
|
+
}
|
|
119
|
+
/** Resolve a boundary, resuming exactly the one matching paused node. */
|
|
120
|
+
resolve(decision) {
|
|
121
|
+
return this.drive("resolve", decision);
|
|
122
|
+
}
|
|
123
|
+
expire(decision) {
|
|
124
|
+
return this.drive("expire", decision);
|
|
125
|
+
}
|
|
126
|
+
cancel(decision) {
|
|
127
|
+
return this.drive("cancel", decision);
|
|
128
|
+
}
|
|
129
|
+
drive(op, decision, assignee) {
|
|
130
|
+
const record = this.records.get(decision.coordinate.requestId);
|
|
131
|
+
if (record === undefined)
|
|
132
|
+
throw new HandoffError("unknown_boundary");
|
|
133
|
+
if (!coordinatesMatch(record.coordinate, decision.coordinate)) {
|
|
134
|
+
throw new HandoffError(record.coordinate.vector !== decision.coordinate.vector
|
|
135
|
+
? "stale_vector"
|
|
136
|
+
: "identity_mismatch");
|
|
137
|
+
}
|
|
138
|
+
// Expiry is checked before the transition and, except for an explicit `expire`/`cancel`, is
|
|
139
|
+
// terminal: a decision that arrives at or past the deadline expires the boundary closed and
|
|
140
|
+
// resumes no work.
|
|
141
|
+
if (op !== "expire" && op !== "cancel" && !coordinateIsFresh(record.coordinate, this.now())) {
|
|
142
|
+
if (!this.isTerminal(record.state))
|
|
143
|
+
this.settle(record, "expired");
|
|
144
|
+
throw new HandoffError("expired");
|
|
145
|
+
}
|
|
146
|
+
// An assigned boundary may only be acted on by its owner. A different actor is an authority
|
|
147
|
+
// expansion, not a routine mismatch.
|
|
148
|
+
if (record.to !== undefined &&
|
|
149
|
+
(op === "accept" || op === "decline" || op === "resolve") &&
|
|
150
|
+
decision.by !== record.to)
|
|
151
|
+
throw new HandoffError("authority_expanded");
|
|
152
|
+
const next = nextHandoffState(record.state, op);
|
|
153
|
+
if (next === undefined)
|
|
154
|
+
throw new HandoffError("illegal_transition");
|
|
155
|
+
if (op === "assign")
|
|
156
|
+
record.to = assignee;
|
|
157
|
+
record.state = next;
|
|
158
|
+
if (this.isTerminal(next))
|
|
159
|
+
this.settleApproval(record, op);
|
|
160
|
+
return this.view(record);
|
|
161
|
+
}
|
|
162
|
+
settle(record, state) {
|
|
163
|
+
record.state = state;
|
|
164
|
+
this.settleApproval(record, "expire");
|
|
165
|
+
}
|
|
166
|
+
settleApproval(record, op) {
|
|
167
|
+
if (!record.requireApproval || this.approvals === undefined)
|
|
168
|
+
return;
|
|
169
|
+
this.approvals.resolve(record.coordinate.requestId, op === "accept" || op === "resolve");
|
|
170
|
+
}
|
|
171
|
+
isTerminal(state) {
|
|
172
|
+
return (state === "accepted" ||
|
|
173
|
+
state === "declined" ||
|
|
174
|
+
state === "resolved" ||
|
|
175
|
+
state === "expired" ||
|
|
176
|
+
state === "cancelled");
|
|
177
|
+
}
|
|
178
|
+
activeCount() {
|
|
179
|
+
let count = 0;
|
|
180
|
+
for (const record of this.records.values())
|
|
181
|
+
if (!this.isTerminal(record.state))
|
|
182
|
+
count++;
|
|
183
|
+
return count;
|
|
184
|
+
}
|
|
185
|
+
view(record) {
|
|
186
|
+
return Object.freeze({
|
|
187
|
+
requestId: record.coordinate.requestId,
|
|
188
|
+
runId: record.coordinate.runId,
|
|
189
|
+
nodeId: record.coordinate.nodeId,
|
|
190
|
+
capability: record.coordinate.capability,
|
|
191
|
+
vector: record.coordinate.vector,
|
|
192
|
+
expiresAt: record.coordinate.expiresAt,
|
|
193
|
+
state: record.state,
|
|
194
|
+
from: record.from,
|
|
195
|
+
...(record.to === undefined ? {} : { to: record.to }),
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=handoffs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handoffs.js","sourceRoot":"","sources":["../src/handoffs.ts"],"names":[],"mappings":"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"}
|