aws-runtime-bridge 1.9.189 → 1.9.192
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/CHANGELOG.md +111 -0
- package/dist/adapter/AcodeSdkAdapter.d.ts +13 -0
- package/dist/adapter/AcodeSdkAdapter.js +3 -3
- package/dist/config.d.ts +0 -31
- package/dist/config.js +2 -2
- package/dist/index.js +1 -1
- package/dist/routes/media-files.d.ts +19 -0
- package/dist/routes/media-files.js +2 -0
- package/dist/routes/plugin-ui.d.ts +17 -0
- package/dist/routes/plugin-ui.js +2 -0
- package/dist/routes/plugins.d.ts +3 -0
- package/dist/routes/plugins.js +1 -1
- package/dist/routes/terminal.d.ts +83 -0
- package/dist/routes/terminal.js +25 -25
- package/dist/scripts/migrate-user-scopes.js +1 -1
- package/dist/services/agent-capability-sync.js +1 -1
- package/dist/services/capability-config.d.ts +0 -1
- package/dist/services/capability-config.js +2 -2
- package/dist/services/instance-ai-config-service.js +1 -1
- package/dist/services/plugin-deployment.d.ts +2 -30
- package/dist/services/plugin-deployment.js +2 -2
- package/dist/services/plugin-handler-adapter.d.ts +10 -1
- package/dist/services/plugin-handler-adapter.js +2 -2
- package/dist/services/plugin-listener-runner.js +4 -4
- package/dist/services/plugin-loader.d.ts +7 -1
- package/dist/services/plugin-loader.js +1 -1
- package/dist/services/plugin-manager.d.ts +32 -12
- package/dist/services/plugin-manager.js +4 -4
- package/dist/services/plugin-manifest.d.ts +53 -3
- package/dist/services/plugin-manifest.js +1 -1
- package/dist/services/plugin-runtime.d.ts +8 -9
- package/dist/services/plugin-ui-status-runtime.d.ts +8 -0
- package/dist/services/plugin-ui-status-runtime.js +2 -0
- package/dist/services/plugin-ui-status.d.ts +96 -0
- package/dist/services/plugin-ui-status.js +2 -0
- package/dist/services/plugin-wecom-callback.d.ts +61 -0
- package/dist/services/plugin-wecom-callback.js +3 -0
- package/dist/services/user-scope.d.ts +1 -9
- package/dist/services/user-scope.js +1 -1
- package/package/acode/dist/plugin-types.d.ts +41 -1
- package/package/acode/dist/runtime.d.ts +17 -0
- package/package/acode/dist/runtime.js +20 -20
- package/package/aws-client-agent-mcp/dist/mcp-server.js +1 -1
- package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts +15 -0
- package/package/aws-client-agent-mcp/dist/mcp-tools.js +35 -5
- package/package/aws-client-agent-mcp/dist/tool-groups.js +2 -2
- package/package.json +1 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const l=/^[a-zA-Z0-9_][a-zA-Z0-9_-]*$/,
|
|
1
|
+
const R=2,S=["puzzle","github"];function $(n){return S.includes(n)?!0:!n||n.includes("..")||n.includes("\\")||/^\//.test(n)?!1:n.startsWith("ui/")&&/\.(svg|png)$/i.test(n)}function c(n){return!n||n.includes("..")||n.includes("\\")||/^\//.test(n)?!1:n.startsWith("ui/")}const m=new Set(["icon","status","view"]),w=new Set(["tool","persistent","hideWhenZero","pollIntervalMs","title"]),E=new Set(["entry","title","assetsRoot","invoke","defaultRoute"]);function _(n){if(n===void 0)return null;if(!o(n))return"plugin.json: ui \u987B\u4E3A\u5BF9\u8C61";const t=l("plugin.json: ui",n,m);if(t)return t;if(n.icon!==void 0&&(typeof n.icon!="string"||!$(n.icon)))return"plugin.json: ui.icon \u975E\u6CD5\uFF08\u5185\u7F6E\u540D puzzle/github \u6216 ui/ \u4E0B\u7684 svg/png \u76F8\u5BF9\u8DEF\u5F84\uFF09";if(n.status!==void 0){if(!o(n.status))return"plugin.json: ui.status \u987B\u4E3A\u5BF9\u8C61";const r=l("plugin.json: ui.status",n.status,w);if(r)return r;if(typeof n.status.tool!="string"||!a.test(n.status.tool))return"plugin.json: ui.status.tool \u975E\u6CD5\uFF08\u987B\u4E3A\u672C\u63D2\u4EF6 tools \u4E2D\u7684\u5DE5\u5177\u540D\uFF09";if(n.status.pollIntervalMs!==void 0&&(typeof n.status.pollIntervalMs!="number"||n.status.pollIntervalMs<5e3||n.status.pollIntervalMs>3e5))return"plugin.json: ui.status.pollIntervalMs \u987B\u4E3A 5000~300000 \u6BEB\u79D2";if(n.status.persistent!==void 0&&typeof n.status.persistent!="boolean")return"plugin.json: ui.status.persistent \u987B\u4E3A\u5E03\u5C14";if(n.status.hideWhenZero!==void 0&&typeof n.status.hideWhenZero!="boolean")return"plugin.json: ui.status.hideWhenZero \u987B\u4E3A\u5E03\u5C14";if(n.status.title!==void 0&&typeof n.status.title!="string")return"plugin.json: ui.status.title \u987B\u4E3A\u5B57\u7B26\u4E32"}if(n.view!==void 0){if(!o(n.view))return"plugin.json: ui.view \u987B\u4E3A\u5BF9\u8C61";const r=l("plugin.json: ui.view",n.view,E);if(r)return r;if(typeof n.view.entry!="string"||!c(n.view.entry))return"plugin.json: ui.view.entry \u975E\u6CD5\uFF08\u987B\u4E3A ui/ \u4E0B\u7684\u76F8\u5BF9\u8DEF\u5F84\uFF09";if(!/\.(html)$/i.test(n.view.entry))return"plugin.json: ui.view.entry \u987B\u4E3A .html \u6587\u4EF6";if(typeof n.view.title!="string"||!n.view.title.trim())return"plugin.json: ui.view.title \u5FC5\u586B\uFF08\u529F\u80FD\u683C\u6309\u94AE/\u5F39\u7A97\u6807\u9898\uFF09";if(n.view.title.length>64)return"plugin.json: ui.view.title \u8FC7\u957F\uFF08\u226464\uFF09";if(n.view.assetsRoot!==void 0&&(typeof n.view.assetsRoot!="string"||!c(n.view.assetsRoot)))return"plugin.json: ui.view.assetsRoot \u975E\u6CD5\uFF08\u987B\u4E3A ui/ \u4E0B\u7684\u76F8\u5BF9\u8DEF\u5F84\uFF09";if(!Array.isArray(n.view.invoke))return"plugin.json: ui.view.invoke \u987B\u4E3A\u5DE5\u5177\u540D\u6570\u7EC4";for(const i of n.view.invoke)if(typeof i!="string"||!a.test(i))return`plugin.json: ui.view.invoke \u542B\u975E\u6CD5\u5DE5\u5177\u540D: ${String(i)}`;if(n.view.defaultRoute!==void 0&&(typeof n.view.defaultRoute!="string"||n.view.defaultRoute.length>256))return"plugin.json: ui.view.defaultRoute \u987B\u4E3A \u2264256 \u5B57\u7B26\u7684\u5B57\u7B26\u4E32"}return null}const a=/^[a-zA-Z0-9_][a-zA-Z0-9_-]*$/,d=/^[a-z0-9][a-z0-9-]*$/,A=["system.","aws-","acode-"],h=/[^\x20-\x7E]/,j=new Set(["schemaVersion","name","version","description","author","tools","listeners","commands","userConfig","ui"]),v=new Set(["key","type","required","sensitive","description","default"]),I=new Set(["type","command","shell","stdin","timeoutMs","module","export"]),N=new Set(["name","title","description","inputSchema","handler"]),L=new Set(["event","description","transport","delivery","priority","matcher","dedupKey","toolHints","summary"]),O=new Set(["type","command","intervalMs","restartBackoffMs"]);function l(n,t,r){if(!o(t))return null;const i=Object.keys(t).filter(e=>!r.has(e));return i.length===0?null:`${n}: \u4E0D\u652F\u6301\u7684\u5B57\u6BB5 ${i.map(e=>`"${e}"`).join("\u3001")}\uFF08\u5141\u8BB8: ${[...r].join("\u3001")}\uFF09`}function o(n){return typeof n=="object"&&n!==null&&!Array.isArray(n)}function p(n,t){let r=n;for(const i of t.split(".")){if(!o(r))return;r=r[i]}return r}function M(n,t){return n.length<=t?n:`${n.slice(0,t)}\u2026(\u622A\u65AD,\u5171 ${n.length} \u5B57\u7B26)`}function g(n,t,r="params"){if(!o(n))return[];const i=[],e=n.type;if(typeof e=="string"&&!k(e,t))return[`${r}: \u671F\u671B ${e}\uFF0C\u5B9E\u9645 ${U(t)}`];if(Array.isArray(n.enum)&&n.enum.length>0&&(n.enum.some(u=>JSON.stringify(u)===JSON.stringify(t))||i.push(`${r}: \u503C ${JSON.stringify(t)} \u4E0D\u5728\u679A\u4E3E ${JSON.stringify(n.enum)} \u5185`)),e==="object"&&o(t)){const s=o(n.properties)?n.properties:{},u=Array.isArray(n.required)?n.required:[];for(const f of u)(!(f in t)||t[f]===void 0)&&i.push(`${r}.${f}: \u5FC5\u586B\u53C2\u6570\u7F3A\u5931`);for(const[f,y]of Object.entries(s))f in t&&t[f]!==void 0&&i.push(...g(y,t[f],`${r}.${f}`));if(n.additionalProperties===!1)for(const f of Object.keys(t))f in s||i.push(`${r}.${f}: \u4E0D\u5141\u8BB8\u7684\u672A\u77E5\u53C2\u6570\uFF08schema additionalProperties=false\uFF09`)}return e==="array"&&Array.isArray(t)&&o(n.items)&&t.forEach((s,u)=>{i.push(...g(n.items,s,`${r}[${u}]`))}),i}function k(n,t){switch(n){case"string":return typeof t=="string";case"number":return typeof t=="number"&&Number.isFinite(t);case"boolean":return typeof t=="boolean";case"object":return o(t);case"array":return Array.isArray(t);case"null":return t===null;default:return!0}}function U(n){return n===null?"null":Array.isArray(n)?"array":typeof n}function T(n){return typeof n=="string"&&n.length>0&&n.length<=64&&d.test(n)}function b(n){if(n.schemaVersion!==2)return'plugin.json: \u7F3A\u5C11\u6216\u4E0D\u652F\u6301\u7684 schemaVersion\uFF08\u987B\u4E3A 2\uFF09\uFF1B\u8BF7\u5728 plugin.json \u9876\u5C42\u58F0\u660E "schemaVersion": 2';const t=l("plugin.json",n,j);if(t)return t;const r=n.name;if(typeof r!="string"||!d.test(r))return`plugin.json: name \u975E\u6CD5\uFF08\u987B\u4E3A kebab-case\uFF09: ${String(r)}`;if(r.length>64)return"plugin.json: name \u8FC7\u957F\uFF08\u226464\uFF09";for(const e of A)if(r===e.replace(/\.$/,"")||r.startsWith(e))return`plugin.json: name \u4F7F\u7528\u4E86\u4FDD\u7559\u524D\u7F00 ${e}`;if(h.test(r))return"plugin.json: name \u542B\u975E ASCII \u5B57\u7B26\uFF08\u540C\u5F62\u5B57\u9632\u62A4\uFF09";if(n.version!==void 0&&typeof n.version!="string")return"plugin.json: version \u987B\u4E3A\u5B57\u7B26\u4E32";if(n.userConfig!==void 0){if(!Array.isArray(n.userConfig))return"plugin.json: userConfig \u987B\u4E3A\u6570\u7EC4";for(const e of n.userConfig){if(!o(e))return"plugin.json: userConfig \u6761\u76EE\u987B\u4E3A\u5BF9\u8C61";const s=l(`plugin.json: userConfig["${String(e.key)}"]`,e,v);if(s)return s;if(typeof e.key!="string"||!e.key.trim())return"plugin.json: userConfig \u6761\u76EE\u7F3A\u5C11 key"}}const i=_(n.ui);return i||null}function P(n){if(!o(n))return"\u5DE5\u5177\u6761\u76EE\u987B\u4E3A\u5BF9\u8C61";const t=n.name;if(typeof t!="string"||!a.test(t))return`\u5DE5\u5177 name \u975E\u6CD5: ${String(t)}`;const r=l(`\u5DE5\u5177 ${t}`,n,N);if(r)return r;if(typeof n.description!="string"||!n.description.trim())return`\u5DE5\u5177 ${t} \u7F3A\u5C11 description`;const i=n.handler;if(!o(i))return`\u5DE5\u5177 ${t} \u7F3A\u5C11 handler`;const e=l(`\u5DE5\u5177 ${t} handler`,i,I);if(e)return e;const s=i.type;return s!=="process"&&s!=="module"?`\u5DE5\u5177 ${t} handler.type \u975E\u6CD5: ${String(s)}\uFF08\u5F53\u524D\u652F\u6301 process / module\uFF09`:s==="process"&&typeof i.command!="string"?`\u5DE5\u5177 ${t} \u7684 process handler \u7F3A\u5C11 command`:s==="module"&&typeof i.module!="string"?`\u5DE5\u5177 ${t} \u7684 module handler \u7F3A\u5C11 module`:n.inputSchema!==void 0&&!o(n.inputSchema)?`\u5DE5\u5177 ${t} inputSchema \u987B\u4E3A\u5BF9\u8C61`:null}function W(n){if(!o(n))return"\u76D1\u542C\u5668\u6761\u76EE\u987B\u4E3A\u5BF9\u8C61";if(typeof n.event!="string"||!n.event.trim())return"\u76D1\u542C\u5668\u7F3A\u5C11 event";const t=l(`\u76D1\u542C\u5668 ${String(n.event)}`,n,L);if(t)return t;const r=n.transport;if(!o(r))return`\u76D1\u542C\u5668 ${String(n.event)} \u7F3A\u5C11 transport`;const i=l(`\u76D1\u542C\u5668 ${String(n.event)} transport`,r,O);if(i)return i;const e=r.type;if(e!=="command-stream"&&e!=="poll-command"&&e!=="http-callback")return`\u76D1\u542C\u5668 ${String(n.event)} transport.type \u975E\u6CD5: ${String(e)}`;if((e==="command-stream"||e==="poll-command")&&typeof r.command!="string")return`\u76D1\u542C\u5668 ${String(n.event)} \u7684 ${e} transport \u7F3A\u5C11 command`;const s=n.delivery;return s!==void 0&&s!=="poll"?`\u76D1\u542C\u5668 ${String(n.event)} delivery \u975E\u6CD5: ${String(s)}\uFF08\u5F53\u524D\u4EC5\u652F\u6301 "poll"\uFF09`:null}function x(n,t){return n.trim().split(/\s+/).map(r=>{const i=/^\{\{(.+)\}\}$/.exec(r);if(i){const e=p(t,i[1].trim());return e==null?"":typeof e=="string"?e:JSON.stringify(e)}return r.replace(/\{\{(.+?)\}\}/g,(e,s)=>{const u=p(t,s.trim());return u==null?"":typeof u=="string"?u:JSON.stringify(u)})}).filter(r=>r!=="")}function C(n,t){return n.replace(/\{\{(.+?)\}\}/g,(r,i)=>{let e=p(t,i.trim());return e===void 0&&!i.trim().startsWith("params.")&&(e=p(t,`data.${i.trim()}`)),e==null?"":typeof e=="string"?e:JSON.stringify(e)})}function D(n){try{return JSON.stringify(n)??"null"}catch{return"(\u4E0D\u53EF\u5E8F\u5217\u5316\u7684\u4E8B\u4EF6\u8D1F\u8F7D)"}}export{R as PLUGIN_MANIFEST_SCHEMA_VERSION,d as PLUGIN_NAME_PATTERN,S as PLUGIN_UI_BUILTIN_ICONS,p as getPath,o as isRecord,T as isValidPluginName,$ as isValidUiIcon,c as isValidUiPath,x as renderCommandArgv,C as renderTemplate,D as safeStableStringify,M as truncate,g as validateAgainstSchema,W as validateListenerDef,b as validateManifest,P as validateToolDef,_ as validateUiManifest};
|
|
2
2
|
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
import type { ChildProcess } from "node:child_process";
|
|
12
12
|
import type { PluginStatus } from "@agentswork/acode";
|
|
13
13
|
import type { PluginEventBuffer } from "./plugin-event-buffer.js";
|
|
14
|
-
import type { PluginListenerDef, PluginToolDef, PluginUserConfigField } from "./plugin-manifest.js";
|
|
14
|
+
import type { PluginListenerDef, PluginToolDef, PluginUiManifest, PluginUserConfigField } from "./plugin-manifest.js";
|
|
15
15
|
export interface ListenerRuntime {
|
|
16
16
|
def: PluginListenerDef;
|
|
17
17
|
child?: ChildProcess;
|
|
@@ -35,8 +35,15 @@ export interface LoadedPlugin {
|
|
|
35
35
|
tools: PluginToolDef[];
|
|
36
36
|
listeners: PluginListenerDef[];
|
|
37
37
|
commandDir?: string;
|
|
38
|
+
|
|
39
|
+
ui?: PluginUiManifest;
|
|
38
40
|
userConfig: PluginUserConfigField[];
|
|
39
41
|
configValues: Record<string, string>;
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
configuredKeys?: ReadonlySet<string>;
|
|
40
47
|
status: PluginStatus;
|
|
41
48
|
error?: string;
|
|
42
49
|
runtimes: ListenerRuntime[];
|
|
@@ -74,17 +81,9 @@ export interface AgentState {
|
|
|
74
81
|
export interface SharedPluginEntry {
|
|
75
82
|
pluginName: string;
|
|
76
83
|
|
|
77
|
-
zipFile?: string;
|
|
78
|
-
|
|
79
84
|
fileName?: string;
|
|
80
85
|
|
|
81
86
|
defaultEnabled?: boolean;
|
|
82
87
|
|
|
83
88
|
sha256?: string;
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
removed?: boolean;
|
|
90
89
|
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{pluginManager as t}from"./plugin-manager.js";import{createServerNotifier as n,PluginUiStatusWatcher as l}from"./plugin-ui-status.js";const u=new l({invokeTool:(i,e,o,r)=>t.invokeTool(i,e,o,r),listPlugins:i=>t.list(i),notifyServer:n()});export{u as pluginUiStatusWatcher};
|
|
2
|
+
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
export interface PluginUiStatusEntry {
|
|
18
|
+
pluginName: string;
|
|
19
|
+
|
|
20
|
+
status: Record<string, unknown> | null;
|
|
21
|
+
|
|
22
|
+
updatedAt: number;
|
|
23
|
+
|
|
24
|
+
error?: string;
|
|
25
|
+
|
|
26
|
+
revision: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type AgentUiStatusSnapshot = Record<string, PluginUiStatusEntry>;
|
|
30
|
+
|
|
31
|
+
export interface WatcherDeps {
|
|
32
|
+
|
|
33
|
+
invokeTool: (agentId: string, plugin: string, tool: string, params: Record<string, unknown>) => Promise<{
|
|
34
|
+
ok: boolean;
|
|
35
|
+
result?: unknown;
|
|
36
|
+
error?: string;
|
|
37
|
+
}>;
|
|
38
|
+
|
|
39
|
+
listPlugins: (agentId: string) => Promise<Array<{
|
|
40
|
+
name: string;
|
|
41
|
+
enabled: boolean;
|
|
42
|
+
frontend?: {
|
|
43
|
+
status?: {
|
|
44
|
+
tool: string;
|
|
45
|
+
pollIntervalMs?: number;
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
}>>;
|
|
49
|
+
|
|
50
|
+
notifyServer: (agentId: string, states: AgentUiStatusSnapshot) => Promise<void>;
|
|
51
|
+
|
|
52
|
+
setInterval?: (fn: () => void, ms: number) => ReturnType<typeof setInterval>;
|
|
53
|
+
clearInterval?: (handle: unknown) => void;
|
|
54
|
+
now?: () => number;
|
|
55
|
+
}
|
|
56
|
+
export declare class PluginUiStatusWatcher {
|
|
57
|
+
private readonly deps;
|
|
58
|
+
|
|
59
|
+
private readonly cache;
|
|
60
|
+
|
|
61
|
+
private readonly nextRunAt;
|
|
62
|
+
|
|
63
|
+
private readonly collecting;
|
|
64
|
+
private timer;
|
|
65
|
+
private started;
|
|
66
|
+
constructor(deps: WatcherDeps);
|
|
67
|
+
start(): void;
|
|
68
|
+
stop(): void;
|
|
69
|
+
|
|
70
|
+
snapshot(agentId: string): AgentUiStatusSnapshot;
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
onPluginChanged(agentId: string, pluginName: string, removed: boolean): Promise<void>;
|
|
77
|
+
|
|
78
|
+
clearAgent(agentId: string): void;
|
|
79
|
+
|
|
80
|
+
scan(): Promise<void>;
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
refreshAgent(agentId: string): Promise<void>;
|
|
86
|
+
stopAgent(agentId: string): Promise<void>;
|
|
87
|
+
private collectDue;
|
|
88
|
+
private collectOne;
|
|
89
|
+
private safeNotify;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
export declare function createServerNotifier(): (agentId: string, states: AgentUiStatusSnapshot) => Promise<void>;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{createLogger as R}from"../utils/logger.js";const w=R("plugin-ui-status"),M=3e4,k=5e3,T=5e3;class g{constructor(t){this.cache=new Map,this.nextRunAt=new Map,this.collecting=new Set,this.timer=null,this.started=!1,this.deps=t}start(){if(this.started)return;this.started=!0;const t=this.deps.setInterval??((e,s)=>{const r=setInterval(e,s);return r.unref?.(),r});this.timer=t(()=>void this.scan(),T)}stop(){this.started=!1,this.timer&&((this.deps.clearInterval??clearInterval)(this.timer),this.timer=null),this.cache.clear(),this.nextRunAt.clear(),this.collecting.clear()}snapshot(t){const e=this.cache.get(t);return e?structuredClone(e):{}}async onPluginChanged(t,e,s){const r=this.cache.get(t);if(s){if(r&&r[e]){const i={...r};delete i[e],this.cache.set(t,i),await this.safeNotify(t,i)}this.nextRunAt.get(t)?.delete(e);return}if(r?.[e]){const i={...r};delete i[e],this.cache.set(t,i)}const o=this.nextRunAt.get(t);o&&o.delete(e),await this.refreshAgent(t)}clearAgent(t){this.cache.delete(t),this.nextRunAt.delete(t)}async scan(){const t=(this.deps.now??Date.now)(),e=Array.from(this.nextRunAt.keys());for(const s of e)await this.collectDue(s,t)}async refreshAgent(t){let e;try{e=await this.deps.listPlugins(t)}catch(n){w.warn("[plugin-ui-status] \u5217\u51FA\u63D2\u4EF6\u5931\u8D25 agent=%s: %s",t,x(n));return}const s=(this.deps.now??Date.now)(),r=this.nextRunAt.get(t)??new Map,o=new Set;for(const n of e){const h=n.frontend?.status;!n.enabled||!h?.tool||(o.add(n.name),r.has(n.name)||r.set(n.name,0))}this.nextRunAt.set(t,r);const i=this.cache.get(t);if(i){let n=!1;const h={...i};for(const a of Object.keys(h))o.has(a)||(delete h[a],r.delete(a),n=!0);n&&(this.cache.set(t,h),await this.safeNotify(t,h))}await this.collectDue(t,s)}async stopAgent(t){this.clearAgent(t)}async collectDue(t,e){const s=this.nextRunAt.get(t);if(!(!s||s.size===0)&&!this.collecting.has(t)){this.collecting.add(t);try{for(const[r,o]of s)o>e||await this.collectOne(t,r)}finally{this.collecting.delete(t)}}}async collectOne(t,e){const s=this.nextRunAt.get(t),r=s?.get(e);let o;try{const A=(await this.deps.listPlugins(t)).find(y=>y.name===e),u=A?.frontend?.status;if(!A||!A.enabled||!u?.tool){const y=this.cache.get(t);if(y?.[e]){const v={...y};delete v[e],this.cache.set(t,v),s?.delete(e),await this.safeNotify(t,v)}return}o={agentId:t,pluginName:e,tool:u.tool,intervalMs:typeof u.pollIntervalMs=="number"&&u.pollIntervalMs>=k?u.pollIntervalMs:M}}catch(f){w.warn("[plugin-ui-status] \u8BFB\u53D6\u63D2\u4EF6\u58F0\u660E\u5931\u8D25 %s/%s: %s",t,e,x(f));return}const i=await this.deps.invokeTool(t,e,o.tool,{}),n=(this.deps.now??Date.now)(),h=i.ok?o.intervalMs:Math.min(o.intervalMs,3e4);s?.set(e,n+h);const a=this.cache.get(t)??{},l=a[e];if(!i.ok){const f={...a,[e]:{pluginName:e,status:l?.status??null,updatedAt:n,error:i.error??"\u72B6\u6001\u5DE5\u5177\u6267\u884C\u5931\u8D25",revision:l?.revision??0}};this.cache.set(t,f);return}const d=_(i.result),p=JSON.stringify(d),S=l&&l.status?JSON.stringify(l.status):null;if(p===S){l&&(a[e]={...l,updatedAt:n,error:void 0});return}const m={...a,[e]:{pluginName:e,status:d,updatedAt:n,revision:(l?.revision??0)+1}};this.cache.set(t,m),await this.safeNotify(t,m)}async safeNotify(t,e){try{await this.deps.notifyServer(t,structuredClone(e))}catch(s){w.warn("[plugin-ui-status] \u72B6\u6001\u56DE\u8C03\u5931\u8D25\uFF08\u4E0B\u8F6E\u53D8\u5316\u91CD\u8BD5\uFF09agent=%s: %s",t,x(s))}}}function _(c){return!c||typeof c!="object"||Array.isArray(c)?null:c}function x(c){return c instanceof Error?c.message:String(c)}function O(){return async(c,t)=>{const{resolveSchedulerBaseUrlFrom:e}=await import("../config.js"),{getRuntimeAccessToken:s}=await import("./runtime-binding.js"),{requestRuntimeAccessTokenRefreshForServer:r,resolveTargetIdentityFromToken:o}=await import("./auto-register.js"),i=e(void 0).url;let n=s(i)??s()??void 0;if(!n){w.warn("[plugin-ui-status] \u65E0 runtime token\uFF0C\u8DF3\u8FC7\u72B6\u6001\u56DE\u8C03");return}const h=JSON.stringify({agentId:c,states:t}),a=async()=>{await fetch(`${i}/api/runtime/callback/plugin-ui-status`,{method:"POST",headers:{"Content-Type":"application/json","X-Runtime-Token":n},body:h,signal:AbortSignal.timeout(1e4)})};try{await a()}catch(l){if(l?.response?.status===401){const p=o(n)?.identityKey;if((await r(i,p)).success){n=s(i)??s()??n,await a();return}}throw l}}}export{g as PluginUiStatusWatcher,O as createServerNotifier};
|
|
2
|
+
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
export interface WecomVerifyParams {
|
|
13
|
+
msg_signature: string;
|
|
14
|
+
timestamp: string;
|
|
15
|
+
nonce: string;
|
|
16
|
+
echostr: string;
|
|
17
|
+
}
|
|
18
|
+
export interface WecomMessageParams extends WecomVerifyParams {
|
|
19
|
+
|
|
20
|
+
xml?: string;
|
|
21
|
+
}
|
|
22
|
+
interface WecomCrypto {
|
|
23
|
+
token: string;
|
|
24
|
+
aesKey: Buffer;
|
|
25
|
+
receiveId: string;
|
|
26
|
+
}
|
|
27
|
+
export declare function verifySignature(crypto: WecomCrypto, timestamp: string, nonce: string, encrypt: string): string;
|
|
28
|
+
|
|
29
|
+
export declare function decryptMessage(crypto: WecomCrypto, ciphertextB64: string): {
|
|
30
|
+
message: Buffer;
|
|
31
|
+
receiveId: string;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export declare function extractEncrypt(xml: string): string | null;
|
|
35
|
+
|
|
36
|
+
export declare function parseWecomXml(xml: string): Record<string, string>;
|
|
37
|
+
export interface WecomCallbackResult {
|
|
38
|
+
ok: boolean;
|
|
39
|
+
status: number;
|
|
40
|
+
|
|
41
|
+
body: string;
|
|
42
|
+
}
|
|
43
|
+
export declare class PluginWecomCallbackService {
|
|
44
|
+
private readonly pluginManager;
|
|
45
|
+
constructor(pluginManager: {
|
|
46
|
+
hydrateForAdmin: (agentId: string) => Promise<{
|
|
47
|
+
plugins: Map<string, {
|
|
48
|
+
dir: string;
|
|
49
|
+
enabled: boolean;
|
|
50
|
+
configValues: Record<string, string>;
|
|
51
|
+
}>;
|
|
52
|
+
}>;
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
private resolveCrypto;
|
|
56
|
+
|
|
57
|
+
verify(agentId: string, params: WecomVerifyParams, pluginName?: string): Promise<WecomCallbackResult>;
|
|
58
|
+
|
|
59
|
+
receive(agentId: string, params: WecomMessageParams, xmlBody: string, pluginName?: string): Promise<WecomCallbackResult>;
|
|
60
|
+
}
|
|
61
|
+
export {};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{createDecipheriv as w,createHash as b}from"node:crypto";import{appendFileSync as E,existsSync as v,mkdirSync as k}from"node:fs";import{join as m}from"node:path";import{createLogger as C}from"../utils/logger.js";const i=C("plugin-wecom-callback"),I="im-bot";function f(t,e,r,o){const s=[t.token,e,r,o].sort();return b("sha1").update(s.join("")).digest("hex")}function d(t,e){const r=Buffer.from(e,"base64"),o=w("aes-256-cbc",t.aesKey,t.aesKey.subarray(0,16));o.setAutoPadding(!1);const s=Buffer.concat([o.update(r),o.final()]),n=s[s.length-1];if(n<1||n>32)throw new Error(`\u975E\u6CD5 PKCS#7 \u586B\u5145: ${n}`);const c=s.subarray(0,s.length-n);if(c.length<20)throw new Error("\u89E3\u5BC6\u5185\u5BB9\u8FC7\u77ED");const a=c.readUInt32BE(16);if(a+20>c.length)throw new Error(`\u6D88\u606F\u957F\u5EA6\u8D8A\u754C: ${a} > ${c.length-20}`);return{message:c.subarray(20,20+a),receiveId:c.subarray(20+a).toString("utf8")}}function S(t){const e=Buffer.from(`${t}=`,"base64");if(e.length!==32)throw new Error(`EncodingAESKey \u975E\u6CD5\uFF08Base64 \u89E3\u7801\u540E\u987B\u4E3A 32 \u5B57\u8282\uFF0C\u5B9E\u9645 ${e.length}\uFF09`);return e}function p(t){const e=/<Encrypt><!\[CDATA\[([\s\S]*?)\]\]><\/Encrypt>|<Encrypt>([\s\S]*?)<\/Encrypt>/.exec(t);return e?.[1]??e?.[2]??null}function x(t){const e={},r=/<(\w+)><!\[CDATA\[([\s\S]*?)\]\]><\/\1>|<(\w+)>([^<]*)<\/\3>/g;let o;for(;(o=r.exec(t))!==null;){const s=o[1]??o[3],n=o[2]??o[4]??"";s&&(e[s]=n)}return e}function _(t){const e=String(t.MsgType??"");if(e!=="text"&&e!=="image")return null;const r=t.ChatType==="group"||t.ChatId?t.ChatType??"single":"single",o=e==="text"?String(t.Content??""):"";return e==="text"&&!o?null:{event:"wecom.message",data:{msgId:t.MsgId??`${t.FromUserName??"unknown"}-${t.CreateTime??Date.now()}`,msgType:e,content:o,fromUser:t.FromUserName??"",chatId:t.ChatId??t.FromUserName??"",chatType:r,groupName:t.ChatName??void 0,createTime:Number(t.CreateTime)||Math.floor(Date.now()/1e3)}}}class O{constructor(e){this.pluginManager=e}async resolveCrypto(e,r=I){const s=(await this.pluginManager.hydrateForAdmin(e)).plugins.get(r);if(!s||!s.enabled)return{error:`\u63D2\u4EF6 ${r} \u672A\u5B89\u88C5\u6216\u672A\u542F\u7528`};const n=s.configValues??{},c=n.WECOM_TOKEN,a=n.WECOM_ENCODING_AES_KEY;if(!c||!a)return{error:"\u63D2\u4EF6\u7F3A\u5C11 WECOM_TOKEN / WECOM_ENCODING_AES_KEY \u914D\u7F6E"};let u;try{u=S(a)}catch(g){return{error:g instanceof Error?g.message:String(g)}}return{crypto:{token:c,aesKey:u,receiveId:n.WECOM_CORP_ID??""},pluginDir:s.dir}}async verify(e,r,o){const s=await this.resolveCrypto(e,o);if(!s.crypto)return{ok:!1,status:400,body:s.error??"unconfigured"};const n=s.crypto;if(!r.msg_signature||!r.echostr)return{ok:!1,status:400,body:"msg_signature/echostr is required"};try{if(f(n,r.timestamp??"",r.nonce??"",r.echostr)!==r.msg_signature)return i.warn("[wecom-callback] URL \u9A8C\u8BC1\u7B7E\u540D\u4E0D\u7B26 agentId=%s",e),{ok:!1,status:403,body:"signature mismatch"};const a=d(n,r.echostr);return n.receiveId&&a.receiveId!==n.receiveId?(i.warn("[wecom-callback] URL \u9A8C\u8BC1 receiveId \u4E0D\u7B26: %s",a.receiveId),{ok:!1,status:403,body:"receiveId mismatch"}):{ok:!0,status:200,body:a.message.toString("utf8")}}catch(c){return i.warn("[wecom-callback] URL \u9A8C\u8BC1\u5931\u8D25 agentId=%s: %s",e,c instanceof Error?c.message:c),{ok:!1,status:400,body:"verify failed"}}}async receive(e,r,o,s){const n=await this.resolveCrypto(e,s);if(!n.crypto||!n.pluginDir)return i.warn("[wecom-callback] \u62D2\u7EDD\u6D88\u606F\u56DE\u8C03 agentId=%s: %s",e,n.error),{ok:!1,status:400,body:"success"};const c=n.crypto,a=p(o)??p(r.xml??"");if(!a)return{ok:!1,status:400,body:"success"};try{if(f(c,r.timestamp??"",r.nonce??"",a)!==r.msg_signature)return i.warn("[wecom-callback] \u6D88\u606F\u7B7E\u540D\u4E0D\u7B26 agentId=%s",e),{ok:!1,status:403,body:"success"};const g=d(c,a);if(c.receiveId&&g.receiveId!==c.receiveId)return i.warn("[wecom-callback] \u6D88\u606F receiveId \u4E0D\u7B26: %s",g.receiveId),{ok:!0,status:200,body:"success"};const h=x(g.message.toString("utf8")),l=_(h);if(l){const y=m(n.pluginDir,"data",e);v(y)||k(y,{recursive:!0}),E(m(y,"inbox-wecom.jsonl"),`${JSON.stringify(l)}
|
|
2
|
+
`,"utf8"),i.info("[wecom-callback] \u5165\u7AD9\u6D88\u606F\u5DF2\u5165\u6536\u4EF6\u7BB1 agentId=%s msgId=%s",e,l.data.msgId)}return{ok:!0,status:200,body:"success"}}catch(u){return i.warn("[wecom-callback] \u6D88\u606F\u5904\u7406\u5931\u8D25 agentId=%s: %s",e,u instanceof Error?u.message:u),{ok:!0,status:200,body:"success"}}}}export{O as PluginWecomCallbackService,d as decryptMessage,p as extractEncrypt,x as parseWecomXml,f as verifySignature};
|
|
3
|
+
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
|
|
24
|
+
|
|
24
25
|
|
|
25
26
|
|
|
26
27
|
import type { NextFunction, Request, Response } from "express";
|
|
@@ -30,8 +31,6 @@ export interface UserScope {
|
|
|
30
31
|
}
|
|
31
32
|
export declare const SCOPE_ID_PATTERN: RegExp;
|
|
32
33
|
|
|
33
|
-
export declare const LEGACY_SCOPE: Readonly<UserScope>;
|
|
34
|
-
|
|
35
34
|
export declare const TENANT_HEADER = "x-tenant-id";
|
|
36
35
|
export declare const USER_HEADER = "x-user-id";
|
|
37
36
|
declare module "express-serve-static-core" {
|
|
@@ -62,13 +61,6 @@ export declare function scopeEquals(a: UserScope | null, b: UserScope | null): b
|
|
|
62
61
|
|
|
63
62
|
export declare function isLegacyScope(scope: UserScope | null): boolean;
|
|
64
63
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
export declare function isLegacyScopeAllowed(): boolean;
|
|
69
|
-
|
|
70
|
-
export declare function isLegacyFallbackDisabled(): boolean;
|
|
71
|
-
|
|
72
64
|
export declare function getUserScopeRoot(scope: UserScope): string;
|
|
73
65
|
|
|
74
66
|
export declare function getUserAiConfigFile(scope: UserScope): string;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import o from"node:path";import{getBridgeDataHome as
|
|
1
|
+
import o from"node:path";import{getBridgeDataHome as I}from"../config.js";import{loadRuntimeBinding as x}from"./runtime-binding.js";const S=/^[a-zA-Z0-9_.-]+$/,m="x-tenant-id",U="x-user-id";function i(e){const r=String(e??"").replace(/[^a-zA-Z0-9_.-]/g,"_");return/^\.+$/.test(r)?"_":r.replace(/^\.+/g,"")}function E(e){return typeof e=="string"&&e.length>0&&S.test(e)}function p(e,r){const t=String(e??"").trim(),n=String(r??"").trim();return!t||!n?null:{tenantId:t,userId:n}}function A(e,r){return!e||!r?!1:i(e.tenantId)===i(r.tenantId)&&i(e.userId)===i(r.userId)}function b(e){return i(e?.tenantId??"")==="_legacy"&&i(e?.userId??"")==="_legacy"}function y(e){return[i(e.tenantId),i(e.userId)]}function s(e){return o.join(I(),"users",...y(e))}function C(e){return o.join(s(e),"ai","acode.json")}function h(e){return o.join(s(e),"skills")}function H(e){return o.join(h(e),"deployed")}function f(e){return o.join(s(e),"mcp")}function O(e){return o.join(f(e),"deployed")}function R(e){return o.join(f(e),"packages")}function j(e){return o.join(s(e),"plugins")}function T(e){return o.join(j(e),"deployed")}function l(e,r){return o.join(s(e),"capability",r)}function P(e,r){return o.join(l(e,r),"config.json")}function z(e,r,t){return o.join(l(e,r),"agents",`${i(t)}.json`)}function D(...e){for(const r of e){const t=String(r??"").trim();if(t)return t}return""}function u(e){const r=p(e.header(m),e.header(U));if(r)return r;const t=e.body??{};return p(t.tenantId,D(t.ownerUserId,t.userId))}function d(){try{const e=x();return e?.userId?p("_local",e.userId):null}catch{return null}}function F(e,r,t){const n=u(e)??d();n&&(e.userScope=n),t()}function M(e,r,t){if(e.userScope){t();return}const n=u(e)??d();if(n){e.userScope=n,t();return}r.status(400).json({ok:!1,error:"user-scope-required",message:"\u8BF7\u6C42\u7F3A\u5C11 X-Tenant-Id / X-User-Id\uFF08\u6216\u4F53 tenantId + ownerUserId\uFF09\u8EAB\u4EFD"})}function N(e){const r=e.userScope??u(e);if(!r)throw new Error("user-scope-required: \u8BF7\u6C42\u7F3A\u5C11 (tenantId, userId) \u8EAB\u4EFD");return r}let a=null,g=null;function $(e){a=e}function v(e){g=e}function B(e,r,t){const n=String(e.params?.agentId??e.body?.agentId??"").trim();if(!n){t();return}const c=e.userScope??u(e);if(!c){r.status(400).json({ok:!1,error:"user-scope-required",message:"agent \u7EA7\u64CD\u4F5C\u7F3A\u5C11 (tenantId, userId) \u8EAB\u4EFD"});return}if(a&&!a(n,c)){if(g?.(n,c)){t();return}r.status(403).json({ok:!1,error:"agent-ownership-mismatch",message:"\u8BE5\u5B9E\u4F8B\u4E0D\u5C5E\u4E8E\u5F53\u524D\u7528\u6237"});return}t()}export{S as SCOPE_ID_PATTERN,m as TENANT_HEADER,U as USER_HEADER,u as extractUserScope,C as getUserAiConfigFile,z as getUserCapabilityAgentFile,P as getUserCapabilityDefaultsFile,l as getUserCapabilityDir,O as getUserMcpDeployedDir,f as getUserMcpDir,R as getUserMcpPackagesDir,T as getUserPluginsDeployedDir,j as getUserPluginsDir,N as getUserScopeOrThrow,s as getUserScopeRoot,H as getUserSkillsDeployedDir,h as getUserSkillsDir,b as isLegacyScope,E as isValidScopeId,p as normalizeUserScope,B as requireAgentOwnership,M as requireUserScope,F as resolveUserScope,i as sanitizeScopeId,A as scopeEquals,$ as setAgentOwnershipChecker,v as setMachineOwnershipSelfHeal};
|
|
2
2
|
|
|
@@ -27,11 +27,35 @@ export declare function splitQualifiedToolName(qualifiedName: string): {
|
|
|
27
27
|
|
|
28
28
|
export type PluginStatus = "enabled" | "disabled" | "error";
|
|
29
29
|
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
export interface PluginUiSummary {
|
|
34
|
+
|
|
35
|
+
icon?: string;
|
|
36
|
+
status?: {
|
|
37
|
+
tool: string;
|
|
38
|
+
persistent: boolean;
|
|
39
|
+
|
|
40
|
+
hideWhenZero?: boolean;
|
|
41
|
+
pollIntervalMs: number;
|
|
42
|
+
title?: string;
|
|
43
|
+
};
|
|
44
|
+
view?: {
|
|
45
|
+
|
|
46
|
+
entry: string;
|
|
47
|
+
title: string;
|
|
48
|
+
|
|
49
|
+
invoke: string[];
|
|
50
|
+
defaultRoute?: string;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
30
54
|
export type PluginListenerState = "pending" | "running" | "stopped";
|
|
31
55
|
|
|
32
56
|
export interface PluginListenerSummary {
|
|
33
57
|
event: string;
|
|
34
|
-
delivery: "poll"
|
|
58
|
+
delivery: "poll";
|
|
35
59
|
running: boolean;
|
|
36
60
|
|
|
37
61
|
|
|
@@ -68,6 +92,22 @@ export interface PluginSummary {
|
|
|
68
92
|
listenerState?: PluginListenerState;
|
|
69
93
|
|
|
70
94
|
error?: string;
|
|
95
|
+
|
|
96
|
+
frontend?: PluginUiSummary;
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
userConfig?: Array<{
|
|
102
|
+
key: string;
|
|
103
|
+
description?: string;
|
|
104
|
+
required?: boolean;
|
|
105
|
+
sensitive?: boolean;
|
|
106
|
+
|
|
107
|
+
source: "json" | "env" | "default";
|
|
108
|
+
|
|
109
|
+
value?: string;
|
|
110
|
+
}>;
|
|
71
111
|
}
|
|
72
112
|
|
|
73
113
|
export type PluginManageAction = "install" | "uninstall" | "reload" | "enable" | "disable" | "list";
|
|
@@ -256,6 +256,12 @@ export declare class ACodeRuntime extends EventEmitter {
|
|
|
256
256
|
private instructionsDirty;
|
|
257
257
|
|
|
258
258
|
private turnPromptPushed;
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
private resumeContextNoticeAppended;
|
|
259
265
|
private abortRequested;
|
|
260
266
|
|
|
261
267
|
|
|
@@ -523,6 +529,7 @@ export declare class ACodeRuntime extends EventEmitter {
|
|
|
523
529
|
|
|
524
530
|
|
|
525
531
|
|
|
532
|
+
|
|
526
533
|
exportConversation(): ChatMessage[];
|
|
527
534
|
|
|
528
535
|
|
|
@@ -542,6 +549,8 @@ export declare class ACodeRuntime extends EventEmitter {
|
|
|
542
549
|
|
|
543
550
|
|
|
544
551
|
|
|
552
|
+
|
|
553
|
+
|
|
545
554
|
|
|
546
555
|
|
|
547
556
|
importTranscript(transcript: ChatMessage[]): Promise<number>;
|
|
@@ -552,6 +561,14 @@ export declare class ACodeRuntime extends EventEmitter {
|
|
|
552
561
|
|
|
553
562
|
|
|
554
563
|
|
|
564
|
+
appendResumeContextNotice(): void;
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
|
|
568
|
+
|
|
569
|
+
|
|
570
|
+
|
|
571
|
+
|
|
555
572
|
addBuiltInTools(tools: unknown[]): number;
|
|
556
573
|
|
|
557
574
|
|