@hivefloor/cli 0.1.4 → 0.1.5

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 (38) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +2 -1
  3. package/dist/{chunk-R5KDI4WI.js → chunk-3N5JYP5O.js} +7 -3
  4. package/dist/{chunk-ZC2DAKB5.js → chunk-4DRHR7LR.js} +349 -127
  5. package/dist/{chunk-PDXYOREI.js → chunk-6MDJB3BV.js} +97 -26
  6. package/dist/{chunk-QHYZBHXO.js → chunk-6XVIEX75.js} +293 -71
  7. package/dist/{chunk-DNG5CRT3.js → chunk-C627OKTW.js} +2 -2
  8. package/dist/chunk-H6NYMF2D.js +50 -0
  9. package/dist/{chunk-T7TG6WA4.js → chunk-IJRHCDIG.js} +1 -1
  10. package/dist/{chunk-SD65CIIY.js → chunk-IWIDKNWC.js} +109 -29
  11. package/dist/{chunk-UJ4BQFWV.js → chunk-J36OIJBM.js} +41 -23
  12. package/dist/{chunk-W7DROKC7.js → chunk-MZGGJ6ZS.js} +87 -13
  13. package/dist/{chunk-2BSA7LFD.js → chunk-RYGL6XU4.js} +5 -3
  14. package/dist/chunk-SOXRITAW.js +139 -0
  15. package/dist/{chunk-VNCQFFQO.js → chunk-TPMFQUAW.js} +102 -1
  16. package/dist/chunk-U6RRUAC2.js +229 -0
  17. package/dist/chunk-VX7SCIF2.js +65 -0
  18. package/dist/{chunk-O2TC3WSS.js → chunk-X6B6R32A.js} +1 -1
  19. package/dist/cli-JCBZICR3.js +243 -0
  20. package/dist/connect-2HLVPEOL.js +23 -0
  21. package/dist/{disconnect-MKRHK4CX.js → disconnect-WQMDCUXT.js} +41 -27
  22. package/dist/{hook-KR2HGVAR.js → hook-AYJNRGIY.js} +22 -8
  23. package/dist/index.js +2 -2
  24. package/dist/{link-HXBMMSG3.js → link-ORT4LID6.js} +29 -16
  25. package/dist/{machine-connect-BYHZRRRB.js → machine-connect-N52CKQEW.js} +21 -21
  26. package/dist/{mcp-N2TMD4GR.js → mcp-2SF6Y73M.js} +27 -30
  27. package/dist/{run-336BSU72.js → run-ZAZ45MKQ.js} +22 -10
  28. package/dist/{status-KBBSAADD.js → status-GOCFNO7K.js} +25 -13
  29. package/dist/{token-JDRLEV5D.js → token-EMM4AJAU.js} +15 -6
  30. package/dist/voice-F5MIS3IZ.js +262 -0
  31. package/dist/{where-KR7VWSEC.js → where-XFXRTP7E.js} +16 -7
  32. package/package.json +2 -2
  33. package/dist/chunk-2IMJECYD.js +0 -71
  34. package/dist/chunk-7KF7IQJN.js +0 -30
  35. package/dist/chunk-GT3HFFT4.js +0 -132
  36. package/dist/chunk-PY74LT2W.js +0 -41
  37. package/dist/cli-P3DYE5IR.js +0 -103
  38. package/dist/connect-ACNM5DQG.js +0 -23
@@ -19826,10 +19826,14 @@ var isoSchema = external_exports.string();
19826
19826
  var roleEnum = external_exports.enum(["owner", "admin", "member", "viewer"]);
19827
19827
  var okResponse = external_exports.object({ ok: external_exports.literal(true) }).strict();
19828
19828
  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();
19829
+ 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
19830
  var publicUserSchema = external_exports.object({ id: idSchema, login: external_exports.string(), name: external_exports.string().nullable(), avatar_url: external_exports.string().nullable() }).strict();
19831
19831
  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();
19832
+ var meProjectSchema = projectBriefSchema.extend({
19833
+ personal: external_exports.boolean(),
19834
+ /** 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. */
19835
+ owned: external_exports.boolean().optional()
19836
+ }).strict();
19833
19837
  var meResponse = external_exports.object({ user: publicUserSchema, projects: external_exports.array(meProjectSchema) }).strict();
19834
19838
  var projectSettingsViewSchema = external_exports.looseObject({ answer_blocked: external_exports.boolean().optional() });
19835
19839
  var projectTransferSchema = external_exports.object({ to_user_id: idSchema, requested_at: isoSchema.nullable() }).strict();
