runwork 0.15.1 → 0.16.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/bundled-types/task-delegation/task-delegation/types.d.ts +6 -0
- package/dist/index.js +20237 -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 -105
- 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 -59
- package/dist/agents/claude-code.js +0 -753
- 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 -35
- package/dist/agents/cursor.js +0 -294
- 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 -87
- package/dist/agents/defaults-merge.js +0 -150
- 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/git/preflight.js
DELETED
|
@@ -1,276 +0,0 @@
|
|
|
1
|
-
import { execFileSync } from '../utils/subprocess.js';
|
|
2
|
-
import { existsSync } from 'fs';
|
|
3
|
-
import { win32 as winPath } from 'path';
|
|
4
|
-
import { homedir } from 'os';
|
|
5
|
-
const VERSION_REGEX = /(\d+\.\d+(?:\.\d+)?)/;
|
|
6
|
-
function tryRun(bin) {
|
|
7
|
-
try {
|
|
8
|
-
const out = execFileSync(bin, ['--version'], { stdio: ['ignore', 'pipe', 'pipe'] });
|
|
9
|
-
return { ok: true, version: out.toString('utf-8').trim() };
|
|
10
|
-
}
|
|
11
|
-
catch (err) {
|
|
12
|
-
return { ok: false, error: err };
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
function whereGit() {
|
|
16
|
-
if (process.platform !== 'win32')
|
|
17
|
-
return null;
|
|
18
|
-
try {
|
|
19
|
-
// No `encoding: 'utf-8'` on purpose: keep the return as a Buffer to
|
|
20
|
-
// match tryRun()'s shape. We toString() ourselves so test mocks can
|
|
21
|
-
// return Buffers uniformly.
|
|
22
|
-
const buf = execFileSync('where.exe', ['git'], {
|
|
23
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
24
|
-
windowsHide: true,
|
|
25
|
-
});
|
|
26
|
-
const out = buf.toString('utf-8');
|
|
27
|
-
// `where.exe git` may print multiple matches (cmd shim, exe shim).
|
|
28
|
-
// Prefer git.exe -- the bare shim is a .cmd that's harder to invoke
|
|
29
|
-
// reliably from spawn() and that mismatch is exactly what we're trying
|
|
30
|
-
// to work around.
|
|
31
|
-
const lines = out.split(/\r?\n/).map(line => line.trim()).filter(Boolean);
|
|
32
|
-
const exe = lines.find(line => /\.exe$/i.test(line));
|
|
33
|
-
if (exe && existsSync(exe))
|
|
34
|
-
return exe;
|
|
35
|
-
const fallback = lines.find(line => existsSync(line));
|
|
36
|
-
return fallback ?? null;
|
|
37
|
-
}
|
|
38
|
-
catch {
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Query Git for Windows' registry keys for an InstallPath.
|
|
44
|
-
*
|
|
45
|
-
* The official Git for Windows installer always writes
|
|
46
|
-
* `HKLM\SOFTWARE\GitForWindows\InstallPath` (system installs) or
|
|
47
|
-
* `HKCU\Software\GitForWindows\InstallPath` (per-user installs). When that
|
|
48
|
-
* value points at e.g. `C:\Program Files\Git`, the binary lives at
|
|
49
|
-
* `<value>\cmd\git.exe`. Portable / non-installer Gits (MinGit, Scoop,
|
|
50
|
-
* GitHub Desktop's bundled git) won't appear here -- they're covered by
|
|
51
|
-
* canonicalGitCandidates().
|
|
52
|
-
*/
|
|
53
|
-
function registryGit() {
|
|
54
|
-
if (process.platform !== 'win32')
|
|
55
|
-
return null;
|
|
56
|
-
const queries = [
|
|
57
|
-
['HKLM\\SOFTWARE\\GitForWindows', '/v', 'InstallPath'],
|
|
58
|
-
['HKCU\\Software\\GitForWindows', '/v', 'InstallPath'],
|
|
59
|
-
];
|
|
60
|
-
for (const args of queries) {
|
|
61
|
-
try {
|
|
62
|
-
const buf = execFileSync('reg.exe', ['query', ...args], {
|
|
63
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
64
|
-
windowsHide: true,
|
|
65
|
-
});
|
|
66
|
-
const out = buf.toString('utf-8');
|
|
67
|
-
// Output shape:
|
|
68
|
-
// HKEY_LOCAL_MACHINE\SOFTWARE\GitForWindows
|
|
69
|
-
// InstallPath REG_SZ C:\Program Files\Git
|
|
70
|
-
const match = out.match(/InstallPath\s+REG_SZ\s+(.+)/i);
|
|
71
|
-
if (!match)
|
|
72
|
-
continue;
|
|
73
|
-
const installRoot = match[1].trim();
|
|
74
|
-
const gitExe = winPath.join(installRoot, 'cmd', 'git.exe');
|
|
75
|
-
if (existsSync(gitExe))
|
|
76
|
-
return gitExe;
|
|
77
|
-
}
|
|
78
|
-
catch {
|
|
79
|
-
// reg.exe missing or key not present -- next query.
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
return null;
|
|
83
|
-
}
|
|
84
|
-
function canonicalGitCandidates() {
|
|
85
|
-
if (process.platform !== 'win32')
|
|
86
|
-
return [];
|
|
87
|
-
const paths = [];
|
|
88
|
-
const push = (...parts) => {
|
|
89
|
-
if (parts.every((part) => typeof part === 'string' && part.length > 0)) {
|
|
90
|
-
// Use winPath.join (not the bare `join` from 'path') because the path
|
|
91
|
-
// module's separator is locked at module-load time. On macOS test
|
|
92
|
-
// hosts running these tests with process.platform spoofed to 'win32',
|
|
93
|
-
// bare join would mix '\' and '/' separators and miss real Windows
|
|
94
|
-
// file system paths.
|
|
95
|
-
paths.push(winPath.join(...parts));
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
const home = homedir();
|
|
99
|
-
// Standard installer locations. `Git\cmd\git.exe` is the public entry
|
|
100
|
-
// point (a small shim that sets up PATH internally then runs the real
|
|
101
|
-
// git from `Git\mingw64\bin`). Bun's spawn copes with .exe just fine,
|
|
102
|
-
// so the shim works as long as we call it by absolute path.
|
|
103
|
-
push(process.env.ProgramFiles, 'Git', 'cmd', 'git.exe');
|
|
104
|
-
push(process.env['ProgramFiles(x86)'], 'Git', 'cmd', 'git.exe');
|
|
105
|
-
push(process.env.LOCALAPPDATA, 'Programs', 'Git', 'cmd', 'git.exe');
|
|
106
|
-
// Portable / per-user installs that don't register in HKLM:
|
|
107
|
-
// - ~/.runwork/tools/mingit, ~/.runwork/tools/git -- our own namespace.
|
|
108
|
-
// Other tools (e.g. Codex CLI) have been observed dropping a portable
|
|
109
|
-
// MinGit there; if anything lives in our directory we should respect
|
|
110
|
-
// it, even when we didn't put it there ourselves.
|
|
111
|
-
// - Scoop -- ~/scoop/apps/git/current/cmd/git.exe.
|
|
112
|
-
// - GitHub Desktop's bundled git lives under a versioned path that's
|
|
113
|
-
// awkward to enumerate without a glob; skipped intentionally.
|
|
114
|
-
if (home) {
|
|
115
|
-
push(home, '.runwork', 'tools', 'mingit', 'cmd', 'git.exe');
|
|
116
|
-
push(home, '.runwork', 'tools', 'git', 'cmd', 'git.exe');
|
|
117
|
-
push(home, '.runwork', 'tools', 'PortableGit', 'cmd', 'git.exe');
|
|
118
|
-
push(home, 'scoop', 'apps', 'git', 'current', 'cmd', 'git.exe');
|
|
119
|
-
}
|
|
120
|
-
// Hard-coded defaults in case the env vars are missing (e.g. bizarre
|
|
121
|
-
// sandbox where %ProgramFiles% isn't propagated).
|
|
122
|
-
paths.push('C:\\Program Files\\Git\\cmd\\git.exe');
|
|
123
|
-
paths.push('C:\\Program Files (x86)\\Git\\cmd\\git.exe');
|
|
124
|
-
// De-dup while preserving order.
|
|
125
|
-
return [...new Set(paths)];
|
|
126
|
-
}
|
|
127
|
-
function prependToPath(dir) {
|
|
128
|
-
// Hard-coded ';' instead of `path.delimiter`: this helper is only called
|
|
129
|
-
// from the Windows-only fallback branch of probeGit(), but the path
|
|
130
|
-
// module's `delimiter` is determined by the *real* host OS at module
|
|
131
|
-
// load time -- so unit tests that flip `process.platform` to 'win32' on
|
|
132
|
-
// a macOS host would otherwise see ':' and fail to detect a duplicate
|
|
133
|
-
// entry. PATH on Windows always uses ';'.
|
|
134
|
-
const PATH_DELIM = ';';
|
|
135
|
-
const current = process.env.PATH ?? '';
|
|
136
|
-
const parts = current.split(PATH_DELIM);
|
|
137
|
-
if (parts.includes(dir))
|
|
138
|
-
return;
|
|
139
|
-
process.env.PATH = `${dir}${PATH_DELIM}${current}`;
|
|
140
|
-
// Windows historically reads `Path` (any case). Node normalizes via
|
|
141
|
-
// process.env, but the Bun-on-Windows path lookup we're working around
|
|
142
|
-
// here has surprised us before, so make the casing redundant.
|
|
143
|
-
if (process.env.Path !== undefined) {
|
|
144
|
-
process.env.Path = process.env.PATH;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
let cachedProbe;
|
|
148
|
-
/**
|
|
149
|
-
* Probe whether `git` is callable from this process.
|
|
150
|
-
*
|
|
151
|
-
* Strategy:
|
|
152
|
-
* 1. Try a bare `git --version` -- the common path on macOS, Linux, and
|
|
153
|
-
* most Windows installs.
|
|
154
|
-
* 2. On Windows, fall back to `where.exe git` (uses the same PATH +
|
|
155
|
-
* PATHEXT rules cmd.exe applies, which are more permissive than
|
|
156
|
-
* Bun's spawn lookup in standalone-compiled binaries).
|
|
157
|
-
* 3. On Windows, finally probe canonical install paths under
|
|
158
|
-
* %ProgramFiles%, %ProgramFiles(x86)%, %LOCALAPPDATA%\Programs.
|
|
159
|
-
*
|
|
160
|
-
* When step 2 or 3 succeeds, we prepend the resolved directory to
|
|
161
|
-
* process.env.PATH so the ~50 other call sites that do
|
|
162
|
-
* `execFileSync('git', ...)` automatically benefit, without rewriting
|
|
163
|
-
* each one. Result is cached for the lifetime of the process.
|
|
164
|
-
*/
|
|
165
|
-
export function probeGit() {
|
|
166
|
-
if (cachedProbe)
|
|
167
|
-
return cachedProbe;
|
|
168
|
-
// 1. Bare lookup.
|
|
169
|
-
const bare = tryRun('git');
|
|
170
|
-
if (bare.ok) {
|
|
171
|
-
cachedProbe = { installed: true, version: bare.version, path: 'git', source: 'PATH' };
|
|
172
|
-
return cachedProbe;
|
|
173
|
-
}
|
|
174
|
-
if (process.platform === 'win32') {
|
|
175
|
-
// 2. where.exe -- uses the same PATH+PATHEXT rules cmd.exe applies.
|
|
176
|
-
const whereResult = whereGit();
|
|
177
|
-
if (whereResult) {
|
|
178
|
-
const verify = tryRun(whereResult);
|
|
179
|
-
if (verify.ok) {
|
|
180
|
-
prependToPath(winPath.dirname(whereResult));
|
|
181
|
-
cachedProbe = { installed: true, version: verify.version, path: whereResult, source: 'where' };
|
|
182
|
-
return cachedProbe;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
// 3. Registry -- the official Git for Windows installer always writes
|
|
186
|
-
// HKLM\SOFTWARE\GitForWindows\InstallPath (or the HKCU equivalent
|
|
187
|
-
// for per-user installs), so this catches "git is installed but
|
|
188
|
-
// something has stripped both PATH and any chance of where.exe
|
|
189
|
-
// finding it" cases (e.g. sandboxed agent shells).
|
|
190
|
-
const registryResult = registryGit();
|
|
191
|
-
if (registryResult) {
|
|
192
|
-
const verify = tryRun(registryResult);
|
|
193
|
-
if (verify.ok) {
|
|
194
|
-
prependToPath(winPath.dirname(registryResult));
|
|
195
|
-
cachedProbe = { installed: true, version: verify.version, path: registryResult, source: 'registry' };
|
|
196
|
-
return cachedProbe;
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
// 4. Canonical paths -- standard installer dirs plus our own
|
|
200
|
-
// ~/.runwork/tools/{mingit,git,PortableGit} namespace and Scoop's
|
|
201
|
-
// install location, for portable / non-installer Gits the registry
|
|
202
|
-
// won't know about.
|
|
203
|
-
for (const candidate of canonicalGitCandidates()) {
|
|
204
|
-
if (!existsSync(candidate))
|
|
205
|
-
continue;
|
|
206
|
-
const verify = tryRun(candidate);
|
|
207
|
-
if (verify.ok) {
|
|
208
|
-
prependToPath(winPath.dirname(candidate));
|
|
209
|
-
cachedProbe = { installed: true, version: verify.version, path: candidate, source: 'canonical' };
|
|
210
|
-
return cachedProbe;
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
cachedProbe = { installed: false, error: bare.error };
|
|
215
|
-
return cachedProbe;
|
|
216
|
-
}
|
|
217
|
-
/**
|
|
218
|
-
* Reset the cached probe result. Exposed for tests and for `runwork doctor`
|
|
219
|
-
* when it wants to re-check after a guided install.
|
|
220
|
-
*/
|
|
221
|
-
export function resetGitProbeCache() {
|
|
222
|
-
cachedProbe = undefined;
|
|
223
|
-
}
|
|
224
|
-
/**
|
|
225
|
-
* Extract a short numeric version (e.g. "2.43.0") from a `git --version`
|
|
226
|
-
* output line. Returns null if no number could be parsed.
|
|
227
|
-
*/
|
|
228
|
-
export function parseGitVersion(versionLine) {
|
|
229
|
-
if (!versionLine)
|
|
230
|
-
return null;
|
|
231
|
-
const match = versionLine.match(VERSION_REGEX);
|
|
232
|
-
return match ? match[1] : null;
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* Build a beginner-friendly message explaining how to recover from a missing
|
|
236
|
-
* git binary. Includes a Windows-specific hint because the most common
|
|
237
|
-
* scenario there is "winget install Git.Git just succeeded but this shell's
|
|
238
|
-
* PATH was cached at launch" -- restarting the shell fixes it without a
|
|
239
|
-
* second install attempt.
|
|
240
|
-
*
|
|
241
|
-
* If a probe error is supplied, the underlying message is appended so users
|
|
242
|
-
* can see *why* detection failed (ENOENT vs EACCES vs something else).
|
|
243
|
-
*/
|
|
244
|
-
export function buildMissingGitMessage(commandName, probe) {
|
|
245
|
-
const lines = [
|
|
246
|
-
`Git is required to run \`runwork ${commandName}\`, but it was not found on PATH.`,
|
|
247
|
-
'',
|
|
248
|
-
'Install Git, then re-run this command:',
|
|
249
|
-
' - macOS: brew install git (or: xcode-select --install)',
|
|
250
|
-
' - Windows: winget install --id Git.Git -e',
|
|
251
|
-
' - Linux: sudo apt-get install -y git (or your distro\'s equivalent)',
|
|
252
|
-
];
|
|
253
|
-
if (process.platform === 'win32') {
|
|
254
|
-
lines.push('', 'If you just installed Git, this shell\'s PATH was cached when it opened', 'and does not yet include Git. Close this PowerShell / Command Prompt', 'window, open a fresh one, and re-run the command.');
|
|
255
|
-
}
|
|
256
|
-
lines.push('', 'Verify the install with: git --version');
|
|
257
|
-
if (probe?.error?.message) {
|
|
258
|
-
// Surface the underlying error for diagnostics so users (and we, in bug
|
|
259
|
-
// reports) can see whether this was ENOENT, EACCES, a sandbox PATH
|
|
260
|
-
// strip, etc. -- not just "not found".
|
|
261
|
-
lines.push('', `Underlying error: ${probe.error.message}`);
|
|
262
|
-
}
|
|
263
|
-
return lines.join('\n');
|
|
264
|
-
}
|
|
265
|
-
/**
|
|
266
|
-
* Convenience wrapper for command entry points: probe git, and if it's
|
|
267
|
-
* missing, print the beginner-friendly message and exit with code 1.
|
|
268
|
-
* Returns void on success so callers can early-return on failure.
|
|
269
|
-
*/
|
|
270
|
-
export function requireGit(commandName) {
|
|
271
|
-
const probe = probeGit();
|
|
272
|
-
if (probe.installed)
|
|
273
|
-
return;
|
|
274
|
-
console.error(buildMissingGitMessage(commandName, probe));
|
|
275
|
-
process.exit(1);
|
|
276
|
-
}
|
package/dist/git/remote.d.ts
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The git remote name runwork uses for all sync/push operations. The sync
|
|
3
|
-
* loop (git/sync.ts) references this remote by name, so clone/dev/deploy must
|
|
4
|
-
* guarantee it exists and points at the app's canonical URL before syncing.
|
|
5
|
-
*/
|
|
6
|
-
export declare const RUNWORK_REMOTE = "runwork";
|
|
7
|
-
export type EnsureRemoteResult = {
|
|
8
|
-
action: 'noop';
|
|
9
|
-
} | {
|
|
10
|
-
action: 'updated';
|
|
11
|
-
} | {
|
|
12
|
-
action: 'added';
|
|
13
|
-
reusedFrom?: string;
|
|
14
|
-
};
|
|
15
|
-
/**
|
|
16
|
-
* Normalize a git remote URL for equality comparison. Strips a trailing
|
|
17
|
-
* `.git`, trailing slashes, and userinfo; lower-cases the host (case-
|
|
18
|
-
* insensitive) while preserving the path (case-sensitive). Falls back to a
|
|
19
|
-
* lower-cased trim for scp-style / non-URL remotes.
|
|
20
|
-
*/
|
|
21
|
-
export declare function normalizeRemoteUrl(raw: string): string;
|
|
22
|
-
/** Map of remote name -> fetch URL, parsed from `git remote -v`. */
|
|
23
|
-
export declare function listRemotes(cwd: string): Record<string, string>;
|
|
24
|
-
/**
|
|
25
|
-
* Ensure a `runwork` remote exists and points at the app's canonical git URL,
|
|
26
|
-
* so the sync loop's `runwork`-named git calls succeed regardless of how the
|
|
27
|
-
* repo was obtained. A plain `git clone <url>` names the remote `origin`,
|
|
28
|
-
* which previously made `runwork dev`/`deploy` fail with
|
|
29
|
-
* `fatal: 'runwork' does not appear to be a git repository`.
|
|
30
|
-
*
|
|
31
|
-
* We don't require the remote to literally be named `runwork`: if another
|
|
32
|
-
* remote (e.g. `origin`) already points at the canonical URL, we recognize it
|
|
33
|
-
* (reported via `reusedFrom`) and still register the `runwork` alias so the
|
|
34
|
-
* hardcoded sync path keeps working. Idempotent: a no-op when `runwork`
|
|
35
|
-
* already points at the canonical URL.
|
|
36
|
-
*/
|
|
37
|
-
export declare function ensureRunworkRemote(cwd: string, canonicalUrl: string): EnsureRemoteResult;
|
package/dist/git/remote.js
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { execFileSync } from '../utils/subprocess.js';
|
|
2
|
-
/**
|
|
3
|
-
* The git remote name runwork uses for all sync/push operations. The sync
|
|
4
|
-
* loop (git/sync.ts) references this remote by name, so clone/dev/deploy must
|
|
5
|
-
* guarantee it exists and points at the app's canonical URL before syncing.
|
|
6
|
-
*/
|
|
7
|
-
export const RUNWORK_REMOTE = 'runwork';
|
|
8
|
-
// existing remote, e.g. `origin`, already at this URL)
|
|
9
|
-
/**
|
|
10
|
-
* Normalize a git remote URL for equality comparison. Strips a trailing
|
|
11
|
-
* `.git`, trailing slashes, and userinfo; lower-cases the host (case-
|
|
12
|
-
* insensitive) while preserving the path (case-sensitive). Falls back to a
|
|
13
|
-
* lower-cased trim for scp-style / non-URL remotes.
|
|
14
|
-
*/
|
|
15
|
-
export function normalizeRemoteUrl(raw) {
|
|
16
|
-
const trimmed = raw.trim().replace(/\.git$/, '').replace(/\/+$/, '');
|
|
17
|
-
try {
|
|
18
|
-
const u = new URL(trimmed);
|
|
19
|
-
const host = u.host.toLowerCase();
|
|
20
|
-
const path = u.pathname.replace(/\/+$/, '');
|
|
21
|
-
return `${u.protocol}//${host}${path}`;
|
|
22
|
-
}
|
|
23
|
-
catch {
|
|
24
|
-
return trimmed.toLowerCase();
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
/** Map of remote name -> fetch URL, parsed from `git remote -v`. */
|
|
28
|
-
export function listRemotes(cwd) {
|
|
29
|
-
const remotes = {};
|
|
30
|
-
let output;
|
|
31
|
-
try {
|
|
32
|
-
output = execFileSync('git', ['remote', '-v'], { cwd, stdio: ['ignore', 'pipe', 'ignore'] }).toString();
|
|
33
|
-
}
|
|
34
|
-
catch {
|
|
35
|
-
return remotes; // not a git repo, or git unavailable
|
|
36
|
-
}
|
|
37
|
-
for (const line of output.split(/\r?\n/)) {
|
|
38
|
-
// Format: `<name>\t<url> (fetch)` / `<name>\t<url> (push)`
|
|
39
|
-
const match = line.match(/^(\S+)\s+(\S+)\s+\((fetch|push)\)$/);
|
|
40
|
-
if (match && match[3] === 'fetch') {
|
|
41
|
-
remotes[match[1]] = match[2];
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return remotes;
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Ensure a `runwork` remote exists and points at the app's canonical git URL,
|
|
48
|
-
* so the sync loop's `runwork`-named git calls succeed regardless of how the
|
|
49
|
-
* repo was obtained. A plain `git clone <url>` names the remote `origin`,
|
|
50
|
-
* which previously made `runwork dev`/`deploy` fail with
|
|
51
|
-
* `fatal: 'runwork' does not appear to be a git repository`.
|
|
52
|
-
*
|
|
53
|
-
* We don't require the remote to literally be named `runwork`: if another
|
|
54
|
-
* remote (e.g. `origin`) already points at the canonical URL, we recognize it
|
|
55
|
-
* (reported via `reusedFrom`) and still register the `runwork` alias so the
|
|
56
|
-
* hardcoded sync path keeps working. Idempotent: a no-op when `runwork`
|
|
57
|
-
* already points at the canonical URL.
|
|
58
|
-
*/
|
|
59
|
-
export function ensureRunworkRemote(cwd, canonicalUrl) {
|
|
60
|
-
const remotes = listRemotes(cwd);
|
|
61
|
-
const target = normalizeRemoteUrl(canonicalUrl);
|
|
62
|
-
const existing = remotes[RUNWORK_REMOTE];
|
|
63
|
-
if (existing && normalizeRemoteUrl(existing) === target) {
|
|
64
|
-
return { action: 'noop' };
|
|
65
|
-
}
|
|
66
|
-
if (existing) {
|
|
67
|
-
execFileSync('git', ['remote', 'set-url', RUNWORK_REMOTE, canonicalUrl], { cwd, stdio: 'pipe' });
|
|
68
|
-
return { action: 'updated' };
|
|
69
|
-
}
|
|
70
|
-
// `runwork` is missing. Note if any other remote already points at the same
|
|
71
|
-
// URL (the manual `git clone` case, where it's typically `origin`).
|
|
72
|
-
const reusedFrom = Object.entries(remotes).find(([, url]) => normalizeRemoteUrl(url) === target)?.[0];
|
|
73
|
-
execFileSync('git', ['remote', 'add', RUNWORK_REMOTE, canonicalUrl], { cwd, stdio: 'pipe' });
|
|
74
|
-
return reusedFrom ? { action: 'added', reusedFrom } : { action: 'added' };
|
|
75
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Disable git's background gc/maintenance for the repo at `cwd`. This is set
|
|
3
|
-
* locally (repo scope), is harmless on normal filesystems -- these app repos
|
|
4
|
-
* are small and centrally managed -- and avoids the pack-unlink failures that
|
|
5
|
-
* restricted mounts produce. Applied cross-platform with no FS detection, so
|
|
6
|
-
* it never risks a false positive (notably on Windows). Best-effort.
|
|
7
|
-
*/
|
|
8
|
-
export declare function hardenRepoForRestrictedFs(cwd: string): void;
|
package/dist/git/repo-config.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { execFileSync } from '../utils/subprocess.js';
|
|
2
|
-
/**
|
|
3
|
-
* Git config keys we disable on a freshly cloned app repo, with values.
|
|
4
|
-
* Background gc/maintenance rewrite pack files, which on restricted
|
|
5
|
-
* filesystems (some AI-agent "outputs" mounts disallow certain unlinks) fail
|
|
6
|
-
* with `unable to unlink '.git/objects/pack/...': Operation not permitted`,
|
|
7
|
-
* leaving git state unreliable (friction log #9).
|
|
8
|
-
*/
|
|
9
|
-
const HARDENING = [
|
|
10
|
-
['gc.auto', '0'],
|
|
11
|
-
['maintenance.auto', 'false'],
|
|
12
|
-
];
|
|
13
|
-
/**
|
|
14
|
-
* Disable git's background gc/maintenance for the repo at `cwd`. This is set
|
|
15
|
-
* locally (repo scope), is harmless on normal filesystems -- these app repos
|
|
16
|
-
* are small and centrally managed -- and avoids the pack-unlink failures that
|
|
17
|
-
* restricted mounts produce. Applied cross-platform with no FS detection, so
|
|
18
|
-
* it never risks a false positive (notably on Windows). Best-effort.
|
|
19
|
-
*/
|
|
20
|
-
export function hardenRepoForRestrictedFs(cwd) {
|
|
21
|
-
for (const [key, value] of HARDENING) {
|
|
22
|
-
try {
|
|
23
|
-
execFileSync('git', ['config', key, value], { cwd, stdio: 'pipe' });
|
|
24
|
-
}
|
|
25
|
-
catch {
|
|
26
|
-
// Best-effort: failing to set a hardening config must not fail a clone.
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
package/dist/git/sync.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export interface SyncResult {
|
|
2
|
-
status: 'synced' | 'merged' | 'sync-failed' | 'skipped';
|
|
3
|
-
pushed: boolean;
|
|
4
|
-
error?: string;
|
|
5
|
-
}
|
|
6
|
-
export declare function hasCommits(cwd: string): boolean;
|
|
7
|
-
export declare function hasTrackedChanges(cwd: string): boolean;
|
|
8
|
-
/**
|
|
9
|
-
* Sync local repository with the runwork remote.
|
|
10
|
-
*
|
|
11
|
-
* Strategy: fetch, then attempt rebase. If rebase fails (e.g. diverged
|
|
12
|
-
* histories after a template update), fall back to merge with
|
|
13
|
-
* --allow-unrelated-histories. Stash/pop around dirty working trees.
|
|
14
|
-
*/
|
|
15
|
-
export declare function syncWithRemote(cwd: string): SyncResult;
|
package/dist/git/sync.js
DELETED
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
import { execFileSync } from '../utils/subprocess.js';
|
|
2
|
-
import { unlinkSync } from 'fs';
|
|
3
|
-
import { join } from 'path';
|
|
4
|
-
export function hasCommits(cwd) {
|
|
5
|
-
try {
|
|
6
|
-
execFileSync('git', ['rev-parse', 'HEAD'], { cwd, stdio: 'pipe' });
|
|
7
|
-
return true;
|
|
8
|
-
}
|
|
9
|
-
catch {
|
|
10
|
-
return false;
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
export function hasTrackedChanges(cwd) {
|
|
14
|
-
try {
|
|
15
|
-
const output = execFileSync('git', ['status', '--porcelain'], { cwd, encoding: 'utf-8' });
|
|
16
|
-
return output.trim().split('\n').some(line => line.length > 0 && !line.startsWith('??'));
|
|
17
|
-
}
|
|
18
|
-
catch {
|
|
19
|
-
return false;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Remove untracked local files that exist on the remote.
|
|
24
|
-
* Skeleton files are ephemeral (re-downloaded each session) so the
|
|
25
|
-
* server's versions take precedence. User-edited files are already
|
|
26
|
-
* tracked/committed at this point and won't be affected.
|
|
27
|
-
*/
|
|
28
|
-
function removeConflictingUntrackedFiles(cwd) {
|
|
29
|
-
try {
|
|
30
|
-
const remoteFiles = execFileSync('git', ['ls-tree', '-r', '--name-only', 'runwork/main'], {
|
|
31
|
-
cwd,
|
|
32
|
-
encoding: 'utf-8',
|
|
33
|
-
}).trim().split('\n');
|
|
34
|
-
const untrackedOutput = execFileSync('git', ['ls-files', '--others', '--exclude-standard'], {
|
|
35
|
-
cwd,
|
|
36
|
-
encoding: 'utf-8',
|
|
37
|
-
}).trim();
|
|
38
|
-
const untracked = new Set(untrackedOutput.split('\n').filter(Boolean));
|
|
39
|
-
for (const file of remoteFiles) {
|
|
40
|
-
if (untracked.has(file)) {
|
|
41
|
-
try {
|
|
42
|
-
unlinkSync(join(cwd, file));
|
|
43
|
-
}
|
|
44
|
-
catch { /* already gone */ }
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
catch {
|
|
49
|
-
// best effort
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
function extractGitError(err) {
|
|
53
|
-
if (err && typeof err === 'object') {
|
|
54
|
-
const obj = err;
|
|
55
|
-
// execFileSync errors have stderr and stdout as Buffer or string
|
|
56
|
-
const stderr = bufToStr(obj.stderr);
|
|
57
|
-
const stdout = bufToStr(obj.stdout);
|
|
58
|
-
// Prefer stderr (git's error output), fall back to stdout (merge conflict details)
|
|
59
|
-
if (stderr)
|
|
60
|
-
return stderr;
|
|
61
|
-
if (stdout)
|
|
62
|
-
return stdout;
|
|
63
|
-
}
|
|
64
|
-
if (err instanceof Error)
|
|
65
|
-
return err.message;
|
|
66
|
-
return String(err);
|
|
67
|
-
}
|
|
68
|
-
function bufToStr(val) {
|
|
69
|
-
if (!val)
|
|
70
|
-
return '';
|
|
71
|
-
if (typeof val === 'string')
|
|
72
|
-
return val.trim();
|
|
73
|
-
if (Buffer.isBuffer(val))
|
|
74
|
-
return val.toString('utf-8').trim();
|
|
75
|
-
return '';
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Sync local repository with the runwork remote.
|
|
79
|
-
*
|
|
80
|
-
* Strategy: fetch, then attempt rebase. If rebase fails (e.g. diverged
|
|
81
|
-
* histories after a template update), fall back to merge with
|
|
82
|
-
* --allow-unrelated-histories. Stash/pop around dirty working trees.
|
|
83
|
-
*/
|
|
84
|
-
export function syncWithRemote(cwd) {
|
|
85
|
-
if (!hasCommits(cwd)) {
|
|
86
|
-
return { status: 'skipped', pushed: false };
|
|
87
|
-
}
|
|
88
|
-
const dirty = hasTrackedChanges(cwd);
|
|
89
|
-
if (dirty) {
|
|
90
|
-
execFileSync('git', ['stash', 'push', '-m', 'runwork-dev-sync'], { cwd, stdio: 'pipe' });
|
|
91
|
-
}
|
|
92
|
-
let status = 'synced';
|
|
93
|
-
let syncError;
|
|
94
|
-
try {
|
|
95
|
-
execFileSync('git', ['fetch', 'runwork', 'main'], { cwd, stdio: 'pipe' });
|
|
96
|
-
removeConflictingUntrackedFiles(cwd);
|
|
97
|
-
try {
|
|
98
|
-
execFileSync('git', ['rebase', 'runwork/main'], { cwd, stdio: 'pipe' });
|
|
99
|
-
}
|
|
100
|
-
catch (rebaseErr) {
|
|
101
|
-
try {
|
|
102
|
-
execFileSync('git', ['rebase', '--abort'], { cwd, stdio: 'pipe' });
|
|
103
|
-
}
|
|
104
|
-
catch { /* no rebase in progress */ }
|
|
105
|
-
try {
|
|
106
|
-
execFileSync('git', ['merge', 'runwork/main', '--allow-unrelated-histories', '--no-edit'], { cwd, stdio: 'pipe' });
|
|
107
|
-
status = 'merged';
|
|
108
|
-
}
|
|
109
|
-
catch {
|
|
110
|
-
// Merge conflicts (common with unrelated histories / first sync).
|
|
111
|
-
// Abort and retry accepting the remote's version for all conflicts.
|
|
112
|
-
// This is safe because: user edits were committed before sync,
|
|
113
|
-
// and local template files are ephemeral (re-downloaded each session).
|
|
114
|
-
try {
|
|
115
|
-
execFileSync('git', ['merge', '--abort'], { cwd, stdio: 'pipe' });
|
|
116
|
-
}
|
|
117
|
-
catch { /* no merge in progress */ }
|
|
118
|
-
try {
|
|
119
|
-
execFileSync('git', ['merge', 'runwork/main', '--allow-unrelated-histories', '--no-edit', '-X', 'theirs'], { cwd, stdio: 'pipe' });
|
|
120
|
-
status = 'merged';
|
|
121
|
-
}
|
|
122
|
-
catch (mergeErr) {
|
|
123
|
-
try {
|
|
124
|
-
execFileSync('git', ['merge', '--abort'], { cwd, stdio: 'pipe' });
|
|
125
|
-
}
|
|
126
|
-
catch { /* no merge in progress */ }
|
|
127
|
-
status = 'sync-failed';
|
|
128
|
-
syncError = extractGitError(mergeErr);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
catch (fetchErr) {
|
|
134
|
-
status = 'sync-failed';
|
|
135
|
-
syncError = extractGitError(fetchErr);
|
|
136
|
-
}
|
|
137
|
-
if (dirty) {
|
|
138
|
-
try {
|
|
139
|
-
execFileSync('git', ['stash', 'pop'], { cwd, stdio: 'pipe' });
|
|
140
|
-
}
|
|
141
|
-
catch {
|
|
142
|
-
return { status, pushed: false, error: 'stash-conflict' };
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
if (status === 'sync-failed') {
|
|
146
|
-
return { status, pushed: false, error: syncError };
|
|
147
|
-
}
|
|
148
|
-
let pushed = false;
|
|
149
|
-
try {
|
|
150
|
-
// `HEAD:main` so the push works regardless of local branch name
|
|
151
|
-
// (older Git defaults to `master`, some users keep custom defaults).
|
|
152
|
-
execFileSync('git', ['push', 'runwork', 'HEAD:main'], { cwd, stdio: 'pipe' });
|
|
153
|
-
pushed = true;
|
|
154
|
-
}
|
|
155
|
-
catch {
|
|
156
|
-
// push failed — continue with current state
|
|
157
|
-
}
|
|
158
|
-
return { status, pushed };
|
|
159
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|