@giselles-ai/agent 0.1.22 → 0.1.23
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/chunk-TAQV6ZOB.js +75 -0
- package/dist/index.d.ts +15 -1
- package/dist/index.js +5 -3
- package/dist/next/index.d.ts +1 -1
- package/dist/next/index.js +94 -55
- package/dist/server/index.js +88 -27
- package/package.json +2 -2
- package/dist/chunk-K2DPJIHU.js +0 -17
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// src/hash.ts
|
|
2
|
+
import { createHash } from "crypto";
|
|
3
|
+
function computeConfigHash(config) {
|
|
4
|
+
const payload = JSON.stringify({
|
|
5
|
+
agentType: config.agentType ?? "gemini",
|
|
6
|
+
agentMd: config.agentMd ?? null,
|
|
7
|
+
files: (config.files ?? []).map((f) => ({
|
|
8
|
+
path: f.path,
|
|
9
|
+
content: f.content
|
|
10
|
+
}))
|
|
11
|
+
});
|
|
12
|
+
return createHash("sha256").update(payload).digest("hex").slice(0, 16);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// src/request-build.ts
|
|
16
|
+
function trimTrailingSlash(url) {
|
|
17
|
+
return url.replace(/\/+$/, "");
|
|
18
|
+
}
|
|
19
|
+
function resolveFiles(agent) {
|
|
20
|
+
const files = [
|
|
21
|
+
...agent.files ?? []
|
|
22
|
+
];
|
|
23
|
+
if (agent.agentMd !== void 0) {
|
|
24
|
+
files.push(
|
|
25
|
+
{
|
|
26
|
+
path: "/home/vercel-sandbox/.codex/AGENTS.md",
|
|
27
|
+
content: agent.agentMd
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
path: "/home/vercel-sandbox/.gemini/GEMINI.md",
|
|
31
|
+
content: agent.agentMd
|
|
32
|
+
}
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
return files;
|
|
36
|
+
}
|
|
37
|
+
async function requestBuild(agent, options) {
|
|
38
|
+
const baseUrl = trimTrailingSlash(
|
|
39
|
+
options?.baseUrl ?? process.env.GISELLE_AGENT_BASE_URL ?? "https://studio.giselles.ai/agent-api"
|
|
40
|
+
);
|
|
41
|
+
const apiUrl = `${baseUrl}/build`;
|
|
42
|
+
const token = options?.token ?? process.env.GISELLE_AGENT_API_KEY;
|
|
43
|
+
if (!token) {
|
|
44
|
+
throw new Error(
|
|
45
|
+
"Missing API token. Set GISELLE_AGENT_API_KEY or pass options.token."
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
const configHash = computeConfigHash(agent);
|
|
49
|
+
const files = resolveFiles(agent);
|
|
50
|
+
const requestBody = {
|
|
51
|
+
config_hash: configHash,
|
|
52
|
+
agent_type: agent.agentType ?? "gemini",
|
|
53
|
+
files
|
|
54
|
+
};
|
|
55
|
+
const requestHeaders = {
|
|
56
|
+
"content-type": "application/json",
|
|
57
|
+
authorization: `Bearer ${token}`,
|
|
58
|
+
...options?.headers
|
|
59
|
+
};
|
|
60
|
+
const response = await fetch(apiUrl, {
|
|
61
|
+
method: "POST",
|
|
62
|
+
headers: requestHeaders,
|
|
63
|
+
body: JSON.stringify(requestBody)
|
|
64
|
+
});
|
|
65
|
+
if (!response.ok) {
|
|
66
|
+
const body = await response.text().catch(() => "");
|
|
67
|
+
throw new Error(`Build failed (${response.status}): ${body}`);
|
|
68
|
+
}
|
|
69
|
+
return await response.json();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export {
|
|
73
|
+
computeConfigHash,
|
|
74
|
+
requestBuild
|
|
75
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -5,4 +5,18 @@ declare function defineAgent(config: AgentConfig): DefinedAgent;
|
|
|
5
5
|
|
|
6
6
|
declare function computeConfigHash(config: AgentConfig): string;
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
type RequestBuildOptions = {
|
|
9
|
+
/** Base URL for the agent API. Default: process.env.GISELLE_AGENT_BASE_URL ?? "https://studio.giselles.ai/agent-api" */
|
|
10
|
+
baseUrl?: string;
|
|
11
|
+
/** Bearer token. Default: process.env.GISELLE_AGENT_API_KEY */
|
|
12
|
+
token?: string;
|
|
13
|
+
/** Additional headers to include in the build API request */
|
|
14
|
+
headers?: Record<string, string | undefined>;
|
|
15
|
+
};
|
|
16
|
+
type BuildResult = {
|
|
17
|
+
snapshot_id: string;
|
|
18
|
+
cached: boolean;
|
|
19
|
+
};
|
|
20
|
+
declare function requestBuild(agent: AgentConfig, options?: RequestBuildOptions): Promise<BuildResult>;
|
|
21
|
+
|
|
22
|
+
export { AgentConfig, type BuildResult, DefinedAgent, type RequestBuildOptions, computeConfigHash, defineAgent, requestBuild };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
-
computeConfigHash
|
|
3
|
-
|
|
2
|
+
computeConfigHash,
|
|
3
|
+
requestBuild
|
|
4
|
+
} from "./chunk-TAQV6ZOB.js";
|
|
4
5
|
|
|
5
6
|
// src/define-agent.ts
|
|
6
7
|
function defineAgent(config) {
|
|
@@ -21,5 +22,6 @@ function defineAgent(config) {
|
|
|
21
22
|
}
|
|
22
23
|
export {
|
|
23
24
|
computeConfigHash,
|
|
24
|
-
defineAgent
|
|
25
|
+
defineAgent,
|
|
26
|
+
requestBuild
|
|
25
27
|
};
|
package/dist/next/index.d.ts
CHANGED
|
@@ -10,6 +10,6 @@ type GiselleAgentPluginOptions = {
|
|
|
10
10
|
headers?: Record<string, string | undefined>;
|
|
11
11
|
};
|
|
12
12
|
|
|
13
|
-
declare function withGiselleAgent(nextConfig: NextConfig, agent: AgentConfig, options?: GiselleAgentPluginOptions): () => Promise<NextConfig>;
|
|
13
|
+
declare function withGiselleAgent(nextConfig: NextConfig, agent: AgentConfig, options?: GiselleAgentPluginOptions): (phase: string) => Promise<NextConfig>;
|
|
14
14
|
|
|
15
15
|
export { type GiselleAgentPluginOptions, withGiselleAgent };
|
package/dist/next/index.js
CHANGED
|
@@ -1,73 +1,112 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
} from "../chunk-
|
|
2
|
+
requestBuild
|
|
3
|
+
} from "../chunk-TAQV6ZOB.js";
|
|
4
4
|
|
|
5
5
|
// src/next/with-giselle-agent.ts
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
import crypto from "crypto";
|
|
7
|
+
import fs from "fs";
|
|
8
|
+
import { createRequire } from "module";
|
|
9
|
+
import path from "path";
|
|
10
|
+
var require2 = createRequire(import.meta.url);
|
|
11
|
+
var { version: PKG_VERSION } = require2("../../package.json");
|
|
12
|
+
var bold = (s) => `\x1B[1m${s}\x1B[22m`;
|
|
13
|
+
var green = (s) => `\x1B[32m${s}\x1B[39m`;
|
|
14
|
+
var red = (s) => `\x1B[31m${s}\x1B[39m`;
|
|
15
|
+
var magenta = (s) => `\x1B[35m${s}\x1B[39m`;
|
|
16
|
+
var dim = (s) => `\x1B[2m${s}\x1B[22m`;
|
|
17
|
+
function resolveBaseUrl(options) {
|
|
18
|
+
return (options?.baseUrl ?? process.env.GISELLE_AGENT_BASE_URL ?? "https://studio.giselles.ai/agent-api").replace(/\/+$/, "");
|
|
19
|
+
}
|
|
20
|
+
function getSnapshotFile(agent) {
|
|
21
|
+
const key = {
|
|
22
|
+
agentType: agent.agentType,
|
|
23
|
+
agentMd: agent.agentMd,
|
|
24
|
+
files: agent.files
|
|
25
|
+
};
|
|
26
|
+
const hash = crypto.createHash("sha256").update(JSON.stringify(key)).digest("hex").slice(0, 16);
|
|
27
|
+
return path.join(process.cwd(), ".next", "giselle", hash);
|
|
28
|
+
}
|
|
29
|
+
function hasRunRecently() {
|
|
30
|
+
const lockFile = path.join(process.cwd(), ".next", "giselle", ".lock");
|
|
31
|
+
try {
|
|
32
|
+
const ts = Number(fs.readFileSync(lockFile, "utf-8").trim());
|
|
33
|
+
if (Date.now() - ts < 2e3) {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
} catch {
|
|
37
|
+
}
|
|
38
|
+
fs.mkdirSync(path.dirname(lockFile), { recursive: true });
|
|
39
|
+
fs.writeFileSync(lockFile, String(Date.now()));
|
|
40
|
+
return false;
|
|
8
41
|
}
|
|
9
42
|
function withGiselleAgent(nextConfig, agent, options) {
|
|
10
43
|
return async () => {
|
|
11
|
-
|
|
12
|
-
options?.baseUrl ?? process.env.GISELLE_AGENT_BASE_URL ?? "https://studio.giselles.ai/agent-api"
|
|
13
|
-
);
|
|
14
|
-
const apiUrl = `${baseUrl}/build`;
|
|
15
|
-
const token = options?.token ?? process.env.GISELLE_AGENT_API_KEY;
|
|
16
|
-
if (!token) {
|
|
17
|
-
console.warn("[withGiselleAgent] Skipped snapshot build: missing token.");
|
|
44
|
+
if (hasRunRecently()) {
|
|
18
45
|
return nextConfig;
|
|
19
46
|
}
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
{
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
path: "/home/vercel-sandbox/.gemini/GEMINI.md",
|
|
32
|
-
content: agent.agentMd
|
|
47
|
+
const baseUrl = resolveBaseUrl(options);
|
|
48
|
+
const snapshotFile = getSnapshotFile(agent);
|
|
49
|
+
const cached = fs.existsSync(snapshotFile) ? fs.readFileSync(snapshotFile, "utf-8").trim() : void 0;
|
|
50
|
+
if (cached) {
|
|
51
|
+
return {
|
|
52
|
+
...nextConfig,
|
|
53
|
+
env: {
|
|
54
|
+
...nextConfig.env,
|
|
55
|
+
GISELLE_AGENT_SNAPSHOT_ID: cached
|
|
33
56
|
}
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
console.log("");
|
|
60
|
+
console.log(`${magenta(bold(`\u2726 Giselle Agent ${PKG_VERSION}`))}`);
|
|
61
|
+
console.log(`${dim("- Base URL:")} ${baseUrl}`);
|
|
62
|
+
console.log("");
|
|
63
|
+
const token = options?.token ?? process.env.GISELLE_AGENT_API_KEY;
|
|
64
|
+
if (!token) {
|
|
65
|
+
console.log(`${red("\u2717")} Missing API key`);
|
|
66
|
+
console.log("");
|
|
67
|
+
console.log(
|
|
68
|
+
" Create an account at https://studio.giselles.ai and generate"
|
|
69
|
+
);
|
|
70
|
+
console.log(
|
|
71
|
+
" an API key, then set it as GISELLE_AGENT_API_KEY in your environment."
|
|
34
72
|
);
|
|
73
|
+
console.log("");
|
|
74
|
+
throw new Error("Missing GISELLE_AGENT_API_KEY");
|
|
35
75
|
}
|
|
36
|
-
const
|
|
37
|
-
config_hash: configHash,
|
|
38
|
-
agent_type: agent.agentType ?? "gemini",
|
|
39
|
-
files
|
|
40
|
-
};
|
|
41
|
-
const requestHeaders = {
|
|
42
|
-
"content-type": "application/json",
|
|
43
|
-
authorization: `Bearer ${token}`,
|
|
44
|
-
...options?.headers
|
|
45
|
-
};
|
|
46
|
-
console.debug("[withGiselleAgent] POST %s", apiUrl);
|
|
47
|
-
console.debug(
|
|
48
|
-
"[withGiselleAgent] headers:",
|
|
49
|
-
JSON.stringify(requestHeaders, null, 2)
|
|
50
|
-
);
|
|
51
|
-
console.debug(
|
|
52
|
-
"[withGiselleAgent] body:",
|
|
53
|
-
JSON.stringify(requestBody, null, 2)
|
|
54
|
-
);
|
|
55
|
-
const response = await fetch(apiUrl, {
|
|
76
|
+
const authResponse = await fetch(`${baseUrl}/auth`, {
|
|
56
77
|
method: "POST",
|
|
57
|
-
headers:
|
|
58
|
-
|
|
78
|
+
headers: {
|
|
79
|
+
authorization: `Bearer ${token}`,
|
|
80
|
+
...options?.headers
|
|
81
|
+
}
|
|
59
82
|
});
|
|
60
|
-
if (!
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
83
|
+
if (!authResponse.ok) {
|
|
84
|
+
console.log(`${red("\u2717")} Authentication failed`);
|
|
85
|
+
console.log("");
|
|
86
|
+
console.log(
|
|
87
|
+
" Create an account at https://studio.giselles.ai and generate"
|
|
88
|
+
);
|
|
89
|
+
console.log(
|
|
90
|
+
" an API key, then set it as GISELLE_AGENT_API_KEY in your environment."
|
|
64
91
|
);
|
|
92
|
+
console.log("");
|
|
93
|
+
throw new Error("Authentication failed");
|
|
65
94
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
95
|
+
console.log(`${green("\u2713")} Authenticated`);
|
|
96
|
+
const start = performance.now();
|
|
97
|
+
const result = await requestBuild(agent, {
|
|
98
|
+
baseUrl: options?.baseUrl,
|
|
99
|
+
token,
|
|
100
|
+
headers: options?.headers
|
|
101
|
+
});
|
|
102
|
+
fs.mkdirSync(path.dirname(snapshotFile), { recursive: true });
|
|
103
|
+
fs.writeFileSync(snapshotFile, result.snapshot_id);
|
|
104
|
+
const elapsed = Math.round(performance.now() - start);
|
|
105
|
+
const elapsedStr = elapsed < 1e3 ? `${elapsed}ms` : `${(elapsed / 1e3).toFixed(1)}s`;
|
|
106
|
+
console.log(`${green("\u2713")} Building...`);
|
|
107
|
+
console.log(`${green("\u2713")} Ready in ${elapsedStr}`);
|
|
108
|
+
console.log("");
|
|
109
|
+
console.log("");
|
|
71
110
|
return {
|
|
72
111
|
...nextConfig,
|
|
73
112
|
env: {
|
package/dist/server/index.js
CHANGED
|
@@ -90,7 +90,36 @@ import {
|
|
|
90
90
|
|
|
91
91
|
// src/build.ts
|
|
92
92
|
import { Sandbox as Sandbox2 } from "@vercel/sandbox";
|
|
93
|
-
var
|
|
93
|
+
var CACHE_KEY_PREFIX = "agent-build:snapshot:";
|
|
94
|
+
var CACHE_TTL_SEC = 60 * 60 * 24;
|
|
95
|
+
var memoryCache = /* @__PURE__ */ new Map();
|
|
96
|
+
var MemorySnapshotCache = class {
|
|
97
|
+
async get(key2) {
|
|
98
|
+
return memoryCache.get(key2) ?? null;
|
|
99
|
+
}
|
|
100
|
+
async set(key2, value) {
|
|
101
|
+
memoryCache.set(key2, value);
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
var RedisSnapshotCache = class {
|
|
105
|
+
constructor(redis) {
|
|
106
|
+
this.redis = redis;
|
|
107
|
+
}
|
|
108
|
+
async get(key2) {
|
|
109
|
+
return this.redis.get(`${CACHE_KEY_PREFIX}${key2}`);
|
|
110
|
+
}
|
|
111
|
+
async set(key2, value) {
|
|
112
|
+
await this.redis.set(
|
|
113
|
+
`${CACHE_KEY_PREFIX}${key2}`,
|
|
114
|
+
value,
|
|
115
|
+
"EX",
|
|
116
|
+
CACHE_TTL_SEC
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
function createSnapshotCache(redis) {
|
|
121
|
+
return redis ? new RedisSnapshotCache(redis) : new MemorySnapshotCache();
|
|
122
|
+
}
|
|
94
123
|
function resolveBaseSnapshotId(configured) {
|
|
95
124
|
const envValue = process.env.GISELLE_AGENT_SANDBOX_BASE_SNAPSHOT_ID?.trim();
|
|
96
125
|
if (envValue) {
|
|
@@ -136,6 +165,7 @@ function parseBuildRequest(body) {
|
|
|
136
165
|
};
|
|
137
166
|
}
|
|
138
167
|
async function buildAgent(input) {
|
|
168
|
+
const cache = input.cache ?? new MemorySnapshotCache();
|
|
139
169
|
const body = await input.request.json().catch(() => null);
|
|
140
170
|
const parsed = parseBuildRequest(body);
|
|
141
171
|
if (!parsed) {
|
|
@@ -155,7 +185,7 @@ async function buildAgent(input) {
|
|
|
155
185
|
);
|
|
156
186
|
}
|
|
157
187
|
const cacheKey = `${baseSnapshotId}:${parsed.config_hash}`;
|
|
158
|
-
const cached =
|
|
188
|
+
const cached = await cache.get(cacheKey);
|
|
159
189
|
if (cached) {
|
|
160
190
|
console.log(
|
|
161
191
|
`[agent-build] cache hit: hash=${cacheKey} -> snapshot=${cached}`
|
|
@@ -179,7 +209,7 @@ async function buildAgent(input) {
|
|
|
179
209
|
}
|
|
180
210
|
const snapshot = await sandbox.snapshot();
|
|
181
211
|
console.log(`[agent-build] snapshot created: ${snapshot.snapshotId}`);
|
|
182
|
-
|
|
212
|
+
await cache.set(cacheKey, snapshot.snapshotId);
|
|
183
213
|
const response = {
|
|
184
214
|
snapshot_id: snapshot.snapshotId,
|
|
185
215
|
cached: false
|
|
@@ -1328,14 +1358,10 @@ function continueManagedCloudResponseFromLiveConnection(input) {
|
|
|
1328
1358
|
return managed.response;
|
|
1329
1359
|
}
|
|
1330
1360
|
|
|
1331
|
-
// src/
|
|
1332
|
-
var CHAT_STATE_TTL_SEC = 60 * 60;
|
|
1361
|
+
// src/redis.ts
|
|
1333
1362
|
var REDIS_URL_ENV_NAME = "REDIS_URL";
|
|
1334
|
-
function key(chatId) {
|
|
1335
|
-
return `cloud-chat:${chatId}`;
|
|
1336
|
-
}
|
|
1337
1363
|
function resolveRedisUrl(url) {
|
|
1338
|
-
const resolved = url?.trim() || process.env
|
|
1364
|
+
const resolved = url?.trim() || process.env[REDIS_URL_ENV_NAME]?.trim();
|
|
1339
1365
|
if (resolved) {
|
|
1340
1366
|
return resolved;
|
|
1341
1367
|
}
|
|
@@ -1343,6 +1369,26 @@ function resolveRedisUrl(url) {
|
|
|
1343
1369
|
`Missing Redis URL. Set ${REDIS_URL_ENV_NAME} or pass store.url.`
|
|
1344
1370
|
);
|
|
1345
1371
|
}
|
|
1372
|
+
async function createRedisClient(url) {
|
|
1373
|
+
let RedisCtor;
|
|
1374
|
+
try {
|
|
1375
|
+
const module = await import("ioredis");
|
|
1376
|
+
RedisCtor = module.default;
|
|
1377
|
+
} catch {
|
|
1378
|
+
throw new Error(
|
|
1379
|
+
"Redis store adapter requires `ioredis` to be installed as a peer dependency."
|
|
1380
|
+
);
|
|
1381
|
+
}
|
|
1382
|
+
return new RedisCtor(resolveRedisUrl(url), {
|
|
1383
|
+
maxRetriesPerRequest: 2
|
|
1384
|
+
});
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
// src/cloud-chat-store.ts
|
|
1388
|
+
var CHAT_STATE_TTL_SEC = 60 * 60;
|
|
1389
|
+
function key(chatId) {
|
|
1390
|
+
return `cloud-chat:${chatId}`;
|
|
1391
|
+
}
|
|
1346
1392
|
var RedisCloudChatStateStore = class {
|
|
1347
1393
|
constructor(redis) {
|
|
1348
1394
|
this.redis = redis;
|
|
@@ -1363,25 +1409,12 @@ var RedisCloudChatStateStore = class {
|
|
|
1363
1409
|
await this.redis.del(key(chatId));
|
|
1364
1410
|
}
|
|
1365
1411
|
};
|
|
1366
|
-
async function createRedisStore(url) {
|
|
1367
|
-
let RedisCtor;
|
|
1368
|
-
try {
|
|
1369
|
-
const module = await import("ioredis");
|
|
1370
|
-
RedisCtor = module.default;
|
|
1371
|
-
} catch {
|
|
1372
|
-
throw new Error(
|
|
1373
|
-
"Redis store adapter requires `ioredis` to be installed as a peer dependency."
|
|
1374
|
-
);
|
|
1375
|
-
}
|
|
1376
|
-
const redis = new RedisCtor(resolveRedisUrl(url), {
|
|
1377
|
-
maxRetriesPerRequest: 2
|
|
1378
|
-
});
|
|
1379
|
-
return new RedisCloudChatStateStore(redis);
|
|
1380
|
-
}
|
|
1381
1412
|
async function resolveCloudChatStateStore(store) {
|
|
1382
1413
|
switch (store.adapter) {
|
|
1383
|
-
case "redis":
|
|
1384
|
-
|
|
1414
|
+
case "redis": {
|
|
1415
|
+
const redis = await createRedisClient(store.url);
|
|
1416
|
+
return new RedisCloudChatStateStore(redis);
|
|
1417
|
+
}
|
|
1385
1418
|
}
|
|
1386
1419
|
}
|
|
1387
1420
|
|
|
@@ -1413,6 +1446,8 @@ function createAgentApi(options) {
|
|
|
1413
1446
|
const relay = createRelayHandler();
|
|
1414
1447
|
const { basePath, agent: agentOptions } = options;
|
|
1415
1448
|
let storePromise = null;
|
|
1449
|
+
let snapshotCachePromise = null;
|
|
1450
|
+
const authPath = `${basePath}/auth`;
|
|
1416
1451
|
const runPath = `${basePath}/run`;
|
|
1417
1452
|
const buildPath = `${basePath}/build`;
|
|
1418
1453
|
const relayPrefix = `${basePath}/relay`;
|
|
@@ -1420,6 +1455,13 @@ function createAgentApi(options) {
|
|
|
1420
1455
|
storePromise ??= resolveCloudChatStateStore(options.store);
|
|
1421
1456
|
return storePromise;
|
|
1422
1457
|
}
|
|
1458
|
+
function getSnapshotCache() {
|
|
1459
|
+
snapshotCachePromise ??= (async () => {
|
|
1460
|
+
const redis = await createRedisClient(options.store.url);
|
|
1461
|
+
return createSnapshotCache(redis);
|
|
1462
|
+
})();
|
|
1463
|
+
return snapshotCachePromise;
|
|
1464
|
+
}
|
|
1423
1465
|
async function handleBuild(request) {
|
|
1424
1466
|
const baseSnapshotId = process.env.GISELLE_AGENT_SANDBOX_BASE_SNAPSHOT_ID?.trim() || options.build?.baseSnapshotId;
|
|
1425
1467
|
if (!options.build && !baseSnapshotId) {
|
|
@@ -1432,7 +1474,8 @@ function createAgentApi(options) {
|
|
|
1432
1474
|
}
|
|
1433
1475
|
return await buildAgent({
|
|
1434
1476
|
request,
|
|
1435
|
-
baseSnapshotId
|
|
1477
|
+
baseSnapshotId,
|
|
1478
|
+
cache: await getSnapshotCache()
|
|
1436
1479
|
});
|
|
1437
1480
|
} catch (error) {
|
|
1438
1481
|
const message = error instanceof Error ? error.message : "Failed to process build request.";
|
|
@@ -1478,9 +1521,24 @@ function createAgentApi(options) {
|
|
|
1478
1521
|
return errorResponse(500, "INTERNAL_ERROR", message);
|
|
1479
1522
|
}
|
|
1480
1523
|
}
|
|
1524
|
+
async function handleAuth(request) {
|
|
1525
|
+
try {
|
|
1526
|
+
const hookResult = await options.hooks?.build?.before?.(request);
|
|
1527
|
+
if (hookResult instanceof Response) {
|
|
1528
|
+
return hookResult;
|
|
1529
|
+
}
|
|
1530
|
+
return Response.json({ ok: true });
|
|
1531
|
+
} catch (error) {
|
|
1532
|
+
const message = error instanceof Error ? error.message : "Authentication failed.";
|
|
1533
|
+
return errorResponse(401, "UNAUTHORIZED", message);
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1481
1536
|
function matchSubPath(request) {
|
|
1482
1537
|
const url = new URL(request.url);
|
|
1483
1538
|
const pathname = url.pathname;
|
|
1539
|
+
if (pathname === authPath || pathname === `${authPath}/`) {
|
|
1540
|
+
return "auth";
|
|
1541
|
+
}
|
|
1484
1542
|
if (pathname === runPath || pathname === `${runPath}/`) {
|
|
1485
1543
|
return "run";
|
|
1486
1544
|
}
|
|
@@ -1502,6 +1560,9 @@ function createAgentApi(options) {
|
|
|
1502
1560
|
},
|
|
1503
1561
|
POST: async (request) => {
|
|
1504
1562
|
const sub = matchSubPath(request);
|
|
1563
|
+
if (sub === "auth") {
|
|
1564
|
+
return handleAuth(request);
|
|
1565
|
+
}
|
|
1505
1566
|
if (sub === "run") {
|
|
1506
1567
|
return handleRun(request);
|
|
1507
1568
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@giselles-ai/agent",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.23",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"format": "pnpm exec biome check --write ."
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@giselles-ai/browser-tool": "0.1.
|
|
40
|
+
"@giselles-ai/browser-tool": "0.1.23",
|
|
41
41
|
"@vercel/sandbox": "1.6.0",
|
|
42
42
|
"@iarna/toml": "3.0.0",
|
|
43
43
|
"zod": "4.3.6"
|
package/dist/chunk-K2DPJIHU.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
// src/hash.ts
|
|
2
|
-
import { createHash } from "crypto";
|
|
3
|
-
function computeConfigHash(config) {
|
|
4
|
-
const payload = JSON.stringify({
|
|
5
|
-
agentType: config.agentType ?? "gemini",
|
|
6
|
-
agentMd: config.agentMd ?? null,
|
|
7
|
-
files: (config.files ?? []).map((f) => ({
|
|
8
|
-
path: f.path,
|
|
9
|
-
content: f.content
|
|
10
|
-
}))
|
|
11
|
-
});
|
|
12
|
-
return createHash("sha256").update(payload).digest("hex").slice(0, 16);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export {
|
|
16
|
-
computeConfigHash
|
|
17
|
-
};
|