@@ -20150,9 +20154,21 @@ var taskCardSchema = external_exports.object({
20150
20154
  /** Tasks this one waits on (stage 2). It is claimable only when every one of them is done. */
20151
20155
  blocked_by: external_exports.array(blockerRefSchema).default([]),
20152
20156
  /** 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()
20157
+ at_risk: external_exports.boolean().optional(),
20158
+ /** A fleet lane's task (mirrored from the owner's fleet, docs/FLEET.md). Absent for the project's own and vq-mirror tasks. */
20159
+ fleet: external_exports.boolean().optional(),
20160
+ /**
20161
+ * The holder agent. Present on `GET /projects/:pid/tasks` (null when nobody holds the task).
20162
+ * A completed task keeps its holder. Absent on floor, detail and share cards.
20163
+ */
20164
+ agent: external_exports.object({ id: entityIdSchema, name: external_exports.string() }).nullable().optional(),
20165
+ /**
20166
+ * Sum of stored `task_usage.cost_usd` for this task. Null when no usage row exists.
20167
+ * Present on the task list only; absent on floor, detail and share cards.
20168
+ */
20169
+ cost_usd: external_exports.number().nonnegative().nullable().optional()
20154
20170
  });
20155
- var TASK_TIMELINE_KINDS = ["created", "claimed", "note", "blocked", "released", "lease_expired", "pr", "in_review", "done", "answered", "archived", "unarchived", "unblocked", "steered", "nudged"];
20171
+ var TASK_TIMELINE_KINDS = ["created", "claimed", "note", "blocked", "released", "lease_expired", "pr", "in_review", "done", "answered", "archived", "unarchived", "unblocked", "steered", "nudged", "edited", "moved"];
20156
20172
  var taskTimelineKindSchema = external_exports.enum(TASK_TIMELINE_KINDS);
