pilotswarm 0.4.0 → 0.5.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/mcp/README.md +88 -4
- package/mcp/dist/src/context.d.ts +36 -6
- package/mcp/dist/src/context.d.ts.map +1 -1
- package/mcp/dist/src/context.js +102 -8
- package/mcp/dist/src/context.js.map +1 -1
- package/mcp/dist/src/resources/artifacts.d.ts +5 -0
- package/mcp/dist/src/resources/artifacts.d.ts.map +1 -0
- package/mcp/dist/src/resources/artifacts.js +39 -0
- package/mcp/dist/src/resources/artifacts.js.map +1 -0
- package/mcp/dist/src/resources/capabilities.d.ts +4 -0
- package/mcp/dist/src/resources/capabilities.d.ts.map +1 -0
- package/mcp/dist/src/resources/capabilities.js +17 -0
- package/mcp/dist/src/resources/capabilities.js.map +1 -0
- package/mcp/dist/src/resources/graph.d.ts +5 -0
- package/mcp/dist/src/resources/graph.d.ts.map +1 -0
- package/mcp/dist/src/resources/graph.js +45 -0
- package/mcp/dist/src/resources/graph.js.map +1 -0
- package/mcp/dist/src/server.d.ts.map +1 -1
- package/mcp/dist/src/server.js +61 -2
- package/mcp/dist/src/server.js.map +1 -1
- package/mcp/dist/src/tools/agents.d.ts.map +1 -1
- package/mcp/dist/src/tools/agents.js +3 -2
- package/mcp/dist/src/tools/agents.js.map +1 -1
- package/mcp/dist/src/tools/artifacts.d.ts +12 -0
- package/mcp/dist/src/tools/artifacts.d.ts.map +1 -0
- package/mcp/dist/src/tools/artifacts.js +92 -0
- package/mcp/dist/src/tools/artifacts.js.map +1 -0
- package/mcp/dist/src/tools/capabilities.d.ts +27 -0
- package/mcp/dist/src/tools/capabilities.d.ts.map +1 -0
- package/mcp/dist/src/tools/capabilities.js +69 -0
- package/mcp/dist/src/tools/capabilities.js.map +1 -0
- package/mcp/dist/src/tools/debug.d.ts +4 -0
- package/mcp/dist/src/tools/debug.d.ts.map +1 -0
- package/mcp/dist/src/tools/debug.js +94 -0
- package/mcp/dist/src/tools/debug.js.map +1 -0
- package/mcp/dist/src/tools/facts-enhanced.d.ts +13 -0
- package/mcp/dist/src/tools/facts-enhanced.d.ts.map +1 -0
- package/mcp/dist/src/tools/facts-enhanced.js +80 -0
- package/mcp/dist/src/tools/facts-enhanced.js.map +1 -0
- package/mcp/dist/src/tools/graph.d.ts +12 -0
- package/mcp/dist/src/tools/graph.d.ts.map +1 -0
- package/mcp/dist/src/tools/graph.js +237 -0
- package/mcp/dist/src/tools/graph.js.map +1 -0
- package/mcp/dist/src/tools/groups.d.ts +10 -0
- package/mcp/dist/src/tools/groups.d.ts.map +1 -0
- package/mcp/dist/src/tools/groups.js +107 -0
- package/mcp/dist/src/tools/groups.js.map +1 -0
- package/mcp/dist/src/tools/models.d.ts.map +1 -1
- package/mcp/dist/src/tools/models.js +16 -4
- package/mcp/dist/src/tools/models.js.map +1 -1
- package/mcp/dist/src/tools/observability.d.ts +13 -0
- package/mcp/dist/src/tools/observability.d.ts.map +1 -0
- package/mcp/dist/src/tools/observability.js +174 -0
- package/mcp/dist/src/tools/observability.js.map +1 -0
- package/mcp/dist/src/tools/sessions.d.ts.map +1 -1
- package/mcp/dist/src/tools/sessions.js +120 -94
- package/mcp/dist/src/tools/sessions.js.map +1 -1
- package/mcp/dist/src/tools/system.d.ts +14 -0
- package/mcp/dist/src/tools/system.d.ts.map +1 -0
- package/mcp/dist/src/tools/system.js +110 -0
- package/mcp/dist/src/tools/system.js.map +1 -0
- package/mcp/dist/src/tools/turn-control.d.ts +13 -0
- package/mcp/dist/src/tools/turn-control.d.ts.map +1 -0
- package/mcp/dist/src/tools/turn-control.js +98 -0
- package/mcp/dist/src/tools/turn-control.js.map +1 -0
- package/mcp/dist/src/util/respond.d.ts +21 -0
- package/mcp/dist/src/util/respond.d.ts.map +1 -0
- package/mcp/dist/src/util/respond.js +42 -0
- package/mcp/dist/src/util/respond.js.map +1 -0
- package/package.json +6 -4
- package/tui/bin/tui.js +0 -3
- package/tui/src/node-sdk-transport.js +30 -5
- package/tui/src/plugin-config.js +36 -2
- package/tui/tui-splash-mobile.txt +7 -0
- package/ui/core/src/controller.js +104 -7
- package/ui/core/src/history.js +20 -2
- package/ui/core/src/reducer.js +19 -2
- package/ui/core/src/selectors.js +32 -1
- package/ui/core/src/state.js +3 -0
- package/ui/react/src/web-app.js +122 -10
- package/web/dist/assets/{index-DMefB7Wb.js → index-B8ge3rzb.js} +4 -4
- package/web/dist/assets/index-DXRIxmIv.css +1 -0
- package/web/dist/assets/pilotswarm-Dt1qY6hD.js +90 -0
- package/web/dist/assets/{react-BZwsW8pe.js → react-IRUjK5Iz.js} +1 -1
- package/web/dist/index.html +4 -4
- package/web/runtime.js +33 -2
- package/web/dist/assets/index-CBgQQk-j.css +0 -1
- package/web/dist/assets/pilotswarm-DyBlqVTY.js +0 -87
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system.d.ts","sourceRoot":"","sources":["../../../src/tools/system.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAGnD;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,aAAa,QA8GxE"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { jsonResult, errorResult, withToolErrors } from "../util/respond.js";
|
|
3
|
+
/**
|
|
4
|
+
* Ops preflight & system tools (proposal G7).
|
|
5
|
+
*
|
|
6
|
+
* get_system_status workers / log config / session policy / creatable agents
|
|
7
|
+
* restart_system_session bounce sweeper, resourcemgr, ... [admin]
|
|
8
|
+
* facts_admin purge tombstoned facts, prune deleted summaries [admin]
|
|
9
|
+
*
|
|
10
|
+
* get_system_status turns the `no_worker_claimed` create_session failure into
|
|
11
|
+
* a preflight check: workers === 0 means don't bother creating sessions yet.
|
|
12
|
+
*/
|
|
13
|
+
export function registerSystemTools(server, ctx) {
|
|
14
|
+
// Web-mode only: worker count / log config / policy / agents are Web API
|
|
15
|
+
// operations with no direct-mode equivalent.
|
|
16
|
+
if (ctx.api) {
|
|
17
|
+
server.registerTool("get_system_status", {
|
|
18
|
+
title: "Get System Status",
|
|
19
|
+
description: "Deployment status: embedded-worker count (workers running inside the portal process — dedicated "
|
|
20
|
+
+ "worker pods report 0 here and that is normal), session-creation policy, creatable agents, and "
|
|
21
|
+
+ "log-tail availability. include narrows the fetch (default all).",
|
|
22
|
+
inputSchema: {
|
|
23
|
+
include: z
|
|
24
|
+
.array(z.enum(["workers", "policy", "agents", "log_config"]))
|
|
25
|
+
.optional()
|
|
26
|
+
.describe("Axes to fetch (default all)"),
|
|
27
|
+
},
|
|
28
|
+
}, withToolErrors(async ({ include }) => {
|
|
29
|
+
const wants = new Set(include ?? ["workers", "policy", "agents", "log_config"]);
|
|
30
|
+
const result = {};
|
|
31
|
+
const errors = {};
|
|
32
|
+
const grab = async (key, fn) => {
|
|
33
|
+
try {
|
|
34
|
+
result[key] = await fn();
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
errors[key] = err instanceof Error ? err.message : String(err);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
if (wants.has("workers")) {
|
|
41
|
+
await grab("workers", async () => {
|
|
42
|
+
const w = await ctx.api.call("getWorkerCount");
|
|
43
|
+
const count = typeof w === "number" ? w : (w?.count ?? null);
|
|
44
|
+
return {
|
|
45
|
+
embedded_count: count,
|
|
46
|
+
note: "Counts workers embedded in the portal process only. Deployments with dedicated worker pods report 0 here — use worker_claimed on create_session responses for per-run liveness.",
|
|
47
|
+
};
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
if (wants.has("policy"))
|
|
51
|
+
await grab("policy", () => ctx.api.call("getSessionCreationPolicy"));
|
|
52
|
+
if (wants.has("agents"))
|
|
53
|
+
await grab("agents", () => ctx.api.call("listCreatableAgents"));
|
|
54
|
+
if (wants.has("log_config"))
|
|
55
|
+
await grab("log_config", () => ctx.api.call("getLogConfig"));
|
|
56
|
+
if (Object.keys(errors).length > 0)
|
|
57
|
+
result.errors = errors;
|
|
58
|
+
return jsonResult(result);
|
|
59
|
+
}));
|
|
60
|
+
}
|
|
61
|
+
// restart_system_session — [admin] disruptive lifecycle operation on the
|
|
62
|
+
// deployment's system agents (sweeper, resourcemgr, ...).
|
|
63
|
+
if (ctx.admin) {
|
|
64
|
+
server.registerTool("restart_system_session", {
|
|
65
|
+
title: "Restart System Session",
|
|
66
|
+
description: "Restart a system session (sweeper, resourcemgr, ...) by agent id or session id. disposition "
|
|
67
|
+
+ "controls what happens to the old session: complete (graceful), terminate, or hard_delete. [admin]",
|
|
68
|
+
inputSchema: {
|
|
69
|
+
agent_or_session_id: z.string().min(1).describe("System agent id (e.g. 'sweeper') or its session id"),
|
|
70
|
+
disposition: z.enum(["complete", "terminate", "hard_delete"]).describe("How to dispose of the old session"),
|
|
71
|
+
reason: z.string().optional().describe("Reason recorded on the restart"),
|
|
72
|
+
},
|
|
73
|
+
}, withToolErrors(async ({ agent_or_session_id, disposition, reason }) => {
|
|
74
|
+
const result = await ctx.mgmt.restartSystemSession(agent_or_session_id, { disposition, reason });
|
|
75
|
+
// The system-agent set may have changed identity; refresh the
|
|
76
|
+
// dynamic resource registrations' source of truth.
|
|
77
|
+
await ctx.refreshSystemAgentIds();
|
|
78
|
+
return jsonResult({ restarted: true, ...(result && typeof result === "object" ? result : {}) });
|
|
79
|
+
}));
|
|
80
|
+
// facts_admin — destructive housekeeping, action-dispatched.
|
|
81
|
+
server.registerTool("facts_admin", {
|
|
82
|
+
title: "Facts Admin",
|
|
83
|
+
description: "Administrative facts housekeeping. action: 'purge' force-purges soft-deleted (tombstoned) facts; "
|
|
84
|
+
+ "'prune_summaries' prunes summaries of deleted sessions older than a cutoff. Both DESTRUCTIVE. [admin]",
|
|
85
|
+
inputSchema: {
|
|
86
|
+
action: z.enum(["purge", "prune_summaries"]).describe("The housekeeping operation"),
|
|
87
|
+
cutoff: z.string().describe("ISO timestamp — purge/prune anything soft-deleted before this"),
|
|
88
|
+
key_prefix: z.string().optional().describe("purge: restrict to keys under this prefix"),
|
|
89
|
+
only_unreconciled: z.boolean().optional().describe("purge: only facts whose graph evidence is not yet reconciled"),
|
|
90
|
+
limit: z.number().int().positive().optional().describe("purge: max rows per call"),
|
|
91
|
+
},
|
|
92
|
+
}, withToolErrors(async ({ action, cutoff, key_prefix, only_unreconciled, limit }) => {
|
|
93
|
+
const cutoffDate = new Date(cutoff);
|
|
94
|
+
if (Number.isNaN(cutoffDate.getTime()))
|
|
95
|
+
return errorResult("cutoff must be a valid ISO timestamp");
|
|
96
|
+
if (action === "purge") {
|
|
97
|
+
const purged = await ctx.facts.forcePurgeFacts({
|
|
98
|
+
cutoff: cutoffDate,
|
|
99
|
+
keyPrefix: key_prefix,
|
|
100
|
+
onlyUnreconciled: only_unreconciled,
|
|
101
|
+
limit,
|
|
102
|
+
});
|
|
103
|
+
return jsonResult({ purged });
|
|
104
|
+
}
|
|
105
|
+
const pruned = await ctx.mgmt.pruneDeletedSummaries(cutoffDate);
|
|
106
|
+
return jsonResult({ pruned });
|
|
107
|
+
}));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=system.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system.js","sourceRoot":"","sources":["../../../src/tools/system.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { ServerContext } from "../context.js";
|
|
3
|
+
/**
|
|
4
|
+
* Turn- and queue-level session control (proposal G3) — finer levers than
|
|
5
|
+
* abort_session's whole-session cancel:
|
|
6
|
+
*
|
|
7
|
+
* stop_turn abort the in-flight turn, keep the session
|
|
8
|
+
* complete_session mark done (distinct from cancelled)
|
|
9
|
+
* cancel_pending_messages drop queued messages by client message id
|
|
10
|
+
* send_session_event inject a custom event into the session
|
|
11
|
+
*/
|
|
12
|
+
export declare function registerTurnControlTools(server: McpServer, ctx: ServerContext): void;
|
|
13
|
+
//# sourceMappingURL=turn-control.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"turn-control.d.ts","sourceRoot":"","sources":["../../../src/tools/turn-control.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAGnD;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,aAAa,QA+G7E"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { jsonResult, errorResult, withToolErrors } from "../util/respond.js";
|
|
3
|
+
/**
|
|
4
|
+
* Turn- and queue-level session control (proposal G3) — finer levers than
|
|
5
|
+
* abort_session's whole-session cancel:
|
|
6
|
+
*
|
|
7
|
+
* stop_turn abort the in-flight turn, keep the session
|
|
8
|
+
* complete_session mark done (distinct from cancelled)
|
|
9
|
+
* cancel_pending_messages drop queued messages by client message id
|
|
10
|
+
* send_session_event inject a custom event into the session
|
|
11
|
+
*/
|
|
12
|
+
export function registerTurnControlTools(server, ctx) {
|
|
13
|
+
async function requireSession(session_id) {
|
|
14
|
+
const existing = await ctx.mgmt.getSession(session_id);
|
|
15
|
+
return existing ?? null;
|
|
16
|
+
}
|
|
17
|
+
server.registerTool("stop_turn", {
|
|
18
|
+
title: "Stop Turn",
|
|
19
|
+
description: "Abort the in-flight turn of a running PilotSwarm session without cancelling the session — it stays "
|
|
20
|
+
+ "alive and accepts new messages. Use abort_session only when the whole session should end.",
|
|
21
|
+
inputSchema: {
|
|
22
|
+
session_id: z.string().uuid({ message: "session_id must be a valid UUID" }).describe("The session whose current turn to stop"),
|
|
23
|
+
reason: z.string().optional().describe("Optional reason, surfaced to the session"),
|
|
24
|
+
timeout_ms: z.number().int().positive().optional().describe("Max time to wait for the turn to stop"),
|
|
25
|
+
},
|
|
26
|
+
}, withToolErrors(async ({ session_id, reason, timeout_ms }) => {
|
|
27
|
+
if (!(await requireSession(session_id))) {
|
|
28
|
+
return errorResult("session not found", { session_id });
|
|
29
|
+
}
|
|
30
|
+
const result = await ctx.mgmt.stopSessionTurn(session_id, { reason, timeoutMs: timeout_ms });
|
|
31
|
+
return jsonResult({ stopped: true, ...(result && typeof result === "object" ? result : {}) });
|
|
32
|
+
}));
|
|
33
|
+
server.registerTool("complete_session", {
|
|
34
|
+
title: "Complete Session",
|
|
35
|
+
description: "Mark a PilotSwarm session completed (a successful terminal state — distinct from abort_session's "
|
|
36
|
+
+ "cancelled). Use when the session's work is done and it should stop cleanly.",
|
|
37
|
+
inputSchema: {
|
|
38
|
+
session_id: z.string().uuid({ message: "session_id must be a valid UUID" }).describe("The session to complete"),
|
|
39
|
+
reason: z.string().optional().describe("Optional completion reason"),
|
|
40
|
+
},
|
|
41
|
+
}, withToolErrors(async ({ session_id, reason }) => {
|
|
42
|
+
if (!(await requireSession(session_id))) {
|
|
43
|
+
return errorResult("session not found", { session_id });
|
|
44
|
+
}
|
|
45
|
+
await ctx.mgmt.completeSession(session_id, reason);
|
|
46
|
+
return jsonResult({ completed: true });
|
|
47
|
+
}));
|
|
48
|
+
server.registerTool("cancel_pending_messages", {
|
|
49
|
+
title: "Cancel Pending Messages",
|
|
50
|
+
description: "Cancel queued (not yet processed) messages in a session, identified by the client_message_ids they "
|
|
51
|
+
+ "were sent with. Pair with send_message's client_message_ids parameter.",
|
|
52
|
+
inputSchema: {
|
|
53
|
+
session_id: z.string().uuid({ message: "session_id must be a valid UUID" }).describe("The session holding the queued messages"),
|
|
54
|
+
client_message_ids: z.array(z.string().min(1)).min(1).describe("Client message ids to cancel"),
|
|
55
|
+
},
|
|
56
|
+
}, withToolErrors(async ({ session_id, client_message_ids }) => {
|
|
57
|
+
if (!(await requireSession(session_id))) {
|
|
58
|
+
return errorResult("session not found", { session_id });
|
|
59
|
+
}
|
|
60
|
+
try {
|
|
61
|
+
await ctx.mgmt.cancelPendingMessage(session_id, client_message_ids);
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
65
|
+
if (/not started|NotFound/i.test(msg)) {
|
|
66
|
+
// Pending-message cancellation rides the orchestration
|
|
67
|
+
// command channel, which only exists once the session's
|
|
68
|
+
// orchestration has started. Explain, don't confuse.
|
|
69
|
+
return errorResult("cannot cancel yet: this session's orchestration has not started, so the command channel "
|
|
70
|
+
+ "is not live. Monitor the session (get_session_detail include: ['status']) and retry "
|
|
71
|
+
+ "once orchestration_status is no longer NotFound.", { session_id, client_message_ids });
|
|
72
|
+
}
|
|
73
|
+
throw err;
|
|
74
|
+
}
|
|
75
|
+
return jsonResult({ cancelled: true, client_message_ids });
|
|
76
|
+
}));
|
|
77
|
+
// sendSessionEvent is a Web API session operation; in direct mode there is
|
|
78
|
+
// no equivalent seam (events are worker-internal), so web-only.
|
|
79
|
+
if (ctx.api) {
|
|
80
|
+
server.registerTool("send_session_event", {
|
|
81
|
+
title: "Send Session Event",
|
|
82
|
+
description: "Inject a custom named event into a PilotSwarm session (e.g. a webhook-style signal an agent "
|
|
83
|
+
+ "is waiting on). Not a chat message — use send_message for prompts.",
|
|
84
|
+
inputSchema: {
|
|
85
|
+
session_id: z.string().uuid({ message: "session_id must be a valid UUID" }).describe("The target session"),
|
|
86
|
+
event_name: z.string().min(1).describe("Event name the session listens for"),
|
|
87
|
+
data: z.record(z.string(), z.any()).optional().describe("Event payload"),
|
|
88
|
+
},
|
|
89
|
+
}, withToolErrors(async ({ session_id, event_name, data }) => {
|
|
90
|
+
if (!(await requireSession(session_id))) {
|
|
91
|
+
return errorResult("session not found", { session_id });
|
|
92
|
+
}
|
|
93
|
+
await ctx.api.call("sendSessionEvent", { sessionId: session_id, eventName: event_name, data });
|
|
94
|
+
return jsonResult({ sent: true, event_name });
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=turn-control.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"turn-control.js","sourceRoot":"","sources":["../../../src/tools/turn-control.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** Shared MCP tool-response helpers — same content shape the existing tool
|
|
2
|
+
* files emit inline; new tool modules use these to cut boilerplate. */
|
|
3
|
+
export interface ToolResult {
|
|
4
|
+
content: Array<{
|
|
5
|
+
type: "text";
|
|
6
|
+
text: string;
|
|
7
|
+
}>;
|
|
8
|
+
isError?: boolean;
|
|
9
|
+
[key: string]: unknown;
|
|
10
|
+
}
|
|
11
|
+
export declare function jsonResult(payload: unknown): ToolResult;
|
|
12
|
+
export declare function errorResult(message: string, extra?: Record<string, unknown>): ToolResult;
|
|
13
|
+
/**
|
|
14
|
+
* Map a thrown error to a tool error result. Recognizes the Web API's 403
|
|
15
|
+
* (admin-gated operation hit without the admin role) and shapes it into
|
|
16
|
+
* actionable text instead of a bare status line.
|
|
17
|
+
*/
|
|
18
|
+
export declare function errorToResult(err: unknown): ToolResult;
|
|
19
|
+
/** Wrap a tool handler with the standard try/catch → errorToResult mapping. */
|
|
20
|
+
export declare function withToolErrors<A extends unknown[]>(fn: (...args: A) => Promise<ToolResult>): (...args: A) => Promise<ToolResult>;
|
|
21
|
+
//# sourceMappingURL=respond.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"respond.d.ts","sourceRoot":"","sources":["../../../src/util/respond.ts"],"names":[],"mappings":"AAAA;uEACuE;AAEvE,MAAM,WAAW,UAAU;IACvB,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,UAAU,CAIvD;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,UAAU,CAQxF;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,UAAU,CAWtD;AAED,+EAA+E;AAC/E,wBAAgB,cAAc,CAAC,CAAC,SAAS,OAAO,EAAE,EAC9C,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,UAAU,CAAC,GACxC,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,UAAU,CAAC,CAQrC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/** Shared MCP tool-response helpers — same content shape the existing tool
|
|
2
|
+
* files emit inline; new tool modules use these to cut boilerplate. */
|
|
3
|
+
export function jsonResult(payload) {
|
|
4
|
+
return {
|
|
5
|
+
content: [{ type: "text", text: JSON.stringify(payload, null, 2) }],
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
export function errorResult(message, extra) {
|
|
9
|
+
const text = extra
|
|
10
|
+
? JSON.stringify({ error: message, ...extra })
|
|
11
|
+
: `Error: ${message}`;
|
|
12
|
+
return {
|
|
13
|
+
content: [{ type: "text", text }],
|
|
14
|
+
isError: true,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Map a thrown error to a tool error result. Recognizes the Web API's 403
|
|
19
|
+
* (admin-gated operation hit without the admin role) and shapes it into
|
|
20
|
+
* actionable text instead of a bare status line.
|
|
21
|
+
*/
|
|
22
|
+
export function errorToResult(err) {
|
|
23
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
24
|
+
const status = err?.status ?? err?.statusCode;
|
|
25
|
+
if (status === 403 || /\b403\b|forbidden/i.test(message)) {
|
|
26
|
+
return errorResult("forbidden: this operation requires the deployment's admin role. "
|
|
27
|
+
+ "The MCP server's credential (PILOTSWARM_API_TOKEN or cached login) does not carry it.", { status: 403 });
|
|
28
|
+
}
|
|
29
|
+
return errorResult(message);
|
|
30
|
+
}
|
|
31
|
+
/** Wrap a tool handler with the standard try/catch → errorToResult mapping. */
|
|
32
|
+
export function withToolErrors(fn) {
|
|
33
|
+
return async (...args) => {
|
|
34
|
+
try {
|
|
35
|
+
return await fn(...args);
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
return errorToResult(err);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=respond.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"respond.js","sourceRoot":"","sources":["../../../src/util/respond.ts"],"names":[],"mappings":"AAAA;uEACuE;AAQvE,MAAM,UAAU,UAAU,CAAC,OAAgB;IACvC,OAAO;QACH,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;KAC/E,CAAC;AACN,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,OAAe,EAAE,KAA+B;IACxE,MAAM,IAAI,GAAG,KAAK;QACd,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,KAAK,EAAE,CAAC;QAC9C,CAAC,CAAC,UAAU,OAAO,EAAE,CAAC;IAC1B,OAAO;QACH,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC;QAC1C,OAAO,EAAE,IAAI;KAChB,CAAC;AACN,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,GAAY;IACtC,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACjE,MAAM,MAAM,GAAI,GAAW,EAAE,MAAM,IAAK,GAAW,EAAE,UAAU,CAAC;IAChE,IAAI,MAAM,KAAK,GAAG,IAAI,oBAAoB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACvD,OAAO,WAAW,CACd,kEAAkE;cAChE,uFAAuF,EACzF,EAAE,MAAM,EAAE,GAAG,EAAE,CAClB,CAAC;IACN,CAAC;IACD,OAAO,WAAW,CAAC,OAAO,CAAC,CAAC;AAChC,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,cAAc,CAC1B,EAAuC;IAEvC,OAAO,KAAK,EAAE,GAAG,IAAO,EAAE,EAAE;QACxB,IAAI,CAAC;YACD,OAAO,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;QAC7B,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACpB,OAAO,aAAa,CAAC,GAAG,CAAC,CAAC;QAC9B,CAAC;IACL,CAAC,CAAC;AACN,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pilotswarm",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "PilotSwarm application package: terminal UI, browser portal + Web API server, and MCP server — one install, three bins.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"tui/src/**/*",
|
|
36
36
|
"tui/plugins/**/*",
|
|
37
37
|
"tui/tui-splash.txt",
|
|
38
|
+
"tui/tui-splash-mobile.txt",
|
|
38
39
|
"web/auth.js",
|
|
39
40
|
"web/auth/**/*",
|
|
40
41
|
"web/api/**/*",
|
|
@@ -61,9 +62,10 @@
|
|
|
61
62
|
"test:tui": "node --test tui/test/*.test.mjs",
|
|
62
63
|
"test:web": "node --test web/test/*.test.mjs",
|
|
63
64
|
"test:ui": "node --test ui/core/test/*.test.mjs",
|
|
64
|
-
"test:mcp": "node mcp/test/unit/sendCommandAndWait.unit.mjs",
|
|
65
|
+
"test:mcp": "node mcp/test/unit/sendCommandAndWait.unit.mjs && node mcp/test/unit/registration.unit.mjs && node mcp/test/unit/dispatch.unit.mjs",
|
|
65
66
|
"test:mcp:integration": "node mcp/test/integration/smoke.live.mjs",
|
|
66
|
-
"test:mcp:integration:
|
|
67
|
+
"test:mcp:integration:horizondb": "MCP_PARITY_REQUIRE=search,graph node --env-file=../../.env.horizondb mcp/test/integration/parity.live.mjs",
|
|
68
|
+
"test:mcp:integration:all": "node mcp/test/integration/smoke.live.mjs && node mcp/test/integration/tools.live.mjs && node mcp/test/integration/edge-cases.live.mjs && node mcp/test/integration/verify.live.mjs && node mcp/test/integration/parity.live.mjs",
|
|
67
69
|
"clean": "rm -rf web/dist mcp/dist"
|
|
68
70
|
},
|
|
69
71
|
"dependencies": {
|
|
@@ -75,7 +77,7 @@
|
|
|
75
77
|
"hono": "^4.12.10",
|
|
76
78
|
"ink": "^6.8.0",
|
|
77
79
|
"jose": "^6.2.2",
|
|
78
|
-
"pilotswarm-sdk": "^0.
|
|
80
|
+
"pilotswarm-sdk": "^0.5.0",
|
|
79
81
|
"react": "^19.2.4",
|
|
80
82
|
"react-dom": "^19.2.4",
|
|
81
83
|
"ws": "^8.18.2"
|
package/tui/bin/tui.js
CHANGED
|
@@ -4,9 +4,6 @@
|
|
|
4
4
|
// explicitly opts into another environment for debugging.
|
|
5
5
|
process.env.NODE_ENV ??= "production";
|
|
6
6
|
|
|
7
|
-
const { syncBundledWorkspaceUiPackages } = await import("../src/sync-workspace-ui.js");
|
|
8
|
-
syncBundledWorkspaceUiPackages({ linkWorkspacePackages: true });
|
|
9
|
-
|
|
10
7
|
const argv = process.argv.slice(2);
|
|
11
8
|
if (argv[0] === "auth") {
|
|
12
9
|
const { runAuthCommand } = await import("../src/auth/cli.js");
|
|
@@ -782,6 +782,30 @@ export class NodeSdkTransport {
|
|
|
782
782
|
return this.mgmt.getFleetRetrievalUsage(opts);
|
|
783
783
|
}
|
|
784
784
|
|
|
785
|
+
async getSessionRetrievalUsage(sessionId, opts) {
|
|
786
|
+
return this.mgmt.getSessionRetrievalUsage(sessionId, opts);
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
async getSessionTreeRetrievalUsage(sessionId, opts) {
|
|
790
|
+
return this.mgmt.getSessionTreeRetrievalUsage(sessionId, opts);
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
async getSessionGraphNodeUsage(sessionId, opts) {
|
|
794
|
+
return this.mgmt.getSessionGraphNodeUsage(sessionId, opts);
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
async getSessionGraphEdgeSearchUsage(sessionId, opts) {
|
|
798
|
+
return this.mgmt.getSessionGraphEdgeSearchUsage(sessionId, opts);
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
async getSessionGraphSearches(sessionId, limit) {
|
|
802
|
+
return this.mgmt.getSessionGraphSearches(sessionId, limit);
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
async getFleetGraphNodeUsage(opts) {
|
|
806
|
+
return this.mgmt.getFleetGraphNodeUsage(opts);
|
|
807
|
+
}
|
|
808
|
+
|
|
785
809
|
async getSessionFactsStats(sessionId) {
|
|
786
810
|
return this.mgmt.getSessionFactsStats(sessionId);
|
|
787
811
|
}
|
|
@@ -927,13 +951,14 @@ export class NodeSdkTransport {
|
|
|
927
951
|
return { sessionId: session.sessionId, model: effectiveModel, reasoningEffort: reasoningEffort || undefined };
|
|
928
952
|
}
|
|
929
953
|
|
|
930
|
-
async createSessionForAgent(agentName, { model, reasoningEffort, title, splash, initialPrompt, owner, groupId } = {}) {
|
|
954
|
+
async createSessionForAgent(agentName, { model, reasoningEffort, title, splash, splashMobile, initialPrompt, owner, groupId } = {}) {
|
|
931
955
|
const effectiveModel = await this.assertSessionModelCreatable({ model, owner });
|
|
932
956
|
const session = await this.client.createSessionForAgent(agentName, {
|
|
933
957
|
...(effectiveModel ? { model: effectiveModel } : {}),
|
|
934
958
|
...(reasoningEffort ? { reasoningEffort } : {}),
|
|
935
959
|
...(title ? { title } : {}),
|
|
936
960
|
...(splash ? { splash } : {}),
|
|
961
|
+
...(splashMobile ? { splashMobile } : {}),
|
|
937
962
|
...(initialPrompt ? { initialPrompt } : {}),
|
|
938
963
|
...(owner ? { owner } : {}),
|
|
939
964
|
...(groupId ? { groupId } : {}),
|
|
@@ -1311,13 +1336,13 @@ export class NodeSdkTransport {
|
|
|
1311
1336
|
return this.mgmt.getDefaultModel();
|
|
1312
1337
|
}
|
|
1313
1338
|
|
|
1314
|
-
async getSessionEvents(sessionId, afterSeq, limit) {
|
|
1315
|
-
return this.mgmt.getSessionEvents(sessionId, afterSeq, limit);
|
|
1339
|
+
async getSessionEvents(sessionId, afterSeq, limit, eventTypes) {
|
|
1340
|
+
return this.mgmt.getSessionEvents(sessionId, afterSeq, limit, eventTypes);
|
|
1316
1341
|
}
|
|
1317
1342
|
|
|
1318
|
-
async getSessionEventsBefore(sessionId, beforeSeq, limit) {
|
|
1343
|
+
async getSessionEventsBefore(sessionId, beforeSeq, limit, eventTypes) {
|
|
1319
1344
|
if (typeof this.mgmt.getSessionEventsBefore !== "function") return [];
|
|
1320
|
-
return this.mgmt.getSessionEventsBefore(sessionId, beforeSeq, limit);
|
|
1345
|
+
return this.mgmt.getSessionEventsBefore(sessionId, beforeSeq, limit, eventTypes);
|
|
1321
1346
|
}
|
|
1322
1347
|
|
|
1323
1348
|
emitLogEntry(entry) {
|
package/tui/src/plugin-config.js
CHANGED
|
@@ -5,6 +5,7 @@ import { fileURLToPath } from "node:url";
|
|
|
5
5
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
6
6
|
const pkgRoot = path.resolve(__dirname, "..");
|
|
7
7
|
const defaultTuiSplashPath = path.join(pkgRoot, "tui-splash.txt");
|
|
8
|
+
const defaultTuiSplashMobilePath = path.join(pkgRoot, "tui-splash-mobile.txt");
|
|
8
9
|
|
|
9
10
|
function fileExists(filePath) {
|
|
10
11
|
try {
|
|
@@ -93,10 +94,27 @@ function readSplashValue(baseDir, config, fallback) {
|
|
|
93
94
|
return fallback;
|
|
94
95
|
}
|
|
95
96
|
|
|
97
|
+
// Narrow-viewport splash variant (splashMobile / splashMobileFile). No
|
|
98
|
+
// default art: null means "wrap the main splash when it does not fit".
|
|
99
|
+
function readSplashMobileValue(baseDir, config, fallback = null) {
|
|
100
|
+
if (typeof config?.splashMobile === "string" && config.splashMobile.trim()) {
|
|
101
|
+
return config.splashMobile;
|
|
102
|
+
}
|
|
103
|
+
if (typeof config?.splashMobileFile === "string" && config.splashMobileFile.trim()) {
|
|
104
|
+
const fileText = readRelativeTextFile(baseDir, config.splashMobileFile);
|
|
105
|
+
if (fileText != null) return fileText;
|
|
106
|
+
}
|
|
107
|
+
return fallback;
|
|
108
|
+
}
|
|
109
|
+
|
|
96
110
|
function getDefaultSplash() {
|
|
97
111
|
return readOptionalTextFile(defaultTuiSplashPath) || "{bold}{cyan-fg}PilotSwarm{/cyan-fg}{/bold}";
|
|
98
112
|
}
|
|
99
113
|
|
|
114
|
+
function getDefaultSplashMobile() {
|
|
115
|
+
return readOptionalTextFile(defaultTuiSplashMobilePath) || null;
|
|
116
|
+
}
|
|
117
|
+
|
|
100
118
|
export function readPluginMetadata(pluginDir) {
|
|
101
119
|
if (!pluginDir) return null;
|
|
102
120
|
const pluginJsonPath = path.join(pluginDir, "plugin.json");
|
|
@@ -130,12 +148,17 @@ export function resolveTuiBranding(pluginDir) {
|
|
|
130
148
|
const tui = pluginMeta?.tui;
|
|
131
149
|
const defaultSplash = getDefaultSplash();
|
|
132
150
|
if (!tui || typeof tui !== "object") {
|
|
133
|
-
|
|
151
|
+
const defaultMobile = getDefaultSplashMobile();
|
|
152
|
+
return { title: "PilotSwarm", splash: defaultSplash, ...(defaultMobile ? { splashMobile: defaultMobile } : {}) };
|
|
134
153
|
}
|
|
135
154
|
|
|
136
155
|
const title = firstNonEmptyString(tui.title, "PilotSwarm") || "PilotSwarm";
|
|
137
156
|
const splash = readSplashValue(pluginDir, tui, defaultSplash);
|
|
138
|
-
|
|
157
|
+
// The default mobile art only pairs with the default splash — an app that
|
|
158
|
+
// ships its own splash without a mobile variant wraps instead of showing
|
|
159
|
+
// PilotSwarm-branded art.
|
|
160
|
+
const splashMobile = readSplashMobileValue(pluginDir, tui, splash === defaultSplash ? getDefaultSplashMobile() : null);
|
|
161
|
+
return { title, splash, ...(splashMobile ? { splashMobile } : {}) };
|
|
139
162
|
}
|
|
140
163
|
|
|
141
164
|
export function resolvePortalConfigBundleFromPluginDirs(pluginDirs = []) {
|
|
@@ -145,6 +168,7 @@ export function resolvePortalConfigBundleFromPluginDirs(pluginDirs = []) {
|
|
|
145
168
|
title: "PilotSwarm",
|
|
146
169
|
pageTitle: "PilotSwarm",
|
|
147
170
|
splash: defaultSplash,
|
|
171
|
+
splashMobile: getDefaultSplashMobile(),
|
|
148
172
|
logoUrl: null,
|
|
149
173
|
faviconUrl: null,
|
|
150
174
|
},
|
|
@@ -179,6 +203,15 @@ export function resolvePortalConfigBundleFromPluginDirs(pluginDirs = []) {
|
|
|
179
203
|
portalBranding,
|
|
180
204
|
readSplashValue(absDir, portal, readSplashValue(absDir, tui, defaults.branding.splash)),
|
|
181
205
|
);
|
|
206
|
+
const splashMobile = readSplashMobileValue(
|
|
207
|
+
absDir,
|
|
208
|
+
portalBranding,
|
|
209
|
+
readSplashMobileValue(
|
|
210
|
+
absDir,
|
|
211
|
+
portal,
|
|
212
|
+
readSplashMobileValue(absDir, tui, splash === defaultSplash ? getDefaultSplashMobile() : null),
|
|
213
|
+
),
|
|
214
|
+
);
|
|
182
215
|
const logoAsset = resolvePortalAsset(absDir, {
|
|
183
216
|
file: firstNonEmptyString(portalBranding.logoFile, portal.logoFile),
|
|
184
217
|
url: firstNonEmptyString(portalBranding.logoUrl, portal.logoUrl),
|
|
@@ -193,6 +226,7 @@ export function resolvePortalConfigBundleFromPluginDirs(pluginDirs = []) {
|
|
|
193
226
|
title,
|
|
194
227
|
pageTitle,
|
|
195
228
|
splash,
|
|
229
|
+
splashMobile: splashMobile || null,
|
|
196
230
|
logoUrl: logoAsset.publicUrl || null,
|
|
197
231
|
faviconUrl: faviconAsset.publicUrl || null,
|
|
198
232
|
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{bold}{cyan-fg}█▀█ █ █ █▀█ ▀█▀{/cyan-fg} {magenta-fg}█▀ █ █ █ ▄▀█ █▀█ █▀▄▀█{/magenta-fg}{/bold}
|
|
2
|
+
{bold}{cyan-fg}█▀▀ █ █▄▄ █▄█ █ {/cyan-fg} {magenta-fg}▄█ ▀▄▀▄▀ █▀█ █▀▄ █ ▀ █{/magenta-fg}{/bold}
|
|
3
|
+
{yellow-fg}░▒▓██████████████████████████████████▓▒░{/yellow-fg}
|
|
4
|
+
{bold}{white-fg}Durable AI Agent Orchestration{/white-fg}{/bold}
|
|
5
|
+
{cyan-fg}Crash recovery{/cyan-fg} · {magenta-fg}Durable timers{/magenta-fg}
|
|
6
|
+
{yellow-fg}Sub-agents{/yellow-fg} · {green-fg}Multi-node scaling{/green-fg}
|
|
7
|
+
{gray-fg}Powered by duroxide + Copilot SDK{/gray-fg}
|