macro-agent 0.1.0 → 0.1.1
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/.claude/settings.local.json +3 -1
- package/.sudocode/specs.jsonl +4 -0
- package/CLAUDE.md +16 -14
- package/README.md +11 -29
- package/dist/acp/macro-agent.d.ts +15 -0
- package/dist/acp/macro-agent.d.ts.map +1 -1
- package/dist/acp/macro-agent.js +131 -35
- package/dist/acp/macro-agent.js.map +1 -1
- package/dist/acp/types.d.ts +32 -1
- package/dist/acp/types.d.ts.map +1 -1
- package/dist/acp/types.js.map +1 -1
- package/dist/agent/agent-manager.d.ts +65 -1
- package/dist/agent/agent-manager.d.ts.map +1 -1
- package/dist/agent/agent-manager.js +464 -183
- package/dist/agent/agent-manager.js.map +1 -1
- package/dist/agent/types.d.ts +1 -1
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/api/server.d.ts +3 -0
- package/dist/api/server.d.ts.map +1 -1
- package/dist/api/server.js +37 -6
- package/dist/api/server.js.map +1 -1
- package/dist/auth/index.d.ts +2 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +2 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/token.d.ts +41 -0
- package/dist/auth/token.d.ts.map +1 -0
- package/dist/auth/token.js +73 -0
- package/dist/auth/token.js.map +1 -0
- package/dist/cli/acp.d.ts +2 -23
- package/dist/cli/acp.d.ts.map +1 -1
- package/dist/cli/acp.js +127 -61
- package/dist/cli/acp.js.map +1 -1
- package/dist/cli/index.js +147 -15
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp.d.ts +6 -0
- package/dist/cli/mcp.d.ts.map +1 -1
- package/dist/cli/mcp.js +268 -181
- package/dist/cli/mcp.js.map +1 -1
- package/dist/cli/parse-args.d.ts +20 -0
- package/dist/cli/parse-args.d.ts.map +1 -0
- package/dist/cli/parse-args.js +43 -0
- package/dist/cli/parse-args.js.map +1 -0
- package/dist/cli/stable-instance-id.d.ts +8 -0
- package/dist/cli/stable-instance-id.d.ts.map +1 -0
- package/dist/cli/stable-instance-id.js +14 -0
- package/dist/cli/stable-instance-id.js.map +1 -0
- package/dist/config/project-config.d.ts +74 -7
- package/dist/config/project-config.d.ts.map +1 -1
- package/dist/config/project-config.js +123 -20
- package/dist/config/project-config.js.map +1 -1
- package/dist/map/adapter/acp-over-map.d.ts +17 -0
- package/dist/map/adapter/acp-over-map.d.ts.map +1 -1
- package/dist/map/adapter/acp-over-map.js +384 -23
- package/dist/map/adapter/acp-over-map.js.map +1 -1
- package/dist/map/adapter/connection-manager.d.ts.map +1 -1
- package/dist/map/adapter/connection-manager.js +3 -0
- package/dist/map/adapter/connection-manager.js.map +1 -1
- package/dist/map/adapter/event-log.d.ts +87 -0
- package/dist/map/adapter/event-log.d.ts.map +1 -0
- package/dist/map/adapter/event-log.js +122 -0
- package/dist/map/adapter/event-log.js.map +1 -0
- package/dist/map/adapter/event-translator.js +6 -6
- package/dist/map/adapter/event-translator.js.map +1 -1
- package/dist/map/adapter/extensions/agent-lifecycle.d.ts +82 -0
- package/dist/map/adapter/extensions/agent-lifecycle.d.ts.map +1 -0
- package/dist/map/adapter/extensions/agent-lifecycle.js +164 -0
- package/dist/map/adapter/extensions/agent-lifecycle.js.map +1 -0
- package/dist/map/adapter/extensions/index.d.ts +10 -1
- package/dist/map/adapter/extensions/index.d.ts.map +1 -1
- package/dist/map/adapter/extensions/index.js +34 -0
- package/dist/map/adapter/extensions/index.js.map +1 -1
- package/dist/map/adapter/extensions/mcp-bridge.d.ts +57 -0
- package/dist/map/adapter/extensions/mcp-bridge.d.ts.map +1 -0
- package/dist/map/adapter/extensions/mcp-bridge.js +745 -0
- package/dist/map/adapter/extensions/mcp-bridge.js.map +1 -0
- package/dist/map/adapter/extensions/rename.d.ts +29 -0
- package/dist/map/adapter/extensions/rename.d.ts.map +1 -0
- package/dist/map/adapter/extensions/rename.js +49 -0
- package/dist/map/adapter/extensions/rename.js.map +1 -0
- package/dist/map/adapter/extensions/task.d.ts.map +1 -1
- package/dist/map/adapter/extensions/task.js +10 -0
- package/dist/map/adapter/extensions/task.js.map +1 -1
- package/dist/map/adapter/extensions/update-metadata.d.ts +29 -0
- package/dist/map/adapter/extensions/update-metadata.d.ts.map +1 -0
- package/dist/map/adapter/extensions/update-metadata.js +67 -0
- package/dist/map/adapter/extensions/update-metadata.js.map +1 -0
- package/dist/map/adapter/index.d.ts +2 -1
- package/dist/map/adapter/index.d.ts.map +1 -1
- package/dist/map/adapter/index.js +8 -2
- package/dist/map/adapter/index.js.map +1 -1
- package/dist/map/adapter/interface.d.ts +2 -0
- package/dist/map/adapter/interface.d.ts.map +1 -1
- package/dist/map/adapter/map-adapter.d.ts +3 -0
- package/dist/map/adapter/map-adapter.d.ts.map +1 -1
- package/dist/map/adapter/map-adapter.js +258 -35
- package/dist/map/adapter/map-adapter.js.map +1 -1
- package/dist/map/adapter/subscription-manager.d.ts.map +1 -1
- package/dist/map/adapter/subscription-manager.js +5 -1
- package/dist/map/adapter/subscription-manager.js.map +1 -1
- package/dist/map/adapter/types.d.ts +2 -0
- package/dist/map/adapter/types.d.ts.map +1 -1
- package/dist/mcp/map-client.d.ts +39 -0
- package/dist/mcp/map-client.d.ts.map +1 -0
- package/dist/mcp/map-client.js +129 -0
- package/dist/mcp/map-client.js.map +1 -0
- package/dist/mcp/mcp-server.d.ts +14 -0
- package/dist/mcp/mcp-server.d.ts.map +1 -1
- package/dist/mcp/mcp-server.js +113 -85
- package/dist/mcp/mcp-server.js.map +1 -1
- package/dist/mcp/types.d.ts +9 -1
- package/dist/mcp/types.d.ts.map +1 -1
- package/dist/mcp/types.js.map +1 -1
- package/dist/metrics/metrics.js +1 -1
- package/dist/metrics/metrics.js.map +1 -1
- package/dist/roles/capabilities.d.ts +3 -1
- package/dist/roles/capabilities.d.ts.map +1 -1
- package/dist/roles/capabilities.js +17 -7
- package/dist/roles/capabilities.js.map +1 -1
- package/dist/roles/config-loader.d.ts +6 -6
- package/dist/roles/config-loader.d.ts.map +1 -1
- package/dist/roles/config-loader.js +6 -6
- package/dist/roles/config-loader.js.map +1 -1
- package/dist/roles/registry.d.ts +2 -2
- package/dist/roles/registry.js +2 -2
- package/dist/server/combined-server.d.ts +20 -0
- package/dist/server/combined-server.d.ts.map +1 -1
- package/dist/server/combined-server.js +107 -8
- package/dist/server/combined-server.js.map +1 -1
- package/dist/store/event-store.d.ts +2 -1
- package/dist/store/event-store.d.ts.map +1 -1
- package/dist/store/event-store.js +69 -20
- package/dist/store/event-store.js.map +1 -1
- package/dist/store/types/agents.d.ts +18 -0
- package/dist/store/types/agents.d.ts.map +1 -1
- package/dist/store/types/events.d.ts +1 -1
- package/dist/store/types/events.d.ts.map +1 -1
- package/dist/task/backend/index.d.ts +47 -29
- package/dist/task/backend/index.d.ts.map +1 -1
- package/dist/task/backend/index.js +109 -71
- package/dist/task/backend/index.js.map +1 -1
- package/dist/task/backend/memory.d.ts +1 -0
- package/dist/task/backend/memory.d.ts.map +1 -1
- package/dist/task/backend/memory.js +3 -0
- package/dist/task/backend/memory.js.map +1 -1
- package/dist/task/backend/opentasks/backend.d.ts +140 -0
- package/dist/task/backend/opentasks/backend.d.ts.map +1 -0
- package/dist/task/backend/opentasks/backend.js +1023 -0
- package/dist/task/backend/opentasks/backend.js.map +1 -0
- package/dist/task/backend/opentasks/client.d.ts +337 -0
- package/dist/task/backend/opentasks/client.d.ts.map +1 -0
- package/dist/task/backend/opentasks/client.js +225 -0
- package/dist/task/backend/opentasks/client.js.map +1 -0
- package/dist/task/backend/opentasks/daemon-manager.d.ts +89 -0
- package/dist/task/backend/opentasks/daemon-manager.d.ts.map +1 -0
- package/dist/task/backend/opentasks/daemon-manager.js +195 -0
- package/dist/task/backend/opentasks/daemon-manager.js.map +1 -0
- package/dist/task/backend/opentasks/index.d.ts +21 -0
- package/dist/task/backend/opentasks/index.d.ts.map +1 -0
- package/dist/task/backend/opentasks/index.js +21 -0
- package/dist/task/backend/opentasks/index.js.map +1 -0
- package/dist/task/backend/opentasks/mapping.d.ts +48 -0
- package/dist/task/backend/opentasks/mapping.d.ts.map +1 -0
- package/dist/task/backend/opentasks/mapping.js +77 -0
- package/dist/task/backend/opentasks/mapping.js.map +1 -0
- package/dist/task/backend/types.d.ts +33 -53
- package/dist/task/backend/types.d.ts.map +1 -1
- package/dist/task/backend/types.js +7 -11
- package/dist/task/backend/types.js.map +1 -1
- package/dist/task/backend/unified-tool-provider.d.ts +57 -0
- package/dist/task/backend/unified-tool-provider.d.ts.map +1 -0
- package/dist/task/backend/unified-tool-provider.js +623 -0
- package/dist/task/backend/unified-tool-provider.js.map +1 -0
- package/dist/teams/team-loader.d.ts +2 -2
- package/dist/teams/team-loader.js +3 -3
- package/dist/teams/team-loader.js.map +1 -1
- package/dist/teams/team-runtime.d.ts.map +1 -1
- package/dist/teams/team-runtime.js +2 -0
- package/dist/teams/team-runtime.js.map +1 -1
- package/docs/architecture.md +7 -6
- package/docs/configuration.md +26 -62
- package/docs/implementation-details.md +5 -5
- package/docs/implementation-summary.md +17 -17
- package/docs/plan-self-driving-support.md +4 -4
- package/docs/spec-self-driving-support.md +10 -10
- package/docs/team-templates.md +2 -2
- package/docs/teams.md +3 -3
- package/docs/troubleshooting.md +10 -11
- package/package.json +6 -4
- package/src/__tests__/e2e/agent-spawn-visibility.e2e.test.ts +761 -0
- package/src/__tests__/e2e/full-agent-conflict-resolution.e2e.test.ts +2 -2
- package/src/__tests__/e2e/mcp-thin-client-bridge.e2e.test.ts +304 -0
- package/src/__tests__/e2e/mcp-tools-available.e2e.test.ts +324 -0
- package/src/__tests__/e2e/multi-agent.e2e.test.ts +5 -5
- package/src/__tests__/e2e/spawn-session-streaming.e2e.test.ts +563 -0
- package/src/acp/__tests__/integration.test.ts +56 -31
- package/src/acp/__tests__/macro-agent.test.ts +16 -7
- package/src/acp/macro-agent.ts +170 -36
- package/src/acp/types.ts +46 -1
- package/src/agent/__tests__/agent-manager.test.ts +228 -2
- package/src/agent/agent-manager.ts +714 -261
- package/src/agent/types.ts +3 -1
- package/src/api/server.ts +41 -7
- package/src/auth/__tests__/token.test.ts +100 -0
- package/src/auth/index.ts +1 -0
- package/src/auth/token.ts +82 -0
- package/src/cli/__tests__/acp.test.ts +1 -1
- package/src/cli/__tests__/stable-instance-id.test.ts +1 -1
- package/src/cli/acp.ts +130 -72
- package/src/cli/index.ts +120 -14
- package/src/cli/mcp.ts +311 -207
- package/src/cli/parse-args.ts +54 -0
- package/src/cli/stable-instance-id.ts +14 -0
- package/src/config/project-config.ts +190 -27
- package/src/lifecycle/__tests__/cascade-termination.test.ts +1 -1
- package/src/map/adapter/__tests__/acp-over-map-cancel.test.ts +22 -4
- package/src/map/adapter/__tests__/acp-over-map-getmodels.test.ts +355 -0
- package/src/map/adapter/__tests__/acp-over-map-history.test.ts +263 -0
- package/src/map/adapter/__tests__/acp-over-map-persistence.e2e.test.ts +1 -1
- package/src/map/adapter/__tests__/event-broadcast.test.ts +420 -0
- package/src/map/adapter/__tests__/event-log.test.ts +527 -0
- package/src/map/adapter/__tests__/event-translator.test.ts +3 -3
- package/src/map/adapter/__tests__/extensions.test.ts +408 -0
- package/src/map/adapter/__tests__/map-adapter.test.ts +99 -0
- package/src/map/adapter/__tests__/mcp-bridge.test.ts +1187 -0
- package/src/map/adapter/__tests__/multi-client-broadcast.test.ts +711 -0
- package/src/map/adapter/__tests__/websocket-integration.test.ts +218 -0
- package/src/map/adapter/acp-over-map.ts +678 -66
- package/src/map/adapter/connection-manager.ts +3 -0
- package/src/map/adapter/event-log.ts +208 -0
- package/src/map/adapter/event-translator.ts +6 -6
- package/src/map/adapter/extensions/agent-lifecycle.ts +267 -0
- package/src/map/adapter/extensions/index.ts +60 -0
- package/src/map/adapter/extensions/mcp-bridge.ts +995 -0
- package/src/map/adapter/extensions/task.ts +11 -0
- package/src/map/adapter/extensions/update-metadata.ts +126 -0
- package/src/map/adapter/index.ts +28 -0
- package/src/map/adapter/interface.ts +2 -0
- package/src/map/adapter/map-adapter.ts +312 -47
- package/src/map/adapter/subscription-manager.ts +5 -1
- package/src/map/adapter/types.ts +2 -0
- package/src/mcp/__tests__/map-client.test.ts +386 -0
- package/src/mcp/__tests__/mcp-server-thin-client.test.ts +368 -0
- package/src/mcp/__tests__/mcp-server.test.ts +100 -1
- package/src/mcp/map-client.ts +177 -0
- package/src/mcp/mcp-server.ts +191 -100
- package/src/mcp/types.ts +6 -1
- package/src/metrics/metrics.ts +1 -1
- package/src/monitor/__tests__/stale-agent-flow.integration.test.ts +1 -1
- package/src/roles/__tests__/config-loader.test.ts +7 -7
- package/src/roles/capabilities.ts +17 -7
- package/src/roles/config-loader.ts +6 -6
- package/src/roles/registry.ts +2 -2
- package/src/server/__tests__/combined-server.test.ts +94 -21
- package/src/server/combined-server.ts +189 -33
- package/src/steering/__tests__/steering-integration.test.ts +1 -1
- package/src/store/__tests__/event-store.test.ts +196 -1
- package/src/store/__tests__/instance.test.ts +3 -3
- package/src/store/event-store.ts +80 -21
- package/src/store/types/agents.ts +15 -0
- package/src/store/types/events.ts +1 -1
- package/src/task/backend/__tests__/create-task-backend.test.ts +225 -0
- package/src/task/backend/__tests__/e2e/unified-tool-provider-opentasks.e2e.test.ts +524 -0
- package/src/task/backend/__tests__/unified-tool-provider.test.ts +579 -0
- package/src/task/backend/index.ts +156 -106
- package/src/task/backend/memory.ts +4 -0
- package/src/task/backend/opentasks/__tests__/backend.test.ts +968 -0
- package/src/task/backend/opentasks/__tests__/daemon-manager.test.ts +406 -0
- package/src/task/backend/opentasks/__tests__/mapping.test.ts +84 -0
- package/src/task/backend/opentasks/__tests__/opentasks-backend.e2e.test.ts +1338 -0
- package/src/task/backend/opentasks/backend.ts +1323 -0
- package/src/task/backend/opentasks/client.ts +652 -0
- package/src/task/backend/opentasks/daemon-manager.ts +253 -0
- package/src/task/backend/opentasks/index.ts +69 -0
- package/src/task/backend/opentasks/mapping.ts +94 -0
- package/src/task/backend/types.ts +42 -66
- package/src/task/backend/unified-tool-provider.ts +779 -0
- package/src/teams/__tests__/cross-subsystem.integration.test.ts +1 -1
- package/src/teams/team-loader.ts +3 -3
- package/src/teams/team-runtime.ts +2 -0
- package/test_fixtures/README.md +2 -3
- package/test_fixtures/fixtures/index.ts +0 -3
- package/test_fixtures/fixtures/projects/project-with-specs.ts +7 -149
- package/test_fixtures/fixtures/repos/index.ts +1 -3
- package/test_fixtures/fixtures/repos/temp-repo-factory.ts +0 -116
- package/test_fixtures/fixtures/repos/types.ts +0 -11
- package/test_fixtures/harness/__tests__/fixtures.test.ts +10 -102
- package/test_fixtures/harness/__tests__/temp-repo-and-simulator.test.ts +0 -33
- package/test_fixtures/harness/simulator/agent-simulator.ts +4 -4
- package/vitest.config.ts +1 -1
- package/vitest.e2e.config.ts +1 -1
- package/vitest.setup.ts +1 -30
- package/.macro-agent/teams/self-driving/prompts/grinder.md +0 -27
- package/.macro-agent/teams/self-driving/prompts/judge.md +0 -27
- package/.macro-agent/teams/self-driving/prompts/planner.md +0 -33
- package/.macro-agent/teams/self-driving/roles/grinder.yaml +0 -17
- package/.macro-agent/teams/self-driving/roles/judge.yaml +0 -24
- package/.macro-agent/teams/self-driving/roles/planner.yaml +0 -18
- package/.macro-agent/teams/self-driving/team.yaml +0 -103
- package/.macro-agent/teams/structured/prompts/developer.md +0 -26
- package/.macro-agent/teams/structured/prompts/lead.md +0 -25
- package/.macro-agent/teams/structured/prompts/reviewer.md +0 -24
- package/.macro-agent/teams/structured/roles/developer.yaml +0 -12
- package/.macro-agent/teams/structured/roles/lead.yaml +0 -11
- package/.macro-agent/teams/structured/roles/reviewer.yaml +0 -19
- package/.macro-agent/teams/structured/team.yaml +0 -89
- package/docs/sudocode-integration.md +0 -383
- package/src/task/backend/__tests__/backend-parity.test.ts +0 -451
- package/src/task/backend/__tests__/tool-provider-edge-cases.test.ts +0 -430
- package/src/task/backend/__tests__/tool-provider.test.ts +0 -983
- package/src/task/backend/sudocode/__tests__/backend-edge-cases.test.ts +0 -575
- package/src/task/backend/sudocode/__tests__/backend.test.ts +0 -1194
- package/src/task/backend/sudocode/__tests__/client-integration.test.ts +0 -418
- package/src/task/backend/sudocode/__tests__/client.test.ts +0 -345
- package/src/task/backend/sudocode/__tests__/e2e/backend.e2e.test.ts +0 -753
- package/src/task/backend/sudocode/__tests__/e2e/server-client.e2e.test.ts +0 -680
- package/src/task/backend/sudocode/__tests__/e2e-workflow.test.ts +0 -666
- package/src/task/backend/sudocode/__tests__/integration/standalone-client.integration.test.ts +0 -396
- package/src/task/backend/sudocode/__tests__/integration/sudocode-cli.integration.test.ts +0 -328
- package/src/task/backend/sudocode/__tests__/integration/test-utils.ts +0 -175
- package/src/task/backend/sudocode/__tests__/mapping-edge-cases.test.ts +0 -265
- package/src/task/backend/sudocode/__tests__/server-client.test.ts +0 -675
- package/src/task/backend/sudocode/__tests__/sync-policy-edge-cases.test.ts +0 -521
- package/src/task/backend/sudocode/__tests__/sync-policy.test.ts +0 -519
- package/src/task/backend/sudocode/__tests__/tools.test.ts +0 -471
- package/src/task/backend/sudocode/backend.ts +0 -1237
- package/src/task/backend/sudocode/client.ts +0 -515
- package/src/task/backend/sudocode/index.ts +0 -120
- package/src/task/backend/sudocode/mapping.ts +0 -93
- package/src/task/backend/sudocode/server-client.ts +0 -522
- package/src/task/backend/sudocode/standalone-client.ts +0 -623
- package/src/task/backend/sudocode/sync-policy.ts +0 -387
- package/src/task/backend/sudocode/tools.ts +0 -896
- package/src/task/backend/tool-provider.ts +0 -506
- package/test_fixtures/fixtures/sudocode/index.ts +0 -29
- package/test_fixtures/fixtures/sudocode/issues.ts +0 -185
- package/test_fixtures/fixtures/sudocode/specs.ts +0 -159
|
@@ -0,0 +1,652 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenTasks Client Interface
|
|
3
|
+
*
|
|
4
|
+
* Defines the client interface for communicating with the OpenTasks daemon.
|
|
5
|
+
* This abstracts over the IPC transport so the backend doesn't depend on
|
|
6
|
+
* opentasks internals.
|
|
7
|
+
*
|
|
8
|
+
* @module task/backend/opentasks/client
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { OpenTasksClient as OTClient } from "opentasks";
|
|
12
|
+
|
|
13
|
+
// =============================================================================
|
|
14
|
+
// OpenTasks Data Types (mirrored from opentasks schema)
|
|
15
|
+
// =============================================================================
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* OpenTasks issue node.
|
|
19
|
+
* Represents an actionable work item in the OpenTasks graph.
|
|
20
|
+
*/
|
|
21
|
+
export interface OpenTasksIssue {
|
|
22
|
+
id: string;
|
|
23
|
+
uuid: string;
|
|
24
|
+
type: "task";
|
|
25
|
+
title: string;
|
|
26
|
+
content?: string;
|
|
27
|
+
status: string;
|
|
28
|
+
assignee?: string;
|
|
29
|
+
closed_at?: string;
|
|
30
|
+
priority?: number;
|
|
31
|
+
tags?: string[];
|
|
32
|
+
parent_id?: string;
|
|
33
|
+
created_at: string;
|
|
34
|
+
updated_at: string;
|
|
35
|
+
claimed_by?: string;
|
|
36
|
+
claimed_at?: string;
|
|
37
|
+
lock_until?: string;
|
|
38
|
+
archived?: boolean;
|
|
39
|
+
archived_at?: string;
|
|
40
|
+
metadata?: Record<string, unknown>;
|
|
41
|
+
source?: string;
|
|
42
|
+
branch?: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* OpenTasks edge (relationship between nodes).
|
|
47
|
+
*/
|
|
48
|
+
export interface OpenTasksEdge {
|
|
49
|
+
id: string;
|
|
50
|
+
uuid: string;
|
|
51
|
+
from_id: string;
|
|
52
|
+
to_id: string;
|
|
53
|
+
type: string;
|
|
54
|
+
created_at: string;
|
|
55
|
+
created_by?: string;
|
|
56
|
+
metadata?: Record<string, unknown>;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Reduced node summary from queries.
|
|
61
|
+
*/
|
|
62
|
+
export interface OpenTasksNodeSummary {
|
|
63
|
+
id: string;
|
|
64
|
+
type: string;
|
|
65
|
+
title: string;
|
|
66
|
+
status?: string;
|
|
67
|
+
priority?: number;
|
|
68
|
+
archived: boolean;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// =============================================================================
|
|
72
|
+
// Client Configuration
|
|
73
|
+
// =============================================================================
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Configuration for the OpenTasks client
|
|
77
|
+
*/
|
|
78
|
+
export interface OpenTasksClientConfig {
|
|
79
|
+
/** Path to the daemon Unix socket */
|
|
80
|
+
socketPath?: string;
|
|
81
|
+
|
|
82
|
+
/** Auto-connect on first request (default: true) */
|
|
83
|
+
autoConnect?: boolean;
|
|
84
|
+
|
|
85
|
+
/** Request timeout in milliseconds (default: 30000) */
|
|
86
|
+
timeout?: number;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// =============================================================================
|
|
90
|
+
// Input Types
|
|
91
|
+
// =============================================================================
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Input for creating a new issue in OpenTasks
|
|
95
|
+
*/
|
|
96
|
+
export interface CreateIssueInput {
|
|
97
|
+
title: string;
|
|
98
|
+
content?: string;
|
|
99
|
+
status?: string;
|
|
100
|
+
assignee?: string;
|
|
101
|
+
priority?: number;
|
|
102
|
+
tags?: string[];
|
|
103
|
+
parent_id?: string;
|
|
104
|
+
metadata?: Record<string, unknown>;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Input for updating an issue in OpenTasks
|
|
109
|
+
*/
|
|
110
|
+
export interface UpdateIssueInput {
|
|
111
|
+
title?: string;
|
|
112
|
+
content?: string;
|
|
113
|
+
status?: string;
|
|
114
|
+
assignee?: string | null;
|
|
115
|
+
priority?: number;
|
|
116
|
+
tags?: string[];
|
|
117
|
+
parent_id?: string | null;
|
|
118
|
+
archived?: boolean;
|
|
119
|
+
metadata?: Record<string, unknown>;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// =============================================================================
|
|
123
|
+
// Task Lifecycle Types (mirrors opentasks tools.task interface)
|
|
124
|
+
// =============================================================================
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Semantic task actions supported by TaskManageable providers
|
|
128
|
+
*/
|
|
129
|
+
export type TaskAction = "start" | "complete" | "block" | "reopen" | "close";
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Parameters for the tools.task IPC method.
|
|
133
|
+
* Exactly one operation must be specified.
|
|
134
|
+
*/
|
|
135
|
+
export interface TaskParams {
|
|
136
|
+
/** Transition a task's status using a semantic action */
|
|
137
|
+
transition?: {
|
|
138
|
+
/** Task ID or provider URI */
|
|
139
|
+
id: string;
|
|
140
|
+
/** Semantic action */
|
|
141
|
+
action: TaskAction;
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
/** Get tasks ready to work on (federated across TaskManageable providers) */
|
|
145
|
+
ready?: {
|
|
146
|
+
/** Only query these providers (by name). Omit to query all. */
|
|
147
|
+
providers?: string[];
|
|
148
|
+
/** Maximum results */
|
|
149
|
+
limit?: number;
|
|
150
|
+
/** Filter by tags */
|
|
151
|
+
tags?: string[];
|
|
152
|
+
/** Filter by minimum priority */
|
|
153
|
+
priority?: number;
|
|
154
|
+
/** Filter by assignee */
|
|
155
|
+
assignee?: string;
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
/** Assign a task to an owner */
|
|
159
|
+
assign?: {
|
|
160
|
+
/** Task ID or provider URI */
|
|
161
|
+
id: string;
|
|
162
|
+
/** Assignee identifier */
|
|
163
|
+
assignee: string;
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
/** Get valid next actions for a task in its current state */
|
|
167
|
+
validActions?: {
|
|
168
|
+
/** Task ID or provider URI */
|
|
169
|
+
id: string;
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
/** Return full objects instead of summaries (default: false) */
|
|
173
|
+
verbose?: boolean;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Result from tools.task operations
|
|
178
|
+
*/
|
|
179
|
+
export interface TaskResult {
|
|
180
|
+
/** Whether the operation succeeded */
|
|
181
|
+
success: boolean;
|
|
182
|
+
/** Result data (shape depends on operation) */
|
|
183
|
+
data?: TaskTransitionData | TaskReadyData | TaskAssignData | TaskValidActionsData;
|
|
184
|
+
/** Error message if operation failed */
|
|
185
|
+
error?: string;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export interface TaskTransitionData {
|
|
189
|
+
type: "transition";
|
|
190
|
+
node: TaskNodeSummary;
|
|
191
|
+
provider: string;
|
|
192
|
+
action: string;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export interface TaskReadyData {
|
|
196
|
+
type: "ready";
|
|
197
|
+
items: TaskNodeSummary[];
|
|
198
|
+
total: number;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export interface TaskAssignData {
|
|
202
|
+
type: "assign";
|
|
203
|
+
node: TaskNodeSummary;
|
|
204
|
+
provider: string;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export interface TaskValidActionsData {
|
|
208
|
+
type: "validActions";
|
|
209
|
+
actions: string[];
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Node summary returned by task operations
|
|
214
|
+
*/
|
|
215
|
+
export interface TaskNodeSummary {
|
|
216
|
+
id: string;
|
|
217
|
+
type: string;
|
|
218
|
+
title: string;
|
|
219
|
+
status?: string;
|
|
220
|
+
priority?: number;
|
|
221
|
+
archived: boolean;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Provider summary from provider.list
|
|
226
|
+
*/
|
|
227
|
+
export interface ProviderSummary {
|
|
228
|
+
name: string;
|
|
229
|
+
schemes: string[];
|
|
230
|
+
capabilities: Record<string, boolean>;
|
|
231
|
+
isDefault: boolean;
|
|
232
|
+
taskCapabilities?: {
|
|
233
|
+
actions: TaskAction[];
|
|
234
|
+
supportsAssignment: boolean;
|
|
235
|
+
supportsReadyQuery: boolean;
|
|
236
|
+
statusModel: string[];
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// =============================================================================
|
|
241
|
+
// Event Types
|
|
242
|
+
// =============================================================================
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Issue change event types
|
|
246
|
+
*/
|
|
247
|
+
export type IssueChangeType =
|
|
248
|
+
| "created"
|
|
249
|
+
| "updated"
|
|
250
|
+
| "deleted"
|
|
251
|
+
| "status_changed";
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Issue change event
|
|
255
|
+
*/
|
|
256
|
+
export interface IssueChangeEvent {
|
|
257
|
+
type: IssueChangeType;
|
|
258
|
+
issueId: string;
|
|
259
|
+
issue?: OpenTasksIssue;
|
|
260
|
+
previousIssue?: OpenTasksIssue;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Callback for issue change events
|
|
265
|
+
*/
|
|
266
|
+
export type IssueChangeCallback = (event: IssueChangeEvent) => void;
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Unsubscribe function
|
|
270
|
+
*/
|
|
271
|
+
export type ClientUnsubscribe = () => void;
|
|
272
|
+
|
|
273
|
+
// =============================================================================
|
|
274
|
+
// OpenTasksClient Interface
|
|
275
|
+
// =============================================================================
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Client interface for interacting with the OpenTasks daemon.
|
|
279
|
+
*
|
|
280
|
+
* This defines only the operations needed by the macro-agent task backend.
|
|
281
|
+
* It can be implemented by:
|
|
282
|
+
* - The opentasks package's OpenTasksClient (when available)
|
|
283
|
+
* - A custom IPC client
|
|
284
|
+
* - A mock for testing
|
|
285
|
+
*/
|
|
286
|
+
export interface OpenTasksClient {
|
|
287
|
+
// ─── Issue CRUD ──────────────────────────────────────────────
|
|
288
|
+
|
|
289
|
+
/** Create a new issue */
|
|
290
|
+
createIssue(input: CreateIssueInput): Promise<OpenTasksIssue>;
|
|
291
|
+
|
|
292
|
+
/** Get an issue by ID */
|
|
293
|
+
getIssue(id: string): Promise<OpenTasksIssue | null>;
|
|
294
|
+
|
|
295
|
+
/** Update an issue */
|
|
296
|
+
updateIssue(id: string, updates: UpdateIssueInput): Promise<OpenTasksIssue>;
|
|
297
|
+
|
|
298
|
+
/** Delete an issue (soft delete / archive) */
|
|
299
|
+
deleteIssue(id: string): Promise<void>;
|
|
300
|
+
|
|
301
|
+
/** List issues with optional filters */
|
|
302
|
+
listIssues(filter?: {
|
|
303
|
+
status?: string | string[];
|
|
304
|
+
assignee?: string;
|
|
305
|
+
tags?: string[];
|
|
306
|
+
parent_id?: string;
|
|
307
|
+
archived?: boolean;
|
|
308
|
+
limit?: number;
|
|
309
|
+
}): Promise<OpenTasksIssue[]>;
|
|
310
|
+
|
|
311
|
+
// ─── Ready / Claimable Queries ───────────────────────────────
|
|
312
|
+
|
|
313
|
+
/** Get issues that are ready to work on (no blocking dependencies) */
|
|
314
|
+
getReadyIssues(options?: {
|
|
315
|
+
tags?: string[];
|
|
316
|
+
assignee?: string;
|
|
317
|
+
limit?: number;
|
|
318
|
+
}): Promise<OpenTasksNodeSummary[]>;
|
|
319
|
+
|
|
320
|
+
// ─── Relationship Operations ─────────────────────────────────
|
|
321
|
+
|
|
322
|
+
/** Create an edge between two nodes */
|
|
323
|
+
createEdge(
|
|
324
|
+
fromId: string,
|
|
325
|
+
toId: string,
|
|
326
|
+
type: string
|
|
327
|
+
): Promise<OpenTasksEdge>;
|
|
328
|
+
|
|
329
|
+
/** Remove an edge between two nodes */
|
|
330
|
+
removeEdge(
|
|
331
|
+
fromId: string,
|
|
332
|
+
toId: string,
|
|
333
|
+
type: string
|
|
334
|
+
): Promise<void>;
|
|
335
|
+
|
|
336
|
+
/** Get nodes that block the given node */
|
|
337
|
+
getBlockers(nodeId: string): Promise<OpenTasksNodeSummary[]>;
|
|
338
|
+
|
|
339
|
+
/** Get nodes that the given node blocks */
|
|
340
|
+
getBlocking(nodeId: string): Promise<OpenTasksNodeSummary[]>;
|
|
341
|
+
|
|
342
|
+
// ─── Task Lifecycle (provider-agnostic via tools.task) ──────
|
|
343
|
+
|
|
344
|
+
/** Execute a task lifecycle operation (tools.task IPC) */
|
|
345
|
+
task(params: TaskParams): Promise<TaskResult>;
|
|
346
|
+
|
|
347
|
+
/** Transition a task's status using a semantic action */
|
|
348
|
+
taskTransition(id: string, action: TaskAction): Promise<TaskResult>;
|
|
349
|
+
|
|
350
|
+
/** Get tasks ready to work on across all TaskManageable providers */
|
|
351
|
+
taskReady(options?: TaskParams["ready"]): Promise<TaskResult>;
|
|
352
|
+
|
|
353
|
+
/** Assign a task to an owner */
|
|
354
|
+
taskAssign(id: string, assignee: string): Promise<TaskResult>;
|
|
355
|
+
|
|
356
|
+
/** Get valid next actions for a task in its current state */
|
|
357
|
+
taskValidActions(id: string): Promise<TaskResult>;
|
|
358
|
+
|
|
359
|
+
// ─── Provider Introspection ───────────────────────────────
|
|
360
|
+
|
|
361
|
+
/** List all registered providers and their capabilities */
|
|
362
|
+
listProviders(): Promise<ProviderSummary[]>;
|
|
363
|
+
|
|
364
|
+
// ─── Lifecycle ───────────────────────────────────────────────
|
|
365
|
+
|
|
366
|
+
/** Check if the client is connected */
|
|
367
|
+
isConnected(): boolean;
|
|
368
|
+
|
|
369
|
+
/** Connect to the daemon */
|
|
370
|
+
connect(): Promise<void>;
|
|
371
|
+
|
|
372
|
+
/** Disconnect from the daemon */
|
|
373
|
+
disconnect(): void;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// =============================================================================
|
|
377
|
+
// IPC-based Client Implementation
|
|
378
|
+
// =============================================================================
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Default OpenTasks client implementation using the opentasks package.
|
|
382
|
+
*
|
|
383
|
+
* Wraps the opentasks client library to implement the OpenTasksClient interface.
|
|
384
|
+
*/
|
|
385
|
+
export class IPCOpenTasksClient implements OpenTasksClient {
|
|
386
|
+
private client: any = null;
|
|
387
|
+
private readonly config: OpenTasksClientConfig;
|
|
388
|
+
|
|
389
|
+
constructor(config?: OpenTasksClientConfig) {
|
|
390
|
+
this.config = {
|
|
391
|
+
autoConnect: true,
|
|
392
|
+
timeout: 30000,
|
|
393
|
+
...config,
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
async connect(): Promise<void> {
|
|
398
|
+
if (this.client?.connected) return;
|
|
399
|
+
|
|
400
|
+
try {
|
|
401
|
+
this.client = new OTClient({
|
|
402
|
+
socketPath: this.config.socketPath,
|
|
403
|
+
autoConnect: false,
|
|
404
|
+
timeout: this.config.timeout,
|
|
405
|
+
});
|
|
406
|
+
await this.client.connect();
|
|
407
|
+
} catch (error: any) {
|
|
408
|
+
throw new OpenTasksClientError(
|
|
409
|
+
`Failed to connect to OpenTasks daemon: ${error.message}`,
|
|
410
|
+
"CONNECTION_FAILED"
|
|
411
|
+
);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
disconnect(): void {
|
|
416
|
+
if (this.client) {
|
|
417
|
+
this.client.disconnect();
|
|
418
|
+
this.client = null;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
isConnected(): boolean {
|
|
423
|
+
return this.client?.connected ?? false;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
private async ensureConnected(): Promise<void> {
|
|
427
|
+
if (this.isConnected()) return;
|
|
428
|
+
if (this.config.autoConnect) {
|
|
429
|
+
await this.connect();
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
throw new OpenTasksClientError(
|
|
433
|
+
"Not connected to OpenTasks daemon",
|
|
434
|
+
"NOT_CONNECTED"
|
|
435
|
+
);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
async createIssue(input: CreateIssueInput): Promise<OpenTasksIssue> {
|
|
439
|
+
await this.ensureConnected();
|
|
440
|
+
return this.client.createNode({
|
|
441
|
+
type: "task",
|
|
442
|
+
title: input.title,
|
|
443
|
+
content: input.content,
|
|
444
|
+
status: input.status ?? "open",
|
|
445
|
+
assignee: input.assignee,
|
|
446
|
+
priority: input.priority,
|
|
447
|
+
tags: input.tags,
|
|
448
|
+
parent_id: input.parent_id,
|
|
449
|
+
metadata: input.metadata,
|
|
450
|
+
}) as Promise<OpenTasksIssue>;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
async getIssue(id: string): Promise<OpenTasksIssue | null> {
|
|
454
|
+
await this.ensureConnected();
|
|
455
|
+
try {
|
|
456
|
+
const node = await this.client.getNode(id);
|
|
457
|
+
if (!node || (node as any).type !== "task") return null;
|
|
458
|
+
return node as OpenTasksIssue;
|
|
459
|
+
} catch {
|
|
460
|
+
return null;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
async updateIssue(
|
|
465
|
+
id: string,
|
|
466
|
+
updates: UpdateIssueInput
|
|
467
|
+
): Promise<OpenTasksIssue> {
|
|
468
|
+
await this.ensureConnected();
|
|
469
|
+
return this.client.updateNode(id, updates) as Promise<OpenTasksIssue>;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
async deleteIssue(id: string): Promise<void> {
|
|
473
|
+
await this.ensureConnected();
|
|
474
|
+
await this.client.deleteNode(id, { hard: false });
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
async listIssues(filter?: {
|
|
478
|
+
status?: string | string[];
|
|
479
|
+
assignee?: string;
|
|
480
|
+
tags?: string[];
|
|
481
|
+
parent_id?: string;
|
|
482
|
+
archived?: boolean;
|
|
483
|
+
limit?: number;
|
|
484
|
+
}): Promise<OpenTasksIssue[]> {
|
|
485
|
+
await this.ensureConnected();
|
|
486
|
+
const result = await this.client.query({
|
|
487
|
+
nodes: {
|
|
488
|
+
type: "task",
|
|
489
|
+
status: filter?.status,
|
|
490
|
+
assignee: filter?.assignee,
|
|
491
|
+
tags: filter?.tags,
|
|
492
|
+
parent_id: filter?.parent_id,
|
|
493
|
+
archived: filter?.archived ?? false,
|
|
494
|
+
limit: filter?.limit ?? 100,
|
|
495
|
+
},
|
|
496
|
+
verbose: true,
|
|
497
|
+
});
|
|
498
|
+
return (result.items ?? []) as OpenTasksIssue[];
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
async getReadyIssues(options?: {
|
|
502
|
+
tags?: string[];
|
|
503
|
+
assignee?: string;
|
|
504
|
+
limit?: number;
|
|
505
|
+
}): Promise<OpenTasksNodeSummary[]> {
|
|
506
|
+
await this.ensureConnected();
|
|
507
|
+
const result = await this.client.query({
|
|
508
|
+
ready: {
|
|
509
|
+
tags: options?.tags,
|
|
510
|
+
assignee: options?.assignee,
|
|
511
|
+
limit: options?.limit,
|
|
512
|
+
},
|
|
513
|
+
});
|
|
514
|
+
return (result.items ?? []) as OpenTasksNodeSummary[];
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
async createEdge(
|
|
518
|
+
fromId: string,
|
|
519
|
+
toId: string,
|
|
520
|
+
type: string
|
|
521
|
+
): Promise<OpenTasksEdge> {
|
|
522
|
+
await this.ensureConnected();
|
|
523
|
+
const result = await this.client.link({
|
|
524
|
+
fromId,
|
|
525
|
+
toId,
|
|
526
|
+
type,
|
|
527
|
+
});
|
|
528
|
+
return {
|
|
529
|
+
id: result.edgeId ?? "",
|
|
530
|
+
uuid: "",
|
|
531
|
+
from_id: fromId,
|
|
532
|
+
to_id: toId,
|
|
533
|
+
type,
|
|
534
|
+
created_at: new Date().toISOString(),
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
async removeEdge(
|
|
539
|
+
fromId: string,
|
|
540
|
+
toId: string,
|
|
541
|
+
type: string
|
|
542
|
+
): Promise<void> {
|
|
543
|
+
await this.ensureConnected();
|
|
544
|
+
await this.client.link({
|
|
545
|
+
fromId,
|
|
546
|
+
toId,
|
|
547
|
+
type,
|
|
548
|
+
remove: true,
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
async getBlockers(nodeId: string): Promise<OpenTasksNodeSummary[]> {
|
|
553
|
+
await this.ensureConnected();
|
|
554
|
+
const result = await this.client.query({
|
|
555
|
+
blockers: {
|
|
556
|
+
nodeId,
|
|
557
|
+
activeOnly: true,
|
|
558
|
+
},
|
|
559
|
+
});
|
|
560
|
+
return (result.items ?? []) as OpenTasksNodeSummary[];
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
async getBlocking(nodeId: string): Promise<OpenTasksNodeSummary[]> {
|
|
564
|
+
await this.ensureConnected();
|
|
565
|
+
const result = await this.client.query({
|
|
566
|
+
blocking: {
|
|
567
|
+
nodeId,
|
|
568
|
+
activeOnly: true,
|
|
569
|
+
},
|
|
570
|
+
});
|
|
571
|
+
return (result.items ?? []) as OpenTasksNodeSummary[];
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
// ─── Task Lifecycle (tools.task) ──────────────────────────────
|
|
575
|
+
|
|
576
|
+
async task(params: TaskParams): Promise<TaskResult> {
|
|
577
|
+
await this.ensureConnected();
|
|
578
|
+
return this.client.call("tools.task", params) as Promise<TaskResult>;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
async taskTransition(id: string, action: TaskAction): Promise<TaskResult> {
|
|
582
|
+
return this.task({ transition: { id, action } });
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
async taskReady(options?: TaskParams["ready"]): Promise<TaskResult> {
|
|
586
|
+
return this.task({ ready: options ?? {} });
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
async taskAssign(id: string, assignee: string): Promise<TaskResult> {
|
|
590
|
+
return this.task({ assign: { id, assignee } });
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
async taskValidActions(id: string): Promise<TaskResult> {
|
|
594
|
+
return this.task({ validActions: { id } });
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
// ─── Provider Introspection ─────────────────────────────────
|
|
598
|
+
|
|
599
|
+
async listProviders(): Promise<ProviderSummary[]> {
|
|
600
|
+
await this.ensureConnected();
|
|
601
|
+
const result = await this.client.call("provider.list", {}) as {
|
|
602
|
+
providers: ProviderSummary[];
|
|
603
|
+
};
|
|
604
|
+
return result.providers ?? [];
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
// ─── Generic IPC Call ──────────────────────────────────────
|
|
608
|
+
|
|
609
|
+
async call(method: string, params: Record<string, unknown>): Promise<unknown> {
|
|
610
|
+
await this.ensureConnected();
|
|
611
|
+
return this.client.call(method, params);
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
// =============================================================================
|
|
616
|
+
// Error Types
|
|
617
|
+
// =============================================================================
|
|
618
|
+
|
|
619
|
+
/**
|
|
620
|
+
* Error thrown by OpenTasks client operations
|
|
621
|
+
*/
|
|
622
|
+
export class OpenTasksClientError extends Error {
|
|
623
|
+
constructor(
|
|
624
|
+
message: string,
|
|
625
|
+
public readonly code:
|
|
626
|
+
| "NOT_CONNECTED"
|
|
627
|
+
| "CONNECTION_FAILED"
|
|
628
|
+
| "REQUEST_FAILED"
|
|
629
|
+
| "NOT_FOUND"
|
|
630
|
+
) {
|
|
631
|
+
super(message);
|
|
632
|
+
this.name = "OpenTasksClientError";
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
// =============================================================================
|
|
637
|
+
// Factory
|
|
638
|
+
// =============================================================================
|
|
639
|
+
|
|
640
|
+
/**
|
|
641
|
+
* Create an OpenTasks client.
|
|
642
|
+
*
|
|
643
|
+
* @param config - Client configuration
|
|
644
|
+
* @returns An OpenTasksClient instance
|
|
645
|
+
*/
|
|
646
|
+
export async function createOpenTasksClient(
|
|
647
|
+
config?: OpenTasksClientConfig
|
|
648
|
+
): Promise<OpenTasksClient> {
|
|
649
|
+
const client = new IPCOpenTasksClient(config);
|
|
650
|
+
await client.connect();
|
|
651
|
+
return client;
|
|
652
|
+
}
|