lorenz 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/LICENSE +201 -0
- package/NOTICE +13 -0
- package/README.md +774 -0
- package/RELEASE-MANIFEST.json +211 -0
- package/apps/cli/bin/lorenz.js +25 -0
- package/apps/cli/dist/bin/cli.d.ts +3 -0
- package/apps/cli/dist/bin/cli.d.ts.map +1 -0
- package/apps/cli/dist/bin/cli.js +4 -0
- package/apps/cli/dist/bin/cli.js.map +1 -0
- package/apps/cli/dist/daemon.d.ts +76 -0
- package/apps/cli/dist/daemon.d.ts.map +1 -0
- package/apps/cli/dist/daemon.js +189 -0
- package/apps/cli/dist/daemon.js.map +1 -0
- package/apps/cli/dist/doctor.d.ts +40 -0
- package/apps/cli/dist/doctor.d.ts.map +1 -0
- package/apps/cli/dist/doctor.js +590 -0
- package/apps/cli/dist/doctor.js.map +1 -0
- package/apps/cli/dist/index.d.ts +32 -0
- package/apps/cli/dist/index.d.ts.map +1 -0
- package/apps/cli/dist/index.js +26 -0
- package/apps/cli/dist/index.js.map +1 -0
- package/apps/cli/dist/main.d.ts +40 -0
- package/apps/cli/dist/main.d.ts.map +1 -0
- package/apps/cli/dist/main.js +259 -0
- package/apps/cli/dist/main.js.map +1 -0
- package/apps/cli/dist/runs.d.ts +31 -0
- package/apps/cli/dist/runs.d.ts.map +1 -0
- package/apps/cli/dist/runs.js +281 -0
- package/apps/cli/dist/runs.js.map +1 -0
- package/apps/cli/dist/workerDriverLoader.d.ts +64 -0
- package/apps/cli/dist/workerDriverLoader.d.ts.map +1 -0
- package/apps/cli/dist/workerDriverLoader.js +211 -0
- package/apps/cli/dist/workerDriverLoader.js.map +1 -0
- package/apps/cli/package.json +57 -0
- package/apps/symphony-dashboard/dist/assets/index-B3owF3jd.css +1 -0
- package/apps/symphony-dashboard/dist/assets/index-DQ6XlL0d.js +227 -0
- package/apps/symphony-dashboard/dist/index.html +18 -0
- package/bin/lorenz +16 -0
- package/extensions/docker-worker/dist/index.d.ts +92 -0
- package/extensions/docker-worker/dist/index.d.ts.map +1 -0
- package/extensions/docker-worker/dist/index.js +283 -0
- package/extensions/docker-worker/dist/index.js.map +1 -0
- package/extensions/docker-worker/package.json +14 -0
- package/extensions/jira-tracker/dist/client.d.ts +50 -0
- package/extensions/jira-tracker/dist/client.d.ts.map +1 -0
- package/extensions/jira-tracker/dist/client.js +619 -0
- package/extensions/jira-tracker/dist/client.js.map +1 -0
- package/extensions/jira-tracker/dist/index.d.ts +5 -0
- package/extensions/jira-tracker/dist/index.d.ts.map +1 -0
- package/extensions/jira-tracker/dist/index.js +5 -0
- package/extensions/jira-tracker/dist/index.js.map +1 -0
- package/extensions/jira-tracker/dist/options.d.ts +38 -0
- package/extensions/jira-tracker/dist/options.d.ts.map +1 -0
- package/extensions/jira-tracker/dist/options.js +61 -0
- package/extensions/jira-tracker/dist/options.js.map +1 -0
- package/extensions/jira-tracker/dist/provider.d.ts +6 -0
- package/extensions/jira-tracker/dist/provider.d.ts.map +1 -0
- package/extensions/jira-tracker/dist/provider.js +178 -0
- package/extensions/jira-tracker/dist/provider.js.map +1 -0
- package/extensions/jira-tracker/dist/register.d.ts +10 -0
- package/extensions/jira-tracker/dist/register.d.ts.map +1 -0
- package/extensions/jira-tracker/dist/register.js +15 -0
- package/extensions/jira-tracker/dist/register.js.map +1 -0
- package/extensions/jira-tracker/package.json +16 -0
- package/extensions/linear-tracker/dist/client.d.ts +82 -0
- package/extensions/linear-tracker/dist/client.d.ts.map +1 -0
- package/extensions/linear-tracker/dist/client.js +622 -0
- package/extensions/linear-tracker/dist/client.js.map +1 -0
- package/extensions/linear-tracker/dist/index.d.ts +8 -0
- package/extensions/linear-tracker/dist/index.d.ts.map +1 -0
- package/extensions/linear-tracker/dist/index.js +7 -0
- package/extensions/linear-tracker/dist/index.js.map +1 -0
- package/extensions/linear-tracker/dist/options.d.ts +32 -0
- package/extensions/linear-tracker/dist/options.d.ts.map +1 -0
- package/extensions/linear-tracker/dist/options.js +59 -0
- package/extensions/linear-tracker/dist/options.js.map +1 -0
- package/extensions/linear-tracker/dist/provider.d.ts +4 -0
- package/extensions/linear-tracker/dist/provider.d.ts.map +1 -0
- package/extensions/linear-tracker/dist/provider.js +58 -0
- package/extensions/linear-tracker/dist/provider.js.map +1 -0
- package/extensions/linear-tracker/dist/register.d.ts +11 -0
- package/extensions/linear-tracker/dist/register.d.ts.map +1 -0
- package/extensions/linear-tracker/dist/register.js +19 -0
- package/extensions/linear-tracker/dist/register.js.map +1 -0
- package/extensions/linear-tracker/dist/toolOps.d.ts +8 -0
- package/extensions/linear-tracker/dist/toolOps.d.ts.map +1 -0
- package/extensions/linear-tracker/dist/toolOps.js +160 -0
- package/extensions/linear-tracker/dist/toolOps.js.map +1 -0
- package/extensions/linear-tracker/dist/tools.d.ts +7 -0
- package/extensions/linear-tracker/dist/tools.d.ts.map +1 -0
- package/extensions/linear-tracker/dist/tools.js +210 -0
- package/extensions/linear-tracker/dist/tools.js.map +1 -0
- package/extensions/linear-tracker/package.json +18 -0
- package/extensions/local-tracker/dist/boardStore.d.ts +116 -0
- package/extensions/local-tracker/dist/boardStore.d.ts.map +1 -0
- package/extensions/local-tracker/dist/boardStore.js +475 -0
- package/extensions/local-tracker/dist/boardStore.js.map +1 -0
- package/extensions/local-tracker/dist/client.d.ts +14 -0
- package/extensions/local-tracker/dist/client.d.ts.map +1 -0
- package/extensions/local-tracker/dist/client.js +27 -0
- package/extensions/local-tracker/dist/client.js.map +1 -0
- package/extensions/local-tracker/dist/index.d.ts +7 -0
- package/extensions/local-tracker/dist/index.d.ts.map +1 -0
- package/extensions/local-tracker/dist/index.js +7 -0
- package/extensions/local-tracker/dist/index.js.map +1 -0
- package/extensions/local-tracker/dist/options.d.ts +31 -0
- package/extensions/local-tracker/dist/options.d.ts.map +1 -0
- package/extensions/local-tracker/dist/options.js +69 -0
- package/extensions/local-tracker/dist/options.js.map +1 -0
- package/extensions/local-tracker/dist/provider.d.ts +9 -0
- package/extensions/local-tracker/dist/provider.d.ts.map +1 -0
- package/extensions/local-tracker/dist/provider.js +35 -0
- package/extensions/local-tracker/dist/provider.js.map +1 -0
- package/extensions/local-tracker/dist/register.d.ts +11 -0
- package/extensions/local-tracker/dist/register.d.ts.map +1 -0
- package/extensions/local-tracker/dist/register.js +19 -0
- package/extensions/local-tracker/dist/register.js.map +1 -0
- package/extensions/local-tracker/dist/resolveBoardDir.d.ts +24 -0
- package/extensions/local-tracker/dist/resolveBoardDir.d.ts.map +1 -0
- package/extensions/local-tracker/dist/resolveBoardDir.js +39 -0
- package/extensions/local-tracker/dist/resolveBoardDir.js.map +1 -0
- package/extensions/local-tracker/dist/toolOps.d.ts +9 -0
- package/extensions/local-tracker/dist/toolOps.d.ts.map +1 -0
- package/extensions/local-tracker/dist/toolOps.js +86 -0
- package/extensions/local-tracker/dist/toolOps.js.map +1 -0
- package/extensions/local-tracker/dist/tools.d.ts +7 -0
- package/extensions/local-tracker/dist/tools.d.ts.map +1 -0
- package/extensions/local-tracker/dist/tools.js +170 -0
- package/extensions/local-tracker/dist/tools.js.map +1 -0
- package/extensions/local-tracker/package.json +18 -0
- package/extensions/memory-tracker/dist/index.d.ts +24 -0
- package/extensions/memory-tracker/dist/index.d.ts.map +1 -0
- package/extensions/memory-tracker/dist/index.js +110 -0
- package/extensions/memory-tracker/dist/index.js.map +1 -0
- package/extensions/memory-tracker/package.json +16 -0
- package/extensions/slack-tracker/dist/client.d.ts +88 -0
- package/extensions/slack-tracker/dist/client.d.ts.map +1 -0
- package/extensions/slack-tracker/dist/client.js +246 -0
- package/extensions/slack-tracker/dist/client.js.map +1 -0
- package/extensions/slack-tracker/dist/inMemoryTransport.d.ts +42 -0
- package/extensions/slack-tracker/dist/inMemoryTransport.d.ts.map +1 -0
- package/extensions/slack-tracker/dist/inMemoryTransport.js +104 -0
- package/extensions/slack-tracker/dist/inMemoryTransport.js.map +1 -0
- package/extensions/slack-tracker/dist/index.d.ts +15 -0
- package/extensions/slack-tracker/dist/index.d.ts.map +1 -0
- package/extensions/slack-tracker/dist/index.js +11 -0
- package/extensions/slack-tracker/dist/index.js.map +1 -0
- package/extensions/slack-tracker/dist/mapping.d.ts +27 -0
- package/extensions/slack-tracker/dist/mapping.d.ts.map +1 -0
- package/extensions/slack-tracker/dist/mapping.js +109 -0
- package/extensions/slack-tracker/dist/mapping.js.map +1 -0
- package/extensions/slack-tracker/dist/operations.d.ts +41 -0
- package/extensions/slack-tracker/dist/operations.d.ts.map +1 -0
- package/extensions/slack-tracker/dist/operations.js +97 -0
- package/extensions/slack-tracker/dist/operations.js.map +1 -0
- package/extensions/slack-tracker/dist/options.d.ts +30 -0
- package/extensions/slack-tracker/dist/options.d.ts.map +1 -0
- package/extensions/slack-tracker/dist/options.js +49 -0
- package/extensions/slack-tracker/dist/options.js.map +1 -0
- package/extensions/slack-tracker/dist/provider.d.ts +9 -0
- package/extensions/slack-tracker/dist/provider.d.ts.map +1 -0
- package/extensions/slack-tracker/dist/provider.js +74 -0
- package/extensions/slack-tracker/dist/provider.js.map +1 -0
- package/extensions/slack-tracker/dist/register.d.ts +11 -0
- package/extensions/slack-tracker/dist/register.d.ts.map +1 -0
- package/extensions/slack-tracker/dist/register.js +19 -0
- package/extensions/slack-tracker/dist/register.js.map +1 -0
- package/extensions/slack-tracker/dist/threadState.d.ts +52 -0
- package/extensions/slack-tracker/dist/threadState.d.ts.map +1 -0
- package/extensions/slack-tracker/dist/threadState.js +192 -0
- package/extensions/slack-tracker/dist/threadState.js.map +1 -0
- package/extensions/slack-tracker/dist/toolOps.d.ts +13 -0
- package/extensions/slack-tracker/dist/toolOps.d.ts.map +1 -0
- package/extensions/slack-tracker/dist/toolOps.js +76 -0
- package/extensions/slack-tracker/dist/toolOps.js.map +1 -0
- package/extensions/slack-tracker/dist/tools.d.ts +8 -0
- package/extensions/slack-tracker/dist/tools.d.ts.map +1 -0
- package/extensions/slack-tracker/dist/tools.js +266 -0
- package/extensions/slack-tracker/dist/tools.js.map +1 -0
- package/extensions/slack-tracker/dist/transport.d.ts +63 -0
- package/extensions/slack-tracker/dist/transport.d.ts.map +1 -0
- package/extensions/slack-tracker/dist/transport.js +2 -0
- package/extensions/slack-tracker/dist/transport.js.map +1 -0
- package/extensions/slack-tracker/dist/webTransport.d.ts +44 -0
- package/extensions/slack-tracker/dist/webTransport.d.ts.map +1 -0
- package/extensions/slack-tracker/dist/webTransport.js +402 -0
- package/extensions/slack-tracker/dist/webTransport.js.map +1 -0
- package/extensions/slack-tracker/package.json +17 -0
- package/package.json +89 -0
- package/packages/acp/dist/childProcess.d.ts +4 -0
- package/packages/acp/dist/childProcess.d.ts.map +1 -0
- package/packages/acp/dist/childProcess.js +33 -0
- package/packages/acp/dist/childProcess.js.map +1 -0
- package/packages/acp/dist/index.d.ts +70 -0
- package/packages/acp/dist/index.d.ts.map +1 -0
- package/packages/acp/dist/index.js +701 -0
- package/packages/acp/dist/index.js.map +1 -0
- package/packages/acp/dist/options.d.ts +24 -0
- package/packages/acp/dist/options.d.ts.map +1 -0
- package/packages/acp/dist/options.js +92 -0
- package/packages/acp/dist/options.js.map +1 -0
- package/packages/acp/dist/toml.d.ts +2 -0
- package/packages/acp/dist/toml.d.ts.map +1 -0
- package/packages/acp/dist/toml.js +51 -0
- package/packages/acp/dist/toml.js.map +1 -0
- package/packages/acp/package.json +24 -0
- package/packages/agent-runner/dist/index.d.ts +58 -0
- package/packages/agent-runner/dist/index.d.ts.map +1 -0
- package/packages/agent-runner/dist/index.js +288 -0
- package/packages/agent-runner/dist/index.js.map +1 -0
- package/packages/agent-runner/package.json +19 -0
- package/packages/agent-sdk/dist/index.d.ts +2 -0
- package/packages/agent-sdk/dist/index.d.ts.map +1 -0
- package/packages/agent-sdk/dist/index.js +2 -0
- package/packages/agent-sdk/dist/index.js.map +1 -0
- package/packages/agent-sdk/dist/provider.d.ts +66 -0
- package/packages/agent-sdk/dist/provider.d.ts.map +1 -0
- package/packages/agent-sdk/dist/provider.js +38 -0
- package/packages/agent-sdk/dist/provider.js.map +1 -0
- package/packages/agent-sdk/package.json +14 -0
- package/packages/cli-kit/dist/index.d.ts +20 -0
- package/packages/cli-kit/dist/index.d.ts.map +1 -0
- package/packages/cli-kit/dist/index.js +72 -0
- package/packages/cli-kit/dist/index.js.map +1 -0
- package/packages/cli-kit/package.json +14 -0
- package/packages/config/dist/aliases.d.ts +10 -0
- package/packages/config/dist/aliases.d.ts.map +1 -0
- package/packages/config/dist/aliases.js +153 -0
- package/packages/config/dist/aliases.js.map +1 -0
- package/packages/config/dist/defaults.d.ts +12 -0
- package/packages/config/dist/defaults.d.ts.map +1 -0
- package/packages/config/dist/defaults.js +78 -0
- package/packages/config/dist/defaults.js.map +1 -0
- package/packages/config/dist/errors.d.ts +3 -0
- package/packages/config/dist/errors.d.ts.map +1 -0
- package/packages/config/dist/errors.js +56 -0
- package/packages/config/dist/errors.js.map +1 -0
- package/packages/config/dist/index.d.ts +5 -0
- package/packages/config/dist/index.d.ts.map +1 -0
- package/packages/config/dist/index.js +4 -0
- package/packages/config/dist/index.js.map +1 -0
- package/packages/config/dist/leaf-utils.d.ts +3 -0
- package/packages/config/dist/leaf-utils.d.ts.map +1 -0
- package/packages/config/dist/leaf-utils.js +9 -0
- package/packages/config/dist/leaf-utils.js.map +1 -0
- package/packages/config/dist/parse.d.ts +11 -0
- package/packages/config/dist/parse.d.ts.map +1 -0
- package/packages/config/dist/parse.js +821 -0
- package/packages/config/dist/parse.js.map +1 -0
- package/packages/config/dist/schemas.d.ts +214 -0
- package/packages/config/dist/schemas.d.ts.map +1 -0
- package/packages/config/dist/schemas.js +248 -0
- package/packages/config/dist/schemas.js.map +1 -0
- package/packages/config/package.json +19 -0
- package/packages/dispatch/dist/index.d.ts +22 -0
- package/packages/dispatch/dist/index.d.ts.map +1 -0
- package/packages/dispatch/dist/index.js +117 -0
- package/packages/dispatch/dist/index.js.map +1 -0
- package/packages/dispatch/package.json +16 -0
- package/packages/dispatch-coordinator/dist/coordinator.d.ts +158 -0
- package/packages/dispatch-coordinator/dist/coordinator.d.ts.map +1 -0
- package/packages/dispatch-coordinator/dist/coordinator.js +529 -0
- package/packages/dispatch-coordinator/dist/coordinator.js.map +1 -0
- package/packages/dispatch-coordinator/dist/gate.d.ts +24 -0
- package/packages/dispatch-coordinator/dist/gate.d.ts.map +1 -0
- package/packages/dispatch-coordinator/dist/gate.js +47 -0
- package/packages/dispatch-coordinator/dist/gate.js.map +1 -0
- package/packages/dispatch-coordinator/dist/index.d.ts +6 -0
- package/packages/dispatch-coordinator/dist/index.d.ts.map +1 -0
- package/packages/dispatch-coordinator/dist/index.js +16 -0
- package/packages/dispatch-coordinator/dist/index.js.map +1 -0
- package/packages/dispatch-coordinator/dist/mcpEndpointManager.d.ts +28 -0
- package/packages/dispatch-coordinator/dist/mcpEndpointManager.d.ts.map +1 -0
- package/packages/dispatch-coordinator/dist/mcpEndpointManager.js +54 -0
- package/packages/dispatch-coordinator/dist/mcpEndpointManager.js.map +1 -0
- package/packages/dispatch-coordinator/dist/nullEndpointManager.d.ts +18 -0
- package/packages/dispatch-coordinator/dist/nullEndpointManager.d.ts.map +1 -0
- package/packages/dispatch-coordinator/dist/nullEndpointManager.js +40 -0
- package/packages/dispatch-coordinator/dist/nullEndpointManager.js.map +1 -0
- package/packages/dispatch-coordinator/dist/types.d.ts +119 -0
- package/packages/dispatch-coordinator/dist/types.d.ts.map +1 -0
- package/packages/dispatch-coordinator/dist/types.js +17 -0
- package/packages/dispatch-coordinator/dist/types.js.map +1 -0
- package/packages/dispatch-coordinator/package.json +16 -0
- package/packages/domain/dist/index.d.ts +775 -0
- package/packages/domain/dist/index.d.ts.map +1 -0
- package/packages/domain/dist/index.js +124 -0
- package/packages/domain/dist/index.js.map +1 -0
- package/packages/domain/package.json +14 -0
- package/packages/humanize/dist/index.d.ts +4 -0
- package/packages/humanize/dist/index.d.ts.map +1 -0
- package/packages/humanize/dist/index.js +347 -0
- package/packages/humanize/dist/index.js.map +1 -0
- package/packages/humanize/package.json +11 -0
- package/packages/issue/dist/index.d.ts +7 -0
- package/packages/issue/dist/index.d.ts.map +1 -0
- package/packages/issue/dist/index.js +147 -0
- package/packages/issue/dist/index.js.map +1 -0
- package/packages/issue/package.json +14 -0
- package/packages/log-file/dist/index.d.ts +10 -0
- package/packages/log-file/dist/index.d.ts.map +1 -0
- package/packages/log-file/dist/index.js +200 -0
- package/packages/log-file/dist/index.js.map +1 -0
- package/packages/log-file/package.json +15 -0
- package/packages/mcp/dist/agentEndpoint.d.ts +31 -0
- package/packages/mcp/dist/agentEndpoint.d.ts.map +1 -0
- package/packages/mcp/dist/agentEndpoint.js +270 -0
- package/packages/mcp/dist/agentEndpoint.js.map +1 -0
- package/packages/mcp/dist/auth.d.ts +7 -0
- package/packages/mcp/dist/auth.d.ts.map +1 -0
- package/packages/mcp/dist/auth.js +48 -0
- package/packages/mcp/dist/auth.js.map +1 -0
- package/packages/mcp/dist/filter.d.ts +70 -0
- package/packages/mcp/dist/filter.d.ts.map +1 -0
- package/packages/mcp/dist/filter.js +231 -0
- package/packages/mcp/dist/filter.js.map +1 -0
- package/packages/mcp/dist/index.d.ts +7 -0
- package/packages/mcp/dist/index.d.ts.map +1 -0
- package/packages/mcp/dist/index.js +5 -0
- package/packages/mcp/dist/index.js.map +1 -0
- package/packages/mcp/dist/server.d.ts +31 -0
- package/packages/mcp/dist/server.d.ts.map +1 -0
- package/packages/mcp/dist/server.js +176 -0
- package/packages/mcp/dist/server.js.map +1 -0
- package/packages/mcp/dist/tools/linear.d.ts +5 -0
- package/packages/mcp/dist/tools/linear.d.ts.map +1 -0
- package/packages/mcp/dist/tools/linear.js +192 -0
- package/packages/mcp/dist/tools/linear.js.map +1 -0
- package/packages/mcp/dist/tools/local.d.ts +5 -0
- package/packages/mcp/dist/tools/local.d.ts.map +1 -0
- package/packages/mcp/dist/tools/local.js +161 -0
- package/packages/mcp/dist/tools/local.js.map +1 -0
- package/packages/mcp/dist/tools/result.d.ts +5 -0
- package/packages/mcp/dist/tools/result.d.ts.map +1 -0
- package/packages/mcp/dist/tools/result.js +15 -0
- package/packages/mcp/dist/tools/result.js.map +1 -0
- package/packages/mcp/dist/tools.d.ts +14 -0
- package/packages/mcp/dist/tools.d.ts.map +1 -0
- package/packages/mcp/dist/tools.js +58 -0
- package/packages/mcp/dist/tools.js.map +1 -0
- package/packages/mcp/package.json +20 -0
- package/packages/orchestrator/dist/index.d.ts +171 -0
- package/packages/orchestrator/dist/index.d.ts.map +1 -0
- package/packages/orchestrator/dist/index.js +524 -0
- package/packages/orchestrator/dist/index.js.map +1 -0
- package/packages/orchestrator/package.json +18 -0
- package/packages/policies/dist/index.d.ts +11 -0
- package/packages/policies/dist/index.d.ts.map +1 -0
- package/packages/policies/dist/index.js +6 -0
- package/packages/policies/dist/index.js.map +1 -0
- package/packages/policies/dist/reconciliation.d.ts +5 -0
- package/packages/policies/dist/reconciliation.d.ts.map +1 -0
- package/packages/policies/dist/reconciliation.js +17 -0
- package/packages/policies/dist/reconciliation.js.map +1 -0
- package/packages/policies/dist/resume.d.ts +14 -0
- package/packages/policies/dist/resume.d.ts.map +1 -0
- package/packages/policies/dist/resume.js +7 -0
- package/packages/policies/dist/resume.js.map +1 -0
- package/packages/policies/dist/retry.d.ts +4 -0
- package/packages/policies/dist/retry.d.ts.map +1 -0
- package/packages/policies/dist/retry.js +7 -0
- package/packages/policies/dist/retry.js.map +1 -0
- package/packages/policies/dist/stopReason.d.ts +4 -0
- package/packages/policies/dist/stopReason.d.ts.map +1 -0
- package/packages/policies/dist/stopReason.js +11 -0
- package/packages/policies/dist/stopReason.js.map +1 -0
- package/packages/policies/dist/usage.d.ts +14 -0
- package/packages/policies/dist/usage.d.ts.map +1 -0
- package/packages/policies/dist/usage.js +38 -0
- package/packages/policies/dist/usage.js.map +1 -0
- package/packages/policies/dist/workerHost.d.ts +8 -0
- package/packages/policies/dist/workerHost.d.ts.map +1 -0
- package/packages/policies/dist/workerHost.js +20 -0
- package/packages/policies/dist/workerHost.js.map +1 -0
- package/packages/policies/package.json +21 -0
- package/packages/presenter/dist/index.d.ts +81 -0
- package/packages/presenter/dist/index.d.ts.map +1 -0
- package/packages/presenter/dist/index.js +421 -0
- package/packages/presenter/dist/index.js.map +1 -0
- package/packages/presenter/package.json +16 -0
- package/packages/projections/dist/index.d.ts +10 -0
- package/packages/projections/dist/index.d.ts.map +1 -0
- package/packages/projections/dist/index.js +30 -0
- package/packages/projections/dist/index.js.map +1 -0
- package/packages/projections/package.json +15 -0
- package/packages/prompt/dist/index.d.ts +9 -0
- package/packages/prompt/dist/index.d.ts.map +1 -0
- package/packages/prompt/dist/index.js +71 -0
- package/packages/prompt/dist/index.js.map +1 -0
- package/packages/prompt/package.json +16 -0
- package/packages/retry-scheduler/dist/index.d.ts +12 -0
- package/packages/retry-scheduler/dist/index.d.ts.map +1 -0
- package/packages/retry-scheduler/dist/index.js +39 -0
- package/packages/retry-scheduler/dist/index.js.map +1 -0
- package/packages/retry-scheduler/package.json +15 -0
- package/packages/runtime/dist/index.d.ts +157 -0
- package/packages/runtime/dist/index.d.ts.map +1 -0
- package/packages/runtime/dist/index.js +1074 -0
- package/packages/runtime/dist/index.js.map +1 -0
- package/packages/runtime/package.json +26 -0
- package/packages/runtime-events/dist/index.d.ts +110 -0
- package/packages/runtime-events/dist/index.d.ts.map +1 -0
- package/packages/runtime-events/dist/index.js +25 -0
- package/packages/runtime-events/dist/index.js.map +1 -0
- package/packages/runtime-events/package.json +14 -0
- package/packages/server/dist/index.d.ts +25 -0
- package/packages/server/dist/index.d.ts.map +1 -0
- package/packages/server/dist/index.js +213 -0
- package/packages/server/dist/index.js.map +1 -0
- package/packages/server/dist/issue-store.d.ts +26 -0
- package/packages/server/dist/issue-store.d.ts.map +1 -0
- package/packages/server/dist/issue-store.js +88 -0
- package/packages/server/dist/issue-store.js.map +1 -0
- package/packages/server/dist/path-params.d.ts +6 -0
- package/packages/server/dist/path-params.d.ts.map +1 -0
- package/packages/server/dist/path-params.js +15 -0
- package/packages/server/dist/path-params.js.map +1 -0
- package/packages/server/dist/source.d.ts +12 -0
- package/packages/server/dist/source.d.ts.map +1 -0
- package/packages/server/dist/source.js +2 -0
- package/packages/server/dist/source.js.map +1 -0
- package/packages/server/dist/trace-routes.d.ts +21 -0
- package/packages/server/dist/trace-routes.d.ts.map +1 -0
- package/packages/server/dist/trace-routes.js +66 -0
- package/packages/server/dist/trace-routes.js.map +1 -0
- package/packages/server/dist/ws.d.ts +18 -0
- package/packages/server/dist/ws.d.ts.map +1 -0
- package/packages/server/dist/ws.js +168 -0
- package/packages/server/dist/ws.js.map +1 -0
- package/packages/server/package.json +22 -0
- package/packages/ssh/dist/index.d.ts +33 -0
- package/packages/ssh/dist/index.d.ts.map +1 -0
- package/packages/ssh/dist/index.js +281 -0
- package/packages/ssh/dist/index.js.map +1 -0
- package/packages/ssh/package.json +15 -0
- package/packages/static-worker/dist/index.d.ts +73 -0
- package/packages/static-worker/dist/index.d.ts.map +1 -0
- package/packages/static-worker/dist/index.js +150 -0
- package/packages/static-worker/dist/index.js.map +1 -0
- package/packages/static-worker/package.json +14 -0
- package/packages/tool-sdk/dist/filter.d.ts +70 -0
- package/packages/tool-sdk/dist/filter.d.ts.map +1 -0
- package/packages/tool-sdk/dist/filter.js +231 -0
- package/packages/tool-sdk/dist/filter.js.map +1 -0
- package/packages/tool-sdk/dist/index.d.ts +6 -0
- package/packages/tool-sdk/dist/index.d.ts.map +1 -0
- package/packages/tool-sdk/dist/index.js +4 -0
- package/packages/tool-sdk/dist/index.js.map +1 -0
- package/packages/tool-sdk/dist/provider.d.ts +51 -0
- package/packages/tool-sdk/dist/provider.d.ts.map +1 -0
- package/packages/tool-sdk/dist/provider.js +2 -0
- package/packages/tool-sdk/dist/provider.js.map +1 -0
- package/packages/tool-sdk/dist/registry.d.ts +35 -0
- package/packages/tool-sdk/dist/registry.d.ts.map +1 -0
- package/packages/tool-sdk/dist/registry.js +85 -0
- package/packages/tool-sdk/dist/registry.js.map +1 -0
- package/packages/tool-sdk/dist/result.d.ts +5 -0
- package/packages/tool-sdk/dist/result.d.ts.map +1 -0
- package/packages/tool-sdk/dist/result.js +15 -0
- package/packages/tool-sdk/dist/result.js.map +1 -0
- package/packages/tool-sdk/package.json +14 -0
- package/packages/traceviz-emitter/dist/index.d.ts +19 -0
- package/packages/traceviz-emitter/dist/index.d.ts.map +1 -0
- package/packages/traceviz-emitter/dist/index.js +97 -0
- package/packages/traceviz-emitter/dist/index.js.map +1 -0
- package/packages/traceviz-emitter/package.json +17 -0
- package/packages/traceviz-server/dist/index.d.ts +14 -0
- package/packages/traceviz-server/dist/index.d.ts.map +1 -0
- package/packages/traceviz-server/dist/index.js +10 -0
- package/packages/traceviz-server/dist/index.js.map +1 -0
- package/packages/traceviz-server/dist/models/api.d.ts +51 -0
- package/packages/traceviz-server/dist/models/api.d.ts.map +1 -0
- package/packages/traceviz-server/dist/models/api.js +5 -0
- package/packages/traceviz-server/dist/models/api.js.map +1 -0
- package/packages/traceviz-server/dist/models/display-events.d.ts +58 -0
- package/packages/traceviz-server/dist/models/display-events.d.ts.map +1 -0
- package/packages/traceviz-server/dist/models/display-events.js +6 -0
- package/packages/traceviz-server/dist/models/display-events.js.map +1 -0
- package/packages/traceviz-server/dist/parser.d.ts +14 -0
- package/packages/traceviz-server/dist/parser.d.ts.map +1 -0
- package/packages/traceviz-server/dist/parser.js +363 -0
- package/packages/traceviz-server/dist/parser.js.map +1 -0
- package/packages/traceviz-server/dist/stats.d.ts +7 -0
- package/packages/traceviz-server/dist/stats.d.ts.map +1 -0
- package/packages/traceviz-server/dist/stats.js +81 -0
- package/packages/traceviz-server/dist/stats.js.map +1 -0
- package/packages/traceviz-server/dist/watcher.d.ts +54 -0
- package/packages/traceviz-server/dist/watcher.d.ts.map +1 -0
- package/packages/traceviz-server/dist/watcher.js +368 -0
- package/packages/traceviz-server/dist/watcher.js.map +1 -0
- package/packages/traceviz-server/package.json +16 -0
- package/packages/tracker-sdk/dist/index.d.ts +5 -0
- package/packages/tracker-sdk/dist/index.d.ts.map +1 -0
- package/packages/tracker-sdk/dist/index.js +4 -0
- package/packages/tracker-sdk/dist/index.js.map +1 -0
- package/packages/tracker-sdk/dist/options.d.ts +20 -0
- package/packages/tracker-sdk/dist/options.d.ts.map +1 -0
- package/packages/tracker-sdk/dist/options.js +46 -0
- package/packages/tracker-sdk/dist/options.js.map +1 -0
- package/packages/tracker-sdk/dist/provider.d.ts +104 -0
- package/packages/tracker-sdk/dist/provider.d.ts.map +1 -0
- package/packages/tracker-sdk/dist/provider.js +2 -0
- package/packages/tracker-sdk/dist/provider.js.map +1 -0
- package/packages/tracker-sdk/dist/registry.d.ts +26 -0
- package/packages/tracker-sdk/dist/registry.d.ts.map +1 -0
- package/packages/tracker-sdk/dist/registry.js +52 -0
- package/packages/tracker-sdk/dist/registry.js.map +1 -0
- package/packages/tracker-sdk/dist/toolPack.d.ts +10 -0
- package/packages/tracker-sdk/dist/toolPack.d.ts.map +1 -0
- package/packages/tracker-sdk/dist/toolPack.js +185 -0
- package/packages/tracker-sdk/dist/toolPack.js.map +1 -0
- package/packages/tracker-sdk/package.json +15 -0
- package/packages/tui/dist/index.d.ts +35 -0
- package/packages/tui/dist/index.d.ts.map +1 -0
- package/packages/tui/dist/index.js +354 -0
- package/packages/tui/dist/index.js.map +1 -0
- package/packages/tui/package.json +18 -0
- package/packages/worker-host-pool/dist/index.d.ts +33 -0
- package/packages/worker-host-pool/dist/index.d.ts.map +1 -0
- package/packages/worker-host-pool/dist/index.js +311 -0
- package/packages/worker-host-pool/dist/index.js.map +1 -0
- package/packages/worker-host-pool/package.json +14 -0
- package/packages/worker-pool/dist/index.d.ts +6 -0
- package/packages/worker-pool/dist/index.d.ts.map +1 -0
- package/packages/worker-pool/dist/index.js +15 -0
- package/packages/worker-pool/dist/index.js.map +1 -0
- package/packages/worker-pool/dist/lease.d.ts +36 -0
- package/packages/worker-pool/dist/lease.d.ts.map +1 -0
- package/packages/worker-pool/dist/lease.js +53 -0
- package/packages/worker-pool/dist/lease.js.map +1 -0
- package/packages/worker-pool/dist/ledger.d.ts +51 -0
- package/packages/worker-pool/dist/ledger.d.ts.map +1 -0
- package/packages/worker-pool/dist/ledger.js +165 -0
- package/packages/worker-pool/dist/ledger.js.map +1 -0
- package/packages/worker-pool/dist/mutex.d.ts +10 -0
- package/packages/worker-pool/dist/mutex.d.ts.map +1 -0
- package/packages/worker-pool/dist/mutex.js +22 -0
- package/packages/worker-pool/dist/mutex.js.map +1 -0
- package/packages/worker-pool/dist/pool.d.ts +33 -0
- package/packages/worker-pool/dist/pool.d.ts.map +1 -0
- package/packages/worker-pool/dist/pool.js +1727 -0
- package/packages/worker-pool/dist/pool.js.map +1 -0
- package/packages/worker-pool/dist/reaper.d.ts +94 -0
- package/packages/worker-pool/dist/reaper.d.ts.map +1 -0
- package/packages/worker-pool/dist/reaper.js +295 -0
- package/packages/worker-pool/dist/reaper.js.map +1 -0
- package/packages/worker-pool/dist/types.d.ts +249 -0
- package/packages/worker-pool/dist/types.d.ts.map +1 -0
- package/packages/worker-pool/dist/types.js +2 -0
- package/packages/worker-pool/dist/types.js.map +1 -0
- package/packages/worker-pool/package.json +16 -0
- package/packages/worker-sdk/dist/conformance.d.ts +64 -0
- package/packages/worker-sdk/dist/conformance.d.ts.map +1 -0
- package/packages/worker-sdk/dist/conformance.js +109 -0
- package/packages/worker-sdk/dist/conformance.js.map +1 -0
- package/packages/worker-sdk/dist/fake.d.ts +76 -0
- package/packages/worker-sdk/dist/fake.d.ts.map +1 -0
- package/packages/worker-sdk/dist/fake.js +142 -0
- package/packages/worker-sdk/dist/fake.js.map +1 -0
- package/packages/worker-sdk/dist/index.d.ts +5 -0
- package/packages/worker-sdk/dist/index.d.ts.map +1 -0
- package/packages/worker-sdk/dist/index.js +10 -0
- package/packages/worker-sdk/dist/index.js.map +1 -0
- package/packages/worker-sdk/dist/module.d.ts +46 -0
- package/packages/worker-sdk/dist/module.d.ts.map +1 -0
- package/packages/worker-sdk/dist/module.js +59 -0
- package/packages/worker-sdk/dist/module.js.map +1 -0
- package/packages/worker-sdk/dist/registry.d.ts +24 -0
- package/packages/worker-sdk/dist/registry.d.ts.map +1 -0
- package/packages/worker-sdk/dist/registry.js +49 -0
- package/packages/worker-sdk/dist/registry.js.map +1 -0
- package/packages/worker-sdk/dist/types.d.ts +138 -0
- package/packages/worker-sdk/dist/types.d.ts.map +1 -0
- package/packages/worker-sdk/dist/types.js +21 -0
- package/packages/worker-sdk/dist/types.js.map +1 -0
- package/packages/worker-sdk/package.json +15 -0
- package/packages/workflow/dist/index.d.ts +33 -0
- package/packages/workflow/dist/index.d.ts.map +1 -0
- package/packages/workflow/dist/index.js +125 -0
- package/packages/workflow/dist/index.js.map +1 -0
- package/packages/workflow/package.json +19 -0
- package/packages/workspace/dist/index.d.ts +70 -0
- package/packages/workspace/dist/index.d.ts.map +1 -0
- package/packages/workspace/dist/index.js +1016 -0
- package/packages/workspace/dist/index.js.map +1 -0
- package/packages/workspace/package.json +17 -0
- package/runtime-deps/anthropic-claude-agent-sdk/LICENSE.md +1 -0
- package/runtime-deps/anthropic-claude-agent-sdk/README.md +65 -0
- package/runtime-deps/anthropic-claude-agent-sdk/agentSdkTypes.d.ts +1 -0
- package/runtime-deps/anthropic-claude-agent-sdk/assistant.d.ts +135 -0
- package/runtime-deps/anthropic-claude-agent-sdk/assistant.mjs +190 -0
- package/runtime-deps/anthropic-claude-agent-sdk/bridge.d.ts +231 -0
- package/runtime-deps/anthropic-claude-agent-sdk/bridge.mjs +168 -0
- package/runtime-deps/anthropic-claude-agent-sdk/browser-sdk.d.ts +53 -0
- package/runtime-deps/anthropic-claude-agent-sdk/browser-sdk.js +93 -0
- package/runtime-deps/anthropic-claude-agent-sdk/extractFromBunfs.d.ts +1 -0
- package/runtime-deps/anthropic-claude-agent-sdk/extractFromBunfs.js +156 -0
- package/runtime-deps/anthropic-claude-agent-sdk/manifest.json +47 -0
- package/runtime-deps/anthropic-claude-agent-sdk/manifest.zst.json +55 -0
- package/runtime-deps/anthropic-claude-agent-sdk/node_modules/.bin/anthropic-ai-sdk +21 -0
- package/runtime-deps/anthropic-claude-agent-sdk/package.json +81 -0
- package/runtime-deps/anthropic-claude-agent-sdk/sdk-tools.d.ts +3170 -0
- package/runtime-deps/anthropic-claude-agent-sdk/sdk.d.ts +6000 -0
- package/runtime-deps/anthropic-claude-agent-sdk/sdk.mjs +119 -0
- package/runtime-deps/openai-codex/README.md +60 -0
- package/runtime-deps/openai-codex/bin/codex.js +229 -0
- package/runtime-deps/openai-codex/bin/rg +79 -0
- package/runtime-deps/openai-codex/package.json +22 -0
- package/vendor/claude-agent-acp/dist/acp-agent.d.ts +239 -0
- package/vendor/claude-agent-acp/dist/acp-agent.d.ts.map +1 -0
- package/vendor/claude-agent-acp/dist/acp-agent.js +2693 -0
- package/vendor/claude-agent-acp/dist/bundle.js +41230 -0
- package/vendor/claude-agent-acp/dist/index.d.ts +3 -0
- package/vendor/claude-agent-acp/dist/index.d.ts.map +1 -0
- package/vendor/claude-agent-acp/dist/index.js +67 -0
- package/vendor/claude-agent-acp/dist/lib.d.ts +6 -0
- package/vendor/claude-agent-acp/dist/lib.d.ts.map +1 -0
- package/vendor/claude-agent-acp/dist/lib.js +5 -0
- package/vendor/claude-agent-acp/dist/settings.d.ts +68 -0
- package/vendor/claude-agent-acp/dist/settings.d.ts.map +1 -0
- package/vendor/claude-agent-acp/dist/settings.js +182 -0
- package/vendor/claude-agent-acp/dist/tools.d.ts +103 -0
- package/vendor/claude-agent-acp/dist/tools.d.ts.map +1 -0
- package/vendor/claude-agent-acp/dist/tools.js +713 -0
- package/vendor/claude-agent-acp/dist/utils.d.ts +16 -0
- package/vendor/claude-agent-acp/dist/utils.d.ts.map +1 -0
- package/vendor/claude-agent-acp/dist/utils.js +83 -0
- package/vendor/claude-agent-acp/package.json +23 -0
- package/vendor/codex-acp/dist/index.js +21280 -0
- package/vendor/codex-acp/package.json +17 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAiB,MAAM,gBAAgB,CAAC;AACvE,OAAO,EACL,WAAW,EACX,WAAW,EACX,sBAAsB,GAIvB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,qBAAqB,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAEhF;;;;GAIG;AACH,MAAM,sBAAsB,GAAG,IAAI,CAAC,OAAO,CACzC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAC5C,IAAI,EACJ,QAAQ,EACR,iBAAiB,CAClB,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAC7B,MAAM,wBAAwB,GAAG,IAAI,CAAC;AAOtC,MAAM,uBAAuB,GAAqB;IAChD,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;IACxC,KAAK,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC;CAC3C,CAAC;AAEF,MAAM,UAAU,eAAe;IAC7B,OAAO;QACL;YACE,IAAI,EAAE,gBAAgB;YACtB,WAAW,EAAE,gFAAgF;YAC7F,WAAW,EAAE;gBACX,IAAI,EAAE,QAAQ;gBACd,oBAAoB,EAAE,KAAK;gBAC3B,UAAU,EAAE;oBACV,KAAK,EAAE;wBACL,IAAI,EAAE,QAAQ;wBACd,WAAW,EAAE,+DAA+D;qBAC7E;oBACD,SAAS,EAAE;wBACT,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC;wBACxB,WAAW,EAAE,oCAAoC;wBACjD,oBAAoB,EAAE,IAAI;qBAC3B;iBACF;gBACD,QAAQ,EAAE,CAAC,OAAO,CAAC;aACpB;SACF;KACF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,IAAY,EACZ,KAAc,EACd,QAAkB,EAClB,YAA0B,KAAK;IAE/B,IAAI,IAAI,KAAK,gBAAgB,EAAE,CAAC;QAC9B,OAAO,sBAAsB,CAAC,IAAI,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAC1D,CAAC;IACD,MAAM,eAAe,GAAG,2BAA2B,CAAC,KAAK,CAAC,CAAC;IAC3D,IAAI,CAAC,eAAe,CAAC,EAAE,EAAE,CAAC;QACxB,OAAO,WAAW,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;IAC5C,CAAC;IACD,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IAC7D,IAAI,CAAC,MAAM;QACT,OAAO,WAAW,CAChB,oGAAoG,CACrG,CAAC;IACJ,IACE,eAAe,CAAC,SAAS,KAAK,SAAS;QACvC,eAAe,CAAC,SAAS,KAAK,IAAI;QAClC,CAAC,QAAQ,CAAC,eAAe,CAAC,SAAS,CAAC,EACpC,CAAC;QACD,OAAO,WAAW,CAAC,iEAAiE,CAAC,CAAC;IACxF,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,uBAAuB,CAAC;QACvC,MAAM,QAAQ,GAAG,MAAM,uBAAuB,CAC5C,SAAS,EACT,EAAE,MAAM,EAAE,QAAQ,EAAE,EACpB,eAAe,CAAC,KAAK,EACrB,eAAe,CAAC,SAAS,IAAI,EAAE,EAC/B,MAAM,CACP,CAAC;QACF,MAAM,UAAU,GAAG,MAAM,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QACpD,IAAI,CAAC,UAAU,CAAC,EAAE,EAAE,CAAC;YACnB,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,cAAc,CAAC,MAAM,EAAE,eAAe,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;gBACnF,OAAO,WAAW,CAAC,2CAA2C,QAAQ,CAAC,MAAM,GAAG,EAAE;oBAChF,MAAM,EAAE,QAAQ,CAAC,MAAM;iBACxB,CAAC,CAAC;YACL,CAAC;YACD,OAAO,WAAW,CAAC,wBAAwB,YAAY,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC/E,CAAC;QACD,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC;QAC7B,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,cAAc,CAAC,MAAM,EAAE,eAAe,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YACrE,OAAO,WAAW,CAAC,2CAA2C,QAAQ,CAAC,MAAM,GAAG,EAAE;gBAChF,MAAM,EAAE,QAAQ,CAAC,MAAM;aACxB,CAAC,CAAC;QACL,CAAC;QACD,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3E,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QAC1C,CAAC;QACD,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,uBAAuB,CAAC,KAAK,CAC3B,kCAAkC,YAAY,CAAC,KAAK,CAAC,GAAG,kBAAkB,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,CACpG,CAAC;QACF,OAAO,WAAW,CAAC,uEAAuE,EAAE;YAC1F,MAAM,EAAE,YAAY,CAAC,KAAK,CAAC;SAC5B,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,wFAAwF;AACxF,MAAM,CAAC,MAAM,kBAAkB,GAAiB;IAC9C,IAAI,EAAE,QAAQ;IACd,MAAM,EAAE,CAAC,sBAAsB,CAAC;IAChC,eAAe,EAAE,yBAAyB;IAC1C,SAAS,EAAE,GAAG,EAAE,CAAC,eAAe,EAAE;IAClC,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAC1C,iBAAiB,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,SAAS,CAAC;CACtE,CAAC;AAEF,SAAS,2BAA2B,CAClC,KAAc;IAId,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE;YACrB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,uDAAuD,EAAE,CAAC;QACvF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IACpC,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;QACxD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,uDAAuD,EAAE,CAAC;IACvF,CAAC;IACD,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE;QAC3B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,uDAAuD,EAAE,CAAC;IACvF,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS,IAAI,KAAK,CAAC,SAAS,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;QAC5F,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,iEAAiE,EAAE,CAAC;IACjG,CAAC;IACD,OAAO;QACL,EAAE,EAAE,IAAI;QACR,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,SAAS,EAAE,KAAK,CAAC,SAA2C;KAC7D,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,uBAAuB,CACpC,SAAuB,EACvB,IAA0C,EAC1C,KAAa,EACb,SAAkC,EAClC,MAAwB;IAExB,KAAK,IAAI,UAAU,GAAG,CAAC,GAAI,UAAU,IAAI,CAAC,EAAE,CAAC;QAC3C,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE;YAC9C,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC;YACnC,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,IAAI,CAAC,MAAM;aAC3B;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;SAC3C,CAAC,CAAC;QACH,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,UAAU,IAAI,kBAAkB;YAAE,OAAO,QAAQ,CAAC;QACjF,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAC3D,MAAM,CAAC,IAAI,CACT,wDAAwD,UAAU,GAAG,CAAC,IAAI,kBAAkB,aAAa,OAAO,GAAG,kBAAkB,CAAC,KAAK,EAAE,MAAM,kBAAkB,CAAC,QAAQ,CAAC,CAAC,EAAE,CACnL,CAAC;QACF,MAAM,KAAK,CAAC,OAAO,CAAC,CAAC;IACvB,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,OAAgB,EAAE,UAAkB;IACxD,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAC9C,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;QACxB,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;QAC1C,IAAI,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,OAAO,IAAI,CAAC;YAAE,OAAO,OAAO,GAAG,IAAI,CAAC;QACrE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;QAC7C,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC;YAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,IAAI,UAAU,EAAE,MAAM,CAAC,CAAC;AACnD,CAAC;AAED,KAAK,UAAU,KAAK,CAAC,OAAe;IAClC,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED,KAAK,UAAU,gBAAgB,CAC7B,QAAkB;IAElB,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IAC9B,CAAC;IACD,IAAI,CAAC;QACH,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAY,EAAE,CAAC;IAC5D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;IACvC,CAAC;AACH,CAAC;AAED,KAAK,UAAU,kBAAkB,CAAC,QAAkB;IAClD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC;QAC9C,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAY,CAAC;QACxC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,OAAO,CAAC;QACjB,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CACrB,MAAwB,EACxB,KAAa,EACb,MAAc,EACd,IAAa;IAEb,MAAM,CAAC,KAAK,CAAC,wCAAwC,MAAM,GAAG,kBAAkB,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;AACnG,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAa,EAAE,IAAc;IACvD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,SAAS,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IACvC,IAAI,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,aAAa,SAAS,EAAE,CAAC,CAAC;IACpD,IAAI,IAAI,KAAK,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACvE,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;AACzD,CAAC;AAED,SAAS,aAAa,CAAC,KAAa;IAClC,OAAO,iDAAiD,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;AACpF,CAAC;AAED,SAAS,kBAAkB,CAAC,IAAa;IACvC,MAAM,IAAI,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;IACxE,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACjD,IAAI,OAAO,CAAC,MAAM,IAAI,wBAAwB;QAAE,OAAO,OAAO,CAAC;IAC/D,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,wBAAwB,CAAC,gBAAgB,CAAC;AACvE,CAAC;AAED,SAAS,kBAAkB,CAAC,IAAa;IACvC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lorenz/linear-tracker",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./dist/index.js"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@linear/sdk": "^84.0.0",
|
|
13
|
+
"@lorenz/domain": "file:../../packages/domain",
|
|
14
|
+
"@lorenz/issue": "file:../../packages/issue",
|
|
15
|
+
"@lorenz/tool-sdk": "file:../../packages/tool-sdk",
|
|
16
|
+
"@lorenz/tracker-sdk": "file:../../packages/tracker-sdk"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import type { Issue } from "@lorenz/domain";
|
|
2
|
+
/**
|
|
3
|
+
* Default issue-id prefix. {@link BoardStore} mints ids shaped `<prefix><n>` (see
|
|
4
|
+
* {@link BoardStore.nextId}); the prefix is configurable per board (tracker.id_prefix) and
|
|
5
|
+
* defaults to this. Anything not matching `^<prefix>\d+$` - including ids containing path
|
|
6
|
+
* separators, "..", or NUL - is rejected before it can reach the filesystem, closing off path
|
|
7
|
+
* traversal via agent-supplied ids.
|
|
8
|
+
*/
|
|
9
|
+
export declare const DEFAULT_ID_PREFIX = "BOARD-";
|
|
10
|
+
/**
|
|
11
|
+
* The agent-facing read view of a single board issue. Returned by {@link BoardStore.readContent}
|
|
12
|
+
* so a worker can read back an issue's current status, title, description, AND the comments it (or
|
|
13
|
+
* the operator) has appended - symmetric with the write tools (updateStatus/appendComment/create).
|
|
14
|
+
* `comments` is the list of individual "- ..." lines from the issue's "## Comments" section, with
|
|
15
|
+
* an empty array when the issue has no comments yet.
|
|
16
|
+
*/
|
|
17
|
+
export interface BoardIssueContent {
|
|
18
|
+
id: string;
|
|
19
|
+
status: string;
|
|
20
|
+
title: string;
|
|
21
|
+
description: string;
|
|
22
|
+
comments: string[];
|
|
23
|
+
}
|
|
24
|
+
/** A board file that {@link BoardStore.list} could not parse, surfaced rather than hidden. */
|
|
25
|
+
export interface SkippedBoardFile {
|
|
26
|
+
/** The id derived from the filename (e.g. "BOARD-2"), even if its contents are invalid. */
|
|
27
|
+
id: string;
|
|
28
|
+
/** Human-readable reason the file was skipped (missing status, unparseable YAML, etc.). */
|
|
29
|
+
error: string;
|
|
30
|
+
}
|
|
31
|
+
export interface BoardStoreOptions {
|
|
32
|
+
/**
|
|
33
|
+
* Invoked once per board file that fails to parse during a bulk {@link BoardStore.list}
|
|
34
|
+
* (and the {@link BoardStore.byStatus} / candidate flows built on it). A single bad file is
|
|
35
|
+
* skipped so it cannot starve the rest of the board, but it is reported here so the problem
|
|
36
|
+
* is observable instead of silently swallowed. Explicit {@link BoardStore.getByIds} lookups
|
|
37
|
+
* stay strict and throw rather than routing through this callback.
|
|
38
|
+
*/
|
|
39
|
+
onSkip?: (skip: SkippedBoardFile) => void;
|
|
40
|
+
/**
|
|
41
|
+
* Issue-id prefix for this board (e.g. `"BOARD-"`, `"XXX-"`). Ids are `<prefix><n>`; only
|
|
42
|
+
* `<prefix><n>.md` files are treated as issues, and new ids are minted with this prefix.
|
|
43
|
+
* Defaults to {@link DEFAULT_ID_PREFIX}. Must be filesystem-safe (see {@link assertValidIdPrefix});
|
|
44
|
+
* an invalid prefix throws from the constructor.
|
|
45
|
+
*/
|
|
46
|
+
idPrefix?: string;
|
|
47
|
+
}
|
|
48
|
+
export declare class BoardStore {
|
|
49
|
+
private readonly dir;
|
|
50
|
+
private readonly onSkip;
|
|
51
|
+
private readonly idPrefix;
|
|
52
|
+
/** `^<prefix>\d+$` - the canonical id shape this board mints and accepts. */
|
|
53
|
+
private readonly idPattern;
|
|
54
|
+
constructor(dir: string, options?: BoardStoreOptions);
|
|
55
|
+
list(): Promise<Issue[]>;
|
|
56
|
+
getByIds(ids: string[]): Promise<Issue[]>;
|
|
57
|
+
byStatus(states: string[]): Promise<Issue[]>;
|
|
58
|
+
updateStatus(id: string, status: string): Promise<Issue>;
|
|
59
|
+
appendComment(id: string, body: string, now?: () => Date): Promise<void>;
|
|
60
|
+
/**
|
|
61
|
+
* Agent-facing read of a single issue's content: its current status, title, description, and the
|
|
62
|
+
* comments appended to it. Symmetric with the write methods so a worker can read back what it (or
|
|
63
|
+
* the operator) wrote. Validates the id and reads/parses the file via the same parse() the write
|
|
64
|
+
* paths use, so a missing/invalid id throws exactly as getByIds/updateStatus do. The "## Comments"
|
|
65
|
+
* block is split into individual "- ..." entries (empty array when the issue has no comments).
|
|
66
|
+
*/
|
|
67
|
+
readContent(id: string): Promise<BoardIssueContent>;
|
|
68
|
+
create(input: {
|
|
69
|
+
title: string;
|
|
70
|
+
body?: string;
|
|
71
|
+
status?: string;
|
|
72
|
+
}): Promise<Issue>;
|
|
73
|
+
/**
|
|
74
|
+
* Create the board directory durably so a freshly-created board survives a crash. mkdir alone
|
|
75
|
+
* is not enough: fsyncing this.dir after publishing a file persists the entries INSIDE it, but
|
|
76
|
+
* NOT the directory entry in the PARENT that makes a newly-created board dir reachable. On a
|
|
77
|
+
* first-run board (the .symphony/local path did not exist) a crash right after create() could
|
|
78
|
+
* otherwise lose the entire new directory and the acknowledged issue even though the file and
|
|
79
|
+
* the board dir were synced.
|
|
80
|
+
*
|
|
81
|
+
* fs.mkdir(dir, { recursive: true }) returns the path of the FIRST (topmost) directory it
|
|
82
|
+
* actually created, or undefined when nothing was created (the dir already existed). When it
|
|
83
|
+
* created something, every directory along the chain from that topmost-created dir down to (and
|
|
84
|
+
* including) this.dir is brand new, and each gained a new child entry in its own parent. To make
|
|
85
|
+
* the whole chain reachable we fsync each parent that gained a new entry: path.dirname(topmost)
|
|
86
|
+
* (the pre-existing parent that gained the top new dir) plus every newly-created directory from
|
|
87
|
+
* the topmost down to - but NOT including - this.dir (this.dir's own entry is fsynced by the
|
|
88
|
+
* existing post-publish fsyncDir(this.dir), which persists the new FILE entry inside it). When
|
|
89
|
+
* nothing was created (dir already existed) there is no parent entry to flush. fsyncDir is
|
|
90
|
+
* best-effort (it swallows dir-fsync-unsupported errors), so platforms that cannot fsync a dir
|
|
91
|
+
* handle are unaffected.
|
|
92
|
+
*/
|
|
93
|
+
private ensureBoardDir;
|
|
94
|
+
private filePath;
|
|
95
|
+
private issueIds;
|
|
96
|
+
private nextId;
|
|
97
|
+
private read;
|
|
98
|
+
private parse;
|
|
99
|
+
private render;
|
|
100
|
+
/**
|
|
101
|
+
* Atomic replace: write to a uniquely-named sibling temp file in the SAME directory and
|
|
102
|
+
* fs.rename it over the target. rename is atomic within a filesystem, so a crash mid-write
|
|
103
|
+
* leaves either the prior file or the fully-written new file intact - never a truncated one.
|
|
104
|
+
* The contents are fsync'd before the rename and the directory after it, so the rename cannot
|
|
105
|
+
* expose a name whose data has not yet reached disk (which would otherwise read back empty).
|
|
106
|
+
*/
|
|
107
|
+
private write;
|
|
108
|
+
/** Reject any id not matching this board's `^<prefix>\d+$` (defends agent-supplied ids). */
|
|
109
|
+
private assertValidId;
|
|
110
|
+
/**
|
|
111
|
+
* Numeric suffix of a canonical id (e.g. "XXX-7" -> 7). Callers pass ids that already matched
|
|
112
|
+
* idPattern, so the slice after the prefix is always digits; the fallback is belt-and-suspenders.
|
|
113
|
+
*/
|
|
114
|
+
private boardNumber;
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=boardStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"boardStore.d.ts","sourceRoot":"","sources":["../src/boardStore.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAmB5C;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,WAAW,CAAC;AA6G1C;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,8FAA8F;AAC9F,MAAM,WAAW,gBAAgB;IAC/B,2FAA2F;IAC3F,EAAE,EAAE,MAAM,CAAC;IACX,2FAA2F;IAC3F,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC1C;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,UAAU;IAOnB,OAAO,CAAC,QAAQ,CAAC,GAAG;IANtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiD;IACxE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,6EAA6E;IAC7E,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAGhB,GAAG,EAAE,MAAM,EAC5B,OAAO,GAAE,iBAAsB;IAQ3B,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;IAexB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAQzC,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAK5C,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAiBxD,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,IAAuB,GAAG,OAAO,CAAC,IAAI,CAAC;IAYhG;;;;;;OAMG;IACG,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAanD,MAAM,CAAC,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,KAAK,CAAC;IAwEtF;;;;;;;;;;;;;;;;;;;OAmBG;YACW,cAAc;IAsB5B,OAAO,CAAC,QAAQ;YAWF,QAAQ;YAgCR,MAAM;YAMN,IAAI;YAmBJ,KAAK;IAYnB,OAAO,CAAC,MAAM;IAUd;;;;;;OAMG;YACW,KAAK;IAenB,4FAA4F;IAC5F,OAAO,CAAC,aAAa;IAQrB;;;OAGG;IACH,OAAO,CAAC,WAAW;CAIpB"}
|
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { defaultStateType, normalizeIssue } from "@lorenz/issue";
|
|
4
|
+
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
5
|
+
/**
|
|
6
|
+
* Collision-resistant sentinel that marks the start of the comments section. It sits
|
|
7
|
+
* immediately before the human-readable "## Comments" heading so a description that
|
|
8
|
+
* legitimately contains a "## Comments" heading is never misparsed.
|
|
9
|
+
*/
|
|
10
|
+
const COMMENTS_MARKER = "<!-- symphony:comments -->";
|
|
11
|
+
/**
|
|
12
|
+
* Default issue-id prefix. {@link BoardStore} mints ids shaped `<prefix><n>` (see
|
|
13
|
+
* {@link BoardStore.nextId}); the prefix is configurable per board (tracker.id_prefix) and
|
|
14
|
+
* defaults to this. Anything not matching `^<prefix>\d+$` - including ids containing path
|
|
15
|
+
* separators, "..", or NUL - is rejected before it can reach the filesystem, closing off path
|
|
16
|
+
* traversal via agent-supplied ids.
|
|
17
|
+
*/
|
|
18
|
+
export const DEFAULT_ID_PREFIX = "BOARD-";
|
|
19
|
+
/**
|
|
20
|
+
* Valid id prefixes: an alphanumeric, then alphanumerics / `_` / `-`. Disallowing `.`, `/`, `\`,
|
|
21
|
+
* whitespace and NUL keeps every minted filename inside the board dir (no traversal) and keeps
|
|
22
|
+
* `<prefix><n>` an unambiguous, safe filename stem. The trailing `-` in "BOARD-" is allowed.
|
|
23
|
+
*/
|
|
24
|
+
const ID_PREFIX_PATTERN = /^[A-Za-z0-9][A-Za-z0-9_-]*$/;
|
|
25
|
+
/** Escape a string for safe literal interpolation into a RegExp (the configured prefix). */
|
|
26
|
+
function escapeRegExp(s) {
|
|
27
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
28
|
+
}
|
|
29
|
+
/** Throw if `prefix` is not a safe id prefix (letters/digits, then letters/digits/`_`/`-`). */
|
|
30
|
+
function assertValidIdPrefix(prefix) {
|
|
31
|
+
if (!ID_PREFIX_PATTERN.test(prefix)) {
|
|
32
|
+
throw new Error(`invalid board id_prefix: ${JSON.stringify(prefix)} ` +
|
|
33
|
+
`(must start alphanumeric, then only letters, digits, "_" or "-")`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Module-level (process-wide) lock chain keyed by an absolute filesystem path. Because
|
|
38
|
+
* {@link BoardStore} is rebuilt per MCP call (see storeFor), the mutex MUST live at module
|
|
39
|
+
* scope so every instance pointing at the same board file/dir shares the same chain.
|
|
40
|
+
*
|
|
41
|
+
* Each key maps to a promise that resolves when the currently-queued critical sections for
|
|
42
|
+
* that key have finished. {@link withLock} appends its work to the chain so read-modify-write
|
|
43
|
+
* cycles on the same file (or id allocation in the same dir) serialize instead of interleaving
|
|
44
|
+
* and losing an update. This is IN-PROCESS serialization only: it covers concurrent agents and
|
|
45
|
+
* ensemble slots inside the single Symphony daemon, but assumes no external process is editing
|
|
46
|
+
* the board files concurrently (that is out of scope - see ts/README.md).
|
|
47
|
+
*/
|
|
48
|
+
const pathLocks = new Map();
|
|
49
|
+
/**
|
|
50
|
+
* Force a file's CONTENTS to durable storage. The temp/rename and temp/link publish dances are
|
|
51
|
+
* only crash-atomic if the new file's data blocks reach disk BEFORE the directory entry that
|
|
52
|
+
* exposes them: otherwise a power-loss can leave a published BOARD-<n>.md whose name is visible
|
|
53
|
+
* but whose contents are still buffered (zero-length or truncated) - the exact "empty/partial
|
|
54
|
+
* file" failure the atomic publish is meant to prevent. fsync the data first, then the dir entry.
|
|
55
|
+
*/
|
|
56
|
+
async function fsyncFile(filePath) {
|
|
57
|
+
const fh = await fs.open(filePath, "r");
|
|
58
|
+
try {
|
|
59
|
+
await fh.sync();
|
|
60
|
+
}
|
|
61
|
+
finally {
|
|
62
|
+
await fh.close();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Force a DIRECTORY entry to durable storage so a freshly-published (renamed/linked) file is
|
|
67
|
+
* guaranteed to survive a crash. Directory fsync is a best-effort durability barrier: some
|
|
68
|
+
* platforms (notably Windows) cannot fsync a directory handle and reject with EINVAL/EISDIR/
|
|
69
|
+
* EPERM/EBADF/ENOTSUP/EACCES. Those are swallowed - the data fsync above already protects the
|
|
70
|
+
* contents, and the OS will flush the entry on its own schedule - but unexpected errors propagate.
|
|
71
|
+
*/
|
|
72
|
+
async function fsyncDir(dirPath) {
|
|
73
|
+
let fh;
|
|
74
|
+
try {
|
|
75
|
+
fh = await fs.open(dirPath, "r");
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
if (isUnsupportedDirSync(err.code))
|
|
79
|
+
return;
|
|
80
|
+
throw err;
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
await fh.sync();
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
if (!isUnsupportedDirSync(err.code))
|
|
87
|
+
throw err;
|
|
88
|
+
}
|
|
89
|
+
finally {
|
|
90
|
+
await fh.close();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/** Platforms that cannot fsync a directory handle reject with one of these; treat as a no-op. */
|
|
94
|
+
function isUnsupportedDirSync(code) {
|
|
95
|
+
return (code === "EINVAL" ||
|
|
96
|
+
code === "EISDIR" ||
|
|
97
|
+
code === "EPERM" ||
|
|
98
|
+
code === "EBADF" ||
|
|
99
|
+
code === "ENOTSUP" ||
|
|
100
|
+
code === "EACCES");
|
|
101
|
+
}
|
|
102
|
+
async function withLock(key, fn) {
|
|
103
|
+
const prior = pathLocks.get(key) ?? Promise.resolve();
|
|
104
|
+
// Run fn after the prior holder settles. Always continue (.then with both handlers) so one
|
|
105
|
+
// critical section's failure cannot poison the next caller's turn.
|
|
106
|
+
const run = prior.then(fn, fn);
|
|
107
|
+
// The tail is what later callers wait on; its settled value/error is intentionally discarded.
|
|
108
|
+
const tail = run.then(() => undefined, () => undefined);
|
|
109
|
+
pathLocks.set(key, tail);
|
|
110
|
+
try {
|
|
111
|
+
return await run;
|
|
112
|
+
}
|
|
113
|
+
finally {
|
|
114
|
+
// Once this is the last queued work for the key, drop it so the Map cannot grow unbounded.
|
|
115
|
+
if (pathLocks.get(key) === tail)
|
|
116
|
+
pathLocks.delete(key);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
export class BoardStore {
|
|
120
|
+
dir;
|
|
121
|
+
onSkip;
|
|
122
|
+
idPrefix;
|
|
123
|
+
/** `^<prefix>\d+$` - the canonical id shape this board mints and accepts. */
|
|
124
|
+
idPattern;
|
|
125
|
+
constructor(dir, options = {}) {
|
|
126
|
+
this.dir = dir;
|
|
127
|
+
this.onSkip = options.onSkip;
|
|
128
|
+
this.idPrefix = options.idPrefix ?? DEFAULT_ID_PREFIX;
|
|
129
|
+
assertValidIdPrefix(this.idPrefix);
|
|
130
|
+
this.idPattern = new RegExp(`^${escapeRegExp(this.idPrefix)}\\d+$`);
|
|
131
|
+
}
|
|
132
|
+
async list() {
|
|
133
|
+
const ids = await this.issueIds();
|
|
134
|
+
const out = [];
|
|
135
|
+
for (const id of ids) {
|
|
136
|
+
try {
|
|
137
|
+
out.push(await this.read(id));
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
// One malformed/unreadable file must not abort the whole listing (and, via the
|
|
141
|
+
// runtime, the poll). Skip it but surface the reason through onSkip so it is visible.
|
|
142
|
+
this.onSkip?.({ id, error: err instanceof Error ? err.message : String(err) });
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return out;
|
|
146
|
+
}
|
|
147
|
+
async getByIds(ids) {
|
|
148
|
+
for (const id of ids)
|
|
149
|
+
this.assertValidId(id);
|
|
150
|
+
const existing = new Set(await this.issueIds());
|
|
151
|
+
const out = [];
|
|
152
|
+
for (const id of ids)
|
|
153
|
+
if (existing.has(id))
|
|
154
|
+
out.push(await this.read(id));
|
|
155
|
+
return out;
|
|
156
|
+
}
|
|
157
|
+
async byStatus(states) {
|
|
158
|
+
const wanted = new Set(states.map((s) => s.trim().toLowerCase()));
|
|
159
|
+
return (await this.list()).filter((i) => wanted.has(i.state.trim().toLowerCase()));
|
|
160
|
+
}
|
|
161
|
+
async updateStatus(id, status) {
|
|
162
|
+
this.assertValidId(id);
|
|
163
|
+
const trimmed = status.trim();
|
|
164
|
+
// Reject an empty/whitespace-only status BEFORE writing: a blank status produces a file
|
|
165
|
+
// that parse() rejects as "missing required 'status'", which would silently drop the issue
|
|
166
|
+
// from list(). Failing fast here leaves the file (and its prior status) intact.
|
|
167
|
+
if (trimmed === "")
|
|
168
|
+
throw new Error(`board issue ${id} status must not be empty`);
|
|
169
|
+
// Serialize the read-modify-write per target file (module-level lock) so a concurrent
|
|
170
|
+
// appendComment/updateStatus on the same issue cannot read-then-clobber and lose an update.
|
|
171
|
+
return withLock(this.filePath(id), async () => {
|
|
172
|
+
const parsed = await this.parse(id);
|
|
173
|
+
parsed.status = trimmed;
|
|
174
|
+
await this.write(id, parsed);
|
|
175
|
+
return this.read(id);
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
async appendComment(id, body, now = () => new Date()) {
|
|
179
|
+
this.assertValidId(id);
|
|
180
|
+
// Same per-file lock as updateStatus: the parse -> append -> write cycle must be atomic with
|
|
181
|
+
// respect to other mutations of this issue, otherwise concurrent comments overwrite each other.
|
|
182
|
+
await withLock(this.filePath(id), async () => {
|
|
183
|
+
const parsed = await this.parse(id);
|
|
184
|
+
const line = `- ${now().toISOString()} agent: ${body}`;
|
|
185
|
+
parsed.comments = parsed.comments ? `${parsed.comments}\n${line}` : line;
|
|
186
|
+
await this.write(id, parsed);
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Agent-facing read of a single issue's content: its current status, title, description, and the
|
|
191
|
+
* comments appended to it. Symmetric with the write methods so a worker can read back what it (or
|
|
192
|
+
* the operator) wrote. Validates the id and reads/parses the file via the same parse() the write
|
|
193
|
+
* paths use, so a missing/invalid id throws exactly as getByIds/updateStatus do. The "## Comments"
|
|
194
|
+
* block is split into individual "- ..." entries (empty array when the issue has no comments).
|
|
195
|
+
*/
|
|
196
|
+
async readContent(id) {
|
|
197
|
+
this.assertValidId(id);
|
|
198
|
+
const parsed = await this.parse(id);
|
|
199
|
+
const comments = parsed.comments.trim() === "" ? [] : parsed.comments.split("\n");
|
|
200
|
+
return {
|
|
201
|
+
id,
|
|
202
|
+
status: parsed.status,
|
|
203
|
+
title: parsed.title,
|
|
204
|
+
description: parsed.description,
|
|
205
|
+
comments,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
async create(input) {
|
|
209
|
+
const status = input.status === undefined ? "Todo" : input.status.trim();
|
|
210
|
+
if (status === "")
|
|
211
|
+
throw new Error("board issue status must not be empty");
|
|
212
|
+
const parsed = {
|
|
213
|
+
status,
|
|
214
|
+
labels: [],
|
|
215
|
+
title: input.title,
|
|
216
|
+
description: input.body ?? "",
|
|
217
|
+
comments: "",
|
|
218
|
+
};
|
|
219
|
+
const contents = this.render(parsed);
|
|
220
|
+
// Serialize id allocation per board DIRECTORY under the same module-level lock so concurrent
|
|
221
|
+
// creates in one daemon do not all scan the same nextId in lockstep. The no-overwrite link
|
|
222
|
+
// below is still the authoritative guard (it also defends against any external writer), so the
|
|
223
|
+
// lock is an optimization that also keeps the bounded retry loop from churning.
|
|
224
|
+
return withLock(path.resolve(this.dir), async () => {
|
|
225
|
+
// ensureBoardDir MUST run inside the per-directory lock. On a first-run board the chain is
|
|
226
|
+
// created by mkdir(recursive), and fs.mkdir returns only the topmost level THIS call observed
|
|
227
|
+
// as newly-created. Two concurrent first-run creates can interleave inside Node's recursive
|
|
228
|
+
// mkdir so each sees a different topmost-created level and fsyncs only its own slice of the
|
|
229
|
+
// chain - with no happens-before barrier guaranteeing the slice covering the upper parents is
|
|
230
|
+
// durable before the other caller publishes its file. Serializing ensureBoardDir under the
|
|
231
|
+
// same lock as the publish makes exactly one create build AND fully fsync the new chain before
|
|
232
|
+
// any racing create observes the dir as existing (mkdir returns undefined) and links its file.
|
|
233
|
+
await this.ensureBoardDir();
|
|
234
|
+
// Crash-atomic publish: write the full contents to a sibling TEMP file first, then PUBLISH
|
|
235
|
+
// it to the final BOARD-<n>.md with a no-overwrite hard link. fs.link is atomic and fails
|
|
236
|
+
// with EEXIST if the target already exists, so it is collision-safe (two racing creates can
|
|
237
|
+
// never pick the same BOARD-<n>, and an external writer is still defended against) AND
|
|
238
|
+
// crash-safe (a process death mid-write leaves only the ignored temp, never a truncated
|
|
239
|
+
// <prefix><n>.md - issueIds() filters to ^<prefix>\d+$ so the dotted temp is invisible). On
|
|
240
|
+
// EEXIST we recompute nextId and retry the link, reusing the same fully-written temp file.
|
|
241
|
+
//
|
|
242
|
+
// The temp name is NOT a "<prefix><n>.md" stem (it is dotted and ends in .tmp) so it is never
|
|
243
|
+
// mistaken for an issue; the id is not part of the name because one temp serves every retry.
|
|
244
|
+
const tmp = path.join(this.dir, `.symphony-create.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`);
|
|
245
|
+
try {
|
|
246
|
+
await fs.writeFile(tmp, contents, "utf8");
|
|
247
|
+
// Flush the temp's CONTENTS to disk before publishing its directory entry. Otherwise a
|
|
248
|
+
// crash after fs.link could leave a named BOARD-<n>.md whose data is still buffered (i.e.
|
|
249
|
+
// an empty/partial file) - the very failure the temp+link publish is meant to rule out.
|
|
250
|
+
await fsyncFile(tmp);
|
|
251
|
+
// Allocate an id with a no-overwrite link so two racing creates can never publish over the
|
|
252
|
+
// same BOARD-<n>. On collision (EEXIST) we recompute the next id and retry within a bounded
|
|
253
|
+
// loop rather than blindly overwriting an existing issue file.
|
|
254
|
+
const attempts = 64;
|
|
255
|
+
for (let attempt = 0; attempt < attempts; attempt++) {
|
|
256
|
+
const id = await this.nextId();
|
|
257
|
+
const target = this.filePath(id);
|
|
258
|
+
try {
|
|
259
|
+
await fs.link(tmp, target);
|
|
260
|
+
}
|
|
261
|
+
catch (err) {
|
|
262
|
+
if (err.code === "EEXIST")
|
|
263
|
+
continue;
|
|
264
|
+
throw err;
|
|
265
|
+
}
|
|
266
|
+
// The new directory entry must itself be durable, or a crash could lose the just-linked
|
|
267
|
+
// name even though its (already-fsynced) contents are safe. Flush the dir, then read back.
|
|
268
|
+
await fsyncDir(this.dir);
|
|
269
|
+
return await this.read(id);
|
|
270
|
+
}
|
|
271
|
+
throw new Error(`failed to allocate a board id after ${attempts} attempts`);
|
|
272
|
+
}
|
|
273
|
+
finally {
|
|
274
|
+
// Always drop the temp (success or failure). A leftover is harmless - issueIds() ignores
|
|
275
|
+
// it - but removing it keeps the board dir clean. force:true so a never-created temp is fine.
|
|
276
|
+
await fs.rm(tmp, { force: true }).catch(() => { });
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Create the board directory durably so a freshly-created board survives a crash. mkdir alone
|
|
282
|
+
* is not enough: fsyncing this.dir after publishing a file persists the entries INSIDE it, but
|
|
283
|
+
* NOT the directory entry in the PARENT that makes a newly-created board dir reachable. On a
|
|
284
|
+
* first-run board (the .symphony/local path did not exist) a crash right after create() could
|
|
285
|
+
* otherwise lose the entire new directory and the acknowledged issue even though the file and
|
|
286
|
+
* the board dir were synced.
|
|
287
|
+
*
|
|
288
|
+
* fs.mkdir(dir, { recursive: true }) returns the path of the FIRST (topmost) directory it
|
|
289
|
+
* actually created, or undefined when nothing was created (the dir already existed). When it
|
|
290
|
+
* created something, every directory along the chain from that topmost-created dir down to (and
|
|
291
|
+
* including) this.dir is brand new, and each gained a new child entry in its own parent. To make
|
|
292
|
+
* the whole chain reachable we fsync each parent that gained a new entry: path.dirname(topmost)
|
|
293
|
+
* (the pre-existing parent that gained the top new dir) plus every newly-created directory from
|
|
294
|
+
* the topmost down to - but NOT including - this.dir (this.dir's own entry is fsynced by the
|
|
295
|
+
* existing post-publish fsyncDir(this.dir), which persists the new FILE entry inside it). When
|
|
296
|
+
* nothing was created (dir already existed) there is no parent entry to flush. fsyncDir is
|
|
297
|
+
* best-effort (it swallows dir-fsync-unsupported errors), so platforms that cannot fsync a dir
|
|
298
|
+
* handle are unaffected.
|
|
299
|
+
*/
|
|
300
|
+
async ensureBoardDir() {
|
|
301
|
+
const firstCreated = await fs.mkdir(this.dir, { recursive: true });
|
|
302
|
+
if (!firstCreated)
|
|
303
|
+
return;
|
|
304
|
+
// Every directory that gained a NEW child entry along the freshly-created chain must be
|
|
305
|
+
// fsynced so the chain is reachable. Those are exactly the parents of each newly-created
|
|
306
|
+
// directory: path.dirname(top) (the pre-existing dir that gained `top`) through to
|
|
307
|
+
// path.dirname(this.dir) (the last new dir above this.dir). We walk UP from this.dir's parent
|
|
308
|
+
// and stop after flushing path.dirname(top). this.dir itself is intentionally skipped - its
|
|
309
|
+
// own entry is persisted by the post-publish fsyncDir(this.dir) that flushes the new file.
|
|
310
|
+
const top = path.resolve(firstCreated);
|
|
311
|
+
const stop = path.dirname(top);
|
|
312
|
+
let parent = path.dirname(path.resolve(this.dir));
|
|
313
|
+
// Guard against an unexpected loop at a filesystem root (path.dirname("/") === "/").
|
|
314
|
+
while (true) {
|
|
315
|
+
await fsyncDir(parent);
|
|
316
|
+
if (parent === stop)
|
|
317
|
+
break;
|
|
318
|
+
const next = path.dirname(parent);
|
|
319
|
+
if (next === parent)
|
|
320
|
+
break;
|
|
321
|
+
parent = next;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
filePath(id) {
|
|
325
|
+
this.assertValidId(id);
|
|
326
|
+
const resolved = path.resolve(this.dir, `${id}.md`);
|
|
327
|
+
// Defense in depth: even with a valid-looking id, refuse any path that escapes the board dir.
|
|
328
|
+
const base = path.resolve(this.dir);
|
|
329
|
+
if (resolved !== path.join(base, `${id}.md`) || !resolved.startsWith(base + path.sep)) {
|
|
330
|
+
throw new Error(`invalid board issue id: ${JSON.stringify(id)}`);
|
|
331
|
+
}
|
|
332
|
+
return resolved;
|
|
333
|
+
}
|
|
334
|
+
async issueIds() {
|
|
335
|
+
let entries;
|
|
336
|
+
try {
|
|
337
|
+
entries = await fs.readdir(this.dir);
|
|
338
|
+
}
|
|
339
|
+
catch (err) {
|
|
340
|
+
// A MISSING board directory is a legitimately empty board: return [] so list()/byStatus()/
|
|
341
|
+
// fetchCandidateIssues report no issues. But any OTHER failure (EACCES on a locked-down dir,
|
|
342
|
+
// ENOTDIR when the path points at a file, etc.) means the board is misconfigured or broken,
|
|
343
|
+
// and silently returning [] would make it look idle - hiding the operator action needed.
|
|
344
|
+
// Re-throw with the dir in the message so the runtime poll-loop guard records a poll_error
|
|
345
|
+
// (it catches throws from fetchCandidateIssues, logs, and keeps the daemon alive) instead of
|
|
346
|
+
// swallowing the failure.
|
|
347
|
+
if (err.code === "ENOENT")
|
|
348
|
+
return [];
|
|
349
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
350
|
+
throw new Error(`failed to read board directory ${JSON.stringify(this.dir)}: ${reason}`, {
|
|
351
|
+
cause: err,
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
return (entries
|
|
355
|
+
.filter((f) => f.endsWith(".md"))
|
|
356
|
+
.map((f) => f.slice(0, -3))
|
|
357
|
+
// Keep ONLY canonical board ids (the same shape filePath/assertValidId enforce). Stray
|
|
358
|
+
// markdown files (README.md, notes.md) and files with a different prefix are not board
|
|
359
|
+
// issues, so ignoring them here keeps list()/getByIds()/byStatus() clean AND prevents
|
|
360
|
+
// nextId() from feeding a non-matching stem into boardNumber() (whose MAX_SAFE_INTEGER
|
|
361
|
+
// fallback would otherwise blow up id allocation).
|
|
362
|
+
.filter((id) => this.idPattern.test(id))
|
|
363
|
+
.sort((a, b) => this.boardNumber(a) - this.boardNumber(b)));
|
|
364
|
+
}
|
|
365
|
+
async nextId() {
|
|
366
|
+
let max = 0;
|
|
367
|
+
for (const id of await this.issueIds())
|
|
368
|
+
max = Math.max(max, this.boardNumber(id));
|
|
369
|
+
return `${this.idPrefix}${max + 1}`;
|
|
370
|
+
}
|
|
371
|
+
async read(id) {
|
|
372
|
+
const parsed = await this.parse(id);
|
|
373
|
+
const stat = await fs.stat(this.filePath(id));
|
|
374
|
+
// normalizeIssue requires a stateType. Map known statuses and fall back to "backlog"
|
|
375
|
+
// for custom/free-form board statuses so an unrecognized status never crashes the read.
|
|
376
|
+
const stateType = defaultStateType(parsed.status) ?? "backlog";
|
|
377
|
+
return normalizeIssue({
|
|
378
|
+
id,
|
|
379
|
+
identifier: id,
|
|
380
|
+
title: parsed.title.trim() === "" ? id : parsed.title,
|
|
381
|
+
description: parsed.description === "" ? null : parsed.description,
|
|
382
|
+
state: parsed.status,
|
|
383
|
+
state_type: stateType,
|
|
384
|
+
labels: parsed.labels,
|
|
385
|
+
created_at: stat.birthtime.toISOString(),
|
|
386
|
+
updated_at: stat.mtime.toISOString(),
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
async parse(id) {
|
|
390
|
+
const raw = (await fs.readFile(this.filePath(id), "utf8")).replace(/\r\n/g, "\n");
|
|
391
|
+
const { frontmatter, body } = splitFrontmatter(raw);
|
|
392
|
+
const fm = (frontmatter ? parseYaml(frontmatter) : {});
|
|
393
|
+
const status = typeof fm.status === "string" ? fm.status.trim() : "";
|
|
394
|
+
if (status === "")
|
|
395
|
+
throw new Error(`board issue ${id} is missing required 'status'`);
|
|
396
|
+
const labels = Array.isArray(fm.labels)
|
|
397
|
+
? fm.labels.filter((l) => typeof l === "string")
|
|
398
|
+
: [];
|
|
399
|
+
return { status, labels, ...splitBody(body) };
|
|
400
|
+
}
|
|
401
|
+
render(p) {
|
|
402
|
+
const fm = { status: p.status };
|
|
403
|
+
if (p.labels.length > 0)
|
|
404
|
+
fm.labels = p.labels;
|
|
405
|
+
const sections = [`---\n${stringifyYaml(fm).trimEnd()}\n---`, `# ${p.title}`];
|
|
406
|
+
if (p.description.trim() !== "")
|
|
407
|
+
sections.push(p.description.trim());
|
|
408
|
+
if (p.comments.trim() !== "")
|
|
409
|
+
sections.push(`${COMMENTS_MARKER}\n## Comments\n${p.comments.trim()}`);
|
|
410
|
+
return `${sections.join("\n\n")}\n`;
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Atomic replace: write to a uniquely-named sibling temp file in the SAME directory and
|
|
414
|
+
* fs.rename it over the target. rename is atomic within a filesystem, so a crash mid-write
|
|
415
|
+
* leaves either the prior file or the fully-written new file intact - never a truncated one.
|
|
416
|
+
* The contents are fsync'd before the rename and the directory after it, so the rename cannot
|
|
417
|
+
* expose a name whose data has not yet reached disk (which would otherwise read back empty).
|
|
418
|
+
*/
|
|
419
|
+
async write(id, p) {
|
|
420
|
+
await this.ensureBoardDir();
|
|
421
|
+
const target = this.filePath(id);
|
|
422
|
+
const tmp = `${target}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`;
|
|
423
|
+
try {
|
|
424
|
+
await fs.writeFile(tmp, this.render(p), "utf8");
|
|
425
|
+
await fsyncFile(tmp);
|
|
426
|
+
await fs.rename(tmp, target);
|
|
427
|
+
await fsyncDir(this.dir);
|
|
428
|
+
}
|
|
429
|
+
catch (err) {
|
|
430
|
+
await fs.rm(tmp, { force: true }).catch(() => { });
|
|
431
|
+
throw err;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
/** Reject any id not matching this board's `^<prefix>\d+$` (defends agent-supplied ids). */
|
|
435
|
+
assertValidId(id) {
|
|
436
|
+
if (!this.idPattern.test(id)) {
|
|
437
|
+
throw new Error(`invalid board issue id: ${JSON.stringify(id)} (expected ${this.idPrefix}<n>)`);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Numeric suffix of a canonical id (e.g. "XXX-7" -> 7). Callers pass ids that already matched
|
|
442
|
+
* idPattern, so the slice after the prefix is always digits; the fallback is belt-and-suspenders.
|
|
443
|
+
*/
|
|
444
|
+
boardNumber(id) {
|
|
445
|
+
const n = Number(id.slice(this.idPrefix.length));
|
|
446
|
+
return Number.isInteger(n) ? n : Number.MAX_SAFE_INTEGER;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
function splitFrontmatter(raw) {
|
|
450
|
+
if (!raw.startsWith("---"))
|
|
451
|
+
return { frontmatter: null, body: raw };
|
|
452
|
+
const end = raw.indexOf("\n---", 3);
|
|
453
|
+
if (end === -1)
|
|
454
|
+
return { frontmatter: null, body: raw };
|
|
455
|
+
const frontmatter = raw.slice(raw.indexOf("\n") + 1, end);
|
|
456
|
+
const afterClose = raw.indexOf("\n", end + 1);
|
|
457
|
+
const body = afterClose === -1 ? "" : raw.slice(afterClose + 1);
|
|
458
|
+
return { frontmatter, body };
|
|
459
|
+
}
|
|
460
|
+
function splitBody(body) {
|
|
461
|
+
const markerIdx = body.indexOf(COMMENTS_MARKER);
|
|
462
|
+
const main = markerIdx === -1 ? body : body.slice(0, markerIdx);
|
|
463
|
+
const comments = markerIdx === -1
|
|
464
|
+
? ""
|
|
465
|
+
: body
|
|
466
|
+
.slice(markerIdx + COMMENTS_MARKER.length)
|
|
467
|
+
.replace(/^\n?## Comments\n?/, "")
|
|
468
|
+
.trim();
|
|
469
|
+
const lines = main.split("\n");
|
|
470
|
+
const headingIdx = lines.findIndex((l) => l.startsWith("# "));
|
|
471
|
+
const title = headingIdx === -1 ? "" : lines[headingIdx].slice(2).trim();
|
|
472
|
+
const descLines = headingIdx === -1 ? lines : lines.slice(headingIdx + 1);
|
|
473
|
+
return { title, description: descLines.join("\n").trim(), comments };
|
|
474
|
+
}
|
|
475
|
+
//# sourceMappingURL=boardStore.js.map
|