@a1hvdy/cc-openclaw 0.6.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/dist/src/engines/persistent-session.js +13 -0
  2. package/dist/src/engines/persistent-session.js.map +1 -1
  3. package/dist/src/lib/config.d.ts +2 -0
  4. package/dist/src/lib/config.js +19 -0
  5. package/dist/src/lib/config.js.map +1 -1
  6. package/dist/src/lib/trajectory.d.ts +1 -1
  7. package/dist/src/lib/trajectory.js.map +1 -1
  8. package/dist/src/lib/vendor-paths.d.ts +6 -4
  9. package/dist/src/lib/vendor-paths.js +21 -14
  10. package/dist/src/lib/vendor-paths.js.map +1 -1
  11. package/dist/src/openai-compat/openai-compat.d.ts +7 -1
  12. package/dist/src/openai-compat/openai-compat.js +35 -4
  13. package/dist/src/openai-compat/openai-compat.js.map +1 -1
  14. package/dist/src/openai-compat/sse-translator.d.ts +23 -3
  15. package/dist/src/openai-compat/sse-translator.js +45 -6
  16. package/dist/src/openai-compat/sse-translator.js.map +1 -1
  17. package/dist/src/types.d.ts +9 -0
  18. package/package.json +2 -3
  19. package/vendor/base-oneshot-session.d.ts +0 -87
  20. package/vendor/base-oneshot-session.js +0 -227
  21. package/vendor/base-oneshot-session.js.map +0 -1
  22. package/vendor/circuit-breaker.d.ts +0 -21
  23. package/vendor/circuit-breaker.js +0 -47
  24. package/vendor/circuit-breaker.js.map +0 -1
  25. package/vendor/consensus.d.ts +0 -20
  26. package/vendor/consensus.js +0 -52
  27. package/vendor/consensus.js.map +0 -1
  28. package/vendor/constants.d.ts +0 -130
  29. package/vendor/constants.js +0 -139
  30. package/vendor/constants.js.map +0 -1
  31. package/vendor/council.d.ts +0 -67
  32. package/vendor/council.js +0 -913
  33. package/vendor/council.js.map +0 -1
  34. package/vendor/embedded-server.d.ts +0 -25
  35. package/vendor/embedded-server.js +0 -373
  36. package/vendor/embedded-server.js.map +0 -1
  37. package/vendor/inbox-manager.d.ts +0 -38
  38. package/vendor/inbox-manager.js +0 -111
  39. package/vendor/inbox-manager.js.map +0 -1
  40. package/vendor/index.d.ts +0 -63
  41. package/vendor/index.js +0 -705
  42. package/vendor/index.js.map +0 -1
  43. package/vendor/logger.d.ts +0 -16
  44. package/vendor/logger.js +0 -44
  45. package/vendor/logger.js.map +0 -1
  46. package/vendor/models.d.ts +0 -69
  47. package/vendor/models.js +0 -289
  48. package/vendor/models.js.map +0 -1
  49. package/vendor/openai-compat.d.ts +0 -197
  50. package/vendor/openai-compat.js +0 -765
  51. package/vendor/openai-compat.js.map +0 -1
  52. package/vendor/persistent-codex-session.d.ts +0 -16
  53. package/vendor/persistent-codex-session.js +0 -105
  54. package/vendor/persistent-codex-session.js.map +0 -1
  55. package/vendor/persistent-cursor-session.d.ts +0 -21
  56. package/vendor/persistent-cursor-session.js +0 -241
  57. package/vendor/persistent-cursor-session.js.map +0 -1
  58. package/vendor/persistent-custom-session.d.ts +0 -78
  59. package/vendor/persistent-custom-session.js +0 -937
  60. package/vendor/persistent-custom-session.js.map +0 -1
  61. package/vendor/persistent-gemini-session.d.ts +0 -21
  62. package/vendor/persistent-gemini-session.js +0 -216
  63. package/vendor/persistent-gemini-session.js.map +0 -1
  64. package/vendor/persistent-session.d.ts +0 -74
  65. package/vendor/persistent-session.js +0 -698
  66. package/vendor/persistent-session.js.map +0 -1
  67. package/vendor/proxy/anthropic-adapter.d.ts +0 -136
  68. package/vendor/proxy/anthropic-adapter.js +0 -392
  69. package/vendor/proxy/anthropic-adapter.js.map +0 -1
  70. package/vendor/proxy/handler.d.ts +0 -39
  71. package/vendor/proxy/handler.js +0 -323
  72. package/vendor/proxy/handler.js.map +0 -1
  73. package/vendor/proxy/schema-cleaner.d.ts +0 -11
  74. package/vendor/proxy/schema-cleaner.js +0 -34
  75. package/vendor/proxy/schema-cleaner.js.map +0 -1
  76. package/vendor/proxy/thought-cache.d.ts +0 -19
  77. package/vendor/proxy/thought-cache.js +0 -53
  78. package/vendor/proxy/thought-cache.js.map +0 -1
  79. package/vendor/session-manager.d.ts +0 -211
  80. package/vendor/session-manager.js +0 -1345
  81. package/vendor/session-manager.js.map +0 -1
  82. package/vendor/skill-resolver.js +0 -107
  83. package/vendor/types.d.ts +0 -466
  84. package/vendor/types.js +0 -8
  85. package/vendor/types.js.map +0 -1
  86. package/vendor/validation.d.ts +0 -31
  87. package/vendor/validation.js +0 -104
  88. package/vendor/validation.js.map +0 -1
