@danypops/papyrus 0.29.3 → 0.29.5

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.
@@ -150,6 +150,23 @@ async function resolveArtifactIdByName(listOperation: OperationName, baseRequest
150
150
  return matchArtifactByName(candidates, name);
151
151
  }
152
152
 
153
+ /**
154
+ * Playbook `arguments` is intentionally untyped in this tool's schema (an array on create, a
155
+ * {name: value} map on invoke) -- unlike every other JSON-shaped field here, which has a concrete
156
+ * array/record schema the calling layer can serialize correctly. A genuinely schema-less field can
157
+ * arrive pre-serialized as JSON text instead of a parsed value; parse it back in place before it
158
+ * reaches the service, the same tolerance the CLI's own --arguments-json/--*-json flags already give.
159
+ */
160
+ export function normalizeJsonEncodedField(params: Record<string, unknown>, key: string): void {
161
+ const value = params[key];
162
+ if (typeof value !== "string") return;
163
+ try {
164
+ params[key] = JSON.parse(value);
165
+ } catch {
166
+ throw new Error(`${key} must be valid JSON`);
167
+ }
168
+ }
169
+
153
170
  /** Resolves every {nameKey -> idKey} pair present and not already satisfied by an explicit id, in place. */
154
171
  async function resolveNameFields(
155
172
  params: Record<string, unknown>,
@@ -610,6 +627,7 @@ export function registerDomainTools(pi: ExtensionAPI): void {
610
627
  await resolveNameFields(params, [
611
628
  { nameKey: "name", idKey: "id", listOperation: "playbooks.list", baseRequest: { project_root: params.project_root } },
612
629
  ]);
630
+ if (action === "create" || action === "invoke") normalizeJsonEncodedField(params, "arguments");
613
631
  if (action === "create") {
614
632
  const artifact = await callService<Record<string, unknown>, Artifact>("playbooks.create", params);
615
633
  return text(`Created playbook ${artifactLine(artifact)}`, createArtifactDetails("playbooks.create", artifact));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danypops/papyrus",
3
- "version": "0.29.3",
3
+ "version": "0.29.5",
4
4
  "description": "Daemon-backed graph artifacts, evidence-bearing tasks, rules, skills, and native TUI workflows for Pi",
5
5
  "type": "module",
6
6
  "keywords": ["pi-package"],
package/src/cli.ts CHANGED
@@ -112,7 +112,8 @@ const USAGE = `Usage:
112
112
  papyrus skills instantiate <template-id> [--title <title>] [--body <body>] [--status <status>] [--labels-json <json>] [--extra-json <json>] [--json]
113
113
  papyrus skills assign-project <id> [project-root] [--json]
114
114
  papyrus skills update <id> [--title <title>] [--body <body>] [--labels-json <json>] [--json]
115
- papyrus playbooks create --title <title> [--body <body>] [--trigger <text>] [--steps-json <json>] [--tools-json <json>] [--labels-json <json>] [--extra-json <json>] [--project-root <path>] [--json]
115
+ papyrus playbooks create --title <title> [--body <body>] [--trigger <text>] [--steps-json <json>] [--tools-json <json>] [--labels-json <json>] [--extra-json <json>] [--arguments-json <json array>] [--project-root <path>] [--json]
116
+ papyrus playbooks invoke <id> [--arguments-json <json object>] [--json]
116
117
  papyrus playbooks list [--status <status>] [--text <query>] [--limit <count>] [--project-root <path>] [--json]
117
118
  papyrus playbooks show <id> [--json]
118
119
  papyrus playbooks invoke <id> [--json]
@@ -201,6 +202,17 @@ function parseJsonStringArrayFlag(value: string | undefined, flag: string): stri
201
202
  return parsed as string[];
202
203
  }
203
204
 
205
+ /**
206
+ * No shape assertion here -- unlike every other JSON flag, playbooks --arguments-json is genuinely
207
+ * polymorphic (an array on create, a {name: value} map on invoke), and the two actions share one
208
+ * flag-parsing pass in runPlaybooksCli. The service validates the shape for whichever operation
209
+ * actually receives it.
210
+ */
211
+ function parseJsonAnyFlag(value: string | undefined, flag: string): unknown {
212
+ if (value === undefined) throw new Error(`${flag} requires a value`);
213
+ return JSON.parse(value) as unknown;
214
+ }
215
+
204
216
  function artifactLabel(artifact: CliArtifact): string {
205
217
  return `${artifact.id} ${artifact.title}`;
206
218
  }
@@ -786,6 +798,7 @@ export async function runPlaybooksCli(args: string[], client: TaskCliClient): Pr
786
798
  let tools: string[] | undefined;
787
799
  let labels: string[] | undefined;
788
800
  let extra: Record<string, unknown> | undefined;
801
+ let playbookArguments: unknown;
789
802
  let status: string | undefined;
790
803
  let text: string | undefined;
791
804
  let limit: number | undefined;
@@ -800,6 +813,7 @@ export async function runPlaybooksCli(args: string[], client: TaskCliClient): Pr
800
813
  if (argument === "--tools-json") { tools = parseJsonStringArrayFlag(args[++index], "--tools-json"); continue; }
801
814
  if (argument === "--labels-json") { labels = parseJsonStringArrayFlag(args[++index], "--labels-json"); continue; }
802
815
  if (argument === "--extra-json") { extra = parseJsonObjectFlag(args[++index], "--extra-json"); continue; }
816
+ if (argument === "--arguments-json") { playbookArguments = parseJsonAnyFlag(args[++index], "--arguments-json"); continue; }
803
817
  if (argument === "--status") { status = args[++index]; if (!status) throw new Error("--status requires a value"); continue; }
804
818
  if (argument === "--text") { text = args[++index]; if (text === undefined) throw new Error("--text requires a value"); continue; }
805
819
  if (argument === "--project-root") { playbookProjectRoot = args[++index]; if (!playbookProjectRoot) throw new Error("--project-root requires a value"); continue; }
@@ -819,7 +833,7 @@ export async function runPlaybooksCli(args: string[], client: TaskCliClient): Pr
819
833
  case "create": {
820
834
  if (id) throw new Error("playbooks create accepts no positional arguments");
821
835
  if (!title) throw new Error("playbooks create requires --title");
822
- const artifact = await client.call<Record<string, unknown>, CliArtifact>("playbooks.create", { title, body, trigger, steps, tools, labels, extra, project_root: playbookProjectRoot });
836
+ const artifact = await client.call<Record<string, unknown>, CliArtifact>("playbooks.create", { title, body, trigger, steps, tools, labels, extra, arguments: playbookArguments, project_root: playbookProjectRoot });
823
837
  result = artifact;
824
838
  human = `Created playbook: ${artifactLabel(artifact)}`;
825
839
  break;
@@ -840,7 +854,7 @@ export async function runPlaybooksCli(args: string[], client: TaskCliClient): Pr
840
854
  }
841
855
  case "invoke": {
842
856
  if (!id || second) throw new Error("playbooks invoke requires exactly one playbook id");
843
- const invocation = await client.call<Record<string, unknown>, string>("playbooks.invoke", { id });
857
+ const invocation = await client.call<Record<string, unknown>, string>("playbooks.invoke", { id, arguments: playbookArguments });
844
858
  result = invocation;
845
859
  human = invocation;
846
860
  break;