veryfront 0.1.216 → 0.1.217
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/esm/cli/commands/generate/integration-generator-helpers.d.ts +35 -0
- package/esm/cli/commands/generate/integration-generator-helpers.d.ts.map +1 -0
- package/esm/cli/commands/generate/integration-generator-helpers.js +123 -0
- package/esm/cli/commands/generate/integration-generator.d.ts +1 -2
- package/esm/cli/commands/generate/integration-generator.d.ts.map +1 -1
- package/esm/cli/commands/generate/integration-generator.js +1 -123
- package/esm/cli/commands/knowledge/command-helpers.d.ts +48 -0
- package/esm/cli/commands/knowledge/command-helpers.d.ts.map +1 -0
- package/esm/cli/commands/knowledge/command-helpers.js +216 -0
- package/esm/cli/commands/knowledge/command.d.ts +11 -16
- package/esm/cli/commands/knowledge/command.d.ts.map +1 -1
- package/esm/cli/commands/knowledge/command.js +25 -212
- package/esm/cli/mcp/remote-file-tool-helpers.d.ts +5 -0
- package/esm/cli/mcp/remote-file-tool-helpers.d.ts.map +1 -0
- package/esm/cli/mcp/remote-file-tool-helpers.js +22 -0
- package/esm/cli/mcp/remote-file-tools.d.ts.map +1 -1
- package/esm/cli/mcp/remote-file-tools.js +1 -22
- package/esm/cli/templates/integration-loader-helpers.d.ts +8 -0
- package/esm/cli/templates/integration-loader-helpers.d.ts.map +1 -0
- package/esm/cli/templates/integration-loader-helpers.js +29 -0
- package/esm/cli/templates/integration-loader.d.ts.map +1 -1
- package/esm/cli/templates/integration-loader.js +5 -21
- package/esm/cli/templates/manifest.d.ts +1 -0
- package/esm/cli/templates/manifest.js +2 -1
- package/esm/deno.js +2 -2
- package/esm/src/agent/runtime/index.d.ts.map +1 -1
- package/esm/src/agent/runtime/index.js +48 -90
- package/esm/src/chat/ag-ui-helpers.d.ts +17 -0
- package/esm/src/chat/ag-ui-helpers.d.ts.map +1 -0
- package/esm/src/chat/ag-ui-helpers.js +111 -0
- package/esm/src/chat/ag-ui.d.ts.map +1 -1
- package/esm/src/chat/ag-ui.js +1 -111
- package/esm/src/config/schemas/config.schema.d.ts +1 -0
- package/esm/src/config/schemas/config.schema.d.ts.map +1 -1
- package/esm/src/config/schemas/config.schema.js +11 -0
- package/esm/src/config/schemas/index.d.ts +11 -1
- package/esm/src/config/schemas/index.d.ts.map +1 -1
- package/esm/src/errors/error-registry-helpers.d.ts +6 -0
- package/esm/src/errors/error-registry-helpers.d.ts.map +1 -0
- package/esm/src/errors/error-registry-helpers.js +9 -0
- package/esm/src/errors/error-registry.d.ts.map +1 -1
- package/esm/src/errors/error-registry.js +4 -3
- package/esm/src/extensions/factory-loader.d.ts +29 -0
- package/esm/src/extensions/factory-loader.d.ts.map +1 -0
- package/esm/src/extensions/factory-loader.js +63 -0
- package/esm/src/extensions/index.d.ts +16 -0
- package/esm/src/extensions/index.d.ts.map +1 -1
- package/esm/src/extensions/index.js +16 -0
- package/esm/src/extensions/orchestrate.d.ts +54 -0
- package/esm/src/extensions/orchestrate.d.ts.map +1 -0
- package/esm/src/extensions/orchestrate.js +116 -0
- package/esm/src/html/styles-builder/plugin-loader.d.ts.map +1 -1
- package/esm/src/html/styles-builder/plugin-loader.js +23 -0
- package/esm/src/html/styles-builder/tailwind-plugin-allowlist.d.ts +29 -0
- package/esm/src/html/styles-builder/tailwind-plugin-allowlist.d.ts.map +1 -0
- package/esm/src/html/styles-builder/tailwind-plugin-allowlist.js +48 -0
- package/esm/src/modules/react-loader/ssr-module-loader/loader-helpers.d.ts +15 -0
- package/esm/src/modules/react-loader/ssr-module-loader/loader-helpers.d.ts.map +1 -0
- package/esm/src/modules/react-loader/ssr-module-loader/loader-helpers.js +22 -0
- package/esm/src/modules/react-loader/ssr-module-loader/loader.d.ts +0 -2
- package/esm/src/modules/react-loader/ssr-module-loader/loader.d.ts.map +1 -1
- package/esm/src/modules/react-loader/ssr-module-loader/loader.js +4 -24
- package/esm/src/platform/adapters/fs/veryfront/adapter-helpers.d.ts +19 -0
- package/esm/src/platform/adapters/fs/veryfront/adapter-helpers.d.ts.map +1 -0
- package/esm/src/platform/adapters/fs/veryfront/adapter-helpers.js +26 -0
- package/esm/src/platform/adapters/fs/veryfront/adapter.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/veryfront/adapter.js +4 -20
- package/esm/src/platform/adapters/fs/veryfront/read-operations-helpers.d.ts +1 -0
- package/esm/src/platform/adapters/fs/veryfront/read-operations-helpers.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/veryfront/read-operations-helpers.js +3 -0
- package/esm/src/platform/adapters/fs/veryfront/read-operations.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/veryfront/read-operations.js +4 -7
- package/esm/src/platform/adapters/fs/veryfront/websocket-manager-helpers.d.ts +28 -0
- package/esm/src/platform/adapters/fs/veryfront/websocket-manager-helpers.d.ts.map +1 -0
- package/esm/src/platform/adapters/fs/veryfront/websocket-manager-helpers.js +41 -0
- package/esm/src/platform/adapters/fs/veryfront/websocket-manager.d.ts +1 -4
- package/esm/src/platform/adapters/fs/veryfront/websocket-manager.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/veryfront/websocket-manager.js +7 -40
- package/esm/src/provider/runtime-loader/tool-input-status.d.ts +17 -0
- package/esm/src/provider/runtime-loader/tool-input-status.d.ts.map +1 -0
- package/esm/src/provider/runtime-loader/tool-input-status.js +155 -0
- package/esm/src/provider/runtime-loader.d.ts +2 -3
- package/esm/src/provider/runtime-loader.d.ts.map +1 -1
- package/esm/src/provider/runtime-loader.js +2 -155
- package/esm/src/rendering/orchestrator/pipeline-helpers.d.ts +8 -0
- package/esm/src/rendering/orchestrator/pipeline-helpers.d.ts.map +1 -0
- package/esm/src/rendering/orchestrator/pipeline-helpers.js +20 -0
- package/esm/src/rendering/orchestrator/pipeline.d.ts +0 -3
- package/esm/src/rendering/orchestrator/pipeline.d.ts.map +1 -1
- package/esm/src/rendering/orchestrator/pipeline.js +4 -22
- package/esm/src/routing/api/module-loader/loader-helpers.d.ts +10 -0
- package/esm/src/routing/api/module-loader/loader-helpers.d.ts.map +1 -0
- package/esm/src/routing/api/module-loader/loader-helpers.js +62 -0
- package/esm/src/routing/api/module-loader/loader.d.ts +1 -1
- package/esm/src/routing/api/module-loader/loader.d.ts.map +1 -1
- package/esm/src/routing/api/module-loader/loader.js +2 -60
- package/esm/src/server/bootstrap.d.ts +22 -2
- package/esm/src/server/bootstrap.d.ts.map +1 -1
- package/esm/src/server/bootstrap.js +67 -5
- package/esm/src/server/dev-ui/manifest.d.ts +2 -0
- package/esm/src/server/dev-ui/manifest.js +3 -1
- package/esm/src/server/handlers/request/api/project-discovery.d.ts.map +1 -1
- package/esm/src/server/handlers/request/api/project-discovery.js +14 -8
- package/esm/src/server/production-server.js +1 -1
- package/esm/src/server/services/rsc/endpoints/rsc-bundles.generated.d.ts.map +1 -1
- package/esm/src/server/services/rsc/endpoints/rsc-bundles.generated.js +2 -2
- package/esm/src/studio/bridge/bridge-bundle.generated.d.ts.map +1 -1
- package/esm/src/studio/bridge/bridge-bundle.generated.js +1 -1
- package/esm/src/tool/index.d.ts +1 -1
- package/esm/src/tool/index.d.ts.map +1 -1
- package/esm/src/tool/types.d.ts +20 -0
- package/esm/src/tool/types.d.ts.map +1 -1
- package/esm/src/utils/version-constant.d.ts +1 -1
- package/esm/src/utils/version-constant.js +1 -1
- package/package.json +1 -1
- package/src/cli/commands/generate/integration-generator-helpers.ts +185 -0
- package/src/cli/commands/generate/integration-generator.ts +12 -168
- package/src/cli/commands/knowledge/command-helpers.ts +295 -0
- package/src/cli/commands/knowledge/command.ts +33 -259
- package/src/cli/mcp/remote-file-tool-helpers.ts +27 -0
- package/src/cli/mcp/remote-file-tools.ts +6 -28
- package/src/cli/templates/integration-loader-helpers.ts +49 -0
- package/src/cli/templates/integration-loader.ts +10 -28
- package/src/cli/templates/manifest.js +2 -1
- package/src/deno.js +2 -2
- package/src/src/agent/runtime/index.ts +77 -94
- package/src/src/chat/ag-ui-helpers.ts +139 -0
- package/src/src/chat/ag-ui.ts +11 -139
- package/src/src/config/schemas/config.schema.ts +11 -0
- package/src/src/config/schemas/index.ts +15 -1
- package/src/src/errors/error-registry-helpers.ts +23 -0
- package/src/src/errors/error-registry.ts +8 -3
- package/src/src/extensions/factory-loader.ts +76 -0
- package/src/src/extensions/index.ts +20 -0
- package/src/src/extensions/orchestrate.ts +184 -0
- package/src/src/html/styles-builder/plugin-loader.ts +32 -0
- package/src/src/html/styles-builder/tailwind-plugin-allowlist.ts +51 -0
- package/src/src/modules/react-loader/ssr-module-loader/loader-helpers.ts +37 -0
- package/src/src/modules/react-loader/ssr-module-loader/loader.ts +8 -39
- package/src/src/platform/adapters/fs/veryfront/adapter-helpers.ts +43 -0
- package/src/src/platform/adapters/fs/veryfront/adapter.ts +8 -22
- package/src/src/platform/adapters/fs/veryfront/read-operations-helpers.ts +4 -0
- package/src/src/platform/adapters/fs/veryfront/read-operations.ts +4 -7
- package/src/src/platform/adapters/fs/veryfront/websocket-manager-helpers.ts +73 -0
- package/src/src/platform/adapters/fs/veryfront/websocket-manager.ts +29 -44
- package/src/src/provider/runtime-loader/tool-input-status.ts +210 -0
- package/src/src/provider/runtime-loader.ts +6 -203
- package/src/src/rendering/orchestrator/pipeline-helpers.ts +35 -0
- package/src/src/rendering/orchestrator/pipeline.ts +8 -35
- package/src/src/routing/api/module-loader/loader-helpers.ts +68 -0
- package/src/src/routing/api/module-loader/loader.ts +8 -65
- package/src/src/server/bootstrap.ts +88 -7
- package/src/src/server/dev-ui/manifest.js +3 -1
- package/src/src/server/handlers/request/api/project-discovery.ts +19 -8
- package/src/src/server/production-server.ts +1 -1
- package/src/src/server/services/rsc/endpoints/rsc-bundles.generated.ts +2 -2
- package/src/src/studio/bridge/bridge-bundle.generated.ts +1 -1
- package/src/src/tool/index.ts +1 -0
- package/src/src/tool/types.ts +21 -0
- package/src/src/utils/version-constant.ts +1 -1
|
@@ -2,7 +2,7 @@ import * as dntShim from "../../../_dnt.shims.js";
|
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
type SafeParseResult<T> = { success: true; data: T } | { success: false; error: z.ZodError };
|
|
4
4
|
import { type CommandResult, createFileSystem, getEnv, runCommand } from "../../../src/platform/index.js";
|
|
5
|
-
import { basename
|
|
5
|
+
import { basename } from "../../../src/platform/compat/path/index.js";
|
|
6
6
|
import { withSpan } from "../../../src/observability/tracing/otlp-setup.js";
|
|
7
7
|
import { cliLogger } from "../../utils/index.js";
|
|
8
8
|
import { type ApiClient, createApiClient, resolveConfigWithAuth } from "../../shared/config.js";
|
|
@@ -11,9 +11,10 @@ import { getStringArg } from "../../shared/parsed-args.js";
|
|
|
11
11
|
import { downloadUploadToFile, listAllUploads, type UploadItem } from "../uploads/command.js";
|
|
12
12
|
import { putRemoteFileFromLocal } from "../files/command.js";
|
|
13
13
|
import { knowledgeIngestPythonSource } from "./parser-source.js";
|
|
14
|
+
import * as commandHelpers from "./command-helpers.js";
|
|
14
15
|
import { createJobUserLogger, type Logger, serverLogger } from "../../../src/utils/index.js";
|
|
15
16
|
import { writeJobResultIfConfigured } from "../../utils/write-job-result.js";
|
|
16
|
-
import {
|
|
17
|
+
import { classifyKnowledgeSourcePath } from "./source-policy.js";
|
|
17
18
|
import {
|
|
18
19
|
buildKnowledgeIngestJobResult,
|
|
19
20
|
type KnowledgeIngestFailedFileResult,
|
|
@@ -172,108 +173,10 @@ export function parseKnowledgeIngestArgs(
|
|
|
172
173
|
});
|
|
173
174
|
}
|
|
174
175
|
|
|
175
|
-
export function normalizeKnowledgeInputPath(inputPath: string): string {
|
|
176
|
-
const normalizedPath = normalize(inputPath).replace(/^\/+/, "").replace(/\\/g, "/");
|
|
177
|
-
if (!normalizedPath || normalizedPath.startsWith("..") || normalizedPath.startsWith("/")) {
|
|
178
|
-
throw new Error(`Invalid knowledge input path: ${inputPath}`);
|
|
179
|
-
}
|
|
180
|
-
return normalizedPath;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
export function normalizeProjectUploadPath(inputPath: string): string {
|
|
184
|
-
return normalizeKnowledgeInputPath(inputPath);
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
export function formatKnowledgeUploadSource(uploadPath: string): string {
|
|
188
|
-
const normalizedPath = normalizeKnowledgeInputPath(uploadPath);
|
|
189
|
-
return normalizedPath === "uploads" || normalizedPath.startsWith("uploads/")
|
|
190
|
-
? normalizedPath
|
|
191
|
-
: `uploads/${normalizedPath}`;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
function resolveExplicitUploadPath(inputPath: string): string {
|
|
195
|
-
const normalizedInput = normalizeKnowledgeInputPath(inputPath);
|
|
196
|
-
const displayInput = inputPath.replace(/\\/g, "/");
|
|
197
|
-
const uploadPath = normalizeProjectUploadPath(inputPath);
|
|
198
|
-
if (
|
|
199
|
-
!uploadPath || uploadPath === "uploads" || normalizedInput === "uploads" ||
|
|
200
|
-
normalizedInput.endsWith("/")
|
|
201
|
-
) {
|
|
202
|
-
throw new Error(
|
|
203
|
-
`Directory upload references require --path <prefix> --all: ${displayInput}`,
|
|
204
|
-
);
|
|
205
|
-
}
|
|
206
|
-
return uploadPath;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
export function isLikelyLocalPath(value: string): boolean {
|
|
210
|
-
return value.startsWith("/") || value.startsWith("./") || value.startsWith("../") ||
|
|
211
|
-
/^[A-Za-z]:[\\/]/.test(value);
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
function isProjectUploadReference(value: string): boolean {
|
|
215
|
-
if (isLikelyLocalPath(value)) return false;
|
|
216
|
-
const normalizedValue = normalize(value).replace(/\\/g, "/").replace(/^\/+/, "");
|
|
217
|
-
return normalizedValue === "uploads" || normalizedValue.startsWith("uploads/");
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
function slugify(value: string): string {
|
|
221
|
-
return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "document";
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* Strip the chat-upload prefix that Studio prepends to uploaded files.
|
|
226
|
-
*
|
|
227
|
-
* Studio stores uploads with a generated prefix like:
|
|
228
|
-
* chat-<uuid>-<timestamp>-<shortid>-<original-filename>
|
|
229
|
-
*
|
|
230
|
-
* This function removes the prefix so knowledge files use the clean
|
|
231
|
-
* original filename (e.g. "agents" instead of
|
|
232
|
-
* "chat-909d3dbc-5a9a-4156-97e4-bcceb5c2ec0d-1773942180291-fv1qg5-agents").
|
|
233
|
-
*/
|
|
234
|
-
const CHAT_UPLOAD_PREFIX_RE =
|
|
235
|
-
/^chat-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}-\d+-[a-z0-9]+-/i;
|
|
236
|
-
|
|
237
|
-
export function stripChatUploadPrefix(name: string): string {
|
|
238
|
-
return name.replace(CHAT_UPLOAD_PREFIX_RE, "");
|
|
239
|
-
}
|
|
240
|
-
|
|
241
176
|
function defaultOutputRoot(): Promise<string> {
|
|
242
177
|
return dntShim.Deno.makeTempDir({ prefix: "veryfront-knowledge-" });
|
|
243
178
|
}
|
|
244
179
|
|
|
245
|
-
export function resolveKnowledgeDownloadOutputDir(outputDir: string): string {
|
|
246
|
-
return join(outputDir, ".uploads");
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
function createSkippedKnowledgeSource(input: {
|
|
250
|
-
source: string;
|
|
251
|
-
localSourcePath?: string | null;
|
|
252
|
-
message: string;
|
|
253
|
-
reason: KnowledgeIngestSkippedFileResult["reason"];
|
|
254
|
-
}): KnowledgeIngestSkippedFileResult {
|
|
255
|
-
return {
|
|
256
|
-
source: input.source,
|
|
257
|
-
localSourcePath: input.localSourcePath ?? null,
|
|
258
|
-
message: input.message,
|
|
259
|
-
reason: input.reason,
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
function createFailedKnowledgeSource(input: {
|
|
264
|
-
source: string;
|
|
265
|
-
localSourcePath: string;
|
|
266
|
-
message: string;
|
|
267
|
-
reason: KnowledgeIngestFailedFileResult["reason"];
|
|
268
|
-
}): KnowledgeIngestFailedFileResult {
|
|
269
|
-
return {
|
|
270
|
-
source: input.source,
|
|
271
|
-
localSourcePath: input.localSourcePath,
|
|
272
|
-
message: input.message,
|
|
273
|
-
reason: input.reason,
|
|
274
|
-
};
|
|
275
|
-
}
|
|
276
|
-
|
|
277
180
|
function classifySourceOrSkip(input: {
|
|
278
181
|
source: string;
|
|
279
182
|
localSourcePath?: string | null;
|
|
@@ -283,180 +186,51 @@ function classifySourceOrSkip(input: {
|
|
|
283
186
|
return null;
|
|
284
187
|
}
|
|
285
188
|
|
|
286
|
-
return
|
|
189
|
+
return {
|
|
287
190
|
source: input.source,
|
|
288
|
-
localSourcePath: input.localSourcePath,
|
|
191
|
+
localSourcePath: input.localSourcePath ?? null,
|
|
289
192
|
message: decision.message,
|
|
290
193
|
reason: decision.reason,
|
|
291
|
-
}
|
|
194
|
+
};
|
|
292
195
|
}
|
|
293
196
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
197
|
+
export const normalizeKnowledgeInputPath = commandHelpers.normalizeKnowledgeInputPath;
|
|
198
|
+
export const normalizeProjectUploadPath = commandHelpers.normalizeProjectUploadPath;
|
|
199
|
+
export const formatKnowledgeUploadSource = commandHelpers.formatKnowledgeUploadSource;
|
|
200
|
+
export const isLikelyLocalPath = commandHelpers.isLikelyLocalPath;
|
|
201
|
+
export const stripChatUploadPrefix = commandHelpers.stripChatUploadPrefix;
|
|
202
|
+
export const resolveKnowledgeDownloadOutputDir = commandHelpers.resolveKnowledgeDownloadOutputDir;
|
|
203
|
+
export const buildSuggestedSlug = commandHelpers.buildSuggestedSlug;
|
|
204
|
+
export const ensureUniqueSlugs = commandHelpers.ensureUniqueSlugs;
|
|
205
|
+
export const deriveKnowledgeRemotePath = commandHelpers.deriveKnowledgeRemotePath;
|
|
206
|
+
export const createKnowledgeIngestResult = commandHelpers.createKnowledgeIngestResult;
|
|
301
207
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
208
|
+
function resolveExplicitUploadPath(inputPath: string): string {
|
|
209
|
+
return commandHelpers.resolveExplicitUploadPath(inputPath);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function isProjectUploadReference(value: string): boolean {
|
|
213
|
+
return commandHelpers.isProjectUploadReference(value);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function createFailedKnowledgeSource(input: {
|
|
217
|
+
source: string;
|
|
218
|
+
localSourcePath: string;
|
|
219
|
+
message: string;
|
|
220
|
+
reason: KnowledgeIngestFailedFileResult["reason"];
|
|
221
|
+
}): KnowledgeIngestFailedFileResult {
|
|
222
|
+
return commandHelpers.createFailedKnowledgeSource(input);
|
|
308
223
|
}
|
|
309
224
|
|
|
310
225
|
async function collectLocalFiles(
|
|
311
226
|
root: string,
|
|
312
227
|
recursive: boolean,
|
|
313
228
|
): Promise<KnowledgeSourceCollection> {
|
|
314
|
-
|
|
315
|
-
const stat = await fs.stat(root);
|
|
316
|
-
if (stat.isFile) {
|
|
317
|
-
const skipped = classifySourceOrSkip({ source: root, localSourcePath: root });
|
|
318
|
-
return skipped == null
|
|
319
|
-
? {
|
|
320
|
-
sources: [{ kind: "local", input: root, localPath: root }],
|
|
321
|
-
skipped: [],
|
|
322
|
-
}
|
|
323
|
-
: {
|
|
324
|
-
sources: [],
|
|
325
|
-
skipped: [skipped],
|
|
326
|
-
};
|
|
327
|
-
}
|
|
328
|
-
if (!stat.isDirectory) {
|
|
329
|
-
return { sources: [], skipped: [] };
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
const skippedRootDirectory = classifyDirectoryOrSkip({ source: root });
|
|
333
|
-
if (skippedRootDirectory != null) {
|
|
334
|
-
return {
|
|
335
|
-
sources: [],
|
|
336
|
-
skipped: [skippedRootDirectory],
|
|
337
|
-
};
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
const collection: KnowledgeSourceCollection = {
|
|
341
|
-
sources: [],
|
|
342
|
-
skipped: [],
|
|
343
|
-
};
|
|
344
|
-
async function walk(dir: string): Promise<void> {
|
|
345
|
-
for await (const entry of fs.readDir(dir)) {
|
|
346
|
-
const entryPath = join(dir, entry.name);
|
|
347
|
-
if (entry.isDirectory) {
|
|
348
|
-
const skipped = classifyDirectoryOrSkip({ source: entryPath });
|
|
349
|
-
if (skipped != null) {
|
|
350
|
-
collection.skipped.push(skipped);
|
|
351
|
-
continue;
|
|
352
|
-
}
|
|
353
|
-
if (recursive) await walk(entryPath);
|
|
354
|
-
continue;
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
if (!entry.isFile) {
|
|
358
|
-
continue;
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
const skipped = classifySourceOrSkip({ source: entryPath, localSourcePath: entryPath });
|
|
362
|
-
if (skipped != null) {
|
|
363
|
-
collection.skipped.push(skipped);
|
|
364
|
-
continue;
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
collection.sources.push({ kind: "local", input: root, localPath: entryPath });
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
await walk(root);
|
|
372
|
-
collection.sources.sort((left, right) => left.localPath.localeCompare(right.localPath));
|
|
373
|
-
collection.skipped.sort((left, right) => left.source.localeCompare(right.source));
|
|
374
|
-
return collection;
|
|
229
|
+
return commandHelpers.collectLocalFiles(root, recursive);
|
|
375
230
|
}
|
|
376
231
|
|
|
377
232
|
function buildSourceReference(source: KnowledgeSource): string {
|
|
378
|
-
return source
|
|
379
|
-
? formatKnowledgeUploadSource(source.uploadPath)
|
|
380
|
-
: source.localPath;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
export function buildSuggestedSlug(source: KnowledgeSource, index: number): string {
|
|
384
|
-
const normalized = normalize(
|
|
385
|
-
source.kind === "upload" ? source.uploadPath : source.localPath,
|
|
386
|
-
).replace(/\\/g, "/");
|
|
387
|
-
|
|
388
|
-
let stripped: string;
|
|
389
|
-
if (source.kind === "upload") {
|
|
390
|
-
stripped = normalized
|
|
391
|
-
.replace(/^\/workspace\/uploads\//, "")
|
|
392
|
-
.replace(/^\/workspace\//, "")
|
|
393
|
-
.replace(/^uploads\//, "")
|
|
394
|
-
.replace(/\.[^.]+$/, "");
|
|
395
|
-
} else if (normalized.startsWith("/workspace/uploads/")) {
|
|
396
|
-
stripped = normalized.replace(/^\/workspace\/uploads\//, "").replace(/\.[^.]+$/, "");
|
|
397
|
-
} else if (normalized.startsWith("/workspace/")) {
|
|
398
|
-
stripped = normalized.replace(/^\/workspace\//, "").replace(/\.[^.]+$/, "");
|
|
399
|
-
} else if (normalized.startsWith("/")) {
|
|
400
|
-
stripped = basename(normalized, extname(normalized));
|
|
401
|
-
} else {
|
|
402
|
-
stripped = normalized.replace(/\.[^.]+$/, "");
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
// Strip Studio's chat-upload prefix from the filename portion so that
|
|
406
|
-
// knowledge files use the original clean filename.
|
|
407
|
-
const lastSlash = stripped.lastIndexOf("/");
|
|
408
|
-
if (lastSlash >= 0) {
|
|
409
|
-
const dir = stripped.slice(0, lastSlash + 1);
|
|
410
|
-
const file = stripChatUploadPrefix(stripped.slice(lastSlash + 1));
|
|
411
|
-
stripped = file ? `${dir}${file}` : stripped;
|
|
412
|
-
} else {
|
|
413
|
-
stripped = stripChatUploadPrefix(stripped) || stripped;
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
return slugify(stripped || basename(normalized, extname(normalized)) || `document-${index + 1}`);
|
|
417
|
-
}
|
|
418
|
-
export function ensureUniqueSlugs(sources: KnowledgeSource[]): string[] {
|
|
419
|
-
const counts = new Map<string, number>();
|
|
420
|
-
return sources.map((source, index) => {
|
|
421
|
-
const baseSlug = buildSuggestedSlug(source, index);
|
|
422
|
-
const nextCount = (counts.get(baseSlug) ?? 0) + 1;
|
|
423
|
-
counts.set(baseSlug, nextCount);
|
|
424
|
-
return nextCount === 1 ? baseSlug : `${baseSlug}-${nextCount}`;
|
|
425
|
-
});
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
export function deriveKnowledgeRemotePath(
|
|
429
|
-
outputPath: string,
|
|
430
|
-
outputDir: string,
|
|
431
|
-
knowledgePath: string,
|
|
432
|
-
): string {
|
|
433
|
-
const relativeOutputPath = relative(outputDir, outputPath).replace(/\\/g, "/");
|
|
434
|
-
if (!relativeOutputPath || relativeOutputPath.startsWith("..")) {
|
|
435
|
-
throw new Error(`Output path is outside output directory: ${outputPath}`);
|
|
436
|
-
}
|
|
437
|
-
const prefix = normalizeKnowledgeInputPath(knowledgePath);
|
|
438
|
-
const normalizedRelative = normalize(relativeOutputPath).replace(/^\/+/, "");
|
|
439
|
-
return `${prefix}/${normalizedRelative}`.replace(/\\/g, "/");
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
export function createKnowledgeIngestResult(input: {
|
|
443
|
-
source: string;
|
|
444
|
-
localSourcePath: string;
|
|
445
|
-
outputPath: string;
|
|
446
|
-
remotePath: string;
|
|
447
|
-
parser: Pick<KnowledgeParserResult, "slug" | "stats" | "warnings" | "source_type" | "summary">;
|
|
448
|
-
}): KnowledgeIngestFileResult {
|
|
449
|
-
return {
|
|
450
|
-
source: input.source,
|
|
451
|
-
localSourcePath: input.localSourcePath,
|
|
452
|
-
outputPath: input.outputPath,
|
|
453
|
-
remotePath: input.remotePath,
|
|
454
|
-
slug: input.parser.slug,
|
|
455
|
-
sourceType: input.parser.source_type,
|
|
456
|
-
summary: input.parser.summary,
|
|
457
|
-
stats: input.parser.stats,
|
|
458
|
-
warnings: input.parser.warnings,
|
|
459
|
-
};
|
|
233
|
+
return commandHelpers.buildSourceReference(source);
|
|
460
234
|
}
|
|
461
235
|
|
|
462
236
|
export async function runKnowledgeParser(input: {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
function encodeFilePath(path: string): string {
|
|
2
|
+
return path.split("/").map(encodeURIComponent).join("/");
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
function getBranchPath(branch?: string): string {
|
|
6
|
+
return branch ? `/branches/${branch}` : "";
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function getBranchParam(branch?: string): string {
|
|
10
|
+
return branch ? `?branch_id=${branch}` : "";
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function buildProjectApiPath(project: string, resource: string, branch?: string): string {
|
|
14
|
+
const normalizedResource = resource.startsWith("/") ? resource.slice(1) : resource;
|
|
15
|
+
return `/${project}${getBranchPath(branch)}/${normalizedResource}`;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function buildProjectFilePath(project: string, filePath: string, branch?: string): string {
|
|
19
|
+
return buildProjectApiPath(project, `files/${encodeFilePath(filePath)}`, branch);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function slugToName(slug: string): string {
|
|
23
|
+
return slug
|
|
24
|
+
.split("-")
|
|
25
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
26
|
+
.join(" ");
|
|
27
|
+
}
|
|
@@ -16,6 +16,12 @@ import { withSpan } from "../../src/observability/tracing/otlp-setup.js";
|
|
|
16
16
|
import { randomSuffix } from "../shared/slug.js";
|
|
17
17
|
|
|
18
18
|
import { DEFAULT_LOCAL_API_URL } from "../shared/constants.js";
|
|
19
|
+
import {
|
|
20
|
+
buildProjectApiPath,
|
|
21
|
+
buildProjectFilePath,
|
|
22
|
+
getBranchParam,
|
|
23
|
+
slugToName,
|
|
24
|
+
} from "./remote-file-tool-helpers.js";
|
|
19
25
|
|
|
20
26
|
function getApiBaseUrl(): string {
|
|
21
27
|
return getEnvironmentConfig().apiBaseUrl || DEFAULT_LOCAL_API_URL;
|
|
@@ -73,27 +79,6 @@ async function apiRequest<T>(
|
|
|
73
79
|
}
|
|
74
80
|
}
|
|
75
81
|
|
|
76
|
-
function encodeFilePath(path: string): string {
|
|
77
|
-
return path.split("/").map(encodeURIComponent).join("/");
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
function getBranchPath(branch?: string): string {
|
|
81
|
-
return branch ? `/branches/${branch}` : "";
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
function getBranchParam(branch?: string): string {
|
|
85
|
-
return branch ? `?branch_id=${branch}` : "";
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function buildProjectApiPath(project: string, resource: string, branch?: string): string {
|
|
89
|
-
const normalizedResource = resource.startsWith("/") ? resource.slice(1) : resource;
|
|
90
|
-
return `/${project}${getBranchPath(branch)}/${normalizedResource}`;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
function buildProjectFilePath(project: string, filePath: string, branch?: string): string {
|
|
94
|
-
return buildProjectApiPath(project, `files/${encodeFilePath(filePath)}`, branch);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
82
|
interface RemoteFile {
|
|
98
83
|
id?: string;
|
|
99
84
|
path: string;
|
|
@@ -145,13 +130,6 @@ interface Project {
|
|
|
145
130
|
|
|
146
131
|
const MAX_SLUG_ATTEMPTS = 10;
|
|
147
132
|
|
|
148
|
-
function slugToName(slug: string): string {
|
|
149
|
-
return slug
|
|
150
|
-
.split("-")
|
|
151
|
-
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
|
|
152
|
-
.join(" ");
|
|
153
|
-
}
|
|
154
|
-
|
|
155
133
|
/**
|
|
156
134
|
* Create a project with slug conflict retry.
|
|
157
135
|
* On 409, appends a random suffix and retries (matches reserveProjectSlug behavior).
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { join } from "../../src/fs/index.js";
|
|
2
|
+
import type { IntegrationName, TemplateFile } from "./types.js";
|
|
3
|
+
|
|
4
|
+
export function resolveIntegrationModuleDir(
|
|
5
|
+
moduleUrl: string,
|
|
6
|
+
platform = typeof process !== "undefined" ? process.platform : undefined,
|
|
7
|
+
): string {
|
|
8
|
+
const normalizedModuleUrl = new URL(".", moduleUrl);
|
|
9
|
+
|
|
10
|
+
if (normalizedModuleUrl.protocol !== "file:") return normalizedModuleUrl.href;
|
|
11
|
+
|
|
12
|
+
let moduleDir = normalizedModuleUrl.pathname;
|
|
13
|
+
if (platform === "win32" && moduleDir.startsWith("/")) {
|
|
14
|
+
moduleDir = moduleDir.slice(1);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return moduleDir;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function buildIntegrationDirectory(
|
|
21
|
+
moduleDir: string,
|
|
22
|
+
integrationName: string,
|
|
23
|
+
): string {
|
|
24
|
+
return join(moduleDir, "integrations", integrationName);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function buildUnknownIntegrationErrors(
|
|
28
|
+
integrations: IntegrationName[],
|
|
29
|
+
availableIntegrations: readonly IntegrationName[],
|
|
30
|
+
): string[] {
|
|
31
|
+
const availableList = availableIntegrations.join(", ");
|
|
32
|
+
return integrations
|
|
33
|
+
.filter((integration) => !availableIntegrations.includes(integration))
|
|
34
|
+
.map((integration) => `Unknown integration: ${integration}. Available: ${availableList}`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function mergeIntegrationFiles(
|
|
38
|
+
integrations: Array<{ files: TemplateFile[] }>,
|
|
39
|
+
): TemplateFile[] {
|
|
40
|
+
const fileMap = new Map<string, TemplateFile>();
|
|
41
|
+
|
|
42
|
+
for (const integration of integrations) {
|
|
43
|
+
for (const file of integration.files) {
|
|
44
|
+
fileMap.set(file.path, file);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return [...fileMap.values()].sort((a, b) => a.path.localeCompare(b.path));
|
|
49
|
+
}
|
|
@@ -10,6 +10,12 @@
|
|
|
10
10
|
|
|
11
11
|
import { createFileSystem, join } from "../../src/fs/index.js";
|
|
12
12
|
import { loadTemplateFromDirectory } from "./loader.js";
|
|
13
|
+
import {
|
|
14
|
+
buildIntegrationDirectory,
|
|
15
|
+
buildUnknownIntegrationErrors,
|
|
16
|
+
mergeIntegrationFiles,
|
|
17
|
+
resolveIntegrationModuleDir,
|
|
18
|
+
} from "./integration-loader-helpers.js";
|
|
13
19
|
import type {
|
|
14
20
|
IntegrationConfig,
|
|
15
21
|
IntegrationName,
|
|
@@ -140,23 +146,14 @@ export const USE_CASE_CONFIGS: Record<UseCaseName, UseCaseConfig> = {
|
|
|
140
146
|
};
|
|
141
147
|
|
|
142
148
|
function getModuleDir(): string {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
if (moduleUrl.protocol !== "file:") return moduleUrl.href;
|
|
146
|
-
|
|
147
|
-
let moduleDir = moduleUrl.pathname;
|
|
148
|
-
if (typeof process !== "undefined" && process.platform === "win32" && moduleDir.startsWith("/")) {
|
|
149
|
-
moduleDir = moduleDir.slice(1);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
return moduleDir;
|
|
149
|
+
return resolveIntegrationModuleDir(import.meta.url);
|
|
153
150
|
}
|
|
154
151
|
|
|
155
152
|
/**
|
|
156
153
|
* Get the directory path for an integration
|
|
157
154
|
*/
|
|
158
155
|
export function getIntegrationDirectory(integrationName: string): string {
|
|
159
|
-
return
|
|
156
|
+
return buildIntegrationDirectory(getModuleDir(), integrationName);
|
|
160
157
|
}
|
|
161
158
|
|
|
162
159
|
/**
|
|
@@ -200,15 +197,7 @@ export function validateIntegrations(integrations: IntegrationName[]): {
|
|
|
200
197
|
valid: boolean;
|
|
201
198
|
errors: string[];
|
|
202
199
|
} {
|
|
203
|
-
const errors
|
|
204
|
-
|
|
205
|
-
for (const integration of integrations) {
|
|
206
|
-
if (AVAILABLE_INTEGRATIONS.includes(integration)) continue;
|
|
207
|
-
|
|
208
|
-
errors.push(
|
|
209
|
-
`Unknown integration: ${integration}. Available: ${AVAILABLE_INTEGRATIONS.join(", ")}`,
|
|
210
|
-
);
|
|
211
|
-
}
|
|
200
|
+
const errors = buildUnknownIntegrationErrors(integrations, AVAILABLE_INTEGRATIONS);
|
|
212
201
|
|
|
213
202
|
return { valid: errors.length === 0, errors };
|
|
214
203
|
}
|
|
@@ -225,8 +214,6 @@ export async function loadIntegrations(
|
|
|
225
214
|
}> {
|
|
226
215
|
const integrations: ResolvedIntegration[] = [];
|
|
227
216
|
const errors: string[] = [];
|
|
228
|
-
const fileMap = new Map<string, TemplateFile>();
|
|
229
|
-
|
|
230
217
|
for (const name of integrationNames) {
|
|
231
218
|
const integration = await loadIntegration(name);
|
|
232
219
|
if (!integration) {
|
|
@@ -235,16 +222,11 @@ export async function loadIntegrations(
|
|
|
235
222
|
}
|
|
236
223
|
|
|
237
224
|
integrations.push(integration);
|
|
238
|
-
|
|
239
|
-
for (const file of integration.files) {
|
|
240
|
-
// Later integrations override earlier ones
|
|
241
|
-
fileMap.set(file.path, file);
|
|
242
|
-
}
|
|
243
225
|
}
|
|
244
226
|
|
|
245
227
|
return {
|
|
246
228
|
integrations,
|
|
247
|
-
files:
|
|
229
|
+
files: mergeIntegrationFiles(integrations),
|
|
248
230
|
errors,
|
|
249
231
|
};
|
|
250
232
|
}
|