@inhuman.tools/turn 0.2.0 → 0.3.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/README.md +38 -0
- package/dist/agent-calls/acceptance.d.ts +1 -1
- package/dist/agent-calls/acceptance.d.ts.map +1 -1
- package/dist/agent-calls/acceptance.js +1 -1
- package/dist/agent-calls/acceptance.js.map +1 -1
- package/dist/agent-calls/callbacks.d.ts +1 -1
- package/dist/agent-calls/callbacks.d.ts.map +1 -1
- package/dist/agent-calls/callbacks.js +1 -1
- package/dist/agent-calls/callbacks.js.map +1 -1
- package/dist/agent-calls/delivery.d.ts +1 -1
- package/dist/agent-calls/delivery.d.ts.map +1 -1
- package/dist/agent-calls/delivery.js +1 -1
- package/dist/agent-calls/delivery.js.map +1 -1
- package/dist/agent-calls/operator.d.ts +1 -1
- package/dist/agent-calls/operator.d.ts.map +1 -1
- package/dist/agent-calls/operator.js +1 -1
- package/dist/agent-calls/operator.js.map +1 -1
- package/dist/agent-calls/runtime.d.ts +4 -2
- package/dist/agent-calls/runtime.d.ts.map +1 -1
- package/dist/agent-calls/runtime.js +17 -11
- package/dist/agent-calls/runtime.js.map +1 -1
- package/dist/agent-calls/types.d.ts +1 -1
- package/dist/agent-calls/types.d.ts.map +1 -1
- package/dist/context/compact-floors.d.ts +1 -1
- package/dist/context/compact-floors.d.ts.map +1 -1
- package/dist/context/compact.d.ts +1 -1
- package/dist/context/compact.d.ts.map +1 -1
- package/dist/context/compact.js +5 -4
- package/dist/context/compact.js.map +1 -1
- package/dist/context/history.d.ts +1 -1
- package/dist/context/history.d.ts.map +1 -1
- package/dist/context/history.js +35 -3
- package/dist/context/history.js.map +1 -1
- package/dist/context/retention/defaults.js +1 -1
- package/dist/context/retention/defaults.js.map +1 -1
- package/dist/context/retention/resolve.js +1 -1
- package/dist/context/retention/resolve.js.map +1 -1
- package/dist/context/retention/schema.js +1 -1
- package/dist/context/retention/schema.js.map +1 -1
- package/dist/context/retention/stamp.d.ts +1 -1
- package/dist/context/retention/stamp.d.ts.map +1 -1
- package/dist/context/retention/stamp.js +5 -2
- package/dist/context/retention/stamp.js.map +1 -1
- package/dist/context/retention/step.d.ts +1 -1
- package/dist/context/retention/step.d.ts.map +1 -1
- package/dist/context/retention/step.js +7 -4
- package/dist/context/retention/step.js.map +1 -1
- package/dist/context/retention/view.d.ts +1 -1
- package/dist/context/retention/view.d.ts.map +1 -1
- package/dist/context/retention/view.js +1 -1
- package/dist/context/retention/view.js.map +1 -1
- package/dist/context/spawn-history.d.ts +13 -0
- package/dist/context/spawn-history.d.ts.map +1 -0
- package/dist/context/spawn-history.js +82 -0
- package/dist/context/spawn-history.js.map +1 -0
- package/dist/context/squeeze.d.ts +1 -1
- package/dist/context/squeeze.d.ts.map +1 -1
- package/dist/context/squeeze.js +1 -1
- package/dist/context/squeeze.js.map +1 -1
- package/dist/context/tools.d.ts +2 -2
- package/dist/context/tools.d.ts.map +1 -1
- package/dist/context/tools.js +2 -2
- package/dist/context/tools.js.map +1 -1
- package/dist/context/transcript.d.ts +3 -1
- package/dist/context/transcript.d.ts.map +1 -1
- package/dist/context/transcript.js +17 -4
- package/dist/context/transcript.js.map +1 -1
- package/dist/policy-processor/classifier.d.ts.map +1 -1
- package/dist/policy-processor/classifier.js +3 -1
- package/dist/policy-processor/classifier.js.map +1 -1
- package/dist/policy-processor/scope.d.ts +1 -0
- package/dist/policy-processor/scope.d.ts.map +1 -1
- package/dist/policy-processor/scope.js +9 -2
- package/dist/policy-processor/scope.js.map +1 -1
- package/dist/policy-processor/unattended-guard.js +8 -2
- package/dist/policy-processor/unattended-guard.js.map +1 -1
- package/dist/resources/compact-assets.d.ts +5 -0
- package/dist/resources/compact-assets.d.ts.map +1 -0
- package/dist/resources/compact-assets.js +6 -0
- package/dist/resources/compact-assets.js.map +1 -0
- package/dist/resources/compact-snapshot.d.ts +21 -0
- package/dist/resources/compact-snapshot.d.ts.map +1 -0
- package/dist/resources/compact-snapshot.js +44 -0
- package/dist/resources/compact-snapshot.js.map +1 -0
- package/dist/resources/index.d.ts +6 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +19 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/resources/module-bundle.d.ts +16 -0
- package/dist/resources/module-bundle.d.ts.map +1 -0
- package/dist/resources/module-bundle.js +78 -0
- package/dist/resources/module-bundle.js.map +1 -0
- package/dist/runtime/ambient-compact.d.ts +38 -0
- package/dist/runtime/ambient-compact.d.ts.map +1 -0
- package/dist/runtime/ambient-compact.js +123 -0
- package/dist/runtime/ambient-compact.js.map +1 -0
- package/dist/runtime/index.d.ts +9 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +8 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/ports.d.ts +33 -0
- package/dist/runtime/ports.d.ts.map +1 -0
- package/dist/runtime/ports.js +2 -0
- package/dist/runtime/ports.js.map +1 -0
- package/dist/runtime/prompt-message-of.d.ts +4 -0
- package/dist/runtime/prompt-message-of.d.ts.map +1 -0
- package/dist/runtime/prompt-message-of.js +8 -0
- package/dist/runtime/prompt-message-of.js.map +1 -0
- package/dist/runtime/re-act-loop-intent-detected-trigger.d.ts +32 -0
- package/dist/runtime/re-act-loop-intent-detected-trigger.d.ts.map +1 -0
- package/dist/runtime/re-act-loop-intent-detected-trigger.js +132 -0
- package/dist/runtime/re-act-loop-intent-detected-trigger.js.map +1 -0
- package/dist/runtime/round-boundary.d.ts +13 -0
- package/dist/runtime/round-boundary.d.ts.map +1 -0
- package/dist/runtime/round-boundary.js +210 -0
- package/dist/runtime/round-boundary.js.map +1 -0
- package/dist/runtime/round-stop.d.ts +9 -0
- package/dist/runtime/round-stop.d.ts.map +1 -0
- package/dist/runtime/round-stop.js +19 -0
- package/dist/runtime/round-stop.js.map +1 -0
- package/dist/runtime/tool-call.d.ts +4 -0
- package/dist/runtime/tool-call.d.ts.map +1 -0
- package/dist/runtime/tool-call.js +8 -0
- package/dist/runtime/tool-call.js.map +1 -0
- package/dist/runtime/turn-iterator.d.ts +32 -0
- package/dist/runtime/turn-iterator.d.ts.map +1 -0
- package/dist/runtime/turn-iterator.js +251 -0
- package/dist/runtime/turn-iterator.js.map +1 -0
- package/dist/runtime/turn-resolvers.d.ts +17 -0
- package/dist/runtime/turn-resolvers.d.ts.map +1 -0
- package/dist/runtime/turn-resolvers.js +29 -0
- package/dist/runtime/turn-resolvers.js.map +1 -0
- package/dist/session/cancel.d.ts +4 -1
- package/dist/session/cancel.d.ts.map +1 -1
- package/dist/session/cancel.js +10 -2
- package/dist/session/cancel.js.map +1 -1
- package/dist/session/commands.d.ts +1 -1
- package/dist/session/commands.d.ts.map +1 -1
- package/dist/session/commands.js +4 -2
- package/dist/session/commands.js.map +1 -1
- package/dist/session/compact-actor.d.ts +12 -5
- package/dist/session/compact-actor.d.ts.map +1 -1
- package/dist/session/compact-actor.js +64 -12
- package/dist/session/compact-actor.js.map +1 -1
- package/dist/session/compact-env.d.ts +31 -5
- package/dist/session/compact-env.d.ts.map +1 -1
- package/dist/session/compact-env.js +23 -13
- package/dist/session/compact-env.js.map +1 -1
- package/dist/session/compact.d.ts +6 -3
- package/dist/session/compact.d.ts.map +1 -1
- package/dist/session/compact.js.map +1 -1
- package/dist/session/index.d.ts +2 -2
- package/dist/session/index.d.ts.map +1 -1
- package/dist/session/index.js +2 -2
- package/dist/session/index.js.map +1 -1
- package/dist/session/park.d.ts +1 -1
- package/dist/session/park.d.ts.map +1 -1
- package/dist/session/park.js +1 -1
- package/dist/session/park.js.map +1 -1
- package/dist/session/side-channel-reminder.d.ts +1 -1
- package/dist/session/side-channel-reminder.d.ts.map +1 -1
- package/dist/session/side-channel-reminder.js +1 -1
- package/dist/session/side-channel-reminder.js.map +1 -1
- package/dist/session/types.d.ts +1 -1
- package/dist/session/types.d.ts.map +1 -1
- package/dist/session-runtime/ask-line.d.ts +7 -0
- package/dist/session-runtime/ask-line.d.ts.map +1 -0
- package/dist/session-runtime/ask-line.js +36 -0
- package/dist/session-runtime/ask-line.js.map +1 -0
- package/dist/session-runtime/durability.d.ts +25 -0
- package/dist/session-runtime/durability.d.ts.map +1 -0
- package/dist/session-runtime/durability.js +18 -0
- package/dist/session-runtime/durability.js.map +1 -0
- package/dist/session-runtime/effects.d.ts +53 -0
- package/dist/session-runtime/effects.d.ts.map +1 -0
- package/dist/session-runtime/effects.js +18 -0
- package/dist/session-runtime/effects.js.map +1 -0
- package/dist/session-runtime/index.d.ts +8 -0
- package/dist/session-runtime/index.d.ts.map +1 -0
- package/dist/session-runtime/index.js +8 -0
- package/dist/session-runtime/index.js.map +1 -0
- package/dist/session-runtime/interrupt.d.ts +3 -0
- package/dist/session-runtime/interrupt.d.ts.map +1 -0
- package/dist/session-runtime/interrupt.js +33 -0
- package/dist/session-runtime/interrupt.js.map +1 -0
- package/dist/session-runtime/recovery.d.ts +17 -0
- package/dist/session-runtime/recovery.d.ts.map +1 -0
- package/dist/session-runtime/recovery.js +119 -0
- package/dist/session-runtime/recovery.js.map +1 -0
- package/dist/session-runtime/runtime.d.ts +50 -0
- package/dist/session-runtime/runtime.d.ts.map +1 -0
- package/dist/session-runtime/runtime.js +533 -0
- package/dist/session-runtime/runtime.js.map +1 -0
- package/dist/session-runtime/summary.d.ts +26 -0
- package/dist/session-runtime/summary.d.ts.map +1 -0
- package/dist/session-runtime/summary.js +33 -0
- package/dist/session-runtime/summary.js.map +1 -0
- package/dist/tool-catalog/bindings.d.ts +6 -0
- package/dist/tool-catalog/bindings.d.ts.map +1 -0
- package/dist/tool-catalog/bindings.js +37 -0
- package/dist/tool-catalog/bindings.js.map +1 -0
- package/dist/tool-catalog/catalog.d.ts +1 -3
- package/dist/tool-catalog/catalog.d.ts.map +1 -1
- package/dist/tool-catalog/catalog.js +6 -34
- package/dist/tool-catalog/catalog.js.map +1 -1
- package/dist/tool-catalog/types.d.ts +8 -0
- package/dist/tool-catalog/types.d.ts.map +1 -1
- package/dist/tool-catalog/types.js.map +1 -1
- package/dist/tool-runtime/approval/approved.d.ts +1 -1
- package/dist/tool-runtime/approval/approved.d.ts.map +1 -1
- package/dist/tool-runtime/approval/approved.js +1 -1
- package/dist/tool-runtime/approval/approved.js.map +1 -1
- package/dist/tool-runtime/handler.d.ts.map +1 -1
- package/dist/tool-runtime/handler.js +291 -237
- package/dist/tool-runtime/handler.js.map +1 -1
- package/dist/tool-runtime/run-system-tool.d.ts +1 -0
- package/dist/tool-runtime/run-system-tool.d.ts.map +1 -1
- package/dist/tool-runtime/run-system-tool.js +30 -10
- package/dist/tool-runtime/run-system-tool.js.map +1 -1
- package/dist/tool-runtime/worker-tools.d.ts.map +1 -1
- package/dist/tool-runtime/worker-tools.js +2 -2
- package/dist/tool-runtime/worker-tools.js.map +1 -1
- package/package.json +29 -16
- package/src/agent-calls/acceptance.ts +1 -1
- package/src/agent-calls/callbacks.ts +1 -1
- package/src/agent-calls/delivery.ts +1 -1
- package/src/agent-calls/operator.ts +7 -1
- package/src/agent-calls/runtime.ts +23 -11
- package/src/agent-calls/types.ts +1 -1
- package/src/context/compact-floors.ts +1 -1
- package/src/context/compact.ts +4 -5
- package/src/context/history.ts +46 -4
- package/src/context/retention/defaults.ts +1 -1
- package/src/context/retention/resolve.ts +1 -1
- package/src/context/retention/schema.ts +1 -1
- package/src/context/retention/stamp.ts +7 -2
- package/src/context/retention/step.ts +7 -4
- package/src/context/retention/view.ts +1 -1
- package/src/context/spawn-history.ts +95 -0
- package/src/context/squeeze.ts +1 -1
- package/src/context/tools.ts +3 -2
- package/src/context/transcript.ts +15 -4
- package/src/policy-processor/README.md +1 -1
- package/src/policy-processor/classifier.ts +3 -1
- package/src/policy-processor/scope.ts +7 -2
- package/src/policy-processor/unattended-guard.ts +5 -2
- package/src/resources/compact-assets.ts +9 -0
- package/src/resources/compact-snapshot.ts +51 -0
- package/src/resources/index.ts +27 -0
- package/src/resources/module-bundle.ts +90 -0
- package/src/runtime/ambient-compact.ts +147 -0
- package/src/runtime/index.ts +17 -0
- package/src/runtime/ports.ts +28 -0
- package/src/runtime/prompt-message-of.ts +14 -0
- package/src/runtime/re-act-loop-intent-detected-trigger.ts +177 -0
- package/src/runtime/round-boundary.ts +248 -0
- package/src/runtime/round-stop.ts +24 -0
- package/src/runtime/tool-call.ts +10 -0
- package/src/runtime/turn-iterator.ts +312 -0
- package/src/runtime/turn-resolvers.ts +43 -0
- package/src/session/cancel.ts +11 -3
- package/src/session/commands.ts +5 -2
- package/src/session/compact-actor.ts +76 -16
- package/src/session/compact-env.ts +27 -18
- package/src/session/compact.ts +8 -3
- package/src/session/index.ts +7 -2
- package/src/session/park.ts +7 -1
- package/src/session/side-channel-reminder.ts +1 -1
- package/src/session/types.ts +1 -1
- package/src/session-runtime/ask-line.ts +39 -0
- package/src/session-runtime/durability.ts +41 -0
- package/src/session-runtime/effects.ts +35 -0
- package/src/session-runtime/index.ts +19 -0
- package/src/session-runtime/interrupt.ts +34 -0
- package/src/session-runtime/recovery.ts +145 -0
- package/src/session-runtime/runtime.ts +535 -0
- package/src/session-runtime/summary.ts +67 -0
- package/src/tool-catalog/bindings.ts +37 -0
- package/src/tool-catalog/catalog.ts +6 -31
- package/src/tool-catalog/types.ts +9 -0
- package/src/tool-runtime/approval/approved.ts +1 -1
- package/src/tool-runtime/handler.ts +40 -24
- package/src/tool-runtime/run-system-tool.ts +27 -11
- package/src/tool-runtime/worker-tools.ts +2 -2
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AskAgentSpec,
|
|
3
|
+
latestUserPrompt,
|
|
4
|
+
outgoingAgentRelations,
|
|
5
|
+
SessionTurn,
|
|
6
|
+
type AgentNature,
|
|
7
|
+
type SessionUnfinished,
|
|
8
|
+
type SessionPlexus,
|
|
9
|
+
type SessionRoot,
|
|
10
|
+
} from "@inhuman.tools/harness-model/session";
|
|
11
|
+
import { comparer, reaction } from "mobx";
|
|
12
|
+
|
|
13
|
+
import { glanceAskLine } from "./ask-line.js";
|
|
14
|
+
|
|
15
|
+
export type SessionSummary = {
|
|
16
|
+
readonly title: string;
|
|
17
|
+
readonly recipeScope: AgentNature;
|
|
18
|
+
readonly specName: string;
|
|
19
|
+
readonly resident: boolean;
|
|
20
|
+
readonly keepAlive: boolean;
|
|
21
|
+
readonly oneShot: boolean;
|
|
22
|
+
readonly model: string;
|
|
23
|
+
readonly status: string;
|
|
24
|
+
readonly midMotion: boolean;
|
|
25
|
+
readonly openTurn: boolean;
|
|
26
|
+
readonly openToolCount: number;
|
|
27
|
+
readonly periodArmed: boolean;
|
|
28
|
+
readonly openCallbackCount: number;
|
|
29
|
+
readonly asking: boolean;
|
|
30
|
+
readonly unfinished: SessionUnfinished;
|
|
31
|
+
readonly lastPrompt: string;
|
|
32
|
+
readonly askLine: string;
|
|
33
|
+
readonly questionLine: string;
|
|
34
|
+
readonly path: string;
|
|
35
|
+
readonly calls: ReturnType<typeof outgoingAgentRelations>;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export function sessionSummary(root: SessionRoot): SessionSummary {
|
|
39
|
+
const spec = root.agent.spec;
|
|
40
|
+
const unfinished = root.unfinished;
|
|
41
|
+
return {
|
|
42
|
+
title: root.title,
|
|
43
|
+
recipeScope: spec.recipeScope,
|
|
44
|
+
specName: spec.name,
|
|
45
|
+
resident: spec.resident,
|
|
46
|
+
keepAlive: spec.keepAlive,
|
|
47
|
+
oneShot: spec instanceof AskAgentSpec,
|
|
48
|
+
model: (root.kvs.model ?? "").trim(),
|
|
49
|
+
status: root.turnDescription,
|
|
50
|
+
midMotion: root.midMotion,
|
|
51
|
+
openTurn: root.openTurn,
|
|
52
|
+
openToolCount: root.openToolCount,
|
|
53
|
+
periodArmed: root.periodArmed,
|
|
54
|
+
openCallbackCount: root.openCallbackCount,
|
|
55
|
+
asking: root.asking,
|
|
56
|
+
unfinished,
|
|
57
|
+
lastPrompt: latestUserPrompt(root.head),
|
|
58
|
+
askLine: unfinished === "ask" ? glanceAskLine(root.head?.approvalHead ?? null) : "",
|
|
59
|
+
questionLine: unfinished === "question" && root.head instanceof SessionTurn ? root.head.questionLine : "",
|
|
60
|
+
path: root.path,
|
|
61
|
+
calls: outgoingAgentRelations(root),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function observeSessionSummary(session: SessionPlexus, publish: (summary: SessionSummary) => void): () => void {
|
|
66
|
+
return reaction(() => sessionSummary(session.root), publish, { equals: comparer.structural, fireImmediately: true });
|
|
67
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import invariant from "tiny-invariant";
|
|
2
|
+
|
|
3
|
+
import type { KernelToolCatalog } from "./catalog.js";
|
|
4
|
+
|
|
5
|
+
const catalogsByRoot = new WeakMap<object, KernelToolCatalog>();
|
|
6
|
+
const rootsByCatalog = new WeakMap<KernelToolCatalog, Set<object>>();
|
|
7
|
+
|
|
8
|
+
/** Bind a session (or test) root to a kernel catalog. */
|
|
9
|
+
export function bindSessionCatalog(root: object, catalog: KernelToolCatalog): void {
|
|
10
|
+
invariant(!catalog.disposed, "bindSessionCatalog: catalog is disposed");
|
|
11
|
+
const prior = catalogsByRoot.get(root);
|
|
12
|
+
if (prior != null && prior !== catalog) rootsByCatalog.get(prior)?.delete(root);
|
|
13
|
+
catalogsByRoot.set(root, catalog);
|
|
14
|
+
let roots = rootsByCatalog.get(catalog);
|
|
15
|
+
if (roots == null) {
|
|
16
|
+
roots = new Set();
|
|
17
|
+
rootsByCatalog.set(catalog, roots);
|
|
18
|
+
}
|
|
19
|
+
roots.add(root);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function catalogOf(root: object | undefined | null): KernelToolCatalog | undefined {
|
|
23
|
+
if (root == null) return undefined;
|
|
24
|
+
const catalog = catalogsByRoot.get(root);
|
|
25
|
+
if (catalog == null || catalog.disposed) return undefined;
|
|
26
|
+
return catalog;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function releaseCatalogRoots(catalog: KernelToolCatalog): void {
|
|
30
|
+
const roots = rootsByCatalog.get(catalog);
|
|
31
|
+
if (roots == null) return;
|
|
32
|
+
for (const root of roots) {
|
|
33
|
+
if (catalogsByRoot.get(root) === catalog) catalogsByRoot.delete(root);
|
|
34
|
+
}
|
|
35
|
+
roots.clear();
|
|
36
|
+
rootsByCatalog.delete(catalog);
|
|
37
|
+
}
|
|
@@ -12,9 +12,12 @@ import { DisposableClass, disposableGuard, prompt, type SystemPrompt } from "@in
|
|
|
12
12
|
import { action, computed, observable } from "mobx";
|
|
13
13
|
import invariant from "tiny-invariant";
|
|
14
14
|
|
|
15
|
+
import { releaseCatalogRoots } from "./bindings.js";
|
|
15
16
|
import { type CatalogRecipe, dedupeRecipes, findRecipe, invokeCyclePath } from "./recipes.js";
|
|
16
17
|
import { type CatalogEntry, PLAIN_WORKER_HOST, type WorkerToolHost } from "./types.js";
|
|
17
18
|
|
|
19
|
+
export { bindSessionCatalog, catalogOf } from "./bindings.js";
|
|
20
|
+
|
|
18
21
|
export type CompiledPluginContribution = {
|
|
19
22
|
readonly compiledRecipes: readonly CatalogRecipe[];
|
|
20
23
|
};
|
|
@@ -224,21 +227,16 @@ export class KernelToolCatalog extends DisposableClass {
|
|
|
224
227
|
this.behaviorEntries = [];
|
|
225
228
|
this.connectionHost = undefined;
|
|
226
229
|
this.botRevisions = new Map();
|
|
227
|
-
|
|
228
|
-
if (roots == null) return;
|
|
229
|
-
for (const root of roots) {
|
|
230
|
-
if (catalogsByRoot.get(root) === this) catalogsByRoot.delete(root);
|
|
231
|
-
}
|
|
232
|
-
roots.clear();
|
|
233
|
-
rootsByCatalog.delete(this);
|
|
230
|
+
releaseCatalogRoots(this);
|
|
234
231
|
}
|
|
235
232
|
}
|
|
236
233
|
|
|
237
234
|
export function catalogTriggersReactLoop(catalog: KernelToolCatalog, wire: string): boolean {
|
|
238
235
|
const entry = catalog.catalogEntry(wire);
|
|
236
|
+
if (entry?.continuation != null) return entry.continuation.kind === "observation";
|
|
239
237
|
if (entry?.triggersReactLoop === false) return false;
|
|
240
238
|
if (entry?.triggersReactLoop === true) return true;
|
|
241
|
-
return
|
|
239
|
+
return true;
|
|
242
240
|
}
|
|
243
241
|
|
|
244
242
|
export function requireCatalog<T extends KernelToolCatalog>(catalog: T | undefined, what: string): T {
|
|
@@ -246,8 +244,6 @@ export function requireCatalog<T extends KernelToolCatalog>(catalog: T | undefin
|
|
|
246
244
|
return catalog;
|
|
247
245
|
}
|
|
248
246
|
|
|
249
|
-
const catalogsByRoot = new WeakMap<object, KernelToolCatalog>();
|
|
250
|
-
const rootsByCatalog = new WeakMap<KernelToolCatalog, Set<object>>();
|
|
251
247
|
const behaviorEntriesByRoot = observable.map<object, readonly CatalogEntry[]>(new Map(), { deep: false });
|
|
252
248
|
|
|
253
249
|
/** Tools the session's pinned behavior declares. Replaced whenever the pin reattaches. */
|
|
@@ -259,24 +255,3 @@ export const bindBehaviorEntries = action((root: object, entries: readonly Catal
|
|
|
259
255
|
export function behaviorEntriesOf(root: object | undefined | null): readonly CatalogEntry[] {
|
|
260
256
|
return root == null ? [] : (behaviorEntriesByRoot.get(root) ?? []);
|
|
261
257
|
}
|
|
262
|
-
|
|
263
|
-
/** Bind a session (or test) root to a kernel catalog. */
|
|
264
|
-
export function bindSessionCatalog(root: object, catalog: KernelToolCatalog): void {
|
|
265
|
-
invariant(!catalog.disposed, "bindSessionCatalog: catalog is disposed");
|
|
266
|
-
const prior = catalogsByRoot.get(root);
|
|
267
|
-
if (prior != null && prior !== catalog) rootsByCatalog.get(prior)?.delete(root);
|
|
268
|
-
catalogsByRoot.set(root, catalog);
|
|
269
|
-
let roots = rootsByCatalog.get(catalog);
|
|
270
|
-
if (roots == null) {
|
|
271
|
-
roots = new Set();
|
|
272
|
-
rootsByCatalog.set(catalog, roots);
|
|
273
|
-
}
|
|
274
|
-
roots.add(root);
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
export function catalogOf(root: object | undefined | null): KernelToolCatalog | undefined {
|
|
278
|
-
if (root == null) return undefined;
|
|
279
|
-
const catalog = catalogsByRoot.get(root);
|
|
280
|
-
if (catalog == null || catalog.disposed) return undefined;
|
|
281
|
-
return catalog;
|
|
282
|
-
}
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
* Catalog row identity. wireName is a model-edge projection — never durable
|
|
3
3
|
* routing. Connection tools route by connectionKey + serverToolName.
|
|
4
4
|
*/
|
|
5
|
+
import type { ToolContinuation } from "@inhuman.tools/harness-commons";
|
|
6
|
+
|
|
5
7
|
import type { RuleInput } from "../context/retention/schema.js";
|
|
6
8
|
|
|
7
9
|
export type CatalogSource =
|
|
@@ -23,6 +25,11 @@ export type CatalogExecute = (
|
|
|
23
25
|
catalog?: unknown;
|
|
24
26
|
onPriorContent?: (text: string | null) => void;
|
|
25
27
|
invocation?: unknown;
|
|
28
|
+
storage?: {
|
|
29
|
+
readonly session: unknown;
|
|
30
|
+
readonly invocation: unknown;
|
|
31
|
+
propose(action: unknown): void;
|
|
32
|
+
};
|
|
26
33
|
shellTailBytes?: number;
|
|
27
34
|
onTail?: (frame: { readonly text: string; readonly totalBytes: number }) => void;
|
|
28
35
|
},
|
|
@@ -62,6 +69,8 @@ export type CatalogEntry = {
|
|
|
62
69
|
*/
|
|
63
70
|
readonly execute?: CatalogExecute;
|
|
64
71
|
readonly packMeta?: PackToolMeta;
|
|
72
|
+
readonly continuation?: ToolContinuation;
|
|
73
|
+
/** @deprecated Use continuation; explicit policy takes precedence. */
|
|
65
74
|
readonly triggersReactLoop?: boolean;
|
|
66
75
|
/** Skips the license floor. Copied from the tool that declared it. */
|
|
67
76
|
readonly isSideChannel?: boolean;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* in harness-model. Cancel writes `cancelled`, not `approved`. Human
|
|
4
4
|
* `approvalComment` is a `TurnApprovalNoteChunk`, not this receipt.
|
|
5
5
|
*/
|
|
6
|
-
import { ApprovableJob, applyToolOutcomeReceipt, cancelUnstarted } from "@inhuman.tools/harness-model";
|
|
6
|
+
import { ApprovableJob, applyToolOutcomeReceipt, cancelUnstarted } from "@inhuman.tools/harness-model/session";
|
|
7
7
|
import { action } from "mobx";
|
|
8
8
|
|
|
9
9
|
export function stampToolOutcome(leaf: ApprovableJob, text: "denied" | "cancelled", reason?: unknown): void {
|
|
@@ -2,13 +2,14 @@
|
|
|
2
2
|
* Project-bound mint of one model tool_call. Does not execute.
|
|
3
3
|
* Connection-sourced names are MCPToolJob; write_file / edit_file are
|
|
4
4
|
* FileMutateToolJob; pack / unknown are SystemToolJob.
|
|
5
|
-
* `agentCallFromWire` mints `agent__ask` / `agent__send`. `admit` wraps it
|
|
5
|
+
* `agentCallFromWire` mints `agent__ask` / `agent__send`. `admit` wraps it with frozen policy and retention facts.
|
|
6
6
|
* Both append onto `AdmitContext.parent` when the caller passes one. They do not enqueue.
|
|
7
7
|
* Bot-call pack tools and standing bot invocations mint BotCallJob.
|
|
8
8
|
* `scheme_repl` is a ProgrammaticJob bag. Inner admits reuse this door.
|
|
9
9
|
*/
|
|
10
10
|
import { createHash } from "node:crypto";
|
|
11
11
|
|
|
12
|
+
import type { ToolContinuation } from "@inhuman.tools/harness-commons";
|
|
12
13
|
import {
|
|
13
14
|
AgentCallJob,
|
|
14
15
|
BotCallJob,
|
|
@@ -23,8 +24,6 @@ import {
|
|
|
23
24
|
AGENT_SEND,
|
|
24
25
|
AGENT_VOID,
|
|
25
26
|
CallDelivery,
|
|
26
|
-
CONTEXT_NEED_TOOL_NAME,
|
|
27
|
-
ContextNeedToolJob,
|
|
28
27
|
FailureOutcome,
|
|
29
28
|
FileMutateToolJob,
|
|
30
29
|
MCPToolJob,
|
|
@@ -50,6 +49,7 @@ import {
|
|
|
50
49
|
} from "@inhuman.tools/harness-model";
|
|
51
50
|
import { parseJsonRecord } from "@inhuman.tools/harness-model/json-record";
|
|
52
51
|
import type { ToolCall } from "@inhuman.tools/tool-call-normalize";
|
|
52
|
+
import { action } from "mobx";
|
|
53
53
|
|
|
54
54
|
import { externalizePrior } from "./blob-port.js";
|
|
55
55
|
import { peelAgentCallArgs, requestIdOf } from "./peel.js";
|
|
@@ -57,7 +57,12 @@ import { workerToolAllowed } from "./worker-tools.js";
|
|
|
57
57
|
import { lineStartOfSpan, writeFileAdmitSnap } from "./write-admit.js";
|
|
58
58
|
import { policyOfTurn, stampJobRetention } from "../context/retention/index.js";
|
|
59
59
|
import { peelShellCwd } from "../policy-processor/peel-cwd.js";
|
|
60
|
-
import {
|
|
60
|
+
import {
|
|
61
|
+
agentCallSupportsNotify,
|
|
62
|
+
behaviorEntriesOf,
|
|
63
|
+
type CatalogEntry,
|
|
64
|
+
type KernelToolCatalog,
|
|
65
|
+
} from "../tool-catalog/index.js";
|
|
61
66
|
|
|
62
67
|
/** Catalog face the handler proxies to. A kernel host satisfies this. */
|
|
63
68
|
export type ToolCallKernel = {
|
|
@@ -106,12 +111,17 @@ function priorProps(text: string | null): { readonly priorContent?: string; read
|
|
|
106
111
|
}
|
|
107
112
|
|
|
108
113
|
function catalogFlags(entry: CatalogEntry | undefined): {
|
|
114
|
+
readonly continuationJson: string;
|
|
109
115
|
readonly triggersReactLoop: boolean;
|
|
110
116
|
readonly tapeHidden: boolean;
|
|
111
117
|
readonly isSideChannel: boolean;
|
|
112
118
|
} {
|
|
119
|
+
const continuation: ToolContinuation = entry?.continuation ?? {
|
|
120
|
+
kind: entry?.triggersReactLoop === false ? "none" : "observation",
|
|
121
|
+
};
|
|
113
122
|
return {
|
|
114
|
-
|
|
123
|
+
continuationJson: JSON.stringify(continuation),
|
|
124
|
+
triggersReactLoop: continuation.kind === "observation",
|
|
115
125
|
tapeHidden: entry?.tapeHidden ?? false,
|
|
116
126
|
isSideChannel: entry?.isSideChannel === true,
|
|
117
127
|
};
|
|
@@ -171,15 +181,15 @@ function admitExam(call: ToolCall, ctx: AdmitContext, entry: CatalogEntry): Prog
|
|
|
171
181
|
bag.outcomeSnap ??= { ok: true, value: { job_id: bag.toolCallId, background: true } };
|
|
172
182
|
}
|
|
173
183
|
ctx.originTurn?.pushChild(bag);
|
|
174
|
-
const
|
|
175
|
-
let jobUuid
|
|
184
|
+
const admittedAction = exam.admit(prefix, input);
|
|
185
|
+
let jobUuid: string;
|
|
176
186
|
try {
|
|
177
187
|
jobUuid = bag.uuid;
|
|
178
188
|
} catch {
|
|
179
189
|
jobUuid = "";
|
|
180
190
|
}
|
|
181
|
-
const actionRec = asRecord(
|
|
182
|
-
writePluginMeta(bag, pluginId, actionRec == null ?
|
|
191
|
+
const actionRec = asRecord(admittedAction);
|
|
192
|
+
writePluginMeta(bag, pluginId, actionRec == null ? admittedAction : { ...actionRec, jobUuid }, true);
|
|
183
193
|
return bag;
|
|
184
194
|
}
|
|
185
195
|
|
|
@@ -233,6 +243,11 @@ export function agentCallFromWire(
|
|
|
233
243
|
if (ctx.session != null && !workerToolAllowed(catalog, ctx.session.agent.spec.name, name, ctx.session)) {
|
|
234
244
|
return appendJob(ctx, ceilingJob(call));
|
|
235
245
|
}
|
|
246
|
+
const flags = catalogFlags(
|
|
247
|
+
catalog.catalogEntry(call.function.name) ??
|
|
248
|
+
catalog.privateWorkerEntries.find((row) => row.wireName === call.function.name) ??
|
|
249
|
+
behaviorEntriesOf(ctx.session).find((row) => row.wireName === call.function.name),
|
|
250
|
+
);
|
|
236
251
|
const peeled = peelAgentCallArgs(call.function.arguments);
|
|
237
252
|
const spec = parseJsonRecord(peeled.argsJson)?.spec;
|
|
238
253
|
// Select the explicit child or bot node at admission;
|
|
@@ -246,6 +261,7 @@ export function agentCallFromWire(
|
|
|
246
261
|
argsJson: peeled.argsJson,
|
|
247
262
|
botName: spec.trim(),
|
|
248
263
|
voidLegal: name === AGENT_SEND ? peeled.voidLegal : false,
|
|
264
|
+
...flags,
|
|
249
265
|
readonly: peeled.readonly,
|
|
250
266
|
responseSchema: peeled.responseSchema,
|
|
251
267
|
...stamp(peeled.argsJson),
|
|
@@ -260,6 +276,7 @@ export function agentCallFromWire(
|
|
|
260
276
|
argsJson: peeled.argsJson,
|
|
261
277
|
regenerateable: false,
|
|
262
278
|
voidLegal: name === AGENT_SEND ? peeled.voidLegal : false,
|
|
279
|
+
...flags,
|
|
263
280
|
readonly: peeled.readonly,
|
|
264
281
|
responseSchema: peeled.responseSchema,
|
|
265
282
|
constitution: peeled.constitution,
|
|
@@ -275,16 +292,26 @@ export function agentCallFromWire(
|
|
|
275
292
|
export class ToolCallHandler {
|
|
276
293
|
constructor(readonly kernel: ToolCallKernel) {}
|
|
277
294
|
|
|
295
|
+
@action
|
|
278
296
|
admit(call: ToolCall, catalog: KernelToolCatalog = this.kernel.catalog, ctx: AdmitContext = {}): AdmittedCall {
|
|
279
|
-
const job = this.#admit(call, catalog, ctx);
|
|
297
|
+
const job = this.#admit(call, catalog, { ...ctx, parent: undefined });
|
|
280
298
|
// R2: the horizon is resolved once, here, from the turn's R1 policy and the catalog as it is now.
|
|
281
|
-
const entry =
|
|
299
|
+
const entry =
|
|
300
|
+
catalog.catalogEntry(call.function.name) ??
|
|
301
|
+
this.kernel.catalog.catalogEntry(call.function.name) ??
|
|
302
|
+
catalog.privateWorkerEntries.find((row) => row.wireName === call.function.name) ??
|
|
303
|
+
behaviorEntriesOf(ctx.session).find((row) => row.wireName === call.function.name);
|
|
304
|
+
const policy = catalogFlags(entry);
|
|
305
|
+
job.continuationJson = policy.continuationJson;
|
|
306
|
+
job.triggersReactLoop = policy.triggersReactLoop;
|
|
307
|
+
job.isSideChannel = policy.isSideChannel;
|
|
308
|
+
job.tapeHidden = policy.tapeHidden;
|
|
282
309
|
const turn = ctx.originTurn ?? ctx.session?.head ?? null;
|
|
283
310
|
stampJobRetention(job, policyOfTurn(turn instanceof SessionTurn ? turn : null), {
|
|
284
311
|
...(entry?.class === undefined ? {} : { entryClass: entry.class }),
|
|
285
312
|
...(entry?.retention === undefined ? {} : { hint: entry.retention }),
|
|
286
313
|
});
|
|
287
|
-
return job;
|
|
314
|
+
return appendJob(ctx, job);
|
|
288
315
|
}
|
|
289
316
|
|
|
290
317
|
#admit(call: ToolCall, catalog: KernelToolCatalog, ctx: AdmitContext): AdmittedCall {
|
|
@@ -302,6 +329,7 @@ export class ToolCallHandler {
|
|
|
302
329
|
toolName: name,
|
|
303
330
|
toolCallId,
|
|
304
331
|
argsJson,
|
|
332
|
+
...catalogFlags(catalog.catalogEntry(name) ?? this.kernel.catalog.catalogEntry(name)),
|
|
305
333
|
...flagged,
|
|
306
334
|
});
|
|
307
335
|
if (job.background && job.toolCallId.trim() !== "") {
|
|
@@ -437,18 +465,6 @@ export class ToolCallHandler {
|
|
|
437
465
|
}),
|
|
438
466
|
);
|
|
439
467
|
}
|
|
440
|
-
if (name === CONTEXT_NEED_TOOL_NAME) {
|
|
441
|
-
return place(
|
|
442
|
-
new ContextNeedToolJob({
|
|
443
|
-
toolCallId,
|
|
444
|
-
name,
|
|
445
|
-
argsJson,
|
|
446
|
-
regenerateable: false,
|
|
447
|
-
...stamp(argsJson),
|
|
448
|
-
...catalogFlags(entry),
|
|
449
|
-
}),
|
|
450
|
-
);
|
|
451
|
-
}
|
|
452
468
|
if (name === WEB_SEARCH_TOOL_NAME) {
|
|
453
469
|
const parsed = parseWebSearchArgs(argsJson);
|
|
454
470
|
return place(
|
|
@@ -27,7 +27,6 @@ import { z } from "zod";
|
|
|
27
27
|
import { externalizePrior } from "./blob-port.js";
|
|
28
28
|
import { runWithExtraRoot } from "./extra-root.js";
|
|
29
29
|
import { pendingPropose, pluginCallContextOf } from "./plugin-context.js";
|
|
30
|
-
import { CONTEXT_RECALL_TOOL_NAME, recallContext } from "./recall.js";
|
|
31
30
|
import { ToolError } from "./tool-error.js";
|
|
32
31
|
import { workerToolAllowed } from "./worker-tools.js";
|
|
33
32
|
import { lineStartOfSpan } from "./write-admit.js";
|
|
@@ -39,7 +38,10 @@ function cancelledSnap(signal: AbortSignal): ToolOutcomeSnap {
|
|
|
39
38
|
|
|
40
39
|
const TAIL_MS = 50;
|
|
41
40
|
|
|
42
|
-
function tailPublisher(
|
|
41
|
+
function tailPublisher(
|
|
42
|
+
job: SystemToolJob,
|
|
43
|
+
canApplyResults: () => boolean,
|
|
44
|
+
): {
|
|
43
45
|
push: (frame: { readonly text: string; readonly totalBytes: number }) => void;
|
|
44
46
|
flush: () => void;
|
|
45
47
|
} {
|
|
@@ -47,6 +49,7 @@ function tailPublisher(job: SystemToolJob): {
|
|
|
47
49
|
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
48
50
|
let latest: { text: string; totalBytes: number } | undefined;
|
|
49
51
|
const send = (frame: { text: string; totalBytes: number }): void => {
|
|
52
|
+
if (!canApplyResults()) return;
|
|
50
53
|
if (job.receiptJson != null && job.receiptJson !== "") return;
|
|
51
54
|
latest = undefined;
|
|
52
55
|
lastAt = Date.now();
|
|
@@ -54,6 +57,7 @@ function tailPublisher(job: SystemToolJob): {
|
|
|
54
57
|
};
|
|
55
58
|
return {
|
|
56
59
|
push(frame) {
|
|
60
|
+
if (!canApplyResults()) return;
|
|
57
61
|
const now = Date.now();
|
|
58
62
|
if (now - lastAt >= TAIL_MS) {
|
|
59
63
|
if (timer !== undefined) clearTimeout(timer);
|
|
@@ -104,6 +108,7 @@ function asToolResult(out: unknown): ToolOutcomeSnap {
|
|
|
104
108
|
ok?: unknown;
|
|
105
109
|
text?: unknown;
|
|
106
110
|
value?: unknown;
|
|
111
|
+
json?: unknown;
|
|
107
112
|
truncated?: unknown;
|
|
108
113
|
};
|
|
109
114
|
if (typeof row.ok === "boolean") {
|
|
@@ -111,6 +116,7 @@ function asToolResult(out: unknown): ToolOutcomeSnap {
|
|
|
111
116
|
ok: row.ok,
|
|
112
117
|
...(typeof row.text === "string" ? { text: row.text } : {}),
|
|
113
118
|
...("value" in row ? { value: row.value } : {}),
|
|
119
|
+
...("json" in row ? { json: row.json } : {}),
|
|
114
120
|
...(row.truncated === true ? { truncated: true } : {}),
|
|
115
121
|
};
|
|
116
122
|
}
|
|
@@ -133,14 +139,19 @@ export async function executeSystemTool(
|
|
|
133
139
|
signal: AbortSignal,
|
|
134
140
|
opts?: {
|
|
135
141
|
readonly shellTailBytes?: number;
|
|
142
|
+
readonly canApplyResults?: () => boolean;
|
|
136
143
|
/** Host list/stop for `job_stop`. The tool body has no job table of its own. */
|
|
137
144
|
readonly stopJob?: (jobId: string) => JobStopReport | Promise<JobStopReport>;
|
|
138
145
|
},
|
|
139
146
|
): Promise<void> {
|
|
147
|
+
const canApplyResults = opts?.canApplyResults ?? (() => true);
|
|
140
148
|
const seal = (outcome: ToolOutcomeSnap): void => {
|
|
149
|
+
if (!canApplyResults()) return;
|
|
141
150
|
sealToolCall(job, outcome);
|
|
142
151
|
};
|
|
152
|
+
pendingPropose.delete(job);
|
|
143
153
|
try {
|
|
154
|
+
if (!canApplyResults() || job.outcomeSnap != null) return;
|
|
144
155
|
if (signal.aborted) {
|
|
145
156
|
seal(cancelledSnap(signal));
|
|
146
157
|
return;
|
|
@@ -180,11 +191,6 @@ export async function executeSystemTool(
|
|
|
180
191
|
return;
|
|
181
192
|
}
|
|
182
193
|
|
|
183
|
-
if (name === CONTEXT_RECALL_TOOL_NAME) {
|
|
184
|
-
seal(recallContext(session, args));
|
|
185
|
-
return;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
194
|
if (name === "job_stop") {
|
|
189
195
|
const jobIdRaw = args.job_id;
|
|
190
196
|
const jobId = typeof jobIdRaw === "string" ? jobIdRaw : "";
|
|
@@ -203,7 +209,7 @@ export async function executeSystemTool(
|
|
|
203
209
|
// reads under it (a session read root), so it opens the same door through `licenseAllows`; nothing is remembered
|
|
204
210
|
// from a single outside read.
|
|
205
211
|
const tailBytes = parseShellTailBytes(opts?.shellTailBytes ?? DEFAULT_SHELL_TAIL_BYTES);
|
|
206
|
-
const live = name === "shell" && tailBytes > 0 ? tailPublisher(job) : undefined;
|
|
212
|
+
const live = name === "shell" && tailBytes > 0 ? tailPublisher(job, canApplyResults) : undefined;
|
|
207
213
|
let dispatched: unknown;
|
|
208
214
|
try {
|
|
209
215
|
ToolError.invariant(entry?.execute, () =>
|
|
@@ -214,13 +220,13 @@ export async function executeSystemTool(
|
|
|
214
220
|
try {
|
|
215
221
|
dispatched = await runWithExtraRoot(job.licenseAllows, () =>
|
|
216
222
|
entry.execute!(args, {
|
|
217
|
-
root,
|
|
218
223
|
catalog,
|
|
219
224
|
signal,
|
|
220
225
|
sessionId: session.sessionId,
|
|
221
226
|
onPriorContent:
|
|
222
227
|
job instanceof FileMutateToolJob
|
|
223
228
|
? (text) => {
|
|
229
|
+
if (!canApplyResults()) return;
|
|
224
230
|
stampPrior(job, text);
|
|
225
231
|
if (typeof text === "string" && name === "edit_file") {
|
|
226
232
|
const old = typeof args.old_string === "string" ? args.old_string : "";
|
|
@@ -232,6 +238,7 @@ export async function executeSystemTool(
|
|
|
232
238
|
shellTailBytes: tailBytes,
|
|
233
239
|
onTail: live?.push,
|
|
234
240
|
...pluginCallContextOf(session, job, signal, entry.source.kind === "pack" ? entry.source.pluginName : ""),
|
|
241
|
+
root,
|
|
235
242
|
}),
|
|
236
243
|
);
|
|
237
244
|
} catch (error) {
|
|
@@ -246,7 +253,13 @@ export async function executeSystemTool(
|
|
|
246
253
|
}
|
|
247
254
|
const proposed = pendingPropose.get(job);
|
|
248
255
|
pendingPropose.delete(job);
|
|
249
|
-
if (
|
|
256
|
+
if (!canApplyResults()) return;
|
|
257
|
+
const outcome = asToolResult(dispatched);
|
|
258
|
+
if (signal.aborted) {
|
|
259
|
+
seal(outcome.ok ? cancelledSnap(signal) : outcome);
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
if (proposed != null && outcome.ok) {
|
|
250
263
|
const projection = projectionsOf(job).get(proposed.pluginId);
|
|
251
264
|
if (projection?.hostOnly?.(proposed.action) === true) {
|
|
252
265
|
seal({ ok: false, text: `${proposed.pluginId}: host-only metadata` });
|
|
@@ -254,8 +267,9 @@ export async function executeSystemTool(
|
|
|
254
267
|
}
|
|
255
268
|
writePluginMeta(job, proposed.pluginId, proposed.action, false);
|
|
256
269
|
}
|
|
257
|
-
seal(
|
|
270
|
+
seal(outcome);
|
|
258
271
|
} catch (error) {
|
|
272
|
+
if (!canApplyResults()) return;
|
|
259
273
|
if (signal.aborted) {
|
|
260
274
|
seal(cancelledSnap(signal));
|
|
261
275
|
return;
|
|
@@ -269,5 +283,7 @@ export async function executeSystemTool(
|
|
|
269
283
|
return;
|
|
270
284
|
}
|
|
271
285
|
seal({ ok: false, text: `error: ${error instanceof Error ? error.message : String(error)}` });
|
|
286
|
+
} finally {
|
|
287
|
+
pendingPropose.delete(job);
|
|
272
288
|
}
|
|
273
289
|
}
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
SessionRoot,
|
|
16
16
|
} from "@inhuman.tools/harness-model";
|
|
17
17
|
|
|
18
|
-
import { behaviorEntriesOf,
|
|
18
|
+
import { behaviorEntriesOf, type KernelToolCatalog } from "../tool-catalog/index.js";
|
|
19
19
|
|
|
20
20
|
function isAgentComms(wire: string): boolean {
|
|
21
21
|
return (
|
|
@@ -67,7 +67,7 @@ export function workerToolAllowed(
|
|
|
67
67
|
if (
|
|
68
68
|
wire === SCHEME_REPL_TOOL_NAME ||
|
|
69
69
|
wire === SCHEME_WATCH_TOOL_NAME ||
|
|
70
|
-
|
|
70
|
+
entry.isSideChannel === true ||
|
|
71
71
|
isAgentComms(wire)
|
|
72
72
|
) {
|
|
73
73
|
return true;
|