@aramisfa/openclaw-a2a-outbound 0.2.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +355 -33
  2. package/dist/capability-diagnostics.d.ts +13 -0
  3. package/dist/capability-diagnostics.d.ts.map +1 -0
  4. package/dist/capability-diagnostics.js +131 -0
  5. package/dist/capability-diagnostics.js.map +1 -0
  6. package/dist/errors.d.ts +1 -0
  7. package/dist/errors.d.ts.map +1 -1
  8. package/dist/errors.js +1 -0
  9. package/dist/errors.js.map +1 -1
  10. package/dist/request-normalization.d.ts +4 -10
  11. package/dist/request-normalization.d.ts.map +1 -1
  12. package/dist/request-normalization.js +83 -47
  13. package/dist/request-normalization.js.map +1 -1
  14. package/dist/result-shape.d.ts +58 -15
  15. package/dist/result-shape.d.ts.map +1 -1
  16. package/dist/result-shape.js +324 -85
  17. package/dist/result-shape.js.map +1 -1
  18. package/dist/schemas.d.ts +28 -5
  19. package/dist/schemas.d.ts.map +1 -1
  20. package/dist/schemas.js +128 -21
  21. package/dist/schemas.js.map +1 -1
  22. package/dist/sdk-client-pool.d.ts +0 -2
  23. package/dist/sdk-client-pool.d.ts.map +1 -1
  24. package/dist/sdk-client-pool.js +2 -22
  25. package/dist/sdk-client-pool.js.map +1 -1
  26. package/dist/service.d.ts +4 -2
  27. package/dist/service.d.ts.map +1 -1
  28. package/dist/service.js +333 -80
  29. package/dist/service.js.map +1 -1
  30. package/dist/target-catalog.d.ts +27 -5
  31. package/dist/target-catalog.d.ts.map +1 -1
  32. package/dist/target-catalog.js +164 -58
  33. package/dist/target-catalog.js.map +1 -1
  34. package/dist/task-handle-registry.d.ts +3 -2
  35. package/dist/task-handle-registry.d.ts.map +1 -1
  36. package/dist/task-handle-registry.js +7 -0
  37. package/dist/task-handle-registry.js.map +1 -1
  38. package/openclaw.plugin.json +42 -12
  39. package/package.json +10 -10
  40. package/skills/remote-agent/SKILL.md +74 -8
  41. package/dist/plugin-config.d.ts +0 -5
  42. package/dist/plugin-config.d.ts.map +0 -1
  43. package/dist/plugin-config.js +0 -89
  44. package/dist/plugin-config.js.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aramisfa/openclaw-a2a-outbound",
3
- "version": "0.2.2",
3
+ "version": "2.0.0",
4
4
  "description": "Outbound A2A delegation plugin for OpenClaw agents",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -41,14 +41,6 @@
41
41
  "./dist/index.js"
42
42
  ]
43
43
  },
44
- "scripts": {
45
- "build": "tsc -b",
46
- "typecheck:src": "tsc -b --pretty false",
47
- "typecheck:tests": "tsc -p tsconfig.tests.json --pretty false",
48
- "typecheck": "corepack pnpm run typecheck:src && corepack pnpm run typecheck:tests",
49
- "test": "corepack pnpm run build && node --import tsx --test tests/*.test.ts",
50
- "clean": "rm -rf dist"
51
- },
52
44
  "dependencies": {
53
45
  "@a2a-js/sdk": "^0.3.10",
54
46
  "ajv": "^8.18.0",
@@ -67,5 +59,13 @@
67
59
  },
68
60
  "publishConfig": {
69
61
  "access": "public"
62
+ },
63
+ "scripts": {
64
+ "build": "tsc -b",
65
+ "typecheck:src": "tsc -b --pretty false",
66
+ "typecheck:tests": "tsc -p tsconfig.tests.json --pretty false",
67
+ "typecheck": "corepack pnpm run typecheck:src && corepack pnpm run typecheck:tests",
68
+ "test": "corepack pnpm run build && node --import tsx --test tests/*.test.ts",
69
+ "clean": "rm -rf dist"
70
70
  }
71
- }
71
+ }
@@ -1,12 +1,14 @@
1
1
  ---
2
2
  name: remote-agent
3
3
  description: Delegate work to external A2A agents using the remote_agent tool.
4
- metadata: {"openclaw": {"requires": {"config": ["plugins.entries.openclaw-a2a-outbound.enabled"]}}}
4
+ metadata: {"openclaw": {"requires": {"config": ["plugins.entries.openclaw-a2a-outbound.enabled", "plugins.entries.openclaw-a2a-outbound.config.enabled"]}}}
5
5
  ---
6
6
 
7
7
  # Remote Agent Delegation
8
8
 
9
- Use the `remote_agent` tool to delegate work to external A2A-compatible agents and manage delegated tasks.
9
+ If the plugin is not installed or configured yet, use the `a2a-delegation-setup` skill first.
10
+
11
+ Use the `remote_agent` tool to delegate work to external A2A-compatible agents and manage delegated tasks. `send` is the only action to start a new remote turn or continue an existing one.
10
12
 
11
13
  ## When to delegate
12
14
 
@@ -38,21 +40,85 @@ Discover configured targets.
38
40
 
39
41
  ### send
40
42
 
41
- Send a request to a remote agent.
43
+ Send a request to a remote agent. Use it for:
44
+
45
+ - a brand-new remote task
46
+ - a follow-up turn on an existing remote task
47
+ - a related new task that references prior work
48
+ - a new task inside an existing remote conversation
42
49
 
43
50
  ```json
44
51
  {
45
52
  "action": "send",
46
53
  "target_alias": "my-agent",
47
- "input": "Summarize the latest quarterly report.",
54
+ "parts": [
55
+ {
56
+ "kind": "text",
57
+ "text": "Summarize the latest quarterly report."
58
+ }
59
+ ],
48
60
  "follow_updates": true
49
61
  }
50
62
  ```
51
63
 
52
- - `input` (required): the user text to send.
64
+ - `parts` (required): non-empty array of `text`, `file`, or `data` parts.
53
65
  - `target_alias`: configured target name. Omit when a default target exists.
54
- - `follow_updates`: when `true`, streams updates and returns the full event log.
55
- - `attachments`: optional array of file or data attachments.
66
+ - `task_handle`: preferred continuation key for `send`, `watch`, `status`, and `cancel`.
67
+ - `task_id`: optional continuation id for `send`; for follow-up actions it identifies the remote task when no `task_handle` is available. `task_id` continues an existing task.
68
+ - `context_id`: optional conversation continuation id for `send`. Use it with `task_id`, or by itself to start a new task in the same conversation.
69
+ - `reference_task_ids`: optional related task ids for `send`. `reference_task_ids` references prior tasks without continuing them.
70
+ - `task_requirement`: optional durability contract. `task_requirement="required"` forces explicit task creation or fails fast.
71
+ - `follow_updates`: when `true`, streams updates and returns the full event log. `follow_updates=true` means “stream the initial send”; it does not guarantee task creation unless `task_requirement="required"`.
72
+ - `blocking`: only for non-stream `send`; do not combine it with `follow_updates=true`.
73
+
74
+ Preferred continuation forms:
75
+
76
+ ```json
77
+ { "action": "send", "task_handle": "rah_abc123", "parts": [{ "kind": "text", "text": "Approved. Continue." }] }
78
+ ```
79
+
80
+ ```json
81
+ { "action": "send", "target_alias": "my-agent", "task_id": "task-123", "parts": [{ "kind": "text", "text": "Continue the task." }] }
82
+ ```
83
+
84
+ ```json
85
+ { "action": "send", "target_alias": "my-agent", "context_id": "ctx-123", "parts": [{ "kind": "text", "text": "Start a new task in the same conversation." }] }
86
+ ```
87
+
88
+ ```json
89
+ { "action": "send", "target_alias": "my-agent", "context_id": "ctx-123", "reference_task_ids": ["task-1", "task-2"], "parts": [{ "kind": "text", "text": "Start related work without continuing those tasks." }] }
90
+ ```
91
+
92
+ ## Continuation safety
93
+
94
+ Interpret follow-up capability from `result.summary.continuation`, not from prompt text, message text, or other inferred context.
95
+
96
+ - `response_kind` is descriptive only. Keep follow-up logic anchored to `summary.continuation`.
97
+ - `summary.continuation.task`: trackable task continuity. Use it for follow-up `send`, `watch`, `status`, and `cancel`.
98
+ - `summary.continuation.conversation`: conversation continuity only. Use it only with `send` to start a new task in the same conversation.
99
+ - Branch on `summary.continuation.task` vs `summary.continuation.conversation` before choosing the next action.
100
+ - Never infer or synthesize `summary.continuation.task` from `summary.continuation.conversation`, session ids, run ids, prior prompts, or summary text.
101
+ - Do not call `watch`, `status`, or `cancel` from a result that has only `summary.continuation.conversation`.
102
+ - If lifecycle tracking is required, fail fast when the peer returns only `summary.continuation.conversation`.
103
+
104
+ ```ts
105
+ const task = result.summary.continuation?.task
106
+ const conversation = result.summary.continuation?.conversation
107
+
108
+ if (task) {
109
+ // Trackable task lifecycle.
110
+ } else if (conversation) {
111
+ // Send-only conversation continuity.
112
+ }
113
+ ```
114
+
115
+ Invalid follow-up example:
116
+
117
+ ```json
118
+ { "action": "status", "context_id": "ctx-123" }
119
+ ```
120
+
121
+ That is invalid because `status`, `watch`, and `cancel` require task continuity, not just conversation continuity.
56
122
 
57
123
  ### status
58
124
 
@@ -80,7 +146,7 @@ Cancel a running task.
80
146
 
81
147
  ## Task handles
82
148
 
83
- After a successful `send`, the result includes a `task_handle` (prefixed `rah_`). Always prefer `task_handle` over `target_alias + task_id` for follow-up actions — the handle encodes the target and task identity in one opaque token. Handles are process-local and expire after restart or TTL. If a handle expires, fall back to `target_alias` + `task_id`.
149
+ After a successful `send`, the result usually includes `summary.continuation.task.task_handle` (prefixed `rah_`) when the remote peer exposes task continuity. `task_handle` is returned only when the peer actually created a task. Always prefer `summary.continuation.task.task_handle` over `target_alias + summary.continuation.task.task_id` for follow-up `send`/`watch`/`status`/`cancel` actions. Handles are process-local and expire after restart or TTL. If a handle expires, fall back to `target_alias` + `summary.continuation.task.task_id`. Treat `send.task_id` as a continuation id for the remote peer, not as a replacement for `summary.continuation.task.task_handle`. If the result includes only `summary.continuation.conversation`, there is no task lifecycle to poll, watch, or cancel.
84
150
 
85
151
  ## watch vs status
86
152
 
@@ -1,5 +0,0 @@
1
- import type { OpenClawPluginConfigSchema } from "openclaw/plugin-sdk";
2
- import { type A2AOutboundPluginConfig } from "./constants.js";
3
- export declare function parseA2AOutboundPluginConfig(input: unknown): A2AOutboundPluginConfig;
4
- export declare const A2AOutboundPluginConfigSchema: OpenClawPluginConfigSchema;
5
- //# sourceMappingURL=plugin-config.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"plugin-config.d.ts","sourceRoot":"","sources":["../src/plugin-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,EAGL,KAAK,uBAAuB,EAE7B,MAAM,gBAAgB,CAAC;AAuFxB,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,OAAO,GACb,uBAAuB,CA4CzB;AAED,eAAO,MAAM,6BAA6B,EAAE,0BAI3C,CAAC"}
@@ -1,89 +0,0 @@
1
- import { ALL_TRANSPORTS, DEFAULTS, } from "./constants.js";
2
- function cloneConfig(config) {
3
- return {
4
- enabled: config.enabled,
5
- defaults: {
6
- timeoutMs: config.defaults.timeoutMs,
7
- cardPath: config.defaults.cardPath,
8
- preferredTransports: [...config.defaults.preferredTransports],
9
- serviceParameters: { ...config.defaults.serviceParameters },
10
- },
11
- policy: {
12
- acceptedOutputModes: [...config.policy.acceptedOutputModes],
13
- normalizeBaseUrl: config.policy.normalizeBaseUrl,
14
- enforceSupportedTransports: config.policy.enforceSupportedTransports,
15
- },
16
- };
17
- }
18
- function isPlainObject(value) {
19
- return typeof value === "object" && value !== null && !Array.isArray(value);
20
- }
21
- function normalizeStringArray(value, fallback = []) {
22
- if (!Array.isArray(value)) {
23
- return [...fallback];
24
- }
25
- const normalized = [];
26
- for (const entry of value) {
27
- if (typeof entry !== "string" || entry.trim() === "") {
28
- continue;
29
- }
30
- if (!normalized.includes(entry)) {
31
- normalized.push(entry);
32
- }
33
- }
34
- return normalized;
35
- }
36
- function normalizeTransports(value, fallback) {
37
- const normalized = normalizeStringArray(value).filter((entry) => ALL_TRANSPORTS.includes(entry));
38
- return normalized.length > 0 ? normalized : [...fallback];
39
- }
40
- function normalizeStringMap(value, fallback = {}) {
41
- if (!isPlainObject(value)) {
42
- return { ...fallback };
43
- }
44
- const normalized = {};
45
- for (const [key, entry] of Object.entries(value)) {
46
- if (typeof entry === "string") {
47
- normalized[key] = entry;
48
- }
49
- }
50
- return normalized;
51
- }
52
- function readBoolean(value, fallback) {
53
- return typeof value === "boolean" ? value : fallback;
54
- }
55
- function readPositiveInteger(value, fallback) {
56
- return Number.isInteger(value) && value > 0
57
- ? value
58
- : fallback;
59
- }
60
- export function parseA2AOutboundPluginConfig(input) {
61
- if (!isPlainObject(input)) {
62
- return cloneConfig(DEFAULTS);
63
- }
64
- const rawDefaults = isPlainObject(input.defaults) ? input.defaults : {};
65
- const rawPolicy = isPlainObject(input.policy) ? input.policy : {};
66
- return {
67
- enabled: readBoolean(input.enabled, DEFAULTS.enabled),
68
- defaults: {
69
- timeoutMs: readPositiveInteger(rawDefaults.timeoutMs, DEFAULTS.defaults.timeoutMs),
70
- cardPath: typeof rawDefaults.cardPath === "string" &&
71
- rawDefaults.cardPath.trim() !== ""
72
- ? rawDefaults.cardPath
73
- : DEFAULTS.defaults.cardPath,
74
- preferredTransports: normalizeTransports(rawDefaults.preferredTransports, DEFAULTS.defaults.preferredTransports),
75
- serviceParameters: normalizeStringMap(rawDefaults.serviceParameters, DEFAULTS.defaults.serviceParameters),
76
- },
77
- policy: {
78
- acceptedOutputModes: normalizeStringArray(rawPolicy.acceptedOutputModes, DEFAULTS.policy.acceptedOutputModes),
79
- normalizeBaseUrl: readBoolean(rawPolicy.normalizeBaseUrl, DEFAULTS.policy.normalizeBaseUrl),
80
- enforceSupportedTransports: readBoolean(rawPolicy.enforceSupportedTransports, DEFAULTS.policy.enforceSupportedTransports),
81
- },
82
- };
83
- }
84
- export const A2AOutboundPluginConfigSchema = {
85
- parse(value) {
86
- return parseA2AOutboundPluginConfig(value);
87
- },
88
- };
89
- //# sourceMappingURL=plugin-config.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"plugin-config.js","sourceRoot":"","sources":["../src/plugin-config.ts"],"names":[],"mappings":"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"}