@soederpop/luca 0.0.2

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 (358) hide show
  1. package/CLAUDE.md +71 -0
  2. package/README.md +78 -0
  3. package/bun.lock +2928 -0
  4. package/bunfig.toml +3 -0
  5. package/commands/audit-docs.ts +740 -0
  6. package/commands/build-scaffolds.ts +154 -0
  7. package/commands/generate-api-docs.ts +114 -0
  8. package/commands/update-introspection.ts +67 -0
  9. package/docs/CLI.md +335 -0
  10. package/docs/README.md +88 -0
  11. package/docs/TABLE-OF-CONTENTS.md +157 -0
  12. package/docs/apis/clients/elevenlabs.md +84 -0
  13. package/docs/apis/clients/graph.md +56 -0
  14. package/docs/apis/clients/openai.md +69 -0
  15. package/docs/apis/clients/rest.md +41 -0
  16. package/docs/apis/clients/websocket.md +107 -0
  17. package/docs/apis/features/agi/assistant.md +471 -0
  18. package/docs/apis/features/agi/assistants-manager.md +154 -0
  19. package/docs/apis/features/agi/claude-code.md +602 -0
  20. package/docs/apis/features/agi/conversation-history.md +352 -0
  21. package/docs/apis/features/agi/conversation.md +333 -0
  22. package/docs/apis/features/agi/docs-reader.md +121 -0
  23. package/docs/apis/features/agi/openai-codex.md +318 -0
  24. package/docs/apis/features/agi/openapi.md +138 -0
  25. package/docs/apis/features/agi/semantic-search.md +387 -0
  26. package/docs/apis/features/agi/skills-library.md +216 -0
  27. package/docs/apis/features/node/container-link.md +133 -0
  28. package/docs/apis/features/node/content-db.md +313 -0
  29. package/docs/apis/features/node/disk-cache.md +379 -0
  30. package/docs/apis/features/node/dns.md +651 -0
  31. package/docs/apis/features/node/docker.md +705 -0
  32. package/docs/apis/features/node/downloader.md +81 -0
  33. package/docs/apis/features/node/esbuild.md +59 -0
  34. package/docs/apis/features/node/file-manager.md +182 -0
  35. package/docs/apis/features/node/fs.md +581 -0
  36. package/docs/apis/features/node/git.md +330 -0
  37. package/docs/apis/features/node/google-auth.md +174 -0
  38. package/docs/apis/features/node/google-calendar.md +187 -0
  39. package/docs/apis/features/node/google-docs.md +151 -0
  40. package/docs/apis/features/node/google-drive.md +225 -0
  41. package/docs/apis/features/node/google-sheets.md +179 -0
  42. package/docs/apis/features/node/grep.md +290 -0
  43. package/docs/apis/features/node/helpers.md +135 -0
  44. package/docs/apis/features/node/ink.md +334 -0
  45. package/docs/apis/features/node/ipc-socket.md +260 -0
  46. package/docs/apis/features/node/json-tree.md +86 -0
  47. package/docs/apis/features/node/launcher-app-command-listener.md +145 -0
  48. package/docs/apis/features/node/networking.md +281 -0
  49. package/docs/apis/features/node/nlp.md +133 -0
  50. package/docs/apis/features/node/opener.md +97 -0
  51. package/docs/apis/features/node/os.md +118 -0
  52. package/docs/apis/features/node/package-finder.md +402 -0
  53. package/docs/apis/features/node/postgres.md +212 -0
  54. package/docs/apis/features/node/proc.md +430 -0
  55. package/docs/apis/features/node/process-manager.md +210 -0
  56. package/docs/apis/features/node/python.md +278 -0
  57. package/docs/apis/features/node/repl.md +88 -0
  58. package/docs/apis/features/node/runpod.md +673 -0
  59. package/docs/apis/features/node/secure-shell.md +169 -0
  60. package/docs/apis/features/node/semantic-search.md +401 -0
  61. package/docs/apis/features/node/sqlite.md +211 -0
  62. package/docs/apis/features/node/telegram.md +254 -0
  63. package/docs/apis/features/node/tts.md +118 -0
  64. package/docs/apis/features/node/ui.md +703 -0
  65. package/docs/apis/features/node/vault.md +64 -0
  66. package/docs/apis/features/node/vm.md +84 -0
  67. package/docs/apis/features/node/window-manager.md +337 -0
  68. package/docs/apis/features/node/yaml-tree.md +85 -0
  69. package/docs/apis/features/node/yaml.md +176 -0
  70. package/docs/apis/features/web/asset-loader.md +47 -0
  71. package/docs/apis/features/web/container-link.md +133 -0
  72. package/docs/apis/features/web/esbuild.md +59 -0
  73. package/docs/apis/features/web/helpers.md +135 -0
  74. package/docs/apis/features/web/network.md +30 -0
  75. package/docs/apis/features/web/speech.md +55 -0
  76. package/docs/apis/features/web/vault.md +64 -0
  77. package/docs/apis/features/web/vm.md +84 -0
  78. package/docs/apis/features/web/voice.md +67 -0
  79. package/docs/apis/servers/express.md +127 -0
  80. package/docs/apis/servers/mcp.md +213 -0
  81. package/docs/apis/servers/websocket.md +99 -0
  82. package/docs/documentation-audit.md +134 -0
  83. package/docs/examples/content-db.md +77 -0
  84. package/docs/examples/disk-cache.md +83 -0
  85. package/docs/examples/docker.md +101 -0
  86. package/docs/examples/downloader.md +70 -0
  87. package/docs/examples/esbuild.md +80 -0
  88. package/docs/examples/file-manager.md +82 -0
  89. package/docs/examples/fs.md +83 -0
  90. package/docs/examples/git.md +85 -0
  91. package/docs/examples/google-auth.md +88 -0
  92. package/docs/examples/google-calendar.md +94 -0
  93. package/docs/examples/google-docs.md +82 -0
  94. package/docs/examples/google-drive.md +96 -0
  95. package/docs/examples/google-sheets.md +95 -0
  96. package/docs/examples/grep.md +85 -0
  97. package/docs/examples/ink-blocks.md +75 -0
  98. package/docs/examples/ink-renderer.md +41 -0
  99. package/docs/examples/ink.md +103 -0
  100. package/docs/examples/ipc-socket.md +103 -0
  101. package/docs/examples/json-tree.md +91 -0
  102. package/docs/examples/launcher-app-command-listener.md +120 -0
  103. package/docs/examples/networking.md +58 -0
  104. package/docs/examples/nlp.md +91 -0
  105. package/docs/examples/opener.md +78 -0
  106. package/docs/examples/os.md +72 -0
  107. package/docs/examples/package-finder.md +89 -0
  108. package/docs/examples/port-exposer.md +89 -0
  109. package/docs/examples/postgres.md +91 -0
  110. package/docs/examples/proc.md +81 -0
  111. package/docs/examples/process-manager.md +79 -0
  112. package/docs/examples/python.md +91 -0
  113. package/docs/examples/repl.md +93 -0
  114. package/docs/examples/runpod.md +119 -0
  115. package/docs/examples/secure-shell.md +92 -0
  116. package/docs/examples/sqlite.md +86 -0
  117. package/docs/examples/telegram.md +77 -0
  118. package/docs/examples/tts.md +86 -0
  119. package/docs/examples/ui.md +80 -0
  120. package/docs/examples/vault.md +70 -0
  121. package/docs/examples/vm.md +86 -0
  122. package/docs/examples/window-manager.md +125 -0
  123. package/docs/examples/yaml-tree.md +93 -0
  124. package/docs/examples/yaml.md +104 -0
  125. package/docs/ideas/class-registration-refactor-possibilities.md +197 -0
  126. package/docs/ideas/container-use-api.md +9 -0
  127. package/docs/ideas/easy-auth-for-express-servers-and-luca-serve.md +0 -0
  128. package/docs/ideas/feature-stacks.md +22 -0
  129. package/docs/ideas/luca-cli-self-sufficiency-demo.md +23 -0
  130. package/docs/ideas/mcp-design.md +9 -0
  131. package/docs/ideas/web-container-debugging-feature.md +13 -0
  132. package/docs/introspection-audit.md +49 -0
  133. package/docs/introspection.md +154 -0
  134. package/docs/mcp/readme.md +162 -0
  135. package/docs/models.ts +38 -0
  136. package/docs/philosophy.md +85 -0
  137. package/docs/principles.md +7 -0
  138. package/docs/prompts/audit-codebase-for-failures-to-use-the-container.md +34 -0
  139. package/docs/prompts/mcp-test-easy-command.md +27 -0
  140. package/docs/reports/assistant-bugs.md +38 -0
  141. package/docs/reports/attach-pattern-usage.md +18 -0
  142. package/docs/reports/code-audit-results.md +391 -0
  143. package/docs/reports/introspection-audit-tasks.md +378 -0
  144. package/docs/reports/luca-mcp-improvements.md +128 -0
  145. package/docs/scaffolds/client.md +140 -0
  146. package/docs/scaffolds/command.md +106 -0
  147. package/docs/scaffolds/endpoint.md +176 -0
  148. package/docs/scaffolds/feature.md +148 -0
  149. package/docs/scaffolds/server.md +187 -0
  150. package/docs/tasks/web-container-helper-discovery.md +71 -0
  151. package/docs/todos.md +1 -0
  152. package/docs/tutorials/01-getting-started.md +106 -0
  153. package/docs/tutorials/02-container.md +210 -0
  154. package/docs/tutorials/03-scripts.md +194 -0
  155. package/docs/tutorials/04-features-overview.md +196 -0
  156. package/docs/tutorials/05-state-and-events.md +171 -0
  157. package/docs/tutorials/06-servers.md +157 -0
  158. package/docs/tutorials/07-endpoints.md +198 -0
  159. package/docs/tutorials/08-commands.md +171 -0
  160. package/docs/tutorials/09-clients.md +162 -0
  161. package/docs/tutorials/10-creating-features.md +198 -0
  162. package/docs/tutorials/11-contentbase.md +191 -0
  163. package/docs/tutorials/12-assistants.md +215 -0
  164. package/docs/tutorials/13-introspection.md +147 -0
  165. package/docs/tutorials/14-type-system.md +174 -0
  166. package/docs/tutorials/15-project-patterns.md +222 -0
  167. package/docs/tutorials/16-google-features.md +534 -0
  168. package/docs/tutorials/17-tui-blocks.md +530 -0
  169. package/docs/tutorials/18-semantic-search.md +334 -0
  170. package/index.ts +1 -0
  171. package/luca.console.ts +9 -0
  172. package/main.py +6 -0
  173. package/package.json +154 -0
  174. package/pyproject.toml +7 -0
  175. package/scripts/animations/chrome-glitch.ts +55 -0
  176. package/scripts/animations/index.ts +16 -0
  177. package/scripts/animations/neon-pulse.ts +64 -0
  178. package/scripts/animations/types.ts +6 -0
  179. package/scripts/build-web.ts +28 -0
  180. package/scripts/examples/ask-luca-expert.ts +42 -0
  181. package/scripts/examples/assistant-questions.ts +12 -0
  182. package/scripts/examples/excalidraw-expert.ts +75 -0
  183. package/scripts/examples/expert-chat.ts +0 -0
  184. package/scripts/examples/file-manager.ts +14 -0
  185. package/scripts/examples/ideas.ts +12 -0
  186. package/scripts/examples/interactive-chat.ts +20 -0
  187. package/scripts/examples/openai-tool-calls.ts +113 -0
  188. package/scripts/examples/opening-a-web-browser.ts +5 -0
  189. package/scripts/examples/telegram-bot.ts +79 -0
  190. package/scripts/examples/telegram-ink-ui.ts +302 -0
  191. package/scripts/examples/using-assistant-with-mcp.ts +560 -0
  192. package/scripts/examples/using-claude-code.ts +10 -0
  193. package/scripts/examples/using-contentdb.ts +35 -0
  194. package/scripts/examples/using-conversations.ts +35 -0
  195. package/scripts/examples/using-disk-cache.ts +10 -0
  196. package/scripts/examples/using-docker-shell.ts +75 -0
  197. package/scripts/examples/using-elevenlabs.ts +25 -0
  198. package/scripts/examples/using-google-calendar.ts +57 -0
  199. package/scripts/examples/using-google-docs.ts +74 -0
  200. package/scripts/examples/using-google-drive.ts +74 -0
  201. package/scripts/examples/using-google-sheets.ts +89 -0
  202. package/scripts/examples/using-nlp.ts +55 -0
  203. package/scripts/examples/using-ollama.ts +10 -0
  204. package/scripts/examples/using-openai-codex.ts +23 -0
  205. package/scripts/examples/using-postgres.ts +55 -0
  206. package/scripts/examples/using-runpod.ts +32 -0
  207. package/scripts/examples/using-tts.ts +40 -0
  208. package/scripts/examples/vm-loading-esm-modules.ts +16 -0
  209. package/scripts/scaffold.ts +391 -0
  210. package/scripts/scratch.ts +15 -0
  211. package/scripts/test-command-listener.ts +123 -0
  212. package/scripts/test-window-manager-lifecycle.ts +86 -0
  213. package/scripts/test-window-manager.ts +43 -0
  214. package/scripts/update-introspection-data.ts +58 -0
  215. package/src/agi/README.md +14 -0
  216. package/src/agi/container.server.ts +114 -0
  217. package/src/agi/endpoints/ask.ts +60 -0
  218. package/src/agi/endpoints/conversations/[id].ts +45 -0
  219. package/src/agi/endpoints/conversations.ts +31 -0
  220. package/src/agi/endpoints/experts.ts +37 -0
  221. package/src/agi/features/assistant.ts +767 -0
  222. package/src/agi/features/assistants-manager.ts +260 -0
  223. package/src/agi/features/claude-code.ts +1111 -0
  224. package/src/agi/features/conversation-history.ts +497 -0
  225. package/src/agi/features/conversation.ts +799 -0
  226. package/src/agi/features/openai-codex.ts +631 -0
  227. package/src/agi/features/openapi.ts +438 -0
  228. package/src/agi/features/skills-library.ts +425 -0
  229. package/src/agi/index.ts +6 -0
  230. package/src/agi/lib/token-counter.ts +122 -0
  231. package/src/browser.ts +25 -0
  232. package/src/bus.ts +100 -0
  233. package/src/cli/cli.ts +70 -0
  234. package/src/client.ts +461 -0
  235. package/src/clients/civitai/index.ts +541 -0
  236. package/src/clients/client-template.ts +41 -0
  237. package/src/clients/comfyui/index.ts +597 -0
  238. package/src/clients/elevenlabs/index.ts +291 -0
  239. package/src/clients/openai/index.ts +451 -0
  240. package/src/clients/supabase/index.ts +366 -0
  241. package/src/command.ts +164 -0
  242. package/src/commands/chat.ts +182 -0
  243. package/src/commands/console.ts +192 -0
  244. package/src/commands/describe.ts +433 -0
  245. package/src/commands/eval.ts +116 -0
  246. package/src/commands/help.ts +214 -0
  247. package/src/commands/index.ts +14 -0
  248. package/src/commands/mcp.ts +64 -0
  249. package/src/commands/prompt.ts +807 -0
  250. package/src/commands/run.ts +257 -0
  251. package/src/commands/sandbox-mcp.ts +439 -0
  252. package/src/commands/scaffold.ts +79 -0
  253. package/src/commands/serve.ts +172 -0
  254. package/src/container.ts +781 -0
  255. package/src/endpoint.ts +340 -0
  256. package/src/feature.ts +75 -0
  257. package/src/hash-object.ts +97 -0
  258. package/src/helper.ts +543 -0
  259. package/src/introspection/generated.agi.ts +23388 -0
  260. package/src/introspection/generated.node.ts +18899 -0
  261. package/src/introspection/generated.web.ts +2021 -0
  262. package/src/introspection/index.ts +256 -0
  263. package/src/introspection/scan.ts +912 -0
  264. package/src/node/container.ts +354 -0
  265. package/src/node/feature.ts +13 -0
  266. package/src/node/features/container-link.ts +558 -0
  267. package/src/node/features/content-db.ts +475 -0
  268. package/src/node/features/disk-cache.ts +382 -0
  269. package/src/node/features/dns.ts +655 -0
  270. package/src/node/features/docker.ts +912 -0
  271. package/src/node/features/downloader.ts +92 -0
  272. package/src/node/features/esbuild.ts +68 -0
  273. package/src/node/features/file-manager.ts +357 -0
  274. package/src/node/features/fs.ts +534 -0
  275. package/src/node/features/git.ts +492 -0
  276. package/src/node/features/google-auth.ts +502 -0
  277. package/src/node/features/google-calendar.ts +300 -0
  278. package/src/node/features/google-docs.ts +404 -0
  279. package/src/node/features/google-drive.ts +339 -0
  280. package/src/node/features/google-sheets.ts +279 -0
  281. package/src/node/features/grep.ts +406 -0
  282. package/src/node/features/helpers.ts +374 -0
  283. package/src/node/features/ink.ts +490 -0
  284. package/src/node/features/ipc-socket.ts +459 -0
  285. package/src/node/features/json-tree.ts +188 -0
  286. package/src/node/features/launcher-app-command-listener.ts +388 -0
  287. package/src/node/features/networking.ts +925 -0
  288. package/src/node/features/nlp.ts +211 -0
  289. package/src/node/features/opener.ts +166 -0
  290. package/src/node/features/os.ts +157 -0
  291. package/src/node/features/package-finder.ts +539 -0
  292. package/src/node/features/port-exposer.ts +342 -0
  293. package/src/node/features/postgres.ts +273 -0
  294. package/src/node/features/proc.ts +502 -0
  295. package/src/node/features/process-manager.ts +542 -0
  296. package/src/node/features/python.ts +444 -0
  297. package/src/node/features/repl.ts +194 -0
  298. package/src/node/features/runpod.ts +802 -0
  299. package/src/node/features/secure-shell.ts +248 -0
  300. package/src/node/features/semantic-search.ts +924 -0
  301. package/src/node/features/sqlite.ts +289 -0
  302. package/src/node/features/telegram.ts +342 -0
  303. package/src/node/features/tts.ts +184 -0
  304. package/src/node/features/ui.ts +857 -0
  305. package/src/node/features/vault.ts +164 -0
  306. package/src/node/features/vm.ts +312 -0
  307. package/src/node/features/window-manager.ts +804 -0
  308. package/src/node/features/yaml-tree.ts +149 -0
  309. package/src/node/features/yaml.ts +132 -0
  310. package/src/node.ts +70 -0
  311. package/src/react/index.ts +175 -0
  312. package/src/registry.ts +199 -0
  313. package/src/scaffolds/generated.ts +1613 -0
  314. package/src/scaffolds/template.ts +37 -0
  315. package/src/schemas/base.ts +255 -0
  316. package/src/server.ts +135 -0
  317. package/src/servers/express.ts +209 -0
  318. package/src/servers/mcp.ts +805 -0
  319. package/src/servers/socket.ts +120 -0
  320. package/src/state.ts +101 -0
  321. package/src/web/clients/socket.ts +82 -0
  322. package/src/web/container.ts +74 -0
  323. package/src/web/extension.ts +30 -0
  324. package/src/web/feature.ts +12 -0
  325. package/src/web/features/asset-loader.ts +64 -0
  326. package/src/web/features/container-link.ts +385 -0
  327. package/src/web/features/esbuild.ts +79 -0
  328. package/src/web/features/helpers.ts +267 -0
  329. package/src/web/features/network.ts +61 -0
  330. package/src/web/features/speech.ts +87 -0
  331. package/src/web/features/vault.ts +189 -0
  332. package/src/web/features/vm.ts +78 -0
  333. package/src/web/features/voice-recognition.ts +129 -0
  334. package/src/web/shims/isomorphic-vm.ts +149 -0
  335. package/test/bus.test.ts +134 -0
  336. package/test/clients-servers.test.ts +216 -0
  337. package/test/container-link.test.ts +274 -0
  338. package/test/features.test.ts +160 -0
  339. package/test/integration.test.ts +787 -0
  340. package/test/node-container.test.ts +121 -0
  341. package/test/rate-limit.test.ts +272 -0
  342. package/test/semantic-search.test.ts +550 -0
  343. package/test/state.test.ts +121 -0
  344. package/test-integration/assistant.test.ts +138 -0
  345. package/test-integration/assistants-manager.test.ts +123 -0
  346. package/test-integration/claude-code.test.ts +98 -0
  347. package/test-integration/conversation-history.test.ts +205 -0
  348. package/test-integration/conversation.test.ts +137 -0
  349. package/test-integration/elevenlabs.test.ts +55 -0
  350. package/test-integration/google-services.test.ts +80 -0
  351. package/test-integration/helpers.ts +89 -0
  352. package/test-integration/openai-codex.test.ts +93 -0
  353. package/test-integration/runpod.test.ts +58 -0
  354. package/test-integration/server-endpoints.test.ts +97 -0
  355. package/test-integration/skills-library.test.ts +157 -0
  356. package/test-integration/telegram.test.ts +46 -0
  357. package/tsconfig.json +58 -0
  358. package/uv.lock +8 -0
