thoth-agents 0.11.0 → 0.12.0

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.
Files changed (68) hide show
  1. package/README.md +5 -3
  2. package/dist/agents/agent-config.d.ts +13 -0
  3. package/dist/agents/index.d.ts +1 -1
  4. package/dist/agents/orchestrator.d.ts +1 -1
  5. package/dist/{chunk-5WPP6IY7.js → chunk-7F33WUSD.js} +1 -1
  6. package/dist/{chunk-RWQPMWEM.js → chunk-JLU3FSBT.js} +17 -2
  7. package/dist/chunk-MIDGZE34.js +107 -0
  8. package/dist/{chunk-DNPKVFOB.js → chunk-NY2IPJ7V.js} +78 -87
  9. package/dist/{chunk-HACUJFKI.js → chunk-QOA2AETX.js} +2 -228
  10. package/dist/{chunk-I5TXGNSG.js → chunk-SEF6PFM6.js} +504 -211
  11. package/dist/cli/config-io.d.ts +2 -2
  12. package/dist/cli/index.js +92 -39
  13. package/dist/cli/install.d.ts +1 -0
  14. package/dist/cli/opencode-skill-consent.d.ts +5 -0
  15. package/dist/cli/operations/opencode.d.ts +2 -1
  16. package/dist/cli/operations/types.d.ts +1 -0
  17. package/dist/cli/owned-skills.d.ts +16 -0
  18. package/dist/cli/paths.d.ts +1 -1
  19. package/dist/cli/providers.d.ts +1 -1
  20. package/dist/cli/system.d.ts +3 -1
  21. package/dist/cli/thoth-mem-install.d.ts +10 -10
  22. package/dist/cli/tui/index.js +53 -5
  23. package/dist/cli/tui/operations.d.ts +2 -0
  24. package/dist/cli/types.d.ts +2 -4
  25. package/dist/config/loader.d.ts +1 -1
  26. package/dist/config/schema.d.ts +0 -31
  27. package/dist/harness/adapters/opencode.d.ts +1 -1
  28. package/dist/hooks/delegate-task-retry/hook.d.ts +8 -8
  29. package/dist/hooks/foreground-fallback/index.d.ts +14 -69
  30. package/dist/hooks/index.d.ts +0 -2
  31. package/dist/hooks/json-error-recovery/hook.d.ts +2 -15
  32. package/dist/hooks/oracle-gate-verdict/hook.d.ts +4 -11
  33. package/dist/index.d.ts +7 -4
  34. package/dist/index.js +822 -1421
  35. package/dist/opencode/agents.d.ts +3 -0
  36. package/dist/opencode/command.d.ts +3 -0
  37. package/dist/opencode/context.d.ts +20 -0
  38. package/dist/opencode/delegation-hooks.d.ts +3 -0
  39. package/dist/opencode/mcp.d.ts +3 -0
  40. package/dist/opencode/permission-rules.d.ts +9 -0
  41. package/dist/opencode/permissions.d.ts +3 -0
  42. package/dist/opencode/session-hooks.d.ts +3 -0
  43. package/dist/opencode/session-state.d.ts +39 -0
  44. package/dist/opencode/skills.d.ts +3 -0
  45. package/dist/opencode/tools.d.ts +3 -0
  46. package/dist/pi.js +3 -3
  47. package/dist/tools/ast-grep/cli.d.ts +1 -0
  48. package/dist/tools/ast-grep/index.d.ts +108 -2
  49. package/dist/tools/ast-grep/tools.d.ts +107 -3
  50. package/dist/tools/define-tool.d.ts +23 -0
  51. package/dist/tools/lsp/tools.d.ts +97 -5
  52. package/dist/utils/index.d.ts +0 -1
  53. package/package.json +14 -3
  54. package/plugin/.claude-plugin/plugin.json +1 -1
  55. package/plugin/.codex-plugin/plugin.json +1 -1
  56. package/plugin/skills/thoth-sdd/SKILL.md +8 -2
  57. package/plugin/skills/thoth-sdd/scripts/validate-result.mjs +28 -2
  58. package/skills/thoth-sdd/SKILL.md +8 -2
  59. package/skills/thoth-sdd/scripts/validate-result.mjs +28 -2
  60. package/thoth-agents.schema.json +0 -26
  61. package/dist/chunk-62L3ORXN.js +0 -30
  62. package/dist/delegation/project-id.d.ts +0 -10
  63. package/dist/hooks/auto-update-checker/checker.d.ts +0 -23
  64. package/dist/hooks/auto-update-checker/constants.d.ts +0 -11
  65. package/dist/hooks/auto-update-checker/index.d.ts +0 -17
  66. package/dist/hooks/auto-update-checker/types.d.ts +0 -22
  67. package/dist/utils/tmux-session-manager.d.ts +0 -63
  68. package/dist/utils/tmux.d.ts +0 -32
