@selesai/code 0.5.21 → 0.5.22
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.
- package/README.md +1 -1
- package/dist/core/agent-session-skill-block.test.d.ts +2 -0
- package/dist/core/agent-session-skill-block.test.d.ts.map +1 -0
- package/dist/core/agent-session-skill-block.test.js +20 -0
- package/dist/core/agent-session-skill-block.test.js.map +1 -0
- package/dist/core/agent-session.d.ts +7 -4
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +22 -12
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +1 -1
- package/dist/core/skills.js.map +1 -1
- package/dist/extensions/inline-skills.test.ts +96 -0
- package/dist/extensions/inline-skills.ts +92 -0
- package/dist/extensions/package.json +1 -0
- package/dist/extensions/pi-powerline-footer/tests/tps.test.ts +39 -0
- package/dist/extensions/pi-powerline-footer/tps.ts +172 -113
- package/dist/extensions/question/batch.ts +89 -25
- package/dist/extensions/question/constants.ts +1 -1
- package/dist/extensions/question/helpers.ts +34 -78
- package/dist/extensions/question/index.ts +327 -564
- package/dist/extensions/question/package.json +2 -1
- package/dist/extensions/question/question-list.ts +21 -14
- package/dist/extensions/question/row-layout.ts +2 -2
- package/dist/extensions/question/schemas.ts +33 -47
- package/dist/extensions/question/selection-mode.ts +5 -7
- package/dist/extensions/question/tests/batch.test.ts +65 -16
- package/dist/extensions/question/tests/helpers.test.ts +31 -156
- package/dist/extensions/question/tests/question-list.test.ts +17 -3
- package/dist/extensions/question/tests/row-layout.test.ts +4 -4
- package/dist/extensions/question/tests/schemas.test.ts +30 -0
- package/dist/extensions/question/tests/wizard.test.ts +99 -0
- package/dist/extensions/question/types.ts +65 -66
- package/dist/extensions/workflow/adapter.ts +4 -76
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +10 -10
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/skills/workflow-creation/SKILL.md +2 -2
- package/docs/skills.md +8 -0
- package/docs/workflows.md +4 -4
- package/package.json +1 -1
|
@@ -1,102 +1,58 @@
|
|
|
1
1
|
// Pure helper functions for the question extension.
|
|
2
2
|
|
|
3
|
-
import type {
|
|
3
|
+
import type { PreparedQuestion, QuestionOption, QuestionResponse } from "./types.ts";
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
for (const option of options ?? []) {
|
|
9
|
-
if (typeof option !== "string") continue;
|
|
10
|
-
const text = option.trim();
|
|
11
|
-
if (!text.startsWith("[") && !text.startsWith("{")) continue;
|
|
12
|
-
try {
|
|
13
|
-
const parsed = JSON.parse(text);
|
|
14
|
-
const jsonOption = (value: unknown) => !!value && typeof value === "object" && typeof (value as { label?: unknown }).label === "string";
|
|
15
|
-
if (jsonOption(parsed) || (Array.isArray(parsed) && parsed.some(jsonOption))) {
|
|
16
|
-
return 'Invalid question.options: pass an array of strings or {label, description} objects, not a JSON-encoded string. Example: {"options":[{"label":"Yes","description":"..."}]}, not {"options":["[{\\"label\\":\\"Yes\\"}]"]}.';
|
|
17
|
-
}
|
|
18
|
-
} catch {}
|
|
19
|
-
}
|
|
20
|
-
return null;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function normalizeOptions(options: RawOption[] | undefined): QuestionOption[] {
|
|
24
|
-
return (options ?? [])
|
|
25
|
-
.map((option) =>
|
|
26
|
-
typeof option === "string"
|
|
27
|
-
? { label: option }
|
|
28
|
-
: { label: option.label, description: option.description },
|
|
29
|
-
)
|
|
30
|
-
.filter((option) => option.label.trim().length > 0);
|
|
5
|
+
export function trimText(value: string | null | undefined): string | undefined {
|
|
6
|
+
const trimmed = value?.trim();
|
|
7
|
+
return trimmed || undefined;
|
|
31
8
|
}
|
|
32
9
|
|
|
33
10
|
export function oneLine(value: unknown, max = 100): string {
|
|
34
11
|
const text = String(value ?? "").replace(/\s+/g, " ").trim();
|
|
35
|
-
return text.length > max ? `${text.slice(0, max - 1)}…` : text;
|
|
12
|
+
return text.length > max ? `${text.slice(0, Math.max(0, max - 1))}…` : text;
|
|
36
13
|
}
|
|
37
14
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (_getMarkdownTheme === undefined) {
|
|
45
|
-
// Dynamic require avoids breaking module load when package is absent.
|
|
46
|
-
_getMarkdownTheme = (globalThis as any).require
|
|
47
|
-
? (globalThis as any).require("@selesai/code").getMarkdownTheme
|
|
48
|
-
: null;
|
|
49
|
-
}
|
|
50
|
-
if (!_getMarkdownTheme) return undefined;
|
|
51
|
-
const md = _getMarkdownTheme();
|
|
52
|
-
if (!md) return undefined;
|
|
53
|
-
md.bold("");
|
|
54
|
-
return md;
|
|
55
|
-
} catch {
|
|
56
|
-
return undefined;
|
|
57
|
-
}
|
|
15
|
+
export function previewText(value: unknown, max = 160, maxLines = 2): string {
|
|
16
|
+
const lines = String(value ?? "").trim().split(/\r?\n/);
|
|
17
|
+
const limited = lines.slice(0, maxLines).join("\n");
|
|
18
|
+
const wasCut = lines.length > maxLines || limited.length > max;
|
|
19
|
+
const text = limited.length > max ? limited.slice(0, Math.max(0, max - 1)) : limited;
|
|
20
|
+
return wasCut ? `${text}…` : text;
|
|
58
21
|
}
|
|
59
22
|
|
|
60
|
-
export function
|
|
61
|
-
const
|
|
62
|
-
return
|
|
23
|
+
export function createTextResponse(text: string | null | undefined): QuestionResponse | null {
|
|
24
|
+
const normalized = trimText(text);
|
|
25
|
+
return normalized ? { kind: "text", text: normalized } : null;
|
|
63
26
|
}
|
|
64
27
|
|
|
65
|
-
export function createSelectionResponse(
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
return
|
|
28
|
+
export function createSelectionResponse(values: string[], otherText?: string | null): QuestionResponse | null {
|
|
29
|
+
const normalizedValues = values.map((value) => value.trim()).filter(Boolean);
|
|
30
|
+
const normalizedOther = trimText(otherText);
|
|
31
|
+
if (normalizedValues.length === 0 && !normalizedOther) return null;
|
|
32
|
+
return normalizedOther
|
|
33
|
+
? { kind: "selection", values: normalizedValues, otherText: normalizedOther }
|
|
34
|
+
: { kind: "selection", values: normalizedValues };
|
|
70
35
|
}
|
|
71
36
|
|
|
72
37
|
export function formatResponseSummary(response: QuestionResponse): string {
|
|
73
|
-
if (response.kind === "
|
|
74
|
-
|
|
75
|
-
|
|
38
|
+
if (response.kind === "text") return response.text;
|
|
39
|
+
return [...response.values, ...(response.otherText ? [response.otherText] : [])].join(", ");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function formatQuestionResponse(question: PreparedQuestion, response: QuestionResponse): string {
|
|
43
|
+
if (response.kind === "text") return response.text;
|
|
44
|
+
const labels = response.values.map(
|
|
45
|
+
(value) => question.options.find((option) => option.value === value)?.label ?? value,
|
|
46
|
+
);
|
|
47
|
+
if (response.otherText) labels.push(`Other: ${response.otherText}`);
|
|
48
|
+
return labels.join(", ");
|
|
76
49
|
}
|
|
77
50
|
|
|
78
51
|
export function formatOptionsForMessage(options: QuestionOption[]): string {
|
|
79
52
|
return options
|
|
80
53
|
.map((option, index) => {
|
|
81
|
-
const
|
|
82
|
-
return `${index + 1}. ${option.label}${
|
|
54
|
+
const description = option.description ? ` — ${option.description}` : "";
|
|
55
|
+
return `${index + 1}. ${option.label}${description}`;
|
|
83
56
|
})
|
|
84
57
|
.join("\n");
|
|
85
58
|
}
|
|
86
|
-
|
|
87
|
-
export function buildCommentPrompt(prompt: string, selections: string[]): string {
|
|
88
|
-
const label = selections.length === 1 ? "Selected option" : "Selected options";
|
|
89
|
-
const lines = selections.map((selection) => `- ${selection}`).join("\n");
|
|
90
|
-
return `${prompt}\n\n${label}:\n${lines}`;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export function parseDialogSelections(input: string): string[] {
|
|
94
|
-
return input
|
|
95
|
-
.split(",")
|
|
96
|
-
.map((selection) => selection.trim())
|
|
97
|
-
.filter(Boolean);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export function isCancelled(value: unknown): value is null | undefined {
|
|
101
|
-
return value === null || value === undefined;
|
|
102
|
-
}
|