@jyork0828/pi-pilot 0.0.1 → 0.0.2

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/dist/index.js CHANGED
@@ -486,6 +486,62 @@ import {
486
486
  SessionManager
487
487
  } from "@earendil-works/pi-coding-agent";
488
488
 
489
+ // src/extensions/plan/schema.ts
490
+ import { Type } from "typebox";
491
+ var planItemStatusSchema = Type.Union([
492
+ Type.Literal("pending"),
493
+ Type.Literal("in_progress"),
494
+ Type.Literal("completed")
495
+ ]);
496
+ var planItemSchema = Type.Object({
497
+ id: Type.String({ description: 'Short stable identifier for the item (kebab-case, e.g. "wire-factory").' }),
498
+ title: Type.String({ description: "One-line description of the step. Specific and verifiable." }),
499
+ status: planItemStatusSchema,
500
+ note: Type.Optional(Type.String({ description: "Optional short context \u2014 blocker, decision, or follow-up." }))
501
+ });
502
+ var updatePlanParamsSchema = Type.Object({
503
+ items: Type.Array(planItemSchema, {
504
+ description: "The full ordered plan. Always send the complete list; previous tool calls are not merged."
505
+ })
506
+ });
507
+
508
+ // src/extensions/plan/factory.ts
509
+ var planExtensionFactory = (pi) => {
510
+ pi.registerTool({
511
+ name: "update_plan",
512
+ label: "Plan",
513
+ description: "Publish or refresh the working plan for the current task. Use for any task that takes 3+ discrete steps. Always send the full ordered list; previous calls are replaced, not merged.",
514
+ parameters: updatePlanParamsSchema,
515
+ promptSnippet: "update_plan: maintain a live checklist for multi-step tasks; update statuses as you progress.",
516
+ promptGuidelines: [
517
+ "For tasks with 3+ discrete steps, call update_plan once with the full list before starting work.",
518
+ "After completing each step, call update_plan again with refreshed statuses, then continue immediately \u2014 do not pause the turn just because the plan was updated.",
519
+ 'Plan items should be specific and verifiable (e.g. "Add typebox dependency to packages/server"), not vague ("Set up infrastructure").',
520
+ "Exactly one item should be in_progress at a time. Mark completed only when the work is actually done."
521
+ ],
522
+ execute: async (_toolCallId, params) => ({
523
+ content: [
524
+ {
525
+ type: "text",
526
+ text: `Plan updated (${params.items.length} item${params.items.length === 1 ? "" : "s"}).`
527
+ }
528
+ ],
529
+ details: params
530
+ })
531
+ });
532
+ pi.registerCommand("plan", {
533
+ description: "Ask the agent to draft a plan for the current task.",
534
+ handler: async (args) => {
535
+ const task = args.trim();
536
+ const message = task ? `Draft a plan for: ${task}. Use the update_plan tool to publish it before starting any work.` : "Draft a plan for the current task. Use the update_plan tool to publish it before starting any work.";
537
+ pi.sendUserMessage(message);
538
+ }
539
+ });
540
+ };
541
+
542
+ // src/extensions/index.ts
543
+ var builtinExtensionFactories = [planExtensionFactory];
544
+
489
545
  // src/ws/extension-ui.ts
