fix: narrow skills watcher ignores (#1074) (thanks @roshanasingh4)

This commit is contained in:
Peter Steinberger 2026-01-17 07:56:35 +00:00
parent 6aaa302be5
commit e13a332ac8
7 changed files with 11 additions and 8 deletions

View File

@ -48,6 +48,7 @@
- Sessions: propagate deliveryContext into last-route updates to keep account/channel routing stable. (#1058)
- Gateway: honor explicit delivery targets without implicit accountId fallback; preserve lastAccountId for implicit routing.
- Gateway: avoid reusing last-to/accountId when the requested channel differs; sync deliveryContext with last route fields.
- Skills: narrow skills watcher ignores to `.git` so hidden workspaces still refresh. (#1074) — thanks @roshanasingh4.
- Repo: fix oxlint config filename and move ignore pattern into config. (#1064) — thanks @connorshea.
- Messages: `/stop` now hard-aborts queued followups and sub-agent runs; suppress zero-count stop notes.
- Messages: include sender labels for live group messages across channels, matching queued/history formatting. (#1059)

View File

@ -50,7 +50,7 @@ test("process submit sends CR for pty sessions", async () => {
const processTool = createProcessTool();
const result = await execTool.execute("toolcall", {
command:
"node -e \"process.stdin.on('data', d => { if (d.includes(13)) { process.stdout.write('submitted'); process.exit(0); } });\"",
"node -e \"process.stdin.on('data', d => { if (d.includes(10) || d.includes(13)) { process.stdout.write('submitted'); process.exit(0); } });\"",
pty: true,
background: true,
});

View File

@ -1,4 +1,5 @@
const DSR_PATTERN = /\x1b\[\??6n/g;
const ESC = "\u001b";
const DSR_PATTERN = new RegExp(`${ESC}\\[\\??6n`, "g");
export function stripDsrRequests(input: string): { cleaned: string; requests: number } {
let requests = 0;

View File

@ -12,7 +12,7 @@ vi.mock("chokidar", () => {
});
describe("ensureSkillsWatcher", () => {
it("ignores node_modules and dist by default", async () => {
it("ignores node_modules, dist, and .git by default", async () => {
const mod = await import("./refresh.js");
mod.ensureSkillsWatcher({ workspaceDir: "/tmp/workspace" });
@ -26,5 +26,6 @@ describe("ensureSkillsWatcher", () => {
);
expect(ignored.some((re) => re.test("/tmp/workspace/skills/dist/index.js"))).toBe(true);
expect(ignored.some((re) => re.test("/tmp/workspace/skills/.git/config"))).toBe(true);
expect(ignored.some((re) => re.test("/tmp/.hidden/skills/index.md"))).toBe(false);
});
});

View File

@ -128,7 +128,7 @@ export function ensureSkillsWatcher(params: { workspaceDir: string; config?: Cla
// Avoid FD exhaustion on macOS when a workspace contains huge trees.
// This watcher only needs to react to skill changes.
ignored: [
/(^|[\\/])\../, // dotfiles (includes .git)
/(^|[\\/])\.git([\\/]|$)/,
/(^|[\\/])node_modules([\\/]|$)/,
/(^|[\\/])dist([\\/]|$)/,
],

View File

@ -677,15 +677,15 @@ export function registerHooksCli(program: Command): void {
for (const hookId of targets) {
const record = installs[hookId];
if (!record) {
defaultRuntime.log(chalk.yellow(`No install record for \"${hookId}\".`));
defaultRuntime.log(chalk.yellow(`No install record for "${hookId}".`));
continue;
}
if (record.source !== "npm") {
defaultRuntime.log(chalk.yellow(`Skipping \"${hookId}\" (source: ${record.source}).`));
defaultRuntime.log(chalk.yellow(`Skipping "${hookId}" (source: ${record.source}).`));
continue;
}
if (!record.spec) {
defaultRuntime.log(chalk.yellow(`Skipping \"${hookId}\" (missing npm spec).`));
defaultRuntime.log(chalk.yellow(`Skipping "${hookId}" (missing npm spec).`));
continue;
}

View File

@ -102,7 +102,7 @@ export function normalizeAttachments(ctx: MsgContext): MediaAttachment[] {
export function resolveAttachmentKind(
attachment: MediaAttachment,
): "image" | "audio" | "video" | "unknown" {
): "image" | "audio" | "video" | "document" | "unknown" {
const kind = kindFromMime(attachment.mime);
if (kind !== "unknown") return kind;