mcp-coordinator 0.6.1 → 0.7.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/README.md +24 -0
- package/dist/src/agent-activity.d.ts +13 -9
- package/dist/src/agent-activity.js +45 -24
- package/dist/src/agent-registry.d.ts +7 -7
- package/dist/src/agent-registry.js +19 -18
- package/dist/src/announce-workflow.d.ts +1 -0
- package/dist/src/announce-workflow.js +13 -12
- package/dist/src/auth/providers/registry.d.ts +4 -0
- package/dist/src/auth/providers/registry.js +7 -0
- package/dist/src/auth/providers/types.d.ts +11 -0
- package/dist/src/auth/providers/types.js +1 -0
- package/dist/src/auth.d.ts +24 -5
- package/dist/src/auth.js +172 -23
- package/dist/src/conflict-detector.d.ts +1 -0
- package/dist/src/conflict-detector.js +4 -4
- package/dist/src/consultation.d.ts +28 -14
- package/dist/src/consultation.js +101 -68
- package/dist/src/context-provider.d.ts +2 -2
- package/dist/src/context-provider.js +3 -4
- package/dist/src/database.js +203 -4
- package/dist/src/dependency-map.d.ts +25 -4
- package/dist/src/dependency-map.js +49 -11
- package/dist/src/file-tracker.d.ts +5 -4
- package/dist/src/file-tracker.js +16 -14
- package/dist/src/git-cochange-builder.d.ts +11 -2
- package/dist/src/git-cochange-builder.js +15 -7
- package/dist/src/http/handle-health.d.ts +9 -5
- package/dist/src/http/handle-health.js +22 -8
- package/dist/src/http/handle-rest.d.ts +3 -0
- package/dist/src/http/handle-rest.js +56 -55
- package/dist/src/http/utils.d.ts +4 -0
- package/dist/src/http/utils.js +7 -1
- package/dist/src/impact-scorer.d.ts +3 -0
- package/dist/src/impact-scorer.js +65 -51
- package/dist/src/introspection.d.ts +13 -7
- package/dist/src/introspection.js +34 -11
- package/dist/src/metrics.js +2 -1
- package/dist/src/mqtt-bridge.d.ts +3 -2
- package/dist/src/mqtt-bridge.js +33 -23
- package/dist/src/mqtt-broker.d.ts +16 -7
- package/dist/src/mqtt-broker.js +57 -15
- package/dist/src/security/audit.d.ts +11 -0
- package/dist/src/security/audit.js +7 -0
- package/dist/src/security/encryption.d.ts +17 -0
- package/dist/src/security/encryption.js +5 -0
- package/dist/src/serve-http.js +136 -57
- package/dist/src/server-setup.d.ts +12 -2
- package/dist/src/server-setup.js +33 -15
- package/dist/src/sse-emitter.d.ts +7 -4
- package/dist/src/sse-emitter.js +27 -21
- package/dist/src/tools/agents-tools.d.ts +2 -1
- package/dist/src/tools/agents-tools.js +36 -12
- package/dist/src/tools/consultation-tools.d.ts +2 -1
- package/dist/src/tools/consultation-tools.js +102 -36
- package/dist/src/tools/dependencies-tools.d.ts +2 -1
- package/dist/src/tools/dependencies-tools.js +25 -7
- package/dist/src/tools/files-tools.d.ts +2 -1
- package/dist/src/tools/files-tools.js +25 -7
- package/dist/src/tools/mqtt-tools.d.ts +7 -1
- package/dist/src/tools/mqtt-tools.js +27 -4
- package/dist/src/tools/status-tools.d.ts +7 -1
- package/dist/src/tools/status-tools.js +26 -9
- package/dist/src/types.d.ts +2 -0
- package/dist/src/working-files-tracker.d.ts +21 -11
- package/dist/src/working-files-tracker.js +32 -21
- package/package.json +1 -1
|
@@ -6,10 +6,10 @@ import type { Metrics } from "./metrics.js";
|
|
|
6
6
|
* historical log; this is current state with TTL.
|
|
7
7
|
*
|
|
8
8
|
* Lifecycle:
|
|
9
|
-
* PreToolUse → start(agent, file, ttlMin) → UPSERT row
|
|
10
|
-
* PostToolUse → stop(agent, file) → DELETE row
|
|
11
|
-
* Sweeper → sweepExpired()
|
|
12
|
-
* Agent LWT → clearForAgent(agent)
|
|
9
|
+
* PreToolUse → start(orgId, agent, file, ttlMin) → UPSERT row
|
|
10
|
+
* PostToolUse → stop(orgId, agent, file) → DELETE row
|
|
11
|
+
* Sweeper → sweepExpired() → DELETE rows past claim_until (cross-org)
|
|
12
|
+
* Agent LWT → clearForAgent(agent) → DELETE all rows for agent (cross-org maintenance)
|
|
13
13
|
*/
|
|
14
14
|
export declare class WorkingFilesTracker {
|
|
15
15
|
private sweeperHandle;
|
|
@@ -18,18 +18,26 @@ export declare class WorkingFilesTracker {
|
|
|
18
18
|
constructor(logger?: Logger, metrics?: Metrics);
|
|
19
19
|
/**
|
|
20
20
|
* Start (or refresh) a working-files claim. Idempotent: re-calling with
|
|
21
|
-
* the same (agent_id, file_path) updates last_activity_at + claim_until
|
|
21
|
+
* the same (org_id, agent_id, file_path) updates last_activity_at + claim_until
|
|
22
22
|
* without erroring.
|
|
23
23
|
*/
|
|
24
|
-
start(agentId: string, filePath: string, ttlMinutes: number): void;
|
|
24
|
+
start(orgId: string, agentId: string, filePath: string, ttlMinutes: number): void;
|
|
25
25
|
/**
|
|
26
26
|
* Stop a working-files claim. No-op when no row matches (PostToolUse can
|
|
27
27
|
* arrive after a TTL eviction or before the matching PreToolUse on slow Pre).
|
|
28
28
|
*/
|
|
29
|
-
stop(agentId: string, filePath: string): void;
|
|
30
|
-
/** Returns number of rows evicted.
|
|
29
|
+
stop(orgId: string, agentId: string, filePath: string): void;
|
|
30
|
+
/** Returns number of rows evicted.
|
|
31
|
+
* cross-org maintenance — intentional: TTL expiry is a housekeeping concern,
|
|
32
|
+
* not a data-visibility concern; sweeping only own-org would leave other orgs'
|
|
33
|
+
* expired rows accumulating indefinitely.
|
|
34
|
+
*/
|
|
31
35
|
sweepExpired(): number;
|
|
32
|
-
/** Called when an agent goes offline (MQTT LWT). Returns rows deleted.
|
|
36
|
+
/** Called when an agent goes offline (MQTT LWT). Returns rows deleted.
|
|
37
|
+
* cross-org maintenance — intentional: MQTT topics carry no org_id today
|
|
38
|
+
* (see TODO(Task 22) in serve-http.ts); clearing by agent_id only is safe
|
|
39
|
+
* in single-tenant Phase 1 and matches the cross-org setOffline("default", …) pattern.
|
|
40
|
+
*/
|
|
33
41
|
clearForAgent(agentId: string): number;
|
|
34
42
|
/**
|
|
35
43
|
* Background sweeper. unref() so it doesn't keep the loop alive at shutdown.
|
|
@@ -37,6 +45,8 @@ export declare class WorkingFilesTracker {
|
|
|
37
45
|
*/
|
|
38
46
|
startSweeper(intervalMs?: number): void;
|
|
39
47
|
stopSweeper(): void;
|
|
40
|
-
/** Read in-flight files map: file_path → set<agent_id>, excluding caller.
|
|
41
|
-
|
|
48
|
+
/** Read in-flight files map: file_path → set<agent_id>, excluding caller.
|
|
49
|
+
* Scoped to orgId so cross-org agent lists are not leaked.
|
|
50
|
+
*/
|
|
51
|
+
getIndex(orgId: string, filePaths: string[], excludeAgentId: string): Map<string, Set<string>>;
|
|
42
52
|
}
|
|
@@ -6,10 +6,10 @@ import { silentLogger } from "./logger.js";
|
|
|
6
6
|
* historical log; this is current state with TTL.
|
|
7
7
|
*
|
|
8
8
|
* Lifecycle:
|
|
9
|
-
* PreToolUse → start(agent, file, ttlMin) → UPSERT row
|
|
10
|
-
* PostToolUse → stop(agent, file) → DELETE row
|
|
11
|
-
* Sweeper → sweepExpired()
|
|
12
|
-
* Agent LWT → clearForAgent(agent)
|
|
9
|
+
* PreToolUse → start(orgId, agent, file, ttlMin) → UPSERT row
|
|
10
|
+
* PostToolUse → stop(orgId, agent, file) → DELETE row
|
|
11
|
+
* Sweeper → sweepExpired() → DELETE rows past claim_until (cross-org)
|
|
12
|
+
* Agent LWT → clearForAgent(agent) → DELETE all rows for agent (cross-org maintenance)
|
|
13
13
|
*/
|
|
14
14
|
export class WorkingFilesTracker {
|
|
15
15
|
sweeperHandle = null;
|
|
@@ -21,30 +21,34 @@ export class WorkingFilesTracker {
|
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
23
|
* Start (or refresh) a working-files claim. Idempotent: re-calling with
|
|
24
|
-
* the same (agent_id, file_path) updates last_activity_at + claim_until
|
|
24
|
+
* the same (org_id, agent_id, file_path) updates last_activity_at + claim_until
|
|
25
25
|
* without erroring.
|
|
26
26
|
*/
|
|
27
|
-
start(agentId, filePath, ttlMinutes) {
|
|
27
|
+
start(orgId, agentId, filePath, ttlMinutes) {
|
|
28
28
|
const db = getDb();
|
|
29
|
-
const existing = db.prepare("SELECT 1 FROM working_files WHERE agent_id = ? AND file_path = ?")
|
|
30
|
-
.get(agentId, filePath);
|
|
31
|
-
db.prepare(`INSERT INTO working_files (agent_id, file_path, started_at, last_activity_at, claim_until)
|
|
32
|
-
VALUES (?, ?, strftime('%Y-%m-%dT%H:%M:%SZ', 'now'), strftime('%Y-%m-%dT%H:%M:%SZ', 'now'), strftime('%Y-%m-%dT%H:%M:%SZ', 'now', '+' || CAST(? AS TEXT) || ' minutes'))
|
|
33
|
-
ON CONFLICT(agent_id, file_path) DO UPDATE SET
|
|
29
|
+
const existing = db.prepare("SELECT 1 FROM working_files WHERE org_id = ? AND agent_id = ? AND file_path = ?")
|
|
30
|
+
.get(orgId, agentId, filePath);
|
|
31
|
+
db.prepare(`INSERT INTO working_files (org_id, agent_id, file_path, started_at, last_activity_at, claim_until)
|
|
32
|
+
VALUES (?, ?, ?, strftime('%Y-%m-%dT%H:%M:%SZ', 'now'), strftime('%Y-%m-%dT%H:%M:%SZ', 'now'), strftime('%Y-%m-%dT%H:%M:%SZ', 'now', '+' || CAST(? AS TEXT) || ' minutes'))
|
|
33
|
+
ON CONFLICT(org_id, agent_id, file_path) DO UPDATE SET
|
|
34
34
|
last_activity_at = strftime('%Y-%m-%dT%H:%M:%SZ', 'now'),
|
|
35
|
-
claim_until = strftime('%Y-%m-%dT%H:%M:%SZ', 'now', '+' || CAST(? AS TEXT) || ' minutes')`).run(agentId, filePath, ttlMinutes, ttlMinutes);
|
|
35
|
+
claim_until = strftime('%Y-%m-%dT%H:%M:%SZ', 'now', '+' || CAST(? AS TEXT) || ' minutes')`).run(orgId, agentId, filePath, ttlMinutes, ttlMinutes);
|
|
36
36
|
this.metrics?.workingFilesStarts.inc({ result: existing ? "updated" : "inserted" });
|
|
37
37
|
}
|
|
38
38
|
/**
|
|
39
39
|
* Stop a working-files claim. No-op when no row matches (PostToolUse can
|
|
40
40
|
* arrive after a TTL eviction or before the matching PreToolUse on slow Pre).
|
|
41
41
|
*/
|
|
42
|
-
stop(agentId, filePath) {
|
|
42
|
+
stop(orgId, agentId, filePath) {
|
|
43
43
|
const db = getDb();
|
|
44
|
-
db.prepare("DELETE FROM working_files WHERE agent_id = ? AND file_path = ?")
|
|
45
|
-
.run(agentId, filePath);
|
|
44
|
+
db.prepare("DELETE FROM working_files WHERE org_id = ? AND agent_id = ? AND file_path = ?")
|
|
45
|
+
.run(orgId, agentId, filePath);
|
|
46
46
|
}
|
|
47
|
-
/** Returns number of rows evicted.
|
|
47
|
+
/** Returns number of rows evicted.
|
|
48
|
+
* cross-org maintenance — intentional: TTL expiry is a housekeeping concern,
|
|
49
|
+
* not a data-visibility concern; sweeping only own-org would leave other orgs'
|
|
50
|
+
* expired rows accumulating indefinitely.
|
|
51
|
+
*/
|
|
48
52
|
sweepExpired() {
|
|
49
53
|
const db = getDb();
|
|
50
54
|
const result = db.prepare("DELETE FROM working_files WHERE claim_until < strftime('%Y-%m-%dT%H:%M:%SZ', 'now')").run();
|
|
@@ -55,7 +59,11 @@ export class WorkingFilesTracker {
|
|
|
55
59
|
}
|
|
56
60
|
return evicted;
|
|
57
61
|
}
|
|
58
|
-
/** Called when an agent goes offline (MQTT LWT). Returns rows deleted.
|
|
62
|
+
/** Called when an agent goes offline (MQTT LWT). Returns rows deleted.
|
|
63
|
+
* cross-org maintenance — intentional: MQTT topics carry no org_id today
|
|
64
|
+
* (see TODO(Task 22) in serve-http.ts); clearing by agent_id only is safe
|
|
65
|
+
* in single-tenant Phase 1 and matches the cross-org setOffline("default", …) pattern.
|
|
66
|
+
*/
|
|
59
67
|
clearForAgent(agentId) {
|
|
60
68
|
const db = getDb();
|
|
61
69
|
const result = db.prepare("DELETE FROM working_files WHERE agent_id = ?").run(agentId);
|
|
@@ -87,17 +95,20 @@ export class WorkingFilesTracker {
|
|
|
87
95
|
this.sweeperHandle = null;
|
|
88
96
|
}
|
|
89
97
|
}
|
|
90
|
-
/** Read in-flight files map: file_path → set<agent_id>, excluding caller.
|
|
91
|
-
|
|
98
|
+
/** Read in-flight files map: file_path → set<agent_id>, excluding caller.
|
|
99
|
+
* Scoped to orgId so cross-org agent lists are not leaked.
|
|
100
|
+
*/
|
|
101
|
+
getIndex(orgId, filePaths, excludeAgentId) {
|
|
92
102
|
const index = new Map();
|
|
93
103
|
if (filePaths.length === 0)
|
|
94
104
|
return index;
|
|
95
105
|
const db = getDb();
|
|
96
106
|
const placeholders = filePaths.map(() => "?").join(",");
|
|
97
107
|
const rows = db.prepare(`SELECT DISTINCT file_path, agent_id FROM working_files
|
|
98
|
-
WHERE
|
|
108
|
+
WHERE org_id = ?
|
|
109
|
+
AND file_path IN (${placeholders})
|
|
99
110
|
AND agent_id != ?
|
|
100
|
-
AND claim_until > strftime('%Y-%m-%dT%H:%M:%SZ', 'now')`).all(...filePaths, excludeAgentId);
|
|
111
|
+
AND claim_until > strftime('%Y-%m-%dT%H:%M:%SZ', 'now')`).all(orgId, ...filePaths, excludeAgentId);
|
|
101
112
|
for (const r of rows) {
|
|
102
113
|
let set = index.get(r.file_path);
|
|
103
114
|
if (!set) {
|