sparkecoder 0.1.65 → 0.1.66
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/agent/index.d.ts +3 -3
- package/dist/agent/index.js +31 -28
- package/dist/agent/index.js.map +1 -1
- package/dist/cli.js +96 -118
- package/dist/cli.js.map +1 -1
- package/dist/db/index.d.ts +2 -2
- package/dist/{index-BhKQYdOx.d.ts → index-Db23cukG.d.ts} +25 -25
- package/dist/index.d.ts +5 -5
- package/dist/index.js +96 -118
- package/dist/index.js.map +1 -1
- package/dist/{schema-XcP0dedO.d.ts → schema-C7Mm4Ykn.d.ts} +3 -3
- package/dist/{search-DkNNtC5A.d.ts → search-CVVfuBPZ.d.ts} +5 -4
- package/dist/server/index.js +96 -118
- package/dist/server/index.js.map +1 -1
- package/dist/tools/index.d.ts +3 -3
- package/dist/tools/index.js +16 -11
- package/dist/tools/index.js.map +1 -1
- package/package.json +1 -1
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/standalone/web/.next/BUILD_ID +1 -1
- package/web/.next/standalone/web/.next/build-manifest.json +2 -2
- package/web/.next/standalone/web/.next/prerender-manifest.json +3 -3
- package/web/.next/standalone/web/.next/server/app/(main)/page.js.nft.json +1 -1
- package/web/.next/standalone/web/.next/server/app/(main)/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/app/(main)/session/[id]/page.js.nft.json +1 -1
- package/web/.next/standalone/web/.next/server/app/(main)/session/[id]/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/standalone/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.html +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/installation/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/installation.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_full.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_index.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_tree.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/skills.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_full.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_index.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_tree.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/tools.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_full.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_index.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_tree.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs.segments/_full.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_index.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs.segments/_tree.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs.segments/docs/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/embed/[id]/page.js.nft.json +1 -1
- package/web/.next/standalone/web/.next/server/app/embed/[id]/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/app/index.html +1 -1
- package/web/.next/standalone/web/.next/server/app/index.rsc +4 -4
- package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p/__PAGE__.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/index.segments/_full.segment.rsc +4 -4
- package/web/.next/standalone/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/_index.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_708e1a2e._.js → 2374f_02a118f9._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_3db08933._.js → 2374f_0ed477f8._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_7d957e38._.js → 2374f_12bad06e._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_1225fb9d._.js → 2374f_2526ca80._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_95e53328._.js → 2374f_3b51a934._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_f1f229dd._.js → 2374f_3e519469._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_a19628a3._.js → 2374f_5ebfcf1a._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_a90b70ee._.js → 2374f_a0f483d1._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_2775224f._.js → 2374f_acf3dfe4._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_32fd5733._.js → 2374f_ad08e83a._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_2eac907f._.js → 2374f_c1d54c16._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_51500fd2._.js → 2374f_db3e363b._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_8385a57b._.js → 2374f_f0d7e130._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_6f1ea3a7._.js → 2374f_fc992d90._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{[root-of-the-server]__5bde4c40._.js → [root-of-the-server]__06818a54._.js} +2 -2
- package/web/.next/standalone/web/.next/server/chunks/ssr/{[root-of-the-server]__4085bf35._.js → [root-of-the-server]__c71f29f9._.js} +4 -4
- package/web/.next/standalone/web/.next/server/chunks/ssr/web_2b3a5919._.js +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/web_38156da8._.js +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/web_5cca707f._.js +7 -0
- package/web/.next/standalone/web/.next/server/chunks/ssr/web_935e81f5._.js +7 -0
- package/web/.next/standalone/web/.next/server/chunks/ssr/{web_14735895._.js → web_cc5f7515._.js} +2 -2
- package/web/.next/standalone/web/.next/server/pages/404.html +1 -1
- package/web/.next/standalone/web/.next/server/pages/500.html +2 -2
- package/web/.next/standalone/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/server-reference-manifest.json +1 -1
- package/web/.next/{static/chunks/4b6a9454bc6460c5.js → standalone/web/.next/static/chunks/31208ade542a0fcb.js} +3 -3
- package/web/.next/{static/chunks/4a490bc538aa0940.js → standalone/web/.next/static/chunks/4e673433173ad456.js} +3 -3
- package/web/.next/standalone/web/.next/static/chunks/{c2dccd8f56d8eb5a.js → 515f0c0bd6087843.js} +5 -5
- package/web/.next/standalone/web/.next/static/chunks/fd39dd62879495e1.css +1 -0
- package/web/.next/standalone/web/.next/static/static/chunks/{4b6a9454bc6460c5.js → 31208ade542a0fcb.js} +3 -3
- package/web/.next/standalone/web/.next/static/static/chunks/{4a490bc538aa0940.js → 4e673433173ad456.js} +3 -3
- package/web/.next/standalone/web/.next/static/static/chunks/{c2dccd8f56d8eb5a.js → 515f0c0bd6087843.js} +5 -5
- package/web/.next/standalone/web/.next/static/static/chunks/fd39dd62879495e1.css +1 -0
- package/web/.next/standalone/web/src/components/chat-interface.tsx +96 -1
- package/web/.next/standalone/web/src/lib/api.ts +24 -0
- package/web/.next/{standalone/web/.next/static/chunks/4b6a9454bc6460c5.js → static/chunks/31208ade542a0fcb.js} +3 -3
- package/web/.next/{standalone/web/.next/static/chunks/4a490bc538aa0940.js → static/chunks/4e673433173ad456.js} +3 -3
- package/web/.next/static/chunks/{c2dccd8f56d8eb5a.js → 515f0c0bd6087843.js} +5 -5
- package/web/.next/static/chunks/fd39dd62879495e1.css +1 -0
- package/web/.next/standalone/web/.next/server/chunks/ssr/web_08bbd8c8._.js +0 -7
- package/web/.next/standalone/web/.next/server/chunks/ssr/web_c729ad51._.js +0 -7
- package/web/.next/standalone/web/.next/static/chunks/8b53c110c5a6f9a0.css +0 -1
- package/web/.next/standalone/web/.next/static/static/chunks/8b53c110c5a6f9a0.css +0 -1
- package/web/.next/static/chunks/8b53c110c5a6f9a0.css +0 -1
- /package/web/.next/standalone/web/.next/static/{NuySHGSR0CchKU9zo42LK → UMGGmtMDTCI6fL-AIFkiM}/_buildManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/{NuySHGSR0CchKU9zo42LK → UMGGmtMDTCI6fL-AIFkiM}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/web/.next/static/{NuySHGSR0CchKU9zo42LK → UMGGmtMDTCI6fL-AIFkiM}/_ssgManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/static/{NuySHGSR0CchKU9zo42LK → UMGGmtMDTCI6fL-AIFkiM}/_buildManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/static/{NuySHGSR0CchKU9zo42LK → UMGGmtMDTCI6fL-AIFkiM}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/web/.next/static/static/{NuySHGSR0CchKU9zo42LK → UMGGmtMDTCI6fL-AIFkiM}/_ssgManifest.js +0 -0
- /package/web/.next/static/{NuySHGSR0CchKU9zo42LK → UMGGmtMDTCI6fL-AIFkiM}/_buildManifest.js +0 -0
- /package/web/.next/static/{NuySHGSR0CchKU9zo42LK → UMGGmtMDTCI6fL-AIFkiM}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{NuySHGSR0CchKU9zo42LK → UMGGmtMDTCI6fL-AIFkiM}/_ssgManifest.js +0 -0
|
@@ -85,7 +85,7 @@ declare const sessions: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
85
85
|
tableName: "sessions";
|
|
86
86
|
dataType: "string";
|
|
87
87
|
columnType: "SQLiteText";
|
|
88
|
-
data: "
|
|
88
|
+
data: "completed" | "error" | "active" | "waiting";
|
|
89
89
|
driverParam: string;
|
|
90
90
|
notNull: true;
|
|
91
91
|
hasDefault: true;
|
|
@@ -391,7 +391,7 @@ declare const toolExecutions: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
391
391
|
tableName: "tool_executions";
|
|
392
392
|
dataType: "string";
|
|
393
393
|
columnType: "SQLiteText";
|
|
394
|
-
data: "
|
|
394
|
+
data: "completed" | "error" | "pending" | "approved" | "rejected";
|
|
395
395
|
driverParam: string;
|
|
396
396
|
notNull: true;
|
|
397
397
|
hasDefault: true;
|
|
@@ -814,7 +814,7 @@ declare const terminals: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
814
814
|
tableName: "terminals";
|
|
815
815
|
dataType: "string";
|
|
816
816
|
columnType: "SQLiteText";
|
|
817
|
-
data: "
|
|
817
|
+
data: "running" | "error" | "stopped";
|
|
818
818
|
driverParam: string;
|
|
819
819
|
notNull: true;
|
|
820
820
|
hasDefault: true;
|
|
@@ -5,6 +5,7 @@ interface BashToolProgress {
|
|
|
5
5
|
status: 'started' | 'running' | 'completed';
|
|
6
6
|
command?: string;
|
|
7
7
|
browserStreamPort?: number;
|
|
8
|
+
browserClosed?: boolean;
|
|
8
9
|
}
|
|
9
10
|
interface BashToolOptions {
|
|
10
11
|
workingDirectory: string;
|
|
@@ -14,12 +15,12 @@ interface BashToolOptions {
|
|
|
14
15
|
}
|
|
15
16
|
declare function createBashTool(options: BashToolOptions): ai.Tool<{
|
|
16
17
|
background: boolean;
|
|
17
|
-
input?: string | undefined;
|
|
18
18
|
id?: string | undefined;
|
|
19
|
+
input?: string | undefined;
|
|
19
20
|
command?: string | undefined;
|
|
20
21
|
kill?: boolean | undefined;
|
|
21
22
|
tail?: number | undefined;
|
|
22
|
-
key?: "
|
|
23
|
+
key?: "Enter" | "Escape" | "Up" | "Down" | "Left" | "Right" | "Tab" | "C-c" | "C-d" | "y" | "n" | undefined;
|
|
23
24
|
}, {
|
|
24
25
|
success: boolean;
|
|
25
26
|
id: string;
|
|
@@ -65,7 +66,7 @@ declare function createBashTool(options: BashToolOptions): ai.Tool<{
|
|
|
65
66
|
id: string;
|
|
66
67
|
output: string;
|
|
67
68
|
exitCode: number;
|
|
68
|
-
status: "
|
|
69
|
+
status: "running" | "completed" | "error" | "stopped";
|
|
69
70
|
message?: undefined;
|
|
70
71
|
error?: undefined;
|
|
71
72
|
} | {
|
|
@@ -217,8 +218,8 @@ interface SearchToolOptions {
|
|
|
217
218
|
* Progress is streamed back to the UI so users can see exploration happening.
|
|
218
219
|
*/
|
|
219
220
|
declare function createSearchTool(options: SearchToolOptions): ai.Tool<{
|
|
220
|
-
context: string;
|
|
221
221
|
query: string;
|
|
222
|
+
context: string;
|
|
222
223
|
}, {
|
|
223
224
|
success: boolean;
|
|
224
225
|
error: string;
|
package/dist/server/index.js
CHANGED
|
@@ -1784,19 +1784,14 @@ __export(stream_proxy_exports, {
|
|
|
1784
1784
|
import WebSocket from "ws";
|
|
1785
1785
|
import { EventEmitter } from "events";
|
|
1786
1786
|
function getOrCreateProxy(sessionId, port) {
|
|
1787
|
-
|
|
1788
|
-
if (
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
proxy.on("close", () => {
|
|
1796
|
-
activeProxies.delete(sessionId);
|
|
1797
|
-
});
|
|
1798
|
-
proxy.connect();
|
|
1799
|
-
}
|
|
1787
|
+
const existing = activeProxies.get(sessionId);
|
|
1788
|
+
if (existing) return existing;
|
|
1789
|
+
const proxy = new BrowserStreamProxy(port);
|
|
1790
|
+
activeProxies.set(sessionId, proxy);
|
|
1791
|
+
proxy.on("close", () => {
|
|
1792
|
+
activeProxies.delete(sessionId);
|
|
1793
|
+
});
|
|
1794
|
+
proxy.connect();
|
|
1800
1795
|
return proxy;
|
|
1801
1796
|
}
|
|
1802
1797
|
function getProxy(sessionId) {
|
|
@@ -1813,8 +1808,8 @@ var RECONNECT_DELAY_MS, MAX_RECONNECT_ATTEMPTS, FRAME_THROTTLE_MS, BrowserStream
|
|
|
1813
1808
|
var init_stream_proxy = __esm({
|
|
1814
1809
|
"src/browser/stream-proxy.ts"() {
|
|
1815
1810
|
"use strict";
|
|
1816
|
-
RECONNECT_DELAY_MS =
|
|
1817
|
-
MAX_RECONNECT_ATTEMPTS =
|
|
1811
|
+
RECONNECT_DELAY_MS = 1e3;
|
|
1812
|
+
MAX_RECONNECT_ATTEMPTS = 20;
|
|
1818
1813
|
FRAME_THROTTLE_MS = 100;
|
|
1819
1814
|
BrowserStreamProxy = class extends EventEmitter {
|
|
1820
1815
|
ws = null;
|
|
@@ -1864,8 +1859,11 @@ var init_stream_proxy = __esm({
|
|
|
1864
1859
|
}
|
|
1865
1860
|
});
|
|
1866
1861
|
this.ws.on("close", () => {
|
|
1862
|
+
const wasConnected = this._connected;
|
|
1867
1863
|
this._connected = false;
|
|
1868
|
-
|
|
1864
|
+
if (wasConnected) {
|
|
1865
|
+
this.emit("status", { connected: false, screencasting: false });
|
|
1866
|
+
}
|
|
1869
1867
|
if (!this.destroyed) {
|
|
1870
1868
|
this.scheduleReconnect();
|
|
1871
1869
|
}
|
|
@@ -1907,7 +1905,7 @@ var init_stream_proxy = __esm({
|
|
|
1907
1905
|
return;
|
|
1908
1906
|
}
|
|
1909
1907
|
this.reconnectAttempts++;
|
|
1910
|
-
const delay = RECONNECT_DELAY_MS * this.reconnectAttempts;
|
|
1908
|
+
const delay = this.reconnectAttempts <= 5 ? RECONNECT_DELAY_MS : RECONNECT_DELAY_MS * (this.reconnectAttempts - 4);
|
|
1911
1909
|
this.reconnectTimer = setTimeout(() => this.doConnect(), delay);
|
|
1912
1910
|
}
|
|
1913
1911
|
/**
|
|
@@ -2617,15 +2615,15 @@ function getBrowserStreamPort(sessionId) {
|
|
|
2617
2615
|
}
|
|
2618
2616
|
return port;
|
|
2619
2617
|
}
|
|
2620
|
-
function
|
|
2621
|
-
return /\bagent-browser\
|
|
2618
|
+
function hasAgentBrowserCommand(command) {
|
|
2619
|
+
return /\bagent-browser\b/.test(command);
|
|
2622
2620
|
}
|
|
2623
2621
|
function isAgentBrowserCloseCommand(command) {
|
|
2624
|
-
return /\bagent-browser\s+close\b/.test(command);
|
|
2622
|
+
return /\bagent-browser\s+(close|close\s+--all)\b/.test(command);
|
|
2625
2623
|
}
|
|
2626
2624
|
function injectBrowserStreamPort(command, port) {
|
|
2627
2625
|
return command.replace(
|
|
2628
|
-
/\bagent-browser\b
|
|
2626
|
+
/\bagent-browser\b/g,
|
|
2629
2627
|
`AGENT_BROWSER_STREAM_PORT=${port} agent-browser`
|
|
2630
2628
|
);
|
|
2631
2629
|
}
|
|
@@ -2795,12 +2793,14 @@ Terminal output is stored in the global SparkECoder data directory. Use the \`ta
|
|
|
2795
2793
|
};
|
|
2796
2794
|
}
|
|
2797
2795
|
let actualCommand = command;
|
|
2798
|
-
const
|
|
2796
|
+
const hasAgentBrowser = hasAgentBrowserCommand(command);
|
|
2799
2797
|
const browserClose = isAgentBrowserCloseCommand(command);
|
|
2800
2798
|
let browserPort;
|
|
2801
|
-
if (
|
|
2799
|
+
if (hasAgentBrowser) {
|
|
2802
2800
|
browserPort = getBrowserStreamPort(options.sessionId);
|
|
2803
|
-
|
|
2801
|
+
if (!browserClose) {
|
|
2802
|
+
actualCommand = injectBrowserStreamPort(command, browserPort);
|
|
2803
|
+
}
|
|
2804
2804
|
}
|
|
2805
2805
|
const canUseTmux = await shouldUseTmux();
|
|
2806
2806
|
if (background) {
|
|
@@ -2816,9 +2816,6 @@ Terminal output is stored in the global SparkECoder data directory. Use the \`ta
|
|
|
2816
2816
|
sessionId: options.sessionId,
|
|
2817
2817
|
terminalId
|
|
2818
2818
|
});
|
|
2819
|
-
if (browserOpen && browserPort) {
|
|
2820
|
-
options.onProgress?.({ terminalId, status: "running", command, browserStreamPort: browserPort });
|
|
2821
|
-
}
|
|
2822
2819
|
return {
|
|
2823
2820
|
success: true,
|
|
2824
2821
|
id: result.id,
|
|
@@ -2837,7 +2834,13 @@ Terminal output is stored in the global SparkECoder data directory. Use the \`ta
|
|
|
2837
2834
|
});
|
|
2838
2835
|
const truncatedOutput = truncateOutput(result.output, MAX_OUTPUT_CHARS2);
|
|
2839
2836
|
options.onOutput?.(truncatedOutput);
|
|
2840
|
-
options.onProgress?.({
|
|
2837
|
+
options.onProgress?.({
|
|
2838
|
+
terminalId,
|
|
2839
|
+
status: "completed",
|
|
2840
|
+
command,
|
|
2841
|
+
browserStreamPort: browserPort,
|
|
2842
|
+
browserClosed: browserClose || void 0
|
|
2843
|
+
});
|
|
2841
2844
|
return {
|
|
2842
2845
|
success: result.exitCode === 0,
|
|
2843
2846
|
id: result.id,
|
|
@@ -8082,42 +8085,6 @@ function enrichPromptWithDevtoolsContext(sessionId, prompt) {
|
|
|
8082
8085
|
|
|
8083
8086
|
${prompt}`;
|
|
8084
8087
|
}
|
|
8085
|
-
async function encodAndUploadRecording(sessionId, recorder) {
|
|
8086
|
-
if (!isRemoteConfigured()) {
|
|
8087
|
-
console.log("[RECORDING] Remote server not configured, skipping upload");
|
|
8088
|
-
recorder.clear();
|
|
8089
|
-
return;
|
|
8090
|
-
}
|
|
8091
|
-
console.log(`[RECORDING] Encoding ${recorder.frameCount} frames for session ${sessionId}...`);
|
|
8092
|
-
const result = await recorder.encode();
|
|
8093
|
-
recorder.clear();
|
|
8094
|
-
if (!result) {
|
|
8095
|
-
console.log("[RECORDING] Encoding failed or produced no output");
|
|
8096
|
-
return;
|
|
8097
|
-
}
|
|
8098
|
-
try {
|
|
8099
|
-
const { storageQueries: storageQueries2 } = await Promise.resolve().then(() => (init_remote(), remote_exports));
|
|
8100
|
-
const { readFile: readFile11, unlink: unlink3 } = await import("fs/promises");
|
|
8101
|
-
const uploadInfo = await storageQueries2.getUploadUrl(
|
|
8102
|
-
sessionId,
|
|
8103
|
-
`browser-recording-${Date.now()}.mp4`,
|
|
8104
|
-
"video/mp4",
|
|
8105
|
-
"browser-recording"
|
|
8106
|
-
);
|
|
8107
|
-
const fileData = await readFile11(result.path);
|
|
8108
|
-
await fetch(uploadInfo.uploadUrl, {
|
|
8109
|
-
method: "PUT",
|
|
8110
|
-
headers: { "Content-Type": "video/mp4" },
|
|
8111
|
-
body: fileData
|
|
8112
|
-
});
|
|
8113
|
-
await storageQueries2.updateFile(uploadInfo.fileId, { sizeBytes: result.sizeBytes });
|
|
8114
|
-
console.log(`[RECORDING] Uploaded recording for session ${sessionId} (${result.sizeBytes} bytes)`);
|
|
8115
|
-
await unlink3(result.path).catch(() => {
|
|
8116
|
-
});
|
|
8117
|
-
} catch (err) {
|
|
8118
|
-
console.error("[RECORDING] Upload failed:", err.message);
|
|
8119
|
-
}
|
|
8120
|
-
}
|
|
8121
8088
|
var agents = new Hono2();
|
|
8122
8089
|
var attachmentSchema = z16.object({
|
|
8123
8090
|
type: z16.enum(["image", "file"]),
|
|
@@ -8332,30 +8299,38 @@ ${prompt}` });
|
|
|
8332
8299
|
await new Promise((resolve11) => setTimeout(resolve11, 0));
|
|
8333
8300
|
}
|
|
8334
8301
|
const browserPort = progress.data?.browserStreamPort;
|
|
8335
|
-
|
|
8302
|
+
const browserClosed = progress.data?.browserClosed;
|
|
8303
|
+
if (progress.toolName === "bash" && browserClosed) {
|
|
8304
|
+
console.log(`[BROWSER-STREAM] agent-browser close detected, destroying proxy`);
|
|
8305
|
+
destroyProxy(sessionId);
|
|
8306
|
+
} else if (progress.toolName === "bash" && browserPort) {
|
|
8307
|
+
console.log(`[BROWSER-STREAM] agent-browser command detected, ensuring proxy on port ${browserPort}`);
|
|
8336
8308
|
const proxy = getOrCreateProxy(sessionId, browserPort);
|
|
8337
|
-
|
|
8338
|
-
|
|
8339
|
-
recorder = new FrameRecorder(sessionId);
|
|
8309
|
+
if (!sessionRecorders.has(sessionId)) {
|
|
8310
|
+
const recorder = new FrameRecorder(sessionId);
|
|
8340
8311
|
recorder.start();
|
|
8341
8312
|
sessionRecorders.set(sessionId, recorder);
|
|
8342
8313
|
}
|
|
8343
|
-
proxy.
|
|
8344
|
-
|
|
8345
|
-
|
|
8346
|
-
|
|
8347
|
-
|
|
8348
|
-
|
|
8349
|
-
|
|
8314
|
+
if (proxy.listenerCount("frame") === 0) {
|
|
8315
|
+
proxy.on("frame", (frame) => {
|
|
8316
|
+
const rec = sessionRecorders.get(sessionId);
|
|
8317
|
+
rec?.addFrame(frame);
|
|
8318
|
+
writeSSE(JSON.stringify({
|
|
8319
|
+
type: "browser-frame",
|
|
8320
|
+
data: frame.data,
|
|
8321
|
+
metadata: frame.metadata
|
|
8322
|
+
})).catch(() => {
|
|
8323
|
+
});
|
|
8350
8324
|
});
|
|
8351
|
-
|
|
8352
|
-
|
|
8353
|
-
|
|
8354
|
-
|
|
8355
|
-
|
|
8356
|
-
|
|
8325
|
+
proxy.on("status", (s) => {
|
|
8326
|
+
console.log(`[BROWSER-STREAM] Status:`, s);
|
|
8327
|
+
writeSSE(JSON.stringify({
|
|
8328
|
+
type: "browser-status",
|
|
8329
|
+
...s
|
|
8330
|
+
})).catch(() => {
|
|
8331
|
+
});
|
|
8357
8332
|
});
|
|
8358
|
-
}
|
|
8333
|
+
}
|
|
8359
8334
|
}
|
|
8360
8335
|
},
|
|
8361
8336
|
onStepFinish: async () => {
|
|
@@ -8467,15 +8442,6 @@ ${prompt}` });
|
|
|
8467
8442
|
}
|
|
8468
8443
|
} finally {
|
|
8469
8444
|
cleanupAbortController();
|
|
8470
|
-
destroyProxy(sessionId);
|
|
8471
|
-
const recorder = sessionRecorders.get(sessionId);
|
|
8472
|
-
if (recorder && recorder.frameCount > 0) {
|
|
8473
|
-
sessionRecorders.delete(sessionId);
|
|
8474
|
-
recorder.stop();
|
|
8475
|
-
encodAndUploadRecording(sessionId, recorder).catch((err) => {
|
|
8476
|
-
console.error("[RECORDING] Failed to encode/upload:", err.message);
|
|
8477
|
-
});
|
|
8478
|
-
}
|
|
8479
8445
|
await writeSSE("[DONE]");
|
|
8480
8446
|
await safeClose();
|
|
8481
8447
|
}
|
|
@@ -8831,30 +8797,38 @@ agents.post(
|
|
|
8831
8797
|
await new Promise((resolve11) => setTimeout(resolve11, 0));
|
|
8832
8798
|
}
|
|
8833
8799
|
const browserPort = progress.data?.browserStreamPort;
|
|
8834
|
-
|
|
8800
|
+
const browserClosed = progress.data?.browserClosed;
|
|
8801
|
+
if (progress.toolName === "bash" && browserClosed) {
|
|
8802
|
+
console.log(`[BROWSER-STREAM] agent-browser close detected`);
|
|
8803
|
+
destroyProxy(session.id);
|
|
8804
|
+
} else if (progress.toolName === "bash" && browserPort) {
|
|
8805
|
+
console.log(`[BROWSER-STREAM] agent-browser command detected, port ${browserPort}`);
|
|
8835
8806
|
const proxy = getOrCreateProxy(session.id, browserPort);
|
|
8836
|
-
|
|
8837
|
-
|
|
8838
|
-
recorder = new FrameRecorder(session.id);
|
|
8807
|
+
if (!sessionRecorders.has(session.id)) {
|
|
8808
|
+
const recorder = new FrameRecorder(session.id);
|
|
8839
8809
|
recorder.start();
|
|
8840
8810
|
sessionRecorders.set(session.id, recorder);
|
|
8841
8811
|
}
|
|
8842
|
-
proxy.
|
|
8843
|
-
|
|
8844
|
-
|
|
8845
|
-
|
|
8846
|
-
|
|
8847
|
-
|
|
8848
|
-
|
|
8812
|
+
if (proxy.listenerCount("frame") === 0) {
|
|
8813
|
+
proxy.on("frame", (frame) => {
|
|
8814
|
+
const rec = sessionRecorders.get(session.id);
|
|
8815
|
+
rec?.addFrame(frame);
|
|
8816
|
+
writeSSE(JSON.stringify({
|
|
8817
|
+
type: "browser-frame",
|
|
8818
|
+
data: frame.data,
|
|
8819
|
+
metadata: frame.metadata
|
|
8820
|
+
})).catch(() => {
|
|
8821
|
+
});
|
|
8849
8822
|
});
|
|
8850
|
-
|
|
8851
|
-
|
|
8852
|
-
|
|
8853
|
-
|
|
8854
|
-
|
|
8855
|
-
|
|
8823
|
+
proxy.on("status", (s) => {
|
|
8824
|
+
console.log(`[BROWSER-STREAM] Status:`, s);
|
|
8825
|
+
writeSSE(JSON.stringify({
|
|
8826
|
+
type: "browser-status",
|
|
8827
|
+
...s
|
|
8828
|
+
})).catch(() => {
|
|
8829
|
+
});
|
|
8856
8830
|
});
|
|
8857
|
-
}
|
|
8831
|
+
}
|
|
8858
8832
|
}
|
|
8859
8833
|
},
|
|
8860
8834
|
onStepFinish: async () => {
|
|
@@ -8960,15 +8934,6 @@ agents.post(
|
|
|
8960
8934
|
}
|
|
8961
8935
|
} finally {
|
|
8962
8936
|
cleanupAbortController();
|
|
8963
|
-
destroyProxy(session.id);
|
|
8964
|
-
const recorder = sessionRecorders.get(session.id);
|
|
8965
|
-
if (recorder && recorder.frameCount > 0) {
|
|
8966
|
-
sessionRecorders.delete(session.id);
|
|
8967
|
-
recorder.stop();
|
|
8968
|
-
encodAndUploadRecording(session.id, recorder).catch((err) => {
|
|
8969
|
-
console.error("[RECORDING] Failed to encode/upload:", err.message);
|
|
8970
|
-
});
|
|
8971
|
-
}
|
|
8972
8937
|
await writeSSE("[DONE]");
|
|
8973
8938
|
await safeClose();
|
|
8974
8939
|
}
|
|
@@ -9028,6 +8993,19 @@ agents.post(
|
|
|
9028
8993
|
return c.json({ success: true });
|
|
9029
8994
|
}
|
|
9030
8995
|
);
|
|
8996
|
+
agents.get("/:id/browser-stream", async (c) => {
|
|
8997
|
+
const sessionId = c.req.param("id");
|
|
8998
|
+
const proxy = getProxy(sessionId);
|
|
8999
|
+
return c.json({
|
|
9000
|
+
sessionId,
|
|
9001
|
+
active: !!proxy?.connected,
|
|
9002
|
+
hasProxy: !!proxy,
|
|
9003
|
+
latestFrame: proxy?.latestFrame ? {
|
|
9004
|
+
metadata: proxy.latestFrame.metadata,
|
|
9005
|
+
timestamp: proxy.latestFrame.timestamp
|
|
9006
|
+
} : null
|
|
9007
|
+
});
|
|
9008
|
+
});
|
|
9031
9009
|
|
|
9032
9010
|
// src/server/routes/health.ts
|
|
9033
9011
|
init_config();
|