@atolis-hq/wake 0.2.44 → 0.2.45

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.
@@ -1,6 +1,7 @@
1
1
  import { parseClaudePrintResult, parseRunnerResult } from '../../domain/schema.js';
2
2
  import { runAgentCliCommand } from '../runner/cli-command.js';
3
3
  import { buildStagePrompt } from '../runner/stage-prompt.js';
4
+ import { emitRuntimeEvent, runnerRuntimeEvent } from '../runner/runtime-events.js';
4
5
  import { writeRunnerTranscript } from '../runner/transcripts.js';
5
6
  export { buildStagePrompt } from '../runner/stage-prompt.js';
6
7
  function slugify(value, maxLength = 40) {
@@ -221,7 +222,18 @@ export function createClaudeRunner(options) {
221
222
  args,
222
223
  cwd: input.workspacePath ?? options.cwd,
223
224
  timeoutMs: options.settings.timeoutMs,
224
- ...(input.onProcessStart === undefined ? {} : { onProcessStart: input.onProcessStart }),
225
+ onProcessStart: async (identity) => {
226
+ await input.onProcessStart?.(identity);
227
+ await emitRuntimeEvent(input.onRuntimeEvent, runnerRuntimeEvent({
228
+ type: 'agent.process.started',
229
+ runId: input.runId,
230
+ projection: input.projection,
231
+ routing: input.routing,
232
+ cli: CLAUDE_CLI_NAME,
233
+ model,
234
+ payload: { pid: identity.pid, processStartedAt: identity.processStartedAt },
235
+ }));
236
+ },
225
237
  });
226
238
  const responseTranscriptPath = await writeRunnerTranscript({
227
239
  config: input.config,
@@ -250,6 +262,15 @@ export function createClaudeRunner(options) {
250
262
  ...(input.workspacePath === undefined ? {} : { workspacePath: input.workspacePath }),
251
263
  exitCode: result.exitCode,
252
264
  }));
265
+ await emitRuntimeEvent(input.onRuntimeEvent, runnerRuntimeEvent({
266
+ type: 'agent.process.exited',
267
+ runId: input.runId,
268
+ projection: input.projection,
269
+ routing: input.routing,
270
+ cli: CLAUDE_CLI_NAME,
271
+ model,
272
+ payload: { exitCode: result.exitCode, timedOut: result.timedOut },
273
+ }));
253
274
  let parsedReason;
254
275
  let stdoutFailureDetail;
255
276
  const trimmedStdout = result.stdout.trim();
@@ -295,6 +316,16 @@ export function createClaudeRunner(options) {
295
316
  }
296
317
  const parsed = parseClaudePrintOutput(result.stdout);
297
318
  const sandboxLog = readSandboxLogBreadcrumb();
