@mondaydotcomorg/atp-server 0.20.7 → 0.21.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/aggregator/index.d.ts +17 -1
- package/dist/aggregator/index.d.ts.map +1 -1
- package/dist/aggregator/index.js +68 -0
- package/dist/aggregator/index.js.map +1 -1
- package/dist/explorer/index.d.ts +1 -18
- package/dist/explorer/index.d.ts.map +1 -1
- package/dist/explorer/index.js +4 -65
- package/dist/explorer/index.js.map +1 -1
- package/dist/index.cjs +881 -880
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +881 -880
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
- package/src/aggregator/index.ts +81 -0
- package/src/core/request-scope.ts +3 -0
- package/src/explorer/index.ts +4 -79
package/dist/index.cjs
CHANGED
|
@@ -10385,371 +10385,635 @@ var ExecutionStateManager = class {
|
|
|
10385
10385
|
};
|
|
10386
10386
|
}
|
|
10387
10387
|
};
|
|
10388
|
-
|
|
10389
|
-
// src/explorer/index.ts
|
|
10390
|
-
var ExplorerService = class {
|
|
10388
|
+
var APIAggregator = class {
|
|
10391
10389
|
static {
|
|
10392
|
-
__name(this, "
|
|
10390
|
+
__name(this, "APIAggregator");
|
|
10393
10391
|
}
|
|
10394
|
-
root;
|
|
10395
10392
|
apiGroups;
|
|
10396
|
-
|
|
10393
|
+
/**
|
|
10394
|
+
* Creates a new APIAggregator instance.
|
|
10395
|
+
* @param apiGroups - Array of API group configurations
|
|
10396
|
+
*/
|
|
10397
10397
|
constructor(apiGroups) {
|
|
10398
10398
|
this.apiGroups = apiGroups;
|
|
10399
|
-
this.apiGroupMap = new Map(apiGroups.map((group) => [
|
|
10400
|
-
group.name,
|
|
10401
|
-
group
|
|
10402
|
-
]));
|
|
10403
|
-
this.root = {
|
|
10404
|
-
type: "directory",
|
|
10405
|
-
name: "/",
|
|
10406
|
-
children: /* @__PURE__ */ new Map()
|
|
10407
|
-
};
|
|
10408
|
-
this.buildTree(apiGroups);
|
|
10409
10399
|
}
|
|
10410
10400
|
/**
|
|
10411
|
-
*
|
|
10412
|
-
*
|
|
10401
|
+
* Generates TypeScript type definitions for selected API groups.
|
|
10402
|
+
* @param selectedGroups - Optional array of group names to include
|
|
10403
|
+
* @returns TypeScript definition string
|
|
10413
10404
|
*/
|
|
10414
|
-
|
|
10415
|
-
const
|
|
10416
|
-
|
|
10417
|
-
|
|
10418
|
-
|
|
10419
|
-
|
|
10420
|
-
|
|
10421
|
-
|
|
10422
|
-
|
|
10423
|
-
|
|
10424
|
-
context.allowedTypes.add(group.type);
|
|
10425
|
-
}
|
|
10426
|
-
context.allowedGroups.add(group.name);
|
|
10427
|
-
}
|
|
10428
|
-
for (const group of this.apiGroups) {
|
|
10429
|
-
if (!context.allowedGroups.has(group.name)) continue;
|
|
10405
|
+
async generateTypeScript(selectedGroups) {
|
|
10406
|
+
const groups = selectedGroups ? this.apiGroups.filter((g) => selectedGroups.includes(g.name)) : this.apiGroups;
|
|
10407
|
+
let typescript = `// Agent Tool Protocol Runtime SDK v1.0.0
|
|
10408
|
+
|
|
10409
|
+
`;
|
|
10410
|
+
typescript += this.generateRuntimeTypes();
|
|
10411
|
+
for (const group of groups) {
|
|
10412
|
+
typescript += `
|
|
10413
|
+
// API Group: ${group.name}
|
|
10414
|
+
`;
|
|
10430
10415
|
if (group.functions) {
|
|
10431
10416
|
for (const func of group.functions) {
|
|
10432
|
-
|
|
10417
|
+
typescript += this.generateFunctionTypes(func, group.name);
|
|
10433
10418
|
}
|
|
10434
10419
|
}
|
|
10435
10420
|
}
|
|
10436
|
-
|
|
10421
|
+
typescript += this.generateAPINamespace(groups);
|
|
10422
|
+
return typescript;
|
|
10437
10423
|
}
|
|
10438
10424
|
/**
|
|
10439
|
-
*
|
|
10425
|
+
* Generates TypeScript definitions for the runtime SDK.
|
|
10426
|
+
* @param options - Optional filtering options
|
|
10427
|
+
* @returns TypeScript definition string
|
|
10440
10428
|
*/
|
|
10441
|
-
|
|
10442
|
-
|
|
10443
|
-
"openapi",
|
|
10444
|
-
"mcp",
|
|
10445
|
-
"custom",
|
|
10446
|
-
"graphql"
|
|
10447
|
-
];
|
|
10448
|
-
if (currentPath === "/" && API_TYPES.includes(name)) {
|
|
10449
|
-
return ctx.allowedTypes.has(name) || ctx.allowedGroups.has(name);
|
|
10450
|
-
}
|
|
10451
|
-
if (ctx.allGroups.has(name)) {
|
|
10452
|
-
return ctx.allowedGroups.has(name);
|
|
10453
|
-
}
|
|
10454
|
-
return true;
|
|
10429
|
+
generateRuntimeTypes(options) {
|
|
10430
|
+
return atpRuntime.generateRuntimeTypes(atpRuntime.GENERATED_METADATA, options);
|
|
10455
10431
|
}
|
|
10456
10432
|
/**
|
|
10457
|
-
*
|
|
10433
|
+
* Generates TypeScript types for a single function.
|
|
10434
|
+
* @param func - Function definition
|
|
10435
|
+
* @param groupName - API group name
|
|
10436
|
+
* @returns TypeScript definition string
|
|
10458
10437
|
*/
|
|
10459
|
-
|
|
10460
|
-
|
|
10461
|
-
|
|
10462
|
-
|
|
10463
|
-
|
|
10464
|
-
|
|
10465
|
-
|
|
10466
|
-
|
|
10467
|
-
|
|
10468
|
-
|
|
10469
|
-
|
|
10470
|
-
const
|
|
10471
|
-
|
|
10472
|
-
|
|
10473
|
-
|
|
10474
|
-
current = this.ensureDirectory(current, segments[i]);
|
|
10475
|
-
}
|
|
10476
|
-
this.addFunction(current, segments[segments.length - 1], func, group.name);
|
|
10477
|
-
} else {
|
|
10478
|
-
this.addFunction(groupFolder, func.name, func, group.name);
|
|
10479
|
-
}
|
|
10438
|
+
generateFunctionTypes(func, groupName) {
|
|
10439
|
+
const inputTypeName = `${func.name}_Input`;
|
|
10440
|
+
const outputTypeName = `${func.name}_Output`;
|
|
10441
|
+
let typescript = `
|
|
10442
|
+
interface ${inputTypeName} {
|
|
10443
|
+
`;
|
|
10444
|
+
if (func.inputSchema?.properties) {
|
|
10445
|
+
const required = func.inputSchema.required || [];
|
|
10446
|
+
for (const [key, value] of Object.entries(func.inputSchema.properties)) {
|
|
10447
|
+
const prop = value;
|
|
10448
|
+
const tsType = this.jsonSchemaTypeToTS(prop.type ?? "any");
|
|
10449
|
+
const comment = prop.description ? ` // ${prop.description}` : "";
|
|
10450
|
+
const optional = required.includes(key) ? "" : "?";
|
|
10451
|
+
typescript += ` ${key}${optional}: ${tsType};${comment}
|
|
10452
|
+
`;
|
|
10480
10453
|
}
|
|
10481
10454
|
}
|
|
10455
|
+
typescript += `}
|
|
10456
|
+
`;
|
|
10457
|
+
typescript += `
|
|
10458
|
+
interface ${outputTypeName} {
|
|
10459
|
+
`;
|
|
10460
|
+
if (func.outputSchema) {
|
|
10461
|
+
const outputType = this.jsonSchemaToTSInterface(func.outputSchema);
|
|
10462
|
+
typescript += outputType;
|
|
10463
|
+
} else {
|
|
10464
|
+
typescript += ` [key: string]: unknown;
|
|
10465
|
+
`;
|
|
10466
|
+
}
|
|
10467
|
+
typescript += `}
|
|
10468
|
+
`;
|
|
10469
|
+
return typescript;
|
|
10482
10470
|
}
|
|
10483
10471
|
/**
|
|
10484
|
-
*
|
|
10472
|
+
* Converts JSON Schema type to TypeScript type.
|
|
10473
|
+
* @param type - JSON Schema type string
|
|
10474
|
+
* @returns TypeScript type string
|
|
10485
10475
|
*/
|
|
10486
|
-
|
|
10487
|
-
|
|
10488
|
-
|
|
10489
|
-
|
|
10490
|
-
|
|
10491
|
-
|
|
10492
|
-
|
|
10493
|
-
|
|
10494
|
-
|
|
10495
|
-
|
|
10496
|
-
return [
|
|
10497
|
-
|
|
10498
|
-
|
|
10499
|
-
|
|
10500
|
-
|
|
10501
|
-
}
|
|
10502
|
-
if (group.type === "openapi") {
|
|
10503
|
-
const name = func.name;
|
|
10504
|
-
const camelSplit = name.match(/[A-Z]?[a-z]+|[A-Z]+(?=[A-Z][a-z]|\b)/g);
|
|
10505
|
-
if (camelSplit && camelSplit.length > 2) {
|
|
10506
|
-
const verb = camelSplit[0].toLowerCase();
|
|
10507
|
-
const isVerb = [
|
|
10508
|
-
"get",
|
|
10509
|
-
"list",
|
|
10510
|
-
"create",
|
|
10511
|
-
"update",
|
|
10512
|
-
"delete",
|
|
10513
|
-
"post",
|
|
10514
|
-
"put",
|
|
10515
|
-
"patch"
|
|
10516
|
-
].includes(verb);
|
|
10517
|
-
if (isVerb) {
|
|
10518
|
-
const resource = camelSplit.slice(1).join("_").toLowerCase();
|
|
10519
|
-
return [
|
|
10520
|
-
resource,
|
|
10521
|
-
name
|
|
10522
|
-
];
|
|
10523
|
-
}
|
|
10524
|
-
}
|
|
10525
|
-
if (name.includes("_")) {
|
|
10526
|
-
const parts = name.split("_");
|
|
10527
|
-
if (parts.length > 1 && parts[0]) {
|
|
10528
|
-
return [
|
|
10529
|
-
parts[0],
|
|
10530
|
-
name
|
|
10531
|
-
];
|
|
10532
|
-
}
|
|
10533
|
-
}
|
|
10534
|
-
if (name.includes("-")) {
|
|
10535
|
-
const parts = name.split("-");
|
|
10536
|
-
if (parts.length > 1 && parts[0]) {
|
|
10537
|
-
return [
|
|
10538
|
-
parts[0],
|
|
10539
|
-
name
|
|
10540
|
-
];
|
|
10541
|
-
}
|
|
10542
|
-
}
|
|
10476
|
+
jsonSchemaTypeToTS(type) {
|
|
10477
|
+
switch (type) {
|
|
10478
|
+
case "string":
|
|
10479
|
+
return "string";
|
|
10480
|
+
case "number":
|
|
10481
|
+
case "integer":
|
|
10482
|
+
return "number";
|
|
10483
|
+
case "boolean":
|
|
10484
|
+
return "boolean";
|
|
10485
|
+
case "array":
|
|
10486
|
+
return "unknown[]";
|
|
10487
|
+
case "object":
|
|
10488
|
+
return "Record<string, unknown>";
|
|
10489
|
+
default:
|
|
10490
|
+
return "unknown";
|
|
10543
10491
|
}
|
|
10544
|
-
return [
|
|
10545
|
-
func.name
|
|
10546
|
-
];
|
|
10547
10492
|
}
|
|
10548
10493
|
/**
|
|
10549
|
-
*
|
|
10494
|
+
* Converts a full JSON Schema to TypeScript interface properties
|
|
10495
|
+
* @param schema - JSON Schema object
|
|
10496
|
+
* @param depth - Current recursion depth (prevents infinite recursion)
|
|
10497
|
+
* @returns TypeScript interface properties string
|
|
10550
10498
|
*/
|
|
10551
|
-
|
|
10552
|
-
if (
|
|
10553
|
-
|
|
10499
|
+
jsonSchemaToTSInterface(schema, depth = 0) {
|
|
10500
|
+
if (depth > 3) {
|
|
10501
|
+
return " [key: string]: unknown;\n";
|
|
10554
10502
|
}
|
|
10555
|
-
|
|
10556
|
-
|
|
10557
|
-
|
|
10558
|
-
|
|
10559
|
-
|
|
10560
|
-
description,
|
|
10561
|
-
children: /* @__PURE__ */ new Map()
|
|
10562
|
-
};
|
|
10563
|
-
parent.children.set(name, child);
|
|
10564
|
-
} else if (description && !child.description) {
|
|
10565
|
-
child.description = description;
|
|
10503
|
+
if (schema.type === "array" && schema.items) {
|
|
10504
|
+
const itemType = this.schemaToTSType(schema.items, depth + 1);
|
|
10505
|
+
return ` [index: number]: ${itemType};
|
|
10506
|
+
length: number;
|
|
10507
|
+
`;
|
|
10566
10508
|
}
|
|
10567
|
-
|
|
10509
|
+
if (schema.type === "object" && schema.properties) {
|
|
10510
|
+
const required = schema.required || [];
|
|
10511
|
+
let result = "";
|
|
10512
|
+
for (const [key, value] of Object.entries(schema.properties)) {
|
|
10513
|
+
const prop = value;
|
|
10514
|
+
const optional = required.includes(key) ? "" : "?";
|
|
10515
|
+
const tsType = this.schemaToTSType(prop, depth + 1);
|
|
10516
|
+
result += ` ${key}${optional}: ${tsType};
|
|
10517
|
+
`;
|
|
10518
|
+
}
|
|
10519
|
+
return result || " [key: string]: unknown;\n";
|
|
10520
|
+
}
|
|
10521
|
+
return " [key: string]: unknown;\n";
|
|
10568
10522
|
}
|
|
10569
10523
|
/**
|
|
10570
|
-
*
|
|
10571
|
-
|
|
10572
|
-
|
|
10573
|
-
|
|
10574
|
-
|
|
10524
|
+
* Converts any JSON Schema to a TypeScript type expression
|
|
10525
|
+
* @param schema - JSON Schema object
|
|
10526
|
+
* @param depth - Current recursion depth
|
|
10527
|
+
* @returns TypeScript type expression
|
|
10528
|
+
*/
|
|
10529
|
+
schemaToTSType(schema, depth = 0) {
|
|
10530
|
+
if (!schema) return "unknown";
|
|
10531
|
+
if (depth > 3) {
|
|
10532
|
+
return "unknown";
|
|
10575
10533
|
}
|
|
10576
|
-
|
|
10577
|
-
|
|
10578
|
-
|
|
10579
|
-
|
|
10580
|
-
func,
|
|
10581
|
-
group
|
|
10534
|
+
if (schema.type === "array") {
|
|
10535
|
+
if (schema.items) {
|
|
10536
|
+
const itemType = this.schemaToTSType(schema.items, depth + 1);
|
|
10537
|
+
return `${itemType}[]`;
|
|
10582
10538
|
}
|
|
10583
|
-
|
|
10539
|
+
return "unknown[]";
|
|
10540
|
+
}
|
|
10541
|
+
if (schema.enum) {
|
|
10542
|
+
return schema.enum.map((v) => `"${v}"`).join(" | ") || "string";
|
|
10543
|
+
}
|
|
10544
|
+
if (schema.type === "object" && schema.properties) {
|
|
10545
|
+
const required = schema.required || [];
|
|
10546
|
+
const props = [];
|
|
10547
|
+
for (const [key, value] of Object.entries(schema.properties)) {
|
|
10548
|
+
const prop = value;
|
|
10549
|
+
const optional = required.includes(key) ? "" : "?";
|
|
10550
|
+
const tsType = this.schemaToTSType(prop, depth + 1);
|
|
10551
|
+
props.push(`${key}${optional}: ${tsType}`);
|
|
10552
|
+
}
|
|
10553
|
+
if (props.length > 0) {
|
|
10554
|
+
return `{ ${props.join("; ")} }`;
|
|
10555
|
+
}
|
|
10556
|
+
return "Record<string, unknown>";
|
|
10557
|
+
}
|
|
10558
|
+
if (schema.type) {
|
|
10559
|
+
return this.jsonSchemaTypeToTS(schema.type);
|
|
10560
|
+
}
|
|
10561
|
+
return "unknown";
|
|
10584
10562
|
}
|
|
10585
10563
|
/**
|
|
10586
|
-
*
|
|
10587
|
-
* Tool rules are automatically applied from the request scope.
|
|
10588
|
-
* @param path - The path to explore
|
|
10564
|
+
* Helper to check if a string is a valid JavaScript identifier
|
|
10589
10565
|
*/
|
|
10590
|
-
|
|
10591
|
-
|
|
10592
|
-
|
|
10593
|
-
|
|
10594
|
-
|
|
10595
|
-
|
|
10596
|
-
|
|
10597
|
-
|
|
10598
|
-
|
|
10599
|
-
}
|
|
10600
|
-
current = current.children.get(segment);
|
|
10601
|
-
currentPath = currentPath === "/" ? `/${segment}` : `${currentPath}/${segment}`;
|
|
10566
|
+
isValidIdentifier(name) {
|
|
10567
|
+
return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
|
|
10568
|
+
}
|
|
10569
|
+
/**
|
|
10570
|
+
* Helper to safely format a property name for TypeScript type definitions
|
|
10571
|
+
* Returns the property name with quotes if needed, or just the name if valid
|
|
10572
|
+
*/
|
|
10573
|
+
formatPropertyName(name) {
|
|
10574
|
+
if (!this.isValidIdentifier(name)) {
|
|
10575
|
+
return `'${name}'`;
|
|
10602
10576
|
}
|
|
10603
|
-
|
|
10604
|
-
|
|
10605
|
-
|
|
10606
|
-
|
|
10607
|
-
|
|
10608
|
-
|
|
10609
|
-
|
|
10610
|
-
|
|
10611
|
-
|
|
10612
|
-
|
|
10613
|
-
|
|
10614
|
-
|
|
10615
|
-
|
|
10616
|
-
|
|
10617
|
-
|
|
10618
|
-
|
|
10619
|
-
|
|
10620
|
-
|
|
10621
|
-
|
|
10577
|
+
return name;
|
|
10578
|
+
}
|
|
10579
|
+
/**
|
|
10580
|
+
* Generates the API namespace with all function declarations.
|
|
10581
|
+
* Handles hierarchical group names (e.g., "github/readOnly" -> api.github.readOnly)
|
|
10582
|
+
* @param groups - API groups to include
|
|
10583
|
+
* @returns TypeScript definition string
|
|
10584
|
+
*/
|
|
10585
|
+
generateAPINamespace(groups) {
|
|
10586
|
+
const rootGroups = /* @__PURE__ */ new Map();
|
|
10587
|
+
for (const group of groups) {
|
|
10588
|
+
if (!group.functions || group.functions.length === 0) continue;
|
|
10589
|
+
const parts = group.name.split("/");
|
|
10590
|
+
let current = rootGroups;
|
|
10591
|
+
for (let i = 0; i < parts.length; i++) {
|
|
10592
|
+
const part = parts[i];
|
|
10593
|
+
if (!current.has(part)) {
|
|
10594
|
+
current.set(part, {
|
|
10595
|
+
functions: [],
|
|
10596
|
+
subgroups: /* @__PURE__ */ new Map()
|
|
10597
|
+
});
|
|
10622
10598
|
}
|
|
10599
|
+
const node = current.get(part);
|
|
10600
|
+
if (i === parts.length - 1) {
|
|
10601
|
+
node.functions.push(...group.functions);
|
|
10602
|
+
}
|
|
10603
|
+
current = node.subgroups;
|
|
10623
10604
|
}
|
|
10624
|
-
|
|
10625
|
-
|
|
10626
|
-
|
|
10605
|
+
}
|
|
10606
|
+
const generateLevel = /* @__PURE__ */ __name((groups2, indent2) => {
|
|
10607
|
+
let ts = "";
|
|
10608
|
+
for (const [name, node] of groups2.entries()) {
|
|
10609
|
+
if (!name) continue;
|
|
10610
|
+
const formattedName = this.formatPropertyName(name);
|
|
10611
|
+
ts += `${indent2}${formattedName}: {
|
|
10612
|
+
`;
|
|
10613
|
+
for (const func of node.functions) {
|
|
10614
|
+
if (!func.name) continue;
|
|
10615
|
+
const funcName = this.formatPropertyName(func.name);
|
|
10616
|
+
const description = func.description && typeof func.description === "string" ? func.description.replace(/\n/g, " ").substring(0, 200) : "";
|
|
10617
|
+
ts += `${indent2} /**
|
|
10618
|
+
${indent2} * ${description}
|
|
10619
|
+
${indent2} */
|
|
10620
|
+
`;
|
|
10621
|
+
ts += `${indent2} ${funcName}(params: ${func.name}_Input): Promise<${func.name}_Output>;
|
|
10622
|
+
`;
|
|
10627
10623
|
}
|
|
10628
|
-
|
|
10629
|
-
|
|
10630
|
-
const result = {
|
|
10631
|
-
type: "directory",
|
|
10632
|
-
path: currentPath,
|
|
10633
|
-
items
|
|
10634
|
-
};
|
|
10635
|
-
if (current.apiGroupName) {
|
|
10636
|
-
const apiGroup = this.apiGroupMap.get(current.apiGroupName);
|
|
10637
|
-
if (apiGroup?.documentation) {
|
|
10638
|
-
result.documentation = apiGroup.documentation;
|
|
10624
|
+
if (node.subgroups.size > 0) {
|
|
10625
|
+
ts += generateLevel(node.subgroups, indent2 + " ");
|
|
10639
10626
|
}
|
|
10627
|
+
ts += `${indent2}};
|
|
10628
|
+
`;
|
|
10640
10629
|
}
|
|
10641
|
-
return
|
|
10642
|
-
}
|
|
10643
|
-
|
|
10644
|
-
|
|
10645
|
-
|
|
10646
|
-
|
|
10647
|
-
|
|
10648
|
-
|
|
10649
|
-
|
|
10650
|
-
|
|
10651
|
-
|
|
10652
|
-
|
|
10653
|
-
path: currentPath,
|
|
10654
|
-
name: func.name,
|
|
10655
|
-
description: func.description,
|
|
10656
|
-
definition,
|
|
10657
|
-
group,
|
|
10658
|
-
inputSchema: func.inputSchema,
|
|
10659
|
-
outputSchema: func.outputSchema
|
|
10660
|
-
};
|
|
10661
|
-
}
|
|
10630
|
+
return ts;
|
|
10631
|
+
}, "generateLevel");
|
|
10632
|
+
let typescript = `
|
|
10633
|
+
declare const api: {
|
|
10634
|
+
`;
|
|
10635
|
+
typescript += generateLevel(rootGroups, " ");
|
|
10636
|
+
typescript += `};
|
|
10637
|
+
`;
|
|
10638
|
+
typescript += `
|
|
10639
|
+
export { api };
|
|
10640
|
+
`;
|
|
10641
|
+
return typescript;
|
|
10662
10642
|
}
|
|
10663
10643
|
/**
|
|
10664
|
-
*
|
|
10644
|
+
* Gets the list of available API group names.
|
|
10645
|
+
* @returns Array of API group names
|
|
10665
10646
|
*/
|
|
10666
|
-
|
|
10667
|
-
|
|
10668
|
-
if (!path.startsWith("/")) {
|
|
10669
|
-
path = "/" + path;
|
|
10670
|
-
}
|
|
10671
|
-
if (path !== "/" && path.endsWith("/")) {
|
|
10672
|
-
path = path.slice(0, -1);
|
|
10673
|
-
}
|
|
10674
|
-
return path;
|
|
10647
|
+
getApiGroups() {
|
|
10648
|
+
return this.apiGroups.map((g) => g.name);
|
|
10675
10649
|
}
|
|
10676
10650
|
/**
|
|
10677
|
-
* Generates
|
|
10651
|
+
* Generates a compact TypeScript definition for a single function.
|
|
10652
|
+
* Includes input types with inline descriptions and compact output type.
|
|
10653
|
+
* @param func - Function definition
|
|
10654
|
+
* @param groupName - API group name
|
|
10655
|
+
* @returns Compact TypeScript definition string
|
|
10678
10656
|
*/
|
|
10679
|
-
|
|
10680
|
-
const
|
|
10681
|
-
const
|
|
10682
|
-
const outputType = func.outputSchema ? this.
|
|
10657
|
+
generateCompactFunctionDefinition(func, groupName) {
|
|
10658
|
+
const groupPath = groupName.replace(/\//g, ".");
|
|
10659
|
+
const inputType = this.generateCompactInputType(func.inputSchema);
|
|
10660
|
+
const outputType = func.outputSchema ? this.generateCompactOutputType(func.outputSchema) : "unknown";
|
|
10683
10661
|
return `async function api.${groupPath}.${func.name}(${inputType}): Promise<${outputType}>`;
|
|
10684
10662
|
}
|
|
10685
10663
|
/**
|
|
10686
|
-
* Generates
|
|
10664
|
+
* Generates compact input type with inline descriptions
|
|
10687
10665
|
*/
|
|
10688
|
-
|
|
10666
|
+
generateCompactInputType(schema) {
|
|
10689
10667
|
if (!schema || !schema.properties) {
|
|
10690
10668
|
return "{}";
|
|
10691
10669
|
}
|
|
10692
10670
|
const props = [];
|
|
10693
10671
|
const required = schema.required || [];
|
|
10694
10672
|
for (const [key, value] of Object.entries(schema.properties)) {
|
|
10695
|
-
const isRequired = required.includes(key);
|
|
10696
10673
|
const prop = value;
|
|
10697
|
-
const
|
|
10674
|
+
const isRequired = required.includes(key);
|
|
10675
|
+
const tsType = prop.enum ? prop.enum.map((v) => `"${v}"`).join(" | ") : this.jsonSchemaTypeToTS(prop.type ?? "unknown");
|
|
10698
10676
|
const optional = isRequired ? "" : "?";
|
|
10699
|
-
|
|
10677
|
+
if (prop.description) {
|
|
10678
|
+
const desc = prop.description.replace(/\n/g, " ").substring(0, 100);
|
|
10679
|
+
props.push(`/* ${desc} */ ${key}${optional}: ${tsType}`);
|
|
10680
|
+
} else {
|
|
10681
|
+
props.push(`${key}${optional}: ${tsType}`);
|
|
10682
|
+
}
|
|
10700
10683
|
}
|
|
10701
10684
|
return `{ ${props.join("; ")} }`;
|
|
10702
10685
|
}
|
|
10703
10686
|
/**
|
|
10704
|
-
* Generates output type
|
|
10687
|
+
* Generates compact output type with inline descriptions (top-level fields only, limited count)
|
|
10705
10688
|
*/
|
|
10706
|
-
|
|
10689
|
+
generateCompactOutputType(schema) {
|
|
10707
10690
|
if (!schema.properties) {
|
|
10708
10691
|
return "unknown";
|
|
10709
10692
|
}
|
|
10710
|
-
const
|
|
10711
|
-
|
|
10712
|
-
|
|
10713
|
-
const tsType = this.jsonSchemaTypeToTS(prop.type ?? "any");
|
|
10714
|
-
props.push(`${key}: ${tsType}`);
|
|
10693
|
+
const keys = Object.keys(schema.properties);
|
|
10694
|
+
if (keys.length === 0) {
|
|
10695
|
+
return "unknown";
|
|
10715
10696
|
}
|
|
10716
|
-
|
|
10717
|
-
|
|
10718
|
-
|
|
10719
|
-
|
|
10720
|
-
|
|
10721
|
-
|
|
10722
|
-
|
|
10723
|
-
|
|
10724
|
-
|
|
10725
|
-
|
|
10726
|
-
|
|
10727
|
-
|
|
10728
|
-
|
|
10729
|
-
return "boolean";
|
|
10730
|
-
case "array":
|
|
10731
|
-
return "any[]";
|
|
10732
|
-
case "object":
|
|
10733
|
-
return "Record<string, any>";
|
|
10734
|
-
default:
|
|
10735
|
-
return "any";
|
|
10697
|
+
const maxFields = 6;
|
|
10698
|
+
const displayKeys = keys.slice(0, maxFields);
|
|
10699
|
+
const props = displayKeys.map((key) => {
|
|
10700
|
+
const prop = schema.properties[key];
|
|
10701
|
+
const tsType = this.jsonSchemaTypeToTS(prop.type ?? "unknown");
|
|
10702
|
+
if (prop.description) {
|
|
10703
|
+
const desc = prop.description.replace(/\n/g, " ").substring(0, 80);
|
|
10704
|
+
return `/* ${desc} */ ${key}: ${tsType}`;
|
|
10705
|
+
}
|
|
10706
|
+
return `${key}: ${tsType}`;
|
|
10707
|
+
});
|
|
10708
|
+
if (keys.length > maxFields) {
|
|
10709
|
+
return `{ ${props.join("; ")}; /* +${keys.length - maxFields} more */ }`;
|
|
10736
10710
|
}
|
|
10711
|
+
return `{ ${props.join("; ")} }`;
|
|
10737
10712
|
}
|
|
10738
10713
|
};
|
|
10739
10714
|
|
|
10740
|
-
// src/
|
|
10741
|
-
|
|
10742
|
-
|
|
10743
|
-
|
|
10744
|
-
|
|
10745
|
-
|
|
10746
|
-
|
|
10715
|
+
// src/explorer/index.ts
|
|
10716
|
+
var ExplorerService = class {
|
|
10717
|
+
static {
|
|
10718
|
+
__name(this, "ExplorerService");
|
|
10719
|
+
}
|
|
10720
|
+
root;
|
|
10721
|
+
apiGroups;
|
|
10722
|
+
apiGroupMap;
|
|
10723
|
+
aggregator;
|
|
10724
|
+
constructor(apiGroups) {
|
|
10725
|
+
this.apiGroups = apiGroups;
|
|
10726
|
+
this.apiGroupMap = new Map(apiGroups.map((group) => [
|
|
10727
|
+
group.name,
|
|
10728
|
+
group
|
|
10729
|
+
]));
|
|
10730
|
+
this.aggregator = new APIAggregator(apiGroups);
|
|
10731
|
+
this.root = {
|
|
10732
|
+
type: "directory",
|
|
10733
|
+
name: "/",
|
|
10734
|
+
children: /* @__PURE__ */ new Map()
|
|
10747
10735
|
};
|
|
10748
|
-
|
|
10736
|
+
this.buildTree(apiGroups);
|
|
10749
10737
|
}
|
|
10750
|
-
|
|
10751
|
-
|
|
10752
|
-
|
|
10738
|
+
/**
|
|
10739
|
+
* Get filtering context based on current request's tool rules.
|
|
10740
|
+
* Returns sets for allowed items and all known items (for filtering).
|
|
10741
|
+
*/
|
|
10742
|
+
getFilterContext() {
|
|
10743
|
+
const allowedGroups = filterApiGroups(this.apiGroups);
|
|
10744
|
+
const context = {
|
|
10745
|
+
allowedTypes: /* @__PURE__ */ new Set(),
|
|
10746
|
+
allowedGroups: /* @__PURE__ */ new Set(),
|
|
10747
|
+
allowedTools: /* @__PURE__ */ new Set(),
|
|
10748
|
+
allGroups: new Set(this.apiGroups.map((g) => g.name))
|
|
10749
|
+
};
|
|
10750
|
+
for (const group of allowedGroups) {
|
|
10751
|
+
if (group.type !== "graphql") {
|
|
10752
|
+
context.allowedTypes.add(group.type);
|
|
10753
|
+
}
|
|
10754
|
+
context.allowedGroups.add(group.name);
|
|
10755
|
+
}
|
|
10756
|
+
for (const group of this.apiGroups) {
|
|
10757
|
+
if (!context.allowedGroups.has(group.name)) continue;
|
|
10758
|
+
if (group.functions) {
|
|
10759
|
+
for (const func of group.functions) {
|
|
10760
|
+
context.allowedTools.add(`${group.name}:${func.name}`);
|
|
10761
|
+
}
|
|
10762
|
+
}
|
|
10763
|
+
}
|
|
10764
|
+
return context;
|
|
10765
|
+
}
|
|
10766
|
+
/**
|
|
10767
|
+
* Check if a directory should be visible based on filter context.
|
|
10768
|
+
*/
|
|
10769
|
+
isDirectoryAllowed(name, currentPath, ctx) {
|
|
10770
|
+
const API_TYPES = [
|
|
10771
|
+
"openapi",
|
|
10772
|
+
"mcp",
|
|
10773
|
+
"custom",
|
|
10774
|
+
"graphql"
|
|
10775
|
+
];
|
|
10776
|
+
if (currentPath === "/" && API_TYPES.includes(name)) {
|
|
10777
|
+
return ctx.allowedTypes.has(name) || ctx.allowedGroups.has(name);
|
|
10778
|
+
}
|
|
10779
|
+
if (ctx.allGroups.has(name)) {
|
|
10780
|
+
return ctx.allowedGroups.has(name);
|
|
10781
|
+
}
|
|
10782
|
+
return true;
|
|
10783
|
+
}
|
|
10784
|
+
/**
|
|
10785
|
+
* Builds the virtual filesystem tree from API groups
|
|
10786
|
+
*/
|
|
10787
|
+
buildTree(apiGroups) {
|
|
10788
|
+
for (const group of apiGroups) {
|
|
10789
|
+
if (!group.functions || group.functions.length === 0) continue;
|
|
10790
|
+
let groupFolder;
|
|
10791
|
+
if (group.type === "graphql") {
|
|
10792
|
+
groupFolder = this.ensureDirectory(this.root, group.name, group.description);
|
|
10793
|
+
} else {
|
|
10794
|
+
groupFolder = this.ensureDirectory(this.ensureDirectory(this.root, group.type), group.name, group.description);
|
|
10795
|
+
}
|
|
10796
|
+
groupFolder.apiGroupName = group.name;
|
|
10797
|
+
for (const func of group.functions) {
|
|
10798
|
+
const segments = this.extractSegments(func, group);
|
|
10799
|
+
if (segments.length > 1) {
|
|
10800
|
+
let current = groupFolder;
|
|
10801
|
+
for (let i = 0; i < segments.length - 1; i++) {
|
|
10802
|
+
current = this.ensureDirectory(current, segments[i]);
|
|
10803
|
+
}
|
|
10804
|
+
this.addFunction(current, segments[segments.length - 1], func, group.name);
|
|
10805
|
+
} else {
|
|
10806
|
+
this.addFunction(groupFolder, func.name, func, group.name);
|
|
10807
|
+
}
|
|
10808
|
+
}
|
|
10809
|
+
}
|
|
10810
|
+
}
|
|
10811
|
+
/**
|
|
10812
|
+
* Extract path segments for organizing functions
|
|
10813
|
+
*/
|
|
10814
|
+
extractSegments(func, group) {
|
|
10815
|
+
if (group.type === "graphql") {
|
|
10816
|
+
const name = func.name;
|
|
10817
|
+
if (name.startsWith("query_")) {
|
|
10818
|
+
return [
|
|
10819
|
+
"query",
|
|
10820
|
+
name.replace("query_", "")
|
|
10821
|
+
];
|
|
10822
|
+
}
|
|
10823
|
+
if (name.startsWith("mutation_")) {
|
|
10824
|
+
return [
|
|
10825
|
+
"mutation",
|
|
10826
|
+
name.replace("mutation_", "")
|
|
10827
|
+
];
|
|
10828
|
+
}
|
|
10829
|
+
}
|
|
10830
|
+
if (group.type === "openapi") {
|
|
10831
|
+
const name = func.name;
|
|
10832
|
+
const camelSplit = name.match(/[A-Z]?[a-z]+|[A-Z]+(?=[A-Z][a-z]|\b)/g);
|
|
10833
|
+
if (camelSplit && camelSplit.length > 2) {
|
|
10834
|
+
const verb = camelSplit[0].toLowerCase();
|
|
10835
|
+
const isVerb = [
|
|
10836
|
+
"get",
|
|
10837
|
+
"list",
|
|
10838
|
+
"create",
|
|
10839
|
+
"update",
|
|
10840
|
+
"delete",
|
|
10841
|
+
"post",
|
|
10842
|
+
"put",
|
|
10843
|
+
"patch"
|
|
10844
|
+
].includes(verb);
|
|
10845
|
+
if (isVerb) {
|
|
10846
|
+
const resource = camelSplit.slice(1).join("_").toLowerCase();
|
|
10847
|
+
return [
|
|
10848
|
+
resource,
|
|
10849
|
+
name
|
|
10850
|
+
];
|
|
10851
|
+
}
|
|
10852
|
+
}
|
|
10853
|
+
if (name.includes("_")) {
|
|
10854
|
+
const parts = name.split("_");
|
|
10855
|
+
if (parts.length > 1 && parts[0]) {
|
|
10856
|
+
return [
|
|
10857
|
+
parts[0],
|
|
10858
|
+
name
|
|
10859
|
+
];
|
|
10860
|
+
}
|
|
10861
|
+
}
|
|
10862
|
+
if (name.includes("-")) {
|
|
10863
|
+
const parts = name.split("-");
|
|
10864
|
+
if (parts.length > 1 && parts[0]) {
|
|
10865
|
+
return [
|
|
10866
|
+
parts[0],
|
|
10867
|
+
name
|
|
10868
|
+
];
|
|
10869
|
+
}
|
|
10870
|
+
}
|
|
10871
|
+
}
|
|
10872
|
+
return [
|
|
10873
|
+
func.name
|
|
10874
|
+
];
|
|
10875
|
+
}
|
|
10876
|
+
/**
|
|
10877
|
+
* Ensures a directory exists at the given path
|
|
10878
|
+
*/
|
|
10879
|
+
ensureDirectory(parent, name, description) {
|
|
10880
|
+
if (!parent.children) {
|
|
10881
|
+
parent.children = /* @__PURE__ */ new Map();
|
|
10882
|
+
}
|
|
10883
|
+
let child = parent.children.get(name);
|
|
10884
|
+
if (!child) {
|
|
10885
|
+
child = {
|
|
10886
|
+
type: "directory",
|
|
10887
|
+
name,
|
|
10888
|
+
description,
|
|
10889
|
+
children: /* @__PURE__ */ new Map()
|
|
10890
|
+
};
|
|
10891
|
+
parent.children.set(name, child);
|
|
10892
|
+
} else if (description && !child.description) {
|
|
10893
|
+
child.description = description;
|
|
10894
|
+
}
|
|
10895
|
+
return child;
|
|
10896
|
+
}
|
|
10897
|
+
/**
|
|
10898
|
+
* Adds a function to the tree
|
|
10899
|
+
*/
|
|
10900
|
+
addFunction(parent, name, func, group) {
|
|
10901
|
+
if (!parent.children) {
|
|
10902
|
+
parent.children = /* @__PURE__ */ new Map();
|
|
10903
|
+
}
|
|
10904
|
+
parent.children.set(name, {
|
|
10905
|
+
type: "function",
|
|
10906
|
+
name,
|
|
10907
|
+
functionDef: {
|
|
10908
|
+
func,
|
|
10909
|
+
group
|
|
10910
|
+
}
|
|
10911
|
+
});
|
|
10912
|
+
}
|
|
10913
|
+
/**
|
|
10914
|
+
* Explores the filesystem at the given path.
|
|
10915
|
+
* Tool rules are automatically applied from the request scope.
|
|
10916
|
+
* @param path - The path to explore
|
|
10917
|
+
*/
|
|
10918
|
+
explore(path) {
|
|
10919
|
+
const ctx = this.getFilterContext();
|
|
10920
|
+
const normalizedPath = this.normalizePath(path);
|
|
10921
|
+
const segments = normalizedPath === "/" ? [] : normalizedPath.split("/").filter((s) => s);
|
|
10922
|
+
let current = this.root;
|
|
10923
|
+
let currentPath = "/";
|
|
10924
|
+
for (const segment of segments) {
|
|
10925
|
+
if (!current.children || !current.children.has(segment)) {
|
|
10926
|
+
return null;
|
|
10927
|
+
}
|
|
10928
|
+
current = current.children.get(segment);
|
|
10929
|
+
currentPath = currentPath === "/" ? `/${segment}` : `${currentPath}/${segment}`;
|
|
10930
|
+
}
|
|
10931
|
+
if (current.type === "directory") {
|
|
10932
|
+
const items = [];
|
|
10933
|
+
if (current.children) {
|
|
10934
|
+
for (const [name, node] of current.children) {
|
|
10935
|
+
if (node.type === "directory") {
|
|
10936
|
+
if (!this.isDirectoryAllowed(name, currentPath, ctx)) continue;
|
|
10937
|
+
} else if (node.type === "function" && node.functionDef) {
|
|
10938
|
+
if (!ctx.allowedTools.has(`${node.functionDef.group}:${node.functionDef.func.name}`)) continue;
|
|
10939
|
+
}
|
|
10940
|
+
const item = {
|
|
10941
|
+
name,
|
|
10942
|
+
type: node.type
|
|
10943
|
+
};
|
|
10944
|
+
if (node.description) {
|
|
10945
|
+
item.description = node.description;
|
|
10946
|
+
} else if (node.type === "function" && node.functionDef?.func.description) {
|
|
10947
|
+
item.description = node.functionDef.func.description;
|
|
10948
|
+
}
|
|
10949
|
+
items.push(item);
|
|
10950
|
+
}
|
|
10951
|
+
}
|
|
10952
|
+
items.sort((a, b) => {
|
|
10953
|
+
if (a.type === b.type) {
|
|
10954
|
+
return a.name.localeCompare(b.name);
|
|
10955
|
+
}
|
|
10956
|
+
return a.type === "directory" ? -1 : 1;
|
|
10957
|
+
});
|
|
10958
|
+
const result = {
|
|
10959
|
+
type: "directory",
|
|
10960
|
+
path: currentPath,
|
|
10961
|
+
items
|
|
10962
|
+
};
|
|
10963
|
+
if (current.apiGroupName) {
|
|
10964
|
+
const apiGroup = this.apiGroupMap.get(current.apiGroupName);
|
|
10965
|
+
if (apiGroup?.documentation) {
|
|
10966
|
+
result.documentation = apiGroup.documentation;
|
|
10967
|
+
}
|
|
10968
|
+
}
|
|
10969
|
+
return result;
|
|
10970
|
+
} else {
|
|
10971
|
+
if (!current.functionDef) {
|
|
10972
|
+
return null;
|
|
10973
|
+
}
|
|
10974
|
+
const { func, group } = current.functionDef;
|
|
10975
|
+
if (!ctx.allowedTools.has(`${group}:${func.name}`)) {
|
|
10976
|
+
return null;
|
|
10977
|
+
}
|
|
10978
|
+
const definition = this.aggregator.generateCompactFunctionDefinition(func, group);
|
|
10979
|
+
return {
|
|
10980
|
+
type: "function",
|
|
10981
|
+
path: currentPath,
|
|
10982
|
+
name: func.name,
|
|
10983
|
+
description: func.description,
|
|
10984
|
+
definition,
|
|
10985
|
+
group
|
|
10986
|
+
};
|
|
10987
|
+
}
|
|
10988
|
+
}
|
|
10989
|
+
/**
|
|
10990
|
+
* Normalizes a path (removes trailing slashes, ensures leading slash)
|
|
10991
|
+
*/
|
|
10992
|
+
normalizePath(path) {
|
|
10993
|
+
if (!path || path === "") return "/";
|
|
10994
|
+
if (!path.startsWith("/")) {
|
|
10995
|
+
path = "/" + path;
|
|
10996
|
+
}
|
|
10997
|
+
if (path !== "/" && path.endsWith("/")) {
|
|
10998
|
+
path = path.slice(0, -1);
|
|
10999
|
+
}
|
|
11000
|
+
return path;
|
|
11001
|
+
}
|
|
11002
|
+
};
|
|
11003
|
+
|
|
11004
|
+
// src/utils/schema.ts
|
|
11005
|
+
function toJSONSchema(types) {
|
|
11006
|
+
const properties = {};
|
|
11007
|
+
const required = [];
|
|
11008
|
+
for (const [key, type] of Object.entries(types)) {
|
|
11009
|
+
properties[key] = {
|
|
11010
|
+
type
|
|
11011
|
+
};
|
|
11012
|
+
required.push(key);
|
|
11013
|
+
}
|
|
11014
|
+
return {
|
|
11015
|
+
type: "object",
|
|
11016
|
+
properties,
|
|
10753
11017
|
required
|
|
10754
11018
|
};
|
|
10755
11019
|
}
|
|
@@ -11396,640 +11660,377 @@ async function handleExecute(ctx, executor, stateManager, config, auditSink, ses
|
|
|
11396
11660
|
executionId: prelimExecutionId
|
|
11397
11661
|
});
|
|
11398
11662
|
} catch (error) {
|
|
11399
|
-
atpRuntime.log.error("Failed to verify provenance hints", {
|
|
11400
|
-
error
|
|
11401
|
-
});
|
|
11402
|
-
}
|
|
11403
|
-
}
|
|
11404
|
-
const startTime = Date.now();
|
|
11405
|
-
if (auditSink) {
|
|
11406
|
-
const startEvent = {
|
|
11407
|
-
eventId: crypto__default.default.randomUUID(),
|
|
11408
|
-
timestamp: startTime,
|
|
11409
|
-
clientId: ctx.clientId || "anonymous",
|
|
11410
|
-
eventType: "execution",
|
|
11411
|
-
action: "start",
|
|
11412
|
-
code,
|
|
11413
|
-
status: "success"
|
|
11414
|
-
};
|
|
11415
|
-
await auditSink.write(startEvent).catch(() => {
|
|
11416
|
-
});
|
|
11417
|
-
}
|
|
11418
|
-
const result = await executor.execute(code, executionConfig, ctx.clientId, {
|
|
11419
|
-
callbackHistory: [],
|
|
11420
|
-
newCallbackResult: void 0,
|
|
11421
|
-
executionId: prelimExecutionId
|
|
11422
|
-
});
|
|
11423
|
-
if (result.status === atpProtocol.ExecutionStatus.COMPLETED && executionConfig.provenanceMode && executionConfig.provenanceMode !== atpProtocol.ProvenanceMode.NONE && ctx.cache && result.provenanceSnapshot) {
|
|
11424
|
-
try {
|
|
11425
|
-
atpRuntime.log.info("Attempting to emit provenance tokens from snapshot", {
|
|
11426
|
-
executionId: result.executionId,
|
|
11427
|
-
provenanceMode: executionConfig.provenanceMode,
|
|
11428
|
-
hasCache: !!ctx.cache,
|
|
11429
|
-
hasSnapshot: !!result.provenanceSnapshot,
|
|
11430
|
-
resultType: typeof result.result
|
|
11431
|
-
});
|
|
11432
|
-
const tokens = await emitProvenanceTokens(
|
|
11433
|
-
result.result,
|
|
11434
|
-
ctx.clientId || "anonymous",
|
|
11435
|
-
result.executionId,
|
|
11436
|
-
executionConfig.provenanceMode,
|
|
11437
|
-
ctx.cache,
|
|
11438
|
-
atpRuntime.log.child({
|
|
11439
|
-
executionId: result.executionId
|
|
11440
|
-
}),
|
|
11441
|
-
5e3,
|
|
11442
|
-
3600,
|
|
11443
|
-
result.provenanceSnapshot
|
|
11444
|
-
// Pass snapshot
|
|
11445
|
-
);
|
|
11446
|
-
atpRuntime.log.info("Provenance tokens emitted", {
|
|
11447
|
-
executionId: result.executionId,
|
|
11448
|
-
tokenCount: tokens.length
|
|
11449
|
-
});
|
|
11450
|
-
if (tokens.length > 0) {
|
|
11451
|
-
result.provenanceTokens = tokens;
|
|
11452
|
-
}
|
|
11453
|
-
} catch (error) {
|
|
11454
|
-
atpRuntime.log.error("Failed to emit provenance tokens", {
|
|
11455
|
-
error,
|
|
11456
|
-
executionId: result.executionId
|
|
11457
|
-
});
|
|
11458
|
-
}
|
|
11459
|
-
}
|
|
11460
|
-
delete result.provenanceSnapshot;
|
|
11461
|
-
if (result.result && typeof result.result === "object") {
|
|
11462
|
-
const hasProv = "__prov_id__" in result.result;
|
|
11463
|
-
result.result = cleanProvenanceIds(result.result);
|
|
11464
|
-
const stillHasProv = result.result && typeof result.result === "object" && "__prov_id__" in result.result;
|
|
11465
|
-
if (hasProv && !stillHasProv) {
|
|
11466
|
-
atpRuntime.log.debug("Successfully cleaned __prov_id__ from result");
|
|
11467
|
-
} else if (hasProv && stillHasProv) {
|
|
11468
|
-
atpRuntime.log.warn("Failed to clean __prov_id__ from result!");
|
|
11469
|
-
}
|
|
11470
|
-
}
|
|
11471
|
-
if (auditSink) {
|
|
11472
|
-
const endEvent = {
|
|
11473
|
-
eventId: crypto__default.default.randomUUID(),
|
|
11474
|
-
timestamp: Date.now(),
|
|
11475
|
-
clientId: ctx.clientId || "anonymous",
|
|
11476
|
-
eventType: "execution",
|
|
11477
|
-
action: result.status === atpProtocol.ExecutionStatus.PAUSED ? "pause" : "complete",
|
|
11478
|
-
resourceId: result.executionId,
|
|
11479
|
-
status: result.status === atpProtocol.ExecutionStatus.COMPLETED ? "success" : result.status === atpProtocol.ExecutionStatus.FAILED ? "failed" : "paused",
|
|
11480
|
-
duration: Date.now() - startTime,
|
|
11481
|
-
memoryUsed: result.stats?.memoryUsed,
|
|
11482
|
-
llmCallsCount: result.stats?.llmCallsCount,
|
|
11483
|
-
error: result.error ? {
|
|
11484
|
-
message: result.error.message,
|
|
11485
|
-
code: result.error.code,
|
|
11486
|
-
stack: result.error.stack
|
|
11487
|
-
} : void 0
|
|
11488
|
-
};
|
|
11489
|
-
await auditSink.write(endEvent).catch(() => {
|
|
11490
|
-
});
|
|
11491
|
-
}
|
|
11492
|
-
if (result.status === "paused" && (result.needsCallback || result.needsCallbacks) && result.callbackHistory) {
|
|
11493
|
-
if (!ctx.clientId) {
|
|
11494
|
-
ctx.throw(400, "Client ID required for paused executions");
|
|
11495
|
-
}
|
|
11496
|
-
const provenanceSnap = executionConfig.provenanceMode && executionConfig.provenanceMode !== atpProtocol.ProvenanceMode.NONE ? atpProvenance.captureProvenanceSnapshot(result.executionId) : void 0;
|
|
11497
|
-
const callbackRequest = result.needsCallback || result.needsCallbacks && result.needsCallbacks[0];
|
|
11498
|
-
if (!callbackRequest) {
|
|
11499
|
-
ctx.throw(500, "Invalid paused state: no callback request");
|
|
11500
|
-
}
|
|
11501
|
-
const transformedCodeToSave = result.transformedCode || code;
|
|
11502
|
-
await stateManager.pause({
|
|
11503
|
-
executionId: result.executionId,
|
|
11504
|
-
code: transformedCodeToSave,
|
|
11505
|
-
config: executionConfig,
|
|
11506
|
-
clientId: ctx.clientId,
|
|
11507
|
-
callbackRequest,
|
|
11508
|
-
pausedAt: Date.now(),
|
|
11509
|
-
callbackHistory: result.callbackHistory,
|
|
11510
|
-
currentCallbackIndex: result.callbackHistory.length - 1,
|
|
11511
|
-
context: {
|
|
11512
|
-
codeTransformed: !!result.transformedCode
|
|
11513
|
-
},
|
|
11514
|
-
provenanceState: provenanceSnap
|
|
11515
|
-
});
|
|
11516
|
-
}
|
|
11517
|
-
if (hintMap && hintMap.size > 0) {
|
|
11518
|
-
clearHintMap(prelimExecutionId);
|
|
11519
|
-
}
|
|
11520
|
-
return result;
|
|
11521
|
-
}
|
|
11522
|
-
__name(handleExecute, "handleExecute");
|
|
11523
|
-
function tagCallbackResult(callbackRecord, result, provenanceMode) {
|
|
11524
|
-
if (!provenanceMode || provenanceMode === atpProtocol.ProvenanceMode.NONE) {
|
|
11525
|
-
return result;
|
|
11526
|
-
}
|
|
11527
|
-
if (result === null || result === void 0) {
|
|
11528
|
-
return result;
|
|
11529
|
-
}
|
|
11530
|
-
const tagValue = /* @__PURE__ */ __name((value, source) => {
|
|
11531
|
-
if (value === null || value === void 0) {
|
|
11532
|
-
return value;
|
|
11533
|
-
}
|
|
11534
|
-
if (typeof value === "string" || typeof value === "number") {
|
|
11535
|
-
const metadata = {
|
|
11536
|
-
id: crypto.randomUUID(),
|
|
11537
|
-
source,
|
|
11538
|
-
readers: {
|
|
11539
|
-
type: "public"
|
|
11540
|
-
},
|
|
11541
|
-
dependencies: [],
|
|
11542
|
-
context: {}
|
|
11543
|
-
};
|
|
11544
|
-
atpProvenance.markPrimitiveTainted(value, metadata);
|
|
11545
|
-
return value;
|
|
11546
|
-
}
|
|
11547
|
-
if (typeof value === "object") {
|
|
11548
|
-
return atpProvenance.createProvenanceProxy(value, source, {
|
|
11549
|
-
type: "public"
|
|
11663
|
+
atpRuntime.log.error("Failed to verify provenance hints", {
|
|
11664
|
+
error
|
|
11550
11665
|
});
|
|
11551
11666
|
}
|
|
11552
|
-
return value;
|
|
11553
|
-
}, "tagValue");
|
|
11554
|
-
if (callbackRecord.type === "llm") {
|
|
11555
|
-
const source = {
|
|
11556
|
-
type: atpProvenance.ProvenanceSource.LLM,
|
|
11557
|
-
operation: callbackRecord.operation || "call",
|
|
11558
|
-
timestamp: Date.now()
|
|
11559
|
-
};
|
|
11560
|
-
return Array.isArray(result) ? result.map((r) => tagValue(r, source)) : tagValue(result, source);
|
|
11561
11667
|
}
|
|
11562
|
-
|
|
11563
|
-
|
|
11564
|
-
|
|
11565
|
-
|
|
11566
|
-
|
|
11567
|
-
|
|
11668
|
+
const startTime = Date.now();
|
|
11669
|
+
if (auditSink) {
|
|
11670
|
+
const startEvent = {
|
|
11671
|
+
eventId: crypto__default.default.randomUUID(),
|
|
11672
|
+
timestamp: startTime,
|
|
11673
|
+
clientId: ctx.clientId || "anonymous",
|
|
11674
|
+
eventType: "execution",
|
|
11675
|
+
action: "start",
|
|
11676
|
+
code,
|
|
11677
|
+
status: "success"
|
|
11568
11678
|
};
|
|
11569
|
-
|
|
11570
|
-
}
|
|
11571
|
-
return result;
|
|
11572
|
-
}
|
|
11573
|
-
__name(tagCallbackResult, "tagCallbackResult");
|
|
11574
|
-
async function handleResume(ctx, executionId, executor, stateManager, serverConfig, sessionManager) {
|
|
11575
|
-
const requestClientId = ctx.headers["x-client-id"] || ctx.clientId;
|
|
11576
|
-
const requestToken = ctx.headers["authorization"]?.replace("Bearer ", "");
|
|
11577
|
-
if (!requestClientId || !requestToken) {
|
|
11578
|
-
atpRuntime.log.warn("Resume attempt without authentication", {
|
|
11579
|
-
executionId
|
|
11580
|
-
});
|
|
11581
|
-
ctx.throw(401, "Authentication required");
|
|
11582
|
-
}
|
|
11583
|
-
ctx.clientId = requestClientId;
|
|
11584
|
-
if (sessionManager) {
|
|
11585
|
-
const isValid = await sessionManager.verifyClient(requestClientId, requestToken);
|
|
11586
|
-
if (!isValid) {
|
|
11587
|
-
atpRuntime.log.warn("Resume attempt with invalid token", {
|
|
11588
|
-
executionId,
|
|
11589
|
-
clientId: requestClientId
|
|
11590
|
-
});
|
|
11591
|
-
ctx.throw(403, "Invalid client credentials");
|
|
11592
|
-
}
|
|
11593
|
-
}
|
|
11594
|
-
const pausedState = await stateManager.get(executionId);
|
|
11595
|
-
if (!pausedState) {
|
|
11596
|
-
ctx.throw(404, "Not found");
|
|
11597
|
-
}
|
|
11598
|
-
if (pausedState.clientId !== requestClientId) {
|
|
11599
|
-
atpRuntime.log.warn("Resume attempt by unauthorized client", {
|
|
11600
|
-
executionId,
|
|
11601
|
-
requestClientId,
|
|
11602
|
-
ownerClientId: pausedState.clientId
|
|
11679
|
+
await auditSink.write(startEvent).catch(() => {
|
|
11603
11680
|
});
|
|
11604
|
-
ctx.throw(403, "Unauthorized: execution belongs to different client");
|
|
11605
11681
|
}
|
|
11606
|
-
|
|
11607
|
-
|
|
11608
|
-
|
|
11682
|
+
const result = await executor.execute(code, executionConfig, ctx.clientId, {
|
|
11683
|
+
callbackHistory: [],
|
|
11684
|
+
newCallbackResult: void 0,
|
|
11685
|
+
executionId: prelimExecutionId
|
|
11609
11686
|
});
|
|
11610
|
-
if (
|
|
11611
|
-
|
|
11612
|
-
|
|
11613
|
-
|
|
11614
|
-
|
|
11615
|
-
|
|
11616
|
-
|
|
11617
|
-
|
|
11687
|
+
if (result.status === atpProtocol.ExecutionStatus.COMPLETED && executionConfig.provenanceMode && executionConfig.provenanceMode !== atpProtocol.ProvenanceMode.NONE && ctx.cache && result.provenanceSnapshot) {
|
|
11688
|
+
try {
|
|
11689
|
+
atpRuntime.log.info("Attempting to emit provenance tokens from snapshot", {
|
|
11690
|
+
executionId: result.executionId,
|
|
11691
|
+
provenanceMode: executionConfig.provenanceMode,
|
|
11692
|
+
hasCache: !!ctx.cache,
|
|
11693
|
+
hasSnapshot: !!result.provenanceSnapshot,
|
|
11694
|
+
resultType: typeof result.result
|
|
11618
11695
|
});
|
|
11619
|
-
|
|
11620
|
-
|
|
11621
|
-
|
|
11622
|
-
|
|
11623
|
-
|
|
11696
|
+
const tokens = await emitProvenanceTokens(
|
|
11697
|
+
result.result,
|
|
11698
|
+
ctx.clientId || "anonymous",
|
|
11699
|
+
result.executionId,
|
|
11700
|
+
executionConfig.provenanceMode,
|
|
11701
|
+
ctx.cache,
|
|
11702
|
+
atpRuntime.log.child({
|
|
11703
|
+
executionId: result.executionId
|
|
11704
|
+
}),
|
|
11705
|
+
5e3,
|
|
11706
|
+
3600,
|
|
11707
|
+
result.provenanceSnapshot
|
|
11708
|
+
// Pass snapshot
|
|
11709
|
+
);
|
|
11710
|
+
atpRuntime.log.info("Provenance tokens emitted", {
|
|
11711
|
+
executionId: result.executionId,
|
|
11712
|
+
tokenCount: tokens.length
|
|
11624
11713
|
});
|
|
11625
|
-
|
|
11626
|
-
|
|
11627
|
-
|
|
11714
|
+
if (tokens.length > 0) {
|
|
11715
|
+
result.provenanceTokens = tokens;
|
|
11716
|
+
}
|
|
11717
|
+
} catch (error) {
|
|
11718
|
+
atpRuntime.log.error("Failed to emit provenance tokens", {
|
|
11719
|
+
error,
|
|
11720
|
+
executionId: result.executionId
|
|
11628
11721
|
});
|
|
11629
11722
|
}
|
|
11630
11723
|
}
|
|
11631
|
-
|
|
11632
|
-
|
|
11633
|
-
|
|
11634
|
-
|
|
11635
|
-
|
|
11636
|
-
|
|
11637
|
-
|
|
11638
|
-
|
|
11639
|
-
|
|
11640
|
-
ctx.throw(500, "Invalid paused state: no callback record");
|
|
11641
|
-
}
|
|
11642
|
-
if (request.results) {
|
|
11643
|
-
const batchResults = request.results;
|
|
11644
|
-
atpRuntime.log.info("Processing batch callback results", {
|
|
11645
|
-
executionId,
|
|
11646
|
-
batchCount: batchResults.length
|
|
11647
|
-
});
|
|
11648
|
-
for (const br of batchResults) {
|
|
11649
|
-
if (br.result && typeof br.result === "object" && "__error" in br.result) {
|
|
11650
|
-
const errorObj = br.result;
|
|
11651
|
-
if (errorObj.message && errorObj.message.includes("service not provided")) {
|
|
11652
|
-
atpRuntime.log.error("Service provider error in batch", {
|
|
11653
|
-
executionId,
|
|
11654
|
-
error: errorObj.message
|
|
11655
|
-
});
|
|
11656
|
-
await stateManager.delete(executionId);
|
|
11657
|
-
return {
|
|
11658
|
-
executionId,
|
|
11659
|
-
status: atpProtocol.ExecutionStatus.FAILED,
|
|
11660
|
-
error: {
|
|
11661
|
-
message: errorObj.message || "Service not available",
|
|
11662
|
-
code: "SERVICE_NOT_PROVIDED"
|
|
11663
|
-
},
|
|
11664
|
-
stats: {
|
|
11665
|
-
duration: 0,
|
|
11666
|
-
memoryUsed: 0,
|
|
11667
|
-
llmCallsCount: 0,
|
|
11668
|
-
approvalCallsCount: 0
|
|
11669
|
-
}
|
|
11670
|
-
};
|
|
11671
|
-
}
|
|
11672
|
-
}
|
|
11673
|
-
}
|
|
11674
|
-
const taggedBatchResults = batchResults.map((br) => ({
|
|
11675
|
-
...br,
|
|
11676
|
-
result: tagCallbackResult(lastRecord, br.result, pausedState.config.provenanceMode)
|
|
11677
|
-
}));
|
|
11678
|
-
callbackResult = taggedBatchResults.map((br) => br.result);
|
|
11679
|
-
updatedHistory = pausedState.callbackHistory.map((record, index) => {
|
|
11680
|
-
if (index === pausedState.currentCallbackIndex) {
|
|
11681
|
-
return {
|
|
11682
|
-
...record,
|
|
11683
|
-
result: callbackResult
|
|
11684
|
-
};
|
|
11685
|
-
}
|
|
11686
|
-
return record;
|
|
11687
|
-
});
|
|
11688
|
-
} else {
|
|
11689
|
-
const rawResult = request.result;
|
|
11690
|
-
if (rawResult && typeof rawResult === "object" && "__error" in rawResult) {
|
|
11691
|
-
const errorObj = rawResult;
|
|
11692
|
-
if (errorObj.message && errorObj.message.includes("service not provided")) {
|
|
11693
|
-
atpRuntime.log.error("Service provider error", {
|
|
11694
|
-
executionId,
|
|
11695
|
-
error: errorObj.message
|
|
11696
|
-
});
|
|
11697
|
-
await stateManager.delete(executionId);
|
|
11698
|
-
return {
|
|
11699
|
-
executionId,
|
|
11700
|
-
status: atpProtocol.ExecutionStatus.FAILED,
|
|
11701
|
-
error: {
|
|
11702
|
-
message: errorObj.message || "Service not available",
|
|
11703
|
-
code: "SERVICE_NOT_PROVIDED"
|
|
11704
|
-
},
|
|
11705
|
-
stats: {
|
|
11706
|
-
duration: 0,
|
|
11707
|
-
memoryUsed: 0,
|
|
11708
|
-
llmCallsCount: 0,
|
|
11709
|
-
approvalCallsCount: 0
|
|
11710
|
-
}
|
|
11711
|
-
};
|
|
11712
|
-
}
|
|
11724
|
+
delete result.provenanceSnapshot;
|
|
11725
|
+
if (result.result && typeof result.result === "object") {
|
|
11726
|
+
const hasProv = "__prov_id__" in result.result;
|
|
11727
|
+
result.result = cleanProvenanceIds(result.result);
|
|
11728
|
+
const stillHasProv = result.result && typeof result.result === "object" && "__prov_id__" in result.result;
|
|
11729
|
+
if (hasProv && !stillHasProv) {
|
|
11730
|
+
atpRuntime.log.debug("Successfully cleaned __prov_id__ from result");
|
|
11731
|
+
} else if (hasProv && stillHasProv) {
|
|
11732
|
+
atpRuntime.log.warn("Failed to clean __prov_id__ from result!");
|
|
11713
11733
|
}
|
|
11714
|
-
callbackResult = tagCallbackResult(lastRecord, rawResult, pausedState.config.provenanceMode);
|
|
11715
|
-
updatedHistory = pausedState.callbackHistory.map((record, index) => {
|
|
11716
|
-
if (index === pausedState.currentCallbackIndex) {
|
|
11717
|
-
return {
|
|
11718
|
-
...record,
|
|
11719
|
-
result: callbackResult
|
|
11720
|
-
};
|
|
11721
|
-
}
|
|
11722
|
-
return record;
|
|
11723
|
-
});
|
|
11724
11734
|
}
|
|
11725
|
-
|
|
11726
|
-
|
|
11727
|
-
|
|
11728
|
-
|
|
11729
|
-
|
|
11730
|
-
|
|
11731
|
-
|
|
11732
|
-
|
|
11733
|
-
|
|
11734
|
-
|
|
11735
|
-
|
|
11736
|
-
|
|
11737
|
-
|
|
11738
|
-
|
|
11739
|
-
|
|
11740
|
-
|
|
11741
|
-
|
|
11742
|
-
|
|
11743
|
-
|
|
11744
|
-
callbackHistory: result.callbackHistory,
|
|
11745
|
-
currentCallbackIndex: result.callbackHistory.length - 1,
|
|
11746
|
-
context: {},
|
|
11747
|
-
provenanceState
|
|
11735
|
+
if (auditSink) {
|
|
11736
|
+
const endEvent = {
|
|
11737
|
+
eventId: crypto__default.default.randomUUID(),
|
|
11738
|
+
timestamp: Date.now(),
|
|
11739
|
+
clientId: ctx.clientId || "anonymous",
|
|
11740
|
+
eventType: "execution",
|
|
11741
|
+
action: result.status === atpProtocol.ExecutionStatus.PAUSED ? "pause" : "complete",
|
|
11742
|
+
resourceId: result.executionId,
|
|
11743
|
+
status: result.status === atpProtocol.ExecutionStatus.COMPLETED ? "success" : result.status === atpProtocol.ExecutionStatus.FAILED ? "failed" : "paused",
|
|
11744
|
+
duration: Date.now() - startTime,
|
|
11745
|
+
memoryUsed: result.stats?.memoryUsed,
|
|
11746
|
+
llmCallsCount: result.stats?.llmCallsCount,
|
|
11747
|
+
error: result.error ? {
|
|
11748
|
+
message: result.error.message,
|
|
11749
|
+
code: result.error.code,
|
|
11750
|
+
stack: result.error.stack
|
|
11751
|
+
} : void 0
|
|
11752
|
+
};
|
|
11753
|
+
await auditSink.write(endEvent).catch(() => {
|
|
11748
11754
|
});
|
|
11749
|
-
}
|
|
11750
|
-
|
|
11751
|
-
|
|
11755
|
+
}
|
|
11756
|
+
if (result.status === "paused" && (result.needsCallback || result.needsCallbacks) && result.callbackHistory) {
|
|
11757
|
+
if (!ctx.clientId) {
|
|
11758
|
+
ctx.throw(400, "Client ID required for paused executions");
|
|
11759
|
+
}
|
|
11760
|
+
const provenanceSnap = executionConfig.provenanceMode && executionConfig.provenanceMode !== atpProtocol.ProvenanceMode.NONE ? atpProvenance.captureProvenanceSnapshot(result.executionId) : void 0;
|
|
11761
|
+
const callbackRequest = result.needsCallback || result.needsCallbacks && result.needsCallbacks[0];
|
|
11762
|
+
if (!callbackRequest) {
|
|
11763
|
+
ctx.throw(500, "Invalid paused state: no callback request");
|
|
11764
|
+
}
|
|
11765
|
+
const transformedCodeToSave = result.transformedCode || code;
|
|
11752
11766
|
await stateManager.pause({
|
|
11753
11767
|
executionId: result.executionId,
|
|
11754
|
-
code:
|
|
11755
|
-
config:
|
|
11756
|
-
clientId:
|
|
11757
|
-
callbackRequest
|
|
11768
|
+
code: transformedCodeToSave,
|
|
11769
|
+
config: executionConfig,
|
|
11770
|
+
clientId: ctx.clientId,
|
|
11771
|
+
callbackRequest,
|
|
11758
11772
|
pausedAt: Date.now(),
|
|
11759
11773
|
callbackHistory: result.callbackHistory,
|
|
11760
11774
|
currentCallbackIndex: result.callbackHistory.length - 1,
|
|
11761
|
-
context: {
|
|
11762
|
-
|
|
11775
|
+
context: {
|
|
11776
|
+
codeTransformed: !!result.transformedCode
|
|
11777
|
+
},
|
|
11778
|
+
provenanceState: provenanceSnap
|
|
11763
11779
|
});
|
|
11764
|
-
}
|
|
11765
|
-
|
|
11780
|
+
}
|
|
11781
|
+
if (hintMap && hintMap.size > 0) {
|
|
11782
|
+
clearHintMap(prelimExecutionId);
|
|
11766
11783
|
}
|
|
11767
11784
|
return result;
|
|
11768
11785
|
}
|
|
11769
|
-
__name(
|
|
11770
|
-
|
|
11771
|
-
|
|
11772
|
-
|
|
11773
|
-
}
|
|
11774
|
-
apiGroups;
|
|
11775
|
-
/**
|
|
11776
|
-
* Creates a new APIAggregator instance.
|
|
11777
|
-
* @param apiGroups - Array of API group configurations
|
|
11778
|
-
*/
|
|
11779
|
-
constructor(apiGroups) {
|
|
11780
|
-
this.apiGroups = apiGroups;
|
|
11781
|
-
}
|
|
11782
|
-
/**
|
|
11783
|
-
* Generates TypeScript type definitions for selected API groups.
|
|
11784
|
-
* @param selectedGroups - Optional array of group names to include
|
|
11785
|
-
* @returns TypeScript definition string
|
|
11786
|
-
*/
|
|
11787
|
-
async generateTypeScript(selectedGroups) {
|
|
11788
|
-
const groups = selectedGroups ? this.apiGroups.filter((g) => selectedGroups.includes(g.name)) : this.apiGroups;
|
|
11789
|
-
let typescript = `// Agent Tool Protocol Runtime SDK v1.0.0
|
|
11790
|
-
|
|
11791
|
-
`;
|
|
11792
|
-
typescript += this.generateRuntimeTypes();
|
|
11793
|
-
for (const group of groups) {
|
|
11794
|
-
typescript += `
|
|
11795
|
-
// API Group: ${group.name}
|
|
11796
|
-
`;
|
|
11797
|
-
if (group.functions) {
|
|
11798
|
-
for (const func of group.functions) {
|
|
11799
|
-
typescript += this.generateFunctionTypes(func, group.name);
|
|
11800
|
-
}
|
|
11801
|
-
}
|
|
11802
|
-
}
|
|
11803
|
-
typescript += this.generateAPINamespace(groups);
|
|
11804
|
-
return typescript;
|
|
11786
|
+
__name(handleExecute, "handleExecute");
|
|
11787
|
+
function tagCallbackResult(callbackRecord, result, provenanceMode) {
|
|
11788
|
+
if (!provenanceMode || provenanceMode === atpProtocol.ProvenanceMode.NONE) {
|
|
11789
|
+
return result;
|
|
11805
11790
|
}
|
|
11806
|
-
|
|
11807
|
-
|
|
11808
|
-
* @param options - Optional filtering options
|
|
11809
|
-
* @returns TypeScript definition string
|
|
11810
|
-
*/
|
|
11811
|
-
generateRuntimeTypes(options) {
|
|
11812
|
-
return atpRuntime.generateRuntimeTypes(atpRuntime.GENERATED_METADATA, options);
|
|
11791
|
+
if (result === null || result === void 0) {
|
|
11792
|
+
return result;
|
|
11813
11793
|
}
|
|
11814
|
-
|
|
11815
|
-
|
|
11816
|
-
|
|
11817
|
-
* @param groupName - API group name
|
|
11818
|
-
* @returns TypeScript definition string
|
|
11819
|
-
*/
|
|
11820
|
-
generateFunctionTypes(func, groupName) {
|
|
11821
|
-
const inputTypeName = `${func.name}_Input`;
|
|
11822
|
-
const outputTypeName = `${func.name}_Output`;
|
|
11823
|
-
let typescript = `
|
|
11824
|
-
interface ${inputTypeName} {
|
|
11825
|
-
`;
|
|
11826
|
-
if (func.inputSchema?.properties) {
|
|
11827
|
-
const required = func.inputSchema.required || [];
|
|
11828
|
-
for (const [key, value] of Object.entries(func.inputSchema.properties)) {
|
|
11829
|
-
const prop = value;
|
|
11830
|
-
const tsType = this.jsonSchemaTypeToTS(prop.type ?? "any");
|
|
11831
|
-
const comment = prop.description ? ` // ${prop.description}` : "";
|
|
11832
|
-
const optional = required.includes(key) ? "" : "?";
|
|
11833
|
-
typescript += ` ${key}${optional}: ${tsType};${comment}
|
|
11834
|
-
`;
|
|
11835
|
-
}
|
|
11794
|
+
const tagValue = /* @__PURE__ */ __name((value, source) => {
|
|
11795
|
+
if (value === null || value === void 0) {
|
|
11796
|
+
return value;
|
|
11836
11797
|
}
|
|
11837
|
-
|
|
11838
|
-
|
|
11839
|
-
|
|
11840
|
-
|
|
11841
|
-
|
|
11842
|
-
|
|
11843
|
-
|
|
11844
|
-
|
|
11845
|
-
|
|
11846
|
-
|
|
11847
|
-
|
|
11798
|
+
if (typeof value === "string" || typeof value === "number") {
|
|
11799
|
+
const metadata = {
|
|
11800
|
+
id: crypto.randomUUID(),
|
|
11801
|
+
source,
|
|
11802
|
+
readers: {
|
|
11803
|
+
type: "public"
|
|
11804
|
+
},
|
|
11805
|
+
dependencies: [],
|
|
11806
|
+
context: {}
|
|
11807
|
+
};
|
|
11808
|
+
atpProvenance.markPrimitiveTainted(value, metadata);
|
|
11809
|
+
return value;
|
|
11848
11810
|
}
|
|
11849
|
-
|
|
11850
|
-
|
|
11851
|
-
|
|
11852
|
-
|
|
11853
|
-
/**
|
|
11854
|
-
* Converts JSON Schema type to TypeScript type.
|
|
11855
|
-
* @param type - JSON Schema type string
|
|
11856
|
-
* @returns TypeScript type string
|
|
11857
|
-
*/
|
|
11858
|
-
jsonSchemaTypeToTS(type) {
|
|
11859
|
-
switch (type) {
|
|
11860
|
-
case "string":
|
|
11861
|
-
return "string";
|
|
11862
|
-
case "number":
|
|
11863
|
-
case "integer":
|
|
11864
|
-
return "number";
|
|
11865
|
-
case "boolean":
|
|
11866
|
-
return "boolean";
|
|
11867
|
-
case "array":
|
|
11868
|
-
return "unknown[]";
|
|
11869
|
-
case "object":
|
|
11870
|
-
return "Record<string, unknown>";
|
|
11871
|
-
default:
|
|
11872
|
-
return "unknown";
|
|
11811
|
+
if (typeof value === "object") {
|
|
11812
|
+
return atpProvenance.createProvenanceProxy(value, source, {
|
|
11813
|
+
type: "public"
|
|
11814
|
+
});
|
|
11873
11815
|
}
|
|
11816
|
+
return value;
|
|
11817
|
+
}, "tagValue");
|
|
11818
|
+
if (callbackRecord.type === "llm") {
|
|
11819
|
+
const source = {
|
|
11820
|
+
type: atpProvenance.ProvenanceSource.LLM,
|
|
11821
|
+
operation: callbackRecord.operation || "call",
|
|
11822
|
+
timestamp: Date.now()
|
|
11823
|
+
};
|
|
11824
|
+
return Array.isArray(result) ? result.map((r) => tagValue(r, source)) : tagValue(result, source);
|
|
11874
11825
|
}
|
|
11875
|
-
|
|
11876
|
-
|
|
11877
|
-
|
|
11878
|
-
|
|
11879
|
-
|
|
11880
|
-
|
|
11881
|
-
|
|
11882
|
-
|
|
11883
|
-
return " [key: string]: unknown;\n";
|
|
11884
|
-
}
|
|
11885
|
-
if (schema.type === "array" && schema.items) {
|
|
11886
|
-
const itemType = this.schemaToTSType(schema.items, depth + 1);
|
|
11887
|
-
return ` [index: number]: ${itemType};
|
|
11888
|
-
length: number;
|
|
11889
|
-
`;
|
|
11890
|
-
}
|
|
11891
|
-
if (schema.type === "object" && schema.properties) {
|
|
11892
|
-
const required = schema.required || [];
|
|
11893
|
-
let result = "";
|
|
11894
|
-
for (const [key, value] of Object.entries(schema.properties)) {
|
|
11895
|
-
const prop = value;
|
|
11896
|
-
const optional = required.includes(key) ? "" : "?";
|
|
11897
|
-
const tsType = this.schemaToTSType(prop, depth + 1);
|
|
11898
|
-
result += ` ${key}${optional}: ${tsType};
|
|
11899
|
-
`;
|
|
11900
|
-
}
|
|
11901
|
-
return result || " [key: string]: unknown;\n";
|
|
11902
|
-
}
|
|
11903
|
-
return " [key: string]: unknown;\n";
|
|
11826
|
+
if (callbackRecord.type === "tool") {
|
|
11827
|
+
const source = {
|
|
11828
|
+
type: atpProvenance.ProvenanceSource.TOOL,
|
|
11829
|
+
toolName: callbackRecord.payload?.toolName || "clientTool",
|
|
11830
|
+
apiGroup: callbackRecord.payload?.namespace || "client",
|
|
11831
|
+
timestamp: Date.now()
|
|
11832
|
+
};
|
|
11833
|
+
return Array.isArray(result) ? result.map((r) => tagValue(r, source)) : tagValue(result, source);
|
|
11904
11834
|
}
|
|
11905
|
-
|
|
11906
|
-
|
|
11907
|
-
|
|
11908
|
-
|
|
11909
|
-
|
|
11910
|
-
|
|
11911
|
-
|
|
11912
|
-
|
|
11913
|
-
|
|
11914
|
-
|
|
11915
|
-
|
|
11916
|
-
|
|
11917
|
-
|
|
11918
|
-
|
|
11919
|
-
|
|
11920
|
-
|
|
11921
|
-
|
|
11922
|
-
|
|
11923
|
-
|
|
11924
|
-
|
|
11925
|
-
|
|
11926
|
-
if (schema.type === "object" && schema.properties) {
|
|
11927
|
-
const required = schema.required || [];
|
|
11928
|
-
const props = [];
|
|
11929
|
-
for (const [key, value] of Object.entries(schema.properties)) {
|
|
11930
|
-
const prop = value;
|
|
11931
|
-
const optional = required.includes(key) ? "" : "?";
|
|
11932
|
-
const tsType = this.schemaToTSType(prop, depth + 1);
|
|
11933
|
-
props.push(`${key}${optional}: ${tsType}`);
|
|
11934
|
-
}
|
|
11935
|
-
if (props.length > 0) {
|
|
11936
|
-
return `{ ${props.join("; ")} }`;
|
|
11937
|
-
}
|
|
11938
|
-
return "Record<string, unknown>";
|
|
11939
|
-
}
|
|
11940
|
-
if (schema.type) {
|
|
11941
|
-
return this.jsonSchemaTypeToTS(schema.type);
|
|
11835
|
+
return result;
|
|
11836
|
+
}
|
|
11837
|
+
__name(tagCallbackResult, "tagCallbackResult");
|
|
11838
|
+
async function handleResume(ctx, executionId, executor, stateManager, serverConfig, sessionManager) {
|
|
11839
|
+
const requestClientId = ctx.headers["x-client-id"] || ctx.clientId;
|
|
11840
|
+
const requestToken = ctx.headers["authorization"]?.replace("Bearer ", "");
|
|
11841
|
+
if (!requestClientId || !requestToken) {
|
|
11842
|
+
atpRuntime.log.warn("Resume attempt without authentication", {
|
|
11843
|
+
executionId
|
|
11844
|
+
});
|
|
11845
|
+
ctx.throw(401, "Authentication required");
|
|
11846
|
+
}
|
|
11847
|
+
ctx.clientId = requestClientId;
|
|
11848
|
+
if (sessionManager) {
|
|
11849
|
+
const isValid = await sessionManager.verifyClient(requestClientId, requestToken);
|
|
11850
|
+
if (!isValid) {
|
|
11851
|
+
atpRuntime.log.warn("Resume attempt with invalid token", {
|
|
11852
|
+
executionId,
|
|
11853
|
+
clientId: requestClientId
|
|
11854
|
+
});
|
|
11855
|
+
ctx.throw(403, "Invalid client credentials");
|
|
11942
11856
|
}
|
|
11943
|
-
return "unknown";
|
|
11944
11857
|
}
|
|
11945
|
-
|
|
11946
|
-
|
|
11947
|
-
|
|
11948
|
-
isValidIdentifier(name) {
|
|
11949
|
-
return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
|
|
11858
|
+
const pausedState = await stateManager.get(executionId);
|
|
11859
|
+
if (!pausedState) {
|
|
11860
|
+
ctx.throw(404, "Not found");
|
|
11950
11861
|
}
|
|
11951
|
-
|
|
11952
|
-
|
|
11953
|
-
|
|
11954
|
-
|
|
11955
|
-
|
|
11956
|
-
|
|
11957
|
-
|
|
11862
|
+
if (pausedState.clientId !== requestClientId) {
|
|
11863
|
+
atpRuntime.log.warn("Resume attempt by unauthorized client", {
|
|
11864
|
+
executionId,
|
|
11865
|
+
requestClientId,
|
|
11866
|
+
ownerClientId: pausedState.clientId
|
|
11867
|
+
});
|
|
11868
|
+
ctx.throw(403, "Unauthorized: execution belongs to different client");
|
|
11869
|
+
}
|
|
11870
|
+
atpRuntime.log.info("Resume authorized", {
|
|
11871
|
+
executionId,
|
|
11872
|
+
clientId: requestClientId
|
|
11873
|
+
});
|
|
11874
|
+
if (pausedState.provenanceState && pausedState.config.provenanceMode && pausedState.config.provenanceMode !== atpProtocol.ProvenanceMode.NONE) {
|
|
11875
|
+
const state = pausedState.provenanceState;
|
|
11876
|
+
if ("primitives" in state) {
|
|
11877
|
+
atpProvenance.restoreProvenanceSnapshot(executionId, state);
|
|
11878
|
+
atpRuntime.log.info("Provenance snapshot restored", {
|
|
11879
|
+
executionId,
|
|
11880
|
+
registryEntries: state.registry.length,
|
|
11881
|
+
primitiveEntries: state.primitives.length
|
|
11882
|
+
});
|
|
11883
|
+
} else {
|
|
11884
|
+
const provenanceMap = new Map(state.registry);
|
|
11885
|
+
atpProvenance.restoreProvenanceSnapshot(executionId, {
|
|
11886
|
+
registry: state.registry,
|
|
11887
|
+
primitives: []
|
|
11888
|
+
});
|
|
11889
|
+
atpRuntime.log.info("Provenance state restored (legacy format)", {
|
|
11890
|
+
executionId,
|
|
11891
|
+
entries: provenanceMap.size
|
|
11892
|
+
});
|
|
11958
11893
|
}
|
|
11959
|
-
return name;
|
|
11960
11894
|
}
|
|
11961
|
-
|
|
11962
|
-
|
|
11963
|
-
|
|
11964
|
-
|
|
11965
|
-
|
|
11966
|
-
|
|
11967
|
-
|
|
11968
|
-
|
|
11969
|
-
|
|
11970
|
-
|
|
11971
|
-
|
|
11972
|
-
|
|
11973
|
-
|
|
11974
|
-
|
|
11975
|
-
|
|
11976
|
-
|
|
11977
|
-
|
|
11978
|
-
|
|
11895
|
+
const request = ctx.body;
|
|
11896
|
+
let updatedHistory;
|
|
11897
|
+
let callbackResult;
|
|
11898
|
+
const lastRecord = pausedState.callbackHistory[pausedState.currentCallbackIndex];
|
|
11899
|
+
if (!lastRecord) {
|
|
11900
|
+
atpRuntime.log.error("No callback record found at current index", {
|
|
11901
|
+
executionId,
|
|
11902
|
+
currentIndex: pausedState.currentCallbackIndex
|
|
11903
|
+
});
|
|
11904
|
+
ctx.throw(500, "Invalid paused state: no callback record");
|
|
11905
|
+
}
|
|
11906
|
+
if (request.results) {
|
|
11907
|
+
const batchResults = request.results;
|
|
11908
|
+
atpRuntime.log.info("Processing batch callback results", {
|
|
11909
|
+
executionId,
|
|
11910
|
+
batchCount: batchResults.length
|
|
11911
|
+
});
|
|
11912
|
+
for (const br of batchResults) {
|
|
11913
|
+
if (br.result && typeof br.result === "object" && "__error" in br.result) {
|
|
11914
|
+
const errorObj = br.result;
|
|
11915
|
+
if (errorObj.message && errorObj.message.includes("service not provided")) {
|
|
11916
|
+
atpRuntime.log.error("Service provider error in batch", {
|
|
11917
|
+
executionId,
|
|
11918
|
+
error: errorObj.message
|
|
11979
11919
|
});
|
|
11920
|
+
await stateManager.delete(executionId);
|
|
11921
|
+
return {
|
|
11922
|
+
executionId,
|
|
11923
|
+
status: atpProtocol.ExecutionStatus.FAILED,
|
|
11924
|
+
error: {
|
|
11925
|
+
message: errorObj.message || "Service not available",
|
|
11926
|
+
code: "SERVICE_NOT_PROVIDED"
|
|
11927
|
+
},
|
|
11928
|
+
stats: {
|
|
11929
|
+
duration: 0,
|
|
11930
|
+
memoryUsed: 0,
|
|
11931
|
+
llmCallsCount: 0,
|
|
11932
|
+
approvalCallsCount: 0
|
|
11933
|
+
}
|
|
11934
|
+
};
|
|
11980
11935
|
}
|
|
11981
|
-
const node = current.get(part);
|
|
11982
|
-
if (i === parts.length - 1) {
|
|
11983
|
-
node.functions.push(...group.functions);
|
|
11984
|
-
}
|
|
11985
|
-
current = node.subgroups;
|
|
11986
11936
|
}
|
|
11987
11937
|
}
|
|
11988
|
-
const
|
|
11989
|
-
|
|
11990
|
-
|
|
11991
|
-
|
|
11992
|
-
|
|
11993
|
-
|
|
11994
|
-
|
|
11995
|
-
|
|
11996
|
-
|
|
11997
|
-
|
|
11998
|
-
|
|
11999
|
-
ts += `${indent2} /**
|
|
12000
|
-
${indent2} * ${description}
|
|
12001
|
-
${indent2} */
|
|
12002
|
-
`;
|
|
12003
|
-
ts += `${indent2} ${funcName}(params: ${func.name}_Input): Promise<${func.name}_Output>;
|
|
12004
|
-
`;
|
|
12005
|
-
}
|
|
12006
|
-
if (node.subgroups.size > 0) {
|
|
12007
|
-
ts += generateLevel(node.subgroups, indent2 + " ");
|
|
12008
|
-
}
|
|
12009
|
-
ts += `${indent2}};
|
|
12010
|
-
`;
|
|
11938
|
+
const taggedBatchResults = batchResults.map((br) => ({
|
|
11939
|
+
...br,
|
|
11940
|
+
result: tagCallbackResult(lastRecord, br.result, pausedState.config.provenanceMode)
|
|
11941
|
+
}));
|
|
11942
|
+
callbackResult = taggedBatchResults.map((br) => br.result);
|
|
11943
|
+
updatedHistory = pausedState.callbackHistory.map((record, index) => {
|
|
11944
|
+
if (index === pausedState.currentCallbackIndex) {
|
|
11945
|
+
return {
|
|
11946
|
+
...record,
|
|
11947
|
+
result: callbackResult
|
|
11948
|
+
};
|
|
12011
11949
|
}
|
|
12012
|
-
return
|
|
12013
|
-
}
|
|
12014
|
-
|
|
12015
|
-
|
|
12016
|
-
|
|
12017
|
-
|
|
12018
|
-
|
|
12019
|
-
|
|
12020
|
-
|
|
12021
|
-
|
|
12022
|
-
|
|
12023
|
-
|
|
11950
|
+
return record;
|
|
11951
|
+
});
|
|
11952
|
+
} else {
|
|
11953
|
+
const rawResult = request.result;
|
|
11954
|
+
if (rawResult && typeof rawResult === "object" && "__error" in rawResult) {
|
|
11955
|
+
const errorObj = rawResult;
|
|
11956
|
+
if (errorObj.message && errorObj.message.includes("service not provided")) {
|
|
11957
|
+
atpRuntime.log.error("Service provider error", {
|
|
11958
|
+
executionId,
|
|
11959
|
+
error: errorObj.message
|
|
11960
|
+
});
|
|
11961
|
+
await stateManager.delete(executionId);
|
|
11962
|
+
return {
|
|
11963
|
+
executionId,
|
|
11964
|
+
status: atpProtocol.ExecutionStatus.FAILED,
|
|
11965
|
+
error: {
|
|
11966
|
+
message: errorObj.message || "Service not available",
|
|
11967
|
+
code: "SERVICE_NOT_PROVIDED"
|
|
11968
|
+
},
|
|
11969
|
+
stats: {
|
|
11970
|
+
duration: 0,
|
|
11971
|
+
memoryUsed: 0,
|
|
11972
|
+
llmCallsCount: 0,
|
|
11973
|
+
approvalCallsCount: 0
|
|
11974
|
+
}
|
|
11975
|
+
};
|
|
11976
|
+
}
|
|
11977
|
+
}
|
|
11978
|
+
callbackResult = tagCallbackResult(lastRecord, rawResult, pausedState.config.provenanceMode);
|
|
11979
|
+
updatedHistory = pausedState.callbackHistory.map((record, index) => {
|
|
11980
|
+
if (index === pausedState.currentCallbackIndex) {
|
|
11981
|
+
return {
|
|
11982
|
+
...record,
|
|
11983
|
+
result: callbackResult
|
|
11984
|
+
};
|
|
11985
|
+
}
|
|
11986
|
+
return record;
|
|
11987
|
+
});
|
|
12024
11988
|
}
|
|
12025
|
-
|
|
12026
|
-
|
|
12027
|
-
|
|
12028
|
-
|
|
12029
|
-
|
|
12030
|
-
|
|
11989
|
+
const restoredConfig = {
|
|
11990
|
+
...pausedState.config,
|
|
11991
|
+
securityPolicies: serverConfig.execution.securityPolicies || []
|
|
11992
|
+
};
|
|
11993
|
+
const result = await executor.execute(pausedState.code, restoredConfig, pausedState.clientId, {
|
|
11994
|
+
callbackHistory: updatedHistory,
|
|
11995
|
+
newCallbackResult: callbackResult,
|
|
11996
|
+
executionId
|
|
11997
|
+
});
|
|
11998
|
+
if (result.status === atpProtocol.ExecutionStatus.PAUSED && result.needsCallbacks && result.callbackHistory) {
|
|
11999
|
+
const provenanceState = pausedState.config.provenanceMode && pausedState.config.provenanceMode !== atpProtocol.ProvenanceMode.NONE ? atpProvenance.captureProvenanceSnapshot(result.executionId) : void 0;
|
|
12000
|
+
const codeToSave = result.transformedCode || pausedState.code;
|
|
12001
|
+
await stateManager.pause({
|
|
12002
|
+
executionId: result.executionId,
|
|
12003
|
+
code: codeToSave,
|
|
12004
|
+
config: pausedState.config,
|
|
12005
|
+
clientId: pausedState.clientId,
|
|
12006
|
+
callbackRequest: result.needsCallbacks[0],
|
|
12007
|
+
pausedAt: Date.now(),
|
|
12008
|
+
callbackHistory: result.callbackHistory,
|
|
12009
|
+
currentCallbackIndex: result.callbackHistory.length - 1,
|
|
12010
|
+
context: {},
|
|
12011
|
+
provenanceState
|
|
12012
|
+
});
|
|
12013
|
+
} else if (result.status === atpProtocol.ExecutionStatus.PAUSED && result.needsCallback && result.callbackHistory) {
|
|
12014
|
+
const provenanceState = pausedState.config.provenanceMode && pausedState.config.provenanceMode !== atpProtocol.ProvenanceMode.NONE ? atpProvenance.captureProvenanceSnapshot(result.executionId) : void 0;
|
|
12015
|
+
const codeToSave = result.transformedCode || pausedState.code;
|
|
12016
|
+
await stateManager.pause({
|
|
12017
|
+
executionId: result.executionId,
|
|
12018
|
+
code: codeToSave,
|
|
12019
|
+
config: pausedState.config,
|
|
12020
|
+
clientId: pausedState.clientId,
|
|
12021
|
+
callbackRequest: result.needsCallback,
|
|
12022
|
+
pausedAt: Date.now(),
|
|
12023
|
+
callbackHistory: result.callbackHistory,
|
|
12024
|
+
currentCallbackIndex: result.callbackHistory.length - 1,
|
|
12025
|
+
context: {},
|
|
12026
|
+
provenanceState
|
|
12027
|
+
});
|
|
12028
|
+
} else {
|
|
12029
|
+
await stateManager.delete(executionId);
|
|
12031
12030
|
}
|
|
12032
|
-
|
|
12031
|
+
return result;
|
|
12032
|
+
}
|
|
12033
|
+
__name(handleResume, "handleResume");
|
|
12033
12034
|
|
|
12034
12035
|
// src/handlers/definitions.handler.ts
|
|
12035
12036
|
async function getDefinitions(apiGroups) {
|