@semiont/cli 0.4.2 → 0.4.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.
Files changed (3) hide show
  1. package/README.md +108 -455
  2. package/dist/cli.mjs +1486 -546
  3. package/package.json +8 -10
package/dist/cli.mjs CHANGED
@@ -4206,20 +4206,26 @@ var init_zod = __esm({
4206
4206
  });
4207
4207
 
4208
4208
  // src/core/base-options-schema.ts
4209
- function withBaseArgs(commandArgs = {}, commandAliases = {}, positional) {
4209
+ function withOpsArgs(commandArgs = {}, commandAliases = {}, positional) {
4210
4210
  return {
4211
- args: { ...BASE_ARGS, ...commandArgs },
4212
- aliases: { ...BASE_ALIASES, ...commandAliases },
4211
+ args: { ...BASE_ARGS, ...OPS_ARGS, ...commandArgs },
4212
+ aliases: { ...BASE_ALIASES, ...OPS_ALIASES, ...commandAliases },
4213
4213
  ...positional && { positional }
4214
4214
  };
4215
4215
  }
4216
- var BaseOptionsSchema, CommonExtensions, BASE_ARGS, BASE_ALIASES;
4216
+ function withApiArgs(commandArgs = {}, commandAliases = {}, positional) {
4217
+ return {
4218
+ args: { ...BASE_ARGS, ...API_ARGS, ...commandArgs },
4219
+ aliases: { ...BASE_ALIASES, ...API_ALIASES, ...commandAliases },
4220
+ ...positional && { positional }
4221
+ };
4222
+ }
4223
+ var BaseOptionsSchema, OpsOptionsSchema, ApiOptionsSchema, CommonExtensions, BASE_ARGS, OPS_ARGS, API_ARGS, BASE_ALIASES, OPS_ALIASES, API_ALIASES;
4217
4224
  var init_base_options_schema = __esm({
4218
4225
  "src/core/base-options-schema.ts"() {
4219
4226
  "use strict";
4220
4227
  init_zod();
4221
4228
  BaseOptionsSchema = external_exports.object({
4222
- environment: external_exports.string().optional(),
4223
4229
  verbose: external_exports.boolean().optional().default(false),
4224
4230
  dryRun: external_exports.boolean().optional().default(false),
4225
4231
  quiet: external_exports.boolean().optional().default(false),
@@ -4227,6 +4233,12 @@ var init_base_options_schema = __esm({
4227
4233
  forceDiscovery: external_exports.boolean().optional().default(false),
4228
4234
  preflight: external_exports.boolean().optional().default(false)
4229
4235
  });
4236
+ OpsOptionsSchema = BaseOptionsSchema.extend({
4237
+ environment: external_exports.string().optional()
4238
+ });
4239
+ ApiOptionsSchema = BaseOptionsSchema.extend({
4240
+ bus: external_exports.string().optional()
4241
+ });
4230
4242
  CommonExtensions = {
4231
4243
  service: external_exports.string().optional(),
4232
4244
  all: external_exports.boolean().optional().default(false),
@@ -4236,11 +4248,6 @@ var init_base_options_schema = __esm({
4236
4248
  registry: external_exports.string().optional()
4237
4249
  };
4238
4250
  BASE_ARGS = {
4239
- "--environment": {
4240
- type: "string",
4241
- description: "Target environment",
4242
- required: false
4243
- },
4244
4251
  "--verbose": {
4245
4252
  type: "boolean",
4246
4253
  description: "Verbose output",
@@ -4273,12 +4280,30 @@ var init_base_options_schema = __esm({
4273
4280
  default: false
4274
4281
  }
4275
4282
  };
4283
+ OPS_ARGS = {
4284
+ "--environment": {
4285
+ type: "string",
4286
+ description: "Target environment",
4287
+ required: false
4288
+ }
4289
+ };
4290
+ API_ARGS = {
4291
+ "--bus": {
4292
+ type: "string",
4293
+ description: "Backend URL (e.g. http://localhost:4000). Fallback: $SEMIONT_BUS. Use `semiont login` to authenticate."
4294
+ }
4295
+ };
4276
4296
  BASE_ALIASES = {
4277
- "-e": "--environment",
4278
4297
  "-v": "--verbose",
4279
4298
  "-q": "--quiet",
4280
4299
  "-o": "--output"
4281
4300
  };
4301
+ OPS_ALIASES = {
4302
+ "-e": "--environment"
4303
+ };
4304
+ API_ALIASES = {
4305
+ "-b": "--bus"
4306
+ };
4282
4307
  }
4283
4308
  });
4284
4309
 
@@ -4410,20 +4435,20 @@ function findPortOwner(port) {
4410
4435
  return null;
4411
4436
  }
4412
4437
  async function checkPortFree(port) {
4413
- return new Promise((resolve12) => {
4438
+ return new Promise((resolve10) => {
4414
4439
  const server = net.createServer();
4415
4440
  server.once("error", (err) => {
4416
4441
  if (err.code === "EADDRINUSE") {
4417
4442
  const owner = findPortOwner(port);
4418
4443
  const hint = owner ? ` (${owner})` : "";
4419
- resolve12({ name: `port-${port}`, pass: false, message: `Port ${port} is in use${hint}` });
4444
+ resolve10({ name: `port-${port}`, pass: false, message: `Port ${port} is in use${hint}` });
4420
4445
  } else {
4421
- resolve12({ name: `port-${port}`, pass: false, message: `Cannot check port ${port}: ${err.message}` });
4446
+ resolve10({ name: `port-${port}`, pass: false, message: `Cannot check port ${port}: ${err.message}` });
4422
4447
  }
4423
4448
  });
4424
4449
  server.once("listening", () => {
4425
4450
  server.close(() => {
4426
- resolve12({ name: `port-${port}`, pass: true, message: `Port ${port} is available` });
4451
+ resolve10({ name: `port-${port}`, pass: true, message: `Port ${port} is available` });
4427
4452
  });
4428
4453
  });
4429
4454
  server.listen(port, "127.0.0.1");
@@ -6439,18 +6464,18 @@ var init_state_manager = __esm({
6439
6464
  // src/core/io/network-utils.ts
6440
6465
  import * as net2 from "net";
6441
6466
  async function isPortInUse(port) {
6442
- return new Promise((resolve12) => {
6467
+ return new Promise((resolve10) => {
6443
6468
  const server = net2.createServer();
6444
6469
  server.once("error", (err) => {
6445
6470
  if (err.code === "EADDRINUSE") {
6446
- resolve12(true);
6471
+ resolve10(true);
6447
6472
  } else {
6448
- resolve12(false);
6473
+ resolve10(false);
6449
6474
  }
6450
6475
  });
6451
6476
  server.once("listening", () => {
6452
6477
  server.close();
6453
- resolve12(false);
6478
+ resolve10(false);
6454
6479
  });
6455
6480
  server.listen(port);
6456
6481
  });
@@ -7468,7 +7493,7 @@ var init_database_start = __esm({
7468
7493
  // Use path for data directory
7469
7494
  }
7470
7495
  };
7471
- await new Promise((resolve12) => setTimeout(resolve12, 2e3));
7496
+ await new Promise((resolve10) => setTimeout(resolve10, 2e3));
7472
7497
  return {
7473
7498
  success: true,
7474
7499
  endpoint,
@@ -7690,7 +7715,7 @@ async function startJanusGraph(context) {
7690
7715
  let ready = false;
7691
7716
  const maxAttempts = 30;
7692
7717
  for (let i = 0; i < maxAttempts; i++) {
7693
- await new Promise((resolve12) => setTimeout(resolve12, 2e3));
7718
+ await new Promise((resolve10) => setTimeout(resolve10, 2e3));
7694
7719
  try {
7695
7720
  const { execFileSync: execFileSync43 } = await import("child_process");
7696
7721
  execFileSync43(gremlinShellScript, ["-e", "g.V().count()"], {
@@ -7957,7 +7982,7 @@ var init_backend_start = __esm({
7957
7982
  appLogStream.end();
7958
7983
  errorLogStream.end();
7959
7984
  proc.unref();
7960
- await new Promise((resolve12) => setTimeout(resolve12, 2e3));
7985
+ await new Promise((resolve10) => setTimeout(resolve10, 2e3));
7961
7986
  try {
7962
7987
  process.kill(proc.pid, 0);
7963
7988
  } catch {
@@ -8193,7 +8218,7 @@ var init_frontend_start = __esm({
8193
8218
  appLogStream.end();
8194
8219
  errorLogStream.end();
8195
8220
  proc.unref();
8196
- await new Promise((resolve12) => setTimeout(resolve12, 2e3));
8221
+ await new Promise((resolve10) => setTimeout(resolve10, 2e3));
8197
8222
  try {
8198
8223
  process.kill(proc.pid, 0);
8199
8224
  } catch {
@@ -8367,7 +8392,7 @@ var init_proxy_start = __esm({
8367
8392
  _ENVOY_PID: pidFile
8368
8393
  }
8369
8394
  });
8370
- await new Promise((resolve12) => setTimeout(resolve12, 2e3));
8395
+ await new Promise((resolve10) => setTimeout(resolve10, 2e3));
8371
8396
  if (!fs18.existsSync(pidFile)) {
8372
8397
  return {
8373
8398
  success: false,
@@ -8478,7 +8503,7 @@ var init_mcp_provision = __esm({
8478
8503
  if (!service.quiet) {
8479
8504
  printInfo("\u{1F510} Setting up MCP authentication...");
8480
8505
  }
8481
- return new Promise((resolve12, _reject) => {
8506
+ return new Promise((resolve10, _reject) => {
8482
8507
  let timeoutId;
8483
8508
  const connections = /* @__PURE__ */ new Set();
8484
8509
  const server = http.createServer((req, res) => {
@@ -8525,7 +8550,7 @@ var init_mcp_provision = __esm({
8525
8550
  }
8526
8551
  }, null, 2));
8527
8552
  }
8528
- resolve12({
8553
+ resolve10({
8529
8554
  success: true,
8530
8555
  metadata: {
8531
8556
  serviceType: "mcp",
@@ -8535,7 +8560,7 @@ var init_mcp_provision = __esm({
8535
8560
  }
8536
8561
  });
8537
8562
  } else {
8538
- resolve12({
8563
+ resolve10({
8539
8564
  success: false,
8540
8565
  error: "No token received from authentication",
8541
8566
  metadata: {
@@ -8577,7 +8602,7 @@ var init_mcp_provision = __esm({
8577
8602
  timeoutId = setTimeout(() => {
8578
8603
  connections.forEach((conn) => conn.destroy());
8579
8604
  server.close();
8580
- resolve12({
8605
+ resolve10({
8581
8606
  success: false,
8582
8607
  error: "Authentication timeout - please try again",
8583
8608
  metadata: {
@@ -9064,18 +9089,18 @@ import * as path20 from "path";
9064
9089
  import { fileURLToPath } from "url";
9065
9090
  function getTemplatesDir(importMetaUrl) {
9066
9091
  const filename = fileURLToPath(importMetaUrl);
9067
- const dirname15 = path20.dirname(filename);
9068
- if (dirname15.includes(path20.sep + "src" + path20.sep)) {
9069
- let dir = dirname15;
9092
+ const dirname16 = path20.dirname(filename);
9093
+ if (dirname16.includes(path20.sep + "src" + path20.sep)) {
9094
+ let dir = dirname16;
9070
9095
  while (dir !== path20.dirname(dir)) {
9071
9096
  if (path20.basename(dir) === "src") {
9072
9097
  return path20.join(path20.dirname(dir), "templates");
9073
9098
  }
9074
9099
  dir = path20.dirname(dir);
9075
9100
  }
9076
- throw new Error(`Cannot locate templates directory from source path: ${dirname15}`);
9101
+ throw new Error(`Cannot locate templates directory from source path: ${dirname16}`);
9077
9102
  }
9078
- return path20.join(dirname15, "templates");
9103
+ return path20.join(dirname16, "templates");
9079
9104
  }
9080
9105
  var init_cli_paths = __esm({
9081
9106
  "src/core/io/cli-paths.ts"() {
@@ -9257,7 +9282,7 @@ async function stopJanusGraph(context) {
9257
9282
  const startTime = Date.now();
9258
9283
  let processRunning = true;
9259
9284
  while (processRunning && Date.now() - startTime < timeout) {
9260
- await new Promise((resolve12) => setTimeout(resolve12, 1e3));
9285
+ await new Promise((resolve10) => setTimeout(resolve10, 1e3));
9261
9286
  try {
9262
9287
  process.kill(pid, 0);
9263
9288
  } catch {
@@ -9360,14 +9385,14 @@ async function killProcessGroupAndRelated(pid, serviceType, verbose = false) {
9360
9385
  }
9361
9386
  process.kill(-pid, "SIGTERM");
9362
9387
  killed = true;
9363
- await new Promise((resolve12) => setTimeout(resolve12, 2e3));
9388
+ await new Promise((resolve10) => setTimeout(resolve10, 2e3));
9364
9389
  try {
9365
9390
  process.kill(pid, 0);
9366
9391
  if (verbose) {
9367
9392
  printWarning(`Process group didn't terminate gracefully, force killing...`);
9368
9393
  }
9369
9394
  process.kill(-pid, "SIGKILL");
9370
- await new Promise((resolve12) => setTimeout(resolve12, 1e3));
9395
+ await new Promise((resolve10) => setTimeout(resolve10, 1e3));
9371
9396
  } catch {
9372
9397
  }
9373
9398
  } catch (error) {
@@ -9376,7 +9401,7 @@ async function killProcessGroupAndRelated(pid, serviceType, verbose = false) {
9376
9401
  }
9377
9402
  try {
9378
9403
  process.kill(pid, "SIGTERM");
9379
- await new Promise((resolve12) => setTimeout(resolve12, 2e3));
9404
+ await new Promise((resolve10) => setTimeout(resolve10, 2e3));
9380
9405
  try {
9381
9406
  process.kill(pid, 0);
9382
9407
  process.kill(pid, "SIGKILL");
@@ -10043,7 +10068,7 @@ var init_inference_start = __esm({
10043
10068
  const maxAttempts = 15;
10044
10069
  let ready = false;
10045
10070
  for (let i = 0; i < maxAttempts; i++) {
10046
- await new Promise((resolve12) => setTimeout(resolve12, 1e3));
10071
+ await new Promise((resolve10) => setTimeout(resolve10, 1e3));
10047
10072
  if (await isOllamaRunning(port)) {
10048
10073
  ready = true;
10049
10074
  break;
@@ -10159,7 +10184,7 @@ var init_inference_stop = __esm({
10159
10184
  const startTime = Date.now();
10160
10185
  let processRunning = true;
10161
10186
  while (processRunning && Date.now() - startTime < timeout) {
10162
- await new Promise((resolve12) => setTimeout(resolve12, 1e3));
10187
+ await new Promise((resolve10) => setTimeout(resolve10, 1e3));
10163
10188
  try {
10164
10189
  process.kill(pid, 0);
10165
10190
  } catch {
@@ -11226,7 +11251,7 @@ async function waitForContainer(runtime, containerName) {
11226
11251
  }
11227
11252
  } catch {
11228
11253
  }
11229
- await new Promise((resolve12) => setTimeout(resolve12, 1e3));
11254
+ await new Promise((resolve10) => setTimeout(resolve10, 1e3));
11230
11255
  attempts++;
11231
11256
  }
11232
11257
  throw new Error(`Container ${containerName} failed to start within ${maxAttempts} seconds`);
@@ -11336,7 +11361,7 @@ import { execFileSync as execFileSync19 } from "child_process";
11336
11361
  async function waitForDatabase(runtime, containerName, image, quiet, dbUser, verbose) {
11337
11362
  const maxAttempts = 15;
11338
11363
  let attempts = 0;
11339
- await new Promise((resolve12) => setTimeout(resolve12, 2e3));
11364
+ await new Promise((resolve10) => setTimeout(resolve10, 2e3));
11340
11365
  const skipHealthCheck = process.env.SKIP_DB_HEALTH_CHECK === "true";
11341
11366
  if (skipHealthCheck) {
11342
11367
  try {
@@ -11346,7 +11371,7 @@ async function waitForDatabase(runtime, containerName, image, quiet, dbUser, ver
11346
11371
  { encoding: "utf-8", timeout: 5e3 }
11347
11372
  ).trim();
11348
11373
  if (status === "running") {
11349
- await new Promise((resolve12) => setTimeout(resolve12, 3e3));
11374
+ await new Promise((resolve10) => setTimeout(resolve10, 3e3));
11350
11375
  return;
11351
11376
  }
11352
11377
  } catch {
@@ -11379,7 +11404,7 @@ async function waitForDatabase(runtime, containerName, image, quiet, dbUser, ver
11379
11404
  stdio: verbose ? "inherit" : "ignore",
11380
11405
  timeout: 5e3
11381
11406
  });
11382
- await new Promise((resolve12) => setTimeout(resolve12, 1e3));
11407
+ await new Promise((resolve10) => setTimeout(resolve10, 1e3));
11383
11408
  if (verbose) {
11384
11409
  printInfo(`PostgreSQL is ready`);
11385
11410
  }
@@ -11408,7 +11433,7 @@ async function waitForDatabase(runtime, containerName, image, quiet, dbUser, ver
11408
11433
  } catch {
11409
11434
  }
11410
11435
  } else {
11411
- await new Promise((resolve12) => setTimeout(resolve12, 3e3));
11436
+ await new Promise((resolve10) => setTimeout(resolve10, 3e3));
11412
11437
  return;
11413
11438
  }
11414
11439
  }
@@ -11417,7 +11442,7 @@ async function waitForDatabase(runtime, containerName, image, quiet, dbUser, ver
11417
11442
  printInfo(`Waiting for database to be ready... (${attempts + 1}/${maxAttempts})`);
11418
11443
  }
11419
11444
  }
11420
- await new Promise((resolve12) => setTimeout(resolve12, 1e3));
11445
+ await new Promise((resolve10) => setTimeout(resolve10, 1e3));
11421
11446
  attempts++;
11422
11447
  }
11423
11448
  printWarning(`Database container ${containerName} is taking longer than expected to start`);
@@ -11598,14 +11623,14 @@ async function startJanusGraph2(context) {
11598
11623
  { encoding: "utf-8", stdio: "pipe" }
11599
11624
  );
11600
11625
  if (logs.includes("Channel started") || logs.includes("Started") || i >= 5) {
11601
- await new Promise((resolve12) => setTimeout(resolve12, 3e3));
11626
+ await new Promise((resolve10) => setTimeout(resolve10, 3e3));
11602
11627
  ready = true;
11603
11628
  break;
11604
11629
  }
11605
11630
  }
11606
11631
  } catch {
11607
11632
  }
11608
- await new Promise((resolve12) => setTimeout(resolve12, 3e3));
11633
+ await new Promise((resolve10) => setTimeout(resolve10, 3e3));
11609
11634
  if (!service.quiet && i > 0 && i % 5 === 0) {
11610
11635
  printInfo(`Still waiting... (${i * 3}s elapsed)`);
11611
11636
  }
@@ -11817,7 +11842,7 @@ var init_database_provision = __esm({
11817
11842
  break;
11818
11843
  }
11819
11844
  } catch {
11820
- await new Promise((resolve12) => setTimeout(resolve12, 1e3));
11845
+ await new Promise((resolve10) => setTimeout(resolve10, 1e3));
11821
11846
  attempts++;
11822
11847
  }
11823
11848
  }
@@ -14967,7 +14992,7 @@ var init_database_stop = __esm({
14967
14992
  if (currentStatus === "exited" || currentStatus === "stopped") {
14968
14993
  stopped = true;
14969
14994
  } else {
14970
- await new Promise((resolve12) => setTimeout(resolve12, 1e3));
14995
+ await new Promise((resolve10) => setTimeout(resolve10, 1e3));
14971
14996
  attempts++;
14972
14997
  }
14973
14998
  } catch {
@@ -15341,7 +15366,7 @@ var init_proxy_start2 = __esm({
15341
15366
  if (!service.quiet) {
15342
15367
  printInfo("Waiting for proxy to become healthy...");
15343
15368
  }
15344
- await new Promise((resolve12) => setTimeout(resolve12, 2e3));
15369
+ await new Promise((resolve10) => setTimeout(resolve10, 2e3));
15345
15370
  const isRunning = execFileSync26(runtime, ["ps", "-q", "-f", `id=${containerId}`], { encoding: "utf-8" }).trim();
15346
15371
  if (!isRunning) {
15347
15372
  const logs = execFileSync26(runtime, ["logs", containerId], { encoding: "utf-8" });
@@ -15942,7 +15967,7 @@ var init_inference_start2 = __esm({
15942
15967
  let ready = false;
15943
15968
  const maxAttempts = 15;
15944
15969
  for (let i = 0; i < maxAttempts; i++) {
15945
- await new Promise((resolve12) => setTimeout(resolve12, 1e3));
15970
+ await new Promise((resolve10) => setTimeout(resolve10, 1e3));
15946
15971
  try {
15947
15972
  const status = execFileSync30(
15948
15973
  runtime,
@@ -18310,7 +18335,7 @@ Waiting for ${otherActiveDeployments.length} old deployment(s) to complete drain
18310
18335
  if (taskDetails.new.running > 0) {
18311
18336
  consecutiveFailures = 0;
18312
18337
  }
18313
- await new Promise((resolve12) => setTimeout(resolve12, checkInterval));
18338
+ await new Promise((resolve10) => setTimeout(resolve10, checkInterval));
18314
18339
  } catch (error) {
18315
18340
  if (error instanceof Error && error.message.includes("Deployment")) {
18316
18341
  if (!verbose) {
@@ -19056,20 +19081,20 @@ var init_database_check3 = __esm({
19056
19081
  const host = serviceConfig.host;
19057
19082
  const port = serviceConfig.port;
19058
19083
  try {
19059
- const isReachable = await new Promise((resolve12) => {
19084
+ const isReachable = await new Promise((resolve10) => {
19060
19085
  const socket = new net3.Socket();
19061
19086
  socket.setTimeout(5e3);
19062
19087
  socket.once("connect", () => {
19063
19088
  socket.destroy();
19064
- resolve12(true);
19089
+ resolve10(true);
19065
19090
  });
19066
19091
  socket.once("error", () => {
19067
19092
  socket.destroy();
19068
- resolve12(false);
19093
+ resolve10(false);
19069
19094
  });
19070
19095
  socket.once("timeout", () => {
19071
19096
  socket.destroy();
19072
- resolve12(false);
19097
+ resolve10(false);
19073
19098
  });
19074
19099
  socket.connect(port, host);
19075
19100
  });
@@ -19139,20 +19164,20 @@ var init_database_check3 = __esm({
19139
19164
  const host = serviceConfig.host;
19140
19165
  const port = serviceConfig.port;
19141
19166
  try {
19142
- const isReachable = await new Promise((resolve12) => {
19167
+ const isReachable = await new Promise((resolve10) => {
19143
19168
  const socket = new net3.Socket();
19144
19169
  socket.setTimeout(5e3);
19145
19170
  socket.once("connect", () => {
19146
19171
  socket.destroy();
19147
- resolve12(true);
19172
+ resolve10(true);
19148
19173
  });
19149
19174
  socket.once("error", () => {
19150
19175
  socket.destroy();
19151
- resolve12(false);
19176
+ resolve10(false);
19152
19177
  });
19153
19178
  socket.once("timeout", () => {
19154
19179
  socket.destroy();
19155
- resolve12(false);
19180
+ resolve10(false);
19156
19181
  });
19157
19182
  socket.connect(port, host);
19158
19183
  });
@@ -19626,7 +19651,7 @@ var init_values = __esm({
19626
19651
  var sleep;
19627
19652
  var init_sleep = __esm({
19628
19653
  "node_modules/@anthropic-ai/sdk/internal/utils/sleep.mjs"() {
19629
- sleep = (ms) => new Promise((resolve12) => setTimeout(resolve12, ms));
19654
+ sleep = (ms) => new Promise((resolve10) => setTimeout(resolve10, ms));
19630
19655
  }
19631
19656
  });
19632
19657
 
@@ -20380,8 +20405,8 @@ var init_api_promise = __esm({
20380
20405
  init_parse();
20381
20406
  APIPromise = class _APIPromise extends Promise {
20382
20407
  constructor(client, responsePromise, parseResponse = defaultParseResponse) {
20383
- super((resolve12) => {
20384
- resolve12(null);
20408
+ super((resolve10) => {
20409
+ resolve10(null);
20385
20410
  });
20386
20411
  this.responsePromise = responsePromise;
20387
20412
  this.parseResponse = parseResponse;
@@ -21577,12 +21602,12 @@ var init_BetaMessageStream = __esm({
21577
21602
  }
21578
21603
  return this._emit("error", new AnthropicError(String(error)));
21579
21604
  });
21580
- __classPrivateFieldSet(this, _BetaMessageStream_connectedPromise, new Promise((resolve12, reject) => {
21581
- __classPrivateFieldSet(this, _BetaMessageStream_resolveConnectedPromise, resolve12, "f");
21605
+ __classPrivateFieldSet(this, _BetaMessageStream_connectedPromise, new Promise((resolve10, reject) => {
21606
+ __classPrivateFieldSet(this, _BetaMessageStream_resolveConnectedPromise, resolve10, "f");
21582
21607
  __classPrivateFieldSet(this, _BetaMessageStream_rejectConnectedPromise, reject, "f");
21583
21608
  }), "f");
21584
- __classPrivateFieldSet(this, _BetaMessageStream_endPromise, new Promise((resolve12, reject) => {
21585
- __classPrivateFieldSet(this, _BetaMessageStream_resolveEndPromise, resolve12, "f");
21609
+ __classPrivateFieldSet(this, _BetaMessageStream_endPromise, new Promise((resolve10, reject) => {
21610
+ __classPrivateFieldSet(this, _BetaMessageStream_resolveEndPromise, resolve10, "f");
21586
21611
  __classPrivateFieldSet(this, _BetaMessageStream_rejectEndPromise, reject, "f");
21587
21612
  }), "f");
21588
21613
  __classPrivateFieldGet(this, _BetaMessageStream_connectedPromise, "f").catch(() => {
@@ -21748,11 +21773,11 @@ var init_BetaMessageStream = __esm({
21748
21773
  * const message = await stream.emitted('message') // rejects if the stream errors
21749
21774
  */
21750
21775
  emitted(event) {
21751
- return new Promise((resolve12, reject) => {
21776
+ return new Promise((resolve10, reject) => {
21752
21777
  __classPrivateFieldSet(this, _BetaMessageStream_catchingPromiseCreated, true, "f");
21753
21778
  if (event !== "error")
21754
21779
  this.once("error", reject);
21755
- this.once(event, resolve12);
21780
+ this.once(event, resolve10);
21756
21781
  });
21757
21782
  }
21758
21783
  async done() {
@@ -22075,7 +22100,7 @@ var init_BetaMessageStream = __esm({
22075
22100
  if (done) {
22076
22101
  return { value: void 0, done: true };
22077
22102
  }
22078
- return new Promise((resolve12, reject) => readQueue.push({ resolve: resolve12, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: void 0, done: true });
22103
+ return new Promise((resolve10, reject) => readQueue.push({ resolve: resolve10, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: void 0, done: true });
22079
22104
  }
22080
22105
  const chunk = pushQueue.shift();
22081
22106
  return { value: chunk, done: false };
@@ -22113,13 +22138,13 @@ var init_constants = __esm({
22113
22138
 
22114
22139
  // node_modules/@anthropic-ai/sdk/lib/tools/BetaToolRunner.mjs
22115
22140
  function promiseWithResolvers() {
22116
- let resolve12;
22141
+ let resolve10;
22117
22142
  let reject;
22118
22143
  const promise = new Promise((res, rej) => {
22119
- resolve12 = res;
22144
+ resolve10 = res;
22120
22145
  reject = rej;
22121
22146
  });
22122
- return { promise, resolve: resolve12, reject };
22147
+ return { promise, resolve: resolve10, reject };
22123
22148
  }
22124
22149
  async function generateToolResponse(params, lastMessage = params.messages.at(-1)) {
22125
22150
  if (!lastMessage || lastMessage.role !== "assistant" || !lastMessage.content || typeof lastMessage.content === "string") {
@@ -22573,12 +22598,12 @@ var init_MessageStream = __esm({
22573
22598
  }
22574
22599
  return this._emit("error", new AnthropicError(String(error)));
22575
22600
  });
22576
- __classPrivateFieldSet(this, _MessageStream_connectedPromise, new Promise((resolve12, reject) => {
22577
- __classPrivateFieldSet(this, _MessageStream_resolveConnectedPromise, resolve12, "f");
22601
+ __classPrivateFieldSet(this, _MessageStream_connectedPromise, new Promise((resolve10, reject) => {
22602
+ __classPrivateFieldSet(this, _MessageStream_resolveConnectedPromise, resolve10, "f");
22578
22603
  __classPrivateFieldSet(this, _MessageStream_rejectConnectedPromise, reject, "f");
22579
22604
  }), "f");
22580
- __classPrivateFieldSet(this, _MessageStream_endPromise, new Promise((resolve12, reject) => {
22581
- __classPrivateFieldSet(this, _MessageStream_resolveEndPromise, resolve12, "f");
22605
+ __classPrivateFieldSet(this, _MessageStream_endPromise, new Promise((resolve10, reject) => {
22606
+ __classPrivateFieldSet(this, _MessageStream_resolveEndPromise, resolve10, "f");
22582
22607
  __classPrivateFieldSet(this, _MessageStream_rejectEndPromise, reject, "f");
22583
22608
  }), "f");
22584
22609
  __classPrivateFieldGet(this, _MessageStream_connectedPromise, "f").catch(() => {
@@ -22744,11 +22769,11 @@ var init_MessageStream = __esm({
22744
22769
  * const message = await stream.emitted('message') // rejects if the stream errors
22745
22770
  */
22746
22771
  emitted(event) {
22747
- return new Promise((resolve12, reject) => {
22772
+ return new Promise((resolve10, reject) => {
22748
22773
  __classPrivateFieldSet(this, _MessageStream_catchingPromiseCreated, true, "f");
22749
22774
  if (event !== "error")
22750
22775
  this.once("error", reject);
22751
- this.once(event, resolve12);
22776
+ this.once(event, resolve10);
22752
22777
  });
22753
22778
  }
22754
22779
  async done() {
@@ -23065,7 +23090,7 @@ var init_MessageStream = __esm({
23065
23090
  if (done) {
23066
23091
  return { value: void 0, done: true };
23067
23092
  }
23068
- return new Promise((resolve12, reject) => readQueue.push({ resolve: resolve12, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: void 0, done: true });
23093
+ return new Promise((resolve10, reject) => readQueue.push({ resolve: resolve10, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: void 0, done: true });
23069
23094
  }
23070
23095
  const chunk = pushQueue.shift();
23071
23096
  return { value: chunk, done: false };
@@ -24272,7 +24297,7 @@ var init_default_start = __esm({
24272
24297
  printInfo(`[MOCK] Starting service: ${service.name}`);
24273
24298
  }
24274
24299
  const startupDelay = mockData?.startupDelay || 100;
24275
- await new Promise((resolve12) => setTimeout(resolve12, startupDelay));
24300
+ await new Promise((resolve10) => setTimeout(resolve10, startupDelay));
24276
24301
  if (mockData?.simulateFailure) {
24277
24302
  return {
24278
24303
  success: false,
@@ -25815,7 +25840,7 @@ var init_check = __esm({
25815
25840
  init_multi_service_executor();
25816
25841
  init_command_definition();
25817
25842
  init_base_options_schema();
25818
- CheckOptionsSchema = BaseOptionsSchema.extend({
25843
+ CheckOptionsSchema = OpsOptionsSchema.extend({
25819
25844
  service: external_exports.string().optional(),
25820
25845
  all: external_exports.boolean().default(false),
25821
25846
  deep: external_exports.boolean().default(true),
@@ -26225,7 +26250,7 @@ var init_dashboard_data = __esm({
26225
26250
  }
26226
26251
  }
26227
26252
  fetchBackendHealth(port) {
26228
- return new Promise((resolve12, reject) => {
26253
+ return new Promise((resolve10, reject) => {
26229
26254
  const req = http2.get(`http://localhost:${port}/api/health`, { timeout: 2e3 }, (res) => {
26230
26255
  let body = "";
26231
26256
  res.on("data", (chunk) => {
@@ -26233,7 +26258,7 @@ var init_dashboard_data = __esm({
26233
26258
  });
26234
26259
  res.on("end", () => {
26235
26260
  try {
26236
- resolve12(JSON.parse(body));
26261
+ resolve10(JSON.parse(body));
26237
26262
  } catch {
26238
26263
  reject(new Error("Invalid JSON"));
26239
26264
  }
@@ -26678,7 +26703,7 @@ var init_web_dashboard_server = __esm({
26678
26703
  this.actorsInterval = null;
26679
26704
  }
26680
26705
  async start() {
26681
- return new Promise((resolve12) => {
26706
+ return new Promise((resolve10) => {
26682
26707
  this.server.listen(this.port, () => {
26683
26708
  console.log(`
26684
26709
  \u{1F310} Web dashboard running at http://localhost:${this.port}`);
@@ -26687,7 +26712,7 @@ var init_web_dashboard_server = __esm({
26687
26712
  console.log(`
26688
26713
  Press Ctrl+C to stop
26689
26714
  `);
26690
- resolve12();
26715
+ resolve10();
26691
26716
  });
26692
26717
  });
26693
26718
  }
@@ -27020,7 +27045,7 @@ var require_package = __commonJS({
27020
27045
  "package.json"(exports, module) {
27021
27046
  module.exports = {
27022
27047
  name: "@semiont/cli",
27023
- version: "0.4.2",
27048
+ version: "0.4.3",
27024
27049
  description: "Semiont CLI - Unified environment management tool",
27025
27050
  _comment: "AWS SDK dependencies (@aws-sdk/*) are only used by platforms/aws",
27026
27051
  type: "module",
@@ -27084,13 +27109,12 @@ var require_package = __commonJS({
27084
27109
  "@aws-sdk/client-secrets-manager": "^3.600.0",
27085
27110
  "@aws-sdk/client-sts": "^3.859.0",
27086
27111
  "@aws-sdk/client-wafv2": "^3.859.0",
27087
- "@semiont/api-client": "^0.4.2",
27088
- "@semiont/content": "^0.4.2",
27089
- "@semiont/core": "^0.4.2",
27090
- "@semiont/event-sourcing": "^0.4.2",
27091
- "@semiont/graph": "^0.4.2",
27092
- "@semiont/make-meaning": "^0.4.2",
27093
- "@vitest/ui": "4.0.18",
27112
+ "@semiont/api-client": "^0.4.3",
27113
+ "@semiont/content": "^0.4.3",
27114
+ "@semiont/core": "^0.4.3",
27115
+ "@semiont/event-sourcing": "^0.4.3",
27116
+ "@semiont/graph": "^0.4.3",
27117
+ "@semiont/make-meaning": "^0.4.3",
27094
27118
  arg: "^5.0.2",
27095
27119
  argon2: "^0.44.0",
27096
27120
  express: "^5.2.1",
@@ -27109,8 +27133,7 @@ var require_package = __commonJS({
27109
27133
  "@types/react": "^19.2.14",
27110
27134
  "@vitest/coverage-v8": "^4.1.0",
27111
27135
  chalk: "^5.3.0",
27112
- typescript: "^5.9.2",
27113
- vitest: "^4.0.18"
27136
+ typescript: "^5.9.2"
27114
27137
  },
27115
27138
  overrides: {
27116
27139
  esbuild: "0.27.2"
@@ -27144,17 +27167,15 @@ var InitOptionsSchema = BaseOptionsSchema.extend({
27144
27167
  environments: external_exports.array(external_exports.string()).default(["local", "test", "staging", "production"])
27145
27168
  }).transform((data) => ({
27146
27169
  ...data,
27147
- environment: data.environment || "_init_",
27148
- // Dummy value - init doesn't use environment
27149
27170
  output: data.output === "table" ? "summary" : data.output
27150
27171
  // Init doesn't support table output
27151
27172
  }));
27152
27173
  function prompt(question) {
27153
- return new Promise((resolve12) => {
27174
+ return new Promise((resolve10) => {
27154
27175
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
27155
27176
  rl.question(question, (answer) => {
27156
27177
  rl.close();
27157
- resolve12(answer.trim());
27178
+ resolve10(answer.trim());
27158
27179
  });
27159
27180
  });
27160
27181
  }
@@ -27329,7 +27350,7 @@ async function init(options) {
27329
27350
  console.log(`${colors.yellow}\u2139 --no-git: git init will be skipped${colors.reset}`);
27330
27351
  console.log(`${colors.yellow}\u2139 --no-git: git.sync will be set to false in .semiont/config${colors.reset}`);
27331
27352
  console.log(`${colors.yellow}\u2139 --no-git: .semiont/config will NOT be staged (git add skipped)${colors.reset}`);
27332
- console.log(`${colors.yellow}\u2139 --no-git: semiont yield/mv/archive will not stage files in the git index${colors.reset}`);
27353
+ console.log(`${colors.yellow}\u2139 --no-git: semiont yield/mv will not stage files in the git index${colors.reset}`);
27333
27354
  }
27334
27355
  const dotSemiontConfigPath = path2.join(dotSemiontDir, "config");
27335
27356
  if (!fs2.existsSync(dotSemiontDir) || options.force) {
@@ -27386,7 +27407,7 @@ Next steps:`);
27386
27407
  results.duration = Date.now() - startTime;
27387
27408
  return results;
27388
27409
  }
27389
- var initCommand = new CommandBuilder().name("init").description("Initialize a new Semiont project").schema(InitOptionsSchema).args(withBaseArgs({
27410
+ var initCommand = new CommandBuilder().name("init").description("Initialize a new Semiont project").schema(InitOptionsSchema).args(withOpsArgs({
27390
27411
  "--name": {
27391
27412
  type: "string",
27392
27413
  description: "Project name"
@@ -27427,7 +27448,7 @@ init_command_descriptor();
27427
27448
  init_multi_service_executor();
27428
27449
  init_command_definition();
27429
27450
  init_base_options_schema();
27430
- var StartOptionsSchema = BaseOptionsSchema.extend({
27451
+ var StartOptionsSchema = OpsOptionsSchema.extend({
27431
27452
  service: external_exports.string().optional()
27432
27453
  });
27433
27454
  var startDescriptor = createCommandDescriptor({
@@ -27498,7 +27519,7 @@ init_command_descriptor();
27498
27519
  init_multi_service_executor();
27499
27520
  init_command_definition();
27500
27521
  init_base_options_schema();
27501
- var StopOptionsSchema = BaseOptionsSchema.extend({
27522
+ var StopOptionsSchema = OpsOptionsSchema.extend({
27502
27523
  service: external_exports.string().optional(),
27503
27524
  force: external_exports.boolean().default(false).describe("Force stop without graceful shutdown"),
27504
27525
  timeout: external_exports.number().default(30).describe("Timeout for graceful shutdown in seconds")
@@ -27588,7 +27609,7 @@ init_command_descriptor();
27588
27609
  init_multi_service_executor();
27589
27610
  init_command_definition();
27590
27611
  init_base_options_schema();
27591
- var ProvisionOptionsSchema = BaseOptionsSchema.extend({
27612
+ var ProvisionOptionsSchema = OpsOptionsSchema.extend({
27592
27613
  service: external_exports.string().optional(),
27593
27614
  all: external_exports.boolean().default(false),
27594
27615
  stack: external_exports.enum(["data", "app", "all"]).optional(),
@@ -27722,7 +27743,7 @@ init_command_descriptor();
27722
27743
  init_multi_service_executor();
27723
27744
  init_command_definition();
27724
27745
  init_base_options_schema();
27725
- var PublishOptionsSchema = BaseOptionsSchema.extend({
27746
+ var PublishOptionsSchema = OpsOptionsSchema.extend({
27726
27747
  service: external_exports.string().optional(),
27727
27748
  all: external_exports.boolean().default(false),
27728
27749
  tag: external_exports.string().optional(),
@@ -27822,7 +27843,7 @@ init_command_descriptor();
27822
27843
  init_multi_service_executor();
27823
27844
  init_command_definition();
27824
27845
  init_base_options_schema();
27825
- var UpdateOptionsSchema = BaseOptionsSchema.extend({
27846
+ var UpdateOptionsSchema = OpsOptionsSchema.extend({
27826
27847
  service: external_exports.string().optional(),
27827
27848
  force: external_exports.boolean().default(false),
27828
27849
  wait: external_exports.boolean().default(false),
@@ -27948,7 +27969,7 @@ init_platform3();
27948
27969
  init_platform2();
27949
27970
  init_cli_colors();
27950
27971
  init_dashboard_data();
27951
- var WatchOptionsSchema = BaseOptionsSchema.extend({
27972
+ var WatchOptionsSchema = OpsOptionsSchema.extend({
27952
27973
  target: external_exports.enum(["all", "logs", "metrics", "services"]).default("all"),
27953
27974
  noFollow: external_exports.boolean().default(false),
27954
27975
  interval: external_exports.number().int().positive().default(30),
@@ -27957,9 +27978,9 @@ var WatchOptionsSchema = BaseOptionsSchema.extend({
27957
27978
  });
27958
27979
  async function launchDashboard(environment, serviceDeployments, envConfig, interval, port) {
27959
27980
  const startTime = Date.now();
27960
- return new Promise(async (resolve12) => {
27981
+ return new Promise(async (resolve10) => {
27961
27982
  if (process.env.VITEST) {
27962
- setTimeout(() => resolve12({ duration: 100, exitReason: "user-quit" }), 100);
27983
+ setTimeout(() => resolve10({ duration: 100, exitReason: "user-quit" }), 100);
27963
27984
  return;
27964
27985
  }
27965
27986
  try {
@@ -27977,13 +27998,13 @@ async function launchDashboard(environment, serviceDeployments, envConfig, inter
27977
27998
  await server.start();
27978
27999
  const stop2 = () => {
27979
28000
  server.stop();
27980
- resolve12({ duration: Date.now() - startTime, exitReason: "user-quit" });
28001
+ resolve10({ duration: Date.now() - startTime, exitReason: "user-quit" });
27981
28002
  };
27982
28003
  process.on("SIGINT", stop2);
27983
28004
  process.on("SIGTERM", stop2);
27984
28005
  } catch (error) {
27985
28006
  console.error("Dashboard error:", error);
27986
- resolve12({ duration: Date.now() - startTime, exitReason: "error" });
28007
+ resolve10({ duration: Date.now() - startTime, exitReason: "error" });
27987
28008
  }
27988
28009
  });
27989
28010
  }
@@ -28098,7 +28119,7 @@ ${colors.bright}To fix this issue:${colors.reset}`);
28098
28119
  executionContext: { user: process.env.USER || "unknown", workingDirectory: process.cwd(), dryRun: options.dryRun }
28099
28120
  };
28100
28121
  }
28101
- var watchCommand = new CommandBuilder().name("watch").description("Monitor services using new architecture").schema(WatchOptionsSchema).requiresEnvironment(true).requiresServices(true).args(withBaseArgs({
28122
+ var watchCommand = new CommandBuilder().name("watch").description("Monitor services using new architecture").schema(WatchOptionsSchema).requiresEnvironment(true).requiresServices(true).args(withOpsArgs({
28102
28123
  "--service": { type: "string", description: 'Service name or "all" for all services' },
28103
28124
  "--target": { type: "string", description: "What to watch (all, logs, metrics, services)" },
28104
28125
  "--no-follow": { type: "boolean", description: "Do not follow new logs" },
@@ -28146,7 +28167,7 @@ function loadPrismaClient(projectRoot) {
28146
28167
  );
28147
28168
  }
28148
28169
  }
28149
- var UseraddOptionsSchema = BaseOptionsSchema.extend({
28170
+ var UseraddOptionsSchema = OpsOptionsSchema.extend({
28150
28171
  email: external_exports.string().email().min(1, "Email is required"),
28151
28172
  name: external_exports.string().optional(),
28152
28173
  password: external_exports.string().optional(),
@@ -28407,7 +28428,7 @@ function createCliLogger(verbose) {
28407
28428
  child: () => createCliLogger(verbose)
28408
28429
  };
28409
28430
  }
28410
- var BackupOptionsSchema = BaseOptionsSchema.extend({
28431
+ var BackupOptionsSchema = OpsOptionsSchema.extend({
28411
28432
  out: external_exports.string().min(1, "Output path is required")
28412
28433
  });
28413
28434
  async function runBackup(options) {
@@ -28534,7 +28555,7 @@ function createNoopGraphDatabase() {
28534
28555
  clearDatabase: noop2
28535
28556
  };
28536
28557
  }
28537
- var RestoreOptionsSchema = BaseOptionsSchema.extend({
28558
+ var RestoreOptionsSchema = OpsOptionsSchema.extend({
28538
28559
  file: external_exports.string().min(1, "Input file path is required")
28539
28560
  });
28540
28561
  async function runRestore(options) {
@@ -28613,11 +28634,11 @@ import { isBackupManifest, validateManifestVersion, BACKUP_FORMAT } from "@semio
28613
28634
  import { createGunzip } from "node:zlib";
28614
28635
  var BLOCK_SIZE = 512;
28615
28636
  async function readTarGzEntries(input) {
28616
- const decompressed = await new Promise((resolve12, reject) => {
28637
+ const decompressed = await new Promise((resolve10, reject) => {
28617
28638
  const gunzip = createGunzip();
28618
28639
  const chunks = [];
28619
28640
  gunzip.on("data", (chunk) => chunks.push(chunk));
28620
- gunzip.on("end", () => resolve12(Buffer.concat(chunks)));
28641
+ gunzip.on("end", () => resolve10(Buffer.concat(chunks)));
28621
28642
  gunzip.on("error", reject);
28622
28643
  input.on("error", reject);
28623
28644
  input.pipe(gunzip);
@@ -28640,7 +28661,7 @@ async function readTarGzEntries(input) {
28640
28661
  }
28641
28662
  return entries;
28642
28663
  }
28643
- var VerifyOptionsSchema = BaseOptionsSchema.extend({
28664
+ var VerifyOptionsSchema = OpsOptionsSchema.extend({
28644
28665
  file: external_exports.string().min(1, "File path is required")
28645
28666
  });
28646
28667
  async function runVerify(options) {
@@ -28799,7 +28820,7 @@ function createCliLogger3(verbose) {
28799
28820
  child: () => createCliLogger3(verbose)
28800
28821
  };
28801
28822
  }
28802
- var ExportOptionsSchema = BaseOptionsSchema.extend({
28823
+ var ExportOptionsSchema = OpsOptionsSchema.extend({
28803
28824
  out: external_exports.string().min(1, "Output path is required"),
28804
28825
  includeArchived: external_exports.boolean().optional().default(false)
28805
28826
  });
@@ -28942,7 +28963,7 @@ function createNoopGraphDatabase2() {
28942
28963
  clearDatabase: noop2
28943
28964
  };
28944
28965
  }
28945
- var ImportOptionsSchema = BaseOptionsSchema.extend({
28966
+ var ImportOptionsSchema = OpsOptionsSchema.extend({
28946
28967
  file: external_exports.string().min(1, "Input file path is required"),
28947
28968
  userId: external_exports.string().optional()
28948
28969
  });
@@ -29027,7 +29048,7 @@ import * as fs49 from "fs";
29027
29048
  import * as path42 from "path";
29028
29049
  import * as readline2 from "readline";
29029
29050
  import { execFileSync as execFileSync41 } from "child_process";
29030
- var LocalOptionsSchema = BaseOptionsSchema.extend({
29051
+ var LocalOptionsSchema = OpsOptionsSchema.extend({
29031
29052
  directory: external_exports.string().optional(),
29032
29053
  yes: external_exports.boolean().default(false)
29033
29054
  }).transform((data) => ({
@@ -29035,11 +29056,11 @@ var LocalOptionsSchema = BaseOptionsSchema.extend({
29035
29056
  environment: data.environment || "_local_"
29036
29057
  }));
29037
29058
  function prompt2(question) {
29038
- return new Promise((resolve12) => {
29059
+ return new Promise((resolve10) => {
29039
29060
  const rl = readline2.createInterface({ input: process.stdin, output: process.stdout });
29040
29061
  rl.question(question, (answer) => {
29041
29062
  rl.close();
29042
- resolve12(answer.trim());
29063
+ resolve10(answer.trim());
29043
29064
  });
29044
29065
  });
29045
29066
  }
@@ -29298,7 +29319,7 @@ ${colors.red}\u2717 Setup failed: ${msg}${colors.reset}`);
29298
29319
  results.duration = Date.now() - startTime;
29299
29320
  return results;
29300
29321
  }
29301
- var localCommand = new CommandBuilder().name("local").description("Set up and start Semiont locally (init + provision + start + useradd)").schema(LocalOptionsSchema).args(withBaseArgs({
29322
+ var localCommand = new CommandBuilder().name("local").description("Set up and start Semiont locally (init + provision + start + useradd)").schema(LocalOptionsSchema).args(withOpsArgs({
29302
29323
  "--directory": {
29303
29324
  type: "string",
29304
29325
  description: "Project directory (default: cwd)"
@@ -29325,7 +29346,7 @@ import * as fs50 from "fs";
29325
29346
  import * as readline3 from "readline";
29326
29347
  import { execFileSync as execFileSync42 } from "child_process";
29327
29348
  import { SemiontProject as SemiontProject20 } from "@semiont/core/node";
29328
- var CleanOptionsSchema = BaseOptionsSchema.extend({
29349
+ var CleanOptionsSchema = OpsOptionsSchema.extend({
29329
29350
  force: external_exports.boolean().default(false),
29330
29351
  logs: external_exports.boolean().default(false),
29331
29352
  pids: external_exports.boolean().default(false),
@@ -29337,11 +29358,11 @@ var CleanOptionsSchema = BaseOptionsSchema.extend({
29337
29358
  output: data.output === "table" ? "summary" : data.output
29338
29359
  }));
29339
29360
  function confirm(question) {
29340
- return new Promise((resolve12) => {
29361
+ return new Promise((resolve10) => {
29341
29362
  const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
29342
29363
  rl.question(`${question} [y/N] `, (answer) => {
29343
29364
  rl.close();
29344
- resolve12(answer.trim().toLowerCase() === "y");
29365
+ resolve10(answer.trim().toLowerCase() === "y");
29345
29366
  });
29346
29367
  });
29347
29368
  }
@@ -29571,7 +29592,7 @@ ${colors.bright}Semiont clean \u2014 project: ${project.name}${colors.reset}
29571
29592
  results.duration = Date.now() - startTime;
29572
29593
  return results;
29573
29594
  }
29574
- var cleanCommand = new CommandBuilder().name("clean").description("Remove ephemeral files (logs, PID files, generated config, Docker volumes)").schema(CleanOptionsSchema).args(withBaseArgs({
29595
+ var cleanCommand = new CommandBuilder().name("clean").description("Remove ephemeral files (logs, PID files, generated config, Docker volumes)").schema(CleanOptionsSchema).args(withOpsArgs({
29575
29596
  "--force": {
29576
29597
  type: "boolean",
29577
29598
  description: "Skip confirmation prompts",
@@ -29671,7 +29692,7 @@ function createNoopGraphDatabase3() {
29671
29692
  clearDatabase: noop2
29672
29693
  };
29673
29694
  }
29674
- var MvOptionsSchema = BaseOptionsSchema.extend({
29695
+ var MvOptionsSchema = OpsOptionsSchema.extend({
29675
29696
  from: external_exports.string().min(1, "Source path is required"),
29676
29697
  to: external_exports.string().min(1, "Destination path is required"),
29677
29698
  noGit: external_exports.boolean().default(false)
@@ -29701,10 +29722,10 @@ async function runMv(options) {
29701
29722
  const stower = new Stower3(kb, eventBus, logger.child({ component: "stower" }));
29702
29723
  await stower.initialize();
29703
29724
  try {
29704
- const movedPromise = new Promise((resolve12, reject) => {
29725
+ const movedPromise = new Promise((resolve10, reject) => {
29705
29726
  const sub = eventBus.get("yield:moved").subscribe(() => {
29706
29727
  sub.unsubscribe();
29707
- resolve12();
29728
+ resolve10();
29708
29729
  });
29709
29730
  eventBus.get("yield:move-failed").subscribe((e) => {
29710
29731
  reject(new Error(e.error?.message ?? "Move failed"));
@@ -29764,74 +29785,83 @@ init_command_definition();
29764
29785
  init_base_options_schema();
29765
29786
  init_cli_logger();
29766
29787
  init_config_loader();
29767
- init_preflight_utils();
29768
- import * as path43 from "path";
29788
+ import * as path44 from "path";
29769
29789
  import { promises as nodeFs } from "fs";
29770
- import { createHash } from "crypto";
29771
- import { SemiontProject as SemiontProject22 } from "@semiont/core/node";
29772
- import { EventBus as EventBus4, resourceId as toResourceId } from "@semiont/core";
29773
- import { createEventStore as createEventStore6 } from "@semiont/event-sourcing";
29774
- import { resolveStorageUri, ResourceNotFoundError } from "@semiont/event-sourcing";
29775
- import { Stower as Stower4, createKnowledgeBase as createKnowledgeBase4 } from "@semiont/make-meaning";
29776
- function createCliLogger6(verbose) {
29777
- return {
29778
- debug: (msg, meta) => {
29779
- if (verbose) console.log(`[debug] ${msg}`, meta ?? "");
29780
- },
29781
- info: (msg, meta) => console.log(`[info] ${msg}`, meta ?? ""),
29782
- warn: (msg, meta) => console.warn(`[warn] ${msg}`, meta ?? ""),
29783
- error: (msg, meta) => console.error(`[error] ${msg}`, meta ?? ""),
29784
- child: () => createCliLogger6(verbose)
29785
- };
29790
+ import { resourceId as toResourceId, annotationId as toAnnotationId, EventBus as EventBus4 } from "@semiont/core";
29791
+
29792
+ // src/core/api-client-factory.ts
29793
+ import * as fs51 from "fs";
29794
+ import * as path43 from "path";
29795
+ import * as os5 from "os";
29796
+ import { SemiontApiClient as SemiontApiClient3 } from "@semiont/api-client";
29797
+ import {
29798
+ email as toEmail,
29799
+ accessToken as toAccessToken,
29800
+ baseUrl as toBaseUrl
29801
+ } from "@semiont/core";
29802
+ var TOKEN_CACHE_TTL_MS = 864e5;
29803
+ function authStoreDir() {
29804
+ const xdgState = process.env.XDG_STATE_HOME ?? path43.join(os5.homedir(), ".local", "state");
29805
+ return path43.join(xdgState, "semiont", "auth");
29806
+ }
29807
+ function busSlug(rawUrl) {
29808
+ return rawUrl.replace(/^https?:\/\//, "").replace(/\/+$/, "").replace(/[:/]/g, "-").toLowerCase();
29809
+ }
29810
+ function tokenCachePath(rawBusUrl) {
29811
+ return path43.join(authStoreDir(), `${busSlug(rawBusUrl)}.json`);
29812
+ }
29813
+ function readTokenCache(cachePath) {
29814
+ try {
29815
+ const raw = fs51.readFileSync(cachePath, "utf-8");
29816
+ return JSON.parse(raw);
29817
+ } catch {
29818
+ return null;
29819
+ }
29786
29820
  }
29787
- function createNoopGraphDatabase4() {
29788
- const noop2 = async () => {
29789
- throw new Error("Graph not available during yield");
29790
- };
29791
- return {
29792
- connect: async () => {
29793
- },
29794
- disconnect: async () => {
29795
- },
29796
- isConnected: () => false,
29797
- createResource: noop2,
29798
- getResource: noop2,
29799
- updateResource: noop2,
29800
- deleteResource: noop2,
29801
- listResources: noop2,
29802
- searchResources: noop2,
29803
- createAnnotation: noop2,
29804
- getAnnotation: noop2,
29805
- updateAnnotation: noop2,
29806
- deleteAnnotation: noop2,
29807
- listAnnotations: noop2,
29808
- getHighlights: noop2,
29809
- resolveReference: noop2,
29810
- getReferences: noop2,
29811
- getEntityReferences: noop2,
29812
- getResourceAnnotations: noop2,
29813
- getResourceReferencedBy: noop2,
29814
- getResourceConnections: noop2,
29815
- findPath: noop2,
29816
- getEntityTypeStats: noop2,
29817
- getStats: noop2,
29818
- batchCreateResources: noop2,
29819
- createAnnotations: noop2,
29820
- resolveReferences: noop2,
29821
- detectAnnotations: noop2,
29822
- getEntityTypes: noop2,
29823
- addEntityType: noop2,
29824
- addEntityTypes: noop2,
29825
- generateId: () => "noop",
29826
- clearDatabase: noop2
29821
+ function writeTokenCache(cachePath, cache) {
29822
+ fs51.mkdirSync(path43.dirname(cachePath), { recursive: true, mode: 448 });
29823
+ fs51.writeFileSync(cachePath, JSON.stringify(cache, null, 2), { mode: 384 });
29824
+ }
29825
+ function isTokenValid(cache) {
29826
+ const cachedAt = new Date(cache.cachedAt).getTime();
29827
+ return Date.now() < cachedAt + TOKEN_CACHE_TTL_MS;
29828
+ }
29829
+ async function acquireToken(rawBusUrl, emailStr, passwordStr) {
29830
+ const client = new SemiontApiClient3({ baseUrl: toBaseUrl(rawBusUrl) });
29831
+ const authResult = await client.authenticatePassword(toEmail(emailStr), passwordStr);
29832
+ const cache = {
29833
+ bus: rawBusUrl,
29834
+ email: emailStr,
29835
+ token: authResult.token,
29836
+ cachedAt: (/* @__PURE__ */ new Date()).toISOString()
29827
29837
  };
29838
+ writeTokenCache(tokenCachePath(rawBusUrl), cache);
29828
29839
  }
29829
- async function checksumFile(absPath) {
29830
- const buf = await nodeFs.readFile(absPath);
29831
- return createHash("sha256").update(buf).digest("hex");
29840
+ function loadCachedClient(rawBusUrl) {
29841
+ const cachePath = tokenCachePath(rawBusUrl);
29842
+ const cached = readTokenCache(cachePath);
29843
+ if (!cached || !isTokenValid(cached)) {
29844
+ throw new Error(
29845
+ `Not logged in to ${rawBusUrl}.
29846
+ Run: semiont login --bus ${rawBusUrl}`
29847
+ );
29848
+ }
29849
+ const client = new SemiontApiClient3({ baseUrl: toBaseUrl(rawBusUrl) });
29850
+ return { client, token: toAccessToken(cached.token) };
29851
+ }
29852
+ function resolveBusUrl(busFlag) {
29853
+ const url = busFlag ?? process.env.SEMIONT_BUS;
29854
+ if (!url) {
29855
+ throw new Error(
29856
+ "Backend URL not configured. Use --bus <url> or set $SEMIONT_BUS.\nRun `semiont login --bus <url>` to authenticate."
29857
+ );
29858
+ }
29859
+ return url;
29832
29860
  }
29861
+
29862
+ // src/core/commands/yield.ts
29833
29863
  function guessFormat(filePath) {
29834
- const ext = path43.extname(filePath).toLowerCase();
29864
+ const ext = path44.extname(filePath).toLowerCase();
29835
29865
  const map2 = {
29836
29866
  ".md": "text/markdown",
29837
29867
  ".markdown": "text/markdown",
@@ -29846,428 +29876,1332 @@ function guessFormat(filePath) {
29846
29876
  };
29847
29877
  return map2[ext] ?? "application/octet-stream";
29848
29878
  }
29849
- var YieldOptionsSchema = BaseOptionsSchema.extend({
29850
- files: external_exports.array(external_exports.string()).min(1, "At least one file path is required"),
29879
+ var YieldOptionsSchema = ApiOptionsSchema.extend({
29880
+ // Mode flags
29881
+ upload: external_exports.array(external_exports.string()).default([]),
29882
+ delegate: external_exports.boolean().default(false),
29883
+ // Upload mode options
29851
29884
  name: external_exports.string().optional(),
29852
- noGit: external_exports.boolean().default(false)
29885
+ // Delegate mode required
29886
+ resource: external_exports.string().optional(),
29887
+ annotation: external_exports.string().optional(),
29888
+ storageUri: external_exports.string().optional(),
29889
+ // Delegate mode optional
29890
+ title: external_exports.string().optional(),
29891
+ prompt: external_exports.string().optional(),
29892
+ language: external_exports.string().optional(),
29893
+ temperature: external_exports.coerce.number().min(0).max(1).optional(),
29894
+ maxTokens: external_exports.coerce.number().int().min(100).max(4e3).optional(),
29895
+ contextWindow: external_exports.coerce.number().int().min(100).max(5e3).default(1e3)
29896
+ }).superRefine((val, ctx) => {
29897
+ const hasUpload = val.upload.length > 0;
29898
+ const hasDelegate = val.delegate;
29899
+ if (!hasUpload && !hasDelegate) {
29900
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, message: "One of --upload <file> or --delegate is required" });
29901
+ }
29902
+ if (hasUpload && hasDelegate) {
29903
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, message: "--upload and --delegate are mutually exclusive" });
29904
+ }
29905
+ if (hasUpload && val.name && val.upload.length > 1) {
29906
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, message: "--name can only be used when uploading a single file" });
29907
+ }
29908
+ if (hasDelegate) {
29909
+ if (!val.resource) ctx.addIssue({ code: external_exports.ZodIssueCode.custom, message: "--resource <resourceId> is required with --delegate" });
29910
+ if (!val.annotation) ctx.addIssue({ code: external_exports.ZodIssueCode.custom, message: "--annotation <annotationId> is required with --delegate" });
29911
+ if (!val.storageUri) ctx.addIssue({ code: external_exports.ZodIssueCode.custom, message: "--storage-uri is required with --delegate" });
29912
+ }
29853
29913
  });
29914
+ function waitForYieldFinished(eventBus) {
29915
+ return new Promise((resolve10, reject) => {
29916
+ const doneSub = eventBus.get("yield:finished").subscribe((event) => {
29917
+ doneSub.unsubscribe();
29918
+ failSub.unsubscribe();
29919
+ resolve10({ resourceId: event.resourceId, resourceName: event.resourceName });
29920
+ });
29921
+ const failSub = eventBus.get("yield:failed").subscribe((event) => {
29922
+ doneSub.unsubscribe();
29923
+ failSub.unsubscribe();
29924
+ reject(event.error ?? new Error("Generation failed"));
29925
+ });
29926
+ });
29927
+ }
29928
+ function waitForGatherAnnotationFinished(eventBus, annotationId) {
29929
+ return new Promise((resolve10, reject) => {
29930
+ const doneSub = eventBus.get("gather:annotation-finished").subscribe((event) => {
29931
+ if (event.annotationId !== annotationId) return;
29932
+ doneSub.unsubscribe();
29933
+ failSub.unsubscribe();
29934
+ const context = event.response.context;
29935
+ if (!context) {
29936
+ reject(new Error("No context returned from gatherAnnotation \u2014 cannot generate"));
29937
+ } else {
29938
+ resolve10(context);
29939
+ }
29940
+ });
29941
+ const failSub = eventBus.get("gather:failed").subscribe((event) => {
29942
+ if (event.annotationId !== annotationId) return;
29943
+ doneSub.unsubscribe();
29944
+ failSub.unsubscribe();
29945
+ reject(event.error ?? new Error("Gather annotation failed"));
29946
+ });
29947
+ });
29948
+ }
29949
+ async function runDelegate(client, token, options) {
29950
+ const rawResourceId = options.resource;
29951
+ const rawAnnotationId = options.annotation;
29952
+ const resourceId = toResourceId(rawResourceId);
29953
+ const annotationId = toAnnotationId(rawAnnotationId);
29954
+ const gatherEventBus = new EventBus4();
29955
+ const gatherPromise = waitForGatherAnnotationFinished(gatherEventBus, rawAnnotationId);
29956
+ client.sse.gatherAnnotation(
29957
+ resourceId,
29958
+ annotationId,
29959
+ { contextWindow: options.contextWindow },
29960
+ { auth: token, eventBus: gatherEventBus }
29961
+ );
29962
+ const context = await gatherPromise;
29963
+ if (!options.quiet) process.stderr.write(`Generating from annotation ${rawAnnotationId}...
29964
+ `);
29965
+ const eventBus = new EventBus4();
29966
+ const donePromise = waitForYieldFinished(eventBus);
29967
+ client.sse.yieldResource(
29968
+ resourceId,
29969
+ annotationId,
29970
+ {
29971
+ context,
29972
+ storageUri: options.storageUri,
29973
+ ...options.title && { title: options.title },
29974
+ ...options.prompt && { prompt: options.prompt },
29975
+ ...options.language && { language: options.language },
29976
+ ...options.temperature !== void 0 && { temperature: options.temperature },
29977
+ ...options.maxTokens !== void 0 && { maxTokens: options.maxTokens }
29978
+ },
29979
+ { auth: token, eventBus }
29980
+ );
29981
+ return await donePromise;
29982
+ }
29854
29983
  async function runYield(options) {
29855
29984
  const startTime = Date.now();
29985
+ const rawBusUrl = resolveBusUrl(options.bus);
29986
+ const { client, token } = loadCachedClient(rawBusUrl);
29856
29987
  const projectRoot = findProjectRoot();
29857
- const environment = options.environment;
29858
- const logger = createCliLogger6(options.verbose ?? false);
29859
- const userId = `did:web:localhost:users:${process.env.USER ?? "cli"}`;
29860
- if (options.name && options.files.length > 1) {
29861
- throw new Error("--name can only be used when yielding a single file");
29862
- }
29863
- const project = new SemiontProject22(projectRoot);
29864
- if (project.gitSync && !options.noGit) {
29865
- const gitCheck = checkGitAvailable();
29866
- if (!gitCheck.pass) throw new Error(gitCheck.message);
29988
+ if (options.delegate) {
29989
+ const { resourceId, resourceName } = await runDelegate(client, token, options);
29990
+ const label = resourceName ?? resourceId ?? options.storageUri;
29991
+ if (!options.quiet) printSuccess(`Yielded: ${options.storageUri} \u2192 ${resourceId ?? "(pending)"}`);
29992
+ process.stdout.write(JSON.stringify({ resourceId, resourceName, storageUri: options.storageUri }));
29993
+ if (!options.quiet) process.stdout.write("\n");
29994
+ return {
29995
+ command: "yield",
29996
+ environment: rawBusUrl,
29997
+ timestamp: /* @__PURE__ */ new Date(),
29998
+ duration: Date.now() - startTime,
29999
+ summary: { succeeded: 1, failed: 0, total: 1, warnings: 0 },
30000
+ executionContext: { user: process.env.USER || "unknown", workingDirectory: process.cwd(), dryRun: options.dryRun },
30001
+ results: [{ entity: label, platform: "posix", success: true, metadata: { resourceId, storageUri: options.storageUri }, duration: Date.now() - startTime }]
30002
+ };
29867
30003
  }
29868
- const eventBus = new EventBus4();
29869
- const eventStore = createEventStore6(project, eventBus, logger);
29870
- const kb = createKnowledgeBase4(eventStore, project, createNoopGraphDatabase4(), logger);
29871
- const stower = new Stower4(kb, eventBus, logger.child({ component: "stower" }));
29872
- await stower.initialize();
29873
30004
  let succeeded = 0;
29874
30005
  let failed = 0;
29875
30006
  const results = [];
29876
- try {
29877
- for (const filePath of options.files) {
29878
- const absPath = path43.isAbsolute(filePath) ? filePath : path43.resolve(projectRoot, filePath);
29879
- try {
29880
- await nodeFs.access(absPath);
29881
- } catch {
29882
- if (!options.quiet) printWarning(`File not found: ${filePath}`);
29883
- results.push({ entity: filePath, platform: "posix", success: false, metadata: { error: "File not found" }, duration: 0 });
29884
- failed++;
29885
- continue;
29886
- }
29887
- const relPath = path43.relative(projectRoot, absPath).replace(/\\/g, "/");
29888
- const storageUri = `file://${relPath}`;
29889
- let isTracked = false;
29890
- let existingResourceId;
29891
- try {
29892
- existingResourceId = await resolveStorageUri(kb.projectionsDir, storageUri);
29893
- isTracked = true;
29894
- } catch (e) {
29895
- if (!(e instanceof ResourceNotFoundError)) throw e;
29896
- }
29897
- const format = guessFormat(filePath);
29898
- const contentChecksum = await checksumFile(absPath);
29899
- const fileStart = Date.now();
29900
- if (!isTracked) {
29901
- const name = options.name ?? path43.basename(filePath, path43.extname(filePath));
29902
- const created = await new Promise((resolve12, reject) => {
29903
- const sub = eventBus.get("yield:created").subscribe((e) => {
29904
- sub.unsubscribe();
29905
- resolve12(e.resourceId);
29906
- });
29907
- eventBus.get("yield:create-failed").subscribe((e) => reject(e.error));
29908
- eventBus.get("yield:create").next({ name, storageUri, contentChecksum, format, userId, noGit: options.noGit });
29909
- });
29910
- if (!options.quiet) printSuccess(`Yielded: ${filePath} \u2192 ${created}`);
29911
- results.push({ entity: filePath, platform: "posix", success: true, metadata: { resourceId: created, storageUri }, duration: Date.now() - fileStart });
29912
- succeeded++;
29913
- } else {
29914
- const updated = await new Promise((resolve12, reject) => {
29915
- const sub = eventBus.get("yield:updated").subscribe(() => {
29916
- sub.unsubscribe();
29917
- resolve12();
29918
- });
29919
- eventBus.get("yield:update-failed").subscribe((e) => reject(e.error));
29920
- eventBus.get("yield:update").next({
29921
- resourceId: toResourceId(existingResourceId),
29922
- storageUri,
29923
- contentChecksum,
29924
- userId,
29925
- noGit: options.noGit
29926
- });
29927
- });
29928
- void updated;
29929
- if (!options.quiet) printSuccess(`Updated: ${filePath} (${existingResourceId})`);
29930
- results.push({ entity: filePath, platform: "posix", success: true, metadata: { resourceId: existingResourceId, storageUri }, duration: Date.now() - fileStart });
29931
- succeeded++;
29932
- }
30007
+ for (const filePath of options.upload) {
30008
+ const absPath = path44.isAbsolute(filePath) ? filePath : path44.resolve(projectRoot, filePath);
30009
+ const fileStart = Date.now();
30010
+ let content;
30011
+ try {
30012
+ content = await nodeFs.readFile(absPath);
30013
+ } catch {
30014
+ if (!options.quiet) printWarning(`File not found: ${filePath}`);
30015
+ results.push({ entity: filePath, platform: "posix", success: false, metadata: { error: "File not found" }, duration: 0 });
30016
+ failed++;
30017
+ continue;
29933
30018
  }
29934
- } finally {
29935
- await stower.stop();
29936
- eventBus.destroy();
30019
+ const relPath = path44.relative(projectRoot, absPath).replace(/\\/g, "/");
30020
+ const storageUri = `file://${relPath}`;
30021
+ const name = options.name ?? path44.basename(filePath, path44.extname(filePath));
30022
+ const format = guessFormat(filePath);
30023
+ const { resourceId } = await client.yieldResource(
30024
+ { name, file: content, format, storageUri },
30025
+ { auth: token }
30026
+ );
30027
+ if (!options.quiet) printSuccess(`Yielded: ${filePath} \u2192 ${resourceId}`);
30028
+ results.push({ entity: filePath, platform: "posix", success: true, metadata: { resourceId, storageUri }, duration: Date.now() - fileStart });
30029
+ succeeded++;
29937
30030
  }
29938
- const duration = Date.now() - startTime;
29939
30031
  return {
29940
30032
  command: "yield",
29941
- environment,
30033
+ environment: rawBusUrl,
29942
30034
  timestamp: /* @__PURE__ */ new Date(),
29943
- duration,
29944
- summary: { succeeded, failed, total: options.files.length, warnings: 0 },
30035
+ duration: Date.now() - startTime,
30036
+ summary: { succeeded, failed, total: options.upload.length, warnings: 0 },
29945
30037
  executionContext: { user: process.env.USER || "unknown", workingDirectory: process.cwd(), dryRun: options.dryRun },
29946
30038
  results
29947
30039
  };
29948
30040
  }
29949
- var yieldCmd = new CommandBuilder().name("yield").description("Register existing files as semiont resources, or record content updates for tracked files").requiresEnvironment(true).requiresServices(false).examples(
29950
- "semiont yield docs/overview.md",
29951
- 'semiont yield docs/new.md --name "Overview Document"'
30041
+ var yieldCmd = new CommandBuilder().name("yield").description(
30042
+ "Upload a local file as a resource (--upload), or generate a new resource from an annotation's gathered context (--delegate). Delegate mode outputs JSON { resourceId, resourceName, storageUri } to stdout."
30043
+ ).requiresEnvironment(true).requiresServices(true).examples(
30044
+ "semiont yield --upload docs/overview.md",
30045
+ 'semiont yield --upload docs/overview.md --name "Overview Document"',
30046
+ "semiont yield --upload docs/a.md --upload docs/b.md --upload docs/c.md",
30047
+ "semiont yield --delegate --resource <resourceId> --annotation <annotationId> --storage-uri file://generated/paris.md",
30048
+ 'semiont yield --delegate --resource <resourceId> --annotation <annotationId> --storage-uri file://generated/paris.md --title "Paris" --language en',
30049
+ 'semiont yield --delegate --resource <resourceId> --annotation <annotationId> --storage-uri file://generated/paris.md --prompt "Write a brief encyclopedia entry" --temperature 0.3',
30050
+ `NEW_ID=$(semiont yield --delegate --resource <resourceId> --annotation <annotationId> --storage-uri file://generated/loc.md --quiet | jq -r '.resourceId') && semiont bind <resourceId> <annotationId> "$NEW_ID"`
29952
30051
  ).args({
29953
- args: {
29954
- "--name": {
29955
- type: "string",
29956
- description: "Resource name (only valid for a single new file)"
30052
+ ...withApiArgs({
30053
+ "--upload": {
30054
+ type: "array",
30055
+ description: "Upload mode: one or more local file paths to register as resources (repeatable)"
29957
30056
  },
29958
- "--no-git": {
30057
+ "--delegate": {
29959
30058
  type: "boolean",
29960
- description: "Skip git add even when gitSync is configured",
30059
+ description: "Delegate mode: generate a new resource from an annotation's gathered context",
29961
30060
  default: false
30061
+ },
30062
+ "--name": {
30063
+ type: "string",
30064
+ description: "Upload mode: resource name (single file only)"
30065
+ },
30066
+ "--resource": {
30067
+ type: "string",
30068
+ description: "Delegate mode: source resourceId"
30069
+ },
30070
+ "--annotation": {
30071
+ type: "string",
30072
+ description: "Delegate mode: source annotationId"
30073
+ },
30074
+ "--storage-uri": {
30075
+ type: "string",
30076
+ description: "Delegate mode: file://-relative URI where the generated resource will be saved"
30077
+ },
30078
+ "--title": {
30079
+ type: "string",
30080
+ description: "Delegate mode: custom title for the generated resource"
30081
+ },
30082
+ "--prompt": {
30083
+ type: "string",
30084
+ description: "Delegate mode: custom prompt to guide content generation"
30085
+ },
30086
+ "--language": {
30087
+ type: "string",
30088
+ description: "Delegate mode: BCP 47 language tag for generated content (e.g. en, fr, ja)"
30089
+ },
30090
+ "--temperature": {
30091
+ type: "string",
30092
+ description: "Delegate mode: inference temperature 0.0\u20131.0 (0 = focused, 1 = creative)"
30093
+ },
30094
+ "--max-tokens": {
30095
+ type: "string",
30096
+ description: "Delegate mode: maximum tokens to generate (100\u20134000)"
30097
+ },
30098
+ "--context-window": {
30099
+ type: "string",
30100
+ description: "Delegate mode: characters of annotation context to gather (100\u20135000, default: 1000)"
29962
30101
  }
29963
- },
29964
- aliases: {
30102
+ }, {
29965
30103
  "-n": "--name"
29966
- },
29967
- restAs: "files"
30104
+ }),
30105
+ aliases: {}
29968
30106
  }).schema(YieldOptionsSchema).handler(runYield).build();
29969
30107
 
29970
- // src/core/commands/archive.ts
30108
+ // src/core/commands/mark.ts
29971
30109
  init_zod();
29972
30110
  init_command_definition();
29973
30111
  init_base_options_schema();
29974
30112
  init_cli_logger();
29975
- init_config_loader();
29976
- init_preflight_utils();
29977
- import * as path44 from "path";
29978
- import { SemiontProject as SemiontProject23 } from "@semiont/core/node";
29979
- import { EventBus as EventBus5 } from "@semiont/core";
29980
- import { createEventStore as createEventStore7 } from "@semiont/event-sourcing";
29981
- import { resolveStorageUri as resolveStorageUri2, ResourceNotFoundError as ResourceNotFoundError2 } from "@semiont/event-sourcing";
29982
- import { Stower as Stower5, createKnowledgeBase as createKnowledgeBase5 } from "@semiont/make-meaning";
29983
- function createCliLogger7(verbose) {
29984
- return {
29985
- debug: (msg, meta) => {
29986
- if (verbose) console.log(`[debug] ${msg}`, meta ?? "");
29987
- },
29988
- info: (msg, meta) => console.log(`[info] ${msg}`, meta ?? ""),
29989
- warn: (msg, meta) => console.warn(`[warn] ${msg}`, meta ?? ""),
29990
- error: (msg, meta) => console.error(`[error] ${msg}`, meta ?? ""),
29991
- child: () => createCliLogger7(verbose)
29992
- };
30113
+ import { resourceId as toResourceId2, EventBus as EventBus5 } from "@semiont/core";
30114
+ var MOTIVATIONS = ["highlighting", "commenting", "tagging", "assessing", "linking"];
30115
+ var CONTEXT_WINDOW = 32;
30116
+ var MarkOptionsSchema = ApiOptionsSchema.extend({
30117
+ resourceIdArr: external_exports.array(external_exports.string()).min(1, "resourceId is required").max(1, "Only one resourceId allowed"),
30118
+ motivation: external_exports.enum(MOTIVATIONS),
30119
+ // ── Mode switch ──────────────────────────────────────────────────────
30120
+ delegate: external_exports.boolean().default(false),
30121
+ // ── Manual mode ──────────────────────────────────────────────────────
30122
+ // TextQuoteSelector
30123
+ quote: external_exports.string().optional(),
30124
+ prefix: external_exports.string().optional(),
30125
+ suffix: external_exports.string().optional(),
30126
+ // TextPositionSelector
30127
+ start: external_exports.coerce.number().int().nonnegative().optional(),
30128
+ end: external_exports.coerce.number().int().nonnegative().optional(),
30129
+ // SvgSelector
30130
+ svg: external_exports.string().optional(),
30131
+ // FragmentSelector
30132
+ fragment: external_exports.string().optional(),
30133
+ fragmentConformsTo: external_exports.string().optional(),
30134
+ // Content fetching
30135
+ fetchContent: external_exports.boolean().default(false),
30136
+ // Body
30137
+ bodyText: external_exports.string().optional(),
30138
+ bodyFormat: external_exports.string().optional(),
30139
+ bodyLanguage: external_exports.string().optional(),
30140
+ bodyPurpose: external_exports.string().optional(),
30141
+ link: external_exports.array(external_exports.string()).optional(),
30142
+ // ── Delegate mode: shared ──────────────────────────────────────────────
30143
+ instructions: external_exports.string().optional(),
30144
+ density: external_exports.coerce.number().int().optional(),
30145
+ tone: external_exports.string().optional(),
30146
+ // ── Delegate mode: linking ─────────────────────────────────────────────
30147
+ entityType: external_exports.array(external_exports.string()).default([]),
30148
+ includeDescriptive: external_exports.boolean().default(false),
30149
+ // ── Delegate mode: tagging ─────────────────────────────────────────────
30150
+ schemaId: external_exports.string().optional(),
30151
+ category: external_exports.array(external_exports.string()).default([])
30152
+ }).superRefine((val, ctx) => {
30153
+ if (val.delegate) {
30154
+ const manualFlags = ["quote", "start", "end", "svg", "fragment", "fetchContent", "bodyText", "link"];
30155
+ for (const f of manualFlags) {
30156
+ const v = val[f];
30157
+ if (v !== void 0 && v !== false && !(Array.isArray(v) && v.length === 0)) {
30158
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, message: `--${f.replace(/([A-Z])/g, "-$1").toLowerCase()} cannot be used with --delegate` });
30159
+ }
30160
+ }
30161
+ if (val.motivation === "linking" && val.entityType.length === 0) {
30162
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, message: "--entity-type is required for --delegate --motivation linking" });
30163
+ }
30164
+ if (val.motivation === "tagging") {
30165
+ if (!val.schemaId) ctx.addIssue({ code: external_exports.ZodIssueCode.custom, message: "--schema-id is required for --delegate --motivation tagging" });
30166
+ if (val.category.length === 0) ctx.addIssue({ code: external_exports.ZodIssueCode.custom, message: "--category is required for --delegate --motivation tagging" });
30167
+ }
30168
+ }
30169
+ });
30170
+ async function fetchResourceText(client, resourceId, token) {
30171
+ const { data } = await client.getResourceRepresentation(resourceId, { accept: "text/plain", auth: token });
30172
+ return new TextDecoder().decode(data);
30173
+ }
30174
+ function buildTextSelector(options, content) {
30175
+ let exact = options.quote;
30176
+ let start2 = options.start;
30177
+ let end = options.end;
30178
+ if (content !== void 0) {
30179
+ if (exact !== void 0 && (start2 === void 0 || end === void 0)) {
30180
+ const idx = content.indexOf(exact);
30181
+ if (idx === -1) throw new Error(`--quote text not found in resource content: "${exact}"`);
30182
+ start2 = idx;
30183
+ end = idx + exact.length;
30184
+ } else if (start2 !== void 0 && end !== void 0 && exact === void 0) {
30185
+ exact = content.slice(start2, end);
30186
+ if (!exact) throw new Error(`--start/--end range [${start2}, ${end}) is empty or out of bounds`);
30187
+ }
30188
+ }
30189
+ const selectors = [];
30190
+ if (start2 !== void 0 && end !== void 0) {
30191
+ selectors.push({ type: "TextPositionSelector", start: start2, end });
30192
+ }
30193
+ if (exact !== void 0) {
30194
+ const q = { type: "TextQuoteSelector", exact };
30195
+ if (options.prefix !== void 0) {
30196
+ q.prefix = options.prefix;
30197
+ } else if (content !== void 0 && start2 !== void 0) {
30198
+ q.prefix = content.slice(Math.max(0, start2 - CONTEXT_WINDOW), start2);
30199
+ }
30200
+ if (options.suffix !== void 0) {
30201
+ q.suffix = options.suffix;
30202
+ } else if (content !== void 0 && end !== void 0) {
30203
+ q.suffix = content.slice(end, end + CONTEXT_WINDOW);
30204
+ }
30205
+ selectors.push(q);
30206
+ }
30207
+ return selectors;
30208
+ }
30209
+ async function buildSelector(options, client, resourceId, token) {
30210
+ const hasText = options.quote !== void 0 || options.start !== void 0 && options.end !== void 0;
30211
+ const hasSvg = options.svg !== void 0;
30212
+ const hasFragment = options.fragment !== void 0;
30213
+ const selectorTypes = [hasText, hasSvg, hasFragment].filter(Boolean).length;
30214
+ if (selectorTypes > 1) {
30215
+ throw new Error("Selector flags are mutually exclusive: use text (--quote/--start/--end), --svg, or --fragment, not a combination.");
30216
+ }
30217
+ if (hasSvg) {
30218
+ return { type: "SvgSelector", value: options.svg };
30219
+ }
30220
+ if (hasFragment) {
30221
+ const f = { type: "FragmentSelector", value: options.fragment };
30222
+ if (options.fragmentConformsTo) f.conformsTo = options.fragmentConformsTo;
30223
+ return f;
30224
+ }
30225
+ if (!hasText) return void 0;
30226
+ const content = options.fetchContent ? await fetchResourceText(client, resourceId, token) : void 0;
30227
+ const selectors = buildTextSelector(options, content);
30228
+ if (selectors.length === 0) return void 0;
30229
+ if (selectors.length === 1) return selectors[0];
30230
+ return selectors;
30231
+ }
30232
+ function buildBody(options) {
30233
+ const items = [];
30234
+ if (options.bodyText !== void 0) {
30235
+ const b = { type: "TextualBody", value: options.bodyText };
30236
+ if (options.bodyFormat) b.format = options.bodyFormat;
30237
+ if (options.bodyLanguage) b.language = options.bodyLanguage;
30238
+ b.purpose = options.bodyPurpose ?? options.motivation;
30239
+ items.push(b);
30240
+ }
30241
+ for (const source of options.link ?? []) {
30242
+ items.push({ type: "SpecificResource", source, purpose: "linking" });
30243
+ }
30244
+ if (items.length === 0) return [];
30245
+ if (items.length === 1) return items[0];
30246
+ return items;
30247
+ }
30248
+ function waitForAssistFinished(eventBus) {
30249
+ return new Promise((resolve10, reject) => {
30250
+ const doneSub = eventBus.get("mark:assist-finished").subscribe((event) => {
30251
+ doneSub.unsubscribe();
30252
+ failSub.unsubscribe();
30253
+ resolve10({
30254
+ motivation: event.motivation,
30255
+ resourceId: event.resourceId,
30256
+ createdCount: event.progress?.createdCount
30257
+ });
30258
+ });
30259
+ const failSub = eventBus.get("mark:assist-failed").subscribe((event) => {
30260
+ doneSub.unsubscribe();
30261
+ failSub.unsubscribe();
30262
+ reject(new Error(event.payload?.message ?? "Annotation failed"));
30263
+ });
30264
+ });
29993
30265
  }
29994
- function createNoopGraphDatabase5() {
29995
- const noop2 = async () => {
29996
- throw new Error("Graph not available during archive");
30266
+ async function runDelegate2(client, token, options) {
30267
+ const rawResourceId = options.resourceIdArr[0];
30268
+ const resourceId = toResourceId2(rawResourceId);
30269
+ const { motivation, instructions, density, tone, entityType, includeDescriptive, schemaId, category } = options;
30270
+ if (!options.quiet) process.stderr.write(`Annotating ${motivation} on ${rawResourceId}...
30271
+ `);
30272
+ const eventBus = new EventBus5();
30273
+ const donePromise = waitForAssistFinished(eventBus);
30274
+ const auth = token;
30275
+ switch (motivation) {
30276
+ case "highlighting":
30277
+ client.sse.markHighlights(resourceId, { instructions, density }, { auth, eventBus });
30278
+ break;
30279
+ case "assessing":
30280
+ client.sse.markAssessments(resourceId, { instructions, tone, density }, { auth, eventBus });
30281
+ break;
30282
+ case "commenting":
30283
+ client.sse.markComments(resourceId, { instructions, tone, density }, { auth, eventBus });
30284
+ break;
30285
+ case "linking":
30286
+ client.sse.markReferences(resourceId, { entityTypes: entityType, includeDescriptiveReferences: includeDescriptive }, { auth, eventBus });
30287
+ break;
30288
+ case "tagging":
30289
+ client.sse.markTags(resourceId, { schemaId, categories: category }, { auth, eventBus });
30290
+ break;
30291
+ }
30292
+ const result = await donePromise;
30293
+ const createdCount = result.createdCount ?? 0;
30294
+ if (!options.quiet) process.stderr.write(`\u2713 ${createdCount} annotations created
30295
+ `);
30296
+ return { motivation, resourceId: rawResourceId, createdCount };
30297
+ }
30298
+ async function runMark(options) {
30299
+ const startTime = Date.now();
30300
+ const rawBusUrl = resolveBusUrl(options.bus);
30301
+ const { client, token } = loadCachedClient(rawBusUrl);
30302
+ if (options.delegate) {
30303
+ const result = await runDelegate2(client, token, options);
30304
+ process.stdout.write(JSON.stringify(result));
30305
+ if (!options.quiet) process.stdout.write("\n");
30306
+ return {
30307
+ command: "mark",
30308
+ environment: rawBusUrl,
30309
+ timestamp: /* @__PURE__ */ new Date(),
30310
+ duration: Date.now() - startTime,
30311
+ summary: { succeeded: result.createdCount, failed: 0, total: result.createdCount, warnings: 0 },
30312
+ executionContext: { user: process.env.USER || "unknown", workingDirectory: process.cwd(), dryRun: options.dryRun },
30313
+ results: [{ entity: result.resourceId, platform: "posix", success: true, metadata: { createdCount: result.createdCount, motivation: result.motivation }, duration: Date.now() - startTime }]
30314
+ };
30315
+ }
30316
+ const rawResourceId = options.resourceIdArr[0];
30317
+ const resourceId = toResourceId2(rawResourceId);
30318
+ const selector = await buildSelector(options, client, resourceId, token);
30319
+ const body = buildBody(options);
30320
+ const target = selector !== void 0 ? { source: rawResourceId, selector } : { source: rawResourceId, selector: void 0 };
30321
+ const request = {
30322
+ motivation: options.motivation,
30323
+ target,
30324
+ body
29997
30325
  };
30326
+ const { annotationId } = await client.markAnnotation(resourceId, request, { auth: token });
30327
+ if (!options.quiet) printSuccess(`Marked: ${rawResourceId} \u2192 ${annotationId}`);
29998
30328
  return {
29999
- connect: async () => {
30000
- },
30001
- disconnect: async () => {
30002
- },
30003
- isConnected: () => false,
30004
- createResource: noop2,
30005
- getResource: noop2,
30006
- updateResource: noop2,
30007
- deleteResource: noop2,
30008
- listResources: noop2,
30009
- searchResources: noop2,
30010
- createAnnotation: noop2,
30011
- getAnnotation: noop2,
30012
- updateAnnotation: noop2,
30013
- deleteAnnotation: noop2,
30014
- listAnnotations: noop2,
30015
- getHighlights: noop2,
30016
- resolveReference: noop2,
30017
- getReferences: noop2,
30018
- getEntityReferences: noop2,
30019
- getResourceAnnotations: noop2,
30020
- getResourceReferencedBy: noop2,
30021
- getResourceConnections: noop2,
30022
- findPath: noop2,
30023
- getEntityTypeStats: noop2,
30024
- getStats: noop2,
30025
- batchCreateResources: noop2,
30026
- createAnnotations: noop2,
30027
- resolveReferences: noop2,
30028
- detectAnnotations: noop2,
30029
- getEntityTypes: noop2,
30030
- addEntityType: noop2,
30031
- addEntityTypes: noop2,
30032
- generateId: () => "noop",
30033
- clearDatabase: noop2
30329
+ command: "mark",
30330
+ environment: rawBusUrl,
30331
+ timestamp: /* @__PURE__ */ new Date(),
30332
+ duration: Date.now() - startTime,
30333
+ summary: { succeeded: 1, failed: 0, total: 1, warnings: 0 },
30334
+ executionContext: { user: process.env.USER || "unknown", workingDirectory: process.cwd(), dryRun: options.dryRun },
30335
+ results: [{ entity: rawResourceId, platform: "posix", success: true, metadata: { annotationId }, duration: Date.now() - startTime }]
30034
30336
  };
30035
30337
  }
30036
- var ArchiveOptionsSchema = BaseOptionsSchema.extend({
30037
- files: external_exports.array(external_exports.string()).min(1, "At least one file path is required"),
30038
- keepFile: external_exports.boolean().default(false),
30039
- noGit: external_exports.boolean().default(false)
30040
- });
30041
- async function runArchive(options) {
30042
- const startTime = Date.now();
30043
- const projectRoot = findProjectRoot();
30044
- const environment = options.environment;
30045
- const logger = createCliLogger7(options.verbose ?? false);
30046
- const userId = `did:web:localhost:users:${process.env.USER ?? "cli"}`;
30047
- const project = new SemiontProject23(projectRoot);
30048
- if (project.gitSync && !options.noGit) {
30049
- const gitCheck = checkGitAvailable();
30050
- if (!gitCheck.pass) throw new Error(gitCheck.message);
30051
- }
30052
- const eventBus = new EventBus5();
30053
- const eventStore = createEventStore7(project, eventBus, logger);
30054
- const kb = createKnowledgeBase5(eventStore, project, createNoopGraphDatabase5(), logger);
30055
- const stower = new Stower5(kb, eventBus, logger.child({ component: "stower" }));
30056
- await stower.initialize();
30057
- let succeeded = 0;
30058
- let failed = 0;
30059
- const results = [];
30060
- try {
30061
- for (const filePath of options.files) {
30062
- const absPath = path44.isAbsolute(filePath) ? filePath : path44.resolve(projectRoot, filePath);
30063
- const relPath = path44.relative(projectRoot, absPath).replace(/\\/g, "/");
30064
- const storageUri = `file://${relPath}`;
30065
- const fileStart = Date.now();
30066
- let resourceId;
30067
- try {
30068
- resourceId = await resolveStorageUri2(kb.projectionsDir, storageUri);
30069
- } catch (e) {
30070
- if (e instanceof ResourceNotFoundError2) {
30071
- if (!options.quiet) printWarning(`Not tracked by semiont: ${filePath}`);
30072
- results.push({ entity: filePath, platform: "posix", success: false, metadata: { error: "Not tracked" }, duration: 0 });
30073
- failed++;
30074
- continue;
30075
- }
30076
- throw e;
30077
- }
30078
- eventBus.scope(resourceId).get("mark:archive").next({
30079
- userId,
30080
- resourceId,
30081
- storageUri,
30082
- keepFile: options.keepFile,
30083
- noGit: options.noGit
30084
- });
30085
- await new Promise((resolve12) => setTimeout(resolve12, 200));
30086
- if (!options.quiet) printSuccess(`Archived: ${filePath}`);
30087
- results.push({ entity: filePath, platform: "posix", success: true, metadata: { resourceId, storageUri }, duration: Date.now() - fileStart });
30088
- succeeded++;
30338
+ var markCmd = new CommandBuilder().name("mark").description(
30339
+ "Create a W3C annotation on a resource. Manual mode (default): create a single explicitly-specified annotation. Delegate mode (--delegate): AI-assisted bulk annotation via SSE stream. Outputs JSON { motivation, resourceId, createdCount } in delegate mode."
30340
+ ).requiresEnvironment(true).requiresServices(true).examples(
30341
+ // Manual mode
30342
+ 'semiont mark <resourceId> --motivation highlighting --quote "some text"',
30343
+ 'semiont mark <resourceId> --motivation highlighting --quote "some text" --fetch-content',
30344
+ 'semiont mark <resourceId> --motivation commenting --quote "some text" --body-text "my comment"',
30345
+ 'semiont mark <resourceId> --motivation linking --quote "some text" --link <targetResourceId>',
30346
+ 'semiont mark <resourceId> --motivation tagging --quote "Einstein" --body-text "Person"',
30347
+ // Detect mode
30348
+ "semiont mark <resourceId> --delegate --motivation highlighting",
30349
+ 'semiont mark <resourceId> --delegate --motivation highlighting --instructions "Focus on key claims" --density 8',
30350
+ "semiont mark <resourceId> --delegate --motivation assessing --tone analytical --density 4",
30351
+ "semiont mark <resourceId> --delegate --motivation commenting --tone scholarly",
30352
+ "semiont mark <resourceId> --delegate --motivation linking --entity-type Location --entity-type Person",
30353
+ "semiont mark <resourceId> --delegate --motivation linking --entity-type Location --include-descriptive",
30354
+ "semiont mark <resourceId> --delegate --motivation tagging --schema-id <schemaId> --category Biology --category Chemistry"
30355
+ ).args({
30356
+ ...withApiArgs({
30357
+ "--motivation": {
30358
+ type: "string",
30359
+ description: `Annotation motivation: ${MOTIVATIONS.join(", ")}`
30360
+ },
30361
+ // ── Mode switch ───────────────────────────────────────────────────
30362
+ "--delegate": {
30363
+ type: "boolean",
30364
+ description: "Delegate annotation work to AI (request mode); incompatible with manual selector flags",
30365
+ default: false
30366
+ },
30367
+ // ── Manual mode options ───────────────────────────────────────────
30368
+ "--quote": {
30369
+ type: "string",
30370
+ description: "Manual: TextQuoteSelector exact text to select"
30371
+ },
30372
+ "--prefix": {
30373
+ type: "string",
30374
+ description: "Manual: TextQuoteSelector context before the quote (auto-derived with --fetch-content)"
30375
+ },
30376
+ "--suffix": {
30377
+ type: "string",
30378
+ description: "Manual: TextQuoteSelector context after the quote (auto-derived with --fetch-content)"
30379
+ },
30380
+ "--start": {
30381
+ type: "string",
30382
+ description: "Manual: TextPositionSelector start character offset"
30383
+ },
30384
+ "--end": {
30385
+ type: "string",
30386
+ description: "Manual: TextPositionSelector end character offset"
30387
+ },
30388
+ "--fetch-content": {
30389
+ type: "boolean",
30390
+ description: "Manual: fetch resource text to auto-complete dual selector",
30391
+ default: false
30392
+ },
30393
+ "--svg": {
30394
+ type: "string",
30395
+ description: "Manual: SvgSelector SVG markup defining a region (for images)"
30396
+ },
30397
+ "--fragment": {
30398
+ type: "string",
30399
+ description: "Manual: FragmentSelector media fragment value"
30400
+ },
30401
+ "--fragment-conforms-to": {
30402
+ type: "string",
30403
+ description: "Manual: FragmentSelector conformance URI"
30404
+ },
30405
+ "--body-text": {
30406
+ type: "string",
30407
+ description: "Manual: TextualBody text content"
30408
+ },
30409
+ "--body-format": {
30410
+ type: "string",
30411
+ description: "Manual: TextualBody MIME type (default: text/plain)"
30412
+ },
30413
+ "--body-language": {
30414
+ type: "string",
30415
+ description: "Manual: TextualBody BCP 47 language tag"
30416
+ },
30417
+ "--body-purpose": {
30418
+ type: "string",
30419
+ description: "Manual: TextualBody purpose (defaults to motivation)"
30420
+ },
30421
+ "--link": {
30422
+ type: "array",
30423
+ description: "Manual: SpecificResource body target resourceId to link to (repeatable)"
30424
+ },
30425
+ // ── Delegate mode: shared ───────────────────────────────────────────
30426
+ "--instructions": {
30427
+ type: "string",
30428
+ description: "Delegate: free-text instructions for the AI (highlighting, assessing, commenting)"
30429
+ },
30430
+ "--density": {
30431
+ type: "string",
30432
+ description: "Delegate: annotations per 2000 words (highlighting: 1\u201315; assessing: 1\u201310; commenting: 2\u201312)"
30433
+ },
30434
+ "--tone": {
30435
+ type: "string",
30436
+ description: "Delegate: tone for assessing (analytical|critical|balanced|constructive) or commenting (scholarly|explanatory|conversational|technical)"
30437
+ },
30438
+ // ── Delegate mode: linking ──────────────────────────────────────────
30439
+ "--entity-type": {
30440
+ type: "array",
30441
+ description: "Delegate linking: entity type to detect (repeatable; at least one required)"
30442
+ },
30443
+ "--include-descriptive": {
30444
+ type: "boolean",
30445
+ description: "Delegate linking: also detect descriptive/prose references",
30446
+ default: false
30447
+ },
30448
+ // ── Delegate mode: tagging ──────────────────────────────────────────
30449
+ "--schema-id": {
30450
+ type: "string",
30451
+ description: "Delegate tagging: tag schema ID (required)"
30452
+ },
30453
+ "--category": {
30454
+ type: "array",
30455
+ description: "Delegate tagging: category within the schema (repeatable; at least one required)"
30089
30456
  }
30090
- } finally {
30091
- await stower.stop();
30092
- eventBus.destroy();
30457
+ }, {
30458
+ "-m": "--motivation"
30459
+ }),
30460
+ restAs: "resourceIdArr",
30461
+ aliases: {}
30462
+ }).schema(MarkOptionsSchema).handler(runMark).build();
30463
+
30464
+ // src/core/commands/gather.ts
30465
+ init_zod();
30466
+ init_command_definition();
30467
+ init_base_options_schema();
30468
+ import { resourceId as toResourceId3, annotationId as toAnnotationId2, EventBus as EventBus6 } from "@semiont/core";
30469
+ var GatherOptionsSchema = ApiOptionsSchema.extend({
30470
+ args: external_exports.array(external_exports.string()).min(2, "Usage: semiont gather resource <resourceId> | gather annotation <resourceId> <annotationId>"),
30471
+ // resource options
30472
+ depth: external_exports.coerce.number().int().min(1).max(3).default(2),
30473
+ maxResources: external_exports.coerce.number().int().min(1).max(20).default(10),
30474
+ noContent: external_exports.boolean().default(false),
30475
+ summary: external_exports.boolean().default(false),
30476
+ // annotation options
30477
+ contextWindow: external_exports.coerce.number().int().min(100).max(5e3).default(1e3)
30478
+ });
30479
+ function waitForGatherResourceFinished(eventBus) {
30480
+ return new Promise((resolve10, reject) => {
30481
+ const doneSub = eventBus.get("gather:finished").subscribe((event) => {
30482
+ doneSub.unsubscribe();
30483
+ failSub.unsubscribe();
30484
+ resolve10(event.context);
30485
+ });
30486
+ const failSub = eventBus.get("gather:failed").subscribe((event) => {
30487
+ doneSub.unsubscribe();
30488
+ failSub.unsubscribe();
30489
+ reject(event.error ?? new Error("Gather resource failed"));
30490
+ });
30491
+ });
30492
+ }
30493
+ function waitForGatherAnnotationFinished2(eventBus) {
30494
+ return new Promise((resolve10, reject) => {
30495
+ const doneSub = eventBus.get("gather:annotation-finished").subscribe((event) => {
30496
+ doneSub.unsubscribe();
30497
+ failSub.unsubscribe();
30498
+ resolve10(event.response);
30499
+ });
30500
+ const failSub = eventBus.get("gather:failed").subscribe((event) => {
30501
+ doneSub.unsubscribe();
30502
+ failSub.unsubscribe();
30503
+ reject(event.error ?? new Error("Gather annotation failed"));
30504
+ });
30505
+ });
30506
+ }
30507
+ async function runGather(options) {
30508
+ const startTime = Date.now();
30509
+ const rawBusUrl = resolveBusUrl(options.bus);
30510
+ const { client, token } = loadCachedClient(rawBusUrl);
30511
+ const [subcommand, rawResourceId, rawAnnotationId] = options.args;
30512
+ let result;
30513
+ if (subcommand === "resource") {
30514
+ const id = toResourceId3(rawResourceId);
30515
+ const eventBus = new EventBus6();
30516
+ const donePromise = waitForGatherResourceFinished(eventBus);
30517
+ client.sse.gatherResource(
30518
+ id,
30519
+ {
30520
+ depth: options.depth,
30521
+ maxResources: options.maxResources,
30522
+ includeContent: !options.noContent,
30523
+ includeSummary: options.summary
30524
+ },
30525
+ { auth: token, eventBus }
30526
+ );
30527
+ result = await donePromise;
30528
+ } else if (subcommand === "annotation") {
30529
+ if (!rawAnnotationId) {
30530
+ throw new Error("Usage: semiont gather annotation <resourceId> <annotationId>");
30531
+ }
30532
+ const resourceId = toResourceId3(rawResourceId);
30533
+ const annotationId = toAnnotationId2(rawAnnotationId);
30534
+ const eventBus = new EventBus6();
30535
+ const donePromise = waitForGatherAnnotationFinished2(eventBus);
30536
+ client.sse.gatherAnnotation(
30537
+ resourceId,
30538
+ annotationId,
30539
+ { contextWindow: options.contextWindow },
30540
+ { auth: token, eventBus }
30541
+ );
30542
+ result = await donePromise;
30543
+ } else {
30544
+ throw new Error(`Unknown subcommand: ${subcommand}. Use 'resource' or 'annotation'.`);
30093
30545
  }
30094
- const duration = Date.now() - startTime;
30546
+ process.stdout.write(JSON.stringify(result, null, 2));
30547
+ if (!options.quiet) process.stdout.write("\n");
30095
30548
  return {
30096
- command: "archive",
30097
- environment,
30549
+ command: "gather",
30550
+ environment: rawBusUrl,
30098
30551
  timestamp: /* @__PURE__ */ new Date(),
30099
- duration,
30100
- summary: { succeeded, failed, total: options.files.length, warnings: 0 },
30552
+ duration: Date.now() - startTime,
30553
+ summary: { succeeded: 1, failed: 0, total: 1, warnings: 0 },
30101
30554
  executionContext: { user: process.env.USER || "unknown", workingDirectory: process.cwd(), dryRun: options.dryRun },
30102
- results
30555
+ results: [{ entity: rawResourceId, platform: "posix", success: true, duration: Date.now() - startTime }]
30103
30556
  };
30104
30557
  }
30105
- var archiveCmd = new CommandBuilder().name("archive").description("Archive tracked semiont resources (removes file from git and disk)").requiresEnvironment(true).requiresServices(false).examples(
30106
- "semiont archive docs/old.md",
30107
- "semiont archive docs/old.md --keep-file"
30558
+ var gatherCmd = new CommandBuilder().name("gather").description("Fetch LLM-optimized context for a resource or annotation. Outputs JSON to stdout: ResourceLLMContextResponse (resource) or AnnotationLLMContextResponse containing GatheredContext (annotation). Schemas defined in specs/src/components/schemas/.").requiresEnvironment(true).requiresServices(true).examples(
30559
+ "semiont gather resource <resourceId>",
30560
+ "semiont gather resource <resourceId> --depth 3 --max-resources 20",
30561
+ "semiont gather resource <resourceId> --no-content",
30562
+ "semiont gather annotation <resourceId> <annotationId>",
30563
+ "semiont gather annotation <resourceId> <annotationId> --context-window 200",
30564
+ "semiont gather resource <resourceId> | jq '.mainResource.name'",
30565
+ "semiont gather annotation <resourceId> <annotationId> | jq '.context.sourceContext.selected'"
30108
30566
  ).args({
30109
- args: {
30110
- "--keep-file": {
30567
+ ...withApiArgs({
30568
+ "--depth": {
30569
+ type: "string",
30570
+ description: "Graph traversal depth: 1\u20133 (default: 2)"
30571
+ },
30572
+ "--max-resources": {
30573
+ type: "string",
30574
+ description: "Max related resources to include: 1\u201320 (default: 10)"
30575
+ },
30576
+ "--no-content": {
30111
30577
  type: "boolean",
30112
- description: "Remove from git index only \u2014 keep file on disk",
30578
+ description: "Exclude full resource content (default: content included)",
30113
30579
  default: false
30114
30580
  },
30115
- "--no-git": {
30581
+ "--summary": {
30116
30582
  type: "boolean",
30117
- description: "Skip git rm even when gitSync is configured",
30583
+ description: "Request AI-generated summary (default: false)",
30118
30584
  default: false
30585
+ },
30586
+ "--context-window": {
30587
+ type: "string",
30588
+ description: "Characters of surrounding text context: 100\u20135000 (default: 1000)"
30119
30589
  }
30120
- },
30121
- aliases: {},
30122
- restAs: "files"
30123
- }).schema(ArchiveOptionsSchema).handler(runArchive).build();
30590
+ }, {}),
30591
+ restAs: "args",
30592
+ aliases: {}
30593
+ }).schema(GatherOptionsSchema).handler(runGather).build();
30124
30594
 
30125
- // src/core/commands/unarchive.ts
30595
+ // src/core/commands/match.ts
30126
30596
  init_zod();
30127
30597
  init_command_definition();
30128
30598
  init_base_options_schema();
30129
- init_cli_logger();
30130
- init_config_loader();
30131
- import * as path45 from "path";
30132
- import { promises as nodeFs2 } from "fs";
30133
- import { SemiontProject as SemiontProject24 } from "@semiont/core/node";
30134
- import { EventBus as EventBus6 } from "@semiont/core";
30135
- import { createEventStore as createEventStore8 } from "@semiont/event-sourcing";
30136
- import { resolveStorageUri as resolveStorageUri3, ResourceNotFoundError as ResourceNotFoundError3 } from "@semiont/event-sourcing";
30137
- import { Stower as Stower6, createKnowledgeBase as createKnowledgeBase6 } from "@semiont/make-meaning";
30138
- function createCliLogger8(verbose) {
30139
- return {
30140
- debug: (msg, meta) => {
30141
- if (verbose) console.log(`[debug] ${msg}`, meta ?? "");
30599
+ import { resourceId as toResourceId4, annotationId as toAnnotationId3, EventBus as EventBus7 } from "@semiont/core";
30600
+ var MatchOptionsSchema = ApiOptionsSchema.extend({
30601
+ args: external_exports.array(external_exports.string()).min(2, "Usage: semiont match <resourceId> <annotationId>").max(2),
30602
+ contextWindow: external_exports.coerce.number().int().min(100).max(5e3).default(1e3),
30603
+ userHint: external_exports.string().optional(),
30604
+ limit: external_exports.coerce.number().int().min(1).max(20).default(10),
30605
+ noSemantic: external_exports.boolean().default(false)
30606
+ });
30607
+ function waitForSearchResults(eventBus, referenceId) {
30608
+ return new Promise((resolve10, reject) => {
30609
+ const resultSub = eventBus.get("bind:search-results").subscribe((event) => {
30610
+ if (event.referenceId === referenceId) {
30611
+ resultSub.unsubscribe();
30612
+ errorSub.unsubscribe();
30613
+ resolve10(event.results);
30614
+ }
30615
+ });
30616
+ const errorSub = eventBus.get("bind:search-failed").subscribe((event) => {
30617
+ if (event.referenceId === referenceId) {
30618
+ resultSub.unsubscribe();
30619
+ errorSub.unsubscribe();
30620
+ reject(event.error);
30621
+ }
30622
+ });
30623
+ });
30624
+ }
30625
+ async function gatherContext(client, resourceId, annotationId, contextWindow, token) {
30626
+ const eventBus = new EventBus7();
30627
+ const contextPromise = new Promise((resolve10, reject) => {
30628
+ const doneSub = eventBus.get("gather:annotation-finished").subscribe((event) => {
30629
+ if (event.annotationId !== annotationId) return;
30630
+ doneSub.unsubscribe();
30631
+ failSub.unsubscribe();
30632
+ const context = event.response.context;
30633
+ if (!context) {
30634
+ reject(new Error("No context returned from gatherAnnotation"));
30635
+ } else {
30636
+ resolve10(context);
30637
+ }
30638
+ });
30639
+ const failSub = eventBus.get("gather:failed").subscribe((event) => {
30640
+ if (event.annotationId !== annotationId) return;
30641
+ doneSub.unsubscribe();
30642
+ failSub.unsubscribe();
30643
+ reject(event.error ?? new Error("Gather annotation failed"));
30644
+ });
30645
+ });
30646
+ client.sse.gatherAnnotation(
30647
+ resourceId,
30648
+ annotationId,
30649
+ { contextWindow },
30650
+ { auth: token, eventBus }
30651
+ );
30652
+ return contextPromise;
30653
+ }
30654
+ async function runMatch(options) {
30655
+ const startTime = Date.now();
30656
+ const [rawResourceId, rawAnnotationId] = options.args;
30657
+ const resourceId = toResourceId4(rawResourceId);
30658
+ const annotationId = toAnnotationId3(rawAnnotationId);
30659
+ const rawBusUrl = resolveBusUrl(options.bus);
30660
+ const { client, token } = loadCachedClient(rawBusUrl);
30661
+ let context = await gatherContext(client, resourceId, annotationId, options.contextWindow, token);
30662
+ if (options.userHint) {
30663
+ context = { ...context, userHint: options.userHint };
30664
+ }
30665
+ const eventBus = new EventBus7();
30666
+ const resultsPromise = waitForSearchResults(eventBus, rawAnnotationId);
30667
+ client.sse.bindSearch(
30668
+ resourceId,
30669
+ {
30670
+ referenceId: rawAnnotationId,
30671
+ context,
30672
+ limit: options.limit,
30673
+ useSemanticScoring: !options.noSemantic
30142
30674
  },
30143
- info: (msg, meta) => console.log(`[info] ${msg}`, meta ?? ""),
30144
- warn: (msg, meta) => console.warn(`[warn] ${msg}`, meta ?? ""),
30145
- error: (msg, meta) => console.error(`[error] ${msg}`, meta ?? ""),
30146
- child: () => createCliLogger8(verbose)
30675
+ { auth: token, eventBus }
30676
+ );
30677
+ const results = await resultsPromise;
30678
+ process.stdout.write(JSON.stringify(results, null, 2));
30679
+ if (!options.quiet) process.stdout.write("\n");
30680
+ return {
30681
+ command: "match",
30682
+ environment: rawBusUrl,
30683
+ timestamp: /* @__PURE__ */ new Date(),
30684
+ duration: Date.now() - startTime,
30685
+ summary: { succeeded: 1, failed: 0, total: 1, warnings: 0 },
30686
+ executionContext: { user: process.env.USER || "unknown", workingDirectory: process.cwd(), dryRun: options.dryRun },
30687
+ results: [{ entity: rawAnnotationId, platform: "posix", success: true, metadata: { resultCount: results.length }, duration: Date.now() - startTime }]
30147
30688
  };
30148
30689
  }
30149
- function createNoopGraphDatabase6() {
30150
- const noop2 = async () => {
30151
- throw new Error("Graph not available during unarchive");
30690
+ var matchCmd = new CommandBuilder().name("match").description("Search for binding candidates for an annotation. Outputs JSON array of ResourceDescriptor & { score?, matchReason? } to stdout. Uses the same flow as the Search button in the Gather Context modal.").requiresEnvironment(true).requiresServices(true).examples(
30691
+ "semiont match <resourceId> <annotationId>",
30692
+ 'semiont match <resourceId> <annotationId> --user-hint "look for papers about neural scaling"',
30693
+ "semiont match <resourceId> <annotationId> --limit 5 --no-semantic",
30694
+ "semiont match <resourceId> <annotationId> | jq '.[0].name'",
30695
+ `semiont match <resourceId> <annotationId> | jq -r '.[0]["@id"]' | xargs -I{} semiont mark <resourceId> --motivation linking --link {}`
30696
+ ).args({
30697
+ ...withApiArgs({
30698
+ "--context-window": {
30699
+ type: "string",
30700
+ description: "Characters of context around annotation: 100\u20135000 (default: 1000)"
30701
+ },
30702
+ "--user-hint": {
30703
+ type: "string",
30704
+ description: "Override/supplement the context text used for matching"
30705
+ },
30706
+ "--limit": {
30707
+ type: "string",
30708
+ description: "Max results to return: 1\u201320 (default: 10)"
30709
+ },
30710
+ "--no-semantic": {
30711
+ type: "boolean",
30712
+ description: "Disable semantic scoring (faster, keyword-only)",
30713
+ default: false
30714
+ }
30715
+ }, {}),
30716
+ restAs: "args",
30717
+ aliases: {}
30718
+ }).schema(MatchOptionsSchema).handler(runMatch).build();
30719
+
30720
+ // src/core/commands/bind.ts
30721
+ init_zod();
30722
+ init_command_definition();
30723
+ init_base_options_schema();
30724
+ init_cli_logger();
30725
+ import { resourceId as toResourceId5, annotationId as toAnnotationId4, EventBus as EventBus8 } from "@semiont/core";
30726
+ var BindOptionsSchema = ApiOptionsSchema.extend({
30727
+ args: external_exports.array(external_exports.string()).min(3, "Usage: semiont bind <resourceId> <annotationId> <targetResourceId>").max(3)
30728
+ });
30729
+ function waitForBindFinished(eventBus) {
30730
+ return new Promise((resolve10, reject) => {
30731
+ const doneSub = eventBus.get("bind:finished").subscribe(() => {
30732
+ doneSub.unsubscribe();
30733
+ failSub.unsubscribe();
30734
+ resolve10();
30735
+ });
30736
+ const failSub = eventBus.get("bind:failed").subscribe((event) => {
30737
+ doneSub.unsubscribe();
30738
+ failSub.unsubscribe();
30739
+ reject(event.error ?? new Error("Bind failed"));
30740
+ });
30741
+ });
30742
+ }
30743
+ async function runBind(options) {
30744
+ const startTime = Date.now();
30745
+ const rawBusUrl = resolveBusUrl(options.bus);
30746
+ const { client, token } = loadCachedClient(rawBusUrl);
30747
+ const [rawResourceId, rawAnnotationId, targetResourceId] = options.args;
30748
+ const resourceId = toResourceId5(rawResourceId);
30749
+ const annotationId = toAnnotationId4(rawAnnotationId);
30750
+ const request = {
30751
+ resourceId: rawResourceId,
30752
+ operations: [{
30753
+ op: "add",
30754
+ item: {
30755
+ type: "SpecificResource",
30756
+ source: targetResourceId,
30757
+ purpose: "linking"
30758
+ }
30759
+ }]
30152
30760
  };
30761
+ const eventBus = new EventBus8();
30762
+ const donePromise = waitForBindFinished(eventBus);
30763
+ client.sse.bindAnnotation(resourceId, annotationId, request, { auth: token, eventBus });
30764
+ await donePromise;
30765
+ if (!options.quiet) printSuccess(`Bound: ${rawAnnotationId} \u2192 ${targetResourceId}`);
30153
30766
  return {
30154
- connect: async () => {
30767
+ command: "bind",
30768
+ environment: rawBusUrl,
30769
+ timestamp: /* @__PURE__ */ new Date(),
30770
+ duration: Date.now() - startTime,
30771
+ summary: { succeeded: 1, failed: 0, total: 1, warnings: 0 },
30772
+ executionContext: { user: process.env.USER || "unknown", workingDirectory: process.cwd(), dryRun: options.dryRun },
30773
+ results: [{ entity: rawAnnotationId, platform: "posix", success: true, metadata: { targetResourceId }, duration: Date.now() - startTime }]
30774
+ };
30775
+ }
30776
+ var bindCmd = new CommandBuilder().name("bind").description("Resolve a linking annotation to a target resource. Adds a SpecificResource body item (purpose: linking) via PUT /resources/{resourceId}/annotations/{annotationId}/body.").requiresEnvironment(true).requiresServices(true).examples(
30777
+ "semiont bind <resourceId> <annotationId> <targetResourceId>",
30778
+ `TARGET=$(semiont match <resourceId> <annotationId> --quiet | jq -r '.[0]["@id"]') && semiont bind <resourceId> <annotationId> "$TARGET"`
30779
+ ).args({
30780
+ ...withApiArgs({}, {}),
30781
+ restAs: "args",
30782
+ aliases: {}
30783
+ }).schema(BindOptionsSchema).handler(runBind).build();
30784
+
30785
+ // src/core/commands/beckon.ts
30786
+ init_zod();
30787
+ init_command_definition();
30788
+ init_base_options_schema();
30789
+ var BeckonOptionsSchema = ApiOptionsSchema.extend({
30790
+ participantArr: external_exports.array(external_exports.string()).min(1, "participantId is required").max(1, "Only one participant per beckon"),
30791
+ resource: external_exports.string({ required_error: "--resource <resourceId> is required" }),
30792
+ annotation: external_exports.string().optional(),
30793
+ message: external_exports.string().max(500).optional()
30794
+ });
30795
+ async function runBeckon(options) {
30796
+ const startTime = Date.now();
30797
+ const rawBusUrl = resolveBusUrl(options.bus);
30798
+ const { client, token } = loadCachedClient(rawBusUrl);
30799
+ const [participantId] = options.participantArr;
30800
+ const result = await client.beckonAttention(
30801
+ participantId,
30802
+ {
30803
+ resourceId: options.resource,
30804
+ ...options.annotation ? { annotationId: options.annotation } : {},
30805
+ ...options.message ? { message: options.message } : {}
30155
30806
  },
30156
- disconnect: async () => {
30807
+ { auth: token }
30808
+ );
30809
+ if (!options.quiet) {
30810
+ const target = options.annotation ? `${options.resource} (${options.annotation})` : options.resource;
30811
+ process.stderr.write(`Beckoned ${participantId} \u2192 ${target}
30812
+ `);
30813
+ }
30814
+ process.stdout.write(JSON.stringify(result) + "\n");
30815
+ return {
30816
+ command: "beckon",
30817
+ environment: rawBusUrl,
30818
+ timestamp: /* @__PURE__ */ new Date(),
30819
+ duration: Date.now() - startTime,
30820
+ summary: { succeeded: 1, failed: 0, total: 1, warnings: 0 },
30821
+ executionContext: { user: process.env.USER || "unknown", workingDirectory: process.cwd(), dryRun: options.dryRun },
30822
+ results: [{ entity: participantId, platform: "posix", success: true, duration: Date.now() - startTime }]
30823
+ };
30824
+ }
30825
+ var beckonCmd = new CommandBuilder().name("beckon").description(
30826
+ "Direct a participant's attention to a resource or annotation. Produces no persistent state \u2014 attention signal only. The participant may be a human username or an agent identifier."
30827
+ ).requiresEnvironment(true).requiresServices(true).examples(
30828
+ "semiont beckon alice --resource <resourceId>",
30829
+ "semiont beckon alice --resource <resourceId> --annotation <annotationId>",
30830
+ 'semiont beckon alice --resource <resourceId> --annotation <annotationId> --message "Needs manual review"',
30831
+ "semiont beckon my-review-agent --resource <resourceId> --annotation <annotationId>"
30832
+ ).args({
30833
+ ...withApiArgs({
30834
+ "--resource": {
30835
+ type: "string",
30836
+ description: "Resource to direct attention at (required)",
30837
+ required: true
30157
30838
  },
30158
- isConnected: () => false,
30159
- createResource: noop2,
30160
- getResource: noop2,
30161
- updateResource: noop2,
30162
- deleteResource: noop2,
30163
- listResources: noop2,
30164
- searchResources: noop2,
30165
- createAnnotation: noop2,
30166
- getAnnotation: noop2,
30167
- updateAnnotation: noop2,
30168
- deleteAnnotation: noop2,
30169
- listAnnotations: noop2,
30170
- getHighlights: noop2,
30171
- resolveReference: noop2,
30172
- getReferences: noop2,
30173
- getEntityReferences: noop2,
30174
- getResourceAnnotations: noop2,
30175
- getResourceReferencedBy: noop2,
30176
- getResourceConnections: noop2,
30177
- findPath: noop2,
30178
- getEntityTypeStats: noop2,
30179
- getStats: noop2,
30180
- batchCreateResources: noop2,
30181
- createAnnotations: noop2,
30182
- resolveReferences: noop2,
30183
- detectAnnotations: noop2,
30184
- getEntityTypes: noop2,
30185
- addEntityType: noop2,
30186
- addEntityTypes: noop2,
30187
- generateId: () => "noop",
30188
- clearDatabase: noop2
30839
+ "--annotation": {
30840
+ type: "string",
30841
+ description: "Specific annotation within the resource (optional)"
30842
+ },
30843
+ "--message": {
30844
+ type: "string",
30845
+ description: "Human-readable context for the participant (max 500 chars)"
30846
+ }
30847
+ }, {}),
30848
+ restAs: "participantArr",
30849
+ aliases: {}
30850
+ }).schema(BeckonOptionsSchema).handler(runBeckon).build();
30851
+
30852
+ // src/core/commands/browse.ts
30853
+ init_zod();
30854
+ init_command_definition();
30855
+ init_base_options_schema();
30856
+ import { resourceId as toResourceId6, annotationId as toAnnotationId5 } from "@semiont/core";
30857
+ var BrowseOptionsSchema = ApiOptionsSchema.extend({
30858
+ args: external_exports.array(external_exports.string()).min(1, "Subcommand required: resources | resource | annotation | references | events | history | entity-types"),
30859
+ // browse resources options
30860
+ search: external_exports.string().optional(),
30861
+ entityType: external_exports.array(external_exports.string()).default([]),
30862
+ limit: external_exports.coerce.number().int().min(1).max(200).default(50),
30863
+ // browse resource options
30864
+ annotations: external_exports.boolean().default(false),
30865
+ references: external_exports.boolean().default(false)
30866
+ }).superRefine((val, ctx) => {
30867
+ const sub = val.args[0];
30868
+ const valid = ["resources", "resource", "annotation", "references", "events", "history", "entity-types"];
30869
+ if (!valid.includes(sub)) {
30870
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, message: `Unknown subcommand '${sub}'. Valid: ${valid.join(", ")}` });
30871
+ }
30872
+ if (sub === "resource" && val.args.length < 2) {
30873
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, message: "Usage: semiont browse resource <resourceId>" });
30874
+ }
30875
+ if (sub === "annotation" && val.args.length < 3) {
30876
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, message: "Usage: semiont browse annotation <resourceId> <annotationId>" });
30877
+ }
30878
+ if (sub === "references" && val.args.length < 2) {
30879
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, message: "Usage: semiont browse references <resourceId>" });
30880
+ }
30881
+ if (sub === "events" && val.args.length < 2) {
30882
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, message: "Usage: semiont browse events <resourceId>" });
30883
+ }
30884
+ if (sub === "history" && val.args.length < 3) {
30885
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, message: "Usage: semiont browse history <resourceId> <annotationId>" });
30886
+ }
30887
+ });
30888
+ async function runBrowse(options) {
30889
+ const startTime = Date.now();
30890
+ const rawBusUrl = resolveBusUrl(options.bus);
30891
+ const { client, token } = loadCachedClient(rawBusUrl);
30892
+ const [subcommand, rawResourceId, rawAnnotationId] = options.args;
30893
+ let result;
30894
+ let label;
30895
+ if (subcommand === "resources") {
30896
+ const data = await client.browseResources(
30897
+ options.limit,
30898
+ void 0,
30899
+ options.search,
30900
+ { auth: token }
30901
+ );
30902
+ result = data;
30903
+ const items = Array.isArray(data) ? data : data?.resources ?? [];
30904
+ label = `${items.length} resource${items.length !== 1 ? "s" : ""} found`;
30905
+ } else if (subcommand === "resource") {
30906
+ const id = toResourceId6(rawResourceId);
30907
+ const resourceData = await client.browseResource(id, { auth: token });
30908
+ if (options.annotations || options.references) {
30909
+ const annotationsData = await client.browseAnnotations(id, void 0, { auth: token });
30910
+ const annotations = annotationsData?.annotations ?? annotationsData ?? [];
30911
+ let referencedBy = [];
30912
+ if (options.references) {
30913
+ const refData = await client.browseReferences(id, { auth: token });
30914
+ referencedBy = refData.referencedBy ?? [];
30915
+ }
30916
+ result = {
30917
+ ...resourceData,
30918
+ ...options.annotations ? { annotations } : {},
30919
+ ...options.references ? { referencedBy } : {}
30920
+ };
30921
+ } else {
30922
+ result = resourceData;
30923
+ }
30924
+ label = `${rawResourceId}: ${resourceData?.name ?? rawResourceId}`;
30925
+ } else if (subcommand === "annotation") {
30926
+ const resourceId = toResourceId6(rawResourceId);
30927
+ const annotationId = toAnnotationId5(rawAnnotationId);
30928
+ result = await client.browseAnnotation(resourceId, annotationId, { auth: token });
30929
+ label = `${rawAnnotationId}: annotation on ${rawResourceId}`;
30930
+ } else if (subcommand === "references") {
30931
+ const id = toResourceId6(rawResourceId);
30932
+ const data = await client.browseReferences(id, { auth: token });
30933
+ result = data.referencedBy ?? [];
30934
+ const count = Array.isArray(result) ? result.length : 0;
30935
+ label = `${count} resource${count !== 1 ? "s" : ""} reference ${rawResourceId}`;
30936
+ } else if (subcommand === "events") {
30937
+ const id = toResourceId6(rawResourceId);
30938
+ const data = await client.getResourceEvents(id, { auth: token });
30939
+ result = data.events ?? data;
30940
+ const items = Array.isArray(result) ? result : [];
30941
+ label = `${items.length} event${items.length !== 1 ? "s" : ""} for ${rawResourceId}`;
30942
+ } else if (subcommand === "history") {
30943
+ const resourceId = toResourceId6(rawResourceId);
30944
+ const annotationId = toAnnotationId5(rawAnnotationId);
30945
+ result = await client.getAnnotationHistory(resourceId, annotationId, { auth: token });
30946
+ label = `history for annotation ${rawAnnotationId} on ${rawResourceId}`;
30947
+ } else {
30948
+ result = await client.listEntityTypes({ auth: token });
30949
+ const items = Array.isArray(result) ? result : result?.tags ?? [];
30950
+ label = `${items.length} entity type${items.length !== 1 ? "s" : ""}`;
30951
+ }
30952
+ if (!options.quiet) process.stderr.write(label + "\n");
30953
+ process.stdout.write(JSON.stringify(result, null, 2) + "\n");
30954
+ return {
30955
+ command: "browse",
30956
+ environment: rawBusUrl,
30957
+ timestamp: /* @__PURE__ */ new Date(),
30958
+ duration: Date.now() - startTime,
30959
+ summary: { succeeded: 1, failed: 0, total: 1, warnings: 0 },
30960
+ executionContext: { user: process.env.USER || "unknown", workingDirectory: process.cwd(), dryRun: options.dryRun },
30961
+ results: [{ entity: rawResourceId ?? subcommand, platform: "posix", success: true, duration: Date.now() - startTime }]
30189
30962
  };
30190
30963
  }
30191
- var UnarchiveOptionsSchema = BaseOptionsSchema.extend({
30192
- files: external_exports.array(external_exports.string()).min(1, "At least one file path is required")
30964
+ var browseCmd = new CommandBuilder().name("browse").description(
30965
+ "Human-readable traversal of the knowledge base. Subcommands: resources (list), resource <id> (inspect), annotation <resourceId> <annotationId> (inspect), references <id> (who links here), events <resourceId> (historical event log), history <resourceId> <annotationId> (annotation audit trail), entity-types (available entity type catalogue). Outputs JSON to stdout; progress label to stderr. For LLM pipeline consumption use `semiont gather` instead."
30966
+ ).requiresEnvironment(true).requiresServices(true).examples(
30967
+ "semiont browse resources",
30968
+ 'semiont browse resources --search "Paris"',
30969
+ "semiont browse resources --entity-type Location --limit 20",
30970
+ "semiont browse resource <resourceId>",
30971
+ "semiont browse resource <resourceId> --annotations",
30972
+ "semiont browse resource <resourceId> --references",
30973
+ "semiont browse annotation <resourceId> <annotationId>",
30974
+ "semiont browse references <resourceId>",
30975
+ "semiont browse events <resourceId>",
30976
+ "semiont browse history <resourceId> <annotationId>",
30977
+ "semiont browse entity-types",
30978
+ `semiont browse resources --search "Paris" | jq '.[]["@id"]'`,
30979
+ "semiont browse references <resourceId> | jq '.[].name'",
30980
+ "semiont browse entity-types | jq '.[].tag'"
30981
+ ).args({
30982
+ ...withApiArgs({
30983
+ "--search": {
30984
+ type: "string",
30985
+ description: "Filter resources by name or content (browse resources only)"
30986
+ },
30987
+ "--entity-type": {
30988
+ type: "array",
30989
+ description: "Filter resources by entity type (browse resources only; repeatable)"
30990
+ },
30991
+ "--limit": {
30992
+ type: "string",
30993
+ description: "Maximum number of results (browse resources only; default: 50)"
30994
+ },
30995
+ "--annotations": {
30996
+ type: "boolean",
30997
+ description: "Include annotation list in resource output (browse resource only)",
30998
+ default: false
30999
+ },
31000
+ "--references": {
31001
+ type: "boolean",
31002
+ description: "Include resolved reference targets (browse resource only)",
31003
+ default: false
31004
+ }
31005
+ }, {}),
31006
+ restAs: "args",
31007
+ aliases: {}
31008
+ }).schema(BrowseOptionsSchema).handler(runBrowse).build();
31009
+
31010
+ // src/core/commands/listen.ts
31011
+ init_zod();
31012
+ init_command_definition();
31013
+ init_base_options_schema();
31014
+ import { resourceId as toResourceId7, EventBus as EventBus9 } from "@semiont/core";
31015
+ var ListenOptionsSchema = ApiOptionsSchema.extend({
31016
+ args: external_exports.array(external_exports.string()).default([])
31017
+ }).superRefine((val, ctx) => {
31018
+ const sub = val.args[0];
31019
+ if (sub !== void 0 && sub !== "resource") {
31020
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, message: `Unknown subcommand '${sub}'. Usage: semiont listen [resource <resourceId>]` });
31021
+ }
31022
+ if (sub === "resource" && val.args.length < 2) {
31023
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, message: "Usage: semiont listen resource <resourceId>" });
31024
+ }
30193
31025
  });
30194
- async function runUnarchive(options) {
31026
+ async function runListen(options) {
30195
31027
  const startTime = Date.now();
30196
- const projectRoot = findProjectRoot();
30197
- const environment = options.environment;
30198
- const logger = createCliLogger8(options.verbose ?? false);
30199
- const userId = `did:web:localhost:users:${process.env.USER ?? "cli"}`;
30200
- const project = new SemiontProject24(projectRoot);
30201
- const eventBus = new EventBus6();
30202
- const eventStore = createEventStore8(project, eventBus, logger);
30203
- const kb = createKnowledgeBase6(eventStore, project, createNoopGraphDatabase6(), logger);
30204
- const stower = new Stower6(kb, eventBus, logger.child({ component: "stower" }));
30205
- await stower.initialize();
30206
- let succeeded = 0;
30207
- let failed = 0;
30208
- const results = [];
31028
+ const rawBusUrl = resolveBusUrl(options.bus);
31029
+ const { client, token } = loadCachedClient(rawBusUrl);
31030
+ const [subcommand, rawResourceId] = options.args;
31031
+ const isResourceScoped = subcommand === "resource";
31032
+ const eventBus = new EventBus9();
31033
+ let eventCount = 0;
31034
+ eventBus.get("make-meaning:event").subscribe((event) => {
31035
+ eventCount++;
31036
+ process.stdout.write(JSON.stringify(event) + "\n");
31037
+ });
31038
+ const label = isResourceScoped ? `Listening for events on resource ${rawResourceId}` : "Listening for global events";
31039
+ if (!options.quiet) process.stderr.write(label + " (Ctrl-C to stop)\n");
31040
+ const stream = isResourceScoped ? client.sse.resourceEvents(toResourceId7(rawResourceId), { auth: token, eventBus }) : client.sse.globalEvents({ auth: token, eventBus });
31041
+ await new Promise((resolve10) => {
31042
+ const cleanup = () => {
31043
+ stream.close();
31044
+ resolve10();
31045
+ };
31046
+ process.once("SIGINT", cleanup);
31047
+ process.once("SIGTERM", cleanup);
31048
+ });
31049
+ return {
31050
+ command: "listen",
31051
+ environment: rawBusUrl,
31052
+ timestamp: /* @__PURE__ */ new Date(),
31053
+ duration: Date.now() - startTime,
31054
+ summary: { succeeded: eventCount, failed: 0, total: eventCount, warnings: 0 },
31055
+ executionContext: { user: process.env.USER || "unknown", workingDirectory: process.cwd(), dryRun: options.dryRun },
31056
+ results: [{ entity: rawResourceId ?? "global", platform: "posix", success: true, duration: Date.now() - startTime }]
31057
+ };
31058
+ }
31059
+ var listenCmd = new CommandBuilder().name("listen").description(
31060
+ "Open a persistent SSE connection and stream domain events as NDJSON to stdout. Without a subcommand, streams global system events. With `resource <resourceId>`, streams events scoped to that resource. Runs until Ctrl-C or the server closes the connection."
31061
+ ).requiresEnvironment(true).requiresServices(true).examples(
31062
+ "semiont listen",
31063
+ "semiont listen resource <resourceId>",
31064
+ "semiont listen resource <resourceId> | jq .type",
31065
+ "semiont listen | grep entitytype"
31066
+ ).args({
31067
+ ...withApiArgs({}, {}),
31068
+ restAs: "args",
31069
+ aliases: {}
31070
+ }).schema(ListenOptionsSchema).handler(runListen).build();
31071
+
31072
+ // src/core/commands/login.ts
31073
+ init_zod();
31074
+ init_dist();
31075
+ init_command_definition();
31076
+ init_base_options_schema();
31077
+ import * as fs52 from "fs";
31078
+ import * as os6 from "os";
31079
+ import * as path45 from "path";
31080
+ import * as readline4 from "readline";
31081
+ var LoginOptionsSchema = BaseOptionsSchema.extend({
31082
+ bus: external_exports.string().optional(),
31083
+ user: external_exports.string().optional(),
31084
+ password: external_exports.string().optional(),
31085
+ refresh: external_exports.boolean().optional().default(false)
31086
+ });
31087
+ function readLoginConfig() {
31088
+ const configPath = path45.join(os6.homedir(), ".semiontconfig");
30209
31089
  try {
30210
- for (const filePath of options.files) {
30211
- const absPath = path45.isAbsolute(filePath) ? filePath : path45.resolve(projectRoot, filePath);
30212
- const relPath = path45.relative(projectRoot, absPath).replace(/\\/g, "/");
30213
- const storageUri = `file://${relPath}`;
30214
- const fileStart = Date.now();
30215
- try {
30216
- await nodeFs2.access(absPath);
30217
- } catch {
30218
- console.error(
30219
- `Error: File not found at storageUri '${storageUri}'
30220
- To restore from git: git checkout -- ${relPath}
30221
- Then re-run: semiont unarchive ${filePath}`
30222
- );
30223
- results.push({ entity: filePath, platform: "posix", success: false, metadata: { error: "File not found on disk" }, duration: 0 });
30224
- failed++;
30225
- continue;
30226
- }
30227
- let resourceId;
30228
- try {
30229
- resourceId = await resolveStorageUri3(kb.projectionsDir, storageUri);
30230
- } catch (e) {
30231
- if (e instanceof ResourceNotFoundError3) {
30232
- if (!options.quiet) printWarning(`Not tracked by semiont: ${filePath}`);
30233
- results.push({ entity: filePath, platform: "posix", success: false, metadata: { error: "Not tracked" }, duration: 0 });
30234
- failed++;
30235
- continue;
30236
- }
30237
- throw e;
30238
- }
30239
- eventBus.scope(resourceId).get("mark:unarchive").next({
30240
- userId,
30241
- resourceId,
30242
- storageUri
30243
- });
30244
- await new Promise((resolve12) => setTimeout(resolve12, 200));
30245
- if (!options.quiet) printSuccess(`Unarchived: ${filePath}`);
30246
- results.push({ entity: filePath, platform: "posix", success: true, metadata: { resourceId, storageUri }, duration: Date.now() - fileStart });
30247
- succeeded++;
31090
+ const content = fs52.existsSync(configPath) ? fs52.readFileSync(configPath, "utf-8") : null;
31091
+ if (!content) return {};
31092
+ return parse(content);
31093
+ } catch {
31094
+ return {};
31095
+ }
31096
+ }
31097
+ function getDefaultEnvironment(config) {
31098
+ return config.defaults?.environment ?? null;
31099
+ }
31100
+ function promptPassword(prompt3) {
31101
+ return new Promise((resolve10, reject) => {
31102
+ if (!process.stdin.isTTY) {
31103
+ reject(new Error("No password provided and stdin is not a TTY. Use --password or $SEMIONT_PASSWORD."));
31104
+ return;
30248
31105
  }
30249
- } finally {
30250
- await stower.stop();
30251
- eventBus.destroy();
31106
+ const rl = readline4.createInterface({ input: process.stdin, output: process.stderr });
31107
+ process.stderr.write(prompt3);
31108
+ if (process.stdin.setRawMode) {
31109
+ process.stdin.setRawMode(true);
31110
+ }
31111
+ let value = "";
31112
+ process.stdin.on("data", function onData(chunk) {
31113
+ const char = chunk.toString();
31114
+ if (char === "\r" || char === "\n") {
31115
+ process.stdin.removeListener("data", onData);
31116
+ if (process.stdin.setRawMode) {
31117
+ process.stdin.setRawMode(false);
31118
+ }
31119
+ process.stderr.write("\n");
31120
+ rl.close();
31121
+ resolve10(value);
31122
+ } else if (char === "") {
31123
+ process.stderr.write("\n");
31124
+ rl.close();
31125
+ reject(new Error("Interrupted"));
31126
+ } else if (char === "\x7F" || char === "\b") {
31127
+ value = value.slice(0, -1);
31128
+ } else {
31129
+ value += char;
31130
+ }
31131
+ });
31132
+ process.stdin.resume();
31133
+ });
31134
+ }
31135
+ async function runLogin(options) {
31136
+ const startTime = Date.now();
31137
+ const config = readLoginConfig();
31138
+ const defaultEnv = getDefaultEnvironment(config);
31139
+ const envSection = defaultEnv ? config.environments?.[defaultEnv] : void 0;
31140
+ const rawBusUrl = resolveBusUrl(
31141
+ options.bus ?? envSection?.backend?.publicURL
31142
+ );
31143
+ const emailStr = options.user ?? process.env.SEMIONT_USER ?? envSection?.auth?.email ?? null;
31144
+ if (!emailStr) {
31145
+ throw new Error(
31146
+ 'No auth email configured. Use --user, set $SEMIONT_USER, or add:\n [environments.<env>.auth]\n email = "you@example.com"\nto ~/.semiontconfig'
31147
+ );
31148
+ }
31149
+ let passwordStr = options.password ?? process.env.SEMIONT_PASSWORD ?? envSection?.auth?.password ?? "";
31150
+ if (!passwordStr) {
31151
+ passwordStr = await promptPassword(`Password for ${emailStr}: `);
31152
+ }
31153
+ if (!passwordStr) {
31154
+ throw new Error("Password is required.");
31155
+ }
31156
+ await acquireToken(rawBusUrl, emailStr, passwordStr);
31157
+ const slug = busSlug(rawBusUrl);
31158
+ const xdgState = process.env.XDG_STATE_HOME ?? path45.join(os6.homedir(), ".local", "state");
31159
+ const cachePath = path45.join(xdgState, "semiont", "auth", `${slug}.json`);
31160
+ if (!options.quiet) {
31161
+ process.stderr.write(`Logged in to ${rawBusUrl} as ${emailStr}
31162
+ `);
31163
+ process.stderr.write(`Token cached at ${cachePath} (expires in 24h)
31164
+ `);
30252
31165
  }
30253
- const duration = Date.now() - startTime;
30254
31166
  return {
30255
- command: "unarchive",
30256
- environment,
31167
+ command: "login",
31168
+ environment: "n/a",
30257
31169
  timestamp: /* @__PURE__ */ new Date(),
30258
- duration,
30259
- summary: { succeeded, failed, total: options.files.length, warnings: 0 },
30260
- executionContext: { user: process.env.USER || "unknown", workingDirectory: process.cwd(), dryRun: options.dryRun },
30261
- results
31170
+ duration: Date.now() - startTime,
31171
+ summary: { succeeded: 1, failed: 0, total: 1, warnings: 0 },
31172
+ executionContext: { user: emailStr, workingDirectory: process.cwd(), dryRun: false },
31173
+ results: [{ entity: rawBusUrl, platform: "posix", success: true, duration: Date.now() - startTime }]
30262
31174
  };
30263
31175
  }
30264
- var unarchiveCmd = new CommandBuilder().name("unarchive").description("Restore an archived semiont resource (file must already exist on disk)").requiresEnvironment(true).requiresServices(false).examples(
30265
- "semiont unarchive docs/old.md"
31176
+ var loginCmd = new CommandBuilder().name("login").description(
31177
+ "Authenticate against a Semiont backend and cache the token. Run this once before using browse, gather, mark, bind, match, listen, yield, or beckon. Credentials resolved from: --bus/--user/--password flags \u2192 $SEMIONT_BUS/$SEMIONT_USER/$SEMIONT_PASSWORD \u2192 ~/.semiontconfig \u2192 interactive prompt."
31178
+ ).requiresEnvironment(false).requiresServices(false).examples(
31179
+ "semiont login --bus http://localhost:4000 --user alice@example.com",
31180
+ "semiont login --bus https://api.acme.com",
31181
+ "semiont login --refresh --bus https://api.acme.com"
30266
31182
  ).args({
30267
- args: {},
30268
- aliases: {},
30269
- restAs: "files"
30270
- }).schema(UnarchiveOptionsSchema).handler(runUnarchive).build();
31183
+ args: {
31184
+ ...BASE_ARGS,
31185
+ "--bus": {
31186
+ type: "string",
31187
+ description: "Backend URL (e.g. http://localhost:4000). Fallback: $SEMIONT_BUS \u2192 ~/.semiontconfig"
31188
+ },
31189
+ "--user": {
31190
+ type: "string",
31191
+ description: "Login email. Fallback: $SEMIONT_USER \u2192 ~/.semiontconfig [environments.<env>.auth] email"
31192
+ },
31193
+ "--password": {
31194
+ type: "string",
31195
+ description: "Login password. Fallback: $SEMIONT_PASSWORD \u2192 ~/.semiontconfig \u2192 interactive prompt"
31196
+ },
31197
+ "--refresh": {
31198
+ type: "boolean",
31199
+ description: "Re-authenticate using cached email without requiring a new password (if stored)",
31200
+ default: false
31201
+ }
31202
+ },
31203
+ aliases: { ...BASE_ALIASES, "-b": "--bus", "-u": "--user" }
31204
+ }).schema(LoginOptionsSchema).handler(runLogin).build();
30271
31205
 
30272
31206
  // src/core/command-discovery.ts
30273
31207
  var commandCache = /* @__PURE__ */ new Map();
@@ -30290,8 +31224,14 @@ var COMMANDS = {
30290
31224
  "clean": cleanCommand,
30291
31225
  "mv": mvCmd,
30292
31226
  "yield": yieldCmd,
30293
- "archive": archiveCmd,
30294
- "unarchive": unarchiveCmd
31227
+ "mark": markCmd,
31228
+ "gather": gatherCmd,
31229
+ "match": matchCmd,
31230
+ "bind": bindCmd,
31231
+ "beckon": beckonCmd,
31232
+ "browse": browseCmd,
31233
+ "listen": listenCmd,
31234
+ "login": loginCmd
30295
31235
  };
30296
31236
  async function loadCommand(name) {
30297
31237
  if (commandCache.has(name)) {