@agent-native/core 0.7.41 → 0.7.42
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/a2a/client.d.ts +4 -1
- package/dist/a2a/client.d.ts.map +1 -1
- package/dist/a2a/client.js +152 -43
- package/dist/a2a/client.js.map +1 -1
- package/dist/client/NewWorkspaceAppFlow.d.ts.map +1 -1
- package/dist/client/NewWorkspaceAppFlow.js +12 -7
- package/dist/client/NewWorkspaceAppFlow.js.map +1 -1
- package/dist/deploy/workspace-deploy.d.ts.map +1 -1
- package/dist/deploy/workspace-deploy.js +81 -1
- package/dist/deploy/workspace-deploy.js.map +1 -1
- package/dist/integrations/a2a-continuation-processor.d.ts.map +1 -1
- package/dist/integrations/a2a-continuation-processor.js +21 -1
- package/dist/integrations/a2a-continuation-processor.js.map +1 -1
- package/dist/server/framework-request-handler.d.ts.map +1 -1
- package/dist/server/framework-request-handler.js +22 -5
- package/dist/server/framework-request-handler.js.map +1 -1
- package/dist/templates/workspace-root/.env.example +23 -2
- package/package.json +1 -1
- package/src/templates/workspace-root/.env.example +23 -2
package/dist/a2a/client.d.ts
CHANGED
|
@@ -16,7 +16,8 @@ export declare function signA2AToken(email: string, orgDomain?: string, orgSecre
|
|
|
16
16
|
export declare class A2AClient {
|
|
17
17
|
private baseUrl;
|
|
18
18
|
private apiKey?;
|
|
19
|
-
private
|
|
19
|
+
private endpointCandidates;
|
|
20
|
+
private endpointResolved;
|
|
20
21
|
private requestTimeoutMs?;
|
|
21
22
|
constructor(baseUrl: string, apiKey?: string, options?: {
|
|
22
23
|
requestTimeoutMs?: number;
|
|
@@ -69,6 +70,8 @@ export declare class A2AClient {
|
|
|
69
70
|
contextId?: string;
|
|
70
71
|
metadata?: Record<string, unknown>;
|
|
71
72
|
}): AsyncGenerator<Task>;
|
|
73
|
+
private ensureEndpointCandidates;
|
|
74
|
+
private postJson;
|
|
72
75
|
}
|
|
73
76
|
/**
|
|
74
77
|
* One-shot convenience function: send a text message and get a text response.
|
package/dist/a2a/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/a2a/client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,SAAS,EAGT,OAAO,EACP,IAAI,EACL,MAAM,YAAY,CAAC;AAEpB,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;gBAEf,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM;CAW9D;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,KAAK,EAAE,MAAM,EACb,SAAS,CAAC,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CAuBjB;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,OAAO,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/a2a/client.ts"],"names":[],"mappings":"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"}
|
package/dist/a2a/client.js
CHANGED
|
@@ -42,10 +42,17 @@ export async function signA2AToken(email, orgDomain, orgSecret) {
|
|
|
42
42
|
export class A2AClient {
|
|
43
43
|
baseUrl;
|
|
44
44
|
apiKey;
|
|
45
|
-
|
|
45
|
+
endpointCandidates = [];
|
|
46
|
+
endpointResolved = false;
|
|
46
47
|
requestTimeoutMs;
|
|
47
48
|
constructor(baseUrl, apiKey, options) {
|
|
48
|
-
|
|
49
|
+
const normalized = baseUrl.replace(/\/$/, "");
|
|
50
|
+
const explicitEndpoint = splitExplicitA2AEndpoint(normalized);
|
|
51
|
+
this.baseUrl = explicitEndpoint?.baseUrl ?? normalized;
|
|
52
|
+
if (explicitEndpoint) {
|
|
53
|
+
this.endpointCandidates = [explicitEndpoint.endpointUrl];
|
|
54
|
+
this.endpointResolved = true;
|
|
55
|
+
}
|
|
49
56
|
this.apiKey = apiKey;
|
|
50
57
|
this.requestTimeoutMs = options?.requestTimeoutMs;
|
|
51
58
|
}
|
|
@@ -54,15 +61,25 @@ export class A2AClient {
|
|
|
54
61
|
* Agent-native apps use /_agent-native/a2a, external agents may use /a2a.
|
|
55
62
|
*/
|
|
56
63
|
async resolveEndpoint() {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
64
|
+
await this.ensureEndpointCandidates();
|
|
65
|
+
if (this.endpointCandidates.length <= 1)
|
|
66
|
+
return;
|
|
67
|
+
for (const endpoint of this.endpointCandidates) {
|
|
68
|
+
try {
|
|
69
|
+
const res = await fetch(endpoint, { method: "OPTIONS" });
|
|
70
|
+
if (res.status !== 404 && res.status !== 405) {
|
|
71
|
+
this.endpointCandidates = [endpoint];
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (res.status === 405) {
|
|
75
|
+
this.endpointCandidates = [endpoint];
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
// Try the next candidate.
|
|
81
|
+
}
|
|
63
82
|
}
|
|
64
|
-
catch { }
|
|
65
|
-
this.a2aPath = "/a2a"; // Fallback for external A2A servers
|
|
66
83
|
}
|
|
67
84
|
headers() {
|
|
68
85
|
const h = { "Content-Type": "application/json" };
|
|
@@ -78,34 +95,24 @@ export class A2AClient {
|
|
|
78
95
|
method,
|
|
79
96
|
params,
|
|
80
97
|
};
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
res = await fetch(url, {
|
|
93
|
-
method: "POST",
|
|
94
|
-
headers: this.headers(),
|
|
95
|
-
body: JSON.stringify(body),
|
|
96
|
-
signal: controller?.signal,
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
finally {
|
|
100
|
-
if (timer)
|
|
101
|
-
clearTimeout(timer);
|
|
102
|
-
}
|
|
103
|
-
console.log(`[A2A Client] Response: ${res.status} in ${Date.now() - startTime}ms`);
|
|
104
|
-
if (!res.ok) {
|
|
98
|
+
await this.ensureEndpointCandidates();
|
|
99
|
+
let lastError = null;
|
|
100
|
+
for (const url of this.endpointCandidates) {
|
|
101
|
+
console.log(`[A2A Client] POST ${url} method=${method}`);
|
|
102
|
+
const startTime = Date.now();
|
|
103
|
+
const res = await this.postJson(url, body);
|
|
104
|
+
console.log(`[A2A Client] Response: ${res.status} in ${Date.now() - startTime}ms`);
|
|
105
|
+
if (res.ok) {
|
|
106
|
+
this.endpointCandidates = [url];
|
|
107
|
+
return res.json();
|
|
108
|
+
}
|
|
105
109
|
const text = await res.text();
|
|
106
|
-
|
|
110
|
+
lastError = new Error(`A2A request failed (${res.status}): ${text}`);
|
|
111
|
+
if (!shouldTryNextEndpoint(res.status)) {
|
|
112
|
+
throw lastError;
|
|
113
|
+
}
|
|
107
114
|
}
|
|
108
|
-
|
|
115
|
+
throw lastError ?? new Error("No A2A endpoint candidates available");
|
|
109
116
|
}
|
|
110
117
|
async getAgentCard() {
|
|
111
118
|
const res = await fetch(`${this.baseUrl}/.well-known/agent-card.json`);
|
|
@@ -184,14 +191,22 @@ export class A2AClient {
|
|
|
184
191
|
metadata: opts?.metadata,
|
|
185
192
|
},
|
|
186
193
|
};
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
194
|
+
await this.ensureEndpointCandidates();
|
|
195
|
+
let res = null;
|
|
196
|
+
let lastError = null;
|
|
197
|
+
for (const candidate of this.endpointCandidates) {
|
|
198
|
+
res = await this.postJson(candidate, body);
|
|
199
|
+
if (res.ok) {
|
|
200
|
+
this.endpointCandidates = [candidate];
|
|
201
|
+
break;
|
|
202
|
+
}
|
|
193
203
|
const text = await res.text();
|
|
194
|
-
|
|
204
|
+
lastError = new Error(`A2A stream failed (${res.status}): ${text}`);
|
|
205
|
+
if (!shouldTryNextEndpoint(res.status))
|
|
206
|
+
throw lastError;
|
|
207
|
+
}
|
|
208
|
+
if (!res?.ok) {
|
|
209
|
+
throw lastError ?? new Error("No A2A endpoint candidates available");
|
|
195
210
|
}
|
|
196
211
|
const reader = res.body?.getReader();
|
|
197
212
|
if (!reader)
|
|
@@ -221,6 +236,100 @@ export class A2AClient {
|
|
|
221
236
|
}
|
|
222
237
|
}
|
|
223
238
|
}
|
|
239
|
+
async ensureEndpointCandidates() {
|
|
240
|
+
if (this.endpointResolved)
|
|
241
|
+
return;
|
|
242
|
+
this.endpointResolved = true;
|
|
243
|
+
const candidates = [];
|
|
244
|
+
addDefaultEndpointCandidates(candidates, this.baseUrl);
|
|
245
|
+
try {
|
|
246
|
+
const card = await this.getAgentCard();
|
|
247
|
+
const cardUrl = normalizeUrl(card.url, this.baseUrl);
|
|
248
|
+
if (cardUrl) {
|
|
249
|
+
const explicitEndpoint = splitExplicitA2AEndpoint(cardUrl);
|
|
250
|
+
if (explicitEndpoint) {
|
|
251
|
+
candidates.unshift(explicitEndpoint.endpointUrl);
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
addDefaultEndpointCandidates(candidates, cardUrl);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
catch {
|
|
259
|
+
// Agent cards are discovery hints. Fall back to conventional endpoints.
|
|
260
|
+
}
|
|
261
|
+
this.endpointCandidates = unique(candidates);
|
|
262
|
+
}
|
|
263
|
+
async postJson(url, body) {
|
|
264
|
+
const controller = this.requestTimeoutMs
|
|
265
|
+
? new AbortController()
|
|
266
|
+
: undefined;
|
|
267
|
+
const timer = controller && this.requestTimeoutMs
|
|
268
|
+
? setTimeout(() => controller.abort(), this.requestTimeoutMs)
|
|
269
|
+
: undefined;
|
|
270
|
+
try {
|
|
271
|
+
return await fetch(url, {
|
|
272
|
+
method: "POST",
|
|
273
|
+
headers: this.headers(),
|
|
274
|
+
body: JSON.stringify(body),
|
|
275
|
+
signal: controller?.signal,
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
finally {
|
|
279
|
+
if (timer)
|
|
280
|
+
clearTimeout(timer);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
function splitExplicitA2AEndpoint(url) {
|
|
285
|
+
try {
|
|
286
|
+
const parsed = new URL(url);
|
|
287
|
+
const pathname = parsed.pathname.replace(/\/$/, "");
|
|
288
|
+
if (pathname.endsWith("/_agent-native/a2a")) {
|
|
289
|
+
parsed.pathname = pathname.slice(0, -"/_agent-native/a2a".length) || "/";
|
|
290
|
+
parsed.search = "";
|
|
291
|
+
parsed.hash = "";
|
|
292
|
+
return {
|
|
293
|
+
baseUrl: parsed.toString().replace(/\/$/, ""),
|
|
294
|
+
endpointUrl: url,
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
if (pathname.endsWith("/a2a")) {
|
|
298
|
+
parsed.pathname = pathname.slice(0, -"/a2a".length) || "/";
|
|
299
|
+
parsed.search = "";
|
|
300
|
+
parsed.hash = "";
|
|
301
|
+
return {
|
|
302
|
+
baseUrl: parsed.toString().replace(/\/$/, ""),
|
|
303
|
+
endpointUrl: url,
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
catch {
|
|
308
|
+
// Relative or invalid URLs are handled by the caller's normal fetch path.
|
|
309
|
+
}
|
|
310
|
+
return null;
|
|
311
|
+
}
|
|
312
|
+
function addDefaultEndpointCandidates(candidates, baseUrl) {
|
|
313
|
+
const base = baseUrl.replace(/\/$/, "");
|
|
314
|
+
candidates.push(`${base}/_agent-native/a2a`, `${base}/a2a`);
|
|
315
|
+
}
|
|
316
|
+
function normalizeUrl(value, baseUrl) {
|
|
317
|
+
if (!value)
|
|
318
|
+
return null;
|
|
319
|
+
try {
|
|
320
|
+
return new URL(value, `${baseUrl.replace(/\/$/, "")}/`)
|
|
321
|
+
.toString()
|
|
322
|
+
.replace(/\/$/, "");
|
|
323
|
+
}
|
|
324
|
+
catch {
|
|
325
|
+
return null;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
function shouldTryNextEndpoint(status) {
|
|
329
|
+
return status === 404 || status === 405;
|
|
330
|
+
}
|
|
331
|
+
function unique(values) {
|
|
332
|
+
return Array.from(new Set(values));
|
|
224
333
|
}
|
|
225
334
|
/**
|
|
226
335
|
* One-shot convenience function: send a text message and get a text response.
|
package/dist/a2a/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/a2a/client.ts"],"names":[],"mappings":"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","sourcesContent":["import * as jose from \"jose\";\nimport type {\n AgentCard,\n JsonRpcRequest,\n JsonRpcResponse,\n Message,\n Task,\n} from \"./types.js\";\n\nexport class A2ATaskTimeoutError extends Error {\n readonly taskId: string;\n readonly lastTask: Task;\n readonly lastState: string;\n readonly timeoutMs: number;\n\n constructor(taskId: string, lastTask: Task, timeoutMs: number) {\n const lastState = lastTask.status.state;\n super(\n `A2A task ${taskId} did not complete within ${timeoutMs}ms (last state: ${lastState})`,\n );\n this.name = \"A2ATaskTimeoutError\";\n this.taskId = taskId;\n this.lastTask = lastTask;\n this.lastState = lastState;\n this.timeoutMs = timeoutMs;\n }\n}\n\n/**\n * Sign a JWT for A2A cross-app identity verification.\n *\n * Uses A2A_SECRET as an HMAC key. The token contains the caller's email\n * as `sub`, so the receiving app can verify who's calling.\n */\nexport async function signA2AToken(\n email: string,\n orgDomain?: string,\n orgSecret?: string,\n): Promise<string> {\n const secret = orgSecret || process.env.A2A_SECRET;\n if (!secret) {\n throw new Error(\n \"No A2A secret available. Set an org-level A2A secret in Team settings, \" +\n \"or set A2A_SECRET as an environment variable on all apps that need to verify identity.\",\n );\n }\n\n const appUrl =\n process.env.APP_URL ||\n process.env.BETTER_AUTH_URL ||\n \"http://localhost:3000\";\n\n return new jose.SignJWT({\n sub: email,\n ...(orgDomain ? { org_domain: orgDomain } : {}),\n })\n .setProtectedHeader({ alg: \"HS256\" })\n .setIssuer(appUrl)\n .setIssuedAt()\n .setExpirationTime(\"15m\")\n .sign(new TextEncoder().encode(secret));\n}\n\nexport class A2AClient {\n private baseUrl: string;\n private apiKey?: string;\n private a2aPath = \"/_agent-native/a2a\";\n private requestTimeoutMs?: number;\n\n constructor(\n baseUrl: string,\n apiKey?: string,\n options?: { requestTimeoutMs?: number },\n ) {\n this.baseUrl = baseUrl.replace(/\\/$/, \"\");\n this.apiKey = apiKey;\n this.requestTimeoutMs = options?.requestTimeoutMs;\n }\n\n /**\n * Detect which A2A path the target agent uses.\n * Agent-native apps use /_agent-native/a2a, external agents may use /a2a.\n */\n async resolveEndpoint(): Promise<void> {\n try {\n const res = await fetch(`${this.baseUrl}/_agent-native/a2a`, {\n method: \"OPTIONS\",\n });\n if (res.status !== 404) return; // /_agent-native/a2a exists\n } catch {}\n this.a2aPath = \"/a2a\"; // Fallback for external A2A servers\n }\n\n private headers(): Record<string, string> {\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (this.apiKey) {\n h[\"Authorization\"] = `Bearer ${this.apiKey}`;\n }\n return h;\n }\n\n private async rpc(\n method: string,\n params: Record<string, unknown>,\n ): Promise<JsonRpcResponse> {\n const body: JsonRpcRequest = {\n jsonrpc: \"2.0\",\n id: Date.now(),\n method,\n params,\n };\n\n const url = `${this.baseUrl}${this.a2aPath}`;\n console.log(`[A2A Client] POST ${url} method=${method}`);\n const startTime = Date.now();\n const controller = this.requestTimeoutMs\n ? new AbortController()\n : undefined;\n const timer =\n controller && this.requestTimeoutMs\n ? setTimeout(() => controller.abort(), this.requestTimeoutMs)\n : undefined;\n let res!: Response;\n try {\n res = await fetch(url, {\n method: \"POST\",\n headers: this.headers(),\n body: JSON.stringify(body),\n signal: controller?.signal,\n });\n } finally {\n if (timer) clearTimeout(timer);\n }\n console.log(\n `[A2A Client] Response: ${res.status} in ${Date.now() - startTime}ms`,\n );\n\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`A2A request failed (${res.status}): ${text}`);\n }\n\n return res.json() as Promise<JsonRpcResponse>;\n }\n\n async getAgentCard(): Promise<AgentCard> {\n const res = await fetch(`${this.baseUrl}/.well-known/agent-card.json`);\n if (!res.ok) {\n throw new Error(`Failed to fetch agent card (${res.status})`);\n }\n return res.json() as Promise<AgentCard>;\n }\n\n async send(\n message: Message,\n opts?: {\n contextId?: string;\n metadata?: Record<string, unknown>;\n /**\n * If true, ask the server to return the task immediately in `working`\n * state and process the handler in the background. The caller should\n * then poll `getTask(taskId)` until `completed` / `failed` / `canceled`.\n *\n * Use this when you expect the handler may exceed a synchronous\n * serverless request budget.\n */\n async?: boolean;\n },\n ): Promise<Task> {\n const response = await this.rpc(\"message/send\", {\n message,\n contextId: opts?.contextId,\n metadata: opts?.metadata,\n ...(opts?.async ? { async: true } : {}),\n });\n\n if (response.error) {\n throw new Error(\n `A2A error (${response.error.code}): ${response.error.message}`,\n );\n }\n\n return response.result as Task;\n }\n\n /**\n * Poll for a task by id. Used in async mode after `send({ async: true })`.\n */\n async getTask(taskId: string): Promise<Task> {\n const response = await this.rpc(\"tasks/get\", { id: taskId });\n if (response.error) {\n throw new Error(\n `A2A error (${response.error.code}): ${response.error.message}`,\n );\n }\n return response.result as Task;\n }\n\n /**\n * Send a message in async mode and poll until the task reaches a terminal\n * state. This is the recommended path on serverless hosts with short\n * function timeouts (Netlify, Vercel) where a synchronous LLM-driven A2A\n * call can exceed the gateway limit.\n *\n * Each individual fetch returns quickly; long-running work happens on the\n * receiving side and is checked via `tasks/get`.\n */\n async sendAndWait(\n message: Message,\n opts?: {\n contextId?: string;\n metadata?: Record<string, unknown>;\n /** Total time to wait for completion. Default 5 min. */\n timeoutMs?: number;\n /** Poll interval. Default 2s. */\n pollIntervalMs?: number;\n /** Called with each polled task — useful for surfacing progress. */\n onUpdate?: (task: Task) => void;\n },\n ): Promise<Task> {\n const submitted = await this.send(message, {\n contextId: opts?.contextId,\n metadata: opts?.metadata,\n async: true,\n });\n\n const terminalStates = new Set([\"completed\", \"failed\", \"canceled\"]);\n if (terminalStates.has(submitted.status.state)) return submitted;\n\n const timeoutMs = opts?.timeoutMs ?? 5 * 60_000;\n const pollMs = opts?.pollIntervalMs ?? 2_000;\n const deadline = Date.now() + timeoutMs;\n\n let current = submitted;\n while (Date.now() < deadline) {\n await new Promise((r) => setTimeout(r, pollMs));\n try {\n current = await this.getTask(submitted.id);\n opts?.onUpdate?.(current);\n } catch (err) {\n // Transient fetch failure — keep polling until the deadline.\n continue;\n }\n if (terminalStates.has(current.status.state)) return current;\n }\n throw new A2ATaskTimeoutError(submitted.id, current, timeoutMs);\n }\n\n async *stream(\n message: Message,\n opts?: { contextId?: string; metadata?: Record<string, unknown> },\n ): AsyncGenerator<Task> {\n const body: JsonRpcRequest = {\n jsonrpc: \"2.0\",\n id: Date.now(),\n method: \"message/stream\",\n params: {\n message,\n contextId: opts?.contextId,\n metadata: opts?.metadata,\n },\n };\n\n const res = await fetch(`${this.baseUrl}${this.a2aPath}`, {\n method: \"POST\",\n headers: this.headers(),\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`A2A stream failed (${res.status}): ${text}`);\n }\n\n const reader = res.body?.getReader();\n if (!reader) throw new Error(\"No response body\");\n\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n for (const line of lines) {\n if (!line.startsWith(\"data: \")) continue;\n const json = line.slice(6).trim();\n if (!json) continue;\n\n const response: JsonRpcResponse = JSON.parse(json);\n if (response.error) {\n throw new Error(\n `A2A error (${response.error.code}): ${response.error.message}`,\n );\n }\n if (response.result) {\n yield response.result as Task;\n }\n }\n }\n }\n}\n\n/**\n * One-shot convenience function: send a text message and get a text response.\n *\n * When A2A_SECRET is set and userEmail is provided, outbound calls are signed\n * with a JWT so the receiving app can cryptographically verify the caller's\n * identity (instead of blindly trusting metadata).\n */\nexport async function callAgent(\n url: string,\n text: string,\n opts?: {\n apiKey?: string;\n contextId?: string;\n userEmail?: string;\n orgDomain?: string;\n orgSecret?: string;\n /**\n * Use async/poll instead of a single blocking POST. Recommended for\n * cross-app calls that may exceed a synchronous serverless request budget.\n * Defaults to true so callers get safe behavior out of the box.\n */\n async?: boolean;\n /** Total time to wait for the polled task (default 5 min). */\n timeoutMs?: number;\n },\n): Promise<string> {\n let apiKey = opts?.apiKey;\n\n // Auto-sign with JWT when an A2A secret (org or global) is available and we have a user email\n if (\n !apiKey &&\n opts?.userEmail &&\n (opts?.orgSecret || process.env.A2A_SECRET)\n ) {\n try {\n apiKey = await signA2AToken(\n opts.userEmail,\n opts.orgDomain,\n opts.orgSecret,\n );\n } catch {\n // Fall back to unsigned call\n }\n }\n\n const client = new A2AClient(url, apiKey);\n const metadata: Record<string, unknown> = {};\n if (opts?.userEmail) metadata.userEmail = opts.userEmail;\n if (opts?.orgDomain) metadata.orgDomain = opts.orgDomain;\n\n // Default to async + poll. The receiving A2A server's `_process-task` route\n // runs the handler in a fresh function execution (cross-platform queue\n // pattern), so async mode now works on every host instead of relying on\n // detached promises that get killed on Netlify/Vercel. Callers that\n // explicitly want a single-shot blocking POST can pass `async: false`.\n const useAsync = opts?.async ?? true;\n const message: Message = {\n role: \"user\",\n parts: [{ type: \"text\", text }],\n };\n\n let task: Task;\n if (useAsync) {\n task = await client.sendAndWait(message, {\n contextId: opts?.contextId,\n metadata,\n timeoutMs: opts?.timeoutMs,\n });\n } else {\n task = await client.send(message, {\n contextId: opts?.contextId,\n metadata,\n });\n }\n\n // Extract text from the response\n const responseMessage = task.status.message;\n if (responseMessage) {\n const textParts = responseMessage.parts\n .filter((p): p is { type: \"text\"; text: string } => p.type === \"text\")\n .map((p) => p.text);\n return textParts.join(\"\\n\");\n }\n\n return \"\";\n}\n"]}
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/a2a/client.ts"],"names":[],"mappings":"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","sourcesContent":["import * as jose from \"jose\";\nimport type {\n AgentCard,\n JsonRpcRequest,\n JsonRpcResponse,\n Message,\n Task,\n} from \"./types.js\";\n\nexport class A2ATaskTimeoutError extends Error {\n readonly taskId: string;\n readonly lastTask: Task;\n readonly lastState: string;\n readonly timeoutMs: number;\n\n constructor(taskId: string, lastTask: Task, timeoutMs: number) {\n const lastState = lastTask.status.state;\n super(\n `A2A task ${taskId} did not complete within ${timeoutMs}ms (last state: ${lastState})`,\n );\n this.name = \"A2ATaskTimeoutError\";\n this.taskId = taskId;\n this.lastTask = lastTask;\n this.lastState = lastState;\n this.timeoutMs = timeoutMs;\n }\n}\n\n/**\n * Sign a JWT for A2A cross-app identity verification.\n *\n * Uses A2A_SECRET as an HMAC key. The token contains the caller's email\n * as `sub`, so the receiving app can verify who's calling.\n */\nexport async function signA2AToken(\n email: string,\n orgDomain?: string,\n orgSecret?: string,\n): Promise<string> {\n const secret = orgSecret || process.env.A2A_SECRET;\n if (!secret) {\n throw new Error(\n \"No A2A secret available. Set an org-level A2A secret in Team settings, \" +\n \"or set A2A_SECRET as an environment variable on all apps that need to verify identity.\",\n );\n }\n\n const appUrl =\n process.env.APP_URL ||\n process.env.BETTER_AUTH_URL ||\n \"http://localhost:3000\";\n\n return new jose.SignJWT({\n sub: email,\n ...(orgDomain ? { org_domain: orgDomain } : {}),\n })\n .setProtectedHeader({ alg: \"HS256\" })\n .setIssuer(appUrl)\n .setIssuedAt()\n .setExpirationTime(\"15m\")\n .sign(new TextEncoder().encode(secret));\n}\n\nexport class A2AClient {\n private baseUrl: string;\n private apiKey?: string;\n private endpointCandidates: string[] = [];\n private endpointResolved = false;\n private requestTimeoutMs?: number;\n\n constructor(\n baseUrl: string,\n apiKey?: string,\n options?: { requestTimeoutMs?: number },\n ) {\n const normalized = baseUrl.replace(/\\/$/, \"\");\n const explicitEndpoint = splitExplicitA2AEndpoint(normalized);\n this.baseUrl = explicitEndpoint?.baseUrl ?? normalized;\n if (explicitEndpoint) {\n this.endpointCandidates = [explicitEndpoint.endpointUrl];\n this.endpointResolved = true;\n }\n this.apiKey = apiKey;\n this.requestTimeoutMs = options?.requestTimeoutMs;\n }\n\n /**\n * Detect which A2A path the target agent uses.\n * Agent-native apps use /_agent-native/a2a, external agents may use /a2a.\n */\n async resolveEndpoint(): Promise<void> {\n await this.ensureEndpointCandidates();\n if (this.endpointCandidates.length <= 1) return;\n\n for (const endpoint of this.endpointCandidates) {\n try {\n const res = await fetch(endpoint, { method: \"OPTIONS\" });\n if (res.status !== 404 && res.status !== 405) {\n this.endpointCandidates = [endpoint];\n return;\n }\n if (res.status === 405) {\n this.endpointCandidates = [endpoint];\n return;\n }\n } catch {\n // Try the next candidate.\n }\n }\n }\n\n private headers(): Record<string, string> {\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (this.apiKey) {\n h[\"Authorization\"] = `Bearer ${this.apiKey}`;\n }\n return h;\n }\n\n private async rpc(\n method: string,\n params: Record<string, unknown>,\n ): Promise<JsonRpcResponse> {\n const body: JsonRpcRequest = {\n jsonrpc: \"2.0\",\n id: Date.now(),\n method,\n params,\n };\n\n await this.ensureEndpointCandidates();\n let lastError: Error | null = null;\n\n for (const url of this.endpointCandidates) {\n console.log(`[A2A Client] POST ${url} method=${method}`);\n const startTime = Date.now();\n const res = await this.postJson(url, body);\n console.log(\n `[A2A Client] Response: ${res.status} in ${Date.now() - startTime}ms`,\n );\n\n if (res.ok) {\n this.endpointCandidates = [url];\n return res.json() as Promise<JsonRpcResponse>;\n }\n\n const text = await res.text();\n lastError = new Error(`A2A request failed (${res.status}): ${text}`);\n if (!shouldTryNextEndpoint(res.status)) {\n throw lastError;\n }\n }\n\n throw lastError ?? new Error(\"No A2A endpoint candidates available\");\n }\n\n async getAgentCard(): Promise<AgentCard> {\n const res = await fetch(`${this.baseUrl}/.well-known/agent-card.json`);\n if (!res.ok) {\n throw new Error(`Failed to fetch agent card (${res.status})`);\n }\n return res.json() as Promise<AgentCard>;\n }\n\n async send(\n message: Message,\n opts?: {\n contextId?: string;\n metadata?: Record<string, unknown>;\n /**\n * If true, ask the server to return the task immediately in `working`\n * state and process the handler in the background. The caller should\n * then poll `getTask(taskId)` until `completed` / `failed` / `canceled`.\n *\n * Use this when you expect the handler may exceed a synchronous\n * serverless request budget.\n */\n async?: boolean;\n },\n ): Promise<Task> {\n const response = await this.rpc(\"message/send\", {\n message,\n contextId: opts?.contextId,\n metadata: opts?.metadata,\n ...(opts?.async ? { async: true } : {}),\n });\n\n if (response.error) {\n throw new Error(\n `A2A error (${response.error.code}): ${response.error.message}`,\n );\n }\n\n return response.result as Task;\n }\n\n /**\n * Poll for a task by id. Used in async mode after `send({ async: true })`.\n */\n async getTask(taskId: string): Promise<Task> {\n const response = await this.rpc(\"tasks/get\", { id: taskId });\n if (response.error) {\n throw new Error(\n `A2A error (${response.error.code}): ${response.error.message}`,\n );\n }\n return response.result as Task;\n }\n\n /**\n * Send a message in async mode and poll until the task reaches a terminal\n * state. This is the recommended path on serverless hosts with short\n * function timeouts (Netlify, Vercel) where a synchronous LLM-driven A2A\n * call can exceed the gateway limit.\n *\n * Each individual fetch returns quickly; long-running work happens on the\n * receiving side and is checked via `tasks/get`.\n */\n async sendAndWait(\n message: Message,\n opts?: {\n contextId?: string;\n metadata?: Record<string, unknown>;\n /** Total time to wait for completion. Default 5 min. */\n timeoutMs?: number;\n /** Poll interval. Default 2s. */\n pollIntervalMs?: number;\n /** Called with each polled task — useful for surfacing progress. */\n onUpdate?: (task: Task) => void;\n },\n ): Promise<Task> {\n const submitted = await this.send(message, {\n contextId: opts?.contextId,\n metadata: opts?.metadata,\n async: true,\n });\n\n const terminalStates = new Set([\"completed\", \"failed\", \"canceled\"]);\n if (terminalStates.has(submitted.status.state)) return submitted;\n\n const timeoutMs = opts?.timeoutMs ?? 5 * 60_000;\n const pollMs = opts?.pollIntervalMs ?? 2_000;\n const deadline = Date.now() + timeoutMs;\n\n let current = submitted;\n while (Date.now() < deadline) {\n await new Promise((r) => setTimeout(r, pollMs));\n try {\n current = await this.getTask(submitted.id);\n opts?.onUpdate?.(current);\n } catch (err) {\n // Transient fetch failure — keep polling until the deadline.\n continue;\n }\n if (terminalStates.has(current.status.state)) return current;\n }\n throw new A2ATaskTimeoutError(submitted.id, current, timeoutMs);\n }\n\n async *stream(\n message: Message,\n opts?: { contextId?: string; metadata?: Record<string, unknown> },\n ): AsyncGenerator<Task> {\n const body: JsonRpcRequest = {\n jsonrpc: \"2.0\",\n id: Date.now(),\n method: \"message/stream\",\n params: {\n message,\n contextId: opts?.contextId,\n metadata: opts?.metadata,\n },\n };\n\n await this.ensureEndpointCandidates();\n let res: Response | null = null;\n let lastError: Error | null = null;\n for (const candidate of this.endpointCandidates) {\n res = await this.postJson(candidate, body);\n if (res.ok) {\n this.endpointCandidates = [candidate];\n break;\n }\n const text = await res.text();\n lastError = new Error(`A2A stream failed (${res.status}): ${text}`);\n if (!shouldTryNextEndpoint(res.status)) throw lastError;\n }\n if (!res?.ok) {\n throw lastError ?? new Error(\"No A2A endpoint candidates available\");\n }\n\n const reader = res.body?.getReader();\n if (!reader) throw new Error(\"No response body\");\n\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n for (const line of lines) {\n if (!line.startsWith(\"data: \")) continue;\n const json = line.slice(6).trim();\n if (!json) continue;\n\n const response: JsonRpcResponse = JSON.parse(json);\n if (response.error) {\n throw new Error(\n `A2A error (${response.error.code}): ${response.error.message}`,\n );\n }\n if (response.result) {\n yield response.result as Task;\n }\n }\n }\n }\n\n private async ensureEndpointCandidates(): Promise<void> {\n if (this.endpointResolved) return;\n this.endpointResolved = true;\n\n const candidates: string[] = [];\n addDefaultEndpointCandidates(candidates, this.baseUrl);\n\n try {\n const card = await this.getAgentCard();\n const cardUrl = normalizeUrl(card.url, this.baseUrl);\n if (cardUrl) {\n const explicitEndpoint = splitExplicitA2AEndpoint(cardUrl);\n if (explicitEndpoint) {\n candidates.unshift(explicitEndpoint.endpointUrl);\n } else {\n addDefaultEndpointCandidates(candidates, cardUrl);\n }\n }\n } catch {\n // Agent cards are discovery hints. Fall back to conventional endpoints.\n }\n\n this.endpointCandidates = unique(candidates);\n }\n\n private async postJson(url: string, body: JsonRpcRequest): Promise<Response> {\n const controller = this.requestTimeoutMs\n ? new AbortController()\n : undefined;\n const timer =\n controller && this.requestTimeoutMs\n ? setTimeout(() => controller.abort(), this.requestTimeoutMs)\n : undefined;\n try {\n return await fetch(url, {\n method: \"POST\",\n headers: this.headers(),\n body: JSON.stringify(body),\n signal: controller?.signal,\n });\n } finally {\n if (timer) clearTimeout(timer);\n }\n }\n}\n\nfunction splitExplicitA2AEndpoint(\n url: string,\n): { baseUrl: string; endpointUrl: string } | null {\n try {\n const parsed = new URL(url);\n const pathname = parsed.pathname.replace(/\\/$/, \"\");\n if (pathname.endsWith(\"/_agent-native/a2a\")) {\n parsed.pathname = pathname.slice(0, -\"/_agent-native/a2a\".length) || \"/\";\n parsed.search = \"\";\n parsed.hash = \"\";\n return {\n baseUrl: parsed.toString().replace(/\\/$/, \"\"),\n endpointUrl: url,\n };\n }\n if (pathname.endsWith(\"/a2a\")) {\n parsed.pathname = pathname.slice(0, -\"/a2a\".length) || \"/\";\n parsed.search = \"\";\n parsed.hash = \"\";\n return {\n baseUrl: parsed.toString().replace(/\\/$/, \"\"),\n endpointUrl: url,\n };\n }\n } catch {\n // Relative or invalid URLs are handled by the caller's normal fetch path.\n }\n return null;\n}\n\nfunction addDefaultEndpointCandidates(candidates: string[], baseUrl: string) {\n const base = baseUrl.replace(/\\/$/, \"\");\n candidates.push(`${base}/_agent-native/a2a`, `${base}/a2a`);\n}\n\nfunction normalizeUrl(\n value: string | undefined,\n baseUrl: string,\n): string | null {\n if (!value) return null;\n try {\n return new URL(value, `${baseUrl.replace(/\\/$/, \"\")}/`)\n .toString()\n .replace(/\\/$/, \"\");\n } catch {\n return null;\n }\n}\n\nfunction shouldTryNextEndpoint(status: number): boolean {\n return status === 404 || status === 405;\n}\n\nfunction unique(values: string[]): string[] {\n return Array.from(new Set(values));\n}\n\n/**\n * One-shot convenience function: send a text message and get a text response.\n *\n * When A2A_SECRET is set and userEmail is provided, outbound calls are signed\n * with a JWT so the receiving app can cryptographically verify the caller's\n * identity (instead of blindly trusting metadata).\n */\nexport async function callAgent(\n url: string,\n text: string,\n opts?: {\n apiKey?: string;\n contextId?: string;\n userEmail?: string;\n orgDomain?: string;\n orgSecret?: string;\n /**\n * Use async/poll instead of a single blocking POST. Recommended for\n * cross-app calls that may exceed a synchronous serverless request budget.\n * Defaults to true so callers get safe behavior out of the box.\n */\n async?: boolean;\n /** Total time to wait for the polled task (default 5 min). */\n timeoutMs?: number;\n },\n): Promise<string> {\n let apiKey = opts?.apiKey;\n\n // Auto-sign with JWT when an A2A secret (org or global) is available and we have a user email\n if (\n !apiKey &&\n opts?.userEmail &&\n (opts?.orgSecret || process.env.A2A_SECRET)\n ) {\n try {\n apiKey = await signA2AToken(\n opts.userEmail,\n opts.orgDomain,\n opts.orgSecret,\n );\n } catch {\n // Fall back to unsigned call\n }\n }\n\n const client = new A2AClient(url, apiKey);\n const metadata: Record<string, unknown> = {};\n if (opts?.userEmail) metadata.userEmail = opts.userEmail;\n if (opts?.orgDomain) metadata.orgDomain = opts.orgDomain;\n\n // Default to async + poll. The receiving A2A server's `_process-task` route\n // runs the handler in a fresh function execution (cross-platform queue\n // pattern), so async mode now works on every host instead of relying on\n // detached promises that get killed on Netlify/Vercel. Callers that\n // explicitly want a single-shot blocking POST can pass `async: false`.\n const useAsync = opts?.async ?? true;\n const message: Message = {\n role: \"user\",\n parts: [{ type: \"text\", text }],\n };\n\n let task: Task;\n if (useAsync) {\n task = await client.sendAndWait(message, {\n contextId: opts?.contextId,\n metadata,\n timeoutMs: opts?.timeoutMs,\n });\n } else {\n task = await client.send(message, {\n contextId: opts?.contextId,\n metadata,\n });\n }\n\n // Extract text from the response\n const responseMessage = task.status.message;\n if (responseMessage) {\n const textParts = responseMessage.parts\n .filter((p): p is { type: \"text\"; text: string } => p.type === \"text\")\n .map((p) => p.text);\n return textParts.join(\"\\n\");\n }\n\n return \"\";\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NewWorkspaceAppFlow.d.ts","sourceRoot":"","sources":["../../src/client/NewWorkspaceAppFlow.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"NewWorkspaceAppFlow.d.ts","sourceRoot":"","sources":["../../src/client/NewWorkspaceAppFlow.tsx"],"names":[],"mappings":"AAeA,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,wBAAwB;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AA0DD,wBAAgB,mBAAmB,CAAC,EAClC,SAAqB,EACrB,SAAc,EACd,gBAAgB,GACjB,EAAE,wBAAwB,2CAqV1B"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useMemo, useState } from "react";
|
|
3
|
-
import { IconArrowUpRight, IconCheck, IconCode, IconKey, IconLoader2, IconPlus, } from "@tabler/icons-react";
|
|
3
|
+
import { IconArrowUpRight, IconCheck, IconChevronDown, IconCode, IconKey, IconLoader2, IconPlus, } from "@tabler/icons-react";
|
|
4
4
|
import { agentNativePath, appBasePath } from "./api-path.js";
|
|
5
5
|
import { sendToAgentChat } from "./agent-chat.js";
|
|
6
6
|
import { isInBuilderFrame } from "./builder-frame.js";
|
|
@@ -96,6 +96,9 @@ export function NewWorkspaceAppFlow({ sourceApp = "starter", className = "", dis
|
|
|
96
96
|
setAppName(titleFromPrompt(prompt));
|
|
97
97
|
}, [prompt, appName]);
|
|
98
98
|
const selectedSecrets = useMemo(() => secrets.filter((secret) => selectedSecretIds.includes(secret.id)), [secrets, selectedSecretIds]);
|
|
99
|
+
const selectedSecretLabel = selectedSecretIds.length === 0
|
|
100
|
+
? "No keys selected"
|
|
101
|
+
: `${selectedSecretIds.length} key${selectedSecretIds.length === 1 ? "" : "s"} selected`;
|
|
99
102
|
const canSubmit = prompt.trim().length > 0 && slugify(appName).length > 0;
|
|
100
103
|
const submitShortcut = typeof navigator !== "undefined" &&
|
|
101
104
|
/Mac|iPhone|iPad/.test(navigator.userAgent)
|
|
@@ -195,13 +198,15 @@ export function NewWorkspaceAppFlow({ sourceApp = "starter", className = "", dis
|
|
|
195
198
|
e.preventDefault();
|
|
196
199
|
submit();
|
|
197
200
|
}
|
|
198
|
-
}, placeholder: "Describe the app your teammate should be able to use...", rows: 6, className: "min-h-36 w-full resize-none rounded-md border border-input bg-background px-3 py-2 text-sm outline-none focus:border-ring" })] }), _jsxs("div", { className: "grid gap-3 sm:grid-cols-2", children: [_jsxs("label", { className: "block space-y-2", children: [_jsx("span", { className: "text-xs font-medium text-muted-foreground", children: "App path" }), _jsx("input", { value: appName, onChange: (e) => setAppName(slugify(e.target.value)), placeholder: "customer-health", className: "h-10 w-full rounded-md border border-input bg-background px-3 text-sm outline-none focus:border-ring" })] }), _jsxs("label", { className: "block space-y-2", children: [_jsx("span", { className: "text-xs font-medium text-muted-foreground", children: "Starter template" }), _jsx("select", { value: template, onChange: (e) => setTemplate(e.target.value), className: "h-10 w-full rounded-md border border-input bg-background px-3 text-sm outline-none focus:border-ring", children: TEMPLATE_OPTIONS.map((option) => (_jsx("option", { value: option.value, children: option.label }, option.value))) })] })] }), _jsxs("div", { className: "flex items-center justify-end gap-3", children: [_jsxs("span", { className: "text-[11px] text-muted-foreground/75", children: [submitShortcut, "+Enter to submit"] }), _jsxs("button", { type: "button", onClick: submit, disabled: !canSubmit || isSubmitting, className: "inline-flex h-10 items-center gap-2 rounded-md bg-foreground px-4 text-sm font-medium text-background disabled:cursor-not-allowed disabled:opacity-40", children: [isSubmitting ? (_jsx(IconLoader2, { className: "h-4 w-4 animate-spin" })) : (_jsx(IconCode, { className: "h-4 w-4" })), "Create app"] })] }), statusMessage ? (_jsxs("div", { className: "rounded-md border border-border bg-muted/40 px-3 py-2 text-sm text-muted-foreground", children: [statusMessage, branchUrl ? (_jsxs("a", { href: branchUrl, target: "_blank", rel: "noreferrer", className: "ml-2 inline-flex items-center gap-1 font-medium text-foreground underline", children: ["Open branch ", _jsx(IconArrowUpRight, { className: "h-3 w-3" })] })) : null] })) : null] })] }), _jsxs("aside", { className: "rounded-lg border border-border bg-card", children: [_jsx("div", { className: "border-b border-border px-4 py-3", children: _jsxs("div", { className: "flex items-center gap-2 text-sm font-medium", children: [_jsx(IconKey, { className: "h-4 w-4" }), "Dispatch keys"] }) }), _jsx("div", { className: "max-h-[440px] space-y-2 overflow-y-auto p-3", children: secretsError ? (_jsx("p", { className: "rounded-md border border-dashed border-border px-3 py-3 text-xs text-muted-foreground", children: secretsError })) : secrets.length === 0 ? (_jsx("p", { className: "rounded-md border border-dashed border-border px-3 py-3 text-xs text-muted-foreground", children: "No Dispatch vault keys found yet." })) : (secrets.map((secret) => {
|
|
201
|
+
}, placeholder: "Describe the app your teammate should be able to use...", rows: 6, className: "min-h-36 w-full resize-none rounded-md border border-input bg-background px-3 py-2 text-sm outline-none focus:border-ring" })] }), _jsxs("div", { className: "grid gap-3 sm:grid-cols-2", children: [_jsxs("label", { className: "block space-y-2", children: [_jsx("span", { className: "text-xs font-medium text-muted-foreground", children: "App path" }), _jsx("input", { value: appName, onChange: (e) => setAppName(slugify(e.target.value)), placeholder: "customer-health", className: "h-10 w-full rounded-md border border-input bg-background px-3 text-sm outline-none focus:border-ring" })] }), _jsxs("label", { className: "block space-y-2", children: [_jsx("span", { className: "text-xs font-medium text-muted-foreground", children: "Starter template" }), _jsx("select", { value: template, onChange: (e) => setTemplate(e.target.value), className: "h-10 w-full rounded-md border border-input bg-background px-3 text-sm outline-none focus:border-ring", children: TEMPLATE_OPTIONS.map((option) => (_jsx("option", { value: option.value, children: option.label }, option.value))) })] })] }), _jsxs("div", { className: "flex items-center justify-end gap-3", children: [_jsxs("span", { className: "text-[11px] text-muted-foreground/75", children: [submitShortcut, "+Enter to submit"] }), _jsxs("button", { type: "button", onClick: submit, disabled: !canSubmit || isSubmitting, className: "inline-flex h-10 items-center gap-2 rounded-md bg-foreground px-4 text-sm font-medium text-background disabled:cursor-not-allowed disabled:opacity-40", children: [isSubmitting ? (_jsx(IconLoader2, { className: "h-4 w-4 animate-spin" })) : (_jsx(IconCode, { className: "h-4 w-4" })), "Create app"] })] }), statusMessage ? (_jsxs("div", { className: "rounded-md border border-border bg-muted/40 px-3 py-2 text-sm text-muted-foreground", children: [statusMessage, branchUrl ? (_jsxs("a", { href: branchUrl, target: "_blank", rel: "noreferrer", className: "ml-2 inline-flex items-center gap-1 font-medium text-foreground underline", children: ["Open branch ", _jsx(IconArrowUpRight, { className: "h-3 w-3" })] })) : null] })) : null] })] }), _jsxs("aside", { className: "rounded-lg border border-border bg-card", children: [_jsx("div", { className: "border-b border-border px-4 py-3", children: _jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsxs("div", { className: "flex items-center gap-2 text-sm font-medium", children: [_jsx(IconKey, { className: "h-4 w-4" }), "Dispatch keys"] }), _jsx("span", { className: "shrink-0 rounded border border-border bg-background/40 px-2 py-0.5 text-[11px] text-muted-foreground", children: selectedSecretLabel })] }) }), _jsx("div", { className: "max-h-[440px] space-y-2 overflow-y-auto p-3", children: secretsError ? (_jsx("p", { className: "rounded-md border border-dashed border-border px-3 py-3 text-xs text-muted-foreground", children: secretsError })) : secrets.length === 0 ? (_jsx("p", { className: "rounded-md border border-dashed border-border px-3 py-3 text-xs text-muted-foreground", children: "No Dispatch vault keys found yet." })) : (secrets.map((secret) => {
|
|
199
202
|
const selected = selectedSecretIds.includes(secret.id);
|
|
200
|
-
return (_jsxs("
|
|
201
|
-
? "border-
|
|
202
|
-
: "border-border bg-background/
|
|
203
|
-
|
|
204
|
-
|
|
203
|
+
return (_jsxs("div", { className: `group rounded-md border text-sm transition ${selected
|
|
204
|
+
? "border-primary/45 bg-primary/5 text-foreground shadow-[inset_0_0_0_1px_hsl(var(--primary)/0.08)]"
|
|
205
|
+
: "border-border bg-background/25 text-foreground hover:border-muted-foreground/40 hover:bg-accent/35"}`, children: [_jsxs("button", { type: "button", "aria-pressed": selected, onClick: () => toggleSecret(secret.id), className: "flex w-full items-start gap-3 rounded-md px-3 py-2 text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/30", children: [_jsx("span", { className: `mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded border transition ${selected
|
|
206
|
+
? "border-primary/60 bg-primary/10 text-primary"
|
|
207
|
+
: "border-muted-foreground/35 text-transparent group-hover:border-muted-foreground/60"}`, children: selected ? _jsx(IconCheck, { className: "h-3 w-3" }) : null }), _jsxs("span", { className: "min-w-0 flex-1", children: [_jsx("span", { className: "block truncate font-medium", children: secret.credentialKey }), _jsx("span", { className: "block truncate text-xs text-muted-foreground/70", children: selected
|
|
208
|
+
? "Will be granted to this app"
|
|
209
|
+
: "Click to grant" })] })] }), _jsxs("details", { className: "group/details border-t border-border/60 px-3 py-1.5 text-xs text-muted-foreground/75 open:bg-background/10", children: [_jsxs("summary", { className: "flex cursor-pointer list-none items-center gap-1.5 text-[11px] hover:text-muted-foreground [&::-webkit-details-marker]:hidden", children: [_jsx(IconChevronDown, { className: "h-3 w-3 transition-transform group-open/details:rotate-180" }), "Details"] }), _jsxs("div", { className: "mt-1.5 space-y-1 pb-0.5 pl-4", children: [_jsxs("div", { className: "truncate", children: ["Provider: ", secret.provider || "Not specified"] }), _jsxs("div", { className: "truncate", children: ["Name: ", secret.name] })] })] })] }, secret.id));
|
|
205
210
|
})) })] })] }) }));
|
|
206
211
|
}
|
|
207
212
|
//# sourceMappingURL=NewWorkspaceAppFlow.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NewWorkspaceAppFlow.js","sourceRoot":"","sources":["../../src/client/NewWorkspaceAppFlow.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACrD,OAAO,EACL,gBAAgB,EAChB,SAAS,EACT,QAAQ,EACR,OAAO,EACP,WAAW,EACX,QAAQ,GACT,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAgB/C,MAAM,gBAAgB,GAAG;IACvB,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;IACtC,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE;IAC1C,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE;IACxC,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;IACtC,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;IACpC,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE;IACxC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;IAClC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;IAChC,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;IACpC,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;IACpC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;CAC1B,CAAC;AAEX,SAAS,OAAO,CAAC,KAAa;IAC5B,OAAO,KAAK;SACT,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAClB,CAAC;AAED,SAAS,eAAe,CAAC,MAAc;IACrC,MAAM,OAAO,GAAG,MAAM;SACnB,OAAO,CAAC,sDAAsD,EAAE,GAAG,CAAC;SACpE,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,IAAI,EAAE,CAAC;IACV,OAAO,OAAO,CAAC,OAAO,IAAI,SAAS,CAAC,IAAI,SAAS,CAAC;AACpD,CAAC;AAED,SAAS,SAAS,CAAC,QAAuB,EAAE,MAAc;IACxD,MAAM,IAAI,GAAG,0BAA0B,MAAM,EAAE,CAAC;IAChD,IAAI,QAAQ,KAAK,IAAI;QAAE,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;IACpD,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAChD,OAAO,GAAG,UAAU,GAAG,IAAI,EAAE,CAAC;AAChC,CAAC;AAED,SAAS,uBAAuB,CAAC,SAAkB;IACjD,IAAI,SAAS,KAAK,UAAU;QAAE,OAAO,IAAI,CAAC;IAC1C,MAAM,IAAI,GAAG,WAAW,EAAE,CAAC;IAC3B,IAAI,IAAI,KAAK,WAAW;QAAE,OAAO,IAAI,CAAC;IACtC,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,GAAW,EAAE,IAAkB;IACtD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IAChD,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,IAAI,EAAE,KAAK,IAAI,IAAI,EAAE,OAAO,IAAI,kBAAkB,GAAG,CAAC,MAAM,EAAE,CAC/D,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,EAClC,SAAS,GAAG,SAAS,EACrB,SAAS,GAAG,EAAE,EACd,gBAAgB,GACS;IACzB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACzC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC3C,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAC3B,QAAQ,CAA6C,SAAS,CAAC,CAAC;IAClE,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,GAAG,QAAQ,CAAW,EAAE,CAAC,CAAC;IACzE,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAsB,EAAE,CAAC,CAAC;IAChE,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IACtE,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IACxE,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAChE,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxD,MAAM,EAAE,SAAS,EAAE,GAAG,UAAU,EAAE,CAAC;IAEnC,MAAM,yBAAyB,GAC7B,gBAAgB,KAAK,SAAS;QAC5B,CAAC,CAAC,uBAAuB,CAAC,SAAS,CAAC;QACpC,CAAC,CAAC,gBAAgB,CAAC;IAEvB,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,MAAM,GAAG,GAAG,SAAS,CACnB,yBAAyB,EACzB,2BAA2B,CAC5B,CAAC;QACF,SAAS,CAAC,GAAG,CAAC;aACX,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;YACb,IAAI,SAAS;gBAAE,OAAO;YACtB,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC5C,eAAe,CAAC,IAAI,CAAC,CAAC;QACxB,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACb,IAAI,SAAS;gBAAE,OAAO;YACtB,UAAU,CAAC,EAAE,CAAC,CAAC;YACf,eAAe,CAAC,GAAG,EAAE,OAAO,IAAI,8BAA8B,CAAC,CAAC;QAClE,CAAC,CAAC,CAAC;QACL,OAAO,GAAG,EAAE;YACV,SAAS,GAAG,IAAI,CAAC;QACnB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,yBAAyB,CAAC,CAAC,CAAC;IAEhC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE;YAAE,OAAO;QACtC,UAAU,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC;IACtC,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAEtB,MAAM,eAAe,GAAG,OAAO,CAC7B,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,iBAAiB,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,EACvE,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAC7B,CAAC;IAEF,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;IAC1E,MAAM,cAAc,GAClB,OAAO,SAAS,KAAK,WAAW;QAChC,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;QACzC,CAAC,CAAC,GAAG;QACL,CAAC,CAAC,MAAM,CAAC;IAEb,SAAS,YAAY;QACnB,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,eAAe,CAAC,MAAM,CAAC,CAAC;QAChE,MAAM,OAAO,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvE,OAAO;YACL,kDAAkD;YAClD,EAAE;YACF,aAAa,WAAW,EAAE;YAC1B,2BAA2B,QAAQ,EAAE;YACrC,gBAAgB,MAAM,CAAC,IAAI,EAAE,EAAE;YAC/B,OAAO;gBACL,CAAC,CAAC,8CAA8C,OAAO,EAAE;gBACzD,CAAC,CAAC,iDAAiD;YACrD,EAAE;YACF,sDAAsD,WAAW,kBAAkB,WAAW,4IAA4I;YAC1O,OAAO;gBACL,CAAC,CAAC,oDAAoD,WAAW,mDAAmD;gBACpH,CAAC,CAAC,kEAAkE;YACtE,8EAA8E,WAAW,GAAG;SAC7F,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACf,CAAC;IAED,KAAK,UAAU,oBAAoB,CAAC,WAAmB;QACrD,IAAI,iBAAiB,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAC3C,IAAI,CAAC;YACH,MAAM,SAAS,CACb,SAAS,CAAC,yBAAyB,EAAE,4BAA4B,CAAC,EAClE;gBACE,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;oBACnB,KAAK,EAAE,WAAW;oBAClB,SAAS,EAAE,iBAAiB;iBAC7B,CAAC;aACH,CACF,CAAC;QACJ,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,gBAAgB,CACd,6EAA6E,GAAG,EAAE,OAAO,IAAI,eAAe,EAAE,CAC/G,CAAC;QACJ,CAAC;IACH,CAAC;IAED,KAAK,UAAU,MAAM;QACnB,IAAI,CAAC,SAAS,IAAI,YAAY;YAAE,OAAO;QACvC,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,eAAe,CAAC,MAAM,CAAC,CAAC;QAChE,MAAM,OAAO,GAAG,YAAY,EAAE,CAAC;QAC/B,eAAe,CAAC,IAAI,CAAC,CAAC;QACtB,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACvB,YAAY,CAAC,IAAI,CAAC,CAAC;QAEnB,IAAI,CAAC;YACH,MAAM,oBAAoB,CAAC,WAAW,CAAC,CAAC;YAExC,IAAI,gBAAgB,EAAE,EAAE,CAAC;gBACvB,eAAe,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;gBACzD,gBAAgB,CAAC,uBAAuB,CAAC,CAAC;YAC5C,CAAC;iBAAM,IAAI,SAAS,EAAE,CAAC;gBACrB,eAAe,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;gBACvE,gBAAgB,CAAC,0BAA0B,CAAC,CAAC;YAC/C,CAAC;iBAAM,CAAC;gBACN,MAAM,MAAM,GAAG,MAAM,SAAS,CAC5B,SAAS,CAAC,yBAAyB,EAAE,8BAA8B,CAAC,EACpE;oBACE,MAAM,EAAE,MAAM;oBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;oBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;wBACnB,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE;wBACrB,KAAK,EAAE,WAAW;wBAClB,QAAQ;wBACR,SAAS,EAAE,iBAAiB;wBAC5B,cAAc,EAAE,OAAO;qBACxB,CAAC;iBACH,CACF,CAAC;gBACF,IAAI,MAAM,EAAE,IAAI,KAAK,SAAS,EAAE,CAAC;oBAC/B,YAAY,CAAC,MAAM,EAAE,GAAG,IAAI,IAAI,CAAC,CAAC;oBAClC,gBAAgB,CAAC,yBAAyB,CAAC,CAAC;gBAC9C,CAAC;qBAAM,CAAC;oBACN,gBAAgB,CACd,MAAM,EAAE,OAAO;wBACb,6GAA6G,CAChH,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,gBAAgB,CAAC,GAAG,EAAE,OAAO,IAAI,mCAAmC,CAAC,CAAC;QACxE,CAAC;gBAAS,CAAC;YACT,eAAe,CAAC,KAAK,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IAED,SAAS,YAAY,CAAC,EAAU;QAC9B,oBAAoB,CAAC,CAAC,OAAO,EAAE,EAAE,CAC/B,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YAClB,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,KAAK,EAAE,CAAC;YAC/C,CAAC,CAAC,CAAC,GAAG,OAAO,EAAE,EAAE,CAAC,CACrB,CAAC;IACJ,CAAC;IAED,OAAO,CACL,kBACE,SAAS,EAAE,0DAA0D,SAAS,EAAE,YAEhF,eAAK,SAAS,EAAC,+CAA+C,aAC5D,eAAK,SAAS,EAAC,yCAAyC,aACtD,cAAK,SAAS,EAAC,kCAAkC,YAC/C,eAAK,SAAS,EAAC,6CAA6C,aAC1D,KAAC,QAAQ,IAAC,SAAS,EAAC,SAAS,GAAG,eAE5B,GACF,EACN,eAAK,SAAS,EAAC,eAAe,aAC5B,iBAAO,SAAS,EAAC,iBAAiB,aAChC,eAAM,SAAS,EAAC,2CAA2C,uBAEpD,EACP,mBACE,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAC1C,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE;gDACf,IAAI,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO,EAAE,CAAC;oDAClD,CAAC,CAAC,cAAc,EAAE,CAAC;oDACnB,MAAM,EAAE,CAAC;gDACX,CAAC;4CACH,CAAC,EACD,WAAW,EAAC,yDAAyD,EACrE,IAAI,EAAE,CAAC,EACP,SAAS,EAAC,2HAA2H,GACrI,IACI,EAER,eAAK,SAAS,EAAC,2BAA2B,aACxC,iBAAO,SAAS,EAAC,iBAAiB,aAChC,eAAM,SAAS,EAAC,2CAA2C,yBAEpD,EACP,gBACE,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EACpD,WAAW,EAAC,iBAAiB,EAC7B,SAAS,EAAC,sGAAsG,GAChH,IACI,EACR,iBAAO,SAAS,EAAC,iBAAiB,aAChC,eAAM,SAAS,EAAC,2CAA2C,iCAEpD,EACP,iBACE,KAAK,EAAE,QAAQ,EACf,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CACd,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,KAAwB,CAAC,EAEhD,SAAS,EAAC,sGAAsG,YAE/G,gBAAgB,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAChC,iBAA2B,KAAK,EAAE,MAAM,CAAC,KAAK,YAC3C,MAAM,CAAC,KAAK,IADF,MAAM,CAAC,KAAK,CAEhB,CACV,CAAC,GACK,IACH,IACJ,EAEN,eAAK,SAAS,EAAC,qCAAqC,aAClD,gBAAM,SAAS,EAAC,sCAAsC,aACnD,cAAc,wBACV,EACP,kBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,CAAC,SAAS,IAAI,YAAY,EACpC,SAAS,EAAC,uJAAuJ,aAEhK,YAAY,CAAC,CAAC,CAAC,CACd,KAAC,WAAW,IAAC,SAAS,EAAC,sBAAsB,GAAG,CACjD,CAAC,CAAC,CAAC,CACF,KAAC,QAAQ,IAAC,SAAS,EAAC,SAAS,GAAG,CACjC,kBAEM,IACL,EAEL,aAAa,CAAC,CAAC,CAAC,CACf,eAAK,SAAS,EAAC,qFAAqF,aACjG,aAAa,EACb,SAAS,CAAC,CAAC,CAAC,CACX,aACE,IAAI,EAAE,SAAS,EACf,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,YAAY,EAChB,SAAS,EAAC,2EAA2E,6BAEzE,KAAC,gBAAgB,IAAC,SAAS,EAAC,SAAS,GAAG,IAClD,CACL,CAAC,CAAC,CAAC,IAAI,IACJ,CACP,CAAC,CAAC,CAAC,IAAI,IACJ,IACF,EAEN,iBAAO,SAAS,EAAC,yCAAyC,aACxD,cAAK,SAAS,EAAC,kCAAkC,YAC/C,eAAK,SAAS,EAAC,6CAA6C,aAC1D,KAAC,OAAO,IAAC,SAAS,EAAC,SAAS,GAAG,qBAE3B,GACF,EACN,cAAK,SAAS,EAAC,6CAA6C,YACzD,YAAY,CAAC,CAAC,CAAC,CACd,YAAG,SAAS,EAAC,uFAAuF,YACjG,YAAY,GACX,CACL,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CACzB,YAAG,SAAS,EAAC,uFAAuF,kDAEhG,CACL,CAAC,CAAC,CAAC,CACF,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;gCACrB,MAAM,QAAQ,GAAG,iBAAiB,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gCACvD,OAAO,CACL,kBAEE,IAAI,EAAC,QAAQ,kBACC,QAAQ,EACtB,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,EACtC,SAAS,EAAE,2KACT,QAAQ;wCACN,CAAC,CAAC,4CAA4C;wCAC9C,CAAC,CAAC,oGACN,EAAE,aAEF,eACE,SAAS,EAAE,sFACT,QAAQ;gDACN,CAAC,CAAC,2CAA2C;gDAC7C,CAAC,CAAC,oFACN,EAAE,YAED,QAAQ,CAAC,CAAC,CAAC,KAAC,SAAS,IAAC,SAAS,EAAC,SAAS,GAAG,CAAC,CAAC,CAAC,IAAI,GAC/C,EACP,gBAAM,SAAS,EAAC,SAAS,aACvB,eAAM,SAAS,EAAC,4BAA4B,YACzC,MAAM,CAAC,aAAa,GAChB,EACP,eAAM,SAAS,EAAC,8CAA8C,YAC3D,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,IAAI,GAC1B,IACF,KA1BF,MAAM,CAAC,EAAE,CA2BP,CACV,CAAC;4BACJ,CAAC,CAAC,CACH,GACG,IACA,IACJ,GACE,CACX,CAAC;AACJ,CAAC","sourcesContent":["import { useEffect, useMemo, useState } from \"react\";\nimport {\n IconArrowUpRight,\n IconCheck,\n IconCode,\n IconKey,\n IconLoader2,\n IconPlus,\n} from \"@tabler/icons-react\";\nimport { agentNativePath, appBasePath } from \"./api-path.js\";\nimport { sendToAgentChat } from \"./agent-chat.js\";\nimport { isInBuilderFrame } from \"./builder-frame.js\";\nimport { useDevMode } from \"./use-dev-mode.js\";\n\nexport interface VaultSecretOption {\n id: string;\n name: string;\n credentialKey: string;\n provider?: string | null;\n description?: string | null;\n}\n\nexport interface NewWorkspaceAppFlowProps {\n sourceApp?: string;\n className?: string;\n dispatchBasePath?: string | null;\n}\n\nconst TEMPLATE_OPTIONS = [\n { value: \"starter\", label: \"Starter\" },\n { value: \"analytics\", label: \"Analytics\" },\n { value: \"calendar\", label: \"Calendar\" },\n { value: \"content\", label: \"Content\" },\n { value: \"design\", label: \"Design\" },\n { value: \"dispatch\", label: \"Dispatch\" },\n { value: \"forms\", label: \"Forms\" },\n { value: \"mail\", label: \"Mail\" },\n { value: \"slides\", label: \"Slides\" },\n { value: \"videos\", label: \"Videos\" },\n { value: \"clips\", label: \"Clips\" },\n] as const;\n\nfunction slugify(value: string): string {\n return value\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .replace(/^[^a-z]+/, \"\")\n .slice(0, 48);\n}\n\nfunction titleFromPrompt(prompt: string): string {\n const cleaned = prompt\n .replace(/\\b(build|create|make|an?|the|app|tool|dashboard)\\b/gi, \" \")\n .replace(/\\s+/g, \" \")\n .trim();\n return slugify(cleaned || \"new-app\") || \"new-app\";\n}\n\nfunction actionUrl(basePath: string | null, action: string): string {\n const path = `/_agent-native/actions/${action}`;\n if (basePath === null) return agentNativePath(path);\n const normalized = basePath.replace(/\\/+$/, \"\");\n return `${normalized}${path}`;\n}\n\nfunction defaultDispatchBasePath(sourceApp?: string): string | null {\n if (sourceApp === \"dispatch\") return null;\n const base = appBasePath();\n if (base === \"/dispatch\") return null;\n return \"/dispatch\";\n}\n\nasync function fetchJson(url: string, init?: RequestInit): Promise<any> {\n const res = await fetch(url, init);\n const data = await res.json().catch(() => null);\n if (!res.ok) {\n throw new Error(\n data?.error || data?.message || `Request failed ${res.status}`,\n );\n }\n return data;\n}\n\nexport function NewWorkspaceAppFlow({\n sourceApp = \"starter\",\n className = \"\",\n dispatchBasePath,\n}: NewWorkspaceAppFlowProps) {\n const [prompt, setPrompt] = useState(\"\");\n const [appName, setAppName] = useState(\"\");\n const [template, setTemplate] =\n useState<(typeof TEMPLATE_OPTIONS)[number][\"value\"]>(\"starter\");\n const [selectedSecretIds, setSelectedSecretIds] = useState<string[]>([]);\n const [secrets, setSecrets] = useState<VaultSecretOption[]>([]);\n const [secretsError, setSecretsError] = useState<string | null>(null);\n const [statusMessage, setStatusMessage] = useState<string | null>(null);\n const [branchUrl, setBranchUrl] = useState<string | null>(null);\n const [isSubmitting, setIsSubmitting] = useState(false);\n const { isDevMode } = useDevMode();\n\n const effectiveDispatchBasePath =\n dispatchBasePath === undefined\n ? defaultDispatchBasePath(sourceApp)\n : dispatchBasePath;\n\n useEffect(() => {\n let cancelled = false;\n const url = actionUrl(\n effectiveDispatchBasePath,\n \"list-vault-secret-options\",\n );\n fetchJson(url)\n .then((data) => {\n if (cancelled) return;\n setSecrets(Array.isArray(data) ? data : []);\n setSecretsError(null);\n })\n .catch((err) => {\n if (cancelled) return;\n setSecrets([]);\n setSecretsError(err?.message || \"Could not load Dispatch keys\");\n });\n return () => {\n cancelled = true;\n };\n }, [effectiveDispatchBasePath]);\n\n useEffect(() => {\n if (appName || !prompt.trim()) return;\n setAppName(titleFromPrompt(prompt));\n }, [prompt, appName]);\n\n const selectedSecrets = useMemo(\n () => secrets.filter((secret) => selectedSecretIds.includes(secret.id)),\n [secrets, selectedSecretIds],\n );\n\n const canSubmit = prompt.trim().length > 0 && slugify(appName).length > 0;\n const submitShortcut =\n typeof navigator !== \"undefined\" &&\n /Mac|iPhone|iPad/.test(navigator.userAgent)\n ? \"⌘\"\n : \"Ctrl\";\n\n function buildMessage(): string {\n const safeAppName = slugify(appName) || titleFromPrompt(prompt);\n const keyList = selectedSecrets.map((s) => s.credentialKey).join(\", \");\n return [\n `Create a new agent-native app in this workspace.`,\n ``,\n `App name: ${safeAppName}`,\n `Template to start from: ${template}`,\n `User prompt: ${prompt.trim()}`,\n keyList\n ? `Dispatch vault keys selected for this app: ${keyList}`\n : `Dispatch vault keys selected for this app: none`,\n ``,\n `Use the workspace app layout: create it under apps/${safeAppName}, mount it at /${safeAppName}, keep it on the shared workspace database/hosting model, and avoid table-name collisions by namespacing any new domain tables to the app.`,\n keyList\n ? `Grant the selected Dispatch vault keys to appId \"${safeAppName}\" and sync them once the app server is available.`\n : `Do not grant any Dispatch vault keys unless the user asks later.`,\n `When it is ready, start or update the dev server and navigate the user to /${safeAppName}.`,\n ].join(\"\\n\");\n }\n\n async function grantSelectedSecrets(safeAppName: string) {\n if (selectedSecretIds.length === 0) return;\n try {\n await fetchJson(\n actionUrl(effectiveDispatchBasePath, \"grant-vault-secrets-to-app\"),\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n appId: safeAppName,\n secretIds: selectedSecretIds,\n }),\n },\n );\n } catch (err: any) {\n setStatusMessage(\n `The app request was prepared, but Dispatch grants could not be saved yet: ${err?.message || \"unknown error\"}`,\n );\n }\n }\n\n async function submit() {\n if (!canSubmit || isSubmitting) return;\n const safeAppName = slugify(appName) || titleFromPrompt(prompt);\n const message = buildMessage();\n setIsSubmitting(true);\n setStatusMessage(null);\n setBranchUrl(null);\n\n try {\n await grantSelectedSecrets(safeAppName);\n\n if (isInBuilderFrame()) {\n sendToAgentChat({ message, submit: true, type: \"code\" });\n setStatusMessage(\"Sent to Builder chat.\");\n } else if (isDevMode) {\n sendToAgentChat({ message, submit: true, type: \"code\", newTab: true });\n setStatusMessage(\"Sent to the local agent.\");\n } else {\n const result = await fetchJson(\n actionUrl(effectiveDispatchBasePath, \"start-workspace-app-creation\"),\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n prompt: prompt.trim(),\n appId: safeAppName,\n template,\n secretIds: selectedSecretIds,\n preparedPrompt: message,\n }),\n },\n );\n if (result?.mode === \"builder\") {\n setBranchUrl(result?.url || null);\n setStatusMessage(\"Builder branch created.\");\n } else {\n setStatusMessage(\n result?.message ||\n \"Builder app creation is coming soon here. Open this workspace in Builder to create an app from this prompt.\",\n );\n }\n }\n } catch (err: any) {\n setStatusMessage(err?.message || \"Could not start the new app flow.\");\n } finally {\n setIsSubmitting(false);\n }\n }\n\n function toggleSecret(id: string) {\n setSelectedSecretIds((current) =>\n current.includes(id)\n ? current.filter((existing) => existing !== id)\n : [...current, id],\n );\n }\n\n return (\n <section\n className={`mx-auto flex w-full max-w-5xl flex-col gap-5 px-4 py-6 ${className}`}\n >\n <div className=\"grid gap-5 lg:grid-cols-[minmax(0,1fr)_320px]\">\n <div className=\"rounded-lg border border-border bg-card\">\n <div className=\"border-b border-border px-4 py-3\">\n <div className=\"flex items-center gap-2 text-sm font-medium\">\n <IconPlus className=\"h-4 w-4\" />\n New app\n </div>\n </div>\n <div className=\"space-y-4 p-4\">\n <label className=\"block space-y-2\">\n <span className=\"text-xs font-medium text-muted-foreground\">\n Prompt\n </span>\n <textarea\n value={prompt}\n onChange={(e) => setPrompt(e.target.value)}\n onKeyDown={(e) => {\n if ((e.metaKey || e.ctrlKey) && e.key === \"Enter\") {\n e.preventDefault();\n submit();\n }\n }}\n placeholder=\"Describe the app your teammate should be able to use...\"\n rows={6}\n className=\"min-h-36 w-full resize-none rounded-md border border-input bg-background px-3 py-2 text-sm outline-none focus:border-ring\"\n />\n </label>\n\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <label className=\"block space-y-2\">\n <span className=\"text-xs font-medium text-muted-foreground\">\n App path\n </span>\n <input\n value={appName}\n onChange={(e) => setAppName(slugify(e.target.value))}\n placeholder=\"customer-health\"\n className=\"h-10 w-full rounded-md border border-input bg-background px-3 text-sm outline-none focus:border-ring\"\n />\n </label>\n <label className=\"block space-y-2\">\n <span className=\"text-xs font-medium text-muted-foreground\">\n Starter template\n </span>\n <select\n value={template}\n onChange={(e) =>\n setTemplate(e.target.value as typeof template)\n }\n className=\"h-10 w-full rounded-md border border-input bg-background px-3 text-sm outline-none focus:border-ring\"\n >\n {TEMPLATE_OPTIONS.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n </label>\n </div>\n\n <div className=\"flex items-center justify-end gap-3\">\n <span className=\"text-[11px] text-muted-foreground/75\">\n {submitShortcut}+Enter to submit\n </span>\n <button\n type=\"button\"\n onClick={submit}\n disabled={!canSubmit || isSubmitting}\n className=\"inline-flex h-10 items-center gap-2 rounded-md bg-foreground px-4 text-sm font-medium text-background disabled:cursor-not-allowed disabled:opacity-40\"\n >\n {isSubmitting ? (\n <IconLoader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <IconCode className=\"h-4 w-4\" />\n )}\n Create app\n </button>\n </div>\n\n {statusMessage ? (\n <div className=\"rounded-md border border-border bg-muted/40 px-3 py-2 text-sm text-muted-foreground\">\n {statusMessage}\n {branchUrl ? (\n <a\n href={branchUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"ml-2 inline-flex items-center gap-1 font-medium text-foreground underline\"\n >\n Open branch <IconArrowUpRight className=\"h-3 w-3\" />\n </a>\n ) : null}\n </div>\n ) : null}\n </div>\n </div>\n\n <aside className=\"rounded-lg border border-border bg-card\">\n <div className=\"border-b border-border px-4 py-3\">\n <div className=\"flex items-center gap-2 text-sm font-medium\">\n <IconKey className=\"h-4 w-4\" />\n Dispatch keys\n </div>\n </div>\n <div className=\"max-h-[440px] space-y-2 overflow-y-auto p-3\">\n {secretsError ? (\n <p className=\"rounded-md border border-dashed border-border px-3 py-3 text-xs text-muted-foreground\">\n {secretsError}\n </p>\n ) : secrets.length === 0 ? (\n <p className=\"rounded-md border border-dashed border-border px-3 py-3 text-xs text-muted-foreground\">\n No Dispatch vault keys found yet.\n </p>\n ) : (\n secrets.map((secret) => {\n const selected = selectedSecretIds.includes(secret.id);\n return (\n <button\n key={secret.id}\n type=\"button\"\n aria-pressed={selected}\n onClick={() => toggleSecret(secret.id)}\n className={`group flex w-full items-start gap-3 rounded-md border px-3 py-2 text-left text-sm transition focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/30 ${\n selected\n ? \"border-ring/60 bg-muted/70 text-foreground\"\n : \"border-border bg-background/30 text-foreground hover:border-muted-foreground/40 hover:bg-accent/45\"\n }`}\n >\n <span\n className={`mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded border transition ${\n selected\n ? \"border-ring bg-background text-foreground\"\n : \"border-muted-foreground/35 text-transparent group-hover:border-muted-foreground/60\"\n }`}\n >\n {selected ? <IconCheck className=\"h-3 w-3\" /> : null}\n </span>\n <span className=\"min-w-0\">\n <span className=\"block truncate font-medium\">\n {secret.credentialKey}\n </span>\n <span className=\"block truncate text-xs text-muted-foreground\">\n {secret.provider || secret.name}\n </span>\n </span>\n </button>\n );\n })\n )}\n </div>\n </aside>\n </div>\n </section>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"NewWorkspaceAppFlow.js","sourceRoot":"","sources":["../../src/client/NewWorkspaceAppFlow.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useMemo, useState } from \"react\";\nimport {\n IconArrowUpRight,\n IconCheck,\n IconChevronDown,\n IconCode,\n IconKey,\n IconLoader2,\n IconPlus,\n} from \"@tabler/icons-react\";\nimport { agentNativePath, appBasePath } from \"./api-path.js\";\nimport { sendToAgentChat } from \"./agent-chat.js\";\nimport { isInBuilderFrame } from \"./builder-frame.js\";\nimport { useDevMode } from \"./use-dev-mode.js\";\n\nexport interface VaultSecretOption {\n id: string;\n name: string;\n credentialKey: string;\n provider?: string | null;\n description?: string | null;\n}\n\nexport interface NewWorkspaceAppFlowProps {\n sourceApp?: string;\n className?: string;\n dispatchBasePath?: string | null;\n}\n\nconst TEMPLATE_OPTIONS = [\n { value: \"starter\", label: \"Starter\" },\n { value: \"analytics\", label: \"Analytics\" },\n { value: \"calendar\", label: \"Calendar\" },\n { value: \"content\", label: \"Content\" },\n { value: \"design\", label: \"Design\" },\n { value: \"dispatch\", label: \"Dispatch\" },\n { value: \"forms\", label: \"Forms\" },\n { value: \"mail\", label: \"Mail\" },\n { value: \"slides\", label: \"Slides\" },\n { value: \"videos\", label: \"Videos\" },\n { value: \"clips\", label: \"Clips\" },\n] as const;\n\nfunction slugify(value: string): string {\n return value\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .replace(/^[^a-z]+/, \"\")\n .slice(0, 48);\n}\n\nfunction titleFromPrompt(prompt: string): string {\n const cleaned = prompt\n .replace(/\\b(build|create|make|an?|the|app|tool|dashboard)\\b/gi, \" \")\n .replace(/\\s+/g, \" \")\n .trim();\n return slugify(cleaned || \"new-app\") || \"new-app\";\n}\n\nfunction actionUrl(basePath: string | null, action: string): string {\n const path = `/_agent-native/actions/${action}`;\n if (basePath === null) return agentNativePath(path);\n const normalized = basePath.replace(/\\/+$/, \"\");\n return `${normalized}${path}`;\n}\n\nfunction defaultDispatchBasePath(sourceApp?: string): string | null {\n if (sourceApp === \"dispatch\") return null;\n const base = appBasePath();\n if (base === \"/dispatch\") return null;\n return \"/dispatch\";\n}\n\nasync function fetchJson(url: string, init?: RequestInit): Promise<any> {\n const res = await fetch(url, init);\n const data = await res.json().catch(() => null);\n if (!res.ok) {\n throw new Error(\n data?.error || data?.message || `Request failed ${res.status}`,\n );\n }\n return data;\n}\n\nexport function NewWorkspaceAppFlow({\n sourceApp = \"starter\",\n className = \"\",\n dispatchBasePath,\n}: NewWorkspaceAppFlowProps) {\n const [prompt, setPrompt] = useState(\"\");\n const [appName, setAppName] = useState(\"\");\n const [template, setTemplate] =\n useState<(typeof TEMPLATE_OPTIONS)[number][\"value\"]>(\"starter\");\n const [selectedSecretIds, setSelectedSecretIds] = useState<string[]>([]);\n const [secrets, setSecrets] = useState<VaultSecretOption[]>([]);\n const [secretsError, setSecretsError] = useState<string | null>(null);\n const [statusMessage, setStatusMessage] = useState<string | null>(null);\n const [branchUrl, setBranchUrl] = useState<string | null>(null);\n const [isSubmitting, setIsSubmitting] = useState(false);\n const { isDevMode } = useDevMode();\n\n const effectiveDispatchBasePath =\n dispatchBasePath === undefined\n ? defaultDispatchBasePath(sourceApp)\n : dispatchBasePath;\n\n useEffect(() => {\n let cancelled = false;\n const url = actionUrl(\n effectiveDispatchBasePath,\n \"list-vault-secret-options\",\n );\n fetchJson(url)\n .then((data) => {\n if (cancelled) return;\n setSecrets(Array.isArray(data) ? data : []);\n setSecretsError(null);\n })\n .catch((err) => {\n if (cancelled) return;\n setSecrets([]);\n setSecretsError(err?.message || \"Could not load Dispatch keys\");\n });\n return () => {\n cancelled = true;\n };\n }, [effectiveDispatchBasePath]);\n\n useEffect(() => {\n if (appName || !prompt.trim()) return;\n setAppName(titleFromPrompt(prompt));\n }, [prompt, appName]);\n\n const selectedSecrets = useMemo(\n () => secrets.filter((secret) => selectedSecretIds.includes(secret.id)),\n [secrets, selectedSecretIds],\n );\n const selectedSecretLabel =\n selectedSecretIds.length === 0\n ? \"No keys selected\"\n : `${selectedSecretIds.length} key${selectedSecretIds.length === 1 ? \"\" : \"s\"} selected`;\n\n const canSubmit = prompt.trim().length > 0 && slugify(appName).length > 0;\n const submitShortcut =\n typeof navigator !== \"undefined\" &&\n /Mac|iPhone|iPad/.test(navigator.userAgent)\n ? \"⌘\"\n : \"Ctrl\";\n\n function buildMessage(): string {\n const safeAppName = slugify(appName) || titleFromPrompt(prompt);\n const keyList = selectedSecrets.map((s) => s.credentialKey).join(\", \");\n return [\n `Create a new agent-native app in this workspace.`,\n ``,\n `App name: ${safeAppName}`,\n `Template to start from: ${template}`,\n `User prompt: ${prompt.trim()}`,\n keyList\n ? `Dispatch vault keys selected for this app: ${keyList}`\n : `Dispatch vault keys selected for this app: none`,\n ``,\n `Use the workspace app layout: create it under apps/${safeAppName}, mount it at /${safeAppName}, keep it on the shared workspace database/hosting model, and avoid table-name collisions by namespacing any new domain tables to the app.`,\n keyList\n ? `Grant the selected Dispatch vault keys to appId \"${safeAppName}\" and sync them once the app server is available.`\n : `Do not grant any Dispatch vault keys unless the user asks later.`,\n `When it is ready, start or update the dev server and navigate the user to /${safeAppName}.`,\n ].join(\"\\n\");\n }\n\n async function grantSelectedSecrets(safeAppName: string) {\n if (selectedSecretIds.length === 0) return;\n try {\n await fetchJson(\n actionUrl(effectiveDispatchBasePath, \"grant-vault-secrets-to-app\"),\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n appId: safeAppName,\n secretIds: selectedSecretIds,\n }),\n },\n );\n } catch (err: any) {\n setStatusMessage(\n `The app request was prepared, but Dispatch grants could not be saved yet: ${err?.message || \"unknown error\"}`,\n );\n }\n }\n\n async function submit() {\n if (!canSubmit || isSubmitting) return;\n const safeAppName = slugify(appName) || titleFromPrompt(prompt);\n const message = buildMessage();\n setIsSubmitting(true);\n setStatusMessage(null);\n setBranchUrl(null);\n\n try {\n await grantSelectedSecrets(safeAppName);\n\n if (isInBuilderFrame()) {\n sendToAgentChat({ message, submit: true, type: \"code\" });\n setStatusMessage(\"Sent to Builder chat.\");\n } else if (isDevMode) {\n sendToAgentChat({ message, submit: true, type: \"code\", newTab: true });\n setStatusMessage(\"Sent to the local agent.\");\n } else {\n const result = await fetchJson(\n actionUrl(effectiveDispatchBasePath, \"start-workspace-app-creation\"),\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n prompt: prompt.trim(),\n appId: safeAppName,\n template,\n secretIds: selectedSecretIds,\n preparedPrompt: message,\n }),\n },\n );\n if (result?.mode === \"builder\") {\n setBranchUrl(result?.url || null);\n setStatusMessage(\"Builder branch created.\");\n } else {\n setStatusMessage(\n result?.message ||\n \"Builder app creation is coming soon here. Open this workspace in Builder to create an app from this prompt.\",\n );\n }\n }\n } catch (err: any) {\n setStatusMessage(err?.message || \"Could not start the new app flow.\");\n } finally {\n setIsSubmitting(false);\n }\n }\n\n function toggleSecret(id: string) {\n setSelectedSecretIds((current) =>\n current.includes(id)\n ? current.filter((existing) => existing !== id)\n : [...current, id],\n );\n }\n\n return (\n <section\n className={`mx-auto flex w-full max-w-5xl flex-col gap-5 px-4 py-6 ${className}`}\n >\n <div className=\"grid gap-5 lg:grid-cols-[minmax(0,1fr)_320px]\">\n <div className=\"rounded-lg border border-border bg-card\">\n <div className=\"border-b border-border px-4 py-3\">\n <div className=\"flex items-center gap-2 text-sm font-medium\">\n <IconPlus className=\"h-4 w-4\" />\n New app\n </div>\n </div>\n <div className=\"space-y-4 p-4\">\n <label className=\"block space-y-2\">\n <span className=\"text-xs font-medium text-muted-foreground\">\n Prompt\n </span>\n <textarea\n value={prompt}\n onChange={(e) => setPrompt(e.target.value)}\n onKeyDown={(e) => {\n if ((e.metaKey || e.ctrlKey) && e.key === \"Enter\") {\n e.preventDefault();\n submit();\n }\n }}\n placeholder=\"Describe the app your teammate should be able to use...\"\n rows={6}\n className=\"min-h-36 w-full resize-none rounded-md border border-input bg-background px-3 py-2 text-sm outline-none focus:border-ring\"\n />\n </label>\n\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <label className=\"block space-y-2\">\n <span className=\"text-xs font-medium text-muted-foreground\">\n App path\n </span>\n <input\n value={appName}\n onChange={(e) => setAppName(slugify(e.target.value))}\n placeholder=\"customer-health\"\n className=\"h-10 w-full rounded-md border border-input bg-background px-3 text-sm outline-none focus:border-ring\"\n />\n </label>\n <label className=\"block space-y-2\">\n <span className=\"text-xs font-medium text-muted-foreground\">\n Starter template\n </span>\n <select\n value={template}\n onChange={(e) =>\n setTemplate(e.target.value as typeof template)\n }\n className=\"h-10 w-full rounded-md border border-input bg-background px-3 text-sm outline-none focus:border-ring\"\n >\n {TEMPLATE_OPTIONS.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n </label>\n </div>\n\n <div className=\"flex items-center justify-end gap-3\">\n <span className=\"text-[11px] text-muted-foreground/75\">\n {submitShortcut}+Enter to submit\n </span>\n <button\n type=\"button\"\n onClick={submit}\n disabled={!canSubmit || isSubmitting}\n className=\"inline-flex h-10 items-center gap-2 rounded-md bg-foreground px-4 text-sm font-medium text-background disabled:cursor-not-allowed disabled:opacity-40\"\n >\n {isSubmitting ? (\n <IconLoader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <IconCode className=\"h-4 w-4\" />\n )}\n Create app\n </button>\n </div>\n\n {statusMessage ? (\n <div className=\"rounded-md border border-border bg-muted/40 px-3 py-2 text-sm text-muted-foreground\">\n {statusMessage}\n {branchUrl ? (\n <a\n href={branchUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"ml-2 inline-flex items-center gap-1 font-medium text-foreground underline\"\n >\n Open branch <IconArrowUpRight className=\"h-3 w-3\" />\n </a>\n ) : null}\n </div>\n ) : null}\n </div>\n </div>\n\n <aside className=\"rounded-lg border border-border bg-card\">\n <div className=\"border-b border-border px-4 py-3\">\n <div className=\"flex items-center justify-between gap-3\">\n <div className=\"flex items-center gap-2 text-sm font-medium\">\n <IconKey className=\"h-4 w-4\" />\n Dispatch keys\n </div>\n <span className=\"shrink-0 rounded border border-border bg-background/40 px-2 py-0.5 text-[11px] text-muted-foreground\">\n {selectedSecretLabel}\n </span>\n </div>\n </div>\n <div className=\"max-h-[440px] space-y-2 overflow-y-auto p-3\">\n {secretsError ? (\n <p className=\"rounded-md border border-dashed border-border px-3 py-3 text-xs text-muted-foreground\">\n {secretsError}\n </p>\n ) : secrets.length === 0 ? (\n <p className=\"rounded-md border border-dashed border-border px-3 py-3 text-xs text-muted-foreground\">\n No Dispatch vault keys found yet.\n </p>\n ) : (\n secrets.map((secret) => {\n const selected = selectedSecretIds.includes(secret.id);\n return (\n <div\n key={secret.id}\n className={`group rounded-md border text-sm transition ${\n selected\n ? \"border-primary/45 bg-primary/5 text-foreground shadow-[inset_0_0_0_1px_hsl(var(--primary)/0.08)]\"\n : \"border-border bg-background/25 text-foreground hover:border-muted-foreground/40 hover:bg-accent/35\"\n }`}\n >\n <button\n type=\"button\"\n aria-pressed={selected}\n onClick={() => toggleSecret(secret.id)}\n className=\"flex w-full items-start gap-3 rounded-md px-3 py-2 text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/30\"\n >\n <span\n className={`mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded border transition ${\n selected\n ? \"border-primary/60 bg-primary/10 text-primary\"\n : \"border-muted-foreground/35 text-transparent group-hover:border-muted-foreground/60\"\n }`}\n >\n {selected ? <IconCheck className=\"h-3 w-3\" /> : null}\n </span>\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate font-medium\">\n {secret.credentialKey}\n </span>\n <span className=\"block truncate text-xs text-muted-foreground/70\">\n {selected\n ? \"Will be granted to this app\"\n : \"Click to grant\"}\n </span>\n </span>\n </button>\n <details className=\"group/details border-t border-border/60 px-3 py-1.5 text-xs text-muted-foreground/75 open:bg-background/10\">\n <summary className=\"flex cursor-pointer list-none items-center gap-1.5 text-[11px] hover:text-muted-foreground [&::-webkit-details-marker]:hidden\">\n <IconChevronDown className=\"h-3 w-3 transition-transform group-open/details:rotate-180\" />\n Details\n </summary>\n <div className=\"mt-1.5 space-y-1 pb-0.5 pl-4\">\n <div className=\"truncate\">\n Provider: {secret.provider || \"Not specified\"}\n </div>\n <div className=\"truncate\">Name: {secret.name}</div>\n </div>\n </details>\n </div>\n );\n })\n )}\n </div>\n </aside>\n </div>\n </section>\n );\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-deploy.d.ts","sourceRoot":"","sources":["../../src/deploy/workspace-deploy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAK7C,MAAM,MAAM,qBAAqB,GAAG,kBAAkB,GAAG,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"workspace-deploy.d.ts","sourceRoot":"","sources":["../../src/deploy/workspace-deploy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAK7C,MAAM,MAAM,qBAAqB,GAAG,kBAAkB,GAAG,SAAS,CAAC;AAqCnE,MAAM,WAAW,sBAAsB;IACrC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,qEAAqE;IACrE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yDAAyD;IACzD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,qDAAqD;IACrD,MAAM,CAAC,EAAE,qBAAqB,CAAC;IAC/B,qDAAqD;IACrD,QAAQ,CAAC,EAAE,OAAO,YAAY,CAAC;CAChC;AAED,wBAAsB,kBAAkB,CACtC,IAAI,GAAE,sBAA2B,GAChC,OAAO,CAAC,IAAI,CAAC,CAiFf"}
|