fix: remove workflow completion surface

This commit is contained in:
2026-07-16 06:22:41 +09:00
parent d30dca2d99
commit 0b56052a44
10 changed files with 73 additions and 36 deletions
@@ -1,4 +1,7 @@
import { buildComposerRequest, parseSigilSegments } from "./composer-command.ts";
import {
buildComposerRequest,
parseSigilSegments,
} from "./composer-command.ts";
declare const Deno: {
test(name: string, fn: () => void): void;
@@ -19,13 +22,16 @@ function assertEquals<T>(actual: T, expected: T): void {
}
Deno.test("parseSigilSegments converts TUI-style references", () => {
assertEquals(parseSigilSegments("read @src/main.rs then #memory and /workflow"), [
{ kind: "text", content: "read " },
{ kind: "file_ref", path: "src/main.rs" },
{ kind: "text", content: " then " },
{ kind: "knowledge_ref", slug: "memory" },
{ kind: "text", content: " and /workflow" },
]);
assertEquals(
parseSigilSegments("read @src/main.rs then #memory and /literal"),
[
{ kind: "text", content: "read " },
{ kind: "file_ref", path: "src/main.rs" },
{ kind: "text", content: " then " },
{ kind: "knowledge_ref", slug: "memory" },
{ kind: "text", content: " and /literal" },
],
);
});
Deno.test("buildComposerRequest sends user segments when sigils are present", () => {
@@ -51,7 +57,10 @@ Deno.test("buildComposerRequest parses colon commands", () => {
const help = buildComposerRequest(":help compact");
assert(help.ok, "help should be accepted");
assertEquals(help.request, undefined);
assert(help.notice?.includes(":compact"), "help should return a local notice");
assert(
help.notice?.includes(":compact"),
"help should return a local notice",
);
});
Deno.test("buildComposerRequest rejects invalid colon commands", () => {
@@ -32,7 +32,7 @@ Deno.test("completionTokenAt detects TUI-style sigils before the cursor", () =>
});
assertEquals(completionTokenAt(":comp", 5)?.kind, "command");
assertEquals(completionTokenAt("ask #mem", 8)?.kind, "knowledge");
assertEquals(completionTokenAt("run /work", 9)?.kind, "workflow");
assertEquals(completionTokenAt("run /work", 9), null);
});
Deno.test("applyCompletion replaces the active token and advances the cursor", () => {
@@ -50,5 +50,7 @@ Deno.test("applyCompletion replaces the active token and advances the cursor", (
});
Deno.test("localCommandCompletions filters colon commands", () => {
assertEquals(localCommandCompletions("com").map((entry) => entry.value), ["compact"]);
assertEquals(localCommandCompletions("com").map((entry) => entry.value), [
"compact",
]);
});
@@ -1,7 +1,7 @@
export type ComposerCompletionKind = "command" | "file" | "knowledge" | "workflow";
export type ComposerCompletionKind = "command" | "file" | "knowledge";
export type ComposerCompletionToken = {
sigil: ":" | "@" | "#" | "/";
sigil: ":" | "@" | "#";
kind: ComposerCompletionKind;
start: number;
end: number;
@@ -35,7 +35,7 @@ export function completionTokenAt(
): ComposerCompletionToken | null {
const boundedCursor = Math.max(0, Math.min(cursor, value.length));
const before = value.slice(0, boundedCursor);
const match = /(^|\s)([:@#/])([^\s]*)$/.exec(before);
const match = /(^|\s)([:@#])([^\s]*)$/.exec(before);
if (!match) {
return null;
}
@@ -51,7 +51,9 @@ export function completionTokenAt(
};
}
export function localCommandCompletions(prefix: string): ComposerCompletionEntry[] {
export function localCommandCompletions(
prefix: string,
): ComposerCompletionEntry[] {
const normalized = prefix.toLowerCase();
return COLON_COMMAND_COMPLETIONS.filter((entry) =>
entry.value.toLowerCase().startsWith(normalized)
@@ -65,13 +67,19 @@ export function applyCompletion(
): CompletionApplyResult {
const suffix = entry.is_dir ? "/" : " ";
const replacement = `${token.sigil}${entry.value}${suffix}`;
const restStart = !entry.is_dir && value[token.end] === " " ? token.end + 1 : token.end;
const next = `${value.slice(0, token.start)}${replacement}${value.slice(restStart)}`;
const restStart = !entry.is_dir && value[token.end] === " "
? token.end + 1
: token.end;
const next = `${value.slice(0, token.start)}${replacement}${
value.slice(restStart)
}`;
const cursor = token.start + replacement.length;
return { value: next, cursor };
}
function completionKindForSigil(sigil: ComposerCompletionToken["sigil"]): ComposerCompletionKind {
function completionKindForSigil(
sigil: ComposerCompletionToken["sigil"],
): ComposerCompletionKind {
switch (sigil) {
case ":":
return "command";
@@ -79,7 +87,5 @@ function completionKindForSigil(sigil: ComposerCompletionToken["sigil"]): Compos
return "file";
case "#":
return "knowledge";
case "/":
return "workflow";
}
}
@@ -46,7 +46,7 @@
}
type WorkerCompletionsResult = {
kind: "file" | "knowledge" | "workflow";
kind: "file" | "knowledge";
prefix: string;
entries: ComposerCompletionEntry[];
diagnostics: Diagnostic[];