@docyrus/docyrus 0.0.34 → 0.0.36

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 (66) hide show
  1. package/README.md +25 -0
  2. package/agent-loader.js +3 -2
  3. package/agent-loader.js.map +2 -2
  4. package/main.js +82162 -46093
  5. package/main.js.map +4 -4
  6. package/package.json +12 -3
  7. package/resources/chrome-tools/browser-content.js +46 -46
  8. package/resources/chrome-tools/browser-cookies.js +16 -16
  9. package/resources/chrome-tools/browser-eval.js +27 -27
  10. package/resources/chrome-tools/browser-hn-scraper.js +1 -1
  11. package/resources/chrome-tools/browser-nav.js +23 -23
  12. package/resources/chrome-tools/browser-pick.js +127 -127
  13. package/resources/chrome-tools/browser-screenshot.js +10 -10
  14. package/resources/chrome-tools/browser-start.js +38 -38
  15. package/resources/pi-agent/extensions/answer.ts +392 -384
  16. package/resources/pi-agent/extensions/context.ts +415 -415
  17. package/resources/pi-agent/extensions/control.ts +1287 -1287
  18. package/resources/pi-agent/extensions/diff.ts +171 -171
  19. package/resources/pi-agent/extensions/files.ts +155 -155
  20. package/resources/pi-agent/extensions/knowledge.ts +664 -0
  21. package/resources/pi-agent/extensions/loop.ts +375 -375
  22. package/resources/pi-agent/extensions/pi-bash-live-view/index.ts +1 -1
  23. package/resources/pi-agent/extensions/pi-bash-live-view/package.json +22 -22
  24. package/resources/pi-agent/extensions/pi-bash-live-view/pty-execute.ts +2 -2
  25. package/resources/pi-agent/extensions/pi-bash-live-view/pty-session.ts +2 -2
  26. package/resources/pi-agent/extensions/pi-bash-live-view/spawn-helper.ts +2 -2
  27. package/resources/pi-agent/extensions/pi-bash-live-view/terminal-emulator.ts +18 -18
  28. package/resources/pi-agent/extensions/pi-bash-live-view/truncate.ts +1 -1
  29. package/resources/pi-agent/extensions/pi-bash-live-view/widget.ts +4 -4
  30. package/resources/pi-agent/extensions/pi-custom-compaction/package.json +4 -4
  31. package/resources/pi-agent/extensions/pi-mcp-adapter/app-bridge.bundle.js +14 -14
  32. package/resources/pi-agent/extensions/pi-mcp-adapter/commands.ts +6 -6
  33. package/resources/pi-agent/extensions/pi-mcp-adapter/config.ts +9 -9
  34. package/resources/pi-agent/extensions/pi-mcp-adapter/consent-manager.ts +4 -4
  35. package/resources/pi-agent/extensions/pi-mcp-adapter/direct-tools.ts +13 -13
  36. package/resources/pi-agent/extensions/pi-mcp-adapter/glimpse-ui.ts +5 -5
  37. package/resources/pi-agent/extensions/pi-mcp-adapter/host-html-template.ts +13 -13
  38. package/resources/pi-agent/extensions/pi-mcp-adapter/index.ts +14 -14
  39. package/resources/pi-agent/extensions/pi-mcp-adapter/init.ts +17 -17
  40. package/resources/pi-agent/extensions/pi-mcp-adapter/lifecycle.ts +2 -2
  41. package/resources/pi-agent/extensions/pi-mcp-adapter/logger.ts +2 -2
  42. package/resources/pi-agent/extensions/pi-mcp-adapter/mcp-panel.ts +17 -17
  43. package/resources/pi-agent/extensions/pi-mcp-adapter/metadata-cache.ts +9 -9
  44. package/resources/pi-agent/extensions/pi-mcp-adapter/npx-resolver.ts +35 -35
  45. package/resources/pi-agent/extensions/pi-mcp-adapter/oauth-handler.ts +1 -1
  46. package/resources/pi-agent/extensions/pi-mcp-adapter/proxy-modes.ts +12 -12
  47. package/resources/pi-agent/extensions/pi-mcp-adapter/server-manager.ts +6 -6
  48. package/resources/pi-agent/extensions/pi-mcp-adapter/tool-metadata.ts +4 -4
  49. package/resources/pi-agent/extensions/pi-mcp-adapter/types.ts +2 -2
  50. package/resources/pi-agent/extensions/pi-mcp-adapter/ui-resource-handler.ts +6 -6
  51. package/resources/pi-agent/extensions/pi-mcp-adapter/ui-server.ts +17 -17
  52. package/resources/pi-agent/extensions/pi-mcp-adapter/ui-session.ts +22 -22
  53. package/resources/pi-agent/extensions/pi-mcp-adapter/utils.ts +2 -2
  54. package/resources/pi-agent/extensions/prompt-editor.ts +900 -900
  55. package/resources/pi-agent/extensions/prompt-url-widget.ts +122 -122
  56. package/resources/pi-agent/extensions/redraws.ts +14 -14
  57. package/resources/pi-agent/extensions/review.ts +1533 -1533
  58. package/resources/pi-agent/extensions/todos.ts +1735 -1735
  59. package/resources/pi-agent/extensions/tps.ts +40 -40
  60. package/resources/pi-agent/extensions/whimsical.ts +3 -3
  61. package/resources/pi-agent/prompts/agent-system.md +2 -0
  62. package/resources/pi-agent/prompts/coder-system.md +2 -0
  63. package/server-loader.js +82 -1
  64. package/server-loader.js.map +3 -3
  65. package/tui.mjs +2 -0
  66. package/tui.mjs.map +1 -1
