@opencoven/coven-code 0.0.4 → 0.0.6

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 (115) hide show
  1. package/README.md +29 -130
  2. package/bin/coven-code +26 -0
  3. package/install.js +117 -0
  4. package/package.json +26 -23
  5. package/bin/coven-code-sdk.mjs +0 -12
  6. package/bin/coven-code.mjs +0 -19
  7. package/docs/CLI.md +0 -256
  8. package/docs/CONFIGURATION.md +0 -107
  9. package/docs/DEMO.md +0 -453
  10. package/docs/DEVELOPMENT.md +0 -104
  11. package/docs/DOGFOOD-PROTOCOL.md +0 -263
  12. package/docs/MCP-SKILLS-PLUGINS.md +0 -127
  13. package/docs/README.md +0 -39
  14. package/docs/RELEASE.md +0 -33
  15. package/docs/SDK.md +0 -107
  16. package/docs/superpowers/plans/2026-05-25-coven-code-panel-tui.md +0 -904
  17. package/docs/superpowers/plans/2026-05-25-coven-code-rebrand.md +0 -670
  18. package/docs/superpowers/specs/2026-05-25-coven-code-panel-tui-design.md +0 -235
  19. package/docs/superpowers/specs/2026-05-26-slash-first-tui-review.md +0 -63
  20. package/src/agent/fixture.mjs +0 -95
  21. package/src/agent/lane.mjs +0 -136
  22. package/src/cli/dispatch.mjs +0 -66
  23. package/src/cli/execute.mjs +0 -452
  24. package/src/cli/help.mjs +0 -58
  25. package/src/cli/interactive-core.mjs +0 -28
  26. package/src/cli/interactive-io.mjs +0 -101
  27. package/src/cli/interactive-slash.mjs +0 -184
  28. package/src/cli/notifications.mjs +0 -13
  29. package/src/cli/parse.mjs +0 -83
  30. package/src/cli/reasoning.mjs +0 -45
  31. package/src/cli/refs.mjs +0 -162
  32. package/src/cli/repl.mjs +0 -60
  33. package/src/cli/slash-commands.mjs +0 -375
  34. package/src/cli/stream-json.mjs +0 -225
  35. package/src/cli/tui-actions.mjs +0 -72
  36. package/src/cli/tui-blessed.mjs +0 -198
  37. package/src/cli/tui-keys.mjs +0 -80
  38. package/src/cli/tui-lane.mjs +0 -73
  39. package/src/cli/tui-render.mjs +0 -169
  40. package/src/cli/tui-submit.mjs +0 -82
  41. package/src/cli/tui.mjs +0 -174
  42. package/src/commands/agents.mjs +0 -53
  43. package/src/commands/config.mjs +0 -27
  44. package/src/commands/ide.mjs +0 -17
  45. package/src/commands/login.mjs +0 -84
  46. package/src/commands/mcp.mjs +0 -176
  47. package/src/commands/permissions-eval.mjs +0 -122
  48. package/src/commands/permissions-rules.mjs +0 -53
  49. package/src/commands/permissions-text.mjs +0 -112
  50. package/src/commands/permissions.mjs +0 -62
  51. package/src/commands/plugins.mjs +0 -86
  52. package/src/commands/review.mjs +0 -74
  53. package/src/commands/skill.mjs +0 -23
  54. package/src/commands/threads.mjs +0 -165
  55. package/src/commands/tools.mjs +0 -77
  56. package/src/commands/update.mjs +0 -31
  57. package/src/commands/usage.mjs +0 -34
  58. package/src/constants.mjs +0 -52
  59. package/src/main.mjs +0 -87
  60. package/src/mcp/discover.mjs +0 -154
  61. package/src/mcp/local.mjs +0 -55
  62. package/src/mcp/parsers.mjs +0 -46
  63. package/src/mcp/permissions.mjs +0 -52
  64. package/src/mcp/probe.mjs +0 -85
  65. package/src/mcp/registry.mjs +0 -96
  66. package/src/mcp/remote-oauth.mjs +0 -55
  67. package/src/mcp/remote-session.mjs +0 -54
  68. package/src/mcp/remote-sse.mjs +0 -82
  69. package/src/mcp/remote.mjs +0 -74
  70. package/src/plugins/api.mjs +0 -187
  71. package/src/plugins/configuration.mjs +0 -124
  72. package/src/plugins/discover.mjs +0 -84
  73. package/src/plugins/helpers.mjs +0 -187
  74. package/src/plugins/subsystems.mjs +0 -198
  75. package/src/plugins/validators.mjs +0 -142
  76. package/src/sdk-execute.mjs +0 -82
  77. package/src/sdk-install.mjs +0 -187
  78. package/src/sdk-settings.mjs +0 -88
  79. package/src/sdk.mjs +0 -163
  80. package/src/settings/load.mjs +0 -134
  81. package/src/settings/paths.mjs +0 -101
  82. package/src/skills/builtin/building-skills/SKILL.md +0 -20
  83. package/src/skills/discover.mjs +0 -95
  84. package/src/threads/store.mjs +0 -176
  85. package/src/tools/builtin/bash.mjs +0 -110
  86. package/src/tools/builtin/create-file.mjs +0 -66
  87. package/src/tools/builtin/edit-file.mjs +0 -76
  88. package/src/tools/builtin/finder.mjs +0 -73
  89. package/src/tools/builtin/glob.mjs +0 -74
  90. package/src/tools/builtin/grep.mjs +0 -82
  91. package/src/tools/builtin/index.mjs +0 -83
  92. package/src/tools/builtin/librarian.mjs +0 -97
  93. package/src/tools/builtin/look-at.mjs +0 -92
  94. package/src/tools/builtin/mcp.mjs +0 -51
  95. package/src/tools/builtin/mermaid.mjs +0 -59
  96. package/src/tools/builtin/oracle.mjs +0 -56
  97. package/src/tools/builtin/painter.mjs +0 -81
  98. package/src/tools/builtin/plugin-tool.mjs +0 -53
  99. package/src/tools/builtin/read-mcp-resource.mjs +0 -63
  100. package/src/tools/builtin/read-web-page.mjs +0 -72
  101. package/src/tools/builtin/read.mjs +0 -59
  102. package/src/tools/builtin/runtime-content.mjs +0 -31
  103. package/src/tools/builtin/runtime-decisions.mjs +0 -115
  104. package/src/tools/builtin/runtime.mjs +0 -85
  105. package/src/tools/builtin/task.mjs +0 -63
  106. package/src/tools/builtin/toolbox-tool.mjs +0 -57
  107. package/src/tools/builtin/undo-edit.mjs +0 -97
  108. package/src/tools/builtin/web-search.mjs +0 -128
  109. package/src/tools/toolbox.mjs +0 -273
  110. package/src/util/fs.mjs +0 -13
  111. package/src/util/glob.mjs +0 -46
  112. package/src/util/html.mjs +0 -21
  113. package/src/util/media.mjs +0 -13
  114. package/src/util/shell.mjs +0 -24
  115. package/src/util/table.mjs +0 -11
