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
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import type { Credentials } from '../types.js';
|
|
2
|
-
/**
|
|
3
|
-
* Performs the full browser-based login flow:
|
|
4
|
-
* 1. Initiates login, opens browser
|
|
5
|
-
* 2. Polls for completion
|
|
6
|
-
* 3. Saves credentials and configures git
|
|
7
|
-
*
|
|
8
|
-
* Returns the credentials on success, exits process on timeout.
|
|
9
|
-
*/
|
|
10
|
-
export declare function performLogin(baseUrl?: string): Promise<Credentials>;
|
|
11
|
-
/**
|
|
12
|
-
* Initiate a login session without opening the browser.
|
|
13
|
-
* Prints the login URL to stdout and polls for completion.
|
|
14
|
-
* If printOnly is true, prints the URL and returns null (exits without polling).
|
|
15
|
-
*/
|
|
16
|
-
export declare function performLoginNoOpen(baseUrl?: string, printOnly?: boolean): Promise<Credentials | null>;
|
|
17
|
-
/**
|
|
18
|
-
* Resume a previously initiated login session by providing the login URL.
|
|
19
|
-
* Extracts the session ID from the URL and polls until authenticated.
|
|
20
|
-
*/
|
|
21
|
-
export declare function performLoginFromUrl(loginUrl: string): Promise<Credentials>;
|
|
22
|
-
/**
|
|
23
|
-
* Authenticate directly with an API key (no browser flow).
|
|
24
|
-
* Validates the key by calling the API, then saves credentials.
|
|
25
|
-
*/
|
|
26
|
-
export declare function performLoginWithApiKey(apiKey: string, baseUrl?: string): Promise<Credentials>;
|
package/dist/auth/login-flow.js
DELETED
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
import { ApiClient } from '../api/client.js';
|
|
2
|
-
import { saveCredentials } from './store.js';
|
|
3
|
-
import { configureGitCredentials } from '../git/credentials.js';
|
|
4
|
-
const DEFAULT_BASE_URL = 'https://runwork.ai';
|
|
5
|
-
/**
|
|
6
|
-
* Performs the full browser-based login flow:
|
|
7
|
-
* 1. Initiates login, opens browser
|
|
8
|
-
* 2. Polls for completion
|
|
9
|
-
* 3. Saves credentials and configures git
|
|
10
|
-
*
|
|
11
|
-
* Returns the credentials on success, exits process on timeout.
|
|
12
|
-
*/
|
|
13
|
-
export async function performLogin(baseUrl) {
|
|
14
|
-
const url = baseUrl || DEFAULT_BASE_URL;
|
|
15
|
-
const client = new ApiClient({ apiKey: '', email: '', baseUrl: url });
|
|
16
|
-
const { sessionId, loginUrl } = await client.initiateLogin();
|
|
17
|
-
// Open browser
|
|
18
|
-
const open = await import('open');
|
|
19
|
-
await open.default(loginUrl);
|
|
20
|
-
console.log(`If browser didn't open, visit: ${loginUrl}`);
|
|
21
|
-
console.log('');
|
|
22
|
-
console.log('Waiting for authentication...');
|
|
23
|
-
return pollAndSave(client, sessionId, url);
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Initiate a login session without opening the browser.
|
|
27
|
-
* Prints the login URL to stdout and polls for completion.
|
|
28
|
-
* If printOnly is true, prints the URL and returns null (exits without polling).
|
|
29
|
-
*/
|
|
30
|
-
export async function performLoginNoOpen(baseUrl, printOnly) {
|
|
31
|
-
const url = baseUrl || DEFAULT_BASE_URL;
|
|
32
|
-
const client = new ApiClient({ apiKey: '', email: '', baseUrl: url });
|
|
33
|
-
const { loginUrl } = await client.initiateLogin();
|
|
34
|
-
// Print the URL for the agent/human to use
|
|
35
|
-
console.log(loginUrl);
|
|
36
|
-
if (printOnly) {
|
|
37
|
-
return null;
|
|
38
|
-
}
|
|
39
|
-
console.error('Waiting for authentication...');
|
|
40
|
-
return pollAndSave(client, extractSessionId(loginUrl), url);
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Resume a previously initiated login session by providing the login URL.
|
|
44
|
-
* Extracts the session ID from the URL and polls until authenticated.
|
|
45
|
-
*/
|
|
46
|
-
export async function performLoginFromUrl(loginUrl) {
|
|
47
|
-
const sessionId = extractSessionId(loginUrl);
|
|
48
|
-
const baseUrl = extractBaseUrl(loginUrl);
|
|
49
|
-
const client = new ApiClient({ apiKey: '', email: '', baseUrl });
|
|
50
|
-
console.log('Waiting for authentication...');
|
|
51
|
-
return pollAndSave(client, sessionId, baseUrl);
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Authenticate directly with an API key (no browser flow).
|
|
55
|
-
* Validates the key by calling the API, then saves credentials.
|
|
56
|
-
*/
|
|
57
|
-
export async function performLoginWithApiKey(apiKey, baseUrl) {
|
|
58
|
-
const url = baseUrl || DEFAULT_BASE_URL;
|
|
59
|
-
const client = new ApiClient({ apiKey, email: '', baseUrl: url });
|
|
60
|
-
// Validate the key by fetching workspaces
|
|
61
|
-
try {
|
|
62
|
-
const workspaces = await client.listWorkspaces();
|
|
63
|
-
const defaultWs = workspaces[0];
|
|
64
|
-
const creds = {
|
|
65
|
-
apiKey,
|
|
66
|
-
email: 'api-key-auth',
|
|
67
|
-
baseUrl: url,
|
|
68
|
-
defaultWorkspaceId: defaultWs?.id,
|
|
69
|
-
defaultWorkspaceName: defaultWs?.name,
|
|
70
|
-
};
|
|
71
|
-
saveCredentials(creds);
|
|
72
|
-
await configureGitCredentials(url);
|
|
73
|
-
console.log('Logged in with API key.');
|
|
74
|
-
if (defaultWs) {
|
|
75
|
-
console.log(`Default workspace: ${defaultWs.name}`);
|
|
76
|
-
}
|
|
77
|
-
return creds;
|
|
78
|
-
}
|
|
79
|
-
catch (err) {
|
|
80
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
81
|
-
console.error(`Invalid API key: ${message}`);
|
|
82
|
-
process.exit(1);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Extract session ID from a login URL.
|
|
87
|
-
* Supports both query param (?session=xxx) and path segment formats.
|
|
88
|
-
*/
|
|
89
|
-
function extractSessionId(loginUrl) {
|
|
90
|
-
try {
|
|
91
|
-
const url = new URL(loginUrl);
|
|
92
|
-
const session = url.searchParams.get('session');
|
|
93
|
-
if (session)
|
|
94
|
-
return session;
|
|
95
|
-
// Try path-based: /cli-auth/SESSION_ID
|
|
96
|
-
const pathParts = url.pathname.split('/');
|
|
97
|
-
const authIdx = pathParts.indexOf('cli-auth');
|
|
98
|
-
if (authIdx >= 0 && pathParts[authIdx + 1]) {
|
|
99
|
-
return pathParts[authIdx + 1];
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
catch {
|
|
103
|
-
// Not a valid URL
|
|
104
|
-
}
|
|
105
|
-
console.error(`Could not extract session ID from URL: ${loginUrl}`);
|
|
106
|
-
process.exit(1);
|
|
107
|
-
}
|
|
108
|
-
/**
|
|
109
|
-
* Extract the base URL (origin) from a login URL.
|
|
110
|
-
*/
|
|
111
|
-
function extractBaseUrl(loginUrl) {
|
|
112
|
-
try {
|
|
113
|
-
return new URL(loginUrl).origin;
|
|
114
|
-
}
|
|
115
|
-
catch {
|
|
116
|
-
return DEFAULT_BASE_URL;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* Poll for login completion and save credentials.
|
|
121
|
-
*/
|
|
122
|
-
async function pollAndSave(client, sessionId, baseUrl) {
|
|
123
|
-
const maxAttempts = 60;
|
|
124
|
-
const pollInterval = 5000;
|
|
125
|
-
for (let i = 0; i < maxAttempts; i++) {
|
|
126
|
-
await new Promise(resolve => setTimeout(resolve, pollInterval));
|
|
127
|
-
const result = await client.pollLogin(sessionId);
|
|
128
|
-
if (result) {
|
|
129
|
-
saveCredentials(result);
|
|
130
|
-
await configureGitCredentials(result.baseUrl || baseUrl);
|
|
131
|
-
console.log(`Logged in as ${result.email}`);
|
|
132
|
-
return result;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
console.error('Login timed out. Please try again.');
|
|
136
|
-
process.exit(1);
|
|
137
|
-
}
|
package/dist/auth/store.d.ts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { Credentials } from '../types.js';
|
|
2
|
-
export declare function getCredentials(): Credentials | null;
|
|
3
|
-
export declare function saveCredentials(credentials: Credentials): void;
|
|
4
|
-
export declare function clearCredentials(): void;
|
|
5
|
-
export declare function requireAuth(): Credentials;
|
package/dist/auth/store.js
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { readFileSync, writeFileSync, mkdirSync, existsSync, unlinkSync } from 'fs';
|
|
2
|
-
import { join } from 'path';
|
|
3
|
-
import { homedir } from 'os';
|
|
4
|
-
const RUNWORK_DIR = join(homedir(), '.runwork');
|
|
5
|
-
const CREDENTIALS_FILE = join(RUNWORK_DIR, '.credentials');
|
|
6
|
-
export function getCredentials() {
|
|
7
|
-
// Support env var auth for sandbox agent sessions
|
|
8
|
-
// RUNWORK_API_KEY is a JWT proxy token set by the platform when running agents in sandbox
|
|
9
|
-
if (process.env.RUNWORK_API_KEY) {
|
|
10
|
-
let baseUrl = 'https://runwork.ai';
|
|
11
|
-
if (process.env.WORKSPACE_API_URL) {
|
|
12
|
-
try {
|
|
13
|
-
baseUrl = new URL(process.env.WORKSPACE_API_URL).origin;
|
|
14
|
-
}
|
|
15
|
-
catch { /* use default */ }
|
|
16
|
-
}
|
|
17
|
-
return {
|
|
18
|
-
apiKey: process.env.RUNWORK_API_KEY,
|
|
19
|
-
email: 'agent@runwork.ai',
|
|
20
|
-
baseUrl,
|
|
21
|
-
defaultWorkspaceId: process.env.WORKSPACE_ID,
|
|
22
|
-
defaultWorkspaceName: undefined,
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
if (!existsSync(CREDENTIALS_FILE))
|
|
26
|
-
return null;
|
|
27
|
-
try {
|
|
28
|
-
const raw = readFileSync(CREDENTIALS_FILE, 'utf-8');
|
|
29
|
-
return JSON.parse(raw);
|
|
30
|
-
}
|
|
31
|
-
catch {
|
|
32
|
-
return null;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
export function saveCredentials(credentials) {
|
|
36
|
-
mkdirSync(RUNWORK_DIR, { recursive: true });
|
|
37
|
-
writeFileSync(CREDENTIALS_FILE, JSON.stringify(credentials, null, 2), { mode: 0o600 });
|
|
38
|
-
}
|
|
39
|
-
export function clearCredentials() {
|
|
40
|
-
if (existsSync(CREDENTIALS_FILE)) {
|
|
41
|
-
unlinkSync(CREDENTIALS_FILE);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
export function requireAuth() {
|
|
45
|
-
const creds = getCredentials();
|
|
46
|
-
if (!creds) {
|
|
47
|
-
const isTTY = process.stdin.isTTY;
|
|
48
|
-
if (isTTY) {
|
|
49
|
-
console.error('Not logged in. Run `runwork login` first.');
|
|
50
|
-
}
|
|
51
|
-
else {
|
|
52
|
-
// Headless / sandbox / AI agent environment: provide actionable guidance
|
|
53
|
-
console.error('Not logged in. In a sandbox or headless environment, authenticate using one of:\n' +
|
|
54
|
-
' 1. Call the get_cli_setup MCP tool, then write the returned credentials to ~/.runwork/.credentials\n' +
|
|
55
|
-
' 2. Set the RUNWORK_API_KEY environment variable\n' +
|
|
56
|
-
' 3. Run: runwork login --api-key <your-api-key>\n' +
|
|
57
|
-
' 4. Run: runwork login --no-open --print-only (prints a URL for browser auth)');
|
|
58
|
-
}
|
|
59
|
-
process.exit(1);
|
|
60
|
-
}
|
|
61
|
-
return creds;
|
|
62
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { normalizeCloneArgs, RESTRICTED_FS_HELP } from '../clone.js';
|
|
3
|
-
describe('normalizeCloneArgs', () => {
|
|
4
|
-
it('passes through both args unchanged when --app is not provided', () => {
|
|
5
|
-
expect(normalizeCloneArgs('app-id', 'C:/dir', undefined)).toEqual({
|
|
6
|
-
appId: 'app-id',
|
|
7
|
-
directory: 'C:/dir',
|
|
8
|
-
});
|
|
9
|
-
expect(normalizeCloneArgs('app-id', 'C:/dir', {})).toEqual({
|
|
10
|
-
appId: 'app-id',
|
|
11
|
-
directory: 'C:/dir',
|
|
12
|
-
});
|
|
13
|
-
});
|
|
14
|
-
it('passes through both args unchanged when --app is set but directory is also explicit', () => {
|
|
15
|
-
expect(normalizeCloneArgs('app-id', 'C:/dir', { app: 'foo' })).toEqual({ appId: 'app-id', directory: 'C:/dir' });
|
|
16
|
-
});
|
|
17
|
-
it('shifts the first positional to directory when --app is set and only one positional arg is present', () => {
|
|
18
|
-
// The reproducer from the field:
|
|
19
|
-
// runwork clone --app academic-grade-conversion C:\Users\Oytun\Desktop\agc-test
|
|
20
|
-
// commander binds rawAppId = "C:\Users\..." and rawDirectory = undefined.
|
|
21
|
-
expect(normalizeCloneArgs('C:\\Users\\Oytun\\Desktop\\agc-test', undefined, {
|
|
22
|
-
app: 'academic-grade-conversion',
|
|
23
|
-
})).toEqual({
|
|
24
|
-
appId: undefined,
|
|
25
|
-
directory: 'C:\\Users\\Oytun\\Desktop\\agc-test',
|
|
26
|
-
});
|
|
27
|
-
});
|
|
28
|
-
it('does not shift when --app is set and no positional args are provided', () => {
|
|
29
|
-
expect(normalizeCloneArgs(undefined, undefined, { app: 'foo' })).toEqual({
|
|
30
|
-
appId: undefined,
|
|
31
|
-
directory: undefined,
|
|
32
|
-
});
|
|
33
|
-
});
|
|
34
|
-
it('does not shift when --app is set with only the directory positional (rawAppId already undefined)', () => {
|
|
35
|
-
// commander binds positional arguments left-to-right; if only one is
|
|
36
|
-
// given, it's always rawAppId. So this case shouldn't arise in practice
|
|
37
|
-
// -- but if a future commander upgrade changes that, we should leave
|
|
38
|
-
// already-correct args alone.
|
|
39
|
-
expect(normalizeCloneArgs(undefined, 'C:/dir', { app: 'foo' })).toEqual({
|
|
40
|
-
appId: undefined,
|
|
41
|
-
directory: 'C:/dir',
|
|
42
|
-
});
|
|
43
|
-
});
|
|
44
|
-
});
|
|
45
|
-
describe('clone --help restricted-FS guidance', () => {
|
|
46
|
-
it('warns agents about restricted "outputs" mounts and the remedy', () => {
|
|
47
|
-
expect(RESTRICTED_FS_HELP).toContain('Operation not permitted');
|
|
48
|
-
expect(RESTRICTED_FS_HELP).toContain('outputs');
|
|
49
|
-
expect(RESTRICTED_FS_HELP).toContain('home directory');
|
|
50
|
-
});
|
|
51
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { pullOutcomeFromError, isCloneSourceFailure } from '../clone.js';
|
|
3
|
-
/** Fake an execFileSync error carrying git's stderr. */
|
|
4
|
-
function gitError(stderr) {
|
|
5
|
-
const err = new Error('git failed');
|
|
6
|
-
err.stderr = Buffer.from(stderr);
|
|
7
|
-
return err;
|
|
8
|
-
}
|
|
9
|
-
describe('clone source outcome', () => {
|
|
10
|
-
describe('pullOutcomeFromError()', () => {
|
|
11
|
-
it('classifies an empty remote (brand-new app) as benign', () => {
|
|
12
|
-
const src = pullOutcomeFromError(gitError("fatal: couldn't find remote ref main"));
|
|
13
|
-
expect(src.pulled).toBe(false);
|
|
14
|
-
expect(src.reason).toBe('empty-remote');
|
|
15
|
-
});
|
|
16
|
-
it('classifies an auth failure', () => {
|
|
17
|
-
const src = pullOutcomeFromError(gitError('fatal: Authentication failed for https://runwork.ai'));
|
|
18
|
-
expect(src.reason).toBe('auth');
|
|
19
|
-
});
|
|
20
|
-
it('classifies a network failure', () => {
|
|
21
|
-
const src = pullOutcomeFromError(gitError('fatal: unable to access: Could not resolve host: runwork.ai'));
|
|
22
|
-
expect(src.reason).toBe('network');
|
|
23
|
-
});
|
|
24
|
-
it('classifies a missing remote', () => {
|
|
25
|
-
const src = pullOutcomeFromError(gitError("fatal: 'runwork' does not appear to be a git repository"));
|
|
26
|
-
expect(src.reason).toBe('no-remote');
|
|
27
|
-
});
|
|
28
|
-
it('preserves the raw stderr as detail', () => {
|
|
29
|
-
const src = pullOutcomeFromError(gitError('fatal: Authentication failed'));
|
|
30
|
-
expect(src.detail).toContain('Authentication failed');
|
|
31
|
-
});
|
|
32
|
-
});
|
|
33
|
-
describe('isCloneSourceFailure()', () => {
|
|
34
|
-
it('is false for a successful pull', () => {
|
|
35
|
-
expect(isCloneSourceFailure({ pulled: true })).toBe(false);
|
|
36
|
-
});
|
|
37
|
-
it('is false for an empty remote (expected for new apps)', () => {
|
|
38
|
-
expect(isCloneSourceFailure({ pulled: false, reason: 'empty-remote' })).toBe(false);
|
|
39
|
-
});
|
|
40
|
-
it.each(['auth', 'network', 'no-remote', 'unknown'])('is true for a real %s failure (template-only scaffold)', (reason) => {
|
|
41
|
-
const src = { pulled: false, reason };
|
|
42
|
-
expect(isCloneSourceFailure(src)).toBe(true);
|
|
43
|
-
});
|
|
44
|
-
});
|
|
45
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { __testing } from '../info.js';
|
|
3
|
-
const { mergeSources, padName } = __testing;
|
|
4
|
-
describe('mergeSources — bad data resilience', () => {
|
|
5
|
-
it('drops blueprint entries with missing name', () => {
|
|
6
|
-
const map = mergeSources([
|
|
7
|
-
{ name: 'good', extra: {} },
|
|
8
|
-
{ name: undefined, extra: {} },
|
|
9
|
-
{ name: '', extra: {} },
|
|
10
|
-
], [], (item) => item.name ?? '', 'app-1');
|
|
11
|
-
expect(Array.from(map.keys())).toEqual(['good']);
|
|
12
|
-
});
|
|
13
|
-
it('drops server items whose name resolver returns undefined or empty', () => {
|
|
14
|
-
const map = mergeSources([], [
|
|
15
|
-
{ name: 'good', appId: 'app-1', appName: 'My App', deploymentMode: 'preview' },
|
|
16
|
-
{ name: undefined, appId: 'app-1', appName: 'My App', deploymentMode: 'preview' },
|
|
17
|
-
{ name: '', appId: 'app-1', appName: 'My App', deploymentMode: 'preview' },
|
|
18
|
-
], (item) => item.name ?? '', 'app-1');
|
|
19
|
-
expect(Array.from(map.keys())).toEqual(['good']);
|
|
20
|
-
});
|
|
21
|
-
it('skips server items belonging to other apps', () => {
|
|
22
|
-
const map = mergeSources([], [
|
|
23
|
-
{ name: 'mine', appId: 'app-1', appName: 'A', deploymentMode: 'preview' },
|
|
24
|
-
{ name: 'theirs', appId: 'app-2', appName: 'B', deploymentMode: 'preview' },
|
|
25
|
-
], (item) => item.name ?? '', 'app-1');
|
|
26
|
-
expect(Array.from(map.keys())).toEqual(['mine']);
|
|
27
|
-
});
|
|
28
|
-
it('merges blueprint and server entries by name', () => {
|
|
29
|
-
const map = mergeSources([{ name: 'agent-x', extra: { type: 'task' } }], [
|
|
30
|
-
{ name: 'agent-x', appId: 'app-1', appName: 'A', deploymentMode: 'production' },
|
|
31
|
-
{ name: 'agent-y', appId: 'app-1', appName: 'A', deploymentMode: 'preview' },
|
|
32
|
-
], (item) => item.name ?? '', 'app-1');
|
|
33
|
-
const x = map.get('agent-x');
|
|
34
|
-
const y = map.get('agent-y');
|
|
35
|
-
expect(x?.sources).toEqual(['blueprint', 'production']);
|
|
36
|
-
expect(x?.blueprintExtra).toEqual({ type: 'task' });
|
|
37
|
-
expect(y?.sources).toEqual(['preview']);
|
|
38
|
-
});
|
|
39
|
-
});
|
|
40
|
-
describe('padName — defensive printer', () => {
|
|
41
|
-
it('pads valid names to the requested width', () => {
|
|
42
|
-
expect(padName('foo', 8)).toBe('foo ');
|
|
43
|
-
});
|
|
44
|
-
it('returns a placeholder for undefined / null / empty inputs', () => {
|
|
45
|
-
expect(padName(undefined, 12)).toContain('(unnamed)');
|
|
46
|
-
expect(padName(null, 12)).toContain('(unnamed)');
|
|
47
|
-
expect(padName('', 12)).toContain('(unnamed)');
|
|
48
|
-
// Placeholder is also padded to the requested width.
|
|
49
|
-
expect(padName(undefined, 12).length).toBe(12);
|
|
50
|
-
});
|
|
51
|
-
it('does not throw on non-string inputs', () => {
|
|
52
|
-
expect(() => padName(42, 8)).not.toThrow();
|
|
53
|
-
expect(() => padName({}, 8)).not.toThrow();
|
|
54
|
-
});
|
|
55
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { buildExternalMcpEntries } from '../mcp-entries.js';
|
|
3
|
-
const PLATFORM_KEY = 'rk_ws_live_supersecretplatformkey';
|
|
4
|
-
function server(overrides) {
|
|
5
|
-
return {
|
|
6
|
-
id: 'srv-1',
|
|
7
|
-
name: 'example',
|
|
8
|
-
url: 'https://mcp.example.com',
|
|
9
|
-
transport: 'streamable-http',
|
|
10
|
-
enabled: true,
|
|
11
|
-
addedAt: 0,
|
|
12
|
-
addedBy: 'user-1',
|
|
13
|
-
...overrides,
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
describe('buildExternalMcpEntries', () => {
|
|
17
|
-
it('never injects the Runwork platform key onto external entries', () => {
|
|
18
|
-
const entries = buildExternalMcpEntries([
|
|
19
|
-
server({ id: 'a', authType: 'header' }),
|
|
20
|
-
server({ id: 'b', authType: 'oauth' }),
|
|
21
|
-
server({ id: 'c', authType: 'none' }),
|
|
22
|
-
server({ id: 'd' }), // authType unset
|
|
23
|
-
], { a: { Authorization: 'Bearer user-token' } });
|
|
24
|
-
// Regression: the platform key must not appear anywhere in the output.
|
|
25
|
-
expect(JSON.stringify(entries)).not.toContain(PLATFORM_KEY);
|
|
26
|
-
});
|
|
27
|
-
it('injects resolved per-server headers for header-auth servers', () => {
|
|
28
|
-
const entries = buildExternalMcpEntries([server({ id: 'a', authType: 'header' })], { a: { Authorization: 'Bearer tok', 'X-Api-Key': 'key123' } });
|
|
29
|
-
expect(entries[0].headers).toEqual({ Authorization: 'Bearer tok', 'X-Api-Key': 'key123' });
|
|
30
|
-
});
|
|
31
|
-
it('emits no auth header for oauth servers (local agent runs its own flow)', () => {
|
|
32
|
-
const entries = buildExternalMcpEntries([server({ id: 'a', authType: 'oauth' })], { a: { Authorization: 'Bearer should-not-be-used' } });
|
|
33
|
-
expect(entries[0].headers).toBeUndefined();
|
|
34
|
-
});
|
|
35
|
-
it('emits no auth header for none/unset servers', () => {
|
|
36
|
-
const entries = buildExternalMcpEntries([server({ id: 'a', authType: 'none' }), server({ id: 'b' })], {});
|
|
37
|
-
expect(entries[0].headers).toBeUndefined();
|
|
38
|
-
expect(entries[1].headers).toBeUndefined();
|
|
39
|
-
});
|
|
40
|
-
it('omits headers when a header-auth server has no resolved credentials', () => {
|
|
41
|
-
const entries = buildExternalMcpEntries([server({ id: 'a', authType: 'header' })], {});
|
|
42
|
-
expect(entries[0].headers).toBeUndefined();
|
|
43
|
-
});
|
|
44
|
-
it('skips disabled servers', () => {
|
|
45
|
-
const entries = buildExternalMcpEntries([server({ id: 'a', enabled: false })], {});
|
|
46
|
-
expect(entries).toHaveLength(0);
|
|
47
|
-
});
|
|
48
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { resolvePersona } from '../setup.js';
|
|
3
|
-
/**
|
|
4
|
-
* resolvePersona decides what persona ends up in setup.json. The `--persona`
|
|
5
|
-
* flag (set by the desktop onboarding flow) wins; otherwise an existing persona
|
|
6
|
-
* on disk is preserved so a manual `runwork setup` re-run does not wipe it.
|
|
7
|
-
*/
|
|
8
|
-
describe('resolvePersona', () => {
|
|
9
|
-
it('maps a valid --persona flag to level and label', () => {
|
|
10
|
-
expect(resolvePersona('1', undefined)).toEqual({ level: 1, label: 'everyday' });
|
|
11
|
-
expect(resolvePersona('2', undefined)).toEqual({ level: 2, label: 'curious' });
|
|
12
|
-
expect(resolvePersona('3', undefined)).toEqual({ level: 3, label: 'engineer' });
|
|
13
|
-
});
|
|
14
|
-
it('preserves the existing persona when no flag is given', () => {
|
|
15
|
-
const existing = { level: 2, label: 'curious' };
|
|
16
|
-
expect(resolvePersona(undefined, existing)).toEqual(existing);
|
|
17
|
-
});
|
|
18
|
-
it('falls back to the existing persona for an invalid flag', () => {
|
|
19
|
-
const existing = { level: 3, label: 'engineer' };
|
|
20
|
-
expect(resolvePersona('99', existing)).toEqual(existing);
|
|
21
|
-
expect(resolvePersona('abc', existing)).toEqual(existing);
|
|
22
|
-
expect(resolvePersona('0', existing)).toEqual(existing);
|
|
23
|
-
});
|
|
24
|
-
it('returns undefined when there is no flag and nothing on disk', () => {
|
|
25
|
-
expect(resolvePersona(undefined, undefined)).toBeUndefined();
|
|
26
|
-
});
|
|
27
|
-
it('prefers the flag over an existing on-disk persona', () => {
|
|
28
|
-
const existing = { level: 1, label: 'everyday' };
|
|
29
|
-
expect(resolvePersona('3', existing)).toEqual({ level: 3, label: 'engineer' });
|
|
30
|
-
});
|
|
31
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
-
vi.mock('../../auth/store.js', () => ({
|
|
3
|
-
getCredentials: vi.fn(),
|
|
4
|
-
saveCredentials: vi.fn(),
|
|
5
|
-
requireAuth: vi.fn(),
|
|
6
|
-
}));
|
|
7
|
-
import { getCredentials, saveCredentials } from '../../auth/store.js';
|
|
8
|
-
import { resolveAndPersistWorkspace } from '../setup.js';
|
|
9
|
-
const mockedGetCredentials = vi.mocked(getCredentials);
|
|
10
|
-
const mockedSaveCredentials = vi.mocked(saveCredentials);
|
|
11
|
-
const baseCreds = {
|
|
12
|
-
apiKey: 'rw_test',
|
|
13
|
-
email: 'user@example.com',
|
|
14
|
-
baseUrl: 'https://runwork.ai',
|
|
15
|
-
};
|
|
16
|
-
function buildClient(overrides = {}) {
|
|
17
|
-
return {
|
|
18
|
-
listWorkspaces: overrides.listWorkspaces ?? vi.fn().mockResolvedValue([
|
|
19
|
-
{ id: 'ws-motaword', name: 'MotaWord', slug: 'motaword' },
|
|
20
|
-
{ id: 'ws-personal', name: 'Murat Boyraz\'s Workspace', slug: 'murat' },
|
|
21
|
-
]),
|
|
22
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
beforeEach(() => {
|
|
26
|
-
vi.clearAllMocks();
|
|
27
|
-
mockedGetCredentials.mockReturnValue(baseCreds);
|
|
28
|
-
vi.spyOn(console, 'error').mockImplementation(() => { });
|
|
29
|
-
vi.spyOn(console, 'log').mockImplementation(() => { });
|
|
30
|
-
});
|
|
31
|
-
describe('resolveAndPersistWorkspace', () => {
|
|
32
|
-
it('persists the workspace picked via --workspace flag into credentials', async () => {
|
|
33
|
-
const client = buildClient();
|
|
34
|
-
const result = await resolveAndPersistWorkspace(client, { workspace: 'ws-motaword' });
|
|
35
|
-
expect(result).toEqual({
|
|
36
|
-
workspaceId: 'ws-motaword',
|
|
37
|
-
workspaceName: 'MotaWord',
|
|
38
|
-
workspaceSlug: 'motaword',
|
|
39
|
-
});
|
|
40
|
-
expect(mockedSaveCredentials).toHaveBeenCalledTimes(1);
|
|
41
|
-
expect(mockedSaveCredentials).toHaveBeenCalledWith({
|
|
42
|
-
...baseCreds,
|
|
43
|
-
defaultWorkspaceId: 'ws-motaword',
|
|
44
|
-
defaultWorkspaceName: 'MotaWord',
|
|
45
|
-
});
|
|
46
|
-
});
|
|
47
|
-
it('exits with error when --workspace id is not in the user\'s accessible workspaces', async () => {
|
|
48
|
-
const client = buildClient();
|
|
49
|
-
const exitSpy = vi.spyOn(process, 'exit').mockImplementation(((code) => {
|
|
50
|
-
throw new Error(`process.exit(${code})`);
|
|
51
|
-
}));
|
|
52
|
-
await expect(resolveAndPersistWorkspace(client, { workspace: 'ws-unknown' })).rejects.toThrow('process.exit(1)');
|
|
53
|
-
expect(exitSpy).toHaveBeenCalledWith(1);
|
|
54
|
-
expect(mockedSaveCredentials).not.toHaveBeenCalled();
|
|
55
|
-
expect(console.error).toHaveBeenCalledWith(expect.stringContaining('ws-unknown'));
|
|
56
|
-
});
|
|
57
|
-
it('does not overwrite other credential fields when persisting', async () => {
|
|
58
|
-
const richCreds = {
|
|
59
|
-
...baseCreds,
|
|
60
|
-
defaultWorkspaceId: 'ws-old',
|
|
61
|
-
defaultWorkspaceName: 'Old',
|
|
62
|
-
};
|
|
63
|
-
mockedGetCredentials.mockReturnValue(richCreds);
|
|
64
|
-
const client = buildClient();
|
|
65
|
-
await resolveAndPersistWorkspace(client, { workspace: 'ws-motaword' });
|
|
66
|
-
expect(mockedSaveCredentials).toHaveBeenCalledWith({
|
|
67
|
-
apiKey: 'rw_test',
|
|
68
|
-
email: 'user@example.com',
|
|
69
|
-
baseUrl: 'https://runwork.ai',
|
|
70
|
-
defaultWorkspaceId: 'ws-motaword',
|
|
71
|
-
defaultWorkspaceName: 'MotaWord',
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
it('skips persistence when no credentials are present', async () => {
|
|
75
|
-
mockedGetCredentials.mockReturnValue(null);
|
|
76
|
-
const client = buildClient();
|
|
77
|
-
const result = await resolveAndPersistWorkspace(client, { workspace: 'ws-motaword' });
|
|
78
|
-
expect(result.workspaceId).toBe('ws-motaword');
|
|
79
|
-
expect(mockedSaveCredentials).not.toHaveBeenCalled();
|
|
80
|
-
});
|
|
81
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|