From a27624437e96fb2ffd53521fa1ab78ca64c7fcb7 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 27 Mar 2026 23:18:07 +0000 Subject: [PATCH] fix(ci): align skills api drift and tui keybindings --- src/agents/compaction.retry.test.ts | 2 +- src/agents/compaction.ts | 27 +++++++------------ src/agents/skills-install.download.test.ts | 6 ++++- src/agents/skills-status.test.ts | 6 ++++- .../skills.buildworkspaceskillstatus.test.ts | 6 ++++- .../skills.resolveskillspromptforrun.test.ts | 6 ++++- src/agents/skills/compact-format.test.ts | 11 ++++++-- src/agents/skills/source.ts | 2 +- src/cli/skills-cli.formatting.test.ts | 6 ++++- src/tui/components/filterable-select-list.ts | 6 ++--- src/tui/components/searchable-select-list.ts | 6 ++--- 11 files changed, 51 insertions(+), 33 deletions(-) diff --git a/src/agents/compaction.retry.test.ts b/src/agents/compaction.retry.test.ts index 31404e2e9b2..30f81ca6664 100644 --- a/src/agents/compaction.retry.test.ts +++ b/src/agents/compaction.retry.test.ts @@ -56,7 +56,7 @@ describe("compaction retry integration", () => { } as unknown as NonNullable; const invokeGenerateSummary = (signal = new AbortController().signal) => - mockGenerateSummary(testMessages, testModel, 1000, "test-api-key", signal); + mockGenerateSummary(testMessages, testModel, 1000, "test-api-key", undefined, signal); const runSummaryRetry = (options: Parameters[1]) => retryAsync(() => invokeGenerateSummary(), options); diff --git a/src/agents/compaction.ts b/src/agents/compaction.ts index 20a6d80fa43..c8d7209028a 100644 --- a/src/agents/compaction.ts +++ b/src/agents/compaction.ts @@ -208,22 +208,6 @@ export function isOversizedForSummary(msg: AgentMessage, contextWindow: number): return tokens > contextWindow * 0.5; } -function withSummaryHeaders( - model: NonNullable, - headers?: Record, -): NonNullable { - if (!headers || Object.keys(headers).length === 0) { - return model; - } - return { - ...model, - headers: { - ...model.headers, - ...headers, - }, - }; -} - async function summarizeChunks(params: { messages: AgentMessage[]; model: NonNullable; @@ -248,15 +232,22 @@ async function summarizeChunks(params: { params.customInstructions, params.summarizationInstructions, ); - const model = withSummaryHeaders(params.model, params.headers); + const headers = + params.headers || params.model.headers + ? { + ...params.model.headers, + ...params.headers, + } + : undefined; for (const chunk of chunks) { summary = await retryAsync( () => generateSummary( chunk, - model, + params.model, params.reserveTokens, params.apiKey, + headers, params.signal, effectiveInstructions, summary, diff --git a/src/agents/skills-install.download.test.ts b/src/agents/skills-install.download.test.ts index bd8559b60fe..f3a879066a6 100644 --- a/src/agents/skills-install.download.test.ts +++ b/src/agents/skills-install.download.test.ts @@ -1,6 +1,7 @@ import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; +import { createSyntheticSourceInfo } from "@mariozechner/pi-coding-agent"; import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import { installDownloadSpec } from "./skills-install-download.js"; import { setTempStateDir } from "./skills-install.download-test-utils.js"; @@ -60,7 +61,10 @@ function buildEntry(name: string): SkillEntry { description: `${name} test skill`, filePath: path.join(skillDir, "SKILL.md"), baseDir: skillDir, - source: "openclaw-workspace", + sourceInfo: createSyntheticSourceInfo(path.join(skillDir, "SKILL.md"), { + source: "openclaw-workspace", + baseDir: skillDir, + }), disableModelInvocation: false, }, frontmatter: {}, diff --git a/src/agents/skills-status.test.ts b/src/agents/skills-status.test.ts index 3e0b2ab6783..2d3abda70b4 100644 --- a/src/agents/skills-status.test.ts +++ b/src/agents/skills-status.test.ts @@ -1,3 +1,4 @@ +import { createSyntheticSourceInfo } from "@mariozechner/pi-coding-agent"; import { describe, expect, it } from "vitest"; import { buildWorkspaceSkillStatus } from "./skills-status.js"; import type { SkillEntry } from "./skills/types.js"; @@ -17,7 +18,10 @@ describe("buildWorkspaceSkillStatus", () => { description: "test", filePath: "/tmp/os-scoped", baseDir: "/tmp", - source: "test", + sourceInfo: createSyntheticSourceInfo("/tmp/os-scoped", { + source: "test", + baseDir: "/tmp", + }), disableModelInvocation: false, }, frontmatter: {}, diff --git a/src/agents/skills.buildworkspaceskillstatus.test.ts b/src/agents/skills.buildworkspaceskillstatus.test.ts index 4b3cca8808f..36089a505fa 100644 --- a/src/agents/skills.buildworkspaceskillstatus.test.ts +++ b/src/agents/skills.buildworkspaceskillstatus.test.ts @@ -1,3 +1,4 @@ +import { createSyntheticSourceInfo } from "@mariozechner/pi-coding-agent"; import { describe, expect, it } from "vitest"; import { withEnv } from "../test-utils/env.js"; import { buildWorkspaceSkillStatus } from "./skills-status.js"; @@ -24,7 +25,10 @@ function makeEntry(params: { description: `desc:${params.name}`, filePath: `/tmp/${params.name}/SKILL.md`, baseDir: `/tmp/${params.name}`, - source: params.source ?? "openclaw-workspace", + sourceInfo: createSyntheticSourceInfo(`/tmp/${params.name}/SKILL.md`, { + source: params.source ?? "openclaw-workspace", + baseDir: `/tmp/${params.name}`, + }), disableModelInvocation: false, }, frontmatter: {}, diff --git a/src/agents/skills.resolveskillspromptforrun.test.ts b/src/agents/skills.resolveskillspromptforrun.test.ts index 305e11f2f4e..3e655721e21 100644 --- a/src/agents/skills.resolveskillspromptforrun.test.ts +++ b/src/agents/skills.resolveskillspromptforrun.test.ts @@ -1,3 +1,4 @@ +import { createSyntheticSourceInfo } from "@mariozechner/pi-coding-agent"; import { describe, expect, it } from "vitest"; import { resolveSkillsPromptForRun } from "./skills.js"; import type { SkillEntry } from "./skills/types.js"; @@ -17,7 +18,10 @@ describe("resolveSkillsPromptForRun", () => { description: "Demo", filePath: "/app/skills/demo-skill/SKILL.md", baseDir: "/app/skills/demo-skill", - source: "openclaw-bundled", + sourceInfo: createSyntheticSourceInfo("/app/skills/demo-skill/SKILL.md", { + source: "openclaw-bundled", + baseDir: "/app/skills/demo-skill", + }), disableModelInvocation: false, }, frontmatter: {}, diff --git a/src/agents/skills/compact-format.test.ts b/src/agents/skills/compact-format.test.ts index cd9d6f42f15..9f4cf961135 100644 --- a/src/agents/skills/compact-format.test.ts +++ b/src/agents/skills/compact-format.test.ts @@ -1,5 +1,9 @@ import os from "node:os"; -import { formatSkillsForPrompt, type Skill } from "@mariozechner/pi-coding-agent"; +import { + createSyntheticSourceInfo, + formatSkillsForPrompt, + type Skill, +} from "@mariozechner/pi-coding-agent"; import { describe, expect, it } from "vitest"; import type { OpenClawConfig } from "../../config/config.js"; import type { SkillEntry } from "./types.js"; @@ -15,7 +19,10 @@ function makeSkill(name: string, desc = "A skill", filePath = `/skills/${name}/S description: desc, filePath, baseDir: `/skills/${name}`, - source: "workspace", + sourceInfo: createSyntheticSourceInfo(filePath, { + source: "workspace", + baseDir: `/skills/${name}`, + }), disableModelInvocation: false, }; } diff --git a/src/agents/skills/source.ts b/src/agents/skills/source.ts index d90f0514ccd..f1ff2885ec3 100644 --- a/src/agents/skills/source.ts +++ b/src/agents/skills/source.ts @@ -1,5 +1,5 @@ import type { Skill } from "@mariozechner/pi-coding-agent"; export function resolveSkillSource(skill: Skill): string { - return skill.source ?? "unknown"; + return skill.sourceInfo.source ?? "unknown"; } diff --git a/src/cli/skills-cli.formatting.test.ts b/src/cli/skills-cli.formatting.test.ts index 7002bdc4aec..8bc07c9a79b 100644 --- a/src/cli/skills-cli.formatting.test.ts +++ b/src/cli/skills-cli.formatting.test.ts @@ -1,6 +1,7 @@ import fs from "node:fs"; import os from "node:os"; import path from "node:path"; +import { createSyntheticSourceInfo } from "@mariozechner/pi-coding-agent"; import { afterAll, beforeAll, describe, expect, it } from "vitest"; import { buildWorkspaceSkillStatus } from "../agents/skills-status.js"; import type { SkillEntry } from "../agents/skills.js"; @@ -38,7 +39,10 @@ describe("skills-cli (e2e)", () => { description: "Capture UI screenshots", filePath: path.join(baseDir, "SKILL.md"), baseDir, - source: "openclaw-bundled", + sourceInfo: createSyntheticSourceInfo(path.join(baseDir, "SKILL.md"), { + source: "openclaw-bundled", + baseDir, + }), disableModelInvocation: false, }, frontmatter: {}, diff --git a/src/tui/components/filterable-select-list.ts b/src/tui/components/filterable-select-list.ts index e6b3e7bdbfd..21123aa0466 100644 --- a/src/tui/components/filterable-select-list.ts +++ b/src/tui/components/filterable-select-list.ts @@ -1,6 +1,6 @@ import type { Component } from "@mariozechner/pi-tui"; import { - getEditorKeybindings, + getKeybindings, Input, matchesKey, type SelectItem, @@ -110,8 +110,8 @@ export class FilterableSelectList implements Component { } // Escape: clear filter or cancel - const keybindings = getEditorKeybindings(); - if (keybindings.matches(keyData, "selectCancel")) { + const keybindings = getKeybindings(); + if (keybindings.matches(keyData, "tui.select.cancel")) { if (this.filterText) { this.filterText = ""; this.input.setValue(""); diff --git a/src/tui/components/searchable-select-list.ts b/src/tui/components/searchable-select-list.ts index cff3a6b9a7f..63b2af2cfbe 100644 --- a/src/tui/components/searchable-select-list.ts +++ b/src/tui/components/searchable-select-list.ts @@ -1,6 +1,6 @@ import { type Component, - getEditorKeybindings, + getKeybindings, Input, isKeyRelease, matchesKey, @@ -362,8 +362,8 @@ export class SearchableSelectList implements Component { return; } - const keybindings = getEditorKeybindings(); - if (keybindings.matches(keyData, "selectCancel")) { + const keybindings = getKeybindings(); + if (keybindings.matches(keyData, "tui.select.cancel")) { if (this.onCancel) { this.onCancel(); }