319
+ await emitRuntimeEvent(input.onRuntimeEvent, runnerRuntimeEvent({
320
+ type: 'agent.progress',
321
+ runId: input.runId,
322
+ projection: input.projection,
323
+ routing: input.routing,
324
+ cli: CLAUDE_CLI_NAME,
325
+ model,
326
+ ...(parsed.session_id === undefined ? {} : { sessionId: parsed.session_id }),
327
+ payload: { message: 'Claude print result received', raw: parsed },
328
+ }));
298
329
  console.log(formatClaudeRunLogLine({
299
330
  phase: 'success',
300
331
  runId: input.runId,
@@ -307,6 +338,28 @@ export function createClaudeRunner(options) {
307
338
  ...(parsed.session_id === undefined ? {} : { sessionId: parsed.session_id }),
308
339
  }));
309
340
  const tokenUsage = extractTokenUsage(parsed);
341
+ if (tokenUsage !== undefined) {
342
+ await emitRuntimeEvent(input.onRuntimeEvent, runnerRuntimeEvent({
343
+ type: 'agent.usage.updated',
344
+ runId: input.runId,
345
+ projection: input.projection,
346
+ routing: input.routing,
347
+ cli: CLAUDE_CLI_NAME,
348
+ model,
349
+ ...(parsed.session_id === undefined ? {} : { sessionId: parsed.session_id }),
350
+ payload: { tokenUsage },
351
+ }));
352
+ }
353
+ await emitRuntimeEvent(input.onRuntimeEvent, runnerRuntimeEvent({
354
+ type: 'agent.process.exited',
355
+ runId: input.runId,
356
+ projection: input.projection,
357
+ routing: input.routing,
358
+ cli: CLAUDE_CLI_NAME,
359
+ model,
360
+ ...(parsed.session_id === undefined ? {} : { sessionId: parsed.session_id }),
361
+ payload: { exitCode: result.exitCode, timedOut: result.timedOut },
362
+ }));
310
363
  return {
311
364
  result: parsed.result,
312
365
  model,
@@ -1,5 +1,6 @@
1
1
  import { buildStagePrompt } from '../runner/stage-prompt.js';
2
2
  import { runAgentCliCommand } from '../runner/cli-command.js';
3
+ import { emitRuntimeEvent, runnerRuntimeEvent } from '../runner/runtime-events.js';
3
4
  import { writeRunnerTranscript } from '../runner/transcripts.js';
4
5
  import { parseRunnerResult } from '../../domain/schema.js';
5
6
  const CODEX_CLI_NAME = 'Codex';
@@ -268,7 +269,18 @@ export function createCodexRunner(options) {
268
269
  }),
269
270
  cwd,
270
271
  timeoutMs: options.settings.timeoutMs,
271
- ...(input.onProcessStart === undefined ? {} : { onProcessStart: input.onProcessStart }),
272
+ onProcessStart: async (identity) => {
273
+ await input.onProcessStart?.(identity);
274
+ await emitRuntimeEvent(input.onRuntimeEvent, runnerRuntimeEvent({
275
+ type: 'agent.process.started',
276
+ runId: input.runId,
277
+ projection: input.projection,
278
+ routing: input.routing,
279
+ cli: CODEX_CLI_NAME,
280
+ model,
281
+ payload: { pid: identity.pid, processStartedAt: identity.processStartedAt },
282
+ }));
283
+ },
272
284
  });
273
285
  const responseTranscriptPath = await writeRunnerTranscript({
274
286
  config: input.config,
@@ -300,6 +312,15 @@ export function createCodexRunner(options) {
300
312
  ...(input.workspacePath === undefined ? {} : { workspacePath: input.workspacePath }),
301
313
  exitCode: result.exitCode,
302
314
  }));
