@opengsd/gsd-pi 1.5.0-dev.4fb2d460 → 1.5.0-dev.c4c8885f
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/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +114 -36
- package/dist/resources/extensions/gsd/activity-log.js +1 -1
- package/dist/resources/extensions/gsd/auto/orchestrator.js +16 -10
- package/dist/resources/extensions/gsd/auto-artifact-paths.js +2 -2
- package/dist/resources/extensions/gsd/auto-dispatch.js +53 -15
- package/dist/resources/extensions/gsd/auto-model-selection.js +28 -1
- package/dist/resources/extensions/gsd/auto-post-unit.js +4 -3
- package/dist/resources/extensions/gsd/auto-prompts.js +29 -117
- package/dist/resources/extensions/gsd/auto-start.js +53 -30
- package/dist/resources/extensions/gsd/auto-timeout-recovery.js +12 -2
- package/dist/resources/extensions/gsd/auto-timers.js +9 -2
- package/dist/resources/extensions/gsd/auto.js +97 -31
- package/dist/resources/extensions/gsd/compat/compat-marker.js +44 -0
- package/dist/resources/extensions/gsd/config-overlay.js +7 -2
- package/dist/resources/extensions/gsd/db/engine.js +33 -0
- package/dist/resources/extensions/gsd/db-adapter.js +30 -3
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +3 -3
- package/dist/resources/extensions/gsd/journal.js +1 -1
- package/dist/resources/extensions/gsd/markdown-renderer.js +34 -91
- package/dist/resources/extensions/gsd/metrics.js +2 -2
- package/dist/resources/extensions/gsd/paths.js +70 -49
- package/dist/resources/extensions/gsd/post-unit-hooks.js +27 -0
- package/dist/resources/extensions/gsd/preferences-models.js +66 -15
- package/dist/resources/extensions/gsd/preferences-validation.js +66 -10
- package/dist/resources/extensions/gsd/rule-registry.js +106 -10
- package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +1 -10
- package/dist/resources/extensions/gsd/state-reconciliation/drift/completion.js +3 -24
- package/dist/resources/extensions/gsd/state-reconciliation/index.js +10 -0
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +3 -5
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +16 -10
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +3 -8
- package/dist/resources/extensions/gsd/uat-dispatch.js +94 -0
- package/dist/resources/extensions/gsd/uok/audit-toggle.js +31 -2
- package/dist/resources/extensions/gsd/uok/audit.js +3 -0
- package/dist/resources/extensions/gsd/uok/gate-runner.js +22 -30
- package/dist/resources/extensions/gsd/uok/gitops.js +18 -15
- package/dist/resources/extensions/gsd/uok/kernel.js +120 -46
- package/dist/resources/extensions/gsd/uok/model-policy.js +17 -14
- package/dist/resources/extensions/gsd/workflow-event-ledger.js +1 -1
- package/dist/resources/extensions/gsd/workflow-logger.js +1 -1
- package/dist/resources/extensions/gsd/workflow-projections.js +9 -26
- package/dist/resources/extensions/gsd/workspace.js +5 -14
- package/dist/resources/extensions/shared/gsd-browser-cli.js +29 -0
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +10 -10
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +10 -10
- package/dist/web/standalone/.next/server/chunks/{1128.js → 1991.js} +1 -1
- package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/worktree-cli-create.d.ts +10 -0
- package/dist/worktree-cli-create.js +11 -0
- package/dist/worktree-cli-format.d.ts +12 -0
- package/dist/worktree-cli-format.js +38 -0
- package/dist/worktree-cli-plan.d.ts +16 -0
- package/dist/worktree-cli-plan.js +19 -0
- package/dist/worktree-cli-session.d.ts +13 -0
- package/dist/worktree-cli-session.js +18 -0
- package/dist/worktree-cli-status.d.ts +35 -0
- package/dist/worktree-cli-status.js +54 -0
- package/dist/worktree-cli.d.ts +1 -16
- package/dist/worktree-cli.js +28 -122
- package/integrations/hermes/open_gsd_hermes/gsd_client.py +1 -1
- package/integrations/hermes/pyproject.toml +1 -1
- package/package.json +1 -1
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/dist/orchestrator-agent.d.ts +21 -0
- package/packages/daemon/dist/orchestrator-agent.d.ts.map +1 -0
- package/packages/daemon/dist/orchestrator-agent.js +113 -0
- package/packages/daemon/dist/orchestrator-agent.js.map +1 -0
- package/packages/daemon/dist/orchestrator-tools.d.ts +12 -0
- package/packages/daemon/dist/orchestrator-tools.d.ts.map +1 -0
- package/packages/daemon/dist/orchestrator-tools.js +137 -0
- package/packages/daemon/dist/orchestrator-tools.js.map +1 -0
- package/packages/daemon/dist/orchestrator.d.ts +4 -56
- package/packages/daemon/dist/orchestrator.d.ts.map +1 -1
- package/packages/daemon/dist/orchestrator.js +13 -303
- package/packages/daemon/dist/orchestrator.js.map +1 -1
- package/packages/daemon/dist/orchestrator.test.js +11 -1
- package/packages/daemon/dist/orchestrator.test.js.map +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/package.json +4 -4
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/package.json +2 -2
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +146 -33
- package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +25 -0
- package/src/resources/extensions/browser-tools/tests/managed-gsd-browser-tools.test.mjs +93 -0
- package/src/resources/extensions/gsd/activity-log.ts +1 -1
- package/src/resources/extensions/gsd/auto/orchestrator.ts +17 -11
- package/src/resources/extensions/gsd/auto-artifact-paths.ts +2 -1
- package/src/resources/extensions/gsd/auto-dispatch.ts +59 -14
- package/src/resources/extensions/gsd/auto-model-selection.ts +33 -1
- package/src/resources/extensions/gsd/auto-post-unit.ts +4 -2
- package/src/resources/extensions/gsd/auto-prompts.ts +53 -113
- package/src/resources/extensions/gsd/auto-start.ts +57 -28
- package/src/resources/extensions/gsd/auto-timeout-recovery.ts +12 -2
- package/src/resources/extensions/gsd/auto-timers.ts +9 -2
- package/src/resources/extensions/gsd/auto.ts +103 -30
- package/src/resources/extensions/gsd/compat/compat-marker.ts +47 -0
- package/src/resources/extensions/gsd/config-overlay.ts +7 -1
- package/src/resources/extensions/gsd/db/engine.ts +36 -0
- package/src/resources/extensions/gsd/db-adapter.ts +29 -3
- package/src/resources/extensions/gsd/docs/preferences-reference.md +3 -3
- package/src/resources/extensions/gsd/journal.ts +1 -1
- package/src/resources/extensions/gsd/markdown-renderer.ts +52 -103
- package/src/resources/extensions/gsd/metrics.ts +2 -2
- package/src/resources/extensions/gsd/paths.ts +87 -48
- package/src/resources/extensions/gsd/post-unit-hooks.ts +32 -0
- package/src/resources/extensions/gsd/preferences-models.ts +74 -20
- package/src/resources/extensions/gsd/preferences-types.ts +24 -1
- package/src/resources/extensions/gsd/preferences-validation.ts +77 -9
- package/src/resources/extensions/gsd/rule-registry.ts +111 -9
- package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +1 -9
- package/src/resources/extensions/gsd/state-reconciliation/drift/completion.ts +2 -22
- package/src/resources/extensions/gsd/state-reconciliation/index.ts +14 -0
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +41 -2
- package/src/resources/extensions/gsd/tests/auto-post-unit-artifact-diagnostic.test.ts +48 -1
- package/src/resources/extensions/gsd/tests/auto-start-project-milestone-reconcile.test.ts +29 -1
- package/src/resources/extensions/gsd/tests/auto-timeout-recovery-supervisor-inflight-guard.test.ts +159 -0
- package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/compat-marker.test.ts +85 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/db-adapter.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/db-writable-probe.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/flat-phase-renderer.test.ts +22 -1
- package/src/resources/extensions/gsd/tests/flat-phase-validation-path.test.ts +72 -32
- package/src/resources/extensions/gsd/tests/integration/paths.test.ts +88 -1
- package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +0 -1
- package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +269 -0
- package/src/resources/extensions/gsd/tests/post-unit-retry-on-orchestrator-bridge.test.ts +8 -1
- package/src/resources/extensions/gsd/tests/read-uat-gate-verdict.test.ts +54 -0
- package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +49 -1
- package/src/resources/extensions/gsd/tests/rule-registry.test.ts +95 -1
- package/src/resources/extensions/gsd/tests/sibling-model-fallbacks.test.ts +189 -0
- package/src/resources/extensions/gsd/tests/single-field-model-thinking.test.ts +156 -0
- package/src/resources/extensions/gsd/tests/skipped-validation-db-atomicity.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/supervisor-model-swap-inflight-guard.test.ts +181 -0
- package/src/resources/extensions/gsd/tests/supervisor-model-swap-thinking-clamp.test.ts +122 -0
- package/src/resources/extensions/gsd/tests/uat-dispatch.test.ts +211 -0
- package/src/resources/extensions/gsd/tests/uok-gate-runner.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/uok-kernel-path.test.ts +226 -2
- package/src/resources/extensions/gsd/tests/uok-model-policy.test.ts +6 -0
- package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +213 -2
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +9 -5
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +19 -8
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +13 -9
- package/src/resources/extensions/gsd/types.ts +23 -4
- package/src/resources/extensions/gsd/uat-dispatch.ts +176 -0
- package/src/resources/extensions/gsd/uok/audit-toggle.ts +32 -2
- package/src/resources/extensions/gsd/uok/audit.ts +2 -0
- package/src/resources/extensions/gsd/uok/gate-runner.ts +26 -36
- package/src/resources/extensions/gsd/uok/gitops.ts +21 -18
- package/src/resources/extensions/gsd/uok/kernel.ts +169 -48
- package/src/resources/extensions/gsd/uok/model-policy.ts +20 -17
- package/src/resources/extensions/gsd/workflow-event-ledger.ts +1 -1
- package/src/resources/extensions/gsd/workflow-logger.ts +1 -1
- package/src/resources/extensions/gsd/workflow-projections.ts +9 -24
- package/src/resources/extensions/gsd/workspace.ts +5 -21
- package/src/resources/extensions/shared/gsd-browser-cli.ts +29 -0
- /package/dist/web/standalone/.next/static/{gXoWec4UNqcR0tkuHwYCr → NPMNi2HV8BuK3baQsEUhk}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{gXoWec4UNqcR0tkuHwYCr → NPMNi2HV8BuK3baQsEUhk}/_ssgManifest.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orchestrator.test.js","sourceRoot":"","sources":["../src/orchestrator.test.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Tests for Orchestrator — LLM agent for #gsd-control channel.\n *\n * Uses a MockAnthropicClient that simulates messages.create() responses,\n * allowing tool execution and conversation flow testing without real API calls.\n */\n\nimport { describe, it, afterEach } from 'node:test';\nimport assert from 'node:assert/strict';\nimport { mkdtempSync, rmSync, existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { tmpdir } from 'node:os';\nimport { randomUUID } from 'node:crypto';\nimport { Orchestrator, type OrchestratorConfig, type OrchestratorDeps, type DiscordMessageLike } from './orchestrator.js';\nimport { Logger } from './logger.js';\nimport type { ManagedSession, ProjectInfo, SessionStatus, CostAccumulator } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction tmpDir(): string {\n return mkdtempSync(join(tmpdir(), `orch-test-${randomUUID().slice(0, 8)}-`));\n}\n\nconst cleanupDirs: string[] = [];\nconst activeLoggers: Logger[] = [];\n\nasync function cleanupAll(): Promise<void> {\n // Close all loggers first so write streams flush before dirs are removed\n for (const logger of activeLoggers) {\n try { await logger.close(); } catch { /* ignore */ }\n }\n activeLoggers.length = 0;\n\n while (cleanupDirs.length) {\n const d = cleanupDirs.pop()!;\n if (existsSync(d)) rmSync(d, { recursive: true, force: true });\n }\n}\n\n// ---------------------------------------------------------------------------\n// Mock Anthropic Client\n// ---------------------------------------------------------------------------\n\ninterface MockCreateParams {\n model: string;\n max_tokens: number;\n system: string;\n tools: unknown[];\n messages: unknown[];\n}\n\ntype CreateHandler = (params: MockCreateParams) => {\n stop_reason: string;\n content: Array<{ type: string; text?: string; id?: string; name?: string; input?: unknown }>;\n};\n\nclass MockAnthropicClient {\n public createCallCount = 0;\n public lastCreateParams: MockCreateParams | null = null;\n private createHandler: CreateHandler;\n\n constructor(handler?: CreateHandler) {\n this.createHandler = handler ?? MockAnthropicClient.defaultHandler;\n }\n\n /** Default handler: returns a simple text response */\n static defaultHandler(): ReturnType<CreateHandler> {\n return {\n stop_reason: 'end_turn',\n content: [{ type: 'text', text: 'Mock LLM response' }],\n };\n }\n\n /** Handler that simulates a tool call then end_turn */\n static toolThenTextHandler(toolName: string, toolInput: unknown, finalText: string): CreateHandler {\n let callCount = 0;\n return () => {\n callCount++;\n if (callCount === 1) {\n return {\n stop_reason: 'tool_use',\n content: [\n {\n type: 'tool_use',\n id: `toolu_${randomUUID().slice(0, 8)}`,\n name: toolName,\n input: toolInput,\n },\n ],\n };\n }\n return {\n stop_reason: 'end_turn',\n content: [{ type: 'text', text: finalText }],\n };\n };\n }\n\n /** Handler that throws an error */\n static errorHandler(message: string): CreateHandler {\n return () => {\n throw new Error(message);\n };\n }\n\n messages = {\n create: async (params: MockCreateParams) => {\n this.createCallCount++;\n this.lastCreateParams = params;\n return this.createHandler(params);\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Mock SessionManager\n// ---------------------------------------------------------------------------\n\nfunction makeMockSession(overrides: Partial<ManagedSession> = {}): ManagedSession {\n return {\n sessionId: overrides.sessionId ?? 'sess-123',\n projectDir: overrides.projectDir ?? '/home/user/project',\n projectName: overrides.projectName ?? 'my-project',\n status: overrides.status ?? ('running' as SessionStatus),\n client: {} as ManagedSession['client'],\n events: [],\n pendingBlocker: null,\n cost: overrides.cost ?? { totalCost: 0.1234, tokens: { input: 1000, output: 500, cacheRead: 0, cacheWrite: 0 } },\n startTime: overrides.startTime ?? Date.now() - 300_000, // 5 min ago\n ...overrides,\n };\n}\n\nclass MockSessionManager {\n public sessions: ManagedSession[] = [];\n public startSessionCalls: Array<{ projectDir: string; command?: string }> = [];\n public cancelSessionCalls: string[] = [];\n public getResultCalls: string[] = [];\n\n async startSession(opts: { projectDir: string; command?: string }): Promise<string> {\n this.startSessionCalls.push(opts);\n return 'sess-new-123';\n }\n\n getSession(sessionId: string): ManagedSession | undefined {\n return this.sessions.find((s) => s.sessionId === sessionId);\n }\n\n getAllSessions(): ManagedSession[] {\n return this.sessions;\n }\n\n async cancelSession(sessionId: string): Promise<void> {\n this.cancelSessionCalls.push(sessionId);\n }\n\n getResult(sessionId: string): Record<string, unknown> {\n const session = this.sessions.find((s) => s.sessionId === sessionId);\n if (!session) throw new Error(`Session not found: ${sessionId}`);\n return {\n sessionId: session.sessionId,\n projectDir: session.projectDir,\n projectName: session.projectName,\n status: session.status,\n durationMs: 300_000,\n cost: session.cost,\n recentEvents: [],\n pendingBlocker: null,\n error: null,\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Mock ChannelManager (unused by orchestrator directly, but required by deps)\n// ---------------------------------------------------------------------------\n\nclass MockChannelManager {}\n\n// ---------------------------------------------------------------------------\n// Mock Discord Message\n// ---------------------------------------------------------------------------\n\nfunction makeMessage(overrides: Partial<{\n authorId: string;\n bot: boolean;\n channelId: string;\n content: string;\n}>): DiscordMessageLike & { sentMessages: string[] } {\n const sentMessages: string[] = [];\n return {\n author: {\n id: overrides.authorId ?? 'owner-123',\n bot: overrides.bot ?? false,\n },\n channelId: overrides.channelId ?? 'control-channel-1',\n content: overrides.content ?? 'hello',\n channel: {\n send: async (content: string) => {\n sentMessages.push(content);\n },\n sendTyping: async () => {},\n },\n sentMessages,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Test Setup Factory\n// ---------------------------------------------------------------------------\n\nfunction makeOrchestrator(opts?: {\n client?: MockAnthropicClient;\n sessions?: ManagedSession[];\n projects?: ProjectInfo[];\n}) {\n const dir = tmpDir();\n cleanupDirs.push(dir);\n const logPath = join(dir, 'test.log');\n const logger = new Logger({ filePath: logPath, level: 'debug' });\n activeLoggers.push(logger);\n\n const sessionManager = new MockSessionManager();\n if (opts?.sessions) sessionManager.sessions = opts.sessions;\n\n const projects: ProjectInfo[] = opts?.projects ?? [\n { name: 'alpha', path: '/home/user/alpha', markers: ['git', 'node', 'gsd'], lastModified: Date.now() },\n { name: 'bravo', path: '/home/user/bravo', markers: ['git', 'rust'], lastModified: Date.now() },\n ];\n\n const config: OrchestratorConfig = {\n model: 'claude-sonnet-4-20250514',\n max_tokens: 4096,\n control_channel_id: 'control-channel-1',\n };\n\n const deps: OrchestratorDeps = {\n sessionManager: sessionManager as unknown as OrchestratorDeps['sessionManager'],\n channelManager: new MockChannelManager() as unknown as OrchestratorDeps['channelManager'],\n scanProjects: async () => projects,\n config,\n logger,\n ownerId: 'owner-123',\n };\n\n const mockClient = opts?.client ?? new MockAnthropicClient();\n const orchestrator = new Orchestrator(deps, mockClient as unknown as import('@anthropic-ai/sdk').default);\n\n return { orchestrator, mockClient, sessionManager, logger, logPath };\n}\n\n// ---------------------------------------------------------------------------\n// Tests\n// ---------------------------------------------------------------------------\n\ndescribe('Orchestrator', () => {\n // Clean up after each test so logger streams are flushed before dirs removed\n afterEach(async () => {\n await cleanupAll();\n });\n\n // ---- Tool definitions ----\n\n describe('tool definitions', () => {\n it('passes 5 tools to the Anthropic API', async () => {\n const { orchestrator, mockClient } = makeOrchestrator();\n const msg = makeMessage({ content: 'what can you do?' });\n await orchestrator.handleMessage(msg);\n\n assert.ok(mockClient.lastCreateParams);\n const tools = mockClient.lastCreateParams.tools as Array<{ name: string }>;\n assert.equal(tools.length, 5);\n\n const names = tools.map((t) => t.name).sort();\n assert.deepEqual(names, [\n 'get_session_detail',\n 'get_status',\n 'list_projects',\n 'start_session',\n 'stop_session',\n ]);\n });\n });\n\n // ---- list_projects tool ----\n\n describe('list_projects tool', () => {\n it('returns project list from scanProjects', async () => {\n const mockClient = new MockAnthropicClient(\n MockAnthropicClient.toolThenTextHandler('list_projects', {}, 'Here are your projects'),\n );\n const { orchestrator } = makeOrchestrator({ client: mockClient });\n const msg = makeMessage({ content: 'list my projects' });\n await orchestrator.handleMessage(msg);\n\n assert.equal(msg.sentMessages.length, 1);\n assert.equal(msg.sentMessages[0], 'Here are your projects');\n // The tool was called (2 create calls: tool_use + end_turn)\n assert.equal(mockClient.createCallCount, 2);\n });\n });\n\n // ---- start_session tool ----\n\n describe('start_session tool', () => {\n it('calls sessionManager.startSession and returns confirmation', async () => {\n const mockClient = new MockAnthropicClient(\n MockAnthropicClient.toolThenTextHandler(\n 'start_session',\n { projectPath: '/home/user/alpha' },\n 'Started session for alpha',\n ),\n );\n const { orchestrator, sessionManager } = makeOrchestrator({ client: mockClient });\n const msg = makeMessage({ content: 'start alpha' });\n await orchestrator.handleMessage(msg);\n\n assert.equal(sessionManager.startSessionCalls.length, 1);\n assert.equal(sessionManager.startSessionCalls[0]!.projectDir, '/home/user/alpha');\n assert.equal(msg.sentMessages[0], 'Started session for alpha');\n });\n });\n\n // ---- get_status tool ----\n\n describe('get_status tool', () => {\n it('returns formatted session status', async () => {\n const session = makeMockSession({ projectName: 'alpha', status: 'running' as SessionStatus });\n const mockClient = new MockAnthropicClient(\n MockAnthropicClient.toolThenTextHandler('get_status', {}, 'Status: alpha is running'),\n );\n const { orchestrator } = makeOrchestrator({ client: mockClient, sessions: [session] });\n const msg = makeMessage({ content: 'status' });\n await orchestrator.handleMessage(msg);\n\n assert.equal(msg.sentMessages[0], 'Status: alpha is running');\n });\n\n it('handles empty session list', async () => {\n const mockClient = new MockAnthropicClient(\n MockAnthropicClient.toolThenTextHandler('get_status', {}, 'No sessions running'),\n );\n const { orchestrator } = makeOrchestrator({ client: mockClient, sessions: [] });\n const msg = makeMessage({ content: 'status' });\n await orchestrator.handleMessage(msg);\n\n assert.equal(msg.sentMessages[0], 'No sessions running');\n });\n });\n\n // ---- stop_session tool ----\n\n describe('stop_session tool', () => {\n it('stops session matched by sessionId', async () => {\n const session = makeMockSession({ sessionId: 'sess-abc', projectName: 'alpha' });\n const mockClient = new MockAnthropicClient(\n MockAnthropicClient.toolThenTextHandler(\n 'stop_session',\n { identifier: 'sess-abc' },\n 'Stopped alpha',\n ),\n );\n const { orchestrator, sessionManager } = makeOrchestrator({ client: mockClient, sessions: [session] });\n const msg = makeMessage({ content: 'stop sess-abc' });\n await orchestrator.handleMessage(msg);\n\n assert.equal(sessionManager.cancelSessionCalls.length, 1);\n assert.equal(sessionManager.cancelSessionCalls[0], 'sess-abc');\n });\n\n it('fuzzy matches by project name', async () => {\n const session = makeMockSession({ sessionId: 'sess-xyz', projectName: 'my-big-project' });\n const mockClient = new MockAnthropicClient(\n MockAnthropicClient.toolThenTextHandler(\n 'stop_session',\n { identifier: 'big-project' },\n 'Stopped my-big-project',\n ),\n );\n const { orchestrator, sessionManager } = makeOrchestrator({ client: mockClient, sessions: [session] });\n const msg = makeMessage({ content: 'stop big project' });\n await orchestrator.handleMessage(msg);\n\n assert.equal(sessionManager.cancelSessionCalls.length, 1);\n assert.equal(sessionManager.cancelSessionCalls[0], 'sess-xyz');\n });\n\n it('returns not-found for unmatched identifier', async () => {\n const mockClient = new MockAnthropicClient(\n MockAnthropicClient.toolThenTextHandler(\n 'stop_session',\n { identifier: 'nonexistent' },\n 'No session found',\n ),\n );\n const { orchestrator, sessionManager } = makeOrchestrator({ client: mockClient, sessions: [] });\n const msg = makeMessage({ content: 'stop nonexistent' });\n await orchestrator.handleMessage(msg);\n\n assert.equal(sessionManager.cancelSessionCalls.length, 0);\n });\n });\n\n // ---- get_session_detail tool ----\n\n describe('get_session_detail tool', () => {\n it('returns formatted session detail', async () => {\n const session = makeMockSession({ sessionId: 'sess-detail' });\n const mockClient = new MockAnthropicClient(\n MockAnthropicClient.toolThenTextHandler(\n 'get_session_detail',\n { sessionId: 'sess-detail' },\n 'Session details for my-project',\n ),\n );\n const { orchestrator } = makeOrchestrator({ client: mockClient, sessions: [session] });\n const msg = makeMessage({ content: 'detail sess-detail' });\n await orchestrator.handleMessage(msg);\n\n assert.equal(msg.sentMessages[0], 'Session details for my-project');\n });\n });\n\n // ---- Message routing / auth guards ----\n\n describe('handleMessage routing', () => {\n it('ignores bot messages', async () => {\n const { orchestrator, mockClient } = makeOrchestrator();\n const msg = makeMessage({ bot: true, content: 'hello from bot' });\n await orchestrator.handleMessage(msg);\n\n assert.equal(mockClient.createCallCount, 0);\n assert.equal(msg.sentMessages.length, 0);\n });\n\n it('ignores non-owner messages', async () => {\n const { orchestrator, mockClient } = makeOrchestrator();\n const msg = makeMessage({ authorId: 'stranger-456', content: 'hack the planet' });\n await orchestrator.handleMessage(msg);\n\n assert.equal(mockClient.createCallCount, 0);\n assert.equal(msg.sentMessages.length, 0);\n });\n\n it('ignores messages from non-control channels', async () => {\n const { orchestrator, mockClient } = makeOrchestrator();\n const msg = makeMessage({ channelId: 'random-channel', content: 'hello' });\n await orchestrator.handleMessage(msg);\n\n assert.equal(mockClient.createCallCount, 0);\n assert.equal(msg.sentMessages.length, 0);\n });\n\n it('ignores empty message content', async () => {\n const { orchestrator, mockClient } = makeOrchestrator();\n const msg = makeMessage({ content: ' ' });\n await orchestrator.handleMessage(msg);\n\n assert.equal(mockClient.createCallCount, 0);\n });\n\n it('routes valid message through LLM and sends response', async () => {\n const { orchestrator, mockClient } = makeOrchestrator();\n const msg = makeMessage({ content: 'hello orchestrator' });\n await orchestrator.handleMessage(msg);\n\n assert.equal(mockClient.createCallCount, 1);\n assert.equal(msg.sentMessages.length, 1);\n assert.equal(msg.sentMessages[0], 'Mock LLM response');\n });\n });\n\n // ---- Conversation history ----\n\n describe('conversation history', () => {\n it('accumulates user and assistant entries', async () => {\n const { orchestrator } = makeOrchestrator();\n\n await orchestrator.handleMessage(makeMessage({ content: 'first' }));\n await orchestrator.handleMessage(makeMessage({ content: 'second' }));\n\n const history = orchestrator.getHistory();\n assert.equal(history.length, 4); // 2 user + 2 assistant\n assert.equal(history[0]!.role, 'user');\n assert.equal(history[1]!.role, 'assistant');\n assert.equal(history[2]!.role, 'user');\n assert.equal(history[3]!.role, 'assistant');\n });\n\n it('trims to MAX_HISTORY (30) by removing oldest pairs', async () => {\n const { orchestrator } = makeOrchestrator();\n\n // Send 17 messages → 34 history entries (17 user + 17 assistant)\n // After trimming: should be ≤30\n for (let i = 0; i < 17; i++) {\n await orchestrator.handleMessage(makeMessage({ content: `msg-${i}` }));\n }\n\n const history = orchestrator.getHistory();\n assert.ok(history.length <= 30, `History length ${history.length} exceeds 30`);\n // Should have trimmed from the front — oldest entries gone\n // 34 entries → trim 2 at a time until ≤30 → 30 entries (trimmed 4)\n assert.equal(history.length, 30);\n });\n });\n\n // ---- Error handling ----\n\n describe('error handling', () => {\n it('sends error message to Discord when LLM API throws', async () => {\n const mockClient = new MockAnthropicClient(\n MockAnthropicClient.errorHandler('API rate limit exceeded'),\n );\n const { orchestrator } = makeOrchestrator({ client: mockClient });\n const msg = makeMessage({ content: 'hello' });\n await orchestrator.handleMessage(msg);\n\n assert.equal(msg.sentMessages.length, 1);\n assert.ok(msg.sentMessages[0]!.includes('Something went wrong'));\n });\n\n it('appends error placeholder to history on LLM failure', async () => {\n const mockClient = new MockAnthropicClient(\n MockAnthropicClient.errorHandler('Network error'),\n );\n const { orchestrator } = makeOrchestrator({ client: mockClient });\n await orchestrator.handleMessage(makeMessage({ content: 'fail' }));\n\n const history = orchestrator.getHistory();\n assert.equal(history.length, 2); // user + error assistant\n assert.equal(history[1]!.role, 'assistant');\n assert.equal(history[1]!.content, '[error — see logs]');\n });\n });\n\n // ---- stop() ----\n\n describe('stop()', () => {\n it('clears conversation history and nulls client', async () => {\n const { orchestrator } = makeOrchestrator();\n\n await orchestrator.handleMessage(makeMessage({ content: 'hello' }));\n assert.ok(orchestrator.getHistory().length > 0);\n\n orchestrator.stop();\n assert.equal(orchestrator.getHistory().length, 0);\n });\n });\n\n // ---- Tool execution direct tests ----\n\n describe('tool execution (via agent loop)', () => {\n it('list_projects returns empty message when no projects', async () => {\n const mockClient = new MockAnthropicClient(\n MockAnthropicClient.toolThenTextHandler('list_projects', {}, 'No projects'),\n );\n const { orchestrator } = makeOrchestrator({ client: mockClient, projects: [] });\n const msg = makeMessage({ content: 'list' });\n await orchestrator.handleMessage(msg);\n\n // The second create call receives the tool result\n assert.equal(mockClient.createCallCount, 2);\n });\n\n it('start_session with optional command passes through', async () => {\n const mockClient = new MockAnthropicClient(\n MockAnthropicClient.toolThenTextHandler(\n 'start_session',\n { projectPath: '/p', command: '/gsd quick fix tests' },\n 'Started',\n ),\n );\n const { orchestrator, sessionManager } = makeOrchestrator({ client: mockClient });\n const msg = makeMessage({ content: 'start with custom command' });\n await orchestrator.handleMessage(msg);\n\n assert.equal(sessionManager.startSessionCalls.length, 1);\n assert.equal(sessionManager.startSessionCalls[0]!.command, '/gsd quick fix tests');\n });\n });\n\n});\n"]}
|
|
1
|
+
{"version":3,"file":"orchestrator.test.js","sourceRoot":"","sources":["../src/orchestrator.test.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Tests for Orchestrator — LLM agent for #gsd-control channel.\n *\n * Uses a MockAnthropicClient that simulates messages.create() responses,\n * allowing tool execution and conversation flow testing without real API calls.\n */\n\nimport { describe, it, afterEach } from 'node:test';\nimport assert from 'node:assert/strict';\nimport { mkdtempSync, rmSync, existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { tmpdir } from 'node:os';\nimport { randomUUID } from 'node:crypto';\nimport { Orchestrator, type OrchestratorConfig, type OrchestratorDeps, type DiscordMessageLike } from './orchestrator.js';\nimport { Logger } from './logger.js';\nimport type { ManagedSession, ProjectInfo, SessionStatus, CostAccumulator } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction tmpDir(): string {\n return mkdtempSync(join(tmpdir(), `orch-test-${randomUUID().slice(0, 8)}-`));\n}\n\nconst cleanupDirs: string[] = [];\nconst activeLoggers: Logger[] = [];\n\nasync function cleanupAll(): Promise<void> {\n // Close all loggers first so write streams flush before dirs are removed\n for (const logger of activeLoggers) {\n try { await logger.close(); } catch { /* ignore */ }\n }\n activeLoggers.length = 0;\n\n while (cleanupDirs.length) {\n const d = cleanupDirs.pop()!;\n if (existsSync(d)) rmSync(d, { recursive: true, force: true });\n }\n}\n\n// ---------------------------------------------------------------------------\n// Mock Anthropic Client\n// ---------------------------------------------------------------------------\n\ninterface MockCreateParams {\n model: string;\n max_tokens: number;\n system: string;\n tools: unknown[];\n messages: unknown[];\n}\n\ntype CreateHandler = (params: MockCreateParams) => {\n stop_reason: string;\n content: Array<{ type: string; text?: string; id?: string; name?: string; input?: unknown }>;\n};\n\nclass MockAnthropicClient {\n public createCallCount = 0;\n public lastCreateParams: MockCreateParams | null = null;\n private createHandler: CreateHandler;\n\n constructor(handler?: CreateHandler) {\n this.createHandler = handler ?? MockAnthropicClient.defaultHandler;\n }\n\n /** Default handler: returns a simple text response */\n static defaultHandler(): ReturnType<CreateHandler> {\n return {\n stop_reason: 'end_turn',\n content: [{ type: 'text', text: 'Mock LLM response' }],\n };\n }\n\n /** Handler that simulates a tool call then end_turn */\n static toolThenTextHandler(toolName: string, toolInput: unknown, finalText: string): CreateHandler {\n let callCount = 0;\n return () => {\n callCount++;\n if (callCount === 1) {\n return {\n stop_reason: 'tool_use',\n content: [\n {\n type: 'tool_use',\n id: `toolu_${randomUUID().slice(0, 8)}`,\n name: toolName,\n input: toolInput,\n },\n ],\n };\n }\n return {\n stop_reason: 'end_turn',\n content: [{ type: 'text', text: finalText }],\n };\n };\n }\n\n /** Handler that throws an error */\n static errorHandler(message: string): CreateHandler {\n return () => {\n throw new Error(message);\n };\n }\n\n messages = {\n create: async (params: MockCreateParams) => {\n this.createCallCount++;\n this.lastCreateParams = params;\n return this.createHandler(params);\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Mock SessionManager\n// ---------------------------------------------------------------------------\n\nfunction makeMockSession(overrides: Partial<ManagedSession> = {}): ManagedSession {\n return {\n sessionId: overrides.sessionId ?? 'sess-123',\n projectDir: overrides.projectDir ?? '/home/user/project',\n projectName: overrides.projectName ?? 'my-project',\n status: overrides.status ?? ('running' as SessionStatus),\n client: {} as ManagedSession['client'],\n events: [],\n pendingBlocker: null,\n cost: overrides.cost ?? { totalCost: 0.1234, tokens: { input: 1000, output: 500, cacheRead: 0, cacheWrite: 0 } },\n startTime: overrides.startTime ?? Date.now() - 300_000, // 5 min ago\n ...overrides,\n };\n}\n\nclass MockSessionManager {\n public sessions: ManagedSession[] = [];\n public startSessionCalls: Array<{ projectDir: string; command?: string }> = [];\n public cancelSessionCalls: string[] = [];\n public getResultCalls: string[] = [];\n\n async startSession(opts: { projectDir: string; command?: string }): Promise<string> {\n this.startSessionCalls.push(opts);\n return 'sess-new-123';\n }\n\n getSession(sessionId: string): ManagedSession | undefined {\n return this.sessions.find((s) => s.sessionId === sessionId);\n }\n\n getAllSessions(): ManagedSession[] {\n return this.sessions;\n }\n\n async cancelSession(sessionId: string): Promise<void> {\n this.cancelSessionCalls.push(sessionId);\n }\n\n getResult(sessionId: string): Record<string, unknown> {\n const session = this.sessions.find((s) => s.sessionId === sessionId);\n if (!session) throw new Error(`Session not found: ${sessionId}`);\n return {\n sessionId: session.sessionId,\n projectDir: session.projectDir,\n projectName: session.projectName,\n status: session.status,\n durationMs: 300_000,\n cost: session.cost,\n recentEvents: [],\n pendingBlocker: null,\n error: null,\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Mock ChannelManager (unused by orchestrator directly, but required by deps)\n// ---------------------------------------------------------------------------\n\nclass MockChannelManager {}\n\n// ---------------------------------------------------------------------------\n// Mock Discord Message\n// ---------------------------------------------------------------------------\n\nfunction makeMessage(overrides: Partial<{\n authorId: string;\n bot: boolean;\n channelId: string;\n content: string;\n}>): DiscordMessageLike & { sentMessages: string[] } {\n const sentMessages: string[] = [];\n return {\n author: {\n id: overrides.authorId ?? 'owner-123',\n bot: overrides.bot ?? false,\n },\n channelId: overrides.channelId ?? 'control-channel-1',\n content: overrides.content ?? 'hello',\n channel: {\n send: async (content: string) => {\n sentMessages.push(content);\n },\n sendTyping: async () => {},\n },\n sentMessages,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Test Setup Factory\n// ---------------------------------------------------------------------------\n\nfunction makeOrchestrator(opts?: {\n client?: MockAnthropicClient;\n sessions?: ManagedSession[];\n projects?: ProjectInfo[];\n}) {\n const dir = tmpDir();\n cleanupDirs.push(dir);\n const logPath = join(dir, 'test.log');\n const logger = new Logger({ filePath: logPath, level: 'debug' });\n activeLoggers.push(logger);\n\n const sessionManager = new MockSessionManager();\n if (opts?.sessions) sessionManager.sessions = opts.sessions;\n\n const projects: ProjectInfo[] = opts?.projects ?? [\n { name: 'alpha', path: '/home/user/alpha', markers: ['git', 'node', 'gsd'], lastModified: Date.now() },\n { name: 'bravo', path: '/home/user/bravo', markers: ['git', 'rust'], lastModified: Date.now() },\n ];\n\n const config: OrchestratorConfig = {\n model: 'claude-sonnet-4-20250514',\n max_tokens: 4096,\n control_channel_id: 'control-channel-1',\n };\n\n const deps: OrchestratorDeps = {\n sessionManager: sessionManager as unknown as OrchestratorDeps['sessionManager'],\n channelManager: new MockChannelManager() as unknown as OrchestratorDeps['channelManager'],\n scanProjects: async () => projects,\n config,\n logger,\n ownerId: 'owner-123',\n };\n\n const mockClient = opts?.client ?? new MockAnthropicClient();\n const orchestrator = new Orchestrator(deps, mockClient as unknown as import('@anthropic-ai/sdk').default);\n\n return { orchestrator, mockClient, sessionManager, logger, logPath };\n}\n\n// ---------------------------------------------------------------------------\n// Tests\n// ---------------------------------------------------------------------------\n\ndescribe('Orchestrator', () => {\n // Clean up after each test so logger streams are flushed before dirs removed\n afterEach(async () => {\n await cleanupAll();\n });\n\n // ---- Tool definitions ----\n\n describe('tool definitions', () => {\n it('passes 5 tools to the Anthropic API', async () => {\n const { orchestrator, mockClient } = makeOrchestrator();\n const msg = makeMessage({ content: 'what can you do?' });\n await orchestrator.handleMessage(msg);\n\n assert.ok(mockClient.lastCreateParams);\n const tools = mockClient.lastCreateParams.tools as Array<{ name: string }>;\n assert.equal(tools.length, 5);\n\n const names = tools.map((t) => t.name).sort();\n assert.deepEqual(names, [\n 'get_session_detail',\n 'get_status',\n 'list_projects',\n 'start_session',\n 'stop_session',\n ]);\n });\n });\n\n // ---- list_projects tool ----\n\n describe('list_projects tool', () => {\n it('returns project list from scanProjects', async () => {\n const mockClient = new MockAnthropicClient(\n MockAnthropicClient.toolThenTextHandler('list_projects', {}, 'Here are your projects'),\n );\n const { orchestrator } = makeOrchestrator({ client: mockClient });\n const msg = makeMessage({ content: 'list my projects' });\n await orchestrator.handleMessage(msg);\n\n assert.equal(msg.sentMessages.length, 1);\n assert.equal(msg.sentMessages[0], 'Here are your projects');\n assert.equal(mockClient.createCallCount, 2);\n\n const finalMessages = mockClient.lastCreateParams?.messages as Array<{ role: string; content: unknown }>;\n const toolResultMessage = finalMessages.at(-1);\n assert.equal(toolResultMessage?.role, 'user');\n\n const toolResults = toolResultMessage?.content as Array<{\n type: string;\n tool_use_id: string;\n content: string;\n }>;\n assert.equal(toolResults.length, 1);\n assert.match(toolResults[0]!.tool_use_id, /^toolu_/);\n assert.equal(toolResults[0]!.type, 'tool_result');\n assert.equal(\n toolResults[0]!.content,\n JSON.stringify(\n [\n { name: 'alpha', path: '/home/user/alpha', markers: ['git', 'node', 'gsd'] },\n { name: 'bravo', path: '/home/user/bravo', markers: ['git', 'rust'] },\n ],\n null,\n 2,\n ),\n );\n });\n });\n\n // ---- start_session tool ----\n\n describe('start_session tool', () => {\n it('calls sessionManager.startSession and returns confirmation', async () => {\n const mockClient = new MockAnthropicClient(\n MockAnthropicClient.toolThenTextHandler(\n 'start_session',\n { projectPath: '/home/user/alpha' },\n 'Started session for alpha',\n ),\n );\n const { orchestrator, sessionManager } = makeOrchestrator({ client: mockClient });\n const msg = makeMessage({ content: 'start alpha' });\n await orchestrator.handleMessage(msg);\n\n assert.equal(sessionManager.startSessionCalls.length, 1);\n assert.equal(sessionManager.startSessionCalls[0]!.projectDir, '/home/user/alpha');\n assert.equal(msg.sentMessages[0], 'Started session for alpha');\n });\n });\n\n // ---- get_status tool ----\n\n describe('get_status tool', () => {\n it('returns formatted session status', async () => {\n const session = makeMockSession({ projectName: 'alpha', status: 'running' as SessionStatus });\n const mockClient = new MockAnthropicClient(\n MockAnthropicClient.toolThenTextHandler('get_status', {}, 'Status: alpha is running'),\n );\n const { orchestrator } = makeOrchestrator({ client: mockClient, sessions: [session] });\n const msg = makeMessage({ content: 'status' });\n await orchestrator.handleMessage(msg);\n\n assert.equal(msg.sentMessages[0], 'Status: alpha is running');\n });\n\n it('handles empty session list', async () => {\n const mockClient = new MockAnthropicClient(\n MockAnthropicClient.toolThenTextHandler('get_status', {}, 'No sessions running'),\n );\n const { orchestrator } = makeOrchestrator({ client: mockClient, sessions: [] });\n const msg = makeMessage({ content: 'status' });\n await orchestrator.handleMessage(msg);\n\n assert.equal(msg.sentMessages[0], 'No sessions running');\n });\n });\n\n // ---- stop_session tool ----\n\n describe('stop_session tool', () => {\n it('stops session matched by sessionId', async () => {\n const session = makeMockSession({ sessionId: 'sess-abc', projectName: 'alpha' });\n const mockClient = new MockAnthropicClient(\n MockAnthropicClient.toolThenTextHandler(\n 'stop_session',\n { identifier: 'sess-abc' },\n 'Stopped alpha',\n ),\n );\n const { orchestrator, sessionManager } = makeOrchestrator({ client: mockClient, sessions: [session] });\n const msg = makeMessage({ content: 'stop sess-abc' });\n await orchestrator.handleMessage(msg);\n\n assert.equal(sessionManager.cancelSessionCalls.length, 1);\n assert.equal(sessionManager.cancelSessionCalls[0], 'sess-abc');\n });\n\n it('fuzzy matches by project name', async () => {\n const session = makeMockSession({ sessionId: 'sess-xyz', projectName: 'my-big-project' });\n const mockClient = new MockAnthropicClient(\n MockAnthropicClient.toolThenTextHandler(\n 'stop_session',\n { identifier: 'big-project' },\n 'Stopped my-big-project',\n ),\n );\n const { orchestrator, sessionManager } = makeOrchestrator({ client: mockClient, sessions: [session] });\n const msg = makeMessage({ content: 'stop big project' });\n await orchestrator.handleMessage(msg);\n\n assert.equal(sessionManager.cancelSessionCalls.length, 1);\n assert.equal(sessionManager.cancelSessionCalls[0], 'sess-xyz');\n });\n\n it('returns not-found for unmatched identifier', async () => {\n const mockClient = new MockAnthropicClient(\n MockAnthropicClient.toolThenTextHandler(\n 'stop_session',\n { identifier: 'nonexistent' },\n 'No session found',\n ),\n );\n const { orchestrator, sessionManager } = makeOrchestrator({ client: mockClient, sessions: [] });\n const msg = makeMessage({ content: 'stop nonexistent' });\n await orchestrator.handleMessage(msg);\n\n assert.equal(sessionManager.cancelSessionCalls.length, 0);\n });\n });\n\n // ---- get_session_detail tool ----\n\n describe('get_session_detail tool', () => {\n it('returns formatted session detail', async () => {\n const session = makeMockSession({ sessionId: 'sess-detail' });\n const mockClient = new MockAnthropicClient(\n MockAnthropicClient.toolThenTextHandler(\n 'get_session_detail',\n { sessionId: 'sess-detail' },\n 'Session details for my-project',\n ),\n );\n const { orchestrator } = makeOrchestrator({ client: mockClient, sessions: [session] });\n const msg = makeMessage({ content: 'detail sess-detail' });\n await orchestrator.handleMessage(msg);\n\n assert.equal(msg.sentMessages[0], 'Session details for my-project');\n });\n });\n\n // ---- Message routing / auth guards ----\n\n describe('handleMessage routing', () => {\n it('ignores bot messages', async () => {\n const { orchestrator, mockClient } = makeOrchestrator();\n const msg = makeMessage({ bot: true, content: 'hello from bot' });\n await orchestrator.handleMessage(msg);\n\n assert.equal(mockClient.createCallCount, 0);\n assert.equal(msg.sentMessages.length, 0);\n });\n\n it('ignores non-owner messages', async () => {\n const { orchestrator, mockClient } = makeOrchestrator();\n const msg = makeMessage({ authorId: 'stranger-456', content: 'hack the planet' });\n await orchestrator.handleMessage(msg);\n\n assert.equal(mockClient.createCallCount, 0);\n assert.equal(msg.sentMessages.length, 0);\n });\n\n it('ignores messages from non-control channels', async () => {\n const { orchestrator, mockClient } = makeOrchestrator();\n const msg = makeMessage({ channelId: 'random-channel', content: 'hello' });\n await orchestrator.handleMessage(msg);\n\n assert.equal(mockClient.createCallCount, 0);\n assert.equal(msg.sentMessages.length, 0);\n });\n\n it('ignores empty message content', async () => {\n const { orchestrator, mockClient } = makeOrchestrator();\n const msg = makeMessage({ content: ' ' });\n await orchestrator.handleMessage(msg);\n\n assert.equal(mockClient.createCallCount, 0);\n });\n\n it('routes valid message through LLM and sends response', async () => {\n const { orchestrator, mockClient } = makeOrchestrator();\n const msg = makeMessage({ content: 'hello orchestrator' });\n await orchestrator.handleMessage(msg);\n\n assert.equal(mockClient.createCallCount, 1);\n assert.equal(msg.sentMessages.length, 1);\n assert.equal(msg.sentMessages[0], 'Mock LLM response');\n });\n });\n\n // ---- Conversation history ----\n\n describe('conversation history', () => {\n it('accumulates user and assistant entries', async () => {\n const { orchestrator } = makeOrchestrator();\n\n await orchestrator.handleMessage(makeMessage({ content: 'first' }));\n await orchestrator.handleMessage(makeMessage({ content: 'second' }));\n\n const history = orchestrator.getHistory();\n assert.equal(history.length, 4); // 2 user + 2 assistant\n assert.equal(history[0]!.role, 'user');\n assert.equal(history[1]!.role, 'assistant');\n assert.equal(history[2]!.role, 'user');\n assert.equal(history[3]!.role, 'assistant');\n });\n\n it('trims to MAX_HISTORY (30) by removing oldest pairs', async () => {\n const { orchestrator } = makeOrchestrator();\n\n // Send 17 messages → 34 history entries (17 user + 17 assistant)\n // After trimming: should be ≤30\n for (let i = 0; i < 17; i++) {\n await orchestrator.handleMessage(makeMessage({ content: `msg-${i}` }));\n }\n\n const history = orchestrator.getHistory();\n assert.ok(history.length <= 30, `History length ${history.length} exceeds 30`);\n // Should have trimmed from the front — oldest entries gone\n // 34 entries → trim 2 at a time until ≤30 → 30 entries (trimmed 4)\n assert.equal(history.length, 30);\n });\n });\n\n // ---- Error handling ----\n\n describe('error handling', () => {\n it('sends error message to Discord when LLM API throws', async () => {\n const mockClient = new MockAnthropicClient(\n MockAnthropicClient.errorHandler('API rate limit exceeded'),\n );\n const { orchestrator } = makeOrchestrator({ client: mockClient });\n const msg = makeMessage({ content: 'hello' });\n await orchestrator.handleMessage(msg);\n\n assert.equal(msg.sentMessages.length, 1);\n assert.ok(msg.sentMessages[0]!.includes('Something went wrong'));\n });\n\n it('appends error placeholder to history on LLM failure', async () => {\n const mockClient = new MockAnthropicClient(\n MockAnthropicClient.errorHandler('Network error'),\n );\n const { orchestrator } = makeOrchestrator({ client: mockClient });\n await orchestrator.handleMessage(makeMessage({ content: 'fail' }));\n\n const history = orchestrator.getHistory();\n assert.equal(history.length, 2); // user + error assistant\n assert.equal(history[1]!.role, 'assistant');\n assert.equal(history[1]!.content, '[error — see logs]');\n });\n });\n\n // ---- stop() ----\n\n describe('stop()', () => {\n it('clears conversation history and nulls client', async () => {\n const { orchestrator } = makeOrchestrator();\n\n await orchestrator.handleMessage(makeMessage({ content: 'hello' }));\n assert.ok(orchestrator.getHistory().length > 0);\n\n orchestrator.stop();\n assert.equal(orchestrator.getHistory().length, 0);\n });\n });\n\n // ---- Tool execution direct tests ----\n\n describe('tool execution (via agent loop)', () => {\n it('list_projects returns empty message when no projects', async () => {\n const mockClient = new MockAnthropicClient(\n MockAnthropicClient.toolThenTextHandler('list_projects', {}, 'No projects'),\n );\n const { orchestrator } = makeOrchestrator({ client: mockClient, projects: [] });\n const msg = makeMessage({ content: 'list' });\n await orchestrator.handleMessage(msg);\n\n // The second create call receives the tool result\n assert.equal(mockClient.createCallCount, 2);\n });\n\n it('start_session with optional command passes through', async () => {\n const mockClient = new MockAnthropicClient(\n MockAnthropicClient.toolThenTextHandler(\n 'start_session',\n { projectPath: '/p', command: '/gsd quick fix tests' },\n 'Started',\n ),\n );\n const { orchestrator, sessionManager } = makeOrchestrator({ client: mockClient });\n const msg = makeMessage({ content: 'start with custom command' });\n await orchestrator.handleMessage(msg);\n\n assert.equal(sessionManager.startSessionCalls.length, 1);\n assert.equal(sessionManager.startSessionCalls[0]!.command, '/gsd quick fix tests');\n });\n });\n\n});\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengsd/daemon",
|
|
3
|
-
"version": "1.5.0-dev.
|
|
3
|
+
"version": "1.5.0-dev.c4c8885f",
|
|
4
4
|
"description": "GSD daemon — background process for project monitoring and Discord integration",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@anthropic-ai/sdk": "^0.52.0",
|
|
34
|
-
"@opengsd/contracts": "^1.5.0-dev.
|
|
35
|
-
"@opengsd/mcp-server": "^1.5.0-dev.
|
|
36
|
-
"@opengsd/rpc-client": "^1.5.0-dev.
|
|
34
|
+
"@opengsd/contracts": "^1.5.0-dev.c4c8885f",
|
|
35
|
+
"@opengsd/mcp-server": "^1.5.0-dev.c4c8885f",
|
|
36
|
+
"@opengsd/rpc-client": "^1.5.0-dev.c4c8885f",
|
|
37
37
|
"discord.js": "^14.25.1",
|
|
38
38
|
"ws": "^8.20.0",
|
|
39
39
|
"yaml": "^2.8.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gsd/agent-core",
|
|
3
|
-
"version": "1.5.0-dev.
|
|
3
|
+
"version": "1.5.0-dev.c4c8885f",
|
|
4
4
|
"description": "GSD session orchestration layer on top of @gsd/pi-coding-agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"gsd": {
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
"test": "node --import ../../src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/*.test.ts src/**/*.test.ts"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@gsd/native": "^1.5.0-dev.
|
|
29
|
-
"@gsd/pi-agent-core": "^1.5.0-dev.
|
|
30
|
-
"@gsd/pi-ai": "^1.5.0-dev.
|
|
31
|
-
"@gsd/pi-coding-agent": "^1.5.0-dev.
|
|
28
|
+
"@gsd/native": "^1.5.0-dev.c4c8885f",
|
|
29
|
+
"@gsd/pi-agent-core": "^1.5.0-dev.c4c8885f",
|
|
30
|
+
"@gsd/pi-ai": "^1.5.0-dev.c4c8885f",
|
|
31
|
+
"@gsd/pi-coding-agent": "^1.5.0-dev.c4c8885f"
|
|
32
32
|
}
|
|
33
33
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gsd/agent-modes",
|
|
3
|
-
"version": "1.5.0-dev.
|
|
3
|
+
"version": "1.5.0-dev.c4c8885f",
|
|
4
4
|
"description": "GSD run modes and CLI layer",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"gsd": {
|
|
@@ -25,12 +25,12 @@
|
|
|
25
25
|
"test": "node --import ../../src/resources/extensions/gsd/tests/resolve-ts.mjs --experimental-strip-types --test src/**/*.test.ts"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@gsd/agent-core": "^1.5.0-dev.
|
|
29
|
-
"@gsd/pi-agent-core": "^1.5.0-dev.
|
|
30
|
-
"@gsd/pi-ai": "^1.5.0-dev.
|
|
31
|
-
"@gsd/pi-coding-agent": "^1.5.0-dev.
|
|
32
|
-
"@gsd/pi-tui": "^1.5.0-dev.
|
|
33
|
-
"@opengsd/contracts": "^1.5.0-dev.
|
|
28
|
+
"@gsd/agent-core": "^1.5.0-dev.c4c8885f",
|
|
29
|
+
"@gsd/pi-agent-core": "^1.5.0-dev.c4c8885f",
|
|
30
|
+
"@gsd/pi-ai": "^1.5.0-dev.c4c8885f",
|
|
31
|
+
"@gsd/pi-coding-agent": "^1.5.0-dev.c4c8885f",
|
|
32
|
+
"@gsd/pi-tui": "^1.5.0-dev.c4c8885f",
|
|
33
|
+
"@opengsd/contracts": "^1.5.0-dev.c4c8885f",
|
|
34
34
|
"chalk": "^5.5.0"
|
|
35
35
|
}
|
|
36
36
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengsd/mcp-server",
|
|
3
|
-
"version": "1.5.0-dev.
|
|
3
|
+
"version": "1.5.0-dev.c4c8885f",
|
|
4
4
|
"description": "MCP server exposing GSD orchestration tools for compatible clients",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"gsd": {
|
|
@@ -50,9 +50,9 @@
|
|
|
50
50
|
"test": "pnpm run build:test && node --test dist/mcp-server.test.js dist/remote-questions.test.js dist/moonshot-tool-schema.test.js dist/pid-registry.test.js dist/probe-mode.test.js dist/stdio-watchdog.test.js dist/cli-runner.test.js dist/readers/graph.test.js dist/readers/paths.test.js dist/readers/readers.test.js"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@gsd/pi-ai": "^1.5.0-dev.
|
|
54
|
-
"@opengsd/contracts": "^1.5.0-dev.
|
|
55
|
-
"@opengsd/rpc-client": "^1.5.0-dev.
|
|
53
|
+
"@gsd/pi-ai": "^1.5.0-dev.c4c8885f",
|
|
54
|
+
"@opengsd/contracts": "^1.5.0-dev.c4c8885f",
|
|
55
|
+
"@opengsd/rpc-client": "^1.5.0-dev.c4c8885f",
|
|
56
56
|
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
57
57
|
"zod": "^4.0.0"
|
|
58
58
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gsd/pi-coding-agent",
|
|
3
|
-
"version": "1.5.0-dev.
|
|
3
|
+
"version": "1.5.0-dev.c4c8885f",
|
|
4
4
|
"description": "Coding agent CLI (vendored from earendil-works/pi)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"gsd": {
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"copy-assets": "node scripts/copy-assets.cjs"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@opengsd/contracts": "^1.5.0-dev.
|
|
36
|
+
"@opengsd/contracts": "^1.5.0-dev.c4c8885f",
|
|
37
37
|
"@mariozechner/jiti": "^2.6.2",
|
|
38
38
|
"@silvia-odwyer/photon-node": "0.3.4",
|
|
39
39
|
"chalk": "5.6.2",
|
|
@@ -53,11 +53,11 @@
|
|
|
53
53
|
"typebox": "1.1.38",
|
|
54
54
|
"undici": "7.28.0",
|
|
55
55
|
"yaml": "2.9.0",
|
|
56
|
-
"@gsd/agent-core": "^1.5.0-dev.
|
|
57
|
-
"@gsd/native": "^1.5.0-dev.
|
|
58
|
-
"@gsd/pi-agent-core": "^1.5.0-dev.
|
|
59
|
-
"@gsd/pi-ai": "^1.5.0-dev.
|
|
60
|
-
"@gsd/pi-tui": "^1.5.0-dev.
|
|
56
|
+
"@gsd/agent-core": "^1.5.0-dev.c4c8885f",
|
|
57
|
+
"@gsd/native": "^1.5.0-dev.c4c8885f",
|
|
58
|
+
"@gsd/pi-agent-core": "^1.5.0-dev.c4c8885f",
|
|
59
|
+
"@gsd/pi-ai": "^1.5.0-dev.c4c8885f",
|
|
60
|
+
"@gsd/pi-tui": "^1.5.0-dev.c4c8885f",
|
|
61
61
|
"@sinclair/typebox": "^0.34.41"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gsd/pi-tui",
|
|
3
|
-
"version": "1.5.0-dev.
|
|
3
|
+
"version": "1.5.0-dev.c4c8885f",
|
|
4
4
|
"description": "Terminal UI library (vendored from earendil-works/pi)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"gsd": {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"build": "node ../../scripts/clean-package-dist.cjs && tsc -p tsconfig.json --incremental false"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@gsd/native": "^1.5.0-dev.
|
|
24
|
+
"@gsd/native": "^1.5.0-dev.c4c8885f",
|
|
25
25
|
"get-east-asian-width": "1.6.0",
|
|
26
26
|
"marked": "15.0.12",
|
|
27
27
|
"@sinclair/typebox": "^0.34.41"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengsd/rpc-client",
|
|
3
|
-
"version": "1.5.0-dev.
|
|
3
|
+
"version": "1.5.0-dev.c4c8885f",
|
|
4
4
|
"description": "Standalone RPC client SDK for GSD — zero internal dependencies",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"gsd": {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"test": "node --test dist/rpc-client.test.js"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@opengsd/contracts": "^1.5.0-dev.
|
|
37
|
+
"@opengsd/contracts": "^1.5.0-dev.c4c8885f"
|
|
38
38
|
},
|
|
39
39
|
"engines": {
|
|
40
40
|
"node": ">=22.0.0"
|
package/pkg/package.json
CHANGED
|
@@ -32,6 +32,18 @@ interface ManagedConnection {
|
|
|
32
32
|
launch: GsdBrowserMcpLaunchConfig;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
type ConnectManagedGsdBrowser = (
|
|
36
|
+
launch: GsdBrowserMcpLaunchConfig,
|
|
37
|
+
signal?: AbortSignal,
|
|
38
|
+
) => Promise<ManagedConnection>;
|
|
39
|
+
|
|
40
|
+
type CloseManagedGsdBrowserConnection = (connection: ManagedConnection) => Promise<void>;
|
|
41
|
+
|
|
42
|
+
interface PendingManagedConnection {
|
|
43
|
+
promise: Promise<ManagedConnection>;
|
|
44
|
+
abortController: AbortController;
|
|
45
|
+
}
|
|
46
|
+
|
|
35
47
|
interface McpContentItem {
|
|
36
48
|
type: string;
|
|
37
49
|
text?: string;
|
|
@@ -69,8 +81,6 @@ interface ManagedBrowserToolSpec {
|
|
|
69
81
|
compatibility?: { producesImages?: boolean };
|
|
70
82
|
}
|
|
71
83
|
|
|
72
|
-
const connections = new Map<string, ManagedConnection>();
|
|
73
|
-
const pendingConnections = new Map<string, Promise<ManagedConnection>>();
|
|
74
84
|
const DEFAULT_MAX_LINES = 2_000;
|
|
75
85
|
const DEFAULT_MAX_BYTES = 50 * 1024;
|
|
76
86
|
const MCP_CALL_TIMEOUT_MS = 60_000;
|
|
@@ -368,6 +378,120 @@ function buildConnectionKey(launch: GsdBrowserMcpLaunchConfig): string {
|
|
|
368
378
|
});
|
|
369
379
|
}
|
|
370
380
|
|
|
381
|
+
function combineAbortSignals(
|
|
382
|
+
poolSignal: AbortSignal,
|
|
383
|
+
callerSignal?: AbortSignal,
|
|
384
|
+
): AbortSignal {
|
|
385
|
+
if (!callerSignal) return poolSignal;
|
|
386
|
+
if (typeof AbortSignal.any === "function") {
|
|
387
|
+
return AbortSignal.any([poolSignal, callerSignal]);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
const controller = new AbortController();
|
|
391
|
+
const abort = (): void => {
|
|
392
|
+
if (!controller.signal.aborted) controller.abort();
|
|
393
|
+
};
|
|
394
|
+
if (poolSignal.aborted || callerSignal.aborted) {
|
|
395
|
+
abort();
|
|
396
|
+
} else {
|
|
397
|
+
poolSignal.addEventListener("abort", abort, { once: true });
|
|
398
|
+
callerSignal.addEventListener("abort", abort, { once: true });
|
|
399
|
+
}
|
|
400
|
+
return controller.signal;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
export class ManagedGsdBrowserConnectionPool {
|
|
404
|
+
private readonly connections = new Map<string, ManagedConnection>();
|
|
405
|
+
private readonly pendingConnections = new Map<string, PendingManagedConnection>();
|
|
406
|
+
private readonly connect: ConnectManagedGsdBrowser;
|
|
407
|
+
private readonly closeConnection: CloseManagedGsdBrowserConnection;
|
|
408
|
+
private generation = 0;
|
|
409
|
+
private closing = false;
|
|
410
|
+
|
|
411
|
+
constructor(
|
|
412
|
+
connect: ConnectManagedGsdBrowser,
|
|
413
|
+
closeConnection: CloseManagedGsdBrowserConnection,
|
|
414
|
+
) {
|
|
415
|
+
this.connect = connect;
|
|
416
|
+
this.closeConnection = closeConnection;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
get activeCount(): number {
|
|
420
|
+
return this.connections.size;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
get pendingCount(): number {
|
|
424
|
+
return this.pendingConnections.size;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
getOrConnect(
|
|
428
|
+
launch: GsdBrowserMcpLaunchConfig,
|
|
429
|
+
signal?: AbortSignal,
|
|
430
|
+
): Promise<ManagedConnection> {
|
|
431
|
+
if (this.closing) {
|
|
432
|
+
return Promise.reject(new Error("gsd-browser connection pool is closing"));
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
const key = buildConnectionKey(launch);
|
|
436
|
+
const existing = this.connections.get(key);
|
|
437
|
+
if (existing) return Promise.resolve(existing);
|
|
438
|
+
|
|
439
|
+
const pending = this.pendingConnections.get(key);
|
|
440
|
+
if (pending) return pending.promise;
|
|
441
|
+
|
|
442
|
+
const generation = this.generation;
|
|
443
|
+
const abortController = new AbortController();
|
|
444
|
+
const connectionSignal = combineAbortSignals(abortController.signal, signal);
|
|
445
|
+
const connectionPromise = this.connect(launch, connectionSignal)
|
|
446
|
+
.then(async (connection) => {
|
|
447
|
+
if (this.closing || this.generation !== generation) {
|
|
448
|
+
await this.closeConnection(connection);
|
|
449
|
+
throw new Error("gsd-browser connection closed during startup");
|
|
450
|
+
}
|
|
451
|
+
this.connections.set(key, connection);
|
|
452
|
+
return connection;
|
|
453
|
+
})
|
|
454
|
+
.finally(() => {
|
|
455
|
+
if (this.pendingConnections.get(key)?.promise === connectionPromise) {
|
|
456
|
+
this.pendingConnections.delete(key);
|
|
457
|
+
}
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
this.pendingConnections.set(key, { promise: connectionPromise, abortController });
|
|
461
|
+
return connectionPromise;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
async closeAll(): Promise<void> {
|
|
465
|
+
this.closing = true;
|
|
466
|
+
this.generation += 1;
|
|
467
|
+
|
|
468
|
+
const activeConnections = Array.from(this.connections.values());
|
|
469
|
+
const pendingConnections = Array.from(this.pendingConnections.values());
|
|
470
|
+
this.connections.clear();
|
|
471
|
+
this.pendingConnections.clear();
|
|
472
|
+
for (const pending of pendingConnections) {
|
|
473
|
+
pending.abortController.abort();
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
const closingActive = activeConnections.map((connection) => this.closeConnection(connection));
|
|
477
|
+
const closingPending = pendingConnections.map(async (pending) => {
|
|
478
|
+
try {
|
|
479
|
+
const connection = await pending.promise;
|
|
480
|
+
await this.closeConnection(connection);
|
|
481
|
+
} catch {
|
|
482
|
+
// Failed or invalidated connection attempts have already cleaned up.
|
|
483
|
+
}
|
|
484
|
+
});
|
|
485
|
+
|
|
486
|
+
try {
|
|
487
|
+
await Promise.allSettled([...closingActive, ...closingPending]);
|
|
488
|
+
} finally {
|
|
489
|
+
this.closing = false;
|
|
490
|
+
this.generation += 1;
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
371
495
|
async function connectManagedGsdBrowser(
|
|
372
496
|
launch: GsdBrowserMcpLaunchConfig,
|
|
373
497
|
signal?: AbortSignal,
|
|
@@ -399,6 +523,24 @@ async function connectManagedGsdBrowser(
|
|
|
399
523
|
}
|
|
400
524
|
}
|
|
401
525
|
|
|
526
|
+
async function closeManagedGsdBrowserConnection(connection: ManagedConnection): Promise<void> {
|
|
527
|
+
try {
|
|
528
|
+
await connection.client.close();
|
|
529
|
+
} catch {
|
|
530
|
+
// Best-effort cleanup.
|
|
531
|
+
}
|
|
532
|
+
try {
|
|
533
|
+
await connection.transport.close();
|
|
534
|
+
} catch {
|
|
535
|
+
// Best-effort cleanup.
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
const connectionPool = new ManagedGsdBrowserConnectionPool(
|
|
540
|
+
connectManagedGsdBrowser,
|
|
541
|
+
closeManagedGsdBrowserConnection,
|
|
542
|
+
);
|
|
543
|
+
|
|
402
544
|
async function getOrConnectManagedGsdBrowser(
|
|
403
545
|
ctx?: ExtensionContext,
|
|
404
546
|
signal?: AbortSignal,
|
|
@@ -406,22 +548,7 @@ async function getOrConnectManagedGsdBrowser(
|
|
|
406
548
|
const launch = resolveGsdBrowserMcpLaunchConfig(resolveProjectRoot(ctx), process.env, {
|
|
407
549
|
sessionSuffix: resolveManagedSessionSuffix(ctx),
|
|
408
550
|
});
|
|
409
|
-
|
|
410
|
-
const existing = connections.get(key);
|
|
411
|
-
if (existing) return existing;
|
|
412
|
-
|
|
413
|
-
const pending = pendingConnections.get(key);
|
|
414
|
-
if (pending) return pending;
|
|
415
|
-
|
|
416
|
-
const connectionPromise = connectManagedGsdBrowser(launch, signal);
|
|
417
|
-
pendingConnections.set(key, connectionPromise);
|
|
418
|
-
try {
|
|
419
|
-
const connection = await connectionPromise;
|
|
420
|
-
connections.set(key, connection);
|
|
421
|
-
return connection;
|
|
422
|
-
} finally {
|
|
423
|
-
pendingConnections.delete(key);
|
|
424
|
-
}
|
|
551
|
+
return connectionPool.getOrConnect(launch, signal);
|
|
425
552
|
}
|
|
426
553
|
|
|
427
554
|
function isUnknownMcpToolError(error: unknown): boolean {
|
|
@@ -743,21 +870,7 @@ export function registerManagedGsdBrowserTools(pi: ExtensionAPI): void {
|
|
|
743
870
|
}
|
|
744
871
|
|
|
745
872
|
export async function closeManagedGsdBrowser(): Promise<void> {
|
|
746
|
-
|
|
747
|
-
try {
|
|
748
|
-
await connection.client.close();
|
|
749
|
-
} catch {
|
|
750
|
-
// Best-effort cleanup.
|
|
751
|
-
}
|
|
752
|
-
try {
|
|
753
|
-
await connection.transport.close();
|
|
754
|
-
} catch {
|
|
755
|
-
// Best-effort cleanup.
|
|
756
|
-
}
|
|
757
|
-
connections.delete(key);
|
|
758
|
-
});
|
|
759
|
-
await Promise.allSettled(closing);
|
|
760
|
-
pendingConnections.clear();
|
|
873
|
+
await connectionPool.closeAll();
|
|
761
874
|
}
|
|
762
875
|
|
|
763
876
|
export async function _resetManagedGsdBrowserForTest(): Promise<void> {
|