Compare commits
2 Commits
main
...
fix/1056-i
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e13a332ac8 | ||
|
|
6aaa302be5 |
@ -48,6 +48,7 @@
|
|||||||
- Sessions: propagate deliveryContext into last-route updates to keep account/channel routing stable. (#1058)
|
- 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: 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.
|
- 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.
|
- 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: `/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)
|
- Messages: include sender labels for live group messages across channels, matching queued/history formatting. (#1059)
|
||||||
|
|||||||
@ -50,7 +50,7 @@ test("process submit sends CR for pty sessions", async () => {
|
|||||||
const processTool = createProcessTool();
|
const processTool = createProcessTool();
|
||||||
const result = await execTool.execute("toolcall", {
|
const result = await execTool.execute("toolcall", {
|
||||||
command:
|
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,
|
pty: true,
|
||||||
background: true,
|
background: true,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -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 } {
|
export function stripDsrRequests(input: string): { cleaned: string; requests: number } {
|
||||||
let requests = 0;
|
let requests = 0;
|
||||||
|
|||||||
31
src/agents/skills/refresh.test.ts
Normal file
31
src/agents/skills/refresh.test.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import { describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
|
const watchMock = vi.fn(() => ({
|
||||||
|
on: vi.fn(),
|
||||||
|
close: vi.fn(async () => undefined),
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock("chokidar", () => {
|
||||||
|
return {
|
||||||
|
default: { watch: watchMock },
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("ensureSkillsWatcher", () => {
|
||||||
|
it("ignores node_modules, dist, and .git by default", async () => {
|
||||||
|
const mod = await import("./refresh.js");
|
||||||
|
mod.ensureSkillsWatcher({ workspaceDir: "/tmp/workspace" });
|
||||||
|
|
||||||
|
expect(watchMock).toHaveBeenCalledTimes(1);
|
||||||
|
const opts = watchMock.mock.calls[0]?.[1] as { ignored?: unknown };
|
||||||
|
|
||||||
|
expect(Array.isArray(opts.ignored)).toBe(true);
|
||||||
|
const ignored = opts.ignored as RegExp[];
|
||||||
|
expect(ignored.some((re) => re.test("/tmp/workspace/skills/node_modules/pkg/index.js"))).toBe(
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -125,6 +125,13 @@ export function ensureSkillsWatcher(params: { workspaceDir: string; config?: Cla
|
|||||||
stabilityThreshold: debounceMs,
|
stabilityThreshold: debounceMs,
|
||||||
pollInterval: 100,
|
pollInterval: 100,
|
||||||
},
|
},
|
||||||
|
// Avoid FD exhaustion on macOS when a workspace contains huge trees.
|
||||||
|
// This watcher only needs to react to skill changes.
|
||||||
|
ignored: [
|
||||||
|
/(^|[\\/])\.git([\\/]|$)/,
|
||||||
|
/(^|[\\/])node_modules([\\/]|$)/,
|
||||||
|
/(^|[\\/])dist([\\/]|$)/,
|
||||||
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
const state: SkillsWatchState = { watcher, pathsKey, debounceMs };
|
const state: SkillsWatchState = { watcher, pathsKey, debounceMs };
|
||||||
|
|||||||
@ -677,15 +677,15 @@ export function registerHooksCli(program: Command): void {
|
|||||||
for (const hookId of targets) {
|
for (const hookId of targets) {
|
||||||
const record = installs[hookId];
|
const record = installs[hookId];
|
||||||
if (!record) {
|
if (!record) {
|
||||||
defaultRuntime.log(chalk.yellow(`No install record for \"${hookId}\".`));
|
defaultRuntime.log(chalk.yellow(`No install record for "${hookId}".`));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (record.source !== "npm") {
|
if (record.source !== "npm") {
|
||||||
defaultRuntime.log(chalk.yellow(`Skipping \"${hookId}\" (source: ${record.source}).`));
|
defaultRuntime.log(chalk.yellow(`Skipping "${hookId}" (source: ${record.source}).`));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!record.spec) {
|
if (!record.spec) {
|
||||||
defaultRuntime.log(chalk.yellow(`Skipping \"${hookId}\" (missing npm spec).`));
|
defaultRuntime.log(chalk.yellow(`Skipping "${hookId}" (missing npm spec).`));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -102,7 +102,7 @@ export function normalizeAttachments(ctx: MsgContext): MediaAttachment[] {
|
|||||||
|
|
||||||
export function resolveAttachmentKind(
|
export function resolveAttachmentKind(
|
||||||
attachment: MediaAttachment,
|
attachment: MediaAttachment,
|
||||||
): "image" | "audio" | "video" | "unknown" {
|
): "image" | "audio" | "video" | "document" | "unknown" {
|
||||||
const kind = kindFromMime(attachment.mime);
|
const kind = kindFromMime(attachment.mime);
|
||||||
if (kind !== "unknown") return kind;
|
if (kind !== "unknown") return kind;
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user