Skip to content

Commit 60388f0

Browse files
committed
Merge remote-tracking branch 'upstream/main' into alix/foundry-az-stream-errors
# Conflicts: # docs/.generated/plugin-sdk-api-baseline.sha256
2 parents de04d02 + cf0b80b commit 60388f0

164 files changed

Lines changed: 10737 additions & 7829 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.

.github/workflows/ci.yml

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1559,6 +1559,7 @@ jobs:
15591559
env:
15601560
HISTORICAL_TARGET: ${{ needs.preflight.outputs.compatibility_target }}
15611561
FORMAT_CHECK: ${{ needs.preflight.outputs.run_format_check }}
1562+
LOC_BASE_SHA: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || (github.event_name == 'push' && github.event.before || '') }}
15621563
OPENCLAW_LOCAL_CHECK: "0"
15631564
TASK: ${{ matrix.task }}
15641565
PR_BASE_SHA: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || '' }}
@@ -1568,12 +1569,17 @@ jobs:
15681569
case "$TASK" in
15691570
guards)
15701571
pnpm check:no-conflict-markers
1572+
if [ -n "$LOC_BASE_SHA" ]; then
1573+
git fetch --no-tags --depth=1 origin "+${LOC_BASE_SHA}:refs/remotes/origin/loc-base"
1574+
pnpm check:loc --base-ref refs/remotes/origin/loc-base
1575+
else
1576+
pnpm check:loc
1577+
fi
15711578
pnpm tool-display:check
15721579
pnpm check:host-env-policy:swift
15731580
pnpm dup:check:coverage
15741581
if [ -n "$PR_BASE_SHA" ]; then
1575-
git fetch --no-tags --depth=1 origin "+${PR_BASE_SHA}:refs/remotes/origin/pr-base"
1576-
node scripts/report-test-temp-creations.mjs --base refs/remotes/origin/pr-base --head HEAD --no-merge-base
1582+
node scripts/report-test-temp-creations.mjs --base refs/remotes/origin/loc-base --head HEAD --no-merge-base
15771583
fi
15781584
pnpm deps:patches:check
15791585
pnpm lint:webhook:no-low-level-body-read
@@ -1607,6 +1613,12 @@ jobs:
16071613
has_package_script "deadcode:unused-files"; then
16081614
pnpm deadcode:dependencies
16091615
pnpm deadcode:unused-files
1616+
if has_package_script "deadcode:exports"; then
1617+
pnpm deadcode:exports
1618+
elif [[ "$HISTORICAL_TARGET" != "true" ]]; then
1619+
echo "Current CI targets must provide the deadcode:exports package script." >&2
1620+
exit 1
1621+
fi
16101622
elif [[ "$HISTORICAL_TARGET" == "true" ]] && has_package_script "deadcode:ci"; then
16111623
pnpm deadcode:ci
16121624
else

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ Docs: https://docs.openclaw.ai
3434

