nomoreide 0.2.0 → 0.3.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/README.md +12 -9
- package/bin/nomoreide.js +82 -0
- package/package.json +24 -132
- package/dist/cli/agents.d.ts +0 -2
- package/dist/cli/agents.js +0 -43
- package/dist/cli/agents.js.map +0 -1
- package/dist/cli/commands.d.ts +0 -11
- package/dist/cli/commands.js +0 -235
- package/dist/cli/commands.js.map +0 -1
- package/dist/cli/daemon.d.ts +0 -15
- package/dist/cli/daemon.js +0 -139
- package/dist/cli/daemon.js.map +0 -1
- package/dist/cli/database.d.ts +0 -2
- package/dist/cli/database.js +0 -145
- package/dist/cli/database.js.map +0 -1
- package/dist/cli/errors.d.ts +0 -2
- package/dist/cli/errors.js +0 -3
- package/dist/cli/errors.js.map +0 -1
- package/dist/cli/flags.d.ts +0 -1
- package/dist/cli/flags.js +0 -19
- package/dist/cli/flags.js.map +0 -1
- package/dist/cli/git.d.ts +0 -2
- package/dist/cli/git.js +0 -113
- package/dist/cli/git.js.map +0 -1
- package/dist/cli/profile.d.ts +0 -2
- package/dist/cli/profile.js +0 -171
- package/dist/cli/profile.js.map +0 -1
- package/dist/core/agent-context.d.ts +0 -9
- package/dist/core/agent-context.js +0 -43
- package/dist/core/agent-context.js.map +0 -1
- package/dist/core/agent-env/antigravity-reader.d.ts +0 -7
- package/dist/core/agent-env/antigravity-reader.js +0 -86
- package/dist/core/agent-env/antigravity-reader.js.map +0 -1
- package/dist/core/agent-env/availability.d.ts +0 -6
- package/dist/core/agent-env/availability.js +0 -79
- package/dist/core/agent-env/availability.js.map +0 -1
- package/dist/core/agent-env/claude-reader.d.ts +0 -7
- package/dist/core/agent-env/claude-reader.js +0 -101
- package/dist/core/agent-env/claude-reader.js.map +0 -1
- package/dist/core/agent-env/codex-reader.d.ts +0 -11
- package/dist/core/agent-env/codex-reader.js +0 -164
- package/dist/core/agent-env/codex-reader.js.map +0 -1
- package/dist/core/agent-env/index.d.ts +0 -9
- package/dist/core/agent-env/index.js +0 -29
- package/dist/core/agent-env/index.js.map +0 -1
- package/dist/core/agent-env/managed-plugins.d.ts +0 -18
- package/dist/core/agent-env/managed-plugins.js +0 -68
- package/dist/core/agent-env/managed-plugins.js.map +0 -1
- package/dist/core/agent-env/plugin-reader.d.ts +0 -9
- package/dist/core/agent-env/plugin-reader.js +0 -174
- package/dist/core/agent-env/plugin-reader.js.map +0 -1
- package/dist/core/agent-env/shared.d.ts +0 -26
- package/dist/core/agent-env/shared.js +0 -116
- package/dist/core/agent-env/shared.js.map +0 -1
- package/dist/core/agent-env/types.d.ts +0 -66
- package/dist/core/agent-env/types.js +0 -7
- package/dist/core/agent-env/types.js.map +0 -1
- package/dist/core/agent-env-actions.d.ts +0 -117
- package/dist/core/agent-env-actions.js +0 -273
- package/dist/core/agent-env-actions.js.map +0 -1
- package/dist/core/agent-env-plugin-uninstall.d.ts +0 -11
- package/dist/core/agent-env-plugin-uninstall.js +0 -189
- package/dist/core/agent-env-plugin-uninstall.js.map +0 -1
- package/dist/core/agent-env-writers.d.ts +0 -71
- package/dist/core/agent-env-writers.js +0 -632
- package/dist/core/agent-env-writers.js.map +0 -1
- package/dist/core/agent-profiles/apply.d.ts +0 -57
- package/dist/core/agent-profiles/apply.js +0 -209
- package/dist/core/agent-profiles/apply.js.map +0 -1
- package/dist/core/agent-profiles/builtin.d.ts +0 -8
- package/dist/core/agent-profiles/builtin.js +0 -33
- package/dist/core/agent-profiles/builtin.js.map +0 -1
- package/dist/core/agent-profiles/credentials.d.ts +0 -26
- package/dist/core/agent-profiles/credentials.js +0 -151
- package/dist/core/agent-profiles/credentials.js.map +0 -1
- package/dist/core/agent-profiles/debug-setup.d.ts +0 -18
- package/dist/core/agent-profiles/debug-setup.js +0 -237
- package/dist/core/agent-profiles/debug-setup.js.map +0 -1
- package/dist/core/agent-profiles/index.d.ts +0 -18
- package/dist/core/agent-profiles/index.js +0 -19
- package/dist/core/agent-profiles/index.js.map +0 -1
- package/dist/core/agent-profiles/plugin-apply.d.ts +0 -16
- package/dist/core/agent-profiles/plugin-apply.js +0 -383
- package/dist/core/agent-profiles/plugin-apply.js.map +0 -1
- package/dist/core/agent-profiles/plugin-bundle.d.ts +0 -6
- package/dist/core/agent-profiles/plugin-bundle.js +0 -32
- package/dist/core/agent-profiles/plugin-bundle.js.map +0 -1
- package/dist/core/agent-profiles/publication.d.ts +0 -105
- package/dist/core/agent-profiles/publication.js +0 -126
- package/dist/core/agent-profiles/publication.js.map +0 -1
- package/dist/core/agent-profiles/registry-auth.d.ts +0 -25
- package/dist/core/agent-profiles/registry-auth.js +0 -78
- package/dist/core/agent-profiles/registry-auth.js.map +0 -1
- package/dist/core/agent-profiles/registry-client.d.ts +0 -98
- package/dist/core/agent-profiles/registry-client.js +0 -109
- package/dist/core/agent-profiles/registry-client.js.map +0 -1
- package/dist/core/agent-profiles/registry-config.d.ts +0 -62
- package/dist/core/agent-profiles/registry-config.js +0 -221
- package/dist/core/agent-profiles/registry-config.js.map +0 -1
- package/dist/core/agent-profiles/registry-transfer.d.ts +0 -42
- package/dist/core/agent-profiles/registry-transfer.js +0 -133
- package/dist/core/agent-profiles/registry-transfer.js.map +0 -1
- package/dist/core/agent-profiles/store.d.ts +0 -62
- package/dist/core/agent-profiles/store.js +0 -479
- package/dist/core/agent-profiles/store.js.map +0 -1
- package/dist/core/agent-profiles/transfer.d.ts +0 -27
- package/dist/core/agent-profiles/transfer.js +0 -359
- package/dist/core/agent-profiles/transfer.js.map +0 -1
- package/dist/core/agent-profiles/types.d.ts +0 -364
- package/dist/core/agent-profiles/types.js +0 -79
- package/dist/core/agent-profiles/types.js.map +0 -1
- package/dist/core/agent-runtime.d.ts +0 -114
- package/dist/core/agent-runtime.js +0 -494
- package/dist/core/agent-runtime.js.map +0 -1
- package/dist/core/agent-sessions.d.ts +0 -46
- package/dist/core/agent-sessions.js +0 -109
- package/dist/core/agent-sessions.js.map +0 -1
- package/dist/core/agent-settings.d.ts +0 -31
- package/dist/core/agent-settings.js +0 -129
- package/dist/core/agent-settings.js.map +0 -1
- package/dist/core/agent-terminal.d.ts +0 -22
- package/dist/core/agent-terminal.js +0 -62
- package/dist/core/agent-terminal.js.map +0 -1
- package/dist/core/agent-transcripts.d.ts +0 -29
- package/dist/core/agent-transcripts.js +0 -281
- package/dist/core/agent-transcripts.js.map +0 -1
- package/dist/core/app-settings.d.ts +0 -74
- package/dist/core/app-settings.js +0 -118
- package/dist/core/app-settings.js.map +0 -1
- package/dist/core/app-version.d.ts +0 -2
- package/dist/core/app-version.js +0 -16
- package/dist/core/app-version.js.map +0 -1
- package/dist/core/approval-broker.d.ts +0 -29
- package/dist/core/approval-broker.js +0 -48
- package/dist/core/approval-broker.js.map +0 -1
- package/dist/core/claude-settings.d.ts +0 -18
- package/dist/core/claude-settings.js +0 -48
- package/dist/core/claude-settings.js.map +0 -1
- package/dist/core/cloudflare-actions.d.ts +0 -90
- package/dist/core/cloudflare-actions.js +0 -178
- package/dist/core/cloudflare-actions.js.map +0 -1
- package/dist/core/cloudflare-auth.d.ts +0 -61
- package/dist/core/cloudflare-auth.js +0 -149
- package/dist/core/cloudflare-auth.js.map +0 -1
- package/dist/core/cloudflare-context.d.ts +0 -2
- package/dist/core/cloudflare-context.js +0 -106
- package/dist/core/cloudflare-context.js.map +0 -1
- package/dist/core/cloudflare-manager.d.ts +0 -258
- package/dist/core/cloudflare-manager.js +0 -414
- package/dist/core/cloudflare-manager.js.map +0 -1
- package/dist/core/cloudflare-provider.d.ts +0 -64
- package/dist/core/cloudflare-provider.js +0 -348
- package/dist/core/cloudflare-provider.js.map +0 -1
- package/dist/core/config-files.d.ts +0 -27
- package/dist/core/config-files.js +0 -154
- package/dist/core/config-files.js.map +0 -1
- package/dist/core/config-store.d.ts +0 -181
- package/dist/core/config-store.js +0 -1026
- package/dist/core/config-store.js.map +0 -1
- package/dist/core/context-library.d.ts +0 -53
- package/dist/core/context-library.js +0 -605
- package/dist/core/context-library.js.map +0 -1
- package/dist/core/context-types.d.ts +0 -83
- package/dist/core/context-types.js +0 -9
- package/dist/core/context-types.js.map +0 -1
- package/dist/core/daemon-client.d.ts +0 -84
- package/dist/core/daemon-client.js +0 -156
- package/dist/core/daemon-client.js.map +0 -1
- package/dist/core/daemon-lifecycle.d.ts +0 -59
- package/dist/core/daemon-lifecycle.js +0 -147
- package/dist/core/daemon-lifecycle.js.map +0 -1
- package/dist/core/db/catalog.d.ts +0 -57
- package/dist/core/db/catalog.js +0 -38
- package/dist/core/db/catalog.js.map +0 -1
- package/dist/core/db/data-masking.d.ts +0 -3
- package/dist/core/db/data-masking.js +0 -14
- package/dist/core/db/data-masking.js.map +0 -1
- package/dist/core/db/driver.d.ts +0 -151
- package/dist/core/db/driver.js +0 -209
- package/dist/core/db/driver.js.map +0 -1
- package/dist/core/db/export.d.ts +0 -17
- package/dist/core/db/export.js +0 -67
- package/dist/core/db/export.js.map +0 -1
- package/dist/core/db/mysql-driver.d.ts +0 -33
- package/dist/core/db/mysql-driver.js +0 -364
- package/dist/core/db/mysql-driver.js.map +0 -1
- package/dist/core/db/postgres-driver.d.ts +0 -34
- package/dist/core/db/postgres-driver.js +0 -430
- package/dist/core/db/postgres-driver.js.map +0 -1
- package/dist/core/db/sqlite-driver.d.ts +0 -30
- package/dist/core/db/sqlite-driver.js +0 -301
- package/dist/core/db/sqlite-driver.js.map +0 -1
- package/dist/core/db-peek.d.ts +0 -99
- package/dist/core/db-peek.js +0 -322
- package/dist/core/db-peek.js.map +0 -1
- package/dist/core/db-write.d.ts +0 -45
- package/dist/core/db-write.js +0 -190
- package/dist/core/db-write.js.map +0 -1
- package/dist/core/docker-inspect.d.ts +0 -34
- package/dist/core/docker-inspect.js +0 -108
- package/dist/core/docker-inspect.js.map +0 -1
- package/dist/core/docker-resources.d.ts +0 -28
- package/dist/core/docker-resources.js +0 -59
- package/dist/core/docker-resources.js.map +0 -1
- package/dist/core/docker-service-runner.d.ts +0 -21
- package/dist/core/docker-service-runner.js +0 -80
- package/dist/core/docker-service-runner.js.map +0 -1
- package/dist/core/docker-stats.d.ts +0 -24
- package/dist/core/docker-stats.js +0 -76
- package/dist/core/docker-stats.js.map +0 -1
- package/dist/core/docker.d.ts +0 -75
- package/dist/core/docker.js +0 -219
- package/dist/core/docker.js.map +0 -1
- package/dist/core/env-file.d.ts +0 -24
- package/dist/core/env-file.js +0 -123
- package/dist/core/env-file.js.map +0 -1
- package/dist/core/env-runtime.d.ts +0 -32
- package/dist/core/env-runtime.js +0 -42
- package/dist/core/env-runtime.js.map +0 -1
- package/dist/core/error-inbox.d.ts +0 -91
- package/dist/core/error-inbox.js +0 -292
- package/dist/core/error-inbox.js.map +0 -1
- package/dist/core/extensions.d.ts +0 -78
- package/dist/core/extensions.js +0 -41
- package/dist/core/extensions.js.map +0 -1
- package/dist/core/external-terminal.d.ts +0 -60
- package/dist/core/external-terminal.js +0 -429
- package/dist/core/external-terminal.js.map +0 -1
- package/dist/core/fix-loop.d.ts +0 -55
- package/dist/core/fix-loop.js +0 -73
- package/dist/core/fix-loop.js.map +0 -1
- package/dist/core/git-actions.d.ts +0 -69
- package/dist/core/git-actions.js +0 -161
- package/dist/core/git-actions.js.map +0 -1
- package/dist/core/git-graph-layout.d.ts +0 -34
- package/dist/core/git-graph-layout.js +0 -94
- package/dist/core/git-graph-layout.js.map +0 -1
- package/dist/core/git-identity.d.ts +0 -78
- package/dist/core/git-identity.js +0 -178
- package/dist/core/git-identity.js.map +0 -1
- package/dist/core/git-manager.d.ts +0 -129
- package/dist/core/git-manager.js +0 -509
- package/dist/core/git-manager.js.map +0 -1
- package/dist/core/git-worktrees.d.ts +0 -35
- package/dist/core/git-worktrees.js +0 -142
- package/dist/core/git-worktrees.js.map +0 -1
- package/dist/core/github-auth.d.ts +0 -28
- package/dist/core/github-auth.js +0 -134
- package/dist/core/github-auth.js.map +0 -1
- package/dist/core/github-context.d.ts +0 -12
- package/dist/core/github-context.js +0 -36
- package/dist/core/github-context.js.map +0 -1
- package/dist/core/github-manager.d.ts +0 -230
- package/dist/core/github-manager.js +0 -324
- package/dist/core/github-manager.js.map +0 -1
- package/dist/core/host-metrics.d.ts +0 -41
- package/dist/core/host-metrics.js +0 -93
- package/dist/core/host-metrics.js.map +0 -1
- package/dist/core/http-inspector.d.ts +0 -20
- package/dist/core/http-inspector.js +0 -106
- package/dist/core/http-inspector.js.map +0 -1
- package/dist/core/jetbrains-import.d.ts +0 -85
- package/dist/core/jetbrains-import.js +0 -599
- package/dist/core/jetbrains-import.js.map +0 -1
- package/dist/core/log-sources.d.ts +0 -21
- package/dist/core/log-sources.js +0 -219
- package/dist/core/log-sources.js.map +0 -1
- package/dist/core/log-store.d.ts +0 -33
- package/dist/core/log-store.js +0 -94
- package/dist/core/log-store.js.map +0 -1
- package/dist/core/log-volume.d.ts +0 -41
- package/dist/core/log-volume.js +0 -81
- package/dist/core/log-volume.js.map +0 -1
- package/dist/core/mcp-auth.d.ts +0 -27
- package/dist/core/mcp-auth.js +0 -90
- package/dist/core/mcp-auth.js.map +0 -1
- package/dist/core/metrics-store.d.ts +0 -74
- package/dist/core/metrics-store.js +0 -187
- package/dist/core/metrics-store.js.map +0 -1
- package/dist/core/one-time-skills.d.ts +0 -27
- package/dist/core/one-time-skills.js +0 -185
- package/dist/core/one-time-skills.js.map +0 -1
- package/dist/core/port-utils.d.ts +0 -23
- package/dist/core/port-utils.js +0 -83
- package/dist/core/port-utils.js.map +0 -1
- package/dist/core/process-manager.d.ts +0 -99
- package/dist/core/process-manager.js +0 -738
- package/dist/core/process-manager.js.map +0 -1
- package/dist/core/process-tree.d.ts +0 -17
- package/dist/core/process-tree.js +0 -64
- package/dist/core/process-tree.js.map +0 -1
- package/dist/core/project-overview.d.ts +0 -52
- package/dist/core/project-overview.js +0 -122
- package/dist/core/project-overview.js.map +0 -1
- package/dist/core/providers/api-base.d.ts +0 -24
- package/dist/core/providers/api-base.js +0 -44
- package/dist/core/providers/api-base.js.map +0 -1
- package/dist/core/providers/credentials.d.ts +0 -93
- package/dist/core/providers/credentials.js +0 -88
- package/dist/core/providers/credentials.js.map +0 -1
- package/dist/core/providers/deploy-provider.d.ts +0 -327
- package/dist/core/providers/deploy-provider.js +0 -25
- package/dist/core/providers/deploy-provider.js.map +0 -1
- package/dist/core/providers/egress.d.ts +0 -58
- package/dist/core/providers/egress.js +0 -124
- package/dist/core/providers/egress.js.map +0 -1
- package/dist/core/providers/host-bridge.d.ts +0 -20
- package/dist/core/providers/host-bridge.js +0 -57
- package/dist/core/providers/host-bridge.js.map +0 -1
- package/dist/core/providers/host-provider.d.ts +0 -160
- package/dist/core/providers/host-provider.js +0 -2
- package/dist/core/providers/host-provider.js.map +0 -1
- package/dist/core/providers/oauth.d.ts +0 -97
- package/dist/core/providers/oauth.js +0 -238
- package/dist/core/providers/oauth.js.map +0 -1
- package/dist/core/providers/project-resolution.d.ts +0 -81
- package/dist/core/providers/project-resolution.js +0 -101
- package/dist/core/providers/project-resolution.js.map +0 -1
- package/dist/core/providers/registry.d.ts +0 -73
- package/dist/core/providers/registry.js +0 -53
- package/dist/core/providers/registry.js.map +0 -1
- package/dist/core/providers/strings.d.ts +0 -95
- package/dist/core/providers/strings.js +0 -59
- package/dist/core/providers/strings.js.map +0 -1
- package/dist/core/public-config.d.ts +0 -18
- package/dist/core/public-config.js +0 -76
- package/dist/core/public-config.js.map +0 -1
- package/dist/core/read-only-files.d.ts +0 -28
- package/dist/core/read-only-files.js +0 -93
- package/dist/core/read-only-files.js.map +0 -1
- package/dist/core/repo-create.d.ts +0 -11
- package/dist/core/repo-create.js +0 -54
- package/dist/core/repo-create.js.map +0 -1
- package/dist/core/repo-match.d.ts +0 -12
- package/dist/core/repo-match.js +0 -40
- package/dist/core/repo-match.js.map +0 -1
- package/dist/core/repo-onboard.d.ts +0 -297
- package/dist/core/repo-onboard.js +0 -667
- package/dist/core/repo-onboard.js.map +0 -1
- package/dist/core/repro-bundle.d.ts +0 -30
- package/dist/core/repro-bundle.js +0 -116
- package/dist/core/repro-bundle.js.map +0 -1
- package/dist/core/service-graph.d.ts +0 -50
- package/dist/core/service-graph.js +0 -143
- package/dist/core/service-graph.js.map +0 -1
- package/dist/core/service-health.d.ts +0 -10
- package/dist/core/service-health.js +0 -46
- package/dist/core/service-health.js.map +0 -1
- package/dist/core/service-log-source.d.ts +0 -9
- package/dist/core/service-log-source.js +0 -49
- package/dist/core/service-log-source.js.map +0 -1
- package/dist/core/service-registry.d.ts +0 -52
- package/dist/core/service-registry.js +0 -101
- package/dist/core/service-registry.js.map +0 -1
- package/dist/core/snapshot-manager.d.ts +0 -62
- package/dist/core/snapshot-manager.js +0 -219
- package/dist/core/snapshot-manager.js.map +0 -1
- package/dist/core/ssh-servers.d.ts +0 -89
- package/dist/core/ssh-servers.js +0 -251
- package/dist/core/ssh-servers.js.map +0 -1
- package/dist/core/ssh-service-runner.d.ts +0 -7
- package/dist/core/ssh-service-runner.js +0 -36
- package/dist/core/ssh-service-runner.js.map +0 -1
- package/dist/core/ssh-setup.d.ts +0 -11
- package/dist/core/ssh-setup.js +0 -49
- package/dist/core/ssh-setup.js.map +0 -1
- package/dist/core/system-processes.d.ts +0 -29
- package/dist/core/system-processes.js +0 -119
- package/dist/core/system-processes.js.map +0 -1
- package/dist/core/terminal-manager.d.ts +0 -123
- package/dist/core/terminal-manager.js +0 -470
- package/dist/core/terminal-manager.js.map +0 -1
- package/dist/core/terminal-session.d.ts +0 -122
- package/dist/core/terminal-session.js +0 -242
- package/dist/core/terminal-session.js.map +0 -1
- package/dist/core/terminal-spawn.d.ts +0 -26
- package/dist/core/terminal-spawn.js +0 -63
- package/dist/core/terminal-spawn.js.map +0 -1
- package/dist/core/test-runner.d.ts +0 -69
- package/dist/core/test-runner.js +0 -199
- package/dist/core/test-runner.js.map +0 -1
- package/dist/core/timeline-store.d.ts +0 -20
- package/dist/core/timeline-store.js +0 -36
- package/dist/core/timeline-store.js.map +0 -1
- package/dist/core/tool-call-store.d.ts +0 -25
- package/dist/core/tool-call-store.js +0 -62
- package/dist/core/tool-call-store.js.map +0 -1
- package/dist/core/types.d.ts +0 -312
- package/dist/core/types.js +0 -2
- package/dist/core/types.js.map +0 -1
- package/dist/core/usage-history.d.ts +0 -81
- package/dist/core/usage-history.js +0 -149
- package/dist/core/usage-history.js.map +0 -1
- package/dist/core/vercel-actions.d.ts +0 -71
- package/dist/core/vercel-actions.js +0 -109
- package/dist/core/vercel-actions.js.map +0 -1
- package/dist/core/vercel-auth.d.ts +0 -40
- package/dist/core/vercel-auth.js +0 -88
- package/dist/core/vercel-auth.js.map +0 -1
- package/dist/core/vercel-context.d.ts +0 -2
- package/dist/core/vercel-context.js +0 -97
- package/dist/core/vercel-context.js.map +0 -1
- package/dist/core/vercel-manager.d.ts +0 -268
- package/dist/core/vercel-manager.js +0 -401
- package/dist/core/vercel-manager.js.map +0 -1
- package/dist/core/vercel-oauth.d.ts +0 -37
- package/dist/core/vercel-oauth.js +0 -57
- package/dist/core/vercel-oauth.js.map +0 -1
- package/dist/core/vercel-provider.d.ts +0 -23
- package/dist/core/vercel-provider.js +0 -276
- package/dist/core/vercel-provider.js.map +0 -1
- package/dist/core/vultr-actions.d.ts +0 -52
- package/dist/core/vultr-actions.js +0 -62
- package/dist/core/vultr-actions.js.map +0 -1
- package/dist/core/vultr-auth.d.ts +0 -32
- package/dist/core/vultr-auth.js +0 -54
- package/dist/core/vultr-auth.js.map +0 -1
- package/dist/core/vultr-context.d.ts +0 -2
- package/dist/core/vultr-context.js +0 -55
- package/dist/core/vultr-context.js.map +0 -1
- package/dist/core/vultr-manager.d.ts +0 -113
- package/dist/core/vultr-manager.js +0 -170
- package/dist/core/vultr-manager.js.map +0 -1
- package/dist/core/vultr-provider.d.ts +0 -69
- package/dist/core/vultr-provider.js +0 -226
- package/dist/core/vultr-provider.js.map +0 -1
- package/dist/core/workflow-triggers.d.ts +0 -139
- package/dist/core/workflow-triggers.js +0 -208
- package/dist/core/workflow-triggers.js.map +0 -1
- package/dist/core/workflows.d.ts +0 -290
- package/dist/core/workflows.js +0 -190
- package/dist/core/workflows.js.map +0 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.js +0 -66
- package/dist/index.js.map +0 -1
- package/dist/mcp/server.d.ts +0 -37
- package/dist/mcp/server.js +0 -84
- package/dist/mcp/server.js.map +0 -1
- package/dist/mcp/tools/agent-env.d.ts +0 -9
- package/dist/mcp/tools/agent-env.js +0 -160
- package/dist/mcp/tools/agent-env.js.map +0 -1
- package/dist/mcp/tools/agent-profiles.d.ts +0 -9
- package/dist/mcp/tools/agent-profiles.js +0 -197
- package/dist/mcp/tools/agent-profiles.js.map +0 -1
- package/dist/mcp/tools/agent-registry.d.ts +0 -9
- package/dist/mcp/tools/agent-registry.js +0 -81
- package/dist/mcp/tools/agent-registry.js.map +0 -1
- package/dist/mcp/tools/agent.d.ts +0 -4
- package/dist/mcp/tools/agent.js +0 -29
- package/dist/mcp/tools/agent.js.map +0 -1
- package/dist/mcp/tools/context.d.ts +0 -36
- package/dist/mcp/tools/context.js +0 -69
- package/dist/mcp/tools/context.js.map +0 -1
- package/dist/mcp/tools/database.d.ts +0 -9
- package/dist/mcp/tools/database.js +0 -166
- package/dist/mcp/tools/database.js.map +0 -1
- package/dist/mcp/tools/docs.d.ts +0 -29
- package/dist/mcp/tools/docs.js +0 -134
- package/dist/mcp/tools/docs.js.map +0 -1
- package/dist/mcp/tools/errors.d.ts +0 -12
- package/dist/mcp/tools/errors.js +0 -47
- package/dist/mcp/tools/errors.js.map +0 -1
- package/dist/mcp/tools/git.d.ts +0 -4
- package/dist/mcp/tools/git.js +0 -209
- package/dist/mcp/tools/git.js.map +0 -1
- package/dist/mcp/tools/github.d.ts +0 -4
- package/dist/mcp/tools/github.js +0 -196
- package/dist/mcp/tools/github.js.map +0 -1
- package/dist/mcp/tools/index.d.ts +0 -36
- package/dist/mcp/tools/index.js +0 -61
- package/dist/mcp/tools/index.js.map +0 -1
- package/dist/mcp/tools/onboard.d.ts +0 -10
- package/dist/mcp/tools/onboard.js +0 -30
- package/dist/mcp/tools/onboard.js.map +0 -1
- package/dist/mcp/tools/provider.d.ts +0 -16
- package/dist/mcp/tools/provider.js +0 -110
- package/dist/mcp/tools/provider.js.map +0 -1
- package/dist/mcp/tools/services.d.ts +0 -13
- package/dist/mcp/tools/services.js +0 -204
- package/dist/mcp/tools/services.js.map +0 -1
- package/dist/mcp/tools/snapshots.d.ts +0 -8
- package/dist/mcp/tools/snapshots.js +0 -37
- package/dist/mcp/tools/snapshots.js.map +0 -1
- package/dist/mcp/tools/terminal.d.ts +0 -4
- package/dist/mcp/tools/terminal.js +0 -38
- package/dist/mcp/tools/terminal.js.map +0 -1
- package/dist/tui/app.d.ts +0 -22
- package/dist/tui/app.js +0 -138
- package/dist/tui/app.js.map +0 -1
- package/dist/web/agent-info.d.ts +0 -82
- package/dist/web/agent-info.js +0 -775
- package/dist/web/agent-info.js.map +0 -1
- package/dist/web/client/assets/SymbolsNerdFontMono-Regular-DDncdh2F.ttf +0 -0
- package/dist/web/client/assets/code-editor-TE0sjFGO.js +0 -30
- package/dist/web/client/assets/context-graph-B9MnBpp6.js +0 -7
- package/dist/web/client/assets/core-DhEqZVGG.js +0 -1
- package/dist/web/client/assets/event-BK_86lmQ.js +0 -1
- package/dist/web/client/assets/index-BhDAhmA1.js +0 -1
- package/dist/web/client/assets/index-CSo__8A6.css +0 -1
- package/dist/web/client/assets/index-DAJvBqn9.js +0 -352
- package/dist/web/client/assets/nomoreide-favicon-Ds7Tgj9p.svg +0 -24
- package/dist/web/client/assets/system-process-table-DetWu0Gj.js +0 -1
- package/dist/web/client/assets/window-DlR023_X.js +0 -1
- package/dist/web/client/index.html +0 -44
- package/dist/web/dashboard.d.ts +0 -61
- package/dist/web/dashboard.js +0 -221
- package/dist/web/dashboard.js.map +0 -1
- package/dist/web/directories.d.ts +0 -27
- package/dist/web/directories.js +0 -81
- package/dist/web/directories.js.map +0 -1
- package/dist/web/http-utils.d.ts +0 -13
- package/dist/web/http-utils.js +0 -72
- package/dist/web/http-utils.js.map +0 -1
- package/dist/web/routes/agent-chat-routes.d.ts +0 -3
- package/dist/web/routes/agent-chat-routes.js +0 -186
- package/dist/web/routes/agent-chat-routes.js.map +0 -1
- package/dist/web/routes/agent-env-routes.d.ts +0 -9
- package/dist/web/routes/agent-env-routes.js +0 -86
- package/dist/web/routes/agent-env-routes.js.map +0 -1
- package/dist/web/routes/agent-profile-routes.d.ts +0 -8
- package/dist/web/routes/agent-profile-routes.js +0 -211
- package/dist/web/routes/agent-profile-routes.js.map +0 -1
- package/dist/web/routes/agent-registry-routes.d.ts +0 -2
- package/dist/web/routes/agent-registry-routes.js +0 -375
- package/dist/web/routes/agent-registry-routes.js.map +0 -1
- package/dist/web/routes/agent-routes.d.ts +0 -3
- package/dist/web/routes/agent-routes.js +0 -73
- package/dist/web/routes/agent-routes.js.map +0 -1
- package/dist/web/routes/agent-settings-routes.d.ts +0 -8
- package/dist/web/routes/agent-settings-routes.js +0 -67
- package/dist/web/routes/agent-settings-routes.js.map +0 -1
- package/dist/web/routes/context-library-routes.d.ts +0 -2
- package/dist/web/routes/context-library-routes.js +0 -139
- package/dist/web/routes/context-library-routes.js.map +0 -1
- package/dist/web/routes/context.d.ts +0 -73
- package/dist/web/routes/context.js +0 -48
- package/dist/web/routes/context.js.map +0 -1
- package/dist/web/routes/dashboard-routes.d.ts +0 -3
- package/dist/web/routes/dashboard-routes.js +0 -47
- package/dist/web/routes/dashboard-routes.js.map +0 -1
- package/dist/web/routes/database-routes.d.ts +0 -3
- package/dist/web/routes/database-routes.js +0 -341
- package/dist/web/routes/database-routes.js.map +0 -1
- package/dist/web/routes/docker-routes.d.ts +0 -7
- package/dist/web/routes/docker-routes.js +0 -122
- package/dist/web/routes/docker-routes.js.map +0 -1
- package/dist/web/routes/errors-routes.d.ts +0 -3
- package/dist/web/routes/errors-routes.js +0 -77
- package/dist/web/routes/errors-routes.js.map +0 -1
- package/dist/web/routes/extensions-routes.d.ts +0 -14
- package/dist/web/routes/extensions-routes.js +0 -21
- package/dist/web/routes/extensions-routes.js.map +0 -1
- package/dist/web/routes/git-routes.d.ts +0 -3
- package/dist/web/routes/git-routes.js +0 -598
- package/dist/web/routes/git-routes.js.map +0 -1
- package/dist/web/routes/github-context.d.ts +0 -11
- package/dist/web/routes/github-context.js +0 -34
- package/dist/web/routes/github-context.js.map +0 -1
- package/dist/web/routes/github-routes.d.ts +0 -2
- package/dist/web/routes/github-routes.js +0 -699
- package/dist/web/routes/github-routes.js.map +0 -1
- package/dist/web/routes/host-routes.d.ts +0 -2
- package/dist/web/routes/host-routes.js +0 -188
- package/dist/web/routes/host-routes.js.map +0 -1
- package/dist/web/routes/index.d.ts +0 -10
- package/dist/web/routes/index.js +0 -72
- package/dist/web/routes/index.js.map +0 -1
- package/dist/web/routes/jetbrains-import-routes.d.ts +0 -2
- package/dist/web/routes/jetbrains-import-routes.js +0 -121
- package/dist/web/routes/jetbrains-import-routes.js.map +0 -1
- package/dist/web/routes/log-sources-routes.d.ts +0 -6
- package/dist/web/routes/log-sources-routes.js +0 -102
- package/dist/web/routes/log-sources-routes.js.map +0 -1
- package/dist/web/routes/metrics-routes.d.ts +0 -3
- package/dist/web/routes/metrics-routes.js +0 -60
- package/dist/web/routes/metrics-routes.js.map +0 -1
- package/dist/web/routes/onboard-routes.d.ts +0 -9
- package/dist/web/routes/onboard-routes.js +0 -146
- package/dist/web/routes/onboard-routes.js.map +0 -1
- package/dist/web/routes/overview-routes.d.ts +0 -2
- package/dist/web/routes/overview-routes.js +0 -36
- package/dist/web/routes/overview-routes.js.map +0 -1
- package/dist/web/routes/provider-routes.d.ts +0 -2
- package/dist/web/routes/provider-routes.js +0 -558
- package/dist/web/routes/provider-routes.js.map +0 -1
- package/dist/web/routes/service-routes.d.ts +0 -3
- package/dist/web/routes/service-routes.js +0 -511
- package/dist/web/routes/service-routes.js.map +0 -1
- package/dist/web/routes/settings-routes.d.ts +0 -2
- package/dist/web/routes/settings-routes.js +0 -151
- package/dist/web/routes/settings-routes.js.map +0 -1
- package/dist/web/routes/shell-routes.d.ts +0 -22
- package/dist/web/routes/shell-routes.js +0 -75
- package/dist/web/routes/shell-routes.js.map +0 -1
- package/dist/web/routes/skills-routes.d.ts +0 -2
- package/dist/web/routes/skills-routes.js +0 -49
- package/dist/web/routes/skills-routes.js.map +0 -1
- package/dist/web/routes/snapshot-routes.d.ts +0 -8
- package/dist/web/routes/snapshot-routes.js +0 -194
- package/dist/web/routes/snapshot-routes.js.map +0 -1
- package/dist/web/routes/ssh-server-routes.d.ts +0 -10
- package/dist/web/routes/ssh-server-routes.js +0 -163
- package/dist/web/routes/ssh-server-routes.js.map +0 -1
- package/dist/web/routes/terminal-routes.d.ts +0 -7
- package/dist/web/routes/terminal-routes.js +0 -313
- package/dist/web/routes/terminal-routes.js.map +0 -1
- package/dist/web/routes/workflow-routes.d.ts +0 -8
- package/dist/web/routes/workflow-routes.js +0 -45
- package/dist/web/routes/workflow-routes.js.map +0 -1
- package/dist/web/routes/workflow-trigger-routes.d.ts +0 -9
- package/dist/web/routes/workflow-trigger-routes.js +0 -78
- package/dist/web/routes/workflow-trigger-routes.js.map +0 -1
- package/dist/web/server.d.ts +0 -31
- package/dist/web/server.js +0 -325
- package/dist/web/server.js.map +0 -1
- package/dist/web/service-tester.d.ts +0 -16
- package/dist/web/service-tester.js +0 -107
- package/dist/web/service-tester.js.map +0 -1
- package/dist/web/static-assets.d.ts +0 -9
- package/dist/web/static-assets.js +0 -77
- package/dist/web/static-assets.js.map +0 -1
- package/dist/web/usage-info.d.ts +0 -56
- package/dist/web/usage-info.js +0 -265
- package/dist/web/usage-info.js.map +0 -1
|
@@ -1,1026 +0,0 @@
|
|
|
1
|
-
import { randomUUID } from "node:crypto";
|
|
2
|
-
import { execFile } from "node:child_process";
|
|
3
|
-
import { mkdir, open, realpath, readFile, rename, stat, unlink, writeFile, } from "node:fs/promises";
|
|
4
|
-
import { homedir } from "node:os";
|
|
5
|
-
import { basename, dirname, isAbsolute, join } from "node:path";
|
|
6
|
-
import { promisify } from "node:util";
|
|
7
|
-
import { z } from "zod";
|
|
8
|
-
import { workflowSchema } from "./workflows.js";
|
|
9
|
-
import { workflowTriggerSchema } from "./workflow-triggers.js";
|
|
10
|
-
import { GitWorktreeManager } from "./git-worktrees.js";
|
|
11
|
-
const execFileAsync = promisify(execFile);
|
|
12
|
-
const ENV_KEY_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
13
|
-
const CONFIG_LOCK_WAIT_MS = 5_000;
|
|
14
|
-
const CONFIG_LOCK_STALE_MS = 30_000;
|
|
15
|
-
const CONFIG_LOCK_RETRY_MIN_MS = 10;
|
|
16
|
-
const CONFIG_LOCK_RETRY_MAX_MS = 50;
|
|
17
|
-
const baseServiceSchema = z.object({
|
|
18
|
-
name: z.string().min(1),
|
|
19
|
-
port: z.number().int().positive().max(65535).optional(),
|
|
20
|
-
description: z.string().optional(),
|
|
21
|
-
/** Command used by the Test Runner; defaults to `npm test` when absent. */
|
|
22
|
-
test: z.string().min(1).optional(),
|
|
23
|
-
/** Services that must be running/healthy before this one (bundle start order). */
|
|
24
|
-
dependsOn: z.array(z.string().min(1)).optional(),
|
|
25
|
-
/**
|
|
26
|
-
* Explicit project assignment, overriding the cwd-containment inference.
|
|
27
|
-
* Needed because a remote service's `cwd` is a path on another machine
|
|
28
|
-
* (`/var/www/...`, `/root`) and can never sit under a local repo root, so
|
|
29
|
-
* inference alone leaves those services in no project at all.
|
|
30
|
-
*/
|
|
31
|
-
projectPath: z.string().min(1).optional(),
|
|
32
|
-
});
|
|
33
|
-
const serviceEnvSchema = z
|
|
34
|
-
.record(z.string())
|
|
35
|
-
.refine((env) => Object.keys(env).every((key) => ENV_KEY_PATTERN.test(key)), {
|
|
36
|
-
message: "Environment variable names must use letters, numbers, and underscores.",
|
|
37
|
-
});
|
|
38
|
-
const localServiceSchema = baseServiceSchema.extend({
|
|
39
|
-
kind: z.literal("local").optional(),
|
|
40
|
-
command: z.string().min(1),
|
|
41
|
-
args: z.array(z.string().refine((value) => !value.includes("\0"))).optional(),
|
|
42
|
-
cwd: z.string().min(1),
|
|
43
|
-
env: serviceEnvSchema.optional(),
|
|
44
|
-
});
|
|
45
|
-
const dockerServiceSchema = baseServiceSchema.extend({
|
|
46
|
-
kind: z.literal("docker-compose"),
|
|
47
|
-
cwd: z.string().min(1),
|
|
48
|
-
composeFile: z.string().min(1).optional(),
|
|
49
|
-
composeService: z.string().min(1),
|
|
50
|
-
});
|
|
51
|
-
const sshServiceSchema = baseServiceSchema.extend({
|
|
52
|
-
kind: z.literal("ssh"),
|
|
53
|
-
host: z.string().min(1),
|
|
54
|
-
cwd: z.string().min(1),
|
|
55
|
-
command: z
|
|
56
|
-
.string()
|
|
57
|
-
.min(1)
|
|
58
|
-
.refine((value) => !value.includes("\0"), {
|
|
59
|
-
message: "SSH command contains invalid null byte.",
|
|
60
|
-
}),
|
|
61
|
-
env: serviceEnvSchema.optional(),
|
|
62
|
-
});
|
|
63
|
-
const serviceSchema = z.union([
|
|
64
|
-
localServiceSchema,
|
|
65
|
-
dockerServiceSchema,
|
|
66
|
-
sshServiceSchema,
|
|
67
|
-
]);
|
|
68
|
-
const bundleSchema = z.object({
|
|
69
|
-
name: z.string().min(1),
|
|
70
|
-
services: z.array(z.string().min(1)),
|
|
71
|
-
});
|
|
72
|
-
const githubCredentialSchema = z.discriminatedUnion("source", [
|
|
73
|
-
z.object({
|
|
74
|
-
source: z.literal("gh"),
|
|
75
|
-
host: z.string().min(1),
|
|
76
|
-
login: z.string().min(1),
|
|
77
|
-
}),
|
|
78
|
-
z.object({
|
|
79
|
-
source: z.literal("stored"),
|
|
80
|
-
host: z.string().min(1),
|
|
81
|
-
}),
|
|
82
|
-
]);
|
|
83
|
-
const gitRepositorySchema = z.object({
|
|
84
|
-
name: z.string().min(1),
|
|
85
|
-
path: z.string().min(1),
|
|
86
|
-
activeWorktreePath: z.string().min(1).optional(),
|
|
87
|
-
githubCredential: githubCredentialSchema.optional(),
|
|
88
|
-
/** Pinned deploy-provider project per provider id; see `providerProjects`. */
|
|
89
|
-
providerProjects: z.record(z.string(), z.string().min(1)).optional(),
|
|
90
|
-
});
|
|
91
|
-
/** Upper bound on board-pinned repos, mirroring the web UI's 5-column cap. */
|
|
92
|
-
const MAX_BOARD_REPOSITORIES = 5;
|
|
93
|
-
const databaseSchema = z.object({
|
|
94
|
-
name: z.string().min(1),
|
|
95
|
-
engine: z.enum(["postgres", "mysql", "sqlite"]),
|
|
96
|
-
url: z.string().min(1),
|
|
97
|
-
writeUnlocked: z.boolean().optional(),
|
|
98
|
-
projectPath: z.string().min(1).optional(),
|
|
99
|
-
});
|
|
100
|
-
const logSourceSchema = z
|
|
101
|
-
.object({
|
|
102
|
-
name: z.string().min(1),
|
|
103
|
-
kind: z.enum(["file", "ssh", "command"]),
|
|
104
|
-
path: z.string().min(1).optional(),
|
|
105
|
-
host: z.string().min(1).optional(),
|
|
106
|
-
command: z.string().min(1).optional(),
|
|
107
|
-
cwd: z.string().min(1).optional(),
|
|
108
|
-
driver: z.enum(["journald", "docker"]).optional(),
|
|
109
|
-
unit: z.string().min(1).optional(),
|
|
110
|
-
container: z.string().min(1).optional(),
|
|
111
|
-
})
|
|
112
|
-
.superRefine((source, ctx) => {
|
|
113
|
-
if (source.driver === "journald") {
|
|
114
|
-
if (!source.unit) {
|
|
115
|
-
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "journald log source requires a unit." });
|
|
116
|
-
}
|
|
117
|
-
return; // driver sources build their own query; kind-based paths don't apply.
|
|
118
|
-
}
|
|
119
|
-
if (source.driver === "docker") {
|
|
120
|
-
if (!source.container) {
|
|
121
|
-
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "docker log source requires a container." });
|
|
122
|
-
}
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
if (source.kind === "file" && !source.path) {
|
|
126
|
-
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "File log source requires a path." });
|
|
127
|
-
}
|
|
128
|
-
if (source.kind === "ssh" && (!source.host || !source.path)) {
|
|
129
|
-
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "SSH log source requires host and path." });
|
|
130
|
-
}
|
|
131
|
-
if (source.kind === "command" && !source.command) {
|
|
132
|
-
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "Command log source requires a command." });
|
|
133
|
-
}
|
|
134
|
-
});
|
|
135
|
-
const sshHostPattern = /^[A-Za-z0-9][A-Za-z0-9._:@-]*$/;
|
|
136
|
-
const sshServerSchema = z.object({
|
|
137
|
-
host: z
|
|
138
|
-
.string()
|
|
139
|
-
.trim()
|
|
140
|
-
.min(1)
|
|
141
|
-
.max(255)
|
|
142
|
-
.regex(sshHostPattern, "SSH host must be a host name or ~/.ssh/config alias."),
|
|
143
|
-
name: z.string().trim().min(1).max(80).optional(),
|
|
144
|
-
environment: z.string().trim().min(1).max(40).optional(),
|
|
145
|
-
});
|
|
146
|
-
const githubTokenSchema = z.object({
|
|
147
|
-
host: z.string().min(1),
|
|
148
|
-
token: z.string().min(1),
|
|
149
|
-
/**
|
|
150
|
-
* Who the token belongs to, captured once at connect time. Optional because
|
|
151
|
-
* tokens stored before this existed stay valid — the GitHub status route
|
|
152
|
-
* backfills them on the next check.
|
|
153
|
-
*/
|
|
154
|
-
login: z.string().min(1).optional(),
|
|
155
|
-
avatarUrl: z.string().url().optional(),
|
|
156
|
-
});
|
|
157
|
-
/**
|
|
158
|
-
* Commit identity for a GitHub account, cached so committing does not spend an
|
|
159
|
-
* API call resolving a name and address that effectively never change.
|
|
160
|
-
*/
|
|
161
|
-
const githubIdentitySchema = z.object({
|
|
162
|
-
host: z.string().min(1),
|
|
163
|
-
login: z.string().min(1),
|
|
164
|
-
name: z.string().min(1),
|
|
165
|
-
email: z.string().min(1),
|
|
166
|
-
});
|
|
167
|
-
/**
|
|
168
|
-
* A provider connection. A `cli` connection stores no token — it is re-read
|
|
169
|
-
* from the vendor CLI's auth file per request — so `token` is set only for
|
|
170
|
-
* `stored` (the pasted token) and `oauth` (the current access token, alongside
|
|
171
|
-
* the refresh token that renews it).
|
|
172
|
-
*/
|
|
173
|
-
const providerConnectionSchema = z.object({
|
|
174
|
-
source: z.enum(["cli", "stored", "oauth"]),
|
|
175
|
-
token: z.string().min(1).optional(),
|
|
176
|
-
refreshToken: z.string().min(1).optional(),
|
|
177
|
-
expiresAt: z.number().int().positive().optional(),
|
|
178
|
-
clientId: z.string().min(1).optional(),
|
|
179
|
-
scopeId: z.string().min(1).optional(),
|
|
180
|
-
scopeSlug: z.string().min(1).optional(),
|
|
181
|
-
username: z.string().min(1).optional(),
|
|
182
|
-
});
|
|
183
|
-
/** Provider ids key `connections` and `providerProjects`; keep them file-safe. */
|
|
184
|
-
const providerIdSchema = z.string().trim().min(1).max(64).regex(/^[a-z0-9][a-z0-9-]*$/, {
|
|
185
|
-
message: "a provider id must be lowercase alphanumeric or dashes",
|
|
186
|
-
});
|
|
187
|
-
/**
|
|
188
|
-
* Display name for a provider id in user-facing errors. ConfigStore has no
|
|
189
|
-
* access to provider manifests, so it title-cases the id — which is exactly
|
|
190
|
-
* right for `vercel`, `cloudflare`, and `vultr`. A provider whose name needs
|
|
191
|
-
* more than that should surface its own message at the route layer.
|
|
192
|
-
*/
|
|
193
|
-
function providerLabel(providerId) {
|
|
194
|
-
return providerId.charAt(0).toUpperCase() + providerId.slice(1);
|
|
195
|
-
}
|
|
196
|
-
export const projectPreferencesSchema = z
|
|
197
|
-
.object({
|
|
198
|
-
logs: z
|
|
199
|
-
.object({
|
|
200
|
-
showTimestamps: z.boolean(),
|
|
201
|
-
wrapLines: z.boolean(),
|
|
202
|
-
})
|
|
203
|
-
.strict(),
|
|
204
|
-
database: z
|
|
205
|
-
.object({
|
|
206
|
-
confirmWrites: z.boolean(),
|
|
207
|
-
resultLimit: z.number().int().min(10).max(5_000),
|
|
208
|
-
})
|
|
209
|
-
.strict(),
|
|
210
|
-
})
|
|
211
|
-
.strict();
|
|
212
|
-
export const projectPreferencesPatchSchema = z
|
|
213
|
-
.object({
|
|
214
|
-
logs: z
|
|
215
|
-
.object({
|
|
216
|
-
showTimestamps: z.boolean().optional(),
|
|
217
|
-
wrapLines: z.boolean().optional(),
|
|
218
|
-
})
|
|
219
|
-
.strict()
|
|
220
|
-
.optional(),
|
|
221
|
-
database: z
|
|
222
|
-
.object({
|
|
223
|
-
confirmWrites: z.boolean().optional(),
|
|
224
|
-
resultLimit: z.number().int().min(10).max(5_000).optional(),
|
|
225
|
-
})
|
|
226
|
-
.strict()
|
|
227
|
-
.optional(),
|
|
228
|
-
})
|
|
229
|
-
.strict();
|
|
230
|
-
export const DEFAULT_PROJECT_PREFERENCES = Object.freeze({
|
|
231
|
-
logs: Object.freeze({ showTimestamps: true, wrapLines: true }),
|
|
232
|
-
database: Object.freeze({ confirmWrites: true, resultLimit: 100 }),
|
|
233
|
-
});
|
|
234
|
-
/**
|
|
235
|
-
* Provider identity as it was stored before connections were keyed by provider.
|
|
236
|
-
* Both legacy shapes below are Vercel's, because it was the only provider.
|
|
237
|
-
*/
|
|
238
|
-
const LEGACY_PROVIDER_ID = "vercel";
|
|
239
|
-
/**
|
|
240
|
-
* Lift the pre-registry Vercel fields into their provider-keyed homes:
|
|
241
|
-
*
|
|
242
|
-
* config.vercel → config.connections.vercel
|
|
243
|
-
* connection.teamId / .teamSlug → .scopeId / .scopeSlug
|
|
244
|
-
* repository.vercelProjectId → repository.providerProjects.vercel
|
|
245
|
-
*
|
|
246
|
-
* Runs as a parse-time preprocess rather than a one-shot upgrade script so that
|
|
247
|
-
* a config written by an older build is readable on every load, not just the
|
|
248
|
-
* first one after upgrading. `configSchema` is non-strict, so the legacy keys
|
|
249
|
-
* are dropped on the next write with no further action.
|
|
250
|
-
*
|
|
251
|
-
* Existing provider-keyed values win: if both shapes are somehow present, the
|
|
252
|
-
* new one is authoritative and the legacy key is simply discarded.
|
|
253
|
-
*/
|
|
254
|
-
function migrateLegacyProviderFields(input) {
|
|
255
|
-
if (!isRecord(input))
|
|
256
|
-
return input;
|
|
257
|
-
const config = { ...input };
|
|
258
|
-
const legacy = config[LEGACY_PROVIDER_ID];
|
|
259
|
-
if (isRecord(legacy)) {
|
|
260
|
-
const { teamId, teamSlug, ...rest } = legacy;
|
|
261
|
-
const existing = isRecord(config.connections) ? config.connections : {};
|
|
262
|
-
config.connections = {
|
|
263
|
-
[LEGACY_PROVIDER_ID]: {
|
|
264
|
-
...rest,
|
|
265
|
-
...(teamId === undefined ? {} : { scopeId: teamId }),
|
|
266
|
-
...(teamSlug === undefined ? {} : { scopeSlug: teamSlug }),
|
|
267
|
-
},
|
|
268
|
-
...existing,
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
if (Array.isArray(config.gitRepositories)) {
|
|
272
|
-
config.gitRepositories = config.gitRepositories.map((entry) => {
|
|
273
|
-
if (!isRecord(entry) || entry.vercelProjectId === undefined)
|
|
274
|
-
return entry;
|
|
275
|
-
const { vercelProjectId, ...rest } = entry;
|
|
276
|
-
const existing = isRecord(entry.providerProjects) ? entry.providerProjects : {};
|
|
277
|
-
return {
|
|
278
|
-
...rest,
|
|
279
|
-
providerProjects: { [LEGACY_PROVIDER_ID]: vercelProjectId, ...existing },
|
|
280
|
-
};
|
|
281
|
-
});
|
|
282
|
-
}
|
|
283
|
-
return config;
|
|
284
|
-
}
|
|
285
|
-
function isRecord(value) {
|
|
286
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
287
|
-
}
|
|
288
|
-
const configShape = z.object({
|
|
289
|
-
version: z.literal(1),
|
|
290
|
-
services: z.array(serviceSchema),
|
|
291
|
-
bundles: z.array(bundleSchema),
|
|
292
|
-
gitRepositories: z.array(gitRepositorySchema).default([]),
|
|
293
|
-
selectedGitRepository: z.string().min(1).optional(),
|
|
294
|
-
/**
|
|
295
|
-
* Ordered names of repositories pinned to the multi-repo board. Undefined
|
|
296
|
-
* means "never curated" → the board shows every registered repo; an empty
|
|
297
|
-
* array means the user has explicitly cleared the board.
|
|
298
|
-
*/
|
|
299
|
-
gitBoardRepositories: z.array(z.string().min(1)).optional(),
|
|
300
|
-
databases: z.array(databaseSchema).default([]),
|
|
301
|
-
logSources: z.array(logSourceSchema).default([]),
|
|
302
|
-
sshServers: z.array(sshServerSchema).default([]),
|
|
303
|
-
githubTokens: z.array(githubTokenSchema).default([]),
|
|
304
|
-
githubIdentities: z.array(githubIdentitySchema).default([]),
|
|
305
|
-
/**
|
|
306
|
-
* How each provider authenticates, keyed by provider id. A missing entry
|
|
307
|
-
* means that provider is not connected.
|
|
308
|
-
*/
|
|
309
|
-
connections: z.record(providerIdSchema, providerConnectionSchema).default({}),
|
|
310
|
-
workflows: z.array(workflowSchema).default([]),
|
|
311
|
-
/** Event→workflow bindings that auto-fire workflows (IDEAS #16). */
|
|
312
|
-
workflowTriggers: z.array(workflowTriggerSchema).default([]),
|
|
313
|
-
/**
|
|
314
|
-
* Which CLI the in-dock agent chat drives. Undefined = "never chosen" → fall
|
|
315
|
-
* back to startup-agent detection. Set explicitly when the user picks/switches
|
|
316
|
-
* providers, so the choice sticks across CLI/web/desktop.
|
|
317
|
-
*/
|
|
318
|
-
chatProvider: z.enum(["claude", "codex"]).optional(),
|
|
319
|
-
/**
|
|
320
|
-
* Model each agent CLI is pinned to, keyed by provider. A missing entry means
|
|
321
|
-
* "let the CLI pick", which is why this is a partial map rather than a pair of
|
|
322
|
-
* defaulted fields — there is no model name that safely stands in for "the
|
|
323
|
-
* provider's own default".
|
|
324
|
-
*/
|
|
325
|
-
chatModels: z
|
|
326
|
-
.object({
|
|
327
|
-
claude: z.string().trim().min(1).max(64).optional(),
|
|
328
|
-
codex: z.string().trim().min(1).max(64).optional(),
|
|
329
|
-
})
|
|
330
|
-
.optional(),
|
|
331
|
-
preferences: projectPreferencesSchema.optional(),
|
|
332
|
-
});
|
|
333
|
-
const configSchema = z.preprocess(migrateLegacyProviderFields, configShape);
|
|
334
|
-
const defaultConfig = {
|
|
335
|
-
version: 1,
|
|
336
|
-
services: [],
|
|
337
|
-
bundles: [],
|
|
338
|
-
gitRepositories: [],
|
|
339
|
-
databases: [],
|
|
340
|
-
logSources: [],
|
|
341
|
-
sshServers: [],
|
|
342
|
-
githubTokens: [],
|
|
343
|
-
githubIdentities: [],
|
|
344
|
-
connections: {},
|
|
345
|
-
workflows: [],
|
|
346
|
-
workflowTriggers: [],
|
|
347
|
-
};
|
|
348
|
-
export function defaultGlobalConfigPath() {
|
|
349
|
-
const base = process.env.XDG_CONFIG_HOME?.trim();
|
|
350
|
-
const root = base && base.length > 0 ? base : join(homedir(), ".config");
|
|
351
|
-
return join(root, "nomoreide", "config.json");
|
|
352
|
-
}
|
|
353
|
-
export class ConfigStore {
|
|
354
|
-
configPath;
|
|
355
|
-
mutationQueue = Promise.resolve();
|
|
356
|
-
constructor(configPath = defaultGlobalConfigPath()) {
|
|
357
|
-
this.configPath = configPath;
|
|
358
|
-
}
|
|
359
|
-
async load() {
|
|
360
|
-
return this.loadUnlocked();
|
|
361
|
-
}
|
|
362
|
-
async loadUnlocked() {
|
|
363
|
-
try {
|
|
364
|
-
const raw = await readFile(this.configPath, "utf8");
|
|
365
|
-
return configSchema.parse(JSON.parse(raw));
|
|
366
|
-
}
|
|
367
|
-
catch (error) {
|
|
368
|
-
if (isMissingFileError(error)) {
|
|
369
|
-
return structuredClone(defaultConfig);
|
|
370
|
-
}
|
|
371
|
-
throw error;
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
async save(config) {
|
|
375
|
-
await this.enqueueMutation(() => this.withConfigLock(() => this.persistUnlocked(config)));
|
|
376
|
-
}
|
|
377
|
-
async persistUnlocked(config) {
|
|
378
|
-
const parsed = configSchema.parse(config);
|
|
379
|
-
const parentDirectory = dirname(this.configPath);
|
|
380
|
-
const temporaryPath = join(parentDirectory, `.${basename(this.configPath)}.${process.pid}.${randomUUID()}.tmp`);
|
|
381
|
-
await mkdir(parentDirectory, { recursive: true });
|
|
382
|
-
try {
|
|
383
|
-
await writeFile(temporaryPath, `${JSON.stringify(parsed, null, 2)}\n`, { flag: "wx", mode: 0o600 });
|
|
384
|
-
await rename(temporaryPath, this.configPath);
|
|
385
|
-
}
|
|
386
|
-
catch (error) {
|
|
387
|
-
await unlink(temporaryPath).catch(() => undefined);
|
|
388
|
-
throw error;
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
async getPreferences() {
|
|
392
|
-
const config = await this.load();
|
|
393
|
-
return structuredClone(config.preferences ?? DEFAULT_PROJECT_PREFERENCES);
|
|
394
|
-
}
|
|
395
|
-
async updatePreferences(patch) {
|
|
396
|
-
const validatedPatch = projectPreferencesPatchSchema.parse(patch);
|
|
397
|
-
return this.enqueueMutation(() => this.withConfigLock(async () => {
|
|
398
|
-
const config = await this.loadUnlocked();
|
|
399
|
-
const current = config.preferences ?? DEFAULT_PROJECT_PREFERENCES;
|
|
400
|
-
const next = projectPreferencesSchema.parse({
|
|
401
|
-
logs: { ...current.logs, ...validatedPatch.logs },
|
|
402
|
-
database: { ...current.database, ...validatedPatch.database },
|
|
403
|
-
});
|
|
404
|
-
config.preferences = next;
|
|
405
|
-
await this.persistUnlocked(config);
|
|
406
|
-
return structuredClone(next);
|
|
407
|
-
}));
|
|
408
|
-
}
|
|
409
|
-
async resetPreferences() {
|
|
410
|
-
return this.enqueueMutation(() => this.withConfigLock(async () => {
|
|
411
|
-
const config = await this.loadUnlocked();
|
|
412
|
-
delete config.preferences;
|
|
413
|
-
await this.persistUnlocked(config);
|
|
414
|
-
return structuredClone(DEFAULT_PROJECT_PREFERENCES);
|
|
415
|
-
}));
|
|
416
|
-
}
|
|
417
|
-
async withConfigLock(operation) {
|
|
418
|
-
const lockPath = `${this.configPath}.lock`;
|
|
419
|
-
const lock = await acquireConfigLock(lockPath);
|
|
420
|
-
try {
|
|
421
|
-
return await operation();
|
|
422
|
-
}
|
|
423
|
-
finally {
|
|
424
|
-
await lock.handle.close().finally(() => releaseConfigLock(lockPath, lock.ownerToken));
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
enqueueMutation(operation) {
|
|
428
|
-
const result = this.mutationQueue.then(operation);
|
|
429
|
-
this.mutationQueue = result.then(() => undefined, () => undefined);
|
|
430
|
-
return result;
|
|
431
|
-
}
|
|
432
|
-
mutateConfig(mutation) {
|
|
433
|
-
return this.enqueueMutation(() => this.withConfigLock(async () => {
|
|
434
|
-
const config = await this.loadUnlocked();
|
|
435
|
-
await mutation(config);
|
|
436
|
-
await this.persistUnlocked(config);
|
|
437
|
-
return config;
|
|
438
|
-
}));
|
|
439
|
-
}
|
|
440
|
-
async registerService(service) {
|
|
441
|
-
const parsedService = serviceSchema.parse(service);
|
|
442
|
-
return this.mutateConfig((config) => {
|
|
443
|
-
config.services = [
|
|
444
|
-
...config.services.filter((item) => item.name !== parsedService.name),
|
|
445
|
-
parsedService,
|
|
446
|
-
];
|
|
447
|
-
});
|
|
448
|
-
}
|
|
449
|
-
/** Apply a reviewed import as one config mutation; no partial registration. */
|
|
450
|
-
async importServices(services) {
|
|
451
|
-
return this.importProjectSetup({ services, databases: [] });
|
|
452
|
-
}
|
|
453
|
-
/** Atomically applies a reviewed project setup import across both resource kinds. */
|
|
454
|
-
async importProjectSetup(input) {
|
|
455
|
-
const parsed = input.services.map((service) => ({
|
|
456
|
-
definition: serviceSchema.parse(service.definition),
|
|
457
|
-
onConflict: service.onConflict,
|
|
458
|
-
}));
|
|
459
|
-
const parsedDatabases = input.databases.map((database) => ({
|
|
460
|
-
definition: databaseSchema.parse({
|
|
461
|
-
...database.definition,
|
|
462
|
-
// An import is never authority to unlock writes, including replace.
|
|
463
|
-
writeUnlocked: false,
|
|
464
|
-
}),
|
|
465
|
-
onConflict: database.onConflict,
|
|
466
|
-
}));
|
|
467
|
-
const importedNames = new Set();
|
|
468
|
-
for (const service of parsed) {
|
|
469
|
-
if (importedNames.has(service.definition.name)) {
|
|
470
|
-
throw new ConfigValidationError(`Import contains duplicate service name: ${service.definition.name}`);
|
|
471
|
-
}
|
|
472
|
-
importedNames.add(service.definition.name);
|
|
473
|
-
}
|
|
474
|
-
const importedDatabaseNames = new Set();
|
|
475
|
-
for (const database of parsedDatabases) {
|
|
476
|
-
if (importedDatabaseNames.has(database.definition.name)) {
|
|
477
|
-
throw new ConfigValidationError(`Import contains duplicate database name: ${database.definition.name}`);
|
|
478
|
-
}
|
|
479
|
-
importedDatabaseNames.add(database.definition.name);
|
|
480
|
-
}
|
|
481
|
-
return this.mutateConfig((config) => {
|
|
482
|
-
const next = [...config.services];
|
|
483
|
-
for (const service of parsed) {
|
|
484
|
-
const index = next.findIndex((item) => item.name === service.definition.name);
|
|
485
|
-
if (index >= 0 && service.onConflict === "error") {
|
|
486
|
-
throw new ConfigValidationError(`Service "${service.definition.name}" is already registered.`);
|
|
487
|
-
}
|
|
488
|
-
if (index >= 0)
|
|
489
|
-
next[index] = service.definition;
|
|
490
|
-
else
|
|
491
|
-
next.push(service.definition);
|
|
492
|
-
}
|
|
493
|
-
const nextDatabases = [...config.databases];
|
|
494
|
-
for (const database of parsedDatabases) {
|
|
495
|
-
const index = nextDatabases.findIndex((item) => item.name === database.definition.name);
|
|
496
|
-
if (index >= 0 && database.onConflict === "error") {
|
|
497
|
-
throw new ConfigValidationError(`Database connection "${database.definition.name}" is already registered.`);
|
|
498
|
-
}
|
|
499
|
-
if (index >= 0)
|
|
500
|
-
nextDatabases[index] = database.definition;
|
|
501
|
-
else
|
|
502
|
-
nextDatabases.push(database.definition);
|
|
503
|
-
}
|
|
504
|
-
config.services = next;
|
|
505
|
-
config.databases = nextDatabases;
|
|
506
|
-
});
|
|
507
|
-
}
|
|
508
|
-
/**
|
|
509
|
-
* Patches only the project assignment. Reassignment goes through here rather
|
|
510
|
-
* than `registerService` because that replaces the whole definition by name —
|
|
511
|
-
* a caller would have to resend every field, and any field it did not know
|
|
512
|
-
* about would be silently dropped.
|
|
513
|
-
*
|
|
514
|
-
* A blank or absent `projectPath` clears the assignment back to cwd inference.
|
|
515
|
-
*/
|
|
516
|
-
async setServiceProject(name, projectPath) {
|
|
517
|
-
const serviceName = name.trim();
|
|
518
|
-
if (!serviceName) {
|
|
519
|
-
throw new ConfigValidationError("service name is required");
|
|
520
|
-
}
|
|
521
|
-
const assigned = projectPath?.trim();
|
|
522
|
-
return this.mutateConfig((config) => {
|
|
523
|
-
const service = config.services.find((item) => item.name === serviceName);
|
|
524
|
-
if (!service) {
|
|
525
|
-
throw new Error(`Service "${serviceName}" is not registered.`);
|
|
526
|
-
}
|
|
527
|
-
if (assigned) {
|
|
528
|
-
service.projectPath = assigned;
|
|
529
|
-
}
|
|
530
|
-
else {
|
|
531
|
-
delete service.projectPath;
|
|
532
|
-
}
|
|
533
|
-
});
|
|
534
|
-
}
|
|
535
|
-
async removeService(name) {
|
|
536
|
-
const serviceName = name.trim();
|
|
537
|
-
if (!serviceName) {
|
|
538
|
-
throw new ConfigValidationError("service name is required");
|
|
539
|
-
}
|
|
540
|
-
return this.mutateConfig((config) => {
|
|
541
|
-
const nextServices = config.services.filter((item) => item.name !== serviceName);
|
|
542
|
-
if (nextServices.length === config.services.length) {
|
|
543
|
-
throw new Error(`Service "${serviceName}" is not registered.`);
|
|
544
|
-
}
|
|
545
|
-
config.services = nextServices;
|
|
546
|
-
config.bundles = config.bundles.map((bundle) => ({
|
|
547
|
-
...bundle,
|
|
548
|
-
services: bundle.services.filter((service) => service !== serviceName),
|
|
549
|
-
}));
|
|
550
|
-
});
|
|
551
|
-
}
|
|
552
|
-
async registerBundle(bundle, previousName) {
|
|
553
|
-
const parsedBundle = bundleSchema.parse(bundle);
|
|
554
|
-
return this.mutateConfig((config) => {
|
|
555
|
-
config.bundles = [
|
|
556
|
-
...config.bundles.filter((item) => item.name !== parsedBundle.name && item.name !== previousName),
|
|
557
|
-
parsedBundle,
|
|
558
|
-
];
|
|
559
|
-
});
|
|
560
|
-
}
|
|
561
|
-
async registerGitRepository(repository) {
|
|
562
|
-
const parsedRepository = gitRepositorySchema.parse(repository);
|
|
563
|
-
requireAbsolutePath(parsedRepository.path);
|
|
564
|
-
await requireGitWorktree(parsedRepository.path);
|
|
565
|
-
return this.mutateConfig((config) => {
|
|
566
|
-
const existing = config.gitRepositories.find((item) => item.name === parsedRepository.name);
|
|
567
|
-
if (!parsedRepository.githubCredential && existing?.githubCredential) {
|
|
568
|
-
parsedRepository.githubCredential = existing.githubCredential;
|
|
569
|
-
}
|
|
570
|
-
if (!parsedRepository.providerProjects && existing?.providerProjects) {
|
|
571
|
-
parsedRepository.providerProjects = existing.providerProjects;
|
|
572
|
-
}
|
|
573
|
-
config.gitRepositories = [
|
|
574
|
-
...config.gitRepositories.filter((item) => item.name !== parsedRepository.name),
|
|
575
|
-
parsedRepository,
|
|
576
|
-
];
|
|
577
|
-
config.selectedGitRepository = parsedRepository.name;
|
|
578
|
-
});
|
|
579
|
-
}
|
|
580
|
-
async setGitHubCredential(repositoryName, credential) {
|
|
581
|
-
const parsed = githubCredentialSchema.parse(credential);
|
|
582
|
-
return this.mutateConfig((config) => {
|
|
583
|
-
const repository = config.gitRepositories.find((item) => item.name === repositoryName.trim());
|
|
584
|
-
if (!repository) {
|
|
585
|
-
throw new Error(`Git repository "${repositoryName}" is not registered.`);
|
|
586
|
-
}
|
|
587
|
-
repository.githubCredential = parsed;
|
|
588
|
-
});
|
|
589
|
-
}
|
|
590
|
-
async removeGitRepository(name) {
|
|
591
|
-
const repositoryName = name.trim();
|
|
592
|
-
if (!repositoryName) {
|
|
593
|
-
throw new ConfigValidationError("repository name is required");
|
|
594
|
-
}
|
|
595
|
-
return this.mutateConfig((config) => {
|
|
596
|
-
const nextRepositories = config.gitRepositories.filter((repository) => repository.name !== repositoryName);
|
|
597
|
-
if (nextRepositories.length === config.gitRepositories.length) {
|
|
598
|
-
throw new Error(`Git repository "${repositoryName}" is not registered.`);
|
|
599
|
-
}
|
|
600
|
-
config.gitRepositories = nextRepositories;
|
|
601
|
-
if (config.selectedGitRepository === repositoryName) {
|
|
602
|
-
delete config.selectedGitRepository;
|
|
603
|
-
}
|
|
604
|
-
});
|
|
605
|
-
}
|
|
606
|
-
/**
|
|
607
|
-
* Persist the ordered set of repositories pinned to the board. Names are
|
|
608
|
-
* filtered to those still registered, de-duped (order preserved), and capped
|
|
609
|
-
* at {@link MAX_BOARD_REPOSITORIES} so a stale, repeated, or overflowing list
|
|
610
|
-
* from the client can never corrupt the board or strand repos off-screen.
|
|
611
|
-
*/
|
|
612
|
-
async setGitBoardRepositories(names) {
|
|
613
|
-
return this.mutateConfig((config) => {
|
|
614
|
-
const registered = new Set(config.gitRepositories.map((repo) => repo.name));
|
|
615
|
-
const seen = new Set();
|
|
616
|
-
config.gitBoardRepositories = names
|
|
617
|
-
.filter((name) => {
|
|
618
|
-
if (!registered.has(name) || seen.has(name))
|
|
619
|
-
return false;
|
|
620
|
-
seen.add(name);
|
|
621
|
-
return true;
|
|
622
|
-
})
|
|
623
|
-
.slice(0, MAX_BOARD_REPOSITORIES);
|
|
624
|
-
});
|
|
625
|
-
}
|
|
626
|
-
async selectGitRepository(name) {
|
|
627
|
-
return this.mutateConfig((config) => {
|
|
628
|
-
if (!config.gitRepositories.some((repository) => repository.name === name)) {
|
|
629
|
-
throw new Error(`Git repository "${name}" is not registered.`);
|
|
630
|
-
}
|
|
631
|
-
config.selectedGitRepository = name;
|
|
632
|
-
});
|
|
633
|
-
}
|
|
634
|
-
async selectGitWorktree(name, path) {
|
|
635
|
-
requireAbsolutePath(path);
|
|
636
|
-
const config = await this.load();
|
|
637
|
-
const repository = config.gitRepositories.find((item) => item.name === name);
|
|
638
|
-
if (!repository) {
|
|
639
|
-
throw new Error(`Git repository "${name}" is not registered.`);
|
|
640
|
-
}
|
|
641
|
-
const worktrees = await new GitWorktreeManager(repository.path).list();
|
|
642
|
-
const canonicalPath = await realpath(path).catch(() => path);
|
|
643
|
-
const canonicalWorktrees = await Promise.all(worktrees.map((worktree) => realpath(worktree.path).catch(() => worktree.path)));
|
|
644
|
-
const selectedIndex = canonicalWorktrees.indexOf(canonicalPath);
|
|
645
|
-
if (selectedIndex < 0) {
|
|
646
|
-
throw new ConfigValidationError("The selected folder is not a worktree of this project.");
|
|
647
|
-
}
|
|
648
|
-
const selectedPath = worktrees[selectedIndex].path;
|
|
649
|
-
return this.mutateConfig((next) => {
|
|
650
|
-
const target = next.gitRepositories.find((item) => item.name === name);
|
|
651
|
-
if (target)
|
|
652
|
-
target.activeWorktreePath = selectedPath;
|
|
653
|
-
});
|
|
654
|
-
}
|
|
655
|
-
/** Persist which agent CLI the in-dock chat drives. */
|
|
656
|
-
async setChatProvider(provider) {
|
|
657
|
-
return this.mutateConfig((config) => {
|
|
658
|
-
config.chatProvider = provider;
|
|
659
|
-
});
|
|
660
|
-
}
|
|
661
|
-
/**
|
|
662
|
-
* Persist the model new sessions for `provider` spawn with. A null/empty
|
|
663
|
-
* model clears the pin so the CLI falls back to its own default.
|
|
664
|
-
*/
|
|
665
|
-
async setChatModel(provider, model) {
|
|
666
|
-
const trimmed = model?.trim();
|
|
667
|
-
return this.mutateConfig((config) => {
|
|
668
|
-
const models = { ...config.chatModels };
|
|
669
|
-
if (trimmed)
|
|
670
|
-
models[provider] = trimmed;
|
|
671
|
-
else
|
|
672
|
-
delete models[provider];
|
|
673
|
-
config.chatModels = models;
|
|
674
|
-
});
|
|
675
|
-
}
|
|
676
|
-
async registerDatabase(database) {
|
|
677
|
-
const parsed = databaseSchema.parse(database);
|
|
678
|
-
return this.mutateConfig((config) => {
|
|
679
|
-
config.databases = [
|
|
680
|
-
...config.databases.filter((item) => item.name !== parsed.name),
|
|
681
|
-
parsed,
|
|
682
|
-
];
|
|
683
|
-
});
|
|
684
|
-
}
|
|
685
|
-
async removeDatabase(name) {
|
|
686
|
-
return this.mutateConfig((config) => {
|
|
687
|
-
config.databases = config.databases.filter((item) => item.name !== name);
|
|
688
|
-
});
|
|
689
|
-
}
|
|
690
|
-
/** Lock or unlock write access for a single connection's SQL console. */
|
|
691
|
-
async setDatabaseWriteAccess(name, unlocked) {
|
|
692
|
-
return this.mutateConfig((config) => {
|
|
693
|
-
const connection = config.databases.find((item) => item.name === name);
|
|
694
|
-
if (!connection) {
|
|
695
|
-
throw new Error(`Database connection "${name}" is not registered.`);
|
|
696
|
-
}
|
|
697
|
-
connection.writeUnlocked = unlocked;
|
|
698
|
-
});
|
|
699
|
-
}
|
|
700
|
-
async registerLogSource(source) {
|
|
701
|
-
const parsed = logSourceSchema.parse(source);
|
|
702
|
-
return this.mutateConfig((config) => {
|
|
703
|
-
config.logSources = [
|
|
704
|
-
...config.logSources.filter((item) => item.name !== parsed.name),
|
|
705
|
-
parsed,
|
|
706
|
-
];
|
|
707
|
-
});
|
|
708
|
-
}
|
|
709
|
-
async removeLogSource(name) {
|
|
710
|
-
return this.mutateConfig((config) => {
|
|
711
|
-
config.logSources = config.logSources.filter((item) => item.name !== name);
|
|
712
|
-
});
|
|
713
|
-
}
|
|
714
|
-
async registerSshServer(server) {
|
|
715
|
-
const parsed = sshServerSchema.parse(server);
|
|
716
|
-
return this.mutateConfig((config) => {
|
|
717
|
-
config.sshServers = [
|
|
718
|
-
...config.sshServers.filter((item) => item.host !== parsed.host),
|
|
719
|
-
parsed,
|
|
720
|
-
];
|
|
721
|
-
});
|
|
722
|
-
}
|
|
723
|
-
async removeSshServer(host) {
|
|
724
|
-
const target = sshServerSchema.shape.host.parse(host);
|
|
725
|
-
return this.mutateConfig((config) => {
|
|
726
|
-
config.sshServers = config.sshServers.filter((item) => item.host !== target);
|
|
727
|
-
});
|
|
728
|
-
}
|
|
729
|
-
async setGithubToken(host, token, profile) {
|
|
730
|
-
const parsed = githubTokenSchema.parse({
|
|
731
|
-
host: host.trim(),
|
|
732
|
-
token: token.trim(),
|
|
733
|
-
login: profile?.login?.trim() || undefined,
|
|
734
|
-
avatarUrl: profile?.avatarUrl?.trim() || undefined,
|
|
735
|
-
});
|
|
736
|
-
return this.mutateConfig((config) => {
|
|
737
|
-
config.githubTokens = [
|
|
738
|
-
...config.githubTokens.filter((t) => t.host !== parsed.host),
|
|
739
|
-
parsed,
|
|
740
|
-
];
|
|
741
|
-
});
|
|
742
|
-
}
|
|
743
|
-
/** Cached account identity for a stored token, when one was captured. */
|
|
744
|
-
getGithubProfile(config, host = "github.com") {
|
|
745
|
-
const entry = config.githubTokens.find((t) => t.host === host);
|
|
746
|
-
if (!entry?.login)
|
|
747
|
-
return undefined;
|
|
748
|
-
return { login: entry.login, avatarUrl: entry.avatarUrl };
|
|
749
|
-
}
|
|
750
|
-
/** Attach identity to an already-stored token without touching the secret. */
|
|
751
|
-
async setGithubProfile(host, profile) {
|
|
752
|
-
return this.mutateConfig((config) => {
|
|
753
|
-
config.githubTokens = config.githubTokens.map((entry) => entry.host === host.trim()
|
|
754
|
-
? { ...entry, login: profile.login, avatarUrl: profile.avatarUrl }
|
|
755
|
-
: entry);
|
|
756
|
-
});
|
|
757
|
-
}
|
|
758
|
-
/** Cached commit identity for a GitHub account, when one has been resolved. */
|
|
759
|
-
getGithubIdentity(config, host, login) {
|
|
760
|
-
return config.githubIdentities.find((entry) => entry.host === host && entry.login.toLowerCase() === login.toLowerCase());
|
|
761
|
-
}
|
|
762
|
-
async setGithubIdentity(identity) {
|
|
763
|
-
const parsed = githubIdentitySchema.parse(identity);
|
|
764
|
-
return this.mutateConfig((config) => {
|
|
765
|
-
config.githubIdentities = [
|
|
766
|
-
...config.githubIdentities.filter((entry) => entry.host !== parsed.host ||
|
|
767
|
-
entry.login.toLowerCase() !== parsed.login.toLowerCase()),
|
|
768
|
-
parsed,
|
|
769
|
-
];
|
|
770
|
-
});
|
|
771
|
-
}
|
|
772
|
-
async removeGithubToken(host) {
|
|
773
|
-
return this.mutateConfig((config) => {
|
|
774
|
-
config.githubTokens = config.githubTokens.filter((t) => t.host !== host.trim());
|
|
775
|
-
});
|
|
776
|
-
}
|
|
777
|
-
getGithubToken(config, host = "github.com") {
|
|
778
|
-
return config.githubTokens.find((t) => t.host === host)?.token;
|
|
779
|
-
}
|
|
780
|
-
/**
|
|
781
|
-
* Save how a provider is connected. A `cli` connection deliberately drops any
|
|
782
|
-
* token it was handed: the vendor CLI's auth file stays the single source, so
|
|
783
|
-
* `vercel logout` also revokes us instead of leaving a stale copy behind.
|
|
784
|
-
*/
|
|
785
|
-
async setConnection(providerId, connection) {
|
|
786
|
-
const id = providerIdSchema.parse(providerId);
|
|
787
|
-
const parsed = providerConnectionSchema.parse(connection);
|
|
788
|
-
if (parsed.source === "cli") {
|
|
789
|
-
delete parsed.token;
|
|
790
|
-
}
|
|
791
|
-
else if (!parsed.token) {
|
|
792
|
-
throw new ConfigValidationError(`a ${providerLabel(id)} token is required`);
|
|
793
|
-
}
|
|
794
|
-
if (parsed.source === "oauth" && !parsed.clientId) {
|
|
795
|
-
throw new ConfigValidationError(`a ${providerLabel(id)} OAuth connection needs its client id`);
|
|
796
|
-
}
|
|
797
|
-
return this.mutateConfig((config) => {
|
|
798
|
-
config.connections[id] = parsed;
|
|
799
|
-
});
|
|
800
|
-
}
|
|
801
|
-
/**
|
|
802
|
-
* Persist the tokens a refresh returned. Separate from
|
|
803
|
-
* {@link setConnection} because it runs mid-request on an already connected
|
|
804
|
-
* account, and must not disturb the scope or cached username.
|
|
805
|
-
*/
|
|
806
|
-
async updateConnectionTokens(providerId, tokens) {
|
|
807
|
-
const id = providerIdSchema.parse(providerId);
|
|
808
|
-
return this.mutateConfig((config) => {
|
|
809
|
-
const connection = config.connections[id];
|
|
810
|
-
if (connection?.source !== "oauth")
|
|
811
|
-
return;
|
|
812
|
-
config.connections[id] = {
|
|
813
|
-
...connection,
|
|
814
|
-
token: tokens.token,
|
|
815
|
-
// Providers rotate refresh tokens; keep the previous one only if this
|
|
816
|
-
// response omitted a replacement, or the connection becomes unrenewable.
|
|
817
|
-
refreshToken: tokens.refreshToken ?? connection.refreshToken,
|
|
818
|
-
expiresAt: tokens.expiresAt,
|
|
819
|
-
};
|
|
820
|
-
});
|
|
821
|
-
}
|
|
822
|
-
/** Re-scope an existing connection without re-entering the token. */
|
|
823
|
-
async setConnectionScope(providerId, scope) {
|
|
824
|
-
const id = providerIdSchema.parse(providerId);
|
|
825
|
-
return this.mutateConfig((config) => {
|
|
826
|
-
const connection = config.connections[id];
|
|
827
|
-
if (!connection)
|
|
828
|
-
throw new Error(`${providerLabel(id)} is not connected.`);
|
|
829
|
-
config.connections[id] = {
|
|
830
|
-
...connection,
|
|
831
|
-
scopeId: scope.scopeId?.trim() || undefined,
|
|
832
|
-
scopeSlug: scope.scopeSlug?.trim() || undefined,
|
|
833
|
-
};
|
|
834
|
-
});
|
|
835
|
-
}
|
|
836
|
-
async removeConnection(providerId) {
|
|
837
|
-
const id = providerIdSchema.parse(providerId);
|
|
838
|
-
return this.mutateConfig((config) => {
|
|
839
|
-
delete config.connections[id];
|
|
840
|
-
});
|
|
841
|
-
}
|
|
842
|
-
/** Pin which provider project a registered repository deploys. */
|
|
843
|
-
async setProviderProject(providerId, repositoryName, projectId) {
|
|
844
|
-
const id = providerIdSchema.parse(providerId);
|
|
845
|
-
return this.mutateConfig((config) => {
|
|
846
|
-
const repository = config.gitRepositories.find((item) => item.name === repositoryName.trim());
|
|
847
|
-
if (!repository) {
|
|
848
|
-
throw new Error(`Git repository "${repositoryName}" is not registered.`);
|
|
849
|
-
}
|
|
850
|
-
const pinned = projectId?.trim();
|
|
851
|
-
const projects = { ...repository.providerProjects };
|
|
852
|
-
if (pinned)
|
|
853
|
-
projects[id] = pinned;
|
|
854
|
-
else
|
|
855
|
-
delete projects[id];
|
|
856
|
-
// Drop the key entirely when nothing is pinned, so an untouched repo
|
|
857
|
-
// serializes exactly as it did before providers were introduced.
|
|
858
|
-
if (Object.keys(projects).length > 0)
|
|
859
|
-
repository.providerProjects = projects;
|
|
860
|
-
else
|
|
861
|
-
delete repository.providerProjects;
|
|
862
|
-
});
|
|
863
|
-
}
|
|
864
|
-
/** Persist a user-saved/forked workflow (replaces one with the same id). */
|
|
865
|
-
async saveWorkflow(workflow) {
|
|
866
|
-
const parsed = workflowSchema.parse(workflow);
|
|
867
|
-
return this.mutateConfig((config) => {
|
|
868
|
-
config.workflows = [
|
|
869
|
-
...config.workflows.filter((item) => item.id !== parsed.id),
|
|
870
|
-
parsed,
|
|
871
|
-
];
|
|
872
|
-
});
|
|
873
|
-
}
|
|
874
|
-
async removeWorkflow(id) {
|
|
875
|
-
return this.mutateConfig((config) => {
|
|
876
|
-
config.workflows = config.workflows.filter((item) => item.id !== id.trim());
|
|
877
|
-
});
|
|
878
|
-
}
|
|
879
|
-
/** Persist an event→workflow trigger (replaces one with the same id). */
|
|
880
|
-
async saveWorkflowTrigger(trigger) {
|
|
881
|
-
const parsed = workflowTriggerSchema.parse(trigger);
|
|
882
|
-
return this.mutateConfig((config) => {
|
|
883
|
-
config.workflowTriggers = [
|
|
884
|
-
...config.workflowTriggers.filter((item) => item.id !== parsed.id),
|
|
885
|
-
parsed,
|
|
886
|
-
];
|
|
887
|
-
});
|
|
888
|
-
}
|
|
889
|
-
async removeWorkflowTrigger(id) {
|
|
890
|
-
return this.mutateConfig((config) => {
|
|
891
|
-
config.workflowTriggers = config.workflowTriggers.filter((item) => item.id !== id.trim());
|
|
892
|
-
});
|
|
893
|
-
}
|
|
894
|
-
}
|
|
895
|
-
export class ConfigValidationError extends Error {
|
|
896
|
-
}
|
|
897
|
-
function requireAbsolutePath(path) {
|
|
898
|
-
if (!isAbsolute(path)) {
|
|
899
|
-
throw new ConfigValidationError("Please add an absolute path. Paths beginning with ~ are not expanded here.");
|
|
900
|
-
}
|
|
901
|
-
}
|
|
902
|
-
export async function isGitWorktree(path) {
|
|
903
|
-
try {
|
|
904
|
-
const { stdout } = await execFileAsync("git", ["rev-parse", "--is-inside-work-tree"], { cwd: path });
|
|
905
|
-
return stdout.trim() === "true";
|
|
906
|
-
}
|
|
907
|
-
catch {
|
|
908
|
-
return false;
|
|
909
|
-
}
|
|
910
|
-
}
|
|
911
|
-
/**
|
|
912
|
-
* The worktree root enclosing `path`, or null when it is not inside a repo.
|
|
913
|
-
*
|
|
914
|
-
* Registering a service's own `cwd` is usually the wrong granularity — a service
|
|
915
|
-
* often runs from a subdirectory (`repo/frontend`), and a project pinned there
|
|
916
|
-
* would fight the path-based grouping. Resolving to the root first is what makes
|
|
917
|
-
* "adopt this service's folder" produce the project the user actually meant.
|
|
918
|
-
*/
|
|
919
|
-
export async function gitToplevel(path) {
|
|
920
|
-
try {
|
|
921
|
-
const { stdout } = await execFileAsync("git", ["rev-parse", "--show-toplevel"], {
|
|
922
|
-
cwd: path,
|
|
923
|
-
});
|
|
924
|
-
return stdout.trim() || null;
|
|
925
|
-
}
|
|
926
|
-
catch {
|
|
927
|
-
return null;
|
|
928
|
-
}
|
|
929
|
-
}
|
|
930
|
-
async function requireGitWorktree(path) {
|
|
931
|
-
if (await isGitWorktree(path))
|
|
932
|
-
return;
|
|
933
|
-
throw new ConfigValidationError("Not a Git repository. Choose a folder inside a Git worktree.");
|
|
934
|
-
}
|
|
935
|
-
async function acquireConfigLock(lockPath) {
|
|
936
|
-
await mkdir(dirname(lockPath), { recursive: true });
|
|
937
|
-
const startedAt = Date.now();
|
|
938
|
-
let attempts = 0;
|
|
939
|
-
while (Date.now() - startedAt < CONFIG_LOCK_WAIT_MS) {
|
|
940
|
-
try {
|
|
941
|
-
const handle = await open(lockPath, "wx");
|
|
942
|
-
const ownerToken = `${process.pid}:${randomUUID()}`;
|
|
943
|
-
try {
|
|
944
|
-
await handle.writeFile(ownerToken, "utf8");
|
|
945
|
-
return { handle, ownerToken };
|
|
946
|
-
}
|
|
947
|
-
catch (error) {
|
|
948
|
-
await handle.close().catch(() => undefined);
|
|
949
|
-
await unlink(lockPath).catch(() => undefined);
|
|
950
|
-
throw error;
|
|
951
|
-
}
|
|
952
|
-
}
|
|
953
|
-
catch (error) {
|
|
954
|
-
if (!hasErrorCode(error, "EEXIST"))
|
|
955
|
-
throw error;
|
|
956
|
-
}
|
|
957
|
-
if (await recoverStaleConfigLock(lockPath)) {
|
|
958
|
-
continue;
|
|
959
|
-
}
|
|
960
|
-
attempts += 1;
|
|
961
|
-
const retryDelay = Math.min(CONFIG_LOCK_RETRY_MIN_MS * attempts, CONFIG_LOCK_RETRY_MAX_MS);
|
|
962
|
-
await new Promise((resolveDelay) => {
|
|
963
|
-
setTimeout(resolveDelay, retryDelay);
|
|
964
|
-
});
|
|
965
|
-
}
|
|
966
|
-
throw new Error(`Timed out waiting for config lock: ${lockPath}`);
|
|
967
|
-
}
|
|
968
|
-
async function releaseConfigLock(lockPath, ownerToken) {
|
|
969
|
-
let currentOwner;
|
|
970
|
-
try {
|
|
971
|
-
currentOwner = await readFile(lockPath, "utf8");
|
|
972
|
-
}
|
|
973
|
-
catch (error) {
|
|
974
|
-
if (hasErrorCode(error, "ENOENT"))
|
|
975
|
-
return true;
|
|
976
|
-
throw error;
|
|
977
|
-
}
|
|
978
|
-
if (currentOwner !== ownerToken)
|
|
979
|
-
return false;
|
|
980
|
-
try {
|
|
981
|
-
await unlink(lockPath);
|
|
982
|
-
}
|
|
983
|
-
catch (error) {
|
|
984
|
-
if (!hasErrorCode(error, "ENOENT"))
|
|
985
|
-
throw error;
|
|
986
|
-
}
|
|
987
|
-
return true;
|
|
988
|
-
}
|
|
989
|
-
async function recoverStaleConfigLock(lockPath, afterOwnerRead) {
|
|
990
|
-
let observedOwner;
|
|
991
|
-
try {
|
|
992
|
-
observedOwner = await readFile(lockPath, "utf8");
|
|
993
|
-
}
|
|
994
|
-
catch (error) {
|
|
995
|
-
if (hasErrorCode(error, "ENOENT"))
|
|
996
|
-
return true;
|
|
997
|
-
throw error;
|
|
998
|
-
}
|
|
999
|
-
await afterOwnerRead?.();
|
|
1000
|
-
let lockMtimeMs;
|
|
1001
|
-
try {
|
|
1002
|
-
lockMtimeMs = (await stat(lockPath)).mtimeMs;
|
|
1003
|
-
}
|
|
1004
|
-
catch (error) {
|
|
1005
|
-
if (hasErrorCode(error, "ENOENT"))
|
|
1006
|
-
return true;
|
|
1007
|
-
throw error;
|
|
1008
|
-
}
|
|
1009
|
-
if (Date.now() - lockMtimeMs <= CONFIG_LOCK_STALE_MS)
|
|
1010
|
-
return false;
|
|
1011
|
-
return releaseConfigLock(lockPath, observedOwner);
|
|
1012
|
-
}
|
|
1013
|
-
/** @internal Deterministic stale-lock ownership seam used by regression tests. */
|
|
1014
|
-
export async function __recoverStaleConfigLockForTests(lockPath, afterOwnerRead) {
|
|
1015
|
-
await recoverStaleConfigLock(lockPath, afterOwnerRead);
|
|
1016
|
-
}
|
|
1017
|
-
function hasErrorCode(error, code) {
|
|
1018
|
-
return (typeof error === "object" &&
|
|
1019
|
-
error !== null &&
|
|
1020
|
-
"code" in error &&
|
|
1021
|
-
error.code === code);
|
|
1022
|
-
}
|
|
1023
|
-
function isMissingFileError(error) {
|
|
1024
|
-
return hasErrorCode(error, "ENOENT");
|
|
1025
|
-
}
|
|
1026
|
-
//# sourceMappingURL=config-store.js.map
|