chatroom-cli 1.13.3 → 1.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +164 -46
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -12552,7 +12552,7 @@ async function createDefaultDeps8() {
12552
12552
  }
12553
12553
  async function handoff(chatroomId, options, deps) {
12554
12554
  const d = deps ?? await createDefaultDeps8();
12555
- const { role, message, nextRole, attachedArtifactIds = [] } = options;
12555
+ const { role, message, nextRole, attachedArtifactIds = [], attachedWorkflowKeys = [] } = options;
12556
12556
  const sessionId = d.session.getSessionId();
12557
12557
  if (!sessionId) {
12558
12558
  const otherUrls = d.session.getOtherSessionUrls();
@@ -12582,6 +12582,22 @@ async function handoff(chatroomId, options, deps) {
12582
12582
  process.exit(1);
12583
12583
  }
12584
12584
  }
12585
+ const resolvedWorkflowIds = [];
12586
+ if (attachedWorkflowKeys.length > 0) {
12587
+ for (const key of attachedWorkflowKeys) {
12588
+ try {
12589
+ const result2 = await d.backend.query(api.workflows.resolveWorkflowId, {
12590
+ sessionId,
12591
+ chatroomId,
12592
+ workflowKey: key
12593
+ });
12594
+ resolvedWorkflowIds.push(result2.workflowId);
12595
+ } catch {
12596
+ formatError(`Workflow "${key}" not found`, ["Check the workflow key and try again"]);
12597
+ process.exit(1);
12598
+ }
12599
+ }
12600
+ }
12585
12601
  let result;
12586
12602
  try {
12587
12603
  result = await d.backend.mutation(api.messages.handoff, {
@@ -12592,6 +12608,9 @@ async function handoff(chatroomId, options, deps) {
12592
12608
  targetRole: nextRole,
12593
12609
  ...attachedArtifactIds.length > 0 && {
12594
12610
  attachedArtifactIds
12611
+ },
12612
+ ...resolvedWorkflowIds.length > 0 && {
12613
+ attachedWorkflowIds: resolvedWorkflowIds
12595
12614
  }
12596
12615
  });
12597
12616
  } catch (error) {
@@ -12665,6 +12684,32 @@ ${error instanceof Error ? error.message : String(error)}`);
12665
12684
  console.log(` • ${id}`);
12666
12685
  });
12667
12686
  }
12687
+ if (resolvedWorkflowIds.length > 0) {
12688
+ for (const wfId of resolvedWorkflowIds) {
12689
+ try {
12690
+ const detail = await d.backend.query(api.workflows.getWorkflowDetail, {
12691
+ sessionId,
12692
+ chatroomId,
12693
+ workflowId: wfId
12694
+ });
12695
+ const wf = detail.workflow;
12696
+ console.log("");
12697
+ console.log(`\uD83D\uDCCA Attached Workflow: ${wf.workflowKey} (${wf.status}, ${detail.steps.length} steps)`);
12698
+ for (let i2 = 0;i2 < detail.steps.length; i2++) {
12699
+ const step = detail.steps[i2];
12700
+ const isLast = i2 === detail.steps.length - 1;
12701
+ const prefix = isLast ? "└─" : "├─";
12702
+ const statusEmoji = step.status === "completed" ? "✅" : step.status === "in_progress" ? "\uD83D\uDD04" : step.status === "cancelled" ? "❌" : "⏳";
12703
+ const roleLabel = step.assigneeRole ? ` [${step.assigneeRole}]` : "";
12704
+ const deps2 = step.dependsOn.length > 0 ? ` (depends: ${step.dependsOn.join(", ")})` : "";
12705
+ console.log(` ${prefix} ${step.stepKey}${roleLabel} ${statusEmoji} ${step.status}${deps2}`);
12706
+ }
12707
+ console.log("");
12708
+ console.log(` Inspect: chatroom workflow status --chatroom-id=${chatroomId} --workflow-key=${wf.workflowKey}`);
12709
+ console.log(` View step: chatroom workflow step-view --chatroom-id=${chatroomId} --workflow-key=${wf.workflowKey} --step-key=<key>`);
12710
+ } catch {}
12711
+ }
12712
+ }
12668
12713
  const convexUrl = d.session.getConvexUrl();
12669
12714
  const cliEnvPrefix = getCliEnvPrefix(convexUrl);
12670
12715
  console.log(`
@@ -13428,14 +13473,14 @@ var init_file_content = () => {};
13428
13473
  // src/commands/workflow/index.ts
13429
13474
  var exports_workflow = {};
13430
13475
  __export(exports_workflow, {
13476
+ viewStep: () => viewStep,
13431
13477
  specifyWorkflowStep: () => specifyWorkflowStep,
13432
13478
  parseSections: () => parseSections,
13433
13479
  getWorkflowStatus: () => getWorkflowStatus,
13434
13480
  exitWorkflow: () => exitWorkflow,
13435
13481
  executeWorkflow: () => executeWorkflow,
13436
13482
  createWorkflow: () => createWorkflow,
13437
- completeStep: () => completeStep,
13438
- cancelStep: () => cancelStep
13483
+ completeStep: () => completeStep
13439
13484
  });
13440
13485
  async function createDefaultDeps11() {
13441
13486
  const client2 = await getConvexClient();
@@ -13612,10 +13657,11 @@ async function specifyWorkflowStep(chatroomId, options, deps) {
13612
13657
  const d = deps ?? await createDefaultDeps11();
13613
13658
  const sessionId = requireAuth3(d);
13614
13659
  validateChatroomId2(chatroomId);
13615
- const sections = parseSections(options.stdinContent, ["GOAL", "REQUIREMENTS"], ["WARNINGS"]);
13660
+ const sections = parseSections(options.stdinContent, ["GOAL", "REQUIREMENTS"], ["WARNINGS", "SKILLS"]);
13616
13661
  const goal = sections.get("GOAL");
13617
13662
  const requirements = sections.get("REQUIREMENTS");
13618
13663
  const warnings = sections.get("WARNINGS") || undefined;
13664
+ const skills = sections.get("SKILLS") || undefined;
13619
13665
  try {
13620
13666
  await d.backend.mutation(api.workflows.specifyStep, {
13621
13667
  sessionId,
@@ -13625,7 +13671,8 @@ async function specifyWorkflowStep(chatroomId, options, deps) {
13625
13671
  assigneeRole: options.assigneeRole,
13626
13672
  goal,
13627
13673
  requirements,
13628
- warnings
13674
+ warnings,
13675
+ skills
13629
13676
  });
13630
13677
  console.log("");
13631
13678
  console.log("✅ Step specified");
@@ -13732,6 +13779,9 @@ async function getWorkflowStatus(chatroomId, options, deps) {
13732
13779
  if (spec.goal) {
13733
13780
  console.log(` \uD83D\uDCCE Goal: ${spec.goal}`);
13734
13781
  }
13782
+ if (spec.skills) {
13783
+ console.log(` \uD83D\uDD27 Skills: ${spec.skills}`);
13784
+ }
13735
13785
  if (spec.requirements) {
13736
13786
  console.log(` \uD83D\uDCCE Requirements: ${spec.requirements}`);
13737
13787
  }
@@ -13787,58 +13837,118 @@ async function completeStep(chatroomId, options, deps) {
13787
13837
  return;
13788
13838
  }
13789
13839
  }
13790
- async function cancelStep(chatroomId, options, deps) {
13840
+ async function exitWorkflow(chatroomId, options, deps) {
13791
13841
  const d = deps ?? await createDefaultDeps11();
13792
13842
  const sessionId = requireAuth3(d);
13793
13843
  validateChatroomId2(chatroomId);
13794
13844
  if (!options.reason || options.reason.trim().length === 0) {
13795
- console.error("❌ Reason is required when cancelling a step");
13845
+ console.error("❌ Reason is required when exiting a workflow");
13796
13846
  process.exit(1);
13797
13847
  return;
13798
13848
  }
13799
13849
  try {
13800
- await d.backend.mutation(api.workflows.cancelStep, {
13850
+ await d.backend.mutation(api.workflows.exitWorkflow, {
13801
13851
  sessionId,
13802
13852
  chatroomId,
13803
13853
  workflowKey: options.workflowKey,
13804
- stepKey: options.stepKey,
13805
13854
  reason: options.reason.trim()
13806
13855
  });
13807
13856
  console.log("");
13808
- console.log("❌ Step cancelled");
13809
- console.log(` Workflow: ${options.workflowKey}`);
13810
- console.log(` Step: ${options.stepKey}`);
13857
+ console.log("❌ Workflow exited (cancelled)");
13858
+ console.log(` Key: ${options.workflowKey}`);
13811
13859
  console.log(` Reason: ${options.reason.trim()}`);
13812
13860
  console.log("");
13813
13861
  } catch (error) {
13814
- console.error(`❌ Failed to cancel step: ${error.message}`);
13862
+ console.error(`❌ Failed to exit workflow: ${error.message}`);
13815
13863
  process.exit(1);
13816
13864
  return;
13817
13865
  }
13818
13866
  }
13819
- async function exitWorkflow(chatroomId, options, deps) {
13867
+ async function viewStep(chatroomId, options, deps) {
13820
13868
  const d = deps ?? await createDefaultDeps11();
13821
13869
  const sessionId = requireAuth3(d);
13822
13870
  validateChatroomId2(chatroomId);
13823
- if (!options.reason || options.reason.trim().length === 0) {
13824
- console.error("❌ Reason is required when exiting a workflow");
13825
- process.exit(1);
13826
- return;
13827
- }
13828
13871
  try {
13829
- await d.backend.mutation(api.workflows.exitWorkflow, {
13872
+ const result = await d.backend.query(api.workflows.getStepView, {
13830
13873
  sessionId,
13831
13874
  chatroomId,
13832
13875
  workflowKey: options.workflowKey,
13833
- reason: options.reason.trim()
13876
+ stepKey: options.stepKey
13834
13877
  });
13878
+ const step = result.step;
13879
+ const emoji = getStepStatusEmoji(step.status);
13835
13880
  console.log("");
13836
- console.log("❌ Workflow exited (cancelled)");
13837
- console.log(` Key: ${options.workflowKey}`);
13838
- console.log(` Reason: ${options.reason.trim()}`);
13881
+ console.log("══════════════════════════════════════════════════");
13882
+ console.log(`${emoji} STEP: ${step.stepKey}`);
13883
+ console.log("══════════════════════════════════════════════════");
13884
+ console.log(`Workflow: ${result.workflowKey} (${result.workflowStatus})`);
13885
+ console.log(`Description: ${step.description}`);
13886
+ console.log(`Status: ${step.status.toUpperCase()}`);
13887
+ if (step.assigneeRole) {
13888
+ console.log(`Assignee: ${step.assigneeRole}`);
13889
+ }
13890
+ if (step.dependsOn.length > 0) {
13891
+ console.log(`Dependencies: ${step.dependsOn.join(", ")}`);
13892
+ }
13893
+ console.log(`Order: ${step.order}`);
13894
+ if (step.completedAt) {
13895
+ const completedDate = new Date(step.completedAt).toLocaleString("en-US", {
13896
+ month: "short",
13897
+ day: "numeric",
13898
+ hour: "2-digit",
13899
+ minute: "2-digit",
13900
+ hour12: false
13901
+ });
13902
+ console.log(`Completed: ${completedDate}`);
13903
+ }
13904
+ if (step.cancelledAt) {
13905
+ const cancelledDate = new Date(step.cancelledAt).toLocaleString("en-US", {
13906
+ month: "short",
13907
+ day: "numeric",
13908
+ hour: "2-digit",
13909
+ minute: "2-digit",
13910
+ hour12: false
13911
+ });
13912
+ console.log(`Cancelled: ${cancelledDate}`);
13913
+ if (step.cancelReason) {
13914
+ console.log(`Cancel reason: ${step.cancelReason}`);
13915
+ }
13916
+ }
13917
+ if (step.specification) {
13918
+ const spec = step.specification;
13919
+ console.log("");
13920
+ console.log("──────────────────────────────────────────────────");
13921
+ console.log("\uD83D\uDCCB SPECIFICATION");
13922
+ console.log("──────────────────────────────────────────────────");
13923
+ if (spec.goal) {
13924
+ console.log("");
13925
+ console.log("Goal:");
13926
+ console.log(spec.goal);
13927
+ }
13928
+ if (spec.skills) {
13929
+ console.log("");
13930
+ console.log("Skills:");
13931
+ console.log(spec.skills);
13932
+ }
13933
+ if (spec.requirements) {
13934
+ console.log("");
13935
+ console.log("Requirements:");
13936
+ console.log(spec.requirements);
13937
+ }
13938
+ if (spec.warnings) {
13939
+ console.log("");
13940
+ console.log("⚠️ Warnings:");
13941
+ console.log(spec.warnings);
13942
+ }
13943
+ } else {
13944
+ console.log("");
13945
+ console.log("⚠️ No specification set. Run `workflow specify` to add one.");
13946
+ }
13947
+ console.log("");
13948
+ console.log("══════════════════════════════════════════════════");
13839
13949
  console.log("");
13840
13950
  } catch (error) {
13841
- console.error(`❌ Failed to exit workflow: ${error.message}`);
13951
+ console.error(`❌ Failed to view step: ${error.message}`);
13842
13952
  process.exit(1);
13843
13953
  return;
13844
13954
  }
@@ -15850,9 +15960,7 @@ var init_crash_loop_tracker = __esm(() => {
15850
15960
  });
15851
15961
 
15852
15962
  // src/infrastructure/machine/stop-reason.ts
15853
- function resolveStopReason(code2, signal, wasIntentional) {
15854
- if (wasIntentional)
15855
- return "user.stop";
15963
+ function resolveStopReason(code2, signal) {
15856
15964
  if (signal !== null)
15857
15965
  return "agent_process.signal";
15858
15966
  if (code2 === 0)
@@ -15868,7 +15976,6 @@ function agentKey2(chatroomId, role) {
15868
15976
  class AgentProcessManager {
15869
15977
  deps;
15870
15978
  slots = new Map;
15871
- pendingStopReasons = new Map;
15872
15979
  constructor(deps) {
15873
15980
  this.deps = deps;
15874
15981
  }
@@ -15923,7 +16030,6 @@ class AgentProcessManager {
15923
16030
  slot.pendingOperation = undefined;
15924
16031
  return { success: true };
15925
16032
  }
15926
- this.pendingStopReasons.set(key, opts.reason);
15927
16033
  slot.state = "stopping";
15928
16034
  const operation = this.doStop(key, slot, pid, opts);
15929
16035
  slot.pendingOperation = operation;
@@ -15939,9 +16045,7 @@ class AgentProcessManager {
15939
16045
  if (slot.state === "stopping") {
15940
16046
  return;
15941
16047
  }
15942
- const intentionalReason = this.pendingStopReasons.get(key);
15943
- this.pendingStopReasons.delete(key);
15944
- const stopReason = intentionalReason ?? resolveStopReason(opts.code, opts.signal, false);
16048
+ const stopReason = resolveStopReason(opts.code, opts.signal);
15945
16049
  this.deps.spawning.recordExit(opts.chatroomId);
15946
16050
  const harness = slot.harness;
15947
16051
  const model = slot.model;
@@ -17305,6 +17409,8 @@ program2.command("classify").description("Classify a task's origin message (entr
17305
17409
  });
17306
17410
  program2.command("handoff").description("Complete your task and hand off to the next role").requiredOption("--chatroom-id <id>", "Chatroom identifier").requiredOption("--role <role>", "Your role").requiredOption("--next-role <nextRole>", "Role to hand off to").option("--attach-artifact <artifactId>", "Attach artifact to handoff (can be used multiple times)", (value, previous) => {
17307
17411
  return previous ? [...previous, value] : [value];
17412
+ }, []).option("--attachment <type:value>", "Attach a resource (can be used multiple times). Format: type:value. Supported: workflow-key:<key>", (value, previous) => {
17413
+ return previous ? [...previous, value] : [value];
17308
17414
  }, []).action(async (options) => {
17309
17415
  await maybeRequireAuth();
17310
17416
  const { decode: decode2 } = await Promise.resolve().then(() => exports_decode);
@@ -17321,12 +17427,29 @@ program2.command("handoff").description("Complete your task and hand off to the
17321
17427
  console.error("❌ Message is empty");
17322
17428
  process.exit(1);
17323
17429
  }
17430
+ const attachedWorkflowKeys = [];
17431
+ for (const att of options.attachment || []) {
17432
+ const colonIndex = att.indexOf(":");
17433
+ if (colonIndex === -1) {
17434
+ console.error(`❌ Invalid attachment format: "${att}". Expected type:value (e.g., workflow-key:my-workflow)`);
17435
+ process.exit(1);
17436
+ }
17437
+ const type = att.substring(0, colonIndex);
17438
+ const value = att.substring(colonIndex + 1);
17439
+ if (type === "workflow-key") {
17440
+ attachedWorkflowKeys.push(value);
17441
+ } else {
17442
+ console.error(`❌ Unknown attachment type: "${type}". Supported: workflow-key`);
17443
+ process.exit(1);
17444
+ }
17445
+ }
17324
17446
  const { handoff: handoff2 } = await Promise.resolve().then(() => (init_handoff(), exports_handoff));
17325
17447
  await handoff2(options.chatroomId, {
17326
17448
  role: options.role,
17327
17449
  message,
17328
17450
  nextRole: options.nextRole,
17329
- attachedArtifactIds: options.attachArtifact || []
17451
+ attachedArtifactIds: options.attachArtifact || [],
17452
+ attachedWorkflowKeys
17330
17453
  });
17331
17454
  });
17332
17455
  program2.command("report-progress").description("Report progress on current task (does not complete the task)").requiredOption("--chatroom-id <id>", "Chatroom identifier").requiredOption("--role <role>", "Your role").action(async (options) => {
@@ -17512,31 +17635,26 @@ workflowCommand.command("step-complete").description("Mark a workflow step as co
17512
17635
  stepKey: options.stepKey
17513
17636
  });
17514
17637
  });
17515
- workflowCommand.command("step-cancel").description("Cancel a workflow step with a reason").requiredOption("--chatroom-id <id>", "Chatroom identifier").requiredOption("--role <role>", "Your role").requiredOption("--workflow-key <key>", "Workflow key").requiredOption("--step-key <stepKey>", "Step key to cancel").requiredOption("--reason <text>", "Reason for cancellation (required)").action(async (options) => {
17638
+ workflowCommand.command("exit").description("Exit (cancel) an entire workflow with a reason").requiredOption("--chatroom-id <id>", "Chatroom identifier").requiredOption("--role <role>", "Your role").requiredOption("--workflow-key <key>", "Workflow key to exit").requiredOption("--reason <text>", "Reason for exiting the workflow (required)").action(async (options) => {
17516
17639
  await maybeRequireAuth();
17517
17640
  if (!options.reason || options.reason.trim().length === 0) {
17518
17641
  console.error("❌ --reason is required and cannot be empty");
17519
17642
  process.exit(1);
17520
17643
  }
17521
- const { cancelStep: cancelStep2 } = await Promise.resolve().then(() => (init_workflow(), exports_workflow));
17522
- await cancelStep2(options.chatroomId, {
17644
+ const { exitWorkflow: exitWorkflow2 } = await Promise.resolve().then(() => (init_workflow(), exports_workflow));
17645
+ await exitWorkflow2(options.chatroomId, {
17523
17646
  role: options.role,
17524
17647
  workflowKey: options.workflowKey,
17525
- stepKey: options.stepKey,
17526
17648
  reason: options.reason
17527
17649
  });
17528
17650
  });
17529
- workflowCommand.command("exit").description("Exit (cancel) an entire workflow with a reason").requiredOption("--chatroom-id <id>", "Chatroom identifier").requiredOption("--role <role>", "Your role").requiredOption("--workflow-key <key>", "Workflow key to exit").requiredOption("--reason <text>", "Reason for exiting the workflow (required)").action(async (options) => {
17651
+ workflowCommand.command("step-view").description("View the full details and specification of a single workflow step").requiredOption("--chatroom-id <id>", "Chatroom identifier").requiredOption("--role <role>", "Your role").requiredOption("--workflow-key <key>", "Workflow key").requiredOption("--step-key <stepKey>", "Step key to view").action(async (options) => {
17530
17652
  await maybeRequireAuth();
17531
- if (!options.reason || options.reason.trim().length === 0) {
17532
- console.error("❌ --reason is required and cannot be empty");
17533
- process.exit(1);
17534
- }
17535
- const { exitWorkflow: exitWorkflow2 } = await Promise.resolve().then(() => (init_workflow(), exports_workflow));
17536
- await exitWorkflow2(options.chatroomId, {
17653
+ const { viewStep: viewStep2 } = await Promise.resolve().then(() => (init_workflow(), exports_workflow));
17654
+ await viewStep2(options.chatroomId, {
17537
17655
  role: options.role,
17538
17656
  workflowKey: options.workflowKey,
17539
- reason: options.reason
17657
+ stepKey: options.stepKey
17540
17658
  });
17541
17659
  });
17542
17660
  var taskCommand = program2.command("task").description("Manage tasks");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chatroom-cli",
3
- "version": "1.13.3",
3
+ "version": "1.14.1",
4
4
  "description": "CLI for multi-agent chatroom collaboration",
5
5
  "type": "module",
6
6
  "bin": {