@kata-sh/pi-symphony-extension 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,33 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { parseAttachArgs, parseDoctorArgs, parseInitArgs, parseStartArgs, parseSteerArgs } from "./command-args.ts";
3
+
4
+ describe("command argument parsing", () => {
5
+ it("parses init force flag", () => {
6
+ expect(parseInitArgs("--force")).toEqual({ force: true });
7
+ expect(parseInitArgs("")).toEqual({ force: false });
8
+ });
9
+
10
+ it("rejects unknown init flags", () => {
11
+ expect(() => parseInitArgs("--bad")).toThrow("Unknown /symphony:init option: --bad");
12
+ });
13
+
14
+ it("keeps workflow arguments as one path string", () => {
15
+ expect(parseDoctorArgs(".symphony/WORKFLOW.md")).toEqual({ workflow: ".symphony/WORKFLOW.md" });
16
+ expect(parseStartArgs("/tmp/My Workflow.md")).toEqual({ workflow: "/tmp/My Workflow.md" });
17
+ expect(parseStartArgs(" ")).toEqual({ workflow: undefined });
18
+ });
19
+
20
+ it("parses attach URL as optional", () => {
21
+ expect(parseAttachArgs("http://127.0.0.1:8080")).toEqual({ url: "http://127.0.0.1:8080" });
22
+ expect(parseAttachArgs("")).toEqual({ url: undefined });
23
+ });
24
+
25
+ it("parses steer issue and instruction", () => {
26
+ expect(parseSteerArgs("SIM-123 Use the existing auth module")).toEqual({
27
+ issueIdentifier: "SIM-123",
28
+ instruction: "Use the existing auth module",
29
+ });
30
+ expect(() => parseSteerArgs("SIM-123")).toThrow("Usage: /symphony:steer <ISSUE> <instruction>");
31
+ expect(() => parseSteerArgs(" ")).toThrow("Usage: /symphony:steer <ISSUE> <instruction>");
32
+ });
33
+ });
@@ -0,0 +1,58 @@
1
+ export interface InitArgs {
2
+ force: boolean;
3
+ }
4
+
5
+ export interface WorkflowArgs {
6
+ workflow?: string;
7
+ }
8
+
9
+ export interface AttachArgs {
10
+ url?: string;
11
+ }
12
+
13
+ export interface SteerArgs {
14
+ issueIdentifier: string;
15
+ instruction: string;
16
+ }
17
+
18
+ export function parseInitArgs(args: string): InitArgs {
19
+ const tokens = args.trim().split(/\s+/).filter(Boolean);
20
+ let force = false;
21
+ for (const token of tokens) {
22
+ if (token === "--force") {
23
+ force = true;
24
+ continue;
25
+ }
26
+ throw new Error(`Unknown /symphony:init option: ${token}`);
27
+ }
28
+ return { force };
29
+ }
30
+
31
+ export function parseDoctorArgs(args: string): WorkflowArgs {
32
+ return parseWorkflowArg(args);
33
+ }
34
+
35
+ export function parseStartArgs(args: string): WorkflowArgs {
36
+ return parseWorkflowArg(args);
37
+ }
38
+
39
+ function parseWorkflowArg(args: string): WorkflowArgs {
40
+ const workflow = args.trim();
41
+ return workflow ? { workflow } : { workflow: undefined };
42
+ }
43
+
44
+ export function parseAttachArgs(args: string): AttachArgs {
45
+ const url = args.trim();
46
+ return { url: url || undefined };
47
+ }
48
+
49
+ export function parseSteerArgs(args: string): SteerArgs {
50
+ const trimmed = args.trim();
51
+ const firstSpaceIndex = trimmed.search(/\s/);
52
+ if (!trimmed || firstSpaceIndex === -1) throw new Error("Usage: /symphony:steer <ISSUE> <instruction>");
53
+
54
+ const issueIdentifier = trimmed.slice(0, firstSpaceIndex).trim();
55
+ const instruction = trimmed.slice(firstSpaceIndex).trim();
56
+ if (!issueIdentifier || !instruction) throw new Error("Usage: /symphony:steer <ISSUE> <instruction>");
57
+ return { issueIdentifier, instruction };
58
+ }