@vetala/vetala 0.1.0-beta

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.

Potentially problematic release.


This version of @vetala/vetala might be problematic. Click here for more details.

Files changed (271) hide show
  1. package/CONTRIBUTING.md +77 -0
  2. package/LICENSE +184 -0
  3. package/README.md +136 -0
  4. package/THIRD_PARTY_LICENSES.md +17 -0
  5. package/dist/src/agent.d.ts +30 -0
  6. package/dist/src/agent.js +216 -0
  7. package/dist/src/agent.js.map +1 -0
  8. package/dist/src/approvals.d.ts +18 -0
  9. package/dist/src/approvals.js +81 -0
  10. package/dist/src/approvals.js.map +1 -0
  11. package/dist/src/cli.d.ts +2 -0
  12. package/dist/src/cli.js +87 -0
  13. package/dist/src/cli.js.map +1 -0
  14. package/dist/src/config.d.ts +12 -0
  15. package/dist/src/config.js +183 -0
  16. package/dist/src/config.js.map +1 -0
  17. package/dist/src/context-memory.d.ts +7 -0
  18. package/dist/src/context-memory.js +96 -0
  19. package/dist/src/context-memory.js.map +1 -0
  20. package/dist/src/ink/command-suggestions.d.ts +7 -0
  21. package/dist/src/ink/command-suggestions.js +179 -0
  22. package/dist/src/ink/command-suggestions.js.map +1 -0
  23. package/dist/src/ink/ink-terminal-ui.d.ts +36 -0
  24. package/dist/src/ink/ink-terminal-ui.js +79 -0
  25. package/dist/src/ink/ink-terminal-ui.js.map +1 -0
  26. package/dist/src/ink/repl-app.d.ts +9 -0
  27. package/dist/src/ink/repl-app.js +789 -0
  28. package/dist/src/ink/repl-app.js.map +1 -0
  29. package/dist/src/ink/transcript-cards.d.ts +6 -0
  30. package/dist/src/ink/transcript-cards.js +24 -0
  31. package/dist/src/ink/transcript-cards.js.map +1 -0
  32. package/dist/src/path-policy.d.ts +11 -0
  33. package/dist/src/path-policy.js +67 -0
  34. package/dist/src/path-policy.js.map +1 -0
  35. package/dist/src/process-utils.d.ts +13 -0
  36. package/dist/src/process-utils.js +52 -0
  37. package/dist/src/process-utils.js.map +1 -0
  38. package/dist/src/repl.d.ts +9 -0
  39. package/dist/src/repl.js +13 -0
  40. package/dist/src/repl.js.map +1 -0
  41. package/dist/src/sarvam/client.d.ts +15 -0
  42. package/dist/src/sarvam/client.js +208 -0
  43. package/dist/src/sarvam/client.js.map +1 -0
  44. package/dist/src/sarvam/models.d.ts +2 -0
  45. package/dist/src/sarvam/models.js +7 -0
  46. package/dist/src/sarvam/models.js.map +1 -0
  47. package/dist/src/search-provider.d.ts +6 -0
  48. package/dist/src/search-provider.js +8 -0
  49. package/dist/src/search-provider.js.map +1 -0
  50. package/dist/src/session-store.d.ts +19 -0
  51. package/dist/src/session-store.js +318 -0
  52. package/dist/src/session-store.js.map +1 -0
  53. package/dist/src/skills/runtime.d.ts +26 -0
  54. package/dist/src/skills/runtime.js +317 -0
  55. package/dist/src/skills/runtime.js.map +1 -0
  56. package/dist/src/skills/types.d.ts +25 -0
  57. package/dist/src/skills/types.js +2 -0
  58. package/dist/src/skills/types.js.map +1 -0
  59. package/dist/src/terminal-ui.d.ts +29 -0
  60. package/dist/src/terminal-ui.js +236 -0
  61. package/dist/src/terminal-ui.js.map +1 -0
  62. package/dist/src/tools/filesystem.d.ts +2 -0
  63. package/dist/src/tools/filesystem.js +622 -0
  64. package/dist/src/tools/filesystem.js.map +1 -0
  65. package/dist/src/tools/git.d.ts +2 -0
  66. package/dist/src/tools/git.js +326 -0
  67. package/dist/src/tools/git.js.map +1 -0
  68. package/dist/src/tools/index.d.ts +6 -0
  69. package/dist/src/tools/index.js +21 -0
  70. package/dist/src/tools/index.js.map +1 -0
  71. package/dist/src/tools/registry.d.ts +15 -0
  72. package/dist/src/tools/registry.js +59 -0
  73. package/dist/src/tools/registry.js.map +1 -0
  74. package/dist/src/tools/shell.d.ts +2 -0
  75. package/dist/src/tools/shell.js +97 -0
  76. package/dist/src/tools/shell.js.map +1 -0
  77. package/dist/src/tools/skill.d.ts +3 -0
  78. package/dist/src/tools/skill.js +130 -0
  79. package/dist/src/tools/skill.js.map +1 -0
  80. package/dist/src/tools/web.d.ts +3 -0
  81. package/dist/src/tools/web.js +144 -0
  82. package/dist/src/tools/web.js.map +1 -0
  83. package/dist/src/types.d.ts +236 -0
  84. package/dist/src/types.js +2 -0
  85. package/dist/src/types.js.map +1 -0
  86. package/dist/src/workspace-trust.d.ts +3 -0
  87. package/dist/src/workspace-trust.js +31 -0
  88. package/dist/src/workspace-trust.js.map +1 -0
  89. package/dist/src/xdg.d.ts +9 -0
  90. package/dist/src/xdg.js +77 -0
  91. package/dist/src/xdg.js.map +1 -0
  92. package/package.json +57 -0
  93. package/skill/agents-md-generator/SKILL.md +75 -0
  94. package/skill/agents-md-generator/references/agents_md_template.md +160 -0
  95. package/skill/agents-md-generator/references/loc_measurement.md +67 -0
  96. package/skill/agents-md-generator/references/monorepo_detection.md +78 -0
  97. package/skill/agents-md-generator/references/monorepo_strategy.md +60 -0
  98. package/skill/agents-md-generator/references/read_only_commands.md +151 -0
  99. package/skill/agents-md-generator/references/update_strategy.md +160 -0
  100. package/skill/agents-md-generator/references/working_agreements.md +53 -0
  101. package/skill/biz-opportunity-scout/SKILL.md +53 -0
  102. package/skill/biz-opportunity-scout/references/competitive_analysis.md +84 -0
  103. package/skill/biz-opportunity-scout/references/market_sizing.md +68 -0
  104. package/skill/biz-opportunity-scout/references/pmf_indicators.md +94 -0
  105. package/skill/biz-opportunity-scout/references/report_template.md +243 -0
  106. package/skill/biz-opportunity-scout/references/unit_economics.md +97 -0
  107. package/skill/code-review/SKILL.md +86 -0
  108. package/skill/code-review/references/change_analysis.md +116 -0
  109. package/skill/code-review/references/git_operations.md +115 -0
  110. package/skill/code-review/references/impact_detection.md +149 -0
  111. package/skill/code-review/references/output_format.md +137 -0
  112. package/skill/code-review/references/severity_criteria.md +100 -0
  113. package/skill/code-security-audit/SKILL.md +123 -0
  114. package/skill/code-security-audit/references/audit_process.md +277 -0
  115. package/skill/code-security-audit/references/remediation_patterns.md +599 -0
  116. package/skill/code-security-audit/references/report_format.md +391 -0
  117. package/skill/code-security-audit/references/security_domains.md +830 -0
  118. package/skill/code-security-audit/references/vulnerability_patterns.md +813 -0
  119. package/skill/composition-patterns/SKILL.md +83 -0
  120. package/skill/composition-patterns/rules/architecture-avoid-boolean-props.md +100 -0
  121. package/skill/composition-patterns/rules/architecture-compound-components.md +112 -0
  122. package/skill/composition-patterns/rules/patterns-children-over-render-props.md +87 -0
  123. package/skill/composition-patterns/rules/patterns-explicit-variants.md +100 -0
  124. package/skill/composition-patterns/rules/react19-no-forwardref.md +42 -0
  125. package/skill/composition-patterns/rules/state-context-interface.md +191 -0
  126. package/skill/composition-patterns/rules/state-decouple-implementation.md +113 -0
  127. package/skill/composition-patterns/rules/state-lift-state.md +125 -0
  128. package/skill/deploy-to-vercel/SKILL.md +293 -0
  129. package/skill/deploy-to-vercel/resources/deploy-sandbox.sh +301 -0
  130. package/skill/deploy-to-vercel/resources/deploy.sh +301 -0
  131. package/skill/doc/SKILL_GUIDELINES.md +138 -0
  132. package/skill/git-workflow/SKILL.md +94 -0
  133. package/skill/git-workflow/references/advanced-git.md +632 -0
  134. package/skill/git-workflow/references/branching-strategies.md +344 -0
  135. package/skill/git-workflow/references/ci-cd-integration.md +683 -0
  136. package/skill/git-workflow/references/code-quality-tools.md +351 -0
  137. package/skill/git-workflow/references/commit-conventions.md +439 -0
  138. package/skill/git-workflow/references/github-releases.md +288 -0
  139. package/skill/git-workflow/references/pull-request-workflow.md +773 -0
  140. package/skill/git-workflow/scripts/verify-git-workflow.sh +263 -0
  141. package/skill/jetbrains-vmoptions/SKILL.md +51 -0
  142. package/skill/jetbrains-vmoptions/references/common-options.md +357 -0
  143. package/skill/jetbrains-vmoptions/references/gc-options.md +350 -0
  144. package/skill/jetbrains-vmoptions/references/memory-options.md +339 -0
  145. package/skill/jetbrains-vmoptions/references/prerequisite-check.md +65 -0
  146. package/skill/kysely-converter/SKILL.md +62 -0
  147. package/skill/kysely-converter/references/delete.md +323 -0
  148. package/skill/kysely-converter/references/insert.md +386 -0
  149. package/skill/kysely-converter/references/operators.md +331 -0
  150. package/skill/kysely-converter/references/select.md +1000 -0
  151. package/skill/kysely-converter/references/update.md +349 -0
  152. package/skill/kysely-converter/references/window_function.md +537 -0
  153. package/skill/react-best-practices/SKILL.md +131 -0
  154. package/skill/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  155. package/skill/react-best-practices/rules/advanced-init-once.md +42 -0
  156. package/skill/react-best-practices/rules/advanced-use-latest.md +39 -0
  157. package/skill/react-best-practices/rules/async-api-routes.md +38 -0
  158. package/skill/react-best-practices/rules/async-defer-await.md +80 -0
  159. package/skill/react-best-practices/rules/async-dependencies.md +51 -0
  160. package/skill/react-best-practices/rules/async-parallel.md +28 -0
  161. package/skill/react-best-practices/rules/async-suspense-boundaries.md +99 -0
  162. package/skill/react-best-practices/rules/bundle-barrel-imports.md +59 -0
  163. package/skill/react-best-practices/rules/bundle-conditional.md +31 -0
  164. package/skill/react-best-practices/rules/bundle-defer-third-party.md +49 -0
  165. package/skill/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  166. package/skill/react-best-practices/rules/bundle-preload.md +50 -0
  167. package/skill/react-best-practices/rules/client-event-listeners.md +74 -0
  168. package/skill/react-best-practices/rules/client-localstorage-schema.md +71 -0
  169. package/skill/react-best-practices/rules/client-passive-event-listeners.md +48 -0
  170. package/skill/react-best-practices/rules/client-swr-dedup.md +56 -0
  171. package/skill/react-best-practices/rules/js-batch-dom-css.md +107 -0
  172. package/skill/react-best-practices/rules/js-cache-function-results.md +80 -0
  173. package/skill/react-best-practices/rules/js-cache-property-access.md +28 -0
  174. package/skill/react-best-practices/rules/js-cache-storage.md +70 -0
  175. package/skill/react-best-practices/rules/js-combine-iterations.md +32 -0
  176. package/skill/react-best-practices/rules/js-early-exit.md +50 -0
  177. package/skill/react-best-practices/rules/js-hoist-regexp.md +45 -0
  178. package/skill/react-best-practices/rules/js-index-maps.md +37 -0
  179. package/skill/react-best-practices/rules/js-length-check-first.md +49 -0
  180. package/skill/react-best-practices/rules/js-min-max-loop.md +82 -0
  181. package/skill/react-best-practices/rules/js-set-map-lookups.md +24 -0
  182. package/skill/react-best-practices/rules/js-tosorted-immutable.md +57 -0
  183. package/skill/react-best-practices/rules/rendering-activity.md +26 -0
  184. package/skill/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  185. package/skill/react-best-practices/rules/rendering-conditional-render.md +40 -0
  186. package/skill/react-best-practices/rules/rendering-content-visibility.md +38 -0
  187. package/skill/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  188. package/skill/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  189. package/skill/react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
  190. package/skill/react-best-practices/rules/rendering-svg-precision.md +28 -0
  191. package/skill/react-best-practices/rules/rendering-usetransition-loading.md +75 -0
  192. package/skill/react-best-practices/rules/rerender-defer-reads.md +39 -0
  193. package/skill/react-best-practices/rules/rerender-dependencies.md +45 -0
  194. package/skill/react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
  195. package/skill/react-best-practices/rules/rerender-derived-state.md +29 -0
  196. package/skill/react-best-practices/rules/rerender-functional-setstate.md +74 -0
  197. package/skill/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  198. package/skill/react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
  199. package/skill/react-best-practices/rules/rerender-memo.md +44 -0
  200. package/skill/react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
  201. package/skill/react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
  202. package/skill/react-best-practices/rules/rerender-transitions.md +40 -0
  203. package/skill/react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
  204. package/skill/react-best-practices/rules/server-after-nonblocking.md +73 -0
  205. package/skill/react-best-practices/rules/server-auth-actions.md +96 -0
  206. package/skill/react-best-practices/rules/server-cache-lru.md +41 -0
  207. package/skill/react-best-practices/rules/server-cache-react.md +76 -0
  208. package/skill/react-best-practices/rules/server-dedup-props.md +65 -0
  209. package/skill/react-best-practices/rules/server-hoist-static-io.md +142 -0
  210. package/skill/react-best-practices/rules/server-parallel-fetching.md +83 -0
  211. package/skill/react-best-practices/rules/server-serialization.md +38 -0
  212. package/skill/react-native-skills/SKILL.md +115 -0
  213. package/skill/react-native-skills/rules/animation-derived-value.md +53 -0
  214. package/skill/react-native-skills/rules/animation-gesture-detector-press.md +95 -0
  215. package/skill/react-native-skills/rules/animation-gpu-properties.md +65 -0
  216. package/skill/react-native-skills/rules/design-system-compound-components.md +66 -0
  217. package/skill/react-native-skills/rules/fonts-config-plugin.md +71 -0
  218. package/skill/react-native-skills/rules/imports-design-system-folder.md +68 -0
  219. package/skill/react-native-skills/rules/js-hoist-intl.md +61 -0
  220. package/skill/react-native-skills/rules/list-performance-callbacks.md +44 -0
  221. package/skill/react-native-skills/rules/list-performance-function-references.md +132 -0
  222. package/skill/react-native-skills/rules/list-performance-images.md +53 -0
  223. package/skill/react-native-skills/rules/list-performance-inline-objects.md +97 -0
  224. package/skill/react-native-skills/rules/list-performance-item-expensive.md +94 -0
  225. package/skill/react-native-skills/rules/list-performance-item-memo.md +82 -0
  226. package/skill/react-native-skills/rules/list-performance-item-types.md +104 -0
  227. package/skill/react-native-skills/rules/list-performance-virtualize.md +67 -0
  228. package/skill/react-native-skills/rules/monorepo-native-deps-in-app.md +46 -0
  229. package/skill/react-native-skills/rules/monorepo-single-dependency-versions.md +63 -0
  230. package/skill/react-native-skills/rules/navigation-native-navigators.md +188 -0
  231. package/skill/react-native-skills/rules/react-compiler-destructure-functions.md +50 -0
  232. package/skill/react-native-skills/rules/react-compiler-reanimated-shared-values.md +48 -0
  233. package/skill/react-native-skills/rules/react-state-dispatcher.md +91 -0
  234. package/skill/react-native-skills/rules/react-state-fallback.md +56 -0
  235. package/skill/react-native-skills/rules/react-state-minimize.md +65 -0
  236. package/skill/react-native-skills/rules/rendering-no-falsy-and.md +74 -0
  237. package/skill/react-native-skills/rules/rendering-text-in-text-component.md +36 -0
  238. package/skill/react-native-skills/rules/scroll-position-no-state.md +82 -0
  239. package/skill/react-native-skills/rules/state-ground-truth.md +80 -0
  240. package/skill/react-native-skills/rules/ui-expo-image.md +66 -0
  241. package/skill/react-native-skills/rules/ui-image-gallery.md +104 -0
  242. package/skill/react-native-skills/rules/ui-measure-views.md +78 -0
  243. package/skill/react-native-skills/rules/ui-menus.md +174 -0
  244. package/skill/react-native-skills/rules/ui-native-modals.md +77 -0
  245. package/skill/react-native-skills/rules/ui-pressable.md +61 -0
  246. package/skill/react-native-skills/rules/ui-safe-area-scroll.md +65 -0
  247. package/skill/react-native-skills/rules/ui-scrollview-content-inset.md +45 -0
  248. package/skill/react-native-skills/rules/ui-styling.md +87 -0
  249. package/skill/react-vite-guide/SKILL.md +101 -0
  250. package/skill/react-vite-guide/references/composition-patterns.md +709 -0
  251. package/skill/react-vite-guide/references/performance-optimization.md +1222 -0
  252. package/skill/react-vite-guide/references/vite-specific.md +385 -0
  253. package/skill/react-vite-guide/references/web-interface.md +146 -0
  254. package/skill/skill-maker/SKILL.md +52 -0
  255. package/skill/skill-maker/references/content_spec.md +67 -0
  256. package/skill/skill-maker/references/frontmatter_spec.md +96 -0
  257. package/skill/skill-maker/references/input_validation.md +90 -0
  258. package/skill/skill-maker/references/skill_structure.md +74 -0
  259. package/skill/system-prompt-creator/SKILL.md +50 -0
  260. package/skill/system-prompt-creator/references/data_format_selection.md +135 -0
  261. package/skill/system-prompt-creator/references/multi_prompt_architecture.md +386 -0
  262. package/skill/system-prompt-creator/references/prompt_structure.md +140 -0
  263. package/skill/system-prompt-creator/references/quality_criteria.md +83 -0
  264. package/skill/typst-creator/SKILL.md +51 -0
  265. package/skill/typst-creator/references/layout.md +401 -0
  266. package/skill/typst-creator/references/math.md +297 -0
  267. package/skill/typst-creator/references/scripting.md +237 -0
  268. package/skill/typst-creator/references/styling.md +217 -0
  269. package/skill/typst-creator/references/syntax.md +234 -0
  270. package/skill/web-design-guidelines/SKILL.md +35 -0
  271. package/terminal.png +0 -0
