@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,497 @@
|
|
|
1
|
+
import { withQueryPairing } from "../providers/basic/ash/dist/index.mjs";
|
|
2
|
+
import { resolveDotPaths } from "./tool-discovery/dot-path-resolver.mjs";
|
|
3
|
+
import { runGuideRails } from "../agent-runners/guide-rails.mjs";
|
|
4
|
+
import { sanitizeSystemAppend } from "../agent-runners/system-prompt.mjs";
|
|
5
|
+
import { withRetry } from "../agent-runners/retry.mjs";
|
|
6
|
+
import { isJsonSafe, sanitizeMetaEnv, sanitizeScratchPath } from "./result-contract.mjs";
|
|
7
|
+
import { normalizeRunnerError } from "./runner-error.mjs";
|
|
8
|
+
import { getRunnerForType } from "./agent-runner-registry.mjs";
|
|
9
|
+
import { joinURL } from "ufo";
|
|
10
|
+
|
|
11
|
+
//#region src/program/agent-action.ts
|
|
12
|
+
const MAX_PAYLOAD_BYTES = 1024 * 1024;
|
|
13
|
+
const BLOCKED_FIELDS = new Set([
|
|
14
|
+
"_system_append",
|
|
15
|
+
"_budget_override",
|
|
16
|
+
"_model_override",
|
|
17
|
+
"_parent_session",
|
|
18
|
+
"_parent_budget_remaining",
|
|
19
|
+
"_chain"
|
|
20
|
+
]);
|
|
21
|
+
function buildInputSchema(inputKey, override) {
|
|
22
|
+
if (override && typeof override === "object") return override;
|
|
23
|
+
return {
|
|
24
|
+
type: "object",
|
|
25
|
+
properties: { [inputKey]: {
|
|
26
|
+
type: "string",
|
|
27
|
+
description: `Input for the agent (key: ${inputKey})`
|
|
28
|
+
} },
|
|
29
|
+
required: [inputKey]
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function sanitizeArgs(args) {
|
|
33
|
+
const sanitized = {};
|
|
34
|
+
for (const [key, value] of Object.entries(args)) if (!BLOCKED_FIELDS.has(key)) sanitized[key] = value;
|
|
35
|
+
return sanitized;
|
|
36
|
+
}
|
|
37
|
+
const SAFE_META_KEYS = new Set([
|
|
38
|
+
"run_id",
|
|
39
|
+
"rounds",
|
|
40
|
+
"tokens_used",
|
|
41
|
+
"sub_runs",
|
|
42
|
+
"scratch_path",
|
|
43
|
+
"mode",
|
|
44
|
+
"pipeline_steps",
|
|
45
|
+
"members_run",
|
|
46
|
+
"max_iterations_hit",
|
|
47
|
+
"warnings",
|
|
48
|
+
"session",
|
|
49
|
+
"parent_session",
|
|
50
|
+
"depth",
|
|
51
|
+
"chain",
|
|
52
|
+
"hook_events",
|
|
53
|
+
"hook_events_path",
|
|
54
|
+
"max_concurrency",
|
|
55
|
+
"member_run_ids",
|
|
56
|
+
"completed_steps",
|
|
57
|
+
"iterations",
|
|
58
|
+
"items_count",
|
|
59
|
+
"render",
|
|
60
|
+
"context"
|
|
61
|
+
]);
|
|
62
|
+
/**
|
|
63
|
+
* B9 — accept only the documented shape: { template_vars: string[] }.
|
|
64
|
+
* Anything else (primitives, arrays, foreign keys) is rejected so the
|
|
65
|
+
* envelope can't leak arbitrary runner internals through _meta.
|
|
66
|
+
*/
|
|
67
|
+
function sanitizeRenderMeta(raw) {
|
|
68
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
|
|
69
|
+
const vars = raw.template_vars;
|
|
70
|
+
if (!Array.isArray(vars)) return void 0;
|
|
71
|
+
return { template_vars: vars.filter((v) => typeof v === "string") };
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* B9 — accept only the documented shape: { system: string }. Empty string is
|
|
75
|
+
* allowed (ai-runner sets it to "" when no system prompt is configured).
|
|
76
|
+
*/
|
|
77
|
+
function sanitizeContextMeta(raw) {
|
|
78
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
|
|
79
|
+
const sys = raw.system;
|
|
80
|
+
if (typeof sys !== "string") return void 0;
|
|
81
|
+
return { system: sys };
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* B24 — strip any leading path so a full session path like
|
|
85
|
+
* `/instance/.sessions/agent/deep-42` is recorded as `deep-42` in _meta.
|
|
86
|
+
* Callers (MCP, LLM tool results) receive only the opaque id.
|
|
87
|
+
*/
|
|
88
|
+
function sessionBasename(value) {
|
|
89
|
+
const trimmed = value.replace(/\/+$/, "");
|
|
90
|
+
const idx = trimmed.lastIndexOf("/");
|
|
91
|
+
return idx >= 0 ? trimmed.slice(idx + 1) : trimmed;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* B23 — coerce any runner-reported count into a non-negative finite integer.
|
|
95
|
+
*
|
|
96
|
+
* The result-contract promises `rounds`/`tokens_used`/`sub_runs` are always
|
|
97
|
+
* numbers. Runners have historically leaked strings (`"5"`), NaN, Infinity,
|
|
98
|
+
* and negative values. Silent passthrough breaks downstream consumers that
|
|
99
|
+
* e.g. render `_meta.tokens_used.toLocaleString()`.
|
|
100
|
+
*/
|
|
101
|
+
function coerceCount(raw) {
|
|
102
|
+
const n = typeof raw === "number" ? raw : typeof raw === "string" ? Number(raw) : NaN;
|
|
103
|
+
if (!Number.isFinite(n)) return 0;
|
|
104
|
+
return Math.max(0, Math.floor(n));
|
|
105
|
+
}
|
|
106
|
+
function shapeOutput(runnerOutput, options) {
|
|
107
|
+
if (!runnerOutput || typeof runnerOutput !== "object") {
|
|
108
|
+
const baseMeta = {
|
|
109
|
+
run_id: crypto.randomUUID(),
|
|
110
|
+
rounds: 0,
|
|
111
|
+
tokens_used: 0,
|
|
112
|
+
sub_runs: 0
|
|
113
|
+
};
|
|
114
|
+
const ctx0 = options?.context;
|
|
115
|
+
if (ctx0) {
|
|
116
|
+
if (typeof ctx0.session === "string" && ctx0.session.length > 0) baseMeta.session = sessionBasename(ctx0.session);
|
|
117
|
+
if (Array.isArray(ctx0.chain)) {
|
|
118
|
+
const cleaned = ctx0.chain.filter((s) => typeof s === "string" && s.length > 0);
|
|
119
|
+
if (cleaned.length > 0) baseMeta.chain = cleaned;
|
|
120
|
+
baseMeta.depth = cleaned.length;
|
|
121
|
+
} else if (ctx0.session !== void 0) baseMeta.depth = 0;
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
result: runnerOutput ?? null,
|
|
125
|
+
_meta: baseMeta
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
const out = runnerOutput;
|
|
129
|
+
const warnings = [];
|
|
130
|
+
const runnerMeta = out._meta && typeof out._meta === "object" ? out._meta : {};
|
|
131
|
+
const data = out.data && typeof out.data === "object" ? out.data : {};
|
|
132
|
+
const hasStructuredShape = "data" in out || "result" in out || "_meta" in out || "success" in out || "error" in out;
|
|
133
|
+
const isFailureEnvelope = out.success === false;
|
|
134
|
+
let resultValue;
|
|
135
|
+
if (isFailureEnvelope) resultValue = data.result !== void 0 ? data.result : null;
|
|
136
|
+
else if (!hasStructuredShape) resultValue = runnerOutput;
|
|
137
|
+
else if (out.result !== void 0) resultValue = out.result;
|
|
138
|
+
else if (data.result !== void 0) resultValue = data.result;
|
|
139
|
+
else if (out.data !== void 0 && out.data !== null && typeof out.data === "object") {
|
|
140
|
+
const { _meta: _dataMeta, ...rest } = data;
|
|
141
|
+
resultValue = Object.keys(rest).length > 0 ? rest : null;
|
|
142
|
+
} else if (out.data !== void 0) resultValue = out.data;
|
|
143
|
+
else resultValue = null;
|
|
144
|
+
const resultIsEmpty = resultValue === void 0 || resultValue === null || typeof resultValue === "object" && Object.keys(resultValue).length === 0;
|
|
145
|
+
if (options?.outputKey && resultIsEmpty) {
|
|
146
|
+
warnings.push({
|
|
147
|
+
code: "OUTPUT_KEY_MISSING",
|
|
148
|
+
message: `Expected output key "${options.outputKey}" but runner returned no result`
|
|
149
|
+
});
|
|
150
|
+
resultValue = null;
|
|
151
|
+
}
|
|
152
|
+
if (resultValue != null && !isJsonSafe(resultValue)) {
|
|
153
|
+
warnings.push({
|
|
154
|
+
code: "RESULT_NOT_JSON_SAFE",
|
|
155
|
+
message: "Result contains circular references or non-serializable values"
|
|
156
|
+
});
|
|
157
|
+
resultValue = null;
|
|
158
|
+
}
|
|
159
|
+
const runIdRaw = runnerMeta.run_id ?? data.run_id;
|
|
160
|
+
const meta = {
|
|
161
|
+
run_id: typeof runIdRaw === "string" && runIdRaw.length > 0 ? runIdRaw : crypto.randomUUID(),
|
|
162
|
+
rounds: coerceCount(runnerMeta.rounds ?? runnerMeta.iterations ?? data.rounds),
|
|
163
|
+
tokens_used: coerceCount(runnerMeta.tokens_used ?? data.total_tokens),
|
|
164
|
+
sub_runs: coerceCount(runnerMeta.sub_runs ?? data.sub_runs)
|
|
165
|
+
};
|
|
166
|
+
const rawScratch = runnerMeta.scratch_path ?? data.scratch_path;
|
|
167
|
+
if (typeof rawScratch === "string") meta.scratch_path = sanitizeScratchPath(rawScratch);
|
|
168
|
+
for (const key of Object.keys(runnerMeta)) if (SAFE_META_KEYS.has(key) && !(key in meta)) if (key === "render") {
|
|
169
|
+
const cleaned = sanitizeRenderMeta(runnerMeta[key]);
|
|
170
|
+
if (cleaned) meta[key] = cleaned;
|
|
171
|
+
} else if (key === "context") {
|
|
172
|
+
const cleaned = sanitizeContextMeta(runnerMeta[key]);
|
|
173
|
+
if (cleaned) meta[key] = cleaned;
|
|
174
|
+
} else meta[key] = runnerMeta[key];
|
|
175
|
+
const ctx = options?.context;
|
|
176
|
+
if (ctx) {
|
|
177
|
+
if (typeof ctx.session === "string" && ctx.session.length > 0) meta.session = sessionBasename(ctx.session);
|
|
178
|
+
if (Array.isArray(ctx.chain)) {
|
|
179
|
+
const cleaned = ctx.chain.filter((s) => typeof s === "string" && s.length > 0);
|
|
180
|
+
if (cleaned.length > 0) meta.chain = cleaned;
|
|
181
|
+
meta.depth = cleaned.length;
|
|
182
|
+
} else if (ctx.session !== void 0) meta.depth = 0;
|
|
183
|
+
}
|
|
184
|
+
if (runnerMeta.env && typeof runnerMeta.env === "object") meta.env = sanitizeMetaEnv(runnerMeta.env);
|
|
185
|
+
if (warnings.length > 0) meta.warnings = warnings;
|
|
186
|
+
return {
|
|
187
|
+
result: resultValue,
|
|
188
|
+
_meta: meta
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
function estimatePayloadSize(args) {
|
|
192
|
+
let size = 0;
|
|
193
|
+
for (const value of Object.values(args)) if (typeof value === "string") size += value.length;
|
|
194
|
+
else if (value instanceof Uint8Array) size += value.length;
|
|
195
|
+
else if (typeof value === "function" || typeof value === "symbol") {} else if (value !== null && value !== void 0) try {
|
|
196
|
+
const serialized = JSON.stringify(value);
|
|
197
|
+
if (typeof serialized === "string") size += serialized.length;
|
|
198
|
+
} catch {}
|
|
199
|
+
return size;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* B29 — Compile a statically-known tool catalog from `manifest.tools` so
|
|
203
|
+
* `/.actions/run/.meta` can surface the LLM's tool surface without having to
|
|
204
|
+
* invoke the agent.
|
|
205
|
+
*
|
|
206
|
+
* This is the dot-path resolver pass only — `.ash` frontmatter discovery and
|
|
207
|
+
* skill-gated helpers require AFS I/O and happen later inside the runner. The
|
|
208
|
+
* catalog returned here covers:
|
|
209
|
+
* - resolved bare-path declarations (`./knowledge/` → `<root>/knowledge/**`)
|
|
210
|
+
* - object-form declarations (passed through verbatim)
|
|
211
|
+
* - built-in `.actions/cancel` and `.actions/status` (auto-registered for
|
|
212
|
+
* every agent blocklet, so they must always appear)
|
|
213
|
+
*
|
|
214
|
+
* Invalid declarations (absolute paths, null bytes, …) surface as structured
|
|
215
|
+
* warnings instead of silently dropping — one bad tool must not poison the
|
|
216
|
+
* rest (mirrors the S13 "data loss prevention" contract).
|
|
217
|
+
*/
|
|
218
|
+
function compileStaticToolCatalog(manifest, mountPath, actionPrefix) {
|
|
219
|
+
const catalog = [];
|
|
220
|
+
const warnings = [];
|
|
221
|
+
const tools = manifest.tools ?? [];
|
|
222
|
+
for (const raw of tools) if (typeof raw === "string") try {
|
|
223
|
+
const [resolved] = resolveDotPaths([raw], mountPath);
|
|
224
|
+
if (resolved) catalog.push(resolved);
|
|
225
|
+
} catch (err) {
|
|
226
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
227
|
+
const code = msg.startsWith("TOOL_PATH_OUTSIDE_BLOCKLET") ? "TOOL_PATH_OUTSIDE_BLOCKLET" : "TOOL_PATH_INVALID";
|
|
228
|
+
warnings.push({
|
|
229
|
+
code,
|
|
230
|
+
path: raw,
|
|
231
|
+
message: msg
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
else if (raw && typeof raw === "object") {
|
|
235
|
+
const entry = raw;
|
|
236
|
+
if (typeof entry.path !== "string" || entry.path.length === 0) {
|
|
237
|
+
warnings.push({
|
|
238
|
+
code: "TOOL_PATH_INVALID",
|
|
239
|
+
message: "object tool entry missing 'path' field"
|
|
240
|
+
});
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
catalog.push({
|
|
244
|
+
path: entry.path,
|
|
245
|
+
ops: withQueryPairing(entry.ops ?? [
|
|
246
|
+
"read",
|
|
247
|
+
"list",
|
|
248
|
+
"search"
|
|
249
|
+
]),
|
|
250
|
+
...entry.maxDepth != null ? { maxDepth: entry.maxDepth } : {}
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
const cancelName = actionPrefix ? `${actionPrefix}-cancel` : "cancel";
|
|
254
|
+
const statusName = actionPrefix ? `${actionPrefix}-status` : "status";
|
|
255
|
+
catalog.push({
|
|
256
|
+
path: joinURL(mountPath, `.actions/${cancelName}`),
|
|
257
|
+
ops: ["exec"]
|
|
258
|
+
});
|
|
259
|
+
catalog.push({
|
|
260
|
+
path: joinURL(mountPath, `.actions/${statusName}`),
|
|
261
|
+
ops: ["exec"]
|
|
262
|
+
});
|
|
263
|
+
return {
|
|
264
|
+
catalog,
|
|
265
|
+
warnings
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
function createAgentActionHandlers(manifest, _mountPath, options) {
|
|
269
|
+
const inputKey = manifest.inputKey ?? "message";
|
|
270
|
+
const inputSchema = buildInputSchema(inputKey, manifest.inputSchema);
|
|
271
|
+
const actionPrefix = options?.actionPrefix;
|
|
272
|
+
const runName = actionPrefix ? `${actionPrefix}-run` : "run";
|
|
273
|
+
const cancelName = actionPrefix ? `${actionPrefix}-cancel` : "cancel";
|
|
274
|
+
const statusName = actionPrefix ? `${actionPrefix}-status` : "status";
|
|
275
|
+
const { catalog: toolCatalog, warnings: catalogWarnings } = compileStaticToolCatalog(manifest, _mountPath, actionPrefix);
|
|
276
|
+
const runEntry = {
|
|
277
|
+
id: runName,
|
|
278
|
+
path: `/.actions/${runName}`,
|
|
279
|
+
summary: `Run agent "${manifest.name}"`,
|
|
280
|
+
meta: {
|
|
281
|
+
kind: "afs:executable",
|
|
282
|
+
kinds: ["afs:executable", "afs:node"],
|
|
283
|
+
effect: "write",
|
|
284
|
+
tool_catalog: toolCatalog,
|
|
285
|
+
...catalogWarnings.length > 0 ? { warnings: catalogWarnings } : {}
|
|
286
|
+
},
|
|
287
|
+
actions: [{
|
|
288
|
+
name: runName,
|
|
289
|
+
description: `Execute the "${manifest.name}" agent with the given input`,
|
|
290
|
+
inputSchema,
|
|
291
|
+
effect: "write"
|
|
292
|
+
}]
|
|
293
|
+
};
|
|
294
|
+
const cancelEntry = {
|
|
295
|
+
id: cancelName,
|
|
296
|
+
path: `/.actions/${cancelName}`,
|
|
297
|
+
summary: `Cancel a running agent session for "${manifest.name}"`,
|
|
298
|
+
meta: {
|
|
299
|
+
kind: "afs:executable",
|
|
300
|
+
kinds: ["afs:executable", "afs:node"],
|
|
301
|
+
effect: "write"
|
|
302
|
+
},
|
|
303
|
+
actions: [{
|
|
304
|
+
name: cancelName,
|
|
305
|
+
effect: "write",
|
|
306
|
+
description: `Cancel the "${manifest.name}" agent run for a given session`,
|
|
307
|
+
inputSchema: {
|
|
308
|
+
type: "object",
|
|
309
|
+
properties: { session: {
|
|
310
|
+
type: "string",
|
|
311
|
+
description: "Session ID to cancel"
|
|
312
|
+
} },
|
|
313
|
+
required: ["session"]
|
|
314
|
+
}
|
|
315
|
+
}]
|
|
316
|
+
};
|
|
317
|
+
const statusEntry = {
|
|
318
|
+
id: statusName,
|
|
319
|
+
path: `/.actions/${statusName}`,
|
|
320
|
+
summary: `Get agent run status for "${manifest.name}"`,
|
|
321
|
+
meta: {
|
|
322
|
+
kind: "afs:executable",
|
|
323
|
+
kinds: ["afs:executable", "afs:node"],
|
|
324
|
+
effect: "read"
|
|
325
|
+
},
|
|
326
|
+
actions: [{
|
|
327
|
+
name: statusName,
|
|
328
|
+
effect: "read",
|
|
329
|
+
description: `Get the current status of a "${manifest.name}" agent run`,
|
|
330
|
+
inputSchema: {
|
|
331
|
+
type: "object",
|
|
332
|
+
properties: { session: {
|
|
333
|
+
type: "string",
|
|
334
|
+
description: "Session ID to check"
|
|
335
|
+
} }
|
|
336
|
+
}
|
|
337
|
+
}]
|
|
338
|
+
};
|
|
339
|
+
return {
|
|
340
|
+
run: {
|
|
341
|
+
entry: runEntry,
|
|
342
|
+
inputSchema,
|
|
343
|
+
handler: async (args, context) => {
|
|
344
|
+
const sanitized = sanitizeArgs(args);
|
|
345
|
+
if (estimatePayloadSize(sanitized) > MAX_PAYLOAD_BYTES) return {
|
|
346
|
+
success: false,
|
|
347
|
+
error: {
|
|
348
|
+
code: "PAYLOAD_TOO_LARGE",
|
|
349
|
+
message: "Input payload exceeds 1 MB limit"
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
const inputValue = sanitized[inputKey];
|
|
353
|
+
if (inputValue === void 0 || inputValue === null) return {
|
|
354
|
+
success: false,
|
|
355
|
+
error: {
|
|
356
|
+
code: "INPUT_SCHEMA_INVALID",
|
|
357
|
+
message: `Missing required field: ${inputKey}`,
|
|
358
|
+
details: { field: inputKey }
|
|
359
|
+
}
|
|
360
|
+
};
|
|
361
|
+
const expectedType = (inputSchema?.properties)?.[inputKey]?.type;
|
|
362
|
+
if ((expectedType === void 0 || expectedType === "string") && typeof inputValue !== "string") return {
|
|
363
|
+
success: false,
|
|
364
|
+
error: {
|
|
365
|
+
code: "INPUT_SCHEMA_INVALID",
|
|
366
|
+
message: `Field "${inputKey}" must be a string, got ${typeof inputValue}`,
|
|
367
|
+
details: { field: inputKey }
|
|
368
|
+
}
|
|
369
|
+
};
|
|
370
|
+
if (!context) return {
|
|
371
|
+
success: false,
|
|
372
|
+
error: {
|
|
373
|
+
code: "INTERNAL_ERROR",
|
|
374
|
+
message: "No runner context provided"
|
|
375
|
+
}
|
|
376
|
+
};
|
|
377
|
+
try {
|
|
378
|
+
const runner = getRunnerForType(manifest.type);
|
|
379
|
+
const systemAppend = sanitizeSystemAppend(args._system_append);
|
|
380
|
+
const enrichedContext = {
|
|
381
|
+
...context,
|
|
382
|
+
session: typeof args.session === "string" ? args.session : context.session,
|
|
383
|
+
parentSession: args._parent_session ?? void 0,
|
|
384
|
+
chain: Array.isArray(args._chain) ? args._chain : void 0,
|
|
385
|
+
systemAppend
|
|
386
|
+
};
|
|
387
|
+
const result = await withRetry(() => runner(sanitized, enrichedContext), manifest.retry, (r) => r?.success === false);
|
|
388
|
+
let effectiveResult = result;
|
|
389
|
+
if (result?.success !== false && manifest.guideRails && manifest.guideRails.length > 0) {
|
|
390
|
+
const decision = await runGuideRails(enrichedContext.afs, manifest.guideRails, sanitized, result?.data ?? result, { mountPath: enrichedContext.mountPath });
|
|
391
|
+
if (decision.abort) {
|
|
392
|
+
const shapedAbort = shapeOutput(null, {
|
|
393
|
+
outputKey: manifest.outputKey,
|
|
394
|
+
context: {
|
|
395
|
+
session: enrichedContext.session,
|
|
396
|
+
chain: enrichedContext.chain
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
return {
|
|
400
|
+
success: false,
|
|
401
|
+
error: {
|
|
402
|
+
code: "GUIDE_RAIL_ABORT",
|
|
403
|
+
message: decision.reason ?? "GuideRail aborted"
|
|
404
|
+
},
|
|
405
|
+
data: shapedAbort
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
if (decision.output !== void 0) effectiveResult = {
|
|
409
|
+
...result,
|
|
410
|
+
data: decision.output
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
const shaped = shapeOutput(effectiveResult, {
|
|
414
|
+
outputKey: manifest.outputKey,
|
|
415
|
+
context: {
|
|
416
|
+
session: enrichedContext.session,
|
|
417
|
+
chain: enrichedContext.chain
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
if (result?.success === false) return {
|
|
421
|
+
success: false,
|
|
422
|
+
error: normalizeRunnerError(result?.error ?? {
|
|
423
|
+
code: "RUNNER_FAILED",
|
|
424
|
+
message: "Runner reported failure"
|
|
425
|
+
}),
|
|
426
|
+
data: shaped
|
|
427
|
+
};
|
|
428
|
+
return {
|
|
429
|
+
success: true,
|
|
430
|
+
data: shaped
|
|
431
|
+
};
|
|
432
|
+
} catch (err) {
|
|
433
|
+
const sessionFromArgs = typeof args.session === "string" ? args.session : context.session;
|
|
434
|
+
const chainFromArgs = Array.isArray(args._chain) ? args._chain : void 0;
|
|
435
|
+
const shapedOnError = shapeOutput(null, {
|
|
436
|
+
outputKey: manifest.outputKey,
|
|
437
|
+
context: {
|
|
438
|
+
session: sessionFromArgs,
|
|
439
|
+
chain: chainFromArgs
|
|
440
|
+
}
|
|
441
|
+
});
|
|
442
|
+
return {
|
|
443
|
+
success: false,
|
|
444
|
+
error: normalizeRunnerError(err),
|
|
445
|
+
data: shapedOnError
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
},
|
|
449
|
+
sanitizeArgs,
|
|
450
|
+
shapeOutput
|
|
451
|
+
},
|
|
452
|
+
cancel: {
|
|
453
|
+
entry: cancelEntry,
|
|
454
|
+
inputSchema: cancelEntry.actions[0].inputSchema,
|
|
455
|
+
handler: async (args) => {
|
|
456
|
+
const session = args.session;
|
|
457
|
+
if (session) return {
|
|
458
|
+
success: false,
|
|
459
|
+
error: {
|
|
460
|
+
code: "SESSION_NOT_FOUND",
|
|
461
|
+
message: `Session "${session}" not found`
|
|
462
|
+
}
|
|
463
|
+
};
|
|
464
|
+
return {
|
|
465
|
+
success: true,
|
|
466
|
+
data: { cancelled: true }
|
|
467
|
+
};
|
|
468
|
+
},
|
|
469
|
+
sanitizeArgs,
|
|
470
|
+
shapeOutput
|
|
471
|
+
},
|
|
472
|
+
status: {
|
|
473
|
+
entry: statusEntry,
|
|
474
|
+
inputSchema: statusEntry.actions[0].inputSchema,
|
|
475
|
+
handler: async (args) => {
|
|
476
|
+
const session = args.session;
|
|
477
|
+
if (session) return {
|
|
478
|
+
success: false,
|
|
479
|
+
error: {
|
|
480
|
+
code: "SESSION_NOT_FOUND",
|
|
481
|
+
message: `Session "${session}" not found`
|
|
482
|
+
}
|
|
483
|
+
};
|
|
484
|
+
return {
|
|
485
|
+
success: true,
|
|
486
|
+
data: { state: "unknown" }
|
|
487
|
+
};
|
|
488
|
+
},
|
|
489
|
+
sanitizeArgs,
|
|
490
|
+
shapeOutput
|
|
491
|
+
}
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
//#endregion
|
|
496
|
+
export { createAgentActionHandlers };
|
|
497
|
+
//# sourceMappingURL=agent-action.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-action.mjs","names":[],"sources":["../../src/program/agent-action.ts"],"sourcesContent":["/**\n * Agent action handlers — .actions/run, .actions/cancel, .actions/status.\n *\n * Auto-generated from an AgentManifest and registered on the blocklet's\n * runtime AFS as custom root actions during activation.\n */\n\nimport type { AFSEntry, AFSExecResult, AgentManifest } from \"@aigne/afs\";\nimport { withQueryPairing } from \"@aigne/afs-ash\";\nimport { joinURL } from \"ufo\";\nimport { runGuideRails } from \"../agent-runners/guide-rails.js\";\nimport { withRetry } from \"../agent-runners/retry.js\";\nimport { sanitizeSystemAppend } from \"../agent-runners/system-prompt.js\";\nimport { getRunnerForType, type RunnerContext } from \"./agent-runner-registry.js\";\nimport { isJsonSafe, sanitizeMetaEnv, sanitizeScratchPath } from \"./result-contract.js\";\nimport { normalizeRunnerError } from \"./runner-error.js\";\nimport { resolveDotPaths } from \"./tool-discovery/dot-path-resolver.js\";\n\nconst MAX_PAYLOAD_BYTES = 1024 * 1024; // 1 MB\n\nconst BLOCKED_FIELDS = new Set([\n \"_system_append\",\n \"_budget_override\",\n \"_model_override\",\n \"_parent_session\",\n \"_parent_budget_remaining\",\n \"_chain\",\n]);\n\nexport interface AgentActionHandler {\n entry: AFSEntry;\n inputSchema: Record<string, unknown>;\n handler: (args: Record<string, unknown>, context?: RunnerContext) => Promise<AFSExecResult>;\n sanitizeArgs: (args: Record<string, unknown>) => Record<string, unknown>;\n shapeOutput: (\n runnerOutput: unknown,\n options?: {\n outputKey?: string;\n context?: { session?: string; chain?: string[] };\n },\n ) => { result: any; _meta: Record<string, unknown> };\n}\n\nexport interface AgentActionHandlers {\n run: AgentActionHandler;\n cancel: AgentActionHandler;\n status: AgentActionHandler;\n}\n\nfunction buildInputSchema(\n inputKey: string,\n override?: Record<string, unknown>,\n): Record<string, unknown> {\n // B13: honor manifest-declared inputSchema when provided. This lets a\n // fixture say \"feeds is an array\" or \"query is a nested object\" instead\n // of the one-size-fits-all string default.\n if (override && typeof override === \"object\") {\n return override;\n }\n return {\n type: \"object\",\n properties: {\n [inputKey]: { type: \"string\", description: `Input for the agent (key: ${inputKey})` },\n },\n required: [inputKey],\n };\n}\n\nfunction sanitizeArgs(args: Record<string, unknown>): Record<string, unknown> {\n const sanitized: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(args)) {\n if (!BLOCKED_FIELDS.has(key)) {\n sanitized[key] = value;\n }\n }\n return sanitized;\n}\n\nconst SAFE_META_KEYS = new Set([\n \"run_id\",\n \"rounds\",\n \"tokens_used\",\n \"sub_runs\",\n \"scratch_path\",\n \"mode\",\n \"pipeline_steps\",\n \"members_run\",\n \"max_iterations_hit\",\n \"warnings\",\n \"session\",\n \"parent_session\",\n \"depth\",\n \"chain\",\n \"hook_events\",\n \"hook_events_path\",\n // team/parallel/iterate observability — runners emit these but shapeOutput's\n // allow-list would drop them without explicit listing.\n \"max_concurrency\",\n \"member_run_ids\",\n \"completed_steps\",\n \"iterations\",\n \"items_count\",\n // B9: template introspection for S4 ai runner. `render.template_vars` exposes\n // which template variables were available; `context.system` exposes the fully\n // rendered system prompt. Both are copied through only when the runner emits\n // them as objects with the expected shape (see sanitizeRenderMeta /\n // sanitizeContextMeta below).\n \"render\",\n \"context\",\n]);\n\n/**\n * B9 — accept only the documented shape: { template_vars: string[] }.\n * Anything else (primitives, arrays, foreign keys) is rejected so the\n * envelope can't leak arbitrary runner internals through _meta.\n */\nfunction sanitizeRenderMeta(raw: unknown): { template_vars: string[] } | undefined {\n if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return undefined;\n const vars = (raw as Record<string, unknown>).template_vars;\n if (!Array.isArray(vars)) return undefined;\n const cleaned = vars.filter((v): v is string => typeof v === \"string\");\n return { template_vars: cleaned };\n}\n\n/**\n * B9 — accept only the documented shape: { system: string }. Empty string is\n * allowed (ai-runner sets it to \"\" when no system prompt is configured).\n */\nfunction sanitizeContextMeta(raw: unknown): { system: string } | undefined {\n if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return undefined;\n const sys = (raw as Record<string, unknown>).system;\n if (typeof sys !== \"string\") return undefined;\n return { system: sys };\n}\n\n/**\n * B24 — strip any leading path so a full session path like\n * `/instance/.sessions/agent/deep-42` is recorded as `deep-42` in _meta.\n * Callers (MCP, LLM tool results) receive only the opaque id.\n */\nfunction sessionBasename(value: string): string {\n const trimmed = value.replace(/\\/+$/, \"\");\n const idx = trimmed.lastIndexOf(\"/\");\n return idx >= 0 ? trimmed.slice(idx + 1) : trimmed;\n}\n\n/**\n * B23 — coerce any runner-reported count into a non-negative finite integer.\n *\n * The result-contract promises `rounds`/`tokens_used`/`sub_runs` are always\n * numbers. Runners have historically leaked strings (`\"5\"`), NaN, Infinity,\n * and negative values. Silent passthrough breaks downstream consumers that\n * e.g. render `_meta.tokens_used.toLocaleString()`.\n */\nfunction coerceCount(raw: unknown): number {\n const n = typeof raw === \"number\" ? raw : typeof raw === \"string\" ? Number(raw) : NaN;\n if (!Number.isFinite(n)) return 0;\n return Math.max(0, Math.floor(n));\n}\n\nfunction shapeOutput(\n runnerOutput: unknown,\n options?: {\n outputKey?: string;\n context?: { session?: string; chain?: string[] };\n },\n): { result: any; _meta: Record<string, unknown> } {\n if (!runnerOutput || typeof runnerOutput !== \"object\") {\n const baseMeta: Record<string, unknown> = {\n run_id: crypto.randomUUID(),\n rounds: 0,\n tokens_used: 0,\n sub_runs: 0,\n };\n const ctx0 = options?.context;\n if (ctx0) {\n if (typeof ctx0.session === \"string\" && ctx0.session.length > 0) {\n baseMeta.session = sessionBasename(ctx0.session);\n }\n if (Array.isArray(ctx0.chain)) {\n const cleaned = ctx0.chain.filter(\n (s): s is string => typeof s === \"string\" && s.length > 0,\n );\n if (cleaned.length > 0) baseMeta.chain = cleaned;\n baseMeta.depth = cleaned.length;\n } else if (ctx0.session !== undefined) {\n baseMeta.depth = 0;\n }\n }\n return { result: runnerOutput ?? null, _meta: baseMeta };\n }\n\n const out = runnerOutput as Record<string, unknown>;\n const warnings: Array<{ code: string; message: string }> = [];\n\n const runnerMeta = (out._meta && typeof out._meta === \"object\" ? out._meta : {}) as Record<\n string,\n unknown\n >;\n const data = (out.data && typeof out.data === \"object\" ? out.data : {}) as Record<\n string,\n unknown\n >;\n\n const hasStructuredShape =\n \"data\" in out || \"result\" in out || \"_meta\" in out || \"success\" in out || \"error\" in out;\n const isFailureEnvelope = out.success === false;\n let resultValue: unknown;\n if (isFailureEnvelope) {\n // Runner returned a failure envelope — the inner `data` may carry a partial\n // result (e.g. tokens consumed before abort), but there is no completed\n // output. Callers should see `result: null` rather than the envelope itself.\n resultValue = data.result !== undefined ? data.result : null;\n } else if (!hasStructuredShape) {\n resultValue = runnerOutput;\n } else if (out.result !== undefined) {\n resultValue = out.result;\n } else if (data.result !== undefined) {\n resultValue = data.result;\n } else if (out.data !== undefined && out.data !== null && typeof out.data === \"object\") {\n // B8 — data fallback must not surface `_meta` as part of the result payload.\n const { _meta: _dataMeta, ...rest } = data;\n resultValue = Object.keys(rest).length > 0 ? rest : null;\n } else if (out.data !== undefined) {\n resultValue = out.data;\n } else {\n resultValue = null;\n }\n\n const resultIsEmpty =\n resultValue === undefined ||\n resultValue === null ||\n (typeof resultValue === \"object\" && Object.keys(resultValue as object).length === 0);\n if (options?.outputKey && resultIsEmpty) {\n warnings.push({\n code: \"OUTPUT_KEY_MISSING\",\n message: `Expected output key \"${options.outputKey}\" but runner returned no result`,\n });\n resultValue = null;\n }\n\n if (resultValue != null && !isJsonSafe(resultValue)) {\n warnings.push({\n code: \"RESULT_NOT_JSON_SAFE\",\n message: \"Result contains circular references or non-serializable values\",\n });\n resultValue = null;\n }\n\n const runIdRaw = runnerMeta.run_id ?? data.run_id;\n const meta: Record<string, unknown> = {\n run_id: typeof runIdRaw === \"string\" && runIdRaw.length > 0 ? runIdRaw : crypto.randomUUID(),\n rounds: coerceCount(runnerMeta.rounds ?? runnerMeta.iterations ?? data.rounds),\n tokens_used: coerceCount(runnerMeta.tokens_used ?? data.total_tokens),\n // B4 — fall back to data.sub_runs the same way rounds/tokens_used do.\n // Runners that embed counts inside the inner data envelope (e.g. ash\n // agent-run's nested .actions/run dispatch counter) were silently zeroed.\n sub_runs: coerceCount(runnerMeta.sub_runs ?? data.sub_runs),\n };\n\n const rawScratch = runnerMeta.scratch_path ?? data.scratch_path;\n if (typeof rawScratch === \"string\") {\n meta.scratch_path = sanitizeScratchPath(rawScratch);\n }\n\n for (const key of Object.keys(runnerMeta)) {\n if (SAFE_META_KEYS.has(key) && !(key in meta)) {\n // B9 — render/context go through structural sanitizers so malformed\n // runner output (e.g. `render: \"oops\"`) is dropped, not propagated.\n if (key === \"render\") {\n const cleaned = sanitizeRenderMeta(runnerMeta[key]);\n if (cleaned) meta[key] = cleaned;\n } else if (key === \"context\") {\n const cleaned = sanitizeContextMeta(runnerMeta[key]);\n if (cleaned) meta[key] = cleaned;\n } else {\n meta[key] = runnerMeta[key];\n }\n }\n }\n\n // B24 — caller context takes precedence over runner-reported session/chain.\n // When a context is supplied, the current run has authoritative knowledge of\n // its own session hierarchy; the runner's self-report may be stale (e.g. a\n // mocked result carrying an old session id).\n const ctx = options?.context;\n if (ctx) {\n if (typeof ctx.session === \"string\" && ctx.session.length > 0) {\n meta.session = sessionBasename(ctx.session);\n }\n if (Array.isArray(ctx.chain)) {\n const cleaned = ctx.chain.filter((s): s is string => typeof s === \"string\" && s.length > 0);\n if (cleaned.length > 0) meta.chain = cleaned;\n meta.depth = cleaned.length;\n } else if (ctx.session !== undefined) {\n // Explicit context supplied without a chain → root-level (depth 0)\n meta.depth = 0;\n }\n }\n\n if (runnerMeta.env && typeof runnerMeta.env === \"object\") {\n meta.env = sanitizeMetaEnv(runnerMeta.env as Record<string, unknown>);\n }\n\n if (warnings.length > 0) meta.warnings = warnings;\n\n return { result: resultValue, _meta: meta };\n}\n\nfunction estimatePayloadSize(args: Record<string, unknown>): number {\n let size = 0;\n for (const value of Object.values(args)) {\n if (typeof value === \"string\") {\n size += value.length;\n } else if (value instanceof Uint8Array) {\n size += value.length;\n } else if (typeof value === \"function\" || typeof value === \"symbol\") {\n // Non-serializable — skip (callers may pass progress callbacks etc.)\n } else if (value !== null && value !== undefined) {\n try {\n const serialized = JSON.stringify(value);\n if (typeof serialized === \"string\") {\n size += serialized.length;\n }\n } catch {\n // Circular references / non-serializable objects — skip\n }\n }\n }\n return size;\n}\n\n/**\n * B29 — Compile a statically-known tool catalog from `manifest.tools` so\n * `/.actions/run/.meta` can surface the LLM's tool surface without having to\n * invoke the agent.\n *\n * This is the dot-path resolver pass only — `.ash` frontmatter discovery and\n * skill-gated helpers require AFS I/O and happen later inside the runner. The\n * catalog returned here covers:\n * - resolved bare-path declarations (`./knowledge/` → `<root>/knowledge/**`)\n * - object-form declarations (passed through verbatim)\n * - built-in `.actions/cancel` and `.actions/status` (auto-registered for\n * every agent blocklet, so they must always appear)\n *\n * Invalid declarations (absolute paths, null bytes, …) surface as structured\n * warnings instead of silently dropping — one bad tool must not poison the\n * rest (mirrors the S13 \"data loss prevention\" contract).\n */\nfunction compileStaticToolCatalog(\n manifest: AgentManifest,\n mountPath: string,\n actionPrefix?: string,\n): {\n catalog: Array<{ path: string; ops: string[]; maxDepth?: number }>;\n warnings: Array<{ code: string; path?: string; message: string }>;\n} {\n const catalog: Array<{ path: string; ops: string[]; maxDepth?: number }> = [];\n const warnings: Array<{ code: string; path?: string; message: string }> = [];\n const tools = (manifest as { tools?: unknown[] }).tools ?? [];\n\n for (const raw of tools) {\n if (typeof raw === \"string\") {\n try {\n const [resolved] = resolveDotPaths([raw], mountPath);\n if (resolved) catalog.push(resolved);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n const code = msg.startsWith(\"TOOL_PATH_OUTSIDE_BLOCKLET\")\n ? \"TOOL_PATH_OUTSIDE_BLOCKLET\"\n : \"TOOL_PATH_INVALID\";\n warnings.push({ code, path: raw, message: msg });\n }\n } else if (raw && typeof raw === \"object\") {\n const entry = raw as { path?: string; ops?: string[]; maxDepth?: number };\n if (typeof entry.path !== \"string\" || entry.path.length === 0) {\n warnings.push({\n code: \"TOOL_PATH_INVALID\",\n message: \"object tool entry missing 'path' field\",\n });\n continue;\n }\n catalog.push({\n path: entry.path,\n // list grants pair with query (read-class collection view).\n ops: withQueryPairing(entry.ops ?? [\"read\", \"list\", \"search\"]),\n ...(entry.maxDepth != null ? { maxDepth: entry.maxDepth } : {}),\n });\n }\n }\n\n // Built-in action paths — always visible, always exec-only.\n // Under an actionPrefix, the cancel/status siblings live at the prefixed\n // names; pointing the catalog at the bare paths would lure tool-using\n // LLMs into calling actions that don't exist on this blocklet.\n const cancelName = actionPrefix ? `${actionPrefix}-cancel` : \"cancel\";\n const statusName = actionPrefix ? `${actionPrefix}-status` : \"status\";\n catalog.push({ path: joinURL(mountPath, `.actions/${cancelName}`), ops: [\"exec\"] });\n catalog.push({ path: joinURL(mountPath, `.actions/${statusName}`), ops: [\"exec\"] });\n\n return { catalog, warnings };\n}\n\n/**\n * Options for `createAgentActionHandlers`.\n *\n * `actionPrefix` is used by the blocklet manager when registering nested\n * agents under a single blocklet's runtime AFS. Without a prefix, every\n * blocklet would collide on the unqualified `run`/`cancel`/`status` keys\n * after the second nested manifest. With `actionPrefix: \"s1\"`, the\n * registered names become `s1-run`/`s1-cancel`/`s1-status`, and any\n * catalog references the LLM sees rewrite to match.\n */\nexport interface CreateAgentActionHandlersOptions {\n actionPrefix?: string;\n}\n\nexport function createAgentActionHandlers(\n manifest: AgentManifest,\n _mountPath: string,\n options?: CreateAgentActionHandlersOptions,\n): AgentActionHandlers {\n const inputKey = manifest.inputKey ?? \"message\";\n const inputSchema = buildInputSchema(\n inputKey,\n (manifest as any).inputSchema as Record<string, unknown> | undefined,\n );\n\n const actionPrefix = options?.actionPrefix;\n const runName = actionPrefix ? `${actionPrefix}-run` : \"run\";\n const cancelName = actionPrefix ? `${actionPrefix}-cancel` : \"cancel\";\n const statusName = actionPrefix ? `${actionPrefix}-status` : \"status\";\n\n const { catalog: toolCatalog, warnings: catalogWarnings } = compileStaticToolCatalog(\n manifest,\n _mountPath,\n actionPrefix,\n );\n\n const runEntry: AFSEntry = {\n id: runName,\n path: `/.actions/${runName}`,\n summary: `Run agent \"${manifest.name}\"`,\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n // exec-auth-gate P2: agent runs mutate state (traces, sessions) — the\n // custom-action gate branch reads this (fail-closed \"write\" if absent).\n effect: \"write\",\n tool_catalog: toolCatalog,\n ...(catalogWarnings.length > 0 ? { warnings: catalogWarnings } : {}),\n },\n actions: [\n {\n name: runName,\n description: `Execute the \"${manifest.name}\" agent with the given input`,\n inputSchema: inputSchema as any,\n effect: \"write\",\n },\n ],\n };\n\n const cancelEntry: AFSEntry = {\n id: cancelName,\n path: `/.actions/${cancelName}`,\n summary: `Cancel a running agent session for \"${manifest.name}\"`,\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n // exec-auth-gate P2: cancel mutates the run's lifecycle state.\n effect: \"write\",\n },\n actions: [\n {\n name: cancelName,\n effect: \"write\",\n description: `Cancel the \"${manifest.name}\" agent run for a given session`,\n inputSchema: {\n type: \"object\",\n properties: {\n session: { type: \"string\", description: \"Session ID to cancel\" },\n },\n required: [\"session\"],\n },\n },\n ],\n };\n\n const statusEntry: AFSEntry = {\n id: statusName,\n path: `/.actions/${statusName}`,\n summary: `Get agent run status for \"${manifest.name}\"`,\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n // exec-auth-gate P2: status is read-only — without this annotation the\n // fail-closed custom branch would 401 anonymous status checks (P3).\n effect: \"read\",\n },\n actions: [\n {\n name: statusName,\n effect: \"read\",\n description: `Get the current status of a \"${manifest.name}\" agent run`,\n inputSchema: {\n type: \"object\",\n properties: {\n session: { type: \"string\", description: \"Session ID to check\" },\n },\n },\n },\n ],\n };\n\n const runHandler: AgentActionHandler = {\n entry: runEntry,\n inputSchema,\n handler: async (args, context) => {\n const sanitized = sanitizeArgs(args);\n\n if (estimatePayloadSize(sanitized) > MAX_PAYLOAD_BYTES) {\n return {\n success: false,\n error: { code: \"PAYLOAD_TOO_LARGE\", message: \"Input payload exceeds 1 MB limit\" },\n };\n }\n\n const inputValue = sanitized[inputKey];\n if (inputValue === undefined || inputValue === null) {\n return {\n success: false,\n error: {\n code: \"INPUT_SCHEMA_INVALID\",\n message: `Missing required field: ${inputKey}`,\n details: { field: inputKey },\n },\n };\n }\n\n // B13: enforce string only when the effective schema for inputKey says so.\n // If the manifest declared a richer type (array/object/number/...), skip\n // the string check and let the runner handle the value natively.\n const schemaProps = (inputSchema as any)?.properties as Record<string, any> | undefined;\n const expectedType = schemaProps?.[inputKey]?.type;\n const expectsString = expectedType === undefined || expectedType === \"string\";\n if (expectsString && typeof inputValue !== \"string\") {\n return {\n success: false,\n error: {\n code: \"INPUT_SCHEMA_INVALID\",\n message: `Field \"${inputKey}\" must be a string, got ${typeof inputValue}`,\n details: { field: inputKey },\n },\n };\n }\n\n if (!context) {\n return {\n success: false,\n error: { code: \"INTERNAL_ERROR\", message: \"No runner context provided\" },\n };\n }\n\n try {\n const runner = getRunnerForType(manifest.type);\n\n // Phase 6 — legacy `_budget_override`, `_parent_budget_remaining`,\n // `_hook_chain_depth`, and `_parent_tools` exec-args are retired.\n // Budget / tools / chain depth now flow through AgentScope\n // (`context.afs.scope`) via `projectForChild`.\n const systemAppend = sanitizeSystemAppend(args._system_append);\n\n const enrichedContext: RunnerContext = {\n ...context,\n session: typeof args.session === \"string\" ? args.session : context.session,\n parentSession: (args._parent_session as string) ?? undefined,\n chain: Array.isArray(args._chain) ? (args._chain as string[]) : undefined,\n systemAppend,\n };\n const result = await withRetry(\n () => runner(sanitized, enrichedContext),\n manifest.retry,\n (r) => (r as { success?: boolean })?.success === false,\n );\n\n let effectiveResult: unknown = result;\n const runnerSuccessForRails = (result as any)?.success !== false;\n if (runnerSuccessForRails && manifest.guideRails && manifest.guideRails.length > 0) {\n const decision = await runGuideRails(\n enrichedContext.afs,\n manifest.guideRails,\n sanitized,\n (result as any)?.data ?? result,\n { mountPath: enrichedContext.mountPath },\n );\n if (decision.abort) {\n const shapedAbort = shapeOutput(null, {\n outputKey: manifest.outputKey,\n context: { session: enrichedContext.session, chain: enrichedContext.chain },\n });\n return {\n success: false,\n error: {\n code: \"GUIDE_RAIL_ABORT\",\n message: decision.reason ?? \"GuideRail aborted\",\n },\n data: shapedAbort,\n };\n }\n if (decision.output !== undefined) {\n effectiveResult = {\n ...(result as unknown as Record<string, unknown>),\n data: decision.output,\n };\n }\n }\n\n const shaped = shapeOutput(effectiveResult, {\n outputKey: manifest.outputKey,\n context: {\n session: enrichedContext.session,\n chain: enrichedContext.chain,\n },\n });\n const runnerSuccess = (result as any)?.success;\n if (runnerSuccess === false) {\n const rawError = (result as any)?.error ?? {\n code: \"RUNNER_FAILED\",\n message: \"Runner reported failure\",\n };\n return {\n success: false,\n error: normalizeRunnerError(rawError),\n data: shaped,\n };\n }\n return { success: true, data: shaped };\n } catch (err: unknown) {\n // B23 — even on exception we must emit the { result, _meta } envelope\n // so callers never have to branch on shape. Session/chain context is\n // still captured from the sanitized args.\n const sessionFromArgs = typeof args.session === \"string\" ? args.session : context.session;\n const chainFromArgs = Array.isArray(args._chain) ? (args._chain as string[]) : undefined;\n const shapedOnError = shapeOutput(null, {\n outputKey: manifest.outputKey,\n context: { session: sessionFromArgs, chain: chainFromArgs },\n });\n return { success: false, error: normalizeRunnerError(err), data: shapedOnError };\n }\n },\n sanitizeArgs,\n shapeOutput,\n };\n\n const cancelHandler: AgentActionHandler = {\n entry: cancelEntry,\n inputSchema: cancelEntry.actions![0]!.inputSchema as Record<string, unknown>,\n handler: async (args) => {\n const session = args.session as string | undefined;\n if (session) {\n // S2 stub: full cancel wiring comes in S11.\n // For now, return SESSION_NOT_FOUND for any specific session\n // since we don't track sessions yet.\n return {\n success: false,\n error: { code: \"SESSION_NOT_FOUND\", message: `Session \"${session}\" not found` },\n };\n }\n return { success: true, data: { cancelled: true } };\n },\n sanitizeArgs,\n shapeOutput,\n };\n\n const statusHandler: AgentActionHandler = {\n entry: statusEntry,\n inputSchema: statusEntry.actions![0]!.inputSchema as Record<string, unknown>,\n handler: async (args) => {\n const session = args.session as string | undefined;\n if (session) {\n // S2 stub: return SESSION_NOT_FOUND for specific sessions\n return {\n success: false,\n error: { code: \"SESSION_NOT_FOUND\", message: `Session \"${session}\" not found` },\n };\n }\n // Generic status: stub until S14 provisions scratch\n return { success: true, data: { state: \"unknown\" } };\n },\n sanitizeArgs,\n shapeOutput,\n };\n\n return {\n run: runHandler,\n cancel: cancelHandler,\n status: statusHandler,\n };\n}\n"],"mappings":";;;;;;;;;;;AAkBA,MAAM,oBAAoB,OAAO;AAEjC,MAAM,iBAAiB,IAAI,IAAI;CAC7B;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAsBF,SAAS,iBACP,UACA,UACyB;AAIzB,KAAI,YAAY,OAAO,aAAa,SAClC,QAAO;AAET,QAAO;EACL,MAAM;EACN,YAAY,GACT,WAAW;GAAE,MAAM;GAAU,aAAa,6BAA6B,SAAS;GAAI,EACtF;EACD,UAAU,CAAC,SAAS;EACrB;;AAGH,SAAS,aAAa,MAAwD;CAC5E,MAAM,YAAqC,EAAE;AAC7C,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,CAC7C,KAAI,CAAC,eAAe,IAAI,IAAI,CAC1B,WAAU,OAAO;AAGrB,QAAO;;AAGT,MAAM,iBAAiB,IAAI,IAAI;CAC7B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAGA;CACA;CACA;CACA;CACA;CAMA;CACA;CACD,CAAC;;;;;;AAOF,SAAS,mBAAmB,KAAuD;AACjF,KAAI,CAAC,OAAO,OAAO,QAAQ,YAAY,MAAM,QAAQ,IAAI,CAAE,QAAO;CAClE,MAAM,OAAQ,IAAgC;AAC9C,KAAI,CAAC,MAAM,QAAQ,KAAK,CAAE,QAAO;AAEjC,QAAO,EAAE,eADO,KAAK,QAAQ,MAAmB,OAAO,MAAM,SAAS,EACrC;;;;;;AAOnC,SAAS,oBAAoB,KAA8C;AACzE,KAAI,CAAC,OAAO,OAAO,QAAQ,YAAY,MAAM,QAAQ,IAAI,CAAE,QAAO;CAClE,MAAM,MAAO,IAAgC;AAC7C,KAAI,OAAO,QAAQ,SAAU,QAAO;AACpC,QAAO,EAAE,QAAQ,KAAK;;;;;;;AAQxB,SAAS,gBAAgB,OAAuB;CAC9C,MAAM,UAAU,MAAM,QAAQ,QAAQ,GAAG;CACzC,MAAM,MAAM,QAAQ,YAAY,IAAI;AACpC,QAAO,OAAO,IAAI,QAAQ,MAAM,MAAM,EAAE,GAAG;;;;;;;;;;AAW7C,SAAS,YAAY,KAAsB;CACzC,MAAM,IAAI,OAAO,QAAQ,WAAW,MAAM,OAAO,QAAQ,WAAW,OAAO,IAAI,GAAG;AAClF,KAAI,CAAC,OAAO,SAAS,EAAE,CAAE,QAAO;AAChC,QAAO,KAAK,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;;AAGnC,SAAS,YACP,cACA,SAIiD;AACjD,KAAI,CAAC,gBAAgB,OAAO,iBAAiB,UAAU;EACrD,MAAM,WAAoC;GACxC,QAAQ,OAAO,YAAY;GAC3B,QAAQ;GACR,aAAa;GACb,UAAU;GACX;EACD,MAAM,OAAO,SAAS;AACtB,MAAI,MAAM;AACR,OAAI,OAAO,KAAK,YAAY,YAAY,KAAK,QAAQ,SAAS,EAC5D,UAAS,UAAU,gBAAgB,KAAK,QAAQ;AAElD,OAAI,MAAM,QAAQ,KAAK,MAAM,EAAE;IAC7B,MAAM,UAAU,KAAK,MAAM,QACxB,MAAmB,OAAO,MAAM,YAAY,EAAE,SAAS,EACzD;AACD,QAAI,QAAQ,SAAS,EAAG,UAAS,QAAQ;AACzC,aAAS,QAAQ,QAAQ;cAChB,KAAK,YAAY,OAC1B,UAAS,QAAQ;;AAGrB,SAAO;GAAE,QAAQ,gBAAgB;GAAM,OAAO;GAAU;;CAG1D,MAAM,MAAM;CACZ,MAAM,WAAqD,EAAE;CAE7D,MAAM,aAAc,IAAI,SAAS,OAAO,IAAI,UAAU,WAAW,IAAI,QAAQ,EAAE;CAI/E,MAAM,OAAQ,IAAI,QAAQ,OAAO,IAAI,SAAS,WAAW,IAAI,OAAO,EAAE;CAKtE,MAAM,qBACJ,UAAU,OAAO,YAAY,OAAO,WAAW,OAAO,aAAa,OAAO,WAAW;CACvF,MAAM,oBAAoB,IAAI,YAAY;CAC1C,IAAI;AACJ,KAAI,kBAIF,eAAc,KAAK,WAAW,SAAY,KAAK,SAAS;UAC/C,CAAC,mBACV,eAAc;UACL,IAAI,WAAW,OACxB,eAAc,IAAI;UACT,KAAK,WAAW,OACzB,eAAc,KAAK;UACV,IAAI,SAAS,UAAa,IAAI,SAAS,QAAQ,OAAO,IAAI,SAAS,UAAU;EAEtF,MAAM,EAAE,OAAO,WAAW,GAAG,SAAS;AACtC,gBAAc,OAAO,KAAK,KAAK,CAAC,SAAS,IAAI,OAAO;YAC3C,IAAI,SAAS,OACtB,eAAc,IAAI;KAElB,eAAc;CAGhB,MAAM,gBACJ,gBAAgB,UAChB,gBAAgB,QACf,OAAO,gBAAgB,YAAY,OAAO,KAAK,YAAsB,CAAC,WAAW;AACpF,KAAI,SAAS,aAAa,eAAe;AACvC,WAAS,KAAK;GACZ,MAAM;GACN,SAAS,wBAAwB,QAAQ,UAAU;GACpD,CAAC;AACF,gBAAc;;AAGhB,KAAI,eAAe,QAAQ,CAAC,WAAW,YAAY,EAAE;AACnD,WAAS,KAAK;GACZ,MAAM;GACN,SAAS;GACV,CAAC;AACF,gBAAc;;CAGhB,MAAM,WAAW,WAAW,UAAU,KAAK;CAC3C,MAAM,OAAgC;EACpC,QAAQ,OAAO,aAAa,YAAY,SAAS,SAAS,IAAI,WAAW,OAAO,YAAY;EAC5F,QAAQ,YAAY,WAAW,UAAU,WAAW,cAAc,KAAK,OAAO;EAC9E,aAAa,YAAY,WAAW,eAAe,KAAK,aAAa;EAIrE,UAAU,YAAY,WAAW,YAAY,KAAK,SAAS;EAC5D;CAED,MAAM,aAAa,WAAW,gBAAgB,KAAK;AACnD,KAAI,OAAO,eAAe,SACxB,MAAK,eAAe,oBAAoB,WAAW;AAGrD,MAAK,MAAM,OAAO,OAAO,KAAK,WAAW,CACvC,KAAI,eAAe,IAAI,IAAI,IAAI,EAAE,OAAO,MAGtC,KAAI,QAAQ,UAAU;EACpB,MAAM,UAAU,mBAAmB,WAAW,KAAK;AACnD,MAAI,QAAS,MAAK,OAAO;YAChB,QAAQ,WAAW;EAC5B,MAAM,UAAU,oBAAoB,WAAW,KAAK;AACpD,MAAI,QAAS,MAAK,OAAO;OAEzB,MAAK,OAAO,WAAW;CAS7B,MAAM,MAAM,SAAS;AACrB,KAAI,KAAK;AACP,MAAI,OAAO,IAAI,YAAY,YAAY,IAAI,QAAQ,SAAS,EAC1D,MAAK,UAAU,gBAAgB,IAAI,QAAQ;AAE7C,MAAI,MAAM,QAAQ,IAAI,MAAM,EAAE;GAC5B,MAAM,UAAU,IAAI,MAAM,QAAQ,MAAmB,OAAO,MAAM,YAAY,EAAE,SAAS,EAAE;AAC3F,OAAI,QAAQ,SAAS,EAAG,MAAK,QAAQ;AACrC,QAAK,QAAQ,QAAQ;aACZ,IAAI,YAAY,OAEzB,MAAK,QAAQ;;AAIjB,KAAI,WAAW,OAAO,OAAO,WAAW,QAAQ,SAC9C,MAAK,MAAM,gBAAgB,WAAW,IAA+B;AAGvE,KAAI,SAAS,SAAS,EAAG,MAAK,WAAW;AAEzC,QAAO;EAAE,QAAQ;EAAa,OAAO;EAAM;;AAG7C,SAAS,oBAAoB,MAAuC;CAClE,IAAI,OAAO;AACX,MAAK,MAAM,SAAS,OAAO,OAAO,KAAK,CACrC,KAAI,OAAO,UAAU,SACnB,SAAQ,MAAM;UACL,iBAAiB,WAC1B,SAAQ,MAAM;UACL,OAAO,UAAU,cAAc,OAAO,UAAU,UAAU,YAE1D,UAAU,QAAQ,UAAU,OACrC,KAAI;EACF,MAAM,aAAa,KAAK,UAAU,MAAM;AACxC,MAAI,OAAO,eAAe,SACxB,SAAQ,WAAW;SAEf;AAKZ,QAAO;;;;;;;;;;;;;;;;;;;AAoBT,SAAS,yBACP,UACA,WACA,cAIA;CACA,MAAM,UAAqE,EAAE;CAC7E,MAAM,WAAoE,EAAE;CAC5E,MAAM,QAAS,SAAmC,SAAS,EAAE;AAE7D,MAAK,MAAM,OAAO,MAChB,KAAI,OAAO,QAAQ,SACjB,KAAI;EACF,MAAM,CAAC,YAAY,gBAAgB,CAAC,IAAI,EAAE,UAAU;AACpD,MAAI,SAAU,SAAQ,KAAK,SAAS;UAC7B,KAAK;EACZ,MAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;EAC5D,MAAM,OAAO,IAAI,WAAW,6BAA6B,GACrD,+BACA;AACJ,WAAS,KAAK;GAAE;GAAM,MAAM;GAAK,SAAS;GAAK,CAAC;;UAEzC,OAAO,OAAO,QAAQ,UAAU;EACzC,MAAM,QAAQ;AACd,MAAI,OAAO,MAAM,SAAS,YAAY,MAAM,KAAK,WAAW,GAAG;AAC7D,YAAS,KAAK;IACZ,MAAM;IACN,SAAS;IACV,CAAC;AACF;;AAEF,UAAQ,KAAK;GACX,MAAM,MAAM;GAEZ,KAAK,iBAAiB,MAAM,OAAO;IAAC;IAAQ;IAAQ;IAAS,CAAC;GAC9D,GAAI,MAAM,YAAY,OAAO,EAAE,UAAU,MAAM,UAAU,GAAG,EAAE;GAC/D,CAAC;;CAQN,MAAM,aAAa,eAAe,GAAG,aAAa,WAAW;CAC7D,MAAM,aAAa,eAAe,GAAG,aAAa,WAAW;AAC7D,SAAQ,KAAK;EAAE,MAAM,QAAQ,WAAW,YAAY,aAAa;EAAE,KAAK,CAAC,OAAO;EAAE,CAAC;AACnF,SAAQ,KAAK;EAAE,MAAM,QAAQ,WAAW,YAAY,aAAa;EAAE,KAAK,CAAC,OAAO;EAAE,CAAC;AAEnF,QAAO;EAAE;EAAS;EAAU;;AAiB9B,SAAgB,0BACd,UACA,YACA,SACqB;CACrB,MAAM,WAAW,SAAS,YAAY;CACtC,MAAM,cAAc,iBAClB,UACC,SAAiB,YACnB;CAED,MAAM,eAAe,SAAS;CAC9B,MAAM,UAAU,eAAe,GAAG,aAAa,QAAQ;CACvD,MAAM,aAAa,eAAe,GAAG,aAAa,WAAW;CAC7D,MAAM,aAAa,eAAe,GAAG,aAAa,WAAW;CAE7D,MAAM,EAAE,SAAS,aAAa,UAAU,oBAAoB,yBAC1D,UACA,YACA,aACD;CAED,MAAM,WAAqB;EACzB,IAAI;EACJ,MAAM,aAAa;EACnB,SAAS,cAAc,SAAS,KAAK;EACrC,MAAM;GACJ,MAAM;GACN,OAAO,CAAC,kBAAkB,WAAW;GAGrC,QAAQ;GACR,cAAc;GACd,GAAI,gBAAgB,SAAS,IAAI,EAAE,UAAU,iBAAiB,GAAG,EAAE;GACpE;EACD,SAAS,CACP;GACE,MAAM;GACN,aAAa,gBAAgB,SAAS,KAAK;GAC9B;GACb,QAAQ;GACT,CACF;EACF;CAED,MAAM,cAAwB;EAC5B,IAAI;EACJ,MAAM,aAAa;EACnB,SAAS,uCAAuC,SAAS,KAAK;EAC9D,MAAM;GACJ,MAAM;GACN,OAAO,CAAC,kBAAkB,WAAW;GAErC,QAAQ;GACT;EACD,SAAS,CACP;GACE,MAAM;GACN,QAAQ;GACR,aAAa,eAAe,SAAS,KAAK;GAC1C,aAAa;IACX,MAAM;IACN,YAAY,EACV,SAAS;KAAE,MAAM;KAAU,aAAa;KAAwB,EACjE;IACD,UAAU,CAAC,UAAU;IACtB;GACF,CACF;EACF;CAED,MAAM,cAAwB;EAC5B,IAAI;EACJ,MAAM,aAAa;EACnB,SAAS,6BAA6B,SAAS,KAAK;EACpD,MAAM;GACJ,MAAM;GACN,OAAO,CAAC,kBAAkB,WAAW;GAGrC,QAAQ;GACT;EACD,SAAS,CACP;GACE,MAAM;GACN,QAAQ;GACR,aAAa,gCAAgC,SAAS,KAAK;GAC3D,aAAa;IACX,MAAM;IACN,YAAY,EACV,SAAS;KAAE,MAAM;KAAU,aAAa;KAAuB,EAChE;IACF;GACF,CACF;EACF;AAqLD,QAAO;EACL,KApLqC;GACrC,OAAO;GACP;GACA,SAAS,OAAO,MAAM,YAAY;IAChC,MAAM,YAAY,aAAa,KAAK;AAEpC,QAAI,oBAAoB,UAAU,GAAG,kBACnC,QAAO;KACL,SAAS;KACT,OAAO;MAAE,MAAM;MAAqB,SAAS;MAAoC;KAClF;IAGH,MAAM,aAAa,UAAU;AAC7B,QAAI,eAAe,UAAa,eAAe,KAC7C,QAAO;KACL,SAAS;KACT,OAAO;MACL,MAAM;MACN,SAAS,2BAA2B;MACpC,SAAS,EAAE,OAAO,UAAU;MAC7B;KACF;IAOH,MAAM,gBADe,aAAqB,cACP,WAAW;AAE9C,SADsB,iBAAiB,UAAa,iBAAiB,aAChD,OAAO,eAAe,SACzC,QAAO;KACL,SAAS;KACT,OAAO;MACL,MAAM;MACN,SAAS,UAAU,SAAS,0BAA0B,OAAO;MAC7D,SAAS,EAAE,OAAO,UAAU;MAC7B;KACF;AAGH,QAAI,CAAC,QACH,QAAO;KACL,SAAS;KACT,OAAO;MAAE,MAAM;MAAkB,SAAS;MAA8B;KACzE;AAGH,QAAI;KACF,MAAM,SAAS,iBAAiB,SAAS,KAAK;KAM9C,MAAM,eAAe,qBAAqB,KAAK,eAAe;KAE9D,MAAM,kBAAiC;MACrC,GAAG;MACH,SAAS,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU,QAAQ;MACnE,eAAgB,KAAK,mBAA8B;MACnD,OAAO,MAAM,QAAQ,KAAK,OAAO,GAAI,KAAK,SAAsB;MAChE;MACD;KACD,MAAM,SAAS,MAAM,gBACb,OAAO,WAAW,gBAAgB,EACxC,SAAS,QACR,MAAO,GAA6B,YAAY,MAClD;KAED,IAAI,kBAA2B;AAE/B,SAD+B,QAAgB,YAAY,SAC9B,SAAS,cAAc,SAAS,WAAW,SAAS,GAAG;MAClF,MAAM,WAAW,MAAM,cACrB,gBAAgB,KAChB,SAAS,YACT,WACC,QAAgB,QAAQ,QACzB,EAAE,WAAW,gBAAgB,WAAW,CACzC;AACD,UAAI,SAAS,OAAO;OAClB,MAAM,cAAc,YAAY,MAAM;QACpC,WAAW,SAAS;QACpB,SAAS;SAAE,SAAS,gBAAgB;SAAS,OAAO,gBAAgB;SAAO;QAC5E,CAAC;AACF,cAAO;QACL,SAAS;QACT,OAAO;SACL,MAAM;SACN,SAAS,SAAS,UAAU;SAC7B;QACD,MAAM;QACP;;AAEH,UAAI,SAAS,WAAW,OACtB,mBAAkB;OAChB,GAAI;OACJ,MAAM,SAAS;OAChB;;KAIL,MAAM,SAAS,YAAY,iBAAiB;MAC1C,WAAW,SAAS;MACpB,SAAS;OACP,SAAS,gBAAgB;OACzB,OAAO,gBAAgB;OACxB;MACF,CAAC;AAEF,SADuB,QAAgB,YACjB,MAKpB,QAAO;MACL,SAAS;MACT,OAAO,qBANS,QAAgB,SAAS;OACzC,MAAM;OACN,SAAS;OACV,CAGsC;MACrC,MAAM;MACP;AAEH,YAAO;MAAE,SAAS;MAAM,MAAM;MAAQ;aAC/B,KAAc;KAIrB,MAAM,kBAAkB,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU,QAAQ;KAClF,MAAM,gBAAgB,MAAM,QAAQ,KAAK,OAAO,GAAI,KAAK,SAAsB;KAC/E,MAAM,gBAAgB,YAAY,MAAM;MACtC,WAAW,SAAS;MACpB,SAAS;OAAE,SAAS;OAAiB,OAAO;OAAe;MAC5D,CAAC;AACF,YAAO;MAAE,SAAS;MAAO,OAAO,qBAAqB,IAAI;MAAE,MAAM;MAAe;;;GAGpF;GACA;GACD;EA2CC,QAzCwC;GACxC,OAAO;GACP,aAAa,YAAY,QAAS,GAAI;GACtC,SAAS,OAAO,SAAS;IACvB,MAAM,UAAU,KAAK;AACrB,QAAI,QAIF,QAAO;KACL,SAAS;KACT,OAAO;MAAE,MAAM;MAAqB,SAAS,YAAY,QAAQ;MAAc;KAChF;AAEH,WAAO;KAAE,SAAS;KAAM,MAAM,EAAE,WAAW,MAAM;KAAE;;GAErD;GACA;GACD;EAwBC,QAtBwC;GACxC,OAAO;GACP,aAAa,YAAY,QAAS,GAAI;GACtC,SAAS,OAAO,SAAS;IACvB,MAAM,UAAU,KAAK;AACrB,QAAI,QAEF,QAAO;KACL,SAAS;KACT,OAAO;MAAE,MAAM;MAAqB,SAAS,YAAY,QAAQ;MAAc;KAChF;AAGH,WAAO;KAAE,SAAS;KAAM,MAAM,EAAE,OAAO,WAAW;KAAE;;GAEtD;GACA;GACD;EAMA"}
|