mixdog 0.9.1 → 0.9.2
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 +8 -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/background-task-meta-smoke.mjs +1 -1
- package/scripts/bench-run.mjs +262 -0
- package/scripts/compact-smoke.mjs +12 -0
- package/scripts/compact-trigger-migration-smoke.mjs +67 -1
- 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/provider-stream-stall-test.mjs +276 -0
- package/scripts/provider-toolcall-test.mjs +599 -1
- 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 +306 -66
- package/scripts/toolcall-args-test.mjs +81 -0
- package/src/agents/debugger/AGENT.md +4 -4
- package/src/agents/heavy-worker/AGENT.md +4 -2
- package/src/agents/reviewer/AGENT.md +4 -4
- package/src/agents/worker/AGENT.md +4 -2
- 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 +710 -318
- 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 +12 -2
- package/src/rules/agent/00-common.md +7 -5
- package/src/rules/agent/30-explorer.md +7 -8
- package/src/rules/lead/01-general.md +3 -1
- package/src/rules/lead/lead-tool.md +7 -0
- package/src/rules/shared/01-tool.md +17 -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 +131 -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 +94 -16
- 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-oauth.mjs +332 -57
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +59 -32
- package/src/runtime/agent/orchestrator/providers/api-usage.mjs +27 -20
- 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/model-catalog.mjs +18 -8
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +210 -21
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +78 -3
- package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +202 -98
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +183 -20
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +18 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-usage.mjs +11 -5
- package/src/runtime/agent/orchestrator/providers/registry.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +15 -9
- 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.mjs +394 -132
- package/src/runtime/agent/orchestrator/session/manager.mjs +217 -170
- 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 +0 -0
- 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-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 +13 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +10 -17
- package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +18 -2
- 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 +59 -1
- package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +5 -5
- package/src/runtime/agent/orchestrator/tools/code-graph.mjs +4076 -3985
- package/src/runtime/agent/orchestrator/tools/patch.mjs +116 -2
- package/src/runtime/channels/backends/discord.mjs +99 -9
- package/src/runtime/channels/backends/telegram.mjs +501 -0
- package/src/runtime/channels/index.mjs +441 -1224
- package/src/runtime/channels/lib/config.mjs +54 -2
- package/src/runtime/channels/lib/format.mjs +4 -2
- package/src/runtime/channels/lib/output-forwarder.mjs +80 -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 +283 -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/tool-defs.mjs +1 -1
- package/src/runtime/memory/index.mjs +184 -19
- package/src/runtime/memory/lib/agent-ipc.mjs +2 -2
- package/src/runtime/memory/lib/core-memory-store.mjs +1 -1
- package/src/runtime/memory/lib/memory-cycle1.mjs +1 -1
- package/src/runtime/memory/lib/memory-cycle2.mjs +9 -6
- package/src/runtime/memory/lib/memory-cycle3.mjs +1 -1
- package/src/runtime/memory/lib/memory.mjs +101 -4
- package/src/runtime/memory/lib/pg/adapter.mjs +139 -15
- 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 +6 -3
- 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/tool-surface.mjs +98 -13
- package/src/runtime/shared/transcript-writer.mjs +129 -0
- package/src/runtime/shared/update-checker.mjs +214 -0
- package/src/standalone/agent-tool.mjs +255 -109
- package/src/standalone/channel-admin.mjs +133 -40
- package/src/standalone/channel-worker.mjs +8 -291
- package/src/standalone/explore-tool.mjs +2 -2
- package/src/standalone/memory-runtime-proxy.mjs +3 -1
- package/src/standalone/provider-admin.mjs +11 -0
- package/src/standalone/usage-dashboard.mjs +1 -1
- package/src/tui/App.jsx +2096 -732
- 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 +83 -7
- 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 +170 -98
- package/src/tui/components/TurnDone.jsx +4 -4
- package/src/tui/components/UsagePanel.jsx +1 -1
- package/src/tui/components/tool-output-format.mjs +159 -21
- 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 +6965 -2391
- package/src/tui/engine.mjs +287 -126
- package/src/tui/index.jsx +117 -7
- package/src/tui/keyboard-protocol.mjs +42 -0
- package/src/tui/lib/voice-recorder.mjs +453 -0
- package/src/tui/markdown/format-token.mjs +129 -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 +0 -11
- 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 +81 -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 +26 -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 +39 -12
- package/src/workflows/sequential/WORKFLOW.md +46 -0
- package/src/workflows/solo/WORKFLOW.md +7 -0
- 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 {
|
|
@@ -121,6 +121,70 @@ export function loadSkillContent(name, cwd) {
|
|
|
121
121
|
return readSafe(skill.filePath);
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
+
/**
|
|
125
|
+
* Load full skill content plus its on-disk directory (for base-dir + ${MIXDOG_SKILL_DIR}).
|
|
126
|
+
*/
|
|
127
|
+
export function loadSkillResource(name, cwd) {
|
|
128
|
+
const skills = collectSkillsCached(cwd);
|
|
129
|
+
const skill = skills.find(s => s.name === name);
|
|
130
|
+
if (!skill)
|
|
131
|
+
return null;
|
|
132
|
+
const content = readSafe(skill.filePath);
|
|
133
|
+
if (content == null)
|
|
134
|
+
return null;
|
|
135
|
+
return { content, dir: dirname(skill.filePath), filePath: skill.filePath };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function escapeSkillXmlText(value) {
|
|
139
|
+
return String(value || '').replace(/[<>&]/g, (ch) => ({ '<': '<', '>': '>', '&': '&' }[ch]));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Wrap loaded SKILL.md body for Skill tool results (runtime + loop).
|
|
144
|
+
*/
|
|
145
|
+
export function buildSkillResultEnvelope(name, content, skillDir) {
|
|
146
|
+
const escapedName = escapeSkillXmlText(name);
|
|
147
|
+
let body = String(content == null ? '' : content);
|
|
148
|
+
let dirLine = '';
|
|
149
|
+
if (skillDir) {
|
|
150
|
+
const normDir = String(skillDir).replace(/\\/g, '/');
|
|
151
|
+
body = body.replace(/\$\{MIXDOG_SKILL_DIR\}/g, normDir);
|
|
152
|
+
const escapedDir = escapeSkillXmlText(normDir);
|
|
153
|
+
dirLine = `<base-dir>${escapedDir}</base-dir>\n`;
|
|
154
|
+
}
|
|
155
|
+
return `<skill>\n<name>${escapedName}</name>\n${dirLine}${body}\n</skill>`;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Short, model-visible tool_result stub for a loaded skill. The full SKILL.md
|
|
160
|
+
* body is delivered separately as ONE injected user message (newMessages),
|
|
161
|
+
* never in the tool_result — so the body appears exactly once.
|
|
162
|
+
*/
|
|
163
|
+
export function buildSkillStub(name) {
|
|
164
|
+
return `Loaded skill: ${String(name || '').trim()}`;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Build the Skill tool-result envelope used by BOTH the agent-loop viewSkill
|
|
169
|
+
* path and the runtime skillToolContent path so behavior matches across main
|
|
170
|
+
* + agent sessions:
|
|
171
|
+
* - result = short stub (`Loaded skill: <name>`), no body.
|
|
172
|
+
* - newMessages = exactly ONE role:'user' message carrying the full
|
|
173
|
+
* buildSkillResultEnvelope output (<base-dir> + body).
|
|
174
|
+
* The injected user message is flagged `meta:'skill'` so compaction's
|
|
175
|
+
* "latest human prompt" selection does not mistake the skill body for the
|
|
176
|
+
* human's request.
|
|
177
|
+
*/
|
|
178
|
+
export function buildSkillToolEnvelope(name, content, skillDir) {
|
|
179
|
+
return {
|
|
180
|
+
__toolEnvelope: true,
|
|
181
|
+
result: buildSkillStub(name),
|
|
182
|
+
newMessages: [
|
|
183
|
+
{ role: 'user', content: buildSkillResultEnvelope(name, content, skillDir), meta: 'skill' },
|
|
184
|
+
],
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
124
188
|
function compactSkillManifestText(value, max = 180) {
|
|
125
189
|
const text = String(value || '').replace(/\s+/g, ' ').trim();
|
|
126
190
|
return text.length > max ? `${text.slice(0, Math.max(1, max - 3))}...` : text;
|
|
@@ -194,34 +258,34 @@ export function buildSkillToolDefs(skills, { ownerIsAgentSession = false } = {})
|
|
|
194
258
|
];
|
|
195
259
|
return _skillToolDefsCache;
|
|
196
260
|
}
|
|
197
|
-
// ---
|
|
198
|
-
// Emits a BP2
|
|
199
|
-
// - Public/custom agents: their own agents/<
|
|
261
|
+
// --- Agent-scoped instruction loader ---
|
|
262
|
+
// Emits a BP2 agent/system block scoped to the calling agent:
|
|
263
|
+
// - Public/custom agents: their own agents/<agent>.md when present,
|
|
200
264
|
// plus the public agent-worker contract.
|
|
201
|
-
// - Hidden
|
|
202
|
-
// - Null
|
|
265
|
+
// - Hidden agents: their own rules/agent/<agent>.md section only.
|
|
266
|
+
// - Null agent: falls back to the full all-in-one block
|
|
203
267
|
// (explicit-cache unified-shard path).
|
|
204
268
|
//
|
|
205
|
-
//
|
|
206
|
-
// and skill manifest prefix, so
|
|
269
|
+
// Agent-specific markdown intentionally rides BP2, behind the shared BP1 tool
|
|
270
|
+
// and skill manifest prefix, so agent changes do not disturb the common layer.
|
|
207
271
|
//
|
|
208
272
|
// Classification is dynamic — hidden retrieval/maintenance sets come from the
|
|
209
|
-
// `kind` field in internal-
|
|
273
|
+
// `kind` field in internal-agents.mjs. Any other non-null agent is public/custom.
|
|
210
274
|
import {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
} from '../internal-
|
|
275
|
+
listHiddenAgentsByKind,
|
|
276
|
+
isHiddenAgent,
|
|
277
|
+
getAgentCatalogShareAgents,
|
|
278
|
+
isInboundEventAgent,
|
|
279
|
+
} from '../internal-agents.mjs';
|
|
216
280
|
|
|
217
|
-
function
|
|
281
|
+
function loadAgentClassification() {
|
|
218
282
|
// Not cached — called only on instruction rebuild (mtime-busted), and
|
|
219
|
-
//
|
|
220
|
-
// internal-
|
|
221
|
-
//
|
|
283
|
+
// listHiddenAgentsByKind now reads from the mtime-aware cache inside
|
|
284
|
+
// internal-agents.mjs so the classification always reflects the current
|
|
285
|
+
// agents.json on disk.
|
|
222
286
|
return {
|
|
223
|
-
retrieval: new Set(
|
|
224
|
-
maintenance: new Set(
|
|
287
|
+
retrieval: new Set(listHiddenAgentsByKind('retrieval')),
|
|
288
|
+
maintenance: new Set(listHiddenAgentsByKind('maintenance')),
|
|
225
289
|
};
|
|
226
290
|
}
|
|
227
291
|
|
|
@@ -235,7 +299,7 @@ const _scopedRoleInstructionsCache = new Map();
|
|
|
235
299
|
const _scopedRoleInstructionsMtimeCache = new Map();
|
|
236
300
|
const _ROLE_INSTRUCTIONS_MTIME_TTL_MS = 2000;
|
|
237
301
|
|
|
238
|
-
function
|
|
302
|
+
function loadHiddenAgentSnippets(pluginRoot) {
|
|
239
303
|
try {
|
|
240
304
|
const agentRulesDir = join(pluginRoot, 'rules', 'agent');
|
|
241
305
|
if (!existsSync(agentRulesDir)) return [];
|
|
@@ -262,11 +326,11 @@ function loadAgentSections(pluginRoot) {
|
|
|
262
326
|
const agentSections = [];
|
|
263
327
|
if (!existsSync(agentsDir)) return agentSections;
|
|
264
328
|
// 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
|
|
329
|
+
// - flat: agents/<agent>.md (legacy: scheduler-task, webhook-handler)
|
|
330
|
+
// - nested: agents/<agent>/AGENT.md (current: worker, heavy-worker, reviewer, …)
|
|
331
|
+
// The previous flat-only readdir silently dropped every nested agent, so a
|
|
332
|
+
// public agent like heavy-worker produced an EMPTY scoped instruction block
|
|
333
|
+
// (BP2) — the model lost its agent contract and the tool smoke's
|
|
270
334
|
// "heavy-worker AGENT.md must be included" assertion failed. Walk both.
|
|
271
335
|
let entries;
|
|
272
336
|
try {
|
|
@@ -295,22 +359,22 @@ function loadAgentSections(pluginRoot) {
|
|
|
295
359
|
return agentSections;
|
|
296
360
|
}
|
|
297
361
|
|
|
298
|
-
// Empty by design: scoped
|
|
362
|
+
// Empty by design: scoped agent markdown already rides BP2 for every provider.
|
|
299
363
|
// Keeping the set in place preserves the old branch point for a future
|
|
300
364
|
// provider-specific experiment without changing today's cache layout.
|
|
301
365
|
const EXPLICIT_CACHE_PROVIDERS = new Set();
|
|
302
366
|
|
|
303
|
-
// Inbound-event maintenance
|
|
304
|
-
// declared via `inboundEvent: true` in defaults/
|
|
305
|
-
// through
|
|
367
|
+
// Inbound-event maintenance agents that report results back to Lead are
|
|
368
|
+
// declared via `inboundEvent: true` in defaults/agents.json and read
|
|
369
|
+
// through isInboundEventAgent(). Such agents must follow
|
|
306
370
|
// rules/agent/20-skip-protocol.md so genuine no-ops (label-only events,
|
|
307
371
|
// dedup, "nothing to report") prefix their output with `[meta:silent]` and the
|
|
308
|
-
// dispatch layer suppresses the Lead inject. Other
|
|
309
|
-
// maintenance, retrieval
|
|
372
|
+
// dispatch layer suppresses the Lead inject. Other agents (cycle1/cycle2 memory
|
|
373
|
+
// maintenance, retrieval agents) never emit toward Lead.
|
|
310
374
|
|
|
311
|
-
export function loadScopedRoleInstructions(
|
|
375
|
+
export function loadScopedRoleInstructions(agent, provider = null) {
|
|
312
376
|
const useUnified = !!(provider && EXPLICIT_CACHE_PROVIDERS.has(provider));
|
|
313
|
-
const cacheKey = useUnified ? '__unified__' : (
|
|
377
|
+
const cacheKey = useUnified ? '__unified__' : (agent || '__all__');
|
|
314
378
|
const cached = _scopedRoleInstructionsCache.get(cacheKey);
|
|
315
379
|
const pluginRoot = mixdogRoot();
|
|
316
380
|
// Use maxMtimeRecursive so edits to .md files inside agents/ and
|
|
@@ -327,7 +391,7 @@ export function loadScopedRoleInstructions(role, provider = null) {
|
|
|
327
391
|
mtime = maxMtimeRecursive([
|
|
328
392
|
join(pluginRoot, 'agents'),
|
|
329
393
|
join(pluginRoot, 'rules', 'agent'),
|
|
330
|
-
join(pluginRoot, 'defaults', '
|
|
394
|
+
join(pluginRoot, 'defaults', 'agents.json'),
|
|
331
395
|
]);
|
|
332
396
|
_scopedRoleInstructionsMtimeCache.set(cacheKey, { mtime, checkedAt: Date.now() });
|
|
333
397
|
if (_scopedRoleInstructionsMtimeCache.size > 16) {
|
|
@@ -338,68 +402,68 @@ export function loadScopedRoleInstructions(role, provider = null) {
|
|
|
338
402
|
if (cached && mtime <= cached.mtime) {
|
|
339
403
|
return cached.value;
|
|
340
404
|
}
|
|
341
|
-
// Compute classification before file loading — internal-
|
|
342
|
-
// failures (malformed/missing
|
|
405
|
+
// Compute classification before file loading — internal-agents metadata
|
|
406
|
+
// failures (malformed/missing agents.json) must propagate, not be
|
|
343
407
|
// silently swallowed by the file-IO catch below.
|
|
344
|
-
const classification =
|
|
345
|
-
const
|
|
346
|
-
? new Set(
|
|
408
|
+
const classification = loadAgentClassification();
|
|
409
|
+
const agentSharesCatalog = agent && classification.retrieval.has(agent)
|
|
410
|
+
? new Set(getAgentCatalogShareAgents(agent))
|
|
347
411
|
: new Set();
|
|
348
|
-
const
|
|
349
|
-
?
|
|
412
|
+
const agentIsInboundEvent = agent && classification.maintenance.has(agent)
|
|
413
|
+
? isInboundEventAgent(agent)
|
|
350
414
|
: false;
|
|
351
415
|
|
|
352
416
|
try {
|
|
353
417
|
const agentSections = loadAgentSections(pluginRoot);
|
|
354
|
-
const hiddenPairs =
|
|
418
|
+
const hiddenPairs = loadHiddenAgentSnippets(pluginRoot);
|
|
355
419
|
|
|
356
|
-
// Pick which agent-rule sections + agents/<
|
|
357
|
-
// based on
|
|
420
|
+
// Pick which agent-rule sections + agents/<agent>.md sections to emit
|
|
421
|
+
// based on agent classification. Self-only emit keeps BP2 minimal.
|
|
358
422
|
let agentRuleSectionsToEmit = null; // null -> drop the agent-rule block entirely
|
|
359
|
-
let agentSectionsToEmit = agentSections; // default: full (unknown-
|
|
423
|
+
let agentSectionsToEmit = agentSections; // default: full (unknown-agent fallback)
|
|
360
424
|
if (useUnified) {
|
|
361
|
-
// Explicit-cache providers — every
|
|
362
|
-
// instruction surface. Cross-
|
|
363
|
-
// shard, eliminating the
|
|
425
|
+
// Explicit-cache providers — every agent sees the same all-in-one
|
|
426
|
+
// instruction surface. Cross-agent calls hit the same provider-side prefix
|
|
427
|
+
// shard, eliminating the agent-shard miss seen on Pool C
|
|
364
428
|
// transitions for openai-oauth/openai. This branch is disabled by the
|
|
365
|
-
// empty provider set above; BP2 remains the active
|
|
429
|
+
// empty provider set above; BP2 remains the active agent surface.
|
|
366
430
|
agentRuleSectionsToEmit = hiddenPairs.map(p => `## ${p.name}\n\n${p.body}`);
|
|
367
431
|
agentSectionsToEmit = agentSections;
|
|
368
|
-
} else if (
|
|
369
|
-
// Retrieval
|
|
432
|
+
} else if (agent && classification.retrieval.has(agent)) {
|
|
433
|
+
// Retrieval agents (explorer) get their own contract section
|
|
370
434
|
// (rules/agent/30-explorer.md) in BP2.
|
|
371
|
-
const self = hiddenPairs.find(p => p.name ===
|
|
435
|
+
const self = hiddenPairs.find(p => p.name === agent);
|
|
372
436
|
agentRuleSectionsToEmit = self ? [`## ${self.name}\n\n${self.body}`] : [];
|
|
373
437
|
agentSectionsToEmit = agentSections.filter(s =>
|
|
374
|
-
[...
|
|
375
|
-
} else if (
|
|
376
|
-
const self = hiddenPairs.find(p => p.name ===
|
|
438
|
+
[...agentSharesCatalog].some(name => s.startsWith(`## ${name}\n`)));
|
|
439
|
+
} else if (agent && classification.maintenance.has(agent)) {
|
|
440
|
+
const self = hiddenPairs.find(p => p.name === agent);
|
|
377
441
|
agentRuleSectionsToEmit = [];
|
|
378
442
|
if (self) {
|
|
379
443
|
agentRuleSectionsToEmit.push(`## ${self.name}\n\n${self.body}`);
|
|
380
444
|
} else {
|
|
381
|
-
//
|
|
382
|
-
//
|
|
383
|
-
//
|
|
384
|
-
const fromAgent = agentSections.find(s => s.startsWith(`## ${
|
|
445
|
+
// Self body from agents/<agent>.md for a maintenance agent
|
|
446
|
+
// without a rules/agent/*.md entry so newly-added hidden agents
|
|
447
|
+
// work without needing a duplicate agent rule file.
|
|
448
|
+
const fromAgent = agentSections.find(s => s.startsWith(`## ${agent}\n`));
|
|
385
449
|
if (fromAgent) agentRuleSectionsToEmit.push(fromAgent);
|
|
386
450
|
}
|
|
387
|
-
// Inbound-event
|
|
451
|
+
// Inbound-event agents also need the skip-protocol rule so they
|
|
388
452
|
// can opt their no-op outputs out of the Lead inject (BP1 would
|
|
389
453
|
// waste the bytes on unrelated agents).
|
|
390
|
-
if (
|
|
454
|
+
if (agentIsInboundEvent) {
|
|
391
455
|
const skip = hiddenPairs.find(p => p.name === 'skip-protocol');
|
|
392
456
|
if (skip) agentRuleSectionsToEmit.push(`## ${skip.name}\n\n${skip.body}`);
|
|
393
457
|
}
|
|
394
458
|
agentSectionsToEmit = [];
|
|
395
|
-
} else if (
|
|
396
|
-
// Public/custom
|
|
459
|
+
} else if (agent) {
|
|
460
|
+
// Public/custom agent — self-only agents/<agent>.md when present,
|
|
397
461
|
// not the full hidden/maintenance bundle. The universal agent
|
|
398
462
|
// contract rides BP2 (rules/agent/00-common.md).
|
|
399
463
|
agentRuleSectionsToEmit = [];
|
|
400
|
-
agentSectionsToEmit = agentSections.filter(s => s.startsWith(`## ${
|
|
464
|
+
agentSectionsToEmit = agentSections.filter(s => s.startsWith(`## ${agent}\n`));
|
|
401
465
|
} else {
|
|
402
|
-
// Null
|
|
466
|
+
// Null agent — full instruction surface emitted (explicit-cache providers that
|
|
403
467
|
// shard by __all__ key).
|
|
404
468
|
agentRuleSectionsToEmit = hiddenPairs.map(p => `## ${p.name}\n\n${p.body}`);
|
|
405
469
|
// agentSectionsToEmit already set to full agentSections above.
|
|
@@ -448,7 +512,7 @@ export function composeSystemPrompt(opts) {
|
|
|
448
512
|
// ── BP2: role/system layer ─────────────────────────────────────────
|
|
449
513
|
const roleInstructionContext = opts.skipRoleCatalog
|
|
450
514
|
? ''
|
|
451
|
-
: loadScopedRoleInstructions(opts.
|
|
515
|
+
: loadScopedRoleInstructions(opts.agent || null, opts.provider || null);
|
|
452
516
|
const stableSystemParts = [];
|
|
453
517
|
if (opts.roleRules) stableSystemParts.push(opts.roleRules);
|
|
454
518
|
if (opts.userPrompt) stableSystemParts.push(opts.userPrompt);
|
|
@@ -1,50 +1,50 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Internal hidden
|
|
2
|
+
* Internal hidden agents — Mixdog-managed, user-untouchable.
|
|
3
3
|
*
|
|
4
|
-
* Unlike public workflow agents, these hidden
|
|
4
|
+
* Unlike public workflow agents, these hidden agents are NEVER exposed to callers of the `agent` tool. They are
|
|
5
5
|
* invoked only by internal handlers (explore / recall / search) and carry
|
|
6
6
|
* their own system prompt + tool-set policy.
|
|
7
7
|
*
|
|
8
8
|
* Lookup order (agent-dispatch.resolvePresetName):
|
|
9
9
|
* 1. explicit preset arg
|
|
10
10
|
* 2. opts.preset
|
|
11
|
-
* 3. hidden-
|
|
11
|
+
* 3. hidden-agent registry (defaults/agents.json + systemFile frontmatter)
|
|
12
12
|
*
|
|
13
|
-
*
|
|
13
|
+
* Agent definitions live in defaults/agents.json and the referenced
|
|
14
14
|
* systemFile markdown frontmatter. Editing those files is a Mixdog source change.
|
|
15
15
|
*
|
|
16
16
|
* The preset names refer to entries seeded in mixdog-config.json (agent.presets)
|
|
17
17
|
* via DEFAULT_PRESETS (see config.mjs). If the user deletes the referenced preset
|
|
18
|
-
* from their config the hidden
|
|
18
|
+
* from their config the hidden agents degrade gracefully — `resolvePresetName`
|
|
19
19
|
* returns a name, but session creation will fail with a clear "preset not
|
|
20
20
|
* found" error rather than silently mis-dispatching.
|
|
21
21
|
*
|
|
22
22
|
* Kind classification:
|
|
23
|
-
* - 'retrieval' : short-lived hidden retrieval
|
|
24
|
-
* - 'maintenance' : background-trigger hidden
|
|
23
|
+
* - 'retrieval' : short-lived hidden retrieval agents (explore).
|
|
24
|
+
* - 'maintenance' : background-trigger hidden agents (memory cycle, scheduler,
|
|
25
25
|
* webhook). Receive only their own self section in BP2.
|
|
26
26
|
*
|
|
27
27
|
* Permission classification:
|
|
28
28
|
* - 'read' : read-only — apply_patch/shell blocked at loop.mjs runtime
|
|
29
|
-
* guard with the same error string public read-only
|
|
30
|
-
* - 'read-write' : full tool surface — used by hidden
|
|
29
|
+
* guard with the same error string public read-only agents see.
|
|
30
|
+
* - 'read-write' : full tool surface — used by hidden agents that legitimately
|
|
31
31
|
* mutate state (scheduler-task launches commands,
|
|
32
32
|
* webhook-handler persists payloads). agent-dispatch honors this
|
|
33
|
-
* declaratively instead of forcing every hidden
|
|
33
|
+
* declaratively instead of forcing every hidden agent to 'read'.
|
|
34
34
|
*
|
|
35
35
|
* Tool schema profile:
|
|
36
|
-
* - 'none' : no tools exposed; pure transform/classifier
|
|
36
|
+
* - 'none' : no tools exposed; pure transform/classifier agents.
|
|
37
37
|
* - 'read' : read/search/code-navigation tools only.
|
|
38
38
|
* - 'full' : shared agent tool schema for provider cache reuse.
|
|
39
39
|
*
|
|
40
|
-
*
|
|
40
|
+
* Agent-specific instruction metadata (consumed by rules-builder.cjs
|
|
41
41
|
* buildAgentRoleSpecificContent + collect.mjs):
|
|
42
|
-
* - inboundEvent :
|
|
42
|
+
* - inboundEvent : agent reports results back to Lead and must carry the
|
|
43
43
|
* skip-protocol rule (rules/agent/20-skip-protocol.md)
|
|
44
|
-
* in its BP2
|
|
44
|
+
* in its BP2 agent-rule block so no-op outputs opt out of the Lead
|
|
45
45
|
* inject.
|
|
46
46
|
* - instructionDir : DATA_DIR subdir whose *.md tree is folded into the
|
|
47
|
-
*
|
|
47
|
+
* agent's BP4-adjacent user/task data (webhook-handler →
|
|
48
48
|
* webhooks, scheduler-task → schedules).
|
|
49
49
|
*/
|
|
50
50
|
|
|
@@ -56,24 +56,24 @@ import {
|
|
|
56
56
|
parseMarkdownFrontmatter,
|
|
57
57
|
} from '../../shared/markdown-frontmatter.mjs'
|
|
58
58
|
|
|
59
|
-
// Resolve the path to defaults/
|
|
59
|
+
// Resolve the path to defaults/agents.json once.
|
|
60
60
|
const _MIXDOG_ROOT = mixdogRoot()
|
|
61
|
-
const
|
|
62
|
-
return join(_MIXDOG_ROOT, 'defaults', '
|
|
61
|
+
const _AGENTS_PATH = (() => {
|
|
62
|
+
return join(_MIXDOG_ROOT, 'defaults', 'agents.json')
|
|
63
63
|
})()
|
|
64
64
|
|
|
65
65
|
/** @type {{ mtime: number, map: object } | null} */
|
|
66
|
-
let
|
|
66
|
+
let _hiddenAgentsCache = null
|
|
67
67
|
|
|
68
68
|
function _mtimeSafe(file) {
|
|
69
69
|
try { return statSync(file).mtimeMs } catch { return 0 }
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
function
|
|
73
|
-
let mtime = _mtimeSafe(
|
|
72
|
+
function _hiddenAgentsDependencyMtime() {
|
|
73
|
+
let mtime = _mtimeSafe(_AGENTS_PATH)
|
|
74
74
|
try {
|
|
75
|
-
const raw = JSON.parse(readFileSync(
|
|
76
|
-
for (const entry of (raw.
|
|
75
|
+
const raw = JSON.parse(readFileSync(_AGENTS_PATH, 'utf8'))
|
|
76
|
+
for (const entry of (raw.agents || [])) {
|
|
77
77
|
const systemFile = typeof entry?.systemFile === 'string' ? entry.systemFile.trim() : ''
|
|
78
78
|
if (!systemFile) continue
|
|
79
79
|
mtime = Math.max(mtime, _mtimeSafe(join(_MIXDOG_ROOT, systemFile)))
|
|
@@ -82,7 +82,7 @@ function _hiddenRolesDependencyMtime() {
|
|
|
82
82
|
return mtime
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
function
|
|
85
|
+
function _loadHiddenAgentFrontmatter(systemFile) {
|
|
86
86
|
const rel = typeof systemFile === 'string' ? systemFile.trim() : ''
|
|
87
87
|
if (!rel) return {}
|
|
88
88
|
try {
|
|
@@ -92,8 +92,8 @@ function _loadHiddenRoleFrontmatter(systemFile) {
|
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
function
|
|
96
|
-
const fm =
|
|
95
|
+
function _mergeHiddenAgentFrontmatter(entry) {
|
|
96
|
+
const fm = _loadHiddenAgentFrontmatter(entry.systemFile)
|
|
97
97
|
const merged = { ...entry }
|
|
98
98
|
const permission = normalizeAgentPermissionOrNone(fm.permission)
|
|
99
99
|
if (permission) merged.permission = permission
|
|
@@ -111,62 +111,62 @@ function _mergeHiddenRoleFrontmatter(entry) {
|
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
/**
|
|
114
|
-
* Read and parse defaults/
|
|
114
|
+
* Read and parse defaults/agents.json. Throws on missing/malformed.
|
|
115
115
|
*/
|
|
116
|
-
function
|
|
116
|
+
function _loadHiddenAgents() {
|
|
117
117
|
try {
|
|
118
|
-
const raw = JSON.parse(readFileSync(
|
|
118
|
+
const raw = JSON.parse(readFileSync(_AGENTS_PATH, 'utf8'))
|
|
119
119
|
const map = Object.create(null)
|
|
120
|
-
for (const entry of (raw.
|
|
121
|
-
if (entry && entry.
|
|
120
|
+
for (const entry of (raw.agents || [])) {
|
|
121
|
+
if (entry && entry.agent) map[entry.agent] = Object.freeze(_mergeHiddenAgentFrontmatter(entry))
|
|
122
122
|
}
|
|
123
123
|
return Object.freeze(map)
|
|
124
124
|
} catch (err) {
|
|
125
|
-
// Fail loudly — a missing or malformed
|
|
126
|
-
throw new Error(`[internal-
|
|
125
|
+
// Fail loudly — a missing or malformed agents.json breaks dispatch.
|
|
126
|
+
throw new Error(`[internal-agents] failed to load defaults/agents.json: ${err.message}`)
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
129
|
|
|
130
130
|
/**
|
|
131
|
-
* Return the hidden-
|
|
131
|
+
* Return the hidden-agent map, re-reading from disk when the file mtime has
|
|
132
132
|
* changed since the last load. This ensures that BP2 cache rebuilds triggered
|
|
133
|
-
* by
|
|
133
|
+
* by an agents.json modification (tracked via maxMtimeRecursive in
|
|
134
134
|
* collect.mjs) consume fresh metadata in the same process.
|
|
135
135
|
*/
|
|
136
|
-
function
|
|
136
|
+
function _getHiddenAgents() {
|
|
137
137
|
try {
|
|
138
|
-
const mtime =
|
|
139
|
-
if (
|
|
140
|
-
return
|
|
138
|
+
const mtime = _hiddenAgentsDependencyMtime()
|
|
139
|
+
if (_hiddenAgentsCache && mtime <= _hiddenAgentsCache.mtime) {
|
|
140
|
+
return _hiddenAgentsCache.map
|
|
141
141
|
}
|
|
142
|
-
const map =
|
|
143
|
-
|
|
142
|
+
const map = _loadHiddenAgents()
|
|
143
|
+
_hiddenAgentsCache = { mtime, map }
|
|
144
144
|
return map
|
|
145
145
|
} catch (err) {
|
|
146
146
|
// Fail loudly — re-throw with a clear message. A cache hit is never used
|
|
147
147
|
// when statSync fails because the caller expects current data.
|
|
148
|
-
throw new Error(`[internal-
|
|
148
|
+
throw new Error(`[internal-agents] failed to load defaults/agents.json: ${err.message}`)
|
|
149
149
|
}
|
|
150
150
|
}
|
|
151
151
|
|
|
152
152
|
// Eager validate at module init so startup failures are immediate.
|
|
153
|
-
|
|
153
|
+
_getHiddenAgents()
|
|
154
154
|
|
|
155
155
|
/**
|
|
156
|
-
* Return the hidden-
|
|
156
|
+
* Return the hidden-agent definition, or null if the name is not internal.
|
|
157
157
|
*/
|
|
158
|
-
export function
|
|
158
|
+
export function getHiddenAgent(name) {
|
|
159
159
|
if (!name) return null
|
|
160
|
-
return
|
|
160
|
+
return _getHiddenAgents()[name] || null
|
|
161
161
|
}
|
|
162
162
|
|
|
163
163
|
/**
|
|
164
|
-
* Resolve permission stamped on a agent session. Hidden
|
|
164
|
+
* Resolve permission stamped on a agent session. Hidden agents declared
|
|
165
165
|
* `permission: 'read'` are read-locked — caller opts cannot upgrade them.
|
|
166
166
|
* Other built-in permissions include `none`, `read-write`, `mcp`, and `full`.
|
|
167
167
|
*/
|
|
168
|
-
export function resolveAgentSessionPermission(
|
|
169
|
-
const hidden =
|
|
168
|
+
export function resolveAgentSessionPermission(agent, callerPermission) {
|
|
169
|
+
const hidden = getHiddenAgent(agent)
|
|
170
170
|
if (hidden && hidden.permission === 'read') return 'read'
|
|
171
171
|
if (callerPermission != null && callerPermission !== '') return callerPermission
|
|
172
172
|
if (hidden?.permission) return hidden.permission
|
|
@@ -176,61 +176,61 @@ export function resolveAgentSessionPermission(role, callerPermission) {
|
|
|
176
176
|
/**
|
|
177
177
|
* Boolean check — useful for branching inside agent-dispatch / session-manager.
|
|
178
178
|
*/
|
|
179
|
-
export function
|
|
179
|
+
export function isHiddenAgent(name) {
|
|
180
180
|
if (!name) return false
|
|
181
|
-
return Object.prototype.hasOwnProperty.call(
|
|
181
|
+
return Object.prototype.hasOwnProperty.call(_getHiddenAgents(), name)
|
|
182
182
|
}
|
|
183
183
|
|
|
184
184
|
/**
|
|
185
|
-
* List all hidden
|
|
186
|
-
* a user-defined
|
|
185
|
+
* List all hidden agent names. Used by diagnostics / setup UI guards to ensure
|
|
186
|
+
* a user-defined agent doesn't collide with an internal one.
|
|
187
187
|
*/
|
|
188
|
-
export function
|
|
189
|
-
return Object.keys(
|
|
188
|
+
export function listHiddenAgentNames() {
|
|
189
|
+
return Object.keys(_getHiddenAgents())
|
|
190
190
|
}
|
|
191
191
|
|
|
192
192
|
/**
|
|
193
|
-
* List hidden
|
|
194
|
-
* Consumed by collect.mjs to drive BP2
|
|
195
|
-
* instead of hard-coding
|
|
193
|
+
* List hidden agent names matching a given kind ('retrieval' | 'maintenance').
|
|
194
|
+
* Consumed by collect.mjs to drive BP2 agent-shard classification dynamically
|
|
195
|
+
* instead of hard-coding agent-name sets.
|
|
196
196
|
*/
|
|
197
|
-
export function
|
|
197
|
+
export function listHiddenAgentsByKind(kind) {
|
|
198
198
|
const out = []
|
|
199
|
-
for (const [name, def] of Object.entries(
|
|
199
|
+
for (const [name, def] of Object.entries(_getHiddenAgents())) {
|
|
200
200
|
if (def.kind === kind) out.push(name)
|
|
201
201
|
}
|
|
202
202
|
return out
|
|
203
203
|
}
|
|
204
204
|
|
|
205
205
|
/**
|
|
206
|
-
* Return the agents/<name>.md sections a hidden
|
|
206
|
+
* Return the agents/<name>.md sections a hidden agent shares in its BP2 catalog
|
|
207
207
|
* (in addition to its own self section). Drives the explorer→worker cache
|
|
208
|
-
* alignment declaratively instead of a hard-coded
|
|
209
|
-
* collect.mjs. Returns [] when the
|
|
208
|
+
* alignment declaratively instead of a hard-coded agent-name branch in
|
|
209
|
+
* collect.mjs. Returns [] when the agent declares none.
|
|
210
210
|
*/
|
|
211
|
-
export function
|
|
212
|
-
const hidden =
|
|
211
|
+
export function getAgentCatalogShareAgents(name) {
|
|
212
|
+
const hidden = getHiddenAgent(name)
|
|
213
213
|
if (!hidden || !Array.isArray(hidden.catalogShareAgents)) return []
|
|
214
214
|
return hidden.catalogShareAgents.map((n) => String(n || '').trim()).filter(Boolean)
|
|
215
215
|
}
|
|
216
216
|
|
|
217
217
|
/**
|
|
218
|
-
* True when a hidden
|
|
219
|
-
* skip-protocol rule in its BP2
|
|
218
|
+
* True when a hidden agent reports results back to Lead and must carry the
|
|
219
|
+
* skip-protocol rule in its BP2 agent-rule block. Replaces the hard-coded
|
|
220
220
|
* INBOUND_EVENT_ROLES set in collect.mjs.
|
|
221
221
|
*/
|
|
222
|
-
export function
|
|
223
|
-
const hidden =
|
|
222
|
+
export function isInboundEventAgent(name) {
|
|
223
|
+
const hidden = getHiddenAgent(name)
|
|
224
224
|
return !!(hidden && hidden.inboundEvent === true)
|
|
225
225
|
}
|
|
226
226
|
|
|
227
227
|
/**
|
|
228
228
|
* Return the DATA_DIR subdir whose *.md tree rides as BP4-adjacent
|
|
229
|
-
* user/task data, or null when the
|
|
229
|
+
* user/task data, or null when the agent declares none. Replaces the
|
|
230
230
|
* webhook/scheduler ternary in rules-builder.cjs buildAgentRoleSpecificContent.
|
|
231
231
|
*/
|
|
232
|
-
export function
|
|
233
|
-
const hidden =
|
|
232
|
+
export function getAgentInstructionDir(name) {
|
|
233
|
+
const hidden = getHiddenAgent(name)
|
|
234
234
|
const dir = hidden && typeof hidden.instructionDir === 'string' ? hidden.instructionDir.trim() : ''
|
|
235
235
|
return dir || null
|
|
236
236
|
}
|