@sna-sdk/core 0.7.1 → 0.8.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/dist/scripts/sna.js +3 -1
- package/dist/server/api-types.d.ts +2 -2
- package/dist/server/routes/agent.js +8 -4
- package/dist/server/session-manager.d.ts +8 -1
- package/dist/server/session-manager.js +35 -18
- package/dist/server/standalone.js +51 -26
- package/dist/server/ws.js +7 -3
- package/package.json +1 -1
package/dist/scripts/sna.js
CHANGED
|
@@ -1008,7 +1008,9 @@ Run "sna help submit" for data submission patterns.`);
|
|
|
1008
1008
|
cmdApiUp();
|
|
1009
1009
|
break;
|
|
1010
1010
|
case "tu":
|
|
1011
|
-
|
|
1011
|
+
console.log(' "sna tu" has moved to @sna-sdk/testing.');
|
|
1012
|
+
console.log(' Install it and use "sna-test" instead.');
|
|
1013
|
+
console.log(' e.g. sna-test api:up, sna-test claude "hello"');
|
|
1012
1014
|
break;
|
|
1013
1015
|
case "restart":
|
|
1014
1016
|
cmdDown();
|
|
@@ -49,7 +49,7 @@ interface ApiResponses {
|
|
|
49
49
|
};
|
|
50
50
|
"agent.set-permission-mode": {
|
|
51
51
|
status: "updated" | "no_session";
|
|
52
|
-
permissionMode
|
|
52
|
+
permissionMode?: string;
|
|
53
53
|
};
|
|
54
54
|
"agent.kill": {
|
|
55
55
|
status: "killed" | "no_session";
|
|
@@ -69,7 +69,7 @@ interface ApiResponses {
|
|
|
69
69
|
config: {
|
|
70
70
|
provider: string;
|
|
71
71
|
model: string;
|
|
72
|
-
permissionMode
|
|
72
|
+
permissionMode?: string;
|
|
73
73
|
extraArgs?: string[];
|
|
74
74
|
} | null;
|
|
75
75
|
};
|
|
@@ -142,7 +142,7 @@ function createAgentRoutes(sessionManager) {
|
|
|
142
142
|
}
|
|
143
143
|
const providerName = body.provider ?? "claude-code";
|
|
144
144
|
const model = body.model ?? "claude-sonnet-4-6";
|
|
145
|
-
const permissionMode = body.permissionMode
|
|
145
|
+
const permissionMode = body.permissionMode;
|
|
146
146
|
const extraArgs = body.extraArgs;
|
|
147
147
|
try {
|
|
148
148
|
const proc = provider.spawn({
|
|
@@ -253,7 +253,7 @@ function createAgentRoutes(sessionManager) {
|
|
|
253
253
|
} else {
|
|
254
254
|
cursor = session.eventCounter;
|
|
255
255
|
}
|
|
256
|
-
while (queue.length > 0 && queue[0].cursor <= cursor) queue.shift();
|
|
256
|
+
while (queue.length > 0 && queue[0].cursor !== -1 && queue[0].cursor <= cursor) queue.shift();
|
|
257
257
|
while (!signal.aborted) {
|
|
258
258
|
if (queue.length === 0) {
|
|
259
259
|
await Promise.race([
|
|
@@ -267,7 +267,11 @@ function createAgentRoutes(sessionManager) {
|
|
|
267
267
|
if (queue.length > 0) {
|
|
268
268
|
while (queue.length > 0) {
|
|
269
269
|
const item = queue.shift();
|
|
270
|
-
|
|
270
|
+
if (item.cursor === -1) {
|
|
271
|
+
await stream.writeSSE({ data: JSON.stringify(item.event) });
|
|
272
|
+
} else {
|
|
273
|
+
await stream.writeSSE({ id: String(item.cursor), data: JSON.stringify(item.event) });
|
|
274
|
+
}
|
|
271
275
|
}
|
|
272
276
|
} else {
|
|
273
277
|
await stream.writeSSE({ data: "" });
|
|
@@ -318,7 +322,7 @@ function createAgentRoutes(sessionManager) {
|
|
|
318
322
|
}
|
|
319
323
|
const providerName = body.provider ?? "claude-code";
|
|
320
324
|
const model = body.model ?? session.lastStartConfig?.model ?? "claude-sonnet-4-6";
|
|
321
|
-
const permissionMode = body.permissionMode ?? session.lastStartConfig?.permissionMode
|
|
325
|
+
const permissionMode = body.permissionMode ?? session.lastStartConfig?.permissionMode;
|
|
322
326
|
const extraArgs = body.extraArgs ?? session.lastStartConfig?.extraArgs;
|
|
323
327
|
const provider = getProvider(providerName);
|
|
324
328
|
try {
|
|
@@ -11,7 +11,7 @@ type SessionState = "idle" | "processing" | "waiting" | "permission";
|
|
|
11
11
|
interface StartConfig {
|
|
12
12
|
provider: string;
|
|
13
13
|
model: string;
|
|
14
|
-
permissionMode
|
|
14
|
+
permissionMode?: string;
|
|
15
15
|
extraArgs?: string[];
|
|
16
16
|
}
|
|
17
17
|
interface Session {
|
|
@@ -108,6 +108,12 @@ declare class SessionManager {
|
|
|
108
108
|
/** Broadcast a skill event to all subscribers (called after DB insert). */
|
|
109
109
|
broadcastSkillEvent(event: Record<string, unknown>): void;
|
|
110
110
|
/** Push a synthetic event into a session's event stream (for user message broadcast). */
|
|
111
|
+
/**
|
|
112
|
+
* Push an externally-persisted event into the session.
|
|
113
|
+
* The caller is responsible for DB persistence — this method only updates
|
|
114
|
+
* the in-memory counter/buffer and notifies listeners.
|
|
115
|
+
* eventCounter increments to stay in sync with the DB row count.
|
|
116
|
+
*/
|
|
111
117
|
pushEvent(sessionId: string, event: AgentEvent): void;
|
|
112
118
|
/** Subscribe to permission request notifications. Returns unsubscribe function. */
|
|
113
119
|
onPermissionRequest(cb: (sessionId: string, request: Record<string, unknown>, createdAt: number) => void): () => void;
|
|
@@ -165,6 +171,7 @@ declare class SessionManager {
|
|
|
165
171
|
touch(id: string): void;
|
|
166
172
|
/** Persist an agent event to chat_messages. */
|
|
167
173
|
private getMessageStats;
|
|
174
|
+
/** Persist an agent event to chat_messages. Returns true if a row was inserted. */
|
|
168
175
|
private persistEvent;
|
|
169
176
|
/** Kill all sessions. Used during shutdown. */
|
|
170
177
|
killAll(): void;
|
|
@@ -143,22 +143,27 @@ class SessionManager {
|
|
|
143
143
|
}
|
|
144
144
|
this.setSessionState(sessionId, session, "waiting");
|
|
145
145
|
}
|
|
146
|
-
if (e.type !== "assistant_delta") {
|
|
147
|
-
session.eventBuffer.push(e);
|
|
148
|
-
if (session.eventBuffer.length > MAX_EVENT_BUFFER) {
|
|
149
|
-
session.eventBuffer.splice(0, session.eventBuffer.length - MAX_EVENT_BUFFER);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
session.eventCounter++;
|
|
153
146
|
if (e.type === "thinking" || e.type === "tool_use" || e.type === "assistant_delta") {
|
|
154
147
|
this.setSessionState(sessionId, session, "processing");
|
|
155
148
|
} else if (e.type === "complete" || e.type === "error" || e.type === "interrupted") {
|
|
156
149
|
this.setSessionState(sessionId, session, "waiting");
|
|
157
150
|
}
|
|
158
|
-
this.persistEvent(sessionId, e);
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
151
|
+
const persisted = this.persistEvent(sessionId, e);
|
|
152
|
+
if (persisted) {
|
|
153
|
+
session.eventCounter++;
|
|
154
|
+
session.eventBuffer.push(e);
|
|
155
|
+
if (session.eventBuffer.length > MAX_EVENT_BUFFER) {
|
|
156
|
+
session.eventBuffer.splice(0, session.eventBuffer.length - MAX_EVENT_BUFFER);
|
|
157
|
+
}
|
|
158
|
+
const listeners = this.eventListeners.get(sessionId);
|
|
159
|
+
if (listeners) {
|
|
160
|
+
for (const cb of listeners) cb(session.eventCounter, e);
|
|
161
|
+
}
|
|
162
|
+
} else if (e.type === "assistant_delta") {
|
|
163
|
+
const listeners = this.eventListeners.get(sessionId);
|
|
164
|
+
if (listeners) {
|
|
165
|
+
for (const cb of listeners) cb(-1, e);
|
|
166
|
+
}
|
|
162
167
|
}
|
|
163
168
|
});
|
|
164
169
|
proc.on("exit", (code) => {
|
|
@@ -196,11 +201,17 @@ class SessionManager {
|
|
|
196
201
|
for (const cb of this.skillEventListeners) cb(event);
|
|
197
202
|
}
|
|
198
203
|
/** Push a synthetic event into a session's event stream (for user message broadcast). */
|
|
204
|
+
/**
|
|
205
|
+
* Push an externally-persisted event into the session.
|
|
206
|
+
* The caller is responsible for DB persistence — this method only updates
|
|
207
|
+
* the in-memory counter/buffer and notifies listeners.
|
|
208
|
+
* eventCounter increments to stay in sync with the DB row count.
|
|
209
|
+
*/
|
|
199
210
|
pushEvent(sessionId, event) {
|
|
200
211
|
const session = this.sessions.get(sessionId);
|
|
201
212
|
if (!session) return;
|
|
202
|
-
session.eventBuffer.push(event);
|
|
203
213
|
session.eventCounter++;
|
|
214
|
+
session.eventBuffer.push(event);
|
|
204
215
|
if (session.eventBuffer.length > MAX_EVENT_BUFFER) {
|
|
205
216
|
session.eventBuffer.splice(0, session.eventBuffer.length - MAX_EVENT_BUFFER);
|
|
206
217
|
}
|
|
@@ -425,6 +436,7 @@ class SessionManager {
|
|
|
425
436
|
return { messageCount: 0, lastMessage: null };
|
|
426
437
|
}
|
|
427
438
|
}
|
|
439
|
+
/** Persist an agent event to chat_messages. Returns true if a row was inserted. */
|
|
428
440
|
persistEvent(sessionId, e) {
|
|
429
441
|
try {
|
|
430
442
|
const db = getDb();
|
|
@@ -432,29 +444,34 @@ class SessionManager {
|
|
|
432
444
|
case "assistant":
|
|
433
445
|
if (e.message) {
|
|
434
446
|
db.prepare(`INSERT INTO chat_messages (session_id, role, content) VALUES (?, 'assistant', ?)`).run(sessionId, e.message);
|
|
447
|
+
return true;
|
|
435
448
|
}
|
|
436
|
-
|
|
449
|
+
return false;
|
|
437
450
|
case "thinking":
|
|
438
451
|
if (e.message) {
|
|
439
452
|
db.prepare(`INSERT INTO chat_messages (session_id, role, content) VALUES (?, 'thinking', ?)`).run(sessionId, e.message);
|
|
453
|
+
return true;
|
|
440
454
|
}
|
|
441
|
-
|
|
455
|
+
return false;
|
|
442
456
|
case "tool_use": {
|
|
443
457
|
const toolName = e.data?.toolName ?? e.message ?? "tool";
|
|
444
458
|
db.prepare(`INSERT INTO chat_messages (session_id, role, content, meta) VALUES (?, 'tool', ?, ?)`).run(sessionId, toolName, JSON.stringify(e.data ?? {}));
|
|
445
|
-
|
|
459
|
+
return true;
|
|
446
460
|
}
|
|
447
461
|
case "tool_result":
|
|
448
462
|
db.prepare(`INSERT INTO chat_messages (session_id, role, content, meta) VALUES (?, 'tool_result', ?, ?)`).run(sessionId, e.message ?? "", JSON.stringify(e.data ?? {}));
|
|
449
|
-
|
|
463
|
+
return true;
|
|
450
464
|
case "complete":
|
|
451
465
|
db.prepare(`INSERT INTO chat_messages (session_id, role, content, meta) VALUES (?, 'status', '', ?)`).run(sessionId, JSON.stringify({ status: "complete", ...e.data }));
|
|
452
|
-
|
|
466
|
+
return true;
|
|
453
467
|
case "error":
|
|
454
468
|
db.prepare(`INSERT INTO chat_messages (session_id, role, content, meta) VALUES (?, 'error', ?, ?)`).run(sessionId, e.message ?? "Error", JSON.stringify({ status: "error" }));
|
|
455
|
-
|
|
469
|
+
return true;
|
|
470
|
+
default:
|
|
471
|
+
return false;
|
|
456
472
|
}
|
|
457
473
|
} catch {
|
|
474
|
+
return false;
|
|
458
475
|
}
|
|
459
476
|
}
|
|
460
477
|
/** Kill all sessions. Used during shutdown. */
|
|
@@ -1004,7 +1004,7 @@ function createAgentRoutes(sessionManager2) {
|
|
|
1004
1004
|
}
|
|
1005
1005
|
const providerName = body.provider ?? "claude-code";
|
|
1006
1006
|
const model = body.model ?? "claude-sonnet-4-6";
|
|
1007
|
-
const permissionMode2 = body.permissionMode
|
|
1007
|
+
const permissionMode2 = body.permissionMode;
|
|
1008
1008
|
const extraArgs = body.extraArgs;
|
|
1009
1009
|
try {
|
|
1010
1010
|
const proc = provider2.spawn({
|
|
@@ -1115,7 +1115,7 @@ function createAgentRoutes(sessionManager2) {
|
|
|
1115
1115
|
} else {
|
|
1116
1116
|
cursor = session.eventCounter;
|
|
1117
1117
|
}
|
|
1118
|
-
while (queue.length > 0 && queue[0].cursor <= cursor) queue.shift();
|
|
1118
|
+
while (queue.length > 0 && queue[0].cursor !== -1 && queue[0].cursor <= cursor) queue.shift();
|
|
1119
1119
|
while (!signal.aborted) {
|
|
1120
1120
|
if (queue.length === 0) {
|
|
1121
1121
|
await Promise.race([
|
|
@@ -1129,7 +1129,11 @@ function createAgentRoutes(sessionManager2) {
|
|
|
1129
1129
|
if (queue.length > 0) {
|
|
1130
1130
|
while (queue.length > 0) {
|
|
1131
1131
|
const item = queue.shift();
|
|
1132
|
-
|
|
1132
|
+
if (item.cursor === -1) {
|
|
1133
|
+
await stream.writeSSE({ data: JSON.stringify(item.event) });
|
|
1134
|
+
} else {
|
|
1135
|
+
await stream.writeSSE({ id: String(item.cursor), data: JSON.stringify(item.event) });
|
|
1136
|
+
}
|
|
1133
1137
|
}
|
|
1134
1138
|
} else {
|
|
1135
1139
|
await stream.writeSSE({ data: "" });
|
|
@@ -1180,7 +1184,7 @@ function createAgentRoutes(sessionManager2) {
|
|
|
1180
1184
|
}
|
|
1181
1185
|
const providerName = body.provider ?? "claude-code";
|
|
1182
1186
|
const model = body.model ?? session.lastStartConfig?.model ?? "claude-sonnet-4-6";
|
|
1183
|
-
const permissionMode2 = body.permissionMode ?? session.lastStartConfig?.permissionMode
|
|
1187
|
+
const permissionMode2 = body.permissionMode ?? session.lastStartConfig?.permissionMode;
|
|
1184
1188
|
const extraArgs = body.extraArgs ?? session.lastStartConfig?.extraArgs;
|
|
1185
1189
|
const provider2 = getProvider(providerName);
|
|
1186
1190
|
try {
|
|
@@ -1544,22 +1548,27 @@ var SessionManager = class {
|
|
|
1544
1548
|
}
|
|
1545
1549
|
this.setSessionState(sessionId, session, "waiting");
|
|
1546
1550
|
}
|
|
1547
|
-
if (e.type !== "assistant_delta") {
|
|
1548
|
-
session.eventBuffer.push(e);
|
|
1549
|
-
if (session.eventBuffer.length > MAX_EVENT_BUFFER) {
|
|
1550
|
-
session.eventBuffer.splice(0, session.eventBuffer.length - MAX_EVENT_BUFFER);
|
|
1551
|
-
}
|
|
1552
|
-
}
|
|
1553
|
-
session.eventCounter++;
|
|
1554
1551
|
if (e.type === "thinking" || e.type === "tool_use" || e.type === "assistant_delta") {
|
|
1555
1552
|
this.setSessionState(sessionId, session, "processing");
|
|
1556
1553
|
} else if (e.type === "complete" || e.type === "error" || e.type === "interrupted") {
|
|
1557
1554
|
this.setSessionState(sessionId, session, "waiting");
|
|
1558
1555
|
}
|
|
1559
|
-
this.persistEvent(sessionId, e);
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1556
|
+
const persisted = this.persistEvent(sessionId, e);
|
|
1557
|
+
if (persisted) {
|
|
1558
|
+
session.eventCounter++;
|
|
1559
|
+
session.eventBuffer.push(e);
|
|
1560
|
+
if (session.eventBuffer.length > MAX_EVENT_BUFFER) {
|
|
1561
|
+
session.eventBuffer.splice(0, session.eventBuffer.length - MAX_EVENT_BUFFER);
|
|
1562
|
+
}
|
|
1563
|
+
const listeners = this.eventListeners.get(sessionId);
|
|
1564
|
+
if (listeners) {
|
|
1565
|
+
for (const cb of listeners) cb(session.eventCounter, e);
|
|
1566
|
+
}
|
|
1567
|
+
} else if (e.type === "assistant_delta") {
|
|
1568
|
+
const listeners = this.eventListeners.get(sessionId);
|
|
1569
|
+
if (listeners) {
|
|
1570
|
+
for (const cb of listeners) cb(-1, e);
|
|
1571
|
+
}
|
|
1563
1572
|
}
|
|
1564
1573
|
});
|
|
1565
1574
|
proc.on("exit", (code) => {
|
|
@@ -1597,11 +1606,17 @@ var SessionManager = class {
|
|
|
1597
1606
|
for (const cb of this.skillEventListeners) cb(event);
|
|
1598
1607
|
}
|
|
1599
1608
|
/** Push a synthetic event into a session's event stream (for user message broadcast). */
|
|
1609
|
+
/**
|
|
1610
|
+
* Push an externally-persisted event into the session.
|
|
1611
|
+
* The caller is responsible for DB persistence — this method only updates
|
|
1612
|
+
* the in-memory counter/buffer and notifies listeners.
|
|
1613
|
+
* eventCounter increments to stay in sync with the DB row count.
|
|
1614
|
+
*/
|
|
1600
1615
|
pushEvent(sessionId, event) {
|
|
1601
1616
|
const session = this.sessions.get(sessionId);
|
|
1602
1617
|
if (!session) return;
|
|
1603
|
-
session.eventBuffer.push(event);
|
|
1604
1618
|
session.eventCounter++;
|
|
1619
|
+
session.eventBuffer.push(event);
|
|
1605
1620
|
if (session.eventBuffer.length > MAX_EVENT_BUFFER) {
|
|
1606
1621
|
session.eventBuffer.splice(0, session.eventBuffer.length - MAX_EVENT_BUFFER);
|
|
1607
1622
|
}
|
|
@@ -1826,6 +1841,7 @@ var SessionManager = class {
|
|
|
1826
1841
|
return { messageCount: 0, lastMessage: null };
|
|
1827
1842
|
}
|
|
1828
1843
|
}
|
|
1844
|
+
/** Persist an agent event to chat_messages. Returns true if a row was inserted. */
|
|
1829
1845
|
persistEvent(sessionId, e) {
|
|
1830
1846
|
try {
|
|
1831
1847
|
const db = getDb();
|
|
@@ -1833,29 +1849,34 @@ var SessionManager = class {
|
|
|
1833
1849
|
case "assistant":
|
|
1834
1850
|
if (e.message) {
|
|
1835
1851
|
db.prepare(`INSERT INTO chat_messages (session_id, role, content) VALUES (?, 'assistant', ?)`).run(sessionId, e.message);
|
|
1852
|
+
return true;
|
|
1836
1853
|
}
|
|
1837
|
-
|
|
1854
|
+
return false;
|
|
1838
1855
|
case "thinking":
|
|
1839
1856
|
if (e.message) {
|
|
1840
1857
|
db.prepare(`INSERT INTO chat_messages (session_id, role, content) VALUES (?, 'thinking', ?)`).run(sessionId, e.message);
|
|
1858
|
+
return true;
|
|
1841
1859
|
}
|
|
1842
|
-
|
|
1860
|
+
return false;
|
|
1843
1861
|
case "tool_use": {
|
|
1844
1862
|
const toolName = e.data?.toolName ?? e.message ?? "tool";
|
|
1845
1863
|
db.prepare(`INSERT INTO chat_messages (session_id, role, content, meta) VALUES (?, 'tool', ?, ?)`).run(sessionId, toolName, JSON.stringify(e.data ?? {}));
|
|
1846
|
-
|
|
1864
|
+
return true;
|
|
1847
1865
|
}
|
|
1848
1866
|
case "tool_result":
|
|
1849
1867
|
db.prepare(`INSERT INTO chat_messages (session_id, role, content, meta) VALUES (?, 'tool_result', ?, ?)`).run(sessionId, e.message ?? "", JSON.stringify(e.data ?? {}));
|
|
1850
|
-
|
|
1868
|
+
return true;
|
|
1851
1869
|
case "complete":
|
|
1852
1870
|
db.prepare(`INSERT INTO chat_messages (session_id, role, content, meta) VALUES (?, 'status', '', ?)`).run(sessionId, JSON.stringify({ status: "complete", ...e.data }));
|
|
1853
|
-
|
|
1871
|
+
return true;
|
|
1854
1872
|
case "error":
|
|
1855
1873
|
db.prepare(`INSERT INTO chat_messages (session_id, role, content, meta) VALUES (?, 'error', ?, ?)`).run(sessionId, e.message ?? "Error", JSON.stringify({ status: "error" }));
|
|
1856
|
-
|
|
1874
|
+
return true;
|
|
1875
|
+
default:
|
|
1876
|
+
return false;
|
|
1857
1877
|
}
|
|
1858
1878
|
} catch {
|
|
1879
|
+
return false;
|
|
1859
1880
|
}
|
|
1860
1881
|
}
|
|
1861
1882
|
/** Kill all sessions. Used during shutdown. */
|
|
@@ -2084,7 +2105,7 @@ function handleAgentStart(ws, msg, sm) {
|
|
|
2084
2105
|
}
|
|
2085
2106
|
const providerName = msg.provider ?? "claude-code";
|
|
2086
2107
|
const model = msg.model ?? "claude-sonnet-4-6";
|
|
2087
|
-
const permissionMode2 = msg.permissionMode
|
|
2108
|
+
const permissionMode2 = msg.permissionMode;
|
|
2088
2109
|
const extraArgs = msg.extraArgs;
|
|
2089
2110
|
try {
|
|
2090
2111
|
const proc = provider2.spawn({
|
|
@@ -2159,7 +2180,7 @@ function handleAgentResume(ws, msg, sm) {
|
|
|
2159
2180
|
}
|
|
2160
2181
|
const providerName = msg.provider ?? session.lastStartConfig?.provider ?? "claude-code";
|
|
2161
2182
|
const model = msg.model ?? session.lastStartConfig?.model ?? "claude-sonnet-4-6";
|
|
2162
|
-
const permissionMode2 = msg.permissionMode ?? session.lastStartConfig?.permissionMode
|
|
2183
|
+
const permissionMode2 = msg.permissionMode ?? session.lastStartConfig?.permissionMode;
|
|
2163
2184
|
const extraArgs = msg.extraArgs ?? session.lastStartConfig?.extraArgs;
|
|
2164
2185
|
const provider2 = getProvider(providerName);
|
|
2165
2186
|
try {
|
|
@@ -2326,7 +2347,11 @@ function handleAgentSubscribe(ws, msg, sm, state) {
|
|
|
2326
2347
|
}
|
|
2327
2348
|
}
|
|
2328
2349
|
const unsub = sm.onSessionEvent(sessionId, (eventCursor, event) => {
|
|
2329
|
-
|
|
2350
|
+
if (eventCursor === -1) {
|
|
2351
|
+
send(ws, { type: "agent.event", session: sessionId, event });
|
|
2352
|
+
} else {
|
|
2353
|
+
send(ws, { type: "agent.event", session: sessionId, cursor: eventCursor, event });
|
|
2354
|
+
}
|
|
2330
2355
|
});
|
|
2331
2356
|
state.agentUnsubs.set(sessionId, unsub);
|
|
2332
2357
|
reply(ws, msg, { cursor });
|
|
@@ -2562,7 +2587,7 @@ try {
|
|
|
2562
2587
|
process.exit(1);
|
|
2563
2588
|
}
|
|
2564
2589
|
var port = parseInt(process.env.SNA_PORT ?? "3099", 10);
|
|
2565
|
-
var permissionMode = process.env.SNA_PERMISSION_MODE
|
|
2590
|
+
var permissionMode = process.env.SNA_PERMISSION_MODE;
|
|
2566
2591
|
var defaultModel = process.env.SNA_MODEL ?? "claude-sonnet-4-6";
|
|
2567
2592
|
var maxSessions = parseInt(process.env.SNA_MAX_SESSIONS ?? "5", 10);
|
|
2568
2593
|
var root = new Hono4();
|
package/dist/server/ws.js
CHANGED
|
@@ -217,7 +217,7 @@ function handleAgentStart(ws, msg, sm) {
|
|
|
217
217
|
}
|
|
218
218
|
const providerName = msg.provider ?? "claude-code";
|
|
219
219
|
const model = msg.model ?? "claude-sonnet-4-6";
|
|
220
|
-
const permissionMode = msg.permissionMode
|
|
220
|
+
const permissionMode = msg.permissionMode;
|
|
221
221
|
const extraArgs = msg.extraArgs;
|
|
222
222
|
try {
|
|
223
223
|
const proc = provider.spawn({
|
|
@@ -292,7 +292,7 @@ function handleAgentResume(ws, msg, sm) {
|
|
|
292
292
|
}
|
|
293
293
|
const providerName = msg.provider ?? session.lastStartConfig?.provider ?? "claude-code";
|
|
294
294
|
const model = msg.model ?? session.lastStartConfig?.model ?? "claude-sonnet-4-6";
|
|
295
|
-
const permissionMode = msg.permissionMode ?? session.lastStartConfig?.permissionMode
|
|
295
|
+
const permissionMode = msg.permissionMode ?? session.lastStartConfig?.permissionMode;
|
|
296
296
|
const extraArgs = msg.extraArgs ?? session.lastStartConfig?.extraArgs;
|
|
297
297
|
const provider = getProvider(providerName);
|
|
298
298
|
try {
|
|
@@ -459,7 +459,11 @@ function handleAgentSubscribe(ws, msg, sm, state) {
|
|
|
459
459
|
}
|
|
460
460
|
}
|
|
461
461
|
const unsub = sm.onSessionEvent(sessionId, (eventCursor, event) => {
|
|
462
|
-
|
|
462
|
+
if (eventCursor === -1) {
|
|
463
|
+
send(ws, { type: "agent.event", session: sessionId, event });
|
|
464
|
+
} else {
|
|
465
|
+
send(ws, { type: "agent.event", session: sessionId, cursor: eventCursor, event });
|
|
466
|
+
}
|
|
463
467
|
});
|
|
464
468
|
state.agentUnsubs.set(sessionId, unsub);
|
|
465
469
|
reply(ws, msg, { cursor });
|