@agent-native/core 0.131.7 → 0.131.9
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/corpus/README.md +1 -1
- package/corpus/core/CHANGELOG.md +24 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/application-state/store.ts +18 -31
- package/corpus/core/src/cli/create.ts +115 -16
- package/corpus/core/src/client/AssistantChat.tsx +10 -2
- package/corpus/core/src/client/frame-protocol.ts +5 -1
- package/corpus/core/src/workspace-files/tool.ts +18 -11
- package/corpus/templates/clips/actions/generate-workflow.ts +6 -4
- package/corpus/templates/clips/actions/reconcile-workflow-generation.ts +257 -0
- package/corpus/templates/clips/app/hooks/use-auto-title.ts +166 -4
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +1 -1
- package/corpus/templates/clips/changelog/2026-07-27-stopped-agent-runs-no-longer-leave-generated-workflow-cards-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-30-workflow-generation-now-stops-retrying-after-repeated-failur.md +6 -0
- package/corpus/templates/clips/shared/workflow.ts +5 -0
- package/dist/application-state/store.d.ts.map +1 -1
- package/dist/application-state/store.js +20 -36
- package/dist/application-state/store.js.map +1 -1
- package/dist/cli/create.d.ts +8 -1
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +98 -16
- package/dist/cli/create.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +10 -2
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/frame-protocol.d.ts +1 -0
- package/dist/client/frame-protocol.d.ts.map +1 -1
- package/dist/client/frame-protocol.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +3 -3
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/workspace-files/tool.d.ts.map +1 -1
- package/dist/workspace-files/tool.js +18 -11
- package/dist/workspace-files/tool.js.map +1 -1
- package/package.json +3 -3
- package/src/application-state/store.ts +18 -31
- package/src/cli/create.ts +115 -16
- package/src/client/AssistantChat.tsx +10 -2
- package/src/client/frame-protocol.ts +5 -1
- package/src/workspace-files/tool.ts +18 -11
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frame-protocol.d.ts","sourceRoot":"","sources":["../../src/client/frame-protocol.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,+BAA+B,EAC/B,6BAA6B,EAC7B,0BAA0B,EAC1B,gBAAgB,EACjB,MAAM,iBAAiB,CAAC;AAMzB,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,sBAAsB,CAAC;CAC9B;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,wBAAwB,CAAC;IAC/B,IAAI,EAAE,gBAAgB,CAAC;CACxB;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,4BAA4B,CAAC;IACnC,IAAI,EAAE,0BAA0B,CAAC;CAClC;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,+BAA+B,CAAC;IACtC,IAAI,EAAE,6BAA6B,CAAC;CACrC;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,8BAA8B,CAAC;IACrC,IAAI,EAAE,+BAA+B,CAAC;CACvC;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,yBAAyB,CAAC;CACjC;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,wBAAwB,CAAC;IAC/B,IAAI,EAAE;QAAE,IAAI,EAAE,KAAK,CAAC;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,CAAC;CACvD;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,2BAA2B,CAAC;IAClC,IAAI,EAAE;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC;CAC9B;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,2BAA2B,CAAC;IAClC,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CAC3B;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,+BAA+B,CAAC;IACtC,IAAI,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;CAC5B;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,8BAA8B,CAAC;IACrC,IAAI,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;CAC5B;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,+BAA+B,CAAC;CACvC;AAED;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,8BAA8B,CAAC;IACrC,IAAI,EAAE;QAAE,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC;CAC3B;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,cAAc,CAAC;CACtB;AAED,MAAM,MAAM,iBAAiB,GACzB,eAAe,GACf,iBAAiB,GACjB,qBAAqB,GACrB,wBAAwB,GACxB,uBAAuB,GACvB,kBAAkB,GAClB,iBAAiB,GACjB,oBAAoB,GACpB,oBAAoB,GACpB,wBAAwB,GACxB,uBAAuB,GACvB,wBAAwB,GACxB,uBAAuB,GACvB,kBAAkB,CAAC;AAMvB,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,yBAAyB,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,yBAAyB,CAAC;IAChC,MAAM,EAAE;
|
|
1
|
+
{"version":3,"file":"frame-protocol.d.ts","sourceRoot":"","sources":["../../src/client/frame-protocol.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frame-protocol.js","sourceRoot":"","sources":["../../src/client/frame-protocol.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG","sourcesContent":["/**\n * Frame Protocol — typed message definitions for frame communication.\n *\n * Any frame implementation (local dev frame, Builder.io cloud, Electron)\n * must support these message types. Communication happens via postMessage\n * between the app iframe and the parent frame.\n */\n\nimport type {\n AgentChatContextMutationOptions,\n AgentChatContextRemoveOptions,\n AgentChatContextSetOptions,\n AgentChatMessage,\n} from \"./agent-chat.js\";\n\n// ---------------------------------------------------------------------------\n// Messages FROM app TO frame\n// ---------------------------------------------------------------------------\n\nexport interface AppReadyMessage {\n type: \"agentNative.appReady\";\n}\n\nexport interface SubmitChatMessage {\n type: \"agentNative.submitChat\";\n data: AgentChatMessage;\n}\n\nexport interface SetChatContextMessage {\n type: \"agentNative.setChatContext\";\n data: AgentChatContextSetOptions;\n}\n\nexport interface RemoveChatContextMessage {\n type: \"agentNative.removeChatContext\";\n data: AgentChatContextRemoveOptions;\n}\n\nexport interface ClearChatContextMessage {\n type: \"agentNative.clearChatContext\";\n data: AgentChatContextMutationOptions;\n}\n\nexport interface GetUserInfoMessage {\n type: \"agentNative.getUserInfo\";\n}\n\nexport interface SetEnvVarsMessage {\n type: \"agentNative.setEnvVars\";\n data: { vars: Array<{ key: string; value: string }> };\n}\n\nexport interface DevModeChangeMessage {\n type: \"agentNative.devModeChange\";\n data: { isDevMode: boolean };\n}\n\nexport interface ToggleSidebarMessage {\n type: \"agentNative.toggleSidebar\";\n data?: { open?: boolean };\n}\n\nexport interface EnterStyleEditingMessage {\n type: \"agentNative.enterStyleEditing\";\n data: { selector: string };\n}\n\nexport interface EnterTextEditingMessage {\n type: \"agentNative.enterTextEditing\";\n data: { selector: string };\n}\n\nexport interface ExitSelectionModeMessage {\n type: \"agentNative.exitSelectionMode\";\n}\n\n/**\n * Sent both ways: the app announces it has entered/exited presentation mode\n * (so the frame can hide its chrome), and an outer frame can push the app\n * into presentation mode (so the app's sidebar hides).\n */\nexport interface PresentationModeMessage {\n type: \"agentNative.presentationMode\";\n data: { active: boolean };\n}\n\nexport interface DesignCloseMessage {\n type: \"design:close\";\n}\n\nexport type AppToFrameMessage =\n | AppReadyMessage\n | SubmitChatMessage\n | SetChatContextMessage\n | RemoveChatContextMessage\n | ClearChatContextMessage\n | GetUserInfoMessage\n | SetEnvVarsMessage\n | DevModeChangeMessage\n | ToggleSidebarMessage\n | EnterStyleEditingMessage\n | EnterTextEditingMessage\n | ExitSelectionModeMessage\n | PresentationModeMessage\n | DesignCloseMessage;\n\n// ---------------------------------------------------------------------------\n// Messages FROM frame TO app\n// ---------------------------------------------------------------------------\n\nexport interface FrameOriginMessage {\n type: \"agentNative.frameOrigin\";\n origin: string;\n}\n\nexport interface ChatRunningMessage {\n type: \"agentNative.chatRunning\";\n detail: {
|
|
1
|
+
{"version":3,"file":"frame-protocol.js","sourceRoot":"","sources":["../../src/client/frame-protocol.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG","sourcesContent":["/**\n * Frame Protocol — typed message definitions for frame communication.\n *\n * Any frame implementation (local dev frame, Builder.io cloud, Electron)\n * must support these message types. Communication happens via postMessage\n * between the app iframe and the parent frame.\n */\n\nimport type {\n AgentChatContextMutationOptions,\n AgentChatContextRemoveOptions,\n AgentChatContextSetOptions,\n AgentChatMessage,\n} from \"./agent-chat.js\";\n\n// ---------------------------------------------------------------------------\n// Messages FROM app TO frame\n// ---------------------------------------------------------------------------\n\nexport interface AppReadyMessage {\n type: \"agentNative.appReady\";\n}\n\nexport interface SubmitChatMessage {\n type: \"agentNative.submitChat\";\n data: AgentChatMessage;\n}\n\nexport interface SetChatContextMessage {\n type: \"agentNative.setChatContext\";\n data: AgentChatContextSetOptions;\n}\n\nexport interface RemoveChatContextMessage {\n type: \"agentNative.removeChatContext\";\n data: AgentChatContextRemoveOptions;\n}\n\nexport interface ClearChatContextMessage {\n type: \"agentNative.clearChatContext\";\n data: AgentChatContextMutationOptions;\n}\n\nexport interface GetUserInfoMessage {\n type: \"agentNative.getUserInfo\";\n}\n\nexport interface SetEnvVarsMessage {\n type: \"agentNative.setEnvVars\";\n data: { vars: Array<{ key: string; value: string }> };\n}\n\nexport interface DevModeChangeMessage {\n type: \"agentNative.devModeChange\";\n data: { isDevMode: boolean };\n}\n\nexport interface ToggleSidebarMessage {\n type: \"agentNative.toggleSidebar\";\n data?: { open?: boolean };\n}\n\nexport interface EnterStyleEditingMessage {\n type: \"agentNative.enterStyleEditing\";\n data: { selector: string };\n}\n\nexport interface EnterTextEditingMessage {\n type: \"agentNative.enterTextEditing\";\n data: { selector: string };\n}\n\nexport interface ExitSelectionModeMessage {\n type: \"agentNative.exitSelectionMode\";\n}\n\n/**\n * Sent both ways: the app announces it has entered/exited presentation mode\n * (so the frame can hide its chrome), and an outer frame can push the app\n * into presentation mode (so the app's sidebar hides).\n */\nexport interface PresentationModeMessage {\n type: \"agentNative.presentationMode\";\n data: { active: boolean };\n}\n\nexport interface DesignCloseMessage {\n type: \"design:close\";\n}\n\nexport type AppToFrameMessage =\n | AppReadyMessage\n | SubmitChatMessage\n | SetChatContextMessage\n | RemoveChatContextMessage\n | ClearChatContextMessage\n | GetUserInfoMessage\n | SetEnvVarsMessage\n | DevModeChangeMessage\n | ToggleSidebarMessage\n | EnterStyleEditingMessage\n | EnterTextEditingMessage\n | ExitSelectionModeMessage\n | PresentationModeMessage\n | DesignCloseMessage;\n\n// ---------------------------------------------------------------------------\n// Messages FROM frame TO app\n// ---------------------------------------------------------------------------\n\nexport interface FrameOriginMessage {\n type: \"agentNative.frameOrigin\";\n origin: string;\n}\n\nexport interface ChatRunningMessage {\n type: \"agentNative.chatRunning\";\n detail: {\n isRunning: boolean;\n tabId?: string;\n reason?: \"stopped\" | \"failed\";\n };\n}\n\nexport interface UserInfoMessage {\n type: \"agentNative.userInfo\";\n data: { name?: string; email?: string };\n}\n\nexport interface CodeCompleteMessage {\n type: \"agentNative.codeComplete\";\n tabId: string;\n success: boolean;\n}\n\nexport interface SidebarModeMessage {\n type: \"agentNative.sidebarMode\";\n data: {\n /** \"code\" hides the app's sidebar (frame controls it); \"app\" defers to the app. */\n mode: \"code\" | \"app\";\n /** When mode === \"app\", which panel the app should show. */\n appMode?: \"cli\" | \"resources\" | \"chat\";\n /** Frame-controlled sidebar width to sync into the app. */\n width?: number;\n /** Whether the app's sidebar should be open. */\n open?: boolean;\n };\n}\n\nexport interface DesignInitMessage {\n type: \"design:init\";\n data: {\n previewUrl: string;\n themeVars?: Record<string, string>;\n context?: { projectId?: string; branchId?: string; orgId?: string };\n };\n}\n\nexport type FrameToAppMessage =\n | FrameOriginMessage\n | ChatRunningMessage\n | UserInfoMessage\n | CodeCompleteMessage\n | SidebarModeMessage\n | PresentationModeMessage\n | DesignInitMessage;\n\n// ---------------------------------------------------------------------------\n// All message types\n// ---------------------------------------------------------------------------\n\nexport type FrameMessage = AppToFrameMessage | FrameToAppMessage;\n"]}
|
package/dist/collab/routes.d.ts
CHANGED
|
@@ -26,8 +26,8 @@ export declare const getCollabState: import("h3").EventHandlerWithFetch<import("
|
|
|
26
26
|
* Body: { update: string (base64), requestSource?: string }
|
|
27
27
|
*/
|
|
28
28
|
export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
29
|
-
error: string;
|
|
30
29
|
ok?: undefined;
|
|
30
|
+
error: string;
|
|
31
31
|
} | {
|
|
32
32
|
error?: undefined;
|
|
33
33
|
ok: boolean;
|
|
@@ -41,16 +41,16 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
|
|
|
41
41
|
thumbsUpRate: number;
|
|
42
42
|
avgEvalScore: number;
|
|
43
43
|
} | {
|
|
44
|
-
error?: undefined;
|
|
45
44
|
summary: import("./types.js").TraceSummary;
|
|
46
45
|
spans: import("./types.js").TraceSpan[];
|
|
47
46
|
id?: undefined;
|
|
47
|
+
error?: undefined;
|
|
48
48
|
ok?: undefined;
|
|
49
49
|
} | {
|
|
50
|
-
error?: undefined;
|
|
51
50
|
summary?: undefined;
|
|
52
51
|
spans?: undefined;
|
|
53
52
|
id: string;
|
|
53
|
+
error?: undefined;
|
|
54
54
|
ok?: undefined;
|
|
55
55
|
} | {
|
|
56
56
|
summary?: undefined;
|
|
@@ -59,10 +59,10 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
|
|
|
59
59
|
error: any;
|
|
60
60
|
ok?: undefined;
|
|
61
61
|
} | {
|
|
62
|
-
error?: undefined;
|
|
63
62
|
summary?: undefined;
|
|
64
63
|
spans?: undefined;
|
|
65
64
|
id?: undefined;
|
|
65
|
+
error?: undefined;
|
|
66
66
|
ok: boolean;
|
|
67
67
|
}>>;
|
|
68
68
|
//# sourceMappingURL=routes.d.ts.map
|
|
@@ -26,9 +26,9 @@ export declare function createRealtimeTokenHandler(): import("h3").EventHandlerW
|
|
|
26
26
|
expiresAt?: undefined;
|
|
27
27
|
ttlSeconds?: undefined;
|
|
28
28
|
} | {
|
|
29
|
-
error?: undefined;
|
|
30
29
|
token: string;
|
|
31
30
|
expiresAt: string;
|
|
32
31
|
ttlSeconds: number;
|
|
32
|
+
error?: undefined;
|
|
33
33
|
}>>;
|
|
34
34
|
//# sourceMappingURL=realtime-token.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/workspace-files/tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AA2BhE,wBAAgB,wBAAwB,IAAI,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,
|
|
1
|
+
{"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/workspace-files/tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AA2BhE,wBAAgB,wBAAwB,IAAI,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CA6OtE"}
|
|
@@ -69,12 +69,15 @@ export function createWorkspaceFilesTool() {
|
|
|
69
69
|
description: 'MIME type for new files. Default: "text/plain". Use "application/json" for JSON, "text/markdown" for Markdown.',
|
|
70
70
|
},
|
|
71
71
|
offset: {
|
|
72
|
-
type: "
|
|
73
|
-
|
|
72
|
+
type: "integer",
|
|
73
|
+
minimum: 0,
|
|
74
|
+
description: "Non-negative character offset to start reading from (for paging large files). Default: 0.",
|
|
74
75
|
},
|
|
75
76
|
maxChars: {
|
|
76
|
-
type: "
|
|
77
|
-
|
|
77
|
+
type: "integer",
|
|
78
|
+
minimum: 1,
|
|
79
|
+
maximum: MAX_READ_CHARS,
|
|
80
|
+
description: `Positive maximum characters to return when reading. Default: ${DEFAULT_READ_CHARS}. Max: ${MAX_READ_CHARS}.`,
|
|
78
81
|
},
|
|
79
82
|
pattern: {
|
|
80
83
|
type: "string",
|
|
@@ -135,14 +138,17 @@ export function createWorkspaceFilesTool() {
|
|
|
135
138
|
if (!path)
|
|
136
139
|
return "Error: path is required for read.";
|
|
137
140
|
const rawOffset = Number(args.offset);
|
|
138
|
-
const offset = Number.isFinite(rawOffset) && rawOffset > 0
|
|
141
|
+
const offset = Number.isFinite(rawOffset) && rawOffset > 0
|
|
142
|
+
? Math.floor(rawOffset)
|
|
143
|
+
: 0;
|
|
139
144
|
const rawMax = Number(args.maxChars);
|
|
140
145
|
const maxChars = Number.isFinite(rawMax) && rawMax > 0
|
|
141
|
-
? Math.min(rawMax, MAX_READ_CHARS)
|
|
146
|
+
? Math.min(Math.max(1, Math.floor(rawMax)), MAX_READ_CHARS)
|
|
142
147
|
: DEFAULT_READ_CHARS;
|
|
148
|
+
// The sentinel character distinguishes an exact page from a truncated one.
|
|
143
149
|
const file = await readWorkspaceFile(scope, path, {
|
|
144
150
|
offset,
|
|
145
|
-
maxChars,
|
|
151
|
+
maxChars: maxChars + 1,
|
|
146
152
|
});
|
|
147
153
|
if (!file) {
|
|
148
154
|
return JSON.stringify({
|
|
@@ -150,19 +156,20 @@ export function createWorkspaceFilesTool() {
|
|
|
150
156
|
error: `File not found: "${path}"`,
|
|
151
157
|
});
|
|
152
158
|
}
|
|
153
|
-
const truncated = file.content.length
|
|
159
|
+
const truncated = file.content.length > maxChars;
|
|
160
|
+
const content = file.content.slice(0, maxChars);
|
|
154
161
|
return JSON.stringify({
|
|
155
162
|
ok: true,
|
|
156
163
|
path: file.path,
|
|
157
164
|
contentType: file.contentType,
|
|
158
165
|
sizeBytes: file.sizeBytes,
|
|
159
166
|
updatedAt: file.updatedAt,
|
|
160
|
-
content
|
|
167
|
+
content,
|
|
161
168
|
...(truncated
|
|
162
169
|
? {
|
|
163
170
|
truncated: true,
|
|
164
|
-
nextOffset: offset +
|
|
165
|
-
hint: `File has more content. Call again with offset: ${offset +
|
|
171
|
+
nextOffset: offset + content.length,
|
|
172
|
+
hint: `File has more content. Call again with offset: ${offset + content.length}`,
|
|
166
173
|
}
|
|
167
174
|
: {}),
|
|
168
175
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool.js","sourceRoot":"","sources":["../../src/workspace-files/tool.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `workspace-files` bridge tool.\n *\n * A single tool with an `action` discriminator covering write, append, read,\n * list, delete, and grep. It is kept for `run-code` workspaceRead/workspaceWrite\n * compatibility and delegates storage to the Resources table.\n *\n * Scope is automatically resolved from the active request context:\n * - org scope when a request orgId is present (shared across users in the org)\n * - user scope otherwise (personal to the requesting user's email)\n */\n\nimport type { ActionEntry } from \"../agent/production-agent.js\";\nimport {\n getRequestOrgId,\n getRequestUserEmail,\n} from \"../server/request-context.js\";\nimport {\n writeWorkspaceFile,\n appendWorkspaceFile,\n readWorkspaceFile,\n listWorkspaceFiles,\n deleteWorkspaceFile,\n grepWorkspaceFiles,\n type WorkspaceFilesScope,\n} from \"./store.js\";\n\nconst MAX_READ_CHARS = 100_000;\nconst DEFAULT_READ_CHARS = 40_000;\n\n/** Resolve scope from the current request context (org-preferred). */\nfunction resolveScope(): WorkspaceFilesScope | null {\n const orgId = getRequestOrgId();\n if (orgId) return { scope: \"org\", scopeId: orgId };\n const email = getRequestUserEmail();\n if (email) return { scope: \"user\", scopeId: email };\n return null;\n}\n\nexport function createWorkspaceFilesTool(): Record<string, ActionEntry> {\n return {\n \"workspace-files\": {\n agentTool: false,\n readOnly: false,\n tool: {\n description: [\n \"Bridge-only workspace file storage backed by Resources. Files are scoped to the current org/user and appear in the Resources workspace.\",\n \"Use scratch/... for temporary intermediate results; scratch files are hidden from the Resources view by default and expire. Use durable folder names for files the user explicitly wants to keep/manage.\",\n \"Use this to stage large intermediate results (fetched pages, per-item analysis memos, API payloads) so they don't consume context window, then read them back selectively for synthesis.\",\n \"\",\n \"Typical fusion-style workflow:\",\n \" 1. Fan out: for each item, fetch data and `write` a per-item memo file.\",\n \" 2. Synthesize: `list` files, then `read` each memo (with offset/maxChars to page large ones).\",\n \" 3. Optionally `grep` across all memos to find patterns.\",\n \" 4. `delete` temp files when no longer needed.\",\n \"\",\n \"Actions:\",\n \" write — create or overwrite a file. Max 2 MB per file.\",\n \" append — append text to a file (or create if absent).\",\n \" read — read content, optionally with offset/maxChars for paging large files.\",\n \" list — list files (with optional path prefix filter) showing name, size, updated.\",\n \" delete — delete a file by path.\",\n \" grep — search content across files for a substring or regex.\",\n ].join(\"\\n\"),\n parameters: {\n type: \"object\",\n properties: {\n action: {\n type: \"string\",\n enum: [\"write\", \"append\", \"read\", \"list\", \"delete\", \"grep\"],\n description: \"Operation to perform.\",\n },\n path: {\n type: \"string\",\n description:\n 'File path relative to the scope root, e.g. \"scratch/analysis/q2-memos/acme.md\". Required for write/append/read/delete. Optional for list/grep (acts as prefix filter).',\n },\n content: {\n type: \"string\",\n description:\n \"Text content to write or append. Required for write/append.\",\n },\n contentType: {\n type: \"string\",\n description:\n 'MIME type for new files. Default: \"text/plain\". Use \"application/json\" for JSON, \"text/markdown\" for Markdown.',\n },\n offset: {\n type: \"number\",\n description:\n \"Character offset to start reading from (for paging large files). Default: 0.\",\n },\n maxChars: {\n type: \"number\",\n description: `Maximum characters to return when reading. Default: ${DEFAULT_READ_CHARS}. Max: ${MAX_READ_CHARS}.`,\n },\n pattern: {\n type: \"string\",\n description:\n \"Search pattern for grep. Required for grep action. A plain substring by default; set useRegex to true for a regex.\",\n },\n useRegex: {\n type: \"boolean\",\n description:\n \"When true, treat `pattern` as a JavaScript regex (case-insensitive). Default: false.\",\n },\n },\n required: [\"action\"],\n },\n },\n\n run: async (args: Record<string, unknown>): Promise<string> => {\n const scope = resolveScope();\n if (!scope) {\n return \"Error: workspace-files requires an authenticated request context.\";\n }\n\n const action = String(args.action ?? \"\").trim();\n\n try {\n switch (action) {\n case \"write\": {\n const path = String(args.path ?? \"\").trim();\n if (!path) return \"Error: path is required for write.\";\n const content = String(args.content ?? \"\");\n const contentType = String(args.contentType ?? \"text/plain\");\n const meta = await writeWorkspaceFile(\n scope,\n path,\n content,\n contentType,\n );\n return JSON.stringify({\n ok: true,\n action: \"write\",\n resourceId: meta.id,\n path: meta.path,\n contentType: meta.contentType,\n sizeBytes: meta.sizeBytes,\n updatedAt: meta.updatedAt,\n });\n }\n\n case \"append\": {\n const path = String(args.path ?? \"\").trim();\n if (!path) return \"Error: path is required for append.\";\n const content = String(args.content ?? \"\");\n const contentType = String(args.contentType ?? \"text/plain\");\n const meta = await appendWorkspaceFile(\n scope,\n path,\n content,\n contentType,\n );\n return JSON.stringify({\n ok: true,\n action: \"append\",\n resourceId: meta.id,\n path: meta.path,\n contentType: meta.contentType,\n sizeBytes: meta.sizeBytes,\n updatedAt: meta.updatedAt,\n });\n }\n\n case \"read\": {\n const path = String(args.path ?? \"\").trim();\n if (!path) return \"Error: path is required for read.\";\n const rawOffset = Number(args.offset);\n const offset =\n Number.isFinite(rawOffset) && rawOffset > 0 ? rawOffset : 0;\n const rawMax = Number(args.maxChars);\n const maxChars =\n Number.isFinite(rawMax) && rawMax > 0\n ? Math.min(rawMax, MAX_READ_CHARS)\n : DEFAULT_READ_CHARS;\n\n const file = await readWorkspaceFile(scope, path, {\n offset,\n maxChars,\n });\n if (!file) {\n return JSON.stringify({\n ok: false,\n error: `File not found: \"${path}\"`,\n });\n }\n\n const truncated = file.content.length >= maxChars;\n return JSON.stringify({\n ok: true,\n path: file.path,\n contentType: file.contentType,\n sizeBytes: file.sizeBytes,\n updatedAt: file.updatedAt,\n content: file.content,\n ...(truncated\n ? {\n truncated: true,\n nextOffset: offset + file.content.length,\n hint: `File has more content. Call again with offset: ${offset + file.content.length}`,\n }\n : {}),\n });\n }\n\n case \"list\": {\n const prefix = args.path ? String(args.path).trim() : undefined;\n const files = await listWorkspaceFiles(\n scope,\n prefix || undefined,\n );\n return JSON.stringify({\n ok: true,\n count: files.length,\n files: files.map((f) => ({\n path: f.path,\n sizeBytes: f.sizeBytes,\n contentType: f.contentType,\n updatedAt: f.updatedAt,\n })),\n });\n }\n\n case \"delete\": {\n const path = String(args.path ?? \"\").trim();\n if (!path) return \"Error: path is required for delete.\";\n const deleted = await deleteWorkspaceFile(scope, path);\n return JSON.stringify({\n ok: true,\n deleted,\n path,\n });\n }\n\n case \"grep\": {\n const pattern = String(args.pattern ?? \"\").trim();\n if (!pattern) return \"Error: pattern is required for grep.\";\n const prefix = args.path ? String(args.path).trim() : undefined;\n const useRegex =\n args.useRegex === true || String(args.useRegex) === \"true\";\n const matches = await grepWorkspaceFiles(scope, pattern, {\n pathPrefix: prefix || undefined,\n useRegex,\n maxMatchesPerFile: 20,\n maxFiles: 50,\n });\n return JSON.stringify({\n ok: true,\n pattern,\n matchCount: matches.length,\n matches: matches.map((m) => ({\n path: m.path,\n line: m.lineNumber,\n text: m.line,\n })),\n });\n }\n\n default:\n return `Error: unknown action \"${action}\". Valid actions: write, append, read, list, delete, grep.`;\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return JSON.stringify({ ok: false, error: msg });\n }\n },\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"tool.js","sourceRoot":"","sources":["../../src/workspace-files/tool.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `workspace-files` bridge tool.\n *\n * A single tool with an `action` discriminator covering write, append, read,\n * list, delete, and grep. It is kept for `run-code` workspaceRead/workspaceWrite\n * compatibility and delegates storage to the Resources table.\n *\n * Scope is automatically resolved from the active request context:\n * - org scope when a request orgId is present (shared across users in the org)\n * - user scope otherwise (personal to the requesting user's email)\n */\n\nimport type { ActionEntry } from \"../agent/production-agent.js\";\nimport {\n getRequestOrgId,\n getRequestUserEmail,\n} from \"../server/request-context.js\";\nimport {\n writeWorkspaceFile,\n appendWorkspaceFile,\n readWorkspaceFile,\n listWorkspaceFiles,\n deleteWorkspaceFile,\n grepWorkspaceFiles,\n type WorkspaceFilesScope,\n} from \"./store.js\";\n\nconst MAX_READ_CHARS = 100_000;\nconst DEFAULT_READ_CHARS = 40_000;\n\n/** Resolve scope from the current request context (org-preferred). */\nfunction resolveScope(): WorkspaceFilesScope | null {\n const orgId = getRequestOrgId();\n if (orgId) return { scope: \"org\", scopeId: orgId };\n const email = getRequestUserEmail();\n if (email) return { scope: \"user\", scopeId: email };\n return null;\n}\n\nexport function createWorkspaceFilesTool(): Record<string, ActionEntry> {\n return {\n \"workspace-files\": {\n agentTool: false,\n readOnly: false,\n tool: {\n description: [\n \"Bridge-only workspace file storage backed by Resources. Files are scoped to the current org/user and appear in the Resources workspace.\",\n \"Use scratch/... for temporary intermediate results; scratch files are hidden from the Resources view by default and expire. Use durable folder names for files the user explicitly wants to keep/manage.\",\n \"Use this to stage large intermediate results (fetched pages, per-item analysis memos, API payloads) so they don't consume context window, then read them back selectively for synthesis.\",\n \"\",\n \"Typical fusion-style workflow:\",\n \" 1. Fan out: for each item, fetch data and `write` a per-item memo file.\",\n \" 2. Synthesize: `list` files, then `read` each memo (with offset/maxChars to page large ones).\",\n \" 3. Optionally `grep` across all memos to find patterns.\",\n \" 4. `delete` temp files when no longer needed.\",\n \"\",\n \"Actions:\",\n \" write — create or overwrite a file. Max 2 MB per file.\",\n \" append — append text to a file (or create if absent).\",\n \" read — read content, optionally with offset/maxChars for paging large files.\",\n \" list — list files (with optional path prefix filter) showing name, size, updated.\",\n \" delete — delete a file by path.\",\n \" grep — search content across files for a substring or regex.\",\n ].join(\"\\n\"),\n parameters: {\n type: \"object\",\n properties: {\n action: {\n type: \"string\",\n enum: [\"write\", \"append\", \"read\", \"list\", \"delete\", \"grep\"],\n description: \"Operation to perform.\",\n },\n path: {\n type: \"string\",\n description:\n 'File path relative to the scope root, e.g. \"scratch/analysis/q2-memos/acme.md\". Required for write/append/read/delete. Optional for list/grep (acts as prefix filter).',\n },\n content: {\n type: \"string\",\n description:\n \"Text content to write or append. Required for write/append.\",\n },\n contentType: {\n type: \"string\",\n description:\n 'MIME type for new files. Default: \"text/plain\". Use \"application/json\" for JSON, \"text/markdown\" for Markdown.',\n },\n offset: {\n type: \"integer\",\n minimum: 0,\n description:\n \"Non-negative character offset to start reading from (for paging large files). Default: 0.\",\n },\n maxChars: {\n type: \"integer\",\n minimum: 1,\n maximum: MAX_READ_CHARS,\n description: `Positive maximum characters to return when reading. Default: ${DEFAULT_READ_CHARS}. Max: ${MAX_READ_CHARS}.`,\n },\n pattern: {\n type: \"string\",\n description:\n \"Search pattern for grep. Required for grep action. A plain substring by default; set useRegex to true for a regex.\",\n },\n useRegex: {\n type: \"boolean\",\n description:\n \"When true, treat `pattern` as a JavaScript regex (case-insensitive). Default: false.\",\n },\n },\n required: [\"action\"],\n },\n },\n\n run: async (args: Record<string, unknown>): Promise<string> => {\n const scope = resolveScope();\n if (!scope) {\n return \"Error: workspace-files requires an authenticated request context.\";\n }\n\n const action = String(args.action ?? \"\").trim();\n\n try {\n switch (action) {\n case \"write\": {\n const path = String(args.path ?? \"\").trim();\n if (!path) return \"Error: path is required for write.\";\n const content = String(args.content ?? \"\");\n const contentType = String(args.contentType ?? \"text/plain\");\n const meta = await writeWorkspaceFile(\n scope,\n path,\n content,\n contentType,\n );\n return JSON.stringify({\n ok: true,\n action: \"write\",\n resourceId: meta.id,\n path: meta.path,\n contentType: meta.contentType,\n sizeBytes: meta.sizeBytes,\n updatedAt: meta.updatedAt,\n });\n }\n\n case \"append\": {\n const path = String(args.path ?? \"\").trim();\n if (!path) return \"Error: path is required for append.\";\n const content = String(args.content ?? \"\");\n const contentType = String(args.contentType ?? \"text/plain\");\n const meta = await appendWorkspaceFile(\n scope,\n path,\n content,\n contentType,\n );\n return JSON.stringify({\n ok: true,\n action: \"append\",\n resourceId: meta.id,\n path: meta.path,\n contentType: meta.contentType,\n sizeBytes: meta.sizeBytes,\n updatedAt: meta.updatedAt,\n });\n }\n\n case \"read\": {\n const path = String(args.path ?? \"\").trim();\n if (!path) return \"Error: path is required for read.\";\n const rawOffset = Number(args.offset);\n const offset =\n Number.isFinite(rawOffset) && rawOffset > 0\n ? Math.floor(rawOffset)\n : 0;\n const rawMax = Number(args.maxChars);\n const maxChars =\n Number.isFinite(rawMax) && rawMax > 0\n ? Math.min(Math.max(1, Math.floor(rawMax)), MAX_READ_CHARS)\n : DEFAULT_READ_CHARS;\n\n // The sentinel character distinguishes an exact page from a truncated one.\n const file = await readWorkspaceFile(scope, path, {\n offset,\n maxChars: maxChars + 1,\n });\n if (!file) {\n return JSON.stringify({\n ok: false,\n error: `File not found: \"${path}\"`,\n });\n }\n\n const truncated = file.content.length > maxChars;\n const content = file.content.slice(0, maxChars);\n return JSON.stringify({\n ok: true,\n path: file.path,\n contentType: file.contentType,\n sizeBytes: file.sizeBytes,\n updatedAt: file.updatedAt,\n content,\n ...(truncated\n ? {\n truncated: true,\n nextOffset: offset + content.length,\n hint: `File has more content. Call again with offset: ${offset + content.length}`,\n }\n : {}),\n });\n }\n\n case \"list\": {\n const prefix = args.path ? String(args.path).trim() : undefined;\n const files = await listWorkspaceFiles(\n scope,\n prefix || undefined,\n );\n return JSON.stringify({\n ok: true,\n count: files.length,\n files: files.map((f) => ({\n path: f.path,\n sizeBytes: f.sizeBytes,\n contentType: f.contentType,\n updatedAt: f.updatedAt,\n })),\n });\n }\n\n case \"delete\": {\n const path = String(args.path ?? \"\").trim();\n if (!path) return \"Error: path is required for delete.\";\n const deleted = await deleteWorkspaceFile(scope, path);\n return JSON.stringify({\n ok: true,\n deleted,\n path,\n });\n }\n\n case \"grep\": {\n const pattern = String(args.pattern ?? \"\").trim();\n if (!pattern) return \"Error: pattern is required for grep.\";\n const prefix = args.path ? String(args.path).trim() : undefined;\n const useRegex =\n args.useRegex === true || String(args.useRegex) === \"true\";\n const matches = await grepWorkspaceFiles(scope, pattern, {\n pathPrefix: prefix || undefined,\n useRegex,\n maxMatchesPerFile: 20,\n maxFiles: 50,\n });\n return JSON.stringify({\n ok: true,\n pattern,\n matchCount: matches.length,\n matches: matches.map((m) => ({\n path: m.path,\n line: m.lineNumber,\n text: m.line,\n })),\n });\n }\n\n default:\n return `Error: unknown action \"${action}\". Valid actions: write, append, read, list, delete, grep.`;\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return JSON.stringify({ ok: false, error: msg });\n }\n },\n },\n };\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.131.
|
|
3
|
+
"version": "0.131.9",
|
|
4
4
|
"description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
|
|
5
5
|
"homepage": "https://github.com/BuilderIO/agent-native#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -395,8 +395,8 @@
|
|
|
395
395
|
"y-protocols": "^1.0.7",
|
|
396
396
|
"yjs": "^13.6.31",
|
|
397
397
|
"zod": "^4.3.6",
|
|
398
|
-
"@agent-native/
|
|
399
|
-
"@agent-native/
|
|
398
|
+
"@agent-native/recap-cli": "0.5.1",
|
|
399
|
+
"@agent-native/toolkit": "^0.12.0"
|
|
400
400
|
},
|
|
401
401
|
"devDependencies": {
|
|
402
402
|
"@ai-sdk/anthropic": "^3.0.71",
|
|
@@ -2,7 +2,6 @@ import {
|
|
|
2
2
|
getDbExec,
|
|
3
3
|
getDialect,
|
|
4
4
|
isLocalDatabase,
|
|
5
|
-
isConnectionError,
|
|
6
5
|
isPostgres,
|
|
7
6
|
intType,
|
|
8
7
|
type DbExec,
|
|
@@ -102,21 +101,14 @@ export async function appStateGet(
|
|
|
102
101
|
sessionId: string,
|
|
103
102
|
key: string,
|
|
104
103
|
): Promise<Record<string, unknown> | null> {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
return JSON.parse(rows[0].value as string);
|
|
114
|
-
} catch (err) {
|
|
115
|
-
// Transient WS / connection drops (Neon serverless) — caller polls every
|
|
116
|
-
// 2s and will see the value on the next tick. Swallow rather than 500.
|
|
117
|
-
if (isConnectionError(err)) return null;
|
|
118
|
-
throw err;
|
|
119
|
-
}
|
|
104
|
+
await ensureTable();
|
|
105
|
+
const client = getDbExec();
|
|
106
|
+
const { rows } = await client.execute({
|
|
107
|
+
sql: `SELECT value FROM application_state WHERE session_id = ? AND key = ?`,
|
|
108
|
+
args: [sessionId, key],
|
|
109
|
+
});
|
|
110
|
+
if (rows.length === 0) return null;
|
|
111
|
+
return JSON.parse(rows[0].value as string);
|
|
120
112
|
}
|
|
121
113
|
|
|
122
114
|
/**
|
|
@@ -133,22 +125,17 @@ export async function appStateGetMany(
|
|
|
133
125
|
for (const key of uniqueKeys) values[key] = null;
|
|
134
126
|
if (uniqueKeys.length === 0) return values;
|
|
135
127
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
values[row.key as string] = JSON.parse(row.value as string);
|
|
146
|
-
}
|
|
147
|
-
return values;
|
|
148
|
-
} catch (err) {
|
|
149
|
-
if (isConnectionError(err)) return values;
|
|
150
|
-
throw err;
|
|
128
|
+
await ensureTable();
|
|
129
|
+
const client = getDbExec();
|
|
130
|
+
const placeholders = uniqueKeys.map(() => "?").join(", ");
|
|
131
|
+
const { rows } = await client.execute({
|
|
132
|
+
sql: `SELECT key, value FROM application_state WHERE session_id = ? AND key IN (${placeholders})`,
|
|
133
|
+
args: [sessionId, ...uniqueKeys],
|
|
134
|
+
});
|
|
135
|
+
for (const row of rows) {
|
|
136
|
+
values[row.key as string] = JSON.parse(row.value as string);
|
|
151
137
|
}
|
|
138
|
+
return values;
|
|
152
139
|
}
|
|
153
140
|
|
|
154
141
|
export async function appStatePut(
|
package/src/cli/create.ts
CHANGED
|
@@ -50,6 +50,18 @@ const FIRST_PARTY_TARBALL_SYMLINK_EXCLUDES = [
|
|
|
50
50
|
"*/.claude/skills",
|
|
51
51
|
];
|
|
52
52
|
const localPackageTarballs = new Map<string, string>();
|
|
53
|
+
/** VCS/editor files that don't count as "not empty" for an in-place scaffold. */
|
|
54
|
+
const IN_PLACE_ALLOWLIST = new Set([
|
|
55
|
+
".git",
|
|
56
|
+
".gitignore",
|
|
57
|
+
".gitattributes",
|
|
58
|
+
".DS_Store",
|
|
59
|
+
".idea",
|
|
60
|
+
".vscode",
|
|
61
|
+
"LICENSE",
|
|
62
|
+
"README.md",
|
|
63
|
+
"Thumbs.db",
|
|
64
|
+
]);
|
|
53
65
|
|
|
54
66
|
/**
|
|
55
67
|
* Tagged error for input that fails CLI-level validation (repo names, app
|
|
@@ -110,6 +122,11 @@ export interface CreateAppOptions {
|
|
|
110
122
|
* unconditional workspace scaffold.
|
|
111
123
|
*/
|
|
112
124
|
forceWorkspace?: boolean;
|
|
125
|
+
/**
|
|
126
|
+
* Internal: scaffold into the current directory instead of a new subfolder.
|
|
127
|
+
* Set when the name argument is `.`/`./` (see `createApp`).
|
|
128
|
+
*/
|
|
129
|
+
inPlace?: boolean;
|
|
113
130
|
}
|
|
114
131
|
|
|
115
132
|
/**
|
|
@@ -127,6 +144,13 @@ export async function createApp(
|
|
|
127
144
|
): Promise<void> {
|
|
128
145
|
const clack = await import("@clack/prompts");
|
|
129
146
|
|
|
147
|
+
// `create .` (or `./`) means "scaffold into the current folder" — derive the
|
|
148
|
+
// project name from the folder's basename, like create-react-app / npm init.
|
|
149
|
+
if (name === "." || name === "./") {
|
|
150
|
+
name = path.basename(process.cwd());
|
|
151
|
+
opts = { ...opts, inPlace: true };
|
|
152
|
+
}
|
|
153
|
+
|
|
130
154
|
// Reject an invalid provided name before any interactive prompt so bad input
|
|
131
155
|
// fails fast instead of blocking on the start-shape picker below.
|
|
132
156
|
if (name !== undefined) {
|
|
@@ -335,6 +359,44 @@ function assertValidProjectName(
|
|
|
335
359
|
process.exit(1);
|
|
336
360
|
}
|
|
337
361
|
}
|
|
362
|
+
/**
|
|
363
|
+
* Resolve where a scaffold writes and guard the target. A named project writes
|
|
364
|
+
* to a new sibling subfolder that must not already exist; `create .` writes
|
|
365
|
+
* into the current directory, which must be empty apart from benign VCS/editor
|
|
366
|
+
* files (a pre-existing repo is allowed).
|
|
367
|
+
*
|
|
368
|
+
* For an in-place scaffold we do NOT return the current directory: we build
|
|
369
|
+
* into a private staging directory and `finalizeScaffold` copies the result
|
|
370
|
+
* in afterward. Staging keeps the whole scaffold atomic — a mid-scaffold
|
|
371
|
+
* failure's cleanup can only ever delete the staging dir, never the user's
|
|
372
|
+
* current directory (including its `.git`).
|
|
373
|
+
*/
|
|
374
|
+
function resolveScaffoldTarget(
|
|
375
|
+
name: string,
|
|
376
|
+
inPlace: boolean | undefined,
|
|
377
|
+
clack: typeof import("@clack/prompts"),
|
|
378
|
+
): string {
|
|
379
|
+
if (inPlace) {
|
|
380
|
+
const conflicting = fs
|
|
381
|
+
.readdirSync(process.cwd())
|
|
382
|
+
.filter((entry) => !IN_PLACE_ALLOWLIST.has(entry));
|
|
383
|
+
if (conflicting.length > 0) {
|
|
384
|
+
const shown = conflicting.slice(0, 3).join(", ");
|
|
385
|
+
const more = conflicting.length > 3 ? ", …" : "";
|
|
386
|
+
clack.cancel(
|
|
387
|
+
`Current directory is not empty (${shown}${more}). Scaffold into an empty folder, or run \`create <name>\` to make a new one.`,
|
|
388
|
+
);
|
|
389
|
+
process.exit(1);
|
|
390
|
+
}
|
|
391
|
+
return fs.mkdtempSync(path.join(os.tmpdir(), "agent-native-create-"));
|
|
392
|
+
}
|
|
393
|
+
const targetDir = path.resolve(process.cwd(), name);
|
|
394
|
+
if (fs.existsSync(targetDir)) {
|
|
395
|
+
clack.cancel(`Directory "${name}" already exists.`);
|
|
396
|
+
process.exit(1);
|
|
397
|
+
}
|
|
398
|
+
return targetDir;
|
|
399
|
+
}
|
|
338
400
|
|
|
339
401
|
/* ─────────────────────────────────────────────────────────────────────────
|
|
340
402
|
* Workspace creation (new default)
|
|
@@ -378,11 +440,7 @@ async function createWorkspaceInteractive(
|
|
|
378
440
|
});
|
|
379
441
|
const templates = ["dispatch", ...optionalPicks];
|
|
380
442
|
|
|
381
|
-
const targetDir =
|
|
382
|
-
if (fs.existsSync(targetDir)) {
|
|
383
|
-
clack.cancel(`Directory "${name}" already exists.`);
|
|
384
|
-
process.exit(1);
|
|
385
|
-
}
|
|
443
|
+
const targetDir = resolveScaffoldTarget(name, opts?.inPlace, clack);
|
|
386
444
|
|
|
387
445
|
const s = clack.spinner();
|
|
388
446
|
for (const template of templates) {
|
|
@@ -482,13 +540,15 @@ async function createWorkspaceInteractive(
|
|
|
482
540
|
} catch (err: any) {
|
|
483
541
|
s.stop("Failed to scaffold workspace.");
|
|
484
542
|
// Remove the partially-scaffolded workspace so a retry of `agent-native
|
|
485
|
-
// create <name>` doesn't trip the "Directory already exists" guard.
|
|
543
|
+
// create <name>` doesn't trip the "Directory already exists" guard. For an
|
|
544
|
+
// in-place scaffold `targetDir` is the private staging dir, so this never
|
|
545
|
+
// touches the user's current directory.
|
|
486
546
|
cleanupOnFailure(targetDir);
|
|
487
547
|
clack.cancel(err?.message ?? String(err));
|
|
488
548
|
process.exit(1);
|
|
489
549
|
}
|
|
490
550
|
|
|
491
|
-
|
|
551
|
+
finalizeScaffold(targetDir, opts?.inPlace);
|
|
492
552
|
|
|
493
553
|
// Show the user the tree we just built so the workspace/app distinction is
|
|
494
554
|
// visible, not just described. First-time users routinely expect their
|
|
@@ -845,11 +905,7 @@ async function createStandaloneApp(
|
|
|
845
905
|
|
|
846
906
|
name = await promptNameIfMissing(name, clack, "app", "my-app");
|
|
847
907
|
|
|
848
|
-
const targetDir =
|
|
849
|
-
if (fs.existsSync(targetDir)) {
|
|
850
|
-
clack.cancel(`Directory "${name}" already exists.`);
|
|
851
|
-
process.exit(1);
|
|
852
|
-
}
|
|
908
|
+
const targetDir = resolveScaffoldTarget(name, opts?.inPlace, clack);
|
|
853
909
|
|
|
854
910
|
// Standalone is single-select — pick one template.
|
|
855
911
|
let template =
|
|
@@ -889,12 +945,14 @@ async function createStandaloneApp(
|
|
|
889
945
|
s.stop("App created!");
|
|
890
946
|
} catch (err: any) {
|
|
891
947
|
s.stop("Failed to create app.");
|
|
948
|
+
// `targetDir` is the private staging dir for an in-place scaffold, so this
|
|
949
|
+
// only ever removes the staging copy, never the user's current directory.
|
|
892
950
|
cleanupOnFailure(targetDir);
|
|
893
951
|
clack.cancel(err?.message ?? String(err));
|
|
894
952
|
process.exit(1);
|
|
895
953
|
}
|
|
896
954
|
|
|
897
|
-
|
|
955
|
+
finalizeScaffold(targetDir, opts?.inPlace);
|
|
898
956
|
|
|
899
957
|
if (template === "headless") {
|
|
900
958
|
clack.outro(
|
|
@@ -954,6 +1012,35 @@ function cleanupOnFailure(targetDir: string): void {
|
|
|
954
1012
|
}
|
|
955
1013
|
}
|
|
956
1014
|
|
|
1015
|
+
/**
|
|
1016
|
+
* Land a finished scaffold in its final home and initialize git. A named
|
|
1017
|
+
* scaffold is already in place, so this only inits git. An in-place scaffold
|
|
1018
|
+
* (`create .`) was built in `scaffoldDir` (a staging dir); copy only the files
|
|
1019
|
+
* that don't already exist into the current directory so pre-existing files
|
|
1020
|
+
* (`.git`, `README.md`, `.gitignore`, editor configs) are preserved, then drop
|
|
1021
|
+
* the staging dir. Git init/commit is skipped when the current directory is
|
|
1022
|
+
* already a repo so we never write an unexpected commit into the user's
|
|
1023
|
+
* history.
|
|
1024
|
+
*/
|
|
1025
|
+
function finalizeScaffold(scaffoldDir: string, inPlace?: boolean): void {
|
|
1026
|
+
if (!inPlace) {
|
|
1027
|
+
tryGitInitUnlessRepo(scaffoldDir);
|
|
1028
|
+
return;
|
|
1029
|
+
}
|
|
1030
|
+
const dest = process.cwd();
|
|
1031
|
+
try {
|
|
1032
|
+
copyDir(scaffoldDir, dest, undefined, { skipExisting: true });
|
|
1033
|
+
} finally {
|
|
1034
|
+
cleanupOnFailure(scaffoldDir);
|
|
1035
|
+
}
|
|
1036
|
+
tryGitInitUnlessRepo(dest);
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
function tryGitInitUnlessRepo(dir: string): void {
|
|
1040
|
+
if (fs.existsSync(path.join(dir, ".git"))) return;
|
|
1041
|
+
tryGitInit(dir);
|
|
1042
|
+
}
|
|
1043
|
+
|
|
957
1044
|
/* ─────────────────────────────────────────────────────────────────────────
|
|
958
1045
|
* Shared scaffolding helpers
|
|
959
1046
|
* ───────────────────────────────────────────────────────────────────────── */
|
|
@@ -3399,13 +3486,25 @@ function replacePlaceholders(
|
|
|
3399
3486
|
}
|
|
3400
3487
|
}
|
|
3401
3488
|
|
|
3402
|
-
function copyDir(
|
|
3489
|
+
function copyDir(
|
|
3490
|
+
src: string,
|
|
3491
|
+
dest: string,
|
|
3492
|
+
root?: string,
|
|
3493
|
+
opts?: { skipExisting?: boolean },
|
|
3494
|
+
): void {
|
|
3403
3495
|
const resolvedRoot = root ?? path.resolve(src);
|
|
3496
|
+
const skipExisting = opts?.skipExisting ?? false;
|
|
3404
3497
|
fs.mkdirSync(dest, { recursive: true });
|
|
3405
3498
|
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
3406
3499
|
const srcPath = path.join(src, entry.name);
|
|
3407
3500
|
if (shouldSkipScaffoldEntry(entry.name, srcPath)) continue;
|
|
3408
3501
|
const destPath = path.join(dest, entry.name);
|
|
3502
|
+
// Preserve anything already at the destination (in-place scaffold merges
|
|
3503
|
+
// into a directory the user may already own). Directories still recurse so
|
|
3504
|
+
// new files land inside a pre-existing folder.
|
|
3505
|
+
if (skipExisting && !entry.isDirectory() && fs.existsSync(destPath)) {
|
|
3506
|
+
continue;
|
|
3507
|
+
}
|
|
3409
3508
|
if (entry.isSymbolicLink()) {
|
|
3410
3509
|
const target = fs.readlinkSync(srcPath);
|
|
3411
3510
|
const resolvedTarget = path.resolve(path.dirname(srcPath), target);
|
|
@@ -3415,7 +3514,7 @@ function copyDir(src: string, dest: string, root?: string): void {
|
|
|
3415
3514
|
try {
|
|
3416
3515
|
const stat = fs.statSync(srcPath);
|
|
3417
3516
|
if (stat.isDirectory()) {
|
|
3418
|
-
copyDir(srcPath, destPath, resolvedRoot);
|
|
3517
|
+
copyDir(srcPath, destPath, resolvedRoot, opts);
|
|
3419
3518
|
} else {
|
|
3420
3519
|
fs.copyFileSync(srcPath, destPath);
|
|
3421
3520
|
}
|
|
@@ -3424,7 +3523,7 @@ function copyDir(src: string, dest: string, root?: string): void {
|
|
|
3424
3523
|
}
|
|
3425
3524
|
}
|
|
3426
3525
|
} else if (entry.isDirectory()) {
|
|
3427
|
-
copyDir(srcPath, destPath, resolvedRoot);
|
|
3526
|
+
copyDir(srcPath, destPath, resolvedRoot, opts);
|
|
3428
3527
|
} else {
|
|
3429
3528
|
fs.copyFileSync(srcPath, destPath);
|
|
3430
3529
|
}
|
|
@@ -3421,7 +3421,11 @@ const AssistantChatInner = forwardRef<
|
|
|
3421
3421
|
}
|
|
3422
3422
|
window.dispatchEvent(
|
|
3423
3423
|
new CustomEvent("agentNative.chatRunning", {
|
|
3424
|
-
detail: {
|
|
3424
|
+
detail: {
|
|
3425
|
+
isRunning: false,
|
|
3426
|
+
tabId: tabId || threadId,
|
|
3427
|
+
reason: "failed",
|
|
3428
|
+
},
|
|
3425
3429
|
}),
|
|
3426
3430
|
);
|
|
3427
3431
|
return;
|
|
@@ -4510,7 +4514,11 @@ const AssistantChatInner = forwardRef<
|
|
|
4510
4514
|
if (typeof window !== "undefined") {
|
|
4511
4515
|
window.dispatchEvent(
|
|
4512
4516
|
new CustomEvent("agentNative.chatRunning", {
|
|
4513
|
-
detail: {
|
|
4517
|
+
detail: {
|
|
4518
|
+
isRunning: false,
|
|
4519
|
+
tabId: tabId || threadId,
|
|
4520
|
+
reason: "stopped",
|
|
4521
|
+
},
|
|
4514
4522
|
}),
|
|
4515
4523
|
);
|
|
4516
4524
|
}
|
|
@@ -115,7 +115,11 @@ export interface FrameOriginMessage {
|
|
|
115
115
|
|
|
116
116
|
export interface ChatRunningMessage {
|
|
117
117
|
type: "agentNative.chatRunning";
|
|
118
|
-
detail: {
|
|
118
|
+
detail: {
|
|
119
|
+
isRunning: boolean;
|
|
120
|
+
tabId?: string;
|
|
121
|
+
reason?: "stopped" | "failed";
|
|
122
|
+
};
|
|
119
123
|
}
|
|
120
124
|
|
|
121
125
|
export interface UserInfoMessage {
|