chainlesschain 0.47.6 → 0.47.7

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 (107) hide show
  1. package/package.json +2 -2
  2. package/src/assets/web-panel/.build-hash +1 -1
  3. package/src/assets/web-panel/assets/Analytics-BFI7jbwM.css +1 -0
  4. package/src/assets/web-panel/assets/Analytics-DQ135mAd.js +3 -0
  5. package/src/assets/web-panel/assets/AppLayout-6SPt_8Y_.js +1 -0
  6. package/src/assets/web-panel/assets/AppLayout-BFJ-Fofn.css +1 -0
  7. package/src/assets/web-panel/assets/{Backup-Ba9UybpT.js → Backup-DbVRG5vE.js} +1 -1
  8. package/src/assets/web-panel/assets/{Chat-BwXskT21.js → Chat-wVhrFK9C.js} +1 -1
  9. package/src/assets/web-panel/assets/{Cowork-UmOe7qvE.js → Cowork-lOC25IW2.js} +1 -1
  10. package/src/assets/web-panel/assets/{Cron-JHS-rc-4.js → Cron-3P0eVLTV.js} +1 -1
  11. package/src/assets/web-panel/assets/{Dashboard-B95cMCO7.js → Dashboard-Br7kCwKJ.js} +1 -1
  12. package/src/assets/web-panel/assets/{Git-CSYO0_zk.js → Git-CrDCcBig.js} +2 -2
  13. package/src/assets/web-panel/assets/{Logs-Hxw_K0km.js → Logs-BfTE8urP.js} +1 -1
  14. package/src/assets/web-panel/assets/{McpTools-DIE75TrB.js → McpTools-CsGIijNe.js} +1 -1
  15. package/src/assets/web-panel/assets/{Memory-C4KVnLlp.js → Memory-BXX_yMKJ.js} +1 -1
  16. package/src/assets/web-panel/assets/{Notes-DuzrHMAk.js → Notes-DU6Vf2cL.js} +1 -1
  17. package/src/assets/web-panel/assets/{Organization-DTq6uF82.js → Organization-Bny6yOPV.js} +4 -4
  18. package/src/assets/web-panel/assets/{P2P-C0hjlhsR.js → P2P-BxFZ1Bit.js} +2 -2
  19. package/src/assets/web-panel/assets/{Permissions-Ec0NH-xC.js → Permissions-B1j3Mtms.js} +3 -3
  20. package/src/assets/web-panel/assets/{Projects-U8D0asCS.js → Projects-D-CGscDu.js} +1 -1
  21. package/src/assets/web-panel/assets/{Providers-BngtTLvJ.js → Providers-r6NaBYMf.js} +1 -1
  22. package/src/assets/web-panel/assets/{RssFeed-B9NbwCKM.js → RssFeed-D7b68C5q.js} +1 -1
  23. package/src/assets/web-panel/assets/{Security-BL5Rkr1T.js → Security-MJfKv0EJ.js} +3 -3
  24. package/src/assets/web-panel/assets/{Services-D4MJzLld.js → Services-Yb_Q1V3d.js} +1 -1
  25. package/src/assets/web-panel/assets/{Skills-CQTOMDwF.js → Skills-DLTHcH5T.js} +1 -1
  26. package/src/assets/web-panel/assets/{Tasks-DepbJMnL.js → Tasks-CqycpPjS.js} +1 -1
  27. package/src/assets/web-panel/assets/{Templates-C24PVZPu.js → Templates-y01u2Zis.js} +1 -1
  28. package/src/assets/web-panel/assets/VideoEditing-BA1N-5kq.css +1 -0
  29. package/src/assets/web-panel/assets/VideoEditing-B_nPKw6B.js +1 -0
  30. package/src/assets/web-panel/assets/{Wallet-PQoSpN_P.js → Wallet-CsRgnjJY.js} +1 -1
  31. package/src/assets/web-panel/assets/{WebAuthn-BcuyQ4Lr.js → WebAuthn-DWoR5ADp.js} +1 -1
  32. package/src/assets/web-panel/assets/{WorkflowEditor-C-SvXbHW.js → WorkflowEditor-DBJhFPMN.js} +1 -1
  33. package/src/assets/web-panel/assets/{antd-DEjZPGMj.js → antd-Dh2t0vGq.js} +84 -84
  34. package/src/assets/web-panel/assets/index-tN-8TosE.js +2 -0
  35. package/src/assets/web-panel/assets/{markdown-CusdXFxb.js → markdown-CBnGGMzE.js} +1 -1
  36. package/src/assets/web-panel/index.html +2 -2
  37. package/src/commands/agent.js +20 -0
  38. package/src/commands/mcp.js +86 -4
  39. package/src/commands/memory.js +85 -4
  40. package/src/commands/sandbox.js +80 -6
  41. package/src/commands/serve.js +10 -0
  42. package/src/commands/session.js +250 -0
  43. package/src/commands/stream.js +75 -0
  44. package/src/commands/video.js +363 -0
  45. package/src/gateways/http/envelope-http-server.js +194 -0
  46. package/src/gateways/ws/message-dispatcher.js +123 -0
  47. package/src/gateways/ws/session-core-protocol.js +427 -0
  48. package/src/gateways/ws/session-protocol.js +42 -1
  49. package/src/gateways/ws/video-protocol.js +230 -0
  50. package/src/gateways/ws/ws-server.js +72 -0
  51. package/src/gateways/ws/ws-session-gateway.js +7 -3
  52. package/src/harness/jsonl-session-store.js +17 -9
  53. package/src/index.js +8 -0
  54. package/src/lib/agent-stream.js +63 -0
  55. package/src/lib/chat-core.js +183 -6
  56. package/src/lib/cowork/ab-comparator-cli.js +44 -23
  57. package/src/lib/cowork/agent-group-runner.js +145 -0
  58. package/src/lib/cowork/debate-review-cli.js +47 -25
  59. package/src/lib/cowork/project-style-analyzer-cli.js +34 -7
  60. package/src/lib/interaction-adapter.js +59 -1
  61. package/src/lib/jsonl-session-store.js +2 -0
  62. package/src/lib/memory-injection.js +90 -0
  63. package/src/lib/provider-stream.js +120 -0
  64. package/src/lib/sandbox-v2.js +198 -3
  65. package/src/lib/session-consolidator.js +125 -0
  66. package/src/lib/session-core-singletons.js +56 -0
  67. package/src/lib/session-tail.js +128 -0
  68. package/src/lib/session-usage.js +166 -0
  69. package/src/lib/shell-approval.js +96 -0
  70. package/src/lib/ws-chat-handler.js +3 -0
  71. package/src/repl/agent-repl.js +271 -6
  72. package/src/repl/chat-repl.js +87 -100
  73. package/src/runtime/agent-core.js +98 -15
  74. package/src/runtime/agent-runtime.js +105 -3
  75. package/src/runtime/policies/agent-policy.js +10 -0
  76. package/src/skills/video-editing/SKILL.md +46 -0
  77. package/src/skills/video-editing/beat-snap.js +127 -0
  78. package/src/skills/video-editing/extractors/audio-extractor.js +212 -0
  79. package/src/skills/video-editing/extractors/subtitle-extractor.js +90 -0
  80. package/src/skills/video-editing/extractors/video-extractor.js +137 -0
  81. package/src/skills/video-editing/parallel-orchestrator.js +212 -0
  82. package/src/skills/video-editing/pipeline.js +480 -0
  83. package/src/skills/video-editing/prompts/aesthetic-analysis.md +21 -0
  84. package/src/skills/video-editing/prompts/audio-segment.md +15 -0
  85. package/src/skills/video-editing/prompts/character-identify.md +19 -0
  86. package/src/skills/video-editing/prompts/dense-caption.md +20 -0
  87. package/src/skills/video-editing/prompts/editor-system.md +29 -0
  88. package/src/skills/video-editing/prompts/hook-dialogue.md +17 -0
  89. package/src/skills/video-editing/prompts/protagonist-detect.md +20 -0
  90. package/src/skills/video-editing/prompts/scene-caption.md +16 -0
  91. package/src/skills/video-editing/prompts/shot-caption.md +25 -0
  92. package/src/skills/video-editing/prompts/shot-plan.md +28 -0
  93. package/src/skills/video-editing/prompts/structure-proposal.md +16 -0
  94. package/src/skills/video-editing/prompts/vlog-scene-caption.md +18 -0
  95. package/src/skills/video-editing/render/audio-mix.js +128 -0
  96. package/src/skills/video-editing/render/ffmpeg-concat.js +45 -0
  97. package/src/skills/video-editing/render/ffmpeg-extract.js +67 -0
  98. package/src/skills/video-editing/reviewer.js +161 -0
  99. package/src/skills/video-editing/tools/commit.js +108 -0
  100. package/src/skills/video-editing/tools/review-clip.js +46 -0
  101. package/src/skills/video-editing/tools/semantic-retrieval.js +56 -0
  102. package/src/skills/video-editing/tools/shot-trimming.js +73 -0
  103. package/src/assets/web-panel/assets/Analytics-B4OM8S8X.css +0 -1
  104. package/src/assets/web-panel/assets/Analytics-DgypYeUB.js +0 -3
  105. package/src/assets/web-panel/assets/AppLayout-Bzf3mSZI.js +0 -1
  106. package/src/assets/web-panel/assets/AppLayout-DQyDwGut.css +0 -1
  107. package/src/assets/web-panel/assets/index-CwvzTTw_.js +0 -2
