@hmharness/agent 0.6.7 → 0.7.0
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/dist/runner.js +26 -0
- package/package.json +6 -5
package/dist/runner.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* approval gate construction.
|
|
7
7
|
*/
|
|
8
8
|
import { homeDir, loadConfig, resolveProvider, mcpServerTools, Registry, runLoop, Session, } from '@hmharness/kernel';
|
|
9
|
+
import { brief, createTrajectoryRecorder } from '@hmharness/observability';
|
|
9
10
|
import { readFile } from 'node:fs/promises';
|
|
10
11
|
import { readFileSync, writeFileSync } from 'node:fs';
|
|
11
12
|
import { join, dirname } from 'node:path';
|
|
@@ -229,6 +230,11 @@ export async function runAgentTask(opts) {
|
|
|
229
230
|
const ctx = opts.ctx ?? { cwd: process.cwd(), home: homeDir() };
|
|
230
231
|
const events = opts.events ?? {};
|
|
231
232
|
const session = new Session(ctx.home, ctx.cwd, cfg.provider.model);
|
|
233
|
+
// V2 M1 flight recorder: every run leaves a typed, replayable trajectory
|
|
234
|
+
// under <home>/runs/<run-id>/. Best-effort by contract - storage failures
|
|
235
|
+
// are swallowed inside the recorder and can never fail the task itself.
|
|
236
|
+
const traj = createTrajectoryRecorder(ctx.home, { task: opts.task, model: cfg.provider.model, cwd: ctx.cwd });
|
|
237
|
+
traj.emit('run.started', 'user', { task: brief(opts.task, 400) });
|
|
232
238
|
// workspace scoping + optional embedding hybrid for memory retrieval.
|
|
233
239
|
// Embeddings only when routing.embedding is EXPLICITLY set - an inherited
|
|
234
240
|
// chat route would 404 on /embeddings once per task for nothing.
|
|
@@ -256,6 +262,14 @@ export async function runAgentTask(opts) {
|
|
|
256
262
|
// watches IT - this makes the size visible every run (review finding #5)
|
|
257
263
|
const systemTokens = Math.ceil(system.length / 4);
|
|
258
264
|
events.onLine?.(` [prompt] system: ${system.length} chars (~${systemTokens} tokens) · ${agentsMd ? 'AGENTS.md: yes' : 'no AGENTS.md'}`);
|
|
265
|
+
traj.emit('context.assembled', 'system', {
|
|
266
|
+
systemChars: system.length,
|
|
267
|
+
systemTokens,
|
|
268
|
+
agentsMd: Boolean(agentsMd),
|
|
269
|
+
memoryChars: pack.memory.length,
|
|
270
|
+
skills: pack.skills.length,
|
|
271
|
+
insights: pack.insights.length,
|
|
272
|
+
});
|
|
259
273
|
await session.user(opts.task);
|
|
260
274
|
// YOLO fix: when yes=true the caller's approvalAsk (TUI dialog, web remote
|
|
261
275
|
// gate) must NOT override the auto-approve gate - it used to take
|
|
@@ -306,6 +320,7 @@ export async function runAgentTask(opts) {
|
|
|
306
320
|
onDelta: (kind, chunk) => events.onDelta?.(kind, chunk),
|
|
307
321
|
onToolCall: (name, args) => {
|
|
308
322
|
toolsUsed.push(name);
|
|
323
|
+
traj.emit('tool.requested', 'tool', { name, args: brief(args, 120) });
|
|
309
324
|
events.onToolCall?.(name, args);
|
|
310
325
|
},
|
|
311
326
|
onToolResult: (name, output, isError) => {
|
|
@@ -313,19 +328,30 @@ export async function runAgentTask(opts) {
|
|
|
313
328
|
const list = toolErrors.get(name) ?? [];
|
|
314
329
|
list.push(output.split('\n')[0].slice(0, 120));
|
|
315
330
|
toolErrors.set(name, list);
|
|
331
|
+
traj.emit('error.observed', 'tool', { name, preview: brief(output, 160) });
|
|
316
332
|
}
|
|
317
333
|
void session.tool(name, output, isError);
|
|
334
|
+
traj.emit('tool.completed', 'tool', { name, isError, preview: brief(output, 120) });
|
|
318
335
|
events.onToolResult?.(name, output, isError);
|
|
319
336
|
},
|
|
320
337
|
onApproval: (name, args, granted) => {
|
|
321
338
|
void session.approval(name, granted);
|
|
339
|
+
traj.emit(granted ? 'tool.approved' : 'tool.denied', 'system', { name });
|
|
322
340
|
events.onApproval?.(name, args, granted);
|
|
323
341
|
},
|
|
324
342
|
onAssistant: async (m) => {
|
|
343
|
+
// stamp the event when the message lands, not after the session
|
|
344
|
+
// write drains - awaiting first made model.responded land AFTER
|
|
345
|
+
// run.completed in the timeline
|
|
346
|
+
traj.emit('model.responded', 'agent', { contentChars: m.content?.length ?? 0, toolCalls: m.tool_calls?.length ?? 0 });
|
|
325
347
|
await session.assistant(m.content ?? null, m.tool_calls);
|
|
326
348
|
},
|
|
327
349
|
},
|
|
350
|
+
}).catch((err) => {
|
|
351
|
+
traj.finish({ success: false, reason: 'error', error: brief(String(err), 200) }, { toolUses: toolsUsed.length });
|
|
352
|
+
throw err;
|
|
328
353
|
});
|
|
354
|
+
traj.finish({ success: result.reason === 'final', reason: result.reason }, { turns: result.turns, toolUses: result.toolUses, promptTokens: result.usage.promptTokens, completionTokens: result.usage.completionTokens });
|
|
329
355
|
// ---- instant feedback: learn from THIS task's mistakes, not 8 tasks later ----
|
|
330
356
|
// Tier 1 (always, zero cost): raw error pattern → memory self-note. Lowered
|
|
331
357
|
// to 1 failure for system-level patterns (shell incompat, auth, missing
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hmharness/agent",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "hmharness agent execution layer: base tools, system prompt, sub-agent spawn, and the shared task runner that frontends (cli, web) drive.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -15,10 +15,11 @@
|
|
|
15
15
|
"build": "tsc -p tsconfig.build.json"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@hmharness/kernel": "0.
|
|
19
|
-
"@hmharness/
|
|
20
|
-
"@hmharness/
|
|
21
|
-
"@hmharness/domain-
|
|
18
|
+
"@hmharness/kernel": "0.7.0",
|
|
19
|
+
"@hmharness/observability": "0.7.0",
|
|
20
|
+
"@hmharness/evolution": "0.7.0",
|
|
21
|
+
"@hmharness/domain-harmony": "0.7.0",
|
|
22
|
+
"@hmharness/domain-ops": "0.7.0"
|
|
22
23
|
},
|
|
23
24
|
"files": [
|
|
24
25
|
"dist"
|