@usecontextlayer/cli 0.14.2 → 0.14.3

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.
@@ -1,5 +1,5 @@
1
- import { mkdir, readFile, writeFile } from "node:fs/promises";
2
- import path, { join } from "node:path";
1
+ import { glob, mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import path, { join, resolve } from "node:path";
3
3
  import { EventEmitter, addAbortListener, on, once, setMaxListeners } from "node:events";
4
4
  import { ChildProcess, execFile, spawn, spawnSync } from "node:child_process";
5
5
  import fs, { appendFileSync, closeSync, createReadStream, createWriteStream, openSync, readFileSync, readSync, statSync, writeFileSync } from "node:fs";
@@ -9836,6 +9836,7 @@ const initializer = (inst, issues) => {
9836
9836
  } }
9837
9837
  });
9838
9838
  };
9839
+ const ZodError = /*@__PURE__*/ $constructor("ZodError", initializer);
9839
9840
  const ZodRealError = /*@__PURE__*/ $constructor("ZodError", initializer, { Parent: Error });
9840
9841
  //#endregion
9841
9842
  //#region ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/parse.js
@@ -10688,6 +10689,85 @@ function superRefine(fn, params) {
10688
10689
  return /* @__PURE__ */ _superRefine(fn, params);
10689
10690
  }
10690
10691
  //#endregion
10692
+ //#region ../shared/dist/slate.mjs
10693
+ const credentialModeSchema = _enum(["viewer", "owner"]);
10694
+ const connectionRequirementSchema = strictObject({
10695
+ mode: credentialModeSchema,
10696
+ toolkit: string().min(1)
10697
+ });
10698
+ const secretNameSchema = string().regex(/^[A-Z_][A-Z0-9_]*$/);
10699
+ const secretRequirementSchema = strictObject({ mode: credentialModeSchema });
10700
+ const folderRequirementSchema = strictObject({ mode: credentialModeSchema });
10701
+ const slateSchema = strictObject({
10702
+ connections: record(string().min(1), connectionRequirementSchema),
10703
+ folders: record(string().min(1), folderRequirementSchema).default({}),
10704
+ secrets: record(secretNameSchema, secretRequirementSchema).default({})
10705
+ });
10706
+ strictObject({
10707
+ agents: record(string().min(1), slateSchema),
10708
+ app: slateSchema
10709
+ });
10710
+ const resourceConsumerSchema = discriminatedUnion("type", [strictObject({ type: literal("app") }), strictObject({
10711
+ name: string().min(1),
10712
+ type: literal("agent")
10713
+ })]);
10714
+ const resourcesSchema = slateSchema.extend({
10715
+ connections: record(string().min(1), connectionRequirementSchema.extend({ consumers: array(resourceConsumerSchema) })),
10716
+ folders: record(string().min(1), folderRequirementSchema.extend({ consumers: array(resourceConsumerSchema) })),
10717
+ secrets: record(secretNameSchema, secretRequirementSchema.extend({ consumers: array(resourceConsumerSchema) }))
10718
+ });
10719
+ function collectAppResources(slates) {
10720
+ const declarations = [{
10721
+ consumer: { type: "app" },
10722
+ slate: slates.app
10723
+ }, ...Object.entries(slates.agents).map(([name, slate]) => ({
10724
+ consumer: {
10725
+ name,
10726
+ type: "agent"
10727
+ },
10728
+ slate
10729
+ }))];
10730
+ return {
10731
+ connections: collectRequirements("connections", declarations, (slate) => slate.connections),
10732
+ folders: collectRequirements("folders", declarations, (slate) => slate.folders),
10733
+ secrets: collectRequirements("secrets", declarations, (slate) => slate.secrets)
10734
+ };
10735
+ }
10736
+ function resourcesForConsumer(resources, consumer) {
10737
+ return {
10738
+ connections: filterRequirements(resources.connections, consumer),
10739
+ folders: filterRequirements(resources.folders, consumer),
10740
+ secrets: filterRequirements(resources.secrets, consumer)
10741
+ };
10742
+ }
10743
+ function filterRequirements(requirements, consumer) {
10744
+ return Object.fromEntries(Object.entries(requirements).filter(([, requirement]) => requirement.consumers.some((declared) => declared.type === consumer.type && (consumer.type === "app" || declared.type === "agent" && declared.name === consumer.name))));
10745
+ }
10746
+ function collectRequirements(category, declarations, select) {
10747
+ const resources = /* @__PURE__ */ new Map();
10748
+ for (const { consumer, slate } of declarations) for (const [name, requirement] of Object.entries(select(slate))) {
10749
+ const existing = resources.get(name);
10750
+ if (!existing) {
10751
+ resources.set(name, {
10752
+ ...requirement,
10753
+ consumers: [consumer]
10754
+ });
10755
+ continue;
10756
+ }
10757
+ if (existing.mode !== requirement.mode || existing.toolkit !== requirement.toolkit) throw new ZodError([{
10758
+ code: "custom",
10759
+ message: `Conflicting ${category} requirement "${name}": declarations must agree on mode${category === "connections" ? " and toolkit" : ""}`,
10760
+ path: [
10761
+ ...consumer.type === "app" ? ["app"] : ["agents", consumer.name],
10762
+ category,
10763
+ name
10764
+ ]
10765
+ }]);
10766
+ existing.consumers.push(consumer);
10767
+ }
10768
+ return Object.fromEntries(resources);
10769
+ }
10770
+ //#endregion
10691
10771
  //#region ../../node_modules/.pnpm/oauth4webapi@3.8.8/node_modules/oauth4webapi/build/index.js
