@agentuity/opencode 0.1.39 → 0.1.41

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 (161) hide show
  1. package/README.md +321 -9
  2. package/dist/agents/architect.d.ts +4 -0
  3. package/dist/agents/architect.d.ts.map +1 -0
  4. package/dist/agents/architect.js +259 -0
  5. package/dist/agents/architect.js.map +1 -0
  6. package/dist/agents/builder.d.ts +1 -1
  7. package/dist/agents/builder.d.ts.map +1 -1
  8. package/dist/agents/builder.js +44 -1
  9. package/dist/agents/builder.js.map +1 -1
  10. package/dist/agents/index.d.ts.map +1 -1
  11. package/dist/agents/index.js +6 -0
  12. package/dist/agents/index.js.map +1 -1
  13. package/dist/agents/lead.d.ts +1 -1
  14. package/dist/agents/lead.d.ts.map +1 -1
  15. package/dist/agents/lead.js +183 -19
  16. package/dist/agents/lead.js.map +1 -1
  17. package/dist/agents/planner.d.ts +4 -0
  18. package/dist/agents/planner.d.ts.map +1 -0
  19. package/dist/agents/planner.js +158 -0
  20. package/dist/agents/planner.js.map +1 -0
  21. package/dist/agents/runner.d.ts +4 -0
  22. package/dist/agents/runner.d.ts.map +1 -0
  23. package/dist/agents/runner.js +364 -0
  24. package/dist/agents/runner.js.map +1 -0
  25. package/dist/agents/types.d.ts +5 -1
  26. package/dist/agents/types.d.ts.map +1 -1
  27. package/dist/background/concurrency.d.ts +36 -0
  28. package/dist/background/concurrency.d.ts.map +1 -0
  29. package/dist/background/concurrency.js +92 -0
  30. package/dist/background/concurrency.js.map +1 -0
  31. package/dist/background/index.d.ts +5 -0
  32. package/dist/background/index.d.ts.map +1 -0
  33. package/dist/background/index.js +4 -0
  34. package/dist/background/index.js.map +1 -0
  35. package/dist/background/manager.d.ts +54 -0
  36. package/dist/background/manager.d.ts.map +1 -0
  37. package/dist/background/manager.js +409 -0
  38. package/dist/background/manager.js.map +1 -0
  39. package/dist/background/types.d.ts +47 -0
  40. package/dist/background/types.d.ts.map +1 -0
  41. package/dist/background/types.js +2 -0
  42. package/dist/background/types.js.map +1 -0
  43. package/dist/config/index.d.ts +2 -0
  44. package/dist/config/index.d.ts.map +1 -1
  45. package/dist/config/index.js +2 -0
  46. package/dist/config/index.js.map +1 -1
  47. package/dist/config/loader.d.ts +24 -0
  48. package/dist/config/loader.d.ts.map +1 -1
  49. package/dist/config/loader.js +102 -23
  50. package/dist/config/loader.js.map +1 -1
  51. package/dist/config/presets.d.ts +16 -0
  52. package/dist/config/presets.d.ts.map +1 -0
  53. package/dist/config/presets.js +20 -0
  54. package/dist/config/presets.js.map +1 -0
  55. package/dist/config/validation.d.ts +26 -0
  56. package/dist/config/validation.d.ts.map +1 -0
  57. package/dist/config/validation.js +48 -0
  58. package/dist/config/validation.js.map +1 -0
  59. package/dist/index.d.ts +1 -1
  60. package/dist/index.d.ts.map +1 -1
  61. package/dist/index.js.map +1 -1
  62. package/dist/plugin/hooks/keyword.d.ts.map +1 -1
  63. package/dist/plugin/hooks/keyword.js +3 -0
  64. package/dist/plugin/hooks/keyword.js.map +1 -1
  65. package/dist/plugin/plugin.d.ts.map +1 -1
  66. package/dist/plugin/plugin.js +297 -36
  67. package/dist/plugin/plugin.js.map +1 -1
  68. package/dist/skills/frontmatter.d.ts +7 -0
  69. package/dist/skills/frontmatter.d.ts.map +1 -0
  70. package/dist/skills/frontmatter.js +17 -0
  71. package/dist/skills/frontmatter.js.map +1 -0
  72. package/dist/skills/index.d.ts +4 -0
  73. package/dist/skills/index.d.ts.map +1 -0
  74. package/dist/skills/index.js +4 -0
  75. package/dist/skills/index.js.map +1 -0
  76. package/dist/skills/loader.d.ts +20 -0
  77. package/dist/skills/loader.d.ts.map +1 -0
  78. package/dist/skills/loader.js +152 -0
  79. package/dist/skills/loader.js.map +1 -0
  80. package/dist/skills/types.d.ts +41 -0
  81. package/dist/skills/types.d.ts.map +1 -0
  82. package/dist/skills/types.js +2 -0
  83. package/dist/skills/types.js.map +1 -0
  84. package/dist/tmux/decision-engine.d.ts +24 -0
  85. package/dist/tmux/decision-engine.d.ts.map +1 -0
  86. package/dist/tmux/decision-engine.js +193 -0
  87. package/dist/tmux/decision-engine.js.map +1 -0
  88. package/dist/tmux/executor.d.ts +56 -0
  89. package/dist/tmux/executor.d.ts.map +1 -0
  90. package/dist/tmux/executor.js +231 -0
  91. package/dist/tmux/executor.js.map +1 -0
  92. package/dist/tmux/index.d.ts +7 -0
  93. package/dist/tmux/index.d.ts.map +1 -0
  94. package/dist/tmux/index.js +7 -0
  95. package/dist/tmux/index.js.map +1 -0
  96. package/dist/tmux/manager.d.ts +80 -0
  97. package/dist/tmux/manager.d.ts.map +1 -0
  98. package/dist/tmux/manager.js +276 -0
  99. package/dist/tmux/manager.js.map +1 -0
  100. package/dist/tmux/state-query.d.ts +7 -0
  101. package/dist/tmux/state-query.d.ts.map +1 -0
  102. package/dist/tmux/state-query.js +67 -0
  103. package/dist/tmux/state-query.js.map +1 -0
  104. package/dist/tmux/types.d.ts +96 -0
  105. package/dist/tmux/types.d.ts.map +1 -0
  106. package/dist/tmux/types.js +8 -0
  107. package/dist/tmux/types.js.map +1 -0
  108. package/dist/tmux/utils.d.ts +32 -0
  109. package/dist/tmux/utils.d.ts.map +1 -0
  110. package/dist/tmux/utils.js +80 -0
  111. package/dist/tmux/utils.js.map +1 -0
  112. package/dist/tools/background.d.ts +61 -0
  113. package/dist/tools/background.d.ts.map +1 -0
  114. package/dist/tools/background.js +78 -0
  115. package/dist/tools/background.js.map +1 -0
  116. package/dist/tools/delegate.d.ts +6 -0
  117. package/dist/tools/delegate.d.ts.map +1 -1
  118. package/dist/tools/delegate.js +8 -2
  119. package/dist/tools/delegate.js.map +1 -1
  120. package/dist/tools/index.d.ts +1 -0
  121. package/dist/tools/index.d.ts.map +1 -1
  122. package/dist/tools/index.js +1 -0
  123. package/dist/tools/index.js.map +1 -1
  124. package/dist/types.d.ts +118 -18
  125. package/dist/types.d.ts.map +1 -1
  126. package/dist/types.js +49 -7
  127. package/dist/types.js.map +1 -1
  128. package/package.json +4 -3
  129. package/src/agents/architect.ts +262 -0
  130. package/src/agents/builder.ts +44 -1
  131. package/src/agents/index.ts +6 -0
  132. package/src/agents/lead.ts +183 -19
  133. package/src/agents/planner.ts +161 -0
  134. package/src/agents/runner.ts +367 -0
  135. package/src/agents/types.ts +5 -1
  136. package/src/background/concurrency.ts +116 -0
  137. package/src/background/index.ts +4 -0
  138. package/src/background/manager.ts +478 -0
  139. package/src/background/types.ts +52 -0
  140. package/src/config/index.ts +2 -0
  141. package/src/config/loader.ts +128 -31
  142. package/src/config/presets.ts +21 -0
  143. package/src/config/validation.ts +70 -0
  144. package/src/index.ts +1 -0
  145. package/src/plugin/hooks/keyword.ts +3 -0
  146. package/src/plugin/plugin.ts +323 -42
  147. package/src/skills/frontmatter.ts +25 -0
  148. package/src/skills/index.ts +3 -0
  149. package/src/skills/loader.ts +185 -0
  150. package/src/skills/types.ts +43 -0
  151. package/src/tmux/decision-engine.ts +246 -0
  152. package/src/tmux/executor.ts +286 -0
  153. package/src/tmux/index.ts +11 -0
  154. package/src/tmux/manager.ts +331 -0
  155. package/src/tmux/state-query.ts +74 -0
  156. package/src/tmux/types.ts +106 -0
  157. package/src/tmux/utils.ts +85 -0
  158. package/src/tools/background.ts +145 -0
  159. package/src/tools/delegate.ts +8 -2
  160. package/src/tools/index.ts +9 -0
  161. package/src/types.ts +88 -15
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Information about a tmux pane
3
+ */
4
+ export interface TmuxPaneInfo {
5
+ paneId: string; // e.g., %0, %1
6
+ width: number; // Columns
7
+ height: number; // Rows
8
+ left: number; // Position from left
9
+ top: number; // Position from top
10
+ title: string; // Pane title
11
+ isActive: boolean; // Is this the active pane?
12
+ }
13
+
14
+ /**
15
+ * Current state of the tmux window
16
+ */
17
+ export interface WindowState {
18
+ windowWidth: number;
19
+ windowHeight: number;
20
+ mainPane: TmuxPaneInfo | null; // The pane running the main agent
21
+ agentPanes: TmuxPaneInfo[]; // Panes for background agents
22
+ }
23
+
24
+ /**
25
+ * Tracked session for a background agent in tmux
26
+ */
27
+ export interface TrackedSession {
28
+ sessionId: string; // OpenCode session ID
29
+ paneId: string; // Tmux pane ID
30
+ description: string; // Task description
31
+ createdAt: Date;
32
+ lastSeenAt: Date;
33
+ }
34
+
35
+ /**
36
+ * Direction for splitting panes
37
+ */
38
+ export type SplitDirection = '-h' | '-v'; // -h = horizontal (side by side), -v = vertical (stacked)
39
+
40
+ /**
41
+ * Actions for managing panes
42
+ */
43
+ export type PaneAction =
44
+ | {
45
+ type: 'spawn';
46
+ sessionId: string;
47
+ description: string;
48
+ targetPaneId: string;
49
+ splitDirection: SplitDirection;
50
+ }
51
+ | { type: 'close'; paneId: string; sessionId: string }
52
+ | {
53
+ type: 'replace';
54
+ paneId: string;
55
+ oldSessionId: string;
56
+ newSessionId: string;
57
+ description: string;
58
+ };
59
+
60
+ /**
61
+ * Decision result from the spawn decision engine
62
+ */
63
+ export interface SpawnDecision {
64
+ canSpawn: boolean;
65
+ actions: PaneAction[];
66
+ reason?: string;
67
+ }
68
+
69
+ /**
70
+ * Capacity configuration for pane layout
71
+ */
72
+ export interface CapacityConfig {
73
+ mainPaneMinWidth: number;
74
+ agentPaneMinWidth: number;
75
+ }
76
+
77
+ /**
78
+ * Session mapping for decision engine
79
+ */
80
+ export interface SessionMapping {
81
+ sessionId: string;
82
+ paneId: string;
83
+ createdAt: Date;
84
+ }
85
+
86
+ /**
87
+ * Configuration for tmux integration
88
+ *
89
+ * Agents spawn in a dedicated "Agents" window with tiled grid layout.
90
+ * This keeps the main pane untouched while grouping all agent panes together.
91
+ */
92
+ export interface TmuxConfig {
93
+ enabled: boolean;
94
+ maxPanes: number;
95
+ mainPaneMinWidth: number;
96
+ agentPaneMinWidth: number;
97
+ }
98
+
99
+ // Minimum pane dimensions
100
+ export const MIN_PANE_WIDTH = 52;
101
+ export const MIN_PANE_HEIGHT = 11;
102
+
103
+ // Polling intervals
104
+ export const POLL_INTERVAL_MS = 2000;
105
+ export const SESSION_MISSING_GRACE_MS = 5000;
106
+ export const SESSION_TIMEOUT_MS = 10 * 60 * 1000;
@@ -0,0 +1,85 @@
1
+ import { spawn, spawnSync } from 'bun';
2
+
3
+ /**
4
+ * Check if running inside a tmux session
5
+ */
6
+ export function isInsideTmux(): boolean {
7
+ return !!process.env.TMUX;
8
+ }
9
+
10
+ /**
11
+ * Get the current pane ID
12
+ */
13
+ export function getCurrentPaneId(): string | undefined {
14
+ return process.env.TMUX_PANE;
15
+ }
16
+
17
+ /**
18
+ * Get the path to the tmux binary
19
+ */
20
+ export async function getTmuxPath(): Promise<string | null> {
21
+ try {
22
+ const proc = spawn(['which', 'tmux'], { stdout: 'pipe' });
23
+ await proc.exited;
24
+ const output = await new Response(proc.stdout).text();
25
+ return output.trim() || null;
26
+ } catch {
27
+ return null;
28
+ }
29
+ }
30
+
31
+ /**
32
+ * Run a tmux command and return output
33
+ */
34
+ export async function runTmuxCommand(
35
+ args: string[]
36
+ ): Promise<{ success: boolean; output: string }> {
37
+ const tmux = await getTmuxPath();
38
+ if (!tmux) return { success: false, output: 'tmux not found' };
39
+
40
+ const proc = spawn([tmux, ...args], { stdout: 'pipe', stderr: 'pipe' });
41
+ const exitCode = await proc.exited;
42
+ const stdout = await new Response(proc.stdout).text();
43
+ const stderr = await new Response(proc.stderr).text();
44
+
45
+ return {
46
+ success: exitCode === 0,
47
+ output: exitCode === 0 ? stdout.trim() : stderr.trim(),
48
+ };
49
+ }
50
+
51
+ /**
52
+ * Run a tmux command synchronously (for shutdown scenarios)
53
+ * Uses spawnSync to ensure completion before process exit
54
+ */
55
+ export function runTmuxCommandSync(args: string[]): { success: boolean; output: string } {
56
+ const tmux = getTmuxPathSync();
57
+ if (!tmux) return { success: false, output: 'tmux not found' };
58
+
59
+ try {
60
+ const result = spawnSync([tmux, ...args], { timeout: 2000 });
61
+ const stdout = result.stdout?.toString() ?? '';
62
+ const stderr = result.stderr?.toString() ?? '';
63
+
64
+ return {
65
+ success: result.exitCode === 0,
66
+ output: result.exitCode === 0 ? stdout.trim() : stderr.trim(),
67
+ };
68
+ } catch {
69
+ return { success: false, output: 'tmux command failed' };
70
+ }
71
+ }
72
+
73
+ /**
74
+ * Get the path to the tmux binary synchronously
75
+ */
76
+ export function getTmuxPathSync(): string | null {
77
+ try {
78
+ const result = spawnSync(['which', 'tmux']);
79
+ if (result.exitCode !== 0) return null;
80
+ const output = result.stdout?.toString() ?? '';
81
+ return output.trim() || null;
82
+ } catch {
83
+ return null;
84
+ }
85
+ }
@@ -0,0 +1,145 @@
1
+ import { z } from 'zod';
2
+ import type { ToolContext } from '@opencode-ai/plugin';
3
+ import type { AgentRole } from '../types';
4
+ import { AgentRoleSchema } from '../types';
5
+ import { agents } from '../agents';
6
+ import type { BackgroundManager } from '../background';
7
+
8
+ export const BackgroundTaskArgsSchema = z.object({
9
+ agent: AgentRoleSchema.describe('Agent role to run the task'),
10
+ task: z.string().describe('Task prompt to run in the background'),
11
+ description: z.string().optional().describe('Short description of the task'),
12
+ });
13
+
14
+ export const BackgroundOutputArgsSchema = z.object({
15
+ task_id: z.string().describe('Background task ID'),
16
+ });
17
+
18
+ export const BackgroundCancelArgsSchema = z.object({
19
+ task_id: z.string().describe('Background task ID'),
20
+ });
21
+
22
+ export type BackgroundTaskArgs = z.infer<typeof BackgroundTaskArgsSchema>;
23
+ export type BackgroundOutputArgs = z.infer<typeof BackgroundOutputArgsSchema>;
24
+ export type BackgroundCancelArgs = z.infer<typeof BackgroundCancelArgsSchema>;
25
+
26
+ export function createBackgroundTools(manager: BackgroundManager): {
27
+ backgroundTaskTool: {
28
+ name: string;
29
+ description: string;
30
+ args: typeof BackgroundTaskArgsSchema;
31
+ execute: (
32
+ args: BackgroundTaskArgs,
33
+ context: ToolContext
34
+ ) => Promise<{
35
+ taskId: string;
36
+ status: string;
37
+ message: string;
38
+ }>;
39
+ };
40
+ backgroundOutputTool: {
41
+ name: string;
42
+ description: string;
43
+ args: typeof BackgroundOutputArgsSchema;
44
+ execute: (args: BackgroundOutputArgs) => Promise<{
45
+ taskId: string;
46
+ status: string;
47
+ result?: string;
48
+ error?: string;
49
+ }>;
50
+ };
51
+ backgroundCancelTool: {
52
+ name: string;
53
+ description: string;
54
+ args: typeof BackgroundCancelArgsSchema;
55
+ execute: (args: BackgroundCancelArgs) => Promise<{
56
+ taskId: string;
57
+ success: boolean;
58
+ message: string;
59
+ }>;
60
+ };
61
+ } {
62
+ const backgroundTaskTool = {
63
+ name: 'background_task',
64
+ description: 'Launch a task to run in the background.',
65
+ args: BackgroundTaskArgsSchema,
66
+ async execute(
67
+ args: BackgroundTaskArgs,
68
+ context: ToolContext
69
+ ): Promise<{
70
+ taskId: string;
71
+ status: string;
72
+ message: string;
73
+ }> {
74
+ const agentName = resolveAgentName(args.agent);
75
+ const task = await manager.launch({
76
+ description: args.description ?? args.task,
77
+ prompt: args.task,
78
+ agent: agentName,
79
+ parentSessionId: context.sessionID,
80
+ parentMessageId: context.messageID,
81
+ });
82
+
83
+ return {
84
+ taskId: task.id,
85
+ status: task.status,
86
+ message:
87
+ task.status === 'error'
88
+ ? (task.error ?? 'Failed to launch background task.')
89
+ : 'Background task launched.',
90
+ };
91
+ },
92
+ };
93
+
94
+ const backgroundOutputTool = {
95
+ name: 'background_output',
96
+ description: 'Retrieve output for a background task.',
97
+ args: BackgroundOutputArgsSchema,
98
+ async execute(args: BackgroundOutputArgs): Promise<{
99
+ taskId: string;
100
+ status: string;
101
+ result?: string;
102
+ error?: string;
103
+ }> {
104
+ const task = manager.getTask(args.task_id);
105
+ if (!task) {
106
+ return {
107
+ taskId: args.task_id,
108
+ status: 'error',
109
+ error: 'Task not found.',
110
+ };
111
+ }
112
+ return {
113
+ taskId: task.id,
114
+ status: task.status,
115
+ result: task.result,
116
+ error: task.error,
117
+ };
118
+ },
119
+ };
120
+
121
+ const backgroundCancelTool = {
122
+ name: 'background_cancel',
123
+ description: 'Cancel a running background task.',
124
+ args: BackgroundCancelArgsSchema,
125
+ async execute(args: BackgroundCancelArgs): Promise<{
126
+ taskId: string;
127
+ success: boolean;
128
+ message: string;
129
+ }> {
130
+ const success = manager.cancel(args.task_id);
131
+ return {
132
+ taskId: args.task_id,
133
+ success,
134
+ message: success ? 'Background task cancelled.' : 'Unable to cancel task.',
135
+ };
136
+ },
137
+ };
138
+
139
+ return { backgroundTaskTool, backgroundOutputTool, backgroundCancelTool };
140
+ }
141
+
142
+ function resolveAgentName(role: AgentRole): string {
143
+ const agent = agents[role];
144
+ return agent?.displayName ?? role;
145
+ }
@@ -4,7 +4,7 @@ import type { AgentRole } from '../types';
4
4
  // Schema for the delegate tool