package/vendor/index.js DELETED
@@ -1,705 +0,0 @@
1
- /**
2
- * openclaw-claude-code — Plugin entry point
3
- *
4
- * Registers tools, hooks, and HTTP routes with the OpenClaw Plugin SDK.
5
- * When used standalone (no OpenClaw), exports SessionManager for direct use.
6
- *
7
- * Lazy initialisation: SessionManager and EmbeddedServer are created only on
8
- * the first tool call. While the plugin is registered but never used, it
9
- * consumes no memory beyond the tool schema definitions.
10
- */
11
- import { SessionManager } from './session-manager.js';
12
- import { createProxyHandler } from './proxy/handler.js';
13
- import { EmbeddedServer } from './embedded-server.js';
14
- import { sanitizeCwd, validateRegex } from './validation.js';
15
- // ─── Standalone Export ───────────────────────────────────────────────────────
16
- export { SessionManager } from './session-manager.js';
17
- export { PersistentClaudeSession } from './persistent-session.js';
18
- export { BaseOneShotSession } from './base-oneshot-session.js';
19
- export { PersistentCodexSession } from './persistent-codex-session.js';
20
- export { PersistentGeminiSession } from './persistent-gemini-session.js';
21
- export { PersistentCursorSession } from './persistent-cursor-session.js';
22
- export { PersistentCustomSession } from './persistent-custom-session.js';
23
- export { Council, getDefaultCouncilConfig } from './council.js';
24
- export { parseConsensus, stripConsensusTags, hasConsensusMarker } from './consensus.js';
25
- export { sanitizeCwd, validateRegex, validateName } from './validation.js';
26
- export { createConsoleLogger, nullLogger } from './logger.js';
27
- export { CircuitBreaker } from './circuit-breaker.js';
28
- export { InboxManager } from './inbox-manager.js';
29
- export * from './types.js';
30
- /**
31
- * OpenClaw plugin object — standard format
32
- */
33
- const plugin = {
34
- id: 'openclaw-claude-code',
35
- name: 'Claude Code SDK',
36
- description: 'Full-featured Claude Code integration — session management, agent teams, worktree isolation, multi-model proxy',
37
- register(api) {
38
- const rawConfig = (api.pluginConfig || {});
39
- // ─── Lazy Init ────────────────────────────────────────────────────────
40
- //
41
- // Neither SessionManager nor EmbeddedServer is created at plugin load
42
- // time. They are initialised on the first tool invocation and reused
43
- // thereafter. This keeps memory overhead at zero for users who have the
44
- // plugin installed but do not actively use Claude Code sessions.
45
- let manager = null;
46
- let server = null;
47
- function getManager() {
48
- if (!manager) {
49
- api.logger.info('[openclaw-claude-code] First use — initialising SessionManager and embedded server');
50
- manager = new SessionManager(rawConfig);
51
- server = new EmbeddedServer(manager);
52
- server.start().catch((err) => api.logger.error('[openclaw-claude-code] Embedded server failed to start:', err));
53
- }
54
- return manager;
55
- }
56
- // ─── Service Lifecycle ────────────────────────────────────────────────
57
- api.registerService({
58
- id: 'openclaw-claude-code',
59
- start: () => api.logger.info('[openclaw-claude-code] Plugin registered (lazy init — will activate on first use)'),
60
- stop: () => {
61
- if (server)
62
- server.stop().catch(() => { });
63
- if (manager)
64
- manager.shutdown().catch(() => { });
65
- server = null;
66
- manager = null;
67
- },
68
- });
69
- // ─── Proxy HTTP Route (multi-model support) ───────────────────────────
70
- //
71
- // The proxy route handler itself is lightweight (just an HTTP handler
72
- // function); registering it eagerly is fine. The heavy proxy work only
73
- // happens when a request actually arrives.
74
- if (rawConfig.proxy?.enabled !== false) {
75
- const proxyHandler = createProxyHandler(rawConfig.proxy, {
76
- anthropicApiKey: process.env.ANTHROPIC_API_KEY,
77
- openaiApiKey: process.env.OPENAI_API_KEY,
78
- geminiApiKey: process.env.GEMINI_API_KEY,
79
- gatewayUrl: process.env.GATEWAY_URL,
80
- gatewayKey: process.env.GATEWAY_KEY,
81
- });
82
- api.registerHttpRoute({
83
- path: '/v1/claude-code-proxy',
84
- auth: 'gateway',
85
- match: 'prefix',
86
- handler: proxyHandler,
87
- });
88
- }
89
- // ─── Tool: claude_session_start ──────────────────────────────────────
90
- api.registerTool({
91
- name: 'claude_session_start',
92
- description: 'Start a persistent coding session. Supports multiple engines: claude (default) for Claude Code CLI, codex for OpenAI Codex CLI, gemini for Google Gemini CLI, cursor for Cursor Agent CLI, or custom for any user-configured coding agent CLI.',
93
- parameters: {
94
- type: 'object',
95
- properties: {
96
- name: { type: 'string', description: 'Session name (auto-generated if omitted)' },
97
- cwd: { type: 'string', description: 'Working directory' },
98
- engine: {
99
- type: 'string',
100
- enum: ['claude', 'codex', 'gemini', 'cursor', 'custom'],
101
- description: 'Engine to use (default: claude). Use "custom" with customEngine config for any CLI.',
102
- },
103
- model: { type: 'string', description: 'Model to use (opus, sonnet, haiku, gemini-pro, o4-mini, etc.)' },
104
- permissionMode: {
105
- type: 'string',
106
- enum: ['acceptEdits', 'bypassPermissions', 'default', 'delegate', 'dontAsk', 'plan', 'auto'],
107
- },
108
- effort: { type: 'string', enum: ['low', 'medium', 'high', 'max', 'auto'] },
109
- allowedTools: { type: 'array', items: { type: 'string' }, description: 'Tools to auto-approve' },
110
- disallowedTools: { type: 'array', items: { type: 'string' }, description: 'Tools to deny' },
111
- maxTurns: { type: 'number', description: 'Max agent loop turns' },
112
- maxBudgetUsd: { type: 'number', description: 'Max API spend (USD)' },
113
- systemPrompt: { type: 'string', description: 'Replace system prompt' },
114
- appendSystemPrompt: { type: 'string', description: 'Append to system prompt' },
115
- agents: { type: 'object', description: 'Custom sub-agents JSON' },
116
- agent: { type: 'string', description: 'Default agent to use' },
117
- bare: { type: 'boolean', description: 'Minimal mode: skip hooks, LSP, auto-memory, CLAUDE.md' },
118
- worktree: { type: ['string', 'boolean'], description: 'Run in git worktree' },
119
- fallbackModel: { type: 'string', description: 'Auto fallback when primary overloaded' },
120
- jsonSchema: { type: 'string', description: 'JSON Schema for structured output' },
121
- mcpConfig: { type: ['string', 'array'], items: { type: 'string' }, description: 'MCP server config file(s)' },
122
- settings: { type: 'string', description: 'Settings.json path or inline JSON' },
123
- noSessionPersistence: { type: 'boolean', description: 'Do not save session to disk' },
124
- betas: { type: ['string', 'array'], items: { type: 'string' }, description: 'Custom beta headers' },
125
- enableAgentTeams: { type: 'boolean', description: 'Enable experimental agent teams' },
126
- enableAutoMode: { type: 'boolean', description: 'Enable auto permission mode' },
127
- customEngine: {
128
- type: 'object',
129
- description: 'Custom engine config (required when engine="custom"). Defines how to invoke any coding agent CLI.',
130
- properties: {
131
- name: { type: 'string', description: 'Engine display name' },
132
- bin: { type: 'string', description: 'Binary path or command' },
133
- binEnv: { type: 'string', description: 'Env var that overrides bin' },
134
- persistent: {
135
- type: 'boolean',
136
- description: 'true=long-running subprocess (Claude Code style), false=spawn per send (default)',
137
- },
138
- args: {
139
- type: 'object',
140
- description: 'CLI flag mappings',
141
- properties: {
142
- print: { type: 'string' },
143
- outputFormat: { type: 'string' },
144
- outputFormatValue: { type: 'string' },
145
- inputFormat: { type: 'string' },
146
- inputFormatValue: { type: 'string' },
147
- skipPermissions: { type: 'string' },
148
- permissionMode: { type: 'string' },
149
- model: { type: 'string' },
150
- systemPrompt: { type: 'string' },
151
- appendSystemPrompt: { type: 'string' },
152
- maxTurns: { type: 'string' },
153
- resume: { type: 'string' },
154
- verbose: { type: 'string' },
155
- replayUserMessages: { type: 'string' },
156
- includePartialMessages: { type: 'string' },
157
- effort: { type: 'string' },
158
- workspace: { type: 'string' },
159
- extra: { type: 'array', items: { type: 'string' } },
160
- },
161
- },
162
- permissionModes: { type: 'object', description: 'Map OpenClaw permission names to CLI values' },
163
- pricing: {
164
- type: 'object',
165
- properties: {
166
- input: { type: 'number' },
167
- output: { type: 'number' },
168
- cached: { type: 'number' },
169
- },
170
- },
171
- contextWindow: { type: 'number' },
172
- env: { type: 'object', description: 'Extra environment variables' },
173
- sanitizePatterns: { type: 'array', items: { type: 'string' } },
174
- },
175
- required: ['name', 'bin', 'args'],
176
- },
177
- resumeSessionId: {
178
- type: 'string',
179
- description: 'Resume an existing Claude Code session by its ID (e.g. from ~/.claude/sessions/). Replays conversation history via session/load instead of starting fresh.',
180
- },
181
- },
182
- },
183
- execute: async (_id, args) => {
184
- const sanitized = { ...args };
185
- if (sanitized.cwd)
186
- sanitized.cwd = sanitizeCwd(sanitized.cwd);
187
- const info = await getManager().startSession(sanitized);
188
- return { ok: true, ...info };
189
- },
190
- });
191
- // ─── Tool: claude_session_send ───────────────────────────────────────
192
- api.registerTool({
193
- name: 'claude_session_send',
194
- description: 'Send a message to a persistent Claude Code session and get the response',
195
- parameters: {
196
- type: 'object',
197
- properties: {
198
- name: { type: 'string', description: 'Session name' },
199
- message: { type: 'string', description: 'Message to send' },
200
- effort: { type: 'string', enum: ['low', 'medium', 'high', 'max'], description: 'Effort for this message' },
201
- plan: { type: 'boolean', description: 'Enable plan mode' },
202
- timeout: { type: 'number', description: 'Timeout in ms (default 300000)' },
203
- stream: {
204
- type: 'boolean',
205
- description: 'Collect text chunks as they arrive and include them in result.chunks[] (default false). Note: OpenClaw plugin SDK does not yet support mid-tool streaming to the caller, so chunks are buffered and returned with the final result.',
206
- },
207
- },
208
- required: ['name', 'message'],
209
- },
210
- execute: async (_id, args) => {
211
- const wantChunks = args.stream;
212
- const chunks = [];
213
- const result = await getManager().sendMessage(args.name, args.message, {
214
- effort: args.effort,
215
- plan: args.plan,
216
- timeout: args.timeout,
217
- // When stream:true, collect chunks into array for caller.
218
- // True mid-tool streaming requires SDK-level support (not yet available).
219
- onChunk: wantChunks
220
- ? (chunk) => {
221
- chunks.push(chunk);
222
- }
223
- : undefined,
224
- });
225
- return {
226
- ok: true,
227
- ...result,
228
- ...(wantChunks ? { chunks } : {}),
229
- };
230
- },
231
- });
232
- // ─── Tool: claude_session_stop ───────────────────────────────────────
233
- api.registerTool({
234
- name: 'claude_session_stop',
235
- description: 'Stop a persistent Claude Code session',
236
- parameters: {
237
- type: 'object',
238
- properties: { name: { type: 'string', description: 'Session name' } },
239
- required: ['name'],
240
- },
241
- execute: async (_id, args) => {
242
- await getManager().stopSession(args.name);
243
- return { ok: true };
244
- },
245
- });
246
- // ─── Tool: claude_session_list ───────────────────────────────────────
247
- api.registerTool({
248
- name: 'claude_session_list',
249
- description: 'List all active Claude Code sessions',
250
- parameters: { type: 'object', properties: {} },
251
- execute: async (_id) => {
252
- if (!manager)
253
- return { ok: true, sessions: [], persisted: [] };
254
- return { ok: true, sessions: manager.listSessions(), persisted: manager.listPersistedSessions() };
255
- },
256
- });
257
- // ─── Tool: claude_sessions_overview ──────────────────────────────────
258
- api.registerTool({
259
- name: 'claude_sessions_overview',
260
- description: 'Get an aggregate overview of all active Claude Code sessions — readiness, busy/paused state, cost, context usage, and last activity for each. Use this for a dashboard view across all sessions. For single-session detail, use claude_session_status instead.',
261
- parameters: { type: 'object', properties: {} },
262
- execute: async (_id) => {
263
- if (!manager)
264
- return { ok: true, version: 'unknown', sessions: 0, sessionNames: [], uptime: process.uptime(), details: [] };
265
- return manager.health();
266
- },
267
- });
268
- // ─── Tool: claude_session_status ─────────────────────────────────────
269
- api.registerTool({
270
- name: 'claude_session_status',
271
- description: 'Get detailed status of a Claude Code session (context %, tokens, cost, uptime)',
272
- parameters: {
273
- type: 'object',
274
- properties: { name: { type: 'string', description: 'Session name' } },
275
- required: ['name'],
276
- },
277
- execute: async (_id, args) => {
278
- const status = getManager().getStatus(args.name);
279
- return { ok: true, ...status };
280
- },
281
- });
282
- // ─── Tool: claude_session_grep ───────────────────────────────────────
283
- api.registerTool({
284
- name: 'claude_session_grep',
285
- description: 'Search session history for events matching a regex pattern',
286
- parameters: {
287
- type: 'object',
288
- properties: {
289
- name: { type: 'string', description: 'Session name' },
290
- pattern: { type: 'string', description: 'Regex pattern to search' },
291
- limit: { type: 'number', description: 'Max results (default 50)' },
292
- },
293
- required: ['name', 'pattern'],
294
- },
295
- execute: async (_id, args) => {
296
- validateRegex(args.pattern);
297
- const matches = await getManager().grepSession(args.name, args.pattern, args.limit);
298
- return { ok: true, count: matches.length, matches };
299
- },
300
- });
301
- // ─── Tool: claude_session_compact ────────────────────────────────────
302
- api.registerTool({
303
- name: 'claude_session_compact',
304
- description: 'Compact a session to reclaim context window space',
305
- parameters: {
306
- type: 'object',
307
- properties: {
308
- name: { type: 'string', description: 'Session name' },
309
- summary: { type: 'string', description: 'Optional summary for compaction' },
310
- },
311
- required: ['name'],
312
- },
313
- execute: async (_id, args) => {
314
- await getManager().compactSession(args.name, args.summary);
315
- return { ok: true };
316
- },
317
- });
318
- // ─── Tool: claude_agents_list ────────────────────────────────────────
319
- api.registerTool({
320
- name: 'claude_agents_list',
321
- description: 'List agent definitions from .claude/agents/',
322
- parameters: {
323
- type: 'object',
324
- properties: { cwd: { type: 'string', description: 'Project directory' } },
325
- },
326
- execute: async (_id, args) => {
327
- const agents = getManager().listAgents(sanitizeCwd(args.cwd));
328
- return { ok: true, agents };
329
- },
330
- });
331
- // ─── Tool: claude_team_list ──────────────────────────────────────────
332
- api.registerTool({
333
- name: 'claude_team_list',
334
- description: 'List teammates in an agent team session (requires enableAgentTeams)',
335
- parameters: {
336
- type: 'object',
337
- properties: { name: { type: 'string', description: 'Session name' } },
338
- required: ['name'],
339
- },
340
- execute: async (_id, args) => {
341
- const response = await getManager().teamList(args.name);
342
- return { ok: true, response };
343
- },
344
- });
345
- // ─── Tool: claude_team_send ──────────────────────────────────────────
346
- api.registerTool({
347
- name: 'claude_team_send',
348
- description: 'Send a message to a specific teammate in an agent team session',
349
- parameters: {
350
- type: 'object',
351
- properties: {
352
- name: { type: 'string', description: 'Session name' },
353
- teammate: { type: 'string', description: 'Teammate name' },
354
- message: { type: 'string', description: 'Message to send' },
355
- },
356
- required: ['name', 'teammate', 'message'],
357
- },
358
- execute: async (_id, args) => {
359
- const result = await getManager().teamSend(args.name, args.teammate, args.message);
360
- return { ok: true, ...result };
361
- },
362
- });
363
- // ─── Tool: claude_session_update_tools ───────────────────────────────
364
- api.registerTool({
365
- name: 'claude_session_update_tools',
366
- description: 'Update allowedTools or disallowedTools for a running session. Restarts the session process with --resume to apply the new tool constraints while preserving conversation history. Rejects if the session is currently busy.',
367
- parameters: {
368
- type: 'object',
369
- properties: {
370
- name: { type: 'string', description: 'Session name' },
371
- allowedTools: {
372
- type: 'array',
373
- items: { type: 'string' },
374
- description: 'New allowedTools list (replaces existing, or merges if merge:true)',
375
- },
376
- disallowedTools: {
377
- type: 'array',
378
- items: { type: 'string' },
379
- description: 'New disallowedTools list (replaces existing, or merges if merge:true)',
380
- },
381
- removeTools: {
382
- type: 'array',
383
- items: { type: 'string' },
384
- description: 'Tools to remove from allowedTools/disallowedTools (applied after merge)',
385
- },
386
- merge: { type: 'boolean', description: 'Merge with existing lists instead of replacing (default false)' },
387
- },
388
- required: ['name'],
389
- },
390
- execute: async (_id, args) => {
391
- const info = await getManager().updateTools(args.name, {
392
- allowedTools: args.allowedTools,
393
- disallowedTools: args.disallowedTools,
394
- removeTools: args.removeTools,
395
- merge: args.merge,
396
- });
397
- return { ok: true, restarted: true, ...info };
398
- },
399
- });
400
- // ─── Tool: claude_session_switch_model ───────────────────────────────
401
- api.registerTool({
402
- name: 'claude_session_switch_model',
403
- description: 'Switch the model for a running session immediately. Restarts the session process with --resume so the new model takes effect on the next message while preserving conversation history.',
404
- parameters: {
405
- type: 'object',
406
- properties: {
407
- name: { type: 'string', description: 'Session name' },
408
- model: { type: 'string', description: 'New model (opus, sonnet, haiku, gemini-pro, etc.)' },
409
- },
410
- required: ['name', 'model'],
411
- },
412
- execute: async (_id, args) => {
413
- const info = await getManager().switchModel(args.name, args.model);
414
- return { ok: true, restarted: true, ...info };
415
- },
416
- });
417
- // ─── Tool: council_start ────────────────────────────────────────────
418
- api.registerTool({
419
- name: 'council_start',
420
- description: 'Start a multi-agent council that collaborates on a task using git worktree isolation, round-based execution, and consensus voting. Agents can use different engines (Claude, Codex) and models.',
421
- parameters: {
422
- type: 'object',
423
- properties: {
424
- task: { type: 'string', description: 'Task description for the council to work on' },
425
- projectDir: { type: 'string', description: 'Working directory for the council project' },
426
- agents: {
427
- type: 'array',
428
- description: 'Agent personas. Defaults to 3-agent team (Planner, Generator, Evaluator) if omitted.',
429
- items: {
430
- type: 'object',
431
- properties: {
432
- name: { type: 'string', description: 'Agent display name' },
433
- emoji: { type: 'string', description: 'Agent emoji identifier' },
434
- persona: { type: 'string', description: 'Agent personality/expertise description' },
435
- engine: {
436
- type: 'string',
437
- enum: ['claude', 'codex', 'gemini', 'cursor', 'custom'],
438
- description: 'Engine (default: claude). Use "custom" with customEngine for any CLI.',
439
- },
440
- model: { type: 'string', description: 'Model to use' },
441
- baseUrl: { type: 'string', description: 'Custom API endpoint (for proxy)' },
442
- customEngine: { type: 'object', description: 'Custom engine config (when engine="custom")' },
443
- },
444
- required: ['name', 'emoji', 'persona'],
445
- },
446
- },
447
- maxRounds: { type: 'number', description: 'Max collaboration rounds (default 15)' },
448
- agentTimeoutMs: { type: 'number', description: 'Per-agent timeout in ms (default 1800000)' },
449
- maxTurnsPerAgent: { type: 'number', description: 'Max tool turns per agent per round (default 30)' },
450
- maxBudgetUsd: { type: 'number', description: 'Max API spend per agent (USD)' },
451
- defaultPermissionMode: {
452
- type: 'string',
453
- enum: ['acceptEdits', 'bypassPermissions', 'default', 'delegate', 'dontAsk', 'plan', 'auto'],
454
- description: 'Default permission mode for council agents (default: bypassPermissions)',
455
- },
456
- },
457
- required: ['task', 'projectDir'],
458
- },
459
- execute: async (_id, args) => {
460
- const { getDefaultCouncilConfig } = await import('./council.js');
461
- const projectDir = sanitizeCwd(args.projectDir);
462
- const defaultConfig = getDefaultCouncilConfig(projectDir);
463
- const config = {
464
- name: 'council',
465
- agents: args.agents || defaultConfig.agents,
466
- maxRounds: args.maxRounds ?? defaultConfig.maxRounds,
467
- projectDir,
468
- agentTimeoutMs: args.agentTimeoutMs,
469
- maxTurnsPerAgent: args.maxTurnsPerAgent,
470
- maxBudgetUsd: args.maxBudgetUsd,
471
- defaultPermissionMode: args.defaultPermissionMode,
472
- };
473
- const session = getManager().councilStart(args.task, config);
474
- return { ok: true, ...session, note: 'Council running in background. Poll with council_status.' };
475
- },
476
- });
477
- // ─── Tool: council_status ───────────────────────────────────────────
478
- api.registerTool({
479
- name: 'council_status',
480
- description: 'Get the status of a running council session',
481
- parameters: {
482
- type: 'object',
483
- properties: { id: { type: 'string', description: 'Council session ID' } },
484
- required: ['id'],
485
- },
486
- execute: async (_id, args) => {
487
- const session = getManager().councilStatus(args.id);
488
- if (!session)
489
- return { ok: false, error: 'Council not found' };
490
- return { ok: true, ...session };
491
- },
492
- });
493
- // ─── Tool: council_abort ────────────────────────────────────────────
494
- api.registerTool({
495
- name: 'council_abort',
496
- description: 'Abort a running council, stopping all agent sessions',
497
- parameters: {
498
- type: 'object',
499
- properties: { id: { type: 'string', description: 'Council session ID' } },
500
- required: ['id'],
501
- },
502
- execute: async (_id, args) => {
503
- getManager().councilAbort(args.id);
504
- return { ok: true };
505
- },
506
- });
507
- // ─── Tool: council_inject ───────────────────────────────────────────
508
- api.registerTool({
509
- name: 'council_inject',
510
- description: 'Inject a user message into the next round of a running council. The message will be appended to all agent prompts in the next round.',
511
- parameters: {
512
- type: 'object',
513
- properties: {
514
- id: { type: 'string', description: 'Council session ID' },
515
- message: { type: 'string', description: 'Message to inject' },
516
- },
517
- required: ['id', 'message'],
518
- },
519
- execute: async (_id, args) => {
520
- getManager().councilInject(args.id, args.message);
521
- return { ok: true };
522
- },
523
- });
524
- // ─── Tool: council_review ──────────────────────────────────────────
525
- api.registerTool({
526
- name: 'council_review',
527
- description: 'Review a completed council session. Returns a structured report of all changed files, branches, worktrees, plan.md status, review files, and agent summaries. Does not modify any state — purely informational. Use this before deciding to accept or reject.',
528
- parameters: {
529
- type: 'object',
530
- properties: { id: { type: 'string', description: 'Council session ID' } },
531
- required: ['id'],
532
- },
533
- execute: async (_id, args) => {
534
- const result = await getManager().councilReview(args.id);
535
- return { ok: true, ...result };
536
- },
537
- });
538
- // ─── Tool: council_accept ──────────────────────────────────────────
539
- api.registerTool({
540
- name: 'council_accept',
541
- description: 'Accept and finalize council work. Cleans up all council scaffolding: removes worktrees, deletes council/* branches, removes plan.md and reviews/ directory. Only call after reviewing with council_review.',
542
- parameters: {
543
- type: 'object',
544
- properties: { id: { type: 'string', description: 'Council session ID' } },
545
- required: ['id'],
546
- },
547
- execute: async (_id, args) => {
548
- const result = await getManager().councilAccept(args.id);
549
- return { ok: true, ...result };
550
- },
551
- });
552
- // ─── Tool: council_reject ──────────────────────────────────────────
553
- api.registerTool({
554
- name: 'council_reject',
555
- description: 'Reject council work and provide feedback. Rewrites plan.md with rejection feedback and commits it. Does NOT delete any worktrees or branches — the council can be restarted to retry. Use this when the council output is incomplete or broken.',
556
- parameters: {
557
- type: 'object',
558
- properties: {
559
- id: { type: 'string', description: 'Council session ID' },
560
- feedback: {
561
- type: 'string',
562
- description: 'Detailed feedback explaining why the work is rejected and what needs to be fixed',
563
- },
564
- },
565
- required: ['id', 'feedback'],
566
- },
567
- execute: async (_id, args) => {
568
- const result = await getManager().councilReject(args.id, args.feedback);
569
- return { ok: true, ...result };
570
- },
571
- });
572
- // ─── Tool: claude_session_send_to ─────────────────────────────────
573
- api.registerTool({
574
- name: 'claude_session_send_to',
575
- description: 'Send a cross-session message from one session to another. If the target is idle, the message is delivered immediately. If busy, it is queued in the inbox for later delivery. Use "*" as target to broadcast to all other sessions.',
576
- parameters: {
577
- type: 'object',
578
- properties: {
579
- from: { type: 'string', description: 'Sender session name' },
580
- to: { type: 'string', description: 'Target session name, or "*" for broadcast' },
581
- message: { type: 'string', description: 'Message text' },
582
- summary: { type: 'string', description: 'Short preview (5-10 words)' },
583
- },
584
- required: ['from', 'to', 'message'],
585
- },
586
- execute: async (_id, args) => {
587
- const result = await getManager().sessionSendTo(args.from, args.to, args.message, args.summary);
588
- return { ok: true, ...result };
589
- },
590
- });
591
- // ─── Tool: claude_session_inbox ──────────────────────────────────
592
- api.registerTool({
593
- name: 'claude_session_inbox',
594
- description: 'Read inbox messages for a session. Returns unread messages by default.',
595
- parameters: {
596
- type: 'object',
597
- properties: {
598
- name: { type: 'string', description: 'Session name' },
599
- unreadOnly: { type: 'boolean', description: 'Only unread messages (default true)' },
600
- },
601
- required: ['name'],
602
- },
603
- execute: async (_id, args) => {
604
- const messages = getManager().sessionInbox(args.name, args.unreadOnly ?? true);
605
- return { ok: true, count: messages.length, messages };
606
- },
607
- });
608
- // ─── Tool: claude_session_deliver_inbox ──────────────────────────
609
- api.registerTool({
610
- name: 'claude_session_deliver_inbox',
611
- description: 'Deliver all queued inbox messages to an idle session. Call this when a session finishes a task to process waiting messages.',
612
- parameters: {
613
- type: 'object',
614
- properties: { name: { type: 'string', description: 'Session name' } },
615
- required: ['name'],
616
- },
617
- execute: async (_id, args) => {
618
- const count = await getManager().sessionDeliverInbox(args.name);
619
- return { ok: true, delivered: count };
620
- },
621
- });
622
- // ─── Tool: ultraplan_start ──────────────────────────────────────
623
- api.registerTool({
624
- name: 'ultraplan_start',
625
- description: 'Start an Ultraplan session: a dedicated Opus planning session that explores your project for up to 30 minutes and produces a detailed implementation plan. Runs in background.',
626
- parameters: {
627
- type: 'object',
628
- properties: {
629
- task: { type: 'string', description: 'What to plan — describe the feature, refactor, or problem' },
630
- cwd: { type: 'string', description: 'Project directory to explore' },
631
- model: { type: 'string', description: 'Model to use (default: opus)' },
632
- timeout: { type: 'number', description: 'Timeout in ms (default: 1800000 = 30 min)' },
633
- },
634
- required: ['task'],
635
- },
636
- execute: async (_id, args) => {
637
- const result = getManager().ultraplanStart(args.task, {
638
- cwd: sanitizeCwd(args.cwd),
639
- model: args.model,
640
- timeout: args.timeout,
641
- });
642
- return { ok: true, ...result, note: 'Ultraplan running in background. Poll with ultraplan_status.' };
643
- },
644
- });
645
- // ─── Tool: ultraplan_status ─────────────────────────────────────
646
- api.registerTool({
647
- name: 'ultraplan_status',
648
- description: 'Get the status of an Ultraplan session. Returns the plan text when completed.',
649
- parameters: {
650
- type: 'object',
651
- properties: { id: { type: 'string', description: 'Ultraplan ID' } },
652
- required: ['id'],
653
- },
654
- execute: async (_id, args) => {
655
- const result = getManager().ultraplanStatus(args.id);
656
- if (!result)
657
- return { ok: false, error: 'Ultraplan not found' };
658
- return { ok: true, ...result };
659
- },
660
- });
661
- // ─── Tool: ultrareview_start ────────────────────────────────────
662
- api.registerTool({
663
- name: 'ultrareview_start',
664
- description: 'Start an Ultrareview: a fleet of bug-hunting agents (5-20) that review your codebase from different angles in parallel. Each agent specializes in a different area (security, performance, logic, types, etc.). Runs in background.',
665
- parameters: {
666
- type: 'object',
667
- properties: {
668
- cwd: { type: 'string', description: 'Project directory to review' },
669
- agentCount: { type: 'number', description: 'Number of reviewer agents (1-20, default 5)' },
670
- maxDurationMinutes: { type: 'number', description: 'Max review duration in minutes (5-25, default 10)' },
671
- model: { type: 'string', description: 'Model for reviewers (default: session default)' },
672
- focus: { type: 'string', description: 'Review focus area (default: bugs + security + quality)' },
673
- },
674
- required: ['cwd'],
675
- },
676
- execute: async (_id, args) => {
677
- const result = getManager().ultrareviewStart(sanitizeCwd(args.cwd), {
678
- agentCount: args.agentCount,
679
- maxDurationMinutes: args.maxDurationMinutes,
680
- model: args.model,
681
- focus: args.focus,
682
- });
683
- return { ok: true, ...result, note: 'Ultrareview running in background. Poll with ultrareview_status.' };
684
- },
685
- });
686
- // ─── Tool: ultrareview_status ───────────────────────────────────
687
- api.registerTool({
688
- name: 'ultrareview_status',
689
- description: 'Get the status of an Ultrareview. Returns all findings when completed.',
690
- parameters: {
691
- type: 'object',
692
- properties: { id: { type: 'string', description: 'Ultrareview ID' } },
693
- required: ['id'],
694
- },
695
- execute: async (_id, args) => {
696
- const result = getManager().ultrareviewStatus(args.id);
697
- if (!result)
698
- return { ok: false, error: 'Ultrareview not found' };
699
- return { ok: true, ...result };
700
- },
701
- });
702
- },
703
- };
704
- export default plugin;
705
- //# sourceMappingURL=index.js.map