@polardbx/pxbaas 0.0.0-stage → 0.1.0-beta.1

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 (264) hide show
  1. package/bin/pxbaas.js +13 -0
  2. package/dist/app/preflight.d.ts +38 -0
  3. package/dist/app/preflight.d.ts.map +1 -0
  4. package/dist/app/preflight.js +79 -0
  5. package/dist/app/preflight.js.map +1 -0
  6. package/dist/app/spec-lint.d.ts +45 -0
  7. package/dist/app/spec-lint.d.ts.map +1 -0
  8. package/dist/app/spec-lint.js +407 -0
  9. package/dist/app/spec-lint.js.map +1 -0
  10. package/dist/app/templates.d.ts +143 -0
  11. package/dist/app/templates.d.ts.map +1 -0
  12. package/dist/app/templates.js +151 -0
  13. package/dist/app/templates.js.map +1 -0
  14. package/dist/cli/root.d.ts +3 -0
  15. package/dist/cli/root.d.ts.map +1 -0
  16. package/dist/cli/root.js +69 -0
  17. package/dist/cli/root.js.map +1 -0
  18. package/dist/commands/app/index.d.ts +8 -0
  19. package/dist/commands/app/index.d.ts.map +1 -0
  20. package/dist/commands/app/index.js +1267 -0
  21. package/dist/commands/app/index.js.map +1 -0
  22. package/dist/commands/auth/index.d.ts +3 -0
  23. package/dist/commands/auth/index.d.ts.map +1 -0
  24. package/dist/commands/auth/index.js +198 -0
  25. package/dist/commands/auth/index.js.map +1 -0
  26. package/dist/commands/completion/index.d.ts +3 -0
  27. package/dist/commands/completion/index.d.ts.map +1 -0
  28. package/dist/commands/completion/index.js +10 -0
  29. package/dist/commands/completion/index.js.map +1 -0
  30. package/dist/commands/data/index.d.ts +3 -0
  31. package/dist/commands/data/index.d.ts.map +1 -0
  32. package/dist/commands/data/index.js +245 -0
  33. package/dist/commands/data/index.js.map +1 -0
  34. package/dist/commands/db/index.d.ts +14 -0
  35. package/dist/commands/db/index.d.ts.map +1 -0
  36. package/dist/commands/db/index.js +355 -0
  37. package/dist/commands/db/index.js.map +1 -0
  38. package/dist/commands/doctor/index.d.ts +3 -0
  39. package/dist/commands/doctor/index.d.ts.map +1 -0
  40. package/dist/commands/doctor/index.js +305 -0
  41. package/dist/commands/doctor/index.js.map +1 -0
  42. package/dist/commands/functions/delete.d.ts +3 -0
  43. package/dist/commands/functions/delete.d.ts.map +1 -0
  44. package/dist/commands/functions/delete.js +55 -0
  45. package/dist/commands/functions/delete.js.map +1 -0
  46. package/dist/commands/functions/deploy.d.ts +3 -0
  47. package/dist/commands/functions/deploy.d.ts.map +1 -0
  48. package/dist/commands/functions/deploy.js +118 -0
  49. package/dist/commands/functions/deploy.js.map +1 -0
  50. package/dist/commands/functions/index.d.ts +3 -0
  51. package/dist/commands/functions/index.d.ts.map +1 -0
  52. package/dist/commands/functions/index.js +15 -0
  53. package/dist/commands/functions/index.js.map +1 -0
  54. package/dist/commands/functions/list.d.ts +6 -0
  55. package/dist/commands/functions/list.d.ts.map +1 -0
  56. package/dist/commands/functions/list.js +63 -0
  57. package/dist/commands/functions/list.js.map +1 -0
  58. package/dist/commands/functions/new.d.ts +3 -0
  59. package/dist/commands/functions/new.d.ts.map +1 -0
  60. package/dist/commands/functions/new.js +57 -0
  61. package/dist/commands/functions/new.js.map +1 -0
  62. package/dist/commands/gen/index.d.ts +3 -0
  63. package/dist/commands/gen/index.d.ts.map +1 -0
  64. package/dist/commands/gen/index.js +320 -0
  65. package/dist/commands/gen/index.js.map +1 -0
  66. package/dist/commands/instance/index.d.ts +8 -0
  67. package/dist/commands/instance/index.d.ts.map +1 -0
  68. package/dist/commands/instance/index.js +361 -0
  69. package/dist/commands/instance/index.js.map +1 -0
  70. package/dist/commands/login/index.d.ts +3 -0
  71. package/dist/commands/login/index.d.ts.map +1 -0
  72. package/dist/commands/login/index.js +185 -0
  73. package/dist/commands/login/index.js.map +1 -0
  74. package/dist/commands/login/login.d.ts +3 -0
  75. package/dist/commands/login/login.d.ts.map +1 -0
  76. package/dist/commands/login/login.js +185 -0
  77. package/dist/commands/login/login.js.map +1 -0
  78. package/dist/commands/logout/index.d.ts +3 -0
  79. package/dist/commands/logout/index.d.ts.map +1 -0
  80. package/dist/commands/logout/index.js +41 -0
  81. package/dist/commands/logout/index.js.map +1 -0
  82. package/dist/commands/profile/import-env.d.ts +13 -0
  83. package/dist/commands/profile/import-env.d.ts.map +1 -0
  84. package/dist/commands/profile/import-env.js +81 -0
  85. package/dist/commands/profile/import-env.js.map +1 -0
  86. package/dist/commands/profile/index.d.ts +3 -0
  87. package/dist/commands/profile/index.d.ts.map +1 -0
  88. package/dist/commands/profile/index.js +109 -0
  89. package/dist/commands/profile/index.js.map +1 -0
  90. package/dist/commands/rest/index.d.ts +3 -0
  91. package/dist/commands/rest/index.d.ts.map +1 -0
  92. package/dist/commands/rest/index.js +102 -0
  93. package/dist/commands/rest/index.js.map +1 -0
  94. package/dist/commands/skill/index.d.ts +11 -0
  95. package/dist/commands/skill/index.d.ts.map +1 -0
  96. package/dist/commands/skill/index.js +153 -0
  97. package/dist/commands/skill/index.js.map +1 -0
  98. package/dist/commands/status/index.d.ts +3 -0
  99. package/dist/commands/status/index.d.ts.map +1 -0
  100. package/dist/commands/status/index.js +59 -0
  101. package/dist/commands/status/index.js.map +1 -0
  102. package/dist/commands/storage/index.d.ts +3 -0
  103. package/dist/commands/storage/index.d.ts.map +1 -0
  104. package/dist/commands/storage/index.js +198 -0
  105. package/dist/commands/storage/index.js.map +1 -0
  106. package/dist/commands/whoami/index.d.ts +3 -0
  107. package/dist/commands/whoami/index.d.ts.map +1 -0
  108. package/dist/commands/whoami/index.js +82 -0
  109. package/dist/commands/whoami/index.js.map +1 -0
  110. package/dist/credentials/commit.d.ts +38 -0
  111. package/dist/credentials/commit.d.ts.map +1 -0
  112. package/dist/credentials/commit.js +57 -0
  113. package/dist/credentials/commit.js.map +1 -0
  114. package/dist/credentials/credential-store.d.ts +57 -0
  115. package/dist/credentials/credential-store.d.ts.map +1 -0
  116. package/dist/credentials/credential-store.js +180 -0
  117. package/dist/credentials/credential-store.js.map +1 -0
  118. package/dist/credentials/env-file.d.ts +44 -0
  119. package/dist/credentials/env-file.d.ts.map +1 -0
  120. package/dist/credentials/env-file.js +118 -0
  121. package/dist/credentials/env-file.js.map +1 -0
  122. package/dist/credentials/formatter.d.ts +39 -0
  123. package/dist/credentials/formatter.d.ts.map +1 -0
  124. package/dist/credentials/formatter.js +79 -0
  125. package/dist/credentials/formatter.js.map +1 -0
  126. package/dist/credentials/index.d.ts +11 -0
  127. package/dist/credentials/index.d.ts.map +1 -0
  128. package/dist/credentials/index.js +11 -0
  129. package/dist/credentials/index.js.map +1 -0
  130. package/dist/credentials/jwt-introspect.d.ts +32 -0
  131. package/dist/credentials/jwt-introspect.d.ts.map +1 -0
  132. package/dist/credentials/jwt-introspect.js +64 -0
  133. package/dist/credentials/jwt-introspect.js.map +1 -0
  134. package/dist/credentials/masker.d.ts +20 -0
  135. package/dist/credentials/masker.d.ts.map +1 -0
  136. package/dist/credentials/masker.js +37 -0
  137. package/dist/credentials/masker.js.map +1 -0
  138. package/dist/credentials/profile.d.ts +83 -0
  139. package/dist/credentials/profile.d.ts.map +1 -0
  140. package/dist/credentials/profile.js +184 -0
  141. package/dist/credentials/profile.js.map +1 -0
  142. package/dist/credentials/tenant-guard.d.ts +16 -0
  143. package/dist/credentials/tenant-guard.d.ts.map +1 -0
  144. package/dist/credentials/tenant-guard.js +53 -0
  145. package/dist/credentials/tenant-guard.js.map +1 -0
  146. package/dist/credentials/tty-guard.d.ts +19 -0
  147. package/dist/credentials/tty-guard.d.ts.map +1 -0
  148. package/dist/credentials/tty-guard.js +47 -0
  149. package/dist/credentials/tty-guard.js.map +1 -0
  150. package/dist/db/apply-schema.d.ts +57 -0
  151. package/dist/db/apply-schema.d.ts.map +1 -0
  152. package/dist/db/apply-schema.js +192 -0
  153. package/dist/db/apply-schema.js.map +1 -0
  154. package/dist/db/sql-file.d.ts +49 -0
  155. package/dist/db/sql-file.d.ts.map +1 -0
  156. package/dist/db/sql-file.js +167 -0
  157. package/dist/db/sql-file.js.map +1 -0
  158. package/dist/instance/provision.d.ts +89 -0
  159. package/dist/instance/provision.d.ts.map +1 -0
  160. package/dist/instance/provision.js +139 -0
  161. package/dist/instance/provision.js.map +1 -0
  162. package/dist/instance/zero-store.d.ts +47 -0
  163. package/dist/instance/zero-store.d.ts.map +1 -0
  164. package/dist/instance/zero-store.js +91 -0
  165. package/dist/instance/zero-store.js.map +1 -0
  166. package/dist/main.d.ts +3 -0
  167. package/dist/main.d.ts.map +1 -0
  168. package/dist/main.js +46 -0
  169. package/dist/main.js.map +1 -0
  170. package/dist/skill/assets.d.ts +38 -0
  171. package/dist/skill/assets.d.ts.map +1 -0
  172. package/dist/skill/assets.js +111 -0
  173. package/dist/skill/assets.js.map +1 -0
  174. package/dist/skill/hint.d.ts +39 -0
  175. package/dist/skill/hint.d.ts.map +1 -0
  176. package/dist/skill/hint.js +109 -0
  177. package/dist/skill/hint.js.map +1 -0
  178. package/dist/skill/hosts.d.ts +21 -0
  179. package/dist/skill/hosts.d.ts.map +1 -0
  180. package/dist/skill/hosts.js +38 -0
  181. package/dist/skill/hosts.js.map +1 -0
  182. package/dist/skill/installer.d.ts +88 -0
  183. package/dist/skill/installer.d.ts.map +1 -0
  184. package/dist/skill/installer.js +203 -0
  185. package/dist/skill/installer.js.map +1 -0
  186. package/dist/skill/ownership.d.ts +35 -0
  187. package/dist/skill/ownership.d.ts.map +1 -0
  188. package/dist/skill/ownership.js +52 -0
  189. package/dist/skill/ownership.js.map +1 -0
  190. package/package.json +63 -3
  191. package/skills/pxbaas-app-spec/SKILL.md +163 -0
  192. package/skills/pxbaas-app-spec/references/deploy-options.md +157 -0
  193. package/skills/pxbaas-app-spec/references/guardrails-pitfalls.md +89 -0
  194. package/skills/pxbaas-app-spec/references/runtime-contract.md +151 -0
  195. package/skills/pxbaas-app-spec/references/ssr-session.md +121 -0
  196. package/skills/pxbaas-app-spec/references/templates-examples.md +308 -0
  197. package/skills/pxbaas-cli/SKILL.md +168 -0
  198. package/skills/pxbaas-cli/references/api-reference.md +68 -0
  199. package/skills/pxbaas-cli/references/app-deploy.md +143 -0
  200. package/skills/pxbaas-cli/references/auth-and-credentials.md +88 -0
  201. package/skills/pxbaas-cli/references/data-postgrest.md +85 -0
  202. package/skills/pxbaas-cli/references/db-and-meta.md +85 -0
  203. package/skills/pxbaas-cli/references/edge-functions.md +71 -0
  204. package/skills/pxbaas-cli/references/multi-tenant-apps.md +107 -0
  205. package/skills/pxbaas-cli/references/provision.md +86 -0
  206. package/skills/pxbaas-cli/references/safety-and-two-phase.md +49 -0
  207. package/skills/pxbaas-cli/references/storage.md +61 -0
  208. package/skills/pxbaas-cli/references/troubleshooting.md +73 -0
  209. package/templates/webapp/api/index.ts +55 -0
  210. package/templates/webapp/csr-bff/README.md +81 -0
  211. package/templates/webapp/csr-bff/backend/index.ts +168 -0
  212. package/templates/webapp/csr-bff/db/schema.sql +69 -0
  213. package/templates/webapp/csr-bff/frontend/dist/admin.html +101 -0
  214. package/templates/webapp/csr-bff/frontend/dist/article.html +44 -0
  215. package/templates/webapp/csr-bff/frontend/dist/blog.js +206 -0
  216. package/templates/webapp/csr-bff/frontend/dist/blogger.html +53 -0
  217. package/templates/webapp/csr-bff/frontend/dist/index.html +70 -0
  218. package/templates/webapp/csr-bff/frontend/dist/login.html +56 -0
  219. package/templates/webapp/csr-bff/frontend/dist/profile.html +59 -0
  220. package/templates/webapp/csr-bff/frontend/dist/signup.html +78 -0
  221. package/templates/webapp/csr-bff/frontend/dist/style.css +27 -0
  222. package/templates/webapp/manifest.json +296 -0
  223. package/templates/webapp/mpa/about.html +29 -0
  224. package/templates/webapp/mpa/app.js +42 -0
  225. package/templates/webapp/mpa/index.html +42 -0
  226. package/templates/webapp/mpa/index.ts +60 -0
  227. package/templates/webapp/mpa/style.css +42 -0
  228. package/templates/webapp/react-vite/frontend/index.html +12 -0
  229. package/templates/webapp/react-vite/frontend/package-lock.json +1826 -0
  230. package/templates/webapp/react-vite/frontend/package.json +23 -0
  231. package/templates/webapp/react-vite/frontend/src/App.tsx +34 -0
  232. package/templates/webapp/react-vite/frontend/src/main.tsx +13 -0
  233. package/templates/webapp/react-vite/frontend/src/style.css +46 -0
  234. package/templates/webapp/react-vite/frontend/tsconfig.json +20 -0
  235. package/templates/webapp/react-vite/frontend/vite.config.ts +10 -0
  236. package/templates/webapp/react-vite-hono/backend/index.ts +21 -0
  237. package/templates/webapp/react-vite-hono/frontend/index.html +12 -0
  238. package/templates/webapp/react-vite-hono/frontend/package-lock.json +1826 -0
  239. package/templates/webapp/react-vite-hono/frontend/package.json +23 -0
  240. package/templates/webapp/react-vite-hono/frontend/src/App.tsx +47 -0
  241. package/templates/webapp/react-vite-hono/frontend/src/main.tsx +13 -0
  242. package/templates/webapp/react-vite-hono/frontend/src/style.css +66 -0
  243. package/templates/webapp/react-vite-hono/frontend/tsconfig.json +20 -0
  244. package/templates/webapp/react-vite-hono/frontend/vite.config.ts +10 -0
  245. package/templates/webapp/spa/index.ts +119 -0
  246. package/templates/webapp/ssr-auth/backend/index.ts +133 -0
  247. package/templates/webapp/ssr-auth/frontend/dist/index.html +15 -0
  248. package/templates/webapp/ssr-blog/README.md +111 -0
  249. package/templates/webapp/ssr-blog/backend/index.ts +764 -0
  250. package/templates/webapp/ssr-blog/db/schema.sql +71 -0
  251. package/templates/webapp/ssr-blog/frontend/dist/index.html +39 -0
  252. package/templates/webapp/ssr-frameworks/README.md +64 -0
  253. package/templates/webapp/ssr-frameworks/backend/index.ts +241 -0
  254. package/templates/webapp/ssr-frameworks/frontend/dist/index.html +31 -0
  255. package/templates/webapp/ssr-hono/backend/index.ts +92 -0
  256. package/templates/webapp/ssr-hono/frontend/dist/index.html +12 -0
  257. package/templates/webapp/ssr-shop/README.md +80 -0
  258. package/templates/webapp/ssr-shop/backend/index.ts +491 -0
  259. package/templates/webapp/ssr-shop/db/schema.sql +120 -0
  260. package/templates/webapp/ssr-shop/frontend/dist/index.html +12 -0
  261. package/templates/webapp/vanilla-static/frontend/app.js +6 -0
  262. package/templates/webapp/vanilla-static/frontend/index.html +19 -0
  263. package/templates/webapp/vanilla-static/frontend/style.css +43 -0
  264. package/README.md +0 -3
