granclaw 0.0.1-beta.91 → 0.0.1-beta.93
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.
|
@@ -98,15 +98,25 @@ async function executeLlmStep(config, prevOutput, allResults, workspaceDir, agen
|
|
|
98
98
|
process.env[envKey] = prevValue;
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
|
-
async function executeAgentStep(config, prevOutput, allResults, agent, channelId) {
|
|
101
|
+
async function executeAgentStep(config, prevOutput, allResults, agent, channelId, onEvent) {
|
|
102
102
|
const rawPrompt = config.prompt;
|
|
103
103
|
const timeoutMs = config.timeout_ms ?? 300_000;
|
|
104
104
|
const prompt = resolveTemplates(rawPrompt, prevOutput, allResults);
|
|
105
105
|
let responseText = '';
|
|
106
106
|
await Promise.race([
|
|
107
107
|
(0, runner_pi_js_1.runAgent)(agent, prompt, (chunk) => {
|
|
108
|
-
if (chunk.type === 'text')
|
|
108
|
+
if (chunk.type === 'text') {
|
|
109
109
|
responseText += chunk.text;
|
|
110
|
+
}
|
|
111
|
+
else if (chunk.type === 'tool_call') {
|
|
112
|
+
onEvent({ type: 'tool_call', ts: Date.now(), tool: chunk.tool, input: chunk.input });
|
|
113
|
+
}
|
|
114
|
+
else if (chunk.type === 'tool_result') {
|
|
115
|
+
onEvent({ type: 'tool_result', ts: Date.now(), tool: chunk.tool, output: chunk.output });
|
|
116
|
+
}
|
|
117
|
+
else if (chunk.type === 'error') {
|
|
118
|
+
onEvent({ type: 'error', ts: Date.now(), message: chunk.message });
|
|
119
|
+
}
|
|
110
120
|
}, { channelId }),
|
|
111
121
|
new Promise((_, reject) => setTimeout(() => reject(new Error('Agent step timed out')), timeoutMs)),
|
|
112
122
|
]);
|
|
@@ -178,7 +188,39 @@ async function executeWorkflow(agentId, workflowId, trigger) {
|
|
|
178
188
|
}
|
|
179
189
|
else if (currentStep.type === 'agent') {
|
|
180
190
|
const stepChannelId = `wf-${run.id}-s${currentStep.position}`;
|
|
181
|
-
|
|
191
|
+
const events = [];
|
|
192
|
+
let pendingFlush = null;
|
|
193
|
+
let lastFlushAt = 0;
|
|
194
|
+
const flush = () => {
|
|
195
|
+
pendingFlush = null;
|
|
196
|
+
lastFlushAt = Date.now();
|
|
197
|
+
try {
|
|
198
|
+
(0, workflows_db_js_1.writeRunStepEvents)(agentId, runStepId, events);
|
|
199
|
+
}
|
|
200
|
+
catch { }
|
|
201
|
+
};
|
|
202
|
+
const scheduleFlush = () => {
|
|
203
|
+
if (pendingFlush)
|
|
204
|
+
return;
|
|
205
|
+
const elapsed = Date.now() - lastFlushAt;
|
|
206
|
+
const delay = elapsed >= 1000 ? 0 : 1000 - elapsed;
|
|
207
|
+
pendingFlush = setTimeout(flush, delay);
|
|
208
|
+
};
|
|
209
|
+
try {
|
|
210
|
+
output = await executeAgentStep(currentStep.config, prevOutput, allResults, agent, stepChannelId, (event) => { events.push(event); scheduleFlush(); });
|
|
211
|
+
}
|
|
212
|
+
finally {
|
|
213
|
+
if (pendingFlush) {
|
|
214
|
+
clearTimeout(pendingFlush);
|
|
215
|
+
pendingFlush = null;
|
|
216
|
+
}
|
|
217
|
+
if (events.length > 0) {
|
|
218
|
+
try {
|
|
219
|
+
(0, workflows_db_js_1.writeRunStepEvents)(agentId, runStepId, events);
|
|
220
|
+
}
|
|
221
|
+
catch { }
|
|
222
|
+
}
|
|
223
|
+
}
|
|
182
224
|
}
|
|
183
225
|
else {
|
|
184
226
|
output = await executeLlmStep(currentStep.config, prevOutput, allResults, workspaceDir, agent.model);
|
|
@@ -17,6 +17,7 @@ exports.listRuns = listRuns;
|
|
|
17
17
|
exports.getRun = getRun;
|
|
18
18
|
exports.createRunStep = createRunStep;
|
|
19
19
|
exports.updateRunStep = updateRunStep;
|
|
20
|
+
exports.writeRunStepEvents = writeRunStepEvents;
|
|
20
21
|
exports.getRunningRuns = getRunningRuns;
|
|
21
22
|
exports.finalizeRunningRuns = finalizeRunningRuns;
|
|
22
23
|
exports.getLatestRun = getLatestRun;
|
|
@@ -71,6 +72,7 @@ function rowToRunStep(r) {
|
|
|
71
72
|
input: r.input ? JSON.parse(r.input) : null,
|
|
72
73
|
output: r.output ? JSON.parse(r.output) : null,
|
|
73
74
|
error: r.error ?? null,
|
|
75
|
+
events: r.events ? JSON.parse(r.events) : null,
|
|
74
76
|
startedAt: r.started_at ?? null,
|
|
75
77
|
finishedAt: r.finished_at ?? null,
|
|
76
78
|
durationMs: r.duration_ms ?? null,
|
|
@@ -196,6 +198,10 @@ function updateRunStep(agentId, runStepId, data) {
|
|
|
196
198
|
WHERE id = ?
|
|
197
199
|
`).run(data.status, data.input !== undefined ? JSON.stringify(data.input) : null, data.output !== undefined ? JSON.stringify(data.output) : null, data.error ?? null, data.startedAt ?? null, data.finishedAt ?? null, data.durationMs ?? null, runStepId);
|
|
198
200
|
}
|
|
201
|
+
function writeRunStepEvents(agentId, runStepId, events) {
|
|
202
|
+
getDb(agentId).prepare(`UPDATE run_steps SET events = ? WHERE id = ?`)
|
|
203
|
+
.run(JSON.stringify(events), runStepId);
|
|
204
|
+
}
|
|
199
205
|
function getRunningRuns(agentId) {
|
|
200
206
|
try {
|
|
201
207
|
const db = getDb(agentId);
|
|
@@ -110,12 +110,18 @@ function getWorkspaceDb(workspaceDir) {
|
|
|
110
110
|
input TEXT,
|
|
111
111
|
output TEXT,
|
|
112
112
|
error TEXT,
|
|
113
|
+
events TEXT,
|
|
113
114
|
started_at INTEGER,
|
|
114
115
|
finished_at INTEGER,
|
|
115
116
|
duration_ms INTEGER
|
|
116
117
|
);
|
|
117
118
|
CREATE INDEX IF NOT EXISTS idx_run_steps_run ON run_steps(run_id, started_at);
|
|
118
119
|
`);
|
|
120
|
+
const runStepsCols = db.prepare(`PRAGMA table_info(run_steps)`).all();
|
|
121
|
+
if (runStepsCols.length > 0 && !runStepsCols.some(c => c.name === 'events')) {
|
|
122
|
+
db.exec(`ALTER TABLE run_steps ADD COLUMN events TEXT`);
|
|
123
|
+
console.log('[workspace-pool] migrated run_steps table (added events column)');
|
|
124
|
+
}
|
|
119
125
|
const tasksSchema = db.prepare(`SELECT sql FROM sqlite_master WHERE type='table' AND name='tasks'`).get();
|
|
120
126
|
if (tasksSchema?.sql && !tasksSchema.sql.includes('cancelled')) {
|
|
121
127
|
db.exec(`
|