openclaw-openagent 1.0.1 → 1.0.2
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/index.d.ts +25 -0
- package/dist/index.js +105 -0
- package/dist/src/app/channel-tools.d.ts +28 -0
- package/dist/src/app/channel-tools.js +251 -0
- package/dist/src/app/discovery-tools.d.ts +35 -0
- package/dist/src/app/discovery-tools.js +243 -0
- package/dist/src/app/download-file-tool.d.ts +10 -0
- package/dist/src/app/download-file-tool.js +104 -0
- package/dist/src/app/hooks.d.ts +14 -0
- package/dist/src/app/hooks.js +118 -0
- package/dist/src/app/index.d.ts +13 -0
- package/dist/src/app/index.js +44 -0
- package/dist/src/app/messaging-tools.d.ts +11 -0
- package/dist/src/app/messaging-tools.js +79 -0
- package/dist/src/app/ops-tools.d.ts +21 -0
- package/dist/src/app/ops-tools.js +158 -0
- package/dist/src/app/remote-agent-tool.d.ts +27 -0
- package/dist/src/app/remote-agent-tool.js +461 -0
- package/dist/src/app/types.d.ts +61 -0
- package/dist/src/app/types.js +11 -0
- package/dist/src/app/upload-file-tool.d.ts +16 -0
- package/dist/src/app/upload-file-tool.js +353 -0
- package/dist/src/app/verbose-preflight.d.ts +2 -0
- package/dist/src/app/verbose-preflight.js +145 -0
- package/dist/src/auth/config.d.ts +79 -0
- package/dist/src/auth/config.js +133 -0
- package/dist/src/auth/credential-manager.d.ts +65 -0
- package/dist/src/auth/credential-manager.js +122 -0
- package/dist/src/auth/index.d.ts +6 -0
- package/dist/src/auth/index.js +6 -0
- package/dist/src/auth/verify.d.ts +42 -0
- package/dist/src/auth/verify.js +60 -0
- package/dist/src/channel.d.ts +269 -0
- package/dist/src/channel.js +488 -0
- package/dist/src/compat.d.ts +37 -0
- package/dist/src/compat.js +70 -0
- package/dist/src/config/config-schema.d.ts +56 -0
- package/dist/src/config/config-schema.js +34 -0
- package/dist/src/messaging/aggregator.d.ts +25 -0
- package/dist/src/messaging/aggregator.js +90 -0
- package/dist/src/messaging/collector.d.ts +27 -0
- package/dist/src/messaging/collector.js +76 -0
- package/dist/src/messaging/executor.d.ts +14 -0
- package/dist/src/messaging/executor.js +59 -0
- package/dist/src/messaging/inbound.d.ts +97 -0
- package/dist/src/messaging/inbound.js +63 -0
- package/dist/src/messaging/index.d.ts +10 -0
- package/dist/src/messaging/index.js +9 -0
- package/dist/src/messaging/mention-protocol.d.ts +42 -0
- package/dist/src/messaging/mention-protocol.js +74 -0
- package/dist/src/messaging/process-c2c-request.d.ts +55 -0
- package/dist/src/messaging/process-c2c-request.js +445 -0
- package/dist/src/messaging/process-message.d.ts +62 -0
- package/dist/src/messaging/process-message.js +282 -0
- package/dist/src/messaging/scheduler.d.ts +17 -0
- package/dist/src/messaging/scheduler.js +47 -0
- package/dist/src/messaging/types.d.ts +34 -0
- package/dist/src/messaging/types.js +4 -0
- package/dist/src/plugin-ui/assets/openagent-override.js +9267 -0
- package/dist/src/plugin-ui/index.d.ts +13 -0
- package/dist/src/plugin-ui/index.js +16 -0
- package/dist/src/plugin-ui/ui-extension-loader/backup.d.ts +23 -0
- package/dist/src/plugin-ui/ui-extension-loader/backup.js +82 -0
- package/dist/src/plugin-ui/ui-extension-loader/index.d.ts +28 -0
- package/dist/src/plugin-ui/ui-extension-loader/index.js +240 -0
- package/dist/src/plugin-ui/ui-extension-loader/locator.d.ts +35 -0
- package/dist/src/plugin-ui/ui-extension-loader/locator.js +129 -0
- package/dist/src/plugin-ui/ui-extension-loader/manifest.d.ts +26 -0
- package/dist/src/plugin-ui/ui-extension-loader/manifest.js +45 -0
- package/dist/src/plugin-ui/ui-extension-loader/registry-regex.d.ts +9 -0
- package/dist/src/plugin-ui/ui-extension-loader/registry-regex.js +701 -0
- package/dist/src/plugin-ui/ui-extension-loader/removed-extensions.d.ts +8 -0
- package/dist/src/plugin-ui/ui-extension-loader/removed-extensions.js +58 -0
- package/dist/src/plugin-ui/ui-extension-loader/types.d.ts +55 -0
- package/dist/src/plugin-ui/ui-extension-loader/types.js +23 -0
- package/dist/src/proxy/auth-proxy.d.ts +20 -0
- package/dist/src/proxy/auth-proxy.js +337 -0
- package/dist/src/runtime/account.d.ts +156 -0
- package/dist/src/runtime/account.js +491 -0
- package/dist/src/runtime/index.d.ts +5 -0
- package/dist/src/runtime/index.js +6 -0
- package/dist/src/runtime/plugin-runtime.d.ts +40 -0
- package/dist/src/runtime/plugin-runtime.js +72 -0
- package/dist/src/runtime/registry.d.ts +41 -0
- package/dist/src/runtime/registry.js +60 -0
- package/dist/src/sdk/CLASS_MAP.md +143 -0
- package/dist/src/sdk/index.d.ts +126 -0
- package/dist/src/sdk/index.js +23990 -0
- package/dist/src/sdk/modules/cloud-search-module.js +1117 -0
- package/dist/src/sdk/modules/follow-module.js +1069 -0
- package/dist/src/sdk/modules/group-module.js +7397 -0
- package/dist/src/sdk/modules/relationship-module.js +2269 -0
- package/dist/src/sdk/modules/signaling-module.js +1468 -0
- package/dist/src/sdk/modules/tim-upload-plugin.js +730 -0
- package/dist/src/sdk/node-env/http-request.js +90 -0
- package/dist/src/sdk/node-env/index.js +57 -0
- package/dist/src/sdk/node-env/storage.js +114 -0
- package/dist/src/sdk/package.json +10 -0
- package/dist/src/sdk/sdk/CLASS_MAP.md +143 -0
- package/dist/src/sdk/sdk/index.d.ts +126 -0
- package/dist/src/sdk/sdk/index.js +23990 -0
- package/dist/src/sdk/sdk/modules/cloud-search-module.js +1117 -0
- package/dist/src/sdk/sdk/modules/follow-module.js +1069 -0
- package/dist/src/sdk/sdk/modules/group-module.js +7397 -0
- package/dist/src/sdk/sdk/modules/relationship-module.js +2269 -0
- package/dist/src/sdk/sdk/modules/signaling-module.js +1468 -0
- package/dist/src/sdk/sdk/modules/tim-upload-plugin.js +730 -0
- package/dist/src/sdk/sdk/node-env/http-request.js +90 -0
- package/dist/src/sdk/sdk/node-env/index.js +57 -0
- package/dist/src/sdk/sdk/node-env/storage.js +114 -0
- package/dist/src/sdk/sdk/package.json +10 -0
- package/dist/src/sdk/sdk/tsconfig.json +16 -0
- package/dist/src/sdk/tsconfig.json +16 -0
- package/dist/src/state/pending-invocation-store.d.ts +26 -0
- package/dist/src/state/pending-invocation-store.js +39 -0
- package/dist/src/state/store.d.ts +165 -0
- package/dist/src/state/store.js +535 -0
- package/dist/src/tim/c2c.d.ts +83 -0
- package/dist/src/tim/c2c.js +318 -0
- package/dist/src/tim/channels.d.ts +95 -0
- package/dist/src/tim/channels.js +279 -0
- package/dist/src/tim/client.d.ts +54 -0
- package/dist/src/tim/client.js +268 -0
- package/dist/src/tim/index.d.ts +6 -0
- package/dist/src/tim/index.js +6 -0
- package/dist/src/tim/messages.d.ts +50 -0
- package/dist/src/tim/messages.js +104 -0
- package/dist/src/tim/sdk-logger-init.d.ts +13 -0
- package/dist/src/tim/sdk-logger-init.js +46 -0
- package/dist/src/tools.d.ts +9 -0
- package/dist/src/tools.js +8 -0
- package/dist/src/transport/factory.d.ts +63 -0
- package/dist/src/transport/factory.js +54 -0
- package/dist/src/transport/oasn/index.d.ts +12 -0
- package/dist/src/transport/oasn/index.js +9 -0
- package/dist/src/transport/oasn/oasn-agent-card.d.ts +38 -0
- package/dist/src/transport/oasn/oasn-agent-card.js +102 -0
- package/dist/src/transport/oasn/oasn-discovery.d.ts +33 -0
- package/dist/src/transport/oasn/oasn-discovery.js +97 -0
- package/dist/src/transport/oasn/oasn-files.d.ts +64 -0
- package/dist/src/transport/oasn/oasn-files.js +174 -0
- package/dist/src/transport/oasn/oasn-http.d.ts +98 -0
- package/dist/src/transport/oasn/oasn-http.js +362 -0
- package/dist/src/transport/oasn/oasn-invocation.d.ts +154 -0
- package/dist/src/transport/oasn/oasn-invocation.js +432 -0
- package/dist/src/transport/oasn/oasn-normalize.d.ts +6 -0
- package/dist/src/transport/oasn/oasn-normalize.js +112 -0
- package/dist/src/transport/oasn/oasn-register.d.ts +19 -0
- package/dist/src/transport/oasn/oasn-register.js +24 -0
- package/dist/src/transport/oasn/oasn-transport.d.ts +114 -0
- package/dist/src/transport/oasn/oasn-transport.js +230 -0
- package/dist/src/transport/oasn/oasn-types.d.ts +331 -0
- package/dist/src/transport/oasn/oasn-types.js +44 -0
- package/dist/src/transport/tim/index.d.ts +7 -0
- package/dist/src/transport/tim/index.js +6 -0
- package/dist/src/transport/tim/tim-transport.d.ts +122 -0
- package/dist/src/transport/tim/tim-transport.js +402 -0
- package/dist/src/transport/types.d.ts +450 -0
- package/dist/src/transport/types.js +38 -0
- package/dist/src/util/http.d.ts +21 -0
- package/dist/src/util/http.js +93 -0
- package/dist/src/util/logger.d.ts +20 -0
- package/dist/src/util/logger.js +100 -0
- package/dist/src/util/url-resolver.d.ts +7 -0
- package/dist/src/util/url-resolver.js +20 -0
- package/index.ts +11 -0
- package/openclaw.plugin.json +9 -0
- package/package.json +7 -4
- package/src/app/download-file-tool.ts +133 -0
- package/src/app/hooks.ts +89 -5
- package/src/app/index.ts +6 -0
- package/src/app/remote-agent-tool.ts +46 -0
- package/src/app/types.ts +1 -0
- package/src/app/upload-file-tool.ts +411 -0
- package/src/plugin-ui/assets/openagent-override.js +1 -63
- package/src/plugin-ui/modules/agent-book/panel/agent-book.js +0 -61
- package/src/plugin-ui/modules/agent-book/panel/agent-data.js +0 -1
- package/src/plugin-ui/ui-extension-loader/registry-regex.ts +30 -13
- package/src/runtime/account.ts +0 -23
- package/src/transport/oasn/oasn-files.ts +5 -5
- package/src/transport/oasn/oasn-invocation.ts +44 -2
- package/src/transport/oasn/oasn-normalize.ts +0 -26
- package/src/transport/oasn/oasn-register.ts +8 -81
- package/src/transport/oasn/oasn-transport.ts +9 -32
- package/src/transport/oasn/oasn-types.ts +53 -6
- package/src/transport/types.ts +33 -36
- package/src/util/url-resolver.ts +17 -0
|
@@ -583,7 +583,7 @@ const toolcallidPropagate: UIExtension = {
|
|
|
583
583
|
};
|
|
584
584
|
|
|
585
585
|
|
|
586
|
-
// ── Extension 6: remote-agent-message-short-circuit
|
|
586
|
+
// ── Extension 6: remote-agent-message-short-circuit(三策略 A/B/C)───────
|
|
587
587
|
|
|
588
588
|
const remoteAgentMessageShortCircuit: UIExtension = {
|
|
589
589
|
id: 'remote-agent-message-short-circuit',
|
|
@@ -597,16 +597,16 @@ const remoteAgentMessageShortCircuit: UIExtension = {
|
|
|
597
597
|
if (hasMarker(content, this.id)) { return true; }
|
|
598
598
|
if (!backupFile(bundlePath)) return false;
|
|
599
599
|
|
|
600
|
-
// 找 showToolCalls 赋值
|
|
600
|
+
// 找 showToolCalls 赋值 → 提取 toolCardsVar / hasToolCardsVar
|
|
601
601
|
const assignRe = /(\w+)=\w+\.showToolCalls[^;]*\(\w+(?:,\w+)?\)\s*:\s*\[\]\s*,\s*(\w+)\s*=\s*\1\.length\s*>\s*0/;
|
|
602
602
|
const assignMatch = content.match(assignRe);
|
|
603
603
|
if (!assignMatch) {
|
|
604
|
-
logger.warn('[ui-ext:regex] remote-agent-msg: showToolCalls
|
|
604
|
+
logger.warn('[ui-ext:regex] remote-agent-msg: showToolCalls assignment not found');
|
|
605
605
|
return false;
|
|
606
606
|
}
|
|
607
607
|
|
|
608
|
-
const toolCardsVar = assignMatch[1]
|
|
609
|
-
const hasToolCardsVar = assignMatch[2]
|
|
608
|
+
const toolCardsVar = assignMatch[1]!;
|
|
609
|
+
const hasToolCardsVar = assignMatch[2]!;
|
|
610
610
|
const marker = makeMarker(this.id);
|
|
611
611
|
|
|
612
612
|
// 策略A (v3.23~v4.10): if(!markdown&&hasToolCards&&isToolResult)
|
|
@@ -614,8 +614,8 @@ const remoteAgentMessageShortCircuit: UIExtension = {
|
|
|
614
614
|
const ifMatchA = content.match(ifReA);
|
|
615
615
|
|
|
616
616
|
if (ifMatchA) {
|
|
617
|
-
const markdownVar = ifMatchA[1]
|
|
618
|
-
const isToolResultVar = ifMatchA[2]
|
|
617
|
+
const markdownVar = ifMatchA[1]!;
|
|
618
|
+
const isToolResultVar = ifMatchA[2]!;
|
|
619
619
|
const patched = `if(${marker}(!${markdownVar}||window.__openagentOwnsToolCards&&window.__openagentOwnsToolCards(${toolCardsVar}))&&${hasToolCardsVar}&&${isToolResultVar})`;
|
|
620
620
|
content = content.substring(0, ifMatchA.index!) + patched + content.substring(ifMatchA.index! + ifMatchA[0].length);
|
|
621
621
|
writeFileSync(bundlePath, content, 'utf-8');
|
|
@@ -623,15 +623,30 @@ const remoteAgentMessageShortCircuit: UIExtension = {
|
|
|
623
623
|
return true;
|
|
624
624
|
}
|
|
625
625
|
|
|
626
|
-
// 策略
|
|
626
|
+
// 策略C (2026.4.x): if(!VAR.showToolCalls&&...toolresult...)continue
|
|
627
|
+
// 直接匹配 continue 跳过语句,注入 openagentOwnsToolCards 条件
|
|
628
|
+
const continueRe = /if\(!(\w+)\.showToolCalls&&(\w+)\.role\.toLowerCase\(\)===`toolresult`\)continue/;
|
|
629
|
+
const continueMatch = content.match(continueRe);
|
|
630
|
+
|
|
631
|
+
if (continueMatch) {
|
|
632
|
+
const scVar = continueMatch[1]!;
|
|
633
|
+
const roleVar = continueMatch[2]!;
|
|
634
|
+
const patched = `if(!${scVar}.showToolCalls&&!window.__openagentOwnsToolCards?.(${toolCardsVar})&&${roleVar}.role.toLowerCase()===\`toolresult\`)continue`;
|
|
635
|
+
content = content.substring(0, continueMatch.index!) + marker + patched + content.substring(continueMatch.index! + continueMatch[0].length);
|
|
636
|
+
writeFileSync(bundlePath, content, 'utf-8');
|
|
637
|
+
logger.info(`[ui-ext:regex] remote-agent-msg: patched (strategy C, sc=${scVar})`);
|
|
638
|
+
return true;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
// 策略B (v4.11~v4.1x fallback): compound = hasToolCards && (showToolCalls ?? !0)
|
|
627
642
|
const compoundRe = new RegExp(`(\\w+)=${hasToolCardsVar}&&\\(\\w+\\.showToolCalls\\?\\?!0\\)`);
|
|
628
643
|
const compoundMatch = content.match(compoundRe);
|
|
629
644
|
if (!compoundMatch) {
|
|
630
|
-
logger.warn('[ui-ext:regex] remote-agent-msg:
|
|
645
|
+
logger.warn('[ui-ext:regex] remote-agent-msg: all strategies (A/C/B) failed');
|
|
631
646
|
return false;
|
|
632
647
|
}
|
|
633
648
|
|
|
634
|
-
const compoundVar = compoundMatch[1]
|
|
649
|
+
const compoundVar = compoundMatch[1]!;
|
|
635
650
|
const ifReB = new RegExp(`if\\(!(\\w+)&&!${compoundVar}&&`);
|
|
636
651
|
const ifMatchB = content.match(ifReB);
|
|
637
652
|
if (!ifMatchB) {
|
|
@@ -639,7 +654,7 @@ const remoteAgentMessageShortCircuit: UIExtension = {
|
|
|
639
654
|
return false;
|
|
640
655
|
}
|
|
641
656
|
|
|
642
|
-
const markdownVarB = ifMatchB[1]
|
|
657
|
+
const markdownVarB = ifMatchB[1]!;
|
|
643
658
|
const patchedCond = `if(${marker}(!${markdownVarB}||window.__openagentOwnsToolCards&&window.__openagentOwnsToolCards(${toolCardsVar}))&&!${compoundVar}&&`;
|
|
644
659
|
content = content.substring(0, ifMatchB.index!) + patchedCond + content.substring(ifMatchB.index! + ifMatchB[0].length);
|
|
645
660
|
writeFileSync(bundlePath, content, 'utf-8');
|
|
@@ -668,14 +683,16 @@ const mentionHooks: UIExtension = {
|
|
|
668
683
|
if (!backupFile(bundlePath)) return false;
|
|
669
684
|
|
|
670
685
|
// 注入点 A: handleKeyDown
|
|
671
|
-
|
|
686
|
+
// 匹配 return;if(key===Enter&&!shiftKey){if(isComposing 结构
|
|
687
|
+
// 兼容 2026.4.x: return;if (无 }) 和旧版 ;return}if (有 })
|
|
688
|
+
const keydownRe = /;return\}?if\(([a-zA-Z_$][a-zA-Z0-9_$]*)\.key===`Enter`&&!\1\.shiftKey\)\{if\(\1\.isComposing/;
|
|
672
689
|
const keydownMatch = content.match(keydownRe);
|
|
673
690
|
if (!keydownMatch) {
|
|
674
691
|
logger.warn('[ui-ext:regex] mention-hooks: keydown anchor not found');
|
|
675
692
|
return false;
|
|
676
693
|
}
|
|
677
694
|
const eventParam = keydownMatch[1];
|
|
678
|
-
const keydownInsertIdx = content.indexOf(keydownMatch[0]) + '
|
|
695
|
+
const keydownInsertIdx = content.indexOf(keydownMatch[0]) + keydownMatch[0].indexOf('if(');
|
|
679
696
|
const markerA = makeMarker(this.id);
|
|
680
697
|
const hookA = `${markerA}if(window.__clMention?.onKeyDown(${eventParam}))return;`;
|
|
681
698
|
content = content.substring(0, keydownInsertIdx) + hookA + content.substring(keydownInsertIdx);
|
package/src/runtime/account.ts
CHANGED
|
@@ -39,7 +39,6 @@ import { createTransport } from '../transport/factory.js';
|
|
|
39
39
|
import type {
|
|
40
40
|
AgentTransport,
|
|
41
41
|
AgentStatusResult,
|
|
42
|
-
ClaimResult,
|
|
43
42
|
OasnTransport,
|
|
44
43
|
TransportCredentials,
|
|
45
44
|
} from '../transport/types.js';
|
|
@@ -310,28 +309,6 @@ export class AccountRuntime {
|
|
|
310
309
|
this._statusPollTimer = null;
|
|
311
310
|
}
|
|
312
311
|
|
|
313
|
-
async claimOwnerEmail(ownerEmail: string): Promise<ClaimResult> {
|
|
314
|
-
if (this._transportType !== 'oasn') {
|
|
315
|
-
throw new Error('Agent claim is only available in OASN mode');
|
|
316
|
-
}
|
|
317
|
-
await this.ensureConnected();
|
|
318
|
-
const transport = this.transport;
|
|
319
|
-
if (!transport || transport.transportType !== 'oasn') {
|
|
320
|
-
throw new Error('OASN transport not ready');
|
|
321
|
-
}
|
|
322
|
-
const oasnTransport = transport as OasnTransport;
|
|
323
|
-
const result = await oasnTransport.claimAgent({
|
|
324
|
-
agent_id: this._config?.agentId,
|
|
325
|
-
owner_email: ownerEmail,
|
|
326
|
-
});
|
|
327
|
-
this._claimStatus = 'claim_pending';
|
|
328
|
-
this._claimExpiresAt = result.expires_at;
|
|
329
|
-
this._saveOasnAccountConfig({ status: 'claim_pending' });
|
|
330
|
-
this._scheduleOasnStatusPolling(oasnTransport);
|
|
331
|
-
logger.info(`[runtime] OASN claim started: agent_id=${result.agent_id} owner=${result.owner_email_masked} expires_at=${result.expires_at}`);
|
|
332
|
-
return result;
|
|
333
|
-
}
|
|
334
|
-
|
|
335
312
|
assertOasnInvocationAllowed(): void {
|
|
336
313
|
if (this._transportType === 'oasn' && this._claimStatus !== 'claimed') {
|
|
337
314
|
throw new Error(`OASN ClientAgent is not claimed yet (status=${this._claimStatus}). Complete claim before calling remote agents.`);
|
|
@@ -155,11 +155,11 @@ export class OasnFiles {
|
|
|
155
155
|
);
|
|
156
156
|
|
|
157
157
|
return {
|
|
158
|
-
fileRef: resp.file_ref,
|
|
159
|
-
displayName: resp.display_name,
|
|
160
|
-
mimeType: resp.mime_type,
|
|
161
|
-
sizeBytes: resp.size_bytes,
|
|
162
|
-
expiresAt: this._parseExpiresAt(resp.expires_at),
|
|
158
|
+
fileRef: resp.fileRef ?? resp.file_ref ?? '',
|
|
159
|
+
displayName: resp.displayName ?? resp.display_name ?? 'unknown',
|
|
160
|
+
mimeType: resp.mimeType ?? resp.mime_type ?? 'application/octet-stream',
|
|
161
|
+
sizeBytes: resp.sizeBytes ?? resp.size_bytes ?? 0,
|
|
162
|
+
expiresAt: this._parseExpiresAt(resp.expiresAt ?? resp.expires_at ?? ''),
|
|
163
163
|
};
|
|
164
164
|
}
|
|
165
165
|
|
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
type TaskRequest,
|
|
39
39
|
type TaskResult,
|
|
40
40
|
type TransportError,
|
|
41
|
+
type WebuiContinuationRef,
|
|
41
42
|
} from '../types.js';
|
|
42
43
|
import type { OasnHttpClient } from './oasn-http.js';
|
|
43
44
|
import {
|
|
@@ -48,6 +49,7 @@ import {
|
|
|
48
49
|
type CreateInvocationResponse,
|
|
49
50
|
type GetInvocationResponse,
|
|
50
51
|
type InvocationStatus,
|
|
52
|
+
type VisibleResultResponse,
|
|
51
53
|
} from './oasn-types.js';
|
|
52
54
|
|
|
53
55
|
/** Invocation 持久化钩子(接 StateStore.pending_invocations,§11.1) */
|
|
@@ -378,31 +380,71 @@ export class OasnInvocation {
|
|
|
378
380
|
/**
|
|
379
381
|
* 把终态 Invocation 响应转换为 TaskResult。
|
|
380
382
|
*
|
|
381
|
-
* - succeeded → status:'complete' + content=summary + artifacts
|
|
383
|
+
* - succeeded → status:'complete' + content=summary + artifacts + webuiContinuation
|
|
382
384
|
* - 其它终态 → status:'error' + content=user_error.message
|
|
385
|
+
*
|
|
386
|
+
* content 的归一路径:
|
|
387
|
+
* inlineResult.summary > visible_result.inline_result_summary > ''
|
|
388
|
+
*
|
|
389
|
+
* webui_continuation 仅在 succeeded 时抽取(失败场景后端不保证存在)。
|
|
383
390
|
*/
|
|
384
391
|
private _toTaskResult(invocationId: string, final: GetInvocationResponse): TaskResult {
|
|
392
|
+
const webuiContinuation = this._toWebuiContinuation(final);
|
|
393
|
+
|
|
385
394
|
if (final.status === 'succeeded') {
|
|
386
395
|
const inlineResult = final.inlineResult ?? final.inline_result;
|
|
396
|
+
const visible = final.visibleResult ?? final.visible_result;
|
|
397
|
+
const summary = inlineResult?.summary
|
|
398
|
+
?? visible?.inlineResultSummary
|
|
399
|
+
?? visible?.inline_result_summary
|
|
400
|
+
?? '';
|
|
387
401
|
return {
|
|
388
402
|
requestId: invocationId,
|
|
389
403
|
status: 'complete',
|
|
390
|
-
content:
|
|
404
|
+
content: summary,
|
|
391
405
|
artifacts: (final.artifacts ?? []).map(this._toArtifactRef),
|
|
406
|
+
webuiContinuation,
|
|
392
407
|
};
|
|
393
408
|
}
|
|
394
409
|
|
|
395
410
|
// 失败/超时/取消 —— 文本统一用 user_error.message 兜底
|
|
396
411
|
const userError = final.userError ?? final.user_error;
|
|
397
412
|
const inlineResult = final.inlineResult ?? final.inline_result;
|
|
413
|
+
const visible = final.visibleResult ?? final.visible_result;
|
|
398
414
|
const message = userError?.message
|
|
399
415
|
?? inlineResult?.summary
|
|
416
|
+
?? visible?.inlineResultSummary
|
|
417
|
+
?? visible?.inline_result_summary
|
|
400
418
|
?? `Invocation ended with status=${final.status}`;
|
|
401
419
|
return {
|
|
402
420
|
requestId: invocationId,
|
|
403
421
|
status: 'error',
|
|
404
422
|
content: message,
|
|
405
423
|
artifacts: (final.artifacts ?? []).map(this._toArtifactRef),
|
|
424
|
+
webuiContinuation,
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* 从终态响应里抽取 WebUI continuation(camelCase / snake_case 双归一)。
|
|
430
|
+
* 缺必要字段(id / launch_url)时返回 undefined,调用方按 falsy 处理即可。
|
|
431
|
+
*/
|
|
432
|
+
private _toWebuiContinuation(final: GetInvocationResponse): WebuiContinuationRef | undefined {
|
|
433
|
+
const visible: VisibleResultResponse | undefined =
|
|
434
|
+
final.visibleResult ?? final.visible_result;
|
|
435
|
+
const raw = visible?.webuiContinuation ?? visible?.webui_continuation;
|
|
436
|
+
if (!raw) return undefined;
|
|
437
|
+
|
|
438
|
+
const id = raw.continuationId ?? raw.continuation_id;
|
|
439
|
+
const launchUrl = raw.launchUrl ?? raw.launch_url;
|
|
440
|
+
if (!id || !launchUrl) return undefined;
|
|
441
|
+
|
|
442
|
+
return {
|
|
443
|
+
id,
|
|
444
|
+
launchUrl,
|
|
445
|
+
displayName: raw.displayName ?? raw.display_name ?? 'Open WebUI',
|
|
446
|
+
visibleState: raw.visibleState ?? raw.visible_state ?? 'available',
|
|
447
|
+
sessionId: raw.sessionId ?? raw.session_id,
|
|
406
448
|
};
|
|
407
449
|
}
|
|
408
450
|
|
|
@@ -3,8 +3,6 @@ import type {
|
|
|
3
3
|
AgentStatusResult,
|
|
4
4
|
CategoryNode,
|
|
5
5
|
CategoryTree,
|
|
6
|
-
ClaimResult,
|
|
7
|
-
RegisterResult,
|
|
8
6
|
SearchResult,
|
|
9
7
|
} from '../types.js';
|
|
10
8
|
import type {
|
|
@@ -12,8 +10,6 @@ import type {
|
|
|
12
10
|
AgentStatusResponse,
|
|
13
11
|
CategoryNodeResponse,
|
|
14
12
|
CategoryTreeResponse,
|
|
15
|
-
ClaimAgentResponse,
|
|
16
|
-
RegisterAgentResponse,
|
|
17
13
|
SearchResponse,
|
|
18
14
|
} from './oasn-types.js';
|
|
19
15
|
|
|
@@ -96,28 +92,6 @@ export function normalizeAgentCard(resp: AgentCardResponse | unknown): AgentCard
|
|
|
96
92
|
};
|
|
97
93
|
}
|
|
98
94
|
|
|
99
|
-
export function normalizeRegisterResult(resp: RegisterAgentResponse | unknown): RegisterResult {
|
|
100
|
-
const record = asRecord(resp);
|
|
101
|
-
return {
|
|
102
|
-
agent_id: pickString(record, 'agentId', 'agent_id'),
|
|
103
|
-
agent_type: (pickString(record, 'agentType', 'agent_type') || 'client') as 'client',
|
|
104
|
-
api_key: pickString(record, 'apiKey', 'api_key'),
|
|
105
|
-
claim_url: pickString(record, 'claimUrl', 'claim_url'),
|
|
106
|
-
status: (pickString(record, 'status') || 'unclaimed') as 'unclaimed',
|
|
107
|
-
agent_card: normalizeAgentCard(pickRecord(record, 'agentCard', 'agent_card')),
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
export function normalizeClaimResult(resp: ClaimAgentResponse | unknown): ClaimResult {
|
|
112
|
-
const record = asRecord(resp);
|
|
113
|
-
return {
|
|
114
|
-
agent_id: pickString(record, 'agentId', 'agent_id'),
|
|
115
|
-
status: (pickString(record, 'status') || 'claim_email_sent') as 'claim_email_sent',
|
|
116
|
-
owner_email_masked: pickString(record, 'ownerEmailMasked', 'owner_email_masked'),
|
|
117
|
-
expires_at: pickString(record, 'expiresAt', 'expires_at'),
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
|
|
121
95
|
export function normalizeAgentStatus(resp: AgentStatusResponse | unknown): AgentStatusResult {
|
|
122
96
|
const record = asRecord(resp);
|
|
123
97
|
return {
|
|
@@ -1,101 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* OASN Agent
|
|
2
|
+
* OASN Agent 状态查询
|
|
3
3
|
*
|
|
4
4
|
* 设计依据:
|
|
5
|
-
* - docs/specs/2026-06-16-oasn-api-module-mapping.md §2.
|
|
5
|
+
* - docs/specs/2026-06-16-oasn-api-module-mapping.md §2.3
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* - claimAgent:用户主动触发认领(带 owner_email)
|
|
10
|
-
*
|
|
11
|
-
* 关键约束:
|
|
12
|
-
* - register 返回的 api_key **是明文且仅此一次**。调用方必须立即持久化(最好走 keychain,§11.6)
|
|
13
|
-
* - 当前后端 RegisterAgentCommand 只定义 platform;install_id/device_hint 需先扩展后端契约
|
|
7
|
+
* 注意:register 和 claim 已迁移到 CLI(openclaw-plugin-openagent-cli),
|
|
8
|
+
* 本模块仅保留 getStatus(GET /api/agents/{agent_id})。
|
|
14
9
|
*/
|
|
15
10
|
|
|
16
11
|
import { logger } from '../../util/logger.js';
|
|
17
|
-
import type { AgentStatusResult
|
|
12
|
+
import type { AgentStatusResult } from '../types.js';
|
|
18
13
|
import type { OasnHttpClient } from './oasn-http.js';
|
|
19
14
|
import {
|
|
20
15
|
OASN_ENDPOINTS,
|
|
21
|
-
type ClaimAgentRequest,
|
|
22
|
-
type ClaimAgentResponse,
|
|
23
16
|
type AgentStatusResponse,
|
|
24
|
-
type RegisterAgentRequest,
|
|
25
|
-
type RegisterAgentResponse,
|
|
26
17
|
} from './oasn-types.js';
|
|
27
|
-
import {
|
|
28
|
-
normalizeAgentStatus,
|
|
29
|
-
normalizeClaimResult,
|
|
30
|
-
normalizeRegisterResult,
|
|
31
|
-
} from './oasn-normalize.js';
|
|
18
|
+
import { normalizeAgentStatus } from './oasn-normalize.js';
|
|
32
19
|
|
|
33
20
|
/**
|
|
34
|
-
* OASN Agent
|
|
35
|
-
*
|
|
36
|
-
* 注意 register 和 claim 是 OASN-only 能力,TIM transport 不暴露这两个方法。
|
|
37
|
-
* AccountRuntime 在 transport-type === 'oasn' 时才能调用。
|
|
21
|
+
* OASN Agent 状态查询模块。
|
|
38
22
|
*/
|
|
39
|
-
export class
|
|
23
|
+
export class OasnAgentStatus {
|
|
40
24
|
constructor(private readonly _http: OasnHttpClient) {}
|
|
41
25
|
|
|
42
|
-
/**
|
|
43
|
-
* 注册新 Agent(首次安装流程)。
|
|
44
|
-
*
|
|
45
|
-
* @param platform OpenClaw 上固定为 "openclaw"
|
|
46
|
-
* @returns 含一次性明文 api_key 的注册响应。调用方必须立即持久化。
|
|
47
|
-
*/
|
|
48
|
-
async register(
|
|
49
|
-
platform: string,
|
|
50
|
-
_params?: { installId?: string; deviceHint?: string },
|
|
51
|
-
): Promise<RegisterResult> {
|
|
52
|
-
const body: RegisterAgentRequest = { platform };
|
|
53
|
-
|
|
54
|
-
logger.info(`[transport/oasn/register] register platform=${platform}`);
|
|
55
|
-
|
|
56
|
-
// skipRetry=true:register 是不幂等的写入,重试可能创建多个 agent
|
|
57
|
-
const resp = await this._http.post<RegisterAgentResponse>(
|
|
58
|
-
OASN_ENDPOINTS.REGISTER,
|
|
59
|
-
body,
|
|
60
|
-
{ skipRetry: true },
|
|
61
|
-
);
|
|
62
|
-
|
|
63
|
-
const result = normalizeRegisterResult(resp);
|
|
64
|
-
logger.info(`[transport/oasn/register] registered agent_id=${result.agent_id} status=${result.status}`);
|
|
65
|
-
return result;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* 触发认领邮件发送。
|
|
70
|
-
* 认证方式由 OasnHttpClient 注入的 Bearer 决定:
|
|
71
|
-
* - 带 api_key:传入 { agent_id, owner_email }
|
|
72
|
-
* - 不带 api_key(首次进入):传入 { claim_token, owner_email }
|
|
73
|
-
*/
|
|
74
|
-
async claim(params: ClaimParams): Promise<ClaimResult> {
|
|
75
|
-
if (!params.agent_id && !params.claim_token) {
|
|
76
|
-
throw new Error('OasnRegister.claim: must provide either agent_id or claim_token');
|
|
77
|
-
}
|
|
78
|
-
if (!params.owner_email) {
|
|
79
|
-
throw new Error('OasnRegister.claim: owner_email required');
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const body: ClaimAgentRequest = {
|
|
83
|
-
ownerEmail: params.owner_email,
|
|
84
|
-
};
|
|
85
|
-
if (params.agent_id) body.agentId = params.agent_id;
|
|
86
|
-
if (params.claim_token) body.claimToken = params.claim_token;
|
|
87
|
-
|
|
88
|
-
logger.info(`[transport/oasn/register] claim email=${params.owner_email.replace(/(.).+(@.+)/, '$1***$2')}`);
|
|
89
|
-
|
|
90
|
-
const resp = await this._http.post<ClaimAgentResponse>(
|
|
91
|
-
OASN_ENDPOINTS.CLAIM,
|
|
92
|
-
body,
|
|
93
|
-
{ skipRetry: true },
|
|
94
|
-
);
|
|
95
|
-
|
|
96
|
-
return normalizeClaimResult(resp);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
26
|
async getStatus(agentId: string): Promise<AgentStatusResult> {
|
|
100
27
|
const resp = await this._http.get<AgentStatusResponse>(
|
|
101
28
|
OASN_ENDPOINTS.AGENT_STATUS(agentId),
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*
|
|
8
8
|
* 子模块组装:
|
|
9
9
|
* - OasnHttpClient HTTP 基础(Bearer 注入 / 重试 / 401 拦截)
|
|
10
|
-
* -
|
|
10
|
+
* - OasnAgentStatus agent status query (GET /api/agents/{agent_id})
|
|
11
11
|
* - OasnAgentCard get / update / getCurrentOwner
|
|
12
12
|
* - OasnDiscovery search / categories
|
|
13
13
|
* - OasnInvocation sendTask / waitForTaskResult(核心路径)
|
|
@@ -37,14 +37,11 @@ import {
|
|
|
37
37
|
type AgentCardPatch,
|
|
38
38
|
type AgentStatusResult,
|
|
39
39
|
type CategoryTree,
|
|
40
|
-
type ClaimParams,
|
|
41
|
-
type ClaimResult,
|
|
42
40
|
type CoreTransportEvent,
|
|
43
41
|
type DownloadArtifactResult,
|
|
44
42
|
type OasnTransport,
|
|
45
43
|
type OwnerInfo,
|
|
46
44
|
type ProgressCallback,
|
|
47
|
-
type RegisterResult,
|
|
48
45
|
type SearchQuery,
|
|
49
46
|
type SearchResult,
|
|
50
47
|
type TaskHandle,
|
|
@@ -64,7 +61,7 @@ import {
|
|
|
64
61
|
type CreateInvocationOptions,
|
|
65
62
|
type PendingInvocationStore,
|
|
66
63
|
} from './oasn-invocation.js';
|
|
67
|
-
import {
|
|
64
|
+
import { OasnAgentStatus } from './oasn-register.js';
|
|
68
65
|
|
|
69
66
|
// ───────────────────────────────────────────────────────────────
|
|
70
67
|
// 构造选项
|
|
@@ -102,7 +99,7 @@ export class OasnTransportImpl extends EventEmitter implements OasnTransport {
|
|
|
102
99
|
private _accessHttp: OasnHttpClient;
|
|
103
100
|
private _agentCard: OasnAgentCard;
|
|
104
101
|
private _discovery: OasnDiscovery;
|
|
105
|
-
private
|
|
102
|
+
private _agentStatus: OasnAgentStatus;
|
|
106
103
|
private _invocation: OasnInvocation;
|
|
107
104
|
private _files: OasnFiles;
|
|
108
105
|
|
|
@@ -131,7 +128,7 @@ export class OasnTransportImpl extends EventEmitter implements OasnTransport {
|
|
|
131
128
|
// ── 子模块(共享 HTTP 实例) ──────────────────────────────────
|
|
132
129
|
this._agentCard = new OasnAgentCard(this._http);
|
|
133
130
|
this._discovery = new OasnDiscovery(this._http);
|
|
134
|
-
this.
|
|
131
|
+
this._agentStatus = new OasnAgentStatus(this._http);
|
|
135
132
|
this._invocation = new OasnInvocation(this._accessHttp, options.pendingStore);
|
|
136
133
|
this._files = new OasnFiles(this._accessHttp);
|
|
137
134
|
}
|
|
@@ -165,7 +162,7 @@ export class OasnTransportImpl extends EventEmitter implements OasnTransport {
|
|
|
165
162
|
|
|
166
163
|
if (this._agentId) {
|
|
167
164
|
try {
|
|
168
|
-
const status = await this.
|
|
165
|
+
const status = await this._agentStatus.getStatus(this._agentId);
|
|
169
166
|
this._claimStatus = status.status;
|
|
170
167
|
logger.info(
|
|
171
168
|
`[transport/oasn] ready agent_id=${this._agentId} `
|
|
@@ -264,33 +261,13 @@ export class OasnTransportImpl extends EventEmitter implements OasnTransport {
|
|
|
264
261
|
}
|
|
265
262
|
|
|
266
263
|
// ═══════════════════════════════════════════════════════════════
|
|
267
|
-
//
|
|
264
|
+
// AgentCard / Status(OASN-only)
|
|
268
265
|
// ═══════════════════════════════════════════════════════════════
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
* 注册新 Agent。
|
|
272
|
-
*
|
|
273
|
-
* 注意:register 不要求 ready() —— 首次安装时还没有 api_key。
|
|
274
|
-
* 但 register 成功后,调用方需立即把 api_key 持久化 + 调 ready() 进入可工作状态。
|
|
275
|
-
*/
|
|
276
|
-
async registerAgent(
|
|
277
|
-
platform: string,
|
|
278
|
-
params?: { installId?: string; deviceHint?: string },
|
|
279
|
-
): Promise<RegisterResult> {
|
|
280
|
-
const result = await this._register.register(platform, params);
|
|
281
|
-
// 回填 agentId(后续 ready() 探活会用到)
|
|
282
|
-
this._agentId = result.agent_id;
|
|
283
|
-
return result;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
async claimAgent(params: ClaimParams): Promise<ClaimResult> {
|
|
287
|
-
const result = await this._register.claim(params);
|
|
288
|
-
this._claimStatus = 'claim_pending';
|
|
289
|
-
return result;
|
|
290
|
-
}
|
|
266
|
+
//
|
|
267
|
+
// registerAgent / claimAgent 已迁移到 CLI,此处仅保留状态查询。
|
|
291
268
|
|
|
292
269
|
async getAgentStatus(agentId: string): Promise<AgentStatusResult> {
|
|
293
|
-
const result = await this.
|
|
270
|
+
const result = await this._agentStatus.getStatus(agentId);
|
|
294
271
|
this._claimStatus = result.status;
|
|
295
272
|
return result;
|
|
296
273
|
}
|
|
@@ -258,6 +258,40 @@ export interface ArtifactResponse {
|
|
|
258
258
|
content_url?: string;
|
|
259
259
|
}
|
|
260
260
|
|
|
261
|
+
/**
|
|
262
|
+
* OASN WebUI continuation —— 标准 run 完成后,声明了 webui 能力的 ServiceAgent
|
|
263
|
+
* 会在用户视图里暴露一个可继续打开 WebUI 的入口。
|
|
264
|
+
*
|
|
265
|
+
* 后端同时兼容 camelCase / snake_case,插件两侧都需要做 fallback 归一。
|
|
266
|
+
* launch_url 通常是相对路径(如 /webui/continuations/{continuation_id}),
|
|
267
|
+
* 由上层按 OASN Access base URL 解析为绝对地址。
|
|
268
|
+
*/
|
|
269
|
+
export interface WebuiContinuationResponse {
|
|
270
|
+
continuationId?: string;
|
|
271
|
+
continuation_id?: string;
|
|
272
|
+
type?: string;
|
|
273
|
+
displayName?: string;
|
|
274
|
+
display_name?: string;
|
|
275
|
+
visibleState?: string;
|
|
276
|
+
visible_state?: string;
|
|
277
|
+
sessionId?: string;
|
|
278
|
+
session_id?: string;
|
|
279
|
+
launchUrl?: string;
|
|
280
|
+
launch_url?: string;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* 用户视图结果 —— 后端在 sanitizeInvocationView() 后追加的结构。
|
|
285
|
+
* 除已声明字段外,保留 index signature 以容纳后续新增字段。
|
|
286
|
+
*/
|
|
287
|
+
export interface VisibleResultResponse {
|
|
288
|
+
inlineResultSummary?: string;
|
|
289
|
+
inline_result_summary?: string;
|
|
290
|
+
webuiContinuation?: WebuiContinuationResponse;
|
|
291
|
+
webui_continuation?: WebuiContinuationResponse;
|
|
292
|
+
[key: string]: unknown;
|
|
293
|
+
}
|
|
294
|
+
|
|
261
295
|
export interface GetInvocationResponse {
|
|
262
296
|
invocationId?: string;
|
|
263
297
|
invocation_id?: string;
|
|
@@ -273,6 +307,10 @@ export interface GetInvocationResponse {
|
|
|
273
307
|
summary: string;
|
|
274
308
|
[key: string]: unknown;
|
|
275
309
|
};
|
|
310
|
+
/** 用户视图 —— 含 inline_result_summary 与 webui_continuation(camelCase) */
|
|
311
|
+
visibleResult?: VisibleResultResponse;
|
|
312
|
+
/** 用户视图 —— 含 inline_result_summary 与 webui_continuation(snake_case) */
|
|
313
|
+
visible_result?: VisibleResultResponse;
|
|
276
314
|
artifacts?: ArtifactResponse[];
|
|
277
315
|
/** 终态时为 null */
|
|
278
316
|
nextPollAfterMs?: number | null;
|
|
@@ -291,13 +329,22 @@ export interface GetInvocationResponse {
|
|
|
291
329
|
// ═══════════════════════════════════════════════════════════════
|
|
292
330
|
|
|
293
331
|
export interface UploadFileResponse {
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
332
|
+
// snake_case (旧,向后兼容)
|
|
333
|
+
file_ref?: string;
|
|
334
|
+
display_name?: string;
|
|
335
|
+
mime_type?: string;
|
|
336
|
+
size_bytes?: number;
|
|
298
337
|
/** ISO 8601 字符串 */
|
|
299
|
-
expires_at
|
|
300
|
-
created_at
|
|
338
|
+
expires_at?: string;
|
|
339
|
+
created_at?: string;
|
|
340
|
+
// camelCase (access 层实际返回,见 access-upload-download-api.md §2.2)
|
|
341
|
+
fileRef?: string;
|
|
342
|
+
displayName?: string;
|
|
343
|
+
mimeType?: string;
|
|
344
|
+
sizeBytes?: number;
|
|
345
|
+
/** ISO 8601 字符串 */
|
|
346
|
+
expiresAt?: string | null;
|
|
347
|
+
createdAt?: string;
|
|
301
348
|
}
|
|
302
349
|
|
|
303
350
|
// Artifact 下载返回二进制,没有 JSON 结构 —— 详见 oasn-files.ts
|