@goondocks/myco 0.21.0 → 0.21.1
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/bin/myco-run +68 -7
- package/dist/{agent-eval-RJSQI5S2.js → agent-eval-YK2VP2S4.js} +7 -6
- package/dist/{agent-eval-RJSQI5S2.js.map → agent-eval-YK2VP2S4.js.map} +1 -1
- package/dist/{agent-run-2JSYFOKU.js → agent-run-GEJBD2YD.js} +5 -5
- package/dist/{agent-tasks-APFJIM2T.js → agent-tasks-5XSRGTRX.js} +5 -5
- package/dist/{chunk-R2JIJBCL.js → chunk-6ALVMIB4.js} +3 -3
- package/dist/{chunk-JZS6GZ6T.js → chunk-AUIXX33A.js} +10 -3
- package/dist/chunk-AUIXX33A.js.map +1 -0
- package/dist/{chunk-RL5R4CQU.js → chunk-DTWUHHFI.js} +39 -2
- package/dist/{chunk-RL5R4CQU.js.map → chunk-DTWUHHFI.js.map} +1 -1
- package/dist/{chunk-CESKJD44.js → chunk-EEOJWLMP.js} +5 -9
- package/dist/chunk-EEOJWLMP.js.map +1 -0
- package/dist/{chunk-BUTL6IFS.js → chunk-ENZR5NG7.js} +2 -2
- package/dist/{chunk-P66DLD6G.js → chunk-KTTSXYEK.js} +2 -2
- package/dist/chunk-LQIPXVDH.js +17 -0
- package/dist/chunk-LQIPXVDH.js.map +1 -0
- package/dist/{chunk-5ZG4RMUH.js → chunk-N2DGFACQ.js} +2 -2
- package/dist/{chunk-F3OEQYLS.js → chunk-N7Z3LUEZ.js} +33 -22
- package/dist/{chunk-F3OEQYLS.js.map → chunk-N7Z3LUEZ.js.map} +1 -1
- package/dist/{chunk-G6QIBNZM.js → chunk-NFO7BRCO.js} +4 -4
- package/dist/{chunk-VHNRMM4O.js → chunk-OTQH5KZW.js} +87 -37
- package/dist/chunk-OTQH5KZW.js.map +1 -0
- package/dist/{chunk-DJ3IHNYO.js → chunk-OZ3FBAK5.js} +2 -2
- package/dist/{chunk-6LB7XELY.js → chunk-QATYARI5.js} +15 -13
- package/dist/chunk-QATYARI5.js.map +1 -0
- package/dist/{chunk-JR54LTPP.js → chunk-QDLVIW2O.js} +3 -3
- package/dist/{chunk-LVIY7P35.js → chunk-QLLBJEM7.js} +5 -1
- package/dist/chunk-QLLBJEM7.js.map +1 -0
- package/dist/chunk-TSM6VESW.js +25 -0
- package/dist/chunk-TSM6VESW.js.map +1 -0
- package/dist/{chunk-ILJPRYES.js → chunk-USVFEWYL.js} +2 -2
- package/dist/{chunk-75Z7UKDY.js → chunk-VRI56337.js} +2 -2
- package/dist/{chunk-NGH7U6A3.js → chunk-X2IRGXGF.js} +336 -77
- package/dist/chunk-X2IRGXGF.js.map +1 -0
- package/dist/{chunk-NGROSFOH.js → chunk-Z66IT5KL.js} +14 -9
- package/dist/chunk-Z66IT5KL.js.map +1 -0
- package/dist/{cli-LNYSTDQM.js → cli-HSLIG7EX.js} +37 -37
- package/dist/{client-NWE4TCNO.js → client-Z43DNLJH.js} +3 -3
- package/dist/{detect-PXNM6TA7.js → detect-7NUD5B5R.js} +2 -2
- package/dist/{doctor-TI7EZ3RW.js → doctor-HJCWHAU4.js} +6 -6
- package/dist/{executor-F2YU7HXJ.js → executor-DO6QFC6G.js} +11 -10
- package/dist/{init-KG3TYVGE.js → init-4KVK7W2E.js} +9 -9
- package/dist/{installer-UMH7OJ5A.js → installer-N4UTEACX.js} +2 -2
- package/dist/{loader-NAVVZK63.js → loader-UDNUMEDA.js} +3 -2
- package/dist/{main-5PRQNEEE.js → main-4J4QZZTZ.js} +121 -62
- package/dist/main-4J4QZZTZ.js.map +1 -0
- package/dist/{open-5A27BCSB.js → open-7TXJQM3H.js} +5 -5
- package/dist/{post-compact-USAODKPQ.js → post-compact-7AEFVCZS.js} +7 -7
- package/dist/{post-tool-use-GMMSYBII.js → post-tool-use-TZINWWDH.js} +6 -6
- package/dist/{post-tool-use-failure-NZVSL2PO.js → post-tool-use-failure-TCFEU2GI.js} +7 -7
- package/dist/{pre-compact-LZ57DLUS.js → pre-compact-LO2VZCGR.js} +7 -7
- package/dist/{registry-M2Z5QBWH.js → registry-F3THYC5M.js} +4 -3
- package/dist/{remove-T3KE6C5N.js → remove-F77AAALE.js} +7 -7
- package/dist/{restart-YWDEVZUJ.js → restart-UEFDPMLT.js} +6 -6
- package/dist/{search-GKFDGELR.js → search-NHNVUAQQ.js} +6 -6
- package/dist/{server-AHUR6CWF.js → server-AZJSTQEK.js} +5 -5
- package/dist/{session-2ZEPLWW6.js → session-3HLC5KOD.js} +5 -5
- package/dist/{session-end-LWJYQAXX.js → session-end-FS46UARX.js} +6 -6
- package/dist/{session-start-WTA6GCOQ.js → session-start-46KPFV2H.js} +10 -10
- package/dist/{setup-llm-E7UU5IO7.js → setup-llm-JMWSNQ2C.js} +5 -5
- package/dist/src/agent/definitions/tasks/cortex-instructions.yaml +63 -41
- package/dist/src/agent/definitions/tasks/skill-evolve.yaml +177 -21
- package/dist/src/agent/definitions/tasks/skill-generate.yaml +20 -6
- package/dist/src/agent/definitions/tasks/vault-evolve.yaml +65 -55
- package/dist/src/cli.js +1 -1
- package/dist/src/daemon/main.js +1 -1
- package/dist/src/hooks/post-tool-use.js +1 -1
- package/dist/src/hooks/session-end.js +1 -1
- package/dist/src/hooks/session-start.js +1 -1
- package/dist/src/hooks/stop.js +1 -1
- package/dist/src/hooks/user-prompt-submit.js +1 -1
- package/dist/src/mcp/server.js +1 -1
- package/dist/src/symbionts/manifests/opencode.yaml +7 -0
- package/dist/src/symbionts/templates/agents-starter.md +1 -1
- package/dist/{stats-DFG6S23S.js → stats-MKMETHMA.js} +6 -6
- package/dist/{stop-WRBTXEVT.js → stop-OUEX6KA4.js} +6 -6
- package/dist/{stop-failure-32MGIG2Q.js → stop-failure-2BWVNZEG.js} +7 -7
- package/dist/{subagent-start-VFGHQFVL.js → subagent-start-J4VV6DEE.js} +7 -7
- package/dist/{subagent-stop-663FXG3P.js → subagent-stop-JMLVEPIA.js} +7 -7
- package/dist/{task-completed-ZCQYEFMZ.js → task-completed-65CHMMKA.js} +7 -7
- package/dist/{team-JTI5CDUO.js → team-U2LDKIS4.js} +3 -3
- package/dist/ui/assets/{index-DGf1h-Ha.js → index-BUGor9dk.js} +1 -1
- package/dist/ui/index.html +1 -1
- package/dist/{update-3NBQTG32.js → update-ZSHVXWSQ.js} +7 -7
- package/dist/{user-prompt-submit-ME2TBKOS.js → user-prompt-submit-APMO6FVU.js} +6 -6
- package/dist/{version-GQAFBBPX.js → version-TXPPS3L5.js} +2 -2
- package/package.json +1 -1
- package/skills/myco-rules/SKILL.md +94 -0
- package/skills/{rules → myco-rules}/references/rules-bad-example.md +1 -1
- package/skills/{rules → myco-rules}/references/rules-good-example.md +1 -1
- package/dist/chunk-6LB7XELY.js.map +0 -1
- package/dist/chunk-CESKJD44.js.map +0 -1
- package/dist/chunk-CUDIZJY7.js +0 -36
- package/dist/chunk-CUDIZJY7.js.map +0 -1
- package/dist/chunk-JZS6GZ6T.js.map +0 -1
- package/dist/chunk-LVIY7P35.js.map +0 -1
- package/dist/chunk-NGH7U6A3.js.map +0 -1
- package/dist/chunk-NGROSFOH.js.map +0 -1
- package/dist/chunk-VHNRMM4O.js.map +0 -1
- package/dist/main-5PRQNEEE.js.map +0 -1
- package/skills/myco-curate/SKILL.md +0 -86
- package/skills/rules/SKILL.md +0 -214
- /package/dist/{agent-run-2JSYFOKU.js.map → agent-run-GEJBD2YD.js.map} +0 -0
- /package/dist/{agent-tasks-APFJIM2T.js.map → agent-tasks-5XSRGTRX.js.map} +0 -0
- /package/dist/{chunk-R2JIJBCL.js.map → chunk-6ALVMIB4.js.map} +0 -0
- /package/dist/{chunk-BUTL6IFS.js.map → chunk-ENZR5NG7.js.map} +0 -0
- /package/dist/{chunk-P66DLD6G.js.map → chunk-KTTSXYEK.js.map} +0 -0
- /package/dist/{chunk-5ZG4RMUH.js.map → chunk-N2DGFACQ.js.map} +0 -0
- /package/dist/{chunk-G6QIBNZM.js.map → chunk-NFO7BRCO.js.map} +0 -0
- /package/dist/{chunk-DJ3IHNYO.js.map → chunk-OZ3FBAK5.js.map} +0 -0
- /package/dist/{chunk-JR54LTPP.js.map → chunk-QDLVIW2O.js.map} +0 -0
- /package/dist/{chunk-ILJPRYES.js.map → chunk-USVFEWYL.js.map} +0 -0
- /package/dist/{chunk-75Z7UKDY.js.map → chunk-VRI56337.js.map} +0 -0
- /package/dist/{cli-LNYSTDQM.js.map → cli-HSLIG7EX.js.map} +0 -0
- /package/dist/{client-NWE4TCNO.js.map → client-Z43DNLJH.js.map} +0 -0
- /package/dist/{detect-PXNM6TA7.js.map → detect-7NUD5B5R.js.map} +0 -0
- /package/dist/{doctor-TI7EZ3RW.js.map → doctor-HJCWHAU4.js.map} +0 -0
- /package/dist/{executor-F2YU7HXJ.js.map → executor-DO6QFC6G.js.map} +0 -0
- /package/dist/{init-KG3TYVGE.js.map → init-4KVK7W2E.js.map} +0 -0
- /package/dist/{installer-UMH7OJ5A.js.map → installer-N4UTEACX.js.map} +0 -0
- /package/dist/{loader-NAVVZK63.js.map → loader-UDNUMEDA.js.map} +0 -0
- /package/dist/{open-5A27BCSB.js.map → open-7TXJQM3H.js.map} +0 -0
- /package/dist/{post-compact-USAODKPQ.js.map → post-compact-7AEFVCZS.js.map} +0 -0
- /package/dist/{post-tool-use-GMMSYBII.js.map → post-tool-use-TZINWWDH.js.map} +0 -0
- /package/dist/{post-tool-use-failure-NZVSL2PO.js.map → post-tool-use-failure-TCFEU2GI.js.map} +0 -0
- /package/dist/{pre-compact-LZ57DLUS.js.map → pre-compact-LO2VZCGR.js.map} +0 -0
- /package/dist/{registry-M2Z5QBWH.js.map → registry-F3THYC5M.js.map} +0 -0
- /package/dist/{remove-T3KE6C5N.js.map → remove-F77AAALE.js.map} +0 -0
- /package/dist/{restart-YWDEVZUJ.js.map → restart-UEFDPMLT.js.map} +0 -0
- /package/dist/{search-GKFDGELR.js.map → search-NHNVUAQQ.js.map} +0 -0
- /package/dist/{server-AHUR6CWF.js.map → server-AZJSTQEK.js.map} +0 -0
- /package/dist/{session-2ZEPLWW6.js.map → session-3HLC5KOD.js.map} +0 -0
- /package/dist/{session-end-LWJYQAXX.js.map → session-end-FS46UARX.js.map} +0 -0
- /package/dist/{session-start-WTA6GCOQ.js.map → session-start-46KPFV2H.js.map} +0 -0
- /package/dist/{setup-llm-E7UU5IO7.js.map → setup-llm-JMWSNQ2C.js.map} +0 -0
- /package/dist/{stats-DFG6S23S.js.map → stats-MKMETHMA.js.map} +0 -0
- /package/dist/{stop-WRBTXEVT.js.map → stop-OUEX6KA4.js.map} +0 -0
- /package/dist/{stop-failure-32MGIG2Q.js.map → stop-failure-2BWVNZEG.js.map} +0 -0
- /package/dist/{subagent-start-VFGHQFVL.js.map → subagent-start-J4VV6DEE.js.map} +0 -0
- /package/dist/{subagent-stop-663FXG3P.js.map → subagent-stop-JMLVEPIA.js.map} +0 -0
- /package/dist/{task-completed-ZCQYEFMZ.js.map → task-completed-65CHMMKA.js.map} +0 -0
- /package/dist/{team-JTI5CDUO.js.map → team-U2LDKIS4.js.map} +0 -0
- /package/dist/{update-3NBQTG32.js.map → update-ZSHVXWSQ.js.map} +0 -0
- /package/dist/{user-prompt-submit-ME2TBKOS.js.map → user-prompt-submit-APMO6FVU.js.map} +0 -0
- /package/dist/{version-GQAFBBPX.js.map → version-TXPPS3L5.js.map} +0 -0
|
@@ -8,21 +8,22 @@ import {
|
|
|
8
8
|
buildRunAccountingUpdate,
|
|
9
9
|
buildUsageData,
|
|
10
10
|
checkpointResultsForResume,
|
|
11
|
-
errorMessage,
|
|
12
11
|
inferRuntimeFromProviderType,
|
|
12
|
+
isExpiredSessionError,
|
|
13
13
|
isSessionResumeFailure,
|
|
14
14
|
parseCheckpointState,
|
|
15
15
|
resolveProviderForResume,
|
|
16
16
|
serializeCheckpointState,
|
|
17
17
|
summarizePhaseCosts
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-QATYARI5.js";
|
|
19
19
|
import {
|
|
20
20
|
fullTextSearch,
|
|
21
|
-
hydrateSearchResults
|
|
22
|
-
|
|
21
|
+
hydrateSearchResults,
|
|
22
|
+
sanitizeFtsQuery
|
|
23
|
+
} from "./chunk-QLLBJEM7.js";
|
|
23
24
|
import {
|
|
24
25
|
loadAllTasks
|
|
25
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-USVFEWYL.js";
|
|
26
27
|
import {
|
|
27
28
|
getAgent,
|
|
28
29
|
getDefaultTask,
|
|
@@ -31,7 +32,10 @@ import {
|
|
|
31
32
|
loadSystemPrompt,
|
|
32
33
|
resolveDefinitionsDir,
|
|
33
34
|
resolveEffectiveConfig
|
|
34
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-AUIXX33A.js";
|
|
36
|
+
import {
|
|
37
|
+
errorMessage
|
|
38
|
+
} from "./chunk-LQIPXVDH.js";
|
|
35
39
|
import {
|
|
36
40
|
countToolCallsByRun,
|
|
37
41
|
insertTurn,
|
|
@@ -64,7 +68,7 @@ import {
|
|
|
64
68
|
updateSporeStatus,
|
|
65
69
|
upsertCortexInstructions,
|
|
66
70
|
upsertDigestExtract
|
|
67
|
-
} from "./chunk-
|
|
71
|
+
} from "./chunk-N7Z3LUEZ.js";
|
|
68
72
|
import {
|
|
69
73
|
countSessions,
|
|
70
74
|
getActiveSessionIds,
|
|
@@ -78,7 +82,7 @@ import {
|
|
|
78
82
|
AGENT_SETTABLE_STATUSES,
|
|
79
83
|
CANDIDATE_STATUS,
|
|
80
84
|
createSchema
|
|
81
|
-
} from "./chunk-
|
|
85
|
+
} from "./chunk-DTWUHHFI.js";
|
|
82
86
|
import {
|
|
83
87
|
loadMergedConfig
|
|
84
88
|
} from "./chunk-53RPGOEN.js";
|
|
@@ -89,7 +93,7 @@ import {
|
|
|
89
93
|
} from "./chunk-MYX5NCRH.js";
|
|
90
94
|
import {
|
|
91
95
|
getPluginVersion
|
|
92
|
-
} from "./chunk-
|
|
96
|
+
} from "./chunk-ENZR5NG7.js";
|
|
93
97
|
import {
|
|
94
98
|
findPackageRoot
|
|
95
99
|
} from "./chunk-LPUQPDC2.js";
|
|
@@ -97,6 +101,7 @@ import {
|
|
|
97
101
|
CONTENT_HASH_ALGORITHM,
|
|
98
102
|
DEFAULT_AGENT_ID,
|
|
99
103
|
DEFAULT_LIST_LIMIT,
|
|
104
|
+
DIGEST_TIERS,
|
|
100
105
|
EDGE_TYPE_DERIVED_FROM,
|
|
101
106
|
EDGE_TYPE_EXTRACTED_FROM,
|
|
102
107
|
EDGE_TYPE_FROM_SESSION,
|
|
@@ -197,6 +202,7 @@ var STATUS_RUNNING = "running";
|
|
|
197
202
|
var STATUS_COMPLETED = "completed";
|
|
198
203
|
var STATUS_FAILED = "failed";
|
|
199
204
|
var RESUME_STATUS_READY = "ready";
|
|
205
|
+
var RESUME_STATUS_SESSION_EXPIRED = "session_expired";
|
|
200
206
|
var RUN_COLUMNS = [
|
|
201
207
|
"id",
|
|
202
208
|
"agent_id",
|
|
@@ -2403,6 +2409,7 @@ var ORCHESTRATOR_GUIDANCE_HEADER = "## Orchestrator Guidance";
|
|
|
2403
2409
|
var NO_CONTEXT_QUERIES_TEXT = "No context queries configured.";
|
|
2404
2410
|
var FALLBACK_REASONING_PARSE_ERROR = "Orchestrator response could not be parsed \u2014 running all phases with defaults.";
|
|
2405
2411
|
var FALLBACK_REASONING_MISSING_PHASES = "Orchestrator plan missing phases array \u2014 running all phases with defaults.";
|
|
2412
|
+
var ORCHESTRATOR_PARSE_ERROR_PREVIEW_CHARS = 200;
|
|
2406
2413
|
var PLACEHOLDER_VAULT_STATE = "{{vault_state}}";
|
|
2407
2414
|
var PLACEHOLDER_PHASE_DEFINITIONS = "{{phase_definitions}}";
|
|
2408
2415
|
var PLACEHOLDER_CONTEXT_RESULTS = "{{context_results}}";
|
|
@@ -2436,7 +2443,7 @@ function composeOrchestratorPrompt(vaultState, phases, contextResults) {
|
|
|
2436
2443
|
const contextSection = formatContextResults(contextResults);
|
|
2437
2444
|
return template.replace(PLACEHOLDER_VAULT_STATE, vaultState).replace(PLACEHOLDER_PHASE_DEFINITIONS, phaseList).replace(PLACEHOLDER_CONTEXT_RESULTS, contextSection);
|
|
2438
2445
|
}
|
|
2439
|
-
function parseOrchestratorPlan(response, phases) {
|
|
2446
|
+
function parseOrchestratorPlan(response, phases, logger) {
|
|
2440
2447
|
const trimmed = response.trim();
|
|
2441
2448
|
if (!trimmed) {
|
|
2442
2449
|
return buildRunAllPlan(phases, FALLBACK_REASONING_PARSE_ERROR);
|
|
@@ -2447,8 +2454,14 @@ function parseOrchestratorPlan(response, phases) {
|
|
|
2447
2454
|
return buildRunAllPlan(phases, FALLBACK_REASONING_MISSING_PHASES);
|
|
2448
2455
|
}
|
|
2449
2456
|
return parsed;
|
|
2450
|
-
} catch {
|
|
2451
|
-
|
|
2457
|
+
} catch (err) {
|
|
2458
|
+
const detail = errorMessage(err);
|
|
2459
|
+
const truncated = detail.length > ORCHESTRATOR_PARSE_ERROR_PREVIEW_CHARS ? `${detail.slice(0, ORCHESTRATOR_PARSE_ERROR_PREVIEW_CHARS)}\u2026` : detail;
|
|
2460
|
+
logger?.warn("agent.orchestrator.parse-failed", "Orchestrator plan parse failed", {
|
|
2461
|
+
error: detail,
|
|
2462
|
+
responsePreview: trimmed.slice(0, 200)
|
|
2463
|
+
});
|
|
2464
|
+
return buildRunAllPlan(phases, `${FALLBACK_REASONING_PARSE_ERROR} (${truncated})`);
|
|
2452
2465
|
}
|
|
2453
2466
|
}
|
|
2454
2467
|
function applyDirectives(phases, directives) {
|
|
@@ -3355,23 +3368,36 @@ function createReadTools(deps) {
|
|
|
3355
3368
|
);
|
|
3356
3369
|
const vaultSearchFts = tool(
|
|
3357
3370
|
"vault_search_fts",
|
|
3358
|
-
|
|
3371
|
+
'Full-text search across sessions, spores, prompt batches, and activities using FTS5. Best for finding exact keywords, file paths, function names, and specific text. You can pass natural-language queries containing hyphens, slashes, dots, etc. \u2014 the tool auto-quotes tokens with non-word characters so file paths and hyphenated identifiers (e.g., "skill-evolve-inventory", "packages/myco/src/loader.ts") are treated as literal phrases instead of being rejected by FTS5 MATCH syntax. Plain alphanumeric/underscore tokens are left unquoted so they AND together normally. Results from in-flight sessions are hidden by default so intelligence tasks only see settled work; pass include_active=true to bypass.',
|
|
3359
3372
|
{
|
|
3360
|
-
query: external_exports.string().describe("Search query text"),
|
|
3373
|
+
query: external_exports.string().describe("Search query text. Special characters (hyphens, slashes, dots, colons) are auto-quoted \u2014 no manual escaping needed."),
|
|
3361
3374
|
type: external_exports.string().optional().describe("Restrict to a result type (session, spore, prompt_batch, activity)"),
|
|
3362
3375
|
limit: external_exports.number().optional().describe("Maximum number of results to return"),
|
|
3363
3376
|
include_active: external_exports.boolean().optional().describe("Include results from sessions still in active status (default: false)")
|
|
3364
3377
|
},
|
|
3365
3378
|
async (args) => {
|
|
3379
|
+
const sanitizedQuery = sanitizeFtsQuery(args.query);
|
|
3366
3380
|
try {
|
|
3367
|
-
const results = fullTextSearch(
|
|
3381
|
+
const results = fullTextSearch(sanitizedQuery, {
|
|
3368
3382
|
type: args.type,
|
|
3369
3383
|
limit: args.limit ?? DEFAULT_SEARCH_LIMIT,
|
|
3370
3384
|
includeActive: args.include_active === true
|
|
3371
3385
|
});
|
|
3372
|
-
return textResult({ results });
|
|
3373
|
-
} catch {
|
|
3374
|
-
|
|
3386
|
+
return textResult({ results, sanitized_query: sanitizedQuery !== args.query ? sanitizedQuery : void 0 });
|
|
3387
|
+
} catch (err) {
|
|
3388
|
+
const message = errorMessage(err);
|
|
3389
|
+
let hint;
|
|
3390
|
+
if (/no such table|no such module: fts5/i.test(message)) {
|
|
3391
|
+
hint = "FTS index missing \u2014 the searched table may not have an FTS5 mirror. Check the type parameter.";
|
|
3392
|
+
} else if (/syntax error|malformed MATCH/i.test(message)) {
|
|
3393
|
+
hint = 'FTS5 query syntax rejected. Quote special characters (e.g., wrap file paths in double quotes: "packages/myco/src/loader.ts").';
|
|
3394
|
+
}
|
|
3395
|
+
return textResult({
|
|
3396
|
+
error: `vault_search_fts failed: ${message}${hint ? ` \u2014 ${hint}` : ""}`,
|
|
3397
|
+
results: [],
|
|
3398
|
+
query: args.query,
|
|
3399
|
+
type: args.type ?? null
|
|
3400
|
+
});
|
|
3375
3401
|
}
|
|
3376
3402
|
},
|
|
3377
3403
|
{ annotations: { readOnlyHint: true } }
|
|
@@ -3427,8 +3453,22 @@ function createReadTools(deps) {
|
|
|
3427
3453
|
...dedupedTeam
|
|
3428
3454
|
].sort((a, b) => (b.score ?? 0) - (a.score ?? 0)).slice(0, searchLimit);
|
|
3429
3455
|
return textResult({ results: merged });
|
|
3430
|
-
} catch {
|
|
3431
|
-
|
|
3456
|
+
} catch (err) {
|
|
3457
|
+
const message = errorMessage(err);
|
|
3458
|
+
let hint;
|
|
3459
|
+
if (/timeout|ETIMEDOUT|AbortError/i.test(message)) {
|
|
3460
|
+
hint = "Embedding provider timed out. Retry once or reduce query length.";
|
|
3461
|
+
} else if (/ECONNREFUSED|fetch failed|network/i.test(message)) {
|
|
3462
|
+
hint = "Embedding provider unreachable. Check that the configured provider (Ollama/LM Studio/Anthropic) is running.";
|
|
3463
|
+
} else if (/no such table|no such column/i.test(message)) {
|
|
3464
|
+
hint = "Vector table missing or schema mismatch. Run `myco rebuild` or check migrations.";
|
|
3465
|
+
}
|
|
3466
|
+
return textResult({
|
|
3467
|
+
error: `vault_search_semantic failed: ${message}${hint ? ` \u2014 ${hint}` : ""}`,
|
|
3468
|
+
results: [],
|
|
3469
|
+
query: args.query,
|
|
3470
|
+
namespace: args.namespace ?? null
|
|
3471
|
+
});
|
|
3432
3472
|
}
|
|
3433
3473
|
},
|
|
3434
3474
|
{ annotations: { readOnlyHint: true, openWorldHint: true } }
|
|
@@ -3726,12 +3766,54 @@ function createWriteTools(deps) {
|
|
|
3726
3766
|
);
|
|
3727
3767
|
const vaultReadDigest = tool2(
|
|
3728
3768
|
"vault_read_digest",
|
|
3729
|
-
|
|
3769
|
+
'Read current digest extracts. Three modes: (1) no args \u2192 summary metadata for all tiers; (2) tier \u2192 full content for that tier; (3) pick: "rotate_oldest" \u2192 the digest-rotation decision, returning the tier whose generated_at is oldest plus its full content (or skip:true when all tiers are fresher than min_staleness_seconds). The rotation mode lets callers outsource the "which tier should we update this run" choice to a deterministic tool decision instead of prompting the LLM to compare timestamps.',
|
|
3730
3770
|
{
|
|
3731
|
-
tier: external_exports.number().optional().describe("Specific tier to read in full (e.g., 1500, 5000, 10000). Omit to get summary of all tiers.")
|
|
3771
|
+
tier: external_exports.number().optional().describe("Specific tier to read in full (e.g., 1500, 5000, 10000). Omit to get summary of all tiers. Ignored when pick is set."),
|
|
3772
|
+
pick: external_exports.enum(["rotate_oldest"]).optional().describe('Rotation mode. "rotate_oldest" picks the tier with the oldest generated_at (missing tiers count as never-generated and sort first). The response includes the selected tier, its full content, a rotation_reason explaining the choice, and metadata for all tiers so the caller can audit the decision.'),
|
|
3773
|
+
min_staleness_seconds: external_exports.number().optional().describe(`Used with pick="rotate_oldest". If every tier's generated_at is newer than (now - min_staleness_seconds), the tool returns {skip: true, reason, all_tiers} instead of selecting a tier. Defaults to 0 (never skip).`)
|
|
3732
3774
|
},
|
|
3733
3775
|
async (args) => {
|
|
3734
3776
|
const extracts = listDigestExtracts(agentId);
|
|
3777
|
+
if (args.pick === "rotate_oldest") {
|
|
3778
|
+
const now = epochSeconds();
|
|
3779
|
+
const canonical = DIGEST_TIERS.map((tier) => {
|
|
3780
|
+
const existing = extracts.find((e) => e.tier === tier);
|
|
3781
|
+
return {
|
|
3782
|
+
tier,
|
|
3783
|
+
generated_at: existing?.generated_at ?? 0,
|
|
3784
|
+
content_length: existing?.content.length ?? 0,
|
|
3785
|
+
content: existing?.content ?? null
|
|
3786
|
+
};
|
|
3787
|
+
});
|
|
3788
|
+
const minStale = args.min_staleness_seconds ?? 0;
|
|
3789
|
+
if (minStale > 0) {
|
|
3790
|
+
const allPresent = canonical.every((t) => t.generated_at > 0);
|
|
3791
|
+
const cutoff = now - minStale;
|
|
3792
|
+
const allFresh = canonical.every((t) => t.generated_at > cutoff);
|
|
3793
|
+
if (allPresent && allFresh) {
|
|
3794
|
+
return textResult({
|
|
3795
|
+
mode: "rotate_oldest",
|
|
3796
|
+
skip: true,
|
|
3797
|
+
reason: `All ${canonical.length} tiers were generated within the last ${minStale} seconds (cutoff=${cutoff}).`,
|
|
3798
|
+
all_tiers: canonical.map((t) => ({ tier: t.tier, generated_at: t.generated_at, content_length: t.content_length }))
|
|
3799
|
+
});
|
|
3800
|
+
}
|
|
3801
|
+
}
|
|
3802
|
+
const sorted = [...canonical].sort((a, b) => {
|
|
3803
|
+
if (a.generated_at !== b.generated_at) return a.generated_at - b.generated_at;
|
|
3804
|
+
return b.tier - a.tier;
|
|
3805
|
+
});
|
|
3806
|
+
const selected = sorted[0];
|
|
3807
|
+
const reason = selected.generated_at === 0 ? `Tier ${selected.tier} has never been generated \u2014 seeding.` : `Tier ${selected.tier} has the oldest generated_at (${selected.generated_at}); next oldest is tier ${sorted[1]?.tier} at ${sorted[1]?.generated_at}.`;
|
|
3808
|
+
return textResult({
|
|
3809
|
+
mode: "rotate_oldest",
|
|
3810
|
+
selected_tier: selected.tier,
|
|
3811
|
+
selected_generated_at: selected.generated_at,
|
|
3812
|
+
selected_content: selected.content,
|
|
3813
|
+
rotation_reason: reason,
|
|
3814
|
+
all_tiers: canonical.map((t) => ({ tier: t.tier, generated_at: t.generated_at, content_length: t.content_length }))
|
|
3815
|
+
});
|
|
3816
|
+
}
|
|
3735
3817
|
if (args.tier !== void 0) {
|
|
3736
3818
|
const extract = extracts.find((e) => e.tier === args.tier);
|
|
3737
3819
|
if (!extract) return textResult({ tier: args.tier, content: null, message: "No digest at this tier" });
|
|
@@ -4131,7 +4213,7 @@ function createSkillTools(deps) {
|
|
|
4131
4213
|
);
|
|
4132
4214
|
}
|
|
4133
4215
|
try {
|
|
4134
|
-
const { syncSkillSymlinks } = await import("./installer-
|
|
4216
|
+
const { syncSkillSymlinks } = await import("./installer-N4UTEACX.js");
|
|
4135
4217
|
syncSkillSymlinks(root, params.name, { remove: true });
|
|
4136
4218
|
} catch (rollbackErr) {
|
|
4137
4219
|
console.warn(
|
|
@@ -4149,7 +4231,7 @@ function createSkillTools(deps) {
|
|
|
4149
4231
|
};
|
|
4150
4232
|
}
|
|
4151
4233
|
try {
|
|
4152
|
-
const { syncSkillSymlinks } = await import("./installer-
|
|
4234
|
+
const { syncSkillSymlinks } = await import("./installer-N4UTEACX.js");
|
|
4153
4235
|
syncSkillSymlinks(root, params.name);
|
|
4154
4236
|
} catch (err) {
|
|
4155
4237
|
console.warn(
|
|
@@ -4351,14 +4433,15 @@ function createSkillTools(deps) {
|
|
|
4351
4433
|
);
|
|
4352
4434
|
const vaultSkillRecords = tool4(
|
|
4353
4435
|
"vault_skill_records",
|
|
4354
|
-
"Read, update, and delete skill records (materialized skills on disk). Supports list, get, update, and delete actions. The get action includes the full SKILL.md file content.",
|
|
4436
|
+
"Read, update, and delete skill records (materialized skills on disk). Supports list, get, update, and delete actions. The get action includes the full SKILL.md file content. For update, at least one mutating field (status, generation, source_ids, description, or properties) is required \u2014 calls with only {action, id} are rejected to prevent silent no-op updates.",
|
|
4355
4437
|
{
|
|
4356
4438
|
action: external_exports.enum(["list", "get", "update", "delete"]).describe("Action to perform"),
|
|
4357
4439
|
id: external_exports.string().optional().describe("Skill record ID or name (required for get/update/delete)"),
|
|
4358
|
-
status: external_exports.enum(["active", "stale", "retired"]).optional().describe("Filter by status"),
|
|
4440
|
+
status: external_exports.enum(["active", "stale", "retired"]).optional().describe("Filter by status or new status (for update)"),
|
|
4359
4441
|
generation: external_exports.number().optional().describe("New generation number (for update)"),
|
|
4360
4442
|
source_ids: external_exports.string().optional().describe("JSON array of source IDs (for update)"),
|
|
4361
4443
|
description: external_exports.string().optional().describe("Updated description (for update)"),
|
|
4444
|
+
properties: external_exports.string().optional().describe(`JSON-encoded object of properties to MERGE into the existing properties (for update). Example: '{"last_verified_at": 1776580022}'. Existing keys not included in the payload are preserved; included keys overwrite. Used by skill-evolve to persist watermarks like last_assessed_at, knowledge_watermark, last_verified_at, last_classification.`),
|
|
4362
4445
|
limit: external_exports.number().optional().describe("Maximum records to return (for list)")
|
|
4363
4446
|
},
|
|
4364
4447
|
async (args) => {
|
|
@@ -4386,14 +4469,44 @@ function createSkillTools(deps) {
|
|
|
4386
4469
|
}
|
|
4387
4470
|
case "update": {
|
|
4388
4471
|
if (!args.id) return textResult({ error: "id is required for update action" });
|
|
4472
|
+
const hasMutatingField = args.status !== void 0 || args.generation !== void 0 || args.source_ids !== void 0 || args.description !== void 0 || args.properties !== void 0;
|
|
4473
|
+
if (!hasMutatingField) {
|
|
4474
|
+
return textResult({
|
|
4475
|
+
error: "update action requires at least one mutating field (status, generation, source_ids, description, or properties). Calls with only {action, id} are rejected to prevent silent no-op updates."
|
|
4476
|
+
});
|
|
4477
|
+
}
|
|
4389
4478
|
const existing = getSkillRecord(args.id) ?? getSkillRecordByName(args.id);
|
|
4390
4479
|
if (!existing) return textResult({ error: `Skill record not found: ${args.id}` });
|
|
4480
|
+
let mergedProperties;
|
|
4481
|
+
if (args.properties !== void 0) {
|
|
4482
|
+
let incoming;
|
|
4483
|
+
try {
|
|
4484
|
+
const parsed = JSON.parse(args.properties);
|
|
4485
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
4486
|
+
return textResult({ error: "properties must be a JSON-encoded object (not null, array, or primitive)." });
|
|
4487
|
+
}
|
|
4488
|
+
incoming = parsed;
|
|
4489
|
+
} catch (err) {
|
|
4490
|
+
return textResult({ error: `properties is not valid JSON: ${errorMessage(err)}` });
|
|
4491
|
+
}
|
|
4492
|
+
let existingProps = {};
|
|
4493
|
+
try {
|
|
4494
|
+
const parsedExisting = JSON.parse(existing.properties || "{}");
|
|
4495
|
+
if (parsedExisting && typeof parsedExisting === "object" && !Array.isArray(parsedExisting)) {
|
|
4496
|
+
existingProps = parsedExisting;
|
|
4497
|
+
}
|
|
4498
|
+
} catch (err) {
|
|
4499
|
+
console.warn(`[vault_skill_records] Skill ${existing.id} has unparseable properties; treating as empty for merge. Error: ${errorMessage(err)}`);
|
|
4500
|
+
}
|
|
4501
|
+
mergedProperties = JSON.stringify({ ...existingProps, ...incoming });
|
|
4502
|
+
}
|
|
4391
4503
|
const now = epochSeconds();
|
|
4392
4504
|
const updated = updateSkillRecord(existing.id, {
|
|
4393
4505
|
...args.status !== void 0 ? { status: args.status } : {},
|
|
4394
4506
|
...args.generation !== void 0 ? { generation: args.generation } : {},
|
|
4395
4507
|
...args.source_ids !== void 0 ? { source_ids: args.source_ids } : {},
|
|
4396
4508
|
...args.description !== void 0 ? { description: args.description } : {},
|
|
4509
|
+
...mergedProperties !== void 0 ? { properties: mergedProperties } : {},
|
|
4397
4510
|
updated_at: now
|
|
4398
4511
|
});
|
|
4399
4512
|
if (!updated) return textResult({ error: `Failed to update skill record: ${existing.id}` });
|
|
@@ -4416,7 +4529,7 @@ function createSkillTools(deps) {
|
|
|
4416
4529
|
console.warn("[vault_skill_records] Failed to remove skill directory:", err instanceof Error ? err.message : err);
|
|
4417
4530
|
}
|
|
4418
4531
|
try {
|
|
4419
|
-
const { syncSkillSymlinks } = await import("./installer-
|
|
4532
|
+
const { syncSkillSymlinks } = await import("./installer-N4UTEACX.js");
|
|
4420
4533
|
syncSkillSymlinks(root, result.name, { remove: true });
|
|
4421
4534
|
} catch (err) {
|
|
4422
4535
|
console.warn("[vault_skill_records] Failed to remove symlinks:", err instanceof Error ? err.message : err);
|
|
@@ -4534,7 +4647,7 @@ function createSkillTools(deps) {
|
|
|
4534
4647
|
return textResult({ error: `Failed to write skill file: ${err instanceof Error ? err.message : String(err)}` });
|
|
4535
4648
|
}
|
|
4536
4649
|
try {
|
|
4537
|
-
const { syncSkillSymlinks } = await import("./installer-
|
|
4650
|
+
const { syncSkillSymlinks } = await import("./installer-N4UTEACX.js");
|
|
4538
4651
|
syncSkillSymlinks(root, args.name);
|
|
4539
4652
|
} catch (err) {
|
|
4540
4653
|
console.warn("[vault_write_skill] syncSkillSymlinks failed:", err instanceof Error ? err.message : err);
|
|
@@ -5116,19 +5229,34 @@ function truncateSummary(text) {
|
|
|
5116
5229
|
if (!text) return null;
|
|
5117
5230
|
return text.length > TOOL_OUTPUT_SUMMARY_LIMIT ? `${text.slice(0, TOOL_OUTPUT_SUMMARY_LIMIT - 1)}\u2026` : text;
|
|
5118
5231
|
}
|
|
5232
|
+
var TOOL_ERROR_PREFIX = "[ERROR] ";
|
|
5233
|
+
function isErrorResult(result) {
|
|
5234
|
+
if (!result || typeof result !== "object") return false;
|
|
5235
|
+
const content = result.content;
|
|
5236
|
+
if (!Array.isArray(content) || content.length === 0) return false;
|
|
5237
|
+
const first = content[0];
|
|
5238
|
+
if (!first || first.type !== "text" || typeof first.text !== "string") return false;
|
|
5239
|
+
const trimmed = first.text.trimStart();
|
|
5240
|
+
if (!trimmed.startsWith("{")) return false;
|
|
5241
|
+
try {
|
|
5242
|
+
const parsed = JSON.parse(trimmed);
|
|
5243
|
+
return !!parsed && typeof parsed === "object" && "error" in parsed && parsed.error !== void 0;
|
|
5244
|
+
} catch {
|
|
5245
|
+
return false;
|
|
5246
|
+
}
|
|
5247
|
+
}
|
|
5119
5248
|
function summarizeToolResult(result) {
|
|
5120
5249
|
if (!result || typeof result !== "object") return null;
|
|
5121
5250
|
const content = result.content;
|
|
5122
5251
|
if (!Array.isArray(content) || content.length === 0) return null;
|
|
5123
5252
|
const first = content[0];
|
|
5124
5253
|
if (!first || first.type !== "text" || typeof first.text !== "string") return null;
|
|
5125
|
-
|
|
5254
|
+
const body = first.text.replace(/\s+/g, " ").trim();
|
|
5255
|
+
const prefix = isErrorResult(result) ? TOOL_ERROR_PREFIX : "";
|
|
5256
|
+
return truncateSummary(prefix + body);
|
|
5126
5257
|
}
|
|
5127
5258
|
function summarizeToolError(error) {
|
|
5128
|
-
|
|
5129
|
-
return truncateSummary(error.message) ?? "Tool failed";
|
|
5130
|
-
}
|
|
5131
|
-
return truncateSummary(String(error)) ?? "Tool failed";
|
|
5259
|
+
return truncateSummary(TOOL_ERROR_PREFIX + errorMessage(error)) ?? TOOL_ERROR_PREFIX + "Tool failed";
|
|
5132
5260
|
}
|
|
5133
5261
|
function buildRepeatedReadSuppressionResult(toolName, repeatedCalls) {
|
|
5134
5262
|
return {
|
|
@@ -5265,6 +5393,7 @@ function createVaultTools(agentId, runId, options) {
|
|
|
5265
5393
|
}
|
|
5266
5394
|
function wrapToolWithAudit(toolDef) {
|
|
5267
5395
|
const originalHandler = toolDef.handler;
|
|
5396
|
+
const declaredKeys = toolDef.inputSchema && typeof toolDef.inputSchema === "object" ? new Set(Object.keys(toolDef.inputSchema)) : /* @__PURE__ */ new Set();
|
|
5268
5397
|
return {
|
|
5269
5398
|
...toolDef,
|
|
5270
5399
|
handler: async (args, extra) => {
|
|
@@ -5272,6 +5401,28 @@ function createVaultTools(agentId, runId, options) {
|
|
|
5272
5401
|
const priorIdenticalCalls = repeatedReadKey ? repeatedReadCounts.get(repeatedReadKey) ?? 0 : 0;
|
|
5273
5402
|
const turnId = recordTurn(toolDef.name, args);
|
|
5274
5403
|
try {
|
|
5404
|
+
if (declaredKeys.size > 0 && args && typeof args === "object") {
|
|
5405
|
+
const unknown = [];
|
|
5406
|
+
for (const key of Object.keys(args)) {
|
|
5407
|
+
if (!declaredKeys.has(key)) unknown.push(key);
|
|
5408
|
+
}
|
|
5409
|
+
if (unknown.length > 0) {
|
|
5410
|
+
const accepted = Array.from(declaredKeys).sort().join(", ");
|
|
5411
|
+
const result2 = textResult({
|
|
5412
|
+
error: `Unknown parameter(s) for ${toolDef.name}: ${unknown.join(", ")}. Accepted parameters: ${accepted}.`
|
|
5413
|
+
});
|
|
5414
|
+
if (turnId !== null) {
|
|
5415
|
+
try {
|
|
5416
|
+
updateTurn(turnId, {
|
|
5417
|
+
tool_output_summary: summarizeToolResult(result2),
|
|
5418
|
+
completed_at: epochSeconds()
|
|
5419
|
+
});
|
|
5420
|
+
} catch {
|
|
5421
|
+
}
|
|
5422
|
+
}
|
|
5423
|
+
return result2;
|
|
5424
|
+
}
|
|
5425
|
+
}
|
|
5275
5426
|
if (priorIdenticalCalls >= REPEATED_READ_FAILURE_THRESHOLD) {
|
|
5276
5427
|
throw new Error(
|
|
5277
5428
|
`Repeated identical ${toolDef.name} reads detected (${priorIdenticalCalls + 1} calls). Reuse the prior result already in context and proceed to a write, report, or different query.`
|
|
@@ -5405,6 +5556,13 @@ function getIsolatedPluginCacheDir() {
|
|
|
5405
5556
|
if (isolatedPluginCacheDir) return isolatedPluginCacheDir;
|
|
5406
5557
|
const dir = path3.join(os.tmpdir(), `myco-agent-plugin-cache-${process.pid}`);
|
|
5407
5558
|
fs3.mkdirSync(dir, { recursive: true });
|
|
5559
|
+
const manifestPath = path3.join(dir, "installed_plugins.json");
|
|
5560
|
+
if (!fs3.existsSync(manifestPath)) {
|
|
5561
|
+
fs3.writeFileSync(
|
|
5562
|
+
manifestPath,
|
|
5563
|
+
JSON.stringify({ version: 2, plugins: {} })
|
|
5564
|
+
);
|
|
5565
|
+
}
|
|
5408
5566
|
isolatedPluginCacheDir = dir;
|
|
5409
5567
|
return dir;
|
|
5410
5568
|
}
|
|
@@ -5450,6 +5608,18 @@ var ClaudeSdkRuntime = class {
|
|
|
5450
5608
|
// user hasn't explicitly overridden the cache dir themselves.
|
|
5451
5609
|
CLAUDE_CODE_PLUGIN_CACHE_DIR: process.env.CLAUDE_CODE_PLUGIN_CACHE_DIR ?? getIsolatedPluginCacheDir()
|
|
5452
5610
|
};
|
|
5611
|
+
if (input.logger) {
|
|
5612
|
+
const mcpToolNames = input.toolSurface.toolNames ?? (toolServer ? ["<full-vault-surface>"] : []);
|
|
5613
|
+
input.logger.debug("agent.runtime.request", "Agent runtime request", {
|
|
5614
|
+
runId: input.toolSurface.runId,
|
|
5615
|
+
agentId: input.toolSurface.agentId,
|
|
5616
|
+
model: input.model,
|
|
5617
|
+
mcpToolCount: mcpToolNames.length,
|
|
5618
|
+
mcpTools: mcpToolNames,
|
|
5619
|
+
pluginCacheDir: env.CLAUDE_CODE_PLUGIN_CACHE_DIR,
|
|
5620
|
+
sessionRef: input.sessionRef ?? null
|
|
5621
|
+
});
|
|
5622
|
+
}
|
|
5453
5623
|
let finalText = "";
|
|
5454
5624
|
let turnsUsed = 0;
|
|
5455
5625
|
let inputTokens = 0;
|
|
@@ -5464,6 +5634,7 @@ var ClaudeSdkRuntime = class {
|
|
|
5464
5634
|
tools: [],
|
|
5465
5635
|
mcpServers: toolServer ? { [MCP_SERVER_NAME]: toolServer } : {},
|
|
5466
5636
|
strictMcpConfig: true,
|
|
5637
|
+
settingSources: [],
|
|
5467
5638
|
maxTurns: input.maxTurns,
|
|
5468
5639
|
permissionMode: "bypassPermissions",
|
|
5469
5640
|
allowDangerouslySkipPermissions: true,
|
|
@@ -5504,7 +5675,7 @@ var ClaudeSdkRuntime = class {
|
|
|
5504
5675
|
} catch (err) {
|
|
5505
5676
|
if (turnsUsed > 0 || inputTokens > 0 || outputTokens > 0) {
|
|
5506
5677
|
throw new RuntimeExecutionError(
|
|
5507
|
-
|
|
5678
|
+
errorMessage(err),
|
|
5508
5679
|
{ usage: buildUsage(), sessionRef: input.sessionRef },
|
|
5509
5680
|
{ cause: err }
|
|
5510
5681
|
);
|
|
@@ -13069,7 +13240,17 @@ function getAgentRuntime(runtimeId) {
|
|
|
13069
13240
|
// src/agent/phase-loop.ts
|
|
13070
13241
|
async function executePhase(input) {
|
|
13071
13242
|
const { ctx, phasePrompt, phaseModel, phase, toolSurface, provider, sessionId, sessionData } = input;
|
|
13243
|
+
const logger = ctx.options?.logger;
|
|
13072
13244
|
const runtime = getAgentRuntime(ctx.config.runtime);
|
|
13245
|
+
logger?.debug("agent.phase.start", `Phase ${phase.name} starting`, {
|
|
13246
|
+
runId: ctx.runId,
|
|
13247
|
+
phase: phase.name,
|
|
13248
|
+
model: phaseModel,
|
|
13249
|
+
maxTurns: phase.maxTurns,
|
|
13250
|
+
required: phase.required ?? false,
|
|
13251
|
+
toolNames: toolSurface.toolNames ?? null,
|
|
13252
|
+
sessionRef: sessionId ?? null
|
|
13253
|
+
});
|
|
13073
13254
|
try {
|
|
13074
13255
|
let result;
|
|
13075
13256
|
try {
|
|
@@ -13082,13 +13263,19 @@ async function executePhase(input) {
|
|
|
13082
13263
|
sessionRef: sessionId,
|
|
13083
13264
|
sessionData,
|
|
13084
13265
|
abortController: ctx.abortController,
|
|
13085
|
-
toolSurface
|
|
13266
|
+
toolSurface,
|
|
13267
|
+
logger
|
|
13086
13268
|
});
|
|
13087
13269
|
} catch (error) {
|
|
13088
|
-
if (!sessionId || !runtime.supports("supportsSessionResume") || !isSessionResumeFailure(error)) {
|
|
13270
|
+
if (!sessionId || !runtime.supports("supportsSessionResume") || !isSessionResumeFailure(error) && !isExpiredSessionError(error)) {
|
|
13089
13271
|
throw error;
|
|
13090
13272
|
}
|
|
13091
|
-
|
|
13273
|
+
logger?.info("agent.phase.session-retry", `Phase ${phase.name} session failed, retrying without prior session`, {
|
|
13274
|
+
runId: ctx.runId,
|
|
13275
|
+
phase: phase.name,
|
|
13276
|
+
priorSession: sessionId,
|
|
13277
|
+
error: errorMessage(error)
|
|
13278
|
+
});
|
|
13092
13279
|
result = await runtime.execute({
|
|
13093
13280
|
prompt: phasePrompt,
|
|
13094
13281
|
model: phaseModel,
|
|
@@ -13096,14 +13283,24 @@ async function executePhase(input) {
|
|
|
13096
13283
|
systemPrompt: ctx.systemPrompt,
|
|
13097
13284
|
provider,
|
|
13098
13285
|
abortController: ctx.abortController,
|
|
13099
|
-
toolSurface
|
|
13286
|
+
toolSurface,
|
|
13287
|
+
logger
|
|
13100
13288
|
});
|
|
13101
13289
|
}
|
|
13102
|
-
|
|
13103
|
-
|
|
13104
|
-
|
|
13290
|
+
logger?.debug("agent.phase.end", `Phase ${phase.name} finished`, {
|
|
13291
|
+
runId: ctx.runId,
|
|
13292
|
+
phase: phase.name,
|
|
13293
|
+
status: "completed",
|
|
13294
|
+
turnsUsed: result.turnsUsed,
|
|
13295
|
+
maxTurns: phase.maxTurns ?? null,
|
|
13296
|
+
tokensUsed: result.usage.totalTokens ?? 0,
|
|
13297
|
+
costUsd: result.usage.costUsd ?? null
|
|
13298
|
+
});
|
|
13105
13299
|
if (phase.required && result.turnsUsed === 0) {
|
|
13106
|
-
|
|
13300
|
+
logger?.warn("agent.phase.zero-turns", `Required phase ${phase.name} produced 0 turns`, {
|
|
13301
|
+
runId: ctx.runId,
|
|
13302
|
+
phase: phase.name
|
|
13303
|
+
});
|
|
13107
13304
|
}
|
|
13108
13305
|
const costData = await resolveCost({
|
|
13109
13306
|
runtime: ctx.config.runtime,
|
|
@@ -13129,6 +13326,15 @@ async function executePhase(input) {
|
|
|
13129
13326
|
model: phaseModel,
|
|
13130
13327
|
usage: telemetry.usage
|
|
13131
13328
|
}) : void 0;
|
|
13329
|
+
logger?.debug("agent.phase.end", `Phase ${phase.name} failed`, {
|
|
13330
|
+
runId: ctx.runId,
|
|
13331
|
+
phase: phase.name,
|
|
13332
|
+
status: "failed",
|
|
13333
|
+
turnsUsed: telemetry?.usage.requests ?? 0,
|
|
13334
|
+
tokensUsed: telemetry?.usage.totalTokens ?? 0,
|
|
13335
|
+
costUsd: telemetry?.usage.costUsd ?? null,
|
|
13336
|
+
error: abortReason ?? errorMessage(err)
|
|
13337
|
+
});
|
|
13132
13338
|
return buildPhaseResult({
|
|
13133
13339
|
name: phase.name,
|
|
13134
13340
|
status: "failed",
|
|
@@ -13146,23 +13352,41 @@ async function executeSingleQuery(ctx, taskPrompt, provider, sessionRef, session
|
|
|
13146
13352
|
provider,
|
|
13147
13353
|
ctx.config.model
|
|
13148
13354
|
);
|
|
13149
|
-
const
|
|
13355
|
+
const toolSurface = {
|
|
13356
|
+
agentId: ctx.agentId,
|
|
13357
|
+
runId: ctx.runId,
|
|
13358
|
+
vaultDir: ctx.vaultDir,
|
|
13359
|
+
embeddingManager: ctx.embeddingManager,
|
|
13360
|
+
dryRun: ctx.config.dryRun ?? false
|
|
13361
|
+
};
|
|
13362
|
+
const baseInput = {
|
|
13150
13363
|
prompt: taskPrompt,
|
|
13151
13364
|
model: effectiveModel,
|
|
13152
13365
|
maxTurns: ctx.config.maxTurns,
|
|
13153
13366
|
systemPrompt: ctx.systemPrompt,
|
|
13154
13367
|
provider,
|
|
13155
13368
|
abortController: ctx.abortController,
|
|
13156
|
-
|
|
13157
|
-
|
|
13158
|
-
|
|
13159
|
-
|
|
13160
|
-
|
|
13161
|
-
|
|
13162
|
-
|
|
13163
|
-
|
|
13369
|
+
toolSurface,
|
|
13370
|
+
logger: ctx.options?.logger
|
|
13371
|
+
};
|
|
13372
|
+
let result;
|
|
13373
|
+
try {
|
|
13374
|
+
result = await runtime.execute({ ...baseInput, sessionRef, sessionData });
|
|
13375
|
+
} catch (err) {
|
|
13376
|
+
if (!sessionRef || !runtime.supports("supportsSessionResume") || !isSessionResumeFailure(err) && !isExpiredSessionError(err)) {
|
|
13377
|
+
throw err;
|
|
13164
13378
|
}
|
|
13165
|
-
|
|
13379
|
+
ctx.options?.logger?.info(
|
|
13380
|
+
"agent.single-query.session-retry",
|
|
13381
|
+
"Single-query session failed, retrying without prior session",
|
|
13382
|
+
{
|
|
13383
|
+
runId: ctx.runId,
|
|
13384
|
+
priorSession: sessionRef,
|
|
13385
|
+
error: errorMessage(err)
|
|
13386
|
+
}
|
|
13387
|
+
);
|
|
13388
|
+
result = await runtime.execute(baseInput);
|
|
13389
|
+
}
|
|
13166
13390
|
const costData = await resolveCost({
|
|
13167
13391
|
runtime: ctx.config.runtime,
|
|
13168
13392
|
provider,
|
|
@@ -13210,10 +13434,17 @@ async function executePhasedQuery(ctx) {
|
|
|
13210
13434
|
vaultDir: ctx.vaultDir,
|
|
13211
13435
|
dryRun: config.dryRun ?? false
|
|
13212
13436
|
},
|
|
13213
|
-
abortController: ctx.abortController
|
|
13437
|
+
abortController: ctx.abortController,
|
|
13438
|
+
logger: ctx.options?.logger
|
|
13214
13439
|
});
|
|
13215
|
-
const plan = parseOrchestratorPlan(planResponse.finalText, phases);
|
|
13440
|
+
const plan = parseOrchestratorPlan(planResponse.finalText, phases, ctx.options?.logger);
|
|
13216
13441
|
effectivePhases = applyDirectives(phases, plan.phases);
|
|
13442
|
+
ctx.options?.logger?.debug("agent.orchestrator.plan", "Orchestrator plan applied", {
|
|
13443
|
+
runId,
|
|
13444
|
+
reasoning: plan.reasoning,
|
|
13445
|
+
effectivePhases: effectivePhases.map((p) => p.name),
|
|
13446
|
+
skippedPhases: plan.phases.filter((d) => d.skip).map((d) => d.name)
|
|
13447
|
+
});
|
|
13217
13448
|
}
|
|
13218
13449
|
const declarationOrder = new Map(phases.map((p, i) => [p.name, i]));
|
|
13219
13450
|
const waves = computeWaves(effectivePhases);
|
|
@@ -13373,12 +13604,16 @@ var SKIP_REASON_ALREADY_RUNNING = "already_running";
|
|
|
13373
13604
|
var CORTEX_INSTRUCTIONS_REPORT_ACTION = "cortex_instructions";
|
|
13374
13605
|
var CORTEX_INSTRUCTIONS_CONTENT_KEY = "content";
|
|
13375
13606
|
var TOKEN_BUDGET_PRESSURE_STATUSES = /* @__PURE__ */ new Set(["warning", "post_run_pressure"]);
|
|
13376
|
-
function logTokenBudgetPressure(taskName, usage, provider) {
|
|
13607
|
+
function logTokenBudgetPressure(taskName, usage, provider, logger) {
|
|
13377
13608
|
const budget = analyzeRuntimeTokenBudget(usage, provider);
|
|
13378
13609
|
if (!TOKEN_BUDGET_PRESSURE_STATUSES.has(budget.status)) return;
|
|
13379
|
-
|
|
13380
|
-
|
|
13381
|
-
|
|
13610
|
+
logger?.warn("agent.token-budget-pressure", `${taskName} token budget ${budget.status}`, {
|
|
13611
|
+
task: taskName,
|
|
13612
|
+
status: budget.status,
|
|
13613
|
+
utilizationPercent: budget.utilizationPercent,
|
|
13614
|
+
contextWindowTokens: budget.contextWindowTokens,
|
|
13615
|
+
peakRequestTotalTokens: budget.peakRequestTotalTokens
|
|
13616
|
+
});
|
|
13382
13617
|
}
|
|
13383
13618
|
async function runAgent(vaultDir, options) {
|
|
13384
13619
|
const db = initDatabase(vaultDbPath(vaultDir));
|
|
@@ -13523,15 +13758,25 @@ async function runAgent(vaultDir, options) {
|
|
|
13523
13758
|
taskProviderOverride = resolved.taskProvider;
|
|
13524
13759
|
phaseProviderOverrides = resolved.phaseOverrides;
|
|
13525
13760
|
for (const conflict of resolved.conflicts) {
|
|
13526
|
-
|
|
13527
|
-
|
|
13761
|
+
options?.logger?.warn(
|
|
13762
|
+
"agent.ollama.context-variant-conflict",
|
|
13763
|
+
`Ollama model "${conflict.model}" referenced with conflicting context_length values \u2014 reconciled to ${conflict.resolved}`,
|
|
13764
|
+
{
|
|
13765
|
+
model: conflict.model,
|
|
13766
|
+
values: conflict.values,
|
|
13767
|
+
resolved: conflict.resolved
|
|
13768
|
+
}
|
|
13528
13769
|
);
|
|
13529
13770
|
}
|
|
13530
13771
|
}
|
|
13531
13772
|
const taskAbortController = new AbortController();
|
|
13532
13773
|
const timeoutMs = config.timeoutSeconds * MS_PER_SECOND;
|
|
13533
13774
|
const timeoutId = setTimeout(() => {
|
|
13534
|
-
|
|
13775
|
+
options?.logger?.warn("agent.run.timeout", `Run ${runId} exceeded timeout, aborting`, {
|
|
13776
|
+
runId,
|
|
13777
|
+
taskName: config.taskName,
|
|
13778
|
+
timeoutSeconds: config.timeoutSeconds
|
|
13779
|
+
});
|
|
13535
13780
|
taskAbortController.abort(new Error(`Agent run timed out after ${config.timeoutSeconds} seconds`));
|
|
13536
13781
|
}, timeoutMs);
|
|
13537
13782
|
timeoutId.unref?.();
|
|
@@ -13623,7 +13868,7 @@ async function runAgent(vaultDir, options) {
|
|
|
13623
13868
|
}
|
|
13624
13869
|
}
|
|
13625
13870
|
clearTimeout(timeoutId);
|
|
13626
|
-
logTokenBudgetPressure(config.taskName, usage, effectiveProvider);
|
|
13871
|
+
logTokenBudgetPressure(config.taskName, usage, effectiveProvider, options?.logger);
|
|
13627
13872
|
await finalizeOnTaskSuccess({
|
|
13628
13873
|
taskName: config.taskName,
|
|
13629
13874
|
agentId,
|
|
@@ -13677,34 +13922,48 @@ ${err.stack.split("\n").slice(0, 3).join("\n")}`;
|
|
|
13677
13922
|
}
|
|
13678
13923
|
}
|
|
13679
13924
|
const failedAt = epochSeconds();
|
|
13680
|
-
|
|
13925
|
+
options?.logger?.error("agent.run.failed", `Run ${runId} failed`, {
|
|
13926
|
+
runId,
|
|
13927
|
+
taskName: config.taskName,
|
|
13928
|
+
error: errorMessage2
|
|
13929
|
+
});
|
|
13681
13930
|
try {
|
|
13682
13931
|
const usage = aggregateUsage(phaseResults?.map((phase) => phase.usage) ?? []);
|
|
13683
|
-
logTokenBudgetPressure(config.taskName, usage, effectiveProvider);
|
|
13932
|
+
logTokenBudgetPressure(config.taskName, usage, effectiveProvider, options?.logger);
|
|
13684
13933
|
const costData = phaseResults ? summarizePhaseCosts(phaseResults) : await resolveCost({
|
|
13685
13934
|
runtime: runtimeId,
|
|
13686
13935
|
provider: effectiveProvider,
|
|
13687
13936
|
model: effectiveModel,
|
|
13688
13937
|
usage
|
|
13689
13938
|
});
|
|
13939
|
+
const hadPriorSession = Boolean(checkpointState.sessionRef) || Object.values(checkpointState.phases).some((phase) => Boolean(phase.sessionRef));
|
|
13940
|
+
const recordedAnyTurns = (usage.requests ?? 0) > 0 || (phaseResults?.some((phase) => phase.turnsUsed > 0) ?? false);
|
|
13941
|
+
const sessionExpired = Boolean(options?.resumeRunId) && hadPriorSession && !recordedAnyTurns && isExpiredSessionError(err);
|
|
13942
|
+
const accountingUpdate = buildRunAccountingUpdate({
|
|
13943
|
+
runtime: runtimeId,
|
|
13944
|
+
provider: effectiveProvider,
|
|
13945
|
+
model: effectiveModel,
|
|
13946
|
+
checkpointState,
|
|
13947
|
+
usage,
|
|
13948
|
+
costData,
|
|
13949
|
+
phaseResults
|
|
13950
|
+
});
|
|
13951
|
+
if (sessionExpired) {
|
|
13952
|
+
accountingUpdate.checkpoints = null;
|
|
13953
|
+
}
|
|
13690
13954
|
updateRunStatus(runId, STATUS_FAILED, {
|
|
13691
|
-
resumable: 1,
|
|
13692
|
-
resume_status: RESUME_STATUS_READY,
|
|
13955
|
+
resumable: sessionExpired ? 0 : 1,
|
|
13956
|
+
resume_status: sessionExpired ? RESUME_STATUS_SESSION_EXPIRED : RESUME_STATUS_READY,
|
|
13693
13957
|
completed_at: failedAt,
|
|
13694
13958
|
tokens_used: usage.totalTokens ?? phaseResults?.reduce((sum, phase) => sum + phase.tokensUsed, 0) ?? void 0,
|
|
13695
13959
|
error: errorMessage2,
|
|
13696
|
-
...
|
|
13697
|
-
runtime: runtimeId,
|
|
13698
|
-
provider: effectiveProvider,
|
|
13699
|
-
model: effectiveModel,
|
|
13700
|
-
checkpointState,
|
|
13701
|
-
usage,
|
|
13702
|
-
costData,
|
|
13703
|
-
phaseResults
|
|
13704
|
-
})
|
|
13960
|
+
...accountingUpdate
|
|
13705
13961
|
});
|
|
13706
13962
|
} catch (dbErr) {
|
|
13707
|
-
|
|
13963
|
+
options?.logger?.error("agent.run.db-save-failed", `Failed to save error to DB for run ${runId}`, {
|
|
13964
|
+
runId,
|
|
13965
|
+
error: errorMessage(dbErr)
|
|
13966
|
+
});
|
|
13708
13967
|
}
|
|
13709
13968
|
await cleanupOnTaskFailure({
|
|
13710
13969
|
taskName: config.taskName,
|
|
@@ -13841,4 +14100,4 @@ export {
|
|
|
13841
14100
|
cleanupOnTaskFailure,
|
|
13842
14101
|
finalizeOnTaskSuccess
|
|
13843
14102
|
};
|
|
13844
|
-
//# sourceMappingURL=chunk-
|
|
14103
|
+
//# sourceMappingURL=chunk-X2IRGXGF.js.map
|