@axiom-lattice/gateway 10.1.1 → 10.2.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/{WechatChannelAdapter-QLPJJD6S.mjs → WechatChannelAdapter-EEETBUR3.mjs} +2 -2
- package/dist/{a2a-standard-NOAVPYXJ.mjs → a2a-standard-OANCQYQ2.mjs} +8 -4
- package/dist/a2a-standard-OANCQYQ2.mjs.map +1 -0
- package/dist/{chunk-A7YNAU5L.mjs → chunk-4XWI7U3L.mjs} +106 -1
- package/dist/chunk-4XWI7U3L.mjs.map +1 -0
- package/dist/{chunk-PHWGCRW2.mjs → chunk-67CDUQM3.mjs} +16 -2
- package/dist/chunk-67CDUQM3.mjs.map +1 -0
- package/dist/{chunk-6CUQGDJI.mjs → chunk-ELYWN3TJ.mjs} +8 -4
- package/dist/chunk-ELYWN3TJ.mjs.map +1 -0
- package/dist/embed/{embed-page-AgentDetailSideApp-HNSIMIXX.js → embed-page-AgentDetailSideApp-WAATX6D3.js} +1 -1
- package/dist/embed/{embed-page-AgentGovernanceWorkbench-QBEH3KYW.js → embed-page-AgentGovernanceWorkbench-MOIYXL5S.js} +1 -1
- package/dist/embed/{embed-page-LangfuseDashboard-QHWHMJVB.js → embed-page-LangfuseDashboard-7ZWWE45Q.js} +1 -1
- package/dist/embed/{embed-page-MessageGraph-GXEC7IPB.js → embed-page-MessageGraph-JG554SNZ.js} +1 -1
- package/dist/embed/{embed-page-ReactChart-LW6COMT3.js → embed-page-ReactChart-WHOMS6I6.js} +1 -1
- package/dist/embed/{embed-page-ReactInfographic-677NVKOU.js → embed-page-ReactInfographic-5P36JLSX.js} +1 -1
- package/dist/embed/{embed-page-SkillFlow-ULY3XZ3A.js → embed-page-SkillFlow-RP54B2A5.js} +1 -1
- package/dist/embed/{embed-page-TasksSideApp-Q76BWXUV.js → embed-page-TasksSideApp-6TCN3T73.js} +1 -1
- package/dist/embed/{embed-page-ThreadMaintenancePanel-N5IFOOFT.js → embed-page-ThreadMaintenancePanel-WNWYNASM.js} +1 -1
- package/dist/embed/{embed-page-TopologyRuntimeView-POBS44XX.js → embed-page-TopologyRuntimeView-UMC4XOUL.js} +1 -1
- package/dist/embed/{embed-page-WorkflowAutomationView-UH633BXC.js → embed-page-WorkflowAutomationView-PUOPYYGB.js} +1 -1
- package/dist/embed/embed-page-all-NEJVJ4G7.js +1 -0
- package/dist/embed/{embed-page-architectureDiagram-VXUJARFQ-TYJ3NO2K.js → embed-page-architectureDiagram-VXUJARFQ-THUN2PFL.js} +1 -1
- package/dist/embed/embed-page-aspnet-SRK67AH2.js +1 -0
- package/dist/embed/{embed-page-blockDiagram-VD42YOAC-L4J3TZWR.js → embed-page-blockDiagram-VD42YOAC-K7OX6LIO.js} +1 -1
- package/dist/embed/{embed-page-c4Diagram-YG6GDRKO-CP2IXU3Z.js → embed-page-c4Diagram-YG6GDRKO-DJDAF5AO.js} +1 -1
- package/dist/embed/embed-page-chunk-4GCFDWE7.js +6997 -0
- package/dist/embed/{embed-page-chunk-3FNSGFP2.js → embed-page-chunk-5EENS2J7.js} +16 -16
- package/dist/embed/{embed-page-chunk-3XPHW2C7.js → embed-page-chunk-5O5IKZOC.js} +1 -1
- package/dist/embed/{embed-page-chunk-DQJVWZOB.js → embed-page-chunk-A2AHDN6K.js} +1 -1
- package/dist/embed/embed-page-chunk-AFYXBC77.js +217 -0
- package/dist/embed/{embed-page-chunk-F5QVZLK5.js → embed-page-chunk-DTRFJLVZ.js} +1 -1
- package/dist/embed/embed-page-chunk-ESQ5V77Q.js +1 -0
- package/dist/embed/{embed-page-chunk-2VJ7T35I.js → embed-page-chunk-FD2PRLMW.js} +1 -1
- package/dist/embed/{embed-page-chunk-KXVXKWED.js → embed-page-chunk-G2RO6IBN.js} +1 -1
- package/dist/embed/{embed-page-chunk-KKNZYZVB.js → embed-page-chunk-G6UTU7IC.js} +1 -1
- package/dist/embed/{embed-page-chunk-7GLQRV3J.js → embed-page-chunk-J5AHS4PO.js} +1 -1
- package/dist/embed/{embed-page-chunk-5WWOKLDB.js → embed-page-chunk-JUZPOR5Y.js} +1 -1
- package/dist/embed/{embed-page-chunk-62CAXPZK.js → embed-page-chunk-ML6AVDQQ.js} +1 -1
- package/dist/embed/{embed-page-chunk-YBP3MD23.js → embed-page-chunk-OBN4XHZP.js} +1 -1
- package/dist/embed/{embed-page-chunk-NVFNRWRN.js → embed-page-chunk-PLNJRORR.js} +1 -1
- package/dist/embed/{embed-page-chunk-AJV2ISVF.js → embed-page-chunk-QRFTGCB2.js} +1 -1
- package/dist/embed/{embed-page-chunk-NR4M6XSO.js → embed-page-chunk-RU45VIPM.js} +1 -1
- package/dist/embed/{embed-page-chunk-AEDAOTEO.js → embed-page-chunk-SQ4GANYE.js} +1 -1
- package/dist/embed/embed-page-chunk-TZPX2O54.js +7 -0
- package/dist/embed/{embed-page-chunk-YJUCDIYK.js → embed-page-chunk-V7R2Y72J.js} +1 -1
- package/dist/embed/{embed-page-chunk-XSKDYUNQ.js → embed-page-chunk-VY6MAPHR.js} +1 -1
- package/dist/embed/{embed-page-chunk-WK77HIEN.js → embed-page-chunk-WFUFTRWA.js} +1 -1
- package/dist/embed/{embed-page-chunk-7CJDHJEH.js → embed-page-chunk-XKGF5D6L.js} +1 -1
- package/dist/embed/{embed-page-chunk-WWXRO4ZL.js → embed-page-chunk-XSKNS3LY.js} +1 -1
- package/dist/embed/{embed-page-chunk-NGO5C5RH.js → embed-page-chunk-ZVTX7OVB.js} +1 -1
- package/dist/embed/embed-page-classDiagram-2ON5EDUG-VYHHMIKZ.js +1 -0
- package/dist/embed/embed-page-classDiagram-v2-WZHVMYZB-5AISLXUF.js +1 -0
- package/dist/embed/{embed-page-code-highlighter-4XNLEZAM.js → embed-page-code-highlighter-ZZBZ7CEQ.js} +1 -1
- package/dist/embed/embed-page-cshtml-ZY7LJSTH.js +1 -0
- package/dist/embed/{embed-page-dagre-6UL2VRFP-LTZ2DVVO.js → embed-page-dagre-6UL2VRFP-UQFZMKYW.js} +1 -1
- package/dist/embed/{embed-page-diagram-PSM6KHXK-JHYXSMCB.js → embed-page-diagram-PSM6KHXK-4IKXWNA4.js} +1 -1
- package/dist/embed/{embed-page-diagram-QEK2KX5R-2YGDFFTU.js → embed-page-diagram-QEK2KX5R-245T32UF.js} +1 -1
- package/dist/embed/{embed-page-diagram-S2PKOQOG-6EW6MDJW.js → embed-page-diagram-S2PKOQOG-BOA5MJA5.js} +1 -1
- package/dist/embed/embed-page-en-5E2A4Q7G.js +1 -0
- package/dist/embed/embed-page-en-AEJHFSAV.js +1 -0
- package/dist/embed/{embed-page-en-3Z4N5KXB.js → embed-page-en-QULE3S6E.js} +1 -1
- package/dist/embed/{embed-page-erDiagram-Q2GNP2WA-KSUS6MHW.js → embed-page-erDiagram-Q2GNP2WA-S4J4SQPR.js} +1 -1
- package/dist/embed/{embed-page-flowDiagram-NV44I4VS-AYXRDKAJ.js → embed-page-flowDiagram-NV44I4VS-ZFIJXKMW.js} +1 -1
- package/dist/embed/{embed-page-ganttDiagram-JELNMOA3-AV7N2N3T.js → embed-page-ganttDiagram-JELNMOA3-7MSIEWL4.js} +1 -1
- package/dist/embed/{embed-page-gitGraphDiagram-NY62KEGX-IBVOXVO5.js → embed-page-gitGraphDiagram-NY62KEGX-F6KE6PZK.js} +1 -1
- package/dist/embed/embed-page-infoDiagram-WHAUD3N6-FQMKXERB.js +2 -0
- package/dist/embed/{embed-page-journeyDiagram-XKPGCS4Q-3GILI7Y4.js → embed-page-journeyDiagram-XKPGCS4Q-6VTW6GQ3.js} +1 -1
- package/dist/embed/{embed-page-kanban-definition-3W4ZIXB7-UGO3J7IH.js → embed-page-kanban-definition-3W4ZIXB7-7IZYCLQZ.js} +1 -1
- package/dist/embed/{embed-page-mermaid-QZJOSGTZ.js → embed-page-mermaid-O5AJMXHC.js} +2 -2
- package/dist/embed/{embed-page-mindmap-definition-VGOIOE7T-VXXZJS3Z.js → embed-page-mindmap-definition-VGOIOE7T-GKTOT34A.js} +1 -1
- package/dist/embed/{embed-page-pieDiagram-ADFJNKIX-ZFAWYA2N.js → embed-page-pieDiagram-ADFJNKIX-VDPALO42.js} +1 -1
- package/dist/embed/{embed-page-requirementDiagram-UZGBJVZJ-2QBINXR7.js → embed-page-requirementDiagram-UZGBJVZJ-LTZH6RTD.js} +1 -1
- package/dist/embed/{embed-page-sequenceDiagram-WL72ISMW-3MGTESG4.js → embed-page-sequenceDiagram-WL72ISMW-LV6Q4SHW.js} +1 -1
- package/dist/embed/{embed-page-stateDiagram-FKZM4ZOC-W6VPIMB5.js → embed-page-stateDiagram-FKZM4ZOC-U4NHQDNP.js} +1 -1
- package/dist/embed/embed-page-stateDiagram-v2-4FDKWEC3-G3EWQCOW.js +1 -0
- package/dist/embed/{embed-page-tsx-LGDDERM2.js → embed-page-tsx-PNW7N5T4.js} +1 -1
- package/dist/embed/{embed-page-xychartDiagram-PRI3JC2R-7XKT4R7V.js → embed-page-xychartDiagram-PRI3JC2R-VZSIXBFK.js} +1 -1
- package/dist/embed/embed-page-zh-EZHTNARQ.js +1 -0
- package/dist/embed/embed-page-zh-TOINMHLQ.js +1 -0
- package/dist/embed/{embed-page-zh-GXE63PQ7.js → embed-page-zh-WT752BVZ.js} +1 -1
- package/dist/embed/embed-page.js +1 -1
- package/dist/embed/mcp-app-page.js +32 -32
- package/dist/index.d.mts +145 -1
- package/dist/index.d.ts +145 -1
- package/dist/index.js +8156 -1476
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +7077 -491
- package/dist/index.mjs.map +1 -1
- package/dist/{mcp-app-shares-SHPBJQXS.mjs → mcp-app-shares-VN6G3LNW.mjs} +2 -2
- package/package.json +11 -7
- package/dist/a2a-standard-NOAVPYXJ.mjs.map +0 -1
- package/dist/chunk-6CUQGDJI.mjs.map +0 -1
- package/dist/chunk-A7YNAU5L.mjs.map +0 -1
- package/dist/chunk-PHWGCRW2.mjs.map +0 -1
- package/dist/embed/embed-page-all-JEPF6WHD.js +0 -1
- package/dist/embed/embed-page-aspnet-GIV4ESY6.js +0 -1
- package/dist/embed/embed-page-chunk-54M4265G.js +0 -211
- package/dist/embed/embed-page-chunk-5QZRLAW2.js +0 -7
- package/dist/embed/embed-page-chunk-KWZEITYQ.js +0 -6986
- package/dist/embed/embed-page-chunk-ZQQFWEWO.js +0 -1
- package/dist/embed/embed-page-classDiagram-2ON5EDUG-MHNSVPAN.js +0 -1
- package/dist/embed/embed-page-classDiagram-v2-WZHVMYZB-QCMEVMYH.js +0 -1
- package/dist/embed/embed-page-cshtml-RYMZMLKB.js +0 -1
- package/dist/embed/embed-page-en-2S7Q4NKN.js +0 -1
- package/dist/embed/embed-page-infoDiagram-WHAUD3N6-ZULKOSOZ.js +0 -2
- package/dist/embed/embed-page-stateDiagram-v2-4FDKWEC3-QYJ47QBY.js +0 -1
- package/dist/embed/embed-page-zh-GX6IEO57.js +0 -1
- /package/dist/{WechatChannelAdapter-QLPJJD6S.mjs.map → WechatChannelAdapter-EEETBUR3.mjs.map} +0 -0
- /package/dist/embed/{embed-page-chunk-UH47IEAR.js → embed-page-chunk-34FVRFPW.js} +0 -0
- /package/dist/{mcp-app-shares-SHPBJQXS.mjs.map → mcp-app-shares-VN6G3LNW.mjs.map} +0 -0
|
@@ -24,6 +24,46 @@ var DEFAULT_RATE_LIMIT_POLICIES = {
|
|
|
24
24
|
windowMs: 6e4,
|
|
25
25
|
dimensions: ["ip"]
|
|
26
26
|
},
|
|
27
|
+
"auth.oidc.begin": {
|
|
28
|
+
limit: 60,
|
|
29
|
+
windowMs: 6e4,
|
|
30
|
+
dimensions: ["ip"]
|
|
31
|
+
},
|
|
32
|
+
"auth.oidc.callback": {
|
|
33
|
+
limit: 30,
|
|
34
|
+
windowMs: 6e4,
|
|
35
|
+
dimensions: ["ip"]
|
|
36
|
+
},
|
|
37
|
+
"auth.oidc.exchange": {
|
|
38
|
+
limit: 60,
|
|
39
|
+
windowMs: 6e4,
|
|
40
|
+
dimensions: ["ip"]
|
|
41
|
+
},
|
|
42
|
+
"invite.link.resolve": {
|
|
43
|
+
limit: 60,
|
|
44
|
+
windowMs: 6e4,
|
|
45
|
+
dimensions: ["ip"]
|
|
46
|
+
},
|
|
47
|
+
"invite.link.claim": {
|
|
48
|
+
limit: 30,
|
|
49
|
+
windowMs: 6e4,
|
|
50
|
+
dimensions: ["ip"]
|
|
51
|
+
},
|
|
52
|
+
"branding.read": {
|
|
53
|
+
limit: 300,
|
|
54
|
+
windowMs: 6e4,
|
|
55
|
+
dimensions: ["ip"]
|
|
56
|
+
},
|
|
57
|
+
"auth.oidc.email_completion": {
|
|
58
|
+
limit: 30,
|
|
59
|
+
windowMs: 6e4,
|
|
60
|
+
dimensions: ["ip"]
|
|
61
|
+
},
|
|
62
|
+
"oidc-provider.test": {
|
|
63
|
+
limit: 20,
|
|
64
|
+
windowMs: 6e4,
|
|
65
|
+
dimensions: ["user", "ip"]
|
|
66
|
+
},
|
|
27
67
|
"open.api": {
|
|
28
68
|
limit: 6e4,
|
|
29
69
|
windowMs: 6e4,
|
|
@@ -268,11 +308,74 @@ function mergeRateLimitPolicies(config = {}, logger = console) {
|
|
|
268
308
|
}
|
|
269
309
|
return merged;
|
|
270
310
|
}
|
|
311
|
+
function platformRateLimitOverrides(settings) {
|
|
312
|
+
const snapshot = settings.getSnapshot();
|
|
313
|
+
const sources = snapshot.sources;
|
|
314
|
+
const rateLimits = snapshot.effective.rateLimits;
|
|
315
|
+
const overrides = {};
|
|
316
|
+
if (sources.openApiPerMinute === "platform") {
|
|
317
|
+
overrides["open.api"] = { limit: rateLimits.openApiPerMinute };
|
|
318
|
+
}
|
|
319
|
+
if (sources.openAgentPerMinute === "platform") {
|
|
320
|
+
overrides["open.agent"] = { limit: rateLimits.openAgentPerMinute };
|
|
321
|
+
}
|
|
322
|
+
const a2a = {};
|
|
323
|
+
if (sources.a2aJsonRpcPerMinute === "platform") {
|
|
324
|
+
a2a.limit = rateLimits.a2aJsonRpcPerMinute;
|
|
325
|
+
}
|
|
326
|
+
if (sources.a2aJsonRpcIpPerMinute === "platform") {
|
|
327
|
+
a2a.dimensionLimits = { ip: rateLimits.a2aJsonRpcIpPerMinute };
|
|
328
|
+
}
|
|
329
|
+
if (Object.keys(a2a).length > 0) overrides["a2a.jsonrpc"] = a2a;
|
|
330
|
+
return overrides;
|
|
331
|
+
}
|
|
332
|
+
function mergePolicyOverrides(base, overrides) {
|
|
333
|
+
const merged = { ...base };
|
|
334
|
+
for (const [name, value] of Object.entries(overrides)) {
|
|
335
|
+
const existing = merged[name];
|
|
336
|
+
if (!existing) {
|
|
337
|
+
merged[name] = { ...value };
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
340
|
+
const dimensionLimits = {
|
|
341
|
+
...existing.dimensionLimits ?? {},
|
|
342
|
+
...value.dimensionLimits ?? {}
|
|
343
|
+
};
|
|
344
|
+
merged[name] = {
|
|
345
|
+
...existing,
|
|
346
|
+
...value,
|
|
347
|
+
...Object.keys(dimensionLimits).length > 0 ? { dimensionLimits } : {}
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
return merged;
|
|
351
|
+
}
|
|
271
352
|
var RateLimitService = class {
|
|
272
353
|
constructor(options) {
|
|
273
354
|
this.options = options;
|
|
274
355
|
this.warnedPolicies = /* @__PURE__ */ new Set();
|
|
275
356
|
}
|
|
357
|
+
/** Replace the active policy map, e.g. after platform settings change. */
|
|
358
|
+
updatePolicies(policies) {
|
|
359
|
+
this.options.policies = policies;
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Rebuild the active policy map on top of the host config overrides.
|
|
363
|
+
*
|
|
364
|
+
* Use this for platform settings changes so host-supplied
|
|
365
|
+
* `rateLimits.policies` are preserved instead of being lost by a full-map
|
|
366
|
+
* replacement.
|
|
367
|
+
*/
|
|
368
|
+
updatePlatformPolicies(overrides) {
|
|
369
|
+
this.options.policies = mergeRateLimitPolicies(
|
|
370
|
+
{
|
|
371
|
+
policies: mergePolicyOverrides(
|
|
372
|
+
this.options.basePolicyOverrides ?? {},
|
|
373
|
+
overrides
|
|
374
|
+
)
|
|
375
|
+
},
|
|
376
|
+
this.options.logger
|
|
377
|
+
);
|
|
378
|
+
}
|
|
276
379
|
/**
|
|
277
380
|
* Consume one request against a named policy.
|
|
278
381
|
*
|
|
@@ -350,6 +453,7 @@ function createRateLimitService(config = {}, logger = console) {
|
|
|
350
453
|
maxEntries: config.maxInMemoryEntries ?? DEFAULT_MAX_ENTRIES
|
|
351
454
|
}),
|
|
352
455
|
policies: mergeRateLimitPolicies(config, logger),
|
|
456
|
+
basePolicyOverrides: config.policies ?? {},
|
|
353
457
|
enabled: config.enabled ?? process.env.AXIOM_RATE_LIMIT_DISABLED !== "true",
|
|
354
458
|
logger
|
|
355
459
|
});
|
|
@@ -370,8 +474,9 @@ function getRateLimitService() {
|
|
|
370
474
|
export {
|
|
371
475
|
claimDedupKey,
|
|
372
476
|
incrementRateCounter,
|
|
477
|
+
platformRateLimitOverrides,
|
|
373
478
|
createRateLimitService,
|
|
374
479
|
setRateLimitService,
|
|
375
480
|
getRateLimitService
|
|
376
481
|
};
|
|
377
|
-
//# sourceMappingURL=chunk-
|
|
482
|
+
//# sourceMappingURL=chunk-4XWI7U3L.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/services/rate-limit/RateLimitService.ts","../src/services/rate-limit/defaultPolicies.ts","../src/router/middlewares/channelSharedState.ts","../src/services/rate-limit/RateLimitStore.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport type { PlatformSettingsProvider } from \"@axiom-lattice/protocols\";\nimport {\n DEFAULT_RATE_LIMIT_POLICIES,\n legacyOpenRateLimitPolicies,\n} from \"./defaultPolicies\";\nimport {\n HybridRateLimitStore,\n RedisRateLimitStore,\n} from \"./RateLimitStore\";\nimport type {\n RateLimitConfig,\n RateLimitDecision,\n RateLimitDimension,\n RateLimitPolicy,\n RateLimitStore,\n} from \"./types\";\n\nconst DIMENSIONS: ReadonlySet<RateLimitDimension> = new Set([\n \"ip\",\n \"token\",\n \"user\",\n \"tenant\",\n \"credential\",\n \"key\",\n \"session\",\n]);\nconst DEFAULT_MAX_ENTRIES = 10_000;\n\n/** SHA-256 a dimension value so secrets never appear in keys. */\nfunction hashDimension(value: string): string {\n return createHash(\"sha256\").update(value).digest(\"hex\");\n}\n\n/** Validate one policy before it can be used for enforcement. */\nfunction normalizePolicy(\n name: string,\n value: Partial<RateLimitPolicy>,\n base?: RateLimitPolicy,\n logger: Pick<Console, \"warn\"> = console,\n): RateLimitPolicy | undefined {\n const limit = value.limit ?? base?.limit;\n const windowMs = value.windowMs ?? base?.windowMs;\n const dimensions = value.dimensions ?? base?.dimensions;\n if (\n typeof limit !== \"number\" ||\n !Number.isFinite(limit) ||\n limit <= 0 ||\n typeof windowMs !== \"number\" ||\n !Number.isFinite(windowMs) ||\n windowMs <= 0 ||\n !Array.isArray(dimensions) ||\n dimensions.length === 0 ||\n dimensions.some((dimension) => !DIMENSIONS.has(dimension))\n ) {\n logger.warn(JSON.stringify({\n event: \"rate-limit:invalid-policy\",\n policy: name,\n }));\n return base ? { ...base, dimensions: [...base.dimensions] } : undefined;\n }\n const dimensionLimits: Partial<Record<RateLimitDimension, number>> = {\n ...(base?.dimensionLimits ?? {}),\n };\n const rawDimensionLimits = (value as { dimensionLimits?: unknown }).dimensionLimits;\n if (rawDimensionLimits !== undefined) {\n if (\n typeof rawDimensionLimits !== \"object\" ||\n rawDimensionLimits === null ||\n Array.isArray(rawDimensionLimits)\n ) {\n logger.warn(JSON.stringify({\n event: \"rate-limit:invalid-dimension-limits\",\n policy: name,\n }));\n } else {\n for (const [dimension, raw] of Object.entries(rawDimensionLimits)) {\n if (\n !DIMENSIONS.has(dimension as RateLimitDimension) ||\n typeof raw !== \"number\" ||\n !Number.isFinite(raw) ||\n raw <= 0\n ) {\n logger.warn(JSON.stringify({\n event: \"rate-limit:invalid-dimension-limit\",\n policy: name,\n dimension,\n }));\n continue;\n }\n dimensionLimits[dimension as RateLimitDimension] = Math.floor(raw);\n }\n }\n }\n return {\n limit: Math.floor(limit),\n windowMs: Math.floor(windowMs),\n dimensions: [...dimensions],\n ...(Object.keys(dimensionLimits).length > 0 ? { dimensionLimits } : {}),\n ...(value.enabled !== undefined\n ? { enabled: value.enabled }\n : base?.enabled !== undefined\n ? { enabled: base.enabled }\n : {}),\n };\n}\n\n/** Parse `AXIOM_RATE_LIMIT_POLICIES` as a partial policy map. */\nexport function parseRateLimitPoliciesEnv(\n raw: string | undefined,\n logger: Pick<Console, \"warn\"> = console,\n): Record<string, Partial<RateLimitPolicy>> {\n if (!raw || raw.trim() === \"\") return {};\n try {\n const parsed: unknown = JSON.parse(raw);\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n throw new Error(\"expected an object\");\n }\n return parsed as Record<string, Partial<RateLimitPolicy>>;\n } catch (error) {\n logger.warn(JSON.stringify({\n event: \"rate-limit:invalid-env-policies\",\n error: error instanceof Error ? error.message : String(error),\n }));\n return {};\n }\n}\n\n/** Merge defaults, env, and host overrides into a validated policy map. */\nexport function mergeRateLimitPolicies(\n config: RateLimitConfig = {},\n logger: Pick<Console, \"warn\"> = console,\n): Record<string, RateLimitPolicy> {\n const merged: Record<string, RateLimitPolicy> = {};\n for (const [name, policy] of Object.entries(DEFAULT_RATE_LIMIT_POLICIES)) {\n merged[name] = { ...policy, dimensions: [...policy.dimensions] };\n }\n const overrides = [\n legacyOpenRateLimitPolicies(process.env),\n parseRateLimitPoliciesEnv(process.env.AXIOM_RATE_LIMIT_POLICIES, logger),\n config.policies ?? {},\n ];\n for (const layer of overrides) {\n for (const [name, value] of Object.entries(layer)) {\n const policy = normalizePolicy(name, value, merged[name], logger);\n if (policy) merged[name] = policy;\n }\n }\n return merged;\n}\n\n/**\n * Map the platform rate-limit settings onto policy overrides.\n *\n * Only leaves actually sourced from the persisted platform document are\n * emitted. Effective env/default values must not become platform overrides:\n * doing so would silently replace operator-configured host or environment\n * limits during composition.\n */\nexport function platformRateLimitOverrides(\n settings: Pick<PlatformSettingsProvider, \"getSnapshot\" | \"getRateLimits\">,\n): Record<string, Partial<RateLimitPolicy>> {\n const snapshot = settings.getSnapshot();\n const sources = snapshot.sources;\n const rateLimits = snapshot.effective.rateLimits;\n const overrides: Record<string, Partial<RateLimitPolicy>> = {};\n\n if (sources.openApiPerMinute === \"platform\") {\n overrides[\"open.api\"] = { limit: rateLimits.openApiPerMinute };\n }\n if (sources.openAgentPerMinute === \"platform\") {\n overrides[\"open.agent\"] = { limit: rateLimits.openAgentPerMinute };\n }\n\n const a2a: Partial<RateLimitPolicy> = {};\n if (sources.a2aJsonRpcPerMinute === \"platform\") {\n a2a.limit = rateLimits.a2aJsonRpcPerMinute;\n }\n if (sources.a2aJsonRpcIpPerMinute === \"platform\") {\n a2a.dimensionLimits = { ip: rateLimits.a2aJsonRpcIpPerMinute };\n }\n if (Object.keys(a2a).length > 0) overrides[\"a2a.jsonrpc\"] = a2a;\n\n return overrides;\n}\n\n/**\n * Merge two partial policy maps at policy-key granularity.\n *\n * Host base overrides are preserved unless the platform layer sets the same\n * field. `dimensionLimits` objects are merged per dimension instead of being\n * replaced, so a platform override of one dimension keeps host dimensions.\n */\nfunction mergePolicyOverrides(\n base: Record<string, Partial<RateLimitPolicy>>,\n overrides: Record<string, Partial<RateLimitPolicy>>,\n): Record<string, Partial<RateLimitPolicy>> {\n const merged: Record<string, Partial<RateLimitPolicy>> = { ...base };\n for (const [name, value] of Object.entries(overrides)) {\n const existing = merged[name];\n if (!existing) {\n merged[name] = { ...value };\n continue;\n }\n const dimensionLimits = {\n ...(existing.dimensionLimits ?? {}),\n ...(value.dimensionLimits ?? {}),\n };\n merged[name] = {\n ...existing,\n ...value,\n ...(Object.keys(dimensionLimits).length > 0 ? { dimensionLimits } : {}),\n };\n }\n return merged;\n}\n\n/** Dependencies for {@link RateLimitService}. */\nexport interface RateLimitServiceOptions {\n store: RateLimitStore;\n policies: Record<string, RateLimitPolicy>;\n enabled: boolean;\n logger?: Pick<Console, \"warn\">;\n /**\n * Host-supplied policy overrides (the gateway `rateLimits.policies` config).\n *\n * Kept so platform settings updates can rebuild the effective policy map\n * without dropping these host overrides.\n */\n basePolicyOverrides?: Record<string, Partial<RateLimitPolicy>>;\n}\n\n/**\n * Reusable fixed-window rate limiter.\n *\n * Each policy declares dimensions; a request is allowed only when every\n * supplied dimension stays under the policy limit. Missing dimension values are\n * skipped, so routes should provide at least one meaningful dimension.\n */\nexport class RateLimitService {\n private readonly warnedPolicies = new Set<string>();\n\n constructor(private options: RateLimitServiceOptions) {}\n\n /** Replace the active policy map, e.g. after platform settings change. */\n updatePolicies(policies: Record<string, RateLimitPolicy>): void {\n this.options.policies = policies;\n }\n\n /**\n * Rebuild the active policy map on top of the host config overrides.\n *\n * Use this for platform settings changes so host-supplied\n * `rateLimits.policies` are preserved instead of being lost by a full-map\n * replacement.\n */\n updatePlatformPolicies(\n overrides: Record<string, Partial<RateLimitPolicy>>,\n ): void {\n this.options.policies = mergeRateLimitPolicies(\n {\n policies: mergePolicyOverrides(\n this.options.basePolicyOverrides ?? {},\n overrides,\n ),\n },\n this.options.logger,\n );\n }\n\n /**\n * Consume one request against a named policy.\n *\n * @param policyName - Policy key (for example `mcp-app-share.rpc`).\n * @param values - Dimension values for this request.\n * @returns The decision; `allowed:false` means the caller should return 429.\n */\n async consume(\n policyName: string,\n values: Partial<Record<RateLimitDimension, string | undefined>>,\n ): Promise<RateLimitDecision> {\n if (!this.options.enabled) {\n return {\n allowed: true,\n policy: policyName,\n limit: 0,\n remaining: 0,\n retryAfterSeconds: 0,\n };\n }\n const policy = this.options.policies[policyName];\n if (!policy && !this.warnedPolicies.has(policyName)) {\n this.warnedPolicies.add(policyName);\n this.options.logger?.warn(JSON.stringify({\n event: \"rate-limit:unknown-policy\",\n policy: policyName,\n }));\n }\n if (!policy || policy.enabled === false) {\n return {\n allowed: true,\n policy: policyName,\n limit: policy?.limit ?? 0,\n remaining: policy?.limit ?? 0,\n retryAfterSeconds: 0,\n };\n }\n\n let remaining = policy.limit;\n for (const dimension of policy.dimensions) {\n const raw = values[dimension];\n if (typeof raw !== \"string\" || raw === \"\") continue;\n const key = `axiom:rate-limit:${policyName}:${dimension}:${hashDimension(raw)}`;\n const result = await this.options.store.increment(key, policy.windowMs);\n if (!result) continue;\n const dimensionLimit = policy.dimensionLimits?.[dimension] ?? policy.limit;\n remaining = Math.min(remaining, dimensionLimit - result.count);\n if (result.count > dimensionLimit) {\n return {\n allowed: false,\n policy: policyName,\n limit: dimensionLimit,\n remaining: 0,\n retryAfterSeconds: Math.max(1, Math.ceil(result.ttlMs / 1000)),\n exceededDimension: dimension,\n };\n }\n }\n\n return {\n allowed: true,\n policy: policyName,\n limit: policy.limit,\n remaining: Math.max(0, remaining),\n retryAfterSeconds: 0,\n };\n }\n}\n\n/**\n * Build the gateway rate-limit service from config + environment.\n */\nexport function createRateLimitService(\n config: RateLimitConfig = {},\n logger: Pick<Console, \"warn\"> = console,\n): RateLimitService {\n const redisUrl = config.redisUrl ?? process.env.REDIS_URL?.trim();\n const redis = redisUrl\n ? new RedisRateLimitStore({\n url: redisUrl,\n onError: (error) => logger.warn(JSON.stringify({\n event: \"rate-limit:redis-unavailable\",\n error: error instanceof Error ? error.message : String(error),\n })),\n })\n : undefined;\n return new RateLimitService({\n store: new HybridRateLimitStore(redis, {\n maxEntries: config.maxInMemoryEntries ?? DEFAULT_MAX_ENTRIES,\n }),\n policies: mergeRateLimitPolicies(config, logger),\n basePolicyOverrides: config.policies ?? {},\n enabled:\n config.enabled\n ?? process.env.AXIOM_RATE_LIMIT_DISABLED !== \"true\",\n logger,\n });\n}\n\nconst disabledService = new RateLimitService({\n store: new HybridRateLimitStore(undefined),\n policies: {},\n enabled: false,\n});\nlet defaultService: RateLimitService | undefined;\n\n/** Install the gateway-wide rate-limit service (called by gateway startup). */\nexport function setRateLimitService(service: RateLimitService): void {\n defaultService = service;\n}\n\n/** Reset to the disabled default; intended for tests. */\nexport function resetRateLimitService(): void {\n defaultService = undefined;\n}\n\n/**\n * Read the gateway-wide rate-limit service.\n *\n * Direct route unit tests (which do not start the gateway) get a disabled\n * service; production startup installs the configured one via\n * {@link setRateLimitService}.\n */\nexport function getRateLimitService(): RateLimitService {\n return defaultService ?? disabledService;\n}\n","import type { RateLimitPolicy } from \"./types\";\n\n/**\n * Gateway default rate-limit policies.\n *\n * Routes opt in explicitly; this table is not a blanket limit for every API.\n * Deployment overrides merge over these values (see `RateLimitConfig`).\n */\nexport const DEFAULT_RATE_LIMIT_POLICIES: Record<string, RateLimitPolicy> = {\n \"mcp-app-share.rpc\": {\n limit: 600,\n windowMs: 60_000,\n dimensions: [\"token\", \"ip\"],\n dimensionLimits: { ip: 60 },\n },\n \"mcp-app-share.unlock\": {\n limit: 5,\n windowMs: 60_000,\n dimensions: [\"token\", \"ip\"],\n },\n \"mcp-app-share.bootstrap\": {\n limit: 300,\n windowMs: 60_000,\n dimensions: [\"ip\"],\n },\n \"auth.login\": {\n limit: 10,\n windowMs: 60_000,\n dimensions: [\"ip\"],\n },\n \"auth.oidc.begin\": {\n limit: 60,\n windowMs: 60_000,\n dimensions: [\"ip\"],\n },\n \"auth.oidc.callback\": {\n limit: 30,\n windowMs: 60_000,\n dimensions: [\"ip\"],\n },\n \"auth.oidc.exchange\": {\n limit: 60,\n windowMs: 60_000,\n dimensions: [\"ip\"],\n },\n \"invite.link.resolve\": {\n limit: 60,\n windowMs: 60_000,\n dimensions: [\"ip\"],\n },\n \"invite.link.claim\": {\n limit: 30,\n windowMs: 60_000,\n dimensions: [\"ip\"],\n },\n \"branding.read\": {\n limit: 300,\n windowMs: 60_000,\n dimensions: [\"ip\"],\n },\n \"auth.oidc.email_completion\": {\n limit: 30,\n windowMs: 60_000,\n dimensions: [\"ip\"],\n },\n \"oidc-provider.test\": {\n limit: 20,\n windowMs: 60_000,\n dimensions: [\"user\", \"ip\"],\n },\n \"open.api\": {\n limit: 60_000,\n windowMs: 60_000,\n dimensions: [\"credential\"],\n },\n \"open.agent\": {\n limit: 2_000,\n windowMs: 60_000,\n dimensions: [\"credential\"],\n },\n \"a2a.jsonrpc\": {\n limit: 600,\n windowMs: 60_000,\n dimensions: [\"key\", \"ip\"],\n dimensionLimits: { ip: 300 },\n },\n};\n\n/**\n * Legacy Open rate-limit env as a fallback layer.\n *\n * `OPEN_RATE_LIMIT_PER_MINUTE` / `OPEN_AGENT_RATE_LIMIT_PER_MINUTE` predate the\n * gateway policy table. They sit below `AXIOM_RATE_LIMIT_POLICIES` and host\n * overrides so new configuration can supersede them.\n */\nexport function legacyOpenRateLimitPolicies(\n env: NodeJS.ProcessEnv = process.env,\n): Record<string, Partial<RateLimitPolicy>> {\n const open = Number(env.OPEN_RATE_LIMIT_PER_MINUTE);\n const agent = Number(env.OPEN_AGENT_RATE_LIMIT_PER_MINUTE);\n return {\n ...(Number.isFinite(open) && open > 0 ? { \"open.api\": { limit: open } } : {}),\n ...(Number.isFinite(agent) && agent > 0\n ? { \"open.agent\": { limit: agent } }\n : {}),\n };\n}\n","import { createClient } from \"redis\";\n\nexport interface SharedRedis {\n readonly isOpen: boolean;\n connect(): Promise<void>;\n on(event: \"error\", listener: (error: unknown) => void): unknown;\n set(key: string, value: string, options: { NX: true; PX: number }): Promise<string | null>;\n incr(key: string): Promise<number>;\n pExpire(key: string, ms: number): Promise<boolean>;\n eval(script: string, options: { keys: string[]; arguments: string[] }): Promise<unknown>;\n}\n\nconst clientPromises = new Map<string, Promise<SharedRedis>>();\n\n/** Lazily connect a shared Redis client; defaults to `REDIS_URL`. */\nexport async function getSharedRedisClient(\n url: string | undefined = process.env.REDIS_URL?.trim(),\n): Promise<SharedRedis | undefined> {\n if (!url) return undefined;\n let clientPromise = clientPromises.get(url);\n if (!clientPromise) {\n clientPromise = (async () => {\n const client = createClient({ url }) as unknown as SharedRedis;\n client.on(\"error\", () => undefined);\n await client.connect();\n return client;\n })();\n clientPromises.set(url, clientPromise);\n }\n try {\n const client = await clientPromise;\n return client.isOpen ? client : undefined;\n } catch {\n if (clientPromises.get(url) === clientPromise) clientPromises.delete(url);\n return undefined;\n }\n}\n\n/** Atomically claim a dedup key. `undefined` means Redis is unavailable. */\nexport async function claimDedupKey(key: string, ttlMs: number): Promise<boolean | undefined> {\n try {\n const client = await getSharedRedisClient();\n if (!client) return undefined;\n const result = await client.set(key, \"1\", { NX: true, PX: ttlMs });\n return result === \"OK\";\n } catch {\n return undefined;\n }\n}\n\n/** Atomically increment a rate counter. `undefined` means Redis is unavailable. */\nexport async function incrementRateCounter(key: string, windowMs: number): Promise<number | undefined> {\n try {\n const client = await getSharedRedisClient();\n if (!client) return undefined;\n const count = await client.incr(key);\n if (count === 1) await client.pExpire(key, windowMs);\n return count;\n } catch {\n return undefined;\n }\n}\n","import { getSharedRedisClient } from \"../../router/middlewares/channelSharedState\";\nimport type { RateLimitStore } from \"./types\";\n\n/** Fixed-window counter incremented atomically in Redis. */\nconst INCREMENT_SCRIPT = `\nlocal count = redis.call(\"INCR\", KEYS[1])\nlocal ttl = redis.call(\"PTTL\", KEYS[1])\nif count == 1 or ttl < 0 then\n redis.call(\"PEXPIRE\", KEYS[1], ARGV[1])\n ttl = tonumber(ARGV[1])\nend\nreturn {count, ttl}\n`;\n\n/**\n * Process-local fixed-window counters.\n *\n * Used directly in single-process deployments and as the fallback when Redis\n * is unavailable. Entries expire lazily and the map is bounded.\n */\nexport class InMemoryRateLimitStore implements RateLimitStore {\n private readonly counters = new Map<string, { count: number; resetAt: number }>();\n\n constructor(\n private readonly options: {\n maxEntries?: number;\n now?: () => number;\n } = {},\n ) {}\n\n async increment(\n key: string,\n windowMs: number,\n ): Promise<{ count: number; ttlMs: number }> {\n const now = this.options.now?.() ?? Date.now();\n const current = this.counters.get(key);\n const next =\n !current || now >= current.resetAt\n ? { count: 1, resetAt: now + windowMs }\n : { count: current.count + 1, resetAt: current.resetAt };\n this.counters.set(key, next);\n this.evict(now);\n return {\n count: next.count,\n ttlMs: Math.max(0, next.resetAt - now),\n };\n }\n\n /** Drop expired entries, then the oldest entries if still over the cap. */\n private evict(now: number): void {\n const max = this.options.maxEntries ?? 10_000;\n if (this.counters.size <= max) return;\n for (const [key, counter] of this.counters) {\n if (counter.resetAt <= now) this.counters.delete(key);\n }\n if (this.counters.size <= max) return;\n // Insertion order approximates reset order for fixed windows; avoid an\n // O(n log n) sort on a hot path under attack.\n let excess = this.counters.size - max;\n for (const key of this.counters.keys()) {\n if (excess <= 0) break;\n this.counters.delete(key);\n excess -= 1;\n }\n }\n}\n\n/** Redis-backed fixed-window counters. Returns `undefined` on any failure. */\nexport class RedisRateLimitStore implements RateLimitStore {\n constructor(\n private readonly options: {\n url?: string;\n onError?: (error: unknown) => void;\n } = {},\n ) {}\n\n async increment(\n key: string,\n windowMs: number,\n ): Promise<{ count: number; ttlMs: number } | undefined> {\n try {\n const client = await getSharedRedisClient(this.options.url);\n if (!client) return undefined;\n const result = await client.eval(INCREMENT_SCRIPT, {\n keys: [key],\n arguments: [String(windowMs)],\n });\n if (!Array.isArray(result) || result.length < 2) return undefined;\n const count = Number(result[0]);\n const ttlMs = Number(result[1]);\n if (!Number.isFinite(count) || count < 1) return undefined;\n return {\n count,\n ttlMs: Number.isFinite(ttlMs) && ttlMs > 0 ? ttlMs : windowMs,\n };\n } catch (error) {\n this.options.onError?.(error);\n return undefined;\n }\n }\n}\n\n/**\n * Use Redis when available, otherwise fall back to the process-local store.\n *\n * A Redis failure is treated as \"unavailable\", not \"unlimited\": the request is\n * still counted in memory.\n */\nexport class HybridRateLimitStore implements RateLimitStore {\n private readonly memory: InMemoryRateLimitStore;\n\n constructor(\n private readonly redis: RateLimitStore | undefined,\n options: { maxEntries?: number; now?: () => number } = {},\n ) {\n this.memory = new InMemoryRateLimitStore(options);\n }\n\n async increment(\n key: string,\n windowMs: number,\n ): Promise<{ count: number; ttlMs: number }> {\n if (this.redis) {\n const shared = await this.redis.increment(key, windowMs);\n if (shared) return shared;\n }\n return this.memory.increment(key, windowMs);\n }\n}\n"],"mappings":";AAAA,SAAS,kBAAkB;;;ACQpB,IAAM,8BAA+D;AAAA,EAC1E,qBAAqB;AAAA,IACnB,OAAO;AAAA,IACP,UAAU;AAAA,IACV,YAAY,CAAC,SAAS,IAAI;AAAA,IAC1B,iBAAiB,EAAE,IAAI,GAAG;AAAA,EAC5B;AAAA,EACA,wBAAwB;AAAA,IACtB,OAAO;AAAA,IACP,UAAU;AAAA,IACV,YAAY,CAAC,SAAS,IAAI;AAAA,EAC5B;AAAA,EACA,2BAA2B;AAAA,IACzB,OAAO;AAAA,IACP,UAAU;AAAA,IACV,YAAY,CAAC,IAAI;AAAA,EACnB;AAAA,EACA,cAAc;AAAA,IACZ,OAAO;AAAA,IACP,UAAU;AAAA,IACV,YAAY,CAAC,IAAI;AAAA,EACnB;AAAA,EACA,mBAAmB;AAAA,IACjB,OAAO;AAAA,IACP,UAAU;AAAA,IACV,YAAY,CAAC,IAAI;AAAA,EACnB;AAAA,EACA,sBAAsB;AAAA,IACpB,OAAO;AAAA,IACP,UAAU;AAAA,IACV,YAAY,CAAC,IAAI;AAAA,EACnB;AAAA,EACA,sBAAsB;AAAA,IACpB,OAAO;AAAA,IACP,UAAU;AAAA,IACV,YAAY,CAAC,IAAI;AAAA,EACnB;AAAA,EACA,uBAAuB;AAAA,IACrB,OAAO;AAAA,IACP,UAAU;AAAA,IACV,YAAY,CAAC,IAAI;AAAA,EACnB;AAAA,EACA,qBAAqB;AAAA,IACnB,OAAO;AAAA,IACP,UAAU;AAAA,IACV,YAAY,CAAC,IAAI;AAAA,EACnB;AAAA,EACA,iBAAiB;AAAA,IACf,OAAO;AAAA,IACP,UAAU;AAAA,IACV,YAAY,CAAC,IAAI;AAAA,EACnB;AAAA,EACA,8BAA8B;AAAA,IAC5B,OAAO;AAAA,IACP,UAAU;AAAA,IACV,YAAY,CAAC,IAAI;AAAA,EACnB;AAAA,EACA,sBAAsB;AAAA,IACpB,OAAO;AAAA,IACP,UAAU;AAAA,IACV,YAAY,CAAC,QAAQ,IAAI;AAAA,EAC3B;AAAA,EACA,YAAY;AAAA,IACV,OAAO;AAAA,IACP,UAAU;AAAA,IACV,YAAY,CAAC,YAAY;AAAA,EAC3B;AAAA,EACA,cAAc;AAAA,IACZ,OAAO;AAAA,IACP,UAAU;AAAA,IACV,YAAY,CAAC,YAAY;AAAA,EAC3B;AAAA,EACA,eAAe;AAAA,IACb,OAAO;AAAA,IACP,UAAU;AAAA,IACV,YAAY,CAAC,OAAO,IAAI;AAAA,IACxB,iBAAiB,EAAE,IAAI,IAAI;AAAA,EAC7B;AACF;AASO,SAAS,4BACd,MAAyB,QAAQ,KACS;AAC1C,QAAM,OAAO,OAAO,IAAI,0BAA0B;AAClD,QAAM,QAAQ,OAAO,IAAI,gCAAgC;AACzD,SAAO;AAAA,IACL,GAAI,OAAO,SAAS,IAAI,KAAK,OAAO,IAAI,EAAE,YAAY,EAAE,OAAO,KAAK,EAAE,IAAI,CAAC;AAAA,IAC3E,GAAI,OAAO,SAAS,KAAK,KAAK,QAAQ,IAClC,EAAE,cAAc,EAAE,OAAO,MAAM,EAAE,IACjC,CAAC;AAAA,EACP;AACF;;;AC1GA,SAAS,oBAAoB;AAY7B,IAAM,iBAAiB,oBAAI,IAAkC;AAG7D,eAAsB,qBACpB,MAA0B,QAAQ,IAAI,WAAW,KAAK,GACpB;AAClC,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI,gBAAgB,eAAe,IAAI,GAAG;AAC1C,MAAI,CAAC,eAAe;AAClB,qBAAiB,YAAY;AAC3B,YAAM,SAAS,aAAa,EAAE,IAAI,CAAC;AACnC,aAAO,GAAG,SAAS,MAAM,MAAS;AAClC,YAAM,OAAO,QAAQ;AACrB,aAAO;AAAA,IACT,GAAG;AACH,mBAAe,IAAI,KAAK,aAAa;AAAA,EACvC;AACA,MAAI;AACF,UAAM,SAAS,MAAM;AACrB,WAAO,OAAO,SAAS,SAAS;AAAA,EAClC,QAAQ;AACN,QAAI,eAAe,IAAI,GAAG,MAAM,cAAe,gBAAe,OAAO,GAAG;AACxE,WAAO;AAAA,EACT;AACF;AAGA,eAAsB,cAAc,KAAa,OAA6C;AAC5F,MAAI;AACF,UAAM,SAAS,MAAM,qBAAqB;AAC1C,QAAI,CAAC,OAAQ,QAAO;AACpB,UAAM,SAAS,MAAM,OAAO,IAAI,KAAK,KAAK,EAAE,IAAI,MAAM,IAAI,MAAM,CAAC;AACjE,WAAO,WAAW;AAAA,EACpB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGA,eAAsB,qBAAqB,KAAa,UAA+C;AACrG,MAAI;AACF,UAAM,SAAS,MAAM,qBAAqB;AAC1C,QAAI,CAAC,OAAQ,QAAO;AACpB,UAAM,QAAQ,MAAM,OAAO,KAAK,GAAG;AACnC,QAAI,UAAU,EAAG,OAAM,OAAO,QAAQ,KAAK,QAAQ;AACnD,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;ACzDA,IAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBlB,IAAM,yBAAN,MAAuD;AAAA,EAG5D,YACmB,UAGb,CAAC,GACL;AAJiB;AAHnB,SAAiB,WAAW,oBAAI,IAAgD;AAAA,EAO7E;AAAA,EAEH,MAAM,UACJ,KACA,UAC2C;AAC3C,UAAM,MAAM,KAAK,QAAQ,MAAM,KAAK,KAAK,IAAI;AAC7C,UAAM,UAAU,KAAK,SAAS,IAAI,GAAG;AACrC,UAAM,OACJ,CAAC,WAAW,OAAO,QAAQ,UACvB,EAAE,OAAO,GAAG,SAAS,MAAM,SAAS,IACpC,EAAE,OAAO,QAAQ,QAAQ,GAAG,SAAS,QAAQ,QAAQ;AAC3D,SAAK,SAAS,IAAI,KAAK,IAAI;AAC3B,SAAK,MAAM,GAAG;AACd,WAAO;AAAA,MACL,OAAO,KAAK;AAAA,MACZ,OAAO,KAAK,IAAI,GAAG,KAAK,UAAU,GAAG;AAAA,IACvC;AAAA,EACF;AAAA;AAAA,EAGQ,MAAM,KAAmB;AAC/B,UAAM,MAAM,KAAK,QAAQ,cAAc;AACvC,QAAI,KAAK,SAAS,QAAQ,IAAK;AAC/B,eAAW,CAAC,KAAK,OAAO,KAAK,KAAK,UAAU;AAC1C,UAAI,QAAQ,WAAW,IAAK,MAAK,SAAS,OAAO,GAAG;AAAA,IACtD;AACA,QAAI,KAAK,SAAS,QAAQ,IAAK;AAG/B,QAAI,SAAS,KAAK,SAAS,OAAO;AAClC,eAAW,OAAO,KAAK,SAAS,KAAK,GAAG;AACtC,UAAI,UAAU,EAAG;AACjB,WAAK,SAAS,OAAO,GAAG;AACxB,gBAAU;AAAA,IACZ;AAAA,EACF;AACF;AAGO,IAAM,sBAAN,MAAoD;AAAA,EACzD,YACmB,UAGb,CAAC,GACL;AAJiB;AAAA,EAIhB;AAAA,EAEH,MAAM,UACJ,KACA,UACuD;AACvD,QAAI;AACF,YAAM,SAAS,MAAM,qBAAqB,KAAK,QAAQ,GAAG;AAC1D,UAAI,CAAC,OAAQ,QAAO;AACpB,YAAM,SAAS,MAAM,OAAO,KAAK,kBAAkB;AAAA,QACjD,MAAM,CAAC,GAAG;AAAA,QACV,WAAW,CAAC,OAAO,QAAQ,CAAC;AAAA,MAC9B,CAAC;AACD,UAAI,CAAC,MAAM,QAAQ,MAAM,KAAK,OAAO,SAAS,EAAG,QAAO;AACxD,YAAM,QAAQ,OAAO,OAAO,CAAC,CAAC;AAC9B,YAAM,QAAQ,OAAO,OAAO,CAAC,CAAC;AAC9B,UAAI,CAAC,OAAO,SAAS,KAAK,KAAK,QAAQ,EAAG,QAAO;AACjD,aAAO;AAAA,QACL;AAAA,QACA,OAAO,OAAO,SAAS,KAAK,KAAK,QAAQ,IAAI,QAAQ;AAAA,MACvD;AAAA,IACF,SAAS,OAAO;AACd,WAAK,QAAQ,UAAU,KAAK;AAC5B,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAQO,IAAM,uBAAN,MAAqD;AAAA,EAG1D,YACmB,OACjB,UAAuD,CAAC,GACxD;AAFiB;AAGjB,SAAK,SAAS,IAAI,uBAAuB,OAAO;AAAA,EAClD;AAAA,EAEA,MAAM,UACJ,KACA,UAC2C;AAC3C,QAAI,KAAK,OAAO;AACd,YAAM,SAAS,MAAM,KAAK,MAAM,UAAU,KAAK,QAAQ;AACvD,UAAI,OAAQ,QAAO;AAAA,IACrB;AACA,WAAO,KAAK,OAAO,UAAU,KAAK,QAAQ;AAAA,EAC5C;AACF;;;AH9GA,IAAM,aAA8C,oBAAI,IAAI;AAAA,EAC1D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AACD,IAAM,sBAAsB;AAG5B,SAAS,cAAc,OAAuB;AAC5C,SAAO,WAAW,QAAQ,EAAE,OAAO,KAAK,EAAE,OAAO,KAAK;AACxD;AAGA,SAAS,gBACP,MACA,OACA,MACA,SAAgC,SACH;AAC7B,QAAM,QAAQ,MAAM,SAAS,MAAM;AACnC,QAAM,WAAW,MAAM,YAAY,MAAM;AACzC,QAAM,aAAa,MAAM,cAAc,MAAM;AAC7C,MACE,OAAO,UAAU,YACjB,CAAC,OAAO,SAAS,KAAK,KACtB,SAAS,KACT,OAAO,aAAa,YACpB,CAAC,OAAO,SAAS,QAAQ,KACzB,YAAY,KACZ,CAAC,MAAM,QAAQ,UAAU,KACzB,WAAW,WAAW,KACtB,WAAW,KAAK,CAAC,cAAc,CAAC,WAAW,IAAI,SAAS,CAAC,GACzD;AACA,WAAO,KAAK,KAAK,UAAU;AAAA,MACzB,OAAO;AAAA,MACP,QAAQ;AAAA,IACV,CAAC,CAAC;AACF,WAAO,OAAO,EAAE,GAAG,MAAM,YAAY,CAAC,GAAG,KAAK,UAAU,EAAE,IAAI;AAAA,EAChE;AACA,QAAM,kBAA+D;AAAA,IACnE,GAAI,MAAM,mBAAmB,CAAC;AAAA,EAChC;AACA,QAAM,qBAAsB,MAAwC;AACpE,MAAI,uBAAuB,QAAW;AACpC,QACE,OAAO,uBAAuB,YAC9B,uBAAuB,QACvB,MAAM,QAAQ,kBAAkB,GAChC;AACA,aAAO,KAAK,KAAK,UAAU;AAAA,QACzB,OAAO;AAAA,QACP,QAAQ;AAAA,MACV,CAAC,CAAC;AAAA,IACJ,OAAO;AACL,iBAAW,CAAC,WAAW,GAAG,KAAK,OAAO,QAAQ,kBAAkB,GAAG;AACjE,YACE,CAAC,WAAW,IAAI,SAA+B,KAC/C,OAAO,QAAQ,YACf,CAAC,OAAO,SAAS,GAAG,KACpB,OAAO,GACP;AACA,iBAAO,KAAK,KAAK,UAAU;AAAA,YACzB,OAAO;AAAA,YACP,QAAQ;AAAA,YACR;AAAA,UACF,CAAC,CAAC;AACF;AAAA,QACF;AACA,wBAAgB,SAA+B,IAAI,KAAK,MAAM,GAAG;AAAA,MACnE;AAAA,IACF;AAAA,EACF;AACA,SAAO;AAAA,IACL,OAAO,KAAK,MAAM,KAAK;AAAA,IACvB,UAAU,KAAK,MAAM,QAAQ;AAAA,IAC7B,YAAY,CAAC,GAAG,UAAU;AAAA,IAC1B,GAAI,OAAO,KAAK,eAAe,EAAE,SAAS,IAAI,EAAE,gBAAgB,IAAI,CAAC;AAAA,IACrE,GAAI,MAAM,YAAY,SAClB,EAAE,SAAS,MAAM,QAAQ,IACzB,MAAM,YAAY,SAChB,EAAE,SAAS,KAAK,QAAQ,IACxB,CAAC;AAAA,EACT;AACF;AAGO,SAAS,0BACd,KACA,SAAgC,SACU;AAC1C,MAAI,CAAC,OAAO,IAAI,KAAK,MAAM,GAAI,QAAO,CAAC;AACvC,MAAI;AACF,UAAM,SAAkB,KAAK,MAAM,GAAG;AACtC,QAAI,OAAO,WAAW,YAAY,WAAW,QAAQ,MAAM,QAAQ,MAAM,GAAG;AAC1E,YAAM,IAAI,MAAM,oBAAoB;AAAA,IACtC;AACA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,WAAO,KAAK,KAAK,UAAU;AAAA,MACzB,OAAO;AAAA,MACP,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,IAC9D,CAAC,CAAC;AACF,WAAO,CAAC;AAAA,EACV;AACF;AAGO,SAAS,uBACd,SAA0B,CAAC,GAC3B,SAAgC,SACC;AACjC,QAAM,SAA0C,CAAC;AACjD,aAAW,CAAC,MAAM,MAAM,KAAK,OAAO,QAAQ,2BAA2B,GAAG;AACxE,WAAO,IAAI,IAAI,EAAE,GAAG,QAAQ,YAAY,CAAC,GAAG,OAAO,UAAU,EAAE;AAAA,EACjE;AACA,QAAM,YAAY;AAAA,IAChB,4BAA4B,QAAQ,GAAG;AAAA,IACvC,0BAA0B,QAAQ,IAAI,2BAA2B,MAAM;AAAA,IACvE,OAAO,YAAY,CAAC;AAAA,EACtB;AACA,aAAW,SAAS,WAAW;AAC7B,eAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AACjD,YAAM,SAAS,gBAAgB,MAAM,OAAO,OAAO,IAAI,GAAG,MAAM;AAChE,UAAI,OAAQ,QAAO,IAAI,IAAI;AAAA,IAC7B;AAAA,EACF;AACA,SAAO;AACT;AAUO,SAAS,2BACd,UAC0C;AAC1C,QAAM,WAAW,SAAS,YAAY;AACtC,QAAM,UAAU,SAAS;AACzB,QAAM,aAAa,SAAS,UAAU;AACtC,QAAM,YAAsD,CAAC;AAE7D,MAAI,QAAQ,qBAAqB,YAAY;AAC3C,cAAU,UAAU,IAAI,EAAE,OAAO,WAAW,iBAAiB;AAAA,EAC/D;AACA,MAAI,QAAQ,uBAAuB,YAAY;AAC7C,cAAU,YAAY,IAAI,EAAE,OAAO,WAAW,mBAAmB;AAAA,EACnE;AAEA,QAAM,MAAgC,CAAC;AACvC,MAAI,QAAQ,wBAAwB,YAAY;AAC9C,QAAI,QAAQ,WAAW;AAAA,EACzB;AACA,MAAI,QAAQ,0BAA0B,YAAY;AAChD,QAAI,kBAAkB,EAAE,IAAI,WAAW,sBAAsB;AAAA,EAC/D;AACA,MAAI,OAAO,KAAK,GAAG,EAAE,SAAS,EAAG,WAAU,aAAa,IAAI;AAE5D,SAAO;AACT;AASA,SAAS,qBACP,MACA,WAC0C;AAC1C,QAAM,SAAmD,EAAE,GAAG,KAAK;AACnE,aAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,SAAS,GAAG;AACrD,UAAM,WAAW,OAAO,IAAI;AAC5B,QAAI,CAAC,UAAU;AACb,aAAO,IAAI,IAAI,EAAE,GAAG,MAAM;AAC1B;AAAA,IACF;AACA,UAAM,kBAAkB;AAAA,MACtB,GAAI,SAAS,mBAAmB,CAAC;AAAA,MACjC,GAAI,MAAM,mBAAmB,CAAC;AAAA,IAChC;AACA,WAAO,IAAI,IAAI;AAAA,MACb,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAI,OAAO,KAAK,eAAe,EAAE,SAAS,IAAI,EAAE,gBAAgB,IAAI,CAAC;AAAA,IACvE;AAAA,EACF;AACA,SAAO;AACT;AAwBO,IAAM,mBAAN,MAAuB;AAAA,EAG5B,YAAoB,SAAkC;AAAlC;AAFpB,SAAiB,iBAAiB,oBAAI,IAAY;AAAA,EAEK;AAAA;AAAA,EAGvD,eAAe,UAAiD;AAC9D,SAAK,QAAQ,WAAW;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,uBACE,WACM;AACN,SAAK,QAAQ,WAAW;AAAA,MACtB;AAAA,QACE,UAAU;AAAA,UACR,KAAK,QAAQ,uBAAuB,CAAC;AAAA,UACrC;AAAA,QACF;AAAA,MACF;AAAA,MACA,KAAK,QAAQ;AAAA,IACf;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,QACJ,YACA,QAC4B;AAC5B,QAAI,CAAC,KAAK,QAAQ,SAAS;AACzB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,WAAW;AAAA,QACX,mBAAmB;AAAA,MACrB;AAAA,IACF;AACA,UAAM,SAAS,KAAK,QAAQ,SAAS,UAAU;AAC/C,QAAI,CAAC,UAAU,CAAC,KAAK,eAAe,IAAI,UAAU,GAAG;AACnD,WAAK,eAAe,IAAI,UAAU;AAClC,WAAK,QAAQ,QAAQ,KAAK,KAAK,UAAU;AAAA,QACvC,OAAO;AAAA,QACP,QAAQ;AAAA,MACV,CAAC,CAAC;AAAA,IACJ;AACA,QAAI,CAAC,UAAU,OAAO,YAAY,OAAO;AACvC,aAAO;AAAA,QACL,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,OAAO,QAAQ,SAAS;AAAA,QACxB,WAAW,QAAQ,SAAS;AAAA,QAC5B,mBAAmB;AAAA,MACrB;AAAA,IACF;AAEA,QAAI,YAAY,OAAO;AACvB,eAAW,aAAa,OAAO,YAAY;AACzC,YAAM,MAAM,OAAO,SAAS;AAC5B,UAAI,OAAO,QAAQ,YAAY,QAAQ,GAAI;AAC3C,YAAM,MAAM,oBAAoB,UAAU,IAAI,SAAS,IAAI,cAAc,GAAG,CAAC;AAC7E,YAAM,SAAS,MAAM,KAAK,QAAQ,MAAM,UAAU,KAAK,OAAO,QAAQ;AACtE,UAAI,CAAC,OAAQ;AACb,YAAM,iBAAiB,OAAO,kBAAkB,SAAS,KAAK,OAAO;AACrE,kBAAY,KAAK,IAAI,WAAW,iBAAiB,OAAO,KAAK;AAC7D,UAAI,OAAO,QAAQ,gBAAgB;AACjC,eAAO;AAAA,UACL,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,WAAW;AAAA,UACX,mBAAmB,KAAK,IAAI,GAAG,KAAK,KAAK,OAAO,QAAQ,GAAI,CAAC;AAAA,UAC7D,mBAAmB;AAAA,QACrB;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,OAAO,OAAO;AAAA,MACd,WAAW,KAAK,IAAI,GAAG,SAAS;AAAA,MAChC,mBAAmB;AAAA,IACrB;AAAA,EACF;AACF;AAKO,SAAS,uBACd,SAA0B,CAAC,GAC3B,SAAgC,SACd;AAClB,QAAM,WAAW,OAAO,YAAY,QAAQ,IAAI,WAAW,KAAK;AAChE,QAAM,QAAQ,WACV,IAAI,oBAAoB;AAAA,IACtB,KAAK;AAAA,IACL,SAAS,CAAC,UAAU,OAAO,KAAK,KAAK,UAAU;AAAA,MAC7C,OAAO;AAAA,MACP,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,IAC9D,CAAC,CAAC;AAAA,EACJ,CAAC,IACD;AACJ,SAAO,IAAI,iBAAiB;AAAA,IAC1B,OAAO,IAAI,qBAAqB,OAAO;AAAA,MACrC,YAAY,OAAO,sBAAsB;AAAA,IAC3C,CAAC;AAAA,IACD,UAAU,uBAAuB,QAAQ,MAAM;AAAA,IAC/C,qBAAqB,OAAO,YAAY,CAAC;AAAA,IACzC,SACE,OAAO,WACJ,QAAQ,IAAI,8BAA8B;AAAA,IAC/C;AAAA,EACF,CAAC;AACH;AAEA,IAAM,kBAAkB,IAAI,iBAAiB;AAAA,EAC3C,OAAO,IAAI,qBAAqB,MAAS;AAAA,EACzC,UAAU,CAAC;AAAA,EACX,SAAS;AACX,CAAC;AACD,IAAI;AAGG,SAAS,oBAAoB,SAAiC;AACnE,mBAAiB;AACnB;AAcO,SAAS,sBAAwC;AACtD,SAAO,kBAAkB;AAC3B;","names":[]}
|
|
@@ -8,7 +8,10 @@ function getRunCancelRouter() {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
// src/services/run-task/runTaskQuota.ts
|
|
11
|
-
function resolveRunTaskMaxActivePerTenant(env = process.env) {
|
|
11
|
+
function resolveRunTaskMaxActivePerTenant(env = process.env, settings) {
|
|
12
|
+
const platform = settings?.getRateLimits().maxActiveRunTasksPerTenant;
|
|
13
|
+
if (platform === null) return void 0;
|
|
14
|
+
if (platform !== void 0) return platform;
|
|
12
15
|
return resolvePositiveInteger(env.RUN_TASK_MAX_ACTIVE_PER_TENANT);
|
|
13
16
|
}
|
|
14
17
|
function resolveRunTaskMaxRunningPerTenant(env = process.env) {
|
|
@@ -52,6 +55,15 @@ async function wakeRunTaskQueue() {
|
|
|
52
55
|
}
|
|
53
56
|
}
|
|
54
57
|
|
|
58
|
+
// src/services/settings/settingsRuntime.ts
|
|
59
|
+
var current2;
|
|
60
|
+
function setPlatformSettingsProvider(provider) {
|
|
61
|
+
current2 = provider;
|
|
62
|
+
}
|
|
63
|
+
function getPlatformSettingsProvider() {
|
|
64
|
+
return current2;
|
|
65
|
+
}
|
|
66
|
+
|
|
55
67
|
// src/services/workspace-file-service.ts
|
|
56
68
|
import * as fs2 from "fs/promises";
|
|
57
69
|
import * as path2 from "path";
|
|
@@ -239,6 +251,8 @@ export {
|
|
|
239
251
|
setRunTaskWakeStatsSource,
|
|
240
252
|
getRunTaskWakeStatsSource,
|
|
241
253
|
wakeRunTaskQueue,
|
|
254
|
+
setPlatformSettingsProvider,
|
|
255
|
+
getPlatformSettingsProvider,
|
|
242
256
|
PathOutsideRootError,
|
|
243
257
|
isPathWithinRoot,
|
|
244
258
|
resolvePathWithinRoot,
|
|
@@ -248,4 +262,4 @@ export {
|
|
|
248
262
|
saveProjectFile,
|
|
249
263
|
formatFileRefsSection
|
|
250
264
|
};
|
|
251
|
-
//# sourceMappingURL=chunk-
|
|
265
|
+
//# sourceMappingURL=chunk-67CDUQM3.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/services/run-cancel/runCancelRuntime.ts","../src/services/run-task/runTaskQuota.ts","../src/services/run-task/runTaskRuntimeRegistry.ts","../src/services/settings/settingsRuntime.ts","../src/services/workspace-file-service.ts","../src/utils/path-containment.ts","../src/services/files/task-file-refs.ts"],"sourcesContent":["import type { RunCancelRouter } from \"./RunCancelRouter\";\n\nlet runCancelRouter: RunCancelRouter | undefined;\n\n/**\n * Register the process-wide run cancellation router.\n *\n * @param router - Router available to HTTP controllers, or `undefined` to\n * clear it during shutdown.\n *\n * @remarks\n * The router is only constructed when the gateway uses the Redis chunk source,\n * a Redis URL, and a durable run ledger. Controllers treat a missing router as\n * cancellation being unavailable rather than aborting locally.\n */\nexport function setRunCancelRouter(router?: RunCancelRouter): void {\n runCancelRouter = router;\n}\n\n/**\n * Return the registered run cancellation router, if any.\n *\n * @returns The process-wide router, or `undefined` when cancellation routing\n * is not configured for this replica.\n */\nexport function getRunCancelRouter(): RunCancelRouter | undefined {\n return runCancelRouter;\n}\n\n/**\n * Clear the process-wide run cancellation router between tests.\n *\n * @remarks Test-only helper; production code clears the router through\n * {@link setRunCancelRouter} during shutdown.\n */\nexport function resetRunCancelRouterForTests(): void {\n runCancelRouter = undefined;\n}\n","import type { PlatformSettingsProvider } from \"@axiom-lattice/protocols\";\n\n/**\n * Resolves the optional per-tenant run-queue admission limit.\n *\n * @param env Environment source; defaults to `process.env`.\n * @param settings Optional platform settings provider; its cached snapshot\n * takes precedence over the environment.\n * @returns The configured positive safe integer, or `undefined` when unlimited.\n * @remarks Unset, blank, zero, negative, fractional and unsafe values all mean\n * unlimited. An explicit platform `null` means unlimited and overrides the\n * environment. This is admission control (pending + running `run_api` rows per\n * tenant); it is not fair scheduling or per-tenant execution concurrency.\n */\nexport function resolveRunTaskMaxActivePerTenant(\n env: NodeJS.ProcessEnv = process.env,\n settings?: Pick<PlatformSettingsProvider, \"getRateLimits\">,\n): number | undefined {\n const platform = settings?.getRateLimits().maxActiveRunTasksPerTenant;\n if (platform === null) return undefined;\n if (platform !== undefined) return platform;\n return resolvePositiveInteger(env.RUN_TASK_MAX_ACTIVE_PER_TENANT);\n}\n\n/**\n * Resolves the optional per-tenant execution concurrency cap.\n *\n * @param env Environment source; defaults to `process.env`.\n * @returns The configured positive safe integer, or `undefined` when unlimited.\n * @remarks Unset, blank, zero, negative, fractional and unsafe values all mean\n * unlimited. This caps `running` `run_api` rows per tenant; it does not admit\n * or reject new work (that is {@link resolveRunTaskMaxActivePerTenant}) and it\n * is not strict round-robin fairness across tenants.\n */\nexport function resolveRunTaskMaxRunningPerTenant(\n env: NodeJS.ProcessEnv = process.env,\n): number | undefined {\n return resolvePositiveInteger(env.RUN_TASK_MAX_RUNNING_PER_TENANT);\n}\n\nfunction resolvePositiveInteger(raw: string | undefined): number | undefined {\n if (raw === undefined) return undefined;\n const parsed = Number(raw);\n return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : undefined;\n}\n","import type {\n RunTaskWakePublisher,\n RunTaskWakeStats,\n} from \"./RedisRunTaskWake\";\nimport type { RunTaskRuntime } from \"./RunTaskRuntime\";\n\n/** Structural source of wake transport posture for process metrics. */\nexport interface RunTaskWakeStatsSource {\n /** Returns a point-in-time wake posture snapshot. */\n stats(): RunTaskWakeStats;\n}\n\nlet current: RunTaskRuntime | undefined;\nlet publisher: RunTaskWakePublisher | undefined;\nlet wakeStatsSource: RunTaskWakeStatsSource | undefined;\n\n/**\n * Registers the process-local run task runtime.\n *\n * @param runtime The running runtime, or `undefined` on shutdown.\n * @remarks The registry is intentionally process-local: it can only wake the\n * worker in this process. Other replicas still discover pending runs through DB\n * polling, which remains authoritative.\n */\nexport function setRunTaskRuntime(runtime?: RunTaskRuntime): void {\n current = runtime;\n}\n\n/**\n * Returns the process-local run task runtime, when this replica runs one.\n *\n * @returns The registered runtime, or `undefined`.\n */\nexport function getRunTaskRuntime(): RunTaskRuntime | undefined {\n return current;\n}\n\n/**\n * Registers the best-effort cross-replica wake publisher.\n *\n * @param next The Redis-backed publisher, or `undefined` on shutdown.\n * @remarks API-only replicas may register a publisher without subscribing. A\n * missing publisher leaves the process-local wake (and DB polling) intact.\n */\nexport function setRunTaskWakePublisher(\n next?: RunTaskWakePublisher,\n): void {\n publisher = next;\n}\n\n/**\n * Registers the process-local wake transport used for metrics.\n *\n * @param next The wake transport, or `undefined` on shutdown.\n * @remarks Kept separate from the publish registry so API-only replicas can\n * expose publisher connection posture even without a local worker.\n */\nexport function setRunTaskWakeStatsSource(\n next?: RunTaskWakeStatsSource,\n): void {\n wakeStatsSource = next;\n}\n\n/**\n * Returns the process-local wake transport registered for metrics.\n *\n * @returns The wake stats source, or `undefined` when no Redis wake exists.\n */\nexport function getRunTaskWakeStatsSource(): RunTaskWakeStatsSource | undefined {\n return wakeStatsSource;\n}\n\n/**\n * Best-effort wake for newly created pending runs.\n *\n * @returns A promise that resolves after the local wake attempt; the Redis\n * publish continues in the background.\n * @remarks Never authoritative and never throws. The local runtime is woken\n * first so a hung or failed publisher cannot suppress it. The cross-replica\n * publish is fire-and-forget and wakes other worker replicas; this replica does\n * not depend on round-tripping its own frame. A missing runtime, missing\n * publisher, or transport failure leaves the durable run to polling.\n */\nexport async function wakeRunTaskQueue(): Promise<void> {\n try {\n await current?.wake();\n } catch {\n // Polling is the durable fallback; wake failures are best-effort.\n }\n const next = publisher;\n if (!next) return;\n try {\n void next.publish().catch(() => undefined);\n } catch {\n // Polling is the durable fallback; wake failures are best-effort.\n }\n}\n","import type { PlatformSettingsProvider } from \"@axiom-lattice/protocols\";\n\n/**\n * Composition-root provider used by legacy gateway route modules.\n *\n * New code should accept an injected {@link PlatformSettingsProvider}; this\n * process-local accessor only bridges modules that are not yet wired through\n * dependency injection.\n */\nlet current: PlatformSettingsProvider | undefined;\n\n/** Installs (or clears) the process-local platform settings provider. */\nexport function setPlatformSettingsProvider(\n provider: PlatformSettingsProvider | undefined,\n): void {\n current = provider;\n}\n\n/** Returns the process-local provider, or undefined before composition. */\nexport function getPlatformSettingsProvider():\n | PlatformSettingsProvider\n | undefined {\n return current;\n}\n","import * as fs from \"fs/promises\";\nimport * as path from \"path\";\nimport { getStoreLattice, getSandBoxManager } from \"@axiom-lattice/core\";\nimport { isPathWithinRoot } from \"../utils/path-containment\";\n\n/** Binary file extensions handled as raw bytes rather than UTF-8 text. */\nconst BINARY_EXTENSIONS = new Set([\n \"pdf\", \"xlsx\", \"xls\", \"docx\", \"doc\", \"pptx\", \"ppt\",\n \"png\", \"jpg\", \"jpeg\", \"gif\", \"bmp\", \"ico\", \"webp\",\n \"mp3\", \"mp4\", \"webm\", \"ogg\", \"wav\", \"avi\", \"mov\",\n \"m4v\", \"mkv\", \"3gp\", \"m4a\", \"aac\", \"flac\", \"opus\", \"oga\", \"wma\", \"aiff\",\n \"zip\", \"tar\", \"gz\", \"rar\", \"7z\",\n]);\n\n/**\n * Whether a filename denotes a binary (non-UTF-8) payload, used to choose the\n * raw-bytes write path in sandbox volume backends.\n */\nexport function isBinaryContentType(filename: string): boolean {\n const ext = filename.split(\".\").pop()?.toLowerCase() || \"\";\n return BINARY_EXTENSIONS.has(ext);\n}\n\n/**\n * Filesystem root directory for a project, mirroring the layout used by the\n * workspace file backend (`/lattice_store/tenants/:tenant/workspaces/:ws/:project`).\n */\nexport function filesystemRootDirectory(\n tenantId: string,\n workspaceId: string,\n projectId: string,\n): string {\n return `/lattice_store/tenants/${tenantId}/workspaces/${workspaceId}/${projectId}`;\n}\n\n/** Raised when a file write request is rejected for path/name safety reasons. */\nexport class ProjectFileValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ProjectFileValidationError\";\n }\n}\n\n/** Parameters for writing a file into a project's workspace storage. */\nexport interface SaveProjectFileParams {\n tenantId: string;\n projectId: string;\n /**\n * Pre-resolved workspace id. When omitted it is derived from the project via\n * the project store (needed by callers that only know the project, e.g. A2A).\n */\n workspaceId?: string;\n name: string;\n bytes: Uint8Array;\n mimeType?: string;\n /** Relative subdirectory under the project root; sandbox defaults to `/project/uploads`. */\n path?: string;\n assistantId?: string;\n}\n\n/** Result of a successful project-file write. */\nexport interface SavedProjectFile {\n /** Storage path usable as a `TaskFileRef.uri` (e.g. `/project/uploads/a.pdf`). */\n uri: string;\n name: string;\n size: number;\n}\n\n/**\n * Persist file bytes into a project's workspace storage and return a URI to it.\n *\n * Supports both sandbox-backed workspaces (delegating to the sandbox/volume\n * upload API) and filesystem-backed workspaces (writing under the project root).\n * The returned URI is the storage path agents reference via {@link TaskFileRef}.\n */\nexport async function saveProjectFile(\n params: SaveProjectFileParams,\n): Promise<SavedProjectFile> {\n const workspaceStore = getStoreLattice(\"default\", \"workspace\").store;\n const projectStore = getStoreLattice(\"default\", \"project\").store;\n\n let workspaceId = params.workspaceId;\n if (!workspaceId) {\n const project = await projectStore.getProjectById(\n params.tenantId,\n params.projectId,\n );\n if (!project) {\n throw new Error(\"Project not found\");\n }\n workspaceId = project.workspaceId;\n }\n if (!workspaceId) throw new Error(\"Workspace not found\");\n\n const workspace = await workspaceStore.getWorkspaceById(\n params.tenantId,\n workspaceId,\n );\n if (!workspace) {\n throw new Error(\"Workspace not found\");\n }\n\n const buffer = Buffer.from(params.bytes);\n const filename = params.name || \"file\";\n const pathValue = params.path;\n\n // Validate the untrusted filename before any path join or disk I/O, equally\n // for sandbox and filesystem branches: reject anything that is not a bare\n // basename on either path flavor (blocks \"../../etc/passwd\", \"a\\\\b\", \"..\").\n if (\n path.basename(filename) !== filename ||\n path.posix.basename(filename) !== filename ||\n filename === \"..\"\n ) {\n throw new ProjectFileValidationError(\"Invalid filename\");\n }\n\n if (workspace.storageType === \"sandbox\") {\n const sandboxManager = getSandBoxManager();\n const volumeConfig = {\n assistant_id: params.assistantId || \"\",\n thread_id: \"\",\n tenantId: params.tenantId,\n workspaceId,\n projectId: params.projectId,\n };\n\n const relativePath = pathValue\n ? path.posix.join(pathValue, filename)\n : path.posix.join(\"/project/uploads\", filename);\n\n const isBinary = isBinaryContentType(filename);\n const volumeBackend = await sandboxManager.getVolumeBackendForPath(\n volumeConfig,\n relativePath,\n );\n if (volumeBackend && !isBinary) {\n await volumeBackend.write(relativePath, buffer.toString(\"utf-8\"));\n } else if (volumeBackend && volumeBackend.writeBinary) {\n await volumeBackend.writeBinary(relativePath, buffer);\n } else {\n const sandbox = await sandboxManager.getSandboxFromConfig(volumeConfig);\n await sandbox.file.uploadFile({ file: relativePath, data: buffer });\n }\n\n return { uri: relativePath, name: filename, size: buffer.length };\n }\n\n const rootDir = filesystemRootDirectory(\n params.tenantId,\n workspaceId,\n params.projectId,\n );\n await fs.mkdir(rootDir, { recursive: true });\n const relativeDirectory = pathValue?.replace(/^[/\\\\]+/, \"\") || \".\";\n const targetDir = path.resolve(rootDir, relativeDirectory);\n if (!isPathWithinRoot(path.resolve(rootDir), targetDir)) {\n throw new ProjectFileValidationError(\n \"Upload path must stay within the project directory\",\n );\n }\n await fs.mkdir(targetDir, { recursive: true });\n\n const [resolvedRoot, resolvedTargetDir] = await Promise.all([\n fs.realpath(rootDir),\n fs.realpath(targetDir),\n ]);\n if (!isPathWithinRoot(resolvedRoot, resolvedTargetDir)) {\n throw new ProjectFileValidationError(\n \"Upload path must stay within the project directory\",\n );\n }\n\n const targetPath = path.join(resolvedTargetDir, filename);\n await fs.writeFile(targetPath, buffer);\n const stat = await fs.stat(targetPath);\n\n const uri = path.posix.join(\"/\", relativeDirectory, filename);\n return { uri, name: filename, size: stat.size };\n}\n","import * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\n\nexport class PathOutsideRootError extends Error {\n constructor(\n public readonly rootPath: string,\n public readonly targetPath: string,\n ) {\n super(`Path is outside the allowed root: ${targetPath}`);\n this.name = \"PathOutsideRootError\";\n }\n}\n\nexport function isPathWithinRoot(rootPath: string, targetPath: string): boolean {\n const relative = path.relative(rootPath, targetPath);\n return (\n relative === \"\" ||\n (relative !== \"..\" &&\n !relative.startsWith(`..${path.sep}`) &&\n !path.isAbsolute(relative))\n );\n}\n\nexport async function resolvePathWithinRoot(\n rootPath: string,\n targetPath: string,\n): Promise<{ rootPath: string; targetPath: string }> {\n const [resolvedRoot, resolvedTarget] = await Promise.all([\n fs.realpath(rootPath),\n fs.realpath(targetPath),\n ]);\n\n if (!isPathWithinRoot(resolvedRoot, resolvedTarget)) {\n throw new PathOutsideRootError(resolvedRoot, resolvedTarget);\n }\n\n return { rootPath: resolvedRoot, targetPath: resolvedTarget };\n}\n","import type { TaskFileRef } from \"@axiom-lattice/protocols\";\n\n/** Render task file references for Agent-visible message text. */\nexport function formatFileRefsSection(refs: TaskFileRef[]): string {\n const lines = refs.map((ref) => {\n const label = ref.name ?? ref.uri;\n const mime = ref.mimeType ? ` (${ref.mimeType})` : \"\";\n return `- ${label}${mime}: ${ref.uri}`;\n });\n return [\"[附件]\", ...lines].join(\"\\n\");\n}\n"],"mappings":"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","names":["current","fs","path","relative","stat"]}
|
|
@@ -2,9 +2,12 @@
|
|
|
2
2
|
import pino from "pino";
|
|
3
3
|
import "pino-pretty";
|
|
4
4
|
import "pino-roll";
|
|
5
|
+
function resolveLegacyLogFile(env = process.env) {
|
|
6
|
+
const file = env.LOG_FILE?.trim();
|
|
7
|
+
return file ? file : null;
|
|
8
|
+
}
|
|
5
9
|
var PinoLoggerFactory = class _PinoLoggerFactory {
|
|
6
10
|
constructor() {
|
|
7
|
-
const isProd = process.env.NODE_ENV === "production";
|
|
8
11
|
const loggerConfig = {
|
|
9
12
|
// 自定义时间戳格式
|
|
10
13
|
timestamp: () => `,"@timestamp":"${(/* @__PURE__ */ new Date()).toISOString()}"`,
|
|
@@ -25,14 +28,15 @@ var PinoLoggerFactory = class _PinoLoggerFactory {
|
|
|
25
28
|
}
|
|
26
29
|
}
|
|
27
30
|
};
|
|
28
|
-
|
|
31
|
+
const logFile = resolveLegacyLogFile(process.env);
|
|
32
|
+
if (logFile) {
|
|
29
33
|
try {
|
|
30
34
|
this.pinoLogger = pino(
|
|
31
35
|
loggerConfig,
|
|
32
36
|
pino.transport({
|
|
33
37
|
target: "pino-roll",
|
|
34
38
|
options: {
|
|
35
|
-
file:
|
|
39
|
+
file: logFile,
|
|
36
40
|
frequency: "daily",
|
|
37
41
|
mkdir: true
|
|
38
42
|
}
|
|
@@ -235,4 +239,4 @@ export {
|
|
|
235
239
|
getQrCode,
|
|
236
240
|
getQrCodeStatus
|
|
237
241
|
};
|
|
238
|
-
//# sourceMappingURL=chunk-
|
|
242
|
+
//# sourceMappingURL=chunk-ELYWN3TJ.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/logger/Logger.ts","../src/channels/wechat/wechat-client.ts"],"sourcesContent":["import pino from \"pino\";\nimport \"pino-pretty\";\nimport \"pino-roll\";\nimport { AsyncLocalStorage } from \"async_hooks\";\n\nexport interface LoggerContext {\n \"x-user-id\"?: string;\n \"x-tenant-id\"?: string;\n \"x-request-id\"?: string;\n \"x-task-id\"?: string;\n \"x-thread-id\"?: string;\n}\n\nexport interface LoggerOptions {\n name?: string;\n serviceName?: string;\n context?: LoggerContext;\n}\n\n/**\n * Resolve the optional file destination for the legacy pino logger.\n *\n * File logging is strictly opt-in through `LOG_FILE`. `NODE_ENV` is ignored so\n * a production process on a read-only filesystem (e.g. Kubernetes) never tries\n * to create a `logs/` directory unless the operator asked for it.\n *\n * @param env Environment variables to read (defaults to `process.env`).\n * @returns The configured log file path, or `null` when file logging is off.\n *\n * @example\n * ```ts\n * resolveLegacyLogFile({ LOG_FILE: \"./logs/app\" }); // → \"./logs/app\"\n * resolveLegacyLogFile({ NODE_ENV: \"production\" }); // → null\n * ```\n */\nexport function resolveLegacyLogFile(\n env: NodeJS.ProcessEnv = process.env\n): string | null {\n const file = env.LOG_FILE?.trim();\n return file ? file : null;\n}\n\n/**\n * 单例的Pino日志工厂类,管理底层pino实例\n */\nclass PinoLoggerFactory {\n private static instance: PinoLoggerFactory;\n private pinoLogger: pino.Logger;\n\n private constructor() {\n const loggerConfig: pino.LoggerOptions = {\n // 自定义时间戳格式\n timestamp: () => `,\"@timestamp\":\"${new Date().toISOString()}\"`,\n\n // 关闭默认的时间戳键\n base: {\n \"@version\": \"1\",\n app_name: \"lattice\",\n service_name: \"lattice/graph-server\",\n thread_name: \"main\",\n logger_name: \"lattice-graph-logger\",\n },\n\n formatters: {\n level: (label, number) => {\n return {\n level: label.toUpperCase(),\n level_value: number * 1000,\n };\n },\n },\n };\n\n // 仅在显式配置 LOG_FILE 时写入文件;默认输出到控制台\n const logFile = resolveLegacyLogFile(process.env);\n if (logFile) {\n try {\n this.pinoLogger = pino(\n loggerConfig,\n pino.transport({\n target: \"pino-roll\",\n options: {\n file: logFile,\n frequency: \"daily\",\n mkdir: true,\n },\n })\n );\n } catch (error) {\n console.error(\n \"无法初始化 pino-roll 日志记录器,回退到控制台日志\",\n error\n );\n // 回退到控制台输出\n this.pinoLogger = pino({\n ...loggerConfig,\n transport: {\n target: \"pino-pretty\",\n options: {\n colorize: true,\n },\n },\n });\n }\n } else {\n // 默认使用格式化输出\n this.pinoLogger = pino({\n ...loggerConfig,\n transport: {\n target: \"pino-pretty\",\n options: {\n colorize: true,\n },\n },\n });\n }\n }\n\n public static getInstance(): PinoLoggerFactory {\n if (!PinoLoggerFactory.instance) {\n PinoLoggerFactory.instance = new PinoLoggerFactory();\n }\n return PinoLoggerFactory.instance;\n }\n\n public getPinoLogger(): pino.Logger {\n return this.pinoLogger;\n }\n}\n\n/**\n * Logger类,可以创建多个实例,每个实例有自己的上下文\n */\nexport class Logger {\n private context: LoggerContext;\n private name: string;\n private serviceName: string;\n\n constructor(options?: LoggerOptions) {\n this.context = options?.context || {};\n this.name = options?.name || \"lattice-graph-logger\";\n this.serviceName = options?.serviceName || \"lattice/graph-server\";\n }\n\n /**\n * 获取合并了上下文的日志对象\n * @param additionalContext 额外的上下文数据\n * @returns 带有上下文的pino日志对象\n */\n private getContextualLogger(additionalContext?: object): pino.Logger {\n const pinoLogger = PinoLoggerFactory.getInstance().getPinoLogger();\n\n // 合并Logger实例的上下文和额外上下文\n const contextObj = {\n \"x-user-id\": this.context[\"x-user-id\"] || \"\",\n \"x-tenant-id\": this.context[\"x-tenant-id\"] || \"\",\n \"x-request-id\": this.context[\"x-request-id\"] || \"\",\n \"x-task-id\": this.context[\"x-task-id\"] || \"\",\n \"x-thread-id\": this.context[\"x-thread-id\"] || \"\",\n service_name: this.serviceName,\n logger_name: this.name,\n ...additionalContext,\n };\n\n // 创建带有上下文的子日志记录器\n return pinoLogger.child(contextObj);\n }\n\n info(msg: string, obj?: object): void {\n this.getContextualLogger(obj).info(msg);\n }\n\n error(msg: string, obj?: object | Error): void {\n this.getContextualLogger(obj).error(msg);\n }\n\n warn(msg: string, obj?: object): void {\n this.getContextualLogger(obj).warn(msg);\n }\n\n debug(msg: string, obj?: object): void {\n this.getContextualLogger(obj).debug(msg);\n }\n\n /**\n * 更新Logger实例的上下文\n */\n updateContext(context: Partial<LoggerContext>): void {\n this.context = {\n ...this.context,\n ...context,\n };\n }\n\n /**\n * 创建一个新的Logger实例,继承当前Logger的上下文\n */\n child(options: Partial<LoggerOptions>): Logger {\n return new Logger({\n name: options.name || this.name,\n serviceName: options.serviceName || this.serviceName,\n context: {\n ...this.context,\n ...options.context,\n },\n });\n }\n}\n","import { randomBytes } from \"crypto\";\n\nconst DEFAULT_BASE_URL = \"https://ilinkai.weixin.qq.com\";\n\nfunction getBaseUrl(): string {\n return process.env.WECHAT_ILINK_BASE_URL || DEFAULT_BASE_URL;\n}\n\nfunction generateWechatUin(): string {\n const buf = Buffer.alloc(4);\n buf.writeUInt32BE(Math.floor(Math.random() * 0xffffffff), 0);\n return buf.toString(\"base64url\");\n}\n\nasync function apiGet<T>(path: string, extraHeaders?: Record<string, string>): Promise<T> {\n const url = `${getBaseUrl()}${path}`;\n const headers: Record<string, string> = { ...extraHeaders };\n const res = await fetch(url, { headers });\n if (!res.ok) {\n throw new Error(`iLink GET ${path} failed: ${res.status} ${res.statusText}`);\n }\n return res.json() as Promise<T>;\n}\n\nasync function apiGetAuth<T>(path: string, botToken: string, extraHeaders?: Record<string, string>): Promise<T> {\n const url = `${getBaseUrl()}${path}`;\n const headers: Record<string, string> = {\n \"AuthorizationType\": \"ilink_bot_token\",\n \"X-WECHAT-UIN\": generateWechatUin(),\n \"Authorization\": `Bearer ${botToken}`,\n ...extraHeaders,\n };\n const res = await fetch(url, { headers });\n if (!res.ok) {\n throw new Error(`iLink GET ${path} failed: ${res.status} ${res.statusText}`);\n }\n return res.json() as Promise<T>;\n}\n\nasync function apiPost<T>(path: string, body: unknown, botToken: string, signal?: AbortSignal): Promise<T> {\n const url = `${getBaseUrl()}${path}`;\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"AuthorizationType\": \"ilink_bot_token\",\n \"X-WECHAT-UIN\": generateWechatUin(),\n \"Authorization\": `Bearer ${botToken}`,\n };\n\n const res = await fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n signal,\n });\n if (!res.ok) {\n throw new Error(`iLink POST ${path} failed: ${res.status} ${res.statusText}`);\n }\n return res.json() as Promise<T>;\n}\n\nexport async function getUpdates(\n botToken: string,\n syncBuffer: string,\n signal?: AbortSignal,\n): Promise<{ msgs: Array<{\n message_type?: number;\n from_user_id?: string;\n client_id?: string;\n item_list?: Array<{ type?: number; text_item?: { text?: string } }>;\n context_token?: string;\n create_time_ms?: number;\n}>; syncBuffer: string }> {\n const data = await apiPost<{\n ret?: number;\n errcode?: number;\n errmsg?: string;\n msgs?: Array<{\n message_type?: number;\n from_user_id?: string;\n client_id?: string;\n item_list?: Array<{ type?: number; text_item?: { text?: string } }>;\n context_token?: string;\n create_time_ms?: number;\n }>;\n get_updates_buf?: string;\n }>(\"/ilink/bot/getupdates\", {\n get_updates_buf: syncBuffer,\n base_info: { channel_version: \"1.0.2\" },\n }, botToken, signal);\n\n // Check API-level error codes (HTTP 200 can still be an error)\n if ((data.ret !== undefined && data.ret !== 0) || (data.errcode !== undefined && data.errcode !== 0)) {\n throw new Error(`iLink getUpdates error: ret=${data.ret} errcode=${data.errcode} errmsg=${data.errmsg ?? \"\"}`);\n }\n\n return {\n msgs: data.msgs ?? [],\n syncBuffer: data.get_updates_buf ?? syncBuffer,\n };\n}\n\nfunction generateClientId(): string {\n return `axiom-wechat:${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nexport async function sendMessage(\n botToken: string,\n toUserId: string,\n text: string,\n contextToken: string,\n): Promise<void> {\n await apiPost<unknown>(\"/ilink/bot/sendmessage\", {\n msg: {\n from_user_id: \"\",\n to_user_id: toUserId,\n client_id: generateClientId(),\n message_type: 2, // MSG_TYPE_BOT\n message_state: 2, // MSG_STATE_FINISH\n item_list: [{ type: 1, text_item: { text } }],\n context_token: contextToken,\n },\n base_info: { channel_version: \"1.0.2\" },\n }, botToken);\n}\n\nexport async function getQrCode(): Promise<{ qrcode: string; qrcodeImgUrl: string }> {\n const data = await apiGet<{ qrcode?: string; qrcode_img_content?: string }>(\n \"/ilink/bot/get_bot_qrcode?bot_type=3\",\n );\n if (!data.qrcode || !data.qrcode_img_content) {\n throw new Error(\"Failed to get WeChat QR code\");\n }\n return { qrcode: data.qrcode, qrcodeImgUrl: data.qrcode_img_content };\n}\n\nexport async function getQrCodeStatus(\n qrcode: string,\n signal?: AbortSignal,\n): Promise<{\n status: \"wait\" | \"scaned\" | \"confirmed\" | \"expired\";\n botToken?: string;\n uin?: string;\n botId?: string;\n baseUrl?: string;\n}> {\n const data = await apiGet<{\n status?: string;\n bot_token?: string;\n ilink_bot_id?: string;\n ilink_user_id?: string;\n baseurl?: string;\n }>(`/ilink/bot/get_qrcode_status?qrcode=${encodeURIComponent(qrcode)}`, {\n \"iLink-App-ClientVersion\": \"1\",\n });\n return {\n status: (data.status as \"wait\" | \"scaned\" | \"confirmed\" | \"expired\") || \"wait\",\n botToken: data.bot_token,\n uin: data.ilink_user_id,\n botId: data.ilink_bot_id,\n baseUrl: data.baseurl,\n };\n}\n"],"mappings":";AAAA,OAAO,UAAU;AACjB,OAAO;AACP,OAAO;AAiCA,SAAS,qBACd,MAAyB,QAAQ,KAClB;AACf,QAAM,OAAO,IAAI,UAAU,KAAK;AAChC,SAAO,OAAO,OAAO;AACvB;AAKA,IAAM,oBAAN,MAAM,mBAAkB;AAAA,EAId,cAAc;AACpB,UAAM,eAAmC;AAAA;AAAA,MAEvC,WAAW,MAAM,mBAAkB,oBAAI,KAAK,GAAE,YAAY,CAAC;AAAA;AAAA,MAG3D,MAAM;AAAA,QACJ,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,cAAc;AAAA,QACd,aAAa;AAAA,QACb,aAAa;AAAA,MACf;AAAA,MAEA,YAAY;AAAA,QACV,OAAO,CAAC,OAAO,WAAW;AACxB,iBAAO;AAAA,YACL,OAAO,MAAM,YAAY;AAAA,YACzB,aAAa,SAAS;AAAA,UACxB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,UAAM,UAAU,qBAAqB,QAAQ,GAAG;AAChD,QAAI,SAAS;AACX,UAAI;AACF,aAAK,aAAa;AAAA,UAChB;AAAA,UACA,KAAK,UAAU;AAAA,YACb,QAAQ;AAAA,YACR,SAAS;AAAA,cACP,MAAM;AAAA,cACN,WAAW;AAAA,cACX,OAAO;AAAA,YACT;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF,SAAS,OAAO;AACd,gBAAQ;AAAA,UACN;AAAA,UACA;AAAA,QACF;AAEA,aAAK,aAAa,KAAK;AAAA,UACrB,GAAG;AAAA,UACH,WAAW;AAAA,YACT,QAAQ;AAAA,YACR,SAAS;AAAA,cACP,UAAU;AAAA,YACZ;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF,OAAO;AAEL,WAAK,aAAa,KAAK;AAAA,QACrB,GAAG;AAAA,QACH,WAAW;AAAA,UACT,QAAQ;AAAA,UACR,SAAS;AAAA,YACP,UAAU;AAAA,UACZ;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,OAAc,cAAiC;AAC7C,QAAI,CAAC,mBAAkB,UAAU;AAC/B,yBAAkB,WAAW,IAAI,mBAAkB;AAAA,IACrD;AACA,WAAO,mBAAkB;AAAA,EAC3B;AAAA,EAEO,gBAA6B;AAClC,WAAO,KAAK;AAAA,EACd;AACF;AAKO,IAAM,SAAN,MAAM,QAAO;AAAA,EAKlB,YAAY,SAAyB;AACnC,SAAK,UAAU,SAAS,WAAW,CAAC;AACpC,SAAK,OAAO,SAAS,QAAQ;AAC7B,SAAK,cAAc,SAAS,eAAe;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,oBAAoB,mBAAyC;AACnE,UAAM,aAAa,kBAAkB,YAAY,EAAE,cAAc;AAGjE,UAAM,aAAa;AAAA,MACjB,aAAa,KAAK,QAAQ,WAAW,KAAK;AAAA,MAC1C,eAAe,KAAK,QAAQ,aAAa,KAAK;AAAA,MAC9C,gBAAgB,KAAK,QAAQ,cAAc,KAAK;AAAA,MAChD,aAAa,KAAK,QAAQ,WAAW,KAAK;AAAA,MAC1C,eAAe,KAAK,QAAQ,aAAa,KAAK;AAAA,MAC9C,cAAc,KAAK;AAAA,MACnB,aAAa,KAAK;AAAA,MAClB,GAAG;AAAA,IACL;AAGA,WAAO,WAAW,MAAM,UAAU;AAAA,EACpC;AAAA,EAEA,KAAK,KAAa,KAAoB;AACpC,SAAK,oBAAoB,GAAG,EAAE,KAAK,GAAG;AAAA,EACxC;AAAA,EAEA,MAAM,KAAa,KAA4B;AAC7C,SAAK,oBAAoB,GAAG,EAAE,MAAM,GAAG;AAAA,EACzC;AAAA,EAEA,KAAK,KAAa,KAAoB;AACpC,SAAK,oBAAoB,GAAG,EAAE,KAAK,GAAG;AAAA,EACxC;AAAA,EAEA,MAAM,KAAa,KAAoB;AACrC,SAAK,oBAAoB,GAAG,EAAE,MAAM,GAAG;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,SAAuC;AACnD,SAAK,UAAU;AAAA,MACb,GAAG,KAAK;AAAA,MACR,GAAG;AAAA,IACL;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAyC;AAC7C,WAAO,IAAI,QAAO;AAAA,MAChB,MAAM,QAAQ,QAAQ,KAAK;AAAA,MAC3B,aAAa,QAAQ,eAAe,KAAK;AAAA,MACzC,SAAS;AAAA,QACP,GAAG,KAAK;AAAA,QACR,GAAG,QAAQ;AAAA,MACb;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;AC7MA,IAAM,mBAAmB;AAEzB,SAAS,aAAqB;AAC5B,SAAO,QAAQ,IAAI,yBAAyB;AAC9C;AAEA,SAAS,oBAA4B;AACnC,QAAM,MAAM,OAAO,MAAM,CAAC;AAC1B,MAAI,cAAc,KAAK,MAAM,KAAK,OAAO,IAAI,UAAU,GAAG,CAAC;AAC3D,SAAO,IAAI,SAAS,WAAW;AACjC;AAEA,eAAe,OAAU,MAAc,cAAmD;AACxF,QAAM,MAAM,GAAG,WAAW,CAAC,GAAG,IAAI;AAClC,QAAM,UAAkC,EAAE,GAAG,aAAa;AAC1D,QAAM,MAAM,MAAM,MAAM,KAAK,EAAE,QAAQ,CAAC;AACxC,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,IAAI,MAAM,aAAa,IAAI,YAAY,IAAI,MAAM,IAAI,IAAI,UAAU,EAAE;AAAA,EAC7E;AACA,SAAO,IAAI,KAAK;AAClB;AAiBA,eAAe,QAAW,MAAc,MAAe,UAAkB,QAAkC;AACzG,QAAM,MAAM,GAAG,WAAW,CAAC,GAAG,IAAI;AAClC,QAAM,UAAkC;AAAA,IACtC,gBAAgB;AAAA,IAChB,qBAAqB;AAAA,IACrB,gBAAgB,kBAAkB;AAAA,IAClC,iBAAiB,UAAU,QAAQ;AAAA,EACrC;AAEA,QAAM,MAAM,MAAM,MAAM,KAAK;AAAA,IAC3B,QAAQ;AAAA,IACR;AAAA,IACA,MAAM,KAAK,UAAU,IAAI;AAAA,IACzB;AAAA,EACF,CAAC;AACD,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,IAAI,MAAM,cAAc,IAAI,YAAY,IAAI,MAAM,IAAI,IAAI,UAAU,EAAE;AAAA,EAC9E;AACA,SAAO,IAAI,KAAK;AAClB;AAEA,eAAsB,WACpB,UACA,YACA,QAQwB;AACxB,QAAM,OAAO,MAAM,QAahB,yBAAyB;AAAA,IAC1B,iBAAiB;AAAA,IACjB,WAAW,EAAE,iBAAiB,QAAQ;AAAA,EACxC,GAAG,UAAU,MAAM;AAGnB,MAAK,KAAK,QAAQ,UAAa,KAAK,QAAQ,KAAO,KAAK,YAAY,UAAa,KAAK,YAAY,GAAI;AACpG,UAAM,IAAI,MAAM,+BAA+B,KAAK,GAAG,YAAY,KAAK,OAAO,WAAW,KAAK,UAAU,EAAE,EAAE;AAAA,EAC/G;AAEA,SAAO;AAAA,IACL,MAAM,KAAK,QAAQ,CAAC;AAAA,IACpB,YAAY,KAAK,mBAAmB;AAAA,EACtC;AACF;AAEA,SAAS,mBAA2B;AAClC,SAAO,gBAAgB,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC;AAC9E;AAEA,eAAsB,YACpB,UACA,UACA,MACA,cACe;AACf,QAAM,QAAiB,0BAA0B;AAAA,IAC/C,KAAK;AAAA,MACH,cAAc;AAAA,MACd,YAAY;AAAA,MACZ,WAAW,iBAAiB;AAAA,MAC5B,cAAc;AAAA;AAAA,MACd,eAAe;AAAA;AAAA,MACf,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,EAAE,KAAK,EAAE,CAAC;AAAA,MAC5C,eAAe;AAAA,IACjB;AAAA,IACA,WAAW,EAAE,iBAAiB,QAAQ;AAAA,EACxC,GAAG,QAAQ;AACb;AAEA,eAAsB,YAA+D;AACnF,QAAM,OAAO,MAAM;AAAA,IACjB;AAAA,EACF;AACA,MAAI,CAAC,KAAK,UAAU,CAAC,KAAK,oBAAoB;AAC5C,UAAM,IAAI,MAAM,8BAA8B;AAAA,EAChD;AACA,SAAO,EAAE,QAAQ,KAAK,QAAQ,cAAc,KAAK,mBAAmB;AACtE;AAEA,eAAsB,gBACpB,QACA,QAOC;AACD,QAAM,OAAO,MAAM,OAMhB,uCAAuC,mBAAmB,MAAM,CAAC,IAAI;AAAA,IACtE,2BAA2B;AAAA,EAC7B,CAAC;AACD,SAAO;AAAA,IACL,QAAS,KAAK,UAA0D;AAAA,IACxE,UAAU,KAAK;AAAA,IACf,KAAK,KAAK;AAAA,IACV,OAAO,KAAK;AAAA,IACZ,SAAS,KAAK;AAAA,EAChB;AACF;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{k as R}from"./embed-page-chunk-
|
|
1
|
+
import{k as R}from"./embed-page-chunk-QRFTGCB2.js";import"./embed-page-chunk-D7YTSCUO.js";import"./embed-page-chunk-ML6AVDQQ.js";import"./embed-page-chunk-ZVTX7OVB.js";import"./embed-page-chunk-RU45VIPM.js";import"./embed-page-chunk-HQLSH3FC.js";import"./embed-page-chunk-5AWYMAAX.js";import"./embed-page-chunk-S4XZPBRM.js";import"./embed-page-chunk-G6UTU7IC.js";import{U as L,h as E}from"./embed-page-chunk-4GCFDWE7.js";import{a as P}from"./embed-page-chunk-5O5IKZOC.js";import"./embed-page-chunk-AFYXBC77.js";import"./embed-page-chunk-TZPX2O54.js";import"./embed-page-chunk-F7ZUYG42.js";import{l as C}from"./embed-page-chunk-5EENS2J7.js";import{a as F}from"./embed-page-chunk-QV7QAJ4N.js";import"./embed-page-chunk-VW3NF5NT.js";import"./embed-page-chunk-Z4Z6VCUZ.js";import"./embed-page-chunk-L7GPZSYD.js";import{Ja as T,W as p,_ as m,aa as b,za as I}from"./embed-page-chunk-BUFWD6SE.js";import{a as O}from"./embed-page-chunk-R5QL57JJ.js";import"./embed-page-chunk-QOWM3LMZ.js";import"./embed-page-chunk-EUOOO2LS.js";import"./embed-page-chunk-5JDQ456X.js";import{f as u}from"./embed-page-chunk-QBTAJ2YI.js";var n=u(O());var t=u(F()),$={component_key:"workspace_assistants",data:{}},J=d=>{let i=d;if(typeof d=="string")try{i=JSON.parse(d)}catch{return{}}return i!==null&&typeof i=="object"&&!Array.isArray(i)?i:{}},X=({data:d})=>{let{message:i}=b.useApp(),{assistantId:l,initialTab:B}=d??{},{get:f,put:A,del:y}=P(),e=C(),v=E(),[g,w]=(0,n.useState)(null),[_,h]=(0,n.useState)([]),[j,S]=(0,n.useState)(!1),[x,k]=(0,n.useState)(null),c=(0,n.useCallback)(()=>{v({...$,message:e("governance.detail.listCardMessage")})},[v,e]),o=(0,n.useCallback)(async()=>{S(!0),k(null);try{let s=(await f("/api/assistants")).data?.records??[];h(s),w(s.find(r=>r.id===l)??null)}catch{k(e("governance.detail.loadFailed"))}finally{S(!1)}},[f,l,e]);(0,n.useEffect)(()=>{l&&o()},[o,l]);let z=(0,n.useCallback)(async(a,s)=>{let r=J(a.graphDefinition),D;try{D=await A(`/api/assistants/${a.id}`,{name:s.name!==void 0?s.name:a.name,description:s.description!==void 0?s.description:a.description,graphDefinition:{...r,...s}})}catch(N){throw i.error(e("governance.detail.saveFailed")),N}if(!D.success)throw i.error(e("governance.detail.saveFailed")),new Error("Failed to save agent");i.success(e("common.saved")),await o()},[A,o,e]),U=(0,n.useCallback)(a=>{w(s=>s&&s.id===a.id?a:s),h(s=>s.map(r=>r.id===a.id?a:r))},[]),G=(0,n.useCallback)(async a=>{if(!(await y(`/api/assistants/${a}`)).success)throw new Error("Failed to delete agent");i.success(e("governance.detail.deleted")),c()},[y,c,e]);return l?g?(0,t.jsx)("div",{style:{height:"100%",overflow:"auto"},children:(0,t.jsx)(L,{children:(0,t.jsx)(R,{assistant:g,allAssistants:_,onBack:c,onDeleted:G,onSave:z,onAssistantUpdated:U,onAgentListInvalidated:()=>void o(),initialTab:B})},g.id)}):j?(0,t.jsx)("div",{style:{display:"flex",alignItems:"center",justifyContent:"center",height:"100%"},children:(0,t.jsx)(T,{})}):x?(0,t.jsx)("div",{style:{padding:24},children:(0,t.jsx)(p,{type:"error",showIcon:!0,message:e("governance.detail.loadFailed"),"data-testid":"detail-error",action:(0,t.jsxs)(I,{children:[(0,t.jsx)(m,{size:"small",onClick:()=>void o(),children:e("common.retry")}),(0,t.jsx)(m,{size:"small",type:"primary",onClick:c,children:e("governance.detail.backToList")})]})})}):(0,t.jsx)("div",{style:{padding:24},children:(0,t.jsx)(p,{type:"warning",showIcon:!0,message:e("governance.detail.notFound"),"data-testid":"detail-not-found",action:(0,t.jsx)(m,{size:"small",type:"primary",onClick:c,children:e("governance.detail.backToList")})})}):(0,t.jsx)("div",{style:{padding:24},children:(0,t.jsx)(p,{type:"warning",showIcon:!0,message:e("governance.detail.missingId"),"data-testid":"detail-missing-id"})})};export{X as AgentDetailSideApp};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as Ie,b as De,c as xt,d as wt,e as Tt,f as It,g as St,h as Ft,i as Pt,j as Rt,k as Dt}from"./embed-page-chunk-AJV2ISVF.js";import{a as Ge}from"./embed-page-chunk-62CAXPZK.js";import"./embed-page-chunk-NGO5C5RH.js";import"./embed-page-chunk-NR4M6XSO.js";import"./embed-page-chunk-HQLSH3FC.js";import{b as Ve,e as _e,f as yt,g as ht,h as Ct,i as At,l as bt,m as kt}from"./embed-page-chunk-5AWYMAAX.js";import"./embed-page-chunk-D7YTSCUO.js";import{a as dt,b as gt,c as pt,d as mt,e as ut}from"./embed-page-chunk-SV2BM3WO.js";import"./embed-page-chunk-S4XZPBRM.js";import"./embed-page-chunk-KKNZYZVB.js";import{U as vt,e as ct,h as ft,r as Oe}from"./embed-page-chunk-KWZEITYQ.js";import{i as lt}from"./embed-page-chunk-54M4265G.js";import{a as me}from"./embed-page-chunk-3XPHW2C7.js";import{o as Ye}from"./embed-page-chunk-5QZRLAW2.js";import{C as tt,La as rt,Q as nt,U as at,ba as ot,n as Te,oa as it,ua as st}from"./embed-page-chunk-F7ZUYG42.js";import{l as z}from"./embed-page-chunk-3FNSGFP2.js";import{a as D}from"./embed-page-chunk-QV7QAJ4N.js";import"./embed-page-chunk-VW3NF5NT.js";import"./embed-page-chunk-Z4Z6VCUZ.js";import{Ja as et,Q as Qe,g as Je,na as Re,za as Xe}from"./embed-page-chunk-L7GPZSYD.js";import{Da as F,Ia as O,Ka as Ne,Ma as pe,Sa as We,Za as we,_ as $,_a as Ze,aa as Fe,bb as J,fa as xe,ha as Ue,na as Pe,ua as Le,va as qe,xa as He,za as $e}from"./embed-page-chunk-BUFWD6SE.js";import{a as ge}from"./embed-page-chunk-R5QL57JJ.js";import"./embed-page-chunk-QOWM3LMZ.js";import"./embed-page-chunk-EUOOO2LS.js";import"./embed-page-chunk-5JDQ456X.js";import{f as T}from"./embed-page-chunk-QBTAJ2YI.js";var C=T(ge());var X=T(ge());var W=T(ge());var Mt=T(ge());var ie=T(D()),Et=60,Kt=72,ze=(0,Mt.memo)(({data:a})=>{let c=Ie(a.type),f=Math.min(12+Math.sqrt(a.subAgentCount)*10,48);return(0,ie.jsxs)("div",{style:{display:"flex",flexDirection:"column",alignItems:"center"},children:[(0,ie.jsx)(_e,{type:"target",position:Ve.Top,style:{left:"50%",top:"50%",transform:"translate(-50%, -50%)",background:"transparent",border:"none",width:0,height:0},isConnectable:!1}),(0,ie.jsx)("div",{title:a.label,style:{width:f,height:f,borderRadius:"50%",background:De(c.color),display:"flex",alignItems:"center",justifyContent:"center",color:"#fff",fontSize:Math.max(10,f*.4),fontWeight:600,cursor:"pointer",boxShadow:"0 2px 8px rgba(0,0,0,0.15)"},children:a.label.charAt(0).toUpperCase()}),(0,ie.jsx)("div",{style:{fontSize:11,maxWidth:120,textAlign:"center",whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis",marginTop:4},children:a.label}),(0,ie.jsx)(_e,{type:"source",position:Ve.Top,style:{left:"50%",top:"50%",transform:"translate(-50%, -50%)",background:"transparent",border:"none",width:0,height:0},isConnectable:!1})]})});ze.displayName="AgentGraphNode";var Q=T(D()),tn=({assistants:a,onNodeClick:c})=>{let[f,A,d]=Ct([]),[g,i,e]=At([]),[l,I]=(0,W.useState)(null),m=(0,W.useMemo)(()=>({agent:ze}),[]),R=(0,W.useMemo)(()=>Tt(a),[a]);(0,W.useEffect)(()=>{let u=R.nodes.map(o=>({id:o.id})),P=R.edges.map(o=>({source:o.source,target:o.target})),M=new Map(R.nodes.map(o=>[o.id,o])),_=mt(u).force("link",pt(P).id(o=>o.id).distance(80)).force("charge",ut().strength(-220)).force("center",dt(0,0)).force("collide",gt(45)).stop();for(let o=0;o<300;o++)_.tick();let q=u.map(o=>({id:o.id,type:"agent",data:M.get(o.id),position:{x:o.x-Et/2,y:o.y-Kt/2}})),r=R.edges.map(o=>({id:`e${o.source}-${o.target}`,source:o.source,target:o.target,style:{stroke:"#1677ff",strokeWidth:2},type:"straight"}));A(q),i(r)},[R,A,i]);let U=(0,W.useMemo)(()=>l===null?f:f.map(u=>{let P=u.id===l||g.some(M=>M.source===l&&M.target===u.id||M.target===l&&M.source===u.id);return{...u,style:{opacity:P?1:.2,transition:"opacity 0.2s ease"}}}),[f,g,l]),y=(0,W.useMemo)(()=>l===null?g.map(u=>({...u,style:{stroke:"#1677ff",strokeWidth:1.5,opacity:.25,transition:"opacity 0.2s ease"}})):g.map(u=>{let P=u.source===l||u.target===l;return{...u,style:{stroke:"#1677ff",strokeWidth:P?2.5:1,opacity:P?1:.04,transition:"opacity 0.2s ease"}}}),[g,l]);return(0,Q.jsx)("div",{style:{width:"100%",height:"100%",background:"#fafafa",position:"relative"},children:(0,Q.jsxs)(ht,{nodes:U,edges:y,onNodesChange:d,onEdgesChange:e,onNodeMouseEnter:(u,P)=>I(P.id),onNodeMouseLeave:()=>I(null),onNodeClick:(u,P)=>c?.(String(P.id)),nodeTypes:m,fitView:!0,fitViewOptions:{padding:.25},children:[(0,Q.jsx)(bt,{color:"#eee",gap:20}),(0,Q.jsx)(kt,{})]})})},Bt=a=>(0,Q.jsx)(yt,{children:(0,Q.jsx)(tn,{...a})});var w=T(D()),nn=[{key:"all",labelKey:"governance.list.tab.all"},{key:"capability",labelKey:"governance.list.tab.capability"},{key:"orchestrator",labelKey:"governance.list.tab.orchestrator"},{key:"workflow",labelKey:"governance.list.tab.workflow"}],Lt=({items:a,assistants:c=[],loading:f,onItemClick:A,onOpenPlayground:d,onOpenEval:g,onCreate:i,onDelete:e})=>{let l=z(),[I,m]=(0,X.useState)("all"),[R,U]=(0,X.useState)(null),[y,u]=(0,X.useState)(null),P=(0,X.useMemo)(()=>{let r=new Set;return a.forEach(o=>o.tags.forEach(te=>r.add(te))),Array.from(r).map(o=>({value:o,label:o}))},[a]),M=(0,X.useMemo)(()=>a.filter(r=>!(I!=="all"&&r.type!==I||R&&!r.tags.includes(R)||y&&r.status!==y)),[a,I,R,y]),_=[{key:"edit",icon:st,label:l("common.edit"),onClick:r=>A(r.id)},{key:"playground",icon:tt,label:l("governance.list.action.playground"),onClick:r=>d(r.id)},{key:"eval",icon:at,label:l("governance.list.action.eval"),onClick:r=>g(r.id)}];e&&_.push({key:"delete",icon:rt,label:l("common.delete"),danger:!0,onClick:r=>e(r.id)});let q=(0,X.useMemo)(()=>[{mode:"graph",icon:it,label:l("governance.list.viewMode.graph"),render:()=>(0,w.jsx)(Bt,{assistants:c,onNodeClick:A})}],[c,A,l]);return(0,w.jsxs)(w.Fragment,{children:[(0,w.jsx)("span",{"data-testid":"agent-list-state","data-loading":String(f),"data-count":M.length,hidden:!0,"aria-hidden":"true"}),(0,w.jsx)(ct,{title:l("governance.list.title"),itemName:"common.item.agent",items:M,loading:f,keyExtractor:r=>r.id,tabs:nn.map(r=>({key:r.key,label:l(r.labelKey)})),activeTab:I,onTabChange:r=>m(r),headerLeft:(0,w.jsxs)("div",{style:{display:"flex",gap:8,alignItems:"center"},children:[(0,w.jsx)(Oe,{value:R,onChange:U,options:P,placeholder:l("governance.list.filter.domain"),allLabel:l("governance.list.filter.allDomains")}),(0,w.jsx)(Oe,{value:y,onChange:u,options:[{value:"enabled",label:l("governance.list.status.enabled")},{value:"draft",label:l("governance.list.status.draft")},{value:"disabled",label:l("governance.list.status.disabled")}],placeholder:l("governance.list.filter.status"),allLabel:l("governance.list.filter.allStatuses")})]}),renderIcon:r=>{let o=De(Ie(r.type).color);return(0,w.jsx)("div",{title:l("governance.list.typeIconTitle",{type:r.type}),style:{width:32,height:32,borderRadius:8,background:`${o}1A`,color:o,display:"flex",alignItems:"center",justifyContent:"center",flexShrink:0},children:(0,w.jsx)(Te,{size:18})})},renderPrimary:r=>(0,w.jsx)("span",{"data-testid":"agent-name","data-agent-id":r.id,children:r.name}),renderSecondary:r=>r.description||void 0,renderDetails:r=>(0,w.jsxs)("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",gap:8,flexWrap:"wrap"},children:[(0,w.jsxs)("div",{style:{display:"flex",gap:4,flexWrap:"wrap",alignItems:"center"},children:[r.tags.map(o=>(0,w.jsx)(we,{color:"magenta",style:{margin:0,borderRadius:10,border:"none"},children:o},o)),(0,w.jsx)(we,{color:Ie(r.type).color,style:{margin:0,borderRadius:10,border:"none"},children:r.type})]}),(0,w.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:8,flexShrink:0},children:[(0,w.jsx)(Ue,{title:l("governance.list.statusTooltip",{status:r.status}),children:(0,w.jsx)("span",{style:{width:8,height:8,borderRadius:"50%",background:xt(r.status),display:"inline-block",cursor:"help"}})}),(0,w.jsx)("span",{style:{fontSize:12,color:"#8c8c8c"},children:r.version})]})]}),itemActions:_,actionsStyle:"icon",actionsPosition:"hover",onItemClick:r=>A(r.id),createLabel:l("governance.list.create"),onCreateClick:i,viewModeExtensions:q,emptyIcon:(0,w.jsx)(Te,{size:48,style:{opacity:.5}}),emptyTitle:l("governance.list.emptyTitle"),emptyDescription:l("governance.list.emptyDescription")})]})};var b=T(ge());var se=T(ge());var ue=T(D()),{Text:an}=J,Nt=({onSelect:a,value:c,placeholder:f})=>{let A=z(),d=f??A("chatConfig.parentAgent.selectPlaceholder"),[g,i]=(0,se.useState)([]),[e,l]=(0,se.useState)(!1),{get:I}=me(),m=(0,se.useCallback)(async()=>{l(!0);try{let y=await I("/api/assistants");y.success&&i(y.data?.records||[])}catch(y){console.error("Failed to fetch assistants:",y)}finally{l(!1)}},[I]);return(0,se.useEffect)(()=>{m()},[m]),(0,ue.jsx)(xe,{showSearch:!0,allowClear:!0,value:c,placeholder:d,loading:e,onChange:y=>{if(!y){a(null);return}let u=g.find(P=>P.id===y);a(u||null)},onDropdownVisibleChange:y=>{y&&m()},optionFilterProp:"label",style:{width:"100%"},options:g.map(y=>({value:y.id,label:y.name||y.id,description:y.description})),optionRender:y=>(0,ue.jsxs)("div",{children:[(0,ue.jsx)("div",{children:y.label}),y.data.description&&(0,ue.jsx)(an,{type:"secondary",style:{fontSize:12},children:y.data.description})]})})};var B=T(D()),{Text:Ot}=J,Vt=({subAgentKeys:a,decisions:c,onChange:f})=>{let{token:A}=Ze.useToken(),d=z(),g=(e,l)=>{let I=c.map(m=>m.originalKey===e?{...m,clone:l,cloneKey:l?`${e}_clone`:void 0}:m);f(I)},i=(e,l)=>{let I=c.map(m=>m.originalKey===e?{...m,cloneKey:l}:m);f(I)};return a.length===0?null:(0,B.jsxs)("div",{children:[(0,B.jsx)(Ot,{type:"secondary",style:{display:"block",marginBottom:8},children:d("chatConfig.subAgentInherit.hint")}),(0,B.jsx)(Ne,{size:"small",bordered:!0,dataSource:c,style:{borderRadius:A.borderRadius},renderItem:e=>(0,B.jsxs)(Ne.Item,{style:{display:"flex",flexDirection:"column",alignItems:"stretch",gap:8,padding:"8px 16px"},children:[(0,B.jsxs)("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[(0,B.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.clone?(0,B.jsx)(Re,{style:{color:A.colorPrimary}}):(0,B.jsx)(Xe,{style:{color:A.colorTextSecondary}}),(0,B.jsx)(Ot,{style:{fontFamily:"monospace"},children:e.originalKey})]}),(0,B.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:8},children:[(0,B.jsx)(we,{color:e.clone?"blue":"default",children:e.clone?d("chatConfig.subAgentInherit.clone"):d("chatConfig.subAgentInherit.reuse")}),(0,B.jsx)(We,{size:"small",checked:e.clone,onChange:l=>g(e.originalKey,l)})]})]}),e.clone&&(0,B.jsx)(O,{size:"small",placeholder:d("chatConfig.subAgentInherit.cloneKeyPlaceholder"),value:e.cloneKey,onChange:l=>i(e.originalKey,l.target.value),style:{fontFamily:"monospace",fontSize:12},addonBefore:d("chatConfig.keyValue.key")})]})})]})};function _t(a,c){return a.mode!=="local"||a.templateKey||typeof a.executable=="string"&&a.executable.trim().length>0?null:c?c("chat.config.executableRequired"):"Choose a template or enter a custom executable"}var n=T(D()),{TextArea:Gt}=O,{Text:ee}=J,zt="/.well-known/agent-card.json",on=[{value:"http://",label:"http://"},{value:"https://",label:"https://"}],sn={react:"chatConfig.createAssistant.typeDesc.react",deep_agent:"chatConfig.createAssistant.typeDesc.deepAgent",a2a_remote:"chatConfig.createAssistant.typeDesc.a2aRemote"};function jt(a,c,f="https://"){let A=String(a??"").trim();if(!A)return"";let d=c==="http://"||c==="https://"?c:f,i=(/^https?:\/\//i.test(A)?A:`${d}${A.replace(/^\/+/,"")}`).replace(/\/+$/,"");return i.endsWith(zt)?i:`${i}${zt}`}function rn(a){try{return new URL(a).port||void 0}catch{return}}function ln(a){return a.some(c=>c==="--port"||c==="-p"||/^--port=/.test(c)||/^-p=/.test(c))}function Ut(a,c){let f=[...a.args],A=rn(c);return A&&!ln(f)&&f.push("--port",A),{...a,args:f,...a.env?{env:{...a.env}}:{}}}var qt=({open:a,onCancel:c,onSuccess:f,initialMode:A,initialValues:d})=>{let{message:g}=Fe.useApp(),[i]=F.useForm(),e=z(),[l,I]=(0,b.useState)(!1),[m,R]=(0,b.useState)("learn"),[U,y]=(0,b.useState)(""),[u,P]=(0,b.useState)(null),[M,_]=(0,b.useState)([]),q=F.useWatch("type",i)||"react",r=q==="a2a_remote",[o,te]=(0,b.useState)("remote"),[H,fe]=(0,b.useState)(void 0),[re,ye]=(0,b.useState)([]),[Se,le]=(0,b.useState)(!1),ne=(0,b.useRef)(0),[ae,oe]=(0,b.useState)(!1),[Me,Z]=(0,b.useState)(!1),{get:L,post:Y,put:he}=me(),Ee=Ye("agent-architect"),{workspaceId:Ce,trainingProjects:ce,loading:de}=lt(),[Ke,Ae]=(0,b.useState)(null),Be=JSON.stringify(d??null),E=ce.find(t=>t.id===Ke)??ce[0]??null,[be,ke]=(0,b.useState)([]),p=(0,b.useCallback)(()=>{P(null),_([])},[]),k=(0,b.useCallback)(()=>{i.resetFields(),p(),R("learn"),y(""),ke([]),Ae(null),te("remote"),fe(void 0),ye([]),Z(!1),oe(!1)},[i,p]);(0,b.useEffect)(()=>{if(a){k(),R(A??"learn");let t=d?.a2aMode;(t==="remote"||t==="local")&&te(t),i.setFieldsValue({type:"react",agentCardProtocol:"https://",a2aMode:"remote",timeout:3e5,...d})}},[a,i,A,Be,k]),(0,b.useEffect)(()=>{let t=++ne.current,s=!0;return a&&r?(i.setFieldValue("prompt",""),o==="local"?(le(!0),L("/api/local-a2a/templates").then(v=>{s&&t===ne.current&&v?.data?.records&&ye(v.data.records)}).catch(()=>{s&&t===ne.current&&ye([])}).finally(()=>{s&&t===ne.current&&le(!1)})):le(!1)):le(!1),()=>{s=!1,ne.current+=1}},[i,r,o,L,a]);let x=re.find(t=>t.key===H),j=(0,b.useCallback)(()=>{let t=_t({mode:o,templateKey:H,executable:i.getFieldValue("commandExecutable")},e);return t?(Z(!0),i.setFields([{name:"commandExecutable",errors:[t]}]),g.warning(t),!1):!0},[o,H,i,e]);(0,b.useEffect)(()=>{x&&i.setFieldsValue({agentCardProtocol:"http://"})},[i,x]);let ve=(0,b.useCallback)(async()=>{if(!j())return;let t=jt(i.getFieldValue("agentCardUrl"),i.getFieldValue("agentCardProtocol"),o==="local"?"http://":"https://");if(!t){g.warning(e("chatConfig.createAssistant.a2aUrlWarning"));return}oe(!0);try{let s={agentCardUrl:t,apiKey:i.getFieldValue("apiKey")};if(o==="local"){let h=x;if(h)s.localRuntime={label:i.getFieldValue("name")||void 0,agentCardUrl:t,command:Ut(h.command,t)};else{let K=i.getFieldValue("commandArgs")||"",G=K?K.split(/\s+/).filter(Boolean):[],S=String(i.getFieldValue(["command","cwd"])||"").trim();s.localRuntime={label:i.getFieldValue("name")||void 0,agentCardUrl:t,command:{executable:String(i.getFieldValue("commandExecutable")||"").trim(),args:G,...S?{cwd:S}:{}}}}}let v=await Y("/api/a2a/test-connection",s);if(v.data?.reachable){let h=v.data.agentCard;g.success(e("chatConfig.createAssistant.connectedTo",{name:v.data.agentName||t}))}else g.error(v.data?.error||e("chatConfig.createAssistant.connectionFailed"))}catch{g.error(e("chatConfig.createAssistant.connectionTestFailed"))}finally{oe(!1)}},[i,Y,o,x,j,e]),Wt=(0,b.useCallback)(t=>{if(P(t),!t){i.resetFields(["key","name","description","type","prompt"]),_([]);return}let s=typeof t.graphDefinition=="object"&&t.graphDefinition!==null?t.graphDefinition:{},v=s.key||t.id,h=t.name||s.name||"";i.setFieldsValue({key:`${v}_ext`,name:h?`${h} (Extended)`:"",description:t.description||s.description||"",type:s.type||"react",prompt:s.prompt||""});let K=s.subAgents||[];_(K.map(G=>({originalKey:G,clone:!1})))},[i]),Zt=async(t,s)=>{let v=await L(`/api/assistants/${t}`);if(!v.success)throw new Error(e("chatConfig.createAssistant.cloneFetchFailed",{key:t}));let h=v.data,K=typeof h.graphDefinition=="object"?h.graphDefinition:{},G={id:s,name:`${h.name} (Clone)`,description:h.description||"",graphDefinition:{...K,key:s,name:`${h.name} (Clone)`}},S=await Y("/api/assistants",G);if(!S.success)throw new Error(S.message||e("chatConfig.createAssistant.cloneFailed",{key:t}));return S.data},Yt=t=>{let s={id:t.key,name:t.name,description:t.description||"",graphDefinition:{key:t.key,name:t.name,description:t.description||"",type:t.type,prompt:t.prompt||"",tools:[],skills:[],subAgents:t.type==="deep_agent"?[]:void 0,middleware:[]}};if(t.type==="a2a_remote"&&(s.graphDefinition.agentCardUrl=jt(t.agentCardUrl,t.agentCardProtocol,(t.a2aMode||o)==="local"?"http://":"https://"),t.apiKey&&(s.graphDefinition.apiKey=t.apiKey),t.timeout&&(s.graphDefinition.timeout=t.timeout),(t.a2aMode||o)==="local")){let v=x;if(v)s.graphDefinition.localRuntime={label:t.name||void 0,agentCardUrl:s.graphDefinition.agentCardUrl,command:Ut(v.command,s.graphDefinition.agentCardUrl)};else{let h=t.commandArgs||"",K=h?h.split(/\s+/).filter(Boolean):[],G=String(t.command?.cwd||"").trim();s.graphDefinition.localRuntime={label:t.name||void 0,agentCardUrl:s.graphDefinition.agentCardUrl,command:{executable:String(t.commandExecutable||"").trim(),args:K,...G?{cwd:G}:{}}}}}return s},Jt=async(t,s)=>{if(!u)throw new Error(e("chatConfig.createAssistant.noParentAgent"));let v=M.filter(S=>S.clone);for(let S of v){if(!S.cloneKey||!S.cloneKey.trim())throw new Error(e("chatConfig.createAssistant.cloneKeyRequired",{key:S.originalKey}));if(!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(S.cloneKey))throw new Error(e("chatConfig.createAssistant.cloneKeyInvalid",{key:S.cloneKey,originalKey:S.originalKey}))}let h=[];for(let S of M)if(S.clone){let en=await Zt(S.originalKey,S.cloneKey);s.push(en),h.push(S.cloneKey)}else h.push(S.originalKey);let K=typeof u.graphDefinition=="object"?u.graphDefinition:{},G={key:t.key,name:t.name,description:t.description||"",extendsAgent:u.id,type:t.type||K.type};return t.prompt&&t.prompt!==K.prompt&&(G.prompt=t.prompt),(h.length>0||K.subAgents&&K.subAgents.length>0)&&(G.subAgents=h),{id:t.key,name:t.name,description:t.description||"",graphDefinition:G}},Qt=async()=>{if(m==="learn"){let t=U.trim();if(!t){g.error(e("chatConfig.createAssistant.trainingGoalRequired"));return}if(!E){g.error(e("chatConfig.createAssistant.noTrainingProject"));return}I(!0);try{let s=`agent-${St(t+Date.now())}`,v=await Y("/api/assistants",{id:s,name:s,graphDefinition:{key:s,name:s,description:"",type:"react",prompt:"To be trained",metadata:{trainingProjectId:E.id,learningPlaceholder:"true",architectureStatus:"undecided"}}});if(!v.data)throw new Error(e("chatConfig.createAssistant.agentCreateFailed"));let{roundTaskId:h}=await Pt({goal:t,targetAgentId:s,workspaceId:Ce??void 0,projectId:E.id,existingThreadId:Ft(Ee.tenantId,s),files:be,post:Y,put:he});g.success(e("chatConfig.createAssistant.agentCreated")),y(""),ke([]),R("learn"),f?.(v.data,{initialMessage:Rt({goal:t,roundTaskId:h,targetAgentId:s,targetMode:"placeholder",files:be,projectId:E.id,workspaceId:E.workspaceId??Ce??void 0}),projectId:E.id,initialMessageCustomRunConfig:{execution:{taskId:h}}}),c()}catch(s){g.error(s instanceof Error?s.message:e("chatConfig.createAssistant.agentCreateFailed"))}finally{I(!1)}return}try{if(m==="scratch"&&r&&!j())return;let t=await i.validateFields();I(!0);let s=[],v=m==="scratch"?Yt(t):await Jt(t,s),h=await Y("/api/assistants",v);if(h.success){g.success(m==="extend"?e("chatConfig.createAssistant.createdByExtending",{name:u?.name??""}):e("chatConfig.createAssistant.created")),k();for(let K of s)f?.(K);f?.(h.data),c()}else g.error(h.message||e("chatConfig.createAssistant.createFailed"))}catch(t){if(t?.errorFields){let s={key:e("chatConfig.createAssistant.field.key"),name:e("chatConfig.createAssistant.field.name"),description:e("chatConfig.createAssistant.field.description"),prompt:e("chatConfig.createAssistant.field.systemPrompt")},v=t.errorFields.map(h=>s[String((h.name??[])[0])]??String((h.name??[])[0])).filter(Boolean);g.warning(v.length>0?e("chatConfig.createAssistant.requiredFields",{fields:[...new Set(v)].join(", ")}):e("chatConfig.createAssistant.requiredFieldsGeneric"));return}g.error(t.message||e("chatConfig.createAssistant.createError"))}finally{I(!1)}},je=u?.graphDefinition?.subAgents||[],Xt=m==="extend"&&u&&je.length>0;return(0,n.jsxs)(pe,{title:e("chatConfig.createAssistant.title"),open:a,onCancel:()=>{k(),c()},footer:[(0,n.jsx)($,{onClick:()=>{k(),c()},children:e("common.cancel")},"cancel"),(0,n.jsx)($,{type:"primary",icon:m==="extend"?(0,n.jsx)(Re,{}):m==="learn"?(0,n.jsx)(Qe,{}):(0,n.jsx)(et,{}),loading:l,disabled:m==="learn"&&(de||!E),onClick:Qt,children:e(m==="extend"?"chatConfig.createAssistant.createExtend":m==="learn"?"chatConfig.createAssistant.startLearning":"common.create")},"submit")],width:760,children:[m==="extend"&&(0,n.jsxs)("div",{style:{marginBottom:20},children:[(0,n.jsx)(ee,{type:"secondary",style:{display:"block",marginBottom:8},children:e("chatConfig.createAssistant.parentAgent")}),(0,n.jsx)(Nt,{value:u?.id,onSelect:Wt}),u&&(0,n.jsx)(ee,{type:"secondary",style:{display:"block",marginTop:4,fontSize:12},children:e("chatConfig.createAssistant.inheritHint")})]}),m==="extend"&&u&&(0,n.jsx)(Le,{style:{margin:"12px 0"}}),m==="learn"&&(0,n.jsxs)("div",{children:[(0,n.jsx)(ee,{style:{display:"block",marginBottom:8},children:e("chatConfig.createAssistant.learnHint")}),(0,n.jsx)(O.TextArea,{rows:3,value:U,onChange:t=>y(t.target.value),placeholder:e("chatConfig.createAssistant.learnGoalPlaceholder")}),E&&(0,n.jsxs)("div",{style:{marginTop:12},children:[(0,n.jsxs)("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:12,marginBottom:8},children:[(0,n.jsx)(ee,{type:"secondary",children:e("chatConfig.createAssistant.referenceFiles")}),(0,n.jsx)(Ge,{project:E,value:E?.id??null,onChange:Ae,loading:de})]}),(0,n.jsx)(It,{projectId:E.id,value:be,onChange:ke}),(0,n.jsx)(ee,{type:"secondary",style:{display:"block",marginTop:6,fontSize:12},children:e("chatConfig.createAssistant.referenceFilesHint")})]}),!E&&!de&&(0,n.jsx)("div",{style:{marginTop:12},children:(0,n.jsx)(Ge,{project:E,value:null,onChange:Ae,loading:de})})]}),m!=="learn"&&(0,n.jsxs)(F,{form:i,layout:"vertical",autoComplete:"off",initialValues:{type:"react",agentCardProtocol:"https://",a2aMode:"remote"},children:[(0,n.jsx)(F.Item,{name:"key",label:e("chatConfig.createAssistant.field.key"),rules:[{required:!0,message:e("chatConfig.createAssistant.validation.keyRequired")},{pattern:/^[a-zA-Z][a-zA-Z0-9_-]*$/,message:e("chatConfig.createAssistant.validation.keyPattern")}],style:{marginBottom:16},children:(0,n.jsx)(O,{placeholder:e("chatConfig.createAssistant.keyPlaceholder")})}),(0,n.jsx)(F.Item,{name:"name",label:e("chatConfig.createAssistant.field.name"),rules:[{required:!0,message:e("chatConfig.createAssistant.validation.nameRequired")}],style:{marginBottom:16},children:(0,n.jsx)(O,{placeholder:e("chatConfig.createAssistant.namePlaceholder")})}),(0,n.jsx)(F.Item,{name:"description",label:e("chatConfig.createAssistant.field.description"),rules:[{required:!0,message:e("chatConfig.createAssistant.validation.descriptionRequired")}],style:{marginBottom:16},children:(0,n.jsx)(Gt,{placeholder:e("chatConfig.createAssistant.descriptionPlaceholder"),autoSize:{minRows:2,maxRows:4}})}),(0,n.jsx)(F.Item,{name:"type",label:e("chatConfig.createAssistant.field.agentType"),rules:[{required:!0}],style:{marginBottom:16},children:(0,n.jsx)(qe,{options:[{value:"react",label:e("chatConfig.agentType.executor")},{value:"deep_agent",label:e("chatConfig.agentType.orchestrator")},{value:"a2a_remote",label:e("chatConfig.agentType.a2aRemote")}],block:!0})}),(0,n.jsx)(ee,{type:"secondary",style:{fontSize:12,display:"block",marginTop:-12,marginBottom:16,lineHeight:1.5},children:e(sn[q]??"chatConfig.createAssistant.typeDesc.react")}),r&&(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(F.Item,{label:e("chatConfig.createAssistant.field.connectionMode"),style:{marginBottom:16},children:(0,n.jsxs)(Pe.Group,{value:o,onChange:t=>{let s=t.target.value;te(s),i.setFieldValue("a2aMode",s),s==="local"&&i.setFieldValue("agentCardProtocol","http://"),fe(void 0)},optionType:"button",buttonStyle:"solid",children:[(0,n.jsx)(Pe.Button,{value:"remote",children:e("chatConfig.createAssistant.mode.remoteUrl")}),(0,n.jsx)(Pe.Button,{value:"local",children:e("chatConfig.createAssistant.mode.localManaged")})]})}),(0,n.jsx)(F.Item,{name:"a2aMode",noStyle:!0,hidden:!0,children:(0,n.jsx)(O,{})}),o==="local"&&(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(F.Item,{label:e("chatConfig.createAssistant.field.template"),style:{marginBottom:16},children:(0,n.jsx)(xe,{placeholder:e("chatConfig.createAssistant.templatePlaceholder"),allowClear:!0,loading:Se,value:H,onChange:t=>{fe(t),t&&Z(!1)},options:re.map(t=>({value:t.key,label:t.name||t.key})),notFoundContent:Se?void 0:(0,n.jsx)(ee,{type:"secondary",style:{padding:8,display:"block"},children:e("chatConfig.createAssistant.noTemplates")})})}),!H&&(0,n.jsx)(n.Fragment,{children:Me?(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(F.Item,{name:"commandExecutable",label:e("chatConfig.createAssistant.field.executable"),rules:[{required:!0,whitespace:!0,message:e("chatConfig.createAssistant.validation.executableRequired")}],style:{marginBottom:16},children:(0,n.jsx)(O,{placeholder:e("chatConfig.createAssistant.executablePlaceholder")})}),(0,n.jsx)(F.Item,{name:"commandArgs",label:e("chatConfig.createAssistant.field.arguments"),style:{marginBottom:16},children:(0,n.jsx)(O,{placeholder:e("chatConfig.createAssistant.argumentsPlaceholder")})}),(0,n.jsx)(F.Item,{name:["command","cwd"],label:e("chatConfig.createAssistant.field.workingDirectory"),style:{marginBottom:16},children:(0,n.jsx)(O,{placeholder:e("chatConfig.createAssistant.workingDirectoryPlaceholder")})}),(0,n.jsx)($,{type:"link",onClick:()=>{Z(!1),i.setFieldsValue({commandExecutable:"",commandArgs:"",command:{cwd:void 0}})},style:{padding:0,marginBottom:16,display:"block"},children:e("chatConfig.createAssistant.hideCustomCommand")})]}):(0,n.jsx)($,{type:"link",onClick:()=>Z(!0),style:{padding:0,marginBottom:16,display:"block"},children:e("chatConfig.createAssistant.customCommand")})})]}),(0,n.jsx)(F.Item,{label:e("chatConfig.createAssistant.field.agentCardUrl"),required:!0,style:{marginBottom:16},children:(0,n.jsxs)($e.Compact,{style:{width:"100%"},children:[(0,n.jsx)(F.Item,{name:"agentCardProtocol",noStyle:!0,children:(0,n.jsx)(xe,{style:{width:100},options:on})}),(0,n.jsx)(F.Item,{name:"agentCardUrl",noStyle:!0,rules:[{required:!0,message:e("chatConfig.createAssistant.validation.urlRequired")}],children:(0,n.jsx)(O,{placeholder:o==="local"?"localhost:4301":"host:port or full URL"})}),(0,n.jsx)($,{icon:(0,n.jsx)(Je,{}),onClick:ve,loading:ae,children:e("chatConfig.connection.action.test")})]})}),o==="remote"&&(0,n.jsx)(F.Item,{name:"apiKey",label:e("chatConfig.createAssistant.field.apiKeyOptional"),style:{marginBottom:16},children:(0,n.jsx)(O.Password,{placeholder:e("chatConfig.createAssistant.apiKeyPlaceholder")})}),(0,n.jsx)(F.Item,{name:"timeout",label:e("chatConfig.createAssistant.field.timeout"),style:{marginBottom:16},initialValue:3e5,children:(0,n.jsx)(He,{min:1e3,max:36e5,style:{width:"100%"},placeholder:"300000"})})]}),!r&&(0,n.jsx)(F.Item,{name:"prompt",label:e(m==="extend"&&u?"chatConfig.createAssistant.field.systemPromptInherit":"chatConfig.createAssistant.field.systemPrompt"),rules:m==="scratch"?[{required:!0,message:e("chatConfig.createAssistant.validation.systemPromptRequired")}]:[],children:(0,n.jsx)(Gt,{placeholder:e(m==="extend"&&u?"chatConfig.createAssistant.systemPromptInheritPlaceholder":"chatConfig.createAssistant.systemPromptPlaceholder"),autoSize:{minRows:4,maxRows:8},style:{fontFamily:"monospace",fontSize:13,lineHeight:1.6}})})]}),Xt&&(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(Le,{style:{margin:"12px 0"}}),(0,n.jsx)(ee,{strong:!0,style:{display:"block",marginBottom:8},children:e("chatConfig.createAssistant.subAgents")}),(0,n.jsx)(Vt,{subAgentKeys:je,decisions:M,onChange:_})]})]})};var N=T(D()),{Paragraph:cn,Text:Ht}=J,dn=[{key:"manual",icon:Te,titleKey:"governance.creation.manual.title",descriptionKey:"governance.creation.manual.description"},{key:"external",icon:nt,titleKey:"governance.creation.external.title",descriptionKey:"governance.creation.external.description"},{key:"learn",icon:ot,titleKey:"governance.creation.learn.title",descriptionKey:"governance.creation.learn.description"}],$t=({open:a,onCancel:c,onSelectMethod:f,focusTriggerAfterClose:A=!0})=>{let d=z();return(0,N.jsx)(pe,{title:d("governance.creation.title"),open:a,onCancel:c,footer:null,width:560,centered:!0,destroyOnHidden:!0,focusTriggerAfterClose:A,children:(0,N.jsxs)("div",{style:{padding:"8px 4px 4px"},children:[(0,N.jsx)(cn,{style:{color:"#595959",fontSize:15,margin:"8px 0 24px"},children:d("governance.creation.subtitle")}),(0,N.jsx)("div",{style:{display:"flex",flexDirection:"column",gap:12},children:dn.map(g=>{let i=g.icon,e=d(g.titleKey);return(0,N.jsxs)($,{type:"default",onClick:()=>f(g.key),"aria-label":e,style:{display:"flex",flexDirection:"row",alignItems:"center",justifyContent:"flex-start",gap:16,width:"100%",minHeight:88,height:"auto",padding:16,borderRadius:16,textAlign:"left",whiteSpace:"normal"},children:[(0,N.jsx)("div",{style:{width:40,height:40,borderRadius:12,display:"flex",alignItems:"center",justifyContent:"center",flexShrink:0,color:"#6366f1",background:"#eeeeff"},children:(0,N.jsx)(i,{size:19})}),(0,N.jsxs)("div",{style:{minWidth:0},children:[(0,N.jsx)(Ht,{strong:!0,style:{display:"block",fontSize:15,marginBottom:3},children:e}),(0,N.jsx)(Ht,{style:{color:"#737373",lineHeight:1.5},children:d(g.descriptionKey)})]})]},g.key)})}),(0,N.jsx)("div",{style:{display:"flex",justifyContent:"flex-end",gap:8,flexWrap:"wrap",marginTop:24},children:(0,N.jsx)($,{onClick:c,children:d("governance.creation.notNow")})})]})})};var V=T(D()),gn=a=>{let c=a;if(typeof a=="string")try{c=JSON.parse(a)}catch{return{}}return c!==null&&typeof c=="object"&&!Array.isArray(c)?c:{}},va=()=>{let{message:a}=Fe.useApp(),{get:c,del:f,put:A}=me(),d=z(),[g,i]=(0,C.useState)([]),[e,l]=(0,C.useState)(!1),[I,m]=(0,C.useState)(null),[R,U]=(0,C.useState)("graph"),[y,u]=(0,C.useState)(null),[P,M]=(0,C.useState)(null),[_,q]=(0,C.useState)(null),[r,o]=(0,C.useState)(!1),[te,H]=(0,C.useState)(!0),[fe,re]=(0,C.useState)(!1),[ye,Se]=(0,C.useState)("learn"),[le,ne]=(0,C.useState)({}),[ae,oe]=(0,C.useState)(null),[Me,Z]=(0,C.useState)(!1),L=(0,C.useCallback)(async()=>{l(!0);try{let p=await c("/api/assistants");p.success&&p.data?.records&&i(p.data.records)}catch{a.error(d("governance.workbench.loadFailed"))}finally{l(!1)}},[c,d]);(0,C.useEffect)(()=>{L()},[L]);let Y=C.default.useMemo(()=>wt(g),[g]),he=g.find(p=>p.id===I)??null,Ee=(0,C.useCallback)((p,k="graph")=>{m(p),U(k),u(null),q(null)},[]),Ce=ft(),ce=(0,C.useCallback)((p,k)=>{let x=g.find(j=>j.id===p)?.name??d("governance.workbench.agentFallback");Ce({component_key:"agent_detail_side_app",data:{assistantId:p,initialTab:k},message:x})},[g,Ce,d]),de=(0,C.useCallback)(()=>{H(!0),o(!0)},[]),Ke=(0,C.useCallback)(p=>{let x={manual:{mode:"scratch",values:{}},external:{mode:"scratch",values:{type:"a2a_remote"}},learn:{mode:"learn",values:{}}}[p];Se(x.mode),ne(x.values),H(!1),o(!1),re(!0)},[]),Ae=(0,C.useCallback)(async(p,k)=>{let x=gn(p.graphDefinition),j;try{j=await A(`/api/assistants/${p.id}`,{name:k.name!==void 0?k.name:p.name,description:k.description!==void 0?k.description:p.description,graphDefinition:{...x,...k}})}catch(ve){throw a.error(d("governance.detail.saveFailed")),ve}if(!j.success)throw a.error(d("governance.detail.saveFailed")),new Error("Failed to save agent");a.success(d("common.saved")),L()},[A,L,d]),Be=(0,C.useCallback)(p=>{i(k=>k.map(x=>x.id===p.id?p:x))},[]),E=(0,C.useCallback)(p=>{oe(p)},[]),be=(0,C.useCallback)(async()=>{if(ae){Z(!0);try{(await f(`/api/assistants/${ae}`)).success?(a.success(d("governance.detail.deleted")),i(k=>k.filter(x=>x.id!==ae)),L(),oe(null)):a.error(d("governance.detail.deleteFailed"))}catch{a.error(d("governance.detail.deleteFailed"))}finally{Z(!1)}}},[ae,f,L,d]),ke=(0,C.useCallback)(async p=>{if(!(await f(`/api/assistants/${p}`)).success)throw new Error("Failed to delete agent");a.success(d("governance.detail.deleted")),i(x=>x.filter(j=>j.id!==p)),L()},[f,L,d]);return(0,V.jsxs)("div",{style:{height:"100%",background:"#fafafa",overflow:"hidden"},children:[he?(0,V.jsx)(vt,{defaultProjectId:_??void 0,children:(0,V.jsx)(Dt,{assistant:he,allAssistants:g,onBack:()=>m(null),onDeleted:ke,onSave:Ae,onAssistantUpdated:Be,onAgentListInvalidated:L,initialTab:R,initialMessage:y,initialMessageCustomRunConfig:P,initialProjectId:_})},he.id):(0,V.jsx)(V.Fragment,{children:(0,V.jsx)(Lt,{items:Y,assistants:g,loading:e,onItemClick:p=>ce(p,"graph"),onOpenPlayground:p=>ce(p,"playground"),onOpenEval:p=>ce(p,"eval"),onCreate:de,onDelete:E})}),(0,V.jsx)($t,{open:r,onCancel:()=>{H(!0),o(!1)},onSelectMethod:Ke,focusTriggerAfterClose:te}),(0,V.jsx)(qt,{open:fe,initialMode:ye,initialValues:le,onCancel:()=>re(!1),onSuccess:(p,k)=>{re(!1),i(x=>x.some(ve=>ve.id===p.id)?x:[p,...x]),Ee(p.id,"graph"),u(k?.initialMessage??null),M(k?.initialMessageCustomRunConfig??null),q(k?.projectId??null),L()}}),(0,V.jsx)(pe,{title:d("governance.deleteAgent"),open:ae!==null,onCancel:()=>oe(null),onOk:be,okText:d("common.delete"),okButtonProps:{danger:!0,loading:Me},cancelText:d("common.cancel"),children:(0,V.jsx)("p",{children:d("governance.delete.irreversible")})})]})};export{va as AgentGovernanceWorkbench};
|
|
1
|
+
import{a as Ie,b as De,c as xt,d as wt,e as Tt,f as It,g as St,h as Ft,i as Pt,j as Rt,k as Dt}from"./embed-page-chunk-QRFTGCB2.js";import"./embed-page-chunk-D7YTSCUO.js";import{a as Ge}from"./embed-page-chunk-ML6AVDQQ.js";import"./embed-page-chunk-ZVTX7OVB.js";import"./embed-page-chunk-RU45VIPM.js";import"./embed-page-chunk-HQLSH3FC.js";import{b as Ve,e as _e,f as yt,g as ht,h as Ct,i as At,l as bt,m as kt}from"./embed-page-chunk-5AWYMAAX.js";import{a as dt,b as gt,c as pt,d as mt,e as ut}from"./embed-page-chunk-SV2BM3WO.js";import"./embed-page-chunk-S4XZPBRM.js";import"./embed-page-chunk-G6UTU7IC.js";import{U as vt,e as ct,h as ft,r as Oe}from"./embed-page-chunk-4GCFDWE7.js";import{a as me}from"./embed-page-chunk-5O5IKZOC.js";import{i as lt}from"./embed-page-chunk-AFYXBC77.js";import{o as Ye}from"./embed-page-chunk-TZPX2O54.js";import{C as tt,La as rt,Q as nt,U as at,ba as ot,n as Te,oa as it,ua as st}from"./embed-page-chunk-F7ZUYG42.js";import{l as z}from"./embed-page-chunk-5EENS2J7.js";import{a as D}from"./embed-page-chunk-QV7QAJ4N.js";import"./embed-page-chunk-VW3NF5NT.js";import"./embed-page-chunk-Z4Z6VCUZ.js";import{Ja as et,Q as Qe,g as Je,na as Re,za as Xe}from"./embed-page-chunk-L7GPZSYD.js";import{Da as F,Ia as O,Ka as Ne,Ma as pe,Sa as We,Za as we,_ as $,_a as Ze,aa as Fe,bb as J,fa as xe,ha as Ue,na as Pe,ua as Le,va as qe,xa as He,za as $e}from"./embed-page-chunk-BUFWD6SE.js";import{a as ge}from"./embed-page-chunk-R5QL57JJ.js";import"./embed-page-chunk-QOWM3LMZ.js";import"./embed-page-chunk-EUOOO2LS.js";import"./embed-page-chunk-5JDQ456X.js";import{f as T}from"./embed-page-chunk-QBTAJ2YI.js";var C=T(ge());var X=T(ge());var W=T(ge());var Mt=T(ge());var ie=T(D()),Et=60,Kt=72,ze=(0,Mt.memo)(({data:a})=>{let c=Ie(a.type),f=Math.min(12+Math.sqrt(a.subAgentCount)*10,48);return(0,ie.jsxs)("div",{style:{display:"flex",flexDirection:"column",alignItems:"center"},children:[(0,ie.jsx)(_e,{type:"target",position:Ve.Top,style:{left:"50%",top:"50%",transform:"translate(-50%, -50%)",background:"transparent",border:"none",width:0,height:0},isConnectable:!1}),(0,ie.jsx)("div",{title:a.label,style:{width:f,height:f,borderRadius:"50%",background:De(c.color),display:"flex",alignItems:"center",justifyContent:"center",color:"#fff",fontSize:Math.max(10,f*.4),fontWeight:600,cursor:"pointer",boxShadow:"0 2px 8px rgba(0,0,0,0.15)"},children:a.label.charAt(0).toUpperCase()}),(0,ie.jsx)("div",{style:{fontSize:11,maxWidth:120,textAlign:"center",whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis",marginTop:4},children:a.label}),(0,ie.jsx)(_e,{type:"source",position:Ve.Top,style:{left:"50%",top:"50%",transform:"translate(-50%, -50%)",background:"transparent",border:"none",width:0,height:0},isConnectable:!1})]})});ze.displayName="AgentGraphNode";var Q=T(D()),tn=({assistants:a,onNodeClick:c})=>{let[f,A,d]=Ct([]),[g,i,e]=At([]),[l,I]=(0,W.useState)(null),m=(0,W.useMemo)(()=>({agent:ze}),[]),R=(0,W.useMemo)(()=>Tt(a),[a]);(0,W.useEffect)(()=>{let u=R.nodes.map(o=>({id:o.id})),P=R.edges.map(o=>({source:o.source,target:o.target})),M=new Map(R.nodes.map(o=>[o.id,o])),_=mt(u).force("link",pt(P).id(o=>o.id).distance(80)).force("charge",ut().strength(-220)).force("center",dt(0,0)).force("collide",gt(45)).stop();for(let o=0;o<300;o++)_.tick();let q=u.map(o=>({id:o.id,type:"agent",data:M.get(o.id),position:{x:o.x-Et/2,y:o.y-Kt/2}})),r=R.edges.map(o=>({id:`e${o.source}-${o.target}`,source:o.source,target:o.target,style:{stroke:"#1677ff",strokeWidth:2},type:"straight"}));A(q),i(r)},[R,A,i]);let U=(0,W.useMemo)(()=>l===null?f:f.map(u=>{let P=u.id===l||g.some(M=>M.source===l&&M.target===u.id||M.target===l&&M.source===u.id);return{...u,style:{opacity:P?1:.2,transition:"opacity 0.2s ease"}}}),[f,g,l]),y=(0,W.useMemo)(()=>l===null?g.map(u=>({...u,style:{stroke:"#1677ff",strokeWidth:1.5,opacity:.25,transition:"opacity 0.2s ease"}})):g.map(u=>{let P=u.source===l||u.target===l;return{...u,style:{stroke:"#1677ff",strokeWidth:P?2.5:1,opacity:P?1:.04,transition:"opacity 0.2s ease"}}}),[g,l]);return(0,Q.jsx)("div",{style:{width:"100%",height:"100%",background:"#fafafa",position:"relative"},children:(0,Q.jsxs)(ht,{nodes:U,edges:y,onNodesChange:d,onEdgesChange:e,onNodeMouseEnter:(u,P)=>I(P.id),onNodeMouseLeave:()=>I(null),onNodeClick:(u,P)=>c?.(String(P.id)),nodeTypes:m,fitView:!0,fitViewOptions:{padding:.25},children:[(0,Q.jsx)(bt,{color:"#eee",gap:20}),(0,Q.jsx)(kt,{})]})})},Bt=a=>(0,Q.jsx)(yt,{children:(0,Q.jsx)(tn,{...a})});var w=T(D()),nn=[{key:"all",labelKey:"governance.list.tab.all"},{key:"capability",labelKey:"governance.list.tab.capability"},{key:"orchestrator",labelKey:"governance.list.tab.orchestrator"},{key:"workflow",labelKey:"governance.list.tab.workflow"}],Lt=({items:a,assistants:c=[],loading:f,onItemClick:A,onOpenPlayground:d,onOpenEval:g,onCreate:i,onDelete:e})=>{let l=z(),[I,m]=(0,X.useState)("all"),[R,U]=(0,X.useState)(null),[y,u]=(0,X.useState)(null),P=(0,X.useMemo)(()=>{let r=new Set;return a.forEach(o=>o.tags.forEach(te=>r.add(te))),Array.from(r).map(o=>({value:o,label:o}))},[a]),M=(0,X.useMemo)(()=>a.filter(r=>!(I!=="all"&&r.type!==I||R&&!r.tags.includes(R)||y&&r.status!==y)),[a,I,R,y]),_=[{key:"edit",icon:st,label:l("common.edit"),onClick:r=>A(r.id)},{key:"playground",icon:tt,label:l("governance.list.action.playground"),onClick:r=>d(r.id)},{key:"eval",icon:at,label:l("governance.list.action.eval"),onClick:r=>g(r.id)}];e&&_.push({key:"delete",icon:rt,label:l("common.delete"),danger:!0,onClick:r=>e(r.id)});let q=(0,X.useMemo)(()=>[{mode:"graph",icon:it,label:l("governance.list.viewMode.graph"),render:()=>(0,w.jsx)(Bt,{assistants:c,onNodeClick:A})}],[c,A,l]);return(0,w.jsxs)(w.Fragment,{children:[(0,w.jsx)("span",{"data-testid":"agent-list-state","data-loading":String(f),"data-count":M.length,hidden:!0,"aria-hidden":"true"}),(0,w.jsx)(ct,{title:l("governance.list.title"),itemName:"common.item.agent",items:M,loading:f,keyExtractor:r=>r.id,tabs:nn.map(r=>({key:r.key,label:l(r.labelKey)})),activeTab:I,onTabChange:r=>m(r),headerLeft:(0,w.jsxs)("div",{style:{display:"flex",gap:8,alignItems:"center"},children:[(0,w.jsx)(Oe,{value:R,onChange:U,options:P,placeholder:l("governance.list.filter.domain"),allLabel:l("governance.list.filter.allDomains")}),(0,w.jsx)(Oe,{value:y,onChange:u,options:[{value:"enabled",label:l("governance.list.status.enabled")},{value:"draft",label:l("governance.list.status.draft")},{value:"disabled",label:l("governance.list.status.disabled")}],placeholder:l("governance.list.filter.status"),allLabel:l("governance.list.filter.allStatuses")})]}),renderIcon:r=>{let o=De(Ie(r.type).color);return(0,w.jsx)("div",{title:l("governance.list.typeIconTitle",{type:r.type}),style:{width:32,height:32,borderRadius:8,background:`${o}1A`,color:o,display:"flex",alignItems:"center",justifyContent:"center",flexShrink:0},children:(0,w.jsx)(Te,{size:18})})},renderPrimary:r=>(0,w.jsx)("span",{"data-testid":"agent-name","data-agent-id":r.id,children:r.name}),renderSecondary:r=>r.description||void 0,renderDetails:r=>(0,w.jsxs)("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",gap:8,flexWrap:"wrap"},children:[(0,w.jsxs)("div",{style:{display:"flex",gap:4,flexWrap:"wrap",alignItems:"center"},children:[r.tags.map(o=>(0,w.jsx)(we,{color:"magenta",style:{margin:0,borderRadius:10,border:"none"},children:o},o)),(0,w.jsx)(we,{color:Ie(r.type).color,style:{margin:0,borderRadius:10,border:"none"},children:r.type})]}),(0,w.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:8,flexShrink:0},children:[(0,w.jsx)(Ue,{title:l("governance.list.statusTooltip",{status:r.status}),children:(0,w.jsx)("span",{style:{width:8,height:8,borderRadius:"50%",background:xt(r.status),display:"inline-block",cursor:"help"}})}),(0,w.jsx)("span",{style:{fontSize:12,color:"#8c8c8c"},children:r.version})]})]}),itemActions:_,actionsStyle:"icon",actionsPosition:"hover",onItemClick:r=>A(r.id),createLabel:l("governance.list.create"),onCreateClick:i,viewModeExtensions:q,emptyIcon:(0,w.jsx)(Te,{size:48,style:{opacity:.5}}),emptyTitle:l("governance.list.emptyTitle"),emptyDescription:l("governance.list.emptyDescription")})]})};var b=T(ge());var se=T(ge());var ue=T(D()),{Text:an}=J,Nt=({onSelect:a,value:c,placeholder:f})=>{let A=z(),d=f??A("chatConfig.parentAgent.selectPlaceholder"),[g,i]=(0,se.useState)([]),[e,l]=(0,se.useState)(!1),{get:I}=me(),m=(0,se.useCallback)(async()=>{l(!0);try{let y=await I("/api/assistants");y.success&&i(y.data?.records||[])}catch(y){console.error("Failed to fetch assistants:",y)}finally{l(!1)}},[I]);return(0,se.useEffect)(()=>{m()},[m]),(0,ue.jsx)(xe,{showSearch:!0,allowClear:!0,value:c,placeholder:d,loading:e,onChange:y=>{if(!y){a(null);return}let u=g.find(P=>P.id===y);a(u||null)},onDropdownVisibleChange:y=>{y&&m()},optionFilterProp:"label",style:{width:"100%"},options:g.map(y=>({value:y.id,label:y.name||y.id,description:y.description})),optionRender:y=>(0,ue.jsxs)("div",{children:[(0,ue.jsx)("div",{children:y.label}),y.data.description&&(0,ue.jsx)(an,{type:"secondary",style:{fontSize:12},children:y.data.description})]})})};var B=T(D()),{Text:Ot}=J,Vt=({subAgentKeys:a,decisions:c,onChange:f})=>{let{token:A}=Ze.useToken(),d=z(),g=(e,l)=>{let I=c.map(m=>m.originalKey===e?{...m,clone:l,cloneKey:l?`${e}_clone`:void 0}:m);f(I)},i=(e,l)=>{let I=c.map(m=>m.originalKey===e?{...m,cloneKey:l}:m);f(I)};return a.length===0?null:(0,B.jsxs)("div",{children:[(0,B.jsx)(Ot,{type:"secondary",style:{display:"block",marginBottom:8},children:d("chatConfig.subAgentInherit.hint")}),(0,B.jsx)(Ne,{size:"small",bordered:!0,dataSource:c,style:{borderRadius:A.borderRadius},renderItem:e=>(0,B.jsxs)(Ne.Item,{style:{display:"flex",flexDirection:"column",alignItems:"stretch",gap:8,padding:"8px 16px"},children:[(0,B.jsxs)("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[(0,B.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.clone?(0,B.jsx)(Re,{style:{color:A.colorPrimary}}):(0,B.jsx)(Xe,{style:{color:A.colorTextSecondary}}),(0,B.jsx)(Ot,{style:{fontFamily:"monospace"},children:e.originalKey})]}),(0,B.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:8},children:[(0,B.jsx)(we,{color:e.clone?"blue":"default",children:e.clone?d("chatConfig.subAgentInherit.clone"):d("chatConfig.subAgentInherit.reuse")}),(0,B.jsx)(We,{size:"small",checked:e.clone,onChange:l=>g(e.originalKey,l)})]})]}),e.clone&&(0,B.jsx)(O,{size:"small",placeholder:d("chatConfig.subAgentInherit.cloneKeyPlaceholder"),value:e.cloneKey,onChange:l=>i(e.originalKey,l.target.value),style:{fontFamily:"monospace",fontSize:12},addonBefore:d("chatConfig.keyValue.key")})]})})]})};function _t(a,c){return a.mode!=="local"||a.templateKey||typeof a.executable=="string"&&a.executable.trim().length>0?null:c?c("chat.config.executableRequired"):"Choose a template or enter a custom executable"}var n=T(D()),{TextArea:Gt}=O,{Text:ee}=J,zt="/.well-known/agent-card.json",on=[{value:"http://",label:"http://"},{value:"https://",label:"https://"}],sn={react:"chatConfig.createAssistant.typeDesc.react",deep_agent:"chatConfig.createAssistant.typeDesc.deepAgent",a2a_remote:"chatConfig.createAssistant.typeDesc.a2aRemote"};function jt(a,c,f="https://"){let A=String(a??"").trim();if(!A)return"";let d=c==="http://"||c==="https://"?c:f,i=(/^https?:\/\//i.test(A)?A:`${d}${A.replace(/^\/+/,"")}`).replace(/\/+$/,"");return i.endsWith(zt)?i:`${i}${zt}`}function rn(a){try{return new URL(a).port||void 0}catch{return}}function ln(a){return a.some(c=>c==="--port"||c==="-p"||/^--port=/.test(c)||/^-p=/.test(c))}function Ut(a,c){let f=[...a.args],A=rn(c);return A&&!ln(f)&&f.push("--port",A),{...a,args:f,...a.env?{env:{...a.env}}:{}}}var qt=({open:a,onCancel:c,onSuccess:f,initialMode:A,initialValues:d})=>{let{message:g}=Fe.useApp(),[i]=F.useForm(),e=z(),[l,I]=(0,b.useState)(!1),[m,R]=(0,b.useState)("learn"),[U,y]=(0,b.useState)(""),[u,P]=(0,b.useState)(null),[M,_]=(0,b.useState)([]),q=F.useWatch("type",i)||"react",r=q==="a2a_remote",[o,te]=(0,b.useState)("remote"),[H,fe]=(0,b.useState)(void 0),[re,ye]=(0,b.useState)([]),[Se,le]=(0,b.useState)(!1),ne=(0,b.useRef)(0),[ae,oe]=(0,b.useState)(!1),[Me,Z]=(0,b.useState)(!1),{get:L,post:Y,put:he}=me(),Ee=Ye("agent-architect"),{workspaceId:Ce,trainingProjects:ce,loading:de}=lt(),[Ke,Ae]=(0,b.useState)(null),Be=JSON.stringify(d??null),E=ce.find(t=>t.id===Ke)??ce[0]??null,[be,ke]=(0,b.useState)([]),p=(0,b.useCallback)(()=>{P(null),_([])},[]),k=(0,b.useCallback)(()=>{i.resetFields(),p(),R("learn"),y(""),ke([]),Ae(null),te("remote"),fe(void 0),ye([]),Z(!1),oe(!1)},[i,p]);(0,b.useEffect)(()=>{if(a){k(),R(A??"learn");let t=d?.a2aMode;(t==="remote"||t==="local")&&te(t),i.setFieldsValue({type:"react",agentCardProtocol:"https://",a2aMode:"remote",timeout:3e5,...d})}},[a,i,A,Be,k]),(0,b.useEffect)(()=>{let t=++ne.current,s=!0;return a&&r?(i.setFieldValue("prompt",""),o==="local"?(le(!0),L("/api/local-a2a/templates").then(v=>{s&&t===ne.current&&v?.data?.records&&ye(v.data.records)}).catch(()=>{s&&t===ne.current&&ye([])}).finally(()=>{s&&t===ne.current&&le(!1)})):le(!1)):le(!1),()=>{s=!1,ne.current+=1}},[i,r,o,L,a]);let x=re.find(t=>t.key===H),j=(0,b.useCallback)(()=>{let t=_t({mode:o,templateKey:H,executable:i.getFieldValue("commandExecutable")},e);return t?(Z(!0),i.setFields([{name:"commandExecutable",errors:[t]}]),g.warning(t),!1):!0},[o,H,i,e]);(0,b.useEffect)(()=>{x&&i.setFieldsValue({agentCardProtocol:"http://"})},[i,x]);let ve=(0,b.useCallback)(async()=>{if(!j())return;let t=jt(i.getFieldValue("agentCardUrl"),i.getFieldValue("agentCardProtocol"),o==="local"?"http://":"https://");if(!t){g.warning(e("chatConfig.createAssistant.a2aUrlWarning"));return}oe(!0);try{let s={agentCardUrl:t,apiKey:i.getFieldValue("apiKey")};if(o==="local"){let h=x;if(h)s.localRuntime={label:i.getFieldValue("name")||void 0,agentCardUrl:t,command:Ut(h.command,t)};else{let K=i.getFieldValue("commandArgs")||"",G=K?K.split(/\s+/).filter(Boolean):[],S=String(i.getFieldValue(["command","cwd"])||"").trim();s.localRuntime={label:i.getFieldValue("name")||void 0,agentCardUrl:t,command:{executable:String(i.getFieldValue("commandExecutable")||"").trim(),args:G,...S?{cwd:S}:{}}}}}let v=await Y("/api/a2a/test-connection",s);if(v.data?.reachable){let h=v.data.agentCard;g.success(e("chatConfig.createAssistant.connectedTo",{name:v.data.agentName||t}))}else g.error(v.data?.error||e("chatConfig.createAssistant.connectionFailed"))}catch{g.error(e("chatConfig.createAssistant.connectionTestFailed"))}finally{oe(!1)}},[i,Y,o,x,j,e]),Wt=(0,b.useCallback)(t=>{if(P(t),!t){i.resetFields(["key","name","description","type","prompt"]),_([]);return}let s=typeof t.graphDefinition=="object"&&t.graphDefinition!==null?t.graphDefinition:{},v=s.key||t.id,h=t.name||s.name||"";i.setFieldsValue({key:`${v}_ext`,name:h?`${h} (Extended)`:"",description:t.description||s.description||"",type:s.type||"react",prompt:s.prompt||""});let K=s.subAgents||[];_(K.map(G=>({originalKey:G,clone:!1})))},[i]),Zt=async(t,s)=>{let v=await L(`/api/assistants/${t}`);if(!v.success)throw new Error(e("chatConfig.createAssistant.cloneFetchFailed",{key:t}));let h=v.data,K=typeof h.graphDefinition=="object"?h.graphDefinition:{},G={id:s,name:`${h.name} (Clone)`,description:h.description||"",graphDefinition:{...K,key:s,name:`${h.name} (Clone)`}},S=await Y("/api/assistants",G);if(!S.success)throw new Error(S.message||e("chatConfig.createAssistant.cloneFailed",{key:t}));return S.data},Yt=t=>{let s={id:t.key,name:t.name,description:t.description||"",graphDefinition:{key:t.key,name:t.name,description:t.description||"",type:t.type,prompt:t.prompt||"",tools:[],skills:[],subAgents:t.type==="deep_agent"?[]:void 0,middleware:[]}};if(t.type==="a2a_remote"&&(s.graphDefinition.agentCardUrl=jt(t.agentCardUrl,t.agentCardProtocol,(t.a2aMode||o)==="local"?"http://":"https://"),t.apiKey&&(s.graphDefinition.apiKey=t.apiKey),t.timeout&&(s.graphDefinition.timeout=t.timeout),(t.a2aMode||o)==="local")){let v=x;if(v)s.graphDefinition.localRuntime={label:t.name||void 0,agentCardUrl:s.graphDefinition.agentCardUrl,command:Ut(v.command,s.graphDefinition.agentCardUrl)};else{let h=t.commandArgs||"",K=h?h.split(/\s+/).filter(Boolean):[],G=String(t.command?.cwd||"").trim();s.graphDefinition.localRuntime={label:t.name||void 0,agentCardUrl:s.graphDefinition.agentCardUrl,command:{executable:String(t.commandExecutable||"").trim(),args:K,...G?{cwd:G}:{}}}}}return s},Jt=async(t,s)=>{if(!u)throw new Error(e("chatConfig.createAssistant.noParentAgent"));let v=M.filter(S=>S.clone);for(let S of v){if(!S.cloneKey||!S.cloneKey.trim())throw new Error(e("chatConfig.createAssistant.cloneKeyRequired",{key:S.originalKey}));if(!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(S.cloneKey))throw new Error(e("chatConfig.createAssistant.cloneKeyInvalid",{key:S.cloneKey,originalKey:S.originalKey}))}let h=[];for(let S of M)if(S.clone){let en=await Zt(S.originalKey,S.cloneKey);s.push(en),h.push(S.cloneKey)}else h.push(S.originalKey);let K=typeof u.graphDefinition=="object"?u.graphDefinition:{},G={key:t.key,name:t.name,description:t.description||"",extendsAgent:u.id,type:t.type||K.type};return t.prompt&&t.prompt!==K.prompt&&(G.prompt=t.prompt),(h.length>0||K.subAgents&&K.subAgents.length>0)&&(G.subAgents=h),{id:t.key,name:t.name,description:t.description||"",graphDefinition:G}},Qt=async()=>{if(m==="learn"){let t=U.trim();if(!t){g.error(e("chatConfig.createAssistant.trainingGoalRequired"));return}if(!E){g.error(e("chatConfig.createAssistant.noTrainingProject"));return}I(!0);try{let s=`agent-${St(t+Date.now())}`,v=await Y("/api/assistants",{id:s,name:s,graphDefinition:{key:s,name:s,description:"",type:"react",prompt:"To be trained",metadata:{trainingProjectId:E.id,learningPlaceholder:"true",architectureStatus:"undecided"}}});if(!v.data)throw new Error(e("chatConfig.createAssistant.agentCreateFailed"));let{roundTaskId:h}=await Pt({goal:t,targetAgentId:s,workspaceId:Ce??void 0,projectId:E.id,existingThreadId:Ft(Ee.tenantId,s),files:be,post:Y,put:he});g.success(e("chatConfig.createAssistant.agentCreated")),y(""),ke([]),R("learn"),f?.(v.data,{initialMessage:Rt({goal:t,roundTaskId:h,targetAgentId:s,targetMode:"placeholder",files:be,projectId:E.id,workspaceId:E.workspaceId??Ce??void 0}),projectId:E.id,initialMessageCustomRunConfig:{execution:{taskId:h}}}),c()}catch(s){g.error(s instanceof Error?s.message:e("chatConfig.createAssistant.agentCreateFailed"))}finally{I(!1)}return}try{if(m==="scratch"&&r&&!j())return;let t=await i.validateFields();I(!0);let s=[],v=m==="scratch"?Yt(t):await Jt(t,s),h=await Y("/api/assistants",v);if(h.success){g.success(m==="extend"?e("chatConfig.createAssistant.createdByExtending",{name:u?.name??""}):e("chatConfig.createAssistant.created")),k();for(let K of s)f?.(K);f?.(h.data),c()}else g.error(h.message||e("chatConfig.createAssistant.createFailed"))}catch(t){if(t?.errorFields){let s={key:e("chatConfig.createAssistant.field.key"),name:e("chatConfig.createAssistant.field.name"),description:e("chatConfig.createAssistant.field.description"),prompt:e("chatConfig.createAssistant.field.systemPrompt")},v=t.errorFields.map(h=>s[String((h.name??[])[0])]??String((h.name??[])[0])).filter(Boolean);g.warning(v.length>0?e("chatConfig.createAssistant.requiredFields",{fields:[...new Set(v)].join(", ")}):e("chatConfig.createAssistant.requiredFieldsGeneric"));return}g.error(t.message||e("chatConfig.createAssistant.createError"))}finally{I(!1)}},je=u?.graphDefinition?.subAgents||[],Xt=m==="extend"&&u&&je.length>0;return(0,n.jsxs)(pe,{title:e("chatConfig.createAssistant.title"),open:a,onCancel:()=>{k(),c()},footer:[(0,n.jsx)($,{onClick:()=>{k(),c()},children:e("common.cancel")},"cancel"),(0,n.jsx)($,{type:"primary",icon:m==="extend"?(0,n.jsx)(Re,{}):m==="learn"?(0,n.jsx)(Qe,{}):(0,n.jsx)(et,{}),loading:l,disabled:m==="learn"&&(de||!E),onClick:Qt,children:e(m==="extend"?"chatConfig.createAssistant.createExtend":m==="learn"?"chatConfig.createAssistant.startLearning":"common.create")},"submit")],width:760,children:[m==="extend"&&(0,n.jsxs)("div",{style:{marginBottom:20},children:[(0,n.jsx)(ee,{type:"secondary",style:{display:"block",marginBottom:8},children:e("chatConfig.createAssistant.parentAgent")}),(0,n.jsx)(Nt,{value:u?.id,onSelect:Wt}),u&&(0,n.jsx)(ee,{type:"secondary",style:{display:"block",marginTop:4,fontSize:12},children:e("chatConfig.createAssistant.inheritHint")})]}),m==="extend"&&u&&(0,n.jsx)(Le,{style:{margin:"12px 0"}}),m==="learn"&&(0,n.jsxs)("div",{children:[(0,n.jsx)(ee,{style:{display:"block",marginBottom:8},children:e("chatConfig.createAssistant.learnHint")}),(0,n.jsx)(O.TextArea,{rows:3,value:U,onChange:t=>y(t.target.value),placeholder:e("chatConfig.createAssistant.learnGoalPlaceholder")}),E&&(0,n.jsxs)("div",{style:{marginTop:12},children:[(0,n.jsxs)("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:12,marginBottom:8},children:[(0,n.jsx)(ee,{type:"secondary",children:e("chatConfig.createAssistant.referenceFiles")}),(0,n.jsx)(Ge,{project:E,value:E?.id??null,onChange:Ae,loading:de})]}),(0,n.jsx)(It,{projectId:E.id,value:be,onChange:ke}),(0,n.jsx)(ee,{type:"secondary",style:{display:"block",marginTop:6,fontSize:12},children:e("chatConfig.createAssistant.referenceFilesHint")})]}),!E&&!de&&(0,n.jsx)("div",{style:{marginTop:12},children:(0,n.jsx)(Ge,{project:E,value:null,onChange:Ae,loading:de})})]}),m!=="learn"&&(0,n.jsxs)(F,{form:i,layout:"vertical",autoComplete:"off",initialValues:{type:"react",agentCardProtocol:"https://",a2aMode:"remote"},children:[(0,n.jsx)(F.Item,{name:"key",label:e("chatConfig.createAssistant.field.key"),rules:[{required:!0,message:e("chatConfig.createAssistant.validation.keyRequired")},{pattern:/^[a-zA-Z][a-zA-Z0-9_-]*$/,message:e("chatConfig.createAssistant.validation.keyPattern")}],style:{marginBottom:16},children:(0,n.jsx)(O,{placeholder:e("chatConfig.createAssistant.keyPlaceholder")})}),(0,n.jsx)(F.Item,{name:"name",label:e("chatConfig.createAssistant.field.name"),rules:[{required:!0,message:e("chatConfig.createAssistant.validation.nameRequired")}],style:{marginBottom:16},children:(0,n.jsx)(O,{placeholder:e("chatConfig.createAssistant.namePlaceholder")})}),(0,n.jsx)(F.Item,{name:"description",label:e("chatConfig.createAssistant.field.description"),rules:[{required:!0,message:e("chatConfig.createAssistant.validation.descriptionRequired")}],style:{marginBottom:16},children:(0,n.jsx)(Gt,{placeholder:e("chatConfig.createAssistant.descriptionPlaceholder"),autoSize:{minRows:2,maxRows:4}})}),(0,n.jsx)(F.Item,{name:"type",label:e("chatConfig.createAssistant.field.agentType"),rules:[{required:!0}],style:{marginBottom:16},children:(0,n.jsx)(qe,{options:[{value:"react",label:e("chatConfig.agentType.executor")},{value:"deep_agent",label:e("chatConfig.agentType.orchestrator")},{value:"a2a_remote",label:e("chatConfig.agentType.a2aRemote")}],block:!0})}),(0,n.jsx)(ee,{type:"secondary",style:{fontSize:12,display:"block",marginTop:-12,marginBottom:16,lineHeight:1.5},children:e(sn[q]??"chatConfig.createAssistant.typeDesc.react")}),r&&(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(F.Item,{label:e("chatConfig.createAssistant.field.connectionMode"),style:{marginBottom:16},children:(0,n.jsxs)(Pe.Group,{value:o,onChange:t=>{let s=t.target.value;te(s),i.setFieldValue("a2aMode",s),s==="local"&&i.setFieldValue("agentCardProtocol","http://"),fe(void 0)},optionType:"button",buttonStyle:"solid",children:[(0,n.jsx)(Pe.Button,{value:"remote",children:e("chatConfig.createAssistant.mode.remoteUrl")}),(0,n.jsx)(Pe.Button,{value:"local",children:e("chatConfig.createAssistant.mode.localManaged")})]})}),(0,n.jsx)(F.Item,{name:"a2aMode",noStyle:!0,hidden:!0,children:(0,n.jsx)(O,{})}),o==="local"&&(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(F.Item,{label:e("chatConfig.createAssistant.field.template"),style:{marginBottom:16},children:(0,n.jsx)(xe,{placeholder:e("chatConfig.createAssistant.templatePlaceholder"),allowClear:!0,loading:Se,value:H,onChange:t=>{fe(t),t&&Z(!1)},options:re.map(t=>({value:t.key,label:t.name||t.key})),notFoundContent:Se?void 0:(0,n.jsx)(ee,{type:"secondary",style:{padding:8,display:"block"},children:e("chatConfig.createAssistant.noTemplates")})})}),!H&&(0,n.jsx)(n.Fragment,{children:Me?(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(F.Item,{name:"commandExecutable",label:e("chatConfig.createAssistant.field.executable"),rules:[{required:!0,whitespace:!0,message:e("chatConfig.createAssistant.validation.executableRequired")}],style:{marginBottom:16},children:(0,n.jsx)(O,{placeholder:e("chatConfig.createAssistant.executablePlaceholder")})}),(0,n.jsx)(F.Item,{name:"commandArgs",label:e("chatConfig.createAssistant.field.arguments"),style:{marginBottom:16},children:(0,n.jsx)(O,{placeholder:e("chatConfig.createAssistant.argumentsPlaceholder")})}),(0,n.jsx)(F.Item,{name:["command","cwd"],label:e("chatConfig.createAssistant.field.workingDirectory"),style:{marginBottom:16},children:(0,n.jsx)(O,{placeholder:e("chatConfig.createAssistant.workingDirectoryPlaceholder")})}),(0,n.jsx)($,{type:"link",onClick:()=>{Z(!1),i.setFieldsValue({commandExecutable:"",commandArgs:"",command:{cwd:void 0}})},style:{padding:0,marginBottom:16,display:"block"},children:e("chatConfig.createAssistant.hideCustomCommand")})]}):(0,n.jsx)($,{type:"link",onClick:()=>Z(!0),style:{padding:0,marginBottom:16,display:"block"},children:e("chatConfig.createAssistant.customCommand")})})]}),(0,n.jsx)(F.Item,{label:e("chatConfig.createAssistant.field.agentCardUrl"),required:!0,style:{marginBottom:16},children:(0,n.jsxs)($e.Compact,{style:{width:"100%"},children:[(0,n.jsx)(F.Item,{name:"agentCardProtocol",noStyle:!0,children:(0,n.jsx)(xe,{style:{width:100},options:on})}),(0,n.jsx)(F.Item,{name:"agentCardUrl",noStyle:!0,rules:[{required:!0,message:e("chatConfig.createAssistant.validation.urlRequired")}],children:(0,n.jsx)(O,{placeholder:o==="local"?"localhost:4301":"host:port or full URL"})}),(0,n.jsx)($,{icon:(0,n.jsx)(Je,{}),onClick:ve,loading:ae,children:e("chatConfig.connection.action.test")})]})}),o==="remote"&&(0,n.jsx)(F.Item,{name:"apiKey",label:e("chatConfig.createAssistant.field.apiKeyOptional"),style:{marginBottom:16},children:(0,n.jsx)(O.Password,{placeholder:e("chatConfig.createAssistant.apiKeyPlaceholder")})}),(0,n.jsx)(F.Item,{name:"timeout",label:e("chatConfig.createAssistant.field.timeout"),style:{marginBottom:16},initialValue:3e5,children:(0,n.jsx)(He,{min:1e3,max:36e5,style:{width:"100%"},placeholder:"300000"})})]}),!r&&(0,n.jsx)(F.Item,{name:"prompt",label:e(m==="extend"&&u?"chatConfig.createAssistant.field.systemPromptInherit":"chatConfig.createAssistant.field.systemPrompt"),rules:m==="scratch"?[{required:!0,message:e("chatConfig.createAssistant.validation.systemPromptRequired")}]:[],children:(0,n.jsx)(Gt,{placeholder:e(m==="extend"&&u?"chatConfig.createAssistant.systemPromptInheritPlaceholder":"chatConfig.createAssistant.systemPromptPlaceholder"),autoSize:{minRows:4,maxRows:8},style:{fontFamily:"monospace",fontSize:13,lineHeight:1.6}})})]}),Xt&&(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(Le,{style:{margin:"12px 0"}}),(0,n.jsx)(ee,{strong:!0,style:{display:"block",marginBottom:8},children:e("chatConfig.createAssistant.subAgents")}),(0,n.jsx)(Vt,{subAgentKeys:je,decisions:M,onChange:_})]})]})};var N=T(D()),{Paragraph:cn,Text:Ht}=J,dn=[{key:"manual",icon:Te,titleKey:"governance.creation.manual.title",descriptionKey:"governance.creation.manual.description"},{key:"external",icon:nt,titleKey:"governance.creation.external.title",descriptionKey:"governance.creation.external.description"},{key:"learn",icon:ot,titleKey:"governance.creation.learn.title",descriptionKey:"governance.creation.learn.description"}],$t=({open:a,onCancel:c,onSelectMethod:f,focusTriggerAfterClose:A=!0})=>{let d=z();return(0,N.jsx)(pe,{title:d("governance.creation.title"),open:a,onCancel:c,footer:null,width:560,centered:!0,destroyOnHidden:!0,focusTriggerAfterClose:A,children:(0,N.jsxs)("div",{style:{padding:"8px 4px 4px"},children:[(0,N.jsx)(cn,{style:{color:"#595959",fontSize:15,margin:"8px 0 24px"},children:d("governance.creation.subtitle")}),(0,N.jsx)("div",{style:{display:"flex",flexDirection:"column",gap:12},children:dn.map(g=>{let i=g.icon,e=d(g.titleKey);return(0,N.jsxs)($,{type:"default",onClick:()=>f(g.key),"aria-label":e,style:{display:"flex",flexDirection:"row",alignItems:"center",justifyContent:"flex-start",gap:16,width:"100%",minHeight:88,height:"auto",padding:16,borderRadius:16,textAlign:"left",whiteSpace:"normal"},children:[(0,N.jsx)("div",{style:{width:40,height:40,borderRadius:12,display:"flex",alignItems:"center",justifyContent:"center",flexShrink:0,color:"#6366f1",background:"#eeeeff"},children:(0,N.jsx)(i,{size:19})}),(0,N.jsxs)("div",{style:{minWidth:0},children:[(0,N.jsx)(Ht,{strong:!0,style:{display:"block",fontSize:15,marginBottom:3},children:e}),(0,N.jsx)(Ht,{style:{color:"#737373",lineHeight:1.5},children:d(g.descriptionKey)})]})]},g.key)})}),(0,N.jsx)("div",{style:{display:"flex",justifyContent:"flex-end",gap:8,flexWrap:"wrap",marginTop:24},children:(0,N.jsx)($,{onClick:c,children:d("governance.creation.notNow")})})]})})};var V=T(D()),gn=a=>{let c=a;if(typeof a=="string")try{c=JSON.parse(a)}catch{return{}}return c!==null&&typeof c=="object"&&!Array.isArray(c)?c:{}},va=()=>{let{message:a}=Fe.useApp(),{get:c,del:f,put:A}=me(),d=z(),[g,i]=(0,C.useState)([]),[e,l]=(0,C.useState)(!1),[I,m]=(0,C.useState)(null),[R,U]=(0,C.useState)("graph"),[y,u]=(0,C.useState)(null),[P,M]=(0,C.useState)(null),[_,q]=(0,C.useState)(null),[r,o]=(0,C.useState)(!1),[te,H]=(0,C.useState)(!0),[fe,re]=(0,C.useState)(!1),[ye,Se]=(0,C.useState)("learn"),[le,ne]=(0,C.useState)({}),[ae,oe]=(0,C.useState)(null),[Me,Z]=(0,C.useState)(!1),L=(0,C.useCallback)(async()=>{l(!0);try{let p=await c("/api/assistants");p.success&&p.data?.records&&i(p.data.records)}catch{a.error(d("governance.workbench.loadFailed"))}finally{l(!1)}},[c,d]);(0,C.useEffect)(()=>{L()},[L]);let Y=C.default.useMemo(()=>wt(g),[g]),he=g.find(p=>p.id===I)??null,Ee=(0,C.useCallback)((p,k="graph")=>{m(p),U(k),u(null),q(null)},[]),Ce=ft(),ce=(0,C.useCallback)((p,k)=>{let x=g.find(j=>j.id===p)?.name??d("governance.workbench.agentFallback");Ce({component_key:"agent_detail_side_app",data:{assistantId:p,initialTab:k},message:x})},[g,Ce,d]),de=(0,C.useCallback)(()=>{H(!0),o(!0)},[]),Ke=(0,C.useCallback)(p=>{let x={manual:{mode:"scratch",values:{}},external:{mode:"scratch",values:{type:"a2a_remote"}},learn:{mode:"learn",values:{}}}[p];Se(x.mode),ne(x.values),H(!1),o(!1),re(!0)},[]),Ae=(0,C.useCallback)(async(p,k)=>{let x=gn(p.graphDefinition),j;try{j=await A(`/api/assistants/${p.id}`,{name:k.name!==void 0?k.name:p.name,description:k.description!==void 0?k.description:p.description,graphDefinition:{...x,...k}})}catch(ve){throw a.error(d("governance.detail.saveFailed")),ve}if(!j.success)throw a.error(d("governance.detail.saveFailed")),new Error("Failed to save agent");a.success(d("common.saved")),L()},[A,L,d]),Be=(0,C.useCallback)(p=>{i(k=>k.map(x=>x.id===p.id?p:x))},[]),E=(0,C.useCallback)(p=>{oe(p)},[]),be=(0,C.useCallback)(async()=>{if(ae){Z(!0);try{(await f(`/api/assistants/${ae}`)).success?(a.success(d("governance.detail.deleted")),i(k=>k.filter(x=>x.id!==ae)),L(),oe(null)):a.error(d("governance.detail.deleteFailed"))}catch{a.error(d("governance.detail.deleteFailed"))}finally{Z(!1)}}},[ae,f,L,d]),ke=(0,C.useCallback)(async p=>{if(!(await f(`/api/assistants/${p}`)).success)throw new Error("Failed to delete agent");a.success(d("governance.detail.deleted")),i(x=>x.filter(j=>j.id!==p)),L()},[f,L,d]);return(0,V.jsxs)("div",{style:{height:"100%",background:"#fafafa",overflow:"hidden"},children:[he?(0,V.jsx)(vt,{defaultProjectId:_??void 0,children:(0,V.jsx)(Dt,{assistant:he,allAssistants:g,onBack:()=>m(null),onDeleted:ke,onSave:Ae,onAssistantUpdated:Be,onAgentListInvalidated:L,initialTab:R,initialMessage:y,initialMessageCustomRunConfig:P,initialProjectId:_})},he.id):(0,V.jsx)(V.Fragment,{children:(0,V.jsx)(Lt,{items:Y,assistants:g,loading:e,onItemClick:p=>ce(p,"graph"),onOpenPlayground:p=>ce(p,"playground"),onOpenEval:p=>ce(p,"eval"),onCreate:de,onDelete:E})}),(0,V.jsx)($t,{open:r,onCancel:()=>{H(!0),o(!1)},onSelectMethod:Ke,focusTriggerAfterClose:te}),(0,V.jsx)(qt,{open:fe,initialMode:ye,initialValues:le,onCancel:()=>re(!1),onSuccess:(p,k)=>{re(!1),i(x=>x.some(ve=>ve.id===p.id)?x:[p,...x]),Ee(p.id,"graph"),u(k?.initialMessage??null),M(k?.initialMessageCustomRunConfig??null),q(k?.projectId??null),L()}}),(0,V.jsx)(pe,{title:d("governance.deleteAgent"),open:ae!==null,onCancel:()=>oe(null),onOk:be,okText:d("common.delete"),okButtonProps:{danger:!0,loading:Me},cancelText:d("common.cancel"),children:(0,V.jsx)("p",{children:d("governance.delete.irreversible")})})]})};export{va as AgentGovernanceWorkbench};
|