10692
10772
  let USER_AGENT$1;
10693
10773
  if (typeof navigator === "undefined" || !navigator.userAgent?.startsWith?.("Mozilla/5.0 ")) USER_AGENT$1 = `oauth4webapi/v3.8.8`;
@@ -11807,6 +11887,9 @@ function retryable(err, options) {
11807
11887
  const retry = Symbol();
11808
11888
  //#endregion
11809
11889
  //#region env.ts
11890
+ function readLocalSecret(name) {
11891
+ return process.env[name] ?? null;
11892
+ }
11810
11893
  const env = object({
11811
11894
  CTX_AUTH_CLIENT_ID: string().min(1).default("QBFOYTTCdjpEiXwgDNnovDPoJBYAfRpF"),
11812
11895
  CTX_AUTH_ISSUER: url().default("https://www.usecontextlayer.com/api/auth"),
@@ -11876,20 +11959,23 @@ async function whoami() {
11876
11959
  console.log(user.id);
11877
11960
  }
11878
11961
  //#endregion
11879
- //#region ../shared/dist/slate.mjs
11880
- const credentialModeSchema = _enum(["viewer", "owner"]);
11881
- const connectionRequirementSchema = strictObject({
11882
- mode: credentialModeSchema,
11883
- toolkit: string().min(1)
11884
- });
11885
- const secretNameSchema = string().regex(/^[A-Z_][A-Z0-9_]*$/);
11886
- const secretRequirementSchema = strictObject({ mode: credentialModeSchema });
11887
- const slateSchema = strictObject({
11888
- connections: record(string().min(1), connectionRequirementSchema),
11889
- secrets: record(secretNameSchema, secretRequirementSchema).default({})
11890
- });
11891
- //#endregion
11892
11962
  //#region app.ts
11963
+ async function resolveAppTarget(target) {
11964
+ return target === "local" ? getLocalAppId() : target;
11965
+ }
11966
+ async function joinApp(target) {
11967
+ const appTarget = await resolveAppTarget(target);
11968
+ const response = await fetch(new URL(`/api/apps/${encodeURIComponent(appTarget)}/join`, env.CTX_PLATFORM_URL), {
11969
+ headers: { authorization: `Bearer ${await getAccessToken()}` },
11970
+ method: "POST"
11971
+ });
11972
+ if (!response.ok) throw new Error(`App join failed: HTTP ${response.status}`);
11973
+ const member = object({
11974
+ app_id: uuid(),
11975
+ user_id: string().min(1)
11976
+ }).parse(await response.json());
11977
+ console.log(JSON.stringify(member));
11978
+ }
11893
11979
  async function getLocalAppId() {
11894
11980
  const { stdout: remote } = await execa("git", [
11895
11981
  "remote",
@@ -11898,10 +11984,102 @@ async function getLocalAppId() {
11898
11984
  ]);
11899
11985
  return uuid().parse(new URL(remote).pathname.replace(/^\/git\//, ""));
11900
11986
  }
11901
- async function readLocalManifest() {
11902
- return slateSchema.parse(JSON.parse(await readFile("public/slate.json", "utf8")));
11987
+ async function readLocalResources(directory = process.cwd()) {
11988
+ const app = await readLocalSlate(join(directory, "public/slate.json"));
11989
+ const agents = {};
11990
+ for await (const entry of glob("agents/*", {
11991
+ cwd: directory,
11992
+ withFileTypes: true
11993
+ })) if (entry.isDirectory()) agents[entry.name] = await readLocalSlate(join(directory, "agents", entry.name, "slate.json"));
11994
+ return collectAppResources({
11995
+ agents,
11996
+ app
11997
+ });
11998
+ }
11999
+ async function readLocalSlate(path) {
12000
+ return slateSchema.parse(JSON.parse(await readFile(path, "utf8")));
12001
+ }
12002
+ //#endregion
12003
+ //#region ../shared/dist/app-usage.mjs
12004
+ const ownerSchema = discriminatedUnion("type", [object({
12005
+ id: string().min(1),
12006
+ type: literal("user")
12007
+ }), object({
12008
+ id: string().min(1),
12009
+ type: literal("organization")
12010
+ })]);
12011
+ object({
12012
+ id: uuid(),
12013
+ owner: ownerSchema
12014
+ });
12015
+ //#endregion
12016
+ //#region ../shared/dist/app-resources.mjs
12017
+ const appResourceConfigurationSchema = resourcesSchema.extend({
12018
+ connections: record(resourcesSchema.shape.connections.keyType, resourcesSchema.shape.connections.valueType.extend({
12019
+ connection_id: string().nullable(),
12020
+ owner: ownerSchema
12021
+ })),
12022
+ folders: record(resourcesSchema.shape.folders.keyType, resourcesSchema.shape.folders.valueType.extend({ owner: ownerSchema })),
12023
+ secrets: record(resourcesSchema.shape.secrets.keyType, resourcesSchema.shape.secrets.valueType.extend({ owner: ownerSchema }))
12024
+ });
12025
+ object({ resources: appResourceConfigurationSchema });
12026
+ const localResourceConfigurationSchema = resourcesSchema.extend({
12027
+ connections: record(resourcesSchema.shape.connections.keyType, resourcesSchema.shape.connections.valueType.extend({ connection_id: string().min(1).nullable() })),
12028
+ folders: record(resourcesSchema.shape.folders.keyType.regex(/^(?!\.{1,2}$)[^/\\]+$/), resourcesSchema.shape.folders.valueType.extend({ path: string().min(1) })),
12029
+ secrets: record(resourcesSchema.shape.secrets.keyType, resourcesSchema.shape.secrets.valueType.extend({ value: string().nullable() }))
12030
+ });
12031
+ //#endregion
12032
+ //#region resources.ts
12033
+ const localConnectionsSchema = record(resourcesSchema.shape.connections.keyType, string().min(1));
12034
+ async function readOptionalFile(path) {
12035
+ try {
12036
+ return await readFile(path, "utf8");
12037
+ } catch (error) {
12038
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") return null;
12039
+ throw error;
12040
+ }
11903
12041
  }
11904
- //#endregion
11905
- export { execa as S, record as _, getAccessToken as a, url as b, whoami as c, boolean as d, discriminatedUnion as f, object as g, looseObject as h, secretNameSchema as i, env as l, literal as m, readLocalManifest as n, getCurrentUser as o, hostname as p, connectionRequirementSchema as r, login as s, getLocalAppId as t, array as u, string as v, uuid as x, unknown as y };
12042
+ async function readLocalConnections(directory) {
12043
+ const contents = await readOptionalFile(resolve(directory, ".contextlayer/connections.json"));
12044
+ return localConnectionsSchema.parse(contents === null ? {} : JSON.parse(contents));
12045
+ }
12046
+ async function prepareLocalDirectory(directory) {
12047
+ await mkdir(resolve(directory, ".contextlayer"), { recursive: true });
12048
+ const ignorePath = resolve(directory, ".gitignore");
12049
+ const contents = await readOptionalFile(ignorePath) ?? "";
12050
+ if (!contents.split(/\r?\n/).includes("/.contextlayer/")) await writeFile(ignorePath, `${contents}${contents && !contents.endsWith("\n") ? "\n" : ""}/.contextlayer/\n`);
12051
+ }
12052
+ async function prepareLocalResourceConfiguration(directory = process.cwd()) {
12053
+ const resources = await readLocalResources(directory);
12054
+ const bindings = new Map(Object.entries(await readLocalConnections(directory)));
12055
+ const configuration = localResourceConfigurationSchema.parse({
12056
+ connections: Object.fromEntries(Object.entries(resources.connections).map(([slug, requirement]) => [slug, {
12057
+ ...requirement,
12058
+ connection_id: bindings.get(slug) ?? null
12059
+ }])),
12060
+ folders: Object.fromEntries(Object.entries(resources.folders).map(([slug, requirement]) => [slug, {
12061
+ ...requirement,
12062
+ path: resolve(directory, ".contextlayer", "folders", slug)
12063
+ }])),
12064
+ secrets: Object.fromEntries(Object.entries(resources.secrets).map(([name, requirement]) => [name, {
12065
+ ...requirement,
12066
+ value: readLocalSecret(name)
12067
+ }]))
12068
+ });
12069
+ await prepareLocalDirectory(directory);
12070
+ await Promise.all(Object.values(configuration.folders).map(({ path }) => mkdir(path, { recursive: true })));
12071
+ return configuration;
12072
+ }
12073
+ async function saveLocalConnection(slug, connectionId, directory = process.cwd()) {
12074
+ const binding = localConnectionsSchema.parse({ [slug]: connectionId });
12075
+ const connections = {
12076
+ ...await readLocalConnections(directory),
12077
+ ...binding
12078
+ };
12079
+ await prepareLocalDirectory(directory);
12080
+ await writeFile(resolve(directory, ".contextlayer/connections.json"), `${JSON.stringify(connections, null, 2)}\n`);
12081
+ }
12082
+ //#endregion
12083
+ export { unknown as C, execa as E, union as S, uuid as T, literal as _, getLocalAppId as a, record as b, getCurrentUser as c, env as d, resourcesForConsumer as f, hostname as g, boolean as h, ownerSchema as i, login as l, array as m, saveLocalConnection as n, joinApp as o, secretNameSchema as p, appResourceConfigurationSchema as r, getAccessToken as s, prepareLocalResourceConfiguration as t, whoami as u, looseObject as v, url as w, string as x, object as y };
11906
12084
 
11907
- //# sourceMappingURL=app-CJgT3IKd.mjs.map
12085
+ //# sourceMappingURL=resources-DEdwfmku.mjs.map