@lumerahq/cli 0.31.0-dev.0 → 0.31.0-dev.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,8 +5,8 @@ import { join, resolve } from "path";
5
5
  import pc from "picocolors";
6
6
 
7
7
  // src/lib/functions-sdk.ts
8
- var FUNCTIONS_SDK_VERSION_RANGE = ">=0.38.1,<0.39.0";
9
- var FUNCTIONS_SDK_COMPATIBILITY_RANGE = ">=0.34.0,<0.39.0";
8
+ var FUNCTIONS_SDK_VERSION_RANGE = ">=0.41.2,<0.42.0";
9
+ var FUNCTIONS_SDK_COMPATIBILITY_RANGE = ">=0.34.0,<0.42.0";
10
10
  var FUNCTIONS_SDK_REQUIREMENT = `lumera[functions]${FUNCTIONS_SDK_COMPATIBILITY_RANGE}`;
11
11
  var DEFAULT_FUNCTIONS_SDK_REQUIREMENT = `lumera[functions]${FUNCTIONS_SDK_VERSION_RANGE}`;
12
12
  var RELEASE_SDK_REQUIREMENT = `lumera[release]${FUNCTIONS_SDK_VERSION_RANGE}`;
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  createApiClient,
6
6
  isApiErrorStatus
7
- } from "./chunk-E7YZ6QS6.js";
7
+ } from "./chunk-ZJ7M7JD3.js";
8
8
  import {
9
9
  findProjectRoot,
10
10
  getAppName
@@ -15,9 +15,13 @@ import pc from "picocolors";
15
15
  import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync } from "fs";
16
16
  import { join } from "path";
17
17
  var SHARED_COLLECTIONS_DIR = "platform/collections/shared";
18
+ var SHARED_FUNCTIONS_DIR = "platform/functions/shared";
18
19
  function sharedCollectionsDir(projectRoot) {
19
20
  return join(projectRoot, SHARED_COLLECTIONS_DIR);
20
21
  }
22
+ function sharedFunctionsDir(projectRoot) {
23
+ return join(projectRoot, SHARED_FUNCTIONS_DIR);
24
+ }
21
25
  function safeShareFilenamePart(value) {
22
26
  return value.trim().replace(/[^a-zA-Z0-9._-]+/g, "_").replace(/^_+|_+$/g, "") || "unknown";
23
27
  }
@@ -36,6 +40,13 @@ function readSharedCollectionFile(path) {
36
40
  return null;
37
41
  }
38
42
  }
43
+ function readSharedFunctionFile(path) {
44
+ try {
45
+ return JSON.parse(readFileSync(path, "utf-8"));
46
+ } catch {
47
+ return null;
48
+ }
49
+ }
39
50
  function loadSharedCollectionDeps(projectRoot) {
40
51
  const dir = sharedCollectionsDir(projectRoot);
41
52
  if (!existsSync(dir)) return [];
@@ -53,7 +64,33 @@ function declarationForShare(share, existing) {
53
64
  ...existing ?? {},
54
65
  source_project: share.source_project.external_id,
55
66
  collection: shareCollectionName(share),
56
- privilege: share.privilege,
67
+ privilege: share.privilege === "collection.write" ? "collection.write" : "collection.read",
68
+ reason: typeof existing?.reason === "string" ? existing.reason : ""
69
+ };
70
+ }
71
+ function functionImportFileName(item) {
72
+ const source = safeShareFilenamePart(
73
+ item.source_project.external_id || item.source_project.name || "source"
74
+ );
75
+ return `${source}__${safeShareFilenamePart(item.function_key)}.json`;
76
+ }
77
+ function declarationForFunctionImport(item, existing) {
78
+ return {
79
+ source_project: item.source_project.external_id,
80
+ function: item.function_key,
81
+ import_id: item.id,
82
+ share_id: item.share_id,
83
+ alias: item.local_alias,
84
+ effect: item.version.effect,
85
+ is_async: item.version.is_async,
86
+ pinned: {
87
+ function_version_id: item.version.id,
88
+ release_id: item.version.release_id,
89
+ release_digest: item.version.release_digest,
90
+ runtime_abi: item.version.runtime_abi
91
+ },
92
+ input_schema: item.version.input_schema,
93
+ output_schema: item.version.output_schema,
57
94
  reason: typeof existing?.reason === "string" ? existing.reason : ""
58
95
  };
59
96
  }
