@dungle-scrubs/tallow 0.8.7 → 0.8.8
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 +1 -1
- package/dist/cli.js +244 -54
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/sdk.d.ts +39 -0
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +322 -13
- package/dist/sdk.js.map +1 -1
- package/dist/session-utils.d.ts +8 -0
- package/dist/session-utils.d.ts.map +1 -1
- package/dist/session-utils.js +38 -1
- package/dist/session-utils.js.map +1 -1
- package/extensions/__integration__/plan-rejection-feedback.test.ts +272 -0
- package/extensions/__integration__/worktree.test.ts +88 -0
- package/extensions/_icons/index.ts +2 -3
- package/extensions/_shared/inline-preview.ts +2 -4
- package/extensions/_shared/interop-events.ts +48 -0
- package/extensions/_shared/shell-policy.ts +2 -1
- package/extensions/_shared/tallow-paths.ts +48 -0
- package/extensions/agent-commands-tool/__tests__/parsing.test.ts +40 -1
- package/extensions/agent-commands-tool/index.ts +38 -6
- package/extensions/background-task-tool/index.ts +2 -2
- package/extensions/bash-tool-enhanced/index.ts +3 -4
- package/extensions/cd-tool/index.ts +3 -3
- package/extensions/claude-bridge/index.ts +2 -1
- package/extensions/command-prompt/__tests__/plugin-sources.test.ts +49 -0
- package/extensions/command-prompt/index.ts +36 -0
- package/extensions/context-files/index.ts +2 -1
- package/extensions/context-fork/index.ts +2 -1
- package/extensions/context-usage/__tests__/tool-result-memory.test.ts +62 -0
- package/extensions/context-usage/index.ts +169 -8
- package/extensions/debug/__tests__/analysis.test.ts +35 -2
- package/extensions/debug/__tests__/diagnostics-commands.test.ts +11 -2
- package/extensions/debug/analysis.ts +53 -16
- package/extensions/debug/index.ts +84 -10
- package/extensions/debug/logger.ts +2 -2
- package/extensions/health/index.ts +2 -2
- package/extensions/hooks/__tests__/claude-compat.test.ts +31 -0
- package/extensions/hooks/extension.json +3 -1
- package/extensions/hooks/hooks.schema.json +17 -1
- package/extensions/hooks/index.ts +52 -7
- package/extensions/lsp/index.ts +2 -7
- package/extensions/output-styles-tool/index.ts +2 -4
- package/extensions/plan-mode-tool/extension.json +1 -0
- package/extensions/plan-mode-tool/index.ts +119 -4
- package/extensions/prompt-suggestions/index.ts +2 -3
- package/extensions/random-spinner/index.ts +2 -3
- package/extensions/read-tool-enhanced/__tests__/notebook-read.test.ts +100 -0
- package/extensions/read-tool-enhanced/__tests__/notebook.test.ts +136 -0
- package/extensions/read-tool-enhanced/extension.json +4 -4
- package/extensions/read-tool-enhanced/index.ts +112 -10
- package/extensions/read-tool-enhanced/notebook.ts +526 -0
- package/extensions/rewind/__tests__/snapshots.test.ts +43 -1
- package/extensions/rewind/snapshots.ts +18 -6
- package/extensions/session-memory/index.ts +3 -2
- package/extensions/stats/stats-log.ts +2 -3
- package/extensions/subagent-tool/__tests__/discovery-defaults.test.ts +23 -0
- package/extensions/subagent-tool/__tests__/isolation-frontmatter.test.ts +100 -0
- package/extensions/subagent-tool/__tests__/model-router.test.ts +8 -0
- package/extensions/subagent-tool/agents.ts +77 -16
- package/extensions/subagent-tool/index.ts +213 -48
- package/extensions/subagent-tool/model-router.ts +3 -3
- package/extensions/subagent-tool/process.ts +233 -22
- package/extensions/subagent-tool/schema.ts +11 -0
- package/extensions/subagent-tool/widget.ts +15 -2
- package/extensions/tasks/__tests__/widget-subagents.test.ts +28 -7
- package/extensions/tasks/commands/register-tasks-extension.ts +15 -33
- package/extensions/tasks/state/index.ts +2 -2
- package/extensions/theme-selector/index.ts +3 -7
- package/extensions/worktree/__tests__/lifecycle.test.ts +115 -0
- package/extensions/worktree/extension.json +31 -0
- package/extensions/worktree/index.ts +149 -0
- package/extensions/worktree/lifecycle.ts +372 -0
- package/package.json +1 -1
- package/skills/tallow-expert/SKILL.md +1 -1
|
@@ -54,7 +54,7 @@ import {
|
|
|
54
54
|
setPiRef,
|
|
55
55
|
spawnBackgroundSubagent,
|
|
56
56
|
} from "./process.js";
|
|
57
|
-
import type { SubagentCompleteDetails } from "./schema.js";
|
|
57
|
+
import type { IsolationMode, SubagentCompleteDetails } from "./schema.js";
|
|
58
58
|
import { SubagentParams } from "./schema.js";
|
|
59
59
|
import {
|
|
60
60
|
backgroundSubagents,
|
|
@@ -173,6 +173,11 @@ export default function (pi: ExtensionAPI) {
|
|
|
173
173
|
label: "subagent",
|
|
174
174
|
description: `Delegate tasks to specialized subagents with isolated context. Modes: single (agent + task), parallel (tasks array), centipede (sequential with {previous} placeholder). Default agent scope is "user" (from ~/.tallow/agents). To include project-local agents, set agentScope: "both". Missing agent names recover gracefully via best-match or ephemeral fallback.
|
|
175
175
|
|
|
176
|
+
ISOLATION:
|
|
177
|
+
- isolation: "worktree" runs a subagent in a detached temporary git worktree
|
|
178
|
+
- precedence: per-call param > agent frontmatter > _defaults.md frontmatter
|
|
179
|
+
- in parallel/centipede mode, isolation can be set per task item
|
|
180
|
+
|
|
176
181
|
MODEL SELECTION:
|
|
177
182
|
- model: explicit model name (fuzzy matched, e.g. "opus", "haiku", "gemini flash")
|
|
178
183
|
- No model specified: auto-routes based on task type and complexity
|
|
@@ -246,7 +251,22 @@ WHEN NOT TO USE SUBAGENTS:
|
|
|
246
251
|
}
|
|
247
252
|
|
|
248
253
|
const agentScope: AgentScope = params.agentScope ?? "user";
|
|
249
|
-
|
|
254
|
+
let discovery: ReturnType<typeof discoverAgents>;
|
|
255
|
+
try {
|
|
256
|
+
discovery = discoverAgents(ctx.cwd, agentScope);
|
|
257
|
+
} catch (error) {
|
|
258
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
259
|
+
return {
|
|
260
|
+
content: [{ type: "text", text: `Invalid agent frontmatter: ${reason}` }],
|
|
261
|
+
details: {
|
|
262
|
+
mode: "single" as const,
|
|
263
|
+
agentScope,
|
|
264
|
+
projectAgentsDir: null,
|
|
265
|
+
results: [],
|
|
266
|
+
},
|
|
267
|
+
isError: true,
|
|
268
|
+
};
|
|
269
|
+
}
|
|
250
270
|
const agents = discovery.agents;
|
|
251
271
|
const defaults = discovery.defaults;
|
|
252
272
|
|
|
@@ -376,12 +396,15 @@ WHEN NOT TO USE SUBAGENTS:
|
|
|
376
396
|
bg.historyRetainedMessageCount !== undefined
|
|
377
397
|
? `\n**History:** compacted (${bg.historyRetainedMessageCount}/${bg.historyOriginalMessageCount} messages retained)`
|
|
378
398
|
: "";
|
|
399
|
+
const isolationLine = bg.isolationMode
|
|
400
|
+
? `\n**Isolation:** ${bg.isolationMode}${bg.worktreePath ? ` (${bg.worktreePath})` : ""}`
|
|
401
|
+
: "";
|
|
379
402
|
return {
|
|
380
403
|
details: {},
|
|
381
404
|
content: [
|
|
382
405
|
{
|
|
383
406
|
type: "text",
|
|
384
|
-
text: `**Task:** ${bg.id}\n**Agent:** ${bg.agent}\n**Status:** ${bg.status}\n**Duration:** ${duration}\n**Task:** ${bg.task}${historyLine}\n\n**Output:**\n${output}`,
|
|
407
|
+
text: `**Task:** ${bg.id}\n**Agent:** ${bg.agent}\n**Status:** ${bg.status}\n**Duration:** ${duration}\n**Task:** ${bg.task}${isolationLine}${historyLine}\n\n**Output:**\n${output}`,
|
|
385
408
|
},
|
|
386
409
|
],
|
|
387
410
|
};
|
|
@@ -406,7 +429,8 @@ WHEN NOT TO USE SUBAGENTS:
|
|
|
406
429
|
: getIcon("error");
|
|
407
430
|
const preview = bg.task.length > 40 ? `${bg.task.slice(0, 37)}...` : bg.task;
|
|
408
431
|
const compactedBadge = bg.historyCompacted ? " · compacted" : "";
|
|
409
|
-
|
|
432
|
+
const isolationBadge = bg.isolationMode ? ` · ${bg.isolationMode}` : "";
|
|
433
|
+
return `${statusIcon} **${bg.id}** (${bg.agent}) - ${bg.status}${compactedBadge}${isolationBadge} (${duration})\n ${preview}`;
|
|
410
434
|
});
|
|
411
435
|
|
|
412
436
|
return {
|
|
@@ -428,7 +452,13 @@ WHEN NOT TO USE SUBAGENTS:
|
|
|
428
452
|
* Execute centipede (sequential) mode.
|
|
429
453
|
*/
|
|
430
454
|
async function executeCentipede(
|
|
431
|
-
centipede: {
|
|
455
|
+
centipede: {
|
|
456
|
+
agent: string;
|
|
457
|
+
task: string;
|
|
458
|
+
cwd?: string;
|
|
459
|
+
model?: string;
|
|
460
|
+
isolation?: IsolationMode;
|
|
461
|
+
}[],
|
|
432
462
|
ctx: ExtensionContext,
|
|
433
463
|
agents: { name: string; source: string }[],
|
|
434
464
|
defaults: Parameters<typeof runSingleAgent>[13],
|
|
@@ -511,7 +541,8 @@ async function executeCentipede(
|
|
|
511
541
|
step.model,
|
|
512
542
|
parentModelId,
|
|
513
543
|
defaults,
|
|
514
|
-
routingHints
|
|
544
|
+
routingHints,
|
|
545
|
+
step.isolation
|
|
515
546
|
);
|
|
516
547
|
results.push(result);
|
|
517
548
|
latestPartialResult = undefined;
|
|
@@ -552,11 +583,20 @@ async function executeCentipede(
|
|
|
552
583
|
}
|
|
553
584
|
}
|
|
554
585
|
|
|
586
|
+
/** Parallel-task payload for subagent parallel mode. */
|
|
587
|
+
type ParallelTask = {
|
|
588
|
+
agent: string;
|
|
589
|
+
task: string;
|
|
590
|
+
cwd?: string;
|
|
591
|
+
model?: string;
|
|
592
|
+
isolation?: IsolationMode;
|
|
593
|
+
};
|
|
594
|
+
|
|
555
595
|
/**
|
|
556
596
|
* Execute parallel mode.
|
|
557
597
|
*/
|
|
558
598
|
async function executeParallel(
|
|
559
|
-
tasks:
|
|
599
|
+
tasks: ParallelTask[],
|
|
560
600
|
params: { background?: boolean },
|
|
561
601
|
ctx: ExtensionContext,
|
|
562
602
|
agents: Parameters<typeof runSingleAgent>[1],
|
|
@@ -586,7 +626,8 @@ async function executeParallel(
|
|
|
586
626
|
(t as { model?: string }).model,
|
|
587
627
|
parentModelId,
|
|
588
628
|
defaults,
|
|
589
|
-
routingHints
|
|
629
|
+
routingHints,
|
|
630
|
+
t.isolation
|
|
590
631
|
);
|
|
591
632
|
if (result?.startsWith("bg_")) taskIds.push(result);
|
|
592
633
|
else if (result) errors.push(result);
|
|
@@ -710,7 +751,8 @@ async function executeParallel(
|
|
|
710
751
|
(t as { model?: string }).model,
|
|
711
752
|
parentModelId,
|
|
712
753
|
defaults,
|
|
713
|
-
routingHints
|
|
754
|
+
routingHints,
|
|
755
|
+
t.isolation
|
|
714
756
|
);
|
|
715
757
|
allResults[globalIndex] = result;
|
|
716
758
|
return result;
|
|
@@ -725,7 +767,95 @@ async function executeParallel(
|
|
|
725
767
|
ctx.ui.setWorkingMessage();
|
|
726
768
|
}
|
|
727
769
|
|
|
728
|
-
|
|
770
|
+
let counts = countParallelResultStates(results);
|
|
771
|
+
let stalledRetrySummary: string | undefined;
|
|
772
|
+
|
|
773
|
+
const initialStalledIndexes = collectParallelStateIndices(results, "stalled");
|
|
774
|
+
if (initialStalledIndexes.length > 0) {
|
|
775
|
+
const retrySummaryLines: string[] = [];
|
|
776
|
+
const totalRetries = initialStalledIndexes.length;
|
|
777
|
+
|
|
778
|
+
try {
|
|
779
|
+
ctx.ui.setWorkingMessage(
|
|
780
|
+
`Rerunning ${totalRetries} stalled worker${totalRetries === 1 ? "" : "s"} individually`
|
|
781
|
+
);
|
|
782
|
+
|
|
783
|
+
for (let retryIndex = 0; retryIndex < initialStalledIndexes.length; retryIndex++) {
|
|
784
|
+
const stalledIndex = initialStalledIndexes[retryIndex];
|
|
785
|
+
const stalledTask = tasks[stalledIndex];
|
|
786
|
+
const priorResult = allResults[stalledIndex];
|
|
787
|
+
const retryTask = buildStalledRetryTask(stalledTask.task);
|
|
788
|
+
const explicitRetryModel = stalledTask.model ?? priorResult.model ?? parentModelId;
|
|
789
|
+
const retryRoutingHints = explicitRetryModel ? undefined : routingHints;
|
|
790
|
+
const retryLabel = explicitRetryModel
|
|
791
|
+
? `model:${explicitRetryModel}`
|
|
792
|
+
: retryRoutingHints?.modelScope
|
|
793
|
+
? `modelScope:${retryRoutingHints.modelScope}`
|
|
794
|
+
: "auto-routing";
|
|
795
|
+
|
|
796
|
+
ctx.ui.setWorkingMessage(
|
|
797
|
+
`Retrying stalled worker ${retryIndex + 1}/${totalRetries}: ${stalledTask.agent}`
|
|
798
|
+
);
|
|
799
|
+
|
|
800
|
+
const retryResult = await runSingleAgent(
|
|
801
|
+
ctx.cwd,
|
|
802
|
+
agents,
|
|
803
|
+
stalledTask.agent,
|
|
804
|
+
retryTask,
|
|
805
|
+
stalledTask.cwd,
|
|
806
|
+
undefined,
|
|
807
|
+
signal,
|
|
808
|
+
(partial) => {
|
|
809
|
+
if (partial.details?.results[0]) {
|
|
810
|
+
const partialResult = {
|
|
811
|
+
...partial.details.results[0],
|
|
812
|
+
task: stalledTask.task,
|
|
813
|
+
};
|
|
814
|
+
allResults[stalledIndex] = partialResult;
|
|
815
|
+
emitParallelUpdate();
|
|
816
|
+
}
|
|
817
|
+
},
|
|
818
|
+
makeDetails("parallel"),
|
|
819
|
+
pi.events,
|
|
820
|
+
undefined,
|
|
821
|
+
explicitRetryModel,
|
|
822
|
+
parentModelId,
|
|
823
|
+
defaults,
|
|
824
|
+
retryRoutingHints,
|
|
825
|
+
stalledTask.isolation
|
|
826
|
+
);
|
|
827
|
+
|
|
828
|
+
retryResult.task = stalledTask.task;
|
|
829
|
+
retryResult.stderr = appendStderrNote(
|
|
830
|
+
retryResult.stderr,
|
|
831
|
+
`[Auto-rerun] retried stalled worker individually (${retryLabel})`
|
|
832
|
+
);
|
|
833
|
+
allResults[stalledIndex] = retryResult;
|
|
834
|
+
retrySummaryLines.push(`- [${stalledTask.agent}] ${retryLabel}`);
|
|
835
|
+
emitParallelUpdate();
|
|
836
|
+
}
|
|
837
|
+
} finally {
|
|
838
|
+
ctx.ui.setWorkingMessage();
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
results = [...allResults];
|
|
842
|
+
counts = countParallelResultStates(results);
|
|
843
|
+
const remainingStalledIndexes = collectParallelStateIndices(results, "stalled");
|
|
844
|
+
const recoveredCount = totalRetries - remainingStalledIndexes.length;
|
|
845
|
+
const remainingAgents = remainingStalledIndexes.map((index) => results[index].agent).join(", ");
|
|
846
|
+
const lines = [
|
|
847
|
+
`Auto-rerun: retried ${totalRetries} stalled worker${totalRetries === 1 ? "" : "s"} individually with narrowed scope.`,
|
|
848
|
+
`Recovered ${recoveredCount}/${totalRetries}.`,
|
|
849
|
+
];
|
|
850
|
+
if (remainingStalledIndexes.length > 0) {
|
|
851
|
+
lines.push(`Still stalled: ${remainingAgents}.`);
|
|
852
|
+
}
|
|
853
|
+
stalledRetrySummary = lines.join(" ");
|
|
854
|
+
if (retrySummaryLines.length > 0) {
|
|
855
|
+
stalledRetrySummary += `\n${retrySummaryLines.join("\n")}`;
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
|
|
729
859
|
const summaries = results.map((result) => {
|
|
730
860
|
const output = getFinalOutput(result.messages);
|
|
731
861
|
const fallback = result.errorMessage || result.stderr || "(no output)";
|
|
@@ -737,7 +867,6 @@ async function executeParallel(
|
|
|
737
867
|
return `[${result.agent}] ${stateLabel}: ${preview}`;
|
|
738
868
|
});
|
|
739
869
|
|
|
740
|
-
const finishedNonStalled = counts.completed + counts.failed;
|
|
741
870
|
let isError = false;
|
|
742
871
|
let stalledRemediation: string | undefined;
|
|
743
872
|
|
|
@@ -748,41 +877,16 @@ async function executeParallel(
|
|
|
748
877
|
const stalledAgentList = stalledAgents.join(", ");
|
|
749
878
|
const remediation =
|
|
750
879
|
`Stalled workers: ${stalledAgentList}. ` +
|
|
751
|
-
"
|
|
752
|
-
"
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
`${
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
);
|
|
762
|
-
if (!continueWithPartials) {
|
|
763
|
-
return {
|
|
764
|
-
content: [
|
|
765
|
-
{
|
|
766
|
-
type: "text" as const,
|
|
767
|
-
text:
|
|
768
|
-
"Parallel run aborted because stalled workers were detected and " +
|
|
769
|
-
"you chose not to continue with partial results.\n\n" +
|
|
770
|
-
`${remediation}`,
|
|
771
|
-
},
|
|
772
|
-
],
|
|
773
|
-
details: makeDetails("parallel")(results),
|
|
774
|
-
isError: true,
|
|
775
|
-
};
|
|
776
|
-
}
|
|
777
|
-
} else {
|
|
778
|
-
isError = true;
|
|
779
|
-
stalledRemediation = ctx.hasUI
|
|
780
|
-
? "Parallel run finished with stalled workers and no completed non-stalled results.\n" +
|
|
781
|
-
`${remediation}`
|
|
782
|
-
: "Non-interactive mode: returning partial results and marking this " +
|
|
783
|
-
"parallel call as error because some workers stalled.\n" +
|
|
784
|
-
`${remediation}`;
|
|
785
|
-
}
|
|
880
|
+
"Automatic rerun already attempted once per stalled worker. " +
|
|
881
|
+
"Split task scope further, avoid confirmation-gated steps, " +
|
|
882
|
+
"or pin a different explicit model/modelScope.";
|
|
883
|
+
isError = true;
|
|
884
|
+
stalledRemediation = ctx.hasUI
|
|
885
|
+
? "Parallel run finished with unrecovered stalled workers after automatic reruns.\n" +
|
|
886
|
+
`${remediation}`
|
|
887
|
+
: "Non-interactive mode: returning partial results with error because " +
|
|
888
|
+
"workers remained stalled after automatic reruns.\n" +
|
|
889
|
+
`${remediation}`;
|
|
786
890
|
}
|
|
787
891
|
|
|
788
892
|
const batchNote =
|
|
@@ -796,6 +900,7 @@ async function executeParallel(
|
|
|
796
900
|
`(${counts.completed} completed, ${counts.failed} failed, ${counts.stalled} stalled)`;
|
|
797
901
|
const summaryText =
|
|
798
902
|
`${header}${batchNote}\n\n${summaries.join("\n\n")}` +
|
|
903
|
+
(stalledRetrySummary ? `\n\n${stalledRetrySummary}` : "") +
|
|
799
904
|
(stalledRemediation ? `\n\n${stalledRemediation}` : "");
|
|
800
905
|
|
|
801
906
|
return {
|
|
@@ -816,6 +921,7 @@ async function executeSingle(
|
|
|
816
921
|
session?: string;
|
|
817
922
|
model?: string;
|
|
818
923
|
background?: boolean;
|
|
924
|
+
isolation?: IsolationMode;
|
|
819
925
|
},
|
|
820
926
|
ctx: ExtensionContext,
|
|
821
927
|
agents: Parameters<typeof runSingleAgent>[1],
|
|
@@ -845,7 +951,8 @@ async function executeSingle(
|
|
|
845
951
|
params.model,
|
|
846
952
|
parentModelId,
|
|
847
953
|
defaults,
|
|
848
|
-
routingHints
|
|
954
|
+
routingHints,
|
|
955
|
+
params.isolation
|
|
849
956
|
);
|
|
850
957
|
if (result?.startsWith("bg_")) {
|
|
851
958
|
return {
|
|
@@ -907,7 +1014,8 @@ async function executeSingle(
|
|
|
907
1014
|
params.model,
|
|
908
1015
|
parentModelId,
|
|
909
1016
|
defaults,
|
|
910
|
-
routingHints
|
|
1017
|
+
routingHints,
|
|
1018
|
+
params.isolation
|
|
911
1019
|
);
|
|
912
1020
|
|
|
913
1021
|
if (singleSpinnerInterval) {
|
|
@@ -1138,6 +1246,63 @@ function countParallelResultStates(results: SingleResult[]): ParallelResultCount
|
|
|
1138
1246
|
return counts;
|
|
1139
1247
|
}
|
|
1140
1248
|
|
|
1249
|
+
/**
|
|
1250
|
+
* Retry directive appended to stalled-worker reruns.
|
|
1251
|
+
*
|
|
1252
|
+
* Instructs the worker to aggressively narrow scope so retried tasks
|
|
1253
|
+
* are less likely to deadlock on long/interactive paths.
|
|
1254
|
+
*/
|
|
1255
|
+
const STALLED_RETRY_SCOPE_GUIDANCE =
|
|
1256
|
+
"[Automatic retry after stall]\n" +
|
|
1257
|
+
"Your previous parallel attempt stalled. Execute a narrower slice now: " +
|
|
1258
|
+
"complete only the smallest high-confidence chunk you can finish quickly.\n" +
|
|
1259
|
+
"If the original task is already small, complete it fully. " +
|
|
1260
|
+
"If it is broad, finish one concrete slice and list remaining follow-ups.";
|
|
1261
|
+
|
|
1262
|
+
/**
|
|
1263
|
+
* Build the retry task text for a stalled parallel worker.
|
|
1264
|
+
*
|
|
1265
|
+
* @param task - Original worker task
|
|
1266
|
+
* @returns Task text with explicit scope-narrowing retry guidance
|
|
1267
|
+
*/
|
|
1268
|
+
function buildStalledRetryTask(task: string): string {
|
|
1269
|
+
const baseTask = task.trim();
|
|
1270
|
+
if (baseTask.length === 0) return STALLED_RETRY_SCOPE_GUIDANCE;
|
|
1271
|
+
return `${baseTask}\n\n${STALLED_RETRY_SCOPE_GUIDANCE}`;
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1274
|
+
/**
|
|
1275
|
+
* Collect indexes of results that match a target parallel state.
|
|
1276
|
+
*
|
|
1277
|
+
* @param results - Parallel result list
|
|
1278
|
+
* @param state - Target state to match
|
|
1279
|
+
* @returns Zero-based indexes for matching rows
|
|
1280
|
+
*/
|
|
1281
|
+
function collectParallelStateIndices(
|
|
1282
|
+
results: SingleResult[],
|
|
1283
|
+
state: ParallelResultState
|
|
1284
|
+
): number[] {
|
|
1285
|
+
const indexes: number[] = [];
|
|
1286
|
+
for (let index = 0; index < results.length; index++) {
|
|
1287
|
+
if (getParallelResultState(results[index]) === state) {
|
|
1288
|
+
indexes.push(index);
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
return indexes;
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1294
|
+
/**
|
|
1295
|
+
* Append a note to stderr while preserving existing diagnostics.
|
|
1296
|
+
*
|
|
1297
|
+
* @param stderr - Existing stderr text
|
|
1298
|
+
* @param note - Diagnostic note to append
|
|
1299
|
+
* @returns Combined stderr string
|
|
1300
|
+
*/
|
|
1301
|
+
function appendStderrNote(stderr: string, note: string): string {
|
|
1302
|
+
if (!stderr.trim()) return note;
|
|
1303
|
+
return `${stderr}\n${note}`;
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1141
1306
|
/**
|
|
1142
1307
|
* Render the tool call header for the subagent tool.
|
|
1143
1308
|
*
|
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
resolveModelFuzzy,
|
|
32
32
|
selectModels,
|
|
33
33
|
} from "@dungle-scrubs/synapse";
|
|
34
|
+
import { getTallowPath, getTallowSettingsPath } from "../_shared/tallow-paths.js";
|
|
34
35
|
import { classifyTask } from "./task-classifier.js";
|
|
35
36
|
|
|
36
37
|
// ─── Types ───────────────────────────────────────────────────────────────────
|
|
@@ -412,8 +413,7 @@ function resolveModePolicyOverridesField(
|
|
|
412
413
|
* @returns Merged routing config
|
|
413
414
|
*/
|
|
414
415
|
export function loadRoutingConfig(cwd: string = process.cwd()): RoutingConfig {
|
|
415
|
-
const
|
|
416
|
-
const userSettingsPath = path.join(home, ".tallow", "settings.json");
|
|
416
|
+
const userSettingsPath = getTallowSettingsPath();
|
|
417
417
|
const projectSettingsPath = path.join(cwd, ".tallow", "settings.json");
|
|
418
418
|
|
|
419
419
|
const userRouting = readRawRoutingConfig(userSettingsPath);
|
|
@@ -698,7 +698,7 @@ export function loadRoutingSignalsSnapshot(
|
|
|
698
698
|
*/
|
|
699
699
|
function getSubscriptionProviders(): string[] {
|
|
700
700
|
try {
|
|
701
|
-
const authPath =
|
|
701
|
+
const authPath = getTallowPath("auth.json");
|
|
702
702
|
const raw = fs.readFileSync(authPath, "utf-8");
|
|
703
703
|
const data = JSON.parse(raw) as Record<string, { type?: string }>;
|
|
704
704
|
return Object.entries(data)
|