@hivefloor/cli 0.1.4 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/LICENSE +6 -20
  2. package/README.md +31 -9
  3. package/dist/chunk-2ERPDCOT.js +38 -0
  4. package/dist/chunk-4G362W6G.js +19 -0
  5. package/dist/chunk-5OJUJCE3.js +817 -0
  6. package/dist/chunk-5XXYQQG6.js +274 -0
  7. package/dist/chunk-AGIYVFDQ.js +10984 -0
  8. package/dist/{chunk-2BSA7LFD.js → chunk-BLLPDPTL.js} +7 -3
  9. package/dist/{chunk-R5KDI4WI.js → chunk-FPJNGKT5.js} +9 -3
  10. package/dist/chunk-HW3KRNCO.js +201 -0
  11. package/dist/{chunk-ZC2DAKB5.js → chunk-HWBUESB4.js} +1500 -316
  12. package/dist/{chunk-DNG5CRT3.js → chunk-K2IRTZH5.js} +8 -7
  13. package/dist/chunk-KQMPCV57.js +122 -0
  14. package/dist/{chunk-UJ4BQFWV.js → chunk-L6EFW2SJ.js} +53 -31
  15. package/dist/{chunk-T7TG6WA4.js → chunk-LX5A25O6.js} +4 -2
  16. package/dist/{chunk-W7DROKC7.js → chunk-MYJCU5JL.js} +89 -13
  17. package/dist/chunk-NMUH5NXN.js +52 -0
  18. package/dist/chunk-NRJONTFT.js +67 -0
  19. package/dist/chunk-QBBKGORP.js +327 -0
  20. package/dist/chunk-QGULSOQ2.js +142 -0
  21. package/dist/{chunk-PDXYOREI.js → chunk-QLMLB7RB.js} +110 -31
  22. package/dist/{chunk-TKMIV7BG.js → chunk-QPAFN47B.js} +3 -1
  23. package/dist/chunk-SBOEAOHD.js +48 -0
  24. package/dist/{chunk-SD65CIIY.js → chunk-TIR4CV3P.js} +117 -33
  25. package/dist/{chunk-QHYZBHXO.js → chunk-X2KH6AR4.js} +195 -251
  26. package/dist/chunk-XAXKZ572.js +106 -0
  27. package/dist/{chunk-VNCQFFQO.js → chunk-XPGL7VYE.js} +114 -1
  28. package/dist/cli-BFOJWJNG.js +279 -0
  29. package/dist/connect-ZJ4JXBAJ.js +27 -0
  30. package/dist/control-6GHTZQJV.js +25 -0
  31. package/dist/{disconnect-MKRHK4CX.js → disconnect-3T25NTKX.js} +55 -34
  32. package/dist/hook-TPSHBCWU.js +575 -0
  33. package/dist/index.js +9 -6
  34. package/dist/{link-HXBMMSG3.js → link-EAS5F5PC.js} +34 -18
  35. package/dist/{machine-connect-BYHZRRRB.js → machine-connect-KEI4BRWF.js} +30 -24
  36. package/dist/mcp-LVIYR3EN.js +1882 -0
  37. package/dist/orch-KVRL2YA2.js +137 -0
  38. package/dist/{run-336BSU72.js → run-JL2OZWK3.js} +1933 -29
  39. package/dist/{status-KBBSAADD.js → status-QXOOJGGN.js} +29 -14
  40. package/dist/token-BFWWQIDA.js +44 -0
  41. package/dist/voice-QXHFXRWG.js +264 -0
  42. package/dist/{where-KR7VWSEC.js → where-CMUORQIO.js} +20 -8
  43. package/package.json +6 -7
  44. package/dist/chunk-2IMJECYD.js +0 -71
  45. package/dist/chunk-7KF7IQJN.js +0 -30
  46. package/dist/chunk-GT3HFFT4.js +0 -132
  47. package/dist/chunk-JCLWCMEM.js +0 -8
  48. package/dist/chunk-K3NQKI34.js +0 -10
  49. package/dist/chunk-O2TC3WSS.js +0 -303
  50. package/dist/chunk-PY74LT2W.js +0 -41
  51. package/dist/cli-P3DYE5IR.js +0 -103
  52. package/dist/connect-ACNM5DQG.js +0 -23
  53. package/dist/hook-KR2HGVAR.js +0 -301
  54. package/dist/mcp-N2TMD4GR.js +0 -121
  55. package/dist/token-JDRLEV5D.js +0 -32
@@ -1,7 +1,9 @@
1
1
  #!/usr/bin/env node
2
+ import { createRequire as __hfCreateRequire } from 'node:module';
3
+ const require = __hfCreateRequire(import.meta.url);
2
4
  import {
3
5
  __export
4
- } from "./chunk-K3NQKI34.js";
6
+ } from "./chunk-2ERPDCOT.js";
5
7
 
6
8
  // ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/classic/external.js
7
9
  var external_exports = {};
@@ -838,14 +840,14 @@ function promiseAllObject(promisesObj) {
838
840
  }
839
841
  function randomString(length = 10) {
840
842
  const chars = "abcdefghijklmnopqrstuvwxyz";
841
- let str = "";
843
+ let str2 = "";
842
844
  for (let i = 0; i < length; i++) {
843
- str += chars[Math.floor(Math.random() * chars.length)];
845
+ str2 += chars[Math.floor(Math.random() * chars.length)];
844
846
  }
845
- return str;
847
+ return str2;
846
848
  }
