@phnx-labs/agents-cli 1.22.119 → 1.22.121
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/CHANGELOG.md +236 -0
- package/README.md +19 -2
- package/dist/bootstrap.d.ts +0 -15
- package/dist/bootstrap.js +10 -409
- package/dist/cli/command-registry.d.ts +0 -58
- package/dist/cli/command-registry.js +2 -74
- package/dist/commands/accounts.d.ts +0 -17
- package/dist/commands/accounts.js +1 -52
- package/dist/commands/alias.d.ts +0 -12
- package/dist/commands/alias.js +0 -6
- package/dist/commands/apply.d.ts +0 -15
- package/dist/commands/apply.js +0 -63
- package/dist/commands/audit.d.ts +0 -12
- package/dist/commands/audit.js +0 -13
- package/dist/commands/auth.js +4 -12
- package/dist/commands/beta.d.ts +0 -6
- package/dist/commands/beta.js +2 -6
- package/dist/commands/browser-sessions-picker.d.ts +0 -8
- package/dist/commands/browser-sessions-picker.js +0 -26
- package/dist/commands/browser.d.ts +0 -57
- package/dist/commands/browser.js +0 -80
- package/dist/commands/budget.d.ts +0 -13
- package/dist/commands/budget.js +0 -2
- package/dist/commands/cli.d.ts +0 -12
- package/dist/commands/cli.js +0 -4
- package/dist/commands/cloud.d.ts +0 -9
- package/dist/commands/cloud.js +0 -43
- package/dist/commands/commands.d.ts +0 -9
- package/dist/commands/commands.js +0 -18
- package/dist/commands/computer-sessions-picker.d.ts +0 -11
- package/dist/commands/computer-sessions-picker.js +0 -29
- package/dist/commands/computer.d.ts +0 -62
- package/dist/commands/computer.js +3 -114
- package/dist/commands/config.d.ts +0 -14
- package/dist/commands/config.js +21 -60
- package/dist/commands/cost.d.ts +0 -11
- package/dist/commands/cost.js +1 -17
- package/dist/commands/daemon-test-harness.d.ts +0 -32
- package/dist/commands/daemon-test-harness.js +1 -36
- package/dist/commands/daemon.d.ts +0 -46
- package/dist/commands/daemon.js +8 -255
- package/dist/commands/detach-core.d.ts +0 -28
- package/dist/commands/detach-core.js +0 -30
- package/dist/commands/detach.d.ts +1 -12
- package/dist/commands/detach.js +16 -52
- package/dist/commands/device-config-test-harness.js +0 -12
- package/dist/commands/doctor.d.ts +0 -103
- package/dist/commands/doctor.js +3 -279
- package/dist/commands/events.d.ts +0 -29
- package/dist/commands/events.js +1 -55
- package/dist/commands/exec.d.ts +0 -163
- package/dist/commands/exec.js +15 -964
- package/dist/commands/factory.d.ts +0 -6
- package/dist/commands/factory.js +0 -2
- package/dist/commands/feed-watch.js +0 -20
- package/dist/commands/feed.d.ts +0 -38
- package/dist/commands/feed.js +1 -151
- package/dist/commands/feedback.d.ts +0 -5
- package/dist/commands/feedback.js +0 -5
- package/dist/commands/fleet-capture.d.ts +0 -12
- package/dist/commands/fleet-capture.js +1 -39
- package/dist/commands/focus.d.ts +6 -94
- package/dist/commands/focus.js +13 -183
- package/dist/commands/fork.d.ts +0 -21
- package/dist/commands/fork.js +0 -45
- package/dist/commands/funnel.d.ts +0 -3
- package/dist/commands/go.d.ts +2 -71
- package/dist/commands/go.js +5 -99
- package/dist/commands/harness-hooks.d.ts +0 -41
- package/dist/commands/harness-hooks.js +0 -48
- package/dist/commands/harness-wizard.d.ts +0 -137
- package/dist/commands/harness-wizard.js +0 -109
- package/dist/commands/harness.d.ts +0 -63
- package/dist/commands/harness.js +0 -103
- package/dist/commands/hooks.d.ts +0 -9
- package/dist/commands/hooks.js +0 -26
- package/dist/commands/humans.d.ts +0 -8
- package/dist/commands/humans.js +0 -8
- package/dist/commands/import.d.ts +0 -22
- package/dist/commands/import.js +0 -79
- package/dist/commands/insights.d.ts +0 -37
- package/dist/commands/insights.js +3 -115
- package/dist/commands/inspect.d.ts +0 -117
- package/dist/commands/inspect.js +2 -448
- package/dist/commands/lease.d.ts +0 -28
- package/dist/commands/lease.js +0 -43
- package/dist/commands/logs.d.ts +0 -23
- package/dist/commands/logs.js +0 -30
- package/dist/commands/mailboxes.d.ts +0 -18
- package/dist/commands/mailboxes.js +0 -29
- package/dist/commands/mcp.d.ts +0 -9
- package/dist/commands/mcp.js +0 -53
- package/dist/commands/memory.d.ts +0 -7
- package/dist/commands/memory.js +0 -7
- package/dist/commands/menubar.d.ts +0 -8
- package/dist/commands/menubar.js +0 -24
- package/dist/commands/message.d.ts +0 -23
- package/dist/commands/message.js +0 -50
- package/dist/commands/mine.d.ts +0 -22
- package/dist/commands/mine.js +0 -21
- package/dist/commands/models.d.ts +0 -8
- package/dist/commands/models.js +0 -33
- package/dist/commands/modes.d.ts +0 -10
- package/dist/commands/modes.js +0 -13
- package/dist/commands/monitors.d.ts +0 -9
- package/dist/commands/monitors.js +3 -160
- package/dist/commands/open.d.ts +0 -26
- package/dist/commands/open.js +0 -10
- package/dist/commands/output.d.ts +0 -18
- package/dist/commands/output.js +1 -34
- package/dist/commands/packages-materialize.d.ts +0 -11
- package/dist/commands/packages-materialize.js +0 -3
- package/dist/commands/packages.d.ts +0 -10
- package/dist/commands/packages.js +0 -50
- package/dist/commands/perf.d.ts +0 -41
- package/dist/commands/perf.js +0 -55
- package/dist/commands/permissions.d.ts +0 -9
- package/dist/commands/permissions.js +0 -43
- package/dist/commands/plugins.d.ts +0 -14
- package/dist/commands/plugins.js +2 -55
- package/dist/commands/profiles.d.ts +0 -25
- package/dist/commands/profiles.js +0 -27
- package/dist/commands/projects-todo.d.ts +2 -0
- package/dist/commands/projects-todo.js +132 -0
- package/dist/commands/projects.d.ts +0 -85
- package/dist/commands/projects.js +344 -291
- package/dist/commands/prune.js +0 -30
- package/dist/commands/ps-roster.d.ts +92 -0
- package/dist/commands/ps-roster.js +744 -0
- package/dist/commands/ps.d.ts +6 -0
- package/dist/commands/ps.js +98 -0
- package/dist/commands/refresh-rules.d.ts +0 -13
- package/dist/commands/refresh-rules.js +0 -14
- package/dist/commands/reminders.d.ts +0 -7
- package/dist/commands/repo.d.ts +0 -89
- package/dist/commands/repo.js +7 -205
- package/dist/commands/resource-view.d.ts +0 -33
- package/dist/commands/resource-view.js +0 -49
- package/dist/commands/resume.d.ts +1 -19
- package/dist/commands/resume.js +0 -50
- package/dist/commands/route.d.ts +0 -10
- package/dist/commands/route.js +0 -19
- package/dist/commands/routines.d.ts +0 -42
- package/dist/commands/routines.js +5 -290
- package/dist/commands/routines.test-fixture.d.ts +0 -34
- package/dist/commands/routines.test-fixture.js +4 -100
- package/dist/commands/rules.d.ts +0 -9
- package/dist/commands/rules.js +1 -6
- package/dist/commands/run-account-picker.d.ts +0 -59
- package/dist/commands/run-account-picker.js +0 -71
- package/dist/commands/run-broadcast.d.ts +0 -9
- package/dist/commands/run-broadcast.js +0 -7
- package/dist/commands/run-cloud.d.ts +0 -15
- package/dist/commands/run-cloud.js +0 -37
- package/dist/commands/run-device-picker.d.ts +0 -25
- package/dist/commands/run-device-picker.js +1 -53
- package/dist/commands/secrets-passthrough.d.ts +0 -31
- package/dist/commands/secrets-passthrough.js +0 -10
- package/dist/commands/send.d.ts +0 -20
- package/dist/commands/send.js +14 -18
- package/dist/commands/sessions-backfill.d.ts +0 -7
- package/dist/commands/sessions-backfill.js +1 -16
- package/dist/commands/sessions-backup-setup.js +0 -11
- package/dist/commands/sessions-bookmark.d.ts +0 -8
- package/dist/commands/sessions-bookmark.js +0 -28
- package/dist/commands/sessions-browser.d.ts +2 -117
- package/dist/commands/sessions-browser.js +5 -243
- package/dist/commands/sessions-export.d.ts +1 -26
- package/dist/commands/sessions-export.js +3 -81
- package/dist/commands/sessions-import.d.ts +0 -14
- package/dist/commands/sessions-import.js +0 -59
- package/dist/commands/sessions-inject.d.ts +0 -60
- package/dist/commands/sessions-inject.js +3 -96
- package/dist/commands/sessions-migrate.d.ts +2 -37
- package/dist/commands/sessions-migrate.js +7 -159
- package/dist/commands/sessions-optimize.d.ts +0 -12
- package/dist/commands/sessions-picker-factory.d.ts +0 -7
- package/dist/commands/sessions-picker-factory.js +0 -8
- package/dist/commands/sessions-picker.d.ts +4 -103
- package/dist/commands/sessions-picker.js +13 -352
- package/dist/commands/sessions-render.d.ts +1 -2
- package/dist/commands/sessions-render.js +3 -7
- package/dist/commands/sessions-resume.d.ts +1 -24
- package/dist/commands/sessions-resume.js +2 -65
- package/dist/commands/sessions-share.d.ts +1 -9
- package/dist/commands/sessions-share.js +1 -45
- package/dist/commands/sessions-stats.d.ts +0 -24
- package/dist/commands/sessions-stats.js +0 -49
- package/dist/commands/sessions-stop.d.ts +1 -20
- package/dist/commands/sessions-stop.js +4 -9
- package/dist/commands/sessions-tail.d.ts +1 -19
- package/dist/commands/sessions-tail.js +3 -36
- package/dist/commands/sessions-trace.d.ts +5 -36
- package/dist/commands/sessions-trace.js +7 -82
- package/dist/commands/sessions.d.ts +1 -666
- package/dist/commands/sessions.js +30 -2279
- package/dist/commands/sessions.test-fixture.d.ts +0 -9
- package/dist/commands/sessions.test-fixture.js +8 -23
- package/dist/commands/setup-accounts.d.ts +0 -6
- package/dist/commands/setup-browser.d.ts +0 -23
- package/dist/commands/setup-browser.js +0 -28
- package/dist/commands/setup-computer.d.ts +0 -16
- package/dist/commands/setup-computer.js +0 -28
- package/dist/commands/setup-fleet.d.ts +0 -8
- package/dist/commands/setup-fleet.js +0 -11
- package/dist/commands/setup-mine.d.ts +0 -14
- package/dist/commands/setup-mine.js +0 -25
- package/dist/commands/setup-preferences.d.ts +0 -47
- package/dist/commands/setup-preferences.js +0 -53
- package/dist/commands/setup-secrets.d.ts +2 -24
- package/dist/commands/setup-secrets.js +0 -24
- package/dist/commands/setup-term.d.ts +0 -21
- package/dist/commands/setup-term.js +0 -21
- package/dist/commands/setup-terminal.d.ts +0 -1
- package/dist/commands/setup-terminal.js +0 -1
- package/dist/commands/setup-tools.d.ts +2 -0
- package/dist/commands/setup-tools.js +73 -0
- package/dist/commands/setup.d.ts +0 -20
- package/dist/commands/setup.js +4 -57
- package/dist/commands/skills.d.ts +0 -9
- package/dist/commands/skills.js +1 -22
- package/dist/commands/snapshot.d.ts +0 -9
- package/dist/commands/snapshot.js +0 -10
- package/dist/commands/ssh.d.ts +0 -64
- package/dist/commands/ssh.js +9 -420
- package/dist/commands/status.d.ts +0 -12
- package/dist/commands/status.js +0 -26
- package/dist/commands/subagents.d.ts +0 -8
- package/dist/commands/subagents.js +0 -31
- package/dist/commands/sync.d.ts +0 -37
- package/dist/commands/sync.js +0 -256
- package/dist/commands/teams-picker.d.ts +0 -3
- package/dist/commands/teams-picker.js +0 -34
- package/dist/commands/teams.d.ts +1 -76
- package/dist/commands/teams.js +9 -477
- package/dist/commands/tmux.d.ts +0 -25
- package/dist/commands/tmux.js +0 -46
- package/dist/commands/traces.js +0 -19
- package/dist/commands/trash.d.ts +0 -17
- package/dist/commands/trash.js +1 -11
- package/dist/commands/uninstall.d.ts +0 -9
- package/dist/commands/uninstall.js +0 -6
- package/dist/commands/update.d.ts +0 -22
- package/dist/commands/update.js +0 -44
- package/dist/commands/upgrade.d.ts +0 -1
- package/dist/commands/upgrade.js +0 -1
- package/dist/commands/utils.d.ts +0 -85
- package/dist/commands/utils.js +1 -95
- package/dist/commands/versions.d.ts +0 -16
- package/dist/commands/versions.js +0 -134
- package/dist/commands/view.d.ts +0 -90
- package/dist/commands/view.js +4 -343
- package/dist/commands/watchdog.d.ts +0 -19
- package/dist/commands/watchdog.js +3 -43
- package/dist/commands/webhook.d.ts +0 -8
- package/dist/commands/webhook.js +0 -14
- package/dist/commands/workflows.d.ts +0 -8
- package/dist/commands/workflows.js +0 -6
- package/dist/index.d.ts +0 -25
- package/dist/index.js +5 -119
- package/dist/lib/account-capabilities.d.ts +0 -34
- package/dist/lib/account-capabilities.js +0 -32
- package/dist/lib/account-catalog.d.ts +0 -128
- package/dist/lib/account-catalog.js +8 -154
- package/dist/lib/account-provider-registry.d.ts +0 -14
- package/dist/lib/account-provider-registry.js +0 -8
- package/dist/lib/account-registry.d.ts +0 -74
- package/dist/lib/account-registry.js +14 -189
- package/dist/lib/account-schema.d.ts +0 -19
- package/dist/lib/account-schema.js +0 -43
- package/dist/lib/accounting/account-launch.d.ts +0 -15
- package/dist/lib/accounting/account-launch.js +1 -3
- package/dist/lib/accounting/account-pool-collect.d.ts +0 -26
- package/dist/lib/accounting/account-pool-collect.js +0 -42
- package/dist/lib/accounting/account-pool.d.ts +0 -41
- package/dist/lib/accounting/account-pool.js +0 -17
- package/dist/lib/accounting/capacity.d.ts +0 -32
- package/dist/lib/accounting/capacity.js +0 -32
- package/dist/lib/accounting/rotate.d.ts +0 -518
- package/dist/lib/accounting/rotate.js +4 -598
- package/dist/lib/accounting/usage-ingest.d.ts +0 -1
- package/dist/lib/accounting/usage-ingest.js +0 -44
- package/dist/lib/accounting/usage-sync.d.ts +0 -60
- package/dist/lib/accounting/usage-sync.js +4 -51
- package/dist/lib/accounting/usage.d.ts +0 -632
- package/dist/lib/accounting/usage.js +14 -1055
- package/dist/lib/accounts/add.d.ts +0 -60
- package/dist/lib/accounts/add.js +0 -127
- package/dist/lib/accounts/auth-operation-lock.d.ts +0 -1
- package/dist/lib/accounts/auth-operation-lock.js +0 -4
- package/dist/lib/accounts/migrate.d.ts +0 -9
- package/dist/lib/accounts/migrate.js +3 -42
- package/dist/lib/accounts/slots.d.ts +0 -25
- package/dist/lib/accounts/slots.js +1 -49
- package/dist/lib/acp/client.d.ts +0 -16
- package/dist/lib/acp/client.js +0 -29
- package/dist/lib/acp/harnesses.d.ts +0 -15
- package/dist/lib/acp/harnesses.js +0 -16
- package/dist/lib/acp/run.d.ts +0 -8
- package/dist/lib/acp/run.js +0 -8
- package/dist/lib/actor.d.ts +1 -71
- package/dist/lib/actor.js +1 -99
- package/dist/lib/add-dir.d.ts +0 -46
- package/dist/lib/add-dir.js +1 -70
- package/dist/lib/address.d.ts +0 -17
- package/dist/lib/address.js +0 -15
- package/dist/lib/agent-cli-commands.d.ts +0 -10
- package/dist/lib/agent-cli-commands.js +0 -10
- package/dist/lib/agent-modes.d.ts +0 -29
- package/dist/lib/agent-modes.js +0 -31
- package/dist/lib/agent-spec/agents.d.ts +0 -426
- package/dist/lib/agent-spec/agents.js +37 -924
- package/dist/lib/agent-spec/index.d.ts +0 -5
- package/dist/lib/agent-spec/index.js +0 -14
- package/dist/lib/agent-spec/materialize.d.ts +0 -10
- package/dist/lib/agent-spec/materialize.js +2 -139
- package/dist/lib/agent-spec/package-resolve.d.ts +0 -8
- package/dist/lib/agent-spec/package-resolve.js +1 -44
- package/dist/lib/agent-spec/package-schema.d.ts +0 -2
- package/dist/lib/agent-spec/package-schema.js +0 -11
- package/dist/lib/agent-spec/package-types.d.ts +0 -27
- package/dist/lib/agent-spec/package-types.js +0 -1
- package/dist/lib/agent-spec/primitives.d.ts +0 -18
- package/dist/lib/agent-spec/primitives.js +0 -27
- package/dist/lib/agent-spec/provider.js +0 -2
- package/dist/lib/agent-spec/resolve.d.ts +0 -23
- package/dist/lib/agent-spec/resolve.js +0 -41
- package/dist/lib/agent-spec/types.d.ts +0 -34
- package/dist/lib/agent-spec/types.js +0 -6
- package/dist/lib/agents.d.ts +0 -1
- package/dist/lib/agents.js +0 -1
- package/dist/lib/analytics/mix-commands.d.ts +0 -23
- package/dist/lib/analytics/mix-commands.js +0 -26
- package/dist/lib/analytics/recipes.d.ts +0 -1
- package/dist/lib/analytics/recipes.js +5 -10
- package/dist/lib/analytics/usage-db.js +4 -6
- package/dist/lib/answer-router.d.ts +0 -61
- package/dist/lib/answer-router.js +0 -57
- package/dist/lib/app-bundle-install.d.ts +0 -13
- package/dist/lib/app-bundle-install.js +0 -50
- package/dist/lib/artifact-actions.d.ts +0 -15
- package/dist/lib/artifact-actions.js +0 -18
- package/dist/lib/artifacts-client.d.ts +0 -10
- package/dist/lib/artifacts-client.js +0 -17
- package/dist/lib/ask-classifier.d.ts +0 -38
- package/dist/lib/ask-classifier.js +0 -27
- package/dist/lib/audit/log.d.ts +0 -47
- package/dist/lib/audit/log.js +1 -59
- package/dist/lib/auth-health.d.ts +0 -213
- package/dist/lib/auth-health.js +16 -266
- package/dist/lib/auth-mint.d.ts +0 -83
- package/dist/lib/auth-mint.js +8 -85
- package/dist/lib/auto-pull-worker.d.ts +0 -10
- package/dist/lib/auto-pull-worker.js +3 -48
- package/dist/lib/auto-pull.d.ts +0 -64
- package/dist/lib/auto-pull.js +0 -79
- package/dist/lib/beta.d.ts +0 -9
- package/dist/lib/beta.js +0 -9
- package/dist/lib/binary-shadow.d.ts +0 -22
- package/dist/lib/binary-shadow.js +4 -34
- package/dist/lib/boot-profile.d.ts +0 -10
- package/dist/lib/boot-profile.js +1 -31
- package/dist/lib/brand.d.ts +0 -20
- package/dist/lib/brand.js +0 -50
- package/dist/lib/browser/context.d.ts +0 -54
- package/dist/lib/browser/context.js +0 -49
- package/dist/lib/browser/paths.d.ts +0 -21
- package/dist/lib/browser/paths.js +0 -26
- package/dist/lib/browser/record.d.ts +0 -34
- package/dist/lib/browser/record.js +0 -38
- package/dist/lib/browser/sessions-list.d.ts +1 -79
- package/dist/lib/browser/sessions-list.js +2 -98
- package/dist/lib/browser-client.d.ts +0 -112
- package/dist/lib/browser-client.js +1 -90
- package/dist/lib/budget/config.d.ts +0 -6
- package/dist/lib/budget/config.js +0 -29
- package/dist/lib/budget/enforce.d.ts +0 -50
- package/dist/lib/budget/enforce.js +0 -27
- package/dist/lib/budget/ledger.d.ts +0 -23
- package/dist/lib/budget/ledger.js +0 -28
- package/dist/lib/budget/live-cloud.d.ts +0 -26
- package/dist/lib/budget/live-cloud.js +0 -12
- package/dist/lib/budget/live-team.d.ts +0 -17
- package/dist/lib/budget/live-team.js +1 -35
- package/dist/lib/budget/preflight.d.ts +0 -51
- package/dist/lib/budget/preflight.js +0 -36
- package/dist/lib/byok-usage.d.ts +0 -20
- package/dist/lib/byok-usage.js +1 -24
- package/dist/lib/capabilities.d.ts +0 -24
- package/dist/lib/capabilities.js +0 -29
- package/dist/lib/catchup.d.ts +0 -87
- package/dist/lib/catchup.js +1 -81
- package/dist/lib/channels/owner-forward.d.ts +0 -70
- package/dist/lib/channels/owner-forward.js +1 -43
- package/dist/lib/channels/owner-sink.js +0 -21
- package/dist/lib/channels/providers/desktop.d.ts +0 -37
- package/dist/lib/channels/providers/desktop.js +0 -72
- package/dist/lib/channels/providers/index.d.ts +0 -1
- package/dist/lib/channels/providers/index.js +2 -6
- package/dist/lib/channels/providers/mailbox.js +0 -7
- package/dist/lib/channels/providers/openclaw-telegram.js +0 -8
- package/dist/lib/channels/providers/rush.d.ts +0 -2
- package/dist/lib/channels/providers/rush.js +0 -26
- package/dist/lib/channels/providers/session.d.ts +2 -0
- package/dist/lib/channels/providers/session.js +26 -0
- package/dist/lib/channels/registry.d.ts +0 -27
- package/dist/lib/channels/registry.js +0 -10
- package/dist/lib/channels/resolve.d.ts +0 -19
- package/dist/lib/channels/resolve.js +0 -2
- package/dist/lib/channels/send.d.ts +0 -50
- package/dist/lib/channels/send.js +0 -25
- package/dist/lib/checkpoint.d.ts +0 -36
- package/dist/lib/checkpoint.js +0 -28
- package/dist/lib/claude-account-token.d.ts +0 -98
- package/dist/lib/claude-account-token.js +7 -169
- package/dist/lib/claude-statusline.d.ts +0 -41
- package/dist/lib/claude-statusline.js +0 -68
- package/dist/lib/cli-entry.d.ts +0 -26
- package/dist/lib/cli-entry.js +1 -61
- package/dist/lib/cli-resources.d.ts +31 -89
- package/dist/lib/cli-resources.js +116 -152
- package/dist/lib/cloud/antigravity.d.ts +0 -29
- package/dist/lib/cloud/antigravity.js +0 -36
- package/dist/lib/cloud/codex.d.ts +0 -8
- package/dist/lib/cloud/codex.js +0 -41
- package/dist/lib/cloud/cursor.d.ts +0 -5
- package/dist/lib/cloud/cursor.js +2 -7
- package/dist/lib/cloud/dispatch.d.ts +0 -13
- package/dist/lib/cloud/dispatch.js +1 -48
- package/dist/lib/cloud/factory.d.ts +0 -52
- package/dist/lib/cloud/factory.js +3 -67
- package/dist/lib/cloud/host.d.ts +0 -39
- package/dist/lib/cloud/host.js +5 -48
- package/dist/lib/cloud/registry.d.ts +0 -25
- package/dist/lib/cloud/registry.js +0 -29
- package/dist/lib/cloud/rush.d.ts +0 -47
- package/dist/lib/cloud/rush.js +1 -82
- package/dist/lib/cloud/session-index.d.ts +0 -27
- package/dist/lib/cloud/session-index.js +1 -32
- package/dist/lib/cloud/store.d.ts +0 -18
- package/dist/lib/cloud/store.js +0 -28
- package/dist/lib/cloud/stream.d.ts +0 -14
- package/dist/lib/cloud/stream.js +0 -25
- package/dist/lib/cloud/types.d.ts +0 -168
- package/dist/lib/cloud/types.js +0 -46
- package/dist/lib/cloudflare/creds.d.ts +0 -2
- package/dist/lib/cloudflare/creds.js +0 -14
- package/dist/lib/cloudflare/provision.d.ts +0 -8
- package/dist/lib/cloudflare/provision.js +1 -19
- package/dist/lib/codex-home.d.ts +0 -60
- package/dist/lib/codex-home.js +2 -72
- package/dist/lib/codex-policy.d.ts +0 -10
- package/dist/lib/codex-policy.js +0 -13
- package/dist/lib/command-skills.d.ts +0 -10
- package/dist/lib/command-skills.js +0 -10
- package/dist/lib/commands.d.ts +0 -74
- package/dist/lib/commands.js +0 -112
- package/dist/lib/comms-render.d.ts +0 -5
- package/dist/lib/comms-render.js +0 -5
- package/dist/lib/computer/context.d.ts +0 -23
- package/dist/lib/computer/context.js +0 -14
- package/dist/lib/computer/policy.d.ts +0 -20
- package/dist/lib/computer/policy.js +0 -53
- package/dist/lib/computer/record.d.ts +0 -33
- package/dist/lib/computer/record.js +1 -48
- package/dist/lib/computer/sessions-list.d.ts +1 -128
- package/dist/lib/computer/sessions-list.js +6 -165
- package/dist/lib/computer-client.d.ts +0 -106
- package/dist/lib/computer-client.js +5 -86
- package/dist/lib/concurrency.d.ts +0 -14
- package/dist/lib/concurrency.js +0 -3
- package/dist/lib/config-drift.d.ts +0 -31
- package/dist/lib/config-drift.js +0 -32
- package/dist/lib/config-keys.d.ts +1 -65
- package/dist/lib/config-keys.js +6 -52
- package/dist/lib/config-transfer.d.ts +0 -14
- package/dist/lib/config-transfer.js +0 -26
- package/dist/lib/convert.d.ts +0 -17
- package/dist/lib/convert.js +0 -18
- package/dist/lib/crabbox/cli.d.ts +0 -156
- package/dist/lib/crabbox/cli.js +1 -188
- package/dist/lib/crabbox/config.d.ts +0 -18
- package/dist/lib/crabbox/config.js +1 -19
- package/dist/lib/crabbox/lease.d.ts +0 -93
- package/dist/lib/crabbox/lease.js +4 -148
- package/dist/lib/crabbox/progress.d.ts +0 -56
- package/dist/lib/crabbox/progress.js +2 -49
- package/dist/lib/crabbox/runtimes.d.ts +0 -94
- package/dist/lib/crabbox/runtimes.js +1 -111
- package/dist/lib/crabbox/setup-copy.d.ts +0 -64
- package/dist/lib/crabbox/setup-copy.js +1 -53
- package/dist/lib/daemon/account-state-daemon-service.d.ts +0 -48
- package/dist/lib/daemon/account-state-daemon-service.js +2 -63
- package/dist/lib/daemon/attention-notify-service.d.ts +0 -12
- package/dist/lib/daemon/attention-notify-service.js +1 -24
- package/dist/lib/daemon/auth-sync-service.d.ts +0 -28
- package/dist/lib/daemon/auth-sync-service.js +0 -56
- package/dist/lib/daemon/catchup-service.d.ts +0 -34
- package/dist/lib/daemon/catchup-service.js +0 -30
- package/dist/lib/daemon/daemon.d.ts +0 -374
- package/dist/lib/daemon/daemon.js +44 -1049
- package/dist/lib/daemon/daemon.test-fixture.d.ts +0 -19
- package/dist/lib/daemon/daemon.test-fixture.js +1 -24
- package/dist/lib/daemon/device-probe-service.d.ts +0 -16
- package/dist/lib/daemon/device-probe-service.js +0 -20
- package/dist/lib/daemon/feed-stream-service.d.ts +0 -15
- package/dist/lib/daemon/feed-stream-service.js +0 -20
- package/dist/lib/daemon/harness-update-service.d.ts +2 -61
- package/dist/lib/daemon/harness-update-service.js +6 -86
- package/dist/lib/daemon/heartbeat-service.d.ts +0 -1
- package/dist/lib/daemon/heartbeat-service.js +0 -1
- package/dist/lib/daemon/leaked-daemons.d.ts +0 -46
- package/dist/lib/daemon/leaked-daemons.js +2 -78
- package/dist/lib/daemon/monitor-engine-service.d.ts +0 -13
- package/dist/lib/daemon/monitor-engine-service.js +3 -15
- package/dist/lib/daemon/runner.d.ts +0 -194
- package/dist/lib/daemon/runner.js +39 -760
- package/dist/lib/daemon/self-heal-service.d.ts +18 -17
- package/dist/lib/daemon/self-heal-service.js +83 -37
- package/dist/lib/daemon/self-update-service.d.ts +1 -131
- package/dist/lib/daemon/self-update-service.js +26 -189
- package/dist/lib/daemon/service.d.ts +0 -73
- package/dist/lib/daemon/service.js +0 -34
- package/dist/lib/daemon/session-index-service.d.ts +0 -12
- package/dist/lib/daemon/session-index-service.js +0 -23
- package/dist/lib/daemon/session-state-service.d.ts +0 -8
- package/dist/lib/daemon/session-state-service.js +0 -8
- package/dist/lib/daemon/session-summarizer-service.d.ts +0 -14
- package/dist/lib/daemon/session-summarizer-service.js +1 -19
- package/dist/lib/daemon/session-title-service.d.ts +0 -25
- package/dist/lib/daemon/session-title-service.js +0 -32
- package/dist/lib/daemon/state-dir-check-service.d.ts +0 -24
- package/dist/lib/daemon/state-dir-check-service.js +0 -29
- package/dist/lib/daemon/supervisor.d.ts +0 -112
- package/dist/lib/daemon/supervisor.js +4 -147
- package/dist/lib/daemon/testdata/process-view-daemon.js +0 -2
- package/dist/lib/daemon/testdata/process-view-start.js +0 -5
- package/dist/lib/daemon/tmux-reap-service.d.ts +0 -1
- package/dist/lib/daemon/tmux-reap-service.js +0 -1
- package/dist/lib/daemon/usage-sync-service.d.ts +0 -23
- package/dist/lib/daemon/usage-sync-service.js +0 -26
- package/dist/lib/daemon/watchdog-service.d.ts +0 -9
- package/dist/lib/daemon/watchdog-service.js +0 -13
- package/dist/lib/daemon/webhook-receiver-service.d.ts +0 -1
- package/dist/lib/daemon/webhook-receiver-service.js +0 -1
- package/dist/lib/daemon-health.d.ts +0 -55
- package/dist/lib/daemon-health.js +4 -77
- package/dist/lib/daemon-services.d.ts +0 -36
- package/dist/lib/daemon-services.js +0 -45
- package/dist/lib/daemon-ticks.d.ts +0 -126
- package/dist/lib/daemon-ticks.js +1 -156
- package/dist/lib/daemon-webhooks.d.ts +0 -57
- package/dist/lib/daemon-webhooks.js +2 -54
- package/dist/lib/deeplink/register.d.ts +0 -15
- package/dist/lib/deeplink/register.js +0 -60
- package/dist/lib/deeplink/url.d.ts +0 -24
- package/dist/lib/deeplink/url.js +1 -33
- package/dist/lib/device-config.d.ts +1 -192
- package/dist/lib/device-config.js +86 -240
- package/dist/lib/devices/config-migration.d.ts +0 -43
- package/dist/lib/devices/config-migration.js +7 -127
- package/dist/lib/devices/connect.d.ts +0 -168
- package/dist/lib/devices/connect.js +6 -254
- package/dist/lib/devices/device-docs.d.ts +0 -24
- package/dist/lib/devices/device-docs.js +0 -46
- package/dist/lib/devices/discovery-policy.d.ts +0 -30
- package/dist/lib/devices/discovery-policy.js +3 -34
- package/dist/lib/devices/doctor-findings.d.ts +0 -109
- package/dist/lib/devices/doctor-findings.js +30 -326
- package/dist/lib/devices/doctor-overview-cache.d.ts +0 -33
- package/dist/lib/devices/doctor-overview-cache.js +0 -81
- package/dist/lib/devices/fleet-divergence.d.ts +0 -89
- package/dist/lib/devices/fleet-divergence.js +1 -60
- package/dist/lib/devices/fleet-inventory.d.ts +0 -27
- package/dist/lib/devices/fleet-inventory.js +0 -38
- package/dist/lib/devices/fleet.d.ts +0 -95
- package/dist/lib/devices/fleet.js +0 -79
- package/dist/lib/devices/harness-inventory.d.ts +0 -75
- package/dist/lib/devices/harness-inventory.js +0 -101
- package/dist/lib/devices/health-report.d.ts +0 -37
- package/dist/lib/devices/health-report.js +0 -73
- package/dist/lib/devices/health.d.ts +0 -71
- package/dist/lib/devices/health.js +2 -82
- package/dist/lib/devices/interactive-host.d.ts +0 -10
- package/dist/lib/devices/interactive-host.js +0 -34
- package/dist/lib/devices/known-hosts.d.ts +0 -45
- package/dist/lib/devices/known-hosts.js +0 -77
- package/dist/lib/devices/pending.d.ts +0 -31
- package/dist/lib/devices/pending.js +7 -67
- package/dist/lib/devices/pool.d.ts +0 -36
- package/dist/lib/devices/pool.js +0 -30
- package/dist/lib/devices/reachability.d.ts +0 -25
- package/dist/lib/devices/reachability.js +0 -14
- package/dist/lib/devices/registry.d.ts +0 -141
- package/dist/lib/devices/registry.js +4 -151
- package/dist/lib/devices/resolve-profile.d.ts +0 -18
- package/dist/lib/devices/resolve-profile.js +0 -18
- package/dist/lib/devices/resolve-target.d.ts +0 -20
- package/dist/lib/devices/resolve-target.js +1 -51
- package/dist/lib/devices/rollout-verify.d.ts +1 -81
- package/dist/lib/devices/rollout-verify.js +0 -77
- package/dist/lib/devices/self-host.d.ts +0 -7
- package/dist/lib/devices/self-host.js +1 -29
- package/dist/lib/devices/ssh-config.d.ts +0 -18
- package/dist/lib/devices/ssh-config.js +0 -9
- package/dist/lib/devices/stats-cache.d.ts +0 -48
- package/dist/lib/devices/stats-cache.js +0 -80
- package/dist/lib/devices/sync.d.ts +0 -97
- package/dist/lib/devices/sync.js +0 -88
- package/dist/lib/devices/tailscale.d.ts +0 -18
- package/dist/lib/devices/tailscale.js +1 -38
- package/dist/lib/devices/terminfo.d.ts +0 -27
- package/dist/lib/devices/terminfo.js +2 -64
- package/dist/lib/devices/worker-pick.d.ts +0 -15
- package/dist/lib/devices/worker-pick.js +0 -48
- package/dist/lib/diff-text.d.ts +0 -18
- package/dist/lib/diff-text.js +0 -15
- package/dist/lib/doctor-diff.d.ts +0 -79
- package/dist/lib/doctor-diff.js +2 -181
- package/dist/lib/drift-sync.d.ts +0 -29
- package/dist/lib/drift-sync.js +0 -40
- package/dist/lib/drift.d.ts +0 -43
- package/dist/lib/drift.js +0 -31
- package/dist/lib/event-families.d.ts +0 -17
- package/dist/lib/event-families.js +0 -33
- package/dist/lib/event-provenance.d.ts +0 -4
- package/dist/lib/event-provenance.js +0 -5
- package/dist/lib/event-stream.d.ts +0 -29
- package/dist/lib/event-stream.js +0 -36
- package/dist/lib/events-ingest.d.ts +0 -27
- package/dist/lib/events-ingest.js +0 -54
- package/dist/lib/exec-account-home.d.ts +0 -24
- package/dist/lib/exec-account-home.js +0 -41
- package/dist/lib/exec-bounded.d.ts +1 -37
- package/dist/lib/exec-bounded.js +10 -46
- package/dist/lib/exec.d.ts +3 -583
- package/dist/lib/exec.js +18 -1025
- package/dist/lib/factory/snapshot.js +1 -15
- package/dist/lib/feed/activity-stream.d.ts +0 -27
- package/dist/lib/feed/activity-stream.js +4 -80
- package/dist/lib/feed/activity.d.ts +1 -243
- package/dist/lib/feed/activity.js +8 -273
- package/dist/lib/feed/answer.d.ts +0 -103
- package/dist/lib/feed/answer.js +0 -267
- package/dist/lib/feed/attention.d.ts +0 -56
- package/dist/lib/feed/attention.js +0 -161
- package/dist/lib/feed/envelope.d.ts +2 -17
- package/dist/lib/feed/envelope.js +0 -14
- package/dist/lib/feed/events.d.ts +0 -118
- package/dist/lib/feed/events.js +13 -213
- package/dist/lib/feed/feed.d.ts +1 -250
- package/dist/lib/feed/feed.js +24 -334
- package/dist/lib/feed/hub-server.d.ts +0 -100
- package/dist/lib/feed/hub-server.js +1 -191
- package/dist/lib/feed/hub.d.ts +0 -53
- package/dist/lib/feed/hub.js +0 -89
- package/dist/lib/feed/pr-status.d.ts +1 -19
- package/dist/lib/feed/pr-status.js +0 -18
- package/dist/lib/feed/tool-activity.d.ts +0 -59
- package/dist/lib/feed/tool-activity.js +1 -119
- package/dist/lib/feed/tools.d.ts +0 -100
- package/dist/lib/feed/tools.js +0 -89
- package/dist/lib/feed/watch.d.ts +0 -33
- package/dist/lib/feed/watch.js +2 -94
- package/dist/lib/feed-broadcast.d.ts +0 -148
- package/dist/lib/feed-broadcast.js +1 -283
- package/dist/lib/feed-outcome.d.ts +0 -50
- package/dist/lib/feed-outcome.js +1 -67
- package/dist/lib/feed-policy.d.ts +0 -6
- package/dist/lib/feed-policy.js +1 -27
- package/dist/lib/feed-post.d.ts +0 -61
- package/dist/lib/feed-post.js +4 -61
- package/dist/lib/feed-ranking.d.ts +1 -1
- package/dist/lib/fleet/apply.d.ts +0 -64
- package/dist/lib/fleet/apply.js +0 -125
- package/dist/lib/fleet/auth-sync.d.ts +0 -48
- package/dist/lib/fleet/auth-sync.js +4 -49
- package/dist/lib/fleet/capture.d.ts +0 -26
- package/dist/lib/fleet/capture.js +1 -36
- package/dist/lib/fleet/manifest.d.ts +0 -38
- package/dist/lib/fleet/manifest.js +0 -40
- package/dist/lib/fleet/types.d.ts +1 -138
- package/dist/lib/fleet/types.js +0 -12
- package/dist/lib/fleet-cache.d.ts +0 -12
- package/dist/lib/fleet-cache.js +0 -24
- package/dist/lib/fleet-shared-state.d.ts +6 -59
- package/dist/lib/fleet-shared-state.js +5 -51
- package/dist/lib/fleet-status.d.ts +0 -27
- package/dist/lib/fleet-status.js +0 -48
- package/dist/lib/format.d.ts +0 -74
- package/dist/lib/format.js +3 -77
- package/dist/lib/friction-heuristics.d.ts +0 -20
- package/dist/lib/friction-heuristics.js +0 -8
- package/dist/lib/fs-atomic.d.ts +0 -51
- package/dist/lib/fs-atomic.js +8 -66
- package/dist/lib/fs-walk.d.ts +0 -13
- package/dist/lib/fs-walk.js +0 -22
- package/dist/lib/fuzzy.d.ts +0 -29
- package/dist/lib/fuzzy.js +0 -31
- package/dist/lib/gemini-settings.js +0 -12
- package/dist/lib/git.d.ts +0 -366
- package/dist/lib/git.js +7 -574
- package/dist/lib/github/ci-failure.d.ts +30 -0
- package/dist/lib/github/ci-failure.js +95 -0
- package/dist/lib/github/gh-overload.d.ts +0 -38
- package/dist/lib/github/gh-overload.js +3 -55
- package/dist/lib/github/pr-mergeable.d.ts +3 -34
- package/dist/lib/github/pr-mergeable.js +2 -42
- package/dist/lib/github/pr-verdict.d.ts +0 -44
- package/dist/lib/github/pr-verdict.js +0 -36
- package/dist/lib/github/project-prs.d.ts +135 -105
- package/dist/lib/github/project-prs.js +530 -170
- package/dist/lib/github/release-drift.d.ts +45 -0
- package/dist/lib/github/release-drift.js +91 -0
- package/dist/lib/github/rest.d.ts +0 -50
- package/dist/lib/github/rest.js +0 -49
- package/dist/lib/github/viewer.d.ts +27 -0
- package/dist/lib/github/viewer.js +101 -0
- package/dist/lib/goose-commands.d.ts +0 -29
- package/dist/lib/goose-commands.js +3 -48
- package/dist/lib/harness/adapter.d.ts +0 -151
- package/dist/lib/harness/adapter.js +0 -41
- package/dist/lib/harness/adapters/claude.d.ts +0 -8
- package/dist/lib/harness/adapters/claude.js +0 -89
- package/dist/lib/harness/adapters/codex.js +0 -18
- package/dist/lib/harness/adapters/copilot.js +0 -3
- package/dist/lib/harness/adapters/cursor.js +0 -16
- package/dist/lib/harness/adapters/droid.js +0 -3
- package/dist/lib/harness/adapters/kimi.js +0 -19
- package/dist/lib/harness/adapters/muse.js +0 -9
- package/dist/lib/harness/adapters/opencode.js +0 -2
- package/dist/lib/harness/exec-config-version.d.ts +0 -2
- package/dist/lib/harness/exec-config-version.js +0 -13
- package/dist/lib/harness/index.js +0 -10
- package/dist/lib/harness-auth-capabilities.d.ts +0 -26
- package/dist/lib/harness-auth-capabilities.js +0 -18
- package/dist/lib/harness-connection-test.d.ts +0 -27
- package/dist/lib/harness-connection-test.js +2 -20
- package/dist/lib/heal.d.ts +0 -45
- package/dist/lib/heal.js +2 -82
- package/dist/lib/help.d.ts +0 -32
- package/dist/lib/help.js +0 -41
- package/dist/lib/helper-download.d.ts +0 -85
- package/dist/lib/helper-download.js +0 -95
- package/dist/lib/helper-versions.d.ts +0 -51
- package/dist/lib/helper-versions.js +1 -45
- package/dist/lib/hooks/cache.d.ts +0 -40
- package/dist/lib/hooks/cache.js +8 -122
- package/dist/lib/hooks/install.d.ts +0 -253
- package/dist/lib/hooks/install.js +49 -822
- package/dist/lib/hooks/match.d.ts +0 -24
- package/dist/lib/hooks/match.js +0 -31
- package/dist/lib/hooks/profile.d.ts +0 -21
- package/dist/lib/hooks/profile.js +0 -28
- package/dist/lib/hosts/credential-transport.d.ts +0 -6
- package/dist/lib/hosts/credential-transport.js +0 -17
- package/dist/lib/hosts/credentials.d.ts +0 -35
- package/dist/lib/hosts/credentials.js +0 -38
- package/dist/lib/hosts/dispatch.d.ts +0 -140
- package/dist/lib/hosts/dispatch.js +0 -176
- package/dist/lib/hosts/logs.d.ts +0 -25
- package/dist/lib/hosts/logs.js +1 -51
- package/dist/lib/hosts/option.d.ts +0 -12
- package/dist/lib/hosts/option.js +0 -12
- package/dist/lib/hosts/passthrough.d.ts +0 -129
- package/dist/lib/hosts/passthrough.js +12 -249
- package/dist/lib/hosts/progress.d.ts +0 -90
- package/dist/lib/hosts/progress.js +5 -115
- package/dist/lib/hosts/providers/devices.d.ts +0 -19
- package/dist/lib/hosts/providers/devices.js +1 -34
- package/dist/lib/hosts/providers/local.d.ts +0 -14
- package/dist/lib/hosts/providers/local.js +0 -22
- package/dist/lib/hosts/ready.d.ts +0 -99
- package/dist/lib/hosts/ready.js +0 -101
- package/dist/lib/hosts/reconcile.d.ts +0 -38
- package/dist/lib/hosts/reconcile.js +1 -50
- package/dist/lib/hosts/reconnect.d.ts +0 -75
- package/dist/lib/hosts/reconnect.js +0 -98
- package/dist/lib/hosts/registry.d.ts +0 -74
- package/dist/lib/hosts/registry.js +0 -110
- package/dist/lib/hosts/remote-cmd.d.ts +1 -228
- package/dist/lib/hosts/remote-cmd.js +19 -294
- package/dist/lib/hosts/remote-cmd.test-fixture.d.ts +0 -1
- package/dist/lib/hosts/remote-cmd.test-fixture.js +0 -12
- package/dist/lib/hosts/remote-os.d.ts +0 -19
- package/dist/lib/hosts/remote-os.js +0 -22
- package/dist/lib/hosts/remote-session-id.d.ts +0 -22
- package/dist/lib/hosts/remote-session-id.js +0 -24
- package/dist/lib/hosts/routing-flag.d.ts +0 -21
- package/dist/lib/hosts/routing-flag.js +0 -21
- package/dist/lib/hosts/run-target.d.ts +0 -53
- package/dist/lib/hosts/run-target.js +0 -56
- package/dist/lib/hosts/session-index.d.ts +1 -53
- package/dist/lib/hosts/session-index.js +2 -59
- package/dist/lib/hosts/session-marker.d.ts +0 -31
- package/dist/lib/hosts/session-marker.js +0 -32
- package/dist/lib/hosts/ssh-config.d.ts +0 -25
- package/dist/lib/hosts/ssh-config.js +1 -32
- package/dist/lib/hosts/tasks.d.ts +0 -54
- package/dist/lib/hosts/tasks.js +0 -35
- package/dist/lib/hosts/types.d.ts +0 -39
- package/dist/lib/hosts/types.js +0 -22
- package/dist/lib/humans.d.ts +0 -21
- package/dist/lib/humans.js +0 -30
- package/dist/lib/identity/client.d.ts +1 -35
- package/dist/lib/identity/client.js +3 -29
- package/dist/lib/identity/index.d.ts +3 -27
- package/dist/lib/identity/index.js +8 -24
- package/dist/lib/import.d.ts +0 -104
- package/dist/lib/import.js +1 -137
- package/dist/lib/installations/active-check.d.ts +0 -53
- package/dist/lib/installations/active-check.js +0 -49
- package/dist/lib/installations/index.d.ts +0 -9
- package/dist/lib/installations/index.js +0 -9
- package/dist/lib/installations/installation-lock.js +0 -8
- package/dist/lib/installations/launch-gate.d.ts +0 -56
- package/dist/lib/installations/launch-gate.js +0 -83
- package/dist/lib/installations/migrate.d.ts +0 -100
- package/dist/lib/installations/migrate.js +105 -572
- package/dist/lib/installations/native-command.d.ts +0 -1
- package/dist/lib/installations/native-command.js +0 -6
- package/dist/lib/installations/resolve.d.ts +0 -24
- package/dist/lib/installations/resolve.js +0 -24
- package/dist/lib/installations/shims.d.ts +0 -395
- package/dist/lib/installations/shims.js +30 -957
- package/dist/lib/installations/store.d.ts +0 -199
- package/dist/lib/installations/store.js +1 -297
- package/dist/lib/installations/strategies.d.ts +0 -44
- package/dist/lib/installations/strategies.js +0 -87
- package/dist/lib/installations/types.d.ts +1 -67
- package/dist/lib/installations/types.js +0 -6
- package/dist/lib/installations/update-cancellation.d.ts +0 -74
- package/dist/lib/installations/update-cancellation.js +0 -74
- package/dist/lib/installations/update-policy.d.ts +0 -57
- package/dist/lib/installations/update-policy.js +0 -62
- package/dist/lib/installations/update-runtime.d.ts +0 -88
- package/dist/lib/installations/update-runtime.js +1 -127
- package/dist/lib/installations/update.d.ts +0 -53
- package/dist/lib/installations/update.js +0 -95
- package/dist/lib/installations/versions.d.ts +0 -310
- package/dist/lib/installations/versions.js +14 -837
- package/dist/lib/isolation-boundary-report.d.ts +0 -7
- package/dist/lib/isolation-boundary-report.js +0 -7
- package/dist/lib/launch-identity.d.ts +0 -8
- package/dist/lib/launch-identity.js +0 -8
- package/dist/lib/linear-autoclose.d.ts +0 -25
- package/dist/lib/linear-autoclose.js +0 -19
- package/dist/lib/linear-cache.d.ts +0 -57
- package/dist/lib/linear-cache.js +1 -81
- package/dist/lib/linear-project-counts.d.ts +0 -83
- package/dist/lib/linear-project-counts.js +2 -64
- package/dist/lib/linear-projects.d.ts +0 -62
- package/dist/lib/linear-projects.js +0 -85
- package/dist/lib/linear-rate-limit.d.ts +0 -21
- package/dist/lib/linear-rate-limit.js +1 -93
- package/dist/lib/linux-userns.d.ts +1 -42
- package/dist/lib/linux-userns.js +0 -47
- package/dist/lib/lock-compromise.d.ts +0 -7
- package/dist/lib/lock-compromise.js +0 -7
- package/dist/lib/log-follow.d.ts +0 -2
- package/dist/lib/log-follow.js +5 -15
- package/dist/lib/loop.d.ts +0 -106
- package/dist/lib/loop.js +0 -135
- package/dist/lib/machine-id.d.ts +0 -19
- package/dist/lib/machine-id.js +0 -19
- package/dist/lib/mailbox-gc.d.ts +0 -7
- package/dist/lib/mailbox-gc.js +0 -25
- package/dist/lib/mailbox-target.d.ts +0 -31
- package/dist/lib/mailbox-target.js +0 -27
- package/dist/lib/mailbox.d.ts +0 -77
- package/dist/lib/mailbox.js +5 -105
- package/dist/lib/manifest.d.ts +0 -4
- package/dist/lib/manifest.js +0 -36
- package/dist/lib/markdown.d.ts +0 -3
- package/dist/lib/markdown.js +0 -9
- package/dist/lib/mcp-registry.d.ts +1 -50
- package/dist/lib/mcp-registry.js +0 -64
- package/dist/lib/mcp.d.ts +0 -115
- package/dist/lib/mcp.js +3 -199
- package/dist/lib/memory-cache.d.ts +0 -11
- package/dist/lib/memory-cache.js +0 -9
- package/dist/lib/memory.d.ts +0 -52
- package/dist/lib/memory.js +12 -74
- package/dist/lib/menubar/download-menubar.d.ts +0 -35
- package/dist/lib/menubar/download-menubar.js +0 -38
- package/dist/lib/menubar/install-menubar.d.ts +0 -405
- package/dist/lib/menubar/install-menubar.js +25 -667
- package/dist/lib/menubar/migrate-prefs.d.ts +0 -47
- package/dist/lib/menubar/migrate-prefs.js +1 -70
- package/dist/lib/menubar/notify-desktop.d.ts +0 -82
- package/dist/lib/menubar/notify-desktop.js +0 -68
- package/dist/lib/menubar/resolve-version.d.ts +0 -41
- package/dist/lib/menubar/resolve-version.js +2 -44
- package/dist/lib/menubar/snapshot.d.ts +13 -66
- package/dist/lib/menubar/snapshot.js +45 -39
- package/dist/lib/merged-resources.d.ts +0 -10
- package/dist/lib/merged-resources.js +0 -10
- package/dist/lib/migrate-fold.d.ts +0 -31
- package/dist/lib/migrate-fold.js +6 -38
- package/dist/lib/model-tier-overrides.d.ts +0 -30
- package/dist/lib/model-tier-overrides.js +0 -14
- package/dist/lib/model-tiers.d.ts +0 -43
- package/dist/lib/model-tiers.js +5 -78
- package/dist/lib/models.d.ts +0 -145
- package/dist/lib/models.js +3 -333
- package/dist/lib/monitors/config.d.ts +0 -187
- package/dist/lib/monitors/config.js +4 -101
- package/dist/lib/monitors/dispatch.d.ts +0 -22
- package/dist/lib/monitors/dispatch.js +0 -35
- package/dist/lib/monitors/engine.d.ts +1 -53
- package/dist/lib/monitors/engine.js +17 -106
- package/dist/lib/monitors/fingerprint.d.ts +0 -43
- package/dist/lib/monitors/fingerprint.js +0 -57
- package/dist/lib/monitors/pid-watch.d.ts +0 -31
- package/dist/lib/monitors/pid-watch.js +0 -31
- package/dist/lib/monitors/remote.d.ts +0 -52
- package/dist/lib/monitors/remote.js +0 -42
- package/dist/lib/monitors/sources/command.d.ts +2 -9
- package/dist/lib/monitors/sources/command.js +13 -34
- package/dist/lib/monitors/sources/device.d.ts +0 -10
- package/dist/lib/monitors/sources/device.js +0 -14
- package/dist/lib/monitors/sources/failure.d.ts +0 -27
- package/dist/lib/monitors/sources/failure.js +0 -27
- package/dist/lib/monitors/sources/file.d.ts +0 -10
- package/dist/lib/monitors/sources/file.js +0 -11
- package/dist/lib/monitors/sources/http.d.ts +0 -7
- package/dist/lib/monitors/sources/http.js +0 -9
- package/dist/lib/monitors/sources/index.d.ts +0 -9
- package/dist/lib/monitors/sources/index.js +0 -9
- package/dist/lib/monitors/sources/poll.d.ts +0 -8
- package/dist/lib/monitors/sources/poll.js +0 -8
- package/dist/lib/monitors/sources/types.d.ts +0 -18
- package/dist/lib/monitors/sources/types.js +0 -8
- package/dist/lib/monitors/sources/webhook.d.ts +0 -7
- package/dist/lib/monitors/sources/webhook.js +0 -7
- package/dist/lib/monitors/sources/ws.d.ts +0 -10
- package/dist/lib/monitors/sources/ws.js +3 -13
- package/dist/lib/monitors/state.d.ts +0 -132
- package/dist/lib/monitors/state.js +2 -86
- package/dist/lib/native-accounts.d.ts +0 -32
- package/dist/lib/native-accounts.js +0 -17
- package/dist/lib/net-close.d.ts +0 -9
- package/dist/lib/net-close.js +0 -5
- package/dist/lib/notify.d.ts +0 -47
- package/dist/lib/notify.js +0 -30
- package/dist/lib/onepassword.d.ts +0 -14
- package/dist/lib/onepassword.js +0 -12
- package/dist/lib/open-url.d.ts +0 -38
- package/dist/lib/open-url.js +1 -69
- package/dist/lib/openclaw-keychain.js +2 -7
- package/dist/lib/operator.d.ts +0 -9
- package/dist/lib/operator.js +0 -34
- package/dist/lib/origin-machine.d.ts +0 -16
- package/dist/lib/origin-machine.js +0 -16
- package/dist/lib/output/git-output.d.ts +0 -31
- package/dist/lib/output/git-output.js +4 -43
- package/dist/lib/overdue.d.ts +0 -35
- package/dist/lib/overdue.js +0 -60
- package/dist/lib/owner-message.d.ts +0 -20
- package/dist/lib/owner-message.js +1 -40
- package/dist/lib/packages/output-home.d.ts +0 -28
- package/dist/lib/packages/output-home.js +0 -114
- package/dist/lib/paths.d.ts +0 -26
- package/dist/lib/paths.js +1 -27
- package/dist/lib/percentile.d.ts +0 -11
- package/dist/lib/percentile.js +0 -11
- package/dist/lib/perf/db.d.ts +0 -16
- package/dist/lib/perf/db.js +3 -32
- package/dist/lib/perf/spool.d.ts +0 -12
- package/dist/lib/perf/spool.js +0 -13
- package/dist/lib/perf/types.d.ts +0 -26
- package/dist/lib/perf/types.js +0 -1
- package/dist/lib/permissions-registry.d.ts +0 -48
- package/dist/lib/permissions-registry.js +0 -108
- package/dist/lib/permissions.d.ts +0 -215
- package/dist/lib/permissions.js +4 -407
- package/dist/lib/picker.d.ts +0 -124
- package/dist/lib/picker.js +0 -140
- package/dist/lib/placement.d.ts +0 -57
- package/dist/lib/placement.js +0 -47
- package/dist/lib/platform/exec.d.ts +0 -73
- package/dist/lib/platform/exec.js +0 -80
- package/dist/lib/platform/index.d.ts +0 -14
- package/dist/lib/platform/index.js +0 -14
- package/dist/lib/platform/ipc.d.ts +0 -10
- package/dist/lib/platform/ipc.js +0 -13
- package/dist/lib/platform/links.d.ts +0 -14
- package/dist/lib/platform/links.js +0 -25
- package/dist/lib/platform/paths.d.ts +0 -48
- package/dist/lib/platform/paths.js +0 -52
- package/dist/lib/platform/posixpath.d.ts +0 -18
- package/dist/lib/platform/posixpath.js +0 -62
- package/dist/lib/platform/process.d.ts +0 -67
- package/dist/lib/platform/process.js +5 -99
- package/dist/lib/platform/winpath.d.ts +0 -50
- package/dist/lib/platform/winpath.js +0 -81
- package/dist/lib/plugins/plugin-marketplace.d.ts +0 -165
- package/dist/lib/plugins/plugin-marketplace.js +10 -238
- package/dist/lib/plugins/plugins.d.ts +0 -238
- package/dist/lib/plugins/plugins.js +20 -454
- package/dist/lib/plugins/skills.d.ts +0 -86
- package/dist/lib/plugins/skills.js +1 -139
- package/dist/lib/pr-land-detach.d.ts +0 -17
- package/dist/lib/pr-land-detach.js +0 -30
- package/dist/lib/pricing/cost.d.ts +0 -29
- package/dist/lib/pricing/cost.js +0 -38
- package/dist/lib/pricing/index.d.ts +0 -6
- package/dist/lib/pricing/index.js +0 -6
- package/dist/lib/pricing/table.d.ts +0 -8
- package/dist/lib/pricing/table.js +3 -56
- package/dist/lib/probe.d.ts +0 -5
- package/dist/lib/probe.js +0 -40
- package/dist/lib/profiles-presets.d.ts +0 -20
- package/dist/lib/profiles-presets.js +1 -36
- package/dist/lib/profiles.d.ts +0 -185
- package/dist/lib/profiles.js +1 -158
- package/dist/lib/project-doctor.d.ts +0 -29
- package/dist/lib/project-doctor.js +0 -26
- package/dist/lib/project-focus.d.ts +0 -41
- package/dist/lib/project-focus.js +0 -49
- package/dist/lib/project-import.d.ts +0 -41
- package/dist/lib/project-import.js +0 -36
- package/dist/lib/project-key.d.ts +0 -65
- package/dist/lib/project-key.js +0 -70
- package/dist/lib/project-launch.d.ts +0 -49
- package/dist/lib/project-launch.js +2 -91
- package/dist/lib/project-probe.d.ts +0 -86
- package/dist/lib/project-probe.js +1 -88
- package/dist/lib/project-pull.d.ts +0 -96
- package/dist/lib/project-pull.js +0 -122
- package/dist/lib/project-resources.d.ts +0 -44
- package/dist/lib/project-resources.js +7 -171
- package/dist/lib/project-root.d.ts +0 -95
- package/dist/lib/project-root.js +0 -101
- package/dist/lib/project-schedule.d.ts +0 -43
- package/dist/lib/project-schedule.js +0 -52
- package/dist/lib/project-status.d.ts +0 -108
- package/dist/lib/project-status.js +0 -117
- package/dist/lib/projects.d.ts +0 -197
- package/dist/lib/projects.js +1 -213
- package/dist/lib/pwsh.d.ts +0 -41
- package/dist/lib/pwsh.js +0 -51
- package/dist/lib/quick-todo.d.ts +84 -0
- package/dist/lib/quick-todo.js +243 -0
- package/dist/lib/reconcile-and-repair.d.ts +0 -78
- package/dist/lib/reconcile-and-repair.js +3 -66
- package/dist/lib/redact.d.ts +0 -29
- package/dist/lib/redact.js +0 -54
- package/dist/lib/refresh-coordinator.d.ts +0 -15
- package/dist/lib/refresh-coordinator.js +0 -10
- package/dist/lib/refresh.d.ts +0 -39
- package/dist/lib/refresh.js +0 -45
- package/dist/lib/registry.d.ts +0 -65
- package/dist/lib/registry.js +0 -127
- package/dist/lib/reminders.d.ts +0 -21
- package/dist/lib/reminders.js +0 -30
- package/dist/lib/remote-agents-json.d.ts +0 -44
- package/dist/lib/remote-agents-json.js +1 -44
- package/dist/lib/reserved-stores.d.ts +0 -28
- package/dist/lib/reserved-stores.js +2 -28
- package/dist/lib/resource-aliases.d.ts +0 -12
- package/dist/lib/resource-aliases.js +0 -12
- package/dist/lib/resource-content-diff.d.ts +0 -28
- package/dist/lib/resource-content-diff.js +7 -34
- package/dist/lib/resource-inventory.d.ts +0 -51
- package/dist/lib/resource-inventory.js +0 -45
- package/dist/lib/resource-patterns.d.ts +0 -32
- package/dist/lib/resource-patterns.js +0 -34
- package/dist/lib/resource-profiles.d.ts +0 -7
- package/dist/lib/resource-profiles.js +0 -11
- package/dist/lib/resources/types.d.ts +0 -50
- package/dist/lib/resources/types.js +0 -7
- package/dist/lib/resources/workflows.d.ts +0 -7
- package/dist/lib/resources/workflows.js +0 -13
- package/dist/lib/resources.d.ts +0 -65
- package/dist/lib/resources.js +0 -78
- package/dist/lib/routers.d.ts +0 -67
- package/dist/lib/routers.js +0 -60
- package/dist/lib/routine-activation.d.ts +0 -23
- package/dist/lib/routine-activation.js +0 -24
- package/dist/lib/routine-context.d.ts +1 -91
- package/dist/lib/routine-context.js +0 -107
- package/dist/lib/routine-notify-owner.d.ts +0 -79
- package/dist/lib/routine-notify-owner.js +1 -103
- package/dist/lib/routine-notify.d.ts +0 -70
- package/dist/lib/routine-notify.js +1 -75
- package/dist/lib/routine-process-cleanup.d.ts +0 -1
- package/dist/lib/routine-process-cleanup.js +1 -4
- package/dist/lib/routine-readiness.d.ts +0 -63
- package/dist/lib/routine-readiness.js +4 -86
- package/dist/lib/routines-format.d.ts +0 -40
- package/dist/lib/routines-format.js +0 -67
- package/dist/lib/routines-placement.d.ts +0 -33
- package/dist/lib/routines-placement.js +0 -40
- package/dist/lib/routines-project.d.ts +0 -57
- package/dist/lib/routines-project.js +6 -80
- package/dist/lib/rules/compile.d.ts +0 -66
- package/dist/lib/rules/compile.js +6 -118
- package/dist/lib/rules/compose.d.ts +0 -56
- package/dist/lib/rules/compose.js +2 -83
- package/dist/lib/rules/rules.d.ts +0 -23
- package/dist/lib/rules/rules.js +0 -35
- package/dist/lib/rules/run-sync.d.ts +0 -16
- package/dist/lib/rules/run-sync.js +1 -44
- package/dist/lib/run-config.d.ts +0 -7
- package/dist/lib/run-config.js +0 -8
- package/dist/lib/run-defaults.d.ts +0 -14
- package/dist/lib/run-defaults.js +0 -14
- package/dist/lib/run-notify.d.ts +0 -18
- package/dist/lib/run-notify.js +0 -36
- package/dist/lib/run-trace-sync.d.ts +0 -21
- package/dist/lib/run-trace-sync.js +2 -66
- package/dist/lib/rush-session.d.ts +0 -26
- package/dist/lib/rush-session.js +0 -28
- package/dist/lib/sandbox.d.ts +0 -45
- package/dist/lib/sandbox.js +5 -93
- package/dist/lib/scheduler.d.ts +0 -28
- package/dist/lib/scheduler.js +0 -45
- package/dist/lib/scheduling/routines.d.ts +0 -652
- package/dist/lib/scheduling/routines.js +8 -475
- package/dist/lib/secrets-cli.d.ts +3 -8
- package/dist/lib/secrets-cli.js +1 -19
- package/dist/lib/secrets-client.d.ts +0 -117
- package/dist/lib/secrets-client.js +4 -275
- package/dist/lib/secrets-policy.d.ts +0 -142
- package/dist/lib/secrets-policy.js +4 -237
- package/dist/lib/secrets-types.d.ts +0 -87
- package/dist/lib/secrets-types.js +0 -13
- package/dist/lib/self-heal/checks/hook-manifest.js +0 -25
- package/dist/lib/self-heal/checks/hook-runtime.js +0 -5
- package/dist/lib/self-heal/checks/install-staging.d.ts +0 -1
- package/dist/lib/self-heal/checks/install-staging.js +1 -28
- package/dist/lib/self-heal/checks/menubar-helper.js +0 -5
- package/dist/lib/self-heal/checks/path.js +0 -9
- package/dist/lib/self-heal/checks/resources.js +0 -5
- package/dist/lib/self-heal/checks/shadowing.js +2 -16
- package/dist/lib/self-heal/checks/shims.js +0 -14
- package/dist/lib/self-heal/child.d.ts +12 -0
- package/dist/lib/self-heal/child.js +23 -0
- package/dist/lib/self-heal/registry.d.ts +0 -9
- package/dist/lib/self-heal/registry.js +0 -16
- package/dist/lib/self-heal/types.d.ts +0 -12
- package/dist/lib/self-heal/types.js +0 -15
- package/dist/lib/self-update.d.ts +0 -312
- package/dist/lib/self-update.js +9 -360
- package/dist/lib/service-manifest.d.ts +0 -39
- package/dist/lib/service-manifest.js +0 -72
- package/dist/lib/session/active.d.ts +13 -869
- package/dist/lib/session/active.js +20 -976
- package/dist/lib/session/actor-sidecar.d.ts +1 -32
- package/dist/lib/session/actor-sidecar.js +1 -41
- package/dist/lib/session/bookmarks.d.ts +0 -33
- package/dist/lib/session/bookmarks.js +0 -37
- package/dist/lib/session/bundle.d.ts +0 -86
- package/dist/lib/session/bundle.js +0 -54
- package/dist/lib/session/claude-accounts.d.ts +0 -40
- package/dist/lib/session/claude-accounts.js +0 -49
- package/dist/lib/session/cloud.d.ts +1 -23
- package/dist/lib/session/cloud.js +0 -26
- package/dist/lib/session/db.d.ts +5 -658
- package/dist/lib/session/db.js +22 -1443
- package/dist/lib/session/detached.d.ts +0 -21
- package/dist/lib/session/detached.js +0 -29
- package/dist/lib/session/discover.d.ts +3 -420
- package/dist/lib/session/discover.js +30 -1123
- package/dist/lib/session/fork.d.ts +1 -41
- package/dist/lib/session/fork.js +0 -19
- package/dist/lib/session/ghostty-tabs.d.ts +0 -24
- package/dist/lib/session/ghostty-tabs.js +0 -37
- package/dist/lib/session/glance-files.d.ts +19 -0
- package/dist/lib/session/glance-files.js +258 -0
- package/dist/lib/session/hook-sessions.d.ts +0 -33
- package/dist/lib/session/hook-sessions.js +4 -99
- package/dist/lib/session/host-link.d.ts +1 -94
- package/dist/lib/session/host-link.js +1 -81
- package/dist/lib/session/inject-target.d.ts +8 -0
- package/dist/lib/session/inject-target.js +32 -0
- package/dist/lib/session/inject.d.ts +0 -15
- package/dist/lib/session/inject.js +0 -15
- package/dist/lib/session/live-metadata.d.ts +1 -34
- package/dist/lib/session/live-metadata.js +1 -73
- package/dist/lib/session/local-tmux-attach.d.ts +0 -37
- package/dist/lib/session/local-tmux-attach.js +1 -76
- package/dist/lib/session/migrate-targets.d.ts +0 -46
- package/dist/lib/session/migrate-targets.js +0 -24
- package/dist/lib/session/migrations.d.ts +0 -12
- package/dist/lib/session/migrations.js +1 -20
- package/dist/lib/session/mirror.d.ts +0 -32
- package/dist/lib/session/mirror.js +0 -77
- package/dist/lib/session/origin-machine.js +0 -3
- package/dist/lib/session/pid-registry.d.ts +0 -80
- package/dist/lib/session/pid-registry.js +2 -81
- package/dist/lib/session/presence.d.ts +0 -39
- package/dist/lib/session/presence.js +2 -52
- package/dist/lib/session/process-view.d.ts +0 -11
- package/dist/lib/session/process-view.js +0 -25
- package/dist/lib/session/projection.d.ts +0 -3
- package/dist/lib/session/projection.js +0 -10
- package/dist/lib/session/provenance.d.ts +1 -37
- package/dist/lib/session/provenance.js +0 -69
- package/dist/lib/session/recovery.d.ts +1 -40
- package/dist/lib/session/recovery.js +2 -80
- package/dist/lib/session/relative-time.js +0 -3
- package/dist/lib/session/remote/peer-stream.d.ts +0 -42
- package/dist/lib/session/remote/peer-stream.js +0 -64
- package/dist/lib/session/remote/remote-bundle.d.ts +0 -6
- package/dist/lib/session/remote/remote-bundle.js +0 -21
- package/dist/lib/session/remote/remote-list.d.ts +1 -110
- package/dist/lib/session/remote/remote-list.js +5 -139
- package/dist/lib/session/remote/remote.d.ts +0 -98
- package/dist/lib/session/remote/remote.js +3 -119
- package/dist/lib/session/remote/watch.d.ts +1 -34
- package/dist/lib/session/remote/watch.js +12 -72
- package/dist/lib/session/remote-active.d.ts +0 -35
- package/dist/lib/session/remote-active.js +0 -48
- package/dist/lib/session/remote-bundle.js +0 -2
- package/dist/lib/session/remote-list.js +0 -2
- package/dist/lib/session/remote-preview-cache.d.ts +0 -7
- package/dist/lib/session/remote-preview-cache.js +1 -76
- package/dist/lib/session/remote.js +0 -2
- package/dist/lib/session/resume-command.d.ts +0 -6
- package/dist/lib/session/resume-command.js +0 -6
- package/dist/lib/session/resume-owner.d.ts +1 -52
- package/dist/lib/session/resume-owner.js +0 -56
- package/dist/lib/session/run-names.d.ts +0 -24
- package/dist/lib/session/run-names.js +0 -26
- package/dist/lib/session/session-cache.d.ts +2 -146
- package/dist/lib/session/session-cache.js +26 -203
- package/dist/lib/session/short-id.js +0 -3
- package/dist/lib/session/sync/agents.d.ts +0 -68
- package/dist/lib/session/sync/agents.js +0 -0
- package/dist/lib/session/sync/backend.d.ts +0 -39
- package/dist/lib/session/sync/backend.js +0 -45
- package/dist/lib/session/sync/config.d.ts +0 -27
- package/dist/lib/session/sync/config.js +0 -56
- package/dist/lib/session/sync/managed-config.d.ts +0 -17
- package/dist/lib/session/sync/managed-config.js +0 -17
- package/dist/lib/session/sync/managed-key.d.ts +0 -38
- package/dist/lib/session/sync/managed-key.js +1 -42
- package/dist/lib/session/sync/net-client.d.ts +0 -36
- package/dist/lib/session/sync/net-client.js +0 -30
- package/dist/lib/session/sync/provision.d.ts +0 -2
- package/dist/lib/session/sync/provision.js +0 -13
- package/dist/lib/session/sync/r2.d.ts +0 -20
- package/dist/lib/session/sync/r2.js +0 -20
- package/dist/lib/session/sync/transcript-crypto.d.ts +0 -37
- package/dist/lib/session/sync/transcript-crypto.js +5 -37
- package/dist/lib/session/sync/worker-template.d.ts +0 -5
- package/dist/lib/session/sync/worker-template.js +0 -40
- package/dist/lib/session/testdata/pid-registry-namespace.js +0 -2
- package/dist/lib/session/testdata/process-view-private.js +0 -1
- package/dist/lib/session/throughput.d.ts +0 -24
- package/dist/lib/session/throughput.js +1 -25
- package/dist/lib/session/timeline-pass.d.ts +1 -63
- package/dist/lib/session/timeline-pass.js +161 -148
- package/dist/lib/session/title.d.ts +0 -182
- package/dist/lib/session/title.js +0 -139
- package/dist/lib/session/tool-index.d.ts +2 -21
- package/dist/lib/session/tool-index.js +3 -75
- package/dist/lib/session/tool-store.d.ts +2 -48
- package/dist/lib/session/tool-store.js +1 -33
- package/dist/lib/session/viewing-in.d.ts +0 -67
- package/dist/lib/session/viewing-in.js +1 -71
- package/dist/lib/session/watch.js +0 -2
- package/dist/lib/session/width.js +0 -3
- package/dist/lib/sessions-client.d.ts +0 -46
- package/dist/lib/sessions-client.js +36 -113
- package/dist/lib/settings-manifest.d.ts +1 -17
- package/dist/lib/settings-manifest.js +4 -57
- package/dist/lib/setup-tool-install.d.ts +0 -1
- package/dist/lib/setup-tool-install.js +2 -7
- package/dist/lib/setup-tool-status.d.ts +0 -3
- package/dist/lib/setup-tool-status.js +4 -14
- package/dist/lib/sha256-asset.d.ts +0 -20
- package/dist/lib/sha256-asset.js +0 -20
- package/dist/lib/share-runtime.d.ts +0 -10
- package/dist/lib/share-runtime.js +1 -27
- package/dist/lib/shim-heal.d.ts +0 -15
- package/dist/lib/shim-heal.js +3 -29
- package/dist/lib/signin-badge.d.ts +0 -72
- package/dist/lib/signin-badge.js +0 -86
- package/dist/lib/sink-format.d.ts +0 -32
- package/dist/lib/sink-format.js +0 -14
- package/dist/lib/smart-launch.d.ts +0 -75
- package/dist/lib/smart-launch.js +1 -83
- package/dist/lib/snapshot.d.ts +0 -46
- package/dist/lib/snapshot.js +5 -31
- package/dist/lib/spinner.d.ts +0 -37
- package/dist/lib/spinner.js +0 -37
- package/dist/lib/sqlite.d.ts +0 -13
- package/dist/lib/sqlite.js +3 -71
- package/dist/lib/ssh-exec.d.ts +0 -209
- package/dist/lib/ssh-exec.js +11 -248
- package/dist/lib/ssh-tunnel.d.ts +0 -43
- package/dist/lib/ssh-tunnel.js +2 -48
- package/dist/lib/staleness/checkers/commands.d.ts +0 -4
- package/dist/lib/staleness/checkers/commands.js +0 -4
- package/dist/lib/staleness/checkers/hooks.d.ts +0 -10
- package/dist/lib/staleness/checkers/hooks.js +0 -15
- package/dist/lib/staleness/checkers/mcp.d.ts +0 -9
- package/dist/lib/staleness/checkers/mcp.js +0 -9
- package/dist/lib/staleness/checkers/permissions.d.ts +0 -12
- package/dist/lib/staleness/checkers/permissions.js +0 -13
- package/dist/lib/staleness/checkers/plugins.d.ts +0 -8
- package/dist/lib/staleness/checkers/plugins.js +0 -8
- package/dist/lib/staleness/checkers/rules.d.ts +0 -15
- package/dist/lib/staleness/checkers/rules.js +0 -26
- package/dist/lib/staleness/checkers/skills.d.ts +0 -4
- package/dist/lib/staleness/checkers/skills.js +0 -4
- package/dist/lib/staleness/checkers/subagents.d.ts +0 -9
- package/dist/lib/staleness/checkers/subagents.js +0 -9
- package/dist/lib/staleness/checkers/types.d.ts +0 -34
- package/dist/lib/staleness/checkers/types.js +0 -19
- package/dist/lib/staleness/checkers/workflows.d.ts +0 -7
- package/dist/lib/staleness/checkers/workflows.js +0 -7
- package/dist/lib/staleness/detectors/commands.js +0 -17
- package/dist/lib/staleness/detectors/hooks.js +1 -6
- package/dist/lib/staleness/detectors/mcp.js +0 -4
- package/dist/lib/staleness/detectors/permissions.js +10 -23
- package/dist/lib/staleness/detectors/rules.js +0 -6
- package/dist/lib/staleness/detectors/skills.d.ts +0 -1
- package/dist/lib/staleness/detectors/skills.js +1 -12
- package/dist/lib/staleness/detectors/types.d.ts +0 -10
- package/dist/lib/staleness/fingerprint.d.ts +0 -19
- package/dist/lib/staleness/fingerprint.js +0 -35
- package/dist/lib/staleness/index.d.ts +0 -28
- package/dist/lib/staleness/index.js +1 -45
- package/dist/lib/staleness/layers.d.ts +0 -23
- package/dist/lib/staleness/layers.js +0 -34
- package/dist/lib/staleness/prune.d.ts +0 -71
- package/dist/lib/staleness/prune.js +2 -27
- package/dist/lib/staleness/registry.d.ts +0 -10
- package/dist/lib/staleness/registry.js +3 -33
- package/dist/lib/staleness/types.d.ts +0 -36
- package/dist/lib/staleness/types.js +0 -5
- package/dist/lib/staleness/writers/commands.js +1 -48
- package/dist/lib/staleness/writers/hooks.js +1 -18
- package/dist/lib/staleness/writers/kinds.d.ts +0 -12
- package/dist/lib/staleness/writers/kinds.js +0 -1
- package/dist/lib/staleness/writers/lazy-map.d.ts +0 -11
- package/dist/lib/staleness/writers/mcp.js +0 -13
- package/dist/lib/staleness/writers/plugins.js +0 -4
- package/dist/lib/staleness/writers/rules.d.ts +0 -1
- package/dist/lib/staleness/writers/rules.js +1 -19
- package/dist/lib/staleness/writers/skills.js +3 -14
- package/dist/lib/staleness/writers/sources.d.ts +0 -11
- package/dist/lib/staleness/writers/sources.js +0 -32
- package/dist/lib/staleness/writers/subagents.js +0 -16
- package/dist/lib/staleness/writers/types.d.ts +0 -58
- package/dist/lib/staleness/writers/workflows.js +1 -1
- package/dist/lib/standalone-tools.d.ts +24 -0
- package/dist/lib/standalone-tools.js +58 -0
- package/dist/lib/star-nudge.d.ts +0 -32
- package/dist/lib/star-nudge.js +2 -36
- package/dist/lib/startup/command-registry.d.ts +0 -45
- package/dist/lib/startup/command-registry.js +1 -46
- package/dist/lib/startup/dev-build.d.ts +0 -9
- package/dist/lib/startup/dev-build.js +1 -42
- package/dist/lib/startup/root-command.d.ts +0 -19
- package/dist/lib/startup/root-command.js +0 -19
- package/dist/lib/startup/spellcheck.d.ts +0 -13
- package/dist/lib/startup/spellcheck.js +0 -13
- package/dist/lib/state.d.ts +0 -376
- package/dist/lib/state.js +19 -737
- package/dist/lib/storage/selection.d.ts +0 -40
- package/dist/lib/storage/selection.js +0 -29
- package/dist/lib/subagents-registry.d.ts +0 -56
- package/dist/lib/subagents-registry.js +0 -99
- package/dist/lib/subagents.d.ts +0 -128
- package/dist/lib/subagents.js +1 -158
- package/dist/lib/summarizer/config.d.ts +0 -37
- package/dist/lib/summarizer/config.js +0 -37
- package/dist/lib/summarizer/pass.d.ts +0 -20
- package/dist/lib/summarizer/pass.js +1 -34
- package/dist/lib/summarizer/summarize.d.ts +1 -49
- package/dist/lib/summarizer/summarize.js +0 -35
- package/dist/lib/sync-passphrase.d.ts +0 -16
- package/dist/lib/sync-passphrase.js +1 -18
- package/dist/lib/sync-status.d.ts +0 -72
- package/dist/lib/sync-status.js +0 -55
- package/dist/lib/sync-umbrella.d.ts +0 -54
- package/dist/lib/sync-umbrella.js +0 -48
- package/dist/lib/system-run-sync.d.ts +0 -5
- package/dist/lib/system-run-sync.js +1 -31
- package/dist/lib/teams/agents.d.ts +1 -444
- package/dist/lib/teams/agents.js +11 -871
- package/dist/lib/teams/api.d.ts +2 -52
- package/dist/lib/teams/api.js +4 -63
- package/dist/lib/teams/debug.d.ts +0 -6
- package/dist/lib/teams/debug.js +0 -6
- package/dist/lib/teams/delivery.d.ts +0 -41
- package/dist/lib/teams/delivery.js +0 -32
- package/dist/lib/teams/file_ops.d.ts +0 -11
- package/dist/lib/teams/file_ops.js +0 -11
- package/dist/lib/teams/forEach.d.ts +0 -76
- package/dist/lib/teams/forEach.js +1 -77
- package/dist/lib/teams/index.d.ts +1 -7
- package/dist/lib/teams/index.js +1 -7
- package/dist/lib/teams/parsers.d.ts +0 -4
- package/dist/lib/teams/parsers.js +0 -81
- package/dist/lib/teams/persistence.d.ts +0 -2
- package/dist/lib/teams/persistence.js +0 -12
- package/dist/lib/teams/placement-probe.d.ts +0 -12
- package/dist/lib/teams/placement-probe.js +1 -51
- package/dist/lib/teams/pr-watch.d.ts +0 -107
- package/dist/lib/teams/pr-watch.js +1 -107
- package/dist/lib/teams/registry.d.ts +0 -36
- package/dist/lib/teams/registry.js +0 -47
- package/dist/lib/teams/remoteWorktree.d.ts +0 -50
- package/dist/lib/teams/remoteWorktree.js +1 -96
- package/dist/lib/teams/scheduler.d.ts +0 -111
- package/dist/lib/teams/scheduler.js +2 -125
- package/dist/lib/teams/summarizer.d.ts +0 -22
- package/dist/lib/teams/summarizer.js +6 -50
- package/dist/lib/teams/supervisor.d.ts +0 -38
- package/dist/lib/teams/supervisor.js +0 -21
- package/dist/lib/teams/worktree.d.ts +0 -95
- package/dist/lib/teams/worktree.js +3 -110
- package/dist/lib/template.d.ts +0 -21
- package/dist/lib/template.js +0 -23
- package/dist/lib/term-client.d.ts +0 -26
- package/dist/lib/term-client.js +0 -48
- package/dist/lib/term-driver.d.ts +0 -5
- package/dist/lib/term-driver.js +0 -8
- package/dist/lib/terminal/backends/ghostty.d.ts +0 -2
- package/dist/lib/terminal/backends/ghostty.js +0 -12
- package/dist/lib/terminal/backends/index.d.ts +0 -17
- package/dist/lib/terminal/backends/index.js +0 -15
- package/dist/lib/terminal/backends/iterm.d.ts +0 -2
- package/dist/lib/terminal/backends/iterm.js +0 -10
- package/dist/lib/terminal/backends/terminal-app.d.ts +0 -10
- package/dist/lib/terminal/backends/terminal-app.js +0 -30
- package/dist/lib/terminal/backends/tmux.d.ts +0 -10
- package/dist/lib/terminal/backends/tmux.js +0 -2
- package/dist/lib/terminal/backends/vscodium-agent.d.ts +0 -25
- package/dist/lib/terminal/backends/vscodium-agent.js +0 -36
- package/dist/lib/terminal/engine.d.ts +0 -17
- package/dist/lib/terminal/engine.js +0 -10
- package/dist/lib/terminal/index.d.ts +0 -8
- package/dist/lib/terminal/inject.d.ts +1 -173
- package/dist/lib/terminal/inject.js +0 -146
- package/dist/lib/terminal/policy.d.ts +0 -8
- package/dist/lib/terminal/policy.js +0 -1
- package/dist/lib/terminal/preferred.d.ts +0 -66
- package/dist/lib/terminal/preferred.js +0 -30
- package/dist/lib/terminal/quote.d.ts +0 -8
- package/dist/lib/terminal/quote.js +0 -8
- package/dist/lib/terminal/resolve.d.ts +0 -46
- package/dist/lib/terminal/resolve.js +0 -30
- package/dist/lib/terminal/run-surface.d.ts +0 -56
- package/dist/lib/terminal/run-surface.js +0 -46
- package/dist/lib/terminal/shell.d.ts +0 -3
- package/dist/lib/terminal/shell.js +0 -13
- package/dist/lib/terminal/transport.d.ts +0 -14
- package/dist/lib/terminal/transport.js +1 -30
- package/dist/lib/terminal/types.d.ts +0 -40
- package/dist/lib/terminal/types.js +0 -10
- package/dist/lib/text/relative-time.d.ts +0 -36
- package/dist/lib/text/relative-time.js +0 -43
- package/dist/lib/text/short-id.d.ts +0 -16
- package/dist/lib/text/short-id.js +0 -16
- package/dist/lib/text/width.d.ts +0 -24
- package/dist/lib/text/width.js +10 -52
- package/dist/lib/tmux/binary.d.ts +0 -36
- package/dist/lib/tmux/binary.js +0 -28
- package/dist/lib/tmux/index.d.ts +0 -5
- package/dist/lib/tmux/index.js +0 -5
- package/dist/lib/tmux/orphan-reap.d.ts +0 -253
- package/dist/lib/tmux/orphan-reap.js +3 -299
- package/dist/lib/tmux/paths.d.ts +0 -14
- package/dist/lib/tmux/paths.js +0 -14
- package/dist/lib/tmux/session.d.ts +0 -263
- package/dist/lib/tmux/session.js +6 -344
- package/dist/lib/traces/backend.d.ts +0 -20
- package/dist/lib/traces/backend.js +0 -23
- package/dist/lib/traces/classify.d.ts +0 -20
- package/dist/lib/traces/classify.js +0 -7
- package/dist/lib/traces/insights.d.ts +1 -84
- package/dist/lib/traces/insights.js +0 -126
- package/dist/lib/traces/phenotype.d.ts +0 -69
- package/dist/lib/traces/phenotype.js +0 -150
- package/dist/lib/traces/provision.d.ts +0 -1
- package/dist/lib/traces/provision.js +0 -5
- package/dist/lib/traces/schema2-build.d.ts +3 -60
- package/dist/lib/traces/schema2-build.js +8 -149
- package/dist/lib/traces/schema2-danger.d.ts +0 -30
- package/dist/lib/traces/schema2-danger.js +1 -63
- package/dist/lib/traces/schema2.d.ts +0 -11
- package/dist/lib/traces/segments.d.ts +0 -44
- package/dist/lib/traces/segments.js +0 -65
- package/dist/lib/traces/sync.d.ts +2 -239
- package/dist/lib/traces/sync.js +15 -237
- package/dist/lib/traces/worker-template.d.ts +0 -3
- package/dist/lib/traces/worker-template.js +0 -29
- package/dist/lib/triggers/handlers.d.ts +0 -82
- package/dist/lib/triggers/handlers.js +0 -75
- package/dist/lib/triggers/webhook.d.ts +0 -158
- package/dist/lib/triggers/webhook.js +0 -143
- package/dist/lib/types.d.ts +0 -736
- package/dist/lib/types.js +0 -50
- package/dist/lib/uninstall.d.ts +0 -17
- package/dist/lib/uninstall.js +0 -75
- package/dist/lib/usage-backoff.d.ts +0 -20
- package/dist/lib/usage-backoff.js +3 -60
- package/dist/lib/usage-refresh.d.ts +0 -154
- package/dist/lib/usage-refresh.js +8 -212
- package/dist/lib/verbs.d.ts +0 -12
- package/dist/lib/verbs.js +0 -12
- package/dist/lib/version-duplicates.d.ts +0 -6
- package/dist/lib/version-duplicates.js +0 -6
- package/dist/lib/version.d.ts +0 -55
- package/dist/lib/version.js +1 -58
- package/dist/lib/view-types.d.ts +0 -48
- package/dist/lib/warn-unpushed.d.ts +0 -27
- package/dist/lib/warn-unpushed.js +1 -45
- package/dist/lib/watchdog/history.d.ts +0 -1
- package/dist/lib/watchdog/history.js +0 -3
- package/dist/lib/watchdog/index.js +0 -2
- package/dist/lib/watchdog/log.d.ts +0 -19
- package/dist/lib/watchdog/log.js +0 -34
- package/dist/lib/watchdog/read.d.ts +0 -27
- package/dist/lib/watchdog/read.js +3 -58
- package/dist/lib/watchdog/rotate.d.ts +0 -139
- package/dist/lib/watchdog/rotate.js +2 -151
- package/dist/lib/watchdog/runner.d.ts +0 -125
- package/dist/lib/watchdog/runner.js +3 -223
- package/dist/lib/watchdog/service.d.ts +0 -1
- package/dist/lib/watchdog/service.js +0 -2
- package/dist/lib/watchdog/watchdog-agent.d.ts +0 -31
- package/dist/lib/watchdog/watchdog-agent.js +0 -27
- package/dist/lib/watchdog/watchdog.d.ts +0 -7
- package/dist/lib/watchdog/watchdog.js +0 -10
- package/dist/lib/watchdog/watchdogTail.js +0 -7
- package/dist/lib/whats-new.d.ts +0 -10
- package/dist/lib/whats-new.js +0 -21
- package/dist/lib/workflows-registry.d.ts +0 -45
- package/dist/lib/workflows-registry.js +0 -60
- package/dist/lib/workflows.d.ts +0 -282
- package/dist/lib/workflows.js +3 -213
- package/dist/lib/worktree/held.d.ts +0 -89
- package/dist/lib/worktree/held.js +1 -103
- package/dist/lib/wrap.d.ts +0 -32
- package/dist/lib/wrap.js +0 -32
- package/dist/lib/yaml-io.d.ts +0 -45
- package/dist/lib/yaml-io.js +0 -47
- package/dist/session-tracker/dist/adapters/claude.js +0 -2
- package/dist/session-tracker/dist/hook.sh +4 -37
- package/dist/session-tracker/dist/index.d.ts +0 -7
- package/dist/session-tracker/dist/index.js +0 -5
- package/dist/session-tracker/dist/install-hook.d.ts +0 -5
- package/dist/session-tracker/dist/install-hook.js +1 -15
- package/dist/session-tracker/dist/prune-state.js +0 -4
- package/dist/session-tracker/dist/reader.js +0 -4
- package/dist/session-tracker/dist/state-file.d.ts +0 -3
- package/dist/session-tracker/dist/state-file.js +3 -8
- package/package.json +3 -4
- package/scripts/postinstall.js +8 -116
- package/dist/lib/session/artifacts.d.ts +0 -14
- package/dist/lib/session/artifacts.js +0 -101
- package/dist/lib/session/bash-command.d.ts +0 -63
- package/dist/lib/session/bash-command.js +0 -490
- package/dist/lib/session/digest.d.ts +0 -66
- package/dist/lib/session/digest.js +0 -328
- package/dist/lib/session/highlights.d.ts +0 -151
- package/dist/lib/session/highlights.js +0 -391
- package/dist/lib/session/insights.d.ts +0 -165
- package/dist/lib/session/insights.js +0 -563
- package/dist/lib/session/linear.d.ts +0 -19
- package/dist/lib/session/linear.js +0 -99
- package/dist/lib/session/parse.d.ts +0 -224
- package/dist/lib/session/parse.js +0 -2408
- package/dist/lib/session/prompt.d.ts +0 -213
- package/dist/lib/session/prompt.js +0 -601
- package/dist/lib/session/render.d.ts +0 -133
- package/dist/lib/session/render.js +0 -1047
- package/dist/lib/session/share-html.d.ts +0 -35
- package/dist/lib/session/share-html.js +0 -319
- package/dist/lib/session/shell-programs.d.ts +0 -33
- package/dist/lib/session/shell-programs.js +0 -380
- package/dist/lib/session/state.d.ts +0 -269
- package/dist/lib/session/state.js +0 -777
- package/dist/lib/session/stream-render.d.ts +0 -4
- package/dist/lib/session/stream-render.js +0 -131
- package/dist/lib/session/tail.d.ts +0 -88
- package/dist/lib/session/tail.js +0 -294
- package/dist/lib/session/team-filter.d.ts +0 -129
- package/dist/lib/session/team-filter.js +0 -269
- package/dist/lib/session/timeline.d.ts +0 -172
- package/dist/lib/session/timeline.js +0 -636
- package/dist/lib/session/tool-calls.d.ts +0 -132
- package/dist/lib/session/tool-calls.js +0 -674
- package/dist/lib/session/trajectory-compare.d.ts +0 -48
- package/dist/lib/session/trajectory-compare.js +0 -116
- package/dist/lib/session/trajectory-html.d.ts +0 -19
- package/dist/lib/session/trajectory-html.js +0 -771
- package/dist/lib/session/trajectory-lineage.d.ts +0 -93
- package/dist/lib/session/trajectory-lineage.js +0 -195
- package/dist/lib/session/trajectory-text.d.ts +0 -38
- package/dist/lib/session/trajectory-text.js +0 -284
- package/dist/lib/session/trajectory.d.ts +0 -145
- package/dist/lib/session/trajectory.js +0 -394
- package/dist/lib/session/types.d.ts +0 -627
- package/dist/lib/session/types.js +0 -43
|
@@ -1,2408 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Session file parsers for Claude, Codex, Gemini, and OpenCode.
|
|
3
|
-
*
|
|
4
|
-
* Each agent stores sessions in a different format (JSONL, JSON, SQLite).
|
|
5
|
-
* This module normalizes all of them into a flat array of SessionEvent
|
|
6
|
-
* objects suitable for rendering, filtering, and summarization.
|
|
7
|
-
*/
|
|
8
|
-
import * as fs from 'fs';
|
|
9
|
-
import { truncate } from '../format.js';
|
|
10
|
-
import { sanitizeForTerminal } from '../redact.js';
|
|
11
|
-
import * as path from 'path';
|
|
12
|
-
import Database from '../sqlite.js';
|
|
13
|
-
import { isSyntheticUserMessage, extractSlashCommandName, extractSlashCommandFromToolInput, unwrapUserQuery } from './prompt.js';
|
|
14
|
-
import { structuredToolResult, commandsFromCodexExec } from './tool-calls.js';
|
|
15
|
-
import { isCloudSessionPath } from './cloud.js';
|
|
16
|
-
/**
|
|
17
|
-
* Largest session file we will load into memory. Above this we throw a clean
|
|
18
|
-
* error instead of OOMing or hitting V8's ERR_STRING_TOO_LONG. Aligns with
|
|
19
|
-
* Node's ~512MB string ceiling with a healthy margin.
|
|
20
|
-
*/
|
|
21
|
-
export const SESSION_FILE_MAX_BYTES = 200_000_000;
|
|
22
|
-
/**
|
|
23
|
-
* Strip terminal control sequences that a malicious session file could use to
|
|
24
|
-
* hijack the user's terminal (clipboard via OSC 52, scrollback wipe, alt-screen
|
|
25
|
-
* takeover, cursor moves, etc.). Allowed through: tab (0x09), newline (0x0a),
|
|
26
|
-
* carriage return (0x0d). Everything else in the C0/C1 range and every CSI/OSC
|
|
27
|
-
* escape is dropped.
|
|
28
|
-
*/
|
|
29
|
-
export { sanitizeForTerminal } from '../redact.js';
|
|
30
|
-
/** Recursively sanitize every string value within a tool-args object. */
|
|
31
|
-
function sanitizeArgsDeep(value) {
|
|
32
|
-
if (typeof value === 'string')
|
|
33
|
-
return sanitizeForTerminal(value);
|
|
34
|
-
if (Array.isArray(value))
|
|
35
|
-
return value.map(sanitizeArgsDeep);
|
|
36
|
-
if (value && typeof value === 'object') {
|
|
37
|
-
const out = {};
|
|
38
|
-
for (const k of Object.keys(value))
|
|
39
|
-
out[k] = sanitizeArgsDeep(value[k]);
|
|
40
|
-
return out;
|
|
41
|
-
}
|
|
42
|
-
return value;
|
|
43
|
-
}
|
|
44
|
-
/** In-place sanitize every user-visible string field on a list of events. */
|
|
45
|
-
export function sanitizeEvents(events) {
|
|
46
|
-
for (const e of events)
|
|
47
|
-
sanitizeEvent(e);
|
|
48
|
-
}
|
|
49
|
-
/** In-place sanitize all user-visible string fields on an event. */
|
|
50
|
-
function sanitizeEvent(e) {
|
|
51
|
-
if (e.content)
|
|
52
|
-
e.content = sanitizeForTerminal(e.content);
|
|
53
|
-
if (e.command)
|
|
54
|
-
e.command = sanitizeForTerminal(e.command);
|
|
55
|
-
if (e.path)
|
|
56
|
-
e.path = sanitizeForTerminal(e.path);
|
|
57
|
-
if (e.name)
|
|
58
|
-
e.name = sanitizeForTerminal(e.name);
|
|
59
|
-
if (e.output)
|
|
60
|
-
e.output = sanitizeForTerminal(e.output);
|
|
61
|
-
if (e.tool)
|
|
62
|
-
e.tool = sanitizeForTerminal(e.tool);
|
|
63
|
-
if (e.model)
|
|
64
|
-
e.model = sanitizeForTerminal(e.model);
|
|
65
|
-
if (e.mediaType)
|
|
66
|
-
e.mediaType = sanitizeForTerminal(e.mediaType);
|
|
67
|
-
if (e.hookName)
|
|
68
|
-
e.hookName = sanitizeForTerminal(e.hookName);
|
|
69
|
-
if (e.hookEvent)
|
|
70
|
-
e.hookEvent = sanitizeForTerminal(e.hookEvent);
|
|
71
|
-
// The harness's own per-call label and turn phase are free text from the same
|
|
72
|
-
// untrusted transcript, and the timeline ships them straight to a terminal.
|
|
73
|
-
if (e.label)
|
|
74
|
-
e.label = sanitizeForTerminal(e.label);
|
|
75
|
-
if (e.phase)
|
|
76
|
-
e.phase = sanitizeForTerminal(e.phase);
|
|
77
|
-
if (e.args)
|
|
78
|
-
e.args = sanitizeArgsDeep(e.args);
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Did this Claude tool_result record fail, or was it never allowed to run?
|
|
82
|
-
*
|
|
83
|
-
* Two distinct signals, both on the record ENCLOSING the `tool_result` block:
|
|
84
|
-
* `toolDenialKind` when a permission rule or hook refused the call, and
|
|
85
|
-
* `toolUseResult.interrupted` when the operator cut it short with Ctrl-C.
|
|
86
|
-
* Neither is a failure of the work, so both land on `blocked`, which is what
|
|
87
|
-
* separates "this agent is failing" from "this agent is being stopped".
|
|
88
|
-
*/
|
|
89
|
-
function isBlockedToolResult(raw) {
|
|
90
|
-
if (typeof raw?.toolDenialKind === 'string' && raw.toolDenialKind)
|
|
91
|
-
return true;
|
|
92
|
-
return raw?.toolUseResult?.interrupted === true;
|
|
93
|
-
}
|
|
94
|
-
function firstString(...values) {
|
|
95
|
-
for (const value of values) {
|
|
96
|
-
if (typeof value === 'string' && value.trim())
|
|
97
|
-
return value.trim();
|
|
98
|
-
}
|
|
99
|
-
return undefined;
|
|
100
|
-
}
|
|
101
|
-
function attachmentPath(block, source) {
|
|
102
|
-
return firstString(source?.path, source?.file_path, source?.filePath, source?.url, source?.ref, block?.path, block?.file_path, block?.filePath, block?.ref);
|
|
103
|
-
}
|
|
104
|
-
function attachmentName(block, source, filePath) {
|
|
105
|
-
return firstString(block?.name, block?.title, source?.name, source?.filename, source?.file_name, source?.fileName, filePath ? path.basename(filePath) : undefined);
|
|
106
|
-
}
|
|
107
|
-
function normalizedAttachmentEvent(agent, timestamp, block, source, defaultMediaType, sizeBytes) {
|
|
108
|
-
const filePath = attachmentPath(block, source);
|
|
109
|
-
const name = attachmentName(block, source, filePath);
|
|
110
|
-
const explicitSize = typeof source?.sizeBytes === 'number' ? source.sizeBytes :
|
|
111
|
-
typeof source?.size === 'number' ? source.size :
|
|
112
|
-
typeof block?.sizeBytes === 'number' ? block.sizeBytes :
|
|
113
|
-
undefined;
|
|
114
|
-
return {
|
|
115
|
-
type: 'attachment',
|
|
116
|
-
agent,
|
|
117
|
-
timestamp,
|
|
118
|
-
path: filePath,
|
|
119
|
-
name,
|
|
120
|
-
mediaType: firstString(source?.media_type, source?.mediaType, block?.media_type, block?.mediaType) || defaultMediaType,
|
|
121
|
-
sizeBytes: sizeBytes || explicitSize || 0,
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
/**
|
|
125
|
-
* Read a session file, refusing files above maxBytes. Bounded read protects
|
|
126
|
-
* against multi-GB session blobs that would OOM the CLI or exceed V8's
|
|
127
|
-
* ERR_STRING_TOO_LONG ceiling.
|
|
128
|
-
*/
|
|
129
|
-
export function safeReadSessionFile(filePath, maxBytes = SESSION_FILE_MAX_BYTES) {
|
|
130
|
-
const stat = fs.statSync(filePath);
|
|
131
|
-
if (stat.size > maxBytes) {
|
|
132
|
-
throw new Error(`Session file too large: ${filePath} is ${stat.size} bytes (limit ${maxBytes}). Refusing to load.`);
|
|
133
|
-
}
|
|
134
|
-
return fs.readFileSync(filePath, 'utf-8');
|
|
135
|
-
}
|
|
136
|
-
function truncateNormalizedToolOutput(output, maxChars) {
|
|
137
|
-
if (!Number.isFinite(maxChars) || output.length <= maxChars)
|
|
138
|
-
return output;
|
|
139
|
-
return `${output.slice(0, maxChars)}\n\n[Output truncated: ${output.length - maxChars} characters omitted.]`;
|
|
140
|
-
}
|
|
141
|
-
/** Separate from HarnessAdapter because offline transcripts include session-only agents such as Rush. */
|
|
142
|
-
const TRANSCRIPT_PARSERS = {
|
|
143
|
-
claude: (filePath, opts) => parseClaude(filePath, opts),
|
|
144
|
-
codex: (filePath) => parseCodex(filePath),
|
|
145
|
-
antigravity: (filePath) => parseAntigravity(filePath),
|
|
146
|
-
// Cloud-captured opencode sessions are normalized JSONL (produced by the
|
|
147
|
-
// factory at capture time), NOT the local `opencode.db#<session>` SQLite
|
|
148
|
-
// composite the offline parser reads — route by whether the path is in the
|
|
149
|
-
// cloud session cache (PHNX-3845).
|
|
150
|
-
opencode: (filePath) => isCloudSessionPath(filePath) ? parseOpencodeCloud(filePath) : parseOpenCode(filePath),
|
|
151
|
-
grok: (filePath) => parseGrok(filePath),
|
|
152
|
-
rush: (filePath) => parseRush(filePath),
|
|
153
|
-
openclaw: () => [], // OpenClaw sessions don't have parseable files yet
|
|
154
|
-
hermes: (filePath) => parseHermes(filePath),
|
|
155
|
-
kimi: (filePath) => parseKimi(filePath),
|
|
156
|
-
droid: (filePath) => parseDroid(filePath),
|
|
157
|
-
cursor: (filePath) => parseCursor(filePath),
|
|
158
|
-
muse: (filePath) => parseMuse(filePath),
|
|
159
|
-
};
|
|
160
|
-
export function parseSession(filePath, agent, opts = {}) {
|
|
161
|
-
const detected = agent || detectAgent(filePath);
|
|
162
|
-
if (!detected) {
|
|
163
|
-
throw new Error(`Cannot detect agent type from path: ${filePath}`);
|
|
164
|
-
}
|
|
165
|
-
const events = TRANSCRIPT_PARSERS[detected](filePath, opts);
|
|
166
|
-
// Sanitize untrusted strings and identify synthetic user scaffolding once for every consumer.
|
|
167
|
-
const maxToolOutputChars = opts.maxToolOutputChars ?? 500;
|
|
168
|
-
for (const e of events) {
|
|
169
|
-
if (e.type === 'tool_result' && e.output) {
|
|
170
|
-
e.output = truncateNormalizedToolOutput(e.output, maxToolOutputChars);
|
|
171
|
-
}
|
|
172
|
-
sanitizeEvent(e);
|
|
173
|
-
if (e.type === 'message' && e.role === 'user' && isSyntheticUserMessage(e.content)) {
|
|
174
|
-
e._synthetic = true;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
return events;
|
|
178
|
-
}
|
|
179
|
-
/** Infer the agent type from a session file path using known directory conventions. */
|
|
180
|
-
export function detectAgent(filePath) {
|
|
181
|
-
if (filePath.includes('/.claude/') || filePath.includes('\\.claude\\'))
|
|
182
|
-
return 'claude';
|
|
183
|
-
if (filePath.includes('/.codex/') || filePath.includes('\\.codex\\'))
|
|
184
|
-
return 'codex';
|
|
185
|
-
// Antigravity lives under ~/.gemini/antigravity-cli/conversations/<uuid>.db.
|
|
186
|
-
if ((filePath.includes('/antigravity-cli/conversations/') || filePath.includes('\\antigravity-cli\\conversations\\'))
|
|
187
|
-
&& filePath.endsWith('.db'))
|
|
188
|
-
return 'antigravity';
|
|
189
|
-
if (filePath.includes('/.grok/') || filePath.includes('\\.grok\\'))
|
|
190
|
-
return 'grok';
|
|
191
|
-
if (filePath.includes('/.rush/') || filePath.includes('\\.rush\\'))
|
|
192
|
-
return 'rush';
|
|
193
|
-
if (filePath.includes('/.hermes/') || filePath.includes('\\.hermes\\'))
|
|
194
|
-
return 'hermes';
|
|
195
|
-
if (filePath.includes('/.kimi-code/') || filePath.includes('\\.kimi-code\\'))
|
|
196
|
-
return 'kimi';
|
|
197
|
-
if (filePath.includes('/.factory/') || filePath.includes('\\.factory\\'))
|
|
198
|
-
return 'droid';
|
|
199
|
-
if (filePath.includes('/.cursor/') || filePath.includes('\\.cursor\\'))
|
|
200
|
-
return 'cursor';
|
|
201
|
-
// Muse sessions: ~/.local/share/muse/sessions/YYYY/MM/DD/<uuid>/session.jsonl
|
|
202
|
-
if (filePath.includes('/muse/sessions/') ||
|
|
203
|
-
filePath.includes('\\muse\\sessions\\') ||
|
|
204
|
-
filePath.includes('/.local/share/muse/') ||
|
|
205
|
-
filePath.includes('\\.local\\share\\muse\\')) {
|
|
206
|
-
return 'muse';
|
|
207
|
-
}
|
|
208
|
-
// Cloud convention: cloud-sessions/<id>/session.<format>.jsonl
|
|
209
|
-
const cloudMatch = filePath.match(/session\.(claude|codex|rush|opencode)\.jsonl(?:$|[?#])/);
|
|
210
|
-
if (cloudMatch)
|
|
211
|
-
return cloudMatch[1];
|
|
212
|
-
if (filePath.includes('opencode.db'))
|
|
213
|
-
return 'opencode';
|
|
214
|
-
return null;
|
|
215
|
-
}
|
|
216
|
-
/**
|
|
217
|
-
* Checklist-snapshot tool names across harnesses — each sends the WHOLE list on
|
|
218
|
-
* every write, so the last call is the current checklist. Claude `TodoWrite`,
|
|
219
|
-
* Kimi `TodoList`, Droid/OpenCode `todo_write`, Codex `update_plan`.
|
|
220
|
-
*/
|
|
221
|
-
export const SNAPSHOT_TODO_TOOLS = new Set(['TodoWrite', 'TodoList', 'todo_write', 'update_plan']);
|
|
222
|
-
/**
|
|
223
|
-
* Whether a harness's checklist status means "finished". Claude/Codex write
|
|
224
|
-
* `completed`; Kimi writes `done`.
|
|
225
|
-
*/
|
|
226
|
-
export function isCompletedTodoStatus(status) {
|
|
227
|
-
return status === 'completed' || status === 'done';
|
|
228
|
-
}
|
|
229
|
-
/**
|
|
230
|
-
* Summarize a tool_use into a one-liner string.
|
|
231
|
-
*/
|
|
232
|
-
export function summarizeToolUse(tool, args) {
|
|
233
|
-
if (!args)
|
|
234
|
-
return tool;
|
|
235
|
-
switch (tool) {
|
|
236
|
-
case 'Bash':
|
|
237
|
-
return `Bash: ${truncate(String(args.command || '').replace(/\n/g, ' ').trim(), 120)}`;
|
|
238
|
-
// `path` is the Kimi spelling of Claude's `file_path` for the same tools.
|
|
239
|
-
case 'Read':
|
|
240
|
-
return `Read ${shortenPath(args.file_path || args.path || '')}`;
|
|
241
|
-
case 'Write':
|
|
242
|
-
return `Write ${shortenPath(args.file_path || args.path || '')}`;
|
|
243
|
-
case 'Edit':
|
|
244
|
-
return `Edit ${shortenPath(args.file_path || args.path || '')}`;
|
|
245
|
-
case 'Glob':
|
|
246
|
-
return `Glob ${args.pattern || ''}`;
|
|
247
|
-
case 'Grep':
|
|
248
|
-
return `Grep ${args.pattern || ''} ${args.path || ''}`.trim();
|
|
249
|
-
case 'Agent':
|
|
250
|
-
return `Agent: ${truncate(args.description || args.prompt || '', 80)}`;
|
|
251
|
-
case 'WebSearch':
|
|
252
|
-
case 'WebFetch':
|
|
253
|
-
return `${tool}: ${truncate(args.query || args.url || '', 80)}`;
|
|
254
|
-
// Codex plan tool: arrives as a function_call with {plan:[{step,status}]}.
|
|
255
|
-
case 'update_plan': {
|
|
256
|
-
const steps = Array.isArray(args.plan) ? args.plan.length : 0;
|
|
257
|
-
return `Plan: ${steps} step${steps === 1 ? '' : 's'}`;
|
|
258
|
-
}
|
|
259
|
-
// Live checklist: show progress + the current step, not a bare "TodoWrite".
|
|
260
|
-
// Claude writes `TodoWrite`, Kimi writes `TodoList`; both carry the whole list
|
|
261
|
-
// under `todos`, with Kimi spelling the item text `title` and "done" `done`.
|
|
262
|
-
case 'TodoWrite':
|
|
263
|
-
case 'TodoList': {
|
|
264
|
-
const todos = Array.isArray(args.todos) ? args.todos : [];
|
|
265
|
-
if (todos.length === 0)
|
|
266
|
-
return 'Plan: 0 steps';
|
|
267
|
-
const done = todos.filter((t) => isCompletedTodoStatus(t?.status)).length;
|
|
268
|
-
const active = todos.find((t) => t?.status === 'in_progress');
|
|
269
|
-
const step = active?.activeForm || active?.content || active?.title;
|
|
270
|
-
return step
|
|
271
|
-
? `Plan ${done}/${todos.length}: ${truncate(String(step), 80)}`
|
|
272
|
-
: `Plan: ${done}/${todos.length} done`;
|
|
273
|
-
}
|
|
274
|
-
// Codex tools
|
|
275
|
-
case 'exec_command':
|
|
276
|
-
return `Bash: ${truncate(String(args.command || args.cmd || '').replace(/\n/g, ' ').trim(), 120)}`;
|
|
277
|
-
// Newer Codex JS-cell shell wrapper: prefer the unwrapped command (set at parse
|
|
278
|
-
// time), else the extracted command, else the raw cell code.
|
|
279
|
-
case 'exec': {
|
|
280
|
-
const cmd = args.command || codexExecCommand(String(args.input || ''));
|
|
281
|
-
if (cmd)
|
|
282
|
-
return `Bash: ${truncate(String(cmd).replace(/\n/g, ' ').trim(), 120)}`;
|
|
283
|
-
const code = String(args.input || '').replace(/\n/g, ' ').trim();
|
|
284
|
-
return code ? `exec: ${truncate(code, 100)}` : 'exec';
|
|
285
|
-
}
|
|
286
|
-
case 'read_file':
|
|
287
|
-
return `Read ${shortenPath(args.file_path || args.path || '')}`;
|
|
288
|
-
case 'write_file':
|
|
289
|
-
case 'create_file':
|
|
290
|
-
return `Write ${shortenPath(args.file_path || args.path || '')}`;
|
|
291
|
-
case 'edit_file':
|
|
292
|
-
return `Edit ${shortenPath(args.file_path || args.path || '')}`;
|
|
293
|
-
// Gemini tools
|
|
294
|
-
case 'run_shell_command':
|
|
295
|
-
return `Bash: ${truncate(String(args.command || '').replace(/\n/g, ' ').trim(), 120)}`;
|
|
296
|
-
case 'search_file_content':
|
|
297
|
-
return `Search ${args.pattern || ''}`;
|
|
298
|
-
default: {
|
|
299
|
-
// Generic: show first meaningful arg
|
|
300
|
-
for (const key of ['file_path', 'path', 'pattern', 'command', 'prompt', 'query', 'url']) {
|
|
301
|
-
if (args[key])
|
|
302
|
-
return `${tool}: ${truncate(String(args[key]), 80)}`;
|
|
303
|
-
}
|
|
304
|
-
return tool;
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
/** Replace the home directory prefix with ~ for display. */
|
|
309
|
-
function shortenPath(p) {
|
|
310
|
-
const home = process.env.HOME || '';
|
|
311
|
-
if (home && p.startsWith(home))
|
|
312
|
-
return '~' + p.slice(home.length);
|
|
313
|
-
return p;
|
|
314
|
-
}
|
|
315
|
-
// ---------------------------------------------------------------------------
|
|
316
|
-
// Claude parser
|
|
317
|
-
// ---------------------------------------------------------------------------
|
|
318
|
-
/** Parse a Claude JSONL session file into normalized events. */
|
|
319
|
-
export function parseClaude(filePath, opts = {}) {
|
|
320
|
-
return parseClaudeContent(safeReadSessionFile(filePath), opts);
|
|
321
|
-
}
|
|
322
|
-
/**
|
|
323
|
-
* Parse Claude JSONL *content* (already read into a string) into normalized
|
|
324
|
-
* events. Split from `parseClaude` so the tail reader can parse just the last
|
|
325
|
-
* chunk of a file without re-reading the whole thing. Malformed leading lines
|
|
326
|
-
* (a tail that starts mid-line) are skipped by the per-line try/catch below.
|
|
327
|
-
*/
|
|
328
|
-
export function parseClaudeContent(content, opts = {}) {
|
|
329
|
-
const lines = content.split('\n').filter(l => l.trim());
|
|
330
|
-
const events = [];
|
|
331
|
-
// Map tool_use id -> {tool, args} for correlating with tool_result
|
|
332
|
-
const toolUseMap = new Map();
|
|
333
|
-
for (const line of lines) {
|
|
334
|
-
let raw;
|
|
335
|
-
try {
|
|
336
|
-
raw = JSON.parse(line);
|
|
337
|
-
}
|
|
338
|
-
catch {
|
|
339
|
-
/* malformed JSONL line, skip */
|
|
340
|
-
continue;
|
|
341
|
-
}
|
|
342
|
-
const type = raw.type;
|
|
343
|
-
const timestamp = raw.timestamp || new Date().toISOString();
|
|
344
|
-
// Claude's own file ledger: one record per file it backed up before changing
|
|
345
|
-
// it. `trackingPath` is the exact path; the record carries no add/update/
|
|
346
|
-
// delete verb, so the OPERATION still comes from the tool that touched it —
|
|
347
|
-
// this supplies the authoritative path set and touch time, nothing more.
|
|
348
|
-
if (type === 'file-history-delta' && opts.includeFileHistory) {
|
|
349
|
-
const trackingPath = typeof raw.trackingPath === 'string' ? raw.trackingPath : '';
|
|
350
|
-
if (trackingPath) {
|
|
351
|
-
events.push({
|
|
352
|
-
type: 'file_change',
|
|
353
|
-
agent: 'claude',
|
|
354
|
-
timestamp: typeof raw.timestamp === 'string' ? raw.timestamp : timestamp,
|
|
355
|
-
changes: [{ path: trackingPath, op: 'modified' }],
|
|
356
|
-
});
|
|
357
|
-
}
|
|
358
|
-
continue;
|
|
359
|
-
}
|
|
360
|
-
if (type === 'assistant') {
|
|
361
|
-
const contentBlocks = raw.message?.content || [];
|
|
362
|
-
for (const block of contentBlocks) {
|
|
363
|
-
if (block.type === 'thinking') {
|
|
364
|
-
// Thinking content -- may be encrypted (has .signature field)
|
|
365
|
-
const thinkingText = block.thinking || '';
|
|
366
|
-
if (thinkingText) {
|
|
367
|
-
events.push({
|
|
368
|
-
type: 'thinking',
|
|
369
|
-
agent: 'claude',
|
|
370
|
-
timestamp,
|
|
371
|
-
content: thinkingText,
|
|
372
|
-
});
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
else if (block.type === 'text') {
|
|
376
|
-
const text = (block.text || '').trim();
|
|
377
|
-
if (text) {
|
|
378
|
-
events.push({
|
|
379
|
-
type: 'message',
|
|
380
|
-
agent: 'claude',
|
|
381
|
-
timestamp,
|
|
382
|
-
role: 'assistant',
|
|
383
|
-
content: text,
|
|
384
|
-
});
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
else if (block.type === 'tool_use') {
|
|
388
|
-
const toolName = block.name || 'unknown';
|
|
389
|
-
const toolInput = block.input || {};
|
|
390
|
-
const toolId = block.id;
|
|
391
|
-
const isLocal = toolInput.is_local === true;
|
|
392
|
-
if (toolId) {
|
|
393
|
-
toolUseMap.set(toolId, { tool: toolName, args: toolInput });
|
|
394
|
-
}
|
|
395
|
-
const event = {
|
|
396
|
-
type: 'tool_use',
|
|
397
|
-
agent: 'claude',
|
|
398
|
-
timestamp,
|
|
399
|
-
tool: toolName,
|
|
400
|
-
callId: toolId,
|
|
401
|
-
args: toolInput,
|
|
402
|
-
path: toolInput.file_path || undefined,
|
|
403
|
-
command: toolName === 'Bash' ? toolInput.command : undefined,
|
|
404
|
-
};
|
|
405
|
-
// Claude writes a human `description` on every Bash call (and on Agent
|
|
406
|
-
// spawns) — the one-line label the model authored for exactly this
|
|
407
|
-
// purpose. `summarizeToolUse` renders the command instead, so the label
|
|
408
|
-
// was reaching no consumer; the timeline's now-line is written from it.
|
|
409
|
-
if (typeof toolInput.description === 'string' && toolInput.description.trim()) {
|
|
410
|
-
event.label = toolInput.description.trim();
|
|
411
|
-
}
|
|
412
|
-
if (isLocal)
|
|
413
|
-
event._local = true;
|
|
414
|
-
// SlashCommand: the MODEL invoking a slash command programmatically
|
|
415
|
-
// (distinct from the <command-name> wrapper below, which is the
|
|
416
|
-
// USER typing one) — see prompt.ts's extractSlashCommandFromToolInput.
|
|
417
|
-
if (toolName === 'SlashCommand') {
|
|
418
|
-
const slashCommand = extractSlashCommandFromToolInput(toolInput);
|
|
419
|
-
if (slashCommand)
|
|
420
|
-
event.slashCommand = slashCommand;
|
|
421
|
-
}
|
|
422
|
-
events.push(event);
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
// Capture token usage and model from assistant turn
|
|
426
|
-
if (raw.message?.usage) {
|
|
427
|
-
const u = raw.message.usage;
|
|
428
|
-
events.push({
|
|
429
|
-
type: 'usage',
|
|
430
|
-
agent: 'claude',
|
|
431
|
-
timestamp,
|
|
432
|
-
model: raw.message.model,
|
|
433
|
-
inputTokens: u.input_tokens,
|
|
434
|
-
outputTokens: u.output_tokens,
|
|
435
|
-
cacheReadTokens: u.cache_read_input_tokens,
|
|
436
|
-
cacheCreationTokens: u.cache_creation_input_tokens,
|
|
437
|
-
});
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
else if (type === 'user') {
|
|
441
|
-
const contentBlocks = raw.message?.content;
|
|
442
|
-
if (typeof contentBlocks === 'string') {
|
|
443
|
-
// Simple user text
|
|
444
|
-
const text = contentBlocks.trim();
|
|
445
|
-
if (text) {
|
|
446
|
-
const event = {
|
|
447
|
-
type: 'message',
|
|
448
|
-
agent: 'claude',
|
|
449
|
-
timestamp,
|
|
450
|
-
role: 'user',
|
|
451
|
-
content: text,
|
|
452
|
-
};
|
|
453
|
-
// The USER typing a slash command — Claude injects a <command-name>
|
|
454
|
-
// wrapper as the message content (see prompt.ts's
|
|
455
|
-
// extractSlashCommandName; distinct from the SlashCommand tool-use
|
|
456
|
-
// above, which is the model invoking one programmatically).
|
|
457
|
-
const slashCommand = extractSlashCommandName(text);
|
|
458
|
-
if (slashCommand)
|
|
459
|
-
event.slashCommand = slashCommand;
|
|
460
|
-
events.push(event);
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
else if (Array.isArray(contentBlocks)) {
|
|
464
|
-
for (const block of contentBlocks) {
|
|
465
|
-
if (block.type === 'text') {
|
|
466
|
-
const text = (block.text || '').trim();
|
|
467
|
-
if (text.startsWith('[Request interrupted')) {
|
|
468
|
-
// The harness's marker for a turn the user cut short, not a user
|
|
469
|
-
// message. Surfaced only on request — see includeInterrupts for why
|
|
470
|
-
// the default stream must stay byte-identical.
|
|
471
|
-
if (opts.includeInterrupts) {
|
|
472
|
-
events.push({ type: 'interrupt', agent: 'claude', timestamp, content: text });
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
else if (text) {
|
|
476
|
-
events.push({
|
|
477
|
-
type: 'message',
|
|
478
|
-
agent: 'claude',
|
|
479
|
-
timestamp,
|
|
480
|
-
role: 'user',
|
|
481
|
-
content: text,
|
|
482
|
-
});
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
else if (block.type === 'image') {
|
|
486
|
-
const source = block.source || {};
|
|
487
|
-
if (source.type === 'base64') {
|
|
488
|
-
const sizeBytes = Math.ceil((source.data?.length || 0) * 0.75);
|
|
489
|
-
events.push(normalizedAttachmentEvent('claude', timestamp, block, source, 'image/png', sizeBytes));
|
|
490
|
-
}
|
|
491
|
-
else {
|
|
492
|
-
events.push(normalizedAttachmentEvent('claude', timestamp, block, source, 'image/png', 0));
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
else if (block.type === 'document') {
|
|
496
|
-
const source = block.source || {};
|
|
497
|
-
events.push(normalizedAttachmentEvent('claude', timestamp, block, source, 'application/pdf', 0));
|
|
498
|
-
}
|
|
499
|
-
else if (block.type === 'tool_result') {
|
|
500
|
-
const toolId = block.tool_use_id;
|
|
501
|
-
const toolInfo = toolId ? toolUseMap.get(toolId) : undefined;
|
|
502
|
-
const isError = block.is_error === true;
|
|
503
|
-
const structured = structuredToolResult(block);
|
|
504
|
-
// Extract output text from tool result
|
|
505
|
-
let output = '';
|
|
506
|
-
if (typeof block.content === 'string') {
|
|
507
|
-
output = block.content;
|
|
508
|
-
}
|
|
509
|
-
else if (Array.isArray(block.content)) {
|
|
510
|
-
output = block.content
|
|
511
|
-
.filter((c) => c.type === 'text')
|
|
512
|
-
.map((c) => c.text || '')
|
|
513
|
-
.join('\n');
|
|
514
|
-
}
|
|
515
|
-
if (isError) {
|
|
516
|
-
events.push({
|
|
517
|
-
type: 'error',
|
|
518
|
-
agent: 'claude',
|
|
519
|
-
timestamp,
|
|
520
|
-
tool: toolInfo?.tool,
|
|
521
|
-
callId: toolId,
|
|
522
|
-
outcome: 'error',
|
|
523
|
-
exitCode: structured.exitCode,
|
|
524
|
-
statusCode: structured.statusCode,
|
|
525
|
-
errorCode: structured.errorCode,
|
|
526
|
-
content: output || 'Tool execution failed',
|
|
527
|
-
// A permission rule or a hook denied the call, or the operator cut
|
|
528
|
-
// it short with Ctrl-C: it never completed, so it is not a failure
|
|
529
|
-
// of the work. Claude stamps the denial kind on the enclosing
|
|
530
|
-
// record (`toolDenialKind: 'permission-rule'`) and the interrupt
|
|
531
|
-
// on its result (`toolUseResult.interrupted: true`).
|
|
532
|
-
...(isBlockedToolResult(raw) ? { blocked: true } : {}),
|
|
533
|
-
});
|
|
534
|
-
}
|
|
535
|
-
else {
|
|
536
|
-
events.push({
|
|
537
|
-
type: 'tool_result',
|
|
538
|
-
agent: 'claude',
|
|
539
|
-
timestamp,
|
|
540
|
-
tool: toolInfo?.tool,
|
|
541
|
-
callId: toolId,
|
|
542
|
-
success: true,
|
|
543
|
-
outcome: 'ok',
|
|
544
|
-
exitCode: structured.exitCode,
|
|
545
|
-
statusCode: structured.statusCode,
|
|
546
|
-
errorCode: structured.errorCode,
|
|
547
|
-
// Not truncated here: `parseSession` caps every event's `output`
|
|
548
|
-
// centrally via `maxToolOutputChars` (default 500, the same
|
|
549
|
-
// bound this site used to hardcode), so the render path can ask
|
|
550
|
-
// for the full text with `Infinity`.
|
|
551
|
-
output,
|
|
552
|
-
});
|
|
553
|
-
}
|
|
554
|
-
if (toolId)
|
|
555
|
-
toolUseMap.delete(toolId);
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
else if (type === 'result') {
|
|
561
|
-
events.push({
|
|
562
|
-
type: 'result',
|
|
563
|
-
agent: 'claude',
|
|
564
|
-
timestamp,
|
|
565
|
-
content: raw.subtype || 'success',
|
|
566
|
-
});
|
|
567
|
-
}
|
|
568
|
-
else if (type === 'attachment') {
|
|
569
|
-
// Hook firings are recorded as attachments: `hook_success` / `hook_error` /
|
|
570
|
-
// `hook_blocked` per firing, plus a derivative `hook_additional_context`
|
|
571
|
-
// record for the SAME firing (shared toolUseID) — skip the derivative or
|
|
572
|
-
// every firing counts twice.
|
|
573
|
-
const att = raw.attachment;
|
|
574
|
-
const attType = att?.type;
|
|
575
|
-
if (typeof attType === 'string' && attType.startsWith('hook_') && attType !== 'hook_additional_context') {
|
|
576
|
-
events.push({
|
|
577
|
-
type: 'hook',
|
|
578
|
-
agent: 'claude',
|
|
579
|
-
timestamp,
|
|
580
|
-
hookName: typeof att.hookName === 'string' ? att.hookName : undefined,
|
|
581
|
-
hookEvent: typeof att.hookEvent === 'string' ? att.hookEvent : undefined,
|
|
582
|
-
success: attType === 'hook_success',
|
|
583
|
-
});
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
// Skip: permission-mode, non-hook attachments, and other line types
|
|
587
|
-
}
|
|
588
|
-
return events;
|
|
589
|
-
}
|
|
590
|
-
// ---------------------------------------------------------------------------
|
|
591
|
-
// Codex parser
|
|
592
|
-
// ---------------------------------------------------------------------------
|
|
593
|
-
/** Parse a Codex JSONL session file into normalized events. */
|
|
594
|
-
export function parseCodex(filePath) {
|
|
595
|
-
return parseCodexContent(safeReadSessionFile(filePath));
|
|
596
|
-
}
|
|
597
|
-
/**
|
|
598
|
-
* Extract target file path(s) from a Codex apply_patch envelope. The patch body
|
|
599
|
-
* opens with `*** Begin Patch` and carries one or more file ops of the form
|
|
600
|
-
* `*** Update File: <path>` / `*** Add File: <path>` / `*** Delete File: <path>`.
|
|
601
|
-
* Returns every path in order (a multi-file patch emits multiple paths so
|
|
602
|
-
* artifact discovery sees each file — RUSH-1410). Empty when unparseable.
|
|
603
|
-
*/
|
|
604
|
-
function applyPatchTargets(input) {
|
|
605
|
-
const targets = [];
|
|
606
|
-
const re = /^\*\*\* (Update|Add|Delete) File: (.+)$/gm;
|
|
607
|
-
for (const m of input.matchAll(re)) {
|
|
608
|
-
const p = m[2].trim();
|
|
609
|
-
if (p)
|
|
610
|
-
targets.push({ path: p, op: m[1] });
|
|
611
|
-
}
|
|
612
|
-
return targets;
|
|
613
|
-
}
|
|
614
|
-
export function applyPatchTargetPaths(input) {
|
|
615
|
-
return applyPatchTargets(input).map((target) => target.path);
|
|
616
|
-
}
|
|
617
|
-
/** @deprecated Prefer applyPatchTargetPaths — kept for single-file call sites. */
|
|
618
|
-
function applyPatchTargetPath(input) {
|
|
619
|
-
return applyPatchTargetPaths(input)[0];
|
|
620
|
-
}
|
|
621
|
-
/**
|
|
622
|
-
* Newer Codex (gpt-5.6-sol / codex >=~0.145) runs every shell command inside a JS
|
|
623
|
-
* cell: a `custom_tool_call` named `exec` whose `input` is code like
|
|
624
|
-
* `const r = await tools.exec_command({cmd:"git status", "workdir":"…"});`. The real
|
|
625
|
-
* shell command(s) are buried in those `cmd:"…"` literals. Reuse the canonical
|
|
626
|
-
* acorn-based extractor (`commandsFromCodexExec` in `tool-calls.ts`, already used by
|
|
627
|
-
* the tool-call index): it walks the whole AST — so a cell that runs several via
|
|
628
|
-
* `Promise.all([tools.exec_command(...), tools.exec_command(...)])` yields every
|
|
629
|
-
* command, not just the first — and matches only real `tools.exec_command` calls,
|
|
630
|
-
* so a `cmd:"…"` string mentioned in a comment or docstring is never mistaken for an
|
|
631
|
-
* invocation. Returns `undefined` for a non-shell cell (`tools.view_image(...)`, a
|
|
632
|
-
* raw JS computation) so it stays labeled by its code, not faked into a shell step.
|
|
633
|
-
*/
|
|
634
|
-
function codexExecCommand(input) {
|
|
635
|
-
const commands = commandsFromCodexExec(input);
|
|
636
|
-
return commands.length > 0 ? commands.join('\n') : undefined;
|
|
637
|
-
}
|
|
638
|
-
/**
|
|
639
|
-
* Codex writes its turn TWICE in one rollout: the raw `response_item` records
|
|
640
|
-
* the model exchanged, and a parallel `event_msg` / `item_completed` stream of
|
|
641
|
-
* typed, already-classified items. The two overlap — on a 6,244-line rollout on
|
|
642
|
-
* zion (2026-09-06) the same turn appears as 648 `custom_tool_call` +
|
|
643
|
-
* 60 `function_call` records AND as 1,038 `CommandExecution` items — so the two
|
|
644
|
-
* MUST NOT be merged into one event list: every consumer that counts tool calls
|
|
645
|
-
* (digest, trajectory, insights, the tool index) would double-count.
|
|
646
|
-
*
|
|
647
|
-
* {@link parseCodexContent} therefore keeps reading `response_item` and this is
|
|
648
|
-
* a SEPARATE reader over the item stream, for consumers that want the harness's
|
|
649
|
-
* own classification instead of re-deriving it: the command as Codex parsed it
|
|
650
|
-
* (`parsed_cmd.type`), its `exit_code`/`status`, the per-path `FileChange`
|
|
651
|
-
* ledger, `AgentMessage.phase` (`commentary` is the narration between calls),
|
|
652
|
-
* web searches, sub-agent activity and compactions. The timeline fold is the
|
|
653
|
-
* consumer; `parseSession` is untouched.
|
|
654
|
-
*
|
|
655
|
-
* Version-tolerant by construction: an item type this does not know folds to a
|
|
656
|
-
* generic `other` tool_use rather than throwing, so a Codex release that adds an
|
|
657
|
-
* item type degrades to a counted step instead of an empty timeline.
|
|
658
|
-
*/
|
|
659
|
-
export function parseCodexItemsContent(content) {
|
|
660
|
-
const events = [];
|
|
661
|
-
for (const line of content.split('\n')) {
|
|
662
|
-
if (!line.trim())
|
|
663
|
-
continue;
|
|
664
|
-
let raw;
|
|
665
|
-
try {
|
|
666
|
-
raw = JSON.parse(line);
|
|
667
|
-
}
|
|
668
|
-
catch {
|
|
669
|
-
continue;
|
|
670
|
-
}
|
|
671
|
-
if (raw?.type !== 'event_msg')
|
|
672
|
-
continue;
|
|
673
|
-
const payload = raw.payload || {};
|
|
674
|
-
const timestamp = raw.timestamp || new Date().toISOString();
|
|
675
|
-
if (payload.type === 'turn_aborted') {
|
|
676
|
-
events.push({ type: 'interrupt', agent: 'codex', timestamp, content: 'Turn interrupted by user' });
|
|
677
|
-
continue;
|
|
678
|
-
}
|
|
679
|
-
if (payload.type !== 'item_completed')
|
|
680
|
-
continue;
|
|
681
|
-
const item = payload.item || {};
|
|
682
|
-
const id = typeof item.id === 'string' ? item.id : undefined;
|
|
683
|
-
switch (item.type) {
|
|
684
|
-
case 'AgentMessage': {
|
|
685
|
-
const text = codexItemText(item.content);
|
|
686
|
-
if (!text)
|
|
687
|
-
break;
|
|
688
|
-
events.push({
|
|
689
|
-
type: 'message', agent: 'codex', timestamp, role: 'assistant', content: text,
|
|
690
|
-
...(typeof item.phase === 'string' ? { phase: item.phase } : {}),
|
|
691
|
-
});
|
|
692
|
-
break;
|
|
693
|
-
}
|
|
694
|
-
case 'UserMessage': {
|
|
695
|
-
const text = codexItemText(item.content);
|
|
696
|
-
if (text)
|
|
697
|
-
events.push({ type: 'message', agent: 'codex', timestamp, role: 'user', content: text });
|
|
698
|
-
break;
|
|
699
|
-
}
|
|
700
|
-
case 'CommandExecution': {
|
|
701
|
-
const command = codexItemCommand(item.command);
|
|
702
|
-
const parsed = Array.isArray(item.parsed_cmd) ? item.parsed_cmd[0] : undefined;
|
|
703
|
-
const parsedType = parsed && typeof parsed === 'object' ? parsed.type : undefined;
|
|
704
|
-
const verbClass = CODEX_PARSED_CMD_VERBS[String(parsedType)];
|
|
705
|
-
events.push({
|
|
706
|
-
type: 'tool_use', agent: 'codex', timestamp, tool: 'Bash', callId: id,
|
|
707
|
-
args: { command }, command,
|
|
708
|
-
label: truncate(command.replace(/\n/g, ' ').trim(), 120),
|
|
709
|
-
...(verbClass ? { verbClass } : {}),
|
|
710
|
-
});
|
|
711
|
-
const exitCode = typeof item.exit_code === 'number' ? item.exit_code : undefined;
|
|
712
|
-
const failedStatus = item.status === 'failed' || item.status === 'error';
|
|
713
|
-
// A search that matched nothing exits 1 and is not a failure — the same
|
|
714
|
-
// rule the fold applies to Claude, kept here so the two agree.
|
|
715
|
-
const benign = exitCode === 1 && CODEX_BENIGN_EXIT1_RE.test(command);
|
|
716
|
-
if (failedStatus || (exitCode !== undefined && exitCode !== 0 && !benign)) {
|
|
717
|
-
events.push({
|
|
718
|
-
type: 'error', agent: 'codex', timestamp, tool: 'Bash', callId: id,
|
|
719
|
-
outcome: 'error', ...(exitCode !== undefined ? { exitCode } : {}),
|
|
720
|
-
content: 'Command failed',
|
|
721
|
-
});
|
|
722
|
-
}
|
|
723
|
-
else if (exitCode !== undefined || item.status) {
|
|
724
|
-
events.push({
|
|
725
|
-
type: 'tool_result', agent: 'codex', timestamp, tool: 'Bash', callId: id,
|
|
726
|
-
success: true, outcome: 'ok', ...(exitCode !== undefined ? { exitCode } : {}),
|
|
727
|
-
});
|
|
728
|
-
}
|
|
729
|
-
break;
|
|
730
|
-
}
|
|
731
|
-
case 'FileChange': {
|
|
732
|
-
const changes = codexFileChanges(item.changes);
|
|
733
|
-
if (!changes.length)
|
|
734
|
-
break;
|
|
735
|
-
events.push({ type: 'file_change', agent: 'codex', timestamp, callId: id, changes });
|
|
736
|
-
break;
|
|
737
|
-
}
|
|
738
|
-
case 'Extension': {
|
|
739
|
-
const query = typeof item.query === 'string' ? item.query : '';
|
|
740
|
-
events.push({
|
|
741
|
-
type: 'tool_use', agent: 'codex', timestamp, tool: 'WebSearch', callId: id,
|
|
742
|
-
args: { query }, verbClass: 'browser',
|
|
743
|
-
label: `web search: ${truncate(query, 60)}`,
|
|
744
|
-
});
|
|
745
|
-
break;
|
|
746
|
-
}
|
|
747
|
-
case 'SubAgentActivity': {
|
|
748
|
-
// `started` opens a sub-agent; the matching `completed` would count the
|
|
749
|
-
// same spawn twice, so only the opening edge is a call.
|
|
750
|
-
if (item.kind !== 'started')
|
|
751
|
-
break;
|
|
752
|
-
events.push({
|
|
753
|
-
type: 'tool_use', agent: 'codex', timestamp, tool: 'Agent', callId: id,
|
|
754
|
-
args: { path: item.agent_path }, verbClass: 'agent',
|
|
755
|
-
label: `subagent ${String(item.agent_path ?? '').replace(/^\//, '') || 'started'}`,
|
|
756
|
-
});
|
|
757
|
-
break;
|
|
758
|
-
}
|
|
759
|
-
case 'McpToolCall': {
|
|
760
|
-
const label = `${item.server ?? ''}.${item.tool ?? ''}`.replace(/^\.|\.$/g, '');
|
|
761
|
-
events.push({
|
|
762
|
-
type: 'tool_use', agent: 'codex', timestamp, tool: 'mcp', callId: id,
|
|
763
|
-
args: {}, verbClass: 'other', label: label || 'mcp call',
|
|
764
|
-
});
|
|
765
|
-
break;
|
|
766
|
-
}
|
|
767
|
-
case 'ImageView': {
|
|
768
|
-
events.push({
|
|
769
|
-
type: 'tool_use', agent: 'codex', timestamp, tool: 'Read', callId: id,
|
|
770
|
-
args: { path: item.path }, verbClass: 'read', label: 'viewed image',
|
|
771
|
-
});
|
|
772
|
-
break;
|
|
773
|
-
}
|
|
774
|
-
case 'ContextCompaction': {
|
|
775
|
-
events.push({ type: 'hook', agent: 'codex', timestamp, hookName: 'ContextCompaction', content: 'context compacted' });
|
|
776
|
-
break;
|
|
777
|
-
}
|
|
778
|
-
case 'Reasoning':
|
|
779
|
-
// `summary_text` is empty on every rollout measured (13,461 items, 0 with
|
|
780
|
-
// text — only `encrypted_content`), so there is nothing to read. Skipped
|
|
781
|
-
// deliberately rather than emitted as an empty thinking event.
|
|
782
|
-
break;
|
|
783
|
-
default: {
|
|
784
|
-
// Unknown item type from a newer Codex: counted, never dropped, never thrown.
|
|
785
|
-
if (!item.type)
|
|
786
|
-
break;
|
|
787
|
-
events.push({
|
|
788
|
-
type: 'tool_use', agent: 'codex', timestamp, tool: String(item.type), callId: id,
|
|
789
|
-
args: {}, verbClass: 'other', label: String(item.type),
|
|
790
|
-
});
|
|
791
|
-
break;
|
|
792
|
-
}
|
|
793
|
-
}
|
|
794
|
-
}
|
|
795
|
-
return events;
|
|
796
|
-
}
|
|
797
|
-
/** Codex `parsed_cmd[0].type` → the timeline's verb class. Anything else is derived from the command. */
|
|
798
|
-
const CODEX_PARSED_CMD_VERBS = {
|
|
799
|
-
read: 'read',
|
|
800
|
-
list_files: 'read',
|
|
801
|
-
search: 'read',
|
|
802
|
-
};
|
|
803
|
-
/** Commands whose exit 1 means "no match", not "failed". */
|
|
804
|
-
const CODEX_BENIGN_EXIT1_RE = /^\s*(rg|grep|diff|test|\[)\b/;
|
|
805
|
-
/** Text of a Codex item's `content` array (`{ type, text }` blocks). */
|
|
806
|
-
function codexItemText(content) {
|
|
807
|
-
if (!Array.isArray(content))
|
|
808
|
-
return '';
|
|
809
|
-
return content
|
|
810
|
-
.map((part) => (part && typeof part.text === 'string' ? part.text : ''))
|
|
811
|
-
.join(' ')
|
|
812
|
-
.trim();
|
|
813
|
-
}
|
|
814
|
-
/** `["/bin/zsh", "-lc", "git pull"]` → `git pull`; a plain string passes through. */
|
|
815
|
-
function codexItemCommand(command) {
|
|
816
|
-
if (typeof command === 'string')
|
|
817
|
-
return command;
|
|
818
|
-
if (!Array.isArray(command))
|
|
819
|
-
return '';
|
|
820
|
-
const shellWrapped = command.length >= 3 && (command[1] === '-lc' || command[1] === '-c');
|
|
821
|
-
return (shellWrapped ? command.slice(2) : command).map(String).join(' ');
|
|
822
|
-
}
|
|
823
|
-
/** Codex `FileChange.changes`: `{ "<path>": { type: "add" | "update" | "delete" } }`. */
|
|
824
|
-
function codexFileChanges(changes) {
|
|
825
|
-
if (!changes || typeof changes !== 'object' || Array.isArray(changes))
|
|
826
|
-
return [];
|
|
827
|
-
const ops = {
|
|
828
|
-
add: 'created', update: 'modified', delete: 'deleted',
|
|
829
|
-
};
|
|
830
|
-
return Object.entries(changes).map(([filePath, change]) => ({
|
|
831
|
-
path: filePath,
|
|
832
|
-
op: ops[String(change?.type)] ?? 'modified',
|
|
833
|
-
}));
|
|
834
|
-
}
|
|
835
|
-
/**
|
|
836
|
-
* Parse Codex JSONL *content* (already read into a string) into normalized
|
|
837
|
-
* events. Split from `parseCodex` so the tail reader can parse just the last
|
|
838
|
-
* chunk without re-reading the whole file.
|
|
839
|
-
*/
|
|
840
|
-
export function parseCodexContent(content) {
|
|
841
|
-
const lines = content.split('\n').filter(l => l.trim());
|
|
842
|
-
const events = [];
|
|
843
|
-
// Track function_call id -> name for correlating with function_call_output
|
|
844
|
-
const callMap = new Map();
|
|
845
|
-
for (const line of lines) {
|
|
846
|
-
let raw;
|
|
847
|
-
try {
|
|
848
|
-
raw = JSON.parse(line);
|
|
849
|
-
}
|
|
850
|
-
catch {
|
|
851
|
-
/* malformed JSONL line, skip */
|
|
852
|
-
continue;
|
|
853
|
-
}
|
|
854
|
-
const lineType = raw.type;
|
|
855
|
-
const timestamp = raw.timestamp || new Date().toISOString();
|
|
856
|
-
const payload = raw.payload || {};
|
|
857
|
-
if (lineType === 'session_meta') {
|
|
858
|
-
events.push({
|
|
859
|
-
type: 'init',
|
|
860
|
-
agent: 'codex',
|
|
861
|
-
timestamp,
|
|
862
|
-
content: `Codex ${payload.cli_version || ''} session in ${payload.cwd || ''}`.trim(),
|
|
863
|
-
});
|
|
864
|
-
continue;
|
|
865
|
-
}
|
|
866
|
-
if (lineType === 'event_msg') {
|
|
867
|
-
// Web search is reported out-of-band as event_msg (not response_item).
|
|
868
|
-
// The paired begin (`web_search_call`) has no query; only `web_search_end`
|
|
869
|
-
// carries the resolved query string, so we emit exactly one tool_use per
|
|
870
|
-
// search off the end event and ignore the begin to avoid duplicates.
|
|
871
|
-
if (payload.type === 'web_search_end') {
|
|
872
|
-
const query = typeof payload.query === 'string' ? payload.query : '';
|
|
873
|
-
events.push({
|
|
874
|
-
type: 'tool_use',
|
|
875
|
-
agent: 'codex',
|
|
876
|
-
timestamp,
|
|
877
|
-
tool: 'WebSearch',
|
|
878
|
-
args: { query },
|
|
879
|
-
});
|
|
880
|
-
}
|
|
881
|
-
continue;
|
|
882
|
-
}
|
|
883
|
-
if (lineType === 'response_item') {
|
|
884
|
-
const ptype = payload.type;
|
|
885
|
-
if (ptype === 'message') {
|
|
886
|
-
const contentBlocks = payload.content || [];
|
|
887
|
-
const role = payload.role === 'user' || payload.role === 'developer' ? 'user' : 'assistant';
|
|
888
|
-
for (const block of contentBlocks) {
|
|
889
|
-
if (block.type === 'output_text') {
|
|
890
|
-
const text = (block.text || '').trim();
|
|
891
|
-
if (text) {
|
|
892
|
-
events.push({
|
|
893
|
-
type: 'message',
|
|
894
|
-
agent: 'codex',
|
|
895
|
-
timestamp,
|
|
896
|
-
role: 'assistant',
|
|
897
|
-
content: text,
|
|
898
|
-
});
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
|
-
else if (block.type === 'input_text') {
|
|
902
|
-
// Developer/user input messages -- only include actual prompts, not system instructions
|
|
903
|
-
const text = (block.text || '').trim();
|
|
904
|
-
if (text && text.length < 2000 && !text.includes('<permissions instructions>')) {
|
|
905
|
-
events.push({
|
|
906
|
-
type: 'message',
|
|
907
|
-
agent: 'codex',
|
|
908
|
-
timestamp,
|
|
909
|
-
role: 'user',
|
|
910
|
-
content: text,
|
|
911
|
-
});
|
|
912
|
-
}
|
|
913
|
-
}
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
else if (ptype === 'function_call') {
|
|
917
|
-
const name = payload.name || 'unknown';
|
|
918
|
-
let args = {};
|
|
919
|
-
try {
|
|
920
|
-
args = typeof payload.arguments === 'string'
|
|
921
|
-
? JSON.parse(payload.arguments)
|
|
922
|
-
: (payload.arguments || {});
|
|
923
|
-
}
|
|
924
|
-
catch {
|
|
925
|
-
/* arguments not valid JSON, preserve raw */
|
|
926
|
-
args = { raw: payload.arguments };
|
|
927
|
-
}
|
|
928
|
-
const callId = payload.call_id || payload.id;
|
|
929
|
-
if (callId) {
|
|
930
|
-
callMap.set(callId, { name, args });
|
|
931
|
-
}
|
|
932
|
-
events.push({
|
|
933
|
-
type: 'tool_use',
|
|
934
|
-
agent: 'codex',
|
|
935
|
-
timestamp,
|
|
936
|
-
tool: name,
|
|
937
|
-
callId,
|
|
938
|
-
args,
|
|
939
|
-
command: name === 'exec_command' ? (args.command || args.cmd) : undefined,
|
|
940
|
-
path: args.file_path || args.path || undefined,
|
|
941
|
-
});
|
|
942
|
-
}
|
|
943
|
-
else if (ptype === 'function_call_output') {
|
|
944
|
-
const callId = payload.call_id || payload.id;
|
|
945
|
-
const callInfo = callId ? callMap.get(callId) : undefined;
|
|
946
|
-
const result = structuredToolResult(payload.output);
|
|
947
|
-
events.push({
|
|
948
|
-
type: 'tool_result',
|
|
949
|
-
agent: 'codex',
|
|
950
|
-
timestamp,
|
|
951
|
-
tool: callInfo?.name,
|
|
952
|
-
callId,
|
|
953
|
-
success: result.outcome === 'error' ? false : true,
|
|
954
|
-
outcome: result.outcome,
|
|
955
|
-
exitCode: result.exitCode,
|
|
956
|
-
statusCode: result.statusCode,
|
|
957
|
-
errorCode: result.errorCode,
|
|
958
|
-
output: result.text,
|
|
959
|
-
});
|
|
960
|
-
if (callId)
|
|
961
|
-
callMap.delete(callId);
|
|
962
|
-
}
|
|
963
|
-
else if (ptype === 'custom_tool_call') {
|
|
964
|
-
// Codex edits arrive as custom_tool_call (apply_patch), NOT function_call.
|
|
965
|
-
const rawName = payload.name || 'unknown';
|
|
966
|
-
const input = typeof payload.input === 'string' ? payload.input : '';
|
|
967
|
-
const isApplyPatch = rawName === 'apply_patch';
|
|
968
|
-
// Newer Codex wraps shell in a JS `exec` cell — unwrap the real command so
|
|
969
|
-
// the step reads by its program instead of a bare "exec" (see extractor).
|
|
970
|
-
const execCommand = rawName === 'exec' ? codexExecCommand(input) : undefined;
|
|
971
|
-
// Multi-file patches: one tool_use per file so artifact discovery sees
|
|
972
|
-
// every path (RUSH-1410). Single-file / non-patch keep one event.
|
|
973
|
-
const patchTargets = isApplyPatch ? applyPatchTargets(input) : [];
|
|
974
|
-
const tool = isApplyPatch ? 'Edit' : rawName;
|
|
975
|
-
const truncatedInput = input.length > 500 ? input.slice(0, 497) + '...' : input;
|
|
976
|
-
const emitOne = (patchPath, patchOp) => {
|
|
977
|
-
const args = { input: truncatedInput };
|
|
978
|
-
if (patchPath)
|
|
979
|
-
args.file_path = patchPath;
|
|
980
|
-
if (patchOp)
|
|
981
|
-
args.patch_op = patchOp;
|
|
982
|
-
if (execCommand)
|
|
983
|
-
args.command = execCommand;
|
|
984
|
-
const callId = payload.call_id || payload.id;
|
|
985
|
-
if (callId)
|
|
986
|
-
callMap.set(callId, { name: tool, args });
|
|
987
|
-
events.push({
|
|
988
|
-
type: 'tool_use',
|
|
989
|
-
agent: 'codex',
|
|
990
|
-
timestamp,
|
|
991
|
-
tool,
|
|
992
|
-
callId,
|
|
993
|
-
args,
|
|
994
|
-
command: execCommand,
|
|
995
|
-
path: patchPath,
|
|
996
|
-
});
|
|
997
|
-
};
|
|
998
|
-
if (isApplyPatch && patchTargets.length > 0) {
|
|
999
|
-
for (const target of patchTargets)
|
|
1000
|
-
emitOne(target.path, target.op);
|
|
1001
|
-
}
|
|
1002
|
-
else {
|
|
1003
|
-
emitOne(undefined);
|
|
1004
|
-
}
|
|
1005
|
-
}
|
|
1006
|
-
else if (ptype === 'custom_tool_call_output') {
|
|
1007
|
-
const callId = payload.call_id || payload.id;
|
|
1008
|
-
const callInfo = callId ? callMap.get(callId) : undefined;
|
|
1009
|
-
const result = structuredToolResult(payload.output);
|
|
1010
|
-
events.push({
|
|
1011
|
-
type: 'tool_result',
|
|
1012
|
-
agent: 'codex',
|
|
1013
|
-
timestamp,
|
|
1014
|
-
tool: callInfo?.name,
|
|
1015
|
-
callId,
|
|
1016
|
-
success: result.outcome === 'error' ? false : true,
|
|
1017
|
-
outcome: result.outcome,
|
|
1018
|
-
exitCode: result.exitCode,
|
|
1019
|
-
statusCode: result.statusCode,
|
|
1020
|
-
errorCode: result.errorCode,
|
|
1021
|
-
output: result.text,
|
|
1022
|
-
});
|
|
1023
|
-
if (callId)
|
|
1024
|
-
callMap.delete(callId);
|
|
1025
|
-
}
|
|
1026
|
-
else if (ptype === 'reasoning') {
|
|
1027
|
-
// Codex reasoning -- try to get the readable summary
|
|
1028
|
-
const summaries = payload.summary || [];
|
|
1029
|
-
const text = summaries.length > 0
|
|
1030
|
-
? summaries.map((s) => s.text || '').join('\n')
|
|
1031
|
-
: (payload.text || '');
|
|
1032
|
-
if (text.trim()) {
|
|
1033
|
-
events.push({
|
|
1034
|
-
type: 'thinking',
|
|
1035
|
-
agent: 'codex',
|
|
1036
|
-
timestamp,
|
|
1037
|
-
content: text.trim(),
|
|
1038
|
-
});
|
|
1039
|
-
}
|
|
1040
|
-
}
|
|
1041
|
-
}
|
|
1042
|
-
// Skip: event_msg (token_count, etc.), turn_context
|
|
1043
|
-
}
|
|
1044
|
-
return events;
|
|
1045
|
-
}
|
|
1046
|
-
/** Read a base-128 varint from `b` at offset `i`; returns [value, nextOffset]. */
|
|
1047
|
-
function readVarint(b, i) {
|
|
1048
|
-
let shift = 0;
|
|
1049
|
-
let val = 0;
|
|
1050
|
-
for (;;) {
|
|
1051
|
-
const byte = b[i++];
|
|
1052
|
-
val += (byte & 0x7f) * 2 ** shift;
|
|
1053
|
-
if ((byte & 0x80) === 0)
|
|
1054
|
-
break;
|
|
1055
|
-
shift += 7;
|
|
1056
|
-
}
|
|
1057
|
-
return [val, i];
|
|
1058
|
-
}
|
|
1059
|
-
/** Decode a protobuf message into a flat list of fields (one nesting level). */
|
|
1060
|
-
function decodeProtoMessage(b) {
|
|
1061
|
-
const out = [];
|
|
1062
|
-
let i = 0;
|
|
1063
|
-
while (i < b.length) {
|
|
1064
|
-
let tag;
|
|
1065
|
-
[tag, i] = readVarint(b, i);
|
|
1066
|
-
const field = tag >>> 3;
|
|
1067
|
-
const wire = tag & 7;
|
|
1068
|
-
if (wire === 0) {
|
|
1069
|
-
let v;
|
|
1070
|
-
[v, i] = readVarint(b, i);
|
|
1071
|
-
out.push({ field, wire, value: v });
|
|
1072
|
-
}
|
|
1073
|
-
else if (wire === 2) {
|
|
1074
|
-
let len;
|
|
1075
|
-
[len, i] = readVarint(b, i);
|
|
1076
|
-
out.push({ field, wire, value: b.subarray(i, i + len) });
|
|
1077
|
-
i += len;
|
|
1078
|
-
}
|
|
1079
|
-
else if (wire === 5) {
|
|
1080
|
-
i += 4; // fixed32 — skipped
|
|
1081
|
-
out.push({ field, wire, value: 0 });
|
|
1082
|
-
}
|
|
1083
|
-
else if (wire === 1) {
|
|
1084
|
-
i += 8; // fixed64 — skipped
|
|
1085
|
-
out.push({ field, wire, value: 0 });
|
|
1086
|
-
}
|
|
1087
|
-
else {
|
|
1088
|
-
break; // unknown wire type — stop to avoid runaway reads
|
|
1089
|
-
}
|
|
1090
|
-
}
|
|
1091
|
-
return out;
|
|
1092
|
-
}
|
|
1093
|
-
const ANTIGRAVITY_TEXT_DECODER = new TextDecoder('utf-8', { fatal: false });
|
|
1094
|
-
/**
|
|
1095
|
-
* Recursively locate the tool-call node: the first sub-message that carries an
|
|
1096
|
-
* f2 string tool-name AND an f3 JSON-args string. Also captures the f1 call id
|
|
1097
|
-
* (used to dedupe the request + completion steps) and the f30/f31 human labels.
|
|
1098
|
-
*/
|
|
1099
|
-
function findAntigravityToolCall(fields) {
|
|
1100
|
-
let id;
|
|
1101
|
-
let name;
|
|
1102
|
-
let argsJson;
|
|
1103
|
-
let summary;
|
|
1104
|
-
let action;
|
|
1105
|
-
const subs = [];
|
|
1106
|
-
for (const f of fields) {
|
|
1107
|
-
if (f.wire !== 2)
|
|
1108
|
-
continue;
|
|
1109
|
-
const bytes = f.value;
|
|
1110
|
-
const s = ANTIGRAVITY_TEXT_DECODER.decode(bytes);
|
|
1111
|
-
if (f.field === 1 && !id && /^[a-z0-9]{4,16}$/.test(s))
|
|
1112
|
-
id = s;
|
|
1113
|
-
else if (f.field === 2 && !name && /^[a-z][a-z_]{2,30}$/.test(s))
|
|
1114
|
-
name = s;
|
|
1115
|
-
else if (f.field === 3 && !argsJson && s.startsWith('{') && s.includes('"toolAction"'))
|
|
1116
|
-
argsJson = s;
|
|
1117
|
-
else if (f.field === 30 && !summary)
|
|
1118
|
-
summary = s;
|
|
1119
|
-
else if (f.field === 31 && !action)
|
|
1120
|
-
action = s;
|
|
1121
|
-
else {
|
|
1122
|
-
try {
|
|
1123
|
-
subs.push(decodeProtoMessage(bytes));
|
|
1124
|
-
}
|
|
1125
|
-
catch {
|
|
1126
|
-
/* not a nested message */
|
|
1127
|
-
}
|
|
1128
|
-
}
|
|
1129
|
-
}
|
|
1130
|
-
if (name && argsJson) {
|
|
1131
|
-
let args = {};
|
|
1132
|
-
try {
|
|
1133
|
-
args = JSON.parse(argsJson);
|
|
1134
|
-
}
|
|
1135
|
-
catch {
|
|
1136
|
-
args = { _raw: argsJson };
|
|
1137
|
-
}
|
|
1138
|
-
return { id, name, args, summary, action };
|
|
1139
|
-
}
|
|
1140
|
-
for (const sub of subs) {
|
|
1141
|
-
const hit = findAntigravityToolCall(sub);
|
|
1142
|
-
if (hit)
|
|
1143
|
-
return hit;
|
|
1144
|
-
}
|
|
1145
|
-
return null;
|
|
1146
|
-
}
|
|
1147
|
-
/**
|
|
1148
|
-
* Map an Antigravity tool name onto the shared normalized vocabulary that the
|
|
1149
|
-
* renderer already handles (so no render.ts changes are needed). Unknown tools
|
|
1150
|
-
* pass through untouched (with their JSON args) so future tools are captured.
|
|
1151
|
-
*/
|
|
1152
|
-
const ANTIGRAVITY_TOOL_MAP = {
|
|
1153
|
-
run_command: 'Bash',
|
|
1154
|
-
view_file: 'Read',
|
|
1155
|
-
read_file: 'Read',
|
|
1156
|
-
list_dir: 'LS',
|
|
1157
|
-
grep_search: 'Grep',
|
|
1158
|
-
replace_file_content: 'Edit',
|
|
1159
|
-
write_to_file: 'Write',
|
|
1160
|
-
// Web tools surface identically once observed:
|
|
1161
|
-
search_web: 'WebSearch',
|
|
1162
|
-
read_url: 'WebFetch',
|
|
1163
|
-
execute_url: 'WebFetch',
|
|
1164
|
-
};
|
|
1165
|
-
/**
|
|
1166
|
-
* Parse an Antigravity conversation SQLite DB into normalized tool_use events.
|
|
1167
|
-
* Deduped by the tool-call id so each tool appears once (Antigravity writes a
|
|
1168
|
-
* request step and a completion step that share the id).
|
|
1169
|
-
*/
|
|
1170
|
-
export function parseAntigravity(dbPath) {
|
|
1171
|
-
// Read the raw BLOB payloads through the node/bun SQLite wrapper (not the
|
|
1172
|
-
// `sqlite3` CLI) so this works on every OS — the CLI is absent on Windows.
|
|
1173
|
-
let rows;
|
|
1174
|
-
let db;
|
|
1175
|
-
try {
|
|
1176
|
-
db = new Database(dbPath);
|
|
1177
|
-
rows = db
|
|
1178
|
-
.prepare('SELECT idx, step_type, step_payload FROM steps ORDER BY idx;')
|
|
1179
|
-
.all();
|
|
1180
|
-
}
|
|
1181
|
-
catch {
|
|
1182
|
-
/* DB not accessible, sqlite module unavailable, or query failed */
|
|
1183
|
-
return [];
|
|
1184
|
-
}
|
|
1185
|
-
finally {
|
|
1186
|
-
try {
|
|
1187
|
-
db?.close();
|
|
1188
|
-
}
|
|
1189
|
-
catch {
|
|
1190
|
-
/* best-effort close */
|
|
1191
|
-
}
|
|
1192
|
-
}
|
|
1193
|
-
// Single timestamp for the whole session: the steps table carries no per-step
|
|
1194
|
-
// time column, so fall back to the DB file's mtime for a stable, sortable value.
|
|
1195
|
-
let timestamp = new Date().toISOString();
|
|
1196
|
-
try {
|
|
1197
|
-
timestamp = fs.statSync(dbPath).mtime.toISOString();
|
|
1198
|
-
}
|
|
1199
|
-
catch {
|
|
1200
|
-
/* file vanished between query and stat — keep now() */
|
|
1201
|
-
}
|
|
1202
|
-
const events = [];
|
|
1203
|
-
const seenCallIds = new Set();
|
|
1204
|
-
for (const row of rows) {
|
|
1205
|
-
const payload = row.step_payload;
|
|
1206
|
-
// Both node:sqlite and bun:sqlite return a BLOB as a Uint8Array (Buffer is
|
|
1207
|
-
// a subclass). NULL / non-blob payloads are skipped.
|
|
1208
|
-
if (!(payload instanceof Uint8Array))
|
|
1209
|
-
continue;
|
|
1210
|
-
const bytes = payload;
|
|
1211
|
-
let fields;
|
|
1212
|
-
try {
|
|
1213
|
-
fields = decodeProtoMessage(bytes);
|
|
1214
|
-
}
|
|
1215
|
-
catch {
|
|
1216
|
-
continue;
|
|
1217
|
-
}
|
|
1218
|
-
const call = findAntigravityToolCall(fields);
|
|
1219
|
-
if (!call)
|
|
1220
|
-
continue;
|
|
1221
|
-
// Dedupe: the request + completion steps of one tool share the f1 call id.
|
|
1222
|
-
if (call.id) {
|
|
1223
|
-
if (seenCallIds.has(call.id))
|
|
1224
|
-
continue;
|
|
1225
|
-
seenCallIds.add(call.id);
|
|
1226
|
-
}
|
|
1227
|
-
const norm = ANTIGRAVITY_TOOL_MAP[call.name] || call.name;
|
|
1228
|
-
const a = call.args || {};
|
|
1229
|
-
events.push({
|
|
1230
|
-
type: 'tool_use',
|
|
1231
|
-
agent: 'antigravity',
|
|
1232
|
-
timestamp,
|
|
1233
|
-
tool: norm,
|
|
1234
|
-
callId: call.id,
|
|
1235
|
-
args: a,
|
|
1236
|
-
command: norm === 'Bash' ? a.CommandLine : undefined,
|
|
1237
|
-
// Antigravity uses PascalCase arg keys; probe the known path-bearing ones.
|
|
1238
|
-
path: a.AbsolutePath || a.TargetFile || a.DirectoryPath || a.SearchPath || undefined,
|
|
1239
|
-
// Antigravity's own short human label — free, high quality. It surfaces
|
|
1240
|
-
// either as the f30 string or (more reliably) as `toolSummary` inside the
|
|
1241
|
-
// f3 JSON args.
|
|
1242
|
-
content: call.summary || (typeof a.toolSummary === 'string' ? a.toolSummary : undefined) || undefined,
|
|
1243
|
-
});
|
|
1244
|
-
}
|
|
1245
|
-
return events;
|
|
1246
|
-
}
|
|
1247
|
-
// ---------------------------------------------------------------------------
|
|
1248
|
-
// Composite session file paths
|
|
1249
|
-
// ---------------------------------------------------------------------------
|
|
1250
|
-
/**
|
|
1251
|
-
* Separator between a container file and the id it holds inside a *composite*
|
|
1252
|
-
* session `file_path`. Some harnesses keep every session in ONE file (OpenCode's
|
|
1253
|
-
* single `opencode.db`), so the index stores `<container>#<session-id>` rather
|
|
1254
|
-
* than one path per session — e.g.
|
|
1255
|
-
* `/home/u/.local/share/opencode/opencode.db#ses_02410a2c…`.
|
|
1256
|
-
*/
|
|
1257
|
-
const SESSION_FILE_PATH_SEP = '#';
|
|
1258
|
-
/**
|
|
1259
|
-
* Split a stored session `file_path` into its on-disk container and the optional
|
|
1260
|
-
* in-container fragment. For a plain per-session file the container is the path
|
|
1261
|
-
* itself and `fragment` is undefined; for a composite path it is the part before
|
|
1262
|
-
* the first `#` and the id after it.
|
|
1263
|
-
*/
|
|
1264
|
-
export function splitSessionFilePath(filePath) {
|
|
1265
|
-
const hash = filePath.indexOf(SESSION_FILE_PATH_SEP);
|
|
1266
|
-
if (hash < 0)
|
|
1267
|
-
return { container: filePath, fragment: undefined };
|
|
1268
|
-
return { container: filePath.slice(0, hash), fragment: filePath.slice(hash + 1) || undefined };
|
|
1269
|
-
}
|
|
1270
|
-
/**
|
|
1271
|
-
* The filesystem path whose existence/stat decides whether a session row is
|
|
1272
|
-
* stale. For a composite `file_path` this is the CONTAINER file — the row is a
|
|
1273
|
-
* record inside it, never a filesystem entry of its own — so a composite session
|
|
1274
|
-
* is stale only when its container is gone. For a plain path it is the path
|
|
1275
|
-
* itself. Keying off the composite FORM (a `#` fragment), not any harness name,
|
|
1276
|
-
* means any future single-file-DB harness inherits the correct behavior.
|
|
1277
|
-
*/
|
|
1278
|
-
export function sessionFilePathContainer(filePath) {
|
|
1279
|
-
return splitSessionFilePath(filePath).container;
|
|
1280
|
-
}
|
|
1281
|
-
/**
|
|
1282
|
-
* Read `signals.json` next to a Grok transcript. Returns `undefined` when the
|
|
1283
|
-
* file is absent or unreadable — a Grok session simply has no signals then, and
|
|
1284
|
-
* the fold reports what it does have rather than inventing zeros.
|
|
1285
|
-
*/
|
|
1286
|
-
export function readGrokSignals(filePath) {
|
|
1287
|
-
const signalsPath = filePath.endsWith('signals.json')
|
|
1288
|
-
? filePath
|
|
1289
|
-
: path.join(path.dirname(filePath), 'signals.json');
|
|
1290
|
-
let raw;
|
|
1291
|
-
try {
|
|
1292
|
-
raw = JSON.parse(fs.readFileSync(signalsPath, 'utf-8'));
|
|
1293
|
-
}
|
|
1294
|
-
catch {
|
|
1295
|
-
return undefined;
|
|
1296
|
-
}
|
|
1297
|
-
if (!raw || typeof raw !== 'object')
|
|
1298
|
-
return undefined;
|
|
1299
|
-
const count = (value) => (typeof value === 'number' && Number.isFinite(value) && value > 0 ? value : 0);
|
|
1300
|
-
return {
|
|
1301
|
-
gitCommitCount: count(raw.gitCommitCount),
|
|
1302
|
-
prCreatedCount: count(raw.prCreatedCount),
|
|
1303
|
-
prMergedCount: count(raw.prMergedCount),
|
|
1304
|
-
toolFailureCount: count(raw.toolFailureCount),
|
|
1305
|
-
};
|
|
1306
|
-
}
|
|
1307
|
-
export function parseGrok(filePath) {
|
|
1308
|
-
const sessionDir = path.dirname(filePath);
|
|
1309
|
-
const historyPath = filePath.endsWith('chat_history.jsonl')
|
|
1310
|
-
? filePath
|
|
1311
|
-
: path.join(sessionDir, 'chat_history.jsonl');
|
|
1312
|
-
if (!fs.existsSync(historyPath))
|
|
1313
|
-
return [];
|
|
1314
|
-
let timestamp;
|
|
1315
|
-
try {
|
|
1316
|
-
const summaryPath = filePath.endsWith('summary.json')
|
|
1317
|
-
? filePath
|
|
1318
|
-
: path.join(sessionDir, 'summary.json');
|
|
1319
|
-
if (fs.existsSync(summaryPath)) {
|
|
1320
|
-
const summary = JSON.parse(fs.readFileSync(summaryPath, 'utf-8'));
|
|
1321
|
-
if (typeof summary?.created_at === 'string')
|
|
1322
|
-
timestamp = summary.created_at;
|
|
1323
|
-
}
|
|
1324
|
-
}
|
|
1325
|
-
catch { /* fall back to mtime below */ }
|
|
1326
|
-
if (!timestamp) {
|
|
1327
|
-
let mtime = null;
|
|
1328
|
-
try {
|
|
1329
|
-
mtime = fs.statSync(historyPath).mtime;
|
|
1330
|
-
}
|
|
1331
|
-
catch {
|
|
1332
|
-
mtime = null;
|
|
1333
|
-
}
|
|
1334
|
-
timestamp = (mtime ?? new Date()).toISOString();
|
|
1335
|
-
}
|
|
1336
|
-
const content = safeReadSessionFile(historyPath);
|
|
1337
|
-
const lines = content.split('\n').filter(l => l.trim());
|
|
1338
|
-
const events = [];
|
|
1339
|
-
const toolCallMap = new Map();
|
|
1340
|
-
// Grok text is either a plain string (assistant) or an array of typed blocks
|
|
1341
|
-
// (user: `{ type: 'text', text }`; reasoning summary: `{ text | summary_text }`).
|
|
1342
|
-
const extractText = (raw) => {
|
|
1343
|
-
if (typeof raw === 'string')
|
|
1344
|
-
return raw.trim();
|
|
1345
|
-
if (Array.isArray(raw)) {
|
|
1346
|
-
return raw
|
|
1347
|
-
.map((part) => typeof part?.text === 'string'
|
|
1348
|
-
? part.text
|
|
1349
|
-
: typeof part?.summary_text === 'string'
|
|
1350
|
-
? part.summary_text
|
|
1351
|
-
: '')
|
|
1352
|
-
.join('')
|
|
1353
|
-
.trim();
|
|
1354
|
-
}
|
|
1355
|
-
return '';
|
|
1356
|
-
};
|
|
1357
|
-
for (const line of lines) {
|
|
1358
|
-
let msg;
|
|
1359
|
-
try {
|
|
1360
|
-
msg = JSON.parse(line);
|
|
1361
|
-
}
|
|
1362
|
-
catch {
|
|
1363
|
-
continue;
|
|
1364
|
-
}
|
|
1365
|
-
const type = msg?.type;
|
|
1366
|
-
if (type === 'user') {
|
|
1367
|
-
const text = extractText(msg.content);
|
|
1368
|
-
if (text)
|
|
1369
|
-
events.push({ type: 'message', agent: 'grok', timestamp, role: 'user', content: text });
|
|
1370
|
-
}
|
|
1371
|
-
else if (type === 'assistant') {
|
|
1372
|
-
const text = extractText(msg.content);
|
|
1373
|
-
if (text)
|
|
1374
|
-
events.push({ type: 'message', agent: 'grok', timestamp, role: 'assistant', content: text });
|
|
1375
|
-
const calls = Array.isArray(msg.tool_calls) ? msg.tool_calls : [];
|
|
1376
|
-
for (const call of calls) {
|
|
1377
|
-
const toolName = typeof call?.name === 'string' ? call.name : 'unknown';
|
|
1378
|
-
let args = {};
|
|
1379
|
-
if (call?.arguments && typeof call.arguments === 'object') {
|
|
1380
|
-
args = call.arguments;
|
|
1381
|
-
}
|
|
1382
|
-
else if (typeof call?.arguments === 'string') {
|
|
1383
|
-
try {
|
|
1384
|
-
args = JSON.parse(call.arguments);
|
|
1385
|
-
}
|
|
1386
|
-
catch {
|
|
1387
|
-
args = { _raw: call.arguments };
|
|
1388
|
-
}
|
|
1389
|
-
}
|
|
1390
|
-
if (typeof call?.id === 'string')
|
|
1391
|
-
toolCallMap.set(call.id, toolName);
|
|
1392
|
-
events.push({
|
|
1393
|
-
type: 'tool_use',
|
|
1394
|
-
agent: 'grok',
|
|
1395
|
-
timestamp,
|
|
1396
|
-
tool: toolName,
|
|
1397
|
-
callId: typeof call?.id === 'string' ? call.id : undefined,
|
|
1398
|
-
args,
|
|
1399
|
-
path: args.path || args.file_path || undefined,
|
|
1400
|
-
command: typeof args.command === 'string' ? args.command : undefined,
|
|
1401
|
-
});
|
|
1402
|
-
}
|
|
1403
|
-
}
|
|
1404
|
-
else if (type === 'reasoning') {
|
|
1405
|
-
const text = extractText(msg.summary);
|
|
1406
|
-
if (text)
|
|
1407
|
-
events.push({ type: 'thinking', agent: 'grok', timestamp, content: text });
|
|
1408
|
-
}
|
|
1409
|
-
else if (type === 'tool_result') {
|
|
1410
|
-
const callId = typeof msg.tool_call_id === 'string' ? msg.tool_call_id : undefined;
|
|
1411
|
-
const toolName = (callId && toolCallMap.get(callId)) || 'unknown';
|
|
1412
|
-
const output = typeof msg.content === 'string' ? msg.content : extractText(msg.content);
|
|
1413
|
-
const structuredError = msg.is_error === true;
|
|
1414
|
-
const structuredSuccess = msg.is_error === false;
|
|
1415
|
-
const displayAsError = structuredError || (typeof output === 'string' && output.startsWith('Error:'));
|
|
1416
|
-
events.push({
|
|
1417
|
-
type: displayAsError ? 'error' : 'tool_result',
|
|
1418
|
-
agent: 'grok',
|
|
1419
|
-
timestamp,
|
|
1420
|
-
tool: toolName,
|
|
1421
|
-
callId,
|
|
1422
|
-
success: structuredError ? false : structuredSuccess ? true : undefined,
|
|
1423
|
-
outcome: structuredError ? 'error' : structuredSuccess ? 'ok' : 'unknown',
|
|
1424
|
-
output: output,
|
|
1425
|
-
});
|
|
1426
|
-
if (callId)
|
|
1427
|
-
toolCallMap.delete(callId);
|
|
1428
|
-
}
|
|
1429
|
-
// `system` lines are the system prompt — intentionally skipped.
|
|
1430
|
-
}
|
|
1431
|
-
return events;
|
|
1432
|
-
}
|
|
1433
|
-
/**
|
|
1434
|
-
* Byte/char caps for the OpenCode tool-part projection below. Numeric
|
|
1435
|
-
* constants, interpolated into the SQL — never user input.
|
|
1436
|
-
*/
|
|
1437
|
-
const OPENCODE_OUTPUT_MAX_CHARS = 2000;
|
|
1438
|
-
const OPENCODE_INPUT_MAX_BYTES = 4000;
|
|
1439
|
-
/**
|
|
1440
|
-
* The transcript query {@link parseOpenCode} runs, exported so a test can assert
|
|
1441
|
-
* the projection's real cost against a database instead of re-typing the SQL.
|
|
1442
|
-
*
|
|
1443
|
-
* A tool part is PROJECTED to exactly the fields the `case 'tool'` branch below
|
|
1444
|
-
* reads — `tool`, `callID`, `state.status`, `state.input`, `state.output` —
|
|
1445
|
-
* rather than carried whole. Two things this has to get right at once:
|
|
1446
|
-
*
|
|
1447
|
-
* - Keep `state.input`. It carries `filePath` / `command`, and losing it is
|
|
1448
|
-
* what left `recentDirectoriesTouched` empty (RUSH-2358).
|
|
1449
|
-
* - Stay bounded. A tool part is not bounded by its output: on a real
|
|
1450
|
-
* `opencode.db` the largest part is 1,346,068 bytes of which
|
|
1451
|
-
* `state.attachments` (a base64 data URL from `read`) is 1,345,674, while
|
|
1452
|
-
* `state.output` is 23. Truncating only `state.output` therefore bounded
|
|
1453
|
-
* nothing — it took one session's loaded tool payload from 299,365 to
|
|
1454
|
-
* 1,911,209 bytes. The projection drops `attachments` (and every other
|
|
1455
|
-
* unread key) outright, caps `state.output`, and collapses an oversized
|
|
1456
|
-
* `state.input` to just its addressing fields. Those are the keys the
|
|
1457
|
-
* enrichment reads — `filePath`/`path` for an edit and `cwd`/`workdir`/
|
|
1458
|
-
* `working_directory` for a shell (`extractRecentDirectoriesTouched` in
|
|
1459
|
-
* state.ts), plus `command`/`description`, themselves capped since a command
|
|
1460
|
-
* can be arbitrarily long. Above the cap every other input key (an `edit`'s
|
|
1461
|
-
* `oldString`/`newString`) is gone, deliberately — nothing downstream reads
|
|
1462
|
-
* them, and they are the weight.
|
|
1463
|
-
*
|
|
1464
|
-
* `json_valid` guards every `json_extract`: SQLite raises "malformed JSON" on a
|
|
1465
|
-
* non-JSON value, which aborts the WHOLE query, so one bad `part` row would
|
|
1466
|
-
* otherwise cost the entire transcript. Note the single-argument form is
|
|
1467
|
-
* RFC-8259-strict — it rejects a JSONB blob that `json_extract` would accept.
|
|
1468
|
-
* That is correct for today's schema (`part.data` / `message.data` are TEXT on
|
|
1469
|
-
* a real database); if OpenCode ever migrates them to JSONB, these guards must
|
|
1470
|
-
* move to `json_valid(data, 6)` or they will drop every row.
|
|
1471
|
-
*
|
|
1472
|
-
* The session id is bound as a parameter; the two caps are numeric literals.
|
|
1473
|
-
*/
|
|
1474
|
-
export const OPENCODE_TRANSCRIPT_QUERY = `
|
|
1475
|
-
SELECT
|
|
1476
|
-
CASE WHEN json_valid(m.data) THEN json_extract(m.data, '$.role') END AS role,
|
|
1477
|
-
CASE WHEN json_valid(p.data) THEN json_extract(p.data, '$.type') END AS part_type,
|
|
1478
|
-
CASE
|
|
1479
|
-
WHEN json_valid(p.data) AND json_extract(p.data, '$.type') = 'tool'
|
|
1480
|
-
THEN json_object(
|
|
1481
|
-
'type', 'tool',
|
|
1482
|
-
'tool', json_extract(p.data, '$.tool'),
|
|
1483
|
-
'callID', json_extract(p.data, '$.callID'),
|
|
1484
|
-
'state', json_object(
|
|
1485
|
-
'status', json_extract(p.data, '$.state.status'),
|
|
1486
|
-
/* state.title is the human label OpenCode writes per call ("Read
|
|
1487
|
-
src/index.ts") — kept so the timeline now-line reads as the harness
|
|
1488
|
-
wrote it (PHNX-3939). A BLOCK comment, never a line comment: this
|
|
1489
|
-
template is flattened to one line below, so a line comment would
|
|
1490
|
-
swallow the rest of the query. */
|
|
1491
|
-
'title', json_extract(p.data, '$.state.title'),
|
|
1492
|
-
'input', CASE
|
|
1493
|
-
WHEN LENGTH(CAST(COALESCE(json_extract(p.data, '$.state.input'), '') AS BLOB)) > ${OPENCODE_INPUT_MAX_BYTES}
|
|
1494
|
-
THEN json_object(
|
|
1495
|
-
'filePath', json_extract(p.data, '$.state.input.filePath'),
|
|
1496
|
-
'path', json_extract(p.data, '$.state.input.path'),
|
|
1497
|
-
'command', substr(COALESCE(json_extract(p.data, '$.state.input.command'), ''), 1, ${OPENCODE_OUTPUT_MAX_CHARS}),
|
|
1498
|
-
'description', substr(COALESCE(json_extract(p.data, '$.state.input.description'), ''), 1, ${OPENCODE_OUTPUT_MAX_CHARS}),
|
|
1499
|
-
'cwd', json_extract(p.data, '$.state.input.cwd'),
|
|
1500
|
-
'workdir', json_extract(p.data, '$.state.input.workdir'),
|
|
1501
|
-
'working_directory', json_extract(p.data, '$.state.input.working_directory')
|
|
1502
|
-
)
|
|
1503
|
-
ELSE json_extract(p.data, '$.state.input')
|
|
1504
|
-
END,
|
|
1505
|
-
'output', substr(COALESCE(json_extract(p.data, '$.state.output'), ''), 1, ${OPENCODE_OUTPUT_MAX_CHARS})
|
|
1506
|
-
)
|
|
1507
|
-
)
|
|
1508
|
-
ELSE p.data
|
|
1509
|
-
END AS part_data,
|
|
1510
|
-
m.time_created AS time_created
|
|
1511
|
-
FROM message m
|
|
1512
|
-
JOIN part p ON p.message_id = m.id AND p.session_id = m.session_id
|
|
1513
|
-
WHERE m.session_id = ?
|
|
1514
|
-
ORDER BY m.time_created ASC, p.time_created ASC;
|
|
1515
|
-
`.replace(/\n/g, ' ');
|
|
1516
|
-
export function parseOpenCode(filePath) {
|
|
1517
|
-
const { container: dbPath, fragment: sessionId } = splitSessionFilePath(filePath);
|
|
1518
|
-
if (!dbPath || !sessionId)
|
|
1519
|
-
return [];
|
|
1520
|
-
const events = [];
|
|
1521
|
-
// Read through the node/bun SQLite wrapper (not the `sqlite3` CLI) so this
|
|
1522
|
-
// works on every OS — the CLI is absent on Windows.
|
|
1523
|
-
let rows;
|
|
1524
|
-
// OpenCode stores the session's checklist in its own `todo` table (the current
|
|
1525
|
-
// snapshot, not a history). Emitted below as one `todo_write` tool_use event so
|
|
1526
|
-
// the shared enrichment (`extractTodoProgressFromEvents`) computes `todos`
|
|
1527
|
-
// uniformly with every other harness (RUSH-2358).
|
|
1528
|
-
let todoRows = [];
|
|
1529
|
-
let db;
|
|
1530
|
-
try {
|
|
1531
|
-
// Messages with their parts, ordered chronologically. The query — and why
|
|
1532
|
-
// the tool part is projected rather than carried whole — is documented on
|
|
1533
|
-
// OPENCODE_TRANSCRIPT_QUERY above.
|
|
1534
|
-
db = new Database(dbPath);
|
|
1535
|
-
rows = db.prepare(OPENCODE_TRANSCRIPT_QUERY).all(sessionId);
|
|
1536
|
-
// The `todo` table is a newer OpenCode addition. Probe for it the same way
|
|
1537
|
-
// the scanner probes newer `session` columns, rather than wrapping the read
|
|
1538
|
-
// in a blanket catch — a catch there reported a locked, corrupt, or
|
|
1539
|
-
// permission-denied database as "this session has no todos".
|
|
1540
|
-
//
|
|
1541
|
-
// Row COUNT, not an empty-`get()` sentinel: the two production runtimes
|
|
1542
|
-
// disagree on what `get()` returns for no row — node:sqlite gives
|
|
1543
|
-
// `undefined`, bun:sqlite gives `null` (both ship; see sqlite.ts). A check
|
|
1544
|
-
// written against either sentinel is always-true on the other runtime,
|
|
1545
|
-
// which would run the `todo` SELECT on a schema that has no such table,
|
|
1546
|
-
// throw, and hand the whole transcript to the outer catch — an empty
|
|
1547
|
-
// session, silently, and only in the shipped Bun binary. `.all().length`
|
|
1548
|
-
// cannot express that disagreement.
|
|
1549
|
-
const hasTodoTable = db
|
|
1550
|
-
.prepare(`SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'todo';`)
|
|
1551
|
-
.all().length > 0;
|
|
1552
|
-
if (hasTodoTable) {
|
|
1553
|
-
todoRows = db
|
|
1554
|
-
.prepare('SELECT content, status, time_updated FROM todo WHERE session_id = ? ORDER BY position ASC;')
|
|
1555
|
-
.all(sessionId);
|
|
1556
|
-
}
|
|
1557
|
-
}
|
|
1558
|
-
catch {
|
|
1559
|
-
/* DB not accessible, sqlite module unavailable, or query failed */
|
|
1560
|
-
return events;
|
|
1561
|
-
}
|
|
1562
|
-
finally {
|
|
1563
|
-
try {
|
|
1564
|
-
db?.close();
|
|
1565
|
-
}
|
|
1566
|
-
catch {
|
|
1567
|
-
/* best-effort close */
|
|
1568
|
-
}
|
|
1569
|
-
}
|
|
1570
|
-
try {
|
|
1571
|
-
for (const row of rows) {
|
|
1572
|
-
const role = typeof row.role === 'string' ? row.role : '';
|
|
1573
|
-
const partType = typeof row.part_type === 'string' ? row.part_type : '';
|
|
1574
|
-
const partDataStr = typeof row.part_data === 'string' ? row.part_data : '';
|
|
1575
|
-
const timeMs = typeof row.time_created === 'number' ? row.time_created : parseInt(String(row.time_created), 10);
|
|
1576
|
-
const timestamp = isNaN(timeMs) ? new Date().toISOString() : new Date(timeMs).toISOString();
|
|
1577
|
-
let partData;
|
|
1578
|
-
try {
|
|
1579
|
-
partData = JSON.parse(partDataStr);
|
|
1580
|
-
}
|
|
1581
|
-
catch {
|
|
1582
|
-
/* malformed part data, skip */
|
|
1583
|
-
continue;
|
|
1584
|
-
}
|
|
1585
|
-
switch (partType) {
|
|
1586
|
-
case 'text': {
|
|
1587
|
-
const text = (partData.text || '').trim();
|
|
1588
|
-
if (text) {
|
|
1589
|
-
events.push({
|
|
1590
|
-
type: 'message',
|
|
1591
|
-
agent: 'opencode',
|
|
1592
|
-
timestamp,
|
|
1593
|
-
role: role === 'user' ? 'user' : 'assistant',
|
|
1594
|
-
content: text,
|
|
1595
|
-
});
|
|
1596
|
-
}
|
|
1597
|
-
break;
|
|
1598
|
-
}
|
|
1599
|
-
case 'reasoning': {
|
|
1600
|
-
const text = (partData.text || '').trim();
|
|
1601
|
-
if (text) {
|
|
1602
|
-
events.push({
|
|
1603
|
-
type: 'thinking',
|
|
1604
|
-
agent: 'opencode',
|
|
1605
|
-
timestamp,
|
|
1606
|
-
content: text,
|
|
1607
|
-
});
|
|
1608
|
-
}
|
|
1609
|
-
break;
|
|
1610
|
-
}
|
|
1611
|
-
case 'tool': {
|
|
1612
|
-
const toolName = partData.tool || 'unknown';
|
|
1613
|
-
const state = partData.state || {};
|
|
1614
|
-
const input = state.input || {};
|
|
1615
|
-
const output = state.output || '';
|
|
1616
|
-
const callId = typeof partData.callID === 'string' ? partData.callID : undefined;
|
|
1617
|
-
// OpenCode writes both a per-call `input.description` and a rendered
|
|
1618
|
-
// `state.title`; either is the label a person would read.
|
|
1619
|
-
const label = typeof input.description === 'string' && input.description.trim()
|
|
1620
|
-
? input.description.trim()
|
|
1621
|
-
: typeof state.title === 'string' && state.title.trim()
|
|
1622
|
-
? state.title.trim()
|
|
1623
|
-
: undefined;
|
|
1624
|
-
events.push({
|
|
1625
|
-
type: 'tool_use',
|
|
1626
|
-
agent: 'opencode',
|
|
1627
|
-
timestamp,
|
|
1628
|
-
tool: toolName,
|
|
1629
|
-
callId,
|
|
1630
|
-
args: input,
|
|
1631
|
-
command: toolName === 'shell' ? input.command : undefined,
|
|
1632
|
-
path: input.filePath || input.path || undefined,
|
|
1633
|
-
...(label ? { label } : {}),
|
|
1634
|
-
});
|
|
1635
|
-
if (state.status === 'completed' || state.status === 'error') {
|
|
1636
|
-
const outputStr = typeof output === 'string' ? output : JSON.stringify(output);
|
|
1637
|
-
events.push({
|
|
1638
|
-
type: state.status === 'error' ? 'error' : 'tool_result',
|
|
1639
|
-
agent: 'opencode',
|
|
1640
|
-
timestamp,
|
|
1641
|
-
tool: toolName,
|
|
1642
|
-
callId,
|
|
1643
|
-
success: state.status === 'completed',
|
|
1644
|
-
output: outputStr,
|
|
1645
|
-
});
|
|
1646
|
-
}
|
|
1647
|
-
break;
|
|
1648
|
-
}
|
|
1649
|
-
case 'patch': {
|
|
1650
|
-
// OpenCode's own edit ledger for one step: the exact paths it wrote.
|
|
1651
|
-
// The part records no add/update/delete verb, so the operation still
|
|
1652
|
-
// comes from the tool that produced it (see foldSessionFiles).
|
|
1653
|
-
const files = Array.isArray(partData.files) ? partData.files : [];
|
|
1654
|
-
const changes = files
|
|
1655
|
-
.map((file) => (typeof file === 'string' ? file : file?.path))
|
|
1656
|
-
.filter((filePath) => typeof filePath === 'string' && filePath.length > 0)
|
|
1657
|
-
.map((filePath) => ({ path: filePath, op: 'modified' }));
|
|
1658
|
-
if (changes.length) {
|
|
1659
|
-
events.push({ type: 'file_change', agent: 'opencode', timestamp, changes });
|
|
1660
|
-
}
|
|
1661
|
-
break;
|
|
1662
|
-
}
|
|
1663
|
-
case 'compaction': {
|
|
1664
|
-
events.push({
|
|
1665
|
-
type: 'hook', agent: 'opencode', timestamp,
|
|
1666
|
-
hookName: 'ContextCompaction', content: 'context compacted',
|
|
1667
|
-
});
|
|
1668
|
-
break;
|
|
1669
|
-
}
|
|
1670
|
-
// Skip step-start, step-finish, file — not needed for transcript/trace
|
|
1671
|
-
}
|
|
1672
|
-
}
|
|
1673
|
-
}
|
|
1674
|
-
catch {
|
|
1675
|
-
/* malformed row payload — return what we parsed so far */
|
|
1676
|
-
}
|
|
1677
|
-
// Emit the OpenCode `todo` table as one `todo_write` snapshot so the shared
|
|
1678
|
-
// enrichment layer derives `todos` the same way it does for every harness that
|
|
1679
|
-
// records a checklist tool. `todo_write` is in SNAPSHOT_TODO_TOOLS, and the
|
|
1680
|
-
// enrichment reads `args.todos`, so the shape matches without special-casing.
|
|
1681
|
-
const todos = todoRows
|
|
1682
|
-
.map(t => ({
|
|
1683
|
-
content: typeof t.content === 'string' ? t.content : '',
|
|
1684
|
-
status: typeof t.status === 'string' ? t.status : 'pending',
|
|
1685
|
-
}))
|
|
1686
|
-
.filter(t => t.content.trim());
|
|
1687
|
-
if (todos.length) {
|
|
1688
|
-
const lastTodoMs = todoRows.reduce((max, t) => {
|
|
1689
|
-
const ms = typeof t.time_updated === 'number' ? t.time_updated : parseInt(String(t.time_updated), 10);
|
|
1690
|
-
return Number.isFinite(ms) && ms > max ? ms : max;
|
|
1691
|
-
}, 0);
|
|
1692
|
-
events.push({
|
|
1693
|
-
type: 'tool_use',
|
|
1694
|
-
agent: 'opencode',
|
|
1695
|
-
timestamp: lastTodoMs > 0 ? new Date(lastTodoMs).toISOString() : new Date().toISOString(),
|
|
1696
|
-
tool: 'todo_write',
|
|
1697
|
-
args: { todos },
|
|
1698
|
-
});
|
|
1699
|
-
}
|
|
1700
|
-
return events;
|
|
1701
|
-
}
|
|
1702
|
-
// ---------------------------------------------------------------------------
|
|
1703
|
-
// OpenCode parser — cloud (normalized JSONL)
|
|
1704
|
-
// ---------------------------------------------------------------------------
|
|
1705
|
-
//
|
|
1706
|
-
// OpenCode stores sessions in a SQLite DB, so the offline path reads a
|
|
1707
|
-
// `opencode.db#<session>` composite (parseOpenCode above). The CLOUD path is
|
|
1708
|
-
// different: the factory converts that DB into a flat, normalized JSONL
|
|
1709
|
-
// transcript at capture time (prix/factory opencode-capture.ts, PHNX-3845), so
|
|
1710
|
-
// the whole cloud pipeline stays SQLite-free downstream. This parser reads that
|
|
1711
|
-
// JSONL; it's routed from TRANSCRIPT_PARSERS only when the file lives in the
|
|
1712
|
-
// cloud session cache (isCloudSessionPath).
|
|
1713
|
-
//
|
|
1714
|
-
// Each line is one of:
|
|
1715
|
-
// transcript row:
|
|
1716
|
-
// { role: "user"|"assistant", part_type: "text"|"reasoning"|"tool",
|
|
1717
|
-
// part_data: <json string>, time_created: <ms number> }
|
|
1718
|
-
// todo snapshot (at most one, emitted last):
|
|
1719
|
-
// { part_type: "todo", todos: [{content,status}], time_created: <ms> }
|
|
1720
|
-
//
|
|
1721
|
-
// The per-part logic mirrors parseOpenCode's post-query switch (and prix/api's
|
|
1722
|
-
// server-side parseOpencode) so the event stream is identical to the offline
|
|
1723
|
-
// path. NOTE: the shell tool is named `bash` on real opencode (>=1.18.x), not
|
|
1724
|
-
// `shell` — map `command` for both so a shell step reads by its command line.
|
|
1725
|
-
export function parseOpencodeCloud(filePath) {
|
|
1726
|
-
const content = safeReadSessionFile(filePath);
|
|
1727
|
-
const lines = content.split('\n').filter(l => l.trim());
|
|
1728
|
-
const events = [];
|
|
1729
|
-
for (const line of lines) {
|
|
1730
|
-
let raw;
|
|
1731
|
-
try {
|
|
1732
|
-
raw = JSON.parse(line);
|
|
1733
|
-
}
|
|
1734
|
-
catch {
|
|
1735
|
-
/* malformed JSONL line, skip */
|
|
1736
|
-
continue;
|
|
1737
|
-
}
|
|
1738
|
-
const partType = typeof raw.part_type === 'string' ? raw.part_type : '';
|
|
1739
|
-
const timeMs = typeof raw.time_created === 'number'
|
|
1740
|
-
? raw.time_created
|
|
1741
|
-
: parseInt(String(raw.time_created), 10);
|
|
1742
|
-
const timestamp = Number.isFinite(timeMs)
|
|
1743
|
-
? new Date(timeMs).toISOString()
|
|
1744
|
-
: new Date().toISOString();
|
|
1745
|
-
// Todo snapshot: emit one `todo_write` tool_use so the shared enrichment
|
|
1746
|
-
// (`extractTodoProgressFromEvents`) derives `todos` the same way it does for
|
|
1747
|
-
// every other harness — the offline parser emits the identical event.
|
|
1748
|
-
if (partType === 'todo') {
|
|
1749
|
-
const todos = Array.isArray(raw.todos) ? raw.todos : [];
|
|
1750
|
-
if (todos.length) {
|
|
1751
|
-
events.push({
|
|
1752
|
-
type: 'tool_use',
|
|
1753
|
-
agent: 'opencode',
|
|
1754
|
-
timestamp,
|
|
1755
|
-
tool: 'todo_write',
|
|
1756
|
-
args: { todos },
|
|
1757
|
-
});
|
|
1758
|
-
}
|
|
1759
|
-
continue;
|
|
1760
|
-
}
|
|
1761
|
-
let partData;
|
|
1762
|
-
try {
|
|
1763
|
-
partData = JSON.parse(typeof raw.part_data === 'string' ? raw.part_data : '');
|
|
1764
|
-
}
|
|
1765
|
-
catch {
|
|
1766
|
-
/* malformed part data, skip */
|
|
1767
|
-
continue;
|
|
1768
|
-
}
|
|
1769
|
-
switch (partType) {
|
|
1770
|
-
case 'text': {
|
|
1771
|
-
const text = (partData.text || '').trim();
|
|
1772
|
-
if (text) {
|
|
1773
|
-
events.push({
|
|
1774
|
-
type: 'message',
|
|
1775
|
-
agent: 'opencode',
|
|
1776
|
-
timestamp,
|
|
1777
|
-
role: raw.role === 'user' ? 'user' : 'assistant',
|
|
1778
|
-
content: text,
|
|
1779
|
-
});
|
|
1780
|
-
}
|
|
1781
|
-
break;
|
|
1782
|
-
}
|
|
1783
|
-
case 'reasoning': {
|
|
1784
|
-
const text = (partData.text || '').trim();
|
|
1785
|
-
if (text) {
|
|
1786
|
-
events.push({
|
|
1787
|
-
type: 'thinking',
|
|
1788
|
-
agent: 'opencode',
|
|
1789
|
-
timestamp,
|
|
1790
|
-
content: text,
|
|
1791
|
-
});
|
|
1792
|
-
}
|
|
1793
|
-
break;
|
|
1794
|
-
}
|
|
1795
|
-
case 'tool': {
|
|
1796
|
-
const toolName = partData.tool || 'unknown';
|
|
1797
|
-
const state = partData.state || {};
|
|
1798
|
-
const input = state.input || {};
|
|
1799
|
-
const output = state.output || '';
|
|
1800
|
-
const callId = typeof partData.callID === 'string' ? partData.callID : undefined;
|
|
1801
|
-
events.push({
|
|
1802
|
-
type: 'tool_use',
|
|
1803
|
-
agent: 'opencode',
|
|
1804
|
-
timestamp,
|
|
1805
|
-
tool: toolName,
|
|
1806
|
-
callId,
|
|
1807
|
-
args: input,
|
|
1808
|
-
command: toolName === 'bash' || toolName === 'shell' ? input.command : undefined,
|
|
1809
|
-
path: input.filePath || input.path || undefined,
|
|
1810
|
-
});
|
|
1811
|
-
if (state.status === 'completed' || state.status === 'error') {
|
|
1812
|
-
const outputStr = typeof output === 'string' ? output : JSON.stringify(output);
|
|
1813
|
-
events.push({
|
|
1814
|
-
type: state.status === 'error' ? 'error' : 'tool_result',
|
|
1815
|
-
agent: 'opencode',
|
|
1816
|
-
timestamp,
|
|
1817
|
-
tool: toolName,
|
|
1818
|
-
callId,
|
|
1819
|
-
success: state.status === 'completed',
|
|
1820
|
-
output: outputStr,
|
|
1821
|
-
});
|
|
1822
|
-
}
|
|
1823
|
-
break;
|
|
1824
|
-
}
|
|
1825
|
-
// step-start / step-finish / patch / file never reach the JSONL (dropped
|
|
1826
|
-
// at capture time) — nothing to handle here.
|
|
1827
|
-
}
|
|
1828
|
-
}
|
|
1829
|
-
return events;
|
|
1830
|
-
}
|
|
1831
|
-
// ---------------------------------------------------------------------------
|
|
1832
|
-
// Rush parser
|
|
1833
|
-
//
|
|
1834
|
-
// Rush messages.jsonl format is flat: one JSON object per line with
|
|
1835
|
-
// { id, session_id, role, type, content, created_at, tool_call_id?, name? }
|
|
1836
|
-
// type ∈ {message, tool_call, tool_result}
|
|
1837
|
-
// content varies by type:
|
|
1838
|
-
// message -> { text: string }
|
|
1839
|
-
// tool_call -> { input: {...} }
|
|
1840
|
-
// tool_result -> { input, output } (output.success === false marks an error)
|
|
1841
|
-
// ---------------------------------------------------------------------------
|
|
1842
|
-
/** Parse a Rush JSONL session file into normalized events. */
|
|
1843
|
-
export function parseRush(filePath) {
|
|
1844
|
-
const content = safeReadSessionFile(filePath);
|
|
1845
|
-
const lines = content.split('\n').filter(l => l.trim());
|
|
1846
|
-
const events = [];
|
|
1847
|
-
// Map tool_call id -> {tool, args} for correlating with tool_result.
|
|
1848
|
-
const toolCallMap = new Map();
|
|
1849
|
-
for (const line of lines) {
|
|
1850
|
-
let raw;
|
|
1851
|
-
try {
|
|
1852
|
-
raw = JSON.parse(line);
|
|
1853
|
-
}
|
|
1854
|
-
catch {
|
|
1855
|
-
/* malformed JSONL line, skip */
|
|
1856
|
-
continue;
|
|
1857
|
-
}
|
|
1858
|
-
const type = raw.type;
|
|
1859
|
-
const timestamp = typeof raw.created_at === 'string' ? raw.created_at : new Date().toISOString();
|
|
1860
|
-
const content = raw.content && typeof raw.content === 'object' && !Array.isArray(raw.content)
|
|
1861
|
-
? raw.content
|
|
1862
|
-
: {};
|
|
1863
|
-
if (type === 'message') {
|
|
1864
|
-
const text = typeof content.text === 'string' ? content.text.trim() : '';
|
|
1865
|
-
if (!text)
|
|
1866
|
-
continue;
|
|
1867
|
-
const role = raw.role === 'user' ? 'user' : 'assistant';
|
|
1868
|
-
// Rush wraps the first user turn in <user_input>...</user_input> — strip.
|
|
1869
|
-
const cleaned = text
|
|
1870
|
-
.replace(/^<user_input>/, '')
|
|
1871
|
-
.replace(/<\/user_input>$/, '')
|
|
1872
|
-
.trim();
|
|
1873
|
-
// Skip sentinel execution-start marker that isn't human-readable.
|
|
1874
|
-
if (raw.role === 'system' && cleaned === 'execution_start')
|
|
1875
|
-
continue;
|
|
1876
|
-
events.push({
|
|
1877
|
-
type: 'message',
|
|
1878
|
-
agent: 'rush',
|
|
1879
|
-
timestamp,
|
|
1880
|
-
role,
|
|
1881
|
-
content: cleaned,
|
|
1882
|
-
});
|
|
1883
|
-
}
|
|
1884
|
-
else if (type === 'tool_call') {
|
|
1885
|
-
const toolName = typeof raw.name === 'string' && raw.name.length > 0 ? raw.name : 'unknown';
|
|
1886
|
-
const args = content.input && typeof content.input === 'object' && !Array.isArray(content.input)
|
|
1887
|
-
? content.input
|
|
1888
|
-
: {};
|
|
1889
|
-
const callId = typeof raw.tool_call_id === 'string' ? raw.tool_call_id : undefined;
|
|
1890
|
-
if (callId)
|
|
1891
|
-
toolCallMap.set(callId, { tool: toolName, args });
|
|
1892
|
-
events.push({
|
|
1893
|
-
type: 'tool_use',
|
|
1894
|
-
agent: 'rush',
|
|
1895
|
-
timestamp,
|
|
1896
|
-
tool: toolName,
|
|
1897
|
-
callId,
|
|
1898
|
-
args,
|
|
1899
|
-
path: args.file_path || args.path || undefined,
|
|
1900
|
-
command: (toolName === 'Bash' || toolName === 'shell') ? args.command : undefined,
|
|
1901
|
-
});
|
|
1902
|
-
}
|
|
1903
|
-
else if (type === 'tool_result') {
|
|
1904
|
-
const callId = typeof raw.tool_call_id === 'string' ? raw.tool_call_id : undefined;
|
|
1905
|
-
const info = callId ? toolCallMap.get(callId) : undefined;
|
|
1906
|
-
const output = content.output;
|
|
1907
|
-
let outputStr = '';
|
|
1908
|
-
if (typeof output === 'string') {
|
|
1909
|
-
outputStr = output;
|
|
1910
|
-
}
|
|
1911
|
-
else if (output !== undefined) {
|
|
1912
|
-
try {
|
|
1913
|
-
outputStr = JSON.stringify(output);
|
|
1914
|
-
}
|
|
1915
|
-
catch {
|
|
1916
|
-
outputStr = String(output);
|
|
1917
|
-
}
|
|
1918
|
-
}
|
|
1919
|
-
const success = output?.success !== false;
|
|
1920
|
-
events.push({
|
|
1921
|
-
type: success ? 'tool_result' : 'error',
|
|
1922
|
-
agent: 'rush',
|
|
1923
|
-
timestamp,
|
|
1924
|
-
tool: info?.tool ?? (typeof raw.name === 'string' ? raw.name : 'unknown'),
|
|
1925
|
-
callId,
|
|
1926
|
-
success,
|
|
1927
|
-
output: outputStr,
|
|
1928
|
-
});
|
|
1929
|
-
if (callId)
|
|
1930
|
-
toolCallMap.delete(callId);
|
|
1931
|
-
}
|
|
1932
|
-
}
|
|
1933
|
-
return events;
|
|
1934
|
-
}
|
|
1935
|
-
// ---------------------------------------------------------------------------
|
|
1936
|
-
// Hermes parser
|
|
1937
|
-
//
|
|
1938
|
-
// Hermes stores one JSON file per session at ~/.hermes/sessions/session_<id>.json:
|
|
1939
|
-
// { session_id, model, platform, session_start, last_updated,
|
|
1940
|
-
// system_prompt, message_count, messages: [{role, content}, ...] }
|
|
1941
|
-
// Content may be a string or an array of text parts.
|
|
1942
|
-
// ---------------------------------------------------------------------------
|
|
1943
|
-
/**
|
|
1944
|
-
* Muse Code session.jsonl → normalized events.
|
|
1945
|
-
*
|
|
1946
|
-
* Muse records an append-only event log. We map:
|
|
1947
|
-
* - runtime.command_intake.received / turn_submit → user message
|
|
1948
|
-
* - assistant_message_committed → assistant message
|
|
1949
|
-
* - model_completed.usage → usage
|
|
1950
|
-
* - tool-related events when present
|
|
1951
|
-
*/
|
|
1952
|
-
function parseMuse(filePath) {
|
|
1953
|
-
const content = safeReadSessionFile(filePath);
|
|
1954
|
-
const lines = content.split('\n').filter((l) => l.trim());
|
|
1955
|
-
const events = [];
|
|
1956
|
-
const museTs = (raw) => {
|
|
1957
|
-
if (typeof raw?.recorded_at === 'number') {
|
|
1958
|
-
const v = raw.recorded_at;
|
|
1959
|
-
const ms = v > 1e14 ? Math.floor(v / 1000) : v;
|
|
1960
|
-
return new Date(ms).toISOString();
|
|
1961
|
-
}
|
|
1962
|
-
return new Date().toISOString();
|
|
1963
|
-
};
|
|
1964
|
-
for (const line of lines) {
|
|
1965
|
-
let raw;
|
|
1966
|
-
try {
|
|
1967
|
-
raw = JSON.parse(line);
|
|
1968
|
-
}
|
|
1969
|
-
catch {
|
|
1970
|
-
continue;
|
|
1971
|
-
}
|
|
1972
|
-
const timestamp = museTs(raw);
|
|
1973
|
-
const payloadType = raw.payload_type;
|
|
1974
|
-
const payload = raw.payload;
|
|
1975
|
-
const event = payload?.event ?? payload;
|
|
1976
|
-
if (payloadType === 'runtime.command_intake.received') {
|
|
1977
|
-
const cmd = payload?.record?.command;
|
|
1978
|
-
if (cmd?.kind === 'turn_submit' && typeof cmd.prompt === 'string' && cmd.prompt.trim()) {
|
|
1979
|
-
events.push({
|
|
1980
|
-
type: 'message',
|
|
1981
|
-
agent: 'muse',
|
|
1982
|
-
timestamp,
|
|
1983
|
-
role: 'user',
|
|
1984
|
-
content: cmd.prompt.trim(),
|
|
1985
|
-
});
|
|
1986
|
-
}
|
|
1987
|
-
continue;
|
|
1988
|
-
}
|
|
1989
|
-
if (event?.kind === 'assistant_message_committed' && typeof event.text === 'string') {
|
|
1990
|
-
events.push({
|
|
1991
|
-
type: 'message',
|
|
1992
|
-
agent: 'muse',
|
|
1993
|
-
timestamp,
|
|
1994
|
-
role: 'assistant',
|
|
1995
|
-
content: event.text,
|
|
1996
|
-
});
|
|
1997
|
-
continue;
|
|
1998
|
-
}
|
|
1999
|
-
if (event?.kind === 'model_completed' && event.usage && typeof event.usage === 'object') {
|
|
2000
|
-
const u = event.usage;
|
|
2001
|
-
events.push({
|
|
2002
|
-
type: 'usage',
|
|
2003
|
-
agent: 'muse',
|
|
2004
|
-
timestamp,
|
|
2005
|
-
content: JSON.stringify({
|
|
2006
|
-
input_tokens: u.input_tokens ?? 0,
|
|
2007
|
-
output_tokens: u.output_tokens ?? 0,
|
|
2008
|
-
cached_tokens: u.cached_tokens ?? 0,
|
|
2009
|
-
reasoning_tokens: u.reasoning_tokens ?? 0,
|
|
2010
|
-
}),
|
|
2011
|
-
});
|
|
2012
|
-
continue;
|
|
2013
|
-
}
|
|
2014
|
-
// Tool call / result shapes when Muse records them under task events
|
|
2015
|
-
if (event?.kind === 'tool_call' || event?.kind === 'tool.called') {
|
|
2016
|
-
const tool = event.tool || event.name || event.tool_name;
|
|
2017
|
-
if (typeof tool === 'string') {
|
|
2018
|
-
events.push({
|
|
2019
|
-
type: 'tool_use',
|
|
2020
|
-
agent: 'muse',
|
|
2021
|
-
timestamp,
|
|
2022
|
-
tool,
|
|
2023
|
-
args: typeof event.args === 'object' ? event.args : undefined,
|
|
2024
|
-
callId: typeof event.call_id === 'string' ? event.call_id : undefined,
|
|
2025
|
-
});
|
|
2026
|
-
}
|
|
2027
|
-
}
|
|
2028
|
-
}
|
|
2029
|
-
return events;
|
|
2030
|
-
}
|
|
2031
|
-
/** Parse a Hermes session JSON file into normalized events. */
|
|
2032
|
-
function parseHermes(filePath) {
|
|
2033
|
-
let session;
|
|
2034
|
-
try {
|
|
2035
|
-
session = JSON.parse(safeReadSessionFile(filePath));
|
|
2036
|
-
}
|
|
2037
|
-
catch {
|
|
2038
|
-
return [];
|
|
2039
|
-
}
|
|
2040
|
-
const messages = Array.isArray(session.messages) ? session.messages : [];
|
|
2041
|
-
const timestamp = typeof session.session_start === 'string'
|
|
2042
|
-
? session.session_start
|
|
2043
|
-
: new Date().toISOString();
|
|
2044
|
-
const events = [];
|
|
2045
|
-
for (const msg of messages) {
|
|
2046
|
-
const role = msg?.role === 'user' ? 'user' : 'assistant';
|
|
2047
|
-
const text = hermesContentToText(msg?.content);
|
|
2048
|
-
if (!text)
|
|
2049
|
-
continue;
|
|
2050
|
-
events.push({
|
|
2051
|
-
type: 'message',
|
|
2052
|
-
agent: 'hermes',
|
|
2053
|
-
timestamp,
|
|
2054
|
-
role,
|
|
2055
|
-
content: text,
|
|
2056
|
-
});
|
|
2057
|
-
}
|
|
2058
|
-
return events;
|
|
2059
|
-
}
|
|
2060
|
-
function hermesContentToText(content) {
|
|
2061
|
-
if (typeof content === 'string')
|
|
2062
|
-
return content.trim();
|
|
2063
|
-
if (!Array.isArray(content))
|
|
2064
|
-
return '';
|
|
2065
|
-
return content
|
|
2066
|
-
.map((part) => {
|
|
2067
|
-
if (typeof part === 'string')
|
|
2068
|
-
return part;
|
|
2069
|
-
if (typeof part?.text === 'string')
|
|
2070
|
-
return part.text;
|
|
2071
|
-
return '';
|
|
2072
|
-
})
|
|
2073
|
-
.join('\n')
|
|
2074
|
-
.trim();
|
|
2075
|
-
}
|
|
2076
|
-
// ---------------------------------------------------------------------------
|
|
2077
|
-
// Kimi parser
|
|
2078
|
-
//
|
|
2079
|
-
// Kimi stores session metadata in state.json and the conversation transcript
|
|
2080
|
-
// in agents/main/wire.jsonl under ~/.kimi-code/sessions/<workdir>/session_<uuid>/.
|
|
2081
|
-
// wire.jsonl uses a role-based schema:
|
|
2082
|
-
// - "context.append_message" with role=user/assistant -> messages
|
|
2083
|
-
// - "context.append_loop_event" with content.part type=text/think -> message/thinking
|
|
2084
|
-
// - "context.append_loop_event" with event.type=tool.call -> tool_use
|
|
2085
|
-
// - "context.append_loop_event" with event.type=tool.result -> tool_result
|
|
2086
|
-
// - "usage.record" -> usage
|
|
2087
|
-
// ---------------------------------------------------------------------------
|
|
2088
|
-
/** Parse a Kimi session state.json file by reading its agents/main/wire.jsonl. */
|
|
2089
|
-
export function parseKimi(filePath) {
|
|
2090
|
-
const sessionDir = path.dirname(filePath);
|
|
2091
|
-
const wirePath = path.join(sessionDir, 'agents', 'main', 'wire.jsonl');
|
|
2092
|
-
if (!fs.existsSync(wirePath)) {
|
|
2093
|
-
return [];
|
|
2094
|
-
}
|
|
2095
|
-
const content = safeReadSessionFile(wirePath);
|
|
2096
|
-
const lines = content.split('\n').filter(l => l.trim());
|
|
2097
|
-
const events = [];
|
|
2098
|
-
// Map tool.call uuid -> tool name so tool.result can carry the tool name.
|
|
2099
|
-
const toolCallMap = new Map();
|
|
2100
|
-
function extractMessageText(rawContent) {
|
|
2101
|
-
if (typeof rawContent === 'string')
|
|
2102
|
-
return rawContent.trim();
|
|
2103
|
-
if (Array.isArray(rawContent)) {
|
|
2104
|
-
return rawContent
|
|
2105
|
-
.map((part) => (typeof part?.text === 'string' ? part.text : ''))
|
|
2106
|
-
.join('')
|
|
2107
|
-
.trim();
|
|
2108
|
-
}
|
|
2109
|
-
return '';
|
|
2110
|
-
}
|
|
2111
|
-
function timestampFrom(raw) {
|
|
2112
|
-
const t = raw?.time;
|
|
2113
|
-
if (typeof t === 'number' && t > 0) {
|
|
2114
|
-
return new Date(t).toISOString();
|
|
2115
|
-
}
|
|
2116
|
-
return new Date().toISOString();
|
|
2117
|
-
}
|
|
2118
|
-
for (const line of lines) {
|
|
2119
|
-
let raw;
|
|
2120
|
-
try {
|
|
2121
|
-
raw = JSON.parse(line);
|
|
2122
|
-
}
|
|
2123
|
-
catch {
|
|
2124
|
-
continue;
|
|
2125
|
-
}
|
|
2126
|
-
const type = raw?.type;
|
|
2127
|
-
const timestamp = timestampFrom(raw);
|
|
2128
|
-
if (type === 'context.append_message') {
|
|
2129
|
-
const message = raw.message || {};
|
|
2130
|
-
const role = message.role === 'user' ? 'user' : 'assistant';
|
|
2131
|
-
const text = extractMessageText(message.content);
|
|
2132
|
-
if (!text)
|
|
2133
|
-
continue;
|
|
2134
|
-
events.push({
|
|
2135
|
-
type: 'message',
|
|
2136
|
-
agent: 'kimi',
|
|
2137
|
-
timestamp,
|
|
2138
|
-
role,
|
|
2139
|
-
content: text,
|
|
2140
|
-
});
|
|
2141
|
-
}
|
|
2142
|
-
else if (type === 'context.append_loop_event') {
|
|
2143
|
-
const event = raw.event || {};
|
|
2144
|
-
const eventType = event.type;
|
|
2145
|
-
if (eventType === 'content.part') {
|
|
2146
|
-
const part = event.part || {};
|
|
2147
|
-
const partType = part.type;
|
|
2148
|
-
if (partType === 'text') {
|
|
2149
|
-
const text = typeof part.text === 'string' ? part.text.trim() : '';
|
|
2150
|
-
if (text) {
|
|
2151
|
-
events.push({
|
|
2152
|
-
type: 'message',
|
|
2153
|
-
agent: 'kimi',
|
|
2154
|
-
timestamp,
|
|
2155
|
-
role: 'assistant',
|
|
2156
|
-
content: text,
|
|
2157
|
-
});
|
|
2158
|
-
}
|
|
2159
|
-
}
|
|
2160
|
-
else if (partType === 'think') {
|
|
2161
|
-
const think = typeof part.think === 'string' ? part.think.trim() : '';
|
|
2162
|
-
if (think) {
|
|
2163
|
-
events.push({
|
|
2164
|
-
type: 'thinking',
|
|
2165
|
-
agent: 'kimi',
|
|
2166
|
-
timestamp,
|
|
2167
|
-
content: think,
|
|
2168
|
-
});
|
|
2169
|
-
}
|
|
2170
|
-
}
|
|
2171
|
-
}
|
|
2172
|
-
else if (eventType === 'tool.call') {
|
|
2173
|
-
const fn = event.function || {};
|
|
2174
|
-
const toolName = typeof event.name === 'string'
|
|
2175
|
-
? event.name
|
|
2176
|
-
: typeof fn.name === 'string' ? fn.name : 'unknown';
|
|
2177
|
-
let args = {};
|
|
2178
|
-
if (event.args && typeof event.args === 'object' && !Array.isArray(event.args)) {
|
|
2179
|
-
args = event.args;
|
|
2180
|
-
}
|
|
2181
|
-
else if (typeof fn.arguments === 'string') {
|
|
2182
|
-
try {
|
|
2183
|
-
args = JSON.parse(fn.arguments);
|
|
2184
|
-
}
|
|
2185
|
-
catch {
|
|
2186
|
-
args = { _raw: fn.arguments };
|
|
2187
|
-
}
|
|
2188
|
-
}
|
|
2189
|
-
else if (fn.arguments && typeof fn.arguments === 'object' && !Array.isArray(fn.arguments)) {
|
|
2190
|
-
args = fn.arguments;
|
|
2191
|
-
}
|
|
2192
|
-
const rawCallId = event.toolCallId || event.uuid;
|
|
2193
|
-
const callId = typeof rawCallId === 'string' ? rawCallId : undefined;
|
|
2194
|
-
if (callId) {
|
|
2195
|
-
toolCallMap.set(callId, toolName);
|
|
2196
|
-
}
|
|
2197
|
-
// Kimi writes a per-call `description` on the wire event (and sometimes
|
|
2198
|
-
// inside the args) — the same human label Claude puts on a Bash call.
|
|
2199
|
-
const kimiLabel = typeof event.description === 'string' && event.description.trim()
|
|
2200
|
-
? event.description.trim()
|
|
2201
|
-
: typeof args.description === 'string' && args.description.trim()
|
|
2202
|
-
? args.description.trim()
|
|
2203
|
-
: undefined;
|
|
2204
|
-
events.push({
|
|
2205
|
-
type: 'tool_use',
|
|
2206
|
-
agent: 'kimi',
|
|
2207
|
-
timestamp,
|
|
2208
|
-
tool: toolName,
|
|
2209
|
-
callId,
|
|
2210
|
-
args,
|
|
2211
|
-
path: args.path || args.file_path || undefined,
|
|
2212
|
-
command: toolName === 'Bash' ? args.command : undefined,
|
|
2213
|
-
...(kimiLabel ? { label: kimiLabel } : {}),
|
|
2214
|
-
});
|
|
2215
|
-
}
|
|
2216
|
-
else if (eventType === 'tool.result') {
|
|
2217
|
-
const rawCallId = event.toolCallId || event.parentUuid;
|
|
2218
|
-
const callId = typeof rawCallId === 'string' ? rawCallId : undefined;
|
|
2219
|
-
const toolName = (callId && toolCallMap.get(callId)) || 'unknown';
|
|
2220
|
-
const result = event.result || {};
|
|
2221
|
-
const output = typeof result.output === 'string' ? result.output : '';
|
|
2222
|
-
const structuredError = result.isError === true;
|
|
2223
|
-
const structuredSuccess = result.isError === false;
|
|
2224
|
-
const displayAsError = structuredError || (output && output.startsWith('Error:'));
|
|
2225
|
-
events.push({
|
|
2226
|
-
type: displayAsError ? 'error' : 'tool_result',
|
|
2227
|
-
agent: 'kimi',
|
|
2228
|
-
timestamp,
|
|
2229
|
-
tool: toolName,
|
|
2230
|
-
callId,
|
|
2231
|
-
success: structuredError ? false : structuredSuccess ? true : undefined,
|
|
2232
|
-
outcome: structuredError ? 'error' : structuredSuccess ? 'ok' : 'unknown',
|
|
2233
|
-
output: output,
|
|
2234
|
-
});
|
|
2235
|
-
if (callId) {
|
|
2236
|
-
toolCallMap.delete(callId);
|
|
2237
|
-
}
|
|
2238
|
-
}
|
|
2239
|
-
}
|
|
2240
|
-
else if (type === 'usage.record') {
|
|
2241
|
-
const usage = raw.usage || {};
|
|
2242
|
-
const inputTokens = usage.inputOther ?? usage.input_tokens;
|
|
2243
|
-
const outputTokens = usage.output ?? usage.output_tokens;
|
|
2244
|
-
if ((typeof inputTokens === 'number' && inputTokens >= 0) ||
|
|
2245
|
-
(typeof outputTokens === 'number' && outputTokens >= 0)) {
|
|
2246
|
-
events.push({
|
|
2247
|
-
type: 'usage',
|
|
2248
|
-
agent: 'kimi',
|
|
2249
|
-
timestamp,
|
|
2250
|
-
model: raw.model || usage.model,
|
|
2251
|
-
inputTokens: typeof inputTokens === 'number' ? inputTokens : undefined,
|
|
2252
|
-
outputTokens: typeof outputTokens === 'number' ? outputTokens : undefined,
|
|
2253
|
-
});
|
|
2254
|
-
}
|
|
2255
|
-
}
|
|
2256
|
-
}
|
|
2257
|
-
return events;
|
|
2258
|
-
}
|
|
2259
|
-
// ---------------------------------------------------------------------------
|
|
2260
|
-
// Cursor and Droid (Factory) parsers
|
|
2261
|
-
// ---------------------------------------------------------------------------
|
|
2262
|
-
/** Parse Cursor's Anthropic-shaped message JSONL transcript. */
|
|
2263
|
-
export function parseCursor(filePath) {
|
|
2264
|
-
return parseAnthropicMessageJsonl(filePath, 'cursor');
|
|
2265
|
-
}
|
|
2266
|
-
/**
|
|
2267
|
-
* Cursor stamps the first user turn as
|
|
2268
|
-
* `<timestamp>Sunday, Aug 2, 2026, 3:51 AM (UTC-7)</timestamp>` followed by the
|
|
2269
|
-
* real question in `<user_query>`. `Date.parse` silently DISCARDS the `(UTC-7)`
|
|
2270
|
-
* parenthetical and reads the rest as local time, so the offset has to be applied
|
|
2271
|
-
* by hand — otherwise the recovered instant is wrong on every machine whose zone
|
|
2272
|
-
* differs from the one that wrote the transcript.
|
|
2273
|
-
*/
|
|
2274
|
-
function parseCursorUserText(text) {
|
|
2275
|
-
const stamp = text.match(/<timestamp>\s*([\s\S]*?)\s*<\/timestamp>/)?.[1]?.trim();
|
|
2276
|
-
return { text: unwrapUserQuery(text), timestamp: parseCursorTimestamp(stamp) };
|
|
2277
|
-
}
|
|
2278
|
-
function parseCursorTimestamp(stamp) {
|
|
2279
|
-
if (!stamp)
|
|
2280
|
-
return undefined;
|
|
2281
|
-
const offset = stamp.match(/\(UTC([+-])(\d{1,2})(?::(\d{2}))?\)/);
|
|
2282
|
-
// Without a declared offset there is no instant to recover -- guessing the
|
|
2283
|
-
// local zone would be worse than falling back to the file mtime.
|
|
2284
|
-
if (!offset)
|
|
2285
|
-
return undefined;
|
|
2286
|
-
const wall = Date.parse(`${stamp.replace(/\s*\(UTC[^)]*\)\s*/, " ").trim()} UTC`);
|
|
2287
|
-
if (Number.isNaN(wall))
|
|
2288
|
-
return undefined;
|
|
2289
|
-
const offsetMs = (Number(offset[2]) * 60 + Number(offset[3] ?? 0)) * 60_000;
|
|
2290
|
-
return new Date(offset[1] === "-" ? wall + offsetMs : wall - offsetMs).toISOString();
|
|
2291
|
-
}
|
|
2292
|
-
function parseAnthropicMessageJsonl(filePath, agent) {
|
|
2293
|
-
const content = safeReadSessionFile(filePath);
|
|
2294
|
-
const lines = content.split('\n').filter(l => l.trim());
|
|
2295
|
-
const events = [];
|
|
2296
|
-
const toolUseMap = new Map();
|
|
2297
|
-
const fallbackTimestamp = fs.statSync(filePath).mtime.toISOString();
|
|
2298
|
-
for (const line of lines) {
|
|
2299
|
-
let raw;
|
|
2300
|
-
try {
|
|
2301
|
-
raw = JSON.parse(line);
|
|
2302
|
-
}
|
|
2303
|
-
catch {
|
|
2304
|
-
continue;
|
|
2305
|
-
}
|
|
2306
|
-
if (raw.type === 'turn_ended' || (agent === 'droid' && raw.type !== 'message'))
|
|
2307
|
-
continue;
|
|
2308
|
-
const message = raw.message;
|
|
2309
|
-
const wireRole = agent === 'cursor' ? raw.role : message?.role;
|
|
2310
|
-
if (!message || (agent === 'cursor' && !['user', 'assistant'].includes(wireRole)))
|
|
2311
|
-
continue;
|
|
2312
|
-
const role = wireRole === 'user' ? 'user' : 'assistant';
|
|
2313
|
-
let timestamp = raw.timestamp || fallbackTimestamp;
|
|
2314
|
-
const blocks = message.content;
|
|
2315
|
-
if (typeof blocks === 'string') {
|
|
2316
|
-
const parsed = agent === 'cursor' && role === 'user'
|
|
2317
|
-
? parseCursorUserText(blocks)
|
|
2318
|
-
: { text: blocks.trim(), timestamp: undefined };
|
|
2319
|
-
const text = parsed.text;
|
|
2320
|
-
timestamp = parsed.timestamp || timestamp;
|
|
2321
|
-
if (text)
|
|
2322
|
-
events.push({ type: 'message', agent, timestamp, role, content: text });
|
|
2323
|
-
continue;
|
|
2324
|
-
}
|
|
2325
|
-
if (!Array.isArray(blocks))
|
|
2326
|
-
continue;
|
|
2327
|
-
for (const block of blocks) {
|
|
2328
|
-
if (block.type === 'text') {
|
|
2329
|
-
const parsed = agent === 'cursor' && role === 'user'
|
|
2330
|
-
? parseCursorUserText(block.text || '')
|
|
2331
|
-
: { text: (block.text || '').trim(), timestamp: undefined };
|
|
2332
|
-
const text = parsed.text;
|
|
2333
|
-
timestamp = parsed.timestamp || timestamp;
|
|
2334
|
-
if (text && !(role === 'user' && text.startsWith('<system-reminder>'))) {
|
|
2335
|
-
events.push({ type: 'message', agent, timestamp, role, content: text });
|
|
2336
|
-
}
|
|
2337
|
-
}
|
|
2338
|
-
else if (block.type === 'thinking') {
|
|
2339
|
-
const thinkingText = (block.thinking || '').trim();
|
|
2340
|
-
if (thinkingText)
|
|
2341
|
-
events.push({ type: 'thinking', agent, timestamp, content: thinkingText });
|
|
2342
|
-
}
|
|
2343
|
-
else if (block.type === 'tool_use') {
|
|
2344
|
-
const toolName = block.name || 'unknown';
|
|
2345
|
-
const toolInput = block.input || {};
|
|
2346
|
-
if (block.id)
|
|
2347
|
-
toolUseMap.set(block.id, { tool: toolName, args: toolInput });
|
|
2348
|
-
const event = {
|
|
2349
|
-
type: 'tool_use',
|
|
2350
|
-
agent,
|
|
2351
|
-
timestamp,
|
|
2352
|
-
tool: toolName,
|
|
2353
|
-
callId: typeof block.id === 'string' ? block.id : undefined,
|
|
2354
|
-
args: toolInput,
|
|
2355
|
-
path: toolInput.file_path || toolInput.path || undefined,
|
|
2356
|
-
command: (toolName === 'Bash' || toolName === 'Execute' || toolName === 'Shell') ? toolInput.command : undefined,
|
|
2357
|
-
};
|
|
2358
|
-
// Both harnesses on this parser write the same per-call human label
|
|
2359
|
-
// under different keys — Cursor `description`, Droid `summary` — so the
|
|
2360
|
-
// timeline's now-line reads "List files" rather than `ls -la`, exactly
|
|
2361
|
-
// as it does for the Claude arm above.
|
|
2362
|
-
const label = firstString(toolInput.description, toolInput.summary);
|
|
2363
|
-
if (label)
|
|
2364
|
-
event.label = label;
|
|
2365
|
-
events.push(event);
|
|
2366
|
-
}
|
|
2367
|
-
else if (block.type === 'tool_result') {
|
|
2368
|
-
const toolId = block.tool_use_id;
|
|
2369
|
-
const toolInfo = toolId ? toolUseMap.get(toolId) : undefined;
|
|
2370
|
-
const isError = block.is_error === true;
|
|
2371
|
-
const output = typeof block.content === 'string'
|
|
2372
|
-
? block.content
|
|
2373
|
-
: Array.isArray(block.content)
|
|
2374
|
-
? block.content.filter((c) => c.type === 'text').map((c) => c.text || '').join('\n')
|
|
2375
|
-
: '';
|
|
2376
|
-
if (isError) {
|
|
2377
|
-
events.push({
|
|
2378
|
-
type: 'error', agent, timestamp, tool: toolInfo?.tool,
|
|
2379
|
-
callId: toolId, outcome: 'error', content: output || 'Tool execution failed',
|
|
2380
|
-
});
|
|
2381
|
-
}
|
|
2382
|
-
else {
|
|
2383
|
-
events.push({
|
|
2384
|
-
type: 'tool_result', agent, timestamp, tool: toolInfo?.tool, callId: toolId, success: true,
|
|
2385
|
-
output: output,
|
|
2386
|
-
});
|
|
2387
|
-
}
|
|
2388
|
-
if (toolId)
|
|
2389
|
-
toolUseMap.delete(toolId);
|
|
2390
|
-
}
|
|
2391
|
-
else if (block.type === 'image') {
|
|
2392
|
-
const source = block.source || {};
|
|
2393
|
-
const sizeBytes = source.type === 'base64' ? Math.ceil((source.data?.length || 0) * 0.75) : 0;
|
|
2394
|
-
events.push(normalizedAttachmentEvent(agent, timestamp, block, source, 'image/png', sizeBytes));
|
|
2395
|
-
}
|
|
2396
|
-
}
|
|
2397
|
-
}
|
|
2398
|
-
return events;
|
|
2399
|
-
}
|
|
2400
|
-
/**
|
|
2401
|
-
* Parse a Droid (Factory) JSONL session file into normalized events. Droid
|
|
2402
|
-
* wraps each turn in a `{type:'message', message:{role, content, modelId}}`
|
|
2403
|
-
* envelope; the content blocks are Anthropic-shaped (text/thinking/tool_use/
|
|
2404
|
-
* tool_result), so block handling mirrors the Claude parser.
|
|
2405
|
-
*/
|
|
2406
|
-
export function parseDroid(filePath) {
|
|
2407
|
-
return parseAnthropicMessageJsonl(filePath, 'droid');
|
|
2408
|
-
}
|