@@ -0,0 +1,194 @@
1
+ /**
2
+ * Envelope HTTP Server — Deep Agents Deploy Phase 5 (hosted HTTP follow-up)
3
+ *
4
+ * Wires the `@chainlesschain/session-core/envelope-sse` primitive to a node
5
+ * `http.Server` so consumers without a WebSocket can subscribe to a session's
6
+ * Phase 5 envelope stream via Server-Sent Events.
7
+ *
8
+ * Routes:
9
+ * GET /v1/health → { ok: true, ... }
10
+ * GET /v1/sessions/:sessionId/events → text/event-stream
11
+ *
12
+ * The bus is a minimal pub/sub: callers (ws-server / session-protocol) call
13
+ * `bus.publish(sessionId, envelope)` whenever an envelope is produced, and the
14
+ * HTTP route forwards it to every subscriber for that session.
15
+ *
16
+ * Authentication: optional bearer token via `Authorization: Bearer <token>`
17
+ * (matches the WS server's `--token` semantics).
18
+ */
19
+
20
+ import http from "node:http";
21
+ import { createRequire } from "node:module";
22
+
23
+ const require_ = createRequire(import.meta.url);
24
+ const { sseResponseHeaders, formatEnvelopeAsSse, formatSseComment } = require_(
25
+ "@chainlesschain/session-core/envelope-sse",
26
+ );
27
+
28
+ /** Minimal pub/sub. Not exported as a class to keep the surface small. */
29
+ export function createEnvelopeBus() {
30
+ /** @type {Map<string, Set<(env: object) => void>>} */
31
+ const subs = new Map();
32
+ return {
33
+ subscribe(sessionId, fn) {
34
+ let set = subs.get(sessionId);
35
+ if (!set) {
36
+ set = new Set();
37
+ subs.set(sessionId, set);
38
+ }
39
+ set.add(fn);
40
+ return () => {
41
+ const s = subs.get(sessionId);
42
+ if (!s) return;
43
+ s.delete(fn);
44
+ if (s.size === 0) subs.delete(sessionId);
45
+ };
46
+ },
47
+ publish(sessionId, envelope) {
48
+ const set = subs.get(sessionId);
49
+ if (!set) return 0;
50
+ for (const fn of set) {
51
+ try {
52
+ fn(envelope);
53
+ } catch (_e) {
54
+ // Subscriber error must not stop fan-out.
55
+ }
56
+ }
57
+ return set.size;
58
+ },
59
+ subscriberCount(sessionId) {
60
+ const set = subs.get(sessionId);
61
+ return set ? set.size : 0;
62
+ },
63
+ };
64
+ }
65
+
66
+ const SESSION_EVENTS_RE = /^\/v1\/sessions\/([^/]+)\/events\/?$/;
67
+
68
+ function checkAuth(req, token) {
69
+ if (!token) return true;
70
+ const header = req.headers["authorization"] || "";
71
+ const match = /^Bearer\s+(.+)$/i.exec(header);
72
+ return Boolean(match && match[1] === token);
73
+ }
74
+
75
+ /**
76
+ * @param {object} options
77
+ * @param {ReturnType<typeof createEnvelopeBus>} options.bus
78
+ * @param {number} [options.port=18801]
79
+ * @param {string} [options.host="127.0.0.1"]
80
+ * @param {string} [options.token] - optional bearer token; required for SSE
81
+ * @param {number} [options.heartbeatMs=15000]
82
+ */
83
+ export function createEnvelopeHttpServer(options = {}) {
84
+ const bus = options.bus;
85
+ if (!bus)
86
+ throw new Error("createEnvelopeHttpServer: options.bus is required");
87
+ const port = options.port ?? 18801;
88
+ const host = options.host ?? "127.0.0.1";
89
+ const token = options.token || null;
90
+ const heartbeatMs = options.heartbeatMs ?? 15000;
91
+
92
+ /** Active SSE subscriber unsubscribers, keyed by response object. */
93
+ const activeStreams = new Set();
94
+
95
+ function handleHealth(_req, res) {
96
+ res.writeHead(200, { "Content-Type": "application/json; charset=utf-8" });
97
+ res.end(JSON.stringify({ ok: true, service: "envelope-http", version: 1 }));
98
+ }
99
+
100
+ function handleSessionEvents(req, res, sessionId) {
101
+ if (!checkAuth(req, token)) {
102
+ res.writeHead(401, { "Content-Type": "application/json; charset=utf-8" });
103
+ res.end(JSON.stringify({ error: "unauthorized" }));
104
+ return;
105
+ }
106
+
107
+ res.writeHead(200, sseResponseHeaders());
108
+ // Prime the stream so HTTP/1.1 clients see headers immediately.
109
+ res.write(formatSseComment(`subscribed sessionId=${sessionId}`));
110
+
111
+ const send = (envelope) => {
112
+ try {
113
+ res.write(formatEnvelopeAsSse(envelope));
114
+ } catch (_e) {
115
+ // Bad envelope — drop, do not crash the stream.
116
+ }
117
+ };
118
+
119
+ const unsubscribe = bus.subscribe(sessionId, send);
120
+
121
+ let heartbeatTimer = null;
122
+ if (heartbeatMs > 0) {
123
+ heartbeatTimer = setInterval(() => {
124
+ try {
125
+ res.write(formatSseComment("keep-alive"));
126
+ } catch (_e) {
127
+ // Connection broken — cleanup will run via 'close' below.
128
+ }
129
+ }, heartbeatMs);
130
+ if (typeof heartbeatTimer.unref === "function") heartbeatTimer.unref();
131
+ }
132
+
133
+ const cleanup = () => {
134
+ if (heartbeatTimer) clearInterval(heartbeatTimer);
135
+ unsubscribe();
136
+ activeStreams.delete(cleanup);
137
+ };
138
+ activeStreams.add(cleanup);
139
+
140
+ req.on("close", cleanup);
141
+ req.on("aborted", cleanup);
142
+ }
143
+
144
+ function handler(req, res) {
145
+ const url = req.url || "/";
146
+ if (req.method !== "GET") {
147
+ res.writeHead(405, { Allow: "GET" });
148
+ res.end();
149
+ return;
150
+ }
151
+ if (url === "/v1/health") return handleHealth(req, res);
152
+ const match = SESSION_EVENTS_RE.exec(url);
153
+ if (match)
154
+ return handleSessionEvents(req, res, decodeURIComponent(match[1]));
155
+ res.writeHead(404, { "Content-Type": "application/json; charset=utf-8" });
156
+ res.end(JSON.stringify({ error: "not_found" }));
157
+ }
158
+
159
+ const server = http.createServer(handler);
160
+
161
+ return {
162
+ server,
163
+ bus,
164
+ start() {
165
+ return new Promise((resolve, reject) => {
166
+ const onError = (err) => {
167
+ server.removeListener("listening", onListening);
168
+ reject(err);
169
+ };
170
+ const onListening = () => {
171
+ server.removeListener("error", onError);
172
+ const addr = server.address();
173
+ resolve({
174
+ port: typeof addr === "object" && addr ? addr.port : port,
175
+ host,
176
+ });
177
+ };
178
+ server.once("error", onError);
179
+ server.once("listening", onListening);
180
+ server.listen(port, host);
181
+ });
182
+ },
183
+ stop() {
184
+ return new Promise((resolve) => {
185
+ for (const cleanup of [...activeStreams]) cleanup();
186
+ server.close(() => resolve());
187
+ // Force-close any kept-alive sockets so the server fully shuts down.
188
+ if (typeof server.closeAllConnections === "function") {
189
+ server.closeAllConnections();
190
+ }
191
+ });
192
+ },
193
+ };
194
+ }
@@ -1,3 +1,9 @@
1
+ import {
2
+ SESSION_CORE_HANDLERS,
3
+ SESSION_CORE_STREAMING_HANDLERS,
4
+ } from "./session-core-protocol.js";
5
+ import { VIDEO_HANDLERS, VIDEO_STREAMING_HANDLERS } from "./video-protocol.js";
6
+
1
7
  export function createWsMessageDispatcher(server) {
2
8
  return {
3
9
  async dispatch(clientId, ws, message) {
@@ -86,6 +92,123 @@ export function createWsMessageDispatcher(server) {
86
92
  "task-graph-state": () => server._handleTaskGraphState(id, ws, message),
87
93
  };
88
94
 
95
+ // Phase I — Hosted Session API streaming routes (stream.run).
96
+ // Each intermediate event goes out as { id, type: "stream.event", event }
97
+ // and the final response is sent by the normal ok/err wrapper.
98
+ for (const streamingType of Object.keys(
99
+ SESSION_CORE_STREAMING_HANDLERS,
100
+ )) {
101
+ routes[streamingType] = async () => {
102
+ const controller = new AbortController();
103
+ const client = server.clients.get(clientId);
104
+ if (client) {
105
+ client._streamAborts = client._streamAborts || new Map();
106
+ client._streamAborts.set(id, controller);
107
+ }
108
+ const sender = (payload) => server._send(ws, { id, ...payload });
109
+ const context = { server, ws, clientId };
110
+ try {
111
+ const result = await SESSION_CORE_STREAMING_HANDLERS[streamingType](
112
+ message,
113
+ sender,
114
+ controller.signal,
115
+ context,
116
+ );
117
+ server._send(ws, {
118
+ id,
119
+ type: `${streamingType}.end`,
120
+ ...result,
121
+ });
122
+ } catch (err) {
123
+ server._send(ws, {
124
+ id,
125
+ type: "error",
126
+ code: "STREAM_RUN_ERROR",
127
+ message: err?.message || String(err),
128
+ });
129
+ } finally {
130
+ if (client?._streamAborts) client._streamAborts.delete(id);
131
+ }
132
+ };
133
+ }
134
+
135
+ // Video Editing streaming routes
136
+ for (const videoStreamType of Object.keys(VIDEO_STREAMING_HANDLERS)) {
137
+ routes[videoStreamType] = async () => {
138
+ const controller = new AbortController();
139
+ const client = server.clients.get(clientId);
140
+ if (client) {
141
+ client._streamAborts = client._streamAborts || new Map();
142
+ client._streamAborts.set(id, controller);
143
+ }
144
+ const sender = (payload) => server._send(ws, { id, ...payload });
145
+ try {
146
+ const result = await VIDEO_STREAMING_HANDLERS[videoStreamType](
147
+ message,
148
+ sender,
149
+ controller.signal,
150
+ );
151
+ server._send(ws, {
152
+ id,
153
+ type: `${videoStreamType}.end`,
154
+ ...result,
155
+ });
156
+ } catch (err) {
157
+ server._send(ws, {
158
+ id,
159
+ type: "error",
160
+ code: "VIDEO_STREAM_ERROR",
161
+ message: err?.message || String(err),
162
+ });
163
+ } finally {
164
+ if (client?._streamAborts) client._streamAborts.delete(id);
165
+ }
166
+ };
167
+ }
168
+
169
+ // Video Editing request/response routes
170
+ for (const videoType of Object.keys(VIDEO_HANDLERS)) {
171
+ routes[videoType] = async () => {
172
+ try {
173
+ const result = await VIDEO_HANDLERS[videoType](message);
174
+ server._send(ws, {
175
+ id,
176
+ type: `${videoType}.response`,
177
+ ...result,
178
+ });
179
+ } catch (err) {
180
+ server._send(ws, {
181
+ id,
182
+ type: "error",
183
+ code: "VIDEO_ERROR",
184
+ message: err?.message || String(err),
185
+ });
186
+ }
187
+ };
188
+ }
189
+
190
+ // Phase I — Hosted Session API (session-core, memory, beta, usage)
191
+ for (const sessionCoreType of Object.keys(SESSION_CORE_HANDLERS)) {
192
+ routes[sessionCoreType] = async () => {
193
+ try {
194
+ const result =
195
+ await SESSION_CORE_HANDLERS[sessionCoreType](message);
196
+ server._send(ws, {
197
+ id,
198
+ type: `${sessionCoreType}.response`,
199
+ ...result,
200
+ });
201
+ } catch (err) {
202
+ server._send(ws, {
203
+ id,
204
+ type: "error",
205
+ code: "SESSION_CORE_ERROR",
206
+ message: err?.message || String(err),
207
+ });
208
+ }
209
+ };
210
+ }
211
+
89
212
  const handler = routes[type];
90
213
  if (!handler) {
91
214
  server._send(ws, {