3535
- **Native app connection and relay reliability:** keep Android disconnects stopped across Activity recreation, fail remote camera commands without opening permission prompts, refresh mobile node registration after capability changes, surface iOS onboarding connection failures, cancel stale Talk owners on session switches, reject invalid Watch acknowledgments, preserve Watch events received during startup, and prevent older agent overview requests from replacing newer gateway state.
3636
- **Gateway source watch:** hand the configured port off from the installed service before starting the tmux watcher, preserve failed panes for attach/capture, and keep explicit alternate-port watches side by side with the managed Gateway.
37+
- **Claude CLI max-turn diagnostics:** preserve terminal max-turn results with OpenClaw and Claude session context, warn when tool actions may already have run, and stop unsafe auth-profile or model replay for potentially side-effecting turns. (#94130) Thanks @zhangguiping-xydt.
3738
- **Provider network retries:** align provider read/poll/download and agent-wait recovery for transient connection errors, retry bounded provider `ENOTFOUND` failures while leaving gateway `ENOTFOUND` and non-idempotent create operations fail-fast. (#101496) Thanks @xialonglee.
3839
- **Session retry classification:** stop permanent provider errors whose identifiers or payload details merely contain 429/5xx digit sequences from re-sending full context, and share bounded rate-limit-window parsing across retry paths. (#105258) Thanks @destire-mio.
3940
- **LINE directive templates:** suppress confirms and buttons with blank required fields or unlabeled actions while preserving valid titleless buttons and surrounding reply text. (#105520) Thanks @edenfunf.

config/knip.config.ts

Lines changed: 53 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -79,62 +79,69 @@ const rootBundledPluginRuntimeDependencies = [
7979
"tokenjuice",
8080
] as const;
8181

82+
// These files are test infrastructure, so their exports are intentionally
83+
// available to tests without becoming part of the production dead-code scan.
84+
const ignoredTestSupportFiles = [
85+
"**/__tests__/**",
86+
"src/test-utils/**",
87+
"**/test-helpers/**",
88+
"**/test-fixtures/**",
89+
"**/test-support/**",
90+
"**/test-*.ts",
91+
"**/vitest*.{ts,mjs}",
92+
"**/*test-helpers.ts",
93+
"**/*test-fixtures.ts",
94+
"**/*test-harness.ts",
95+
"**/*test-utils.ts",
96+
"**/*test-support.ts",
97+
"**/*test-shared.ts",
98+
"**/*mocks.ts",
99+
"**/*.e2e-mocks.ts",
100+
"**/*.e2e-*.ts",
101+
"**/*.fixture-test-support.ts",
102+
"**/*.harness.ts",
103+
"**/*.job-fixtures.ts",
104+
"**/*.mock-harness.ts",
105+
"**/*.menu-test-support.ts",
106+
"**/*.suite-helpers.ts",
107+
"**/*.test-setup.ts",
108+
"**/job-fixtures.ts",
109+
"**/*test-mocks.ts",
110+
"**/*test-runtime*.ts",
111+
"**/*.mock-setup.ts",
112+
"**/*.cases.ts",
113+
"**/*.e2e-harness.ts",
114+
"**/*.fixture.ts",
115+
"**/*.fixtures.ts",
116+
"**/*.mocks.ts",
117+
"**/*.mocks.shared.ts",
118+
"**/*.route-test-support.ts",
119+
"**/*.shared-test.ts",
120+
"**/*.suite.ts",
121+
"**/*.test-runtime.ts",
122+
"**/*.testkit.ts",
123+
"**/*.test-fixtures.ts",
124+
"**/*.test-harness.ts",
125+
"**/*.test-helper.ts",
126+
"**/*.test-helpers.ts",
127+
"**/*.test-mocks.ts",
128+
"**/*.test-utils.ts",
129+
"test/helpers/live-image-probe.ts",
130+
] as const;
131+
82132
const config = {
83133
ignoreFiles: [
84134
"scripts/**",
85135
"packages/*/dist/**",
86-
"**/__tests__/**",
87-
"src/test-utils/**",
88-
"**/test-helpers/**",
89-
"**/test-fixtures/**",
90-
"**/test-support/**",
91136
"**/live-*.ts",
92-
"**/test-*.ts",
93-
"**/vitest*.{ts,mjs}",
94-
"**/*test-helpers.ts",
95-
"**/*test-fixtures.ts",
96-
"**/*test-harness.ts",
97-
"**/*test-utils.ts",
98-
"**/*test-support.ts",
99-
"**/*test-shared.ts",
100-
"**/*mocks.ts",
101-
"**/*.e2e-mocks.ts",
102-
"**/*.e2e-*.ts",
103-
"**/*.fixture-test-support.ts",
104-
"**/*.harness.ts",
105-
"**/*.job-fixtures.ts",
106-
"**/*.mock-harness.ts",
107-
"**/*.menu-test-support.ts",
108-
"**/*.suite-helpers.ts",
109-
"**/*.test-setup.ts",
110-
"**/job-fixtures.ts",
111-
"**/*test-mocks.ts",
112-
"**/*test-runtime*.ts",
113-
"**/*.mock-setup.ts",
114-
"**/*.cases.ts",
115-
"**/*.e2e-harness.ts",
116-
"**/*.fixture.ts",
117-
"**/*.fixtures.ts",
118-
"**/*.mocks.ts",
119-
"**/*.mocks.shared.ts",
120-
"**/*.route-test-support.ts",
121-
"**/*.shared-test.ts",
122-
"**/*.suite.ts",
123-
"**/*.test-runtime.ts",
124-
"**/*.testkit.ts",
125-
"**/*.test-fixtures.ts",
126-
"**/*.test-harness.ts",
127-
"**/*.test-helper.ts",
128-
"**/*.test-helpers.ts",
129-
"**/*.test-mocks.ts",
130-
"**/*.test-utils.ts",
131-
"test/helpers/live-image-probe.ts",
132137
"src/secrets/credential-matrix.ts",
133138
"src/shared/text/assistant-visible-text.ts",
134139
bundledPluginFile("telegram", "src/bot/reply-threading.ts"),
135140
bundledPluginFile("telegram", "src/draft-chunking.ts"),
136141
],
137-
ignore: ["packages/*/dist/**"],
142+
// Knip's `ignoreFiles` only suppresses unused-file findings. Test helpers
143+
// belong in `ignore` so they do not inflate unused-export/type findings.
144+
ignore: ["packages/*/dist/**", ...ignoredTestSupportFiles],
138145
workspaces: {
139146
".": {
140147
entry: rootEntries,
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
c332a56a5d4370ec28eaa9f99e130dc088d22b22ea42e8f0cfba2d0c2a8dbbc0 plugin-sdk-api-baseline.json
2-
48039bb0d3e8a51acaa9f84e7d891e9b629e11a8373cbdfe0a3f3d4607fc29af plugin-sdk-api-baseline.jsonl
1+
148a1637fec1068b6387b3fee1d30d3a41c1cb5e05b0b1f0fd7c467660876065 plugin-sdk-api-baseline.json
2+
49119fad171fd335eb80d0fd15585e8109382d9d7f766ca0cd45d1b61dd95139 plugin-sdk-api-baseline.jsonl

docs/ci.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ job budget.
115115

116116
Android CI runs both `testPlayDebugUnitTest` and `testThirdPartyDebugUnitTest` and then builds the Play debug APK. The third-party flavor has no separate source set or manifest; its unit-test lane still compiles the flavor with the SMS/call-log BuildConfig flags, while avoiding a duplicate debug APK packaging job on every Android-relevant push.
117117

118-
The `check-dependencies` shard runs a production Knip dependency-only pass and the unused-file allowlist check. The unused-file guard fails when a PR adds a new unreviewed unused file or leaves a stale allowlist entry, while preserving intentional dynamic plugin, generated, build, live-test, and package bridge surfaces that Knip cannot resolve statically. The unused-exports baseline remains available as an advisory maintenance scan through `pnpm deadcode:exports`; after deleting dead code, regenerate it with `pnpm deadcode:exports:update`.
118+
The `check-dependencies` shard runs production Knip dependency, unused-file, and unused-export checks. The unused-file guard fails when a PR adds a new unreviewed unused file or leaves a stale allowlist entry, while preserving intentional dynamic plugin, generated, build, live-test, and package bridge surfaces that Knip cannot resolve statically. The unused-export guard excludes test-support files, then fails on new findings or stale required baseline entries; after deleting dead exports, regenerate the shrink-only baseline with `pnpm deadcode:exports:update`. Historical targets run the export guard when they provide it and retain their older dead-code fallback otherwise.
119119

120120
## ClawSweeper activity forwarding
121121

extensions/discord/src/monitor/model-picker.state.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@ import type { ComponentData } from "../internal/discord.js";
1212
export const DISCORD_MODEL_PICKER_CUSTOM_ID_KEY = "mdlpk";
1313
export const DISCORD_CUSTOM_ID_MAX_CHARS = 100;
1414

15-
export const DISCORD_COMPONENT_MAX_ROWS = 5;
16-
export const DISCORD_COMPONENT_MAX_BUTTONS_PER_ROW = 5;
17-
export const DISCORD_COMPONENT_MAX_SELECT_OPTIONS = 25;
15+
const DISCORD_COMPONENT_MAX_SELECT_OPTIONS = 25;
1816

1917
export const DISCORD_MODEL_PICKER_PROVIDER_PAGE_SIZE = DISCORD_COMPONENT_MAX_SELECT_OPTIONS;
2018
export const DISCORD_MODEL_PICKER_PROVIDER_SINGLE_PAGE_MAX = DISCORD_COMPONENT_MAX_SELECT_OPTIONS;
@@ -43,8 +41,8 @@ const PICKER_ACTIONS = [
4341
const PICKER_VIEWS = ["providers", "models", "recents"] as const;
4442

4543
export type DiscordModelPickerCommandContext = (typeof COMMAND_CONTEXTS)[number];
46-
export type DiscordModelPickerAction = (typeof PICKER_ACTIONS)[number];
47-
export type DiscordModelPickerView = (typeof PICKER_VIEWS)[number];
44+
type DiscordModelPickerAction = (typeof PICKER_ACTIONS)[number];
45+
type DiscordModelPickerView = (typeof PICKER_VIEWS)[number];
4846
export type DiscordModelPickerLayout = "v2" | "classic";
4947

5048
export type DiscordModelPickerState = {
@@ -550,7 +548,7 @@ export function findModelBucketId(
550548
return containing && containing.id !== "all" ? containing.id : undefined;
551549
}
552550

553-
export function buildDiscordModelPickerProviderItems(
551+
function buildDiscordModelPickerProviderItems(
554552
data: ModelsProviderData,
555553
): DiscordModelPickerProviderItem[] {
556554
// Sort lexicographically so the alpha-bucket boundaries are deterministic

extensions/discord/src/monitor/model-picker.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@ import {
1919
loadDiscordModelPickerData,
2020
parseDiscordModelPickerCustomId,
2121
parseDiscordModelPickerData,
22+
} from "./model-picker.state.js";
23+
import { createModelsProviderData } from "./model-picker.test-utils.js";
24+
import {
2225
renderDiscordModelPickerModelsView,
2326
renderDiscordModelPickerProvidersView,
2427
renderDiscordModelPickerRecentsView,
2528
toDiscordModelPickerMessagePayload,
26-
} from "./model-picker.js";
27-
import { createModelsProviderData } from "./model-picker.test-utils.js";
29+
} from "./model-picker.view.js";
2830

2931
const buildModelsProviderDataMock = vi.hoisted(() => vi.fn());
3032

extensions/discord/src/monitor/model-picker.ts

Lines changed: 0 additions & 48 deletions
This file was deleted.

extensions/discord/src/monitor/native-command-model-picker-interaction.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,14 @@ import {
2525
findProviderBucketId,
2626
loadDiscordModelPickerData,
2727
parseDiscordModelPickerData,
28+
type DiscordModelPickerState,
29+
} from "./model-picker.state.js";
30+
import {
2831
renderDiscordModelPickerModelsView,
2932
renderDiscordModelPickerProvidersView,
3033
renderDiscordModelPickerRecentsView,
3134
toDiscordModelPickerMessagePayload,
32-
type DiscordModelPickerState,
33-
} from "./model-picker.js";
35+
} from "./model-picker.view.js";
3436
import type { DispatchDiscordCommandInteraction } from "./native-command-dispatch.js";
3537
import { applyDiscordModelPickerSelection } from "./native-command-model-picker-apply.js";
3638
import {

extensions/discord/src/monitor/native-command-model-picker-ui.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,13 @@ import {
2929
import {
3030
findProviderBucketLocation,
3131
loadDiscordModelPickerData,
32-
renderDiscordModelPickerModelsView,
3332
resolveDiscordModelPickerPageForModel,
34-
toDiscordModelPickerMessagePayload,
3533
type DiscordModelPickerCommandContext,
36-
} from "./model-picker.js";
34+
} from "./model-picker.state.js";
35+
import {
36+
renderDiscordModelPickerModelsView,
37+
toDiscordModelPickerMessagePayload,
38+
} from "./model-picker.view.js";
3739
import { resolveDiscordNativeInteractionRouteState } from "./native-command-route.js";
3840
import type { SafeDiscordInteractionCall } from "./native-command-ui.types.js";
3941
import { resolveDiscordNativeInteractionChannelContext } from "./native-interaction-channel-context.js";

0 commit comments

Comments
 (0)