@zhixuan92/multi-model-agent-core 4.7.1 → 4.7.2
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/README.md +6 -5
- package/dist/bounded-execution/progress-events-subscriber.d.ts +3 -3
- package/dist/bounded-execution/progress-events-subscriber.d.ts.map +1 -1
- package/dist/bounded-execution/progress-events-subscriber.js +14 -4
- package/dist/bounded-execution/progress-events-subscriber.js.map +1 -1
- package/dist/bounded-execution/stall-watchdog.d.ts +4 -2
- package/dist/bounded-execution/stall-watchdog.d.ts.map +1 -1
- package/dist/bounded-execution/stall-watchdog.js +55 -31
- package/dist/bounded-execution/stall-watchdog.js.map +1 -1
- package/dist/events/envelope-bus.d.ts +22 -0
- package/dist/events/envelope-bus.d.ts.map +1 -0
- package/dist/events/envelope-bus.js +35 -0
- package/dist/events/envelope-bus.js.map +1 -0
- package/dist/events/log-writer.d.ts +24 -0
- package/dist/events/log-writer.d.ts.map +1 -0
- package/dist/events/log-writer.js +52 -0
- package/dist/events/log-writer.js.map +1 -0
- package/dist/events/plain-log-entry.d.ts +45 -0
- package/dist/events/plain-log-entry.d.ts.map +1 -0
- package/dist/events/plain-log-entry.js +45 -0
- package/dist/events/plain-log-entry.js.map +1 -0
- package/dist/events/task-envelope.d.ts +174 -0
- package/dist/events/task-envelope.d.ts.map +1 -0
- package/dist/events/task-envelope.js +152 -0
- package/dist/events/task-envelope.js.map +1 -0
- package/dist/events/telemetry-uploader.d.ts +24 -0
- package/dist/events/telemetry-uploader.d.ts.map +1 -0
- package/dist/events/telemetry-uploader.js +31 -0
- package/dist/events/telemetry-uploader.js.map +1 -0
- package/dist/events/to-wire-record.d.ts +42 -0
- package/dist/events/to-wire-record.d.ts.map +1 -0
- package/dist/events/to-wire-record.js +167 -0
- package/dist/events/to-wire-record.js.map +1 -0
- package/dist/events/{telemetry-types.d.ts → wire-schema.d.ts} +23 -36
- package/dist/events/wire-schema.d.ts.map +1 -0
- package/dist/events/{telemetry-types.js → wire-schema.js} +2 -9
- package/dist/events/wire-schema.js.map +1 -0
- package/dist/identity/{auth-token-store.d.ts → claude-oauth.d.ts} +1 -24
- package/dist/identity/claude-oauth.d.ts.map +1 -0
- package/dist/identity/claude-oauth.js +71 -0
- package/dist/identity/claude-oauth.js.map +1 -0
- package/dist/index.d.ts +9 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -7
- package/dist/index.js.map +1 -1
- package/dist/lifecycle/handlers/annotate-stage.d.ts.map +1 -1
- package/dist/lifecycle/handlers/annotate-stage.js +11 -5
- package/dist/lifecycle/handlers/annotate-stage.js.map +1 -1
- package/dist/lifecycle/handlers/rework-stage.js +2 -2
- package/dist/lifecycle/handlers/rework-stage.js.map +1 -1
- package/dist/lifecycle/handlers/terminal-handlers.d.ts +5 -4
- package/dist/lifecycle/handlers/terminal-handlers.d.ts.map +1 -1
- package/dist/lifecycle/handlers/terminal-handlers.js +34 -71
- package/dist/lifecycle/handlers/terminal-handlers.js.map +1 -1
- package/dist/lifecycle/lifecycle-context.d.ts +11 -5
- package/dist/lifecycle/lifecycle-context.d.ts.map +1 -1
- package/dist/lifecycle/lifecycle-driver.d.ts.map +1 -1
- package/dist/lifecycle/lifecycle-driver.js +96 -9
- package/dist/lifecycle/lifecycle-driver.js.map +1 -1
- package/dist/lifecycle/perform-implementation.js +2 -2
- package/dist/lifecycle/perform-implementation.js.map +1 -1
- package/dist/lifecycle/task-completion-summary.js +1 -1
- package/dist/lifecycle/task-completion-summary.js.map +1 -1
- package/dist/lifecycle/task-runner.d.ts +11 -6
- package/dist/lifecycle/task-runner.d.ts.map +1 -1
- package/dist/lifecycle/task-runner.js +2 -0
- package/dist/lifecycle/task-runner.js.map +1 -1
- package/dist/providers/claude-session.d.ts +1 -0
- package/dist/providers/claude-session.d.ts.map +1 -1
- package/dist/providers/claude-session.js +29 -27
- package/dist/providers/claude-session.js.map +1 -1
- package/dist/providers/claude.js +1 -1
- package/dist/providers/claude.js.map +1 -1
- package/dist/providers/codex-cli-session.d.ts +4 -2
- package/dist/providers/codex-cli-session.d.ts.map +1 -1
- package/dist/providers/codex-cli-session.js +47 -46
- package/dist/providers/codex-cli-session.js.map +1 -1
- package/dist/providers/runner-types.d.ts +3 -3
- package/dist/providers/runner-types.d.ts.map +1 -1
- package/dist/reporting/structured-report.d.ts +3 -3
- package/dist/stores/batch-registry.d.ts +37 -29
- package/dist/stores/batch-registry.d.ts.map +1 -1
- package/dist/stores/batch-registry.js +18 -23
- package/dist/stores/batch-registry.js.map +1 -1
- package/dist/tools/audit/schema.d.ts +1 -1
- package/dist/tools/review/schema.d.ts +1 -1
- package/dist/transport/http-listener.d.ts +1 -1
- package/dist/types/enums.d.ts +16 -16
- package/dist/types/run-result.d.ts +3 -0
- package/dist/types/run-result.d.ts.map +1 -1
- package/package.json +21 -29
- package/dist/events/caller-response-channel.d.ts +0 -17
- package/dist/events/caller-response-channel.d.ts.map +0 -1
- package/dist/events/caller-response-channel.js +0 -10
- package/dist/events/caller-response-channel.js.map +0 -1
- package/dist/events/clamp.d.ts +0 -13
- package/dist/events/clamp.d.ts.map +0 -1
- package/dist/events/clamp.js +0 -24
- package/dist/events/clamp.js.map +0 -1
- package/dist/events/cloud-events.d.ts +0 -108
- package/dist/events/cloud-events.d.ts.map +0 -1
- package/dist/events/cloud-events.js +0 -58
- package/dist/events/cloud-events.js.map +0 -1
- package/dist/events/concern-classifier.d.ts +0 -9
- package/dist/events/concern-classifier.d.ts.map +0 -1
- package/dist/events/concern-classifier.js +0 -26
- package/dist/events/concern-classifier.js.map +0 -1
- package/dist/events/diagnostics-types.d.ts +0 -65
- package/dist/events/diagnostics-types.d.ts.map +0 -1
- package/dist/events/diagnostics-types.js +0 -2
- package/dist/events/diagnostics-types.js.map +0 -1
- package/dist/events/event-base.d.ts +0 -14
- package/dist/events/event-base.d.ts.map +0 -1
- package/dist/events/event-base.js +0 -24
- package/dist/events/event-base.js.map +0 -1
- package/dist/events/event-builder.d.ts +0 -55
- package/dist/events/event-builder.d.ts.map +0 -1
- package/dist/events/event-builder.js +0 -557
- package/dist/events/event-builder.js.map +0 -1
- package/dist/events/event-emitter.d.ts +0 -31
- package/dist/events/event-emitter.d.ts.map +0 -1
- package/dist/events/event-emitter.js +0 -63
- package/dist/events/event-emitter.js.map +0 -1
- package/dist/events/http-server-log.d.ts +0 -63
- package/dist/events/http-server-log.d.ts.map +0 -1
- package/dist/events/http-server-log.js +0 -188
- package/dist/events/http-server-log.js.map +0 -1
- package/dist/events/index.d.ts +0 -6
- package/dist/events/index.d.ts.map +0 -1
- package/dist/events/index.js +0 -7
- package/dist/events/index.js.map +0 -1
- package/dist/events/local-log-sink.d.ts +0 -10
- package/dist/events/local-log-sink.d.ts.map +0 -1
- package/dist/events/local-log-sink.js +0 -11
- package/dist/events/local-log-sink.js.map +0 -1
- package/dist/events/normalize.d.ts +0 -18
- package/dist/events/normalize.d.ts.map +0 -1
- package/dist/events/normalize.js +0 -18
- package/dist/events/normalize.js.map +0 -1
- package/dist/events/observability-events.d.ts +0 -1324
- package/dist/events/observability-events.d.ts.map +0 -1
- package/dist/events/observability-events.js +0 -446
- package/dist/events/observability-events.js.map +0 -1
- package/dist/events/privacy-filter.d.ts +0 -2
- package/dist/events/privacy-filter.d.ts.map +0 -1
- package/dist/events/privacy-filter.js +0 -10
- package/dist/events/privacy-filter.js.map +0 -1
- package/dist/events/request-spill.d.ts +0 -16
- package/dist/events/request-spill.d.ts.map +0 -1
- package/dist/events/request-spill.js +0 -23
- package/dist/events/request-spill.js.map +0 -1
- package/dist/events/telemetry-channel.d.ts +0 -9
- package/dist/events/telemetry-channel.d.ts.map +0 -1
- package/dist/events/telemetry-channel.js +0 -16
- package/dist/events/telemetry-channel.js.map +0 -1
- package/dist/events/telemetry-sink.d.ts +0 -12
- package/dist/events/telemetry-sink.d.ts.map +0 -1
- package/dist/events/telemetry-sink.js +0 -24
- package/dist/events/telemetry-sink.js.map +0 -1
- package/dist/events/telemetry-types.d.ts.map +0 -1
- package/dist/events/telemetry-types.js.map +0 -1
- package/dist/events/verbose-line.d.ts +0 -13
- package/dist/events/verbose-line.d.ts.map +0 -1
- package/dist/events/verbose-line.js +0 -99
- package/dist/events/verbose-line.js.map +0 -1
- package/dist/events/verbose-log-channel.d.ts +0 -29
- package/dist/events/verbose-log-channel.d.ts.map +0 -1
- package/dist/events/verbose-log-channel.js +0 -63
- package/dist/events/verbose-log-channel.js.map +0 -1
- package/dist/identity/auth-token-store.d.ts.map +0 -1
- package/dist/identity/auth-token-store.js +0 -136
- package/dist/identity/auth-token-store.js.map +0 -1
- package/dist/identity/cwd-validator.d.ts +0 -6
- package/dist/identity/cwd-validator.d.ts.map +0 -1
- package/dist/identity/cwd-validator.js +0 -28
- package/dist/identity/cwd-validator.js.map +0 -1
- package/dist/identity/host-allowlist.d.ts +0 -6
- package/dist/identity/host-allowlist.d.ts.map +0 -1
- package/dist/identity/host-allowlist.js +0 -11
- package/dist/identity/host-allowlist.js.map +0 -1
- package/dist/identity/index.d.ts +0 -6
- package/dist/identity/index.d.ts.map +0 -1
- package/dist/identity/index.js +0 -7
- package/dist/identity/index.js.map +0 -1
- package/dist/identity/ssrf-guard.d.ts +0 -4
- package/dist/identity/ssrf-guard.d.ts.map +0 -1
- package/dist/identity/ssrf-guard.js +0 -19
- package/dist/identity/ssrf-guard.js.map +0 -1
package/README.md
CHANGED
|
@@ -228,12 +228,13 @@ mmagent logs --follow --batch=<id> # tail + filter
|
|
|
228
228
|
|
|
229
229
|
As of 3.4.0 every task-execution event the worker emits to the verbose stderr stream is also written to the JSONL log via a single `emit(TaskEvent)` writer — schema parity across both sinks. Crash/disconnect events (`startup`, `request_start`, `request_complete`, `shutdown`, `error`) are written unconditionally; per-task events (`heartbeat`, `stage_change`, `tool_call`, `turn_complete`, etc.) flow through the same writer.
|
|
230
230
|
|
|
231
|
-
## What's new in 4.7.
|
|
231
|
+
## What's new in 4.7.2
|
|
232
232
|
|
|
233
|
-
- **
|
|
234
|
-
- **
|
|
235
|
-
- **
|
|
236
|
-
- **From 4.7.
|
|
233
|
+
- **Events/lifecycle pipeline rewrite.** The legacy `event-emitter` + sinks fan-out is replaced by `TaskEnvelope` + `EnvelopeBus` + `LogWriter` + `TelemetryUploader`. Lifecycle handlers (`stall-watchdog`, `annotate-stage`, `lifecycle-driver`, `heartbeat`, provider sessions, terminal handler) now mutate the envelope directly; the recorder only seals on terminal. `BatchEntry` is slimmed to `taskEnvelopes` plus required infrastructure.
|
|
234
|
+
- **New subpath exports.** `./events/task-envelope`, `./events/envelope-bus`, `./events/log-writer`, `./events/telemetry-uploader`, `./events/wire-schema`. About 20 deleted files (old `event-emitter`, every sink class, `telemetry-channel`, `http-server-log`, dual schemas) are gone.
|
|
235
|
+
- **identity/ slimmed to two files.** `claude-oauth.ts` (was `auth-token-store.ts`, now Claude-OAuth-only — Codex auth is handled by the `codex` CLI subprocess per `providers/codex.ts:9`) and `secret-redactor.ts`. The dormant `cwd-validator.ts`, `host-allowlist.ts`, `ssrf-guard.ts`, `index.ts` are deleted; `getClaudeAuth`/`getCodexAuth`/`ClaudeAuth`/`CodexAuth`/`claudeOAuth`/`codexOAuth` exports removed. The live `getClaudeOAuth()` body is byte-for-byte unchanged; six-case keychain test coverage added.
|
|
236
|
+
- **From 4.7.1:** polling headline `(N/M)` stage counter and live `read/write/tool calls` counters update during a stage; `ActivityTracker.recordFileWrite()` added.
|
|
237
|
+
- **From 4.7.0 (BREAKING):** USD cost caps removed end-to-end — `maxCostUSD`, `cost_cap`/`cost_exceeded`/`cost_check`, `pricingSchema` all deleted; `outputTargets` contract on `/delegate`/`/execute-plan`; `packages/core/src/escalation/` removed.
|
|
237
238
|
|
|
238
239
|
Full history: [CHANGELOG](https://github.com/zhixuan312/multi-model-agent/blob/master/CHANGELOG.md).
|
|
239
240
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { EnvelopeBus } from '../events/envelope-bus.js';
|
|
2
2
|
import type { ActivityTracker } from './activity-tracker.js';
|
|
3
3
|
/**
|
|
4
4
|
* Bridges runner-emitted bus events to ActivityTracker progress counters
|
|
@@ -6,7 +6,7 @@ import type { ActivityTracker } from './activity-tracker.js';
|
|
|
6
6
|
* of jumping from 0/0/0 to the final value only at stage transition.
|
|
7
7
|
*
|
|
8
8
|
* Pattern mirrors stall-watchdog.ts:
|
|
9
|
-
* - Listens on
|
|
9
|
+
* - Listens on EnvelopeBus for runner progress events.
|
|
10
10
|
* - Filters by batchId + taskIndex (bus is process-wide; without filter
|
|
11
11
|
* every task's events would increment every other task's counters).
|
|
12
12
|
* - Calls tracker.recordFileRead / recordFileWrite / recordToolCall /
|
|
@@ -32,7 +32,7 @@ import type { ActivityTracker } from './activity-tracker.js';
|
|
|
32
32
|
* end-of-stage updateProgress() call still snaps to the correct totals.
|
|
33
33
|
*/
|
|
34
34
|
export interface ProgressEventsSubscriberContext {
|
|
35
|
-
bus:
|
|
35
|
+
bus: EnvelopeBus;
|
|
36
36
|
tracker: ActivityTracker;
|
|
37
37
|
batchId?: string;
|
|
38
38
|
taskIndex?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"progress-events-subscriber.d.ts","sourceRoot":"","sources":["../../src/bounded-execution/progress-events-subscriber.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"progress-events-subscriber.d.ts","sourceRoot":"","sources":["../../src/bounded-execution/progress-events-subscriber.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,WAAW,+BAA+B;IAC9C,GAAG,EAAE,WAAW,CAAC;IACjB,OAAO,EAAE,eAAe,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAKD,wBAAgB,6BAA6B,CAC3C,GAAG,EAAE,+BAA+B,GACnC,MAAM,IAAI,CAyDZ"}
|
|
@@ -45,9 +45,19 @@ export function startProgressEventsSubscriber(ctx) {
|
|
|
45
45
|
return;
|
|
46
46
|
}
|
|
47
47
|
};
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
// EnvelopeBus replaces the old EventEmitter on/off API with subscribe().
|
|
49
|
+
// The subscriber receives BusMessage; only envelope snapshots are relevant
|
|
50
|
+
// here, so map them into the handler's old event shape on the fly.
|
|
51
|
+
const sub = ctx.bus.subscribe({
|
|
52
|
+
name: 'progress-events-subscriber',
|
|
53
|
+
receive(msg) {
|
|
54
|
+
if (msg.type === 'envelope') {
|
|
55
|
+
// Synthesize a coarse "envelope_updated" event for the handler so it
|
|
56
|
+
// still has a reason to refresh its progress signal.
|
|
57
|
+
handler({ event: 'envelope_updated', reason: msg.reason });
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
return () => { sub(); };
|
|
52
62
|
}
|
|
53
63
|
//# sourceMappingURL=progress-events-subscriber.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"progress-events-subscriber.js","sourceRoot":"","sources":["../../src/bounded-execution/progress-events-subscriber.ts"],"names":[],"mappings":"AAyCA,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;AACrC,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,cAAc,CAAC,CAAC,CAAC;AAE5E,MAAM,UAAU,6BAA6B,CAC3C,GAAoC;IAEpC,MAAM,OAAO,GAAG,CAAC,KAA8B,EAAE,EAAE;QACjD,MAAM,SAAS,GAAG,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QACrE,IAAI,CAAC,SAAS;YAAE,OAAO;QAEvB,6DAA6D;QAC7D,IAAI,GAAG,CAAC,OAAO,KAAK,SAAS,IAAI,KAAK,CAAC,SAAS,CAAC,KAAK,GAAG,CAAC,OAAO;YAAE,OAAO;QAC1E,IAAI,GAAG,CAAC,SAAS,KAAK,SAAS,IAAI,KAAK,CAAC,WAAW,CAAC,KAAK,GAAG,CAAC,SAAS;YAAE,OAAO;QAEhF,QAAQ,SAAS,EAAE,CAAC;YAClB,KAAK,kBAAkB,CAAC,CAAC,CAAC;gBACxB,MAAM,IAAI,GAAG,OAAO,KAAK,CAAC,MAAM,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpE,GAAG,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;gBAC7B,IAAI,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;oBAAE,GAAG,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;qBAClD,IAAI,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC;oBAAE,GAAG,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC;gBAC9D,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;gBAC9B,OAAO;YACT,CAAC;YACD,KAAK,yBAAyB,CAAC,CAAC,CAAC;gBAC/B,GAAG,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;gBAC7B,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;gBAC9B,OAAO;YACT,CAAC;YACD,KAAK,mBAAmB,CAAC,CAAC,CAAC;gBACzB,GAAG,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC;gBAC9B,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;gBAC9B,OAAO;YACT,CAAC;YACD,KAAK,sBAAsB,CAAC;YAC5B,KAAK,qBAAqB,CAAC,CAAC,CAAC;gBAC3B,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;gBAC9B,OAAO;YACT,CAAC;YACD,KAAK,qBAAqB,CAAC;YAC3B,KAAK,oBAAoB,CAAC,CAAC,CAAC;gBAC1B,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;gBAC7B,OAAO;YACT,CAAC;YACD;gBACE,OAAO;QACX,CAAC;IACH,CAAC,CAAC;IAEF,GAAG,CAAC,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"progress-events-subscriber.js","sourceRoot":"","sources":["../../src/bounded-execution/progress-events-subscriber.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { EnvelopeBus } from '../events/envelope-bus.js';
|
|
2
|
+
import type { TaskEnvelopeStore } from '../events/task-envelope.js';
|
|
2
3
|
export interface StallWatchdogContext {
|
|
3
4
|
stall: {
|
|
4
5
|
controller: AbortController;
|
|
@@ -8,7 +9,8 @@ export interface StallWatchdogContext {
|
|
|
8
9
|
timing: {
|
|
9
10
|
stallTimeoutMs: number;
|
|
10
11
|
};
|
|
11
|
-
bus?:
|
|
12
|
+
bus?: EnvelopeBus;
|
|
13
|
+
envelope?: TaskEnvelopeStore;
|
|
12
14
|
batchId?: string;
|
|
13
15
|
taskIndex?: number;
|
|
14
16
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stall-watchdog.d.ts","sourceRoot":"","sources":["../../src/bounded-execution/stall-watchdog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"stall-watchdog.d.ts","sourceRoot":"","sources":["../../src/bounded-execution/stall-watchdog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAsCpE,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE;QAAE,UAAU,EAAE,eAAe,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;IAC9E,MAAM,EAAE;QAAE,cAAc,EAAE,MAAM,CAAA;KAAE,CAAC;IACnC,GAAG,CAAC,EAAE,WAAW,CAAC;IAClB,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,oBAAoB,GAAG,MAAM,IAAI,CA8ExE"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Wires the long-declared-but-previously-inert orchestrator stall watchdog.
|
|
3
3
|
*
|
|
4
|
-
* Listens on the
|
|
4
|
+
* Listens on the EnvelopeBus for runner progress events; resets
|
|
5
5
|
* `lastEventAtMs` on each one. A polling timer fires
|
|
6
6
|
* `controller.abort()` when no resetting event has arrived for longer
|
|
7
7
|
* than `stallTimeoutMs` — i.e. the runner is hung at the network layer
|
|
@@ -33,27 +33,33 @@ const RESET_EVENTS = new Set([
|
|
|
33
33
|
'claude_tool_call',
|
|
34
34
|
]);
|
|
35
35
|
export function startStallWatchdog(ctx) {
|
|
36
|
-
ctx.
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
36
|
+
const taskId = ctx.batchId ? `${ctx.batchId}:${ctx.taskIndex ?? 0}` : '';
|
|
37
|
+
const bus = ctx.bus;
|
|
38
|
+
if (bus?.emitPlainEntry) {
|
|
39
|
+
// EnvelopeBus — new API
|
|
40
|
+
bus.emitPlainEntry({
|
|
41
|
+
ts: new Date().toISOString(),
|
|
42
|
+
kind: 'stall_watchdog_armed',
|
|
43
|
+
fields: {
|
|
44
|
+
task_id: taskId,
|
|
45
|
+
idle_threshold_ms: ctx.timing.stallTimeoutMs,
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
else if (bus?.emit) {
|
|
50
|
+
// EnvelopeBus — old API (fallback for compatibility)
|
|
51
|
+
bus.emit({
|
|
52
|
+
event: 'stall_watchdog_armed',
|
|
53
|
+
ts: new Date().toISOString(),
|
|
54
|
+
batchId: ctx.batchId,
|
|
55
|
+
taskIndex: ctx.taskIndex,
|
|
56
|
+
stallTimeoutMs: ctx.timing.stallTimeoutMs,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
// Note: EnvelopeBus emits envelope snapshots and plain entries; we no longer
|
|
60
|
+
// subscribe to provider events for stall-watchdog detection. Provider event
|
|
61
|
+
// filtering will be handled by heartbeat tracking in execution-context.ts.
|
|
62
|
+
// This handler is a no-op for the new bus design.
|
|
57
63
|
// Poll interval: fine enough to fire promptly, coarse enough to avoid
|
|
58
64
|
// burning CPU on idle batches. Clamped to [1s, 5s].
|
|
59
65
|
const pollIntervalMs = Math.min(5_000, Math.max(1_000, Math.floor(ctx.timing.stallTimeoutMs / 60)));
|
|
@@ -68,19 +74,37 @@ export function startStallWatchdog(ctx) {
|
|
|
68
74
|
if (idleMs >= ctx.timing.stallTimeoutMs) {
|
|
69
75
|
ctx.stall.fired = true;
|
|
70
76
|
ctx.stall.controller.abort();
|
|
71
|
-
ctx.
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
77
|
+
const taskId = ctx.batchId ? `${ctx.batchId}:${ctx.taskIndex ?? 0}` : '';
|
|
78
|
+
const bus = ctx.bus;
|
|
79
|
+
if (bus?.emitPlainEntry) {
|
|
80
|
+
// EnvelopeBus — new API
|
|
81
|
+
bus.emitPlainEntry({
|
|
82
|
+
ts: new Date().toISOString(),
|
|
83
|
+
kind: 'stall_watchdog_fired',
|
|
84
|
+
fields: {
|
|
85
|
+
task_id: taskId,
|
|
86
|
+
idle_ms_observed: idleMs,
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
else if (bus?.emit) {
|
|
91
|
+
// EnvelopeBus — old API (fallback for compatibility)
|
|
92
|
+
bus.emit({
|
|
93
|
+
event: 'stall_watchdog_fired',
|
|
94
|
+
ts: new Date().toISOString(),
|
|
95
|
+
batchId: ctx.batchId,
|
|
96
|
+
taskIndex: ctx.taskIndex,
|
|
97
|
+
idleMs,
|
|
98
|
+
stallTimeoutMs: ctx.timing.stallTimeoutMs,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
if (ctx.envelope) {
|
|
102
|
+
ctx.envelope.recordStall({ atMs: Date.now(), idleMs });
|
|
103
|
+
}
|
|
79
104
|
}
|
|
80
105
|
}, pollIntervalMs);
|
|
81
106
|
return () => {
|
|
82
107
|
clearInterval(interval);
|
|
83
|
-
ctx.bus?.off(busHandler);
|
|
84
108
|
};
|
|
85
109
|
}
|
|
86
110
|
//# sourceMappingURL=stall-watchdog.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stall-watchdog.js","sourceRoot":"","sources":["../../src/bounded-execution/stall-watchdog.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"stall-watchdog.js","sourceRoot":"","sources":["../../src/bounded-execution/stall-watchdog.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { TaskEnvelope } from './task-envelope.js';
|
|
2
|
+
import type { PlainLogEntry } from './plain-log-entry.js';
|
|
3
|
+
export type BusMessage = {
|
|
4
|
+
type: 'envelope';
|
|
5
|
+
envelope: TaskEnvelope;
|
|
6
|
+
reason: string;
|
|
7
|
+
} | {
|
|
8
|
+
type: 'plain';
|
|
9
|
+
entry: PlainLogEntry;
|
|
10
|
+
};
|
|
11
|
+
export interface Subscriber {
|
|
12
|
+
readonly name: string;
|
|
13
|
+
receive(msg: BusMessage): void;
|
|
14
|
+
}
|
|
15
|
+
export declare class EnvelopeBus {
|
|
16
|
+
private subs;
|
|
17
|
+
subscribe(s: Subscriber): () => void;
|
|
18
|
+
unsubscribe(s: Subscriber): void;
|
|
19
|
+
emitEnvelopeSnapshot(envelope: TaskEnvelope, reason: string): void;
|
|
20
|
+
emitPlainEntry(entry: PlainLogEntry): void;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=envelope-bus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envelope-bus.d.ts","sourceRoot":"","sources":["../../src/events/envelope-bus.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC5D;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,aAAa,CAAA;CAAE,CAAC;AAE5C,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI,CAAC;CAChC;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,IAAI,CAAoB;IAEhC,SAAS,CAAC,CAAC,EAAE,UAAU,GAAG,MAAM,IAAI;IAKpC,WAAW,CAAC,CAAC,EAAE,UAAU,GAAG,IAAI;IAKhC,oBAAoB,CAAC,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IASlE,cAAc,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;CAQ3C"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export class EnvelopeBus {
|
|
2
|
+
subs = [];
|
|
3
|
+
subscribe(s) {
|
|
4
|
+
this.subs.push(s);
|
|
5
|
+
return () => this.unsubscribe(s);
|
|
6
|
+
}
|
|
7
|
+
unsubscribe(s) {
|
|
8
|
+
const i = this.subs.indexOf(s);
|
|
9
|
+
if (i !== -1)
|
|
10
|
+
this.subs.splice(i, 1);
|
|
11
|
+
}
|
|
12
|
+
emitEnvelopeSnapshot(envelope, reason) {
|
|
13
|
+
const msg = { type: 'envelope', envelope, reason };
|
|
14
|
+
for (const s of this.subs) {
|
|
15
|
+
try {
|
|
16
|
+
s.receive(msg);
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
process.stderr.write(`[mmagent] bus_subscriber_error sub=${s.name} reason=${reason} err=${err.message}\n`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
emitPlainEntry(entry) {
|
|
24
|
+
const msg = { type: 'plain', entry };
|
|
25
|
+
for (const s of this.subs) {
|
|
26
|
+
try {
|
|
27
|
+
s.receive(msg);
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
process.stderr.write(`[mmagent] bus_subscriber_error sub=${s.name} kind=${entry.kind} err=${err.message}\n`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=envelope-bus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envelope-bus.js","sourceRoot":"","sources":["../../src/events/envelope-bus.ts"],"names":[],"mappings":"AAaA,MAAM,OAAO,WAAW;IACd,IAAI,GAAiB,EAAE,CAAC;IAEhC,SAAS,CAAC,CAAa;QACrB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IACnC,CAAC;IAED,WAAW,CAAC,CAAa;QACvB,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAC/B,IAAI,CAAC,KAAK,CAAC,CAAC;YAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACvC,CAAC;IAED,oBAAoB,CAAC,QAAsB,EAAE,MAAc;QACzD,MAAM,GAAG,GAAe,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;QAC/D,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YAC1B,IAAI,CAAC;gBAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAAC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACnC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC,IAAI,WAAW,MAAM,QAAS,GAAa,CAAC,OAAO,IAAI,CAAC,CAAC;YACxH,CAAC;QACH,CAAC;IACH,CAAC;IAED,cAAc,CAAC,KAAoB;QACjC,MAAM,GAAG,GAAe,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QACjD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YAC1B,IAAI,CAAC;gBAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAAC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACnC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC,IAAI,SAAS,KAAK,CAAC,IAAI,QAAS,GAAa,CAAC,OAAO,IAAI,CAAC,CAAC;YAC1H,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Subscriber, BusMessage } from './envelope-bus.js';
|
|
2
|
+
export interface LogWriterOpts {
|
|
3
|
+
diagnosticsLog: boolean;
|
|
4
|
+
logDir?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare class LogWriter implements Subscriber {
|
|
7
|
+
private opts;
|
|
8
|
+
readonly name = "log-writer";
|
|
9
|
+
private writer;
|
|
10
|
+
private requestSpillDir;
|
|
11
|
+
constructor(opts: LogWriterOpts);
|
|
12
|
+
receive(msg: BusMessage): void;
|
|
13
|
+
/** Spill an oversized request body to disk and return the path. */
|
|
14
|
+
spillRequestBody(input: {
|
|
15
|
+
batchId: string;
|
|
16
|
+
body: unknown;
|
|
17
|
+
}): Promise<{
|
|
18
|
+
path: string;
|
|
19
|
+
bytes: number;
|
|
20
|
+
}>;
|
|
21
|
+
inlineBodyLimit(): number;
|
|
22
|
+
private serialize;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=log-writer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-writer.d.ts","sourceRoot":"","sources":["../../src/events/log-writer.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAMhE,MAAM,WAAW,aAAa;IAC5B,cAAc,EAAE,OAAO,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,SAAU,YAAW,UAAU;IAK9B,OAAO,CAAC,IAAI;IAJxB,QAAQ,CAAC,IAAI,gBAAgB;IAC7B,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,eAAe,CAAS;gBAEZ,IAAI,EAAE,aAAa;IAMvC,OAAO,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI;IAa9B,mEAAmE;IAC7D,gBAAgB,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAQ3G,eAAe,IAAI,MAAM;IAEzB,OAAO,CAAC,SAAS;CAIlB"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// packages/core/src/events/log-writer.ts
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { promises as fsp } from 'node:fs';
|
|
5
|
+
import { JsonlWriter } from './jsonl-writer.js';
|
|
6
|
+
import { redactSecrets } from '../identity/secret-redactor.js';
|
|
7
|
+
const INLINE_BODY_LIMIT_BYTES = 16_384;
|
|
8
|
+
export class LogWriter {
|
|
9
|
+
opts;
|
|
10
|
+
name = 'log-writer';
|
|
11
|
+
writer = null;
|
|
12
|
+
requestSpillDir;
|
|
13
|
+
constructor(opts) {
|
|
14
|
+
this.opts = opts;
|
|
15
|
+
const baseDir = opts.logDir ?? join(homedir(), '.multi-model', 'logs');
|
|
16
|
+
if (opts.diagnosticsLog)
|
|
17
|
+
this.writer = new JsonlWriter({ dir: baseDir });
|
|
18
|
+
this.requestSpillDir = join(baseDir, 'requests');
|
|
19
|
+
}
|
|
20
|
+
receive(msg) {
|
|
21
|
+
const record = this.serialize(msg);
|
|
22
|
+
// redactSecrets is a recursive walker that returns the redacted value at the same shape.
|
|
23
|
+
const redactedRecord = redactSecrets(record);
|
|
24
|
+
if (this.writer) {
|
|
25
|
+
try {
|
|
26
|
+
this.writer.writeLine(redactedRecord);
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
process.stderr.write(`[mmagent] log_writer_error: ${err.message}\n`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
process.stderr.write(JSON.stringify(redactedRecord) + '\n');
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/** Spill an oversized request body to disk and return the path. */
|
|
37
|
+
async spillRequestBody(input) {
|
|
38
|
+
await fsp.mkdir(this.requestSpillDir, { recursive: true, mode: 0o700 });
|
|
39
|
+
const path = join(this.requestSpillDir, `${input.batchId}.json`);
|
|
40
|
+
const buf = Buffer.from(JSON.stringify(input.body), 'utf8');
|
|
41
|
+
await fsp.writeFile(path, buf, { mode: 0o600, flag: 'wx' }).catch(err => { if (err.code !== 'EEXIST')
|
|
42
|
+
throw err; });
|
|
43
|
+
return { path, bytes: buf.byteLength };
|
|
44
|
+
}
|
|
45
|
+
inlineBodyLimit() { return INLINE_BODY_LIMIT_BYTES; }
|
|
46
|
+
serialize(msg) {
|
|
47
|
+
if (msg.type === 'envelope')
|
|
48
|
+
return { ts: new Date().toISOString(), kind: 'envelope_snapshot', reason: msg.reason, envelope: msg.envelope };
|
|
49
|
+
return { ts: msg.entry.ts, kind: msg.entry.kind, fields: msg.entry.fields };
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=log-writer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-writer.js","sourceRoot":"","sources":["../../src/events/log-writer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const PlainLogKindEnum: z.ZodEnum<{
|
|
3
|
+
server_started: "server_started";
|
|
4
|
+
server_stopped: "server_stopped";
|
|
5
|
+
batch_created: "batch_created";
|
|
6
|
+
request_received: "request_received";
|
|
7
|
+
request_spilled: "request_spilled";
|
|
8
|
+
batch_completed: "batch_completed";
|
|
9
|
+
batch_failed: "batch_failed";
|
|
10
|
+
project_evicted: "project_evicted";
|
|
11
|
+
stall_watchdog_armed: "stall_watchdog_armed";
|
|
12
|
+
stall_watchdog_fired: "stall_watchdog_fired";
|
|
13
|
+
provider_event: "provider_event";
|
|
14
|
+
server_error: "server_error";
|
|
15
|
+
}>;
|
|
16
|
+
export type PlainLogKind = z.infer<typeof PlainLogKindEnum>;
|
|
17
|
+
export declare const PlainLogEntrySchema: z.ZodObject<{
|
|
18
|
+
ts: z.ZodString;
|
|
19
|
+
kind: z.ZodEnum<{
|
|
20
|
+
server_started: "server_started";
|
|
21
|
+
server_stopped: "server_stopped";
|
|
22
|
+
batch_created: "batch_created";
|
|
23
|
+
request_received: "request_received";
|
|
24
|
+
request_spilled: "request_spilled";
|
|
25
|
+
batch_completed: "batch_completed";
|
|
26
|
+
batch_failed: "batch_failed";
|
|
27
|
+
project_evicted: "project_evicted";
|
|
28
|
+
stall_watchdog_armed: "stall_watchdog_armed";
|
|
29
|
+
stall_watchdog_fired: "stall_watchdog_fired";
|
|
30
|
+
provider_event: "provider_event";
|
|
31
|
+
server_error: "server_error";
|
|
32
|
+
}>;
|
|
33
|
+
fields: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>>;
|
|
34
|
+
}, z.core.$strict>;
|
|
35
|
+
export type PlainLogEntry = z.infer<typeof PlainLogEntrySchema>;
|
|
36
|
+
export declare const PROVIDER_EVENT_NAMES: readonly ["claude_session_starting", "claude_turn_started", "claude_error", "claude_turn_completed", "claude_text_emission", "claude_tool_call", "claude_session_closed", "codex_subprocess_starting", "codex_spawn_failed", "codex_subprocess_started", "codex_subprocess_exited", "codex_thread_started", "codex_turn_started", "codex_command_started", "codex_command_completed", "codex_turn_completed", "codex_turn_failed", "codex_error", "codex_agent_message", "codex_file_change"];
|
|
37
|
+
export type ProviderEventName = (typeof PROVIDER_EVENT_NAMES)[number];
|
|
38
|
+
/** Per-event field shapes are NOT pre-declared — `mapProviderEventToPlainEntry`
|
|
39
|
+
* passes through all primitive fields from the raw event payload (object-valued
|
|
40
|
+
* fields become `<name>_json`). The names list above is the closed schema; field
|
|
41
|
+
* shapes are discovered from the provider files at migration time (T11) and
|
|
42
|
+
* asserted by tests/events/provider-event-mapping.test.ts.
|
|
43
|
+
*/
|
|
44
|
+
export declare function mapProviderEventToPlainEntry(provider: 'claude' | 'codex', event: ProviderEventName, rawFields: Record<string, unknown>): PlainLogEntry;
|
|
45
|
+
//# sourceMappingURL=plain-log-entry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plain-log-entry.d.ts","sourceRoot":"","sources":["../../src/events/plain-log-entry.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;EAQ3B,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAG5D,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;kBAIrB,CAAC;AACZ,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,eAAO,MAAM,oBAAoB,+dAQvB,CAAC;AACX,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtE;;;;;GAKG;AAEH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,QAAQ,GAAG,OAAO,EAC5B,KAAK,EAAE,iBAAiB,EACxB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,aAAa,CAUf"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// packages/core/src/events/plain-log-entry.ts
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
export const PlainLogKindEnum = z.enum([
|
|
4
|
+
'server_started', 'server_stopped',
|
|
5
|
+
'batch_created', 'request_received', 'request_spilled',
|
|
6
|
+
'batch_completed', 'batch_failed',
|
|
7
|
+
'project_evicted',
|
|
8
|
+
'stall_watchdog_armed', 'stall_watchdog_fired',
|
|
9
|
+
'provider_event',
|
|
10
|
+
'server_error',
|
|
11
|
+
]);
|
|
12
|
+
const FieldValue = z.union([z.string(), z.number(), z.boolean(), z.null()]);
|
|
13
|
+
export const PlainLogEntrySchema = z.object({
|
|
14
|
+
ts: z.string().datetime({ offset: true }),
|
|
15
|
+
kind: PlainLogKindEnum,
|
|
16
|
+
fields: z.record(z.string(), FieldValue),
|
|
17
|
+
}).strict();
|
|
18
|
+
export const PROVIDER_EVENT_NAMES = [
|
|
19
|
+
// Claude (7)
|
|
20
|
+
'claude_session_starting', 'claude_turn_started', 'claude_error',
|
|
21
|
+
'claude_turn_completed', 'claude_text_emission', 'claude_tool_call', 'claude_session_closed',
|
|
22
|
+
// Codex (13)
|
|
23
|
+
'codex_subprocess_starting', 'codex_spawn_failed', 'codex_subprocess_started', 'codex_subprocess_exited',
|
|
24
|
+
'codex_thread_started', 'codex_turn_started', 'codex_command_started', 'codex_command_completed',
|
|
25
|
+
'codex_turn_completed', 'codex_turn_failed', 'codex_error', 'codex_agent_message', 'codex_file_change',
|
|
26
|
+
];
|
|
27
|
+
/** Per-event field shapes are NOT pre-declared — `mapProviderEventToPlainEntry`
|
|
28
|
+
* passes through all primitive fields from the raw event payload (object-valued
|
|
29
|
+
* fields become `<name>_json`). The names list above is the closed schema; field
|
|
30
|
+
* shapes are discovered from the provider files at migration time (T11) and
|
|
31
|
+
* asserted by tests/events/provider-event-mapping.test.ts.
|
|
32
|
+
*/
|
|
33
|
+
export function mapProviderEventToPlainEntry(provider, event, rawFields) {
|
|
34
|
+
const fields = { provider, event };
|
|
35
|
+
for (const [k, v] of Object.entries(rawFields)) {
|
|
36
|
+
if (v === null || typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean') {
|
|
37
|
+
fields[k] = v;
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
fields[`${k}_json`] = JSON.stringify(v);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return { ts: new Date().toISOString(), kind: 'provider_event', fields };
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=plain-log-entry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plain-log-entry.js","sourceRoot":"","sources":["../../src/events/plain-log-entry.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,IAAI,CAAC;IACrC,gBAAgB,EAAC,gBAAgB;IACjC,eAAe,EAAC,kBAAkB,EAAC,iBAAiB;IACpD,iBAAiB,EAAC,cAAc;IAChC,iBAAiB;IACjB,sBAAsB,EAAC,sBAAsB;IAC7C,gBAAgB;IAChB,cAAc;CACf,CAAC,CAAC;AAGH,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;AAC5E,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACzC,IAAI,EAAE,gBAAgB;IACtB,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,UAAU,CAAC;CACzC,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,aAAa;IACb,yBAAyB,EAAC,qBAAqB,EAAC,cAAc;IAC9D,uBAAuB,EAAC,sBAAsB,EAAC,kBAAkB,EAAC,uBAAuB;IACzF,aAAa;IACb,2BAA2B,EAAC,oBAAoB,EAAC,0BAA0B,EAAC,yBAAyB;IACrG,sBAAsB,EAAC,oBAAoB,EAAC,uBAAuB,EAAC,yBAAyB;IAC7F,sBAAsB,EAAC,mBAAmB,EAAC,aAAa,EAAC,qBAAqB,EAAC,mBAAmB;CAC1F,CAAC;AAGX;;;;;GAKG;AAEH,MAAM,UAAU,4BAA4B,CAC1C,QAA4B,EAC5B,KAAwB,EACxB,SAAkC;IAElC,MAAM,MAAM,GAAqD,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IACrF,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QAC/C,IAAI,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,SAAS,EAAE,CAAC;YAC3F,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAChB,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,EAAE,CAAC;AAC1E,CAAC"}
|