@@ -0,0 +1,211 @@
1
+ import { z } from 'zod'
2
+ import { Feature, features } from '../feature.js'
3
+ import { FeatureStateSchema, FeatureOptionsSchema } from '../../schemas/base.js'
4
+ import compromise from 'compromise'
5
+ import winkNLP from 'wink-nlp'
6
+ import model from 'wink-eng-lite-web-model'
7
+
8
+ export const NLPStateSchema = FeatureStateSchema.extend({
9
+ parseCalls: z.number().default(0).describe('Total parse() invocations'),
10
+ analyzeCalls: z.number().default(0).describe('Total analyze() invocations'),
11
+ })
12
+
13
+ export const NLPOptionsSchema = FeatureOptionsSchema.extend({})
14
+
15
+ export const ParsedCommandSchema = z.object({
16
+ intent: z.string().nullable().describe('The normalized verb/action (infinitive form)'),
17
+ target: z.string().nullable().describe('The primary noun/object'),
18
+ subject: z.string().nullable().describe('Secondary noun from prepositional phrase'),
19
+ modifiers: z.array(z.string()).describe('Adjectives and adverbs'),
20
+ raw: z.string().describe('Original input text'),
21
+ })
22
+
23
+ export const AnalysisSchema = z.object({
24
+ tokens: z.array(z.object({
25
+ value: z.string(),
26
+ pos: z.string(),
27
+ })).describe('POS-tagged tokens (Universal POS tagset)'),
28
+ entities: z.array(z.object({
29
+ value: z.string(),
30
+ type: z.string(),
31
+ })).describe('Recognized named entities'),
32
+ raw: z.string(),
33
+ })
34
+
35
+ export type ParsedCommand = z.infer<typeof ParsedCommandSchema>
36
+ export type Analysis = z.infer<typeof AnalysisSchema>
37
+
38
+ /**
39
+ * The NLP feature provides natural language processing utilities for parsing
40
+ * utterances into structured data. Combines two complementary libraries:
41
+ *
42
+ * - **compromise**: Verb normalization (toInfinitive), POS pattern matching
43
+ * - **wink-nlp**: High-accuracy POS tagging (~95%), named entity recognition
44
+ *
45
+ * Three methods at increasing levels of detail:
46
+ * - `parse()` — compromise-powered quick structure + verb normalization
47
+ * - `analyze()` — wink-powered high-accuracy POS + entity extraction
48
+ * - `understand()` — combined parse + analyze merged
49
+ *
50
+ * @example
51
+ * ```typescript
52
+ * const nlp = container.feature('nlp', { enable: true })
53
+ *
54
+ * nlp.parse("draw a diagram of the auth flow")
55
+ * // { intent: "draw", target: "diagram", subject: "auth flow", modifiers: [], raw: "..." }
56
+ *
57
+ * nlp.analyze("meet john at 3pm about the deployment")
58
+ * // { tokens: [{value:"meet",pos:"VERB"}, ...], entities: [{value:"john",type:"PERSON"}, ...] }
59
+ *
60
+ * nlp.understand("draw a diagram of the auth flow")
61
+ * // { intent, target, subject, modifiers, tokens, entities, raw }
62
+ * ```
63
+ */
64
+ export class NLP extends Feature<z.infer<typeof NLPStateSchema>, z.infer<typeof NLPOptionsSchema>> {
65
+ static override shortcut = 'features.nlp' as const
66
+ static override stateSchema = NLPStateSchema
67
+ static override optionsSchema = NLPOptionsSchema
68
+
69
+ private _wink?: ReturnType<typeof winkNLP>
70
+
71
+ /** Lazily initializes the wink-nlp instance on first use. */
72
+ private get wink(): ReturnType<typeof winkNLP> {
73
+ if (!this._wink) {
74
+ this._wink = winkNLP(model)
75
+ }
76
+ return this._wink
77
+ }
78
+
79
+ /**
80
+ * Parse an utterance into structured command data using compromise.
81
+ * Extracts intent (normalized verb), target noun, prepositional subject, and modifiers.
82
+ *
83
+ * @param text - The raw utterance to parse
84
+ * @returns Parsed command structure with intent, target, subject, modifiers
85
+ *
86
+ * @example
87
+ * ```typescript
88
+ * nlp.parse("open the terminal")
89
+ * // { intent: "open", target: "terminal", subject: null, modifiers: [], raw: "open the terminal" }
90
+ *
91
+ * nlp.parse("draw a diagram of the auth flow")
92
+ * // { intent: "draw", target: "diagram", subject: "auth flow", modifiers: [], raw: "..." }
93
+ * ```
94
+ */
95
+ parse(text: string): ParsedCommand {
96
+ // Use a separate doc for verb normalization (toInfinitive modifies terms in place)
97
+ const verbDoc = compromise(text)
98
+ const verbs = verbDoc.verbs().toInfinitive()
99
+ const verbArray = (verbs as any).out('array') as string[]
100
+ // First verb phrase — take just the root verb word
101
+ const firstVerb = verbArray.length > 0 ? verbArray[0] : null
102
+ const intent = firstVerb
103
+ ? firstVerb.trim().split(/\s+/)[0]!.toLowerCase()
104
+ : null
105
+
106
+ // Fresh doc for structure extraction
107
+ const doc = compromise(text)
108
+
109
+ let target: string | null = null
110
+ let subject: string | null = null
111
+
112
+ // Try prepositional structure: verb [det] noun+ prep [det] noun+
113
+ const prepMatch = doc.match('#Verb #Determiner? #Noun+ (of|about|for|with) #Determiner? #Noun+')
114
+ if ((prepMatch as any).found) {
115
+ // Nouns before the preposition
116
+ const beforePrep = doc.match('#Verb #Determiner? #Noun+ (of|about|for|with)')
117
+ const targetNouns = (beforePrep as any).match('#Noun+')
118
+ target = targetNouns.text().trim() || null
119
+
120
+ // Nouns after the preposition
121
+ const afterPrep = doc.match('(of|about|for|with) #Determiner? #Noun+')
122
+ const subjectNouns = (afterPrep as any).match('#Noun+')
123
+ subject = subjectNouns.text().trim() || null
124
+ } else {
125
+ // Simple: verb [det] noun+
126
+ const simpleMatch = doc.match('#Verb #Determiner? #Noun+')
127
+ if ((simpleMatch as any).found) {
128
+ const targetNouns = (simpleMatch as any).match('#Noun+')
129
+ target = targetNouns.text().trim() || null
130
+ }
131
+ }
132
+
133
+ // Modifiers: adjectives and adverbs
134
+ const adjectives = (doc as any).adjectives().out('array') as string[]
135
+ const adverbs = (doc as any).adverbs().out('array') as string[]
136
+ const modifiers = [...new Set([...adjectives, ...adverbs])].filter(Boolean)
137
+
138
+ this.state.set('parseCalls', (this.state.get('parseCalls') || 0) + 1)
139
+
140
+ return { intent, target, subject, modifiers, raw: text }
141
+ }
142
+
143
+ /**
144
+ * Analyze text with high-accuracy POS tagging and named entity recognition using wink-nlp.
145
+ *
146
+ * @param text - The text to analyze
147
+ * @returns Token-level POS tags (Universal POS tagset) and named entities
148
+ *
149
+ * @example
150
+ * ```typescript
151
+ * nlp.analyze("meet john at 3pm about the deployment")
152
+ * // { tokens: [{value:"meet",pos:"VERB"}, {value:"john",pos:"PROPN"}, ...],
153
+ * // entities: [{value:"john",type:"PERSON"}, {value:"3pm",type:"TIME"}],
154
+ * // raw: "meet john at 3pm about the deployment" }
155
+ * ```
156
+ */
157
+ analyze(text: string): Analysis {
158
+ const doc = this.wink.readDoc(text)
159
+ const its = this.wink.its
160
+
161
+ // Get tokens with POS tags
162
+ const values = doc.tokens().out(its.value) as string[]
163
+ const posTags = doc.tokens().out(its.pos) as string[]
164
+
165
+ const tokens = values.map((value, i) => ({
166
+ value,
167
+ pos: posTags[i] || 'X',
168
+ }))
169
+
170
+ // Get entities with types
171
+ const entities: Array<{ value: string; type: string }> = []
172
+ doc.entities().each((entity: any) => {
173
+ entities.push({
174
+ value: entity.out(),
175
+ type: entity.out((its as any).type) || 'UNKNOWN',
176
+ })
177
+ })
178
+
179
+ this.state.set('analyzeCalls', (this.state.get('analyzeCalls') || 0) + 1)
180
+
181
+ return { tokens, entities, raw: text }
182
+ }
183
+
184
+ /**
185
+ * Full understanding: combines compromise parsing with wink-nlp analysis.
186
+ * Returns intent, target, subject, modifiers (from parse) plus tokens and entities (from analyze).
187
+ *
188
+ * @param text - The text to understand
189
+ * @returns Combined parse + analyze result
190
+ *
191
+ * @example
192
+ * ```typescript
193
+ * nlp.understand("draw a diagram of the auth flow")
194
+ * // { intent: "draw", target: "diagram", subject: "auth flow", modifiers: [],
195
+ * // tokens: [{value:"draw",pos:"VERB"}, ...], entities: [...], raw: "..." }
196
+ * ```
197
+ */
198
+ understand(text: string): ParsedCommand & Analysis {
199
+ const parsed = this.parse(text)
200
+ const analysis = this.analyze(text)
201
+
202
+ // parse() and analyze() each increment their counters,
203
+ // so we correct the double-count by decrementing once
204
+ this.state.set('parseCalls', (this.state.get('parseCalls') || 1) - 1)
205
+ this.state.set('analyzeCalls', (this.state.get('analyzeCalls') || 1) - 1)
206
+
207
+ return { ...parsed, ...analysis }
208
+ }
209
+ }
210
+
211
+ export default features.register('nlp', NLP)
@@ -0,0 +1,166 @@
1
+ import { features, Feature } from "../feature.js";
2
+ import { FeatureStateSchema, FeatureOptionsSchema } from '../../schemas/base.js'
3
+
4
+ /**
5
+ * The Opener feature opens files, URLs, desktop applications, and code editors.
6
+ *
7
+ * HTTP/HTTPS URLs are opened in Google Chrome. Desktop apps can be launched by name.
8
+ * VS Code and Cursor can be opened to a specific path. All other paths are opened
9
+ * with the platform's default handler (e.g. Preview for images, Finder for folders).
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * const opener = container.feature('opener')
14
+ *
15
+ * // Open a URL in Chrome
16
+ * await opener.open('https://www.google.com')
17
+ *
18
+ * // Open a file with the default application
19
+ * await opener.open('/path/to/image.png')
20
+ *
21
+ * // Open a desktop application
22
+ * await opener.app('Slack')
23
+ *
24
+ * // Open VS Code at a project path
25
+ * await opener.code('/Users/jon/projects/my-app')
26
+ *
27
+ * // Open Cursor at a project path
28
+ * await opener.cursor('/Users/jon/projects/my-app')
29
+ * ```
30
+ *
31
+ * @extends Feature
32
+ */
33
+ export class Opener extends Feature {
34
+ static override shortcut = "features.opener" as const
35
+ static override description = "Opens files, URLs, desktop apps, and code editors"
36
+ static override stateSchema = FeatureStateSchema
37
+ static override optionsSchema = FeatureOptionsSchema
38
+
39
+ /**
40
+ * Opens a path or URL with the appropriate application.
41
+ *
42
+ * HTTP and HTTPS URLs are opened in Google Chrome.
43
+ * Everything else is opened with the system default handler via `open` (macOS).
44
+ *
45
+ * @param {string} target - A URL or file path to open
46
+ * @returns {Promise<void>}
47
+ */
48
+ async open(target: string): Promise<void> {
49
+ const isUrl = /^https?:\/\//i.test(target)
50
+ const platform = process.platform
51
+
52
+ if (isUrl) {
53
+ console.log(`Opening ${target} in Chrome`)
54
+ await this.openInChrome(target, platform)
55
+ } else {
56
+ await this.openDefault(target, platform)
57
+ }
58
+ }
59
+
60
+ private async openInChrome(url: string, platform: string): Promise<void> {
61
+ const proc = this.container.proc
62
+
63
+ if (platform === 'darwin') {
64
+ await proc.spawnAndCapture('open', ['-a', 'Google Chrome', url])
65
+ } else if (platform === 'win32') {
66
+ await proc.spawnAndCapture('cmd', ['/c', 'start', 'chrome', url])
67
+ } else {
68
+ // Linux - try google-chrome, then chromium, then fall back to xdg-open
69
+ try {
70
+ await proc.spawnAndCapture('google-chrome', [url])
71
+ } catch {
72
+ try {
73
+ await proc.spawnAndCapture('chromium', [url])
74
+ } catch {
75
+ await proc.spawnAndCapture('xdg-open', [url])
76
+ }
77
+ }
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Opens a desktop application by name.
83
+ *
84
+ * On macOS, uses `open -a` to launch the app. On Windows, uses `start`.
85
+ * On Linux, attempts to run the lowercase app name as a command.
86
+ *
87
+ * @param {string} name - The application name (e.g. "Slack", "Finder", "Safari")
88
+ * @returns {Promise<void>}
89
+ */
90
+ async app(name: string): Promise<void> {
91
+ const platform = process.platform
92
+ const proc = this.container.proc
93
+
94
+ if (platform === 'darwin') {
95
+ await proc.spawnAndCapture('open', ['-a', name])
96
+ } else if (platform === 'win32') {
97
+ await proc.spawnAndCapture('cmd', ['/c', 'start', '', name])
98
+ } else {
99
+ await proc.spawnAndCapture(name.toLowerCase(), [])
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Opens VS Code at the specified path.
105
+ *
106
+ * Uses the `code` CLI command. Falls back to `open -a "Visual Studio Code"` on macOS.
107
+ *
108
+ * @param {string} [path="."] - The file or folder path to open
109
+ * @returns {Promise<void>}
110
+ */
111
+ async code(path: string = "."): Promise<void> {
112
+ const proc = this.container.proc
113
+
114
+ try {
115
+ await proc.spawnAndCapture('code', [path])
116
+ } catch {
117
+ if (process.platform === 'darwin') {
118
+ await proc.spawnAndCapture('open', ['-a', 'Visual Studio Code', path])
119
+ } else {
120
+ throw new Error('VS Code CLI (code) not found. Install it from VS Code: Command Palette > "Shell Command: Install code command in PATH"')
121
+ }
122
+ }
123
+ }
124
+
125
+ /**
126
+ * Opens Cursor at the specified path.
127
+ *
128
+ * Uses the `cursor` CLI command. Falls back to `open -a "Cursor"` on macOS.
129
+ *
130
+ * @param {string} [path="."] - The file or folder path to open
131
+ * @returns {Promise<void>}
132
+ */
133
+ async cursor(path: string = "."): Promise<void> {
134
+ const proc = this.container.proc
135
+
136
+ try {
137
+ await proc.spawnAndCapture('cursor', [path])
138
+ } catch {
139
+ if (process.platform === 'darwin') {
140
+ await proc.spawnAndCapture('open', ['-a', 'Cursor', path])
141
+ } else {
142
+ throw new Error('Cursor CLI (cursor) not found. Install it from Cursor: Command Palette > "Shell Command: Install cursor command in PATH"')
143
+ }
144
+ }
145
+ }
146
+
147
+ private async openDefault(target: string, platform: string): Promise<void> {
148
+ const proc = this.container.proc
149
+
150
+ if (platform === 'darwin') {
151
+ await proc.spawnAndCapture('open', [target])
152
+ } else if (platform === 'win32') {
153
+ await proc.spawnAndCapture('cmd', ['/c', 'start', '', target])
154
+ } else {
155
+ await proc.spawnAndCapture('xdg-open', [target])
156
+ }
157
+ }
158
+ }
159
+
160
+ declare module '../../feature' {
161
+ interface AvailableFeatures {
162
+ opener: typeof Opener
163
+ }
164
+ }
165
+
166
+ export default features.register("opener", Opener)
@@ -0,0 +1,157 @@
1
+ import { Feature, features } from '../feature.js'
2
+ import { FeatureStateSchema, FeatureOptionsSchema } from '../../schemas/base.js'
3
+ import os from 'os'
4
+
5
+ /**
6
+ * The OS feature provides access to operating system utilities and information.
7
+ *
8
+ * This feature wraps Node.js's built-in `os` module and provides convenient
9
+ * getters for system information like architecture, platform, directories,
10
+ * network interfaces, and hardware details.
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const osInfo = container.feature('os')
15
+ *
16
+ * console.log(`Platform: ${osInfo.platform}`)
17
+ * console.log(`Architecture: ${osInfo.arch}`)
18
+ * console.log(`CPU cores: ${osInfo.cpuCount}`)
19
+ * console.log(`Home directory: ${osInfo.homedir}`)
20
+ * ```
21
+ *
22
+ * @extends Feature
23
+ */
24
+ export class OS extends Feature {
25
+ static override shortcut = 'features.os' as const
26
+ static override stateSchema = FeatureStateSchema
27
+ static override optionsSchema = FeatureOptionsSchema
28
+
29
+ /**
30
+ * Gets the operating system CPU architecture.
31
+ *
32
+ * @returns {string} The CPU architecture (e.g., 'x64', 'arm64', 'arm', 'ia32')
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * const arch = os.arch
37
+ * console.log(`Running on ${arch} architecture`)
38
+ * ```
39
+ */
40
+ get arch() {
41
+ return os.arch()
42
+ }
43
+
44
+ /**
45
+ * Gets the operating system's default directory for temporary files.
46
+ *
47
+ * @returns {string} The path to the temporary directory
48
+ *
49
+ * @example
50
+ * ```typescript
51
+ * const tempDir = os.tmpdir
52
+ * console.log(`Temp directory: ${tempDir}`)
53
+ * ```
54
+ */
55
+ get tmpdir() {
56
+ return os.tmpdir()
57
+ }
58
+
59
+ /**
60
+ * Gets the current user's home directory path.
61
+ *
62
+ * @returns {string} The path to the user's home directory
63
+ *
64
+ * @example
65
+ * ```typescript
66
+ * const home = os.homedir
67
+ * console.log(`User home: ${home}`)
68
+ * ```
69
+ */
70
+ get homedir() {
71
+ return os.homedir()
72
+ }
73
+
74
+ /**
75
+ * Gets the number of logical CPU cores available on the system.
76
+ *
77
+ * @returns {number} The number of CPU cores
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * const cores = os.cpuCount
82
+ * console.log(`System has ${cores} CPU cores`)
83
+ * ```
84
+ */
85
+ get cpuCount() {
86
+ return os.cpus().length
87
+ }
88
+
89
+ /**
90
+ * Gets the hostname of the operating system.
91
+ *
92
+ * @returns {string} The system hostname
93
+ *
94
+ * @example
95
+ * ```typescript
96
+ * const hostname = os.hostname
97
+ * console.log(`Hostname: ${hostname}`)
98
+ * ```
99
+ */
100
+ get hostname() {
101
+ return os.hostname()
102
+ }
103
+
104
+ /**
105
+ * Gets the operating system platform.
106
+ *
107
+ * @returns {string} The platform identifier (e.g., 'darwin', 'linux', 'win32')
108
+ *
109
+ * @example
110
+ * ```typescript
111
+ * const platform = os.platform
112
+ * if (platform === 'darwin') {
113
+ * console.log('Running on macOS')
114
+ * }
115
+ * ```
116
+ */
117
+ get platform() {
118
+ return os.platform()
119
+ }
120
+
121
+ /**
122
+ * Gets information about the system's network interfaces.
123
+ *
124
+ * @returns {NodeJS.Dict<os.NetworkInterfaceInfo[]>} Object containing network interface details
125
+ *
126
+ * @example
127
+ * ```typescript
128
+ * const interfaces = os.networkInterfaces
129
+ * Object.keys(interfaces).forEach(name => {
130
+ * console.log(`Interface ${name}:`, interfaces[name])
131
+ * })
132
+ * ```
133
+ */
134
+ get networkInterfaces() {
135
+ return os.networkInterfaces()
136
+ }
137
+
138
+ /**
139
+ * Gets an array of MAC addresses for non-internal IPv4 network interfaces.
140
+ *
141
+ * This filters the network interfaces to only include external IPv4 interfaces
142
+ * and returns their MAC addresses, which can be useful for system identification.
143
+ *
144
+ * @returns {string[]} Array of MAC addresses for external IPv4 interfaces
145
+ *
146
+ * @example
147
+ * ```typescript
148
+ * const macAddresses = os.macAddresses
149
+ * console.log(`External MAC addresses: ${macAddresses.join(', ')}`)
150
+ * ```
151
+ */
152
+ get macAddresses() : string[] {
153
+ return Object.values(this.networkInterfaces).flat().filter(v => typeof v !== 'undefined' && v.internal === false && v.family === 'IPv4').map(v => v?.mac!).filter(Boolean)
154
+ }
155
+ }
156
+
157
+ export default features.register('os', OS)