psyclaw 0.25.1 → 0.26.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.
Files changed (271) hide show
  1. package/README.md +111 -60
  2. package/{apps → dist/apps}/panel/index.html +50 -28
  3. package/dist/src/adapters/pi/extension.d.ts +19 -0
  4. package/dist/src/adapters/pi/extension.js +735 -0
  5. package/dist/src/adapters/pi/extension.js.map +1 -0
  6. package/dist/src/adapters/pi/model.d.ts +72 -0
  7. package/dist/src/adapters/pi/model.js +152 -0
  8. package/dist/src/adapters/pi/model.js.map +1 -0
  9. package/dist/src/adapters/pi/resources.d.ts +23 -0
  10. package/dist/src/adapters/pi/resources.js +54 -0
  11. package/dist/src/adapters/pi/resources.js.map +1 -0
  12. package/dist/src/adapters/pi/rpc.d.ts +58 -0
  13. package/dist/src/adapters/pi/rpc.js +253 -0
  14. package/dist/src/adapters/pi/rpc.js.map +1 -0
  15. package/dist/src/adapters/pi/session.d.ts +30 -0
  16. package/dist/src/adapters/pi/session.js +64 -0
  17. package/dist/src/adapters/pi/session.js.map +1 -0
  18. package/dist/src/agents/catalog.d.ts +30 -0
  19. package/dist/src/agents/catalog.js +118 -0
  20. package/dist/src/agents/catalog.js.map +1 -0
  21. package/dist/src/agents/discover.d.ts +28 -0
  22. package/dist/src/agents/discover.js +127 -0
  23. package/dist/src/agents/discover.js.map +1 -0
  24. package/dist/src/agents/import.d.ts +67 -0
  25. package/dist/src/agents/import.js +789 -0
  26. package/dist/src/agents/import.js.map +1 -0
  27. package/dist/src/analysis/hooks.d.ts +81 -0
  28. package/dist/src/analysis/hooks.js +139 -0
  29. package/dist/src/analysis/hooks.js.map +1 -0
  30. package/dist/src/analysis/pre-registration.d.ts +18 -0
  31. package/dist/src/analysis/pre-registration.js +86 -0
  32. package/dist/src/analysis/pre-registration.js.map +1 -0
  33. package/dist/src/branding.d.ts +44 -0
  34. package/dist/src/branding.js +128 -0
  35. package/dist/src/branding.js.map +1 -0
  36. package/dist/src/chat.d.ts +16 -0
  37. package/dist/src/chat.js +95 -0
  38. package/dist/src/chat.js.map +1 -0
  39. package/dist/src/cli.d.ts +2 -0
  40. package/dist/src/cli.js +316 -0
  41. package/dist/src/cli.js.map +1 -0
  42. package/dist/src/core/citations.d.ts +44 -0
  43. package/dist/src/core/citations.js +48 -0
  44. package/dist/src/core/citations.js.map +1 -0
  45. package/dist/src/core/contracts.d.ts +119 -0
  46. package/dist/src/core/contracts.js +2 -0
  47. package/dist/src/core/contracts.js.map +1 -0
  48. package/dist/src/core/docx.d.ts +11 -0
  49. package/dist/src/core/docx.js +46 -0
  50. package/dist/src/core/docx.js.map +1 -0
  51. package/dist/src/core/doi.d.ts +41 -0
  52. package/dist/src/core/doi.js +82 -0
  53. package/dist/src/core/doi.js.map +1 -0
  54. package/dist/src/core/evidence-policy.d.ts +24 -0
  55. package/dist/src/core/evidence-policy.js +308 -0
  56. package/dist/src/core/evidence-policy.js.map +1 -0
  57. package/dist/src/core/filekind.d.ts +15 -0
  58. package/dist/src/core/filekind.js +82 -0
  59. package/dist/src/core/filekind.js.map +1 -0
  60. package/dist/src/core/hash.d.ts +2 -0
  61. package/dist/src/core/hash.js +17 -0
  62. package/dist/src/core/hash.js.map +1 -0
  63. package/dist/src/core/pricing.d.ts +38 -0
  64. package/dist/src/core/pricing.js +110 -0
  65. package/dist/src/core/pricing.js.map +1 -0
  66. package/dist/src/core/redact.d.ts +12 -0
  67. package/dist/src/core/redact.js +48 -0
  68. package/dist/src/core/redact.js.map +1 -0
  69. package/dist/src/core/references.d.ts +55 -0
  70. package/dist/src/core/references.js +102 -0
  71. package/dist/src/core/references.js.map +1 -0
  72. package/dist/src/core/schemas.d.ts +162 -0
  73. package/dist/src/core/schemas.js +160 -0
  74. package/dist/src/core/schemas.js.map +1 -0
  75. package/dist/src/extension.d.ts +1 -0
  76. package/dist/src/extension.js +2 -0
  77. package/dist/src/extension.js.map +1 -0
  78. package/dist/src/index.d.ts +72 -0
  79. package/dist/src/index.js +73 -0
  80. package/dist/src/index.js.map +1 -0
  81. package/dist/src/install/installer.d.ts +147 -0
  82. package/dist/src/install/installer.js +721 -0
  83. package/dist/src/install/installer.js.map +1 -0
  84. package/dist/src/integrations/contracts.d.ts +35 -0
  85. package/dist/src/integrations/contracts.js +27 -0
  86. package/dist/src/integrations/contracts.js.map +1 -0
  87. package/dist/src/integrations/mcp.d.ts +155 -0
  88. package/dist/src/integrations/mcp.js +826 -0
  89. package/dist/src/integrations/mcp.js.map +1 -0
  90. package/dist/src/knowledge-map/contracts.d.ts +20 -0
  91. package/dist/src/knowledge-map/contracts.js +2 -0
  92. package/dist/src/knowledge-map/contracts.js.map +1 -0
  93. package/dist/src/knowledge-map/index.d.ts +4 -0
  94. package/dist/src/knowledge-map/index.js +39 -0
  95. package/dist/src/knowledge-map/index.js.map +1 -0
  96. package/dist/src/literature/contracts.d.ts +106 -0
  97. package/dist/src/literature/contracts.js +2 -0
  98. package/dist/src/literature/contracts.js.map +1 -0
  99. package/dist/src/literature/fulltext.d.ts +7 -0
  100. package/dist/src/literature/fulltext.js +24 -0
  101. package/dist/src/literature/fulltext.js.map +1 -0
  102. package/dist/src/literature/knowledge-map.d.ts +2 -0
  103. package/dist/src/literature/knowledge-map.js +20 -0
  104. package/dist/src/literature/knowledge-map.js.map +1 -0
  105. package/dist/src/literature/ledger.d.ts +3 -0
  106. package/dist/src/literature/ledger.js +17 -0
  107. package/dist/src/literature/ledger.js.map +1 -0
  108. package/dist/src/literature/metadata.d.ts +6 -0
  109. package/dist/src/literature/metadata.js +32 -0
  110. package/dist/src/literature/metadata.js.map +1 -0
  111. package/dist/src/memory/store.d.ts +22 -0
  112. package/dist/src/memory/store.js +73 -0
  113. package/dist/src/memory/store.js.map +1 -0
  114. package/dist/src/orchestration/contracts.d.ts +61 -0
  115. package/dist/src/orchestration/contracts.js +2 -0
  116. package/dist/src/orchestration/contracts.js.map +1 -0
  117. package/dist/src/orchestration/pi-executor.d.ts +28 -0
  118. package/dist/src/orchestration/pi-executor.js +169 -0
  119. package/dist/src/orchestration/pi-executor.js.map +1 -0
  120. package/dist/src/orchestration/runner.d.ts +196 -0
  121. package/dist/src/orchestration/runner.js +991 -0
  122. package/dist/src/orchestration/runner.js.map +1 -0
  123. package/dist/src/orchestration/scheduler.d.ts +8 -0
  124. package/dist/src/orchestration/scheduler.js +335 -0
  125. package/dist/src/orchestration/scheduler.js.map +1 -0
  126. package/dist/src/panel/events.d.ts +20 -0
  127. package/dist/src/panel/events.js +93 -0
  128. package/dist/src/panel/events.js.map +1 -0
  129. package/dist/src/panel/extension.d.ts +8 -0
  130. package/dist/src/panel/extension.js +115 -0
  131. package/dist/src/panel/extension.js.map +1 -0
  132. package/dist/src/panel/literature-map.d.ts +26 -0
  133. package/dist/src/panel/literature-map.js +34 -0
  134. package/dist/src/panel/literature-map.js.map +1 -0
  135. package/dist/src/panel/projection.d.ts +51 -0
  136. package/dist/src/panel/projection.js +288 -0
  137. package/dist/src/panel/projection.js.map +1 -0
  138. package/dist/src/panel/server.d.ts +46 -0
  139. package/dist/src/panel/server.js +1610 -0
  140. package/dist/src/panel/server.js.map +1 -0
  141. package/dist/src/panel/usage.d.ts +53 -0
  142. package/dist/src/panel/usage.js +150 -0
  143. package/dist/src/panel/usage.js.map +1 -0
  144. package/dist/src/project/bootstrap.d.ts +10 -0
  145. package/dist/src/project/bootstrap.js +83 -0
  146. package/dist/src/project/bootstrap.js.map +1 -0
  147. package/dist/src/project/hitl.d.ts +12 -0
  148. package/dist/src/project/hitl.js +43 -0
  149. package/dist/src/project/hitl.js.map +1 -0
  150. package/dist/src/project/jsonl.d.ts +16 -0
  151. package/dist/src/project/jsonl.js +93 -0
  152. package/dist/src/project/jsonl.js.map +1 -0
  153. package/dist/src/project/manuscript.d.ts +21 -0
  154. package/dist/src/project/manuscript.js +74 -0
  155. package/dist/src/project/manuscript.js.map +1 -0
  156. package/dist/src/project/paths.d.ts +38 -0
  157. package/dist/src/project/paths.js +166 -0
  158. package/dist/src/project/paths.js.map +1 -0
  159. package/dist/src/project/versions.d.ts +10 -0
  160. package/dist/src/project/versions.js +14 -0
  161. package/dist/src/project/versions.js.map +1 -0
  162. package/dist/src/psyclaw-theme.d.ts +88 -0
  163. package/dist/src/psyclaw-theme.js +89 -0
  164. package/dist/src/psyclaw-theme.js.map +1 -0
  165. package/dist/src/research/brief.d.ts +11 -0
  166. package/dist/src/research/brief.js +81 -0
  167. package/dist/src/research/brief.js.map +1 -0
  168. package/dist/src/research/ledger.d.ts +12 -0
  169. package/dist/src/research/ledger.js +43 -0
  170. package/dist/src/research/ledger.js.map +1 -0
  171. package/dist/src/run.d.ts +20 -0
  172. package/dist/src/run.js +34 -0
  173. package/dist/src/run.js.map +1 -0
  174. package/dist/src/setup.d.ts +54 -0
  175. package/dist/src/setup.js +221 -0
  176. package/dist/src/setup.js.map +1 -0
  177. package/dist/src/skills/contracts.d.ts +105 -0
  178. package/dist/src/skills/contracts.js +3 -0
  179. package/dist/src/skills/contracts.js.map +1 -0
  180. package/dist/src/skills/preflight.d.ts +10 -0
  181. package/dist/src/skills/preflight.js +39 -0
  182. package/dist/src/skills/preflight.js.map +1 -0
  183. package/dist/src/skills/registry.d.ts +28 -0
  184. package/dist/src/skills/registry.js +540 -0
  185. package/dist/src/skills/registry.js.map +1 -0
  186. package/dist/src/style/artifact.d.ts +6 -0
  187. package/dist/src/style/artifact.js +61 -0
  188. package/dist/src/style/artifact.js.map +1 -0
  189. package/dist/src/style/cli-ui.d.ts +41 -0
  190. package/dist/src/style/cli-ui.js +119 -0
  191. package/dist/src/style/cli-ui.js.map +1 -0
  192. package/dist/src/style/contracts.d.ts +34 -0
  193. package/dist/src/style/contracts.js +2 -0
  194. package/dist/src/style/contracts.js.map +1 -0
  195. package/dist/src/style/registry.d.ts +16 -0
  196. package/dist/src/style/registry.js +50 -0
  197. package/dist/src/style/registry.js.map +1 -0
  198. package/dist/src/trust/manifest.d.ts +42 -0
  199. package/dist/src/trust/manifest.js +53 -0
  200. package/dist/src/trust/manifest.js.map +1 -0
  201. package/dist/src/trust/sbom.d.ts +54 -0
  202. package/dist/src/trust/sbom.js +77 -0
  203. package/dist/src/trust/sbom.js.map +1 -0
  204. package/dist/src/tui/app.d.ts +3 -0
  205. package/dist/src/tui/app.js +103 -0
  206. package/dist/src/tui/app.js.map +1 -0
  207. package/dist/src/tui/model.d.ts +13 -0
  208. package/dist/src/tui/model.js +25 -0
  209. package/dist/src/tui/model.js.map +1 -0
  210. package/dist/src/updates/check.d.ts +43 -0
  211. package/dist/src/updates/check.js +68 -0
  212. package/dist/src/updates/check.js.map +1 -0
  213. package/dist/src/updates/manifest.d.ts +19 -0
  214. package/dist/src/updates/manifest.js +58 -0
  215. package/dist/src/updates/manifest.js.map +1 -0
  216. package/dist/src/updates/registry.d.ts +21 -0
  217. package/dist/src/updates/registry.js +82 -0
  218. package/dist/src/updates/registry.js.map +1 -0
  219. package/dist/src/updates/skills.d.ts +15 -0
  220. package/dist/src/updates/skills.js +39 -0
  221. package/dist/src/updates/skills.js.map +1 -0
  222. package/dist/src/updates/status.d.ts +7 -0
  223. package/dist/src/updates/status.js +37 -0
  224. package/dist/src/updates/status.js.map +1 -0
  225. package/dist/src/updates/update.d.ts +43 -0
  226. package/dist/src/updates/update.js +128 -0
  227. package/dist/src/updates/update.js.map +1 -0
  228. package/dist/src/wizard.d.ts +7 -0
  229. package/dist/src/wizard.js +90 -0
  230. package/dist/src/wizard.js.map +1 -0
  231. package/dist/src/workflows/analysis-delegation.d.ts +3 -0
  232. package/dist/src/workflows/analysis-delegation.js +96 -0
  233. package/dist/src/workflows/analysis-delegation.js.map +1 -0
  234. package/dist/src/workflows/expert-review-runner.d.ts +29 -0
  235. package/dist/src/workflows/expert-review-runner.js +35 -0
  236. package/dist/src/workflows/expert-review-runner.js.map +1 -0
  237. package/dist/src/workflows/expert-review.d.ts +140 -0
  238. package/dist/src/workflows/expert-review.js +111 -0
  239. package/dist/src/workflows/expert-review.js.map +1 -0
  240. package/dist/src/workflows/institutional-fulltext.d.ts +16 -0
  241. package/dist/src/workflows/institutional-fulltext.js +110 -0
  242. package/dist/src/workflows/institutional-fulltext.js.map +1 -0
  243. package/dist/src/workflows/literature-review.d.ts +3 -0
  244. package/dist/src/workflows/literature-review.js +76 -0
  245. package/dist/src/workflows/literature-review.js.map +1 -0
  246. package/dist/src/workflows/meta-analysis.d.ts +38 -0
  247. package/dist/src/workflows/meta-analysis.js +185 -0
  248. package/dist/src/workflows/meta-analysis.js.map +1 -0
  249. package/dist/src/workflows/publish.d.ts +51 -0
  250. package/dist/src/workflows/publish.js +153 -0
  251. package/dist/src/workflows/publish.js.map +1 -0
  252. package/dist/src/workflows/spec.d.ts +51 -0
  253. package/dist/src/workflows/spec.js +157 -0
  254. package/dist/src/workflows/spec.js.map +1 -0
  255. package/dist/src/workflows/style-contract.d.ts +24 -0
  256. package/dist/src/workflows/style-contract.js +23 -0
  257. package/dist/src/workflows/style-contract.js.map +1 -0
  258. package/dist/src/workflows/writing-review.d.ts +15 -0
  259. package/dist/src/workflows/writing-review.js +82 -0
  260. package/dist/src/workflows/writing-review.js.map +1 -0
  261. package/package.json +20 -8
  262. package/scripts/rebrand-pi.mjs +6 -5
  263. package/scripts/__pycache__/build_dist.cpython-314.pyc +0 -0
  264. package/scripts/__pycache__/build_whitepaper_docx.cpython-314.pyc +0 -0
  265. package/scripts/build_preprint_docx.py +0 -729
  266. package/scripts/build_preprint_figures.py +0 -238
  267. package/scripts/build_three_line_table_fixture.py +0 -56
  268. package/scripts/build_whitepaper_docx.py +0 -768
  269. package/scripts/check-branding.mjs +0 -159
  270. package/scripts/copy-panel.mjs +0 -11
  271. package/scripts/verify_docx.py +0 -41
