@aigne/agent-runtime 1.12.0-beta.5
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/LICENSE.md +26 -0
- package/README.md +79 -0
- package/dist/agent-runners/ai-runner.cjs +133 -0
- package/dist/agent-runners/ai-runner.d.cts +33 -0
- package/dist/agent-runners/ai-runner.d.cts.map +1 -0
- package/dist/agent-runners/ai-runner.d.mts +33 -0
- package/dist/agent-runners/ai-runner.d.mts.map +1 -0
- package/dist/agent-runners/ai-runner.mjs +134 -0
- package/dist/agent-runners/ai-runner.mjs.map +1 -0
- package/dist/agent-runners/ash-runner.cjs +272 -0
- package/dist/agent-runners/ash-runner.d.cts +30 -0
- package/dist/agent-runners/ash-runner.d.cts.map +1 -0
- package/dist/agent-runners/ash-runner.d.mts +30 -0
- package/dist/agent-runners/ash-runner.d.mts.map +1 -0
- package/dist/agent-runners/ash-runner.mjs +273 -0
- package/dist/agent-runners/ash-runner.mjs.map +1 -0
- package/dist/agent-runners/budget.cjs +71 -0
- package/dist/agent-runners/budget.d.cts +40 -0
- package/dist/agent-runners/budget.d.cts.map +1 -0
- package/dist/agent-runners/budget.d.mts +40 -0
- package/dist/agent-runners/budget.d.mts.map +1 -0
- package/dist/agent-runners/budget.mjs +67 -0
- package/dist/agent-runners/budget.mjs.map +1 -0
- package/dist/agent-runners/code-runner.cjs +61 -0
- package/dist/agent-runners/code-runner.mjs +61 -0
- package/dist/agent-runners/code-runner.mjs.map +1 -0
- package/dist/agent-runners/env-whitelist.cjs +36 -0
- package/dist/agent-runners/env-whitelist.d.cts +5 -0
- package/dist/agent-runners/env-whitelist.d.cts.map +1 -0
- package/dist/agent-runners/env-whitelist.d.mts +5 -0
- package/dist/agent-runners/env-whitelist.d.mts.map +1 -0
- package/dist/agent-runners/env-whitelist.mjs +36 -0
- package/dist/agent-runners/env-whitelist.mjs.map +1 -0
- package/dist/agent-runners/guide-rails.cjs +47 -0
- package/dist/agent-runners/guide-rails.d.cts +16 -0
- package/dist/agent-runners/guide-rails.d.cts.map +1 -0
- package/dist/agent-runners/guide-rails.d.mts +16 -0
- package/dist/agent-runners/guide-rails.d.mts.map +1 -0
- package/dist/agent-runners/guide-rails.mjs +48 -0
- package/dist/agent-runners/guide-rails.mjs.map +1 -0
- package/dist/agent-runners/hook-channel.cjs +55 -0
- package/dist/agent-runners/hook-channel.d.cts +38 -0
- package/dist/agent-runners/hook-channel.d.cts.map +1 -0
- package/dist/agent-runners/hook-channel.d.mts +38 -0
- package/dist/agent-runners/hook-channel.d.mts.map +1 -0
- package/dist/agent-runners/hook-channel.mjs +55 -0
- package/dist/agent-runners/hook-channel.mjs.map +1 -0
- package/dist/agent-runners/hooks.cjs +107 -0
- package/dist/agent-runners/hooks.d.cts +41 -0
- package/dist/agent-runners/hooks.d.cts.map +1 -0
- package/dist/agent-runners/hooks.d.mts +41 -0
- package/dist/agent-runners/hooks.d.mts.map +1 -0
- package/dist/agent-runners/hooks.mjs +107 -0
- package/dist/agent-runners/hooks.mjs.map +1 -0
- package/dist/agent-runners/memory-afs.cjs +342 -0
- package/dist/agent-runners/memory-afs.d.cts +221 -0
- package/dist/agent-runners/memory-afs.d.cts.map +1 -0
- package/dist/agent-runners/memory-afs.d.mts +221 -0
- package/dist/agent-runners/memory-afs.d.mts.map +1 -0
- package/dist/agent-runners/memory-afs.mjs +326 -0
- package/dist/agent-runners/memory-afs.mjs.map +1 -0
- package/dist/agent-runners/memory-archive.cjs +263 -0
- package/dist/agent-runners/memory-archive.d.cts +47 -0
- package/dist/agent-runners/memory-archive.d.cts.map +1 -0
- package/dist/agent-runners/memory-archive.d.mts +47 -0
- package/dist/agent-runners/memory-archive.d.mts.map +1 -0
- package/dist/agent-runners/memory-archive.mjs +257 -0
- package/dist/agent-runners/memory-archive.mjs.map +1 -0
- package/dist/agent-runners/orchestrator-runner.cjs +302 -0
- package/dist/agent-runners/orchestrator-runner.d.cts +23 -0
- package/dist/agent-runners/orchestrator-runner.d.cts.map +1 -0
- package/dist/agent-runners/orchestrator-runner.d.mts +23 -0
- package/dist/agent-runners/orchestrator-runner.d.mts.map +1 -0
- package/dist/agent-runners/orchestrator-runner.mjs +303 -0
- package/dist/agent-runners/orchestrator-runner.mjs.map +1 -0
- package/dist/agent-runners/orchestrator-state.cjs +68 -0
- package/dist/agent-runners/orchestrator-state.d.cts +23 -0
- package/dist/agent-runners/orchestrator-state.d.cts.map +1 -0
- package/dist/agent-runners/orchestrator-state.d.mts +23 -0
- package/dist/agent-runners/orchestrator-state.d.mts.map +1 -0
- package/dist/agent-runners/orchestrator-state.mjs +65 -0
- package/dist/agent-runners/orchestrator-state.mjs.map +1 -0
- package/dist/agent-runners/retry.cjs +30 -0
- package/dist/agent-runners/retry.d.cts +13 -0
- package/dist/agent-runners/retry.d.cts.map +1 -0
- package/dist/agent-runners/retry.d.mts +13 -0
- package/dist/agent-runners/retry.d.mts.map +1 -0
- package/dist/agent-runners/retry.mjs +30 -0
- package/dist/agent-runners/retry.mjs.map +1 -0
- package/dist/agent-runners/scratchpad-afs.cjs +276 -0
- package/dist/agent-runners/scratchpad-afs.d.cts +103 -0
- package/dist/agent-runners/scratchpad-afs.d.cts.map +1 -0
- package/dist/agent-runners/scratchpad-afs.d.mts +103 -0
- package/dist/agent-runners/scratchpad-afs.d.mts.map +1 -0
- package/dist/agent-runners/scratchpad-afs.mjs +271 -0
- package/dist/agent-runners/scratchpad-afs.mjs.map +1 -0
- package/dist/agent-runners/stream-router.cjs +72 -0
- package/dist/agent-runners/stream-router.d.cts +22 -0
- package/dist/agent-runners/stream-router.d.cts.map +1 -0
- package/dist/agent-runners/stream-router.d.mts +22 -0
- package/dist/agent-runners/stream-router.d.mts.map +1 -0
- package/dist/agent-runners/stream-router.mjs +72 -0
- package/dist/agent-runners/stream-router.mjs.map +1 -0
- package/dist/agent-runners/system-prompt.cjs +35 -0
- package/dist/agent-runners/system-prompt.d.cts +17 -0
- package/dist/agent-runners/system-prompt.d.cts.map +1 -0
- package/dist/agent-runners/system-prompt.d.mts +17 -0
- package/dist/agent-runners/system-prompt.d.mts.map +1 -0
- package/dist/agent-runners/system-prompt.mjs +34 -0
- package/dist/agent-runners/system-prompt.mjs.map +1 -0
- package/dist/agent-runners/team-modes/aggregates.cjs +36 -0
- package/dist/agent-runners/team-modes/aggregates.mjs +35 -0
- package/dist/agent-runners/team-modes/aggregates.mjs.map +1 -0
- package/dist/agent-runners/team-modes/iterate.cjs +46 -0
- package/dist/agent-runners/team-modes/iterate.mjs +47 -0
- package/dist/agent-runners/team-modes/iterate.mjs.map +1 -0
- package/dist/agent-runners/team-modes/parallel.cjs +59 -0
- package/dist/agent-runners/team-modes/parallel.mjs +60 -0
- package/dist/agent-runners/team-modes/parallel.mjs.map +1 -0
- package/dist/agent-runners/team-modes/reflection.cjs +155 -0
- package/dist/agent-runners/team-modes/reflection.mjs +156 -0
- package/dist/agent-runners/team-modes/reflection.mjs.map +1 -0
- package/dist/agent-runners/team-modes/sequential.cjs +63 -0
- package/dist/agent-runners/team-modes/sequential.mjs +64 -0
- package/dist/agent-runners/team-modes/sequential.mjs.map +1 -0
- package/dist/agent-runners/team-modes/utils.cjs +39 -0
- package/dist/agent-runners/team-modes/utils.mjs +36 -0
- package/dist/agent-runners/team-modes/utils.mjs.map +1 -0
- package/dist/agent-runners/team-runner.cjs +277 -0
- package/dist/agent-runners/team-runner.d.cts +34 -0
- package/dist/agent-runners/team-runner.d.cts.map +1 -0
- package/dist/agent-runners/team-runner.d.mts +34 -0
- package/dist/agent-runners/team-runner.d.mts.map +1 -0
- package/dist/agent-runners/team-runner.mjs +278 -0
- package/dist/agent-runners/team-runner.mjs.map +1 -0
- package/dist/agent-runners/template-context.cjs +32 -0
- package/dist/agent-runners/template-context.d.cts +43 -0
- package/dist/agent-runners/template-context.d.cts.map +1 -0
- package/dist/agent-runners/template-context.d.mts +43 -0
- package/dist/agent-runners/template-context.d.mts.map +1 -0
- package/dist/agent-runners/template-context.mjs +33 -0
- package/dist/agent-runners/template-context.mjs.map +1 -0
- package/dist/index.cjs +123 -0
- package/dist/index.d.cts +29 -0
- package/dist/index.d.mts +29 -0
- package/dist/index.mjs +29 -0
- package/dist/program/agent-action.cjs +496 -0
- package/dist/program/agent-action.d.cts +42 -0
- package/dist/program/agent-action.d.cts.map +1 -0
- package/dist/program/agent-action.d.mts +42 -0
- package/dist/program/agent-action.d.mts.map +1 -0
- package/dist/program/agent-action.mjs +497 -0
- package/dist/program/agent-action.mjs.map +1 -0
- package/dist/program/agent-messages-tools.cjs +137 -0
- package/dist/program/agent-messages-tools.d.cts +59 -0
- package/dist/program/agent-messages-tools.d.cts.map +1 -0
- package/dist/program/agent-messages-tools.d.mts +59 -0
- package/dist/program/agent-messages-tools.d.mts.map +1 -0
- package/dist/program/agent-messages-tools.mjs +130 -0
- package/dist/program/agent-messages-tools.mjs.map +1 -0
- package/dist/program/agent-runner-registry.cjs +314 -0
- package/dist/program/agent-runner-registry.d.cts +52 -0
- package/dist/program/agent-runner-registry.d.cts.map +1 -0
- package/dist/program/agent-runner-registry.d.mts +52 -0
- package/dist/program/agent-runner-registry.d.mts.map +1 -0
- package/dist/program/agent-runner-registry.mjs +313 -0
- package/dist/program/agent-runner-registry.mjs.map +1 -0
- package/dist/program/agent-subscribe.cjs +72 -0
- package/dist/program/agent-subscribe.d.cts +18 -0
- package/dist/program/agent-subscribe.d.cts.map +1 -0
- package/dist/program/agent-subscribe.d.mts +18 -0
- package/dist/program/agent-subscribe.d.mts.map +1 -0
- package/dist/program/agent-subscribe.mjs +73 -0
- package/dist/program/agent-subscribe.mjs.map +1 -0
- package/dist/program/agent-tools.cjs +135 -0
- package/dist/program/agent-tools.d.cts +35 -0
- package/dist/program/agent-tools.d.cts.map +1 -0
- package/dist/program/agent-tools.d.mts +35 -0
- package/dist/program/agent-tools.d.mts.map +1 -0
- package/dist/program/agent-tools.mjs +136 -0
- package/dist/program/agent-tools.mjs.map +1 -0
- package/dist/program/manifest-nesting.cjs +57 -0
- package/dist/program/manifest-nesting.d.cts +13 -0
- package/dist/program/manifest-nesting.d.cts.map +1 -0
- package/dist/program/manifest-nesting.d.mts +13 -0
- package/dist/program/manifest-nesting.d.mts.map +1 -0
- package/dist/program/manifest-nesting.mjs +57 -0
- package/dist/program/manifest-nesting.mjs.map +1 -0
- package/dist/program/result-contract.cjs +55 -0
- package/dist/program/result-contract.d.cts +23 -0
- package/dist/program/result-contract.d.cts.map +1 -0
- package/dist/program/result-contract.d.mts +23 -0
- package/dist/program/result-contract.d.mts.map +1 -0
- package/dist/program/result-contract.mjs +51 -0
- package/dist/program/result-contract.mjs.map +1 -0
- package/dist/program/runner-error.cjs +71 -0
- package/dist/program/runner-error.d.cts +25 -0
- package/dist/program/runner-error.d.cts.map +1 -0
- package/dist/program/runner-error.d.mts +25 -0
- package/dist/program/runner-error.d.mts.map +1 -0
- package/dist/program/runner-error.mjs +72 -0
- package/dist/program/runner-error.mjs.map +1 -0
- package/dist/program/scoped-afs.cjs +538 -0
- package/dist/program/scoped-afs.d.cts +245 -0
- package/dist/program/scoped-afs.d.cts.map +1 -0
- package/dist/program/scoped-afs.d.mts +245 -0
- package/dist/program/scoped-afs.d.mts.map +1 -0
- package/dist/program/scoped-afs.mjs +531 -0
- package/dist/program/scoped-afs.mjs.map +1 -0
- package/dist/program/session-hierarchy.cjs +1 -0
- package/dist/program/session-hierarchy.d.cts +2 -0
- package/dist/program/session-hierarchy.d.mts +2 -0
- package/dist/program/session-hierarchy.mjs +3 -0
- package/dist/program/tool-discovery/ash-frontmatter.cjs +83 -0
- package/dist/program/tool-discovery/ash-frontmatter.d.cts +21 -0
- package/dist/program/tool-discovery/ash-frontmatter.d.cts.map +1 -0
- package/dist/program/tool-discovery/ash-frontmatter.d.mts +21 -0
- package/dist/program/tool-discovery/ash-frontmatter.d.mts.map +1 -0
- package/dist/program/tool-discovery/ash-frontmatter.mjs +84 -0
- package/dist/program/tool-discovery/ash-frontmatter.mjs.map +1 -0
- package/dist/program/tool-discovery/dot-path-resolver.cjs +60 -0
- package/dist/program/tool-discovery/dot-path-resolver.mjs +61 -0
- package/dist/program/tool-discovery/dot-path-resolver.mjs.map +1 -0
- package/dist/program/tool-discovery/skill-gate.cjs +36 -0
- package/dist/program/tool-discovery/skill-gate.d.cts +10 -0
- package/dist/program/tool-discovery/skill-gate.d.cts.map +1 -0
- package/dist/program/tool-discovery/skill-gate.d.mts +10 -0
- package/dist/program/tool-discovery/skill-gate.d.mts.map +1 -0
- package/dist/program/tool-discovery/skill-gate.mjs +35 -0
- package/dist/program/tool-discovery/skill-gate.mjs.map +1 -0
- package/dist/providers/basic/ash/dist/index.cjs +1809 -0
- package/dist/providers/basic/ash/dist/index.mjs +1807 -0
- package/dist/providers/basic/ash/dist/index.mjs.map +1 -0
- package/package.json +67 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const require_scratchpad_afs = require('./scratchpad-afs.cjs');
|
|
2
|
+
|
|
3
|
+
//#region src/agent-runners/hook-channel.ts
|
|
4
|
+
function createHookChannel() {
|
|
5
|
+
const events = [];
|
|
6
|
+
const subscribers = /* @__PURE__ */ new Set();
|
|
7
|
+
return {
|
|
8
|
+
emit(name, payload) {
|
|
9
|
+
const event = {
|
|
10
|
+
name,
|
|
11
|
+
from: payload.from,
|
|
12
|
+
to: payload.to,
|
|
13
|
+
session: payload.session,
|
|
14
|
+
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
15
|
+
};
|
|
16
|
+
if (payload.iteration !== void 0) event.iteration = payload.iteration;
|
|
17
|
+
events.push(event);
|
|
18
|
+
for (const fn of subscribers) fn(event);
|
|
19
|
+
},
|
|
20
|
+
subscribe(fn) {
|
|
21
|
+
subscribers.add(fn);
|
|
22
|
+
return () => {
|
|
23
|
+
subscribers.delete(fn);
|
|
24
|
+
};
|
|
25
|
+
},
|
|
26
|
+
drain() {
|
|
27
|
+
return [...events];
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Persist hook events to the scope-local `/scratch/hook-channel.jsonl` file.
|
|
33
|
+
*
|
|
34
|
+
* Phase 2 moves this off the shared `/modules/memory/runs/<session>/...`
|
|
35
|
+
* tree so that team/orchestrator runs get an isolated, per-scope audit
|
|
36
|
+
* trail. Best-effort writer: returns the written path on success, or null
|
|
37
|
+
* when the caller has no session, no `afs.write`, or the write itself
|
|
38
|
+
* fails. An empty events file is still written (and the path returned) so
|
|
39
|
+
* callers don't special-case "no events".
|
|
40
|
+
*/
|
|
41
|
+
async function persistHookEvents(afs, session, events) {
|
|
42
|
+
if (!session || !afs.write) return null;
|
|
43
|
+
const path = `${require_scratchpad_afs.SCRATCH_SCOPE_ROOT}/hook-channel.jsonl`;
|
|
44
|
+
const content = events.length > 0 ? `${events.map((e) => JSON.stringify(e)).join("\n")}\n` : "";
|
|
45
|
+
try {
|
|
46
|
+
await afs.write(path, { content });
|
|
47
|
+
return path;
|
|
48
|
+
} catch {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
//#endregion
|
|
54
|
+
exports.createHookChannel = createHookChannel;
|
|
55
|
+
exports.persistHookEvents = persistHookEvents;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
//#region src/agent-runners/hook-channel.d.ts
|
|
2
|
+
interface HookEvent {
|
|
3
|
+
name: string;
|
|
4
|
+
from: string;
|
|
5
|
+
to: string;
|
|
6
|
+
iteration?: number;
|
|
7
|
+
session: string;
|
|
8
|
+
ts: string;
|
|
9
|
+
}
|
|
10
|
+
interface HookChannel {
|
|
11
|
+
emit(name: string, payload: {
|
|
12
|
+
from: string;
|
|
13
|
+
to: string;
|
|
14
|
+
iteration?: number;
|
|
15
|
+
session: string;
|
|
16
|
+
}): void;
|
|
17
|
+
subscribe(fn: (event: HookEvent) => void): () => void;
|
|
18
|
+
drain(): HookEvent[];
|
|
19
|
+
}
|
|
20
|
+
declare function createHookChannel(): HookChannel;
|
|
21
|
+
/**
|
|
22
|
+
* Persist hook events to the scope-local `/scratch/hook-channel.jsonl` file.
|
|
23
|
+
*
|
|
24
|
+
* Phase 2 moves this off the shared `/modules/memory/runs/<session>/...`
|
|
25
|
+
* tree so that team/orchestrator runs get an isolated, per-scope audit
|
|
26
|
+
* trail. Best-effort writer: returns the written path on success, or null
|
|
27
|
+
* when the caller has no session, no `afs.write`, or the write itself
|
|
28
|
+
* fails. An empty events file is still written (and the path returned) so
|
|
29
|
+
* callers don't special-case "no events".
|
|
30
|
+
*/
|
|
31
|
+
declare function persistHookEvents(afs: {
|
|
32
|
+
write?: (path: string, payload: {
|
|
33
|
+
content: string;
|
|
34
|
+
}) => Promise<unknown>;
|
|
35
|
+
}, session: string | undefined, events: HookEvent[]): Promise<string | null>;
|
|
36
|
+
//#endregion
|
|
37
|
+
export { HookChannel, HookEvent, createHookChannel, persistHookEvents };
|
|
38
|
+
//# sourceMappingURL=hook-channel.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-channel.d.cts","names":[],"sources":["../../src/agent-runners/hook-channel.ts"],"mappings":";UAEiB,SAAA;EACf,IAAA;EACA,IAAA;EACA,EAAA;EACA,SAAA;EACA,OAAA;EACA,EAAA;AAAA;AAAA,UAGe,WAAA;EACf,IAAA,CACE,IAAA,UACA,OAAA;IAAW,IAAA;IAAc,EAAA;IAAY,SAAA;IAAoB,OAAA;EAAA;EAE3D,SAAA,CAAU,EAAA,GAAK,KAAA,EAAO,SAAA;EACtB,KAAA,IAAS,SAAA;AAAA;AAAA,iBAGK,iBAAA,CAAA,GAAqB,WAAA;;;;;;;;;;;iBA2Cf,iBAAA,CACpB,GAAA;EAAO,KAAA,IAAS,IAAA,UAAc,OAAA;IAAW,OAAA;EAAA,MAAsB,OAAA;AAAA,GAC/D,OAAA,sBACA,MAAA,EAAQ,SAAA,KACP,OAAA"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
//#region src/agent-runners/hook-channel.d.ts
|
|
2
|
+
interface HookEvent {
|
|
3
|
+
name: string;
|
|
4
|
+
from: string;
|
|
5
|
+
to: string;
|
|
6
|
+
iteration?: number;
|
|
7
|
+
session: string;
|
|
8
|
+
ts: string;
|
|
9
|
+
}
|
|
10
|
+
interface HookChannel {
|
|
11
|
+
emit(name: string, payload: {
|
|
12
|
+
from: string;
|
|
13
|
+
to: string;
|
|
14
|
+
iteration?: number;
|
|
15
|
+
session: string;
|
|
16
|
+
}): void;
|
|
17
|
+
subscribe(fn: (event: HookEvent) => void): () => void;
|
|
18
|
+
drain(): HookEvent[];
|
|
19
|
+
}
|
|
20
|
+
declare function createHookChannel(): HookChannel;
|
|
21
|
+
/**
|
|
22
|
+
* Persist hook events to the scope-local `/scratch/hook-channel.jsonl` file.
|
|
23
|
+
*
|
|
24
|
+
* Phase 2 moves this off the shared `/modules/memory/runs/<session>/...`
|
|
25
|
+
* tree so that team/orchestrator runs get an isolated, per-scope audit
|
|
26
|
+
* trail. Best-effort writer: returns the written path on success, or null
|
|
27
|
+
* when the caller has no session, no `afs.write`, or the write itself
|
|
28
|
+
* fails. An empty events file is still written (and the path returned) so
|
|
29
|
+
* callers don't special-case "no events".
|
|
30
|
+
*/
|
|
31
|
+
declare function persistHookEvents(afs: {
|
|
32
|
+
write?: (path: string, payload: {
|
|
33
|
+
content: string;
|
|
34
|
+
}) => Promise<unknown>;
|
|
35
|
+
}, session: string | undefined, events: HookEvent[]): Promise<string | null>;
|
|
36
|
+
//#endregion
|
|
37
|
+
export { HookChannel, HookEvent, createHookChannel, persistHookEvents };
|
|
38
|
+
//# sourceMappingURL=hook-channel.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-channel.d.mts","names":[],"sources":["../../src/agent-runners/hook-channel.ts"],"mappings":";UAEiB,SAAA;EACf,IAAA;EACA,IAAA;EACA,EAAA;EACA,SAAA;EACA,OAAA;EACA,EAAA;AAAA;AAAA,UAGe,WAAA;EACf,IAAA,CACE,IAAA,UACA,OAAA;IAAW,IAAA;IAAc,EAAA;IAAY,SAAA;IAAoB,OAAA;EAAA;EAE3D,SAAA,CAAU,EAAA,GAAK,KAAA,EAAO,SAAA;EACtB,KAAA,IAAS,SAAA;AAAA;AAAA,iBAGK,iBAAA,CAAA,GAAqB,WAAA;;;;;;;;;;;iBA2Cf,iBAAA,CACpB,GAAA;EAAO,KAAA,IAAS,IAAA,UAAc,OAAA;IAAW,OAAA;EAAA,MAAsB,OAAA;AAAA,GAC/D,OAAA,sBACA,MAAA,EAAQ,SAAA,KACP,OAAA"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { SCRATCH_SCOPE_ROOT } from "./scratchpad-afs.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/agent-runners/hook-channel.ts
|
|
4
|
+
function createHookChannel() {
|
|
5
|
+
const events = [];
|
|
6
|
+
const subscribers = /* @__PURE__ */ new Set();
|
|
7
|
+
return {
|
|
8
|
+
emit(name, payload) {
|
|
9
|
+
const event = {
|
|
10
|
+
name,
|
|
11
|
+
from: payload.from,
|
|
12
|
+
to: payload.to,
|
|
13
|
+
session: payload.session,
|
|
14
|
+
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
15
|
+
};
|
|
16
|
+
if (payload.iteration !== void 0) event.iteration = payload.iteration;
|
|
17
|
+
events.push(event);
|
|
18
|
+
for (const fn of subscribers) fn(event);
|
|
19
|
+
},
|
|
20
|
+
subscribe(fn) {
|
|
21
|
+
subscribers.add(fn);
|
|
22
|
+
return () => {
|
|
23
|
+
subscribers.delete(fn);
|
|
24
|
+
};
|
|
25
|
+
},
|
|
26
|
+
drain() {
|
|
27
|
+
return [...events];
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Persist hook events to the scope-local `/scratch/hook-channel.jsonl` file.
|
|
33
|
+
*
|
|
34
|
+
* Phase 2 moves this off the shared `/modules/memory/runs/<session>/...`
|
|
35
|
+
* tree so that team/orchestrator runs get an isolated, per-scope audit
|
|
36
|
+
* trail. Best-effort writer: returns the written path on success, or null
|
|
37
|
+
* when the caller has no session, no `afs.write`, or the write itself
|
|
38
|
+
* fails. An empty events file is still written (and the path returned) so
|
|
39
|
+
* callers don't special-case "no events".
|
|
40
|
+
*/
|
|
41
|
+
async function persistHookEvents(afs, session, events) {
|
|
42
|
+
if (!session || !afs.write) return null;
|
|
43
|
+
const path = `${SCRATCH_SCOPE_ROOT}/hook-channel.jsonl`;
|
|
44
|
+
const content = events.length > 0 ? `${events.map((e) => JSON.stringify(e)).join("\n")}\n` : "";
|
|
45
|
+
try {
|
|
46
|
+
await afs.write(path, { content });
|
|
47
|
+
return path;
|
|
48
|
+
} catch {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
//#endregion
|
|
54
|
+
export { createHookChannel, persistHookEvents };
|
|
55
|
+
//# sourceMappingURL=hook-channel.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-channel.mjs","names":[],"sources":["../../src/agent-runners/hook-channel.ts"],"sourcesContent":["import { SCRATCH_SCOPE_ROOT } from \"./scratchpad-afs.js\";\n\nexport interface HookEvent {\n name: string;\n from: string;\n to: string;\n iteration?: number;\n session: string;\n ts: string;\n}\n\nexport interface HookChannel {\n emit(\n name: string,\n payload: { from: string; to: string; iteration?: number; session: string },\n ): void;\n subscribe(fn: (event: HookEvent) => void): () => void;\n drain(): HookEvent[];\n}\n\nexport function createHookChannel(): HookChannel {\n const events: HookEvent[] = [];\n const subscribers: Set<(event: HookEvent) => void> = new Set();\n\n return {\n emit(name, payload) {\n const event: HookEvent = {\n name,\n from: payload.from,\n to: payload.to,\n session: payload.session,\n ts: new Date().toISOString(),\n };\n if (payload.iteration !== undefined) {\n event.iteration = payload.iteration;\n }\n events.push(event);\n for (const fn of subscribers) fn(event);\n },\n\n subscribe(fn) {\n subscribers.add(fn);\n return () => {\n subscribers.delete(fn);\n };\n },\n\n drain() {\n return [...events];\n },\n };\n}\n\n/**\n * Persist hook events to the scope-local `/scratch/hook-channel.jsonl` file.\n *\n * Phase 2 moves this off the shared `/modules/memory/runs/<session>/...`\n * tree so that team/orchestrator runs get an isolated, per-scope audit\n * trail. Best-effort writer: returns the written path on success, or null\n * when the caller has no session, no `afs.write`, or the write itself\n * fails. An empty events file is still written (and the path returned) so\n * callers don't special-case \"no events\".\n */\nexport async function persistHookEvents(\n afs: { write?: (path: string, payload: { content: string }) => Promise<unknown> },\n session: string | undefined,\n events: HookEvent[],\n): Promise<string | null> {\n if (!session || !afs.write) return null;\n const path = `${SCRATCH_SCOPE_ROOT}/hook-channel.jsonl`;\n const content = events.length > 0 ? `${events.map((e) => JSON.stringify(e)).join(\"\\n\")}\\n` : \"\";\n try {\n await afs.write(path, { content });\n return path;\n } catch {\n return null;\n }\n}\n"],"mappings":";;;AAoBA,SAAgB,oBAAiC;CAC/C,MAAM,SAAsB,EAAE;CAC9B,MAAM,8BAA+C,IAAI,KAAK;AAE9D,QAAO;EACL,KAAK,MAAM,SAAS;GAClB,MAAM,QAAmB;IACvB;IACA,MAAM,QAAQ;IACd,IAAI,QAAQ;IACZ,SAAS,QAAQ;IACjB,qBAAI,IAAI,MAAM,EAAC,aAAa;IAC7B;AACD,OAAI,QAAQ,cAAc,OACxB,OAAM,YAAY,QAAQ;AAE5B,UAAO,KAAK,MAAM;AAClB,QAAK,MAAM,MAAM,YAAa,IAAG,MAAM;;EAGzC,UAAU,IAAI;AACZ,eAAY,IAAI,GAAG;AACnB,gBAAa;AACX,gBAAY,OAAO,GAAG;;;EAI1B,QAAQ;AACN,UAAO,CAAC,GAAG,OAAO;;EAErB;;;;;;;;;;;;AAaH,eAAsB,kBACpB,KACA,SACA,QACwB;AACxB,KAAI,CAAC,WAAW,CAAC,IAAI,MAAO,QAAO;CACnC,MAAM,OAAO,GAAG,mBAAmB;CACnC,MAAM,UAAU,OAAO,SAAS,IAAI,GAAG,OAAO,KAAK,MAAM,KAAK,UAAU,EAAE,CAAC,CAAC,KAAK,KAAK,CAAC,MAAM;AAC7F,KAAI;AACF,QAAM,IAAI,MAAM,MAAM,EAAE,SAAS,CAAC;AAClC,SAAO;SACD;AACN,SAAO"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
let ufo = require("ufo");
|
|
2
|
+
let _aigne_afs = require("@aigne/afs");
|
|
3
|
+
|
|
4
|
+
//#region src/agent-runners/hooks.ts
|
|
5
|
+
const log = (0, _aigne_afs.makeNsLog)("agent-runtime");
|
|
6
|
+
const MAX_HOOK_CHAIN_DEPTH = 3;
|
|
7
|
+
const INTERNAL_FIELD_PREFIX = "_";
|
|
8
|
+
function sanitizePayloadForHook(obj) {
|
|
9
|
+
const sanitized = {};
|
|
10
|
+
for (const [key, value] of Object.entries(obj)) if (!key.startsWith(INTERNAL_FIELD_PREFIX)) sanitized[key] = value;
|
|
11
|
+
return sanitized;
|
|
12
|
+
}
|
|
13
|
+
async function fireHook(afs, hookPath, payload, opts) {
|
|
14
|
+
const chainDepth = opts.chainDepth ?? 0;
|
|
15
|
+
if (chainDepth >= MAX_HOOK_CHAIN_DEPTH) {
|
|
16
|
+
log.warn(`[hooks] Chain depth ${chainDepth} >= ${MAX_HOOK_CHAIN_DEPTH}, skipping: ${hookPath}`);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const cloned = structuredClone(sanitizePayloadForHook(payload));
|
|
20
|
+
const hookSession = opts.session ? `${opts.session}-hook-${Date.now()}` : void 0;
|
|
21
|
+
try {
|
|
22
|
+
await afs.exec(hookPath, {
|
|
23
|
+
...cloned,
|
|
24
|
+
session: hookSession,
|
|
25
|
+
_hook_chain_depth: chainDepth + 1
|
|
26
|
+
}, {});
|
|
27
|
+
} catch (err) {
|
|
28
|
+
log.warn(`[hooks] Hook "${hookPath}" failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function createHookDispatcher(afs, hooks, opts) {
|
|
32
|
+
const { mountPath, blockletId, session, chainDepth = 0 } = opts;
|
|
33
|
+
const resolve = (hookRef) => {
|
|
34
|
+
if (!hookRef) return null;
|
|
35
|
+
if (hookRef.startsWith("/")) return hookRef;
|
|
36
|
+
return (0, ufo.joinURL)(mountPath, hookRef);
|
|
37
|
+
};
|
|
38
|
+
const fire = async (hookRef, payload) => {
|
|
39
|
+
const path = resolve(hookRef);
|
|
40
|
+
if (!path) return;
|
|
41
|
+
await fireHook(afs, path, payload, {
|
|
42
|
+
session,
|
|
43
|
+
chainDepth
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
return {
|
|
47
|
+
async fireOnStart(input) {
|
|
48
|
+
await fire(hooks?.onStart, {
|
|
49
|
+
event: "on_start",
|
|
50
|
+
blockletId,
|
|
51
|
+
input: sanitizePayloadForHook(input),
|
|
52
|
+
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
53
|
+
});
|
|
54
|
+
},
|
|
55
|
+
async fireOnSuccess(result) {
|
|
56
|
+
await fire(hooks?.onSuccess, {
|
|
57
|
+
event: "on_success",
|
|
58
|
+
blockletId,
|
|
59
|
+
result,
|
|
60
|
+
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
61
|
+
});
|
|
62
|
+
},
|
|
63
|
+
async fireOnError(error) {
|
|
64
|
+
await fire(hooks?.onError, {
|
|
65
|
+
event: "on_error",
|
|
66
|
+
blockletId,
|
|
67
|
+
error,
|
|
68
|
+
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
69
|
+
});
|
|
70
|
+
},
|
|
71
|
+
async fireOnHandoff(from, to, iteration) {
|
|
72
|
+
await fire(hooks?.onHandoff, {
|
|
73
|
+
event: "on_handoff",
|
|
74
|
+
blockletId,
|
|
75
|
+
from,
|
|
76
|
+
to,
|
|
77
|
+
...iteration !== void 0 ? { iteration } : {},
|
|
78
|
+
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
79
|
+
});
|
|
80
|
+
},
|
|
81
|
+
async fireOnSkillStart(skill, args) {
|
|
82
|
+
await fire(hooks?.onSkillStart, {
|
|
83
|
+
event: "on_skill_start",
|
|
84
|
+
blockletId,
|
|
85
|
+
skill,
|
|
86
|
+
args: sanitizePayloadForHook(args),
|
|
87
|
+
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
88
|
+
});
|
|
89
|
+
},
|
|
90
|
+
async fireOnSkillEnd(skill, payload) {
|
|
91
|
+
await fire(hooks?.onSkillEnd, {
|
|
92
|
+
event: "on_skill_end",
|
|
93
|
+
blockletId,
|
|
94
|
+
skill,
|
|
95
|
+
status: payload.status,
|
|
96
|
+
...payload.result !== void 0 ? { result: payload.result } : {},
|
|
97
|
+
...payload.error !== void 0 ? { error: payload.error } : {},
|
|
98
|
+
durationMs: payload.durationMs,
|
|
99
|
+
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
//#endregion
|
|
106
|
+
exports.createHookDispatcher = createHookDispatcher;
|
|
107
|
+
exports.fireHook = fireHook;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { AFSRoot } from "@aigne/afs";
|
|
2
|
+
|
|
3
|
+
//#region src/agent-runners/hooks.d.ts
|
|
4
|
+
interface HookConfig {
|
|
5
|
+
onStart?: string;
|
|
6
|
+
onSuccess?: string;
|
|
7
|
+
onError?: string;
|
|
8
|
+
onHandoff?: string;
|
|
9
|
+
onSkillStart?: string;
|
|
10
|
+
onSkillEnd?: string;
|
|
11
|
+
}
|
|
12
|
+
interface SkillEndPayload {
|
|
13
|
+
status: "ok" | "error";
|
|
14
|
+
result?: unknown;
|
|
15
|
+
error?: string;
|
|
16
|
+
durationMs: number;
|
|
17
|
+
}
|
|
18
|
+
declare function fireHook(afs: AFSRoot, hookPath: string, payload: Record<string, unknown>, opts: {
|
|
19
|
+
session?: string;
|
|
20
|
+
chainDepth?: number;
|
|
21
|
+
}): Promise<void>;
|
|
22
|
+
interface HookDispatcher {
|
|
23
|
+
fireOnStart(input: Record<string, unknown>): Promise<void>;
|
|
24
|
+
fireOnSuccess(result: unknown): Promise<void>;
|
|
25
|
+
fireOnError(error: {
|
|
26
|
+
code: string;
|
|
27
|
+
message: string;
|
|
28
|
+
}): Promise<void>;
|
|
29
|
+
fireOnHandoff(from: string, to: string, iteration?: number): Promise<void>;
|
|
30
|
+
fireOnSkillStart(skill: string, args: Record<string, unknown>): Promise<void>;
|
|
31
|
+
fireOnSkillEnd(skill: string, payload: SkillEndPayload): Promise<void>;
|
|
32
|
+
}
|
|
33
|
+
declare function createHookDispatcher(afs: AFSRoot, hooks: HookConfig | undefined, opts: {
|
|
34
|
+
mountPath: string;
|
|
35
|
+
blockletId: string;
|
|
36
|
+
session?: string;
|
|
37
|
+
chainDepth?: number;
|
|
38
|
+
}): HookDispatcher;
|
|
39
|
+
//#endregion
|
|
40
|
+
export { HookConfig, HookDispatcher, SkillEndPayload, createHookDispatcher, fireHook };
|
|
41
|
+
//# sourceMappingURL=hooks.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.cts","names":[],"sources":["../../src/agent-runners/hooks.ts"],"mappings":";;;UAMiB,UAAA;EACf,OAAA;EACA,SAAA;EACA,OAAA;EACA,SAAA;EACA,YAAA;EACA,UAAA;AAAA;AAAA,UAGe,eAAA;EACf,MAAA;EACA,MAAA;EACA,KAAA;EACA,UAAA;AAAA;AAAA,iBAiBoB,QAAA,CACpB,GAAA,EAAK,OAAA,EACL,QAAA,UACA,OAAA,EAAS,MAAA,mBACT,IAAA;EAAQ,OAAA;EAAkB,UAAA;AAAA,IACzB,OAAA;AAAA,UAwBc,cAAA;EACf,WAAA,CAAY,KAAA,EAAO,MAAA,oBAA0B,OAAA;EAC7C,aAAA,CAAc,MAAA,YAAkB,OAAA;EAChC,WAAA,CAAY,KAAA;IAAS,IAAA;IAAc,OAAA;EAAA,IAAoB,OAAA;EACvD,aAAA,CAAc,IAAA,UAAc,EAAA,UAAY,SAAA,YAAqB,OAAA;EAC7D,gBAAA,CAAiB,KAAA,UAAe,IAAA,EAAM,MAAA,oBAA0B,OAAA;EAChE,cAAA,CAAe,KAAA,UAAe,OAAA,EAAS,eAAA,GAAkB,OAAA;AAAA;AAAA,iBAG3C,oBAAA,CACd,GAAA,EAAK,OAAA,EACL,KAAA,EAAO,UAAA,cACP,IAAA;EAAQ,SAAA;EAAmB,UAAA;EAAoB,OAAA;EAAkB,UAAA;AAAA,IAChE,cAAA"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { AFSRoot } from "@aigne/afs";
|
|
2
|
+
|
|
3
|
+
//#region src/agent-runners/hooks.d.ts
|
|
4
|
+
interface HookConfig {
|
|
5
|
+
onStart?: string;
|
|
6
|
+
onSuccess?: string;
|
|
7
|
+
onError?: string;
|
|
8
|
+
onHandoff?: string;
|
|
9
|
+
onSkillStart?: string;
|
|
10
|
+
onSkillEnd?: string;
|
|
11
|
+
}
|
|
12
|
+
interface SkillEndPayload {
|
|
13
|
+
status: "ok" | "error";
|
|
14
|
+
result?: unknown;
|
|
15
|
+
error?: string;
|
|
16
|
+
durationMs: number;
|
|
17
|
+
}
|
|
18
|
+
declare function fireHook(afs: AFSRoot, hookPath: string, payload: Record<string, unknown>, opts: {
|
|
19
|
+
session?: string;
|
|
20
|
+
chainDepth?: number;
|
|
21
|
+
}): Promise<void>;
|
|
22
|
+
interface HookDispatcher {
|
|
23
|
+
fireOnStart(input: Record<string, unknown>): Promise<void>;
|
|
24
|
+
fireOnSuccess(result: unknown): Promise<void>;
|
|
25
|
+
fireOnError(error: {
|
|
26
|
+
code: string;
|
|
27
|
+
message: string;
|
|
28
|
+
}): Promise<void>;
|
|
29
|
+
fireOnHandoff(from: string, to: string, iteration?: number): Promise<void>;
|
|
30
|
+
fireOnSkillStart(skill: string, args: Record<string, unknown>): Promise<void>;
|
|
31
|
+
fireOnSkillEnd(skill: string, payload: SkillEndPayload): Promise<void>;
|
|
32
|
+
}
|
|
33
|
+
declare function createHookDispatcher(afs: AFSRoot, hooks: HookConfig | undefined, opts: {
|
|
34
|
+
mountPath: string;
|
|
35
|
+
blockletId: string;
|
|
36
|
+
session?: string;
|
|
37
|
+
chainDepth?: number;
|
|
38
|
+
}): HookDispatcher;
|
|
39
|
+
//#endregion
|
|
40
|
+
export { HookConfig, HookDispatcher, SkillEndPayload, createHookDispatcher, fireHook };
|
|
41
|
+
//# sourceMappingURL=hooks.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.mts","names":[],"sources":["../../src/agent-runners/hooks.ts"],"mappings":";;;UAMiB,UAAA;EACf,OAAA;EACA,SAAA;EACA,OAAA;EACA,SAAA;EACA,YAAA;EACA,UAAA;AAAA;AAAA,UAGe,eAAA;EACf,MAAA;EACA,MAAA;EACA,KAAA;EACA,UAAA;AAAA;AAAA,iBAiBoB,QAAA,CACpB,GAAA,EAAK,OAAA,EACL,QAAA,UACA,OAAA,EAAS,MAAA,mBACT,IAAA;EAAQ,OAAA;EAAkB,UAAA;AAAA,IACzB,OAAA;AAAA,UAwBc,cAAA;EACf,WAAA,CAAY,KAAA,EAAO,MAAA,oBAA0B,OAAA;EAC7C,aAAA,CAAc,MAAA,YAAkB,OAAA;EAChC,WAAA,CAAY,KAAA;IAAS,IAAA;IAAc,OAAA;EAAA,IAAoB,OAAA;EACvD,aAAA,CAAc,IAAA,UAAc,EAAA,UAAY,SAAA,YAAqB,OAAA;EAC7D,gBAAA,CAAiB,KAAA,UAAe,IAAA,EAAM,MAAA,oBAA0B,OAAA;EAChE,cAAA,CAAe,KAAA,UAAe,OAAA,EAAS,eAAA,GAAkB,OAAA;AAAA;AAAA,iBAG3C,oBAAA,CACd,GAAA,EAAK,OAAA,EACL,KAAA,EAAO,UAAA,cACP,IAAA;EAAQ,SAAA;EAAmB,UAAA;EAAoB,OAAA;EAAkB,UAAA;AAAA,IAChE,cAAA"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { joinURL } from "ufo";
|
|
2
|
+
import { makeNsLog } from "@aigne/afs";
|
|
3
|
+
|
|
4
|
+
//#region src/agent-runners/hooks.ts
|
|
5
|
+
const log = makeNsLog("agent-runtime");
|
|
6
|
+
const MAX_HOOK_CHAIN_DEPTH = 3;
|
|
7
|
+
const INTERNAL_FIELD_PREFIX = "_";
|
|
8
|
+
function sanitizePayloadForHook(obj) {
|
|
9
|
+
const sanitized = {};
|
|
10
|
+
for (const [key, value] of Object.entries(obj)) if (!key.startsWith(INTERNAL_FIELD_PREFIX)) sanitized[key] = value;
|
|
11
|
+
return sanitized;
|
|
12
|
+
}
|
|
13
|
+
async function fireHook(afs, hookPath, payload, opts) {
|
|
14
|
+
const chainDepth = opts.chainDepth ?? 0;
|
|
15
|
+
if (chainDepth >= MAX_HOOK_CHAIN_DEPTH) {
|
|
16
|
+
log.warn(`[hooks] Chain depth ${chainDepth} >= ${MAX_HOOK_CHAIN_DEPTH}, skipping: ${hookPath}`);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const cloned = structuredClone(sanitizePayloadForHook(payload));
|
|
20
|
+
const hookSession = opts.session ? `${opts.session}-hook-${Date.now()}` : void 0;
|
|
21
|
+
try {
|
|
22
|
+
await afs.exec(hookPath, {
|
|
23
|
+
...cloned,
|
|
24
|
+
session: hookSession,
|
|
25
|
+
_hook_chain_depth: chainDepth + 1
|
|
26
|
+
}, {});
|
|
27
|
+
} catch (err) {
|
|
28
|
+
log.warn(`[hooks] Hook "${hookPath}" failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function createHookDispatcher(afs, hooks, opts) {
|
|
32
|
+
const { mountPath, blockletId, session, chainDepth = 0 } = opts;
|
|
33
|
+
const resolve = (hookRef) => {
|
|
34
|
+
if (!hookRef) return null;
|
|
35
|
+
if (hookRef.startsWith("/")) return hookRef;
|
|
36
|
+
return joinURL(mountPath, hookRef);
|
|
37
|
+
};
|
|
38
|
+
const fire = async (hookRef, payload) => {
|
|
39
|
+
const path = resolve(hookRef);
|
|
40
|
+
if (!path) return;
|
|
41
|
+
await fireHook(afs, path, payload, {
|
|
42
|
+
session,
|
|
43
|
+
chainDepth
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
return {
|
|
47
|
+
async fireOnStart(input) {
|
|
48
|
+
await fire(hooks?.onStart, {
|
|
49
|
+
event: "on_start",
|
|
50
|
+
blockletId,
|
|
51
|
+
input: sanitizePayloadForHook(input),
|
|
52
|
+
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
53
|
+
});
|
|
54
|
+
},
|
|
55
|
+
async fireOnSuccess(result) {
|
|
56
|
+
await fire(hooks?.onSuccess, {
|
|
57
|
+
event: "on_success",
|
|
58
|
+
blockletId,
|
|
59
|
+
result,
|
|
60
|
+
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
61
|
+
});
|
|
62
|
+
},
|
|
63
|
+
async fireOnError(error) {
|
|
64
|
+
await fire(hooks?.onError, {
|
|
65
|
+
event: "on_error",
|
|
66
|
+
blockletId,
|
|
67
|
+
error,
|
|
68
|
+
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
69
|
+
});
|
|
70
|
+
},
|
|
71
|
+
async fireOnHandoff(from, to, iteration) {
|
|
72
|
+
await fire(hooks?.onHandoff, {
|
|
73
|
+
event: "on_handoff",
|
|
74
|
+
blockletId,
|
|
75
|
+
from,
|
|
76
|
+
to,
|
|
77
|
+
...iteration !== void 0 ? { iteration } : {},
|
|
78
|
+
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
79
|
+
});
|
|
80
|
+
},
|
|
81
|
+
async fireOnSkillStart(skill, args) {
|
|
82
|
+
await fire(hooks?.onSkillStart, {
|
|
83
|
+
event: "on_skill_start",
|
|
84
|
+
blockletId,
|
|
85
|
+
skill,
|
|
86
|
+
args: sanitizePayloadForHook(args),
|
|
87
|
+
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
88
|
+
});
|
|
89
|
+
},
|
|
90
|
+
async fireOnSkillEnd(skill, payload) {
|
|
91
|
+
await fire(hooks?.onSkillEnd, {
|
|
92
|
+
event: "on_skill_end",
|
|
93
|
+
blockletId,
|
|
94
|
+
skill,
|
|
95
|
+
status: payload.status,
|
|
96
|
+
...payload.result !== void 0 ? { result: payload.result } : {},
|
|
97
|
+
...payload.error !== void 0 ? { error: payload.error } : {},
|
|
98
|
+
durationMs: payload.durationMs,
|
|
99
|
+
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
//#endregion
|
|
106
|
+
export { createHookDispatcher, fireHook };
|
|
107
|
+
//# sourceMappingURL=hooks.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.mjs","names":[],"sources":["../../src/agent-runners/hooks.ts"],"sourcesContent":["import type { AFSRoot } from \"@aigne/afs\";\nimport { makeNsLog } from \"@aigne/afs\";\nimport { joinURL } from \"ufo\";\n\nconst log = makeNsLog(\"agent-runtime\");\n\nexport interface HookConfig {\n onStart?: string;\n onSuccess?: string;\n onError?: string;\n onHandoff?: string;\n onSkillStart?: string;\n onSkillEnd?: string;\n}\n\nexport interface SkillEndPayload {\n status: \"ok\" | \"error\";\n result?: unknown;\n error?: string;\n durationMs: number;\n}\n\nconst MAX_HOOK_CHAIN_DEPTH = 3;\n\nconst INTERNAL_FIELD_PREFIX = \"_\";\n\nfunction sanitizePayloadForHook(obj: Record<string, unknown>): Record<string, unknown> {\n const sanitized: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n if (!key.startsWith(INTERNAL_FIELD_PREFIX)) {\n sanitized[key] = value;\n }\n }\n return sanitized;\n}\n\nexport async function fireHook(\n afs: AFSRoot,\n hookPath: string,\n payload: Record<string, unknown>,\n opts: { session?: string; chainDepth?: number },\n): Promise<void> {\n const chainDepth = opts.chainDepth ?? 0;\n\n if (chainDepth >= MAX_HOOK_CHAIN_DEPTH) {\n log.warn(`[hooks] Chain depth ${chainDepth} >= ${MAX_HOOK_CHAIN_DEPTH}, skipping: ${hookPath}`);\n return;\n }\n\n const cloned = structuredClone(sanitizePayloadForHook(payload));\n const hookSession = opts.session ? `${opts.session}-hook-${Date.now()}` : undefined;\n\n try {\n await afs.exec!(\n hookPath,\n { ...cloned, session: hookSession, _hook_chain_depth: chainDepth + 1 },\n {},\n );\n } catch (err) {\n log.warn(\n `[hooks] Hook \"${hookPath}\" failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n}\n\nexport interface HookDispatcher {\n fireOnStart(input: Record<string, unknown>): Promise<void>;\n fireOnSuccess(result: unknown): Promise<void>;\n fireOnError(error: { code: string; message: string }): Promise<void>;\n fireOnHandoff(from: string, to: string, iteration?: number): Promise<void>;\n fireOnSkillStart(skill: string, args: Record<string, unknown>): Promise<void>;\n fireOnSkillEnd(skill: string, payload: SkillEndPayload): Promise<void>;\n}\n\nexport function createHookDispatcher(\n afs: AFSRoot,\n hooks: HookConfig | undefined,\n opts: { mountPath: string; blockletId: string; session?: string; chainDepth?: number },\n): HookDispatcher {\n const { mountPath, blockletId, session, chainDepth = 0 } = opts;\n\n const resolve = (hookRef: string | undefined): string | null => {\n if (!hookRef) return null;\n if (hookRef.startsWith(\"/\")) return hookRef;\n return joinURL(mountPath, hookRef);\n };\n\n const fire = async (hookRef: string | undefined, payload: Record<string, unknown>) => {\n const path = resolve(hookRef);\n if (!path) return;\n await fireHook(afs, path, payload, { session, chainDepth });\n };\n\n return {\n async fireOnStart(input) {\n await fire(hooks?.onStart, {\n event: \"on_start\",\n blockletId,\n input: sanitizePayloadForHook(input),\n ts: new Date().toISOString(),\n });\n },\n async fireOnSuccess(result) {\n await fire(hooks?.onSuccess, {\n event: \"on_success\",\n blockletId,\n result: result as Record<string, unknown>,\n ts: new Date().toISOString(),\n });\n },\n async fireOnError(error) {\n await fire(hooks?.onError, {\n event: \"on_error\",\n blockletId,\n error,\n ts: new Date().toISOString(),\n });\n },\n async fireOnHandoff(from, to, iteration?) {\n await fire(hooks?.onHandoff, {\n event: \"on_handoff\",\n blockletId,\n from,\n to,\n ...(iteration !== undefined ? { iteration } : {}),\n ts: new Date().toISOString(),\n });\n },\n async fireOnSkillStart(skill, args) {\n await fire(hooks?.onSkillStart, {\n event: \"on_skill_start\",\n blockletId,\n skill,\n args: sanitizePayloadForHook(args),\n ts: new Date().toISOString(),\n });\n },\n async fireOnSkillEnd(skill, payload) {\n await fire(hooks?.onSkillEnd, {\n event: \"on_skill_end\",\n blockletId,\n skill,\n status: payload.status,\n ...(payload.result !== undefined ? { result: payload.result } : {}),\n ...(payload.error !== undefined ? { error: payload.error } : {}),\n durationMs: payload.durationMs,\n ts: new Date().toISOString(),\n });\n },\n };\n}\n"],"mappings":";;;;AAIA,MAAM,MAAM,UAAU,gBAAgB;AAkBtC,MAAM,uBAAuB;AAE7B,MAAM,wBAAwB;AAE9B,SAAS,uBAAuB,KAAuD;CACrF,MAAM,YAAqC,EAAE;AAC7C,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,IAAI,CAC5C,KAAI,CAAC,IAAI,WAAW,sBAAsB,CACxC,WAAU,OAAO;AAGrB,QAAO;;AAGT,eAAsB,SACpB,KACA,UACA,SACA,MACe;CACf,MAAM,aAAa,KAAK,cAAc;AAEtC,KAAI,cAAc,sBAAsB;AACtC,MAAI,KAAK,uBAAuB,WAAW,MAAM,qBAAqB,cAAc,WAAW;AAC/F;;CAGF,MAAM,SAAS,gBAAgB,uBAAuB,QAAQ,CAAC;CAC/D,MAAM,cAAc,KAAK,UAAU,GAAG,KAAK,QAAQ,QAAQ,KAAK,KAAK,KAAK;AAE1E,KAAI;AACF,QAAM,IAAI,KACR,UACA;GAAE,GAAG;GAAQ,SAAS;GAAa,mBAAmB,aAAa;GAAG,EACtE,EAAE,CACH;UACM,KAAK;AACZ,MAAI,KACF,iBAAiB,SAAS,YAAY,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GACvF;;;AAaL,SAAgB,qBACd,KACA,OACA,MACgB;CAChB,MAAM,EAAE,WAAW,YAAY,SAAS,aAAa,MAAM;CAE3D,MAAM,WAAW,YAA+C;AAC9D,MAAI,CAAC,QAAS,QAAO;AACrB,MAAI,QAAQ,WAAW,IAAI,CAAE,QAAO;AACpC,SAAO,QAAQ,WAAW,QAAQ;;CAGpC,MAAM,OAAO,OAAO,SAA6B,YAAqC;EACpF,MAAM,OAAO,QAAQ,QAAQ;AAC7B,MAAI,CAAC,KAAM;AACX,QAAM,SAAS,KAAK,MAAM,SAAS;GAAE;GAAS;GAAY,CAAC;;AAG7D,QAAO;EACL,MAAM,YAAY,OAAO;AACvB,SAAM,KAAK,OAAO,SAAS;IACzB,OAAO;IACP;IACA,OAAO,uBAAuB,MAAM;IACpC,qBAAI,IAAI,MAAM,EAAC,aAAa;IAC7B,CAAC;;EAEJ,MAAM,cAAc,QAAQ;AAC1B,SAAM,KAAK,OAAO,WAAW;IAC3B,OAAO;IACP;IACQ;IACR,qBAAI,IAAI,MAAM,EAAC,aAAa;IAC7B,CAAC;;EAEJ,MAAM,YAAY,OAAO;AACvB,SAAM,KAAK,OAAO,SAAS;IACzB,OAAO;IACP;IACA;IACA,qBAAI,IAAI,MAAM,EAAC,aAAa;IAC7B,CAAC;;EAEJ,MAAM,cAAc,MAAM,IAAI,WAAY;AACxC,SAAM,KAAK,OAAO,WAAW;IAC3B,OAAO;IACP;IACA;IACA;IACA,GAAI,cAAc,SAAY,EAAE,WAAW,GAAG,EAAE;IAChD,qBAAI,IAAI,MAAM,EAAC,aAAa;IAC7B,CAAC;;EAEJ,MAAM,iBAAiB,OAAO,MAAM;AAClC,SAAM,KAAK,OAAO,cAAc;IAC9B,OAAO;IACP;IACA;IACA,MAAM,uBAAuB,KAAK;IAClC,qBAAI,IAAI,MAAM,EAAC,aAAa;IAC7B,CAAC;;EAEJ,MAAM,eAAe,OAAO,SAAS;AACnC,SAAM,KAAK,OAAO,YAAY;IAC5B,OAAO;IACP;IACA;IACA,QAAQ,QAAQ;IAChB,GAAI,QAAQ,WAAW,SAAY,EAAE,QAAQ,QAAQ,QAAQ,GAAG,EAAE;IAClE,GAAI,QAAQ,UAAU,SAAY,EAAE,OAAO,QAAQ,OAAO,GAAG,EAAE;IAC/D,YAAY,QAAQ;IACpB,qBAAI,IAAI,MAAM,EAAC,aAAa;IAC7B,CAAC;;EAEL"}
|