@giselles-ai/agent 0.1.25 → 0.1.27
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/index.d.ts +2 -2
- package/dist/index.js +19 -2
- package/dist/next/index.d.ts +1 -1
- package/dist/server/index.js +273 -17
- package/dist/{types-cRejduhB.d.ts → types-Co_KfALw.d.ts} +12 -2
- package/package.json +5 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { A as AgentConfig, D as DefinedAgent } from './types-
|
|
2
|
-
export { a as AgentFile, b as AgentSetup } from './types-
|
|
1
|
+
import { A as AgentConfig, D as DefinedAgent } from './types-Co_KfALw.js';
|
|
2
|
+
export { a as AgentFile, b as AgentSetup, U as UICatalog } from './types-Co_KfALw.js';
|
|
3
3
|
|
|
4
4
|
declare function defineAgent(config: AgentConfig): DefinedAgent;
|
|
5
5
|
|
package/dist/index.js
CHANGED
|
@@ -4,12 +4,29 @@ import {
|
|
|
4
4
|
} from "./chunk-JGH5DCA7.js";
|
|
5
5
|
|
|
6
6
|
// src/define-agent.ts
|
|
7
|
+
function createInternalArtifactPrompt() {
|
|
8
|
+
return `
|
|
9
|
+
## Artifact Convention
|
|
10
|
+
- Files intended for user review or download must be written under ./artifacts/.
|
|
11
|
+
- Temporary files, logs, caches, and intermediate data should stay outside ./artifacts/.
|
|
12
|
+
- Before finishing, inspect ./artifacts/ and mention only files that actually exist there.
|
|
13
|
+
- Mention created artifact paths in the assistant response for fallback visibility.
|
|
14
|
+
`.trim();
|
|
15
|
+
}
|
|
7
16
|
function defineAgent(config) {
|
|
17
|
+
const catalogPrompt = config.catalog?.prompt({ mode: "inline" });
|
|
18
|
+
const internalPrompt = createInternalArtifactPrompt();
|
|
19
|
+
const agentMd = [config.agentMd, internalPrompt, catalogPrompt].filter(Boolean).join("\n\n");
|
|
8
20
|
return {
|
|
9
21
|
agentType: config.agentType ?? "gemini",
|
|
10
|
-
agentMd:
|
|
22
|
+
agentMd: agentMd || void 0,
|
|
23
|
+
catalog: config.catalog,
|
|
11
24
|
files: config.files ?? [],
|
|
12
|
-
env: config.env
|
|
25
|
+
env: config.env ? Object.fromEntries(
|
|
26
|
+
Object.entries(config.env).filter(
|
|
27
|
+
(entry) => entry[1] != null
|
|
28
|
+
)
|
|
29
|
+
) : {},
|
|
13
30
|
setup: config.setup,
|
|
14
31
|
get snapshotId() {
|
|
15
32
|
const id = process.env?.GISELLE_AGENT_SNAPSHOT_ID;
|
package/dist/next/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NextConfig } from 'next';
|
|
2
|
-
import { A as AgentConfig } from '../types-
|
|
2
|
+
import { A as AgentConfig } from '../types-Co_KfALw.js';
|
|
3
3
|
|
|
4
4
|
type GiselleAgentPluginOptions = {
|
|
5
5
|
/** Base URL for the agent API. Default: process.env.GISELLE_AGENT_BASE_URL ?? "https://studio.giselles.ai/agent-api" */
|
package/dist/server/index.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
// src/agent-api.ts
|
|
2
|
+
import { basename } from "path";
|
|
2
3
|
import {
|
|
3
4
|
createRelayHandler,
|
|
4
5
|
createRelaySession
|
|
5
6
|
} from "@giselles-ai/browser-tool/relay";
|
|
7
|
+
import { Sandbox as Sandbox3 } from "@vercel/sandbox";
|
|
6
8
|
|
|
7
9
|
// src/build.ts
|
|
8
10
|
import { Sandbox } from "@vercel/sandbox";
|
|
@@ -537,11 +539,19 @@ function createGeminiAgent(options = {}) {
|
|
|
537
539
|
"--output-format",
|
|
538
540
|
"stream-json",
|
|
539
541
|
"--approval-mode",
|
|
540
|
-
"yolo"
|
|
542
|
+
"yolo",
|
|
543
|
+
"--sandbox",
|
|
544
|
+
"false"
|
|
541
545
|
];
|
|
542
546
|
if (input.session_id) {
|
|
543
547
|
args.push("--resume", input.session_id);
|
|
544
548
|
}
|
|
549
|
+
console.info("[gemini-agent] createCommand", {
|
|
550
|
+
hasSessionId: Boolean(input.session_id),
|
|
551
|
+
hasSandboxId: Boolean(input.sandbox_id),
|
|
552
|
+
hasSnapshotId: Boolean(input.snapshot_id),
|
|
553
|
+
argCount: args.length
|
|
554
|
+
});
|
|
545
555
|
return {
|
|
546
556
|
cmd: "gemini",
|
|
547
557
|
args,
|
|
@@ -597,6 +607,97 @@ function createAgent(options) {
|
|
|
597
607
|
// src/chat-run.ts
|
|
598
608
|
import { Writable } from "stream";
|
|
599
609
|
import { Sandbox as Sandbox2 } from "@vercel/sandbox";
|
|
610
|
+
var COMMAND_TIMEOUT_EXTENSION_MS = 5 * 60 * 1e3;
|
|
611
|
+
var ARTIFACT_DIRS = ["./artifacts", "/vercel/sandbox/artifacts"];
|
|
612
|
+
function getArtifactMimeType(path) {
|
|
613
|
+
const extension = path.split(".").pop()?.toLowerCase();
|
|
614
|
+
switch (extension) {
|
|
615
|
+
case "md":
|
|
616
|
+
return "text/markdown; charset=utf-8";
|
|
617
|
+
case "json":
|
|
618
|
+
return "application/json; charset=utf-8";
|
|
619
|
+
case "csv":
|
|
620
|
+
return "text/csv; charset=utf-8";
|
|
621
|
+
case "txt":
|
|
622
|
+
return "text/plain; charset=utf-8";
|
|
623
|
+
default:
|
|
624
|
+
return "application/octet-stream";
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
function getArtifactLabel(path) {
|
|
628
|
+
const pieces = path.split("/");
|
|
629
|
+
return pieces[pieces.length - 1] ?? path;
|
|
630
|
+
}
|
|
631
|
+
async function collectArtifacts(sandbox) {
|
|
632
|
+
const artifacts = [];
|
|
633
|
+
const seen = /* @__PURE__ */ new Set();
|
|
634
|
+
let discoveryFailed = false;
|
|
635
|
+
for (const artifactDir of ARTIFACT_DIRS) {
|
|
636
|
+
let output = "";
|
|
637
|
+
let discoveryStderr = "";
|
|
638
|
+
let exitCode = 0;
|
|
639
|
+
try {
|
|
640
|
+
const result = await sandbox.runCommand({
|
|
641
|
+
cmd: "find",
|
|
642
|
+
args: [artifactDir, "-type", "f", "-print"]
|
|
643
|
+
});
|
|
644
|
+
output = await result.stdout();
|
|
645
|
+
discoveryStderr = await result.stderr();
|
|
646
|
+
exitCode = typeof result.exitCode === "number" ? result.exitCode : 0;
|
|
647
|
+
} catch (error) {
|
|
648
|
+
discoveryFailed = true;
|
|
649
|
+
console.warn("[chat-run] artifact discovery failed for directory", {
|
|
650
|
+
directory: artifactDir,
|
|
651
|
+
error: error instanceof Error ? error.message : String(error),
|
|
652
|
+
stderr: discoveryStderr
|
|
653
|
+
});
|
|
654
|
+
continue;
|
|
655
|
+
}
|
|
656
|
+
if (exitCode !== 0 && !output.trim()) {
|
|
657
|
+
discoveryFailed = true;
|
|
658
|
+
console.warn(
|
|
659
|
+
"[chat-run] artifact discovery returned non-zero exit code",
|
|
660
|
+
{
|
|
661
|
+
directory: artifactDir,
|
|
662
|
+
exitCode,
|
|
663
|
+
stderr: discoveryStderr
|
|
664
|
+
}
|
|
665
|
+
);
|
|
666
|
+
continue;
|
|
667
|
+
}
|
|
668
|
+
if (!output.trim()) {
|
|
669
|
+
continue;
|
|
670
|
+
}
|
|
671
|
+
for (const line of output.split("\n")) {
|
|
672
|
+
const trimmed = line.trim();
|
|
673
|
+
if (!trimmed) {
|
|
674
|
+
continue;
|
|
675
|
+
}
|
|
676
|
+
const [path, rawSize] = trimmed.split(" ");
|
|
677
|
+
if (!path) {
|
|
678
|
+
continue;
|
|
679
|
+
}
|
|
680
|
+
const normalizedPath = path.startsWith("/vercel/sandbox/") ? `./${path.slice("/vercel/sandbox/".length)}` : path;
|
|
681
|
+
if (!normalizedPath.startsWith("./artifacts/") || seen.has(normalizedPath)) {
|
|
682
|
+
continue;
|
|
683
|
+
}
|
|
684
|
+
seen.add(normalizedPath);
|
|
685
|
+
const parsedSize = Number.parseInt(rawSize ?? "0", 10);
|
|
686
|
+
const size_bytes = Number.isNaN(parsedSize) ? 0 : parsedSize;
|
|
687
|
+
artifacts.push({
|
|
688
|
+
type: "artifact",
|
|
689
|
+
path: normalizedPath,
|
|
690
|
+
size_bytes,
|
|
691
|
+
mime_type: getArtifactMimeType(normalizedPath),
|
|
692
|
+
label: getArtifactLabel(normalizedPath)
|
|
693
|
+
});
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
if (discoveryFailed && artifacts.length === 0) {
|
|
697
|
+
return [];
|
|
698
|
+
}
|
|
699
|
+
return artifacts;
|
|
700
|
+
}
|
|
600
701
|
function emitText(controller, text, encoder) {
|
|
601
702
|
if (text.length === 0) {
|
|
602
703
|
return;
|
|
@@ -666,7 +767,21 @@ function runChat(input) {
|
|
|
666
767
|
const sandbox = await (async () => {
|
|
667
768
|
if (parsed.sandbox_id) {
|
|
668
769
|
try {
|
|
669
|
-
|
|
770
|
+
const existing = await Sandbox2.get({
|
|
771
|
+
sandboxId: parsed.sandbox_id
|
|
772
|
+
});
|
|
773
|
+
if (existing.status !== "running") {
|
|
774
|
+
if (!snapshotId) {
|
|
775
|
+
throw new Error(
|
|
776
|
+
`Sandbox ${parsed.sandbox_id} is ${existing.status}, not running`
|
|
777
|
+
);
|
|
778
|
+
}
|
|
779
|
+
console.log(
|
|
780
|
+
`[sandbox] sandbox=${parsed.sandbox_id} status=${existing.status}, recreating from snapshot=${snapshotId}`
|
|
781
|
+
);
|
|
782
|
+
return createFromSnapshot(snapshotId);
|
|
783
|
+
}
|
|
784
|
+
return existing;
|
|
670
785
|
} catch (error) {
|
|
671
786
|
if (!snapshotId) {
|
|
672
787
|
throw error;
|
|
@@ -692,6 +807,16 @@ function runChat(input) {
|
|
|
692
807
|
const command = input.agent.createCommand({
|
|
693
808
|
input: parsed
|
|
694
809
|
});
|
|
810
|
+
console.info("[chat-run] starting sandbox command", {
|
|
811
|
+
sandboxId: sandbox.sandboxId,
|
|
812
|
+
cmd: command.cmd,
|
|
813
|
+
args: command.args,
|
|
814
|
+
envKeys: Object.keys(command.env ?? {}).sort(),
|
|
815
|
+
hasSessionId: typeof parsed.session_id === "string" && parsed.session_id.length > 0,
|
|
816
|
+
hasSandboxId: typeof parsed.sandbox_id === "string" && parsed.sandbox_id.length > 0,
|
|
817
|
+
hasSnapshotId: typeof parsed.snapshot_id === "string" && parsed.snapshot_id.length > 0
|
|
818
|
+
});
|
|
819
|
+
await sandbox.extendTimeout(COMMAND_TIMEOUT_EXTENSION_MS);
|
|
695
820
|
await sandbox.runCommand({
|
|
696
821
|
cmd: command.cmd,
|
|
697
822
|
args: command.args,
|
|
@@ -713,12 +838,20 @@ function runChat(input) {
|
|
|
713
838
|
stderr: new Writable({
|
|
714
839
|
write(chunk, _encoding, callback) {
|
|
715
840
|
const text = typeof chunk === "string" ? chunk : chunk.toString("utf8");
|
|
841
|
+
console.error("[chat-run] sandbox stderr", {
|
|
842
|
+
sandboxId: sandbox.sandboxId,
|
|
843
|
+
content: text
|
|
844
|
+
});
|
|
716
845
|
enqueueEvent({ type: "stderr", content: text });
|
|
717
846
|
callback();
|
|
718
847
|
}
|
|
719
848
|
}),
|
|
720
849
|
signal: abortController.signal
|
|
721
850
|
});
|
|
851
|
+
const discoveredArtifacts = await collectArtifacts(sandbox);
|
|
852
|
+
for (const artifact of discoveredArtifacts) {
|
|
853
|
+
enqueueEvent(artifact);
|
|
854
|
+
}
|
|
722
855
|
const snapshot = await sandbox.snapshot();
|
|
723
856
|
enqueueEvent({
|
|
724
857
|
type: "snapshot",
|
|
@@ -969,8 +1102,12 @@ function injectRelayUrl(agent, relayUrl) {
|
|
|
969
1102
|
}
|
|
970
1103
|
};
|
|
971
1104
|
}
|
|
1105
|
+
function usesBrowserTool(agent) {
|
|
1106
|
+
return isCreateAgentOptions2(agent) && agent.tools?.browser !== void 0;
|
|
1107
|
+
}
|
|
972
1108
|
async function runCloudChat(input) {
|
|
973
|
-
const
|
|
1109
|
+
const browserToolEnabled = usesBrowserTool(input.agent);
|
|
1110
|
+
const agentParam = browserToolEnabled ? injectRelayUrl(input.agent, input.relayUrl) : input.agent;
|
|
974
1111
|
const agent = resolveAgent(agentParam);
|
|
975
1112
|
const now = input.now?.() ?? Date.now();
|
|
976
1113
|
const createRelaySub = input.createRelayRequestSubscription ?? createRelayRequestSubscription;
|
|
@@ -992,23 +1129,29 @@ async function runCloudChat(input) {
|
|
|
992
1129
|
sendResponse
|
|
993
1130
|
});
|
|
994
1131
|
}
|
|
995
|
-
const relaySession = await input.createRelaySession();
|
|
996
|
-
const relaySubscription = await createRelaySub({
|
|
997
|
-
sessionId: relaySession.sessionId,
|
|
998
|
-
token: relaySession.token
|
|
999
|
-
});
|
|
1000
|
-
console.info("[cloud-chat] relay subscription ready", {
|
|
1001
|
-
chatId: input.chatId,
|
|
1002
|
-
relaySessionId: relaySession.sessionId
|
|
1003
|
-
});
|
|
1004
1132
|
const runtimeInput = {
|
|
1005
1133
|
...input.request,
|
|
1006
1134
|
...existing?.agentSessionId ? { session_id: existing.agentSessionId } : {},
|
|
1007
1135
|
...existing?.sandboxId ? { sandbox_id: existing.sandboxId } : {},
|
|
1008
|
-
...existing?.snapshotId ? { snapshot_id: existing.snapshotId } : {}
|
|
1009
|
-
relay_session_id: relaySession.sessionId,
|
|
1010
|
-
relay_token: relaySession.token
|
|
1136
|
+
...existing?.snapshotId ? { snapshot_id: existing.snapshotId } : {}
|
|
1011
1137
|
};
|
|
1138
|
+
let relaySession;
|
|
1139
|
+
let relaySubscription = null;
|
|
1140
|
+
if (browserToolEnabled) {
|
|
1141
|
+
relaySession = await input.createRelaySession();
|
|
1142
|
+
relaySubscription = await createRelaySub({
|
|
1143
|
+
sessionId: relaySession.sessionId,
|
|
1144
|
+
token: relaySession.token
|
|
1145
|
+
});
|
|
1146
|
+
console.info("[cloud-chat] relay subscription ready", {
|
|
1147
|
+
chatId: input.chatId,
|
|
1148
|
+
relaySessionId: relaySession.sessionId
|
|
1149
|
+
});
|
|
1150
|
+
Object.assign(runtimeInput, {
|
|
1151
|
+
relay_session_id: relaySession.sessionId,
|
|
1152
|
+
relay_token: relaySession.token
|
|
1153
|
+
});
|
|
1154
|
+
}
|
|
1012
1155
|
let response;
|
|
1013
1156
|
try {
|
|
1014
1157
|
response = await (input.runChatImpl ?? runChat)({
|
|
@@ -1017,7 +1160,7 @@ async function runCloudChat(input) {
|
|
|
1017
1160
|
input: runtimeInput
|
|
1018
1161
|
});
|
|
1019
1162
|
} catch (error) {
|
|
1020
|
-
await relaySubscription
|
|
1163
|
+
await relaySubscription?.close().catch(() => void 0);
|
|
1021
1164
|
throw error;
|
|
1022
1165
|
}
|
|
1023
1166
|
const managed = createManagedCloudResponseFromReader({
|
|
@@ -1032,7 +1175,7 @@ async function runCloudChat(input) {
|
|
|
1032
1175
|
relaySubscription,
|
|
1033
1176
|
relaySession,
|
|
1034
1177
|
relayUrl: input.relayUrl,
|
|
1035
|
-
includeRelaySessionPrelude:
|
|
1178
|
+
includeRelaySessionPrelude: browserToolEnabled,
|
|
1036
1179
|
initialBuffer: "",
|
|
1037
1180
|
initialTextBlockOpen: false
|
|
1038
1181
|
});
|
|
@@ -1433,6 +1576,70 @@ function resolveRelayUrl(basePath, request) {
|
|
|
1433
1576
|
}
|
|
1434
1577
|
return new URL(`${basePath}/relay`, request.url).toString();
|
|
1435
1578
|
}
|
|
1579
|
+
function createArtifactError(status, path, message) {
|
|
1580
|
+
return errorResponse(status, "FILE_ERROR", `${path}: ${message}`);
|
|
1581
|
+
}
|
|
1582
|
+
function getArtifactMimeType2(path) {
|
|
1583
|
+
const extension = path.split(".").pop()?.toLowerCase();
|
|
1584
|
+
switch (extension) {
|
|
1585
|
+
case "md":
|
|
1586
|
+
return "text/markdown; charset=utf-8";
|
|
1587
|
+
case "json":
|
|
1588
|
+
return "application/json; charset=utf-8";
|
|
1589
|
+
case "csv":
|
|
1590
|
+
return "text/csv; charset=utf-8";
|
|
1591
|
+
case "txt":
|
|
1592
|
+
return "text/plain; charset=utf-8";
|
|
1593
|
+
default:
|
|
1594
|
+
return "application/octet-stream";
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
async function resolveReadableSandbox(input) {
|
|
1598
|
+
const createFromSnapshot = async (snapshotId) => Sandbox3.create({
|
|
1599
|
+
source: {
|
|
1600
|
+
type: "snapshot",
|
|
1601
|
+
snapshotId
|
|
1602
|
+
}
|
|
1603
|
+
});
|
|
1604
|
+
if (input.sandboxId) {
|
|
1605
|
+
try {
|
|
1606
|
+
const existing = await Sandbox3.get({ sandboxId: input.sandboxId });
|
|
1607
|
+
if (existing.status === "running") {
|
|
1608
|
+
return existing;
|
|
1609
|
+
}
|
|
1610
|
+
if (!input.snapshotId) {
|
|
1611
|
+
throw new Error(
|
|
1612
|
+
`Sandbox ${input.sandboxId} is ${existing.status}, not running`
|
|
1613
|
+
);
|
|
1614
|
+
}
|
|
1615
|
+
console.log(
|
|
1616
|
+
`[agent-api] sandbox=${input.sandboxId} status=${existing.status}, recreating from snapshot=${input.snapshotId}`
|
|
1617
|
+
);
|
|
1618
|
+
return createFromSnapshot(input.snapshotId);
|
|
1619
|
+
} catch (error) {
|
|
1620
|
+
if (!input.snapshotId) {
|
|
1621
|
+
throw error;
|
|
1622
|
+
}
|
|
1623
|
+
console.log(
|
|
1624
|
+
`[agent-api] sandbox=${input.sandboxId} expired, recreating from snapshot=${input.snapshotId}`
|
|
1625
|
+
);
|
|
1626
|
+
return createFromSnapshot(input.snapshotId);
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
if (!input.snapshotId) {
|
|
1630
|
+
throw new Error("No sandbox_id or snapshot_id available for file read");
|
|
1631
|
+
}
|
|
1632
|
+
return createFromSnapshot(input.snapshotId);
|
|
1633
|
+
}
|
|
1634
|
+
function createDownloadHeaders(path, options) {
|
|
1635
|
+
const filename = basename(path);
|
|
1636
|
+
const mode = options.download === "1" ? "attachment" : "inline";
|
|
1637
|
+
return {
|
|
1638
|
+
"Content-Type": getArtifactMimeType2(path),
|
|
1639
|
+
"Content-Disposition": `${mode}; filename="${filename}"`,
|
|
1640
|
+
"Cache-Control": "private, no-store"
|
|
1641
|
+
};
|
|
1642
|
+
}
|
|
1436
1643
|
function createAgentApi(options) {
|
|
1437
1644
|
const relay = createRelayHandler();
|
|
1438
1645
|
const { basePath, agent: agentOptions } = options;
|
|
@@ -1474,6 +1681,45 @@ function createAgentApi(options) {
|
|
|
1474
1681
|
return errorResponse(500, "INTERNAL_ERROR", message);
|
|
1475
1682
|
}
|
|
1476
1683
|
}
|
|
1684
|
+
async function handleFiles(request) {
|
|
1685
|
+
const url = new URL(request.url);
|
|
1686
|
+
const chatId = url.searchParams.get("chat_id")?.trim();
|
|
1687
|
+
const path = url.searchParams.get("path")?.trim();
|
|
1688
|
+
const download = url.searchParams.get("download")?.trim();
|
|
1689
|
+
if (!chatId || !path) {
|
|
1690
|
+
return createArtifactError(400, "query", "chat_id and path are required");
|
|
1691
|
+
}
|
|
1692
|
+
if (!path.startsWith("./artifacts/") || path.includes("..")) {
|
|
1693
|
+
return createArtifactError(400, "path", "path must be under ./artifacts");
|
|
1694
|
+
}
|
|
1695
|
+
const store = await getStore();
|
|
1696
|
+
const chatState = await store.load(chatId);
|
|
1697
|
+
if (!chatState) {
|
|
1698
|
+
return createArtifactError(404, "chat_id", "chat session not found");
|
|
1699
|
+
}
|
|
1700
|
+
let sandbox;
|
|
1701
|
+
try {
|
|
1702
|
+
sandbox = await resolveReadableSandbox({
|
|
1703
|
+
sandboxId: chatState.sandboxId,
|
|
1704
|
+
snapshotId: chatState.snapshotId
|
|
1705
|
+
});
|
|
1706
|
+
} catch (error) {
|
|
1707
|
+
return createArtifactError(
|
|
1708
|
+
400,
|
|
1709
|
+
"sandbox",
|
|
1710
|
+
error instanceof Error ? error.message : "failed to resolve sandbox"
|
|
1711
|
+
);
|
|
1712
|
+
}
|
|
1713
|
+
const fileBuffer = await sandbox.readFileToBuffer({
|
|
1714
|
+
path
|
|
1715
|
+
});
|
|
1716
|
+
if (!fileBuffer) {
|
|
1717
|
+
return createArtifactError(404, "path", "file not found");
|
|
1718
|
+
}
|
|
1719
|
+
return new Response(new Uint8Array(fileBuffer), {
|
|
1720
|
+
headers: createDownloadHeaders(path, { download })
|
|
1721
|
+
});
|
|
1722
|
+
}
|
|
1477
1723
|
async function handleRun(request) {
|
|
1478
1724
|
try {
|
|
1479
1725
|
const hookResult = await options.hooks?.chat?.before?.(request);
|
|
@@ -1532,6 +1778,7 @@ function createAgentApi(options) {
|
|
|
1532
1778
|
function matchSubPath(request) {
|
|
1533
1779
|
const url = new URL(request.url);
|
|
1534
1780
|
const pathname = url.pathname;
|
|
1781
|
+
const filesPath = `${basePath}/files`;
|
|
1535
1782
|
if (pathname === authPath || pathname === `${authPath}/`) {
|
|
1536
1783
|
return "auth";
|
|
1537
1784
|
}
|
|
@@ -1541,6 +1788,9 @@ function createAgentApi(options) {
|
|
|
1541
1788
|
if (pathname === buildPath || pathname === `${buildPath}/`) {
|
|
1542
1789
|
return "build";
|
|
1543
1790
|
}
|
|
1791
|
+
if (pathname === filesPath || pathname === `${filesPath}/`) {
|
|
1792
|
+
return "files";
|
|
1793
|
+
}
|
|
1544
1794
|
if (pathname === relayPrefix || pathname.startsWith(`${relayPrefix}/`)) {
|
|
1545
1795
|
return "relay";
|
|
1546
1796
|
}
|
|
@@ -1552,6 +1802,9 @@ function createAgentApi(options) {
|
|
|
1552
1802
|
if (sub === "relay") {
|
|
1553
1803
|
return relay.GET(request);
|
|
1554
1804
|
}
|
|
1805
|
+
if (sub === "files") {
|
|
1806
|
+
return handleFiles(request);
|
|
1807
|
+
}
|
|
1555
1808
|
return errorResponse(404, "NOT_FOUND", "Not found.");
|
|
1556
1809
|
},
|
|
1557
1810
|
POST: async (request) => {
|
|
@@ -1575,6 +1828,9 @@ function createAgentApi(options) {
|
|
|
1575
1828
|
if (sub === "relay") {
|
|
1576
1829
|
return relay.OPTIONS(request);
|
|
1577
1830
|
}
|
|
1831
|
+
if (sub === "files") {
|
|
1832
|
+
return new Response(null, { status: 204 });
|
|
1833
|
+
}
|
|
1578
1834
|
return new Response(null, { status: 204 });
|
|
1579
1835
|
}
|
|
1580
1836
|
};
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/** Minimal interface for a json-render catalog. */
|
|
2
|
+
type UICatalog = {
|
|
3
|
+
prompt(options?: {
|
|
4
|
+
mode?: "inline" | "standalone";
|
|
5
|
+
customRules?: string[];
|
|
6
|
+
}): string;
|
|
7
|
+
};
|
|
1
8
|
type AgentFile = {
|
|
2
9
|
path: string;
|
|
3
10
|
content: string;
|
|
@@ -11,8 +18,10 @@ type AgentConfig = {
|
|
|
11
18
|
agentType?: "gemini" | "codex";
|
|
12
19
|
/** Content for AGENTS.md in the sandbox. */
|
|
13
20
|
agentMd?: string;
|
|
21
|
+
/** Optional json-render catalog for generative UI. */
|
|
22
|
+
catalog?: UICatalog;
|
|
14
23
|
/** Environment variables passed to the sandbox at build and run time. */
|
|
15
|
-
env?: Record<string, string>;
|
|
24
|
+
env?: Record<string, string | undefined>;
|
|
16
25
|
/** Additional files to write into the sandbox. */
|
|
17
26
|
files?: AgentFile[];
|
|
18
27
|
/** Setup configuration for the sandbox build phase. */
|
|
@@ -21,6 +30,7 @@ type AgentConfig = {
|
|
|
21
30
|
type DefinedAgent = {
|
|
22
31
|
readonly agentType: "gemini" | "codex";
|
|
23
32
|
readonly agentMd?: string;
|
|
33
|
+
readonly catalog?: UICatalog;
|
|
24
34
|
readonly files: AgentFile[];
|
|
25
35
|
/** Setup configuration. Undefined when no setup is configured. */
|
|
26
36
|
readonly setup?: AgentSetup;
|
|
@@ -30,4 +40,4 @@ type DefinedAgent = {
|
|
|
30
40
|
readonly snapshotId: string;
|
|
31
41
|
};
|
|
32
42
|
|
|
33
|
-
export type { AgentConfig as A, DefinedAgent as D, AgentFile as a, AgentSetup as b };
|
|
43
|
+
export type { AgentConfig as A, DefinedAgent as D, UICatalog as U, AgentFile as a, AgentSetup as b };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@giselles-ai/agent",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.27",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -37,9 +37,11 @@
|
|
|
37
37
|
"format": "pnpm exec biome check --write ."
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@giselles-ai/browser-tool": "0.1.
|
|
41
|
-
"@vercel/sandbox": "1.8.1",
|
|
40
|
+
"@giselles-ai/browser-tool": "0.1.27",
|
|
42
41
|
"@iarna/toml": "3.0.0",
|
|
42
|
+
"@json-render/core": "0.13.0",
|
|
43
|
+
"@vercel/sandbox": "1.8.1",
|
|
44
|
+
"sandbox": "2.5.5",
|
|
43
45
|
"zod": "4.3.6"
|
|
44
46
|
},
|
|
45
47
|
"devDependencies": {
|