@@ -65,10 +102,25 @@ async function listIncomingCollectionShares(api, projectExternalId) {
65
102
  return shareCollectionName(a).localeCompare(shareCollectionName(b));
66
103
  });
67
104
  }
105
+ async function listFunctionImports(api, projectExternalId) {
106
+ try {
107
+ const result = await api.listFunctionImports(projectExternalId);
108
+ return (result.items ?? []).sort((a, b) => {
109
+ const bySource = a.source_project.external_id.localeCompare(b.source_project.external_id);
110
+ if (bySource !== 0) return bySource;
111
+ return a.function_key.localeCompare(b.function_key);
112
+ });
113
+ } catch (e) {
114
+ if (isApiErrorStatus(e, 404)) return [];
115
+ throw e;
116
+ }
117
+ }
68
118
  async function syncResourceShareDeps(projectRoot, api, projectExternalId, opts) {
69
119
  let shares;
120
+ let functionImports;
70
121
  try {
71
122
  shares = await listIncomingCollectionShares(api, projectExternalId);
123
+ functionImports = await listFunctionImports(api, projectExternalId);
72
124
  } catch (e) {
73
125
  if (opts.ignorePermissionDenied && isApiErrorStatus(e, 403)) {
74
126
  console.log(pc.yellow(" \u26A0"), "Skipping resource-share sync \u2014 current token cannot list project shares (403).");
@@ -79,14 +131,32 @@ async function syncResourceShareDeps(projectRoot, api, projectExternalId, opts)
79
131
  }
80
132
  return false;
81
133
  }
82
- if (shares.length === 0) {
134
+ if (shares.length === 0 && functionImports.length === 0) {
83
135
  if (!opts.quiet) console.log(pc.dim(" No incoming resource shares."));
84
136
  return true;
85
137
  }
86
138
  const dir = sharedCollectionsDir(projectRoot);
139
+ const functionsDir = sharedFunctionsDir(projectRoot);
87
140
  const missing = [];
88
141
  if (opts.write) {
89
142
  mkdirSync(dir, { recursive: true });
143
+ mkdirSync(functionsDir, { recursive: true });
144
+ }
145
+ for (const item of functionImports) {
146
+ const fileName = functionImportFileName(item);
147
+ const filePath = join(functionsDir, fileName);
148
+ const exists = existsSync(filePath);
149
+ if (!opts.write) {
150
+ if (!exists) missing.push(`functions/shared/${fileName}`);
151
+ continue;
152
+ }
153
+ const existing = exists ? readSharedFunctionFile(filePath) ?? void 0 : void 0;
154
+ const declaration = declarationForFunctionImport(item, existing);
155
+ writeFileSync(filePath, JSON.stringify(declaration, null, 2) + "\n");
156
+ if (!opts.quiet) {
157
+ const action = exists ? pc.yellow("\u21BB") : pc.green("+");
158
+ console.log(` ${action} functions/shared/${fileName}`);
159
+ }
90
160
  }
91
161
  for (const share of shares) {
92
162
  const fileName = shareFileName(share);
@@ -107,7 +177,9 @@ async function syncResourceShareDeps(projectRoot, api, projectExternalId, opts)
107
177
  if (!opts.write && missing.length > 0) {
108
178
  if (!opts.quiet) {
109
179
  console.log(pc.yellow(` \u26A0 ${missing.length} incoming resource share${missing.length === 1 ? "" : "s"} not synced locally.`));
110
- for (const file of missing) console.log(pc.dim(` collections/shared/${file}`));
180
+ for (const file of missing) {
181
+ console.log(pc.dim(` ${file.includes("/") ? file : `collections/shared/${file}`}`));
182
+ }
111
183
  console.log(pc.dim(` Run ${pc.cyan("lumera deps sync")} to write shared resource declarations.`));
112
184
  }
113
185
  return false;
@@ -151,8 +223,10 @@ async function deps(args) {
151
223
  }
152
224
  if (sub === "list") {
153
225
  const sharedDeps = loadSharedCollectionDeps(projectRoot);
154
- if (sharedDeps.length === 0) {
155
- console.log(pc.dim(" No shared collection declarations in platform/collections/shared"));
226
+ const functionDir = sharedFunctionsDir(projectRoot);
227
+ const functionFiles = existsSync(functionDir) ? readdirSync(functionDir).filter((entry) => entry.endsWith(".json")).sort() : [];
228
+ if (sharedDeps.length === 0 && functionFiles.length === 0) {
229
+ console.log(pc.dim(" No shared resource declarations in platform/*/shared"));
156
230
  return;
157
231
  }
158
232
  console.log();
@@ -165,28 +239,36 @@ async function deps(args) {
165
239
  console.log(` ${pc.bold(file)}`);
166
240
  console.log(` ${source}/${collection} ${pc.dim(`(${privilege})`)}`);
167
241
  }
242
+ for (const file of functionFiles) {
243
+ const dep = readSharedFunctionFile(join(functionDir, file));
244
+ console.log(` ${pc.bold(file)}`);
245
+ console.log(
246
+ ` ${dep?.source_project ?? "unknown-source"}/${dep?.function ?? "unknown-function"} ${pc.dim(`(${dep?.alias ?? "unknown-alias"})`)}`
247
+ );
248
+ }
168
249
  console.log();
169
250
  return;
170
251
  }
171
252
  if (sub === "init") {
172
- const dir = sharedCollectionsDir(projectRoot);
173
- mkdirSync(dir, { recursive: true });
174
- console.log(pc.green(" \u2713"), "Created platform/collections/shared/");
253
+ mkdirSync(sharedCollectionsDir(projectRoot), { recursive: true });
254
+ mkdirSync(sharedFunctionsDir(projectRoot), { recursive: true });
255
+ console.log(pc.green(" \u2713"), "Created platform/collections/shared/ and platform/functions/shared/");
175
256
  return;
176
257
  }
177
258
  console.log(`
178
259
  ${pc.bold("lumera deps")} \u2014 manage cross-project dependencies
179
260
 
180
261
  ${pc.bold("Commands:")}
181
- sync Sync incoming resource shares to platform/collections/shared/*.json
262
+ sync Sync incoming resource shares to platform/*/shared/*.json
182
263
  list Show declared dependencies
183
264
  init Create dependency storage
184
265
 
185
- ${pc.bold("Dependencies:")} platform/collections/shared/*.json
266
+ ${pc.bold("Dependencies:")} platform/collections/shared/*.json and platform/functions/shared/*.json
186
267
  `);
187
268
  }
188
269
 
189
270
  export {
271
+ syncResourceShareDeps,
190
272
  syncDeps,
191
273
  deps
192
274
  };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  userContextHeaders
3
- } from "./chunk-E7YZ6QS6.js";
3
+ } from "./chunk-ZJ7M7JD3.js";
4
4
  import {
5
5
  fetchWithRetry
6
6
  } from "./chunk-FJFIWC7G.js";
@@ -327,6 +327,12 @@ var ApiClient = class {
327
327
  }
328
328
  return all;
329
329
  }
330
+ async getAgentSkill(id, opts) {
331
+ const params = new URLSearchParams();
332
+ if (opts?.resource_urls) params.set("resource_urls", opts.resource_urls);
333
+ const query = params.toString();
334
+ return this.request(`/api/lm_agent_skills/${encodeURIComponent(id)}${query ? `?${query}` : ""}`);
335
+ }
330
336
  async createAgentSkill(def) {
331
337
  return this.request("/api/lm_agent_skills", {
332
338
  method: "POST",
@@ -342,6 +348,24 @@ var ApiClient = class {
342
348
  async deleteAgentSkill(id) {
343
349
  await this.request(`/api/lm_agent_skills/${id}`, { method: "DELETE" });
344
350
  }
351
+ async startAgentSkillResourceUpload(id, resource) {
352
+ return this.request(`/api/lm_agent_skills/${encodeURIComponent(id)}/resource-uploads`, {
353
+ method: "POST",
354
+ body: JSON.stringify(resource)
355
+ });
356
+ }
357
+ async completeAgentSkillResourceUpload(id, uploadId, resource) {
358
+ return this.request(`/api/lm_agent_skills/${encodeURIComponent(id)}/resource-uploads/${encodeURIComponent(uploadId)}/complete`, {
359
+ method: "POST",
360
+ body: JSON.stringify(resource)
361
+ });
362
+ }
363
+ async deleteAgentSkillResource(id, path) {
364
+ return this.request(`/api/lm_agent_skills/${encodeURIComponent(id)}/resources`, {
365
+ method: "PATCH",
366
+ body: JSON.stringify({ operation: "delete", path })
367
+ });
368
+ }
345
369
  // Resolve a list of refs (slugs or IDs) to skill records. Chunks
346
370
  // requests so callers don't have to think about the server-side
347
371
  // per-request cap.
@@ -438,6 +462,11 @@ var ApiClient = class {
438
462
  `/api/projects/${encodeURIComponent(projectExternalId)}/resource-shares${qs}`
439
463
  );
440
464
  }
465
+ async listFunctionImports(projectExternalId) {
466
+ return this.request(
467
+ `/api/projects/${encodeURIComponent(projectExternalId)}/function-imports`
468
+ );
469
+ }
441
470
  // Project manifest — legacy collection list for project_deps.json.
442
471
  async getProjectManifest(externalId) {
443
472
  return this.request(`/api/pb/projects/${encodeURIComponent(externalId)}/manifest`);
@@ -1,13 +1,15 @@
1
1
  import {
2
2
  deps,
3
- syncDeps
4
- } from "./chunk-ODANFLL7.js";
3
+ syncDeps,
4
+ syncResourceShareDeps
5
+ } from "./chunk-HS63O4MH.js";
5
6
  import "./chunk-2CR762KB.js";
6
- import "./chunk-E7YZ6QS6.js";
7
+ import "./chunk-ZJ7M7JD3.js";
7
8
  import "./chunk-JLVVHTBY.js";
8
9
  import "./chunk-FJFIWC7G.js";
9
10
  import "./chunk-PNKVD2UK.js";
10
11
  export {
11
12
  deps,
12
- syncDeps
13
+ syncDeps,
14
+ syncResourceShareDeps
13
15
  };
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  dev
3
- } from "./chunk-2K4ZYGCE.js";
3
+ } from "./chunk-IVII7OZZ.js";
4
4
  import {
5
5
  syncDeps
6
- } from "./chunk-ODANFLL7.js";
6
+ } from "./chunk-HS63O4MH.js";
7
7
  import {
8
8
  loadEnv
9
9
  } from "./chunk-2CR762KB.js";
10
10
  import {
11
11
  createApiClient
12
- } from "./chunk-E7YZ6QS6.js";
12
+ } from "./chunk-ZJ7M7JD3.js";
13
13
  import {
14
14
  findProjectRoot,
15
15
  getApiUrl,
@@ -4,7 +4,7 @@ import {
4
4
  findFunctionsProjectRoot,
5
5
  functions,
6
6
  runFunctionRunner
7
- } from "./chunk-AEZLQMFF.js";
7
+ } from "./chunk-B6Y5CECC.js";
8
8
  import "./chunk-PNKVD2UK.js";
