@soederpop/luca 0.0.6 → 0.0.8
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.
- package/CLAUDE.md +10 -1
- package/RUNME.md +56 -0
- package/bun.lock +1 -1
- package/commands/build-bootstrap.ts +78 -0
- package/commands/build-scaffolds.ts +24 -2
- package/commands/try-all-challenges.ts +543 -0
- package/commands/try-challenge.ts +100 -0
- package/docs/README.md +52 -80
- package/docs/TABLE-OF-CONTENTS.md +82 -51
- package/docs/apis/clients/elevenlabs.md +232 -8
- package/docs/apis/clients/graph.md +59 -8
- package/docs/apis/clients/openai.md +362 -2
- package/docs/apis/clients/rest.md +122 -2
- package/docs/apis/clients/websocket.md +71 -17
- package/docs/apis/features/agi/assistant.md +9 -3
- package/docs/apis/features/agi/assistants-manager.md +2 -2
- package/docs/apis/features/agi/claude-code.md +153 -14
- package/docs/apis/features/agi/conversation-history.md +15 -3
- package/docs/apis/features/agi/conversation.md +133 -20
- package/docs/apis/features/agi/openai-codex.md +90 -12
- package/docs/apis/features/agi/skills-library.md +23 -5
- package/docs/apis/features/node/container-link.md +59 -0
- package/docs/apis/features/node/content-db.md +1 -1
- package/docs/apis/features/node/disk-cache.md +1 -1
- package/docs/apis/features/node/dns.md +1 -0
- package/docs/apis/features/node/docker.md +2 -1
- package/docs/apis/features/node/esbuild.md +4 -3
- package/docs/apis/features/node/file-manager.md +13 -4
- package/docs/apis/features/node/fs.md +726 -171
- package/docs/apis/features/node/git.md +1 -0
- package/docs/apis/features/node/google-auth.md +23 -4
- package/docs/apis/features/node/google-calendar.md +14 -2
- package/docs/apis/features/node/google-docs.md +15 -2
- package/docs/apis/features/node/google-drive.md +21 -3
- package/docs/apis/features/node/google-sheets.md +14 -2
- package/docs/apis/features/node/grep.md +2 -0
- package/docs/apis/features/node/helpers.md +29 -0
- package/docs/apis/features/node/ink.md +2 -2
- package/docs/apis/features/node/networking.md +39 -4
- package/docs/apis/features/node/os.md +28 -0
- package/docs/apis/features/node/postgres.md +26 -4
- package/docs/apis/features/node/proc.md +37 -28
- package/docs/apis/features/node/process-manager.md +33 -5
- package/docs/apis/features/node/repl.md +1 -1
- package/docs/apis/features/node/runpod.md +1 -0
- package/docs/apis/features/node/secure-shell.md +7 -0
- package/docs/apis/features/node/semantic-search.md +12 -5
- package/docs/apis/features/node/sqlite.md +26 -4
- package/docs/apis/features/node/telegram.md +30 -5
- package/docs/apis/features/node/tts.md +17 -2
- package/docs/apis/features/node/ui.md +1 -1
- package/docs/apis/features/node/vault.md +4 -9
- package/docs/apis/features/node/vm.md +3 -12
- package/docs/apis/features/node/window-manager.md +128 -20
- package/docs/apis/features/web/asset-loader.md +13 -1
- package/docs/apis/features/web/container-link.md +59 -0
- package/docs/apis/features/web/esbuild.md +4 -3
- package/docs/apis/features/web/helpers.md +29 -0
- package/docs/apis/features/web/network.md +16 -2
- package/docs/apis/features/web/speech.md +16 -2
- package/docs/apis/features/web/vault.md +4 -9
- package/docs/apis/features/web/vm.md +3 -12
- package/docs/apis/features/web/voice.md +18 -1
- package/docs/apis/servers/express.md +18 -2
- package/docs/apis/servers/mcp.md +29 -4
- package/docs/apis/servers/websocket.md +34 -6
- package/docs/bootstrap/CLAUDE.md +100 -0
- package/docs/bootstrap/SKILL.md +222 -0
- package/docs/bootstrap/templates/about-command.ts +41 -0
- package/docs/bootstrap/templates/docs-models.ts +22 -0
- package/docs/bootstrap/templates/docs-readme.md +43 -0
- package/docs/bootstrap/templates/example-feature.ts +53 -0
- package/docs/bootstrap/templates/health-endpoint.ts +15 -0
- package/docs/bootstrap/templates/luca-cli.ts +25 -0
- package/docs/bootstrap/templates/runme.md +54 -0
- package/docs/challenges/caching-proxy.md +16 -0
- package/docs/challenges/content-db-round-trip.md +14 -0
- package/docs/challenges/custom-command.md +9 -0
- package/docs/challenges/file-watcher-pipeline.md +11 -0
- package/docs/challenges/grep-audit-report.md +15 -0
- package/docs/challenges/multi-feature-dashboard.md +14 -0
- package/docs/challenges/process-orchestrator.md +17 -0
- package/docs/challenges/rest-api-server-with-client.md +12 -0
- package/docs/challenges/script-runner-with-vm.md +11 -0
- package/docs/challenges/simple-rest-api.md +15 -0
- package/docs/challenges/websocket-serve-and-client.md +11 -0
- package/docs/challenges/yaml-config-system.md +14 -0
- package/docs/command-system-overhaul.md +94 -0
- package/docs/examples/assistant/CORE.md +18 -0
- package/docs/examples/assistant/hooks.ts +3 -0
- package/docs/examples/assistant/tools.ts +10 -0
- package/docs/examples/window-manager-layouts.md +180 -0
- package/docs/in-memory-fs.md +4 -0
- package/docs/models.ts +13 -10
- package/docs/philosophy.md +4 -3
- package/docs/reports/console-hmr-design.md +170 -0
- package/docs/reports/helper-semantic-search.md +72 -0
- package/docs/scaffolds/client.md +29 -20
- package/docs/scaffolds/command.md +64 -50
- package/docs/scaffolds/endpoint.md +31 -36
- package/docs/scaffolds/feature.md +28 -18
- package/docs/scaffolds/selector.md +91 -0
- package/docs/scaffolds/server.md +18 -9
- package/docs/selectors.md +115 -0
- package/docs/sessions/custom-command/attempt-log-2.md +195 -0
- package/docs/sessions/file-watcher-pipeline/attempt-log-1.md +728 -0
- package/docs/sessions/file-watcher-pipeline/attempt-log-2.md +555 -0
- package/docs/sessions/grep-audit-report/attempt-log-1.md +289 -0
- package/docs/sessions/multi-feature-dashboard/attempt-log-2.md +679 -0
- package/docs/sessions/rest-api-server-with-client/attempt-log-1.md +1 -0
- package/docs/sessions/rest-api-server-with-client/attempt-log-3.md +920 -0
- package/docs/sessions/simple-rest-api/attempt-log-1.md +593 -0
- package/docs/sessions/websocket-serve-and-client/attempt-log-2.md +995 -0
- package/docs/tutorials/00-bootstrap.md +148 -0
- package/docs/tutorials/07-endpoints.md +7 -7
- package/docs/tutorials/08-commands.md +153 -72
- package/luca.cli.ts +3 -0
- package/package.json +6 -5
- package/public/index.html +1430 -0
- package/scripts/examples/using-ollama.ts +2 -1
- package/scripts/update-introspection-data.ts +2 -2
- package/src/agi/endpoints/experts.ts +1 -1
- package/src/agi/features/assistant.ts +7 -0
- package/src/agi/features/assistants-manager.ts +5 -5
- package/src/agi/features/claude-code.ts +263 -3
- package/src/agi/features/conversation-history.ts +7 -1
- package/src/agi/features/conversation.ts +26 -3
- package/src/agi/features/openai-codex.ts +26 -2
- package/src/agi/features/openapi.ts +6 -1
- package/src/agi/features/skills-library.ts +9 -1
- package/src/bootstrap/generated.ts +595 -0
- package/src/cli/cli.ts +64 -21
- package/src/client.ts +23 -357
- package/src/clients/civitai/index.ts +1 -1
- package/src/clients/client-template.ts +1 -1
- package/src/clients/comfyui/index.ts +13 -2
- package/src/clients/elevenlabs/index.ts +2 -1
- package/src/clients/graph.ts +87 -0
- package/src/clients/openai/index.ts +10 -1
- package/src/clients/rest.ts +207 -0
- package/src/clients/websocket.ts +176 -0
- package/src/command.ts +281 -34
- package/src/commands/bootstrap.ts +185 -0
- package/src/commands/chat.ts +5 -4
- package/src/commands/describe.ts +341 -4
- package/src/commands/help.ts +35 -9
- package/src/commands/index.ts +3 -0
- package/src/commands/introspect.ts +92 -2
- package/src/commands/prompt.ts +5 -6
- package/src/commands/run.ts +75 -10
- package/src/commands/save-api-docs.ts +49 -0
- package/src/commands/scaffold.ts +169 -23
- package/src/commands/select.ts +94 -0
- package/src/commands/serve.ts +10 -1
- package/src/container.ts +15 -0
- package/src/endpoint.ts +19 -0
- package/src/graft.ts +181 -0
- package/src/introspection/generated.agi.ts +12458 -8968
- package/src/introspection/generated.node.ts +10573 -7145
- package/src/introspection/generated.web.ts +1 -1
- package/src/introspection/index.ts +26 -0
- package/src/node/container.ts +6 -7
- package/src/node/features/content-db.ts +49 -2
- package/src/node/features/disk-cache.ts +16 -9
- package/src/node/features/dns.ts +16 -3
- package/src/node/features/docker.ts +16 -4
- package/src/node/features/esbuild.ts +22 -2
- package/src/node/features/file-manager.ts +184 -29
- package/src/node/features/fs.ts +704 -248
- package/src/node/features/git.ts +21 -8
- package/src/node/features/grep.ts +23 -3
- package/src/node/features/helpers.ts +372 -43
- package/src/node/features/networking.ts +39 -4
- package/src/node/features/opener.ts +28 -15
- package/src/node/features/os.ts +76 -0
- package/src/node/features/port-exposer.ts +11 -1
- package/src/node/features/postgres.ts +17 -1
- package/src/node/features/proc.ts +4 -1
- package/src/node/features/python.ts +63 -14
- package/src/node/features/repl.ts +11 -7
- package/src/node/features/runpod.ts +16 -3
- package/src/node/features/secure-shell.ts +27 -2
- package/src/node/features/semantic-search.ts +12 -1
- package/src/node/features/ui.ts +5 -69
- package/src/node/features/vm.ts +17 -0
- package/src/node/features/window-manager.ts +68 -20
- package/src/node.ts +5 -0
- package/src/scaffolds/generated.ts +492 -290
- package/src/scaffolds/template.ts +9 -0
- package/src/schemas/base.ts +46 -5
- package/src/selector.ts +282 -0
- package/src/server.ts +11 -0
- package/src/servers/express.ts +27 -12
- package/src/servers/socket.ts +45 -11
- package/src/web/clients/socket.ts +4 -1
- package/src/web/container.ts +2 -1
- package/src/web/features/network.ts +7 -1
- package/src/web/features/voice-recognition.ts +16 -1
- package/test/clients-servers.test.ts +2 -1
- package/test/command.test.ts +267 -0
- package/test/vm-context.test.ts +146 -0
- package/test-integration/assistants-manager.test.ts +10 -20
- package/docs/apis/features/node/launcher-app-command-listener.md +0 -145
- package/docs/examples/launcher-app-command-listener.md +0 -120
- package/docs/tasks/web-container-helper-discovery.md +0 -71
- package/docs/todos.md +0 -1
- package/scripts/test-command-listener.ts +0 -123
- package/src/node/features/launcher-app-command-listener.ts +0 -389
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { setBuildTimeData, setContainerBuildTimeData } from './index.js';
|
|
2
2
|
|
|
3
3
|
// Auto-generated introspection registry data
|
|
4
|
-
// Generated at: 2026-03-
|
|
4
|
+
// Generated at: 2026-03-19T00:28:05.997Z
|
|
5
5
|
|
|
6
6
|
setBuildTimeData('features.containerLink', {
|
|
7
7
|
"id": "features.containerLink",
|
|
@@ -161,12 +161,38 @@ export function getContainerBuildTimeData(className: string): Partial<ContainerI
|
|
|
161
161
|
export function setBuildTimeData(key: string, data: HelperIntrospection) {
|
|
162
162
|
const existing = __INTROSPECTION__.get(key)
|
|
163
163
|
|
|
164
|
+
// Merge events: build-time AST provides descriptions, runtime Zod schemas provide arguments.
|
|
165
|
+
// For each event, preserve runtime arguments if the build-time entry has none.
|
|
166
|
+
const mergedEvents: Record<string, any> = { ...(data.events || {}) }
|
|
167
|
+
if (existing?.events) {
|
|
168
|
+
for (const [eventName, existingEvent] of Object.entries(existing.events)) {
|
|
169
|
+
if (mergedEvents[eventName]) {
|
|
170
|
+
// Build-time entry exists — merge in runtime arguments and description if build-time has none
|
|
171
|
+
const buildArgs = mergedEvents[eventName].arguments || {}
|
|
172
|
+
const runtimeArgs = (existingEvent as any).arguments || {}
|
|
173
|
+
const buildDesc = mergedEvents[eventName].description || ''
|
|
174
|
+
const runtimeDesc = (existingEvent as any).description || ''
|
|
175
|
+
const isGenericDesc = buildDesc.startsWith('Event emitted by ')
|
|
176
|
+
if (Object.keys(buildArgs).length === 0 && Object.keys(runtimeArgs).length > 0) {
|
|
177
|
+
mergedEvents[eventName] = { ...mergedEvents[eventName], arguments: runtimeArgs }
|
|
178
|
+
}
|
|
179
|
+
if (isGenericDesc && runtimeDesc) {
|
|
180
|
+
mergedEvents[eventName] = { ...mergedEvents[eventName], description: runtimeDesc }
|
|
181
|
+
}
|
|
182
|
+
} else {
|
|
183
|
+
// Event only exists in runtime (from Zod schema) — preserve it
|
|
184
|
+
mergedEvents[eventName] = existingEvent
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
164
189
|
__INTROSPECTION__.set(key, {
|
|
165
190
|
...data,
|
|
166
191
|
// preserve runtime-derived className/state/options if registration already happened
|
|
167
192
|
className: data.className || existing?.className,
|
|
168
193
|
state: existing?.state || data.state || {},
|
|
169
194
|
options: existing?.options || data.options || {},
|
|
195
|
+
events: mergedEvents,
|
|
170
196
|
getters: data.getters || existing?.getters || {},
|
|
171
197
|
envVars: existing?.envVars || data.envVars || [],
|
|
172
198
|
examples: data.examples || existing?.examples,
|
package/src/node/container.ts
CHANGED
|
@@ -6,12 +6,16 @@ import type { FeatureOptions } from "./feature";
|
|
|
6
6
|
import { features, Feature } from "./feature";
|
|
7
7
|
import type { AvailableFeatures } from "../feature";
|
|
8
8
|
import { Client, type ClientsInterface } from "../client";
|
|
9
|
+
import "../clients/rest";
|
|
10
|
+
import "../clients/graph";
|
|
11
|
+
import "../clients/websocket";
|
|
9
12
|
import { Server, type ServersInterface } from "../server";
|
|
10
13
|
import "../servers/express";
|
|
11
14
|
import "../servers/socket";
|
|
12
15
|
import "../servers/mcp";
|
|
13
16
|
import { Command, type CommandsInterface } from "../command";
|
|
14
17
|
import { Endpoint, type EndpointsInterface } from "../endpoint";
|
|
18
|
+
import { Selector, type SelectorsInterface } from "../selector";
|
|
15
19
|
|
|
16
20
|
import minimist from "minimist";
|
|
17
21
|
import { omit, kebabCase, camelCase, mapKeys, castArray } from "lodash-es";
|
|
@@ -53,7 +57,6 @@ import "./features/google-sheets";
|
|
|
53
57
|
import "./features/google-calendar";
|
|
54
58
|
import "./features/google-docs";
|
|
55
59
|
import "./features/window-manager";
|
|
56
|
-
import "./features/launcher-app-command-listener";
|
|
57
60
|
import "./features/nlp";
|
|
58
61
|
import "./features/process-manager"
|
|
59
62
|
import "./features/tts";
|
|
@@ -98,7 +101,6 @@ import type { GoogleSheets } from './features/google-sheets';
|
|
|
98
101
|
import type { GoogleCalendar } from './features/google-calendar';
|
|
99
102
|
import type { GoogleDocs } from './features/google-docs';
|
|
100
103
|
import type { WindowManager } from './features/window-manager';
|
|
101
|
-
import type { LauncherAppCommandListener } from './features/launcher-app-command-listener';
|
|
102
104
|
import type { NLP } from './features/nlp';
|
|
103
105
|
import type { ProcessManager } from './features/process-manager'
|
|
104
106
|
import type { TTS } from './features/tts';
|
|
@@ -138,7 +140,6 @@ export {
|
|
|
138
140
|
type GoogleCalendar,
|
|
139
141
|
type GoogleDocs,
|
|
140
142
|
type WindowManager,
|
|
141
|
-
type LauncherAppCommandListener,
|
|
142
143
|
type NLP,
|
|
143
144
|
type ProcessManager,
|
|
144
145
|
type TTS,
|
|
@@ -204,7 +205,6 @@ export interface NodeFeatures extends AvailableFeatures {
|
|
|
204
205
|
googleCalendar: typeof GoogleCalendar;
|
|
205
206
|
googleDocs: typeof GoogleDocs;
|
|
206
207
|
windowManager: typeof WindowManager;
|
|
207
|
-
launcherAppCommandListener: typeof LauncherAppCommandListener;
|
|
208
208
|
nlp: typeof NLP;
|
|
209
209
|
processManager: typeof ProcessManager;
|
|
210
210
|
tts: typeof TTS;
|
|
@@ -214,7 +214,7 @@ export interface NodeFeatures extends AvailableFeatures {
|
|
|
214
214
|
dns: typeof Dns;
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
-
export type ClientsAndServersInterface = ClientsInterface & ServersInterface & CommandsInterface & EndpointsInterface;
|
|
217
|
+
export type ClientsAndServersInterface = ClientsInterface & ServersInterface & CommandsInterface & EndpointsInterface & SelectorsInterface;
|
|
218
218
|
|
|
219
219
|
export interface NodeContainer extends ClientsAndServersInterface {}
|
|
220
220
|
|
|
@@ -253,7 +253,6 @@ export class NodeContainer<
|
|
|
253
253
|
googleCalendar?: GoogleCalendar;
|
|
254
254
|
googleDocs?: GoogleDocs;
|
|
255
255
|
windowManager?: WindowManager;
|
|
256
|
-
launcherAppCommandListener?: LauncherAppCommandListener;
|
|
257
256
|
nlp?: NLP;
|
|
258
257
|
processManager?: ProcessManager;
|
|
259
258
|
tts?: TTS;
|
|
@@ -286,7 +285,7 @@ export class NodeContainer<
|
|
|
286
285
|
}
|
|
287
286
|
});
|
|
288
287
|
|
|
289
|
-
this.use(Client).use(Server).use(Command).use(Endpoint);
|
|
288
|
+
this.use(Client).use(Server).use(Command).use(Endpoint).use(Selector);
|
|
290
289
|
}
|
|
291
290
|
|
|
292
291
|
override get Feature() {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Feature } from '../feature.js'
|
|
2
|
+
import * as contentbaseExports from 'contentbase'
|
|
2
3
|
import { parse, Collection, extractSections, type ModelDefinition } from 'contentbase'
|
|
3
4
|
import { z } from 'zod'
|
|
4
|
-
import { FeatureStateSchema, FeatureOptionsSchema } from '../../schemas/base.js'
|
|
5
|
+
import { FeatureStateSchema, FeatureOptionsSchema, FeatureEventsSchema } from '../../schemas/base.js'
|
|
5
6
|
import { join, dirname } from 'node:path'
|
|
6
7
|
import { existsSync, readdirSync } from 'node:fs'
|
|
7
8
|
|
|
@@ -18,6 +19,10 @@ export const ContentDbOptionsSchema = FeatureOptionsSchema.extend({
|
|
|
18
19
|
export type ContentDbState = z.infer<typeof ContentDbStateSchema>
|
|
19
20
|
export type ContentDbOptions = z.infer<typeof ContentDbOptionsSchema>
|
|
20
21
|
|
|
22
|
+
export const ContentDbEventsSchema = FeatureEventsSchema.extend({
|
|
23
|
+
reloaded: z.tuple([]).describe('When the content collection is reloaded from disk'),
|
|
24
|
+
}).describe('ContentDb events')
|
|
25
|
+
|
|
21
26
|
/**
|
|
22
27
|
* Provides access to a Contentbase Collection for a folder of structured markdown files.
|
|
23
28
|
*
|
|
@@ -37,6 +42,7 @@ export class ContentDb extends Feature<ContentDbState, ContentDbOptions> {
|
|
|
37
42
|
static override shortcut = 'features.contentDb' as const
|
|
38
43
|
static override stateSchema = ContentDbStateSchema
|
|
39
44
|
static override optionsSchema = ContentDbOptionsSchema
|
|
45
|
+
static override eventsSchema = ContentDbEventsSchema
|
|
40
46
|
static { Feature.register(this, 'contentDb') }
|
|
41
47
|
|
|
42
48
|
override get initialState(): ContentDbState {
|
|
@@ -52,11 +58,52 @@ export class ContentDb extends Feature<ContentDbState, ContentDbOptions> {
|
|
|
52
58
|
}
|
|
53
59
|
|
|
54
60
|
_collection?: Collection
|
|
61
|
+
private _contentbaseSeeded = false
|
|
55
62
|
|
|
56
63
|
/** Returns the lazily-initialized Collection instance for the configured rootPath. */
|
|
57
64
|
get collection() {
|
|
58
65
|
if (this._collection) return this._collection
|
|
59
|
-
|
|
66
|
+
|
|
67
|
+
const opts: any = { rootPath: this.options.rootPath }
|
|
68
|
+
|
|
69
|
+
// When contentbase isn't in node_modules (e.g. compiled luca binary),
|
|
70
|
+
// provide a VM-based module loader so models.ts can resolve its imports
|
|
71
|
+
if (!this._canNativeImportContentbase()) {
|
|
72
|
+
opts.moduleLoader = (filePath: string) => {
|
|
73
|
+
this._seedContentbaseVirtualModules()
|
|
74
|
+
const vm = this.container.feature('vm') as any
|
|
75
|
+
return vm.loadModule(filePath)
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return this._collection = new Collection(opts)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** Check if contentbase is resolvable via native import from the project root */
|
|
83
|
+
private _canNativeImportContentbase(): boolean {
|
|
84
|
+
const cwd = this.container.cwd
|
|
85
|
+
return existsSync(join(cwd, 'node_modules', 'contentbase'))
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** Seed the VM with virtual modules so models.ts can import from 'contentbase', 'zod', etc. */
|
|
89
|
+
private _seedContentbaseVirtualModules(): void {
|
|
90
|
+
if (this._contentbaseSeeded) return
|
|
91
|
+
this._contentbaseSeeded = true
|
|
92
|
+
|
|
93
|
+
const vm = this.container.feature('vm') as any
|
|
94
|
+
|
|
95
|
+
// Seed luca modules first (helpers does this for @soederpop/luca)
|
|
96
|
+
const helpers = this.container.feature('helpers') as any
|
|
97
|
+
if (helpers?.seedVirtualModules) {
|
|
98
|
+
helpers.seedVirtualModules()
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Register contentbase barrel — everything the library exports
|
|
102
|
+
vm.defineModule('contentbase', contentbaseExports)
|
|
103
|
+
|
|
104
|
+
// Common deps that models.ts files tend to use
|
|
105
|
+
try { vm.defineModule('js-yaml', require('js-yaml')) } catch {}
|
|
106
|
+
try { vm.defineModule('mdast-util-to-string', require('mdast-util-to-string')) } catch {}
|
|
60
107
|
}
|
|
61
108
|
|
|
62
109
|
/** Returns the absolute resolved path to the collection root directory. */
|
|
@@ -36,15 +36,17 @@ export class DiskCache extends Feature<FeatureState,DiskCacheOptions> {
|
|
|
36
36
|
static override optionsSchema = DiskCacheOptionsSchema
|
|
37
37
|
static { Feature.register(this, 'diskCache') }
|
|
38
38
|
|
|
39
|
-
constructor(options: DiskCacheOptions, context: ContainerContext) {
|
|
40
|
-
super(options, context)
|
|
41
|
-
this._cache = this.create()
|
|
42
|
-
this.hide('_cache')
|
|
43
|
-
}
|
|
44
|
-
|
|
45
39
|
/** Returns the underlying cacache instance configured with the cache directory path. */
|
|
46
40
|
get cache() {
|
|
47
|
-
|
|
41
|
+
if(this._cache) {
|
|
42
|
+
return this._cache
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const cache = this.create()
|
|
46
|
+
|
|
47
|
+
Object.defineProperty(this, '_cache', { value: cache, enumerable: false })
|
|
48
|
+
|
|
49
|
+
return cache
|
|
48
50
|
}
|
|
49
51
|
|
|
50
52
|
/**
|
|
@@ -328,7 +330,7 @@ export class DiskCache extends Feature<FeatureState,DiskCacheOptions> {
|
|
|
328
330
|
|
|
329
331
|
/**
|
|
330
332
|
* Create a cacache instance with the specified path
|
|
331
|
-
* @param path - Optional cache directory path (defaults to options.path or
|
|
333
|
+
* @param path - Optional cache directory path (defaults to options.path or ~/.cache/luca/disk-cache-{cwdHash})
|
|
332
334
|
* @returns Configured cacache instance with all methods bound to the path
|
|
333
335
|
* @example
|
|
334
336
|
* ```typescript
|
|
@@ -336,7 +338,12 @@ export class DiskCache extends Feature<FeatureState,DiskCacheOptions> {
|
|
|
336
338
|
* ```
|
|
337
339
|
*/
|
|
338
340
|
create(path?: string) {
|
|
339
|
-
|
|
341
|
+
if (!path && !this.options.path) {
|
|
342
|
+
const cwdHash = this.container.utils.hashObject(this.container.cwd)
|
|
343
|
+
path = this.container.paths.resolve(process.env.HOME!, '.cache', 'luca', `disk-cache-${cwdHash}`)
|
|
344
|
+
} else {
|
|
345
|
+
path = path || this.options.path!
|
|
346
|
+
}
|
|
340
347
|
this.container.fs.ensureFolder(path)
|
|
341
348
|
const arg = (fn: (...args: any) => any) => partial(fn, path);
|
|
342
349
|
|
package/src/node/features/dns.ts
CHANGED
|
@@ -131,10 +131,23 @@ export class Dns extends Feature<DnsState, DnsOptions> {
|
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
+
private _resolvedDigPath: string | null = null
|
|
135
|
+
|
|
134
136
|
get proc() {
|
|
135
137
|
return this.container.feature('proc')
|
|
136
138
|
}
|
|
137
139
|
|
|
140
|
+
/** Resolved path to the dig binary */
|
|
141
|
+
get digPath(): string {
|
|
142
|
+
if (this._resolvedDigPath) return this._resolvedDigPath
|
|
143
|
+
try {
|
|
144
|
+
this._resolvedDigPath = this.proc.exec('which dig').trim()
|
|
145
|
+
} catch {
|
|
146
|
+
this._resolvedDigPath = 'dig'
|
|
147
|
+
}
|
|
148
|
+
return this._resolvedDigPath
|
|
149
|
+
}
|
|
150
|
+
|
|
138
151
|
/**
|
|
139
152
|
* Checks whether the `dig` binary is available on the system.
|
|
140
153
|
*
|
|
@@ -148,7 +161,7 @@ export class Dns extends Feature<DnsState, DnsOptions> {
|
|
|
148
161
|
* ```
|
|
149
162
|
*/
|
|
150
163
|
async isAvailable(): Promise<boolean> {
|
|
151
|
-
const result = await this.proc.spawnAndCapture(
|
|
164
|
+
const result = await this.proc.spawnAndCapture(this.digPath, ['-v'])
|
|
152
165
|
// dig -v prints version to stderr and exits 0
|
|
153
166
|
return result.exitCode === 0
|
|
154
167
|
}
|
|
@@ -180,7 +193,7 @@ export class Dns extends Feature<DnsState, DnsOptions> {
|
|
|
180
193
|
*/
|
|
181
194
|
async resolve(domain: string, type: DnsRecordType, options: QueryOptions = {}): Promise<DnsQueryResult> {
|
|
182
195
|
const args = this.buildDigArgs(domain, type, options)
|
|
183
|
-
const result = await this.proc.spawnAndCapture(
|
|
196
|
+
const result = await this.proc.spawnAndCapture(this.digPath, args)
|
|
184
197
|
|
|
185
198
|
if (result.exitCode !== 0) {
|
|
186
199
|
throw new Error(`dig query failed: ${result.stderr || 'unknown error'}`)
|
|
@@ -446,7 +459,7 @@ export class Dns extends Feature<DnsState, DnsOptions> {
|
|
|
446
459
|
}
|
|
447
460
|
args.unshift('-x', ip)
|
|
448
461
|
|
|
449
|
-
const result = await this.proc.spawnAndCapture(
|
|
462
|
+
const result = await this.proc.spawnAndCapture(this.digPath, args)
|
|
450
463
|
|
|
451
464
|
if (result.exitCode !== 0) {
|
|
452
465
|
throw new Error(`dig reverse lookup failed: ${result.stderr || 'unknown error'}`)
|
|
@@ -101,10 +101,24 @@ export class Docker extends Feature<DockerState, DockerOptions> {
|
|
|
101
101
|
/**
|
|
102
102
|
* Get the proc feature for executing shell commands
|
|
103
103
|
*/
|
|
104
|
+
private _resolvedDockerPath: string | null = null
|
|
105
|
+
|
|
104
106
|
get proc() {
|
|
105
107
|
return this.container.feature('proc')
|
|
106
108
|
}
|
|
107
109
|
|
|
110
|
+
/** Resolve the docker binary path via `which`, caching the result. Options take precedence. */
|
|
111
|
+
get dockerPath(): string {
|
|
112
|
+
if (this.options.dockerPath) return this.options.dockerPath
|
|
113
|
+
if (this._resolvedDockerPath) return this._resolvedDockerPath
|
|
114
|
+
try {
|
|
115
|
+
this._resolvedDockerPath = this.proc.exec('which docker').trim()
|
|
116
|
+
} catch {
|
|
117
|
+
this._resolvedDockerPath = 'docker'
|
|
118
|
+
}
|
|
119
|
+
return this._resolvedDockerPath
|
|
120
|
+
}
|
|
121
|
+
|
|
108
122
|
/**
|
|
109
123
|
* Check if Docker is available and working.
|
|
110
124
|
*
|
|
@@ -117,8 +131,7 @@ export class Docker extends Feature<DockerState, DockerOptions> {
|
|
|
117
131
|
*/
|
|
118
132
|
async checkDockerAvailability(): Promise<boolean> {
|
|
119
133
|
try {
|
|
120
|
-
const
|
|
121
|
-
const result = await this.proc.spawnAndCapture(dockerPath, ['--version'])
|
|
134
|
+
const result = await this.proc.spawnAndCapture(this.dockerPath, ['--version'])
|
|
122
135
|
|
|
123
136
|
if (result.exitCode === 0) {
|
|
124
137
|
this.setState({ isDockerAvailable: true, lastError: undefined })
|
|
@@ -152,8 +165,7 @@ export class Docker extends Feature<DockerState, DockerOptions> {
|
|
|
152
165
|
}
|
|
153
166
|
|
|
154
167
|
try {
|
|
155
|
-
const
|
|
156
|
-
const result = await this.proc.spawnAndCapture(dockerPath, args)
|
|
168
|
+
const result = await this.proc.spawnAndCapture(this.dockerPath, args)
|
|
157
169
|
|
|
158
170
|
if (result.exitCode !== 0) {
|
|
159
171
|
this.setState({ lastError: result.stderr })
|
|
@@ -31,7 +31,7 @@ export class ESBuild extends Feature {
|
|
|
31
31
|
return esbuild.transformSync(code, {
|
|
32
32
|
loader: 'ts',
|
|
33
33
|
format: 'esm',
|
|
34
|
-
target: '
|
|
34
|
+
target: 'esnext',
|
|
35
35
|
sourcemap: false,
|
|
36
36
|
minify: false,
|
|
37
37
|
...options
|
|
@@ -48,12 +48,32 @@ export class ESBuild extends Feature {
|
|
|
48
48
|
return esbuild.transform(code, {
|
|
49
49
|
loader: 'ts',
|
|
50
50
|
format: 'esm',
|
|
51
|
-
target: '
|
|
51
|
+
target: 'esnext',
|
|
52
52
|
sourcemap: false,
|
|
53
53
|
minify: false,
|
|
54
54
|
...options
|
|
55
55
|
})
|
|
56
56
|
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Bundle one or more entry points, resolving imports and requires into a single output.
|
|
60
|
+
* Supports Node platform by default so require() and Node builtins are handled.
|
|
61
|
+
* Returns in-memory output files unless write is enabled in options.
|
|
62
|
+
* @param entryPoints - File paths to bundle from
|
|
63
|
+
* @param options - esbuild BuildOptions overrides
|
|
64
|
+
* @returns The build result with outputFiles when write is false
|
|
65
|
+
*/
|
|
66
|
+
async bundle(entryPoints: string[], options?: esbuild.BuildOptions) {
|
|
67
|
+
return esbuild.build({
|
|
68
|
+
entryPoints,
|
|
69
|
+
bundle: true,
|
|
70
|
+
platform: 'node',
|
|
71
|
+
format: 'esm',
|
|
72
|
+
target: 'esnext',
|
|
73
|
+
write: false,
|
|
74
|
+
...options
|
|
75
|
+
})
|
|
76
|
+
}
|
|
57
77
|
}
|
|
58
78
|
|
|
59
79
|
export default ESBuild
|