mixdog 1.2.0 → 1.2.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/README.md +7 -5
- package/package.json +1 -1
- package/src/defaults/shipped-history.json +4 -0
- package/src/defaults/skills/pptx/SKILL.md +6 -6
- package/src/defaults/skills/pptx/references/review.md +6 -4
- package/src/defaults/skills/pptx/scripts/source-extract.mjs +1 -1
- package/src/defaults/skills/setup/references/actions.md +13 -3
- package/src/defaults/skills/visualize/SKILL.md +12 -9
- package/src/rules/shared/60-verification.md +3 -1
- package/src/rules/shared/70-delivery.md +4 -2
- package/src/runtime/agent/orchestrator/cache-mtime.mjs +26 -5
- package/src/runtime/agent/orchestrator/config.mjs +10 -4
- package/src/runtime/agent/orchestrator/context/collect.mjs +2 -1
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +11 -5
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +74 -21
- package/src/runtime/agent/orchestrator/mcp/client-config.mjs +86 -8
- package/src/runtime/agent/orchestrator/mcp/client-handshake.mjs +5 -1
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +65 -7
- package/src/runtime/agent/orchestrator/mcp/client.mjs +128 -44
- package/src/runtime/agent/orchestrator/mcp/lazy-output-validator.mjs +25 -0
- package/src/runtime/agent/orchestrator/mcp/plugin-placeholders.mjs +54 -0
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +108 -17
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +19 -11
- package/src/runtime/agent/orchestrator/providers/auto-effort.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +337 -0
- package/src/runtime/agent/orchestrator/providers/command-code-oauth-tokens.mjs +159 -0
- package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +444 -0
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +7 -4
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +9 -2
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +41 -28
- package/src/runtime/agent/orchestrator/providers/lib/gemini-model-catalog.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-bridge.mjs +1080 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +15 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +35 -0
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +12 -0
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +6 -5
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +6 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +11 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +9 -3
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +4 -4
- package/src/runtime/agent/orchestrator/providers/registry.mjs +35 -9
- package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/extension-scopes.mjs +15 -55
- package/src/runtime/agent/orchestrator/runtime-core/goal-control.mjs +15 -2
- package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +267 -84
- package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +4 -1
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +21 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +54 -3
- package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +284 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +268 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/sqlite-gate.mjs +27 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/worker.mjs +628 -0
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +184 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +136 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +128 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +127 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +101 -0
- package/src/runtime/agent/orchestrator/session/explicit-skills.mjs +83 -5
- package/src/runtime/agent/orchestrator/session/imported-message.mjs +11 -0
- package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +6 -4
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +4 -3
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +12 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +20 -12
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +9 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +17 -4
- package/src/runtime/agent/orchestrator/session/manager.mjs +0 -1
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +4 -3
- package/src/runtime/agent/orchestrator/session/store/listing.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +817 -0
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +7 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +19 -12
- package/src/runtime/agent/orchestrator/session/store-summary-reader-catalog-fixture.mjs +158 -0
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +183 -374
- package/src/runtime/agent/orchestrator/session/synthetic-user-envelope.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +21 -2
- package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +38 -17
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +17 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +4 -0
- package/src/runtime/agent/orchestrator/tools/builtin/lib/list-helpers.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/path-diagnostics.mjs +6 -6
- package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +173 -22
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-guards.mjs +8 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +5 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-source-windows.mjs +15 -2
- package/src/runtime/agent/orchestrator/tools/builtin/search-glob-tool.mjs +13 -10
- package/src/runtime/agent/orchestrator/tools/builtin/search-grep-tool.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +17 -12
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/patch/apply-patch/codex-batch.mjs +4 -4
- package/src/runtime/agent/orchestrator/tools/patch/apply-patch/route.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/patch/read-redirects.mjs +34 -30
- package/src/runtime/agent/orchestrator/tools/patch/sequence/units.mjs +7 -7
- package/src/runtime/agent/orchestrator/tools/patch/sequence.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +4 -0
- package/src/runtime/attachments/store.d.mts +3 -0
- package/src/runtime/channels/lib/owned-runtime/owned-start.mjs +1 -1
- package/src/runtime/channels/lib/webhook/session-dispatch.mjs +16 -4
- package/src/runtime/channels/lib/worker-main.mjs +17 -14
- package/src/runtime/computer-bridge/linux-readiness.mjs +0 -2
- package/src/runtime/effort-judge/judge-client.mjs +56 -18
- package/src/runtime/memory/lib/memory.mjs +1 -1
- package/src/runtime/memory/lib/session-ingest.mjs +2 -2
- package/src/runtime/shared/atomic-file.mjs +25 -4
- package/src/runtime/shared/extension-scopes.mjs +5 -3
- package/src/runtime/shared/file-lock.mjs +37 -11
- package/src/runtime/shared/llm/anthropic-effort.mjs +14 -0
- package/src/runtime/shared/llm/model-catalog.mjs +0 -12
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +6 -0
- package/src/runtime/shared/plugin-manifest.mjs +18 -9
- package/src/runtime/shared/pristine-execution-contract.json +9 -2
- package/src/runtime/shared/pristine-execution.mjs +28 -4
- package/src/runtime/shared/provider-accounts.mjs +124 -20
- package/src/runtime/shared/provider-api-key.mjs +12 -0
- package/src/runtime/shared/shell-display.mjs +9 -3
- package/src/runtime/shared/skill-mentions.d.mts +10 -0
- package/src/runtime/shared/skill-mentions.mjs +133 -0
- package/src/runtime/shared/skill-script-runtime.mjs +264 -0
- package/src/runtime/shared/tool-primitives.mjs +35 -2
- package/src/runtime/shared/turn-worktree-snapshot.mjs +25 -5
- package/src/runtime/shared/worker-requests.mjs +15 -2
- package/src/session-runtime/automation-agents.mjs +8 -2
- package/src/session-runtime/boot/apis.mjs +55 -0
- package/src/session-runtime/boot/config.mjs +5 -2
- package/src/session-runtime/boot/facade.mjs +1 -0
- package/src/session-runtime/boot/infrastructure.mjs +29 -18
- package/src/session-runtime/conversation-import/discovery.mjs +698 -0
- package/src/session-runtime/conversation-import/service.mjs +369 -0
- package/src/session-runtime/cwd-plugins/cwd-apply.mjs +10 -5
- package/src/session-runtime/cwd-plugins/plugin-status.mjs +47 -42
- package/src/session-runtime/mcp-glue/connect.mjs +57 -10
- package/src/session-runtime/mcp-glue/plugin-servers.mjs +499 -0
- package/src/session-runtime/mcp-glue/server-catalog.mjs +115 -30
- package/src/session-runtime/mcp-glue.mjs +22 -2
- package/src/session-runtime/new-session-config.mjs +3 -2
- package/src/session-runtime/notification-bus.mjs +9 -2
- package/src/session-runtime/provider-auth/accounts.mjs +33 -15
- package/src/session-runtime/provider-models/web-search-catalog.mjs +5 -1
- package/src/session-runtime/provider-readiness.mjs +16 -10
- package/src/session-runtime/resource-extension-sync.mjs +20 -5
- package/src/session-runtime/resource-mcp-api.mjs +101 -77
- package/src/session-runtime/resource-plugins-api.mjs +29 -41
- package/src/session-runtime/resource-scope-decorate.mjs +6 -8
- package/src/session-runtime/resource-skills-api.mjs +23 -2
- package/src/session-runtime/schedule-session-run.mjs +1 -1
- package/src/session-runtime/services/channel-session-router.mjs +4 -1
- package/src/session-runtime/services/hook-bus/command-handler.mjs +4 -1
- package/src/session-runtime/services/hook-bus/handlers.mjs +7 -3
- package/src/session-runtime/services/provider-admin.mjs +64 -18
- package/src/session-runtime/services/usage-dashboard-model.mjs +3 -0
- package/src/session-runtime/setup-tool/executor.mjs +12 -1
- package/src/session-runtime/setup-tool/extended-actions.mjs +1 -0
- package/src/session-runtime/setup-tool/settings-contract.mjs +1 -0
- package/src/session-runtime/setup-tool/tool-defs.mjs +7 -1
- package/src/session-runtime/skills-api.mjs +7 -3
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
- package/src/session-runtime/webhook-session-run.mjs +16 -4
- package/src/skill-script-entry.mjs +36 -0
- package/src/standalone/daemon-stored-session-views.mjs +11 -3
- package/src/standalone/daemon.mjs +41 -4
- package/src/standalone/session-protocol.mjs +5 -0
- package/src/standalone/session-service/session-calls/session-action.mjs +6 -1
- package/src/tui/App.jsx +9 -1
- package/src/tui/app/app-view/floating-panel.jsx +9 -1
- package/src/tui/app/app-view.jsx +6 -0
- package/src/tui/app/extension-pickers/plugins-pickers.mjs +35 -16
- package/src/tui/app/model-options.mjs +2 -0
- package/src/tui/app/skill-mention-palette.mjs +88 -0
- package/src/tui/app/slash-palette.mjs +23 -7
- package/src/tui/app/transcript-row-estimate.mjs +11 -3
- package/src/tui/app/use-prompt-draft-flow.mjs +7 -2
- package/src/tui/app/use-prompt-state.mjs +5 -0
- package/src/tui/components/Message.jsx +22 -1
- package/src/tui/components/PromptInput.jsx +21 -3
- package/src/tui/components/SlashCommandPalette.jsx +12 -3
- package/src/tui/components/TranscriptItem.jsx +9 -1
- package/src/tui/components/prompt-input/key-handler.mjs +21 -8
- package/src/tui/components/user-message-skills.mjs +38 -0
- package/src/tui/dist/index.mjs +507 -171
- package/src/tui/session/queue-helpers.mjs +7 -2
- package/src/tui/session/session-api/extensions.mjs +4 -2
- package/src/tui/session/session-api/settings.mjs +7 -0
- package/src/tui/session/session-flow/drain.mjs +14 -4
- package/src/tui/session/tui-steering-persist.mjs +25 -9
- package/src/tui/session/turn.mjs +17 -0
- package/src/runtime/effort-judge/previous-human-request.mjs +0 -162
- package/src/runtime/effort-judge/verified-context-input.mjs +0 -10
|
@@ -45,7 +45,10 @@ async function scanSourceWindows(path, intervals, signal) {
|
|
|
45
45
|
let parts = [];
|
|
46
46
|
let partBytes = 0;
|
|
47
47
|
const lines = new Map();
|
|
48
|
-
const
|
|
48
|
+
const minChunkBytes = 64 * 1024;
|
|
49
|
+
const maxChunkBytes = 1024 * 1024;
|
|
50
|
+
let chunkBytes = minChunkBytes;
|
|
51
|
+
let buffer = Buffer.allocUnsafe(chunkBytes);
|
|
49
52
|
const deadline = Date.now() + READ_STREAM_TIMEOUT_MS;
|
|
50
53
|
const check = () => {
|
|
51
54
|
signal?.throwIfAborted();
|
|
@@ -70,7 +73,11 @@ async function scanSourceWindows(path, intervals, signal) {
|
|
|
70
73
|
};
|
|
71
74
|
while (interval < intervals.length) {
|
|
72
75
|
check();
|
|
73
|
-
|
|
76
|
+
if (buffer.length < chunkBytes) buffer = Buffer.allocUnsafe(chunkBytes);
|
|
77
|
+
// Consume every byte inside the budget, even when a seeking chunk would
|
|
78
|
+
// cross it. The one-byte EOF probe never becomes usable source text.
|
|
79
|
+
const readBytes = Math.min(chunkBytes, Math.max(1, READ_MAX_SCAN_BYTES - scanned));
|
|
80
|
+
const { bytesRead } = await handle.read(buffer, 0, readBytes, position);
|
|
74
81
|
check();
|
|
75
82
|
if (!bytesRead) {
|
|
76
83
|
if (partBytes) save(Buffer.alloc(0), true);
|
|
@@ -95,6 +102,12 @@ async function scanSourceWindows(path, intervals, signal) {
|
|
|
95
102
|
start = end + 1;
|
|
96
103
|
}
|
|
97
104
|
position += bytesRead;
|
|
105
|
+
// Deep windows still validate coordinates from current bytes. Amortize
|
|
106
|
+
// positional IO while skipping, then return to small reads in a window.
|
|
107
|
+
chunkBytes =
|
|
108
|
+
interval < intervals.length && line < intervals[interval].start
|
|
109
|
+
? Math.min(maxChunkBytes, chunkBytes * 2)
|
|
110
|
+
: minChunkBytes;
|
|
98
111
|
}
|
|
99
112
|
// Publication checks after its async stats, immediately before committing.
|
|
100
113
|
// An unpublished result still owes a final deadline/cancellation check.
|
|
@@ -254,8 +254,8 @@ function absolutePaths(lines, rgCwd) {
|
|
|
254
254
|
return lines.map((line) => (isAbsolute(line) ? line : resolveAgainstCwd(line, rgCwd)));
|
|
255
255
|
}
|
|
256
256
|
|
|
257
|
-
function missingGlobRoot(scan, root, rgCwd, err) {
|
|
258
|
-
const hint = buildNotFoundHint(scan.workDir, rgCwd, 'Search', err?.code);
|
|
257
|
+
async function missingGlobRoot(scan, root, rgCwd, err) {
|
|
258
|
+
const hint = await buildNotFoundHint(scan.workDir, rgCwd, 'Search', err?.code);
|
|
259
259
|
return {
|
|
260
260
|
error: `path does not exist: ${normalizeOutputPath(rgCwd)} (${err?.code || 'ENOENT'})${finalizeReadFamilyEnoentTail(hint, root, err?.code)}`,
|
|
261
261
|
paths: [],
|
|
@@ -422,14 +422,14 @@ function globMoreSuffix({ rgWindowIncomplete, remaining, totalBeforeOffset, next
|
|
|
422
422
|
return '';
|
|
423
423
|
}
|
|
424
424
|
|
|
425
|
-
function globEmptyDiagnostic(scan, { totalBeforeOffset }) {
|
|
425
|
+
async function globEmptyDiagnostic(scan, { totalBeforeOffset }) {
|
|
426
426
|
const { patterns, basePath, baseEntries, workDir, statCache, offset } = scan;
|
|
427
427
|
const patternStr = patterns.length === 1 ? JSON.stringify(patterns[0]) : JSON.stringify(patterns);
|
|
428
428
|
const baseLabel = normalizeOutputPath(basePath);
|
|
429
429
|
if (totalBeforeOffset > 0 && offset >= totalBeforeOffset) {
|
|
430
430
|
return `(no entries after offset=${offset}; total=${totalBeforeOffset}) pattern=${patternStr} path=${baseLabel}`;
|
|
431
431
|
}
|
|
432
|
-
const diagnostic = basePathDiagnostic(
|
|
432
|
+
const diagnostic = await basePathDiagnostic(
|
|
433
433
|
baseEntries.map((e) => e.root),
|
|
434
434
|
workDir,
|
|
435
435
|
statCache
|
|
@@ -473,7 +473,7 @@ async function scanGlobGroups(scan) {
|
|
|
473
473
|
const shown = await directAbsoluteMatches({ patterns, headLimit, offset });
|
|
474
474
|
if (shown.length > 0) return patternCapNote + shown.join('\n');
|
|
475
475
|
}
|
|
476
|
-
const out = patternCapNote + renderGlobPage(scan, merged, { capped, remaining, totalBeforeOffset, miss });
|
|
476
|
+
const out = patternCapNote + (await renderGlobPage(scan, merged, { capped, remaining, totalBeforeOffset, miss }));
|
|
477
477
|
settleGlobScanCache(scan, merged, out, remaining);
|
|
478
478
|
reportToolProgress(options, `found ${totalBeforeOffset} files`);
|
|
479
479
|
return out;
|
|
@@ -482,7 +482,7 @@ async function scanGlobGroups(scan) {
|
|
|
482
482
|
// The page body with its more/integrity suffixes. Empty partials are not
|
|
483
483
|
// proof of absence: diagnostics are preserved even when there is no path
|
|
484
484
|
// body, rather than silently dropping the integrity suffix.
|
|
485
|
-
function renderGlobPage(scan, merged, { capped, remaining, totalBeforeOffset, miss }) {
|
|
485
|
+
async function renderGlobPage(scan, merged, { capped, remaining, totalBeforeOffset, miss }) {
|
|
486
486
|
const { offset } = scan;
|
|
487
487
|
const errSuffix = globIntegritySuffix(merged);
|
|
488
488
|
const moreSuffix = globMoreSuffix({
|
|
@@ -492,7 +492,7 @@ function renderGlobPage(scan, merged, { capped, remaining, totalBeforeOffset, mi
|
|
|
492
492
|
nextOffset: offset + capped.length,
|
|
493
493
|
});
|
|
494
494
|
if (capped.length > 0) return `${capped.join('\n')}${moreSuffix}${errSuffix}`;
|
|
495
|
-
const emptyDiag = miss ? globEmptyDiagnostic(scan, { totalBeforeOffset }) : '';
|
|
495
|
+
const emptyDiag = miss ? await globEmptyDiagnostic(scan, { totalBeforeOffset }) : '';
|
|
496
496
|
const emptyBody = (emptyDiag || '(no files found)').replace(
|
|
497
497
|
'(no files found)',
|
|
498
498
|
merged.rgStdoutPartial || merged.rgWindowIncomplete ? '(no files found yet)' : '(no files found)'
|
|
@@ -608,9 +608,12 @@ export async function executeGlobTool(args, workDir, options = {}) {
|
|
|
608
608
|
};
|
|
609
609
|
return await runScopedSearchInFlight(
|
|
610
610
|
cacheKey,
|
|
611
|
-
({ signal: sharedSignal, scopedCacheOutcome }) =>
|
|
612
|
-
|
|
613
|
-
|
|
611
|
+
({ signal: sharedSignal, scopedCacheOutcome }) =>
|
|
612
|
+
scanGlobGroups({
|
|
613
|
+
...scan,
|
|
614
|
+
sharedSignal,
|
|
615
|
+
options: { ...options, scopedCacheOutcome },
|
|
616
|
+
}),
|
|
614
617
|
{ signal: options?.signal || options?.abortSignal || null, scopes },
|
|
615
618
|
options?.scopedCacheOutcome
|
|
616
619
|
);
|
|
@@ -211,7 +211,7 @@ async function runGrepSearch(request, sharedSignal) {
|
|
|
211
211
|
|
|
212
212
|
async function grepMissingPathResult({ workDir, grepResolvedPath, searchPath, executeChildBuiltinTool }, err) {
|
|
213
213
|
const msg = `Error: path does not exist: ${normalizeOutputPath(grepResolvedPath)} (${err?.code || 'ENOENT'})`;
|
|
214
|
-
let hint = buildNotFoundHintBody(workDir, grepResolvedPath, 'Search', err?.code, {});
|
|
214
|
+
let hint = await buildNotFoundHintBody(workDir, grepResolvedPath, 'Search', err?.code, {});
|
|
215
215
|
if (!hint) hint = await _suggestIndexedPaths(grepResolvedPath, executeChildBuiltinTool, workDir);
|
|
216
216
|
return msg + finalizeReadFamilyEnoentTail(appendNotFoundCwdNote(hint, workDir, err?.code), searchPath, err?.code);
|
|
217
217
|
}
|
|
@@ -65,10 +65,10 @@ const ENOENT_ABSENT =
|
|
|
65
65
|
|
|
66
66
|
// Share diagnostic lookup results within one invocation without changing
|
|
67
67
|
// the requested operand or executing a replacement operation.
|
|
68
|
-
function cachedFileByBasename(workDir, missingPath, cache) {
|
|
68
|
+
async function cachedFileByBasename(workDir, missingPath, cache) {
|
|
69
69
|
if (!cache) return findFileByBasename(workDir, missingPath);
|
|
70
70
|
if (!('fileHits' in cache)) cache.fileHits = findFileByBasename(workDir, missingPath);
|
|
71
|
-
return cache.fileHits;
|
|
71
|
+
return await cache.fileHits;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
// A missing ABSOLUTE path that resolves outside the project cannot be
|
|
@@ -180,15 +180,15 @@ export function appendNotFoundCwdNote(hint, workDir, errCode = 'ENOENT') {
|
|
|
180
180
|
return `${hint} (relative paths resolve from ${normalizeOutputPath(workDir)})`;
|
|
181
181
|
}
|
|
182
182
|
|
|
183
|
-
export function buildNotFoundHint(workDir, missingPath, actionVerb, errCode = 'ENOENT', cache = null) {
|
|
183
|
+
export async function buildNotFoundHint(workDir, missingPath, actionVerb, errCode = 'ENOENT', cache = null) {
|
|
184
184
|
return appendNotFoundCwdNote(
|
|
185
|
-
buildNotFoundHintBody(workDir, missingPath, actionVerb, errCode, cache),
|
|
185
|
+
await buildNotFoundHintBody(workDir, missingPath, actionVerb, errCode, cache),
|
|
186
186
|
workDir,
|
|
187
187
|
errCode
|
|
188
188
|
);
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
-
export function buildNotFoundHintBody(workDir, missingPath, actionVerb, errCode = 'ENOENT', cache = null) {
|
|
191
|
+
export async function buildNotFoundHintBody(workDir, missingPath, actionVerb, errCode = 'ENOENT', cache = null) {
|
|
192
192
|
if (!NOT_FOUND_CODES.has(String(errCode || 'ENOENT'))) return '';
|
|
193
193
|
// `C:tmpsmp` shape: a Windows path whose separators were eaten by JSON
|
|
194
194
|
// escaping (`"C:\\tmp\\smp"` written as `"C:\tmp\smp"`). Name the cause —
|
|
@@ -200,12 +200,12 @@ export function buildNotFoundHintBody(workDir, missingPath, actionVerb, errCode
|
|
|
200
200
|
if (missingPathIsOutsideProject(workDir, missingPath)) {
|
|
201
201
|
return outsideProjectNotFoundHint(missingPath, actionVerb);
|
|
202
202
|
}
|
|
203
|
-
const elsewhere = cachedFileByBasename(workDir, missingPath, cache);
|
|
203
|
+
const elsewhere = await cachedFileByBasename(workDir, missingPath, cache);
|
|
204
204
|
if (elsewhere.length) {
|
|
205
205
|
return ` Not found at this path; the same filename exists at: ${elsewhere.map((p) => `"${normalizeOutputPath(p)}"`).join(', ')}. ${actionVerb} that path directly.`;
|
|
206
206
|
}
|
|
207
207
|
if (isDirectoryPathGuess(missingPath)) {
|
|
208
|
-
const dirHits = findDirectoryByBasename(workDir, missingPath, { limit: 5 });
|
|
208
|
+
const dirHits = await findDirectoryByBasename(workDir, missingPath, { limit: 5 });
|
|
209
209
|
if (dirHits.length > 1) {
|
|
210
210
|
return ` Not found at this path; same-named directories exist at: ${dirHits
|
|
211
211
|
.slice(0, 5)
|
|
@@ -268,9 +268,9 @@ export function uncRefusalMessage(toolName, original, resolved) {
|
|
|
268
268
|
return `Error: ${toolName} refuses UNC/SMB path ${JSON.stringify(shown)}; remote share access is blocked to prevent NTLM credential leaks`;
|
|
269
269
|
}
|
|
270
270
|
|
|
271
|
-
export function basePathDiagnostic(basePaths, workDir, statCache = null) {
|
|
272
|
-
|
|
273
|
-
.map((basePath) => {
|
|
271
|
+
export async function basePathDiagnostic(basePaths, workDir, statCache = null) {
|
|
272
|
+
const parts = await Promise.all(
|
|
273
|
+
basePaths.map(async (basePath) => {
|
|
274
274
|
const resolved = resolveSearchScope(basePath, workDir);
|
|
275
275
|
// Reuse the caller's call-scoped stat cache (glob preflight + per-group
|
|
276
276
|
// rg runs already stat'd this same resolved root) instead of re-stating.
|
|
@@ -291,8 +291,13 @@ export function basePathDiagnostic(basePaths, workDir, statCache = null) {
|
|
|
291
291
|
}
|
|
292
292
|
return (
|
|
293
293
|
`${normalizeOutputPath(basePath)}: path does not exist (${err?.code || 'ENOENT'})` +
|
|
294
|
-
finalizeReadFamilyEnoentTail(
|
|
294
|
+
finalizeReadFamilyEnoentTail(
|
|
295
|
+
await buildNotFoundHint(workDir, resolved, 'Search', err?.code),
|
|
296
|
+
basePath,
|
|
297
|
+
err?.code
|
|
298
|
+
)
|
|
295
299
|
);
|
|
296
300
|
})
|
|
297
|
-
|
|
301
|
+
);
|
|
302
|
+
return parts.join('; ');
|
|
298
303
|
}
|
|
@@ -79,10 +79,10 @@ export function resolveAggregateAnchorRoot(name, args, baseCwd, { explicitCwdArg
|
|
|
79
79
|
* One `file` anchor: an error string when it does not exist, otherwise the
|
|
80
80
|
* root it re-homes the call to (null keeps the current cwd).
|
|
81
81
|
*/
|
|
82
|
-
export function resolveFileAnchorRoot(name, args, fileArg, baseCwd) {
|
|
82
|
+
export async function resolveFileAnchorRoot(name, args, fileArg, baseCwd) {
|
|
83
83
|
const abs = _absFrom(baseCwd, fileArg);
|
|
84
84
|
if (!existsSync(abs)) {
|
|
85
|
-
const elsewhere = findFileByBasename(pathResolve(baseCwd), abs);
|
|
85
|
+
const elsewhere = await findFileByBasename(pathResolve(baseCwd), abs);
|
|
86
86
|
const hint = elsewhere.length
|
|
87
87
|
? ` Same filename exists at: ${elsewhere.map((p) => `"${toDisplayPath(p, baseCwd).replace(/\\/g, '/')}"`).join(', ')}. Use that path.`
|
|
88
88
|
: '';
|
|
@@ -345,7 +345,7 @@ async function executeCodeGraphToolRaw(name, rawArgs, cwd, signal = null, option
|
|
|
345
345
|
args = resolved.args;
|
|
346
346
|
}
|
|
347
347
|
if (fileArg && !hasAggregateFileArgs) {
|
|
348
|
-
const anchor = resolveFileAnchorRoot(name, args, fileArg, baseCwd);
|
|
348
|
+
const anchor = await resolveFileAnchorRoot(name, args, fileArg, baseCwd);
|
|
349
349
|
if (anchor.error) return anchor.error;
|
|
350
350
|
if (anchor.root) effectiveCwd = anchor.root;
|
|
351
351
|
}
|
|
@@ -47,7 +47,7 @@ export async function prepareCodexBatch({ patchStr, requestedFormat, basePath, p
|
|
|
47
47
|
let v4aRenamePlan = null;
|
|
48
48
|
if (isV4APatchInput(patchStr, requestedFormat)) {
|
|
49
49
|
try {
|
|
50
|
-
const parsedSections = preParsedV4ASections || rewriteV4AReadRedirects(parseV4APatch(patchStr), basePath);
|
|
50
|
+
const parsedSections = preParsedV4ASections || (await rewriteV4AReadRedirects(parseV4APatch(patchStr), basePath));
|
|
51
51
|
const allSections = coalesceCompatibleV4ASections(parsedSections, basePath);
|
|
52
52
|
v4aRenamePlan = await planV4ARenameSections(allSections, basePath);
|
|
53
53
|
inputPatchStr = await convertV4ASectionsToUnifiedPatch(v4aRenamePlan.remainingSections, basePath, v4aConvertOpts);
|
|
@@ -56,7 +56,7 @@ export async function prepareCodexBatch({ patchStr, requestedFormat, basePath, p
|
|
|
56
56
|
}
|
|
57
57
|
} else if (requestedFormat !== 'unified' && hasUnifiedBareV4AHunk(patchStr)) {
|
|
58
58
|
try {
|
|
59
|
-
const sections = rewriteV4AReadRedirects(parseUnifiedBareV4APatch(patchStr), basePath);
|
|
59
|
+
const sections = await rewriteV4AReadRedirects(parseUnifiedBareV4APatch(patchStr), basePath);
|
|
60
60
|
inputPatchStr = await convertV4ASectionsToUnifiedPatch(sections, basePath, v4aConvertOpts);
|
|
61
61
|
} catch (err) {
|
|
62
62
|
throw new Error(`apply_patch: bare @@ parse failed — ${err?.message || String(err)}`);
|
|
@@ -82,7 +82,7 @@ export async function prepareCodexBatch({ patchStr, requestedFormat, basePath, p
|
|
|
82
82
|
);
|
|
83
83
|
}
|
|
84
84
|
try {
|
|
85
|
-
const sections = rewriteV4AReadRedirects(parseUnifiedCountedAsV4APatch(patchStr), basePath);
|
|
85
|
+
const sections = await rewriteV4AReadRedirects(parseUnifiedCountedAsV4APatch(patchStr), basePath);
|
|
86
86
|
inputPatchStr = await convertV4ASectionsToUnifiedPatch(sections, basePath, v4aConvertOpts);
|
|
87
87
|
parsed = parsePatch(prepareInput(inputPatchStr));
|
|
88
88
|
} catch (fallbackErr) {
|
|
@@ -91,7 +91,7 @@ export async function prepareCodexBatch({ patchStr, requestedFormat, basePath, p
|
|
|
91
91
|
);
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
|
-
parsed = rewriteParsedReadRedirects(parsed, basePath);
|
|
94
|
+
parsed = await rewriteParsedReadRedirects(parsed, basePath);
|
|
95
95
|
if (!Array.isArray(parsed) || parsed.length === 0) {
|
|
96
96
|
return { error: 'Error: patch contained no file sections' };
|
|
97
97
|
}
|
|
@@ -7,11 +7,11 @@ import { pathKey, resolveV4AEntryPath } from '../paths.mjs';
|
|
|
7
7
|
import { rewriteV4AReadRedirects } from '../read-redirects.mjs';
|
|
8
8
|
import { isV4ARenameSection } from '../v4a-convert.mjs';
|
|
9
9
|
|
|
10
|
-
export function selectApplyPatchRoute({ args, patchStr, requestedFormat, basePath }) {
|
|
10
|
+
export async function selectApplyPatchRoute({ args, patchStr, requestedFormat, basePath }) {
|
|
11
11
|
let preParsedV4ASections = null;
|
|
12
12
|
if (isV4APatchInput(patchStr, requestedFormat)) {
|
|
13
13
|
try {
|
|
14
|
-
preParsedV4ASections = rewriteV4AReadRedirects(parseV4APatch(patchStr), basePath);
|
|
14
|
+
preParsedV4ASections = await rewriteV4AReadRedirects(parseV4APatch(patchStr), basePath);
|
|
15
15
|
} catch {
|
|
16
16
|
// The selected execution path reports the authoritative parse error.
|
|
17
17
|
}
|
|
@@ -34,7 +34,7 @@ async function apply_patch(rawArgs, cwd, options = {}) {
|
|
|
34
34
|
}
|
|
35
35
|
const rejectedV4AHunks = [];
|
|
36
36
|
const v4aConvertOpts = { rejectPartial, rejectedHunks: rejectedV4AHunks, fuzzy, dryRun, readStateScope };
|
|
37
|
-
const route = selectApplyPatchRoute({ args, patchStr, requestedFormat, basePath });
|
|
37
|
+
const route = await selectApplyPatchRoute({ args, patchStr, requestedFormat, basePath });
|
|
38
38
|
if (route.useSequence) {
|
|
39
39
|
const seqOut = await applyPatchSequence(patchStr, requestedFormat, basePath, {
|
|
40
40
|
v4aConvertOpts,
|
|
@@ -6,7 +6,7 @@ import { resolve as pathResolve, relative as pathRelative, isAbsolute } from 'no
|
|
|
6
6
|
import { findBySuffixStrip, findFileByBasename } from '../builtin/path-diagnostics.mjs';
|
|
7
7
|
import { resolveEntryPath, resolveV4AEntryPath, classifyEntry, pathKey } from './paths.mjs';
|
|
8
8
|
|
|
9
|
-
function uniqueExistingPatchTarget(basePath, requestedFullPath) {
|
|
9
|
+
async function uniqueExistingPatchTarget(basePath, requestedFullPath) {
|
|
10
10
|
// Auto-relocation is only valid for a missing target lexically inside the
|
|
11
11
|
// patch root. An explicit outside-root path must never be pulled back into
|
|
12
12
|
// the project merely because a basename happens to match.
|
|
@@ -23,14 +23,14 @@ function uniqueExistingPatchTarget(basePath, requestedFullPath) {
|
|
|
23
23
|
};
|
|
24
24
|
const suffix = asFile(findBySuffixStrip(basePath, requestedFullPath));
|
|
25
25
|
if (suffix) return suffix;
|
|
26
|
-
const basenameHits = findFileByBasename(basePath, requestedFullPath, { limit: 2 });
|
|
26
|
+
const basenameHits = await findFileByBasename(basePath, requestedFullPath, { limit: 2 });
|
|
27
27
|
return basenameHits.length === 1 ? asFile(basenameHits[0]) : null;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
function redirectedPatchPath(requestedFullPath, basePath) {
|
|
30
|
+
async function redirectedPatchPath(requestedFullPath, basePath) {
|
|
31
31
|
// An existing requested path always wins over relocation.
|
|
32
32
|
if (!requestedFullPath || existsSync(requestedFullPath)) return requestedFullPath;
|
|
33
|
-
return uniqueExistingPatchTarget(basePath, requestedFullPath) || requestedFullPath;
|
|
33
|
+
return (await uniqueExistingPatchTarget(basePath, requestedFullPath)) || requestedFullPath;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
export function patchHeaderPathForResolved(basePath, fullPath) {
|
|
@@ -41,33 +41,37 @@ export function patchHeaderPathForResolved(basePath, fullPath) {
|
|
|
41
41
|
return fullPath;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
export function rewriteV4AReadRedirects(sections, basePath) {
|
|
45
|
-
return
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
44
|
+
export async function rewriteV4AReadRedirects(sections, basePath) {
|
|
45
|
+
return Promise.all(
|
|
46
|
+
(sections || []).map(async (section) => {
|
|
47
|
+
if (!section || section.kind === 'add' || !section.path) return section;
|
|
48
|
+
const requested = resolveV4AEntryPath(basePath, section.path);
|
|
49
|
+
const redirected = await redirectedPatchPath(requested, basePath);
|
|
50
|
+
if (pathKey(redirected) === pathKey(requested)) return section;
|
|
51
|
+
return { ...section, path: patchHeaderPathForResolved(basePath, redirected) };
|
|
52
|
+
})
|
|
53
|
+
);
|
|
52
54
|
}
|
|
53
55
|
|
|
54
|
-
export function rewriteParsedReadRedirects(parsed, basePath) {
|
|
55
|
-
return
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
56
|
+
export async function rewriteParsedReadRedirects(parsed, basePath) {
|
|
57
|
+
return Promise.all(
|
|
58
|
+
(parsed || []).map(async (entry) => {
|
|
59
|
+
const kind = classifyEntry(entry);
|
|
60
|
+
if (kind === 'create' || !entry?.oldFileName) return entry;
|
|
61
|
+
const requested = resolveEntryPath(basePath, entry.oldFileName);
|
|
62
|
+
const redirected = await redirectedPatchPath(requested, basePath);
|
|
63
|
+
if (pathKey(redirected) === pathKey(requested)) return entry;
|
|
64
|
+
const rewritten = {
|
|
65
|
+
...entry,
|
|
66
|
+
oldFileName: patchHeaderPathForResolved(basePath, redirected),
|
|
67
|
+
};
|
|
68
|
+
if (kind === 'modify' && entry.newFileName) {
|
|
69
|
+
const newRequested = resolveEntryPath(basePath, entry.newFileName);
|
|
70
|
+
if (pathKey(newRequested) === pathKey(requested)) {
|
|
71
|
+
rewritten.newFileName = rewritten.oldFileName;
|
|
72
|
+
}
|
|
69
73
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
74
|
+
return rewritten;
|
|
75
|
+
})
|
|
76
|
+
);
|
|
73
77
|
}
|
|
@@ -84,10 +84,10 @@ function parsedEntryUnit(entry, basePath) {
|
|
|
84
84
|
// Parse the patch body into V4A-style sections (V4A envelope, bare-@@ hunks,
|
|
85
85
|
// or counted-unified salvaged as V4A), or into parsed unified entries for a
|
|
86
86
|
// plain unified diff.
|
|
87
|
-
function parsePatchSections(patchStr, requestedFormat, basePath, { coalesceByFile }) {
|
|
87
|
+
async function parsePatchSections(patchStr, requestedFormat, basePath, { coalesceByFile }) {
|
|
88
88
|
if (isV4APatchInput(patchStr, requestedFormat)) {
|
|
89
89
|
try {
|
|
90
|
-
const parsedSections = rewriteV4AReadRedirects(parseV4APatch(patchStr), basePath);
|
|
90
|
+
const parsedSections = await rewriteV4AReadRedirects(parseV4APatch(patchStr), basePath);
|
|
91
91
|
return { sections: coalesceByFile ? coalesceCompatibleV4ASections(parsedSections, basePath) : parsedSections };
|
|
92
92
|
} catch (err) {
|
|
93
93
|
throw new Error(`apply_patch: V4A parse failed — ${err?.message || String(err)}`);
|
|
@@ -98,7 +98,7 @@ function parsePatchSections(patchStr, requestedFormat, basePath, { coalesceByFil
|
|
|
98
98
|
// section's conversion into its own unit (ordered-stop preserved) rather
|
|
99
99
|
// than converting the whole patch up front.
|
|
100
100
|
try {
|
|
101
|
-
return { sections: rewriteV4AReadRedirects(parseUnifiedBareV4APatch(patchStr), basePath) };
|
|
101
|
+
return { sections: await rewriteV4AReadRedirects(parseUnifiedBareV4APatch(patchStr), basePath) };
|
|
102
102
|
} catch (err) {
|
|
103
103
|
throw new Error(`apply_patch: bare @@ parse failed — ${err?.message || String(err)}`);
|
|
104
104
|
}
|
|
@@ -116,18 +116,18 @@ function parsePatchSections(patchStr, requestedFormat, basePath, { coalesceByFil
|
|
|
116
116
|
// V4A-style sections and defer per-section conversion — same ordered-stop
|
|
117
117
|
// guarantee as the V4A path (no whole-patch up-front convert).
|
|
118
118
|
try {
|
|
119
|
-
return { sections: rewriteV4AReadRedirects(parseUnifiedCountedAsV4APatch(patchStr), basePath) };
|
|
119
|
+
return { sections: await rewriteV4AReadRedirects(parseUnifiedCountedAsV4APatch(patchStr), basePath) };
|
|
120
120
|
} catch (fallbackErr) {
|
|
121
121
|
throw new Error(
|
|
122
122
|
`apply_patch: parse failed — ${err?.message || String(err)}; V4A fallback failed — ${fallbackErr?.message || String(fallbackErr)}`
|
|
123
123
|
);
|
|
124
124
|
}
|
|
125
125
|
}
|
|
126
|
-
return { parsed: rewriteParsedReadRedirects(parsed, basePath) };
|
|
126
|
+
return { parsed: await rewriteParsedReadRedirects(parsed, basePath) };
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
-
export function buildPatchUnits(patchStr, requestedFormat, basePath, ctx) {
|
|
130
|
-
const { sections, parsed } = parsePatchSections(patchStr, requestedFormat, basePath, ctx);
|
|
129
|
+
export async function buildPatchUnits(patchStr, requestedFormat, basePath, ctx) {
|
|
130
|
+
const { sections, parsed } = await parsePatchSections(patchStr, requestedFormat, basePath, ctx);
|
|
131
131
|
if (sections) return sections.map((section) => sectionUnit(section, basePath, ctx));
|
|
132
132
|
return (parsed || []).map((entry) => parsedEntryUnit(entry, basePath));
|
|
133
133
|
}
|
|
@@ -30,7 +30,7 @@ export async function applyPatchSequence(patchStr, requestedFormat, basePath, ct
|
|
|
30
30
|
coalesceByFile = false,
|
|
31
31
|
} = ctx;
|
|
32
32
|
|
|
33
|
-
const units = buildPatchUnits(patchStr, requestedFormat, basePath, {
|
|
33
|
+
const units = await buildPatchUnits(patchStr, requestedFormat, basePath, {
|
|
34
34
|
v4aConvertOpts,
|
|
35
35
|
dryRun,
|
|
36
36
|
readStateScope,
|
|
@@ -18,6 +18,7 @@ import { randomUUID } from 'node:crypto';
|
|
|
18
18
|
import { getPluginData } from '../config.mjs';
|
|
19
19
|
import { scrubLoaderVars, scrubProviderSecrets, scrubRuntimeRootVars } from './env-scrub.mjs';
|
|
20
20
|
import { spawnShellWithRetry } from './lib/shell-spawn-retry.mjs';
|
|
21
|
+
import { ensureSkillLauncherDir } from '../../../shared/skill-script-runtime.mjs';
|
|
21
22
|
|
|
22
23
|
const SNAPSHOT_TIMEOUT_MS = 10_000;
|
|
23
24
|
|
|
@@ -146,6 +147,9 @@ echo "# Shell options" >> "$SNAPSHOT_FILE"
|
|
|
146
147
|
${optDump}
|
|
147
148
|
echo "# Aliases" >> "$SNAPSHOT_FILE"
|
|
148
149
|
${aliasDump}
|
|
150
|
+
# The sourced PATH replaces the model shell's own, so it carries the
|
|
151
|
+
# skill-launcher entry buildShellSpawnEnv prepends (mixdog-skill-node).
|
|
152
|
+
PATH=${_shellQuote(ensureSkillLauncherDir())}:"$PATH"
|
|
149
153
|
# PATH may contain $, backticks, or quotes that would re-expand if we
|
|
150
154
|
# emitted it inside double quotes. Emit a shell-safe single-quoted PATH
|
|
151
155
|
# export line via printf %q-style escaping inside the dump shell.
|
|
@@ -97,7 +97,7 @@ export function createOwnedStarter({
|
|
|
97
97
|
state.automationRunning = true;
|
|
98
98
|
}
|
|
99
99
|
// DEGRADED MODE: a messaging connect failure — packaged runtime without
|
|
100
|
-
//
|
|
100
|
+
// the provider library, bad token, gateway outage — must not take schedules/webhooks
|
|
101
101
|
// down with it. Sends stay dead (connected=false) but session runs, the
|
|
102
102
|
// webhook server and the relay tunnel keep working.
|
|
103
103
|
async function degradeToAutomation() {
|
|
@@ -27,6 +27,14 @@ ${payload}
|
|
|
27
27
|
<<<${_UNTRUSTED}_END>>>`;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
/** The run's model-visible prompt (endpoint instructions + fenced external
|
|
31
|
+
* payload) and its trusted skill-selection input: the endpoint-authored
|
|
32
|
+
* instructions alone, so nothing in the payload or headers selects a skill. */
|
|
33
|
+
function webhookRunPrompt(instructions, body, headers) {
|
|
34
|
+
const trusted = String(instructions ?? '');
|
|
35
|
+
return { prompt: `${trusted}\n\n${buildFencedPayload(body, headers)}`, skillSelection: trusted };
|
|
36
|
+
}
|
|
37
|
+
|
|
30
38
|
function trackDispatch({ name, deliveryId, dispatchP, controller }) {
|
|
31
39
|
let settled = false;
|
|
32
40
|
const timeoutHandle = setTimeout(
|
|
@@ -89,6 +97,10 @@ function createWebhookSessionDispatcher({ getConfig, getBridgeDispatch }) {
|
|
|
89
97
|
workflow: extra.workflow || null,
|
|
90
98
|
attachments: extra.attachments || null,
|
|
91
99
|
delivery: extra.delivery || null,
|
|
100
|
+
// Trusted skill-selection input: only the endpoint-authored
|
|
101
|
+
// instructions, never the fenced external body/headers that share
|
|
102
|
+
// the model-visible prompt.
|
|
103
|
+
skillSelection: String(extra.skillSelection ?? ''),
|
|
92
104
|
context: {
|
|
93
105
|
source: 'webhook',
|
|
94
106
|
endpoint: name,
|
|
@@ -105,14 +117,14 @@ function createWebhookSessionDispatcher({ getConfig, getBridgeDispatch }) {
|
|
|
105
117
|
async function dispatchEndpoint({ name, body, headers, res, deliveryId, endpoint }) {
|
|
106
118
|
try {
|
|
107
119
|
const { model, instructions, cwd, workflow, attachments, delivery } = endpoint;
|
|
108
|
-
const
|
|
120
|
+
const run = webhookRunPrompt(instructions, body, headers);
|
|
109
121
|
if (!getBridgeDispatch()) throw new Error(`[webhook] session dispatch requires bridgeDispatch`);
|
|
110
|
-
|
|
111
|
-
await dispatchSessionRun(name, model || null, fullPrompt, headers, deliveryId, res, {
|
|
122
|
+
await dispatchSessionRun(name, model || null, run.prompt, headers, deliveryId, res, {
|
|
112
123
|
cwd: cwd || null,
|
|
113
124
|
workflow: workflow || null,
|
|
114
125
|
attachments: attachments || null,
|
|
115
126
|
delivery: delivery || null,
|
|
127
|
+
skillSelection: run.skillSelection,
|
|
116
128
|
});
|
|
117
129
|
return true;
|
|
118
130
|
} catch (err) {
|
|
@@ -125,4 +137,4 @@ function createWebhookSessionDispatcher({ getConfig, getBridgeDispatch }) {
|
|
|
125
137
|
return { dispatchEndpoint };
|
|
126
138
|
}
|
|
127
139
|
|
|
128
|
-
export { buildFencedPayload, createWebhookSessionDispatcher };
|
|
140
|
+
export { buildFencedPayload, createWebhookSessionDispatcher, webhookRunPrompt };
|
|
@@ -218,20 +218,23 @@ function wireWebhookHandlers() {
|
|
|
218
218
|
webhookServer.setEventPipeline(eventPipeline);
|
|
219
219
|
// Webhook fires run as sessions (schedules parity); the Automations
|
|
220
220
|
// session row is the only surface (channel relay retired).
|
|
221
|
-
webhookServer.setBridgeDispatch(
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
221
|
+
webhookServer.setBridgeDispatch(
|
|
222
|
+
async ({ prompt, skillSelection, model, cwd, workflow, attachments, context, signal }) => {
|
|
223
|
+
const { runWebhookSession } = await import('../../../session-runtime/webhook-session-run.mjs');
|
|
224
|
+
const run = await runWebhookSession({
|
|
225
|
+
name: context?.endpoint || 'webhook',
|
|
226
|
+
model: model || null,
|
|
227
|
+
cwd: cwd || null,
|
|
228
|
+
workflow: workflow || null,
|
|
229
|
+
attachments: attachments || null,
|
|
230
|
+
// Dispatch-timeout cancellation only works if the signal reaches the run.
|
|
231
|
+
signal: signal || null,
|
|
232
|
+
prompt,
|
|
233
|
+
skillSelection,
|
|
234
|
+
});
|
|
235
|
+
return run;
|
|
236
|
+
}
|
|
237
|
+
);
|
|
235
238
|
}
|
|
236
239
|
function wireEventQueueHandlers(eventQueue) {
|
|
237
240
|
if (!eventQueue) return;
|
|
@@ -17,8 +17,6 @@ export const INPUT_GROUP_SECURITY_NOTE =
|
|
|
17
17
|
export const GNOME_EXTENSION_UUID = 'mixdog-windows@mixdog.io';
|
|
18
18
|
/** The oldest helper interface this app can use (2 added Screenshot and StopRequested, 3 the in-shell indicator). */
|
|
19
19
|
export const MIN_WINDOW_HELPER_VERSION = 3;
|
|
20
|
-
export const WINDOW_CONTROL_HINT =
|
|
21
|
-
'wayland_window_control_unavailable: this compositor offers no window control to other programs; on GNOME the Mixdog Windows extension (mixdog-windows@mixdog.io) provides it and must be enabled and loaded';
|
|
22
20
|
export const WINDOW_HELPER_RELOGIN_HINT =
|
|
23
21
|
'wayland_window_control_unavailable: the Mixdog Windows GNOME extension is installed and enabled but GNOME Shell has not loaded it yet; the user must sign out and sign in again once';
|
|
24
22
|
export const WINDOW_HELPER_ENABLE_HINT =
|