all-hands-cli 0.1.0
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/.allhands/README.md +75 -0
- package/.allhands/agents/compounder.yaml +15 -0
- package/.allhands/agents/coordinator.yaml +17 -0
- package/.allhands/agents/documentor.yaml +15 -0
- package/.allhands/agents/e2e-test-planner.yaml +17 -0
- package/.allhands/agents/emergent.yaml +22 -0
- package/.allhands/agents/executor.yaml +14 -0
- package/.allhands/agents/ideation.yaml +11 -0
- package/.allhands/agents/initiative-steering.yaml +19 -0
- package/.allhands/agents/judge.yaml +13 -0
- package/.allhands/agents/planner.yaml +19 -0
- package/.allhands/agents/pr-reviewer.yaml +15 -0
- package/.allhands/docs.json +5 -0
- package/.allhands/docs.local.json +26 -0
- package/.allhands/flows/COMPOUNDING.md +203 -0
- package/.allhands/flows/COORDINATION.md +89 -0
- package/.allhands/flows/CORE.md +87 -0
- package/.allhands/flows/DOCUMENTATION.md +218 -0
- package/.allhands/flows/E2E_TEST_PLAN_BUILDING.md +140 -0
- package/.allhands/flows/EMERGENT_PLANNING.md +57 -0
- package/.allhands/flows/IDEATION_SCOPING.md +154 -0
- package/.allhands/flows/INITIATIVE_STEERING.md +110 -0
- package/.allhands/flows/JUDGE_REVIEWING.md +79 -0
- package/.allhands/flows/PROMPT_TASK_EXECUTION.md +68 -0
- package/.allhands/flows/PR_REVIEWING.md +43 -0
- package/.allhands/flows/SPEC_PLANNING.md +216 -0
- package/.allhands/flows/harness/WRITING_HARNESS_FLOWS.md +27 -0
- package/.allhands/flows/harness/WRITING_HARNESS_KNOWLEDGE.md +27 -0
- package/.allhands/flows/harness/WRITING_HARNESS_ORCHESTRATION.md +27 -0
- package/.allhands/flows/harness/WRITING_HARNESS_SKILLS.md +27 -0
- package/.allhands/flows/harness/WRITING_HARNESS_TOOLS.md +27 -0
- package/.allhands/flows/harness/WRITING_HARNESS_VALIDATION_TOOLING.md +27 -0
- package/.allhands/flows/shared/CODEBASE_UNDERSTANDING.md +72 -0
- package/.allhands/flows/shared/CREATE_HARNESS_SPEC.md +48 -0
- package/.allhands/flows/shared/CREATE_SPEC.md +41 -0
- package/.allhands/flows/shared/CREATE_VALIDATION_TOOLING_SPEC.md +70 -0
- package/.allhands/flows/shared/DOCUMENTATION_DISCOVERY.md +123 -0
- package/.allhands/flows/shared/DOCUMENTATION_WRITER.md +101 -0
- package/.allhands/flows/shared/EMERGENT_REFINEMENT_ANALYSIS.md +76 -0
- package/.allhands/flows/shared/EXTERNAL_TECH_GUIDANCE.md +97 -0
- package/.allhands/flows/shared/IDEATION_CODEBASE_GROUNDING.md +49 -0
- package/.allhands/flows/shared/PLAN_DEEPENING.md +152 -0
- package/.allhands/flows/shared/PROMPT_TASKS_CURATION.md +113 -0
- package/.allhands/flows/shared/PROMPT_VALIDATION_REVIEW.MD +99 -0
- package/.allhands/flows/shared/QUICK_PREMORTEM.md +70 -0
- package/.allhands/flows/shared/RESEARCH_GUIDANCE.md +38 -0
- package/.allhands/flows/shared/REVIEW_OPTIONS_BREAKDOWN.md +68 -0
- package/.allhands/flows/shared/SKILL_EXTRACTION.md +84 -0
- package/.allhands/flows/shared/SPEC_FLOW_ANALYSIS.md +119 -0
- package/.allhands/flows/shared/TDD_WORKFLOW.md +109 -0
- package/.allhands/flows/shared/UTILIZE_VALIDATION_TOOLING.md +84 -0
- package/.allhands/flows/shared/WRITING_HARNESS_FLOWS.md +11 -0
- package/.allhands/flows/shared/WRITING_HARNESS_MCP_TOOLS.md +84 -0
- package/.allhands/flows/shared/jury/ARCHITECTURE_REVIEW.md +91 -0
- package/.allhands/flows/shared/jury/BEST_PRACTICES_REVIEW.md +80 -0
- package/.allhands/flows/shared/jury/CLAIM_VERIFICATION_REVIEW.md +101 -0
- package/.allhands/flows/shared/jury/EXPECTATIONS_FIT_REVIEW.md +78 -0
- package/.allhands/flows/shared/jury/MAINTAINABILITY_REVIEW.md +110 -0
- package/.allhands/flows/shared/jury/PROMPTS_EXPECTATIONS_FIT.md +74 -0
- package/.allhands/flows/shared/jury/PROMPTS_FLOW_ANALYSIS.md +92 -0
- package/.allhands/flows/shared/jury/PROMPTS_YAGNI.md +78 -0
- package/.allhands/flows/shared/jury/PROMPT_PREMORTEM.md +125 -0
- package/.allhands/flows/shared/jury/SECURITY_REVIEW.md +86 -0
- package/.allhands/flows/shared/jury/YAGNI_REVIEW.md +82 -0
- package/.allhands/flows/wip/DEBUG_INVESTIGATION.md +162 -0
- package/.allhands/flows/wip/MEMORY_RECALL.md +62 -0
- package/.allhands/harness/ah +131 -0
- package/.allhands/harness/package-lock.json +5292 -0
- package/.allhands/harness/package.json +52 -0
- package/.allhands/harness/src/__tests__/e2e/commands.test.ts +307 -0
- package/.allhands/harness/src/__tests__/e2e/event-loop.test.ts +539 -0
- package/.allhands/harness/src/__tests__/e2e/hooks.test.ts +427 -0
- package/.allhands/harness/src/__tests__/e2e/new-initiative-routing.test.ts +137 -0
- package/.allhands/harness/src/__tests__/e2e/run-e2e.ts +109 -0
- package/.allhands/harness/src/__tests__/e2e/specs-type.test.ts +210 -0
- package/.allhands/harness/src/__tests__/e2e/validation-hooks.test.ts +669 -0
- package/.allhands/harness/src/__tests__/e2e/validation-path-consistency.test.ts +354 -0
- package/.allhands/harness/src/__tests__/e2e/validation.test.ts +528 -0
- package/.allhands/harness/src/__tests__/harness/assertions.ts +318 -0
- package/.allhands/harness/src/__tests__/harness/cli-runner.ts +359 -0
- package/.allhands/harness/src/__tests__/harness/fixture.ts +384 -0
- package/.allhands/harness/src/__tests__/harness/hook-runner.ts +411 -0
- package/.allhands/harness/src/__tests__/harness/index.ts +122 -0
- package/.allhands/harness/src/cli.ts +36 -0
- package/.allhands/harness/src/commands/complexity.ts +177 -0
- package/.allhands/harness/src/commands/context7.ts +202 -0
- package/.allhands/harness/src/commands/docs.ts +557 -0
- package/.allhands/harness/src/commands/hooks.ts +24 -0
- package/.allhands/harness/src/commands/index.ts +51 -0
- package/.allhands/harness/src/commands/knowledge.ts +382 -0
- package/.allhands/harness/src/commands/memories.ts +302 -0
- package/.allhands/harness/src/commands/notify.ts +61 -0
- package/.allhands/harness/src/commands/oracle.ts +158 -0
- package/.allhands/harness/src/commands/perplexity.ts +220 -0
- package/.allhands/harness/src/commands/planning.ts +245 -0
- package/.allhands/harness/src/commands/schema.ts +73 -0
- package/.allhands/harness/src/commands/skills.ts +128 -0
- package/.allhands/harness/src/commands/solutions.ts +353 -0
- package/.allhands/harness/src/commands/spawn.ts +158 -0
- package/.allhands/harness/src/commands/specs.ts +532 -0
- package/.allhands/harness/src/commands/tavily.ts +226 -0
- package/.allhands/harness/src/commands/tools.ts +579 -0
- package/.allhands/harness/src/commands/trace.ts +327 -0
- package/.allhands/harness/src/commands/tui.ts +960 -0
- package/.allhands/harness/src/commands/validate.ts +143 -0
- package/.allhands/harness/src/commands/validation-tools.ts +108 -0
- package/.allhands/harness/src/hooks/context.ts +1442 -0
- package/.allhands/harness/src/hooks/enforcement.ts +170 -0
- package/.allhands/harness/src/hooks/index.ts +54 -0
- package/.allhands/harness/src/hooks/lifecycle.ts +229 -0
- package/.allhands/harness/src/hooks/notification.ts +104 -0
- package/.allhands/harness/src/hooks/observability.ts +551 -0
- package/.allhands/harness/src/hooks/session.ts +88 -0
- package/.allhands/harness/src/hooks/shared.ts +815 -0
- package/.allhands/harness/src/hooks/transcript-parser.ts +208 -0
- package/.allhands/harness/src/hooks/validation.ts +617 -0
- package/.allhands/harness/src/lib/__tests__/ctags.test.ts +244 -0
- package/.allhands/harness/src/lib/__tests__/docs-validation.test.ts +344 -0
- package/.allhands/harness/src/lib/__tests__/mcp-runtime.test.ts +190 -0
- package/.allhands/harness/src/lib/__tests__/schema.test.ts +861 -0
- package/.allhands/harness/src/lib/base-command.ts +198 -0
- package/.allhands/harness/src/lib/cli-daemon.ts +343 -0
- package/.allhands/harness/src/lib/compaction.ts +313 -0
- package/.allhands/harness/src/lib/ctags.ts +497 -0
- package/.allhands/harness/src/lib/docs-validation.ts +907 -0
- package/.allhands/harness/src/lib/event-loop.ts +662 -0
- package/.allhands/harness/src/lib/flows.ts +155 -0
- package/.allhands/harness/src/lib/git.ts +276 -0
- package/.allhands/harness/src/lib/knowledge-worker.ts +72 -0
- package/.allhands/harness/src/lib/knowledge.ts +810 -0
- package/.allhands/harness/src/lib/llm.ts +255 -0
- package/.allhands/harness/src/lib/mcp-client.ts +432 -0
- package/.allhands/harness/src/lib/mcp-daemon.ts +486 -0
- package/.allhands/harness/src/lib/mcp-runtime.ts +418 -0
- package/.allhands/harness/src/lib/notification.ts +115 -0
- package/.allhands/harness/src/lib/opencode/index.ts +70 -0
- package/.allhands/harness/src/lib/opencode/profiles.ts +300 -0
- package/.allhands/harness/src/lib/opencode/prompts/codesearch.md +98 -0
- package/.allhands/harness/src/lib/opencode/prompts/knowledge-aggregator.md +67 -0
- package/.allhands/harness/src/lib/opencode/runner.ts +281 -0
- package/.allhands/harness/src/lib/oracle.ts +926 -0
- package/.allhands/harness/src/lib/planning-utils.ts +150 -0
- package/.allhands/harness/src/lib/planning.ts +605 -0
- package/.allhands/harness/src/lib/pr-review.ts +225 -0
- package/.allhands/harness/src/lib/prompts.ts +522 -0
- package/.allhands/harness/src/lib/schema.ts +418 -0
- package/.allhands/harness/src/lib/schemas/agent-profile.ts +141 -0
- package/.allhands/harness/src/lib/schemas/template-vars.ts +138 -0
- package/.allhands/harness/src/lib/session.ts +164 -0
- package/.allhands/harness/src/lib/specs.ts +348 -0
- package/.allhands/harness/src/lib/tldr.ts +829 -0
- package/.allhands/harness/src/lib/tmux.ts +1051 -0
- package/.allhands/harness/src/lib/trace-store.ts +714 -0
- package/.allhands/harness/src/mcp/__tests__/index.test.ts +46 -0
- package/.allhands/harness/src/mcp/_template.ts +47 -0
- package/.allhands/harness/src/mcp/filesystem.ts +33 -0
- package/.allhands/harness/src/mcp/index.ts +69 -0
- package/.allhands/harness/src/mcp/playwright.ts +34 -0
- package/.allhands/harness/src/mcp/xcodebuild.ts +29 -0
- package/.allhands/harness/src/schemas/docs.schema.json +44 -0
- package/.allhands/harness/src/schemas/settings.schema.json +214 -0
- package/.allhands/harness/src/tui/actions.ts +227 -0
- package/.allhands/harness/src/tui/file-viewer-modal.ts +270 -0
- package/.allhands/harness/src/tui/index.ts +1574 -0
- package/.allhands/harness/src/tui/modal.ts +232 -0
- package/.allhands/harness/src/tui/prompts-pane.ts +186 -0
- package/.allhands/harness/src/tui/status-pane.ts +434 -0
- package/.allhands/harness/tsconfig.json +22 -0
- package/.allhands/harness/vitest.config.ts +13 -0
- package/.allhands/pillars.md +33 -0
- package/.allhands/principles.md +88 -0
- package/.allhands/schemas/alignment.yaml +51 -0
- package/.allhands/schemas/documentation.yaml +10 -0
- package/.allhands/schemas/prompt.yaml +92 -0
- package/.allhands/schemas/skill.yaml +34 -0
- package/.allhands/schemas/solution.yaml +131 -0
- package/.allhands/schemas/spec.yaml +67 -0
- package/.allhands/schemas/validation-suite.yaml +49 -0
- package/.allhands/schemas/workflow.yaml +51 -0
- package/.allhands/settings.json +57 -0
- package/.allhands/skills/claude-code-patterns/SKILL.md +60 -0
- package/.allhands/skills/claude-code-patterns/docs/context-hygiene.md +19 -0
- package/.allhands/skills/harness-maintenance/SKILL.md +449 -0
- package/.allhands/skills/harness-maintenance/references/core-architecture.md +187 -0
- package/.allhands/skills/harness-maintenance/references/harness-skills.md +87 -0
- package/.allhands/skills/harness-maintenance/references/knowledge-compounding.md +78 -0
- package/.allhands/skills/harness-maintenance/references/tools-commands-mcp-hooks.md +115 -0
- package/.allhands/skills/harness-maintenance/references/validation-tooling.md +77 -0
- package/.allhands/skills/harness-maintenance/references/writing-flows.md +84 -0
- package/.allhands/validation/browser-automation.md +109 -0
- package/.allhands/validation/xcode-automation.md +195 -0
- package/.allhands/workflows/documentation.md +86 -0
- package/.allhands/workflows/investigation.md +81 -0
- package/.allhands/workflows/milestone.md +91 -0
- package/.allhands/workflows/optimization.md +85 -0
- package/.allhands/workflows/refactor.md +99 -0
- package/.allhands/workflows/triage.md +81 -0
- package/.claude/README.md +1 -0
- package/.claude/agents/explorer.md +10 -0
- package/.claude/agents/researcher.md +11 -0
- package/.claude/agents/task-runner.md +8 -0
- package/.claude/settings.json +231 -0
- package/.env.ai.example +7 -0
- package/.github/workflows/npm-publish.yml +69 -0
- package/.internal.json +45 -0
- package/.tldr/config.json +11 -0
- package/.tldrignore +90 -0
- package/CLAUDE.md +6 -0
- package/README.md +98 -0
- package/bin/sync-cli.js +7552 -0
- package/concerns.md +7 -0
- package/docs/README.md +41 -0
- package/docs/agents/README.md +24 -0
- package/docs/agents/agent-configuration-system.md +86 -0
- package/docs/agents/execution-agents.md +50 -0
- package/docs/agents/knowledge-agents.md +61 -0
- package/docs/agents/orchestration-agent.md +57 -0
- package/docs/agents/planning-agents.md +84 -0
- package/docs/agents/quality-review-agents.md +67 -0
- package/docs/agents/workflow-agent-orchestration.md +69 -0
- package/docs/flows/README.md +44 -0
- package/docs/flows/compounding.md +126 -0
- package/docs/flows/coordination.md +72 -0
- package/docs/flows/core-harness-integration.md +63 -0
- package/docs/flows/documentation-orchestration.md +98 -0
- package/docs/flows/e2e-test-plan-building.md +83 -0
- package/docs/flows/emergent-refinement.md +104 -0
- package/docs/flows/flow-authoring-and-mcp-tools.md +89 -0
- package/docs/flows/judge-reviewing.md +112 -0
- package/docs/flows/plan-deepening-and-research.md +107 -0
- package/docs/flows/plan-review-jury.md +114 -0
- package/docs/flows/pr-reviewing.md +54 -0
- package/docs/flows/prompt-task-execution.md +119 -0
- package/docs/flows/spec-planning.md +162 -0
- package/docs/flows/type-specific-scoping-flows.md +49 -0
- package/docs/flows/validation-and-skills-integration.md +145 -0
- package/docs/flows/wip/wip-flows.md +102 -0
- package/docs/harness/README.md +23 -0
- package/docs/harness/agent-profiles.md +84 -0
- package/docs/harness/cli/README.md +24 -0
- package/docs/harness/cli/cli-entry-and-command-discovery.md +91 -0
- package/docs/harness/cli/docs-command.md +87 -0
- package/docs/harness/cli/knowledge-command.md +91 -0
- package/docs/harness/cli/minor-cli-commands.md +65 -0
- package/docs/harness/cli/oracle-command.md +113 -0
- package/docs/harness/cli/planning-command.md +95 -0
- package/docs/harness/cli/schema-and-validation-commands.md +154 -0
- package/docs/harness/cli/search-commands.md +97 -0
- package/docs/harness/cli/spawn-command.md +136 -0
- package/docs/harness/cli/specs-command.md +102 -0
- package/docs/harness/cli/tools-command.md +122 -0
- package/docs/harness/cli/trace-command.md +122 -0
- package/docs/harness/cli-daemon.md +92 -0
- package/docs/harness/event-loop.md +184 -0
- package/docs/harness/hooks/README.md +15 -0
- package/docs/harness/hooks/context-hooks.md +96 -0
- package/docs/harness/hooks/lifecycle-and-observability-hooks.md +135 -0
- package/docs/harness/hooks/validation-hooks.md +97 -0
- package/docs/harness/test-harness.md +149 -0
- package/docs/harness/tui.md +176 -0
- package/docs/memories.md +20 -0
- package/docs/solutions/agentic-issues/premature-agent-deletion-tui-action-dependency-20260130.md +49 -0
- package/docs/solutions/agentic-issues/ref-anchor-scope-mismatch-skill-references-20260131.md +55 -0
- package/docs/solutions/agentic-issues/tautological-tests-routing-20260131.md +52 -0
- package/docs/solutions/integration_issue/blocktool-output-format-mismatch-hook-runner-20260130.md +52 -0
- package/docs/solutions/integration_issue/dual-validation-path-divergence-schema-20260130.md +66 -0
- package/docs/solutions/security-issues/unsanitized-domain-path-join-20260131.md +52 -0
- package/docs/solutions/test-failures/event-loop-mock-ordering-checkAgentWindows-20260130.md +63 -0
- package/docs/sync-cli/README.md +19 -0
- package/docs/sync-cli/cli-entrypoint-and-commands.md +39 -0
- package/docs/sync-cli/commands/README.md +11 -0
- package/docs/sync-cli/commands/pull-manifest-command.md +36 -0
- package/docs/sync-cli/commands/push-command.md +84 -0
- package/docs/sync-cli/commands/sync-command.md +71 -0
- package/docs/sync-cli/systems/README.md +14 -0
- package/docs/sync-cli/systems/git-and-github-integration.md +49 -0
- package/docs/sync-cli/systems/interactive-ui.md +43 -0
- package/docs/sync-cli/systems/manifest-and-distribution.md +51 -0
- package/docs/sync-cli/systems/path-resolution.md +42 -0
- package/package.json +46 -0
- package/scripts/install-shim.sh +40 -0
- package/scripts/pre-pack.sh +25 -0
- package/specs/harness-maintenance-skill.spec.md +138 -0
- package/specs/roadmap/git-spec-lifecycle-management.spec.md +113 -0
- package/specs/sync-init-flag.spec.md +117 -0
- package/specs/unified-workflow-orchestration.spec.md +250 -0
- package/specs/validation-tooling-practice.spec.md +98 -0
- package/specs/workflow-domain-configuration.spec.md +265 -0
- package/src/commands/pull-manifest.ts +31 -0
- package/src/commands/push.ts +344 -0
- package/src/commands/sync.ts +289 -0
- package/src/lib/constants.ts +10 -0
- package/src/lib/dotfiles.ts +36 -0
- package/src/lib/fs-utils.ts +18 -0
- package/src/lib/gh.ts +40 -0
- package/src/lib/git.ts +63 -0
- package/src/lib/gitignore.ts +167 -0
- package/src/lib/manifest.ts +121 -0
- package/src/lib/marker-sync.ts +39 -0
- package/src/lib/paths.ts +38 -0
- package/src/lib/target-lines.ts +66 -0
- package/src/lib/ui.ts +78 -0
- package/src/sync-cli.ts +120 -0
- package/target-lines.json +23 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Runtime - Lazy-loaded MCP server integration via mcptools CLI.
|
|
3
|
+
*
|
|
4
|
+
* This module provides:
|
|
5
|
+
* - Type definitions for MCP server configs
|
|
6
|
+
* - Env var interpolation (${VAR_NAME} -> process.env.VAR_NAME)
|
|
7
|
+
* - mcptools CLI wrapper for tool discovery and execution
|
|
8
|
+
* - SWR (stale-while-revalidate) caching for tool schemas
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { execSync, spawn } from 'child_process';
|
|
12
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
13
|
+
import { dirname, join } from 'path';
|
|
14
|
+
import { fileURLToPath } from 'url';
|
|
15
|
+
|
|
16
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
17
|
+
// Path: harness/src/lib/ -> harness/src/ -> harness/
|
|
18
|
+
const HARNESS_ROOT = join(__dirname, '..', '..');
|
|
19
|
+
const CACHE_DIR = join(HARNESS_ROOT, '.cache', 'mcp');
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* MCP server configuration - one per server wrapper file.
|
|
23
|
+
*/
|
|
24
|
+
export interface McpServerConfig {
|
|
25
|
+
/** Server identifier (used in CLI: ah tools <name>:tool) */
|
|
26
|
+
name: string;
|
|
27
|
+
|
|
28
|
+
/** Human-readable description of what this server provides */
|
|
29
|
+
description: string;
|
|
30
|
+
|
|
31
|
+
/** Transport type - stdio (command) or http/sse (url) */
|
|
32
|
+
type?: 'stdio' | 'http' | 'sse';
|
|
33
|
+
|
|
34
|
+
/** Command to execute (stdio transport) */
|
|
35
|
+
command?: string;
|
|
36
|
+
|
|
37
|
+
/** Arguments for command (stdio transport) */
|
|
38
|
+
args?: string[];
|
|
39
|
+
|
|
40
|
+
/** Environment variables - values can use ${VAR_NAME} for interpolation */
|
|
41
|
+
env?: Record<string, string>;
|
|
42
|
+
|
|
43
|
+
/** URL endpoint (http/sse transport) */
|
|
44
|
+
url?: string;
|
|
45
|
+
|
|
46
|
+
/** HTTP headers (http/sse transport) */
|
|
47
|
+
headers?: Record<string, string>;
|
|
48
|
+
|
|
49
|
+
/** Tools to hide from discovery (default: show all) */
|
|
50
|
+
hiddenTools?: string[];
|
|
51
|
+
|
|
52
|
+
/** Extra hints for specific tools (shown in --help) */
|
|
53
|
+
toolHints?: Record<string, string>;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Whether this server maintains state between tool calls.
|
|
57
|
+
*
|
|
58
|
+
* Stateful servers (e.g., Playwright, XcodeBuild) keep a persistent session
|
|
59
|
+
* that survives between CLI invocations. The session is automatically started
|
|
60
|
+
* on first tool call and cleaned up after inactivity timeout.
|
|
61
|
+
*
|
|
62
|
+
* Use --restart flag if the server gets into a bad state.
|
|
63
|
+
*
|
|
64
|
+
* Stateless servers (e.g., fetch, filesystem) create a fresh connection
|
|
65
|
+
* for each tool call.
|
|
66
|
+
*/
|
|
67
|
+
stateful?: boolean;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Inactivity timeout for stateful sessions in milliseconds.
|
|
71
|
+
* After this period of no tool calls, the session is automatically closed.
|
|
72
|
+
* Default: 120000 (2 minutes). Only applies when stateful: true.
|
|
73
|
+
*/
|
|
74
|
+
stateful_session_timeout?: number;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Default timeout for stateful MCP sessions (2 minutes).
|
|
79
|
+
*/
|
|
80
|
+
export const DAEMON_DEFAULT_MCP_TIMEOUT = 120000;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Tool schema from MCP server discovery.
|
|
84
|
+
*/
|
|
85
|
+
export interface McpToolSchema {
|
|
86
|
+
name: string;
|
|
87
|
+
description?: string;
|
|
88
|
+
inputSchema?: {
|
|
89
|
+
type: string;
|
|
90
|
+
properties?: Record<string, {
|
|
91
|
+
type: string;
|
|
92
|
+
description?: string;
|
|
93
|
+
items?: { type: string };
|
|
94
|
+
}>;
|
|
95
|
+
required?: string[];
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Cached tool discovery result.
|
|
101
|
+
*/
|
|
102
|
+
interface ToolCache {
|
|
103
|
+
timestamp: number;
|
|
104
|
+
tools: McpToolSchema[];
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Check if mcptools CLI is available.
|
|
109
|
+
*/
|
|
110
|
+
export function isMcpToolsInstalled(): boolean {
|
|
111
|
+
try {
|
|
112
|
+
execSync('mcp version', { stdio: 'ignore' });
|
|
113
|
+
return true;
|
|
114
|
+
} catch {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Interpolate environment variables in a string.
|
|
121
|
+
* Replaces ${VAR_NAME} with process.env.VAR_NAME.
|
|
122
|
+
*/
|
|
123
|
+
export function interpolateEnv(value: string): string {
|
|
124
|
+
return value.replace(/\$\{([^}]+)\}/g, (_, varName) => {
|
|
125
|
+
const envValue = process.env[varName];
|
|
126
|
+
if (envValue === undefined) {
|
|
127
|
+
throw new Error(`Environment variable ${varName} is not set`);
|
|
128
|
+
}
|
|
129
|
+
return envValue;
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Interpolate all env vars in a config's env object.
|
|
135
|
+
*/
|
|
136
|
+
export function resolveEnvVars(env: Record<string, string> | undefined): Record<string, string> {
|
|
137
|
+
if (!env) return {};
|
|
138
|
+
|
|
139
|
+
const resolved: Record<string, string> = {};
|
|
140
|
+
for (const [key, value] of Object.entries(env)) {
|
|
141
|
+
resolved[key] = interpolateEnv(value);
|
|
142
|
+
}
|
|
143
|
+
return resolved;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Build the mcptools server command from config.
|
|
148
|
+
*/
|
|
149
|
+
export function buildServerCommand(config: McpServerConfig): string[] {
|
|
150
|
+
if (config.type === 'http' || config.type === 'sse') {
|
|
151
|
+
if (!config.url) {
|
|
152
|
+
throw new Error(`Server ${config.name} requires 'url' for ${config.type} transport`);
|
|
153
|
+
}
|
|
154
|
+
return [config.url];
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Default to stdio
|
|
158
|
+
if (!config.command) {
|
|
159
|
+
throw new Error(`Server ${config.name} requires 'command' for stdio transport`);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return [config.command, ...(config.args ?? [])];
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Get cache file path for a server.
|
|
167
|
+
*/
|
|
168
|
+
function getCachePath(serverName: string): string {
|
|
169
|
+
return join(CACHE_DIR, `${serverName}.json`);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Load cached tools for a server.
|
|
174
|
+
*/
|
|
175
|
+
function loadCache(serverName: string): ToolCache | null {
|
|
176
|
+
const cachePath = getCachePath(serverName);
|
|
177
|
+
if (!existsSync(cachePath)) return null;
|
|
178
|
+
|
|
179
|
+
try {
|
|
180
|
+
const data = readFileSync(cachePath, 'utf-8');
|
|
181
|
+
return JSON.parse(data) as ToolCache;
|
|
182
|
+
} catch {
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Save tools to cache.
|
|
189
|
+
*/
|
|
190
|
+
function saveCache(serverName: string, tools: McpToolSchema[]): void {
|
|
191
|
+
if (!existsSync(CACHE_DIR)) {
|
|
192
|
+
mkdirSync(CACHE_DIR, { recursive: true });
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const cache: ToolCache = {
|
|
196
|
+
timestamp: Date.now(),
|
|
197
|
+
tools,
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
writeFileSync(getCachePath(serverName), JSON.stringify(cache, null, 2));
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Discover tools from an MCP server via mcptools CLI.
|
|
205
|
+
*/
|
|
206
|
+
export async function discoverTools(config: McpServerConfig): Promise<McpToolSchema[]> {
|
|
207
|
+
const serverCmd = buildServerCommand(config);
|
|
208
|
+
const env = resolveEnvVars(config.env);
|
|
209
|
+
|
|
210
|
+
return new Promise((resolve, reject) => {
|
|
211
|
+
const args = ['tools', '--format', 'json', ...serverCmd];
|
|
212
|
+
|
|
213
|
+
const proc = spawn('mcp', args, {
|
|
214
|
+
env: { ...process.env, ...env },
|
|
215
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
let stdout = '';
|
|
219
|
+
let stderr = '';
|
|
220
|
+
|
|
221
|
+
proc.stdout.on('data', (data) => {
|
|
222
|
+
stdout += data.toString();
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
proc.stderr.on('data', (data) => {
|
|
226
|
+
stderr += data.toString();
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
proc.on('close', (code) => {
|
|
230
|
+
if (code !== 0) {
|
|
231
|
+
reject(new Error(`mcp tools failed: ${stderr || 'unknown error'}`));
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
try {
|
|
236
|
+
const parsed = JSON.parse(stdout);
|
|
237
|
+
// mcptools returns { tools: [...] } wrapper
|
|
238
|
+
const tools = (parsed.tools ?? parsed) as McpToolSchema[];
|
|
239
|
+
|
|
240
|
+
// Filter out hidden tools
|
|
241
|
+
const filtered = config.hiddenTools?.length
|
|
242
|
+
? tools.filter((t) => !config.hiddenTools!.includes(t.name))
|
|
243
|
+
: tools;
|
|
244
|
+
|
|
245
|
+
resolve(filtered);
|
|
246
|
+
} catch (e) {
|
|
247
|
+
reject(new Error(`Failed to parse tool discovery: ${e}`));
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
proc.on('error', (err) => {
|
|
252
|
+
reject(new Error(`Failed to spawn mcp: ${err.message}`));
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Get tools with SWR caching.
|
|
259
|
+
*
|
|
260
|
+
* Returns cached tools immediately, triggers background refresh.
|
|
261
|
+
* If no cache exists, performs blocking discovery.
|
|
262
|
+
*/
|
|
263
|
+
export async function getToolsWithCache(
|
|
264
|
+
config: McpServerConfig,
|
|
265
|
+
forceRefresh = false
|
|
266
|
+
): Promise<McpToolSchema[]> {
|
|
267
|
+
const cache = loadCache(config.name);
|
|
268
|
+
|
|
269
|
+
if (forceRefresh || !cache) {
|
|
270
|
+
// No cache or force refresh - blocking discovery
|
|
271
|
+
const tools = await discoverTools(config);
|
|
272
|
+
saveCache(config.name, tools);
|
|
273
|
+
return tools;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Return cached immediately, refresh in background (SWR pattern)
|
|
277
|
+
discoverTools(config)
|
|
278
|
+
.then((tools) => saveCache(config.name, tools))
|
|
279
|
+
.catch(() => {
|
|
280
|
+
// Silent fail on background refresh - cache still valid
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
return cache.tools;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Call a tool on an MCP server.
|
|
288
|
+
*/
|
|
289
|
+
export async function callTool(
|
|
290
|
+
config: McpServerConfig,
|
|
291
|
+
toolName: string,
|
|
292
|
+
params: Record<string, unknown>
|
|
293
|
+
): Promise<unknown> {
|
|
294
|
+
const serverCmd = buildServerCommand(config);
|
|
295
|
+
const env = resolveEnvVars(config.env);
|
|
296
|
+
|
|
297
|
+
return new Promise((resolve, reject) => {
|
|
298
|
+
const args = [
|
|
299
|
+
'call',
|
|
300
|
+
toolName,
|
|
301
|
+
'--params',
|
|
302
|
+
JSON.stringify(params),
|
|
303
|
+
'--format',
|
|
304
|
+
'json',
|
|
305
|
+
...serverCmd,
|
|
306
|
+
];
|
|
307
|
+
|
|
308
|
+
const proc = spawn('mcp', args, {
|
|
309
|
+
env: { ...process.env, ...env },
|
|
310
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
let stdout = '';
|
|
314
|
+
let stderr = '';
|
|
315
|
+
|
|
316
|
+
proc.stdout.on('data', (data) => {
|
|
317
|
+
stdout += data.toString();
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
proc.stderr.on('data', (data) => {
|
|
321
|
+
stderr += data.toString();
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
proc.on('close', (code) => {
|
|
325
|
+
if (code !== 0) {
|
|
326
|
+
reject(new Error(`Tool call failed: ${stderr || 'unknown error'}`));
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
try {
|
|
331
|
+
const result = JSON.parse(stdout);
|
|
332
|
+
resolve(result);
|
|
333
|
+
} catch {
|
|
334
|
+
// Not JSON - return raw output
|
|
335
|
+
resolve(stdout.trim());
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
proc.on('error', (err) => {
|
|
340
|
+
reject(new Error(`Failed to spawn mcp: ${err.message}`));
|
|
341
|
+
});
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Format tool schema for human-readable help output.
|
|
347
|
+
*/
|
|
348
|
+
export function formatToolHelp(
|
|
349
|
+
tool: McpToolSchema,
|
|
350
|
+
hint?: string
|
|
351
|
+
): string {
|
|
352
|
+
const lines: string[] = [];
|
|
353
|
+
|
|
354
|
+
// Tool signature
|
|
355
|
+
const params: string[] = [];
|
|
356
|
+
const props = tool.inputSchema?.properties ?? {};
|
|
357
|
+
const required = new Set(tool.inputSchema?.required ?? []);
|
|
358
|
+
|
|
359
|
+
for (const [name, schema] of Object.entries(props)) {
|
|
360
|
+
let typeStr = schema.type;
|
|
361
|
+
if (schema.items?.type) {
|
|
362
|
+
typeStr = `${schema.items.type}[]`;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
if (required.has(name)) {
|
|
366
|
+
params.push(`${name}:${typeStr}`);
|
|
367
|
+
} else {
|
|
368
|
+
params.push(`[${name}:${typeStr}]`);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
lines.push(`${tool.name}(${params.join(', ')})`);
|
|
373
|
+
|
|
374
|
+
// Description
|
|
375
|
+
if (tool.description) {
|
|
376
|
+
lines.push(` ${tool.description}`);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// Parameter details
|
|
380
|
+
if (Object.keys(props).length > 0) {
|
|
381
|
+
lines.push('');
|
|
382
|
+
lines.push(' Parameters:');
|
|
383
|
+
for (const [name, schema] of Object.entries(props)) {
|
|
384
|
+
const reqStr = required.has(name) ? '(required)' : '(optional)';
|
|
385
|
+
const desc = schema.description || '';
|
|
386
|
+
lines.push(` ${name} ${reqStr} ${desc}`);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// Custom hint
|
|
391
|
+
if (hint) {
|
|
392
|
+
lines.push('');
|
|
393
|
+
lines.push(` Hint: ${hint}`);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
return lines.join('\n');
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Format all tools from a server for help output.
|
|
401
|
+
*/
|
|
402
|
+
export function formatServerHelp(
|
|
403
|
+
config: McpServerConfig,
|
|
404
|
+
tools: McpToolSchema[]
|
|
405
|
+
): string {
|
|
406
|
+
const lines: string[] = [];
|
|
407
|
+
|
|
408
|
+
lines.push(`${config.name} - ${config.description}`);
|
|
409
|
+
lines.push('');
|
|
410
|
+
lines.push(`Tools (${tools.length}):`);
|
|
411
|
+
|
|
412
|
+
for (const tool of tools) {
|
|
413
|
+
lines.push('');
|
|
414
|
+
lines.push(formatToolHelp(tool, config.toolHints?.[tool.name]));
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
return lines.join('\n');
|
|
418
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* System notification utilities using jamf/Notifier (macOS).
|
|
3
|
+
*
|
|
4
|
+
* Notification structure:
|
|
5
|
+
* - title: Event type (what happened)
|
|
6
|
+
* - subtitle: Branch/feature context (auto-detected)
|
|
7
|
+
* - message: Specific details for the user
|
|
8
|
+
*
|
|
9
|
+
* Requires: https://github.com/jamf/Notifier installed at:
|
|
10
|
+
* /Applications/Utilities/Notifier.app
|
|
11
|
+
* or available in PATH as 'notifier'
|
|
12
|
+
*
|
|
13
|
+
* This is designed to be used from Claude Code hooks via:
|
|
14
|
+
* ah notify send "Title" "Message"
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { spawnSync } from "child_process";
|
|
18
|
+
import { existsSync } from "fs";
|
|
19
|
+
import { getBranch, getRepoName } from "./git.js";
|
|
20
|
+
|
|
21
|
+
export interface NotifyOptions {
|
|
22
|
+
title: string; // Event type (required)
|
|
23
|
+
message: string; // Specific details (required)
|
|
24
|
+
sound?: string; // macOS sound name
|
|
25
|
+
type?: "banner" | "alert"; // banner auto-dismisses, alert persists
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const NOTIFIER_DEFAULT_PATH = "/Applications/Utilities/Notifier.app/Contents/MacOS/Notifier";
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Find the notifier binary path.
|
|
32
|
+
*/
|
|
33
|
+
function getNotifierPath(): string | null {
|
|
34
|
+
// Check default install location
|
|
35
|
+
if (existsSync(NOTIFIER_DEFAULT_PATH)) {
|
|
36
|
+
return NOTIFIER_DEFAULT_PATH;
|
|
37
|
+
}
|
|
38
|
+
// Check if 'notifier' is in PATH
|
|
39
|
+
const result = spawnSync("which", ["notifier"], { encoding: "utf-8" });
|
|
40
|
+
if (result.status === 0 && result.stdout.trim()) {
|
|
41
|
+
return "notifier";
|
|
42
|
+
}
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Send a system notification via jamf/Notifier.
|
|
48
|
+
*
|
|
49
|
+
* Layout:
|
|
50
|
+
* Title: event type (e.g., "Agent Stopped", "Plan Gate")
|
|
51
|
+
* Subtitle: repo + branch name (auto-detected)
|
|
52
|
+
* Message: specific details
|
|
53
|
+
*/
|
|
54
|
+
export function sendNotification(options: NotifyOptions): boolean {
|
|
55
|
+
const notifierPath = getNotifierPath();
|
|
56
|
+
if (!notifierPath) {
|
|
57
|
+
// Notifier not installed - silently skip
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const repo = getRepoName();
|
|
62
|
+
const branch = getBranch() || "unknown";
|
|
63
|
+
const subtitle = repo ? `${repo} ${branch}` : branch;
|
|
64
|
+
const notifType = options.type || "banner";
|
|
65
|
+
|
|
66
|
+
const args: string[] = [
|
|
67
|
+
"--type", notifType,
|
|
68
|
+
"--title", options.title,
|
|
69
|
+
"--subtitle", subtitle,
|
|
70
|
+
"--message", options.message,
|
|
71
|
+
];
|
|
72
|
+
|
|
73
|
+
if (options.sound) {
|
|
74
|
+
args.push("--sound", options.sound);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
try {
|
|
78
|
+
const result = spawnSync(notifierPath, args, {
|
|
79
|
+
stdio: "ignore",
|
|
80
|
+
timeout: 5000,
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
return result.status === 0;
|
|
84
|
+
} catch {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Send a gate notification. Uses alert type (persists until dismissed).
|
|
91
|
+
*/
|
|
92
|
+
export function sendGateNotification(
|
|
93
|
+
gateType: string,
|
|
94
|
+
message: string
|
|
95
|
+
): boolean {
|
|
96
|
+
return sendNotification({
|
|
97
|
+
title: `${gateType} Gate`,
|
|
98
|
+
message,
|
|
99
|
+
type: "alert",
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Send a hook notification. Uses banner type (auto-dismisses).
|
|
105
|
+
*/
|
|
106
|
+
export function sendHookNotification(
|
|
107
|
+
hookType: string,
|
|
108
|
+
message: string
|
|
109
|
+
): boolean {
|
|
110
|
+
return sendNotification({
|
|
111
|
+
title: hookType,
|
|
112
|
+
message,
|
|
113
|
+
type: "banner",
|
|
114
|
+
});
|
|
115
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenCode SDK integration for All Hands.
|
|
3
|
+
*
|
|
4
|
+
* This module provides:
|
|
5
|
+
* - Agent profiles: YAML-defined configurations for TUI-spawned agents
|
|
6
|
+
* - Agent runner: OpenCode SDK wrapper for sub-agent execution
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// Re-export profile management
|
|
10
|
+
export * from './profiles.js';
|
|
11
|
+
|
|
12
|
+
// MCP server configuration (matches opencode SDK McpLocalConfig)
|
|
13
|
+
export interface McpServerConfig {
|
|
14
|
+
type: "local";
|
|
15
|
+
command: string[]; // Command and args as array: ["uvx", "--from", "pkg", "server"]
|
|
16
|
+
environment?: Record<string, string>;
|
|
17
|
+
enabled?: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Agent configuration
|
|
21
|
+
export interface AgentConfig {
|
|
22
|
+
name: string;
|
|
23
|
+
systemPrompt: string;
|
|
24
|
+
model?: string;
|
|
25
|
+
timeoutMs?: number;
|
|
26
|
+
steps?: number; // Hard limit on agent iterations
|
|
27
|
+
mcp?: Record<string, McpServerConfig>; // MCP servers to enable
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Agent execution result
|
|
31
|
+
export interface AgentResult<T = unknown> {
|
|
32
|
+
success: boolean;
|
|
33
|
+
data?: T;
|
|
34
|
+
error?: string;
|
|
35
|
+
metadata?: {
|
|
36
|
+
model: string;
|
|
37
|
+
tokens_used?: number;
|
|
38
|
+
duration_ms: number;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Search result type (mirrors KnowledgeService.SearchResult)
|
|
43
|
+
export interface SearchResult {
|
|
44
|
+
resource_path: string;
|
|
45
|
+
similarity: number;
|
|
46
|
+
token_count: number;
|
|
47
|
+
description: string;
|
|
48
|
+
relevant_files: string[];
|
|
49
|
+
full_resource_context?: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Knowledge aggregator input
|
|
53
|
+
export interface AggregatorInput {
|
|
54
|
+
query: string;
|
|
55
|
+
full_results: SearchResult[];
|
|
56
|
+
minimized_results: SearchResult[];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Knowledge aggregator output
|
|
60
|
+
export interface AggregatorOutput {
|
|
61
|
+
insight: string;
|
|
62
|
+
lsp_entry_points: Array<{
|
|
63
|
+
file: string;
|
|
64
|
+
symbol: string | null;
|
|
65
|
+
why: string;
|
|
66
|
+
}>;
|
|
67
|
+
design_notes?: string[];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export { AgentRunner } from "./runner.js";
|