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.
Files changed (88) hide show
  1. package/mcp/README.md +88 -4
  2. package/mcp/dist/src/context.d.ts +36 -6
  3. package/mcp/dist/src/context.d.ts.map +1 -1
  4. package/mcp/dist/src/context.js +102 -8
  5. package/mcp/dist/src/context.js.map +1 -1
  6. package/mcp/dist/src/resources/artifacts.d.ts +5 -0
  7. package/mcp/dist/src/resources/artifacts.d.ts.map +1 -0
  8. package/mcp/dist/src/resources/artifacts.js +39 -0
  9. package/mcp/dist/src/resources/artifacts.js.map +1 -0
  10. package/mcp/dist/src/resources/capabilities.d.ts +4 -0
  11. package/mcp/dist/src/resources/capabilities.d.ts.map +1 -0
  12. package/mcp/dist/src/resources/capabilities.js +17 -0
  13. package/mcp/dist/src/resources/capabilities.js.map +1 -0
  14. package/mcp/dist/src/resources/graph.d.ts +5 -0
  15. package/mcp/dist/src/resources/graph.d.ts.map +1 -0
  16. package/mcp/dist/src/resources/graph.js +45 -0
  17. package/mcp/dist/src/resources/graph.js.map +1 -0
  18. package/mcp/dist/src/server.d.ts.map +1 -1
  19. package/mcp/dist/src/server.js +61 -2
  20. package/mcp/dist/src/server.js.map +1 -1
  21. package/mcp/dist/src/tools/agents.d.ts.map +1 -1
  22. package/mcp/dist/src/tools/agents.js +3 -2
  23. package/mcp/dist/src/tools/agents.js.map +1 -1
  24. package/mcp/dist/src/tools/artifacts.d.ts +12 -0
  25. package/mcp/dist/src/tools/artifacts.d.ts.map +1 -0
  26. package/mcp/dist/src/tools/artifacts.js +92 -0
  27. package/mcp/dist/src/tools/artifacts.js.map +1 -0
  28. package/mcp/dist/src/tools/capabilities.d.ts +27 -0
  29. package/mcp/dist/src/tools/capabilities.d.ts.map +1 -0
  30. package/mcp/dist/src/tools/capabilities.js +69 -0
  31. package/mcp/dist/src/tools/capabilities.js.map +1 -0
  32. package/mcp/dist/src/tools/debug.d.ts +4 -0
  33. package/mcp/dist/src/tools/debug.d.ts.map +1 -0
  34. package/mcp/dist/src/tools/debug.js +94 -0
  35. package/mcp/dist/src/tools/debug.js.map +1 -0
  36. package/mcp/dist/src/tools/facts-enhanced.d.ts +13 -0
  37. package/mcp/dist/src/tools/facts-enhanced.d.ts.map +1 -0
  38. package/mcp/dist/src/tools/facts-enhanced.js +80 -0
  39. package/mcp/dist/src/tools/facts-enhanced.js.map +1 -0
  40. package/mcp/dist/src/tools/graph.d.ts +12 -0
  41. package/mcp/dist/src/tools/graph.d.ts.map +1 -0
  42. package/mcp/dist/src/tools/graph.js +237 -0
  43. package/mcp/dist/src/tools/graph.js.map +1 -0
  44. package/mcp/dist/src/tools/groups.d.ts +10 -0
  45. package/mcp/dist/src/tools/groups.d.ts.map +1 -0
  46. package/mcp/dist/src/tools/groups.js +107 -0
  47. package/mcp/dist/src/tools/groups.js.map +1 -0
  48. package/mcp/dist/src/tools/models.d.ts.map +1 -1
  49. package/mcp/dist/src/tools/models.js +16 -4
  50. package/mcp/dist/src/tools/models.js.map +1 -1
  51. package/mcp/dist/src/tools/observability.d.ts +13 -0
  52. package/mcp/dist/src/tools/observability.d.ts.map +1 -0
  53. package/mcp/dist/src/tools/observability.js +174 -0
  54. package/mcp/dist/src/tools/observability.js.map +1 -0
  55. package/mcp/dist/src/tools/sessions.d.ts.map +1 -1
  56. package/mcp/dist/src/tools/sessions.js +120 -94
  57. package/mcp/dist/src/tools/sessions.js.map +1 -1
  58. package/mcp/dist/src/tools/system.d.ts +14 -0
  59. package/mcp/dist/src/tools/system.d.ts.map +1 -0
  60. package/mcp/dist/src/tools/system.js +110 -0
  61. package/mcp/dist/src/tools/system.js.map +1 -0
  62. package/mcp/dist/src/tools/turn-control.d.ts +13 -0
  63. package/mcp/dist/src/tools/turn-control.d.ts.map +1 -0
  64. package/mcp/dist/src/tools/turn-control.js +98 -0
  65. package/mcp/dist/src/tools/turn-control.js.map +1 -0
  66. package/mcp/dist/src/util/respond.d.ts +21 -0
  67. package/mcp/dist/src/util/respond.d.ts.map +1 -0
  68. package/mcp/dist/src/util/respond.js +42 -0
  69. package/mcp/dist/src/util/respond.js.map +1 -0
  70. package/package.json +6 -4
  71. package/tui/bin/tui.js +0 -3
  72. package/tui/src/node-sdk-transport.js +30 -5
  73. package/tui/src/plugin-config.js +36 -2
  74. package/tui/tui-splash-mobile.txt +7 -0
  75. package/ui/core/src/controller.js +104 -7
  76. package/ui/core/src/history.js +20 -2
  77. package/ui/core/src/reducer.js +19 -2
  78. package/ui/core/src/selectors.js +32 -1
  79. package/ui/core/src/state.js +3 -0
  80. package/ui/react/src/web-app.js +122 -10
  81. package/web/dist/assets/{index-DMefB7Wb.js → index-B8ge3rzb.js} +4 -4
  82. package/web/dist/assets/index-DXRIxmIv.css +1 -0
  83. package/web/dist/assets/pilotswarm-Dt1qY6hD.js +90 -0
  84. package/web/dist/assets/{react-BZwsW8pe.js → react-IRUjK5Iz.js} +1 -1
  85. package/web/dist/index.html +4 -4
  86. package/web/runtime.js +33 -2
  87. package/web/dist/assets/index-CBgQQk-j.css +0 -1
  88. 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.4.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: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",
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.4.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) {
@@ -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
- return { title: "PilotSwarm", splash: defaultSplash };
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
- return { title, splash };
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}