runwork 0.15.0 → 0.15.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +19272 -116
- package/package.json +4 -4
- package/dist/__tests__/curl-parser.test.d.ts +0 -1
- package/dist/__tests__/curl-parser.test.js +0 -250
- package/dist/__tests__/install-scripts.test.d.ts +0 -1
- package/dist/__tests__/install-scripts.test.js +0 -280
- package/dist/__tests__/types-manager.test.d.ts +0 -1
- package/dist/__tests__/types-manager.test.js +0 -89
- package/dist/agents/__tests__/chatgpt-registry.test.d.ts +0 -1
- package/dist/agents/__tests__/chatgpt-registry.test.js +0 -61
- package/dist/agents/__tests__/claude-code-managed-block.test.d.ts +0 -1
- package/dist/agents/__tests__/claude-code-managed-block.test.js +0 -97
- package/dist/agents/__tests__/claude-code-plugin.test.d.ts +0 -1
- package/dist/agents/__tests__/claude-code-plugin.test.js +0 -47
- package/dist/agents/__tests__/claude-code-stats.test.d.ts +0 -1
- package/dist/agents/__tests__/claude-code-stats.test.js +0 -390
- package/dist/agents/__tests__/claude-desktop-memory.test.d.ts +0 -1
- package/dist/agents/__tests__/claude-desktop-memory.test.js +0 -154
- package/dist/agents/__tests__/claude-desktop-plugin-tree.test.d.ts +0 -1
- package/dist/agents/__tests__/claude-desktop-plugin-tree.test.js +0 -161
- package/dist/agents/__tests__/claude-desktop-plugin.test.d.ts +0 -1
- package/dist/agents/__tests__/claude-desktop-plugin.test.js +0 -117
- package/dist/agents/__tests__/claude-desktop-rpm.test.d.ts +0 -1
- package/dist/agents/__tests__/claude-desktop-rpm.test.js +0 -126
- package/dist/agents/__tests__/claude-desktop-stats.test.d.ts +0 -1
- package/dist/agents/__tests__/claude-desktop-stats.test.js +0 -280
- package/dist/agents/__tests__/codex-instructions.test.d.ts +0 -1
- package/dist/agents/__tests__/codex-instructions.test.js +0 -57
- package/dist/agents/__tests__/codex-minimum-permissions.test.d.ts +0 -1
- package/dist/agents/__tests__/codex-minimum-permissions.test.js +0 -82
- package/dist/agents/__tests__/codex-stats.test.d.ts +0 -1
- package/dist/agents/__tests__/codex-stats.test.js +0 -370
- package/dist/agents/__tests__/cursor-merge.test.d.ts +0 -1
- package/dist/agents/__tests__/cursor-merge.test.js +0 -66
- package/dist/agents/__tests__/cursor-stats.test.d.ts +0 -1
- package/dist/agents/__tests__/cursor-stats.test.js +0 -183
- package/dist/agents/__tests__/defaults-merge.test.d.ts +0 -1
- package/dist/agents/__tests__/defaults-merge.test.js +0 -268
- package/dist/agents/__tests__/detection.test.d.ts +0 -1
- package/dist/agents/__tests__/detection.test.js +0 -89
- package/dist/agents/__tests__/graceful-degradation.test.d.ts +0 -1
- package/dist/agents/__tests__/graceful-degradation.test.js +0 -129
- package/dist/agents/__tests__/instruction-hint.test.d.ts +0 -1
- package/dist/agents/__tests__/instruction-hint.test.js +0 -69
- package/dist/agents/__tests__/intro-skill.test.d.ts +0 -1
- package/dist/agents/__tests__/intro-skill.test.js +0 -193
- package/dist/agents/__tests__/schema-validation.test.d.ts +0 -1
- package/dist/agents/__tests__/schema-validation.test.js +0 -212
- package/dist/agents/__tests__/skill-slug.test.d.ts +0 -1
- package/dist/agents/__tests__/skill-slug.test.js +0 -77
- package/dist/agents/claude-code.d.ts +0 -53
- package/dist/agents/claude-code.js +0 -754
- package/dist/agents/claude-desktop-plugin-tree.d.ts +0 -59
- package/dist/agents/claude-desktop-plugin-tree.js +0 -143
- package/dist/agents/claude-desktop.d.ts +0 -47
- package/dist/agents/claude-desktop.js +0 -684
- package/dist/agents/cline.d.ts +0 -15
- package/dist/agents/cline.js +0 -130
- package/dist/agents/codex.d.ts +0 -44
- package/dist/agents/codex.js +0 -453
- package/dist/agents/conversation-skills.d.ts +0 -18
- package/dist/agents/conversation-skills.js +0 -229
- package/dist/agents/cursor.d.ts +0 -48
- package/dist/agents/cursor.js +0 -324
- package/dist/agents/default-config.d.ts +0 -30
- package/dist/agents/default-config.js +0 -67
- package/dist/agents/defaults-merge.d.ts +0 -72
- package/dist/agents/defaults-merge.js +0 -131
- package/dist/agents/detect.d.ts +0 -4
- package/dist/agents/detect.js +0 -67
- package/dist/agents/detection.d.ts +0 -18
- package/dist/agents/detection.js +0 -94
- package/dist/agents/gemini.d.ts +0 -15
- package/dist/agents/gemini.js +0 -122
- package/dist/agents/generic-adapter.d.ts +0 -25
- package/dist/agents/generic-adapter.js +0 -151
- package/dist/agents/intro-skill.d.ts +0 -45
- package/dist/agents/intro-skill.js +0 -447
- package/dist/agents/registry-data.d.ts +0 -192
- package/dist/agents/registry-data.js +0 -669
- package/dist/agents/registry.d.ts +0 -13
- package/dist/agents/registry.js +0 -36
- package/dist/agents/runtime-detection.d.ts +0 -82
- package/dist/agents/runtime-detection.js +0 -271
- package/dist/agents/session-start-hook.d.ts +0 -37
- package/dist/agents/session-start-hook.js +0 -159
- package/dist/agents/types.d.ts +0 -171
- package/dist/agents/types.js +0 -75
- package/dist/agents/utils/instruction-hint.d.ts +0 -21
- package/dist/agents/utils/instruction-hint.js +0 -108
- package/dist/agents/utils/json-config.d.ts +0 -19
- package/dist/agents/utils/json-config.js +0 -69
- package/dist/agents/utils/toml-config.d.ts +0 -8
- package/dist/agents/utils/toml-config.js +0 -27
- package/dist/agents/windsurf.d.ts +0 -14
- package/dist/agents/windsurf.js +0 -102
- package/dist/api/__tests__/client.test.d.ts +0 -1
- package/dist/api/__tests__/client.test.js +0 -272
- package/dist/api/client.d.ts +0 -326
- package/dist/api/client.js +0 -427
- package/dist/auth/__tests__/login-flow.test.d.ts +0 -1
- package/dist/auth/__tests__/login-flow.test.js +0 -101
- package/dist/auth/__tests__/store.test.d.ts +0 -1
- package/dist/auth/__tests__/store.test.js +0 -132
- package/dist/auth/login-flow.d.ts +0 -26
- package/dist/auth/login-flow.js +0 -137
- package/dist/auth/store.d.ts +0 -5
- package/dist/auth/store.js +0 -62
- package/dist/commands/__tests__/clone-args.test.d.ts +0 -1
- package/dist/commands/__tests__/clone-args.test.js +0 -51
- package/dist/commands/__tests__/clone-source-result.test.d.ts +0 -1
- package/dist/commands/__tests__/clone-source-result.test.js +0 -45
- package/dist/commands/__tests__/info-merge.test.d.ts +0 -1
- package/dist/commands/__tests__/info-merge.test.js +0 -55
- package/dist/commands/__tests__/mcp-entries.test.d.ts +0 -1
- package/dist/commands/__tests__/mcp-entries.test.js +0 -48
- package/dist/commands/__tests__/setup-persona.test.d.ts +0 -1
- package/dist/commands/__tests__/setup-persona.test.js +0 -31
- package/dist/commands/__tests__/setup.test.d.ts +0 -1
- package/dist/commands/__tests__/setup.test.js +0 -81
- package/dist/commands/__tests__/sync-redetect.test.d.ts +0 -1
- package/dist/commands/__tests__/sync-redetect.test.js +0 -96
- package/dist/commands/__tests__/sync-telemetry.test.d.ts +0 -1
- package/dist/commands/__tests__/sync-telemetry.test.js +0 -281
- package/dist/commands/__tests__/upgrade.test.d.ts +0 -1
- package/dist/commands/__tests__/upgrade.test.js +0 -157
- package/dist/commands/agents.d.ts +0 -2
- package/dist/commands/agents.js +0 -160
- package/dist/commands/api-keys.d.ts +0 -2
- package/dist/commands/api-keys.js +0 -95
- package/dist/commands/apps.d.ts +0 -2
- package/dist/commands/apps.js +0 -82
- package/dist/commands/build-plugin.d.ts +0 -2
- package/dist/commands/build-plugin.js +0 -135
- package/dist/commands/clone.d.ts +0 -60
- package/dist/commands/clone.js +0 -271
- package/dist/commands/components.d.ts +0 -2
- package/dist/commands/components.js +0 -43
- package/dist/commands/deploy.d.ts +0 -2
- package/dist/commands/deploy.js +0 -279
- package/dist/commands/dev.d.ts +0 -11
- package/dist/commands/dev.js +0 -1011
- package/dist/commands/doctor.d.ts +0 -2
- package/dist/commands/doctor.js +0 -230
- package/dist/commands/endpoints.d.ts +0 -2
- package/dist/commands/endpoints.js +0 -189
- package/dist/commands/entities.d.ts +0 -2
- package/dist/commands/entities.js +0 -198
- package/dist/commands/files.d.ts +0 -2
- package/dist/commands/files.js +0 -193
- package/dist/commands/inbox.d.ts +0 -11
- package/dist/commands/inbox.js +0 -60
- package/dist/commands/info.d.ts +0 -178
- package/dist/commands/info.js +0 -455
- package/dist/commands/init.d.ts +0 -21
- package/dist/commands/init.js +0 -185
- package/dist/commands/integrations.d.ts +0 -2
- package/dist/commands/integrations.js +0 -233
- package/dist/commands/login.d.ts +0 -2
- package/dist/commands/login.js +0 -44
- package/dist/commands/logout.d.ts +0 -2
- package/dist/commands/logout.js +0 -13
- package/dist/commands/logs.d.ts +0 -2
- package/dist/commands/logs.js +0 -232
- package/dist/commands/mcp-entries.d.ts +0 -13
- package/dist/commands/mcp-entries.js +0 -26
- package/dist/commands/mcp.d.ts +0 -2
- package/dist/commands/mcp.js +0 -245
- package/dist/commands/open.d.ts +0 -2
- package/dist/commands/open.js +0 -53
- package/dist/commands/resume.d.ts +0 -2
- package/dist/commands/resume.js +0 -289
- package/dist/commands/save-convo.d.ts +0 -8
- package/dist/commands/save-convo.js +0 -20
- package/dist/commands/schedules.d.ts +0 -2
- package/dist/commands/schedules.js +0 -221
- package/dist/commands/setup.d.ts +0 -27
- package/dist/commands/setup.js +0 -177
- package/dist/commands/share-convo.d.ts +0 -24
- package/dist/commands/share-convo.js +0 -167
- package/dist/commands/skills.d.ts +0 -2
- package/dist/commands/skills.js +0 -352
- package/dist/commands/sync-telemetry.d.ts +0 -33
- package/dist/commands/sync-telemetry.js +0 -186
- package/dist/commands/sync.d.ts +0 -37
- package/dist/commands/sync.js +0 -702
- package/dist/commands/uninstall.d.ts +0 -2
- package/dist/commands/uninstall.js +0 -145
- package/dist/commands/upgrade.d.ts +0 -14
- package/dist/commands/upgrade.js +0 -217
- package/dist/commands/validate.d.ts +0 -2
- package/dist/commands/validate.js +0 -89
- package/dist/commands/welcome.d.ts +0 -1
- package/dist/commands/welcome.js +0 -86
- package/dist/commands/workflows.d.ts +0 -2
- package/dist/commands/workflows.js +0 -187
- package/dist/deploy/__tests__/deploy-state.test.d.ts +0 -1
- package/dist/deploy/__tests__/deploy-state.test.js +0 -80
- package/dist/deploy/__tests__/deploy-status.test.d.ts +0 -1
- package/dist/deploy/__tests__/deploy-status.test.js +0 -41
- package/dist/deploy/__tests__/detach-args.test.d.ts +0 -1
- package/dist/deploy/__tests__/detach-args.test.js +0 -30
- package/dist/deploy/deploy-state.d.ts +0 -36
- package/dist/deploy/deploy-state.js +0 -63
- package/dist/deploy/deploy-status.d.ts +0 -21
- package/dist/deploy/deploy-status.js +0 -36
- package/dist/deploy/detach.d.ts +0 -32
- package/dist/deploy/detach.js +0 -71
- package/dist/dev/__tests__/attach.test.d.ts +0 -1
- package/dist/dev/__tests__/attach.test.js +0 -296
- package/dist/dev/__tests__/detach.test.d.ts +0 -1
- package/dist/dev/__tests__/detach.test.js +0 -404
- package/dist/dev/__tests__/preview-url-poller.test.d.ts +0 -1
- package/dist/dev/__tests__/preview-url-poller.test.js +0 -149
- package/dist/dev/__tests__/session.test.d.ts +0 -1
- package/dist/dev/__tests__/session.test.js +0 -446
- package/dist/dev/__tests__/startup-sync.test.d.ts +0 -1
- package/dist/dev/__tests__/startup-sync.test.js +0 -32
- package/dist/dev/__tests__/stop.test.d.ts +0 -1
- package/dist/dev/__tests__/stop.test.js +0 -172
- package/dist/dev/attach.d.ts +0 -120
- package/dist/dev/attach.js +0 -269
- package/dist/dev/detach.d.ts +0 -187
- package/dist/dev/detach.js +0 -292
- package/dist/dev/preview-url-poller.d.ts +0 -35
- package/dist/dev/preview-url-poller.js +0 -50
- package/dist/dev/session.d.ts +0 -175
- package/dist/dev/session.js +0 -258
- package/dist/dev/startup-sync.d.ts +0 -23
- package/dist/dev/startup-sync.js +0 -14
- package/dist/dev/stop.d.ts +0 -52
- package/dist/dev/stop.js +0 -101
- package/dist/devtools/registry-data.d.ts +0 -46
- package/dist/devtools/registry-data.js +0 -40
- package/dist/generated/bundled-types.d.ts +0 -1
- package/dist/generated/bundled-types.js +0 -46
- package/dist/generated/version.d.ts +0 -1
- package/dist/generated/version.js +0 -2
- package/dist/git/__tests__/auto-commit.test.d.ts +0 -1
- package/dist/git/__tests__/auto-commit.test.js +0 -431
- package/dist/git/__tests__/classify-sync-error.test.d.ts +0 -1
- package/dist/git/__tests__/classify-sync-error.test.js +0 -57
- package/dist/git/__tests__/credential-helper-e2e.test.d.ts +0 -21
- package/dist/git/__tests__/credential-helper-e2e.test.js +0 -195
- package/dist/git/__tests__/credentials.test.d.ts +0 -1
- package/dist/git/__tests__/credentials.test.js +0 -141
- package/dist/git/__tests__/deploy-guard.test.d.ts +0 -1
- package/dist/git/__tests__/deploy-guard.test.js +0 -61
- package/dist/git/__tests__/ensure-git-credential-helper.test.d.ts +0 -1
- package/dist/git/__tests__/ensure-git-credential-helper.test.js +0 -133
- package/dist/git/__tests__/ensure-runwork-remote.test.d.ts +0 -1
- package/dist/git/__tests__/ensure-runwork-remote.test.js +0 -109
- package/dist/git/__tests__/identity.test.d.ts +0 -1
- package/dist/git/__tests__/identity.test.js +0 -146
- package/dist/git/__tests__/manifest.test.d.ts +0 -1
- package/dist/git/__tests__/manifest.test.js +0 -446
- package/dist/git/__tests__/preflight-resolution.test.d.ts +0 -1
- package/dist/git/__tests__/preflight-resolution.test.js +0 -366
- package/dist/git/__tests__/preflight.test.d.ts +0 -1
- package/dist/git/__tests__/preflight.test.js +0 -36
- package/dist/git/__tests__/repo-config.test.d.ts +0 -1
- package/dist/git/__tests__/repo-config.test.js +0 -26
- package/dist/git/__tests__/sync.test.d.ts +0 -1
- package/dist/git/__tests__/sync.test.js +0 -405
- package/dist/git/auto-commit.d.ts +0 -35
- package/dist/git/auto-commit.js +0 -293
- package/dist/git/classify-sync-error.d.ts +0 -21
- package/dist/git/classify-sync-error.js +0 -111
- package/dist/git/credentials.d.ts +0 -75
- package/dist/git/credentials.js +0 -164
- package/dist/git/critical-files.d.ts +0 -20
- package/dist/git/critical-files.js +0 -68
- package/dist/git/deploy-guard.d.ts +0 -53
- package/dist/git/deploy-guard.js +0 -78
- package/dist/git/identity.d.ts +0 -44
- package/dist/git/identity.js +0 -133
- package/dist/git/preflight.d.ts +0 -57
- package/dist/git/preflight.js +0 -276
- package/dist/git/remote.d.ts +0 -37
- package/dist/git/remote.js +0 -75
- package/dist/git/repo-config.d.ts +0 -8
- package/dist/git/repo-config.js +0 -29
- package/dist/git/sync.d.ts +0 -15
- package/dist/git/sync.js +0 -159
- package/dist/health/__tests__/checks.test.d.ts +0 -1
- package/dist/health/__tests__/checks.test.js +0 -357
- package/dist/health/__tests__/cli-distribution-checks.test.d.ts +0 -1
- package/dist/health/__tests__/cli-distribution-checks.test.js +0 -196
- package/dist/health/__tests__/fix.test.d.ts +0 -1
- package/dist/health/__tests__/fix.test.js +0 -72
- package/dist/health/__tests__/runner-filter.test.d.ts +0 -1
- package/dist/health/__tests__/runner-filter.test.js +0 -61
- package/dist/health/checks.d.ts +0 -42
- package/dist/health/checks.js +0 -636
- package/dist/health/fix.d.ts +0 -22
- package/dist/health/fix.js +0 -62
- package/dist/health/runner.d.ts +0 -8
- package/dist/health/runner.js +0 -47
- package/dist/health/types.d.ts +0 -12
- package/dist/health/types.js +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/logs/__tests__/tailer-format.test.d.ts +0 -1
- package/dist/logs/__tests__/tailer-format.test.js +0 -43
- package/dist/logs/tailer.d.ts +0 -17
- package/dist/logs/tailer.js +0 -217
- package/dist/sync/__tests__/change-detect.test.d.ts +0 -1
- package/dist/sync/__tests__/change-detect.test.js +0 -123
- package/dist/sync/__tests__/hash.test.d.ts +0 -1
- package/dist/sync/__tests__/hash.test.js +0 -18
- package/dist/sync/change-detect.d.ts +0 -19
- package/dist/sync/change-detect.js +0 -136
- package/dist/sync/conflict-ui.d.ts +0 -5
- package/dist/sync/conflict-ui.js +0 -78
- package/dist/sync/executor.d.ts +0 -23
- package/dist/sync/executor.js +0 -102
- package/dist/sync/hash.d.ts +0 -1
- package/dist/sync/hash.js +0 -4
- package/dist/sync/types.d.ts +0 -24
- package/dist/sync/types.js +0 -1
- package/dist/template/manifest.d.ts +0 -17
- package/dist/template/manifest.js +0 -145
- package/dist/tools/types.d.ts +0 -52
- package/dist/tools/types.js +0 -8
- package/dist/types-manager.d.ts +0 -1
- package/dist/types-manager.js +0 -35
- package/dist/types.d.ts +0 -349
- package/dist/types.js +0 -1
- package/dist/ui/__tests__/banner.test.d.ts +0 -1
- package/dist/ui/__tests__/banner.test.js +0 -98
- package/dist/ui/__tests__/colors.test.d.ts +0 -1
- package/dist/ui/__tests__/colors.test.js +0 -22
- package/dist/ui/__tests__/keyboard.test.d.ts +0 -1
- package/dist/ui/__tests__/keyboard.test.js +0 -34
- package/dist/ui/__tests__/status-line.test.d.ts +0 -1
- package/dist/ui/__tests__/status-line.test.js +0 -54
- package/dist/ui/banner.d.ts +0 -29
- package/dist/ui/banner.js +0 -153
- package/dist/ui/colors.d.ts +0 -4
- package/dist/ui/colors.js +0 -7
- package/dist/ui/keyboard.d.ts +0 -12
- package/dist/ui/keyboard.js +0 -61
- package/dist/ui/status-line.d.ts +0 -6
- package/dist/ui/status-line.js +0 -53
- package/dist/utils/__tests__/format-error.test.d.ts +0 -1
- package/dist/utils/__tests__/format-error.test.js +0 -43
- package/dist/utils/__tests__/help-json.test.d.ts +0 -1
- package/dist/utils/__tests__/help-json.test.js +0 -39
- package/dist/utils/__tests__/http.test.d.ts +0 -1
- package/dist/utils/__tests__/http.test.js +0 -381
- package/dist/utils/__tests__/ignore-matcher.test.d.ts +0 -1
- package/dist/utils/__tests__/ignore-matcher.test.js +0 -205
- package/dist/utils/__tests__/output.test.d.ts +0 -1
- package/dist/utils/__tests__/output.test.js +0 -38
- package/dist/utils/__tests__/prompt.test.d.ts +0 -1
- package/dist/utils/__tests__/prompt.test.js +0 -27
- package/dist/utils/__tests__/resolve.test.d.ts +0 -1
- package/dist/utils/__tests__/resolve.test.js +0 -95
- package/dist/utils/__tests__/sqlite.test.d.ts +0 -1
- package/dist/utils/__tests__/sqlite.test.js +0 -89
- package/dist/utils/agent-guidance.d.ts +0 -47
- package/dist/utils/agent-guidance.js +0 -128
- package/dist/utils/app-info.d.ts +0 -70
- package/dist/utils/app-info.js +0 -167
- package/dist/utils/curl-parser.d.ts +0 -12
- package/dist/utils/curl-parser.js +0 -162
- package/dist/utils/data-input.d.ts +0 -1
- package/dist/utils/data-input.js +0 -38
- package/dist/utils/format-error.d.ts +0 -10
- package/dist/utils/format-error.js +0 -38
- package/dist/utils/fs.d.ts +0 -5
- package/dist/utils/fs.js +0 -23
- package/dist/utils/help-json.d.ts +0 -70
- package/dist/utils/help-json.js +0 -88
- package/dist/utils/http.d.ts +0 -46
- package/dist/utils/http.js +0 -421
- package/dist/utils/ignore-matcher.d.ts +0 -47
- package/dist/utils/ignore-matcher.js +0 -132
- package/dist/utils/output.d.ts +0 -17
- package/dist/utils/output.js +0 -27
- package/dist/utils/prompt.d.ts +0 -5
- package/dist/utils/prompt.js +0 -42
- package/dist/utils/resolve.d.ts +0 -12
- package/dist/utils/resolve.js +0 -52
- package/dist/utils/setup-state.d.ts +0 -3
- package/dist/utils/setup-state.js +0 -19
- package/dist/utils/sqlite-adapter.d.ts +0 -48
- package/dist/utils/sqlite-adapter.js +0 -147
- package/dist/utils/sqlite.d.ts +0 -14
- package/dist/utils/sqlite.js +0 -14
- package/dist/utils/subprocess.d.ts +0 -19
- package/dist/utils/subprocess.js +0 -27
- package/dist/utils/which.d.ts +0 -14
- package/dist/utils/which.js +0 -47
- package/dist/utils/zip.d.ts +0 -7
- package/dist/utils/zip.js +0 -42
- package/dist/validate/__tests__/validate.test.d.ts +0 -1
- package/dist/validate/__tests__/validate.test.js +0 -42
- package/dist/validate/freshness.d.ts +0 -28
- package/dist/validate/freshness.js +0 -48
- package/dist/validate/preview.d.ts +0 -21
- package/dist/validate/preview.js +0 -39
- package/dist/workspace/resolve.d.ts +0 -19
- package/dist/workspace/resolve.js +0 -100
package/dist/commands/clone.js
DELETED
|
@@ -1,271 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import { execFileSync } from '../utils/subprocess.js';
|
|
3
|
-
import { writeFileSync, mkdirSync, existsSync } from 'fs';
|
|
4
|
-
import { join, resolve } from 'path';
|
|
5
|
-
import { requireAuth } from '../auth/store.js';
|
|
6
|
-
import { ApiClient } from '../api/client.js';
|
|
7
|
-
import { promptSelect } from '../utils/prompt.js';
|
|
8
|
-
import { resolveApp } from '../utils/resolve.js';
|
|
9
|
-
import { generateManifest, saveManifest } from '../template/manifest.js';
|
|
10
|
-
import { extractZip } from '../utils/zip.js';
|
|
11
|
-
import { removeNestedGitDirs } from '../utils/fs.js';
|
|
12
|
-
import { runAgentWizard } from '../ui/banner.js';
|
|
13
|
-
import { shouldOutputJson, jsonOut } from '../utils/output.js';
|
|
14
|
-
import { buildCloneGuide, buildErrorResponse } from '../utils/agent-guidance.js';
|
|
15
|
-
import { ensureGitIdentity } from '../git/identity.js';
|
|
16
|
-
import { ensureGitCredentialHelper } from '../git/credentials.js';
|
|
17
|
-
import { ensureRunworkRemote } from '../git/remote.js';
|
|
18
|
-
import { hardenRepoForRestrictedFs } from '../git/repo-config.js';
|
|
19
|
-
import { classifySyncError } from '../git/classify-sync-error.js';
|
|
20
|
-
import { requireGit } from '../git/preflight.js';
|
|
21
|
-
import { formatError } from '../utils/format-error.js';
|
|
22
|
-
export async function execClone(client, app, directory, creds) {
|
|
23
|
-
const slug = app.slug || app.name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
|
|
24
|
-
const dir = directory || slug;
|
|
25
|
-
const remoteUrl = client.getGitRemoteUrl(app.workspaceId, app.id);
|
|
26
|
-
// Step 1: Extract skeleton template as the base layer
|
|
27
|
-
console.log('Downloading project template...');
|
|
28
|
-
mkdirSync(dir, { recursive: true });
|
|
29
|
-
try {
|
|
30
|
-
const zipData = await client.downloadSkeleton();
|
|
31
|
-
extractZip(zipData, dir);
|
|
32
|
-
removeNestedGitDirs(dir);
|
|
33
|
-
}
|
|
34
|
-
catch (err) {
|
|
35
|
-
// Surface the real error so we never silently end up with an empty
|
|
36
|
-
// clone directory. The clone is best-effort here -- git fetch may
|
|
37
|
-
// still recover the project below -- but the user should know what
|
|
38
|
-
// went wrong on the way in.
|
|
39
|
-
console.warn(`Failed to download template: ${formatError(err)}`);
|
|
40
|
-
console.warn('Continuing with the git overlay only.');
|
|
41
|
-
}
|
|
42
|
-
// Generate template manifest BEFORE git overlay (captures pristine template checksums)
|
|
43
|
-
const manifest = await generateManifest(dir);
|
|
44
|
-
await saveManifest(dir, manifest);
|
|
45
|
-
// Step 2: Git clone into the directory (overlays changed files on top of template)
|
|
46
|
-
// Init git, add remote, fetch, and checkout to overlay on existing template files
|
|
47
|
-
if (!existsSync(join(dir, '.git'))) {
|
|
48
|
-
try {
|
|
49
|
-
execFileSync('git', ['init'], { cwd: dir, stdio: 'pipe' });
|
|
50
|
-
}
|
|
51
|
-
catch (err) {
|
|
52
|
-
// `stdio: 'pipe'` discards git's stderr, so we have to print the
|
|
53
|
-
// error ourselves -- otherwise this fails silently and the user
|
|
54
|
-
// is left with an empty directory and no clue what happened.
|
|
55
|
-
console.error(`git init failed in ${dir}: ${formatError(err)}`);
|
|
56
|
-
throw err;
|
|
57
|
-
}
|
|
58
|
-
// Force the initial branch to `main` regardless of the user's
|
|
59
|
-
// `init.defaultBranch` config (older Git installs default to
|
|
60
|
-
// `master`). symbolic-ref works before any commits exist.
|
|
61
|
-
try {
|
|
62
|
-
execFileSync('git', ['symbolic-ref', 'HEAD', 'refs/heads/main'], { cwd: dir, stdio: 'pipe' });
|
|
63
|
-
}
|
|
64
|
-
catch { /* best-effort: push uses HEAD:main so this is just cleanliness */ }
|
|
65
|
-
// Disable background gc/maintenance so pack rewrites don't fail on
|
|
66
|
-
// restricted filesystems (e.g. some agent "outputs" mounts). Harmless on
|
|
67
|
-
// normal filesystems. See git/repo-config.ts.
|
|
68
|
-
hardenRepoForRestrictedFs(dir);
|
|
69
|
-
}
|
|
70
|
-
// Seed a local git identity so subsequent commits do not fail on machines
|
|
71
|
-
// (commonly fresh Windows installs) without `git config --global user.email`.
|
|
72
|
-
ensureGitIdentity(dir, creds);
|
|
73
|
-
// Make sure git can authenticate to the runwork remote before we fetch.
|
|
74
|
-
// Headless auth paths (the get_cli_setup MCP tool, or a hand-written
|
|
75
|
-
// ~/.runwork/.credentials) register API creds but not the git helper, so
|
|
76
|
-
// without this the fetch below silently fails and we fall back to a
|
|
77
|
-
// template-only scaffold. See git/credentials.ts:ensureGitCredentialHelper.
|
|
78
|
-
if (creds?.baseUrl) {
|
|
79
|
-
await ensureGitCredentialHelper(creds.baseUrl);
|
|
80
|
-
}
|
|
81
|
-
ensureRunworkRemote(dir, remoteUrl);
|
|
82
|
-
let source = { pulled: true };
|
|
83
|
-
try {
|
|
84
|
-
execFileSync('git', ['fetch', 'runwork', 'main'], { cwd: dir, stdio: 'pipe' });
|
|
85
|
-
// Reset to remote HEAD - overlays git-tracked files on top of template
|
|
86
|
-
execFileSync('git', ['reset', '--mixed', 'runwork/main'], { cwd: dir, stdio: 'pipe' });
|
|
87
|
-
// Checkout git-tracked files (overwrites template files where they differ)
|
|
88
|
-
execFileSync('git', ['checkout', '.'], { cwd: dir, stdio: 'pipe' });
|
|
89
|
-
}
|
|
90
|
-
catch (err) {
|
|
91
|
-
source = pullOutcomeFromError(err);
|
|
92
|
-
if (source.reason === 'empty-remote') {
|
|
93
|
-
// Brand-new app: the remote has no `main` branch yet. Expected and
|
|
94
|
-
// benign -- the template scaffold IS the starting point.
|
|
95
|
-
console.warn('No source pushed for this app yet. Starting from the template scaffold.');
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
// A real failure (auth, missing remote, network). The scaffold here is
|
|
99
|
-
// NOT the app's code -- surface it loudly so the caller fails instead of
|
|
100
|
-
// silently editing the wrong files.
|
|
101
|
-
console.warn('Could not pull the app source from the runwork remote.');
|
|
102
|
-
console.warn(` ${formatError(err)}`);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
// Write .runwork.json config
|
|
106
|
-
const config = {
|
|
107
|
-
workspaceId: app.workspaceId,
|
|
108
|
-
workspaceName: app.workspaceName,
|
|
109
|
-
appId: app.id,
|
|
110
|
-
appName: app.name,
|
|
111
|
-
};
|
|
112
|
-
writeFileSync(join(dir, '.runwork.json'), JSON.stringify(config, null, 2));
|
|
113
|
-
// Fetch SKILL.md (best-effort)
|
|
114
|
-
try {
|
|
115
|
-
const { skill } = await client.getAppSkill(app.id);
|
|
116
|
-
if (skill) {
|
|
117
|
-
writeFileSync(join(dir, 'SKILL.md'), skill, 'utf-8');
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
catch {
|
|
121
|
-
// App may be new with no registries yet
|
|
122
|
-
}
|
|
123
|
-
return {
|
|
124
|
-
appId: app.id,
|
|
125
|
-
appName: app.name,
|
|
126
|
-
slug,
|
|
127
|
-
directory: resolve(dir),
|
|
128
|
-
workspaceId: app.workspaceId,
|
|
129
|
-
workspaceName: app.workspaceName,
|
|
130
|
-
source,
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
/** Pull the raw git stderr off an execFileSync error for classification. */
|
|
134
|
-
function extractStderr(err) {
|
|
135
|
-
const e = err;
|
|
136
|
-
if (e?.stderr)
|
|
137
|
-
return e.stderr.toString().trim();
|
|
138
|
-
return formatError(err);
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* Whether a failed `git fetch runwork main` means the remote simply has no
|
|
142
|
-
* `main` branch yet (a brand-new app), as opposed to an auth/network/remote
|
|
143
|
-
* failure. Git reports this as "couldn't find remote ref main".
|
|
144
|
-
*/
|
|
145
|
-
function isEmptyRemote(stderr) {
|
|
146
|
-
const s = stderr.toLowerCase();
|
|
147
|
-
return s.includes("couldn't find remote ref") || s.includes('could not find remote ref');
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* Turn a failed-pull error into a CloneSource: an empty remote (benign,
|
|
151
|
-
* brand-new app) vs a classified real failure (auth/network/no-remote) that
|
|
152
|
-
* leaves a template-only scaffold.
|
|
153
|
-
*/
|
|
154
|
-
export function pullOutcomeFromError(err) {
|
|
155
|
-
const detail = extractStderr(err);
|
|
156
|
-
if (isEmptyRemote(detail)) {
|
|
157
|
-
return { pulled: false, reason: 'empty-remote', detail };
|
|
158
|
-
}
|
|
159
|
-
return { pulled: false, reason: classifySyncError(detail), detail };
|
|
160
|
-
}
|
|
161
|
-
/**
|
|
162
|
-
* A clone is a real failure -- a template-only scaffold rather than the app's
|
|
163
|
-
* code -- when the source pull didn't happen for any reason other than an
|
|
164
|
-
* empty remote. Callers must not report success in that case.
|
|
165
|
-
*/
|
|
166
|
-
export function isCloneSourceFailure(source) {
|
|
167
|
-
return !source.pulled && source.reason !== 'empty-remote';
|
|
168
|
-
}
|
|
169
|
-
/**
|
|
170
|
-
* Reconcile positional args with --app. When --app is provided, the first
|
|
171
|
-
* positional argument is intended as the *directory* -- not another appId
|
|
172
|
-
* -- because the app is already disambiguated by the option. Without this,
|
|
173
|
-
* `runwork clone --app foo C:\path\to\dir` ends up parsing `C:\path\to\dir`
|
|
174
|
-
* as `appId` (which is then ignored because `--app` wins), leaving
|
|
175
|
-
* `directory` undefined and silently cloning into the slug under cwd.
|
|
176
|
-
*/
|
|
177
|
-
export function normalizeCloneArgs(appId, directory, options) {
|
|
178
|
-
if (options?.app && appId && !directory) {
|
|
179
|
-
return { appId: undefined, directory: appId };
|
|
180
|
-
}
|
|
181
|
-
return { appId, directory };
|
|
182
|
-
}
|
|
183
|
-
/**
|
|
184
|
-
* Help epilogue shown under `runwork clone --help`. Agents tend to read help
|
|
185
|
-
* before running, so we surface the restricted-mount caveat (friction log #9)
|
|
186
|
-
* here. Exported so it can be asserted on directly (commander's help-text
|
|
187
|
-
* hooks aren't reflected by `helpInformation()`).
|
|
188
|
-
*/
|
|
189
|
-
export const RESTRICTED_FS_HELP = `
|
|
190
|
-
Note for AI agents: clone into a normal working directory. Some sandboxed
|
|
191
|
-
"outputs" mounts (e.g. certain agent environments) disallow the unlink
|
|
192
|
-
operations git uses for pack files, which can corrupt the repo with errors
|
|
193
|
-
like "unable to unlink '.git/objects/pack/...': Operation not permitted". If
|
|
194
|
-
you hit that, clone into your home directory or another standard path instead.`;
|
|
195
|
-
export const cloneCommand = new Command('clone')
|
|
196
|
-
.description('Clone a Runwork app to local development')
|
|
197
|
-
.argument('[appId]', 'App ID to clone (interactive if omitted)')
|
|
198
|
-
.argument('[directory]', 'Target directory')
|
|
199
|
-
.option('--app <name-or-id>', 'App name or ID (skips interactive selection)')
|
|
200
|
-
.addHelpText('after', RESTRICTED_FS_HELP)
|
|
201
|
-
.action(async (rawAppId, rawDirectory, options) => {
|
|
202
|
-
requireGit('clone');
|
|
203
|
-
const { appId, directory } = normalizeCloneArgs(rawAppId, rawDirectory, options);
|
|
204
|
-
const creds = requireAuth();
|
|
205
|
-
const client = new ApiClient(creds);
|
|
206
|
-
const useJson = shouldOutputJson(undefined);
|
|
207
|
-
let app;
|
|
208
|
-
const appRef = options?.app || appId;
|
|
209
|
-
if (appRef) {
|
|
210
|
-
app = await resolveApp(client, appRef);
|
|
211
|
-
}
|
|
212
|
-
else {
|
|
213
|
-
const apps = await client.listApps();
|
|
214
|
-
if (apps.length === 0) {
|
|
215
|
-
if (useJson) {
|
|
216
|
-
jsonOut(buildErrorResponse('clone', 'No apps found', 'No apps are available to clone.', ['Create an app first with: runwork init my-app']));
|
|
217
|
-
return;
|
|
218
|
-
}
|
|
219
|
-
console.error('No apps found.');
|
|
220
|
-
process.exit(1);
|
|
221
|
-
}
|
|
222
|
-
const choice = await promptSelect('Select app to clone:', apps.map(a => ({ label: `${a.name} (${a.workspaceName})`, value: a })));
|
|
223
|
-
app = choice.value;
|
|
224
|
-
}
|
|
225
|
-
if (!useJson) {
|
|
226
|
-
console.log(`Cloning "${app.name}"...`);
|
|
227
|
-
}
|
|
228
|
-
const cloneResult = await execClone(client, app, directory, creds);
|
|
229
|
-
// A real pull failure (auth/network/missing-remote) left a template-only
|
|
230
|
-
// scaffold that is NOT the app's deployed code. Report it as a failure so
|
|
231
|
-
// an agent doesn't start editing the wrong files (friction log #1).
|
|
232
|
-
const pullFailed = isCloneSourceFailure(cloneResult.source);
|
|
233
|
-
if (useJson) {
|
|
234
|
-
if (pullFailed) {
|
|
235
|
-
jsonOut(buildErrorResponse('clone', 'Cloned the scaffold but could not pull the app source', `git could not fetch the app's source (${cloneResult.source.reason}), so the directory holds only the template scaffold, not the deployed code. ${cloneResult.source.detail ?? ''}`.trim(), [
|
|
236
|
-
'Run `runwork doctor --fix` to repair git auth and the runwork remote',
|
|
237
|
-
`Then re-clone: runwork clone --app ${cloneResult.appName}`,
|
|
238
|
-
]));
|
|
239
|
-
process.exit(1);
|
|
240
|
-
}
|
|
241
|
-
const response = {
|
|
242
|
-
success: true,
|
|
243
|
-
command: 'clone',
|
|
244
|
-
result: cloneResult,
|
|
245
|
-
warning: cloneResult.source.reason === 'empty-remote'
|
|
246
|
-
? 'This app has no source pushed yet. The directory is the starting template scaffold.'
|
|
247
|
-
: undefined,
|
|
248
|
-
guide: buildCloneGuide(cloneResult.appName, cloneResult.slug),
|
|
249
|
-
};
|
|
250
|
-
jsonOut(response);
|
|
251
|
-
return;
|
|
252
|
-
}
|
|
253
|
-
if (pullFailed) {
|
|
254
|
-
console.error(`\nCloned the scaffold for "${cloneResult.appName}", but could NOT pull the app source (${cloneResult.source.reason}).`);
|
|
255
|
-
console.error('The directory holds only the template scaffold, not the deployed code.');
|
|
256
|
-
console.error('Fix git access, then re-clone:');
|
|
257
|
-
console.error(' runwork doctor --fix');
|
|
258
|
-
console.error(` runwork clone --app ${cloneResult.appName}`);
|
|
259
|
-
process.exit(1);
|
|
260
|
-
}
|
|
261
|
-
// No trailing separator: cloneResult.directory is already an absolute
|
|
262
|
-
// path. Appending '/' here mixed with Windows '\' separators produced
|
|
263
|
-
// confusing output like `C:\Users\...\app/` on Windows.
|
|
264
|
-
console.log(`\nApp "${cloneResult.appName}" cloned to ${cloneResult.directory}`);
|
|
265
|
-
if (cloneResult.source.reason === 'empty-remote') {
|
|
266
|
-
console.log('Note: no source pushed for this app yet. Starting from the template scaffold.');
|
|
267
|
-
}
|
|
268
|
-
console.log(`Remote: ${client.getGitRemoteUrl(cloneResult.workspaceId, cloneResult.appId)}`);
|
|
269
|
-
await runAgentWizard(cloneResult.directory);
|
|
270
|
-
console.log(`Next: cd ${cloneResult.slug} && runwork dev`);
|
|
271
|
-
});
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import { requireAuth } from '../auth/store.js';
|
|
3
|
-
import { ApiClient } from '../api/client.js';
|
|
4
|
-
import { resolveWorkspace } from '../workspace/resolve.js';
|
|
5
|
-
import { shouldOutputJson, jsonOut } from '../utils/output.js';
|
|
6
|
-
const listCommand = new Command('list')
|
|
7
|
-
.description('List components registered in the workspace')
|
|
8
|
-
.option('--workspace <id>', 'Workspace ID')
|
|
9
|
-
.option('--app <id>', 'Filter by app name or ID')
|
|
10
|
-
.action(async (opts, command) => {
|
|
11
|
-
const useJson = shouldOutputJson(command.optsWithGlobals().json);
|
|
12
|
-
const credentials = requireAuth();
|
|
13
|
-
const client = new ApiClient(credentials);
|
|
14
|
-
const { workspaceId, workspaceName } = await resolveWorkspace(client, opts);
|
|
15
|
-
try {
|
|
16
|
-
let components = await client.listComponents(workspaceId);
|
|
17
|
-
if (opts.app) {
|
|
18
|
-
components = components.filter(c => c.appId === opts.app || c.appName === opts.app);
|
|
19
|
-
}
|
|
20
|
-
if (useJson) {
|
|
21
|
-
jsonOut({ components });
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
if (components.length === 0) {
|
|
25
|
-
console.log('No components found in this workspace.');
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
console.log(`\nWorkspace: ${workspaceName || workspaceId}\n`);
|
|
29
|
-
console.log(` ${'Component'.padEnd(28)} ${'App'.padEnd(24)} ${'Mode'.padEnd(12)}`);
|
|
30
|
-
console.log(' ' + '-'.repeat(66));
|
|
31
|
-
for (const c of components) {
|
|
32
|
-
console.log(` ${c.componentName.padEnd(28)} ${c.appName.padEnd(24)} ${(c.deploymentMode ?? '').padEnd(12)}`);
|
|
33
|
-
}
|
|
34
|
-
console.log('');
|
|
35
|
-
}
|
|
36
|
-
catch (err) {
|
|
37
|
-
console.error('Failed to list components:', err instanceof Error ? err.message : err);
|
|
38
|
-
process.exit(1);
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
export const componentsCommand = new Command('components')
|
|
42
|
-
.description('List workspace components')
|
|
43
|
-
.addCommand(listCommand);
|
package/dist/commands/deploy.js
DELETED
|
@@ -1,279 +0,0 @@
|
|
|
1
|
-
import { Command, Option } from 'commander';
|
|
2
|
-
import { readFileSync, existsSync } from 'fs';
|
|
3
|
-
import { requireAuth } from '../auth/store.js';
|
|
4
|
-
import { ApiClient } from '../api/client.js';
|
|
5
|
-
import { shouldOutputJson, jsonOut, jsonLine } from '../utils/output.js';
|
|
6
|
-
import { dim, green, yellow } from '../ui/colors.js';
|
|
7
|
-
import { getHeadSha, writeDeployState, getDeploySummary } from '../deploy/deploy-state.js';
|
|
8
|
-
import { writeDeployStatus, readDeployStatus, deployLogPath } from '../deploy/deploy-status.js';
|
|
9
|
-
import { isInternalDeployChild, buildDeployChildArgs, spawnDetachedDeploy, DEPLOY_DETACHED_CHILD_FLAG } from '../deploy/detach.js';
|
|
10
|
-
import { buildDeployGuide, buildErrorResponse } from '../utils/agent-guidance.js';
|
|
11
|
-
import { requireGit } from '../git/preflight.js';
|
|
12
|
-
import { ensureGitIdentity } from '../git/identity.js';
|
|
13
|
-
import { ensureGitCredentialHelper } from '../git/credentials.js';
|
|
14
|
-
import { ensureRunworkRemote } from '../git/remote.js';
|
|
15
|
-
import { diagnoseSyncError } from '../git/classify-sync-error.js';
|
|
16
|
-
import { commitWorkingTree } from '../git/auto-commit.js';
|
|
17
|
-
import { syncWithRemote, hasCommits } from '../git/sync.js';
|
|
18
|
-
import { snapshotCriticalFiles, restoreMissingCriticalFiles, commitAndPushRestoredFiles } from '../git/critical-files.js';
|
|
19
|
-
import { evaluateDeployGuard } from '../git/deploy-guard.js';
|
|
20
|
-
import { promptConfirm } from '../utils/prompt.js';
|
|
21
|
-
export const deployCommand = new Command('deploy')
|
|
22
|
-
.description('Deploy the current app to production')
|
|
23
|
-
.option('-y, --yes', 'Skip the confirmation prompt when the working tree differs from the preview')
|
|
24
|
-
.option('--detach', 'Run the deploy in the background and return immediately. Logs go to .runwork/deploy-{stdout,stderr}.log; poll `runwork deploy --status`.')
|
|
25
|
-
.option('--status', 'Show the status (in-progress/succeeded/failed) of the last deploy started from this machine, plus the deployed-vs-local commit.')
|
|
26
|
-
// Hidden marker the `--detach` parent passes to its background child. Not
|
|
27
|
-
// for end users -- registered so commander accepts it on the child.
|
|
28
|
-
.addOption(new Option(DEPLOY_DETACHED_CHILD_FLAG).hideHelp())
|
|
29
|
-
.action(async (opts, command) => {
|
|
30
|
-
const useJson = shouldOutputJson(command.optsWithGlobals().json);
|
|
31
|
-
const cwd = process.cwd();
|
|
32
|
-
if (!existsSync('.runwork.json')) {
|
|
33
|
-
if (useJson) {
|
|
34
|
-
jsonOut(buildErrorResponse('deploy', 'No .runwork.json found', 'This directory is not a Runwork app.', ['Run runwork init to create an app first', 'Or cd into an existing app directory']));
|
|
35
|
-
process.exit(1);
|
|
36
|
-
}
|
|
37
|
-
console.error('No .runwork.json found. Run `runwork init` first.');
|
|
38
|
-
process.exit(1);
|
|
39
|
-
}
|
|
40
|
-
// --status: a local read; no auth/git required.
|
|
41
|
-
if (opts.status) {
|
|
42
|
-
printDeployStatus(cwd, useJson);
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
requireGit('deploy');
|
|
46
|
-
const config = JSON.parse(readFileSync('.runwork.json', 'utf-8'));
|
|
47
|
-
const isChild = isInternalDeployChild(process.argv);
|
|
48
|
-
// --detach parent: spawn a background child running the real deploy,
|
|
49
|
-
// record an in-progress status, print a poll hint, and exit immediately so
|
|
50
|
-
// the launching shell doesn't time out (friction log #7).
|
|
51
|
-
if (opts.detach && !isChild) {
|
|
52
|
-
const startedAt = new Date().toISOString();
|
|
53
|
-
const handle = spawnDetachedDeploy(buildDeployChildArgs(process.argv), cwd);
|
|
54
|
-
writeDeployStatus(cwd, { state: 'in-progress', startedAt, pid: handle.pid });
|
|
55
|
-
if (useJson) {
|
|
56
|
-
jsonLine({ event: 'deploy_started', detached: true, pid: handle.pid, logPath: deployLogPath(cwd), startedAt, hint: 'Poll `runwork deploy --status` for completion.' });
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
console.log(`Deploy started in the background (pid ${handle.pid}).`);
|
|
60
|
-
console.log(`Logs: ${deployLogPath(cwd)}`);
|
|
61
|
-
console.log('Check: runwork deploy --status');
|
|
62
|
-
}
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
// The detached child finalizes the status file on exit. If it crashes or
|
|
66
|
-
// hits any `process.exit(1)` failure path before the success block marks
|
|
67
|
-
// it done, record `failed` so `--status` doesn't report a stuck deploy.
|
|
68
|
-
// Register this BEFORE requireAuth(): a child whose credentials expired
|
|
69
|
-
// between spawn and run would otherwise exit in requireAuth() with the
|
|
70
|
-
// status stuck at `in-progress`. (requireGit/config above ran identically
|
|
71
|
-
// in the parent before it spawned this child, so they can't fail here.)
|
|
72
|
-
let deployFinalized = false;
|
|
73
|
-
const childStartedAt = readDeployStatus(cwd)?.startedAt ?? new Date().toISOString();
|
|
74
|
-
if (isChild) {
|
|
75
|
-
jsonLine({ event: 'deploy_started', startedAt: childStartedAt });
|
|
76
|
-
process.on('exit', (code) => {
|
|
77
|
-
if (!deployFinalized && code !== 0) {
|
|
78
|
-
writeDeployStatus(cwd, { state: 'failed', startedAt: childStartedAt, finishedAt: new Date().toISOString(), error: `deploy process exited with code ${code}` });
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
const creds = requireAuth();
|
|
83
|
-
const client = new ApiClient(creds);
|
|
84
|
-
// Deploy guard: the preview reflects the last *pushed* commit. If the
|
|
85
|
-
// working tree is dirty or ahead of `runwork/main` and no auto-syncing
|
|
86
|
-
// dev session is keeping the preview in lockstep, `runwork deploy` will
|
|
87
|
-
// commit and ship code the user never saw in the preview. Warn first.
|
|
88
|
-
// Runs BEFORE the commit/sync/deploy steps below, which are unchanged.
|
|
89
|
-
const guard = evaluateDeployGuard(cwd, config.appId);
|
|
90
|
-
let deployGuardWarning;
|
|
91
|
-
if (guard.warn) {
|
|
92
|
-
deployGuardWarning = 'You have uncommitted or unpushed changes. `runwork deploy` will commit and deploy them, but they are not reflected in the preview.';
|
|
93
|
-
if (useJson) {
|
|
94
|
-
// Agents must never be blocked: the warning rides along in the
|
|
95
|
-
// final success response below so we proceed without prompting.
|
|
96
|
-
}
|
|
97
|
-
else if (opts.yes || isChild || !process.stdin.isTTY) {
|
|
98
|
-
// Non-interactive (no TTY), the detached child, or explicit --yes:
|
|
99
|
-
// warn and proceed without prompting.
|
|
100
|
-
console.warn(deployGuardWarning);
|
|
101
|
-
}
|
|
102
|
-
else {
|
|
103
|
-
console.warn(deployGuardWarning);
|
|
104
|
-
const proceed = await promptConfirm('Deploy these changes anyway?');
|
|
105
|
-
if (!proceed) {
|
|
106
|
-
console.log('Deploy cancelled.');
|
|
107
|
-
process.exit(0);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
// Deploy must work even when no `runwork dev` session is (or ever was)
|
|
112
|
-
// running. Reuse the exact sync path dev uses: commit any pending
|
|
113
|
-
// working-tree changes, then fetch -> rebase (fallback merge) -> push.
|
|
114
|
-
// `ensureGitIdentity` seeds a local identity so the commit cannot fail
|
|
115
|
-
// on a fresh machine where git user.email/.name were never configured.
|
|
116
|
-
ensureGitIdentity(cwd, creds);
|
|
117
|
-
// Ensure git can authenticate to the runwork remote before sync/push.
|
|
118
|
-
// Headless auth (get_cli_setup / hand-written credentials) registers API
|
|
119
|
-
// creds but not the git helper. See
|
|
120
|
-
// git/credentials.ts:ensureGitCredentialHelper.
|
|
121
|
-
if (creds?.baseUrl) {
|
|
122
|
-
await ensureGitCredentialHelper(creds.baseUrl);
|
|
123
|
-
}
|
|
124
|
-
// Ensure the `runwork` remote exists and points at the canonical URL, so a
|
|
125
|
-
// manually `git clone`d repo (remote named `origin`) still syncs/pushes.
|
|
126
|
-
ensureRunworkRemote(cwd, client.getGitRemoteUrl(config.workspaceId, config.appId));
|
|
127
|
-
if (!useJson)
|
|
128
|
-
console.log('Syncing...');
|
|
129
|
-
try {
|
|
130
|
-
commitWorkingTree(cwd, `deploy: ${new Date().toISOString().replace('T', ' ').slice(0, 19)}`);
|
|
131
|
-
}
|
|
132
|
-
catch {
|
|
133
|
-
// No commit created (clean tree) or git not initialized yet. The
|
|
134
|
-
// sync/push step below surfaces the actionable failure.
|
|
135
|
-
}
|
|
136
|
-
if (!hasCommits(cwd)) {
|
|
137
|
-
if (useJson) {
|
|
138
|
-
jsonOut(buildErrorResponse('deploy', 'Nothing to deploy', 'No commits exist and the working tree has no changes to commit, so there is nothing to sync or deploy.', ['Make changes to your app first', 'Run runwork dev to develop and verify changes', 'Then run runwork deploy']));
|
|
139
|
-
process.exit(1);
|
|
140
|
-
}
|
|
141
|
-
console.error('Nothing to deploy. Make changes first, then run `runwork deploy`.');
|
|
142
|
-
process.exit(1);
|
|
143
|
-
}
|
|
144
|
-
// Protect critical files across the sync exactly as `runwork dev` does:
|
|
145
|
-
// syncWithRemote may merge with `-X theirs` (remote wins) to reconcile
|
|
146
|
-
// diverged histories, which can delete `.runwork.json`/`blueprint.json`/
|
|
147
|
-
// `.gitignore` if the remote tip lacks them. Snapshot before, restore after.
|
|
148
|
-
const criticalSnapshot = snapshotCriticalFiles(cwd);
|
|
149
|
-
const syncResult = syncWithRemote(cwd);
|
|
150
|
-
const restoredCriticalFiles = restoreMissingCriticalFiles(cwd, criticalSnapshot);
|
|
151
|
-
if (restoredCriticalFiles.length > 0) {
|
|
152
|
-
const pushed = commitAndPushRestoredFiles(cwd, restoredCriticalFiles);
|
|
153
|
-
if (!useJson) {
|
|
154
|
-
console.warn(`Sync removed critical file(s); restored: ${restoredCriticalFiles.join(', ')}`);
|
|
155
|
-
if (!pushed)
|
|
156
|
-
console.warn('Restoration committed locally but not pushed; will retry on next sync.');
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
if (syncResult.status === 'sync-failed') {
|
|
160
|
-
const diag = diagnoseSyncError(syncResult.error);
|
|
161
|
-
if (useJson) {
|
|
162
|
-
jsonOut(buildErrorResponse('deploy', 'Sync failed before deployment', diag.diagnosis, [...diag.suggestions, 'Then retry runwork deploy']));
|
|
163
|
-
process.exit(1);
|
|
164
|
-
}
|
|
165
|
-
console.error(`Sync failed: ${diag.message}. ${diag.diagnosis}`);
|
|
166
|
-
for (const s of diag.suggestions)
|
|
167
|
-
console.error(` - ${s}`);
|
|
168
|
-
process.exit(1);
|
|
169
|
-
}
|
|
170
|
-
if (!syncResult.pushed) {
|
|
171
|
-
if (useJson) {
|
|
172
|
-
jsonOut(buildErrorResponse('deploy', 'Failed to push before deployment', 'Local commits were synced but could not be pushed to the remote.', ['Check your network connection', 'Run runwork dev to retry syncing', 'Then retry runwork deploy']));
|
|
173
|
-
process.exit(1);
|
|
174
|
-
}
|
|
175
|
-
console.error('Push failed. Check your connection and retry `runwork deploy`.');
|
|
176
|
-
process.exit(1);
|
|
177
|
-
}
|
|
178
|
-
// Trigger deploy
|
|
179
|
-
if (!useJson)
|
|
180
|
-
console.log('Deploying...');
|
|
181
|
-
let result;
|
|
182
|
-
try {
|
|
183
|
-
result = await client.triggerDeploy(config.appId);
|
|
184
|
-
}
|
|
185
|
-
catch (err) {
|
|
186
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
187
|
-
if (useJson) {
|
|
188
|
-
jsonOut(buildErrorResponse('deploy', message, 'The deployment API returned an error.', ['Check for TypeScript errors in your code', 'Run runwork dev to test in the sandbox first', 'Retry runwork deploy']));
|
|
189
|
-
process.exit(1);
|
|
190
|
-
}
|
|
191
|
-
console.error(`Deploy failed: ${message}`);
|
|
192
|
-
process.exit(1);
|
|
193
|
-
}
|
|
194
|
-
// The server returns a deployment URL only when a deploy actually
|
|
195
|
-
// happened. An empty/missing URL means the deploy was a no-op or did
|
|
196
|
-
// not produce a live deployment, so we must not report success.
|
|
197
|
-
const deploymentUrl = result.deploymentUrl?.trim() ?? '';
|
|
198
|
-
const deployed = deploymentUrl.length > 0;
|
|
199
|
-
if (!deployed) {
|
|
200
|
-
if (useJson) {
|
|
201
|
-
jsonOut(buildErrorResponse('deploy', 'Deployment did not produce a URL', 'The deploy API returned no deployment URL. The deploy may have been a no-op (no changes) or failed server-side.', ['Confirm your changes were committed and pushed (the sync step above succeeded)', 'Run runwork info to check the deployed state', 'Run runwork logs --production to inspect server-side errors', 'Retry runwork deploy']));
|
|
202
|
-
process.exit(1);
|
|
203
|
-
}
|
|
204
|
-
console.error('Deploy did not return a URL. The deploy may have been a no-op or failed server-side.');
|
|
205
|
-
console.error('Run `runwork info` to check state, or `runwork logs --production` to inspect errors.');
|
|
206
|
-
process.exit(1);
|
|
207
|
-
}
|
|
208
|
-
// Record what we just deployed (local HEAD == the pushed/deployed commit)
|
|
209
|
-
// so `runwork info` / `deploy --status` can cheaply compare it to HEAD
|
|
210
|
-
// later without scraping the production bundle.
|
|
211
|
-
const deployedSha = getHeadSha(cwd);
|
|
212
|
-
const finishedAt = new Date().toISOString();
|
|
213
|
-
if (deployedSha) {
|
|
214
|
-
writeDeployState(cwd, { sha: deployedSha, deployedAt: finishedAt, url: deploymentUrl });
|
|
215
|
-
}
|
|
216
|
-
// Mark the deploy finished so the child's exit hook doesn't overwrite this
|
|
217
|
-
// with a `failed` status, and so `runwork deploy --status` reports success.
|
|
218
|
-
deployFinalized = true;
|
|
219
|
-
writeDeployStatus(cwd, { state: 'succeeded', startedAt: childStartedAt, finishedAt, url: deploymentUrl, sha: deployedSha ?? undefined });
|
|
220
|
-
if (isChild) {
|
|
221
|
-
jsonLine({ event: 'deploy_succeeded', url: deploymentUrl, deployedSha, finishedAt });
|
|
222
|
-
}
|
|
223
|
-
if (useJson) {
|
|
224
|
-
const response = {
|
|
225
|
-
success: true,
|
|
226
|
-
command: 'deploy',
|
|
227
|
-
result: {
|
|
228
|
-
deployed,
|
|
229
|
-
url: deploymentUrl,
|
|
230
|
-
appName: config.appName,
|
|
231
|
-
deployedSha,
|
|
232
|
-
},
|
|
233
|
-
guide: buildDeployGuide(),
|
|
234
|
-
...(deployGuardWarning ? { warning: deployGuardWarning } : {}),
|
|
235
|
-
};
|
|
236
|
-
jsonOut(response);
|
|
237
|
-
return;
|
|
238
|
-
}
|
|
239
|
-
console.log(`Deployed: ${deploymentUrl}`);
|
|
240
|
-
if (deployedSha)
|
|
241
|
-
console.log(dim(`Commit: ${deployedSha.slice(0, 7)}`));
|
|
242
|
-
});
|
|
243
|
-
/**
|
|
244
|
-
* Print the status of the last deploy started from this machine
|
|
245
|
-
* (`runwork deploy --status`), reconciled with the deployed-vs-local commit
|
|
246
|
-
* comparison from deploy-state.
|
|
247
|
-
*/
|
|
248
|
-
function printDeployStatus(cwd, useJson) {
|
|
249
|
-
const status = readDeployStatus(cwd);
|
|
250
|
-
const summary = getDeploySummary(cwd);
|
|
251
|
-
if (useJson) {
|
|
252
|
-
jsonOut({ success: true, command: 'deploy', result: { status, deploy: summary } });
|
|
253
|
-
return;
|
|
254
|
-
}
|
|
255
|
-
if (!status) {
|
|
256
|
-
console.log('No deploy has been started from this machine yet.');
|
|
257
|
-
}
|
|
258
|
-
else {
|
|
259
|
-
const label = status.state === 'succeeded' ? green('succeeded')
|
|
260
|
-
: status.state === 'failed' ? yellow('failed')
|
|
261
|
-
: 'in-progress';
|
|
262
|
-
console.log(`Last deploy: ${label}`);
|
|
263
|
-
console.log(dim(` started: ${status.startedAt}`));
|
|
264
|
-
if (status.finishedAt)
|
|
265
|
-
console.log(dim(` finished: ${status.finishedAt}`));
|
|
266
|
-
if (status.url)
|
|
267
|
-
console.log(dim(` url: ${status.url}`));
|
|
268
|
-
if (status.error)
|
|
269
|
-
console.log(yellow(` error: ${status.error}`));
|
|
270
|
-
if (status.state === 'in-progress')
|
|
271
|
-
console.log(dim(` logs: ${deployLogPath(cwd)}`));
|
|
272
|
-
}
|
|
273
|
-
if (summary.deployedShortSha) {
|
|
274
|
-
const sync = summary.inSync === true ? green('in sync')
|
|
275
|
-
: summary.inSync === false ? yellow('local has undeployed commits')
|
|
276
|
-
: dim('unknown');
|
|
277
|
-
console.log(`Commit: deployed ${summary.deployedShortSha}${summary.localShortSha ? `, local ${summary.localShortSha}` : ''} ${sync}`);
|
|
278
|
-
}
|
|
279
|
-
}
|
package/dist/commands/dev.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import { type SessionMode } from '../dev/session.js';
|
|
3
|
-
export declare function execDev(options?: {
|
|
4
|
-
logs?: boolean;
|
|
5
|
-
logsOnlyFile?: boolean;
|
|
6
|
-
json?: boolean;
|
|
7
|
-
mode?: SessionMode;
|
|
8
|
-
restart?: boolean;
|
|
9
|
-
noSync?: boolean;
|
|
10
|
-
}): Promise<void>;
|
|
11
|
-
export declare const devCommand: Command;
|