@moldea.ai/adapter-cloudflare-agents 1.0.0
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/LICENSE +21 -0
- package/README.md +77 -0
- package/cover.png +0 -0
- package/dist/adapter/index.d.ts +3 -0
- package/dist/adapter/index.d.ts.map +1 -0
- package/dist/constants/index.d.ts +13 -0
- package/dist/constants/index.d.ts.map +1 -0
- package/dist/contracts/index.d.ts +159 -0
- package/dist/contracts/index.d.ts.map +1 -0
- package/dist/diagnostics/index.d.ts +28 -0
- package/dist/diagnostics/index.d.ts.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1646 -0
- package/dist/inspection/common.d.ts +19 -0
- package/dist/inspection/common.d.ts.map +1 -0
- package/dist/inspection/handoffs.d.ts +7 -0
- package/dist/inspection/handoffs.d.ts.map +1 -0
- package/dist/inspection/index.d.ts +2 -0
- package/dist/inspection/index.d.ts.map +1 -0
- package/dist/inspection/inspection.d.ts +18 -0
- package/dist/inspection/inspection.d.ts.map +1 -0
- package/dist/inspection/package-inspection.d.ts +7 -0
- package/dist/inspection/package-inspection.d.ts.map +1 -0
- package/dist/inspection/relationships.d.ts +7 -0
- package/dist/inspection/relationships.d.ts.map +1 -0
- package/dist/inspection/resolution.d.ts +20 -0
- package/dist/inspection/resolution.d.ts.map +1 -0
- package/dist/inspection/session.d.ts +5 -0
- package/dist/inspection/session.d.ts.map +1 -0
- package/dist/inspection/types.d.ts +12 -0
- package/dist/inspection/types.d.ts.map +1 -0
- package/dist/package-discovery/index.d.ts +7 -0
- package/dist/package-discovery/index.d.ts.map +1 -0
- package/dist/source-analysis/agent-tools.d.ts +5 -0
- package/dist/source-analysis/agent-tools.d.ts.map +1 -0
- package/dist/source-analysis/ai-chat-agents.d.ts +4 -0
- package/dist/source-analysis/ai-chat-agents.d.ts.map +1 -0
- package/dist/source-analysis/bindings.d.ts +14 -0
- package/dist/source-analysis/bindings.d.ts.map +1 -0
- package/dist/source-analysis/channel-tools.d.ts +4 -0
- package/dist/source-analysis/channel-tools.d.ts.map +1 -0
- package/dist/source-analysis/class-definitions.d.ts +4 -0
- package/dist/source-analysis/class-definitions.d.ts.map +1 -0
- package/dist/source-analysis/class-initialization.d.ts +4 -0
- package/dist/source-analysis/class-initialization.d.ts.map +1 -0
- package/dist/source-analysis/function-tools.d.ts +5 -0
- package/dist/source-analysis/function-tools.d.ts.map +1 -0
- package/dist/source-analysis/generation-requests.d.ts +4 -0
- package/dist/source-analysis/generation-requests.d.ts.map +1 -0
- package/dist/source-analysis/index.d.ts +14 -0
- package/dist/source-analysis/index.d.ts.map +1 -0
- package/dist/source-analysis/methods.d.ts +7 -0
- package/dist/source-analysis/methods.d.ts.map +1 -0
- package/dist/source-analysis/output-specifications.d.ts +4 -0
- package/dist/source-analysis/output-specifications.d.ts.map +1 -0
- package/dist/source-analysis/session-builders.d.ts +4 -0
- package/dist/source-analysis/session-builders.d.ts.map +1 -0
- package/dist/source-analysis/source-analysis.d.ts +5 -0
- package/dist/source-analysis/source-analysis.d.ts.map +1 -0
- package/dist/source-analysis/static-strings.d.ts +5 -0
- package/dist/source-analysis/static-strings.d.ts.map +1 -0
- package/dist/source-analysis/think-instructions.d.ts +4 -0
- package/dist/source-analysis/think-instructions.d.ts.map +1 -0
- package/dist/source-analysis/think-tools.d.ts +4 -0
- package/dist/source-analysis/think-tools.d.ts.map +1 -0
- package/dist/source-analysis/tool-maps.d.ts +5 -0
- package/dist/source-analysis/tool-maps.d.ts.map +1 -0
- package/dist/source-analysis/types.d.ts +11 -0
- package/dist/source-analysis/types.d.ts.map +1 -0
- package/package.json +60 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1646 @@
|
|
|
1
|
+
import { posix } from "node:path";
|
|
2
|
+
import { intersects, subset, validRange } from "semver";
|
|
3
|
+
import ts from "typescript";
|
|
4
|
+
import { parseRepositoryPath } from "@moldea.ai/repository";
|
|
5
|
+
//#region src/constants/index.ts
|
|
6
|
+
var CLOUDFLARE_AGENTS_ADAPTER_ID = "cloudflare-agents";
|
|
7
|
+
var CLOUDFLARE_AGENTS_PACKAGE_NAME = "agents";
|
|
8
|
+
var CLOUDFLARE_AI_CHAT_PACKAGE_NAME = "@cloudflare/ai-chat";
|
|
9
|
+
var CLOUDFLARE_THINK_PACKAGE_NAME = "@cloudflare/think";
|
|
10
|
+
var CLOUDFLARE_THINK_TARGET_ID = "typescript-think-0-16-ai-sdk-7";
|
|
11
|
+
var CLOUDFLARE_AI_CHAT_TARGET_ID = "typescript-ai-chat-agent-0-10-ai-sdk-7";
|
|
12
|
+
var CLOUDFLARE_THINK_SUPPORTED_RANGE = ">=0.16.0 <0.17.0";
|
|
13
|
+
var CLOUDFLARE_AI_CHAT_SUPPORTED_RANGE = ">=0.10.2 <0.11.0";
|
|
14
|
+
var CLOUDFLARE_AGENTS_SUPPORTED_RANGE = ">=0.21.0 <0.22.0";
|
|
15
|
+
var AI_SDK_SUPPORTED_RANGE = ">=7.0.0 <8.0.0";
|
|
16
|
+
var CLOUDFLARE_AGENTS_SUPPORTED_REPOSITORY_FORMAT_VERSIONS = Object.freeze([1]);
|
|
17
|
+
//#endregion
|
|
18
|
+
//#region ../../packages/adapter-static-analysis/dist/index.js
|
|
19
|
+
/**
|
|
20
|
+
* Creates an operation-local inspection session with deterministic promise caches.
|
|
21
|
+
* @param options Provider callbacks and the optional operation signal.
|
|
22
|
+
* @returns Cached source, package, and entry inspection functions.
|
|
23
|
+
* @throws If the inspection is aborted.
|
|
24
|
+
*/
|
|
25
|
+
var createInspectionSession = (options) => {
|
|
26
|
+
const sourceCache = /* @__PURE__ */ new Map();
|
|
27
|
+
const packageCache = /* @__PURE__ */ new Map();
|
|
28
|
+
const entryCache = /* @__PURE__ */ new Map();
|
|
29
|
+
const analyzeSource = (path) => {
|
|
30
|
+
options.signal?.throwIfAborted();
|
|
31
|
+
const existing = sourceCache.get(path);
|
|
32
|
+
if (existing !== void 0) return existing;
|
|
33
|
+
const analysis = (async () => {
|
|
34
|
+
options.signal?.throwIfAborted();
|
|
35
|
+
const bytes = await options.readFile(path, options.signal);
|
|
36
|
+
options.signal?.throwIfAborted();
|
|
37
|
+
const result = await options.analyzeSource(path, bytes, options.signal);
|
|
38
|
+
options.signal?.throwIfAborted();
|
|
39
|
+
return result;
|
|
40
|
+
})();
|
|
41
|
+
sourceCache.set(path, analysis);
|
|
42
|
+
return analysis;
|
|
43
|
+
};
|
|
44
|
+
const discoverPackage = (path) => {
|
|
45
|
+
options.signal?.throwIfAborted();
|
|
46
|
+
const existing = packageCache.get(path);
|
|
47
|
+
if (existing !== void 0) return existing;
|
|
48
|
+
const discovery = options.discoverPackage(path, options.signal);
|
|
49
|
+
packageCache.set(path, discovery);
|
|
50
|
+
return discovery;
|
|
51
|
+
};
|
|
52
|
+
const getEntry = (path) => {
|
|
53
|
+
options.signal?.throwIfAborted();
|
|
54
|
+
const existing = entryCache.get(path);
|
|
55
|
+
if (existing !== void 0) return existing;
|
|
56
|
+
const entry = options.getEntry(path, options.signal);
|
|
57
|
+
entryCache.set(path, entry);
|
|
58
|
+
return entry;
|
|
59
|
+
};
|
|
60
|
+
return Object.freeze({
|
|
61
|
+
analyzeSource,
|
|
62
|
+
discoverPackage,
|
|
63
|
+
getEntry,
|
|
64
|
+
...options.signal === void 0 ? {} : { signal: options.signal }
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
var decoder = new TextDecoder("utf-8", {
|
|
68
|
+
fatal: true,
|
|
69
|
+
ignoreBOM: true
|
|
70
|
+
});
|
|
71
|
+
var findLineIndex = (lineStarts, offset) => {
|
|
72
|
+
let lower = 0;
|
|
73
|
+
let upper = lineStarts.length - 1;
|
|
74
|
+
while (lower < upper) {
|
|
75
|
+
const middle = Math.ceil((lower + upper) / 2);
|
|
76
|
+
if ((lineStarts[middle] ?? 0) <= offset) lower = middle;
|
|
77
|
+
else upper = middle - 1;
|
|
78
|
+
}
|
|
79
|
+
return lower;
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* Creates a TypeScript UTF-16-offset to Unicode-scalar source locator.
|
|
83
|
+
* @param value The normalized valid Unicode-scalar text.
|
|
84
|
+
* @returns The scalar-aware source locator.
|
|
85
|
+
*/
|
|
86
|
+
var createSourceLocator = (value) => {
|
|
87
|
+
const scalarOffsets = new Uint32Array(value.length + 1);
|
|
88
|
+
const lineStarts = [0];
|
|
89
|
+
let scalarOffset = 0;
|
|
90
|
+
for (let codeUnitOffset = 0; codeUnitOffset < value.length;) {
|
|
91
|
+
const codePoint = value.codePointAt(codeUnitOffset);
|
|
92
|
+
const width = codePoint !== void 0 && codePoint > 65535 ? 2 : 1;
|
|
93
|
+
scalarOffsets[codeUnitOffset] = scalarOffset;
|
|
94
|
+
for (let interiorOffset = 1; interiorOffset < width; interiorOffset += 1) scalarOffsets[codeUnitOffset + interiorOffset] = scalarOffset;
|
|
95
|
+
codeUnitOffset += width;
|
|
96
|
+
scalarOffset += 1;
|
|
97
|
+
scalarOffsets[codeUnitOffset] = scalarOffset;
|
|
98
|
+
if (codePoint === 10) lineStarts.push(codeUnitOffset);
|
|
99
|
+
}
|
|
100
|
+
const locatePosition = (candidateOffset) => {
|
|
101
|
+
const codeUnitOffset = Math.max(0, Math.min(value.length, candidateOffset));
|
|
102
|
+
const lineIndex = findLineIndex(lineStarts, codeUnitOffset);
|
|
103
|
+
const lineStart = lineStarts[lineIndex] ?? 0;
|
|
104
|
+
const positionScalarOffset = scalarOffsets[codeUnitOffset] ?? 0;
|
|
105
|
+
return {
|
|
106
|
+
column: positionScalarOffset - (scalarOffsets[lineStart] ?? 0) + 1,
|
|
107
|
+
line: lineIndex + 1,
|
|
108
|
+
offset: positionScalarOffset
|
|
109
|
+
};
|
|
110
|
+
};
|
|
111
|
+
return Object.freeze({ locateRange: (startOffset, endOffset) => ({
|
|
112
|
+
end: locatePosition(endOffset),
|
|
113
|
+
start: locatePosition(startOffset)
|
|
114
|
+
}) });
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* Decodes and normalizes source bytes through the runtime-adapter text contract.
|
|
118
|
+
* @param bytes The exact reader-owned source bytes.
|
|
119
|
+
* @returns The normalized text and locator or an invalid-text result.
|
|
120
|
+
*/
|
|
121
|
+
var normalizeText = (bytes) => {
|
|
122
|
+
let decoded;
|
|
123
|
+
try {
|
|
124
|
+
decoded = decoder.decode(bytes);
|
|
125
|
+
} catch {
|
|
126
|
+
return Object.freeze({ valid: false });
|
|
127
|
+
}
|
|
128
|
+
const value = (decoded.startsWith("") ? decoded.slice(1) : decoded).replace(/\r\n?/gu, "\n");
|
|
129
|
+
if (value.includes("\0")) return Object.freeze({ valid: false });
|
|
130
|
+
return Object.freeze({
|
|
131
|
+
locator: createSourceLocator(value),
|
|
132
|
+
valid: true,
|
|
133
|
+
value
|
|
134
|
+
});
|
|
135
|
+
};
|
|
136
|
+
Object.freeze([
|
|
137
|
+
"dependencies",
|
|
138
|
+
"optionalDependencies",
|
|
139
|
+
"peerDependencies",
|
|
140
|
+
"devDependencies"
|
|
141
|
+
]);
|
|
142
|
+
/**
|
|
143
|
+
* Creates nearest-to-root package-manifest candidates for one source path.
|
|
144
|
+
* @param sourcePath The normalized source path.
|
|
145
|
+
* @returns Deterministically ordered manifest paths.
|
|
146
|
+
*/
|
|
147
|
+
var createPackageManifestCandidatePaths = (sourcePath) => {
|
|
148
|
+
const candidates = [];
|
|
149
|
+
let directory = posix.dirname(sourcePath);
|
|
150
|
+
while (true) {
|
|
151
|
+
candidates.push(posix.join(directory, "package.json"));
|
|
152
|
+
if (directory === "/") break;
|
|
153
|
+
directory = posix.dirname(directory);
|
|
154
|
+
}
|
|
155
|
+
return Object.freeze(candidates);
|
|
156
|
+
};
|
|
157
|
+
/**
|
|
158
|
+
* Removes the transparent expression wrappers supported by runtime adapters.
|
|
159
|
+
* @param expression The expression to normalize.
|
|
160
|
+
* @returns The underlying expression used by static matching.
|
|
161
|
+
*/
|
|
162
|
+
var unwrapExpression = (expression) => {
|
|
163
|
+
let current = expression;
|
|
164
|
+
while (ts.isAsExpression(current) || ts.isParenthesizedExpression(current) || ts.isSatisfiesExpression(current)) current = current.expression;
|
|
165
|
+
return current;
|
|
166
|
+
};
|
|
167
|
+
/**
|
|
168
|
+
* Resolves one direct call with an optional outer `await` wrapper.
|
|
169
|
+
* @param expression The candidate call expression.
|
|
170
|
+
* @returns The direct call or `null` when the form is unsupported.
|
|
171
|
+
*/
|
|
172
|
+
var getDirectCall = (expression) => {
|
|
173
|
+
const unwrapped = unwrapExpression(expression);
|
|
174
|
+
const candidate = ts.isAwaitExpression(unwrapped) ? unwrapExpression(unwrapped.expression) : unwrapped;
|
|
175
|
+
return ts.isCallExpression(candidate) ? candidate : null;
|
|
176
|
+
};
|
|
177
|
+
var getStaticPropertyName = (name) => {
|
|
178
|
+
if (ts.isIdentifier(name) || ts.isStringLiteral(name)) return name.text;
|
|
179
|
+
return null;
|
|
180
|
+
};
|
|
181
|
+
/**
|
|
182
|
+
* Indexes a closed object literal with exact identifier or string-literal keys.
|
|
183
|
+
* @param objectLiteral The candidate closed object.
|
|
184
|
+
* @returns Exact property expressions or `null` for dynamic or duplicate members.
|
|
185
|
+
*/
|
|
186
|
+
var getClosedObjectProperties = (objectLiteral) => {
|
|
187
|
+
const properties = /* @__PURE__ */ new Map();
|
|
188
|
+
for (const property of objectLiteral.properties) {
|
|
189
|
+
if (!ts.isPropertyAssignment(property) && !ts.isShorthandPropertyAssignment(property)) return null;
|
|
190
|
+
const propertyName = getStaticPropertyName(property.name);
|
|
191
|
+
if (propertyName === null || properties.has(propertyName)) return null;
|
|
192
|
+
properties.set(propertyName, unwrapExpression(ts.isPropertyAssignment(property) ? property.initializer : property.name));
|
|
193
|
+
}
|
|
194
|
+
return properties;
|
|
195
|
+
};
|
|
196
|
+
/**
|
|
197
|
+
* Reads an exact static string literal from one expression.
|
|
198
|
+
* @param expression The candidate string expression.
|
|
199
|
+
* @returns Its exact value or `null` when dynamic.
|
|
200
|
+
*/
|
|
201
|
+
var getStaticString = (expression) => {
|
|
202
|
+
if (expression === null || expression === void 0) return null;
|
|
203
|
+
const candidate = unwrapExpression(expression);
|
|
204
|
+
return ts.isStringLiteral(candidate) || ts.isNoSubstitutionTemplateLiteral(candidate) ? candidate.text : null;
|
|
205
|
+
};
|
|
206
|
+
/**
|
|
207
|
+
* Determines whether a JSON-like expression is fully static.
|
|
208
|
+
* @param expression The candidate schema or literal value.
|
|
209
|
+
* @returns Whether every nested value is statically represented.
|
|
210
|
+
*/
|
|
211
|
+
var isStaticLiteralValue = (expression) => {
|
|
212
|
+
const candidate = unwrapExpression(expression);
|
|
213
|
+
if (ts.isStringLiteral(candidate) || ts.isNoSubstitutionTemplateLiteral(candidate) || ts.isNumericLiteral(candidate) || candidate.kind === ts.SyntaxKind.TrueKeyword || candidate.kind === ts.SyntaxKind.FalseKeyword || candidate.kind === ts.SyntaxKind.NullKeyword) return true;
|
|
214
|
+
if (ts.isPrefixUnaryExpression(candidate) && (candidate.operator === ts.SyntaxKind.PlusToken || candidate.operator === ts.SyntaxKind.MinusToken) && ts.isNumericLiteral(candidate.operand)) return true;
|
|
215
|
+
if (ts.isArrayLiteralExpression(candidate)) return candidate.elements.every((element) => !ts.isOmittedExpression(element) && !ts.isSpreadElement(element) && isStaticLiteralValue(element));
|
|
216
|
+
if (!ts.isObjectLiteralExpression(candidate)) return false;
|
|
217
|
+
const properties = getClosedObjectProperties(candidate);
|
|
218
|
+
return properties !== null && [...properties.values()].every((property) => isStaticLiteralValue(property));
|
|
219
|
+
};
|
|
220
|
+
var hasModifier = (node, kind) => ts.canHaveModifiers(node) && (ts.getModifiers(node)?.some((modifier) => modifier.kind === kind) ?? false);
|
|
221
|
+
var isConstDeclarationList = (declarationList) => (declarationList.flags & ts.NodeFlags.Const) !== 0;
|
|
222
|
+
/**
|
|
223
|
+
* Indexes static value imports and supported SDK constructor imports.
|
|
224
|
+
* @param sourceFile The parsed TypeScript source.
|
|
225
|
+
* @param config The provider package and constructor import forms.
|
|
226
|
+
* @returns Module-owned import bindings needed by static checks.
|
|
227
|
+
*/
|
|
228
|
+
var indexImports = (sourceFile, config) => {
|
|
229
|
+
const constructorNames = /* @__PURE__ */ new Set();
|
|
230
|
+
const namedImports = /* @__PURE__ */ new Map();
|
|
231
|
+
const supportedNamedImports = new Set(config.namedConstructorImports);
|
|
232
|
+
for (const statement of sourceFile.statements) {
|
|
233
|
+
if (!ts.isImportDeclaration(statement) || !ts.isStringLiteral(statement.moduleSpecifier)) continue;
|
|
234
|
+
const importClause = statement.importClause;
|
|
235
|
+
if (importClause?.isTypeOnly === true) continue;
|
|
236
|
+
const moduleSpecifier = statement.moduleSpecifier.text;
|
|
237
|
+
if (moduleSpecifier === config.packageName && config.supportsDefaultConstructorImport && importClause?.name !== void 0) constructorNames.add(importClause.name.text);
|
|
238
|
+
if (moduleSpecifier === config.packageName && importClause?.namedBindings !== void 0 && ts.isNamedImports(importClause.namedBindings)) for (const element of importClause.namedBindings.elements) {
|
|
239
|
+
const importedName = element.propertyName?.text ?? element.name.text;
|
|
240
|
+
if (!element.isTypeOnly && supportedNamedImports.has(importedName)) constructorNames.add(element.name.text);
|
|
241
|
+
}
|
|
242
|
+
if (!moduleSpecifier.startsWith(".") || importClause?.namedBindings === void 0 || !ts.isNamedImports(importClause.namedBindings)) continue;
|
|
243
|
+
for (const element of importClause.namedBindings.elements) {
|
|
244
|
+
if (element.isTypeOnly) continue;
|
|
245
|
+
namedImports.set(element.name.text, Object.freeze({
|
|
246
|
+
importedName: element.propertyName?.text ?? element.name.text,
|
|
247
|
+
moduleSpecifier
|
|
248
|
+
}));
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return {
|
|
252
|
+
constructorNames,
|
|
253
|
+
namedImports
|
|
254
|
+
};
|
|
255
|
+
};
|
|
256
|
+
/**
|
|
257
|
+
* Indexes direct exports, module-level SDK clients, and constant arrays.
|
|
258
|
+
* @param sourceFile The parsed TypeScript source.
|
|
259
|
+
* @param constructorNames The supported constructor bindings.
|
|
260
|
+
* @returns Static module declarations used by adapter inspection.
|
|
261
|
+
*/
|
|
262
|
+
var indexModuleDeclarations = (sourceFile, constructorNames) => {
|
|
263
|
+
const clientNames = /* @__PURE__ */ new Set();
|
|
264
|
+
const exports = /* @__PURE__ */ new Map();
|
|
265
|
+
const moduleArrays = /* @__PURE__ */ new Map();
|
|
266
|
+
const moduleConstDeclarations = /* @__PURE__ */ new Map();
|
|
267
|
+
for (const statement of sourceFile.statements) {
|
|
268
|
+
if (ts.isFunctionDeclaration(statement) && statement.name !== void 0) {
|
|
269
|
+
if (hasModifier(statement, ts.SyntaxKind.ExportKeyword)) exports.set(statement.name.text, Object.freeze({
|
|
270
|
+
declaration: statement,
|
|
271
|
+
kind: statement.body === void 0 || hasModifier(statement, ts.SyntaxKind.DefaultKeyword) ? "present-unsupported" : "present-supported"
|
|
272
|
+
}));
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
if (ts.isExportDeclaration(statement) && statement.exportClause !== void 0) {
|
|
276
|
+
if (!ts.isNamedExports(statement.exportClause) || statement.isTypeOnly) continue;
|
|
277
|
+
for (const element of statement.exportClause.elements) if (!element.isTypeOnly) exports.set(element.name.text, Object.freeze({
|
|
278
|
+
declaration: element,
|
|
279
|
+
kind: "present-unsupported"
|
|
280
|
+
}));
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
if (!ts.isVariableStatement(statement)) {
|
|
284
|
+
if (hasModifier(statement, ts.SyntaxKind.ExportKeyword) && (ts.isClassDeclaration(statement) || ts.isEnumDeclaration(statement) || ts.isModuleDeclaration(statement)) && statement.name !== void 0 && ts.isIdentifier(statement.name)) exports.set(statement.name.text, Object.freeze({
|
|
285
|
+
declaration: statement,
|
|
286
|
+
kind: "present-unsupported"
|
|
287
|
+
}));
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
const isConst = isConstDeclarationList(statement.declarationList);
|
|
291
|
+
const isExported = hasModifier(statement, ts.SyntaxKind.ExportKeyword);
|
|
292
|
+
for (const declaration of statement.declarationList.declarations) {
|
|
293
|
+
if (!ts.isIdentifier(declaration.name)) continue;
|
|
294
|
+
if (isExported) exports.set(declaration.name.text, Object.freeze({
|
|
295
|
+
declaration,
|
|
296
|
+
kind: isConst && declaration.initializer !== void 0 ? "present-supported" : "present-unsupported"
|
|
297
|
+
}));
|
|
298
|
+
if (!isConst || declaration.initializer === void 0) continue;
|
|
299
|
+
moduleConstDeclarations.set(declaration.name.text, declaration);
|
|
300
|
+
const initializer = unwrapExpression(declaration.initializer);
|
|
301
|
+
if (ts.isNewExpression(initializer)) {
|
|
302
|
+
const constructor = unwrapExpression(initializer.expression);
|
|
303
|
+
if (ts.isIdentifier(constructor) && constructorNames.has(constructor.text)) clientNames.add(declaration.name.text);
|
|
304
|
+
}
|
|
305
|
+
if (ts.isArrayLiteralExpression(initializer)) moduleArrays.set(declaration.name.text, Object.freeze({
|
|
306
|
+
declaration,
|
|
307
|
+
expression: initializer
|
|
308
|
+
}));
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
return {
|
|
312
|
+
clientNames,
|
|
313
|
+
exports,
|
|
314
|
+
moduleArrays,
|
|
315
|
+
moduleConstDeclarations
|
|
316
|
+
};
|
|
317
|
+
};
|
|
318
|
+
var addBindingNames = (names, bindingName) => {
|
|
319
|
+
if (ts.isIdentifier(bindingName)) {
|
|
320
|
+
names.add(bindingName.text);
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
for (const element of bindingName.elements) if (!ts.isOmittedExpression(element)) addBindingNames(names, element.name);
|
|
324
|
+
};
|
|
325
|
+
var addVariableDeclarationListBindings = (names, declarationList) => {
|
|
326
|
+
for (const declaration of declarationList.declarations) addBindingNames(names, declaration.name);
|
|
327
|
+
};
|
|
328
|
+
var addStatementBindings = (names, statement) => {
|
|
329
|
+
if (ts.isVariableStatement(statement)) {
|
|
330
|
+
addVariableDeclarationListBindings(names, statement.declarationList);
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
if (ts.isFunctionDeclaration(statement) || ts.isClassDeclaration(statement) || ts.isEnumDeclaration(statement) || ts.isModuleDeclaration(statement)) {
|
|
334
|
+
if (statement.name !== void 0 && ts.isIdentifier(statement.name)) names.add(statement.name.text);
|
|
335
|
+
}
|
|
336
|
+
};
|
|
337
|
+
var isFunctionScope = (node) => ts.isArrowFunction(node) || ts.isConstructorDeclaration(node) || ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node) || ts.isGetAccessorDeclaration(node) || ts.isMethodDeclaration(node) || ts.isSetAccessorDeclaration(node);
|
|
338
|
+
var getLocalBindingNames = (bindings, scope) => {
|
|
339
|
+
const existingNames = bindings.get(scope);
|
|
340
|
+
if (existingNames !== void 0) return existingNames;
|
|
341
|
+
const names = /* @__PURE__ */ new Set();
|
|
342
|
+
bindings.set(scope, names);
|
|
343
|
+
return names;
|
|
344
|
+
};
|
|
345
|
+
/**
|
|
346
|
+
* Indexes local runtime bindings that can shadow module-owned identifiers.
|
|
347
|
+
* @param sourceFile The parsed TypeScript source.
|
|
348
|
+
* @returns Local binding names keyed by lexical or function scope.
|
|
349
|
+
*/
|
|
350
|
+
var indexLocalBindingNames = (sourceFile) => {
|
|
351
|
+
const bindings = /* @__PURE__ */ new Map();
|
|
352
|
+
const visit = (node, functionScope) => {
|
|
353
|
+
let childFunctionScope = functionScope;
|
|
354
|
+
if (isFunctionScope(node)) {
|
|
355
|
+
const names = getLocalBindingNames(bindings, node);
|
|
356
|
+
for (const parameter of node.parameters) addBindingNames(names, parameter.name);
|
|
357
|
+
if (node.name !== void 0 && ts.isIdentifier(node.name)) names.add(node.name.text);
|
|
358
|
+
childFunctionScope = node;
|
|
359
|
+
}
|
|
360
|
+
if (ts.isBlock(node) || ts.isModuleBlock(node)) {
|
|
361
|
+
const names = getLocalBindingNames(bindings, node);
|
|
362
|
+
for (const statement of node.statements) addStatementBindings(names, statement);
|
|
363
|
+
} else if (ts.isCaseBlock(node)) {
|
|
364
|
+
const names = getLocalBindingNames(bindings, node);
|
|
365
|
+
for (const clause of node.clauses) for (const statement of clause.statements) addStatementBindings(names, statement);
|
|
366
|
+
} else if (ts.isCatchClause(node) && node.variableDeclaration !== void 0) addBindingNames(getLocalBindingNames(bindings, node), node.variableDeclaration.name);
|
|
367
|
+
else if ((ts.isForStatement(node) || ts.isForInStatement(node) || ts.isForOfStatement(node)) && node.initializer !== void 0 && ts.isVariableDeclarationList(node.initializer)) addVariableDeclarationListBindings(getLocalBindingNames(bindings, node), node.initializer);
|
|
368
|
+
else if (ts.isClassExpression(node) && node.name !== void 0) getLocalBindingNames(bindings, node).add(node.name.text);
|
|
369
|
+
if (childFunctionScope !== null && ts.isVariableDeclarationList(node) && (node.flags & ts.NodeFlags.BlockScoped) === 0) addVariableDeclarationListBindings(getLocalBindingNames(bindings, childFunctionScope), node);
|
|
370
|
+
ts.forEachChild(node, (child) => visit(child, childFunctionScope));
|
|
371
|
+
};
|
|
372
|
+
visit(sourceFile, null);
|
|
373
|
+
return bindings;
|
|
374
|
+
};
|
|
375
|
+
/**
|
|
376
|
+
* Indexes identifier occurrences once for binding-specific safety analysis.
|
|
377
|
+
* @param sourceFile The parsed TypeScript source.
|
|
378
|
+
* @returns Identifier occurrences grouped by exact source spelling.
|
|
379
|
+
*/
|
|
380
|
+
var indexIdentifierUses = (sourceFile) => {
|
|
381
|
+
const identifierUses = /* @__PURE__ */ new Map();
|
|
382
|
+
const visit = (node) => {
|
|
383
|
+
if (ts.isIdentifier(node)) {
|
|
384
|
+
const uses = identifierUses.get(node.text) ?? [];
|
|
385
|
+
uses.push(node);
|
|
386
|
+
identifierUses.set(node.text, uses);
|
|
387
|
+
}
|
|
388
|
+
ts.forEachChild(node, visit);
|
|
389
|
+
};
|
|
390
|
+
visit(sourceFile);
|
|
391
|
+
return new Map([...identifierUses].map(([name, uses]) => [name, Object.freeze(uses)]));
|
|
392
|
+
};
|
|
393
|
+
/**
|
|
394
|
+
* Determines whether a module-bound name is visible at one identifier use.
|
|
395
|
+
* @param identifier The identifier whose lexical environment is inspected.
|
|
396
|
+
* @param analysis The indexed source containing the identifier.
|
|
397
|
+
* @returns Whether no parameter or local declaration shadows the module binding.
|
|
398
|
+
*/
|
|
399
|
+
var isModuleBindingVisible = (identifier, analysis) => {
|
|
400
|
+
let current = identifier.parent;
|
|
401
|
+
while (current !== void 0 && !ts.isSourceFile(current)) {
|
|
402
|
+
if (analysis.localBindingNames.get(current)?.has(identifier.text) === true) return false;
|
|
403
|
+
current = current.parent;
|
|
404
|
+
}
|
|
405
|
+
return true;
|
|
406
|
+
};
|
|
407
|
+
/**
|
|
408
|
+
* Resolves TypeScript source candidates for a supported relative ESM specifier.
|
|
409
|
+
* @param containingPath The importing source path.
|
|
410
|
+
* @param moduleSpecifier The exact relative ESM specifier.
|
|
411
|
+
* @returns Supported logical source candidates in deterministic order.
|
|
412
|
+
*/
|
|
413
|
+
var resolveImportCandidatePaths = (containingPath, moduleSpecifier) => {
|
|
414
|
+
const resolved = posix.resolve(posix.dirname(containingPath), moduleSpecifier);
|
|
415
|
+
if (resolved.endsWith(".js")) return [`${resolved.slice(0, -3)}.ts`, `${resolved.slice(0, -3)}.tsx`];
|
|
416
|
+
if (resolved.endsWith(".mjs")) return [`${resolved.slice(0, -4)}.mts`];
|
|
417
|
+
return [
|
|
418
|
+
".ts",
|
|
419
|
+
".tsx",
|
|
420
|
+
".mts"
|
|
421
|
+
].some((extension) => resolved.endsWith(extension)) ? [resolved] : [];
|
|
422
|
+
};
|
|
423
|
+
/**
|
|
424
|
+
* Resolves the explicit module references an identifier can denote.
|
|
425
|
+
* @param identifier The local source identifier.
|
|
426
|
+
* @param analysis The source containing that identifier.
|
|
427
|
+
* @returns Same-file or relative-import candidates in deterministic order.
|
|
428
|
+
*/
|
|
429
|
+
var resolveBindingReferences = (identifier, analysis) => {
|
|
430
|
+
if (!isModuleBindingVisible(identifier, analysis)) return [];
|
|
431
|
+
const references = [];
|
|
432
|
+
if (analysis.exports.has(identifier.text)) references.push(Object.freeze({
|
|
433
|
+
path: analysis.path,
|
|
434
|
+
symbol: identifier.text
|
|
435
|
+
}));
|
|
436
|
+
const namedImport = analysis.namedImports.get(identifier.text);
|
|
437
|
+
if (namedImport !== void 0) references.push(...resolveImportCandidatePaths(analysis.path, namedImport.moduleSpecifier).map((path) => Object.freeze({
|
|
438
|
+
path,
|
|
439
|
+
symbol: namedImport.importedName
|
|
440
|
+
})));
|
|
441
|
+
return references;
|
|
442
|
+
};
|
|
443
|
+
/**
|
|
444
|
+
* Checks whether an identifier resolves directly to an explicit bound reference.
|
|
445
|
+
* @param identifier The local source identifier.
|
|
446
|
+
* @param analysis The source containing that identifier.
|
|
447
|
+
* @param reference The explicit source binding to match.
|
|
448
|
+
* @returns Whether local or named-import identity proves the relationship.
|
|
449
|
+
*/
|
|
450
|
+
var isBoundIdentifier = (identifier, analysis, reference) => {
|
|
451
|
+
if (reference.symbol === void 0) return false;
|
|
452
|
+
return resolveBindingReferences(identifier, analysis).some((candidate) => candidate.path === reference.path && candidate.symbol === reference.symbol);
|
|
453
|
+
};
|
|
454
|
+
var getScriptKind = (path) => path.endsWith(".tsx") ? ts.ScriptKind.TSX : ts.ScriptKind.TS;
|
|
455
|
+
var createSyntaxProgram = (sourceFile, text) => {
|
|
456
|
+
return ts.createProgram({
|
|
457
|
+
host: {
|
|
458
|
+
fileExists: (fileName) => fileName === sourceFile.fileName,
|
|
459
|
+
getCanonicalFileName: (fileName) => fileName,
|
|
460
|
+
getCurrentDirectory: () => "/",
|
|
461
|
+
getDefaultLibFileName: () => "/lib.d.ts",
|
|
462
|
+
getDirectories: () => [],
|
|
463
|
+
getNewLine: () => "\n",
|
|
464
|
+
getSourceFile: (fileName) => fileName === sourceFile.fileName ? sourceFile : void 0,
|
|
465
|
+
readFile: (fileName) => fileName === sourceFile.fileName ? text : void 0,
|
|
466
|
+
useCaseSensitiveFileNames: () => true,
|
|
467
|
+
writeFile: () => void 0
|
|
468
|
+
},
|
|
469
|
+
options: {
|
|
470
|
+
jsx: ts.JsxEmit.Preserve,
|
|
471
|
+
module: ts.ModuleKind.ESNext,
|
|
472
|
+
noLib: true,
|
|
473
|
+
noResolve: true,
|
|
474
|
+
target: ts.ScriptTarget.ES2023
|
|
475
|
+
},
|
|
476
|
+
rootNames: [sourceFile.fileName]
|
|
477
|
+
});
|
|
478
|
+
};
|
|
479
|
+
/**
|
|
480
|
+
* Parses and indexes one TypeScript module without provider request assumptions.
|
|
481
|
+
* @param path The normalized logical source path.
|
|
482
|
+
* @param bytes The exact source bytes returned by the adapter reader.
|
|
483
|
+
* @param importConfig The provider constructor-import contract.
|
|
484
|
+
* @param signal The active inspection signal.
|
|
485
|
+
* @returns A source analysis or stable invalid-text or invalid-syntax result.
|
|
486
|
+
* @throws If source analysis is aborted.
|
|
487
|
+
*/
|
|
488
|
+
var analyzeTypeScriptModule = (path, bytes, importConfig, signal) => {
|
|
489
|
+
signal?.throwIfAborted();
|
|
490
|
+
const text = normalizeText(bytes);
|
|
491
|
+
if (!text.valid) return Object.freeze({ kind: "invalid-text" });
|
|
492
|
+
signal?.throwIfAborted();
|
|
493
|
+
const sourceFile = ts.createSourceFile(path, text.value, ts.ScriptTarget.ES2023, true, getScriptKind(path));
|
|
494
|
+
const syntaxDiagnostic = createSyntaxProgram(sourceFile, text.value).getSyntacticDiagnostics(sourceFile).filter(({ category }) => category === ts.DiagnosticCategory.Error).sort((left, right) => (left.start ?? 0) - (right.start ?? 0))[0];
|
|
495
|
+
signal?.throwIfAborted();
|
|
496
|
+
if (syntaxDiagnostic !== void 0) {
|
|
497
|
+
const start = syntaxDiagnostic.start;
|
|
498
|
+
return Object.freeze({
|
|
499
|
+
kind: "invalid-syntax",
|
|
500
|
+
range: start === void 0 ? null : text.locator.locateRange(start, start + (syntaxDiagnostic.length ?? 0))
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
const { constructorNames, namedImports } = indexImports(sourceFile, importConfig);
|
|
504
|
+
signal?.throwIfAborted();
|
|
505
|
+
const { clientNames, exports, moduleArrays, moduleConstDeclarations } = indexModuleDeclarations(sourceFile, constructorNames);
|
|
506
|
+
signal?.throwIfAborted();
|
|
507
|
+
const identifierUses = indexIdentifierUses(sourceFile);
|
|
508
|
+
signal?.throwIfAborted();
|
|
509
|
+
const localBindingNames = indexLocalBindingNames(sourceFile);
|
|
510
|
+
signal?.throwIfAborted();
|
|
511
|
+
const analysis = Object.freeze({
|
|
512
|
+
clientNames,
|
|
513
|
+
constructorNames,
|
|
514
|
+
exports,
|
|
515
|
+
identifierUses,
|
|
516
|
+
localBindingNames,
|
|
517
|
+
moduleArrays,
|
|
518
|
+
moduleConstDeclarations,
|
|
519
|
+
namedImports,
|
|
520
|
+
path,
|
|
521
|
+
safeModuleArrayNames: /* @__PURE__ */ new Set(),
|
|
522
|
+
sourceFile,
|
|
523
|
+
text
|
|
524
|
+
});
|
|
525
|
+
signal?.throwIfAborted();
|
|
526
|
+
return Object.freeze({
|
|
527
|
+
analysis,
|
|
528
|
+
kind: "valid"
|
|
529
|
+
});
|
|
530
|
+
};
|
|
531
|
+
/**
|
|
532
|
+
* Determines whether a path uses a supported TypeScript source extension.
|
|
533
|
+
* @param path The bound source path.
|
|
534
|
+
* @returns Whether its extension is supported.
|
|
535
|
+
*/
|
|
536
|
+
var isSupportedTypeScriptSourcePath = (path) => [
|
|
537
|
+
".ts",
|
|
538
|
+
".tsx",
|
|
539
|
+
".mts"
|
|
540
|
+
].some((extension) => path.endsWith(extension));
|
|
541
|
+
//#endregion
|
|
542
|
+
//#region src/source-analysis/source-analysis.ts
|
|
543
|
+
var IMPORT_CONFIG = Object.freeze({
|
|
544
|
+
namedConstructorImports: ["Think"],
|
|
545
|
+
packageName: CLOUDFLARE_THINK_PACKAGE_NAME,
|
|
546
|
+
supportsDefaultConstructorImport: false
|
|
547
|
+
});
|
|
548
|
+
var indexCloudflareAgentsImports = (sourceFile) => {
|
|
549
|
+
const imports = {
|
|
550
|
+
agentToolNames: /* @__PURE__ */ new Set(),
|
|
551
|
+
aiChatAgentNames: /* @__PURE__ */ new Set(),
|
|
552
|
+
generateTextNames: /* @__PURE__ */ new Set(),
|
|
553
|
+
outputNames: /* @__PURE__ */ new Set(),
|
|
554
|
+
streamTextNames: /* @__PURE__ */ new Set(),
|
|
555
|
+
thinkNames: /* @__PURE__ */ new Set(),
|
|
556
|
+
toolNames: /* @__PURE__ */ new Set()
|
|
557
|
+
};
|
|
558
|
+
for (const statement of sourceFile.statements) {
|
|
559
|
+
if (!ts.isImportDeclaration(statement) || !ts.isStringLiteral(statement.moduleSpecifier) || statement.importClause?.isTypeOnly === true || statement.importClause?.namedBindings === void 0 || !ts.isNamedImports(statement.importClause.namedBindings)) continue;
|
|
560
|
+
for (const element of statement.importClause.namedBindings.elements) {
|
|
561
|
+
const importedName = element.propertyName?.text ?? element.name.text;
|
|
562
|
+
if (element.isTypeOnly) continue;
|
|
563
|
+
if (statement.moduleSpecifier.text === "@cloudflare/ai-chat" && importedName === "AIChatAgent") imports.aiChatAgentNames.add(element.name.text);
|
|
564
|
+
else if (statement.moduleSpecifier.text === "@cloudflare/think" && importedName === "Think") imports.thinkNames.add(element.name.text);
|
|
565
|
+
else if (statement.moduleSpecifier.text === "agents/agent-tools" && importedName === "agentTool") imports.agentToolNames.add(element.name.text);
|
|
566
|
+
else if (statement.moduleSpecifier.text === "ai") {
|
|
567
|
+
if (importedName === "generateText") imports.generateTextNames.add(element.name.text);
|
|
568
|
+
if (importedName === "Output") imports.outputNames.add(element.name.text);
|
|
569
|
+
if (importedName === "streamText") imports.streamTextNames.add(element.name.text);
|
|
570
|
+
if (importedName === "tool") imports.toolNames.add(element.name.text);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
return Object.freeze(imports);
|
|
575
|
+
};
|
|
576
|
+
/** Parses and indexes one Cloudflare Agents TypeScript module without executing it. */
|
|
577
|
+
var analyzeCloudflareAgentsSource = (path, bytes, signal) => {
|
|
578
|
+
const result = analyzeTypeScriptModule(path, bytes, IMPORT_CONFIG, signal);
|
|
579
|
+
if (result.kind !== "valid") return result;
|
|
580
|
+
const analysis = Object.freeze({
|
|
581
|
+
...result.analysis,
|
|
582
|
+
imports: indexCloudflareAgentsImports(result.analysis.sourceFile),
|
|
583
|
+
path
|
|
584
|
+
});
|
|
585
|
+
return Object.freeze({
|
|
586
|
+
analysis,
|
|
587
|
+
kind: "valid"
|
|
588
|
+
});
|
|
589
|
+
};
|
|
590
|
+
//#endregion
|
|
591
|
+
//#region src/source-analysis/class-initialization.ts
|
|
592
|
+
var hasDecorators = (node) => ts.canHaveDecorators(node) && (ts.getDecorators(node)?.length ?? 0) > 0;
|
|
593
|
+
var hasStaticModifier = (node) => ts.canHaveModifiers(node) && (ts.getModifiers(node)?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword) ?? false);
|
|
594
|
+
var isSimpleParameter = (parameter) => ts.isIdentifier(parameter.name) && parameter.dotDotDotToken === void 0 && parameter.initializer === void 0 && parameter.questionToken === void 0 && (parameter.modifiers?.length ?? 0) === 0 && !hasDecorators(parameter);
|
|
595
|
+
var isPassThroughConstructor = (constructor) => {
|
|
596
|
+
if (constructor.body === void 0 || constructor.parameters.length !== 2 || !constructor.parameters.every(isSimpleParameter) || constructor.body.statements.length !== 1) return false;
|
|
597
|
+
const statement = constructor.body.statements[0];
|
|
598
|
+
if (statement === void 0 || !ts.isExpressionStatement(statement)) return false;
|
|
599
|
+
const expression = unwrapExpression(statement.expression);
|
|
600
|
+
return ts.isCallExpression(expression) && expression.expression.kind === ts.SyntaxKind.SuperKeyword && expression.arguments.length === 2 && expression.arguments.every((argument, index) => ts.isIdentifier(unwrapExpression(argument)) && unwrapExpression(argument).text === (constructor.parameters[index]?.name).text);
|
|
601
|
+
};
|
|
602
|
+
/** Determines whether the class initialization surface is closed and side-effect free. */
|
|
603
|
+
var isCloudflareAgentsClassInitializationSupported = (declaration) => {
|
|
604
|
+
if (hasDecorators(declaration)) return false;
|
|
605
|
+
let constructorCount = 0;
|
|
606
|
+
for (const member of declaration.members) {
|
|
607
|
+
if (hasDecorators(member)) return false;
|
|
608
|
+
if (ts.isConstructorDeclaration(member)) {
|
|
609
|
+
constructorCount += 1;
|
|
610
|
+
if (constructorCount > 1 || !isPassThroughConstructor(member)) return false;
|
|
611
|
+
continue;
|
|
612
|
+
}
|
|
613
|
+
if (ts.isMethodDeclaration(member)) {
|
|
614
|
+
if (member.asteriskToken !== void 0 || ts.isComputedPropertyName(member.name) || member.parameters.some((parameter) => hasDecorators(parameter))) return false;
|
|
615
|
+
continue;
|
|
616
|
+
}
|
|
617
|
+
if (ts.isPropertyDeclaration(member)) {
|
|
618
|
+
if (ts.isComputedPropertyName(member.name) || hasStaticModifier(member) || member.initializer === void 0 || !isStaticLiteralValue(member.initializer)) return false;
|
|
619
|
+
continue;
|
|
620
|
+
}
|
|
621
|
+
return false;
|
|
622
|
+
}
|
|
623
|
+
return true;
|
|
624
|
+
};
|
|
625
|
+
//#endregion
|
|
626
|
+
//#region src/source-analysis/bindings.ts
|
|
627
|
+
/** Returns an exact supported object or class member name. */
|
|
628
|
+
var getCloudflareAgentsPropertyName = (name) => ts.isIdentifier(name) || ts.isStringLiteral(name) ? name.text : null;
|
|
629
|
+
/** Determines whether an object uses JavaScript's non-own `__proto__` setter form. */
|
|
630
|
+
var hasCloudflareAgentsPrototypeSetter = (object) => object.properties.some((property) => ts.isPropertyAssignment(property) && !ts.isComputedPropertyName(property.name) && getCloudflareAgentsPropertyName(property.name) === "__proto__");
|
|
631
|
+
/** Classifies exact fields in one closed or partially unrelated object literal. */
|
|
632
|
+
var analyzeCloudflareAgentsObjectRelationships = (object, names) => {
|
|
633
|
+
const relationships = Object.fromEntries(names.map((name) => [name, { kind: "absent" }]));
|
|
634
|
+
const relationshipNames = new Set(names);
|
|
635
|
+
const markAllUnresolved = () => {
|
|
636
|
+
for (const name of names) relationships[name] = { kind: "unresolved" };
|
|
637
|
+
};
|
|
638
|
+
if (hasCloudflareAgentsPrototypeSetter(object)) {
|
|
639
|
+
markAllUnresolved();
|
|
640
|
+
return relationships;
|
|
641
|
+
}
|
|
642
|
+
for (const property of object.properties) {
|
|
643
|
+
if (ts.isSpreadAssignment(property) || ts.isComputedPropertyName(property.name)) {
|
|
644
|
+
markAllUnresolved();
|
|
645
|
+
continue;
|
|
646
|
+
}
|
|
647
|
+
const propertyName = getCloudflareAgentsPropertyName(property.name);
|
|
648
|
+
if (propertyName === null || !relationshipNames.has(propertyName)) continue;
|
|
649
|
+
const name = propertyName;
|
|
650
|
+
if (relationships[name].kind !== "absent") relationships[name] = { kind: "unresolved" };
|
|
651
|
+
else if (ts.isPropertyAssignment(property)) relationships[name] = {
|
|
652
|
+
expression: unwrapExpression(property.initializer),
|
|
653
|
+
kind: "present"
|
|
654
|
+
};
|
|
655
|
+
else if (ts.isShorthandPropertyAssignment(property)) relationships[name] = {
|
|
656
|
+
expression: property.name,
|
|
657
|
+
kind: "present"
|
|
658
|
+
};
|
|
659
|
+
else relationships[name] = { kind: "unresolved" };
|
|
660
|
+
}
|
|
661
|
+
return relationships;
|
|
662
|
+
};
|
|
663
|
+
/** Classifies a direct relationship to one explicitly bound runtime symbol. */
|
|
664
|
+
var classifyCloudflareAgentsDirectBinding = (relationship, analysis, reference) => {
|
|
665
|
+
if (relationship.kind === "absent") return false;
|
|
666
|
+
if (relationship.kind === "unresolved" || reference.symbol === void 0) return null;
|
|
667
|
+
const candidate = unwrapExpression(relationship.expression);
|
|
668
|
+
if (!ts.isIdentifier(candidate) || !isModuleBindingVisible(candidate, analysis)) return ts.isStringLiteral(candidate) || ts.isNoSubstitutionTemplateLiteral(candidate) || ts.isNumericLiteral(candidate) || ts.isObjectLiteralExpression(candidate) || ts.isArrayLiteralExpression(candidate) || ts.isArrowFunction(candidate) || ts.isFunctionExpression(candidate) || ts.isClassExpression(candidate) || candidate.kind === ts.SyntaxKind.NullKeyword || candidate.kind === ts.SyntaxKind.TrueKeyword || candidate.kind === ts.SyntaxKind.FalseKeyword ? false : null;
|
|
669
|
+
if (isBoundIdentifier(candidate, analysis, reference)) return true;
|
|
670
|
+
return resolveBindingReferences(candidate, analysis).length > 0 ? false : null;
|
|
671
|
+
};
|
|
672
|
+
/** Classifies a required direct or awaited instruction-loader call. */
|
|
673
|
+
var classifyCloudflareAgentsInstructionLoader = (relationship, analysis, reference) => {
|
|
674
|
+
if (relationship.kind === "absent") return false;
|
|
675
|
+
if (relationship.kind === "unresolved" || reference.symbol === void 0) return null;
|
|
676
|
+
const call = getDirectCall(relationship.expression);
|
|
677
|
+
if (call === null) return ts.isStringLiteral(unwrapExpression(relationship.expression)) ? false : null;
|
|
678
|
+
const callee = unwrapExpression(call.expression);
|
|
679
|
+
if (!ts.isIdentifier(callee) || !isModuleBindingVisible(callee, analysis)) return null;
|
|
680
|
+
if (isBoundIdentifier(callee, analysis, reference)) return true;
|
|
681
|
+
return resolveBindingReferences(callee, analysis).length > 0 ? false : null;
|
|
682
|
+
};
|
|
683
|
+
//#endregion
|
|
684
|
+
//#region src/source-analysis/methods.ts
|
|
685
|
+
/** Returns a supported non-generator block-bodied method with an exact parameter count. */
|
|
686
|
+
var getCloudflareAgentsMethod = (methods, name, parameterCount) => {
|
|
687
|
+
const method = methods.get(name);
|
|
688
|
+
if (method === void 0 || method.declaration.asteriskToken !== void 0 || method.declaration.parameters.length !== parameterCount || method.declaration.parameters.some((parameter) => !ts.isIdentifier(parameter.name) || parameter.dotDotDotToken !== void 0 || parameter.initializer !== void 0)) return null;
|
|
689
|
+
return method;
|
|
690
|
+
};
|
|
691
|
+
/** Indexes static method names while rejecting overloads and duplicate implementations. */
|
|
692
|
+
var indexCloudflareAgentsMethods = (declaration) => {
|
|
693
|
+
const methods = /* @__PURE__ */ new Map();
|
|
694
|
+
for (const member of declaration.members) {
|
|
695
|
+
if (!ts.isMethodDeclaration(member)) continue;
|
|
696
|
+
const name = getCloudflareAgentsPropertyName(member.name);
|
|
697
|
+
if (name === null || member.body === void 0 || methods.has(name)) return null;
|
|
698
|
+
methods.set(name, Object.freeze({
|
|
699
|
+
body: member.body,
|
|
700
|
+
declaration: member
|
|
701
|
+
}));
|
|
702
|
+
}
|
|
703
|
+
return methods;
|
|
704
|
+
};
|
|
705
|
+
//#endregion
|
|
706
|
+
//#region src/source-analysis/class-definitions.ts
|
|
707
|
+
var hasExportModifier = (declaration) => ts.canHaveModifiers(declaration) && (ts.getModifiers(declaration)?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword) ?? false);
|
|
708
|
+
var getTargetId = (declaration, analysis) => {
|
|
709
|
+
const heritageClauses = declaration.heritageClauses;
|
|
710
|
+
if (heritageClauses?.length !== 1) return null;
|
|
711
|
+
const clause = heritageClauses[0];
|
|
712
|
+
if (clause === void 0 || clause.token !== ts.SyntaxKind.ExtendsKeyword) return null;
|
|
713
|
+
const types = clause.types;
|
|
714
|
+
if (types.length !== 1) return null;
|
|
715
|
+
const baseType = types[0];
|
|
716
|
+
if (baseType === void 0 || baseType.typeArguments !== void 0) return null;
|
|
717
|
+
const base = unwrapExpression(baseType.expression);
|
|
718
|
+
if (!ts.isIdentifier(base) || !isModuleBindingVisible(base, analysis)) return null;
|
|
719
|
+
if (analysis.imports.thinkNames.has(base.text)) return CLOUDFLARE_THINK_TARGET_ID;
|
|
720
|
+
return analysis.imports.aiChatAgentNames.has(base.text) ? CLOUDFLARE_AI_CHAT_TARGET_ID : null;
|
|
721
|
+
};
|
|
722
|
+
/** Classifies one directly exported Cloudflare agent class under the closed class contract. */
|
|
723
|
+
var getCloudflareAgentsClassDefinition = (analysis, symbol) => {
|
|
724
|
+
const exported = analysis.exports.get(symbol);
|
|
725
|
+
if (exported === void 0) return Object.freeze({ kind: "absent" });
|
|
726
|
+
if (!ts.isClassDeclaration(exported.declaration) || exported.declaration.name?.text !== symbol || !hasExportModifier(exported.declaration)) return Object.freeze({
|
|
727
|
+
declaration: exported.declaration,
|
|
728
|
+
kind: "present-unsupported"
|
|
729
|
+
});
|
|
730
|
+
const targetId = getTargetId(exported.declaration, analysis);
|
|
731
|
+
if (targetId === null) return Object.freeze({
|
|
732
|
+
declaration: exported.declaration,
|
|
733
|
+
kind: "present-unsupported"
|
|
734
|
+
});
|
|
735
|
+
const methods = indexCloudflareAgentsMethods(exported.declaration);
|
|
736
|
+
if (methods === null || !isCloudflareAgentsClassInitializationSupported(exported.declaration)) return Object.freeze({
|
|
737
|
+
declaration: exported.declaration,
|
|
738
|
+
kind: "present-unsupported",
|
|
739
|
+
targetId
|
|
740
|
+
});
|
|
741
|
+
if (targetId === "typescript-ai-chat-agent-0-10-ai-sdk-7" && (methods.get("onChatMessage")?.declaration.parameters.length !== 2 || methods.get("onChatMessage")?.declaration.parameters[0]?.questionToken !== void 0 || methods.get("onChatMessage")?.declaration.parameters[1]?.dotDotDotToken !== void 0)) return Object.freeze({
|
|
742
|
+
declaration: exported.declaration,
|
|
743
|
+
kind: "present-unsupported",
|
|
744
|
+
targetId
|
|
745
|
+
});
|
|
746
|
+
return Object.freeze({
|
|
747
|
+
definition: Object.freeze({
|
|
748
|
+
declaration: exported.declaration,
|
|
749
|
+
methods,
|
|
750
|
+
targetId
|
|
751
|
+
}),
|
|
752
|
+
kind: "present-supported"
|
|
753
|
+
});
|
|
754
|
+
};
|
|
755
|
+
//#endregion
|
|
756
|
+
//#region src/source-analysis/think-instructions.ts
|
|
757
|
+
/** Extracts the exact direct loader call returned by `getSystemPrompt`. */
|
|
758
|
+
var getCloudflareAgentsThinkSystemPrompt = (definition) => {
|
|
759
|
+
const method = getCloudflareAgentsMethod(definition.methods, "getSystemPrompt", 0);
|
|
760
|
+
if (method === null || method.body.statements.length !== 1) return Object.freeze({ kind: "absent" });
|
|
761
|
+
const statement = method.body.statements[0];
|
|
762
|
+
if (statement === void 0 || !ts.isReturnStatement(statement) || statement.expression === void 0) return Object.freeze({ kind: "unresolved" });
|
|
763
|
+
return Object.freeze(getDirectCall(statement.expression) === null ? { kind: "unresolved" } : {
|
|
764
|
+
expression: statement.expression,
|
|
765
|
+
kind: "present"
|
|
766
|
+
});
|
|
767
|
+
};
|
|
768
|
+
//#endregion
|
|
769
|
+
//#region src/source-analysis/session-builders.ts
|
|
770
|
+
var mergeInstruction = (current, expression) => current.kind === "absent" ? Object.freeze({
|
|
771
|
+
expression,
|
|
772
|
+
kind: "present"
|
|
773
|
+
}) : Object.freeze({ kind: "unresolved" });
|
|
774
|
+
var getProviderLoader = (expression) => {
|
|
775
|
+
const candidate = unwrapExpression(expression);
|
|
776
|
+
if (!ts.isObjectLiteralExpression(candidate)) return null;
|
|
777
|
+
const properties = getClosedObjectProperties(candidate);
|
|
778
|
+
if (properties === null || !properties.has("get")) return null;
|
|
779
|
+
const getter = unwrapExpression(properties.get("get"));
|
|
780
|
+
if (ts.isIdentifier(getter)) return ts.factory.createCallExpression(getter, void 0, []);
|
|
781
|
+
if (ts.isArrowFunction(getter) || ts.isFunctionExpression(getter)) {
|
|
782
|
+
if (ts.isBlock(getter.body)) {
|
|
783
|
+
if (getter.body.statements.length !== 1) return null;
|
|
784
|
+
const statement = getter.body.statements[0];
|
|
785
|
+
return statement !== void 0 && ts.isReturnStatement(statement) && statement.expression !== void 0 ? statement.expression : null;
|
|
786
|
+
}
|
|
787
|
+
return getter.body;
|
|
788
|
+
}
|
|
789
|
+
return null;
|
|
790
|
+
};
|
|
791
|
+
/** Extracts an exact Think session-builder instruction source from supported chaining. */
|
|
792
|
+
var getCloudflareAgentsThinkSessionInstructions = (definition) => {
|
|
793
|
+
const method = getCloudflareAgentsMethod(definition.methods, "configureSession", 1);
|
|
794
|
+
if (method === null || method.body.statements.length !== 1) return Object.freeze({ kind: "absent" });
|
|
795
|
+
const statement = method.body.statements[0];
|
|
796
|
+
const parameter = method.declaration.parameters[0]?.name;
|
|
797
|
+
if (statement === void 0 || !ts.isReturnStatement(statement) || statement.expression === void 0 || parameter === void 0 || !ts.isIdentifier(parameter)) return Object.freeze({ kind: "unresolved" });
|
|
798
|
+
let expression = unwrapExpression(statement.expression);
|
|
799
|
+
let instructions = { kind: "absent" };
|
|
800
|
+
while (ts.isCallExpression(expression)) {
|
|
801
|
+
const callee = unwrapExpression(expression.expression);
|
|
802
|
+
if (!ts.isPropertyAccessExpression(callee)) return Object.freeze({ kind: "unresolved" });
|
|
803
|
+
const methodName = callee.name.text;
|
|
804
|
+
if (methodName === "withInstructions") {
|
|
805
|
+
const argument = expression.arguments[0];
|
|
806
|
+
if (expression.arguments.length !== 1 || argument === void 0 || getDirectCall(argument) === null) return Object.freeze({ kind: "unresolved" });
|
|
807
|
+
instructions = mergeInstruction(instructions, argument);
|
|
808
|
+
} else if (methodName === "withContext") {
|
|
809
|
+
const argument = expression.arguments[0];
|
|
810
|
+
const loader = argument === void 0 ? null : getProviderLoader(argument);
|
|
811
|
+
if (expression.arguments.length !== 1 || loader === null || getDirectCall(loader) === null) return Object.freeze({ kind: "unresolved" });
|
|
812
|
+
instructions = mergeInstruction(instructions, loader);
|
|
813
|
+
} else if (methodName === "withCachedPrompt") {
|
|
814
|
+
if (expression.arguments.length > 1) return Object.freeze({ kind: "unresolved" });
|
|
815
|
+
const argument = expression.arguments[0];
|
|
816
|
+
if (argument !== void 0) {
|
|
817
|
+
const loader = getProviderLoader(argument);
|
|
818
|
+
if (loader === null || getDirectCall(loader) === null) return Object.freeze({ kind: "unresolved" });
|
|
819
|
+
instructions = mergeInstruction(instructions, loader);
|
|
820
|
+
}
|
|
821
|
+
} else if (methodName === "forSession") {
|
|
822
|
+
if (expression.arguments.length !== 1 || getStaticString(expression.arguments[0]) === null) return Object.freeze({ kind: "unresolved" });
|
|
823
|
+
} else if (methodName === "compactAfter") {
|
|
824
|
+
const argument = expression.arguments[0];
|
|
825
|
+
if (expression.arguments.length !== 1 || argument === void 0 || !ts.isNumericLiteral(unwrapExpression(argument)) || !Number.isSafeInteger(Number(unwrapExpression(argument).getText())) || Number(unwrapExpression(argument).getText()) < 0) return Object.freeze({ kind: "unresolved" });
|
|
826
|
+
} else return Object.freeze({ kind: "unresolved" });
|
|
827
|
+
expression = unwrapExpression(callee.expression);
|
|
828
|
+
}
|
|
829
|
+
return ts.isIdentifier(expression) && expression.text === parameter.text ? Object.freeze(instructions) : Object.freeze({ kind: "unresolved" });
|
|
830
|
+
};
|
|
831
|
+
//#endregion
|
|
832
|
+
//#region src/source-analysis/channel-tools.ts
|
|
833
|
+
/** Determines whether Think channel configuration can influence the assembled tool set. */
|
|
834
|
+
var getCloudflareAgentsThinkChannelTools = (definition) => {
|
|
835
|
+
const method = getCloudflareAgentsMethod(definition.methods, "configureChannels", 0);
|
|
836
|
+
if (method === null) return Object.freeze({ kind: definition.methods.has("configureChannels") ? "unresolved" : "absent" });
|
|
837
|
+
if (method.body.statements.length !== 1) return Object.freeze({ kind: "unresolved" });
|
|
838
|
+
const statement = method.body.statements[0];
|
|
839
|
+
if (statement === void 0 || !ts.isReturnStatement(statement) || statement.expression === void 0) return Object.freeze({ kind: "unresolved" });
|
|
840
|
+
const channelMap = unwrapExpression(statement.expression);
|
|
841
|
+
if (!ts.isObjectLiteralExpression(channelMap)) return Object.freeze({ kind: "unresolved" });
|
|
842
|
+
const channels = getClosedObjectProperties(channelMap);
|
|
843
|
+
if (channels === null) return Object.freeze({ kind: "unresolved" });
|
|
844
|
+
for (const channelExpression of channels.values()) {
|
|
845
|
+
const channel = unwrapExpression(channelExpression);
|
|
846
|
+
if (!ts.isObjectLiteralExpression(channel)) return Object.freeze({ kind: "unresolved" });
|
|
847
|
+
const properties = getClosedObjectProperties(channel);
|
|
848
|
+
if (properties === null || properties.has("tools")) return Object.freeze({ kind: "unresolved" });
|
|
849
|
+
}
|
|
850
|
+
return Object.freeze({ kind: "absent" });
|
|
851
|
+
};
|
|
852
|
+
//#endregion
|
|
853
|
+
//#region src/source-analysis/think-tools.ts
|
|
854
|
+
/** Extracts the direct tools expression returned by a closed Think `getTools` method. */
|
|
855
|
+
var getCloudflareAgentsThinkTools = (definition) => {
|
|
856
|
+
const method = getCloudflareAgentsMethod(definition.methods, "getTools", 0);
|
|
857
|
+
if (method === null || method.body.statements.length !== 1) return Object.freeze({ kind: "absent" });
|
|
858
|
+
const statement = method.body.statements[0];
|
|
859
|
+
return statement !== void 0 && ts.isReturnStatement(statement) && statement.expression !== void 0 ? Object.freeze({
|
|
860
|
+
expression: unwrapExpression(statement.expression),
|
|
861
|
+
kind: "present"
|
|
862
|
+
}) : Object.freeze({ kind: "unresolved" });
|
|
863
|
+
};
|
|
864
|
+
//#endregion
|
|
865
|
+
//#region src/source-analysis/generation-requests.ts
|
|
866
|
+
/** Finds supported direct AI SDK requests in the method's own lexical body. */
|
|
867
|
+
var getCloudflareAgentsGenerationRequests = (method, analysis) => {
|
|
868
|
+
const requests = [];
|
|
869
|
+
const visit = (node) => {
|
|
870
|
+
if (node !== method.body && ts.isFunctionLike(node)) return;
|
|
871
|
+
if (ts.isCallExpression(node)) {
|
|
872
|
+
const callee = unwrapExpression(node.expression);
|
|
873
|
+
const argument = node.arguments[0] === void 0 ? null : unwrapExpression(node.arguments[0]);
|
|
874
|
+
if (ts.isIdentifier(callee) && isModuleBindingVisible(callee, analysis) && argument !== null && ts.isObjectLiteralExpression(argument)) {
|
|
875
|
+
const call = analysis.imports.generateTextNames.has(callee.text) ? "generateText" : analysis.imports.streamTextNames.has(callee.text) ? "streamText" : null;
|
|
876
|
+
if (call !== null && node.arguments.length === 1) {
|
|
877
|
+
const relationships = analyzeCloudflareAgentsObjectRelationships(argument, [
|
|
878
|
+
"instructions",
|
|
879
|
+
"system",
|
|
880
|
+
"output",
|
|
881
|
+
"tools",
|
|
882
|
+
"prepareStep"
|
|
883
|
+
]);
|
|
884
|
+
const instructions = relationships.prepareStep.kind !== "absent" ? { kind: "unresolved" } : relationships.instructions.kind !== "absent" ? relationships.instructions : relationships.system;
|
|
885
|
+
requests.push(Object.freeze({
|
|
886
|
+
call,
|
|
887
|
+
instructions,
|
|
888
|
+
object: argument,
|
|
889
|
+
output: relationships.output,
|
|
890
|
+
tools: relationships.tools
|
|
891
|
+
}));
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
ts.forEachChild(node, visit);
|
|
896
|
+
};
|
|
897
|
+
visit(method.body);
|
|
898
|
+
return Object.freeze(requests);
|
|
899
|
+
};
|
|
900
|
+
//#endregion
|
|
901
|
+
//#region src/source-analysis/ai-chat-agents.ts
|
|
902
|
+
/** Extracts direct AI SDK requests from the supported AIChatAgent handler. */
|
|
903
|
+
var getCloudflareAgentsAiChatRequests = (definition, analysis) => {
|
|
904
|
+
const method = getCloudflareAgentsMethod(definition.methods, "onChatMessage", 2);
|
|
905
|
+
return method === null ? Object.freeze([]) : getCloudflareAgentsGenerationRequests(method, analysis);
|
|
906
|
+
};
|
|
907
|
+
//#endregion
|
|
908
|
+
//#region src/source-analysis/output-specifications.ts
|
|
909
|
+
/** Classifies a direct AI SDK `Output.object(...)` schema relationship. */
|
|
910
|
+
var getCloudflareAgentsOutputSchema = (relationship, analysis) => {
|
|
911
|
+
if (relationship.kind !== "present") return relationship;
|
|
912
|
+
const candidate = unwrapExpression(relationship.expression);
|
|
913
|
+
if (!ts.isCallExpression(candidate) || candidate.arguments.length !== 1) return Object.freeze({ kind: "unresolved" });
|
|
914
|
+
const callee = unwrapExpression(candidate.expression);
|
|
915
|
+
if (!ts.isPropertyAccessExpression(callee) || callee.name.text !== "object" || !ts.isIdentifier(unwrapExpression(callee.expression))) return Object.freeze({ kind: "unresolved" });
|
|
916
|
+
const output = unwrapExpression(callee.expression);
|
|
917
|
+
const object = unwrapExpression(candidate.arguments[0]);
|
|
918
|
+
if (!analysis.imports.outputNames.has(output.text) || !isModuleBindingVisible(output, analysis) || !ts.isObjectLiteralExpression(object) || hasCloudflareAgentsPrototypeSetter(object)) return Object.freeze({ kind: "unresolved" });
|
|
919
|
+
let schema = { kind: "absent" };
|
|
920
|
+
const seen = /* @__PURE__ */ new Set();
|
|
921
|
+
for (const property of object.properties) {
|
|
922
|
+
if (ts.isSpreadAssignment(property) || ts.isComputedPropertyName(property.name)) return Object.freeze({ kind: "unresolved" });
|
|
923
|
+
const name = getCloudflareAgentsPropertyName(property.name);
|
|
924
|
+
if (name === null || ![
|
|
925
|
+
"description",
|
|
926
|
+
"name",
|
|
927
|
+
"schema"
|
|
928
|
+
].includes(name) || seen.has(name)) return Object.freeze({ kind: "unresolved" });
|
|
929
|
+
seen.add(name);
|
|
930
|
+
if (name === "schema") schema = ts.isPropertyAssignment(property) ? {
|
|
931
|
+
expression: unwrapExpression(property.initializer),
|
|
932
|
+
kind: "present"
|
|
933
|
+
} : ts.isShorthandPropertyAssignment(property) ? {
|
|
934
|
+
expression: property.name,
|
|
935
|
+
kind: "present"
|
|
936
|
+
} : { kind: "unresolved" };
|
|
937
|
+
}
|
|
938
|
+
return Object.freeze(schema.kind === "absent" ? { kind: "unresolved" } : schema);
|
|
939
|
+
};
|
|
940
|
+
//#endregion
|
|
941
|
+
//#region src/source-analysis/function-tools.ts
|
|
942
|
+
var TOLERATED_PROPERTY_NAMES = /* @__PURE__ */ new Set([
|
|
943
|
+
"contextSchema",
|
|
944
|
+
"description",
|
|
945
|
+
"execute",
|
|
946
|
+
"inputExamples",
|
|
947
|
+
"inputSchema",
|
|
948
|
+
"metadata",
|
|
949
|
+
"needsApproval",
|
|
950
|
+
"onInputAvailable",
|
|
951
|
+
"onInputDelta",
|
|
952
|
+
"onInputStart",
|
|
953
|
+
"outputSchema",
|
|
954
|
+
"providerOptions",
|
|
955
|
+
"strict",
|
|
956
|
+
"title",
|
|
957
|
+
"toModelOutput",
|
|
958
|
+
"type"
|
|
959
|
+
]);
|
|
960
|
+
/** Classifies one direct AI SDK function-tool declaration. */
|
|
961
|
+
var getCloudflareAgentsFunctionTool = (analysis, declaration) => {
|
|
962
|
+
if (declaration.initializer === void 0) return null;
|
|
963
|
+
const call = unwrapExpression(declaration.initializer);
|
|
964
|
+
if (!ts.isCallExpression(call) || call.arguments.length !== 1) return null;
|
|
965
|
+
const callee = unwrapExpression(call.expression);
|
|
966
|
+
const object = unwrapExpression(call.arguments[0]);
|
|
967
|
+
if (!ts.isIdentifier(callee) || !analysis.imports.toolNames.has(callee.text) || !isModuleBindingVisible(callee, analysis) || !ts.isObjectLiteralExpression(object)) return null;
|
|
968
|
+
const names = /* @__PURE__ */ new Set();
|
|
969
|
+
for (const property of object.properties) {
|
|
970
|
+
if (ts.isSpreadAssignment(property) || ts.isComputedPropertyName(property.name)) return null;
|
|
971
|
+
const name = getCloudflareAgentsPropertyName(property.name);
|
|
972
|
+
if (name === null || !TOLERATED_PROPERTY_NAMES.has(name) || names.has(name)) return null;
|
|
973
|
+
names.add(name);
|
|
974
|
+
}
|
|
975
|
+
if (!names.has("inputSchema")) return null;
|
|
976
|
+
const relationships = analyzeCloudflareAgentsObjectRelationships(object, [
|
|
977
|
+
"execute",
|
|
978
|
+
"inputSchema",
|
|
979
|
+
"outputSchema"
|
|
980
|
+
]);
|
|
981
|
+
return Object.freeze({
|
|
982
|
+
declaration,
|
|
983
|
+
...relationships
|
|
984
|
+
});
|
|
985
|
+
};
|
|
986
|
+
//#endregion
|
|
987
|
+
//#region src/source-analysis/agent-tools.ts
|
|
988
|
+
/** Classifies one direct Cloudflare `agentTool(...)` declaration. */
|
|
989
|
+
var getCloudflareAgentsAgentTool = (analysis, declaration) => {
|
|
990
|
+
if (declaration.initializer === void 0) return null;
|
|
991
|
+
const call = unwrapExpression(declaration.initializer);
|
|
992
|
+
if (!ts.isCallExpression(call) || call.arguments.length < 1 || call.arguments.length > 2) return null;
|
|
993
|
+
const callee = unwrapExpression(call.expression);
|
|
994
|
+
const target = unwrapExpression(call.arguments[0]);
|
|
995
|
+
if (!ts.isIdentifier(callee) || !analysis.imports.agentToolNames.has(callee.text) || !isModuleBindingVisible(callee, analysis) || !ts.isIdentifier(target)) return null;
|
|
996
|
+
const options = call.arguments[1];
|
|
997
|
+
let description = null;
|
|
998
|
+
if (options !== void 0) {
|
|
999
|
+
const candidate = unwrapExpression(options);
|
|
1000
|
+
if (!ts.isObjectLiteralExpression(candidate)) return null;
|
|
1001
|
+
const properties = getClosedObjectProperties(candidate);
|
|
1002
|
+
if (properties === null || [...properties.keys()].some((name) => !["description", "name"].includes(name))) return null;
|
|
1003
|
+
description = getStaticString(properties.get("description"));
|
|
1004
|
+
if (properties.has("description") && description === null) return null;
|
|
1005
|
+
}
|
|
1006
|
+
return Object.freeze({
|
|
1007
|
+
declaration,
|
|
1008
|
+
description,
|
|
1009
|
+
target
|
|
1010
|
+
});
|
|
1011
|
+
};
|
|
1012
|
+
//#endregion
|
|
1013
|
+
//#region src/source-analysis/tool-maps.ts
|
|
1014
|
+
/** Classifies one direct tools-map object while retaining supported own entries. */
|
|
1015
|
+
var getCloudflareAgentsToolMap = (object) => {
|
|
1016
|
+
const entries = [];
|
|
1017
|
+
const names = /* @__PURE__ */ new Set();
|
|
1018
|
+
let isUnresolved = false;
|
|
1019
|
+
for (const property of object.properties) {
|
|
1020
|
+
if (ts.isSpreadAssignment(property) || ts.isComputedPropertyName(property.name)) {
|
|
1021
|
+
isUnresolved = true;
|
|
1022
|
+
continue;
|
|
1023
|
+
}
|
|
1024
|
+
const name = getCloudflareAgentsPropertyName(property.name);
|
|
1025
|
+
if (name === null || names.has(name)) {
|
|
1026
|
+
isUnresolved = true;
|
|
1027
|
+
continue;
|
|
1028
|
+
}
|
|
1029
|
+
names.add(name);
|
|
1030
|
+
if (ts.isPropertyAssignment(property) && name !== "__proto__") entries.push(Object.freeze({
|
|
1031
|
+
expression: unwrapExpression(property.initializer),
|
|
1032
|
+
name
|
|
1033
|
+
}));
|
|
1034
|
+
else if (ts.isShorthandPropertyAssignment(property)) entries.push(Object.freeze({
|
|
1035
|
+
expression: property.name,
|
|
1036
|
+
name
|
|
1037
|
+
}));
|
|
1038
|
+
else if (name !== "__proto__") isUnresolved = true;
|
|
1039
|
+
}
|
|
1040
|
+
return Object.freeze({
|
|
1041
|
+
entries: Object.freeze(entries),
|
|
1042
|
+
kind: isUnresolved ? "unresolved" : "closed"
|
|
1043
|
+
});
|
|
1044
|
+
};
|
|
1045
|
+
//#endregion
|
|
1046
|
+
//#region src/diagnostics/index.ts
|
|
1047
|
+
var CLOUDFLARE_AGENTS_ADAPTER_DIAGNOSTICS = Object.freeze({
|
|
1048
|
+
CLOUDFLARE_AGENTS_AGENT_OUTPUT_SCHEMA_NOT_WIRED: "The declared agent output schema is not wired to the detected AIChatAgent structured output.",
|
|
1049
|
+
CLOUDFLARE_AGENTS_AGENT_OUTPUT_SCHEMA_SYMBOL_NOT_FOUND: "The declared agent output-schema symbol was not found.",
|
|
1050
|
+
CLOUDFLARE_AGENTS_HANDOFF_ROUTING_DESCRIPTION_MISSING: "The detected Cloudflare agent-tool routing description is missing.",
|
|
1051
|
+
CLOUDFLARE_AGENTS_HANDOFF_ROUTING_DESCRIPTION_NOT_WIRED: "The detected Cloudflare agent-tool routing description is not wired to the target agent's effective routing description.",
|
|
1052
|
+
CLOUDFLARE_AGENTS_HANDOFF_TARGET_AMBIGUOUS: "The detected Cloudflare agent-tool target maps to more than one registered agent.",
|
|
1053
|
+
CLOUDFLARE_AGENTS_INSTRUCTION_LOADER_NOT_WIRED: "The declared instruction loader is not wired to a supported configured Cloudflare agent instruction source.",
|
|
1054
|
+
CLOUDFLARE_AGENTS_INSTRUCTION_LOADER_SYMBOL_NOT_FOUND: "The declared instruction-loader symbol was not found.",
|
|
1055
|
+
CLOUDFLARE_AGENTS_PACKAGE_MANIFEST_INVALID: "The owning package manifest is invalid for Cloudflare Agents dependency detection.",
|
|
1056
|
+
CLOUDFLARE_AGENTS_RUNTIME_AGENT_SYMBOL_NOT_FOUND: "The declared runtime-agent symbol was not found.",
|
|
1057
|
+
CLOUDFLARE_AGENTS_RUNTIME_VERSION_UNSUPPORTED: "The observed Cloudflare Agents dependency range is disjoint from the supported target.",
|
|
1058
|
+
CLOUDFLARE_AGENTS_SOURCE_SYNTAX_INVALID: "The referenced Cloudflare Agents source file contains invalid TypeScript syntax.",
|
|
1059
|
+
CLOUDFLARE_AGENTS_SOURCE_TEXT_INVALID: "The referenced Cloudflare Agents source file is not valid normalized text.",
|
|
1060
|
+
CLOUDFLARE_AGENTS_TOOL_IMPLEMENTATION_NOT_WIRED: "The declared tool implementation is not wired to the detected Cloudflare agent function tool.",
|
|
1061
|
+
CLOUDFLARE_AGENTS_TOOL_IMPLEMENTATION_SYMBOL_NOT_FOUND: "The declared tool-implementation symbol was not found.",
|
|
1062
|
+
CLOUDFLARE_AGENTS_TOOL_INPUT_SCHEMA_NOT_WIRED: "The declared tool input schema is not wired to the detected Cloudflare agent function tool.",
|
|
1063
|
+
CLOUDFLARE_AGENTS_TOOL_INPUT_SCHEMA_SYMBOL_NOT_FOUND: "The declared tool input-schema symbol was not found.",
|
|
1064
|
+
CLOUDFLARE_AGENTS_TOOL_NAME_MISMATCH: "The declared tool name does not match the detected Cloudflare agent tools-map key.",
|
|
1065
|
+
CLOUDFLARE_AGENTS_TOOL_OUTPUT_SCHEMA_NOT_WIRED: "The declared tool output schema is not wired to the detected Cloudflare agent function tool.",
|
|
1066
|
+
CLOUDFLARE_AGENTS_TOOL_OUTPUT_SCHEMA_SYMBOL_NOT_FOUND: "The declared tool output-schema symbol was not found.",
|
|
1067
|
+
CLOUDFLARE_AGENTS_TOOL_REGISTRATION_NOT_WIRED: "The declared tool registration is not wired to the detected Cloudflare agent tools map.",
|
|
1068
|
+
CLOUDFLARE_AGENTS_TOOL_REGISTRATION_SYMBOL_NOT_FOUND: "The declared tool-registration symbol was not found."
|
|
1069
|
+
});
|
|
1070
|
+
/** Creates one frozen, safely namespaced Cloudflare Agents adapter diagnostic. */
|
|
1071
|
+
var createCloudflareAgentsDiagnostic = (input) => Object.freeze({
|
|
1072
|
+
...input,
|
|
1073
|
+
details: Object.freeze({ ...input.details }),
|
|
1074
|
+
entity: input.entity === null ? null : Object.freeze({ ...input.entity }),
|
|
1075
|
+
message: CLOUDFLARE_AGENTS_ADAPTER_DIAGNOSTICS[input.code],
|
|
1076
|
+
source: CLOUDFLARE_AGENTS_ADAPTER_ID
|
|
1077
|
+
});
|
|
1078
|
+
//#endregion
|
|
1079
|
+
//#region src/inspection/common.ts
|
|
1080
|
+
/** Compares exact strings without locale-dependent behavior. */
|
|
1081
|
+
var compareCloudflareAgentsStrings = (left, right) => left < right ? -1 : left > right ? 1 : 0;
|
|
1082
|
+
var freezeReference = (reference) => Object.freeze({
|
|
1083
|
+
path: reference.path,
|
|
1084
|
+
...reference.symbol === void 0 ? {} : { symbol: reference.symbol }
|
|
1085
|
+
});
|
|
1086
|
+
/** Creates one deeply immutable Cloudflare Agents evidence record. */
|
|
1087
|
+
var createCloudflareAgentsEvidence = (evidence) => Object.freeze({
|
|
1088
|
+
...evidence,
|
|
1089
|
+
details: Object.freeze({ ...evidence.details }),
|
|
1090
|
+
references: Object.freeze(evidence.references.map(freezeReference))
|
|
1091
|
+
});
|
|
1092
|
+
var createEntity = (agentId, capabilityId) => Object.freeze({
|
|
1093
|
+
adapterId: CLOUDFLARE_AGENTS_ADAPTER_ID,
|
|
1094
|
+
agentId,
|
|
1095
|
+
...capabilityId === void 0 ? {} : {
|
|
1096
|
+
capabilityId,
|
|
1097
|
+
capabilityKind: "tool"
|
|
1098
|
+
}
|
|
1099
|
+
});
|
|
1100
|
+
/** Appends one stable package-owned diagnostic. */
|
|
1101
|
+
var addCloudflareAgentsDiagnostic = (diagnostics, code, path, agentId, range = null, capabilityId, details = {}) => {
|
|
1102
|
+
diagnostics.push(createCloudflareAgentsDiagnostic({
|
|
1103
|
+
code,
|
|
1104
|
+
details,
|
|
1105
|
+
entity: createEntity(agentId, capabilityId),
|
|
1106
|
+
path,
|
|
1107
|
+
pointer: null,
|
|
1108
|
+
range
|
|
1109
|
+
}));
|
|
1110
|
+
};
|
|
1111
|
+
/** Loads and validates one supported bound TypeScript source. */
|
|
1112
|
+
var analyzeCloudflareAgentsBoundReference = async (session, reference, diagnostics, agentId, capabilityId) => {
|
|
1113
|
+
if (!isSupportedTypeScriptSourcePath(reference.path)) return null;
|
|
1114
|
+
const result = await session.analyzeSource(reference.path);
|
|
1115
|
+
if (result.kind === "invalid-text") {
|
|
1116
|
+
addCloudflareAgentsDiagnostic(diagnostics, "CLOUDFLARE_AGENTS_SOURCE_TEXT_INVALID", reference.path, agentId, null, capabilityId);
|
|
1117
|
+
return null;
|
|
1118
|
+
}
|
|
1119
|
+
if (result.kind === "invalid-syntax") {
|
|
1120
|
+
addCloudflareAgentsDiagnostic(diagnostics, "CLOUDFLARE_AGENTS_SOURCE_SYNTAX_INVALID", reference.path, agentId, result.range, capabilityId);
|
|
1121
|
+
return null;
|
|
1122
|
+
}
|
|
1123
|
+
return result.analysis;
|
|
1124
|
+
};
|
|
1125
|
+
/** Determines whether a declared symbol exists in its exact analyzed module. */
|
|
1126
|
+
var hasCloudflareAgentsSymbol = async (session, reference, diagnostics, agentId, missingCode, capabilityId) => {
|
|
1127
|
+
const analysis = await analyzeCloudflareAgentsBoundReference(session, reference, diagnostics, agentId, capabilityId);
|
|
1128
|
+
if (analysis === null || reference.symbol === void 0) return null;
|
|
1129
|
+
if (!analysis.exports.has(reference.symbol)) {
|
|
1130
|
+
addCloudflareAgentsDiagnostic(diagnostics, missingCode, reference.path, agentId, null, capabilityId);
|
|
1131
|
+
return null;
|
|
1132
|
+
}
|
|
1133
|
+
return analysis;
|
|
1134
|
+
};
|
|
1135
|
+
//#endregion
|
|
1136
|
+
//#region src/inspection/package-inspection.ts
|
|
1137
|
+
var classifyDeclaration = (declaration, supportedRange) => {
|
|
1138
|
+
const normalized = validRange(declaration.declaredRange, {
|
|
1139
|
+
includePrerelease: false,
|
|
1140
|
+
loose: false
|
|
1141
|
+
});
|
|
1142
|
+
if (normalized === null) return "ambiguous";
|
|
1143
|
+
if (subset(normalized, supportedRange, {
|
|
1144
|
+
includePrerelease: false,
|
|
1145
|
+
loose: false
|
|
1146
|
+
})) return "supported";
|
|
1147
|
+
return intersects(normalized, supportedRange, {
|
|
1148
|
+
includePrerelease: false,
|
|
1149
|
+
loose: false
|
|
1150
|
+
}) ? "ambiguous" : "unsupported";
|
|
1151
|
+
};
|
|
1152
|
+
var getTargetPackages = (targetId) => Object.freeze([
|
|
1153
|
+
targetId === "typescript-ai-chat-agent-0-10-ai-sdk-7" ? {
|
|
1154
|
+
packageName: CLOUDFLARE_AI_CHAT_PACKAGE_NAME,
|
|
1155
|
+
supportedRange: CLOUDFLARE_AI_CHAT_SUPPORTED_RANGE
|
|
1156
|
+
} : {
|
|
1157
|
+
packageName: CLOUDFLARE_THINK_PACKAGE_NAME,
|
|
1158
|
+
supportedRange: CLOUDFLARE_THINK_SUPPORTED_RANGE
|
|
1159
|
+
},
|
|
1160
|
+
{
|
|
1161
|
+
packageName: CLOUDFLARE_AGENTS_PACKAGE_NAME,
|
|
1162
|
+
supportedRange: CLOUDFLARE_AGENTS_SUPPORTED_RANGE
|
|
1163
|
+
},
|
|
1164
|
+
{
|
|
1165
|
+
packageName: "ai",
|
|
1166
|
+
supportedRange: AI_SDK_SUPPORTED_RANGE
|
|
1167
|
+
}
|
|
1168
|
+
]);
|
|
1169
|
+
/** Inspects exact package declarations and gates one verified target. */
|
|
1170
|
+
var inspectCloudflareAgentsPackage = async (session, sourcePath, targetId, evidence, diagnostics, agentId) => {
|
|
1171
|
+
const discovery = await session.discoverPackage(sourcePath);
|
|
1172
|
+
if (discovery.kind === "absent") return false;
|
|
1173
|
+
if (discovery.kind === "invalid") {
|
|
1174
|
+
addCloudflareAgentsDiagnostic(diagnostics, "CLOUDFLARE_AGENTS_PACKAGE_MANIFEST_INVALID", discovery.path, agentId);
|
|
1175
|
+
return false;
|
|
1176
|
+
}
|
|
1177
|
+
for (const targetPackage of getTargetPackages(targetId)) {
|
|
1178
|
+
const declarations = discovery.observation.declarations.get(targetPackage.packageName);
|
|
1179
|
+
if (declarations === void 0 || declarations.length === 0) return false;
|
|
1180
|
+
for (const declaration of declarations) {
|
|
1181
|
+
const compatibility = classifyDeclaration(declaration, targetPackage.supportedRange);
|
|
1182
|
+
if (compatibility === "unsupported") {
|
|
1183
|
+
addCloudflareAgentsDiagnostic(diagnostics, "CLOUDFLARE_AGENTS_RUNTIME_VERSION_UNSUPPORTED", discovery.observation.path, agentId, null, void 0, {
|
|
1184
|
+
declaredRange: declaration.declaredRange,
|
|
1185
|
+
packageName: targetPackage.packageName,
|
|
1186
|
+
targetId
|
|
1187
|
+
});
|
|
1188
|
+
return false;
|
|
1189
|
+
}
|
|
1190
|
+
evidence.push(createCloudflareAgentsEvidence({
|
|
1191
|
+
agentId,
|
|
1192
|
+
capabilityId: null,
|
|
1193
|
+
capabilityKind: null,
|
|
1194
|
+
details: {
|
|
1195
|
+
compatibility,
|
|
1196
|
+
declaredRange: declaration.declaredRange,
|
|
1197
|
+
dependencyKind: declaration.dependencyKind,
|
|
1198
|
+
targetId
|
|
1199
|
+
},
|
|
1200
|
+
kind: "runtime-package",
|
|
1201
|
+
references: [{ path: discovery.observation.path }],
|
|
1202
|
+
runtimeName: targetPackage.packageName,
|
|
1203
|
+
source: CLOUDFLARE_AGENTS_ADAPTER_ID
|
|
1204
|
+
}));
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
return true;
|
|
1208
|
+
};
|
|
1209
|
+
//#endregion
|
|
1210
|
+
//#region src/inspection/resolution.ts
|
|
1211
|
+
var resolveVariableReference = async (session, analysis, expression) => {
|
|
1212
|
+
const candidate = unwrapExpression(expression);
|
|
1213
|
+
if (!ts.isIdentifier(candidate)) return null;
|
|
1214
|
+
const references = resolveBindingReferences(candidate, analysis);
|
|
1215
|
+
for (const reference of references) {
|
|
1216
|
+
const path = parseRepositoryPath(reference.path);
|
|
1217
|
+
const targetAnalysis = path === analysis.path ? analysis : await session.analyzeSource(path).then((result) => result.kind === "valid" ? result.analysis : null);
|
|
1218
|
+
if (targetAnalysis === null) continue;
|
|
1219
|
+
const declaration = targetAnalysis.moduleConstDeclarations.get(reference.symbol);
|
|
1220
|
+
if (declaration !== void 0) return Object.freeze({
|
|
1221
|
+
analysis: targetAnalysis,
|
|
1222
|
+
declaration,
|
|
1223
|
+
reference: Object.freeze({
|
|
1224
|
+
path,
|
|
1225
|
+
symbol: reference.symbol
|
|
1226
|
+
})
|
|
1227
|
+
});
|
|
1228
|
+
}
|
|
1229
|
+
return null;
|
|
1230
|
+
};
|
|
1231
|
+
/** Resolves one supported inline, local, or relative-imported tools map. */
|
|
1232
|
+
var resolveCloudflareAgentsToolMap = async (session, analysis, relationship) => {
|
|
1233
|
+
if (relationship.kind !== "present") return null;
|
|
1234
|
+
const candidate = unwrapExpression(relationship.expression);
|
|
1235
|
+
if (ts.isObjectLiteralExpression(candidate)) return Object.freeze({
|
|
1236
|
+
analysis,
|
|
1237
|
+
map: getCloudflareAgentsToolMap(candidate),
|
|
1238
|
+
reference: null
|
|
1239
|
+
});
|
|
1240
|
+
const resolved = await resolveVariableReference(session, analysis, candidate);
|
|
1241
|
+
if (resolved?.declaration.initializer === void 0) return null;
|
|
1242
|
+
const initializer = unwrapExpression(resolved.declaration.initializer);
|
|
1243
|
+
return ts.isObjectLiteralExpression(initializer) ? Object.freeze({
|
|
1244
|
+
analysis: resolved.analysis,
|
|
1245
|
+
map: getCloudflareAgentsToolMap(initializer),
|
|
1246
|
+
reference: resolved.reference
|
|
1247
|
+
}) : null;
|
|
1248
|
+
};
|
|
1249
|
+
/** Resolves one supported ordinary tool or `agentTool` declaration from a map entry. */
|
|
1250
|
+
var resolveCloudflareAgentsToolDefinition = async (session, analysis, expression) => {
|
|
1251
|
+
const resolved = await resolveVariableReference(session, analysis, expression);
|
|
1252
|
+
if (resolved === null) return null;
|
|
1253
|
+
const functionTool = getCloudflareAgentsFunctionTool(resolved.analysis, resolved.declaration);
|
|
1254
|
+
if (functionTool !== null) return Object.freeze({
|
|
1255
|
+
analysis: resolved.analysis,
|
|
1256
|
+
definition: Object.freeze({
|
|
1257
|
+
kind: "function-tool",
|
|
1258
|
+
tool: functionTool
|
|
1259
|
+
}),
|
|
1260
|
+
reference: resolved.reference
|
|
1261
|
+
});
|
|
1262
|
+
const agentTool = getCloudflareAgentsAgentTool(resolved.analysis, resolved.declaration);
|
|
1263
|
+
return agentTool === null ? null : Object.freeze({
|
|
1264
|
+
analysis: resolved.analysis,
|
|
1265
|
+
definition: Object.freeze({
|
|
1266
|
+
kind: "agent-tool",
|
|
1267
|
+
tool: agentTool
|
|
1268
|
+
}),
|
|
1269
|
+
reference: resolved.reference
|
|
1270
|
+
});
|
|
1271
|
+
};
|
|
1272
|
+
//#endregion
|
|
1273
|
+
//#region src/inspection/handoffs.ts
|
|
1274
|
+
var findTargetAgents = (target, analysis, agents) => {
|
|
1275
|
+
const candidate = unwrapExpression(target);
|
|
1276
|
+
if (!ts.isIdentifier(candidate)) return Object.freeze([]);
|
|
1277
|
+
const references = resolveBindingReferences(candidate, analysis);
|
|
1278
|
+
return Object.freeze(agents.filter((agent) => {
|
|
1279
|
+
const runtimeAgent = agent.declaration.bindings?.runtimeAgent;
|
|
1280
|
+
return runtimeAgent?.symbol !== void 0 && references.some((reference) => reference.path === runtimeAgent.path && reference.symbol === runtimeAgent.symbol);
|
|
1281
|
+
}));
|
|
1282
|
+
};
|
|
1283
|
+
/** Inspects active Cloudflare `agentTool` helpers as runtime handoff registrations. */
|
|
1284
|
+
var inspectCloudflareAgentsHandoffs = async (session, sourceAgent, agents, resolvedMaps, evidence, diagnostics) => {
|
|
1285
|
+
for (const resolvedMap of resolvedMaps) for (const entry of resolvedMap.map.entries) {
|
|
1286
|
+
const resolved = await resolveCloudflareAgentsToolDefinition(session, resolvedMap.analysis, entry.expression);
|
|
1287
|
+
if (resolved?.definition.kind !== "agent-tool") continue;
|
|
1288
|
+
const targets = findTargetAgents(resolved.definition.tool.target, resolved.analysis, agents);
|
|
1289
|
+
if (targets.length > 1) {
|
|
1290
|
+
addCloudflareAgentsDiagnostic(diagnostics, "CLOUDFLARE_AGENTS_HANDOFF_TARGET_AMBIGUOUS", resolved.reference.path, sourceAgent.id, null, void 0, { toolName: entry.name });
|
|
1291
|
+
continue;
|
|
1292
|
+
}
|
|
1293
|
+
const target = targets[0];
|
|
1294
|
+
if (target === void 0) continue;
|
|
1295
|
+
const description = resolved.definition.tool.description;
|
|
1296
|
+
const effectiveDescription = target.handoffDescription?.value ?? target.description.value;
|
|
1297
|
+
if (description === null || description.length === 0) {
|
|
1298
|
+
addCloudflareAgentsDiagnostic(diagnostics, "CLOUDFLARE_AGENTS_HANDOFF_ROUTING_DESCRIPTION_MISSING", resolved.reference.path, sourceAgent.id, null, void 0, {
|
|
1299
|
+
targetAgentId: target.id,
|
|
1300
|
+
toolName: entry.name
|
|
1301
|
+
});
|
|
1302
|
+
continue;
|
|
1303
|
+
}
|
|
1304
|
+
if (description !== effectiveDescription) {
|
|
1305
|
+
addCloudflareAgentsDiagnostic(diagnostics, "CLOUDFLARE_AGENTS_HANDOFF_ROUTING_DESCRIPTION_NOT_WIRED", resolved.reference.path, sourceAgent.id, null, void 0, {
|
|
1306
|
+
targetAgentId: target.id,
|
|
1307
|
+
toolName: entry.name
|
|
1308
|
+
});
|
|
1309
|
+
continue;
|
|
1310
|
+
}
|
|
1311
|
+
const targetReference = target.declaration.bindings?.runtimeAgent;
|
|
1312
|
+
if (targetReference === void 0) continue;
|
|
1313
|
+
evidence.push(createCloudflareAgentsEvidence({
|
|
1314
|
+
agentId: sourceAgent.id,
|
|
1315
|
+
capabilityId: null,
|
|
1316
|
+
capabilityKind: null,
|
|
1317
|
+
details: {
|
|
1318
|
+
targetAgentId: target.id,
|
|
1319
|
+
toolName: entry.name
|
|
1320
|
+
},
|
|
1321
|
+
kind: "handoff-registration",
|
|
1322
|
+
references: [resolved.reference, targetReference],
|
|
1323
|
+
runtimeName: entry.name,
|
|
1324
|
+
source: CLOUDFLARE_AGENTS_ADAPTER_ID
|
|
1325
|
+
}));
|
|
1326
|
+
}
|
|
1327
|
+
};
|
|
1328
|
+
//#endregion
|
|
1329
|
+
//#region src/inspection/relationships.ts
|
|
1330
|
+
var inspectBinding = async (session, agent, relationship, analysis, reference, symbolMissingCode, notWiredCode, evidenceKind, evidence, diagnostics, schemaRole) => {
|
|
1331
|
+
if (await hasCloudflareAgentsSymbol(session, reference, diagnostics, agent.id, symbolMissingCode) === null) return;
|
|
1332
|
+
if ((evidenceKind === "instruction-loader" ? classifyCloudflareAgentsInstructionLoader(relationship, analysis, reference) : classifyCloudflareAgentsDirectBinding(relationship, analysis, reference)) !== true) {
|
|
1333
|
+
addCloudflareAgentsDiagnostic(diagnostics, notWiredCode, reference.path, agent.id);
|
|
1334
|
+
return;
|
|
1335
|
+
}
|
|
1336
|
+
evidence.push(createCloudflareAgentsEvidence({
|
|
1337
|
+
agentId: agent.id,
|
|
1338
|
+
capabilityId: null,
|
|
1339
|
+
capabilityKind: null,
|
|
1340
|
+
details: schemaRole === void 0 ? {} : { schemaRole },
|
|
1341
|
+
kind: evidenceKind,
|
|
1342
|
+
references: [reference],
|
|
1343
|
+
runtimeName: reference.symbol ?? null,
|
|
1344
|
+
source: CLOUDFLARE_AGENTS_ADAPTER_ID
|
|
1345
|
+
}));
|
|
1346
|
+
};
|
|
1347
|
+
var inspectToolReference = async (session, agent, capabilityId, relationship, relationshipAnalysis, reference, symbolMissingCode, notWiredCode, diagnostics) => {
|
|
1348
|
+
if (reference === void 0) return true;
|
|
1349
|
+
if (await hasCloudflareAgentsSymbol(session, reference, diagnostics, agent.id, symbolMissingCode, capabilityId) === null) return false;
|
|
1350
|
+
if (classifyCloudflareAgentsDirectBinding(relationship, relationshipAnalysis, reference) !== true) {
|
|
1351
|
+
addCloudflareAgentsDiagnostic(diagnostics, notWiredCode, reference.path, agent.id, null, capabilityId);
|
|
1352
|
+
return false;
|
|
1353
|
+
}
|
|
1354
|
+
return true;
|
|
1355
|
+
};
|
|
1356
|
+
var inspectTools = async (session, inspected, agents, evidence, diagnostics) => {
|
|
1357
|
+
if (inspected.tools.some((relationship) => relationship.kind === "unresolved")) return;
|
|
1358
|
+
const presentRelationships = inspected.tools.filter((relationship) => relationship.kind === "present");
|
|
1359
|
+
const resolvedMaps = (await Promise.all(presentRelationships.map((relationship) => resolveCloudflareAgentsToolMap(session, inspected.analysis, relationship)))).filter((map) => map !== null && map.map.kind === "closed");
|
|
1360
|
+
if (resolvedMaps.length !== presentRelationships.length) return;
|
|
1361
|
+
await inspectCloudflareAgentsHandoffs(session, inspected.agent, agents, resolvedMaps, evidence, diagnostics);
|
|
1362
|
+
for (const [capabilityId, tool] of Object.entries(inspected.agent.declaration.tools ?? {})) {
|
|
1363
|
+
if (tool.registration === void 0) continue;
|
|
1364
|
+
await hasCloudflareAgentsSymbol(session, tool.registration, diagnostics, inspected.agent.id, "CLOUDFLARE_AGENTS_TOOL_REGISTRATION_SYMBOL_NOT_FOUND", capabilityId);
|
|
1365
|
+
let matchedEntry;
|
|
1366
|
+
for (const resolvedMap of resolvedMaps) for (const entry of resolvedMap.map.entries) if (classifyCloudflareAgentsDirectBinding({
|
|
1367
|
+
expression: entry.expression,
|
|
1368
|
+
kind: "present"
|
|
1369
|
+
}, resolvedMap.analysis, tool.registration) === true) {
|
|
1370
|
+
matchedEntry = {
|
|
1371
|
+
analysis: resolvedMap.analysis,
|
|
1372
|
+
...entry
|
|
1373
|
+
};
|
|
1374
|
+
break;
|
|
1375
|
+
}
|
|
1376
|
+
if (matchedEntry === void 0) {
|
|
1377
|
+
addCloudflareAgentsDiagnostic(diagnostics, "CLOUDFLARE_AGENTS_TOOL_REGISTRATION_NOT_WIRED", tool.registration.path, inspected.agent.id, null, capabilityId);
|
|
1378
|
+
continue;
|
|
1379
|
+
}
|
|
1380
|
+
if (matchedEntry.name !== tool.name) {
|
|
1381
|
+
addCloudflareAgentsDiagnostic(diagnostics, "CLOUDFLARE_AGENTS_TOOL_NAME_MISMATCH", tool.registration.path, inspected.agent.id, null, capabilityId, {
|
|
1382
|
+
declaredName: tool.name,
|
|
1383
|
+
detectedName: matchedEntry.name
|
|
1384
|
+
});
|
|
1385
|
+
continue;
|
|
1386
|
+
}
|
|
1387
|
+
const resolvedTool = await resolveCloudflareAgentsToolDefinition(session, matchedEntry.analysis, matchedEntry.expression);
|
|
1388
|
+
if (resolvedTool?.definition.kind !== "function-tool") continue;
|
|
1389
|
+
const functionTool = resolvedTool.definition.tool;
|
|
1390
|
+
const implementationMatches = await inspectToolReference(session, inspected.agent, capabilityId, functionTool.execute, resolvedTool.analysis, tool.implementation, "CLOUDFLARE_AGENTS_TOOL_IMPLEMENTATION_SYMBOL_NOT_FOUND", "CLOUDFLARE_AGENTS_TOOL_IMPLEMENTATION_NOT_WIRED", diagnostics);
|
|
1391
|
+
const inputMatches = await inspectToolReference(session, inspected.agent, capabilityId, functionTool.inputSchema, resolvedTool.analysis, tool.inputSchema, "CLOUDFLARE_AGENTS_TOOL_INPUT_SCHEMA_SYMBOL_NOT_FOUND", "CLOUDFLARE_AGENTS_TOOL_INPUT_SCHEMA_NOT_WIRED", diagnostics);
|
|
1392
|
+
const outputMatches = await inspectToolReference(session, inspected.agent, capabilityId, functionTool.outputSchema, resolvedTool.analysis, tool.outputSchema, "CLOUDFLARE_AGENTS_TOOL_OUTPUT_SCHEMA_SYMBOL_NOT_FOUND", "CLOUDFLARE_AGENTS_TOOL_OUTPUT_SCHEMA_NOT_WIRED", diagnostics);
|
|
1393
|
+
if (implementationMatches && inputMatches && outputMatches) {
|
|
1394
|
+
evidence.push(createCloudflareAgentsEvidence({
|
|
1395
|
+
agentId: inspected.agent.id,
|
|
1396
|
+
capabilityId,
|
|
1397
|
+
capabilityKind: "tool",
|
|
1398
|
+
details: { toolName: matchedEntry.name },
|
|
1399
|
+
kind: "tool-registration",
|
|
1400
|
+
references: [tool.registration, tool.implementation],
|
|
1401
|
+
runtimeName: matchedEntry.name,
|
|
1402
|
+
source: CLOUDFLARE_AGENTS_ADAPTER_ID
|
|
1403
|
+
}));
|
|
1404
|
+
for (const [schemaRole, reference] of [["tool-input", tool.inputSchema], ["tool-output", tool.outputSchema]]) if (reference !== void 0) evidence.push(createCloudflareAgentsEvidence({
|
|
1405
|
+
agentId: inspected.agent.id,
|
|
1406
|
+
capabilityId,
|
|
1407
|
+
capabilityKind: "tool",
|
|
1408
|
+
details: { schemaRole },
|
|
1409
|
+
kind: "schema",
|
|
1410
|
+
references: [reference],
|
|
1411
|
+
runtimeName: reference.symbol ?? null,
|
|
1412
|
+
source: CLOUDFLARE_AGENTS_ADAPTER_ID
|
|
1413
|
+
}));
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
};
|
|
1417
|
+
/** Inspects manifest relationships for every supported Cloudflare runtime agent. */
|
|
1418
|
+
var inspectCloudflareAgentsRelationships = async (session, inspectedAgents, evidence, diagnostics) => {
|
|
1419
|
+
const verifiedAgents = Object.freeze(inspectedAgents.map(({ agent }) => agent));
|
|
1420
|
+
for (const inspected of inspectedAgents) {
|
|
1421
|
+
const bindings = inspected.agent.declaration.bindings;
|
|
1422
|
+
if (bindings?.instructionLoader !== void 0) await inspectBinding(session, inspected.agent, inspected.instructions, inspected.analysis, bindings.instructionLoader, "CLOUDFLARE_AGENTS_INSTRUCTION_LOADER_SYMBOL_NOT_FOUND", "CLOUDFLARE_AGENTS_INSTRUCTION_LOADER_NOT_WIRED", "instruction-loader", evidence, diagnostics);
|
|
1423
|
+
if (bindings?.outputSchema !== void 0) await inspectBinding(session, inspected.agent, getCloudflareAgentsOutputSchema(inspected.output, inspected.analysis), inspected.analysis, bindings.outputSchema, "CLOUDFLARE_AGENTS_AGENT_OUTPUT_SCHEMA_SYMBOL_NOT_FOUND", "CLOUDFLARE_AGENTS_AGENT_OUTPUT_SCHEMA_NOT_WIRED", "schema", evidence, diagnostics, "agent-output");
|
|
1424
|
+
await inspectTools(session, inspected, verifiedAgents, evidence, diagnostics);
|
|
1425
|
+
}
|
|
1426
|
+
};
|
|
1427
|
+
//#endregion
|
|
1428
|
+
//#region src/package-discovery/index.ts
|
|
1429
|
+
var PACKAGE_NAMES = Object.freeze([
|
|
1430
|
+
CLOUDFLARE_THINK_PACKAGE_NAME,
|
|
1431
|
+
CLOUDFLARE_AI_CHAT_PACKAGE_NAME,
|
|
1432
|
+
CLOUDFLARE_AGENTS_PACKAGE_NAME,
|
|
1433
|
+
"ai"
|
|
1434
|
+
]);
|
|
1435
|
+
var DEPENDENCY_FIELDS = Object.freeze([
|
|
1436
|
+
"dependencies",
|
|
1437
|
+
"optionalDependencies",
|
|
1438
|
+
"peerDependencies",
|
|
1439
|
+
"devDependencies"
|
|
1440
|
+
]);
|
|
1441
|
+
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1442
|
+
/** Creates nearest-to-root package-manifest candidates for one source path. */
|
|
1443
|
+
var createCloudflareAgentsPackageManifestCandidatePaths = (sourcePath) => createPackageManifestCandidatePaths(sourcePath).map((path) => parseRepositoryPath(path));
|
|
1444
|
+
var extractDeclarations = (manifest) => {
|
|
1445
|
+
const declarations = /* @__PURE__ */ new Map();
|
|
1446
|
+
for (const field of DEPENDENCY_FIELDS) {
|
|
1447
|
+
const dependencies = manifest[field];
|
|
1448
|
+
if (dependencies === void 0) continue;
|
|
1449
|
+
if (!isRecord(dependencies)) return null;
|
|
1450
|
+
for (const packageName of PACKAGE_NAMES) {
|
|
1451
|
+
const declaredRange = dependencies[packageName];
|
|
1452
|
+
if (declaredRange === void 0) continue;
|
|
1453
|
+
if (typeof declaredRange !== "string" || declaredRange.trim().length === 0) return null;
|
|
1454
|
+
const entries = declarations.get(packageName) ?? [];
|
|
1455
|
+
entries.push(Object.freeze({
|
|
1456
|
+
declaredRange,
|
|
1457
|
+
dependencyKind: field
|
|
1458
|
+
}));
|
|
1459
|
+
declarations.set(packageName, entries);
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
return new Map([...declarations].map(([packageName, entries]) => [packageName, Object.freeze(entries)]));
|
|
1463
|
+
};
|
|
1464
|
+
/** Discovers the nearest manifest containing a Cloudflare Agents target dependency. */
|
|
1465
|
+
var discoverCloudflareAgentsPackage = async (repository, sourcePath, signal) => {
|
|
1466
|
+
const options = signal === void 0 ? void 0 : { signal };
|
|
1467
|
+
for (const candidatePath of createCloudflareAgentsPackageManifestCandidatePaths(sourcePath)) {
|
|
1468
|
+
signal?.throwIfAborted();
|
|
1469
|
+
const entry = await repository.getEntry(candidatePath, options);
|
|
1470
|
+
if (entry === null) continue;
|
|
1471
|
+
if (entry.type !== "file") return Object.freeze({
|
|
1472
|
+
kind: "invalid",
|
|
1473
|
+
path: candidatePath
|
|
1474
|
+
});
|
|
1475
|
+
const text = normalizeText(await repository.readFile(candidatePath, options));
|
|
1476
|
+
if (!text.valid) return Object.freeze({
|
|
1477
|
+
kind: "invalid",
|
|
1478
|
+
path: candidatePath
|
|
1479
|
+
});
|
|
1480
|
+
let parsed;
|
|
1481
|
+
try {
|
|
1482
|
+
parsed = JSON.parse(text.value);
|
|
1483
|
+
} catch {
|
|
1484
|
+
return Object.freeze({
|
|
1485
|
+
kind: "invalid",
|
|
1486
|
+
path: candidatePath
|
|
1487
|
+
});
|
|
1488
|
+
}
|
|
1489
|
+
if (!isRecord(parsed)) return Object.freeze({
|
|
1490
|
+
kind: "invalid",
|
|
1491
|
+
path: candidatePath
|
|
1492
|
+
});
|
|
1493
|
+
const declarations = extractDeclarations(parsed);
|
|
1494
|
+
if (declarations === null) return Object.freeze({
|
|
1495
|
+
kind: "invalid",
|
|
1496
|
+
path: candidatePath
|
|
1497
|
+
});
|
|
1498
|
+
if (!declarations.has("@cloudflare/think") && !declarations.has("@cloudflare/ai-chat")) return Object.freeze({ kind: "absent" });
|
|
1499
|
+
return Object.freeze({
|
|
1500
|
+
kind: "observed",
|
|
1501
|
+
observation: Object.freeze({
|
|
1502
|
+
declarations,
|
|
1503
|
+
path: parseRepositoryPath(posix.normalize(candidatePath))
|
|
1504
|
+
})
|
|
1505
|
+
});
|
|
1506
|
+
}
|
|
1507
|
+
return Object.freeze({ kind: "absent" });
|
|
1508
|
+
};
|
|
1509
|
+
//#endregion
|
|
1510
|
+
//#region src/inspection/session.ts
|
|
1511
|
+
/** Creates one operation-local Cloudflare Agents inspection session. */
|
|
1512
|
+
var createCloudflareAgentsInspectionSession = (context) => createInspectionSession({
|
|
1513
|
+
analyzeSource: analyzeCloudflareAgentsSource,
|
|
1514
|
+
discoverPackage: (path, signal) => discoverCloudflareAgentsPackage(context.repository, path, signal),
|
|
1515
|
+
getEntry: (path, signal) => context.repository.getEntry(path, signal === void 0 ? void 0 : { signal }),
|
|
1516
|
+
readFile: (path, signal) => context.repository.readFile(path, signal === void 0 ? void 0 : { signal }),
|
|
1517
|
+
...context.signal === void 0 ? {} : { signal: context.signal }
|
|
1518
|
+
});
|
|
1519
|
+
//#endregion
|
|
1520
|
+
//#region src/inspection/inspection.ts
|
|
1521
|
+
var combineRelationships = (relationships) => {
|
|
1522
|
+
const present = relationships.filter((relationship) => relationship.kind === "present");
|
|
1523
|
+
if (relationships.some((relationship) => relationship.kind === "unresolved") || present.length > 1) return Object.freeze({ kind: "unresolved" });
|
|
1524
|
+
return Object.freeze(present[0] ?? { kind: "absent" });
|
|
1525
|
+
};
|
|
1526
|
+
var inspectAgent = async (session, agent, evidence, diagnostics) => {
|
|
1527
|
+
const runtimeAgent = agent.declaration.bindings?.runtimeAgent;
|
|
1528
|
+
if (runtimeAgent === void 0 || !isSupportedTypeScriptSourcePath(runtimeAgent.path)) return null;
|
|
1529
|
+
evidence.push(createCloudflareAgentsEvidence({
|
|
1530
|
+
agentId: agent.id,
|
|
1531
|
+
capabilityId: null,
|
|
1532
|
+
capabilityKind: null,
|
|
1533
|
+
details: { language: "typescript" },
|
|
1534
|
+
kind: "language",
|
|
1535
|
+
references: [runtimeAgent],
|
|
1536
|
+
runtimeName: null,
|
|
1537
|
+
source: CLOUDFLARE_AGENTS_ADAPTER_ID
|
|
1538
|
+
}));
|
|
1539
|
+
if (runtimeAgent.symbol === void 0) return null;
|
|
1540
|
+
const analysis = await analyzeCloudflareAgentsBoundReference(session, runtimeAgent, diagnostics, agent.id);
|
|
1541
|
+
if (analysis === null) return null;
|
|
1542
|
+
if (!analysis.exports.has(runtimeAgent.symbol)) {
|
|
1543
|
+
addCloudflareAgentsDiagnostic(diagnostics, "CLOUDFLARE_AGENTS_RUNTIME_AGENT_SYMBOL_NOT_FOUND", runtimeAgent.path, agent.id);
|
|
1544
|
+
return null;
|
|
1545
|
+
}
|
|
1546
|
+
const classResult = getCloudflareAgentsClassDefinition(analysis, runtimeAgent.symbol);
|
|
1547
|
+
if (classResult.kind === "absent") return null;
|
|
1548
|
+
const targetId = classResult.kind === "present-supported" ? classResult.definition.targetId : classResult.targetId;
|
|
1549
|
+
if (targetId === void 0) return null;
|
|
1550
|
+
if (!await inspectCloudflareAgentsPackage(session, runtimeAgent.path, targetId, evidence, diagnostics, agent.id)) return null;
|
|
1551
|
+
evidence.push(createCloudflareAgentsEvidence({
|
|
1552
|
+
agentId: agent.id,
|
|
1553
|
+
capabilityId: null,
|
|
1554
|
+
capabilityKind: null,
|
|
1555
|
+
details: { targetId },
|
|
1556
|
+
kind: "agent-definition",
|
|
1557
|
+
references: [runtimeAgent],
|
|
1558
|
+
runtimeName: runtimeAgent.symbol,
|
|
1559
|
+
source: CLOUDFLARE_AGENTS_ADAPTER_ID
|
|
1560
|
+
}));
|
|
1561
|
+
if (classResult.kind !== "present-supported") return null;
|
|
1562
|
+
if (classResult.definition.targetId === "typescript-ai-chat-agent-0-10-ai-sdk-7") {
|
|
1563
|
+
const requests = getCloudflareAgentsAiChatRequests(classResult.definition, analysis);
|
|
1564
|
+
if (requests.length === 0) return Object.freeze({
|
|
1565
|
+
agent,
|
|
1566
|
+
analysis,
|
|
1567
|
+
definition: classResult.definition,
|
|
1568
|
+
instructions: Object.freeze({ kind: "absent" }),
|
|
1569
|
+
output: Object.freeze({ kind: "absent" }),
|
|
1570
|
+
requests,
|
|
1571
|
+
tools: Object.freeze([])
|
|
1572
|
+
});
|
|
1573
|
+
evidence.push(createCloudflareAgentsEvidence({
|
|
1574
|
+
agentId: agent.id,
|
|
1575
|
+
capabilityId: null,
|
|
1576
|
+
capabilityKind: null,
|
|
1577
|
+
details: { calls: [...new Set(requests.map(({ call }) => call))].join(",") },
|
|
1578
|
+
kind: "runtime-pattern",
|
|
1579
|
+
references: [runtimeAgent],
|
|
1580
|
+
runtimeName: runtimeAgent.symbol,
|
|
1581
|
+
source: CLOUDFLARE_AGENTS_ADAPTER_ID
|
|
1582
|
+
}));
|
|
1583
|
+
return Object.freeze({
|
|
1584
|
+
agent,
|
|
1585
|
+
analysis,
|
|
1586
|
+
definition: classResult.definition,
|
|
1587
|
+
instructions: combineRelationships(requests.map(({ instructions }) => instructions)),
|
|
1588
|
+
output: combineRelationships(requests.map(({ output }) => output)),
|
|
1589
|
+
requests,
|
|
1590
|
+
tools: Object.freeze(requests.map(({ tools }) => tools))
|
|
1591
|
+
});
|
|
1592
|
+
}
|
|
1593
|
+
const thinkTools = combineRelationships([getCloudflareAgentsThinkTools(classResult.definition), getCloudflareAgentsThinkChannelTools(classResult.definition)]);
|
|
1594
|
+
return Object.freeze({
|
|
1595
|
+
agent,
|
|
1596
|
+
analysis,
|
|
1597
|
+
definition: classResult.definition,
|
|
1598
|
+
instructions: combineRelationships([getCloudflareAgentsThinkSystemPrompt(classResult.definition), getCloudflareAgentsThinkSessionInstructions(classResult.definition)]),
|
|
1599
|
+
output: Object.freeze({ kind: "absent" }),
|
|
1600
|
+
requests: Object.freeze([]),
|
|
1601
|
+
tools: Object.freeze([thinkTools])
|
|
1602
|
+
});
|
|
1603
|
+
};
|
|
1604
|
+
/**
|
|
1605
|
+
* Inspects all scoped Cloudflare Agents agents through one deterministic session.
|
|
1606
|
+
* @param context The Core-provided immutable adapter context.
|
|
1607
|
+
* @returns A promise resolving to source-grounded evidence and diagnostics.
|
|
1608
|
+
* @throws
|
|
1609
|
+
* - INVALID_REPOSITORY_PATH: The repository path is invalid.
|
|
1610
|
+
* - ENTRY_NOT_FOUND: The requested repository entry was not found.
|
|
1611
|
+
* - ENTRY_NOT_FILE: The requested repository entry is not a file.
|
|
1612
|
+
* - ACCESS_DENIED: Access to the repository source was denied.
|
|
1613
|
+
* - SOURCE_UNAVAILABLE: The repository source is unavailable.
|
|
1614
|
+
* - SNAPSHOT_CHANGED: The repository snapshot changed during the operation.
|
|
1615
|
+
* - INVALID_SOURCE_DATA: The repository source returned invalid data.
|
|
1616
|
+
* - RESOURCE_LIMIT_EXCEEDED: A repository reading resource limit was exceeded.
|
|
1617
|
+
* - ABORTED: The repository operation or inspection signal was aborted.
|
|
1618
|
+
*/
|
|
1619
|
+
var inspectCloudflareAgents = async (context) => {
|
|
1620
|
+
context.signal?.throwIfAborted();
|
|
1621
|
+
const session = createCloudflareAgentsInspectionSession(context);
|
|
1622
|
+
const evidence = [];
|
|
1623
|
+
const diagnostics = [];
|
|
1624
|
+
const agents = [...context.agents].sort((left, right) => compareCloudflareAgentsStrings(left.id, right.id));
|
|
1625
|
+
const inspectedAgents = [];
|
|
1626
|
+
for (const agent of agents) {
|
|
1627
|
+
context.signal?.throwIfAborted();
|
|
1628
|
+
const inspected = await inspectAgent(session, agent, evidence, diagnostics);
|
|
1629
|
+
if (inspected !== null) inspectedAgents.push(inspected);
|
|
1630
|
+
}
|
|
1631
|
+
context.signal?.throwIfAborted();
|
|
1632
|
+
await inspectCloudflareAgentsRelationships(session, inspectedAgents, evidence, diagnostics);
|
|
1633
|
+
return Object.freeze({
|
|
1634
|
+
diagnostics: Object.freeze(diagnostics),
|
|
1635
|
+
evidence: Object.freeze(evidence)
|
|
1636
|
+
});
|
|
1637
|
+
};
|
|
1638
|
+
//#endregion
|
|
1639
|
+
//#region src/adapter/index.ts
|
|
1640
|
+
var cloudflareAgentsAdapter = Object.freeze({
|
|
1641
|
+
id: CLOUDFLARE_AGENTS_ADAPTER_ID,
|
|
1642
|
+
inspect: inspectCloudflareAgents,
|
|
1643
|
+
supportedRepositoryFormatVersions: CLOUDFLARE_AGENTS_SUPPORTED_REPOSITORY_FORMAT_VERSIONS
|
|
1644
|
+
});
|
|
1645
|
+
//#endregion
|
|
1646
|
+
export { cloudflareAgentsAdapter };
|