chainlesschain 0.37.9 → 0.37.11
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/README.md +309 -19
- package/bin/chainlesschain.js +4 -0
- package/package.json +1 -1
- package/src/commands/a2a.js +374 -0
- package/src/commands/audit.js +286 -0
- package/src/commands/auth.js +387 -0
- package/src/commands/bi.js +240 -0
- package/src/commands/browse.js +184 -0
- package/src/commands/cowork.js +317 -0
- package/src/commands/did.js +376 -0
- package/src/commands/economy.js +375 -0
- package/src/commands/encrypt.js +233 -0
- package/src/commands/evolution.js +398 -0
- package/src/commands/export.js +125 -0
- package/src/commands/git.js +215 -0
- package/src/commands/hmemory.js +273 -0
- package/src/commands/hook.js +260 -0
- package/src/commands/import.js +259 -0
- package/src/commands/init.js +184 -0
- package/src/commands/instinct.js +202 -0
- package/src/commands/llm.js +155 -4
- package/src/commands/lowcode.js +320 -0
- package/src/commands/mcp.js +302 -0
- package/src/commands/memory.js +282 -0
- package/src/commands/note.js +187 -0
- package/src/commands/org.js +505 -0
- package/src/commands/p2p.js +274 -0
- package/src/commands/plugin.js +451 -0
- package/src/commands/sandbox.js +366 -0
- package/src/commands/search.js +237 -0
- package/src/commands/session.js +238 -0
- package/src/commands/skill.js +254 -201
- package/src/commands/sync.js +249 -0
- package/src/commands/tokens.js +214 -0
- package/src/commands/wallet.js +416 -0
- package/src/commands/workflow.js +359 -0
- package/src/commands/zkp.js +277 -0
- package/src/index.js +93 -1
- package/src/lib/a2a-protocol.js +371 -0
- package/src/lib/agent-coordinator.js +273 -0
- package/src/lib/agent-economy.js +369 -0
- package/src/lib/app-builder.js +377 -0
- package/src/lib/audit-logger.js +364 -0
- package/src/lib/bi-engine.js +299 -0
- package/src/lib/bm25-search.js +322 -0
- package/src/lib/browser-automation.js +216 -0
- package/src/lib/cowork/ab-comparator-cli.js +180 -0
- package/src/lib/cowork/code-knowledge-graph-cli.js +232 -0
- package/src/lib/cowork/debate-review-cli.js +144 -0
- package/src/lib/cowork/decision-kb-cli.js +153 -0
- package/src/lib/cowork/project-style-analyzer-cli.js +168 -0
- package/src/lib/cowork-adapter.js +106 -0
- package/src/lib/crypto-manager.js +246 -0
- package/src/lib/did-manager.js +270 -0
- package/src/lib/ensure-utf8.js +59 -0
- package/src/lib/evolution-system.js +508 -0
- package/src/lib/git-integration.js +220 -0
- package/src/lib/hierarchical-memory.js +471 -0
- package/src/lib/hook-manager.js +387 -0
- package/src/lib/instinct-manager.js +190 -0
- package/src/lib/knowledge-exporter.js +302 -0
- package/src/lib/knowledge-importer.js +293 -0
- package/src/lib/llm-providers.js +325 -0
- package/src/lib/mcp-client.js +413 -0
- package/src/lib/memory-manager.js +211 -0
- package/src/lib/note-versioning.js +244 -0
- package/src/lib/org-manager.js +424 -0
- package/src/lib/p2p-manager.js +317 -0
- package/src/lib/pdf-parser.js +96 -0
- package/src/lib/permission-engine.js +374 -0
- package/src/lib/plan-mode.js +333 -0
- package/src/lib/plugin-manager.js +430 -0
- package/src/lib/project-detector.js +53 -0
- package/src/lib/response-cache.js +156 -0
- package/src/lib/sandbox-v2.js +503 -0
- package/src/lib/service-container.js +183 -0
- package/src/lib/session-manager.js +189 -0
- package/src/lib/skill-loader.js +274 -0
- package/src/lib/sync-manager.js +347 -0
- package/src/lib/token-tracker.js +200 -0
- package/src/lib/wallet-manager.js +348 -0
- package/src/lib/workflow-engine.js +503 -0
- package/src/lib/zkp-engine.js +241 -0
- package/src/repl/agent-repl.js +259 -124
package/src/index.js
CHANGED
|
@@ -15,6 +15,45 @@ import { registerAskCommand } from "./commands/ask.js";
|
|
|
15
15
|
import { registerLlmCommand } from "./commands/llm.js";
|
|
16
16
|
import { registerAgentCommand } from "./commands/agent.js";
|
|
17
17
|
import { registerSkillCommand } from "./commands/skill.js";
|
|
18
|
+
import { registerSearchCommand } from "./commands/search.js";
|
|
19
|
+
import { registerTokensCommand } from "./commands/tokens.js";
|
|
20
|
+
import { registerMemoryCommand } from "./commands/memory.js";
|
|
21
|
+
import { registerSessionCommand } from "./commands/session.js";
|
|
22
|
+
import { registerImportCommand } from "./commands/import.js";
|
|
23
|
+
import { registerExportCommand } from "./commands/export.js";
|
|
24
|
+
import { registerGitCommand } from "./commands/git.js";
|
|
25
|
+
import { registerMcpCommand } from "./commands/mcp.js";
|
|
26
|
+
import { registerBrowseCommand } from "./commands/browse.js";
|
|
27
|
+
import { registerInstinctCommand } from "./commands/instinct.js";
|
|
28
|
+
import { registerDidCommand } from "./commands/did.js";
|
|
29
|
+
import { registerEncryptCommand } from "./commands/encrypt.js";
|
|
30
|
+
import { registerAuthCommand } from "./commands/auth.js";
|
|
31
|
+
import { registerAuditCommand } from "./commands/audit.js";
|
|
32
|
+
import { registerP2pCommand } from "./commands/p2p.js";
|
|
33
|
+
import { registerSyncCommand } from "./commands/sync.js";
|
|
34
|
+
import { registerWalletCommand } from "./commands/wallet.js";
|
|
35
|
+
import { registerOrgCommand } from "./commands/org.js";
|
|
36
|
+
import { registerPluginCommand } from "./commands/plugin.js";
|
|
37
|
+
import { registerInitCommand } from "./commands/init.js";
|
|
38
|
+
import { registerCoworkCommand } from "./commands/cowork.js";
|
|
39
|
+
|
|
40
|
+
// Phase 6: Advanced AI & Hooks
|
|
41
|
+
import { registerHookCommand } from "./commands/hook.js";
|
|
42
|
+
import { registerWorkflowCommand } from "./commands/workflow.js";
|
|
43
|
+
import { registerHmemoryCommand } from "./commands/hmemory.js";
|
|
44
|
+
import { registerA2aCommand } from "./commands/a2a.js";
|
|
45
|
+
|
|
46
|
+
// Phase 7: Security & Evolution
|
|
47
|
+
import { registerSandboxCommand } from "./commands/sandbox.js";
|
|
48
|
+
import { registerEvolutionCommand } from "./commands/evolution.js";
|
|
49
|
+
|
|
50
|
+
// Phase 8: Blockchain & Enterprise
|
|
51
|
+
import { registerEconomyCommand } from "./commands/economy.js";
|
|
52
|
+
import { registerZkpCommand } from "./commands/zkp.js";
|
|
53
|
+
import { registerBiCommand } from "./commands/bi.js";
|
|
54
|
+
|
|
55
|
+
// Phase 9: Low-Code & Multi-Agent
|
|
56
|
+
import { registerLowcodeCommand } from "./commands/lowcode.js";
|
|
18
57
|
|
|
19
58
|
export function createProgram() {
|
|
20
59
|
const program = new Command();
|
|
@@ -28,6 +67,9 @@ export function createProgram() {
|
|
|
28
67
|
.option("--verbose", "Enable verbose output")
|
|
29
68
|
.option("--quiet", "Suppress non-essential output");
|
|
30
69
|
|
|
70
|
+
// Project initialization
|
|
71
|
+
registerInitCommand(program);
|
|
72
|
+
|
|
31
73
|
// Existing commands
|
|
32
74
|
registerSetupCommand(program);
|
|
33
75
|
registerStartCommand(program);
|
|
@@ -38,7 +80,7 @@ export function createProgram() {
|
|
|
38
80
|
registerUpdateCommand(program);
|
|
39
81
|
registerDoctorCommand(program);
|
|
40
82
|
|
|
41
|
-
//
|
|
83
|
+
// Headless commands
|
|
42
84
|
registerDbCommand(program);
|
|
43
85
|
registerNoteCommand(program);
|
|
44
86
|
registerChatCommand(program);
|
|
@@ -47,5 +89,55 @@ export function createProgram() {
|
|
|
47
89
|
registerAgentCommand(program);
|
|
48
90
|
registerSkillCommand(program);
|
|
49
91
|
|
|
92
|
+
// Phase 1: AI intelligence layer
|
|
93
|
+
registerSearchCommand(program);
|
|
94
|
+
registerTokensCommand(program);
|
|
95
|
+
registerMemoryCommand(program);
|
|
96
|
+
registerSessionCommand(program);
|
|
97
|
+
|
|
98
|
+
// Phase 2: Knowledge & content management
|
|
99
|
+
registerImportCommand(program);
|
|
100
|
+
registerExportCommand(program);
|
|
101
|
+
registerGitCommand(program);
|
|
102
|
+
|
|
103
|
+
// Phase 3: MCP & external integration
|
|
104
|
+
registerMcpCommand(program);
|
|
105
|
+
registerBrowseCommand(program);
|
|
106
|
+
registerInstinctCommand(program);
|
|
107
|
+
|
|
108
|
+
// Phase 4: Security & identity
|
|
109
|
+
registerDidCommand(program);
|
|
110
|
+
registerEncryptCommand(program);
|
|
111
|
+
registerAuthCommand(program);
|
|
112
|
+
registerAuditCommand(program);
|
|
113
|
+
|
|
114
|
+
// Phase 5: P2P, blockchain & enterprise
|
|
115
|
+
registerP2pCommand(program);
|
|
116
|
+
registerSyncCommand(program);
|
|
117
|
+
registerWalletCommand(program);
|
|
118
|
+
registerOrgCommand(program);
|
|
119
|
+
registerPluginCommand(program);
|
|
120
|
+
|
|
121
|
+
// Multi-agent collaboration
|
|
122
|
+
registerCoworkCommand(program);
|
|
123
|
+
|
|
124
|
+
// Phase 6: Advanced AI & Hooks
|
|
125
|
+
registerHookCommand(program);
|
|
126
|
+
registerWorkflowCommand(program);
|
|
127
|
+
registerHmemoryCommand(program);
|
|
128
|
+
registerA2aCommand(program);
|
|
129
|
+
|
|
130
|
+
// Phase 7: Security & Evolution
|
|
131
|
+
registerSandboxCommand(program);
|
|
132
|
+
registerEvolutionCommand(program);
|
|
133
|
+
|
|
134
|
+
// Phase 8: Blockchain & Enterprise
|
|
135
|
+
registerEconomyCommand(program);
|
|
136
|
+
registerZkpCommand(program);
|
|
137
|
+
registerBiCommand(program);
|
|
138
|
+
|
|
139
|
+
// Phase 9: Low-Code & Multi-Agent
|
|
140
|
+
registerLowcodeCommand(program);
|
|
141
|
+
|
|
50
142
|
return program;
|
|
51
143
|
}
|
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A2A (Agent-to-Agent) Protocol for CLI
|
|
3
|
+
*
|
|
4
|
+
* Implements Google A2A protocol concepts: agent cards, task lifecycle,
|
|
5
|
+
* capability negotiation, and peer discovery.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// ─── Task statuses ───────────────────────────────────────────────
|
|
9
|
+
export const TASK_STATUS = {
|
|
10
|
+
SUBMITTED: "submitted",
|
|
11
|
+
WORKING: "working",
|
|
12
|
+
COMPLETED: "completed",
|
|
13
|
+
FAILED: "failed",
|
|
14
|
+
INPUT_REQUIRED: "input-required",
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
// ─── In-memory task subscriptions ────────────────────────────────
|
|
18
|
+
// Map<taskId, Set<callback>>
|
|
19
|
+
const _subscriptions = new Map();
|
|
20
|
+
|
|
21
|
+
// ─── Helpers ─────────────────────────────────────────────────────
|
|
22
|
+
function generateId(prefix = "a2a") {
|
|
23
|
+
return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function nowISO() {
|
|
27
|
+
return new Date().toISOString();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// ─── Table setup ─────────────────────────────────────────────────
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Create A2A protocol tables
|
|
34
|
+
*/
|
|
35
|
+
export function ensureA2ATables(db) {
|
|
36
|
+
db.exec(`
|
|
37
|
+
CREATE TABLE IF NOT EXISTS a2a_agent_cards (
|
|
38
|
+
id TEXT PRIMARY KEY,
|
|
39
|
+
name TEXT NOT NULL,
|
|
40
|
+
description TEXT DEFAULT '',
|
|
41
|
+
url TEXT DEFAULT '',
|
|
42
|
+
capabilities TEXT DEFAULT '[]',
|
|
43
|
+
skills TEXT DEFAULT '[]',
|
|
44
|
+
auth_type TEXT DEFAULT 'none',
|
|
45
|
+
status TEXT DEFAULT 'active',
|
|
46
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
47
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
48
|
+
)
|
|
49
|
+
`);
|
|
50
|
+
|
|
51
|
+
db.exec(`
|
|
52
|
+
CREATE TABLE IF NOT EXISTS a2a_tasks (
|
|
53
|
+
id TEXT PRIMARY KEY,
|
|
54
|
+
agent_id TEXT NOT NULL,
|
|
55
|
+
status TEXT DEFAULT 'submitted',
|
|
56
|
+
input TEXT DEFAULT '',
|
|
57
|
+
output TEXT DEFAULT '',
|
|
58
|
+
artifacts TEXT DEFAULT '[]',
|
|
59
|
+
error TEXT DEFAULT '',
|
|
60
|
+
history TEXT DEFAULT '[]',
|
|
61
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
62
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
63
|
+
)
|
|
64
|
+
`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ─── Agent Cards ─────────────────────────────────────────────────
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Register an agent card
|
|
71
|
+
*/
|
|
72
|
+
export function registerCard(db, card) {
|
|
73
|
+
ensureA2ATables(db);
|
|
74
|
+
|
|
75
|
+
if (!card || !card.name) {
|
|
76
|
+
throw new Error("Agent card must have a name");
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const id = generateId("agent");
|
|
80
|
+
const now = nowISO();
|
|
81
|
+
const capabilities = JSON.stringify(card.capabilities || []);
|
|
82
|
+
const skills = JSON.stringify(card.skills || []);
|
|
83
|
+
|
|
84
|
+
db.prepare(
|
|
85
|
+
`INSERT INTO a2a_agent_cards (id, name, description, url, capabilities, skills, auth_type, created_at, updated_at)
|
|
86
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
87
|
+
).run(
|
|
88
|
+
id,
|
|
89
|
+
card.name,
|
|
90
|
+
card.description || "",
|
|
91
|
+
card.url || "",
|
|
92
|
+
capabilities,
|
|
93
|
+
skills,
|
|
94
|
+
card.auth_type || "none",
|
|
95
|
+
now,
|
|
96
|
+
now,
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
return { id, name: card.name, status: "active" };
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Update an existing agent card
|
|
104
|
+
*/
|
|
105
|
+
export function updateCard(db, id, updates) {
|
|
106
|
+
ensureA2ATables(db);
|
|
107
|
+
|
|
108
|
+
if (!id) throw new Error("Card ID is required");
|
|
109
|
+
|
|
110
|
+
const fields = [];
|
|
111
|
+
const values = [];
|
|
112
|
+
|
|
113
|
+
if (updates.name !== undefined) {
|
|
114
|
+
fields.push("name = ?");
|
|
115
|
+
values.push(updates.name);
|
|
116
|
+
}
|
|
117
|
+
if (updates.description !== undefined) {
|
|
118
|
+
fields.push("description = ?");
|
|
119
|
+
values.push(updates.description);
|
|
120
|
+
}
|
|
121
|
+
if (updates.url !== undefined) {
|
|
122
|
+
fields.push("url = ?");
|
|
123
|
+
values.push(updates.url);
|
|
124
|
+
}
|
|
125
|
+
if (updates.capabilities !== undefined) {
|
|
126
|
+
fields.push("capabilities = ?");
|
|
127
|
+
values.push(JSON.stringify(updates.capabilities));
|
|
128
|
+
}
|
|
129
|
+
if (updates.skills !== undefined) {
|
|
130
|
+
fields.push("skills = ?");
|
|
131
|
+
values.push(JSON.stringify(updates.skills));
|
|
132
|
+
}
|
|
133
|
+
if (updates.auth_type !== undefined) {
|
|
134
|
+
fields.push("auth_type = ?");
|
|
135
|
+
values.push(updates.auth_type);
|
|
136
|
+
}
|
|
137
|
+
if (updates.status !== undefined) {
|
|
138
|
+
fields.push("status = ?");
|
|
139
|
+
values.push(updates.status);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (fields.length === 0) return { id, updated: false };
|
|
143
|
+
|
|
144
|
+
fields.push("updated_at = ?");
|
|
145
|
+
values.push(nowISO());
|
|
146
|
+
values.push(id);
|
|
147
|
+
|
|
148
|
+
const result = db
|
|
149
|
+
.prepare(`UPDATE a2a_agent_cards SET ${fields.join(", ")} WHERE id = ?`)
|
|
150
|
+
.run(...values);
|
|
151
|
+
|
|
152
|
+
return { id, updated: result.changes > 0 };
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Discover agents matching a filter
|
|
157
|
+
*/
|
|
158
|
+
export function discoverAgents(db, filter = {}) {
|
|
159
|
+
ensureA2ATables(db);
|
|
160
|
+
|
|
161
|
+
let rows = db
|
|
162
|
+
.prepare(`SELECT * FROM a2a_agent_cards WHERE status = 'active'`)
|
|
163
|
+
.all();
|
|
164
|
+
|
|
165
|
+
// Parse JSON fields
|
|
166
|
+
rows = rows.map((r) => ({
|
|
167
|
+
...r,
|
|
168
|
+
capabilities: JSON.parse(r.capabilities || "[]"),
|
|
169
|
+
skills: JSON.parse(r.skills || "[]"),
|
|
170
|
+
}));
|
|
171
|
+
|
|
172
|
+
if (filter.capability) {
|
|
173
|
+
rows = rows.filter((r) => r.capabilities.includes(filter.capability));
|
|
174
|
+
}
|
|
175
|
+
if (filter.skill) {
|
|
176
|
+
rows = rows.filter((r) => r.skills.includes(filter.skill));
|
|
177
|
+
}
|
|
178
|
+
if (filter.name) {
|
|
179
|
+
const pattern = filter.name.toLowerCase();
|
|
180
|
+
rows = rows.filter((r) => r.name.toLowerCase().includes(pattern));
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return rows;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// ─── Task Lifecycle ──────────────────────────────────────────────
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Send a task to an agent (creates with status: submitted)
|
|
190
|
+
*/
|
|
191
|
+
export function sendTask(db, agentId, input) {
|
|
192
|
+
ensureA2ATables(db);
|
|
193
|
+
|
|
194
|
+
if (!agentId) throw new Error("Agent ID is required");
|
|
195
|
+
if (!input) throw new Error("Task input is required");
|
|
196
|
+
|
|
197
|
+
const taskId = generateId("task");
|
|
198
|
+
const now = nowISO();
|
|
199
|
+
const history = JSON.stringify([
|
|
200
|
+
{ status: TASK_STATUS.SUBMITTED, timestamp: now },
|
|
201
|
+
]);
|
|
202
|
+
|
|
203
|
+
db.prepare(
|
|
204
|
+
`INSERT INTO a2a_tasks (id, agent_id, status, input, history, created_at, updated_at)
|
|
205
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
|
206
|
+
).run(taskId, agentId, TASK_STATUS.SUBMITTED, input, history, now, now);
|
|
207
|
+
|
|
208
|
+
_notifySubscribers(taskId, TASK_STATUS.SUBMITTED);
|
|
209
|
+
|
|
210
|
+
return { taskId, status: TASK_STATUS.SUBMITTED };
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Mark a task as completed
|
|
215
|
+
*/
|
|
216
|
+
export function completeTask(db, taskId, output, artifacts = []) {
|
|
217
|
+
ensureA2ATables(db);
|
|
218
|
+
|
|
219
|
+
if (!taskId) throw new Error("Task ID is required");
|
|
220
|
+
|
|
221
|
+
const now = nowISO();
|
|
222
|
+
const task = _getTask(db, taskId);
|
|
223
|
+
const history = JSON.parse(task.history || "[]");
|
|
224
|
+
history.push({ status: TASK_STATUS.COMPLETED, timestamp: now });
|
|
225
|
+
|
|
226
|
+
db.prepare(
|
|
227
|
+
`UPDATE a2a_tasks SET status = ?, output = ?, artifacts = ?, history = ?, updated_at = ? WHERE id = ?`,
|
|
228
|
+
).run(
|
|
229
|
+
TASK_STATUS.COMPLETED,
|
|
230
|
+
output || "",
|
|
231
|
+
JSON.stringify(artifacts),
|
|
232
|
+
JSON.stringify(history),
|
|
233
|
+
now,
|
|
234
|
+
taskId,
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
_notifySubscribers(taskId, TASK_STATUS.COMPLETED);
|
|
238
|
+
|
|
239
|
+
return { taskId, status: TASK_STATUS.COMPLETED };
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Mark a task as failed
|
|
244
|
+
*/
|
|
245
|
+
export function failTask(db, taskId, error) {
|
|
246
|
+
ensureA2ATables(db);
|
|
247
|
+
|
|
248
|
+
if (!taskId) throw new Error("Task ID is required");
|
|
249
|
+
|
|
250
|
+
const now = nowISO();
|
|
251
|
+
const task = _getTask(db, taskId);
|
|
252
|
+
const history = JSON.parse(task.history || "[]");
|
|
253
|
+
history.push({ status: TASK_STATUS.FAILED, timestamp: now });
|
|
254
|
+
|
|
255
|
+
db.prepare(
|
|
256
|
+
`UPDATE a2a_tasks SET status = ?, error = ?, history = ?, updated_at = ? WHERE id = ?`,
|
|
257
|
+
).run(
|
|
258
|
+
TASK_STATUS.FAILED,
|
|
259
|
+
error || "Unknown error",
|
|
260
|
+
JSON.stringify(history),
|
|
261
|
+
now,
|
|
262
|
+
taskId,
|
|
263
|
+
);
|
|
264
|
+
|
|
265
|
+
_notifySubscribers(taskId, TASK_STATUS.FAILED);
|
|
266
|
+
|
|
267
|
+
return { taskId, status: TASK_STATUS.FAILED };
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Get task status with full history
|
|
272
|
+
*/
|
|
273
|
+
export function getTaskStatus(db, taskId) {
|
|
274
|
+
ensureA2ATables(db);
|
|
275
|
+
|
|
276
|
+
const task = _getTask(db, taskId);
|
|
277
|
+
return {
|
|
278
|
+
...task,
|
|
279
|
+
history: JSON.parse(task.history || "[]"),
|
|
280
|
+
artifacts: JSON.parse(task.artifacts || "[]"),
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function _getTask(db, taskId) {
|
|
285
|
+
const task = db.prepare(`SELECT * FROM a2a_tasks WHERE id = ?`).get(taskId);
|
|
286
|
+
if (!task) throw new Error(`Task not found: ${taskId}`);
|
|
287
|
+
return task;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// ─── Capability Negotiation ──────────────────────────────────────
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Check if an agent supports the required capabilities
|
|
294
|
+
*/
|
|
295
|
+
export function negotiateCapability(db, agentId, requiredCapabilities) {
|
|
296
|
+
ensureA2ATables(db);
|
|
297
|
+
|
|
298
|
+
if (!agentId) throw new Error("Agent ID is required");
|
|
299
|
+
if (!Array.isArray(requiredCapabilities)) {
|
|
300
|
+
throw new Error("requiredCapabilities must be an array");
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const card = db
|
|
304
|
+
.prepare(`SELECT * FROM a2a_agent_cards WHERE id = ?`)
|
|
305
|
+
.get(agentId);
|
|
306
|
+
if (!card) throw new Error(`Agent not found: ${agentId}`);
|
|
307
|
+
|
|
308
|
+
const agentCaps = JSON.parse(card.capabilities || "[]");
|
|
309
|
+
const supported = requiredCapabilities.filter((c) => agentCaps.includes(c));
|
|
310
|
+
const missing = requiredCapabilities.filter((c) => !agentCaps.includes(c));
|
|
311
|
+
|
|
312
|
+
return {
|
|
313
|
+
compatible: missing.length === 0,
|
|
314
|
+
supported,
|
|
315
|
+
missing,
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// ─── Peers ───────────────────────────────────────────────────────
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* List all registered agents
|
|
323
|
+
*/
|
|
324
|
+
export function listPeers(db) {
|
|
325
|
+
ensureA2ATables(db);
|
|
326
|
+
|
|
327
|
+
const rows = db
|
|
328
|
+
.prepare(`SELECT * FROM a2a_agent_cards ORDER BY created_at DESC`)
|
|
329
|
+
.all();
|
|
330
|
+
return rows.map((r) => ({
|
|
331
|
+
...r,
|
|
332
|
+
capabilities: JSON.parse(r.capabilities || "[]"),
|
|
333
|
+
skills: JSON.parse(r.skills || "[]"),
|
|
334
|
+
}));
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// ─── Subscriptions ───────────────────────────────────────────────
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Subscribe to task status changes (in-memory)
|
|
341
|
+
*/
|
|
342
|
+
export function subscribeToTask(taskId, callback) {
|
|
343
|
+
if (!_subscriptions.has(taskId)) {
|
|
344
|
+
_subscriptions.set(taskId, new Set());
|
|
345
|
+
}
|
|
346
|
+
_subscriptions.get(taskId).add(callback);
|
|
347
|
+
|
|
348
|
+
return () => {
|
|
349
|
+
const subs = _subscriptions.get(taskId);
|
|
350
|
+
if (subs) {
|
|
351
|
+
subs.delete(callback);
|
|
352
|
+
if (subs.size === 0) _subscriptions.delete(taskId);
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
function _notifySubscribers(taskId, status) {
|
|
358
|
+
const subs = _subscriptions.get(taskId);
|
|
359
|
+
if (subs) {
|
|
360
|
+
for (const cb of subs) {
|
|
361
|
+
try {
|
|
362
|
+
cb(taskId, status);
|
|
363
|
+
} catch (_err) {
|
|
364
|
+
// Subscriber error should not break task lifecycle
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// Export for testing
|
|
371
|
+
export { _subscriptions };
|