runwork 0.15.0 → 0.15.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +19272 -116
- package/package.json +4 -4
- package/dist/__tests__/curl-parser.test.d.ts +0 -1
- package/dist/__tests__/curl-parser.test.js +0 -250
- package/dist/__tests__/install-scripts.test.d.ts +0 -1
- package/dist/__tests__/install-scripts.test.js +0 -280
- package/dist/__tests__/types-manager.test.d.ts +0 -1
- package/dist/__tests__/types-manager.test.js +0 -89
- package/dist/agents/__tests__/chatgpt-registry.test.d.ts +0 -1
- package/dist/agents/__tests__/chatgpt-registry.test.js +0 -61
- package/dist/agents/__tests__/claude-code-managed-block.test.d.ts +0 -1
- package/dist/agents/__tests__/claude-code-managed-block.test.js +0 -97
- package/dist/agents/__tests__/claude-code-plugin.test.d.ts +0 -1
- package/dist/agents/__tests__/claude-code-plugin.test.js +0 -47
- package/dist/agents/__tests__/claude-code-stats.test.d.ts +0 -1
- package/dist/agents/__tests__/claude-code-stats.test.js +0 -390
- package/dist/agents/__tests__/claude-desktop-memory.test.d.ts +0 -1
- package/dist/agents/__tests__/claude-desktop-memory.test.js +0 -154
- package/dist/agents/__tests__/claude-desktop-plugin-tree.test.d.ts +0 -1
- package/dist/agents/__tests__/claude-desktop-plugin-tree.test.js +0 -161
- package/dist/agents/__tests__/claude-desktop-plugin.test.d.ts +0 -1
- package/dist/agents/__tests__/claude-desktop-plugin.test.js +0 -117
- package/dist/agents/__tests__/claude-desktop-rpm.test.d.ts +0 -1
- package/dist/agents/__tests__/claude-desktop-rpm.test.js +0 -126
- package/dist/agents/__tests__/claude-desktop-stats.test.d.ts +0 -1
- package/dist/agents/__tests__/claude-desktop-stats.test.js +0 -280
- package/dist/agents/__tests__/codex-instructions.test.d.ts +0 -1
- package/dist/agents/__tests__/codex-instructions.test.js +0 -57
- package/dist/agents/__tests__/codex-minimum-permissions.test.d.ts +0 -1
- package/dist/agents/__tests__/codex-minimum-permissions.test.js +0 -82
- package/dist/agents/__tests__/codex-stats.test.d.ts +0 -1
- package/dist/agents/__tests__/codex-stats.test.js +0 -370
- package/dist/agents/__tests__/cursor-merge.test.d.ts +0 -1
- package/dist/agents/__tests__/cursor-merge.test.js +0 -66
- package/dist/agents/__tests__/cursor-stats.test.d.ts +0 -1
- package/dist/agents/__tests__/cursor-stats.test.js +0 -183
- package/dist/agents/__tests__/defaults-merge.test.d.ts +0 -1
- package/dist/agents/__tests__/defaults-merge.test.js +0 -268
- package/dist/agents/__tests__/detection.test.d.ts +0 -1
- package/dist/agents/__tests__/detection.test.js +0 -89
- package/dist/agents/__tests__/graceful-degradation.test.d.ts +0 -1
- package/dist/agents/__tests__/graceful-degradation.test.js +0 -129
- package/dist/agents/__tests__/instruction-hint.test.d.ts +0 -1
- package/dist/agents/__tests__/instruction-hint.test.js +0 -69
- package/dist/agents/__tests__/intro-skill.test.d.ts +0 -1
- package/dist/agents/__tests__/intro-skill.test.js +0 -193
- package/dist/agents/__tests__/schema-validation.test.d.ts +0 -1
- package/dist/agents/__tests__/schema-validation.test.js +0 -212
- package/dist/agents/__tests__/skill-slug.test.d.ts +0 -1
- package/dist/agents/__tests__/skill-slug.test.js +0 -77
- package/dist/agents/claude-code.d.ts +0 -53
- package/dist/agents/claude-code.js +0 -754
- package/dist/agents/claude-desktop-plugin-tree.d.ts +0 -59
- package/dist/agents/claude-desktop-plugin-tree.js +0 -143
- package/dist/agents/claude-desktop.d.ts +0 -47
- package/dist/agents/claude-desktop.js +0 -684
- package/dist/agents/cline.d.ts +0 -15
- package/dist/agents/cline.js +0 -130
- package/dist/agents/codex.d.ts +0 -44
- package/dist/agents/codex.js +0 -453
- package/dist/agents/conversation-skills.d.ts +0 -18
- package/dist/agents/conversation-skills.js +0 -229
- package/dist/agents/cursor.d.ts +0 -48
- package/dist/agents/cursor.js +0 -324
- package/dist/agents/default-config.d.ts +0 -30
- package/dist/agents/default-config.js +0 -67
- package/dist/agents/defaults-merge.d.ts +0 -72
- package/dist/agents/defaults-merge.js +0 -131
- package/dist/agents/detect.d.ts +0 -4
- package/dist/agents/detect.js +0 -67
- package/dist/agents/detection.d.ts +0 -18
- package/dist/agents/detection.js +0 -94
- package/dist/agents/gemini.d.ts +0 -15
- package/dist/agents/gemini.js +0 -122
- package/dist/agents/generic-adapter.d.ts +0 -25
- package/dist/agents/generic-adapter.js +0 -151
- package/dist/agents/intro-skill.d.ts +0 -45
- package/dist/agents/intro-skill.js +0 -447
- package/dist/agents/registry-data.d.ts +0 -192
- package/dist/agents/registry-data.js +0 -669
- package/dist/agents/registry.d.ts +0 -13
- package/dist/agents/registry.js +0 -36
- package/dist/agents/runtime-detection.d.ts +0 -82
- package/dist/agents/runtime-detection.js +0 -271
- package/dist/agents/session-start-hook.d.ts +0 -37
- package/dist/agents/session-start-hook.js +0 -159
- package/dist/agents/types.d.ts +0 -171
- package/dist/agents/types.js +0 -75
- package/dist/agents/utils/instruction-hint.d.ts +0 -21
- package/dist/agents/utils/instruction-hint.js +0 -108
- package/dist/agents/utils/json-config.d.ts +0 -19
- package/dist/agents/utils/json-config.js +0 -69
- package/dist/agents/utils/toml-config.d.ts +0 -8
- package/dist/agents/utils/toml-config.js +0 -27
- package/dist/agents/windsurf.d.ts +0 -14
- package/dist/agents/windsurf.js +0 -102
- package/dist/api/__tests__/client.test.d.ts +0 -1
- package/dist/api/__tests__/client.test.js +0 -272
- package/dist/api/client.d.ts +0 -326
- package/dist/api/client.js +0 -427
- package/dist/auth/__tests__/login-flow.test.d.ts +0 -1
- package/dist/auth/__tests__/login-flow.test.js +0 -101
- package/dist/auth/__tests__/store.test.d.ts +0 -1
- package/dist/auth/__tests__/store.test.js +0 -132
- package/dist/auth/login-flow.d.ts +0 -26
- package/dist/auth/login-flow.js +0 -137
- package/dist/auth/store.d.ts +0 -5
- package/dist/auth/store.js +0 -62
- package/dist/commands/__tests__/clone-args.test.d.ts +0 -1
- package/dist/commands/__tests__/clone-args.test.js +0 -51
- package/dist/commands/__tests__/clone-source-result.test.d.ts +0 -1
- package/dist/commands/__tests__/clone-source-result.test.js +0 -45
- package/dist/commands/__tests__/info-merge.test.d.ts +0 -1
- package/dist/commands/__tests__/info-merge.test.js +0 -55
- package/dist/commands/__tests__/mcp-entries.test.d.ts +0 -1
- package/dist/commands/__tests__/mcp-entries.test.js +0 -48
- package/dist/commands/__tests__/setup-persona.test.d.ts +0 -1
- package/dist/commands/__tests__/setup-persona.test.js +0 -31
- package/dist/commands/__tests__/setup.test.d.ts +0 -1
- package/dist/commands/__tests__/setup.test.js +0 -81
- package/dist/commands/__tests__/sync-redetect.test.d.ts +0 -1
- package/dist/commands/__tests__/sync-redetect.test.js +0 -96
- package/dist/commands/__tests__/sync-telemetry.test.d.ts +0 -1
- package/dist/commands/__tests__/sync-telemetry.test.js +0 -281
- package/dist/commands/__tests__/upgrade.test.d.ts +0 -1
- package/dist/commands/__tests__/upgrade.test.js +0 -157
- package/dist/commands/agents.d.ts +0 -2
- package/dist/commands/agents.js +0 -160
- package/dist/commands/api-keys.d.ts +0 -2
- package/dist/commands/api-keys.js +0 -95
- package/dist/commands/apps.d.ts +0 -2
- package/dist/commands/apps.js +0 -82
- package/dist/commands/build-plugin.d.ts +0 -2
- package/dist/commands/build-plugin.js +0 -135
- package/dist/commands/clone.d.ts +0 -60
- package/dist/commands/clone.js +0 -271
- package/dist/commands/components.d.ts +0 -2
- package/dist/commands/components.js +0 -43
- package/dist/commands/deploy.d.ts +0 -2
- package/dist/commands/deploy.js +0 -279
- package/dist/commands/dev.d.ts +0 -11
- package/dist/commands/dev.js +0 -1011
- package/dist/commands/doctor.d.ts +0 -2
- package/dist/commands/doctor.js +0 -230
- package/dist/commands/endpoints.d.ts +0 -2
- package/dist/commands/endpoints.js +0 -189
- package/dist/commands/entities.d.ts +0 -2
- package/dist/commands/entities.js +0 -198
- package/dist/commands/files.d.ts +0 -2
- package/dist/commands/files.js +0 -193
- package/dist/commands/inbox.d.ts +0 -11
- package/dist/commands/inbox.js +0 -60
- package/dist/commands/info.d.ts +0 -178
- package/dist/commands/info.js +0 -455
- package/dist/commands/init.d.ts +0 -21
- package/dist/commands/init.js +0 -185
- package/dist/commands/integrations.d.ts +0 -2
- package/dist/commands/integrations.js +0 -233
- package/dist/commands/login.d.ts +0 -2
- package/dist/commands/login.js +0 -44
- package/dist/commands/logout.d.ts +0 -2
- package/dist/commands/logout.js +0 -13
- package/dist/commands/logs.d.ts +0 -2
- package/dist/commands/logs.js +0 -232
- package/dist/commands/mcp-entries.d.ts +0 -13
- package/dist/commands/mcp-entries.js +0 -26
- package/dist/commands/mcp.d.ts +0 -2
- package/dist/commands/mcp.js +0 -245
- package/dist/commands/open.d.ts +0 -2
- package/dist/commands/open.js +0 -53
- package/dist/commands/resume.d.ts +0 -2
- package/dist/commands/resume.js +0 -289
- package/dist/commands/save-convo.d.ts +0 -8
- package/dist/commands/save-convo.js +0 -20
- package/dist/commands/schedules.d.ts +0 -2
- package/dist/commands/schedules.js +0 -221
- package/dist/commands/setup.d.ts +0 -27
- package/dist/commands/setup.js +0 -177
- package/dist/commands/share-convo.d.ts +0 -24
- package/dist/commands/share-convo.js +0 -167
- package/dist/commands/skills.d.ts +0 -2
- package/dist/commands/skills.js +0 -352
- package/dist/commands/sync-telemetry.d.ts +0 -33
- package/dist/commands/sync-telemetry.js +0 -186
- package/dist/commands/sync.d.ts +0 -37
- package/dist/commands/sync.js +0 -702
- package/dist/commands/uninstall.d.ts +0 -2
- package/dist/commands/uninstall.js +0 -145
- package/dist/commands/upgrade.d.ts +0 -14
- package/dist/commands/upgrade.js +0 -217
- package/dist/commands/validate.d.ts +0 -2
- package/dist/commands/validate.js +0 -89
- package/dist/commands/welcome.d.ts +0 -1
- package/dist/commands/welcome.js +0 -86
- package/dist/commands/workflows.d.ts +0 -2
- package/dist/commands/workflows.js +0 -187
- package/dist/deploy/__tests__/deploy-state.test.d.ts +0 -1
- package/dist/deploy/__tests__/deploy-state.test.js +0 -80
- package/dist/deploy/__tests__/deploy-status.test.d.ts +0 -1
- package/dist/deploy/__tests__/deploy-status.test.js +0 -41
- package/dist/deploy/__tests__/detach-args.test.d.ts +0 -1
- package/dist/deploy/__tests__/detach-args.test.js +0 -30
- package/dist/deploy/deploy-state.d.ts +0 -36
- package/dist/deploy/deploy-state.js +0 -63
- package/dist/deploy/deploy-status.d.ts +0 -21
- package/dist/deploy/deploy-status.js +0 -36
- package/dist/deploy/detach.d.ts +0 -32
- package/dist/deploy/detach.js +0 -71
- package/dist/dev/__tests__/attach.test.d.ts +0 -1
- package/dist/dev/__tests__/attach.test.js +0 -296
- package/dist/dev/__tests__/detach.test.d.ts +0 -1
- package/dist/dev/__tests__/detach.test.js +0 -404
- package/dist/dev/__tests__/preview-url-poller.test.d.ts +0 -1
- package/dist/dev/__tests__/preview-url-poller.test.js +0 -149
- package/dist/dev/__tests__/session.test.d.ts +0 -1
- package/dist/dev/__tests__/session.test.js +0 -446
- package/dist/dev/__tests__/startup-sync.test.d.ts +0 -1
- package/dist/dev/__tests__/startup-sync.test.js +0 -32
- package/dist/dev/__tests__/stop.test.d.ts +0 -1
- package/dist/dev/__tests__/stop.test.js +0 -172
- package/dist/dev/attach.d.ts +0 -120
- package/dist/dev/attach.js +0 -269
- package/dist/dev/detach.d.ts +0 -187
- package/dist/dev/detach.js +0 -292
- package/dist/dev/preview-url-poller.d.ts +0 -35
- package/dist/dev/preview-url-poller.js +0 -50
- package/dist/dev/session.d.ts +0 -175
- package/dist/dev/session.js +0 -258
- package/dist/dev/startup-sync.d.ts +0 -23
- package/dist/dev/startup-sync.js +0 -14
- package/dist/dev/stop.d.ts +0 -52
- package/dist/dev/stop.js +0 -101
- package/dist/devtools/registry-data.d.ts +0 -46
- package/dist/devtools/registry-data.js +0 -40
- package/dist/generated/bundled-types.d.ts +0 -1
- package/dist/generated/bundled-types.js +0 -46
- package/dist/generated/version.d.ts +0 -1
- package/dist/generated/version.js +0 -2
- package/dist/git/__tests__/auto-commit.test.d.ts +0 -1
- package/dist/git/__tests__/auto-commit.test.js +0 -431
- package/dist/git/__tests__/classify-sync-error.test.d.ts +0 -1
- package/dist/git/__tests__/classify-sync-error.test.js +0 -57
- package/dist/git/__tests__/credential-helper-e2e.test.d.ts +0 -21
- package/dist/git/__tests__/credential-helper-e2e.test.js +0 -195
- package/dist/git/__tests__/credentials.test.d.ts +0 -1
- package/dist/git/__tests__/credentials.test.js +0 -141
- package/dist/git/__tests__/deploy-guard.test.d.ts +0 -1
- package/dist/git/__tests__/deploy-guard.test.js +0 -61
- package/dist/git/__tests__/ensure-git-credential-helper.test.d.ts +0 -1
- package/dist/git/__tests__/ensure-git-credential-helper.test.js +0 -133
- package/dist/git/__tests__/ensure-runwork-remote.test.d.ts +0 -1
- package/dist/git/__tests__/ensure-runwork-remote.test.js +0 -109
- package/dist/git/__tests__/identity.test.d.ts +0 -1
- package/dist/git/__tests__/identity.test.js +0 -146
- package/dist/git/__tests__/manifest.test.d.ts +0 -1
- package/dist/git/__tests__/manifest.test.js +0 -446
- package/dist/git/__tests__/preflight-resolution.test.d.ts +0 -1
- package/dist/git/__tests__/preflight-resolution.test.js +0 -366
- package/dist/git/__tests__/preflight.test.d.ts +0 -1
- package/dist/git/__tests__/preflight.test.js +0 -36
- package/dist/git/__tests__/repo-config.test.d.ts +0 -1
- package/dist/git/__tests__/repo-config.test.js +0 -26
- package/dist/git/__tests__/sync.test.d.ts +0 -1
- package/dist/git/__tests__/sync.test.js +0 -405
- package/dist/git/auto-commit.d.ts +0 -35
- package/dist/git/auto-commit.js +0 -293
- package/dist/git/classify-sync-error.d.ts +0 -21
- package/dist/git/classify-sync-error.js +0 -111
- package/dist/git/credentials.d.ts +0 -75
- package/dist/git/credentials.js +0 -164
- package/dist/git/critical-files.d.ts +0 -20
- package/dist/git/critical-files.js +0 -68
- package/dist/git/deploy-guard.d.ts +0 -53
- package/dist/git/deploy-guard.js +0 -78
- package/dist/git/identity.d.ts +0 -44
- package/dist/git/identity.js +0 -133
- package/dist/git/preflight.d.ts +0 -57
- package/dist/git/preflight.js +0 -276
- package/dist/git/remote.d.ts +0 -37
- package/dist/git/remote.js +0 -75
- package/dist/git/repo-config.d.ts +0 -8
- package/dist/git/repo-config.js +0 -29
- package/dist/git/sync.d.ts +0 -15
- package/dist/git/sync.js +0 -159
- package/dist/health/__tests__/checks.test.d.ts +0 -1
- package/dist/health/__tests__/checks.test.js +0 -357
- package/dist/health/__tests__/cli-distribution-checks.test.d.ts +0 -1
- package/dist/health/__tests__/cli-distribution-checks.test.js +0 -196
- package/dist/health/__tests__/fix.test.d.ts +0 -1
- package/dist/health/__tests__/fix.test.js +0 -72
- package/dist/health/__tests__/runner-filter.test.d.ts +0 -1
- package/dist/health/__tests__/runner-filter.test.js +0 -61
- package/dist/health/checks.d.ts +0 -42
- package/dist/health/checks.js +0 -636
- package/dist/health/fix.d.ts +0 -22
- package/dist/health/fix.js +0 -62
- package/dist/health/runner.d.ts +0 -8
- package/dist/health/runner.js +0 -47
- package/dist/health/types.d.ts +0 -12
- package/dist/health/types.js +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/logs/__tests__/tailer-format.test.d.ts +0 -1
- package/dist/logs/__tests__/tailer-format.test.js +0 -43
- package/dist/logs/tailer.d.ts +0 -17
- package/dist/logs/tailer.js +0 -217
- package/dist/sync/__tests__/change-detect.test.d.ts +0 -1
- package/dist/sync/__tests__/change-detect.test.js +0 -123
- package/dist/sync/__tests__/hash.test.d.ts +0 -1
- package/dist/sync/__tests__/hash.test.js +0 -18
- package/dist/sync/change-detect.d.ts +0 -19
- package/dist/sync/change-detect.js +0 -136
- package/dist/sync/conflict-ui.d.ts +0 -5
- package/dist/sync/conflict-ui.js +0 -78
- package/dist/sync/executor.d.ts +0 -23
- package/dist/sync/executor.js +0 -102
- package/dist/sync/hash.d.ts +0 -1
- package/dist/sync/hash.js +0 -4
- package/dist/sync/types.d.ts +0 -24
- package/dist/sync/types.js +0 -1
- package/dist/template/manifest.d.ts +0 -17
- package/dist/template/manifest.js +0 -145
- package/dist/tools/types.d.ts +0 -52
- package/dist/tools/types.js +0 -8
- package/dist/types-manager.d.ts +0 -1
- package/dist/types-manager.js +0 -35
- package/dist/types.d.ts +0 -349
- package/dist/types.js +0 -1
- package/dist/ui/__tests__/banner.test.d.ts +0 -1
- package/dist/ui/__tests__/banner.test.js +0 -98
- package/dist/ui/__tests__/colors.test.d.ts +0 -1
- package/dist/ui/__tests__/colors.test.js +0 -22
- package/dist/ui/__tests__/keyboard.test.d.ts +0 -1
- package/dist/ui/__tests__/keyboard.test.js +0 -34
- package/dist/ui/__tests__/status-line.test.d.ts +0 -1
- package/dist/ui/__tests__/status-line.test.js +0 -54
- package/dist/ui/banner.d.ts +0 -29
- package/dist/ui/banner.js +0 -153
- package/dist/ui/colors.d.ts +0 -4
- package/dist/ui/colors.js +0 -7
- package/dist/ui/keyboard.d.ts +0 -12
- package/dist/ui/keyboard.js +0 -61
- package/dist/ui/status-line.d.ts +0 -6
- package/dist/ui/status-line.js +0 -53
- package/dist/utils/__tests__/format-error.test.d.ts +0 -1
- package/dist/utils/__tests__/format-error.test.js +0 -43
- package/dist/utils/__tests__/help-json.test.d.ts +0 -1
- package/dist/utils/__tests__/help-json.test.js +0 -39
- package/dist/utils/__tests__/http.test.d.ts +0 -1
- package/dist/utils/__tests__/http.test.js +0 -381
- package/dist/utils/__tests__/ignore-matcher.test.d.ts +0 -1
- package/dist/utils/__tests__/ignore-matcher.test.js +0 -205
- package/dist/utils/__tests__/output.test.d.ts +0 -1
- package/dist/utils/__tests__/output.test.js +0 -38
- package/dist/utils/__tests__/prompt.test.d.ts +0 -1
- package/dist/utils/__tests__/prompt.test.js +0 -27
- package/dist/utils/__tests__/resolve.test.d.ts +0 -1
- package/dist/utils/__tests__/resolve.test.js +0 -95
- package/dist/utils/__tests__/sqlite.test.d.ts +0 -1
- package/dist/utils/__tests__/sqlite.test.js +0 -89
- package/dist/utils/agent-guidance.d.ts +0 -47
- package/dist/utils/agent-guidance.js +0 -128
- package/dist/utils/app-info.d.ts +0 -70
- package/dist/utils/app-info.js +0 -167
- package/dist/utils/curl-parser.d.ts +0 -12
- package/dist/utils/curl-parser.js +0 -162
- package/dist/utils/data-input.d.ts +0 -1
- package/dist/utils/data-input.js +0 -38
- package/dist/utils/format-error.d.ts +0 -10
- package/dist/utils/format-error.js +0 -38
- package/dist/utils/fs.d.ts +0 -5
- package/dist/utils/fs.js +0 -23
- package/dist/utils/help-json.d.ts +0 -70
- package/dist/utils/help-json.js +0 -88
- package/dist/utils/http.d.ts +0 -46
- package/dist/utils/http.js +0 -421
- package/dist/utils/ignore-matcher.d.ts +0 -47
- package/dist/utils/ignore-matcher.js +0 -132
- package/dist/utils/output.d.ts +0 -17
- package/dist/utils/output.js +0 -27
- package/dist/utils/prompt.d.ts +0 -5
- package/dist/utils/prompt.js +0 -42
- package/dist/utils/resolve.d.ts +0 -12
- package/dist/utils/resolve.js +0 -52
- package/dist/utils/setup-state.d.ts +0 -3
- package/dist/utils/setup-state.js +0 -19
- package/dist/utils/sqlite-adapter.d.ts +0 -48
- package/dist/utils/sqlite-adapter.js +0 -147
- package/dist/utils/sqlite.d.ts +0 -14
- package/dist/utils/sqlite.js +0 -14
- package/dist/utils/subprocess.d.ts +0 -19
- package/dist/utils/subprocess.js +0 -27
- package/dist/utils/which.d.ts +0 -14
- package/dist/utils/which.js +0 -47
- package/dist/utils/zip.d.ts +0 -7
- package/dist/utils/zip.js +0 -42
- package/dist/validate/__tests__/validate.test.d.ts +0 -1
- package/dist/validate/__tests__/validate.test.js +0 -42
- package/dist/validate/freshness.d.ts +0 -28
- package/dist/validate/freshness.js +0 -48
- package/dist/validate/preview.d.ts +0 -21
- package/dist/validate/preview.js +0 -39
- package/dist/workspace/resolve.d.ts +0 -19
- package/dist/workspace/resolve.js +0 -100
package/dist/api/client.js
DELETED
|
@@ -1,427 +0,0 @@
|
|
|
1
|
-
import { httpFetch } from '../utils/http.js';
|
|
2
|
-
const DEFAULT_BASE_URL = 'https://runwork.ai';
|
|
3
|
-
export class ApiClient {
|
|
4
|
-
baseUrl;
|
|
5
|
-
apiKey;
|
|
6
|
-
constructor(credentials) {
|
|
7
|
-
this.baseUrl = credentials.baseUrl || DEFAULT_BASE_URL;
|
|
8
|
-
this.apiKey = credentials.apiKey;
|
|
9
|
-
}
|
|
10
|
-
async request(path, options = {}) {
|
|
11
|
-
const url = `${this.baseUrl}${path}`;
|
|
12
|
-
const headers = {
|
|
13
|
-
'Content-Type': 'application/json',
|
|
14
|
-
...Object.fromEntries(Object.entries(options.headers || {}).filter(([, v]) => v !== undefined)),
|
|
15
|
-
};
|
|
16
|
-
if (this.apiKey) {
|
|
17
|
-
headers['Authorization'] = `Bearer ${this.apiKey}`;
|
|
18
|
-
}
|
|
19
|
-
const response = await httpFetch(url, { ...options, headers });
|
|
20
|
-
if (!response.ok) {
|
|
21
|
-
const body = await response.text();
|
|
22
|
-
throw new Error(`API error ${response.status}: ${body}`);
|
|
23
|
-
}
|
|
24
|
-
return response.json();
|
|
25
|
-
}
|
|
26
|
-
async listWorkspaces() {
|
|
27
|
-
const res = await this.request('/api/dev/workspaces');
|
|
28
|
-
return res.data;
|
|
29
|
-
}
|
|
30
|
-
async listApps(workspaceId) {
|
|
31
|
-
const query = workspaceId ? `?workspaceId=${workspaceId}` : '';
|
|
32
|
-
const res = await this.request(`/api/dev/apps${query}`);
|
|
33
|
-
return res.data;
|
|
34
|
-
}
|
|
35
|
-
async getApp(appId) {
|
|
36
|
-
const res = await this.request(`/api/dev/apps/${appId}`);
|
|
37
|
-
return res.data;
|
|
38
|
-
}
|
|
39
|
-
async initApp(workspaceId, appName) {
|
|
40
|
-
const res = await this.request('/api/dev/init', {
|
|
41
|
-
method: 'POST',
|
|
42
|
-
body: JSON.stringify({ workspaceId, appName }),
|
|
43
|
-
});
|
|
44
|
-
const app = res.data;
|
|
45
|
-
// Server returns `appName` for init, normalize to `name`
|
|
46
|
-
if (!app.name && app.appName) {
|
|
47
|
-
app.name = app.appName;
|
|
48
|
-
}
|
|
49
|
-
return app;
|
|
50
|
-
}
|
|
51
|
-
async startDevSession(appId) {
|
|
52
|
-
const res = await this.request('/api/dev/sessions', {
|
|
53
|
-
method: 'POST',
|
|
54
|
-
body: JSON.stringify({ appId }),
|
|
55
|
-
});
|
|
56
|
-
return res.data;
|
|
57
|
-
}
|
|
58
|
-
async getDevStatus(appId) {
|
|
59
|
-
const res = await this.request(`/api/dev/status/${appId}`);
|
|
60
|
-
return res.data;
|
|
61
|
-
}
|
|
62
|
-
async triggerDeploy(appId) {
|
|
63
|
-
const res = await this.request(`/api/dev/deploy/${appId}`, {
|
|
64
|
-
method: 'POST',
|
|
65
|
-
});
|
|
66
|
-
return res.data;
|
|
67
|
-
}
|
|
68
|
-
async initiateLogin() {
|
|
69
|
-
const res = await this.request('/api/dev/auth/login', { method: 'POST' });
|
|
70
|
-
return res.data;
|
|
71
|
-
}
|
|
72
|
-
async pollLogin(sessionId) {
|
|
73
|
-
try {
|
|
74
|
-
const res = await this.request(`/api/dev/auth/poll/${sessionId}`);
|
|
75
|
-
return res.data;
|
|
76
|
-
}
|
|
77
|
-
catch {
|
|
78
|
-
return null;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
async getAppSkill(appId) {
|
|
82
|
-
const res = await this.request(`/api/dev/skill/${appId}`);
|
|
83
|
-
return res.data;
|
|
84
|
-
}
|
|
85
|
-
async getPreviewLogs(appId) {
|
|
86
|
-
const res = await this.request(`/api/dev/logs/${appId}/preview`);
|
|
87
|
-
return res.data.logs;
|
|
88
|
-
}
|
|
89
|
-
async getProductionLogs(appId, options) {
|
|
90
|
-
const params = new URLSearchParams();
|
|
91
|
-
if (options?.limit !== undefined)
|
|
92
|
-
params.set('limit', String(options.limit));
|
|
93
|
-
if (options?.level)
|
|
94
|
-
params.set('level', options.level);
|
|
95
|
-
if (options?.search)
|
|
96
|
-
params.set('search', options.search);
|
|
97
|
-
if (options?.startTime)
|
|
98
|
-
params.set('startTime', options.startTime);
|
|
99
|
-
if (options?.endTime)
|
|
100
|
-
params.set('endTime', options.endTime);
|
|
101
|
-
const query = params.toString();
|
|
102
|
-
const res = await this.request(`/api/dev/logs/${appId}/production${query ? `?${query}` : ''}`);
|
|
103
|
-
return res.data;
|
|
104
|
-
}
|
|
105
|
-
async getAppEvents(appId, options) {
|
|
106
|
-
const params = new URLSearchParams();
|
|
107
|
-
if (options?.limit !== undefined)
|
|
108
|
-
params.set('limit', String(options.limit));
|
|
109
|
-
if (options?.type)
|
|
110
|
-
params.set('type', options.type);
|
|
111
|
-
if (options?.source)
|
|
112
|
-
params.set('source', options.source);
|
|
113
|
-
if (options?.before)
|
|
114
|
-
params.set('before', options.before);
|
|
115
|
-
const query = params.toString();
|
|
116
|
-
const res = await this.request(`/api/dev/events/${appId}${query ? `?${query}` : ''}`);
|
|
117
|
-
return res.data;
|
|
118
|
-
}
|
|
119
|
-
async downloadSkeleton() {
|
|
120
|
-
const url = `${this.baseUrl}/api/dev/skeleton`;
|
|
121
|
-
const headers = {};
|
|
122
|
-
if (this.apiKey) {
|
|
123
|
-
headers['Authorization'] = `Bearer ${this.apiKey}`;
|
|
124
|
-
}
|
|
125
|
-
const response = await httpFetch(url, { headers });
|
|
126
|
-
if (!response.ok) {
|
|
127
|
-
throw new Error(`Failed to download skeleton: ${response.status}`);
|
|
128
|
-
}
|
|
129
|
-
return response.arrayBuffer();
|
|
130
|
-
}
|
|
131
|
-
async syncFiles(appId, files, deletedFiles) {
|
|
132
|
-
await this.request(`/api/dev/sync/${appId}`, {
|
|
133
|
-
method: 'POST',
|
|
134
|
-
body: JSON.stringify({ files, deletedFiles }),
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
async searchIntegrations(query, limit = 20, workspaceId) {
|
|
138
|
-
const params = new URLSearchParams({ q: query, limit: String(limit) });
|
|
139
|
-
if (workspaceId)
|
|
140
|
-
params.set('workspaceId', workspaceId);
|
|
141
|
-
const res = await this.request(`/api/integrations/search?${params}`);
|
|
142
|
-
return res.data;
|
|
143
|
-
}
|
|
144
|
-
async listConnectedIntegrations(workspaceId) {
|
|
145
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/integrations`);
|
|
146
|
-
return res.data.integrations;
|
|
147
|
-
}
|
|
148
|
-
async getTeamIntegrationUsage(workspaceId) {
|
|
149
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/integrations/team-usage`);
|
|
150
|
-
return res.data.usage;
|
|
151
|
-
}
|
|
152
|
-
/**
|
|
153
|
-
* Get git remote URL for an app.
|
|
154
|
-
* Both canonical ({baseUrl}/api/git/{workspaceId}/{appId}) and
|
|
155
|
-
* subdomain ({slug}.runwork.ai/api/git/{appId}) formats are supported.
|
|
156
|
-
*/
|
|
157
|
-
async getWorkspaceAll(workspaceId) {
|
|
158
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/all`);
|
|
159
|
-
return res.data;
|
|
160
|
-
}
|
|
161
|
-
getGitRemoteUrl(workspaceId, appId) {
|
|
162
|
-
return `${this.baseUrl}/api/git/${workspaceId}/${appId}`;
|
|
163
|
-
}
|
|
164
|
-
// --- Workspace Chat API (skills & MCP) ---
|
|
165
|
-
async listWorkspaceSkills(workspaceId, includeContent = false) {
|
|
166
|
-
const query = includeContent ? '?includeContent=true' : '';
|
|
167
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/skills${query}`);
|
|
168
|
-
return res.data.skills;
|
|
169
|
-
}
|
|
170
|
-
async listExternalSkills(workspaceId) {
|
|
171
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/external-skills`);
|
|
172
|
-
return res.data.skills;
|
|
173
|
-
}
|
|
174
|
-
async importExternalSkill(workspaceId, skill) {
|
|
175
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/external-skills`, { method: 'POST', body: JSON.stringify(skill) });
|
|
176
|
-
return res.data.skill;
|
|
177
|
-
}
|
|
178
|
-
async updateExternalSkill(workspaceId, skillId, skill) {
|
|
179
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/external-skills/${skillId}`, { method: 'PUT', body: JSON.stringify(skill) });
|
|
180
|
-
return res.data.skill;
|
|
181
|
-
}
|
|
182
|
-
async getAppSkillContent(workspaceId, appId) {
|
|
183
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/apps/${appId}/skill`);
|
|
184
|
-
return res.data.skill;
|
|
185
|
-
}
|
|
186
|
-
async listMcpServers(workspaceId) {
|
|
187
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/mcp-servers`);
|
|
188
|
-
return res.data.servers;
|
|
189
|
-
}
|
|
190
|
-
async addMcpServer(workspaceId, server) {
|
|
191
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/mcp-servers`, { method: 'POST', body: JSON.stringify(server) });
|
|
192
|
-
return res.data.server;
|
|
193
|
-
}
|
|
194
|
-
async removeMcpServer(workspaceId, serverId) {
|
|
195
|
-
await this.request(`/api/workspaces/${workspaceId}/mcp-servers/${serverId}`, { method: 'DELETE' });
|
|
196
|
-
}
|
|
197
|
-
/**
|
|
198
|
-
* Resolve decrypted auth headers for header-auth MCP servers, scoped to the
|
|
199
|
-
* authenticated user (their own + workspace-wide credentials). Keyed by server id.
|
|
200
|
-
*/
|
|
201
|
-
async resolveMcpCredentials(workspaceId) {
|
|
202
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/mcp-credentials/resolved`);
|
|
203
|
-
return res.data.servers;
|
|
204
|
-
}
|
|
205
|
-
// --- Community Marketplace ---
|
|
206
|
-
async searchCommunitySkills(query, limit = 10, includeContent = false) {
|
|
207
|
-
const res = await this.request(`/api/community/skills/search?q=${encodeURIComponent(query)}&limit=${limit}&include_content=${includeContent}`);
|
|
208
|
-
return res.data;
|
|
209
|
-
}
|
|
210
|
-
async getCommunitySkillContent(source, skillId) {
|
|
211
|
-
// source is "owner/repo", keep the slash as a path separator (route is /skills/:owner/:repo/:skillId)
|
|
212
|
-
const encodedSource = source.split('/').map(encodeURIComponent).join('/');
|
|
213
|
-
const res = await this.request(`/api/community/skills/${encodedSource}/${encodeURIComponent(skillId)}`);
|
|
214
|
-
return res.data;
|
|
215
|
-
}
|
|
216
|
-
async searchCommunityMcpServers(query, limit = 20) {
|
|
217
|
-
const res = await this.request(`/api/community/mcp-servers/search?q=${encodeURIComponent(query)}&limit=${limit}`);
|
|
218
|
-
return res.data;
|
|
219
|
-
}
|
|
220
|
-
// --- Workspace Registry: Entities ---
|
|
221
|
-
async listEntities(workspaceId) {
|
|
222
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/entities`);
|
|
223
|
-
return res.data.entities;
|
|
224
|
-
}
|
|
225
|
-
async listEntityRecords(workspaceId, entityName, opts) {
|
|
226
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/entities/${encodeURIComponent(entityName)}/list`, {
|
|
227
|
-
method: 'POST',
|
|
228
|
-
body: JSON.stringify({
|
|
229
|
-
limit: opts?.limit,
|
|
230
|
-
cursor: opts?.cursor,
|
|
231
|
-
deploymentMode: opts?.deploymentMode,
|
|
232
|
-
}),
|
|
233
|
-
});
|
|
234
|
-
return res.data;
|
|
235
|
-
}
|
|
236
|
-
async getEntityRecord(workspaceId, entityName, recordId) {
|
|
237
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/entities/${encodeURIComponent(entityName)}/${encodeURIComponent(recordId)}`);
|
|
238
|
-
return res.data;
|
|
239
|
-
}
|
|
240
|
-
async createEntityRecord(workspaceId, entityName, data) {
|
|
241
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/entities/${encodeURIComponent(entityName)}`, { method: 'POST', body: JSON.stringify({ data }) });
|
|
242
|
-
return res.data;
|
|
243
|
-
}
|
|
244
|
-
async updateEntityRecord(workspaceId, entityName, recordId, data) {
|
|
245
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/entities/${encodeURIComponent(entityName)}/${encodeURIComponent(recordId)}`, { method: 'PUT', body: JSON.stringify({ data }) });
|
|
246
|
-
return res.data;
|
|
247
|
-
}
|
|
248
|
-
async deleteEntityRecord(workspaceId, entityName, recordId) {
|
|
249
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/entities/${encodeURIComponent(entityName)}/${encodeURIComponent(recordId)}`, { method: 'DELETE' });
|
|
250
|
-
return res.data;
|
|
251
|
-
}
|
|
252
|
-
// --- Workspace Registry: Workflows ---
|
|
253
|
-
async listWorkflows(workspaceId) {
|
|
254
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/workflows?includeStatus=true`);
|
|
255
|
-
return res.data.workflows;
|
|
256
|
-
}
|
|
257
|
-
async triggerWorkflow(workspaceId, opts) {
|
|
258
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/workflows/trigger`, { method: 'POST', body: JSON.stringify(opts) });
|
|
259
|
-
return res.data;
|
|
260
|
-
}
|
|
261
|
-
async listWorkflowInstances(workspaceId, appId, opts) {
|
|
262
|
-
const params = new URLSearchParams({ appId });
|
|
263
|
-
if (opts?.workflowName)
|
|
264
|
-
params.set('workflowName', opts.workflowName);
|
|
265
|
-
if (opts?.status)
|
|
266
|
-
params.set('status', opts.status);
|
|
267
|
-
if (opts?.limit)
|
|
268
|
-
params.set('limit', String(opts.limit));
|
|
269
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/workflows/instances?${params}`);
|
|
270
|
-
return res.data;
|
|
271
|
-
}
|
|
272
|
-
async getWorkflowInstance(workspaceId, instanceId, appId) {
|
|
273
|
-
const params = appId ? `?appId=${appId}` : '';
|
|
274
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/workflows/instances/${encodeURIComponent(instanceId)}${params}`);
|
|
275
|
-
return res.data;
|
|
276
|
-
}
|
|
277
|
-
// --- Workspace Registry: Schedules ---
|
|
278
|
-
async listSchedules(workspaceId) {
|
|
279
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/schedules?includeStatus=true`);
|
|
280
|
-
return res.data.schedules;
|
|
281
|
-
}
|
|
282
|
-
async triggerSchedule(workspaceId, opts) {
|
|
283
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/schedules/trigger`, { method: 'POST', body: JSON.stringify(opts) });
|
|
284
|
-
return res.data;
|
|
285
|
-
}
|
|
286
|
-
async getScheduleHistory(workspaceId, appId) {
|
|
287
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/schedules/history?appId=${appId}`);
|
|
288
|
-
return res.data;
|
|
289
|
-
}
|
|
290
|
-
async getScheduleStatus(workspaceId, appId) {
|
|
291
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/schedules/status?appId=${appId}`);
|
|
292
|
-
return res.data;
|
|
293
|
-
}
|
|
294
|
-
async pauseSchedule(workspaceId, scheduleName, appId) {
|
|
295
|
-
await this.request(`/api/workspaces/${workspaceId}/schedules/${encodeURIComponent(scheduleName)}/pause?appId=${appId}`, { method: 'POST' });
|
|
296
|
-
}
|
|
297
|
-
async resumeSchedule(workspaceId, scheduleName, appId) {
|
|
298
|
-
await this.request(`/api/workspaces/${workspaceId}/schedules/${encodeURIComponent(scheduleName)}/resume?appId=${appId}`, { method: 'POST' });
|
|
299
|
-
}
|
|
300
|
-
// --- Workspace Registry: Endpoints ---
|
|
301
|
-
async listEndpoints(workspaceId) {
|
|
302
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/endpoints`);
|
|
303
|
-
return res.data.endpoints;
|
|
304
|
-
}
|
|
305
|
-
// --- Workspace Registry: File Storage ---
|
|
306
|
-
async listFileStorages(workspaceId) {
|
|
307
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/file-storages`);
|
|
308
|
-
return res.data.fileStorages;
|
|
309
|
-
}
|
|
310
|
-
async listBucketFiles(workspaceId, bucketName, opts) {
|
|
311
|
-
const params = new URLSearchParams();
|
|
312
|
-
if (opts?.prefix)
|
|
313
|
-
params.set('prefix', opts.prefix);
|
|
314
|
-
if (opts?.delimiter)
|
|
315
|
-
params.set('delimiter', opts.delimiter);
|
|
316
|
-
const query = params.toString();
|
|
317
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/file-storages/${encodeURIComponent(bucketName)}/files${query ? `?${query}` : ''}`);
|
|
318
|
-
return res.data;
|
|
319
|
-
}
|
|
320
|
-
async getPresignedUrl(workspaceId, bucketName, opts) {
|
|
321
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/file-storages/${encodeURIComponent(bucketName)}/presign`, { method: 'POST', body: JSON.stringify(opts) });
|
|
322
|
-
return res.data;
|
|
323
|
-
}
|
|
324
|
-
async deleteBucketFile(workspaceId, bucketName, key) {
|
|
325
|
-
await this.request(`/api/workspaces/${workspaceId}/file-storages/${encodeURIComponent(bucketName)}/files?key=${encodeURIComponent(key)}`, { method: 'DELETE' });
|
|
326
|
-
}
|
|
327
|
-
// --- Workspace Registry: Components ---
|
|
328
|
-
async listComponents(workspaceId) {
|
|
329
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/components`);
|
|
330
|
-
return res.data.components;
|
|
331
|
-
}
|
|
332
|
-
// --- Workspace Registry: API Keys ---
|
|
333
|
-
async listApiKeys(workspaceId) {
|
|
334
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/api-keys`);
|
|
335
|
-
return res.data.apiKeys;
|
|
336
|
-
}
|
|
337
|
-
async createApiKey(workspaceId, opts) {
|
|
338
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/api-keys`, { method: 'POST', body: JSON.stringify(opts) });
|
|
339
|
-
return res.data;
|
|
340
|
-
}
|
|
341
|
-
// --- Workspace Registry: Agents ---
|
|
342
|
-
async listAgents(workspaceId) {
|
|
343
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/agents`);
|
|
344
|
-
return res.data.agents;
|
|
345
|
-
}
|
|
346
|
-
async getAgentStatus(workspaceId, agentName, appId) {
|
|
347
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/agents/status`, { method: 'POST', body: JSON.stringify({ agentName, appId }) });
|
|
348
|
-
return res.data;
|
|
349
|
-
}
|
|
350
|
-
async listAgentExecutions(workspaceId) {
|
|
351
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/agent-executions`);
|
|
352
|
-
return res.data.executions;
|
|
353
|
-
}
|
|
354
|
-
async getAgentExecutionStream(workspaceId, sessionId) {
|
|
355
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/agent-executions/${encodeURIComponent(sessionId)}/stream`);
|
|
356
|
-
return res.data.stream;
|
|
357
|
-
}
|
|
358
|
-
// --- Team Telemetry ---
|
|
359
|
-
async getOnboardingConfig(workspaceId) {
|
|
360
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/onboarding-config`);
|
|
361
|
-
return res.data;
|
|
362
|
-
}
|
|
363
|
-
async reportTelemetry(workspaceId, events) {
|
|
364
|
-
await this.request(`/api/workspaces/${workspaceId}/team/telemetry`, { method: 'POST', body: JSON.stringify({ events }) });
|
|
365
|
-
}
|
|
366
|
-
// --- Shared Conversations ---
|
|
367
|
-
async createSharedConversation(workspaceId, body) {
|
|
368
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/shared-conversations`, {
|
|
369
|
-
method: 'POST',
|
|
370
|
-
body: JSON.stringify(body),
|
|
371
|
-
});
|
|
372
|
-
return res.data;
|
|
373
|
-
}
|
|
374
|
-
async listSharedConversations(workspaceId, opts) {
|
|
375
|
-
const search = new URLSearchParams();
|
|
376
|
-
if (opts?.scope)
|
|
377
|
-
search.set('scope', opts.scope);
|
|
378
|
-
if (opts?.limit !== undefined)
|
|
379
|
-
search.set('limit', String(opts.limit));
|
|
380
|
-
if (opts?.offset !== undefined)
|
|
381
|
-
search.set('offset', String(opts.offset));
|
|
382
|
-
const query = search.toString() ? `?${search.toString()}` : '';
|
|
383
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/shared-conversations${query}`);
|
|
384
|
-
return res.data;
|
|
385
|
-
}
|
|
386
|
-
async getSharedConversation(workspaceId, shareId) {
|
|
387
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/shared-conversations/${shareId}`);
|
|
388
|
-
return res.data;
|
|
389
|
-
}
|
|
390
|
-
async downloadSharedConversationBundle(workspaceId, shareId, format) {
|
|
391
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/shared-conversations/${shareId}/bundle/${encodeURIComponent(format)}`);
|
|
392
|
-
return res.data;
|
|
393
|
-
}
|
|
394
|
-
async markSharedConversationResumed(workspaceId, shareId) {
|
|
395
|
-
const res = await this.request(`/api/workspaces/${workspaceId}/shared-conversations/${shareId}/resumed`, { method: 'POST' });
|
|
396
|
-
return res.data;
|
|
397
|
-
}
|
|
398
|
-
// --- Integrations: Proxy Call ---
|
|
399
|
-
async callIntegrationProxy(integrationDbId, method, path, opts) {
|
|
400
|
-
const targetPath = opts?.query ? `${path}?${opts.query}` : path;
|
|
401
|
-
const url = `${this.baseUrl}/api/proxy/integrations${targetPath}`;
|
|
402
|
-
const headers = {
|
|
403
|
-
'X-Workspace-Integration-Id': integrationDbId,
|
|
404
|
-
...Object.fromEntries(Object.entries(opts?.headers || {})),
|
|
405
|
-
};
|
|
406
|
-
if (this.apiKey) {
|
|
407
|
-
headers['Authorization'] = `Bearer ${this.apiKey}`;
|
|
408
|
-
}
|
|
409
|
-
if (opts?.body) {
|
|
410
|
-
headers['Content-Type'] = 'application/json';
|
|
411
|
-
}
|
|
412
|
-
const response = await httpFetch(url, {
|
|
413
|
-
method,
|
|
414
|
-
headers,
|
|
415
|
-
body: opts?.body ? JSON.stringify(opts.body) : undefined,
|
|
416
|
-
});
|
|
417
|
-
if (!response.ok) {
|
|
418
|
-
const body = await response.text();
|
|
419
|
-
throw new Error(`Integration proxy error ${response.status}: ${body}`);
|
|
420
|
-
}
|
|
421
|
-
const contentType = response.headers.get('content-type') || '';
|
|
422
|
-
if (contentType.includes('application/json')) {
|
|
423
|
-
return response.json();
|
|
424
|
-
}
|
|
425
|
-
return response.text();
|
|
426
|
-
}
|
|
427
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
-
// Mock only the side-effect dependencies, not ApiClient
|
|
3
|
-
vi.mock('../store.js', () => ({
|
|
4
|
-
saveCredentials: vi.fn(),
|
|
5
|
-
}));
|
|
6
|
-
vi.mock('../../git/credentials.js', () => ({
|
|
7
|
-
configureGitCredentials: vi.fn().mockResolvedValue(undefined),
|
|
8
|
-
}));
|
|
9
|
-
// HTTP goes through our `httpFetch` wrapper (single seam for diagnostics
|
|
10
|
-
// and the optional `curl` transport). Tests mock that wrapper directly so
|
|
11
|
-
// they exercise the same code path the production CLI uses.
|
|
12
|
-
const mockFetch = vi.fn();
|
|
13
|
-
vi.mock('../../utils/http.js', () => ({
|
|
14
|
-
httpFetch: (...args) => mockFetch(...args),
|
|
15
|
-
}));
|
|
16
|
-
import { saveCredentials } from '../store.js';
|
|
17
|
-
function jsonResponse(data, status = 200) {
|
|
18
|
-
return {
|
|
19
|
-
ok: status >= 200 && status < 300,
|
|
20
|
-
status,
|
|
21
|
-
statusText: '',
|
|
22
|
-
url: '',
|
|
23
|
-
headers: new Headers(),
|
|
24
|
-
json: () => Promise.resolve(data),
|
|
25
|
-
text: () => Promise.resolve(JSON.stringify(data)),
|
|
26
|
-
arrayBuffer: () => Promise.resolve(new ArrayBuffer(0)),
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
beforeEach(() => {
|
|
30
|
-
vi.clearAllMocks();
|
|
31
|
-
vi.spyOn(console, 'log').mockImplementation(() => { });
|
|
32
|
-
vi.spyOn(console, 'error').mockImplementation(() => { });
|
|
33
|
-
});
|
|
34
|
-
describe('performLoginNoOpen', () => {
|
|
35
|
-
it('with printOnly prints URL and returns null without polling', async () => {
|
|
36
|
-
mockFetch.mockResolvedValue(jsonResponse({
|
|
37
|
-
data: { sessionId: 'sess-123', loginUrl: 'https://runwork.ai/cli-auth?session=sess-123' },
|
|
38
|
-
}));
|
|
39
|
-
const { performLoginNoOpen } = await import('../login-flow.js');
|
|
40
|
-
const result = await performLoginNoOpen('https://runwork.ai', true);
|
|
41
|
-
expect(console.log).toHaveBeenCalledWith('https://runwork.ai/cli-auth?session=sess-123');
|
|
42
|
-
expect(result).toBeNull();
|
|
43
|
-
expect(saveCredentials).not.toHaveBeenCalled();
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
describe('performLoginWithApiKey', () => {
|
|
47
|
-
it('validates key by listing workspaces and saves credentials', async () => {
|
|
48
|
-
mockFetch.mockResolvedValue(jsonResponse({
|
|
49
|
-
data: [{ id: 'ws-1', name: 'My Workspace' }],
|
|
50
|
-
}));
|
|
51
|
-
const { performLoginWithApiKey } = await import('../login-flow.js');
|
|
52
|
-
const result = await performLoginWithApiKey('rw_test123');
|
|
53
|
-
expect(saveCredentials).toHaveBeenCalledWith(expect.objectContaining({
|
|
54
|
-
apiKey: 'rw_test123',
|
|
55
|
-
defaultWorkspaceId: 'ws-1',
|
|
56
|
-
defaultWorkspaceName: 'My Workspace',
|
|
57
|
-
}));
|
|
58
|
-
expect(result.apiKey).toBe('rw_test123');
|
|
59
|
-
});
|
|
60
|
-
it('saves credentials with custom base URL', async () => {
|
|
61
|
-
mockFetch.mockResolvedValue(jsonResponse({ data: [{ id: 'ws-1', name: 'WS' }] }));
|
|
62
|
-
const { performLoginWithApiKey } = await import('../login-flow.js');
|
|
63
|
-
const result = await performLoginWithApiKey('rw_key', 'https://custom.runwork.dev');
|
|
64
|
-
expect(mockFetch).toHaveBeenCalledWith(expect.stringContaining('https://custom.runwork.dev'), expect.anything());
|
|
65
|
-
expect(result.baseUrl).toBe('https://custom.runwork.dev');
|
|
66
|
-
});
|
|
67
|
-
it('handles no workspaces (sets no default)', async () => {
|
|
68
|
-
mockFetch.mockResolvedValue(jsonResponse({ data: [] }));
|
|
69
|
-
const { performLoginWithApiKey } = await import('../login-flow.js');
|
|
70
|
-
const result = await performLoginWithApiKey('rw_key');
|
|
71
|
-
expect(saveCredentials).toHaveBeenCalledWith(expect.objectContaining({
|
|
72
|
-
apiKey: 'rw_key',
|
|
73
|
-
defaultWorkspaceId: undefined,
|
|
74
|
-
defaultWorkspaceName: undefined,
|
|
75
|
-
}));
|
|
76
|
-
expect(result.apiKey).toBe('rw_key');
|
|
77
|
-
});
|
|
78
|
-
it('exits on invalid API key', async () => {
|
|
79
|
-
mockFetch.mockResolvedValue({
|
|
80
|
-
ok: false,
|
|
81
|
-
status: 401,
|
|
82
|
-
statusText: 'Unauthorized',
|
|
83
|
-
url: '',
|
|
84
|
-
headers: new Headers(),
|
|
85
|
-
json: () => Promise.resolve({ error: 'Unauthorized' }),
|
|
86
|
-
text: () => Promise.resolve('Unauthorized'),
|
|
87
|
-
arrayBuffer: () => Promise.resolve(new ArrayBuffer(0)),
|
|
88
|
-
});
|
|
89
|
-
const mockExit = vi.spyOn(process, 'exit').mockImplementation(((code) => {
|
|
90
|
-
throw new Error(`process.exit(${code})`);
|
|
91
|
-
}));
|
|
92
|
-
try {
|
|
93
|
-
const { performLoginWithApiKey } = await import('../login-flow.js');
|
|
94
|
-
await expect(performLoginWithApiKey('bad-key')).rejects.toThrow('process.exit(1)');
|
|
95
|
-
expect(console.error).toHaveBeenCalledWith(expect.stringContaining('Invalid API key'));
|
|
96
|
-
}
|
|
97
|
-
finally {
|
|
98
|
-
mockExit.mockRestore();
|
|
99
|
-
}
|
|
100
|
-
});
|
|
101
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
-
vi.mock('fs');
|
|
3
|
-
vi.mock('os', () => ({
|
|
4
|
-
homedir: () => '/tmp/test-runwork-home',
|
|
5
|
-
}));
|
|
6
|
-
const mockFs = await import('fs');
|
|
7
|
-
const { getCredentials, saveCredentials, clearCredentials, requireAuth, } = await import('../store.js');
|
|
8
|
-
const EXPECTED_DIR = '/tmp/test-runwork-home/.runwork';
|
|
9
|
-
const EXPECTED_FILE = '/tmp/test-runwork-home/.runwork/.credentials';
|
|
10
|
-
const validCredentials = {
|
|
11
|
-
apiKey: 'test-api-key-123',
|
|
12
|
-
email: 'test@example.com',
|
|
13
|
-
baseUrl: 'https://runwork.ai',
|
|
14
|
-
};
|
|
15
|
-
describe('auth/store', () => {
|
|
16
|
-
beforeEach(() => {
|
|
17
|
-
vi.clearAllMocks();
|
|
18
|
-
});
|
|
19
|
-
describe('getCredentials()', () => {
|
|
20
|
-
it('returns null when credentials file does not exist', () => {
|
|
21
|
-
vi.mocked(mockFs.existsSync).mockReturnValue(false);
|
|
22
|
-
const result = getCredentials();
|
|
23
|
-
expect(result).toBeNull();
|
|
24
|
-
expect(mockFs.existsSync).toHaveBeenCalledWith(EXPECTED_FILE);
|
|
25
|
-
});
|
|
26
|
-
it('returns parsed credentials when file exists with valid JSON', () => {
|
|
27
|
-
vi.mocked(mockFs.existsSync).mockReturnValue(true);
|
|
28
|
-
vi.mocked(mockFs.readFileSync).mockReturnValue(JSON.stringify(validCredentials));
|
|
29
|
-
const result = getCredentials();
|
|
30
|
-
expect(result).toEqual(validCredentials);
|
|
31
|
-
expect(mockFs.readFileSync).toHaveBeenCalledWith(EXPECTED_FILE, 'utf-8');
|
|
32
|
-
});
|
|
33
|
-
it('returns null on malformed JSON', () => {
|
|
34
|
-
vi.mocked(mockFs.existsSync).mockReturnValue(true);
|
|
35
|
-
vi.mocked(mockFs.readFileSync).mockReturnValue('not valid json {{{');
|
|
36
|
-
const result = getCredentials();
|
|
37
|
-
expect(result).toBeNull();
|
|
38
|
-
});
|
|
39
|
-
it('returns null when readFileSync throws', () => {
|
|
40
|
-
vi.mocked(mockFs.existsSync).mockReturnValue(true);
|
|
41
|
-
vi.mocked(mockFs.readFileSync).mockImplementation(() => {
|
|
42
|
-
throw new Error('EACCES: permission denied');
|
|
43
|
-
});
|
|
44
|
-
const result = getCredentials();
|
|
45
|
-
expect(result).toBeNull();
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
describe('saveCredentials()', () => {
|
|
49
|
-
it('creates the .runwork directory recursively', () => {
|
|
50
|
-
saveCredentials(validCredentials);
|
|
51
|
-
expect(mockFs.mkdirSync).toHaveBeenCalledWith(EXPECTED_DIR, {
|
|
52
|
-
recursive: true,
|
|
53
|
-
});
|
|
54
|
-
});
|
|
55
|
-
it('writes JSON with 0o600 permissions', () => {
|
|
56
|
-
saveCredentials(validCredentials);
|
|
57
|
-
expect(mockFs.writeFileSync).toHaveBeenCalledWith(EXPECTED_FILE, JSON.stringify(validCredentials, null, 2), { mode: 0o600 });
|
|
58
|
-
});
|
|
59
|
-
it('stores the correct credential data', () => {
|
|
60
|
-
const customCreds = {
|
|
61
|
-
apiKey: 'custom-key',
|
|
62
|
-
email: 'custom@test.com',
|
|
63
|
-
baseUrl: 'https://custom.runwork.dev',
|
|
64
|
-
};
|
|
65
|
-
saveCredentials(customCreds);
|
|
66
|
-
const writtenData = vi.mocked(mockFs.writeFileSync).mock.calls[0][1];
|
|
67
|
-
const parsed = JSON.parse(writtenData);
|
|
68
|
-
expect(parsed).toEqual(customCreds);
|
|
69
|
-
});
|
|
70
|
-
});
|
|
71
|
-
describe('clearCredentials()', () => {
|
|
72
|
-
it('deletes the credentials file when it exists', () => {
|
|
73
|
-
vi.mocked(mockFs.existsSync).mockReturnValue(true);
|
|
74
|
-
clearCredentials();
|
|
75
|
-
expect(mockFs.unlinkSync).toHaveBeenCalledWith(EXPECTED_FILE);
|
|
76
|
-
});
|
|
77
|
-
it('does nothing when credentials file does not exist', () => {
|
|
78
|
-
vi.mocked(mockFs.existsSync).mockReturnValue(false);
|
|
79
|
-
clearCredentials();
|
|
80
|
-
expect(mockFs.unlinkSync).not.toHaveBeenCalled();
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
describe('requireAuth()', () => {
|
|
84
|
-
it('returns credentials when logged in', () => {
|
|
85
|
-
vi.mocked(mockFs.existsSync).mockReturnValue(true);
|
|
86
|
-
vi.mocked(mockFs.readFileSync).mockReturnValue(JSON.stringify(validCredentials));
|
|
87
|
-
const result = requireAuth();
|
|
88
|
-
expect(result).toEqual(validCredentials);
|
|
89
|
-
});
|
|
90
|
-
it('exits process with code 1 with TTY guidance when invoked from a terminal', () => {
|
|
91
|
-
vi.mocked(mockFs.existsSync).mockReturnValue(false);
|
|
92
|
-
const exitSpy = vi.spyOn(process, 'exit').mockImplementation((() => {
|
|
93
|
-
throw new Error('process.exit called');
|
|
94
|
-
}));
|
|
95
|
-
const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => { });
|
|
96
|
-
const previousTTY = process.stdin.isTTY;
|
|
97
|
-
Object.defineProperty(process.stdin, 'isTTY', { value: true, configurable: true });
|
|
98
|
-
try {
|
|
99
|
-
expect(() => requireAuth()).toThrow('process.exit called');
|
|
100
|
-
expect(exitSpy).toHaveBeenCalledWith(1);
|
|
101
|
-
expect(errorSpy).toHaveBeenCalledWith('Not logged in. Run `runwork login` first.');
|
|
102
|
-
}
|
|
103
|
-
finally {
|
|
104
|
-
Object.defineProperty(process.stdin, 'isTTY', { value: previousTTY, configurable: true });
|
|
105
|
-
exitSpy.mockRestore();
|
|
106
|
-
errorSpy.mockRestore();
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
it('exits process with code 1 with headless guidance when invoked without a TTY', () => {
|
|
110
|
-
vi.mocked(mockFs.existsSync).mockReturnValue(false);
|
|
111
|
-
const exitSpy = vi.spyOn(process, 'exit').mockImplementation((() => {
|
|
112
|
-
throw new Error('process.exit called');
|
|
113
|
-
}));
|
|
114
|
-
const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => { });
|
|
115
|
-
const previousTTY = process.stdin.isTTY;
|
|
116
|
-
Object.defineProperty(process.stdin, 'isTTY', { value: false, configurable: true });
|
|
117
|
-
try {
|
|
118
|
-
expect(() => requireAuth()).toThrow('process.exit called');
|
|
119
|
-
expect(exitSpy).toHaveBeenCalledWith(1);
|
|
120
|
-
const message = errorSpy.mock.calls[0]?.[0];
|
|
121
|
-
expect(message).toContain('Not logged in.');
|
|
122
|
-
expect(message).toContain('RUNWORK_API_KEY');
|
|
123
|
-
expect(message).toContain('runwork login --api-key');
|
|
124
|
-
}
|
|
125
|
-
finally {
|
|
126
|
-
Object.defineProperty(process.stdin, 'isTTY', { value: previousTTY, configurable: true });
|
|
127
|
-
exitSpy.mockRestore();
|
|
128
|
-
errorSpy.mockRestore();
|
|
129
|
-
}
|
|
130
|
-
});
|
|
131
|
-
});
|
|
132
|
-
});
|