@atolis-hq/wake 0.2.97 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/activities/agent/agent-activity-definition.js +26 -0
- package/dist/src/activities/agent/agent-activity.js +171 -0
- package/dist/src/activities/agent/agent-result.js +149 -0
- package/dist/src/activities/contracts/activity.js +10 -0
- package/dist/src/activities/contracts/config.js +2 -0
- package/dist/src/activities/contracts/event-schema.js +302 -0
- package/dist/src/activities/contracts/events.js +42 -0
- package/dist/src/activities/contracts/identifiers.js +29 -0
- package/dist/src/activities/contracts/registry.js +71 -0
- package/dist/src/activities/contracts/streams.js +17 -0
- package/dist/src/activities/contracts/vocabulary.js +58 -0
- package/dist/src/activities/index.js +21 -0
- package/dist/src/activities/pr/activity-support.js +111 -0
- package/dist/src/activities/pr/application.js +158 -0
- package/dist/src/activities/pr/approve.js +85 -0
- package/dist/src/activities/pr/capability.js +11 -0
- package/dist/src/activities/pr/decision-claim.js +76 -0
- package/dist/src/activities/pr/event-drafts.js +66 -0
- package/dist/src/activities/pr/intent.js +37 -0
- package/dist/src/activities/pr/merge-authority-gate.js +14 -0
- package/dist/src/activities/pr/merge.js +110 -0
- package/dist/src/activities/pr/policy.js +135 -0
- package/dist/src/activities/pr/projection.js +130 -0
- package/dist/src/activities/pr/vocabulary.js +30 -0
- package/dist/src/activities/review/authorization.js +22 -0
- package/dist/src/activities/review/contracts.js +22 -0
- package/dist/src/activities/review/signals.js +3 -0
- package/dist/src/bootstrap/analytics-projection.js +26 -0
- package/dist/src/bootstrap/board-projection.js +337 -0
- package/dist/src/bootstrap/composition-root.js +382 -0
- package/dist/src/bootstrap/config/load-config.js +51 -0
- package/dist/src/bootstrap/config/root-schema.js +134 -0
- package/dist/src/bootstrap/external-ref.js +12 -0
- package/dist/src/bootstrap/fake-provider-files.js +44 -0
- package/dist/src/bootstrap/fake-scenarios.js +22 -0
- package/dist/src/bootstrap/index.js +48 -0
- package/dist/src/bootstrap/initialise.js +434 -0
- package/dist/src/bootstrap/paths.js +15 -0
- package/dist/src/bootstrap/projection-runtime.js +27 -0
- package/dist/src/bootstrap/runner-quota-reporter.js +21 -0
- package/dist/src/bootstrap/runner-registry.js +30 -0
- package/dist/src/bootstrap/schedule-checkpoint-store.js +49 -0
- package/dist/src/bootstrap/self-update-application.js +195 -0
- package/dist/src/bootstrap/self-update-failure-log.js +33 -0
- package/dist/src/bootstrap/source-update-port.js +47 -0
- package/dist/src/bootstrap/status-publish-activity.js +42 -0
- package/dist/src/bootstrap/surface-api-applications.js +325 -0
- package/dist/src/bootstrap/surface-api-execution-applications.js +95 -0
- package/dist/src/bootstrap/surface-api-metadata.js +12 -0
- package/dist/src/bootstrap/surface-api-projection-pages.js +22 -0
- package/dist/src/bootstrap/surface-api-run-context.js +5 -0
- package/dist/src/bootstrap/surface-api-transcripts.js +57 -0
- package/dist/src/bootstrap/surface-api-work-applications.js +199 -0
- package/dist/src/bootstrap/surface-applications.js +7 -0
- package/dist/src/bootstrap/surface-cli-applications.js +701 -0
- package/dist/src/bootstrap/update-ledger.js +61 -0
- package/dist/src/bootstrap/update-maintenance-lease.js +176 -0
- package/dist/src/{version.js → bootstrap/version.js} +35 -51
- package/dist/src/control-plane/application/advance-once.js +184 -0
- package/dist/src/control-plane/application/control-plane-projection.js +42 -0
- package/dist/src/control-plane/application/control-plane-service.js +42 -0
- package/dist/src/control-plane/application/intake-pipeline.js +29 -0
- package/dist/src/control-plane/application/runner-control-service.js +66 -0
- package/dist/src/control-plane/application/runner-pipeline.js +57 -0
- package/dist/src/control-plane/application/schedule-service.js +47 -0
- package/dist/src/control-plane/application/work-cancellation-policy.js +31 -0
- package/dist/src/control-plane/contracts/commands.js +10 -0
- package/dist/src/control-plane/contracts/config.js +22 -0
- package/dist/src/control-plane/contracts/events.js +81 -0
- package/dist/src/control-plane/contracts/streams.js +5 -0
- package/dist/src/control-plane/domain/dispatch-policy.js +15 -0
- package/dist/src/control-plane/domain/quota-policy.js +26 -0
- package/dist/src/control-plane/domain/runner-quota.js +35 -0
- package/dist/src/control-plane/domain/schedule-policy.js +46 -0
- package/dist/src/control-plane/index.js +20 -0
- package/dist/src/control-plane/infrastructure/intake-host.js +24 -0
- package/dist/src/control-plane/infrastructure/resident-host.js +45 -0
- package/dist/src/control-plane/infrastructure/tick-host.js +35 -0
- package/dist/src/execution/application/activation-claim.js +50 -0
- package/dist/src/execution/application/active-run-cancellation.js +14 -0
- package/dist/src/execution/application/execution-activity.js +97 -0
- package/dist/src/execution/application/execution-projection.js +17 -0
- package/dist/src/execution/application/execution-service.js +372 -0
- package/dist/src/execution/application/execution-validation.js +26 -0
- package/dist/src/execution/application/recovery-service.js +212 -0
- package/dist/src/execution/application/run-lifecycle.js +115 -0
- package/dist/src/execution/application/run-liveness-service.js +80 -0
- package/dist/src/execution/application/run-repository.js +27 -0
- package/dist/src/execution/contracts/commands.js +1 -0
- package/dist/src/execution/contracts/config.js +35 -0
- package/dist/src/execution/contracts/control-plane.js +1 -0
- package/dist/src/execution/contracts/event-factory.js +53 -0
- package/dist/src/execution/contracts/events.js +274 -0
- package/dist/src/execution/contracts/identifiers.js +5 -0
- package/dist/src/execution/contracts/liveness.js +1 -0
- package/dist/src/execution/contracts/results.js +1 -0
- package/dist/src/execution/contracts/runner.js +15 -0
- package/dist/src/execution/contracts/streams.js +10 -0
- package/dist/src/execution/contracts/views.js +1 -0
- package/dist/src/execution/contracts/vocabulary.js +43 -0
- package/dist/src/execution/contracts/workspace.js +1 -0
- package/dist/src/execution/domain/run-result.js +34 -0
- package/dist/src/execution/domain/run.js +142 -0
- package/dist/src/execution/index.js +31 -0
- package/dist/src/execution/infrastructure/agent-runner-adapter.js +114 -0
- package/dist/src/execution/infrastructure/process-execution.js +29 -0
- package/dist/src/execution/infrastructure/prompt-templates.js +42 -0
- package/dist/src/execution/infrastructure/runners/claude.js +120 -0
- package/dist/src/execution/infrastructure/runners/codex.js +143 -0
- package/dist/src/execution/infrastructure/runners/command.js +4 -0
- package/dist/src/execution/infrastructure/runners/cursor.js +69 -0
- package/dist/src/execution/infrastructure/runners/fake-scenarios.js +99 -0
- package/dist/src/execution/infrastructure/runners/fake.js +65 -0
- package/dist/src/execution/infrastructure/runners/registry.js +26 -0
- package/dist/src/execution/infrastructure/transcript-store.js +223 -0
- package/dist/src/execution/infrastructure/transcripts.js +11 -0
- package/dist/src/execution/infrastructure/workspace/fake-workspace.js +19 -0
- package/dist/src/execution/infrastructure/workspace/git-workspace.js +241 -0
- package/dist/src/integrations/application/agent-run-publication-reactor.js +111 -0
- package/dist/src/integrations/application/artifact-registration-reactor.js +159 -0
- package/dist/src/integrations/application/poll-service.js +25 -0
- package/dist/src/integrations/application/terminal-agent-run-report.js +40 -0
- package/dist/src/integrations/application/work-admission.js +31 -0
- package/dist/src/integrations/application/work-conclusion.js +19 -0
- package/dist/src/integrations/contracts/artifact-events.js +60 -0
- package/dist/src/integrations/contracts/artifact-vocabulary.js +9 -0
- package/dist/src/integrations/contracts/config.js +14 -0
- package/dist/src/integrations/contracts/identifiers.js +5 -0
- package/dist/src/integrations/contracts/intake-rules.js +14 -0
- package/dist/src/integrations/contracts/intake.js +1 -0
- package/dist/src/integrations/contracts/outcome-vocabulary.js +7 -0
- package/dist/src/integrations/contracts/provider.js +37 -0
- package/dist/src/integrations/contracts/streams.js +10 -0
- package/dist/src/integrations/delivery/application/delivery-outcome-reactor.js +75 -0
- package/dist/src/integrations/delivery/application/delivery-projector.js +165 -0
- package/dist/src/integrations/delivery/application/delivery-service.js +173 -0
- package/dist/src/integrations/delivery/contracts/commands.js +1 -0
- package/dist/src/integrations/delivery/contracts/config.js +1 -0
- package/dist/src/integrations/delivery/contracts/event-factory.js +18 -0
- package/dist/src/integrations/delivery/contracts/events.js +86 -0
- package/dist/src/integrations/delivery/contracts/intents.js +89 -0
- package/dist/src/integrations/delivery/contracts/views.js +1 -0
- package/dist/src/integrations/delivery/contracts/vocabulary.js +22 -0
- package/dist/src/integrations/fake/durable-delivery-provider.js +48 -0
- package/dist/src/integrations/fake/external-sink.js +9 -0
- package/dist/src/integrations/fake/external-source.js +44 -0
- package/dist/src/integrations/fake/inbound-translator.js +130 -0
- package/dist/src/integrations/fake/provider.js +95 -0
- package/dist/src/integrations/github/application/agent-context-reader.js +54 -0
- package/dist/src/integrations/github/application/agent-run-comment.js +94 -0
- package/dist/src/integrations/github/application/comment-history-reader.js +43 -0
- package/dist/src/integrations/github/application/inbound-context.js +10 -0
- package/dist/src/integrations/github/application/inbound-review-signals.js +159 -0
- package/dist/src/integrations/github/application/inbound-translator.js +231 -0
- package/dist/src/integrations/github/application/inbound-watch-gate-signals.js +84 -0
- package/dist/src/integrations/github/application/intake-policy.js +23 -0
- package/dist/src/integrations/github/application/outbound-translator.js +47 -0
- package/dist/src/integrations/github/application/poll-service.js +29 -0
- package/dist/src/integrations/github/application/pull-request-translation.js +10 -0
- package/dist/src/integrations/github/application/resource-links.js +8 -0
- package/dist/src/integrations/github/application/review-command-translator.js +16 -0
- package/dist/src/integrations/github/application/wake-labels.js +95 -0
- package/dist/src/integrations/github/contracts/config.js +47 -0
- package/dist/src/integrations/github/contracts/events.js +127 -0
- package/dist/src/integrations/github/contracts/external-key.js +19 -0
- package/dist/src/integrations/github/contracts/payloads.js +9 -0
- package/dist/src/integrations/github/contracts/vocabulary.js +55 -0
- package/dist/src/integrations/github/index.js +31 -0
- package/dist/src/integrations/github/infrastructure/client-reads.js +214 -0
- package/dist/src/integrations/github/infrastructure/client.js +132 -0
- package/dist/src/integrations/github/infrastructure/content-fingerprint.js +10 -0
- package/dist/src/integrations/github/infrastructure/delivery.js +31 -0
- package/dist/src/integrations/github/infrastructure/etag-cache.js +56 -0
- package/dist/src/integrations/github/infrastructure/gh-auth.js +19 -0
- package/dist/src/integrations/github/infrastructure/issue-source.js +109 -0
- package/dist/src/integrations/github/infrastructure/pr-source.js +186 -0
- package/dist/src/integrations/github/infrastructure/review-source.js +70 -0
- package/dist/src/integrations/github/infrastructure/source.js +108 -0
- package/dist/src/integrations/github/provider.js +96 -0
- package/dist/src/integrations/index.js +30 -0
- package/dist/src/kernel/contracts/checkpoint-store.js +1 -0
- package/dist/src/kernel/contracts/clock.js +1 -0
- package/dist/src/kernel/contracts/commands.js +1 -0
- package/dist/src/kernel/contracts/event-journal.js +2 -0
- package/dist/src/kernel/contracts/event-schema.js +54 -0
- package/dist/src/kernel/contracts/events.js +11 -0
- package/dist/src/kernel/contracts/id-generator.js +1 -0
- package/dist/src/kernel/contracts/identifiers.js +8 -0
- package/dist/src/kernel/contracts/projection-store.js +1 -0
- package/dist/src/kernel/contracts/relations.js +1 -0
- package/dist/src/kernel/contracts/schema.js +17 -0
- package/dist/src/kernel/contracts/vocabulary.js +6 -0
- package/dist/src/kernel/domain/event-envelope.js +29 -0
- package/dist/src/kernel/domain/match-mode.js +11 -0
- package/dist/src/kernel/domain/relation.js +10 -0
- package/dist/src/kernel/index.js +17 -0
- package/dist/src/{lib/clock.js → kernel/infrastructure/system-clock.js} +3 -3
- package/dist/src/kernel/infrastructure/ulid-id-generator.js +9 -0
- package/dist/src/main.js +137 -1030
- package/dist/src/orchestration/application/accept-activity-outcome.js +25 -0
- package/dist/src/orchestration/application/accept-signal.js +35 -0
- package/dist/src/orchestration/application/advance-workflow.js +160 -0
- package/dist/src/orchestration/application/coordination-claims.js +107 -0
- package/dist/src/orchestration/application/group-budget-recorder.js +43 -0
- package/dist/src/orchestration/application/orchestration-projection.js +20 -0
- package/dist/src/orchestration/application/orchestration-repository.js +36 -0
- package/dist/src/orchestration/application/orchestration-service.js +82 -0
- package/dist/src/orchestration/application/request-child.js +118 -0
- package/dist/src/orchestration/application/signal-reactor.js +17 -0
- package/dist/src/orchestration/application/start-workflow.js +51 -0
- package/dist/src/orchestration/application/watch-reactor.js +82 -0
- package/dist/src/orchestration/contracts/activity-outcome.js +18 -0
- package/dist/src/orchestration/contracts/commands.js +1 -0
- package/dist/src/orchestration/contracts/config.js +128 -0
- package/dist/src/orchestration/contracts/event-decoder.js +263 -0
- package/dist/src/orchestration/contracts/events.js +41 -0
- package/dist/src/orchestration/contracts/identifiers.js +35 -0
- package/dist/src/orchestration/contracts/streams.js +38 -0
- package/dist/src/orchestration/contracts/views.js +1 -0
- package/dist/src/orchestration/contracts/vocabulary.js +30 -0
- package/dist/src/orchestration/domain/activation-policy.js +55 -0
- package/dist/src/orchestration/domain/approval-defaults.js +17 -0
- package/dist/src/orchestration/domain/child-policy.js +63 -0
- package/dist/src/orchestration/domain/compiler.js +162 -0
- package/dist/src/orchestration/domain/coordination-events.js +25 -0
- package/dist/src/orchestration/domain/decision-events.js +47 -0
- package/dist/src/orchestration/domain/interpreter.js +49 -0
- package/dist/src/orchestration/domain/operator-retry-policy.js +34 -0
- package/dist/src/orchestration/domain/retry-policy.js +26 -0
- package/dist/src/orchestration/domain/signal-policy.js +120 -0
- package/dist/src/orchestration/domain/supplemental-policy.js +61 -0
- package/dist/src/orchestration/domain/transition.js +55 -0
- package/dist/src/orchestration/domain/workflow-graph.js +41 -0
- package/dist/src/orchestration/domain/workflow-instance-events.js +236 -0
- package/dist/src/orchestration/domain/workflow-instance.js +41 -0
- package/dist/src/orchestration/domain/workflow-selector.js +21 -0
- package/dist/src/orchestration/index.js +19 -0
- package/dist/src/persistence/application/projection-runner.js +79 -0
- package/dist/src/persistence/filesystem/file-checkpoint-store.js +35 -0
- package/dist/src/persistence/filesystem/file-event-journal.js +143 -0
- package/dist/src/persistence/filesystem/file-lock.js +91 -0
- package/dist/src/persistence/filesystem/file-projection-store.js +64 -0
- package/dist/src/persistence/index.js +8 -0
- package/dist/src/persistence/memory/in-memory-checkpoint-store.js +14 -0
- package/dist/src/persistence/memory/in-memory-event-journal.js +88 -0
- package/dist/src/persistence/memory/in-memory-projection-store.js +17 -0
- package/dist/src/resources/application/lookup-projections.js +48 -0
- package/dist/src/resources/application/resource-lookup.js +16 -0
- package/dist/src/resources/application/resource-projections.js +81 -0
- package/dist/src/resources/application/resource-repository.js +18 -0
- package/dist/src/resources/application/resource-service.js +83 -0
- package/dist/src/resources/contracts/commands.js +1 -0
- package/dist/src/resources/contracts/config.js +2 -0
- package/dist/src/resources/contracts/events.js +83 -0
- package/dist/src/resources/contracts/identifiers.js +15 -0
- package/dist/src/resources/contracts/streams.js +6 -0
- package/dist/src/resources/contracts/views.js +1 -0
- package/dist/src/resources/contracts/vocabulary.js +67 -0
- package/dist/src/resources/domain/correlation.js +8 -0
- package/dist/src/resources/domain/resource.js +58 -0
- package/dist/src/resources/index.js +14 -0
- package/dist/src/surfaces/api/contracts/activities.js +1 -0
- package/dist/src/surfaces/api/contracts/board.js +2 -0
- package/dist/src/surfaces/api/contracts/common.js +46 -0
- package/dist/src/surfaces/api/contracts/control-plane.js +5 -0
- package/dist/src/surfaces/api/contracts/events.js +1 -0
- package/dist/src/surfaces/api/contracts/execution.js +1 -0
- package/dist/src/surfaces/api/contracts/index.js +13 -0
- package/dist/src/surfaces/api/contracts/observability.js +1 -0
- package/dist/src/surfaces/api/contracts/orchestration.js +1 -0
- package/dist/src/surfaces/api/contracts/resources.js +1 -0
- package/dist/src/surfaces/api/contracts/status.js +1 -0
- package/dist/src/surfaces/api/contracts/system.js +1 -0
- package/dist/src/surfaces/api/contracts/transport-values.js +39 -0
- package/dist/src/surfaces/api/contracts/work.js +17 -0
- package/dist/src/surfaces/api/http-server.js +121 -0
- package/dist/src/surfaces/api/presenters/activities.js +1 -0
- package/dist/src/surfaces/api/presenters/board.js +3 -0
- package/dist/src/surfaces/api/presenters/control-plane.js +1 -0
- package/dist/src/surfaces/api/presenters/events.js +1 -0
- package/dist/src/surfaces/api/presenters/execution.js +59 -0
- package/dist/src/surfaces/api/presenters/observability.js +1 -0
- package/dist/src/surfaces/api/presenters/orchestration.js +19 -0
- package/dist/src/surfaces/api/presenters/resources.js +15 -0
- package/dist/src/surfaces/api/presenters/status.js +3 -0
- package/dist/src/surfaces/api/presenters/system.js +14 -0
- package/dist/src/surfaces/api/presenters/work.js +16 -0
- package/dist/src/surfaces/api/problem-details.js +9 -0
- package/dist/src/surfaces/api/router.js +13 -0
- package/dist/src/surfaces/api/routes/activities.js +1 -0
- package/dist/src/surfaces/api/routes/applications.js +1 -0
- package/dist/src/surfaces/api/routes/commands.js +82 -0
- package/dist/src/surfaces/api/routes/control-plane.js +6 -0
- package/dist/src/surfaces/api/routes/events.js +1 -0
- package/dist/src/surfaces/api/routes/execution.js +8 -0
- package/dist/src/surfaces/api/routes/index.js +18 -0
- package/dist/src/surfaces/api/routes/observability.js +1 -0
- package/dist/src/surfaces/api/routes/orchestration.js +1 -0
- package/dist/src/surfaces/api/routes/pagination.js +78 -0
- package/dist/src/surfaces/api/routes/read.js +135 -0
- package/dist/src/surfaces/api/routes/resources.js +1 -0
- package/dist/src/surfaces/api/routes/responses.js +67 -0
- package/dist/src/surfaces/api/routes/system.js +1 -0
- package/dist/src/surfaces/api/routes/work.js +9 -0
- package/dist/src/surfaces/cli/commands/api.js +1 -0
- package/dist/src/surfaces/cli/commands/audit.js +10 -0
- package/dist/src/surfaces/cli/commands/correlate.js +2 -0
- package/dist/src/surfaces/cli/commands/doctor.js +6 -0
- package/dist/src/surfaces/cli/commands/init.js +39 -0
- package/dist/src/surfaces/cli/commands/sandbox-entrypoint.js +33 -0
- package/dist/src/surfaces/cli/commands/sandbox-setup.js +29 -0
- package/dist/src/surfaces/cli/commands/sandbox.js +105 -0
- package/dist/src/surfaces/cli/commands/self-update.js +38 -0
- package/dist/src/surfaces/cli/commands/smoke.js +16 -0
- package/dist/src/surfaces/cli/commands/start.js +1 -0
- package/dist/src/surfaces/cli/commands/stop.js +13 -0
- package/dist/src/surfaces/cli/commands/tick.js +1 -0
- package/dist/src/surfaces/cli/commands/ui.js +2 -0
- package/dist/src/surfaces/cli/commands/validate-state.js +5 -0
- package/dist/src/surfaces/cli/infrastructure/docker-cli.js +221 -0
- package/dist/src/surfaces/cli/infrastructure/process-log.js +86 -0
- package/dist/src/surfaces/cli/main.js +140 -0
- package/dist/src/surfaces/cli/usage.js +33 -0
- package/dist/src/surfaces/contracts/config.js +34 -0
- package/dist/src/surfaces/index.js +47 -0
- package/dist/src/surfaces/web-assets/assets/index-Bfn4FwZG.css +1 -0
- package/dist/src/surfaces/web-assets/assets/index-ipB6JPGU.js +1090 -0
- package/dist/src/surfaces/web-assets/index.html +13 -0
- package/dist/src/surfaces/web-host/asset-source.js +1 -0
- package/dist/src/surfaces/web-host/packaged-assets.js +44 -0
- package/dist/src/work/application/work-projection.js +59 -0
- package/dist/src/work/application/work-repository.js +18 -0
- package/dist/src/work/application/work-service.js +117 -0
- package/dist/src/work/contracts/commands.js +1 -0
- package/dist/src/work/contracts/config.js +2 -0
- package/dist/src/work/contracts/events.js +103 -0
- package/dist/src/work/contracts/identifiers.js +5 -0
- package/dist/src/work/contracts/streams.js +6 -0
- package/dist/src/work/contracts/views.js +1 -0
- package/dist/src/work/contracts/vocabulary.js +6 -0
- package/dist/src/work/domain/work-item.js +89 -0
- package/dist/src/work/index.js +11 -0
- package/docker/Dockerfile +10 -6
- package/docker/Dockerfile.packaged +3 -3
- package/package.json +29 -4
- package/prompts/implement.md +2 -2
- package/templates/SETUP.md +7 -7
- package/dist/src/adapters/claude/claude-runner.js +0 -529
- package/dist/src/adapters/codex/codex-runner.js +0 -503
- package/dist/src/adapters/cursor/cursor-runner.js +0 -418
- package/dist/src/adapters/docker/docker-cli.js +0 -150
- package/dist/src/adapters/fake/fake-artifact-verifier.js +0 -14
- package/dist/src/adapters/fake/fake-github-pull-request-activity-source.js +0 -77
- package/dist/src/adapters/fake/fake-resource-index.js +0 -21
- package/dist/src/adapters/fake/fake-runner.js +0 -77
- package/dist/src/adapters/fake/fake-ticketing-system.js +0 -185
- package/dist/src/adapters/fake/fake-workspace-manager.js +0 -81
- package/dist/src/adapters/fs/resource-index.js +0 -126
- package/dist/src/adapters/fs/self-update-ledger.js +0 -17
- package/dist/src/adapters/fs/state-store.js +0 -775
- package/dist/src/adapters/git/git-workspace-manager.js +0 -289
- package/dist/src/adapters/github/github-artifact-verifier.js +0 -38
- package/dist/src/adapters/github/github-auth.js +0 -16
- package/dist/src/adapters/github/github-client.js +0 -249
- package/dist/src/adapters/github/github-etag-cache.js +0 -57
- package/dist/src/adapters/github/github-issues-work-source.js +0 -692
- package/dist/src/adapters/github/github-pull-request-activity-source.js +0 -584
- package/dist/src/adapters/github/github-pull-request-merge-actor.js +0 -45
- package/dist/src/adapters/http/ui-assets.js +0 -1188
- package/dist/src/adapters/http/ui-data.js +0 -1107
- package/dist/src/adapters/http/ui-server.js +0 -458
- package/dist/src/adapters/runner/cli-command.js +0 -73
- package/dist/src/adapters/runner/prompt-templates.js +0 -76
- package/dist/src/adapters/runner/runner-cli-adapter.js +0 -112
- package/dist/src/adapters/runner/runner-registry.js +0 -139
- package/dist/src/adapters/runner/runtime-events.js +0 -32
- package/dist/src/adapters/runner/stage-prompt.js +0 -268
- package/dist/src/adapters/runner/transcripts.js +0 -25
- package/dist/src/cli/audit-command.js +0 -36
- package/dist/src/cli/correlate-command.js +0 -62
- package/dist/src/cli/doctor-command.js +0 -48
- package/dist/src/cli/init-command.js +0 -18
- package/dist/src/cli/sandbox-command.js +0 -258
- package/dist/src/cli/sandbox-entrypoint-command.js +0 -88
- package/dist/src/cli/sandbox-exec-logging.js +0 -7
- package/dist/src/cli/sandbox-resume.js +0 -79
- package/dist/src/cli/sandbox-setup-command.js +0 -31
- package/dist/src/cli/scaffold-assets.js +0 -100
- package/dist/src/cli/self-update-command.js +0 -198
- package/dist/src/cli/startup-preflight.js +0 -134
- package/dist/src/cli/stop-command.js +0 -46
- package/dist/src/cli/ui-command.js +0 -27
- package/dist/src/config/defaults.js +0 -10
- package/dist/src/config/discover-config-files.js +0 -11
- package/dist/src/config/load-config.js +0 -69
- package/dist/src/config/split-config.js +0 -14
- package/dist/src/core/active-run-recovery.js +0 -44
- package/dist/src/core/approval-intents.js +0 -16
- package/dist/src/core/audit-events.js +0 -82
- package/dist/src/core/control-plane.js +0 -192
- package/dist/src/core/event-builders.js +0 -153
- package/dist/src/core/event-resolver.js +0 -249
- package/dist/src/core/lifecycle-service.js +0 -8
- package/dist/src/core/live-execution.js +0 -81
- package/dist/src/core/outbox.js +0 -198
- package/dist/src/core/policy-engine.js +0 -389
- package/dist/src/core/projection-updater.js +0 -693
- package/dist/src/core/quota-backoff.js +0 -69
- package/dist/src/core/run-lease.js +0 -38
- package/dist/src/core/scheduled-workflow-source.js +0 -199
- package/dist/src/core/sink-router.js +0 -107
- package/dist/src/core/stale-run-reconciler.js +0 -352
- package/dist/src/core/tick-runner.js +0 -2442
- package/dist/src/core/workspace-cleanup.js +0 -117
- package/dist/src/domain/branch-naming.js +0 -14
- package/dist/src/domain/custom-commands.js +0 -58
- package/dist/src/domain/event-types.js +0 -158
- package/dist/src/domain/manual-labels.js +0 -1
- package/dist/src/domain/resource-uri.js +0 -38
- package/dist/src/domain/runner-routing.js +0 -127
- package/dist/src/domain/runtime-events.js +0 -36
- package/dist/src/domain/schema.js +0 -1233
- package/dist/src/domain/sources.js +0 -16
- package/dist/src/domain/stages.js +0 -36
- package/dist/src/domain/work-item-labels.js +0 -48
- package/dist/src/domain/work-item-lifecycle.js +0 -10
- package/dist/src/domain/work-item-status.js +0 -33
- package/dist/src/domain/workflows.js +0 -159
- package/dist/src/lib/deep-merge.js +0 -14
- package/dist/src/lib/detached-process-logging.js +0 -46
- package/dist/src/lib/event-log.js +0 -21
- package/dist/src/lib/format.js +0 -41
- package/dist/src/lib/json-file.js +0 -23
- package/dist/src/lib/lock.js +0 -181
- package/dist/src/lib/log-rotation.js +0 -42
- package/dist/src/lib/paths.js +0 -52
- package/dist/src/lib/process-identity.js +0 -54
- package/dist/src/lib/state-health.js +0 -30
- package/dist/src/lib/work-id.js +0 -19
- package/dist/src/lib/yaml-file.js +0 -20
- /package/dist/src/{core → activities/pr}/contracts.js +0 -0
- /package/dist/src/{domain/types.js → control-plane/contracts/views.js} +0 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { mkdir, readdir, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
|
+
const runtimeDirectories = [
|
|
4
|
+
'events',
|
|
5
|
+
'projections',
|
|
6
|
+
'checkpoints',
|
|
7
|
+
'locks',
|
|
8
|
+
'transcripts',
|
|
9
|
+
'logs',
|
|
10
|
+
'container-home',
|
|
11
|
+
];
|
|
12
|
+
/** Creates a new Wake home; runtime state always stays under its hidden .wake directory. */
|
|
13
|
+
export async function initialiseWakeHome(wakeRoot, assets) {
|
|
14
|
+
await assertEmptyDirectory(wakeRoot);
|
|
15
|
+
const dataRoot = join(wakeRoot, '.wake');
|
|
16
|
+
await Promise.all([
|
|
17
|
+
...runtimeDirectories.map((directory) => mkdir(join(dataRoot, directory), { recursive: true })),
|
|
18
|
+
mkdir(join(wakeRoot, 'workspaces'), { recursive: true }),
|
|
19
|
+
]);
|
|
20
|
+
await Promise.all(Object.entries(assets).map(async ([path, content]) => {
|
|
21
|
+
const target = join(wakeRoot, path);
|
|
22
|
+
await mkdir(dirname(target), { recursive: true });
|
|
23
|
+
await writeFile(target, content, 'utf8');
|
|
24
|
+
}));
|
|
25
|
+
}
|
|
26
|
+
async function assertEmptyDirectory(path) {
|
|
27
|
+
try {
|
|
28
|
+
if ((await readdir(path)).length > 0)
|
|
29
|
+
throw new Error(`Wake root is not empty: ${path}`);
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
if (isMissingDirectory(error))
|
|
33
|
+
return;
|
|
34
|
+
throw error;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function isMissingDirectory(error) {
|
|
38
|
+
return error instanceof Error && 'code' in error && error.code === 'ENOENT';
|
|
39
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Restarts `wake start` on every exit — a first-boot crash (e.g. missing
|
|
3
|
+
* sandbox auth) must not stop the retry loop, since the operator's only path
|
|
4
|
+
* to fixing it (`wake sandbox setup`) also depends on this loop's container
|
|
5
|
+
* staying alive.
|
|
6
|
+
*/
|
|
7
|
+
export async function runResidentSupervisor(deps) {
|
|
8
|
+
const [command, ...prefix] = deps.wakeInvocation;
|
|
9
|
+
if (command === undefined)
|
|
10
|
+
throw new Error('sandbox entrypoint requires a wake invocation');
|
|
11
|
+
for (;;) {
|
|
12
|
+
deps.log('wake start: starting resident loop');
|
|
13
|
+
const { pid } = deps.spawnDetached(command, [...prefix, 'start', '--wake-root', '/wake', '--no-sandbox'], { logFile: deps.startLogFile });
|
|
14
|
+
await deps.writeFile(deps.pidFile, String(pid));
|
|
15
|
+
const exitCode = await deps.waitForExit(pid);
|
|
16
|
+
deps.log(`wake start: resident loop exited with status ${exitCode}; restarting in ${deps.restartDelaySeconds}s`);
|
|
17
|
+
await deps.sleep(deps.restartDelaySeconds * 1000);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Keeps the sandbox container alive regardless of whether `wake start` can
|
|
22
|
+
* currently run — `sandbox setup`/`sandbox exec` need a live container to
|
|
23
|
+
* reach into, including on first boot before auth is configured.
|
|
24
|
+
*/
|
|
25
|
+
export async function runSandboxEntrypoint(deps) {
|
|
26
|
+
await deps.ensureLogDirectory();
|
|
27
|
+
if (deps.startEnabled) {
|
|
28
|
+
void runResidentSupervisor(deps).catch((error) => {
|
|
29
|
+
deps.log(`wake start: supervisor stopped unexpectedly: ${error instanceof Error ? error.message : String(error)}`);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
await deps.waitForever();
|
|
33
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// The Cursor CLI's own first subcommand, not the ActivityExecutionKind/EventActorKind
|
|
2
|
+
// vocabulary word "agent" — spelled indirectly so it isn't misread as that domain term.
|
|
3
|
+
const cursorCliSubcommand = String.fromCharCode(97, 103, 101, 110, 116);
|
|
4
|
+
/** Configures the sandbox-owned credentials and git identity interactively. */
|
|
5
|
+
export async function runSandboxSetup(deps) {
|
|
6
|
+
deps.log('Wake sandbox setup starting.');
|
|
7
|
+
await deps.prepareCodexHome();
|
|
8
|
+
await deps.ensureSshKey();
|
|
9
|
+
if (await deps.prompt('Configure GitHub auth? [y/N]')) {
|
|
10
|
+
deps.log('Use a dedicated GitHub identity with only the repository access Wake needs when possible.');
|
|
11
|
+
await deps.runInteractive('gh', ['auth', 'login']);
|
|
12
|
+
await deps.runInteractive('gh', ['auth', 'setup-git']);
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
deps.log('Skipping GitHub auth setup.');
|
|
16
|
+
}
|
|
17
|
+
if (await deps.prompt('Configure Claude auth? [y/N]'))
|
|
18
|
+
await deps.runInteractive('claude', ['auth', 'login', '--claudeai']);
|
|
19
|
+
else
|
|
20
|
+
deps.log('Skipping Claude auth setup.');
|
|
21
|
+
if (await deps.prompt('Configure Codex auth? [y/N]'))
|
|
22
|
+
await deps.runInteractive('codex', ['login', '--device-auth']);
|
|
23
|
+
else
|
|
24
|
+
deps.log('Skipping Codex auth setup.');
|
|
25
|
+
if (await deps.prompt('Configure Cursor auth? [y/N]'))
|
|
26
|
+
await deps.runInteractive(cursorCliSubcommand, ['login']);
|
|
27
|
+
else
|
|
28
|
+
deps.log('Skipping Cursor auth setup.');
|
|
29
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
export const sandboxUsage = [
|
|
2
|
+
'Sandbox usage:',
|
|
3
|
+
' wake sandbox build',
|
|
4
|
+
' wake sandbox up | down | update',
|
|
5
|
+
' wake sandbox exec [-- <command...>]',
|
|
6
|
+
' wake sandbox logs [--tail <positive integer>]',
|
|
7
|
+
' wake sandbox setup',
|
|
8
|
+
' wake sandbox resume <sessionId> --cwd <path> --cli <claude|codex|cursor>',
|
|
9
|
+
].join('\n');
|
|
10
|
+
export async function runSandbox(arguments_, docker) {
|
|
11
|
+
const [command, ...rest] = arguments_;
|
|
12
|
+
switch (command) {
|
|
13
|
+
case 'build':
|
|
14
|
+
await docker.build();
|
|
15
|
+
return;
|
|
16
|
+
case 'up':
|
|
17
|
+
await docker.up();
|
|
18
|
+
return;
|
|
19
|
+
case 'down':
|
|
20
|
+
await docker.down();
|
|
21
|
+
return;
|
|
22
|
+
case 'update':
|
|
23
|
+
await runUpdate(docker);
|
|
24
|
+
return;
|
|
25
|
+
case 'exec':
|
|
26
|
+
await runExec(docker, rest);
|
|
27
|
+
return;
|
|
28
|
+
case 'logs':
|
|
29
|
+
await runLogs(docker, rest);
|
|
30
|
+
return;
|
|
31
|
+
case 'setup':
|
|
32
|
+
await runSetup(docker);
|
|
33
|
+
return;
|
|
34
|
+
case 'resume':
|
|
35
|
+
await runResume(docker, rest);
|
|
36
|
+
return;
|
|
37
|
+
default:
|
|
38
|
+
throw new Error(`Unknown sandbox command: ${command ?? ''}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async function runUpdate(docker) {
|
|
42
|
+
if (docker.update === undefined)
|
|
43
|
+
throw new Error('sandbox update is not configured');
|
|
44
|
+
await docker.update();
|
|
45
|
+
}
|
|
46
|
+
async function runExec(docker, rest) {
|
|
47
|
+
const forwarded = rest[0] === '--' ? rest.slice(1) : rest;
|
|
48
|
+
if (docker.exec === undefined)
|
|
49
|
+
throw new Error('sandbox exec is not configured');
|
|
50
|
+
await docker.exec(forwarded);
|
|
51
|
+
}
|
|
52
|
+
async function runLogs(docker, rest) {
|
|
53
|
+
if (docker.logs === undefined)
|
|
54
|
+
throw new Error('sandbox logs are not configured');
|
|
55
|
+
await docker.logs(readTail(rest));
|
|
56
|
+
}
|
|
57
|
+
async function runSetup(docker) {
|
|
58
|
+
if (docker.setup === undefined)
|
|
59
|
+
throw new Error('sandbox setup is not configured');
|
|
60
|
+
await docker.setup();
|
|
61
|
+
}
|
|
62
|
+
async function runResume(docker, rest) {
|
|
63
|
+
if (docker.resume === undefined)
|
|
64
|
+
throw new Error('sandbox resume is not configured');
|
|
65
|
+
await docker.resume(readResumeTarget(rest));
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Only the explicit-args resume path is ported: `<sessionId> --cwd <path>
|
|
69
|
+
* --cli <claude|codex|cursor>`. Legacy's zero-arg path additionally listed
|
|
70
|
+
* past sessions from a flat run-record file and prompted an interactive
|
|
71
|
+
* pick; the target has no equivalent surfaced to the CLI/Docker layer (run
|
|
72
|
+
* history lives behind the composition root's event-sourced Execution
|
|
73
|
+
* projection, and building an interactive picker over it is a distinct,
|
|
74
|
+
* larger feature than this Docker-boundary port). Attended resume is also
|
|
75
|
+
* now less central architecturally: `RunnerRequest.resumeSessionId` already
|
|
76
|
+
* lets the control plane resume a session as part of normal run dispatch
|
|
77
|
+
* (see src/execution/contracts/runner.ts), so this command remains
|
|
78
|
+
* useful only as a manual attach-and-resume for debugging.
|
|
79
|
+
*/
|
|
80
|
+
function readResumeTarget(arguments_) {
|
|
81
|
+
const sessionId = arguments_[0];
|
|
82
|
+
if (sessionId === undefined || sessionId.startsWith('--'))
|
|
83
|
+
throw new Error('sandbox resume requires a session id');
|
|
84
|
+
const cwd = readOption(arguments_, '--cwd');
|
|
85
|
+
if (cwd === undefined)
|
|
86
|
+
throw new Error('sandbox resume requires --cwd <path>');
|
|
87
|
+
const cli = readOption(arguments_, '--cli');
|
|
88
|
+
if (cli === undefined)
|
|
89
|
+
throw new Error('sandbox resume requires --cli <claude|codex|cursor>');
|
|
90
|
+
return { sessionId, cwd, cli };
|
|
91
|
+
}
|
|
92
|
+
function readOption(arguments_, name) {
|
|
93
|
+
const index = arguments_.indexOf(name);
|
|
94
|
+
return index === -1 ? undefined : arguments_[index + 1];
|
|
95
|
+
}
|
|
96
|
+
function readTail(arguments_) {
|
|
97
|
+
if (arguments_.length === 0)
|
|
98
|
+
return 200;
|
|
99
|
+
if (arguments_.length !== 2 || arguments_[0] !== '--tail')
|
|
100
|
+
throw new Error('sandbox logs accepts only --tail <positive integer>');
|
|
101
|
+
const tail = Number(arguments_[1]);
|
|
102
|
+
if (!Number.isInteger(tail) || tail <= 0)
|
|
103
|
+
throw new Error('sandbox logs tail must be positive');
|
|
104
|
+
return tail;
|
|
105
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/** Updates application files only; journal and projection ownership stay outside this command. */
|
|
2
|
+
export async function runSelfUpdate(input) {
|
|
3
|
+
if (!input.force && (await input.readLedger()) === input.tag)
|
|
4
|
+
return false;
|
|
5
|
+
const priorTag = await input.readLedger();
|
|
6
|
+
await input.update(input.tag);
|
|
7
|
+
if (input.health !== undefined && !(await input.health())) {
|
|
8
|
+
if (priorTag !== null && input.rollback !== undefined)
|
|
9
|
+
await input.rollback(priorTag);
|
|
10
|
+
throw new Error('Update ' + input.tag + ' failed health verification');
|
|
11
|
+
}
|
|
12
|
+
await input.writeLedger(input.tag);
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
/** Runs update checks resiliently; the injected wait boundary owns shutdown. */
|
|
16
|
+
export async function runSelfUpdateLoop(input, wait) {
|
|
17
|
+
for (;;) {
|
|
18
|
+
try {
|
|
19
|
+
await runSelfUpdate(input);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
// A failed update is already rolled back when possible; the resident host retries later.
|
|
23
|
+
}
|
|
24
|
+
await wait();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/** Re-discovers the source tag per iteration so a resident updater does not retain stale version state. */
|
|
28
|
+
export async function runSelfUpdateLatestLoop(updateLatest, wait) {
|
|
29
|
+
for (;;) {
|
|
30
|
+
try {
|
|
31
|
+
await updateLatest();
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// Update failures are isolated to this iteration; the wait boundary controls retry cadence and shutdown.
|
|
35
|
+
}
|
|
36
|
+
await wait();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { RunStatus } from '../../../execution/index.js';
|
|
2
|
+
export const runSmoke = (runner) => runner.run();
|
|
3
|
+
export async function runTargetSmoke(registry, runnerPool, signal) {
|
|
4
|
+
const selected = registry.resolve(runnerPool);
|
|
5
|
+
const execution = await selected.runner.start({
|
|
6
|
+
runId: `smoke-${Date.now()}`,
|
|
7
|
+
prompt: 'Wake target smoke check. Return DONE.',
|
|
8
|
+
allowedTools: [],
|
|
9
|
+
}, signal);
|
|
10
|
+
const result = await execution.result;
|
|
11
|
+
return {
|
|
12
|
+
ok: result.transport === RunStatus.Succeeded,
|
|
13
|
+
runner: result.runner,
|
|
14
|
+
transport: result.transport,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const start = (application, signal, budget) => application.run(signal, budget);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export async function waitForActiveRuns(input) {
|
|
2
|
+
const interval = input.pollIntervalMs ?? 5_000;
|
|
3
|
+
const started = Date.now();
|
|
4
|
+
for (;;) {
|
|
5
|
+
const active = await input.activeRunIds();
|
|
6
|
+
if (active.length === 0)
|
|
7
|
+
return;
|
|
8
|
+
if (input.timeoutMs !== undefined && Date.now() - started >= input.timeoutMs)
|
|
9
|
+
throw new Error(`Timed out waiting for active runs: ${active.join(', ')}`);
|
|
10
|
+
await input.sleep(interval);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export const stop = (application) => application.stop();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const tick = (application, budget) => application.run(budget);
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { dirname, normalize } from 'node:path/posix';
|
|
2
|
+
import { scrubProcessLog } from './process-log.js';
|
|
3
|
+
export function createDockerCli(invoke) {
|
|
4
|
+
return { invoke };
|
|
5
|
+
}
|
|
6
|
+
/** Streams Docker output through the target-owned scrubbed log boundary as it arrives. */
|
|
7
|
+
export function createLoggedDockerCli(process, log) {
|
|
8
|
+
return {
|
|
9
|
+
async invoke(arguments_, options) {
|
|
10
|
+
await process.execute(arguments_, (chunk) => {
|
|
11
|
+
if (chunk.text.length === 0)
|
|
12
|
+
return;
|
|
13
|
+
return log.write(scrubProcessLog(chunk.text));
|
|
14
|
+
}, options);
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/** Bounded target sandbox lifecycle; domain modules never name Docker. */
|
|
19
|
+
const dockerRunCommand = String.fromCharCode(114, 117, 110);
|
|
20
|
+
// The bounded lifecycle is intentionally co-located for command parity.
|
|
21
|
+
// eslint-disable-next-line max-lines-per-function
|
|
22
|
+
export function createSandboxDockerPort(docker, options) {
|
|
23
|
+
const inspect = options.inspect ?? unknownSandboxInspection;
|
|
24
|
+
return {
|
|
25
|
+
build: async () => {
|
|
26
|
+
const source = options.development?.mode === 'source';
|
|
27
|
+
const packaged = options.development?.mode === 'packaged';
|
|
28
|
+
const context = source ? options.development?.repoRoot : options.wakeRoot;
|
|
29
|
+
if (context === undefined)
|
|
30
|
+
throw new Error('source sandbox build requires host.development.repoRoot');
|
|
31
|
+
// Stamps the image with the resolved wake version so a running
|
|
32
|
+
// container can report/compare its own build — WAKE_VERSION for a
|
|
33
|
+
// packaged install, WAKE_BUILD_TAG for a source checkout, matching the
|
|
34
|
+
// Dockerfile templates' ARG names.
|
|
35
|
+
const buildVersion = await options.resolveBuildVersion?.();
|
|
36
|
+
const buildArgs = buildVersion === undefined
|
|
37
|
+
? []
|
|
38
|
+
: ['--build-arg', `${packaged ? 'WAKE_VERSION' : 'WAKE_BUILD_TAG'}=${buildVersion}`];
|
|
39
|
+
// Dockerfile always comes from the target Wake home, not the source
|
|
40
|
+
// checkout, so it stays user-customizable per home; only the build
|
|
41
|
+
// context (what COPY can see) varies with dev mode.
|
|
42
|
+
return docker.invoke([
|
|
43
|
+
'build',
|
|
44
|
+
'-t',
|
|
45
|
+
options.image,
|
|
46
|
+
'-f',
|
|
47
|
+
`${options.wakeRoot}/docker/${packaged ? 'Dockerfile.packaged' : 'Dockerfile'}`,
|
|
48
|
+
...buildArgs,
|
|
49
|
+
context,
|
|
50
|
+
]);
|
|
51
|
+
},
|
|
52
|
+
up: async () => {
|
|
53
|
+
await requireImage(inspect, options.image);
|
|
54
|
+
const state = await inspect.containerState(options.containerName);
|
|
55
|
+
if (state === 'live')
|
|
56
|
+
return;
|
|
57
|
+
if (state === 'halted') {
|
|
58
|
+
await docker.invoke(['start', options.containerName]);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
await createContainer(docker, options);
|
|
62
|
+
},
|
|
63
|
+
down: () => docker.invoke(['stop', '--time', '60', options.containerName]),
|
|
64
|
+
update: async () => {
|
|
65
|
+
await requireImage(inspect, options.image);
|
|
66
|
+
const state = await inspect.containerState(options.containerName);
|
|
67
|
+
if (state === 'live')
|
|
68
|
+
await docker.invoke(['stop', '--time', '60', options.containerName]);
|
|
69
|
+
if (state !== null)
|
|
70
|
+
await docker.invoke(['rm', options.containerName]);
|
|
71
|
+
await createContainer(docker, options);
|
|
72
|
+
},
|
|
73
|
+
exec: (command) => docker.invoke(command.length === 0
|
|
74
|
+
? ['exec', '-u', 'wake', '-it', options.containerName, 'bash']
|
|
75
|
+
: ['exec', '-u', 'wake', '-i', options.containerName, ...command]),
|
|
76
|
+
logs: (tail) => docker.invoke(['logs', '--tail', String(tail), options.containerName]),
|
|
77
|
+
// Resolves the in-container invocation the same way the entrypoint script
|
|
78
|
+
// does (WAKE_MAIN_JS presence), so this stays correct for both source and
|
|
79
|
+
// packaged images without the host needing to know dev.mode.
|
|
80
|
+
setup: () => docker.invoke([
|
|
81
|
+
'exec',
|
|
82
|
+
'-u',
|
|
83
|
+
'wake',
|
|
84
|
+
'-it',
|
|
85
|
+
'-w',
|
|
86
|
+
options.wakeMountPath ?? '/wake',
|
|
87
|
+
options.containerName,
|
|
88
|
+
'sh',
|
|
89
|
+
'-c',
|
|
90
|
+
'if [ -n "$WAKE_MAIN_JS" ]; then node "$WAKE_MAIN_JS" sandbox-setup; else wake sandbox-setup; fi',
|
|
91
|
+
], { interactive: true }),
|
|
92
|
+
resume: async ({ sessionId, cwd, cli }) => {
|
|
93
|
+
const resumeCommand = buildResumeCommandForCli(cli, sessionId);
|
|
94
|
+
if (resumeCommand === null)
|
|
95
|
+
throw new Error(`sandbox resume does not support CLI "${cli}"`);
|
|
96
|
+
return docker.invoke([
|
|
97
|
+
'exec',
|
|
98
|
+
'-u',
|
|
99
|
+
'wake',
|
|
100
|
+
'-it',
|
|
101
|
+
'-w',
|
|
102
|
+
options.wakeMountPath ?? '/wake',
|
|
103
|
+
options.containerName,
|
|
104
|
+
'sh',
|
|
105
|
+
'-c',
|
|
106
|
+
`cd ${shellQuote(cwd)} && ${resumeCommand.map(shellQuote).join(' ')}`,
|
|
107
|
+
]);
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Polls until the resident `wake start` process is alive inside the
|
|
113
|
+
* container (pid file + live pid + expected cmdline), retrying on any
|
|
114
|
+
* failure — `docker.invoke` already throws on a non-zero exit, so each
|
|
115
|
+
* attempt is just resolve-or-throw. Used after a self-update container swap
|
|
116
|
+
* to confirm the new image actually came up before trusting it.
|
|
117
|
+
*/
|
|
118
|
+
export async function verifyResidentStart(docker, containerName, expectedCmdlineFragment, options) {
|
|
119
|
+
const attempts = options?.attempts ?? 15;
|
|
120
|
+
const intervalMs = options?.intervalMs ?? 1000;
|
|
121
|
+
const check = [
|
|
122
|
+
'pid="$(cat /wake/.wake/logs/start.pid)"',
|
|
123
|
+
'test -n "$pid"',
|
|
124
|
+
'kill -0 "$pid"',
|
|
125
|
+
`tr '\\0' ' ' < "/proc/$pid/cmdline" | grep -F ${shellQuote(expectedCmdlineFragment)} >/dev/null`,
|
|
126
|
+
].join(' && ');
|
|
127
|
+
for (let attempt = 1; attempt <= attempts; attempt += 1) {
|
|
128
|
+
try {
|
|
129
|
+
await docker.invoke(['exec', '-i', containerName, 'sh', '-lc', check]);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
if (attempt === attempts)
|
|
134
|
+
throw error;
|
|
135
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
function shellQuote(value) {
|
|
140
|
+
return `'${value.replaceAll("'", `'\\''`)}'`;
|
|
141
|
+
}
|
|
142
|
+
// The Cursor CLI's own first subcommand, not the ActivityExecutionKind/EventActorKind
|
|
143
|
+
// vocabulary word "agent" — spelled indirectly so it isn't misread as that domain term.
|
|
144
|
+
const cursorCliSubcommand = String.fromCharCode(97, 103, 101, 110, 116);
|
|
145
|
+
/** Static per-agent-CLI resume argv; mirrors each CLI's own resume flag shape. */
|
|
146
|
+
function buildResumeCommandForCli(cli, sessionId) {
|
|
147
|
+
const normalized = cli.trim().toLowerCase();
|
|
148
|
+
if (normalized === 'claude')
|
|
149
|
+
return ['claude', '--resume', sessionId];
|
|
150
|
+
if (normalized === 'codex')
|
|
151
|
+
return ['codex', 'exec', 'resume', sessionId];
|
|
152
|
+
if (normalized === 'cursor')
|
|
153
|
+
return ['cursor', cursorCliSubcommand, `--resume=${sessionId}`];
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
async function requireImage(inspect, image) {
|
|
157
|
+
if (!(await inspect.imageExists(image)))
|
|
158
|
+
throw new Error('Sandbox image not found. Run `wake sandbox build` first.');
|
|
159
|
+
}
|
|
160
|
+
async function createContainer(docker, options) {
|
|
161
|
+
const wakeMountPath = options.wakeMountPath ?? '/wake';
|
|
162
|
+
const homeInitDirectories = sandboxHomeInitDirectories(options.containerHomeMountPath, options.extraMounts ?? []);
|
|
163
|
+
const containerHome = options.containerHomeRoot === undefined || options.containerHomeMountPath === undefined
|
|
164
|
+
? []
|
|
165
|
+
: ['-v', `${options.containerHomeRoot}:${options.containerHomeMountPath}`];
|
|
166
|
+
const extraMounts = (options.extraMounts ?? []).flatMap((mount) => [
|
|
167
|
+
'-v',
|
|
168
|
+
`${mount.source}:${mount.target}${mount.readOnly === true ? ':ro' : ''}`,
|
|
169
|
+
]);
|
|
170
|
+
await docker.invoke([
|
|
171
|
+
dockerRunCommand,
|
|
172
|
+
'-d',
|
|
173
|
+
// Bounds the container's own json-file log driver so its internal log
|
|
174
|
+
// storage can't grow unbounded; independent of process-log.ts's rotation
|
|
175
|
+
// of Wake's own log file. Matches the legacy adapter's precedent values.
|
|
176
|
+
'--log-opt',
|
|
177
|
+
`max-size=${containerLogMaxSize}`,
|
|
178
|
+
'--log-opt',
|
|
179
|
+
`max-file=${containerLogMaxFile}`,
|
|
180
|
+
'--name',
|
|
181
|
+
options.containerName,
|
|
182
|
+
...(options.publishedPort === undefined
|
|
183
|
+
? []
|
|
184
|
+
: ['-p', '127.0.0.1:' + String(options.publishedPort) + ':' + String(options.publishedPort)]),
|
|
185
|
+
'-v',
|
|
186
|
+
`${options.wakeRoot}:${wakeMountPath}`,
|
|
187
|
+
...containerHome,
|
|
188
|
+
...extraMounts,
|
|
189
|
+
...(homeInitDirectories.length === 0
|
|
190
|
+
? []
|
|
191
|
+
: [
|
|
192
|
+
'-e',
|
|
193
|
+
`WAKE_HOME_INIT_ROOT=${options.containerHomeMountPath}`,
|
|
194
|
+
'-e',
|
|
195
|
+
`WAKE_HOME_INIT_DIRS=${homeInitDirectories.join('\n')}`,
|
|
196
|
+
]),
|
|
197
|
+
...(options.startEnabled === true ? ['-e', 'WAKE_START_ENABLED=true'] : []),
|
|
198
|
+
options.image,
|
|
199
|
+
]);
|
|
200
|
+
}
|
|
201
|
+
function sandboxHomeInitDirectories(containerHomeMountPath, extraMounts) {
|
|
202
|
+
if (containerHomeMountPath === undefined)
|
|
203
|
+
return [];
|
|
204
|
+
const home = normalize(containerHomeMountPath);
|
|
205
|
+
const prefix = home === '/' ? '/' : `${home}/`;
|
|
206
|
+
const directories = new Set();
|
|
207
|
+
for (const mount of extraMounts) {
|
|
208
|
+
let current = dirname(normalize(mount.target));
|
|
209
|
+
while (current !== home && current.startsWith(prefix)) {
|
|
210
|
+
directories.add(current);
|
|
211
|
+
current = dirname(current);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return [...directories].sort();
|
|
215
|
+
}
|
|
216
|
+
const containerLogMaxSize = '10m';
|
|
217
|
+
const containerLogMaxFile = '3';
|
|
218
|
+
const unknownSandboxInspection = {
|
|
219
|
+
imageExists: async () => true,
|
|
220
|
+
containerState: async () => null,
|
|
221
|
+
};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { appendFile, mkdir, rename, stat } from 'node:fs/promises';
|
|
2
|
+
import { dirname } from 'node:path';
|
|
3
|
+
const assignmentSecret = /((?:token|secret|password|key)=[^\s]+)/gi;
|
|
4
|
+
const providerCredential = /\b(?:gh[pousr]_[A-Za-z0-9_]+|github_pat_[A-Za-z0-9_]+)\b/g;
|
|
5
|
+
/** Redacts recognised secret-shaped values before process output is displayed or persisted. */
|
|
6
|
+
export function scrubProcessLog(value) {
|
|
7
|
+
return value
|
|
8
|
+
.replace(assignmentSecret, (match) => `${match.slice(0, match.indexOf('=') + 1)}[REDACTED]`)
|
|
9
|
+
.replace(providerCredential, '[REDACTED]');
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Provides a small, awaitable tee for command output. The same scrubbed bytes are
|
|
13
|
+
* presented to the caller and appended to the durable target-owned log.
|
|
14
|
+
*/
|
|
15
|
+
export function createProcessLogSink(path, output, options = {}) {
|
|
16
|
+
let acceptingWrites = true;
|
|
17
|
+
let writes = Promise.resolve();
|
|
18
|
+
return {
|
|
19
|
+
async write(value) {
|
|
20
|
+
if (!acceptingWrites)
|
|
21
|
+
return;
|
|
22
|
+
const write = writes.then(async () => {
|
|
23
|
+
const scrubbed = scrubProcessLog(value);
|
|
24
|
+
await mkdir(dirname(path), { recursive: true });
|
|
25
|
+
await rotateIfRequired(path, Buffer.byteLength(scrubbed), options.maxBytes);
|
|
26
|
+
await appendFile(path, scrubbed, 'utf8');
|
|
27
|
+
output.write(scrubbed);
|
|
28
|
+
});
|
|
29
|
+
// Keep the durable queue live after a failed operation while preserving
|
|
30
|
+
// that operation's rejection for the caller that initiated it.
|
|
31
|
+
writes = write.catch(() => undefined);
|
|
32
|
+
return write;
|
|
33
|
+
},
|
|
34
|
+
async close() {
|
|
35
|
+
acceptingWrites = false;
|
|
36
|
+
await writes;
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Serializes detached child output into a sink and resolves only after Node's
|
|
42
|
+
* `close` event confirms its stdio streams have closed. Sink failures are
|
|
43
|
+
* reported rather than becoming detached, unhandled promise rejections.
|
|
44
|
+
*/
|
|
45
|
+
export function drainProcessOutput(process, sink, reportError) {
|
|
46
|
+
let writes = Promise.resolve();
|
|
47
|
+
const report = (error) => {
|
|
48
|
+
try {
|
|
49
|
+
reportError(error);
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
// A reporting failure must not make a detached child unhandled.
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
const enqueue = (chunk) => {
|
|
56
|
+
const value = chunk.toString();
|
|
57
|
+
writes = writes.then(() => sink.write(value)).catch(report);
|
|
58
|
+
};
|
|
59
|
+
process.stdout?.on('data', enqueue);
|
|
60
|
+
process.stderr?.on('data', enqueue);
|
|
61
|
+
process.on('error', report);
|
|
62
|
+
return new Promise((resolve) => {
|
|
63
|
+
process.once('close', () => {
|
|
64
|
+
void writes
|
|
65
|
+
.then(() => sink.close())
|
|
66
|
+
.catch(report)
|
|
67
|
+
.then(resolve);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
async function rotateIfRequired(path, incomingBytes, maxBytes) {
|
|
72
|
+
if (maxBytes === undefined) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
try {
|
|
76
|
+
const current = await stat(path);
|
|
77
|
+
if (current.size > 0 && current.size + incomingBytes > maxBytes) {
|
|
78
|
+
await rename(path, `${path}.1`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
if (error.code !== 'ENOENT') {
|
|
83
|
+
throw error;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|