@@ -2,46 +2,46 @@ import type { AssistantMessage } from "@mariozechner/pi-ai";
2
2
  import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
3
3
 
4
4
  function isAssistantMessage(message: unknown): message is AssistantMessage {
5
- if (!message || typeof message !== "object") return false;
6
- const role = (message as { role?: unknown }).role;
7
- return role === "assistant";
5
+ if (!message || typeof message !== "object") {return false;}
6
+ const role = (message as { role?: unknown }).role;
7
+ return role === "assistant";
8
8
  }
9
9
 
10
- export default function (pi: ExtensionAPI) {
11
- let agentStartMs: number | null = null;
12
-
13
- pi.on("agent_start", () => {
14
- agentStartMs = Date.now();
15
- });
16
-
17
- pi.on("agent_end", (event, ctx) => {
18
- if (!ctx.hasUI) return;
19
- if (agentStartMs === null) return;
20
-
21
- const elapsedMs = Date.now() - agentStartMs;
22
- agentStartMs = null;
23
- if (elapsedMs <= 0) return;
24
-
25
- let input = 0;
26
- let output = 0;
27
- let cacheRead = 0;
28
- let cacheWrite = 0;
29
- let totalTokens = 0;
30
-
31
- for (const message of event.messages) {
32
- if (!isAssistantMessage(message)) continue;
33
- input += message.usage.input || 0;
34
- output += message.usage.output || 0;
35
- cacheRead += message.usage.cacheRead || 0;
36
- cacheWrite += message.usage.cacheWrite || 0;
37
- totalTokens += message.usage.totalTokens || 0;
38
- }
39
-
40
- if (output <= 0) return;
41
-
42
- const elapsedSeconds = elapsedMs / 1000;
43
- const tokensPerSecond = output / elapsedSeconds;
44
- const message = `TPS ${tokensPerSecond.toFixed(1)} tok/s. out ${output.toLocaleString()}, in ${input.toLocaleString()}, cache r/w ${cacheRead.toLocaleString()}/${cacheWrite.toLocaleString()}, total ${totalTokens.toLocaleString()}, ${elapsedSeconds.toFixed(1)}s`;
45
- ctx.ui.notify(message, "info");
46
- });
10
+ export default function(pi: ExtensionAPI) {
11
+ let agentStartMs: number | null = null;
12
+
13
+ pi.on("agent_start", () => {
14
+ agentStartMs = Date.now();
15
+ });
16
+
17
+ pi.on("agent_end", (event, ctx) => {
18
+ if (!ctx.hasUI) {return;}
19
+ if (agentStartMs === null) {return;}
20
+
21
+ const elapsedMs = Date.now() - agentStartMs;
22
+ agentStartMs = null;
23
+ if (elapsedMs <= 0) {return;}
24
+
25
+ let input = 0;
26
+ let output = 0;
27
+ let cacheRead = 0;
28
+ let cacheWrite = 0;
29
+ let totalTokens = 0;
30
+
31
+ for (const message of event.messages) {
32
+ if (!isAssistantMessage(message)) {continue;}
33
+ input += message.usage.input || 0;
34
+ output += message.usage.output || 0;
35
+ cacheRead += message.usage.cacheRead || 0;
36
+ cacheWrite += message.usage.cacheWrite || 0;
37
+ totalTokens += message.usage.totalTokens || 0;
38
+ }
39
+
40
+ if (output <= 0) {return;}
41
+
42
+ const elapsedSeconds = elapsedMs / 1000;
43
+ const tokensPerSecond = output / elapsedSeconds;
44
+ const message = `TPS ${tokensPerSecond.toFixed(1)} tok/s. out ${output.toLocaleString()}, in ${input.toLocaleString()}, cache r/w ${cacheRead.toLocaleString()}/${cacheWrite.toLocaleString()}, total ${totalTokens.toLocaleString()}, ${elapsedSeconds.toFixed(1)}s`;
45
+ ctx.ui.notify(message, "info");
46
+ });
47
47
  }
@@ -463,12 +463,12 @@ function pickRandom(): string {
463
463
  return messages[Math.floor(Math.random() * messages.length)];
464
464
  }
465
465
 
466
- export default function (pi: ExtensionAPI) {
467
- pi.on("turn_start", async (_event, ctx) => {
466
+ export default function(pi: ExtensionAPI) {
467
+ pi.on("turn_start", async(_event, ctx) => {
468
468
  ctx.ui.setWorkingMessage(pickRandom());
469
469
  });
470
470
 
471
- pi.on("turn_end", async (_event, ctx) => {
471
+ pi.on("turn_end", async(_event, ctx) => {
472
472
  ctx.ui.setWorkingMessage(); // Reset for next time
473
473
  });
474
474
  }
@@ -7,6 +7,8 @@ Core behavior:
7
7
  - Prefer the local `docyrus` CLI for Docyrus operations instead of guessing undocumented HTTP endpoints.
8
8
  - When you need structured command output, prefer `--json`.
9
9
  - Start by inspecting real tenant state before making claims about apps, data sources, users, environments, auth state, or API shape.
10
+ - If the repository contains `docyrus/knowledge/`, use `docyrus knowledge search`, `docyrus knowledge section`, and `docyrus knowledge expand` before broader repo exploration.
11
+ - When `docyrus/knowledge/` exists, keep it updated and finish local work with `docyrus knowledge check`.
10
12
  - Use the installed Docyrus skills as your command and workflow reference.
11
13
  - Be careful with tenant-scoped mutations. Confirm real identifiers and current context before changing state.
12
14
  - Treat auth files, tokens, and `.docyrus` contents as sensitive.
@@ -18,6 +18,8 @@ Core behavior:
18
18
 
19
19
  - Use repository files and coding tools for implementation work.
20
20
  - Use the local `docyrus` CLI for Docyrus platform state, tenant context, schema inspection, app and data-source operations, API discovery, and data verification.
21
+ - If the repository contains `docyrus/knowledge/`, use `docyrus knowledge search`, `docyrus knowledge section`, and `docyrus knowledge expand` before coding so you start from documented repo intent rather than only source inspection.
22
+ - When `docyrus/knowledge/` exists, keep it in sync with behavior changes and finish with `docyrus knowledge check`.
21
23
  - Prefer `--json` whenever command output needs to be parsed, compared, or fed back into reasoning.
22
24
  - Start from real state before making claims about apps, data sources, users, fields, enums, environments, auth state, API shape, or deployment context.
23
25
  - Distinguish clearly between local code changes and remote Docyrus platform mutations.
package/server-loader.js CHANGED
@@ -723,6 +723,7 @@ var AgentEnvStore = class {
723
723
  constructor(filePath) {
724
724
  this.filePath = filePath;
725
725
  }
726
+ filePath;
726
727
  getFilePath() {
727
728
  return this.filePath;
728
729
  }
@@ -4059,6 +4060,9 @@ function validateProviderLoginInput(params) {
4059
4060
  if (field.required && !normalized) {
4060
4061
  return { ok: false, error: `Missing required field: ${field.name}` };
4061
4062
  }
4063
+ if (normalized && field.options && !field.options.some((option) => option.value === normalized)) {
4064
+ return { ok: false, error: `Invalid value for ${field.name}: ${normalized}` };
4065
+ }
4062
4066
  if (normalized) {
4063
4067
  values[field.name] = normalized;
4064
4068
  } else if (field.defaultValue) {
@@ -6521,6 +6525,60 @@ function parseServerLoaderRequest(payload) {
6521
6525
  return JSON.parse(payload);
6522
6526
  }
6523
6527
 
6528
+ // src/server/restrictedModelRegistry.ts
6529
+ var SERVER_MODE_ALLOWED_MODEL_IDS_BY_PROVIDER = {
6530
+ anthropic: [
6531
+ "claude-opus-4-6",
6532
+ "claude-sonnet-4-6",
6533
+ "claude-haiku-4-5"
6534
+ ],
6535
+ openai: [
6536
+ "gpt-5.4",
6537
+ "gpt-5.4-mini",
6538
+ "gpt-5.4-nano"
6539
+ ],
6540
+ "azure-openai-responses": [
6541
+ "gpt-5.4",
6542
+ "gpt-5.4-mini",
6543
+ "gpt-5.4-nano"
6544
+ ]
6545
+ };
6546
+ var ALLOWED_MODEL_IDS_BY_PROVIDER = Object.fromEntries(
6547
+ Object.entries(SERVER_MODE_ALLOWED_MODEL_IDS_BY_PROVIDER).map(([provider, modelIds]) => [provider, new Set(modelIds)])
6548
+ );
6549
+ function isServerSelectableModel(model) {
6550
+ const allowedModelIds = ALLOWED_MODEL_IDS_BY_PROVIDER[model.provider];
6551
+ if (!allowedModelIds) {
6552
+ return true;
6553
+ }
6554
+ return allowedModelIds.has(model.id);
6555
+ }
6556
+ function filterModels(models) {
6557
+ return models.filter((model) => isServerSelectableModel(model));
6558
+ }
6559
+ function createServerRestrictedModelRegistry(modelRegistry) {
6560
+ return new Proxy(modelRegistry, {
6561
+ get(target, property, receiver) {
6562
+ if (property === "getAll") {
6563
+ return () => filterModels(target.getAll());
6564
+ }
6565
+ if (property === "getAvailable") {
6566
+ return () => filterModels(target.getAvailable());
6567
+ }
6568
+ if (property === "find") {
6569
+ return (provider, modelId) => {
6570
+ if (!isServerSelectableModel({ provider, id: modelId })) {
6571
+ return void 0;
6572
+ }
6573
+ return target.find(provider, modelId);
6574
+ };
6575
+ }
6576
+ const value = Reflect.get(target, property, receiver);
6577
+ return typeof value === "function" ? value.bind(target) : value;
6578
+ }
6579
+ });
6580
+ }
6581
+
6524
6582
  // src/services/spinner.ts
6525
6583
  var import_picocolors = __toESM(require_picocolors());
6526
6584
  var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
@@ -6679,6 +6737,17 @@ function createServerSessionAdapter(params) {
6679
6737
  }
6680
6738
  };
6681
6739
  }
6740
+ async function ensureServerSelectableSessionModel(params) {
6741
+ const availableModels = params.modelRegistry.getAvailable();
6742
+ if (availableModels.length === 0) {
6743
+ return;
6744
+ }
6745
+ const currentModel = params.session.model;
6746
+ const currentModelIsSelectable = currentModel ? availableModels.some((model) => model.provider === currentModel.provider && model.id === currentModel.id) : false;
6747
+ if (!currentModelIsSelectable) {
6748
+ await params.session.setModel(availableModels[0]);
6749
+ }
6750
+ }
6682
6751
  async function main() {
6683
6752
  const request = readLoaderRequest();
6684
6753
  const pi = await loadPiExports();
@@ -6697,7 +6766,7 @@ async function main() {
6697
6766
  const authStorage = pi.AuthStorage.create((0, import_node_path7.join)(agentDir, "auth.json"));
6698
6767
  const settingsManager = pi.SettingsManager.create(cwd, agentDir);
6699
6768
  const modelsJsonPath = (0, import_node_path7.join)(agentDir, "models.json");
6700
- const modelRegistry = new pi.ModelRegistry(authStorage, modelsJsonPath);
6769
+ const modelRegistry = createServerRestrictedModelRegistry(pi.ModelRegistry.create(authStorage, modelsJsonPath));
6701
6770
  const quietStartup = !request.verbose;
6702
6771
  if (quietStartup) {
6703
6772
  process.env.PI_SKIP_VERSION_CHECK = "1";
@@ -6752,6 +6821,10 @@ async function main() {
6752
6821
  if (hasPackagedMcpAdapter) {
6753
6822
  extensionsResult.runtime.flagValues.set("mcp-config", mcpConfigPath);
6754
6823
  }
6824
+ await ensureServerSelectableSessionModel({
6825
+ session,
6826
+ modelRegistry
6827
+ });
6755
6828
  spinner.stop();
6756
6829
  if (!session.model) {
6757
6830
  throw new Error(
@@ -6799,6 +6872,10 @@ Or create ${modelsJsonPath}`
6799
6872
  model: requestedModel,
6800
6873
  thinkingLevel: request.thinking
6801
6874
  });
6875
+ await ensureServerSelectableSessionModel({
6876
+ session: freshSession,
6877
+ modelRegistry
6878
+ });
6802
6879
  return createServerSessionAdapter({
6803
6880
  session: freshSession,
6804
6881
  extensionsResult: freshExtensionsResult
@@ -6827,6 +6904,10 @@ Or create ${modelsJsonPath}`
6827
6904
  model: requestedModel,
6828
6905
  thinkingLevel: request.thinking
6829
6906
  });
6907
+ await ensureServerSelectableSessionModel({
6908
+ session: resumedSession,
6909
+ modelRegistry
6910
+ });
6830
6911
  return createServerSessionAdapter({
6831
6912
  session: resumedSession,
6832
6913
  extensionsResult: resumedExtensionsResult