@covibes/zeroshot 5.4.0 → 5.4.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.
- package/LICENSE +1 -1
- package/README.md +8 -465
- package/cli/index.js +101 -5231
- package/package.json +16 -130
- package/CHANGELOG.md +0 -537
- package/cli/commands/providers.js +0 -149
- package/cli/lib/first-run.js +0 -211
- package/cli/lib/update-checker.js +0 -281
- package/cli/message-formatter-utils.js +0 -75
- package/cli/message-formatters-normal.js +0 -275
- package/cli/message-formatters-watch.js +0 -181
- package/cluster-templates/base-templates/debug-workflow.json +0 -375
- package/cluster-templates/base-templates/full-workflow.json +0 -581
- package/cluster-templates/base-templates/single-worker.json +0 -63
- package/cluster-templates/base-templates/worker-validator.json +0 -208
- package/cluster-templates/conductor-bootstrap.json +0 -124
- package/docker/zeroshot-cluster/Dockerfile +0 -152
- package/docker/zeroshot-cluster/pre-baked-deps.json +0 -28
- package/lib/completion.js +0 -174
- package/lib/docker-config.js +0 -220
- package/lib/git-remote-utils.js +0 -165
- package/lib/id-detector.js +0 -56
- package/lib/provider-defaults.js +0 -62
- package/lib/provider-detection.js +0 -59
- package/lib/provider-names.js +0 -57
- package/lib/settings/claude-auth.js +0 -78
- package/lib/settings.js +0 -503
- package/lib/stream-json-parser.js +0 -10
- package/scripts/fix-node-pty-permissions.js +0 -75
- package/scripts/record-demo.sh +0 -279
- package/scripts/setup-merge-queue.sh +0 -170
- package/scripts/test-install.sh +0 -40
- package/scripts/validate-templates.js +0 -100
- package/src/agent/agent-config.js +0 -246
- package/src/agent/agent-context-builder.js +0 -444
- package/src/agent/agent-hook-executor.js +0 -599
- package/src/agent/agent-lifecycle.js +0 -743
- package/src/agent/agent-stuck-detector.js +0 -256
- package/src/agent/agent-task-executor.js +0 -1690
- package/src/agent/agent-trigger-evaluator.js +0 -67
- package/src/agent/output-extraction.js +0 -217
- package/src/agent/output-reformatter.js +0 -175
- package/src/agent/schema-utils.js +0 -146
- package/src/agent-wrapper.js +0 -579
- package/src/agents/git-pusher-template.js +0 -285
- package/src/attach/attach-client.js +0 -438
- package/src/attach/attach-server.js +0 -543
- package/src/attach/index.js +0 -35
- package/src/attach/protocol.js +0 -220
- package/src/attach/ring-buffer.js +0 -121
- package/src/attach/socket-discovery.js +0 -267
- package/src/claude-task-runner.js +0 -574
- package/src/config-router.js +0 -80
- package/src/config-validator.js +0 -1925
- package/src/copy-worker.js +0 -43
- package/src/input-helpers.js +0 -65
- package/src/isolation-manager.js +0 -1471
- package/src/issue-providers/README.md +0 -305
- package/src/issue-providers/azure-devops-provider.js +0 -273
- package/src/issue-providers/base-provider.js +0 -232
- package/src/issue-providers/github-provider.js +0 -179
- package/src/issue-providers/gitlab-provider.js +0 -241
- package/src/issue-providers/index.js +0 -196
- package/src/issue-providers/jira-provider.js +0 -239
- package/src/ledger.js +0 -631
- package/src/lib/safe-exec.js +0 -88
- package/src/logic-engine.js +0 -223
- package/src/message-bus-bridge.js +0 -139
- package/src/message-bus.js +0 -249
- package/src/name-generator.js +0 -232
- package/src/orchestrator.js +0 -2815
- package/src/preflight.js +0 -639
- package/src/process-metrics.js +0 -608
- package/src/providers/anthropic/cli-builder.js +0 -73
- package/src/providers/anthropic/index.js +0 -204
- package/src/providers/anthropic/models.js +0 -23
- package/src/providers/anthropic/output-parser.js +0 -177
- package/src/providers/base-provider.js +0 -251
- package/src/providers/capabilities.js +0 -60
- package/src/providers/google/cli-builder.js +0 -55
- package/src/providers/google/index.js +0 -116
- package/src/providers/google/models.js +0 -24
- package/src/providers/google/output-parser.js +0 -101
- package/src/providers/index.js +0 -91
- package/src/providers/openai/cli-builder.js +0 -133
- package/src/providers/openai/index.js +0 -136
- package/src/providers/openai/models.js +0 -21
- package/src/providers/openai/output-parser.js +0 -143
- package/src/providers/opencode/cli-builder.js +0 -42
- package/src/providers/opencode/index.js +0 -103
- package/src/providers/opencode/models.js +0 -55
- package/src/providers/opencode/output-parser.js +0 -122
- package/src/schemas/sub-cluster.js +0 -185
- package/src/status-footer.js +0 -1026
- package/src/sub-cluster-wrapper.js +0 -601
- package/src/task-runner.js +0 -30
- package/src/template-resolver.js +0 -372
- package/src/tui/CHANGES.txt +0 -133
- package/src/tui/LAYOUT.md +0 -261
- package/src/tui/README.txt +0 -192
- package/src/tui/TWO-LEVEL-NAVIGATION.md +0 -186
- package/src/tui/data-poller.js +0 -349
- package/src/tui/demo.js +0 -208
- package/src/tui/formatters.js +0 -129
- package/src/tui/index.js +0 -193
- package/src/tui/keybindings.js +0 -324
- package/src/tui/layout.js +0 -334
- package/src/tui/renderer.js +0 -184
- package/task-lib/attachable-watcher.js +0 -309
- package/task-lib/claude-recovery.js +0 -156
- package/task-lib/commands/clean.js +0 -50
- package/task-lib/commands/episodes.js +0 -105
- package/task-lib/commands/get-log-path.js +0 -23
- package/task-lib/commands/kill.js +0 -32
- package/task-lib/commands/list.js +0 -105
- package/task-lib/commands/logs.js +0 -453
- package/task-lib/commands/resume.js +0 -42
- package/task-lib/commands/run.js +0 -57
- package/task-lib/commands/schedule.js +0 -105
- package/task-lib/commands/scheduler-cmd.js +0 -96
- package/task-lib/commands/schedules.js +0 -148
- package/task-lib/commands/status.js +0 -44
- package/task-lib/commands/unschedule.js +0 -16
- package/task-lib/completion.js +0 -9
- package/task-lib/config.js +0 -8
- package/task-lib/name-generator.js +0 -230
- package/task-lib/package.json +0 -3
- package/task-lib/runner.js +0 -201
- package/task-lib/scheduler.js +0 -252
- package/task-lib/store.js +0 -529
- package/task-lib/tui/formatters.js +0 -215
- package/task-lib/tui/index.js +0 -197
- package/task-lib/tui/layout.js +0 -111
- package/task-lib/tui/renderer.js +0 -129
- package/task-lib/tui.js +0 -425
- package/task-lib/watcher.js +0 -226
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
function safeJsonParse(value, fallback) {
|
|
2
|
-
try {
|
|
3
|
-
return JSON.parse(value);
|
|
4
|
-
} catch {
|
|
5
|
-
return fallback;
|
|
6
|
-
}
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
function parseAssistantMessage(item) {
|
|
10
|
-
const events = [];
|
|
11
|
-
const content = Array.isArray(item.content)
|
|
12
|
-
? item.content
|
|
13
|
-
: [{ type: 'text', text: item.content }];
|
|
14
|
-
const text = content
|
|
15
|
-
.filter((c) => c.type === 'text')
|
|
16
|
-
.map((c) => c.text)
|
|
17
|
-
.join('');
|
|
18
|
-
const thinking = content
|
|
19
|
-
.filter((c) => c.type === 'thinking' || c.type === 'reasoning')
|
|
20
|
-
.map((c) => c.text)
|
|
21
|
-
.join('');
|
|
22
|
-
if (text) events.push({ type: 'text', text });
|
|
23
|
-
if (thinking) events.push({ type: 'thinking', text: thinking });
|
|
24
|
-
return events;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function parseFunctionCall(item) {
|
|
28
|
-
const toolId = item.call_id || item.id || item.tool_call_id || item.tool_id;
|
|
29
|
-
const args =
|
|
30
|
-
typeof item.arguments === 'string' ? safeJsonParse(item.arguments, {}) : item.arguments || {};
|
|
31
|
-
return {
|
|
32
|
-
type: 'tool_call',
|
|
33
|
-
toolName: item.name,
|
|
34
|
-
toolId,
|
|
35
|
-
input: args,
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function parseFunctionCallOutput(item) {
|
|
40
|
-
const toolId = item.call_id || item.id || item.tool_call_id || item.tool_id;
|
|
41
|
-
const content = item.output ?? item.result ?? item.content ?? '';
|
|
42
|
-
return {
|
|
43
|
-
type: 'tool_result',
|
|
44
|
-
toolId,
|
|
45
|
-
content,
|
|
46
|
-
isError: !!item.error,
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function parseItem(item) {
|
|
51
|
-
const events = [];
|
|
52
|
-
|
|
53
|
-
// Handle assistant messages (Claude-style: type=message, role=assistant)
|
|
54
|
-
if (item.type === 'message' && item.role === 'assistant') {
|
|
55
|
-
events.push(...parseAssistantMessage(item));
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Handle agent messages (Codex-style: type=agent_message, text=string)
|
|
59
|
-
if (item.type === 'agent_message' && item.text) {
|
|
60
|
-
events.push({ type: 'text', text: item.text });
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if (item.type === 'function_call') {
|
|
64
|
-
events.push(parseFunctionCall(item));
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
if (item.type === 'function_call_output') {
|
|
68
|
-
events.push(parseFunctionCallOutput(item));
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
if (events.length === 1) return events[0];
|
|
72
|
-
if (events.length > 1) return events;
|
|
73
|
-
return null;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function parseEvent(line, options = {}) {
|
|
77
|
-
let event;
|
|
78
|
-
try {
|
|
79
|
-
event = JSON.parse(line);
|
|
80
|
-
} catch {
|
|
81
|
-
return null;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
switch (event.type) {
|
|
85
|
-
case 'thread.started':
|
|
86
|
-
case 'turn.started':
|
|
87
|
-
return null;
|
|
88
|
-
|
|
89
|
-
case 'item.created':
|
|
90
|
-
case 'item.completed':
|
|
91
|
-
return parseItem(event.item);
|
|
92
|
-
|
|
93
|
-
case 'turn.completed': {
|
|
94
|
-
const usage = event.usage || event.response?.usage || {};
|
|
95
|
-
return {
|
|
96
|
-
type: 'result',
|
|
97
|
-
success: true,
|
|
98
|
-
inputTokens: usage.input_tokens || 0,
|
|
99
|
-
outputTokens: usage.output_tokens || 0,
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
case 'turn.failed':
|
|
104
|
-
return {
|
|
105
|
-
type: 'result',
|
|
106
|
-
success: false,
|
|
107
|
-
error: event.error?.message || event.error || 'Turn failed',
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
default:
|
|
111
|
-
// Only log warnings for actual unknown string types, not malformed events
|
|
112
|
-
// (undefined/object types are just noise from non-standard CLI output)
|
|
113
|
-
if (options.onUnknown && typeof event.type === 'string') {
|
|
114
|
-
options.onUnknown(event.type, event);
|
|
115
|
-
}
|
|
116
|
-
return null;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function parseChunk(chunk, options = {}) {
|
|
121
|
-
const events = [];
|
|
122
|
-
const lines = chunk.split('\n');
|
|
123
|
-
|
|
124
|
-
for (const line of lines) {
|
|
125
|
-
if (!line.trim()) continue;
|
|
126
|
-
const event = parseEvent(line, options);
|
|
127
|
-
if (!event) continue;
|
|
128
|
-
if (Array.isArray(event)) {
|
|
129
|
-
events.push(...event);
|
|
130
|
-
} else {
|
|
131
|
-
events.push(event);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
return events;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
module.exports = {
|
|
139
|
-
parseEvent,
|
|
140
|
-
parseChunk,
|
|
141
|
-
parseItem,
|
|
142
|
-
safeJsonParse,
|
|
143
|
-
};
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
function buildCommand(context, options = {}) {
|
|
2
|
-
const { modelSpec, outputFormat, jsonSchema, cwd, cliFeatures = {} } = options;
|
|
3
|
-
|
|
4
|
-
let finalContext = context;
|
|
5
|
-
if (jsonSchema) {
|
|
6
|
-
const schemaStr =
|
|
7
|
-
typeof jsonSchema === 'string' ? jsonSchema : JSON.stringify(jsonSchema, null, 2);
|
|
8
|
-
finalContext =
|
|
9
|
-
context +
|
|
10
|
-
`\n\n## OUTPUT FORMAT (CRITICAL - REQUIRED)\n\nYou MUST respond with a JSON object that exactly matches this schema. NO markdown, NO explanation, NO code blocks. ONLY the raw JSON object.\n\nSchema:\n\`\`\`json\n${schemaStr}\n\`\`\`\n\nYour response must be ONLY valid JSON. Start with { and end with }. Nothing else.`;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const args = ['run'];
|
|
14
|
-
|
|
15
|
-
if ((outputFormat === 'stream-json' || outputFormat === 'json') && cliFeatures.supportsJson) {
|
|
16
|
-
args.push('--format', 'json');
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
if (modelSpec?.model) {
|
|
20
|
-
args.push('--model', modelSpec.model);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if (modelSpec?.reasoningEffort && cliFeatures.supportsVariant) {
|
|
24
|
-
args.push('--variant', modelSpec.reasoningEffort);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (cwd && cliFeatures.supportsCwd) {
|
|
28
|
-
args.push('--cwd', cwd);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
args.push(finalContext);
|
|
32
|
-
|
|
33
|
-
return {
|
|
34
|
-
binary: 'opencode',
|
|
35
|
-
args,
|
|
36
|
-
env: {},
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
module.exports = {
|
|
41
|
-
buildCommand,
|
|
42
|
-
};
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
const BaseProvider = require('../base-provider');
|
|
2
|
-
const { commandExists, getCommandPath, getHelpOutput } = require('../../../lib/provider-detection');
|
|
3
|
-
const { buildCommand } = require('./cli-builder');
|
|
4
|
-
const { parseEvent } = require('./output-parser');
|
|
5
|
-
const {
|
|
6
|
-
MODEL_CATALOG,
|
|
7
|
-
LEVEL_MAPPING,
|
|
8
|
-
DEFAULT_LEVEL,
|
|
9
|
-
DEFAULT_MAX_LEVEL,
|
|
10
|
-
DEFAULT_MIN_LEVEL,
|
|
11
|
-
} = require('./models');
|
|
12
|
-
|
|
13
|
-
const warned = new Set();
|
|
14
|
-
|
|
15
|
-
class OpencodeProvider extends BaseProvider {
|
|
16
|
-
constructor() {
|
|
17
|
-
super({ name: 'opencode', displayName: 'Opencode', cliCommand: 'opencode' });
|
|
18
|
-
this._cliFeatures = null;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
isAvailable() {
|
|
22
|
-
return commandExists(this.cliCommand);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
getCliPath() {
|
|
26
|
-
return getCommandPath(this.cliCommand) || this.cliCommand;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
getInstallInstructions() {
|
|
30
|
-
return 'See https://opencode.ai for installation instructions.';
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
getAuthInstructions() {
|
|
34
|
-
return 'opencode auth login';
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
getCliFeatures() {
|
|
38
|
-
if (this._cliFeatures) return this._cliFeatures;
|
|
39
|
-
const help = getHelpOutput(this.cliCommand, ['run']);
|
|
40
|
-
const unknown = !help;
|
|
41
|
-
|
|
42
|
-
const features = {
|
|
43
|
-
supportsJson: unknown ? true : /--format\b/.test(help),
|
|
44
|
-
supportsModel: unknown ? true : /--model\b/.test(help),
|
|
45
|
-
supportsVariant: unknown ? true : /--variant\b/.test(help),
|
|
46
|
-
supportsCwd: unknown ? false : /--cwd\b/.test(help),
|
|
47
|
-
supportsAutoApprove: false,
|
|
48
|
-
unknown,
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
this._cliFeatures = features;
|
|
52
|
-
return features;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
getCredentialPaths() {
|
|
56
|
-
return ['~/.local/share/opencode'];
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
buildCommand(context, options) {
|
|
60
|
-
const cliFeatures = options.cliFeatures || {};
|
|
61
|
-
|
|
62
|
-
if (options.modelSpec?.reasoningEffort && cliFeatures.supportsVariant === false) {
|
|
63
|
-
this._warnOnce(
|
|
64
|
-
'opencode-variant',
|
|
65
|
-
'Opencode CLI does not support --variant; skipping reasoningEffort.'
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return buildCommand(context, { ...options, cliFeatures });
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
parseEvent(line) {
|
|
73
|
-
return parseEvent(line);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
getModelCatalog() {
|
|
77
|
-
return MODEL_CATALOG;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
getLevelMapping() {
|
|
81
|
-
return LEVEL_MAPPING;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
getDefaultLevel() {
|
|
85
|
-
return DEFAULT_LEVEL;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
getDefaultMaxLevel() {
|
|
89
|
-
return DEFAULT_MAX_LEVEL;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
getDefaultMinLevel() {
|
|
93
|
-
return DEFAULT_MIN_LEVEL;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
_warnOnce(key, message) {
|
|
97
|
-
if (warned.has(key)) return;
|
|
98
|
-
warned.add(key);
|
|
99
|
-
console.warn(`⚠️ ${message}`);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
module.exports = OpencodeProvider;
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
const MODEL_CATALOG = {
|
|
2
|
-
'opencode/big-pickle': { rank: 1 },
|
|
3
|
-
'opencode/glm-4.7-free': { rank: 1 },
|
|
4
|
-
'opencode/gpt-5-nano': { rank: 1 },
|
|
5
|
-
'opencode/grok-code': { rank: 1 },
|
|
6
|
-
'opencode/minimax-m2.1-free': { rank: 1 },
|
|
7
|
-
'google/gemini-1.5-flash': { rank: 1 },
|
|
8
|
-
'google/gemini-1.5-flash-8b': { rank: 1 },
|
|
9
|
-
'google/gemini-1.5-pro': { rank: 1 },
|
|
10
|
-
'google/gemini-2.0-flash': { rank: 1 },
|
|
11
|
-
'google/gemini-2.0-flash-lite': { rank: 1 },
|
|
12
|
-
'google/gemini-2.5-flash': { rank: 1 },
|
|
13
|
-
'google/gemini-2.5-flash-image': { rank: 1 },
|
|
14
|
-
'google/gemini-2.5-flash-image-preview': { rank: 1 },
|
|
15
|
-
'google/gemini-2.5-flash-lite': { rank: 1 },
|
|
16
|
-
'google/gemini-2.5-flash-lite-preview-06-17': { rank: 1 },
|
|
17
|
-
'google/gemini-2.5-flash-lite-preview-09-2025': { rank: 1 },
|
|
18
|
-
'google/gemini-2.5-flash-preview-04-17': { rank: 1 },
|
|
19
|
-
'google/gemini-2.5-flash-preview-05-20': { rank: 1 },
|
|
20
|
-
'google/gemini-2.5-flash-preview-09-2025': { rank: 1 },
|
|
21
|
-
'google/gemini-2.5-flash-preview-tts': { rank: 1 },
|
|
22
|
-
'google/gemini-2.5-pro': { rank: 1 },
|
|
23
|
-
'google/gemini-2.5-pro-preview-05-06': { rank: 1 },
|
|
24
|
-
'google/gemini-2.5-pro-preview-06-05': { rank: 1 },
|
|
25
|
-
'google/gemini-2.5-pro-preview-tts': { rank: 1 },
|
|
26
|
-
'google/gemini-3-flash-preview': { rank: 1 },
|
|
27
|
-
'google/gemini-3-pro-preview': { rank: 1 },
|
|
28
|
-
'google/gemini-embedding-001': { rank: 1 },
|
|
29
|
-
'google/gemini-flash-latest': { rank: 1 },
|
|
30
|
-
'google/gemini-flash-lite-latest': { rank: 1 },
|
|
31
|
-
'google/gemini-live-2.5-flash': { rank: 1 },
|
|
32
|
-
'google/gemini-live-2.5-flash-preview-native-audio': { rank: 1 },
|
|
33
|
-
'openai/gpt-5.1-codex-max': { rank: 1 },
|
|
34
|
-
'openai/gpt-5.1-codex-mini': { rank: 1 },
|
|
35
|
-
'openai/gpt-5.2': { rank: 1 },
|
|
36
|
-
'openai/gpt-5.2-codex': { rank: 1 },
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
const LEVEL_MAPPING = {
|
|
40
|
-
level1: { rank: 1, model: null, reasoningEffort: 'low' },
|
|
41
|
-
level2: { rank: 2, model: null, reasoningEffort: 'medium' },
|
|
42
|
-
level3: { rank: 3, model: null, reasoningEffort: 'high' },
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const DEFAULT_LEVEL = 'level2';
|
|
46
|
-
const DEFAULT_MAX_LEVEL = 'level3';
|
|
47
|
-
const DEFAULT_MIN_LEVEL = 'level1';
|
|
48
|
-
|
|
49
|
-
module.exports = {
|
|
50
|
-
MODEL_CATALOG,
|
|
51
|
-
LEVEL_MAPPING,
|
|
52
|
-
DEFAULT_LEVEL,
|
|
53
|
-
DEFAULT_MAX_LEVEL,
|
|
54
|
-
DEFAULT_MIN_LEVEL,
|
|
55
|
-
};
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
function parseToolPart(part) {
|
|
2
|
-
const state = part.state || {};
|
|
3
|
-
|
|
4
|
-
if (state.status === 'pending' || state.status === 'running') {
|
|
5
|
-
return {
|
|
6
|
-
type: 'tool_call',
|
|
7
|
-
toolName: part.tool,
|
|
8
|
-
toolId: part.callID,
|
|
9
|
-
input: state.input || {},
|
|
10
|
-
};
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
if (state.status === 'completed') {
|
|
14
|
-
return {
|
|
15
|
-
type: 'tool_result',
|
|
16
|
-
toolId: part.callID,
|
|
17
|
-
content: state.output || '',
|
|
18
|
-
isError: false,
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
if (state.status === 'error') {
|
|
23
|
-
return {
|
|
24
|
-
type: 'tool_result',
|
|
25
|
-
toolId: part.callID,
|
|
26
|
-
content: state.error || '',
|
|
27
|
-
isError: true,
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
return null;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function parseStepFinish(part) {
|
|
35
|
-
const tokens = part.tokens || {};
|
|
36
|
-
return {
|
|
37
|
-
type: 'result',
|
|
38
|
-
success: true,
|
|
39
|
-
inputTokens: tokens.input || 0,
|
|
40
|
-
outputTokens: tokens.output || 0,
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function parsePart(part) {
|
|
45
|
-
if (!part || typeof part !== 'object') return null;
|
|
46
|
-
|
|
47
|
-
if (part.type === 'text' && part.text) {
|
|
48
|
-
return { type: 'text', text: part.text };
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if (part.type === 'reasoning' && part.text) {
|
|
52
|
-
return { type: 'thinking', text: part.text };
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if (part.type === 'tool') {
|
|
56
|
-
return parseToolPart(part);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (part.type === 'step-finish') {
|
|
60
|
-
return parseStepFinish(part);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return null;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function parseErrorEvent(event) {
|
|
67
|
-
const error = event.error || {};
|
|
68
|
-
return {
|
|
69
|
-
type: 'result',
|
|
70
|
-
success: false,
|
|
71
|
-
error: error.data?.message || error.message || error.name || 'Unknown error',
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function parseEvent(line) {
|
|
76
|
-
let event;
|
|
77
|
-
try {
|
|
78
|
-
event = JSON.parse(line);
|
|
79
|
-
} catch {
|
|
80
|
-
return null;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if (!event || typeof event !== 'object') return null;
|
|
84
|
-
|
|
85
|
-
if (event.type === 'error') {
|
|
86
|
-
return parseErrorEvent(event);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
if (event.type === 'text' || event.type === 'step_start' || event.type === 'step_finish') {
|
|
90
|
-
return parsePart(event.part || event);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
if (event.type === 'message.part.updated') {
|
|
94
|
-
return parsePart(event.properties?.part);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
return null;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function parseChunk(chunk) {
|
|
101
|
-
const events = [];
|
|
102
|
-
const lines = chunk.split('\n');
|
|
103
|
-
|
|
104
|
-
for (const line of lines) {
|
|
105
|
-
if (!line.trim()) continue;
|
|
106
|
-
const event = parseEvent(line);
|
|
107
|
-
if (!event) continue;
|
|
108
|
-
if (Array.isArray(event)) {
|
|
109
|
-
events.push(...event);
|
|
110
|
-
} else {
|
|
111
|
-
events.push(event);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
return events;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
module.exports = {
|
|
119
|
-
parseEvent,
|
|
120
|
-
parseChunk,
|
|
121
|
-
parsePart,
|
|
122
|
-
};
|
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sub-Cluster Schema
|
|
3
|
-
*
|
|
4
|
-
* Defines the structure for nested clusters where an agent can be replaced
|
|
5
|
-
* with an entire cluster configuration, enabling recursive composition.
|
|
6
|
-
*
|
|
7
|
-
* Example:
|
|
8
|
-
* {
|
|
9
|
-
* "id": "implementation-cluster",
|
|
10
|
-
* "type": "subcluster",
|
|
11
|
-
* "config": {
|
|
12
|
-
* "agents": [
|
|
13
|
-
* { "id": "worker", "role": "implementation", ... },
|
|
14
|
-
* { "id": "validator", "role": "validator", ... }
|
|
15
|
-
* ]
|
|
16
|
-
* },
|
|
17
|
-
* "triggers": [{ "topic": "PLAN_READY" }],
|
|
18
|
-
* "hooks": {
|
|
19
|
-
* "onComplete": {
|
|
20
|
-
* "action": "publish_message",
|
|
21
|
-
* "config": { "topic": "IMPLEMENTATION_COMPLETE" }
|
|
22
|
-
* }
|
|
23
|
-
* }
|
|
24
|
-
* }
|
|
25
|
-
*/
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Validate sub-cluster agent configuration
|
|
29
|
-
* @param {Object} agentConfig - Agent config with type: 'subcluster'
|
|
30
|
-
* @param {Number} depth - Current nesting depth (for recursion limit)
|
|
31
|
-
* @returns {{ valid: boolean, errors: string[], warnings: string[] }}
|
|
32
|
-
*/
|
|
33
|
-
const MAX_SUBCLUSTER_DEPTH = 5;
|
|
34
|
-
|
|
35
|
-
function validateSubCluster(agentConfig, depth = 0) {
|
|
36
|
-
const errors = [];
|
|
37
|
-
const warnings = [];
|
|
38
|
-
|
|
39
|
-
// Max nesting depth to prevent infinite recursion
|
|
40
|
-
if (depth > MAX_SUBCLUSTER_DEPTH) {
|
|
41
|
-
errors.push(
|
|
42
|
-
`Sub-cluster '${agentConfig.id}' exceeds max nesting depth (${MAX_SUBCLUSTER_DEPTH})`
|
|
43
|
-
);
|
|
44
|
-
return buildValidationResult(errors, warnings);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// Validate required fields
|
|
48
|
-
if (agentConfig.type !== 'subcluster') {
|
|
49
|
-
errors.push(`Agent '${agentConfig.id}' must have type: 'subcluster'`);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (!validateSubClusterConfig(agentConfig, depth, errors, warnings)) {
|
|
53
|
-
return buildValidationResult(errors, warnings);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Validate triggers (sub-cluster must have triggers to activate)
|
|
57
|
-
validateSubClusterTriggers(agentConfig, errors);
|
|
58
|
-
|
|
59
|
-
// Validate hooks structure
|
|
60
|
-
validateSubClusterHooks(agentConfig, errors);
|
|
61
|
-
|
|
62
|
-
// Check for context bridging configuration
|
|
63
|
-
validateContextStrategy(agentConfig, errors);
|
|
64
|
-
|
|
65
|
-
return buildValidationResult(errors, warnings);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function buildValidationResult(errors, warnings) {
|
|
69
|
-
return {
|
|
70
|
-
valid: errors.length === 0,
|
|
71
|
-
errors,
|
|
72
|
-
warnings,
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function validateSubClusterConfig(agentConfig, depth, errors, warnings) {
|
|
77
|
-
if (!agentConfig.config) {
|
|
78
|
-
errors.push(`Sub-cluster '${agentConfig.id}' missing config field`);
|
|
79
|
-
return false;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (!agentConfig.config.agents || !Array.isArray(agentConfig.config.agents)) {
|
|
83
|
-
errors.push(`Sub-cluster '${agentConfig.id}' config.agents must be an array`);
|
|
84
|
-
return false;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
if (agentConfig.config.agents.length === 0) {
|
|
88
|
-
errors.push(`Sub-cluster '${agentConfig.id}' config.agents cannot be empty`);
|
|
89
|
-
return false;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Recursively validate nested cluster config
|
|
93
|
-
const configValidator = require('../config-validator');
|
|
94
|
-
const childValidation = configValidator.validateConfig(agentConfig.config, depth + 1);
|
|
95
|
-
|
|
96
|
-
if (!childValidation.valid) {
|
|
97
|
-
errors.push(...childValidation.errors.map((e) => `Sub-cluster '${agentConfig.id}': ${e}`));
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
warnings.push(...childValidation.warnings.map((w) => `Sub-cluster '${agentConfig.id}': ${w}`));
|
|
101
|
-
return true;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function validateSubClusterTriggers(agentConfig, errors) {
|
|
105
|
-
if (!agentConfig.triggers || agentConfig.triggers.length === 0) {
|
|
106
|
-
errors.push(`Sub-cluster '${agentConfig.id}' must have triggers to activate`);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
function validateSubClusterHooks(agentConfig, errors) {
|
|
111
|
-
if (!agentConfig.hooks?.onComplete) {
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const hook = agentConfig.hooks.onComplete;
|
|
116
|
-
if (!hook.action) {
|
|
117
|
-
errors.push(`Sub-cluster '${agentConfig.id}' onComplete hook missing action`);
|
|
118
|
-
}
|
|
119
|
-
if (hook.action === 'publish_message' && !hook.config?.topic) {
|
|
120
|
-
errors.push(`Sub-cluster '${agentConfig.id}' onComplete hook missing config.topic`);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
function validateContextStrategy(agentConfig, errors) {
|
|
125
|
-
const parentTopics = agentConfig.contextStrategy?.parentTopics;
|
|
126
|
-
if (!parentTopics) {
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
if (!Array.isArray(parentTopics)) {
|
|
131
|
-
errors.push(`Sub-cluster '${agentConfig.id}' contextStrategy.parentTopics must be an array`);
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// Validate each parent topic is a string
|
|
136
|
-
for (const topic of parentTopics) {
|
|
137
|
-
if (typeof topic !== 'string') {
|
|
138
|
-
errors.push(
|
|
139
|
-
`Sub-cluster '${agentConfig.id}' parentTopics must contain strings, got ${typeof topic}`
|
|
140
|
-
);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Get default sub-cluster template
|
|
147
|
-
* @returns {Object} Default sub-cluster configuration
|
|
148
|
-
*/
|
|
149
|
-
function getDefaultSubCluster() {
|
|
150
|
-
return {
|
|
151
|
-
id: 'example-subcluster',
|
|
152
|
-
type: 'subcluster',
|
|
153
|
-
role: 'orchestrator',
|
|
154
|
-
config: {
|
|
155
|
-
agents: [
|
|
156
|
-
{
|
|
157
|
-
id: 'worker',
|
|
158
|
-
role: 'implementation',
|
|
159
|
-
triggers: [{ topic: 'PARENT_TRIGGER' }],
|
|
160
|
-
hooks: {
|
|
161
|
-
onComplete: {
|
|
162
|
-
action: 'publish_message',
|
|
163
|
-
config: { topic: 'WORK_COMPLETE' },
|
|
164
|
-
},
|
|
165
|
-
},
|
|
166
|
-
},
|
|
167
|
-
],
|
|
168
|
-
},
|
|
169
|
-
triggers: [{ topic: 'START_WORK' }],
|
|
170
|
-
hooks: {
|
|
171
|
-
onComplete: {
|
|
172
|
-
action: 'publish_message',
|
|
173
|
-
config: { topic: 'SUBCLUSTER_COMPLETE' },
|
|
174
|
-
},
|
|
175
|
-
},
|
|
176
|
-
contextStrategy: {
|
|
177
|
-
parentTopics: ['ISSUE_OPENED', 'PLAN_READY'],
|
|
178
|
-
},
|
|
179
|
-
};
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
module.exports = {
|
|
183
|
-
validateSubCluster,
|
|
184
|
-
getDefaultSubCluster,
|
|
185
|
-
};
|