thoth-agents 0.2.9 → 0.2.11
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 +11 -4
- package/dist/agents/prompt-dialects.d.ts +8 -0
- package/dist/{chunk-75JOF37E.js → chunk-6BNAV534.js} +1 -1
- package/dist/{chunk-6NMPKYWY.js → chunk-ASKXWU6E.js} +850 -201
- package/dist/{chunk-YLRPDTU7.js → chunk-OZE7JVGS.js} +80 -54
- package/dist/cli/config-io.d.ts +5 -0
- package/dist/cli/custom-skills.d.ts +2 -1
- package/dist/cli/index.js +19 -18
- package/dist/cli/operations/types.d.ts +2 -0
- package/dist/cli/tui/index.js +91 -18
- package/dist/harness/adapters/codex-surfaces.d.ts +7 -8
- package/dist/harness/core/sdd.d.ts +2 -0
- package/dist/index.js +2 -2
- package/package.json +1 -1
- package/src/skills/sdd-tasks/SKILL.md +39 -15
|
@@ -425,7 +425,27 @@ function writeConfig(configPath, config) {
|
|
|
425
425
|
writeFileSync(tmpPath, content);
|
|
426
426
|
renameSync(tmpPath, configPath);
|
|
427
427
|
}
|
|
428
|
-
|
|
428
|
+
function mergeOpenCodeMainConfig(config, update) {
|
|
429
|
+
if (update.ensurePlugin) {
|
|
430
|
+
const plugins = Array.isArray(config.plugin) ? config.plugin : [];
|
|
431
|
+
config.plugin = [
|
|
432
|
+
...plugins.filter(
|
|
433
|
+
(plugin) => plugin !== PACKAGE_NAME && !plugin.startsWith(`${PACKAGE_NAME}@`)
|
|
434
|
+
),
|
|
435
|
+
`${PACKAGE_NAME}@latest`
|
|
436
|
+
];
|
|
437
|
+
}
|
|
438
|
+
if (update.disableDefaults) {
|
|
439
|
+
const agent = config.agent && typeof config.agent === "object" ? { ...config.agent } : {};
|
|
440
|
+
const explore = agent.explore && typeof agent.explore === "object" ? { ...agent.explore } : {};
|
|
441
|
+
const general = agent.general && typeof agent.general === "object" ? { ...agent.general } : {};
|
|
442
|
+
agent.explore = { ...explore, disable: true };
|
|
443
|
+
agent.general = { ...general, disable: true };
|
|
444
|
+
config.agent = agent;
|
|
445
|
+
}
|
|
446
|
+
return config;
|
|
447
|
+
}
|
|
448
|
+
function updateOpenCodeMainConfig(update) {
|
|
429
449
|
const configPath = getExistingConfigPath();
|
|
430
450
|
try {
|
|
431
451
|
ensureOpenCodeConfigDir();
|
|
@@ -445,14 +465,10 @@ async function addPluginToOpenCodeConfig() {
|
|
|
445
465
|
error: `Failed to parse config: ${error}`
|
|
446
466
|
};
|
|
447
467
|
}
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
(p) => p !== PACKAGE_NAME && !p.startsWith(`${PACKAGE_NAME}@`)
|
|
468
|
+
writeConfig(
|
|
469
|
+
configPath,
|
|
470
|
+
mergeOpenCodeMainConfig(parsedConfig ?? {}, update)
|
|
452
471
|
);
|
|
453
|
-
filteredPlugins.push(`${PACKAGE_NAME}@latest`);
|
|
454
|
-
config.plugin = filteredPlugins;
|
|
455
|
-
writeConfig(configPath, config);
|
|
456
472
|
return { success: true, configPath };
|
|
457
473
|
} catch (err) {
|
|
458
474
|
return {
|
|
@@ -485,33 +501,6 @@ function writeLiteConfig(installConfig, targetPath) {
|
|
|
485
501
|
};
|
|
486
502
|
}
|
|
487
503
|
}
|
|
488
|
-
function disableDefaultAgents() {
|
|
489
|
-
const configPath = getExistingConfigPath();
|
|
490
|
-
try {
|
|
491
|
-
ensureOpenCodeConfigDir();
|
|
492
|
-
const { config: parsedConfig, error } = parseConfig(configPath);
|
|
493
|
-
if (error) {
|
|
494
|
-
return {
|
|
495
|
-
success: false,
|
|
496
|
-
configPath,
|
|
497
|
-
error: `Failed to parse config: ${error}`
|
|
498
|
-
};
|
|
499
|
-
}
|
|
500
|
-
const config = parsedConfig ?? {};
|
|
501
|
-
const agent = config.agent ?? {};
|
|
502
|
-
agent.explore = { disable: true };
|
|
503
|
-
agent.general = { disable: true };
|
|
504
|
-
config.agent = agent;
|
|
505
|
-
writeConfig(configPath, config);
|
|
506
|
-
return { success: true, configPath };
|
|
507
|
-
} catch (err) {
|
|
508
|
-
return {
|
|
509
|
-
success: false,
|
|
510
|
-
configPath,
|
|
511
|
-
error: `Failed to disable default agents: ${err}`
|
|
512
|
-
};
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
504
|
function detectCurrentConfig() {
|
|
516
505
|
const result = {
|
|
517
506
|
isInstalled: false,
|
|
@@ -710,8 +699,8 @@ var OPENCODE_CAPABILITIES = {
|
|
|
710
699
|
};
|
|
711
700
|
var CODEX_PROMPT_CAPABILITIES = {
|
|
712
701
|
agentDefinitions: "supported",
|
|
713
|
-
delegatedExecution: "
|
|
714
|
-
parallelDelegation: "
|
|
702
|
+
delegatedExecution: "supported",
|
|
703
|
+
parallelDelegation: "supported",
|
|
715
704
|
runtimeHooks: "unknown",
|
|
716
705
|
mcpConfiguration: "supported",
|
|
717
706
|
skillPackaging: "supported",
|
|
@@ -755,6 +744,13 @@ var OPENCODE_PROMPT_DIALECT = {
|
|
|
755
744
|
userQuestionTool: "question",
|
|
756
745
|
progressTool: "todowrite",
|
|
757
746
|
hostStatusSurface: "task_status",
|
|
747
|
+
lifecycle: {
|
|
748
|
+
statusAction: "wait, poll, and collect",
|
|
749
|
+
terminalState: "terminal task_status result",
|
|
750
|
+
nonterminalState: "nonterminal task_status result",
|
|
751
|
+
sameSessionProbe: "task_status on the same task session",
|
|
752
|
+
enforcement: "runtime-supported"
|
|
753
|
+
},
|
|
758
754
|
roleReference: (role) => `@${role}`
|
|
759
755
|
},
|
|
760
756
|
capabilities: supportedCapabilityProfile(OPENCODE_CAPABILITIES),
|
|
@@ -775,12 +771,19 @@ var OPENCODE_PROMPT_DIALECT = {
|
|
|
775
771
|
var CODEX_PROMPT_DIALECT = {
|
|
776
772
|
harness: "codex",
|
|
777
773
|
tools: {
|
|
778
|
-
delegationTool: "
|
|
779
|
-
backgroundDelegationTool: "
|
|
780
|
-
backgroundStatusTool: "
|
|
774
|
+
delegationTool: "collaboration.spawn_agent",
|
|
775
|
+
backgroundDelegationTool: "collaboration.spawn_agent",
|
|
776
|
+
backgroundStatusTool: "collaboration.wait_agent",
|
|
781
777
|
userQuestionTool: "request_user_input",
|
|
782
778
|
progressTool: "functions.update_plan",
|
|
783
|
-
hostStatusSurface: "
|
|
779
|
+
hostStatusSurface: "collaboration.list_agents",
|
|
780
|
+
lifecycle: {
|
|
781
|
+
statusAction: "wait and inspect status",
|
|
782
|
+
terminalState: "terminal mailbox completion or failure update",
|
|
783
|
+
nonterminalState: "collaboration.wait_agent timeout or silence",
|
|
784
|
+
sameSessionProbe: "collaboration.list_agents on the same task path",
|
|
785
|
+
enforcement: "runtime-supported"
|
|
786
|
+
},
|
|
784
787
|
roleReference: (role) => `${role} role agent`
|
|
785
788
|
},
|
|
786
789
|
capabilities: {
|
|
@@ -792,9 +795,9 @@ var CODEX_PROMPT_DIALECT = {
|
|
|
792
795
|
case "root-coordinator":
|
|
793
796
|
return "ambient Codex root session coordinator";
|
|
794
797
|
case "task":
|
|
795
|
-
return "
|
|
798
|
+
return "collaboration.spawn_agent";
|
|
796
799
|
case "synchronous-task-only":
|
|
797
|
-
return "synchronous
|
|
800
|
+
return "synchronous collaboration.spawn_agent only";
|
|
798
801
|
}
|
|
799
802
|
},
|
|
800
803
|
renderRoleInvocation(role) {
|
|
@@ -814,6 +817,13 @@ var CLAUDE_CODE_PROMPT_DIALECT = {
|
|
|
814
817
|
userQuestionTool: "AskUserQuestion",
|
|
815
818
|
progressTool: "TodoWrite",
|
|
816
819
|
hostStatusSurface: "TodoWrite",
|
|
820
|
+
lifecycle: {
|
|
821
|
+
statusAction: "wait, poll, and collect",
|
|
822
|
+
terminalState: "terminal TaskOutput result",
|
|
823
|
+
nonterminalState: "nonterminal TaskOutput result",
|
|
824
|
+
sameSessionProbe: "TaskOutput on the same task session",
|
|
825
|
+
enforcement: "runtime-supported"
|
|
826
|
+
},
|
|
817
827
|
roleReference: (role) => role === "orchestrator" ? "the main-thread orchestrator" : `Task(subagent_type: ${claudeCodeSubagentType(role)})`
|
|
818
828
|
},
|
|
819
829
|
capabilities: supportedCapabilityProfile(CLAUDE_CODE_PROMPT_CAPABILITIES),
|
|
@@ -943,6 +953,7 @@ var SDD_PHASES = [
|
|
|
943
953
|
artifactSkill: "sdd-tasks",
|
|
944
954
|
defaultAgentRole: "quick",
|
|
945
955
|
alternateAgentRoles: ["deep"],
|
|
956
|
+
alternateAgentCondition: "Only when the task plan is complex.",
|
|
946
957
|
delegationReason: "Mechanical conversion of settled design into dependency-ordered execution tasks."
|
|
947
958
|
},
|
|
948
959
|
{
|
|
@@ -1131,6 +1142,10 @@ function alternateSddRoles(id) {
|
|
|
1131
1142
|
const phase = getDelegatedSddPhase(id);
|
|
1132
1143
|
return phase.alternateAgentRoles?.length ? renderRoleList(phase.alternateAgentRoles) : "";
|
|
1133
1144
|
}
|
|
1145
|
+
function alternateSddCondition(id) {
|
|
1146
|
+
const condition = getDelegatedSddPhase(id).alternateAgentCondition;
|
|
1147
|
+
return condition ? condition.replace(/^Only/, "only").replace(/\.$/, "") : "";
|
|
1148
|
+
}
|
|
1134
1149
|
function supportSddRoles(id) {
|
|
1135
1150
|
const phase = getDelegatedSddPhase(id);
|
|
1136
1151
|
return phase.supportingAgentRoles?.length ? renderRoleList(phase.supportingAgentRoles) : "";
|
|
@@ -1142,7 +1157,7 @@ function persistenceSddRole(id) {
|
|
|
1142
1157
|
function renderSddDelegationMatrix() {
|
|
1143
1158
|
return `<sdd-delegation-matrix>
|
|
1144
1159
|
- sdd-init -> ${primarySddRole("init")} (+${supportSddRoles("init")}, if openspec/ missing); sdd-explore -> ${primarySddRole("explore")} (+${supportSddRoles("explore")})
|
|
1145
|
-
- sdd-propose/sdd-spec/sdd-design -> ${primarySddRole("proposal")}; sdd-clarify -> ${primarySddRole("clarify")}; sdd-tasks -> ${primarySddRole("tasks")} (fallback: ${alternateSddRoles("tasks")})
|
|
1160
|
+
- sdd-propose/sdd-spec/sdd-design -> ${primarySddRole("proposal")}; sdd-clarify -> ${primarySddRole("clarify")}; sdd-tasks -> ${primarySddRole("tasks")} (fallback: ${alternateSddRoles("tasks")} ${alternateSddCondition("tasks")})
|
|
1146
1161
|
- plan-reviewer -> ${primarySddRole("plan-review")}; sdd-apply -> ${primarySddRole("apply")} (fallback: ${alternateSddRoles("apply")}); sdd-verify -> ${primarySddRole("verify")} (persistence: ${persistenceSddRole("verify")}); sdd-archive -> ${primarySddRole("archive")}
|
|
1147
1162
|
</sdd-delegation-matrix>`;
|
|
1148
1163
|
}
|
|
@@ -1280,11 +1295,9 @@ For {{role.explorer}}/{{role.librarian}}, ask narrow fact-finding questions for
|
|
|
1280
1295
|
- Experimental background \`{{backgroundDelegationTool}}\` is allowed only for {{role.explorer}} and {{role.librarian}} for asynchronous delegation.
|
|
1281
1296
|
- {{role.oracle}}, {{role.designer}}, {{role.quick}}, and {{role.deep}} always use normal synchronous \`{{delegationTool}}\` execution.
|
|
1282
1297
|
- When using background \`{{delegationTool}}\`, treat it as conditional and non-portable: if the host does not expose the experimental path, fall back to normal synchronous \`{{delegationTool}}\`.
|
|
1283
|
-
- Use \`{{backgroundStatusTool}}\` to
|
|
1284
|
-
-
|
|
1285
|
-
-
|
|
1286
|
-
- Never switch to \`default\`, \`worker\`, or any other role.
|
|
1287
|
-
- After 3 failures, stay on the same role; if a same-role model override exists, use it. Otherwise report a capacity blocker.
|
|
1298
|
+
- Use \`{{backgroundStatusTool}}\` to {{lifecycleStatusAction}}: treat \`{{lifecycleNonterminalState}}\` as in progress and probe the same session via \`{{lifecycleSameSessionProbe}}\`; no retry/reroute/interruption before \`{{lifecycleTerminalState}}\`, an explicit user deadline, user cancellation, or a superseding request.
|
|
1299
|
+
- Terminal result-quality and required-artifact checks share one sharpened retry; nonterminal probes use none.
|
|
1300
|
+
- Capacity is separate: retry the named role up to 3 times; never switch to \`default\`, \`worker\`, or another role; then use a same-role model override or report a blocker.
|
|
1288
1301
|
- Write-capable dispatches must include task instructions and handoff retrieval instructions when a root-owned handoff summary exists, so implementers can recover context without rediscovering settled scope.
|
|
1289
1302
|
- Never tell sub-agents to discard working-tree changes.
|
|
1290
1303
|
</dispatch>
|
|
@@ -1311,7 +1324,6 @@ Hard gates:
|
|
|
1311
1324
|
- Group consecutive ready SDD tasks for the same execution agent into one dispatch when dependencies, scope, and verification can be handled together. Keep per-task tracking and evidence; do not split a compatible {{role.designer}}/{{role.quick}}/{{role.deep}} run into one delegation per checkbox.
|
|
1312
1325
|
|
|
1313
1326
|
SDD dispatch envelope must include: skill name, persistence mode, pipeline type, change name, project name, needed prior artifact context, verification expectation, and return envelope.
|
|
1314
|
-
After each phase, verify the sub-agent reported the openspec path and/or thoth-mem topic_key. Retry once if missing.
|
|
1315
1327
|
|
|
1316
1328
|
Artifact governance handoff:
|
|
1317
1329
|
- After \`sdd-tasks\`, you may surface report-only artifact governance findings before execution preparation starts.
|
|
@@ -1614,7 +1626,19 @@ function renderRoleText(section, dialect) {
|
|
|
1614
1626
|
).replaceAll(
|
|
1615
1627
|
"{{backgroundStatusTool}}",
|
|
1616
1628
|
dialect.tools.backgroundStatusTool ?? dialect.tools.hostStatusSurface ?? ""
|
|
1617
|
-
).replaceAll("{{userQuestionTool}}", dialect.tools.userQuestionTool).replaceAll("{{progressTool}}", dialect.tools.progressTool).replaceAll(
|
|
1629
|
+
).replaceAll("{{userQuestionTool}}", dialect.tools.userQuestionTool).replaceAll("{{progressTool}}", dialect.tools.progressTool).replaceAll(
|
|
1630
|
+
"{{lifecycleStatusAction}}",
|
|
1631
|
+
dialect.tools.lifecycle.statusAction
|
|
1632
|
+
).replaceAll(
|
|
1633
|
+
"{{lifecycleTerminalState}}",
|
|
1634
|
+
dialect.tools.lifecycle.terminalState
|
|
1635
|
+
).replaceAll(
|
|
1636
|
+
"{{lifecycleNonterminalState}}",
|
|
1637
|
+
dialect.tools.lifecycle.nonterminalState
|
|
1638
|
+
).replaceAll(
|
|
1639
|
+
"{{lifecycleSameSessionProbe}}",
|
|
1640
|
+
dialect.tools.lifecycle.sameSessionProbe
|
|
1641
|
+
).replaceAll("{{dispatch.task}}", dialect.dispatchLabel("task")).replaceAll(
|
|
1618
1642
|
"{{dispatch.synchronous-task-only}}",
|
|
1619
1643
|
dialect.dispatchLabel("synchronous-task-only")
|
|
1620
1644
|
).replace(
|
|
@@ -2079,6 +2103,9 @@ function resolvePackageRoot(packageRoot) {
|
|
|
2079
2103
|
const moduleDir = fileURLToPath(new URL(".", import.meta.url));
|
|
2080
2104
|
return findPackageRoot(moduleDir) ?? fileURLToPath(new URL("../..", import.meta.url));
|
|
2081
2105
|
}
|
|
2106
|
+
function checkCustomSkillsNeedUpdate(packageRoot) {
|
|
2107
|
+
return checkSkillsNeedUpdate(resolvePackageRoot(packageRoot));
|
|
2108
|
+
}
|
|
2082
2109
|
function installCustomSkillFiles(skill, packageRoot) {
|
|
2083
2110
|
const sourcePath = join4(packageRoot, skill.sourcePath);
|
|
2084
2111
|
const targetPath = join4(getCustomSkillsDir(), skill.name);
|
|
@@ -2275,14 +2302,12 @@ export {
|
|
|
2275
2302
|
getExistingLiteConfigPath,
|
|
2276
2303
|
getExistingConfigPath,
|
|
2277
2304
|
ensureConfigDir,
|
|
2278
|
-
ensureOpenCodeConfigDir,
|
|
2279
2305
|
generateLiteConfig,
|
|
2280
2306
|
stripJsonComments,
|
|
2281
2307
|
parseConfig,
|
|
2282
2308
|
writeConfig,
|
|
2283
|
-
|
|
2309
|
+
updateOpenCodeMainConfig,
|
|
2284
2310
|
writeLiteConfig,
|
|
2285
|
-
disableDefaultAgents,
|
|
2286
2311
|
detectCurrentConfig,
|
|
2287
2312
|
loadPluginConfig,
|
|
2288
2313
|
loadAgentPrompt,
|
|
@@ -2309,6 +2334,7 @@ export {
|
|
|
2309
2334
|
CUSTOM_SKILLS,
|
|
2310
2335
|
getCustomSkillsDir,
|
|
2311
2336
|
findPackageRoot,
|
|
2337
|
+
checkCustomSkillsNeedUpdate,
|
|
2312
2338
|
installCustomSkills,
|
|
2313
2339
|
CONTEXT7_MCP_URL,
|
|
2314
2340
|
context7,
|
package/dist/cli/config-io.d.ts
CHANGED
|
@@ -16,6 +16,11 @@ export declare function parseConfig(path: string): {
|
|
|
16
16
|
*/
|
|
17
17
|
export declare function writeConfig(configPath: string, config: OpenCodeConfig): void;
|
|
18
18
|
export declare function addPluginToOpenCodeConfig(): Promise<ConfigMergeResult>;
|
|
19
|
+
export interface OpenCodeMainConfigUpdate {
|
|
20
|
+
ensurePlugin?: boolean;
|
|
21
|
+
disableDefaults?: boolean;
|
|
22
|
+
}
|
|
23
|
+
export declare function updateOpenCodeMainConfig(update: OpenCodeMainConfigUpdate): ConfigMergeResult;
|
|
19
24
|
export declare function writeLiteConfig(installConfig: InstallConfig, targetPath?: string): ConfigMergeResult;
|
|
20
25
|
export declare function disableDefaultAgents(): ConfigMergeResult;
|
|
21
26
|
export declare function canModifyOpenCodeConfig(): boolean;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type SkillUpdateReason } from './skill-manifest';
|
|
1
|
+
import { type SkillUpdateCheck, type SkillUpdateReason } from './skill-manifest';
|
|
2
2
|
/**
|
|
3
3
|
* A custom skill bundled in this repository.
|
|
4
4
|
* Unlike npx-installed skills, these are copied from src/skills/ to the OpenCode skills directory
|
|
@@ -37,6 +37,7 @@ export interface InstallCustomSkillsReport {
|
|
|
37
37
|
*/
|
|
38
38
|
export declare function getCustomSkillsDir(): string;
|
|
39
39
|
export declare function findPackageRoot(startDir: string): string | null;
|
|
40
|
+
export declare function checkCustomSkillsNeedUpdate(packageRoot?: string): SkillUpdateCheck;
|
|
40
41
|
export declare function removeObsoleteSkills(removedSkillNames: string[]): string[];
|
|
41
42
|
export declare function installCustomSkills(packageRoot?: string): InstallCustomSkillsReport;
|
|
42
43
|
/**
|
package/dist/cli/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
getOpenCodeVersion,
|
|
5
5
|
isOpenCodeInstalled,
|
|
6
6
|
opencodeAdapter
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-6BNAV534.js";
|
|
8
8
|
import {
|
|
9
9
|
CODEX_ROLE_NAMES,
|
|
10
10
|
RECOMMENDED_SKILLS,
|
|
@@ -41,19 +41,18 @@ import {
|
|
|
41
41
|
installRecommendedSkill,
|
|
42
42
|
listOperationHarnesses,
|
|
43
43
|
normalizeEffortSelection
|
|
44
|
-
} from "../chunk-
|
|
44
|
+
} from "../chunk-ASKXWU6E.js";
|
|
45
45
|
import {
|
|
46
46
|
ALL_AGENT_NAMES,
|
|
47
47
|
CUSTOM_SKILLS,
|
|
48
48
|
DEFAULT_MODELS,
|
|
49
|
-
addPluginToOpenCodeConfig,
|
|
50
49
|
detectCurrentConfig,
|
|
51
|
-
disableDefaultAgents,
|
|
52
50
|
generateLiteConfig,
|
|
53
51
|
getExistingLiteConfigPath,
|
|
54
52
|
installCustomSkills,
|
|
53
|
+
updateOpenCodeMainConfig,
|
|
55
54
|
writeLiteConfig
|
|
56
|
-
} from "../chunk-
|
|
55
|
+
} from "../chunk-OZE7JVGS.js";
|
|
57
56
|
|
|
58
57
|
// src/cli/index.ts
|
|
59
58
|
import { pathToFileURL } from "url";
|
|
@@ -167,7 +166,7 @@ async function runInstall(config) {
|
|
|
167
166
|
const detected = detectCurrentConfig();
|
|
168
167
|
const isUpdate = detected.isInstalled;
|
|
169
168
|
printHeader(isUpdate);
|
|
170
|
-
let totalSteps =
|
|
169
|
+
let totalSteps = 3;
|
|
171
170
|
if (config.installSkills) totalSteps += 1;
|
|
172
171
|
if (config.installCustomSkills) totalSteps += 1;
|
|
173
172
|
let step = 1;
|
|
@@ -178,19 +177,19 @@ async function runInstall(config) {
|
|
|
178
177
|
const { ok } = await checkOpenCodeInstalled();
|
|
179
178
|
if (!ok) return 1;
|
|
180
179
|
}
|
|
181
|
-
printStep(
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
if (!handleStepResult(pluginResult, "Plugin added")) return 1;
|
|
187
|
-
}
|
|
188
|
-
printStep(step++, totalSteps, "Disabling OpenCode default agents...");
|
|
180
|
+
printStep(
|
|
181
|
+
step++,
|
|
182
|
+
totalSteps,
|
|
183
|
+
"Configuring the thoth-agents plugin and OpenCode default agents..."
|
|
184
|
+
);
|
|
189
185
|
if (config.dryRun) {
|
|
190
|
-
printInfo("Dry run mode - skipping
|
|
186
|
+
printInfo("Dry run mode - skipping main config update");
|
|
191
187
|
} else {
|
|
192
|
-
const
|
|
193
|
-
|
|
188
|
+
const mainConfigResult = updateOpenCodeMainConfig({
|
|
189
|
+
ensurePlugin: true,
|
|
190
|
+
disableDefaults: true
|
|
191
|
+
});
|
|
192
|
+
if (!handleStepResult(mainConfigResult, "Main config updated")) return 1;
|
|
194
193
|
}
|
|
195
194
|
printStep(step++, totalSteps, "Writing thoth-agents configuration...");
|
|
196
195
|
if (config.dryRun) {
|
|
@@ -382,7 +381,7 @@ function formatPaths(paths) {
|
|
|
382
381
|
}
|
|
383
382
|
function formatWarnings(warnings) {
|
|
384
383
|
return warnings.map(
|
|
385
|
-
(warning) => `- [${warning.severity}] ${warning.message}`
|
|
384
|
+
(warning) => `- [${warning.severity}]${warning.code ? ` [${warning.code}]` : ""} ${warning.message}`
|
|
386
385
|
);
|
|
387
386
|
}
|
|
388
387
|
function formatDisclaimers(disclaimers) {
|
|
@@ -447,6 +446,7 @@ function formatOperationPlan(plan) {
|
|
|
447
446
|
`Summary: ${plan.summary}`
|
|
448
447
|
],
|
|
449
448
|
plan.targets.length > 0 ? ["Targets:", ...plan.targets.map(formatTarget)] : [],
|
|
449
|
+
plan.blockerTargets?.length ? ["Blocking targets:", ...plan.blockerTargets.map(formatTarget)] : [],
|
|
450
450
|
plan.surfaces.length > 0 ? [
|
|
451
451
|
"Managed surfaces:",
|
|
452
452
|
...plan.surfaces.map(
|
|
@@ -476,6 +476,7 @@ function formatOperationApplyResult(result) {
|
|
|
476
476
|
`Summary: ${result.summary}`
|
|
477
477
|
],
|
|
478
478
|
result.changedTargets.length > 0 ? ["Changed targets:", ...result.changedTargets.map(formatTarget)] : [],
|
|
479
|
+
result.diagnosticTargets?.length ? ["Diagnostic targets:", ...result.diagnosticTargets.map(formatTarget)] : [],
|
|
479
480
|
result.backups.length > 0 ? ["Backups:", ...formatPaths(result.backups)] : [],
|
|
480
481
|
result.warnings.length > 0 ? ["Warnings:", ...formatWarnings(result.warnings)] : [],
|
|
481
482
|
result.disclaimers.length > 0 ? ["Disclaimers:", ...formatDisclaimers(result.disclaimers)] : []
|
|
@@ -80,6 +80,7 @@ export interface OperationPlan {
|
|
|
80
80
|
dryRun: boolean;
|
|
81
81
|
canApply: boolean;
|
|
82
82
|
targets: ManagedTarget[];
|
|
83
|
+
blockerTargets?: ManagedTarget[];
|
|
83
84
|
surfaces: ManagedSurface[];
|
|
84
85
|
backup: BackupExpectation;
|
|
85
86
|
items: OperationPlanItem[];
|
|
@@ -108,6 +109,7 @@ export interface OperationApplyResult {
|
|
|
108
109
|
applied: boolean;
|
|
109
110
|
summary: string;
|
|
110
111
|
changedTargets: ManagedTarget[];
|
|
112
|
+
diagnosticTargets?: ManagedTarget[];
|
|
111
113
|
backups: OperationPath[];
|
|
112
114
|
warnings: OperationWarning[];
|
|
113
115
|
disclaimers: OperationDisclaimer[];
|
package/dist/cli/tui/index.js
CHANGED
|
@@ -2,8 +2,8 @@ import {
|
|
|
2
2
|
defaultTuiOperations,
|
|
3
3
|
effortChoicesForModel,
|
|
4
4
|
listOperationHarnesses
|
|
5
|
-
} from "../../chunk-
|
|
6
|
-
import "../../chunk-
|
|
5
|
+
} from "../../chunk-ASKXWU6E.js";
|
|
6
|
+
import "../../chunk-OZE7JVGS.js";
|
|
7
7
|
|
|
8
8
|
// src/cli/tui/index.tsx
|
|
9
9
|
import { render } from "ink";
|
|
@@ -255,11 +255,21 @@ function PathLine({ label, value, width }) {
|
|
|
255
255
|
|
|
256
256
|
// src/cli/tui/components/PlanPreview.tsx
|
|
257
257
|
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
258
|
+
function targetText(target) {
|
|
259
|
+
const label = target.label ?? target.path ?? target.kind;
|
|
260
|
+
const state = target.state ? `: [${target.state}]` : "";
|
|
261
|
+
const observed = target.observed ? ` - ${target.observed}` : "";
|
|
262
|
+
return `${label}${state}${observed}`;
|
|
263
|
+
}
|
|
264
|
+
function warningText(warning) {
|
|
265
|
+
return `[${warning.severity}]${warning.code ? ` [${warning.code}]` : ""} ${warning.message}`;
|
|
266
|
+
}
|
|
258
267
|
function PlanPreview({
|
|
259
268
|
plan,
|
|
260
269
|
selectedAction,
|
|
261
270
|
result
|
|
262
271
|
}) {
|
|
272
|
+
const blockerTargets = plan.blockerTargets ?? [];
|
|
263
273
|
return /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", children: [
|
|
264
274
|
/* @__PURE__ */ jsx6(Text6, { bold: true, children: plan.title }),
|
|
265
275
|
/* @__PURE__ */ jsx6(Text6, { children: plan.summary }),
|
|
@@ -275,6 +285,19 @@ function PlanPreview({
|
|
|
275
285
|
"Can apply: ",
|
|
276
286
|
plan.canApply ? "yes" : "no"
|
|
277
287
|
] }),
|
|
288
|
+
!plan.canApply && blockerTargets.length > 0 ? /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", children: [
|
|
289
|
+
/* @__PURE__ */ jsx6(Text6, { color: theme.warning, children: "Blocker targets" }),
|
|
290
|
+
blockerTargets.map((target, index) => /* @__PURE__ */ jsxs5(
|
|
291
|
+
Text6,
|
|
292
|
+
{
|
|
293
|
+
children: [
|
|
294
|
+
"- ",
|
|
295
|
+
targetText(target)
|
|
296
|
+
]
|
|
297
|
+
},
|
|
298
|
+
`${target.label ?? target.path ?? target.kind}-${index}`
|
|
299
|
+
))
|
|
300
|
+
] }) : null,
|
|
278
301
|
plan.surfaces.length > 0 ? /* @__PURE__ */ jsx6(Text6, { color: theme.dim, children: "Managed surfaces" }) : null,
|
|
279
302
|
plan.surfaces.map((surface) => /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", children: [
|
|
280
303
|
/* @__PURE__ */ jsxs5(Text6, { children: [
|
|
@@ -306,10 +329,8 @@ function PlanPreview({
|
|
|
306
329
|
" more items"
|
|
307
330
|
] }) : null,
|
|
308
331
|
plan.warnings.map((warning) => /* @__PURE__ */ jsxs5(Text6, { color: theme.warning, children: [
|
|
309
|
-
"-
|
|
310
|
-
warning
|
|
311
|
-
"] ",
|
|
312
|
-
warning.message
|
|
332
|
+
"- ",
|
|
333
|
+
warningText(warning)
|
|
313
334
|
] }, warning.code ?? warning.message)),
|
|
314
335
|
plan.disclaimers.map((disclaimer) => /* @__PURE__ */ jsxs5(Text6, { color: theme.dim, children: [
|
|
315
336
|
"- ",
|
|
@@ -321,7 +342,33 @@ function PlanPreview({
|
|
|
321
342
|
/* @__PURE__ */ jsx6(Text6, { color: selectedAction === "cancel" ? theme.accent : void 0, children: "[Cancel]" })
|
|
322
343
|
] }),
|
|
323
344
|
/* @__PURE__ */ jsx6(Text6, { color: theme.dim, children: "Enter selects. a applies. c cancels." }),
|
|
324
|
-
result ? /* @__PURE__ */
|
|
345
|
+
result ? /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", children: [
|
|
346
|
+
/* @__PURE__ */ jsx6(Text6, { color: result.applied ? theme.ok : theme.warning, children: result.summary }),
|
|
347
|
+
!result.applied && ((result.diagnosticTargets?.length ?? 0) > 0 || result.warnings.length > 0) ? /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", children: [
|
|
348
|
+
/* @__PURE__ */ jsx6(Text6, { color: theme.warning, children: "Apply diagnostics" }),
|
|
349
|
+
result.diagnosticTargets?.map((target, index) => /* @__PURE__ */ jsxs5(
|
|
350
|
+
Text6,
|
|
351
|
+
{
|
|
352
|
+
children: [
|
|
353
|
+
"- ",
|
|
354
|
+
targetText(target)
|
|
355
|
+
]
|
|
356
|
+
},
|
|
357
|
+
`${target.label ?? target.path ?? target.kind}-${index}`
|
|
358
|
+
)),
|
|
359
|
+
result.warnings.map((warning) => /* @__PURE__ */ jsxs5(
|
|
360
|
+
Text6,
|
|
361
|
+
{
|
|
362
|
+
color: theme.warning,
|
|
363
|
+
children: [
|
|
364
|
+
"- ",
|
|
365
|
+
warningText(warning)
|
|
366
|
+
]
|
|
367
|
+
},
|
|
368
|
+
warning.code ?? warning.message
|
|
369
|
+
))
|
|
370
|
+
] }) : null
|
|
371
|
+
] }) : null
|
|
325
372
|
] });
|
|
326
373
|
}
|
|
327
374
|
|
|
@@ -348,10 +395,23 @@ var categoryOrder = [
|
|
|
348
395
|
"Model state",
|
|
349
396
|
"Other"
|
|
350
397
|
];
|
|
398
|
+
function titleCasePart(part) {
|
|
399
|
+
const normalized = part.toLowerCase();
|
|
400
|
+
switch (normalized) {
|
|
401
|
+
case "sdd":
|
|
402
|
+
return "SDD";
|
|
403
|
+
case "cli":
|
|
404
|
+
return "CLI";
|
|
405
|
+
case "mcp":
|
|
406
|
+
return "MCP";
|
|
407
|
+
case "opencode":
|
|
408
|
+
return "OpenCode";
|
|
409
|
+
default:
|
|
410
|
+
return `${part.charAt(0).toUpperCase()}${part.slice(1).toLowerCase()}`;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
351
413
|
function titleCase(value, separator = " ") {
|
|
352
|
-
return value.split(/[-_\s]+/).filter(Boolean).map(
|
|
353
|
-
(part) => part.toLowerCase() === "sdd" ? "SDD" : part.toLowerCase() === "cli" ? "CLI" : part.toLowerCase() === "mcp" ? "MCP" : part.toLowerCase() === "opencode" ? "OpenCode" : `${part.charAt(0).toUpperCase()}${part.slice(1).toLowerCase()}`
|
|
354
|
-
).join(separator);
|
|
414
|
+
return value.split(/[-_\s]+/).filter(Boolean).map(titleCasePart).join(separator);
|
|
355
415
|
}
|
|
356
416
|
function compactPath(path) {
|
|
357
417
|
return path.replaceAll("\\", "/");
|
|
@@ -359,45 +419,56 @@ function compactPath(path) {
|
|
|
359
419
|
function categorizeTarget(target) {
|
|
360
420
|
const path = target.path ? compactPath(target.path) : "";
|
|
361
421
|
const label = target.label ?? target.kind;
|
|
422
|
+
const detail = target.state !== "installed" ? target.observed : void 0;
|
|
362
423
|
const agent = path.match(/thoth-agents-([a-z0-9_-]+)\.toml$/i);
|
|
363
424
|
const skill = path.match(/skills\/([^/]+)\/SKILL\.md$/i);
|
|
364
425
|
if (agent?.[1]) {
|
|
365
426
|
return {
|
|
366
427
|
category: "Agents",
|
|
367
428
|
label: titleCase(agent[1]),
|
|
368
|
-
state: target.state
|
|
429
|
+
state: target.state,
|
|
430
|
+
detail
|
|
369
431
|
};
|
|
370
432
|
}
|
|
371
433
|
if (skill?.[1] || target.kind === "skill") {
|
|
372
434
|
return {
|
|
373
435
|
category: "Skills",
|
|
374
|
-
label:
|
|
375
|
-
state: target.state
|
|
436
|
+
label: skill?.[1] ? titleCase(skill[1], "-") : label,
|
|
437
|
+
state: target.state,
|
|
438
|
+
detail
|
|
376
439
|
};
|
|
377
440
|
}
|
|
378
441
|
if (/marketplace\.json$/i.test(path)) {
|
|
379
442
|
return {
|
|
380
443
|
category: "Marketplace",
|
|
381
444
|
label: "Marketplace",
|
|
382
|
-
state: target.state
|
|
445
|
+
state: target.state,
|
|
446
|
+
detail
|
|
383
447
|
};
|
|
384
448
|
}
|
|
385
449
|
if (/\.mcp\.json$/i.test(path) || /plugin\.json$/i.test(path) || /plugin-assets/i.test(path) || /manifest/i.test(path)) {
|
|
386
450
|
return {
|
|
387
451
|
category: "Plugin/MCP",
|
|
388
452
|
label: titleCase(label.replace(/^codex\s+/i, "")),
|
|
389
|
-
state: target.state
|
|
453
|
+
state: target.state,
|
|
454
|
+
detail
|
|
390
455
|
};
|
|
391
456
|
}
|
|
392
457
|
if (/AGENTS\.md$/i.test(path) || /root instructions/i.test(label)) {
|
|
393
458
|
return {
|
|
394
459
|
category: "Root instructions",
|
|
395
460
|
label: "AGENTS.md",
|
|
396
|
-
state: target.state
|
|
461
|
+
state: target.state,
|
|
462
|
+
detail
|
|
397
463
|
};
|
|
398
464
|
}
|
|
399
465
|
if (/config\.toml$/i.test(path) || target.kind === "config") {
|
|
400
|
-
return {
|
|
466
|
+
return {
|
|
467
|
+
category: "Config",
|
|
468
|
+
label: titleCase(label),
|
|
469
|
+
state: target.state,
|
|
470
|
+
detail
|
|
471
|
+
};
|
|
401
472
|
}
|
|
402
473
|
if (target.kind === "memory-state" || /model/i.test(label)) {
|
|
403
474
|
return {
|
|
@@ -487,7 +558,9 @@ function StatusView({ report }) {
|
|
|
487
558
|
warnings.map((warning) => /* @__PURE__ */ jsxs6(Text7, { color: theme.warning, children: [
|
|
488
559
|
"- [",
|
|
489
560
|
warning.severity,
|
|
490
|
-
"]
|
|
561
|
+
"]",
|
|
562
|
+
warning.code ? ` [${warning.code}]` : "",
|
|
563
|
+
" ",
|
|
491
564
|
warning.message
|
|
492
565
|
] }, warning.code ?? warning.message)),
|
|
493
566
|
hiddenWarnings > 0 ? /* @__PURE__ */ jsxs6(Text7, { color: theme.dim, children: [
|
|
@@ -170,20 +170,19 @@ export declare const CODEX_SURFACES: readonly [{
|
|
|
170
170
|
readonly id: "per-agent-runtime-permissions";
|
|
171
171
|
readonly target: "permission-control";
|
|
172
172
|
readonly status: "unsupported";
|
|
173
|
-
readonly fields: ["per-agent tool allow/deny equivalent to OpenCode permissions"];
|
|
173
|
+
readonly fields: ["named installed-role selection", "per-role permission enforcement", "per-agent tool allow/deny equivalent to OpenCode permissions"];
|
|
174
174
|
readonly diagnosticCode: "codex.permission.memory.enforcement_gap";
|
|
175
|
-
readonly summary: "
|
|
175
|
+
readonly summary: "Named installed-role selection and per-role permission enforcement are instruction-only because collaboration.spawn_agent has no role selector; OpenCode-style per-agent MCP/tool deny maps are not validated.";
|
|
176
176
|
readonly evidence: "Codex approvals/security docs cover sandbox and approval policies, not exact OpenCode per-agent permission maps.";
|
|
177
177
|
readonly fallback: "instruction-only";
|
|
178
178
|
}, {
|
|
179
179
|
readonly id: "programmatic-delegation-runtime";
|
|
180
180
|
readonly target: "delegation-runtime";
|
|
181
|
-
readonly status: "
|
|
182
|
-
readonly fields: ["
|
|
183
|
-
readonly diagnosticCode: "codex.delegation.runtime.
|
|
184
|
-
readonly summary: "Codex
|
|
185
|
-
readonly evidence: "
|
|
186
|
-
readonly fallback: "instruction-only";
|
|
181
|
+
readonly status: "validated";
|
|
182
|
+
readonly fields: ["collaboration.spawn_agent", "collaboration.wait_agent", "collaboration.list_agents", "collaboration.send_message", "collaboration.followup_task", "collaboration.interrupt_agent"];
|
|
183
|
+
readonly diagnosticCode: "codex.delegation.runtime.validated";
|
|
184
|
+
readonly summary: "The current Codex collaboration surface supports generic programmatic delegation, mailbox waits, live task-tree inspection, messages, follow-up turns, and explicit interruption.";
|
|
185
|
+
readonly evidence: "The callable runtime exposes collaboration.spawn_agent with task_name, message, and optional fork_turns plus wait_agent, list_agents, send_message, followup_task, and interrupt_agent.";
|
|
187
186
|
}, {
|
|
188
187
|
readonly id: "parent-context-injection";
|
|
189
188
|
readonly target: "parent-context-injection";
|
|
@@ -15,6 +15,7 @@ export interface SddPhaseContract {
|
|
|
15
15
|
condition?: string;
|
|
16
16
|
defaultAgentRole?: AgentRoleName;
|
|
17
17
|
alternateAgentRoles?: AgentRoleName[];
|
|
18
|
+
alternateAgentCondition?: string;
|
|
18
19
|
supportingAgentRoles?: AgentRoleName[];
|
|
19
20
|
persistenceAgentRole?: AgentRoleName;
|
|
20
21
|
delegationReason?: string;
|
|
@@ -117,6 +118,7 @@ export declare const SDD_PHASES: readonly [{
|
|
|
117
118
|
readonly artifactSkill: "sdd-tasks";
|
|
118
119
|
readonly defaultAgentRole: "quick";
|
|
119
120
|
readonly alternateAgentRoles: ["deep"];
|
|
121
|
+
readonly alternateAgentCondition: "Only when the task plan is complex.";
|
|
120
122
|
readonly delegationReason: "Mechanical conversion of settled design into dependency-ordered execution tasks.";
|
|
121
123
|
}, {
|
|
122
124
|
readonly id: "plan-review";
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
renderOpenCodeAgentConfigs,
|
|
4
4
|
spawn,
|
|
5
5
|
spawnSync
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-6BNAV534.js";
|
|
7
7
|
import {
|
|
8
8
|
DEFAULT_THOTH_COMMAND,
|
|
9
9
|
POLL_INTERVAL_BACKGROUND_MS,
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
installCustomSkills,
|
|
15
15
|
loadPluginConfig,
|
|
16
16
|
stripJsonComments
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-OZE7JVGS.js";
|
|
18
18
|
|
|
19
19
|
// src/index.ts
|
|
20
20
|
import path4 from "path";
|