847
- function esc(str) {
848
- return JSON.stringify(str);
849
+ function esc(str2) {
850
+ return JSON.stringify(str2);
849
851
  }
850
852
  function slugify(input2) {
851
853
  return input2.toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/[\s_-]+/g, "-").replace(/^-+|-+$/g, "");
@@ -959,8 +961,8 @@ var primitiveTypes = /* @__PURE__ */ new Set([
959
961
  "symbol",
960
962
  "undefined"
961
963
  ]);
962
- function escapeRegex(str) {
963
- return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
964
+ function escapeRegex(str2) {
965
+ return str2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
964
966
  }
965
967
  function clone(inst, def, params) {
966
968
  const cl = new inst._zod.constr(def ?? inst._zod.def);
@@ -1226,13 +1228,13 @@ function getSizableOrigin(input2) {
1226
1228
  return "unknown";
1227
1229
  }
1228
1230
  var highSurrogate = /[\uD800-\uDBFF]/;
1229
- function codePointLength(str) {
1230
- const units = str.length;
1231
- if (!highSurrogate.test(str))
1231
+ function codePointLength(str2) {
1232
+ const units = str2.length;
1233
+ if (!highSurrogate.test(str2))
1232
1234
  return units;
1233
1235
  let count = units;
1234
1236
  for (let i = 0; i < units - 1; i++) {
1235
- if ((str.charCodeAt(i) & 64512) === 55296 && (str.charCodeAt(i + 1) & 64512) === 56320) {
1237
+ if ((str2.charCodeAt(i) & 64512) === 55296 && (str2.charCodeAt(i + 1) & 64512) === 56320) {
1236
1238
  count--;
1237
1239
  i++;
1238
1240
  }
@@ -3621,15 +3623,15 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
3621
3623
  const syms = normalized.symbolKeys;
3622
3624
  const doc = new Doc(["payload", "ctx"], { shape, inst, memo: memo2, syms });
3623
3625
  const parseStr = (k) => `shape[${k}]._zod.run({ value: input[${k}], issues: [] }, ctx)`;
3624
- const prefixStr = (id, k) => `
3625
- let ${id}_ab = false;
3626
- for (let i = 0; i < ${id}.issues.length; i++) {
3627
- const iss = ${id}.issues[i];
3626
+ const prefixStr = (id2, k) => `
3627
+ let ${id2}_ab = false;
3628
+ for (let i = 0; i < ${id2}.issues.length; i++) {
3629
+ const iss = ${id2}.issues[i];
3628
3630
  iss.path = iss.path ? [${k}, ...iss.path] : [${k}];
3629
3631
  payload.issues.push(iss);
3630
- if (iss.continue !== true) ${id}_ab = true;
3632
+ if (iss.continue !== true) ${id2}_ab = true;
3631
3633
  }
3632
- if (${id}_ab && ctx && ctx.abortEarly) {
3634
+ if (${id2}_ab && ctx && ctx.abortEarly) {
3633
3635
  payload.value = newResult;
3634
3636
  return payload;
3635
3637
  }`;
@@ -3643,34 +3645,34 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
3643
3645
  for (const key2 of normalized.allKeys) {
3644
3646
  if (key2 === "__proto__")
3645
3647
  continue;
3646
- const id = ids[key2];
3648
+ const id2 = ids[key2];
3647
3649
  const k = typeof key2 === "symbol" ? `syms[${syms.indexOf(key2)}]` : esc(key2);
3648
3650
  const isPresent = `${k} in input`;
3649
3651
  const schema = shape[key2];
3650
3652
  const optin = schema?._zod?.optin;
3651
3653
  const isOptionalIn = optin !== void 0;
3652
3654
  const isOptionalOut = schema?._zod?.optout === "optional";
3653
- doc.write(`const ${id} = ${parseStr(k)};`);
3655
+ doc.write(`const ${id2} = ${parseStr(k)};`);
3654
3656
  if (isOptionalIn && isOptionalOut) {
3655
- const assign = optin === "optional" ? `${id}_present` : `${id}.value !== undefined || ${id}_present`;
3657
+ const assign = optin === "optional" ? `${id2}_present` : `${id2}.value !== undefined || ${id2}_present`;
3656
3658
  doc.write(`
3657
- const ${id}_present = ${isPresent};
3658
- if (!${id}.issues.length || ${id}_present) {
3659
- if (${id}.issues.length) {${prefixStr(id, k)}
3659
+ const ${id2}_present = ${isPresent};
3660
+ if (!${id2}.issues.length || ${id2}_present) {
3661
+ if (${id2}.issues.length) {${prefixStr(id2, k)}
3660
3662
  }
3661
3663
 
3662
3664
  if (${assign}) {
3663
- newResult[${k}] = ${id}.value;
3665
+ newResult[${k}] = ${id2}.value;
3664
3666
  }
3665
3667
  }
3666
3668
 
3667
3669
  `);
3668
3670
  } else if (!isOptionalIn) {
3669
3671
  doc.write(`
3670
- const ${id}_present = ${isPresent};
3671
- if (${id}.issues.length) {${prefixStr(id, k)}
3672
+ const ${id2}_present = ${isPresent};
3673
+ if (${id2}.issues.length) {${prefixStr(id2, k)}
3672
3674
  }
3673
- if (!${id}_present && !${id}.issues.length) {
3675
+ if (!${id2}_present && !${id2}.issues.length) {
3674
3676
  payload.issues.push({
3675
3677
  code: "invalid_type",
3676
3678
  expected: "nonoptional",
@@ -3683,22 +3685,22 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
3683
3685
  }
3684
3686
  }
3685
3687
 
3686
- if (${id}_present) {
3687
- newResult[${k}] = ${id}.value;
3688
+ if (${id2}_present) {
3689
+ newResult[${k}] = ${id2}.value;
3688
3690
  }
3689
3691
 
3690
3692
  `);
3691
3693
  } else {
3692
3694
  doc.write(`
3693
- if (${id}.issues.length) {${prefixStr(id, k)}
3695
+ if (${id2}.issues.length) {${prefixStr(id2, k)}
3694
3696
  }
3695
3697
  `);
3696
3698
  if (optin === "defaulted") {
3697
- doc.write(`newResult[${k}] = ${id}.value;`);
3699
+ doc.write(`newResult[${k}] = ${id2}.value;`);
3698
3700
  } else {
3699
3701
  doc.write(`
3700
- if (${id}.value !== undefined || ${isPresent}) {
3701
- newResult[${k}] = ${id}.value;
3702
+ if (${id2}.value !== undefined || ${isPresent}) {
3703
+ newResult[${k}] = ${id2}.value;
3702
3704
  }
3703
3705
  `);
3704
3706
  }
@@ -15726,26 +15728,26 @@ function extractDefs(ctx, schema) {
15726
15728
  return;
15727
15729
  const idToSchema = /* @__PURE__ */ new Map();
15728
15730
  for (const entry of ctx.seen.entries()) {
15729
- const id = ctx.metadataRegistry.get(entry[0])?.id;
15730
- if (id) {
15731
- const existing = idToSchema.get(id);
15731
+ const id2 = ctx.metadataRegistry.get(entry[0])?.id;
15732
+ if (id2) {
15733
+ const existing = idToSchema.get(id2);
15732
15734
  if (existing && existing !== entry[0]) {
15733
- throw new Error(`Duplicate schema id "${id}" detected during JSON Schema conversion. Two different schemas cannot share the same id when converted together.`);
15735
+ throw new Error(`Duplicate schema id "${id2}" detected during JSON Schema conversion. Two different schemas cannot share the same id when converted together.`);
15734
15736
  }
15735
- idToSchema.set(id, entry[0]);
15737
+ idToSchema.set(id2, entry[0]);
15736
15738
  }
15737
15739
  }
15738
15740
  const makeURI = (entry) => {
15739
15741
  const defsSegment = ctx.target === "draft-2020-12" ? "$defs" : "definitions";
15740
15742
  if (ctx.external) {
15741
15743
  const externalId = ctx.external.registry.get(entry[0])?.id;
15742
- const uriGenerator = ctx.external.uri ?? ((id2) => id2);
15744
+ const uriGenerator = ctx.external.uri ?? ((id3) => id3);
15743
15745
  if (externalId) {
15744
15746
  return { ref: uriGenerator(externalId) };
15745
15747
  }
15746
- const id = entry[1].defId ?? entry[1].schema.id ?? `schema${ctx.counter++}`;
15747
- entry[1].defId = id;
15748
- return { defId: id, ref: `${uriGenerator("__shared")}#/${defsSegment}/${encodeJSONPointerSegment(id)}` };
15748
+ const id2 = entry[1].defId ?? entry[1].schema.id ?? `schema${ctx.counter++}`;
15749
+ entry[1].defId = id2;
15750
+ return { defId: id2, ref: `${uriGenerator("__shared")}#/${defsSegment}/${encodeJSONPointerSegment(id2)}` };
15749
15751
  }
15750
15752
  const uriPrefix = `#`;
15751
15753
  const defUriPrefix = `${uriPrefix}/${defsSegment}/`;
@@ -15793,8 +15795,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15793
15795
  continue;
15794
15796
  }
15795
15797
  }
15796
- const id = ctx.metadataRegistry.get(entry[0])?.id;
15797
- if (id) {
15798
+ const id2 = ctx.metadataRegistry.get(entry[0])?.id;
15799
+ if (id2) {
15798
15800
  extractToDef(entry);
15799
15801
  continue;
15800
15802
  }
@@ -16027,10 +16029,10 @@ function finalize(ctx, schema) {
16027
16029
  } else {
16028
16030
  }
16029
16031
  if (ctx.external?.uri) {
16030
- const id = ctx.external.registry.get(schema)?.id;
16031
- if (!id)
16032
+ const id2 = ctx.external.registry.get(schema)?.id;
16033
+ if (!id2)
16032
16034
  throw new Error("Schema is missing an `id` property");
16033
- result.$id = ctx.external.uri(id);
16035
+ result.$id = ctx.external.uri(id2);
16034
16036
  }
16035
16037
  assignProps(result, root.defId ? root.schema : root.def ?? root.schema);
16036
16038
  const rootMetaId = ctx.metadataRegistry.get(schema)?.id;
@@ -16636,7 +16638,7 @@ function stringifyKeyNames(bySchema, json2, visited) {
16636
16638
  const values = json2.enum ?? (json2.const !== void 0 ? [json2.const] : void 0);
16637
16639
  if (!numericType && !values?.some((v) => typeof v === "number"))
16638
16640
  return json2;
16639
- const { minimum, maximum, exclusiveMinimum, exclusiveMaximum, multipleOf, format, id, ...rest } = json2;
16641
+ const { minimum, maximum, exclusiveMinimum, exclusiveMaximum, multipleOf, format, id: id2, ...rest } = json2;
16640
16642
  if (rest.enum)
16641
16643
  rest.enum = rest.enum.map((v) => typeof v === "number" ? String(v) : v);
16642
16644
  else if (typeof rest.const === "number")
@@ -19785,10 +19787,16 @@ var hookEventSchema = external_exports.object({
19785
19787
  status_line: external_exports.string().max(140).optional(),
19786
19788
  model: external_exports.string().min(1).max(200).optional(),
19787
19789
  repo: repoInfoSchema.optional(),
19790
+ /** The session's working directory as the hook reported it (a later Resume starts the tool there). */
19791
+ cwd: external_exports.string().min(1).max(500).optional(),
19788
19792
  /** ISO time on the client; display only (the server clock decides). */
19789
19793
  client_at: external_exports.iso.datetime({ offset: true }),
19790
19794
  /** The CLI sets it on the event it posts for a hook whose output the tool reads as context (Claude's UserPromptSubmit and the like): only then does the answer carry the session's pending nudges. */
19791
- deliver: external_exports.boolean().optional()
19795
+ deliver: external_exports.boolean().optional(),
19796
+ /** The agent's last message after a turn (docs/CONTROL.md 4.3), sent on `stop` when control allows replies; redacted by the CLI and again by the server. */
19797
+ reply: external_exports.string().max(2048).optional(),
19798
+ /** On `stop`: the turn ended by asking a person something (its last line is a question). The session waits on you, not idle. */
19799
+ asks: external_exports.boolean().optional()
19792
19800
  });
19793
19801
  var hookBatchSchema = external_exports.object({ events: external_exports.array(hookEventSchema).min(1).max(HOOK_BATCH_MAX) });
19794
19802
  var hookBatchResponseSchema = external_exports.object({
@@ -19801,6 +19809,10 @@ var hookBatchResponseSchema = external_exports.object({
19801
19809
  // ../shared/src/machine-health.ts
19802
19810
  var MACHINE_HEALTH_RULES = ["offline_with_claims", "disk_full", "disk_high", "memory_high", "cli_behind"];
19803
19811
 
19812
+ // ../shared/src/plan.ts
19813
+ var PLANS = ["free", "team", "company"];
19814
+ var planSchema = external_exports.enum(PLANS);
19815
+
19804
19816
  // ../shared/src/api/projects.ts
19805
19817
  var idSchema = external_exports.string().regex(/^[0-9]{1,15}$/, "must be a numeric id");
19806
19818
  var projectNameSchema = external_exports.string().trim().min(1).max(100);
@@ -19826,11 +19838,15 @@ var isoSchema = external_exports.string();
19826
19838
  var roleEnum = external_exports.enum(["owner", "admin", "member", "viewer"]);
19827
19839
  var okResponse = external_exports.object({ ok: external_exports.literal(true) }).strict();
19828
19840
  var listOf = (item) => external_exports.object({ items: external_exports.array(item), next_cursor: external_exports.string().nullable(), total: external_exports.number().int().nonnegative().optional() }).strict();
19829
- var publicConfigResponse = external_exports.object({ dev_login: external_exports.boolean(), github: external_exports.boolean(), github_app: external_exports.boolean(), push: external_exports.object({ enabled: external_exports.boolean(), public_key: external_exports.string().nullable() }).optional() }).strict();
19841
+ var publicConfigResponse = external_exports.object({ feedback: external_exports.boolean().optional(), dev_login: external_exports.boolean(), github: external_exports.boolean(), github_app: external_exports.boolean(), demo: external_exports.boolean().optional(), hive: external_exports.boolean().optional(), push: external_exports.object({ enabled: external_exports.boolean(), public_key: external_exports.string().nullable() }).optional() }).strict();
19830
19842
  var publicUserSchema = external_exports.object({ id: idSchema, login: external_exports.string(), name: external_exports.string().nullable(), avatar_url: external_exports.string().nullable() }).strict();
19831
19843
  var projectBriefSchema = external_exports.object({ id: idSchema, key: external_exports.string(), name: external_exports.string(), role: roleEnum }).strict();
19832
- var meProjectSchema = projectBriefSchema.extend({ personal: external_exports.boolean() }).strict();
19833
- var meResponse = external_exports.object({ user: publicUserSchema, projects: external_exports.array(meProjectSchema) }).strict();
19844
+ var meProjectSchema = projectBriefSchema.extend({
19845
+ personal: external_exports.boolean(),
19846
+ /** The person owns it. A key is unique per owner, so `/p/:key` prefers an owned project over a shared one with the same key. */
19847
+ owned: external_exports.boolean().optional()
19848
+ }).strict();
19849
+ var meResponse = external_exports.object({ user: publicUserSchema, projects: external_exports.array(meProjectSchema), plan: planSchema.optional() }).strict();
19834
19850
  var projectSettingsViewSchema = external_exports.looseObject({ answer_blocked: external_exports.boolean().optional() });
19835
19851
  var projectTransferSchema = external_exports.object({ to_user_id: idSchema, requested_at: isoSchema.nullable() }).strict();
19836
19852
  var projectSchema = external_exports.object({
@@ -19907,144 +19923,12 @@ var githubInstallationSchema = external_exports.object({
19907
19923
  }).strict();
19908
19924
  var githubInstallationsResponse = external_exports.object({ installations: external_exports.array(githubInstallationSchema) }).strict();
19909
19925
 
19910
- // ../shared/src/api/machines.ts
19911
- var MACHINE_HEARTBEAT_SECONDS = 30;
19912
- var MACHINE_MIN_INTERVAL_SECONDS = 15;
19913
- var MACHINE_MAX_AGENTS = 40;
19914
- var PROFILE_KEY_RE = /^[a-z0-9][a-z0-9._-]{0,39}$/;
19915
- var profileKeySchema = external_exports.string().regex(PROFILE_KEY_RE, "bad profile key");
19916
- var pct = external_exports.number().min(0).max(100);
19917
- var machineStatsSchema = external_exports.object({
19918
- cpu_pct: pct.optional(),
19919
- mem_pct: pct.optional(),
19920
- disk_pct: pct.optional(),
19921
- mem_total_mb: external_exports.number().int().min(0).max(1e8).optional(),
19922
- load1: external_exports.number().min(0).max(1e5).optional(),
19923
- gpu: external_exports.array(external_exports.object({ name: external_exports.string().max(100), util_pct: pct.optional(), mem_pct: pct.optional() }).strict()).max(8).optional(),
19924
- usage: external_exports.record(external_exports.string().max(80), external_exports.number().finite()).refine((o) => Object.keys(o).length <= 64, "at most 64 usage values").optional()
19925
- }).strict();
19926
- var machineHeartbeatBody = external_exports.object({
19927
- os: external_exports.string().trim().min(1).max(100).optional(),
19928
- cli_version: external_exports.string().trim().min(1).max(50).optional(),
19929
- stats: machineStatsSchema.optional()
19930
- }).strict();
19931
- var projectBriefSchema2 = external_exports.object({ id: external_exports.string(), key: external_exports.string(), name: external_exports.string() });
19932
- var machineHeartbeatResponseSchema = external_exports.object({
19933
- ok: external_exports.literal(true),
19934
- machine: external_exports.object({ id: external_exports.string(), name: external_exports.string() }),
19935
- projects: external_exports.array(projectBriefSchema2),
19936
- /** Seconds the service should wait before the next heartbeat. */
19937
- interval: external_exports.number().int().positive()
19938
- });
19939
- var discoveryProfileSchema = external_exports.object({
19940
- tool: toolSchema,
19941
- key: profileKeySchema,
19942
- /** For example `Claude Max (work)`; no email, no token. */
19943
- label: external_exports.string().trim().max(100).optional(),
19944
- model: external_exports.string().trim().max(200).optional(),
19945
- running: external_exports.number().int().min(0).max(500)
19946
- }).strict();
19947
- var discoveryBody = external_exports.object({ profiles: external_exports.array(discoveryProfileSchema).max(MACHINE_MAX_AGENTS) }).strict();
19948
- var SESSION_ACCOUNT_RE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,59}$/;
19949
- var machineHookEventSchema = hookEventSchema.extend({
19950
- profile: profileKeySchema.optional(),
19951
- account: external_exports.string().regex(SESSION_ACCOUNT_RE).optional().catch(void 0)
19952
- });
19953
- var machineHookBatchSchema = external_exports.object({ events: external_exports.array(machineHookEventSchema).min(1).max(HOOK_BATCH_MAX) });
19954
- var approveMachineBody = external_exports.object({
19955
- name: external_exports.string().trim().min(1).max(100),
19956
- project_ids: external_exports.array(idSchema).max(200).optional(),
19957
- default_project_id: idSchema.nullable().optional(),
19958
- /** Replace one of the person's own machines (listed in the preview's `reusable_machines`): its token is rotated, nothing else changes. */
19959
- machine_id: idSchema.optional()
19960
- }).strict();
19961
- var machineTokenSuccessSchema = external_exports.object({
19962
- token: external_exports.string().min(1),
19963
- machine: external_exports.object({ id: external_exports.string(), name: external_exports.string() }),
19964
- projects: external_exports.array(projectBriefSchema2)
19965
- });
19966
- var machineAgentSchema = external_exports.object({
19967
- id: external_exports.string(),
19968
- name: external_exports.string(),
19969
- tool: toolSchema,
19970
- profile: external_exports.string().nullable(),
19971
- account_label: external_exports.string().nullable(),
19972
- model: external_exports.string().nullable(),
19973
- /** Agent processes alive at the last discovery. */
19974
- running: external_exports.number().int().nonnegative(),
19975
- live_sessions: external_exports.number().int().nonnegative(),
19976
- last_seen_at: external_exports.string().nullable()
19977
- });
19978
- var machineHealthViewSchema = external_exports.object({
19979
- level: external_exports.enum(["warn", "critical"]),
19980
- findings: external_exports.array(external_exports.object({ rule: external_exports.enum(MACHINE_HEALTH_RULES), level: external_exports.enum(["warn", "critical"]), text: external_exports.string() }))
19981
- });
19982
- var machineSchema = external_exports.object({
19983
- id: external_exports.string(),
19984
- name: external_exports.string(),
19985
- os: external_exports.string().nullable(),
19986
- cli_version: external_exports.string().nullable(),
19987
- online: external_exports.boolean(),
19988
- last_seen_at: external_exports.string().nullable(),
19989
- created_at: external_exports.string(),
19990
- default_project_id: external_exports.string().nullable(),
19991
- projects: external_exports.array(external_exports.object({ id: external_exports.string(), key: external_exports.string(), name: external_exports.string(), default: external_exports.boolean() })),
19992
- stats: machineStatsSchema.nullable(),
19993
- agents: external_exports.array(machineAgentSchema),
19994
- /** The rules that fire for this machine; null or absent when healthy (older servers omit it). */
19995
- health: machineHealthViewSchema.nullable().optional()
19996
- });
19997
- var patchMachineBody = external_exports.object({
19998
- name: external_exports.string().trim().min(1).max(100).optional(),
19999
- project_ids: external_exports.array(idSchema).max(200).optional(),
20000
- default_project_id: idSchema.nullable().optional()
20001
- }).strict().refine((b) => b.name !== void 0 || b.project_ids !== void 0 || b.default_project_id !== void 0, "nothing to update");
20002
- var machineResponse = external_exports.object({ machine: machineSchema }).strict();
20003
- var CLI_MAJOR = 0;
20004
-
20005
- // ../shared/src/package-name.ts
20006
- var CLI_PACKAGE_NAME = "@hivefloor/cli";
20007
- var CLI_BIN_NAME = "hivefloor";
20008
- var CLI_INSTALL_COMMAND = `npm i -g ${CLI_PACKAGE_NAME}`;
20009
- function cliNpxCommand(args = "", opts = {}) {
20010
- const spec = opts.pinMajor ? `${CLI_PACKAGE_NAME}@${CLI_MAJOR}` : CLI_PACKAGE_NAME;
20011
- return `npx ${spec}${args ? ` ${args}` : ""}`;
20012
- }
20013
- var CLI_CONNECT_COMMAND = cliNpxCommand("connect");
20014
-
20015
- // ../shared/src/usage.ts
20016
- var MIN_SPAN_MS = 5 * 6e4;
20017
- var MAX_ETA_MS = 31 * 24 * 36e5;
20018
- var USAGE_COUNTERS = ["tokens_in", "tokens_out", "cost_usd"];
20019
- function isUsageCounter(value) {
20020
- return USAGE_COUNTERS.includes(value);
20021
- }
20022
- function parseUsageKey(key2) {
20023
- const parts = key2.split(":");
20024
- if (parts.length < 3) return null;
20025
- const tool = parts[0];
20026
- const profile = parts[1];
20027
- if (!TOOLS.includes(tool)) return null;
20028
- if (!PROFILE_KEY_RE.test(profile)) return null;
20029
- if (parts.length === 3) {
20030
- const counter2 = parts[2];
20031
- return isUsageCounter(counter2) ? { tool, profile, session: null, counter: counter2 } : null;
20032
- }
20033
- if (parts[2] !== "s" || parts.length < 5) return null;
20034
- const session = parts.slice(3, -1).join(":");
20035
- const counter = parts[parts.length - 1];
20036
- if (!session || !isUsageCounter(counter)) return null;
20037
- return { tool, profile, session, counter };
20038
- }
20039
-
20040
- // ../shared/src/usage-alerts.ts
20041
- var WASTE_WITHIN_MS = 3 * 36e5;
20042
-
20043
19926
  // ../shared/src/task-status.ts
20044
19927
  var TASK_STATUSES = ["backlog", "ready", "claimed", "in_review", "done", "blocked", "parked"];
20045
19928
  var taskStatusSchema = external_exports.enum(TASK_STATUSES);
20046
19929
 
20047
19930
  // ../shared/src/health.ts
19931
+ var STALLED_AFTER_SEC = 120;
20048
19932
  var PARKED_AFTER_SEC = 20 * 60;
20049
19933
  var WAITING_LONG_AFTER_SEC = 15 * 60;
20050
19934
  var MIN_STALL_THRESHOLD_SEC = 60;
@@ -20150,9 +20034,21 @@ var taskCardSchema = external_exports.object({
20150
20034
  /** Tasks this one waits on (stage 2). It is claimable only when every one of them is done. */
20151
20035
  blocked_by: external_exports.array(blockerRefSchema).default([]),
20152
20036
  /** A claimed task whose holder's machine is offline: the work may be stuck there. Absent or false otherwise. */
20153
- at_risk: external_exports.boolean().optional()
20037
+ at_risk: external_exports.boolean().optional(),
20038
+ /** A fleet lane's task (mirrored from the owner's fleet, docs/FLEET.md). Absent for the project's own and vq-mirror tasks. */
20039
+ fleet: external_exports.boolean().optional(),
20040
+ /**
20041
+ * The holder agent. Present on `GET /projects/:pid/tasks` (null when nobody holds the task).
20042
+ * A completed task keeps its holder. Absent on floor, detail and share cards.
20043
+ */
20044
+ agent: external_exports.object({ id: entityIdSchema, name: external_exports.string() }).nullable().optional(),
20045
+ /**
20046
+ * Sum of stored `task_usage.cost_usd` for this task. Null when no usage row exists.
20047
+ * Present on the task list only; absent on floor, detail and share cards.
20048
+ */
20049
+ cost_usd: external_exports.number().nonnegative().nullable().optional()
20154
20050
  });
20155
- var TASK_TIMELINE_KINDS = ["created", "claimed", "note", "blocked", "released", "lease_expired", "pr", "in_review", "done", "answered", "archived", "unarchived", "unblocked", "steered", "nudged"];
20051
+ var TASK_TIMELINE_KINDS = ["created", "claimed", "note", "blocked", "released", "lease_expired", "pr", "in_review", "done", "answered", "archived", "unarchived", "unblocked", "steered", "nudged", "edited", "moved"];
20156
20052
  var taskTimelineKindSchema = external_exports.enum(TASK_TIMELINE_KINDS);
20157
20053
  var taskTimelineEventSchema = external_exports.object({
20158
20054
  id: entityIdSchema,
@@ -20164,6 +20060,8 @@ var taskTimelineEventSchema = external_exports.object({
20164
20060
  avatar_url: external_exports.string().nullable()
20165
20061
  }),
20166
20062
  text: external_exports.string().nullable(),
20063
+ /** `answered` lines only: where the person sent the task with the answer (`ready`, `backlog`, `done` or `blocked`). */
20064
+ then: external_exports.enum(["ready", "backlog", "done", "blocked"]).optional(),
20167
20065
  created_at: isoTimeSchema
20168
20066
  });
20169
20067
  var taskListSchema = external_exports.object({
@@ -20209,8 +20107,11 @@ var taskStatusLineQuerySchema = external_exports.object({
20209
20107
  cursor: replayCursor.optional()
20210
20108
  }).strict();
20211
20109
  var taskResultSchema = external_exports.object({ task: taskCardSchema });
20212
- var answerBodySchema = external_exports.object({ text: external_exports.string().trim().min(1).max(500) });
20213
- var NOTIFICATION_KINDS = ["task_done", "task_blocked", "agent_waiting", "invite_received", "member_added", "repo_link_requested", "agent_question", "feedback", "usage_waste", "usage_high", "wait_escalated", "machine_unhealthy"];
20110
+ var answerBodySchema = external_exports.object({
20111
+ text: external_exports.string().trim().min(1).max(500),
20112
+ waiting_since: isoTimeSchema.optional()
20113
+ });
20114
+ var NOTIFICATION_KINDS = ["task_done", "task_blocked", "agent_waiting", "invite_received", "member_added", "repo_link_requested", "agent_question", "feedback", "usage_waste", "usage_high", "wait_escalated", "machine_unhealthy", "team_visibility"];
20214
20115
  var notificationKindSchema = external_exports.enum(NOTIFICATION_KINDS);
20215
20116
  var notificationViewSchema = external_exports.object({
20216
20117
  id: entityIdSchema,
@@ -20259,6 +20160,25 @@ var createTaskBody = external_exports.object({
20259
20160
  source_id: external_exports.string().max(1e3).optional(),
20260
20161
  session: sessionRef.optional()
20261
20162
  }).strict();
20163
+ var boardCreateTaskBody = external_exports.object({
20164
+ title: external_exports.string().min(1).max(1500),
20165
+ body: external_exports.string().max(7e4).optional(),
20166
+ status: external_exports.enum(["backlog", "ready"]).optional(),
20167
+ priority: external_exports.number().int().min(0).max(3).optional(),
20168
+ labels: labels.optional(),
20169
+ for_tools: forTools.optional(),
20170
+ blocked_by: external_exports.array(external_exports.number().int().positive()).max(MAX_BLOCKERS).optional()
20171
+ }).strict();
20172
+ var BOARD_EDIT_STATUSES = ["backlog", "ready", "blocked", "parked", "done", "cancelled"];
20173
+ var boardUpdateTaskBody = external_exports.object({
20174
+ title: external_exports.string().min(1).max(1500).optional(),
20175
+ body: external_exports.string().max(7e4).optional(),
20176
+ labels: labels.optional(),
20177
+ for_tools: forTools.optional(),
20178
+ status: external_exports.enum(BOARD_EDIT_STATUSES).optional(),
20179
+ release_claim: external_exports.boolean().optional(),
20180
+ expected_updated_at: external_exports.string().max(40).optional()
20181
+ }).strict().refine((b) => b.title !== void 0 || b.body !== void 0 || b.labels !== void 0 || b.for_tools !== void 0 || b.status !== void 0, "nothing to change");
20262
20182
  var claimNextBody = external_exports.object({
20263
20183
  project: projectRefSchema.optional(),
20264
20184
  labels: labels.optional(),
@@ -20303,6 +20223,248 @@ var releaseBody = external_exports.object({
20303
20223
  }).strict();
20304
20224
  var completeBody = external_exports.object({ claim_token: claimToken.optional(), summary: external_exports.string().min(1).max(5e3), pr_url: external_exports.string().max(1e3).optional(), session: sessionRef.optional() }).strict();
20305
20225
 
20226
+ // ../shared/src/api/control.ts
20227
+ var CONTROL_KINDS = ["message", "approve", "deny", "stop", "resume", "peek"];
20228
+ var CONTROL_STATUSES = ["queued", "delivered", "done", "failed", "expired"];
20229
+ var CONTROL_VIAS = ["tmux", "hook", "adapter"];
20230
+ var CONTROL_TEXT_MAX = 4e3;
20231
+ var CONTROL_REASON_MAX = 300;
20232
+ var CONTROL_REPLY_MAX = 2048;
20233
+ var PEEK_LINES_MAX = 60;
20234
+ var PEEK_OUTPUT_MAX = 4096;
20235
+ function stripControlChars(input2) {
20236
+ return input2.normalize("NFC").replace(/\r\n?/g, "\n").replace(/[\u0000-\u0008\u000B-\u001F\u007F-\u009F]/g, "");
20237
+ }
20238
+ function cleanControlText(input2, max = CONTROL_TEXT_MAX) {
20239
+ const text2 = stripControlChars(input2);
20240
+ if (text2.length === 0) return null;
20241
+ if (text2.length > max && Array.from(text2).length > max) return null;
20242
+ return text2;
20243
+ }
20244
+ var cleaned = (max) => external_exports.string().transform((s, ctx) => {
20245
+ const t = cleanControlText(s, max);
20246
+ if (t === null) {
20247
+ ctx.addIssue({ code: "custom", message: `must be 1 to ${max} characters after cleaning` });
20248
+ return external_exports.NEVER;
20249
+ }
20250
+ return t;
20251
+ });
20252
+ var promptIdSchema = external_exports.string().regex(/^[A-Za-z0-9_-]{8,128}$/, "a prompt id");
20253
+ var idempotencyKeySchema = external_exports.string().min(8).max(64);
20254
+ var createCommandBody = external_exports.discriminatedUnion("kind", [
20255
+ external_exports.strictObject({ kind: external_exports.literal("message"), args: external_exports.strictObject({ text: cleaned(CONTROL_TEXT_MAX) }), idempotency_key: idempotencyKeySchema }),
20256
+ external_exports.strictObject({ kind: external_exports.literal("approve"), args: external_exports.strictObject({ prompt_id: promptIdSchema }), idempotency_key: idempotencyKeySchema }),
20257
+ external_exports.strictObject({
20258
+ kind: external_exports.literal("deny"),
20259
+ args: external_exports.strictObject({
20260
+ prompt_id: promptIdSchema,
20261
+ // a reason that cleans to nothing is no reason
20262
+ reason: external_exports.string().max(CONTROL_REASON_MAX).transform((s) => cleanControlText(s, CONTROL_REASON_MAX) ?? void 0).optional()
20263
+ }),
20264
+ idempotency_key: idempotencyKeySchema
20265
+ }),
20266
+ external_exports.strictObject({ kind: external_exports.literal("stop"), args: external_exports.strictObject({ mode: external_exports.enum(["interrupt", "end"]) }), idempotency_key: idempotencyKeySchema }),
20267
+ // No args: the machine runs a fixed command for the tool it recorded, in the folder it recorded.
20268
+ // `revive: true` brings back a session that Finished (o160 4): same command, same checks; the new instruction goes later as a message.
20269
+ external_exports.strictObject({ kind: external_exports.literal("resume"), args: external_exports.strictObject({}), revive: external_exports.boolean().optional(), idempotency_key: idempotencyKeySchema }),
20270
+ // Read-only: the last lines of the session's screen (or transcript), redacted on the machine.
20271
+ external_exports.strictObject({ kind: external_exports.literal("peek"), args: external_exports.strictObject({ lines: external_exports.number().int().min(1).max(PEEK_LINES_MAX) }), idempotency_key: idempotencyKeySchema })
20272
+ ]);
20273
+ var requestedBySchema = external_exports.object({ user_id: external_exports.string(), name: external_exports.string() });
20274
+ var commandEventSchema = external_exports.object({
20275
+ id: external_exports.string(),
20276
+ session_id: external_exports.string(),
20277
+ kind: external_exports.enum(CONTROL_KINDS),
20278
+ status: external_exports.enum(CONTROL_STATUSES),
20279
+ code: external_exports.string().optional(),
20280
+ via: external_exports.enum(CONTROL_VIAS).optional(),
20281
+ requested_by: requestedBySchema,
20282
+ created_at: isoTimeSchema,
20283
+ updated_at: isoTimeSchema
20284
+ });
20285
+ var commandSchema = commandEventSchema.extend({
20286
+ detail: external_exports.string().optional(),
20287
+ args: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
20288
+ output: external_exports.string().optional()
20289
+ });
20290
+ var commandResponse = external_exports.object({ command: commandSchema });
20291
+ var commandListResponse = external_exports.object({ commands: external_exports.array(commandSchema) });
20292
+ var commandUpdateEvent = external_exports.object({ command: commandEventSchema });
20293
+ var sessionPromptEvent = external_exports.union([
20294
+ external_exports.object({ session_id: external_exports.string(), prompt_id: external_exports.string(), tool_name: external_exports.string(), summary: external_exports.string(), expires_at: isoTimeSchema }),
20295
+ external_exports.object({ session_id: external_exports.string(), prompt_id: external_exports.string(), closed: external_exports.literal(true) })
20296
+ ]);
20297
+ var sessionReplyEvent = external_exports.object({ session_id: external_exports.string(), text: external_exports.string(), at: isoTimeSchema });
20298
+ var machineCommandSchema = external_exports.object({
20299
+ id: external_exports.string(),
20300
+ kind: external_exports.enum(CONTROL_KINDS),
20301
+ args: external_exports.record(external_exports.string(), external_exports.unknown()),
20302
+ session: external_exports.object({ external_id: external_exports.string(), tool: external_exports.string(), profile: external_exports.string().nullable() }),
20303
+ requested_by: requestedBySchema.extend({ is_machine_owner: external_exports.boolean() }),
20304
+ expires_in_ms: external_exports.number().int()
20305
+ });
20306
+ var machineCommandsResponse = external_exports.object({ commands: external_exports.array(machineCommandSchema) });
20307
+ var commandResultBody = external_exports.object({
20308
+ status: external_exports.enum(["done", "failed"]),
20309
+ code: external_exports.string().regex(/^[a-z][a-z0-9_]{0,39}$/).optional(),
20310
+ detail: external_exports.string().max(200).optional(),
20311
+ via: external_exports.enum(CONTROL_VIAS).optional(),
20312
+ /** A done `peek` only: the screen lines, redacted on the machine. The server ignores it for any other kind. */
20313
+ output: external_exports.string().max(PEEK_OUTPUT_MAX).optional()
20314
+ }).strict();
20315
+ var machinePromptBody = external_exports.object({
20316
+ session_id: external_exports.string().min(1).max(200),
20317
+ prompt_id: promptIdSchema,
20318
+ tool_name: external_exports.string().min(1).max(100),
20319
+ summary: external_exports.string().max(600)
20320
+ }).strict();
20321
+ var machinePromptResponse = external_exports.object({ hold: external_exports.boolean() });
20322
+ var controlVerbsSchema = external_exports.object({ message: external_exports.boolean().optional(), approve: external_exports.boolean().optional(), deny: external_exports.boolean().optional(), stop: external_exports.boolean().optional(), resume: external_exports.boolean().optional(), peek: external_exports.boolean().optional() }).strict();
20323
+
20324
+ // ../shared/src/api/machines.ts
20325
+ var MACHINE_HEARTBEAT_SECONDS = 30;
20326
+ var MACHINE_MIN_INTERVAL_SECONDS = 15;
20327
+ var MACHINE_MAX_AGENTS = 40;
20328
+ var PROFILE_KEY_RE = /^[a-z0-9][a-z0-9._-]{0,39}$/;
20329
+ var profileKeySchema = external_exports.string().regex(PROFILE_KEY_RE, "bad profile key");
20330
+ var pct = external_exports.number().min(0).max(100);
20331
+ var machineStatsSchema = external_exports.object({
20332
+ cpu_pct: pct.optional(),
20333
+ mem_pct: pct.optional(),
20334
+ disk_pct: pct.optional(),
20335
+ mem_total_mb: external_exports.number().int().min(0).max(1e8).optional(),
20336
+ load1: external_exports.number().min(0).max(1e5).optional(),
20337
+ gpu: external_exports.array(external_exports.object({ name: external_exports.string().max(100), util_pct: pct.optional(), mem_pct: pct.optional() }).strict()).max(8).optional(),
20338
+ usage: external_exports.record(external_exports.string().max(80), external_exports.number().finite()).refine((o) => Object.keys(o).length <= 64, "at most 64 usage values").optional()
20339
+ }).strict();
20340
+ var ENDED_SESSION_ID_RE = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,199}$/;
20341
+ var ENDED_SESSIONS_MAX = 100;
20342
+ var machineHeartbeatBody = external_exports.object({
20343
+ os: external_exports.string().trim().min(1).max(100).optional(),
20344
+ cli_version: external_exports.string().trim().min(1).max(50).optional(),
20345
+ stats: machineStatsSchema.optional(),
20346
+ /** The control verbs switched on in `control.json` (docs/CONTROL.md 3.1). Absent: the server keeps what it has. */
20347
+ control: controlVerbsSchema.optional(),
20348
+ /** Tool session ids (the hook's `session_id`) whose agent process is gone on this machine: the server ends them. */
20349
+ ended_sessions: external_exports.array(external_exports.string().min(1).max(200).regex(ENDED_SESSION_ID_RE, "bad session id")).max(ENDED_SESSIONS_MAX).optional()
20350
+ }).strict();
20351
+ var projectBriefSchema2 = external_exports.object({ id: external_exports.string(), key: external_exports.string(), name: external_exports.string() });
20352
+ var machineHeartbeatResponseSchema = external_exports.object({
20353
+ ok: external_exports.literal(true),
20354
+ machine: external_exports.object({ id: external_exports.string(), name: external_exports.string() }),
20355
+ projects: external_exports.array(projectBriefSchema2),
20356
+ /** Seconds the service should wait before the next heartbeat. */
20357
+ interval: external_exports.number().int().positive()
20358
+ });
20359
+ var discoveryProfileSchema = external_exports.object({
20360
+ tool: toolSchema,
20361
+ key: profileKeySchema,
20362
+ /** For example `Claude Max (work)`; no email, no token. */
20363
+ label: external_exports.string().trim().max(100).optional(),
20364
+ model: external_exports.string().trim().max(200).optional(),
20365
+ running: external_exports.number().int().min(0).max(500)
20366
+ }).strict();
20367
+ var discoveryBody = external_exports.object({ profiles: external_exports.array(discoveryProfileSchema).max(MACHINE_MAX_AGENTS) }).strict();
20368
+ var SESSION_ACCOUNT_RE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,59}$/;
20369
+ var machineHookEventSchema = hookEventSchema.extend({
20370
+ profile: profileKeySchema.optional(),
20371
+ account: external_exports.string().regex(SESSION_ACCOUNT_RE).optional().catch(void 0)
20372
+ });
20373
+ var machineHookBatchSchema = external_exports.object({ events: external_exports.array(machineHookEventSchema).min(1).max(HOOK_BATCH_MAX) });
20374
+ var approveMachineBody = external_exports.object({
20375
+ name: external_exports.string().trim().min(1).max(100),
20376
+ project_ids: external_exports.array(idSchema).max(200).optional(),
20377
+ default_project_id: idSchema.nullable().optional(),
20378
+ /** Replace one of the person's own machines (listed in the preview's `reusable_machines`): its token is rotated, nothing else changes. */
20379
+ machine_id: idSchema.optional()
20380
+ }).strict();
20381
+ var machineTokenSuccessSchema = external_exports.object({
20382
+ token: external_exports.string().min(1),
20383
+ machine: external_exports.object({ id: external_exports.string(), name: external_exports.string() }),
20384
+ projects: external_exports.array(projectBriefSchema2)
20385
+ });
20386
+ var machineAgentSchema = external_exports.object({
20387
+ id: external_exports.string(),
20388
+ name: external_exports.string(),
20389
+ tool: toolSchema,
20390
+ profile: external_exports.string().nullable(),
20391
+ account_label: external_exports.string().nullable(),
20392
+ model: external_exports.string().nullable(),
20393
+ /** Agent processes alive at the last discovery. */
20394
+ running: external_exports.number().int().nonnegative(),
20395
+ /** Main sessions running now (live, waiting, idle, stalled): not offline or ended. */
20396
+ live_sessions: external_exports.number().int().nonnegative(),
20397
+ /** Of those, waiting on you (`needsYou`). Older servers omit it. */
20398
+ waiting_sessions: external_exports.number().int().nonnegative().optional(),
20399
+ /** Of those, idle (done, asked nothing). Older servers omit it. */
20400
+ idle_sessions: external_exports.number().int().nonnegative().optional(),
20401
+ last_seen_at: external_exports.string().nullable()
20402
+ });
20403
+ var machineHealthViewSchema = external_exports.object({
20404
+ level: external_exports.enum(["warn", "critical"]),
20405
+ findings: external_exports.array(external_exports.object({ rule: external_exports.enum(MACHINE_HEALTH_RULES), level: external_exports.enum(["warn", "critical"]), text: external_exports.string() }))
20406
+ });
20407
+ var machineSchema = external_exports.object({
20408
+ id: external_exports.string(),
20409
+ name: external_exports.string(),
20410
+ os: external_exports.string().nullable(),
20411
+ cli_version: external_exports.string().nullable(),
20412
+ online: external_exports.boolean(),
20413
+ last_seen_at: external_exports.string().nullable(),
20414
+ created_at: external_exports.string(),
20415
+ default_project_id: external_exports.string().nullable(),
20416
+ projects: external_exports.array(external_exports.object({ id: external_exports.string(), key: external_exports.string(), name: external_exports.string(), default: external_exports.boolean() })),
20417
+ stats: machineStatsSchema.nullable(),
20418
+ agents: external_exports.array(machineAgentSchema),
20419
+ /** The rules that fire for this machine; null or absent when healthy (older servers omit it). */
20420
+ health: machineHealthViewSchema.nullable().optional()
20421
+ });
20422
+ var patchMachineBody = external_exports.object({
20423
+ name: external_exports.string().trim().min(1).max(100).optional(),
20424
+ project_ids: external_exports.array(idSchema).max(200).optional(),
20425
+ default_project_id: idSchema.nullable().optional()
20426
+ }).strict().refine((b) => b.name !== void 0 || b.project_ids !== void 0 || b.default_project_id !== void 0, "nothing to update");
20427
+ var machineResponse = external_exports.object({ machine: machineSchema }).strict();
20428
+ var CLI_MAJOR = 0;
20429
+
20430
+ // ../shared/src/package-name.ts
20431
+ var CLI_PACKAGE_NAME = "@hivefloor/cli";
20432
+ var CLI_BIN_NAME = "hivefloor";
20433
+ var CLI_INSTALL_COMMAND = `npm i -g ${CLI_PACKAGE_NAME}`;
20434
+ function cliNpxCommand(args = "", opts = {}) {
20435
+ const spec = opts.pinMajor ? `${CLI_PACKAGE_NAME}@${CLI_MAJOR}` : CLI_PACKAGE_NAME;
20436
+ return `npx ${spec}${args ? ` ${args}` : ""}`;
20437
+ }
20438
+ var CLI_CONNECT_COMMAND = cliNpxCommand("connect");
20439
+
20440
+ // ../shared/src/usage.ts
20441
+ var MIN_SPAN_MS = 5 * 6e4;
20442
+ var MAX_ETA_MS = 31 * 24 * 36e5;
20443
+ var USAGE_COUNTERS = ["tokens_in", "tokens_out", "cost_usd"];
20444
+ function isUsageCounter(value) {
20445
+ return USAGE_COUNTERS.includes(value);
20446
+ }
20447
+ function parseUsageKey(key2) {
20448
+ const parts = key2.split(":");
20449
+ if (parts.length < 3) return null;
20450
+ const tool = parts[0];
20451
+ const profile = parts[1];
20452
+ if (!TOOLS.includes(tool)) return null;
20453
+ if (!PROFILE_KEY_RE.test(profile)) return null;
20454
+ if (parts.length === 3) {
20455
+ const counter2 = parts[2];
20456
+ return isUsageCounter(counter2) ? { tool, profile, session: null, counter: counter2 } : null;
20457
+ }
20458
+ if (parts[2] !== "s" || parts.length < 5) return null;
20459
+ const session = parts.slice(3, -1).join(":");
20460
+ const counter = parts[parts.length - 1];
20461
+ if (!session || !isUsageCounter(counter)) return null;
20462
+ return { tool, profile, session, counter };
20463
+ }
20464
+
20465
+ // ../shared/src/usage-alerts.ts
20466
+ var WASTE_WITHIN_MS = 3 * 36e5;
20467
+
20306
20468
  // ../shared/src/api/usage.ts
20307
20469
  var isoTime = external_exports.iso.datetime({ offset: true });
20308
20470
  var USAGE_PROVIDERS = [
@@ -20374,6 +20536,8 @@ var usageAccountViewSchema = external_exports.object({
20374
20536
  machines: external_exports.array(external_exports.string().max(80)).max(50),
20375
20537
  windows: external_exports.array(usageWindowViewSchema).max(20),
20376
20538
  issues: external_exports.array(usageIssueSchema).max(10).optional(),
20539
+ /** Distinct live agent lanes, independent of session/subagent count. */
20540
+ live_lanes: external_exports.number().int().nonnegative().optional(),
20377
20541
  /** How many live sessions draw on this account (subagents included). */
20378
20542
  live_sessions: external_exports.number().int().nonnegative().optional(),
20379
20543
  /** The live agents that draw on it, most recent first; `working` when one of its sessions works now. */
@@ -20387,10 +20551,20 @@ var usageMachineViewSchema = external_exports.object({
20387
20551
  last_seen_at: isoTime.optional(),
20388
20552
  stats: machineHostStatsSchema.optional()
20389
20553
  }).strict();
20554
+ var projectToolUsageSchema = external_exports.object({
20555
+ tool: toolSchema,
20556
+ sessions: external_exports.number().int().nonnegative(),
20557
+ priced_sessions: external_exports.number().int().nonnegative(),
20558
+ tokens_in: external_exports.number().int().nonnegative(),
20559
+ tokens_out: external_exports.number().int().nonnegative(),
20560
+ cost_usd: external_exports.number().nonnegative()
20561
+ }).strict();
20390
20562
  var projectUsageViewSchema = external_exports.object({
20391
20563
  id: entityIdSchema,
20392
20564
  key: external_exports.string(),
20393
20565
  name: external_exports.string(),
20566
+ /** The person's catch-all project: shown as "Unmapped sessions". */
20567
+ personal: external_exports.boolean().optional(),
20394
20568
  seconds: external_exports.number().int().nonnegative(),
20395
20569
  tokens_in: external_exports.number().int().nonnegative(),
20396
20570
  tokens_out: external_exports.number().int().nonnegative(),
@@ -20398,7 +20572,13 @@ var projectUsageViewSchema = external_exports.object({
20398
20572
  /** True when any of the numbers is an estimate. */
20399
20573
  approx: external_exports.boolean(),
20400
20574
  /** How many tasks of the project carry usage. */
20401
- tasks: external_exports.number().int().nonnegative()
20575
+ tasks: external_exports.number().int().nonnegative(),
20576
+ /** How many tool sessions reported usage in the project, claimed or not. */
20577
+ sessions: external_exports.number().int().nonnegative().optional(),
20578
+ /** When a machine last reported a session's counters for the project. */
20579
+ last_reported_at: isoTime.optional(),
20580
+ /** The session totals per tool; `priced_sessions` says how many of them sent a cost. */
20581
+ tools: external_exports.array(projectToolUsageSchema).max(10).optional()
20402
20582
  }).strict();
20403
20583
  var meUsageSchema = external_exports.object({
20404
20584
  generated_at: isoTime,
@@ -20479,6 +20659,53 @@ var usageRouteSchema = external_exports.object({
20479
20659
  unlinked_sessions: external_exports.number().int().nonnegative()
20480
20660
  }).strict();
20481
20661
 
20662
+ // ../shared/src/voice.ts
20663
+ var KOKORO_VOICES = [
20664
+ "af_alloy",
20665
+ "af_aoede",
20666
+ "af_bella",
20667
+ "af_heart",
20668
+ "af_jessica",
20669
+ "af_kore",
20670
+ "af_nicole",
20671
+ "af_nova",
20672
+ "af_river",
20673
+ "af_sarah",
20674
+ "af_sky",
20675
+ "am_adam",
20676
+ "am_echo",
20677
+ "am_eric",
20678
+ "am_fenrir",
20679
+ "am_liam",
20680
+ "am_michael",
20681
+ "am_onyx",
20682
+ "am_puck",
20683
+ "am_santa",
20684
+ "bf_alice",
20685
+ "bf_emma",
20686
+ "bf_isabella",
20687
+ "bf_lily",
20688
+ "bm_daniel",
20689
+ "bm_fable",
20690
+ "bm_george",
20691
+ "bm_lewis"
20692
+ ];
20693
+ var AGENT_VOICE_SPEEDS = [0.95, 1, 1.05, 1.1, 1.15];
20694
+ function fnv1a(s, seed) {
20695
+ let h = (2166136261 ^ seed) >>> 0;
20696
+ for (let i = 0; i < s.length; i++) {
20697
+ h ^= s.charCodeAt(i);
20698
+ h = Math.imul(h, 16777619) >>> 0;
20699
+ }
20700
+ return h >>> 0;
20701
+ }
20702
+ function voiceFor(agentId) {
20703
+ const voice = KOKORO_VOICES[fnv1a(agentId, 0) % KOKORO_VOICES.length];
20704
+ const speed = AGENT_VOICE_SPEEDS[fnv1a(agentId, 2654435769) % AGENT_VOICE_SPEEDS.length];
20705
+ return { voice, speed };
20706
+ }
20707
+ var KOKORO_VOICE_ID = /^[a-z]{2}_[a-z0-9]{2,24}$/;
20708
+
20482
20709
  // ../shared/src/remote.ts
20483
20710
  var SCHEME = /^([a-z][a-z0-9+.-]*):\/\//i;
20484
20711
  function normalizeRemote(remote) {
@@ -20522,6 +20749,61 @@ function formatRemote(r) {
20522
20749
  return `${r.host}/${r.owner}/${r.name}`;
20523
20750
  }
20524
20751
 
20752
+ // ../shared/src/project-map.ts
20753
+ var CWD_PREFIX_MAX = 500;
20754
+ function normalizeCwdPrefix(input2) {
20755
+ let s = input2.replace(/[\u0000-\u001f\u007f]/g, "").trim().replace(/\\/g, "/");
20756
+ if (s === "" || s.length > CWD_PREFIX_MAX) return null;
20757
+ const drive = /^[A-Za-z]:(\/|$)/.test(s);
20758
+ if (!drive && !s.startsWith("/")) return null;
20759
+ const parts = s.split("/").filter((p) => p !== "" && p !== ".");
20760
+ if (parts.some((p) => p === "..")) return null;
20761
+ if (drive) {
20762
+ s = parts[0].toUpperCase() + (parts.length > 1 ? "/" + parts.slice(1).join("/") : "/");
20763
+ return parts.length > 1 ? s : null;
20764
+ }
20765
+ return parts.length === 0 ? null : "/" + parts.join("/");
20766
+ }
20767
+
20768
+ // ../shared/src/api/project-map.ts
20769
+ var cwdMapBody = external_exports.object({
20770
+ prefix: external_exports.string().max(CWD_PREFIX_MAX * 2).transform((s, ctx) => {
20771
+ const n = normalizeCwdPrefix(s);
20772
+ if (!n) ctx.addIssue({ code: "custom", message: "must be an absolute folder, for example /home/me/code/app" });
20773
+ return n ?? "";
20774
+ })
20775
+ }).strict();
20776
+ var cwdMapSchema = external_exports.object({ id: idSchema, project_id: idSchema, prefix: external_exports.string(), sessions: external_exports.number().int().nonnegative() }).strict();
20777
+ var seenRemoteSchema = external_exports.object({
20778
+ remote_key: external_exports.string(),
20779
+ sessions: external_exports.number().int().nonnegative(),
20780
+ /** Sessions of this remote still in the catch-all project. */
20781
+ unmapped: external_exports.number().int().nonnegative(),
20782
+ last_seen: external_exports.string().nullable(),
20783
+ /** Projects the remote is linked to (active links). Several is ambiguous: its sessions are routed by folder. */
20784
+ project_ids: external_exports.array(idSchema),
20785
+ /** A project the person may link it to, taken from where its sessions already ran or from a folder entry; null when unknown. */
20786
+ suggested_project_id: idSchema.nullable()
20787
+ }).strict();
20788
+ var mapProjectSchema = external_exports.object({
20789
+ id: idSchema,
20790
+ key: external_exports.string(),
20791
+ name: external_exports.string(),
20792
+ /** The catch-all: shown as "Unmapped sessions", never a target of a link. */
20793
+ personal: external_exports.boolean(),
20794
+ role: external_exports.enum(["owner", "admin", "member", "viewer"]),
20795
+ sessions: external_exports.number().int().nonnegative()
20796
+ }).strict();
20797
+ var projectMapResponse = external_exports.object({
20798
+ projects: external_exports.array(mapProjectSchema),
20799
+ remotes: external_exports.array(seenRemoteSchema),
20800
+ cwd_maps: external_exports.array(cwdMapSchema),
20801
+ total_sessions: external_exports.number().int().nonnegative(),
20802
+ unmapped_sessions: external_exports.number().int().nonnegative()
20803
+ }).strict();
20804
+ var projectMapApplyResponse = external_exports.object({ moved: external_exports.number().int().nonnegative(), kept: external_exports.number().int().nonnegative() }).strict();
20805
+ var cwdMapResponse = external_exports.object({ cwd_map: cwdMapSchema, moved: external_exports.number().int().nonnegative() }).strict();
20806
+
20525
20807
  // ../shared/src/redact.ts
20526
20808
  var tag = (kind) => `[redacted:${kind}]`;
20527
20809
  function isPlaceholder(value) {
@@ -20588,6 +20870,54 @@ function redact(input2) {
20588
20870
  return { text: text2, count };
20589
20871
  }
20590
20872
 
20873
+ // ../shared/src/session-end.ts
20874
+ var SESSION_END_KINDS = ["finished", "interrupted", "unknown"];
20875
+ var SESSION_END_REASONS = [
20876
+ /** Finished: the tool's SessionEnd hook came after the turn ended (the person quit it, `/clear`, a one-shot run that exited). */
20877
+ "exited",
20878
+ /** Finished: the process went away after its last turn ended. */
20879
+ "closed_after_turn",
20880
+ /** Interrupted: the tool quit (SessionEnd) while a turn was open. */
20881
+ "quit_mid_turn",
20882
+ /** Interrupted: the process went away mid-turn (terminal closed, crash, killed). */
20883
+ "process_gone",
20884
+ /** Interrupted: the session went silent until the offline lease ran out while its machine stopped reporting (slept, rebooted, offline). */
20885
+ "machine_offline",
20886
+ /** Interrupted: the session went silent until the offline lease ran out while its machine still reported (the process died). */
20887
+ "process_lost",
20888
+ /** Unknown: the agent was disconnected or removed. */
20889
+ "agent_removed",
20890
+ /** Unknown: the machine lost access to the project. */
20891
+ "access_revoked",
20892
+ /** Unknown: a fleet lane reported stopped. */
20893
+ "fleet_stopped",
20894
+ /** Unknown: nothing tells how the last turn went. */
20895
+ "no_signal"
20896
+ ];
20897
+
20898
+ // ../shared/src/api/nudge.ts
20899
+ var NUDGE_TTL_SEC = 24 * 3600;
20900
+ var NUDGE_NOTE_MAX = 300;
20901
+ var nudgeBody = external_exports.object({ note: external_exports.string().trim().max(NUDGE_NOTE_MAX).optional() }).strict();
20902
+ var nudgeResponse = external_exports.object({
20903
+ nudge: external_exports.object({
20904
+ id: external_exports.string(),
20905
+ session_id: external_exports.string(),
20906
+ created_at: isoTimeSchema,
20907
+ /** When the next nudge of this session is allowed. */
20908
+ next_allowed_at: isoTimeSchema,
20909
+ /** The owner got a push (with the resume command when the tool has one). */
20910
+ pushed: external_exports.boolean(),
20911
+ resume_command: external_exports.string().nullable()
20912
+ })
20913
+ });
20914
+ var agentNudgeSchema = external_exports.object({ id: external_exports.string(), text: external_exports.string(), sent_at: isoTimeSchema });
20915
+ var sessionNudgeAckSchema = external_exports.object({
20916
+ created_at: isoTimeSchema,
20917
+ delivered_at: isoTimeSchema.nullable(),
20918
+ delivered_via: external_exports.enum(["hook", "mcp"]).nullable()
20919
+ });
20920
+
20591
20921
  // ../shared/src/api/memory.ts
20592
20922
  var CONTEXT_DECISIONS = 10;
20593
20923
  var MEMORY_KINDS = ["handoff", "decision"];
@@ -20647,12 +20977,14 @@ var floorAgentSchema = external_exports.object({
20647
20977
  id: entityIdSchema,
20648
20978
  name: external_exports.string(),
20649
20979
  tool: floorToolSchema,
20650
- /** Tiles inside a pod are grouped by this, for example "Claude Max (zan)". */
20980
+ /** Tiles inside a pod are grouped by this, for example "Claude Max (alex)". */
20651
20981
  account_label: external_exports.string(),
20652
20982
  machine: external_exports.string().nullable(),
20653
20983
  default_model: external_exports.string().nullable(),
20654
20984
  owner_id: entityIdSchema,
20655
- last_seen_at: isoTimeSchema.nullable()
20985
+ last_seen_at: isoTimeSchema.nullable(),
20986
+ /** The agent's machine's last heartbeat (null: no live machine). The browser treats the machine as online within `MACHINE_ONLINE_SECONDS` of it; Resume needs that. Never in a share link. Older servers omit it. */
20987
+ machine_seen_at: isoTimeSchema.nullable().optional()
20656
20988
  });
20657
20989
  var floorSessionSchema = external_exports.object({
20658
20990
  id: entityIdSchema,
@@ -20665,6 +20997,9 @@ var floorSessionSchema = external_exports.object({
20665
20997
  state_since: isoTimeSchema.optional(),
20666
20998
  /** For a `waiting` session: false once somebody answered this very wait. Older servers omit it (read as true). */
20667
20999
  wait_open: external_exports.boolean().optional(),
21000
+ /** Main sessions: the normalized error line that keeps coming back, and how many stops in a row repeated it (why a session is `looping`). Never in a share link. Older servers omit them. */
21001
+ loop_key: external_exports.string().nullable().optional(),
21002
+ loop_count: external_exports.number().int().optional(),
20668
21003
  /** The tool's own session id (what `claude --resume` takes), main sessions only. */
20669
21004
  tool_session_id: external_exports.string().nullable(),
20670
21005
  model: external_exports.string().nullable(),
@@ -20683,6 +21018,14 @@ var floorSessionSchema = external_exports.object({
20683
21018
  started_at: isoTimeSchema,
20684
21019
  last_event_at: isoTimeSchema,
20685
21020
  ended_at: isoTimeSchema.nullable(),
21021
+ /** How an ended main session ended (o147): Resume is offered only for 'interrupted'. Null while live; older servers omit it. */
21022
+ end_kind: external_exports.enum(SESSION_END_KINDS).nullable().optional(),
21023
+ /** The stored reason (`SESSION_END_REASON_TEXT` has it in plain words). */
21024
+ end_reason: external_exports.enum(SESSION_END_REASONS).nullable().optional(),
21025
+ /** Set while a session revived after it Finished (o160 4) runs; cleared on its next end. Older servers omit it. */
21026
+ revived_at: isoTimeSchema.nullable().optional(),
21027
+ /** Latest nudge from the last day, or null. Older servers omit it. */
21028
+ nudge: sessionNudgeAckSchema.nullable().optional(),
20686
21029
  get children() {
20687
21030
  return external_exports.array(floorSessionSchema);
20688
21031
  }
@@ -20703,14 +21046,25 @@ var floorSnapshotSchema = external_exports.object({
20703
21046
  }),
20704
21047
  pods: external_exports.array(floorPodSchema),
20705
21048
  shelves: external_exports.object({
20706
- /** Every ready task, most urgent first (at most 200). */
21049
+ /** Ready tasks, most urgent first (at most 200). */
20707
21050
  ready: external_exports.array(taskCardSchema),
21051
+ /** In review, newest first (at most 200). */
20708
21052
  in_review: external_exports.array(taskCardSchema),
20709
21053
  /** Done in the last 24 hours, newest first (at most 50). The client keeps those done since its local midnight. */
20710
21054
  done_today: external_exports.array(taskCardSchema)
20711
21055
  }),
20712
- /** Claimed and blocked tasks, shown on their holder's tile (`session.task_id`). */
21056
+ /** Claimed and blocked tasks, shown on their holder's tile (`session.task_id`). Each status is at most 200. */
20713
21057
  claimed: external_exports.array(taskCardSchema),
21058
+ /**
21059
+ * Set when a shelf was cut at 200. A number is how many rows were left off, when the server counted them;
21060
+ * `true` means there is at least one more. A shelf that fit is omitted, and so is this object when every shelf fit.
21061
+ */
21062
+ truncated: external_exports.object({
21063
+ ready: external_exports.union([external_exports.literal(true), external_exports.number().int().positive()]).optional(),
21064
+ in_review: external_exports.union([external_exports.literal(true), external_exports.number().int().positive()]).optional(),
21065
+ claimed: external_exports.union([external_exports.literal(true), external_exports.number().int().positive()]).optional(),
21066
+ blocked: external_exports.union([external_exports.literal(true), external_exports.number().int().positive()]).optional()
21067
+ }).optional(),
20714
21068
  /** The id of the newest event the snapshot includes; the client ignores stream events up to it. Null when there is none. */
20715
21069
  last_event_id: entityIdSchema.nullable(),
20716
21070
  server_time: isoTimeSchema
@@ -20718,7 +21072,14 @@ var floorSnapshotSchema = external_exports.object({
20718
21072
  var floorStreamPayloads = {
20719
21073
  /** A session upsert; `agent` and `user` let the client place a session of an agent it has not seen yet. */
20720
21074
  session: external_exports.object({ session: floorSessionSchema, agent: floorAgentSchema, user: floorUserSchema }),
20721
- session_end: external_exports.object({ session_id: entityIdSchema, agent_id: entityIdSchema, ended_at: isoTimeSchema }),
21075
+ session_end: external_exports.object({
21076
+ session_id: entityIdSchema,
21077
+ agent_id: entityIdSchema,
21078
+ ended_at: isoTimeSchema,
21079
+ /** How it ended (o147); older servers omit it. */
21080
+ end_kind: external_exports.enum(SESSION_END_KINDS).nullable().optional(),
21081
+ end_reason: external_exports.enum(SESSION_END_REASONS).nullable().optional()
21082
+ }),
20722
21083
  task: external_exports.object({ task: taskCardSchema }),
20723
21084
  task_event: external_exports.object({ event: taskTimelineEventSchema }),
20724
21085
  notification: external_exports.object({ notification: notificationViewSchema }),
@@ -20748,6 +21109,10 @@ var collisionPeerSchema = external_exports.object({
20748
21109
  });
20749
21110
  var taskDetailSchema = external_exports.object({
20750
21111
  task: taskCardSchema,
21112
+ /** The task's description as written (Markdown), for the editor. Null when it has none. */
21113
+ body: external_exports.string().nullish(),
21114
+ /** The tools allowed to claim it; empty means any agent. */
21115
+ for_tools: external_exports.array(external_exports.string()).nullish(),
20751
21116
  events: external_exports.array(taskTimelineEventSchema),
20752
21117
  subtasks: external_exports.array(taskCardSchema),
20753
21118
  holder_session: floorSessionSchema.nullable(),
@@ -20860,6 +21225,32 @@ var HOUR_MS = 36e5;
20860
21225
  var MAX_FLOOR_RANGE_MS = 8 * 24 * HOUR_MS;
20861
21226
  var DEFAULT_FLOOR_WINDOW_MS = 24 * HOUR_MS;
20862
21227
 
21228
+ // ../shared/src/session-state.ts
21229
+ var OFFLINE_AFTER_SEC = 300;
21230
+ var OFFLINE_LEASE_SEC = 6 * 3600;
21231
+ var ENDED_LISTED_SEC = 24 * 3600;
21232
+ var DISPLAY_STATE_LEGEND = {
21233
+ live: { label: "Live", text: "Working now: a turn is running." },
21234
+ waiting: { label: "Waiting on you", text: 'Asked a question or wants a permission. Only these count in "need you".' },
21235
+ idle: { label: "Idle (done)", text: 'Finished its turn with a report and asked nothing. Never counts in "need you".' },
21236
+ stalled: { label: "Stalled", text: `Working, but nothing heard for ${STALLED_AFTER_SEC / 60} min or more.` },
21237
+ offline: { label: "Offline", text: `No heartbeat for ${OFFLINE_AFTER_SEC / 60} min, the machine is off or the process is gone. Moves to Ended after ${OFFLINE_LEASE_SEC / 3600} h.` },
21238
+ ended: { label: "Ended", text: `Closed, or offline past its lease. Listed under "Ended (n)" for ${ENDED_LISTED_SEC / 3600} h; never counted as an agent.` }
21239
+ };
21240
+
21241
+ // ../shared/src/client-routes.ts
21242
+ var SEGMENT = "[^/]+";
21243
+ var PROJECT_TABS = "(?:board|done|team|memory|agents|settings|welcome)";
21244
+ var CLIENT_ROUTE_PATTERNS = [
21245
+ /^\/$/,
21246
+ /^\/docs\/quest$/,
21247
+ /^\/(?:about|docs|signin|signup|app|connect|floor|hive|floor3d|machines|new|settings|inbox|needs-you|feedback|usage|demo|orchestrator|voice-lab)$/,
21248
+ new RegExp(`^/(?:s|invite|u)/${SEGMENT}$`),
21249
+ new RegExp(`^/p/${SEGMENT}$`),
21250
+ new RegExp(`^/p/${SEGMENT}/${PROJECT_TABS}$`),
21251
+ new RegExp(`^/p/${SEGMENT}/board/${SEGMENT}$`)
21252
+ ];
21253
+
20863
21254
  // ../shared/src/collisions.ts
20864
21255
  var COLLISION_WINDOW_SEC = 30 * 60;
20865
21256
  var LOOP_NO_CHANGE_SEC = 30 * 60;
@@ -20891,9 +21282,73 @@ var webhookGetResponse = external_exports.object({ webhook: webhookViewSchema.nu
20891
21282
  var webhookPutResponse = external_exports.object({ webhook: webhookViewSchema, secret: external_exports.string().optional() }).strict();
20892
21283
  var webhookTestResponse = external_exports.object({ ok: external_exports.literal(true), queued: external_exports.literal(true) }).strict();
20893
21284
 
21285
+ // ../shared/src/api/provider-keys.ts
21286
+ var PROVIDER_NAMES = ["anthropic", "openai", "google", "openai_compat"];
21287
+ var providerNameSchema = external_exports.enum(PROVIDER_NAMES);
21288
+ var PROVIDER_KEY_LABEL_MAX = 60;
21289
+ var PROVIDER_KEY_RE = /^[\x21-\x7e]{8,512}$/;
21290
+ var addProviderKeyBody = external_exports.object({
21291
+ provider: providerNameSchema,
21292
+ base_url: external_exports.string().trim().min(1).max(2048).optional(),
21293
+ label: external_exports.string().trim().max(PROVIDER_KEY_LABEL_MAX).optional(),
21294
+ key: external_exports.string().trim().regex(PROVIDER_KEY_RE, "That does not look like an API key")
21295
+ }).strict();
21296
+ var providerKeyViewSchema = external_exports.object({
21297
+ id: entityIdSchema,
21298
+ provider: providerNameSchema,
21299
+ base_url: external_exports.string().nullable(),
21300
+ label: external_exports.string(),
21301
+ last4: external_exports.string(),
21302
+ created_at: isoTimeSchema
21303
+ }).strict();
21304
+ var providerKeyListSchema = external_exports.object({ keys: external_exports.array(providerKeyViewSchema) }).strict();
21305
+ var providerKeyAddedSchema = external_exports.object({ key: providerKeyViewSchema, model_count: external_exports.number().int().nonnegative() }).strict();
21306
+ var providerModelSchema = external_exports.object({ id: external_exports.string(), label: external_exports.string().optional() }).strict();
21307
+ var providerModelsSchema = external_exports.object({ models: external_exports.array(providerModelSchema) }).strict();
21308
+
21309
+ // ../shared/src/model-prices.ts
21310
+ var CLAUDE_PRICES = [
21311
+ ["claude-fable-5-2", { input: 8, output: 40, cacheRead: 0.2 }],
21312
+ ["claude-fable-5-1", { input: 10, output: 50 }],
21313
+ ["claude-fable-5", { input: 10, output: 50 }],
21314
+ ["claude-opus-5-5", { input: 4, output: 20, cacheRead: 0.2 }],
21315
+ ["claude-opus-5", { input: 5, output: 25 }],
21316
+ ["claude-opus-4-8", { input: 5, output: 25 }],
21317
+ ["claude-opus-4-7", { input: 5, output: 25 }],
21318
+ ["claude-opus-4-6", { input: 5, output: 25 }],
21319
+ ["claude-opus-4-5", { input: 5, output: 25 }],
21320
+ ["claude-sonnet-5-5", { input: 2, output: 10, cacheRead: 0.1 }],
21321
+ ["claude-sonnet-5", { input: 2, output: 10 }],
21322
+ ["claude-sonnet-4-6", { input: 3, output: 15 }],
21323
+ ["claude-sonnet-4-5", { input: 3, output: 15 }],
21324
+ ["claude-sonnet-4", { input: 3, output: 15 }],
21325
+ ["claude-haiku-5-5", { input: 0.1, output: 0.5 }],
21326
+ ["claude-haiku-4-5", { input: 1, output: 5 }]
21327
+ ];
21328
+ function claudeModelPrice(model) {
21329
+ if (!model) return null;
21330
+ const m = model.toLowerCase();
21331
+ const at = m.indexOf("claude-");
21332
+ if (at < 0) return null;
21333
+ const id2 = m.slice(at);
21334
+ for (const [prefix, price] of CLAUDE_PRICES) {
21335
+ if (id2 === prefix || id2.startsWith(`${prefix}-`) || id2.startsWith(`${prefix}[`) || id2.startsWith(`${prefix}@`) || id2.startsWith(`${prefix}:`)) return price;
21336
+ }
21337
+ return null;
21338
+ }
21339
+ function estimateClaudeCostUsd(model, t) {
21340
+ const p = claudeModelPrice(model);
21341
+ if (!p) return null;
21342
+ const cacheRead = p.cacheRead ?? p.input * 0.1;
21343
+ const cacheWrite = p.cacheWrite ?? p.input * 1.25;
21344
+ return (t.input * p.input + t.output * p.output + t.cacheRead * cacheRead + t.cacheWrite * cacheWrite) / 1e6;
21345
+ }
21346
+
20894
21347
  // ../shared/src/api/inbox.ts
20895
21348
  var INBOX_KINDS = ["blocked_task", "waiting", "question"];
20896
21349
  var inboxKindSchema = external_exports.enum(INBOX_KINDS);
21350
+ var LISTENERS = ["agent", "fleet", "none"];
21351
+ var listenerSchema = external_exports.enum(LISTENERS);
20897
21352
  var inboxItemSchema = external_exports.object({
20898
21353
  /** `task:<id>`, `session:<id>` or `question:<id>`. */
20899
21354
  id: external_exports.string().regex(/^(task|session|question):\d{1,20}$/),
@@ -20904,20 +21359,45 @@ var inboxItemSchema = external_exports.object({
20904
21359
  /** The question or status text (redacted, at most 1000 characters). */
20905
21360
  text: external_exports.string(),
20906
21361
  waiting_since: isoTimeSchema,
21362
+ /**
21363
+ * Whether an agent or session is on the item. A blocked task nobody holds (a backlog import, a released claim) has no one to
21364
+ * read the answer: the answer is saved on the task only. Sessions and questions always have an agent. Absent from older servers: treat as true.
21365
+ */
21366
+ has_holder: external_exports.boolean().optional(),
21367
+ /**
21368
+ * Who acts on the answer: a live `agent` session, the `fleet` (an imported task: the fleet lead reads `answered` events through the
21369
+ * bridge) or `none` (nobody: the answer is only saved). Absent from older servers.
21370
+ */
21371
+ listener: listenerSchema.optional(),
20907
21372
  /** Whether the caller may answer it (role, the project's answer setting, and for a member: owning the agent). */
20908
21373
  can_answer: external_exports.boolean(),
20909
21374
  /** Whether the caller may nudge the item's session now (F2): owner or admin, and the session is stalled, parked, waiting too long or looping. */
20910
21375
  can_nudge: external_exports.boolean().optional()
20911
21376
  });
21377
+ var inboxGroupSchema = external_exports.object({
21378
+ project: external_exports.object({ id: entityIdSchema, key: external_exports.string(), name: external_exports.string() }),
21379
+ /** Items waiting in the project, answerable or not. */
21380
+ count: external_exports.number().int().min(0),
21381
+ /** Of those, the ones the caller can answer. */
21382
+ answerable: external_exports.number().int().min(0),
21383
+ /** An agent is waiting in it (a live session or a question), not only backlog decisions. */
21384
+ live: external_exports.boolean()
21385
+ });
20912
21386
  var inboxListSchema = external_exports.object({
20913
21387
  items: external_exports.array(inboxItemSchema),
20914
21388
  /** Items the caller can answer: the sidebar badge. */
20915
21389
  count: external_exports.number().int().min(0),
20916
21390
  /** Every item the caller can see, answerable or not (`items` is one page of them). */
20917
21391
  total: external_exports.number().int().min(0).optional(),
21392
+ /** One entry per project with something waiting, over every item: projects with something to answer first, live ones before backlog-only ones. */
21393
+ groups: external_exports.array(inboxGroupSchema).optional(),
20918
21394
  /** Offset of the next page, null on the last one. */
20919
- next_cursor: external_exports.string().nullable().optional()
21395
+ next_cursor: external_exports.string().nullable().optional(),
21396
+ /** Present (true) when a kind had more rows than this response loaded. The list loads 200 per kind, and a `cursor` past that loads further, up to 1000. `total` and `groups` then cover the loaded rows, while `count` stays exact. */
21397
+ truncated: external_exports.boolean().optional()
20920
21398
  });
21399
+ var ANSWER_THEN = ["ready", "backlog", "done", "blocked"];
21400
+ var answerThenSchema = external_exports.enum(ANSWER_THEN);
20921
21401
  var inboxAnswerBodySchema = external_exports.object({
20922
21402
  text: external_exports.string().trim().min(1).max(4e3),
20923
21403
  /**
@@ -20925,8 +21405,28 @@ var inboxAnswerBodySchema = external_exports.object({
20925
21405
  * answer to a wait that changed in the meantime (409 `not_waiting`): the answer would approve a prompt the
20926
21406
  * person never read.
20927
21407
  */
20928
- waiting_since: isoTimeSchema.optional()
21408
+ waiting_since: isoTimeSchema.optional(),
21409
+ /** Blocked-task items only: the status the task takes after the answer (default `ready`). Sessions and questions refuse anything but `ready` (400). */
21410
+ then: answerThenSchema.optional()
20929
21411
  }).strict();
21412
+ var inboxAnswerResponseSchema = external_exports.object({ ok: external_exports.literal(true), count: external_exports.number().int().min(0), listener: listenerSchema });
21413
+ var DELIVERY_STATES = ["waiting", "delivered", "acknowledged", "no_listener"];
21414
+ var deliveryStateSchema = external_exports.enum(DELIVERY_STATES);
21415
+ var inboxAnsweredItemSchema = external_exports.object({
21416
+ id: external_exports.string().regex(/^(task|session|question):\d{1,20}$/),
21417
+ kind: inboxKindSchema,
21418
+ project: external_exports.object({ id: entityIdSchema, key: external_exports.string(), name: external_exports.string() }),
21419
+ task: external_exports.object({ id: entityIdSchema, num: external_exports.number().int().positive(), key: external_exports.string(), title: external_exports.string() }).nullable(),
21420
+ text: external_exports.string(),
21421
+ answer: external_exports.string(),
21422
+ answered_at: isoTimeSchema,
21423
+ listener: listenerSchema,
21424
+ delivery: deliveryStateSchema,
21425
+ delivered_at: isoTimeSchema.nullable(),
21426
+ /** A task answer's outcome (`ready`, `backlog`, `done` or `blocked`). */
21427
+ then: answerThenSchema.nullable()
21428
+ });
21429
+ var inboxAnsweredListSchema = external_exports.object({ items: external_exports.array(inboxAnsweredItemSchema) });
20930
21430
  var askBody = external_exports.object({
20931
21431
  question: external_exports.string().trim().min(1).max(1e3),
20932
21432
  project: external_exports.union([external_exports.string().trim().min(1).max(100), external_exports.number().int().positive()]).transform(String).optional(),
@@ -20940,7 +21440,8 @@ var questionViewSchema = external_exports.object({
20940
21440
  session_id: entityIdSchema.nullable(),
20941
21441
  question: external_exports.string(),
20942
21442
  answer: external_exports.string().nullable(),
20943
- status: external_exports.enum(["open", "answered"]),
21443
+ /** `closed`: nobody answered it and it no longer waits (it expired, its session ended or its task was closed). */
21444
+ status: external_exports.enum(["open", "answered", "closed"]),
20944
21445
  asked_at: isoTimeSchema,
20945
21446
  answered_at: isoTimeSchema.nullable(),
20946
21447
  read_at: isoTimeSchema.nullable()
@@ -20994,6 +21495,52 @@ var teamViewSchema = external_exports.object({
20994
21495
  next_cursor: external_exports.string().nullable().optional()
20995
21496
  }).strict();
20996
21497
 
21498
+ // ../shared/src/api/team-visibility.ts
21499
+ var VISIBILITY_LEVELS = ["none", "counts", "live"];
21500
+ var visibilityLevelSchema = external_exports.enum(VISIBILITY_LEVELS);
21501
+ var roleEnum2 = external_exports.enum(["owner", "admin", "member", "viewer"]);
21502
+ var teamVisibilityPolicySchema = external_exports.object({
21503
+ member_visibility: visibilityLevelSchema,
21504
+ outside_counts: external_exports.boolean(),
21505
+ allow_member_listing: external_exports.boolean()
21506
+ }).strict();
21507
+ var putTeamVisibilityBody = teamVisibilityPolicySchema.partial().strict().refine((b) => b.member_visibility !== void 0 || b.outside_counts !== void 0 || b.allow_member_listing !== void 0, "nothing to update");
21508
+ var shareLevelBody = external_exports.object({ share_level: visibilityLevelSchema }).strict();
21509
+ var shareLevelResponse = external_exports.object({
21510
+ share_level: visibilityLevelSchema,
21511
+ cap: visibilityLevelSchema,
21512
+ effective: visibilityLevelSchema
21513
+ }).strict();
21514
+ var heatmapSchema = external_exports.object({
21515
+ metric: external_exports.literal("sessions"),
21516
+ days: external_exports.array(external_exports.object({ day: external_exports.string(), value: external_exports.number() }).strict())
21517
+ }).strict();
21518
+ var rosterTotalsSchema = external_exports.object({
21519
+ sessions_started: external_exports.number().int().nonnegative(),
21520
+ sessions_finished: external_exports.number().int().nonnegative(),
21521
+ agent_hours: external_exports.number().nonnegative(),
21522
+ machines: external_exports.number().int().nonnegative(),
21523
+ longest_streak: external_exports.number().int().nonnegative(),
21524
+ current_streak: external_exports.number().int().nonnegative()
21525
+ }).strict();
21526
+ var liveCountsSchema = external_exports.object({
21527
+ agents: external_exports.number().int().nonnegative(),
21528
+ machines: external_exports.number().int().nonnegative()
21529
+ }).strict();
21530
+ var rosterEntrySchema = external_exports.object({
21531
+ user: external_exports.object({ id: idSchema, login: external_exports.string(), avatar_url: external_exports.string().nullable() }).strict(),
21532
+ role: roleEnum2,
21533
+ heatmap: heatmapSchema.optional(),
21534
+ totals: rosterTotalsSchema.optional(),
21535
+ live: liveCountsSchema.optional()
21536
+ }).strict();
21537
+ var teamActivityResponse = external_exports.object({
21538
+ policy: teamVisibilityPolicySchema,
21539
+ you: external_exports.object({ share_level: visibilityLevelSchema, cap: visibilityLevelSchema, effective: visibilityLevelSchema }).strict(),
21540
+ heatmap: heatmapSchema,
21541
+ members: external_exports.array(rosterEntrySchema)
21542
+ }).strict();
21543
+
20997
21544
  // ../shared/src/api/fleet.ts
20998
21545
  var FLEET_STATES = ["working", "idle", "waiting", "paused", "stopped", "unknown"];
20999
21546
  var fleetStateSchema = external_exports.enum(FLEET_STATES);
@@ -21061,11 +21608,9 @@ var fleetSnapshotResult = external_exports.object({
21061
21608
  tasks: external_exports.object({ created: external_exports.number(), updated: external_exports.number(), missing: external_exports.number(), skipped: external_exports.number() }).strict()
21062
21609
  }).strict();
21063
21610
  var fleetTokenSchema = external_exports.object({ id: idSchema, label: external_exports.string(), last4: external_exports.string(), created_at: external_exports.string(), last_used_at: external_exports.string().nullable(), revoked_at: external_exports.string().nullable() }).strict();
21064
- var fleetTokensResponse = external_exports.object({ items: external_exports.array(fleetTokenSchema) }).strict();
21611
+ var fleetTokensResponse = listOf(fleetTokenSchema);
21065
21612
 
21066
21613
  // ../shared/src/api/share.ts
21067
- var SHARE_EXPIRY_PRESETS = ["1h", "1d", "7d", "30d"];
21068
- var shareExpiryPresetSchema = external_exports.enum(SHARE_EXPIRY_PRESETS);
21069
21614
  var MAX_SHARE_LINK_DAYS = 30;
21070
21615
  var MIN_SHARE_LINK_SECONDS = 60;
21071
21616
  var MAX_SHARE_LINK_SECONDS = MAX_SHARE_LINK_DAYS * 86400;
@@ -21148,10 +21693,83 @@ var URL_OR_PATH_RE = new RegExp(
21148
21693
  "g"
21149
21694
  );
21150
21695
 
21696
+ // ../shared/src/api/audit.ts
21697
+ var auditEntrySchema = external_exports.object({
21698
+ id: idSchema,
21699
+ /** The project the action was on; null for a user-level action (a token issued, a machine removed). */
21700
+ project_id: idSchema.nullable(),
21701
+ user_id: idSchema.nullable(),
21702
+ user_login: external_exports.string().nullable(),
21703
+ agent_id: idSchema.nullable(),
21704
+ action: external_exports.string().min(1).max(100),
21705
+ /** Small JSON detail written with the action. Never holds a token or secret. */
21706
+ data: external_exports.record(external_exports.string(), external_exports.unknown()),
21707
+ at: isoTimeSchema
21708
+ }).strict();
21709
+ var auditListResponse = external_exports.object({
21710
+ items: external_exports.array(auditEntrySchema),
21711
+ /** Pass as `cursor` for the next (older) page; null on the last page. */
21712
+ next_cursor: external_exports.string().nullable()
21713
+ }).strict();
21714
+
21715
+ // ../shared/src/orch-schedules.ts
21716
+ var MIN_GAP_MINUTES = 5;
21717
+ function cronFields(cron) {
21718
+ const parts = cron.trim().split(/\s+/);
21719
+ if (parts.length !== 5) throw new Error("Use five cron fields: minute hour day month weekday.");
21720
+ return parts.map((raw, i) => {
21721
+ const names = i === 3 ? ["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"] : i === 4 ? ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"] : [];
21722
+ const part = raw.toUpperCase().replace(/[A-Z]+/g, (name) => {
21723
+ const n = names.indexOf(name);
21724
+ return n < 0 ? name : String(n + (i === 3 ? 1 : 0));
21725
+ });
21726
+ const [min, max] = [[0, 59], [0, 23], [1, 31], [1, 12], [0, 7]][i];
21727
+ const values = /* @__PURE__ */ new Set();
21728
+ for (const item of part.split(",")) {
21729
+ const match = /^(\*|\d+(?:-\d+)?)(?:\/(\d+))?$/.exec(item);
21730
+ if (!match) throw new Error("Invalid cron field.");
21731
+ const step = Number(match[2] ?? 1);
21732
+ const range = match[1];
21733
+ const [start, end] = range === "*" ? [min, max] : range.includes("-") ? range.split("-").map(Number) : [Number(range), match[2] ? max : Number(range)];
21734
+ if (step < 1 || start < min || end > max || start > end) throw new Error("Cron value is out of range.");
21735
+ for (let v = start; v <= end; v += step) values.add(i === 4 && v === 7 ? 0 : v);
21736
+ }
21737
+ return { values: [...values].sort((a, b) => a - b), wildcard: part === "*" };
21738
+ });
21739
+ }
21740
+ function formatter(tz) {
21741
+ return new Intl.DateTimeFormat("en-CA", { timeZone: tz, year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit", hourCycle: "h23" });
21742
+ }
21743
+ function scheduleError(s) {
21744
+ if (!s.sessionTarget.trim()) return "Choose a session target.";
21745
+ if (!s.prompt.trim()) return "Enter a prompt.";
21746
+ try {
21747
+ formatter(s.tz).format(0);
21748
+ } catch {
21749
+ return "Enter a valid IANA time zone.";
21750
+ }
21751
+ if (Number(s.at !== void 0) + Number(s.every !== void 0) !== 1) return "Choose one time or one repeat rule.";
21752
+ if (s.at !== void 0) {
21753
+ const match = /^(\d{4})-(\d{2})-(\d{2})T([01]\d|2[0-3]):([0-5]\d)(?::([0-5]\d)(?:\.\d{1,3})?)?(?:Z|[+-]\d{2}:\d{2})$/i.exec(s.at);
21754
+ const calendar = match ? new Date(Date.UTC(Number(match[1]), Number(match[2]) - 1, Number(match[3]))) : null;
21755
+ return match && Number.isFinite(Date.parse(s.at)) && calendar?.getUTCMonth() === Number(match[2]) - 1 && calendar.getUTCDate() === Number(match[3]) ? null : "Enter a valid ISO time with Z or a UTC offset.";
21756
+ }
21757
+ const every = s.every;
21758
+ if (Number(every.minutes !== void 0) + Number(every.cron !== void 0) !== 1) return "Choose minutes or cron.";
21759
+ if (every.minutes !== void 0) return Number.isSafeInteger(every.minutes) && every.minutes > 0 ? null : "Minutes must be a positive whole number.";
21760
+ let minute;
21761
+ try {
21762
+ minute = cronFields(every.cron)[0];
21763
+ } catch (e) {
21764
+ return e.message;
21765
+ }
21766
+ const v = [...minute.values].sort((a, b) => a - b);
21767
+ const gaps = v.map((m, i) => i + 1 < v.length ? v[i + 1] - m : 60 - m + v[0]);
21768
+ return Math.min(...gaps) >= MIN_GAP_MINUTES ? null : `Cron check-ins must be at least ${MIN_GAP_MINUTES} minutes apart.`;
21769
+ }
21770
+
21151
21771
  // ../shared/src/api/digest.ts
21152
21772
  var DIGEST_ITEMS_LIMIT = 5;
21153
- var DIGEST_KINDS = ["tasks_done", "prs_merged", "tasks_blocked", "needs_you", "new_agents"];
21154
- var digestKindSchema = external_exports.enum(DIGEST_KINDS);
21155
21773
  var digestTaskItemSchema = external_exports.object({
21156
21774
  id: idSchema,
21157
21775
  project_id: idSchema,
@@ -21291,130 +21909,690 @@ var feedbackListSchema = external_exports.object({
21291
21909
  next_cursor: external_exports.string().nullable(),
21292
21910
  total: external_exports.number().int().min(0)
21293
21911
  });
21912
+ var REPORT_SCREENSHOT_MAX_BYTES = 1572864;
21913
+ var REPORT_SCREENSHOT_DATA_URL_MAX = Math.ceil(REPORT_SCREENSHOT_MAX_BYTES / 3) * 4 + 32;
21914
+ var REPORT_MESSAGE_MAX = 1500;
21915
+ var reportBodySchema = external_exports.object({
21916
+ message: external_exports.string().trim().min(FEEDBACK_MESSAGE_MIN, `Write at least ${FEEDBACK_MESSAGE_MIN} characters`).max(REPORT_MESSAGE_MAX, `At most ${REPORT_MESSAGE_MAX} characters`),
21917
+ screenshot: external_exports.string().max(REPORT_SCREENSHOT_DATA_URL_MAX, "Screenshot is too large").optional(),
21918
+ /** Where the report came from, so the owner can reproduce it. Short strings only. */
21919
+ context: external_exports.object({
21920
+ mode: external_exports.enum(["vr", "ar", "desktop"]).optional(),
21921
+ world: external_exports.string().trim().max(60).optional(),
21922
+ url: external_exports.string().trim().max(300).optional(),
21923
+ fps: external_exports.number().min(0).max(1e3).optional()
21924
+ }).strict().optional()
21925
+ }).strict();
21926
+ var reportSentSchema = external_exports.object({ ok: external_exports.literal(true), id: entityIdSchema, screenshot: external_exports.boolean() }).strict();
21294
21927
 
21295
- // ../shared/src/api/nudge.ts
21296
- var NUDGE_TTL_SEC = 24 * 3600;
21297
- var NUDGE_NOTE_MAX = 300;
21298
- var nudgeBody = external_exports.object({ note: external_exports.string().trim().max(NUDGE_NOTE_MAX).optional() }).strict();
21299
- var nudgeResponse = external_exports.object({
21300
- nudge: external_exports.object({
21301
- id: external_exports.string(),
21302
- session_id: external_exports.string(),
21303
- created_at: isoTimeSchema,
21304
- /** When the next nudge of this session is allowed. */
21305
- next_allowed_at: isoTimeSchema,
21306
- /** The owner got a push (with the resume command when the tool has one). */
21307
- pushed: external_exports.boolean(),
21308
- resume_command: external_exports.string().nullable()
21309
- })
21928
+ // ../shared/src/api/talk.ts
21929
+ var TALK_UNREACHABLE = ["session_ended", "no_machine", "machine_offline", "control_off", "tool_unsupported"];
21930
+ var talkReachSchema = external_exports.union([external_exports.object({ ok: external_exports.literal(true) }), external_exports.object({ ok: external_exports.literal(false), reason: external_exports.enum(TALK_UNREACHABLE) })]);
21931
+ var talkEntrySchema = external_exports.object({
21932
+ id: external_exports.string(),
21933
+ role: external_exports.enum(["user", "agent"]),
21934
+ text: external_exports.string(),
21935
+ at: isoTimeSchema,
21936
+ /** Who sent it (user rows). */
21937
+ by: external_exports.object({ user_id: external_exports.string(), name: external_exports.string() }).optional(),
21938
+ /** The command that carried it (user rows), while that command row exists: its status shows sent -> delivered -> done / failed. */
21939
+ command: commandSchema.pick({ id: true, status: true, code: true, via: true, detail: true }).optional()
21310
21940
  });
21311
- var agentNudgeSchema = external_exports.object({ id: external_exports.string(), text: external_exports.string(), sent_at: isoTimeSchema });
21312
-
21313
- // ../shared/src/index.ts
21314
- var ROLES = ["owner", "admin", "member", "viewer"];
21315
- var roleSchema2 = external_exports.enum(ROLES);
21941
+ var talkResponse = external_exports.object({ reach: talkReachSchema, thread: external_exports.array(talkEntrySchema) });
21316
21942
 
21317
- // src/ctx.ts
21318
- import { execFile } from "child_process";
21319
- import os from "os";
21320
- import readline from "readline";
21321
- import { spawn } from "child_process";
21322
- var DEFAULT_HOST = "https://hivefloor.worldofz.info";
21323
- function defaultCtx() {
21324
- const ctx = {
21325
- out: (s) => void process.stdout.write(s),
21326
- err: (s) => void process.stderr.write(s),
21327
- env: process.env,
21328
- cwd: process.cwd(),
21329
- fetch: (...args) => fetch(...args),
21330
- sleep: (ms) => new Promise((r) => setTimeout(r, ms)),
21331
- now: () => Date.now(),
21332
- stdoutIsTTY: Boolean(process.stdout.isTTY),
21333
- ask: askOnTerminal,
21334
- open: async (url2) => openBrowser(url2, ctx.platform ?? process.platform)
21335
- };
21336
- return ctx;
21337
- }
21338
- async function askOnTerminal(question) {
21339
- if (!process.stdin.isTTY) return "";
21340
- const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
21341
- try {
21342
- return await new Promise((resolve) => rl.question(question, resolve));
21343
- } finally {
21344
- rl.close();
21943
+ // ../shared/src/resume.ts
21944
+ var RESUME_TOOLS = ["claude", "codex"];
21945
+ var RESUME_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
21946
+ var isResumeTool = (tool) => RESUME_TOOLS.includes(tool);
21947
+ function resumeArgv(tool, sessionId) {
21948
+ if (!sessionId || !RESUME_ID.test(sessionId) || !isResumeTool(tool)) return null;
21949
+ switch (tool) {
21950
+ case "claude":
21951
+ return ["claude", "--resume", sessionId];
21952
+ case "codex":
21953
+ return ["codex", "resume", sessionId];
21345
21954
  }
21346
21955
  }
21347
- function webUrl(url2) {
21348
- let u;
21349
- try {
21350
- u = new URL(url2);
21351
- } catch {
21352
- throw new Error("not a URL");
21956
+
21957
+ // ../shared/src/demo/script.ts
21958
+ var DEMO_LOOP_S = 180;
21959
+ var DEMO_LOOP_MS = DEMO_LOOP_S * 1e3;
21960
+ var DEMO_QUESTION = {
21961
+ agentName: "nova",
21962
+ agentLabel: "nova \xB7 Codex",
21963
+ sessionId: "9002",
21964
+ taskKey: "HIVE-146",
21965
+ taskTitle: "Remove the v1 export API",
21966
+ askedAtS: 40,
21967
+ /** After this the script moves on by itself (nova takes the default) if nobody answered. */
21968
+ resumesAtS: 100,
21969
+ text: "Keep the old v1 export route for one more release, or remove it now?",
21970
+ quickAnswers: ["Keep it one more release", "Remove it now"]
21971
+ };
21972
+ var MAIN = {
21973
+ "1": {
21974
+ id: "9001",
21975
+ steps: [
21976
+ { at: 0, state: "working", line: "Reading the failing checkout spec", task: "138", repo: "acme/shop-web", branch: "fix/checkout-rounding" },
21977
+ { at: 20, state: "working", line: "Fixing the rounding in total.ts", task: "138", repo: "acme/shop-web", branch: "fix/checkout-rounding" },
21978
+ { at: 50, state: "working", line: "Running the checkout tests", task: "138", repo: "acme/shop-web", branch: "fix/checkout-rounding" },
21979
+ { at: 90, state: "idle", line: "Finished HIVE-138", task: null },
21980
+ { at: 110, state: "working", line: "Claimed the CSV export, reading the reports module", task: "153", repo: "acme/api", branch: "feat/csv-export" },
21981
+ { at: 140, state: "working", line: "Writing the export endpoint", task: "153", repo: "acme/api", branch: "feat/csv-export" }
21982
+ ]
21983
+ },
21984
+ "2": {
21985
+ id: "9002",
21986
+ steps: [
21987
+ { at: 0, state: "working", line: "Reading the v1 export routes", task: "146", repo: "acme/api", branch: "chore/drop-v1-export" },
21988
+ { at: 25, state: "working", line: "Listing the callers of the old v1 export route", task: "146", repo: "acme/api", branch: "chore/drop-v1-export" },
21989
+ { at: DEMO_QUESTION.askedAtS, state: "waiting", line: DEMO_QUESTION.text, task: "146", repo: "acme/api", branch: "chore/drop-v1-export" },
21990
+ { at: DEMO_QUESTION.resumesAtS, state: "working", line: "No answer yet, keeping the route for now", task: "146", repo: "acme/api", branch: "chore/drop-v1-export" },
21991
+ { at: 150, state: "working", line: "Adding a deprecation header", task: "146", repo: "acme/api", branch: "chore/drop-v1-export" }
21992
+ ]
21993
+ },
21994
+ "3": {
21995
+ id: "9003",
21996
+ steps: [
21997
+ { at: 0, state: "working", line: "Adding retry with backoff to the webhook sender", task: "141", repo: "acme/worker", branch: "fix/webhook-retry" },
21998
+ { at: 30, state: "working", line: "Writing the retry tests", task: "141", repo: "acme/worker", branch: "fix/webhook-retry" },
21999
+ { at: 70, state: "idle", line: "Opened PR #214", task: null },
22000
+ { at: 85, state: "working", line: "Claimed the currency cache, reading the lookup code", task: "154", repo: "acme/api", branch: "perf/currency-cache" },
22001
+ { at: 125, state: "working", line: "Profiling the slow lookup", task: "154", repo: "acme/api", branch: "perf/currency-cache" }
22002
+ ]
22003
+ },
22004
+ "4": {
22005
+ id: "9004",
22006
+ steps: [
22007
+ { at: 0, state: "working", line: "Styling the settings page", task: "152", repo: "acme/shop-web", branch: "feat/dark-settings" },
22008
+ { at: 60, state: "working", line: "Updating the snapshot tests", task: "152", repo: "acme/shop-web", branch: "feat/dark-settings" },
22009
+ { at: 130, state: "working", line: "Checking contrast on the form fields", task: "152", repo: "acme/shop-web", branch: "feat/dark-settings" }
22010
+ ]
22011
+ },
22012
+ "5": {
22013
+ id: "9005",
22014
+ steps: [
22015
+ { at: 0, state: "working", line: "Moving sessions to Redis", task: "150", repo: "acme/accounts", branch: "feat/redis-sessions" },
22016
+ { at: 50, state: "working", line: "Running the session migration", task: "150", repo: "acme/accounts", branch: "feat/redis-sessions" },
22017
+ { at: 120, state: "blocked", line: "Needs the staging Redis URL to go on", task: "150", repo: "acme/accounts", branch: "feat/redis-sessions" }
22018
+ ]
21353
22019
  }
21354
- if (u.protocol !== "https:" && u.protocol !== "http:") throw new Error(`refusing to open a ${u.protocol} URL`);
21355
- return u;
21356
- }
21357
- function browserCommand(url2, platform = process.platform) {
21358
- const u = webUrl(url2);
21359
- if (platform === "win32") return { cmd: "rundll32.exe", args: ["url.dll,FileProtocolHandler", u.toString()] };
21360
- return { cmd: platform === "darwin" ? "open" : "xdg-open", args: [u.toString()] };
21361
- }
21362
- async function openBrowser(url2, platform = process.platform) {
21363
- let target;
21364
- try {
21365
- target = browserCommand(url2, platform);
21366
- } catch {
21367
- return;
22020
+ };
22021
+ var TASKS = [
22022
+ { num: 138, title: "Fix the rounding in the checkout total", repo: "shop-web", branch: "fix/checkout-rounding", priority: 1, labels: ["bug"], steps: [{ at: 0, status: "claimed", holder: "9001" }, { at: 90, status: "done", summary: "Totals now round half up, with a regression test for the 3-item cart." }] },
22023
+ { num: 141, title: "Retry failed webhook deliveries", repo: "worker", branch: "fix/webhook-retry", priority: 2, labels: [], steps: [{ at: 0, status: "claimed", holder: "9003" }, { at: 70, status: "in_review", pr: 214 }] },
22024
+ { num: 146, title: DEMO_QUESTION.taskTitle, repo: "api", branch: "chore/drop-v1-export", priority: 2, labels: ["tech-debt"], steps: [{ at: 0, status: "claimed", holder: "9002" }] },
22025
+ { num: 150, title: "Move sessions to Redis", repo: "accounts", branch: "feat/redis-sessions", priority: 1, labels: ["infra"], steps: [{ at: 0, status: "claimed", holder: "9005" }, { at: 120, status: "blocked", holder: "9005" }] },
22026
+ { num: 152, title: "Dark mode for the settings page", repo: "shop-web", branch: "feat/dark-settings", priority: 2, labels: ["ui"], steps: [{ at: 0, status: "claimed", holder: "9004" }] },
22027
+ { num: 153, title: "Add CSV export to reports", repo: "api", branch: "feat/csv-export", priority: 1, labels: ["feature"], steps: [{ at: 0, status: "ready" }, { at: 110, status: "claimed", holder: "9001" }] },
22028
+ { num: 154, title: "Cache the currency lookup", repo: "api", branch: "perf/currency-cache", priority: 2, labels: ["perf"], steps: [{ at: 0, status: "ready" }, { at: 85, status: "claimed", holder: "9003" }] },
22029
+ { num: 155, title: "Trim the Docker image", repo: "infra", branch: null, priority: 3, labels: ["chore"], steps: [{ at: 0, status: "ready" }] },
22030
+ { num: 156, title: "Handle the empty-cart edge case", repo: "shop-web", branch: null, priority: 2, labels: ["bug"], steps: [{ at: 0, status: "ready" }] },
22031
+ { num: 140, title: "Fix the flaky login test", repo: "shop-web", branch: "fix/login-flake", priority: 2, labels: ["test"], steps: [{ at: 0, status: "in_review", pr: 212 }] },
22032
+ { num: 131, title: "Index orders by customer", repo: "api", branch: "perf/orders-index", priority: 2, labels: ["perf"], steps: [{ at: 0, status: "done", summary: "Added the index; the order list is 6x faster." }], doneAgoS: 20 * 60 },
22033
+ { num: 130, title: "Upgrade to React 19", repo: "shop-web", branch: "chore/react-19", priority: 2, labels: ["chore"], steps: [{ at: 0, status: "done", summary: "Upgraded with no code changes beyond two typings." }], doneAgoS: 45 * 60 }
22034
+ ];
22035
+
22036
+ // ../shared/src/provider.ts
22037
+ var PROVIDERS = ["claude", "codex", "cursor", "gemini", "grok", "minimax", "other"];
22038
+
22039
+ // ../shared/src/api/me-floor.ts
22040
+ var providerSchema = external_exports.enum(PROVIDERS);
22041
+ var meFloorSessionSchema = external_exports.object({
22042
+ session: floorSessionSchema,
22043
+ agent: floorAgentSchema,
22044
+ user: floorUserSchema,
22045
+ provider: providerSchema
22046
+ });
22047
+ var meFloorProjectSchema = external_exports.object({
22048
+ id: entityIdSchema,
22049
+ key: external_exports.string(),
22050
+ name: external_exports.string(),
22051
+ /** Main sessions with their subagents nested. Cut at the snapshot-wide session cap. */
22052
+ sessions: external_exports.array(meFloorSessionSchema),
22053
+ /** Every status is present (zero when empty); archived tasks do not count. */
22054
+ task_counts: external_exports.record(external_exports.enum(TASK_STATUSES), external_exports.number().int().nonnegative()),
22055
+ /** Items in this project that wait on the caller (what they can answer in the inbox). */
22056
+ needs_you: external_exports.number().int().nonnegative()
22057
+ });
22058
+ var meFloorSchema = external_exports.object({
22059
+ projects: external_exports.array(meFloorProjectSchema),
22060
+ truncated: external_exports.boolean(),
22061
+ /** Pass it as `Last-Event-ID` (or `?last_event_id=`) to `/me/stream`: the stream then replays only what came after this snapshot. */
22062
+ last_event_id: external_exports.string().nullable(),
22063
+ server_time: isoTimeSchema
22064
+ });
22065
+ var withProject = (shape) => external_exports.object({ ...shape, project_id: entityIdSchema });
22066
+ var meStreamPayloads = {
22067
+ session: withProject(floorStreamPayloads.session.shape),
22068
+ session_end: withProject(floorStreamPayloads.session_end.shape),
22069
+ task: withProject(floorStreamPayloads.task.shape),
22070
+ task_event: withProject(floorStreamPayloads.task_event.shape),
22071
+ notification: withProject(floorStreamPayloads.notification.shape),
22072
+ membership_revoked: floorStreamPayloads.membership_revoked,
22073
+ resync: external_exports.object({ project_id: entityIdSchema.optional() })
22074
+ };
22075
+ var ME_STREAM_EVENTS = Object.keys(meStreamPayloads);
22076
+
22077
+ // ../shared/src/api/avatar.ts
22078
+ var PRESET_IDS = ["linen", "sand", "honey", "olive", "umber", "ebony"];
22079
+ var hexColor = external_exports.string().regex(/^#[0-9a-f]{6}$/i);
22080
+ var avatarSpecSchema = external_exports.object({
22081
+ v: external_exports.literal(1),
22082
+ kind: external_exports.enum(["hive", "vrm"]),
22083
+ preset: external_exports.enum(PRESET_IDS),
22084
+ colors: external_exports.object({
22085
+ skin: hexColor,
22086
+ hair: hexColor,
22087
+ top: hexColor,
22088
+ bottom: hexColor,
22089
+ accent: hexColor
22090
+ }).strict(),
22091
+ /** Hair shape, 0 through 3. */
22092
+ hair: external_exports.number().int().min(0).max(3),
22093
+ glasses: external_exports.boolean(),
22094
+ /** Outfit, 0 through 2 (tee, hoodie, jacket). */
22095
+ outfit: external_exports.number().int().min(0).max(2)
22096
+ }).strict();
22097
+ var PRESETS = [
22098
+ { v: 1, kind: "hive", preset: "linen", colors: { skin: "#f6d7c3", hair: "#c4a574", top: "#f0c14b", bottom: "#3e4c5e", accent: "#e39b2b" }, hair: 0, glasses: false, outfit: 0 },
22099
+ { v: 1, kind: "hive", preset: "sand", colors: { skin: "#e8c4a2", hair: "#6b3e26", top: "#d9784a", bottom: "#2f3b4a", accent: "#c45c26" }, hair: 1, glasses: true, outfit: 1 },
22100
+ { v: 1, kind: "hive", preset: "honey", colors: { skin: "#d7a56a", hair: "#3b2414", top: "#e8b84a", bottom: "#4a3b2a", accent: "#f2d48a" }, hair: 2, glasses: false, outfit: 2 },
22101
+ { v: 1, kind: "hive", preset: "olive", colors: { skin: "#c48a5a", hair: "#1c1c1c", top: "#5e7a4a", bottom: "#2c3330", accent: "#c9a227" }, hair: 3, glasses: true, outfit: 0 },
22102
+ { v: 1, kind: "hive", preset: "umber", colors: { skin: "#8d5524", hair: "#2a1a10", top: "#6b3a4a", bottom: "#1e2430", accent: "#d4a017" }, hair: 1, glasses: false, outfit: 1 },
22103
+ { v: 1, kind: "hive", preset: "ebony", colors: { skin: "#4a2c20", hair: "#0e0e0e", top: "#243044", bottom: "#1a1e24", accent: "#e0b050" }, hair: 2, glasses: true, outfit: 2 }
22104
+ ];
22105
+ var DEFAULT_SPEC = PRESETS[0];
22106
+ var meAvatarResponseSchema = external_exports.object({ spec: avatarSpecSchema.nullable() }).strict();
22107
+
22108
+ // ../shared/src/api/hive.ts
22109
+ var HIVE_INVITE_MAX_USES = 20;
22110
+ var iso = external_exports.string();
22111
+ var login = external_exports.string().regex(/^@?[A-Za-z0-9](?:[A-Za-z0-9-]{0,38})$/, "not a GitHub login");
22112
+ var hiveCreateInviteBody = external_exports.object({
22113
+ github_login: login.optional(),
22114
+ max_uses: external_exports.number().int().min(1).max(HIVE_INVITE_MAX_USES).optional()
22115
+ }).strict();
22116
+ var hiveInviteSchema = external_exports.object({
22117
+ id: idSchema,
22118
+ github_login: external_exports.string().nullable(),
22119
+ created_at: iso,
22120
+ expires_at: iso,
22121
+ max_uses: external_exports.number().int(),
22122
+ uses: external_exports.number().int(),
22123
+ revoked_at: iso.nullable()
22124
+ }).strict();
22125
+ var hiveCreateInviteResponse = external_exports.object({ invite: hiveInviteSchema, token: external_exports.string() }).strict();
22126
+ var hiveInviteListResponse = external_exports.object({ items: external_exports.array(hiveInviteSchema) }).strict();
22127
+ var hiveGuestSchema = external_exports.object({ user_id: idSchema, login: external_exports.string(), avatar_url: external_exports.string().nullable(), created_at: iso }).strict();
22128
+ var hiveGuestListResponse = external_exports.object({ items: external_exports.array(hiveGuestSchema) }).strict();
22129
+ var HIVE_AUDIT_ACTIONS = ["invite.create", "invite.revoke", "join", "leave", "remove", "close"];
22130
+ var hiveAuditEntrySchema = external_exports.object({
22131
+ id: idSchema,
22132
+ actor_id: idSchema.nullable(),
22133
+ actor_login: external_exports.string().nullable(),
22134
+ action: external_exports.enum(HIVE_AUDIT_ACTIONS),
22135
+ /** The invite (invite.*) or the person (join, leave, remove); null for close. */
22136
+ target_id: idSchema.nullable(),
22137
+ at: iso
22138
+ }).strict();
22139
+ var hiveAuditListResponse = external_exports.object({ items: external_exports.array(hiveAuditEntrySchema) }).strict();
22140
+ var hiveJoinBody = external_exports.union([
22141
+ external_exports.object({ token: external_exports.string().min(16).max(128) }).strict(),
22142
+ external_exports.object({ invite_id: idSchema }).strict()
22143
+ ]);
22144
+ var hiveJoinResponse = external_exports.object({ owner_id: idSchema, owner_login: external_exports.string() }).strict();
22145
+ var hiveCloseResponse = external_exports.object({ ok: external_exports.literal(true), removed: external_exports.number().int().nonnegative() }).strict();
22146
+ var hiveMembershipsResponse = external_exports.object({
22147
+ hives: external_exports.array(external_exports.object({ owner_id: idSchema, owner_login: external_exports.string(), role: external_exports.enum(["owner", "guest"]) }).strict()),
22148
+ invites: external_exports.array(external_exports.object({ id: idSchema, owner_id: idSchema, owner_login: external_exports.string(), expires_at: iso }).strict())
22149
+ }).strict();
22150
+ var hiveTurnResponse = external_exports.object({
22151
+ iceServers: external_exports.array(external_exports.object({ urls: external_exports.array(external_exports.string()), username: external_exports.string(), credential: external_exports.string() }).strict()),
22152
+ ttl: external_exports.number().int().nonnegative()
22153
+ }).strict();
22154
+ var PRESENCE_MAX_SIGNAL_BYTES = 10 * 1024;
22155
+ var PRESENCE_MAX_SDP_CHARS = 8 * 1024;
22156
+ var PRESENCE_WORLD_LIMIT_M = 40;
22157
+ var PRESENCE_DECIMALS = { position: 3, rotation: 4, blend: 2 };
22158
+ function quantise(v, decimals) {
22159
+ const f = 10 ** decimals;
22160
+ return Math.round(v * f) / f;
22161
+ }
22162
+ var isQuantised = (v, decimals) => Number.isFinite(v) && quantise(v, decimals) === v;
22163
+ var q = (decimals, min, max) => external_exports.number().min(min).max(max).refine((v) => isQuantised(v, decimals), `at most ${decimals} decimals`);
22164
+ var pos = q(PRESENCE_DECIMALS.position, -PRESENCE_WORLD_LIMIT_M, PRESENCE_WORLD_LIMIT_M);
22165
+ var rot = q(PRESENCE_DECIMALS.rotation, -1, 1);
22166
+ var yaw = q(PRESENCE_DECIMALS.rotation, -Math.PI, Math.PI);
22167
+ var blend = q(PRESENCE_DECIMALS.blend, 0, 1);
22168
+ var unitQuat = (q4) => Math.abs(Math.hypot(q4[0], q4[1], q4[2], q4[3]) - 1) <= 1e-3;
22169
+ var posQuat = external_exports.tuple([pos, pos, pos, rot, rot, rot, rot]).refine((t) => unitQuat(t.slice(3)), "quaternion is not unit length");
22170
+ var PRESENCE_FACE_KEYS = [
22171
+ "jawOpen",
22172
+ "mouthClose",
22173
+ "mouthFunnel",
22174
+ "mouthPucker",
22175
+ "mouthSmileLeft",
22176
+ "mouthSmileRight",
22177
+ "eyeBlinkLeft",
22178
+ "eyeBlinkRight",
22179
+ "browInnerUp",
22180
+ "browDownLeft",
22181
+ "browDownRight",
22182
+ "cheekPuff"
22183
+ ];
22184
+ var faceSchema = external_exports.object(Object.fromEntries(PRESENCE_FACE_KEYS.map((k) => [k, blend.optional()]))).strict();
22185
+ var u31 = external_exports.number().int().min(0).max(2 ** 31 - 1);
22186
+ var poseFields = {
22187
+ seq: u31,
22188
+ /** Sender clock, ms; only for ordering and interpolation on the receiver. */
22189
+ t: u31,
22190
+ root: external_exports.tuple([pos, pos, pos, yaw]),
22191
+ head: posQuat,
22192
+ lh: posQuat.nullable(),
22193
+ rh: posQuat.nullable(),
22194
+ fingers: external_exports.array(blend).length(10).nullable(),
22195
+ face: faceSchema.nullable(),
22196
+ speaking: external_exports.union([external_exports.literal(0), external_exports.literal(1)])
22197
+ };
22198
+ var userId = idSchema;
22199
+ var sdp = external_exports.string().min(1).max(PRESENCE_MAX_SDP_CHARS);
22200
+ var iceCandidate = external_exports.object({
22201
+ candidate: external_exports.string().max(512),
22202
+ sdpMid: external_exports.string().max(32).nullable(),
22203
+ sdpMLineIndex: external_exports.number().int().min(0).max(31).nullable()
22204
+ }).strict();
22205
+ var signalFields = (extra) => [
22206
+ external_exports.object({ type: external_exports.literal("signal"), ...extra, kind: external_exports.literal("offer"), sdp }).strict(),
22207
+ external_exports.object({ type: external_exports.literal("signal"), ...extra, kind: external_exports.literal("answer"), sdp }).strict(),
22208
+ external_exports.object({ type: external_exports.literal("signal"), ...extra, kind: external_exports.literal("ice"), candidate: iceCandidate }).strict()
22209
+ ];
22210
+ var presenceHelloSchema = external_exports.object({ type: external_exports.literal("hello"), avatar: avatarSpecSchema }).strict();
22211
+ var presencePoseSchema = external_exports.object({ type: external_exports.literal("pose"), ...poseFields }).strict();
22212
+ var presenceSignalSchema = external_exports.union(signalFields({ to: userId }));
22213
+ var presenceLeaveSchema = external_exports.object({ type: external_exports.literal("leave") }).strict();
22214
+ var presenceClientMessage = external_exports.union([presenceHelloSchema, presencePoseSchema, presenceSignalSchema, presenceLeaveSchema]);
22215
+ var presenceMemberSchema = external_exports.object({ id: userId, login: external_exports.string().max(39), avatar: avatarSpecSchema.nullable(), role: external_exports.enum(["owner", "guest"]) }).strict();
22216
+ var presenceServerMessage = external_exports.union([
22217
+ /** First frame after the upgrade: who you are and who is here (including you). */
22218
+ external_exports.object({ type: external_exports.literal("roster"), you: userId, members: external_exports.array(presenceMemberSchema) }).strict(),
22219
+ /** Someone arrived or changed their avatar (an upsert). */
22220
+ external_exports.object({ type: external_exports.literal("join"), member: presenceMemberSchema }).strict(),
22221
+ external_exports.object({ type: external_exports.literal("leave"), id: userId }).strict(),
22222
+ external_exports.object({ type: external_exports.literal("pose"), from: userId, ...poseFields }).strict(),
22223
+ ...signalFields({ from: userId }),
22224
+ /** Sent just before the server closes this socket. */
22225
+ external_exports.object({ type: external_exports.literal("kick"), reason: external_exports.enum(["removed", "closed", "replaced"]) }).strict()
22226
+ ]);
22227
+
22228
+ // ../shared/src/api/orchestrator-stream.ts
22229
+ var ORCH_RUNTIMES = ["claude", "codex", "cursor"];
22230
+ var orchRuntimeSchema = external_exports.enum(ORCH_RUNTIMES);
22231
+ var ORCH_MODES = ["spawned", "attached"];
22232
+ var ORCH_EFFORTS = ["low", "medium", "high", "xhigh", "max"];
22233
+ var ORCH_POWERS = ["safe", "full"];
22234
+ var ORCH_PERMISSION_MODES = ["default", "acceptEdits", "bypassPermissions"];
22235
+ var ORCH_CWD_MODES = ["auto", "stable"];
22236
+ var ORCH_STATES = ["starting", "idle", "working", "waiting_input", "stopped", "crashed"];
22237
+ var ORCH_LIMITS = {
22238
+ messageText: 32e3,
22239
+ sendText: 4e3,
22240
+ /** The first message of a fresh session (`brief`), in UTF-8 bytes. */
22241
+ briefBytes: 16 * 1024,
22242
+ toolSummary: 2048,
22243
+ thinkingText: 8e3,
22244
+ questionSummary: 1024,
22245
+ optionCount: 8,
22246
+ optionText: 200,
22247
+ errorMessage: 1e3,
22248
+ batch: 100,
22249
+ /** An answer to a question times out into a deny after this long. */
22250
+ questionTimeoutSec: 600,
22251
+ /** A `send` to a machine not seen this recently answers 409 `machine_offline`. */
22252
+ machineOfflineSec: 60,
22253
+ /** A queued orchestrator command not taken by the machine in this time expires. */
22254
+ commandTtlSec: 120,
22255
+ historyDays: 30,
22256
+ historyMaxEvents: 5e3
22257
+ };
22258
+ var id = external_exports.string().regex(/^[A-Za-z0-9][A-Za-z0-9._:@/-]{0,127}$/, "an id");
22259
+ var modelId = external_exports.string().regex(/^[A-Za-z0-9][A-Za-z0-9._:/[\]-]{0,99}$/, "a model id");
22260
+ var str = (max) => external_exports.string().max(max);
22261
+ var ORCH_EVENT_TYPES = ["message", "thinking", "tool_use", "tool_result", "status", "question", "error", "usage"];
22262
+ var messageBody = external_exports.strictObject({
22263
+ role: external_exports.enum(["assistant", "user"]),
22264
+ text: str(ORCH_LIMITS.messageText),
22265
+ msg_id: id,
22266
+ /** Set on user rows, which the server writes itself when it accepts a `send`. */
22267
+ from: external_exports.strictObject({ user_id: idSchema, name: str(100) }).optional(),
22268
+ /** Set when the server sent the row for the user: a batch of fleet reports, or a scheduled check-in. */
22269
+ via: external_exports.enum(["bridge", "schedule"]).optional()
22270
+ });
22271
+ var machineMessageBody = messageBody.omit({ from: true, role: true, via: true }).extend({ role: external_exports.literal("assistant") });
22272
+ var thinkingBody = external_exports.strictObject({ text: str(ORCH_LIMITS.thinkingText) });
22273
+ var toolUseBody = external_exports.strictObject({ tool_use_id: id, name: str(100), input_summary: str(ORCH_LIMITS.toolSummary) });
22274
+ var toolResultBody = external_exports.strictObject({ tool_use_id: id, ok: external_exports.boolean(), summary: str(ORCH_LIMITS.toolSummary) });
22275
+ var statusBody = external_exports.strictObject({
22276
+ state: external_exports.enum(ORCH_STATES),
22277
+ detail: str(300).optional(),
22278
+ /** The runtime's own session id (Claude's `system/init`), kept so a restart can `--resume` it. */
22279
+ external_id: id.optional()
22280
+ });
22281
+ var questionBody = external_exports.strictObject({
22282
+ question_id: external_exports.string().regex(/^[A-Za-z0-9_-]{8,128}$/, "a question id"),
22283
+ kind: external_exports.enum(["permission", "ask"]),
22284
+ tool: str(100).optional(),
22285
+ summary: str(ORCH_LIMITS.questionSummary),
22286
+ options: external_exports.array(str(ORCH_LIMITS.optionText)).max(ORCH_LIMITS.optionCount).optional()
22287
+ });
22288
+ var errorBody = external_exports.strictObject({ code: str(60), message: str(ORCH_LIMITS.errorMessage) });
22289
+ var usageBody = external_exports.strictObject({
22290
+ input_tokens: external_exports.number().int().nonnegative(),
22291
+ output_tokens: external_exports.number().int().nonnegative(),
22292
+ cache_read: external_exports.number().int().nonnegative().optional(),
22293
+ cost_usd: external_exports.number().nonnegative().optional(),
22294
+ duration_ms: external_exports.number().int().nonnegative()
22295
+ });
22296
+ var orchEventIn = external_exports.discriminatedUnion("type", [
22297
+ external_exports.strictObject({ src_seq: external_exports.number().int().positive(), type: external_exports.literal("message"), body: machineMessageBody }),
22298
+ external_exports.strictObject({ src_seq: external_exports.number().int().positive(), type: external_exports.literal("thinking"), body: thinkingBody }),
22299
+ external_exports.strictObject({ src_seq: external_exports.number().int().positive(), type: external_exports.literal("tool_use"), body: toolUseBody }),
22300
+ external_exports.strictObject({ src_seq: external_exports.number().int().positive(), type: external_exports.literal("tool_result"), body: toolResultBody }),
22301
+ external_exports.strictObject({ src_seq: external_exports.number().int().positive(), type: external_exports.literal("status"), body: statusBody }),
22302
+ external_exports.strictObject({ src_seq: external_exports.number().int().positive(), type: external_exports.literal("question"), body: questionBody }),
22303
+ external_exports.strictObject({ src_seq: external_exports.number().int().positive(), type: external_exports.literal("error"), body: errorBody }),
22304
+ external_exports.strictObject({ src_seq: external_exports.number().int().positive(), type: external_exports.literal("usage"), body: usageBody })
22305
+ ]);
22306
+ var orchEventsBatchBody = external_exports.strictObject({ events: external_exports.array(orchEventIn).min(1).max(ORCH_LIMITS.batch) });
22307
+ var orchEventsAckSchema = external_exports.strictObject({ acked_src_seq: external_exports.number().int().nonnegative() });
22308
+ var orchEventSchema = external_exports.object({
22309
+ seq: external_exports.number().int().positive(),
22310
+ at: isoTimeSchema,
22311
+ type: external_exports.enum(ORCH_EVENT_TYPES),
22312
+ body: external_exports.record(external_exports.string(), external_exports.unknown())
22313
+ });
22314
+ var orchHistorySchema = external_exports.object({ events: external_exports.array(orchEventSchema), has_more: external_exports.boolean() });
22315
+ var orchRuntimeInfoSchema = external_exports.strictObject({
22316
+ runtime: orchRuntimeSchema,
22317
+ version: str(40).optional(),
22318
+ logins: external_exports.array(external_exports.strictObject({
22319
+ id,
22320
+ label: str(120),
22321
+ /** Whether this login can start a session. A service from before this field leaves it out. Never a token or an email. */
22322
+ usage: external_exports.enum(["ok", "limited"]).optional(),
22323
+ /** When a limited login expects to be free again, in the machine's own short words. */
22324
+ resets: str(40).optional()
22325
+ })).max(20)
22326
+ });
22327
+ var orchRuntimesSchema = external_exports.array(orchRuntimeInfoSchema).max(3);
22328
+ var orchMachineInfoBody = external_exports.strictObject({
22329
+ enabled: external_exports.boolean(),
22330
+ runtimes: orchRuntimesSchema,
22331
+ /**
22332
+ * True only after the machine's owner ran `hivefloor orch enable --full` on it. The server never sets it: it is the
22333
+ * local consent to full power. A service older than this field leaves it out.
22334
+ */
22335
+ full_allowed: external_exports.boolean().optional()
22336
+ });
22337
+ var orchCapabilitiesSchema = external_exports.strictObject({ answer: external_exports.boolean(), interrupt: external_exports.boolean() });
22338
+ var briefText = external_exports.string().transform((s, ctx) => {
22339
+ const t = cleanOrchText(s).trim();
22340
+ if (t === "" || new TextEncoder().encode(t).length > ORCH_LIMITS.briefBytes) {
22341
+ ctx.addIssue({ code: "custom", message: `must be 1 to ${ORCH_LIMITS.briefBytes} bytes` });
22342
+ return external_exports.NEVER;
21368
22343
  }
21369
- await new Promise((resolve) => {
21370
- try {
21371
- const child = spawn(target.cmd, target.args, { stdio: "ignore", detached: true });
21372
- child.on("error", () => resolve());
21373
- child.unref();
21374
- setTimeout(resolve, 200);
21375
- } catch {
21376
- resolve();
21377
- }
21378
- });
21379
- }
21380
- function hostFromEnv(env) {
21381
- return normalizeHost(env.HIVEFLOOR_URL || DEFAULT_HOST);
21382
- }
21383
- function normalizeHost(input2) {
21384
- let h = input2.trim();
21385
- if (!/^https?:\/\//i.test(h)) h = `https://${h}`;
21386
- const u = new URL(h);
21387
- return u.origin;
21388
- }
21389
- function isLoopbackHost(hostname3) {
21390
- const h = hostname3.toLowerCase();
21391
- return h === "localhost" || h === "127.0.0.1" || h === "[::1]" || h === "::1";
21392
- }
21393
- function isSecureUrl(u) {
21394
- if (u.protocol === "https:") return true;
21395
- return u.protocol === "http:" && isLoopbackHost(u.hostname);
21396
- }
21397
- var machineName = () => os.hostname().split(".")[0] || "machine";
21398
- function runCmd(bin, args, opts = {}) {
21399
- return new Promise((resolve) => {
21400
- execFile(bin, args, { cwd: opts.cwd, env: opts.env, timeout: opts.timeoutMs ?? 2e4, maxBuffer: 1 << 20 }, (error62, stdout, stderr) => {
21401
- if (!error62) return resolve({ code: 0, stdout: String(stdout), stderr: String(stderr) });
21402
- const code = typeof error62.code === "number" ? error62.code : 127;
21403
- resolve({ code, stdout: String(stdout), stderr: String(stderr) });
21404
- });
21405
- });
22344
+ return t;
22345
+ });
22346
+ var startOptions = {
22347
+ power: external_exports.enum(ORCH_POWERS).optional(),
22348
+ /** Full power only. */
22349
+ permission_mode: external_exports.enum(ORCH_PERMISSION_MODES).optional(),
22350
+ /** Full power only: start Claude Code with `--chrome`. */
22351
+ chrome: external_exports.boolean().optional(),
22352
+ /** Keep the machine awake while the session's process lives (macOS; ignored elsewhere). */
22353
+ keep_awake: external_exports.boolean().optional(),
22354
+ /** `mode: 'attached'` only. */
22355
+ cwd: external_exports.enum(ORCH_CWD_MODES).optional()
22356
+ };
22357
+ var configureSessionBody = external_exports.strictObject({
22358
+ machine_id: idSchema,
22359
+ runtime: orchRuntimeSchema,
22360
+ model: modelId,
22361
+ effort: external_exports.enum(ORCH_EFFORTS),
22362
+ login_id: id.optional(),
22363
+ mode: external_exports.enum(ORCH_MODES).default("spawned"),
22364
+ /** The runtime's own session id, for `mode: 'attached'`: the session to resume. */
22365
+ external_id: id.optional(),
22366
+ ...startOptions,
22367
+ /** `mode: 'spawned'` only: starts a new session (never resumes the last one) and sends this as its first message. */
22368
+ brief: briefText.optional()
22369
+ }).superRefine((v, ctx) => {
22370
+ const full = v.power === "full";
22371
+ if (v.mode === "attached" && !v.external_id) ctx.addIssue({ code: "custom", path: ["external_id"], message: "attach needs the session to attach to" });
22372
+ if (v.mode === "spawned" && v.external_id) ctx.addIssue({ code: "custom", path: ["external_id"], message: "only attach takes a session id" });
22373
+ if (v.mode === "attached" && !full) ctx.addIssue({ code: "custom", path: ["power"], message: "attach needs full power" });
22374
+ if (!full && v.permission_mode !== void 0 && v.permission_mode !== "default") ctx.addIssue({ code: "custom", path: ["permission_mode"], message: "only full power takes a permission mode" });
22375
+ if (!full && v.chrome === true) ctx.addIssue({ code: "custom", path: ["chrome"], message: "only full power takes chrome" });
22376
+ if (v.mode !== "attached" && v.cwd !== void 0 && v.cwd !== "auto") ctx.addIssue({ code: "custom", path: ["cwd"], message: "only attach takes a folder choice" });
22377
+ if (v.mode === "attached" && v.brief !== void 0) ctx.addIssue({ code: "custom", path: ["brief"], message: "only a new session takes a brief" });
22378
+ });
22379
+ var orchSessionViewSchema = external_exports.object({
22380
+ id: external_exports.string(),
22381
+ machine: external_exports.object({ id: external_exports.string(), name: external_exports.string() }),
22382
+ runtime: orchRuntimeSchema,
22383
+ model: external_exports.string(),
22384
+ effort: external_exports.enum(ORCH_EFFORTS),
22385
+ login_label: external_exports.string().nullable(),
22386
+ mode: external_exports.enum(ORCH_MODES),
22387
+ power: external_exports.enum(ORCH_POWERS).optional(),
22388
+ permission_mode: external_exports.enum(ORCH_PERMISSION_MODES).optional(),
22389
+ chrome: external_exports.boolean().optional(),
22390
+ keep_awake: external_exports.boolean().optional(),
22391
+ cwd: external_exports.enum(ORCH_CWD_MODES).optional(),
22392
+ state: external_exports.enum(ORCH_STATES),
22393
+ /** False while the machine has not been seen for `machineOfflineSec`. */
22394
+ machine_online: external_exports.boolean(),
22395
+ /** When the machine last reported (o159 G: the health banner says how long it has been asleep). */
22396
+ machine_last_seen_at: isoTimeSchema.nullable().optional(),
22397
+ /** Stopped or crashed, spawned, and the runtime gave its own session id: `POST /orchestrator/session/resume` continues that same session. */
22398
+ resumable: external_exports.boolean().optional(),
22399
+ capabilities: orchCapabilitiesSchema,
22400
+ last_event_seq: external_exports.number().int().nonnegative(),
22401
+ created_at: isoTimeSchema
22402
+ });
22403
+ var orchSessionResponseSchema = external_exports.object({ session: orchSessionViewSchema.nullable() });
22404
+ var ORCH_MACHINE_REASONS = ["offline", "orch_off", "no_claude"];
22405
+ var orchMachineReasonSchema = external_exports.enum(ORCH_MACHINE_REASONS);
22406
+ var orchOptionsSchema = external_exports.object({
22407
+ machines: external_exports.array(external_exports.object({ id: external_exports.string(), name: external_exports.string(), online: external_exports.boolean(), orchestrator_enabled: external_exports.boolean(), full_allowed: external_exports.boolean().optional(), runtimes: orchRuntimesSchema, reason: orchMachineReasonSchema.optional().catch(void 0) })),
22408
+ models: external_exports.record(orchRuntimeSchema, external_exports.array(external_exports.strictObject({ id: external_exports.string(), label: external_exports.string() }))),
22409
+ efforts: external_exports.array(external_exports.enum(ORCH_EFFORTS))
22410
+ });
22411
+ var idempotencyKey = external_exports.string().min(8).max(64);
22412
+ function cleanOrchText(input2) {
22413
+ return input2.normalize("NFC").replace(/\r\n?/g, "\n").replace(/[\u0000-\u0008\u000B-\u001F\u007F-\u009F]/g, "");
21406
22414
  }
22415
+ var sendText = external_exports.string().transform((s, ctx) => {
22416
+ const t = cleanOrchText(s).trim();
22417
+ if (t === "" || Array.from(t).length > ORCH_LIMITS.sendText) {
22418
+ ctx.addIssue({ code: "custom", message: `must be 1 to ${ORCH_LIMITS.sendText} characters` });
22419
+ return external_exports.NEVER;
22420
+ }
22421
+ return t;
22422
+ });
22423
+ var sendBody = external_exports.strictObject({ text: sendText, idempotency_key: idempotencyKey });
22424
+ var answerBody = external_exports.strictObject({ question_id: questionBody.shape.question_id, choice: str(ORCH_LIMITS.optionText).min(1), idempotency_key: idempotencyKey });
22425
+ var orchCommandSchema = external_exports.discriminatedUnion("kind", [
22426
+ external_exports.strictObject({
22427
+ id: external_exports.string(),
22428
+ orch_id: external_exports.string(),
22429
+ kind: external_exports.literal("orch_start"),
22430
+ args: external_exports.strictObject({
22431
+ runtime: orchRuntimeSchema,
22432
+ model: modelId,
22433
+ effort: external_exports.enum(ORCH_EFFORTS),
22434
+ login_id: id.nullable(),
22435
+ /** The session to `--resume` after a restart (reported earlier as `status.external_id`). */
22436
+ resume_id: id.nullable(),
22437
+ mode: external_exports.enum(ORCH_MODES),
22438
+ external_id: id.nullable(),
22439
+ ...startOptions,
22440
+ /** Sent as the first message when the session starts new (never on a resume). Already cleaned by the server; the machine cleans it again. */
22441
+ brief: external_exports.string().max(ORCH_LIMITS.briefBytes).nullable().optional()
22442
+ })
22443
+ }),
22444
+ external_exports.strictObject({ id: external_exports.string(), orch_id: external_exports.string(), kind: external_exports.literal("orch_send"), args: external_exports.strictObject({ text: external_exports.string(), msg_id: id }) }),
22445
+ external_exports.strictObject({ id: external_exports.string(), orch_id: external_exports.string(), kind: external_exports.literal("orch_answer"), args: external_exports.strictObject({ question_id: external_exports.string(), choice: external_exports.string() }) }),
22446
+ external_exports.strictObject({ id: external_exports.string(), orch_id: external_exports.string(), kind: external_exports.literal("orch_interrupt"), args: external_exports.strictObject({}) }),
22447
+ external_exports.strictObject({ id: external_exports.string(), orch_id: external_exports.string(), kind: external_exports.literal("orch_stop"), args: external_exports.strictObject({}) })
22448
+ ]);
22449
+ var orchCommandsResponseSchema = external_exports.object({ commands: external_exports.array(orchCommandSchema).max(10) });
22450
+
22451
+ // ../shared/src/api/orch-bridge.ts
22452
+ var ORCH_BRIDGE_LIMITS = {
22453
+ linesPerPost: 20,
22454
+ lineText: 2e3,
22455
+ /** Lines waiting for one user; past this a post is refused until delivery catches up. */
22456
+ pendingPerUser: 500,
22457
+ /** Same tag and text again within this window is a duplicate. */
22458
+ dedupeHours: 24,
22459
+ minGapMs: 6e5,
22460
+ /** NEEDS-YOU / URGENT may wake the session inside the gap at most this often per hour; past it they wait for the gap. */
22461
+ priorityWakesPerHour: 6,
22462
+ /** Undelivered reports older than this are dropped, so a long stop does not replay stale news. */
22463
+ pendingHours: 24,
22464
+ schedulesPerUser: 50,
22465
+ schedulePrompt: 3900,
22466
+ /** Check-ins one schedule may send per UTC day, whatever its rule says. */
22467
+ firesPerDay: 96,
22468
+ /** A due check-in waits for idle this long, then is skipped for that slot. */
22469
+ lateMs: 15 * 6e4
22470
+ };
22471
+ var ORCH_SCHEDULE_TARGETS = ["orchestrator"];
22472
+ var bridgeLineSchema = external_exports.strictObject({
22473
+ tag: external_exports.string().regex(/^[A-Z0-9_-]{1,32}$/),
22474
+ text: external_exports.string().trim().min(1).max(ORCH_BRIDGE_LIMITS.lineText).refine((t) => !/[\r\n]/.test(t), "One line only."),
22475
+ at: external_exports.iso.datetime({ offset: true }).optional()
22476
+ });
22477
+ var bridgeBody = external_exports.strictObject({ lines: external_exports.array(bridgeLineSchema).min(1).max(ORCH_BRIDGE_LIMITS.linesPerPost) });
22478
+ var bridgeResponseSchema = external_exports.object({ accepted: external_exports.number().int(), duplicates: external_exports.number().int() });
22479
+ var scheduleIdSchema = external_exports.string().regex(/^[A-Za-z0-9_-]{8,64}$/);
22480
+ var scheduleBody = external_exports.strictObject({
22481
+ sessionTarget: external_exports.enum(ORCH_SCHEDULE_TARGETS),
22482
+ prompt: external_exports.string().max(ORCH_BRIDGE_LIMITS.schedulePrompt),
22483
+ at: external_exports.string().max(40).optional(),
22484
+ every: external_exports.strictObject({ minutes: external_exports.number().int().min(5).max(7 * 24 * 60).optional(), cron: external_exports.string().max(120).optional() }).optional(),
22485
+ tz: external_exports.string().min(1).max(64),
22486
+ enabled: external_exports.boolean()
22487
+ }).superRefine((s, ctx) => {
22488
+ const err = scheduleError({ id: "x", ...s });
22489
+ if (err) ctx.addIssue({ code: "custom", message: err });
22490
+ });
22491
+ var scheduleToggleBody = external_exports.strictObject({ enabled: external_exports.boolean() });
22492
+
22493
+ // ../shared/src/profile.ts
22494
+ var HEATMAP_METRICS = ["sessions", "agent_hours"];
22495
+ var heatmapMetricSchema = external_exports.enum(HEATMAP_METRICS);
22496
+ var profileSettingsSchema = external_exports.object({
22497
+ published: external_exports.boolean(),
22498
+ show_name: external_exports.boolean(),
22499
+ show_heatmap: external_exports.boolean(),
22500
+ show_totals: external_exports.boolean(),
22501
+ show_providers: external_exports.boolean(),
22502
+ show_live: external_exports.boolean(),
22503
+ indexable: external_exports.boolean(),
22504
+ include_team_activity: external_exports.boolean(),
22505
+ heatmap_metric: heatmapMetricSchema,
22506
+ record_history: external_exports.boolean()
22507
+ }).strict();
22508
+ var LISTING_FLAGS = ["listable", "hidden"];
22509
+ var listingFlagSchema = external_exports.enum(LISTING_FLAGS);
22510
+ var meListedProjectSchema = external_exports.object({
22511
+ project_id: idSchema,
22512
+ listing: listingFlagSchema
22513
+ }).strict();
22514
+ var meProfileResponseSchema = profileSettingsSchema.extend({
22515
+ projects: external_exports.array(meListedProjectSchema)
22516
+ }).strict();
22517
+ var listedProjectsBody = external_exports.object({ project_ids: external_exports.array(idSchema).max(200) }).strict();
22518
+ var deleteActivityBody = external_exports.object({ login: external_exports.string().min(1).max(39) }).strict();
22519
+ var heatmapSchema2 = external_exports.object({
22520
+ metric: heatmapMetricSchema,
22521
+ days: external_exports.array(external_exports.object({ day: external_exports.string(), value: external_exports.number() }).strict())
22522
+ }).strict();
22523
+ var totalsSchema = external_exports.object({
22524
+ sessions_started: external_exports.number(),
22525
+ sessions_finished: external_exports.number(),
22526
+ agent_hours: external_exports.number(),
22527
+ machines: external_exports.number(),
22528
+ longest_streak: external_exports.number(),
22529
+ current_streak: external_exports.number()
22530
+ }).strict();
22531
+ var providerSchema2 = external_exports.object({ tool: external_exports.string(), sessions: external_exports.number(), agent_hours: external_exports.number() }).strict();
22532
+ var listedProjectSchema = external_exports.object({ name: external_exports.string(), sessions: external_exports.number(), agent_hours: external_exports.number() }).strict();
22533
+ var publicProfileSchema = external_exports.object({
22534
+ login: external_exports.string(),
22535
+ avatar_url: external_exports.string().nullable(),
22536
+ since: external_exports.string(),
22537
+ name: external_exports.string().optional(),
22538
+ heatmap: heatmapSchema2.optional(),
22539
+ totals: totalsSchema.optional(),
22540
+ providers: external_exports.array(providerSchema2).optional(),
22541
+ projects: external_exports.array(listedProjectSchema).optional()
22542
+ }).strict();
22543
+ var liveSummarySchema = external_exports.object({
22544
+ agents: external_exports.number().int().nonnegative(),
22545
+ machines: external_exports.number().int().nonnegative(),
22546
+ as_of: external_exports.string()
22547
+ }).strict();
22548
+
22549
+ // ../shared/src/index.ts
22550
+ var ROLES = ["owner", "admin", "member", "viewer"];
22551
+ var roleSchema2 = external_exports.enum(ROLES);
21407
22552
 
21408
22553
  export {
22554
+ NEVER,
22555
+ safeParse,
22556
+ string2 as string,
22557
+ url,
22558
+ number2 as number,
22559
+ boolean2 as boolean,
22560
+ _null3 as _null,
22561
+ any,
22562
+ unknown,
22563
+ array,
22564
+ object,
22565
+ looseObject,
22566
+ union,
22567
+ discriminatedUnion,
22568
+ intersection,
22569
+ record,
22570
+ _enum2 as _enum,
22571
+ literal,
22572
+ optional,
22573
+ custom,
22574
+ preprocess,
22575
+ ZodIssueCode,
22576
+ iso_exports,
22577
+ coerce_exports,
21409
22578
  normalizeRemote,
21410
22579
  formatRemote,
21411
22580
  deviceCodeResponseSchema,
21412
22581
  deviceTokenErrorSchema,
21413
22582
  deviceTokenSuccessSchema,
21414
22583
  HOOK_BATCH_MAX,
22584
+ CONTROL_REPLY_MAX,
22585
+ PEEK_LINES_MAX,
22586
+ PEEK_OUTPUT_MAX,
22587
+ stripControlChars,
22588
+ cleanControlText,
22589
+ machineCommandsResponse,
22590
+ machinePromptResponse,
21415
22591
  MACHINE_HEARTBEAT_SECONDS,
21416
22592
  MACHINE_MIN_INTERVAL_SECONDS,
21417
22593
  PROFILE_KEY_RE,
22594
+ ENDED_SESSION_ID_RE,
22595
+ ENDED_SESSIONS_MAX,
21418
22596
  machineHeartbeatResponseSchema,
21419
22597
  SESSION_ACCOUNT_RE,
21420
22598
  machineTokenSuccessSchema,
@@ -21424,13 +22602,19 @@ export {
21424
22602
  redact,
21425
22603
  usageReadingSchema,
21426
22604
  parseUsageKey,
22605
+ estimateClaudeCostUsd,
21427
22606
  routeProviderFromParam,
21428
22607
  usageRouteSchema,
21429
- DEFAULT_HOST,
21430
- defaultCtx,
21431
- hostFromEnv,
21432
- normalizeHost,
21433
- isSecureUrl,
21434
- machineName,
21435
- runCmd
22608
+ KOKORO_VOICES,
22609
+ voiceFor,
22610
+ KOKORO_VOICE_ID,
22611
+ RESUME_ID,
22612
+ isResumeTool,
22613
+ resumeArgv,
22614
+ ORCH_PERMISSION_MODES,
22615
+ ORCH_LIMITS,
22616
+ orchEventIn,
22617
+ cleanOrchText,
22618
+ orchCommandSchema,
22619
+ orchCommandsResponseSchema
21436
22620
  };