@wjarka/cezarion 0.16.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -0
- package/README.md +594 -207
- package/dist/agent-config/account-identity.d.ts +3 -19
- package/dist/agent-config/account-identity.js +8 -5
- package/dist/agent-config/account-identity.js.map +1 -1
- package/dist/agent-config/catalog.d.ts +3 -14
- package/dist/agent-config/catalog.js.map +1 -1
- package/dist/agent-config/files.d.ts +2 -6
- package/dist/agent-config/files.js +2 -6
- package/dist/agent-config/files.js.map +1 -1
- package/dist/agent-config/model-settings/types.d.ts +1 -1
- package/dist/agent-config/seed.d.ts +11 -3
- package/dist/agent-config/seed.js +52 -48
- package/dist/agent-config/seed.js.map +1 -1
- package/dist/agent-config/service.js +3 -2
- package/dist/agent-config/service.js.map +1 -1
- package/dist/agent-config/validate.d.ts +1 -4
- package/dist/agent-config/validate.js.map +1 -1
- package/dist/application-update/helper.d.ts +2 -2
- package/dist/application-update/helper.js +7 -12
- package/dist/application-update/helper.js.map +1 -1
- package/dist/application-update/launcher.d.ts +4 -0
- package/dist/application-update/launcher.js +18 -12
- package/dist/application-update/launcher.js.map +1 -1
- package/dist/application-update/service.d.ts +3 -3
- package/dist/application-update/service.js +1 -1
- package/dist/application-update/service.js.map +1 -1
- package/dist/archive-on-merge-setting.d.ts +15 -0
- package/dist/archive-on-merge-setting.js +14 -0
- package/dist/archive-on-merge-setting.js.map +1 -0
- package/dist/artifacts/cli.d.ts +8 -0
- package/dist/artifacts/cli.js +21 -2
- package/dist/artifacts/cli.js.map +1 -1
- package/dist/artifacts/resolve.js +2 -1
- package/dist/artifacts/resolve.js.map +1 -1
- package/dist/artifacts/store.js.map +1 -1
- package/dist/automations/automation-cli.d.ts +59 -0
- package/dist/automations/automation-cli.js +509 -0
- package/dist/automations/automation-cli.js.map +1 -0
- package/dist/automations/builtin-skill.d.ts +7 -0
- package/dist/automations/builtin-skill.js +14 -0
- package/dist/automations/builtin-skill.js.map +1 -0
- package/dist/automations/github-baseline.d.ts +3 -0
- package/dist/automations/github-baseline.js +17 -0
- package/dist/automations/github-baseline.js.map +1 -0
- package/dist/automations/github-poller.d.ts +23 -4
- package/dist/automations/github-poller.js +157 -88
- package/dist/automations/github-poller.js.map +1 -1
- package/dist/automations/prompts.d.ts +12 -0
- package/dist/automations/prompts.js +160 -0
- package/dist/automations/prompts.js.map +1 -0
- package/dist/automations/schedule-runner.d.ts +43 -24
- package/dist/automations/schedule-runner.js +207 -20
- package/dist/automations/schedule-runner.js.map +1 -1
- package/dist/automations/scheduler.d.ts +10 -2
- package/dist/automations/scheduler.js +200 -54
- package/dist/automations/scheduler.js.map +1 -1
- package/dist/automations/service.d.ts +777 -0
- package/dist/automations/service.js +444 -0
- package/dist/automations/service.js.map +1 -0
- package/dist/automations/store.d.ts +17 -7
- package/dist/automations/store.js +88 -17
- package/dist/automations/store.js.map +1 -1
- package/dist/automations/task-template.d.ts +7 -2
- package/dist/automations/task-template.js +93 -44
- package/dist/automations/task-template.js.map +1 -1
- package/dist/automations/tool-adapter.d.ts +6 -0
- package/dist/automations/tool-adapter.js +108 -0
- package/dist/automations/tool-adapter.js.map +1 -0
- package/dist/automations/types.d.ts +1 -405
- package/dist/automations/types.js +1 -218
- package/dist/automations/types.js.map +1 -1
- package/dist/autosave-cleanup.d.ts +26 -0
- package/dist/autosave-cleanup.js +87 -0
- package/dist/autosave-cleanup.js.map +1 -0
- package/dist/autosave-git.d.ts +3 -0
- package/dist/autosave-git.js +67 -35
- package/dist/autosave-git.js.map +1 -1
- package/dist/autosave-group.d.ts +8 -0
- package/dist/autosave-group.js +61 -0
- package/dist/autosave-group.js.map +1 -0
- package/dist/autosave-holders.d.ts +31 -4
- package/dist/autosave-holders.js +92 -7
- package/dist/autosave-holders.js.map +1 -1
- package/dist/autosave-windows.d.ts +14 -0
- package/dist/autosave-windows.js +36 -2
- package/dist/autosave-windows.js.map +1 -1
- package/dist/ci-wait/client.d.ts +20 -3
- package/dist/ci-wait/client.js +40 -44
- package/dist/ci-wait/client.js.map +1 -1
- package/dist/ci-wait/controller.d.ts +622 -36
- package/dist/ci-wait/controller.js +152 -20
- package/dist/ci-wait/controller.js.map +1 -1
- package/dist/ci-wait/errors.d.ts +19 -0
- package/dist/ci-wait/errors.js +180 -2
- package/dist/ci-wait/errors.js.map +1 -1
- package/dist/ci-wait/github.d.ts +25 -1
- package/dist/ci-wait/github.js +76 -9
- package/dist/ci-wait/github.js.map +1 -1
- package/dist/ci-wait/mcp.d.ts +0 -1
- package/dist/ci-wait/mcp.js +0 -2
- package/dist/ci-wait/mcp.js.map +1 -1
- package/dist/ci-wait/supervisor.d.ts +7 -0
- package/dist/ci-wait/supervisor.js +113 -17
- package/dist/ci-wait/supervisor.js.map +1 -1
- package/dist/ci-wait/tools.d.ts +536 -16
- package/dist/ci-wait/tools.js +165 -20
- package/dist/ci-wait/tools.js.map +1 -1
- package/dist/config.d.ts +3 -17
- package/dist/config.js +4 -60
- package/dist/config.js.map +1 -1
- package/dist/contract/active-provider.d.ts +12 -0
- package/dist/contract/agent-profiles.d.ts +2 -10
- package/dist/contract/ask-schema.d.ts +22 -4
- package/dist/contract/ask.d.ts +6 -4
- package/dist/contract/attachments.d.ts +35 -0
- package/dist/contract/attention.d.ts +46 -37
- package/dist/contract/automation-requests.d.ts +308 -0
- package/dist/contract/automation-schedule.d.ts +40 -11
- package/dist/contract/automation-storage.d.ts +512 -0
- package/dist/contract/automations.d.ts +421 -40
- package/dist/contract/ci-wait.d.ts +41 -4
- package/dist/contract/config-requests.d.ts +36 -0
- package/dist/contract/conversations.d.ts +24 -10
- package/dist/contract/defined.d.ts +8 -0
- package/dist/contract/delegation.d.ts +312 -8
- package/dist/contract/events.d.ts +24 -3
- package/dist/contract/github-requests.d.ts +26 -0
- package/dist/contract/github.d.ts +60 -27
- package/dist/contract/handoff.d.ts +43 -0
- package/dist/contract/health.d.ts +2 -2
- package/dist/contract/image-path.d.ts +6 -0
- package/dist/contract/index.d.ts +31 -0
- package/dist/contract/index.js +3756 -1525
- package/dist/contract/live-coordination.d.ts +158 -0
- package/dist/contract/live-limits.d.ts +8 -0
- package/dist/contract/live.d.ts +123 -0
- package/dist/contract/pending-ask.d.ts +58 -0
- package/dist/contract/permissions.d.ts +54 -0
- package/dist/contract/preview.d.ts +33 -0
- package/dist/contract/project-limits.d.ts +33 -0
- package/dist/contract/projects.d.ts +486 -20
- package/dist/contract/provider-requests.d.ts +77 -0
- package/dist/contract/query-requests.d.ts +52 -0
- package/dist/contract/repo-requests.d.ts +12 -0
- package/dist/contract/run-labels.d.ts +8 -0
- package/dist/contract/run-limits.d.ts +8 -0
- package/dist/contract/run-predicates.d.ts +32 -0
- package/dist/contract/run-requests.d.ts +33 -0
- package/dist/contract/run-search.d.ts +193 -0
- package/dist/contract/runs.d.ts +2232 -1894
- package/dist/contract/scheduled-tasks.d.ts +187 -0
- package/dist/contract/skills.d.ts +22 -772
- package/dist/contract/team-skill-ref.d.ts +10 -0
- package/dist/{core → contract}/tool-display.d.ts +4 -10
- package/dist/contract/ui-state-requests.d.ts +60 -0
- package/dist/contract/version.d.ts +3 -0
- package/dist/contract/voice.d.ts +213 -0
- package/dist/contract/waits.d.ts +1204 -0
- package/dist/contract/workflow-file.d.ts +37 -0
- package/dist/contract/workflow-requests.d.ts +7 -0
- package/dist/contract/workflows.d.ts +1 -2
- package/dist/contract/workspace.d.ts +34 -82
- package/dist/contract/zoned-time.d.ts +2 -11
- package/dist/core/agent-env.d.ts +4 -16
- package/dist/core/agent-env.js +14 -16
- package/dist/core/agent-env.js.map +1 -1
- package/dist/core/agent-profiles.d.ts +28 -40
- package/dist/core/agent-profiles.js +56 -51
- package/dist/core/agent-profiles.js.map +1 -1
- package/dist/core/agent-runner.d.ts +88 -44
- package/dist/core/agent-runner.js +17 -18
- package/dist/core/agent-runner.js.map +1 -1
- package/dist/core/ask.d.ts +3 -0
- package/dist/core/ask.js +12 -0
- package/dist/core/ask.js.map +1 -1
- package/dist/core/backend-detect.js +16 -2
- package/dist/core/backend-detect.js.map +1 -1
- package/dist/core/claude-cli-runner.d.ts +23 -4
- package/dist/core/claude-cli-runner.js +280 -76
- package/dist/core/claude-cli-runner.js.map +1 -1
- package/dist/core/claude-model-catalog.d.ts +2 -10
- package/dist/core/claude-model-catalog.js +2 -10
- package/dist/core/claude-model-catalog.js.map +1 -1
- package/dist/core/claude-ui-mapper.d.ts +2 -2
- package/dist/core/claude-ui-mapper.js +94 -2
- package/dist/core/claude-ui-mapper.js.map +1 -1
- package/dist/core/codex-app-server-runner.d.ts +3 -4
- package/dist/core/codex-app-server-runner.js +146 -51
- package/dist/core/codex-app-server-runner.js.map +1 -1
- package/dist/core/codex-app-server-transport.d.ts +4 -3
- package/dist/core/codex-app-server-transport.js +11 -7
- package/dist/core/codex-app-server-transport.js.map +1 -1
- package/dist/core/codex-approvals.d.ts +12 -0
- package/dist/core/codex-approvals.js +161 -0
- package/dist/core/codex-approvals.js.map +1 -0
- package/dist/core/codex-permissions.d.ts +1 -1
- package/dist/core/codex-ui-mapper.js +45 -1
- package/dist/core/codex-ui-mapper.js.map +1 -1
- package/dist/core/cursor-acp-runner.d.ts +1 -1
- package/dist/core/cursor-acp-runner.js +39 -15
- package/dist/core/cursor-acp-runner.js.map +1 -1
- package/dist/core/cursor-cli-flags.d.ts +19 -0
- package/dist/core/cursor-cli-flags.js +47 -0
- package/dist/core/cursor-cli-flags.js.map +1 -0
- package/dist/core/cursor-model-catalog.d.ts +22 -0
- package/dist/core/cursor-model-catalog.js +53 -24
- package/dist/core/cursor-model-catalog.js.map +1 -1
- package/dist/core/cursor-print-capabilities.d.ts +16 -0
- package/dist/core/cursor-print-capabilities.js +141 -0
- package/dist/core/cursor-print-capabilities.js.map +1 -0
- package/dist/core/cursor-print-process.d.ts +31 -0
- package/dist/core/cursor-print-process.js +117 -0
- package/dist/core/cursor-print-process.js.map +1 -0
- package/dist/core/cursor-print-runner.d.ts +31 -0
- package/dist/core/cursor-print-runner.js +555 -0
- package/dist/core/cursor-print-runner.js.map +1 -0
- package/dist/core/cursor-print-tool-catalog.d.ts +10 -0
- package/dist/core/cursor-print-tool-catalog.js +91 -0
- package/dist/core/cursor-print-tool-catalog.js.map +1 -0
- package/dist/core/cursor-print-ui-mapper.d.ts +47 -0
- package/dist/core/cursor-print-ui-mapper.js +553 -0
- package/dist/core/cursor-print-ui-mapper.js.map +1 -0
- package/dist/core/cursor-runner.d.ts +24 -0
- package/dist/core/cursor-runner.js +149 -0
- package/dist/core/cursor-runner.js.map +1 -0
- package/dist/core/cursor-ui-mapper.js +5 -2
- package/dist/core/cursor-ui-mapper.js.map +1 -1
- package/dist/core/defined.d.ts +1 -0
- package/dist/core/defined.js +2 -0
- package/dist/core/defined.js.map +1 -0
- package/dist/core/hook-items.d.ts +14 -0
- package/dist/core/hook-items.js +13 -0
- package/dist/core/hook-items.js.map +1 -0
- package/dist/core/host-model-catalog.d.ts +2 -9
- package/dist/core/host-model-catalog.js +2 -9
- package/dist/core/host-model-catalog.js.map +1 -1
- package/dist/core/managed-session.js +15 -3
- package/dist/core/managed-session.js.map +1 -1
- package/dist/core/model-identity.d.ts +4 -21
- package/dist/core/model-identity.js.map +1 -1
- package/dist/core/model-presets.d.ts +2 -13
- package/dist/core/model-presets.js +2 -13
- package/dist/core/model-presets.js.map +1 -1
- package/dist/core/omp-model-catalog.js.map +1 -1
- package/dist/core/omp-runner.d.ts +6 -7
- package/dist/core/omp-runner.js +92 -33
- package/dist/core/omp-runner.js.map +1 -1
- package/dist/core/omp-ui-mapper.js +1 -1
- package/dist/core/omp-ui-mapper.js.map +1 -1
- package/dist/core/opencode-model-catalog.js.map +1 -1
- package/dist/core/opencode-permissions.d.ts +52 -0
- package/dist/core/opencode-permissions.js +101 -0
- package/dist/core/opencode-permissions.js.map +1 -0
- package/dist/core/opencode-server-runner.d.ts +10 -9
- package/dist/core/opencode-server-runner.js +286 -28
- package/dist/core/opencode-server-runner.js.map +1 -1
- package/dist/core/opencode-session-error.d.ts +15 -7
- package/dist/core/opencode-session-error.js +25 -9
- package/dist/core/opencode-session-error.js.map +1 -1
- package/dist/core/opencode-ui-mapper.js +2 -2
- package/dist/core/opencode-ui-mapper.js.map +1 -1
- package/dist/core/pi-model-catalog.js.map +1 -1
- package/dist/core/pi-runner.d.ts +12 -4
- package/dist/core/pi-runner.js +171 -63
- package/dist/core/pi-runner.js.map +1 -1
- package/dist/core/pi-ui-mapper.js +1 -1
- package/dist/core/pi-ui-mapper.js.map +1 -1
- package/dist/core/process-usage.d.ts +5 -0
- package/dist/core/process-usage.js +24 -4
- package/dist/core/process-usage.js.map +1 -1
- package/dist/core/provider-auth.d.ts +16 -107
- package/dist/core/provider-auth.js +16 -132
- package/dist/core/provider-auth.js.map +1 -1
- package/dist/core/runner-factory.d.ts +4 -1
- package/dist/core/runner-factory.js +3 -3
- package/dist/core/runner-factory.js.map +1 -1
- package/dist/core/runner-runtime.d.ts +22 -0
- package/dist/core/runner-runtime.js +66 -5
- package/dist/core/runner-runtime.js.map +1 -1
- package/dist/core/runner-tool-grants.d.ts +21 -0
- package/dist/core/runner-tool-grants.js +64 -0
- package/dist/core/runner-tool-grants.js.map +1 -0
- package/dist/core/secret-redaction.d.ts +3 -20
- package/dist/core/secret-redaction.js +3 -20
- package/dist/core/secret-redaction.js.map +1 -1
- package/dist/core/session-process.d.ts +22 -2
- package/dist/core/session-process.js +170 -12
- package/dist/core/session-process.js.map +1 -1
- package/dist/core/shell-env.d.ts +2 -15
- package/dist/core/shell-env.js +2 -15
- package/dist/core/shell-env.js.map +1 -1
- package/dist/core/ui-events.d.ts +60 -47
- package/dist/core/ui-events.js +0 -23
- package/dist/core/ui-events.js.map +1 -1
- package/dist/core/usage-limit.js.map +1 -1
- package/dist/data-gitignore.js +3 -1
- package/dist/data-gitignore.js.map +1 -1
- package/dist/delegation/capacity.d.ts +4 -8
- package/dist/delegation/capacity.js +4 -8
- package/dist/delegation/capacity.js.map +1 -1
- package/dist/delegation/cli.js +123 -21
- package/dist/delegation/cli.js.map +1 -1
- package/dist/delegation/context.d.ts +19 -3
- package/dist/delegation/context.js +217 -22
- package/dist/delegation/context.js.map +1 -1
- package/dist/delegation/conversations.d.ts +4 -3
- package/dist/delegation/conversations.js +7 -5
- package/dist/delegation/conversations.js.map +1 -1
- package/dist/delegation/destroy-observation.d.ts +1 -1
- package/dist/delegation/destroy-observation.js.map +1 -1
- package/dist/delegation/effort.js.map +1 -1
- package/dist/delegation/execution-identity.d.ts +1 -1
- package/dist/delegation/execution-identity.js +41 -7
- package/dist/delegation/execution-identity.js.map +1 -1
- package/dist/delegation/idle-test-app.d.ts +4 -0
- package/dist/delegation/idle-test-app.js +174 -0
- package/dist/delegation/idle-test-app.js.map +1 -0
- package/dist/delegation/input.js.map +1 -1
- package/dist/delegation/park-notice.d.ts +42 -0
- package/dist/delegation/park-notice.js +71 -0
- package/dist/delegation/park-notice.js.map +1 -0
- package/dist/delegation/policy.d.ts +2 -0
- package/dist/delegation/policy.js +9 -1
- package/dist/delegation/policy.js.map +1 -1
- package/dist/delegation/process-liveness.d.ts +10 -15
- package/dist/delegation/process-liveness.js +11 -35
- package/dist/delegation/process-liveness.js.map +1 -1
- package/dist/delegation/provision.js +21 -19
- package/dist/delegation/provision.js.map +1 -1
- package/dist/delegation/questions.d.ts +3 -1
- package/dist/delegation/questions.js +10 -5
- package/dist/delegation/questions.js.map +1 -1
- package/dist/delegation/readiness.d.ts +2 -2
- package/dist/delegation/results.d.ts +4 -1
- package/dist/delegation/results.js +49 -18
- package/dist/delegation/results.js.map +1 -1
- package/dist/delegation/retry-backoff.d.ts +8 -0
- package/dist/delegation/retry-backoff.js +8 -0
- package/dist/delegation/retry-backoff.js.map +1 -1
- package/dist/delegation/routes.d.ts +114 -30
- package/dist/delegation/routes.js +4 -1
- package/dist/delegation/routes.js.map +1 -1
- package/dist/delegation/scratch-cleanup.d.ts +4 -5
- package/dist/delegation/scratch-cleanup.js +10 -8
- package/dist/delegation/scratch-cleanup.js.map +1 -1
- package/dist/delegation/service.d.ts +12 -4
- package/dist/delegation/service.js +76 -28
- package/dist/delegation/service.js.map +1 -1
- package/dist/delegation/transport.d.ts +154 -70
- package/dist/delegation/wait.d.ts +11 -0
- package/dist/delegation/wait.js +24 -0
- package/dist/delegation/wait.js.map +1 -1
- package/dist/delegation/windows-test-app.d.ts +5 -0
- package/dist/delegation/windows-test-app.js +63 -0
- package/dist/delegation/windows-test-app.js.map +1 -0
- package/dist/delegation/windows-workspace-identity.d.ts +3 -0
- package/dist/delegation/windows-workspace-identity.js +22 -0
- package/dist/delegation/windows-workspace-identity.js.map +1 -0
- package/dist/delegation/workspace.d.ts +5 -10
- package/dist/delegation/workspace.js +136 -75
- package/dist/delegation/workspace.js.map +1 -1
- package/dist/detached-process.d.ts +103 -0
- package/dist/detached-process.js +301 -0
- package/dist/detached-process.js.map +1 -0
- package/dist/discovery/catalog.d.ts +2 -1
- package/dist/discovery/catalog.js.map +1 -1
- package/dist/discovery/cli.js +3 -1
- package/dist/discovery/cli.js.map +1 -1
- package/dist/git-diff-base.d.ts +6 -61
- package/dist/git-diff-base.js +6 -70
- package/dist/git-diff-base.js.map +1 -1
- package/dist/git-index-copy.d.ts +4 -0
- package/dist/git-index-copy.js +10 -0
- package/dist/git-index-copy.js.map +1 -0
- package/dist/git-worktree-lock.d.ts +2 -4
- package/dist/git-worktree-lock.js +2 -4
- package/dist/git-worktree-lock.js.map +1 -1
- package/dist/git-worktree-release.d.ts +2 -2
- package/dist/git-worktree-release.js.map +1 -1
- package/dist/git-worktree.d.ts +47 -76
- package/dist/git-worktree.js +240 -94
- package/dist/git-worktree.js.map +1 -1
- package/dist/handoff.d.ts +51 -41
- package/dist/handoff.js +130 -78
- package/dist/handoff.js.map +1 -1
- package/dist/index.js +60 -39
- package/dist/index.js.map +1 -1
- package/dist/merge-observations.d.ts +13 -0
- package/dist/merge-observations.js +55 -0
- package/dist/merge-observations.js.map +1 -0
- package/dist/open-url.js +4 -14
- package/dist/open-url.js.map +1 -1
- package/dist/paths.d.ts +10 -13
- package/dist/paths.js +36 -17
- package/dist/paths.js.map +1 -1
- package/dist/planner.d.ts +2 -1
- package/dist/planner.js +9 -6
- package/dist/planner.js.map +1 -1
- package/dist/preview/agent-address.d.ts +34 -0
- package/dist/preview/agent-address.js +51 -0
- package/dist/preview/agent-address.js.map +1 -0
- package/dist/preview/agent-marker.d.ts +17 -0
- package/dist/preview/agent-marker.js +71 -0
- package/dist/preview/agent-marker.js.map +1 -0
- package/dist/preview/cdp-proxy.d.ts +54 -0
- package/dist/preview/cdp-proxy.js +151 -0
- package/dist/preview/cdp-proxy.js.map +1 -0
- package/dist/preview/cdp.d.ts +39 -3
- package/dist/preview/cdp.js +155 -57
- package/dist/preview/cdp.js.map +1 -1
- package/dist/preview/chromium.d.ts +18 -6
- package/dist/preview/chromium.js +112 -25
- package/dist/preview/chromium.js.map +1 -1
- package/dist/preview/dev-server.d.ts +1 -1
- package/dist/preview/dev-server.js +20 -44
- package/dist/preview/dev-server.js.map +1 -1
- package/dist/preview/host.d.ts +70 -3
- package/dist/preview/host.js +314 -28
- package/dist/preview/host.js.map +1 -1
- package/dist/preview/registration.d.ts +10 -5
- package/dist/preview/registration.js +2 -0
- package/dist/preview/registration.js.map +1 -1
- package/dist/preview/session.d.ts +2 -0
- package/dist/preview/session.js +10 -0
- package/dist/preview/session.js.map +1 -1
- package/dist/process-wait/exit-file.d.ts +29 -0
- package/dist/process-wait/exit-file.js +67 -0
- package/dist/process-wait/exit-file.js.map +1 -0
- package/dist/process-wait/supervisor.d.ts +30 -0
- package/dist/process-wait/supervisor.js +71 -0
- package/dist/process-wait/supervisor.js.map +1 -0
- package/dist/release/snapshot.d.ts +6 -6
- package/dist/runs/agent-tmpdir.d.ts +51 -36
- package/dist/runs/agent-tmpdir.js +389 -132
- package/dist/runs/agent-tmpdir.js.map +1 -1
- package/dist/runs/auto-name.d.ts +6 -6
- package/dist/runs/auto-name.js +1 -1
- package/dist/runs/auto-name.js.map +1 -1
- package/dist/runs/client-request.d.ts +3 -3
- package/dist/runs/client-request.js +3 -3
- package/dist/runs/client-request.js.map +1 -1
- package/dist/runs/delegation-state.d.ts +11 -2
- package/dist/runs/delegation-state.js.map +1 -1
- package/dist/runs/event-history-agent-context.d.ts +14 -0
- package/dist/runs/event-history-agent-context.js +105 -0
- package/dist/runs/event-history-agent-context.js.map +1 -0
- package/dist/runs/event-history-context.d.ts +15 -0
- package/dist/runs/event-history-context.js +109 -0
- package/dist/runs/event-history-context.js.map +1 -0
- package/dist/runs/event-history.d.ts +4 -1
- package/dist/runs/event-history.js +29 -130
- package/dist/runs/event-history.js.map +1 -1
- package/dist/runs/history-stream.d.ts +2 -0
- package/dist/runs/history-stream.js +62 -0
- package/dist/runs/history-stream.js.map +1 -0
- package/dist/runs/legacy-index.d.ts +6 -19
- package/dist/runs/legacy-index.js +6 -19
- package/dist/runs/legacy-index.js.map +1 -1
- package/dist/runs/live-item-snapshots.d.ts +13 -0
- package/dist/runs/live-item-snapshots.js +79 -0
- package/dist/runs/live-item-snapshots.js.map +1 -0
- package/dist/runs/loaded-run-healing.d.ts +3 -0
- package/dist/runs/loaded-run-healing.js +17 -0
- package/dist/runs/loaded-run-healing.js.map +1 -0
- package/dist/runs/outcome-commit.d.ts +98 -0
- package/dist/runs/outcome-commit.js +132 -0
- package/dist/runs/outcome-commit.js.map +1 -0
- package/dist/runs/pull-requests.d.ts +14 -0
- package/dist/runs/pull-requests.js +96 -0
- package/dist/runs/pull-requests.js.map +1 -0
- package/dist/runs/raw-record.d.ts +3 -15
- package/dist/runs/raw-record.js +3 -15
- package/dist/runs/raw-record.js.map +1 -1
- package/dist/runs/retention.d.ts +2 -2
- package/dist/runs/retention.js +7 -0
- package/dist/runs/retention.js.map +1 -1
- package/dist/runs/review-gate.d.ts +1 -1
- package/dist/runs/review-gate.js.map +1 -1
- package/dist/runs/run-claims.d.ts +2 -9
- package/dist/runs/run-claims.js.map +1 -1
- package/dist/runs/run-database.d.ts +29 -34
- package/dist/runs/run-database.js +124 -46
- package/dist/runs/run-database.js.map +1 -1
- package/dist/runs/run-index.d.ts +6 -25
- package/dist/runs/run-index.js +25 -38
- package/dist/runs/run-index.js.map +1 -1
- package/dist/runs/run-row.d.ts +5 -34
- package/dist/runs/run-row.js +13 -38
- package/dist/runs/run-row.js.map +1 -1
- package/dist/runs/store.d.ts +1597 -744
- package/dist/runs/store.js +1231 -739
- package/dist/runs/store.js.map +1 -1
- package/dist/runs/task-markers.d.ts +1 -0
- package/dist/runs/task-markers.js +5 -1
- package/dist/runs/task-markers.js.map +1 -1
- package/dist/runs/task-refs.d.ts +3 -3
- package/dist/runs/transcript-facts-fold.d.ts +64 -0
- package/dist/runs/transcript-facts-fold.js +109 -0
- package/dist/runs/transcript-facts-fold.js.map +1 -0
- package/dist/runs/transcript-facts-load.d.ts +11 -0
- package/dist/runs/transcript-facts-load.js +66 -0
- package/dist/runs/transcript-facts-load.js.map +1 -0
- package/dist/runs/transcript-facts-queue.d.ts +30 -0
- package/dist/runs/transcript-facts-queue.js +227 -0
- package/dist/runs/transcript-facts-queue.js.map +1 -0
- package/dist/runs/transcript-facts-worker.d.ts +15 -0
- package/dist/runs/transcript-facts-worker.js +26 -0
- package/dist/runs/transcript-facts-worker.js.map +1 -0
- package/dist/runs/transcript-facts.d.ts +13 -51
- package/dist/runs/transcript-facts.js +86 -202
- package/dist/runs/transcript-facts.js.map +1 -1
- package/dist/runs/ui-event-sink.d.ts +5 -30
- package/dist/runs/ui-event-sink.js +8 -30
- package/dist/runs/ui-event-sink.js.map +1 -1
- package/dist/runs/webhook.d.ts +104 -38
- package/dist/runs/webhook.js +180 -77
- package/dist/runs/webhook.js.map +1 -1
- package/dist/server/app-type.d.ts +2 -17
- package/dist/server/archive-on-merge.d.ts +35 -0
- package/dist/server/archive-on-merge.js +202 -0
- package/dist/server/archive-on-merge.js.map +1 -0
- package/dist/server/capabilities.d.ts +3 -15
- package/dist/server/capabilities.js +6 -19
- package/dist/server/capabilities.js.map +1 -1
- package/dist/server/checkout-progress.d.ts +10 -0
- package/dist/server/checkout-progress.js +27 -0
- package/dist/server/checkout-progress.js.map +1 -0
- package/dist/server/checkout.d.ts +10 -19
- package/dist/server/checkout.js +15 -45
- package/dist/server/checkout.js.map +1 -1
- package/dist/server/cockpit-ownership.d.ts +2 -0
- package/dist/server/cockpit-ownership.js +9 -0
- package/dist/server/cockpit-ownership.js.map +1 -1
- package/dist/server/cold-repo-handles.d.ts +2 -7
- package/dist/server/cold-repo-handles.js +2 -7
- package/dist/server/cold-repo-handles.js.map +1 -1
- package/dist/server/completion-actions.d.ts +30 -0
- package/dist/server/completion-actions.js +204 -0
- package/dist/server/completion-actions.js.map +1 -0
- package/dist/server/create-project.d.ts +71 -0
- package/dist/server/create-project.js +448 -0
- package/dist/server/create-project.js.map +1 -0
- package/dist/server/forge/github-filters.d.ts +7 -1
- package/dist/server/forge/github-filters.js +66 -51
- package/dist/server/forge/github-filters.js.map +1 -1
- package/dist/server/forge/github-merge-requirements.d.ts +18 -0
- package/dist/server/forge/github-merge-requirements.js +137 -0
- package/dist/server/forge/github-merge-requirements.js.map +1 -0
- package/dist/server/forge/github.d.ts +98 -111
- package/dist/server/forge/github.js +625 -306
- package/dist/server/forge/github.js.map +1 -1
- package/dist/server/forge/types.d.ts +25 -22
- package/dist/server/fs-browse.d.ts +3 -28
- package/dist/server/fs-browse.js.map +1 -1
- package/dist/server/git-changes.d.ts +5 -15
- package/dist/server/git-changes.js +3 -50
- package/dist/server/git-changes.js.map +1 -1
- package/dist/server/git.d.ts +3 -1
- package/dist/server/git.js +12 -0
- package/dist/server/git.js.map +1 -1
- package/dist/server/github.d.ts +1 -1
- package/dist/server/github.js +1 -1
- package/dist/server/github.js.map +1 -1
- package/dist/server/launch-key.d.ts +2 -4
- package/dist/server/launch-key.js +2 -4
- package/dist/server/launch-key.js.map +1 -1
- package/dist/server/live-routes.d.ts +68 -0
- package/dist/server/live-routes.js +147 -0
- package/dist/server/live-routes.js.map +1 -0
- package/dist/server/open-in-app.d.ts +4 -13
- package/dist/server/open-in-app.js +5 -41
- package/dist/server/open-in-app.js.map +1 -1
- package/dist/server/open-in-targets.d.ts +42 -0
- package/dist/server/open-in-targets.js +110 -0
- package/dist/server/open-in-targets.js.map +1 -0
- package/dist/server/open-in-terminal.d.ts +3 -0
- package/dist/server/open-in-terminal.js +6 -26
- package/dist/server/open-in-terminal.js.map +1 -1
- package/dist/server/preview-cdp-socket.d.ts +21 -0
- package/dist/server/preview-cdp-socket.js +112 -0
- package/dist/server/preview-cdp-socket.js.map +1 -0
- package/dist/server/preview-socket.d.ts +11 -11
- package/dist/server/preview-socket.js +22 -22
- package/dist/server/preview-socket.js.map +1 -1
- package/dist/server/preview-sockets.d.ts +14 -0
- package/dist/server/preview-sockets.js +18 -0
- package/dist/server/preview-sockets.js.map +1 -0
- package/dist/server/project-context.d.ts +54 -18
- package/dist/server/project-context.js +178 -5
- package/dist/server/project-context.js.map +1 -1
- package/dist/server/provider-action-gate.d.ts +0 -2
- package/dist/server/provider-action-gate.js +0 -21
- package/dist/server/provider-action-gate.js.map +1 -1
- package/dist/server/provider-auth-runtime.d.ts +3 -18
- package/dist/server/provider-auth-runtime.js +3 -18
- package/dist/server/provider-auth-runtime.js.map +1 -1
- package/dist/server/repo-branches.d.ts +3 -9
- package/dist/server/repo-branches.js +6 -22
- package/dist/server/repo-branches.js.map +1 -1
- package/dist/server/run-event-feed.d.ts +20 -0
- package/dist/server/run-event-feed.js +190 -0
- package/dist/server/run-event-feed.js.map +1 -0
- package/dist/server/server-deps.d.ts +37 -0
- package/dist/server/server-deps.js +114 -0
- package/dist/server/server-deps.js.map +1 -0
- package/dist/server/server.d.ts +14082 -11998
- package/dist/server/server.js +785 -1647
- package/dist/server/server.js.map +1 -1
- package/dist/server/start-run-options.d.ts +82 -0
- package/dist/server/start-run-options.js +111 -0
- package/dist/server/start-run-options.js.map +1 -0
- package/dist/server/validators.d.ts +3 -29
- package/dist/server/validators.js +1 -2
- package/dist/server/validators.js.map +1 -1
- package/dist/server/ws.d.ts +3 -23
- package/dist/server/ws.js +3 -23
- package/dist/server/ws.js.map +1 -1
- package/dist/server-install/engine.d.ts +6 -9
- package/dist/server-install/engine.js +2 -9
- package/dist/server-install/engine.js.map +1 -1
- package/dist/server-install/platforms/ubuntu-vps.d.ts +1 -1
- package/dist/server-install/state.d.ts +2 -4
- package/dist/server-install/state.js +2 -4
- package/dist/server-install/state.js.map +1 -1
- package/dist/server-install/steps.d.ts +2 -5
- package/dist/server-install/steps.js +3 -6
- package/dist/server-install/steps.js.map +1 -1
- package/dist/server-install/types.d.ts +3 -6
- package/dist/server-install/types.js +2 -5
- package/dist/server-install/types.js.map +1 -1
- package/dist/server-install/ui.d.ts +2 -8
- package/dist/server-install/ui.js +3 -3
- package/dist/server-install/ui.js.map +1 -1
- package/dist/session-context.d.ts +64 -0
- package/dist/session-context.js +264 -0
- package/dist/session-context.js.map +1 -0
- package/dist/skills-provision.d.ts +62 -0
- package/dist/skills-provision.js +325 -0
- package/dist/skills-provision.js.map +1 -0
- package/dist/skills-remote.d.ts +29 -27
- package/dist/skills-remote.js +236 -100
- package/dist/skills-remote.js.map +1 -1
- package/dist/skills.d.ts +25 -36
- package/dist/skills.js +43 -54
- package/dist/skills.js.map +1 -1
- package/dist/subcommands.d.ts +11 -0
- package/dist/subcommands.js +24 -0
- package/dist/subcommands.js.map +1 -0
- package/dist/task-cli/cli.js +78 -25
- package/dist/task-cli/cli.js.map +1 -1
- package/dist/task-cli/discovery.d.ts +4 -2
- package/dist/task-cli/discovery.js +14 -13
- package/dist/task-cli/discovery.js.map +1 -1
- package/dist/task-cli/hint.d.ts +20 -0
- package/dist/task-cli/hint.js +14 -0
- package/dist/task-cli/hint.js.map +1 -0
- package/dist/task-cli/http.d.ts +1 -0
- package/dist/task-cli/http.js +3 -1
- package/dist/task-cli/http.js.map +1 -1
- package/dist/task-cli/projections.d.ts +14 -11
- package/dist/task-cli/projections.js +15 -11
- package/dist/task-cli/projections.js.map +1 -1
- package/dist/task-cli/watch.d.ts +18 -10
- package/dist/task-cli/watch.js +128 -20
- package/dist/task-cli/watch.js.map +1 -1
- package/dist/ui-state.d.ts +17 -3
- package/dist/ui-state.js +56 -9
- package/dist/ui-state.js.map +1 -1
- package/dist/update-check.d.ts +0 -10
- package/dist/update-check.js +1 -16
- package/dist/update-check.js.map +1 -1
- package/dist/voice/decide.d.ts +32 -0
- package/dist/voice/decide.js +297 -0
- package/dist/voice/decide.js.map +1 -0
- package/dist/voice/decision-log.d.ts +52 -0
- package/dist/voice/decision-log.js +107 -0
- package/dist/voice/decision-log.js.map +1 -0
- package/dist/voice/engine.d.ts +119 -0
- package/dist/voice/engine.js +60 -0
- package/dist/voice/engine.js.map +1 -0
- package/dist/voice/fake-engine.d.ts +10 -0
- package/dist/voice/fake-engine.js +192 -0
- package/dist/voice/fake-engine.js.map +1 -0
- package/dist/voice/jev-engine.d.ts +17 -0
- package/dist/voice/jev-engine.js +110 -0
- package/dist/voice/jev-engine.js.map +1 -0
- package/dist/voice/pending-ask.d.ts +17 -0
- package/dist/voice/pending-ask.js +50 -0
- package/dist/voice/pending-ask.js.map +1 -0
- package/dist/voice/routes.d.ts +115 -0
- package/dist/voice/routes.js +91 -0
- package/dist/voice/routes.js.map +1 -0
- package/dist/voice/sentence.d.ts +21 -0
- package/dist/voice/sentence.js +61 -0
- package/dist/voice/sentence.js.map +1 -0
- package/dist/voice/thresholds.d.ts +28 -0
- package/dist/voice/thresholds.js +29 -0
- package/dist/voice/thresholds.js.map +1 -0
- package/dist/webhooks/cli.d.ts +18 -0
- package/dist/webhooks/cli.js +145 -0
- package/dist/webhooks/cli.js.map +1 -0
- package/dist/webhooks/prompt.d.ts +5 -0
- package/dist/webhooks/prompt.js +26 -0
- package/dist/webhooks/prompt.js.map +1 -0
- package/dist/workflows/active-run.d.ts +167 -0
- package/dist/workflows/active-run.js +21 -0
- package/dist/workflows/active-run.js.map +1 -0
- package/dist/workflows/continuation-admission.d.ts +913 -0
- package/dist/workflows/continuation-admission.js +265 -0
- package/dist/workflows/continuation-admission.js.map +1 -0
- package/dist/workflows/execution-account.d.ts +13 -0
- package/dist/workflows/execution-account.js +18 -0
- package/dist/workflows/execution-account.js.map +1 -0
- package/dist/workflows/input-acknowledgement.d.ts +152 -0
- package/dist/workflows/input-acknowledgement.js +38 -0
- package/dist/workflows/input-acknowledgement.js.map +1 -0
- package/dist/workflows/line-order.d.ts +5 -0
- package/dist/workflows/line-order.js +25 -0
- package/dist/workflows/line-order.js.map +1 -0
- package/dist/workflows/outcome-batches.d.ts +20 -0
- package/dist/workflows/outcome-batches.js +25 -0
- package/dist/workflows/outcome-batches.js.map +1 -0
- package/dist/workflows/question-routing.d.ts +8 -0
- package/dist/workflows/question-routing.js +18 -0
- package/dist/workflows/question-routing.js.map +1 -0
- package/dist/workflows/run-scheduling.d.ts +35 -0
- package/dist/workflows/run-scheduling.js +61 -0
- package/dist/workflows/run-scheduling.js.map +1 -0
- package/dist/workflows/run-states.d.ts +190 -0
- package/dist/workflows/run-states.js +295 -0
- package/dist/workflows/run-states.js.map +1 -0
- package/dist/workflows/run.d.ts +1296 -278
- package/dist/workflows/run.js +5730 -3265
- package/dist/workflows/run.js.map +1 -1
- package/dist/workflows/turn-end.d.ts +116 -0
- package/dist/workflows/turn-end.js +68 -0
- package/dist/workflows/turn-end.js.map +1 -0
- package/dist/workflows/types.d.ts +35 -130
- package/dist/workflows/types.js +47 -100
- package/dist/workflows/types.js.map +1 -1
- package/dist/workflows/waits.d.ts +74 -0
- package/dist/workflows/waits.js +197 -0
- package/dist/workflows/waits.js.map +1 -0
- package/dist/workspace/agent-accounts.d.ts +5 -38
- package/dist/workspace/agent-accounts.js +14 -40
- package/dist/workspace/agent-accounts.js.map +1 -1
- package/dist/workspace/agent-profiles.d.ts +40 -16
- package/dist/workspace/agent-profiles.js +77 -17
- package/dist/workspace/agent-profiles.js.map +1 -1
- package/dist/workspace/config.d.ts +48 -49
- package/dist/workspace/config.js +68 -72
- package/dist/workspace/config.js.map +1 -1
- package/dist/workspace/migrations.d.ts +3 -13
- package/dist/workspace/migrations.js.map +1 -1
- package/dist/workspace/projects-cli.d.ts +1 -1
- package/dist/workspace/projects-cli.js.map +1 -1
- package/dist/workspace/projects.d.ts +15 -18
- package/dist/workspace/projects.js +20 -16
- package/dist/workspace/projects.js.map +1 -1
- package/dist/workspace/semaphore.d.ts +11 -45
- package/dist/workspace/semaphore.js +6 -18
- package/dist/workspace/semaphore.js.map +1 -1
- package/dist/workspace/ui-state.d.ts +6 -4
- package/dist/workspace/ui-state.js +6 -4
- package/dist/workspace/ui-state.js.map +1 -1
- package/dist/workspace/webhooks.d.ts +40 -0
- package/dist/workspace/webhooks.js +146 -0
- package/dist/workspace/webhooks.js.map +1 -0
- package/dist/worktree-manifest.d.ts +165 -0
- package/dist/worktree-manifest.js +530 -0
- package/dist/worktree-manifest.js.map +1 -0
- package/dist/worktree-setup.js.map +1 -1
- package/package.json +6 -5
- package/scripts/benchmark-run-store-fixture.ts +7 -3
- package/scripts/check-pack.mjs +3 -1
- package/scripts/inline-contract.mjs +80 -27
- package/scripts/install-as-command.mjs +3 -1
- package/scripts/measure-transcript-facts-health.mjs +87 -0
- package/scripts/measure-transcript-facts-lag.mjs +68 -0
- package/scripts/mock-ci-tool.mjs +49 -6
- package/scripts/mock-claude-model-refusal.mjs +42 -0
- package/scripts/mock-claude.mjs +833 -591
- package/scripts/mock-codex-app-server.mjs +785 -418
- package/scripts/mock-cursor-acp.mjs +296 -125
- package/scripts/mock-cursor-print.mjs +256 -0
- package/scripts/mock-deferred-turn-start.mjs +16 -0
- package/scripts/mock-delivery-control.d.mts +23 -0
- package/scripts/mock-delivery-control.mjs +80 -0
- package/scripts/mock-env-record.mjs +11 -0
- package/scripts/mock-failure-control.d.mts +13 -0
- package/scripts/mock-failure-control.mjs +68 -0
- package/scripts/mock-multi-pr.mjs +7 -0
- package/scripts/mock-nudge.mjs +45 -0
- package/scripts/mock-omp-rpc.mjs +429 -255
- package/scripts/mock-opencode-serve.mjs +972 -557
- package/scripts/mock-pi-rpc.mjs +558 -331
- package/scripts/mock-runner-crash.mjs +18 -2
- package/scripts/mock-session-context.d.mts +5 -0
- package/scripts/mock-session-context.mjs +56 -0
- package/scripts/mock-silent-tail.mjs +10 -3
- package/scripts/pi-default-tools.mjs +22 -0
- package/scripts/pi-project-skills.mjs +59 -0
- package/scripts/probe-cursor-print.mjs +627 -0
- package/scripts/transcript-facts-fixture.mjs +53 -0
- package/scripts/voice-replay.ts +50 -0
- package/scripts/windows-workspace-identity.cs +208 -0
- package/scripts/windows-workspace-identity.ps1 +10 -0
- package/web/dist/assets/alert-dialog-DfctKUMw.js +1 -0
- package/web/dist/assets/button-CeupvoKG.js +41 -0
- package/web/dist/assets/centered-state-hDsyXrnH.js +1 -0
- package/web/dist/assets/cez-idle-D3aj_9lp.js +1 -0
- package/web/dist/assets/diff-BnIXZK3i2.js +3 -0
- package/web/dist/assets/diff-controls-GewpW9aF.js +1 -0
- package/web/dist/assets/diff-view-Byo7gpvW.js +11 -0
- package/web/dist/assets/dropdown-menu-COj_J5wd.js +6 -0
- package/web/dist/assets/eye-B8okNWXU.js +1 -0
- package/web/dist/assets/git-toolbar-DY0z0n4S.js +1 -0
- package/web/dist/assets/github-DwU6ALRK.js +1 -0
- package/web/dist/assets/{image-preview-FOEfqpZP.js → image-preview-C_t9q45f.js} +1 -1
- package/web/dist/assets/index-BOfE8pyD.js +34 -0
- package/web/dist/assets/index-D9HpsmdW.css +1 -0
- package/web/dist/assets/live-protocol-Uce2NwEX.js +64 -0
- package/web/dist/assets/live-worker-BizfZSoh.ts +33 -0
- package/web/dist/assets/markdown-BBDDg-4t.js +1 -0
- package/web/dist/assets/nav-row-styles-AoIhhIwf.js +1 -0
- package/web/dist/assets/popover-D56fhiXj.js +1 -0
- package/web/dist/assets/preview-pane-connected-BmVqfSU5.js +3 -0
- package/web/dist/assets/reference-chip-gQNk-4jc.js +1 -0
- package/web/dist/assets/repo-git-B5ECDUuv.js +1 -0
- package/web/dist/assets/{repo-git-CoKp-g9K.css → repo-git-DVXNOJDT.css} +1 -1
- package/web/dist/assets/run-header-C0Y1NvEM.js +2 -0
- package/web/dist/assets/run-header-CC7VUTg9.css +1 -0
- package/web/dist/assets/skills-DUeTkZ9z.js +1 -0
- package/web/dist/assets/status-dot-1PR0i69P.js +1 -0
- package/web/dist/assets/tab-link-DmWk4l5O.js +1 -0
- package/web/dist/assets/task-changes-DKZXuW89.js +1 -0
- package/web/dist/assets/task-commits-BZ6KxWdF.js +1 -0
- package/web/dist/assets/task-files-DlF7Apcn.js +2 -0
- package/web/dist/assets/task-github-item-CVPo3geZ.js +1 -0
- package/web/dist/assets/task-thread-DtQ6uGfQ.css +1 -0
- package/web/dist/assets/task-thread-mm4-ECyo.js +9 -0
- package/web/dist/assets/thread-state-CIw2BlhT.js +4 -0
- package/web/dist/assets/use-hand-to-agent-state-BCDjzHnG.js +1 -0
- package/web/dist/assets/use-hand-to-agent-state-C7esPJ-N.css +1 -0
- package/web/dist/assets/workflows-D8vYD-ql.js +7 -0
- package/web/dist/assets/zoomable-image-CxQSsfcn.js +1 -0
- package/web/dist/index.html +13 -17
- package/web/dist/live-worker.js +4 -0
- package/dist/core/tool-display.js +0 -179
- package/dist/core/tool-display.js.map +0 -1
- package/dist/runs/human-ask-summary.d.ts +0 -9
- package/dist/runs/human-ask-summary.js +0 -39
- package/dist/runs/human-ask-summary.js.map +0 -1
- package/dist/runs/run-search.d.ts +0 -29
- package/dist/runs/run-search.js +0 -63
- package/dist/runs/run-search.js.map +0 -1
- package/dist/skills-banner.d.ts +0 -22
- package/dist/skills-banner.js +0 -41
- package/dist/skills-banner.js.map +0 -1
- package/dist/skills-update.d.ts +0 -88
- package/dist/skills-update.js +0 -392
- package/dist/skills-update.js.map +0 -1
- package/dist/todos.d.ts +0 -48
- package/dist/todos.js +0 -201
- package/dist/todos.js.map +0 -1
- package/web/dist/assets/agent-accounts-CFOBMVHc.js +0 -1
- package/web/dist/assets/alert-dialog-BrpNUwMt.js +0 -1
- package/web/dist/assets/button-C_rd7CPp.js +0 -43
- package/web/dist/assets/compare-variants-D6WXhvXA.js +0 -1
- package/web/dist/assets/diff-DrEARXTV.js +0 -3
- package/web/dist/assets/diff-controls-B1-j7nFg.js +0 -1
- package/web/dist/assets/diff-view-DvGLjdTk.js +0 -6
- package/web/dist/assets/dropdown-menu-BegOZFrj.js +0 -1
- package/web/dist/assets/format-DpNe3S0A.js +0 -1
- package/web/dist/assets/git-toolbar-Cw4ljmhB.js +0 -1
- package/web/dist/assets/github-CfV5sqL0.js +0 -1
- package/web/dist/assets/index-DgWWlOLy.js +0 -13
- package/web/dist/assets/index-fBFnuvxu.css +0 -1
- package/web/dist/assets/nav-row-styles-vp2JbhuJ.js +0 -1
- package/web/dist/assets/popover-BohP6WTx.js +0 -1
- package/web/dist/assets/preview-pane-connected-qTA5KNoJ.js +0 -3
- package/web/dist/assets/preview-state-vuMviq6q.js +0 -1
- package/web/dist/assets/prompt-templates-Cubdut_C.js +0 -15
- package/web/dist/assets/repo-git-Cf4t5PD0.js +0 -1
- package/web/dist/assets/run-diff-BpkUW37Z.js +0 -3
- package/web/dist/assets/run-header-68WHf9wV.js +0 -1
- package/web/dist/assets/run-header-8GObNx6F.css +0 -1
- package/web/dist/assets/search-x-I9Q8pgUa.js +0 -1
- package/web/dist/assets/skills-DFBiAuJG.js +0 -1
- package/web/dist/assets/skills-DiVIgKeU.js +0 -1
- package/web/dist/assets/square-terminal-B6RYYieR.js +0 -1
- package/web/dist/assets/status-dot-CqTJHSP9.js +0 -1
- package/web/dist/assets/tab-link-B07Hu4QX.js +0 -1
- package/web/dist/assets/task-changes--lQF6EYf.js +0 -1
- package/web/dist/assets/task-commits-Cx0qy4DN.js +0 -1
- package/web/dist/assets/task-files-D50s-gKW.js +0 -2
- package/web/dist/assets/task-github-item-DaqmSwYT.js +0 -1
- package/web/dist/assets/task-thread-BPQ64lui.js +0 -7
- package/web/dist/assets/task-thread-zNE2Q9E-.css +0 -1
- package/web/dist/assets/textarea-D20O4Pw0.js +0 -1
- package/web/dist/assets/thread-state-DWcFMrvb.js +0 -4
- package/web/dist/assets/use-hand-to-agent-state-BLIGmwbd.css +0 -1
- package/web/dist/assets/use-hand-to-agent-state-Cy9eyyfL.js +0 -1
- package/web/dist/assets/utils-JsL3ZsJf.js +0 -64
- package/web/dist/assets/workflows-jwG7uxqi.js +0 -11
- package/web/dist/assets/zoomable-image-BJJ64KGc.js +0 -1
package/scripts/mock-claude.mjs
CHANGED
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
// Load only when configured: ordinary mock turns retain their event-loop ordering.
|
|
3
|
+
const failureControl = process.env.CEZ_MOCK_FAILURE_CONTROL === undefined ? undefined
|
|
4
|
+
: (await import('./mock-failure-control.mjs')).readFailureControl(['provider', 'usage-limit', 'unread']);
|
|
5
|
+
// Claude acknowledges agent input with the local stdin write, so only a held response is native.
|
|
6
|
+
const delivery = process.env.CEZ_MOCK_DELIVERY_CONTROL === undefined ? undefined
|
|
7
|
+
: (await import('./mock-delivery-control.mjs')).readDeliveryControl(['hold-response']);
|
|
2
8
|
// Keep this fixture standalone: lifecycle tests copy the runner into a temp directory.
|
|
3
9
|
import { spawn as watchdogSpawn } from 'node:child_process';
|
|
4
|
-
import { writeFileSync as
|
|
10
|
+
import { closeSync as watchdogCloseInput, renameSync as watchdogRename, writeFileSync as watchdogWrite } from 'node:fs';
|
|
11
|
+
// Publish a pid atomically (temporary sibling, then rename): a test reading it sees no
|
|
12
|
+
// file or a whole pid, never the empty file whose Number() is 0 (hearsay-tools/cezarion#953).
|
|
13
|
+
function watchdogWritePid(file, pid) { const tmp = `${file}.${process.pid}.tmp`; watchdogWrite(tmp, pid); watchdogRename(tmp, file); }
|
|
5
14
|
function watchdogStall(prompt) {
|
|
6
15
|
if (!prompt.includes('mock:no-progress')) return false;
|
|
7
|
-
|
|
16
|
+
if (prompt.includes('input-closed')) {
|
|
17
|
+
watchdogCloseInput(0);
|
|
18
|
+
watchdogWritePid('input-closed.pid', String(process.pid));
|
|
19
|
+
setTimeout(() => process.exit(0), 300);
|
|
20
|
+
}
|
|
8
21
|
if (prompt.includes('ignore-term')) {
|
|
9
22
|
process.removeAllListeners('SIGTERM');
|
|
10
23
|
process.on('SIGTERM', () => {});
|
|
@@ -17,10 +30,12 @@ function watchdogStall(prompt) {
|
|
|
17
30
|
if (prompt.includes('leftover')) {
|
|
18
31
|
// hearsay-tools/cezarion#890: one child stays in the session's process group and ignores
|
|
19
32
|
// SIGTERM; one leaves the group with setsid. Both exit on their own as a cleanup backstop.
|
|
20
|
-
const leftover = (file) => `process.on('SIGTERM',()=>{}); require('fs').writeFileSync(${JSON.stringify(file)}, String(process.pid)); setTimeout(()=>{},20000)`;
|
|
33
|
+
const leftover = (file) => `process.on('SIGTERM',()=>{}); const fs = require('fs'); fs.writeFileSync(${JSON.stringify(`${file}.tmp`)}, String(process.pid)); fs.renameSync(${JSON.stringify(`${file}.tmp`)}, ${JSON.stringify(file)}); setTimeout(()=>{},20000)`;
|
|
21
34
|
watchdogSpawn(process.execPath, ['-e', leftover('leftover-group.pid')], { stdio: 'ignore' });
|
|
22
35
|
watchdogSpawn(process.execPath, ['-e', leftover('leftover-session.pid')], { stdio: 'ignore', detached: true }).unref();
|
|
23
36
|
}
|
|
37
|
+
// Publish readiness after mode setup: another process may signal us as soon as it sees it.
|
|
38
|
+
watchdogWritePid('watchdog.pid', String(process.pid));
|
|
24
39
|
return true;
|
|
25
40
|
}
|
|
26
41
|
|
|
@@ -32,8 +47,11 @@ function watchdogStall(prompt) {
|
|
|
32
47
|
|
|
33
48
|
import { createInterface } from 'node:readline';
|
|
34
49
|
import { appendFileSync, readFileSync, writeFileSync } from 'node:fs';
|
|
50
|
+
// Dynamic, like every sibling import here, so a test's copy of this mock can repoint it.
|
|
51
|
+
const { answerNudge, silentNudge } = await import('./mock-nudge.mjs');
|
|
35
52
|
|
|
36
53
|
import * as parityGateFs from 'node:fs';
|
|
54
|
+
import { withoutSessionContext } from './mock-session-context.mjs';
|
|
37
55
|
async function waitForMockRelease(fallbackMs) {
|
|
38
56
|
const file = process.env.CEZ_MOCK_RELEASE_FILE;
|
|
39
57
|
if (!file) { if (fallbackMs) await sleep(fallbackMs); return; }
|
|
@@ -52,11 +70,44 @@ async function afterParityPark(prompt) {
|
|
|
52
70
|
}
|
|
53
71
|
|
|
54
72
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
55
|
-
|
|
73
|
+
/** Leave a visible trace in the cwd (the task worktree under spec 006) so
|
|
74
|
+
* the Diff view has something real to show in dry runs. Exactly one line
|
|
75
|
+
* per spawned session: tests read this file back as a per-step trace, so
|
|
76
|
+
* a multi-line prompt must not become multiple lines here. CEZ_MOCK_NOTES=0 leaves the
|
|
77
|
+
* worktree clean, so a suite that never reads it pays no autosave commit (hearsay-tools/cezarion#1665). */
|
|
78
|
+
function writeNotesTrace(userText) {
|
|
79
|
+
if (process.env.CEZ_MOCK_NOTES === '0') return;
|
|
80
|
+
try {
|
|
81
|
+
const head = userText.replace(/\s+/g, ' ').trim().slice(0, 400);
|
|
82
|
+
appendFileSync('notes.md', `mock notes — ${new Date().toISOString()}: ${head}\n`);
|
|
83
|
+
} catch {
|
|
84
|
+
// read-only cwd — the mock still works, just without a diff
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// `mock:steer-tool` holds its tool call for CEZ_MOCK_STEER_MS, or, with CEZ_MOCK_STEER_LINES=<n>,
|
|
88
|
+
// until it has read n steered lines, so a loaded host cannot close the turn first (hearsay-tools/cezarion#1280).
|
|
89
|
+
async function holdSteerTool() {
|
|
90
|
+
const lines = Number(process.env.CEZ_MOCK_STEER_LINES ?? 0);
|
|
91
|
+
if (!lines) { await sleep(Number(process.env.CEZ_MOCK_STEER_MS ?? 600)); return; }
|
|
92
|
+
const deadline = Date.now() + 15_000;
|
|
93
|
+
while (steering.length < lines) {
|
|
94
|
+
if (Date.now() > deadline) throw new Error(`CEZ_MOCK_STEER_LINES: ${steering.length} of ${lines} steered lines arrived`);
|
|
95
|
+
await sleep(10);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// Lines a `mock:ack-only` reply read and never answered (hearsay-tools/cezarion#1301): the turn they
|
|
99
|
+
// opened is still running, so the next turn's result settles them with its own, as Claude settles
|
|
100
|
+
// every line one turn consumed (#505).
|
|
101
|
+
let heldUuids = [];
|
|
102
|
+
let respondingUuid;
|
|
103
|
+
const emit = (obj) => {
|
|
104
|
+
if (obj?.type === 'result' && heldUuids.length) obj = { ...obj, user_message_uuids: [...heldUuids.splice(0), ...(obj.user_message_uuids ?? [respondingUuid].filter(Boolean))] };
|
|
105
|
+
process.stdout.write(`${JSON.stringify(obj)}\n`);
|
|
106
|
+
};
|
|
56
107
|
|
|
57
108
|
// `--help` lists the options cezar feature-detects (#505).
|
|
58
109
|
if (process.argv.includes('--help')) {
|
|
59
|
-
process.stdout.write('Usage: claude [options]\n --input-format <format>\n --replay-user-messages Re-emit user messages from stdin back on stdout\n');
|
|
110
|
+
process.stdout.write('Usage: claude [options]\n --input-format <format>\n --replay-user-messages Re-emit user messages from stdin back on stdout\n --include-hook-events Include all hook lifecycle events in the output stream\n');
|
|
60
111
|
process.exit(0);
|
|
61
112
|
}
|
|
62
113
|
|
|
@@ -89,11 +140,9 @@ let droppedOnce = false;
|
|
|
89
140
|
const MOCK_SCREENSHOT_B64 =
|
|
90
141
|
'iVBORw0KGgoAAAANSUhEUgAAAUAAAADICAIAAAAWZq/8AAACMklEQVR42u3csQnAIBRFUQdJY+b4tfvP4AhCLKyyghAMMRw4Ezz/bU0RBdhUMgEIGBAwIGAQMCBgQMCAgEHAgIABAYOAAQEDAgYEDAIGBAwsCLhfDdiUgEHAgIABAYOAAQEDAgYEDAIGBAwIGAT8vlEr/ImAQcACBgELGAQsYAQsYBCwgEHAAgYBe3IELGAQsIBBwAJGwAIGAQsYBCxgELCAEbCAQcACBgELGAQMAhYwCFjAIGABI2D/QgMCBgEDAgYEDAgYBAwIGBAwCBgQMCBgQMAgYEDAgIBBwCYAAQMCBgQMAgYEDAgYEDAIGBAwIGAQMCBgQMCAgEHAgIABAQMCBgEDAgYEDAIGBAwIGBAwCBgQMCBgQMAgYEDAgIBBwICAAQEDAgYBAwIGBAwCtgIIGBAwIGAQMCBgQMCAgEHAgIABAYOAeejMB/McjIAFLGABW0HAAhYwmhSwgAUsYAQsYAELGAELWMACRsACFrCAEbCABSxgBCxgAQtYwAhYwAIWMAIWsIAFjIAFLGABI2ABC1jACFjAAhYwAhawgAWMgAUsYAEjYAELWMACRsACFrCAEbCABSxgBCxgAQsYAQtYwAJGwAIWMCBgQMAgYEDAgIBBwICAAQEDAgYBAwIGBAwCBgQMCBgQMAgYEDAgYEDAIGBAwICAQcCAgAEBAwIGAQMCBgQMCBgEDAgYEDAIGBAwIGBAwCBgQMCAgAEBg4ABAQMCBgEDAgYEDAgYBAx8xQ1bxBr9kelHqgAAAABJRU5ErkJggg==';
|
|
91
142
|
|
|
92
|
-
|
|
93
|
-
//
|
|
94
|
-
|
|
95
|
-
// CEZ_TODOS_FILE, so the inbox loop is testable without tokens.
|
|
96
|
-
function writeHandoffAndTodo() {
|
|
143
|
+
// Spec 007: behave like an agent that read the handoff instructions —
|
|
144
|
+
// append a progress line to CEZ_HANDOFF_FILE so handoff continuity is testable without tokens.
|
|
145
|
+
function writeHandoff() {
|
|
97
146
|
try {
|
|
98
147
|
const handoff = process.env.CEZ_HANDOFF_FILE;
|
|
99
148
|
if (handoff) {
|
|
@@ -110,648 +159,652 @@ function writeHandoffAndTodo() {
|
|
|
110
159
|
} catch {
|
|
111
160
|
// best effort — the mock still answers without a handoff file
|
|
112
161
|
}
|
|
113
|
-
try {
|
|
114
|
-
const todosFile = process.env.CEZ_TODOS_FILE;
|
|
115
|
-
if (todosFile) {
|
|
116
|
-
let items = [];
|
|
117
|
-
try {
|
|
118
|
-
items = JSON.parse(readFileSync(todosFile, 'utf8'));
|
|
119
|
-
} catch {
|
|
120
|
-
items = []; // missing or broken file — start fresh, append-only
|
|
121
|
-
}
|
|
122
|
-
if (!Array.isArray(items)) items = [];
|
|
123
|
-
items.push({
|
|
124
|
-
ts: new Date().toISOString(),
|
|
125
|
-
taskId: process.env.CEZ_TASK_ID,
|
|
126
|
-
summary: 'Follow up: verify the mock change',
|
|
127
|
-
suggestedPrompt: 'Verify the change from the previous task',
|
|
128
|
-
});
|
|
129
|
-
writeFileSync(todosFile, JSON.stringify(items, null, 2), 'utf8');
|
|
130
|
-
}
|
|
131
|
-
} catch {
|
|
132
|
-
// best effort
|
|
133
|
-
}
|
|
134
162
|
}
|
|
135
163
|
|
|
136
164
|
async function respond(userText, imageCount, uuid) {
|
|
165
|
+
respondingUuid = uuid;
|
|
166
|
+
if (delivery) await delivery.holdResponse(userText);
|
|
167
|
+
// Native refusal and crash handling stay before deferred input and replay.
|
|
168
|
+
// hearsay-tools/cezarion#1351: native refusals before any model work.
|
|
169
|
+
if (userText.startsWith('mock:model-refusal')) {
|
|
170
|
+
const { modelRefusalReply } = await import('./mock-claude-model-refusal.mjs');
|
|
171
|
+
await modelRefusalReply(userText, uuid, emit, emitReplay);
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
137
174
|
if (userText.includes('mock:crash-stderr')) {
|
|
138
175
|
const { crashWithStderr } = await import('./mock-runner-crash.mjs');
|
|
139
176
|
if (crashWithStderr(userText, '{"type":"assistant","message":')) return;
|
|
140
177
|
}
|
|
178
|
+
// hearsay-tools/cezarion#1112: the line waits in the pipe before the model reads it.
|
|
179
|
+
if (userText.includes('mock:deferred-turn-start')) await (await import('./mock-deferred-turn-start.mjs')).deferredTurnStart();
|
|
141
180
|
emitReplay(uuid, userText);
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
const text = autonomousReply(userText);
|
|
145
|
-
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'text', text }] } });
|
|
146
|
-
emit({ type: 'result', subtype: 'success', result: text, user_message_uuids: [uuid].filter(Boolean), usage: { input_tokens: 10, output_tokens: 5 } });
|
|
147
|
-
return;
|
|
148
|
-
}
|
|
149
|
-
if (userText.includes('mock:silent-tail') || userText.includes('mock:tool-tail') || userText.includes('Your last turn ended without a message to the user.')) {
|
|
150
|
-
const silent = await import('./mock-silent-tail.mjs');
|
|
151
|
-
silent.noteSilentTailPrompt(userText);
|
|
152
|
-
if (silent.isFinalMessageNudge(userText)) {
|
|
153
|
-
const kind = silent.finalMessageNudgeKind();
|
|
154
|
-
if (kind === 'ack-only') return;
|
|
155
|
-
if (kind === 'late') await silent.sleep(silent.LATE_REPLY_MS);
|
|
156
|
-
if (kind === 'silent') {
|
|
157
|
-
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'thinking', thinking: silent.SILENT_TAIL_REASONING }] } });
|
|
158
|
-
emit({ type: 'result', subtype: 'success', result: '', user_message_uuids: [uuid].filter(Boolean), usage: { input_tokens: 10, output_tokens: 5 } });
|
|
159
|
-
} else {
|
|
160
|
-
if (kind === 'slow-done') {
|
|
161
|
-
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'text', text: silent.SLOW_DONE_PREFIX }] } });
|
|
162
|
-
await silent.sleep(silent.SLOW_DONE_TAIL_MS);
|
|
163
|
-
}
|
|
164
|
-
const text = kind === 'standing' ? silent.FINAL_MESSAGE_STANDING : silent.SILENT_TAIL_DONE;
|
|
165
|
-
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'text', text }] } });
|
|
166
|
-
emit({ type: 'result', subtype: 'success', result: text, user_message_uuids: [uuid].filter(Boolean), usage: { input_tokens: 10, output_tokens: 5 } });
|
|
167
|
-
}
|
|
168
|
-
return;
|
|
169
|
-
}
|
|
170
|
-
if (silent.isSilentTailScenario(userText)) {
|
|
171
|
-
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'text', text: silent.SILENT_TAIL_OPENING }] } });
|
|
172
|
-
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'tool_use', id: 'toolu_silent_gh', name: 'Bash', input: { command: 'gh issue create' } }] } });
|
|
173
|
-
emit({ type: 'user', message: { role: 'user', content: [{ type: 'tool_result', tool_use_id: 'toolu_silent_gh', content: 'created' }] } });
|
|
174
|
-
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'thinking', thinking: silent.SILENT_TAIL_REASONING }] } });
|
|
175
|
-
emit({ type: 'result', subtype: 'success', result: silent.SILENT_TAIL_OPENING, user_message_uuids: [uuid].filter(Boolean), usage: { input_tokens: 20, output_tokens: 10 } });
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
178
|
-
if (silent.isToolTailScenario(userText)) {
|
|
179
|
-
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'text', text: silent.TOOL_TAIL_OPENING }] } });
|
|
180
|
-
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'tool_use', id: 'toolu_tool_tail', name: 'Bash', input: { command: 'git status --short' } }] } });
|
|
181
|
-
emit({ type: 'user', message: { role: 'user', content: [{ type: 'tool_result', tool_use_id: 'toolu_tool_tail', content: ' M src/example.ts' }] } });
|
|
182
|
-
emit({ type: 'result', subtype: 'success', result: silent.TOOL_TAIL_OPENING, user_message_uuids: [uuid].filter(Boolean), usage: { input_tokens: 20, output_tokens: 10 } });
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
// `mock:steer-tool` → one tool call; lines written while it runs are consumed after
|
|
187
|
-
// it (replayed with their uuid) and settled by the SAME result, like Claude 2.1.280 (#505).
|
|
188
|
-
if (userText.includes('mock:steer-tool')) {
|
|
189
|
-
steering = [];
|
|
190
|
-
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'tool_use', id: 'toolu_steer', name: 'Bash', input: { command: 'wait' } }] } });
|
|
191
|
-
await sleep(Number(process.env.CEZ_MOCK_STEER_MS ?? 600));
|
|
192
|
-
const steered = steering; steering = null;
|
|
193
|
-
emit({ type: 'user', message: { role: 'user', content: [{ type: 'tool_result', tool_use_id: 'toolu_steer', content: 'waited' }] } });
|
|
194
|
-
for (const s of steered) emitReplay(s.uuid, s.userText);
|
|
195
|
-
const text = ['steer tool done', ...steered.map(s => `saw: ${s.userText}`)].join('\n');
|
|
196
|
-
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'text', text }] } });
|
|
197
|
-
emit({ type: 'result', subtype: 'success', result: text, user_message_uuids: [uuid, ...steered.map(s => s.uuid)].filter(Boolean), usage: { input_tokens: 20, output_tokens: 10 } });
|
|
198
|
-
return;
|
|
199
|
-
}
|
|
200
|
-
// Native child attribution from __fixtures__/claude/subagent-task.ndjson.
|
|
201
|
-
if (!userText.includes('[cez-namer]') && userText.includes('mock:subagent-after-park')) {
|
|
202
|
-
const task = `toolu_park_${turn}`;
|
|
203
|
-
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'tool_use', id: task, name: 'Task', input: { description: 'Review' } }] } });
|
|
204
|
-
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'text', text: 'Watching the child.\nCEZ:MONITORING' }] } });
|
|
205
|
-
emit({ type: 'result', subtype: 'success', result: 'Watching the child.\nCEZ:MONITORING', usage: { input_tokens: 10, output_tokens: 5 } });
|
|
206
|
-
await afterParityPark(userText);
|
|
207
|
-
emit({ type: 'assistant', parent_tool_use_id: task, message: { role: 'assistant', content: [{ type: 'tool_use', id: 'late-read', name: 'Read', input: { file_path: 'README.md' } }] } });
|
|
208
|
-
emit({ type: 'user', parent_tool_use_id: task, message: { role: 'user', content: [{ type: 'tool_result', tool_use_id: 'late-read', content: 'Read the file.' }] } });
|
|
209
|
-
emit({ type: 'assistant', parent_tool_use_id: task, message: { role: 'assistant', content: [{ type: 'text', text: 'Post-park child update processed.' }] } });
|
|
210
|
-
return;
|
|
211
|
-
}
|
|
212
|
-
// #401: result-only full text; mapResult and v1 use the same fallback.
|
|
213
|
-
if (userText.includes('mock:turn-messages:')) {
|
|
214
|
-
const { turnMessages } = await import('./mock-turn-messages.mjs');
|
|
215
|
-
const messages = turnMessages(userText);
|
|
216
|
-
for (const text of messages) emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'text', text }] } });
|
|
217
|
-
emit({ type: 'result', subtype: 'success', result: messages.join('\n'), usage: { input_tokens: 10, output_tokens: 5 } });
|
|
218
|
-
return;
|
|
219
|
-
}
|
|
220
|
-
if (!userText.includes('[cez-namer]') && userText.includes('mock:ask-snapshot')) {
|
|
221
|
-
emit({ type: 'result', subtype: 'success', result: userText.includes('mock:ask-snapshot-bad') ? 'CEZ:ASK {not valid json' : 'Using the CEZ:ASK structured question format instead:\n\nCEZ:ASK {"questions":[{"header":"Library","question":"Which test library?","options":[{"label":"Vitest"},{"label":"Node test"}]}]}', usage: { input_tokens: 10, output_tokens: 5 } });
|
|
222
|
-
return;
|
|
223
|
-
}
|
|
224
|
-
if (!userText.includes('[cez-namer]') && userText.includes('mock:ask-prose')) {
|
|
225
|
-
emit({ type: 'result', subtype: 'success', result: 'Use `CEZ:ASK {"questions":[]}` in your reply.\n> CEZ:ASK {not valid json', usage: { input_tokens: 10, output_tokens: 5 } });
|
|
226
|
-
return;
|
|
227
|
-
}
|
|
228
|
-
if (userText.includes('mock:ci-wait')) {
|
|
229
|
-
const { ciPrompt } = await import('./mock-ci-tool.mjs');
|
|
230
|
-
const text = await ciPrompt('claude', process.argv.slice(2), userText);
|
|
231
|
-
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'text', text }] } });
|
|
232
|
-
emit({ type: 'result', subtype: 'success', result: text, usage: { input_tokens: 20, output_tokens: 10 } });
|
|
233
|
-
return;
|
|
234
|
-
}
|
|
235
|
-
if (!userText.includes('[cez-namer]') && userText.includes('mock:preview-serve')) {
|
|
236
|
-
const { previewPrompt } = await import('./mock-ci-tool.mjs');
|
|
237
|
-
const text = await previewPrompt('claude', process.argv.slice(2), userText);
|
|
238
|
-
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'text', text }] } });
|
|
239
|
-
emit({ type: 'result', subtype: 'success', result: text, usage: { input_tokens: 20, output_tokens: 10 } });
|
|
240
|
-
return;
|
|
241
|
-
}
|
|
181
|
+
// Early scenarios do not advance the ordinary turn counter.
|
|
182
|
+
if (await dispatchReply(earlyReplies, userText, uuid)) return;
|
|
242
183
|
turn += 1;
|
|
243
184
|
await sleep(250);
|
|
244
|
-
|
|
245
|
-
// completion marker (#347), so the auto-close path is testable dry.
|
|
246
|
-
const answered = resumeAfterAsk && userText.trim() === 'Library: Vitest';
|
|
247
|
-
resumeAfterAsk = userText.includes('mock:ask') && userText.includes('mock:resume-done');
|
|
248
|
-
const doneMarker = (userText.includes('mock:done') || answered) ? '\n\nCEZ:DONE' : '';
|
|
249
|
-
// `mock:monitoring` → the reply ends with CEZ:MONITORING, the "still working
|
|
250
|
-
// on downstream work" marker (#490), so the monitoring-status path is testable dry.
|
|
251
|
-
const monitoringMarker = userText.includes('mock:monitoring') ? '\n\nCEZ:MONITORING' : '';
|
|
252
|
-
// `mock:ask` → the reply ends with a valid CEZ:ASK marker (#473), so the
|
|
253
|
-
// AskUser card path (park `waiting` + emit `ask.requested`) is testable dry.
|
|
254
|
-
// `mock:ask-bad` → a MALFORMED marker (invalid JSON), to prove graceful
|
|
255
|
-
// degradation: the run still parks `waiting`, no ask card, prose preserved.
|
|
256
|
-
// `mock:ask-invalid` → syntactically valid JSON that FAILS the ask schema
|
|
257
|
-
// (empty questions) — the shape behind the blank-question bug: no card will
|
|
258
|
-
// ever render it, so the marker must survive in the v1 text.
|
|
259
|
-
// `mock:ask-near` → bounded presentation drift: harmless extra keys plus
|
|
260
|
-
// an overlong header/description. It should normalize into exactly one card.
|
|
261
|
-
// `mock:ask-truncated` → a complete payload one closing brace short (#936):
|
|
262
|
-
// the closer repair should still produce one card, note the recovery, and
|
|
263
|
-
// strip the raw marker (which ends on `]`, not `}`).
|
|
264
|
-
const askMarker = userText.includes('mock:ask-bad')
|
|
265
|
-
? '\n\nCEZ:ASK {not valid json'
|
|
266
|
-
: userText.includes('mock:ask-invalid')
|
|
267
|
-
? '\n\nCEZ:ASK {"questions":[]}'
|
|
268
|
-
: userText.includes('mock:ask-truncated')
|
|
269
|
-
? '\n\nCEZ:ASK {"questions":[{"header":"Lint scope","question":"How much of the lint backlog should I land now?","multiSelect":false,"options":[{"label":"First slice only"},{"label":"Rule by rule"},{"label":"Whole backlog"}]}]'
|
|
270
|
-
: userText.includes('mock:ask-near')
|
|
271
|
-
? '\n\nCEZ:ASK ' +
|
|
272
|
-
JSON.stringify({
|
|
273
|
-
transportHint: 'render as chips',
|
|
274
|
-
questions: [
|
|
275
|
-
{
|
|
276
|
-
header: 'Implementation path',
|
|
277
|
-
question: 'Which implementation should I use?',
|
|
278
|
-
presentation: 'compact',
|
|
279
|
-
options: [
|
|
280
|
-
{ label: 'Minimal', description: 'd'.repeat(300), recommended: true },
|
|
281
|
-
{ label: 'Expanded', description: 'Touch the wider surface' },
|
|
282
|
-
],
|
|
283
|
-
},
|
|
284
|
-
],
|
|
285
|
-
})
|
|
286
|
-
: userText.includes('mock:ask')
|
|
287
|
-
? '\n\nCEZ:ASK ' +
|
|
288
|
-
JSON.stringify({
|
|
289
|
-
questions: [
|
|
290
|
-
{
|
|
291
|
-
header: 'Library',
|
|
292
|
-
question: 'Which date library should I standardize on?',
|
|
293
|
-
options: [
|
|
294
|
-
{ label: 'date-fns', description: 'Tree-shakeable, functional' },
|
|
295
|
-
{ label: 'Luxon', description: 'Immutable, tz-aware' },
|
|
296
|
-
],
|
|
297
|
-
},
|
|
298
|
-
],
|
|
299
|
-
})
|
|
300
|
-
: '';
|
|
301
|
-
// `mock:refs` → the reply carries the in-band task-reference markers
|
|
302
|
-
// (spec 2026-07-18-task-ref-markers), so the declaration path is testable dry.
|
|
303
|
-
const refsMarkers = userText.includes('mock:refs')
|
|
304
|
-
? '\nCEZ:PR=4242\nCEZ:ISSUE=17\nCEZ:TITLE=implementing marker refs'
|
|
305
|
-
: '';
|
|
306
|
-
|
|
185
|
+
const markers = markersFor(userText);
|
|
307
186
|
// `mock:slow` → hold the turn for ~25 s so queue states are observable.
|
|
308
187
|
if (userText.includes('mock:slow')) await sleep(25_000);
|
|
188
|
+
if (await dispatchReply(timedReplies, userText, uuid)) return;
|
|
189
|
+
// Failure selection stays after timed holds and before markdown/naming.
|
|
190
|
+
if (await replyWithNativeFailure(userText)) return;
|
|
191
|
+
if (await dispatchReply(trailingReplies, userText, uuid)) return;
|
|
192
|
+
if (userText.includes('mock:schedule-wakeup')) await replyWithScheduleWakeup(userText);
|
|
193
|
+
if (turn === 1) { await replyWithFirstTurn(userText, markers); return; }
|
|
194
|
+
await replyWithFollowup(userText, imageCount, markers);
|
|
195
|
+
}
|
|
309
196
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
// "needs you" instead of monitoring (#2's failure mode on claude's wire).
|
|
316
|
-
if (userText.includes('mock:split-text')) {
|
|
317
|
-
for (const block of ['parity split text', 'CEZ:MONITORING']) {
|
|
318
|
-
emit({
|
|
319
|
-
type: 'assistant',
|
|
320
|
-
message: { role: 'assistant', content: [{ type: 'text', text: block }], usage: { input_tokens: 20, output_tokens: 10 } },
|
|
321
|
-
});
|
|
322
|
-
await sleep(50);
|
|
323
|
-
}
|
|
324
|
-
emit({
|
|
325
|
-
type: 'result',
|
|
326
|
-
subtype: 'success',
|
|
327
|
-
result: 'parity split text\n\nCEZ:MONITORING',
|
|
328
|
-
usage: { input_tokens: 20, output_tokens: 10 },
|
|
329
|
-
total_cost_usd: 0.0001,
|
|
330
|
-
});
|
|
331
|
-
return;
|
|
332
|
-
}
|
|
197
|
+
// `mock:ack-only` → the line is read (replayed) and its turn says nothing until more input
|
|
198
|
+
// arrives (hearsay-tools/cezarion#1301).
|
|
199
|
+
async function acknowledgeOnly(userText, uuid) {
|
|
200
|
+
if (uuid) heldUuids.push(uuid); return;
|
|
201
|
+
}
|
|
333
202
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
203
|
+
async function replyAutonomously(userText, uuid) {
|
|
204
|
+
const { autonomousReply } = await import('./mock-autonomous.mjs');
|
|
205
|
+
const text = autonomousReply(userText);
|
|
206
|
+
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'text', text }] } });
|
|
207
|
+
emit({ type: 'result', subtype: 'success', result: text, user_message_uuids: [uuid].filter(Boolean), usage: { input_tokens: 10, output_tokens: 5 } });
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
340
210
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
return;
|
|
351
|
-
}
|
|
352
|
-
if (userText.includes('mock:hold-done')) {
|
|
353
|
-
await waitForMockRelease(400);
|
|
354
|
-
const held = 'parity hold-done: content after the pause\n\nCEZ:DONE';
|
|
355
|
-
emit({
|
|
356
|
-
type: 'assistant',
|
|
357
|
-
message: { role: 'assistant', content: [{ type: 'text', text: held }], usage: { input_tokens: 20, output_tokens: 10 } },
|
|
358
|
-
});
|
|
359
|
-
emit({ type: 'result', subtype: 'success', result: held, usage: { input_tokens: 20, output_tokens: 10 }, total_cost_usd: 0.0001 });
|
|
360
|
-
return;
|
|
361
|
-
}
|
|
362
|
-
if (userText.includes('mock:hold-ask')) {
|
|
363
|
-
await waitForMockRelease(400);
|
|
364
|
-
const ask = 'Pick one.\n\nCEZ:ASK {"questions":[{"header":"Library","question":"Which test library?","options":[{"label":"Vitest"},{"label":"Node test"}]}]}';
|
|
365
|
-
emit({
|
|
366
|
-
type: 'assistant',
|
|
367
|
-
message: { role: 'assistant', content: [{ type: 'text', text: ask }], usage: { input_tokens: 20, output_tokens: 10 } },
|
|
368
|
-
});
|
|
369
|
-
emit({ type: 'result', subtype: 'success', result: ask, usage: { input_tokens: 20, output_tokens: 10 }, total_cost_usd: 0.0001 });
|
|
370
|
-
return;
|
|
371
|
-
}
|
|
372
|
-
if (userText.includes('mock:hold-gated')) {
|
|
373
|
-
await waitForMockRelease(250);
|
|
374
|
-
const gated = 'parity hold-gated: content after the pause';
|
|
375
|
-
emit({
|
|
376
|
-
type: 'assistant',
|
|
377
|
-
message: { role: 'assistant', content: [{ type: 'text', text: gated }], usage: { input_tokens: 20, output_tokens: 10 } },
|
|
378
|
-
});
|
|
379
|
-
await sleep(250);
|
|
380
|
-
emit({ type: 'result', subtype: 'success', result: gated, usage: { input_tokens: 20, output_tokens: 10 }, total_cost_usd: 0.0001 });
|
|
381
|
-
return;
|
|
382
|
-
}
|
|
383
|
-
if (userText.includes('mock:hold')) {
|
|
384
|
-
await sleep(250);
|
|
385
|
-
const held = 'parity hold: content after the pause';
|
|
386
|
-
emit({
|
|
387
|
-
type: 'assistant',
|
|
388
|
-
message: { role: 'assistant', content: [{ type: 'text', text: held }], usage: { input_tokens: 20, output_tokens: 10 } },
|
|
389
|
-
});
|
|
390
|
-
await sleep(250);
|
|
391
|
-
emit({ type: 'result', subtype: 'success', result: held, usage: { input_tokens: 20, output_tokens: 10 }, total_cost_usd: 0.0001 });
|
|
392
|
-
return;
|
|
211
|
+
async function replyToFinalMessageNudge(silent, uuid) {
|
|
212
|
+
const kind = silent.finalMessageNudgeKind();
|
|
213
|
+
if (kind === 'ack-only') return;
|
|
214
|
+
if (kind === 'late') await waitForMockRelease(silent.LATE_REPLY_MS);
|
|
215
|
+
if (kind === 'silent') {
|
|
216
|
+
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'thinking', thinking: silent.SILENT_TAIL_REASONING }] } });
|
|
217
|
+
emit({ type: 'result', subtype: 'success', result: '', user_message_uuids: [uuid].filter(Boolean), usage: { input_tokens: 10, output_tokens: 5 } });
|
|
218
|
+
} else {
|
|
219
|
+
await replyWithFinalTailText(silent, uuid, kind);
|
|
393
220
|
}
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
394
223
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
usage: { input_tokens: 0, output_tokens: 0 },
|
|
405
|
-
total_cost_usd: 0,
|
|
406
|
-
});
|
|
407
|
-
return;
|
|
408
|
-
}
|
|
224
|
+
async function replyWithFinalTailText(silent, uuid, kind) {
|
|
225
|
+
if (kind === 'slow-done') {
|
|
226
|
+
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'text', text: silent.SLOW_DONE_PREFIX }] } });
|
|
227
|
+
await silent.sleep(silent.SLOW_DONE_TAIL_MS);
|
|
228
|
+
}
|
|
229
|
+
const text = kind === 'standing' ? silent.FINAL_MESSAGE_STANDING : silent.SILENT_TAIL_DONE;
|
|
230
|
+
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'text', text }] } });
|
|
231
|
+
emit({ type: 'result', subtype: 'success', result: text, user_message_uuids: [uuid].filter(Boolean), usage: { input_tokens: 10, output_tokens: 5 } });
|
|
232
|
+
}
|
|
409
233
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
const seconds = Number.isFinite(configured) ? configured : 60;
|
|
419
|
-
emit({
|
|
420
|
-
type: 'result',
|
|
421
|
-
subtype: 'success',
|
|
422
|
-
is_error: true,
|
|
423
|
-
result: `Claude AI usage limit reached|${Math.floor(Date.now() / 1000) + seconds}`,
|
|
424
|
-
usage: { input_tokens: 0, output_tokens: 0 },
|
|
425
|
-
total_cost_usd: 0,
|
|
426
|
-
});
|
|
427
|
-
return;
|
|
428
|
-
}
|
|
234
|
+
async function replyWithSilentTail(silent, uuid) {
|
|
235
|
+
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'text', text: silent.SILENT_TAIL_OPENING }] } });
|
|
236
|
+
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'tool_use', id: 'toolu_silent_gh', name: 'Bash', input: { command: 'gh issue create' } }] } });
|
|
237
|
+
emit({ type: 'user', message: { role: 'user', content: [{ type: 'tool_result', tool_use_id: 'toolu_silent_gh', content: 'created' }] } });
|
|
238
|
+
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'thinking', thinking: silent.SILENT_TAIL_REASONING }] } });
|
|
239
|
+
emit({ type: 'result', subtype: 'success', result: silent.SILENT_TAIL_OPENING, user_message_uuids: [uuid].filter(Boolean), usage: { input_tokens: 20, output_tokens: 10 } });
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
429
242
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
'> quoted intro',
|
|
449
|
-
'> - quoted list item',
|
|
450
|
-
'',
|
|
451
|
-
'```ts',
|
|
452
|
-
'const answer: number = 42;',
|
|
453
|
-
'```',
|
|
454
|
-
'Literal guards: snake_case_name, 2*3 and <script>alert(1)</script>.',
|
|
455
|
-
].join('\n');
|
|
456
|
-
emit({
|
|
457
|
-
type: 'assistant',
|
|
458
|
-
message: { role: 'assistant', content: [{ type: 'text', text: md }], usage: { input_tokens: 100, output_tokens: 200 } },
|
|
459
|
-
});
|
|
460
|
-
await sleep(100);
|
|
461
|
-
emit({ type: 'result', subtype: 'success', result: md, usage: { input_tokens: 100, output_tokens: 200 }, total_cost_usd: 0.001 });
|
|
462
|
-
return;
|
|
243
|
+
async function replyWithToolTail(silent, uuid) {
|
|
244
|
+
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'text', text: silent.TOOL_TAIL_OPENING }] } });
|
|
245
|
+
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'tool_use', id: 'toolu_tool_tail', name: 'Bash', input: { command: 'git status --short' } }] } });
|
|
246
|
+
emit({ type: 'user', message: { role: 'user', content: [{ type: 'tool_result', tool_use_id: 'toolu_tool_tail', content: ' M src/example.ts' }] } });
|
|
247
|
+
emit({ type: 'result', subtype: 'success', result: silent.TOOL_TAIL_OPENING, user_message_uuids: [uuid].filter(Boolean), usage: { input_tokens: 20, output_tokens: 10 } });
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
async function replyToSilentTail(userText, uuid) {
|
|
252
|
+
const silent = await import('./mock-silent-tail.mjs');
|
|
253
|
+
silent.noteSilentTailPrompt(userText);
|
|
254
|
+
const scenarios = [
|
|
255
|
+
[() => silent.isFinalMessageNudge(userText), replyToFinalMessageNudge],
|
|
256
|
+
[() => silent.isSilentTailScenario(userText), replyWithSilentTail],
|
|
257
|
+
[() => silent.isToolTailScenario(userText), replyWithToolTail]
|
|
258
|
+
];
|
|
259
|
+
for (const [matches, reply] of scenarios) {
|
|
260
|
+
if (matches()) { await reply(silent, uuid); return; }
|
|
463
261
|
}
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
464
264
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
{ tool: 'Grep', id: `toolu_sub_a1_${turn}`, input: { pattern: 'session', path: 'src' }, result: 'src/middleware.ts:12: clearSession()' },
|
|
480
|
-
{ tool: 'Read', id: `toolu_sub_a2_${turn}`, input: { file_path: 'src/middleware.ts' }, result: 'export function middleware() { clearSession() }' },
|
|
481
|
-
],
|
|
482
|
-
result: 'The session cookie is dropped in src/middleware.ts:12 (clearSession on every redirect).',
|
|
483
|
-
},
|
|
484
|
-
{
|
|
485
|
-
id: `toolu_task_b_${turn}`,
|
|
486
|
-
description: 'Review the store layer',
|
|
487
|
-
subagent_type: 'code-reviewer',
|
|
488
|
-
steps: [
|
|
489
|
-
{ text: 'Reading the runs store.' },
|
|
490
|
-
{ tool: 'Bash', id: `toolu_sub_b1_${turn}`, input: { command: 'npm test -- runs/store' }, result: '12 passed' },
|
|
491
|
-
],
|
|
492
|
-
result: 'Store layer looks correct; one debounce edge case worth a follow-up.',
|
|
493
|
-
},
|
|
494
|
-
];
|
|
265
|
+
// `mock:steer-tool` → one tool call; lines written while it runs are consumed after
|
|
266
|
+
// it (replayed with their uuid) and settled by the SAME result, like Claude 2.1.280 (#505).
|
|
267
|
+
async function replyToSteering(userText, uuid) {
|
|
268
|
+
steering = [];
|
|
269
|
+
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'tool_use', id: 'toolu_steer', name: 'Bash', input: { command: 'wait' } }] } });
|
|
270
|
+
await holdSteerTool();
|
|
271
|
+
const steered = steering; steering = null;
|
|
272
|
+
emit({ type: 'user', message: { role: 'user', content: [{ type: 'tool_result', tool_use_id: 'toolu_steer', content: 'waited' }] } });
|
|
273
|
+
for (const s of steered) emitReplay(s.uuid, s.userText);
|
|
274
|
+
const text = ['steer tool done', ...steered.map(s => `saw: ${s.userText}`)].join('\n');
|
|
275
|
+
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'text', text }] } });
|
|
276
|
+
emit({ type: 'result', subtype: 'success', result: text, user_message_uuids: [uuid, ...steered.map(s => s.uuid)].filter(Boolean), usage: { input_tokens: 20, output_tokens: 10 } });
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
495
279
|
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
],
|
|
511
|
-
usage: { input_tokens: 900, output_tokens: 95 },
|
|
512
|
-
},
|
|
513
|
-
parent_tool_use_id: null,
|
|
514
|
-
});
|
|
515
|
-
await sleep(200);
|
|
516
|
-
}
|
|
280
|
+
// #961: hook_response frames as `--include-hook-events` emits them (CLI 2.1.301) — one
|
|
281
|
+
// mid-turn, one after the run parked (Squeal's async `waiter` completes this late).
|
|
282
|
+
async function replyWithParkedHook(userText, uuid) {
|
|
283
|
+
const hook = (id, event, text) => ({
|
|
284
|
+
type: 'system', subtype: 'hook_response', hook_id: `hook-${id}-${turn}`, hook_name: event, hook_event: event,
|
|
285
|
+
stdout: JSON.stringify({ hookSpecificOutput: { hookEventName: event, additionalContext: text } }), stderr: '', exit_code: 0, outcome: 'success',
|
|
286
|
+
});
|
|
287
|
+
emit(hook('mid', 'PostToolBatch', 'Mid-turn hook context.'));
|
|
288
|
+
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'text', text: 'Watching.\nCEZ:MONITORING' }] } });
|
|
289
|
+
emit({ type: 'result', subtype: 'success', result: 'Watching.\nCEZ:MONITORING', usage: { input_tokens: 10, output_tokens: 5 } });
|
|
290
|
+
await afterParityPark(userText);
|
|
291
|
+
emit(hook('late', 'Stop', 'Late hook processed.'));
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
517
294
|
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
} else {
|
|
531
|
-
emit({
|
|
532
|
-
type: 'assistant',
|
|
533
|
-
message: {
|
|
534
|
-
role: 'assistant',
|
|
535
|
-
content: [{ type: 'tool_use', id: step.id, name: step.tool, input: step.input }],
|
|
536
|
-
usage: { input_tokens: 40, output_tokens: 50 },
|
|
537
|
-
},
|
|
538
|
-
parent_tool_use_id: agent.id,
|
|
539
|
-
});
|
|
540
|
-
await sleep(250);
|
|
541
|
-
emit({
|
|
542
|
-
type: 'user',
|
|
543
|
-
message: { role: 'user', content: [{ type: 'tool_result', tool_use_id: step.id, content: step.result }] },
|
|
544
|
-
parent_tool_use_id: agent.id,
|
|
545
|
-
});
|
|
546
|
-
}
|
|
547
|
-
await sleep(250);
|
|
548
|
-
}
|
|
549
|
-
}
|
|
295
|
+
// Native child attribution from __fixtures__/claude/subagent-task.ndjson.
|
|
296
|
+
async function replyWithParkedChild(userText, uuid) {
|
|
297
|
+
const task = `toolu_park_${turn}`;
|
|
298
|
+
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'tool_use', id: task, name: 'Task', input: { description: 'Review' } }] } });
|
|
299
|
+
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'text', text: 'Watching the child.\nCEZ:MONITORING' }] } });
|
|
300
|
+
emit({ type: 'result', subtype: 'success', result: 'Watching the child.\nCEZ:MONITORING', usage: { input_tokens: 10, output_tokens: 5 } });
|
|
301
|
+
await afterParityPark(userText);
|
|
302
|
+
emit({ type: 'assistant', parent_tool_use_id: task, message: { role: 'assistant', content: [{ type: 'tool_use', id: 'late-read', name: 'Read', input: { file_path: 'README.md' } }] } });
|
|
303
|
+
emit({ type: 'user', parent_tool_use_id: task, message: { role: 'user', content: [{ type: 'tool_result', tool_use_id: 'late-read', content: 'Read the file.' }] } });
|
|
304
|
+
emit({ type: 'assistant', parent_tool_use_id: task, message: { role: 'assistant', content: [{ type: 'text', text: 'Post-park child update processed.' }] } });
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
550
307
|
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
308
|
+
// hearsay-tools/cezarion#1284: a `context: fork` skill through the Skill tool, from
|
|
309
|
+
// __fixtures__/claude/forked-skill.ndjson (CLI 2.1.303). Real Claude starts the fork
|
|
310
|
+
// whatever --disallowedTools denies, so this branch ignores the argv too.
|
|
311
|
+
async function replyWithForkedSkill(userText, uuid) {
|
|
312
|
+
const skill = `toolu_skill_fork_${turn}`;
|
|
313
|
+
const bash = `toolu_fork_bash_${turn}`;
|
|
314
|
+
const task = { task_id: `a1284f0000000f0a${turn}`, tool_use_id: skill };
|
|
315
|
+
const child = { parent_tool_use_id: skill, agent_id: task.task_id, subagent_type: 'general-purpose' };
|
|
316
|
+
const text = 'The fxfork skill returned: `FXFORK-2W`';
|
|
317
|
+
emit({ type: 'assistant', parent_tool_use_id: null, message: { role: 'assistant', content: [{ type: 'tool_use', id: skill, name: 'Skill', input: { skill: 'fxfork' } }] } });
|
|
318
|
+
emit({ type: 'system', subtype: 'task_started', ...task, description: '/fxfork', subagent_type: 'general-purpose', spawn_depth: 1, task_type: 'local_agent' });
|
|
319
|
+
emit({ type: 'user', ...child, message: { role: 'user', content: [{ type: 'text', text: 'Run the shell command `echo forked > /dev/null` and reply with exactly FXFORK-2W.' }] } });
|
|
320
|
+
emit({ type: 'assistant', ...child, message: { role: 'assistant', content: [{ type: 'tool_use', id: bash, name: 'Bash', input: { command: 'echo forked > /dev/null' } }] } });
|
|
321
|
+
emit({ type: 'user', ...child, message: { role: 'user', content: [{ type: 'tool_result', tool_use_id: bash, content: '(Bash completed with no output)', is_error: false }] } });
|
|
322
|
+
emit({ type: 'system', subtype: 'task_notification', ...task, status: 'completed', summary: '/fxfork' });
|
|
323
|
+
emit({ type: 'user', parent_tool_use_id: null, message: { role: 'user', content: [{ type: 'tool_result', tool_use_id: skill, content: 'Skill "fxfork" completed (forked execution).\n\nResult:\nFXFORK-2W' }] } });
|
|
324
|
+
emit({ type: 'assistant', parent_tool_use_id: null, message: { role: 'assistant', content: [{ type: 'text', text }] } });
|
|
325
|
+
emit({ type: 'result', subtype: 'success', result: text, usage: { input_tokens: 10, output_tokens: 5 } });
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
560
328
|
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
await sleep(150);
|
|
574
|
-
emit({
|
|
575
|
-
type: 'result',
|
|
576
|
-
subtype: 'success',
|
|
577
|
-
result: summary,
|
|
578
|
-
usage: { input_tokens: 2100, output_tokens: 380 },
|
|
579
|
-
total_cost_usd: 0.0512,
|
|
580
|
-
});
|
|
581
|
-
return;
|
|
582
|
-
}
|
|
329
|
+
// #401: result-only full text; mapResult and v1 use the same fallback.
|
|
330
|
+
async function replyWithMultiplePrs(userText, uuid) {
|
|
331
|
+
const { multiPrText, unrelatedPr } = await import('./mock-multi-pr.mjs');
|
|
332
|
+
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'tool_use', id: 'multi-read', name: 'Read', input: { file_path: 'other.txt' } }] } });
|
|
333
|
+
emit({ type: 'user', message: { role: 'user', content: [{ type: 'tool_result', tool_use_id: 'multi-read', content: unrelatedPr }] } });
|
|
334
|
+
emit({ type: 'assistant', parent_tool_use_id: 'multi-read', message: { role: 'assistant', content: [{ type: 'text', text: unrelatedPr }] } });
|
|
335
|
+
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'thinking', thinking: unrelatedPr }] } });
|
|
336
|
+
const text = multiPrText(userText);
|
|
337
|
+
for (const block of text.split('\n')) emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'text', text: block }] } });
|
|
338
|
+
emit({ type: 'result', subtype: 'success', result: text, usage: { input_tokens: 10, output_tokens: 5 } });
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
583
341
|
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
342
|
+
async function replyWithTurnMessages(userText, uuid) {
|
|
343
|
+
const { turnMessages } = await import('./mock-turn-messages.mjs');
|
|
344
|
+
const messages = turnMessages(userText);
|
|
345
|
+
for (const text of messages) emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'text', text }] } });
|
|
346
|
+
emit({ type: 'result', subtype: 'success', result: messages.join('\n'), usage: { input_tokens: 10, output_tokens: 5 } });
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
async function replyWithAskSnapshot(userText, uuid) {
|
|
351
|
+
emit({ type: 'result', subtype: 'success', result: userText.includes('mock:ask-snapshot-bad') ? 'CEZ:ASK {not valid json' : 'Using the CEZ:ASK structured question format instead:\n\nCEZ:ASK {"questions":[{"header":"Library","question":"Which test library?","options":[{"label":"Vitest"},{"label":"Node test"}]}]}', usage: { input_tokens: 10, output_tokens: 5 } });
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
async function replyWithAskProse(userText, uuid) {
|
|
356
|
+
emit({ type: 'result', subtype: 'success', result: 'Use `CEZ:ASK {"questions":[]}` in your reply.\n> CEZ:ASK {not valid json', usage: { input_tokens: 10, output_tokens: 5 } });
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
async function replyWithCezarTool(userText, uuid) {
|
|
361
|
+
const { toolPrompt } = await import('./mock-ci-tool.mjs');
|
|
362
|
+
const text = await toolPrompt('claude', process.argv.slice(2), userText);
|
|
363
|
+
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'text', text }] } });
|
|
364
|
+
emit({ type: 'result', subtype: 'success', result: text, usage: { input_tokens: 20, output_tokens: 10 } });
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
async function replyWithCiWait(userText, uuid) {
|
|
369
|
+
const { ciPrompt } = await import('./mock-ci-tool.mjs');
|
|
370
|
+
const text = await ciPrompt('claude', process.argv.slice(2), userText);
|
|
371
|
+
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'text', text }] } });
|
|
372
|
+
emit({ type: 'result', subtype: 'success', result: text, usage: { input_tokens: 20, output_tokens: 10 } });
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
async function replyWithPreview(userText, uuid) {
|
|
377
|
+
const { previewPrompt } = await import('./mock-ci-tool.mjs');
|
|
378
|
+
const text = await previewPrompt('claude', process.argv.slice(2), userText);
|
|
379
|
+
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'text', text }] } });
|
|
380
|
+
emit({ type: 'result', subtype: 'success', result: text, usage: { input_tokens: 20, output_tokens: 10 } });
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// `mock:split-text` → the reply as TWO assistant blocks, the second being the
|
|
385
|
+
// bare `CEZ:MONITORING` marker. stream-json has no text deltas (one frame is
|
|
386
|
+
// one whole block, see `__fixtures__/claude/text-turn.ndjson`), so claude's
|
|
387
|
+
// strongest form of the harness parity S8 split is a multi-block reply: the
|
|
388
|
+
// assembled turn text must still end with the marker, or the run parks as
|
|
389
|
+
// "needs you" instead of monitoring (#2's failure mode on claude's wire).
|
|
390
|
+
async function replyWithSplitText(userText, uuid) {
|
|
391
|
+
for (const block of ['parity split text', 'CEZ:MONITORING']) {
|
|
593
392
|
emit({
|
|
594
393
|
type: 'assistant',
|
|
595
|
-
message: {
|
|
596
|
-
role: 'assistant',
|
|
597
|
-
content: [{ type: 'text', text: name }],
|
|
598
|
-
usage: { input_tokens: 200, output_tokens: 30 },
|
|
599
|
-
},
|
|
394
|
+
message: { role: 'assistant', content: [{ type: 'text', text: block }], usage: { input_tokens: 20, output_tokens: 10 } },
|
|
600
395
|
});
|
|
601
396
|
await sleep(50);
|
|
602
|
-
emit({
|
|
603
|
-
type: 'result',
|
|
604
|
-
subtype: 'success',
|
|
605
|
-
result: name,
|
|
606
|
-
usage: { input_tokens: 200, output_tokens: 30 },
|
|
607
|
-
total_cost_usd: 0.0002,
|
|
608
|
-
});
|
|
609
|
-
return;
|
|
610
397
|
}
|
|
398
|
+
emit({
|
|
399
|
+
type: 'result',
|
|
400
|
+
subtype: 'success',
|
|
401
|
+
result: 'parity split text\n\nCEZ:MONITORING',
|
|
402
|
+
usage: { input_tokens: 20, output_tokens: 10 },
|
|
403
|
+
total_cost_usd: 0.0001,
|
|
404
|
+
});
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// Same assistant/result envelopes as the baseline stream-json fixture.
|
|
409
|
+
async function replyWithEcho(userText, uuid) {
|
|
410
|
+
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'text', text: userText }] } });
|
|
411
|
+
emit({ type: 'result', subtype: 'success', result: userText, usage: { input_tokens: 20, output_tokens: 10 } });
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
async function acknowledgeStall(userText, uuid) {
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
async function replyWithBusyProgress(userText, uuid) {
|
|
419
|
+
for (let i = 0; i < 24; i++) { emit({ type: 'ping' }); await sleep(100); }
|
|
420
|
+
const busy = 'busy complete\n\nCEZ:DONE';
|
|
421
|
+
emit({ type: 'assistant', message: { role: 'assistant', content: [{ type: 'text', text: busy }], usage: { input_tokens: 20, output_tokens: 10 } } });
|
|
422
|
+
emit({ type: 'result', subtype: 'success', result: busy });
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
async function replyWithHeldDone(userText, uuid) {
|
|
427
|
+
await waitForMockRelease(400);
|
|
428
|
+
const held = 'parity hold-done: content after the pause\n\nCEZ:DONE';
|
|
429
|
+
emit({
|
|
430
|
+
type: 'assistant',
|
|
431
|
+
message: { role: 'assistant', content: [{ type: 'text', text: held }], usage: { input_tokens: 20, output_tokens: 10 } },
|
|
432
|
+
});
|
|
433
|
+
emit({ type: 'result', subtype: 'success', result: held, usage: { input_tokens: 20, output_tokens: 10 }, total_cost_usd: 0.0001 });
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
611
436
|
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
437
|
+
async function replyWithHeldAsk(userText, uuid) {
|
|
438
|
+
await waitForMockRelease(400);
|
|
439
|
+
const ask = 'Pick one.\n\nCEZ:ASK {"questions":[{"header":"Library","question":"Which test library?","options":[{"label":"Vitest"},{"label":"Node test"}]}]}';
|
|
440
|
+
emit({
|
|
441
|
+
type: 'assistant',
|
|
442
|
+
message: { role: 'assistant', content: [{ type: 'text', text: ask }], usage: { input_tokens: 20, output_tokens: 10 } },
|
|
443
|
+
});
|
|
444
|
+
emit({ type: 'result', subtype: 'success', result: ask, usage: { input_tokens: 20, output_tokens: 10 }, total_cost_usd: 0.0001 });
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
async function replyWithGatedHold(userText, uuid) {
|
|
449
|
+
await waitForMockRelease(250);
|
|
450
|
+
const gated = 'parity hold-gated: content after the pause';
|
|
451
|
+
emit({
|
|
452
|
+
type: 'assistant',
|
|
453
|
+
message: { role: 'assistant', content: [{ type: 'text', text: gated }], usage: { input_tokens: 20, output_tokens: 10 } },
|
|
454
|
+
});
|
|
455
|
+
await sleep(250);
|
|
456
|
+
emit({ type: 'result', subtype: 'success', result: gated, usage: { input_tokens: 20, output_tokens: 10 }, total_cost_usd: 0.0001 });
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
// `mock:hold` → pause, THEN stream the content and the terminal `result`.
|
|
461
|
+
// The harness parity matrix's S2 row asserts turn-end follows the last
|
|
462
|
+
// content event, so the pause has to sit BEFORE the content: a runner that
|
|
463
|
+
// closed the turn on a timer after writing the prompt would report it early.
|
|
464
|
+
async function replyWithHold(userText, uuid) {
|
|
465
|
+
// Short on purpose — `mock:slow` above is the 25 s queue-state hold.
|
|
466
|
+
await sleep(250);
|
|
467
|
+
const held = 'parity hold: content after the pause';
|
|
468
|
+
emit({
|
|
469
|
+
type: 'assistant',
|
|
470
|
+
message: { role: 'assistant', content: [{ type: 'text', text: held }], usage: { input_tokens: 20, output_tokens: 10 } },
|
|
471
|
+
});
|
|
472
|
+
await sleep(250);
|
|
473
|
+
emit({ type: 'result', subtype: 'success', result: held, usage: { input_tokens: 20, output_tokens: 10 }, total_cost_usd: 0.0001 });
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
// `mock:md` → answer with a markdown-rich reply (#346 QA: tables, nested
|
|
478
|
+
// lists, emphasis, fences, quotes) instead of the scripted turn.
|
|
479
|
+
async function replyWithMarkdown(userText, uuid) {
|
|
480
|
+
const md = [
|
|
481
|
+
'## Markdown fixture',
|
|
482
|
+
'This paragraph is soft-wrapped\nacross two source lines.',
|
|
483
|
+
'',
|
|
484
|
+
'| Column | Align | Result |',
|
|
485
|
+
'|:-------|:-----:|-------:|',
|
|
486
|
+
'| left `code` | *center* | **42** |',
|
|
487
|
+
'| ~~old~~ new | mid | $1.50 |',
|
|
488
|
+
'',
|
|
489
|
+
'- top item with *emphasis*',
|
|
490
|
+
' - nested child with `code`',
|
|
491
|
+
' - [x] deep done task',
|
|
492
|
+
' - [ ] nested todo',
|
|
493
|
+
'- second top',
|
|
494
|
+
'',
|
|
495
|
+
'> quoted intro',
|
|
496
|
+
'> - quoted list item',
|
|
497
|
+
'',
|
|
498
|
+
'```ts',
|
|
499
|
+
'const answer: number = 42;',
|
|
500
|
+
'```',
|
|
501
|
+
'Literal guards: snake_case_name, 2*3 and <script>alert(1)</script>.',
|
|
502
|
+
].join('\n');
|
|
503
|
+
emit({
|
|
504
|
+
type: 'assistant',
|
|
505
|
+
message: { role: 'assistant', content: [{ type: 'text', text: md }], usage: { input_tokens: 100, output_tokens: 200 } },
|
|
506
|
+
});
|
|
507
|
+
await sleep(100);
|
|
508
|
+
emit({ type: 'result', subtype: 'success', result: md, usage: { input_tokens: 100, output_tokens: 200 }, total_cost_usd: 0.001 });
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
// `mock:subagents` → a parallel fan-out: two `Task` spawns whose child items
|
|
513
|
+
// carry `parent_tool_use_id`, interleaved the way a real fan-out interleaves,
|
|
514
|
+
// then their results. Makes the Agents dock and its drill-down sheet reachable
|
|
515
|
+
// under CEZ_DRY_RUN=1 for QA, screenshots and the e2e smoke (spec
|
|
516
|
+
// `.ai/specs/2026-07-20-grouped-subagent-display.md` §"Testability hook", #474).
|
|
517
|
+
// Derived from the `subagent-task.ndjson` golden fixture's wire shape.
|
|
518
|
+
async function replyWithSubagents(userText, uuid) {
|
|
519
|
+
const agents = [
|
|
520
|
+
{
|
|
521
|
+
id: `toolu_task_a_${turn}`,
|
|
522
|
+
description: 'Audit the auth flow',
|
|
523
|
+
subagent_type: 'general-purpose',
|
|
619
524
|
steps: [
|
|
620
|
-
{
|
|
621
|
-
{
|
|
622
|
-
{
|
|
525
|
+
{ text: 'Scanning the auth middleware.' },
|
|
526
|
+
{ tool: 'Grep', id: `toolu_sub_a1_${turn}`, input: { pattern: 'session', path: 'src' }, result: 'src/middleware.ts:12: clearSession()' },
|
|
527
|
+
{ tool: 'Read', id: `toolu_sub_a2_${turn}`, input: { file_path: 'src/middleware.ts' }, result: 'export function middleware() { clearSession() }' },
|
|
623
528
|
],
|
|
624
|
-
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
529
|
+
result: 'The session cookie is dropped in src/middleware.ts:12 (clearSession on every redirect).',
|
|
530
|
+
},
|
|
531
|
+
{
|
|
532
|
+
id: `toolu_task_b_${turn}`,
|
|
533
|
+
description: 'Review the store layer',
|
|
534
|
+
subagent_type: 'code-reviewer',
|
|
535
|
+
steps: [
|
|
536
|
+
{ text: 'Reading the runs store.' },
|
|
537
|
+
{ tool: 'Bash', id: `toolu_sub_b1_${turn}`, input: { command: 'npm test -- runs/store' }, result: '12 passed' },
|
|
538
|
+
],
|
|
539
|
+
result: 'Store layer looks correct; one debounce edge case worth a follow-up.',
|
|
540
|
+
},
|
|
541
|
+
];
|
|
542
|
+
await replyWithSubagentSpawns(agents);
|
|
543
|
+
await replyWithSubagentSteps(agents);
|
|
544
|
+
await replyWithSubagentResults(agents);
|
|
545
|
+
const summary = 'Both sub-agents reported back: the redirect drops the cookie in src/middleware.ts:12, and the store layer is clean. (dry-run mock)\nCEZ:MONITORING';
|
|
546
|
+
emit({
|
|
547
|
+
type: 'assistant',
|
|
548
|
+
message: { role: 'assistant', content: [{ type: 'text', text: summary }], usage: { input_tokens: 400, output_tokens: 60 } },
|
|
549
|
+
parent_tool_use_id: null,
|
|
550
|
+
});
|
|
551
|
+
// #149: a child assistant frame can arrive after the parent's final marker.
|
|
552
|
+
emit({
|
|
553
|
+
type: 'assistant',
|
|
554
|
+
message: { role: 'assistant', content: [{ type: 'text', text: 'Child review finished.' }] },
|
|
555
|
+
parent_tool_use_id: agents[0].id,
|
|
556
|
+
});
|
|
557
|
+
await sleep(150);
|
|
558
|
+
emit({
|
|
559
|
+
type: 'result',
|
|
560
|
+
subtype: 'success',
|
|
561
|
+
result: summary,
|
|
562
|
+
usage: { input_tokens: 2100, output_tokens: 380 },
|
|
563
|
+
total_cost_usd: 0.0512,
|
|
564
|
+
});
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
644
567
|
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
const id = `toolu_schedule_wakeup_${turn}`;
|
|
568
|
+
// Both spawns first — that is what makes it a FAN-OUT rather than two
|
|
569
|
+
// sequential agents, and what the dock's "N/M" odometer counts.
|
|
570
|
+
async function replyWithSubagentSpawns(agents) {
|
|
571
|
+
for (const agent of agents) {
|
|
650
572
|
emit({
|
|
651
573
|
type: 'assistant',
|
|
652
574
|
message: {
|
|
653
575
|
role: 'assistant',
|
|
654
|
-
content: [
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
content: [{ type: 'tool_result', tool_use_id: id, content: 'Wakeup scheduled.' }],
|
|
576
|
+
content: [
|
|
577
|
+
{
|
|
578
|
+
type: 'tool_use',
|
|
579
|
+
id: agent.id,
|
|
580
|
+
name: 'Task',
|
|
581
|
+
input: { description: agent.description, prompt: `${agent.description}.`, subagent_type: agent.subagent_type },
|
|
582
|
+
},
|
|
583
|
+
],
|
|
584
|
+
usage: { input_tokens: 900, output_tokens: 95 },
|
|
664
585
|
},
|
|
586
|
+
parent_tool_use_id: null,
|
|
665
587
|
});
|
|
666
|
-
await sleep(
|
|
588
|
+
await sleep(200);
|
|
667
589
|
}
|
|
590
|
+
}
|
|
668
591
|
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
} catch {
|
|
678
|
-
// read-only cwd — the mock still works, just without a diff
|
|
592
|
+
// Children, interleaved across agents so the activity lines visibly race.
|
|
593
|
+
async function replyWithSubagentSteps(agents) {
|
|
594
|
+
const maxSteps = Math.max(...agents.map((agent) => agent.steps.length));
|
|
595
|
+
for (let i = 0; i < maxSteps; i += 1) {
|
|
596
|
+
for (const agent of agents) {
|
|
597
|
+
const step = agent.steps[i];
|
|
598
|
+
if (!step) continue;
|
|
599
|
+
await replyWithSubagentStep(agent, step);
|
|
679
600
|
}
|
|
680
|
-
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
async function replyWithSubagentStep(agent, step) {
|
|
605
|
+
if (step.text !== undefined) {
|
|
681
606
|
emit({
|
|
682
607
|
type: 'assistant',
|
|
683
|
-
message: {
|
|
684
|
-
|
|
685
|
-
content: [{ type: 'text', text: `Okay — looking into: ${userText.slice(0, 120)}` }],
|
|
686
|
-
usage: { input_tokens: 850, output_tokens: 40 },
|
|
687
|
-
},
|
|
608
|
+
message: { role: 'assistant', content: [{ type: 'text', text: step.text }], usage: { input_tokens: 300, output_tokens: 25 } },
|
|
609
|
+
parent_tool_use_id: agent.id,
|
|
688
610
|
});
|
|
689
|
-
|
|
611
|
+
} else {
|
|
690
612
|
emit({
|
|
691
613
|
type: 'assistant',
|
|
692
614
|
message: {
|
|
693
615
|
role: 'assistant',
|
|
694
|
-
content: [{ type: 'tool_use', id:
|
|
695
|
-
usage: { input_tokens:
|
|
616
|
+
content: [{ type: 'tool_use', id: step.id, name: step.tool, input: step.input }],
|
|
617
|
+
usage: { input_tokens: 40, output_tokens: 50 },
|
|
696
618
|
},
|
|
619
|
+
parent_tool_use_id: agent.id,
|
|
697
620
|
});
|
|
698
|
-
await sleep(
|
|
621
|
+
await sleep(250);
|
|
699
622
|
emit({
|
|
700
623
|
type: 'user',
|
|
701
|
-
message: {
|
|
702
|
-
|
|
703
|
-
content: [{ type: 'tool_result', tool_use_id: `toolu_mock_${turn}`, content: ' M src/example.ts' }],
|
|
704
|
-
},
|
|
624
|
+
message: { role: 'user', content: [{ type: 'tool_result', tool_use_id: step.id, content: step.result }] },
|
|
625
|
+
parent_tool_use_id: agent.id,
|
|
705
626
|
});
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
role: 'assistant',
|
|
714
|
-
content: [{ type: 'tool_use', id: `toolu_mock_shot_${turn}`, name: 'Screenshot', input: { name: 'repro-login-redirect.png' } }],
|
|
715
|
-
usage: { input_tokens: 80, output_tokens: 30 },
|
|
716
|
-
},
|
|
717
|
-
});
|
|
718
|
-
await sleep(200);
|
|
627
|
+
}
|
|
628
|
+
await sleep(250);
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
// The spawns settle — `parent_tool_use_id: null`, they belong to the main turn.
|
|
632
|
+
async function replyWithSubagentResults(agents) {
|
|
633
|
+
for (const agent of agents) {
|
|
719
634
|
emit({
|
|
720
635
|
type: 'user',
|
|
721
|
-
message: {
|
|
722
|
-
|
|
723
|
-
content: [
|
|
724
|
-
{
|
|
725
|
-
type: 'tool_result',
|
|
726
|
-
tool_use_id: `toolu_mock_shot_${turn}`,
|
|
727
|
-
content: [
|
|
728
|
-
{ type: 'text', text: 'Repro captured: after reload the session toast appears and you are back on /login.' },
|
|
729
|
-
{ type: 'image', source: { type: 'base64', media_type: 'image/png', data: MOCK_SCREENSHOT_B64 } },
|
|
730
|
-
],
|
|
731
|
-
},
|
|
732
|
-
],
|
|
733
|
-
},
|
|
734
|
-
});
|
|
735
|
-
await sleep(300);
|
|
736
|
-
emit({
|
|
737
|
-
type: 'assistant',
|
|
738
|
-
message: {
|
|
739
|
-
role: 'assistant',
|
|
740
|
-
content: [{ type: 'text', text: `Done with the first pass — opened a draft PR: https://github.com/open-mercato/demo/pull/123. Anything to adjust? (dry-run mock)${refsMarkers}${doneMarker}${monitoringMarker}${askMarker}` }],
|
|
741
|
-
usage: { input_tokens: 300, output_tokens: 90 },
|
|
742
|
-
},
|
|
743
|
-
});
|
|
744
|
-
await sleep(150);
|
|
745
|
-
emit({
|
|
746
|
-
type: 'result',
|
|
747
|
-
subtype: 'success',
|
|
748
|
-
result: 'Done with the first pass (dry run).',
|
|
749
|
-
usage: { input_tokens: 1270, output_tokens: 185 },
|
|
750
|
-
total_cost_usd: 0.0342,
|
|
636
|
+
message: { role: 'user', content: [{ type: 'tool_result', tool_use_id: agent.id, content: agent.result }] },
|
|
637
|
+
parent_tool_use_id: null,
|
|
751
638
|
});
|
|
752
|
-
|
|
639
|
+
await sleep(200);
|
|
753
640
|
}
|
|
641
|
+
}
|
|
754
642
|
|
|
643
|
+
// Task auto-naming spec: a naming call (marked `[cez-namer]`) answers a
|
|
644
|
+
// deterministic short title + a PR classification of the sample number so
|
|
645
|
+
// dry-run tests can assert the full apply pipeline.
|
|
646
|
+
async function replyWithName(userText, uuid) {
|
|
647
|
+
const numbered = /(?:^|\D)(\d{1,7})(?:\D|$)/.exec(userText);
|
|
648
|
+
const name = JSON.stringify({
|
|
649
|
+
title: 'implementing cr fixes',
|
|
650
|
+
...(numbered ? { pr: Number(numbered[1]) } : {}),
|
|
651
|
+
});
|
|
652
|
+
emit({
|
|
653
|
+
type: 'assistant',
|
|
654
|
+
message: {
|
|
655
|
+
role: 'assistant',
|
|
656
|
+
content: [{ type: 'text', text: name }],
|
|
657
|
+
usage: { input_tokens: 200, output_tokens: 30 },
|
|
658
|
+
},
|
|
659
|
+
});
|
|
660
|
+
await sleep(50);
|
|
661
|
+
emit({
|
|
662
|
+
type: 'result',
|
|
663
|
+
subtype: 'success',
|
|
664
|
+
result: name,
|
|
665
|
+
usage: { input_tokens: 200, output_tokens: 30 },
|
|
666
|
+
total_cost_usd: 0.0002,
|
|
667
|
+
});
|
|
668
|
+
return;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
// Spec 008: a planning call (marked `[cez-planner]` in the user prompt)
|
|
672
|
+
// gets a canned chain plan. The `code-review` skill is deliberately made up:
|
|
673
|
+
// the planner's sanitizer strips unknown skills, and the step survives on
|
|
674
|
+
// its prompt — which is exactly the path worth exercising in dry runs.
|
|
675
|
+
async function replyWithPlan(userText, uuid) {
|
|
676
|
+
const plan = JSON.stringify({
|
|
677
|
+
title: 'implement-verify-review',
|
|
678
|
+
steps: [
|
|
679
|
+
{ name: 'Implement', prompt: '{{task}}' },
|
|
680
|
+
{ name: 'Verify', command: 'npm test' },
|
|
681
|
+
{ name: 'Review', skill: 'code-review', prompt: 'Review the changes for {{task}}' },
|
|
682
|
+
],
|
|
683
|
+
rationale: 'Implement, verify with tests, then review.',
|
|
684
|
+
});
|
|
685
|
+
emit({
|
|
686
|
+
type: 'assistant',
|
|
687
|
+
message: {
|
|
688
|
+
role: 'assistant',
|
|
689
|
+
content: [{ type: 'text', text: plan }],
|
|
690
|
+
usage: { input_tokens: 500, output_tokens: 120 },
|
|
691
|
+
},
|
|
692
|
+
});
|
|
693
|
+
await sleep(100);
|
|
694
|
+
emit({
|
|
695
|
+
type: 'result',
|
|
696
|
+
subtype: 'success',
|
|
697
|
+
result: plan,
|
|
698
|
+
usage: { input_tokens: 500, output_tokens: 120 },
|
|
699
|
+
total_cost_usd: 0.0011,
|
|
700
|
+
});
|
|
701
|
+
return;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
// `mock:schedule-wakeup` → Claude's native park tool, without also emitting
|
|
705
|
+
// CEZ:MONITORING. The workflow engine must recognize the completed turn's
|
|
706
|
+
// tool use rather than depending on the textual agent contract marker (#46).
|
|
707
|
+
// `mock:schedule-wakeup:<n>` sends the tool's `delaySeconds` (hearsay-tools/cezarion#1233).
|
|
708
|
+
async function replyWithScheduleWakeup(userText, uuid) {
|
|
709
|
+
const id = `toolu_schedule_wakeup_${turn}`;
|
|
710
|
+
const seconds = /mock:schedule-wakeup:(\d+)/.exec(userText)?.[1];
|
|
711
|
+
emit({
|
|
712
|
+
type: 'assistant',
|
|
713
|
+
message: {
|
|
714
|
+
role: 'assistant',
|
|
715
|
+
content: [{ type: 'tool_use', id, name: 'ScheduleWakeup', input: seconds ? { delaySeconds: Number(seconds) } : { delay: '5m' } }],
|
|
716
|
+
usage: { input_tokens: 40, output_tokens: 20 },
|
|
717
|
+
},
|
|
718
|
+
});
|
|
719
|
+
await sleep(100);
|
|
720
|
+
emit({
|
|
721
|
+
type: 'user',
|
|
722
|
+
message: {
|
|
723
|
+
role: 'user',
|
|
724
|
+
content: [{ type: 'tool_result', tool_use_id: id, content: 'Wakeup scheduled.' }],
|
|
725
|
+
},
|
|
726
|
+
});
|
|
727
|
+
await sleep(100);
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
async function replyWithFirstTurn(userText, { refsMarkers, doneMarker, monitoringMarker, askMarker }) {
|
|
731
|
+
writeNotesTrace(userText);
|
|
732
|
+
writeHandoff();
|
|
733
|
+
emit({
|
|
734
|
+
type: 'assistant',
|
|
735
|
+
message: {
|
|
736
|
+
role: 'assistant',
|
|
737
|
+
content: [{ type: 'text', text: `Okay — looking into: ${userText.slice(0, 120)}` }],
|
|
738
|
+
usage: { input_tokens: 850, output_tokens: 40 },
|
|
739
|
+
},
|
|
740
|
+
});
|
|
741
|
+
await sleep(300);
|
|
742
|
+
emit({
|
|
743
|
+
type: 'assistant',
|
|
744
|
+
message: {
|
|
745
|
+
role: 'assistant',
|
|
746
|
+
content: [{ type: 'tool_use', id: `toolu_mock_${turn}`, name: 'Bash', input: { command: 'git status --short' } }],
|
|
747
|
+
usage: { input_tokens: 120, output_tokens: 55 },
|
|
748
|
+
},
|
|
749
|
+
});
|
|
750
|
+
await sleep(300);
|
|
751
|
+
emit({
|
|
752
|
+
type: 'user',
|
|
753
|
+
message: {
|
|
754
|
+
role: 'user',
|
|
755
|
+
content: [{ type: 'tool_result', tool_use_id: `toolu_mock_${turn}`, content: ' M src/example.ts' }],
|
|
756
|
+
},
|
|
757
|
+
});
|
|
758
|
+
await sleep(200);
|
|
759
|
+
// Agent screenshot in a tool result — exercises the image pipeline
|
|
760
|
+
// (persist to <id>-images/, serve via /api/runs/:id/images/, zoomable
|
|
761
|
+
// card + lightbox in the transcript).
|
|
762
|
+
emit({
|
|
763
|
+
type: 'assistant',
|
|
764
|
+
message: {
|
|
765
|
+
role: 'assistant',
|
|
766
|
+
content: [{ type: 'tool_use', id: `toolu_mock_shot_${turn}`, name: 'Screenshot', input: { name: 'repro-login-redirect.png' } }],
|
|
767
|
+
usage: { input_tokens: 80, output_tokens: 30 },
|
|
768
|
+
},
|
|
769
|
+
});
|
|
770
|
+
await sleep(200);
|
|
771
|
+
emit({
|
|
772
|
+
type: 'user',
|
|
773
|
+
message: {
|
|
774
|
+
role: 'user',
|
|
775
|
+
content: [
|
|
776
|
+
{
|
|
777
|
+
type: 'tool_result',
|
|
778
|
+
tool_use_id: `toolu_mock_shot_${turn}`,
|
|
779
|
+
content: [
|
|
780
|
+
{ type: 'text', text: 'Repro captured: after reload the session toast appears and you are back on /login.' },
|
|
781
|
+
{ type: 'image', source: { type: 'base64', media_type: 'image/png', data: MOCK_SCREENSHOT_B64 } },
|
|
782
|
+
],
|
|
783
|
+
},
|
|
784
|
+
],
|
|
785
|
+
},
|
|
786
|
+
});
|
|
787
|
+
await sleep(300);
|
|
788
|
+
emit({
|
|
789
|
+
type: 'assistant',
|
|
790
|
+
message: {
|
|
791
|
+
role: 'assistant',
|
|
792
|
+
content: [{ type: 'text', text: `Done with the first pass — opened a draft PR: https://github.com/open-mercato/demo/pull/123. Anything to adjust? (dry-run mock)${refsMarkers}${doneMarker}${monitoringMarker}${askMarker}` }],
|
|
793
|
+
usage: { input_tokens: 300, output_tokens: 90 },
|
|
794
|
+
},
|
|
795
|
+
});
|
|
796
|
+
await sleep(150);
|
|
797
|
+
emit({
|
|
798
|
+
type: 'result',
|
|
799
|
+
subtype: 'success',
|
|
800
|
+
result: 'Done with the first pass (dry run).',
|
|
801
|
+
usage: { input_tokens: 1270, output_tokens: 185 },
|
|
802
|
+
total_cost_usd: 0.0342,
|
|
803
|
+
});
|
|
804
|
+
return;
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
async function replyWithFollowup(userText, imageCount, { refsMarkers, doneMarker, monitoringMarker, askMarker }) {
|
|
755
808
|
const imgNote = imageCount > 0 ? ` I can see ${imageCount} image(s) you attached.` : '';
|
|
756
809
|
emit({
|
|
757
810
|
type: 'assistant',
|
|
@@ -771,6 +824,194 @@ async function respond(userText, imageCount, uuid) {
|
|
|
771
824
|
});
|
|
772
825
|
}
|
|
773
826
|
|
|
827
|
+
// Mirrors the real Claude Code 2.1.148 revoked-token envelope: the CLI puts
|
|
828
|
+
// the credential failure in an `is_error` result even though its subtype is
|
|
829
|
+
// `success`, rather than emitting a dedicated error frame.
|
|
830
|
+
async function replyWithAuthenticationFailure(userText, uuid) {
|
|
831
|
+
emit({
|
|
832
|
+
type: 'result',
|
|
833
|
+
subtype: 'success',
|
|
834
|
+
is_error: true,
|
|
835
|
+
result: 'Failed to authenticate. API Error: 401 OAuth access token has been revoked.',
|
|
836
|
+
usage: { input_tokens: 0, output_tokens: 0 },
|
|
837
|
+
total_cost_usd: 0,
|
|
838
|
+
});
|
|
839
|
+
return;
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
// `mock:limit` → the envelope Claude Code emits when the subscription window is
|
|
843
|
+
// exhausted: an `is_error` result whose text is the machine-readable
|
|
844
|
+
// `Claude AI usage limit reached|<epoch seconds>` marker. Makes the auto-resume path
|
|
845
|
+
// (spec 2026-08-03-auto-resume-after-usage-limit) reachable under CEZ_DRY_RUN=1 for QA and
|
|
846
|
+
// the e2e smoke. `CEZ_MOCK_LIMIT_RESET_SECONDS` moves the reset instant (default 60 s out),
|
|
847
|
+
// so a dry run can actually watch the resume fire instead of reading about it.
|
|
848
|
+
async function replyWithUsageLimit(userText, uuid) {
|
|
849
|
+
const configured = Number(process.env.CEZ_MOCK_LIMIT_RESET_SECONDS ?? '60');
|
|
850
|
+
const seconds = Number.isFinite(configured) ? configured : 60;
|
|
851
|
+
emit({
|
|
852
|
+
type: 'result',
|
|
853
|
+
subtype: 'success',
|
|
854
|
+
is_error: true,
|
|
855
|
+
result: `Claude AI usage limit reached|${Math.floor(Date.now() / 1000) + seconds}`,
|
|
856
|
+
usage: { input_tokens: 0, output_tokens: 0 },
|
|
857
|
+
total_cost_usd: 0,
|
|
858
|
+
});
|
|
859
|
+
return;
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
async function replyWithNativeFailure(userText) {
|
|
863
|
+
const selectedFailure = failureControl?.failureFor(userText);
|
|
864
|
+
const nativeFailure = selectedFailure instanceof Promise ? await selectedFailure : selectedFailure;
|
|
865
|
+
if (nativeFailure === 'unread') process.exit(1);
|
|
866
|
+
if (failureControl?.failure === 'provider' ? nativeFailure === 'provider' : userText.includes('mock:auth-error')) { await replyWithAuthenticationFailure(); return true; }
|
|
867
|
+
if (failureControl?.failure === 'usage-limit' ? nativeFailure === 'usage-limit' : userText.includes('mock:limit')) { await replyWithUsageLimit(); return true; }
|
|
868
|
+
return false;
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
function multiAskMarker() {
|
|
872
|
+
return '\n\nCEZ:ASK ' +
|
|
873
|
+
JSON.stringify({
|
|
874
|
+
questions: [
|
|
875
|
+
{
|
|
876
|
+
header: 'Library',
|
|
877
|
+
question: 'Which test library?',
|
|
878
|
+
options: [{ label: 'Vitest' }, { label: 'Node test' }],
|
|
879
|
+
},
|
|
880
|
+
{
|
|
881
|
+
header: 'Build',
|
|
882
|
+
question: 'Which build tool?',
|
|
883
|
+
options: [{ label: 'Vite' }, { label: 'Webpack' }],
|
|
884
|
+
},
|
|
885
|
+
],
|
|
886
|
+
});
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
function invalidJsonAskMarker() { return '\n\nCEZ:ASK {not valid json'; }
|
|
890
|
+
|
|
891
|
+
function invalidSchemaAskMarker() { return '\n\nCEZ:ASK {"questions":[]}'; }
|
|
892
|
+
|
|
893
|
+
function truncatedAskMarker() { return '\n\nCEZ:ASK {"questions":[{"header":"Lint scope","question":"How much of the lint backlog should I land now?","multiSelect":false,"options":[{"label":"First slice only"},{"label":"Rule by rule"},{"label":"Whole backlog"}]}]'; }
|
|
894
|
+
|
|
895
|
+
function nearAskMarker() {
|
|
896
|
+
return '\n\nCEZ:ASK ' +
|
|
897
|
+
JSON.stringify({
|
|
898
|
+
transportHint: 'render as chips',
|
|
899
|
+
questions: [
|
|
900
|
+
{
|
|
901
|
+
header: 'Implementation path',
|
|
902
|
+
question: 'Which implementation should I use?',
|
|
903
|
+
presentation: 'compact',
|
|
904
|
+
options: [
|
|
905
|
+
{ label: 'Minimal', description: 'd'.repeat(300), recommended: true },
|
|
906
|
+
{ label: 'Expanded', description: 'Touch the wider surface' },
|
|
907
|
+
],
|
|
908
|
+
},
|
|
909
|
+
],
|
|
910
|
+
});
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
function ordinaryAskMarker() {
|
|
914
|
+
return '\n\nCEZ:ASK ' +
|
|
915
|
+
JSON.stringify({
|
|
916
|
+
questions: [
|
|
917
|
+
{
|
|
918
|
+
header: 'Library',
|
|
919
|
+
question: 'Which date library should I standardize on?',
|
|
920
|
+
options: [
|
|
921
|
+
{ label: 'date-fns', description: 'Tree-shakeable, functional' },
|
|
922
|
+
{ label: 'Luxon', description: 'Immutable, tz-aware' },
|
|
923
|
+
],
|
|
924
|
+
},
|
|
925
|
+
],
|
|
926
|
+
});
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
const askMarkers = [
|
|
930
|
+
[userText => userText.includes('mock:multi-ask'), multiAskMarker],
|
|
931
|
+
[userText => userText.includes('mock:ask-bad'), invalidJsonAskMarker],
|
|
932
|
+
[userText => userText.includes('mock:ask-invalid'), invalidSchemaAskMarker],
|
|
933
|
+
[userText => userText.includes('mock:ask-truncated'), truncatedAskMarker],
|
|
934
|
+
[userText => userText.includes('mock:ask-near'), nearAskMarker],
|
|
935
|
+
[userText => userText.includes('mock:ask'), ordinaryAskMarker]
|
|
936
|
+
];
|
|
937
|
+
function askMarkerFor(userText) {
|
|
938
|
+
const entry = askMarkers.find(([matches]) => matches(userText));
|
|
939
|
+
return entry ? entry[1]() : '';
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
// `mock:done` anywhere in the message → the reply ends with the CEZ:DONE
|
|
943
|
+
// completion marker (#347), so the auto-close path is testable dry.
|
|
944
|
+
// `mock:monitoring` → the reply ends with CEZ:MONITORING, the "still working
|
|
945
|
+
// on downstream work" marker (#490), so the monitoring-status path is testable dry.
|
|
946
|
+
// `mock:ask` → the reply ends with a valid CEZ:ASK marker (#473), so the
|
|
947
|
+
// AskUser card path (park `waiting` + emit `ask.requested`) is testable dry.
|
|
948
|
+
// `mock:ask-bad` → a MALFORMED marker (invalid JSON), to prove graceful
|
|
949
|
+
// degradation: the run still parks `waiting`, no ask card, prose preserved.
|
|
950
|
+
// `mock:ask-invalid` → syntactically valid JSON that FAILS the ask schema
|
|
951
|
+
// (empty questions) — the shape behind the blank-question bug: no card will
|
|
952
|
+
// ever render it, so the marker must survive in the v1 text.
|
|
953
|
+
// `mock:ask-near` → bounded presentation drift: harmless extra keys plus
|
|
954
|
+
// an overlong header/description. It should normalize into exactly one card.
|
|
955
|
+
// `mock:ask-truncated` → a complete payload one closing brace short (#936):
|
|
956
|
+
// the closer repair should still produce one card, note the recovery, and
|
|
957
|
+
// strip the raw marker (which ends on `]`, not `}`).
|
|
958
|
+
// `mock:multi-ask` → ONE marker with two questions (Library, Build), for the voice-mode E2E
|
|
959
|
+
// (spec 2026-10-21-voice-mode). Checked before every `mock:ask` form so none of them can
|
|
960
|
+
// claim the prompt first.
|
|
961
|
+
// `mock:refs` → the reply carries the in-band task-reference markers
|
|
962
|
+
// (spec 2026-07-18-task-ref-markers), so the declaration path is testable dry.
|
|
963
|
+
function markersFor(userText) {
|
|
964
|
+
const answered = resumeAfterAsk && userText.trim() === 'Library: Vitest';
|
|
965
|
+
resumeAfterAsk = userText.includes('mock:ask') && userText.includes('mock:resume-done');
|
|
966
|
+
const doneMarker = (userText.includes('mock:done') || answered) ? '\n\nCEZ:DONE' : '';
|
|
967
|
+
const monitoringMarker = userText.includes('mock:monitoring') ? '\n\nCEZ:MONITORING' : '';
|
|
968
|
+
const askMarker = askMarkerFor(userText);
|
|
969
|
+
const refsMarkers = userText.includes('mock:refs')
|
|
970
|
+
? '\nCEZ:PR=4242\nCEZ:ISSUE=17\nCEZ:TITLE=implementing marker refs'
|
|
971
|
+
: '';
|
|
972
|
+
return { doneMarker, monitoringMarker, askMarker, refsMarkers };
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
// Ordered matchers preserve scenario priority and the silent-tail fall-through.
|
|
976
|
+
const earlyReplies = [
|
|
977
|
+
[userText => userText.includes('mock:ack-only'), acknowledgeOnly],
|
|
978
|
+
[userText => userText.includes('mock:autonomous') || userText.startsWith('Continue working autonomously until the task is fully complete.'), replyAutonomously],
|
|
979
|
+
[userText => userText.includes('mock:silent-tail') || userText.includes('mock:tool-tail') || silentNudge(userText), replyToSilentTail],
|
|
980
|
+
[userText => userText.includes('mock:steer-tool'), replyToSteering],
|
|
981
|
+
[userText => !userText.includes('[cez-namer]') && userText.includes('mock:hook-after-park'), replyWithParkedHook],
|
|
982
|
+
[userText => !userText.includes('[cez-namer]') && userText.includes('mock:subagent-after-park'), replyWithParkedChild],
|
|
983
|
+
[userText => !userText.includes('[cez-namer]') && userText.includes('mock:forked-skill'), replyWithForkedSkill],
|
|
984
|
+
[userText => userText.includes('mock:multi-pr-refs'), replyWithMultiplePrs],
|
|
985
|
+
[userText => userText.includes('mock:turn-messages:'), replyWithTurnMessages],
|
|
986
|
+
[userText => !userText.includes('[cez-namer]') && userText.includes('mock:ask-snapshot'), replyWithAskSnapshot],
|
|
987
|
+
[userText => !userText.includes('[cez-namer]') && userText.includes('mock:ask-prose'), replyWithAskProse],
|
|
988
|
+
[userText => !userText.includes('[cez-namer]') && userText.includes('mock:cezar-tool'), replyWithCezarTool],
|
|
989
|
+
[userText => userText.includes('mock:ci-wait'), replyWithCiWait],
|
|
990
|
+
[userText => !userText.includes('[cez-namer]') && userText.includes('mock:preview-serve'), replyWithPreview]
|
|
991
|
+
];
|
|
992
|
+
const timedReplies = [
|
|
993
|
+
[userText => userText.includes('mock:split-text'), replyWithSplitText],
|
|
994
|
+
[userText => userText.includes('mock:agent-echo'), replyWithEcho],
|
|
995
|
+
[watchdogStall, acknowledgeStall],
|
|
996
|
+
[userText => userText.includes('mock:busy-progress'), replyWithBusyProgress],
|
|
997
|
+
[userText => userText.includes('mock:hold-done'), replyWithHeldDone],
|
|
998
|
+
[userText => userText.includes('mock:hold-ask'), replyWithHeldAsk],
|
|
999
|
+
[userText => userText.includes('mock:hold-gated'), replyWithGatedHold],
|
|
1000
|
+
[userText => userText.includes('mock:hold'), replyWithHold]
|
|
1001
|
+
];
|
|
1002
|
+
const trailingReplies = [
|
|
1003
|
+
[userText => userText.includes('mock:md'), replyWithMarkdown],
|
|
1004
|
+
[userText => userText.includes('mock:subagents'), replyWithSubagents],
|
|
1005
|
+
[userText => userText.includes('[cez-namer]'), replyWithName],
|
|
1006
|
+
[userText => userText.includes('[cez-planner]'), replyWithPlan]
|
|
1007
|
+
];
|
|
1008
|
+
async function dispatchReply(scenarios, userText, uuid) {
|
|
1009
|
+
for (const [matches, reply] of scenarios) {
|
|
1010
|
+
if (matches(userText) && await reply(userText, uuid) !== false) return true;
|
|
1011
|
+
}
|
|
1012
|
+
return false;
|
|
1013
|
+
}
|
|
1014
|
+
|
|
774
1015
|
const rl = createInterface({ input: process.stdin });
|
|
775
1016
|
let queue = Promise.resolve();
|
|
776
1017
|
rl.on('line', (line) => {
|
|
@@ -814,6 +1055,7 @@ rl.on('line', (line) => {
|
|
|
814
1055
|
// and never runs it). CEZ_MOCK_DROP_ONCE=1 drops only the first match.
|
|
815
1056
|
const drop = process.env.CEZ_MOCK_DROP_LINES;
|
|
816
1057
|
if (drop && userText.includes(drop) && !(process.env.CEZ_MOCK_DROP_ONCE === '1' && droppedOnce)) { droppedOnce = true; return; }
|
|
1058
|
+
userText = answerNudge(withoutSessionContext(userText));
|
|
817
1059
|
if (steering) { steering.push({ userText, uuid }); return; }
|
|
818
1060
|
queue = queue.then(() => respond(userText, imageCount, uuid));
|
|
819
1061
|
});
|