@larkup/cli 0.2.24 → 0.2.26

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 (45) hide show
  1. package/README.md +8 -0
  2. package/dist/{analytics-store-KI3NXDYV.js → analytics-store-4NYU7DMO.js} +2 -2
  3. package/dist/api-X4PHQJTH.js +6943 -0
  4. package/dist/bowser-GZLEN3PD.js +2821 -0
  5. package/dist/{chroma-BCASZNMJ.js → chroma-RJVBZZMP.js} +2 -11
  6. package/dist/chunk-3EBUYTA7.js +136 -0
  7. package/dist/chunk-4XN2IRCG.js +46 -0
  8. package/dist/{chunk-FM6HYXZ5.js → chunk-5UWKP64Q.js} +24 -72
  9. package/dist/chunk-65EVYGDT.js +2904 -0
  10. package/dist/chunk-A7HMSODH.js +126 -0
  11. package/dist/chunk-BDMLJQRN.js +534 -0
  12. package/dist/chunk-FUTLPXFR.js +921 -0
  13. package/dist/chunk-HAABLEPO.js +1570 -0
  14. package/dist/chunk-HOPZALAP.js +449 -0
  15. package/dist/{chunk-L34L3RDQ.js → chunk-JZ3UCEGF.js} +157 -197
  16. package/dist/chunk-MACWQEJS.js +2091 -0
  17. package/dist/chunk-MYOADNR2.js +515 -0
  18. package/dist/chunk-N6IF5QLH.js +1850 -0
  19. package/dist/chunk-ODWAFTDP.js +1711 -0
  20. package/dist/chunk-QGM4M3NI.js +37 -0
  21. package/dist/chunk-S5DCG3CZ.js +41 -0
  22. package/dist/{chunk-I6JJWCUQ.js → chunk-V3VNCOZ6.js} +118 -29
  23. package/dist/dist-es-5DTOPEBY.js +322 -0
  24. package/dist/dist-es-BM4STLL5.js +70 -0
  25. package/dist/dist-es-DS5SFRTK.js +377 -0
  26. package/dist/dist-es-F6WXDZQY.js +88 -0
  27. package/dist/dist-es-KMHWFNXI.js +295 -0
  28. package/dist/dist-es-LRDDK5LI.js +11761 -0
  29. package/dist/dist-es-LWW2DNRF.js +139 -0
  30. package/dist/dist-es-NEADJWQM.js +176 -0
  31. package/dist/dist-es-S5FAFKBD.js +23 -0
  32. package/dist/dist-es-YD724GH3.js +221 -0
  33. package/dist/event-streams-NPIZBVLJ.js +43 -0
  34. package/dist/index.js +2163 -1798
  35. package/dist/{lancedb-UB2EPDCN.js → lancedb-TCUZKSHN.js} +1 -1
  36. package/dist/lexer-DQCqS3nf-CGRGK47I.js +62 -0
  37. package/dist/loadSso-HXXA5UNF.js +584 -0
  38. package/dist/{pinecone-OHOY4YYM.js → pinecone-ME3YOCQJ.js} +3 -21
  39. package/dist/signin-7FUGJFG3.js +822 -0
  40. package/dist/sso-oidc-EPMF7LMF.js +838 -0
  41. package/dist/sts-RBEOIBEJ.js +1118 -0
  42. package/dist/{tool-loader-KKODIWEV.js → tool-loader-PEQZZWTB.js} +3 -3
  43. package/dist/{tool-registry-CXCFMOWA.js → tool-registry-VJYLRXKJ.js} +2 -2
  44. package/package.json +20 -16
  45. package/dist/chunk-3RG5ZIWI.js +0 -10
@@ -3,12 +3,12 @@ import { promises as fs2 } from "fs";
3
3
  import path2 from "path";
4
4
  import { randomUUID as randomUUID2 } from "crypto";
5
5
 