@@ -0,0 +1,109 @@
1
+ /**
2
+ * First-run skill hint (option A).
3
+ *
4
+ * Nudges the user once — on any `pxbaas` command — that a bundled Agent Skill can
5
+ * be installed into a detected Agent host, so they discover `pxbaas skill install`
6
+ * without us silently writing into their agent config on npm install.
7
+ *
8
+ * Deliberately non-intrusive:
9
+ * - prints to **stderr** (never pollutes `--json` stdout that agents parse)
10
+ * - skipped when `--json`, when running any `skill` subcommand, when no host is
11
+ * detected, when the skill is already installed in a detected host, when the
12
+ * hint was shown before (state under ~/.baas), or when BAAS_NO_SKILL_HINT is set
13
+ * - never throws: a hint failure must not break the actual command
14
+ */
15
+ import { existsSync } from 'node:fs';
16
+ import { mkdir, writeFile } from 'node:fs/promises';
17
+ import { homedir } from 'node:os';
18
+ import { dirname, join } from 'node:path';
19
+ import { detectInstalledHosts, hostSkillDir } from './hosts.js';
20
+ import { classifyTarget } from './ownership.js';
21
+ import { ProfileManager } from '../credentials/profile.js';
22
+ const STATE_RELPATH = join('.baas', 'skill-hint.json');
23
+ function truthy(value) {
24
+ return ['1', 'true', 'yes', 'on'].includes((value ?? '').toLowerCase());
25
+ }
26
+ /**
27
+ * Print the one-time skill hint when appropriate. Safe to call before any
28
+ * command action; resolves without side effects when suppressed.
29
+ */
30
+ export async function maybePrintSkillHint(options = {}) {
31
+ const env = options.env ?? process.env;
32
+ const home = options.homeDir ?? homedir();
33
+ const write = options.stderr ?? ((line) => process.stderr.write(line + '\n'));
34
+ // Suppress in machine-readable mode and when explicitly disabled.
35
+ if (options.json)
36
+ return;
37
+ if (truthy(env.BAAS_NO_SKILL_HINT))
38
+ return;
39
+ // Do not hint while the user is already running `pxbaas skill ...`.
40
+ const root = (options.commandPath ?? '').trim().split(/\s+/)[0];
41
+ if (root === 'skill')
42
+ return;
43
+ // Only relevant when at least one supported Agent host directory exists.
44
+ const hosts = detectInstalledHosts(home);
45
+ if (hosts.length === 0)
46
+ return;
47
+ // Stay quiet if the skill is already installed in any detected host.
48
+ for (const host of hosts) {
49
+ if ((await classifyTarget(hostSkillDir(host, home))) === 'owned')
50
+ return;
51
+ }
52
+ // First-run only: skip if we already showed the hint.
53
+ const stateFile = join(home, STATE_RELPATH);
54
+ if (existsSync(stateFile))
55
+ return;
56
+ write(`Tip: enable the baas AI-agent skill for detected host(s): ${hosts.join(', ')}.`);
57
+ write(` Run: pxbaas skill install --host ${hosts[0]} (or --all). Set BAAS_NO_SKILL_HINT=1 to silence.`);
58
+ // Record that we showed it (best-effort; never fail the command).
59
+ try {
60
+ await mkdir(dirname(stateFile), { mode: 0o700, recursive: true });
61
+ await writeFile(stateFile, JSON.stringify({ shown: true, at: new Date().toISOString(), hosts }, null, 2) + '\n', { mode: 0o600 });
62
+ }
63
+ catch {
64
+ // ignore — the hint is cosmetic
65
+ }
66
+ }
67
+ const PROVISION_STATE_RELPATH = join('.baas', 'provision-hint.json');
68
+ const PROVISION_SKIP_ROOTS = new Set(['provision', 'instance', 'login', 'logout', 'profile']);
69
+ /**
70
+ * First-run hint shown when NO profile is configured yet: point the user to
71
+ * `pxbaas provision` (free 15-day Zero instance) or `pxbaas login` (own instance).
72
+ * Non-intrusive: stderr, once, skipped under --json / on onboarding commands /
73
+ * when a profile already exists / when BAAS_NO_PROVISION_HINT is set.
74
+ */
75
+ export async function maybePrintProvisionHint(options = {}) {
76
+ const env = options.env ?? process.env;
77
+ const home = options.homeDir ?? homedir();
78
+ const write = options.stderr ?? ((line) => process.stderr.write(line + '\n'));
79
+ if (options.json)
80
+ return;
81
+ if (truthy(env.BAAS_NO_PROVISION_HINT) || truthy(env.BAAS_NO_SKILL_HINT))
82
+ return;
83
+ const root = (options.commandPath ?? '').trim().split(/\s+/)[0];
84
+ if (PROVISION_SKIP_ROOTS.has(root))
85
+ return;
86
+ // Skip when a profile is already configured.
87
+ try {
88
+ const current = await new ProfileManager(join(home, '.baas')).getCurrentProfile();
89
+ if (current)
90
+ return;
91
+ }
92
+ catch {
93
+ return; // profile lookup failed — stay quiet
94
+ }
95
+ const stateFile = join(home, PROVISION_STATE_RELPATH);
96
+ if (existsSync(stateFile))
97
+ return;
98
+ write('Tip: no BaaS instance configured yet.');
99
+ write(' Run: pxbaas provision (claim a free 15-day PolarDB-X Zero instance)');
100
+ write(' or: pxbaas login (use your own instance). Set BAAS_NO_PROVISION_HINT=1 to silence.');
101
+ try {
102
+ await mkdir(dirname(stateFile), { mode: 0o700, recursive: true });
103
+ await writeFile(stateFile, JSON.stringify({ shown: true, at: new Date().toISOString() }, null, 2) + '\n', { mode: 0o600 });
104
+ }
105
+ catch {
106
+ // ignore — the hint is cosmetic
107
+ }
108
+ }
109
+ //# sourceMappingURL=hint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hint.js","sourceRoot":"","sources":["../../src/skill/hint.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Skill host mapping & detection.
3
+ *
4
+ * Mirrors the ctxdb0 `#skillTarget` convention: each supported Agent host keeps
5
+ * its skills under `~/.<host>/skills/<skill>/`. Codex (plugin marketplace) is
6
+ * intentionally out of scope for M1.
7
+ */
8
+ export type HostName = 'qoder' | 'claude' | 'cursor' | 'qwen' | 'hermes';
9
+ /** Hosts supported by `pxbaas skill install` (M1). */
10
+ export declare const SUPPORTED_HOSTS: HostName[];
11
+ export declare function isHostName(value: string): value is HostName;
12
+ /** `~/.<host>/skills` root for a host. */
13
+ export declare function hostSkillsRoot(host: HostName, homeDir: string): string;
14
+ /** Full target directory for the pxbaas-cli skill under a host. */
15
+ export declare function hostSkillDir(host: HostName, homeDir: string, skillName?: string): string;
16
+ /**
17
+ * Detect which supported hosts already have a `~/.<host>` directory, i.e. hosts
18
+ * the user plausibly uses. Used for auto-selection and `--all`.
19
+ */
20
+ export declare function detectInstalledHosts(homeDir: string): HostName[];
21
+ //# sourceMappingURL=hosts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hosts.d.ts","sourceRoot":"","sources":["../../src/skill/hosts.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEzE,sDAAsD;AACtD,eAAO,MAAM,eAAe,EAAE,QAAQ,EAAoD,CAAC;AAW3F,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,QAAQ,CAE3D;AAED,0CAA0C;AAC1C,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEtE;AAED,mEAAmE;AACnE,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,SAAe,GAAG,MAAM,CAE9F;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ,EAAE,CAEhE"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Skill host mapping & detection.
3
+ *
4
+ * Mirrors the ctxdb0 `#skillTarget` convention: each supported Agent host keeps
5
+ * its skills under `~/.<host>/skills/<skill>/`. Codex (plugin marketplace) is
6
+ * intentionally out of scope for M1.
7
+ */
8
+ import { existsSync } from 'node:fs';
9
+ import { join } from 'node:path';
10
+ /** Hosts supported by `pxbaas skill install` (M1). */
11
+ export const SUPPORTED_HOSTS = ['qoder', 'claude', 'cursor', 'qwen', 'hermes'];
12
+ /** Host name -> the dot-directory under $HOME that hosts its config/skills. */
13
+ const HOST_DIR = {
14
+ qoder: '.qoder',
15
+ claude: '.claude',
16
+ cursor: '.cursor',
17
+ qwen: '.qwen',
18
+ hermes: '.hermes',
19
+ };
20
+ export function isHostName(value) {
21
+ return SUPPORTED_HOSTS.includes(value);
22
+ }
23
+ /** `~/.<host>/skills` root for a host. */
24
+ export function hostSkillsRoot(host, homeDir) {
25
+ return join(homeDir, HOST_DIR[host], 'skills');
26
+ }
27
+ /** Full target directory for the pxbaas-cli skill under a host. */
28
+ export function hostSkillDir(host, homeDir, skillName = 'pxbaas-cli') {
29
+ return join(hostSkillsRoot(host, homeDir), skillName);
30
+ }
31
+ /**
32
+ * Detect which supported hosts already have a `~/.<host>` directory, i.e. hosts
33
+ * the user plausibly uses. Used for auto-selection and `--all`.
34
+ */
35
+ export function detectInstalledHosts(homeDir) {
36
+ return SUPPORTED_HOSTS.filter((host) => existsSync(join(homeDir, HOST_DIR[host])));
37
+ }
38
+ //# sourceMappingURL=hosts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hosts.js","sourceRoot":"","sources":["../../src/skill/hosts.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAIjC,sDAAsD;AACtD,MAAM,CAAC,MAAM,eAAe,GAAe,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;AAE3F,+EAA+E;AAC/E,MAAM,QAAQ,GAA6B;IACzC,KAAK,EAAE,QAAQ;IACf,MAAM,EAAE,SAAS;IACjB,MAAM,EAAE,SAAS;IACjB,IAAI,EAAE,OAAO;IACb,MAAM,EAAE,SAAS;CAClB,CAAC;AAEF,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,OAAQ,eAA4B,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACvD,CAAC;AAED,0CAA0C;AAC1C,MAAM,UAAU,cAAc,CAAC,IAAc,EAAE,OAAe;IAC5D,OAAO,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,CAAC;AACjD,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,YAAY,CAAC,IAAc,EAAE,OAAe,EAAE,SAAS,GAAG,YAAY;IACpF,OAAO,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,SAAS,CAAC,CAAC;AACxD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAe;IAClD,OAAO,eAAe,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AACrF,CAAC"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * SkillManager — install/list/remove ALL bundled Agent Skills (e.g. `pxbaas-cli`,
3
+ * `pxbaas-app-spec`) into supported Agent hosts.
4
+ *
5
+ * Purely local and offline: never touches credentials, profiles, or the network,
6
+ * so agents can run it without `pxbaas login`. `homeDir` and `skillsRoot` are
7
+ * injectable for testing.
8
+ *
9
+ * Layout: each host has a skills root (`~/.<host>/skills`); every bundled skill is
10
+ * installed into `<skillsRoot>/<skillName>/` with its own fail-closed owner marker.
11
+ */
12
+ import { type HostName } from './hosts.js';
13
+ export type InstallStatus = 'installed' | 'updated' | 'skipped-foreign' | 'dry-run' | 'error';
14
+ export type RemoveStatus = 'removed' | 'not-installed' | 'skipped-foreign' | 'dry-run' | 'error';
15
+ export type ListStatus = 'installed' | 'not-installed' | 'foreign';
16
+ export interface SkillResult {
17
+ host: string;
18
+ skill: string;
19
+ targetDir: string;
20
+ status: InstallStatus | RemoveStatus | ListStatus;
21
+ filesWritten?: string[];
22
+ skillVersion?: string;
23
+ installedAt?: string;
24
+ reason?: string;
25
+ }
26
+ export interface SkillManagerOptions {
27
+ /** Base home directory (defaults to os.homedir()). Injectable for tests. */
28
+ homeDir?: string;
29
+ /** Directory containing all bundled skills (defaults to resolveSkillsRoot()). */
30
+ skillsRoot?: string;
31
+ /** CLI version stamped into markers (defaults to readCliVersion()). */
32
+ cliVersion?: string;
33
+ }
34
+ export interface InstallOptions {
35
+ dryRun?: boolean;
36
+ force?: boolean;
37
+ /** Restrict to specific skill names (default: all bundled skills). */
38
+ skills?: string[];
39
+ }
40
+ export interface RemoveOptions {
41
+ dryRun?: boolean;
42
+ confirm?: boolean;
43
+ skills?: string[];
44
+ }
45
+ /** A resolved install/remove target: a host label plus its skills root directory. */
46
+ export interface ResolvedTarget {
47
+ host: string;
48
+ destRoot: string;
49
+ }
50
+ export declare class SkillManager {
51
+ private readonly homeDir;
52
+ private readonly skillsRoot;
53
+ private readonly cliVersion;
54
+ private skillsCache;
55
+ constructor(options?: SkillManagerOptions);
56
+ /** Async factory that resolves the CLI version from package.json. */
57
+ static create(options?: SkillManagerOptions): Promise<SkillManager>;
58
+ /** Bundled skill names (memoized). */
59
+ bundledSkills(): Promise<string[]>;
60
+ private selectedSkills;
61
+ /**
62
+ * Resolve which host skills-roots to act on.
63
+ * - `--dir` wins (single custom skills-root, host label "custom")
64
+ * - `--all` → every detected host (those with an existing ~/.<host>)
65
+ * - `--host <h>` → that host
66
+ * - none → auto-detect: exactly one detected host is used; 0 or >1 is an error
67
+ */
68
+ resolveTargets(opts: {
69
+ host?: HostName;
70
+ all?: boolean;
71
+ dir?: string;
72
+ }): ResolvedTarget[];
73
+ /** Install all (or selected) bundled skills into each target's skills root. */
74
+ install(targets: ResolvedTarget[], options?: InstallOptions): Promise<SkillResult[]>;
75
+ private installOne;
76
+ /** Report install state of every bundled skill across all detected hosts. */
77
+ list(options?: {
78
+ skills?: string[];
79
+ }): Promise<SkillResult[]>;
80
+ private listOne;
81
+ /**
82
+ * Remove bundled skills from each target. Only removes directories owned by
83
+ * pxbaas-cli. Two-phase: without `confirm` (or with `dryRun`) it only previews.
84
+ */
85
+ remove(targets: ResolvedTarget[], options?: RemoveOptions): Promise<SkillResult[]>;
86
+ private removeOne;
87
+ }
88
+ //# sourceMappingURL=installer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../../src/skill/installer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAQH,OAAO,EAAwC,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGjF,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,SAAS,GAAG,iBAAiB,GAAG,SAAS,GAAG,OAAO,CAAC;AAC9F,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,eAAe,GAAG,iBAAiB,GAAG,SAAS,GAAG,OAAO,CAAC;AACjG,MAAM,MAAM,UAAU,GAAG,WAAW,GAAG,eAAe,GAAG,SAAS,CAAC;AAEnE,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,aAAa,GAAG,YAAY,GAAG,UAAU,CAAC;IAClD,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iFAAiF;IACjF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,sEAAsE;IACtE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,qFAAqF;AACrF,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,WAAW,CAAyB;gBAEhC,OAAO,GAAE,mBAAwB;IAM7C,qEAAqE;WACxD,MAAM,CAAC,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,YAAY,CAAC;IAK7E,sCAAsC;IAChC,aAAa,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YAO1B,cAAc;IAU5B;;;;;;OAMG;IACH,cAAc,CAAC,IAAI,EAAE;QAAE,IAAI,CAAC,EAAE,QAAQ,CAAC;QAAC,GAAG,CAAC,EAAE,OAAO,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,cAAc,EAAE;IA0BxF,+EAA+E;IACzE,OAAO,CAAC,OAAO,EAAE,cAAc,EAAE,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;YAmBhF,UAAU;IA+DxB,6EAA6E;IACvE,IAAI,CAAC,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;KAAO,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;YAYzD,OAAO;IAUrB;;;OAGG;IACG,MAAM,CAAC,OAAO,EAAE,cAAc,EAAE,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;YAW9E,SAAS;CAgBxB"}
@@ -0,0 +1,203 @@
1
+ /**
2
+ * SkillManager — install/list/remove ALL bundled Agent Skills (e.g. `pxbaas-cli`,
3
+ * `pxbaas-app-spec`) into supported Agent hosts.
4
+ *
5
+ * Purely local and offline: never touches credentials, profiles, or the network,
6
+ * so agents can run it without `pxbaas login`. `homeDir` and `skillsRoot` are
7
+ * injectable for testing.
8
+ *
9
+ * Layout: each host has a skills root (`~/.<host>/skills`); every bundled skill is
10
+ * installed into `<skillsRoot>/<skillName>/` with its own fail-closed owner marker.
11
+ */
12
+ import { copyFile, mkdir, rm, rename } from 'node:fs/promises';
13
+ import { existsSync } from 'node:fs';
14
+ import { homedir } from 'node:os';
15
+ import { dirname, join } from 'node:path';
16
+ import { listBundledSkillsIn, listSkillFiles, readCliVersion, resolveSkillsRoot } from './assets.js';
17
+ import { detectInstalledHosts, hostSkillsRoot } from './hosts.js';
18
+ import { classifyTarget, readMarker, sha256File, writeMarker } from './ownership.js';
19
+ export class SkillManager {
20
+ homeDir;
21
+ skillsRoot;
22
+ cliVersion;
23
+ skillsCache = null;
24
+ constructor(options = {}) {
25
+ this.homeDir = options.homeDir ?? homedir();
26
+ this.skillsRoot = options.skillsRoot ?? resolveSkillsRoot();
27
+ this.cliVersion = options.cliVersion ?? 'unknown';
28
+ }
29
+ /** Async factory that resolves the CLI version from package.json. */
30
+ static async create(options = {}) {
31
+ const cliVersion = options.cliVersion ?? (await readCliVersion());
32
+ return new SkillManager({ ...options, cliVersion });
33
+ }
34
+ /** Bundled skill names (memoized). */
35
+ async bundledSkills() {
36
+ if (!this.skillsCache) {
37
+ this.skillsCache = await listBundledSkillsIn(this.skillsRoot);
38
+ }
39
+ return this.skillsCache;
40
+ }
41
+ async selectedSkills(filter) {
42
+ const all = await this.bundledSkills();
43
+ if (!filter || filter.length === 0)
44
+ return all;
45
+ const unknown = filter.filter((s) => !all.includes(s));
46
+ if (unknown.length > 0) {
47
+ throw new Error(`Unknown skill(s): ${unknown.join(', ')}. Bundled: ${all.join(', ')}.`);
48
+ }
49
+ return filter;
50
+ }
51
+ /**
52
+ * Resolve which host skills-roots to act on.
53
+ * - `--dir` wins (single custom skills-root, host label "custom")
54
+ * - `--all` → every detected host (those with an existing ~/.<host>)
55
+ * - `--host <h>` → that host
56
+ * - none → auto-detect: exactly one detected host is used; 0 or >1 is an error
57
+ */
58
+ resolveTargets(opts) {
59
+ if (opts.dir) {
60
+ return [{ host: 'custom', destRoot: opts.dir }];
61
+ }
62
+ if (opts.all) {
63
+ const detected = detectInstalledHosts(this.homeDir);
64
+ if (detected.length === 0) {
65
+ throw new Error(`No supported host directory found under ${this.homeDir}. Pass --host <name> or --dir <path>.`);
66
+ }
67
+ return detected.map((host) => ({ host, destRoot: hostSkillsRoot(host, this.homeDir) }));
68
+ }
69
+ if (opts.host) {
70
+ return [{ host: opts.host, destRoot: hostSkillsRoot(opts.host, this.homeDir) }];
71
+ }
72
+ const detected = detectInstalledHosts(this.homeDir);
73
+ if (detected.length === 1) {
74
+ return [{ host: detected[0], destRoot: hostSkillsRoot(detected[0], this.homeDir) }];
75
+ }
76
+ if (detected.length === 0) {
77
+ throw new Error(`No supported host directory found under ${this.homeDir}. Pass --host <name> or --dir <path>.`);
78
+ }
79
+ throw new Error(`Multiple hosts detected (${detected.join(', ')}). Pass --host <name> to pick one, or --all for every detected host.`);
80
+ }
81
+ /** Install all (or selected) bundled skills into each target's skills root. */
82
+ async install(targets, options = {}) {
83
+ const skills = await this.selectedSkills(options.skills);
84
+ const filesBySkill = new Map();
85
+ for (const s of skills) {
86
+ filesBySkill.set(s, await listSkillFiles(join(this.skillsRoot, s)));
87
+ }
88
+ const results = [];
89
+ for (const target of targets) {
90
+ for (const skill of skills) {
91
+ const destDir = join(target.destRoot, skill);
92
+ results.push(await this.installOne(target.host, skill, destDir, filesBySkill.get(skill) ?? [], options));
93
+ }
94
+ }
95
+ return results;
96
+ }
97
+ async installOne(host, skill, targetDir, files, options) {
98
+ const assetDir = join(this.skillsRoot, skill);
99
+ const state = await classifyTarget(targetDir);
100
+ if (state === 'foreign' && !options.force) {
101
+ return {
102
+ host,
103
+ skill,
104
+ targetDir,
105
+ status: 'skipped-foreign',
106
+ reason: 'Directory exists but is not managed by pxbaas-cli. Re-run with --force to back it up and overwrite.',
107
+ };
108
+ }
109
+ const plannedStatus = state === 'owned' ? 'updated' : 'installed';
110
+ if (options.dryRun) {
111
+ const verb = state === 'owned' ? 'update' : 'install';
112
+ return { host, skill, targetDir, status: 'dry-run', filesWritten: files, reason: `would ${verb}` };
113
+ }
114
+ try {
115
+ if (state === 'foreign' && options.force) {
116
+ await rename(targetDir, `${targetDir}.bak.${Date.now()}`);
117
+ }
118
+ await mkdir(targetDir, { recursive: true });
119
+ const hashes = {};
120
+ for (const rel of files) {
121
+ const src = join(assetDir, rel);
122
+ const dst = join(targetDir, rel);
123
+ await mkdir(dirname(dst), { recursive: true });
124
+ await copyFile(src, dst);
125
+ hashes[rel] = await sha256File(dst);
126
+ }
127
+ const marker = {
128
+ owner: 'pxbaas-cli',
129
+ skillName: skill,
130
+ skillVersion: this.cliVersion,
131
+ cliVersion: this.cliVersion,
132
+ host,
133
+ installedAt: new Date().toISOString(),
134
+ files: hashes,
135
+ };
136
+ await writeMarker(targetDir, marker);
137
+ for (const rel of files) {
138
+ if (!existsSync(join(targetDir, rel))) {
139
+ throw new Error(`Verification failed: missing ${rel} after copy`);
140
+ }
141
+ }
142
+ return { host, skill, targetDir, status: plannedStatus, filesWritten: files, skillVersion: this.cliVersion };
143
+ }
144
+ catch (err) {
145
+ return { host, skill, targetDir, status: 'error', reason: err instanceof Error ? err.message : String(err) };
146
+ }
147
+ }
148
+ /** Report install state of every bundled skill across all detected hosts. */
149
+ async list(options = {}) {
150
+ const skills = await this.selectedSkills(options.skills);
151
+ const results = [];
152
+ for (const host of detectInstalledHosts(this.homeDir)) {
153
+ const destRoot = hostSkillsRoot(host, this.homeDir);
154
+ for (const skill of skills) {
155
+ results.push(await this.listOne(host, skill, join(destRoot, skill)));
156
+ }
157
+ }
158
+ return results;
159
+ }
160
+ async listOne(host, skill, targetDir) {
161
+ const state = await classifyTarget(targetDir);
162
+ if (state === 'absent')
163
+ return { host, skill, targetDir, status: 'not-installed' };
164
+ if (state === 'foreign') {
165
+ return { host, skill, targetDir, status: 'foreign', reason: 'directory exists but is not managed by pxbaas-cli' };
166
+ }
167
+ const marker = await readMarker(targetDir);
168
+ return { host, skill, targetDir, status: 'installed', skillVersion: marker?.skillVersion, installedAt: marker?.installedAt };
169
+ }
170
+ /**
171
+ * Remove bundled skills from each target. Only removes directories owned by
172
+ * pxbaas-cli. Two-phase: without `confirm` (or with `dryRun`) it only previews.
173
+ */
174
+ async remove(targets, options = {}) {
175
+ const skills = await this.selectedSkills(options.skills);
176
+ const results = [];
177
+ for (const target of targets) {
178
+ for (const skill of skills) {
179
+ results.push(await this.removeOne(target.host, skill, join(target.destRoot, skill), options));
180
+ }
181
+ }
182
+ return results;
183
+ }
184
+ async removeOne(host, skill, targetDir, options) {
185
+ const state = await classifyTarget(targetDir);
186
+ if (state === 'absent')
187
+ return { host, skill, targetDir, status: 'not-installed' };
188
+ if (state === 'foreign') {
189
+ return { host, skill, targetDir, status: 'skipped-foreign', reason: 'Directory is not managed by pxbaas-cli; refusing to delete.' };
190
+ }
191
+ if (options.dryRun || !options.confirm) {
192
+ return { host, skill, targetDir, status: 'dry-run', reason: options.dryRun ? 'would remove' : 'pass --confirm to remove' };
193
+ }
194
+ try {
195
+ await rm(targetDir, { recursive: true, force: true });
196
+ return { host, skill, targetDir, status: 'removed' };
197
+ }
198
+ catch (err) {
199
+ return { host, skill, targetDir, status: 'error', reason: err instanceof Error ? err.message : String(err) };
200
+ }
201
+ }
202
+ }
203
+ //# sourceMappingURL=installer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installer.js","sourceRoot":"","sources":["../../src/skill/installer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Fail-closed ownership tracking for installed skills (lightweight, per-dir).
3
+ *
4
+ * Each installed skill directory carries a `.baas-skill-owner.json` marker
5
+ * recording the owner, versions, timestamp, and a sha256 per file. This lets
6
+ * `install` update its own assets idempotently, refuse to clobber foreign
7
+ * directories (unless `--force`), and lets `remove` delete only what it owns.
8
+ *
9
+ * This is the M1 lightweight model; a ctxdb0-style central manifest
10
+ * (`~/.baas/skill-installations.json`) is deferred to M2.
11
+ */
12
+ export declare const MARKER_FILE = ".baas-skill-owner.json";
13
+ export declare const OWNER_ID = "pxbaas-cli";
14
+ export interface OwnerMarker {
15
+ owner: typeof OWNER_ID;
16
+ skillName: string;
17
+ skillVersion: string;
18
+ cliVersion: string;
19
+ host: string;
20
+ installedAt: string;
21
+ files: Record<string, string>;
22
+ }
23
+ export type TargetState = 'absent' | 'owned' | 'foreign';
24
+ export declare function sha256File(path: string): Promise<string>;
25
+ /** Read and validate the owner marker in a directory; null when absent/invalid. */
26
+ export declare function readMarker(dir: string): Promise<OwnerMarker | null>;
27
+ export declare function writeMarker(dir: string, marker: OwnerMarker): Promise<void>;
28
+ /**
29
+ * Classify a target skill directory:
30
+ * - `absent` : directory does not exist
31
+ * - `owned` : exists and carries a valid pxbaas-cli marker (safe to update)
32
+ * - `foreign` : exists without our marker (must NOT be overwritten unless forced)
33
+ */
34
+ export declare function classifyTarget(dir: string): Promise<TargetState>;
35
+ //# sourceMappingURL=ownership.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ownership.d.ts","sourceRoot":"","sources":["../../src/skill/ownership.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAOH,eAAO,MAAM,WAAW,2BAA2B,CAAC;AACpD,eAAO,MAAM,QAAQ,eAAe,CAAC;AAErC,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,OAAO,QAAQ,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;AAEzD,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAG9D;AAED,mFAAmF;AACnF,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAUzE;AAED,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAEjF;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAItE"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Fail-closed ownership tracking for installed skills (lightweight, per-dir).
3
+ *
4
+ * Each installed skill directory carries a `.baas-skill-owner.json` marker
5
+ * recording the owner, versions, timestamp, and a sha256 per file. This lets
6
+ * `install` update its own assets idempotently, refuse to clobber foreign
7
+ * directories (unless `--force`), and lets `remove` delete only what it owns.
8
+ *
9
+ * This is the M1 lightweight model; a ctxdb0-style central manifest
10
+ * (`~/.baas/skill-installations.json`) is deferred to M2.
11
+ */
12
+ import { createHash } from 'node:crypto';
13
+ import { readFile, writeFile } from 'node:fs/promises';
14
+ import { existsSync } from 'node:fs';
15
+ import { join } from 'node:path';
16
+ export const MARKER_FILE = '.baas-skill-owner.json';
17
+ export const OWNER_ID = 'pxbaas-cli';
18
+ export async function sha256File(path) {
19
+ const buf = await readFile(path);
20
+ return createHash('sha256').update(buf).digest('hex');
21
+ }
22
+ /** Read and validate the owner marker in a directory; null when absent/invalid. */
23
+ export async function readMarker(dir) {
24
+ const markerPath = join(dir, MARKER_FILE);
25
+ if (!existsSync(markerPath))
26
+ return null;
27
+ try {
28
+ const parsed = JSON.parse(await readFile(markerPath, 'utf8'));
29
+ if (parsed?.owner !== OWNER_ID || typeof parsed.skillName !== 'string')
30
+ return null;
31
+ return parsed;
32
+ }
33
+ catch {
34
+ return null;
35
+ }
36
+ }
37
+ export async function writeMarker(dir, marker) {
38
+ await writeFile(join(dir, MARKER_FILE), JSON.stringify(marker, null, 2) + '\n', 'utf8');
39
+ }
40
+ /**
41
+ * Classify a target skill directory:
42
+ * - `absent` : directory does not exist
43
+ * - `owned` : exists and carries a valid pxbaas-cli marker (safe to update)
44
+ * - `foreign` : exists without our marker (must NOT be overwritten unless forced)
45
+ */
46
+ export async function classifyTarget(dir) {
47
+ if (!existsSync(dir))
48
+ return 'absent';
49
+ const marker = await readMarker(dir);
50
+ return marker ? 'owned' : 'foreign';
51
+ }
52
+ //# sourceMappingURL=ownership.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ownership.js","sourceRoot":"","sources":["../../src/skill/ownership.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,CAAC,MAAM,WAAW,GAAG,wBAAwB,CAAC;AACpD,MAAM,CAAC,MAAM,QAAQ,GAAG,YAAY,CAAC;AAcrC,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAY;IAC3C,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;IACjC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACxD,CAAC;AAED,mFAAmF;AACnF,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAW;IAC1C,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IAC1C,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IACzC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAyB,CAAC;QACtF,IAAI,MAAM,EAAE,KAAK,KAAK,QAAQ,IAAI,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QACpF,OAAO,MAAqB,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAW,EAAE,MAAmB;IAChE,MAAM,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;AAC1F,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,GAAW;IAC9C,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,QAAQ,CAAC;IACtC,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,GAAG,CAAC,CAAC;IACrC,OAAO,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;AACtC,CAAC"}