@@ -0,0 +1,318 @@
1
+ import crypto from "node:crypto";
2
+ import path from "node:path";
3
+ import { appendFile, readFile, readdir, writeFile } from "node:fs/promises";
4
+ import { ensureAppPaths } from "./xdg.js";
5
+ const EMPTY_APPROVALS = {
6
+ sessionActionKeys: [],
7
+ outOfTreeRoots: [],
8
+ webAccess: false
9
+ };
10
+ export class SessionStore {
11
+ async createSession(workspaceRoot, model) {
12
+ const paths = await ensureAppPaths();
13
+ const id = createSessionId();
14
+ const createdAt = new Date().toISOString();
15
+ const state = {
16
+ id,
17
+ workspaceRoot,
18
+ model,
19
+ createdAt,
20
+ updatedAt: createdAt,
21
+ approvals: structuredClone(EMPTY_APPROVALS),
22
+ messages: [],
23
+ referencedFiles: [],
24
+ readFiles: [],
25
+ pinnedSkills: []
26
+ };
27
+ const record = {
28
+ type: "meta",
29
+ id,
30
+ workspaceRoot,
31
+ model,
32
+ createdAt
33
+ };
34
+ await appendFile(this.sessionPath(paths.sessionsDir, id), `${JSON.stringify(record)}\n`, "utf8");
35
+ await this.updateLatestWorkspace(workspaceRoot, id);
36
+ return state;
37
+ }
38
+ async loadSession(sessionId) {
39
+ const paths = await ensureAppPaths();
40
+ const sessionPath = this.sessionPath(paths.sessionsDir, sessionId);
41
+ const raw = await readFile(sessionPath, "utf8");
42
+ const lines = raw.split("\n").filter(Boolean);
43
+ let state;
44
+ for (const line of lines) {
45
+ const record = JSON.parse(line);
46
+ switch (record.type) {
47
+ case "meta":
48
+ state = {
49
+ id: record.id,
50
+ workspaceRoot: record.workspaceRoot,
51
+ model: record.model,
52
+ createdAt: record.createdAt,
53
+ updatedAt: record.createdAt,
54
+ approvals: structuredClone(EMPTY_APPROVALS),
55
+ messages: [],
56
+ referencedFiles: [],
57
+ readFiles: [],
58
+ pinnedSkills: []
59
+ };
60
+ break;
61
+ case "message":
62
+ ensureState(state, sessionId);
63
+ state.messages.push(record.message);
64
+ state.updatedAt = record.timestamp;
65
+ break;
66
+ case "approval":
67
+ ensureState(state, sessionId);
68
+ applyApproval(state, record.approval);
69
+ state.updatedAt = record.approval.timestamp;
70
+ break;
71
+ case "reference":
72
+ ensureState(state, sessionId);
73
+ if (!state.referencedFiles.includes(record.path)) {
74
+ state.referencedFiles.push(record.path);
75
+ }
76
+ state.updatedAt = record.timestamp;
77
+ break;
78
+ case "read":
79
+ ensureState(state, sessionId);
80
+ if (!state.readFiles.includes(record.path)) {
81
+ state.readFiles.push(record.path);
82
+ }
83
+ if (!state.referencedFiles.includes(record.path)) {
84
+ state.referencedFiles.push(record.path);
85
+ }
86
+ state.updatedAt = record.timestamp;
87
+ break;
88
+ case "model":
89
+ ensureState(state, sessionId);
90
+ state.model = record.model;
91
+ state.updatedAt = record.timestamp;
92
+ break;
93
+ case "skill":
94
+ ensureState(state, sessionId);
95
+ applySkillRecord(state, record);
96
+ state.updatedAt = record.timestamp;
97
+ break;
98
+ default:
99
+ exhaustive(record);
100
+ }
101
+ }
102
+ if (!state) {
103
+ throw new Error(`Session ${sessionId} is missing a meta record.`);
104
+ }
105
+ return state;
106
+ }
107
+ async loadLatestForWorkspace(workspaceRoot) {
108
+ const latest = await this.readLatestWorkspaceMap();
109
+ const sessionId = latest[workspaceRoot];
110
+ if (!sessionId) {
111
+ return null;
112
+ }
113
+ try {
114
+ return await this.loadSession(sessionId);
115
+ }
116
+ catch (error) {
117
+ if (isMissingFile(error)) {
118
+ return null;
119
+ }
120
+ throw error;
121
+ }
122
+ }
123
+ async listSessions() {
124
+ const paths = await ensureAppPaths();
125
+ const entries = await readdir(paths.sessionsDir, { withFileTypes: true });
126
+ const ids = entries
127
+ .filter((entry) => entry.isFile() && entry.name.endsWith(".jsonl"))
128
+ .map((entry) => entry.name.replace(/\.jsonl$/, ""));
129
+ const sessions = await Promise.all(ids.map((id) => this.loadSession(id)));
130
+ return sessions
131
+ .map((session) => ({
132
+ id: session.id,
133
+ workspaceRoot: session.workspaceRoot,
134
+ model: session.model,
135
+ createdAt: session.createdAt,
136
+ updatedAt: session.updatedAt
137
+ }))
138
+ .sort((left, right) => right.updatedAt.localeCompare(left.updatedAt));
139
+ }
140
+ async appendMessage(session, message) {
141
+ const paths = await ensureAppPaths();
142
+ const record = {
143
+ type: "message",
144
+ timestamp: message.timestamp,
145
+ message
146
+ };
147
+ session.messages.push(message);
148
+ session.updatedAt = message.timestamp;
149
+ await appendFile(this.sessionPath(paths.sessionsDir, session.id), `${JSON.stringify(record)}\n`, "utf8");
150
+ await this.updateLatestWorkspace(session.workspaceRoot, session.id);
151
+ }
152
+ async appendApproval(session, approval) {
153
+ const paths = await ensureAppPaths();
154
+ const record = {
155
+ type: "approval",
156
+ approval
157
+ };
158
+ applyApproval(session, approval);
159
+ session.updatedAt = approval.timestamp;
160
+ await appendFile(this.sessionPath(paths.sessionsDir, session.id), `${JSON.stringify(record)}\n`, "utf8");
161
+ }
162
+ async appendReference(session, targetPath) {
163
+ if (session.referencedFiles.includes(targetPath)) {
164
+ return;
165
+ }
166
+ const paths = await ensureAppPaths();
167
+ const timestamp = new Date().toISOString();
168
+ const record = {
169
+ type: "reference",
170
+ path: targetPath,
171
+ timestamp
172
+ };
173
+ session.referencedFiles.push(targetPath);
174
+ session.updatedAt = timestamp;
175
+ await appendFile(this.sessionPath(paths.sessionsDir, session.id), `${JSON.stringify(record)}\n`, "utf8");
176
+ }
177
+ async appendReadFile(session, targetPath) {
178
+ if (session.readFiles.includes(targetPath)) {
179
+ return;
180
+ }
181
+ const paths = await ensureAppPaths();
182
+ const timestamp = new Date().toISOString();
183
+ const record = {
184
+ type: "read",
185
+ path: targetPath,
186
+ timestamp
187
+ };
188
+ session.readFiles.push(targetPath);
189
+ if (!session.referencedFiles.includes(targetPath)) {
190
+ session.referencedFiles.push(targetPath);
191
+ }
192
+ session.updatedAt = timestamp;
193
+ await appendFile(this.sessionPath(paths.sessionsDir, session.id), `${JSON.stringify(record)}\n`, "utf8");
194
+ await this.updateLatestWorkspace(session.workspaceRoot, session.id);
195
+ }
196
+ async updateModel(session, model) {
197
+ const paths = await ensureAppPaths();
198
+ const timestamp = new Date().toISOString();
199
+ const record = {
200
+ type: "model",
201
+ model,
202
+ timestamp
203
+ };
204
+ session.model = model;
205
+ session.updatedAt = timestamp;
206
+ await appendFile(this.sessionPath(paths.sessionsDir, session.id), `${JSON.stringify(record)}\n`, "utf8");
207
+ }
208
+ async pinSkill(session, skillName) {
209
+ if (session.pinnedSkills.includes(skillName)) {
210
+ return;
211
+ }
212
+ await this.appendSkillRecord(session, {
213
+ type: "skill",
214
+ action: "pin",
215
+ skillName,
216
+ timestamp: new Date().toISOString()
217
+ });
218
+ }
219
+ async unpinSkill(session, skillName) {
220
+ if (!session.pinnedSkills.includes(skillName)) {
221
+ return;
222
+ }
223
+ await this.appendSkillRecord(session, {
224
+ type: "skill",
225
+ action: "unpin",
226
+ skillName,
227
+ timestamp: new Date().toISOString()
228
+ });
229
+ }
230
+ async clearPinnedSkills(session) {
231
+ if (session.pinnedSkills.length === 0) {
232
+ return;
233
+ }
234
+ await this.appendSkillRecord(session, {
235
+ type: "skill",
236
+ action: "clear",
237
+ timestamp: new Date().toISOString()
238
+ });
239
+ }
240
+ async readLatestWorkspaceMap() {
241
+ const paths = await ensureAppPaths();
242
+ try {
243
+ const raw = await readFile(paths.latestWorkspaceFile, "utf8");
244
+ return JSON.parse(raw);
245
+ }
246
+ catch (error) {
247
+ if (isMissingFile(error)) {
248
+ return {};
249
+ }
250
+ throw error;
251
+ }
252
+ }
253
+ async updateLatestWorkspace(workspaceRoot, sessionId) {
254
+ const paths = await ensureAppPaths();
255
+ const latest = await this.readLatestWorkspaceMap();
256
+ latest[workspaceRoot] = sessionId;
257
+ await writeFile(paths.latestWorkspaceFile, `${JSON.stringify(latest, null, 2)}\n`, "utf8");
258
+ }
259
+ async appendSkillRecord(session, record) {
260
+ const paths = await ensureAppPaths();
261
+ applySkillRecord(session, record);
262
+ session.updatedAt = record.timestamp;
263
+ await appendFile(this.sessionPath(paths.sessionsDir, session.id), `${JSON.stringify(record)}\n`, "utf8");
264
+ await this.updateLatestWorkspace(session.workspaceRoot, session.id);
265
+ }
266
+ sessionPath(sessionsDir, sessionId) {
267
+ return path.join(sessionsDir, `${sessionId}.jsonl`);
268
+ }
269
+ }
270
+ function applyApproval(state, approval) {
271
+ if (approval.kind === "web_access") {
272
+ state.approvals.webAccess = true;
273
+ return;
274
+ }
275
+ if (approval.kind === "path_access") {
276
+ if (!state.approvals.outOfTreeRoots.includes(approval.key)) {
277
+ state.approvals.outOfTreeRoots.push(approval.key);
278
+ }
279
+ return;
280
+ }
281
+ if (!state.approvals.sessionActionKeys.includes(approval.key)) {
282
+ state.approvals.sessionActionKeys.push(approval.key);
283
+ }
284
+ }
285
+ function applySkillRecord(state, record) {
286
+ switch (record.action) {
287
+ case "pin":
288
+ if (record.skillName && !state.pinnedSkills.includes(record.skillName)) {
289
+ state.pinnedSkills.push(record.skillName);
290
+ }
291
+ break;
292
+ case "unpin":
293
+ if (record.skillName) {
294
+ state.pinnedSkills = state.pinnedSkills.filter((name) => name !== record.skillName);
295
+ }
296
+ break;
297
+ case "clear":
298
+ state.pinnedSkills = [];
299
+ break;
300
+ default:
301
+ exhaustive(record.action);
302
+ }
303
+ }
304
+ function createSessionId() {
305
+ return crypto.randomUUID();
306
+ }
307
+ function ensureState(state, sessionId) {
308
+ if (!state) {
309
+ throw new Error(`Session ${sessionId} is missing a meta record before other records.`);
310
+ }
311
+ }
312
+ function exhaustive(_) {
313
+ throw new Error("Unexpected session record.");
314
+ }
315
+ function isMissingFile(error) {
316
+ return error !== null && typeof error === "object" && "code" in error && error.code === "ENOENT";
317
+ }
318
+ //# sourceMappingURL=session-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-store.js","sourceRoot":"","sources":["../../src/session-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import { SessionStore } from "../session-store.js";
2
+ import type { SessionState } from "../types.js";
3
+ import type { LoadedSkillSummary, ReadSkillFileResult, SkillCatalogEntry, SkillToolApi } from "./types.js";
4
+ interface SkillRuntimeOptions {
5
+ getSession: () => SessionState;
6
+ sessionStore: SessionStore;
7
+ }
8
+ export declare class SkillRuntime implements SkillToolApi {
9
+ private readonly options;
10
+ private cachedRoot;
11
+ private cachedSkills;
12
+ constructor(options: SkillRuntimeOptions);
13
+ listSkills(): Promise<SkillCatalogEntry[]>;
14
+ loadSkill(name: string): Promise<LoadedSkillSummary>;
15
+ readSkillFile(name: string, relativePath?: string): Promise<ReadSkillFileResult>;
16
+ pinSkill(name: string): Promise<SkillCatalogEntry>;
17
+ unpinSkill(name: string): Promise<SkillCatalogEntry>;
18
+ clearPinnedSkills(): Promise<number>;
19
+ pinnedSkills(): Promise<SkillCatalogEntry[]>;
20
+ inventoryPrompt(): Promise<string>;
21
+ pinnedPrompt(): Promise<string | null>;
22
+ private ensureCatalog;
23
+ private requireSkill;
24
+ private resolveSkillRoot;
25
+ }
26
+ export {};
@@ -0,0 +1,317 @@
1
+ import path from "node:path";
2
+ import { access, readFile, readdir } from "node:fs/promises";
3
+ import { fileURLToPath } from "node:url";
4
+ const FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
5
+ const MAX_FILE_LIST = 24;
6
+ const MAX_LOAD_BODY_CHARS = 4_000;
7
+ const MAX_READ_CHARS = 12_000;
8
+ const MAX_HEADINGS = 8;
9
+ const MAX_LINKS = 12;
10
+ const MAX_PINNED_PROMPT_CHARS = 2_200;
11
+ export class SkillRuntime {
12
+ options;
13
+ cachedRoot = null;
14
+ cachedSkills = [];
15
+ constructor(options) {
16
+ this.options = options;
17
+ }
18
+ async listSkills() {
19
+ return [...await this.ensureCatalog()];
20
+ }
21
+ async loadSkill(name) {
22
+ const skill = await this.requireSkill(name);
23
+ const raw = await readFile(skill.entryPath, "utf8");
24
+ const body = stripFrontmatter(raw).trim();
25
+ const headings = extractHeadings(body);
26
+ const linkedFiles = extractLinkedFiles(body);
27
+ const excerpt = body.length > MAX_LOAD_BODY_CHARS
28
+ ? `${body.slice(0, MAX_LOAD_BODY_CHARS - 3).trimEnd()}...`
29
+ : body;
30
+ const overviewLines = [
31
+ `Skill: ${skill.name}`,
32
+ `Description: ${skill.description || "(none)"}`,
33
+ `Entry: ${skill.entryPath}`
34
+ ];
35
+ if (headings.length > 0) {
36
+ overviewLines.push(`Headings: ${headings.join(" | ")}`);
37
+ }
38
+ if (linkedFiles.length > 0) {
39
+ overviewLines.push(`Linked files: ${linkedFiles.join(", ")}`);
40
+ }
41
+ if (skill.availableFiles.length > 0) {
42
+ overviewLines.push(`Available files: ${formatList(skill.availableFiles, 8)}`);
43
+ }
44
+ if (excerpt) {
45
+ overviewLines.push("", excerpt);
46
+ }
47
+ return {
48
+ ...skill,
49
+ headings,
50
+ linkedFiles,
51
+ overview: overviewLines.join("\n")
52
+ };
53
+ }
54
+ async readSkillFile(name, relativePath = "SKILL.md") {
55
+ const skill = await this.requireSkill(name);
56
+ const targetPath = resolveSkillPath(skill.rootPath, relativePath);
57
+ const buffer = await readFile(targetPath);
58
+ if (buffer.includes(0)) {
59
+ throw new Error(`Skill file is binary and cannot be read as text: ${relativePath}`);
60
+ }
61
+ const content = buffer.toString("utf8");
62
+ return {
63
+ path: targetPath,
64
+ content: content.length > MAX_READ_CHARS
65
+ ? `${content.slice(0, MAX_READ_CHARS - 3).trimEnd()}...`
66
+ : content
67
+ };
68
+ }
69
+ async pinSkill(name) {
70
+ const skill = await this.requireSkill(name);
71
+ await this.options.sessionStore.pinSkill(this.options.getSession(), skill.name);
72
+ return skill;
73
+ }
74
+ async unpinSkill(name) {
75
+ const skill = await this.requireSkill(name);
76
+ await this.options.sessionStore.unpinSkill(this.options.getSession(), skill.name);
77
+ return skill;
78
+ }
79
+ async clearPinnedSkills() {
80
+ const pinnedCount = this.options.getSession().pinnedSkills.length;
81
+ await this.options.sessionStore.clearPinnedSkills(this.options.getSession());
82
+ return pinnedCount;
83
+ }
84
+ async pinnedSkills() {
85
+ const pinned = new Set(this.options.getSession().pinnedSkills);
86
+ const catalog = await this.ensureCatalog();
87
+ return catalog.filter((skill) => pinned.has(skill.name));
88
+ }
89
+ async inventoryPrompt() {
90
+ const skills = await this.ensureCatalog();
91
+ if (skills.length === 0) {
92
+ return "No local skills are available in the skill/ directory.";
93
+ }
94
+ return [
95
+ "Local skills are available through the skill tool. Use `skill` when a request matches one of these domains:",
96
+ ...skills.map((skill) => `- ${skill.name}: ${shorten(skill.description, 160)}`)
97
+ ].join("\n");
98
+ }
99
+ async pinnedPrompt() {
100
+ const skills = await this.pinnedSkills();
101
+ if (skills.length === 0) {
102
+ return null;
103
+ }
104
+ const lines = ["Pinned skills remain active across context compaction:"];
105
+ for (const skill of skills) {
106
+ const loaded = await this.loadSkill(skill.name);
107
+ lines.push(`- ${skill.name}: ${shorten(skill.description, 160)}`);
108
+ if (loaded.headings.length > 0) {
109
+ lines.push(` sections: ${formatList(loaded.headings, 4)}`);
110
+ }
111
+ if (loaded.linkedFiles.length > 0) {
112
+ lines.push(` files: ${formatList(loaded.linkedFiles, 4)}`);
113
+ }
114
+ if (lines.join("\n").length > MAX_PINNED_PROMPT_CHARS) {
115
+ break;
116
+ }
117
+ }
118
+ return lines.join("\n");
119
+ }
120
+ async ensureCatalog() {
121
+ const root = await this.resolveSkillRoot();
122
+ if (!root) {
123
+ this.cachedRoot = null;
124
+ this.cachedSkills = [];
125
+ return this.cachedSkills;
126
+ }
127
+ if (this.cachedRoot === root) {
128
+ return this.cachedSkills;
129
+ }
130
+ const entries = await readdir(root, { withFileTypes: true });
131
+ const skills = [];
132
+ for (const entry of entries) {
133
+ if (!entry.isDirectory() || entry.name.startsWith(".")) {
134
+ continue;
135
+ }
136
+ const skillRoot = path.join(root, entry.name);
137
+ const entryPath = path.join(skillRoot, "SKILL.md");
138
+ if (!await exists(entryPath)) {
139
+ continue;
140
+ }
141
+ const raw = await readFile(entryPath, "utf8");
142
+ const frontmatter = parseFrontmatter(raw);
143
+ skills.push({
144
+ name: frontmatter.name || entry.name,
145
+ description: frontmatter.description || "",
146
+ rootPath: skillRoot,
147
+ entryPath,
148
+ availableFiles: await listSkillFiles(skillRoot)
149
+ });
150
+ }
151
+ skills.sort((left, right) => left.name.localeCompare(right.name));
152
+ this.cachedRoot = root;
153
+ this.cachedSkills = skills;
154
+ return this.cachedSkills;
155
+ }
156
+ async requireSkill(name) {
157
+ const normalized = name.trim();
158
+ if (!normalized) {
159
+ throw new Error("Skill name is required.");
160
+ }
161
+ const skills = await this.ensureCatalog();
162
+ const match = skills.find((skill) => skill.name === normalized);
163
+ if (!match) {
164
+ throw new Error(`Unknown skill: ${normalized}`);
165
+ }
166
+ return match;
167
+ }
168
+ async resolveSkillRoot() {
169
+ const envRoot = process.env.VETALA_SKILL_ROOT?.trim() || process.env.TATTVA_SKILL_ROOT?.trim();
170
+ if (envRoot) {
171
+ return await existsDirectory(path.resolve(envRoot)) ? path.resolve(envRoot) : null;
172
+ }
173
+ const workspaceRoot = this.options.getSession().workspaceRoot;
174
+ const workspaceSkillRoot = path.join(workspaceRoot, "skill");
175
+ if (await existsDirectory(workspaceSkillRoot)) {
176
+ return workspaceSkillRoot;
177
+ }
178
+ return findBundledSkillRoot();
179
+ }
180
+ }
181
+ async function listSkillFiles(skillRoot) {
182
+ const files = [];
183
+ await walkFiles(skillRoot, skillRoot, files);
184
+ files.sort((left, right) => left.localeCompare(right));
185
+ return files.slice(0, MAX_FILE_LIST);
186
+ }
187
+ async function walkFiles(root, current, output) {
188
+ const entries = await readdir(current, { withFileTypes: true });
189
+ for (const entry of entries) {
190
+ if (entry.name.startsWith(".")) {
191
+ continue;
192
+ }
193
+ const target = path.join(current, entry.name);
194
+ if (entry.isDirectory()) {
195
+ await walkFiles(root, target, output);
196
+ continue;
197
+ }
198
+ output.push(path.relative(root, target).split(path.sep).join("/"));
199
+ }
200
+ }
201
+ function parseFrontmatter(raw) {
202
+ const match = raw.match(FRONTMATTER_RE);
203
+ if (!match) {
204
+ return { name: "", description: "" };
205
+ }
206
+ const values = new Map();
207
+ let currentKey = null;
208
+ for (const line of (match[1] ?? "").split(/\r?\n/)) {
209
+ const kv = line.match(/^([A-Za-z0-9_-]+):\s*(.*)$/);
210
+ if (kv) {
211
+ const [, key = "", rawValue = ""] = kv;
212
+ currentKey = key || null;
213
+ if (!currentKey) {
214
+ continue;
215
+ }
216
+ values.set(currentKey, stripQuotes(rawValue.trim()));
217
+ continue;
218
+ }
219
+ if (currentKey && /^\s+/.test(line)) {
220
+ const currentValue = values.get(currentKey) ?? "";
221
+ const nextPart = stripQuotes(line.trim());
222
+ values.set(currentKey, currentValue ? `${currentValue} ${nextPart}` : nextPart);
223
+ continue;
224
+ }
225
+ currentKey = null;
226
+ }
227
+ return {
228
+ name: values.get("name") ?? "",
229
+ description: values.get("description") ?? ""
230
+ };
231
+ }
232
+ function stripFrontmatter(raw) {
233
+ return raw.replace(FRONTMATTER_RE, "");
234
+ }
235
+ function extractHeadings(body) {
236
+ return body
237
+ .split(/\r?\n/)
238
+ .map((line) => line.match(/^##+\s+(.*)$/)?.[1]?.trim() ?? null)
239
+ .filter((value) => Boolean(value))
240
+ .slice(0, MAX_HEADINGS);
241
+ }
242
+ function extractLinkedFiles(body) {
243
+ const links = new Set();
244
+ const re = /\[[^\]]+\]\(([^)]+)\)/g;
245
+ let match;
246
+ while ((match = re.exec(body)) !== null) {
247
+ const target = match[1]?.trim();
248
+ if (!target || target.startsWith("http://") || target.startsWith("https://") || target.startsWith("#")) {
249
+ continue;
250
+ }
251
+ links.add(target);
252
+ if (links.size >= MAX_LINKS) {
253
+ break;
254
+ }
255
+ }
256
+ return [...links];
257
+ }
258
+ function resolveSkillPath(skillRoot, relativePath) {
259
+ const normalized = relativePath.trim() || "SKILL.md";
260
+ if (path.isAbsolute(normalized)) {
261
+ throw new Error("Skill paths must be relative to the skill root.");
262
+ }
263
+ const resolved = path.resolve(skillRoot, normalized);
264
+ const rootWithSep = skillRoot.endsWith(path.sep) ? skillRoot : `${skillRoot}${path.sep}`;
265
+ if (resolved !== skillRoot && !resolved.startsWith(rootWithSep)) {
266
+ throw new Error(`Skill path escapes the skill root: ${relativePath}`);
267
+ }
268
+ return resolved;
269
+ }
270
+ async function findBundledSkillRoot() {
271
+ let current = path.dirname(fileURLToPath(import.meta.url));
272
+ while (true) {
273
+ const candidate = path.join(current, "skill");
274
+ if (await existsDirectory(candidate)) {
275
+ return candidate;
276
+ }
277
+ const parent = path.dirname(current);
278
+ if (parent === current) {
279
+ return null;
280
+ }
281
+ current = parent;
282
+ }
283
+ }
284
+ async function exists(targetPath) {
285
+ try {
286
+ await access(targetPath);
287
+ return true;
288
+ }
289
+ catch {
290
+ return false;
291
+ }
292
+ }
293
+ async function existsDirectory(targetPath) {
294
+ try {
295
+ const entries = await readdir(targetPath);
296
+ return Array.isArray(entries);
297
+ }
298
+ catch {
299
+ return false;
300
+ }
301
+ }
302
+ function shorten(value, maxLength) {
303
+ const compact = value.replace(/\s+/g, " ").trim();
304
+ if (!compact) {
305
+ return "(no description)";
306
+ }
307
+ return compact.length > maxLength ? `${compact.slice(0, maxLength - 3)}...` : compact;
308
+ }
309
+ function formatList(values, limit) {
310
+ const visible = values.slice(0, limit);
311
+ const extra = values.length - visible.length;
312
+ return `${visible.join(", ")}${extra > 0 ? `, and ${extra} more` : ""}`;
313
+ }
314
+ function stripQuotes(value) {
315
+ return value.replace(/^['"]|['"]$/g, "");
316
+ }
317
+ //# sourceMappingURL=runtime.js.map