5
5
  export const DelegateArgsSchema = z.object({
6
6
  agent: z
7
- .enum(['scout', 'builder', 'reviewer', 'memory', 'expert'])
7
+ .enum(['scout', 'builder', 'architect', 'reviewer', 'memory', 'expert', 'planner', 'runner'])
8
8
  .describe('The agent to delegate to'),
9
9
  task: z.string().describe('Clear description of the task to delegate'),
10
10
  context: z.string().optional().describe('Additional context from previous tasks'),
@@ -21,9 +21,12 @@ const AGENT_MENTIONS: Record<AgentRole, string> = {
21
21
  lead: '@Agentuity Coder Lead',
22
22
  scout: '@Agentuity Coder Scout',
23
23
  builder: '@Agentuity Coder Builder',
24
+ architect: '@Agentuity Coder Architect',
24
25
  reviewer: '@Agentuity Coder Reviewer',
25
26
  memory: '@Agentuity Coder Memory',
26
27
  expert: '@Agentuity Coder Expert',
28
+ planner: '@Agentuity Coder Planner',
29
+ runner: '@Agentuity Coder Runner',
27
30
  };
28
31
 
29
32
  export const delegateTool = {
@@ -32,10 +35,13 @@ export const delegateTool = {
32
35
 
33
36
  Use this to:
34
37
  - Scout: Explore codebase, find patterns, research documentation
35
- - Builder: Implement features, write code, run tests
38
+ - Builder: Implement features, write code, run tests (interactive work)
39
+ - Architect: Complex autonomous tasks, Cadence mode, deep reasoning (GPT Codex)
36
40
  - Reviewer: Review changes, catch issues, apply fixes
37
41
  - Memory: Store context, remember decisions across sessions
38
42
  - Expert: Get help with Agentuity CLI and cloud services
43
+ - Planner: Strategic advisor for complex architecture and deep planning (read-only)
44
+ - Runner: Run lint/build/test/typecheck/format/clean/install commands, returns structured results
39
45
 
40
46
  The task will be executed by the specified agent and the result returned.`,
41
47
 
@@ -1 +1,10 @@
1
1
  export { delegateTool, DelegateArgsSchema, type DelegateArgs } from './delegate';
2
+ export {
3
+ createBackgroundTools,
4
+ BackgroundTaskArgsSchema,
5
+ BackgroundOutputArgsSchema,
6
+ BackgroundCancelArgsSchema,
7
+ type BackgroundTaskArgs,
8
+ type BackgroundOutputArgs,
9
+ type BackgroundCancelArgs,
10
+ } from './background';
package/src/types.ts CHANGED
@@ -1,4 +1,7 @@
1
1
  import { z } from 'zod';
2
+ import type { BackgroundTaskConfig } from './background/types';
3
+ import type { SkillsConfig } from './skills/types';
4
+ import type { TmuxConfig } from './tmux/types';
2
5
 
3
6
  // Re-export types from @opencode-ai/plugin
4
7
  export type {
@@ -8,7 +11,21 @@ export type {
8
11
  ToolDefinition,
9
12
  } from '@opencode-ai/plugin';
10
13
 
11
- export const AgentRoleSchema = z.enum(['lead', 'scout', 'builder', 'reviewer', 'memory', 'expert']);
14
+ export type { BackgroundTaskConfig } from './background/types';
15
+ export type { SkillsConfig, LoadedSkill, SkillMetadata, SkillScope } from './skills';
16
+ export type { TmuxConfig } from './tmux/types';
17
+
18
+ export const AgentRoleSchema = z.enum([
19
+ 'lead',
20
+ 'scout',
21
+ 'builder',
22
+ 'architect',
23
+ 'reviewer',
24
+ 'memory',
25
+ 'expert',
26
+ 'planner',
27
+ 'runner',
28
+ ]);
12
29
  export type AgentRole = z.infer<typeof AgentRoleSchema>;
13
30
 
14
31
  export const TaskStatusSchema = z.enum(['pending', 'running', 'completed', 'failed', 'cancelled']);
@@ -64,6 +81,10 @@ export interface AgentConfig {
64
81
  temperature?: number;
65
82
  /** Maximum agentic steps before forcing text response */
66
83
  maxSteps?: number;
84
+ /** Reasoning effort for OpenAI models */
85
+ reasoningEffort?: ReasoningEffort;
86
+ /** Extended thinking configuration for Anthropic models */
87
+ thinking?: ThinkingConfig;
67
88
  }
68
89
 
69
90
  export interface AgentContext {
@@ -86,32 +107,84 @@ export interface CoderTask {
86
107
  error?: string;
87
108
  }
88
109
 
110
+ /** Extended thinking configuration for Anthropic models */
111
+ export const ThinkingConfigSchema = z.object({
112
+ type: z.enum(['enabled', 'disabled']),
113
+ budgetTokens: z.number().optional(),
114
+ });
115
+ export type ThinkingConfig = z.infer<typeof ThinkingConfigSchema>;
116
+
117
+ /** Reasoning effort for OpenAI models */
118
+ export const ReasoningEffortSchema = z.enum(['low', 'medium', 'high', 'xhigh']);
119
+ export type ReasoningEffort = z.infer<typeof ReasoningEffortSchema>;
120
+
121
+ /** Model variant for Anthropic thinking levels */
122
+ export const ModelVariantSchema = z.enum(['low', 'medium', 'high', 'max']);
123
+ export type ModelVariant = z.infer<typeof ModelVariantSchema>;
124
+
125
+ /** Enhanced agent model configuration */
126
+ export interface AgentModelConfig {
127
+ /** Model ID in provider/model-id format */
128
+ model?: string;
129
+ /** Temperature for response creativity (0.0-2.0) */
130
+ temperature?: number;
131
+ /** Model variant for Anthropic thinking levels */
132
+ variant?: ModelVariant;
133
+ /** Reasoning effort for OpenAI models */
134
+ reasoningEffort?: ReasoningEffort;
135
+ /** Extended thinking configuration for Anthropic models */
136
+ thinking?: ThinkingConfig;
137
+ /** Maximum agentic steps before forcing text response */
138
+ maxSteps?: number;
139
+ }
140
+
141
+ export const AgentModelConfigSchema = z.object({
142
+ model: z.string().optional(),
143
+ temperature: z.number().min(0).max(2).optional(),
144
+ variant: ModelVariantSchema.optional(),
145
+ reasoningEffort: ReasoningEffortSchema.optional(),
146
+ thinking: ThinkingConfigSchema.optional(),
147
+ maxSteps: z.number().optional(),
148
+ });
149
+
89
150
  export interface CoderConfig {
90
151
  org?: string;
91
- agents?: Partial<Record<AgentRole, AgentModelConfig>>;
92
152
  disabledMcps?: string[];
93
153
  /** CLI command patterns to block for security (e.g., 'cloud secrets', 'auth token') */
94
154
  blockedCommands?: string[];
155
+ background?: BackgroundTaskConfig;
156
+ skills?: SkillsConfig;
157
+ tmux?: TmuxConfig;
95
158
  }
96
159
 
97
- export interface AgentModelConfig {
98
- model?: string;
99
- temperature?: number;
100
- }
160
+ export const BackgroundTaskConfigSchema = z.object({
161
+ enabled: z.boolean(),
162
+ defaultConcurrency: z.number(),
163
+ staleTimeoutMs: z.number(),
164
+ providerConcurrency: z.record(z.string(), z.number()).optional(),
165
+ modelConcurrency: z.record(z.string(), z.number()).optional(),
166
+ });
167
+
168
+ export const SkillsConfigSchema = z.object({
169
+ enabled: z.boolean(),
170
+ paths: z.array(z.string()).optional(),
171
+ disabled: z.array(z.string()).optional(),
172
+ });
173
+
174
+ export const TmuxConfigSchema = z.object({
175
+ enabled: z.boolean(),
176
+ maxPanes: z.number(),
177
+ mainPaneMinWidth: z.number(),
178
+ agentPaneMinWidth: z.number(),
179
+ });
101
180
 
102
181
  export const CoderConfigSchema = z.object({
103
182
  org: z.string().optional(),
104
- agents: z
105
- .record(
106
- AgentRoleSchema,
107
- z.object({
108
- model: z.string().optional(),
109
- temperature: z.number().min(0).max(2).optional(),
110
- })
111
- )
112
- .optional(),
113
183
  disabledMcps: z.array(z.string()).optional(),
114
184
  blockedCommands: z.array(z.string()).optional(),
185
+ background: BackgroundTaskConfigSchema.optional(),
186
+ skills: SkillsConfigSchema.optional(),
187
+ tmux: TmuxConfigSchema.optional(),
115
188
  });
116
189
 
117
190
  export interface McpConfig {