20157
20173
  var taskTimelineEventSchema = external_exports.object({
20158
20174
  id: entityIdSchema,
@@ -20209,7 +20225,10 @@ var taskStatusLineQuerySchema = external_exports.object({
20209
20225
  cursor: replayCursor.optional()
20210
20226
  }).strict();
20211
20227
  var taskResultSchema = external_exports.object({ task: taskCardSchema });
20212
- var answerBodySchema = external_exports.object({ text: external_exports.string().trim().min(1).max(500) });
20228
+ var answerBodySchema = external_exports.object({
20229
+ text: external_exports.string().trim().min(1).max(500),
20230
+ waiting_since: isoTimeSchema.optional()
20231
+ });
20213
20232
  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"];
20214
20233
  var notificationKindSchema = external_exports.enum(NOTIFICATION_KINDS);
20215
20234
  var notificationViewSchema = external_exports.object({
@@ -20259,6 +20278,25 @@ var createTaskBody = external_exports.object({
20259
20278
  source_id: external_exports.string().max(1e3).optional(),
20260
20279
  session: sessionRef.optional()
20261
20280
  }).strict();
20281
+ var boardCreateTaskBody = external_exports.object({
20282
+ title: external_exports.string().min(1).max(1500),
20283
+ body: external_exports.string().max(7e4).optional(),
20284
+ status: external_exports.enum(["backlog", "ready"]).optional(),
20285
+ priority: external_exports.number().int().min(0).max(3).optional(),
20286
+ labels: labels.optional(),
20287
+ for_tools: forTools.optional(),
20288
+ blocked_by: external_exports.array(external_exports.number().int().positive()).max(MAX_BLOCKERS).optional()
20289
+ }).strict();
20290
+ var BOARD_EDIT_STATUSES = ["backlog", "ready", "blocked", "parked", "done", "cancelled"];
20291
+ var boardUpdateTaskBody = external_exports.object({
20292
+ title: external_exports.string().min(1).max(1500).optional(),
20293
+ body: external_exports.string().max(7e4).optional(),
20294
+ labels: labels.optional(),
20295
+ for_tools: forTools.optional(),
20296
+ status: external_exports.enum(BOARD_EDIT_STATUSES).optional(),
20297
+ release_claim: external_exports.boolean().optional(),
20298
+ expected_updated_at: external_exports.string().max(40).optional()
20299
+ }).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
20300
  var claimNextBody = external_exports.object({
20263
20301
  project: projectRefSchema.optional(),
20264
20302
  labels: labels.optional(),
@@ -20387,6 +20425,14 @@ var usageMachineViewSchema = external_exports.object({
20387
20425
  last_seen_at: isoTime.optional(),
20388
20426
  stats: machineHostStatsSchema.optional()
20389
20427
  }).strict();
20428
+ var projectToolUsageSchema = external_exports.object({
20429
+ tool: toolSchema,
20430
+ sessions: external_exports.number().int().nonnegative(),
20431
+ priced_sessions: external_exports.number().int().nonnegative(),
20432
+ tokens_in: external_exports.number().int().nonnegative(),
20433
+ tokens_out: external_exports.number().int().nonnegative(),
20434
+ cost_usd: external_exports.number().nonnegative()
20435
+ }).strict();
20390
20436
  var projectUsageViewSchema = external_exports.object({
20391
20437
  id: entityIdSchema,
20392
20438
  key: external_exports.string(),
@@ -20398,7 +20444,13 @@ var projectUsageViewSchema = external_exports.object({
20398
20444
  /** True when any of the numbers is an estimate. */
20399
20445
  approx: external_exports.boolean(),
20400
20446
  /** How many tasks of the project carry usage. */
20401
- tasks: external_exports.number().int().nonnegative()
20447
+ tasks: external_exports.number().int().nonnegative(),
20448
+ /** How many tool sessions reported usage in the project, claimed or not. */
20449
+ sessions: external_exports.number().int().nonnegative().optional(),
20450
+ /** When a machine last reported a session's counters for the project. */
20451
+ last_reported_at: isoTime.optional(),
20452
+ /** The session totals per tool; `priced_sessions` says how many of them sent a cost. */
20453
+ tools: external_exports.array(projectToolUsageSchema).max(10).optional()
20402
20454
  }).strict();
20403
20455
  var meUsageSchema = external_exports.object({
20404
20456
  generated_at: isoTime,
@@ -20479,6 +20531,53 @@ var usageRouteSchema = external_exports.object({
20479
20531
  unlinked_sessions: external_exports.number().int().nonnegative()
20480
20532
  }).strict();
20481
20533
 
20534
+ // ../shared/src/voice.ts
20535
+ var KOKORO_VOICES = [
20536
+ "af_alloy",
20537
+ "af_aoede",
20538
+ "af_bella",
20539
+ "af_heart",
20540
+ "af_jessica",
20541
+ "af_kore",
20542
+ "af_nicole",
20543
+ "af_nova",
20544
+ "af_river",
20545
+ "af_sarah",
20546
+ "af_sky",
20547
+ "am_adam",
20548
+ "am_echo",
20549
+ "am_eric",
20550
+ "am_fenrir",
20551
+ "am_liam",
20552
+ "am_michael",
20553
+ "am_onyx",
20554
+ "am_puck",
20555
+ "am_santa",
20556
+ "bf_alice",
20557
+ "bf_emma",
20558
+ "bf_isabella",
20559
+ "bf_lily",
20560
+ "bm_daniel",
20561
+ "bm_fable",
20562
+ "bm_george",
20563
+ "bm_lewis"
20564
+ ];
20565
+ var AGENT_VOICE_SPEEDS = [0.95, 1, 1.05, 1.1, 1.15];
20566
+ function fnv1a(s, seed) {
20567
+ let h = (2166136261 ^ seed) >>> 0;
20568
+ for (let i = 0; i < s.length; i++) {
20569
+ h ^= s.charCodeAt(i);
20570
+ h = Math.imul(h, 16777619) >>> 0;
20571
+ }
20572
+ return h >>> 0;
20573
+ }
20574
+ function voiceFor(agentId) {
20575
+ const voice = KOKORO_VOICES[fnv1a(agentId, 0) % KOKORO_VOICES.length];
20576
+ const speed = AGENT_VOICE_SPEEDS[fnv1a(agentId, 2654435769) % AGENT_VOICE_SPEEDS.length];
20577
+ return { voice, speed };
20578
+ }
20579
+ var KOKORO_VOICE_ID = /^[a-z]{2}_[a-z0-9]{2,24}$/;
20580
+
20482
20581
  // ../shared/src/remote.ts
20483
20582
  var SCHEME = /^([a-z][a-z0-9+.-]*):\/\//i;
20484
20583
  function normalizeRemote(remote) {
@@ -20588,6 +20687,29 @@ function redact(input2) {
20588
20687
  return { text: text2, count };
20589
20688
  }
20590
20689
 
20690
+ // ../shared/src/api/nudge.ts
20691
+ var NUDGE_TTL_SEC = 24 * 3600;
20692
+ var NUDGE_NOTE_MAX = 300;
20693
+ var nudgeBody = external_exports.object({ note: external_exports.string().trim().max(NUDGE_NOTE_MAX).optional() }).strict();
20694
+ var nudgeResponse = external_exports.object({
20695
+ nudge: external_exports.object({
20696
+ id: external_exports.string(),
20697
+ session_id: external_exports.string(),
20698
+ created_at: isoTimeSchema,
20699
+ /** When the next nudge of this session is allowed. */
20700
+ next_allowed_at: isoTimeSchema,
20701
+ /** The owner got a push (with the resume command when the tool has one). */
20702
+ pushed: external_exports.boolean(),
20703
+ resume_command: external_exports.string().nullable()
20704
+ })
20705
+ });
20706
+ var agentNudgeSchema = external_exports.object({ id: external_exports.string(), text: external_exports.string(), sent_at: isoTimeSchema });
20707
+ var sessionNudgeAckSchema = external_exports.object({
20708
+ created_at: isoTimeSchema,
20709
+ delivered_at: isoTimeSchema.nullable(),
20710
+ delivered_via: external_exports.enum(["hook", "mcp"]).nullable()
20711
+ });
20712
+
20591
20713
  // ../shared/src/api/memory.ts
20592
20714
  var CONTEXT_DECISIONS = 10;
20593
20715
  var MEMORY_KINDS = ["handoff", "decision"];
@@ -20647,7 +20769,7 @@ var floorAgentSchema = external_exports.object({
20647
20769
  id: entityIdSchema,
20648
20770
  name: external_exports.string(),
20649
20771
  tool: floorToolSchema,
20650
- /** Tiles inside a pod are grouped by this, for example "Claude Max (zan)". */
20772
+ /** Tiles inside a pod are grouped by this, for example "Claude Max (alex)". */
20651
20773
  account_label: external_exports.string(),
20652
20774
  machine: external_exports.string().nullable(),
20653
20775
  default_model: external_exports.string().nullable(),
@@ -20665,6 +20787,9 @@ var floorSessionSchema = external_exports.object({
20665
20787
  state_since: isoTimeSchema.optional(),
20666
20788
  /** For a `waiting` session: false once somebody answered this very wait. Older servers omit it (read as true). */
20667
20789
  wait_open: external_exports.boolean().optional(),
20790
+ /** 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. */
20791
+ loop_key: external_exports.string().nullable().optional(),
20792
+ loop_count: external_exports.number().int().optional(),
20668
20793
  /** The tool's own session id (what `claude --resume` takes), main sessions only. */
20669
20794
  tool_session_id: external_exports.string().nullable(),
20670
20795
  model: external_exports.string().nullable(),
@@ -20683,6 +20808,8 @@ var floorSessionSchema = external_exports.object({
20683
20808
  started_at: isoTimeSchema,
20684
20809
  last_event_at: isoTimeSchema,
20685
20810
  ended_at: isoTimeSchema.nullable(),
20811
+ /** Latest nudge from the last day, or null. Older servers omit it. */
20812
+ nudge: sessionNudgeAckSchema.nullable().optional(),
20686
20813
  get children() {
20687
20814
  return external_exports.array(floorSessionSchema);
20688
20815
  }
@@ -20748,6 +20875,10 @@ var collisionPeerSchema = external_exports.object({
20748
20875
  });
20749
20876
  var taskDetailSchema = external_exports.object({
20750
20877
  task: taskCardSchema,
20878
+ /** The task's description as written (Markdown), for the editor. Null when it has none. */
20879
+ body: external_exports.string().nullish(),
20880
+ /** The tools allowed to claim it; empty means any agent. */
20881
+ for_tools: external_exports.array(external_exports.string()).nullish(),
20751
20882
  events: external_exports.array(taskTimelineEventSchema),
20752
20883
  subtasks: external_exports.array(taskCardSchema),
20753
20884
  holder_session: floorSessionSchema.nullable(),
@@ -20860,6 +20991,18 @@ var HOUR_MS = 36e5;
20860
20991
  var MAX_FLOOR_RANGE_MS = 8 * 24 * HOUR_MS;
20861
20992
  var DEFAULT_FLOOR_WINDOW_MS = 24 * HOUR_MS;
20862
20993
 
20994
+ // ../shared/src/client-routes.ts
20995
+ var SEGMENT = "[^/]+";
20996
+ var PROJECT_TABS = "(?:board|done|team|memory|agents|settings|welcome)";
20997
+ var CLIENT_ROUTE_PATTERNS = [
20998
+ /^\/$/,
20999
+ /^\/(?:about|docs|signin|signup|app|connect|floor|hive|floor3d|machines|new|settings|inbox|feedback|usage|demo)$/,
21000
+ new RegExp(`^/(?:s|invite)/${SEGMENT}$`),
21001
+ new RegExp(`^/p/${SEGMENT}$`),
21002
+ new RegExp(`^/p/${SEGMENT}/${PROJECT_TABS}$`),
21003
+ new RegExp(`^/p/${SEGMENT}/board/${SEGMENT}$`)
21004
+ ];
21005
+
20863
21006
  // ../shared/src/collisions.ts
20864
21007
  var COLLISION_WINDOW_SEC = 30 * 60;
20865
21008
  var LOOP_NO_CHANGE_SEC = 30 * 60;
@@ -20891,6 +21034,68 @@ var webhookGetResponse = external_exports.object({ webhook: webhookViewSchema.nu
20891
21034
  var webhookPutResponse = external_exports.object({ webhook: webhookViewSchema, secret: external_exports.string().optional() }).strict();
20892
21035
  var webhookTestResponse = external_exports.object({ ok: external_exports.literal(true), queued: external_exports.literal(true) }).strict();
20893
21036
 
21037
+ // ../shared/src/api/provider-keys.ts
21038
+ var PROVIDER_NAMES = ["anthropic", "openai", "google", "openai_compat"];
21039
+ var providerNameSchema = external_exports.enum(PROVIDER_NAMES);
21040
+ var PROVIDER_KEY_LABEL_MAX = 60;
21041
+ var PROVIDER_KEY_RE = /^[\x21-\x7e]{8,512}$/;
21042
+ var addProviderKeyBody = external_exports.object({
21043
+ provider: providerNameSchema,
21044
+ base_url: external_exports.string().trim().min(1).max(2048).optional(),
21045
+ label: external_exports.string().trim().max(PROVIDER_KEY_LABEL_MAX).optional(),
21046
+ key: external_exports.string().trim().regex(PROVIDER_KEY_RE, "That does not look like an API key")
21047
+ }).strict();
21048
+ var providerKeyViewSchema = external_exports.object({
21049
+ id: entityIdSchema,
21050
+ provider: providerNameSchema,
21051
+ base_url: external_exports.string().nullable(),
21052
+ label: external_exports.string(),
21053
+ last4: external_exports.string(),
21054
+ created_at: isoTimeSchema
21055
+ }).strict();
21056
+ var providerKeyListSchema = external_exports.object({ keys: external_exports.array(providerKeyViewSchema) }).strict();
21057
+ var providerKeyAddedSchema = external_exports.object({ key: providerKeyViewSchema, model_count: external_exports.number().int().nonnegative() }).strict();
21058
+ var providerModelSchema = external_exports.object({ id: external_exports.string(), label: external_exports.string().optional() }).strict();
21059
+ var providerModelsSchema = external_exports.object({ models: external_exports.array(providerModelSchema) }).strict();
21060
+
21061
+ // ../shared/src/model-prices.ts
21062
+ var CLAUDE_PRICES = [
21063
+ ["claude-fable-5-2", { input: 8, output: 40, cacheRead: 0.2 }],
21064
+ ["claude-fable-5-1", { input: 10, output: 50 }],
21065
+ ["claude-fable-5", { input: 10, output: 50 }],
21066
+ ["claude-opus-5-5", { input: 4, output: 20, cacheRead: 0.2 }],
21067
+ ["claude-opus-5", { input: 5, output: 25 }],
21068
+ ["claude-opus-4-8", { input: 5, output: 25 }],
21069
+ ["claude-opus-4-7", { input: 5, output: 25 }],
21070
+ ["claude-opus-4-6", { input: 5, output: 25 }],
21071
+ ["claude-opus-4-5", { input: 5, output: 25 }],
21072
+ ["claude-sonnet-5-5", { input: 2, output: 10, cacheRead: 0.1 }],
21073
+ ["claude-sonnet-5", { input: 2, output: 10 }],
21074
+ ["claude-sonnet-4-6", { input: 3, output: 15 }],
21075
+ ["claude-sonnet-4-5", { input: 3, output: 15 }],
21076
+ ["claude-sonnet-4", { input: 3, output: 15 }],
21077
+ ["claude-haiku-5-5", { input: 0.1, output: 0.5 }],
21078
+ ["claude-haiku-4-5", { input: 1, output: 5 }]
21079
+ ];
21080
+ function claudeModelPrice(model) {
21081
+ if (!model) return null;
21082
+ const m = model.toLowerCase();
21083
+ const at = m.indexOf("claude-");
21084
+ if (at < 0) return null;
21085
+ const id = m.slice(at);
21086
+ for (const [prefix, price] of CLAUDE_PRICES) {
21087
+ if (id === prefix || id.startsWith(`${prefix}-`) || id.startsWith(`${prefix}[`) || id.startsWith(`${prefix}@`) || id.startsWith(`${prefix}:`)) return price;
21088
+ }
21089
+ return null;
21090
+ }
21091
+ function estimateClaudeCostUsd(model, t) {
21092
+ const p = claudeModelPrice(model);
21093
+ if (!p) return null;
21094
+ const cacheRead = p.cacheRead ?? p.input * 0.1;
21095
+ const cacheWrite = p.cacheWrite ?? p.input * 1.25;
21096
+ return (t.input * p.input + t.output * p.output + t.cacheRead * cacheRead + t.cacheWrite * cacheWrite) / 1e6;
21097
+ }
21098
+
20894
21099
  // ../shared/src/api/inbox.ts
20895
21100
  var INBOX_KINDS = ["blocked_task", "waiting", "question"];
20896
21101
  var inboxKindSchema = external_exports.enum(INBOX_KINDS);
@@ -20909,14 +21114,27 @@ var inboxItemSchema = external_exports.object({
20909
21114
  /** 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
21115
  can_nudge: external_exports.boolean().optional()
20911
21116
  });
21117
+ var inboxGroupSchema = external_exports.object({
21118
+ project: external_exports.object({ id: entityIdSchema, key: external_exports.string(), name: external_exports.string() }),
21119
+ /** Items waiting in the project, answerable or not. */
21120
+ count: external_exports.number().int().min(0),
21121
+ /** Of those, the ones the caller can answer. */
21122
+ answerable: external_exports.number().int().min(0),
21123
+ /** An agent is waiting in it (a live session or a question), not only backlog decisions. */
21124
+ live: external_exports.boolean()
21125
+ });
20912
21126
  var inboxListSchema = external_exports.object({
20913
21127
  items: external_exports.array(inboxItemSchema),
20914
21128
  /** Items the caller can answer: the sidebar badge. */
20915
21129
  count: external_exports.number().int().min(0),
20916
21130
  /** Every item the caller can see, answerable or not (`items` is one page of them). */
20917
21131
  total: external_exports.number().int().min(0).optional(),
21132
+ /** One entry per project with something waiting, over every item: projects with something to answer first, live ones before backlog-only ones. */
21133
+ groups: external_exports.array(inboxGroupSchema).optional(),
20918
21134
  /** Offset of the next page, null on the last one. */
20919
- next_cursor: external_exports.string().nullable().optional()
21135
+ next_cursor: external_exports.string().nullable().optional(),
21136
+ /** 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. */
21137
+ truncated: external_exports.boolean().optional()
20920
21138
  });
20921
21139
  var inboxAnswerBodySchema = external_exports.object({
20922
21140
  text: external_exports.string().trim().min(1).max(4e3),
@@ -21061,11 +21279,9 @@ var fleetSnapshotResult = external_exports.object({
21061
21279
  tasks: external_exports.object({ created: external_exports.number(), updated: external_exports.number(), missing: external_exports.number(), skipped: external_exports.number() }).strict()
21062
21280
  }).strict();
21063
21281
  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();
21282
+ var fleetTokensResponse = listOf(fleetTokenSchema);
21065
21283
 
21066
21284
  // ../shared/src/api/share.ts
21067
- var SHARE_EXPIRY_PRESETS = ["1h", "1d", "7d", "30d"];
21068
- var shareExpiryPresetSchema = external_exports.enum(SHARE_EXPIRY_PRESETS);
21069
21285
  var MAX_SHARE_LINK_DAYS = 30;
21070
21286
  var MIN_SHARE_LINK_SECONDS = 60;
21071
21287
  var MAX_SHARE_LINK_SECONDS = MAX_SHARE_LINK_DAYS * 86400;
@@ -21150,8 +21366,6 @@ var URL_OR_PATH_RE = new RegExp(
21150
21366
 
21151
21367
  // ../shared/src/api/digest.ts
21152
21368
  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
21369
  var digestTaskItemSchema = external_exports.object({
21156
21370
  id: idSchema,
21157
21371
  project_id: idSchema,
@@ -21292,119 +21506,130 @@ var feedbackListSchema = external_exports.object({
21292
21506
  total: external_exports.number().int().min(0)
21293
21507
  });
21294
21508
 
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
- })
21509
+ // ../shared/src/demo/script.ts
21510
+ var DEMO_LOOP_S = 180;
21511
+ var DEMO_LOOP_MS = DEMO_LOOP_S * 1e3;
21512
+ var DEMO_QUESTION = {
21513
+ agentName: "nova",
21514
+ agentLabel: "nova \xB7 Codex",
21515
+ sessionId: "9002",
21516
+ taskKey: "HIVE-146",
21517
+ taskTitle: "Remove the v1 export API",
21518
+ askedAtS: 40,
21519
+ /** After this the script moves on by itself (nova takes the default) if nobody answered. */
21520
+ resumesAtS: 100,
21521
+ text: "Keep the old v1 export route for one more release, or remove it now?",
21522
+ quickAnswers: ["Keep it one more release", "Remove it now"]
21523
+ };
21524
+ var MAIN = {
21525
+ "1": {
21526
+ id: "9001",
21527
+ steps: [
21528
+ { at: 0, state: "working", line: "Reading the failing checkout spec", task: "138", repo: "acme/shop-web", branch: "fix/checkout-rounding" },
21529
+ { at: 20, state: "working", line: "Fixing the rounding in total.ts", task: "138", repo: "acme/shop-web", branch: "fix/checkout-rounding" },
21530
+ { at: 50, state: "working", line: "Running the checkout tests", task: "138", repo: "acme/shop-web", branch: "fix/checkout-rounding" },
21531
+ { at: 90, state: "idle", line: "Finished HIVE-138", task: null },
21532
+ { at: 110, state: "working", line: "Claimed the CSV export, reading the reports module", task: "153", repo: "acme/api", branch: "feat/csv-export" },
21533
+ { at: 140, state: "working", line: "Writing the export endpoint", task: "153", repo: "acme/api", branch: "feat/csv-export" }
21534
+ ]
21535
+ },
21536
+ "2": {
21537
+ id: "9002",
21538
+ steps: [
21539
+ { at: 0, state: "working", line: "Reading the v1 export routes", task: "146", repo: "acme/api", branch: "chore/drop-v1-export" },
21540
+ { at: 25, state: "working", line: "Listing the callers of the old v1 export route", task: "146", repo: "acme/api", branch: "chore/drop-v1-export" },
21541
+ { at: DEMO_QUESTION.askedAtS, state: "waiting", line: DEMO_QUESTION.text, task: "146", repo: "acme/api", branch: "chore/drop-v1-export" },
21542
+ { 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" },
21543
+ { at: 150, state: "working", line: "Adding a deprecation header", task: "146", repo: "acme/api", branch: "chore/drop-v1-export" }
21544
+ ]
21545
+ },
21546
+ "3": {
21547
+ id: "9003",
21548
+ steps: [
21549
+ { at: 0, state: "working", line: "Adding retry with backoff to the webhook sender", task: "141", repo: "acme/worker", branch: "fix/webhook-retry" },
21550
+ { at: 30, state: "working", line: "Writing the retry tests", task: "141", repo: "acme/worker", branch: "fix/webhook-retry" },
21551
+ { at: 70, state: "idle", line: "Opened PR #214", task: null },
21552
+ { at: 85, state: "working", line: "Claimed the currency cache, reading the lookup code", task: "154", repo: "acme/api", branch: "perf/currency-cache" },
21553
+ { at: 125, state: "working", line: "Profiling the slow lookup", task: "154", repo: "acme/api", branch: "perf/currency-cache" }
21554
+ ]
21555
+ },
21556
+ "4": {
21557
+ id: "9004",
21558
+ steps: [
21559
+ { at: 0, state: "working", line: "Styling the settings page", task: "152", repo: "acme/shop-web", branch: "feat/dark-settings" },
21560
+ { at: 60, state: "working", line: "Updating the snapshot tests", task: "152", repo: "acme/shop-web", branch: "feat/dark-settings" },
21561
+ { at: 130, state: "working", line: "Checking contrast on the form fields", task: "152", repo: "acme/shop-web", branch: "feat/dark-settings" }
21562
+ ]
21563
+ },
21564
+ "5": {
21565
+ id: "9005",
21566
+ steps: [
21567
+ { at: 0, state: "working", line: "Moving sessions to Redis", task: "150", repo: "acme/accounts", branch: "feat/redis-sessions" },
21568
+ { at: 50, state: "working", line: "Running the session migration", task: "150", repo: "acme/accounts", branch: "feat/redis-sessions" },
21569
+ { at: 120, state: "blocked", line: "Needs the staging Redis URL to go on", task: "150", repo: "acme/accounts", branch: "feat/redis-sessions" }
21570
+ ]
21571
+ }
21572
+ };
21573
+ var TASKS = [
21574
+ { 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." }] },
21575
+ { 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 }] },
21576
+ { 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" }] },
21577
+ { 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" }] },
21578
+ { 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" }] },
21579
+ { 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" }] },
21580
+ { 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" }] },
21581
+ { num: 155, title: "Trim the Docker image", repo: "infra", branch: null, priority: 3, labels: ["chore"], steps: [{ at: 0, status: "ready" }] },
21582
+ { num: 156, title: "Handle the empty-cart edge case", repo: "shop-web", branch: null, priority: 2, labels: ["bug"], steps: [{ at: 0, status: "ready" }] },
21583
+ { 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 }] },
21584
+ { 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 },
21585
+ { 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 }
21586
+ ];
21587
+
21588
+ // ../shared/src/provider.ts
21589
+ var PROVIDERS = ["claude", "codex", "cursor", "gemini", "grok", "minimax", "other"];
21590
+
21591
+ // ../shared/src/api/me-floor.ts
21592
+ var providerSchema = external_exports.enum(PROVIDERS);
21593
+ var meFloorSessionSchema = external_exports.object({
21594
+ session: floorSessionSchema,
21595
+ agent: floorAgentSchema,
21596
+ user: floorUserSchema,
21597
+ provider: providerSchema
21310
21598
  });
21311
- var agentNudgeSchema = external_exports.object({ id: external_exports.string(), text: external_exports.string(), sent_at: isoTimeSchema });
21599
+ var meFloorProjectSchema = external_exports.object({
21600
+ id: entityIdSchema,
21601
+ key: external_exports.string(),
21602
+ name: external_exports.string(),
21603
+ /** Main sessions with their subagents nested. Cut at the snapshot-wide session cap. */
21604
+ sessions: external_exports.array(meFloorSessionSchema),
21605
+ /** Every status is present (zero when empty); archived tasks do not count. */
21606
+ task_counts: external_exports.record(external_exports.enum(TASK_STATUSES), external_exports.number().int().nonnegative()),
21607
+ /** Items in this project that wait on the caller (what they can answer in the inbox). */
21608
+ needs_you: external_exports.number().int().nonnegative()
21609
+ });
21610
+ var meFloorSchema = external_exports.object({
21611
+ projects: external_exports.array(meFloorProjectSchema),
21612
+ truncated: external_exports.boolean(),
21613
+ /** Pass it as `Last-Event-ID` (or `?last_event_id=`) to `/me/stream`: the stream then replays only what came after this snapshot. */
21614
+ last_event_id: external_exports.string().nullable(),
21615
+ server_time: isoTimeSchema
21616
+ });
21617
+ var withProject = (shape) => external_exports.object({ ...shape, project_id: entityIdSchema });
21618
+ var meStreamPayloads = {
21619
+ session: withProject(floorStreamPayloads.session.shape),
21620
+ session_end: withProject(floorStreamPayloads.session_end.shape),
21621
+ task: withProject(floorStreamPayloads.task.shape),
21622
+ task_event: withProject(floorStreamPayloads.task_event.shape),
21623
+ notification: withProject(floorStreamPayloads.notification.shape),
21624
+ membership_revoked: floorStreamPayloads.membership_revoked,
21625
+ resync: external_exports.object({ project_id: entityIdSchema.optional() })
21626
+ };
21627
+ var ME_STREAM_EVENTS = Object.keys(meStreamPayloads);
21312
21628
 
21313
21629
  // ../shared/src/index.ts
21314
21630
  var ROLES = ["owner", "admin", "member", "viewer"];
21315
21631
  var roleSchema2 = external_exports.enum(ROLES);
21316
21632
 
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();
21345
- }
21346
- }
21347
- function webUrl(url2) {
21348
- let u;
21349
- try {
21350
- u = new URL(url2);
21351
- } catch {
21352
- throw new Error("not a URL");
21353
- }
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;
21368
- }
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
- });
21406
- }
21407
-
21408
21633
  export {
21409
21634
  normalizeRemote,
21410
21635
  formatRemote,
@@ -21424,13 +21649,10 @@ export {
21424
21649
  redact,
21425
21650
  usageReadingSchema,
21426
21651
  parseUsageKey,
21652
+ estimateClaudeCostUsd,
21427
21653
  routeProviderFromParam,
21428
21654
  usageRouteSchema,
21429
- DEFAULT_HOST,
21430
- defaultCtx,
21431
- hostFromEnv,
21432
- normalizeHost,
21433
- isSecureUrl,
21434
- machineName,
21435
- runCmd
21655
+ KOKORO_VOICES,
21656
+ voiceFor,
21657
+ KOKORO_VOICE_ID
21436
21658
  };