@stackmemoryai/stackmemory 0.3.17 → 0.3.18
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/cli/commands/skills.js +15 -2
- package/dist/cli/commands/skills.js.map +2 -2
- package/dist/cli/index.js +113 -834
- package/dist/cli/index.js.map +3 -3
- package/dist/core/context/dual-stack-manager.js +1 -1
- package/dist/core/context/dual-stack-manager.js.map +1 -1
- package/dist/core/context/frame-manager.js +3 -0
- package/dist/core/context/frame-manager.js.map +2 -2
- package/dist/integrations/claude-code/subagent-client.js +106 -3
- package/dist/integrations/claude-code/subagent-client.js.map +2 -2
- package/dist/servers/railway/config.js +51 -0
- package/dist/servers/railway/config.js.map +7 -0
- package/dist/servers/railway/index-enhanced.js +156 -0
- package/dist/servers/railway/index-enhanced.js.map +7 -0
- package/dist/servers/railway/minimal.js +48 -3
- package/dist/servers/railway/minimal.js.map +2 -2
- package/dist/servers/railway/storage-test.js +455 -0
- package/dist/servers/railway/storage-test.js.map +7 -0
- package/dist/skills/claude-skills.js +13 -12
- package/dist/skills/claude-skills.js.map +2 -2
- package/dist/skills/recursive-agent-orchestrator.js +27 -18
- package/dist/skills/recursive-agent-orchestrator.js.map +2 -2
- package/dist/skills/unified-rlm-orchestrator.js.map +2 -2
- package/package.json +6 -18
- package/scripts/README-TESTING.md +186 -0
- package/scripts/analyze-cli-security.js +288 -0
- package/scripts/archive/add-phase-tasks-to-linear.js +163 -0
- package/scripts/archive/analyze-linear-duplicates.js +214 -0
- package/scripts/archive/analyze-remaining-duplicates.js +230 -0
- package/scripts/archive/analyze-sta-duplicates.js +292 -0
- package/scripts/archive/analyze-sta-graphql.js +399 -0
- package/scripts/archive/cancel-duplicate-tasks.ts +246 -0
- package/scripts/archive/check-all-duplicates.ts +419 -0
- package/scripts/archive/clean-duplicate-tasks.js +114 -0
- package/scripts/archive/cleanup-duplicate-tasks.ts +286 -0
- package/scripts/archive/create-phase-tasks.js +387 -0
- package/scripts/archive/delete-linear-duplicates.js +182 -0
- package/scripts/archive/delete-remaining-duplicates.js +158 -0
- package/scripts/archive/delete-sta-duplicates.js +201 -0
- package/scripts/archive/delete-sta-oauth.js +201 -0
- package/scripts/archive/export-sta-tasks.js +62 -0
- package/scripts/archive/install-auto-sync.js +266 -0
- package/scripts/archive/install-chromadb-hooks.sh +133 -0
- package/scripts/archive/install-enhanced-clear-hooks.sh +431 -0
- package/scripts/archive/install-post-task-hooks.sh +289 -0
- package/scripts/archive/install-stackmemory-hooks.sh +420 -0
- package/scripts/archive/merge-linear-duplicates-safe.ts +362 -0
- package/scripts/archive/merge-linear-duplicates.ts +180 -0
- package/scripts/archive/remove-sta-tasks.js +70 -0
- package/scripts/archive/setup-background-sync.sh +168 -0
- package/scripts/archive/setup-claude-auto-triggers.sh +181 -0
- package/scripts/archive/setup-claude-autostart.sh +305 -0
- package/scripts/archive/setup-git-hooks.sh +25 -0
- package/scripts/archive/setup-linear-oauth.sh +46 -0
- package/scripts/archive/setup-mcp.sh +113 -0
- package/scripts/archive/setup-railway-deployment.sh +81 -0
- package/scripts/auto-handoff.sh +262 -0
- package/scripts/background-sync-manager.js +416 -0
- package/scripts/benchmark-performance.ts +57 -0
- package/scripts/check-redis.ts +48 -0
- package/scripts/chromadb-auto-loader.sh +128 -0
- package/scripts/chromadb-context-loader.js +479 -0
- package/scripts/claude-chromadb-hook.js +460 -0
- package/scripts/claude-code-wrapper.sh +66 -0
- package/scripts/claude-linear-skill.js +455 -0
- package/scripts/claude-pre-commit.sh +302 -0
- package/scripts/claude-sm-autostart.js +532 -0
- package/scripts/claude-sm-setup.sh +367 -0
- package/scripts/claude-with-chromadb.sh +69 -0
- package/scripts/claude-worktree-manager.sh +323 -0
- package/scripts/claude-worktree-monitor.sh +371 -0
- package/scripts/claude-worktree-setup.sh +327 -0
- package/scripts/clean-linear-backlog.js +273 -0
- package/scripts/cleanup-old-sessions.sh +57 -0
- package/scripts/codex-wrapper.sh +88 -0
- package/scripts/create-sandbox.sh +269 -0
- package/scripts/debug-linear-update.js +174 -0
- package/scripts/delete-linear-tasks.js +167 -0
- package/scripts/deploy.sh +89 -0
- package/scripts/deployment/railway.sh +352 -0
- package/scripts/deployment/test-deployment.js +194 -0
- package/scripts/detect-and-rehydrate.js +162 -0
- package/scripts/detect-and-rehydrate.mjs +165 -0
- package/scripts/development/create-demo-tasks.js +143 -0
- package/scripts/development/debug-frame-test.js +16 -0
- package/scripts/development/demo-auto-sync.js +128 -0
- package/scripts/development/fix-all-imports.js +213 -0
- package/scripts/development/fix-imports.js +229 -0
- package/scripts/development/fix-lint-loop.cjs +103 -0
- package/scripts/development/fix-project-id.ts +161 -0
- package/scripts/development/fix-strict-mode-issues.ts +291 -0
- package/scripts/development/reorganize-structure.sh +228 -0
- package/scripts/development/test-persistence-direct.js +148 -0
- package/scripts/development/test-persistence.js +114 -0
- package/scripts/development/test-tasks.js +93 -0
- package/scripts/development/update-imports.js +212 -0
- package/scripts/fetch-linear-status.js +125 -0
- package/scripts/git-hooks/README.md +310 -0
- package/scripts/git-hooks/branch-context-manager.sh +342 -0
- package/scripts/git-hooks/post-checkout-stackmemory.sh +63 -0
- package/scripts/git-hooks/post-commit-stackmemory.sh +305 -0
- package/scripts/git-hooks/pre-commit-stackmemory.sh +275 -0
- package/scripts/hooks/cleanup-shell.sh +130 -0
- package/scripts/hooks/task-complete.sh +114 -0
- package/scripts/initialize.ts +129 -0
- package/scripts/install-claude-hooks-auto.js +104 -0
- package/scripts/install-claude-hooks.sh +133 -0
- package/scripts/install-global.sh +296 -0
- package/scripts/install.sh +235 -0
- package/scripts/linear-auto-sync.js +262 -0
- package/scripts/linear-auto-sync.sh +161 -0
- package/scripts/linear-sync-daemon.js +150 -0
- package/scripts/linear-task-review.js +237 -0
- package/scripts/list-linear-tasks.ts +178 -0
- package/scripts/mcp-proxy.js +66 -0
- package/scripts/opencode-wrapper.sh +85 -0
- package/scripts/publish-local.js +74 -0
- package/scripts/query-chromadb.ts +201 -0
- package/scripts/railway-env-setup.sh +39 -0
- package/scripts/reconcile-local-tasks.js +170 -0
- package/scripts/recreate-frames-db.js +89 -0
- package/scripts/setup/claude-integration.js +138 -0
- package/scripts/setup/configure-alias.js +125 -0
- package/scripts/setup/configure-codex-alias.js +161 -0
- package/scripts/setup/configure-opencode-alias.js +175 -0
- package/scripts/setup-claude-integration.js +204 -0
- package/scripts/setup-claude-integration.sh +183 -0
- package/scripts/setup.sh +31 -0
- package/scripts/show-linear-summary.ts +172 -0
- package/scripts/stackmemory-auto-handoff.sh +231 -0
- package/scripts/stackmemory-daemon.sh +40 -0
- package/scripts/start-linear-sync-daemon.sh +141 -0
- package/scripts/start-temporal-paradox.sh +214 -0
- package/scripts/status.ts +159 -0
- package/scripts/sync-and-clean-tasks.js +258 -0
- package/scripts/sync-frames-from-railway.js +228 -0
- package/scripts/sync-linear-graphql.js +303 -0
- package/scripts/sync-linear-tasks.js +186 -0
- package/scripts/test-auto-triggers.sh +57 -0
- package/scripts/test-browser-mcp.js +74 -0
- package/scripts/test-chromadb-full.js +115 -0
- package/scripts/test-chromadb-hooks.sh +28 -0
- package/scripts/test-chromadb-sync.ts +245 -0
- package/scripts/test-cli-security.js +293 -0
- package/scripts/test-hooks-persistence.sh +220 -0
- package/scripts/test-installation-scenarios.sh +359 -0
- package/scripts/test-installation.sh +224 -0
- package/scripts/test-mcp.js +163 -0
- package/scripts/test-pre-publish-quick.sh +75 -0
- package/scripts/test-quality-gates.sh +263 -0
- package/scripts/test-railway-db.js +222 -0
- package/scripts/test-redis-storage.ts +490 -0
- package/scripts/test-rlm-basic.sh +122 -0
- package/scripts/test-rlm-comprehensive.sh +260 -0
- package/scripts/test-rlm-e2e.sh +268 -0
- package/scripts/test-rlm-simple.js +90 -0
- package/scripts/test-rlm.js +110 -0
- package/scripts/test-session-handoff.sh +165 -0
- package/scripts/test-shell-integration.sh +275 -0
- package/scripts/testing/ab-test-runner.ts +508 -0
- package/scripts/testing/collect-metrics.ts +457 -0
- package/scripts/testing/quick-effectiveness-demo.js +187 -0
- package/scripts/testing/real-performance-test.js +422 -0
- package/scripts/testing/run-effectiveness-tests.sh +176 -0
- package/scripts/testing/scripts/testing/ab-test-runner.js +363 -0
- package/scripts/testing/scripts/testing/collect-metrics.js +292 -0
- package/scripts/testing/simple-effectiveness-test.js +310 -0
- package/scripts/testing/src/core/context/context-bridge.js +253 -0
- package/scripts/testing/src/core/context/frame-manager.js +746 -0
- package/scripts/testing/src/core/context/shared-context-layer.js +437 -0
- package/scripts/testing/src/core/database/database-adapter.js +54 -0
- package/scripts/testing/src/core/errors/index.js +291 -0
- package/scripts/testing/src/core/errors/recovery.js +268 -0
- package/scripts/testing/src/core/monitoring/logger.js +145 -0
- package/scripts/testing/src/core/retrieval/context-retriever.js +516 -0
- package/scripts/testing/src/core/session/index.js +1 -0
- package/scripts/testing/src/core/session/session-manager.js +323 -0
- package/scripts/testing/src/core/trace/cli-trace-wrapper.js +140 -0
- package/scripts/testing/src/core/trace/db-trace-wrapper.js +251 -0
- package/scripts/testing/src/core/trace/debug-trace.js +398 -0
- package/scripts/testing/src/core/trace/index.js +120 -0
- package/scripts/testing/src/core/trace/linear-api-wrapper.js +204 -0
- package/scripts/update-linear-status.js +268 -0
- package/scripts/update-linear-tasks-fixed.js +284 -0
- package/templates/claude-hooks/hooks.json +5 -0
- package/templates/claude-hooks/on-clear.js +56 -0
- package/templates/claude-hooks/on-startup.js +56 -0
- package/templates/claude-hooks/tool-use-trace.js +67 -0
- package/dist/features/tui/components/analytics-panel.js +0 -157
- package/dist/features/tui/components/analytics-panel.js.map +0 -7
- package/dist/features/tui/components/frame-visualizer.js +0 -377
- package/dist/features/tui/components/frame-visualizer.js.map +0 -7
- package/dist/features/tui/components/pr-tracker.js +0 -135
- package/dist/features/tui/components/pr-tracker.js.map +0 -7
- package/dist/features/tui/components/session-monitor.js +0 -299
- package/dist/features/tui/components/session-monitor.js.map +0 -7
- package/dist/features/tui/components/subagent-fleet.js +0 -395
- package/dist/features/tui/components/subagent-fleet.js.map +0 -7
- package/dist/features/tui/components/task-board.js +0 -1139
- package/dist/features/tui/components/task-board.js.map +0 -7
- package/dist/features/tui/index.js +0 -408
- package/dist/features/tui/index.js.map +0 -7
- package/dist/features/tui/services/data-service.js +0 -641
- package/dist/features/tui/services/data-service.js.map +0 -7
- package/dist/features/tui/services/linear-task-reader.js +0 -102
- package/dist/features/tui/services/linear-task-reader.js.map +0 -7
- package/dist/features/tui/services/websocket-client.js +0 -162
- package/dist/features/tui/services/websocket-client.js.map +0 -7
- package/dist/features/tui/terminal-compat.js +0 -220
- package/dist/features/tui/terminal-compat.js.map +0 -7
- package/dist/features/tui/types.js +0 -1
- package/dist/features/tui/types.js.map +0 -7
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/core/context/frame-manager.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * StackMemory Frame Manager - Call Stack Implementation\n * Manages nested frames representing the call stack of work\n */\n\nimport Database from 'better-sqlite3';\nimport { v4 as uuidv4 } from 'uuid';\nimport { logger } from '../monitoring/logger.js';\nimport { trace } from '../trace/index.js';\nimport {\n DatabaseError,\n FrameError,\n SystemError,\n ErrorCode,\n wrapError,\n createErrorHandler,\n} from '../errors/index.js';\nimport { retry, withTimeout } from '../errors/recovery.js';\nimport { sessionManager, FrameQueryMode } from '../session/index.js';\nimport { contextBridge } from './context-bridge.js';\n\n// Constants for frame validation\nconst MAX_FRAME_DEPTH = 100; // Maximum allowed frame depth\nconst DEFAULT_MAX_DEPTH = 100; // Default if not configured\n\n// Type-safe environment variable access\nfunction getEnv(key: string, defaultValue?: string): string {\n const value = process.env[key];\n if (value === undefined) {\n if (defaultValue !== undefined) return defaultValue;\n throw new Error(`Environment variable ${key} is required`);\n }\n return value;\n}\n\nfunction getOptionalEnv(key: string): string | undefined {\n return process.env[key];\n}\n\n// Frame types based on architecture\nexport type FrameType =\n | 'task'\n | 'subtask'\n | 'tool_scope'\n | 'review'\n | 'write'\n | 'debug';\nexport type FrameState = 'active' | 'closed';\n\nexport interface Frame {\n frame_id: string;\n run_id: string;\n project_id: string;\n parent_frame_id?: string;\n depth: number;\n type: FrameType;\n name: string;\n state: FrameState;\n inputs: Record<string, any>;\n outputs: Record<string, any>;\n digest_text?: string;\n digest_json: Record<string, any>;\n created_at: number;\n closed_at?: number;\n}\n\nexport interface FrameContext {\n frameId: string;\n header: {\n goal: string;\n constraints?: string[];\n definitions?: Record<string, string>;\n };\n anchors: Anchor[];\n recentEvents: Event[];\n activeArtifacts: string[];\n}\n\nexport interface Anchor {\n anchor_id: string;\n frame_id: string;\n type:\n | 'FACT'\n | 'DECISION'\n | 'CONSTRAINT'\n | 'INTERFACE_CONTRACT'\n | 'TODO'\n | 'RISK';\n text: string;\n priority: number;\n metadata: Record<string, any>;\n}\n\nexport interface Event {\n event_id: string;\n frame_id: string;\n run_id: string;\n seq: number;\n event_type:\n | 'user_message'\n | 'assistant_message'\n | 'tool_call'\n | 'tool_result'\n | 'decision'\n | 'constraint'\n | 'artifact'\n | 'observation';\n payload: Record<string, any>;\n ts: number;\n}\n\nexport interface FrameManagerOptions {\n skipContextBridge?: boolean;\n runId?: string;\n maxFrameDepth?: number; // Maximum allowed frame depth (default: 100)\n}\n\nexport class FrameManager {\n private db: Database.Database;\n private currentRunId: string;\n private sessionId: string;\n private projectId: string;\n private activeStack: string[] = []; // Stack of active frame IDs\n private queryMode: FrameQueryMode = FrameQueryMode.PROJECT_ACTIVE;\n private maxFrameDepth: number = DEFAULT_MAX_DEPTH;\n\n constructor(\n db: Database.Database,\n projectId: string,\n runIdOrOptions?: string | FrameManagerOptions\n ) {\n this.db = db;\n this.projectId = projectId;\n\n // Handle both legacy string runId and new options object\n let runId: string | undefined;\n let skipContextBridge = false;\n\n if (typeof runIdOrOptions === 'string') {\n runId = runIdOrOptions;\n } else if (runIdOrOptions) {\n runId = runIdOrOptions.runId;\n skipContextBridge = runIdOrOptions.skipContextBridge || false;\n this.maxFrameDepth = runIdOrOptions.maxFrameDepth || DEFAULT_MAX_DEPTH;\n }\n\n // Use session manager for run ID if available\n const session = sessionManager.getCurrentSession();\n if (session) {\n this.currentRunId = session.runId;\n this.sessionId = session.sessionId;\n } else {\n this.currentRunId = runId || uuidv4();\n this.sessionId = this.currentRunId; // Fallback for legacy behavior\n }\n\n this.initializeSchema();\n this.loadActiveStack();\n\n // Initialize context bridge for automatic shared context\n // Skip in test environment, when explicitly requested, or for CLI usage\n const shouldInitializeBridge =\n !skipContextBridge &&\n process.env['NODE_ENV'] !== 'test' &&\n !process.env['VITEST'] &&\n !process.env['STACKMEMORY_CLI'];\n\n if (shouldInitializeBridge) {\n contextBridge\n .initialize(this, {\n autoSync: true,\n syncInterval: 60000, // 1 minute\n minFrameScore: 0.5, // Sync frames above 0.5 score\n importantTags: ['decision', 'error', 'milestone', 'learning'],\n })\n .catch((error) => {\n logger.warn('Failed to initialize context bridge', { error });\n });\n }\n }\n\n setQueryMode(mode: FrameQueryMode): void {\n this.queryMode = mode;\n this.loadActiveStack(); // Reload with new mode\n }\n\n private initializeSchema() {\n const errorHandler = createErrorHandler({\n operation: 'initializeSchema',\n projectId: this.projectId,\n runId: this.currentRunId,\n });\n\n try {\n // Enhanced frames table matching architecture\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS frames (\n frame_id TEXT PRIMARY KEY,\n run_id TEXT NOT NULL,\n project_id TEXT NOT NULL,\n parent_frame_id TEXT REFERENCES frames(frame_id),\n depth INTEGER NOT NULL DEFAULT 0,\n type TEXT NOT NULL,\n name TEXT NOT NULL,\n state TEXT DEFAULT 'active',\n inputs TEXT DEFAULT '{}',\n outputs TEXT DEFAULT '{}',\n digest_text TEXT,\n digest_json TEXT DEFAULT '{}',\n created_at INTEGER DEFAULT (unixepoch()),\n closed_at INTEGER\n );\n\n CREATE TABLE IF NOT EXISTS events (\n event_id TEXT PRIMARY KEY,\n run_id TEXT NOT NULL,\n frame_id TEXT NOT NULL,\n seq INTEGER NOT NULL,\n event_type TEXT NOT NULL,\n payload TEXT NOT NULL,\n ts INTEGER DEFAULT (unixepoch()),\n FOREIGN KEY(frame_id) REFERENCES frames(frame_id)\n );\n\n CREATE TABLE IF NOT EXISTS anchors (\n anchor_id TEXT PRIMARY KEY,\n frame_id TEXT NOT NULL,\n project_id TEXT NOT NULL,\n type TEXT NOT NULL,\n text TEXT NOT NULL,\n priority INTEGER DEFAULT 0,\n created_at INTEGER DEFAULT (unixepoch()),\n metadata TEXT DEFAULT '{}',\n FOREIGN KEY(frame_id) REFERENCES frames(frame_id)\n );\n\n CREATE TABLE IF NOT EXISTS handoff_requests (\n request_id TEXT PRIMARY KEY,\n source_stack_id TEXT NOT NULL,\n target_stack_id TEXT NOT NULL,\n frame_ids TEXT NOT NULL,\n status TEXT NOT NULL DEFAULT 'pending',\n created_at INTEGER DEFAULT (unixepoch()),\n expires_at INTEGER,\n target_user_id TEXT,\n message TEXT\n );\n\n CREATE INDEX IF NOT EXISTS idx_frames_run ON frames(run_id);\n CREATE INDEX IF NOT EXISTS idx_frames_parent ON frames(parent_frame_id);\n CREATE INDEX IF NOT EXISTS idx_frames_state ON frames(state);\n CREATE INDEX IF NOT EXISTS idx_events_frame ON events(frame_id);\n CREATE INDEX IF NOT EXISTS idx_events_seq ON events(frame_id, seq);\n CREATE INDEX IF NOT EXISTS idx_anchors_frame ON anchors(frame_id);\n CREATE INDEX IF NOT EXISTS idx_handoff_requests_status ON handoff_requests(status);\n CREATE INDEX IF NOT EXISTS idx_handoff_requests_target ON handoff_requests(target_stack_id);\n `);\n } catch (error: unknown) {\n const dbError = errorHandler(error, {\n operation: 'initializeSchema',\n schema: 'frames',\n });\n\n if (dbError instanceof DatabaseError) {\n throw new DatabaseError(\n 'Failed to initialize frame database schema',\n ErrorCode.DB_MIGRATION_FAILED,\n {\n projectId: this.projectId,\n operation: 'initializeSchema',\n originalError: error,\n },\n error instanceof Error ? error : undefined\n );\n }\n throw dbError;\n }\n }\n\n private loadActiveStack() {\n const errorHandler = createErrorHandler({\n operation: 'loadActiveStack',\n runId: this.currentRunId,\n projectId: this.projectId,\n });\n\n try {\n let query: string;\n let params: any[];\n\n // Build query based on query mode\n switch (this.queryMode) {\n case FrameQueryMode.ALL_ACTIVE:\n query = `\n SELECT frame_id, parent_frame_id, depth\n FROM frames\n WHERE state = 'active'\n ORDER BY created_at DESC, depth ASC\n `;\n params = [];\n break;\n\n case FrameQueryMode.PROJECT_ACTIVE:\n query = `\n SELECT frame_id, parent_frame_id, depth, run_id\n FROM frames\n WHERE state = 'active' AND project_id = ?\n ORDER BY created_at DESC, depth ASC\n `;\n params = [this.projectId];\n break;\n\n case FrameQueryMode.HISTORICAL:\n query = `\n SELECT frame_id, parent_frame_id, depth\n FROM frames\n WHERE project_id = ?\n ORDER BY created_at DESC, depth ASC\n `;\n params = [this.projectId];\n break;\n\n case FrameQueryMode.CURRENT_SESSION:\n default:\n query = `\n SELECT frame_id, parent_frame_id, depth\n FROM frames\n WHERE run_id = ? AND state = 'active'\n ORDER BY depth ASC\n `;\n params = [this.currentRunId];\n break;\n }\n\n const activeFrames = this.db.prepare(query).all(...params) as Frame[];\n\n // Rebuild stack order\n this.activeStack = this.buildStackOrder(activeFrames);\n\n logger.info('Loaded active stack', {\n runId: this.currentRunId,\n stackDepth: this.activeStack.length,\n activeFrames: this.activeStack,\n queryMode: this.queryMode,\n });\n } catch (error: unknown) {\n const dbError = errorHandler(error, {\n query: 'Frame loading query',\n runId: this.currentRunId,\n queryMode: this.queryMode,\n });\n\n if (dbError instanceof DatabaseError) {\n throw new DatabaseError(\n 'Failed to load active frame stack',\n ErrorCode.DB_QUERY_FAILED,\n {\n runId: this.currentRunId,\n projectId: this.projectId,\n operation: 'loadActiveStack',\n },\n error instanceof Error ? error : undefined\n );\n }\n throw dbError;\n }\n }\n\n private buildStackOrder(\n frames: Pick<Frame, 'frame_id' | 'parent_frame_id' | 'depth'>[]\n ): string[] {\n const stack: string[] = [];\n\n // Find root frame (no parent)\n const rootFrame = frames.find((f) => !f.parent_frame_id);\n if (!rootFrame) return [];\n\n // Build stack by following parent-child relationships\n let currentFrame = rootFrame;\n stack.push(currentFrame.frame_id);\n\n while (currentFrame) {\n const childFrame = frames.find(\n (f) => f.parent_frame_id === currentFrame.frame_id\n );\n if (!childFrame) break;\n stack.push(childFrame.frame_id);\n currentFrame = childFrame;\n }\n\n return stack;\n }\n\n /**\n * Create a new frame and push to stack\n */\n public createFrame(options: {\n type: FrameType;\n name: string;\n inputs?: Record<string, any>;\n parentFrameId?: string;\n }): string {\n return this._createFrame(options);\n }\n\n private _createFrame(options: {\n type: FrameType;\n name: string;\n inputs?: Record<string, any>;\n parentFrameId?: string;\n }): string {\n const frameId = uuidv4();\n const parentFrameId = options.parentFrameId || this.getCurrentFrameId();\n const depth = parentFrameId ? this.getFrameDepth(parentFrameId) + 1 : 0;\n\n // Check for depth limit\n if (depth > this.maxFrameDepth) {\n throw new FrameError(\n `Maximum frame depth exceeded: ${depth} > ${this.maxFrameDepth}`,\n ErrorCode.FRAME_STACK_OVERFLOW,\n {\n currentDepth: depth,\n maxDepth: this.maxFrameDepth,\n frameId,\n parentFrameId,\n frameName: options.name,\n }\n );\n }\n\n // Check for circular reference before creating frame\n if (parentFrameId) {\n const cycle = this.detectCycle(frameId, parentFrameId);\n if (cycle) {\n throw new FrameError(\n `Circular reference detected in frame hierarchy`,\n ErrorCode.FRAME_CYCLE_DETECTED,\n {\n frameId,\n parentFrameId,\n cycle,\n frameName: options.name,\n }\n );\n }\n }\n\n const frame: Omit<\n Frame,\n 'outputs' | 'digest_text' | 'digest_json' | 'closed_at'\n > = {\n frame_id: frameId,\n run_id: this.currentRunId,\n project_id: this.projectId,\n parent_frame_id: parentFrameId,\n depth,\n type: options.type,\n name: options.name,\n state: 'active',\n inputs: options.inputs || {},\n created_at: Math.floor(Date.now() / 1000),\n };\n\n try {\n this.db\n .prepare(\n `\n INSERT INTO frames (\n frame_id, run_id, project_id, parent_frame_id, depth, type, name, state, inputs, created_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `\n )\n .run(\n frame.frame_id,\n frame.run_id,\n frame.project_id,\n frame.parent_frame_id,\n frame.depth,\n frame.type,\n frame.name,\n frame.state,\n JSON.stringify(frame.inputs),\n frame.created_at\n );\n } catch (error: unknown) {\n throw new DatabaseError(\n `Failed to create frame: ${options.name}`,\n ErrorCode.DB_QUERY_FAILED,\n {\n frameId,\n frameType: options.type,\n frameName: options.name,\n parentFrameId,\n depth,\n operation: 'createFrame',\n },\n error instanceof Error ? error : undefined\n );\n }\n\n // Push to active stack\n this.activeStack.push(frameId);\n\n logger.info('Created frame', {\n frameId,\n type: options.type,\n name: options.name,\n depth,\n parentFrameId,\n stackDepth: this.activeStack.length,\n });\n\n return frameId;\n }\n\n /**\n * Close the current frame and generate digest\n */\n public closeFrame(frameId?: string, outputs?: Record<string, any>): void {\n this._closeFrame(frameId, outputs);\n }\n\n private _closeFrame(frameId?: string, outputs?: Record<string, any>): void {\n const targetFrameId = frameId || this.getCurrentFrameId();\n if (!targetFrameId) {\n throw new FrameError(\n 'No active frame to close',\n ErrorCode.FRAME_INVALID_STATE,\n {\n operation: 'closeFrame',\n activeStack: this.activeStack,\n stackDepth: this.activeStack.length,\n }\n );\n }\n\n // Get frame details\n const frame = this.getFrame(targetFrameId);\n if (!frame) {\n throw new FrameError(\n `Frame not found: ${targetFrameId}`,\n ErrorCode.FRAME_NOT_FOUND,\n {\n frameId: targetFrameId,\n operation: 'closeFrame',\n runId: this.currentRunId,\n }\n );\n }\n\n if (frame.state === 'closed') {\n logger.warn('Attempted to close already closed frame', {\n frameId: targetFrameId,\n });\n return;\n }\n\n // Generate digest before closing\n const digest = this.generateDigest(targetFrameId);\n const finalOutputs = { ...outputs, ...digest.structured };\n\n try {\n // Update frame to closed state\n this.db\n .prepare(\n `\n UPDATE frames\n SET state = 'closed',\n outputs = ?,\n digest_text = ?,\n digest_json = ?,\n closed_at = unixepoch()\n WHERE frame_id = ?\n `\n )\n .run(\n JSON.stringify(finalOutputs),\n digest.text,\n JSON.stringify(digest.structured),\n targetFrameId\n );\n } catch (error: unknown) {\n throw new DatabaseError(\n `Failed to close frame: ${targetFrameId}`,\n ErrorCode.DB_QUERY_FAILED,\n {\n frameId: targetFrameId,\n frameName: frame.name,\n operation: 'closeFrame',\n },\n error instanceof Error ? error : undefined\n );\n }\n\n // Remove from active stack\n this.activeStack = this.activeStack.filter((id) => id !== targetFrameId);\n\n // Close all child frames recursively\n this.closeChildFrames(targetFrameId);\n\n logger.info('Closed frame', {\n frameId: targetFrameId,\n name: frame.name,\n duration: Math.floor(Date.now() / 1000) - frame.created_at,\n digestLength: digest.text.length,\n stackDepth: this.activeStack.length,\n });\n }\n\n /**\n * Delete a frame completely from the database (used in handoffs)\n */\n deleteFrame(frameId: string): void {\n try {\n // First delete related data\n this.db.prepare('DELETE FROM events WHERE frame_id = ?').run(frameId);\n this.db.prepare('DELETE FROM anchors WHERE frame_id = ?').run(frameId);\n\n // Remove from active stack if present\n this.activeStack = this.activeStack.filter((id) => id !== frameId);\n\n // Delete the frame itself\n this.db.prepare('DELETE FROM frames WHERE frame_id = ?').run(frameId);\n\n logger.debug('Deleted frame completely', { frameId });\n } catch (error: unknown) {\n logger.error('Failed to delete frame', { frameId, error });\n throw error;\n }\n }\n\n private closeChildFrames(parentFrameId: string) {\n try {\n const children = this.db\n .prepare(\n `\n SELECT frame_id FROM frames\n WHERE parent_frame_id = ? AND state = 'active'\n `\n )\n .all(parentFrameId) as { frame_id: string }[];\n\n children.forEach((child) => {\n try {\n this.closeFrame(child.frame_id);\n } catch (error: unknown) {\n logger.error(\n 'Failed to close child frame',\n error instanceof Error ? error : new Error(String(error)),\n {\n parentFrameId,\n childFrameId: child.frame_id,\n }\n );\n }\n });\n } catch (error: unknown) {\n throw new DatabaseError(\n `Failed to close child frames for parent: ${parentFrameId}`,\n ErrorCode.DB_QUERY_FAILED,\n {\n parentFrameId,\n operation: 'closeChildFrames',\n },\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Generate digest for a frame\n */\n private generateDigest(frameId: string): {\n text: string;\n structured: Record<string, any>;\n } {\n const frame = this.getFrame(frameId);\n const events = this.getFrameEvents(frameId);\n const anchors = this.getFrameAnchors(frameId);\n\n if (!frame) {\n throw new FrameError(\n `Cannot generate digest: frame not found ${frameId}`,\n ErrorCode.FRAME_NOT_FOUND,\n {\n frameId,\n operation: 'generateDigest',\n runId: this.currentRunId,\n }\n );\n }\n\n // Extract key information\n const decisions = anchors.filter((a) => a.type === 'DECISION');\n const constraints = anchors.filter((a) => a.type === 'CONSTRAINT');\n const risks = anchors.filter((a) => a.type === 'RISK');\n\n const toolCalls = events.filter((e) => e.event_type === 'tool_call');\n const artifacts = events.filter((e) => e.event_type === 'artifact');\n\n // Generate structured digest\n const structured = {\n result: frame.name,\n decisions: decisions.map((d) => ({ id: d.anchor_id, text: d.text })),\n constraints: constraints.map((c) => ({ id: c.anchor_id, text: c.text })),\n risks: risks.map((r) => ({ id: r.anchor_id, text: r.text })),\n artifacts: artifacts.map((a) => ({\n kind: a.payload.kind || 'unknown',\n ref: a.payload.ref,\n })),\n tool_calls_count: toolCalls.length,\n duration_seconds: frame.closed_at\n ? frame.closed_at - frame.created_at\n : 0,\n };\n\n // Generate text summary\n const text = this.generateDigestText(frame, structured, events.length);\n\n return { text, structured };\n }\n\n private generateDigestText(\n frame: Frame,\n structured: any,\n eventCount: number\n ): string {\n let summary = `Completed: ${frame.name}\\n`;\n\n if (structured.decisions.length > 0) {\n summary += `\\nDecisions made:\\n${structured.decisions.map((d: any) => `- ${d.text}`).join('\\n')}`;\n }\n\n if (structured.constraints.length > 0) {\n summary += `\\nConstraints established:\\n${structured.constraints.map((c: any) => `- ${c.text}`).join('\\n')}`;\n }\n\n if (structured.risks.length > 0) {\n summary += `\\nRisks identified:\\n${structured.risks.map((r: any) => `- ${r.text}`).join('\\n')}`;\n }\n\n summary += `\\nActivity: ${eventCount} events, ${structured.tool_calls_count} tool calls`;\n\n if (structured.duration_seconds > 0) {\n summary += `, ${Math.floor(structured.duration_seconds / 60)}m ${structured.duration_seconds % 60}s duration`;\n }\n\n return summary;\n }\n\n /**\n * Add event to current frame\n */\n public addEvent(\n eventType: Event['event_type'],\n payload: Record<string, any>,\n frameId?: string\n ): string {\n const targetFrameId = frameId || this.getCurrentFrameId();\n if (!targetFrameId) {\n throw new FrameError(\n 'No active frame for event',\n ErrorCode.FRAME_INVALID_STATE,\n {\n operation: 'addEvent',\n eventType,\n activeStack: this.activeStack,\n }\n );\n }\n\n const eventId = uuidv4();\n const seq = this.getNextEventSequence(targetFrameId);\n\n try {\n this.db\n .prepare(\n `\n INSERT INTO events (event_id, run_id, frame_id, seq, event_type, payload)\n VALUES (?, ?, ?, ?, ?, ?)\n `\n )\n .run(\n eventId,\n this.currentRunId,\n targetFrameId,\n seq,\n eventType,\n JSON.stringify(payload)\n );\n } catch (error: unknown) {\n throw new DatabaseError(\n `Failed to add event to frame: ${targetFrameId}`,\n ErrorCode.DB_QUERY_FAILED,\n {\n eventId,\n frameId: targetFrameId,\n eventType,\n seq,\n operation: 'addEvent',\n },\n error instanceof Error ? error : undefined\n );\n }\n\n return eventId;\n }\n\n /**\n * Add anchor to frame\n */\n public addAnchor(\n type: Anchor['type'],\n text: string,\n priority: number = 0,\n metadata: Record<string, any> = {},\n frameId?: string\n ): string {\n const targetFrameId = frameId || this.getCurrentFrameId();\n if (!targetFrameId) {\n throw new FrameError(\n 'No active frame for anchor',\n ErrorCode.FRAME_INVALID_STATE,\n {\n operation: 'addAnchor',\n anchorType: type,\n text: text.substring(0, 100),\n activeStack: this.activeStack,\n }\n );\n }\n\n const anchorId = uuidv4();\n\n try {\n this.db\n .prepare(\n `\n INSERT INTO anchors (anchor_id, frame_id, project_id, type, text, priority, metadata)\n VALUES (?, ?, ?, ?, ?, ?, ?)\n `\n )\n .run(\n anchorId,\n targetFrameId,\n this.projectId,\n type,\n text,\n priority,\n JSON.stringify(metadata)\n );\n } catch (error: unknown) {\n throw new DatabaseError(\n `Failed to add anchor to frame: ${targetFrameId}`,\n ErrorCode.DB_QUERY_FAILED,\n {\n anchorId,\n frameId: targetFrameId,\n anchorType: type,\n operation: 'addAnchor',\n },\n error instanceof Error ? error : undefined\n );\n }\n\n return anchorId;\n }\n\n /**\n * Get hot stack context for current active frames\n */\n public getHotStackContext(maxEvents: number = 20): FrameContext[] {\n return this.activeStack\n .map((frameId) => {\n const frame = this.getFrame(frameId);\n if (!frame) return null;\n\n return {\n frameId,\n header: {\n goal: frame.name,\n constraints: this.extractConstraints(frame.inputs),\n definitions: frame.inputs.definitions,\n },\n anchors: this.getFrameAnchors(frameId),\n recentEvents: this.getFrameEvents(frameId, maxEvents),\n activeArtifacts: this.getActiveArtifacts(frameId),\n };\n })\n .filter(Boolean) as FrameContext[];\n }\n\n /**\n * Get active frame path (root to current)\n */\n public getActiveFramePath(): Frame[] {\n return this.activeStack\n .map((frameId) => this.getFrame(frameId))\n .filter(Boolean) as Frame[];\n }\n\n // Utility methods\n public getCurrentFrameId(): string | undefined {\n return this.activeStack[this.activeStack.length - 1];\n }\n\n public getStackDepth(): number {\n return this.activeStack.length;\n }\n\n /**\n * Get recent frames for context sharing\n */\n public async getRecentFrames(limit: number = 100): Promise<Frame[]> {\n try {\n const rows = this.db\n .prepare(\n `\n SELECT * FROM frames \n WHERE project_id = ?\n ORDER BY created_at DESC\n LIMIT ?\n `\n )\n .all(this.projectId, limit) as any[];\n\n return rows.map((row) => ({\n ...row,\n frameId: row.frame_id,\n runId: row.run_id,\n projectId: row.project_id,\n parentFrameId: row.parent_frame_id,\n title: row.name,\n timestamp: row.created_at,\n metadata: {\n tags: this.extractTagsFromFrame(row),\n importance: this.calculateFrameImportance(row),\n },\n data: {\n inputs: JSON.parse(row.inputs || '{}'),\n outputs: JSON.parse(row.outputs || '{}'),\n digest: JSON.parse(row.digest_json || '{}'),\n },\n inputs: JSON.parse(row.inputs || '{}'),\n outputs: JSON.parse(row.outputs || '{}'),\n digest_json: JSON.parse(row.digest_json || '{}'),\n }));\n } catch (error: unknown) {\n logger.error('Failed to get recent frames', error as Error);\n return [];\n }\n }\n\n /**\n * Add context metadata to the current frame\n */\n public async addContext(key: string, value: any): Promise<void> {\n const currentFrameId = this.getCurrentFrameId();\n if (!currentFrameId) return;\n\n try {\n const frame = this.getFrame(currentFrameId);\n if (!frame) return;\n\n const metadata = frame.outputs || {};\n metadata[key] = value;\n\n this.db\n .prepare(`UPDATE frames SET outputs = ? WHERE frame_id = ?`)\n .run(JSON.stringify(metadata), currentFrameId);\n } catch (error: unknown) {\n logger.warn('Failed to add context to frame', { error, key });\n }\n }\n\n private extractTagsFromFrame(frame: any): string[] {\n const tags: string[] = [];\n\n // Add type as tag\n if (frame.type) tags.push(frame.type);\n\n // Extract tags from name\n if (frame.name) {\n if (frame.name.toLowerCase().includes('error')) tags.push('error');\n if (frame.name.toLowerCase().includes('fix')) tags.push('resolution');\n if (frame.name.toLowerCase().includes('decision')) tags.push('decision');\n if (frame.name.toLowerCase().includes('milestone'))\n tags.push('milestone');\n }\n\n // Extract from digest\n try {\n const digest = JSON.parse(frame.digest_json || '{}');\n if (digest.tags) tags.push(...digest.tags);\n } catch {}\n\n return [...new Set(tags)];\n }\n\n private calculateFrameImportance(frame: any): 'high' | 'medium' | 'low' {\n // Milestones and decisions are high importance\n if (frame.type === 'milestone' || frame.name?.includes('decision'))\n return 'high';\n\n // Errors and resolutions are medium importance\n if (frame.type === 'error' || frame.type === 'resolution') return 'medium';\n\n // Long-running frames are potentially important\n if (frame.closed_at && frame.created_at) {\n const duration = frame.closed_at - frame.created_at;\n if (duration > 300) return 'medium'; // More than 5 minutes\n }\n\n return 'low';\n }\n\n private getFrameDepth(frameId: string): number {\n const frame = this.getFrame(frameId);\n return frame?.depth || 0;\n }\n\n public getFrame(frameId: string): Frame | undefined {\n try {\n const row = this.db\n .prepare(\n `\n SELECT * FROM frames WHERE frame_id = ?\n `\n )\n .get(frameId) as any;\n\n if (!row) return undefined;\n\n return {\n ...row,\n inputs: JSON.parse(row.inputs || '{}'),\n outputs: JSON.parse(row.outputs || '{}'),\n digest_json: JSON.parse(row.digest_json || '{}'),\n };\n } catch (error: unknown) {\n // Log the error but return undefined instead of throwing\n logger.warn(`Failed to get frame: ${frameId}`, {\n error: error instanceof Error ? error.message : String(error),\n frameId,\n operation: 'getFrame',\n });\n return undefined;\n }\n }\n\n public getFrameEvents(frameId: string, limit?: number): Event[] {\n try {\n const query = limit\n ? `SELECT * FROM events WHERE frame_id = ? ORDER BY seq DESC LIMIT ?`\n : `SELECT * FROM events WHERE frame_id = ? ORDER BY seq ASC`;\n\n const params = limit ? [frameId, limit] : [frameId];\n const rows = this.db.prepare(query).all(...params) as any[];\n\n return rows.map((row) => ({\n ...row,\n payload: JSON.parse(row.payload),\n }));\n } catch (error: unknown) {\n throw new DatabaseError(\n `Failed to get frame events: ${frameId}`,\n ErrorCode.DB_QUERY_FAILED,\n {\n frameId,\n limit,\n operation: 'getFrameEvents',\n },\n error instanceof Error ? error : undefined\n );\n }\n }\n\n private getFrameAnchors(frameId: string): Anchor[] {\n try {\n const rows = this.db\n .prepare(\n `\n SELECT * FROM anchors WHERE frame_id = ? ORDER BY priority DESC, created_at ASC\n `\n )\n .all(frameId) as any[];\n\n return rows.map((row) => ({\n ...row,\n metadata: JSON.parse(row.metadata || '{}'),\n }));\n } catch (error: unknown) {\n throw new DatabaseError(\n `Failed to get frame anchors: ${frameId}`,\n ErrorCode.DB_QUERY_FAILED,\n {\n frameId,\n operation: 'getFrameAnchors',\n },\n error instanceof Error ? error : undefined\n );\n }\n }\n\n private getNextEventSequence(frameId: string): number {\n try {\n const result = this.db\n .prepare(\n `\n SELECT MAX(seq) as max_seq FROM events WHERE frame_id = ?\n `\n )\n .get(frameId) as { max_seq: number | null };\n\n return (result.max_seq || 0) + 1;\n } catch (error: unknown) {\n throw new DatabaseError(\n `Failed to get next event sequence for frame: ${frameId}`,\n ErrorCode.DB_QUERY_FAILED,\n {\n frameId,\n operation: 'getNextEventSequence',\n },\n error instanceof Error ? error : undefined\n );\n }\n }\n\n private extractConstraints(\n inputs: Record<string, any>\n ): string[] | undefined {\n return inputs.constraints;\n }\n\n private getActiveArtifacts(frameId: string): string[] {\n const artifacts = this.getFrameEvents(frameId)\n .filter((e) => e.event_type === 'artifact')\n .map((e) => e.payload.ref)\n .filter(Boolean);\n\n return artifacts;\n }\n\n /**\n * Detect if setting a parent frame would create a cycle in the frame hierarchy.\n * Returns the cycle path if detected, or null if no cycle.\n * @param childFrameId - The frame that would be the child\n * @param parentFrameId - The proposed parent frame\n * @returns Array of frame IDs forming the cycle, or null if no cycle\n */\n private detectCycle(\n childFrameId: string,\n parentFrameId: string\n ): string[] | null {\n const visited = new Set<string>();\n const path: string[] = [];\n\n // Start from the proposed parent and traverse up the hierarchy\n let currentId: string | undefined = parentFrameId;\n \n while (currentId) {\n // If we've seen this frame before, we have a cycle\n if (visited.has(currentId)) {\n // Build the cycle path\n const cycleStart = path.indexOf(currentId);\n return path.slice(cycleStart).concat(currentId);\n }\n\n // If the current frame is the child we're trying to add, it's a cycle\n if (currentId === childFrameId) {\n return path.concat([currentId, childFrameId]);\n }\n\n visited.add(currentId);\n path.push(currentId);\n\n // Move to the parent of current frame\n const frame = this.getFrame(currentId);\n if (!frame) {\n // Frame not found, no cycle possible through this path\n break;\n }\n currentId = frame.parent_frame_id;\n\n // Safety check: if we've traversed too many levels, something is wrong\n if (path.length > this.maxFrameDepth) {\n throw new FrameError(\n `Frame hierarchy traversal exceeded maximum depth during cycle detection`,\n ErrorCode.FRAME_STACK_OVERFLOW,\n {\n depth: path.length,\n maxDepth: this.maxFrameDepth,\n path,\n }\n );\n }\n }\n\n return null; // No cycle detected\n }\n\n /**\n * Update parent frame of an existing frame (with cycle detection)\n * @param frameId - The frame to update\n * @param newParentFrameId - The new parent frame ID\n */\n public updateParentFrame(frameId: string, newParentFrameId: string | null): void {\n // Check if frame exists\n const frame = this.getFrame(frameId);\n if (!frame) {\n throw new FrameError(\n `Frame not found: ${frameId}`,\n ErrorCode.FRAME_NOT_FOUND,\n { frameId }\n );\n }\n\n // If setting a parent, check for cycles\n if (newParentFrameId) {\n const cycle = this.detectCycle(frameId, newParentFrameId);\n if (cycle) {\n throw new FrameError(\n `Cannot set parent: would create circular reference`,\n ErrorCode.FRAME_CYCLE_DETECTED,\n {\n frameId,\n newParentFrameId,\n cycle,\n currentParentId: frame.parent_frame_id,\n }\n );\n }\n\n // Check depth after parent change\n const newParentFrame = this.getFrame(newParentFrameId);\n if (newParentFrame) {\n const newDepth = newParentFrame.depth + 1;\n if (newDepth > this.maxFrameDepth) {\n throw new FrameError(\n `Cannot set parent: would exceed maximum frame depth`,\n ErrorCode.FRAME_STACK_OVERFLOW,\n {\n frameId,\n newParentFrameId,\n newDepth,\n maxDepth: this.maxFrameDepth,\n }\n );\n }\n }\n }\n\n try {\n // Update the parent frame\n this.db\n .prepare(\n `UPDATE frames SET parent_frame_id = ? WHERE frame_id = ?`\n )\n .run(newParentFrameId, frameId);\n\n logger.info('Updated parent frame', {\n frameId,\n oldParentId: frame.parent_frame_id,\n newParentId: newParentFrameId,\n });\n } catch (error: unknown) {\n throw new DatabaseError(\n `Failed to update parent frame`,\n ErrorCode.DB_UPDATE_FAILED,\n {\n frameId,\n newParentFrameId,\n operation: 'updateParentFrame',\n },\n error instanceof Error ? error : undefined\n );\n }\n }\n}\n"],
|
|
5
|
-
"mappings": "AAMA,SAAS,MAAM,cAAc;AAC7B,SAAS,cAAc;AAEvB;AAAA,EACE;AAAA,EACA;AAAA,EAEA;AAAA,EAEA;AAAA,OACK;AAEP,SAAS,gBAAgB,sBAAsB;AAC/C,SAAS,qBAAqB;AAG9B,MAAM,kBAAkB;AACxB,MAAM,oBAAoB;AAG1B,SAAS,OAAO,KAAa,cAA+B;AAC1D,QAAM,QAAQ,QAAQ,IAAI,GAAG;AAC7B,MAAI,UAAU,QAAW;AACvB,QAAI,iBAAiB,OAAW,QAAO;AACvC,UAAM,IAAI,MAAM,wBAAwB,GAAG,cAAc;AAAA,EAC3D;AACA,SAAO;AACT;AAEA,SAAS,eAAe,KAAiC;AACvD,SAAO,QAAQ,IAAI,GAAG;AACxB;AAgFO,MAAM,aAAa;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAwB,CAAC;AAAA;AAAA,EACzB,YAA4B,eAAe;AAAA,EAC3C,gBAAwB;AAAA,EAEhC,YACE,IACA,WACA,gBACA;AACA,SAAK,KAAK;AACV,SAAK,YAAY;AAGjB,QAAI;AACJ,QAAI,oBAAoB;AAExB,QAAI,OAAO,mBAAmB,UAAU;AACtC,cAAQ;AAAA,IACV,WAAW,gBAAgB;AACzB,cAAQ,eAAe;AACvB,0BAAoB,eAAe,qBAAqB;AACxD,WAAK,gBAAgB,eAAe,iBAAiB;AAAA,IACvD;AAGA,UAAM,UAAU,eAAe,kBAAkB;AACjD,QAAI,SAAS;AACX,WAAK,eAAe,QAAQ;AAC5B,WAAK,YAAY,QAAQ;AAAA,IAC3B,OAAO;AACL,WAAK,eAAe,SAAS,OAAO;AACpC,WAAK,YAAY,KAAK;AAAA,IACxB;AAEA,SAAK,iBAAiB;AACtB,SAAK,gBAAgB;AAIrB,UAAM,yBACJ,CAAC,qBACD,QAAQ,IAAI,UAAU,MAAM,UAC5B,CAAC,QAAQ,IAAI,QAAQ,KACrB,CAAC,QAAQ,IAAI,iBAAiB;AAEhC,QAAI,wBAAwB;AAC1B,oBACG,WAAW,MAAM;AAAA,QAChB,UAAU;AAAA,QACV,cAAc;AAAA;AAAA,QACd,eAAe;AAAA;AAAA,QACf,eAAe,CAAC,YAAY,SAAS,aAAa,UAAU;AAAA,MAC9D,CAAC,EACA,MAAM,CAAC,UAAU;AAChB,eAAO,KAAK,uCAAuC,EAAE,MAAM,CAAC;AAAA,MAC9D,CAAC;AAAA,IACL;AAAA,EACF;AAAA,EAEA,aAAa,MAA4B;AACvC,SAAK,YAAY;AACjB,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEQ,mBAAmB;AACzB,UAAM,eAAe,mBAAmB;AAAA,MACtC,WAAW;AAAA,MACX,WAAW,KAAK;AAAA,MAChB,OAAO,KAAK;AAAA,IACd,CAAC;AAED,QAAI;AAEF,WAAK,GAAG,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OA6DZ;AAAA,IACH,SAAS,OAAgB;AACvB,YAAM,UAAU,aAAa,OAAO;AAAA,QAClC,WAAW;AAAA,QACX,QAAQ;AAAA,MACV,CAAC;AAED,UAAI,mBAAmB,eAAe;AACpC,cAAM,IAAI;AAAA,UACR;AAAA,UACA,UAAU;AAAA,UACV;AAAA,YACE,WAAW,KAAK;AAAA,YAChB,WAAW;AAAA,YACX,eAAe;AAAA,UACjB;AAAA,UACA,iBAAiB,QAAQ,QAAQ;AAAA,QACnC;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEQ,kBAAkB;AACxB,UAAM,eAAe,mBAAmB;AAAA,MACtC,WAAW;AAAA,MACX,OAAO,KAAK;AAAA,MACZ,WAAW,KAAK;AAAA,IAClB,CAAC;AAED,QAAI;AACF,UAAI;AACJ,UAAI;AAGJ,cAAQ,KAAK,WAAW;AAAA,QACtB,KAAK,eAAe;AAClB,kBAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAMR,mBAAS,CAAC;AACV;AAAA,QAEF,KAAK,eAAe;AAClB,kBAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAMR,mBAAS,CAAC,KAAK,SAAS;AACxB;AAAA,QAEF,KAAK,eAAe;AAClB,kBAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAMR,mBAAS,CAAC,KAAK,SAAS;AACxB;AAAA,QAEF,KAAK,eAAe;AAAA,QACpB;AACE,kBAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAMR,mBAAS,CAAC,KAAK,YAAY;AAC3B;AAAA,MACJ;AAEA,YAAM,eAAe,KAAK,GAAG,QAAQ,KAAK,EAAE,IAAI,GAAG,MAAM;AAGzD,WAAK,cAAc,KAAK,gBAAgB,YAAY;AAEpD,aAAO,KAAK,uBAAuB;AAAA,QACjC,OAAO,KAAK;AAAA,QACZ,YAAY,KAAK,YAAY;AAAA,QAC7B,cAAc,KAAK;AAAA,QACnB,WAAW,KAAK;AAAA,MAClB,CAAC;AAAA,IACH,SAAS,OAAgB;AACvB,YAAM,UAAU,aAAa,OAAO;AAAA,QAClC,OAAO;AAAA,QACP,OAAO,KAAK;AAAA,QACZ,WAAW,KAAK;AAAA,MAClB,CAAC;AAED,UAAI,mBAAmB,eAAe;AACpC,cAAM,IAAI;AAAA,UACR;AAAA,UACA,UAAU;AAAA,UACV;AAAA,YACE,OAAO,KAAK;AAAA,YACZ,WAAW,KAAK;AAAA,YAChB,WAAW;AAAA,UACb;AAAA,UACA,iBAAiB,QAAQ,QAAQ;AAAA,QACnC;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEQ,gBACN,QACU;AACV,UAAM,QAAkB,CAAC;AAGzB,UAAM,YAAY,OAAO,KAAK,CAAC,MAAM,CAAC,EAAE,eAAe;AACvD,QAAI,CAAC,UAAW,QAAO,CAAC;AAGxB,QAAI,eAAe;AACnB,UAAM,KAAK,aAAa,QAAQ;AAEhC,WAAO,cAAc;AACnB,YAAM,aAAa,OAAO;AAAA,QACxB,CAAC,MAAM,EAAE,oBAAoB,aAAa;AAAA,MAC5C;AACA,UAAI,CAAC,WAAY;AACjB,YAAM,KAAK,WAAW,QAAQ;AAC9B,qBAAe;AAAA,IACjB;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKO,YAAY,SAKR;AACT,WAAO,KAAK,aAAa,OAAO;AAAA,EAClC;AAAA,EAEQ,aAAa,SAKV;AACT,UAAM,UAAU,OAAO;AACvB,UAAM,gBAAgB,QAAQ,iBAAiB,KAAK,kBAAkB;AACtE,UAAM,QAAQ,gBAAgB,KAAK,cAAc,aAAa,IAAI,IAAI;AAGtE,QAAI,QAAQ,KAAK,eAAe;AAC9B,YAAM,IAAI;AAAA,QACR,iCAAiC,KAAK,MAAM,KAAK,aAAa;AAAA,QAC9D,UAAU;AAAA,QACV;AAAA,UACE,cAAc;AAAA,UACd,UAAU,KAAK;AAAA,UACf;AAAA,UACA;AAAA,UACA,WAAW,QAAQ;AAAA,QACrB;AAAA,MACF;AAAA,IACF;AAGA,QAAI,eAAe;AACjB,YAAM,QAAQ,KAAK,YAAY,SAAS,aAAa;AACrD,UAAI,OAAO;AACT,cAAM,IAAI;AAAA,UACR;AAAA,UACA,UAAU;AAAA,UACV;AAAA,YACE;AAAA,YACA;AAAA,YACA;AAAA,YACA,WAAW,QAAQ;AAAA,UACrB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,UAAM,QAGF;AAAA,MACF,UAAU;AAAA,MACV,QAAQ,KAAK;AAAA,MACb,YAAY,KAAK;AAAA,MACjB,iBAAiB;AAAA,MACjB;AAAA,MACA,MAAM,QAAQ;AAAA,MACd,MAAM,QAAQ;AAAA,MACd,OAAO;AAAA,MACP,QAAQ,QAAQ,UAAU,CAAC;AAAA,MAC3B,YAAY,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AAAA,IAC1C;AAEA,QAAI;AACF,WAAK,GACF;AAAA,QACC;AAAA;AAAA;AAAA;AAAA;AAAA,MAKF,EACC;AAAA,QACC,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,QACN,KAAK,UAAU,MAAM,MAAM;AAAA,QAC3B,MAAM;AAAA,MACR;AAAA,IACJ,SAAS,OAAgB;AACvB,YAAM,IAAI;AAAA,QACR,2BAA2B,QAAQ,IAAI;AAAA,QACvC,UAAU;AAAA,QACV;AAAA,UACE;AAAA,UACA,WAAW,QAAQ;AAAA,UACnB,WAAW,QAAQ;AAAA,UACnB;AAAA,UACA;AAAA,UACA,WAAW;AAAA,QACb;AAAA,QACA,iBAAiB,QAAQ,QAAQ;AAAA,MACnC;AAAA,IACF;AAGA,SAAK,YAAY,KAAK,OAAO;AAE7B,WAAO,KAAK,iBAAiB;AAAA,MAC3B;AAAA,MACA,MAAM,QAAQ;AAAA,MACd,MAAM,QAAQ;AAAA,MACd;AAAA,MACA;AAAA,MACA,YAAY,KAAK,YAAY;AAAA,IAC/B,CAAC;AAED,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKO,WAAW,SAAkB,SAAqC;AACvE,SAAK,YAAY,SAAS,OAAO;AAAA,EACnC;AAAA,EAEQ,YAAY,SAAkB,SAAqC;AACzE,UAAM,gBAAgB,WAAW,KAAK,kBAAkB;AACxD,QAAI,CAAC,eAAe;AAClB,YAAM,IAAI;AAAA,QACR;AAAA,QACA,UAAU;AAAA,QACV;AAAA,UACE,WAAW;AAAA,UACX,aAAa,KAAK;AAAA,UAClB,YAAY,KAAK,YAAY;AAAA,QAC/B;AAAA,MACF;AAAA,IACF;AAGA,UAAM,QAAQ,KAAK,SAAS,aAAa;AACzC,QAAI,CAAC,OAAO;AACV,YAAM,IAAI;AAAA,QACR,oBAAoB,aAAa;AAAA,QACjC,UAAU;AAAA,QACV;AAAA,UACE,SAAS;AAAA,UACT,WAAW;AAAA,UACX,OAAO,KAAK;AAAA,QACd;AAAA,MACF;AAAA,IACF;AAEA,QAAI,MAAM,UAAU,UAAU;AAC5B,aAAO,KAAK,2CAA2C;AAAA,QACrD,SAAS;AAAA,MACX,CAAC;AACD;AAAA,IACF;AAGA,UAAM,SAAS,KAAK,eAAe,aAAa;AAChD,UAAM,eAAe,EAAE,GAAG,SAAS,GAAG,OAAO,WAAW;AAExD,QAAI;AAEF,WAAK,GACF;AAAA,QACC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MASF,EACC;AAAA,QACC,KAAK,UAAU,YAAY;AAAA,QAC3B,OAAO;AAAA,QACP,KAAK,UAAU,OAAO,UAAU;AAAA,QAChC;AAAA,MACF;AAAA,IACJ,SAAS,OAAgB;AACvB,YAAM,IAAI;AAAA,QACR,0BAA0B,aAAa;AAAA,QACvC,UAAU;AAAA,QACV;AAAA,UACE,SAAS;AAAA,UACT,WAAW,MAAM;AAAA,UACjB,WAAW;AAAA,QACb;AAAA,QACA,iBAAiB,QAAQ,QAAQ;AAAA,MACnC;AAAA,IACF;AAGA,SAAK,cAAc,KAAK,YAAY,OAAO,CAAC,OAAO,OAAO,aAAa;AAGvE,SAAK,iBAAiB,aAAa;AAEnC,WAAO,KAAK,gBAAgB;AAAA,MAC1B,SAAS;AAAA,MACT,MAAM,MAAM;AAAA,MACZ,UAAU,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,IAAI,MAAM;AAAA,MAChD,cAAc,OAAO,KAAK;AAAA,MAC1B,YAAY,KAAK,YAAY;AAAA,IAC/B,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,SAAuB;AACjC,QAAI;AAEF,WAAK,GAAG,QAAQ,uCAAuC,EAAE,IAAI,OAAO;AACpE,WAAK,GAAG,QAAQ,wCAAwC,EAAE,IAAI,OAAO;AAGrE,WAAK,cAAc,KAAK,YAAY,OAAO,CAAC,OAAO,OAAO,OAAO;AAGjE,WAAK,GAAG,QAAQ,uCAAuC,EAAE,IAAI,OAAO;AAEpE,aAAO,MAAM,4BAA4B,EAAE,QAAQ,CAAC;AAAA,IACtD,SAAS,OAAgB;AACvB,aAAO,MAAM,0BAA0B,EAAE,SAAS,MAAM,CAAC;AACzD,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEQ,iBAAiB,eAAuB;AAC9C,QAAI;AACF,YAAM,WAAW,KAAK,GACnB;AAAA,QACC;AAAA;AAAA;AAAA;AAAA,MAIF,EACC,IAAI,aAAa;AAEpB,eAAS,QAAQ,CAAC,UAAU;AAC1B,YAAI;AACF,eAAK,WAAW,MAAM,QAAQ;AAAA,QAChC,SAAS,OAAgB;AACvB,iBAAO;AAAA,YACL;AAAA,YACA,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AAAA,YACxD;AAAA,cACE;AAAA,cACA,cAAc,MAAM;AAAA,YACtB;AAAA,UACF;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH,SAAS,OAAgB;AACvB,YAAM,IAAI;AAAA,QACR,4CAA4C,aAAa;AAAA,QACzD,UAAU;AAAA,QACV;AAAA,UACE;AAAA,UACA,WAAW;AAAA,QACb;AAAA,QACA,iBAAiB,QAAQ,QAAQ;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAe,SAGrB;AACA,UAAM,QAAQ,KAAK,SAAS,OAAO;AACnC,UAAM,SAAS,KAAK,eAAe,OAAO;AAC1C,UAAM,UAAU,KAAK,gBAAgB,OAAO;AAE5C,QAAI,CAAC,OAAO;AACV,YAAM,IAAI;AAAA,QACR,2CAA2C,OAAO;AAAA,QAClD,UAAU;AAAA,QACV;AAAA,UACE;AAAA,UACA,WAAW;AAAA,UACX,OAAO,KAAK;AAAA,QACd;AAAA,MACF;AAAA,IACF;AAGA,UAAM,YAAY,QAAQ,OAAO,CAAC,MAAM,EAAE,SAAS,UAAU;AAC7D,UAAM,cAAc,QAAQ,OAAO,CAAC,MAAM,EAAE,SAAS,YAAY;AACjE,UAAM,QAAQ,QAAQ,OAAO,CAAC,MAAM,EAAE,SAAS,MAAM;AAErD,UAAM,YAAY,OAAO,OAAO,CAAC,MAAM,EAAE,eAAe,WAAW;AACnE,UAAM,YAAY,OAAO,OAAO,CAAC,MAAM,EAAE,eAAe,UAAU;AAGlE,UAAM,aAAa;AAAA,MACjB,QAAQ,MAAM;AAAA,MACd,WAAW,UAAU,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,WAAW,MAAM,EAAE,KAAK,EAAE;AAAA,MACnE,aAAa,YAAY,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,WAAW,MAAM,EAAE,KAAK,EAAE;AAAA,MACvE,OAAO,MAAM,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,WAAW,MAAM,EAAE,KAAK,EAAE;AAAA,MAC3D,WAAW,UAAU,IAAI,CAAC,OAAO;AAAA,QAC/B,MAAM,EAAE,QAAQ,QAAQ;AAAA,QACxB,KAAK,EAAE,QAAQ;AAAA,MACjB,EAAE;AAAA,MACF,kBAAkB,UAAU;AAAA,MAC5B,kBAAkB,MAAM,YACpB,MAAM,YAAY,MAAM,aACxB;AAAA,IACN;AAGA,UAAM,OAAO,KAAK,mBAAmB,OAAO,YAAY,OAAO,MAAM;AAErE,WAAO,EAAE,MAAM,WAAW;AAAA,EAC5B;AAAA,EAEQ,mBACN,OACA,YACA,YACQ;AACR,QAAI,UAAU,cAAc,MAAM,IAAI;AAAA;AAEtC,QAAI,WAAW,UAAU,SAAS,GAAG;AACnC,iBAAW;AAAA;AAAA,EAAsB,WAAW,UAAU,IAAI,CAAC,MAAW,KAAK,EAAE,IAAI,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA,IACjG;AAEA,QAAI,WAAW,YAAY,SAAS,GAAG;AACrC,iBAAW;AAAA;AAAA,EAA+B,WAAW,YAAY,IAAI,CAAC,MAAW,KAAK,EAAE,IAAI,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA,IAC5G;AAEA,QAAI,WAAW,MAAM,SAAS,GAAG;AAC/B,iBAAW;AAAA;AAAA,EAAwB,WAAW,MAAM,IAAI,CAAC,MAAW,KAAK,EAAE,IAAI,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA,IAC/F;AAEA,eAAW;AAAA,YAAe,UAAU,YAAY,WAAW,gBAAgB;AAE3E,QAAI,WAAW,mBAAmB,GAAG;AACnC,iBAAW,KAAK,KAAK,MAAM,WAAW,mBAAmB,EAAE,CAAC,KAAK,WAAW,mBAAmB,EAAE;AAAA,IACnG;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKO,SACL,WACA,SACA,SACQ;AACR,UAAM,gBAAgB,WAAW,KAAK,kBAAkB;AACxD,QAAI,CAAC,eAAe;AAClB,YAAM,IAAI;AAAA,QACR;AAAA,QACA,UAAU;AAAA,QACV;AAAA,UACE,WAAW;AAAA,UACX;AAAA,UACA,aAAa,KAAK;AAAA,QACpB;AAAA,MACF;AAAA,IACF;AAEA,UAAM,UAAU,OAAO;AACvB,UAAM,MAAM,KAAK,qBAAqB,aAAa;AAEnD,QAAI;AACF,WAAK,GACF;AAAA,QACC;AAAA;AAAA;AAAA;AAAA,MAIF,EACC;AAAA,QACC;AAAA,QACA,KAAK;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA,KAAK,UAAU,OAAO;AAAA,MACxB;AAAA,IACJ,SAAS,OAAgB;AACvB,YAAM,IAAI;AAAA,QACR,iCAAiC,aAAa;AAAA,QAC9C,UAAU;AAAA,QACV;AAAA,UACE;AAAA,UACA,SAAS;AAAA,UACT;AAAA,UACA;AAAA,UACA,WAAW;AAAA,QACb;AAAA,QACA,iBAAiB,QAAQ,QAAQ;AAAA,MACnC;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKO,UACL,MACA,MACA,WAAmB,GACnB,WAAgC,CAAC,GACjC,SACQ;AACR,UAAM,gBAAgB,WAAW,KAAK,kBAAkB;AACxD,QAAI,CAAC,eAAe;AAClB,YAAM,IAAI;AAAA,QACR;AAAA,QACA,UAAU;AAAA,QACV;AAAA,UACE,WAAW;AAAA,UACX,YAAY;AAAA,UACZ,MAAM,KAAK,UAAU,GAAG,GAAG;AAAA,UAC3B,aAAa,KAAK;AAAA,QACpB;AAAA,MACF;AAAA,IACF;AAEA,UAAM,WAAW,OAAO;AAExB,QAAI;AACF,WAAK,GACF;AAAA,QACC;AAAA;AAAA;AAAA;AAAA,MAIF,EACC;AAAA,QACC;AAAA,QACA;AAAA,QACA,KAAK;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA,KAAK,UAAU,QAAQ;AAAA,MACzB;AAAA,IACJ,SAAS,OAAgB;AACvB,YAAM,IAAI;AAAA,QACR,kCAAkC,aAAa;AAAA,QAC/C,UAAU;AAAA,QACV;AAAA,UACE;AAAA,UACA,SAAS;AAAA,UACT,YAAY;AAAA,UACZ,WAAW;AAAA,QACb;AAAA,QACA,iBAAiB,QAAQ,QAAQ;AAAA,MACnC;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKO,mBAAmB,YAAoB,IAAoB;AAChE,WAAO,KAAK,YACT,IAAI,CAAC,YAAY;AAChB,YAAM,QAAQ,KAAK,SAAS,OAAO;AACnC,UAAI,CAAC,MAAO,QAAO;AAEnB,aAAO;AAAA,QACL;AAAA,QACA,QAAQ;AAAA,UACN,MAAM,MAAM;AAAA,UACZ,aAAa,KAAK,mBAAmB,MAAM,MAAM;AAAA,UACjD,aAAa,MAAM,OAAO;AAAA,QAC5B;AAAA,QACA,SAAS,KAAK,gBAAgB,OAAO;AAAA,QACrC,cAAc,KAAK,eAAe,SAAS,SAAS;AAAA,QACpD,iBAAiB,KAAK,mBAAmB,OAAO;AAAA,MAClD;AAAA,IACF,CAAC,EACA,OAAO,OAAO;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKO,qBAA8B;AACnC,WAAO,KAAK,YACT,IAAI,CAAC,YAAY,KAAK,SAAS,OAAO,CAAC,EACvC,OAAO,OAAO;AAAA,EACnB;AAAA;AAAA,EAGO,oBAAwC;AAC7C,WAAO,KAAK,YAAY,KAAK,YAAY,SAAS,CAAC;AAAA,EACrD;AAAA,EAEO,gBAAwB;AAC7B,WAAO,KAAK,YAAY;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,gBAAgB,QAAgB,KAAuB;AAClE,QAAI;AACF,YAAM,OAAO,KAAK,GACf;AAAA,QACC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAMF,EACC,IAAI,KAAK,WAAW,KAAK;AAE5B,aAAO,KAAK,IAAI,CAAC,SAAS;AAAA,QACxB,GAAG;AAAA,QACH,SAAS,IAAI;AAAA,QACb,OAAO,IAAI;AAAA,QACX,WAAW,IAAI;AAAA,QACf,eAAe,IAAI;AAAA,QACnB,OAAO,IAAI;AAAA,QACX,WAAW,IAAI;AAAA,QACf,UAAU;AAAA,UACR,MAAM,KAAK,qBAAqB,GAAG;AAAA,UACnC,YAAY,KAAK,yBAAyB,GAAG;AAAA,QAC/C;AAAA,QACA,MAAM;AAAA,UACJ,QAAQ,KAAK,MAAM,IAAI,UAAU,IAAI;AAAA,UACrC,SAAS,KAAK,MAAM,IAAI,WAAW,IAAI;AAAA,UACvC,QAAQ,KAAK,MAAM,IAAI,eAAe,IAAI;AAAA,QAC5C;AAAA,QACA,QAAQ,KAAK,MAAM,IAAI,UAAU,IAAI;AAAA,QACrC,SAAS,KAAK,MAAM,IAAI,WAAW,IAAI;AAAA,QACvC,aAAa,KAAK,MAAM,IAAI,eAAe,IAAI;AAAA,MACjD,EAAE;AAAA,IACJ,SAAS,OAAgB;AACvB,aAAO,MAAM,+BAA+B,KAAc;AAC1D,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,WAAW,KAAa,OAA2B;AAC9D,UAAM,iBAAiB,KAAK,kBAAkB;AAC9C,QAAI,CAAC,eAAgB;AAErB,QAAI;AACF,YAAM,QAAQ,KAAK,SAAS,cAAc;AAC1C,UAAI,CAAC,MAAO;AAEZ,YAAM,WAAW,MAAM,WAAW,CAAC;AACnC,eAAS,GAAG,IAAI;AAEhB,WAAK,GACF,QAAQ,kDAAkD,EAC1D,IAAI,KAAK,UAAU,QAAQ,GAAG,cAAc;AAAA,IACjD,SAAS,OAAgB;AACvB,aAAO,KAAK,kCAAkC,EAAE,OAAO,IAAI,CAAC;AAAA,IAC9D;AAAA,EACF;AAAA,EAEQ,qBAAqB,OAAsB;AACjD,UAAM,OAAiB,CAAC;AAGxB,QAAI,MAAM,KAAM,MAAK,KAAK,MAAM,IAAI;AAGpC,QAAI,MAAM,MAAM;AACd,UAAI,MAAM,KAAK,YAAY,EAAE,SAAS,OAAO,EAAG,MAAK,KAAK,OAAO;AACjE,UAAI,MAAM,KAAK,YAAY,EAAE,SAAS,KAAK,EAAG,MAAK,KAAK,YAAY;AACpE,UAAI,MAAM,KAAK,YAAY,EAAE,SAAS,UAAU,EAAG,MAAK,KAAK,UAAU;AACvE,UAAI,MAAM,KAAK,YAAY,EAAE,SAAS,WAAW;AAC/C,aAAK,KAAK,WAAW;AAAA,IACzB;AAGA,QAAI;AACF,YAAM,SAAS,KAAK,MAAM,MAAM,eAAe,IAAI;AACnD,UAAI,OAAO,KAAM,MAAK,KAAK,GAAG,OAAO,IAAI;AAAA,IAC3C,QAAQ;AAAA,IAAC;AAET,WAAO,CAAC,GAAG,IAAI,IAAI,IAAI,CAAC;AAAA,EAC1B;AAAA,EAEQ,yBAAyB,OAAuC;AAEtE,QAAI,MAAM,SAAS,eAAe,MAAM,MAAM,SAAS,UAAU;AAC/D,aAAO;AAGT,QAAI,MAAM,SAAS,WAAW,MAAM,SAAS,aAAc,QAAO;AAGlE,QAAI,MAAM,aAAa,MAAM,YAAY;AACvC,YAAM,WAAW,MAAM,YAAY,MAAM;AACzC,UAAI,WAAW,IAAK,QAAO;AAAA,IAC7B;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,cAAc,SAAyB;AAC7C,UAAM,QAAQ,KAAK,SAAS,OAAO;AACnC,WAAO,OAAO,SAAS;AAAA,EACzB;AAAA,EAEO,SAAS,SAAoC;AAClD,QAAI;AACF,YAAM,MAAM,KAAK,GACd;AAAA,QACC;AAAA;AAAA;AAAA,MAGF,EACC,IAAI,OAAO;AAEd,UAAI,CAAC,IAAK,QAAO;AAEjB,aAAO;AAAA,QACL,GAAG;AAAA,QACH,QAAQ,KAAK,MAAM,IAAI,UAAU,IAAI;AAAA,QACrC,SAAS,KAAK,MAAM,IAAI,WAAW,IAAI;AAAA,QACvC,aAAa,KAAK,MAAM,IAAI,eAAe,IAAI;AAAA,MACjD;AAAA,IACF,SAAS,OAAgB;AAEvB,aAAO,KAAK,wBAAwB,OAAO,IAAI;AAAA,QAC7C,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,QAC5D;AAAA,QACA,WAAW;AAAA,MACb,CAAC;AACD,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEO,eAAe,SAAiB,OAAyB;AAC9D,QAAI;AACF,YAAM,QAAQ,QACV,sEACA;AAEJ,YAAM,SAAS,QAAQ,CAAC,SAAS,KAAK,IAAI,CAAC,OAAO;AAClD,YAAM,OAAO,KAAK,GAAG,QAAQ,KAAK,EAAE,IAAI,GAAG,MAAM;AAEjD,aAAO,KAAK,IAAI,CAAC,SAAS;AAAA,QACxB,GAAG;AAAA,QACH,SAAS,KAAK,MAAM,IAAI,OAAO;AAAA,MACjC,EAAE;AAAA,IACJ,SAAS,OAAgB;AACvB,YAAM,IAAI;AAAA,QACR,+BAA+B,OAAO;AAAA,QACtC,UAAU;AAAA,QACV;AAAA,UACE;AAAA,UACA;AAAA,UACA,WAAW;AAAA,QACb;AAAA,QACA,iBAAiB,QAAQ,QAAQ;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,gBAAgB,SAA2B;AACjD,QAAI;AACF,YAAM,OAAO,KAAK,GACf;AAAA,QACC;AAAA;AAAA;AAAA,MAGF,EACC,IAAI,OAAO;AAEd,aAAO,KAAK,IAAI,CAAC,SAAS;AAAA,QACxB,GAAG;AAAA,QACH,UAAU,KAAK,MAAM,IAAI,YAAY,IAAI;AAAA,MAC3C,EAAE;AAAA,IACJ,SAAS,OAAgB;AACvB,YAAM,IAAI;AAAA,QACR,gCAAgC,OAAO;AAAA,QACvC,UAAU;AAAA,QACV;AAAA,UACE;AAAA,UACA,WAAW;AAAA,QACb;AAAA,QACA,iBAAiB,QAAQ,QAAQ;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,qBAAqB,SAAyB;AACpD,QAAI;AACF,YAAM,SAAS,KAAK,GACjB;AAAA,QACC;AAAA;AAAA;AAAA,MAGF,EACC,IAAI,OAAO;AAEd,cAAQ,OAAO,WAAW,KAAK;AAAA,IACjC,SAAS,OAAgB;AACvB,YAAM,IAAI;AAAA,QACR,gDAAgD,OAAO;AAAA,QACvD,UAAU;AAAA,QACV;AAAA,UACE;AAAA,UACA,WAAW;AAAA,QACb;AAAA,QACA,iBAAiB,QAAQ,QAAQ;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,mBACN,QACsB;AACtB,WAAO,OAAO;AAAA,EAChB;AAAA,EAEQ,mBAAmB,SAA2B;AACpD,UAAM,YAAY,KAAK,eAAe,OAAO,EAC1C,OAAO,CAAC,MAAM,EAAE,eAAe,UAAU,EACzC,IAAI,CAAC,MAAM,EAAE,QAAQ,GAAG,EACxB,OAAO,OAAO;AAEjB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,YACN,cACA,eACiB;AACjB,UAAM,UAAU,oBAAI,IAAY;AAChC,UAAM,OAAiB,CAAC;AAGxB,QAAI,YAAgC;AAEpC,WAAO,WAAW;AAEhB,UAAI,QAAQ,IAAI,SAAS,GAAG;AAE1B,cAAM,aAAa,KAAK,QAAQ,SAAS;AACzC,eAAO,KAAK,MAAM,UAAU,EAAE,OAAO,SAAS;AAAA,MAChD;AAGA,UAAI,cAAc,cAAc;AAC9B,eAAO,KAAK,OAAO,CAAC,WAAW,YAAY,CAAC;AAAA,MAC9C;AAEA,cAAQ,IAAI,SAAS;AACrB,WAAK,KAAK,SAAS;AAGnB,YAAM,QAAQ,KAAK,SAAS,SAAS;AACrC,UAAI,CAAC,OAAO;AAEV;AAAA,MACF;AACA,kBAAY,MAAM;AAGlB,UAAI,KAAK,SAAS,KAAK,eAAe;AACpC,cAAM,IAAI;AAAA,UACR;AAAA,UACA,UAAU;AAAA,UACV;AAAA,YACE,OAAO,KAAK;AAAA,YACZ,UAAU,KAAK;AAAA,YACf;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,kBAAkB,SAAiB,kBAAuC;AAE/E,UAAM,QAAQ,KAAK,SAAS,OAAO;AACnC,QAAI,CAAC,OAAO;AACV,YAAM,IAAI;AAAA,QACR,oBAAoB,OAAO;AAAA,QAC3B,UAAU;AAAA,QACV,EAAE,QAAQ;AAAA,MACZ;AAAA,IACF;AAGA,QAAI,kBAAkB;AACpB,YAAM,QAAQ,KAAK,YAAY,SAAS,gBAAgB;AACxD,UAAI,OAAO;AACT,cAAM,IAAI;AAAA,UACR;AAAA,UACA,UAAU;AAAA,UACV;AAAA,YACE;AAAA,YACA;AAAA,YACA;AAAA,YACA,iBAAiB,MAAM;AAAA,UACzB;AAAA,QACF;AAAA,MACF;AAGA,YAAM,iBAAiB,KAAK,SAAS,gBAAgB;AACrD,UAAI,gBAAgB;AAClB,cAAM,WAAW,eAAe,QAAQ;AACxC,YAAI,WAAW,KAAK,eAAe;AACjC,gBAAM,IAAI;AAAA,YACR;AAAA,YACA,UAAU;AAAA,YACV;AAAA,cACE;AAAA,cACA;AAAA,cACA;AAAA,cACA,UAAU,KAAK;AAAA,YACjB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAI;AAEF,WAAK,GACF;AAAA,QACC;AAAA,MACF,EACC,IAAI,kBAAkB,OAAO;AAEhC,aAAO,KAAK,wBAAwB;AAAA,QAClC;AAAA,QACA,aAAa,MAAM;AAAA,QACnB,aAAa;AAAA,MACf,CAAC;AAAA,IACH,SAAS,OAAgB;AACvB,YAAM,IAAI;AAAA,QACR;AAAA,QACA,UAAU;AAAA,QACV;AAAA,UACE;AAAA,UACA;AAAA,UACA,WAAW;AAAA,QACb;AAAA,QACA,iBAAiB,QAAQ,QAAQ;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AACF;",
|
|
4
|
+
"sourcesContent": ["/**\n * StackMemory Frame Manager - Call Stack Implementation\n * Manages nested frames representing the call stack of work\n */\n\nimport Database from 'better-sqlite3';\nimport { v4 as uuidv4 } from 'uuid';\nimport { logger } from '../monitoring/logger.js';\nimport { trace } from '../trace/index.js';\nimport {\n DatabaseError,\n FrameError,\n SystemError,\n ErrorCode,\n wrapError,\n createErrorHandler,\n} from '../errors/index.js';\nimport { retry, withTimeout } from '../errors/recovery.js';\nimport { sessionManager, FrameQueryMode } from '../session/index.js';\nimport { contextBridge } from './context-bridge.js';\n\n// Constants for frame validation\nconst MAX_FRAME_DEPTH = 100; // Maximum allowed frame depth\nconst DEFAULT_MAX_DEPTH = 100; // Default if not configured\n\n// Type-safe environment variable access\nfunction getEnv(key: string, defaultValue?: string): string {\n const value = process.env[key];\n if (value === undefined) {\n if (defaultValue !== undefined) return defaultValue;\n throw new Error(`Environment variable ${key} is required`);\n }\n return value;\n}\n\nfunction getOptionalEnv(key: string): string | undefined {\n return process.env[key];\n}\n\n// Frame types based on architecture\nexport type FrameType =\n | 'task'\n | 'subtask'\n | 'tool_scope'\n | 'review'\n | 'write'\n | 'debug';\nexport type FrameState = 'active' | 'closed';\n\nexport interface Frame {\n frame_id: string;\n run_id: string;\n project_id: string;\n parent_frame_id?: string;\n depth: number;\n type: FrameType;\n name: string;\n state: FrameState;\n inputs: Record<string, any>;\n outputs: Record<string, any>;\n digest_text?: string;\n digest_json: Record<string, any>;\n created_at: number;\n closed_at?: number;\n}\n\nexport interface FrameContext {\n frameId: string;\n header: {\n goal: string;\n constraints?: string[];\n definitions?: Record<string, string>;\n };\n anchors: Anchor[];\n recentEvents: Event[];\n activeArtifacts: string[];\n}\n\nexport interface Anchor {\n anchor_id: string;\n frame_id: string;\n type:\n | 'FACT'\n | 'DECISION'\n | 'CONSTRAINT'\n | 'INTERFACE_CONTRACT'\n | 'TODO'\n | 'RISK';\n text: string;\n priority: number;\n metadata: Record<string, any>;\n}\n\nexport interface Event {\n event_id: string;\n frame_id: string;\n run_id: string;\n seq: number;\n event_type:\n | 'user_message'\n | 'assistant_message'\n | 'tool_call'\n | 'tool_result'\n | 'decision'\n | 'constraint'\n | 'artifact'\n | 'observation';\n payload: Record<string, any>;\n ts: number;\n}\n\nexport interface FrameManagerOptions {\n skipContextBridge?: boolean;\n runId?: string;\n maxFrameDepth?: number; // Maximum allowed frame depth (default: 100)\n}\n\nexport class FrameManager {\n private db: Database.Database;\n private currentRunId: string;\n private sessionId: string;\n private projectId: string;\n private activeStack: string[] = []; // Stack of active frame IDs\n private queryMode: FrameQueryMode = FrameQueryMode.PROJECT_ACTIVE;\n private maxFrameDepth: number = DEFAULT_MAX_DEPTH;\n\n constructor(\n db: Database.Database,\n projectId: string,\n runIdOrOptions?: string | FrameManagerOptions\n ) {\n this.db = db;\n this.projectId = projectId;\n\n // Handle both legacy string runId and new options object\n let runId: string | undefined;\n let skipContextBridge = false;\n\n if (typeof runIdOrOptions === 'string') {\n runId = runIdOrOptions;\n } else if (runIdOrOptions) {\n runId = runIdOrOptions.runId;\n skipContextBridge = runIdOrOptions.skipContextBridge || false;\n this.maxFrameDepth = runIdOrOptions.maxFrameDepth || DEFAULT_MAX_DEPTH;\n }\n\n // Use session manager for run ID if available\n const session = sessionManager.getCurrentSession();\n if (session) {\n this.currentRunId = session.runId;\n this.sessionId = session.sessionId;\n } else {\n this.currentRunId = runId || uuidv4();\n this.sessionId = this.currentRunId; // Fallback for legacy behavior\n }\n\n this.initializeSchema();\n this.loadActiveStack();\n\n // Initialize context bridge for automatic shared context\n // Skip in test environment, when explicitly requested, or for CLI usage\n const shouldInitializeBridge =\n !skipContextBridge &&\n process.env['NODE_ENV'] !== 'test' &&\n !process.env['VITEST'] &&\n !process.env['STACKMEMORY_CLI'];\n\n if (shouldInitializeBridge) {\n contextBridge\n .initialize(this, {\n autoSync: true,\n syncInterval: 60000, // 1 minute\n minFrameScore: 0.5, // Sync frames above 0.5 score\n importantTags: ['decision', 'error', 'milestone', 'learning'],\n })\n .catch((error) => {\n logger.warn('Failed to initialize context bridge', { error });\n });\n }\n }\n\n setQueryMode(mode: FrameQueryMode): void {\n this.queryMode = mode;\n this.loadActiveStack(); // Reload with new mode\n }\n\n private initializeSchema() {\n const errorHandler = createErrorHandler({\n operation: 'initializeSchema',\n projectId: this.projectId,\n runId: this.currentRunId,\n });\n\n try {\n // Check if database is properly initialized\n if (!this.db || typeof this.db.exec !== 'function') {\n throw new Error('Database not properly initialized. Expected SQLite Database instance with exec() method.');\n }\n\n // Enhanced frames table matching architecture\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS frames (\n frame_id TEXT PRIMARY KEY,\n run_id TEXT NOT NULL,\n project_id TEXT NOT NULL,\n parent_frame_id TEXT REFERENCES frames(frame_id),\n depth INTEGER NOT NULL DEFAULT 0,\n type TEXT NOT NULL,\n name TEXT NOT NULL,\n state TEXT DEFAULT 'active',\n inputs TEXT DEFAULT '{}',\n outputs TEXT DEFAULT '{}',\n digest_text TEXT,\n digest_json TEXT DEFAULT '{}',\n created_at INTEGER DEFAULT (unixepoch()),\n closed_at INTEGER\n );\n\n CREATE TABLE IF NOT EXISTS events (\n event_id TEXT PRIMARY KEY,\n run_id TEXT NOT NULL,\n frame_id TEXT NOT NULL,\n seq INTEGER NOT NULL,\n event_type TEXT NOT NULL,\n payload TEXT NOT NULL,\n ts INTEGER DEFAULT (unixepoch()),\n FOREIGN KEY(frame_id) REFERENCES frames(frame_id)\n );\n\n CREATE TABLE IF NOT EXISTS anchors (\n anchor_id TEXT PRIMARY KEY,\n frame_id TEXT NOT NULL,\n project_id TEXT NOT NULL,\n type TEXT NOT NULL,\n text TEXT NOT NULL,\n priority INTEGER DEFAULT 0,\n created_at INTEGER DEFAULT (unixepoch()),\n metadata TEXT DEFAULT '{}',\n FOREIGN KEY(frame_id) REFERENCES frames(frame_id)\n );\n\n CREATE TABLE IF NOT EXISTS handoff_requests (\n request_id TEXT PRIMARY KEY,\n source_stack_id TEXT NOT NULL,\n target_stack_id TEXT NOT NULL,\n frame_ids TEXT NOT NULL,\n status TEXT NOT NULL DEFAULT 'pending',\n created_at INTEGER DEFAULT (unixepoch()),\n expires_at INTEGER,\n target_user_id TEXT,\n message TEXT\n );\n\n CREATE INDEX IF NOT EXISTS idx_frames_run ON frames(run_id);\n CREATE INDEX IF NOT EXISTS idx_frames_parent ON frames(parent_frame_id);\n CREATE INDEX IF NOT EXISTS idx_frames_state ON frames(state);\n CREATE INDEX IF NOT EXISTS idx_events_frame ON events(frame_id);\n CREATE INDEX IF NOT EXISTS idx_events_seq ON events(frame_id, seq);\n CREATE INDEX IF NOT EXISTS idx_anchors_frame ON anchors(frame_id);\n CREATE INDEX IF NOT EXISTS idx_handoff_requests_status ON handoff_requests(status);\n CREATE INDEX IF NOT EXISTS idx_handoff_requests_target ON handoff_requests(target_stack_id);\n `);\n } catch (error: unknown) {\n const dbError = errorHandler(error, {\n operation: 'initializeSchema',\n schema: 'frames',\n });\n\n if (dbError instanceof DatabaseError) {\n throw new DatabaseError(\n 'Failed to initialize frame database schema',\n ErrorCode.DB_MIGRATION_FAILED,\n {\n projectId: this.projectId,\n operation: 'initializeSchema',\n originalError: error,\n },\n error instanceof Error ? error : undefined\n );\n }\n throw dbError;\n }\n }\n\n private loadActiveStack() {\n const errorHandler = createErrorHandler({\n operation: 'loadActiveStack',\n runId: this.currentRunId,\n projectId: this.projectId,\n });\n\n try {\n let query: string;\n let params: any[];\n\n // Build query based on query mode\n switch (this.queryMode) {\n case FrameQueryMode.ALL_ACTIVE:\n query = `\n SELECT frame_id, parent_frame_id, depth\n FROM frames\n WHERE state = 'active'\n ORDER BY created_at DESC, depth ASC\n `;\n params = [];\n break;\n\n case FrameQueryMode.PROJECT_ACTIVE:\n query = `\n SELECT frame_id, parent_frame_id, depth, run_id\n FROM frames\n WHERE state = 'active' AND project_id = ?\n ORDER BY created_at DESC, depth ASC\n `;\n params = [this.projectId];\n break;\n\n case FrameQueryMode.HISTORICAL:\n query = `\n SELECT frame_id, parent_frame_id, depth\n FROM frames\n WHERE project_id = ?\n ORDER BY created_at DESC, depth ASC\n `;\n params = [this.projectId];\n break;\n\n case FrameQueryMode.CURRENT_SESSION:\n default:\n query = `\n SELECT frame_id, parent_frame_id, depth\n FROM frames\n WHERE run_id = ? AND state = 'active'\n ORDER BY depth ASC\n `;\n params = [this.currentRunId];\n break;\n }\n\n const activeFrames = this.db.prepare(query).all(...params) as Frame[];\n\n // Rebuild stack order\n this.activeStack = this.buildStackOrder(activeFrames);\n\n logger.info('Loaded active stack', {\n runId: this.currentRunId,\n stackDepth: this.activeStack.length,\n activeFrames: this.activeStack,\n queryMode: this.queryMode,\n });\n } catch (error: unknown) {\n const dbError = errorHandler(error, {\n query: 'Frame loading query',\n runId: this.currentRunId,\n queryMode: this.queryMode,\n });\n\n if (dbError instanceof DatabaseError) {\n throw new DatabaseError(\n 'Failed to load active frame stack',\n ErrorCode.DB_QUERY_FAILED,\n {\n runId: this.currentRunId,\n projectId: this.projectId,\n operation: 'loadActiveStack',\n },\n error instanceof Error ? error : undefined\n );\n }\n throw dbError;\n }\n }\n\n private buildStackOrder(\n frames: Pick<Frame, 'frame_id' | 'parent_frame_id' | 'depth'>[]\n ): string[] {\n const stack: string[] = [];\n\n // Find root frame (no parent)\n const rootFrame = frames.find((f) => !f.parent_frame_id);\n if (!rootFrame) return [];\n\n // Build stack by following parent-child relationships\n let currentFrame = rootFrame;\n stack.push(currentFrame.frame_id);\n\n while (currentFrame) {\n const childFrame = frames.find(\n (f) => f.parent_frame_id === currentFrame.frame_id\n );\n if (!childFrame) break;\n stack.push(childFrame.frame_id);\n currentFrame = childFrame;\n }\n\n return stack;\n }\n\n /**\n * Create a new frame and push to stack\n */\n public createFrame(options: {\n type: FrameType;\n name: string;\n inputs?: Record<string, any>;\n parentFrameId?: string;\n }): string {\n return this._createFrame(options);\n }\n\n private _createFrame(options: {\n type: FrameType;\n name: string;\n inputs?: Record<string, any>;\n parentFrameId?: string;\n }): string {\n const frameId = uuidv4();\n const parentFrameId = options.parentFrameId || this.getCurrentFrameId();\n const depth = parentFrameId ? this.getFrameDepth(parentFrameId) + 1 : 0;\n\n // Check for depth limit\n if (depth > this.maxFrameDepth) {\n throw new FrameError(\n `Maximum frame depth exceeded: ${depth} > ${this.maxFrameDepth}`,\n ErrorCode.FRAME_STACK_OVERFLOW,\n {\n currentDepth: depth,\n maxDepth: this.maxFrameDepth,\n frameId,\n parentFrameId,\n frameName: options.name,\n }\n );\n }\n\n // Check for circular reference before creating frame\n if (parentFrameId) {\n const cycle = this.detectCycle(frameId, parentFrameId);\n if (cycle) {\n throw new FrameError(\n `Circular reference detected in frame hierarchy`,\n ErrorCode.FRAME_CYCLE_DETECTED,\n {\n frameId,\n parentFrameId,\n cycle,\n frameName: options.name,\n }\n );\n }\n }\n\n const frame: Omit<\n Frame,\n 'outputs' | 'digest_text' | 'digest_json' | 'closed_at'\n > = {\n frame_id: frameId,\n run_id: this.currentRunId,\n project_id: this.projectId,\n parent_frame_id: parentFrameId,\n depth,\n type: options.type,\n name: options.name,\n state: 'active',\n inputs: options.inputs || {},\n created_at: Math.floor(Date.now() / 1000),\n };\n\n try {\n this.db\n .prepare(\n `\n INSERT INTO frames (\n frame_id, run_id, project_id, parent_frame_id, depth, type, name, state, inputs, created_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `\n )\n .run(\n frame.frame_id,\n frame.run_id,\n frame.project_id,\n frame.parent_frame_id,\n frame.depth,\n frame.type,\n frame.name,\n frame.state,\n JSON.stringify(frame.inputs),\n frame.created_at\n );\n } catch (error: unknown) {\n throw new DatabaseError(\n `Failed to create frame: ${options.name}`,\n ErrorCode.DB_QUERY_FAILED,\n {\n frameId,\n frameType: options.type,\n frameName: options.name,\n parentFrameId,\n depth,\n operation: 'createFrame',\n },\n error instanceof Error ? error : undefined\n );\n }\n\n // Push to active stack\n this.activeStack.push(frameId);\n\n logger.info('Created frame', {\n frameId,\n type: options.type,\n name: options.name,\n depth,\n parentFrameId,\n stackDepth: this.activeStack.length,\n });\n\n return frameId;\n }\n\n /**\n * Close the current frame and generate digest\n */\n public closeFrame(frameId?: string, outputs?: Record<string, any>): void {\n this._closeFrame(frameId, outputs);\n }\n\n private _closeFrame(frameId?: string, outputs?: Record<string, any>): void {\n const targetFrameId = frameId || this.getCurrentFrameId();\n if (!targetFrameId) {\n throw new FrameError(\n 'No active frame to close',\n ErrorCode.FRAME_INVALID_STATE,\n {\n operation: 'closeFrame',\n activeStack: this.activeStack,\n stackDepth: this.activeStack.length,\n }\n );\n }\n\n // Get frame details\n const frame = this.getFrame(targetFrameId);\n if (!frame) {\n throw new FrameError(\n `Frame not found: ${targetFrameId}`,\n ErrorCode.FRAME_NOT_FOUND,\n {\n frameId: targetFrameId,\n operation: 'closeFrame',\n runId: this.currentRunId,\n }\n );\n }\n\n if (frame.state === 'closed') {\n logger.warn('Attempted to close already closed frame', {\n frameId: targetFrameId,\n });\n return;\n }\n\n // Generate digest before closing\n const digest = this.generateDigest(targetFrameId);\n const finalOutputs = { ...outputs, ...digest.structured };\n\n try {\n // Update frame to closed state\n this.db\n .prepare(\n `\n UPDATE frames\n SET state = 'closed',\n outputs = ?,\n digest_text = ?,\n digest_json = ?,\n closed_at = unixepoch()\n WHERE frame_id = ?\n `\n )\n .run(\n JSON.stringify(finalOutputs),\n digest.text,\n JSON.stringify(digest.structured),\n targetFrameId\n );\n } catch (error: unknown) {\n throw new DatabaseError(\n `Failed to close frame: ${targetFrameId}`,\n ErrorCode.DB_QUERY_FAILED,\n {\n frameId: targetFrameId,\n frameName: frame.name,\n operation: 'closeFrame',\n },\n error instanceof Error ? error : undefined\n );\n }\n\n // Remove from active stack\n this.activeStack = this.activeStack.filter((id) => id !== targetFrameId);\n\n // Close all child frames recursively\n this.closeChildFrames(targetFrameId);\n\n logger.info('Closed frame', {\n frameId: targetFrameId,\n name: frame.name,\n duration: Math.floor(Date.now() / 1000) - frame.created_at,\n digestLength: digest.text.length,\n stackDepth: this.activeStack.length,\n });\n }\n\n /**\n * Delete a frame completely from the database (used in handoffs)\n */\n deleteFrame(frameId: string): void {\n try {\n // First delete related data\n this.db.prepare('DELETE FROM events WHERE frame_id = ?').run(frameId);\n this.db.prepare('DELETE FROM anchors WHERE frame_id = ?').run(frameId);\n\n // Remove from active stack if present\n this.activeStack = this.activeStack.filter((id) => id !== frameId);\n\n // Delete the frame itself\n this.db.prepare('DELETE FROM frames WHERE frame_id = ?').run(frameId);\n\n logger.debug('Deleted frame completely', { frameId });\n } catch (error: unknown) {\n logger.error('Failed to delete frame', { frameId, error });\n throw error;\n }\n }\n\n private closeChildFrames(parentFrameId: string) {\n try {\n const children = this.db\n .prepare(\n `\n SELECT frame_id FROM frames\n WHERE parent_frame_id = ? AND state = 'active'\n `\n )\n .all(parentFrameId) as { frame_id: string }[];\n\n children.forEach((child) => {\n try {\n this.closeFrame(child.frame_id);\n } catch (error: unknown) {\n logger.error(\n 'Failed to close child frame',\n error instanceof Error ? error : new Error(String(error)),\n {\n parentFrameId,\n childFrameId: child.frame_id,\n }\n );\n }\n });\n } catch (error: unknown) {\n throw new DatabaseError(\n `Failed to close child frames for parent: ${parentFrameId}`,\n ErrorCode.DB_QUERY_FAILED,\n {\n parentFrameId,\n operation: 'closeChildFrames',\n },\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * Generate digest for a frame\n */\n private generateDigest(frameId: string): {\n text: string;\n structured: Record<string, any>;\n } {\n const frame = this.getFrame(frameId);\n const events = this.getFrameEvents(frameId);\n const anchors = this.getFrameAnchors(frameId);\n\n if (!frame) {\n throw new FrameError(\n `Cannot generate digest: frame not found ${frameId}`,\n ErrorCode.FRAME_NOT_FOUND,\n {\n frameId,\n operation: 'generateDigest',\n runId: this.currentRunId,\n }\n );\n }\n\n // Extract key information\n const decisions = anchors.filter((a) => a.type === 'DECISION');\n const constraints = anchors.filter((a) => a.type === 'CONSTRAINT');\n const risks = anchors.filter((a) => a.type === 'RISK');\n\n const toolCalls = events.filter((e) => e.event_type === 'tool_call');\n const artifacts = events.filter((e) => e.event_type === 'artifact');\n\n // Generate structured digest\n const structured = {\n result: frame.name,\n decisions: decisions.map((d) => ({ id: d.anchor_id, text: d.text })),\n constraints: constraints.map((c) => ({ id: c.anchor_id, text: c.text })),\n risks: risks.map((r) => ({ id: r.anchor_id, text: r.text })),\n artifacts: artifacts.map((a) => ({\n kind: a.payload.kind || 'unknown',\n ref: a.payload.ref,\n })),\n tool_calls_count: toolCalls.length,\n duration_seconds: frame.closed_at\n ? frame.closed_at - frame.created_at\n : 0,\n };\n\n // Generate text summary\n const text = this.generateDigestText(frame, structured, events.length);\n\n return { text, structured };\n }\n\n private generateDigestText(\n frame: Frame,\n structured: any,\n eventCount: number\n ): string {\n let summary = `Completed: ${frame.name}\\n`;\n\n if (structured.decisions.length > 0) {\n summary += `\\nDecisions made:\\n${structured.decisions.map((d: any) => `- ${d.text}`).join('\\n')}`;\n }\n\n if (structured.constraints.length > 0) {\n summary += `\\nConstraints established:\\n${structured.constraints.map((c: any) => `- ${c.text}`).join('\\n')}`;\n }\n\n if (structured.risks.length > 0) {\n summary += `\\nRisks identified:\\n${structured.risks.map((r: any) => `- ${r.text}`).join('\\n')}`;\n }\n\n summary += `\\nActivity: ${eventCount} events, ${structured.tool_calls_count} tool calls`;\n\n if (structured.duration_seconds > 0) {\n summary += `, ${Math.floor(structured.duration_seconds / 60)}m ${structured.duration_seconds % 60}s duration`;\n }\n\n return summary;\n }\n\n /**\n * Add event to current frame\n */\n public addEvent(\n eventType: Event['event_type'],\n payload: Record<string, any>,\n frameId?: string\n ): string {\n const targetFrameId = frameId || this.getCurrentFrameId();\n if (!targetFrameId) {\n throw new FrameError(\n 'No active frame for event',\n ErrorCode.FRAME_INVALID_STATE,\n {\n operation: 'addEvent',\n eventType,\n activeStack: this.activeStack,\n }\n );\n }\n\n const eventId = uuidv4();\n const seq = this.getNextEventSequence(targetFrameId);\n\n try {\n this.db\n .prepare(\n `\n INSERT INTO events (event_id, run_id, frame_id, seq, event_type, payload)\n VALUES (?, ?, ?, ?, ?, ?)\n `\n )\n .run(\n eventId,\n this.currentRunId,\n targetFrameId,\n seq,\n eventType,\n JSON.stringify(payload)\n );\n } catch (error: unknown) {\n throw new DatabaseError(\n `Failed to add event to frame: ${targetFrameId}`,\n ErrorCode.DB_QUERY_FAILED,\n {\n eventId,\n frameId: targetFrameId,\n eventType,\n seq,\n operation: 'addEvent',\n },\n error instanceof Error ? error : undefined\n );\n }\n\n return eventId;\n }\n\n /**\n * Add anchor to frame\n */\n public addAnchor(\n type: Anchor['type'],\n text: string,\n priority: number = 0,\n metadata: Record<string, any> = {},\n frameId?: string\n ): string {\n const targetFrameId = frameId || this.getCurrentFrameId();\n if (!targetFrameId) {\n throw new FrameError(\n 'No active frame for anchor',\n ErrorCode.FRAME_INVALID_STATE,\n {\n operation: 'addAnchor',\n anchorType: type,\n text: text.substring(0, 100),\n activeStack: this.activeStack,\n }\n );\n }\n\n const anchorId = uuidv4();\n\n try {\n this.db\n .prepare(\n `\n INSERT INTO anchors (anchor_id, frame_id, project_id, type, text, priority, metadata)\n VALUES (?, ?, ?, ?, ?, ?, ?)\n `\n )\n .run(\n anchorId,\n targetFrameId,\n this.projectId,\n type,\n text,\n priority,\n JSON.stringify(metadata)\n );\n } catch (error: unknown) {\n throw new DatabaseError(\n `Failed to add anchor to frame: ${targetFrameId}`,\n ErrorCode.DB_QUERY_FAILED,\n {\n anchorId,\n frameId: targetFrameId,\n anchorType: type,\n operation: 'addAnchor',\n },\n error instanceof Error ? error : undefined\n );\n }\n\n return anchorId;\n }\n\n /**\n * Get hot stack context for current active frames\n */\n public getHotStackContext(maxEvents: number = 20): FrameContext[] {\n return this.activeStack\n .map((frameId) => {\n const frame = this.getFrame(frameId);\n if (!frame) return null;\n\n return {\n frameId,\n header: {\n goal: frame.name,\n constraints: this.extractConstraints(frame.inputs),\n definitions: frame.inputs.definitions,\n },\n anchors: this.getFrameAnchors(frameId),\n recentEvents: this.getFrameEvents(frameId, maxEvents),\n activeArtifacts: this.getActiveArtifacts(frameId),\n };\n })\n .filter(Boolean) as FrameContext[];\n }\n\n /**\n * Get active frame path (root to current)\n */\n public getActiveFramePath(): Frame[] {\n return this.activeStack\n .map((frameId) => this.getFrame(frameId))\n .filter(Boolean) as Frame[];\n }\n\n // Utility methods\n public getCurrentFrameId(): string | undefined {\n return this.activeStack[this.activeStack.length - 1];\n }\n\n public getStackDepth(): number {\n return this.activeStack.length;\n }\n\n /**\n * Get recent frames for context sharing\n */\n public async getRecentFrames(limit: number = 100): Promise<Frame[]> {\n try {\n const rows = this.db\n .prepare(\n `\n SELECT * FROM frames \n WHERE project_id = ?\n ORDER BY created_at DESC\n LIMIT ?\n `\n )\n .all(this.projectId, limit) as any[];\n\n return rows.map((row) => ({\n ...row,\n frameId: row.frame_id,\n runId: row.run_id,\n projectId: row.project_id,\n parentFrameId: row.parent_frame_id,\n title: row.name,\n timestamp: row.created_at,\n metadata: {\n tags: this.extractTagsFromFrame(row),\n importance: this.calculateFrameImportance(row),\n },\n data: {\n inputs: JSON.parse(row.inputs || '{}'),\n outputs: JSON.parse(row.outputs || '{}'),\n digest: JSON.parse(row.digest_json || '{}'),\n },\n inputs: JSON.parse(row.inputs || '{}'),\n outputs: JSON.parse(row.outputs || '{}'),\n digest_json: JSON.parse(row.digest_json || '{}'),\n }));\n } catch (error: unknown) {\n logger.error('Failed to get recent frames', error as Error);\n return [];\n }\n }\n\n /**\n * Add context metadata to the current frame\n */\n public async addContext(key: string, value: any): Promise<void> {\n const currentFrameId = this.getCurrentFrameId();\n if (!currentFrameId) return;\n\n try {\n const frame = this.getFrame(currentFrameId);\n if (!frame) return;\n\n const metadata = frame.outputs || {};\n metadata[key] = value;\n\n this.db\n .prepare(`UPDATE frames SET outputs = ? WHERE frame_id = ?`)\n .run(JSON.stringify(metadata), currentFrameId);\n } catch (error: unknown) {\n logger.warn('Failed to add context to frame', { error, key });\n }\n }\n\n private extractTagsFromFrame(frame: any): string[] {\n const tags: string[] = [];\n\n // Add type as tag\n if (frame.type) tags.push(frame.type);\n\n // Extract tags from name\n if (frame.name) {\n if (frame.name.toLowerCase().includes('error')) tags.push('error');\n if (frame.name.toLowerCase().includes('fix')) tags.push('resolution');\n if (frame.name.toLowerCase().includes('decision')) tags.push('decision');\n if (frame.name.toLowerCase().includes('milestone'))\n tags.push('milestone');\n }\n\n // Extract from digest\n try {\n const digest = JSON.parse(frame.digest_json || '{}');\n if (digest.tags) tags.push(...digest.tags);\n } catch {}\n\n return [...new Set(tags)];\n }\n\n private calculateFrameImportance(frame: any): 'high' | 'medium' | 'low' {\n // Milestones and decisions are high importance\n if (frame.type === 'milestone' || frame.name?.includes('decision'))\n return 'high';\n\n // Errors and resolutions are medium importance\n if (frame.type === 'error' || frame.type === 'resolution') return 'medium';\n\n // Long-running frames are potentially important\n if (frame.closed_at && frame.created_at) {\n const duration = frame.closed_at - frame.created_at;\n if (duration > 300) return 'medium'; // More than 5 minutes\n }\n\n return 'low';\n }\n\n private getFrameDepth(frameId: string): number {\n const frame = this.getFrame(frameId);\n return frame?.depth || 0;\n }\n\n public getFrame(frameId: string): Frame | undefined {\n try {\n const row = this.db\n .prepare(\n `\n SELECT * FROM frames WHERE frame_id = ?\n `\n )\n .get(frameId) as any;\n\n if (!row) return undefined;\n\n return {\n ...row,\n inputs: JSON.parse(row.inputs || '{}'),\n outputs: JSON.parse(row.outputs || '{}'),\n digest_json: JSON.parse(row.digest_json || '{}'),\n };\n } catch (error: unknown) {\n // Log the error but return undefined instead of throwing\n logger.warn(`Failed to get frame: ${frameId}`, {\n error: error instanceof Error ? error.message : String(error),\n frameId,\n operation: 'getFrame',\n });\n return undefined;\n }\n }\n\n public getFrameEvents(frameId: string, limit?: number): Event[] {\n try {\n const query = limit\n ? `SELECT * FROM events WHERE frame_id = ? ORDER BY seq DESC LIMIT ?`\n : `SELECT * FROM events WHERE frame_id = ? ORDER BY seq ASC`;\n\n const params = limit ? [frameId, limit] : [frameId];\n const rows = this.db.prepare(query).all(...params) as any[];\n\n return rows.map((row) => ({\n ...row,\n payload: JSON.parse(row.payload),\n }));\n } catch (error: unknown) {\n throw new DatabaseError(\n `Failed to get frame events: ${frameId}`,\n ErrorCode.DB_QUERY_FAILED,\n {\n frameId,\n limit,\n operation: 'getFrameEvents',\n },\n error instanceof Error ? error : undefined\n );\n }\n }\n\n private getFrameAnchors(frameId: string): Anchor[] {\n try {\n const rows = this.db\n .prepare(\n `\n SELECT * FROM anchors WHERE frame_id = ? ORDER BY priority DESC, created_at ASC\n `\n )\n .all(frameId) as any[];\n\n return rows.map((row) => ({\n ...row,\n metadata: JSON.parse(row.metadata || '{}'),\n }));\n } catch (error: unknown) {\n throw new DatabaseError(\n `Failed to get frame anchors: ${frameId}`,\n ErrorCode.DB_QUERY_FAILED,\n {\n frameId,\n operation: 'getFrameAnchors',\n },\n error instanceof Error ? error : undefined\n );\n }\n }\n\n private getNextEventSequence(frameId: string): number {\n try {\n const result = this.db\n .prepare(\n `\n SELECT MAX(seq) as max_seq FROM events WHERE frame_id = ?\n `\n )\n .get(frameId) as { max_seq: number | null };\n\n return (result.max_seq || 0) + 1;\n } catch (error: unknown) {\n throw new DatabaseError(\n `Failed to get next event sequence for frame: ${frameId}`,\n ErrorCode.DB_QUERY_FAILED,\n {\n frameId,\n operation: 'getNextEventSequence',\n },\n error instanceof Error ? error : undefined\n );\n }\n }\n\n private extractConstraints(\n inputs: Record<string, any>\n ): string[] | undefined {\n return inputs.constraints;\n }\n\n private getActiveArtifacts(frameId: string): string[] {\n const artifacts = this.getFrameEvents(frameId)\n .filter((e) => e.event_type === 'artifact')\n .map((e) => e.payload.ref)\n .filter(Boolean);\n\n return artifacts;\n }\n\n /**\n * Detect if setting a parent frame would create a cycle in the frame hierarchy.\n * Returns the cycle path if detected, or null if no cycle.\n * @param childFrameId - The frame that would be the child\n * @param parentFrameId - The proposed parent frame\n * @returns Array of frame IDs forming the cycle, or null if no cycle\n */\n private detectCycle(\n childFrameId: string,\n parentFrameId: string\n ): string[] | null {\n const visited = new Set<string>();\n const path: string[] = [];\n\n // Start from the proposed parent and traverse up the hierarchy\n let currentId: string | undefined = parentFrameId;\n \n while (currentId) {\n // If we've seen this frame before, we have a cycle\n if (visited.has(currentId)) {\n // Build the cycle path\n const cycleStart = path.indexOf(currentId);\n return path.slice(cycleStart).concat(currentId);\n }\n\n // If the current frame is the child we're trying to add, it's a cycle\n if (currentId === childFrameId) {\n return path.concat([currentId, childFrameId]);\n }\n\n visited.add(currentId);\n path.push(currentId);\n\n // Move to the parent of current frame\n const frame = this.getFrame(currentId);\n if (!frame) {\n // Frame not found, no cycle possible through this path\n break;\n }\n currentId = frame.parent_frame_id;\n\n // Safety check: if we've traversed too many levels, something is wrong\n if (path.length > this.maxFrameDepth) {\n throw new FrameError(\n `Frame hierarchy traversal exceeded maximum depth during cycle detection`,\n ErrorCode.FRAME_STACK_OVERFLOW,\n {\n depth: path.length,\n maxDepth: this.maxFrameDepth,\n path,\n }\n );\n }\n }\n\n return null; // No cycle detected\n }\n\n /**\n * Update parent frame of an existing frame (with cycle detection)\n * @param frameId - The frame to update\n * @param newParentFrameId - The new parent frame ID\n */\n public updateParentFrame(frameId: string, newParentFrameId: string | null): void {\n // Check if frame exists\n const frame = this.getFrame(frameId);\n if (!frame) {\n throw new FrameError(\n `Frame not found: ${frameId}`,\n ErrorCode.FRAME_NOT_FOUND,\n { frameId }\n );\n }\n\n // If setting a parent, check for cycles\n if (newParentFrameId) {\n const cycle = this.detectCycle(frameId, newParentFrameId);\n if (cycle) {\n throw new FrameError(\n `Cannot set parent: would create circular reference`,\n ErrorCode.FRAME_CYCLE_DETECTED,\n {\n frameId,\n newParentFrameId,\n cycle,\n currentParentId: frame.parent_frame_id,\n }\n );\n }\n\n // Check depth after parent change\n const newParentFrame = this.getFrame(newParentFrameId);\n if (newParentFrame) {\n const newDepth = newParentFrame.depth + 1;\n if (newDepth > this.maxFrameDepth) {\n throw new FrameError(\n `Cannot set parent: would exceed maximum frame depth`,\n ErrorCode.FRAME_STACK_OVERFLOW,\n {\n frameId,\n newParentFrameId,\n newDepth,\n maxDepth: this.maxFrameDepth,\n }\n );\n }\n }\n }\n\n try {\n // Update the parent frame\n this.db\n .prepare(\n `UPDATE frames SET parent_frame_id = ? WHERE frame_id = ?`\n )\n .run(newParentFrameId, frameId);\n\n logger.info('Updated parent frame', {\n frameId,\n oldParentId: frame.parent_frame_id,\n newParentId: newParentFrameId,\n });\n } catch (error: unknown) {\n throw new DatabaseError(\n `Failed to update parent frame`,\n ErrorCode.DB_UPDATE_FAILED,\n {\n frameId,\n newParentFrameId,\n operation: 'updateParentFrame',\n },\n error instanceof Error ? error : undefined\n );\n }\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -8,13 +8,16 @@ const execAsync = promisify(exec);
|
|
|
8
8
|
class ClaudeCodeSubagentClient {
|
|
9
9
|
tempDir;
|
|
10
10
|
activeSubagents = /* @__PURE__ */ new Map();
|
|
11
|
-
|
|
11
|
+
mockMode;
|
|
12
|
+
constructor(mockMode = true) {
|
|
13
|
+
this.mockMode = mockMode;
|
|
12
14
|
this.tempDir = path.join(os.tmpdir(), "stackmemory-rlm");
|
|
13
15
|
if (!fs.existsSync(this.tempDir)) {
|
|
14
16
|
fs.mkdirSync(this.tempDir, { recursive: true });
|
|
15
17
|
}
|
|
16
18
|
logger.info("Claude Code Subagent Client initialized", {
|
|
17
|
-
tempDir: this.tempDir
|
|
19
|
+
tempDir: this.tempDir,
|
|
20
|
+
mockMode: this.mockMode
|
|
18
21
|
});
|
|
19
22
|
}
|
|
20
23
|
/**
|
|
@@ -26,8 +29,12 @@ class ClaudeCodeSubagentClient {
|
|
|
26
29
|
const subagentId = `${request.type}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
27
30
|
logger.info(`Spawning ${request.type} subagent`, {
|
|
28
31
|
subagentId,
|
|
29
|
-
task: request.task.slice(0, 100)
|
|
32
|
+
task: request.task.slice(0, 100),
|
|
33
|
+
mockMode: this.mockMode
|
|
30
34
|
});
|
|
35
|
+
if (this.mockMode) {
|
|
36
|
+
return this.getMockResponse(request, startTime, subagentId);
|
|
37
|
+
}
|
|
31
38
|
try {
|
|
32
39
|
const prompt = this.buildSubagentPrompt(request);
|
|
33
40
|
const contextFile = path.join(this.tempDir, `${subagentId}-context.json`);
|
|
@@ -277,6 +284,102 @@ echo '{"status": "completed", "type": "${request.type}"}' > "${resultFile}"
|
|
|
277
284
|
throw error;
|
|
278
285
|
}
|
|
279
286
|
}
|
|
287
|
+
/**
|
|
288
|
+
* Get mock response for testing
|
|
289
|
+
*/
|
|
290
|
+
async getMockResponse(request, startTime, subagentId) {
|
|
291
|
+
await new Promise((resolve) => setTimeout(resolve, Math.random() * 20 + 10));
|
|
292
|
+
const mockResponses = {
|
|
293
|
+
planning: {
|
|
294
|
+
tasks: [
|
|
295
|
+
{ id: "task-1", name: "Analyze requirements", type: "analysis" },
|
|
296
|
+
{ id: "task-2", name: "Design solution", type: "design" },
|
|
297
|
+
{ id: "task-3", name: "Implement solution", type: "implementation" }
|
|
298
|
+
],
|
|
299
|
+
dependencies: [],
|
|
300
|
+
estimated_time: 300
|
|
301
|
+
},
|
|
302
|
+
code: {
|
|
303
|
+
implementation: `function greetUser(name: string): string {
|
|
304
|
+
if (!name || typeof name !== 'string') {
|
|
305
|
+
throw new Error('Invalid name parameter');
|
|
306
|
+
}
|
|
307
|
+
return \`Hello, \${name}!\`;
|
|
308
|
+
}`,
|
|
309
|
+
files_modified: ["src/greet.ts"],
|
|
310
|
+
lines_added: 6,
|
|
311
|
+
lines_removed: 0
|
|
312
|
+
},
|
|
313
|
+
testing: {
|
|
314
|
+
tests: [
|
|
315
|
+
{
|
|
316
|
+
name: "greetUser should return greeting",
|
|
317
|
+
code: `test('greetUser should return greeting', () => {
|
|
318
|
+
expect(greetUser('Alice')).toBe('Hello, Alice!');
|
|
319
|
+
});`,
|
|
320
|
+
type: "unit"
|
|
321
|
+
}
|
|
322
|
+
],
|
|
323
|
+
coverage: { lines: 100, branches: 100, functions: 100 }
|
|
324
|
+
},
|
|
325
|
+
linting: {
|
|
326
|
+
issues: [],
|
|
327
|
+
fixes: [],
|
|
328
|
+
passed: true
|
|
329
|
+
},
|
|
330
|
+
review: {
|
|
331
|
+
quality: 0.85,
|
|
332
|
+
issues: [
|
|
333
|
+
"Consider adding JSDoc comments",
|
|
334
|
+
"Could add more edge case tests"
|
|
335
|
+
],
|
|
336
|
+
suggestions: [
|
|
337
|
+
"Add documentation for the function",
|
|
338
|
+
"Consider adding internationalization support",
|
|
339
|
+
"Add performance tests for large inputs"
|
|
340
|
+
],
|
|
341
|
+
improvements: []
|
|
342
|
+
},
|
|
343
|
+
improve: {
|
|
344
|
+
improved_code: `/**
|
|
345
|
+
* Greets a user with their name
|
|
346
|
+
* @param name - The name of the user to greet
|
|
347
|
+
* @returns A greeting message
|
|
348
|
+
* @throws {Error} If name is invalid
|
|
349
|
+
*/
|
|
350
|
+
function greetUser(name: string): string {
|
|
351
|
+
if (!name || typeof name !== 'string') {
|
|
352
|
+
throw new Error('Invalid name parameter: name must be a non-empty string');
|
|
353
|
+
}
|
|
354
|
+
return \`Hello, \${name}!\`;
|
|
355
|
+
}`,
|
|
356
|
+
changes_made: [
|
|
357
|
+
"Added JSDoc documentation",
|
|
358
|
+
"Improved error message"
|
|
359
|
+
]
|
|
360
|
+
},
|
|
361
|
+
context: {
|
|
362
|
+
relevant_files: ["src/greet.ts", "test/greet.test.ts"],
|
|
363
|
+
patterns: ["greeting functions", "input validation"],
|
|
364
|
+
dependencies: []
|
|
365
|
+
},
|
|
366
|
+
publish: {
|
|
367
|
+
version: "1.0.0",
|
|
368
|
+
changelog: "Initial release",
|
|
369
|
+
published: false,
|
|
370
|
+
reason: "Mock mode - no actual publishing"
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
const result = mockResponses[request.type] || {};
|
|
374
|
+
return {
|
|
375
|
+
success: true,
|
|
376
|
+
result,
|
|
377
|
+
output: `Mock ${request.type} subagent completed successfully`,
|
|
378
|
+
duration: Date.now() - startTime,
|
|
379
|
+
subagentType: request.type,
|
|
380
|
+
tokens: this.estimateTokens(JSON.stringify(result))
|
|
381
|
+
};
|
|
382
|
+
}
|
|
280
383
|
/**
|
|
281
384
|
* Estimate token usage
|
|
282
385
|
*/
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/integrations/claude-code/subagent-client.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Claude Code Subagent Client\n * \n * Uses Claude Code's Task tool to spawn subagents instead of direct API calls\n * This leverages the Claude Code Max plan for unlimited subagent execution\n */\n\nimport { logger } from '../../core/monitoring/logger.js';\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\n\nconst execAsync = promisify(exec);\n\nexport interface SubagentRequest {\n type: 'planning' | 'code' | 'testing' | 'linting' | 'review' | 'improve' | 'context' | 'publish';\n task: string;\n context: Record<string, any>;\n systemPrompt?: string;\n files?: string[];\n timeout?: number;\n}\n\nexport interface SubagentResponse {\n success: boolean;\n result: any;\n output?: string;\n error?: string;\n tokens?: number;\n duration: number;\n subagentType: string;\n}\n\n/**\n * Claude Code Subagent Client\n * Spawns subagents using Claude Code's Task tool\n */\nexport class ClaudeCodeSubagentClient {\n private tempDir: string;\n private activeSubagents: Map<string, AbortController> = new Map();\n \n constructor() {\n // Create temp directory for subagent communication\n this.tempDir = path.join(os.tmpdir(), 'stackmemory-rlm');\n if (!fs.existsSync(this.tempDir)) {\n fs.mkdirSync(this.tempDir, { recursive: true });\n }\n \n logger.info('Claude Code Subagent Client initialized', {\n tempDir: this.tempDir,\n });\n }\n \n /**\n * Execute a subagent task using Claude Code's Task tool\n * This will spawn a new Claude instance with specific instructions\n */\n async executeSubagent(request: SubagentRequest): Promise<SubagentResponse> {\n const startTime = Date.now();\n const subagentId = `${request.type}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n \n logger.info(`Spawning ${request.type} subagent`, {\n subagentId,\n task: request.task.slice(0, 100),\n });\n \n try {\n // Create subagent prompt based on type\n const prompt = this.buildSubagentPrompt(request);\n \n // Write context to temp file for large contexts\n const contextFile = path.join(this.tempDir, `${subagentId}-context.json`);\n await fs.promises.writeFile(\n contextFile,\n JSON.stringify(request.context, null, 2)\n );\n \n // Create result file path\n const resultFile = path.join(this.tempDir, `${subagentId}-result.json`);\n \n // Build the Task tool command\n // The Task tool will spawn a new Claude instance with the specified prompt\n const taskCommand = this.buildTaskCommand(request, prompt, contextFile, resultFile);\n \n // Execute via Claude Code's Task tool\n const result = await this.executeTaskTool(taskCommand, request.timeout);\n \n // Read result from file\n let subagentResult: any = {};\n if (fs.existsSync(resultFile)) {\n const resultContent = await fs.promises.readFile(resultFile, 'utf-8');\n try {\n subagentResult = JSON.parse(resultContent);\n } catch (e) {\n subagentResult = { rawOutput: resultContent };\n }\n }\n \n // Cleanup temp files\n this.cleanup(subagentId);\n \n return {\n success: true,\n result: subagentResult,\n output: result.stdout,\n duration: Date.now() - startTime,\n subagentType: request.type,\n tokens: this.estimateTokens(prompt + JSON.stringify(subagentResult)),\n };\n \n } catch (error: any) {\n logger.error(`Subagent execution failed: ${request.type}`, { error, subagentId });\n \n return {\n success: false,\n result: null,\n error: error.message,\n duration: Date.now() - startTime,\n subagentType: request.type,\n };\n }\n }\n \n /**\n * Execute multiple subagents in parallel\n */\n async executeParallel(requests: SubagentRequest[]): Promise<SubagentResponse[]> {\n logger.info(`Executing ${requests.length} subagents in parallel`);\n \n const promises = requests.map(request => this.executeSubagent(request));\n const results = await Promise.allSettled(promises);\n \n return results.map((result, index) => {\n if (result.status === 'fulfilled') {\n return result.value;\n } else {\n return {\n success: false,\n result: null,\n error: result.reason?.message || 'Unknown error',\n duration: 0,\n subagentType: requests[index].type,\n };\n }\n });\n }\n \n /**\n * Build subagent prompt based on type\n */\n private buildSubagentPrompt(request: SubagentRequest): string {\n const prompts: Record<string, string> = {\n planning: `You are a Planning Subagent. Your role is to decompose complex tasks into manageable subtasks.\n \n Task: ${request.task}\n \n Instructions:\n 1. Analyze the task and identify all components\n 2. Create a dependency graph of subtasks\n 3. Assign appropriate agent types to each subtask\n 4. Consider parallel execution opportunities\n 5. Include comprehensive testing at each stage\n \n Context is available in the provided file.\n \n Output a JSON structure with the task decomposition.`,\n \n code: `You are a Code Generation Subagent. Your role is to implement high-quality, production-ready code.\n \n Task: ${request.task}\n \n Instructions:\n 1. Write clean, maintainable code\n 2. Follow project conventions (check context)\n 3. Include comprehensive error handling\n 4. Add clear comments for complex logic\n 5. Ensure code is testable\n \n Context and requirements are in the provided file.\n \n Output the implementation code.`,\n \n testing: `You are a Testing Subagent specializing in comprehensive test generation.\n \n Task: ${request.task}\n \n Instructions:\n 1. Generate unit tests for all functions/methods\n 2. Create integration tests for API endpoints\n 3. Add E2E tests for critical user flows\n 4. Include edge cases and error scenarios\n 5. Ensure high code coverage (aim for 100%)\n 6. Validate that all tests pass\n \n Context and code to test are in the provided file.\n \n Output a complete test suite.`,\n \n linting: `You are a Linting Subagent ensuring code quality and standards.\n \n Task: ${request.task}\n \n Instructions:\n 1. Check for syntax errors and type issues\n 2. Verify code formatting and style\n 3. Identify security vulnerabilities\n 4. Find performance anti-patterns\n 5. Detect unused imports and dead code\n 6. Provide specific fixes for each issue\n \n Code to analyze is in the context file.\n \n Output a JSON report with issues and fixes.`,\n \n review: `You are a Code Review Subagent performing thorough multi-stage reviews.\n \n Task: ${request.task}\n \n Instructions:\n 1. Evaluate architecture and design patterns\n 2. Assess code quality and maintainability\n 3. Check performance implications\n 4. Review security considerations\n 5. Verify test coverage adequacy\n 6. Suggest specific improvements with examples\n 7. Rate quality on a 0-1 scale\n \n Code and context are in the provided file.\n \n Output a detailed review with quality score and improvements.`,\n \n improve: `You are an Improvement Subagent enhancing code based on reviews.\n \n Task: ${request.task}\n \n Instructions:\n 1. Implement all suggested improvements\n 2. Refactor for better architecture\n 3. Optimize performance bottlenecks\n 4. Enhance error handling\n 5. Improve code clarity and documentation\n 6. Add missing test cases\n 7. Ensure backward compatibility\n \n Review feedback and code are in the context file.\n \n Output the improved code.`,\n \n context: `You are a Context Retrieval Subagent finding relevant information.\n \n Task: ${request.task}\n \n Instructions:\n 1. Search project codebase for relevant code\n 2. Find similar implementations\n 3. Locate relevant documentation\n 4. Identify dependencies and patterns\n 5. Retrieve best practices\n \n Search parameters are in the context file.\n \n Output relevant context snippets.`,\n \n publish: `You are a Publishing Subagent handling releases and deployments.\n \n Task: ${request.task}\n \n Instructions:\n 1. Prepare package for publishing\n 2. Update version numbers\n 3. Generate changelog\n 4. Create GitHub release\n 5. Publish to NPM if applicable\n 6. Update documentation\n \n Release details are in the context file.\n \n Output the release plan and commands.`,\n };\n \n return request.systemPrompt || prompts[request.type] || prompts.planning;\n }\n \n /**\n * Build Task tool command\n * This creates a command that Claude Code's Task tool can execute\n */\n private buildTaskCommand(\n request: SubagentRequest,\n prompt: string,\n contextFile: string,\n resultFile: string\n ): string {\n // Create a script that the subagent will execute\n const scriptContent = `\n#!/bin/bash\n# Subagent execution script for ${request.type}\n\n# Read context\nCONTEXT=$(cat \"${contextFile}\")\n\n# Execute task based on type\ncase \"${request.type}\" in\n \"testing\")\n # For testing subagent, actually run tests\n echo \"Generating and running tests...\"\n # The subagent will generate test files and run them\n ;;\n \"linting\")\n # For linting subagent, run actual linters\n echo \"Running linters...\"\n npm run lint || true\n ;;\n \"code\")\n # For code generation, create implementation files\n echo \"Generating implementation...\"\n ;;\n *)\n # Default behavior\n echo \"Executing ${request.type} task...\"\n ;;\nesac\n\n# Write result\necho '{\"status\": \"completed\", \"type\": \"${request.type}\"}' > \"${resultFile}\"\n`;\n \n const scriptFile = path.join(this.tempDir, `${request.type}-script.sh`);\n fs.writeFileSync(scriptFile, scriptContent);\n fs.chmodSync(scriptFile, '755');\n \n // Return the command that Task tool will execute\n // In practice, this would trigger Claude Code's Task tool\n return scriptFile;\n }\n \n /**\n * Execute via Task tool (simulated for now)\n * In production, this would use Claude Code's actual Task tool API\n */\n private async executeTaskTool(\n command: string,\n timeout?: number\n ): Promise<{ stdout: string; stderr: string }> {\n try {\n // In production, this would call Claude Code's Task tool\n // For now, we simulate with a subprocess\n const result = await execAsync(command, {\n timeout: timeout || 300000, // 5 minutes default\n maxBuffer: 10 * 1024 * 1024, // 10MB buffer\n });\n \n return result;\n } catch (error: any) {\n if (error.killed || error.signal === 'SIGTERM') {\n throw new Error(`Subagent timeout after ${timeout}ms`);\n }\n throw error;\n }\n }\n \n /**\n * Estimate token usage\n */\n private estimateTokens(text: string): number {\n // Rough estimation: 1 token \u2248 4 characters\n return Math.ceil(text.length / 4);\n }\n \n /**\n * Cleanup temporary files\n */\n private cleanup(subagentId: string): void {\n const patterns = [\n `${subagentId}-context.json`,\n `${subagentId}-result.json`,\n `${subagentId}-script.sh`,\n ];\n \n for (const pattern of patterns) {\n const filePath = path.join(this.tempDir, pattern);\n if (fs.existsSync(filePath)) {\n try {\n fs.unlinkSync(filePath);\n } catch (e) {\n // Ignore cleanup errors\n }\n }\n }\n }\n \n /**\n * Create a mock Task tool response for development\n * This simulates what Claude Code's Task tool would return\n */\n async mockTaskToolExecution(request: SubagentRequest): Promise<SubagentResponse> {\n const startTime = Date.now();\n \n // Simulate processing delay\n await new Promise(resolve => setTimeout(resolve, 1000 + Math.random() * 2000));\n \n // Generate mock responses based on subagent type\n const mockResponses: Record<string, any> = {\n planning: {\n tasks: [\n { id: '1', type: 'analyze', description: 'Analyze requirements' },\n { id: '2', type: 'implement', description: 'Implement solution' },\n { id: '3', type: 'test', description: 'Test implementation' },\n { id: '4', type: 'review', description: 'Review and improve' },\n ],\n dependencies: { '2': ['1'], '3': ['2'], '4': ['3'] },\n },\n code: {\n implementation: `\nexport class Solution {\n constructor(private config: any) {}\n \n async execute(input: string): Promise<string> {\n // Implementation generated by Code subagent\n return this.process(input);\n }\n \n private process(input: string): string {\n return \\`Processed: \\${input}\\`;\n }\n}`,\n files: ['src/solution.ts'],\n },\n testing: {\n tests: `\ndescribe('Solution', () => {\n it('should process input correctly', () => {\n const solution = new Solution({});\n const result = solution.execute('test');\n expect(result).toBe('Processed: test');\n });\n \n it('should handle edge cases', () => {\n // Edge case tests\n });\n});`,\n coverage: { lines: 95, branches: 88, functions: 100 },\n },\n review: {\n quality: 0.82,\n issues: [\n { severity: 'high', message: 'Missing error handling' },\n { severity: 'medium', message: 'Could improve type safety' },\n ],\n suggestions: [\n 'Add try-catch blocks',\n 'Use stricter TypeScript types',\n 'Add input validation',\n ],\n },\n };\n \n return {\n success: true,\n result: mockResponses[request.type] || { status: 'completed' },\n output: `Mock ${request.type} subagent completed successfully`,\n duration: Date.now() - startTime,\n subagentType: request.type,\n tokens: Math.floor(Math.random() * 5000) + 1000,\n };\n }\n \n /**\n * Get active subagent statistics\n */\n getStats() {\n return {\n activeSubagents: this.activeSubagents.size,\n tempDir: this.tempDir,\n };\n }\n \n /**\n * Cleanup all resources\n */\n async cleanupAll(): Promise<void> {\n // Abort all active subagents\n for (const [id, controller] of this.activeSubagents) {\n controller.abort();\n }\n this.activeSubagents.clear();\n \n // Clean temp directory\n if (fs.existsSync(this.tempDir)) {\n const files = await fs.promises.readdir(this.tempDir);\n for (const file of files) {\n await fs.promises.unlink(path.join(this.tempDir, file));\n }\n }\n \n logger.info('Claude Code Subagent Client cleaned up');\n }\n}"],
|
|
5
|
-
"mappings": "AAOA,SAAS,cAAc;AACvB,SAAS,YAAY;AACrB,SAAS,iBAAiB;AAC1B,YAAY,QAAQ;AACpB,YAAY,UAAU;AACtB,YAAY,QAAQ;AAEpB,MAAM,YAAY,UAAU,IAAI;AAyBzB,MAAM,yBAAyB;AAAA,EAC5B;AAAA,EACA,kBAAgD,oBAAI,IAAI;AAAA,
|
|
4
|
+
"sourcesContent": ["/**\n * Claude Code Subagent Client\n * \n * Uses Claude Code's Task tool to spawn subagents instead of direct API calls\n * This leverages the Claude Code Max plan for unlimited subagent execution\n */\n\nimport { logger } from '../../core/monitoring/logger.js';\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\n\nconst execAsync = promisify(exec);\n\nexport interface SubagentRequest {\n type: 'planning' | 'code' | 'testing' | 'linting' | 'review' | 'improve' | 'context' | 'publish';\n task: string;\n context: Record<string, any>;\n systemPrompt?: string;\n files?: string[];\n timeout?: number;\n}\n\nexport interface SubagentResponse {\n success: boolean;\n result: any;\n output?: string;\n error?: string;\n tokens?: number;\n duration: number;\n subagentType: string;\n}\n\n/**\n * Claude Code Subagent Client\n * Spawns subagents using Claude Code's Task tool\n */\nexport class ClaudeCodeSubagentClient {\n private tempDir: string;\n private activeSubagents: Map<string, AbortController> = new Map();\n private mockMode: boolean;\n \n constructor(mockMode: boolean = true) { // Default to mock mode for testing\n this.mockMode = mockMode;\n \n // Create temp directory for subagent communication\n this.tempDir = path.join(os.tmpdir(), 'stackmemory-rlm');\n if (!fs.existsSync(this.tempDir)) {\n fs.mkdirSync(this.tempDir, { recursive: true });\n }\n \n logger.info('Claude Code Subagent Client initialized', {\n tempDir: this.tempDir,\n mockMode: this.mockMode,\n });\n }\n \n /**\n * Execute a subagent task using Claude Code's Task tool\n * This will spawn a new Claude instance with specific instructions\n */\n async executeSubagent(request: SubagentRequest): Promise<SubagentResponse> {\n const startTime = Date.now();\n const subagentId = `${request.type}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n \n logger.info(`Spawning ${request.type} subagent`, {\n subagentId,\n task: request.task.slice(0, 100),\n mockMode: this.mockMode,\n });\n \n // Return mock responses for testing\n if (this.mockMode) {\n return this.getMockResponse(request, startTime, subagentId);\n }\n \n try {\n // Create subagent prompt based on type\n const prompt = this.buildSubagentPrompt(request);\n \n // Write context to temp file for large contexts\n const contextFile = path.join(this.tempDir, `${subagentId}-context.json`);\n await fs.promises.writeFile(\n contextFile,\n JSON.stringify(request.context, null, 2)\n );\n \n // Create result file path\n const resultFile = path.join(this.tempDir, `${subagentId}-result.json`);\n \n // Build the Task tool command\n // The Task tool will spawn a new Claude instance with the specified prompt\n const taskCommand = this.buildTaskCommand(request, prompt, contextFile, resultFile);\n \n // Execute via Claude Code's Task tool\n const result = await this.executeTaskTool(taskCommand, request.timeout);\n \n // Read result from file\n let subagentResult: any = {};\n if (fs.existsSync(resultFile)) {\n const resultContent = await fs.promises.readFile(resultFile, 'utf-8');\n try {\n subagentResult = JSON.parse(resultContent);\n } catch (e) {\n subagentResult = { rawOutput: resultContent };\n }\n }\n \n // Cleanup temp files\n this.cleanup(subagentId);\n \n return {\n success: true,\n result: subagentResult,\n output: result.stdout,\n duration: Date.now() - startTime,\n subagentType: request.type,\n tokens: this.estimateTokens(prompt + JSON.stringify(subagentResult)),\n };\n \n } catch (error: any) {\n logger.error(`Subagent execution failed: ${request.type}`, { error, subagentId });\n \n return {\n success: false,\n result: null,\n error: error.message,\n duration: Date.now() - startTime,\n subagentType: request.type,\n };\n }\n }\n \n /**\n * Execute multiple subagents in parallel\n */\n async executeParallel(requests: SubagentRequest[]): Promise<SubagentResponse[]> {\n logger.info(`Executing ${requests.length} subagents in parallel`);\n \n const promises = requests.map(request => this.executeSubagent(request));\n const results = await Promise.allSettled(promises);\n \n return results.map((result, index) => {\n if (result.status === 'fulfilled') {\n return result.value;\n } else {\n return {\n success: false,\n result: null,\n error: result.reason?.message || 'Unknown error',\n duration: 0,\n subagentType: requests[index].type,\n };\n }\n });\n }\n \n /**\n * Build subagent prompt based on type\n */\n private buildSubagentPrompt(request: SubagentRequest): string {\n const prompts: Record<string, string> = {\n planning: `You are a Planning Subagent. Your role is to decompose complex tasks into manageable subtasks.\n \n Task: ${request.task}\n \n Instructions:\n 1. Analyze the task and identify all components\n 2. Create a dependency graph of subtasks\n 3. Assign appropriate agent types to each subtask\n 4. Consider parallel execution opportunities\n 5. Include comprehensive testing at each stage\n \n Context is available in the provided file.\n \n Output a JSON structure with the task decomposition.`,\n \n code: `You are a Code Generation Subagent. Your role is to implement high-quality, production-ready code.\n \n Task: ${request.task}\n \n Instructions:\n 1. Write clean, maintainable code\n 2. Follow project conventions (check context)\n 3. Include comprehensive error handling\n 4. Add clear comments for complex logic\n 5. Ensure code is testable\n \n Context and requirements are in the provided file.\n \n Output the implementation code.`,\n \n testing: `You are a Testing Subagent specializing in comprehensive test generation.\n \n Task: ${request.task}\n \n Instructions:\n 1. Generate unit tests for all functions/methods\n 2. Create integration tests for API endpoints\n 3. Add E2E tests for critical user flows\n 4. Include edge cases and error scenarios\n 5. Ensure high code coverage (aim for 100%)\n 6. Validate that all tests pass\n \n Context and code to test are in the provided file.\n \n Output a complete test suite.`,\n \n linting: `You are a Linting Subagent ensuring code quality and standards.\n \n Task: ${request.task}\n \n Instructions:\n 1. Check for syntax errors and type issues\n 2. Verify code formatting and style\n 3. Identify security vulnerabilities\n 4. Find performance anti-patterns\n 5. Detect unused imports and dead code\n 6. Provide specific fixes for each issue\n \n Code to analyze is in the context file.\n \n Output a JSON report with issues and fixes.`,\n \n review: `You are a Code Review Subagent performing thorough multi-stage reviews.\n \n Task: ${request.task}\n \n Instructions:\n 1. Evaluate architecture and design patterns\n 2. Assess code quality and maintainability\n 3. Check performance implications\n 4. Review security considerations\n 5. Verify test coverage adequacy\n 6. Suggest specific improvements with examples\n 7. Rate quality on a 0-1 scale\n \n Code and context are in the provided file.\n \n Output a detailed review with quality score and improvements.`,\n \n improve: `You are an Improvement Subagent enhancing code based on reviews.\n \n Task: ${request.task}\n \n Instructions:\n 1. Implement all suggested improvements\n 2. Refactor for better architecture\n 3. Optimize performance bottlenecks\n 4. Enhance error handling\n 5. Improve code clarity and documentation\n 6. Add missing test cases\n 7. Ensure backward compatibility\n \n Review feedback and code are in the context file.\n \n Output the improved code.`,\n \n context: `You are a Context Retrieval Subagent finding relevant information.\n \n Task: ${request.task}\n \n Instructions:\n 1. Search project codebase for relevant code\n 2. Find similar implementations\n 3. Locate relevant documentation\n 4. Identify dependencies and patterns\n 5. Retrieve best practices\n \n Search parameters are in the context file.\n \n Output relevant context snippets.`,\n \n publish: `You are a Publishing Subagent handling releases and deployments.\n \n Task: ${request.task}\n \n Instructions:\n 1. Prepare package for publishing\n 2. Update version numbers\n 3. Generate changelog\n 4. Create GitHub release\n 5. Publish to NPM if applicable\n 6. Update documentation\n \n Release details are in the context file.\n \n Output the release plan and commands.`,\n };\n \n return request.systemPrompt || prompts[request.type] || prompts.planning;\n }\n \n /**\n * Build Task tool command\n * This creates a command that Claude Code's Task tool can execute\n */\n private buildTaskCommand(\n request: SubagentRequest,\n prompt: string,\n contextFile: string,\n resultFile: string\n ): string {\n // Create a script that the subagent will execute\n const scriptContent = `\n#!/bin/bash\n# Subagent execution script for ${request.type}\n\n# Read context\nCONTEXT=$(cat \"${contextFile}\")\n\n# Execute task based on type\ncase \"${request.type}\" in\n \"testing\")\n # For testing subagent, actually run tests\n echo \"Generating and running tests...\"\n # The subagent will generate test files and run them\n ;;\n \"linting\")\n # For linting subagent, run actual linters\n echo \"Running linters...\"\n npm run lint || true\n ;;\n \"code\")\n # For code generation, create implementation files\n echo \"Generating implementation...\"\n ;;\n *)\n # Default behavior\n echo \"Executing ${request.type} task...\"\n ;;\nesac\n\n# Write result\necho '{\"status\": \"completed\", \"type\": \"${request.type}\"}' > \"${resultFile}\"\n`;\n \n const scriptFile = path.join(this.tempDir, `${request.type}-script.sh`);\n fs.writeFileSync(scriptFile, scriptContent);\n fs.chmodSync(scriptFile, '755');\n \n // Return the command that Task tool will execute\n // In practice, this would trigger Claude Code's Task tool\n return scriptFile;\n }\n \n /**\n * Execute via Task tool (simulated for now)\n * In production, this would use Claude Code's actual Task tool API\n */\n private async executeTaskTool(\n command: string,\n timeout?: number\n ): Promise<{ stdout: string; stderr: string }> {\n try {\n // In production, this would call Claude Code's Task tool\n // For now, we simulate with a subprocess\n const result = await execAsync(command, {\n timeout: timeout || 300000, // 5 minutes default\n maxBuffer: 10 * 1024 * 1024, // 10MB buffer\n });\n \n return result;\n } catch (error: any) {\n if (error.killed || error.signal === 'SIGTERM') {\n throw new Error(`Subagent timeout after ${timeout}ms`);\n }\n throw error;\n }\n }\n \n /**\n * Get mock response for testing\n */\n private async getMockResponse(\n request: SubagentRequest, \n startTime: number, \n subagentId: string\n ): Promise<SubagentResponse> {\n // Simulate some processing time\n await new Promise(resolve => setTimeout(resolve, Math.random() * 20 + 10));\n \n const mockResponses: Record<string, any> = {\n planning: {\n tasks: [\n { id: 'task-1', name: 'Analyze requirements', type: 'analysis' },\n { id: 'task-2', name: 'Design solution', type: 'design' },\n { id: 'task-3', name: 'Implement solution', type: 'implementation' },\n ],\n dependencies: [],\n estimated_time: 300,\n },\n \n code: {\n implementation: `function greetUser(name: string): string {\n if (!name || typeof name !== 'string') {\n throw new Error('Invalid name parameter');\n }\n return \\`Hello, \\${name}!\\`;\n}`,\n files_modified: ['src/greet.ts'],\n lines_added: 6,\n lines_removed: 0,\n },\n \n testing: {\n tests: [\n {\n name: 'greetUser should return greeting',\n code: `test('greetUser should return greeting', () => {\n expect(greetUser('Alice')).toBe('Hello, Alice!');\n});`,\n type: 'unit',\n },\n ],\n coverage: { lines: 100, branches: 100, functions: 100 },\n },\n \n linting: {\n issues: [],\n fixes: [],\n passed: true,\n },\n \n review: {\n quality: 0.85,\n issues: [\n 'Consider adding JSDoc comments',\n 'Could add more edge case tests',\n ],\n suggestions: [\n 'Add documentation for the function',\n 'Consider adding internationalization support',\n 'Add performance tests for large inputs',\n ],\n improvements: [],\n },\n \n improve: {\n improved_code: `/**\n * Greets a user with their name\n * @param name - The name of the user to greet\n * @returns A greeting message\n * @throws {Error} If name is invalid\n */\nfunction greetUser(name: string): string {\n if (!name || typeof name !== 'string') {\n throw new Error('Invalid name parameter: name must be a non-empty string');\n }\n return \\`Hello, \\${name}!\\`;\n}`,\n changes_made: [\n 'Added JSDoc documentation',\n 'Improved error message',\n ],\n },\n \n context: {\n relevant_files: ['src/greet.ts', 'test/greet.test.ts'],\n patterns: ['greeting functions', 'input validation'],\n dependencies: [],\n },\n \n publish: {\n version: '1.0.0',\n changelog: 'Initial release',\n published: false,\n reason: 'Mock mode - no actual publishing',\n },\n };\n \n const result = mockResponses[request.type] || {};\n \n return {\n success: true,\n result,\n output: `Mock ${request.type} subagent completed successfully`,\n duration: Date.now() - startTime,\n subagentType: request.type,\n tokens: this.estimateTokens(JSON.stringify(result)),\n };\n }\n \n /**\n * Estimate token usage\n */\n private estimateTokens(text: string): number {\n // Rough estimation: 1 token \u2248 4 characters\n return Math.ceil(text.length / 4);\n }\n \n /**\n * Cleanup temporary files\n */\n private cleanup(subagentId: string): void {\n const patterns = [\n `${subagentId}-context.json`,\n `${subagentId}-result.json`,\n `${subagentId}-script.sh`,\n ];\n \n for (const pattern of patterns) {\n const filePath = path.join(this.tempDir, pattern);\n if (fs.existsSync(filePath)) {\n try {\n fs.unlinkSync(filePath);\n } catch (e) {\n // Ignore cleanup errors\n }\n }\n }\n }\n \n /**\n * Create a mock Task tool response for development\n * This simulates what Claude Code's Task tool would return\n */\n async mockTaskToolExecution(request: SubagentRequest): Promise<SubagentResponse> {\n const startTime = Date.now();\n \n // Simulate processing delay\n await new Promise(resolve => setTimeout(resolve, 1000 + Math.random() * 2000));\n \n // Generate mock responses based on subagent type\n const mockResponses: Record<string, any> = {\n planning: {\n tasks: [\n { id: '1', type: 'analyze', description: 'Analyze requirements' },\n { id: '2', type: 'implement', description: 'Implement solution' },\n { id: '3', type: 'test', description: 'Test implementation' },\n { id: '4', type: 'review', description: 'Review and improve' },\n ],\n dependencies: { '2': ['1'], '3': ['2'], '4': ['3'] },\n },\n code: {\n implementation: `\nexport class Solution {\n constructor(private config: any) {}\n \n async execute(input: string): Promise<string> {\n // Implementation generated by Code subagent\n return this.process(input);\n }\n \n private process(input: string): string {\n return \\`Processed: \\${input}\\`;\n }\n}`,\n files: ['src/solution.ts'],\n },\n testing: {\n tests: `\ndescribe('Solution', () => {\n it('should process input correctly', () => {\n const solution = new Solution({});\n const result = solution.execute('test');\n expect(result).toBe('Processed: test');\n });\n \n it('should handle edge cases', () => {\n // Edge case tests\n });\n});`,\n coverage: { lines: 95, branches: 88, functions: 100 },\n },\n review: {\n quality: 0.82,\n issues: [\n { severity: 'high', message: 'Missing error handling' },\n { severity: 'medium', message: 'Could improve type safety' },\n ],\n suggestions: [\n 'Add try-catch blocks',\n 'Use stricter TypeScript types',\n 'Add input validation',\n ],\n },\n };\n \n return {\n success: true,\n result: mockResponses[request.type] || { status: 'completed' },\n output: `Mock ${request.type} subagent completed successfully`,\n duration: Date.now() - startTime,\n subagentType: request.type,\n tokens: Math.floor(Math.random() * 5000) + 1000,\n };\n }\n \n /**\n * Get active subagent statistics\n */\n getStats() {\n return {\n activeSubagents: this.activeSubagents.size,\n tempDir: this.tempDir,\n };\n }\n \n /**\n * Cleanup all resources\n */\n async cleanupAll(): Promise<void> {\n // Abort all active subagents\n for (const [id, controller] of this.activeSubagents) {\n controller.abort();\n }\n this.activeSubagents.clear();\n \n // Clean temp directory\n if (fs.existsSync(this.tempDir)) {\n const files = await fs.promises.readdir(this.tempDir);\n for (const file of files) {\n await fs.promises.unlink(path.join(this.tempDir, file));\n }\n }\n \n logger.info('Claude Code Subagent Client cleaned up');\n }\n}"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
function getRailwayConfig() {
|
|
2
|
+
const corsOrigins = process.env.CORS_ORIGINS?.split(",") || [
|
|
3
|
+
"https://claude.ai",
|
|
4
|
+
"https://claude.anthropic.com",
|
|
5
|
+
"http://localhost:3000"
|
|
6
|
+
];
|
|
7
|
+
let redisUrl = process.env.REDIS_URL || "";
|
|
8
|
+
if (!redisUrl && process.env.REDISHOST) {
|
|
9
|
+
const host = process.env.REDISHOST;
|
|
10
|
+
const port = process.env.REDISPORT || "6379";
|
|
11
|
+
const user = process.env.REDISUSER || "default";
|
|
12
|
+
const password = process.env.REDISPASSWORD || "";
|
|
13
|
+
if (password) {
|
|
14
|
+
redisUrl = `redis://${user}:${password}@${host}:${port}`;
|
|
15
|
+
} else {
|
|
16
|
+
redisUrl = `redis://${host}:${port}`;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
if (!redisUrl && process.env.NODE_ENV !== "production") {
|
|
20
|
+
redisUrl = "redis://localhost:6379";
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
// Server
|
|
24
|
+
port: parseInt(process.env.PORT || "3000"),
|
|
25
|
+
environment: process.env.NODE_ENV || "development",
|
|
26
|
+
// Database - Railway provides this as DATABASE_URL
|
|
27
|
+
databaseUrl: process.env.DATABASE_URL || "postgresql://localhost:5432/stackmemory",
|
|
28
|
+
// Redis
|
|
29
|
+
redisUrl,
|
|
30
|
+
redisHost: process.env.REDISHOST || "localhost",
|
|
31
|
+
redisPort: parseInt(process.env.REDISPORT || "6379"),
|
|
32
|
+
redisUser: process.env.REDISUSER,
|
|
33
|
+
redisPassword: process.env.REDISPASSWORD,
|
|
34
|
+
// Auth
|
|
35
|
+
authMode: process.env.AUTH_MODE || "api_key",
|
|
36
|
+
apiKeySecret: process.env.API_KEY_SECRET || "development-secret",
|
|
37
|
+
jwtSecret: process.env.JWT_SECRET || "development-jwt-secret",
|
|
38
|
+
// Features
|
|
39
|
+
corsOrigins,
|
|
40
|
+
rateLimitEnabled: process.env.RATE_LIMIT_ENABLED === "true",
|
|
41
|
+
rateLimitFree: parseInt(process.env.RATE_LIMIT_FREE || "100"),
|
|
42
|
+
enableWebSocket: process.env.ENABLE_WEBSOCKET !== "false",
|
|
43
|
+
enableAnalytics: process.env.ENABLE_ANALYTICS === "true",
|
|
44
|
+
// Storage mode
|
|
45
|
+
storageMode: process.env.STORAGE_MODE || "hybrid"
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export {
|
|
49
|
+
getRailwayConfig
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/servers/railway/config.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Railway Server Configuration\n * Handles Railway-specific environment variables and service references\n */\n\nexport interface RailwayConfig {\n // Server\n port: number;\n environment: string;\n \n // Database\n databaseUrl: string;\n \n // Redis\n redisUrl: string;\n redisHost: string;\n redisPort: number;\n redisUser?: string;\n redisPassword?: string;\n \n // Auth\n authMode: string;\n apiKeySecret: string;\n jwtSecret: string;\n \n // Features\n corsOrigins: string[];\n rateLimitEnabled: boolean;\n rateLimitFree: number;\n enableWebSocket: boolean;\n enableAnalytics: boolean;\n \n // Storage\n storageMode: 'redis' | 'postgres' | 'hybrid';\n}\n\n/**\n * Get Railway configuration with proper service references\n * Railway provides reference variables like ${{Postgres.DATABASE_URL}}\n */\nexport function getRailwayConfig(): RailwayConfig {\n // Parse CORS origins\n const corsOrigins = process.env.CORS_ORIGINS?.split(',') || [\n 'https://claude.ai',\n 'https://claude.anthropic.com',\n 'http://localhost:3000'\n ];\n \n // Build Redis URL from Railway reference variables\n // Railway typically provides: REDIS_URL or individual components\n let redisUrl = process.env.REDIS_URL || '';\n \n // If no REDIS_URL, try to build from components\n if (!redisUrl && process.env.REDISHOST) {\n const host = process.env.REDISHOST;\n const port = process.env.REDISPORT || '6379';\n const user = process.env.REDISUSER || 'default';\n const password = process.env.REDISPASSWORD || '';\n \n if (password) {\n redisUrl = `redis://${user}:${password}@${host}:${port}`;\n } else {\n redisUrl = `redis://${host}:${port}`;\n }\n }\n \n // Fallback to local Redis if not in production\n if (!redisUrl && process.env.NODE_ENV !== 'production') {\n redisUrl = 'redis://localhost:6379';\n }\n \n return {\n // Server\n port: parseInt(process.env.PORT || '3000'),\n environment: process.env.NODE_ENV || 'development',\n \n // Database - Railway provides this as DATABASE_URL\n databaseUrl: process.env.DATABASE_URL || 'postgresql://localhost:5432/stackmemory',\n \n // Redis\n redisUrl,\n redisHost: process.env.REDISHOST || 'localhost',\n redisPort: parseInt(process.env.REDISPORT || '6379'),\n redisUser: process.env.REDISUSER,\n redisPassword: process.env.REDISPASSWORD,\n \n // Auth\n authMode: process.env.AUTH_MODE || 'api_key',\n apiKeySecret: process.env.API_KEY_SECRET || 'development-secret',\n jwtSecret: process.env.JWT_SECRET || 'development-jwt-secret',\n \n // Features\n corsOrigins,\n rateLimitEnabled: process.env.RATE_LIMIT_ENABLED === 'true',\n rateLimitFree: parseInt(process.env.RATE_LIMIT_FREE || '100'),\n enableWebSocket: process.env.ENABLE_WEBSOCKET !== 'false',\n enableAnalytics: process.env.ENABLE_ANALYTICS === 'true',\n \n // Storage mode\n storageMode: (process.env.STORAGE_MODE as any) || 'hybrid'\n };\n}"],
|
|
5
|
+
"mappings": "AAwCO,SAAS,mBAAkC;AAEhD,QAAM,cAAc,QAAQ,IAAI,cAAc,MAAM,GAAG,KAAK;AAAA,IAC1D;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAIA,MAAI,WAAW,QAAQ,IAAI,aAAa;AAGxC,MAAI,CAAC,YAAY,QAAQ,IAAI,WAAW;AACtC,UAAM,OAAO,QAAQ,IAAI;AACzB,UAAM,OAAO,QAAQ,IAAI,aAAa;AACtC,UAAM,OAAO,QAAQ,IAAI,aAAa;AACtC,UAAM,WAAW,QAAQ,IAAI,iBAAiB;AAE9C,QAAI,UAAU;AACZ,iBAAW,WAAW,IAAI,IAAI,QAAQ,IAAI,IAAI,IAAI,IAAI;AAAA,IACxD,OAAO;AACL,iBAAW,WAAW,IAAI,IAAI,IAAI;AAAA,IACpC;AAAA,EACF;AAGA,MAAI,CAAC,YAAY,QAAQ,IAAI,aAAa,cAAc;AACtD,eAAW;AAAA,EACb;AAEA,SAAO;AAAA;AAAA,IAEL,MAAM,SAAS,QAAQ,IAAI,QAAQ,MAAM;AAAA,IACzC,aAAa,QAAQ,IAAI,YAAY;AAAA;AAAA,IAGrC,aAAa,QAAQ,IAAI,gBAAgB;AAAA;AAAA,IAGzC;AAAA,IACA,WAAW,QAAQ,IAAI,aAAa;AAAA,IACpC,WAAW,SAAS,QAAQ,IAAI,aAAa,MAAM;AAAA,IACnD,WAAW,QAAQ,IAAI;AAAA,IACvB,eAAe,QAAQ,IAAI;AAAA;AAAA,IAG3B,UAAU,QAAQ,IAAI,aAAa;AAAA,IACnC,cAAc,QAAQ,IAAI,kBAAkB;AAAA,IAC5C,WAAW,QAAQ,IAAI,cAAc;AAAA;AAAA,IAGrC;AAAA,IACA,kBAAkB,QAAQ,IAAI,uBAAuB;AAAA,IACrD,eAAe,SAAS,QAAQ,IAAI,mBAAmB,KAAK;AAAA,IAC5D,iBAAiB,QAAQ,IAAI,qBAAqB;AAAA,IAClD,iBAAiB,QAAQ,IAAI,qBAAqB;AAAA;AAAA,IAGlD,aAAc,QAAQ,IAAI,gBAAwB;AAAA,EACpD;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|