@@ -1,82 +0,0 @@
1
- import { readFileSync } from 'node:fs';
2
- import path from 'node:path';
3
- import { resolvePermissionDecision } from '../../commands/permissions.mjs';
4
- import { runPluginEventHandlers } from '../../plugins/discover.mjs';
5
- import { walkFiles } from '../../util/glob.mjs';
6
- import { isToolDisabled } from '../toolbox.mjs';
7
- import {
8
- applyToolCallDecision,
9
- createToolUseID,
10
- permissionDeniedOutput,
11
- pluginTextToolRunResult,
12
- pluginToolCallEvent,
13
- pluginToolResultEvent,
14
- pluginToolUseBlock,
15
- relativeToolPath,
16
- toolCallDecisionToolRun,
17
- validateToolCallDecision,
18
- } from './runtime.mjs';
19
-
20
- export const TOOL_NAME = 'Grep';
21
-
22
- export async function executePromptGrepToolRequest(request, parsed = {}, plugins = { handlers: {} }, threadId = '') {
23
- if (isToolDisabled(TOOL_NAME, 'built-in', parsed)) return { output: `Tool disabled: ${TOOL_NAME}` };
24
- request = { ...request, flags: normalizeGrepInput(request.flags) };
25
- if (!request.flags.pattern) return { output: 'Grep requires --pattern' };
26
- const toolUseID = createToolUseID();
27
- const callDecision = await runPluginEventHandlers(
28
- plugins.handlers['tool.call'],
29
- pluginToolCallEvent(TOOL_NAME, request.flags, threadId, toolUseID),
30
- validateToolCallDecision,
31
- );
32
- const callResult = applyToolCallDecision(TOOL_NAME, request, callDecision);
33
- if (callResult.output) return toolCallDecisionToolRun(TOOL_NAME, request.flags, toolUseID, callResult);
34
- request = { ...callResult.request, flags: normalizeGrepInput(callResult.request.flags) };
35
- const decision = resolvePermissionDecision(TOOL_NAME, request.flags, parsed, { threadId });
36
- if (!parsed.dangerouslyAllowAll && decision.action !== 'allow') {
37
- return {
38
- output: permissionDeniedOutput(TOOL_NAME, decision),
39
- permissionDenials: [{ tool: TOOL_NAME, action: decision.action, reason: 'permission' }],
40
- };
41
- }
42
- const output = grepBuiltinFiles(request.flags.pattern, request.flags.path);
43
- const resultDecision = await runPluginEventHandlers(
44
- plugins.handlers['tool.result'],
45
- pluginToolResultEvent(TOOL_NAME, request.flags, 'done', output, threadId, toolUseID),
46
- );
47
- return {
48
- ...pluginTextToolRunResult(resultDecision, output),
49
- toolUse: pluginToolUseBlock(TOOL_NAME, request.flags, toolUseID),
50
- };
51
- }
52
-
53
- function normalizeGrepInput(input = {}) {
54
- const pattern = input.pattern ?? input.regex ?? input.query;
55
- const searchPath = input.path ?? input.dir ?? input.cwd ?? '.';
56
- return {
57
- ...input,
58
- pattern: pattern ? String(pattern) : '',
59
- path: searchPath ? String(searchPath) : '.',
60
- };
61
- }
62
-
63
- function grepBuiltinFiles(pattern, searchPath = '.') {
64
- const root = path.isAbsolute(searchPath) ? searchPath : path.resolve(process.cwd(), searchPath);
65
- const files = walkFiles(root).sort();
66
- const re = new RegExp(pattern);
67
- const matches = [];
68
- for (const filePath of files) {
69
- let content = '';
70
- try {
71
- content = readFileSync(filePath, 'utf8');
72
- } catch {
73
- continue;
74
- }
75
- const lines = content.split(/\r?\n/);
76
- for (let index = 0; index < lines.length; index += 1) {
77
- if (!re.test(lines[index])) continue;
78
- matches.push(`${relativeToolPath(filePath)}:${index + 1}:${lines[index]}`);
79
- }
80
- }
81
- return matches.join('\n');
82
- }
@@ -1,83 +0,0 @@
1
- import { loadPlugins } from '../../plugins/discover.mjs';
2
- import { parseToolUseArgs } from '../toolbox.mjs';
3
- import { splitShellWords } from '../../util/shell.mjs';
4
- import { executePromptBashToolRequest } from './bash.mjs';
5
- import { executePromptCreateFileToolRequest } from './create-file.mjs';
6
- import { executePromptEditFileToolRequest } from './edit-file.mjs';
7
- import { executePromptFinderToolRequest } from './finder.mjs';
8
- import { executePromptGlobToolRequest } from './glob.mjs';
9
- import { executePromptGrepToolRequest } from './grep.mjs';
10
- import { executePromptLibrarianToolRequest } from './librarian.mjs';
11
- import { executePromptLookAtToolRequest } from './look-at.mjs';
12
- import { executePromptMcpToolRequest } from './mcp.mjs';
13
- import { executePromptMermaidToolRequest } from './mermaid.mjs';
14
- import { executePromptOracleToolRequest } from './oracle.mjs';
15
- import { executePromptPainterToolRequest } from './painter.mjs';
16
- import { executePromptPluginToolRequest } from './plugin-tool.mjs';
17
- import { executePromptReadMcpResourceToolRequest } from './read-mcp-resource.mjs';
18
- import { executePromptReadToolRequest } from './read.mjs';
19
- import { executePromptReadWebPageToolRequest } from './read-web-page.mjs';
20
- import { executePromptTaskToolRequest } from './task.mjs';
21
- import { executePromptToolboxToolRequest } from './toolbox-tool.mjs';
22
- import { executePromptUndoEditToolRequest } from './undo-edit.mjs';
23
- import { executePromptWebSearchToolRequest } from './web-search.mjs';
24
-
25
- const BUILTIN_DISPATCH = new Map([
26
- ['Bash', (request, stdin, parsed, plugins, threadId) =>
27
- executePromptBashToolRequest(request, stdin, parsed, plugins, threadId)],
28
- ['Read', (request, _stdin, parsed, plugins, threadId) =>
29
- executePromptReadToolRequest(request, parsed, plugins, threadId)],
30
- ['Grep', (request, _stdin, parsed, plugins, threadId) =>
31
- executePromptGrepToolRequest(request, parsed, plugins, threadId)],
32
- ['glob', (request, _stdin, parsed, plugins, threadId) =>
33
- executePromptGlobToolRequest(request, parsed, plugins, threadId)],
34
- ['create_file', (request, _stdin, parsed, plugins, threadId) =>
35
- executePromptCreateFileToolRequest(request, parsed, plugins, threadId)],
36
- ['edit_file', (request, _stdin, parsed, plugins, threadId) =>
37
- executePromptEditFileToolRequest(request, parsed, plugins, threadId)],
38
- ['undo_edit', (request, _stdin, parsed, plugins, threadId) =>
39
- executePromptUndoEditToolRequest(request, parsed, plugins, threadId)],
40
- ['Task', (request, _stdin, parsed, plugins, threadId) =>
41
- executePromptTaskToolRequest(request, parsed, plugins, threadId)],
42
- ['oracle', (request, _stdin, parsed, plugins, threadId) =>
43
- executePromptOracleToolRequest(request, parsed, plugins, threadId)],
44
- ['librarian', (request, _stdin, parsed, plugins, threadId) =>
45
- executePromptLibrarianToolRequest(request, parsed, plugins, threadId)],
46
- ['painter', (request, _stdin, parsed, plugins, threadId) =>
47
- executePromptPainterToolRequest(request, parsed, plugins, threadId)],
48
- ['mermaid', (request, _stdin, parsed, plugins, threadId) =>
49
- executePromptMermaidToolRequest(request, parsed, plugins, threadId)],
50
- ['look_at', (request, _stdin, parsed, plugins, threadId) =>
51
- executePromptLookAtToolRequest(request, parsed, plugins, threadId)],
52
- ['web_search', (request, _stdin, parsed, plugins, threadId) =>
53
- executePromptWebSearchToolRequest(request, parsed, plugins, threadId)],
54
- ['read_web_page', (request, _stdin, parsed, plugins, threadId) =>
55
- executePromptReadWebPageToolRequest(request, parsed, plugins, threadId)],
56
- ['find_thread', (request, _stdin, parsed, plugins, threadId) =>
57
- executePromptFinderToolRequest(request, parsed, plugins, threadId, 'find_thread')],
58
- ['finder', (request, _stdin, parsed, plugins, threadId) =>
59
- executePromptFinderToolRequest(request, parsed, plugins, threadId)],
60
- ['read_mcp_resource', (request, _stdin, parsed, plugins, threadId) =>
61
- executePromptReadMcpResourceToolRequest(request, parsed, plugins, threadId)],
62
- ]);
63
-
64
- export async function executePromptToolRequest(prompt, stdin, threadId, parsed = {}, plugins) {
65
- const request = parsePromptToolRequest(prompt);
66
- if (!request) return undefined;
67
- const resolvedPlugins = plugins ?? await loadPlugins(process.cwd());
68
- if (request.toolName.startsWith('mcp__')) {
69
- return executePromptMcpToolRequest(request, parsed, threadId, resolvedPlugins);
70
- }
71
- const builtin = BUILTIN_DISPATCH.get(request.toolName);
72
- if (builtin) return builtin(request, stdin, parsed, resolvedPlugins, threadId);
73
- const pluginTool = resolvedPlugins.tools.find((entry) => entry.name === request.toolName);
74
- if (pluginTool) return executePromptPluginToolRequest(pluginTool, request, parsed, resolvedPlugins, threadId);
75
- return executePromptToolboxToolRequest(request, stdin, parsed, resolvedPlugins, threadId);
76
- }
77
-
78
- export function parsePromptToolRequest(prompt) {
79
- const match = prompt.match(/\b(?:use|run|call)\s+([A-Za-z0-9_-]+(?:__[A-Za-z0-9_-]+)?)([^\r\n]*)/i);
80
- if (!match) return undefined;
81
- const useArgs = parseToolUseArgs([match[1], ...splitShellWords(match[2] ?? '')]);
82
- return { toolName: useArgs.toolName, flags: useArgs.flags };
83
- }
@@ -1,97 +0,0 @@
1
- import { readFileSync } from 'node:fs';
2
- import path from 'node:path';
3
- import { resolvePermissionDecision } from '../../commands/permissions.mjs';
4
- import { runPluginEventHandlers } from '../../plugins/discover.mjs';
5
- import { walkFiles } from '../../util/glob.mjs';
6
- import { isToolDisabled } from '../toolbox.mjs';
7
- import {
8
- applyToolCallDecision,
9
- createToolUseID,
10
- permissionDeniedOutput,
11
- pluginTextToolRunResult,
12
- pluginToolCallEvent,
13
- pluginToolResultEvent,
14
- pluginToolUseBlock,
15
- toolCallDecisionToolRun,
16
- validateToolCallDecision,
17
- } from './runtime.mjs';
18
-
19
- export const TOOL_NAME = 'librarian';
20
-
21
- export async function executePromptLibrarianToolRequest(request, parsed = {}, plugins = { handlers: {} }, threadId = '') {
22
- if (isToolDisabled(TOOL_NAME, 'built-in', parsed)) return { output: `Tool disabled: ${TOOL_NAME}` };
23
- request = { ...request, flags: normalizeLibrarianInput(request.flags) };
24
- if (!request.flags.query) return { output: 'librarian requires --query' };
25
- const toolUseID = createToolUseID();
26
- const callDecision = await runPluginEventHandlers(
27
- plugins.handlers['tool.call'],
28
- pluginToolCallEvent(TOOL_NAME, request.flags, threadId, toolUseID),
29
- validateToolCallDecision,
30
- );
31
- const callResult = applyToolCallDecision(TOOL_NAME, request, callDecision);
32
- if (callResult.output) return toolCallDecisionToolRun(TOOL_NAME, request.flags, toolUseID, callResult);
33
- request = { ...callResult.request, flags: normalizeLibrarianInput(callResult.request.flags) };
34
- const decision = resolvePermissionDecision(TOOL_NAME, request.flags, parsed, { threadId });
35
- if (!parsed.dangerouslyAllowAll && decision.action !== 'allow') {
36
- return {
37
- output: permissionDeniedOutput(TOOL_NAME, decision),
38
- permissionDenials: [{ tool: TOOL_NAME, action: decision.action, reason: 'permission' }],
39
- };
40
- }
41
- const output = searchWorkspaceForLibrarian(request.flags);
42
- const resultDecision = await runPluginEventHandlers(
43
- plugins.handlers['tool.result'],
44
- pluginToolResultEvent(TOOL_NAME, request.flags, 'done', output, threadId, toolUseID),
45
- );
46
- return {
47
- ...pluginTextToolRunResult(resultDecision, output),
48
- toolUse: pluginToolUseBlock(TOOL_NAME, request.flags, toolUseID),
49
- };
50
- }
51
-
52
- function normalizeLibrarianInput(input = {}) {
53
- const query = input.query ?? input.q ?? input.prompt ?? input.question ?? input.topic;
54
- const limit = Number.parseInt(String(input.limit ?? 5), 10);
55
- return {
56
- ...input,
57
- query: query ? String(query) : '',
58
- limit: Number.isFinite(limit) && limit > 0 ? Math.min(limit, 20) : 5,
59
- };
60
- }
61
-
62
- function searchWorkspaceForLibrarian(input) {
63
- const matches = findWorkspaceTextMatches(input.query, input.limit);
64
- return [
65
- `Librarian search: ${input.query}`,
66
- 'scope: current workspace',
67
- 'matches:',
68
- ...(matches.length ? matches.map(formatLibrarianMatch) : ['- no local matches found']),
69
- ].join('\n');
70
- }
71
-
72
- function findWorkspaceTextMatches(query, limit) {
73
- const needle = query.toLowerCase();
74
- const root = process.cwd();
75
- return walkFiles(root)
76
- .map((filePath) => path.relative(root, filePath))
77
- .filter((relativePath) => !relativePath.split(path.sep).some((part) => part === '.git' || part === 'node_modules'))
78
- .sort()
79
- .flatMap((relativePath) => {
80
- let text;
81
- try {
82
- text = readFileSync(path.join(root, relativePath), 'utf8');
83
- } catch {
84
- return [];
85
- }
86
- return text.split(/\r?\n/).flatMap((line, index) => (
87
- line.toLowerCase().includes(needle)
88
- ? [{ path: relativePath, line: index + 1, text: line.trim() }]
89
- : []
90
- ));
91
- })
92
- .slice(0, limit);
93
- }
94
-
95
- function formatLibrarianMatch(match) {
96
- return `- ${match.path}:${match.line}: ${match.text}`;
97
- }
@@ -1,92 +0,0 @@
1
- import { readFileSync } from 'node:fs';
2
- import path from 'node:path';
3
- import { fileURLToPath } from 'node:url';
4
- import { resolvePermissionDecision } from '../../commands/permissions.mjs';
5
- import { runPluginEventHandlers } from '../../plugins/discover.mjs';
6
- import { detectImageMediaType } from '../../util/media.mjs';
7
- import { isToolDisabled } from '../toolbox.mjs';
8
- import {
9
- applyToolCallDecision,
10
- createToolUseID,
11
- permissionDeniedOutput,
12
- pluginTextToolRunResult,
13
- pluginToolCallEvent,
14
- pluginToolResultEvent,
15
- pluginToolUseBlock,
16
- toolCallDecisionToolRun,
17
- validateToolCallDecision,
18
- } from './runtime.mjs';
19
-
20
- export const TOOL_NAME = 'look_at';
21
-
22
- export async function executePromptLookAtToolRequest(request, parsed = {}, plugins = { handlers: {} }, threadId = '') {
23
- if (isToolDisabled(TOOL_NAME, 'built-in', parsed)) return { output: `Tool disabled: ${TOOL_NAME}` };
24
- request = { ...request, flags: normalizeLookAtInput(request.flags) };
25
- if (!request.flags.path) return { output: 'look_at requires --path' };
26
- const toolUseID = createToolUseID();
27
- const callDecision = await runPluginEventHandlers(
28
- plugins.handlers['tool.call'],
29
- pluginToolCallEvent(TOOL_NAME, request.flags, threadId, toolUseID),
30
- validateToolCallDecision,
31
- );
32
- const callResult = applyToolCallDecision(TOOL_NAME, request, callDecision);
33
- if (callResult.output) return toolCallDecisionToolRun(TOOL_NAME, request.flags, toolUseID, callResult);
34
- request = { ...callResult.request, flags: normalizeLookAtInput(callResult.request.flags) };
35
- const decision = resolvePermissionDecision(TOOL_NAME, request.flags, parsed, { threadId });
36
- if (!parsed.dangerouslyAllowAll && decision.action !== 'allow') {
37
- return {
38
- output: permissionDeniedOutput(TOOL_NAME, decision),
39
- permissionDenials: [{ tool: TOOL_NAME, action: decision.action, reason: 'permission' }],
40
- };
41
- }
42
- const output = inspectLookAtMedia(request.flags);
43
- const resultDecision = await runPluginEventHandlers(
44
- plugins.handlers['tool.result'],
45
- pluginToolResultEvent(TOOL_NAME, request.flags, 'done', output, threadId, toolUseID),
46
- );
47
- return {
48
- ...pluginTextToolRunResult(resultDecision, output),
49
- toolUse: pluginToolUseBlock(TOOL_NAME, request.flags, toolUseID),
50
- };
51
- }
52
-
53
- function normalizeLookAtInput(input = {}) {
54
- const source = input.path ?? input.file ?? input.image ?? input.pdf ?? input.url;
55
- const goal = input.goal ?? input.prompt ?? input.instructions ?? input.question ?? '';
56
- return {
57
- ...input,
58
- path: source ? String(source) : '',
59
- goal: String(goal),
60
- };
61
- }
62
-
63
- function inspectLookAtMedia(input) {
64
- try {
65
- const resolved = resolveLookAtPath(input.path);
66
- const raw = readFileSync(resolved);
67
- return formatLookAtMediaResult(input.path, raw, input.goal);
68
- } catch (error) {
69
- return `Unable to look at ${input.path}: ${error.message}`;
70
- }
71
- }
72
-
73
- function resolveLookAtPath(source) {
74
- if (source.startsWith('file://')) return fileURLToPath(source);
75
- return path.resolve(process.cwd(), source);
76
- }
77
-
78
- function formatLookAtMediaResult(source, raw, goal) {
79
- return [
80
- `Looked at: ${source}`,
81
- `media_type: ${detectLookAtMediaType(raw)}`,
82
- `bytes: ${raw.length}`,
83
- `goal: ${goal || '(none)'}`,
84
- ].join('\n');
85
- }
86
-
87
- function detectLookAtMediaType(raw) {
88
- const imageType = detectImageMediaType(raw);
89
- if (imageType) return imageType;
90
- if (raw.subarray(0, 5).toString('ascii') === '%PDF-') return 'application/pdf';
91
- return 'application/octet-stream';
92
- }
@@ -1,51 +0,0 @@
1
- import { resolvePermissionDecision } from '../../commands/permissions.mjs';
2
- import { listConfiguredMcpServers } from '../../mcp/discover.mjs';
3
- import { callMcpTool, isMcpToolIncluded, parseMcpToolName } from '../../mcp/probe.mjs';
4
- import { runPluginEventHandlers } from '../../plugins/discover.mjs';
5
- import { isToolDisabled } from '../toolbox.mjs';
6
- import {
7
- applyToolCallDecision,
8
- createToolUseID,
9
- permissionDeniedOutput,
10
- pluginTextToolRunResult,
11
- pluginToolCallEvent,
12
- pluginToolResultEvent,
13
- pluginToolUseBlock,
14
- toolCallDecisionToolRun,
15
- validateToolCallDecision,
16
- } from './runtime.mjs';
17
-
18
- export async function executePromptMcpToolRequest(request, parsed = {}, threadId = '', plugins = { handlers: {} }) {
19
- const parsedName = parseMcpToolName(request.toolName);
20
- if (!parsedName) return { output: `Unknown tool: ${request.toolName}` };
21
- if (isToolDisabled(request.toolName, 'local-mcp', parsed)) return { output: `Tool disabled: ${request.toolName}` };
22
- const toolUseID = createToolUseID();
23
- const callDecision = await runPluginEventHandlers(
24
- plugins.handlers['tool.call'],
25
- pluginToolCallEvent(request.toolName, request.flags, threadId, toolUseID),
26
- validateToolCallDecision,
27
- );
28
- const callResult = applyToolCallDecision(request.toolName, request, callDecision);
29
- if (callResult.output) return toolCallDecisionToolRun(request.toolName, request.flags, toolUseID, callResult);
30
- request = callResult.request;
31
- const decision = resolvePermissionDecision(request.toolName, request.flags, parsed, { threadId });
32
- if (!parsed.dangerouslyAllowAll && decision.action !== 'allow') {
33
- return {
34
- output: permissionDeniedOutput(request.toolName, decision),
35
- permissionDenials: [{ tool: request.toolName, action: decision.action, reason: 'permission' }],
36
- };
37
- }
38
- const server = listConfiguredMcpServers(parsed)
39
- .find((entry) => entry.name === parsedName.serverName && entry.status === 'approved');
40
- if (!server) return { output: `Unknown MCP server: ${parsedName.serverName}` };
41
- if (!isMcpToolIncluded(server.config, parsedName.toolName)) return { output: `Tool not available: ${request.toolName}` };
42
- const output = await callMcpTool(server.config, parsedName.toolName, request.flags, server.name);
43
- const resultDecision = await runPluginEventHandlers(
44
- plugins.handlers['tool.result'],
45
- pluginToolResultEvent(request.toolName, request.flags, 'done', output, threadId, toolUseID),
46
- );
47
- return {
48
- ...pluginTextToolRunResult(resultDecision, output),
49
- toolUse: pluginToolUseBlock(request.toolName, request.flags, toolUseID),
50
- };
51
- }
@@ -1,59 +0,0 @@
1
- import { resolvePermissionDecision } from '../../commands/permissions.mjs';
2
- import { runPluginEventHandlers } from '../../plugins/discover.mjs';
3
- import { isToolDisabled } from '../toolbox.mjs';
4
- import {
5
- applyToolCallDecision,
6
- createToolUseID,
7
- permissionDeniedOutput,
8
- pluginTextToolRunResult,
9
- pluginToolCallEvent,
10
- pluginToolResultEvent,
11
- pluginToolUseBlock,
12
- toolCallDecisionToolRun,
13
- validateToolCallDecision,
14
- } from './runtime.mjs';
15
-
16
- export const TOOL_NAME = 'mermaid';
17
-
18
- export async function executePromptMermaidToolRequest(request, parsed = {}, plugins = { handlers: {} }, threadId = '') {
19
- if (isToolDisabled(TOOL_NAME, 'built-in', parsed)) return { output: `Tool disabled: ${TOOL_NAME}` };
20
- request = { ...request, flags: normalizeMermaidInput(request.flags) };
21
- if (!request.flags.code) return { output: 'mermaid requires --code' };
22
- const toolUseID = createToolUseID();
23
- const callDecision = await runPluginEventHandlers(
24
- plugins.handlers['tool.call'],
25
- pluginToolCallEvent(TOOL_NAME, request.flags, threadId, toolUseID),
26
- validateToolCallDecision,
27
- );
28
- const callResult = applyToolCallDecision(TOOL_NAME, request, callDecision);
29
- if (callResult.output) return toolCallDecisionToolRun(TOOL_NAME, request.flags, toolUseID, callResult);
30
- request = { ...callResult.request, flags: normalizeMermaidInput(callResult.request.flags) };
31
- const decision = resolvePermissionDecision(TOOL_NAME, request.flags, parsed, { threadId });
32
- if (!parsed.dangerouslyAllowAll && decision.action !== 'allow') {
33
- return {
34
- output: permissionDeniedOutput(TOOL_NAME, decision),
35
- permissionDenials: [{ tool: TOOL_NAME, action: decision.action, reason: 'permission' }],
36
- };
37
- }
38
- const output = mermaidOutput(request.flags.code);
39
- const resultDecision = await runPluginEventHandlers(
40
- plugins.handlers['tool.result'],
41
- pluginToolResultEvent(TOOL_NAME, request.flags, 'done', output, threadId, toolUseID),
42
- );
43
- return {
44
- ...pluginTextToolRunResult(resultDecision, output),
45
- toolUse: pluginToolUseBlock(TOOL_NAME, request.flags, toolUseID),
46
- };
47
- }
48
-
49
- function normalizeMermaidInput(input = {}) {
50
- const code = input.code ?? input.diagram ?? input.mermaid ?? input.source;
51
- return {
52
- ...input,
53
- code: code ? String(code) : '',
54
- };
55
- }
56
-
57
- function mermaidOutput(code) {
58
- return `\`\`\`mermaid\n${String(code).trim()}\n\`\`\``;
59
- }
@@ -1,56 +0,0 @@
1
- import { fixtureAgentResponse } from '../../agent/fixture.mjs';
2
- import { resolvePermissionDecision } from '../../commands/permissions.mjs';
3
- import { runPluginEventHandlers } from '../../plugins/discover.mjs';
4
- import { isToolDisabled } from '../toolbox.mjs';
5
- import {
6
- applyToolCallDecision,
7
- createToolUseID,
8
- permissionDeniedOutput,
9
- pluginTextToolRunResult,
10
- pluginToolCallEvent,
11
- pluginToolResultEvent,
12
- pluginToolUseBlock,
13
- toolCallDecisionToolRun,
14
- validateToolCallDecision,
15
- } from './runtime.mjs';
16
-
17
- export const TOOL_NAME = 'oracle';
18
-
19
- export async function executePromptOracleToolRequest(request, parsed = {}, plugins = { handlers: {} }, threadId = '') {
20
- if (isToolDisabled(TOOL_NAME, 'built-in', parsed)) return { output: `Tool disabled: ${TOOL_NAME}` };
21
- request = { ...request, flags: normalizeOracleInput(request.flags) };
22
- if (!request.flags.prompt) return { output: 'oracle requires --prompt' };
23
- const toolUseID = createToolUseID();
24
- const callDecision = await runPluginEventHandlers(
25
- plugins.handlers['tool.call'],
26
- pluginToolCallEvent(TOOL_NAME, request.flags, threadId, toolUseID),
27
- validateToolCallDecision,
28
- );
29
- const callResult = applyToolCallDecision(TOOL_NAME, request, callDecision);
30
- if (callResult.output) return toolCallDecisionToolRun(TOOL_NAME, request.flags, toolUseID, callResult);
31
- request = { ...callResult.request, flags: normalizeOracleInput(callResult.request.flags) };
32
- const decision = resolvePermissionDecision(TOOL_NAME, request.flags, parsed, { threadId });
33
- if (!parsed.dangerouslyAllowAll && decision.action !== 'allow') {
34
- return {
35
- output: permissionDeniedOutput(TOOL_NAME, decision),
36
- permissionDenials: [{ tool: TOOL_NAME, action: decision.action, reason: 'permission' }],
37
- };
38
- }
39
- const output = `Oracle: ${fixtureAgentResponse(request.flags.prompt, '')}`;
40
- const resultDecision = await runPluginEventHandlers(
41
- plugins.handlers['tool.result'],
42
- pluginToolResultEvent(TOOL_NAME, request.flags, 'done', output, threadId, toolUseID),
43
- );
44
- return {
45
- ...pluginTextToolRunResult(resultDecision, output),
46
- toolUse: pluginToolUseBlock(TOOL_NAME, request.flags, toolUseID),
47
- };
48
- }
49
-
50
- function normalizeOracleInput(input = {}) {
51
- const prompt = input.prompt ?? input.question ?? input.query ?? input.message;
52
- return {
53
- ...input,
54
- prompt: prompt ? String(prompt) : '',
55
- };
56
- }
@@ -1,81 +0,0 @@
1
- import { mkdirSync, writeFileSync } from 'node:fs';
2
- import path from 'node:path';
3
- import { resolvePermissionDecision } from '../../commands/permissions.mjs';
4
- import { runPluginEventHandlers } from '../../plugins/discover.mjs';
5
- import { isToolDisabled } from '../toolbox.mjs';
6
- import {
7
- applyToolCallDecision,
8
- createToolUseID,
9
- permissionDeniedOutput,
10
- pluginTextToolRunResult,
11
- pluginToolCallEvent,
12
- pluginToolResultEvent,
13
- pluginToolUseBlock,
14
- toolCallDecisionToolRun,
15
- validateToolCallDecision,
16
- } from './runtime.mjs';
17
-
18
- export const TOOL_NAME = 'painter';
19
-
20
- const PAINTER_PLACEHOLDER_PNG = Buffer.from(
21
- 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M/wHwAFeAKU5XgS2wAAAABJRU5ErkJggg==',
22
- 'base64',
23
- );
24
-
25
- export async function executePromptPainterToolRequest(request, parsed = {}, plugins = { handlers: {} }, threadId = '') {
26
- if (isToolDisabled(TOOL_NAME, 'built-in', parsed)) return { output: `Tool disabled: ${TOOL_NAME}` };
27
- request = { ...request, flags: normalizePainterInput(request.flags) };
28
- if (!request.flags.prompt) return { output: 'painter requires --prompt' };
29
- const toolUseID = createToolUseID();
30
- const callDecision = await runPluginEventHandlers(
31
- plugins.handlers['tool.call'],
32
- pluginToolCallEvent(TOOL_NAME, request.flags, threadId, toolUseID),
33
- validateToolCallDecision,
34
- );
35
- const callResult = applyToolCallDecision(TOOL_NAME, request, callDecision);
36
- if (callResult.output) return toolCallDecisionToolRun(TOOL_NAME, request.flags, toolUseID, callResult);
37
- request = { ...callResult.request, flags: normalizePainterInput(callResult.request.flags) };
38
- const decision = resolvePermissionDecision(TOOL_NAME, request.flags, parsed, { threadId });
39
- if (!parsed.dangerouslyAllowAll && decision.action !== 'allow') {
40
- return {
41
- output: permissionDeniedOutput(TOOL_NAME, decision),
42
- permissionDenials: [{ tool: TOOL_NAME, action: decision.action, reason: 'permission' }],
43
- };
44
- }
45
- const output = writePainterArtifact(request.flags);
46
- const resultDecision = await runPluginEventHandlers(
47
- plugins.handlers['tool.result'],
48
- pluginToolResultEvent(TOOL_NAME, request.flags, 'done', output, threadId, toolUseID),
49
- );
50
- return {
51
- ...pluginTextToolRunResult(resultDecision, output),
52
- toolUse: pluginToolUseBlock(TOOL_NAME, request.flags, toolUseID),
53
- };
54
- }
55
-
56
- function normalizePainterInput(input = {}) {
57
- const prompt = input.prompt ?? input.description ?? input.text ?? '';
58
- const output = input.output ?? input.path ?? input.file ?? 'coven-code-painter-output.png';
59
- const references = [input.reference, input.references, input.image, input.images]
60
- .flat()
61
- .filter(Boolean)
62
- .map(String);
63
- return {
64
- ...input,
65
- prompt: String(prompt),
66
- output: String(output),
67
- references,
68
- };
69
- }
70
-
71
- function writePainterArtifact(input) {
72
- const outputPath = path.resolve(process.cwd(), input.output);
73
- mkdirSync(path.dirname(outputPath), { recursive: true });
74
- writeFileSync(outputPath, PAINTER_PLACEHOLDER_PNG);
75
- return [
76
- `Generated image: ${input.output}`,
77
- 'media_type: image/png',
78
- `prompt: ${input.prompt}`,
79
- ...(input.references.length ? [`references: ${input.references.join(', ')}`] : []),
80
- ].join('\n');
81
- }
@@ -1,53 +0,0 @@
1
- import { resolvePermissionDecision } from '../../commands/permissions.mjs';
2
- import { createPluginToolContext, runPluginEventHandlers } from '../../plugins/discover.mjs';
3
- import { isToolDisabled } from '../toolbox.mjs';
4
- import {
5
- applyToolCallDecision,
6
- createToolUseID,
7
- normalizePluginToolExecuteOutput,
8
- normalizePluginToolOutput,
9
- permissionDeniedOutput,
10
- pluginToolCallEvent,
11
- pluginToolResultDecisionExitCode,
12
- pluginToolResultDecisionOutput,
13
- pluginToolResultEvent,
14
- pluginToolUseBlock,
15
- toolCallDecisionToolRun,
16
- validateToolCallDecision,
17
- } from './runtime.mjs';
18
-
19
- export async function executePromptPluginToolRequest(tool, request, parsed = {}, plugins = { handlers: {} }, threadId = '') {
20
- if (isToolDisabled(tool.name, 'plugin', parsed)) return { output: `Tool disabled: ${tool.name}` };
21
- const toolUseID = createToolUseID();
22
- const callDecision = await runPluginEventHandlers(
23
- plugins.handlers['tool.call'],
24
- pluginToolCallEvent(tool.name, request.flags, threadId, toolUseID),
25
- validateToolCallDecision,
26
- );
27
- const callResult = applyToolCallDecision(tool.name, request, callDecision);
28
- if (callResult.output) return toolCallDecisionToolRun(tool.name, request.flags, toolUseID, callResult);
29
- request = callResult.request;
30
- const decision = resolvePermissionDecision(tool.name, request.flags, parsed, { threadId });
31
- if (!parsed.dangerouslyAllowAll && decision.action !== 'allow') {
32
- return {
33
- output: permissionDeniedOutput(tool.name, decision),
34
- permissionDenials: [{ tool: tool.name, action: decision.action, reason: 'permission' }],
35
- };
36
- }
37
- const output = typeof tool.execute === 'function' ? await tool.execute(request.flags, createPluginToolContext()) : undefined;
38
- const normalizedOutput = normalizePluginToolExecuteOutput(output);
39
- const resultDecision = await runPluginEventHandlers(
40
- plugins.handlers['tool.result'],
41
- pluginToolResultEvent(tool.name, request.flags, 'done', normalizedOutput.raw, threadId, toolUseID),
42
- );
43
- const finalOutput = normalizePluginToolOutput(
44
- pluginToolResultDecisionOutput(resultDecision, normalizedOutput.raw),
45
- );
46
- const exitCode = pluginToolResultDecisionExitCode(resultDecision);
47
- return {
48
- output: finalOutput.text,
49
- toolResultOutput: finalOutput.raw,
50
- exitCode,
51
- toolUse: pluginToolUseBlock(tool.name, request.flags, toolUseID),
52
- };
53
- }