315
+ await emitRuntimeEvent(input.onRuntimeEvent, runnerRuntimeEvent({
316
+ type: 'agent.process.exited',
317
+ runId: input.runId,
318
+ projection: input.projection,
319
+ routing: input.routing,
320
+ cli: CODEX_CLI_NAME,
321
+ model,
322
+ payload: { exitCode: result.exitCode, timedOut: result.timedOut },
323
+ }));
303
324
  return {
304
325
  result: [
305
326
  result.timedOut
@@ -331,6 +352,60 @@ export function createCodexRunner(options) {
331
352
  }
332
353
  const parsed = extractCodexExecResult(result.stdout);
333
354
  const sandboxLog = readSandboxLogBreadcrumb();
355
+ const rawEvents = result.stdout
356
+ .split(/\r?\n/)
357
+ .filter((line) => line.trim().length > 0)
358
+ .map((line) => JSON.parse(line));
359
+ for (const raw of rawEvents) {
360
+ if (raw.type === 'thread.started' && typeof raw.thread_id === 'string') {
361
+ await emitRuntimeEvent(input.onRuntimeEvent, runnerRuntimeEvent({
362
+ type: 'agent.session.started',
363
+ runId: input.runId,
364
+ projection: input.projection,
365
+ routing: input.routing,
366
+ cli: CODEX_CLI_NAME,
367
+ model,
368
+ sessionId: raw.thread_id,
369
+ payload: { raw },
370
+ }));
371
+ }
372
+ else if (raw.type === 'turn.completed') {
373
+ await emitRuntimeEvent(input.onRuntimeEvent, runnerRuntimeEvent({
374
+ type: 'agent.turn.completed',
375
+ runId: input.runId,
376
+ projection: input.projection,
377
+ routing: input.routing,
378
+ cli: CODEX_CLI_NAME,
379
+ model,
380
+ ...(parsed.sessionId === undefined ? {} : { sessionId: parsed.sessionId }),
381
+ payload: { raw },
382
+ }));
383
+ }
384
+ else if (raw.type === 'item.completed') {
385
+ await emitRuntimeEvent(input.onRuntimeEvent, runnerRuntimeEvent({
386
+ type: 'agent.progress',
387
+ runId: input.runId,
388
+ projection: input.projection,
389
+ routing: input.routing,
390
+ cli: CODEX_CLI_NAME,
391
+ model,
392
+ ...(parsed.sessionId === undefined ? {} : { sessionId: parsed.sessionId }),
393
+ payload: { raw },
394
+ }));
395
+ }
396
+ }
397
+ if (parsed.tokenUsage !== undefined) {
398
+ await emitRuntimeEvent(input.onRuntimeEvent, runnerRuntimeEvent({
399
+ type: 'agent.usage.updated',
400
+ runId: input.runId,
401
+ projection: input.projection,
402
+ routing: input.routing,
403
+ cli: CODEX_CLI_NAME,
404
+ model,
405
+ ...(parsed.sessionId === undefined ? {} : { sessionId: parsed.sessionId }),
406
+ payload: { tokenUsage: parsed.tokenUsage },
407
+ }));
408
+ }
334
409
  console.log(formatCodexRunLogLine({
335
410
  phase: 'success',
336
411
  runId: input.runId,
@@ -342,6 +417,16 @@ export function createCodexRunner(options) {
342
417
  ...(input.workspacePath === undefined ? {} : { workspacePath: input.workspacePath }),
343
418
  ...(parsed.sessionId === undefined ? {} : { sessionId: parsed.sessionId }),
344
419
  }));
420
+ await emitRuntimeEvent(input.onRuntimeEvent, runnerRuntimeEvent({
421
+ type: 'agent.process.exited',
422
+ runId: input.runId,
423
+ projection: input.projection,
424
+ routing: input.routing,
425
+ cli: CODEX_CLI_NAME,
426
+ model,
427
+ ...(parsed.sessionId === undefined ? {} : { sessionId: parsed.sessionId }),
428
+ payload: { exitCode: result.exitCode, timedOut: result.timedOut },
429
+ }));
345
430
  return {
346
431
  result: parsed.result,
347
432
  model,
@@ -354,10 +439,7 @@ export function createCodexRunner(options) {
354
439
  metadata: {
355
440
  stdout: result.stdout,
356
441
  stderr: result.stderr,
357
- raw: result.stdout
358
- .split(/\r?\n/)
359
- .filter((line) => line.trim().length > 0)
360
- .map((line) => JSON.parse(line)),
442
+ raw: rawEvents,
361
443
  skipApproval: stagePrompt.skipApproval,
362
444
  allowAutoApproval: stagePrompt.allowAutoApproval,
363
445
  ...(promptTranscriptPath === undefined ? {} : { promptTranscriptPath }),
@@ -1,6 +1,7 @@
1
1
  import { parseRunnerResult } from '../../domain/schema.js';
2
2
  import { buildStagePrompt } from '../runner/stage-prompt.js';
3
3
  import { runAgentCliCommand } from '../runner/cli-command.js';
4
+ import { emitRuntimeEvent, runnerRuntimeEvent } from '../runner/runtime-events.js';
4
5
  import { writeRunnerTranscript } from '../runner/transcripts.js';
5
6
  const CURSOR_CLI_NAME = 'Cursor';
6
7
  export function buildCursorAgentArgs(input) {
@@ -219,7 +220,18 @@ export function createCursorRunner(options) {
219
220
  }),
220
221
  cwd,
221
222
  timeoutMs: options.settings.timeoutMs,
222
- ...(input.onProcessStart === undefined ? {} : { onProcessStart: input.onProcessStart }),
223
+ onProcessStart: async (identity) => {
224
+ await input.onProcessStart?.(identity);
225
+ await emitRuntimeEvent(input.onRuntimeEvent, runnerRuntimeEvent({
226
+ type: 'agent.process.started',
227
+ runId: input.runId,
228
+ projection: input.projection,
229
+ routing: input.routing,
230
+ cli: CURSOR_CLI_NAME,
231
+ model,
232
+ payload: { pid: identity.pid, processStartedAt: identity.processStartedAt },
233
+ }));
234
+ },
223
235
  });
224
236
  const responseTranscriptPath = await writeRunnerTranscript({
225
237
  config: input.config,
@@ -248,6 +260,15 @@ export function createCursorRunner(options) {
248
260
  ...(input.workspacePath === undefined ? {} : { workspacePath: input.workspacePath }),
249
261
  exitCode: result.exitCode,
250
262
  }));
263
+ await emitRuntimeEvent(input.onRuntimeEvent, runnerRuntimeEvent({
264
+ type: 'agent.process.exited',
265
+ runId: input.runId,
266
+ projection: input.projection,
267
+ routing: input.routing,
268
+ cli: CURSOR_CLI_NAME,
269
+ model,
270
+ payload: { exitCode: result.exitCode, timedOut: result.timedOut },
271
+ }));
251
272
  return {
252
273
  result: [
253
274
  result.timedOut
@@ -299,6 +320,28 @@ export function createCursorRunner(options) {
299
320
  };
300
321
  }
301
322
  const sandboxLog = readSandboxLogBreadcrumb();
323
+ await emitRuntimeEvent(input.onRuntimeEvent, runnerRuntimeEvent({
324
+ type: 'agent.progress',
325
+ runId: input.runId,
326
+ projection: input.projection,
327
+ routing: input.routing,
328
+ cli: CURSOR_CLI_NAME,
329
+ model,
330
+ ...(parsed.sessionId === undefined ? {} : { sessionId: parsed.sessionId }),
331
+ payload: { message: 'Cursor agent result received', raw: parsed },
332
+ }));
333
+ if (parsed.tokenUsage !== undefined) {
334
+ await emitRuntimeEvent(input.onRuntimeEvent, runnerRuntimeEvent({
335
+ type: 'agent.usage.updated',
336
+ runId: input.runId,
337
+ projection: input.projection,
338
+ routing: input.routing,
339
+ cli: CURSOR_CLI_NAME,
340
+ model,
341
+ ...(parsed.sessionId === undefined ? {} : { sessionId: parsed.sessionId }),
342
+ payload: { tokenUsage: parsed.tokenUsage },
343
+ }));
344
+ }
302
345
  console.log(formatCursorRunLogLine({
303
346
  phase: 'success',
304
347
  runId: input.runId,
@@ -310,6 +353,16 @@ export function createCursorRunner(options) {
310
353
  ...(input.workspacePath === undefined ? {} : { workspacePath: input.workspacePath }),
311
354
  ...(parsed.sessionId === undefined ? {} : { sessionId: parsed.sessionId }),
312
355
  }));
356
+ await emitRuntimeEvent(input.onRuntimeEvent, runnerRuntimeEvent({
357
+ type: 'agent.process.exited',
358
+ runId: input.runId,
359
+ projection: input.projection,
360
+ routing: input.routing,
361
+ cli: CURSOR_CLI_NAME,
362
+ model,
363
+ ...(parsed.sessionId === undefined ? {} : { sessionId: parsed.sessionId }),
364
+ payload: { exitCode: result.exitCode, timedOut: result.timedOut },
365
+ }));
313
366
  return {
314
367
  result: parsed.result,
315
368
  model,
@@ -1,6 +1,37 @@
1
+ import { emitRuntimeEvent, runnerRuntimeEvent } from '../runner/runtime-events.js';
1
2
  export function createFakeRunner(result, options) {
2
3
  return {
3
4
  async run(_) {
5
+ const cli = options?.cli ?? 'Fake';
6
+ await emitRuntimeEvent(_.onRuntimeEvent, runnerRuntimeEvent({
7
+ type: 'agent.process.started',
8
+ runId: _.runId,
9
+ projection: _.projection,
10
+ routing: _.routing,
11
+ cli,
12
+ model: 'fake',
13
+ payload: { synthetic: true },
14
+ }));
15
+ await emitRuntimeEvent(_.onRuntimeEvent, runnerRuntimeEvent({
16
+ type: 'agent.progress',
17
+ runId: _.runId,
18
+ projection: _.projection,
19
+ routing: _.routing,
20
+ cli,
21
+ model: 'fake',
22
+ sessionId: 'fake-session-1',
23
+ payload: { message: 'Fake runner completed', synthetic: true },
24
+ }));
25
+ await emitRuntimeEvent(_.onRuntimeEvent, runnerRuntimeEvent({
26
+ type: 'agent.process.exited',
27
+ runId: _.runId,
28
+ projection: _.projection,
29
+ routing: _.routing,
30
+ cli,
31
+ model: 'fake',
32
+ sessionId: 'fake-session-1',
33
+ payload: { exitCode: 0, synthetic: true },
34
+ }));
4
35
  return (result ?? {
5
36
  result: [
6
37
  'Fake runner completed',
@@ -11,7 +42,7 @@ export function createFakeRunner(result, options) {
11
42
  'DONE',
12
43
  ].join('\n'),
13
44
  model: 'fake',
14
- cli: options?.cli ?? 'Fake',
45
+ cli,
15
46
  session_id: 'fake-session-1',
16
47
  metadata: {
17
48
  source: 'fake-runner',
@@ -0,0 +1,32 @@
1
+ function runnerKindForCli(cli) {
2
+ if (cli === 'Claude') {
3
+ return 'claude';
4
+ }
5
+ if (cli === 'Codex') {
6
+ return 'codex';
7
+ }
8
+ if (cli === 'Cursor') {
9
+ return 'cursor';
10
+ }
11
+ return 'fake';
12
+ }
13
+ export function runnerRuntimeEvent(input) {
14
+ return {
15
+ type: input.type,
16
+ runId: input.runId,
17
+ workItemId: input.projection.workItemKey,
18
+ runner: {
19
+ name: input.routing?.runnerName ?? input.cli.toLowerCase(),
20
+ kind: input.routing?.runnerKind ?? runnerKindForCli(input.cli),
21
+ cli: input.cli,
22
+ ...(input.model === undefined ? {} : { model: input.model }),
23
+ },
24
+ ...(input.sessionId === undefined ? {} : { sessionId: input.sessionId }),
25
+ payload: input.payload ?? {},
26
+ };
27
+ }
28
+ export async function emitRuntimeEvent(emit, event) {
29
+ if (emit !== undefined) {
30
+ await emit(event);
31
+ }
32
+ }
@@ -6,6 +6,7 @@ import { acquireFileLock } from '../lib/lock.js';
6
6
  import { CORRELATION_REGISTERED_EVENT, CORRELATION_PRIMARY_CONFLICT_EVENT, parseRunnerArtifacts, parseRunnerResult, } from '../domain/schema.js';
7
7
  import { maxConfiguredRunnerTimeoutMs, resolveRunnerRouting } from '../domain/runner-routing.js';
8
8
  import { awaitingApprovalRunnerSentinel, stageLabelForStage } from '../domain/stages.js';
9
+ import { isMeaningfulRuntimeEvent } from '../domain/runtime-events.js';
9
10
  import { chooseAction as chooseWorkflowAction, entryStage as workflowEntryStage, isKnownWorkflowStage, workflowChangedBlockReason, workflowForProjection, workflowLabelForWorkflowName, workflowNameForProjection, } from '../domain/workflows.js';
10
11
  import { createEventEnvelope } from '../lib/event-log.js';
11
12
  import { branchNameForIssue } from '../domain/branch-naming.js';
@@ -1052,6 +1053,30 @@ export function createTickRunner(deps) {
1052
1053
  lifecycle,
1053
1054
  });
1054
1055
  }
1056
+ async function appendRuntimeEvent(event) {
1057
+ const timestamp = event.timestamp ?? deps.clock.now().toISOString();
1058
+ await deps.stateStore.updateRunRecordIf(runId, {
1059
+ expect: (record) => record.status === 'running' &&
1060
+ record.lease?.leaseId === lease.leaseId &&
1061
+ record.lease.ownerInstanceId === ownerInstanceId,
1062
+ update: (record) => {
1063
+ const runtimeEvents = record.runtimeEvents ?? [];
1064
+ const sequence = event.sequence ?? runtimeEvents.length;
1065
+ const normalizedEvent = {
1066
+ ...event,
1067
+ timestamp,
1068
+ sequence,
1069
+ };
1070
+ return {
1071
+ ...record,
1072
+ runtimeEvents: [...runtimeEvents, normalizedEvent],
1073
+ ...(isMeaningfulRuntimeEvent(normalizedEvent)
1074
+ ? { lastMeaningfulActivityAt: normalizedEvent.timestamp }
1075
+ : {}),
1076
+ };
1077
+ },
1078
+ });
1079
+ }
1055
1080
  const claimedAt = eventStampNow();
1056
1081
  const claimedEvent = createEventEnvelope({
1057
1082
  eventId: `${runId}-claimed`,
@@ -1201,6 +1226,7 @@ export function createTickRunner(deps) {
1201
1226
  }),
1202
1227
  });
1203
1228
  },
1229
+ onRuntimeEvent: appendRuntimeEvent,
1204
1230
  });
1205
1231
  clearInterval(leaseRenewalTimer);
1206
1232
  leaseRenewalTimer = undefined;
@@ -0,0 +1,36 @@
1
+ export const runtimeEventTypeValues = [
2
+ 'run.claimed',
3
+ 'run.started',
4
+ 'workspace.preparing',
5
+ 'workspace.ready',
6
+ 'agent.process.started',
7
+ 'agent.session.started',
8
+ 'agent.progress',
9
+ 'agent.tool.requested',
10
+ 'agent.approval.requested',
11
+ 'agent.input.required',
12
+ 'agent.usage.updated',
13
+ 'agent.turn.completed',
14
+ 'agent.process.exited',
15
+ 'run.completed',
16
+ 'run.failed',
17
+ 'run.stalled',
18
+ 'run.canceled',
19
+ ];
20
+ export function isMeaningfulRuntimeEvent(event) {
21
+ return (event.type === 'agent.progress' ||
22
+ event.type === 'agent.tool.requested' ||
23
+ event.type === 'agent.approval.requested' ||
24
+ event.type === 'agent.input.required' ||
25
+ event.type === 'agent.usage.updated' ||
26
+ event.type === 'agent.turn.completed');
27
+ }
28
+ export function runtimeEventPayload(input) {
29
+ return {
30
+ ...(input.message === undefined ? {} : { message: input.message }),
31
+ ...(input.raw === undefined ? {} : { raw: input.raw }),
32
+ ...(input.exitCode === undefined ? {} : { exitCode: input.exitCode }),
33
+ ...(input.timedOut === undefined ? {} : { timedOut: input.timedOut }),
34
+ ...(input.tokenUsage === undefined ? {} : { tokenUsage: input.tokenUsage }),
35
+ };
36
+ }
@@ -5,6 +5,7 @@ import { z } from 'zod';
5
5
  import { reservedCommandNames } from './custom-commands.js';
6
6
  import { runnerSentinelValues } from './stages.js';
7
7
  import { correlationProvenanceSchema, correlationRelationSchema, correlationRoleSchema, resourceUriSchema, } from './resource-uri.js';
8
+ import { runtimeEventTypeValues } from './runtime-events.js';
8
9
  import { alwaysManualIgnoredLabels } from './manual-labels.js';
9
10
  const isoTimestampSchema = z.string().datetime({ offset: true });
10
11
  const identifierSchema = z.string().min(1);
@@ -47,6 +48,21 @@ export const executionAttemptLifecycleValues = [
47
48
  export const executionOutcomeSchema = z.enum(executionOutcomeValues);
48
49
  export const workflowOutcomeSchema = z.enum(workflowOutcomeValues);
49
50
  export const executionAttemptLifecycleSchema = z.enum(executionAttemptLifecycleValues);
51
+ export const runtimeEventSchema = z.object({
52
+ type: z.enum(runtimeEventTypeValues),
53
+ runId: z.string(),
54
+ workItemId: z.string(),
55
+ runner: z.object({
56
+ name: z.string(),
57
+ kind: z.enum(['fake', 'claude', 'codex', 'cursor']),
58
+ cli: z.string(),
59
+ model: z.string().optional(),
60
+ }),
61
+ sessionId: z.string().optional(),
62
+ timestamp: isoTimestampSchema,
63
+ sequence: z.number().int().nonnegative(),
64
+ payload: z.record(z.string(), z.unknown()).default({}),
65
+ });
50
66
  export const defaultAgentIdentity = 'Wake';
51
67
  export const defaultSmokePrompt = `This is ${defaultAgentIdentity}, reply with "hi ${defaultAgentIdentity} only"`;
52
68
  const modelOverridesSchema = z
@@ -361,6 +377,8 @@ export const runRecordSchema = z.preprocess((input) => {
361
377
  workerProcessStartedAt: z.string().optional(),
362
378
  agentPid: z.number().int().positive().optional(),
363
379
  agentProcessStartedAt: z.string().optional(),
380
+ lastMeaningfulActivityAt: isoTimestampSchema.optional(),
381
+ runtimeEvents: z.array(runtimeEventSchema).optional(),
364
382
  tokenUsage: runTokenUsageSchema.optional(),
365
383
  metadata: z.record(z.string(), z.unknown()).optional(),
366
384
  }));
@@ -124,4 +124,4 @@ export function resolveWakeVersion(options = {}) {
124
124
  }
125
125
  return '0.1.0-dev';
126
126
  }
127
- export const wakeVersion = "gc00f4ed";
127
+ export const wakeVersion = "gee0e5b1";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atolis-hq/wake",
3
- "version": "0.2.44",
3
+ "version": "0.2.45",
4
4
  "description": "Local autonomous agent control plane for software development",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {