@agentchatme/openclaw 0.6.1 → 0.6.3

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 CHANGED
@@ -5,6 +5,149 @@ All notable changes to `@agentchatme/openclaw` are documented here.
5
5
  The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/);
6
6
  this package adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## 0.6.3 — 2026-04-27
9
+
10
+ ### Fix: `openclaw plugins install` failed with `EUNSUPPORTEDPROTOCOL` on ClawHub source-linked builds
11
+
12
+ 0.6.2 still failed end-user installs with the same truncated `npm install
13
+ failed:` symptom 0.6.2 was supposed to fix. Root cause was different this
14
+ time and only visible after we recovered the swallowed npm log from the
15
+ target machine:
16
+
17
+ ```
18
+ error code EUNSUPPORTEDPROTOCOL
19
+ error Unsupported URL Type "workspace:": workspace:^
20
+ ```
21
+
22
+ The committed source `package.json` declared
23
+ `dependencies."@agentchatme/agentchat": "workspace:^"`. pnpm rewrites this
24
+ to a real semver during `pnpm pack` / `pnpm publish`, so the **npm tarball**
25
+ (`registry.npmjs.org/@agentchatme/openclaw/0.6.2`) is fully clean — the
26
+ spec resolves to `^1.3.0` there. But ClawHub builds community plugins via
27
+ **source-linked verification**: it zips the GitHub source tree at the
28
+ release tag and ships that. `pnpm pack` is never invoked on that path, so
29
+ the `workspace:^` spec reaches end-user machines verbatim, where OpenClaw
30
+ runs `npm install` (not pnpm) and npm rejects the spec at `Arborist`'s
31
+ ideal-tree build step.
32
+
33
+ OpenClaw's `--silent` flag (hardcoded in
34
+ [`src/infra/install-package-dir.ts`](https://github.com/openclaw/openclaw/blob/main/src/infra/install-package-dir.ts))
35
+ suppressed both stdout and stderr, so the user saw only `npm install
36
+ failed:` with nothing after — exactly the same surface as 0.6.1's
37
+ `peerDependencies` bug, but a fundamentally different root cause.
38
+
39
+ The fix is a **production-grade lockdown** — single source of truth, no
40
+ process gymnastics, regression-proof:
41
+
42
+ **Changed:**
43
+
44
+ - `package.json` — `dependencies."@agentchatme/agentchat"` pinned to
45
+ `^1.3.0` (real semver). The committed source is now installable by raw
46
+ npm. Bun, Yarn, npm clone, ClawHub source-linked builds — all succeed.
47
+ - `pnpm-workspace.yaml` (monorepo root) — added
48
+ `linkWorkspacePackages: true` and `preferWorkspacePackages: true`.
49
+ pnpm continues to symlink the in-tree SDK during development even
50
+ though the spec is now a normal semver range; the dev-loop is
51
+ unchanged. Settings live here rather than `.npmrc` because `.npmrc`
52
+ is `.gitignore`d project-wide to prevent npm auth-token leakage.
53
+ - `scripts/strip-publish-fields.mjs` — guard now rejects `workspace:` and
54
+ `catalog:` specs in `dependencies` in addition to `file:` and `link:`.
55
+ Prior comment explicitly allowed `workspace:` on the assumption that
56
+ pnpm pack would rewrite it; that assumption holds for the npm tarball
57
+ but not for ClawHub source-linked builds, so the guard is widened.
58
+
59
+ **New:**
60
+
61
+ - `scripts/verify-source-installs.mjs` — regression test wired into
62
+ `prepublishOnly`. Copies the source `package.json` into a fresh temp
63
+ dir and runs `npm install --dry-run --omit=dev --ignore-scripts ...`
64
+ (the same flags ClawHub-side OpenClaw uses, minus `--silent`). A
65
+ future commit that re-introduces a `workspace:`, `file:`, `link:`, or
66
+ `catalog:` spec in `dependencies` cannot reach npm or ClawHub — the
67
+ prepublish hook fails first with the actual npm error message.
68
+
69
+ ### Upstream improvement (filed in parallel, non-blocking)
70
+
71
+ OpenClaw `src/infra/install-package-dir.ts` hardcodes `--silent` on the
72
+ spawned `npm install`, which suppresses every user-actionable error.
73
+ Combined with the failure handler that formats `"npm install failed: " +
74
+ (stderr || stdout).trim()`, an empty buffer renders as the bare prefix.
75
+ A PR proposing replacement with `--loglevel=error` (or removal of the
76
+ flag entirely) is filed against `openclaw/openclaw` so the next community
77
+ plugin author hits a real error instead of an empty one.
78
+
79
+ ## 0.6.2 — 2026-04-25
80
+
81
+ ### Unblock `openclaw plugins install` on stock end-user machines — strip publish-time fields
82
+
83
+ User reported `openclaw plugins install @agentchatme/openclaw` failing on a
84
+ clean Hetzner Ubuntu box with the truncated message:
85
+
86
+ > npm install failed:
87
+
88
+ with no further detail. Investigation against OpenClaw's own source
89
+ ([`src/infra/install-package-dir.ts`](https://github.com/openclaw/openclaw/blob/main/src/infra/install-package-dir.ts))
90
+ found that the installer runs `npm install --omit=dev --silent
91
+ --ignore-scripts` inside the extracted plugin directory. The `--omit=dev`
92
+ flag excludes `devDependencies`, but `peerDependencies` are NOT stripped —
93
+ npm tries to resolve them as part of the install. Our published manifest
94
+ declared `peerDependencies: { "openclaw": ">=2026.4.0" }`; on an end-user
95
+ machine without a local OpenClaw checkout, npm's peer-dep resolution
96
+ either ERESOLVE-conflicts, 404s on a private spec, or pulls a heavy peer
97
+ tree that fails for unrelated reasons. The `--silent` flag suppresses
98
+ npm's stderr, which is why the user only saw `npm install failed:` with
99
+ no tail.
100
+
101
+ This release adopts the **publish-time strip pattern** that OpenClaw's
102
+ first-party reference plugin `@openclaw/matrix` uses (verified against
103
+ the published manifest at
104
+ `https://registry.npmjs.org/@openclaw/matrix/2026.3.13` — `devDependencies`,
105
+ `peerDependencies`, and `peerDependenciesMeta` are all `null` in the
106
+ tarball, while the in-repo source keeps them for development).
107
+
108
+ **New:**
109
+
110
+ - `scripts/strip-publish-fields.mjs` — runs as `prepack` (snapshot +
111
+ strip) and `postpack` (restore). Removes `devDependencies`,
112
+ `peerDependencies`, `peerDependenciesMeta` from the *published*
113
+ `package.json`; the working-tree copy is unchanged after pack
114
+ completes. Also guards against any runtime `dependencies` using
115
+ `workspace:` / `file:` / `link:` specs that npm cannot resolve from
116
+ the registry — pnpm should already rewrite those at publish time, but
117
+ the guard catches drift before it hits users.
118
+ - `package.json` — `prepack` and `postpack` script hooks wired.
119
+ `prepublishOnly` (build + type-check + test) is preserved.
120
+
121
+ **Removed (no-op for community plugins):**
122
+
123
+ - `package.json` `openclaw.bundle.stageRuntimeDependencies` — this flag
124
+ is consumed only by OpenClaw's release-time
125
+ `scripts/stage-bundled-plugin-runtime-deps.mjs` for plugins shipped
126
+ in-tree by OpenClaw maintainers. Per
127
+ [`docs.openclaw.ai/plugins/bundles`](https://docs.openclaw.ai/plugins/bundles)
128
+ it has no effect on community plugins installed via `openclaw plugins
129
+ install`. Removed to avoid implying a contract that does not exist.
130
+
131
+ ### `hasAgentChatConfiguredState` now requires `agentHandle`
132
+
133
+ `src/configured-state.ts` previously checked only `apiKey.length >= 20`.
134
+ A config with a valid key but no handle would pass the gate, the runtime
135
+ would start, and the agent would have no identity — the `agent-prompt`
136
+ hook silently injects no hints, the inbound bridge cannot self-filter
137
+ echoes (`sender === config.agentHandle` always false). Refusing to count
138
+ the channel as "configured" until the handle is present surfaces the gap
139
+ at the gateway boundary instead of letting it manifest as "the agent
140
+ just doesn't know it's on the network." Added
141
+ `tests/configured-state.test.ts` covering the new bar (apiKey-only is
142
+ rejected, empty / whitespace handle rejected, non-string fields rejected).
143
+
144
+ ### Behavior unchanged otherwise
145
+
146
+ The runtime, binding adapters, agent tools, agent prompt, bundled skill,
147
+ state machine, outbound queue, circuit breaker, and ws-client are
148
+ byte-identical to 0.6.1. This is a publish-pipeline + configured-state
149
+ correctness release.
150
+
8
151
  ## 0.6.1 — 2026-04-25
9
152
 
10
153
  ### Strip trigger keywords from defensive comments — install scanner now passes
@@ -4,7 +4,10 @@
4
4
  function hasAgentChatConfiguredState(config) {
5
5
  if (!config || typeof config !== "object") return false;
6
6
  const key = config.apiKey;
7
- return typeof key === "string" && key.length >= 20;
7
+ if (typeof key !== "string" || key.length < 20) return false;
8
+ const handle = config.agentHandle;
9
+ if (typeof handle !== "string" || handle.trim().length === 0) return false;
10
+ return true;
8
11
  }
9
12
 
10
13
  exports.hasAgentChatConfiguredState = hasAgentChatConfiguredState;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/configured-state.ts"],"names":[],"mappings":";;;AAaO,SAAS,4BAA4B,MAAA,EAA8C;AACxF,EAAA,IAAI,CAAC,MAAA,IAAU,OAAO,MAAA,KAAW,UAAU,OAAO,KAAA;AAClD,EAAA,MAAM,MAAM,MAAA,CAAO,MAAA;AACnB,EAAA,OAAO,OAAO,GAAA,KAAQ,QAAA,IAAY,GAAA,CAAI,MAAA,IAAU,EAAA;AAClD","file":"configured-state.cjs","sourcesContent":["/**\n * Configured-state predicate for the AgentChat channel.\n *\n * OpenClaw calls this to decide whether the channel has \"enough\" config to\n * be considered active (counts toward enabled channels, shown in UI, etc.).\n *\n * Minimum bar: an `apiKey` of plausible length is present.\n */\n\nexport interface MaybeConfigured {\n readonly apiKey?: unknown\n}\n\nexport function hasAgentChatConfiguredState(config: MaybeConfigured | undefined): boolean {\n if (!config || typeof config !== 'object') return false\n const key = config.apiKey\n return typeof key === 'string' && key.length >= 20\n}\n"]}
1
+ {"version":3,"sources":["../src/configured-state.ts"],"names":[],"mappings":";;;AAmBO,SAAS,4BAA4B,MAAA,EAA8C;AACxF,EAAA,IAAI,CAAC,MAAA,IAAU,OAAO,MAAA,KAAW,UAAU,OAAO,KAAA;AAClD,EAAA,MAAM,MAAM,MAAA,CAAO,MAAA;AACnB,EAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,IAAY,GAAA,CAAI,MAAA,GAAS,IAAI,OAAO,KAAA;AACvD,EAAA,MAAM,SAAS,MAAA,CAAO,WAAA;AACtB,EAAA,IAAI,OAAO,WAAW,QAAA,IAAY,MAAA,CAAO,MAAK,CAAE,MAAA,KAAW,GAAG,OAAO,KAAA;AACrE,EAAA,OAAO,IAAA;AACT","file":"configured-state.cjs","sourcesContent":["/**\n * Configured-state predicate for the AgentChat channel.\n *\n * OpenClaw calls this to decide whether the channel has \"enough\" config to\n * be considered active (counts toward enabled channels, shown in UI, etc.).\n *\n * Bar: an `apiKey` of plausible length AND a non-empty `agentHandle`.\n * Without the handle the runtime will start but the agent has no identity\n * to inject into prompts or to use as a self-filter on inbound — both\n * downstream surfaces silently degrade. Refusing to count the channel as\n * \"configured\" until the handle is present surfaces the gap at the\n * gateway boundary instead.\n */\n\nexport interface MaybeConfigured {\n readonly apiKey?: unknown\n readonly agentHandle?: unknown\n}\n\nexport function hasAgentChatConfiguredState(config: MaybeConfigured | undefined): boolean {\n if (!config || typeof config !== 'object') return false\n const key = config.apiKey\n if (typeof key !== 'string' || key.length < 20) return false\n const handle = config.agentHandle\n if (typeof handle !== 'string' || handle.trim().length === 0) return false\n return true\n}\n"]}
@@ -4,10 +4,16 @@
4
4
  * OpenClaw calls this to decide whether the channel has "enough" config to
5
5
  * be considered active (counts toward enabled channels, shown in UI, etc.).
6
6
  *
7
- * Minimum bar: an `apiKey` of plausible length is present.
7
+ * Bar: an `apiKey` of plausible length AND a non-empty `agentHandle`.
8
+ * Without the handle the runtime will start but the agent has no identity
9
+ * to inject into prompts or to use as a self-filter on inbound — both
10
+ * downstream surfaces silently degrade. Refusing to count the channel as
11
+ * "configured" until the handle is present surfaces the gap at the
12
+ * gateway boundary instead.
8
13
  */
9
14
  interface MaybeConfigured {
10
15
  readonly apiKey?: unknown;
16
+ readonly agentHandle?: unknown;
11
17
  }
12
18
  declare function hasAgentChatConfiguredState(config: MaybeConfigured | undefined): boolean;
13
19
 
@@ -4,10 +4,16 @@
4
4
  * OpenClaw calls this to decide whether the channel has "enough" config to
5
5
  * be considered active (counts toward enabled channels, shown in UI, etc.).
6
6
  *
7
- * Minimum bar: an `apiKey` of plausible length is present.
7
+ * Bar: an `apiKey` of plausible length AND a non-empty `agentHandle`.
8
+ * Without the handle the runtime will start but the agent has no identity
9
+ * to inject into prompts or to use as a self-filter on inbound — both
10
+ * downstream surfaces silently degrade. Refusing to count the channel as
11
+ * "configured" until the handle is present surfaces the gap at the
12
+ * gateway boundary instead.
8
13
  */
9
14
  interface MaybeConfigured {
10
15
  readonly apiKey?: unknown;
16
+ readonly agentHandle?: unknown;
11
17
  }
12
18
  declare function hasAgentChatConfiguredState(config: MaybeConfigured | undefined): boolean;
13
19
 
@@ -2,7 +2,10 @@
2
2
  function hasAgentChatConfiguredState(config) {
3
3
  if (!config || typeof config !== "object") return false;
4
4
  const key = config.apiKey;
5
- return typeof key === "string" && key.length >= 20;
5
+ if (typeof key !== "string" || key.length < 20) return false;
6
+ const handle = config.agentHandle;
7
+ if (typeof handle !== "string" || handle.trim().length === 0) return false;
8
+ return true;
6
9
  }
7
10
 
8
11
  export { hasAgentChatConfiguredState };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/configured-state.ts"],"names":[],"mappings":";AAaO,SAAS,4BAA4B,MAAA,EAA8C;AACxF,EAAA,IAAI,CAAC,MAAA,IAAU,OAAO,MAAA,KAAW,UAAU,OAAO,KAAA;AAClD,EAAA,MAAM,MAAM,MAAA,CAAO,MAAA;AACnB,EAAA,OAAO,OAAO,GAAA,KAAQ,QAAA,IAAY,GAAA,CAAI,MAAA,IAAU,EAAA;AAClD","file":"configured-state.js","sourcesContent":["/**\n * Configured-state predicate for the AgentChat channel.\n *\n * OpenClaw calls this to decide whether the channel has \"enough\" config to\n * be considered active (counts toward enabled channels, shown in UI, etc.).\n *\n * Minimum bar: an `apiKey` of plausible length is present.\n */\n\nexport interface MaybeConfigured {\n readonly apiKey?: unknown\n}\n\nexport function hasAgentChatConfiguredState(config: MaybeConfigured | undefined): boolean {\n if (!config || typeof config !== 'object') return false\n const key = config.apiKey\n return typeof key === 'string' && key.length >= 20\n}\n"]}
1
+ {"version":3,"sources":["../src/configured-state.ts"],"names":[],"mappings":";AAmBO,SAAS,4BAA4B,MAAA,EAA8C;AACxF,EAAA,IAAI,CAAC,MAAA,IAAU,OAAO,MAAA,KAAW,UAAU,OAAO,KAAA;AAClD,EAAA,MAAM,MAAM,MAAA,CAAO,MAAA;AACnB,EAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,IAAY,GAAA,CAAI,MAAA,GAAS,IAAI,OAAO,KAAA;AACvD,EAAA,MAAM,SAAS,MAAA,CAAO,WAAA;AACtB,EAAA,IAAI,OAAO,WAAW,QAAA,IAAY,MAAA,CAAO,MAAK,CAAE,MAAA,KAAW,GAAG,OAAO,KAAA;AACrE,EAAA,OAAO,IAAA;AACT","file":"configured-state.js","sourcesContent":["/**\n * Configured-state predicate for the AgentChat channel.\n *\n * OpenClaw calls this to decide whether the channel has \"enough\" config to\n * be considered active (counts toward enabled channels, shown in UI, etc.).\n *\n * Bar: an `apiKey` of plausible length AND a non-empty `agentHandle`.\n * Without the handle the runtime will start but the agent has no identity\n * to inject into prompts or to use as a self-filter on inbound — both\n * downstream surfaces silently degrade. Refusing to count the channel as\n * \"configured\" until the handle is present surfaces the gap at the\n * gateway boundary instead.\n */\n\nexport interface MaybeConfigured {\n readonly apiKey?: unknown\n readonly agentHandle?: unknown\n}\n\nexport function hasAgentChatConfiguredState(config: MaybeConfigured | undefined): boolean {\n if (!config || typeof config !== 'object') return false\n const key = config.apiKey\n if (typeof key !== 'string' || key.length < 20) return false\n const handle = config.agentHandle\n if (typeof handle !== 'string' || handle.trim().length === 0) return false\n return true\n}\n"]}
package/dist/index.cjs CHANGED
@@ -1804,7 +1804,7 @@ var CircuitBreaker = class {
1804
1804
  };
1805
1805
 
1806
1806
  // src/version.ts
1807
- var PACKAGE_VERSION = "0.6.1";
1807
+ var PACKAGE_VERSION = "0.6.3";
1808
1808
 
1809
1809
  // src/outbound.ts
1810
1810
  var DEFAULT_RETRY_POLICY = {
@@ -4418,7 +4418,10 @@ var agentchatSetupEntry = channelCore.defineSetupPluginEntry(agentchatPlugin);
4418
4418
  function hasAgentChatConfiguredState(config) {
4419
4419
  if (!config || typeof config !== "object") return false;
4420
4420
  const key = config.apiKey;
4421
- return typeof key === "string" && key.length >= 20;
4421
+ if (typeof key !== "string" || key.length < 20) return false;
4422
+ const handle = config.agentHandle;
4423
+ if (typeof handle !== "string" || handle.trim().length === 0) return false;
4424
+ return true;
4422
4425
  }
4423
4426
 
4424
4427
  exports.AGENTCHAT_CHANNEL_ID = AGENTCHAT_CHANNEL_ID;