mixdog 0.9.1 → 0.9.3
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/package.json +9 -1
- package/scripts/_bench-cwc.json +20 -0
- package/scripts/agent-loop-policy-test.mjs +37 -0
- package/scripts/agent-parallel-smoke.mjs +54 -10
- package/scripts/anthropic-maxtokens-test.mjs +119 -0
- package/scripts/background-task-meta-smoke.mjs +1 -1
- package/scripts/bench-run.mjs +262 -0
- package/scripts/build-tui.mjs +13 -1
- package/scripts/compact-smoke.mjs +12 -0
- package/scripts/compact-trigger-migration-smoke.mjs +67 -1
- package/scripts/explore-bench.mjs +124 -0
- package/scripts/hook-bus-test.mjs +191 -0
- package/scripts/ingest-pure-conversation-smoke.mjs +148 -0
- package/scripts/internal-comms-bench.mjs +727 -0
- package/scripts/internal-comms-smoke.mjs +75 -0
- package/scripts/lead-workflow-smoke.mjs +4 -4
- package/scripts/live-worker-smoke.mjs +9 -9
- package/scripts/output-style-bench.mjs +285 -0
- package/scripts/output-style-smoke.mjs +13 -10
- package/scripts/patch-replay.mjs +90 -0
- package/scripts/path-suffix-test.mjs +57 -0
- package/scripts/provider-stream-stall-test.mjs +276 -0
- package/scripts/provider-toolcall-test.mjs +599 -1
- package/scripts/recall-bench.mjs +207 -0
- package/scripts/routing-corpus.mjs +281 -0
- package/scripts/session-bench.mjs +1526 -0
- package/scripts/session-diag.mjs +595 -0
- package/scripts/task-bench.mjs +207 -0
- package/scripts/tool-failures.mjs +6 -6
- package/scripts/tool-smoke.mjs +310 -67
- package/scripts/toolcall-args-test.mjs +81 -0
- package/src/agents/debugger/AGENT.md +4 -4
- package/src/agents/heavy-worker/AGENT.md +20 -9
- package/src/agents/reviewer/AGENT.md +4 -4
- package/src/agents/worker/AGENT.md +17 -9
- package/src/app.mjs +10 -6
- package/src/defaults/{hidden-roles.json → agents.json} +7 -7
- package/src/examples/schedules/SCHEDULE.example.md +32 -0
- package/src/examples/webhooks/WEBHOOK.example.md +40 -0
- package/src/headless-role.mjs +14 -14
- package/src/help.mjs +1 -0
- package/src/lib/rules-builder.cjs +32 -54
- package/src/mixdog-session-runtime.mjs +1040 -2036
- package/src/output-styles/default.md +12 -7
- package/src/output-styles/minimal.md +25 -0
- package/src/output-styles/oneline.md +21 -0
- package/src/output-styles/simple.md +10 -9
- package/src/repl.mjs +17 -7
- package/src/rules/agent/00-common.md +7 -5
- package/src/rules/agent/30-explorer.md +8 -12
- package/src/rules/lead/01-general.md +3 -1
- package/src/rules/lead/lead-tool.md +13 -2
- package/src/rules/shared/01-tool.md +23 -12
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +90 -32
- package/src/runtime/agent/orchestrator/agent-runtime/agent-loop-policy.mjs +32 -0
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +18 -6
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +23 -20
- package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +48 -14
- package/src/runtime/agent/orchestrator/agent-trace.mjs +87 -12
- package/src/runtime/agent/orchestrator/config.mjs +3 -0
- package/src/runtime/agent/orchestrator/context/collect.mjs +182 -67
- package/src/runtime/agent/orchestrator/{internal-roles.mjs → internal-agents.mjs} +72 -72
- package/src/runtime/agent/orchestrator/internal-tools.mjs +13 -26
- package/src/runtime/agent/orchestrator/mcp/client.mjs +100 -18
- package/src/runtime/agent/orchestrator/providers/anthropic-betas.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-effort.mjs +188 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-leaked-toolcall.mjs +444 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +93 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +313 -84
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +104 -38
- package/src/runtime/agent/orchestrator/providers/api-usage.mjs +28 -33
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +184 -17
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +8 -1
- package/src/runtime/agent/orchestrator/providers/lib/usage-primitives.mjs +32 -0
- package/src/runtime/agent/orchestrator/providers/model-catalog.mjs +18 -8
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +54 -20
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +227 -31
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +83 -6
- package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +229 -115
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +213 -33
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +18 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-usage.mjs +49 -17
- package/src/runtime/agent/orchestrator/providers/registry.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +22 -17
- package/src/runtime/agent/orchestrator/session/compact.mjs +560 -51
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +250 -3
- package/src/runtime/agent/orchestrator/session/loop/compact-debug.mjs +28 -0
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +262 -0
- package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +38 -0
- package/src/runtime/agent/orchestrator/session/loop/env.mjs +14 -0
- package/src/runtime/agent/orchestrator/session/loop/hidden-agents.mjs +21 -0
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +49 -0
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +63 -0
- package/src/runtime/agent/orchestrator/session/loop/stored-tool-args.mjs +100 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-classify.mjs +52 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +218 -0
- package/src/runtime/agent/orchestrator/session/loop/transcript-repair.mjs +101 -0
- package/src/runtime/agent/orchestrator/session/loop/usage.mjs +35 -0
- package/src/runtime/agent/orchestrator/session/loop.mjs +513 -1000
- package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +227 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +235 -0
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +137 -0
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +155 -0
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +303 -0
- package/src/runtime/agent/orchestrator/session/manager.mjs +232 -1152
- package/src/runtime/agent/orchestrator/session/store.mjs +4 -4
- package/src/runtime/agent/orchestrator/session/tool-envelope.mjs +61 -0
- package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +5 -0
- package/src/runtime/agent/orchestrator/stall-policy.mjs +63 -15
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +194 -24
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.test.mjs +143 -0
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +34 -18
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +241 -0
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.test.mjs +162 -0
- package/src/runtime/agent/orchestrator/tools/builtin/fuzzy-match.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/list-formatting.mjs +10 -0
- package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +5 -4
- package/src/runtime/agent/orchestrator/tools/builtin/path-diagnostics.mjs +42 -2
- package/src/runtime/agent/orchestrator/tools/builtin/path-utils.mjs +15 -0
- package/src/runtime/agent/orchestrator/tools/builtin/read-args.mjs +9 -44
- package/src/runtime/agent/orchestrator/tools/builtin/read-constants.mjs +2 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +14 -5
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +11 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +10 -17
- package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +23 -2
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +50 -39
- package/src/runtime/agent/orchestrator/tools/builtin/shell-output.mjs +3 -2
- package/src/runtime/agent/orchestrator/tools/builtin/tool-output-limit.mjs +10 -0
- package/src/runtime/agent/orchestrator/tools/builtin.mjs +70 -1
- package/src/runtime/agent/orchestrator/tools/code-graph/build.mjs +303 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/constants.mjs +43 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/disk-cache.mjs +382 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +497 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary.mjs +295 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/graph-model.mjs +158 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/lang-predicates.mjs +128 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/memory-cache.mjs +66 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/project-root.mjs +44 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +1192 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/source-access.mjs +81 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/span.mjs +19 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/symbol-index.mjs +280 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/text-mask.mjs +347 -0
- package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +5 -5
- package/src/runtime/agent/orchestrator/tools/code-graph.mjs +39 -4189
- package/src/runtime/agent/orchestrator/tools/patch.mjs +119 -5
- package/src/runtime/agent/orchestrator/tools/progress-message.mjs +1 -2
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +1 -2
- package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +2 -4
- package/src/runtime/channels/backends/discord.mjs +99 -9
- package/src/runtime/channels/backends/telegram.mjs +501 -0
- package/src/runtime/channels/index.mjs +437 -1439
- package/src/runtime/channels/lib/boot-profile.mjs +23 -0
- package/src/runtime/channels/lib/config.mjs +54 -2
- package/src/runtime/channels/lib/crash-log.mjs +106 -0
- package/src/runtime/channels/lib/format.mjs +4 -2
- package/src/runtime/channels/lib/index-drop-trace.mjs +72 -0
- package/src/runtime/channels/lib/output-forwarder.mjs +88 -67
- package/src/runtime/channels/lib/runtime-paths.mjs +29 -0
- package/src/runtime/channels/lib/scheduler.mjs +1 -1
- package/src/runtime/channels/lib/telegram-format.mjs +280 -0
- package/src/runtime/channels/lib/tool-format.mjs +1 -1
- package/src/runtime/channels/lib/transcript-discovery.mjs +19 -1
- package/src/runtime/channels/lib/webhook.mjs +59 -31
- package/src/runtime/channels/lib/whisper-language.mjs +42 -0
- package/src/runtime/channels/tool-defs.mjs +1 -1
- package/src/runtime/memory/index.mjs +465 -345
- package/src/runtime/memory/lib/agent-ipc.mjs +2 -2
- package/src/runtime/memory/lib/core-memory-store.mjs +352 -2
- package/src/runtime/memory/lib/cycle-signatures.mjs +34 -0
- package/src/runtime/memory/lib/http-wire.mjs +57 -0
- package/src/runtime/memory/lib/memory-cycle1.mjs +1 -1
- package/src/runtime/memory/lib/memory-cycle2.mjs +65 -9
- package/src/runtime/memory/lib/memory-cycle3.mjs +1 -1
- package/src/runtime/memory/lib/memory-recall-scope-filter.mjs +24 -0
- package/src/runtime/memory/lib/memory-retrievers.mjs +8 -0
- package/src/runtime/memory/lib/memory.mjs +121 -4
- package/src/runtime/memory/lib/pg/adapter.mjs +139 -15
- package/src/runtime/memory/lib/promotion-fingerprint.mjs +50 -0
- package/src/runtime/memory/lib/recall-format.mjs +183 -0
- package/src/runtime/memory/lib/session-ingest.mjs +107 -0
- package/src/runtime/memory/lib/trace-store.mjs +69 -22
- package/src/runtime/memory/tool-defs.mjs +10 -7
- package/src/runtime/shared/abort-controller.mjs +1 -1
- package/src/runtime/shared/background-tasks.mjs +2 -3
- package/src/runtime/shared/buffered-appender.mjs +149 -0
- package/src/runtime/shared/channel-notification-routing.mjs +12 -0
- package/src/runtime/shared/channel-notification-routing.test.mjs +45 -0
- package/src/runtime/shared/config.mjs +9 -0
- package/src/runtime/shared/llm/http-agent.mjs +12 -5
- package/src/runtime/shared/schedules-store.mjs +21 -19
- package/src/runtime/shared/task-notification-envelope.mjs +98 -0
- package/src/runtime/shared/task-notification-envelope.test.mjs +107 -0
- package/src/runtime/shared/tool-execution-contract.mjs +2 -2
- package/src/runtime/shared/tool-surface.mjs +98 -13
- package/src/runtime/shared/transcript-writer.mjs +156 -0
- package/src/runtime/shared/update-checker.mjs +214 -0
- package/src/session-runtime/config-helpers.mjs +209 -0
- package/src/session-runtime/effort.mjs +128 -0
- package/src/session-runtime/fs-utils.mjs +10 -0
- package/src/session-runtime/model-capabilities.mjs +130 -0
- package/src/session-runtime/output-styles.mjs +124 -0
- package/src/session-runtime/plugin-mcp.mjs +114 -0
- package/src/session-runtime/session-text.mjs +100 -0
- package/src/session-runtime/statusline-route.mjs +35 -0
- package/src/session-runtime/tool-catalog.mjs +720 -0
- package/src/session-runtime/workflow.mjs +358 -0
- package/src/standalone/agent-tool.mjs +302 -117
- package/src/standalone/channel-admin.mjs +133 -40
- package/src/standalone/channel-worker.mjs +10 -292
- package/src/standalone/explore-tool.mjs +12 -5
- package/src/standalone/hook-bus.mjs +165 -8
- package/src/standalone/memory-runtime-proxy.mjs +3 -1
- package/src/standalone/opencode-go-login.mjs +121 -0
- package/src/standalone/provider-admin.mjs +25 -3
- package/src/standalone/usage-dashboard.mjs +1 -1
- package/src/tui/App.jsx +2883 -778
- package/src/tui/components/ConfirmBar.jsx +47 -0
- package/src/tui/components/ContextPanel.jsx +5 -3
- package/src/tui/components/ItemRightHintOverprint.jsx +54 -0
- package/src/tui/components/Markdown.jsx +22 -98
- package/src/tui/components/Message.jsx +14 -35
- package/src/tui/components/Picker.jsx +87 -12
- package/src/tui/components/PromptInput.jsx +355 -22
- package/src/tui/components/QueuedCommands.jsx +1 -1
- package/src/tui/components/SlashCommandPalette.jsx +8 -5
- package/src/tui/components/Spinner.jsx +7 -7
- package/src/tui/components/StatusLine.jsx +40 -21
- package/src/tui/components/TextEntryPanel.jsx +51 -7
- package/src/tui/components/ToolExecution.jsx +183 -101
- package/src/tui/components/TurnDone.jsx +4 -4
- package/src/tui/components/UsagePanel.jsx +1 -1
- package/src/tui/components/tool-output-format.mjs +161 -23
- package/src/tui/components/tool-output-format.test.mjs +87 -0
- package/src/tui/display-width.mjs +69 -0
- package/src/tui/display-width.test.mjs +35 -0
- package/src/tui/dist/index.mjs +6731 -2333
- package/src/tui/engine/agent-envelope.mjs +296 -0
- package/src/tui/engine/boot-profile.mjs +21 -0
- package/src/tui/engine/labels.mjs +67 -0
- package/src/tui/engine/notice-text.mjs +112 -0
- package/src/tui/engine/queue-helpers.mjs +161 -0
- package/src/tui/engine/session-stats.mjs +46 -0
- package/src/tui/engine/tool-call-fields.mjs +23 -0
- package/src/tui/engine/tool-result-text.mjs +126 -0
- package/src/tui/engine.mjs +569 -948
- package/src/tui/index.jsx +117 -7
- package/src/tui/input-editing.mjs +58 -8
- package/src/tui/input-editing.selection.test.mjs +75 -0
- package/src/tui/keyboard-protocol.mjs +42 -0
- package/src/tui/lib/voice-recorder.mjs +469 -0
- package/src/tui/markdown/format-token.mjs +128 -76
- package/src/tui/markdown/format-token.test.mjs +61 -19
- package/src/tui/markdown/measure-rendered-rows.mjs +85 -0
- package/src/tui/markdown/render-ansi.test.mjs +1 -1
- package/src/tui/markdown/streaming-markdown.mjs +167 -0
- package/src/tui/markdown/streaming-markdown.test.mjs +70 -0
- package/src/tui/markdown/table-layout.mjs +9 -9
- package/src/tui/paste-attachments.mjs +36 -9
- package/src/tui/paste-fix.test.mjs +119 -0
- package/src/tui/prompt-history-store.mjs +129 -0
- package/src/tui/prompt-history-store.test.mjs +52 -0
- package/src/tui/statusline-ansi-bridge.test.mjs +3 -3
- package/src/tui/theme.mjs +41 -657
- package/src/tui/themes/base.mjs +86 -0
- package/src/tui/themes/basic.mjs +85 -0
- package/src/tui/themes/catppuccin.mjs +72 -0
- package/src/tui/themes/dracula.mjs +70 -0
- package/src/tui/themes/everforest.mjs +71 -0
- package/src/tui/themes/gruvbox.mjs +71 -0
- package/src/tui/themes/index.mjs +71 -0
- package/src/tui/themes/indigo.mjs +78 -0
- package/src/tui/themes/kanagawa.mjs +80 -0
- package/src/tui/themes/light.mjs +81 -0
- package/src/tui/themes/nord.mjs +72 -0
- package/src/tui/themes/onedark.mjs +16 -0
- package/src/tui/themes/rosepine.mjs +70 -0
- package/src/tui/themes/teal.mjs +80 -0
- package/src/tui/themes/tokyonight.mjs +79 -0
- package/src/tui/themes/utils.mjs +106 -0
- package/src/tui/themes/warm.mjs +79 -0
- package/src/tui/transcript-tool-failures.mjs +13 -2
- package/src/ui/markdown.mjs +1 -1
- package/src/ui/model-display.mjs +2 -2
- package/src/ui/statusline.mjs +75 -27
- package/src/vendor/statusline/bin/statusline-route.mjs +5 -12
- package/src/vendor/statusline/src/gateway/claude-current.mjs +3 -3
- package/src/vendor/statusline/src/gateway/route-meta.mjs +30 -16
- package/src/workflows/default/WORKFLOW.md +46 -12
- package/src/workflows/sequential/WORKFLOW.md +51 -0
- package/src/workflows/solo/WORKFLOW.md +12 -1
- package/vendor/ink/build/display-width.js +62 -0
- package/vendor/ink/build/ink.js +100 -12
- package/vendor/ink/build/measure-text.js +4 -1
- package/vendor/ink/build/output.js +115 -9
- package/vendor/ink/build/render-node-to-output.js +4 -1
- package/vendor/ink/build/render.js +4 -0
- package/src/output-styles/extreme-simple.md +0 -20
- package/src/rules/lead/04-workflow.md +0 -51
- package/src/workflows/default/workflow.json +0 -13
- package/src/workflows/solo/workflow.json +0 -7
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readFileSync, existsSync, readdirSync } from 'fs';
|
|
2
2
|
import { homedir } from 'os';
|
|
3
|
-
import { join } from 'path';
|
|
3
|
+
import { dirname, join } from 'path';
|
|
4
4
|
import { maxMtimeRecursive } from '../cache-mtime.mjs';
|
|
5
5
|
import { resolvePluginData, mixdogRoot } from '../../../shared/plugin-paths.mjs';
|
|
6
6
|
import {
|
|
@@ -33,6 +33,47 @@ function mixdogAssetDirs(projectDir, kind) {
|
|
|
33
33
|
dirs.push(mixdogGlobalDir(kind));
|
|
34
34
|
return dirs;
|
|
35
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Absolute path to the plugin registry file, or null when the data dir is
|
|
38
|
+
* unresolvable. Included in the skills mtime gate so plugin add/remove
|
|
39
|
+
* (which rewrites registry.json) invalidates the cached skill list even
|
|
40
|
+
* when no surviving skills dir got a newer mtime.
|
|
41
|
+
*/
|
|
42
|
+
function pluginRegistryPath() {
|
|
43
|
+
try {
|
|
44
|
+
return join(resolvePluginData(), 'plugins', 'registry.json');
|
|
45
|
+
} catch {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Read `<resolvePluginData()>/plugins/registry.json` (safe JSON parse, ignore
|
|
51
|
+
* errors) and yield `<root>/skills` for each registered plugin whose `root`
|
|
52
|
+
* exists on disk and has a `skills` subdirectory.
|
|
53
|
+
*/
|
|
54
|
+
function pluginSkillDirs() {
|
|
55
|
+
const registryPath = pluginRegistryPath();
|
|
56
|
+
if (!registryPath)
|
|
57
|
+
return [];
|
|
58
|
+
let registry;
|
|
59
|
+
try {
|
|
60
|
+
registry = JSON.parse(readFileSync(registryPath, 'utf-8'));
|
|
61
|
+
} catch {
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
64
|
+
if (!registry || !Array.isArray(registry.plugins))
|
|
65
|
+
return [];
|
|
66
|
+
const dirs = [];
|
|
67
|
+
for (const entry of registry.plugins) {
|
|
68
|
+
const root = entry && typeof entry.root === 'string' ? entry.root : null;
|
|
69
|
+
if (!root || !existsSync(root))
|
|
70
|
+
continue;
|
|
71
|
+
const skillsDir = join(root, 'skills');
|
|
72
|
+
if (existsSync(skillsDir))
|
|
73
|
+
dirs.push(skillsDir);
|
|
74
|
+
}
|
|
75
|
+
return dirs;
|
|
76
|
+
}
|
|
36
77
|
/**
|
|
37
78
|
* Collect available skills (frontmatter only — token efficient).
|
|
38
79
|
* Full content loaded on demand via loadSkillContent().
|
|
@@ -49,6 +90,9 @@ export function collectSkills(cwd) {
|
|
|
49
90
|
// first, then user-global. When cwd is missing, only the global dir is
|
|
50
91
|
// searched.
|
|
51
92
|
const dirs = mixdogAssetDirs(projectDir, 'skills');
|
|
93
|
+
// Plugin-provided skills load last so project-local and global mixdog
|
|
94
|
+
// skill dirs keep precedence; `seen` below dedupes by frontmatter name.
|
|
95
|
+
dirs.push(...pluginSkillDirs());
|
|
52
96
|
const seen = new Set();
|
|
53
97
|
for (const dir of dirs) {
|
|
54
98
|
if (!existsSync(dir))
|
|
@@ -88,6 +132,13 @@ export function collectSkillsCached(cwd) {
|
|
|
88
132
|
const projectDir = (typeof cwd === 'string' && cwd.length > 0) ? cwd : null;
|
|
89
133
|
// Same mixdog-owned dirs collectSkills() reads, used as the freshness gate.
|
|
90
134
|
const skillsDirs = mixdogAssetDirs(projectDir, 'skills');
|
|
135
|
+
skillsDirs.push(...pluginSkillDirs());
|
|
136
|
+
// registry.json itself gates plugin add/remove: removal deletes the
|
|
137
|
+
// plugin's skills dir (so no dir mtime advances), but saveRegistry()
|
|
138
|
+
// always rewrites this file. maxMtimeRecursive stats plain files directly.
|
|
139
|
+
const registryPath = pluginRegistryPath();
|
|
140
|
+
if (registryPath)
|
|
141
|
+
skillsDirs.push(registryPath);
|
|
91
142
|
let mtime;
|
|
92
143
|
const mtimeCached = _mtimeCache.get(key);
|
|
93
144
|
if (mtimeCached && Date.now() - mtimeCached.checkedAt < _MTIME_TTL_MS) {
|
|
@@ -121,6 +172,70 @@ export function loadSkillContent(name, cwd) {
|
|
|
121
172
|
return readSafe(skill.filePath);
|
|
122
173
|
}
|
|
123
174
|
|
|
175
|
+
/**
|
|
176
|
+
* Load full skill content plus its on-disk directory (for base-dir + ${MIXDOG_SKILL_DIR}).
|
|
177
|
+
*/
|
|
178
|
+
export function loadSkillResource(name, cwd) {
|
|
179
|
+
const skills = collectSkillsCached(cwd);
|
|
180
|
+
const skill = skills.find(s => s.name === name);
|
|
181
|
+
if (!skill)
|
|
182
|
+
return null;
|
|
183
|
+
const content = readSafe(skill.filePath);
|
|
184
|
+
if (content == null)
|
|
185
|
+
return null;
|
|
186
|
+
return { content, dir: dirname(skill.filePath), filePath: skill.filePath };
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function escapeSkillXmlText(value) {
|
|
190
|
+
return String(value || '').replace(/[<>&]/g, (ch) => ({ '<': '<', '>': '>', '&': '&' }[ch]));
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Wrap loaded SKILL.md body for Skill tool results (runtime + loop).
|
|
195
|
+
*/
|
|
196
|
+
export function buildSkillResultEnvelope(name, content, skillDir) {
|
|
197
|
+
const escapedName = escapeSkillXmlText(name);
|
|
198
|
+
let body = String(content == null ? '' : content);
|
|
199
|
+
let dirLine = '';
|
|
200
|
+
if (skillDir) {
|
|
201
|
+
const normDir = String(skillDir).replace(/\\/g, '/');
|
|
202
|
+
body = body.replace(/\$\{MIXDOG_SKILL_DIR\}/g, normDir);
|
|
203
|
+
const escapedDir = escapeSkillXmlText(normDir);
|
|
204
|
+
dirLine = `<base-dir>${escapedDir}</base-dir>\n`;
|
|
205
|
+
}
|
|
206
|
+
return `<skill>\n<name>${escapedName}</name>\n${dirLine}${body}\n</skill>`;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Short, model-visible tool_result stub for a loaded skill. The full SKILL.md
|
|
211
|
+
* body is delivered separately as ONE injected user message (newMessages),
|
|
212
|
+
* never in the tool_result — so the body appears exactly once.
|
|
213
|
+
*/
|
|
214
|
+
export function buildSkillStub(name) {
|
|
215
|
+
return `Loaded skill: ${String(name || '').trim()}`;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Build the Skill tool-result envelope used by BOTH the agent-loop viewSkill
|
|
220
|
+
* path and the runtime skillToolContent path so behavior matches across main
|
|
221
|
+
* + agent sessions:
|
|
222
|
+
* - result = short stub (`Loaded skill: <name>`), no body.
|
|
223
|
+
* - newMessages = exactly ONE role:'user' message carrying the full
|
|
224
|
+
* buildSkillResultEnvelope output (<base-dir> + body).
|
|
225
|
+
* The injected user message is flagged `meta:'skill'` so compaction's
|
|
226
|
+
* "latest human prompt" selection does not mistake the skill body for the
|
|
227
|
+
* human's request.
|
|
228
|
+
*/
|
|
229
|
+
export function buildSkillToolEnvelope(name, content, skillDir) {
|
|
230
|
+
return {
|
|
231
|
+
__toolEnvelope: true,
|
|
232
|
+
result: buildSkillStub(name),
|
|
233
|
+
newMessages: [
|
|
234
|
+
{ role: 'user', content: buildSkillResultEnvelope(name, content, skillDir), meta: 'skill' },
|
|
235
|
+
],
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
|
|
124
239
|
function compactSkillManifestText(value, max = 180) {
|
|
125
240
|
const text = String(value || '').replace(/\s+/g, ' ').trim();
|
|
126
241
|
return text.length > max ? `${text.slice(0, Math.max(1, max - 3))}...` : text;
|
|
@@ -194,34 +309,34 @@ export function buildSkillToolDefs(skills, { ownerIsAgentSession = false } = {})
|
|
|
194
309
|
];
|
|
195
310
|
return _skillToolDefsCache;
|
|
196
311
|
}
|
|
197
|
-
// ---
|
|
198
|
-
// Emits a BP2
|
|
199
|
-
// - Public/custom agents: their own agents/<
|
|
312
|
+
// --- Agent-scoped instruction loader ---
|
|
313
|
+
// Emits a BP2 agent/system block scoped to the calling agent:
|
|
314
|
+
// - Public/custom agents: their own agents/<agent>.md when present,
|
|
200
315
|
// plus the public agent-worker contract.
|
|
201
|
-
// - Hidden
|
|
202
|
-
// - Null
|
|
316
|
+
// - Hidden agents: their own rules/agent/<agent>.md section only.
|
|
317
|
+
// - Null agent: falls back to the full all-in-one block
|
|
203
318
|
// (explicit-cache unified-shard path).
|
|
204
319
|
//
|
|
205
|
-
//
|
|
206
|
-
// and skill manifest prefix, so
|
|
320
|
+
// Agent-specific markdown intentionally rides BP2, behind the shared BP1 tool
|
|
321
|
+
// and skill manifest prefix, so agent changes do not disturb the common layer.
|
|
207
322
|
//
|
|
208
323
|
// Classification is dynamic — hidden retrieval/maintenance sets come from the
|
|
209
|
-
// `kind` field in internal-
|
|
324
|
+
// `kind` field in internal-agents.mjs. Any other non-null agent is public/custom.
|
|
210
325
|
import {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
} from '../internal-
|
|
326
|
+
listHiddenAgentsByKind,
|
|
327
|
+
isHiddenAgent,
|
|
328
|
+
getAgentCatalogShareAgents,
|
|
329
|
+
isInboundEventAgent,
|
|
330
|
+
} from '../internal-agents.mjs';
|
|
216
331
|
|
|
217
|
-
function
|
|
332
|
+
function loadAgentClassification() {
|
|
218
333
|
// Not cached — called only on instruction rebuild (mtime-busted), and
|
|
219
|
-
//
|
|
220
|
-
// internal-
|
|
221
|
-
//
|
|
334
|
+
// listHiddenAgentsByKind now reads from the mtime-aware cache inside
|
|
335
|
+
// internal-agents.mjs so the classification always reflects the current
|
|
336
|
+
// agents.json on disk.
|
|
222
337
|
return {
|
|
223
|
-
retrieval: new Set(
|
|
224
|
-
maintenance: new Set(
|
|
338
|
+
retrieval: new Set(listHiddenAgentsByKind('retrieval')),
|
|
339
|
+
maintenance: new Set(listHiddenAgentsByKind('maintenance')),
|
|
225
340
|
};
|
|
226
341
|
}
|
|
227
342
|
|
|
@@ -235,7 +350,7 @@ const _scopedRoleInstructionsCache = new Map();
|
|
|
235
350
|
const _scopedRoleInstructionsMtimeCache = new Map();
|
|
236
351
|
const _ROLE_INSTRUCTIONS_MTIME_TTL_MS = 2000;
|
|
237
352
|
|
|
238
|
-
function
|
|
353
|
+
function loadHiddenAgentSnippets(pluginRoot) {
|
|
239
354
|
try {
|
|
240
355
|
const agentRulesDir = join(pluginRoot, 'rules', 'agent');
|
|
241
356
|
if (!existsSync(agentRulesDir)) return [];
|
|
@@ -262,11 +377,11 @@ function loadAgentSections(pluginRoot) {
|
|
|
262
377
|
const agentSections = [];
|
|
263
378
|
if (!existsSync(agentsDir)) return agentSections;
|
|
264
379
|
// agents/ holds two layouts that must BOTH be loaded:
|
|
265
|
-
// - flat: agents/<
|
|
266
|
-
// - nested: agents/<
|
|
267
|
-
// The previous flat-only readdir silently dropped every nested
|
|
268
|
-
// public
|
|
269
|
-
// (BP2) — the model lost its
|
|
380
|
+
// - flat: agents/<agent>.md (legacy: scheduler-task, webhook-handler)
|
|
381
|
+
// - nested: agents/<agent>/AGENT.md (current: worker, heavy-worker, reviewer, …)
|
|
382
|
+
// The previous flat-only readdir silently dropped every nested agent, so a
|
|
383
|
+
// public agent like heavy-worker produced an EMPTY scoped instruction block
|
|
384
|
+
// (BP2) — the model lost its agent contract and the tool smoke's
|
|
270
385
|
// "heavy-worker AGENT.md must be included" assertion failed. Walk both.
|
|
271
386
|
let entries;
|
|
272
387
|
try {
|
|
@@ -295,22 +410,22 @@ function loadAgentSections(pluginRoot) {
|
|
|
295
410
|
return agentSections;
|
|
296
411
|
}
|
|
297
412
|
|
|
298
|
-
// Empty by design: scoped
|
|
413
|
+
// Empty by design: scoped agent markdown already rides BP2 for every provider.
|
|
299
414
|
// Keeping the set in place preserves the old branch point for a future
|
|
300
415
|
// provider-specific experiment without changing today's cache layout.
|
|
301
416
|
const EXPLICIT_CACHE_PROVIDERS = new Set();
|
|
302
417
|
|
|
303
|
-
// Inbound-event maintenance
|
|
304
|
-
// declared via `inboundEvent: true` in defaults/
|
|
305
|
-
// through
|
|
418
|
+
// Inbound-event maintenance agents that report results back to Lead are
|
|
419
|
+
// declared via `inboundEvent: true` in defaults/agents.json and read
|
|
420
|
+
// through isInboundEventAgent(). Such agents must follow
|
|
306
421
|
// rules/agent/20-skip-protocol.md so genuine no-ops (label-only events,
|
|
307
422
|
// dedup, "nothing to report") prefix their output with `[meta:silent]` and the
|
|
308
|
-
// dispatch layer suppresses the Lead inject. Other
|
|
309
|
-
// maintenance, retrieval
|
|
423
|
+
// dispatch layer suppresses the Lead inject. Other agents (cycle1/cycle2 memory
|
|
424
|
+
// maintenance, retrieval agents) never emit toward Lead.
|
|
310
425
|
|
|
311
|
-
export function loadScopedRoleInstructions(
|
|
426
|
+
export function loadScopedRoleInstructions(agent, provider = null) {
|
|
312
427
|
const useUnified = !!(provider && EXPLICIT_CACHE_PROVIDERS.has(provider));
|
|
313
|
-
const cacheKey = useUnified ? '__unified__' : (
|
|
428
|
+
const cacheKey = useUnified ? '__unified__' : (agent || '__all__');
|
|
314
429
|
const cached = _scopedRoleInstructionsCache.get(cacheKey);
|
|
315
430
|
const pluginRoot = mixdogRoot();
|
|
316
431
|
// Use maxMtimeRecursive so edits to .md files inside agents/ and
|
|
@@ -327,7 +442,7 @@ export function loadScopedRoleInstructions(role, provider = null) {
|
|
|
327
442
|
mtime = maxMtimeRecursive([
|
|
328
443
|
join(pluginRoot, 'agents'),
|
|
329
444
|
join(pluginRoot, 'rules', 'agent'),
|
|
330
|
-
join(pluginRoot, 'defaults', '
|
|
445
|
+
join(pluginRoot, 'defaults', 'agents.json'),
|
|
331
446
|
]);
|
|
332
447
|
_scopedRoleInstructionsMtimeCache.set(cacheKey, { mtime, checkedAt: Date.now() });
|
|
333
448
|
if (_scopedRoleInstructionsMtimeCache.size > 16) {
|
|
@@ -338,68 +453,68 @@ export function loadScopedRoleInstructions(role, provider = null) {
|
|
|
338
453
|
if (cached && mtime <= cached.mtime) {
|
|
339
454
|
return cached.value;
|
|
340
455
|
}
|
|
341
|
-
// Compute classification before file loading — internal-
|
|
342
|
-
// failures (malformed/missing
|
|
456
|
+
// Compute classification before file loading — internal-agents metadata
|
|
457
|
+
// failures (malformed/missing agents.json) must propagate, not be
|
|
343
458
|
// silently swallowed by the file-IO catch below.
|
|
344
|
-
const classification =
|
|
345
|
-
const
|
|
346
|
-
? new Set(
|
|
459
|
+
const classification = loadAgentClassification();
|
|
460
|
+
const agentSharesCatalog = agent && classification.retrieval.has(agent)
|
|
461
|
+
? new Set(getAgentCatalogShareAgents(agent))
|
|
347
462
|
: new Set();
|
|
348
|
-
const
|
|
349
|
-
?
|
|
463
|
+
const agentIsInboundEvent = agent && classification.maintenance.has(agent)
|
|
464
|
+
? isInboundEventAgent(agent)
|
|
350
465
|
: false;
|
|
351
466
|
|
|
352
467
|
try {
|
|
353
468
|
const agentSections = loadAgentSections(pluginRoot);
|
|
354
|
-
const hiddenPairs =
|
|
469
|
+
const hiddenPairs = loadHiddenAgentSnippets(pluginRoot);
|
|
355
470
|
|
|
356
|
-
// Pick which agent-rule sections + agents/<
|
|
357
|
-
// based on
|
|
471
|
+
// Pick which agent-rule sections + agents/<agent>.md sections to emit
|
|
472
|
+
// based on agent classification. Self-only emit keeps BP2 minimal.
|
|
358
473
|
let agentRuleSectionsToEmit = null; // null -> drop the agent-rule block entirely
|
|
359
|
-
let agentSectionsToEmit = agentSections; // default: full (unknown-
|
|
474
|
+
let agentSectionsToEmit = agentSections; // default: full (unknown-agent fallback)
|
|
360
475
|
if (useUnified) {
|
|
361
|
-
// Explicit-cache providers — every
|
|
362
|
-
// instruction surface. Cross-
|
|
363
|
-
// shard, eliminating the
|
|
476
|
+
// Explicit-cache providers — every agent sees the same all-in-one
|
|
477
|
+
// instruction surface. Cross-agent calls hit the same provider-side prefix
|
|
478
|
+
// shard, eliminating the agent-shard miss seen on Pool C
|
|
364
479
|
// transitions for openai-oauth/openai. This branch is disabled by the
|
|
365
|
-
// empty provider set above; BP2 remains the active
|
|
480
|
+
// empty provider set above; BP2 remains the active agent surface.
|
|
366
481
|
agentRuleSectionsToEmit = hiddenPairs.map(p => `## ${p.name}\n\n${p.body}`);
|
|
367
482
|
agentSectionsToEmit = agentSections;
|
|
368
|
-
} else if (
|
|
369
|
-
// Retrieval
|
|
483
|
+
} else if (agent && classification.retrieval.has(agent)) {
|
|
484
|
+
// Retrieval agents (explorer) get their own contract section
|
|
370
485
|
// (rules/agent/30-explorer.md) in BP2.
|
|
371
|
-
const self = hiddenPairs.find(p => p.name ===
|
|
486
|
+
const self = hiddenPairs.find(p => p.name === agent);
|
|
372
487
|
agentRuleSectionsToEmit = self ? [`## ${self.name}\n\n${self.body}`] : [];
|
|
373
488
|
agentSectionsToEmit = agentSections.filter(s =>
|
|
374
|
-
[...
|
|
375
|
-
} else if (
|
|
376
|
-
const self = hiddenPairs.find(p => p.name ===
|
|
489
|
+
[...agentSharesCatalog].some(name => s.startsWith(`## ${name}\n`)));
|
|
490
|
+
} else if (agent && classification.maintenance.has(agent)) {
|
|
491
|
+
const self = hiddenPairs.find(p => p.name === agent);
|
|
377
492
|
agentRuleSectionsToEmit = [];
|
|
378
493
|
if (self) {
|
|
379
494
|
agentRuleSectionsToEmit.push(`## ${self.name}\n\n${self.body}`);
|
|
380
495
|
} else {
|
|
381
|
-
//
|
|
382
|
-
//
|
|
383
|
-
//
|
|
384
|
-
const fromAgent = agentSections.find(s => s.startsWith(`## ${
|
|
496
|
+
// Self body from agents/<agent>.md for a maintenance agent
|
|
497
|
+
// without a rules/agent/*.md entry so newly-added hidden agents
|
|
498
|
+
// work without needing a duplicate agent rule file.
|
|
499
|
+
const fromAgent = agentSections.find(s => s.startsWith(`## ${agent}\n`));
|
|
385
500
|
if (fromAgent) agentRuleSectionsToEmit.push(fromAgent);
|
|
386
501
|
}
|
|
387
|
-
// Inbound-event
|
|
502
|
+
// Inbound-event agents also need the skip-protocol rule so they
|
|
388
503
|
// can opt their no-op outputs out of the Lead inject (BP1 would
|
|
389
504
|
// waste the bytes on unrelated agents).
|
|
390
|
-
if (
|
|
505
|
+
if (agentIsInboundEvent) {
|
|
391
506
|
const skip = hiddenPairs.find(p => p.name === 'skip-protocol');
|
|
392
507
|
if (skip) agentRuleSectionsToEmit.push(`## ${skip.name}\n\n${skip.body}`);
|
|
393
508
|
}
|
|
394
509
|
agentSectionsToEmit = [];
|
|
395
|
-
} else if (
|
|
396
|
-
// Public/custom
|
|
510
|
+
} else if (agent) {
|
|
511
|
+
// Public/custom agent — self-only agents/<agent>.md when present,
|
|
397
512
|
// not the full hidden/maintenance bundle. The universal agent
|
|
398
513
|
// contract rides BP2 (rules/agent/00-common.md).
|
|
399
514
|
agentRuleSectionsToEmit = [];
|
|
400
|
-
agentSectionsToEmit = agentSections.filter(s => s.startsWith(`## ${
|
|
515
|
+
agentSectionsToEmit = agentSections.filter(s => s.startsWith(`## ${agent}\n`));
|
|
401
516
|
} else {
|
|
402
|
-
// Null
|
|
517
|
+
// Null agent — full instruction surface emitted (explicit-cache providers that
|
|
403
518
|
// shard by __all__ key).
|
|
404
519
|
agentRuleSectionsToEmit = hiddenPairs.map(p => `## ${p.name}\n\n${p.body}`);
|
|
405
520
|
// agentSectionsToEmit already set to full agentSections above.
|
|
@@ -448,7 +563,7 @@ export function composeSystemPrompt(opts) {
|
|
|
448
563
|
// ── BP2: role/system layer ─────────────────────────────────────────
|
|
449
564
|
const roleInstructionContext = opts.skipRoleCatalog
|
|
450
565
|
? ''
|
|
451
|
-
: loadScopedRoleInstructions(opts.
|
|
566
|
+
: loadScopedRoleInstructions(opts.agent || null, opts.provider || null);
|
|
452
567
|
const stableSystemParts = [];
|
|
453
568
|
if (opts.roleRules) stableSystemParts.push(opts.roleRules);
|
|
454
569
|
if (opts.userPrompt) stableSystemParts.push(opts.userPrompt);
|