9
9
  export {
10
10
  buildFunctionRunnerArgs,
package/dist/index.js CHANGED
@@ -240,49 +240,49 @@ async function main() {
240
240
  switch (command) {
241
241
  // Resource commands
242
242
  case "plan":
243
- await import("./resources-I6JSKGOX.js").then((m) => m.plan(args.slice(1)));
243
+ await import("./resources-GM2OWDKP.js").then((m) => m.plan(args.slice(1)));
244
244
  break;
245
245
  case "apply":
246
- await import("./resources-I6JSKGOX.js").then((m) => m.apply(args.slice(1)));
246
+ await import("./resources-GM2OWDKP.js").then((m) => m.apply(args.slice(1)));
247
247
  break;
248
248
  case "pull":
249
- await import("./resources-I6JSKGOX.js").then((m) => m.pull(args.slice(1)));
249
+ await import("./resources-GM2OWDKP.js").then((m) => m.pull(args.slice(1)));
250
250
  break;
251
251
  case "destroy":
252
- await import("./resources-I6JSKGOX.js").then((m) => m.destroy(args.slice(1)));
252
+ await import("./resources-GM2OWDKP.js").then((m) => m.destroy(args.slice(1)));
253
253
  break;
254
254
  case "list":
255
- await import("./resources-I6JSKGOX.js").then((m) => m.list(args.slice(1)));
255
+ await import("./resources-GM2OWDKP.js").then((m) => m.list(args.slice(1)));
256
256
  break;
257
257
  case "show":
258
- await import("./resources-I6JSKGOX.js").then((m) => m.show(args.slice(1)));
258
+ await import("./resources-GM2OWDKP.js").then((m) => m.show(args.slice(1)));
259
259
  break;
260
260
  case "diff":
261
- await import("./resources-I6JSKGOX.js").then((m) => m.diff(args.slice(1)));
261
+ await import("./resources-GM2OWDKP.js").then((m) => m.diff(args.slice(1)));
262
262
  break;
263
263
  // Development
264
264
  case "dev":
265
- await import("./dev-S5JVAXDD.js").then((m) => m.dev(args.slice(1)));
265
+ await import("./dev-7ZQRZJXX.js").then((m) => m.dev(args.slice(1)));
266
266
  break;
267
267
  case "run":
268
- await import("./run-MSAMUYQH.js").then((m) => m.run(args.slice(1)));
268
+ await import("./run-7KJPBOIY.js").then((m) => m.run(args.slice(1)));
269
269
  break;
270
270
  case "functions":
271
- await import("./functions-DZCNHDRJ.js").then(
271
+ await import("./functions-WPHGKE54.js").then(
272
272
  (m) => m.functions(subcommand, args.slice(2))
273
273
  );
274
274
  break;
275
275
  case "project":
276
- await import("./project-3HITJUM4.js").then(
276
+ await import("./project-BDRAEZWE.js").then(
277
277
  (m) => m.project(subcommand, args.slice(2))
278
278
  );
279
279
  break;
280
280
  // Project
281
281
  case "init":
282
- await import("./init-QVR42DUW.js").then((m) => m.init(args.slice(1)));
282
+ await import("./init-WE722M4X.js").then((m) => m.init(args.slice(1)));
283
283
  break;
284
284
  case "register":
285
- await import("./register-G3YK77HE.js").then((m) => m.register(args.slice(1)));
285
+ await import("./register-ZXNNU3NJ.js").then((m) => m.register(args.slice(1)));
286
286
  break;
287
287
  case "templates":
288
288
  await import("./templates-LNUOTNLN.js").then((m) => m.templates(subcommand, args.slice(2)));
@@ -299,7 +299,7 @@ async function main() {
299
299
  break;
300
300
  // Dependencies
301
301
  case "deps":
302
- await import("./deps-ZDRNDMUF.js").then((m) => m.deps(args.slice(1)));
302
+ await import("./deps-SIZ77NYE.js").then((m) => m.deps(args.slice(1)));
303
303
  break;
304
304
  // Feature flags (read the in-sandbox snapshot)
305
305
  case "flags":
@@ -12,7 +12,7 @@ import {
12
12
  import {
13
13
  createApiClient,
14
14
  validateProjectNameLength
15
- } from "./chunk-E7YZ6QS6.js";
15
+ } from "./chunk-ZJ7M7JD3.js";
16
16
  import {
17
17
  getToken,
18
18
  init_auth,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  RELEASE_SDK_REQUIREMENT,
3
3
  findFunctionsProjectRoot
4
- } from "./chunk-AEZLQMFF.js";
4
+ } from "./chunk-B6Y5CECC.js";
5
5
  import "./chunk-PNKVD2UK.js";
6
6
 
7
7
  // src/commands/project.ts
@@ -7,7 +7,7 @@ import {
7
7
  import {
8
8
  createApiClient,
9
9
  validateProjectExternalId
10
- } from "./chunk-E7YZ6QS6.js";
10
+ } from "./chunk-ZJ7M7JD3.js";
11
11
  import {
12
12
  findProjectRoot,
13
13
  getAppName,