@supportpages.io/wtfm 0.0.0-stage → 0.3.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 (275) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +23 -0
  3. package/README.md +392 -2
  4. package/dist/actions.d.ts +98 -0
  5. package/dist/actions.js +86 -0
  6. package/dist/actions.js.map +1 -0
  7. package/dist/agent-settings.d.ts +22 -0
  8. package/dist/agent-settings.js +35 -0
  9. package/dist/agent-settings.js.map +1 -0
  10. package/dist/api.d.ts +14 -0
  11. package/dist/api.js +159 -0
  12. package/dist/api.js.map +1 -0
  13. package/dist/article-link.d.ts +16 -0
  14. package/dist/article-link.js +25 -0
  15. package/dist/article-link.js.map +1 -0
  16. package/dist/artifacts.d.ts +45 -0
  17. package/dist/artifacts.js +144 -0
  18. package/dist/artifacts.js.map +1 -0
  19. package/dist/brand.d.ts +4 -0
  20. package/dist/brand.js +9 -0
  21. package/dist/brand.js.map +1 -0
  22. package/dist/bridge.d.ts +2964 -0
  23. package/dist/bridge.js +1036 -0
  24. package/dist/bridge.js.map +1 -0
  25. package/dist/capacity.d.ts +5 -0
  26. package/dist/capacity.js +11 -0
  27. package/dist/capacity.js.map +1 -0
  28. package/dist/credentials.d.ts +13 -0
  29. package/dist/credentials.js +88 -0
  30. package/dist/credentials.js.map +1 -0
  31. package/dist/development-tls.d.ts +8 -0
  32. package/dist/development-tls.js +38 -0
  33. package/dist/development-tls.js.map +1 -0
  34. package/dist/errors.d.ts +15 -0
  35. package/dist/errors.js +18 -0
  36. package/dist/errors.js.map +1 -0
  37. package/dist/export.d.ts +11 -0
  38. package/dist/export.js +91 -0
  39. package/dist/export.js.map +1 -0
  40. package/dist/hosted-operations.d.ts +108 -0
  41. package/dist/hosted-operations.js +120 -0
  42. package/dist/hosted-operations.js.map +1 -0
  43. package/dist/hosting-benefits.d.ts +66 -0
  44. package/dist/hosting-benefits.js +67 -0
  45. package/dist/hosting-benefits.js.map +1 -0
  46. package/dist/index.d.ts +2 -0
  47. package/dist/index.js +49 -0
  48. package/dist/index.js.map +1 -0
  49. package/dist/local-inventory.d.ts +22 -0
  50. package/dist/local-inventory.js +59 -0
  51. package/dist/local-inventory.js.map +1 -0
  52. package/dist/local-setup.d.ts +208 -0
  53. package/dist/local-setup.js +140 -0
  54. package/dist/local-setup.js.map +1 -0
  55. package/dist/pairing.d.ts +71 -0
  56. package/dist/pairing.js +235 -0
  57. package/dist/pairing.js.map +1 -0
  58. package/dist/preferences.d.ts +18 -0
  59. package/dist/preferences.js +44 -0
  60. package/dist/preferences.js.map +1 -0
  61. package/dist/progress.d.ts +205 -0
  62. package/dist/progress.js +224 -0
  63. package/dist/progress.js.map +1 -0
  64. package/dist/reminders.d.ts +31 -0
  65. package/dist/reminders.js +73 -0
  66. package/dist/reminders.js.map +1 -0
  67. package/dist/replace-connection.d.ts +6 -0
  68. package/dist/replace-connection.js +77 -0
  69. package/dist/replace-connection.js.map +1 -0
  70. package/dist/repository-actions.d.ts +18 -0
  71. package/dist/repository-actions.js +9 -0
  72. package/dist/repository-actions.js.map +1 -0
  73. package/dist/repository-benefits.d.ts +96 -0
  74. package/dist/repository-benefits.js +64 -0
  75. package/dist/repository-benefits.js.map +1 -0
  76. package/dist/run-update.d.ts +17 -0
  77. package/dist/run-update.js +27 -0
  78. package/dist/run-update.js.map +1 -0
  79. package/dist/runs.d.ts +541 -0
  80. package/dist/runs.js +146 -0
  81. package/dist/runs.js.map +1 -0
  82. package/dist/runtime.d.ts +12 -0
  83. package/dist/runtime.js +58 -0
  84. package/dist/runtime.js.map +1 -0
  85. package/dist/schema.d.ts +277 -0
  86. package/dist/schema.js +66 -0
  87. package/dist/schema.js.map +1 -0
  88. package/dist/server.d.ts +4 -0
  89. package/dist/server.js +298 -0
  90. package/dist/server.js.map +1 -0
  91. package/dist/session.d.ts +1714 -0
  92. package/dist/session.js +619 -0
  93. package/dist/session.js.map +1 -0
  94. package/dist/settings.d.ts +9 -0
  95. package/dist/settings.js +21 -0
  96. package/dist/settings.js.map +1 -0
  97. package/dist/sync.d.ts +495 -0
  98. package/dist/sync.js +191 -0
  99. package/dist/sync.js.map +1 -0
  100. package/dist/telemetry-scrub.d.ts +13 -0
  101. package/dist/telemetry-scrub.js +51 -0
  102. package/dist/telemetry-scrub.js.map +1 -0
  103. package/dist/telemetry.d.ts +73 -0
  104. package/dist/telemetry.js +173 -0
  105. package/dist/telemetry.js.map +1 -0
  106. package/dist/walkthroughs.d.ts +224 -0
  107. package/dist/walkthroughs.js +109 -0
  108. package/dist/walkthroughs.js.map +1 -0
  109. package/dist/workspace.d.ts +14 -0
  110. package/dist/workspace.js +127 -0
  111. package/dist/workspace.js.map +1 -0
  112. package/dist/writer-agent.d.ts +21 -0
  113. package/dist/writer-agent.js +27 -0
  114. package/dist/writer-agent.js.map +1 -0
  115. package/dist/writer-entry.d.ts +171 -0
  116. package/dist/writer-entry.js +233 -0
  117. package/dist/writer-entry.js.map +1 -0
  118. package/dist/writing-style.d.ts +7 -0
  119. package/dist/writing-style.js +52 -0
  120. package/dist/writing-style.js.map +1 -0
  121. package/engine/SYNC.json +4 -0
  122. package/engine/VERSION +1 -0
  123. package/engine/detect-project/README.md +141 -0
  124. package/engine/detect-project/SKILL.md +1421 -0
  125. package/engine/detect-project/assets/desktop/desktop-frame.css +428 -0
  126. package/engine/detect-project/assets/game/game-frame.css +132 -0
  127. package/engine/detect-project/assets/macosui/LICENSE-puppertino.txt +21 -0
  128. package/engine/detect-project/assets/macosui/VERSIONS.txt +1 -0
  129. package/engine/detect-project/assets/macosui/fonts.css +15 -0
  130. package/engine/detect-project/assets/macosui/macos-frame.css +481 -0
  131. package/engine/detect-project/assets/macosui/puppertino.css +2153 -0
  132. package/engine/detect-project/assets/mobileui/LICENSE-fonts.txt +13 -0
  133. package/engine/detect-project/assets/mobileui/LICENSE-framework7.txt +52 -0
  134. package/engine/detect-project/assets/mobileui/VERSIONS.txt +6 -0
  135. package/engine/detect-project/assets/mobileui/device-frame.css +316 -0
  136. package/engine/detect-project/assets/mobileui/f7-color-theme.mjs +1345 -0
  137. package/engine/detect-project/assets/mobileui/f7-icons-names.json +1254 -0
  138. package/engine/detect-project/assets/mobileui/fonts.css +16 -0
  139. package/engine/detect-project/assets/mobileui/framework7-components.css +39 -0
  140. package/engine/detect-project/assets/mobileui/framework7-core.css +5245 -0
  141. package/engine/detect-project/assets/mobileui/icons.css +31 -0
  142. package/engine/detect-project/assets/mobileui/md3-defaults.css +89 -0
  143. package/engine/detect-project/assets/mobileui/platforms.json +46 -0
  144. package/engine/detect-project/assets/tailwind-fallback.css +1729 -0
  145. package/engine/detect-project/assets/webtui/LICENSE-webtui.txt +28 -0
  146. package/engine/detect-project/assets/webtui/VERSIONS.txt +7 -0
  147. package/engine/detect-project/assets/webtui/terminal-frame.css +195 -0
  148. package/engine/detect-project/assets/webtui/theme-catppuccin.css +1 -0
  149. package/engine/detect-project/assets/webtui/theme-everforest.css +1 -0
  150. package/engine/detect-project/assets/webtui/theme-gruvbox.css +1 -0
  151. package/engine/detect-project/assets/webtui/theme-nord.css +1 -0
  152. package/engine/detect-project/assets/webtui/theme-vitesse.css +1 -0
  153. package/engine/detect-project/assets/webtui/themes.json +37 -0
  154. package/engine/detect-project/assets/webtui/webtui-core.css +1 -0
  155. package/engine/detect-project/assets/win32ui/7css.css +2 -0
  156. package/engine/detect-project/assets/win32ui/LICENSE-7css.txt +21 -0
  157. package/engine/detect-project/assets/win32ui/VERSIONS.txt +1 -0
  158. package/engine/detect-project/assets/win32ui/win32-frame.css +278 -0
  159. package/engine/detect-project/package-lock.json +12 -0
  160. package/engine/detect-project/package.json +10 -0
  161. package/engine/detect-project/scripts/apply_runtime_profiles.js +313 -0
  162. package/engine/detect-project/scripts/check_css_health.js +412 -0
  163. package/engine/detect-project/scripts/check_project_map.js +150 -0
  164. package/engine/detect-project/scripts/check_runtime_coverage.js +311 -0
  165. package/engine/detect-project/scripts/check_runtime_recipe_quality.js +184 -0
  166. package/engine/detect-project/scripts/classify_app_type.sh +246 -0
  167. package/engine/detect-project/scripts/classify_surface.sh +95 -0
  168. package/engine/detect-project/scripts/classify_workspace.js +39 -0
  169. package/engine/detect-project/scripts/compile_css.sh +447 -0
  170. package/engine/detect-project/scripts/detect_static.js +645 -0
  171. package/engine/detect-project/scripts/detect_structure.js +187 -0
  172. package/engine/detect-project/scripts/include_census.js +451 -0
  173. package/engine/detect-project/scripts/json_get.js +142 -0
  174. package/engine/detect-project/scripts/merge_json.js +52 -0
  175. package/engine/detect-project/scripts/recommend_model_tier.js +252 -0
  176. package/engine/detect-project/scripts/resolve_route_chains.js +135 -0
  177. package/engine/detect-project/scripts/run_css_build.sh +40 -0
  178. package/engine/detect-project/scripts/sanitize_css.js +83 -0
  179. package/engine/detect-project/scripts/test_classify_surface.js +108 -0
  180. package/engine/detect-project/scripts/test_node_helpers.js +142 -0
  181. package/engine/detect-project/scripts/test_recommend_model_tier.js +119 -0
  182. package/engine/detect-project/scripts/test_resolve_route_chains.js +182 -0
  183. package/engine/detect-project/scripts/test_runtime_coverage.js +323 -0
  184. package/engine/detect-project/scripts/test_runtime_recipe_quality.js +187 -0
  185. package/engine/detect-project/scripts/theme_overrides.js +169 -0
  186. package/engine/detect-project/scripts/write_branding.js +129 -0
  187. package/engine/generate-illustrated-article/SKILL.md +461 -0
  188. package/engine/generate-illustrated-article/contracts/desktop.md +90 -0
  189. package/engine/generate-illustrated-article/contracts/game.md +38 -0
  190. package/engine/generate-illustrated-article/contracts/label-evidence.md +38 -0
  191. package/engine/generate-illustrated-article/contracts/macos.md +79 -0
  192. package/engine/generate-illustrated-article/contracts/mobile.md +40 -0
  193. package/engine/generate-illustrated-article/contracts/terminal.md +29 -0
  194. package/engine/generate-illustrated-article/contracts/win32.md +43 -0
  195. package/engine/generate-illustrated-article/package-lock.json +366 -0
  196. package/engine/generate-illustrated-article/package.json +15 -0
  197. package/engine/generate-illustrated-article/scripts/article_blocks.js +34 -0
  198. package/engine/generate-illustrated-article/scripts/check_article_json.js +105 -0
  199. package/engine/generate-illustrated-article/scripts/emit_walkthrough_signals.js +100 -0
  200. package/engine/generate-illustrated-article/scripts/extract_images.js +187 -0
  201. package/engine/generate-illustrated-article/scripts/generate_content_images.js +376 -0
  202. package/engine/generate-illustrated-article/scripts/include_census.js +451 -0
  203. package/engine/generate-illustrated-article/scripts/inject_assets.js +1691 -0
  204. package/engine/generate-illustrated-article/scripts/jit_mockup_css.js +191 -0
  205. package/engine/generate-illustrated-article/scripts/label_evidence.js +87 -0
  206. package/engine/generate-illustrated-article/scripts/lint_article_copy.js +252 -0
  207. package/engine/generate-illustrated-article/scripts/lint_mockup_fidelity.js +2403 -0
  208. package/engine/generate-illustrated-article/scripts/polish_tickets.js +1148 -0
  209. package/engine/generate-illustrated-article/scripts/related_repos.sh +52 -0
  210. package/engine/generate-illustrated-article/scripts/render_all.js +177 -0
  211. package/engine/generate-illustrated-article/scripts/render_mockup.js +665 -0
  212. package/engine/generate-illustrated-article/scripts/render_ready.js +164 -0
  213. package/engine/generate-illustrated-article/scripts/resolve_workspace.sh +86 -0
  214. package/engine/generate-illustrated-article/scripts/runtime_region_geometry.js +55 -0
  215. package/engine/generate-illustrated-article/scripts/source_paths.js +49 -0
  216. package/engine/generate-illustrated-article/scripts/test_control_visibility.js +30 -0
  217. package/engine/generate-illustrated-article/scripts/test_emit_walkthrough_signals.js +157 -0
  218. package/engine/generate-illustrated-article/scripts/test_generate_content_images.js +168 -0
  219. package/engine/generate-illustrated-article/scripts/test_include_census.js +126 -0
  220. package/engine/generate-illustrated-article/scripts/test_label_evidence.js +49 -0
  221. package/engine/generate-illustrated-article/scripts/test_lint_article_copy.js +138 -0
  222. package/engine/generate-illustrated-article/scripts/test_lint_mockup_fidelity.js +653 -0
  223. package/engine/generate-illustrated-article/scripts/test_node_ports.js +152 -0
  224. package/engine/generate-illustrated-article/scripts/test_polish_tickets.js +481 -0
  225. package/engine/generate-illustrated-article/scripts/test_related_repos.js +64 -0
  226. package/engine/generate-illustrated-article/scripts/test_render_ready.js +85 -0
  227. package/engine/generate-illustrated-article/scripts/test_source_paths.js +68 -0
  228. package/engine/generate-illustrated-article/scripts/trace_hook.js +79 -0
  229. package/engine/generate-illustrated-article/scripts/trace_hook.sh +4 -0
  230. package/engine/generate-illustrated-article/scripts/validate_html.js +114 -0
  231. package/engine/generate-illustrated-article/scripts/watermark.js +69 -0
  232. package/install.sh +14 -0
  233. package/package.json +57 -4
  234. package/scripts/auth.mjs +33 -0
  235. package/scripts/auto-update.mjs +7 -0
  236. package/scripts/build-plugin.mjs +58 -0
  237. package/scripts/build-release.mjs +94 -0
  238. package/scripts/check-release.mjs +40 -0
  239. package/scripts/check-runtime.mjs +10 -0
  240. package/scripts/cli.mjs +8 -0
  241. package/scripts/install.mjs +64 -0
  242. package/scripts/lib/agent-runner.mjs +181 -0
  243. package/scripts/lib/agent-settings.mjs +215 -0
  244. package/scripts/lib/article-skills.mjs +82 -0
  245. package/scripts/lib/auto-update.mjs +50 -0
  246. package/scripts/lib/brand.mjs +9 -0
  247. package/scripts/lib/browser.mjs +12 -0
  248. package/scripts/lib/claude-connection.mjs +33 -0
  249. package/scripts/lib/claude-permissions.mjs +47 -0
  250. package/scripts/lib/claude-plugin.mjs +15 -0
  251. package/scripts/lib/claude-writer.mjs +10 -0
  252. package/scripts/lib/cli-main.mjs +85 -0
  253. package/scripts/lib/cli.mjs +888 -0
  254. package/scripts/lib/codex-config.mjs +51 -0
  255. package/scripts/lib/codex-integration.mjs +61 -0
  256. package/scripts/lib/codex-skill.mjs +34 -0
  257. package/scripts/lib/harness-models.mjs +109 -0
  258. package/scripts/lib/install.mjs +269 -0
  259. package/scripts/lib/managed-writer.mjs +38 -0
  260. package/scripts/lib/planning.mjs +263 -0
  261. package/scripts/lib/prepare-update.mjs +85 -0
  262. package/scripts/lib/refresh-writers.mjs +12 -0
  263. package/scripts/lib/remove.mjs +167 -0
  264. package/scripts/lib/renderer.mjs +34 -0
  265. package/scripts/lib/terminal.mjs +252 -0
  266. package/scripts/lib/uninit.mjs +72 -0
  267. package/scripts/lib/update.mjs +55 -0
  268. package/scripts/lib/writer-recovery.mjs +35 -0
  269. package/scripts/lib/yolo.mjs +362 -0
  270. package/scripts/plugin-session.mjs +65 -0
  271. package/scripts/prepare-update.mjs +12 -0
  272. package/scripts/publish-release.mjs +92 -0
  273. package/scripts/skills/supportpages/SKILL.md +120 -0
  274. package/scripts/smoke-release.mjs +101 -0
  275. package/server.json +27 -0
