runwork 0.15.1 → 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 -105
- package/dist/agents/__tests__/claude-code-plugin.test.d.ts +0 -1
- package/dist/agents/__tests__/claude-code-plugin.test.js +0 -47
- package/dist/agents/__tests__/claude-code-stats.test.d.ts +0 -1
- package/dist/agents/__tests__/claude-code-stats.test.js +0 -390
- package/dist/agents/__tests__/claude-desktop-memory.test.d.ts +0 -1
- package/dist/agents/__tests__/claude-desktop-memory.test.js +0 -154
- package/dist/agents/__tests__/claude-desktop-plugin-tree.test.d.ts +0 -1
- package/dist/agents/__tests__/claude-desktop-plugin-tree.test.js +0 -161
- package/dist/agents/__tests__/claude-desktop-plugin.test.d.ts +0 -1
- package/dist/agents/__tests__/claude-desktop-plugin.test.js +0 -117
- package/dist/agents/__tests__/claude-desktop-rpm.test.d.ts +0 -1
- package/dist/agents/__tests__/claude-desktop-rpm.test.js +0 -126
- package/dist/agents/__tests__/claude-desktop-stats.test.d.ts +0 -1
- package/dist/agents/__tests__/claude-desktop-stats.test.js +0 -280
- package/dist/agents/__tests__/codex-instructions.test.d.ts +0 -1
- package/dist/agents/__tests__/codex-instructions.test.js +0 -57
- package/dist/agents/__tests__/codex-minimum-permissions.test.d.ts +0 -1
- package/dist/agents/__tests__/codex-minimum-permissions.test.js +0 -82
- package/dist/agents/__tests__/codex-stats.test.d.ts +0 -1
- package/dist/agents/__tests__/codex-stats.test.js +0 -370
- package/dist/agents/__tests__/cursor-merge.test.d.ts +0 -1
- package/dist/agents/__tests__/cursor-merge.test.js +0 -66
- package/dist/agents/__tests__/cursor-stats.test.d.ts +0 -1
- package/dist/agents/__tests__/cursor-stats.test.js +0 -183
- package/dist/agents/__tests__/defaults-merge.test.d.ts +0 -1
- package/dist/agents/__tests__/defaults-merge.test.js +0 -268
- package/dist/agents/__tests__/detection.test.d.ts +0 -1
- package/dist/agents/__tests__/detection.test.js +0 -89
- package/dist/agents/__tests__/graceful-degradation.test.d.ts +0 -1
- package/dist/agents/__tests__/graceful-degradation.test.js +0 -129
- package/dist/agents/__tests__/instruction-hint.test.d.ts +0 -1
- package/dist/agents/__tests__/instruction-hint.test.js +0 -69
- package/dist/agents/__tests__/intro-skill.test.d.ts +0 -1
- package/dist/agents/__tests__/intro-skill.test.js +0 -193
- package/dist/agents/__tests__/schema-validation.test.d.ts +0 -1
- package/dist/agents/__tests__/schema-validation.test.js +0 -212
- package/dist/agents/__tests__/skill-slug.test.d.ts +0 -1
- package/dist/agents/__tests__/skill-slug.test.js +0 -77
- package/dist/agents/claude-code.d.ts +0 -59
- package/dist/agents/claude-code.js +0 -753
- package/dist/agents/claude-desktop-plugin-tree.d.ts +0 -59
- package/dist/agents/claude-desktop-plugin-tree.js +0 -143
- package/dist/agents/claude-desktop.d.ts +0 -47
- package/dist/agents/claude-desktop.js +0 -684
- package/dist/agents/cline.d.ts +0 -15
- package/dist/agents/cline.js +0 -130
- package/dist/agents/codex.d.ts +0 -44
- package/dist/agents/codex.js +0 -453
- package/dist/agents/conversation-skills.d.ts +0 -18
- package/dist/agents/conversation-skills.js +0 -229
- package/dist/agents/cursor.d.ts +0 -35
- package/dist/agents/cursor.js +0 -294
- package/dist/agents/default-config.d.ts +0 -30
- package/dist/agents/default-config.js +0 -67
- package/dist/agents/defaults-merge.d.ts +0 -87
- package/dist/agents/defaults-merge.js +0 -150
- package/dist/agents/detect.d.ts +0 -4
- package/dist/agents/detect.js +0 -67
- package/dist/agents/detection.d.ts +0 -18
- package/dist/agents/detection.js +0 -94
- package/dist/agents/gemini.d.ts +0 -15
- package/dist/agents/gemini.js +0 -122
- package/dist/agents/generic-adapter.d.ts +0 -25
- package/dist/agents/generic-adapter.js +0 -151
- package/dist/agents/intro-skill.d.ts +0 -45
- package/dist/agents/intro-skill.js +0 -447
- package/dist/agents/registry-data.d.ts +0 -192
- package/dist/agents/registry-data.js +0 -669
- package/dist/agents/registry.d.ts +0 -13
- package/dist/agents/registry.js +0 -36
- package/dist/agents/runtime-detection.d.ts +0 -82
- package/dist/agents/runtime-detection.js +0 -271
- package/dist/agents/session-start-hook.d.ts +0 -37
- package/dist/agents/session-start-hook.js +0 -159
- package/dist/agents/types.d.ts +0 -171
- package/dist/agents/types.js +0 -75
- package/dist/agents/utils/instruction-hint.d.ts +0 -21
- package/dist/agents/utils/instruction-hint.js +0 -108
- package/dist/agents/utils/json-config.d.ts +0 -19
- package/dist/agents/utils/json-config.js +0 -69
- package/dist/agents/utils/toml-config.d.ts +0 -8
- package/dist/agents/utils/toml-config.js +0 -27
- package/dist/agents/windsurf.d.ts +0 -14
- package/dist/agents/windsurf.js +0 -102
- package/dist/api/__tests__/client.test.d.ts +0 -1
- package/dist/api/__tests__/client.test.js +0 -272
- package/dist/api/client.d.ts +0 -326
- package/dist/api/client.js +0 -427
- package/dist/auth/__tests__/login-flow.test.d.ts +0 -1
- package/dist/auth/__tests__/login-flow.test.js +0 -101
- package/dist/auth/__tests__/store.test.d.ts +0 -1
- package/dist/auth/__tests__/store.test.js +0 -132
- package/dist/auth/login-flow.d.ts +0 -26
- package/dist/auth/login-flow.js +0 -137
- package/dist/auth/store.d.ts +0 -5
- package/dist/auth/store.js +0 -62
- package/dist/commands/__tests__/clone-args.test.d.ts +0 -1
- package/dist/commands/__tests__/clone-args.test.js +0 -51
- package/dist/commands/__tests__/clone-source-result.test.d.ts +0 -1
- package/dist/commands/__tests__/clone-source-result.test.js +0 -45
- package/dist/commands/__tests__/info-merge.test.d.ts +0 -1
- package/dist/commands/__tests__/info-merge.test.js +0 -55
- package/dist/commands/__tests__/mcp-entries.test.d.ts +0 -1
- package/dist/commands/__tests__/mcp-entries.test.js +0 -48
- package/dist/commands/__tests__/setup-persona.test.d.ts +0 -1
- package/dist/commands/__tests__/setup-persona.test.js +0 -31
- package/dist/commands/__tests__/setup.test.d.ts +0 -1
- package/dist/commands/__tests__/setup.test.js +0 -81
- package/dist/commands/__tests__/sync-redetect.test.d.ts +0 -1
- package/dist/commands/__tests__/sync-redetect.test.js +0 -96
- package/dist/commands/__tests__/sync-telemetry.test.d.ts +0 -1
- package/dist/commands/__tests__/sync-telemetry.test.js +0 -281
- package/dist/commands/__tests__/upgrade.test.d.ts +0 -1
- package/dist/commands/__tests__/upgrade.test.js +0 -157
- package/dist/commands/agents.d.ts +0 -2
- package/dist/commands/agents.js +0 -160
- package/dist/commands/api-keys.d.ts +0 -2
- package/dist/commands/api-keys.js +0 -95
- package/dist/commands/apps.d.ts +0 -2
- package/dist/commands/apps.js +0 -82
- package/dist/commands/build-plugin.d.ts +0 -2
- package/dist/commands/build-plugin.js +0 -135
- package/dist/commands/clone.d.ts +0 -60
- package/dist/commands/clone.js +0 -271
- package/dist/commands/components.d.ts +0 -2
- package/dist/commands/components.js +0 -43
- package/dist/commands/deploy.d.ts +0 -2
- package/dist/commands/deploy.js +0 -279
- package/dist/commands/dev.d.ts +0 -11
- package/dist/commands/dev.js +0 -1011
- package/dist/commands/doctor.d.ts +0 -2
- package/dist/commands/doctor.js +0 -230
- package/dist/commands/endpoints.d.ts +0 -2
- package/dist/commands/endpoints.js +0 -189
- package/dist/commands/entities.d.ts +0 -2
- package/dist/commands/entities.js +0 -198
- package/dist/commands/files.d.ts +0 -2
- package/dist/commands/files.js +0 -193
- package/dist/commands/inbox.d.ts +0 -11
- package/dist/commands/inbox.js +0 -60
- package/dist/commands/info.d.ts +0 -178
- package/dist/commands/info.js +0 -455
- package/dist/commands/init.d.ts +0 -21
- package/dist/commands/init.js +0 -185
- package/dist/commands/integrations.d.ts +0 -2
- package/dist/commands/integrations.js +0 -233
- package/dist/commands/login.d.ts +0 -2
- package/dist/commands/login.js +0 -44
- package/dist/commands/logout.d.ts +0 -2
- package/dist/commands/logout.js +0 -13
- package/dist/commands/logs.d.ts +0 -2
- package/dist/commands/logs.js +0 -232
- package/dist/commands/mcp-entries.d.ts +0 -13
- package/dist/commands/mcp-entries.js +0 -26
- package/dist/commands/mcp.d.ts +0 -2
- package/dist/commands/mcp.js +0 -245
- package/dist/commands/open.d.ts +0 -2
- package/dist/commands/open.js +0 -53
- package/dist/commands/resume.d.ts +0 -2
- package/dist/commands/resume.js +0 -289
- package/dist/commands/save-convo.d.ts +0 -8
- package/dist/commands/save-convo.js +0 -20
- package/dist/commands/schedules.d.ts +0 -2
- package/dist/commands/schedules.js +0 -221
- package/dist/commands/setup.d.ts +0 -27
- package/dist/commands/setup.js +0 -177
- package/dist/commands/share-convo.d.ts +0 -24
- package/dist/commands/share-convo.js +0 -167
- package/dist/commands/skills.d.ts +0 -2
- package/dist/commands/skills.js +0 -352
- package/dist/commands/sync-telemetry.d.ts +0 -33
- package/dist/commands/sync-telemetry.js +0 -186
- package/dist/commands/sync.d.ts +0 -37
- package/dist/commands/sync.js +0 -702
- package/dist/commands/uninstall.d.ts +0 -2
- package/dist/commands/uninstall.js +0 -145
- package/dist/commands/upgrade.d.ts +0 -14
- package/dist/commands/upgrade.js +0 -217
- package/dist/commands/validate.d.ts +0 -2
- package/dist/commands/validate.js +0 -89
- package/dist/commands/welcome.d.ts +0 -1
- package/dist/commands/welcome.js +0 -86
- package/dist/commands/workflows.d.ts +0 -2
- package/dist/commands/workflows.js +0 -187
- package/dist/deploy/__tests__/deploy-state.test.d.ts +0 -1
- package/dist/deploy/__tests__/deploy-state.test.js +0 -80
- package/dist/deploy/__tests__/deploy-status.test.d.ts +0 -1
- package/dist/deploy/__tests__/deploy-status.test.js +0 -41
- package/dist/deploy/__tests__/detach-args.test.d.ts +0 -1
- package/dist/deploy/__tests__/detach-args.test.js +0 -30
- package/dist/deploy/deploy-state.d.ts +0 -36
- package/dist/deploy/deploy-state.js +0 -63
- package/dist/deploy/deploy-status.d.ts +0 -21
- package/dist/deploy/deploy-status.js +0 -36
- package/dist/deploy/detach.d.ts +0 -32
- package/dist/deploy/detach.js +0 -71
- package/dist/dev/__tests__/attach.test.d.ts +0 -1
- package/dist/dev/__tests__/attach.test.js +0 -296
- package/dist/dev/__tests__/detach.test.d.ts +0 -1
- package/dist/dev/__tests__/detach.test.js +0 -404
- package/dist/dev/__tests__/preview-url-poller.test.d.ts +0 -1
- package/dist/dev/__tests__/preview-url-poller.test.js +0 -149
- package/dist/dev/__tests__/session.test.d.ts +0 -1
- package/dist/dev/__tests__/session.test.js +0 -446
- package/dist/dev/__tests__/startup-sync.test.d.ts +0 -1
- package/dist/dev/__tests__/startup-sync.test.js +0 -32
- package/dist/dev/__tests__/stop.test.d.ts +0 -1
- package/dist/dev/__tests__/stop.test.js +0 -172
- package/dist/dev/attach.d.ts +0 -120
- package/dist/dev/attach.js +0 -269
- package/dist/dev/detach.d.ts +0 -187
- package/dist/dev/detach.js +0 -292
- package/dist/dev/preview-url-poller.d.ts +0 -35
- package/dist/dev/preview-url-poller.js +0 -50
- package/dist/dev/session.d.ts +0 -175
- package/dist/dev/session.js +0 -258
- package/dist/dev/startup-sync.d.ts +0 -23
- package/dist/dev/startup-sync.js +0 -14
- package/dist/dev/stop.d.ts +0 -52
- package/dist/dev/stop.js +0 -101
- package/dist/devtools/registry-data.d.ts +0 -46
- package/dist/devtools/registry-data.js +0 -40
- package/dist/generated/bundled-types.d.ts +0 -1
- package/dist/generated/bundled-types.js +0 -46
- package/dist/generated/version.d.ts +0 -1
- package/dist/generated/version.js +0 -2
- package/dist/git/__tests__/auto-commit.test.d.ts +0 -1
- package/dist/git/__tests__/auto-commit.test.js +0 -431
- package/dist/git/__tests__/classify-sync-error.test.d.ts +0 -1
- package/dist/git/__tests__/classify-sync-error.test.js +0 -57
- package/dist/git/__tests__/credential-helper-e2e.test.d.ts +0 -21
- package/dist/git/__tests__/credential-helper-e2e.test.js +0 -195
- package/dist/git/__tests__/credentials.test.d.ts +0 -1
- package/dist/git/__tests__/credentials.test.js +0 -141
- package/dist/git/__tests__/deploy-guard.test.d.ts +0 -1
- package/dist/git/__tests__/deploy-guard.test.js +0 -61
- package/dist/git/__tests__/ensure-git-credential-helper.test.d.ts +0 -1
- package/dist/git/__tests__/ensure-git-credential-helper.test.js +0 -133
- package/dist/git/__tests__/ensure-runwork-remote.test.d.ts +0 -1
- package/dist/git/__tests__/ensure-runwork-remote.test.js +0 -109
- package/dist/git/__tests__/identity.test.d.ts +0 -1
- package/dist/git/__tests__/identity.test.js +0 -146
- package/dist/git/__tests__/manifest.test.d.ts +0 -1
- package/dist/git/__tests__/manifest.test.js +0 -446
- package/dist/git/__tests__/preflight-resolution.test.d.ts +0 -1
- package/dist/git/__tests__/preflight-resolution.test.js +0 -366
- package/dist/git/__tests__/preflight.test.d.ts +0 -1
- package/dist/git/__tests__/preflight.test.js +0 -36
- package/dist/git/__tests__/repo-config.test.d.ts +0 -1
- package/dist/git/__tests__/repo-config.test.js +0 -26
- package/dist/git/__tests__/sync.test.d.ts +0 -1
- package/dist/git/__tests__/sync.test.js +0 -405
- package/dist/git/auto-commit.d.ts +0 -35
- package/dist/git/auto-commit.js +0 -293
- package/dist/git/classify-sync-error.d.ts +0 -21
- package/dist/git/classify-sync-error.js +0 -111
- package/dist/git/credentials.d.ts +0 -75
- package/dist/git/credentials.js +0 -164
- package/dist/git/critical-files.d.ts +0 -20
- package/dist/git/critical-files.js +0 -68
- package/dist/git/deploy-guard.d.ts +0 -53
- package/dist/git/deploy-guard.js +0 -78
- package/dist/git/identity.d.ts +0 -44
- package/dist/git/identity.js +0 -133
- package/dist/git/preflight.d.ts +0 -57
- package/dist/git/preflight.js +0 -276
- package/dist/git/remote.d.ts +0 -37
- package/dist/git/remote.js +0 -75
- package/dist/git/repo-config.d.ts +0 -8
- package/dist/git/repo-config.js +0 -29
- package/dist/git/sync.d.ts +0 -15
- package/dist/git/sync.js +0 -159
- package/dist/health/__tests__/checks.test.d.ts +0 -1
- package/dist/health/__tests__/checks.test.js +0 -357
- package/dist/health/__tests__/cli-distribution-checks.test.d.ts +0 -1
- package/dist/health/__tests__/cli-distribution-checks.test.js +0 -196
- package/dist/health/__tests__/fix.test.d.ts +0 -1
- package/dist/health/__tests__/fix.test.js +0 -72
- package/dist/health/__tests__/runner-filter.test.d.ts +0 -1
- package/dist/health/__tests__/runner-filter.test.js +0 -61
- package/dist/health/checks.d.ts +0 -42
- package/dist/health/checks.js +0 -636
- package/dist/health/fix.d.ts +0 -22
- package/dist/health/fix.js +0 -62
- package/dist/health/runner.d.ts +0 -8
- package/dist/health/runner.js +0 -47
- package/dist/health/types.d.ts +0 -12
- package/dist/health/types.js +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/logs/__tests__/tailer-format.test.d.ts +0 -1
- package/dist/logs/__tests__/tailer-format.test.js +0 -43
- package/dist/logs/tailer.d.ts +0 -17
- package/dist/logs/tailer.js +0 -217
- package/dist/sync/__tests__/change-detect.test.d.ts +0 -1
- package/dist/sync/__tests__/change-detect.test.js +0 -123
- package/dist/sync/__tests__/hash.test.d.ts +0 -1
- package/dist/sync/__tests__/hash.test.js +0 -18
- package/dist/sync/change-detect.d.ts +0 -19
- package/dist/sync/change-detect.js +0 -136
- package/dist/sync/conflict-ui.d.ts +0 -5
- package/dist/sync/conflict-ui.js +0 -78
- package/dist/sync/executor.d.ts +0 -23
- package/dist/sync/executor.js +0 -102
- package/dist/sync/hash.d.ts +0 -1
- package/dist/sync/hash.js +0 -4
- package/dist/sync/types.d.ts +0 -24
- package/dist/sync/types.js +0 -1
- package/dist/template/manifest.d.ts +0 -17
- package/dist/template/manifest.js +0 -145
- package/dist/tools/types.d.ts +0 -52
- package/dist/tools/types.js +0 -8
- package/dist/types-manager.d.ts +0 -1
- package/dist/types-manager.js +0 -35
- package/dist/types.d.ts +0 -349
- package/dist/types.js +0 -1
- package/dist/ui/__tests__/banner.test.d.ts +0 -1
- package/dist/ui/__tests__/banner.test.js +0 -98
- package/dist/ui/__tests__/colors.test.d.ts +0 -1
- package/dist/ui/__tests__/colors.test.js +0 -22
- package/dist/ui/__tests__/keyboard.test.d.ts +0 -1
- package/dist/ui/__tests__/keyboard.test.js +0 -34
- package/dist/ui/__tests__/status-line.test.d.ts +0 -1
- package/dist/ui/__tests__/status-line.test.js +0 -54
- package/dist/ui/banner.d.ts +0 -29
- package/dist/ui/banner.js +0 -153
- package/dist/ui/colors.d.ts +0 -4
- package/dist/ui/colors.js +0 -7
- package/dist/ui/keyboard.d.ts +0 -12
- package/dist/ui/keyboard.js +0 -61
- package/dist/ui/status-line.d.ts +0 -6
- package/dist/ui/status-line.js +0 -53
- package/dist/utils/__tests__/format-error.test.d.ts +0 -1
- package/dist/utils/__tests__/format-error.test.js +0 -43
- package/dist/utils/__tests__/help-json.test.d.ts +0 -1
- package/dist/utils/__tests__/help-json.test.js +0 -39
- package/dist/utils/__tests__/http.test.d.ts +0 -1
- package/dist/utils/__tests__/http.test.js +0 -381
- package/dist/utils/__tests__/ignore-matcher.test.d.ts +0 -1
- package/dist/utils/__tests__/ignore-matcher.test.js +0 -205
- package/dist/utils/__tests__/output.test.d.ts +0 -1
- package/dist/utils/__tests__/output.test.js +0 -38
- package/dist/utils/__tests__/prompt.test.d.ts +0 -1
- package/dist/utils/__tests__/prompt.test.js +0 -27
- package/dist/utils/__tests__/resolve.test.d.ts +0 -1
- package/dist/utils/__tests__/resolve.test.js +0 -95
- package/dist/utils/__tests__/sqlite.test.d.ts +0 -1
- package/dist/utils/__tests__/sqlite.test.js +0 -89
- package/dist/utils/agent-guidance.d.ts +0 -47
- package/dist/utils/agent-guidance.js +0 -128
- package/dist/utils/app-info.d.ts +0 -70
- package/dist/utils/app-info.js +0 -167
- package/dist/utils/curl-parser.d.ts +0 -12
- package/dist/utils/curl-parser.js +0 -162
- package/dist/utils/data-input.d.ts +0 -1
- package/dist/utils/data-input.js +0 -38
- package/dist/utils/format-error.d.ts +0 -10
- package/dist/utils/format-error.js +0 -38
- package/dist/utils/fs.d.ts +0 -5
- package/dist/utils/fs.js +0 -23
- package/dist/utils/help-json.d.ts +0 -70
- package/dist/utils/help-json.js +0 -88
- package/dist/utils/http.d.ts +0 -46
- package/dist/utils/http.js +0 -421
- package/dist/utils/ignore-matcher.d.ts +0 -47
- package/dist/utils/ignore-matcher.js +0 -132
- package/dist/utils/output.d.ts +0 -17
- package/dist/utils/output.js +0 -27
- package/dist/utils/prompt.d.ts +0 -5
- package/dist/utils/prompt.js +0 -42
- package/dist/utils/resolve.d.ts +0 -12
- package/dist/utils/resolve.js +0 -52
- package/dist/utils/setup-state.d.ts +0 -3
- package/dist/utils/setup-state.js +0 -19
- package/dist/utils/sqlite-adapter.d.ts +0 -48
- package/dist/utils/sqlite-adapter.js +0 -147
- package/dist/utils/sqlite.d.ts +0 -14
- package/dist/utils/sqlite.js +0 -14
- package/dist/utils/subprocess.d.ts +0 -19
- package/dist/utils/subprocess.js +0 -27
- package/dist/utils/which.d.ts +0 -14
- package/dist/utils/which.js +0 -47
- package/dist/utils/zip.d.ts +0 -7
- package/dist/utils/zip.js +0 -42
- package/dist/validate/__tests__/validate.test.d.ts +0 -1
- package/dist/validate/__tests__/validate.test.js +0 -42
- package/dist/validate/freshness.d.ts +0 -28
- package/dist/validate/freshness.js +0 -48
- package/dist/validate/preview.d.ts +0 -21
- package/dist/validate/preview.js +0 -39
- package/dist/workspace/resolve.d.ts +0 -19
- package/dist/workspace/resolve.js +0 -100
|
@@ -1,684 +0,0 @@
|
|
|
1
|
-
import { existsSync, mkdtempSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync, mkdirSync } from 'fs';
|
|
2
|
-
import { dirname, join } from 'path';
|
|
3
|
-
import { homedir, platform, tmpdir } from 'os';
|
|
4
|
-
import { mergeJsonMcpServers, readJsonConfig, writeJsonConfig, removeRunworkMcpServers } from './utils/json-config.js';
|
|
5
|
-
import { writeHintToFile, writeTeamInstructionsToFile, removeHintFromFile, removeTeamInstructionsFromFile, } from './utils/instruction-hint.js';
|
|
6
|
-
import { createZipFromDir } from '../utils/zip.js';
|
|
7
|
-
import { writePluginMcpConfig, writePluginMetadata, writePluginSkills, writePluginTeamInstructions, writePluginTree, } from './claude-desktop-plugin-tree.js';
|
|
8
|
-
const PLUGIN_NAME = 'runwork';
|
|
9
|
-
const PLUGIN_VERSION = '1.0.0';
|
|
10
|
-
const PLUGIN_DESCRIPTION = 'Skills and tools from your Runwork workspace';
|
|
11
|
-
const PLUGIN_AUTHOR_NAME = 'Runwork';
|
|
12
|
-
function getPluginMetadata() {
|
|
13
|
-
return {
|
|
14
|
-
pluginName: PLUGIN_NAME,
|
|
15
|
-
pluginVersion: PLUGIN_VERSION,
|
|
16
|
-
description: PLUGIN_DESCRIPTION,
|
|
17
|
-
authorName: PLUGIN_AUTHOR_NAME,
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
function getMcpConfigPath() {
|
|
21
|
-
const os = platform();
|
|
22
|
-
if (os === 'darwin') {
|
|
23
|
-
return join(homedir(), 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json');
|
|
24
|
-
}
|
|
25
|
-
if (os === 'win32') {
|
|
26
|
-
return join(process.env.APPDATA || join(homedir(), 'AppData', 'Roaming'), 'Claude', 'claude_desktop_config.json');
|
|
27
|
-
}
|
|
28
|
-
return join(homedir(), '.config', 'Claude', 'claude_desktop_config.json');
|
|
29
|
-
}
|
|
30
|
-
function getCoworkBaseDir() {
|
|
31
|
-
const os = platform();
|
|
32
|
-
if (os === 'darwin') {
|
|
33
|
-
return join(homedir(), 'Library', 'Application Support', 'Claude', 'local-agent-mode-sessions');
|
|
34
|
-
}
|
|
35
|
-
if (os === 'win32') {
|
|
36
|
-
return join(process.env.APPDATA || join(homedir(), 'AppData', 'Roaming'), 'Claude', 'local-agent-mode-sessions');
|
|
37
|
-
}
|
|
38
|
-
return join(homedir(), '.config', 'Claude', 'local-agent-mode-sessions');
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Walk all `local-agent-mode-sessions/<session>/<org>/` directories and
|
|
42
|
-
* invoke `visit` for each. Stops and returns the first non-null result.
|
|
43
|
-
*/
|
|
44
|
-
function walkOrgDirs(visit) {
|
|
45
|
-
const baseDir = getCoworkBaseDir();
|
|
46
|
-
if (!existsSync(baseDir))
|
|
47
|
-
return null;
|
|
48
|
-
try {
|
|
49
|
-
const sessionDirs = readdirSync(baseDir).filter(d => !d.startsWith('.') && d !== 'skills-plugin');
|
|
50
|
-
for (const sessionId of sessionDirs) {
|
|
51
|
-
const sessionPath = join(baseDir, sessionId);
|
|
52
|
-
let orgDirs;
|
|
53
|
-
try {
|
|
54
|
-
orgDirs = readdirSync(sessionPath).filter(d => !d.startsWith('.'));
|
|
55
|
-
}
|
|
56
|
-
catch {
|
|
57
|
-
continue;
|
|
58
|
-
}
|
|
59
|
-
for (const orgId of orgDirs) {
|
|
60
|
-
const orgDir = join(sessionPath, orgId);
|
|
61
|
-
const result = visit(orgDir);
|
|
62
|
-
if (result !== null)
|
|
63
|
-
return result;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
catch {
|
|
68
|
-
/* ignore */
|
|
69
|
-
}
|
|
70
|
-
return null;
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Collect every `<session>/<org>/memory/CLAUDE.md` path under the Cowork
|
|
74
|
-
* base directory. Claude Desktop loads this file on every conversation in
|
|
75
|
-
* the matching session/org — writing here gets Runwork instructions applied
|
|
76
|
-
* foundationally, without relying on the agent invoking a skill. We target
|
|
77
|
-
* every org we find because users may flip between sessions or orgs.
|
|
78
|
-
*/
|
|
79
|
-
export function getCoworkMemoryClaudeMdPaths() {
|
|
80
|
-
const paths = [];
|
|
81
|
-
const baseDir = getCoworkBaseDir();
|
|
82
|
-
if (!existsSync(baseDir))
|
|
83
|
-
return paths;
|
|
84
|
-
try {
|
|
85
|
-
const sessionDirs = readdirSync(baseDir).filter(d => !d.startsWith('.') && d !== 'skills-plugin');
|
|
86
|
-
for (const sessionId of sessionDirs) {
|
|
87
|
-
const sessionPath = join(baseDir, sessionId);
|
|
88
|
-
let orgDirs;
|
|
89
|
-
try {
|
|
90
|
-
orgDirs = readdirSync(sessionPath).filter(d => !d.startsWith('.'));
|
|
91
|
-
}
|
|
92
|
-
catch {
|
|
93
|
-
continue;
|
|
94
|
-
}
|
|
95
|
-
for (const orgId of orgDirs) {
|
|
96
|
-
paths.push(join(sessionPath, orgId, 'memory', 'CLAUDE.md'));
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
catch {
|
|
101
|
-
/* ignore */
|
|
102
|
-
}
|
|
103
|
-
return paths;
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Find the cowork_plugins directory by discovering the session/org ID structure.
|
|
107
|
-
* Path: local-agent-mode-sessions/<session-id>/<org-id>/cowork_plugins/
|
|
108
|
-
*/
|
|
109
|
-
function findCoworkPluginsDir() {
|
|
110
|
-
return walkOrgDirs((orgDir) => {
|
|
111
|
-
const pluginsDir = join(orgDir, 'cowork_plugins');
|
|
112
|
-
return existsSync(join(pluginsDir, 'installed_plugins.json')) ? pluginsDir : null;
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Look for a plugin named `pluginName` in any `rpm/manifest.json`. These
|
|
117
|
-
* entries are created by Claude Desktop when the user uploads a plugin zip
|
|
118
|
-
* through Customize > Create plugin > Upload plugin. If found, sync should
|
|
119
|
-
* update the plugin content files inside the rpm plugin directory instead
|
|
120
|
-
* of writing to the legacy `cowork_plugins/` layout.
|
|
121
|
-
*
|
|
122
|
-
* We never modify `rpm/manifest.json` itself — Claude Desktop owns that
|
|
123
|
-
* registry and assigns the plugin id we read from it here.
|
|
124
|
-
*/
|
|
125
|
-
export function findRpmPluginByName(pluginName) {
|
|
126
|
-
return walkOrgDirs((orgDir) => {
|
|
127
|
-
const manifestPath = join(orgDir, 'rpm', 'manifest.json');
|
|
128
|
-
if (!existsSync(manifestPath))
|
|
129
|
-
return null;
|
|
130
|
-
try {
|
|
131
|
-
const manifest = JSON.parse(readFileSync(manifestPath, 'utf-8'));
|
|
132
|
-
const entry = manifest.plugins?.find((p) => p.name === pluginName);
|
|
133
|
-
if (!entry?.id)
|
|
134
|
-
return null;
|
|
135
|
-
return {
|
|
136
|
-
pluginPath: join(orgDir, 'rpm', entry.id),
|
|
137
|
-
orgDir,
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
catch {
|
|
141
|
-
return null;
|
|
142
|
-
}
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
function getMarketplaceJson() {
|
|
146
|
-
return {
|
|
147
|
-
name: 'runwork',
|
|
148
|
-
owner: { name: PLUGIN_AUTHOR_NAME },
|
|
149
|
-
plugins: [
|
|
150
|
-
{
|
|
151
|
-
name: PLUGIN_NAME,
|
|
152
|
-
source: `./plugins/${PLUGIN_NAME}`,
|
|
153
|
-
description: PLUGIN_DESCRIPTION,
|
|
154
|
-
},
|
|
155
|
-
],
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
function getCoworkSettingsPath(pluginsDir) {
|
|
159
|
-
return join(dirname(pluginsDir), 'cowork_settings.json');
|
|
160
|
-
}
|
|
161
|
-
function setCoworkPluginEnabled(pluginsDir, enabled) {
|
|
162
|
-
const settingsPath = getCoworkSettingsPath(pluginsDir);
|
|
163
|
-
const settings = readJsonConfig(settingsPath);
|
|
164
|
-
const enabledPlugins = (settings.enabledPlugins ?? {});
|
|
165
|
-
enabledPlugins[`${PLUGIN_NAME}@runwork`] = enabled;
|
|
166
|
-
settings.enabledPlugins = enabledPlugins;
|
|
167
|
-
writeJsonConfig(settingsPath, settings);
|
|
168
|
-
}
|
|
169
|
-
export class ClaudeDesktopAdapter {
|
|
170
|
-
name = 'Claude Desktop (Cowork)';
|
|
171
|
-
slug = 'claude-desktop';
|
|
172
|
-
async detect() {
|
|
173
|
-
const os = platform();
|
|
174
|
-
if (os === 'darwin')
|
|
175
|
-
return existsSync('/Applications/Claude.app');
|
|
176
|
-
return existsSync(getMcpConfigPath());
|
|
177
|
-
}
|
|
178
|
-
supportsMcpScope(scope) {
|
|
179
|
-
return scope === 'user';
|
|
180
|
-
}
|
|
181
|
-
supportsSkills() {
|
|
182
|
-
return true;
|
|
183
|
-
}
|
|
184
|
-
async writeMcpServers(servers, _scope) {
|
|
185
|
-
// Claude Desktop has two MCP transport paths:
|
|
186
|
-
// 1. claude_desktop_config.json with mcp-remote (stdio bridge): for chat mode
|
|
187
|
-
// 2. .mcp.json inside the plugin directory (native HTTP): for cowork mode connectors
|
|
188
|
-
//
|
|
189
|
-
// For cowork connectors, embed the auth token in the URL query string.
|
|
190
|
-
// This lets Claude Desktop connect without requiring the user to go through
|
|
191
|
-
// an OAuth flow or manually click "Connect" in the Connectors UI.
|
|
192
|
-
// Write to claude_desktop_config.json via mcp-remote (chat mode fallback).
|
|
193
|
-
// Forward every auth header (Authorization, X-Api-Key, etc.) as a --header arg.
|
|
194
|
-
const entries = {};
|
|
195
|
-
for (const s of servers) {
|
|
196
|
-
const args = ['mcp-remote', s.url];
|
|
197
|
-
if (s.headers) {
|
|
198
|
-
for (const [name, value] of Object.entries(s.headers)) {
|
|
199
|
-
args.push('--header', `${name}:${value}`);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
entries[s.name] = {
|
|
203
|
-
command: 'npx',
|
|
204
|
-
args: ['-y', ...args],
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
mergeJsonMcpServers(getMcpConfigPath(), entries, 'mcpServers');
|
|
208
|
-
// Prefer rpm/plugin_<id>/ when the user has uploaded our zip through
|
|
209
|
-
// Claude Desktop's Customize > Create plugin > Upload plugin flow.
|
|
210
|
-
const rpm = findRpmPluginByName(PLUGIN_NAME);
|
|
211
|
-
if (rpm) {
|
|
212
|
-
writePluginMcpConfig(rpm.pluginPath, servers);
|
|
213
|
-
return;
|
|
214
|
-
}
|
|
215
|
-
// Fall back to the legacy cowork_plugins layout (cache + marketplace).
|
|
216
|
-
const pluginsDir = findCoworkPluginsDir();
|
|
217
|
-
if (pluginsDir) {
|
|
218
|
-
const cacheDir = join(pluginsDir, 'cache', 'runwork', PLUGIN_NAME, PLUGIN_VERSION);
|
|
219
|
-
const marketDir = join(pluginsDir, 'marketplaces', 'runwork', 'plugins', PLUGIN_NAME);
|
|
220
|
-
for (const dir of [cacheDir, marketDir]) {
|
|
221
|
-
writePluginMcpConfig(dir, servers);
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
async writeSkills(skills, _scope) {
|
|
226
|
-
// Prefer rpm/plugin_<id>/ when the user has uploaded our zip through
|
|
227
|
-
// Claude Desktop's Customize > Create plugin > Upload plugin flow.
|
|
228
|
-
// Claude Desktop owns rpm/manifest.json (registration, enablement),
|
|
229
|
-
// so we only refresh the plugin content files.
|
|
230
|
-
const rpm = findRpmPluginByName(PLUGIN_NAME);
|
|
231
|
-
if (rpm) {
|
|
232
|
-
writePluginMetadata(rpm.pluginPath, getPluginMetadata());
|
|
233
|
-
writePluginSkills(rpm.pluginPath, skills);
|
|
234
|
-
return;
|
|
235
|
-
}
|
|
236
|
-
const pluginsDir = findCoworkPluginsDir();
|
|
237
|
-
if (!pluginsDir) {
|
|
238
|
-
console.warn(' [Claude Desktop] Cowork plugins directory not found. Open Claude Desktop at least once first.');
|
|
239
|
-
return;
|
|
240
|
-
}
|
|
241
|
-
// Fall back to legacy cowork_plugins layout: write to both cache
|
|
242
|
-
// (installed copy) and marketplaces (source).
|
|
243
|
-
const cacheDir = join(pluginsDir, 'cache', 'runwork', PLUGIN_NAME, PLUGIN_VERSION);
|
|
244
|
-
const marketRoot = join(pluginsDir, 'marketplaces', 'runwork');
|
|
245
|
-
const marketDir = join(marketRoot, 'plugins', PLUGIN_NAME);
|
|
246
|
-
for (const dir of [cacheDir, marketDir]) {
|
|
247
|
-
writePluginMetadata(dir, getPluginMetadata());
|
|
248
|
-
writePluginSkills(dir, skills);
|
|
249
|
-
}
|
|
250
|
-
// Register in installed_plugins.json
|
|
251
|
-
const installedPath = join(pluginsDir, 'installed_plugins.json');
|
|
252
|
-
const installed = readJsonConfig(installedPath);
|
|
253
|
-
if (!installed.version)
|
|
254
|
-
installed.version = 2;
|
|
255
|
-
if (!installed.plugins)
|
|
256
|
-
installed.plugins = {};
|
|
257
|
-
installed.plugins[`${PLUGIN_NAME}@runwork`] = [{
|
|
258
|
-
scope: 'user',
|
|
259
|
-
installPath: cacheDir,
|
|
260
|
-
version: PLUGIN_VERSION,
|
|
261
|
-
installedAt: new Date().toISOString(),
|
|
262
|
-
lastUpdated: new Date().toISOString(),
|
|
263
|
-
}];
|
|
264
|
-
writeJsonConfig(installedPath, installed);
|
|
265
|
-
// Write marketplace.json catalog
|
|
266
|
-
const marketCatalogDir = join(marketRoot, '.claude-plugin');
|
|
267
|
-
mkdirSync(marketCatalogDir, { recursive: true });
|
|
268
|
-
writeFileSync(join(marketCatalogDir, 'marketplace.json'), JSON.stringify(getMarketplaceJson(), null, 2));
|
|
269
|
-
// Register in known_marketplaces.json
|
|
270
|
-
const marketplacesPath = join(pluginsDir, 'known_marketplaces.json');
|
|
271
|
-
const marketplaces = readJsonConfig(marketplacesPath);
|
|
272
|
-
marketplaces['runwork'] = {
|
|
273
|
-
source: { source: 'directory', path: marketRoot },
|
|
274
|
-
installLocation: marketRoot,
|
|
275
|
-
lastUpdated: new Date().toISOString(),
|
|
276
|
-
};
|
|
277
|
-
writeJsonConfig(marketplacesPath, marketplaces);
|
|
278
|
-
// Sync should recover a previously disabled plugin so it shows up in Customize.
|
|
279
|
-
setCoworkPluginEnabled(pluginsDir, true);
|
|
280
|
-
}
|
|
281
|
-
async writeInstructionHint(hint, _scope) {
|
|
282
|
-
// Cowork loads `<session>/<org>/memory/CLAUDE.md` on every conversation.
|
|
283
|
-
// This is the same always-on memory surface Claude Code uses with
|
|
284
|
-
// `~/.claude/CLAUDE.md`, so it's the right home for foundational hints.
|
|
285
|
-
// Merge into marker blocks so any user-authored content above/below our
|
|
286
|
-
// block is preserved.
|
|
287
|
-
for (const path of getCoworkMemoryClaudeMdPaths()) {
|
|
288
|
-
try {
|
|
289
|
-
writeHintToFile(path, hint);
|
|
290
|
-
}
|
|
291
|
-
catch { /* best-effort per org */ }
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
async buildPluginZip(skills, mcpServers, teamInstructions, outputPath) {
|
|
295
|
-
// Materialise the plugin tree into a temp dir, zip it, then clean up.
|
|
296
|
-
// Uses the same writePluginTree + writePluginTeamInstructions helpers
|
|
297
|
-
// the sync path uses so the on-disk layout is byte-identical whether
|
|
298
|
-
// the user installs via upload or sync.
|
|
299
|
-
const stagingRoot = mkdtempSync(join(tmpdir(), 'runwork-plugin-'));
|
|
300
|
-
const pluginStagingDir = join(stagingRoot, PLUGIN_NAME);
|
|
301
|
-
try {
|
|
302
|
-
writePluginTree(pluginStagingDir, {
|
|
303
|
-
...getPluginMetadata(),
|
|
304
|
-
skills,
|
|
305
|
-
mcpServers,
|
|
306
|
-
});
|
|
307
|
-
if (teamInstructions) {
|
|
308
|
-
writePluginTeamInstructions(pluginStagingDir, teamInstructions);
|
|
309
|
-
}
|
|
310
|
-
createZipFromDir(pluginStagingDir, outputPath);
|
|
311
|
-
}
|
|
312
|
-
finally {
|
|
313
|
-
try {
|
|
314
|
-
rmSync(stagingRoot, { recursive: true, force: true });
|
|
315
|
-
}
|
|
316
|
-
catch {
|
|
317
|
-
/* best-effort */
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
async writeTeamInstructions(instructions, _scope) {
|
|
322
|
-
// Primary surface: `<org>/memory/CLAUDE.md`. Cowork auto-loads this on
|
|
323
|
-
// every conversation, matching the Claude Code convention. Write through
|
|
324
|
-
// the team-instructions marker block so user-authored content is safe.
|
|
325
|
-
for (const path of getCoworkMemoryClaudeMdPaths()) {
|
|
326
|
-
try {
|
|
327
|
-
writeTeamInstructionsToFile(path, instructions);
|
|
328
|
-
}
|
|
329
|
-
catch { /* best-effort per org */ }
|
|
330
|
-
}
|
|
331
|
-
// Secondary surface: the plugin's `runwork-team-instructions` SKILL.md.
|
|
332
|
-
// Kept for the build-plugin zip flow and as a slash-command fallback
|
|
333
|
-
// when users inspect plugin skills. Prefer the rpm upload location when
|
|
334
|
-
// present, otherwise fall back to the legacy cowork_plugins layout.
|
|
335
|
-
const rpm = findRpmPluginByName(PLUGIN_NAME);
|
|
336
|
-
if (rpm) {
|
|
337
|
-
writePluginTeamInstructions(rpm.pluginPath, instructions);
|
|
338
|
-
return;
|
|
339
|
-
}
|
|
340
|
-
const pluginsDir = findCoworkPluginsDir();
|
|
341
|
-
if (!pluginsDir)
|
|
342
|
-
return;
|
|
343
|
-
writePluginTeamInstructions(join(pluginsDir, 'cache', 'runwork', PLUGIN_NAME, PLUGIN_VERSION), instructions);
|
|
344
|
-
writePluginTeamInstructions(join(pluginsDir, 'marketplaces', 'runwork', 'plugins', PLUGIN_NAME), instructions);
|
|
345
|
-
}
|
|
346
|
-
// ── Agent config (limited to preferences) ──────────────────────────
|
|
347
|
-
async writeAgentConfig(config, _scope) {
|
|
348
|
-
const configPath = getMcpConfigPath();
|
|
349
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
350
|
-
let desktopConfig = {};
|
|
351
|
-
if (existsSync(configPath)) {
|
|
352
|
-
try {
|
|
353
|
-
desktopConfig = JSON.parse(readFileSync(configPath, 'utf-8'));
|
|
354
|
-
}
|
|
355
|
-
catch { /* start fresh */ }
|
|
356
|
-
}
|
|
357
|
-
if (!desktopConfig.preferences)
|
|
358
|
-
desktopConfig.preferences = {};
|
|
359
|
-
const prefs = desktopConfig.preferences;
|
|
360
|
-
if (config.permissionRules) {
|
|
361
|
-
if (config.permissionRules.allow?.includes('web_search')) {
|
|
362
|
-
prefs.coworkWebSearchEnabled = true;
|
|
363
|
-
}
|
|
364
|
-
if (config.permissionRules.deny?.includes('web_search')) {
|
|
365
|
-
prefs.coworkWebSearchEnabled = false;
|
|
366
|
-
}
|
|
367
|
-
if (config.permissionRules.allow?.includes('scheduled_tasks')) {
|
|
368
|
-
prefs.coworkScheduledTasksEnabled = true;
|
|
369
|
-
prefs.ccdScheduledTasksEnabled = true;
|
|
370
|
-
}
|
|
371
|
-
if (config.permissionRules.deny?.includes('scheduled_tasks')) {
|
|
372
|
-
prefs.coworkScheduledTasksEnabled = false;
|
|
373
|
-
prefs.ccdScheduledTasksEnabled = false;
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
writeFileSync(configPath, JSON.stringify(desktopConfig, null, 2));
|
|
377
|
-
}
|
|
378
|
-
// ── Cleanup (uninstall) ────────────────────────────────────────────
|
|
379
|
-
async cleanup(_scope, _manifest) {
|
|
380
|
-
// 1. Remove MCP entries from claude_desktop_config.json
|
|
381
|
-
removeRunworkMcpServers(getMcpConfigPath(), 'mcpServers');
|
|
382
|
-
// Remove Runwork marker blocks from each org's memory/CLAUDE.md, leaving
|
|
383
|
-
// any user-authored content in that file intact.
|
|
384
|
-
for (const path of getCoworkMemoryClaudeMdPaths()) {
|
|
385
|
-
try {
|
|
386
|
-
removeHintFromFile(path);
|
|
387
|
-
}
|
|
388
|
-
catch { /* best-effort per org */ }
|
|
389
|
-
try {
|
|
390
|
-
removeTeamInstructionsFromFile(path);
|
|
391
|
-
}
|
|
392
|
-
catch { /* best-effort per org */ }
|
|
393
|
-
}
|
|
394
|
-
// 2. Remove the uploaded rpm plugin if the user installed via
|
|
395
|
-
// Customize > Create plugin > Upload plugin. We delete both the
|
|
396
|
-
// plugin directory and the manifest entry so Claude Desktop does
|
|
397
|
-
// not show a stale Runwork plugin after uninstall.
|
|
398
|
-
const rpm = findRpmPluginByName(PLUGIN_NAME);
|
|
399
|
-
if (rpm) {
|
|
400
|
-
if (existsSync(rpm.pluginPath)) {
|
|
401
|
-
try {
|
|
402
|
-
rmSync(rpm.pluginPath, { recursive: true, force: true });
|
|
403
|
-
}
|
|
404
|
-
catch { /* best-effort */ }
|
|
405
|
-
}
|
|
406
|
-
const manifestPath = join(rpm.orgDir, 'rpm', 'manifest.json');
|
|
407
|
-
if (existsSync(manifestPath)) {
|
|
408
|
-
try {
|
|
409
|
-
const manifest = JSON.parse(readFileSync(manifestPath, 'utf-8'));
|
|
410
|
-
if (Array.isArray(manifest.plugins)) {
|
|
411
|
-
manifest.plugins = manifest.plugins.filter((p) => p.name !== PLUGIN_NAME);
|
|
412
|
-
manifest.lastUpdated = Date.now();
|
|
413
|
-
writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
catch { /* best-effort */ }
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
// 3. Remove Cowork plugin directories and registration
|
|
420
|
-
const pluginsDir = findCoworkPluginsDir();
|
|
421
|
-
if (pluginsDir) {
|
|
422
|
-
// Remove cache/runwork and marketplaces/runwork directories
|
|
423
|
-
const cacheRunwork = join(pluginsDir, 'cache', 'runwork');
|
|
424
|
-
const marketRunwork = join(pluginsDir, 'marketplaces', 'runwork');
|
|
425
|
-
for (const dir of [cacheRunwork, marketRunwork]) {
|
|
426
|
-
if (existsSync(dir)) {
|
|
427
|
-
try {
|
|
428
|
-
rmSync(dir, { recursive: true, force: true });
|
|
429
|
-
}
|
|
430
|
-
catch { /* best-effort */ }
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
// Remove from installed_plugins.json
|
|
434
|
-
const installedPath = join(pluginsDir, 'installed_plugins.json');
|
|
435
|
-
if (existsSync(installedPath)) {
|
|
436
|
-
try {
|
|
437
|
-
const installed = readJsonConfig(installedPath);
|
|
438
|
-
if (installed.plugins) {
|
|
439
|
-
delete installed.plugins[`${PLUGIN_NAME}@runwork`];
|
|
440
|
-
writeJsonConfig(installedPath, installed);
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
catch { /* best-effort */ }
|
|
444
|
-
}
|
|
445
|
-
// Remove from known_marketplaces.json
|
|
446
|
-
const marketplacesPath = join(pluginsDir, 'known_marketplaces.json');
|
|
447
|
-
if (existsSync(marketplacesPath)) {
|
|
448
|
-
try {
|
|
449
|
-
const marketplaces = readJsonConfig(marketplacesPath);
|
|
450
|
-
delete marketplaces['runwork'];
|
|
451
|
-
writeJsonConfig(marketplacesPath, marketplaces);
|
|
452
|
-
}
|
|
453
|
-
catch { /* best-effort */ }
|
|
454
|
-
}
|
|
455
|
-
// Remove the enable flag so cleanup fully unregisters the plugin.
|
|
456
|
-
const coworkSettingsPath = getCoworkSettingsPath(pluginsDir);
|
|
457
|
-
if (existsSync(coworkSettingsPath)) {
|
|
458
|
-
try {
|
|
459
|
-
const settings = readJsonConfig(coworkSettingsPath);
|
|
460
|
-
const enabledPlugins = settings.enabledPlugins;
|
|
461
|
-
if (enabledPlugins && typeof enabledPlugins === 'object' && !Array.isArray(enabledPlugins)) {
|
|
462
|
-
delete enabledPlugins[`${PLUGIN_NAME}@runwork`];
|
|
463
|
-
settings.enabledPlugins = enabledPlugins;
|
|
464
|
-
writeJsonConfig(coworkSettingsPath, settings);
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
catch { /* best-effort */ }
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
// ── Usage stats (passive, best-effort) ─────────────────────────────
|
|
472
|
-
async readUsageStats(lastSyncAt) {
|
|
473
|
-
try {
|
|
474
|
-
const os = platform();
|
|
475
|
-
let claudeAppDir;
|
|
476
|
-
if (os === 'darwin') {
|
|
477
|
-
claudeAppDir = join(homedir(), 'Library', 'Application Support', 'Claude');
|
|
478
|
-
}
|
|
479
|
-
else if (os === 'win32') {
|
|
480
|
-
claudeAppDir = join(process.env.APPDATA || join(homedir(), 'AppData', 'Roaming'), 'Claude');
|
|
481
|
-
}
|
|
482
|
-
else {
|
|
483
|
-
claudeAppDir = join(homedir(), '.config', 'Claude');
|
|
484
|
-
}
|
|
485
|
-
if (!existsSync(claudeAppDir))
|
|
486
|
-
return null;
|
|
487
|
-
const sinceMs = lastSyncAt ? new Date(lastSyncAt).getTime() : 0;
|
|
488
|
-
let sessionCount = 0;
|
|
489
|
-
let latestActivity = 0;
|
|
490
|
-
const modelsUsed = new Set();
|
|
491
|
-
let maxMcpTools = 0;
|
|
492
|
-
// Read agent mode session JSON files
|
|
493
|
-
// Path: local-agent-mode-sessions/{orgId}/{userId}/*.json
|
|
494
|
-
const agentSessionsDir = join(claudeAppDir, 'local-agent-mode-sessions');
|
|
495
|
-
if (existsSync(agentSessionsDir)) {
|
|
496
|
-
this.walkSessionDirs(agentSessionsDir, sinceMs, (session) => {
|
|
497
|
-
const sessionTime = session.lastActivityAt ?? session.createdAt ?? 0;
|
|
498
|
-
if (sessionTime > sinceMs)
|
|
499
|
-
sessionCount++;
|
|
500
|
-
if (sessionTime > latestActivity)
|
|
501
|
-
latestActivity = sessionTime;
|
|
502
|
-
if (session.model)
|
|
503
|
-
modelsUsed.add(session.model);
|
|
504
|
-
if (session.enabledMcpTools && typeof session.enabledMcpTools === 'object') {
|
|
505
|
-
const toolCount = Object.keys(session.enabledMcpTools).length;
|
|
506
|
-
if (toolCount > maxMcpTools)
|
|
507
|
-
maxMcpTools = toolCount;
|
|
508
|
-
}
|
|
509
|
-
});
|
|
510
|
-
}
|
|
511
|
-
// Also check code sessions launched from Desktop
|
|
512
|
-
const codeSessionsDir = join(claudeAppDir, 'claude-code-sessions');
|
|
513
|
-
if (existsSync(codeSessionsDir)) {
|
|
514
|
-
this.walkSessionDirs(codeSessionsDir, sinceMs, (session) => {
|
|
515
|
-
const sessionTime = session.lastActivityAt ?? session.createdAt ?? 0;
|
|
516
|
-
if (sessionTime > sinceMs)
|
|
517
|
-
sessionCount++;
|
|
518
|
-
if (sessionTime > latestActivity)
|
|
519
|
-
latestActivity = sessionTime;
|
|
520
|
-
if (session.model)
|
|
521
|
-
modelsUsed.add(session.model);
|
|
522
|
-
});
|
|
523
|
-
}
|
|
524
|
-
// Check scheduled tasks
|
|
525
|
-
let scheduledTaskRuns = 0;
|
|
526
|
-
const scheduledTasksPath = join(claudeAppDir, 'scheduled-tasks.json');
|
|
527
|
-
if (existsSync(scheduledTasksPath)) {
|
|
528
|
-
try {
|
|
529
|
-
const raw = readFileSync(scheduledTasksPath, 'utf-8');
|
|
530
|
-
const parsed = JSON.parse(raw);
|
|
531
|
-
const tasks = Array.isArray(parsed) ? parsed : Object.values(parsed);
|
|
532
|
-
for (const task of tasks) {
|
|
533
|
-
const t = task;
|
|
534
|
-
if (t.lastRunAt && new Date(t.lastRunAt).getTime() > sinceMs) {
|
|
535
|
-
scheduledTaskRuns++;
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
catch { /* best-effort */ }
|
|
540
|
-
}
|
|
541
|
-
if (sessionCount === 0 && latestActivity <= sinceMs && scheduledTaskRuns === 0)
|
|
542
|
-
return null;
|
|
543
|
-
return {
|
|
544
|
-
hasNewActivity: sessionCount > 0 || scheduledTaskRuns > 0,
|
|
545
|
-
sessionCount,
|
|
546
|
-
messageCount: 0,
|
|
547
|
-
toolCallCount: 0,
|
|
548
|
-
tokensUsed: 0,
|
|
549
|
-
aiLinesAdded: 0,
|
|
550
|
-
aiLinesRemoved: 0,
|
|
551
|
-
lastActiveAt: latestActivity > 0 ? new Date(latestActivity).toISOString() : null,
|
|
552
|
-
modelsUsed: Array.from(modelsUsed),
|
|
553
|
-
mcpToolCount: maxMcpTools > 0 ? maxMcpTools : undefined,
|
|
554
|
-
extra: scheduledTaskRuns > 0 ? { scheduledTaskRuns } : undefined,
|
|
555
|
-
};
|
|
556
|
-
}
|
|
557
|
-
catch {
|
|
558
|
-
return null;
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
async readVersion() {
|
|
562
|
-
try {
|
|
563
|
-
const os = platform();
|
|
564
|
-
let claudeAppDir;
|
|
565
|
-
if (os === 'darwin') {
|
|
566
|
-
claudeAppDir = join(homedir(), 'Library', 'Application Support', 'Claude');
|
|
567
|
-
}
|
|
568
|
-
else if (os === 'win32') {
|
|
569
|
-
claudeAppDir = join(process.env.APPDATA || join(homedir(), 'AppData', 'Roaming'), 'Claude');
|
|
570
|
-
}
|
|
571
|
-
else {
|
|
572
|
-
claudeAppDir = join(homedir(), '.config', 'Claude');
|
|
573
|
-
}
|
|
574
|
-
const versionPath = join(claudeAppDir, 'claude-code', 'sdk-version');
|
|
575
|
-
if (existsSync(versionPath)) {
|
|
576
|
-
return readFileSync(versionPath, 'utf-8').trim();
|
|
577
|
-
}
|
|
578
|
-
return null;
|
|
579
|
-
}
|
|
580
|
-
catch {
|
|
581
|
-
return null;
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
async readSkillUsage(lastSyncAt) {
|
|
585
|
-
// Cowork session JSON files contain enabledMcpTools, an object whose keys
|
|
586
|
-
// are MCP tool names. Tools matching skill_* patterns indicate which skills
|
|
587
|
-
// were loaded (reach, not invocation). This is the best we can get from
|
|
588
|
-
// local data. For actual invocation data, OTEL or the Enterprise Analytics
|
|
589
|
-
// API are needed.
|
|
590
|
-
try {
|
|
591
|
-
const baseDir = getCoworkBaseDir();
|
|
592
|
-
if (!existsSync(baseDir))
|
|
593
|
-
return null;
|
|
594
|
-
const sinceMs = lastSyncAt ? new Date(lastSyncAt).getTime() : 0;
|
|
595
|
-
const skillCounts = new Map();
|
|
596
|
-
const agentSessionsDir = baseDir;
|
|
597
|
-
this.walkSessionDirs(agentSessionsDir, sinceMs, (session) => {
|
|
598
|
-
const sessionTime = session.lastActivityAt ?? session.createdAt ?? 0;
|
|
599
|
-
if (sessionTime <= sinceMs)
|
|
600
|
-
return;
|
|
601
|
-
const mcpTools = session.enabledMcpTools;
|
|
602
|
-
if (!mcpTools || typeof mcpTools !== 'object')
|
|
603
|
-
return;
|
|
604
|
-
for (const toolName of Object.keys(mcpTools)) {
|
|
605
|
-
// Match patterns like "skill_Blog_Writing_Specialist" or
|
|
606
|
-
// "mcp__Runwork__skill_Write_Cold_Email"
|
|
607
|
-
const skillMatch = toolName.match(/skill_([A-Za-z0-9_]+)/);
|
|
608
|
-
if (!skillMatch)
|
|
609
|
-
continue;
|
|
610
|
-
// Convert Tool_Name_Format to readable name
|
|
611
|
-
const rawName = skillMatch[1].replace(/_/g, ' ').trim();
|
|
612
|
-
if (!rawName)
|
|
613
|
-
continue;
|
|
614
|
-
const existing = skillCounts.get(rawName);
|
|
615
|
-
if (existing) {
|
|
616
|
-
existing.count++;
|
|
617
|
-
if (sessionTime > existing.lastTs)
|
|
618
|
-
existing.lastTs = sessionTime;
|
|
619
|
-
}
|
|
620
|
-
else {
|
|
621
|
-
skillCounts.set(rawName, { count: 1, lastTs: sessionTime });
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
});
|
|
625
|
-
if (skillCounts.size === 0)
|
|
626
|
-
return null;
|
|
627
|
-
const results = [];
|
|
628
|
-
for (const [skillName, { count, lastTs }] of skillCounts) {
|
|
629
|
-
results.push({
|
|
630
|
-
skillName,
|
|
631
|
-
count,
|
|
632
|
-
lastUsedAt: new Date(lastTs).toISOString(),
|
|
633
|
-
});
|
|
634
|
-
}
|
|
635
|
-
return results;
|
|
636
|
-
}
|
|
637
|
-
catch {
|
|
638
|
-
return null;
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
/**
|
|
642
|
-
* Walk the org/user/session directory tree and invoke callback for each session JSON.
|
|
643
|
-
*/
|
|
644
|
-
walkSessionDirs(baseDir, _sinceMs, onSession) {
|
|
645
|
-
try {
|
|
646
|
-
for (const orgDir of readdirSync(baseDir)) {
|
|
647
|
-
if (orgDir.startsWith('.') || orgDir === 'skills-plugin')
|
|
648
|
-
continue;
|
|
649
|
-
const orgPath = join(baseDir, orgDir);
|
|
650
|
-
try {
|
|
651
|
-
if (!statSync(orgPath).isDirectory())
|
|
652
|
-
continue;
|
|
653
|
-
}
|
|
654
|
-
catch {
|
|
655
|
-
continue;
|
|
656
|
-
}
|
|
657
|
-
for (const userDir of readdirSync(orgPath)) {
|
|
658
|
-
if (userDir.startsWith('.'))
|
|
659
|
-
continue;
|
|
660
|
-
const userPath = join(orgPath, userDir);
|
|
661
|
-
try {
|
|
662
|
-
if (!statSync(userPath).isDirectory())
|
|
663
|
-
continue;
|
|
664
|
-
}
|
|
665
|
-
catch {
|
|
666
|
-
continue;
|
|
667
|
-
}
|
|
668
|
-
for (const file of readdirSync(userPath)) {
|
|
669
|
-
if (!file.endsWith('.json'))
|
|
670
|
-
continue;
|
|
671
|
-
try {
|
|
672
|
-
const session = JSON.parse(readFileSync(join(userPath, file), 'utf-8'));
|
|
673
|
-
onSession(session);
|
|
674
|
-
}
|
|
675
|
-
catch {
|
|
676
|
-
continue;
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
catch { /* best-effort */ }
|
|
683
|
-
}
|
|
684
|
-
}
|