@docyrus/docyrus 0.0.40 → 0.0.42

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.
Files changed (31) hide show
  1. package/README.md +7 -0
  2. package/main.js +3708 -1173
  3. package/main.js.map +4 -4
  4. package/package.json +8 -7
  5. package/resources/pi-agent/extensions/control.ts +0 -8
  6. package/resources/pi-agent/extensions/knowledge.ts +0 -7
  7. package/resources/pi-agent/extensions/loop.ts +1 -5
  8. package/resources/pi-agent/extensions/pi-bash-live-view/package.json +1 -1
  9. package/resources/pi-agent/extensions/pi-custom-compaction/events/register-events.ts +0 -10
  10. package/resources/pi-agent/extensions/pi-custom-compaction/package.json +4 -4
  11. package/resources/pi-agent/extensions/plan.ts +95 -4
  12. package/resources/pi-agent/extensions/prompt-editor.ts +0 -18
  13. package/resources/pi-agent/extensions/prompt-url-widget.ts +0 -4
  14. package/resources/pi-agent/extensions/review.ts +0 -4
  15. package/resources/pi-agent/extensions/tasks.ts +497 -0
  16. package/resources/pi-agent/extensions/todos.ts +102 -2
  17. package/resources/pi-agent/skills/agent-browser/SKILL.md +779 -0
  18. package/resources/pi-agent/skills/agent-browser/references/authentication.md +303 -0
  19. package/resources/pi-agent/skills/agent-browser/references/commands.md +295 -0
  20. package/resources/pi-agent/skills/agent-browser/references/profiling.md +120 -0
  21. package/resources/pi-agent/skills/agent-browser/references/proxy-support.md +194 -0
  22. package/resources/pi-agent/skills/agent-browser/references/session-management.md +193 -0
  23. package/resources/pi-agent/skills/agent-browser/references/snapshot-refs.md +219 -0
  24. package/resources/pi-agent/skills/agent-browser/references/video-recording.md +173 -0
  25. package/resources/pi-agent/skills/agent-browser/templates/authenticated-session.sh +105 -0
  26. package/resources/pi-agent/skills/agent-browser/templates/capture-workflow.sh +69 -0
  27. package/resources/pi-agent/skills/agent-browser/templates/form-automation.sh +62 -0
  28. package/resources/pi-agent/skills/docyrus-platform/references/docyrus-cli-usage.md +73 -0
  29. package/resources/pi-agent/skills/grill-me/SKILL.md +109 -0
  30. package/server-loader.js +24270 -3381
  31. package/server-loader.js.map +4 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docyrus/docyrus",
3
- "version": "0.0.40",
3
+ "version": "0.0.42",
4
4
  "private": false,
5
5
  "description": "Docyrus API CLI",
6
6
  "main": "./main.js",
@@ -12,9 +12,9 @@
12
12
  },
13
13
  "dependencies": {
14
14
  "@clack/prompts": "^0.11.0",
15
- "@hono/node-server": "^1.14.1",
16
- "@mariozechner/pi-ai": "0.64.0",
17
- "@mariozechner/pi-coding-agent": "0.64.0",
15
+ "@hono/node-server": "^1.19.13",
16
+ "@mariozechner/pi-ai": "0.65.0",
17
+ "@mariozechner/pi-coding-agent": "0.65.0",
18
18
  "@modelcontextprotocol/ext-apps": "^1.2.2",
19
19
  "@modelcontextprotocol/sdk": "^1.25.1",
20
20
  "@mozilla/readability": "^0.6.0",
@@ -23,8 +23,8 @@
23
23
  "@repomix/tree-sitter-wasms": "^0.1.16",
24
24
  "@sinclair/typebox": "^0.34.48",
25
25
  "@xterm/headless": "^5.5.0",
26
- "diff": "^8.0.2",
27
- "hono": "^4.7.10",
26
+ "diff": "^8.0.4",
27
+ "hono": "^4.12.12",
28
28
  "ignore-walk": "^8.0.0",
29
29
  "incur": "^0.1.6",
30
30
  "jsdom": "^29.0.1",
@@ -40,13 +40,14 @@
40
40
  "strip-ansi": "^7.1.0",
41
41
  "turndown": "^7.2.2",
42
42
  "turndown-plugin-gfm": "^1.0.2",
43
- "undici": "^7.16.0",
43
+ "undici": "^7.24.0",
44
44
  "unified": "^11.0.5",
45
45
  "unist-util-visit": "^5.1.0",
46
46
  "web-tree-sitter": "0.25.10",
47
47
  "zod": "^4.3.6"
48
48
  },
49
49
  "devDependencies": {
50
+ "@types/node": "^24.12.2",
50
51
  "@types/react": "^19.1.13"
51
52
  },
