@smartmemory/compose 0.1.1-beta → 0.1.3-beta
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/.claude/skills/bug-fix/SKILL.md +143 -0
- package/.claude/skills/compose/SKILL.md +604 -0
- package/.compose-deps.json +89 -0
- package/README.md +47 -983
- package/bin/compose.js +473 -0
- package/contracts/comp-obs-contract.schema.json +362 -0
- package/contracts/cross-model-review-result.json +78 -0
- package/contracts/review-result.json +126 -0
- package/dist/assets/{_baseUniq-CQwX6VLz.js → _baseUniq-D-avYfn5.js} +1 -1
- package/dist/assets/{arc-SxJ2J1sh.js → arc-BC4dfQ-X.js} +1 -1
- package/dist/assets/{architectureDiagram-Q4EWVU46-BykunY1F.js → architectureDiagram-Q4EWVU46-BZmFXnGI.js} +1 -1
- package/dist/assets/{blockDiagram-DXYQGD6D-ohAKBOUw.js → blockDiagram-DXYQGD6D-DlfWSuux.js} +1 -1
- package/dist/assets/{c4Diagram-AHTNJAMY-DBDC3ENB.js → c4Diagram-AHTNJAMY-Y__uJrRx.js} +1 -1
- package/dist/assets/channel-LRG9kHqJ.js +1 -0
- package/dist/assets/{chunk-4BX2VUAB-Cv93Z7uM.js → chunk-4BX2VUAB-BfMePfTp.js} +1 -1
- package/dist/assets/{chunk-4TB4RGXK-DE0WBDkj.js → chunk-4TB4RGXK-BdlMSdEA.js} +1 -1
- package/dist/assets/{chunk-55IACEB6-CE1EXenG.js → chunk-55IACEB6-vrQHZTdv.js} +1 -1
- package/dist/assets/{chunk-EDXVE4YY-DA7Ana6H.js → chunk-EDXVE4YY-B8wioVlW.js} +1 -1
- package/dist/assets/{chunk-FMBD7UC4-CTDIPA3p.js → chunk-FMBD7UC4-Cd6Hrux2.js} +1 -1
- package/dist/assets/{chunk-OYMX7WX6-uGBaPaTX.js → chunk-OYMX7WX6-CfrhdQXY.js} +1 -1
- package/dist/assets/{chunk-QZHKN3VN-CYlnXuUO.js → chunk-QZHKN3VN-B9JQerOU.js} +1 -1
- package/dist/assets/{chunk-YZCP3GAM-ojGkzcZK.js → chunk-YZCP3GAM-DFN9X99H.js} +1 -1
- package/dist/assets/classDiagram-6PBFFD2Q-BC9a6pDE.js +1 -0
- package/dist/assets/classDiagram-v2-HSJHXN6E-BC9a6pDE.js +1 -0
- package/dist/assets/clone-dRxgFrBv.js +1 -0
- package/dist/assets/{cose-bilkent-S5V4N54A-Bktn9hL-.js → cose-bilkent-S5V4N54A-BAn0ap_E.js} +1 -1
- package/dist/assets/{dagre-KV5264BT-DFaSzuRF.js → dagre-KV5264BT-DyxnVq1g.js} +1 -1
- package/dist/assets/{diagram-5BDNPKRD-DnfmDzEm.js → diagram-5BDNPKRD-XCrzqski.js} +1 -1
- package/dist/assets/{diagram-G4DWMVQ6-Bm8W9YnG.js → diagram-G4DWMVQ6-MBCAXft_.js} +1 -1
- package/dist/assets/{diagram-MMDJMWI5-B5-TSKvp.js → diagram-MMDJMWI5-DbtB2yS6.js} +1 -1
- package/dist/assets/{diagram-TYMM5635-ls4rqlky.js → diagram-TYMM5635-Bb5NzX61.js} +1 -1
- package/dist/assets/{erDiagram-SMLLAGMA-giG6WO-r.js → erDiagram-SMLLAGMA-CpIeCOh2.js} +1 -1
- package/dist/assets/{flowDiagram-DWJPFMVM-XvlUuz-7.js → flowDiagram-DWJPFMVM-CHyoKnhW.js} +1 -1
- package/dist/assets/{ganttDiagram-T4ZO3ILL-hLBV57oV.js → ganttDiagram-T4ZO3ILL-DErKteO_.js} +1 -1
- package/dist/assets/{gitGraphDiagram-UUTBAWPF-BHu3s_Gn.js → gitGraphDiagram-UUTBAWPF-KFVAtj2F.js} +1 -1
- package/dist/assets/{graph-D0Cfv00Y.js → graph-CRnO_ifT.js} +1 -1
- package/dist/assets/index-DKBsEUJ-.css +1 -0
- package/dist/assets/index-DkRKLuNr.js +1144 -0
- package/dist/assets/{infoDiagram-42DDH7IO-DbqRsOo3.js → infoDiagram-42DDH7IO-BZFnuSp5.js} +1 -1
- package/dist/assets/{ishikawaDiagram-UXIWVN3A-DnCdx7zb.js → ishikawaDiagram-UXIWVN3A-4Xe2Szde.js} +1 -1
- package/dist/assets/{journeyDiagram-VCZTEJTY-CfD7eNcP.js → journeyDiagram-VCZTEJTY-CZRByfS-.js} +1 -1
- package/dist/assets/{kanban-definition-6JOO6SKY-BYaO9-mK.js → kanban-definition-6JOO6SKY-B95sk6Fk.js} +1 -1
- package/dist/assets/{layout-Bj72wOEB.js → layout-BqNQzxWT.js} +1 -1
- package/dist/assets/{linear-BRFo114D.js → linear-CUh7qb64.js} +1 -1
- package/dist/assets/{min-GCHnKlJS.js → min-wXgOS3ig.js} +1 -1
- package/dist/assets/{mindmap-definition-QFDTVHPH-n0PMebY4.js → mindmap-definition-QFDTVHPH-DB6iaAbO.js} +1 -1
- package/dist/assets/{pieDiagram-DEJITSTG-pN4CljHF.js → pieDiagram-DEJITSTG-CHkZHrTW.js} +1 -1
- package/dist/assets/{quadrantDiagram-34T5L4WZ-DNoAy8-D.js → quadrantDiagram-34T5L4WZ-DoTEO8e3.js} +1 -1
- package/dist/assets/{requirementDiagram-MS252O5E-BhtY05PT.js → requirementDiagram-MS252O5E-Dn8peXYp.js} +1 -1
- package/dist/assets/{sankeyDiagram-XADWPNL6-B6AD-16A.js → sankeyDiagram-XADWPNL6-DRXs6Ipb.js} +1 -1
- package/dist/assets/{sequenceDiagram-FGHM5R23-DShHM-uk.js → sequenceDiagram-FGHM5R23-wBBYZ0aq.js} +1 -1
- package/dist/assets/{stateDiagram-FHFEXIEX-DMxn7HTo.js → stateDiagram-FHFEXIEX-DPlBNGmf.js} +1 -1
- package/dist/assets/stateDiagram-v2-QKLJ7IA2-BW0ezXb4.js +1 -0
- package/dist/assets/{timeline-definition-GMOUNBTQ-Cdu6uq52.js → timeline-definition-GMOUNBTQ-CbbyTlHk.js} +1 -1
- package/dist/assets/{vennDiagram-DHZGUBPP-CpK29iRe.js → vennDiagram-DHZGUBPP-Bj4GaFfj.js} +1 -1
- package/dist/assets/{wardley-RL74JXVD-BQgSkdcO.js → wardley-RL74JXVD-RtNzq8KU.js} +55 -55
- package/dist/assets/{wardleyDiagram-NUSXRM2D-DJHYev6O.js → wardleyDiagram-NUSXRM2D-CDfE3zSj.js} +1 -1
- package/dist/assets/{xychartDiagram-5P7HB3ND-1d75pbaO.js → xychartDiagram-5P7HB3ND-CZXHHYD5.js} +1 -1
- package/dist/index.html +2 -2
- package/lib/budget-ledger.js +45 -0
- package/lib/bug-bisect.js +292 -0
- package/lib/bug-checkpoint.js +191 -0
- package/lib/bug-escalation.js +306 -0
- package/lib/bug-index-gen.js +136 -0
- package/lib/bug-ledger.js +126 -0
- package/lib/build-stream-schema.js +176 -0
- package/lib/build-stream-writer.js +3 -1
- package/lib/build.js +854 -284
- package/lib/connector-factory-shim.js +167 -0
- package/lib/constants.js +18 -0
- package/lib/debug-discipline.js +176 -27
- package/lib/deps.js +205 -0
- package/lib/health-score.js +4 -4
- package/lib/import.js +26 -13
- package/lib/inject-schema.js +21 -0
- package/lib/new.js +27 -53
- package/lib/result-normalizer.js +160 -144
- package/lib/review-lenses.js +5 -5
- package/lib/review-normalize.js +413 -0
- package/lib/review-prompt.js +163 -0
- package/lib/sections.js +325 -0
- package/lib/step-prompt.js +21 -1
- package/lib/step-validator.js +5 -3
- package/lib/stratum-mcp-client.js +172 -7
- package/package.json +14 -3
- package/pipelines/bug-fix.stratum.yaml +39 -1
- package/pipelines/build.stratum.yaml +28 -45
- package/pipelines/review-fix.stratum.yaml +1 -1
- package/presets/team-review.stratum.yaml +21 -14
- package/server/build-stream-bridge.js +28 -0
- package/server/cc-session-feature-resolver.js +111 -0
- package/server/cc-session-reader.js +327 -0
- package/server/cc-session-watcher.js +318 -0
- package/server/compose-mcp-tools.js +0 -125
- package/server/compose-mcp.js +2 -4
- package/server/contract-diff.js +192 -0
- package/server/decision-event-emit.js +175 -0
- package/server/decision-event-id.js +64 -0
- package/server/decision-events-snapshot.js +166 -0
- package/server/design-routes.js +92 -49
- package/server/drift-axes.js +365 -0
- package/server/drift-emit.js +121 -0
- package/server/gate-log-store.js +102 -0
- package/server/lifecycle-phase-history.js +44 -0
- package/server/open-loops-store.js +102 -0
- package/server/schema-validator.js +49 -0
- package/server/status-emit.js +27 -0
- package/server/status-snapshot.js +218 -0
- package/server/vision-routes.js +332 -4
- package/server/vision-server.js +104 -12
- package/server/vision-store.js +21 -0
- package/dist/assets/channel-DGElom1e.js +0 -1
- package/dist/assets/classDiagram-6PBFFD2Q-KqWP9wWZ.js +0 -1
- package/dist/assets/classDiagram-v2-HSJHXN6E-KqWP9wWZ.js +0 -1
- package/dist/assets/clone-DUJKJXd7.js +0 -1
- package/dist/assets/index-CUd6pFGF.css +0 -1
- package/dist/assets/index-DReRlzZI.js +0 -1144
- package/dist/assets/stateDiagram-v2-QKLJ7IA2-o6PnCs4e.js +0 -1
- package/server/connectors/agent-connector.js +0 -78
- package/server/connectors/claude-sdk-connector.js +0 -198
- package/server/connectors/codex-connector.js +0 -240
- package/server/connectors/connector-discovery.js +0 -18
- package/server/connectors/connector-runtime.js +0 -13
- package/server/connectors/opencode-connector.js +0 -200
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* OpencodeConnector — spawns `opencode run` for each prompt.
|
|
3
|
-
*
|
|
4
|
-
* Model-agnostic base for any non-Anthropic agent running through OpenCode.
|
|
5
|
-
* NOT exposed as an MCP tool directly — subclasses (e.g. CodexConnector)
|
|
6
|
-
* are exposed after constraining to a specific provider/model set.
|
|
7
|
-
*
|
|
8
|
-
* Uses `opencode run --format json` which streams structured JSON events
|
|
9
|
-
* (step_start, text, tool_use, step_finish) to stdout. This is more reliable
|
|
10
|
-
* than the SDK's serve mode which has event stream issues.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
import { spawn } from 'node:child_process';
|
|
14
|
-
import { createInterface } from 'node:readline';
|
|
15
|
-
import { AgentConnector, injectSchema } from './agent-connector.js';
|
|
16
|
-
|
|
17
|
-
// ---------------------------------------------------------------------------
|
|
18
|
-
// OpencodeConnector
|
|
19
|
-
// ---------------------------------------------------------------------------
|
|
20
|
-
|
|
21
|
-
export class OpencodeConnector extends AgentConnector {
|
|
22
|
-
// ── Discovery ──────────────────────────────────────────────────────────────
|
|
23
|
-
// No overrides — inherits stubs from AgentConnector. See agent-connector.js.
|
|
24
|
-
|
|
25
|
-
_defaultProviderID;
|
|
26
|
-
_defaultModelID;
|
|
27
|
-
_cwd;
|
|
28
|
-
_agentName;
|
|
29
|
-
#proc = null;
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* @param {object} opts
|
|
33
|
-
* @param {string} opts.providerID — OpenCode provider ID (e.g. 'openai')
|
|
34
|
-
* @param {string} opts.modelID — model ID (e.g. 'gpt-5.4')
|
|
35
|
-
* @param {string} [opts.cwd] — default working directory
|
|
36
|
-
* @param {string} [opts.agentName] — label used in system messages
|
|
37
|
-
*/
|
|
38
|
-
constructor({ providerID, modelID, cwd = process.cwd(), agentName = 'opencode' }) {
|
|
39
|
-
super();
|
|
40
|
-
this._defaultProviderID = providerID;
|
|
41
|
-
this._defaultModelID = modelID;
|
|
42
|
-
this._cwd = cwd;
|
|
43
|
-
this._agentName = agentName;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// ── Runtime ────────────────────────────────────────────────────────────────
|
|
47
|
-
|
|
48
|
-
async *run(prompt, { schema, modelID, providerID, cwd } = {}) {
|
|
49
|
-
if (this.#proc) {
|
|
50
|
-
throw new Error(`${this._agentName}: run() already active. Call interrupt() first.`);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const resolvedProviderID = providerID ?? this._defaultProviderID;
|
|
54
|
-
const resolvedModelID = modelID ?? this._defaultModelID;
|
|
55
|
-
const resolvedCwd = cwd ?? this._cwd;
|
|
56
|
-
const actualPrompt = schema ? injectSchema(prompt, schema) : prompt;
|
|
57
|
-
|
|
58
|
-
yield {
|
|
59
|
-
type: 'system', subtype: 'init',
|
|
60
|
-
agent: this._agentName, model: `${resolvedProviderID}/${resolvedModelID}`,
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
// Build clean env: remove OPENAI_API_KEY so opencode uses OAuth
|
|
64
|
-
// (API key overrides OAuth and may lack Codex model access)
|
|
65
|
-
const cleanEnv = { ...process.env };
|
|
66
|
-
delete cleanEnv.OPENAI_API_KEY;
|
|
67
|
-
|
|
68
|
-
const proc = spawn('opencode', [
|
|
69
|
-
'run',
|
|
70
|
-
'-m', `${resolvedProviderID}/${resolvedModelID}`,
|
|
71
|
-
'--format', 'json',
|
|
72
|
-
actualPrompt,
|
|
73
|
-
], {
|
|
74
|
-
cwd: resolvedCwd,
|
|
75
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
76
|
-
env: cleanEnv,
|
|
77
|
-
});
|
|
78
|
-
this.#proc = proc;
|
|
79
|
-
|
|
80
|
-
// Read JSON events line-by-line from stdout
|
|
81
|
-
const rl = createInterface({ input: proc.stdout, crlfDelay: Infinity });
|
|
82
|
-
|
|
83
|
-
const textParts = [];
|
|
84
|
-
let stderrChunks = [];
|
|
85
|
-
|
|
86
|
-
// Stream stderr live — detect rate-limit, auth, and quota errors immediately
|
|
87
|
-
proc.stderr.on('data', chunk => {
|
|
88
|
-
stderrChunks.push(chunk);
|
|
89
|
-
const text = chunk.toString();
|
|
90
|
-
const lower = text.toLowerCase();
|
|
91
|
-
// Check for actionable errors that should surface immediately
|
|
92
|
-
if (lower.includes('rate limit') || lower.includes('rate_limit') ||
|
|
93
|
-
lower.includes('quota') || lower.includes('insufficient_quota') ||
|
|
94
|
-
lower.includes('unauthorized') || lower.includes('401') ||
|
|
95
|
-
lower.includes('403') || lower.includes('authentication') ||
|
|
96
|
-
lower.includes('auth') || lower.includes('billing') ||
|
|
97
|
-
lower.includes('exceeded') || lower.includes('capacity')) {
|
|
98
|
-
process.stderr.write(`\n⚠ ${this._agentName}: ${text.trim()}\n`);
|
|
99
|
-
process.stderr.write(` → Check account: opencode auth status\n`);
|
|
100
|
-
process.stderr.write(` → Switch account: opencode auth login\n\n`);
|
|
101
|
-
}
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
// Stall detection — warn if no stdout events for 120s
|
|
105
|
-
let lastEventAt = Date.now();
|
|
106
|
-
const stallTimer = setInterval(() => {
|
|
107
|
-
const silent = Math.round((Date.now() - lastEventAt) / 1000);
|
|
108
|
-
if (silent >= 120) {
|
|
109
|
-
process.stderr.write(`\n⚠ ${this._agentName}: no response for ${silent}s — may be stalled or rate-limited\n`);
|
|
110
|
-
process.stderr.write(` → Press s to skip, or Ctrl+C to abort\n\n`);
|
|
111
|
-
}
|
|
112
|
-
}, 30_000);
|
|
113
|
-
|
|
114
|
-
try {
|
|
115
|
-
for await (const line of rl) {
|
|
116
|
-
if (!line.trim()) continue;
|
|
117
|
-
lastEventAt = Date.now();
|
|
118
|
-
|
|
119
|
-
let event;
|
|
120
|
-
try {
|
|
121
|
-
event = JSON.parse(line);
|
|
122
|
-
} catch {
|
|
123
|
-
continue; // skip non-JSON lines
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
if (event.type === 'text') {
|
|
127
|
-
const text = event.part?.text ?? '';
|
|
128
|
-
if (text) {
|
|
129
|
-
textParts.push(text);
|
|
130
|
-
yield { type: 'assistant', content: text };
|
|
131
|
-
}
|
|
132
|
-
} else if (event.type === 'tool_use') {
|
|
133
|
-
const tool = event.part?.tool ?? event.part?.state?.input?.command ? 'bash' : 'unknown';
|
|
134
|
-
const input = event.part?.state?.input ?? {};
|
|
135
|
-
yield { type: 'tool_use', tool, input };
|
|
136
|
-
|
|
137
|
-
// If tool has output, yield a summary
|
|
138
|
-
const output = event.part?.state?.output;
|
|
139
|
-
if (output && typeof output === 'string') {
|
|
140
|
-
const short = output.length > 80 ? output.slice(0, 77) + '...' : output;
|
|
141
|
-
yield { type: 'tool_use_summary', summary: short, output: output.slice(0, 2048) };
|
|
142
|
-
}
|
|
143
|
-
} else if (event.type === 'step_finish') {
|
|
144
|
-
// step_finish includes cost and token info — forward as usage event
|
|
145
|
-
const part = event.part;
|
|
146
|
-
if (part && (part.cost != null || part.tokens != null)) {
|
|
147
|
-
if (process.env.COMPOSE_DEBUG) {
|
|
148
|
-
process.stderr.write(` [${this._agentName}] cost=$${(part.cost ?? 0).toFixed(4)} tokens=${part.tokens?.total}\n`);
|
|
149
|
-
}
|
|
150
|
-
yield {
|
|
151
|
-
type: 'usage',
|
|
152
|
-
input_tokens: part.tokens?.input ?? 0,
|
|
153
|
-
output_tokens: part.tokens?.output ?? 0,
|
|
154
|
-
cache_creation_input_tokens: part.tokens?.cache_write ?? 0,
|
|
155
|
-
cache_read_input_tokens: part.tokens?.cache_read ?? 0,
|
|
156
|
-
cost_usd: part.cost ?? 0,
|
|
157
|
-
model: resolvedModelID,
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
// step_start is ignored (already yielded init)
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// Wait for process to exit
|
|
165
|
-
const exitCode = await new Promise((resolve) => {
|
|
166
|
-
proc.on('close', resolve);
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
if (exitCode !== 0 && textParts.length === 0) {
|
|
170
|
-
const stderr = Buffer.concat(stderrChunks).toString();
|
|
171
|
-
yield { type: 'error', message: stderr || `opencode exited with code ${exitCode}` };
|
|
172
|
-
} else {
|
|
173
|
-
// Yield the full concatenated text as a result
|
|
174
|
-
const fullText = textParts.join('');
|
|
175
|
-
if (fullText) {
|
|
176
|
-
yield { type: 'result', content: fullText };
|
|
177
|
-
}
|
|
178
|
-
yield { type: 'system', subtype: 'complete', agent: this._agentName };
|
|
179
|
-
}
|
|
180
|
-
} catch (err) {
|
|
181
|
-
if (err?.name !== 'AbortError') {
|
|
182
|
-
yield { type: 'error', message: err.message || String(err) };
|
|
183
|
-
}
|
|
184
|
-
} finally {
|
|
185
|
-
clearInterval(stallTimer);
|
|
186
|
-
this.#proc = null;
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
interrupt() {
|
|
191
|
-
if (this.#proc) {
|
|
192
|
-
try { this.#proc.kill('SIGTERM'); } catch { /* ignore */ }
|
|
193
|
-
this.#proc = null;
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
get isRunning() {
|
|
198
|
-
return this.#proc !== null;
|
|
199
|
-
}
|
|
200
|
-
}
|