veryfront 0.1.161 → 0.1.162
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/deno.js +1 -1
- package/esm/src/platform/adapters/fs/veryfront/base-operations.d.ts +1 -1
- package/esm/src/platform/adapters/fs/veryfront/base-operations.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/veryfront/directory-operations.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/veryfront/directory-operations.js +9 -52
- package/esm/src/platform/adapters/fs/veryfront/file-list-access.d.ts +33 -0
- package/esm/src/platform/adapters/fs/veryfront/file-list-access.d.ts.map +1 -0
- package/esm/src/platform/adapters/fs/veryfront/file-list-access.js +49 -0
- package/esm/src/platform/adapters/fs/veryfront/read-operations.d.ts +1 -20
- package/esm/src/platform/adapters/fs/veryfront/read-operations.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/veryfront/stat-operations.d.ts.map +1 -1
- package/esm/src/platform/adapters/fs/veryfront/stat-operations.js +8 -49
- package/esm/src/tool/factory.d.ts +3 -5
- package/esm/src/tool/factory.d.ts.map +1 -1
- package/esm/src/tool/factory.js +2 -1
- package/esm/src/tool/index.d.ts +2 -0
- package/esm/src/tool/index.d.ts.map +1 -1
- package/esm/src/tool/index.js +1 -0
- package/esm/src/tool/remote-source-tools.d.ts +8 -0
- package/esm/src/tool/remote-source-tools.d.ts.map +1 -0
- package/esm/src/tool/remote-source-tools.js +33 -0
- 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/deno.js +1 -1
- package/src/src/platform/adapters/fs/veryfront/base-operations.ts +1 -1
- package/src/src/platform/adapters/fs/veryfront/directory-operations.ts +10 -75
- package/src/src/platform/adapters/fs/veryfront/file-list-access.ts +109 -0
- package/src/src/platform/adapters/fs/veryfront/read-operations.ts +1 -22
- package/src/src/platform/adapters/fs/veryfront/stat-operations.ts +8 -71
- package/src/src/tool/factory.ts +4 -6
- package/src/src/tool/index.ts +5 -0
- package/src/src/tool/remote-source-tools.ts +54 -0
- package/src/src/utils/version-constant.ts +1 -1
package/esm/deno.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { VeryfrontApiClient } from "../../veryfront-api-client/index.js";
|
|
2
2
|
import { FileCache } from "../cache/file-cache.js";
|
|
3
|
+
import type { ContentContextProvider } from "./file-list-access.js";
|
|
3
4
|
import { PathNormalizer } from "./path-normalizer.js";
|
|
4
|
-
import type { ContentContextProvider } from "./read-operations.js";
|
|
5
5
|
export declare class VeryfrontOperationsBase {
|
|
6
6
|
protected readonly client: VeryfrontApiClient;
|
|
7
7
|
protected readonly cache: FileCache;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-operations.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/veryfront/base-operations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"base-operations.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/veryfront/base-operations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,qBAAa,uBAAuB;IAEhC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,kBAAkB;IAC7C,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,SAAS;IACnC,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,cAAc;IAC7C,SAAS,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,sBAAsB;gBAHxC,MAAM,EAAE,kBAAkB,EAC1B,KAAK,EAAE,SAAS,EAChB,UAAU,EAAE,cAAc,EAC1B,eAAe,CAAC,EAAE,sBAAsB,YAAA;CAE9D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"directory-operations.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/veryfront/directory-operations.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"directory-operations.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/veryfront/directory-operations.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAY/D,qBAAa,mBAAoB,SAAQ,uBAAuB;IAC9D,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,YAAY,CAA8B;IAElD,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;YAsDlC,eAAe;IAa7B,OAAO,CAAC,SAAS;IA6DjB,SAAS,IAAI,IAAI;IAIjB,OAAO,CAAC,cAAc;CAUvB"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { logger as baseLogger } from "../../../../utils/index.js";
|
|
2
2
|
import { VeryfrontOperationsBase } from "./base-operations.js";
|
|
3
|
-
import { buildDirCacheKeyPrefix
|
|
3
|
+
import { buildDirCacheKeyPrefix } from "./cache-keys.js";
|
|
4
|
+
import { loadAllProjectFiles } from "./file-list-access.js";
|
|
4
5
|
import { withSpan } from "../../../../observability/tracing/otlp-setup.js";
|
|
5
|
-
import { withRetryOnTransient } from "./retry.js";
|
|
6
6
|
const logger = baseLogger.component("directory-operations");
|
|
7
7
|
export class DirectoryOperations extends VeryfrontOperationsBase {
|
|
8
8
|
dirTree = null;
|
|
@@ -110,55 +110,12 @@ export class DirectoryOperations extends VeryfrontOperationsBase {
|
|
|
110
110
|
this.dirTree = null;
|
|
111
111
|
}
|
|
112
112
|
getAllFilesRaw() {
|
|
113
|
-
return withSpan("fs.veryfront.getAllFilesRaw",
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
: undefined;
|
|
121
|
-
if (adapterFiles) {
|
|
122
|
-
const cacheMs = Math.round(performance.now() - cacheStart);
|
|
123
|
-
logger.debug("getAllFilesRaw - from adapter cache", {
|
|
124
|
-
cacheMs,
|
|
125
|
-
fileCount: adapterFiles.length,
|
|
126
|
-
});
|
|
127
|
-
return adapterFiles;
|
|
128
|
-
}
|
|
129
|
-
const cacheKey = buildFileListCacheKey(ctx);
|
|
130
|
-
if (skipPersistentCache) {
|
|
131
|
-
logger.debug("getAllFilesRaw - skipping persistent cache", {
|
|
132
|
-
cacheKey,
|
|
133
|
-
cacheKeyPrefix,
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
const cached = skipPersistentCache
|
|
137
|
-
? undefined
|
|
138
|
-
: await this.cache.getAsync(cacheKey);
|
|
139
|
-
const cacheMs = Math.round(performance.now() - cacheStart);
|
|
140
|
-
if (cached) {
|
|
141
|
-
logger.debug("getAllFilesRaw - fallback cache HIT", {
|
|
142
|
-
cacheKey,
|
|
143
|
-
cacheMs,
|
|
144
|
-
fileCount: cached.length,
|
|
145
|
-
});
|
|
146
|
-
return cached;
|
|
147
|
-
}
|
|
148
|
-
logger.warn("getAllFilesRaw - cache MISS, fetching from API", {
|
|
149
|
-
cacheKey,
|
|
150
|
-
cacheMs,
|
|
151
|
-
});
|
|
152
|
-
const isPublished = ctx?.sourceType !== "branch";
|
|
153
|
-
logger.debug("Fetching files from API", {
|
|
154
|
-
sourceType: ctx?.sourceType,
|
|
155
|
-
cacheKey,
|
|
156
|
-
});
|
|
157
|
-
const files = await withRetryOnTransient(() => isPublished
|
|
158
|
-
? this.client.listPublishedFiles(undefined, ctx?.releaseId ?? undefined, ctx?.environmentName ?? undefined)
|
|
159
|
-
: this.client.listAllFiles(), "getAllFilesRaw (dir)");
|
|
160
|
-
this.cache.set(cacheKey, files);
|
|
161
|
-
return files;
|
|
162
|
-
});
|
|
113
|
+
return withSpan("fs.veryfront.getAllFilesRaw", () => loadAllProjectFiles({
|
|
114
|
+
client: this.client,
|
|
115
|
+
cache: this.cache,
|
|
116
|
+
contextProvider: this.contextProvider,
|
|
117
|
+
logger,
|
|
118
|
+
operationLabel: "dir",
|
|
119
|
+
}));
|
|
163
120
|
}
|
|
164
121
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ProjectFile, VeryfrontApiClient } from "../../veryfront-api-client/index.js";
|
|
2
|
+
import { FileCache } from "../cache/file-cache.js";
|
|
3
|
+
import type { ResolvedContentContext } from "./types.js";
|
|
4
|
+
export interface ContentContextProvider {
|
|
5
|
+
isProductionMode: () => boolean;
|
|
6
|
+
getReleaseId: () => string | null;
|
|
7
|
+
getContentContext: () => ResolvedContentContext | null;
|
|
8
|
+
getFileList?: () => Promise<Array<{
|
|
9
|
+
id?: string;
|
|
10
|
+
path: string;
|
|
11
|
+
content?: string;
|
|
12
|
+
type?: string;
|
|
13
|
+
size?: number;
|
|
14
|
+
updated_at?: string;
|
|
15
|
+
}> | undefined>;
|
|
16
|
+
hasCachedFileList?: () => Promise<boolean>;
|
|
17
|
+
isPersistentCacheInvalidated?: (prefix: string) => boolean;
|
|
18
|
+
isReleaseBeingInvalidated?: (releaseId: string) => boolean;
|
|
19
|
+
}
|
|
20
|
+
interface FileListLogger {
|
|
21
|
+
debug(message: string, context?: Record<string, unknown>): void;
|
|
22
|
+
warn(message: string, context?: Record<string, unknown>): void;
|
|
23
|
+
}
|
|
24
|
+
interface LoadAllProjectFilesOptions {
|
|
25
|
+
client: VeryfrontApiClient;
|
|
26
|
+
cache: FileCache;
|
|
27
|
+
contextProvider?: ContentContextProvider;
|
|
28
|
+
logger: FileListLogger;
|
|
29
|
+
operationLabel: string;
|
|
30
|
+
}
|
|
31
|
+
export declare function loadAllProjectFiles({ client, cache, contextProvider, logger, operationLabel, }: LoadAllProjectFilesOptions): Promise<ProjectFile[]>;
|
|
32
|
+
export {};
|
|
33
|
+
//# sourceMappingURL=file-list-access.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-list-access.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/veryfront/file-list-access.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC3F,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAGnD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEzD,MAAM,WAAW,sBAAsB;IACrC,gBAAgB,EAAE,MAAM,OAAO,CAAC;IAChC,YAAY,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IAClC,iBAAiB,EAAE,MAAM,sBAAsB,GAAG,IAAI,CAAC;IACvD,WAAW,CAAC,EAAE,MAAM,OAAO,CACzB,KAAK,CAAC;QACJ,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC,GAAG,SAAS,CACf,CAAC;IACF,iBAAiB,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3C,4BAA4B,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IAC3D,yBAAyB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;CAC5D;AAED,UAAU,cAAc;IACtB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAChE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAChE;AAED,UAAU,0BAA0B;IAClC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,KAAK,EAAE,SAAS,CAAC;IACjB,eAAe,CAAC,EAAE,sBAAsB,CAAC;IACzC,MAAM,EAAE,cAAc,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,wBAAsB,mBAAmB,CAAC,EACxC,MAAM,EACN,KAAK,EACL,eAAe,EACf,MAAM,EACN,cAAc,GACf,EAAE,0BAA0B,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAgErD"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { buildFileCacheKeyPrefix, buildFileListCacheKey } from "./cache-keys.js";
|
|
2
|
+
import { withRetryOnTransient } from "./retry.js";
|
|
3
|
+
export async function loadAllProjectFiles({ client, cache, contextProvider, logger, operationLabel, }) {
|
|
4
|
+
const cacheStart = performance.now();
|
|
5
|
+
const ctx = contextProvider?.getContentContext();
|
|
6
|
+
const cacheKeyPrefix = buildFileCacheKeyPrefix(ctx);
|
|
7
|
+
const skipPersistentCache = contextProvider?.isPersistentCacheInvalidated?.(cacheKeyPrefix) ??
|
|
8
|
+
false;
|
|
9
|
+
const adapterFiles = !skipPersistentCache ? await contextProvider?.getFileList?.() : undefined;
|
|
10
|
+
if (adapterFiles) {
|
|
11
|
+
const cacheMs = Math.round(performance.now() - cacheStart);
|
|
12
|
+
logger.debug("getAllFilesRaw - from adapter cache", {
|
|
13
|
+
cacheMs,
|
|
14
|
+
fileCount: adapterFiles.length,
|
|
15
|
+
});
|
|
16
|
+
return adapterFiles;
|
|
17
|
+
}
|
|
18
|
+
const cacheKey = buildFileListCacheKey(ctx);
|
|
19
|
+
if (skipPersistentCache) {
|
|
20
|
+
logger.debug("getAllFilesRaw - skipping persistent cache", {
|
|
21
|
+
cacheKey,
|
|
22
|
+
cacheKeyPrefix,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
const cached = skipPersistentCache ? undefined : await cache.getAsync(cacheKey);
|
|
26
|
+
const cacheMs = Math.round(performance.now() - cacheStart);
|
|
27
|
+
if (cached) {
|
|
28
|
+
logger.debug("getAllFilesRaw - fallback cache HIT", {
|
|
29
|
+
cacheKey,
|
|
30
|
+
cacheMs,
|
|
31
|
+
fileCount: cached.length,
|
|
32
|
+
});
|
|
33
|
+
return cached;
|
|
34
|
+
}
|
|
35
|
+
logger.warn("getAllFilesRaw - cache MISS, fetching from API", {
|
|
36
|
+
cacheKey,
|
|
37
|
+
cacheMs,
|
|
38
|
+
});
|
|
39
|
+
const isPublished = ctx?.sourceType !== "branch";
|
|
40
|
+
logger.debug("Fetching files from API", {
|
|
41
|
+
sourceType: ctx?.sourceType,
|
|
42
|
+
cacheKey,
|
|
43
|
+
});
|
|
44
|
+
const files = await withRetryOnTransient(() => isPublished
|
|
45
|
+
? client.listPublishedFiles(undefined, ctx?.releaseId ?? undefined, ctx?.environmentName ?? undefined)
|
|
46
|
+
: client.listAllFiles(), `getAllFilesRaw (${operationLabel})`);
|
|
47
|
+
cache.set(cacheKey, files);
|
|
48
|
+
return files;
|
|
49
|
+
}
|
|
@@ -1,27 +1,8 @@
|
|
|
1
1
|
import type { VeryfrontApiClient } from "../../veryfront-api-client/index.js";
|
|
2
2
|
import { FileCache } from "../cache/file-cache.js";
|
|
3
3
|
import { PathNormalizer } from "./path-normalizer.js";
|
|
4
|
-
import type {
|
|
4
|
+
import type { ContentContextProvider } from "./file-list-access.js";
|
|
5
5
|
export { endRequestMetrics, getContentMetricsSnapshot, resetContentMetrics, startRequestMetrics, } from "./content-metrics.js";
|
|
6
|
-
export interface ContentContextProvider {
|
|
7
|
-
isProductionMode: () => boolean;
|
|
8
|
-
getReleaseId: () => string | null;
|
|
9
|
-
getContentContext: () => ResolvedContentContext | null;
|
|
10
|
-
/** Cached file list from adapter initialization (single source of truth) */
|
|
11
|
-
getFileList?: () => Promise<Array<{
|
|
12
|
-
id?: string;
|
|
13
|
-
path: string;
|
|
14
|
-
content?: string;
|
|
15
|
-
type?: string;
|
|
16
|
-
size?: number;
|
|
17
|
-
updated_at?: string;
|
|
18
|
-
}> | undefined>;
|
|
19
|
-
hasCachedFileList?: () => Promise<boolean>;
|
|
20
|
-
/** True if cache prefix is being deleted - skip persistent cache reads */
|
|
21
|
-
isPersistentCacheInvalidated?: (prefix: string) => boolean;
|
|
22
|
-
/** Back-compat: release-scoped invalidation */
|
|
23
|
-
isReleaseBeingInvalidated?: (releaseId: string) => boolean;
|
|
24
|
-
}
|
|
25
6
|
export declare class ReadOperations {
|
|
26
7
|
private readonly client;
|
|
27
8
|
private readonly cache;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read-operations.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/veryfront/read-operations.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAKnD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"read-operations.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/veryfront/read-operations.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAKnD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAapE,OAAO,EACL,iBAAiB,EACjB,yBAAyB,EACzB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,sBAAsB,CAAC;AAY9B,qBAAa,cAAc;IAWvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC;IACjC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC;IACpC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC;IAfpC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAI9B;IACH,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAC9C,mGAAmG;IACnG,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAA6B;gBAGnD,MAAM,EAAE,kBAAkB,EAC1B,KAAK,EAAE,SAAS,EAChB,UAAU,EAAE,cAAc,EAC1B,eAAe,CAAC,EAAE,sBAAsB,YAAA,EACxC,kBAAkB,CAAC,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,aAAA,EAC7C,gBAAgB,CAAC,GAAE,MAAM,OAAO,CAC/C,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,SAAS,CACtD,aAAA;IAKH,uBAAuB,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAIrD,kBAAkB,IAAI,IAAI;IAK1B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAY3C,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAY3C,OAAO,CAAC,mBAAmB;YAsBb,+BAA+B;YA0C/B,mBAAmB;IA0CjC,OAAO,CAAC,kBAAkB;YAoFZ,2BAA2B;YA8D3B,uCAAuC;IAmCrD,OAAO,CAAC,oBAAoB;YAgBd,YAAY;YA6JZ,qBAAqB;YA8DrB,qBAAqB;YAgDrB,+BAA+B;YA8D/B,iBAAiB;CAyBhC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stat-operations.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/veryfront/stat-operations.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAElE,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"stat-operations.d.ts","sourceRoot":"","sources":["../../../../../../src/src/platform/adapters/fs/veryfront/stat-operations.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAElE,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAuB/D,qBAAa,cAAe,SAAQ,uBAAuB;IACzD,OAAO,CAAC,SAAS,CAAyC;IAC1D,OAAO,CAAC,cAAc,CAA4B;IAClD,OAAO,CAAC,aAAa,CAA8B;IAEnD,OAAO,CAAC,sBAAsB,CAA6B;IAC3D,OAAO,CAAC,qBAAqB,CAA8B;IAE3D,OAAO,CAAC,WAAW,CAAkC;IAErD,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAGrC;IAEH,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;YAiHvB,gBAAgB;YAwChB,UAAU;IAkDxB,UAAU,IAAI,IAAI;IAMlB,kBAAkB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM;YAIpC,cAAc;IAU5B,OAAO,CAAC,0BAA0B;IAgClC,OAAO,CAAC,qBAAqB;YAQf,sBAAsB;YA8EtB,iBAAiB;IASzB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAWtC,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CAkI1F"}
|
|
@@ -2,12 +2,12 @@ import { logger as baseLogger } from "../../../../utils/index.js";
|
|
|
2
2
|
import { isFrameworkSourcePath } from "../../../../utils/path-utils.js";
|
|
3
3
|
import { VeryfrontOperationsBase } from "./base-operations.js";
|
|
4
4
|
import { createError, toError } from "../../../../errors/index.js";
|
|
5
|
-
import {
|
|
6
|
-
import { withRetryOnTransient } from "./retry.js";
|
|
5
|
+
import { buildStatCacheKeyPrefix } from "./cache-keys.js";
|
|
7
6
|
import { STAT_OPERATION_EXTENSION_PRIORITY as EXTENSION_PRIORITY } from "./extension-priority.js";
|
|
8
7
|
import { collectParentDirectories, normalizeIndexedFilePath, resolveByExtensionPriority, resolveIndexByExtensionPriority, sortPathsByExtensionPriority, stripKnownExtension, } from "./stat-operations-helpers.js";
|
|
9
8
|
import { ApiSearchCircuitBreaker } from "./api-search-circuit-breaker.js";
|
|
10
9
|
import { withSpan } from "../../../../observability/tracing/otlp-setup.js";
|
|
10
|
+
import { loadAllProjectFiles } from "./file-list-access.js";
|
|
11
11
|
const logger = baseLogger.component("stat-operations");
|
|
12
12
|
const NOT_FOUND_SENTINEL = "__NOT_FOUND__";
|
|
13
13
|
const API_SEARCH_CIRCUIT_BREAKER_THRESHOLD = 5;
|
|
@@ -206,54 +206,13 @@ export class StatOperations extends VeryfrontOperationsBase {
|
|
|
206
206
|
return this.pathMapping.get(normalizedPath) ?? normalizedPath;
|
|
207
207
|
}
|
|
208
208
|
async getAllFilesRaw() {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
if (files) {
|
|
216
|
-
const cacheMs = Math.round(performance.now() - cacheStart);
|
|
217
|
-
logger.debug("getAllFilesRaw - from adapter cache", {
|
|
218
|
-
cacheMs,
|
|
219
|
-
fileCount: files.length,
|
|
220
|
-
});
|
|
221
|
-
return files;
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
const cacheKey = buildFileListCacheKey(ctx);
|
|
225
|
-
if (skipPersistentCache) {
|
|
226
|
-
logger.debug("getAllFilesRaw - skipping persistent cache (invalidation)", {
|
|
227
|
-
cacheKey,
|
|
228
|
-
cacheKeyPrefix,
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
const cached = skipPersistentCache
|
|
232
|
-
? undefined
|
|
233
|
-
: await this.cache.getAsync(cacheKey);
|
|
234
|
-
const cacheMs = Math.round(performance.now() - cacheStart);
|
|
235
|
-
if (cached) {
|
|
236
|
-
logger.debug("getAllFilesRaw - fallback cache HIT", {
|
|
237
|
-
cacheKey,
|
|
238
|
-
cacheMs,
|
|
239
|
-
fileCount: cached.length,
|
|
240
|
-
});
|
|
241
|
-
return cached;
|
|
242
|
-
}
|
|
243
|
-
logger.warn("getAllFilesRaw - cache MISS, fetching from API", {
|
|
244
|
-
cacheKey,
|
|
245
|
-
cacheMs,
|
|
246
|
-
});
|
|
247
|
-
const isPublished = ctx?.sourceType !== "branch";
|
|
248
|
-
logger.debug("Fetching files from API", {
|
|
249
|
-
sourceType: ctx?.sourceType,
|
|
250
|
-
cacheKey,
|
|
209
|
+
return await loadAllProjectFiles({
|
|
210
|
+
client: this.client,
|
|
211
|
+
cache: this.cache,
|
|
212
|
+
contextProvider: this.contextProvider,
|
|
213
|
+
logger,
|
|
214
|
+
operationLabel: "stat",
|
|
251
215
|
});
|
|
252
|
-
const files = await withRetryOnTransient(() => isPublished
|
|
253
|
-
? this.client.listPublishedFiles(undefined, ctx?.releaseId ?? undefined, ctx?.environmentName ?? undefined)
|
|
254
|
-
: this.client.listAllFiles(), "getAllFilesRaw (stat)");
|
|
255
|
-
this.cache.set(cacheKey, files);
|
|
256
|
-
return files;
|
|
257
216
|
}
|
|
258
217
|
buildResolveSearchPatterns(normalizedPath, options, knownExtensionFallback = "exact") {
|
|
259
218
|
const patterns = new Set();
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import type { Tool, ToolConfig, ToolExecutionContext } from "./types.js";
|
|
2
|
+
import type { JsonSchema } from "./schema/json-schema.js";
|
|
2
3
|
export declare function tool<TInput = unknown, TOutput = unknown>(config: ToolConfig<TInput, TOutput>): Tool<TInput, TOutput>;
|
|
3
4
|
export interface DynamicToolConfig {
|
|
4
5
|
id?: string;
|
|
5
6
|
description: string;
|
|
6
7
|
inputSchema: unknown;
|
|
8
|
+
inputSchemaJson?: JsonSchema;
|
|
7
9
|
execute: (input: unknown, context?: ToolExecutionContext) => Promise<unknown> | unknown;
|
|
8
10
|
toModelOutput?: (output: unknown) => unknown;
|
|
9
|
-
mcp?:
|
|
10
|
-
enabled?: boolean;
|
|
11
|
-
requiresAuth?: boolean;
|
|
12
|
-
cachePolicy?: "no-cache" | "cache" | "cache-first";
|
|
13
|
-
};
|
|
11
|
+
mcp?: ToolConfig["mcp"];
|
|
14
12
|
}
|
|
15
13
|
export declare function dynamicTool(config: DynamicToolConfig): Tool<unknown, unknown>;
|
|
16
14
|
//# sourceMappingURL=factory.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../src/src/tool/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../src/src/tool/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACzE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAuI1D,wBAAgB,IAAI,CAAC,MAAM,GAAG,OAAO,EAAE,OAAO,GAAG,OAAO,EACtD,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,GAClC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAqCvB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;IACrB,eAAe,CAAC,EAAE,UAAU,CAAC;IAC7B,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,oBAAoB,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IACxF,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC;IAC7C,GAAG,CAAC,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;CACzB;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CA4B7E"}
|
package/esm/src/tool/factory.js
CHANGED
|
@@ -105,7 +105,8 @@ export function tool(config) {
|
|
|
105
105
|
export function dynamicTool(config) {
|
|
106
106
|
const explicitId = typeof config.id === "string" && config.id.length > 0 ? config.id : undefined;
|
|
107
107
|
const id = explicitId ?? generateToolId();
|
|
108
|
-
const inputSchemaJson =
|
|
108
|
+
const inputSchemaJson = config.inputSchemaJson ??
|
|
109
|
+
convertSchemaToJson(config.inputSchema, id, "DYNAMIC_TOOL", true);
|
|
109
110
|
const createdTool = {
|
|
110
111
|
id,
|
|
111
112
|
type: "dynamic",
|
package/esm/src/tool/index.d.ts
CHANGED
|
@@ -48,6 +48,8 @@ export { dynamicTool, tool } from "./factory.js";
|
|
|
48
48
|
export type { DynamicToolConfig } from "./factory.js";
|
|
49
49
|
export { createRemoteMCPToolSource } from "./remote-mcp.js";
|
|
50
50
|
export type { RemoteMCPToolSourceConfig } from "./remote-mcp.js";
|
|
51
|
+
export { createToolsFromRemoteDefinitions, loadRemoteToolsFromSource, } from "./remote-source-tools.js";
|
|
52
|
+
export type { RemoteToolMaterializationOptions } from "./remote-source-tools.js";
|
|
51
53
|
export { toolRegistry } from "./registry.js";
|
|
52
54
|
export { executeTool } from "./executor.js";
|
|
53
55
|
export type { JsonSchema } from "./schema/index.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/tool/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,OAAO,yBAAyB,CAAC;AAGjC,YAAY,EACV,gBAAgB,EAChB,IAAI,EACJ,UAAU,EACV,cAAc,EACd,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACjD,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,YAAY,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/tool/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,OAAO,yBAAyB,CAAC;AAGjC,YAAY,EACV,gBAAgB,EAChB,IAAI,EACJ,UAAU,EACV,cAAc,EACd,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACjD,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,YAAY,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AACjE,OAAO,EACL,gCAAgC,EAChC,yBAAyB,GAC1B,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,gCAAgC,EAAE,MAAM,0BAA0B,CAAC;AAEjF,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC"}
|
package/esm/src/tool/index.js
CHANGED
|
@@ -45,5 +45,6 @@
|
|
|
45
45
|
import "../../_dnt.polyfills.js";
|
|
46
46
|
export { dynamicTool, tool } from "./factory.js";
|
|
47
47
|
export { createRemoteMCPToolSource } from "./remote-mcp.js";
|
|
48
|
+
export { createToolsFromRemoteDefinitions, loadRemoteToolsFromSource, } from "./remote-source-tools.js";
|
|
48
49
|
export { toolRegistry } from "./registry.js";
|
|
49
50
|
export { executeTool } from "./executor.js";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { RemoteToolSource, Tool, ToolDefinition, ToolExecutionContext } from "./types.js";
|
|
2
|
+
export interface RemoteToolMaterializationOptions {
|
|
3
|
+
context?: ToolExecutionContext;
|
|
4
|
+
toolNameAliases?: Record<string, string>;
|
|
5
|
+
}
|
|
6
|
+
export declare function createToolsFromRemoteDefinitions(source: RemoteToolSource, definitions: readonly ToolDefinition[], options?: Omit<RemoteToolMaterializationOptions, "context">): Record<string, Tool<unknown, unknown>>;
|
|
7
|
+
export declare function loadRemoteToolsFromSource(source: RemoteToolSource, options?: RemoteToolMaterializationOptions): Promise<Record<string, Tool<unknown, unknown>>>;
|
|
8
|
+
//# sourceMappingURL=remote-source-tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote-source-tools.d.ts","sourceRoot":"","sources":["../../../src/src/tool/remote-source-tools.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAE/F,MAAM,WAAW,gCAAgC;IAC/C,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAC/B,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C;AAUD,wBAAgB,gCAAgC,CAC9C,MAAM,EAAE,gBAAgB,EACxB,WAAW,EAAE,SAAS,cAAc,EAAE,EACtC,OAAO,GAAE,IAAI,CAAC,gCAAgC,EAAE,SAAS,CAAM,GAC9D,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAsBxC;AAED,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,gBAAgB,EACxB,OAAO,GAAE,gCAAqC,GAC7C,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAKjD"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { dynamicTool } from "./factory.js";
|
|
3
|
+
function toToolInputRecord(input) {
|
|
4
|
+
if (typeof input !== "object" || input === null || Array.isArray(input)) {
|
|
5
|
+
return {};
|
|
6
|
+
}
|
|
7
|
+
return Object.fromEntries(Object.entries(input));
|
|
8
|
+
}
|
|
9
|
+
export function createToolsFromRemoteDefinitions(source, definitions, options = {}) {
|
|
10
|
+
return Object.fromEntries(definitions.map((definition) => {
|
|
11
|
+
const toolName = options.toolNameAliases?.[definition.name] ?? definition.name;
|
|
12
|
+
return [
|
|
13
|
+
toolName,
|
|
14
|
+
dynamicTool({
|
|
15
|
+
id: toolName,
|
|
16
|
+
description: definition.description,
|
|
17
|
+
inputSchema: z.object({}).passthrough(),
|
|
18
|
+
inputSchemaJson: definition.parameters,
|
|
19
|
+
mcp: {
|
|
20
|
+
title: definition.title,
|
|
21
|
+
annotations: definition.annotations,
|
|
22
|
+
},
|
|
23
|
+
execute: async (input, context) => await source.executeTool(definition.name, toToolInputRecord(input), context),
|
|
24
|
+
}),
|
|
25
|
+
];
|
|
26
|
+
}));
|
|
27
|
+
}
|
|
28
|
+
export async function loadRemoteToolsFromSource(source, options = {}) {
|
|
29
|
+
const definitions = await source.listTools(options.context);
|
|
30
|
+
return createToolsFromRemoteDefinitions(source, definitions, {
|
|
31
|
+
toolNameAliases: options.toolNameAliases,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "0.1.
|
|
1
|
+
export declare const VERSION = "0.1.162";
|
|
2
2
|
//# sourceMappingURL=version-constant.d.ts.map
|
package/package.json
CHANGED
package/src/deno.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { VeryfrontApiClient } from "../../veryfront-api-client/index.js";
|
|
2
2
|
import { FileCache } from "../cache/file-cache.js";
|
|
3
|
+
import type { ContentContextProvider } from "./file-list-access.js";
|
|
3
4
|
import { PathNormalizer } from "./path-normalizer.js";
|
|
4
|
-
import type { ContentContextProvider } from "./read-operations.js";
|
|
5
5
|
|
|
6
6
|
export class VeryfrontOperationsBase {
|
|
7
7
|
constructor(
|
|
@@ -2,13 +2,9 @@ import { logger as baseLogger } from "../../../../utils/index.js";
|
|
|
2
2
|
import type { DirectoryEntry } from "./types.js";
|
|
3
3
|
import type { ProjectFile } from "../../veryfront-api-client/index.js";
|
|
4
4
|
import { VeryfrontOperationsBase } from "./base-operations.js";
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
buildFileCacheKeyPrefix,
|
|
8
|
-
buildFileListCacheKey,
|
|
9
|
-
} from "./cache-keys.js";
|
|
5
|
+
import { buildDirCacheKeyPrefix } from "./cache-keys.js";
|
|
6
|
+
import { loadAllProjectFiles } from "./file-list-access.js";
|
|
10
7
|
import { withSpan } from "../../../../observability/tracing/otlp-setup.js";
|
|
11
|
-
import { withRetryOnTransient } from "./retry.js";
|
|
12
8
|
|
|
13
9
|
const logger = baseLogger.component("directory-operations");
|
|
14
10
|
|
|
@@ -154,74 +150,13 @@ export class DirectoryOperations extends VeryfrontOperationsBase {
|
|
|
154
150
|
}
|
|
155
151
|
|
|
156
152
|
private getAllFilesRaw(): Promise<ProjectFile[]> {
|
|
157
|
-
return withSpan("fs.veryfront.getAllFilesRaw",
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
? await this.contextProvider?.getFileList?.()
|
|
166
|
-
: undefined;
|
|
167
|
-
|
|
168
|
-
if (adapterFiles) {
|
|
169
|
-
const cacheMs = Math.round(performance.now() - cacheStart);
|
|
170
|
-
logger.debug("getAllFilesRaw - from adapter cache", {
|
|
171
|
-
cacheMs,
|
|
172
|
-
fileCount: adapterFiles.length,
|
|
173
|
-
});
|
|
174
|
-
return adapterFiles as ProjectFile[];
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
const cacheKey = buildFileListCacheKey(ctx);
|
|
178
|
-
|
|
179
|
-
if (skipPersistentCache) {
|
|
180
|
-
logger.debug("getAllFilesRaw - skipping persistent cache", {
|
|
181
|
-
cacheKey,
|
|
182
|
-
cacheKeyPrefix,
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
const cached = skipPersistentCache
|
|
187
|
-
? undefined
|
|
188
|
-
: await this.cache.getAsync<ProjectFile[]>(cacheKey);
|
|
189
|
-
|
|
190
|
-
const cacheMs = Math.round(performance.now() - cacheStart);
|
|
191
|
-
if (cached) {
|
|
192
|
-
logger.debug("getAllFilesRaw - fallback cache HIT", {
|
|
193
|
-
cacheKey,
|
|
194
|
-
cacheMs,
|
|
195
|
-
fileCount: cached.length,
|
|
196
|
-
});
|
|
197
|
-
return cached;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
logger.warn("getAllFilesRaw - cache MISS, fetching from API", {
|
|
201
|
-
cacheKey,
|
|
202
|
-
cacheMs,
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
const isPublished = ctx?.sourceType !== "branch";
|
|
206
|
-
logger.debug("Fetching files from API", {
|
|
207
|
-
sourceType: ctx?.sourceType,
|
|
208
|
-
cacheKey,
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
const files = await withRetryOnTransient(
|
|
212
|
-
() =>
|
|
213
|
-
isPublished
|
|
214
|
-
? this.client.listPublishedFiles(
|
|
215
|
-
undefined,
|
|
216
|
-
ctx?.releaseId ?? undefined,
|
|
217
|
-
ctx?.environmentName ?? undefined,
|
|
218
|
-
)
|
|
219
|
-
: this.client.listAllFiles(),
|
|
220
|
-
"getAllFilesRaw (dir)",
|
|
221
|
-
);
|
|
222
|
-
|
|
223
|
-
this.cache.set(cacheKey, files);
|
|
224
|
-
return files;
|
|
225
|
-
});
|
|
153
|
+
return withSpan("fs.veryfront.getAllFilesRaw", () =>
|
|
154
|
+
loadAllProjectFiles({
|
|
155
|
+
client: this.client,
|
|
156
|
+
cache: this.cache,
|
|
157
|
+
contextProvider: this.contextProvider,
|
|
158
|
+
logger,
|
|
159
|
+
operationLabel: "dir",
|
|
160
|
+
}));
|
|
226
161
|
}
|
|
227
162
|
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import type { ProjectFile, VeryfrontApiClient } from "../../veryfront-api-client/index.js";
|
|
2
|
+
import { FileCache } from "../cache/file-cache.js";
|
|
3
|
+
import { buildFileCacheKeyPrefix, buildFileListCacheKey } from "./cache-keys.js";
|
|
4
|
+
import { withRetryOnTransient } from "./retry.js";
|
|
5
|
+
import type { ResolvedContentContext } from "./types.js";
|
|
6
|
+
|
|
7
|
+
export interface ContentContextProvider {
|
|
8
|
+
isProductionMode: () => boolean;
|
|
9
|
+
getReleaseId: () => string | null;
|
|
10
|
+
getContentContext: () => ResolvedContentContext | null;
|
|
11
|
+
getFileList?: () => Promise<
|
|
12
|
+
Array<{
|
|
13
|
+
id?: string;
|
|
14
|
+
path: string;
|
|
15
|
+
content?: string;
|
|
16
|
+
type?: string;
|
|
17
|
+
size?: number;
|
|
18
|
+
updated_at?: string;
|
|
19
|
+
}> | undefined
|
|
20
|
+
>;
|
|
21
|
+
hasCachedFileList?: () => Promise<boolean>;
|
|
22
|
+
isPersistentCacheInvalidated?: (prefix: string) => boolean;
|
|
23
|
+
isReleaseBeingInvalidated?: (releaseId: string) => boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface FileListLogger {
|
|
27
|
+
debug(message: string, context?: Record<string, unknown>): void;
|
|
28
|
+
warn(message: string, context?: Record<string, unknown>): void;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
interface LoadAllProjectFilesOptions {
|
|
32
|
+
client: VeryfrontApiClient;
|
|
33
|
+
cache: FileCache;
|
|
34
|
+
contextProvider?: ContentContextProvider;
|
|
35
|
+
logger: FileListLogger;
|
|
36
|
+
operationLabel: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export async function loadAllProjectFiles({
|
|
40
|
+
client,
|
|
41
|
+
cache,
|
|
42
|
+
contextProvider,
|
|
43
|
+
logger,
|
|
44
|
+
operationLabel,
|
|
45
|
+
}: LoadAllProjectFilesOptions): Promise<ProjectFile[]> {
|
|
46
|
+
const cacheStart = performance.now();
|
|
47
|
+
const ctx = contextProvider?.getContentContext();
|
|
48
|
+
const cacheKeyPrefix = buildFileCacheKeyPrefix(ctx);
|
|
49
|
+
const skipPersistentCache = contextProvider?.isPersistentCacheInvalidated?.(cacheKeyPrefix) ??
|
|
50
|
+
false;
|
|
51
|
+
|
|
52
|
+
const adapterFiles = !skipPersistentCache ? await contextProvider?.getFileList?.() : undefined;
|
|
53
|
+
|
|
54
|
+
if (adapterFiles) {
|
|
55
|
+
const cacheMs = Math.round(performance.now() - cacheStart);
|
|
56
|
+
logger.debug("getAllFilesRaw - from adapter cache", {
|
|
57
|
+
cacheMs,
|
|
58
|
+
fileCount: adapterFiles.length,
|
|
59
|
+
});
|
|
60
|
+
return adapterFiles as ProjectFile[];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const cacheKey = buildFileListCacheKey(ctx);
|
|
64
|
+
|
|
65
|
+
if (skipPersistentCache) {
|
|
66
|
+
logger.debug("getAllFilesRaw - skipping persistent cache", {
|
|
67
|
+
cacheKey,
|
|
68
|
+
cacheKeyPrefix,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const cached = skipPersistentCache ? undefined : await cache.getAsync<ProjectFile[]>(cacheKey);
|
|
73
|
+
const cacheMs = Math.round(performance.now() - cacheStart);
|
|
74
|
+
|
|
75
|
+
if (cached) {
|
|
76
|
+
logger.debug("getAllFilesRaw - fallback cache HIT", {
|
|
77
|
+
cacheKey,
|
|
78
|
+
cacheMs,
|
|
79
|
+
fileCount: cached.length,
|
|
80
|
+
});
|
|
81
|
+
return cached;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
logger.warn("getAllFilesRaw - cache MISS, fetching from API", {
|
|
85
|
+
cacheKey,
|
|
86
|
+
cacheMs,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const isPublished = ctx?.sourceType !== "branch";
|
|
90
|
+
logger.debug("Fetching files from API", {
|
|
91
|
+
sourceType: ctx?.sourceType,
|
|
92
|
+
cacheKey,
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
const files = await withRetryOnTransient(
|
|
96
|
+
() =>
|
|
97
|
+
isPublished
|
|
98
|
+
? client.listPublishedFiles(
|
|
99
|
+
undefined,
|
|
100
|
+
ctx?.releaseId ?? undefined,
|
|
101
|
+
ctx?.environmentName ?? undefined,
|
|
102
|
+
)
|
|
103
|
+
: client.listAllFiles(),
|
|
104
|
+
`getAllFilesRaw (${operationLabel})`,
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
cache.set(cacheKey, files);
|
|
108
|
+
return files;
|
|
109
|
+
}
|
|
@@ -7,6 +7,7 @@ import { FileListIndex, type FileListMatchResult } from "./file-list-index.js";
|
|
|
7
7
|
import { InFlightRequestDeduper } from "./in-flight-dedupe.js";
|
|
8
8
|
import { getRequestScopedFile, setRequestScopedFile } from "./multi-project-adapter.js";
|
|
9
9
|
import { PathNormalizer } from "./path-normalizer.js";
|
|
10
|
+
import type { ContentContextProvider } from "./file-list-access.js";
|
|
10
11
|
import {
|
|
11
12
|
assertProjectSourcePath,
|
|
12
13
|
buildExtensionCandidatePaths,
|
|
@@ -28,28 +29,6 @@ export {
|
|
|
28
29
|
|
|
29
30
|
const logger = baseLogger.component("read-operations");
|
|
30
31
|
|
|
31
|
-
export interface ContentContextProvider {
|
|
32
|
-
isProductionMode: () => boolean;
|
|
33
|
-
getReleaseId: () => string | null;
|
|
34
|
-
getContentContext: () => ResolvedContentContext | null;
|
|
35
|
-
/** Cached file list from adapter initialization (single source of truth) */
|
|
36
|
-
getFileList?: () => Promise<
|
|
37
|
-
Array<{
|
|
38
|
-
id?: string;
|
|
39
|
-
path: string;
|
|
40
|
-
content?: string;
|
|
41
|
-
type?: string;
|
|
42
|
-
size?: number;
|
|
43
|
-
updated_at?: string;
|
|
44
|
-
}> | undefined
|
|
45
|
-
>;
|
|
46
|
-
hasCachedFileList?: () => Promise<boolean>;
|
|
47
|
-
/** True if cache prefix is being deleted - skip persistent cache reads */
|
|
48
|
-
isPersistentCacheInvalidated?: (prefix: string) => boolean;
|
|
49
|
-
/** Back-compat: release-scoped invalidation */
|
|
50
|
-
isReleaseBeingInvalidated?: (releaseId: string) => boolean;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
32
|
const IN_FLIGHT_REQUEST_TIMEOUT_MS = 15_000;
|
|
54
33
|
const MAX_IN_FLIGHT_REQUESTS = 100;
|
|
55
34
|
const IN_FLIGHT_CLEANUP_INTERVAL_MS = 1_000;
|
|
@@ -4,12 +4,7 @@ import type { FileInfo, ResolveFileOptions } from "../../base.js";
|
|
|
4
4
|
import type { ProjectFile } from "../../veryfront-api-client/index.js";
|
|
5
5
|
import { VeryfrontOperationsBase } from "./base-operations.js";
|
|
6
6
|
import { createError, toError } from "../../../../errors/index.js";
|
|
7
|
-
import {
|
|
8
|
-
buildFileCacheKeyPrefix,
|
|
9
|
-
buildFileListCacheKey,
|
|
10
|
-
buildStatCacheKeyPrefix,
|
|
11
|
-
} from "./cache-keys.js";
|
|
12
|
-
import { withRetryOnTransient } from "./retry.js";
|
|
7
|
+
import { buildStatCacheKeyPrefix } from "./cache-keys.js";
|
|
13
8
|
import { STAT_OPERATION_EXTENSION_PRIORITY as EXTENSION_PRIORITY } from "./extension-priority.js";
|
|
14
9
|
import {
|
|
15
10
|
collectParentDirectories,
|
|
@@ -21,6 +16,7 @@ import {
|
|
|
21
16
|
} from "./stat-operations-helpers.js";
|
|
22
17
|
import { ApiSearchCircuitBreaker } from "./api-search-circuit-breaker.js";
|
|
23
18
|
import { withSpan } from "../../../../observability/tracing/otlp-setup.js";
|
|
19
|
+
import { loadAllProjectFiles } from "./file-list-access.js";
|
|
24
20
|
|
|
25
21
|
const logger = baseLogger.component("stat-operations");
|
|
26
22
|
|
|
@@ -258,72 +254,13 @@ export class StatOperations extends VeryfrontOperationsBase {
|
|
|
258
254
|
}
|
|
259
255
|
|
|
260
256
|
private async getAllFilesRaw(): Promise<ProjectFile[]> {
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
if (!skipPersistentCache) {
|
|
268
|
-
const files = await this.contextProvider?.getFileList?.();
|
|
269
|
-
if (files) {
|
|
270
|
-
const cacheMs = Math.round(performance.now() - cacheStart);
|
|
271
|
-
logger.debug("getAllFilesRaw - from adapter cache", {
|
|
272
|
-
cacheMs,
|
|
273
|
-
fileCount: files.length,
|
|
274
|
-
});
|
|
275
|
-
return files as ProjectFile[];
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
const cacheKey = buildFileListCacheKey(ctx);
|
|
280
|
-
|
|
281
|
-
if (skipPersistentCache) {
|
|
282
|
-
logger.debug("getAllFilesRaw - skipping persistent cache (invalidation)", {
|
|
283
|
-
cacheKey,
|
|
284
|
-
cacheKeyPrefix,
|
|
285
|
-
});
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
const cached = skipPersistentCache
|
|
289
|
-
? undefined
|
|
290
|
-
: await this.cache.getAsync<ProjectFile[]>(cacheKey);
|
|
291
|
-
const cacheMs = Math.round(performance.now() - cacheStart);
|
|
292
|
-
|
|
293
|
-
if (cached) {
|
|
294
|
-
logger.debug("getAllFilesRaw - fallback cache HIT", {
|
|
295
|
-
cacheKey,
|
|
296
|
-
cacheMs,
|
|
297
|
-
fileCount: cached.length,
|
|
298
|
-
});
|
|
299
|
-
return cached;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
logger.warn("getAllFilesRaw - cache MISS, fetching from API", {
|
|
303
|
-
cacheKey,
|
|
304
|
-
cacheMs,
|
|
257
|
+
return await loadAllProjectFiles({
|
|
258
|
+
client: this.client,
|
|
259
|
+
cache: this.cache,
|
|
260
|
+
contextProvider: this.contextProvider,
|
|
261
|
+
logger,
|
|
262
|
+
operationLabel: "stat",
|
|
305
263
|
});
|
|
306
|
-
|
|
307
|
-
const isPublished = ctx?.sourceType !== "branch";
|
|
308
|
-
logger.debug("Fetching files from API", {
|
|
309
|
-
sourceType: ctx?.sourceType,
|
|
310
|
-
cacheKey,
|
|
311
|
-
});
|
|
312
|
-
|
|
313
|
-
const files = await withRetryOnTransient(
|
|
314
|
-
() =>
|
|
315
|
-
isPublished
|
|
316
|
-
? this.client.listPublishedFiles(
|
|
317
|
-
undefined,
|
|
318
|
-
ctx?.releaseId ?? undefined,
|
|
319
|
-
ctx?.environmentName ?? undefined,
|
|
320
|
-
)
|
|
321
|
-
: this.client.listAllFiles(),
|
|
322
|
-
"getAllFilesRaw (stat)",
|
|
323
|
-
);
|
|
324
|
-
|
|
325
|
-
this.cache.set(cacheKey, files);
|
|
326
|
-
return files;
|
|
327
264
|
}
|
|
328
265
|
|
|
329
266
|
private buildResolveSearchPatterns(
|
package/src/src/tool/factory.ts
CHANGED
|
@@ -179,20 +179,18 @@ export interface DynamicToolConfig {
|
|
|
179
179
|
id?: string;
|
|
180
180
|
description: string;
|
|
181
181
|
inputSchema: unknown;
|
|
182
|
+
inputSchemaJson?: JsonSchema;
|
|
182
183
|
execute: (input: unknown, context?: ToolExecutionContext) => Promise<unknown> | unknown;
|
|
183
184
|
toModelOutput?: (output: unknown) => unknown;
|
|
184
|
-
mcp?:
|
|
185
|
-
enabled?: boolean;
|
|
186
|
-
requiresAuth?: boolean;
|
|
187
|
-
cachePolicy?: "no-cache" | "cache" | "cache-first";
|
|
188
|
-
};
|
|
185
|
+
mcp?: ToolConfig["mcp"];
|
|
189
186
|
}
|
|
190
187
|
|
|
191
188
|
export function dynamicTool(config: DynamicToolConfig): Tool<unknown, unknown> {
|
|
192
189
|
const explicitId = typeof config.id === "string" && config.id.length > 0 ? config.id : undefined;
|
|
193
190
|
const id = explicitId ?? generateToolId();
|
|
194
191
|
|
|
195
|
-
const inputSchemaJson =
|
|
192
|
+
const inputSchemaJson = config.inputSchemaJson ??
|
|
193
|
+
convertSchemaToJson(config.inputSchema, id, "DYNAMIC_TOOL", true);
|
|
196
194
|
|
|
197
195
|
const createdTool: Tool<unknown, unknown> = {
|
|
198
196
|
id,
|
package/src/src/tool/index.ts
CHANGED
|
@@ -57,6 +57,11 @@ export { dynamicTool, tool } from "./factory.js";
|
|
|
57
57
|
export type { DynamicToolConfig } from "./factory.js";
|
|
58
58
|
export { createRemoteMCPToolSource } from "./remote-mcp.js";
|
|
59
59
|
export type { RemoteMCPToolSourceConfig } from "./remote-mcp.js";
|
|
60
|
+
export {
|
|
61
|
+
createToolsFromRemoteDefinitions,
|
|
62
|
+
loadRemoteToolsFromSource,
|
|
63
|
+
} from "./remote-source-tools.js";
|
|
64
|
+
export type { RemoteToolMaterializationOptions } from "./remote-source-tools.js";
|
|
60
65
|
|
|
61
66
|
export { toolRegistry } from "./registry.js";
|
|
62
67
|
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { dynamicTool } from "./factory.js";
|
|
3
|
+
import type { RemoteToolSource, Tool, ToolDefinition, ToolExecutionContext } from "./types.js";
|
|
4
|
+
|
|
5
|
+
export interface RemoteToolMaterializationOptions {
|
|
6
|
+
context?: ToolExecutionContext;
|
|
7
|
+
toolNameAliases?: Record<string, string>;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function toToolInputRecord(input: unknown): Record<string, unknown> {
|
|
11
|
+
if (typeof input !== "object" || input === null || Array.isArray(input)) {
|
|
12
|
+
return {};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return Object.fromEntries(Object.entries(input));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function createToolsFromRemoteDefinitions(
|
|
19
|
+
source: RemoteToolSource,
|
|
20
|
+
definitions: readonly ToolDefinition[],
|
|
21
|
+
options: Omit<RemoteToolMaterializationOptions, "context"> = {},
|
|
22
|
+
): Record<string, Tool<unknown, unknown>> {
|
|
23
|
+
return Object.fromEntries(
|
|
24
|
+
definitions.map((definition) => {
|
|
25
|
+
const toolName = options.toolNameAliases?.[definition.name] ?? definition.name;
|
|
26
|
+
|
|
27
|
+
return [
|
|
28
|
+
toolName,
|
|
29
|
+
dynamicTool({
|
|
30
|
+
id: toolName,
|
|
31
|
+
description: definition.description,
|
|
32
|
+
inputSchema: z.object({}).passthrough(),
|
|
33
|
+
inputSchemaJson: definition.parameters,
|
|
34
|
+
mcp: {
|
|
35
|
+
title: definition.title,
|
|
36
|
+
annotations: definition.annotations,
|
|
37
|
+
},
|
|
38
|
+
execute: async (input, context) =>
|
|
39
|
+
await source.executeTool(definition.name, toToolInputRecord(input), context),
|
|
40
|
+
}),
|
|
41
|
+
];
|
|
42
|
+
}),
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export async function loadRemoteToolsFromSource(
|
|
47
|
+
source: RemoteToolSource,
|
|
48
|
+
options: RemoteToolMaterializationOptions = {},
|
|
49
|
+
): Promise<Record<string, Tool<unknown, unknown>>> {
|
|
50
|
+
const definitions = await source.listTools(options.context);
|
|
51
|
+
return createToolsFromRemoteDefinitions(source, definitions, {
|
|
52
|
+
toolNameAliases: options.toolNameAliases,
|
|
53
|
+
});
|
|
54
|
+
}
|