52
53
  "engines": {
@@ -1087,14 +1087,6 @@ export default function(pi: ExtensionAPI) {
1087
1087
  }
1088
1088
  });
1089
1089
 
1090
- pi.on("session_switch", async(_event, ctx) => {
1091
- await refreshServer(ctx);
1092
- });
1093
-
1094
- pi.on("session_fork", async(_event, ctx) => {
1095
- await refreshServer(ctx);
1096
- });
1097
-
1098
1090
  pi.on("session_shutdown", async() => {
1099
1091
  if (state.aliasTimer) {
1100
1092
  clearInterval(state.aliasTimer);
@@ -621,13 +621,6 @@ export default function(pi: ExtensionAPI) {
621
621
  });
622
622
  });
623
623
 
624
- pi.on("session_switch", async(_event, ctx) => {
625
- await refreshKnowledgeState(pi, ctx, {
626
- runCheck: false,
627
- allowReminder: true,
628
- });
629
- });
630
-
631
624
  pi.on("turn_end", async(_event: TurnEndEvent, ctx) => {
632
625
  await refreshKnowledgeState(pi, ctx, {
633
626
  runCheck: false,
@@ -8,7 +8,7 @@
8
8
 
9
9
  import { Type } from "@sinclair/typebox";
10
10
  import { complete, type Api, type Model, type UserMessage } from "@mariozechner/pi-ai";
11
- import type { ExtensionAPI, ExtensionContext, SessionSwitchEvent } from "@mariozechner/pi-coding-agent";
11
+ import type { ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent";
12
12
  import { compact } from "@mariozechner/pi-coding-agent";
13
13
  import { Container, type SelectItem, SelectList, Text } from "@mariozechner/pi-tui";
14
14
  import { DynamicBorder } from "@mariozechner/pi-coding-agent";
@@ -439,8 +439,4 @@ export default function loopExtension(pi: ExtensionAPI): void {
439
439
  pi.on("session_start", async(_event, ctx) => {
440
440
  await restoreLoopState(ctx);
441
441
  });
442
-
443
- pi.on("session_switch", async(_event: SessionSwitchEvent, ctx) => {
444
- await restoreLoopState(ctx);
445
- });
446
442
  }
@@ -40,7 +40,7 @@
40
40
  "test": "node --test tests/*.test.mjs"
41
41
  },
42
42
  "dependencies": {
43
- "@mariozechner/pi-coding-agent": "^0.64.0",
43
+ "@mariozechner/pi-coding-agent": "^0.65.0",
44
44
  "@sinclair/typebox": "^0.34.38",
45
45
  "@xterm/headless": "^5.5.0",
46
46
  "node-pty": "^1.0.0",
@@ -208,16 +208,6 @@ export function registerEvents(pi: ExtensionAPI, runtime: IRuntimeServices): voi
208
208
  initializeSessionStatus(ctx, runtime);
209
209
  });
210
210
 
211
- pi.on("session_switch", async(_event, ctx) => {
212
- runtime.clearSessionScopedState(ctx);
213
- initializeSessionStatus(ctx, runtime);
214
- });
215
-
216
- pi.on("session_fork", async(_event, ctx) => {
217
- runtime.clearSessionScopedState(ctx);
218
- initializeSessionStatus(ctx, runtime);
219
- });
220
-
221
211
  pi.on("session_tree", async(_event, ctx) => {
222
212
  runtime.clearSessionScopedState(ctx);
223
213
  initializeSessionStatus(ctx, runtime);
@@ -43,10 +43,10 @@
43
43
  "test": "tsx --test test/**/*.test.ts"
44
44
  },
45
45
  "devDependencies": {
46
- "@mariozechner/pi-agent-core": "^0.64.0",
47
- "@mariozechner/pi-ai": "^0.64.0",
48
- "@mariozechner/pi-coding-agent": "^0.64.0",
49
- "@mariozechner/pi-tui": "^0.64.0",
46
+ "@mariozechner/pi-agent-core": "^0.65.0",
47
+ "@mariozechner/pi-ai": "^0.65.0",
48
+ "@mariozechner/pi-coding-agent": "^0.65.0",
49
+ "@mariozechner/pi-tui": "^0.65.0",
50
50
  "tsx": "^4.20.5"
51
51
  },
52
52
  "pi": {
@@ -28,6 +28,7 @@ const PLAN_ANCHOR_TYPE = "plan-anchor";
28
28
  const PLAN_CONFIG_FILE = ".pi/plan-policy.json";
29
29
  const PLAN_WIDGET_KEY = "plan-mode";
30
30
  const PLAN_BRANCH_LABEL = "plan";
31
+ const ARCHITECT_PLAN_ARTIFACT_FILE_NAME = "PLAN.md";
31
32
  const ALLOWED_TODO_ACTIONS = new Set(["list", "list-all", "get"]);
32
33
  const ALL_THINKING_LEVELS = new Set(["off", "minimal", "low", "medium", "high", "xhigh"] satisfies ThinkingLevel[]);
33
34
 
@@ -96,6 +97,12 @@ export interface IReadPlanPolicyResult {
96
97
  error?: string;
97
98
  }
98
99
 
100
+ interface IPlanningCliEnvironment {
101
+ executable: string;
102
+ entryPath: string;
103
+ scope: "local" | "global";
104
+ }
105
+
99
106
  export type IParseResult<T> = { ok: true; value: T } | { ok: false; error: string };
100
107
 
101
108
  let currentPlanState: IPlanSessionState | undefined;
@@ -120,6 +127,41 @@ function expandUserPath(inputPath: string): string {
120
127
  return inputPath;
121
128
  }
122
129
 
130
+ function readPlanningCliEnvironment(env: NodeJS.ProcessEnv = process.env): IPlanningCliEnvironment {
131
+ const executable = env.DOCYRUS_CLI_EXECUTABLE?.trim();
132
+ const entryPath = env.DOCYRUS_CLI_ENTRY?.trim();
133
+ const scope = env.DOCYRUS_CLI_SCOPE?.trim() as "local" | "global" | undefined;
134
+ if (!executable || !entryPath || (scope !== "local" && scope !== "global")) {
135
+ throw new Error("Missing Docyrus CLI runtime env. Expected DOCYRUS_CLI_EXECUTABLE, DOCYRUS_CLI_ENTRY, and DOCYRUS_CLI_SCOPE.");
136
+ }
137
+
138
+ return {
139
+ executable,
140
+ entryPath,
141
+ scope,
142
+ };
143
+ }
144
+
145
+ async function runProjectPlanCliJson<TValue>(
146
+ pi: ExtensionAPI,
147
+ ctx: ExtensionContext,
148
+ args: string[],
149
+ ): Promise<TValue> {
150
+ const environment = readPlanningCliEnvironment();
151
+ const scopedArgs = environment.scope === "global" ? ["-g", ...args] : args;
152
+ const result = await pi.exec(environment.executable, [environment.entryPath, ...scopedArgs, "--json"], {
153
+ cwd: ctx.cwd,
154
+ });
155
+ const stdout = result.stdout?.toString().trim() || "";
156
+ const stderr = result.stderr?.toString().trim() || "";
157
+ const output = stdout || stderr;
158
+ if (result.code !== 0 || !output) {
159
+ throw new Error(output || `Command exited with code ${result.code ?? "unknown"}.`);
160
+ }
161
+
162
+ return JSON.parse(output) as TValue;
163
+ }
164
+
123
165
  function resolveAgentRootPath(): string {
124
166
  const agentDir = process.env.PI_CODING_AGENT_DIR?.trim();
125
167
  return agentDir && agentDir.length > 0 ? expandUserPath(agentDir) : path.join(os.homedir(), ".pi", "agent");
@@ -635,6 +677,28 @@ async function writePlanArtifactFromEvent(event: AgentEndEvent, ctx: ExtensionCo
635
677
  }
636
678
  }
637
679
 
680
+ async function writeArchitectArtifactFromEvent(event: AgentEndEvent, ctx: ExtensionContext): Promise<void> {
681
+ const state = getPlanState(ctx);
682
+ if (!state?.active || !state.artifactPath || state.mode !== "architect") {
683
+ return;
684
+ }
685
+
686
+ const text = extractLastAssistantText(event.messages ?? []);
687
+ if (!text || parseAskUserRequestFromText(text)) {
688
+ return;
689
+ }
690
+
691
+ try {
692
+ await fs.mkdir(state.artifactPath, { recursive: true });
693
+ await fs.writeFile(path.join(state.artifactPath, ARCHITECT_PLAN_ARTIFACT_FILE_NAME), `${text.trim()}\n`, "utf8");
694
+ } catch (error) {
695
+ if (ctx.hasUI) {
696
+ const message = error instanceof Error ? error.message : String(error);
697
+ ctx.ui.notify(`Failed to write architect plan artifact: ${message}`, "error");
698
+ }
699
+ }
700
+ }
701
+
638
702
  export function shouldBlockTodoAction(action: string | undefined): boolean {
639
703
  return !!action && !ALLOWED_TODO_ACTIONS.has(action);
640
704
  }
@@ -973,6 +1037,36 @@ export async function endPlanningWorkflow(pi: ExtensionAPI, ctx: ExtensionComman
973
1037
  setPlanWidget(ctx, undefined);
974
1038
  await restoreSourceModel(pi, ctx, state);
975
1039
 
1040
+ if (state.artifactPath) {
1041
+ try {
1042
+ const syncResult = state.mode === "architect"
1043
+ ? await runProjectPlanCliJson<{ updatedTaskIds?: string[] }>(pi, ctx, [
1044
+ "project-plan",
1045
+ "upsert-from-architect",
1046
+ "--artifactDir",
1047
+ state.artifactPath,
1048
+ ...(state.task ? ["--brief", state.task] : []),
1049
+ ])
1050
+ : await runProjectPlanCliJson<{ updatedTaskIds?: string[] }>(pi, ctx, [
1051
+ "project-plan",
1052
+ "upsert-from-plan",
1053
+ "--artifactPath",
1054
+ state.artifactPath,
1055
+ ...(state.task ? ["--task", state.task] : []),
1056
+ ]);
1057
+
1058
+ if (ctx.hasUI) {
1059
+ const updatedCount = Array.isArray(syncResult.updatedTaskIds) ? syncResult.updatedTaskIds.length : 0;
1060
+ ctx.ui.notify(`Project plan synced from ${state.mode} artifact (${updatedCount} task update${updatedCount === 1 ? "" : "s"}).`, "info");
1061
+ }
1062
+ } catch (error) {
1063
+ if (ctx.hasUI) {
1064
+ const message = error instanceof Error ? error.message : String(error);
1065
+ ctx.ui.notify(`Project plan sync failed after ${state.mode}: ${message}`, "warning");
1066
+ }
1067
+ }
1068
+ }
1069
+
976
1070
  if (ctx.hasUI) {
977
1071
  const artifactSuffix = state.artifactPath ? ` Artifact: ${state.artifactPath}` : "";
978
1072
  ctx.ui.notify(`Planning session ended.${artifactSuffix}`, "info");
@@ -1176,16 +1270,13 @@ export default function planExtension(pi: ExtensionAPI) {
1176
1270
  }
1177
1271
 
1178
1272
  await writePlanArtifactFromEvent(event, ctx);
1273
+ await writeArchitectArtifactFromEvent(event, ctx);
1179
1274
  });
1180
1275
 
1181
1276
  pi.on("session_start", async(_event, ctx) => {
1182
1277
  await syncPlanState(pi, ctx);
1183
1278
  });
1184
1279
 
1185
- pi.on("session_switch", async(_event, ctx) => {
1186
- await syncPlanState(pi, ctx);
1187
- });
1188
-
1189
1280
  pi.on("session_tree", async(_event, ctx) => {
1190
1281
  await syncPlanState(pi, ctx);
1191
1282
  });
@@ -1267,24 +1267,6 @@ export default function(pi: ExtensionAPI) {
1267
1267
  applyEditor(pi, ctx);
1268
1268
  });
1269
1269
 
1270
- pi.on("session_switch", async(_event, ctx) => {
1271
- lastObservedModel = { provider: ctx.model?.provider, modelId: ctx.model?.id };
1272
- await ensureRuntime(pi, ctx);
1273
- customOverlay = null;
1274
-
1275
- const inferred = inferModeFromSelection(ctx, pi, runtime.data);
1276
- if (inferred) {
1277
- runtime.currentMode = inferred;
1278
- runtime.lastRealMode = inferred;
1279
- } else {
1280
- runtime.currentMode = CUSTOM_MODE_NAME;
1281
- customOverlay = getCurrentSelectionSpec(pi, ctx);
1282
- }
1283
-
1284
- applyEditor(pi, ctx);
1285
- });
1286
-
1287
-
1288
1270
  pi.on("model_select", async(event: ModelSelectEvent, ctx) => {
1289
1271
  // Always track the last observed model for overlay/store correctness.
1290
1272
  lastObservedModel = { provider: event.model.provider, modelId: event.model.id };
@@ -108,10 +108,6 @@ export default function promptUrlWidgetExtension(pi: ExtensionAPI) {
108
108
  });
109
109
  });
110
110
 
111
- pi.on("session_switch", async(_event, ctx) => {
112
- rebuildFromSession(ctx);
113
- });
114
-
115
111
  const getUserText = (content: string | { type: string; text?: string }[] | undefined): string => {
116
112
  if (!content) {return "";}
117
113
  if (typeof content === "string") {return content;}
@@ -938,10 +938,6 @@ export default function reviewExtension(pi: ExtensionAPI) {
938
938
  applyAllReviewState(ctx);
939
939
  });
940
940
 
941
- pi.on("session_switch", (_event, ctx) => {
942
- applyAllReviewState(ctx);
943
- });
944
-
945
941
  pi.on("session_tree", (_event, ctx) => {
946
942
  applyAllReviewState(ctx);
947
943
  });