@@ -0,0 +1,120 @@
1
+ import { z } from 'zod';
2
+ import { randomUUID, createHash } from 'node:crypto';
3
+ import { parse } from './artifacts.js';
4
+ import { resolveAction, requireExecution } from './actions.js';
5
+ import { fail } from './errors.js';
6
+ import { preferences } from './settings.js';
7
+ import { remoteId } from './schema.js';
8
+ import { secondsSince, track } from './telemetry.js';
9
+ export const operationSchema = z.object({ id: remoteId, project_id: remoteId, action: z.string(), execution: z.literal('hosted'),
10
+ attempt: z.number().int().positive(), status: z.enum(['queued', 'running', 'succeeded', 'failed']), article_id: remoteId.nullable(), walkthrough_id: remoteId.nullable().optional(),
11
+ result: z.record(z.string(), z.unknown()), error: z.object({ code: z.string(), message: z.string().max(500) }).nullable(),
12
+ review_url: z.url().nullable(), created_at: z.iso.datetime(), started_at: z.iso.datetime().nullable(), finished_at: z.iso.datetime().nullable() });
13
+ /** Durable request identity is written before any submission. Status can recover
14
+ * a lost response by key without creating another job, even after a restart. */
15
+ export class HostedOperations {
16
+ bridge;
17
+ constructor(bridge) {
18
+ this.bridge = bridge;
19
+ }
20
+ path(project) { return `${this.bridge.stateRoot}/operations/${project}`; }
21
+ check(raw, project, id, action) {
22
+ const operation = parse(operationSchema, raw, 'invalid_response');
23
+ if (operation.project_id !== project || id && operation.id !== id || action && operation.action !== action)
24
+ fail('invalid_response', 'The server returned a different operation.');
25
+ if (operation.review_url) {
26
+ const url = new URL(operation.review_url), origin = new URL(this.bridge.api.origin);
27
+ if (url.username || url.password || url.origin !== origin.origin && !(this.bridge.api.dev && url.hostname === origin.hostname && url.protocol === 'https:'))
28
+ fail('invalid_response', 'Invalid operation review link.');
29
+ }
30
+ return operation;
31
+ }
32
+ async submit(action, input, options = {}) {
33
+ requireExecution(options.decision ?? await resolveAction(this.bridge, action, typeof input.article_id === 'string' ? input.article_id : undefined), 'hosted');
34
+ const settings = await preferences(this.bridge.api);
35
+ const prefs = { prefer_background: options.prefer_background ?? settings.prefer_background, open_when_ready: options.open_when_ready ?? settings.open_when_ready };
36
+ let operation = await this.bridge.lock(async () => {
37
+ const binding = await this.bridge.binding();
38
+ const canonical = (value) => Array.isArray(value) ? value.map(canonical) : value && typeof value === 'object' ? Object.fromEntries(Object.entries(value).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => [k, canonical(v)])) : value;
39
+ const digest = createHash('sha256').update(JSON.stringify(canonical({ action, input, request_id: options.request_id }))).digest('hex');
40
+ const filename = `${this.path(binding.project_id)}/requests/${digest}.json`;
41
+ const previous = await this.bridge.ws.exists(filename) ? await this.bridge.ws.json(filename) : undefined;
42
+ const key = previous?.key ?? options.request_id ?? randomUUID();
43
+ if (!z.uuid().safeParse(key).success)
44
+ fail('invalid_request', 'Use a UUID request_id.');
45
+ const journal = { key, action, input, preferences: prefs };
46
+ await this.bridge.ws.writeJson(filename, journal);
47
+ await this.bridge.ws.writeJson(`${this.path(binding.project_id)}/latest.json`, journal);
48
+ const value = this.check(await this.bridge.api.request('POST', `/projects/${binding.project_id}/writer_operations`, { action_name: action, input }, key), binding.project_id, undefined, action);
49
+ await this.bridge.ws.writeJson(`${this.path(binding.project_id)}/latest.json`, { ...journal, operation_id: value.id });
50
+ await this.bridge.ws.writeJson(`${this.path(binding.project_id)}/${value.id}.json`, { preferences: prefs });
51
+ return value;
52
+ });
53
+ // Hosted work always runs in SupportPages, where the user can watch it.
54
+ // Holding the call adds latency and teaches the agent to wait; the link does not.
55
+ return this.present(operation);
56
+ }
57
+ async get(id, waitMs = 0, allowOpen = true) {
58
+ const binding = await this.bridge.binding();
59
+ if (id)
60
+ parse(remoteId, id);
61
+ if (!id) {
62
+ const latest = `${this.path(binding.project_id)}/latest.json`;
63
+ if (!await this.bridge.ws.exists(latest))
64
+ return undefined;
65
+ const journal = await this.bridge.ws.json(latest);
66
+ if (!journal.operation_id) {
67
+ const value = this.check(await this.bridge.api.request('GET', `/projects/${binding.project_id}/writer_operations?idempotency_key=${encodeURIComponent(journal.key)}`), binding.project_id, undefined, journal.action);
68
+ await this.bridge.ws.writeJson(latest, { ...journal, operation_id: value.id });
69
+ await this.bridge.ws.writeJson(`${this.path(binding.project_id)}/${value.id}.json`, { preferences: journal.preferences });
70
+ return this.present(value, allowOpen);
71
+ }
72
+ id = journal.operation_id;
73
+ }
74
+ return this.present(await this.poll(id, waitMs), allowOpen);
75
+ }
76
+ async poll(id, waitMs) {
77
+ const binding = await this.bridge.binding();
78
+ const deadline = Date.now() + Math.max(0, Math.min(waitMs, 20_000));
79
+ while (true) {
80
+ const result = this.check(await this.bridge.api.request('GET', `/projects/${binding.project_id}/writer_operations/${id}`), binding.project_id, id);
81
+ if (!['queued', 'running'].includes(result.status) || Date.now() >= deadline)
82
+ return result;
83
+ await new Promise(resolve => setTimeout(resolve, Math.min(3000, deadline - Date.now())));
84
+ }
85
+ }
86
+ async retry(id, attempt) {
87
+ parse(remoteId, id);
88
+ const binding = await this.bridge.binding();
89
+ return this.present(this.check(await this.bridge.api.request('POST', `/projects/${binding.project_id}/writer_operations/${id}/retry_operation`, { expected_attempt: attempt }), binding.project_id, id));
90
+ }
91
+ async present(operation, allowOpen = true) {
92
+ const open = await this.bridge.lock(async () => {
93
+ const file = `${this.path(operation.project_id)}/${operation.id}.json`;
94
+ const saved = await this.bridge.ws.exists(file) ? await this.bridge.ws.json(file) : {};
95
+ const open = allowOpen && operation.status === 'succeeded' && !!saved.preferences?.open_when_ready && !saved.opened;
96
+ // Counted once per operation, however often it is presented.
97
+ const counted = !saved.counted && ['succeeded', 'failed'].includes(operation.status) && ['create_article', 'create_video_walkthrough'].includes(operation.action);
98
+ if (open || counted)
99
+ await this.bridge.ws.writeJson(file, { ...saved, ...(open ? { opened: true } : {}), ...(counted ? { counted: true } : {}) });
100
+ if (counted)
101
+ track(operation.action === 'create_article' ? 'article_completed' : 'walkthrough_completed', {
102
+ ...(operation.action === 'create_article' ? { location: 'hosted' } : {}), outcome: operation.status, error_code: operation.error?.code,
103
+ duration_s: operation.started_at ? secondsSince(operation.started_at, operation.finished_at ? Date.parse(operation.finished_at) : Date.now()) : undefined
104
+ });
105
+ return open;
106
+ });
107
+ const completed = operation.action === 'create_video_walkthrough'
108
+ ? 'The video is ready for private review and playback. Show the review link. Do not publish or share it automatically.'
109
+ : ['suggest_sections', 'recommend_articles', 'find_article_gaps'].includes(operation.action)
110
+ ? `Read the results with ${operation.action === 'suggest_sections' ? 'list_sections' : 'list_recommendations'} and review selected IDs. Do not automatically accept suggestions, advance onboarding or generate articles. Zero new results is a successful analysis.`
111
+ : 'Show the result and review link. Creation remains a draft unless publication was explicitly requested; edits preserve publication state. Do not publish or share automatically.';
112
+ return { ...operation, operation_id: operation.id, open_when_ready: open && operation.status === 'succeeded',
113
+ instructions: operation.status === 'failed' && operation.error?.code === 'revision_conflict' ? 'The target changed. Read it again and submit a new request with its current revision and a new request_id if the editing instructions still apply. Retrying the old operation cannot overwrite a changed article.'
114
+ : operation.status === 'failed' ? 'Show the safe error and review link. Read the current article before retrying a revision conflict. Explicit retries use retry_operation with the current attempt; never start a local writer.'
115
+ : operation.status === 'succeeded' ? completed
116
+ : operation.review_url ? `SupportPages is writing this now, and the page fills in as it is written. Show ${operation.review_url} as the place to watch it, then finish your turn. Do not poll: call get_operation only when the user asks how it is going, or with this operation_id after a client restart — never resubmit, and never launch a local writer.`
117
+ : 'SupportPages is working on this now. Tell the user it is running and finish your turn. Do not poll: call get_operation only when the user asks for progress, or with this operation_id after a client restart — never resubmit, and never launch a local writer.' };
118
+ }
119
+ }
120
+ //# sourceMappingURL=hosted-operations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hosted-operations.js","sourceRoot":"","sources":["../src/hosted-operations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ import { z } from 'zod';
2
+ export declare const hostingInvitationSchema: z.ZodObject<{
3
+ id: z.ZodString;
4
+ message: z.ZodString;
5
+ }, z.core.$strip>;
6
+ export type HostingInvitation = z.infer<typeof hostingInvitationSchema>;
7
+ /** Why an anonymous local folder would want a SupportPages.io account. Every
8
+ * message must hold on the free plan a new account lands on. */
9
+ export declare const hostingBenefits: readonly [{
10
+ readonly id: "public_url";
11
+ readonly category: "reach";
12
+ readonly short: "a public URL to share with customers";
13
+ readonly message: "Give this article a public URL on your own SupportPages.io help centre, ready to share with customers.";
14
+ }, {
15
+ readonly id: "editor_review";
16
+ readonly category: "editing";
17
+ readonly short: "an editor to polish drafts before anyone sees them";
18
+ readonly message: "Review and polish drafts in the SupportPages.io editor, with your screenshots already in place, before anyone else sees them.";
19
+ }, {
20
+ readonly id: "ai_answers";
21
+ readonly category: "reach";
22
+ readonly short: "AI answers for the questions customers ask";
23
+ readonly message: "Let customers ask questions on your help centre and get AI answers grounded in your articles.";
24
+ }, {
25
+ readonly id: "agent_publishing";
26
+ readonly category: "editing";
27
+ readonly message: "Publish, unpublish and update hosted articles straight from your coding agent, with revision-safe saves that never overwrite browser edits.";
28
+ }, {
29
+ readonly id: "free_account";
30
+ readonly category: "usage";
31
+ readonly short: "hosts up to 10 articles and leaves your local files exactly where they are";
32
+ readonly message: "A free SupportPages.io account hosts up to 10 articles, and your local files stay exactly where they are.";
33
+ }, {
34
+ readonly id: "one_help_centre";
35
+ readonly category: "organisation";
36
+ readonly message: "Keep every article together in one help centre organised into sections, instead of scattered Markdown files.";
37
+ }, {
38
+ readonly id: "next_step_repository";
39
+ readonly category: "hosted";
40
+ readonly message: "Once hosted, connect your repository and let SupportPages.io suggest, generate and maintain articles in the background.";
41
+ }];
42
+ export declare const setupInvitation: () => string[];
43
+ /** The exact paragraph the agent shows after a saved local article: the benefit, then the offer. */
44
+ export declare const hostingShowText: (invitation: HostingInvitation) => string;
45
+ /** Anonymous users have no context yet: every one of the first three local
46
+ * completions carries a benefit, then every third completion after that. */
47
+ export declare const hostingReminderDue: (count: number) => boolean;
48
+ /** Device-local preference and deduplication for a whole API origin: an anonymous
49
+ * folder has no help centre to key on, so every local folder on this computer shares it. */
50
+ export declare class HostingReminders {
51
+ private journal;
52
+ constructor(configDir?: string);
53
+ private transaction;
54
+ preference(origin: string, enabled?: boolean): Promise<{
55
+ enabled: boolean;
56
+ api_origin: string;
57
+ scope: string;
58
+ }>;
59
+ complete(input: {
60
+ origin: string;
61
+ articleId: string;
62
+ }): Promise<{
63
+ id: "public_url" | "editor_review" | "ai_answers" | "agent_publishing" | "free_account" | "one_help_centre" | "next_step_repository";
64
+ message: "Give this article a public URL on your own SupportPages.io help centre, ready to share with customers." | "Review and polish drafts in the SupportPages.io editor, with your screenshots already in place, before anyone else sees them." | "Let customers ask questions on your help centre and get AI answers grounded in your articles." | "Publish, unpublish and update hosted articles straight from your coding agent, with revision-safe saves that never overwrite browser edits." | "A free SupportPages.io account hosts up to 10 articles, and your local files stay exactly where they are." | "Keep every article together in one help centre organised into sections, instead of scattered Markdown files." | "Once hosted, connect your repository and let SupportPages.io suggest, generate and maintain articles in the background.";
65
+ } | undefined>;
66
+ }
@@ -0,0 +1,67 @@
1
+ import path from 'node:path';
2
+ import { z } from 'zod';
3
+ import { ReminderJournal, claimDelivery, defaultConfigDir, reminderStateSchema, selectBenefit } from './reminders.js';
4
+ export const hostingInvitationSchema = z.object({ id: z.string(), message: z.string() });
5
+ /** Why an anonymous local folder would want a SupportPages.io account. Every
6
+ * message must hold on the free plan a new account lands on. */
7
+ export const hostingBenefits = [
8
+ { id: 'public_url', category: 'reach', short: 'a public URL to share with customers', message: 'Give this article a public URL on your own SupportPages.io help centre, ready to share with customers.' },
9
+ { id: 'editor_review', category: 'editing', short: 'an editor to polish drafts before anyone sees them', message: 'Review and polish drafts in the SupportPages.io editor, with your screenshots already in place, before anyone else sees them.' },
10
+ { id: 'ai_answers', category: 'reach', short: 'AI answers for the questions customers ask', message: 'Let customers ask questions on your help centre and get AI answers grounded in your articles.' },
11
+ { id: 'agent_publishing', category: 'editing', message: 'Publish, unpublish and update hosted articles straight from your coding agent, with revision-safe saves that never overwrite browser edits.' },
12
+ { id: 'free_account', category: 'usage', short: 'hosts up to 10 articles and leaves your local files exactly where they are', message: 'A free SupportPages.io account hosts up to 10 articles, and your local files stay exactly where they are.' },
13
+ { id: 'one_help_centre', category: 'organisation', message: 'Keep every article together in one help centre organised into sections, instead of scattered Markdown files.' },
14
+ { id: 'next_step_repository', category: 'hosted', message: 'Once hosted, connect your repository and let SupportPages.io suggest, generate and maintain articles in the background.' },
15
+ ];
16
+ /** The invitation shown before a folder has chosen where its articles go,
17
+ * composed from the same catalogue the post-article reminders draw on so a user
18
+ * cannot be promised one thing at setup and another afterwards. Hosting is an
19
+ * offer here, never a requirement: saving articles locally needs no account. */
20
+ const shortForm = (id) => {
21
+ const benefit = hostingBenefits.find(item => item.id === id);
22
+ const short = benefit && 'short' in benefit ? benefit.short : undefined;
23
+ if (!short)
24
+ throw new Error(`Hosting benefit ${id} has no short form for the setup invitation.`);
25
+ return short;
26
+ };
27
+ export const setupInvitation = () => [
28
+ `Linking a free SupportPages.io help centre also gives each article ${shortForm('public_url')}, ${shortForm('editor_review')} and ${shortForm('ai_answers')}.`,
29
+ `A free account ${shortForm('free_account')}.`,
30
+ ];
31
+ /** The exact paragraph the agent shows after a saved local article: the benefit, then the offer. */
32
+ export const hostingShowText = (invitation) => `${invitation.message} If you'd like, I can host it on a SupportPages.io help centre.`;
33
+ /** Anonymous users have no context yet: every one of the first three local
34
+ * completions carries a benefit, then every third completion after that. */
35
+ export const hostingReminderDue = (count) => count <= 3 || (count - 3) % 3 === 0;
36
+ const stateSchema = reminderStateSchema(hostingInvitationSchema);
37
+ /** Device-local preference and deduplication for a whole API origin: an anonymous
38
+ * folder has no help centre to key on, so every local folder on this computer shares it. */
39
+ export class HostingReminders {
40
+ journal;
41
+ constructor(configDir = defaultConfigDir()) {
42
+ this.journal = new ReminderJournal(path.join(configDir, 'hosting-reminders'), stateSchema);
43
+ }
44
+ transaction(origin, operation) {
45
+ return this.journal.transaction([new URL(origin).origin, 'local'], operation);
46
+ }
47
+ preference(origin, enabled) {
48
+ return this.transaction(origin, state => {
49
+ if (enabled !== undefined)
50
+ state.enabled = enabled;
51
+ return { enabled: state.enabled, api_origin: origin, scope: 'local_folders_on_this_device' };
52
+ });
53
+ }
54
+ complete(input) {
55
+ return this.transaction(input.origin, state => {
56
+ if (!claimDelivery(state, input.articleId))
57
+ return;
58
+ if (!state.enabled || !hostingReminderDue(state.count))
59
+ return;
60
+ const benefit = selectBenefit(state, hostingBenefits);
61
+ const invitation = { id: benefit.id, message: benefit.message };
62
+ state.articles[input.articleId] = invitation;
63
+ return invitation;
64
+ });
65
+ }
66
+ }
67
+ //# sourceMappingURL=hosting-benefits.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hosting-benefits.js","sourceRoot":"","sources":["../src/hosting-benefits.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,aAAa,EAAsB,MAAM,gBAAgB,CAAC;AAE1I,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAGzF;gEACgE;AAChE,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,EAAE,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,sCAAsC,EAAE,OAAO,EAAE,wGAAwG,EAAE;IACzM,EAAE,EAAE,EAAE,eAAe,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,oDAAoD,EAAE,OAAO,EAAE,+HAA+H,EAAE;IACnP,EAAE,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,4CAA4C,EAAE,OAAO,EAAE,+FAA+F,EAAE;IACtM,EAAE,EAAE,EAAE,kBAAkB,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,6IAA6I,EAAE;IACvM,EAAE,EAAE,EAAE,cAAc,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,4EAA4E,EAAE,OAAO,EAAE,2GAA2G,EAAE;IACpP,EAAE,EAAE,EAAE,iBAAiB,EAAE,QAAQ,EAAE,cAAc,EAAE,OAAO,EAAE,8GAA8G,EAAE;IAC5K,EAAE,EAAE,EAAE,sBAAsB,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,yHAAyH,EAAE;CAC9K,CAAC;AAEX;;;gFAGgF;AAChF,MAAM,SAAS,GAAG,CAAC,EAAU,EAAE,EAAE;IAC/B,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7D,MAAM,KAAK,GAAG,OAAO,IAAI,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IACxE,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,EAAE,8CAA8C,CAAC,CAAC;IACjG,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AACF,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,EAAE,CAAC;IACnC,sEAAsE,SAAS,CAAC,YAAY,CAAC,KAAK,SAAS,CAAC,eAAe,CAAC,QAAQ,SAAS,CAAC,YAAY,CAAC,GAAG;IAC9J,kBAAkB,SAAS,CAAC,cAAc,CAAC,GAAG;CAC/C,CAAC;AAEF,oGAAoG;AACpG,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,UAA6B,EAAE,EAAE,CAC/D,GAAG,UAAU,CAAC,OAAO,iEAAiE,CAAC;AAEzF;4EAC4E;AAC5E,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AAEzF,MAAM,WAAW,GAAG,mBAAmB,CAAC,uBAAuB,CAAC,CAAC;AAGjE;4FAC4F;AAC5F,MAAM,OAAO,gBAAgB;IACnB,OAAO,CAAqC;IACpD,YAAY,SAAS,GAAG,gBAAgB,EAAE;QACxC,IAAI,CAAC,OAAO,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,mBAAmB,CAAC,EAAE,WAAW,CAAC,CAAC;IAC7F,CAAC;IACO,WAAW,CAAI,MAAc,EAAE,SAA8B;QACnE,OAAO,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,CAAC,CAAC;IAChF,CAAC;IACD,UAAU,CAAC,MAAc,EAAE,OAAiB;QAC1C,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE;YACtC,IAAI,OAAO,KAAK,SAAS;gBAAE,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC;YACnD,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,8BAA8B,EAAE,CAAC;QAC/F,CAAC,CAAC,CAAC;IACL,CAAC;IACD,QAAQ,CAAC,KAA4C;QACnD,OAAO,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE;YAC5C,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;gBAAE,OAAO;YACnD,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,KAAK,CAAC;gBAAE,OAAO;YAC/D,MAAM,OAAO,GAAG,aAAa,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;YACtD,MAAM,UAAU,GAAG,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;YAChE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,UAAU,CAAC;YAC7C,OAAO,UAAU,CAAC;QACpB,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env node
2
+ import { Session, defaultConfigDir } from './session.js';
3
+ import { parseArgs } from 'node:util';
4
+ import path from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+ import { pinSkills, startBackgroundUpdate } from './runtime.js';
7
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
8
+ import { apiOrigin, defaultOrigin, developmentMode } from './api.js';
9
+ import { createServer } from './server.js';
10
+ import { fail, publicError } from './errors.js';
11
+ import { configureTelemetry, reportError } from './telemetry.js';
12
+ try {
13
+ const [major = 0, minor = 0] = process.versions.node.split('.').map(Number);
14
+ if (major < 22 || major === 22 && minor < 12) {
15
+ fail('missing_dependency', `SupportPages Writer needs Node.js 22.12 or later; this is ${process.version}. Install a newer Node.js and restart your coding agent.`);
16
+ }
17
+ const { values } = parseArgs({ options: { workspace: { type: 'string' }, 'api-url': { type: 'string' }, 'skills-dir': { type: 'string' }, 'token-file': { type: 'string' }, 'config-dir': { type: 'string' }, dev: { type: 'boolean' }, help: { type: 'boolean' }, doctor: { type: 'boolean' } } });
18
+ if (values.help) {
19
+ process.stdout.write('Usage: supportpages-mcp [--workspace /absolute/product/path] [--dev] [--api-url ORIGIN] [--skills-dir /path/to/engine] [--token-file /private/credential.json] [--doctor]\nUse --dev (or SUPPORTPAGES_DEV=true) for https://app.lvh.me:3443. Call supportpages_init in your agent to connect this project. Without --doctor, starts an MCP stdio server.\n');
20
+ }
21
+ else {
22
+ // Coding clients launch Node directly, without the wtfm/supportpages shell launchers.
23
+ process.env.PATH = path.dirname(process.execPath) + path.delimiter + (process.env.PATH ?? '');
24
+ const dev = values.dev ?? developmentMode(process.env.SUPPORTPAGES_DEV);
25
+ const origin = apiOrigin(values['api-url'] ?? process.env.SUPPORTPAGES_API_URL ?? defaultOrigin(dev), dev);
26
+ const installRoot = fileURLToPath(new URL('../', import.meta.url)).replace(/\/$/, '');
27
+ const configDir = path.resolve(values['config-dir'] ?? defaultConfigDir());
28
+ const telemetry = configureTelemetry({ configDir, origin, installRoot });
29
+ const skillsDir = await pinSkills(installRoot, path.resolve(values['skills-dir'] ?? process.env.RTFM_SKILLS_DIR ?? path.join(installRoot, 'engine')));
30
+ const session = new Session({ workspace: values.workspace ?? process.env.RTFM_WORKSPACE,
31
+ projectDir: process.env.CLAUDE_PROJECT_DIR, cwd: process.cwd(), origin, dev,
32
+ configDir,
33
+ tokenFile: values['token-file'] ?? process.env.SUPPORTPAGES_API_TOKEN_FILE, token: process.env.SUPPORTPAGES_API_TOKEN,
34
+ skillsDir });
35
+ if (values.doctor)
36
+ process.stdout.write(JSON.stringify(await (await session.bridge()).doctor(), null, 2) + '\n');
37
+ else {
38
+ await createServer(session).connect(new StdioServerTransport());
39
+ telemetry?.start();
40
+ startBackgroundUpdate(installRoot);
41
+ }
42
+ }
43
+ }
44
+ catch (error) {
45
+ reportError(error);
46
+ process.stderr.write(JSON.stringify(publicError(error)) + '\n');
47
+ process.exitCode = 1;
48
+ }
49
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { Bridge } from './bridge.js';
2
+ /** Inspect current article files, without syncing, signing in or changing setup. */
3
+ export declare function localArticleInventory(bridge: Bridge): Promise<{
4
+ status: "local";
5
+ source: "local";
6
+ articles: {
7
+ slug: string;
8
+ title: string;
9
+ artifact_dir: string;
10
+ article_path?: string;
11
+ export_path?: string;
12
+ local_article_id?: string;
13
+ run_id?: string;
14
+ }[];
15
+ next_cursor: null;
16
+ searched_directories: string[];
17
+ warnings: {
18
+ path: string;
19
+ message: string;
20
+ }[];
21
+ instructions: string;
22
+ }>;
@@ -0,0 +1,59 @@
1
+ import path from 'node:path';
2
+ import { z } from 'zod';
3
+ import { publicError } from './errors.js';
4
+ /** Inspect current article files, without syncing, signing in or changing setup. */
5
+ export async function localArticleInventory(bridge) {
6
+ const { ws } = bridge;
7
+ const local = await bridge.local();
8
+ const roots = [...new Set([local?.export_dir, 'output/articles'].filter((value) => Boolean(value)))];
9
+ const saved = await bridge.localArticles();
10
+ const directories = new Map();
11
+ for (const root of roots) {
12
+ for (const entry of await ws.list(root)) {
13
+ if (entry.isDirectory())
14
+ directories.set(path.posix.join(root, entry.name), entry.name);
15
+ }
16
+ }
17
+ for (const item of saved)
18
+ directories.set(item.artifact_dir, item.slug);
19
+ const articles = new Map();
20
+ const warnings = [];
21
+ for (const [directory, slug] of directories) {
22
+ let title, articlePath, exportPath;
23
+ for (const filename of ['article.json', 'index.md']) {
24
+ const relative = path.posix.join(directory, filename);
25
+ try {
26
+ if (!await ws.exists(relative))
27
+ continue;
28
+ if (filename === 'article.json') {
29
+ const article = z.object({ title: z.string().trim().min(1) }).parse(await ws.json(relative));
30
+ title = article.title;
31
+ articlePath = await ws.resolve(relative);
32
+ }
33
+ else {
34
+ const markdown = (await ws.read(relative)).toString('utf8');
35
+ title ??= markdown.match(/^#\s+(.+)$/m)?.[1]?.trim() || slug;
36
+ exportPath = await ws.resolve(relative);
37
+ }
38
+ }
39
+ catch (error) {
40
+ if (publicError(error).code === 'invalid_path')
41
+ throw error;
42
+ warnings.push({ path: relative, message: 'Could not read this local article file.' });
43
+ }
44
+ }
45
+ if (!articlePath && !exportPath)
46
+ continue;
47
+ const state = saved.find(item => item.slug === slug);
48
+ const existing = articles.get(slug);
49
+ // The configured export is preferred; the source folder can supply its JSON.
50
+ articles.set(slug, { slug, title: title ?? slug, artifact_dir: directory,
51
+ ...(state ? { local_article_id: state.local_article_id, run_id: state.run_id } : {}), ...existing,
52
+ ...(existing?.article_path || !articlePath ? {} : { article_path: articlePath }),
53
+ ...(existing?.export_path || !exportPath ? {} : { export_path: exportPath }) });
54
+ }
55
+ return { status: 'local', source: 'local', articles: [...articles.values()].sort((a, b) => a.title.localeCompare(b.title)),
56
+ next_cursor: null, searched_directories: [...new Set([...roots, ...saved.map(item => item.artifact_dir)])], warnings,
57
+ instructions: 'Report the local articles and their file paths. An empty list means no local articles were found in the searched directories; it says nothing about hosted articles. Use these files, not git status, as the inventory. Do not request sign-in or start setup for this local listing. Only offer hosted access if the user explicitly asks for articles on SupportPages.io.' };
58
+ }
59
+ //# sourceMappingURL=local-inventory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-inventory.js","sourceRoot":"","sources":["../src/local-inventory.ts"],"names":[],"mappings":"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"}