6
- // ../../packages/core/src/workspace.ts
7
- import { promises as fs } from "fs";
8
- import path from "path";
9
- import { randomUUID } from "crypto";
6
+ // ../../packages/core/src/project-store.ts
10
7
  import { AsyncLocalStorage } from "async_hooks";
8
+ import { randomUUID } from "crypto";
9
+ import { promises as fs } from "fs";
11
10
  import net from "net";
11
+ import path from "path";
12
12
 
13
13
  // ../../packages/core/src/types.ts
14
14
  var DEFAULT_CONFIG = {
@@ -47,223 +47,178 @@ var DEFAULT_CONFIG = {
47
47
  useScraperProxy: false,
48
48
  webCrawlerProvider: "local",
49
49
  firecrawlApiKey: "",
50
+ defaultSandboxProvider: "local",
51
+ sandboxProviderConfigs: {},
50
52
  toolConfigs: {},
53
+ skills: [],
51
54
  updatedAt: (/* @__PURE__ */ new Date(0)).toISOString()
52
55
  };
53
56
 
54
- // ../../packages/core/src/workspace.ts
55
- var ROOT = path.join(process.cwd(), ".larkup");
56
- var SERVERS_DIR = path.join(ROOT, "servers");
57
- var WORKSPACE_PATH = path.join(ROOT, "workspace.json");
57
+ // ../../packages/core/src/project-store.ts
58
+ var LARKUP_ROOT = path.join(process.cwd(), ".larkup");
59
+ var PROJECTS_DIR = path.join(LARKUP_ROOT, "projects");
58
60
  var BASE_PORT = 8080;
59
- var EMPTY = { username: null, activeServerId: null, servers: [], mode: null };
60
- var als = new AsyncLocalStorage();
61
- function runWithServer(serverId, fn) {
62
- return als.run({ serverId }, fn);
63
- }
61
+ var EMPTY_WORKSPACE = { activeProjectId: null, projects: [] };
62
+ var projectScope = new AsyncLocalStorage();
64
63
  var writeChain = Promise.resolve();
65
- function serialize(fn) {
66
- const run = writeChain.then(fn, fn);
67
- writeChain = run.catch(() => {
68
- });
64
+ function serialize(operation) {
65
+ const run = writeChain.then(operation, operation);
66
+ writeChain = run.catch(() => void 0);
69
67
  return run;
70
68
  }
71
- async function serializeWorkspace(fn) {
72
- await getWorkspace();
73
- return serialize(async () => fn(await readRaw() ?? EMPTY));
74
- }
75
- function serverDir(id) {
76
- return path.join(SERVERS_DIR, id);
77
- }
78
- function relServerPath(id, sub) {
79
- return `./.larkup/servers/${id}/${sub}`;
80
- }
81
- async function exists(p) {
82
- try {
83
- await fs.access(p);
84
- return true;
85
- } catch {
86
- return false;
87
- }
88
- }
89
- async function moveIfExists(from, to) {
90
- if (!await exists(from)) return;
91
- await fs.mkdir(path.dirname(to), { recursive: true });
69
+ async function readWorkspaceFile() {
92
70
  try {
93
- await fs.rename(from, to);
94
- } catch {
95
- await fs.cp(from, to, { recursive: true });
96
- await fs.rm(from, { recursive: true, force: true });
97
- }
98
- }
99
- async function readRaw() {
100
- try {
101
- const raw = await fs.readFile(WORKSPACE_PATH, "utf8");
102
- return { ...EMPTY, ...JSON.parse(raw) };
103
- } catch {
104
- return null;
105
- }
106
- }
107
- async function writeRaw(ws) {
108
- await fs.mkdir(ROOT, { recursive: true });
109
- await fs.writeFile(WORKSPACE_PATH, JSON.stringify(ws, null, 2), "utf8");
110
- return ws;
111
- }
112
- async function getWorkspace() {
113
- const existing = await readRaw();
114
- if (existing) return existing;
115
- return serialize(migrateOrInit);
116
- }
117
- async function migrateOrInit() {
118
- const again = await readRaw();
119
- if (again) return again;
120
- const hasLegacy = await exists(path.join(ROOT, "config.json"));
121
- if (!hasLegacy) {
122
- return writeRaw(EMPTY);
123
- }
124
- const id = randomUUID();
125
- const dir = serverDir(id);
126
- await fs.mkdir(dir, { recursive: true });
127
- for (const f of [
128
- "config.json",
129
- "documents.json",
130
- "jobs.json",
131
- "index-run.json",
132
- "server-local.json"
133
- ]) {
134
- await moveIfExists(path.join(ROOT, f), path.join(dir, f));
135
- }
136
- await moveIfExists(path.join(ROOT, "lancedb"), path.join(dir, "lancedb"));
137
- await moveIfExists(path.join(ROOT, "generated-server"), path.join(dir, "generated-server"));
138
- let name = "Default server";
139
- try {
140
- const cfgPath = path.join(dir, "config.json");
141
- const cfg = JSON.parse(await fs.readFile(cfgPath, "utf8"));
142
- if (cfg.projectName) name = cfg.projectName;
143
- if (cfg.vectorStore === "lancedb" && (cfg.storeConfig?.mode ?? "local") === "local") {
144
- cfg.storeConfig = {
145
- ...cfg.storeConfig,
146
- dbPath: relServerPath(id, "lancedb")
147
- };
148
- }
149
- await fs.writeFile(cfgPath, JSON.stringify(cfg, null, 2), "utf8");
71
+ const entries = await fs.readdir(PROJECTS_DIR, { withFileTypes: true });
72
+ const projects = await Promise.all(
73
+ entries.filter((entry) => entry.isDirectory()).map(async (entry) => {
74
+ try {
75
+ return JSON.parse(
76
+ await fs.readFile(path.join(PROJECTS_DIR, entry.name, "project.json"), "utf8")
77
+ );
78
+ } catch {
79
+ return null;
80
+ }
81
+ })
82
+ );
83
+ const resolvedProjects = projects.filter((project) => project !== null);
84
+ const activeProjectId = resolvedProjects.find((project) => project.active)?.id ?? null;
85
+ return {
86
+ activeProjectId,
87
+ projects: resolvedProjects
88
+ };
150
89
  } catch {
90
+ return EMPTY_WORKSPACE;
151
91
  }
152
- const now = (/* @__PURE__ */ new Date()).toISOString();
153
- const meta = {
154
- id,
155
- name,
156
- port: BASE_PORT,
157
- createdAt: now,
158
- updatedAt: now
159
- };
160
- return writeRaw({ username: null, activeServerId: id, servers: [meta], mode: null });
161
92
  }
162
- async function getActiveServer() {
163
- const ws = await getWorkspace();
164
- const override = als.getStore()?.serverId;
165
- const id = override ?? ws.activeServerId;
166
- if (!id) return null;
167
- return ws.servers.find((s) => s.id === id) ?? null;
168
- }
169
- async function getDataDir() {
170
- const server = await getActiveServer();
171
- if (!server) return null;
172
- const dir = serverDir(server.id);
173
- await fs.mkdir(dir, { recursive: true });
174
- return dir;
175
- }
176
- async function requireDataDir() {
177
- const dir = await getDataDir();
178
- if (dir) return dir;
179
- const scopedServerId = als.getStore()?.serverId;
180
- if (scopedServerId) {
181
- throw new Error(`Server "${scopedServerId}" no longer exists.`);
182
- }
183
- const { server } = await createServer("my-larkup");
184
- return serverDir(server.id);
93
+ async function writeWorkspaceFile(workspace) {
94
+ await fs.mkdir(PROJECTS_DIR, { recursive: true });
95
+ await Promise.all(
96
+ workspace.projects.map(async (project) => {
97
+ const persisted = { ...project, active: project.id === workspace.activeProjectId };
98
+ await fs.mkdir(projectDir(project.id), { recursive: true });
99
+ await fs.writeFile(
100
+ path.join(projectDir(project.id), "project.json"),
101
+ JSON.stringify(persisted, null, 2),
102
+ "utf8"
103
+ );
104
+ })
105
+ );
106
+ return workspace;
185
107
  }
186
108
  async function isPortFree(port) {
187
109
  return new Promise((resolve) => {
188
110
  const server = net.createServer();
189
111
  server.once("error", () => resolve(false));
190
- server.once("listening", () => {
191
- server.close(() => resolve(true));
192
- });
112
+ server.once("listening", () => server.close(() => resolve(true)));
193
113
  server.listen(port, "127.0.0.1");
194
114
  });
195
115
  }
196
- async function nextPort(ws) {
197
- const ports = ws.servers.map((s) => s.port);
198
- let candidate = Math.max(BASE_PORT - 1, ...ports) + 1;
199
- while (!await isPortFree(candidate)) {
200
- candidate++;
201
- }
202
- return candidate;
116
+ async function nextPort(workspace) {
117
+ let port = Math.max(BASE_PORT - 1, ...workspace.projects.map((project) => project.port)) + 1;
118
+ while (!await isPortFree(port)) port += 1;
119
+ return port;
120
+ }
121
+ function slugify(name) {
122
+ return name.toLowerCase().trim().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "my-larkup";
203
123
  }
204
- function defaultConfigFor(id, name, prevConfig = {}) {
124
+ function initialConfig(project) {
205
125
  return {
206
126
  ...DEFAULT_CONFIG,
207
- projectName: name.toLowerCase().trim().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "my-larkup",
208
- storeConfig: { mode: "local", dbPath: relServerPath(id, "lancedb") },
209
- embeddingApiKey: prevConfig.embeddingApiKey ?? DEFAULT_CONFIG.embeddingApiKey,
210
- customEmbeddings: prevConfig.customEmbeddings ?? DEFAULT_CONFIG.customEmbeddings,
211
- chatApiKey: prevConfig.chatApiKey ?? DEFAULT_CONFIG.chatApiKey,
212
- customChatModels: prevConfig.customChatModels ?? DEFAULT_CONFIG.customChatModels,
213
- visionApiKey: prevConfig.visionApiKey ?? DEFAULT_CONFIG.visionApiKey,
214
- customVisionModels: prevConfig.customVisionModels ?? DEFAULT_CONFIG.customVisionModels,
215
- serperApiKey: prevConfig.serperApiKey ?? DEFAULT_CONFIG.serperApiKey,
216
- scraperProxyServer: prevConfig.scraperProxyServer ?? DEFAULT_CONFIG.scraperProxyServer,
217
- scraperProxyUsername: prevConfig.scraperProxyUsername ?? DEFAULT_CONFIG.scraperProxyUsername,
218
- scraperProxyPassword: prevConfig.scraperProxyPassword ?? DEFAULT_CONFIG.scraperProxyPassword,
219
- useScraperProxy: prevConfig.useScraperProxy ?? DEFAULT_CONFIG.useScraperProxy,
220
- webCrawlerProvider: prevConfig.webCrawlerProvider ?? DEFAULT_CONFIG.webCrawlerProvider,
221
- firecrawlApiKey: prevConfig.firecrawlApiKey ?? DEFAULT_CONFIG.firecrawlApiKey,
127
+ projectName: slugify(project.name),
128
+ storeConfig: {
129
+ ...DEFAULT_CONFIG.storeConfig,
130
+ mode: "local",
131
+ dbPath: `./.larkup/projects/${project.id}/index`
132
+ },
222
133
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
223
134
  };
224
135
  }
225
- function createServer(name) {
226
- return serializeWorkspace(async (ws) => {
227
- const id = randomUUID();
136
+ function runWithProject(projectId, operation) {
137
+ return projectScope.run({ projectId }, operation);
138
+ }
139
+ function projectDir(projectId) {
140
+ return path.join(PROJECTS_DIR, projectId);
141
+ }
142
+ async function getProjectWorkspace() {
143
+ return readWorkspaceFile();
144
+ }
145
+ async function getActiveProject() {
146
+ const workspace = await getProjectWorkspace();
147
+ const projectId = projectScope.getStore()?.projectId ?? workspace.activeProjectId;
148
+ return workspace.projects.find((project) => project.id === projectId) ?? null;
149
+ }
150
+ async function getProjectDataDir() {
151
+ const project = await getActiveProject();
152
+ if (!project) return null;
153
+ const dir = projectDir(project.id);
154
+ await fs.mkdir(dir, { recursive: true });
155
+ return dir;
156
+ }
157
+ async function requireProjectDataDir() {
158
+ const dir = await getProjectDataDir();
159
+ if (dir) return dir;
160
+ if (projectScope.getStore()?.projectId) {
161
+ throw new Error(`Project "${projectScope.getStore()?.projectId}" does not exist.`);
162
+ }
163
+ const { project } = await createProject("My project");
164
+ return projectDir(project.id);
165
+ }
166
+ function createProject(name) {
167
+ return serialize(async () => {
168
+ const workspace = await readWorkspaceFile();
228
169
  const now = (/* @__PURE__ */ new Date()).toISOString();
229
- const meta = {
230
- id,
231
- name: name.trim() || "Untitled server",
232
- port: await nextPort(ws),
170
+ const project = {
171
+ id: randomUUID(),
172
+ name: name.trim() || "Untitled project",
173
+ port: await nextPort(workspace),
233
174
  createdAt: now,
234
175
  updatedAt: now
235
176
  };
236
- const dir = serverDir(id);
237
- await fs.mkdir(dir, { recursive: true });
238
- let prevConfig = {};
239
- if (ws.activeServerId) {
240
- try {
241
- const raw = await fs.readFile(
242
- path.join(serverDir(ws.activeServerId), "config.json"),
243
- "utf8"
244
- );
245
- prevConfig = JSON.parse(raw);
246
- } catch {
247
- }
248
- }
249
- await fs.writeFile(
250
- path.join(dir, "config.json"),
251
- JSON.stringify(defaultConfigFor(id, meta.name, prevConfig), null, 2),
252
- "utf8"
253
- );
177
+ const dir = projectDir(project.id);
178
+ await fs.mkdir(path.join(dir, "releases"), { recursive: true });
179
+ await Promise.all([
180
+ fs.writeFile(path.join(dir, "project.json"), JSON.stringify({ ...project, active: true }, null, 2), "utf8"),
181
+ fs.writeFile(
182
+ path.join(dir, "config.json"),
183
+ JSON.stringify(initialConfig(project), null, 2),
184
+ "utf8"
185
+ ),
186
+ fs.writeFile(path.join(dir, "groups.json"), JSON.stringify([{
187
+ id: "default",
188
+ name: "Default",
189
+ description: "Sources added without a specific group.",
190
+ icon: "\u{1F4DA}",
191
+ assistantEnabled: true,
192
+ createdAt: now,
193
+ updatedAt: now
194
+ }], null, 2), "utf8"),
195
+ fs.writeFile(path.join(dir, "documents.json"), "[]\n", "utf8"),
196
+ fs.writeFile(path.join(dir, "deployments.json"), "[]\n", "utf8"),
197
+ fs.writeFile(path.join(dir, "automations.json"), "[]\n", "utf8"),
198
+ fs.writeFile(path.join(dir, "jobs.json"), "[]\n", "utf8"),
199
+ fs.writeFile(path.join(dir, "runtime.json"), "{}\n", "utf8")
200
+ ]);
254
201
  const next = {
255
- ...ws,
256
- servers: [...ws.servers, meta],
257
- activeServerId: id
202
+ activeProjectId: project.id,
203
+ projects: [...workspace.projects.map((item) => ({ ...item, active: false })), project]
258
204
  };
259
- await writeRaw(next);
260
- return { workspace: next, server: meta };
205
+ await writeWorkspaceFile(next);
206
+ return { workspace: next, project };
261
207
  });
262
208
  }
263
- function setActiveServer(id) {
264
- return serializeWorkspace(async (ws) => {
265
- if (!ws.servers.some((s) => s.id === id)) return ws;
266
- return writeRaw({ ...ws, activeServerId: id });
209
+ function setActiveProject(projectId) {
210
+ return serialize(async () => {
211
+ const workspace = await readWorkspaceFile();
212
+ if (!workspace.projects.some((project) => project.id === projectId)) return workspace;
213
+ return writeWorkspaceFile({ ...workspace, activeProjectId: projectId });
214
+ });
215
+ }
216
+ async function resetLocalProjects(confirmedPath) {
217
+ if (confirmedPath !== PROJECTS_DIR) {
218
+ throw new Error(`Confirmation must exactly match ${PROJECTS_DIR}.`);
219
+ }
220
+ await serialize(async () => {
221
+ await fs.rm(PROJECTS_DIR, { recursive: true, force: true });
267
222
  });
268
223
  }
269
224
 
@@ -6924,7 +6879,7 @@ function serialize2(fn) {
6924
6879
  return run;
6925
6880
  }
6926
6881
  async function analyticsPath(create) {
6927
- const dir = create ? await requireDataDir() : await getDataDir();
6882
+ const dir = create ? await requireProjectDataDir() : await getProjectDataDir();
6928
6883
  if (!dir) return null;
6929
6884
  return path2.join(dir, "analytics.json");
6930
6885
  }
@@ -6961,11 +6916,15 @@ function estimateCost(modelId, promptTokens, completionTokens) {
6961
6916
  const outputPrice = parseFloat(model.pricing.output || "0");
6962
6917
  return promptTokens * inputPrice + completionTokens * outputPrice;
6963
6918
  }
6964
- async function getAnalyticsSummary(days) {
6919
+ async function getAnalyticsSummary(days, runtime = "all") {
6965
6920
  const events = await readUsageEvents();
6966
6921
  const now = /* @__PURE__ */ new Date();
6967
6922
  const cutoff = days > 0 ? new Date(now.getTime() - days * 24 * 60 * 60 * 1e3) : /* @__PURE__ */ new Date(0);
6968
- const filtered = events.filter((e) => new Date(e.timestamp) >= cutoff);
6923
+ const filtered = events.filter((e) => {
6924
+ if (new Date(e.timestamp) < cutoff || runtime === "all") return new Date(e.timestamp) >= cutoff;
6925
+ const inferredRuntime = e.runtime ?? (/(localhost|127\.0\.0\.1|\[::1\])/.test(e.endpoint ?? "") ? "local" : "remote");
6926
+ return inferredRuntime === runtime;
6927
+ });
6969
6928
  const summary = {
6970
6929
  totalChatTokens: 0,
6971
6930
  totalEmbeddingTokens: 0,
@@ -7051,13 +7010,14 @@ async function getAnalyticsSummary(days) {
7051
7010
 
7052
7011
  export {
7053
7012
  DEFAULT_CONFIG,
7054
- runWithServer,
7055
- getWorkspace,
7056
- getActiveServer,
7057
- getDataDir,
7058
- requireDataDir,
7059
- createServer,
7060
- setActiveServer,
7013
+ runWithProject,
7014
+ getProjectWorkspace,
7015
+ getActiveProject,
7016
+ getProjectDataDir,
7017
+ requireProjectDataDir,
7018
+ createProject,
7019
+ setActiveProject,
7020
+ resetLocalProjects,
7061
7021
  ALL_MODELS,
7062
7022
  readUsageEvents,
7063
7023
  trackUsageEvent,