package/README.md CHANGED
@@ -46,7 +46,10 @@ verification you can follow—without manually coordinating every agent.
46
46
  - **Continuity between sessions.** Published installs include setup of
47
47
  [thoth-mem](https://github.com/EremesNG/thoth-mem), the independent memory
48
48
  companion for reusable decisions and project knowledge. thoth-mem owns its own
49
- memory lifecycle, persistence, and storage; thoth-agents only invokes its setup.
49
+ memory lifecycle, persistence, and storage; thoth-agents only invokes
50
+ `npx -y "thoth-mem@>=0.7.0" setup <harness> --json` (adding `--plan` for
51
+ dry-run). Only exit 0 with `planned` for dry-run or `complete` for apply is
52
+ successful; see [provider outcomes](docs/installation.md#thoth-mem-companion-setup).
50
53
 
51
54
  > [!NOTE]
52
55
  > OpenCode is the CLI's default harness. Pi is our recommendation for the best
@@ -62,7 +65,7 @@ The commands below install at **global/user scope**.
62
65
 
63
66
  | Harness | What you get | Install command |
64
67
  | --- | --- | --- |
65
- | <a href="https://github.com/anomalyco/opencode"><picture><source media="(prefers-color-scheme: dark)" srcset="https://svgl.app/library/opencode-dark.svg"><img src="https://svgl.app/library/opencode.svg" alt="OpenCode logo" width="48" height="48"></picture></a><br>**OpenCode** | Native plugin, agent team, workflow skills, and memory setup. | `npx thoth-agents@latest install --agent=opencode` |
68
+ | <a href="https://github.com/anomalyco/opencode"><picture><source media="(prefers-color-scheme: dark)" srcset="https://svgl.app/library/opencode-dark.svg"><img src="https://svgl.app/library/opencode.svg" alt="OpenCode logo" width="48" height="48"></picture></a><br>**OpenCode** | OpenCode >=2.2.6 native v2 plugin, package skills, agent team, and memory setup. | `npx thoth-agents@latest install --agent=opencode` |
66
69
  | <a href="https://github.com/openai/codex"><img src="https://github.com/openai.png?size=120" alt="OpenAI logo — Codex" width="48" height="48"></a><br>**Codex** | Native plugin plus the required global agent and instruction setup. **Close Codex first.** | `npx thoth-agents@latest install --agent=codex` |
67
70
  | <a href="https://claude.com/product/claude-code"><img src="https://github.com/anthropics.png?size=120" alt="Anthropic logo — Claude Code" width="48" height="48"></a><br>**Claude Code** | Marketplace agents and skills, completed by the CLI's external skills and memory setup. | `npx thoth-agents@latest install --agent=claude` |
68
71
  | <a href="https://github.com/earendil-works/pi"><img src="https://raw.githubusercontent.com/EremesNG/thoth-mem/master/img/pi.svg" alt="Pi logo" width="48" height="48"></a><br>**Pi** | Native package, five specialists, delegation, research, theme, sidebar and background-task extensions, workflow skills, and memory setup. **Recommended for the best experience.** | `npx thoth-agents@latest install --agent=pi` |
@@ -386,7 +389,6 @@ visible foreign-overlay focus. See [question controls](pi-packages/pi-questions-
386
389
  | [Codex Model Customization](docs/codex-model-customization.md) | Adjust Codex specialist models. |
387
390
  | [Claude Code Install](docs/claude-code-install.md) | Follow marketplace setup and activation. |
388
391
  | [Pi Setup](docs/installation.md#pi) | Check Pi dependencies, permissions, and recovery steps. |
389
- | [Tmux Integration](docs/tmux-integration.md) | Configure OpenCode's optional terminal-pane integration. |
390
392
 
391
393
  ### Technical guides
392
394
 
@@ -0,0 +1,13 @@
1
+ /** Internal role-rendering input; translated to the host's v2 Agent.Info at registration. */
2
+ export interface AgentConfig {
3
+ model?: string;
4
+ variant?: string;
5
+ temperature?: number;
6
+ prompt?: string;
7
+ description?: string;
8
+ mode?: 'primary' | 'subagent' | 'all';
9
+ hidden?: boolean;
10
+ color?: string;
11
+ steps?: number;
12
+ permission?: 'allow' | 'ask' | 'deny' | Record<string, 'allow' | 'ask' | 'deny' | Record<string, 'allow' | 'ask' | 'deny'>>;
13
+ }
@@ -1,5 +1,5 @@
1
- import type { AgentConfig as SDKAgentConfig } from '@opencode-ai/sdk/v2';
2
1
  import { type PluginConfig, SUBAGENT_NAMES } from '../config';
2
+ import type { AgentConfig as SDKAgentConfig } from './agent-config';
3
3
  import { type AgentDefinition } from './orchestrator';
4
4
  export type { AgentDefinition } from './orchestrator';
5
5
  export type SubagentName = (typeof SUBAGENT_NAMES)[number];
@@ -1,4 +1,4 @@
1
- import type { AgentConfig } from '@opencode-ai/sdk/v2';
1
+ import type { AgentConfig } from './agent-config';
2
2
  export interface AgentDefinition {
3
3
  name: string;
4
4
  description?: string;
@@ -19,7 +19,7 @@ import {
19
19
  renderAgentRoutingDescription,
20
20
  renderPromptSection,
21
21
  renderRolePrompt
22
- } from "./chunk-DNPKVFOB.js";
22
+ } from "./chunk-NY2IPJ7V.js";
23
23
 
24
24
  // src/harness/writers/pi-agent.ts
25
25
  var PI_MANAGED_OWNER = "thoth-agents";
@@ -332,12 +332,27 @@ function checkExpectations(options, issue) {
332
332
  "Expected digest must be 64 lowercase hex characters."
333
333
  );
334
334
  }
335
+ var isFenceLine = (line) => /^(?:`{3,}|~{3,})/.test(line);
336
+ var isVerdictLine = (line) => line.startsWith("thoth-gate-verdict ");
337
+ function unwrapSubagent(message, lines) {
338
+ if (!message.startsWith("<subagent ")) return message;
339
+ if (lines.at(-1) !== "</subagent>") return "";
340
+ const opener = lines.lastIndexOf("```thoth-result");
341
+ if (opener < 1) return "";
342
+ const header = lines.slice(0, opener).join("\n").trimEnd();
343
+ if (!header.includes('state="completed"') || lines.slice(0, opener).some((line) => isFenceLine(line) || isVerdictLine(line)))
344
+ return "";
345
+ return lines.slice(opener, -1).join("\n").trim();
346
+ }
335
347
  function parseEnvelope(message) {
336
- const trimmed = typeof message === "string" ? message.trim() : "";
348
+ const complete = typeof message === "string" ? message.trim() : "";
349
+ const lines = complete.split(/\r\n|\r|\n/);
350
+ const singleEnvelope = lines.filter(isFenceLine).length === 2 && !lines.some(isVerdictLine);
351
+ const trimmed = singleEnvelope ? unwrapSubagent(complete, lines) : "";
337
352
  const block = new RegExp(
338
353
  `^\`\`\`${result_contract_default.fence}\\r?\\n([\\s\\S]*?)\\r?\\n\`\`\`$`
339
354
  ).exec(trimmed);
340
- if (!block || (trimmed.match(/^```.*$/gm) ?? []).length !== 2) {
355
+ if (!block) {
341
356
  return {
342
357
  issues: [
343
358
  {
@@ -0,0 +1,107 @@
1
+ // src/mcp/context7.ts
2
+ var CONTEXT7_MCP_URL = "https://mcp.context7.com/mcp";
3
+ var context7 = {
4
+ type: "remote",
5
+ url: CONTEXT7_MCP_URL,
6
+ headers: process.env.CONTEXT7_API_KEY ? { CONTEXT7_API_KEY: process.env.CONTEXT7_API_KEY } : void 0,
7
+ oauth: false
8
+ };
9
+
10
+ // src/mcp/exa.ts
11
+ var exa = {
12
+ type: "local",
13
+ command: ["npx", "-y", "exa-mcp-server"]
14
+ };
15
+
16
+ // src/mcp/grep-app.ts
17
+ var GREP_APP_MCP_URL = "https://mcp.grep.app";
18
+ var grep_app = {
19
+ type: "remote",
20
+ url: GREP_APP_MCP_URL,
21
+ oauth: false
22
+ };
23
+
24
+ // src/utils/subprocess.ts
25
+ import {
26
+ spawn as nodeSpawn,
27
+ spawnSync as nodeSpawnSync
28
+ } from "child_process";
29
+ import { Readable } from "stream";
30
+ function emptyReadableStream() {
31
+ return new ReadableStream({
32
+ start(controller) {
33
+ controller.close();
34
+ }
35
+ });
36
+ }
37
+ function toWebReadable(stream) {
38
+ if (!stream) {
39
+ return emptyReadableStream();
40
+ }
41
+ return Readable.toWeb(
42
+ stream
43
+ );
44
+ }
45
+ function fallbackStdin() {
46
+ return {
47
+ write: () => void 0,
48
+ end: () => void 0
49
+ };
50
+ }
51
+ function spawn(command, options = {}) {
52
+ const child = nodeSpawn(command[0], command.slice(1), {
53
+ cwd: options.cwd,
54
+ env: options.env,
55
+ stdio: [
56
+ options.stdin ?? "pipe",
57
+ options.stdout ?? "pipe",
58
+ options.stderr ?? "pipe"
59
+ ],
60
+ shell: options.shell,
61
+ windowsHide: options.windowsHide ?? true
62
+ });
63
+ const managed = {
64
+ stdin: child.stdin ?? fallbackStdin(),
65
+ stdout: toWebReadable(child.stdout),
66
+ stderr: toWebReadable(child.stderr),
67
+ exited: new Promise((resolve) => {
68
+ child.on("exit", (code) => {
69
+ managed.exitCode = code;
70
+ resolve(code ?? 1);
71
+ });
72
+ child.on("error", () => {
73
+ managed.exitCode = 1;
74
+ resolve(1);
75
+ });
76
+ }),
77
+ exitCode: child.exitCode,
78
+ kill: () => {
79
+ child.kill();
80
+ }
81
+ };
82
+ return managed;
83
+ }
84
+ function spawnSync(command, options = {}) {
85
+ const result = nodeSpawnSync(command[0], command.slice(1), {
86
+ cwd: options.cwd,
87
+ env: options.env,
88
+ stdio: [
89
+ options.stdin ?? "ignore",
90
+ options.stdout ?? "pipe",
91
+ options.stderr ?? "pipe"
92
+ ],
93
+ shell: options.shell,
94
+ windowsHide: options.windowsHide ?? true
95
+ });
96
+ return { exitCode: result.status };
97
+ }
98
+
99
+ export {
100
+ CONTEXT7_MCP_URL,
101
+ context7,
102
+ exa,
103
+ GREP_APP_MCP_URL,
104
+ grep_app,
105
+ spawn,
106
+ spawnSync
107
+ };
@@ -19,20 +19,6 @@ function findPackageRoot(startDir) {
19
19
  }
20
20
  }
21
21
 
22
- // src/config/loader.ts
23
- import * as fs from "fs";
24
- import * as path from "path";
25
-
26
- // src/cli/config-io.ts
27
- import {
28
- copyFileSync,
29
- existsSync as existsSync3,
30
- readFileSync as readFileSync2,
31
- renameSync,
32
- statSync,
33
- writeFileSync
34
- } from "fs";
35
-
36
22
  // src/config/constants.ts
37
23
  var SUBAGENT_NAMES = [
38
24
  "explorer",
@@ -99,7 +85,6 @@ function getDefaultOpenCodeVariant(name) {
99
85
  }
100
86
  return CONFIRMED_OPENAI_SUBAGENT_PRESET[name].effort;
101
87
  }
102
- var POLL_INTERVAL_BACKGROUND_MS = 2e3;
103
88
  var DEFAULT_TIMEOUT_MS = 2 * 60 * 1e3;
104
89
  var MAX_POLL_TIME_MS = 5 * 60 * 1e3;
105
90
 
@@ -195,27 +180,41 @@ function resolveExecutingPackageVersion(options = {}) {
195
180
  return { ok: true, version, packageRoot };
196
181
  }
197
182
 
183
+ // src/config/loader.ts
184
+ import * as fs from "fs";
185
+ import * as path from "path";
186
+
187
+ // src/cli/config-io.ts
188
+ import {
189
+ copyFileSync,
190
+ existsSync as existsSync3,
191
+ readFileSync as readFileSync2,
192
+ renameSync,
193
+ statSync,
194
+ writeFileSync
195
+ } from "fs";
196
+
198
197
  // src/cli/paths.ts
199
198
  import { existsSync as existsSync2, mkdirSync } from "fs";
200
199
  import { homedir } from "os";
201
200
  import { dirname as dirname3, join as join3 } from "path";
202
- function getDefaultOpenCodeConfigDir() {
203
- const userConfigDir = process.env.XDG_CONFIG_HOME ? process.env.XDG_CONFIG_HOME : join3(homedir(), ".config");
201
+ function getDefaultOpenCodeConfigDir(homeDir) {
202
+ const userConfigDir = process.env.XDG_CONFIG_HOME ? process.env.XDG_CONFIG_HOME : join3(homeDir, ".config");
204
203
  return join3(userConfigDir, "opencode");
205
204
  }
206
205
  function getCustomOpenCodeConfigDir() {
207
206
  const configDir = process.env.OPENCODE_CONFIG_DIR?.trim();
208
207
  return configDir || void 0;
209
208
  }
210
- function getConfigDir() {
209
+ function getConfigDir(homeDir = homedir()) {
211
210
  const customConfigDir = getCustomOpenCodeConfigDir();
212
211
  if (customConfigDir) {
213
212
  return customConfigDir;
214
213
  }
215
- return getDefaultOpenCodeConfigDir();
214
+ return getDefaultOpenCodeConfigDir(homeDir);
216
215
  }
217
216
  function getOpenCodeConfigPaths() {
218
- const configDir = getDefaultOpenCodeConfigDir();
217
+ const configDir = getConfigDir();
219
218
  return [join3(configDir, "opencode.json"), join3(configDir, "opencode.jsonc")];
220
219
  }
221
220
  function getConfigJson() {
@@ -328,24 +327,6 @@ var AgentOverrideConfigSchema = z.object({
328
327
  steps: z.number().int().min(1).optional(),
329
328
  variant: z.string().optional().catch(void 0)
330
329
  });
331
- var TmuxLayoutSchema = z.enum([
332
- "main-horizontal",
333
- // Main pane on top, agents stacked below
334
- "main-vertical",
335
- // Main pane on left, agents stacked on right
336
- "tiled",
337
- // All panes equal size grid
338
- "even-horizontal",
339
- // All panes side by side
340
- "even-vertical"
341
- // All panes stacked vertically
342
- ]);
343
- var TmuxConfigSchema = z.object({
344
- enabled: z.boolean().default(false),
345
- layout: TmuxLayoutSchema.default("main-vertical"),
346
- main_pane_size: z.number().min(20).max(80).default(60)
347
- // percentage for main pane
348
- });
349
330
  var PresetSchema = z.record(
350
331
  SupportedAgentRecordKeySchema,
351
332
  AgentOverrideConfigSchema
@@ -378,7 +359,6 @@ var PluginConfigSchema = z.object({
378
359
  presets: z.record(z.string(), PresetSchema).optional(),
379
360
  agents: z.record(SupportedAgentRecordKeySchema, AgentOverrideConfigSchema).optional(),
380
361
  disabled_mcps: z.array(z.string()).optional(),
381
- tmux: TmuxConfigSchema.optional(),
382
362
  fallback: FailoverConfigSchema.optional(),
383
363
  codex: CodexGenerationConfigSchema.optional(),
384
364
  claudeCode: ClaudeCodeGenerationConfigSchema.optional()
@@ -418,7 +398,7 @@ function buildOpenAIModelMappings() {
418
398
  var MODEL_MAPPINGS = {
419
399
  openai: buildOpenAIModelMappings()
420
400
  };
421
- function generateLiteConfig(installConfig) {
401
+ function generateLiteConfig(_installConfig) {
422
402
  const config = {
423
403
  $schema: THOTH_AGENTS_CONFIG_SCHEMA_URL,
424
404
  preset: "openai",
@@ -440,13 +420,6 @@ function generateLiteConfig(installConfig) {
440
420
  );
441
421
  };
442
422
  config.presets.openai = buildPreset("openai");
443
- if (installConfig.hasTmux) {
444
- config.tmux = {
445
- enabled: true,
446
- layout: "main-vertical",
447
- main_pane_size: 60
448
- };
449
- }
450
423
  return config;
451
424
  }
452
425
 
@@ -500,24 +473,32 @@ function writeConfig(configPath, config) {
500
473
  writeFileSync(tmpPath, content);
501
474
  renameSync(tmpPath, configPath);
502
475
  }
476
+ function pluginEntries(value) {
477
+ return Array.isArray(value) ? value : [];
478
+ }
479
+ function isManagedOpenCodePlugin(entry) {
480
+ const name = typeof entry === "string" ? entry : Array.isArray(entry) ? entry[0] : entry && typeof entry === "object" && "package" in entry ? entry.package : void 0;
481
+ return typeof name === "string" && (name === PACKAGE_NAME || name.startsWith(`${PACKAGE_NAME}@`));
482
+ }
483
+ function hasManagedPluginOptions(entry) {
484
+ if (!isManagedOpenCodePlugin(entry)) return false;
485
+ const options = Array.isArray(entry) ? entry[1] : entry && typeof entry === "object" && "options" in entry ? entry.options : void 0;
486
+ return !!options && typeof options === "object" && Object.keys(options).length > 0;
487
+ }
503
488
  function mergeOpenCodeMainConfig(config, update) {
504
489
  if (update.ensurePlugin) {
505
- const plugins = Array.isArray(config.plugin) ? config.plugin : [];
506
- config.plugin = [
507
- ...plugins.filter(
508
- (plugin) => plugin !== PACKAGE_NAME && !plugin.startsWith(`${PACKAGE_NAME}@`)
490
+ const legacy = pluginEntries(config.plugin).filter(
491
+ (entry) => !isManagedOpenCodePlugin(entry)
492
+ );
493
+ if (legacy.length > 0) config.plugin = legacy;
494
+ else delete config.plugin;
495
+ config.plugins = [
496
+ ...pluginEntries(config.plugins).filter(
497
+ (entry) => !isManagedOpenCodePlugin(entry)
509
498
  ),
510
499
  `${PACKAGE_NAME}@${update.pluginVersion}`
511
500
  ];
512
501
  }
513
- if (update.disableDefaults) {
514
- const agent = config.agent && typeof config.agent === "object" ? { ...config.agent } : {};
515
- const explore = agent.explore && typeof agent.explore === "object" ? { ...agent.explore } : {};
516
- const general = agent.general && typeof agent.general === "object" ? { ...agent.general } : {};
517
- agent.explore = { ...explore, disable: true };
518
- agent.general = { ...general, disable: true };
519
- config.agent = agent;
520
- }
521
502
  return config;
522
503
  }
523
504
  function updateOpenCodeMainConfig(update) {
@@ -547,10 +528,19 @@ function updateOpenCodeMainConfig(update) {
547
528
  error: `Failed to parse config: ${error}`
548
529
  };
549
530
  }
531
+ const removedOptions = update.ensurePlugin && [
532
+ ...pluginEntries(parsedConfig?.plugin),
533
+ ...pluginEntries(parsedConfig?.plugins)
534
+ ].some(hasManagedPluginOptions);
550
535
  writeConfig(
551
536
  configPath,
552
537
  mergeOpenCodeMainConfig(parsedConfig ?? {}, update)
553
538
  );
539
+ if (removedOptions) {
540
+ console.warn(
541
+ `[config-manager] Removed non-empty thoth-agents plugin options while pinning the v2 plugin. Original entries are preserved in ${configPath}.bak; configure the plugin via thoth-agents.json instead.`
542
+ );
543
+ }
554
544
  return { success: true, configPath };
555
545
  } catch (err) {
556
546
  return {
@@ -634,13 +624,14 @@ function writeLiteConfig(installConfig, targetPath) {
634
624
  function detectCurrentConfig() {
635
625
  const result = {
636
626
  isInstalled: false,
637
- hasOpenAI: false,
638
- hasTmux: false
627
+ hasOpenAI: false
639
628
  };
640
629
  const { config } = parseConfig(getExistingConfigPath());
641
630
  if (!config) return result;
642
- const plugins = config.plugin ?? [];
643
- result.isInstalled = plugins.some((p) => p.startsWith(PACKAGE_NAME));
631
+ result.isInstalled = [
632
+ ...pluginEntries(config.plugin),
633
+ ...pluginEntries(config.plugins)
634
+ ].some(isManagedOpenCodePlugin);
644
635
  const { config: liteConfig } = parseConfig(getLiteConfig());
645
636
  if (liteConfig && typeof liteConfig === "object") {
646
637
  const configObj = liteConfig;
@@ -651,10 +642,6 @@ function detectCurrentConfig() {
651
642
  const models = Object.values(agents).map((a) => a?.model).filter(Boolean);
652
643
  result.hasOpenAI = models.some((m) => m?.startsWith("openai/"));
653
644
  }
654
- if (configObj.tmux && typeof configObj.tmux === "object") {
655
- const tmuxConfig = configObj.tmux;
656
- result.hasTmux = tmuxConfig.enabled === true;
657
- }
658
645
  }
659
646
  return result;
660
647
  }
@@ -727,7 +714,6 @@ function loadPluginConfig(directory) {
727
714
  ...config,
728
715
  ...projectConfig,
729
716
  agents: deepMerge(config.agents, projectConfig.agents),
730
- tmux: deepMerge(config.tmux, projectConfig.tmux),
731
717
  fallback: deepMerge(config.fallback, projectConfig.fallback),
732
718
  codex: deepMerge(config.codex, projectConfig.codex),
733
719
  claudeCode: deepMerge(config.claudeCode, projectConfig.claudeCode)
@@ -1381,25 +1367,30 @@ function piCapabilityDisclosure(capability) {
1381
1367
  }
1382
1368
  var OPENCODE_PROMPT_DIALECT = {
1383
1369
  harness: "opencode",
1384
- gateDeliveryInstruction: "Delivery verdicts are appended to Oracle `task` output.",
1370
+ gateDeliveryInstruction: "Foreground Oracle `subagent` gates get one `thoth-gate-verdict` line; background completions have none: use the explicit compact validator fallback.",
1385
1371
  tools: {
1386
- delegationTool: "task",
1387
- backgroundDelegationTool: "task(background=true)",
1388
- backgroundStatusTool: "task_status",
1372
+ delegationTool: "subagent",
1373
+ backgroundDelegationTool: "subagent(background:true)",
1374
+ backgroundWaitInstruction: 'Native `<subagent sessionID=... state="completed">` completion wakes root. No status polling tool exists; never poll/sleep.',
1389
1375
  userQuestionTool: "question",
1390
1376
  progressTool: "todowrite",
1391
- hostStatusSurface: "task_status",
1377
+ hostStatusSurface: "native subagent completion messages",
1392
1378
  lifecycle: {
1393
- freshDelegation: "`task` without `task_id`",
1394
- sameAssignmentContinuation: "`task` with the prior `task_id`",
1395
- independentContext: "omitting `task_id` creates an isolated child session",
1396
- statusAction: "wait, poll, and collect",
1397
- terminalState: "terminal task_status result",
1398
- nonterminalState: "nonterminal task_status result",
1399
- sameSessionProbe: "task_status on the same task session",
1379
+ rootInstructions: [
1380
+ "- New objectives, phases, work units, mutable surfaces or independent judgments require fresh specialist sessions via `subagent` (agent, description, prompt; omit sessionID). These are fresh-session boundaries, not permission for root execution; never pool completed agents.",
1381
+ "- Use sessionID only to continue/clarify the same assignment, including while running. Optional model; background:true for independent work. Default nesting depth is 1.",
1382
+ "- Every Oracle plan review, verification round, and PASS judgment uses a fresh Oracle instance. Existing ones only clarify their findings."
1383
+ ].join("\n"),
1384
+ freshDelegation: "`subagent` with agent, description and prompt, omitting sessionID",
1385
+ sameAssignmentContinuation: "`subagent` with the prior sessionID, including while running",
1386
+ independentContext: "omitting sessionID creates an isolated child session",
1387
+ statusAction: "receive native completion automatically; never poll",
1388
+ terminalState: "a completed subagent result/message",
1389
+ nonterminalState: "a running placeholder",
1390
+ sameSessionProbe: "continue or clarify with subagent and the same sessionID; never ask for status",
1400
1391
  enforcement: "runtime-supported"
1401
1392
  },
1402
- roleReference: (role) => `@${role}`
1393
+ roleReference: (role) => `subagent agent:"${role}"`
1403
1394
  },
1404
1395
  capabilities: supportedCapabilityProfile(OPENCODE_CAPABILITIES),
1405
1396
  dispatchLabel(method) {
@@ -1407,11 +1398,11 @@ var OPENCODE_PROMPT_DIALECT = {
1407
1398
  case "root-coordinator":
1408
1399
  return "root coordinator";
1409
1400
  case "task":
1410
- return "task";
1401
+ return "subagent";
1411
1402
  }
1412
1403
  },
1413
1404
  renderRoleInvocation(role) {
1414
- return `@${role}`;
1405
+ return `subagent agent:"${role}"`;
1415
1406
  }
1416
1407
  };
1417
1408
  var CODEX_PROMPT_DIALECT = {
@@ -2231,7 +2222,7 @@ Use \`${dialect.tools.userQuestionTool}\` only for a blocking material choice, d
2231
2222
  }
2232
2223
  function renderSubagentRules(section, dialect) {
2233
2224
  const rules = [
2234
- dialect.tools.progressTool ? `- Do not delegate further or call \`${dialect.tools.progressTool}\`; root owns progress.` : "- Do not delegate further; root owns progress.",
2225
+ dialect.harness === "opencode" ? "- Do not delegate further; no `todowrite` (root-owned)." : dialect.tools.progressTool ? `- Do not delegate further or call \`${dialect.tools.progressTool}\`; root owns progress.` : "- Do not delegate further; root owns progress.",
2235
2226
  "- Use terminating checks; avoid watch processes and indefinite waits.",
2236
2227
  "- Preserve operator-selected model/effort. Stop after the assigned outcome and checks; never expand scope to fill a timeout.",
2237
2228
  "- After two consecutive attempts without new evidence or progress, return partial evidence and the smallest blocker; do not repeat searches or unchanged failing commands.",
@@ -2428,19 +2419,19 @@ export {
2428
2419
  DEFAULT_MODELS,
2429
2420
  getDefaultOpenCodeModel,
2430
2421
  getDefaultOpenCodeVariant,
2431
- POLL_INTERVAL_BACKGROUND_MS,
2432
2422
  findPackageRoot,
2433
2423
  isValidPackageVersion,
2434
2424
  resolveExecutingPackageVersion,
2435
- getOpenCodeConfigPaths,
2425
+ getConfigDir,
2436
2426
  getOpenCodeManagedModelStatePath,
2437
2427
  getExistingLiteConfigPath,
2438
2428
  getExistingConfigPath,
2439
2429
  ensureConfigDir,
2440
2430
  generateLiteConfig,
2441
- stripJsonComments,
2442
2431
  parseConfig,
2443
2432
  writeConfig,
2433
+ pluginEntries,
2434
+ isManagedOpenCodePlugin,
2444
2435
  updateOpenCodeMainConfig,
2445
2436
  writeLiteConfig,
2446
2437
  detectCurrentConfig,