Skip to content

Commit 03c202f

Browse files
authored
Merge branch 'main' into codex/sessions-diagnose-v2
2 parents 6ab3f83 + 7cf6bd5 commit 03c202f

161 files changed

Lines changed: 32180 additions & 5909 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/settings.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"hooks": {
3+
"SessionStart": [
4+
{
5+
"matcher": "startup",
6+
"hooks": [
7+
{
8+
"type": "command",
9+
"command": "bash -c 'r=\"$(git rev-parse --show-toplevel 2>/dev/null)\"; [ -n \"$r\" ] && cd \"$r\" || exit 0; command -v pnpm >/dev/null 2>&1 && [ -f pnpm-lock.yaml ] || exit 0; CI=true pnpm install --frozen-lockfile --ignore-scripts || echo \"[worktree-setup] pnpm install failed; run pnpm install manually in this worktree\"'",
10+
"timeout": 600
11+
}
12+
]
13+
}
14+
]
15+
}
16+
}

.github/workflows/openclaw-performance.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ on:
5050
kova_ref:
5151
description: openclaw/Kova Git ref to install
5252
required: false
53-
default: f3d037b5b8aacd6adf8ef1dd2ea4c1d778ec7c6c
53+
default: 1bf080f6dbf8800a3187591493f2551824e4ccc7
5454
type: string
5555
dispatch_id:
5656
description: Optional parent workflow dispatch identifier
@@ -154,7 +154,7 @@ jobs:
154154
include_filters: "scenario:agent-cold-warm-message"
155155
expected_release_entries: "agent-cold-warm-message:mock-openai-provider"
156156
env:
157-
KOVA_REF: ${{ inputs.kova_ref || 'f3d037b5b8aacd6adf8ef1dd2ea4c1d778ec7c6c' }}
157+
KOVA_REF: ${{ inputs.kova_ref || '1bf080f6dbf8800a3187591493f2551824e4ccc7' }}
158158
KOVA_HOME: ${{ github.workspace }}/.artifacts/kova/home/${{ matrix.lane }}
159159
PERFORMANCE_HELPER_DIR: ${{ github.workspace }}/.artifacts/performance-workflow
160160
REPORT_DIR: ${{ github.workspace }}/.artifacts/kova/reports/${{ matrix.lane }}

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,10 @@ USER.md
230230
package-lock.json
231231
!.github/release/clawhub-cli/package-lock.json
232232
!src/commands/copilot-sdk-install-manifest/package-lock.json
233-
.claude/
233+
.claude/*
234+
# Track the shared Claude Code project config (worktree auto-install hook); keep
235+
# everything else under .claude/ (worktrees, skills, settings.local.json) ignored.
236+
!.claude/settings.json
234237
.agent/
235238
skills-lock.json
236239

config/max-lines-baseline.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,6 @@ src/agents/openclaw-tools.media-factory-plan.test.ts
503503
src/agents/openclaw-tools.session-status.test.ts
504504
src/agents/openclaw-tools.sessions.test.ts
505505
src/agents/provider-attribution.test.ts
506-
src/agents/provider-attribution.ts
507506
src/agents/provider-local-service.ts
508507
src/agents/provider-request-config.ts
509508
src/agents/provider-transport-fetch.test.ts

docs/cli/claws.md

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
summary: "Add, inspect, and remove experimental Claw agent packages"
2+
summary: "Add, inspect, update, and remove experimental Claw agent packages"
33
read_when:
44
- You want to validate a grouped Claw manifest
55
- You want to preview or add one agent from a Claw
@@ -177,11 +177,14 @@ when owned content drifted. Later Claws stages add other declared resources.
177177
```bash
178178
openclaw claws status
179179
openclaw claws status incident-triage --json
180+
openclaw doctor
180181
```
181182

182183
`status` compares the installed agent and its recorded workspace, package, MCP,
183184
and cron provenance with current state. It reports incomplete installs, missing
184-
resources, and drift without changing local state.
185+
resources, and drift without changing local state. `openclaw doctor` adds
186+
Claw-specific diagnostics for incomplete ownership records, unsafe managed
187+
files, and cron jobs that cannot be corroborated with live Gateway inventory.
185188

186189
Claw provenance distinguishes two relationships:
187190

@@ -194,6 +197,30 @@ This is not a reference count. Ordinary plugin, skill, and agent commands keep
194197
their existing behavior; Claws add provenance and guarded lifecycle operations
195198
on top.
196199

200+
## Preview an update
201+
202+
By default, update uses the source recorded when the Claw was added. Use
203+
`--from` when that source moved or when testing another package directory:
204+
205+
```bash
206+
openclaw claws update incident-triage --dry-run --json
207+
openclaw claws update incident-triage \
208+
--from ./incident-triage-next \
209+
--dry-run --json
210+
```
211+
212+
The plan compares current provenance and live state with the target manifest.
213+
It reports agent, workspace, package, MCP, cron, and ownership changes,
214+
including capability escalations and blockers. Capability escalations have
215+
separate machine-readable records and `!` lines with exact redacted effects in
216+
human output. Resolved package integrity, install identity, and any trust
217+
warning are included. Removing a package declaration releases this Claw's edge
218+
without uninstalling the artifact during update. The eventual
219+
exact `planIntegrity` confirmation binds that disclosed set as well as ordinary
220+
content changes. Hosts may use the same records for a separate dialog or an
221+
aggregate multi-agent review. This stage is read-only: `claws update` requires
222+
`--dry-run` and does not apply the plan.
223+
197224
## Remove an installed Claw
198225

199226
Preview removal before selecting cleanup:
@@ -246,6 +273,7 @@ agents, credentials, sessions, and unowned local state are excluded.
246273
| `claws inspect <source>` | Validate a package directory or JSON manifest. |
247274
| `claws add <source>` | Preview or create one new agent and workspace. |
248275
| `claws status [claw-or-agent]` | Report installed state, ownership, and drift. |
276+
| `claws update <claw-or-agent>` | Preview changes from the recorded or given source. |
249277
| `claws remove <claw-or-agent>` | Preview or remove the agent and eligible resources. |
250278
| `claws export <agent> --out <path>` | Create a portable package from an installed agent. |
251279

docs/docs_map.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1375,6 +1375,7 @@ Do not edit it by hand; run `pnpm docs:map:gen`.
13751375
- H2: Create a grouped manifest
13761376
- H2: Inspect and preview
13771377
- H2: Inspect installed state
1378+
- H2: Preview an update
13781379
- H2: Remove an installed Claw
13791380
- H2: Export an installed agent
13801381
- H2: Command reference
@@ -7568,6 +7569,7 @@ Do not edit it by hand; run `pnpm docs:map:gen`.
75687569
- H3: Why
75697570
- H2: Compatibility policy
75707571
- H3: Channel setup input field compatibility
7572+
- H4: Verifying readers
75717573
- H2: How to migrate
75727574
- H2: Import path reference
75737575
- H2: Removed compatibility surfaces

docs/plugins/building-plugins.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,12 @@ routes that declare `contracts.gatewayMethodDispatch: ["authenticated-request"]`
347347

348348
For the full import map, see [Plugin SDK overview](/plugins/sdk-overview).
349349

350+
OpenClaw SDK compatibility fields carry TypeScript `@deprecated` annotations,
351+
which editors surface as migration warnings. To enforce them at build time,
352+
enable a type-aware rule such as
353+
[`@typescript-eslint/no-deprecated`](https://typescript-eslint.io/rules/no-deprecated/).
354+
Oxlint is not type-aware, so it cannot enforce these annotations.
355+
350356
## Pre-submission checklist
351357

352358
<Check>**package.json** has correct `openclaw` metadata</Check>

docs/plugins/sdk-migration.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,13 @@ policy. Declare `singleAccountKeysToMove`, including an empty array when the
119119
plugin needs no extra promotion keys, so the shared fallback can be retired one
120120
key at a time.
121121

122+
#### Verifying readers
123+
124+
1. Page through `https://clawhub.ai/api/v1/packages?family=code-plugin&limit=100` with each `nextCursor`, and keep packages whose `categories` include `channels`.
125+
2. Add npm candidates from `npm search --json --searchlimit=1000 "openclaw channel plugin"`. Add source-only candidates from GitHub code searches for `openclaw/plugin-sdk/channel-setup`, `openclaw/plugin-sdk/setup`, and `openclaw/plugin-sdk/core`.
126+
3. Resolve each candidate's latest published version. Run `npm pack <package>@<version> --json --pack-destination <temp-dir>`, unpack it, and inspect shipped `dist` JavaScript and declarations for direct or destructured field reads. Download the ClawHub artifact when a package has no npm release.
127+
4. Record package, version, field or promotion key, and matching file. A field or key is deletable only when no published plugin artifact reads it. Keep the reader names in the code comments beside the retained field and key lists synchronized with the sweep.
128+
122129
This is a source/type compatibility record only. It has no runtime adapter or
123130
compatibility-registry entry because runtime setup input objects and setup
124131
behavior are unchanged.

docs/plugins/tool-plugins.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,13 @@ openclaw plugins validate --entry ./dist/index.js
358358
npm test
359359
```
360360

361+
OpenClaw SDK compatibility fields carry TypeScript `@deprecated` annotations,
362+
which editors surface as migration warnings. To enforce them in CI, enable a
363+
type-aware rule such as
364+
[`@typescript-eslint/no-deprecated`](https://typescript-eslint.io/rules/no-deprecated/).
365+
Oxlint is not type-aware, so it cannot enforce these annotations. The generated
366+
`plugins init` scaffold therefore does not add a deprecation lint config.
367+
361368
`plugins validate` checks that:
362369

363370
- `openclaw.plugin.json` exists and passes the normal manifest loader.

src/agents/openclaw-tools.media-factory-plan.test.ts

Lines changed: 138 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ import type { PluginMetadataSnapshot } from "../plugins/plugin-metadata-snapshot
1414
import { resetPluginRuntimeStateForTest } from "../plugins/runtime.js";
1515
import { clearSecretsRuntimeSnapshot } from "../secrets/runtime.js";
1616
import type { AuthProfileStore } from "./auth-profiles/types.js";
17-
import { resolveOptionalMediaToolFactoryPlan } from "./openclaw-tools.media-factory-plan.js";
17+
import {
18+
resolveImageToolFactoryAvailable,
19+
resolveOptionalMediaToolFactoryPlan,
20+
} from "./openclaw-tools.media-factory-plan.js";
1821
import { DEFAULT_PLUGIN_TOOLS_ALLOWLIST_ENTRY } from "./tool-policy.js";
1922
import { loadCapabilityMetadataSnapshot } from "./tools/manifest-capability-availability.js";
2023
import * as pdfModelConfigModule from "./tools/pdf-tool.model-config.js";
@@ -156,6 +159,7 @@ function installSnapshot(
156159
},
157160
} satisfies PluginMetadataSnapshot;
158161
setCurrentPluginMetadataSnapshot(snapshot, { config });
162+
return snapshot;
159163
}
160164

161165
describe("optional media tool factory planning", () => {
@@ -193,6 +197,139 @@ describe("optional media tool factory planning", () => {
193197
vi.unstubAllEnvs();
194198
});
195199

200+
it("uses the prepared media family for image-tool availability", () => {
201+
const config: OpenClawConfig = {};
202+
const snapshot = installSnapshot(config, [
203+
createPlugin({
204+
id: "media-owner",
205+
contracts: { mediaUnderstandingProviders: ["media-owner"] },
206+
setupProviders: [{ id: "media-owner" }],
207+
}),
208+
]);
209+
const base = {
210+
config,
211+
agentDir: "/agent",
212+
authStore: createAuthStore(["media-owner"]),
213+
};
214+
215+
expect(
216+
resolveImageToolFactoryAvailable({
217+
...base,
218+
preparedModelRuntime: {
219+
metadataSnapshot: snapshot,
220+
mediaCapabilityProviders: { mediaUnderstandingProviders: [] },
221+
} as never,
222+
}),
223+
).toBe(false);
224+
expect(
225+
resolveImageToolFactoryAvailable({
226+
...base,
227+
preparedModelRuntime: {
228+
metadataSnapshot: snapshot,
229+
mediaCapabilityProviders: {
230+
mediaUnderstandingProviders: [{ id: "media-owner", capabilities: ["image"] }],
231+
},
232+
} as never,
233+
}),
234+
).toBe(true);
235+
});
236+
237+
it("requires image capability and auth on the same prepared provider", () => {
238+
const config: OpenClawConfig = {};
239+
const snapshot = installSnapshot(config, [
240+
createPlugin({
241+
id: "media-owner",
242+
contracts: {
243+
mediaUnderstandingProviders: ["audio-auth", "image-no-auth"],
244+
},
245+
setupProviders: [{ id: "audio-auth" }, { id: "image-no-auth" }],
246+
}),
247+
]);
248+
249+
expect(
250+
resolveImageToolFactoryAvailable({
251+
config,
252+
agentDir: "/agent",
253+
authStore: createAuthStore(["audio-auth"]),
254+
preparedModelRuntime: {
255+
metadataSnapshot: snapshot,
256+
mediaCapabilityProviders: {
257+
mediaUnderstandingProviders: [
258+
{ id: "audio-auth", capabilities: ["audio"] },
259+
{ id: "image-no-auth", capabilities: ["image"] },
260+
],
261+
},
262+
} as never,
263+
}),
264+
).toBe(false);
265+
});
266+
267+
it("keeps config vision routes while gating OpenAI subscription auth on prepared Codex", () => {
268+
vi.stubEnv("OPENAI_API_KEY", "");
269+
const config = {
270+
models: {
271+
providers: {
272+
custom: {
273+
baseUrl: "https://vision.example/v1",
274+
models: [{ id: "vision", input: ["text", "image"] }],
275+
},
276+
openai: {
277+
baseUrl: "https://api.openai.com/v1",
278+
models: [{ id: "gpt-image", input: ["text", "image"] }],
279+
},
280+
},
281+
},
282+
} as unknown as OpenClawConfig;
283+
const snapshot = installSnapshot(config, []);
284+
const preparedModelRuntime = {
285+
metadataSnapshot: snapshot,
286+
mediaCapabilityProviders: { mediaUnderstandingProviders: [] },
287+
} as never;
288+
const oauthStore = createAuthStore();
289+
oauthStore.profiles["openai:default"] = {
290+
provider: "openai",
291+
type: "oauth",
292+
access: "test",
293+
refresh: "test",
294+
expires: Date.now() + 60_000,
295+
};
296+
297+
expect(
298+
resolveImageToolFactoryAvailable({
299+
config,
300+
agentDir: "/agent",
301+
authStore: createAuthStore(["custom"]),
302+
preparedModelRuntime,
303+
}),
304+
).toBe(true);
305+
expect(
306+
resolveImageToolFactoryAvailable({
307+
config,
308+
agentDir: "/agent",
309+
authStore: oauthStore,
310+
preparedModelRuntime,
311+
}),
312+
).toBe(false);
313+
for (const [capabilities, expected] of [
314+
[["audio"], false],
315+
[["image"], true],
316+
] as const) {
317+
expect(
318+
resolveImageToolFactoryAvailable({
319+
config,
320+
agentDir: "/agent",
321+
authStore: oauthStore,
322+
preparedModelRuntime: {
323+
metadataSnapshot: snapshot,
324+
mediaCapabilityProviders: {
325+
mediaUnderstandingProviders: [{ id: "codex", capabilities }],
326+
},
327+
} as never,
328+
}),
329+
).toBe(expected);
330+
}
331+
});
332+
196333
it("skips unavailable generation and PDF factories from snapshot and run auth facts", () => {
197334
const config: OpenClawConfig = {};
198335
installSnapshot(config, [

0 commit comments

Comments
 (0)