@braidhq/server 0.0.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 +21 -0
- package/dist/app.d.ts +7 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +71 -0
- package/dist/app.js.map +1 -0
- package/dist/composeFs.d.ts +20 -0
- package/dist/composeFs.d.ts.map +1 -0
- package/dist/composeFs.js +134 -0
- package/dist/composeFs.js.map +1 -0
- package/dist/composition.d.ts +49 -0
- package/dist/composition.d.ts.map +1 -0
- package/dist/composition.js +43 -0
- package/dist/composition.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/infrastructure/agent/ClaudeCodeAgentBinding.d.ts +8 -0
- package/dist/infrastructure/agent/ClaudeCodeAgentBinding.d.ts.map +1 -0
- package/dist/infrastructure/agent/ClaudeCodeAgentBinding.js +62 -0
- package/dist/infrastructure/agent/ClaudeCodeAgentBinding.js.map +1 -0
- package/dist/infrastructure/agent/SubprocessSkillRunner.d.ts +54 -0
- package/dist/infrastructure/agent/SubprocessSkillRunner.d.ts.map +1 -0
- package/dist/infrastructure/agent/SubprocessSkillRunner.js +240 -0
- package/dist/infrastructure/agent/SubprocessSkillRunner.js.map +1 -0
- package/dist/infrastructure/agent/asyncQueue.d.ts +22 -0
- package/dist/infrastructure/agent/asyncQueue.d.ts.map +1 -0
- package/dist/infrastructure/agent/asyncQueue.js +43 -0
- package/dist/infrastructure/agent/asyncQueue.js.map +1 -0
- package/dist/infrastructure/agent/mcpConfig.d.ts +18 -0
- package/dist/infrastructure/agent/mcpConfig.d.ts.map +1 -0
- package/dist/infrastructure/agent/mcpConfig.js +47 -0
- package/dist/infrastructure/agent/mcpConfig.js.map +1 -0
- package/dist/infrastructure/agent/streamJsonParser.d.ts +20 -0
- package/dist/infrastructure/agent/streamJsonParser.d.ts.map +1 -0
- package/dist/infrastructure/agent/streamJsonParser.js +44 -0
- package/dist/infrastructure/agent/streamJsonParser.js.map +1 -0
- package/dist/infrastructure/agent/subprocessEventStream.d.ts +26 -0
- package/dist/infrastructure/agent/subprocessEventStream.d.ts.map +1 -0
- package/dist/infrastructure/agent/subprocessEventStream.js +112 -0
- package/dist/infrastructure/agent/subprocessEventStream.js.map +1 -0
- package/dist/infrastructure/fs/FsClarifyTicketRepository.d.ts +13 -0
- package/dist/infrastructure/fs/FsClarifyTicketRepository.d.ts.map +1 -0
- package/dist/infrastructure/fs/FsClarifyTicketRepository.js +33 -0
- package/dist/infrastructure/fs/FsClarifyTicketRepository.js.map +1 -0
- package/dist/infrastructure/fs/FsDecisionRepository.d.ts +13 -0
- package/dist/infrastructure/fs/FsDecisionRepository.d.ts.map +1 -0
- package/dist/infrastructure/fs/FsDecisionRepository.js +56 -0
- package/dist/infrastructure/fs/FsDecisionRepository.js.map +1 -0
- package/dist/infrastructure/fs/FsProposalRepository.d.ts +14 -0
- package/dist/infrastructure/fs/FsProposalRepository.d.ts.map +1 -0
- package/dist/infrastructure/fs/FsProposalRepository.js +40 -0
- package/dist/infrastructure/fs/FsProposalRepository.js.map +1 -0
- package/dist/infrastructure/fs/FsRunRepository.d.ts +21 -0
- package/dist/infrastructure/fs/FsRunRepository.d.ts.map +1 -0
- package/dist/infrastructure/fs/FsRunRepository.js +88 -0
- package/dist/infrastructure/fs/FsRunRepository.js.map +1 -0
- package/dist/infrastructure/fs/FsSkillRegistry.d.ts +34 -0
- package/dist/infrastructure/fs/FsSkillRegistry.d.ts.map +1 -0
- package/dist/infrastructure/fs/FsSkillRegistry.js +143 -0
- package/dist/infrastructure/fs/FsSkillRegistry.js.map +1 -0
- package/dist/infrastructure/fs/FsStatusedJsonRepository.d.ts +35 -0
- package/dist/infrastructure/fs/FsStatusedJsonRepository.d.ts.map +1 -0
- package/dist/infrastructure/fs/FsStatusedJsonRepository.js +79 -0
- package/dist/infrastructure/fs/FsStatusedJsonRepository.js.map +1 -0
- package/dist/infrastructure/fs/FsWorkspaceRepository.d.ts +21 -0
- package/dist/infrastructure/fs/FsWorkspaceRepository.d.ts.map +1 -0
- package/dist/infrastructure/fs/FsWorkspaceRepository.js +87 -0
- package/dist/infrastructure/fs/FsWorkspaceRepository.js.map +1 -0
- package/dist/infrastructure/fs/WorkspaceRegistryFile.d.ts +17 -0
- package/dist/infrastructure/fs/WorkspaceRegistryFile.d.ts.map +1 -0
- package/dist/infrastructure/fs/WorkspaceRegistryFile.js +58 -0
- package/dist/infrastructure/fs/WorkspaceRegistryFile.js.map +1 -0
- package/dist/infrastructure/fs/frontmatter.d.ts +13 -0
- package/dist/infrastructure/fs/frontmatter.d.ts.map +1 -0
- package/dist/infrastructure/fs/frontmatter.js +46 -0
- package/dist/infrastructure/fs/frontmatter.js.map +1 -0
- package/dist/infrastructure/fs/jsonFileStore.d.ts +5 -0
- package/dist/infrastructure/fs/jsonFileStore.d.ts.map +1 -0
- package/dist/infrastructure/fs/jsonFileStore.js +29 -0
- package/dist/infrastructure/fs/jsonFileStore.js.map +1 -0
- package/dist/infrastructure/fs/paths.d.ts +22 -0
- package/dist/infrastructure/fs/paths.d.ts.map +1 -0
- package/dist/infrastructure/fs/paths.js +46 -0
- package/dist/infrastructure/fs/paths.js.map +1 -0
- package/dist/infrastructure/fs/productManifestWriter.d.ts +22 -0
- package/dist/infrastructure/fs/productManifestWriter.d.ts.map +1 -0
- package/dist/infrastructure/fs/productManifestWriter.js +75 -0
- package/dist/infrastructure/fs/productManifestWriter.js.map +1 -0
- package/dist/infrastructure/oauth/GoogleOAuth.d.ts +60 -0
- package/dist/infrastructure/oauth/GoogleOAuth.d.ts.map +1 -0
- package/dist/infrastructure/oauth/GoogleOAuth.js +114 -0
- package/dist/infrastructure/oauth/GoogleOAuth.js.map +1 -0
- package/dist/infrastructure/orphanReaper.d.ts +18 -0
- package/dist/infrastructure/orphanReaper.d.ts.map +1 -0
- package/dist/infrastructure/orphanReaper.js +42 -0
- package/dist/infrastructure/orphanReaper.js.map +1 -0
- package/dist/infrastructure/secrets/SecretStore.d.ts +36 -0
- package/dist/infrastructure/secrets/SecretStore.d.ts.map +1 -0
- package/dist/infrastructure/secrets/SecretStore.js +44 -0
- package/dist/infrastructure/secrets/SecretStore.js.map +1 -0
- package/dist/middleware/cors.d.ts +11 -0
- package/dist/middleware/cors.d.ts.map +1 -0
- package/dist/middleware/cors.js +30 -0
- package/dist/middleware/cors.js.map +1 -0
- package/dist/middleware/error.d.ts +3 -0
- package/dist/middleware/error.d.ts.map +1 -0
- package/dist/middleware/error.js +52 -0
- package/dist/middleware/error.js.map +1 -0
- package/dist/middleware/workspaceId.d.ts +10 -0
- package/dist/middleware/workspaceId.d.ts.map +1 -0
- package/dist/middleware/workspaceId.js +9 -0
- package/dist/middleware/workspaceId.js.map +1 -0
- package/dist/routes/clarify.d.ts +8 -0
- package/dist/routes/clarify.d.ts.map +1 -0
- package/dist/routes/clarify.js +84 -0
- package/dist/routes/clarify.js.map +1 -0
- package/dist/routes/decisions.d.ts +7 -0
- package/dist/routes/decisions.d.ts.map +1 -0
- package/dist/routes/decisions.js +30 -0
- package/dist/routes/decisions.js.map +1 -0
- package/dist/routes/edges.d.ts +7 -0
- package/dist/routes/edges.d.ts.map +1 -0
- package/dist/routes/edges.js +30 -0
- package/dist/routes/edges.js.map +1 -0
- package/dist/routes/health.d.ts +3 -0
- package/dist/routes/health.d.ts.map +1 -0
- package/dist/routes/health.js +10 -0
- package/dist/routes/health.js.map +1 -0
- package/dist/routes/helpers.d.ts +5 -0
- package/dist/routes/helpers.d.ts.map +1 -0
- package/dist/routes/helpers.js +14 -0
- package/dist/routes/helpers.js.map +1 -0
- package/dist/routes/model.d.ts +7 -0
- package/dist/routes/model.d.ts.map +1 -0
- package/dist/routes/model.js +12 -0
- package/dist/routes/model.js.map +1 -0
- package/dist/routes/nodes.d.ts +7 -0
- package/dist/routes/nodes.d.ts.map +1 -0
- package/dist/routes/nodes.js +47 -0
- package/dist/routes/nodes.js.map +1 -0
- package/dist/routes/oauth.d.ts +20 -0
- package/dist/routes/oauth.d.ts.map +1 -0
- package/dist/routes/oauth.js +107 -0
- package/dist/routes/oauth.js.map +1 -0
- package/dist/routes/ontology.d.ts +8 -0
- package/dist/routes/ontology.d.ts.map +1 -0
- package/dist/routes/ontology.js +21 -0
- package/dist/routes/ontology.js.map +1 -0
- package/dist/routes/proposals.d.ts +10 -0
- package/dist/routes/proposals.d.ts.map +1 -0
- package/dist/routes/proposals.js +80 -0
- package/dist/routes/proposals.js.map +1 -0
- package/dist/routes/runs.d.ts +9 -0
- package/dist/routes/runs.d.ts.map +1 -0
- package/dist/routes/runs.js +73 -0
- package/dist/routes/runs.js.map +1 -0
- package/dist/routes/skills.d.ts +9 -0
- package/dist/routes/skills.d.ts.map +1 -0
- package/dist/routes/skills.js +42 -0
- package/dist/routes/skills.js.map +1 -0
- package/dist/routes/workspaceEvents.d.ts +14 -0
- package/dist/routes/workspaceEvents.d.ts.map +1 -0
- package/dist/routes/workspaceEvents.js +37 -0
- package/dist/routes/workspaceEvents.js.map +1 -0
- package/dist/routes/workspaces.d.ts +8 -0
- package/dist/routes/workspaces.d.ts.map +1 -0
- package/dist/routes/workspaces.js +167 -0
- package/dist/routes/workspaces.js.map +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +33 -0
- package/dist/server.js.map +1 -0
- package/package.json +49 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import { mkdir, rm, symlink } from 'node:fs/promises';
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
|
+
import { newSkillRunId, NotFoundError } from '@braidhq/core';
|
|
4
|
+
import { AbsolutePath as AbsolutePathSchema, SkillEvent as SkillEventSchema, SkillRunId as SkillRunIdSchema, } from '@braidhq/schema';
|
|
5
|
+
import { sessionDirPath } from '../fs/paths.js';
|
|
6
|
+
import { createAsyncQueue } from './asyncQueue.js';
|
|
7
|
+
import { writeMcpConfigFile } from './mcpConfig.js';
|
|
8
|
+
import { attachOutputBuffers } from './subprocessEventStream.js';
|
|
9
|
+
export class SubprocessSkillRunner {
|
|
10
|
+
deps;
|
|
11
|
+
running = new Map();
|
|
12
|
+
/** sessionId → cwd for resuming. claude needs the same cwd between turns. */
|
|
13
|
+
sessionDirs = new Map();
|
|
14
|
+
subscribers = new Map();
|
|
15
|
+
/** How many events have been emitted (and persisted) per run so far. */
|
|
16
|
+
positions = new Map();
|
|
17
|
+
constructor(deps) {
|
|
18
|
+
this.deps = deps;
|
|
19
|
+
}
|
|
20
|
+
async start(workspace, skillId, args, options) {
|
|
21
|
+
const manifest = await this.deps.skillRegistry.get(workspace, skillId);
|
|
22
|
+
const runId = newSkillRunId();
|
|
23
|
+
const sessionDir = await this.resolveSessionDir(workspace, runId, options?.resumeSessionId);
|
|
24
|
+
const mcpConfigFile = await writeMcpConfigFile(workspace, sessionDir);
|
|
25
|
+
const invocation = this.deps.agentBinding.resolveSpawn({
|
|
26
|
+
skillId,
|
|
27
|
+
args,
|
|
28
|
+
workspace,
|
|
29
|
+
manifest,
|
|
30
|
+
apiUrl: this.deps.apiUrl,
|
|
31
|
+
mcpConfigFile: AbsolutePathSchema.parse(mcpConfigFile),
|
|
32
|
+
...(options?.resumeSessionId ? { resumeSessionId: options.resumeSessionId } : {}),
|
|
33
|
+
});
|
|
34
|
+
const spawnFn = this.deps.spawn ?? (await defaultSpawn());
|
|
35
|
+
// BRAID_SESSION_DIR resolves ambiguity in SKILL.md paths: claude sees
|
|
36
|
+
// both `BRAID_WORKSPACE` and a cwd that lives inside it, and would
|
|
37
|
+
// otherwise guess wrong about which one `.claude/skills/...` is rooted in.
|
|
38
|
+
const child = spawnFn(invocation.bin, [...invocation.args], {
|
|
39
|
+
cwd: sessionDir,
|
|
40
|
+
env: { ...invocation.env, BRAID_SESSION_DIR: sessionDir },
|
|
41
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
42
|
+
});
|
|
43
|
+
this.running.set(runId, { workspace, child });
|
|
44
|
+
// Persist the started record up front so listing endpoints see the run
|
|
45
|
+
// immediately, even before any subprocess output.
|
|
46
|
+
const startedAt = this.now();
|
|
47
|
+
const initialRecord = {
|
|
48
|
+
runId,
|
|
49
|
+
workspaceId: workspace.id,
|
|
50
|
+
skillId,
|
|
51
|
+
args,
|
|
52
|
+
resumed: options?.resumeSessionId !== undefined,
|
|
53
|
+
startedAt,
|
|
54
|
+
...(options?.resumeSessionId ? { sessionId: options.resumeSessionId } : {}),
|
|
55
|
+
};
|
|
56
|
+
await this.deps.runRepository.saveRecord(workspace, initialRecord);
|
|
57
|
+
this.deps.eventBus?.publish({
|
|
58
|
+
type: 'run.started',
|
|
59
|
+
workspaceId: workspace.id,
|
|
60
|
+
runId,
|
|
61
|
+
skillId,
|
|
62
|
+
at: startedAt,
|
|
63
|
+
});
|
|
64
|
+
// Fire-and-forget the drain so the HTTP request that called start()
|
|
65
|
+
// can return immediately.
|
|
66
|
+
void this.drain({
|
|
67
|
+
workspace,
|
|
68
|
+
runId,
|
|
69
|
+
child,
|
|
70
|
+
skillId,
|
|
71
|
+
args,
|
|
72
|
+
sessionDir,
|
|
73
|
+
resumeSessionId: options?.resumeSessionId,
|
|
74
|
+
startedAt,
|
|
75
|
+
initialRecord,
|
|
76
|
+
});
|
|
77
|
+
return runId;
|
|
78
|
+
}
|
|
79
|
+
subscribe(runId, listener) {
|
|
80
|
+
const set = this.subscribers.get(runId) ?? new Set();
|
|
81
|
+
set.add(listener);
|
|
82
|
+
this.subscribers.set(runId, set);
|
|
83
|
+
return {
|
|
84
|
+
unsubscribe: () => {
|
|
85
|
+
set.delete(listener);
|
|
86
|
+
if (set.size === 0)
|
|
87
|
+
this.subscribers.delete(runId);
|
|
88
|
+
},
|
|
89
|
+
positionAtSubscribe: this.positions.get(runId) ?? 0,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
isActive(runId) {
|
|
93
|
+
return this.running.has(runId);
|
|
94
|
+
}
|
|
95
|
+
async cancel(runId) {
|
|
96
|
+
const validated = SkillRunIdSchema.parse(runId);
|
|
97
|
+
const active = this.running.get(validated);
|
|
98
|
+
if (!active)
|
|
99
|
+
throw new NotFoundError(`SkillRun "${validated}" not active`);
|
|
100
|
+
active.child.kill('SIGTERM');
|
|
101
|
+
}
|
|
102
|
+
async forgetSession(sessionId) {
|
|
103
|
+
const dir = this.sessionDirs.get(sessionId);
|
|
104
|
+
if (!dir)
|
|
105
|
+
return;
|
|
106
|
+
this.sessionDirs.delete(sessionId);
|
|
107
|
+
if (this.deps.cleanupSession !== false)
|
|
108
|
+
await rm(dir, { recursive: true, force: true });
|
|
109
|
+
}
|
|
110
|
+
async drain(input) {
|
|
111
|
+
let record = input.initialRecord;
|
|
112
|
+
let capturedSessionId = input.resumeSessionId ?? null;
|
|
113
|
+
let sawError = false;
|
|
114
|
+
let exitCode = 0;
|
|
115
|
+
try {
|
|
116
|
+
await this.emit(input.workspace, input.runId, SkillEventSchema.parse({
|
|
117
|
+
type: 'started',
|
|
118
|
+
runId: input.runId,
|
|
119
|
+
skillId: input.skillId,
|
|
120
|
+
args: input.args,
|
|
121
|
+
resumed: input.resumeSessionId !== undefined,
|
|
122
|
+
at: input.startedAt,
|
|
123
|
+
}));
|
|
124
|
+
const queue = createAsyncQueue();
|
|
125
|
+
const buffers = attachOutputBuffers(input.child, queue.push, () => this.now());
|
|
126
|
+
input.child.on('close', (code) => {
|
|
127
|
+
buffers.flush();
|
|
128
|
+
queue.push(SkillEventSchema.parse({
|
|
129
|
+
type: 'completed',
|
|
130
|
+
runId: input.runId,
|
|
131
|
+
exitCode: code ?? 0,
|
|
132
|
+
at: this.now(),
|
|
133
|
+
}));
|
|
134
|
+
queue.end();
|
|
135
|
+
});
|
|
136
|
+
for await (const event of queue.iterate()) {
|
|
137
|
+
if (event.type === 'session-started') {
|
|
138
|
+
capturedSessionId = event.sessionId;
|
|
139
|
+
this.sessionDirs.set(event.sessionId, input.sessionDir);
|
|
140
|
+
record = { ...record, sessionId: event.sessionId };
|
|
141
|
+
await this.deps.runRepository.saveRecord(input.workspace, record);
|
|
142
|
+
}
|
|
143
|
+
if (event.type === 'completed') {
|
|
144
|
+
record = { ...record, completedAt: event.at, exitCode: event.exitCode };
|
|
145
|
+
exitCode = event.exitCode;
|
|
146
|
+
await this.deps.runRepository.saveRecord(input.workspace, record);
|
|
147
|
+
}
|
|
148
|
+
if (event.type === 'error')
|
|
149
|
+
sawError = true;
|
|
150
|
+
await this.emit(input.workspace, input.runId, event);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
finally {
|
|
154
|
+
this.running.delete(input.runId);
|
|
155
|
+
this.deps.eventBus?.publish({
|
|
156
|
+
type: 'run.completed',
|
|
157
|
+
workspaceId: input.workspace.id,
|
|
158
|
+
runId: input.runId,
|
|
159
|
+
skillId: input.skillId,
|
|
160
|
+
outcome: sawError ? 'error' : exitCode === 0 ? 'success' : 'error',
|
|
161
|
+
at: this.now(),
|
|
162
|
+
});
|
|
163
|
+
this.subscribers.delete(input.runId);
|
|
164
|
+
// Keep the session dir on disk if a session id was captured: claude
|
|
165
|
+
// stores conversation state per-cwd, so the dir must survive between
|
|
166
|
+
// turns. GC happens via forgetSession(sessionId).
|
|
167
|
+
const keepForResume = capturedSessionId !== null;
|
|
168
|
+
if (this.deps.cleanupSession !== false && !keepForResume)
|
|
169
|
+
await rm(input.sessionDir, { recursive: true, force: true }).catch(() => { });
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
// Persist first, then broadcast. A subscriber that arrived just before
|
|
173
|
+
// this emit is guaranteed to receive events strictly past its
|
|
174
|
+
// positionAtSubscribe.
|
|
175
|
+
async emit(workspace, runId, event) {
|
|
176
|
+
await this.deps.runRepository.appendEvent(workspace, runId, event);
|
|
177
|
+
const next = (this.positions.get(runId) ?? 0) + 1;
|
|
178
|
+
this.positions.set(runId, next);
|
|
179
|
+
const listeners = this.subscribers.get(runId);
|
|
180
|
+
if (!listeners)
|
|
181
|
+
return;
|
|
182
|
+
for (const listener of listeners) {
|
|
183
|
+
try {
|
|
184
|
+
listener(event);
|
|
185
|
+
}
|
|
186
|
+
catch {
|
|
187
|
+
// A buggy listener mustn't break delivery to others.
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
async resolveSessionDir(workspace, runId, resumeSessionId) {
|
|
192
|
+
if (resumeSessionId) {
|
|
193
|
+
const cached = this.sessionDirs.get(resumeSessionId);
|
|
194
|
+
if (cached)
|
|
195
|
+
return cached;
|
|
196
|
+
const recovered = await this.recoverSessionDir(workspace, resumeSessionId);
|
|
197
|
+
if (recovered) {
|
|
198
|
+
this.sessionDirs.set(resumeSessionId, recovered);
|
|
199
|
+
return recovered;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return this.buildSessionDir(workspace, runId);
|
|
203
|
+
}
|
|
204
|
+
async recoverSessionDir(workspace, sessionId) {
|
|
205
|
+
const records = await this.deps.runRepository.listRecords(workspace);
|
|
206
|
+
const first = records
|
|
207
|
+
.filter(r => r.sessionId === sessionId && !r.resumed)
|
|
208
|
+
.sort((a, b) => a.startedAt.localeCompare(b.startedAt))[0];
|
|
209
|
+
return first ? sessionDirPath(workspace.rootPath, first.runId) : undefined;
|
|
210
|
+
}
|
|
211
|
+
async buildSessionDir(workspace, runId) {
|
|
212
|
+
const sessionDir = sessionDirPath(workspace.rootPath, runId);
|
|
213
|
+
const skillsDir = join(sessionDir, '.claude', 'skills');
|
|
214
|
+
await mkdir(skillsDir, { recursive: true });
|
|
215
|
+
const manifests = await this.deps.skillRegistry.list(workspace);
|
|
216
|
+
const linked = new Set();
|
|
217
|
+
for (const manifest of manifests) {
|
|
218
|
+
const slashName = manifest.frontmatter.name;
|
|
219
|
+
if (linked.has(slashName))
|
|
220
|
+
continue;
|
|
221
|
+
linked.add(slashName);
|
|
222
|
+
await symlink(dirname(manifest.path), join(skillsDir, slashName), 'dir');
|
|
223
|
+
}
|
|
224
|
+
for (const reference of this.deps.referenceDirs ?? []) {
|
|
225
|
+
if (linked.has(reference.name))
|
|
226
|
+
continue;
|
|
227
|
+
linked.add(reference.name);
|
|
228
|
+
await symlink(reference.path, join(skillsDir, reference.name), 'dir');
|
|
229
|
+
}
|
|
230
|
+
return sessionDir;
|
|
231
|
+
}
|
|
232
|
+
now() {
|
|
233
|
+
return (this.deps.clock ?? (() => new Date().toISOString()))();
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
async function defaultSpawn() {
|
|
237
|
+
const mod = await import('node:child_process');
|
|
238
|
+
return (command, args, options) => mod.spawn(command, [...args], options);
|
|
239
|
+
}
|
|
240
|
+
//# sourceMappingURL=SubprocessSkillRunner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SubprocessSkillRunner.js","sourceRoot":"","sources":["../../../src/infrastructure/agent/SubprocessSkillRunner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single-producer / single-consumer async queue backing an `AsyncIterable`.
|
|
3
|
+
*
|
|
4
|
+
* Used to bridge node `EventEmitter`-style callbacks (which fire whenever
|
|
5
|
+
* subprocess stdout / stderr / close events arrive) into `for await … of`
|
|
6
|
+
* consumers (Hono's SSE writer, vitest assertions) without buffering every
|
|
7
|
+
* event until the producer is done.
|
|
8
|
+
*
|
|
9
|
+
* Contract:
|
|
10
|
+
* - `push(item)` enqueues an item and wakes a pending consumer.
|
|
11
|
+
* - `end()` signals that no more items are coming; the iterator finishes
|
|
12
|
+
* once it has drained the queue.
|
|
13
|
+
* - `iterate()` returns a single-use async generator. Calling it more than
|
|
14
|
+
* once is undefined.
|
|
15
|
+
*/
|
|
16
|
+
export interface AsyncQueue<T> {
|
|
17
|
+
push: (item: T) => void;
|
|
18
|
+
end: () => void;
|
|
19
|
+
iterate: () => AsyncGenerator<T>;
|
|
20
|
+
}
|
|
21
|
+
export declare function createAsyncQueue<T>(): AsyncQueue<T>;
|
|
22
|
+
//# sourceMappingURL=asyncQueue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asyncQueue.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/agent/asyncQueue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAA;IACvB,GAAG,EAAE,MAAM,IAAI,CAAA;IACf,OAAO,EAAE,MAAM,cAAc,CAAC,CAAC,CAAC,CAAA;CACjC;AAED,wBAAgB,gBAAgB,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,CA2CnD"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export function createAsyncQueue() {
|
|
2
|
+
const buffer = [];
|
|
3
|
+
let resolver = null;
|
|
4
|
+
let finished = false;
|
|
5
|
+
const wake = () => {
|
|
6
|
+
if (resolver) {
|
|
7
|
+
const r = resolver;
|
|
8
|
+
resolver = null;
|
|
9
|
+
r();
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
return {
|
|
13
|
+
push: (item) => {
|
|
14
|
+
buffer.push(item);
|
|
15
|
+
wake();
|
|
16
|
+
},
|
|
17
|
+
end: () => {
|
|
18
|
+
finished = true;
|
|
19
|
+
wake();
|
|
20
|
+
},
|
|
21
|
+
iterate: async function* iterate() {
|
|
22
|
+
while (true) {
|
|
23
|
+
if (buffer.length > 0) {
|
|
24
|
+
yield buffer.shift();
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (finished)
|
|
28
|
+
return;
|
|
29
|
+
// The double check inside the Promise constructor avoids a race
|
|
30
|
+
// where `push` or `end` is called between the queue-length check
|
|
31
|
+
// and the resolver assignment.
|
|
32
|
+
await new Promise((r) => {
|
|
33
|
+
if (buffer.length > 0 || finished) {
|
|
34
|
+
r();
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
resolver = r;
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=asyncQueue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asyncQueue.js","sourceRoot":"","sources":["../../../src/infrastructure/agent/asyncQueue.ts"],"names":[],"mappings":"AAqBA,MAAM,UAAU,gBAAgB;IAC9B,MAAM,MAAM,GAAQ,EAAE,CAAA;IACtB,IAAI,QAAQ,GAAwB,IAAI,CAAA;IACxC,IAAI,QAAQ,GAAG,KAAK,CAAA;IAEpB,MAAM,IAAI,GAAG,GAAS,EAAE;QACtB,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,CAAC,GAAG,QAAQ,CAAA;YAClB,QAAQ,GAAG,IAAI,CAAA;YACf,CAAC,EAAE,CAAA;QACL,CAAC;IACH,CAAC,CAAA;IAED,OAAO;QACL,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE;YACb,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACjB,IAAI,EAAE,CAAA;QACR,CAAC;QACD,GAAG,EAAE,GAAG,EAAE;YACR,QAAQ,GAAG,IAAI,CAAA;YACf,IAAI,EAAE,CAAA;QACR,CAAC;QACD,OAAO,EAAE,KAAK,SAAS,CAAC,CAAC,OAAO;YAC9B,OAAO,IAAI,EAAE,CAAC;gBACZ,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACtB,MAAM,MAAM,CAAC,KAAK,EAAG,CAAA;oBACrB,SAAQ;gBACV,CAAC;gBACD,IAAI,QAAQ;oBACV,OAAM;gBACR,gEAAgE;gBAChE,iEAAiE;gBACjE,+BAA+B;gBAC/B,MAAM,IAAI,OAAO,CAAO,CAAC,CAAC,EAAE,EAAE;oBAC5B,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,QAAQ,EAAE,CAAC;wBAClC,CAAC,EAAE,CAAA;wBACH,OAAM;oBACR,CAAC;oBACD,QAAQ,GAAG,CAAC,CAAA;gBACd,CAAC,CAAC,CAAA;YACJ,CAAC;QACH,CAAC;KACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Workspace } from '@braidhq/core';
|
|
2
|
+
export interface McpConfigFile {
|
|
3
|
+
readonly mcpServers: Readonly<Record<string, McpServerEntry>>;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Shape claude expects in `--mcp-config <file>`. Mirrors the spec's
|
|
7
|
+
* Streamable HTTP transport: a single endpoint URL with optional headers.
|
|
8
|
+
*/
|
|
9
|
+
interface McpStreamableHttpEntry {
|
|
10
|
+
readonly type: 'http';
|
|
11
|
+
readonly url: string;
|
|
12
|
+
readonly headers?: Record<string, string>;
|
|
13
|
+
}
|
|
14
|
+
type McpServerEntry = McpStreamableHttpEntry;
|
|
15
|
+
export declare function buildMcpConfig(workspace: Workspace): McpConfigFile;
|
|
16
|
+
export declare function writeMcpConfigFile(workspace: Workspace, targetDir: string): Promise<string>;
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=mcpConfig.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcpConfig.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/agent/mcpConfig.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAM9C,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAA;CAC9D;AAED;;;GAGG;AACH,UAAU,sBAAsB;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAC1C;AAED,KAAK,cAAc,GAAG,sBAAsB,CAAA;AAE5C,wBAAgB,cAAc,CAAC,SAAS,EAAE,SAAS,GAAG,aAAa,CAMlE;AAED,wBAAsB,kBAAkB,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAMjG"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { mkdir, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
|
+
import process from 'node:process';
|
|
4
|
+
export function buildMcpConfig(workspace) {
|
|
5
|
+
const entries = {};
|
|
6
|
+
for (const server of workspace.mcpServers) {
|
|
7
|
+
entries[server.id] = toEntry(server);
|
|
8
|
+
}
|
|
9
|
+
return { mcpServers: entries };
|
|
10
|
+
}
|
|
11
|
+
export async function writeMcpConfigFile(workspace, targetDir) {
|
|
12
|
+
const config = buildMcpConfig(workspace);
|
|
13
|
+
const targetPath = join(targetDir, `.braid-mcp-${workspace.id}.json`);
|
|
14
|
+
await mkdir(dirname(targetPath), { recursive: true });
|
|
15
|
+
await writeFile(targetPath, `${JSON.stringify(config, null, 2)}\n`, 'utf-8');
|
|
16
|
+
return targetPath;
|
|
17
|
+
}
|
|
18
|
+
function toEntry(server) {
|
|
19
|
+
// `type: 'http'` is what the claude CLI's mcp-config schema currently
|
|
20
|
+
// names the Streamable HTTP transport (it predates the rename in the MCP
|
|
21
|
+
// 2025-06-18 spec). We use the new name in PRODUCT.md to match the spec;
|
|
22
|
+
// we emit the legacy name here so claude understands.
|
|
23
|
+
return {
|
|
24
|
+
type: 'http',
|
|
25
|
+
url: server.url,
|
|
26
|
+
...(server.headers ? { headers: resolveHeaders(server.headers) } : {}),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Replace `${VAR}` references in header values with the matching env var.
|
|
31
|
+
* Throws if a referenced var is missing so the user gets a clear error at
|
|
32
|
+
* config-write time rather than a confusing 401 from the MCP server.
|
|
33
|
+
*/
|
|
34
|
+
function resolveHeaders(headers) {
|
|
35
|
+
const out = {};
|
|
36
|
+
for (const [name, value] of Object.entries(headers)) {
|
|
37
|
+
out[name] = value.replace(/\$\{([A-Z_][A-Z0-9_]*)\}/g, (_match, varName) => {
|
|
38
|
+
const resolved = process.env[varName];
|
|
39
|
+
if (resolved === undefined) {
|
|
40
|
+
throw new Error(`MCP header "${name}": environment variable "${varName}" is not set`);
|
|
41
|
+
}
|
|
42
|
+
return resolved;
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=mcpConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcpConfig.js","sourceRoot":"","sources":["../../../src/infrastructure/agent/mcpConfig.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,OAAO,MAAM,cAAc,CAAA;AAkBlC,MAAM,UAAU,cAAc,CAAC,SAAoB;IACjD,MAAM,OAAO,GAAmC,EAAE,CAAA;IAClD,KAAK,MAAM,MAAM,IAAI,SAAS,CAAC,UAAU,EAAE,CAAC;QAC1C,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IACtC,CAAC;IACD,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,CAAA;AAChC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,SAAoB,EAAE,SAAiB;IAC9E,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,CAAC,CAAA;IACxC,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,cAAc,SAAS,CAAC,EAAE,OAAO,CAAC,CAAA;IACrE,MAAM,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IACrD,MAAM,SAAS,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IAC5E,OAAO,UAAU,CAAA;AACnB,CAAC;AAED,SAAS,OAAO,CAAC,MAAuB;IACtC,sEAAsE;IACtE,yEAAyE;IACzE,yEAAyE;IACzE,sDAAsD;IACtD,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,GAAG,EAAE,MAAM,CAAC,GAAG;QACf,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACvE,CAAA;AACH,CAAC;AAED;;;;GAIG;AACH,SAAS,cAAc,CAAC,OAA+B;IACrD,MAAM,GAAG,GAA2B,EAAE,CAAA;IACtC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACpD,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,2BAA2B,EAAE,CAAC,MAAM,EAAE,OAAe,EAAE,EAAE;YACjF,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;YACrC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAC3B,MAAM,IAAI,KAAK,CAAC,eAAe,IAAI,4BAA4B,OAAO,cAAc,CAAC,CAAA;YACvF,CAAC;YACD,OAAO,QAAQ,CAAA;QACjB,CAAC,CAAC,CAAA;IACJ,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type LineHandler = (line: string) => void;
|
|
2
|
+
/**
|
|
3
|
+
* Splits a chunked text stream into newline-delimited lines, invoking the
|
|
4
|
+
* handler exactly once per complete line. Partial lines are buffered until
|
|
5
|
+
* the next chunk completes them. Call `flush()` after the source closes to
|
|
6
|
+
* release any trailing line without a terminator.
|
|
7
|
+
*/
|
|
8
|
+
export declare class LineBuffer {
|
|
9
|
+
private readonly onLine;
|
|
10
|
+
private buffer;
|
|
11
|
+
constructor(onLine: LineHandler);
|
|
12
|
+
append(chunk: string): void;
|
|
13
|
+
flush(): void;
|
|
14
|
+
}
|
|
15
|
+
export interface StreamJsonEvent {
|
|
16
|
+
readonly type: string;
|
|
17
|
+
readonly [key: string]: unknown;
|
|
18
|
+
}
|
|
19
|
+
export declare function parseJsonLine(line: string): StreamJsonEvent | undefined;
|
|
20
|
+
//# sourceMappingURL=streamJsonParser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streamJsonParser.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/agent/streamJsonParser.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;AAEhD;;;;;GAKG;AACH,qBAAa,UAAU;IAGT,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFnC,OAAO,CAAC,MAAM,CAAK;gBAEU,MAAM,EAAE,WAAW;IAEhD,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAY3B,KAAK,IAAI,IAAI;CAOd;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAChC;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAWvE"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Splits a chunked text stream into newline-delimited lines, invoking the
|
|
3
|
+
* handler exactly once per complete line. Partial lines are buffered until
|
|
4
|
+
* the next chunk completes them. Call `flush()` after the source closes to
|
|
5
|
+
* release any trailing line without a terminator.
|
|
6
|
+
*/
|
|
7
|
+
export class LineBuffer {
|
|
8
|
+
onLine;
|
|
9
|
+
buffer = '';
|
|
10
|
+
constructor(onLine) {
|
|
11
|
+
this.onLine = onLine;
|
|
12
|
+
}
|
|
13
|
+
append(chunk) {
|
|
14
|
+
this.buffer += chunk;
|
|
15
|
+
let newlineIndex = this.buffer.indexOf('\n');
|
|
16
|
+
while (newlineIndex >= 0) {
|
|
17
|
+
const line = this.buffer.slice(0, newlineIndex);
|
|
18
|
+
this.buffer = this.buffer.slice(newlineIndex + 1);
|
|
19
|
+
if (line.length > 0)
|
|
20
|
+
this.onLine(line);
|
|
21
|
+
newlineIndex = this.buffer.indexOf('\n');
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
flush() {
|
|
25
|
+
if (this.buffer.length === 0)
|
|
26
|
+
return;
|
|
27
|
+
const remainder = this.buffer;
|
|
28
|
+
this.buffer = '';
|
|
29
|
+
this.onLine(remainder);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export function parseJsonLine(line) {
|
|
33
|
+
const trimmed = line.trim();
|
|
34
|
+
if (trimmed.length === 0)
|
|
35
|
+
return undefined;
|
|
36
|
+
try {
|
|
37
|
+
const parsed = JSON.parse(trimmed);
|
|
38
|
+
return parsed;
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=streamJsonParser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streamJsonParser.js","sourceRoot":"","sources":["../../../src/infrastructure/agent/streamJsonParser.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,OAAO,UAAU;IAGQ;IAFrB,MAAM,GAAG,EAAE,CAAA;IAEnB,YAA6B,MAAmB;QAAnB,WAAM,GAAN,MAAM,CAAa;IAAG,CAAC;IAEpD,MAAM,CAAC,KAAa;QAClB,IAAI,CAAC,MAAM,IAAI,KAAK,CAAA;QACpB,IAAI,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QAC5C,OAAO,YAAY,IAAI,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC,CAAA;YAC/C,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,GAAG,CAAC,CAAC,CAAA;YACjD,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;gBACjB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;YACnB,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QAC1C,CAAC;IACH,CAAC;IAED,KAAK;QACH,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;YAC1B,OAAM;QACR,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAA;QAC7B,IAAI,CAAC,MAAM,GAAG,EAAE,CAAA;QAChB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;IACxB,CAAC;CACF;AAOD,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAA;IAC3B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QACtB,OAAO,SAAS,CAAA;IAClB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAoB,CAAA;QACrD,OAAO,MAAM,CAAA;IACf,CAAC;IACD,MAAM,CAAC;QACL,OAAO,SAAS,CAAA;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { SkillEvent } from '@braidhq/schema';
|
|
2
|
+
import type { ChildProcess } from 'node:child_process';
|
|
3
|
+
interface RawEvent {
|
|
4
|
+
readonly type: string;
|
|
5
|
+
readonly [key: string]: unknown;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Wires a child's stdout / stderr to a single SkillEvent callback.
|
|
9
|
+
* Returns `flush` so callers can drain the final un-terminated line on
|
|
10
|
+
* `close`.
|
|
11
|
+
*/
|
|
12
|
+
export declare function attachOutputBuffers(child: ChildProcess, onEvent: (event: SkillEvent) => void, now: () => string): {
|
|
13
|
+
flush: () => void;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Maps a single `claude --output-format stream-json` line into zero or more
|
|
17
|
+
* `SkillEvent`s. Claude emits these envelope shapes today: `system` (init
|
|
18
|
+
* meta, ignored except for `session_id`), `assistant` (text / tool_use
|
|
19
|
+
* content parts), `user` (echoed tool_result, only `is_error` surfaced),
|
|
20
|
+
* `rate_limit_*` (ignored), `result` (final outcome). Legacy flat shapes
|
|
21
|
+
* (`text`, `tool_use`, `artifact-written`, `error`) are kept for tests and
|
|
22
|
+
* older tools.
|
|
23
|
+
*/
|
|
24
|
+
export declare function mapSubprocessEvents(raw: RawEvent, now: string): SkillEvent[];
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=subprocessEventStream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subprocessEventStream.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/agent/subprocessEventStream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAItD,UAAU,QAAQ;IAAG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE;AAG7E;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,EACpC,GAAG,EAAE,MAAM,MAAM,GAChB;IAAE,KAAK,EAAE,MAAM,IAAI,CAAA;CAAE,CAyBvB;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,UAAU,EAAE,CAyE5E"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { SkillEvent as SkillEventSchema } from '@braidhq/schema';
|
|
2
|
+
import { LineBuffer, parseJsonLine } from './streamJsonParser.js';
|
|
3
|
+
/**
|
|
4
|
+
* Wires a child's stdout / stderr to a single SkillEvent callback.
|
|
5
|
+
* Returns `flush` so callers can drain the final un-terminated line on
|
|
6
|
+
* `close`.
|
|
7
|
+
*/
|
|
8
|
+
export function attachOutputBuffers(child, onEvent, now) {
|
|
9
|
+
const stdout = new LineBuffer((line) => {
|
|
10
|
+
const parsed = parseJsonLine(line);
|
|
11
|
+
if (parsed === undefined)
|
|
12
|
+
return;
|
|
13
|
+
for (const event of mapSubprocessEvents(parsed, now()))
|
|
14
|
+
onEvent(event);
|
|
15
|
+
});
|
|
16
|
+
// stderr is wrapped verbatim into a `[stderr]` message event so it
|
|
17
|
+
// shows up in the transcript alongside model output.
|
|
18
|
+
const stderr = new LineBuffer((line) => {
|
|
19
|
+
onEvent(SkillEventSchema.parse({ type: 'message', text: `[stderr] ${line}` }));
|
|
20
|
+
});
|
|
21
|
+
child.stdout?.setEncoding('utf-8');
|
|
22
|
+
child.stdout?.on('data', (chunk) => stdout.append(chunk));
|
|
23
|
+
child.stderr?.setEncoding('utf-8');
|
|
24
|
+
child.stderr?.on('data', (chunk) => stderr.append(chunk));
|
|
25
|
+
return {
|
|
26
|
+
flush: () => {
|
|
27
|
+
stdout.flush();
|
|
28
|
+
stderr.flush();
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Maps a single `claude --output-format stream-json` line into zero or more
|
|
34
|
+
* `SkillEvent`s. Claude emits these envelope shapes today: `system` (init
|
|
35
|
+
* meta, ignored except for `session_id`), `assistant` (text / tool_use
|
|
36
|
+
* content parts), `user` (echoed tool_result, only `is_error` surfaced),
|
|
37
|
+
* `rate_limit_*` (ignored), `result` (final outcome). Legacy flat shapes
|
|
38
|
+
* (`text`, `tool_use`, `artifact-written`, `error`) are kept for tests and
|
|
39
|
+
* older tools.
|
|
40
|
+
*/
|
|
41
|
+
export function mapSubprocessEvents(raw, now) {
|
|
42
|
+
const out = [];
|
|
43
|
+
if (raw.type === 'system' && raw.subtype === 'init' && typeof raw.session_id === 'string') {
|
|
44
|
+
out.push(SkillEventSchema.parse({ type: 'session-started', sessionId: raw.session_id }));
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
if (raw.type === 'assistant') {
|
|
48
|
+
for (const part of readContent(raw)) {
|
|
49
|
+
if (part?.type === 'text' && typeof part.text === 'string' && part.text.length > 0) {
|
|
50
|
+
out.push(SkillEventSchema.parse({ type: 'message', text: part.text }));
|
|
51
|
+
}
|
|
52
|
+
else if (part?.type === 'tool_use' && typeof part.name === 'string') {
|
|
53
|
+
const event = {
|
|
54
|
+
type: 'tool-call',
|
|
55
|
+
tool: part.name,
|
|
56
|
+
args: part.input ?? null,
|
|
57
|
+
};
|
|
58
|
+
if (typeof part.id === 'string' && part.id.length > 0)
|
|
59
|
+
event.toolCallId = part.id;
|
|
60
|
+
out.push(SkillEventSchema.parse(event));
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return out;
|
|
64
|
+
}
|
|
65
|
+
if (raw.type === 'user') {
|
|
66
|
+
for (const part of readContent(raw)) {
|
|
67
|
+
if (part?.type === 'tool_result' && typeof part.tool_use_id === 'string') {
|
|
68
|
+
const output = typeof part.content === 'string'
|
|
69
|
+
? part.content
|
|
70
|
+
: JSON.stringify(part.content ?? '');
|
|
71
|
+
out.push(SkillEventSchema.parse({
|
|
72
|
+
type: 'tool-result',
|
|
73
|
+
toolCallId: part.tool_use_id,
|
|
74
|
+
output,
|
|
75
|
+
isError: part.is_error === true,
|
|
76
|
+
}));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return out;
|
|
80
|
+
}
|
|
81
|
+
if (raw.type === 'result') {
|
|
82
|
+
const isError = raw.is_error === true;
|
|
83
|
+
const text = typeof raw.result === 'string' ? raw.result : '';
|
|
84
|
+
if (isError)
|
|
85
|
+
out.push(SkillEventSchema.parse({ type: 'error', message: text || 'skill run failed', at: now }));
|
|
86
|
+
else if (text.length > 0)
|
|
87
|
+
out.push(SkillEventSchema.parse({ type: 'message', text }));
|
|
88
|
+
return out;
|
|
89
|
+
}
|
|
90
|
+
if (raw.type === 'text' && typeof raw.text === 'string')
|
|
91
|
+
return [SkillEventSchema.parse({ type: 'message', text: raw.text })];
|
|
92
|
+
if (raw.type === 'tool_use' && typeof raw.name === 'string')
|
|
93
|
+
return [SkillEventSchema.parse({ type: 'tool-call', tool: raw.name, args: raw.input ?? null })];
|
|
94
|
+
if (raw.type === 'artifact-written' && typeof raw.artifactKind === 'string') {
|
|
95
|
+
return [SkillEventSchema.parse({
|
|
96
|
+
type: 'artifact-written',
|
|
97
|
+
artifactKind: raw.artifactKind,
|
|
98
|
+
artifactId: raw.artifactId,
|
|
99
|
+
path: raw.path,
|
|
100
|
+
})];
|
|
101
|
+
}
|
|
102
|
+
if (raw.type === 'error' && typeof raw.message === 'string')
|
|
103
|
+
return [SkillEventSchema.parse({ type: 'error', message: raw.message, at: now })];
|
|
104
|
+
return out;
|
|
105
|
+
}
|
|
106
|
+
function readContent(raw) {
|
|
107
|
+
const message = raw.message;
|
|
108
|
+
if (!message || !Array.isArray(message.content))
|
|
109
|
+
return [];
|
|
110
|
+
return message.content;
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=subprocessEventStream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subprocessEventStream.js","sourceRoot":"","sources":["../../../src/infrastructure/agent/subprocessEventStream.ts"],"names":[],"mappings":"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"}
|