@agent-native/core 0.84.29 → 0.84.32
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 +19 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/client/chat/tool-call-display.tsx +50 -8
- package/corpus/core/src/client/session-replay.ts +5 -0
- package/corpus/core/src/client/sse-event-processor.ts +17 -4
- package/corpus/core/src/server/ssr-handler.ts +152 -8
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +13 -1
- package/corpus/templates/analytics/changelog/2026-07-01-session-replays-keep-inlined-css-without-live-resource-loa.md +6 -0
- package/corpus/templates/design/AGENTS.md +18 -0
- package/corpus/templates/design/actions/apply-source-edit.ts +87 -0
- package/corpus/templates/design/actions/list-source-files.ts +52 -0
- package/corpus/templates/design/actions/navigate.ts +3 -2
- package/corpus/templates/design/actions/preview-source-edit.ts +85 -0
- package/corpus/templates/design/actions/read-source-file.ts +55 -0
- package/corpus/templates/design/actions/resolve-selection-source.ts +101 -0
- package/corpus/templates/design/actions/view-screen.ts +43 -1
- package/corpus/templates/design/app/components/design/CodeWorkbenchHost.tsx +630 -0
- package/corpus/templates/design/app/hooks/use-navigation-state.ts +9 -6
- package/corpus/templates/design/app/pages/DesignEditor.tsx +189 -11
- package/corpus/templates/design/changelog/2026-07-01-design-code-workspace.md +6 -0
- package/corpus/templates/design/changelog/2026-07-01-design-previews-refresh-immediately-after-agent-screen-edits.md +6 -0
- package/corpus/templates/design/server/source-workspace.ts +215 -0
- package/corpus/templates/design/shared/design-source-capabilities.ts +5 -5
- package/corpus/templates/design/shared/source-workspace.ts +149 -0
- package/dist/client/chat/tool-call-display.d.ts +1 -0
- package/dist/client/chat/tool-call-display.d.ts.map +1 -1
- package/dist/client/chat/tool-call-display.js +22 -5
- package/dist/client/chat/tool-call-display.js.map +1 -1
- package/dist/client/session-replay.d.ts +1 -0
- package/dist/client/session-replay.d.ts.map +1 -1
- package/dist/client/session-replay.js +2 -0
- package/dist/client/session-replay.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +13 -4
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +5 -5
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/ssr-handler.d.ts.map +1 -1
- package/dist/server/ssr-handler.js +111 -8
- package/dist/server/ssr-handler.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { defineAction } from "@agent-native/core";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
findSourceWorkspaceFile,
|
|
6
|
+
readLiveSourceFile,
|
|
7
|
+
resolveSourceWorkspace,
|
|
8
|
+
} from "../server/source-workspace.js";
|
|
9
|
+
import {
|
|
10
|
+
applySourceEdit,
|
|
11
|
+
previewSourceDiff,
|
|
12
|
+
} from "../shared/source-workspace.js";
|
|
13
|
+
|
|
14
|
+
const sourceEditSchema = z.discriminatedUnion("kind", [
|
|
15
|
+
z.object({
|
|
16
|
+
kind: z.literal("full-replace"),
|
|
17
|
+
content: z.string().describe("Complete replacement file content"),
|
|
18
|
+
}),
|
|
19
|
+
z.object({
|
|
20
|
+
kind: z.literal("exact-replace"),
|
|
21
|
+
search: z.string().min(1).describe("Unique exact text to replace"),
|
|
22
|
+
replace: z.string().describe("Replacement text"),
|
|
23
|
+
}),
|
|
24
|
+
]);
|
|
25
|
+
|
|
26
|
+
export default defineAction({
|
|
27
|
+
description:
|
|
28
|
+
"Preview a source-file edit without saving it. Returns changed byte counts, " +
|
|
29
|
+
"line range, and compact before/after excerpts for Design code workspace diffs.",
|
|
30
|
+
schema: z
|
|
31
|
+
.object({
|
|
32
|
+
designId: z.string().describe("Design project ID"),
|
|
33
|
+
path: z
|
|
34
|
+
.string()
|
|
35
|
+
.optional()
|
|
36
|
+
.describe("Source path/filename, such as index.html"),
|
|
37
|
+
fileId: z.string().optional().describe("Design file ID"),
|
|
38
|
+
edit: sourceEditSchema,
|
|
39
|
+
expectedVersionHash: z
|
|
40
|
+
.string()
|
|
41
|
+
.optional()
|
|
42
|
+
.describe("Optional hash from read-source-file to detect stale edits"),
|
|
43
|
+
})
|
|
44
|
+
.refine((args) => args.path || args.fileId, {
|
|
45
|
+
message: "Provide either path or fileId.",
|
|
46
|
+
path: ["path"],
|
|
47
|
+
}),
|
|
48
|
+
readOnly: true,
|
|
49
|
+
run: async ({ designId, path, fileId, edit, expectedVersionHash }) => {
|
|
50
|
+
const workspace = await resolveSourceWorkspace(designId, {
|
|
51
|
+
includeContent: true,
|
|
52
|
+
});
|
|
53
|
+
const file = findSourceWorkspaceFile(workspace.files, { fileId, path });
|
|
54
|
+
const live = await readLiveSourceFile(file);
|
|
55
|
+
const stale =
|
|
56
|
+
expectedVersionHash !== undefined &&
|
|
57
|
+
expectedVersionHash !== live.versionHash;
|
|
58
|
+
if (stale) {
|
|
59
|
+
return {
|
|
60
|
+
designId,
|
|
61
|
+
path: file.filename,
|
|
62
|
+
fileId: file.id,
|
|
63
|
+
okToApply: false,
|
|
64
|
+
conflict: "stale-version",
|
|
65
|
+
currentVersionHash: live.versionHash,
|
|
66
|
+
message:
|
|
67
|
+
"Source file changed since it was read. Re-read before saving.",
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const next = applySourceEdit(live.content, edit);
|
|
72
|
+
return {
|
|
73
|
+
designId,
|
|
74
|
+
path: file.filename,
|
|
75
|
+
fileId: file.id,
|
|
76
|
+
okToApply: workspace.canEdit && workspace.sourceType === "inline",
|
|
77
|
+
conflict:
|
|
78
|
+
workspace.sourceType === "inline" ? null : "unsupported-source-backend",
|
|
79
|
+
currentVersionHash: live.versionHash,
|
|
80
|
+
nextVersionHash: next.changed ? undefined : live.versionHash,
|
|
81
|
+
editsApplied: next.editsApplied,
|
|
82
|
+
diff: previewSourceDiff(live.content, next.content),
|
|
83
|
+
};
|
|
84
|
+
},
|
|
85
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { defineAction } from "@agent-native/core";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
findSourceWorkspaceFile,
|
|
6
|
+
readLiveSourceFile,
|
|
7
|
+
resolveSourceWorkspace,
|
|
8
|
+
} from "../server/source-workspace.js";
|
|
9
|
+
|
|
10
|
+
export default defineAction({
|
|
11
|
+
description:
|
|
12
|
+
"Read one Design source file. For inline designs this returns live " +
|
|
13
|
+
"design_files content with a version hash for safe follow-up writes.",
|
|
14
|
+
schema: z
|
|
15
|
+
.object({
|
|
16
|
+
designId: z.string().describe("Design project ID"),
|
|
17
|
+
path: z
|
|
18
|
+
.string()
|
|
19
|
+
.optional()
|
|
20
|
+
.describe("Source path/filename, such as index.html"),
|
|
21
|
+
fileId: z.string().optional().describe("Design file ID"),
|
|
22
|
+
})
|
|
23
|
+
.refine((args) => args.path || args.fileId, {
|
|
24
|
+
message: "Provide either path or fileId.",
|
|
25
|
+
path: ["path"],
|
|
26
|
+
}),
|
|
27
|
+
readOnly: true,
|
|
28
|
+
http: { method: "GET" },
|
|
29
|
+
run: async ({ designId, path, fileId }) => {
|
|
30
|
+
const workspace = await resolveSourceWorkspace(designId, {
|
|
31
|
+
includeContent: true,
|
|
32
|
+
});
|
|
33
|
+
const file = findSourceWorkspaceFile(workspace.files, { fileId, path });
|
|
34
|
+
const live = await readLiveSourceFile(file);
|
|
35
|
+
return {
|
|
36
|
+
designId,
|
|
37
|
+
path: file.filename,
|
|
38
|
+
displayName: file.filename,
|
|
39
|
+
fileId: file.id,
|
|
40
|
+
sourceType: workspace.sourceType,
|
|
41
|
+
backendKind: "virtual-inline",
|
|
42
|
+
readonly: !workspace.canEdit || workspace.sourceType !== "inline",
|
|
43
|
+
language: live.language,
|
|
44
|
+
content: live.content,
|
|
45
|
+
versionHash: live.versionHash,
|
|
46
|
+
updatedAt: file.updatedAt,
|
|
47
|
+
provenance: {
|
|
48
|
+
kind: "design-file",
|
|
49
|
+
designId,
|
|
50
|
+
fileId: file.id,
|
|
51
|
+
filename: file.filename,
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
},
|
|
55
|
+
});
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { defineAction } from "@agent-native/core";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
findSourceWorkspaceFile,
|
|
6
|
+
readLiveSourceFile,
|
|
7
|
+
resolveSourceWorkspace,
|
|
8
|
+
} from "../server/source-workspace.js";
|
|
9
|
+
import { buildCodeLayerProjection } from "../shared/code-layer.js";
|
|
10
|
+
|
|
11
|
+
function offsetToLineColumn(content: string, offset: number) {
|
|
12
|
+
let line = 1;
|
|
13
|
+
let column = 1;
|
|
14
|
+
for (let index = 0; index < offset; index += 1) {
|
|
15
|
+
if (content.charCodeAt(index) === 10) {
|
|
16
|
+
line += 1;
|
|
17
|
+
column = 1;
|
|
18
|
+
} else {
|
|
19
|
+
column += 1;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return { line, column };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default defineAction({
|
|
26
|
+
description:
|
|
27
|
+
"Resolve a selected Design canvas node to the best source file location. " +
|
|
28
|
+
"Inline designs resolve to the containing design file and, when possible, " +
|
|
29
|
+
"a line/column/snippet from the code-layer projection.",
|
|
30
|
+
schema: z
|
|
31
|
+
.object({
|
|
32
|
+
designId: z.string().describe("Design project ID"),
|
|
33
|
+
path: z
|
|
34
|
+
.string()
|
|
35
|
+
.optional()
|
|
36
|
+
.describe("Source path/filename, such as index.html"),
|
|
37
|
+
fileId: z.string().optional().describe("Design file ID"),
|
|
38
|
+
nodeId: z
|
|
39
|
+
.string()
|
|
40
|
+
.optional()
|
|
41
|
+
.describe("data-agent-native-node-id or code-layer node id"),
|
|
42
|
+
selector: z.string().optional().describe("CSS selector fallback"),
|
|
43
|
+
})
|
|
44
|
+
.refine((args) => args.path || args.fileId, {
|
|
45
|
+
message: "Provide either path or fileId.",
|
|
46
|
+
path: ["path"],
|
|
47
|
+
}),
|
|
48
|
+
readOnly: true,
|
|
49
|
+
http: { method: "GET" },
|
|
50
|
+
run: async ({ designId, path, fileId, nodeId, selector }) => {
|
|
51
|
+
const workspace = await resolveSourceWorkspace(designId, {
|
|
52
|
+
includeContent: true,
|
|
53
|
+
});
|
|
54
|
+
const file = findSourceWorkspaceFile(workspace.files, { fileId, path });
|
|
55
|
+
const live = await readLiveSourceFile(file);
|
|
56
|
+
const projection = buildCodeLayerProjection(live.content, {
|
|
57
|
+
source: {
|
|
58
|
+
kind: "design-file",
|
|
59
|
+
designId,
|
|
60
|
+
fileId: file.id,
|
|
61
|
+
filename: file.filename,
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
const node =
|
|
65
|
+
projection.nodes.find(
|
|
66
|
+
(candidate) =>
|
|
67
|
+
candidate.id === nodeId ||
|
|
68
|
+
candidate.dataAttributes["data-agent-native-node-id"] === nodeId ||
|
|
69
|
+
candidate.dataAttributes["data-code-layer-id"] === nodeId,
|
|
70
|
+
) ??
|
|
71
|
+
projection.nodes.find((candidate) =>
|
|
72
|
+
selector
|
|
73
|
+
? candidate.selector === selector ||
|
|
74
|
+
candidate.path === selector ||
|
|
75
|
+
candidate.selectors.includes(selector)
|
|
76
|
+
: false,
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
const start = node?.source?.openStart ?? node?.source?.start;
|
|
80
|
+
const location =
|
|
81
|
+
typeof start === "number"
|
|
82
|
+
? offsetToLineColumn(live.content, start)
|
|
83
|
+
: null;
|
|
84
|
+
const snippet =
|
|
85
|
+
node?.source && typeof node.source.start === "number"
|
|
86
|
+
? live.content.slice(node.source.start, node.source.end).slice(0, 1200)
|
|
87
|
+
: undefined;
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
designId,
|
|
91
|
+
sourceType: workspace.sourceType,
|
|
92
|
+
backendKind: "virtual-inline",
|
|
93
|
+
path: file.filename,
|
|
94
|
+
fileId: file.id,
|
|
95
|
+
line: location?.line ?? null,
|
|
96
|
+
column: location?.column ?? null,
|
|
97
|
+
snippet,
|
|
98
|
+
resolved: Boolean(node),
|
|
99
|
+
};
|
|
100
|
+
},
|
|
101
|
+
});
|
|
@@ -34,6 +34,20 @@ function stringArrayProp(value: unknown, key: string): string[] {
|
|
|
34
34
|
: [];
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
function boolProp(value: unknown, key: string): boolean | undefined {
|
|
38
|
+
if (!value || typeof value !== "object") return undefined;
|
|
39
|
+
const candidate = (value as Record<string, unknown>)[key];
|
|
40
|
+
return typeof candidate === "boolean" ? candidate : undefined;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function objectProp(value: unknown, key: string): Record<string, unknown> {
|
|
44
|
+
if (!value || typeof value !== "object") return {};
|
|
45
|
+
const candidate = (value as Record<string, unknown>)[key];
|
|
46
|
+
return candidate && typeof candidate === "object" && !Array.isArray(candidate)
|
|
47
|
+
? (candidate as Record<string, unknown>)
|
|
48
|
+
: {};
|
|
49
|
+
}
|
|
50
|
+
|
|
37
51
|
function resolveActiveScreen(
|
|
38
52
|
files: Array<{
|
|
39
53
|
id: string;
|
|
@@ -93,9 +107,36 @@ function resolveActiveScreen(
|
|
|
93
107
|
return null;
|
|
94
108
|
}
|
|
95
109
|
|
|
110
|
+
function resolveActiveCodeFile(
|
|
111
|
+
files: Array<{
|
|
112
|
+
id: string;
|
|
113
|
+
filename: string;
|
|
114
|
+
fileType: string | null;
|
|
115
|
+
updatedAt: string | null;
|
|
116
|
+
}>,
|
|
117
|
+
designSelection: unknown,
|
|
118
|
+
) {
|
|
119
|
+
const codeWorkspace = objectProp(designSelection, "codeWorkspace");
|
|
120
|
+
if (Object.keys(codeWorkspace).length === 0) return null;
|
|
121
|
+
const fileId = stringProp(codeWorkspace, "activeFileId");
|
|
122
|
+
const path = stringProp(codeWorkspace, "activePath");
|
|
123
|
+
const file = files.find(
|
|
124
|
+
(candidate) => candidate.id === fileId || candidate.filename === path,
|
|
125
|
+
);
|
|
126
|
+
return {
|
|
127
|
+
open: boolProp(codeWorkspace, "open") ?? false,
|
|
128
|
+
backendKind: stringProp(codeWorkspace, "backendKind") ?? "virtual-inline",
|
|
129
|
+
path: path ?? file?.filename ?? null,
|
|
130
|
+
fileId: fileId ?? file?.id ?? null,
|
|
131
|
+
dirty: boolProp(codeWorkspace, "dirty") ?? false,
|
|
132
|
+
versionHash: stringProp(codeWorkspace, "versionHash") ?? null,
|
|
133
|
+
file: file ?? null,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
96
137
|
export default defineAction({
|
|
97
138
|
description:
|
|
98
|
-
"See what the user is currently looking at on screen. Returns the current navigation state including which design is open, which view they are on (list, editor, design-systems, present, settings), active/focused design screen, selected element, active inspector tab (design or tweaks), active left rail panel (file, agent, assets, tools, or
|
|
139
|
+
"See what the user is currently looking at on screen. Returns the current navigation state including which design is open, which view they are on (list, editor, design-systems, present, settings), active/focused design screen, selected element, active inspector tab (design or tweaks), active left rail panel (file, agent, assets, tools, tokens, or code), active code file metadata, overview canvas state, plus any pending question overlay. Always call this first before taking any action.",
|
|
99
140
|
schema: z.object({}),
|
|
100
141
|
http: false,
|
|
101
142
|
run: async () => {
|
|
@@ -154,6 +195,7 @@ export default defineAction({
|
|
|
154
195
|
title: (access.resource as { title?: unknown }).title ?? null,
|
|
155
196
|
screens: files,
|
|
156
197
|
activeScreen: resolveActiveScreen(files, navigation, designSelection),
|
|
198
|
+
activeCodeFile: resolveActiveCodeFile(files, designSelection),
|
|
157
199
|
canvasFrames: parseCanvasFrameGeometryById(data.canvasFrames),
|
|
158
200
|
};
|
|
159
201
|
}
|