@agent-native/core 0.49.9 → 0.49.11
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/cli/pr-visual-recap-workflow.d.ts +1 -1
- package/dist/cli/pr-visual-recap-workflow.d.ts.map +1 -1
- package/dist/cli/pr-visual-recap-workflow.js +1 -1
- package/dist/cli/pr-visual-recap-workflow.js.map +1 -1
- package/dist/cli/recap.d.ts +4 -1
- package/dist/cli/recap.d.ts.map +1 -1
- package/dist/cli/recap.js +97 -23
- package/dist/cli/recap.js.map +1 -1
- package/dist/cli/skills.d.ts +5 -5
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +219 -24
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/blocks/library/annotation-rail.d.ts.map +1 -1
- package/dist/client/blocks/library/annotation-rail.js +16 -6
- package/dist/client/blocks/library/annotation-rail.js.map +1 -1
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +10 -2
- package/dist/deploy/build.js.map +1 -1
- package/dist/extensions/actions.js +1 -1
- package/dist/extensions/actions.js.map +1 -1
- package/dist/local-artifacts/index.d.ts +101 -0
- package/dist/local-artifacts/index.d.ts.map +1 -0
- package/dist/local-artifacts/index.js +507 -0
- package/dist/local-artifacts/index.js.map +1 -0
- package/dist/secrets/substitution.js +2 -2
- package/dist/secrets/substitution.js.map +1 -1
- package/dist/server/auth-marketing.d.ts +1 -0
- package/dist/server/auth-marketing.d.ts.map +1 -1
- package/dist/server/auth-marketing.js +5 -0
- package/dist/server/auth-marketing.js.map +1 -1
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +59 -37
- package/dist/server/auth.js.map +1 -1
- package/dist/server/entry-server.d.ts +27 -4
- package/dist/server/entry-server.d.ts.map +1 -1
- package/dist/server/entry-server.js +63 -43
- package/dist/server/entry-server.js.map +1 -1
- package/dist/server/onboarding-html.d.ts.map +1 -1
- package/dist/server/onboarding-html.js +3 -3
- package/dist/server/onboarding-html.js.map +1 -1
- package/dist/server/social-og-image.d.ts +2 -0
- package/dist/server/social-og-image.d.ts.map +1 -1
- package/dist/server/social-og-image.js +20 -7
- package/dist/server/social-og-image.js.map +1 -1
- package/dist/server/ssr-handler.d.ts.map +1 -1
- package/dist/server/ssr-handler.js +2 -2
- package/dist/server/ssr-handler.js.map +1 -1
- package/dist/shared/index.d.ts +1 -1
- package/dist/shared/index.d.ts.map +1 -1
- package/dist/shared/index.js +1 -1
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/social-meta.d.ts +2 -0
- package/dist/shared/social-meta.d.ts.map +1 -1
- package/dist/shared/social-meta.js +5 -0
- package/dist/shared/social-meta.js.map +1 -1
- package/dist/templates/default/.agents/skills/storing-data/SKILL.md +3 -1
- package/dist/templates/default/app/entry.server.tsx +8 -2
- package/dist/templates/starter-shell-sync.spec.ts +4 -3
- package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +3 -2
- package/dist/templates/workspace-core/.agents/skills/storing-data/SKILL.md +3 -1
- package/docs/content/pr-visual-recap.md +4 -4
- package/docs/content/template-content.md +9 -0
- package/package.json +6 -1
- package/src/templates/default/.agents/skills/storing-data/SKILL.md +3 -1
- package/src/templates/default/app/entry.server.tsx +8 -2
- package/src/templates/starter-shell-sync.spec.ts +4 -3
- package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +3 -2
- package/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +3 -1
|
@@ -0,0 +1,507 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import fsSync from "node:fs";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { minimatch } from "minimatch";
|
|
7
|
+
const MANIFEST_FILE = "agent-native.json";
|
|
8
|
+
const ENV_MODE_NAMES = ["AGENT_NATIVE_MODE", "AGENT_NATIVE_DATA_MODE"];
|
|
9
|
+
const ENV_MANIFEST_NAMES = [
|
|
10
|
+
"AGENT_NATIVE_MANIFEST",
|
|
11
|
+
"AGENT_NATIVE_MANIFEST_PATH",
|
|
12
|
+
];
|
|
13
|
+
const ALLOW_PRODUCTION_LOCAL_FILES_ENV = "AGENT_NATIVE_ALLOW_LOCAL_FILES_IN_PRODUCTION";
|
|
14
|
+
const DEFAULT_HIDE_PATTERNS = [
|
|
15
|
+
"**/.git/**",
|
|
16
|
+
"**/.agent-native/**",
|
|
17
|
+
"**/.next/**",
|
|
18
|
+
"**/.nuxt/**",
|
|
19
|
+
"**/node_modules/**",
|
|
20
|
+
"**/dist/**",
|
|
21
|
+
"**/build/**",
|
|
22
|
+
];
|
|
23
|
+
function isRecord(value) {
|
|
24
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
25
|
+
}
|
|
26
|
+
function errorCode(error) {
|
|
27
|
+
return isRecord(error) && typeof error.code === "string"
|
|
28
|
+
? error.code
|
|
29
|
+
: undefined;
|
|
30
|
+
}
|
|
31
|
+
function asStringArray(value) {
|
|
32
|
+
if (typeof value === "string" && value.trim())
|
|
33
|
+
return [value.trim()];
|
|
34
|
+
if (!Array.isArray(value))
|
|
35
|
+
return [];
|
|
36
|
+
return value.filter((item) => typeof item === "string");
|
|
37
|
+
}
|
|
38
|
+
function normalizeMode(value) {
|
|
39
|
+
if (value === "database" || value === "local-files")
|
|
40
|
+
return value;
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
function normalizeSlash(filePath) {
|
|
44
|
+
return filePath.replace(/\\/g, "/");
|
|
45
|
+
}
|
|
46
|
+
function normalizeRelativePath(filePath, label = "path") {
|
|
47
|
+
if (!filePath || typeof filePath !== "string") {
|
|
48
|
+
throw new Error(`${label} is required`);
|
|
49
|
+
}
|
|
50
|
+
if (filePath.includes("\0")) {
|
|
51
|
+
throw new Error(`${label} must not contain null bytes`);
|
|
52
|
+
}
|
|
53
|
+
if (path.isAbsolute(filePath)) {
|
|
54
|
+
throw new Error(`${label} must be relative`);
|
|
55
|
+
}
|
|
56
|
+
const normalized = normalizeSlash(path.posix.normalize(normalizeSlash(filePath)));
|
|
57
|
+
if (!normalized ||
|
|
58
|
+
normalized === "." ||
|
|
59
|
+
normalized.startsWith("../") ||
|
|
60
|
+
normalized === ".." ||
|
|
61
|
+
normalized.split("/").some((part) => !part || part === "." || part === "..")) {
|
|
62
|
+
throw new Error(`${label} must be a safe relative path`);
|
|
63
|
+
}
|
|
64
|
+
return normalized;
|
|
65
|
+
}
|
|
66
|
+
function extensionOf(filePath) {
|
|
67
|
+
return path.posix.extname(filePath).toLowerCase();
|
|
68
|
+
}
|
|
69
|
+
function normalizeExtensions(value) {
|
|
70
|
+
const extensions = asStringArray(value)
|
|
71
|
+
.map((ext) => ext.trim().toLowerCase())
|
|
72
|
+
.filter(Boolean)
|
|
73
|
+
.map((ext) => (ext.startsWith(".") ? ext : `.${ext}`));
|
|
74
|
+
return [...new Set(extensions)];
|
|
75
|
+
}
|
|
76
|
+
function rootNameFromPath(rootPath) {
|
|
77
|
+
return (rootPath
|
|
78
|
+
.split("/")
|
|
79
|
+
.filter(Boolean)
|
|
80
|
+
.at(-1)
|
|
81
|
+
?.replace(/[-_]+/g, " ")
|
|
82
|
+
.replace(/\b\w/g, (char) => char.toUpperCase()) || rootPath);
|
|
83
|
+
}
|
|
84
|
+
function normalizeManifestRoot(value) {
|
|
85
|
+
if (typeof value === "string")
|
|
86
|
+
return { path: value };
|
|
87
|
+
if (!isRecord(value) || typeof value.path !== "string")
|
|
88
|
+
return null;
|
|
89
|
+
return {
|
|
90
|
+
name: typeof value.name === "string" ? value.name : undefined,
|
|
91
|
+
path: value.path,
|
|
92
|
+
kind: typeof value.kind === "string" ? value.kind : undefined,
|
|
93
|
+
extensions: normalizeExtensions(value.extensions),
|
|
94
|
+
include: asStringArray(value.include),
|
|
95
|
+
hide: asStringArray(value.hide),
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function normalizeManifestApp(value) {
|
|
99
|
+
if (Array.isArray(value)) {
|
|
100
|
+
return {
|
|
101
|
+
roots: value
|
|
102
|
+
.map(normalizeManifestRoot)
|
|
103
|
+
.filter((root) => !!root),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
if (!isRecord(value))
|
|
107
|
+
return {};
|
|
108
|
+
const roots = Array.isArray(value.roots)
|
|
109
|
+
? value.roots
|
|
110
|
+
.map(normalizeManifestRoot)
|
|
111
|
+
.filter((root) => !!root)
|
|
112
|
+
: [];
|
|
113
|
+
return {
|
|
114
|
+
mode: normalizeMode(value.mode),
|
|
115
|
+
roots,
|
|
116
|
+
components: typeof value.components === "string" || Array.isArray(value.components)
|
|
117
|
+
? asStringArray(value.components)
|
|
118
|
+
: undefined,
|
|
119
|
+
hide: asStringArray(value.hide),
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function normalizeManifest(value) {
|
|
123
|
+
const record = isRecord(value) ? value : {};
|
|
124
|
+
const appsRecord = isRecord(record.apps) ? record.apps : {};
|
|
125
|
+
const apps = {};
|
|
126
|
+
for (const [appId, appValue] of Object.entries(appsRecord)) {
|
|
127
|
+
apps[appId] = normalizeManifestApp(appValue);
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
version: typeof record.version === "number" && Number.isFinite(record.version)
|
|
131
|
+
? record.version
|
|
132
|
+
: undefined,
|
|
133
|
+
mode: normalizeMode(record.mode),
|
|
134
|
+
apps,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
function firstEnvValue(names) {
|
|
138
|
+
for (const name of names) {
|
|
139
|
+
const value = process.env[name]?.trim();
|
|
140
|
+
if (value)
|
|
141
|
+
return value;
|
|
142
|
+
}
|
|
143
|
+
return undefined;
|
|
144
|
+
}
|
|
145
|
+
function envMode() {
|
|
146
|
+
return normalizeMode(firstEnvValue(ENV_MODE_NAMES));
|
|
147
|
+
}
|
|
148
|
+
function envFlag(name) {
|
|
149
|
+
const value = process.env[name]?.trim().toLowerCase();
|
|
150
|
+
return value === "1" || value === "true" || value === "yes" || value === "on";
|
|
151
|
+
}
|
|
152
|
+
function assertLocalFilesRuntimeAllowed(mode) {
|
|
153
|
+
if (mode !== "local-files")
|
|
154
|
+
return;
|
|
155
|
+
if (process.env.NODE_ENV !== "production")
|
|
156
|
+
return;
|
|
157
|
+
if (envFlag(ALLOW_PRODUCTION_LOCAL_FILES_ENV))
|
|
158
|
+
return;
|
|
159
|
+
throw new Error(`Local file mode is only enabled for local development runtimes. Set ${ALLOW_PRODUCTION_LOCAL_FILES_ENV}=true only for a trusted single-tenant local file bridge.`);
|
|
160
|
+
}
|
|
161
|
+
function envManifestPath() {
|
|
162
|
+
return firstEnvValue(ENV_MANIFEST_NAMES);
|
|
163
|
+
}
|
|
164
|
+
export function findAgentNativeManifest(startDir = process.cwd()) {
|
|
165
|
+
let current = path.resolve(startDir);
|
|
166
|
+
for (;;) {
|
|
167
|
+
const candidate = path.join(current, MANIFEST_FILE);
|
|
168
|
+
if (fsSync.existsSync(candidate))
|
|
169
|
+
return candidate;
|
|
170
|
+
const parent = path.dirname(current);
|
|
171
|
+
if (parent === current)
|
|
172
|
+
return null;
|
|
173
|
+
current = parent;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
export async function loadAgentNativeManifest(options = {}) {
|
|
177
|
+
const manifestPath = options.manifestPath ??
|
|
178
|
+
envManifestPath() ??
|
|
179
|
+
findAgentNativeManifest(options.cwd ?? process.cwd());
|
|
180
|
+
if (!manifestPath) {
|
|
181
|
+
if (options.optional)
|
|
182
|
+
return null;
|
|
183
|
+
throw new Error(`Could not find ${MANIFEST_FILE}`);
|
|
184
|
+
}
|
|
185
|
+
const resolvedPath = path.resolve(options.cwd ?? process.cwd(), manifestPath);
|
|
186
|
+
try {
|
|
187
|
+
const raw = await fs.readFile(resolvedPath, "utf8");
|
|
188
|
+
const parsed = JSON.parse(raw);
|
|
189
|
+
return {
|
|
190
|
+
path: resolvedPath,
|
|
191
|
+
rootDir: path.dirname(resolvedPath),
|
|
192
|
+
manifest: normalizeManifest(parsed),
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
catch (error) {
|
|
196
|
+
if (options.optional && errorCode(error) === "ENOENT") {
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
throw error;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
export async function resolveAgentNativeDataMode(options = {}) {
|
|
203
|
+
const explicitMode = envMode();
|
|
204
|
+
if (explicitMode) {
|
|
205
|
+
assertLocalFilesRuntimeAllowed(explicitMode);
|
|
206
|
+
return explicitMode;
|
|
207
|
+
}
|
|
208
|
+
const loaded = await loadAgentNativeManifest({ ...options, optional: true });
|
|
209
|
+
const appMode = options.appId
|
|
210
|
+
? loaded?.manifest.apps?.[options.appId]?.mode
|
|
211
|
+
: undefined;
|
|
212
|
+
const mode = appMode ?? loaded?.manifest.mode ?? options.defaults?.mode ?? "database";
|
|
213
|
+
assertLocalFilesRuntimeAllowed(mode);
|
|
214
|
+
return mode;
|
|
215
|
+
}
|
|
216
|
+
export async function isAgentNativeLocalFileMode(options = {}) {
|
|
217
|
+
return (await resolveAgentNativeDataMode(options)) === "local-files";
|
|
218
|
+
}
|
|
219
|
+
function mergeAppConfig(manifestApp, defaults) {
|
|
220
|
+
return {
|
|
221
|
+
mode: manifestApp?.mode ?? defaults?.mode,
|
|
222
|
+
roots: manifestApp?.roots && manifestApp.roots.length > 0
|
|
223
|
+
? manifestApp.roots
|
|
224
|
+
: (defaults?.roots ?? []),
|
|
225
|
+
components: manifestApp?.components ?? defaults?.components,
|
|
226
|
+
hide: [...(defaults?.hide ?? []), ...(manifestApp?.hide ?? [])],
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
function resolveInsideWorkspace(workspaceRoot, relativePath) {
|
|
230
|
+
const safePath = normalizeRelativePath(relativePath);
|
|
231
|
+
const absolutePath = path.resolve(workspaceRoot, safePath);
|
|
232
|
+
const relative = path.relative(workspaceRoot, absolutePath);
|
|
233
|
+
if (relative === "" ||
|
|
234
|
+
relative.startsWith("..") ||
|
|
235
|
+
path.isAbsolute(relative)) {
|
|
236
|
+
throw new Error(`Path "${relativePath}" is outside the workspace`);
|
|
237
|
+
}
|
|
238
|
+
return { safePath, absolutePath };
|
|
239
|
+
}
|
|
240
|
+
export async function getLocalArtifactApp(options) {
|
|
241
|
+
const loaded = await loadAgentNativeManifest({ ...options, optional: true });
|
|
242
|
+
const workspaceRoot = loaded?.rootDir ?? path.resolve(options.cwd ?? process.cwd());
|
|
243
|
+
const manifestApp = loaded?.manifest.apps?.[options.appId];
|
|
244
|
+
const app = mergeAppConfig(manifestApp, options.defaults);
|
|
245
|
+
const mode = await resolveAgentNativeDataMode({
|
|
246
|
+
...options,
|
|
247
|
+
appId: options.appId,
|
|
248
|
+
defaults: app,
|
|
249
|
+
});
|
|
250
|
+
const roots = (app.roots ?? []).map((root) => {
|
|
251
|
+
const { safePath, absolutePath } = resolveInsideWorkspace(workspaceRoot, root.path);
|
|
252
|
+
const extensions = normalizeExtensions(root.extensions);
|
|
253
|
+
return {
|
|
254
|
+
name: root.name || rootNameFromPath(safePath),
|
|
255
|
+
path: safePath,
|
|
256
|
+
absolutePath,
|
|
257
|
+
kind: root.kind,
|
|
258
|
+
extensions,
|
|
259
|
+
hide: [...DEFAULT_HIDE_PATTERNS, ...asStringArray(root.hide)],
|
|
260
|
+
include: asStringArray(root.include),
|
|
261
|
+
};
|
|
262
|
+
});
|
|
263
|
+
return {
|
|
264
|
+
appId: options.appId,
|
|
265
|
+
mode,
|
|
266
|
+
manifestPath: loaded?.path ?? null,
|
|
267
|
+
workspaceRoot,
|
|
268
|
+
roots,
|
|
269
|
+
components: asStringArray(app.components),
|
|
270
|
+
hide: [...DEFAULT_HIDE_PATTERNS, ...asStringArray(app.hide)],
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
function matchesPatterns(filePath, patterns) {
|
|
274
|
+
return patterns.some((pattern) => minimatch(filePath, pattern, { dot: true, nocase: true }));
|
|
275
|
+
}
|
|
276
|
+
function contentTypeForExtension(extension) {
|
|
277
|
+
if (extension === ".md")
|
|
278
|
+
return "text/markdown";
|
|
279
|
+
if (extension === ".mdx")
|
|
280
|
+
return "text/mdx";
|
|
281
|
+
if (extension === ".json")
|
|
282
|
+
return "application/json";
|
|
283
|
+
if (extension === ".txt")
|
|
284
|
+
return "text/plain";
|
|
285
|
+
return "application/octet-stream";
|
|
286
|
+
}
|
|
287
|
+
function hashContent(content) {
|
|
288
|
+
return crypto.createHash("sha256").update(content).digest("hex");
|
|
289
|
+
}
|
|
290
|
+
const writeLocks = new Map();
|
|
291
|
+
async function withWriteLock(absolutePath, fn) {
|
|
292
|
+
const previous = writeLocks.get(absolutePath) ?? Promise.resolve();
|
|
293
|
+
let release;
|
|
294
|
+
const next = new Promise((resolve) => {
|
|
295
|
+
release = resolve;
|
|
296
|
+
});
|
|
297
|
+
const current = previous.catch(() => { }).then(() => next);
|
|
298
|
+
writeLocks.set(absolutePath, current);
|
|
299
|
+
await previous.catch(() => { });
|
|
300
|
+
try {
|
|
301
|
+
return await fn();
|
|
302
|
+
}
|
|
303
|
+
finally {
|
|
304
|
+
release();
|
|
305
|
+
if (writeLocks.get(absolutePath) === current) {
|
|
306
|
+
writeLocks.delete(absolutePath);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
async function fileMetaForPath(root, artifactPath, absolutePath, contentOverride) {
|
|
311
|
+
const content = contentOverride === undefined
|
|
312
|
+
? await fs.readFile(absolutePath, "utf8")
|
|
313
|
+
: contentOverride;
|
|
314
|
+
const stat = await fs.stat(absolutePath);
|
|
315
|
+
const extension = extensionOf(artifactPath);
|
|
316
|
+
return {
|
|
317
|
+
path: artifactPath,
|
|
318
|
+
rootName: root.name,
|
|
319
|
+
rootPath: root.path,
|
|
320
|
+
kind: root.kind,
|
|
321
|
+
extension,
|
|
322
|
+
contentType: contentTypeForExtension(extension),
|
|
323
|
+
sizeBytes: Buffer.byteLength(content, "utf8"),
|
|
324
|
+
hash: hashContent(content),
|
|
325
|
+
createdAt: stat.birthtime.toISOString(),
|
|
326
|
+
updatedAt: stat.mtime.toISOString(),
|
|
327
|
+
mtimeMs: stat.mtimeMs,
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
function rootAllowsPath(root, artifactPath) {
|
|
331
|
+
const extension = extensionOf(artifactPath);
|
|
332
|
+
if (root.extensions.length > 0 && !root.extensions.includes(extension)) {
|
|
333
|
+
return false;
|
|
334
|
+
}
|
|
335
|
+
if (matchesPatterns(artifactPath, root.hide))
|
|
336
|
+
return false;
|
|
337
|
+
if (root.include.length === 0)
|
|
338
|
+
return true;
|
|
339
|
+
return matchesPatterns(artifactPath, root.include);
|
|
340
|
+
}
|
|
341
|
+
async function walkRoot(root, directory = root.absolutePath) {
|
|
342
|
+
let entries;
|
|
343
|
+
try {
|
|
344
|
+
entries = await fs.readdir(directory, { withFileTypes: true });
|
|
345
|
+
}
|
|
346
|
+
catch (error) {
|
|
347
|
+
if (errorCode(error) === "ENOENT") {
|
|
348
|
+
return [];
|
|
349
|
+
}
|
|
350
|
+
throw error;
|
|
351
|
+
}
|
|
352
|
+
const files = [];
|
|
353
|
+
for (const entry of entries) {
|
|
354
|
+
const absolutePath = path.join(directory, entry.name);
|
|
355
|
+
const relativeToRoot = normalizeSlash(path.relative(root.absolutePath, absolutePath));
|
|
356
|
+
const artifactPath = normalizeSlash(path.posix.join(root.path, relativeToRoot));
|
|
357
|
+
if (matchesPatterns(artifactPath, root.hide))
|
|
358
|
+
continue;
|
|
359
|
+
if (entry.isDirectory()) {
|
|
360
|
+
files.push(...(await walkRoot(root, absolutePath)));
|
|
361
|
+
continue;
|
|
362
|
+
}
|
|
363
|
+
if (!entry.isFile() || !rootAllowsPath(root, artifactPath))
|
|
364
|
+
continue;
|
|
365
|
+
files.push(await fileMetaForPath(root, artifactPath, absolutePath));
|
|
366
|
+
}
|
|
367
|
+
return files;
|
|
368
|
+
}
|
|
369
|
+
export async function listLocalArtifactFiles(options) {
|
|
370
|
+
const app = await getLocalArtifactApp(options);
|
|
371
|
+
if (app.mode !== "local-files")
|
|
372
|
+
return [];
|
|
373
|
+
const files = (await Promise.all(app.roots.map((root) => walkRoot(root))))
|
|
374
|
+
.flat()
|
|
375
|
+
.filter((file) => !matchesPatterns(file.path, app.hide));
|
|
376
|
+
return files.sort((a, b) => a.path.localeCompare(b.path));
|
|
377
|
+
}
|
|
378
|
+
function rootForArtifactPath(app, artifactPath) {
|
|
379
|
+
const safePath = normalizeRelativePath(artifactPath);
|
|
380
|
+
const root = app.roots.find((candidate) => safePath === candidate.path || safePath.startsWith(`${candidate.path}/`));
|
|
381
|
+
if (!root) {
|
|
382
|
+
throw new Error(`Path "${artifactPath}" is not in a configured local root`);
|
|
383
|
+
}
|
|
384
|
+
if (!rootAllowsPath(root, safePath) || matchesPatterns(safePath, app.hide)) {
|
|
385
|
+
throw new Error(`Path "${artifactPath}" is not allowed for this app`);
|
|
386
|
+
}
|
|
387
|
+
return root;
|
|
388
|
+
}
|
|
389
|
+
async function resolveArtifactPath(app, artifactPath) {
|
|
390
|
+
const safePath = normalizeRelativePath(artifactPath);
|
|
391
|
+
const root = rootForArtifactPath(app, safePath);
|
|
392
|
+
const absolutePath = path.resolve(app.workspaceRoot, safePath);
|
|
393
|
+
const relative = path.relative(root.absolutePath, absolutePath);
|
|
394
|
+
if (relative.startsWith("..") ||
|
|
395
|
+
path.isAbsolute(relative) ||
|
|
396
|
+
relative === "") {
|
|
397
|
+
throw new Error(`Path "${artifactPath}" is outside its configured root`);
|
|
398
|
+
}
|
|
399
|
+
return { root, safePath, absolutePath };
|
|
400
|
+
}
|
|
401
|
+
async function assertNoSymlinkPath(root, absolutePath, options = {}) {
|
|
402
|
+
const relative = path.relative(root.absolutePath, absolutePath);
|
|
403
|
+
const segments = relative.split(path.sep).filter(Boolean);
|
|
404
|
+
let current = root.absolutePath;
|
|
405
|
+
const pathsToCheck = [
|
|
406
|
+
current,
|
|
407
|
+
...segments.map((segment) => {
|
|
408
|
+
current = path.join(current, segment);
|
|
409
|
+
return current;
|
|
410
|
+
}),
|
|
411
|
+
];
|
|
412
|
+
for (let index = 0; index < pathsToCheck.length; index += 1) {
|
|
413
|
+
const candidate = pathsToCheck[index];
|
|
414
|
+
try {
|
|
415
|
+
const stat = await fs.lstat(candidate);
|
|
416
|
+
if (stat.isSymbolicLink()) {
|
|
417
|
+
throw new Error(`Path "${candidate}" must not traverse a symlink`);
|
|
418
|
+
}
|
|
419
|
+
if (index < pathsToCheck.length - 1 && !stat.isDirectory()) {
|
|
420
|
+
throw new Error(`Path "${candidate}" is not a directory`);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
catch (error) {
|
|
424
|
+
if (errorCode(error) === "ENOENT" && options.allowMissingLeaf)
|
|
425
|
+
return;
|
|
426
|
+
throw error;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
export async function readLocalArtifactFile(options) {
|
|
431
|
+
const app = await getLocalArtifactApp(options);
|
|
432
|
+
if (app.mode !== "local-files")
|
|
433
|
+
return null;
|
|
434
|
+
const { root, safePath, absolutePath } = await resolveArtifactPath(app, options.path);
|
|
435
|
+
try {
|
|
436
|
+
await assertNoSymlinkPath(root, absolutePath);
|
|
437
|
+
const content = await fs.readFile(absolutePath, "utf8");
|
|
438
|
+
const meta = await fileMetaForPath(root, safePath, absolutePath, content);
|
|
439
|
+
return { ...meta, content };
|
|
440
|
+
}
|
|
441
|
+
catch (error) {
|
|
442
|
+
if (errorCode(error) === "ENOENT") {
|
|
443
|
+
return null;
|
|
444
|
+
}
|
|
445
|
+
throw error;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
export async function writeLocalArtifactFile(options) {
|
|
449
|
+
const app = await getLocalArtifactApp(options);
|
|
450
|
+
if (app.mode !== "local-files") {
|
|
451
|
+
throw new Error("Local file mode is not enabled");
|
|
452
|
+
}
|
|
453
|
+
const { root, safePath, absolutePath } = await resolveArtifactPath(app, options.path);
|
|
454
|
+
return withWriteLock(absolutePath, async () => {
|
|
455
|
+
const existing = await readLocalArtifactFile({
|
|
456
|
+
...options,
|
|
457
|
+
path: safePath,
|
|
458
|
+
});
|
|
459
|
+
if (options.ifNotExists && existing) {
|
|
460
|
+
throw new Error(`File "${safePath}" already exists`);
|
|
461
|
+
}
|
|
462
|
+
if (options.expectedHash &&
|
|
463
|
+
(!existing || existing.hash !== options.expectedHash)) {
|
|
464
|
+
throw new Error(`File "${safePath}" changed on disk. Reload before saving again.`);
|
|
465
|
+
}
|
|
466
|
+
await assertNoSymlinkPath(root, absolutePath, { allowMissingLeaf: true });
|
|
467
|
+
await fs.mkdir(path.dirname(absolutePath), { recursive: true });
|
|
468
|
+
const tempPath = path.join(path.dirname(absolutePath), `.${path.basename(absolutePath)}.${process.pid}.${crypto.randomUUID()}.tmp`);
|
|
469
|
+
await fs.writeFile(tempPath, options.content, "utf8");
|
|
470
|
+
await fs.rename(tempPath, absolutePath);
|
|
471
|
+
return fileMetaForPath(root, safePath, absolutePath, options.content);
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
export async function deleteLocalArtifactFile(options) {
|
|
475
|
+
const app = await getLocalArtifactApp(options);
|
|
476
|
+
if (app.mode !== "local-files") {
|
|
477
|
+
throw new Error("Local file mode is not enabled");
|
|
478
|
+
}
|
|
479
|
+
const { root, absolutePath } = await resolveArtifactPath(app, options.path);
|
|
480
|
+
try {
|
|
481
|
+
await assertNoSymlinkPath(root, absolutePath);
|
|
482
|
+
await fs.unlink(absolutePath);
|
|
483
|
+
return true;
|
|
484
|
+
}
|
|
485
|
+
catch (error) {
|
|
486
|
+
if (errorCode(error) === "ENOENT") {
|
|
487
|
+
return false;
|
|
488
|
+
}
|
|
489
|
+
throw error;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
export async function ensureLocalArtifactRoot(options) {
|
|
493
|
+
const app = await getLocalArtifactApp(options);
|
|
494
|
+
if (app.mode !== "local-files") {
|
|
495
|
+
throw new Error("Local file mode is not enabled");
|
|
496
|
+
}
|
|
497
|
+
const root = app.roots[0];
|
|
498
|
+
if (!root) {
|
|
499
|
+
throw new Error(`No local roots configured for app "${options.appId}"`);
|
|
500
|
+
}
|
|
501
|
+
await fs.mkdir(root.absolutePath, { recursive: true });
|
|
502
|
+
return root;
|
|
503
|
+
}
|
|
504
|
+
export function createTempWorkspaceDir(prefix = "agent-native-local-") {
|
|
505
|
+
return fsSync.mkdtempSync(path.join(os.tmpdir(), prefix));
|
|
506
|
+
}
|
|
507
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/local-artifacts/index.ts"],"names":[],"mappings":"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","sourcesContent":["import crypto from \"node:crypto\";\nimport fs from \"node:fs/promises\";\nimport fsSync from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { minimatch } from \"minimatch\";\n\nexport type AgentNativeDataMode = \"database\" | \"local-files\";\n\nexport interface AgentNativeManifestRoot {\n name?: string;\n path: string;\n kind?: string;\n extensions?: string[];\n include?: string[];\n hide?: string[];\n}\n\nexport interface AgentNativeManifestApp {\n mode?: AgentNativeDataMode;\n roots?: AgentNativeManifestRoot[];\n components?: string | string[];\n hide?: string[];\n}\n\nexport interface AgentNativeManifest {\n version?: number;\n mode?: AgentNativeDataMode;\n apps?: Record<string, AgentNativeManifestApp>;\n}\n\nexport interface LoadedAgentNativeManifest {\n path: string;\n rootDir: string;\n manifest: AgentNativeManifest;\n}\n\nexport interface LocalArtifactAppDefaults {\n mode?: AgentNativeDataMode;\n roots: AgentNativeManifestRoot[];\n hide?: string[];\n components?: string | string[];\n}\n\nexport interface LoadAgentNativeManifestOptions {\n cwd?: string;\n manifestPath?: string;\n optional?: boolean;\n}\n\nexport interface ResolveAgentNativeModeOptions extends LoadAgentNativeManifestOptions {\n appId?: string;\n defaults?: Pick<LocalArtifactAppDefaults, \"mode\">;\n}\n\nexport interface LocalArtifactOptions extends LoadAgentNativeManifestOptions {\n appId: string;\n defaults?: LocalArtifactAppDefaults;\n}\n\nexport interface LoadedLocalArtifactRoot {\n name: string;\n path: string;\n absolutePath: string;\n kind?: string;\n extensions: string[];\n hide: string[];\n include: string[];\n}\n\nexport interface LoadedLocalArtifactApp {\n appId: string;\n mode: AgentNativeDataMode;\n manifestPath: string | null;\n workspaceRoot: string;\n roots: LoadedLocalArtifactRoot[];\n components: string[];\n hide: string[];\n}\n\nexport interface LocalArtifactFileMeta {\n path: string;\n rootName: string;\n rootPath: string;\n kind?: string;\n extension: string;\n contentType: string;\n sizeBytes: number;\n hash: string;\n createdAt: string;\n updatedAt: string;\n mtimeMs: number;\n}\n\nexport interface LocalArtifactFile extends LocalArtifactFileMeta {\n content: string;\n}\n\nexport interface WriteLocalArtifactFileOptions extends LocalArtifactOptions {\n content: string;\n expectedHash?: string | null;\n ifNotExists?: boolean;\n}\n\nconst MANIFEST_FILE = \"agent-native.json\";\nconst ENV_MODE_NAMES = [\"AGENT_NATIVE_MODE\", \"AGENT_NATIVE_DATA_MODE\"];\nconst ENV_MANIFEST_NAMES = [\n \"AGENT_NATIVE_MANIFEST\",\n \"AGENT_NATIVE_MANIFEST_PATH\",\n];\nconst ALLOW_PRODUCTION_LOCAL_FILES_ENV =\n \"AGENT_NATIVE_ALLOW_LOCAL_FILES_IN_PRODUCTION\";\nconst DEFAULT_HIDE_PATTERNS = [\n \"**/.git/**\",\n \"**/.agent-native/**\",\n \"**/.next/**\",\n \"**/.nuxt/**\",\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/build/**\",\n];\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction errorCode(error: unknown): string | undefined {\n return isRecord(error) && typeof error.code === \"string\"\n ? error.code\n : undefined;\n}\n\nfunction asStringArray(value: unknown): string[] {\n if (typeof value === \"string\" && value.trim()) return [value.trim()];\n if (!Array.isArray(value)) return [];\n return value.filter((item): item is string => typeof item === \"string\");\n}\n\nfunction normalizeMode(value: unknown): AgentNativeDataMode | undefined {\n if (value === \"database\" || value === \"local-files\") return value;\n return undefined;\n}\n\nfunction normalizeSlash(filePath: string): string {\n return filePath.replace(/\\\\/g, \"/\");\n}\n\nfunction normalizeRelativePath(filePath: string, label = \"path\"): string {\n if (!filePath || typeof filePath !== \"string\") {\n throw new Error(`${label} is required`);\n }\n if (filePath.includes(\"\\0\")) {\n throw new Error(`${label} must not contain null bytes`);\n }\n if (path.isAbsolute(filePath)) {\n throw new Error(`${label} must be relative`);\n }\n const normalized = normalizeSlash(\n path.posix.normalize(normalizeSlash(filePath)),\n );\n if (\n !normalized ||\n normalized === \".\" ||\n normalized.startsWith(\"../\") ||\n normalized === \"..\" ||\n normalized.split(\"/\").some((part) => !part || part === \".\" || part === \"..\")\n ) {\n throw new Error(`${label} must be a safe relative path`);\n }\n return normalized;\n}\n\nfunction extensionOf(filePath: string): string {\n return path.posix.extname(filePath).toLowerCase();\n}\n\nfunction normalizeExtensions(value: unknown): string[] {\n const extensions = asStringArray(value)\n .map((ext) => ext.trim().toLowerCase())\n .filter(Boolean)\n .map((ext) => (ext.startsWith(\".\") ? ext : `.${ext}`));\n return [...new Set(extensions)];\n}\n\nfunction rootNameFromPath(rootPath: string): string {\n return (\n rootPath\n .split(\"/\")\n .filter(Boolean)\n .at(-1)\n ?.replace(/[-_]+/g, \" \")\n .replace(/\\b\\w/g, (char) => char.toUpperCase()) || rootPath\n );\n}\n\nfunction normalizeManifestRoot(value: unknown): AgentNativeManifestRoot | null {\n if (typeof value === \"string\") return { path: value };\n if (!isRecord(value) || typeof value.path !== \"string\") return null;\n return {\n name: typeof value.name === \"string\" ? value.name : undefined,\n path: value.path,\n kind: typeof value.kind === \"string\" ? value.kind : undefined,\n extensions: normalizeExtensions(value.extensions),\n include: asStringArray(value.include),\n hide: asStringArray(value.hide),\n };\n}\n\nfunction normalizeManifestApp(value: unknown): AgentNativeManifestApp {\n if (Array.isArray(value)) {\n return {\n roots: value\n .map(normalizeManifestRoot)\n .filter((root): root is AgentNativeManifestRoot => !!root),\n };\n }\n if (!isRecord(value)) return {};\n const roots = Array.isArray(value.roots)\n ? value.roots\n .map(normalizeManifestRoot)\n .filter((root): root is AgentNativeManifestRoot => !!root)\n : [];\n return {\n mode: normalizeMode(value.mode),\n roots,\n components:\n typeof value.components === \"string\" || Array.isArray(value.components)\n ? asStringArray(value.components)\n : undefined,\n hide: asStringArray(value.hide),\n };\n}\n\nfunction normalizeManifest(value: unknown): AgentNativeManifest {\n const record = isRecord(value) ? value : {};\n const appsRecord = isRecord(record.apps) ? record.apps : {};\n const apps: Record<string, AgentNativeManifestApp> = {};\n for (const [appId, appValue] of Object.entries(appsRecord)) {\n apps[appId] = normalizeManifestApp(appValue);\n }\n return {\n version:\n typeof record.version === \"number\" && Number.isFinite(record.version)\n ? record.version\n : undefined,\n mode: normalizeMode(record.mode),\n apps,\n };\n}\n\nfunction firstEnvValue(names: string[]): string | undefined {\n for (const name of names) {\n const value = process.env[name]?.trim();\n if (value) return value;\n }\n return undefined;\n}\n\nfunction envMode(): AgentNativeDataMode | undefined {\n return normalizeMode(firstEnvValue(ENV_MODE_NAMES));\n}\n\nfunction envFlag(name: string): boolean {\n const value = process.env[name]?.trim().toLowerCase();\n return value === \"1\" || value === \"true\" || value === \"yes\" || value === \"on\";\n}\n\nfunction assertLocalFilesRuntimeAllowed(mode: AgentNativeDataMode) {\n if (mode !== \"local-files\") return;\n if (process.env.NODE_ENV !== \"production\") return;\n if (envFlag(ALLOW_PRODUCTION_LOCAL_FILES_ENV)) return;\n throw new Error(\n `Local file mode is only enabled for local development runtimes. Set ${ALLOW_PRODUCTION_LOCAL_FILES_ENV}=true only for a trusted single-tenant local file bridge.`,\n );\n}\n\nfunction envManifestPath(): string | undefined {\n return firstEnvValue(ENV_MANIFEST_NAMES);\n}\n\nexport function findAgentNativeManifest(\n startDir = process.cwd(),\n): string | null {\n let current = path.resolve(startDir);\n for (;;) {\n const candidate = path.join(current, MANIFEST_FILE);\n if (fsSync.existsSync(candidate)) return candidate;\n const parent = path.dirname(current);\n if (parent === current) return null;\n current = parent;\n }\n}\n\nexport async function loadAgentNativeManifest(\n options: LoadAgentNativeManifestOptions = {},\n): Promise<LoadedAgentNativeManifest | null> {\n const manifestPath =\n options.manifestPath ??\n envManifestPath() ??\n findAgentNativeManifest(options.cwd ?? process.cwd());\n\n if (!manifestPath) {\n if (options.optional) return null;\n throw new Error(`Could not find ${MANIFEST_FILE}`);\n }\n\n const resolvedPath = path.resolve(options.cwd ?? process.cwd(), manifestPath);\n try {\n const raw = await fs.readFile(resolvedPath, \"utf8\");\n const parsed = JSON.parse(raw) as unknown;\n return {\n path: resolvedPath,\n rootDir: path.dirname(resolvedPath),\n manifest: normalizeManifest(parsed),\n };\n } catch (error) {\n if (options.optional && errorCode(error) === \"ENOENT\") {\n return null;\n }\n throw error;\n }\n}\n\nexport async function resolveAgentNativeDataMode(\n options: ResolveAgentNativeModeOptions = {},\n): Promise<AgentNativeDataMode> {\n const explicitMode = envMode();\n if (explicitMode) {\n assertLocalFilesRuntimeAllowed(explicitMode);\n return explicitMode;\n }\n\n const loaded = await loadAgentNativeManifest({ ...options, optional: true });\n const appMode = options.appId\n ? loaded?.manifest.apps?.[options.appId]?.mode\n : undefined;\n const mode =\n appMode ?? loaded?.manifest.mode ?? options.defaults?.mode ?? \"database\";\n assertLocalFilesRuntimeAllowed(mode);\n return mode;\n}\n\nexport async function isAgentNativeLocalFileMode(\n options: ResolveAgentNativeModeOptions = {},\n): Promise<boolean> {\n return (await resolveAgentNativeDataMode(options)) === \"local-files\";\n}\n\nfunction mergeAppConfig(\n manifestApp: AgentNativeManifestApp | undefined,\n defaults: LocalArtifactAppDefaults | undefined,\n): AgentNativeManifestApp {\n return {\n mode: manifestApp?.mode ?? defaults?.mode,\n roots:\n manifestApp?.roots && manifestApp.roots.length > 0\n ? manifestApp.roots\n : (defaults?.roots ?? []),\n components: manifestApp?.components ?? defaults?.components,\n hide: [...(defaults?.hide ?? []), ...(manifestApp?.hide ?? [])],\n };\n}\n\nfunction resolveInsideWorkspace(workspaceRoot: string, relativePath: string) {\n const safePath = normalizeRelativePath(relativePath);\n const absolutePath = path.resolve(workspaceRoot, safePath);\n const relative = path.relative(workspaceRoot, absolutePath);\n if (\n relative === \"\" ||\n relative.startsWith(\"..\") ||\n path.isAbsolute(relative)\n ) {\n throw new Error(`Path \"${relativePath}\" is outside the workspace`);\n }\n return { safePath, absolutePath };\n}\n\nexport async function getLocalArtifactApp(\n options: LocalArtifactOptions,\n): Promise<LoadedLocalArtifactApp> {\n const loaded = await loadAgentNativeManifest({ ...options, optional: true });\n const workspaceRoot =\n loaded?.rootDir ?? path.resolve(options.cwd ?? process.cwd());\n const manifestApp = loaded?.manifest.apps?.[options.appId];\n const app = mergeAppConfig(manifestApp, options.defaults);\n const mode = await resolveAgentNativeDataMode({\n ...options,\n appId: options.appId,\n defaults: app,\n });\n\n const roots = (app.roots ?? []).map((root) => {\n const { safePath, absolutePath } = resolveInsideWorkspace(\n workspaceRoot,\n root.path,\n );\n const extensions = normalizeExtensions(root.extensions);\n return {\n name: root.name || rootNameFromPath(safePath),\n path: safePath,\n absolutePath,\n kind: root.kind,\n extensions,\n hide: [...DEFAULT_HIDE_PATTERNS, ...asStringArray(root.hide)],\n include: asStringArray(root.include),\n };\n });\n\n return {\n appId: options.appId,\n mode,\n manifestPath: loaded?.path ?? null,\n workspaceRoot,\n roots,\n components: asStringArray(app.components),\n hide: [...DEFAULT_HIDE_PATTERNS, ...asStringArray(app.hide)],\n };\n}\n\nfunction matchesPatterns(filePath: string, patterns: string[]) {\n return patterns.some((pattern) =>\n minimatch(filePath, pattern, { dot: true, nocase: true }),\n );\n}\n\nfunction contentTypeForExtension(extension: string): string {\n if (extension === \".md\") return \"text/markdown\";\n if (extension === \".mdx\") return \"text/mdx\";\n if (extension === \".json\") return \"application/json\";\n if (extension === \".txt\") return \"text/plain\";\n return \"application/octet-stream\";\n}\n\nfunction hashContent(content: string): string {\n return crypto.createHash(\"sha256\").update(content).digest(\"hex\");\n}\n\nconst writeLocks = new Map<string, Promise<void>>();\n\nasync function withWriteLock<T>(\n absolutePath: string,\n fn: () => Promise<T>,\n): Promise<T> {\n const previous = writeLocks.get(absolutePath) ?? Promise.resolve();\n let release!: () => void;\n const next = new Promise<void>((resolve) => {\n release = resolve;\n });\n const current = previous.catch(() => {}).then(() => next);\n writeLocks.set(absolutePath, current);\n await previous.catch(() => {});\n try {\n return await fn();\n } finally {\n release();\n if (writeLocks.get(absolutePath) === current) {\n writeLocks.delete(absolutePath);\n }\n }\n}\n\nasync function fileMetaForPath(\n root: LoadedLocalArtifactRoot,\n artifactPath: string,\n absolutePath: string,\n contentOverride?: string,\n): Promise<LocalArtifactFileMeta> {\n const content =\n contentOverride === undefined\n ? await fs.readFile(absolutePath, \"utf8\")\n : contentOverride;\n const stat = await fs.stat(absolutePath);\n const extension = extensionOf(artifactPath);\n return {\n path: artifactPath,\n rootName: root.name,\n rootPath: root.path,\n kind: root.kind,\n extension,\n contentType: contentTypeForExtension(extension),\n sizeBytes: Buffer.byteLength(content, \"utf8\"),\n hash: hashContent(content),\n createdAt: stat.birthtime.toISOString(),\n updatedAt: stat.mtime.toISOString(),\n mtimeMs: stat.mtimeMs,\n };\n}\n\nfunction rootAllowsPath(root: LoadedLocalArtifactRoot, artifactPath: string) {\n const extension = extensionOf(artifactPath);\n if (root.extensions.length > 0 && !root.extensions.includes(extension)) {\n return false;\n }\n if (matchesPatterns(artifactPath, root.hide)) return false;\n if (root.include.length === 0) return true;\n return matchesPatterns(artifactPath, root.include);\n}\n\nasync function walkRoot(\n root: LoadedLocalArtifactRoot,\n directory = root.absolutePath,\n): Promise<LocalArtifactFileMeta[]> {\n let entries: fsSync.Dirent[];\n try {\n entries = await fs.readdir(directory, { withFileTypes: true });\n } catch (error) {\n if (errorCode(error) === \"ENOENT\") {\n return [];\n }\n throw error;\n }\n\n const files: LocalArtifactFileMeta[] = [];\n for (const entry of entries) {\n const absolutePath = path.join(directory, entry.name);\n const relativeToRoot = normalizeSlash(\n path.relative(root.absolutePath, absolutePath),\n );\n const artifactPath = normalizeSlash(\n path.posix.join(root.path, relativeToRoot),\n );\n if (matchesPatterns(artifactPath, root.hide)) continue;\n\n if (entry.isDirectory()) {\n files.push(...(await walkRoot(root, absolutePath)));\n continue;\n }\n if (!entry.isFile() || !rootAllowsPath(root, artifactPath)) continue;\n files.push(await fileMetaForPath(root, artifactPath, absolutePath));\n }\n return files;\n}\n\nexport async function listLocalArtifactFiles(\n options: LocalArtifactOptions,\n): Promise<LocalArtifactFileMeta[]> {\n const app = await getLocalArtifactApp(options);\n if (app.mode !== \"local-files\") return [];\n\n const files = (await Promise.all(app.roots.map((root) => walkRoot(root))))\n .flat()\n .filter((file) => !matchesPatterns(file.path, app.hide));\n\n return files.sort((a, b) => a.path.localeCompare(b.path));\n}\n\nfunction rootForArtifactPath(\n app: LoadedLocalArtifactApp,\n artifactPath: string,\n): LoadedLocalArtifactRoot {\n const safePath = normalizeRelativePath(artifactPath);\n const root = app.roots.find(\n (candidate) =>\n safePath === candidate.path || safePath.startsWith(`${candidate.path}/`),\n );\n if (!root) {\n throw new Error(`Path \"${artifactPath}\" is not in a configured local root`);\n }\n if (!rootAllowsPath(root, safePath) || matchesPatterns(safePath, app.hide)) {\n throw new Error(`Path \"${artifactPath}\" is not allowed for this app`);\n }\n return root;\n}\n\nasync function resolveArtifactPath(\n app: LoadedLocalArtifactApp,\n artifactPath: string,\n): Promise<{\n root: LoadedLocalArtifactRoot;\n safePath: string;\n absolutePath: string;\n}> {\n const safePath = normalizeRelativePath(artifactPath);\n const root = rootForArtifactPath(app, safePath);\n const absolutePath = path.resolve(app.workspaceRoot, safePath);\n const relative = path.relative(root.absolutePath, absolutePath);\n if (\n relative.startsWith(\"..\") ||\n path.isAbsolute(relative) ||\n relative === \"\"\n ) {\n throw new Error(`Path \"${artifactPath}\" is outside its configured root`);\n }\n return { root, safePath, absolutePath };\n}\n\nasync function assertNoSymlinkPath(\n root: LoadedLocalArtifactRoot,\n absolutePath: string,\n options: { allowMissingLeaf?: boolean } = {},\n) {\n const relative = path.relative(root.absolutePath, absolutePath);\n const segments = relative.split(path.sep).filter(Boolean);\n let current = root.absolutePath;\n const pathsToCheck = [\n current,\n ...segments.map((segment) => {\n current = path.join(current, segment);\n return current;\n }),\n ];\n\n for (let index = 0; index < pathsToCheck.length; index += 1) {\n const candidate = pathsToCheck[index]!;\n try {\n const stat = await fs.lstat(candidate);\n if (stat.isSymbolicLink()) {\n throw new Error(`Path \"${candidate}\" must not traverse a symlink`);\n }\n if (index < pathsToCheck.length - 1 && !stat.isDirectory()) {\n throw new Error(`Path \"${candidate}\" is not a directory`);\n }\n } catch (error) {\n if (errorCode(error) === \"ENOENT\" && options.allowMissingLeaf) return;\n throw error;\n }\n }\n}\n\nexport async function readLocalArtifactFile(\n options: LocalArtifactOptions & { path: string },\n): Promise<LocalArtifactFile | null> {\n const app = await getLocalArtifactApp(options);\n if (app.mode !== \"local-files\") return null;\n const { root, safePath, absolutePath } = await resolveArtifactPath(\n app,\n options.path,\n );\n try {\n await assertNoSymlinkPath(root, absolutePath);\n const content = await fs.readFile(absolutePath, \"utf8\");\n const meta = await fileMetaForPath(root, safePath, absolutePath, content);\n return { ...meta, content };\n } catch (error) {\n if (errorCode(error) === \"ENOENT\") {\n return null;\n }\n throw error;\n }\n}\n\nexport async function writeLocalArtifactFile(\n options: WriteLocalArtifactFileOptions & { path: string },\n): Promise<LocalArtifactFileMeta> {\n const app = await getLocalArtifactApp(options);\n if (app.mode !== \"local-files\") {\n throw new Error(\"Local file mode is not enabled\");\n }\n const { root, safePath, absolutePath } = await resolveArtifactPath(\n app,\n options.path,\n );\n return withWriteLock(absolutePath, async () => {\n const existing = await readLocalArtifactFile({\n ...options,\n path: safePath,\n });\n if (options.ifNotExists && existing) {\n throw new Error(`File \"${safePath}\" already exists`);\n }\n if (\n options.expectedHash &&\n (!existing || existing.hash !== options.expectedHash)\n ) {\n throw new Error(\n `File \"${safePath}\" changed on disk. Reload before saving again.`,\n );\n }\n\n await assertNoSymlinkPath(root, absolutePath, { allowMissingLeaf: true });\n await fs.mkdir(path.dirname(absolutePath), { recursive: true });\n const tempPath = path.join(\n path.dirname(absolutePath),\n `.${path.basename(absolutePath)}.${process.pid}.${crypto.randomUUID()}.tmp`,\n );\n await fs.writeFile(tempPath, options.content, \"utf8\");\n await fs.rename(tempPath, absolutePath);\n return fileMetaForPath(root, safePath, absolutePath, options.content);\n });\n}\n\nexport async function deleteLocalArtifactFile(\n options: LocalArtifactOptions & { path: string },\n): Promise<boolean> {\n const app = await getLocalArtifactApp(options);\n if (app.mode !== \"local-files\") {\n throw new Error(\"Local file mode is not enabled\");\n }\n const { root, absolutePath } = await resolveArtifactPath(app, options.path);\n try {\n await assertNoSymlinkPath(root, absolutePath);\n await fs.unlink(absolutePath);\n return true;\n } catch (error) {\n if (errorCode(error) === \"ENOENT\") {\n return false;\n }\n throw error;\n }\n}\n\nexport async function ensureLocalArtifactRoot(\n options: LocalArtifactOptions,\n): Promise<LoadedLocalArtifactRoot> {\n const app = await getLocalArtifactApp(options);\n if (app.mode !== \"local-files\") {\n throw new Error(\"Local file mode is not enabled\");\n }\n const root = app.roots[0];\n if (!root) {\n throw new Error(`No local roots configured for app \"${options.appId}\"`);\n }\n await fs.mkdir(root.absolutePath, { recursive: true });\n return root;\n}\n\nexport function createTempWorkspaceDir(prefix = \"agent-native-local-\"): string {\n return fsSync.mkdtempSync(path.join(os.tmpdir(), prefix));\n}\n"]}
|
|
@@ -70,7 +70,7 @@ export async function resolveKeyReferences(text, scope, scopeId) {
|
|
|
70
70
|
});
|
|
71
71
|
}
|
|
72
72
|
if (!result) {
|
|
73
|
-
throw new Error(`Referenced key "${name}" is not defined for scope "${scope}". Create it in Settings or via the secrets API before using this automation.`);
|
|
73
|
+
throw new Error(`Referenced key "${name}" is not defined for scope "${scope}". Create it in the Dispatch Vault, app Settings, or via the secrets API before using this automation.`);
|
|
74
74
|
}
|
|
75
75
|
resolutions.set(name, result.value);
|
|
76
76
|
usedKeys.push(name);
|
|
@@ -112,7 +112,7 @@ export async function resolveKeyReferencesWithRequestScopes(text, userScopeId) {
|
|
|
112
112
|
continue;
|
|
113
113
|
const result = await readRequestScopedSecret(name, userScopeId);
|
|
114
114
|
if (!result) {
|
|
115
|
-
throw new Error(`Referenced key "${name}" is not defined for this user or active workspace. Create it in
|
|
115
|
+
throw new Error(`Referenced key "${name}" is not defined for this user or active workspace. Create it in the Dispatch Vault or app Settings before using this extension.`);
|
|
116
116
|
}
|
|
117
117
|
resolutions.set(name, result.value);
|
|
118
118
|
usedKeys.push(name);
|