490
546
  var ExtensionUIBridge = class {
491
547
  /** Symmetric with the old bridge so workspace-manager's dispose path
@@ -576,7 +632,10 @@ var createRuntime = async ({
576
632
  }) => {
577
633
  const services = await createAgentSessionServices({
578
634
  cwd,
579
- resourceLoaderOptions: EXTENSIONS_ENABLED ? void 0 : { noExtensions: true }
635
+ resourceLoaderOptions: {
636
+ noExtensions: !EXTENSIONS_ENABLED,
637
+ extensionFactories: builtinExtensionFactories
638
+ }
580
639
  });
581
640
  const sessionResult = await createAgentSessionFromServices({
582
641
  services,
@@ -1265,6 +1324,17 @@ async function snapshot(workspaceId, roots, workspaceCwd) {
1265
1324
  const { skills } = loader.getSkills();
1266
1325
  const { prompts } = loader.getPrompts();
1267
1326
  const extResult = loader.getExtensions();
1327
+ const resolvedExtCommandsByPath = /* @__PURE__ */ new Map();
1328
+ const resolvedCommands = runtime.session.extensionRunner?.getRegisteredCommands() ?? [];
1329
+ for (const cmd of resolvedCommands) {
1330
+ const key = cmd.sourceInfo.path;
1331
+ let list = resolvedExtCommandsByPath.get(key);
1332
+ if (!list) {
1333
+ list = [];
1334
+ resolvedExtCommandsByPath.set(key, list);
1335
+ }
1336
+ list.push(cmd.invocationName);
1337
+ }
1268
1338
  const skillsOut = skills.map((s) => ({
1269
1339
  name: s.name,
1270
1340
  description: s.description,
@@ -1282,15 +1352,18 @@ async function snapshot(workspaceId, roots, workspaceCwd) {
1282
1352
  source: toResourceSource(p.sourceInfo),
1283
1353
  managed: scopeFor(p.filePath, roots) !== void 0
1284
1354
  }));
1285
- const extensionsOut = extResult.extensions.map((e) => ({
1286
- path: e.path,
1287
- resolvedPath: e.resolvedPath,
1288
- source: toResourceSource(e.sourceInfo),
1289
- tools: [...e.tools.keys()],
1290
- commands: [...e.commands.keys()],
1291
- flags: [...e.flags.keys()],
1292
- shortcuts: [...e.shortcuts.keys()]
1293
- }));
1355
+ const extensionsOut = extResult.extensions.map((e) => {
1356
+ const resolved = resolvedExtCommandsByPath.get(e.sourceInfo.path);
1357
+ return {
1358
+ path: e.path,
1359
+ resolvedPath: e.resolvedPath,
1360
+ source: toResourceSource(e.sourceInfo),
1361
+ tools: [...e.tools.keys()],
1362
+ commands: resolved ?? [...e.commands.keys()],
1363
+ flags: [...e.flags.keys()],
1364
+ shortcuts: [...e.shortcuts.keys()]
1365
+ };
1366
+ });
1294
1367
  const extensionErrors = extResult.errors.map((err) => ({
1295
1368
  path: err.path,
1296
1369
  error: err.error
@@ -1935,8 +2008,11 @@ function translatePiEvent(ev) {
1935
2008
  return { kind: "turn_start" };
1936
2009
  case "turn_end":
1937
2010
  return { kind: "turn_end" };
1938
- case "message_start":
1939
- return { kind: "message_start", role: roleOf(ev.message) };
2011
+ case "message_start": {
2012
+ const role = roleOf(ev.message);
2013
+ const text = role === "user" ? extractUserText2(ev.message) : void 0;
2014
+ return { kind: "message_start", role, text };
2015
+ }
1940
2016
  case "message_end":
1941
2017
  return { kind: "message_end", role: roleOf(ev.message) };
1942
2018
  case "message_update": {
@@ -2023,6 +2099,20 @@ function roleOf(message) {
2023
2099
  }
2024
2100
  return "assistant";
2025
2101
  }
2102
+ function extractUserText2(message) {
2103
+ if (!message || typeof message !== "object") return void 0;
2104
+ const content = message.content;
2105
+ if (typeof content === "string") return content;
2106
+ if (!Array.isArray(content)) return void 0;
2107
+ const parts = [];
2108
+ for (const block of content) {
2109
+ if (block && typeof block === "object" && block.type === "text") {
2110
+ const text = block.text;
2111
+ if (typeof text === "string") parts.push(text);
2112
+ }
2113
+ }
2114
+ return parts.length === 0 ? void 0 : parts.join("");
2115
+ }
2026
2116
  function extractText(result) {
2027
2117
  if (!result || typeof result !== "object") return void 0;
2028
2118
  const content = result.content;