@danypops/papyrus 0.23.0 → 0.24.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.
- package/README.md +1 -0
- package/extension/src/index.ts +5 -0
- package/extension/src/playbooks.ts +35 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -145,6 +145,7 @@ Tasks, Docs, Rules, and Skills all support first-class `update` (title/body/labe
|
|
|
145
145
|
- `/rules` — severity/condition rows, exact injection preview, edit, enable/disable, and task gating
|
|
146
146
|
- `/skills` — trigger/tools rows, edit, invocation into the editor, and artifact templates
|
|
147
147
|
- `/playbooks` — trigger/tools rows, edit, invocation into the editor, and graph links
|
|
148
|
+
- `/playbook <name>` — tab-completes active playbook titles and places that one's invocation directly in the editor, one step instead of browse-then-select; no argument falls back to the full `/playbooks` browser
|
|
148
149
|
|
|
149
150
|
All frontends use daemon-backed domain operations; none opens SQLite from the Pi process. **Show details** opens a bounded navigable view across Tasks, Notes, Docs, Rules, legacy Skills, templates, and workflow Skills. User-authored bodies render as width-aware Markdown with headings, emphasis, links, quotes, lists, tables, inline/fenced code, syntax highlighting, and every color/decorative style derived dynamically from the active Pi theme. Generated lifecycle, metadata, checklist, gate, history, and relationship sections keep explicit semantic theme colors. `↑/↓` scrolls, `←/→` pans wide relationships, and Esc returns to the browser; non-interactive clients receive stable source text.
|
|
150
151
|
|
package/extension/src/index.ts
CHANGED
|
@@ -462,6 +462,11 @@ export default async function (pi: ExtensionAPI) {
|
|
|
462
462
|
description: "Browse, edit, and invoke Papyrus playbooks -- trigger/steps guidance an agent reads and follows (interactive)",
|
|
463
463
|
handler: async (_args, ctx) => { await playbooksModule.showPlaybooks(ctx); },
|
|
464
464
|
});
|
|
465
|
+
pi.registerCommand("playbook", {
|
|
466
|
+
description: "Open one Papyrus playbook directly by name (tab-completes active playbook titles) and place its invocation in the editor; no argument opens the full /playbooks browser instead",
|
|
467
|
+
getArgumentCompletions: (argumentPrefix) => playbooksModule.playbookArgumentCompletions(argumentPrefix),
|
|
468
|
+
handler: async (args, ctx) => { await playbooksModule.openPlaybookByName(args, ctx); },
|
|
469
|
+
});
|
|
465
470
|
pi.registerCommand("discuss", {
|
|
466
471
|
description: "Browse Papyrus Discussions and reply, defer, resume, settle, or block/unblock a task (interactive)",
|
|
467
472
|
handler: async (_args, ctx) => { await discussModule.showDiscussions(ctx); },
|
|
@@ -1,9 +1,44 @@
|
|
|
1
|
+
import type { AutocompleteItem } from "@earendil-works/pi-tui";
|
|
1
2
|
import type { ExtensionCommandContext, Theme } from "@earendil-works/pi-coding-agent";
|
|
2
3
|
import type { Artifact } from "../../src/domain/artifact.ts";
|
|
3
4
|
import { showArtifactBrowser, showArtifactDetails } from "./artifact-browser.ts";
|
|
4
5
|
import { PLAYBOOK_STATUS_PRESENTATION } from "./artifact-status-presentation.ts";
|
|
6
|
+
import { matchArtifactByName } from "./domain-tools.ts";
|
|
5
7
|
import { callService } from "./service-client.ts";
|
|
6
8
|
|
|
9
|
+
const PLAYBOOK_COMPLETION_MAX_CANDIDATES = 100;
|
|
10
|
+
|
|
11
|
+
async function activePlaybooks(): Promise<Artifact[]> {
|
|
12
|
+
return callService<Record<string, unknown>, Artifact[]>("playbooks.list", { status: "active", limit: PLAYBOOK_COMPLETION_MAX_CANDIDATES });
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** `/playbook <tab>` completions -- title-prefix match, since that's what a human actually types, not a full-text search of body content. */
|
|
16
|
+
export async function playbookArgumentCompletions(argumentPrefix: string): Promise<AutocompleteItem[] | null> {
|
|
17
|
+
try {
|
|
18
|
+
const needle = argumentPrefix.trim().toLowerCase();
|
|
19
|
+
const rows = await activePlaybooks();
|
|
20
|
+
return rows
|
|
21
|
+
.filter((row) => row.title.toLowerCase().startsWith(needle))
|
|
22
|
+
.sort((a, b) => a.title.localeCompare(b.title))
|
|
23
|
+
.map((row) => ({ value: row.title, label: row.title, description: typeof row.extra["trigger"] === "string" ? row.extra["trigger"] : undefined }));
|
|
24
|
+
} catch {
|
|
25
|
+
return null; // a Papyrus daemon hiccup degrades to "no suggestions", never breaks the command line
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** `/playbook <name>` (no args opens the full browser instead): resolves by exact title, then places its invocation directly in the editor -- one step, not browse-then-select-then-invoke. */
|
|
30
|
+
export async function openPlaybookByName(name: string, ctx: ExtensionCommandContext): Promise<void> {
|
|
31
|
+
if (!name.trim()) { await showPlaybooks(ctx); return; }
|
|
32
|
+
try {
|
|
33
|
+
const id = matchArtifactByName(await activePlaybooks(), name);
|
|
34
|
+
const invocation = await callService<Record<string, unknown>, string>("playbooks.invoke", { id });
|
|
35
|
+
ctx.ui.setEditorText(invocation);
|
|
36
|
+
ctx.ui.notify(`"${name.trim()}" invocation placed in the editor`, "info");
|
|
37
|
+
} catch (error) {
|
|
38
|
+
ctx.ui.notify(error instanceof Error ? error.message : String(error), "error");
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
7
42
|
const PLAYBOOK_RELATIONS = ["references", "documents", "relates_to", "contains", "part_of"];
|
|
8
43
|
|
|
9
44
|
function strings(value: unknown): string[] {
|
package/package.json
CHANGED