@@ -0,0 +1,103 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useState } from "react";
3
+ import { Box, Text, render, useApp, useInput } from "ink";
4
+ import { spawn } from "node:child_process";
5
+ import { discoverAgents } from "../agents/discover.js";
6
+ import { importAgentSkills } from "../agents/import.js";
7
+ import { planAgentInstall, runInstall } from "../install/installer.js";
8
+ import { agentTableLines } from "./model.js";
9
+ import { PSYCLAW_ACCENT, PSYCLAW_ERROR, PSYCLAW_OK } from "../branding.js";
10
+ function spawnRunner(command) {
11
+ const [bin, ...args] = command.split(/\s+/).filter(Boolean);
12
+ return new Promise((resolve) => {
13
+ const child = spawn(bin, args, { stdio: "ignore", shell: false });
14
+ child.on("error", () => resolve({ exitCode: 1 }));
15
+ child.on("close", (code) => resolve({ exitCode: code ?? 1 }));
16
+ });
17
+ }
18
+ function Banner() {
19
+ return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsxs(Box, { gap: 1, alignItems: "center", children: [_jsx(Text, { color: PSYCLAW_ACCENT, bold: true, children: "\u03C8 PsyClaw shell" }), _jsx(Text, { color: "black", backgroundColor: PSYCLAW_ACCENT, bold: true, children: " TUI " }), _jsx(Text, { dimColor: true, children: "\u667A\u80FD\u4F53\u751F\u6001\u4E0E\u6280\u80FD\u7BA1\u7406 \u00B7 \u53EA\u8BFB\u53D1\u73B0\uFF0C\u663E\u5F0F\u6388\u6743" })] }), _jsx(Text, { dimColor: true, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" })] }));
20
+ }
21
+ function Hint({ children }) {
22
+ return (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["\uD83D\uDCA1 ", children] }) }));
23
+ }
24
+ function App({ root, homeDir }) {
25
+ const { exit } = useApp();
26
+ const [scans, setScans] = useState([]);
27
+ const [loading, setLoading] = useState(true);
28
+ const [selected, setSelected] = useState(0);
29
+ const [mode, setMode] = useState("browse");
30
+ const [message, setMessage] = useState([]);
31
+ const [resultOk, setResultOk] = useState(true);
32
+ const refresh = async () => {
33
+ setLoading(true);
34
+ setScans(await discoverAgents({ ...(homeDir === undefined ? {} : { homeDir }) }));
35
+ setLoading(false);
36
+ };
37
+ useEffect(() => {
38
+ void refresh();
39
+ }, []);
40
+ const current = scans[selected];
41
+ useInput(async (input, key) => {
42
+ if (mode === "browse") {
43
+ if (key.upArrow)
44
+ setSelected((value) => Math.max(0, value - 1));
45
+ if (key.downArrow)
46
+ setSelected((value) => Math.min(Math.max(0, scans.length - 1), value + 1));
47
+ if (input === "r")
48
+ await refresh();
49
+ if (input === "i" && current?.found)
50
+ setMode("install-confirm");
51
+ if (input === "m" && current?.found)
52
+ setMode("import-confirm");
53
+ if (input === "q")
54
+ exit();
55
+ return;
56
+ }
57
+ if (mode === "install-confirm" && current) {
58
+ if (input === "y") {
59
+ setMessage(["正在执行安装…"]);
60
+ const receipt = await runInstall(planAgentInstall(current), { approved: true, actor: "researcher", reason: "tui" }, spawnRunner);
61
+ setResultOk(receipt.ok);
62
+ setMessage([`${receipt.ok ? "✔" : "✗"} ${current.name}: ${receipt.ok ? "已成功安装" : `安装失败 (${receipt.reasonCode ?? "unknown"})`}`]);
63
+ setMode("result");
64
+ }
65
+ if (input === "n" || key.escape)
66
+ setMode("browse");
67
+ return;
68
+ }
69
+ if (mode === "import-confirm" && current) {
70
+ if (input === "y") {
71
+ const result = await importAgentSkills({
72
+ root,
73
+ agent: current,
74
+ approval: { approved: true, actor: "researcher", reason: "tui" },
75
+ });
76
+ setResultOk(true);
77
+ setMessage([`✔ 已从 ${current.name} 导入 ${result.importedCount} 个学术技能`, `产物清单: ${result.manifestPath}`]);
78
+ setMode("result");
79
+ }
80
+ if (input === "n" || key.escape)
81
+ setMode("browse");
82
+ return;
83
+ }
84
+ if (mode === "result" && (input === "q" || key.escape)) {
85
+ setMode("browse");
86
+ }
87
+ });
88
+ const table = agentTableLines(scans);
89
+ return (_jsxs(Box, { borderStyle: "round", borderColor: PSYCLAW_ACCENT, paddingX: 2, paddingY: 1, flexDirection: "column", children: [_jsx(Banner, {}), _jsx(Box, { flexDirection: "column", marginY: 1, children: loading
90
+ ? _jsx(Text, { dimColor: true, children: "\u6B63\u5728\u626B\u63CF\u672C\u673A\u5DF2\u5B89\u88C5\u667A\u80FD\u4F53\u2026" })
91
+ : table.map((line, index) => {
92
+ if (index === 0)
93
+ return _jsx(Text, { bold: true, color: PSYCLAW_ACCENT, children: line }, "header");
94
+ if (index === 1)
95
+ return _jsx(Text, { dimColor: true, children: line }, "divider");
96
+ const isSelected = index === selected + 2;
97
+ return (_jsxs(Box, { children: [_jsx(Text, { color: isSelected ? PSYCLAW_ACCENT : "gray", bold: isSelected, children: isSelected ? "❯ " : " " }), isSelected ? (_jsx(Text, { bold: true, color: PSYCLAW_ACCENT, children: line })) : (_jsx(Text, { children: line }))] }, `${index}:${line}`));
98
+ }) }), _jsxs(Box, { flexDirection: "column", children: [_jsx(Hint, { children: "[\u2191/\u2193] \u9009\u62E9 \u00B7 [R] \u5237\u65B0 \u00B7 [I] \u5B89\u88C5\u6269\u5C55 \u00B7 [M] \u5BFC\u5165\u6280\u80FD \u00B7 [Q] \u9000\u51FA" }), mode === "install-confirm" && current && (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsxs(Text, { color: PSYCLAW_ACCENT, bold: true, children: ["\u279C \u786E\u8BA4\u5B89\u88C5 ", current.name, "\uFF1F(\u6309 Y \u786E\u8BA4\uFF0CN \u53D6\u6D88)"] }), _jsxs(Text, { dimColor: true, children: ["\u6267\u884C\u547D\u4EE4: ", current.install?.installCommand || "无自动化命令(需手动安装)"] })] })), mode === "import-confirm" && current && (_jsx(Box, { marginTop: 1, flexDirection: "column", children: _jsxs(Text, { color: PSYCLAW_ACCENT, bold: true, children: ["\u279C \u786E\u8BA4\u5C06 ", current.name, " \u7684 ", current.skills.length, " \u4E2A\u6280\u80FD\u5BFC\u5165 .psyclaw/imports\uFF1F(\u6309 Y \u786E\u8BA4\uFF0CN \u53D6\u6D88)"] }) })), mode === "result" && (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [message.map((line) => (_jsx(Text, { color: resultOk ? PSYCLAW_OK : PSYCLAW_ERROR, bold: true, children: line }, line))), _jsx(Text, { dimColor: true, children: "[Q / Esc] \u8FD4\u56DE\u5217\u8868" })] }))] })] }));
99
+ }
100
+ export function runTui(root, options = {}) {
101
+ render(_jsx(App, { root: root, ...(options.homeDir === undefined ? {} : { homeDir: options.homeDir }) }), { stdout: process.stdout, exitOnCtrlC: true });
102
+ }
103
+ //# sourceMappingURL=app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../../../src/tui/app.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { AgentScan } from "../agents/discover.js";
2
+ export interface AgentRow {
3
+ name: string;
4
+ status: string;
5
+ skills: string;
6
+ config: string;
7
+ creds: string;
8
+ method: string;
9
+ }
10
+ export declare function agentRows(scans: readonly AgentScan[]): AgentRow[];
11
+ export declare const AGENT_HEADERS: readonly ["name", "status", "skills", "creds", "method", "config"];
12
+ export declare function renderTable(headers: readonly string[], rows: readonly (readonly string[])[]): string[];
13
+ export declare function agentTableLines(scans: readonly AgentScan[]): string[];
@@ -0,0 +1,25 @@
1
+ export function agentRows(scans) {
2
+ return scans.map((scan) => ({
3
+ name: scan.name,
4
+ status: scan.found ? "found" : "not found",
5
+ skills: String(scan.skills.length),
6
+ config: scan.configPath ?? "—",
7
+ creds: scan.hasCredentials ? "yes" : "no",
8
+ method: scan.install?.method ?? "—",
9
+ }));
10
+ }
11
+ export const AGENT_HEADERS = ["name", "status", "skills", "creds", "method", "config"];
12
+ export function renderTable(headers, rows) {
13
+ const widths = headers.map((header, column) => {
14
+ const cellLengths = rows.map((row) => row[column]?.length ?? 0);
15
+ return Math.max(header.length, ...cellLengths);
16
+ });
17
+ const format = (cells) => cells.map((cell, column) => (cell ?? "").padEnd(widths[column] ?? 0)).join(" ");
18
+ const divider = headers.map((_header, column) => "-".repeat(widths[column] ?? 0)).join(" ");
19
+ return [format(headers), divider, ...rows.map(format)];
20
+ }
21
+ export function agentTableLines(scans) {
22
+ const rows = agentRows(scans).map((row) => [row.name, row.status, row.skills, row.creds, row.method, row.config]);
23
+ return renderTable([...AGENT_HEADERS], rows);
24
+ }
25
+ //# sourceMappingURL=model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../../../src/tui/model.ts"],"names":[],"mappings":"AAWA,MAAM,UAAU,SAAS,CAAC,KAA2B;IACnD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC1B,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW;QAC1C,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;QAClC,MAAM,EAAE,IAAI,CAAC,UAAU,IAAI,GAAG;QAC9B,KAAK,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;QACzC,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,IAAI,GAAG;KACpC,CAAC,CAAC,CAAC;AACN,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAU,CAAC;AAEhG,MAAM,UAAU,WAAW,CACzB,OAA0B,EAC1B,IAAoC;IAEpC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE;QAC5C,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC,CAAC,CAAC;QAChE,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,WAAW,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,CAAC,KAAwB,EAAU,EAAE,CAClD,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnF,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7F,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAA2B;IACzD,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IAClH,OAAO,WAAW,CAAC,CAAC,GAAG,aAAa,CAAC,EAAE,IAAI,CAAC,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,43 @@
1
+ import { type SkillDrift } from "./skills.js";
2
+ import { type UpdateStatus } from "./status.js";
3
+ import { type RegistryClient } from "./registry.js";
4
+ export interface SelfUpdate {
5
+ current: string;
6
+ latest?: string;
7
+ status: UpdateStatus;
8
+ }
9
+ /** The bundled Pi runtime: psyclaw's pinned dependency vs the official latest. */
10
+ export interface PiRuntimeUpdate {
11
+ packageName: string;
12
+ current?: string;
13
+ latest?: string;
14
+ note?: string;
15
+ status: UpdateStatus;
16
+ }
17
+ export interface AgentUpdate {
18
+ id: string;
19
+ name: string;
20
+ method: string;
21
+ ref: string;
22
+ latest?: string;
23
+ status: UpdateStatus;
24
+ }
25
+ export interface UpdateReport {
26
+ schemaVersion: "psyclaw/update-report/v1";
27
+ checkedAt: string;
28
+ self: SelfUpdate;
29
+ runtime: PiRuntimeUpdate;
30
+ agents: AgentUpdate[];
31
+ skills: SkillDrift[];
32
+ }
33
+ export interface CheckUpdatesOptions {
34
+ registry: RegistryClient;
35
+ cwd: string;
36
+ now?: () => string;
37
+ }
38
+ /**
39
+ * Build an update report: psyclaw itself, its bundled Pi runtime, each
40
+ * installable agent, and imported skill drift. All registry lookups fail
41
+ * closed to `undefined`; nothing here installs or modifies state.
42
+ */
43
+ export declare function checkUpdates(options: CheckUpdatesOptions): Promise<UpdateReport>;
@@ -0,0 +1,68 @@
1
+ import { KNOWN_AGENTS } from "../agents/catalog.js";
2
+ import { checkSkillDrift } from "./skills.js";
3
+ import { isUnpinnedRef, versionStatus } from "./status.js";
4
+ import { npmPackageName, pipxPackageName } from "./registry.js";
5
+ import { PI_CODING_AGENT, resolvePsyClawManifest } from "./manifest.js";
6
+ /**
7
+ * Build an update report: psyclaw itself, its bundled Pi runtime, each
8
+ * installable agent, and imported skill drift. All registry lookups fail
9
+ * closed to `undefined`; nothing here installs or modifies state.
10
+ */
11
+ export async function checkUpdates(options) {
12
+ const manifest = await resolvePsyClawManifest();
13
+ const current = manifest?.version ?? "unknown";
14
+ const selfLatest = await options.registry.latestNpm("psyclaw");
15
+ const self = {
16
+ current,
17
+ ...(selfLatest === undefined ? {} : { latest: selfLatest }),
18
+ status: selfLatest === undefined ? "not-published" : versionStatus(current, selfLatest),
19
+ };
20
+ const piRelease = await options.registry.latestPiRelease();
21
+ const piVersion = manifest?.piVersion;
22
+ const piNote = piRelease?.note;
23
+ const runtime = {
24
+ packageName: PI_CODING_AGENT,
25
+ ...(piVersion === undefined ? {} : { current: piVersion }),
26
+ ...(piRelease === undefined ? {} : { latest: piRelease.version }),
27
+ ...(piNote === undefined ? {} : { note: piNote }),
28
+ status: piRelease === undefined ? "unavailable" : versionStatus(piVersion, piRelease.version),
29
+ };
30
+ const agents = [];
31
+ for (const agent of KNOWN_AGENTS) {
32
+ const install = agent.install;
33
+ if (!install)
34
+ continue;
35
+ let latest;
36
+ if (install.method === "npm") {
37
+ const packageName = npmPackageName(install.installCommand);
38
+ if (packageName !== undefined)
39
+ latest = await options.registry.latestNpm(packageName);
40
+ }
41
+ else if (install.method === "pipx") {
42
+ const packageName = pipxPackageName(install.installCommand);
43
+ if (packageName !== undefined)
44
+ latest = await options.registry.latestPypi(packageName);
45
+ }
46
+ agents.push({
47
+ id: agent.id,
48
+ name: agent.name,
49
+ method: install.method,
50
+ ref: install.ref,
51
+ ...(latest === undefined ? {} : { latest }),
52
+ status: isUnpinnedRef(install.ref) ? "unpinned" : versionStatus(install.ref, latest),
53
+ });
54
+ }
55
+ const skills = [];
56
+ for (const agent of KNOWN_AGENTS) {
57
+ skills.push(await checkSkillDrift(options.cwd, agent.id));
58
+ }
59
+ return {
60
+ schemaVersion: "psyclaw/update-report/v1",
61
+ checkedAt: (options.now ?? (() => new Date().toISOString()))(),
62
+ self,
63
+ runtime,
64
+ agents,
65
+ skills,
66
+ };
67
+ }
68
+ //# sourceMappingURL=check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.js","sourceRoot":"","sources":["../../../src/updates/check.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /** The two official Pi packages psyclaw pins and bumps in lockstep. */
2
+ export declare const PI_AI = "@earendil-works/pi-ai";
3
+ export declare const PI_CODING_AGENT = "@earendil-works/pi-coding-agent";
4
+ export interface PsyClawManifest {
5
+ root: string;
6
+ version: string;
7
+ piVersion?: string;
8
+ piAiVersion?: string;
9
+ packageManager?: string;
10
+ }
11
+ /** Synchronous psyclaw version read (banner, branding) — same walk as the resolver. */
12
+ export declare function readPsyClawVersionSync(startDir?: string): string | undefined;
13
+ /**
14
+ * Walk up from `startDir` (defaults to this module's location) until a
15
+ * `package.json` named `psyclaw` is found, then return its own version and the
16
+ * pinned Pi dependency versions. Returns `undefined` when no psyclaw package is
17
+ * reachable — the caller fails closed instead of guessing.
18
+ */
19
+ export declare function resolvePsyClawManifest(startDir?: string): Promise<PsyClawManifest | undefined>;
@@ -0,0 +1,58 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ /** The two official Pi packages psyclaw pins and bumps in lockstep. */
5
+ export const PI_AI = "@earendil-works/pi-ai";
6
+ export const PI_CODING_AGENT = "@earendil-works/pi-coding-agent";
7
+ function asString(value) {
8
+ return typeof value === "string" && value.trim() ? value.trim() : undefined;
9
+ }
10
+ /**
11
+ * Walk up from `startDir` until a `package.json` named `psyclaw` is found. The
12
+ * single source of truth for "where is the psyclaw package and what does it
13
+ * say" — used by both the async manifest resolver and the sync version reader.
14
+ */
15
+ function findPsyClawPackage(startDir) {
16
+ let dir = startDir;
17
+ for (let depth = 0; depth < 6; depth += 1) {
18
+ try {
19
+ const parsed = JSON.parse(readFileSync(join(dir, "package.json"), "utf8"));
20
+ if (parsed.name === "psyclaw")
21
+ return { dir, parsed };
22
+ }
23
+ catch {
24
+ // keep walking up
25
+ }
26
+ dir = join(dir, "..");
27
+ }
28
+ return undefined;
29
+ }
30
+ /** Synchronous psyclaw version read (banner, branding) — same walk as the resolver. */
31
+ export function readPsyClawVersionSync(startDir) {
32
+ const found = findPsyClawPackage(startDir ?? dirname(fileURLToPath(import.meta.url)));
33
+ return found === undefined ? undefined : asString(found.parsed.version);
34
+ }
35
+ /**
36
+ * Walk up from `startDir` (defaults to this module's location) until a
37
+ * `package.json` named `psyclaw` is found, then return its own version and the
38
+ * pinned Pi dependency versions. Returns `undefined` when no psyclaw package is
39
+ * reachable — the caller fails closed instead of guessing.
40
+ */
41
+ export async function resolvePsyClawManifest(startDir) {
42
+ const found = findPsyClawPackage(startDir ?? dirname(fileURLToPath(import.meta.url)));
43
+ if (found === undefined)
44
+ return undefined;
45
+ const { dir, parsed } = found;
46
+ const dependencies = parsed.dependencies ?? {};
47
+ const piVersion = asString(dependencies[PI_CODING_AGENT]);
48
+ const piAiVersion = asString(dependencies[PI_AI]);
49
+ const packageManager = asString(parsed.packageManager);
50
+ return {
51
+ root: dir,
52
+ version: asString(parsed.version) ?? "unknown",
53
+ ...(piVersion === undefined ? {} : { piVersion }),
54
+ ...(piAiVersion === undefined ? {} : { piAiVersion }),
55
+ ...(packageManager === undefined ? {} : { packageManager }),
56
+ };
57
+ }
58
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../../src/updates/manifest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Injectable registry clients. Network access is opt-in and every failure
3
+ * resolves to `undefined` (never throws), so callers stay offline-safe and the
4
+ * report simply marks the item unavailable/not-published.
5
+ */
6
+ /** The latest official Pi release as reported by pi.dev. */
7
+ export interface PiRelease {
8
+ version: string;
9
+ packageName?: string;
10
+ note?: string;
11
+ }
12
+ export interface RegistryClient {
13
+ latestNpm(packageName: string): Promise<string | undefined>;
14
+ latestPypi(packageName: string): Promise<string | undefined>;
15
+ latestPiRelease(): Promise<PiRelease | undefined>;
16
+ }
17
+ export declare function createHttpRegistry(fetchFn?: typeof fetch): RegistryClient;
18
+ /** Extract the package name from an `npm install -g <pkg>[@version]` command. */
19
+ export declare function npmPackageName(command: string): string | undefined;
20
+ /** Extract the package name from a `pipx install <pkg>[==version]` command. */
21
+ export declare function pipxPackageName(command: string): string | undefined;
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Injectable registry clients. Network access is opt-in and every failure
3
+ * resolves to `undefined` (never throws), so callers stay offline-safe and the
4
+ * report simply marks the item unavailable/not-published.
5
+ */
6
+ const REQUEST_TIMEOUT_MS = 8000;
7
+ const PI_LATEST_VERSION_URL = "https://pi.dev/api/latest-version";
8
+ export function createHttpRegistry(fetchFn = fetch) {
9
+ return {
10
+ async latestNpm(packageName) {
11
+ try {
12
+ const response = await fetchFn(`https://registry.npmjs.org/${encodeURIComponent(packageName)}/latest`, { signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS) });
13
+ if (!response.ok)
14
+ return undefined;
15
+ const body = await response.json();
16
+ return typeof body.version === "string" && body.version.trim() ? body.version.trim() : undefined;
17
+ }
18
+ catch {
19
+ return undefined;
20
+ }
21
+ },
22
+ async latestPypi(packageName) {
23
+ try {
24
+ const response = await fetchFn(`https://pypi.org/pypi/${encodeURIComponent(packageName)}/json`, { signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS) });
25
+ if (!response.ok)
26
+ return undefined;
27
+ const body = await response.json();
28
+ const version = body.info?.version;
29
+ return typeof version === "string" && version.trim() ? version.trim() : undefined;
30
+ }
31
+ catch {
32
+ return undefined;
33
+ }
34
+ },
35
+ async latestPiRelease() {
36
+ try {
37
+ const response = await fetchFn(PI_LATEST_VERSION_URL, {
38
+ headers: { accept: "application/json" },
39
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
40
+ });
41
+ if (!response.ok)
42
+ return undefined;
43
+ const body = await response.json();
44
+ const version = typeof body.version === "string" && body.version.trim() ? body.version.trim() : undefined;
45
+ if (version === undefined)
46
+ return undefined;
47
+ const packageName = typeof body.packageName === "string" && body.packageName.trim()
48
+ ? body.packageName.trim()
49
+ : undefined;
50
+ const note = typeof body.note === "string" && body.note.trim() ? body.note.trim() : undefined;
51
+ return {
52
+ version,
53
+ ...(packageName === undefined ? {} : { packageName }),
54
+ ...(note === undefined ? {} : { note }),
55
+ };
56
+ }
57
+ catch {
58
+ return undefined;
59
+ }
60
+ },
61
+ };
62
+ }
63
+ /** Extract the package name from an `npm install -g <pkg>[@version]` command. */
64
+ export function npmPackageName(command) {
65
+ const match = command.match(/npm\s+install\s+(?:-g|--global)\s+([^\s]+)/);
66
+ const raw = match?.[1];
67
+ if (raw === undefined)
68
+ return undefined;
69
+ // Strip a trailing `@version` for both scoped and unscoped packages.
70
+ const at = raw.lastIndexOf("@");
71
+ return at > 0 ? raw.slice(0, at) : raw;
72
+ }
73
+ /** Extract the package name from a `pipx install <pkg>[==version]` command. */
74
+ export function pipxPackageName(command) {
75
+ const match = command.match(/pipx\s+install\s+([^\s]+)/);
76
+ const raw = match?.[1];
77
+ if (raw === undefined)
78
+ return undefined;
79
+ // Strip a pip version specifier (`==0.16.0`).
80
+ return raw.split("==")[0] ?? undefined;
81
+ }
82
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/updates/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export type SkillDriftStatus = "up-to-date" | "changed" | "missing" | "no-import";
2
+ export interface SkillDrift {
3
+ agentId: string;
4
+ status: SkillDriftStatus;
5
+ /** Source files whose content changed since import. */
6
+ changed: string[];
7
+ /** Source files that no longer exist. */
8
+ missing: string[];
9
+ }
10
+ /**
11
+ * Detect whether imported skill files drifted from their sources. Only the
12
+ * source path is re-hashed; the imported copy itself is never modified and the
13
+ * result is read-only.
14
+ */
15
+ export declare function checkSkillDrift(root: string, agentId: string): Promise<SkillDrift>;
@@ -0,0 +1,39 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { sha256File } from "../core/hash.js";
4
+ import { projectPaths } from "../project/paths.js";
5
+ /**
6
+ * Detect whether imported skill files drifted from their sources. Only the
7
+ * source path is re-hashed; the imported copy itself is never modified and the
8
+ * result is read-only.
9
+ */
10
+ export async function checkSkillDrift(root, agentId) {
11
+ const manifestPath = join(projectPaths(root).root, ".psyclaw", "imports", agentId, "import-manifest.json");
12
+ let manifest;
13
+ try {
14
+ manifest = JSON.parse(await readFile(manifestPath, "utf8"));
15
+ }
16
+ catch {
17
+ return { agentId, status: "no-import", changed: [], missing: [] };
18
+ }
19
+ const changed = [];
20
+ const missing = [];
21
+ for (const skill of manifest.skills ?? []) {
22
+ for (const file of skill.files ?? []) {
23
+ const source = file.sourcePath;
24
+ const expected = file.sha256;
25
+ if (typeof source !== "string" || typeof expected !== "string")
26
+ continue;
27
+ const actual = await sha256File(source).catch(() => undefined);
28
+ if (actual === undefined) {
29
+ missing.push(source);
30
+ }
31
+ else if (actual.toLowerCase() !== expected.toLowerCase()) {
32
+ changed.push(source);
33
+ }
34
+ }
35
+ }
36
+ const status = missing.length > 0 ? "missing" : changed.length > 0 ? "changed" : "up-to-date";
37
+ return { agentId, status, changed, missing };
38
+ }
39
+ //# sourceMappingURL=skills.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../../src/updates/skills.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAiBnD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAY,EAAE,OAAe;IACjE,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,sBAAsB,CAAC,CAAC;IAC3G,IAAI,QAAuB,CAAC;IAC5B,IAAI,CAAC;QACH,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,CAAkB,CAAC;IAC/E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IACpE,CAAC;IAED,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;QAC1C,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;YACrC,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC;YAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC;YAC7B,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ;gBAAE,SAAS;YACzE,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YAC/D,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACvB,CAAC;iBAAM,IAAI,MAAM,CAAC,WAAW,EAAE,KAAK,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC;gBAC3D,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;IACH,CAAC;IACD,MAAM,MAAM,GAAqB,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC;IAChH,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,7 @@
1
+ export type UpdateStatus = "up-to-date" | "outdated" | "unpinned" | "unavailable" | "not-published" | "unknown";
2
+ /** A ref that cannot be compared to a registry version. */
3
+ export declare function isUnpinnedRef(ref: string | undefined): boolean;
4
+ /** Compare two versions; returns null when either side is not parseable semver. */
5
+ export declare function compareSemver(left: string, right: string): number | null;
6
+ /** Classify a pinned version against the latest available version. */
7
+ export declare function versionStatus(current: string | undefined, latest: string | undefined): UpdateStatus;
@@ -0,0 +1,37 @@
1
+ const UNPINNED_REFS = new Set(["", "unpinned", "latest", "head", "main", "master", "*", "unknown"]);
2
+ /** A ref that cannot be compared to a registry version. */
3
+ export function isUnpinnedRef(ref) {
4
+ return ref === undefined || UNPINNED_REFS.has(ref.trim().toLowerCase());
5
+ }
6
+ /** Compare two versions; returns null when either side is not parseable semver. */
7
+ export function compareSemver(left, right) {
8
+ const a = parseSemver(left);
9
+ const b = parseSemver(right);
10
+ if (a === null || b === null)
11
+ return null;
12
+ for (let index = 0; index < 3; index += 1) {
13
+ const x = a[index] ?? 0;
14
+ const y = b[index] ?? 0;
15
+ if (x !== y)
16
+ return x < y ? -1 : 1;
17
+ }
18
+ return 0;
19
+ }
20
+ function parseSemver(value) {
21
+ const match = value.trim().replace(/^v/i, "").match(/^(\d+)\.(\d+)\.(\d+)/);
22
+ if (!match)
23
+ return null;
24
+ return [Number(match[1]), Number(match[2]), Number(match[3])];
25
+ }
26
+ /** Classify a pinned version against the latest available version. */
27
+ export function versionStatus(current, latest) {
28
+ if (latest === undefined)
29
+ return "unavailable";
30
+ if (current === undefined)
31
+ return "unknown";
32
+ const comparison = compareSemver(current, latest);
33
+ if (comparison === null)
34
+ return "unknown";
35
+ return comparison < 0 ? "outdated" : "up-to-date";
36
+ }
37
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/updates/status.ts"],"names":[],"mappings":"AAQA,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,CAAC,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC;AAEpG,2DAA2D;AAC3D,MAAM,UAAU,aAAa,CAAC,GAAuB;IACnD,OAAO,GAAG,KAAK,SAAS,IAAI,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;AAC1E,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,KAAa;IACvD,MAAM,CAAC,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAC5B,MAAM,CAAC,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IAC7B,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC1C,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QAC1C,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACxB,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACxB,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,SAAS,WAAW,CAAC,KAAa;IAChC,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;IAC5E,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChE,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,aAAa,CAAC,OAA2B,EAAE,MAA0B;IACnF,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,aAAa,CAAC;IAC/C,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC5C,MAAM,UAAU,GAAG,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAClD,IAAI,UAAU,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IAC1C,OAAO,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC;AACpD,CAAC"}