@tt-a1i/hive 2.1.6 → 2.1.7

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 (35) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/src/server/agent-runtime-contract.d.ts +1 -9
  3. package/dist/src/server/agent-runtime.js +1 -7
  4. package/dist/src/server/agent-stdin-dispatcher.d.ts +2 -11
  5. package/dist/src/server/agent-stdin-dispatcher.js +14 -12
  6. package/dist/src/server/post-start-input-writer.js +1 -1
  7. package/dist/src/server/report-outbox-store.d.ts +10 -8
  8. package/dist/src/server/report-outbox-store.js +10 -1
  9. package/dist/src/server/routes-remote.js +46 -14
  10. package/dist/src/server/routes-team.js +1 -1
  11. package/dist/src/server/routes-workspaces.js +3 -6
  12. package/dist/src/server/runtime-store-contract.d.ts +2 -2
  13. package/dist/src/server/runtime-store-helpers.d.ts +4 -0
  14. package/dist/src/server/runtime-store-helpers.js +34 -11
  15. package/dist/src/server/runtime-store-worker-mutations.js +12 -6
  16. package/dist/src/server/runtime-store-workflows.js +7 -1
  17. package/dist/src/server/team-operations.d.ts +12 -5
  18. package/dist/src/server/team-operations.js +217 -158
  19. package/dist/src/shared/remote-bridge-routing.js +3 -1
  20. package/package.json +1 -1
  21. package/web/dist/assets/{AddWorkerDialog-DFNkbR_Q.js → AddWorkerDialog-DuUFz6UK.js} +2 -2
  22. package/web/dist/assets/{AddWorkspaceFlow-BjpjCuRe.js → AddWorkspaceFlow-CFuHJXFe.js} +1 -1
  23. package/web/dist/assets/{FirstRunWizard-BuLgUAny.js → FirstRunWizard-qA5b90Ru.js} +1 -1
  24. package/web/dist/assets/{MarketplaceDrawer-BALuhrnd.js → MarketplaceDrawer-BdkVJyI0.js} +1 -1
  25. package/web/dist/assets/{TaskGraphDrawer-DQTS6JPI.js → TaskGraphDrawer-DDhX2p_z.js} +1 -1
  26. package/web/dist/assets/{WhatsNewDialog-DpgjEIaA.js → WhatsNewDialog-Cp_gv_Co.js} +1 -1
  27. package/web/dist/assets/{WorkerModal-1y-Xdwv-.js → WorkerModal-BbKQsSSJ.js} +1 -1
  28. package/web/dist/assets/{WorkflowsDrawer-DPWlZs4S.js → WorkflowsDrawer-wk6HSGNl.js} +1 -1
  29. package/web/dist/assets/{WorkspaceMemoryDrawer-C0vny4zK.js → WorkspaceMemoryDrawer-CSxU_0b1.js} +1 -1
  30. package/web/dist/assets/{WorkspaceTaskDrawer-CJcFZh8C.js → WorkspaceTaskDrawer-Bz3fMad9.js} +1 -1
  31. package/web/dist/assets/{index-CR1SPGBZ.js → index-B3XoRj0C.js} +28 -28
  32. package/web/dist/assets/{search-Bl5O-SfR.js → search-BdM5IXYB.js} +1 -1
  33. package/web/dist/assets/{square-terminal-DCDaflg3.js → square-terminal-DnmshYpr.js} +1 -1
  34. package/web/dist/index.html +1 -1
  35. package/web/dist/sw.js +1 -1
@@ -50,27 +50,55 @@ const buildPendingWarning = (workerName, pendingTaskCount, action) => pendingTas
50
50
  ? `Hive recorded the ${action}, but ${workerName} still has ${pendingTaskCount} open dispatch${pendingTaskCount === 1 ? '' : 'es'}. ` +
51
51
  'A worker stays working until every dispatch is closed with `team report --dispatch <id>` or `team cancel --dispatch <id>`.'
52
52
  : undefined;
53
- export const createTeamOperations = ({ agentRuntime, createDispatch, deleteDispatch, deleteMessage, findOpenDispatch, findOpenDispatchById, listOpenWorkspaceDispatches, insertMessage, markDispatchCancelled, markDispatchReportedByWorker, claimQueuedDispatch, reparkClaimedDispatch, reportOutbox, notifyWebhook, workflowDispatchAwaiter, workspaceStore, dismissEphemeralWorker, recordProtocolEvent, getFlags, }) => {
53
+ export const createTeamOperations = ({ agentRuntime, createDispatch, deleteDispatch, deleteMessage, findOpenDispatch, findOpenDispatchById, listOpenWorkspaceDispatches, insertMessage, markDispatchCancelled, markDispatchReportedByWorker, claimQueuedDispatch, reparkClaimedDispatch, reportOutbox, notifyWebhook, runDataMutation, isRuntimeClosing, workflowDispatchAwaiter, workspaceStore, dismissEphemeralWorker, recordProtocolEvent, getFlags, }) => {
54
54
  const flags = () => getFlags?.() ?? FEATURE_FLAGS_ALL_OFF;
55
+ const runMutation = runDataMutation ?? ((mutation) => mutation());
56
+ const runtimeClosing = () => isRuntimeClosing?.() === true;
57
+ const drainingReportOutboxIds = new Set();
55
58
  // Best-effort redelivery of reports a prior orchestrator outage stranded.
56
59
  // Called when a fresh report confirms the orchestrator is reachable and
57
60
  // when the orchestrator polls `team list` (its natural post-restart wakeup).
58
61
  // An entry is marked delivered only after its PTY write actually resolves,
59
62
  // so a still-down orchestrator just leaves the backlog pending.
60
- const drainReportOutbox = (workspaceId) => {
61
- const orchestratorId = `${workspaceId}:orchestrator`;
62
- if (!agentRuntime.getActiveRunByAgentId(workspaceId, orchestratorId))
63
- return;
64
- for (const entry of reportOutbox.listPending(workspaceId, orchestratorId)) {
65
- void agentRuntime
66
- .deliverSystemMessageToAgent(workspaceId, orchestratorId, entry.payload, {
67
- requireActiveRun: true,
68
- })
69
- .then(() => reportOutbox.markDelivered(entry.id))
70
- .catch((error) => {
71
- console.error('[hive] swallowed:teamReport.outboxDrain', error);
72
- });
63
+ const drainReportOutbox = (workspaceId, targetAgentId = `${workspaceId}:orchestrator`) => {
64
+ if (runtimeClosing())
65
+ return { attempted: 0, firstSyncError: null };
66
+ if (!agentRuntime.getActiveRunByAgentId(workspaceId, targetAgentId)) {
67
+ return { attempted: 0, firstSyncError: null };
68
+ }
69
+ let attempted = 0;
70
+ let firstSyncError = null;
71
+ for (const entry of reportOutbox.listPending(workspaceId, targetAgentId)) {
72
+ if (drainingReportOutboxIds.has(entry.id))
73
+ continue;
74
+ drainingReportOutboxIds.add(entry.id);
75
+ attempted += 1;
76
+ try {
77
+ void agentRuntime
78
+ .deliverSystemMessageToAgent(workspaceId, targetAgentId, entry.payload, {
79
+ requireActiveRun: true,
80
+ })
81
+ .then(() => {
82
+ if (!runtimeClosing())
83
+ reportOutbox.markDelivered(entry.id);
84
+ })
85
+ .catch((error) => {
86
+ if (runtimeClosing())
87
+ return;
88
+ console.error('[hive] swallowed:teamReport.outboxDrain', error);
89
+ })
90
+ .finally(() => {
91
+ drainingReportOutboxIds.delete(entry.id);
92
+ });
93
+ }
94
+ catch (error) {
95
+ drainingReportOutboxIds.delete(entry.id);
96
+ firstSyncError ??= reportForwardErrorMessage(error);
97
+ if (!runtimeClosing())
98
+ console.error('[hive] swallowed:teamReport.outboxDrain', error);
99
+ }
73
100
  }
101
+ return { attempted, firstSyncError };
74
102
  };
75
103
  const ensureWorkerRun = async (workspaceId, workerId, hivePort) => {
76
104
  const activeRun = agentRuntime.getActiveRunByAgentId(workspaceId, workerId);
@@ -125,6 +153,7 @@ export const createTeamOperations = ({ agentRuntime, createDispatch, deleteDispa
125
153
  return workerId;
126
154
  }
127
155
  };
156
+ const buildIssuerSystemReminderPayload = (text) => `<hive-system-reminder>\n${escapeHiveEnvelopeText(text)}\n</hive-system-reminder>\n`;
128
157
  /** Issuer notification that survives the issuer being down: try the live
129
158
  * PTY first; if the issuer has no active run (or the write rejects), park
130
159
  * the notice in the report outbox — it drains on the issuer's next
@@ -132,7 +161,7 @@ export const createTeamOperations = ({ agentRuntime, createDispatch, deleteDispa
132
161
  * (A fire-and-forget writeSystemMessageToAgent silently no-ops without an
133
162
  * active run, which is exactly when failures cluster — post-restart.) */
134
163
  const notifyIssuerDurably = (workspaceId, issuerAgentId, dispatchId, text) => {
135
- const payload = `<hive-system-reminder>\n${escapeHiveEnvelopeText(text)}\n</hive-system-reminder>\n`;
164
+ const payload = buildIssuerSystemReminderPayload(text);
136
165
  const park = () => {
137
166
  try {
138
167
  reportOutbox.enqueue({
@@ -157,28 +186,30 @@ export const createTeamOperations = ({ agentRuntime, createDispatch, deleteDispa
157
186
  park();
158
187
  }
159
188
  };
160
- /** Called before a worker (and its dispatch rows) are deleted: open
161
- * non-workflow dispatches would otherwise vanish without the issuer ever
162
- * hearing a third silent outcome next to delivered/cancelled. */
189
+ /** Called inside the worker-delete transaction after stale pending outbox rows
190
+ * for the doomed dispatches are removed, but before dispatch rows are
191
+ * deleted. Open non-workflow dispatches get a durable issuer notice, avoiding
192
+ * a third silent outcome next to delivered/cancelled. */
163
193
  const notifyIssuersOfDroppedDispatches = (workspaceId, workerId, reason) => {
164
- let open;
165
- try {
166
- open = listOpenWorkspaceDispatches(workspaceId).filter((item) => item.toAgentId === workerId &&
167
- item.workflowRunId === null &&
168
- item.fromAgentId !== null &&
169
- item.fromAgentId !== getWorkflowAgentId(workspaceId));
170
- }
171
- catch (error) {
172
- console.error('[hive] swallowed:teamDismiss.listOpen', error);
173
- return;
174
- }
194
+ const open = listOpenWorkspaceDispatches(workspaceId).filter((item) => item.toAgentId === workerId &&
195
+ item.workflowRunId === null &&
196
+ item.fromAgentId !== null &&
197
+ item.fromAgentId !== getWorkflowAgentId(workspaceId));
175
198
  const workerName = workerNameOrId(workspaceId, workerId);
199
+ const targetAgentIds = new Set();
176
200
  for (const item of open) {
177
201
  if (!item.fromAgentId)
178
202
  continue;
179
- notifyIssuerDurably(workspaceId, item.fromAgentId, item.id, `Dispatch ${item.id} to @${workerName} was DROPPED: ${reason}. ` +
180
- 'It will not run and cannot be reported — re-dispatch the task to another worker if it still matters.');
203
+ targetAgentIds.add(item.fromAgentId);
204
+ reportOutbox.enqueue({
205
+ workspaceId,
206
+ targetAgentId: item.fromAgentId,
207
+ dispatchId: item.id,
208
+ payload: buildIssuerSystemReminderPayload(`Dispatch ${item.id} to @${workerName} was DROPPED: ${reason}. ` +
209
+ 'It will not run and cannot be reported — re-dispatch the task to another worker if it still matters.'),
210
+ });
181
211
  }
212
+ return [...targetAgentIds];
182
213
  };
183
214
  /** #33: deliver dispatches parked while their worker was stopped. Called on
184
215
  * worker run start (lifecycle) and after dispatchTask auto-starts a worker.
@@ -213,6 +244,8 @@ export const createTeamOperations = ({ agentRuntime, createDispatch, deleteDispa
213
244
  must not destroy parked work. If the row is no longer 'submitted'
214
245
  (reported/cancelled meanwhile), the repark loses and we leave it be. */
215
246
  const failDispatch = (item, error) => {
247
+ if (runtimeClosing())
248
+ return;
216
249
  if (isPromptReadinessTimeoutError(error)) {
217
250
  try {
218
251
  cancelUndeliveredDispatch(workspaceId, workerId, item.id, reportForwardErrorMessage(error), item.workflowRunId ?? undefined, item.fromAgentId ?? undefined);
@@ -303,6 +336,8 @@ export const createTeamOperations = ({ agentRuntime, createDispatch, deleteDispa
303
336
  try {
304
337
  const writePrompt = agentRuntime.writeSendPrompt(workspaceId, workerId, dispatchId, sender.name, currentWorker.description, text);
305
338
  void writePrompt.catch((error) => {
339
+ if (runtimeClosing())
340
+ return;
306
341
  // `team send` is intentionally asynchronous (§3.3). A worker that
307
342
  // exits during paste-submit did not receive actionable work, so
308
343
  // close the open dispatch instead of leaving a fake pending task.
@@ -344,6 +379,8 @@ export const createTeamOperations = ({ agentRuntime, createDispatch, deleteDispa
344
379
  workspaceStore.markTaskDispatched(workspaceId, workerId);
345
380
  pendingMarked = true;
346
381
  const cancelDeferredDispatch = (error) => {
382
+ if (runtimeClosing())
383
+ return;
347
384
  try {
348
385
  cancelUndeliveredDispatch(workspaceId, workerId, dispatchId, reportForwardErrorMessage(error), input.workflowRunId, isWorkflowDispatch ? undefined : fromAgentId);
349
386
  }
@@ -356,6 +393,8 @@ export const createTeamOperations = ({ agentRuntime, createDispatch, deleteDispa
356
393
  };
357
394
  void deferUntilPostStartReady
358
395
  .then(() => {
396
+ if (runtimeClosing())
397
+ return;
359
398
  const current = listOpenWorkspaceDispatches(workspaceId).find((item) => item.id === dispatchId);
360
399
  if (!current || current.status !== 'queued')
361
400
  return;
@@ -408,7 +447,7 @@ export const createTeamOperations = ({ agentRuntime, createDispatch, deleteDispa
408
447
  }
409
448
  };
410
449
  return {
411
- cancelTask(workspaceId, dispatchId, input) {
450
+ async cancelTask(workspaceId, dispatchId, input) {
412
451
  workspaceStore.getAgent(workspaceId, input.fromAgentId);
413
452
  const openDispatch = findOpenDispatchById(workspaceId, dispatchId);
414
453
  if (!openDispatch) {
@@ -433,7 +472,9 @@ export const createTeamOperations = ({ agentRuntime, createDispatch, deleteDispa
433
472
  let forwardError = null;
434
473
  let forwarded = false;
435
474
  try {
436
- agentRuntime.writeCancelPrompt(workspaceId, dispatch.toAgentId, dispatch.id, input.reason);
475
+ await agentRuntime.writeCancelPrompt(workspaceId, dispatch.toAgentId, dispatch.id, input.reason, {
476
+ requireActiveRun: true,
477
+ });
437
478
  forwarded = true;
438
479
  }
439
480
  catch (error) {
@@ -474,10 +515,21 @@ export const createTeamOperations = ({ agentRuntime, createDispatch, deleteDispa
474
515
  },
475
516
  async deliverUserInput(workspaceId, orchestratorId, text) {
476
517
  workspaceStore.getAgent(workspaceId, orchestratorId);
477
- await agentRuntime.deliverUserInputToOrchestrator(workspaceId, text, {
478
- requireActiveRun: true,
479
- });
480
- insertMessage(createUserInputMessage(workspaceId, orchestratorId, text));
518
+ const messageHandle = insertMessage(createUserInputMessage(workspaceId, orchestratorId, text));
519
+ try {
520
+ await agentRuntime.deliverUserInputToOrchestrator(workspaceId, text, {
521
+ requireActiveRun: true,
522
+ });
523
+ }
524
+ catch (error) {
525
+ try {
526
+ deleteMessage(messageHandle);
527
+ }
528
+ catch (deleteError) {
529
+ console.error('[hive] swallowed:userInput.rollback', deleteError);
530
+ }
531
+ throw error;
532
+ }
481
533
  },
482
534
  statusTask(workspaceId, workerId, input = {}) {
483
535
  const text = input.text ?? '';
@@ -522,146 +574,153 @@ export const createTeamOperations = ({ agentRuntime, createDispatch, deleteDispa
522
574
  if (!openDispatch) {
523
575
  throw new ConflictError(formatNoOpenDispatchError(worker.name, input.dispatchId, listOpenWorkspaceDispatches(workspaceId).filter((item) => item.toAgentId === workerId)));
524
576
  }
525
- const messageHandle = insertMessage(createReportMessage(workspaceId, workerId, text, status, artifacts));
577
+ let messageHandle;
578
+ let dispatch;
579
+ let reportQueuedBeforeCommit = false;
580
+ const orchestratorId = `${workspaceId}:orchestrator`;
581
+ const payload = buildOrchestratorReportPayload(worker.name, text, artifacts, flags(), openDispatch.id);
582
+ const workflowDispatch = openDispatch.fromAgentId === getWorkflowAgentId(workspaceId);
583
+ const shouldQueueForOrchestrator = input.requireActiveRun === true && !workflowDispatch;
584
+ if (shouldQueueForOrchestrator &&
585
+ agentRuntime.getActiveRunByAgentId(workspaceId, orchestratorId)) {
586
+ drainReportOutbox(workspaceId);
587
+ }
526
588
  try {
527
- const dispatch = markDispatchReportedByWorker({
528
- artifacts,
529
- ...(input.dispatchId ? { dispatchId: input.dispatchId } : {}),
530
- reportText: text,
531
- toAgentId: workerId,
532
- workspaceId,
533
- });
534
- if (!dispatch) {
535
- // Post-race recheck: the dispatch closed between the precheck and
536
- // the ledger write — re-query so the 409 lists what is still open.
537
- throw new ConflictError(formatNoOpenDispatchError(worker.name, input.dispatchId, listOpenWorkspaceDispatches(workspaceId).filter((item) => item.toAgentId === workerId)));
538
- }
539
- workspaceStore.markTaskReported(workspaceId, workerId);
540
- recordProtocolEvent?.('report');
541
- const remainingPendingTaskCount = workspaceStore.getWorker(workspaceId, workerId).pendingTaskCount;
542
- let forwardError = null;
543
- let forwarded = false;
544
- const pendingWarning = buildPendingWarning(worker.name, remainingPendingTaskCount, 'report');
545
- // Workflow-sourced dispatches: the source is the in-process runner, not a
546
- // PTY. Resolve its awaiting Promise instead of injecting into orchestrator
547
- // stdin (which would do nothing — `__workflow__` has no PTY).
548
- if (dispatch.fromAgentId === getWorkflowAgentId(workspaceId)) {
549
- try {
550
- workflowDispatchAwaiter.notifyReport(dispatch.id, {
551
- artifacts,
552
- text,
553
- ...(status ? { status } : {}),
554
- });
555
- forwarded = true;
556
- }
557
- catch (error) {
558
- forwardError = reportForwardErrorMessage(error);
559
- console.error('[hive] swallowed:teamReport.workflowForward', error);
560
- }
561
- return {
562
- dispatch,
563
- forwardError,
564
- forwarded,
565
- ...(pendingWarning ? { pendingWarning } : {}),
566
- };
567
- }
568
- // Real worker reported (not a workflow-internal step) — fire the
569
- // outbound completion webhook. Best-effort; never blocks the report.
570
- notifyWebhook?.({
571
- type: 'report_received',
572
- workspaceId,
573
- agentId: workerId,
574
- agentName: worker.name,
575
- summary: text.slice(0, 280),
576
- at: Date.now(),
577
- });
578
- if (input.requireActiveRun === true) {
579
- const orchestratorId = `${workspaceId}:orchestrator`;
580
- // A fresh report proves the orchestrator is reachable — flush any
581
- // backlog a prior outage stranded first, in arrival order, before
582
- // this one (both ride the dispatcher's per-agent serial queue).
583
- drainReportOutbox(workspaceId);
584
- const payload = buildOrchestratorReportPayload(worker.name, text, artifacts, flags());
585
- if (agentRuntime.getActiveRunByAgentId(workspaceId, orchestratorId)) {
586
- try {
587
- const delivery = agentRuntime.deliverReportToOrchestrator(workspaceId, worker.name, text, artifacts, { requireActiveRun: true });
588
- forwarded = true;
589
- // The dispatch is already marked reported. If the PTY dies
590
- // mid-write the ledger would say "reported" while the
591
- // orchestrator never received it — persist for redelivery so it
592
- // isn't silently lost.
593
- void delivery.catch((error) => {
594
- console.error('[hive] swallowed:teamReport.forward', error);
595
- reportOutbox.enqueue({
596
- workspaceId,
597
- targetAgentId: orchestratorId,
598
- dispatchId: dispatch.id,
599
- payload,
600
- });
601
- });
602
- }
603
- catch (error) {
604
- // TOCTOU: orchestrator vanished between the active-run check and
605
- // the write. Same fix — queue it.
606
- console.error('[hive] swallowed:teamReport.forward', error);
607
- forwardError = reportForwardErrorMessage(error);
608
- reportOutbox.enqueue({
609
- workspaceId,
610
- targetAgentId: orchestratorId,
611
- dispatchId: dispatch.id,
612
- payload,
613
- });
614
- }
615
- }
616
- else {
617
- // Orchestrator is down. Queue the report instead of dropping it;
618
- // the CLI surfaces forwarded:false and the backlog drains on the
619
- // orchestrator's next `team list` after it restarts.
620
- forwardError = 'Orchestrator is not running; report queued for delivery.';
589
+ runMutation(() => {
590
+ messageHandle = insertMessage(createReportMessage(workspaceId, workerId, text, status, artifacts));
591
+ if (shouldQueueForOrchestrator) {
621
592
  reportOutbox.enqueue({
622
593
  workspaceId,
623
594
  targetAgentId: orchestratorId,
624
- dispatchId: dispatch.id,
595
+ dispatchId: openDispatch.id,
625
596
  payload,
626
597
  });
598
+ reportQueuedBeforeCommit = true;
627
599
  }
628
- }
629
- // M11: if this worker was spawned with `team spawn --ephemeral`, the
630
- // report that closes its LAST open dispatch triggers auto-dismiss.
631
- // Gating on remainingPendingTaskCount === 0 keeps the one-shot
632
- // semantics for the normal single-dispatch case while not deleting
633
- // still-queued dispatches un-reported when the orchestrator stacked
634
- // several sends. (If the last dispatch closes via `team cancel`
635
- // instead, the worker lingers until the orchestrator-exit cascade /
636
- // boot cleanup collects it.) Deferred via queueMicrotask so the
637
- // orchestrator's forward write lands BEFORE the worker's PTY is torn
638
- // down (otherwise the inject + dismiss race). Skipped for workflow
639
- // dispatches — workflow workers are managed by the runner's own
640
- // finally block.
641
- if (worker.ephemeral === true &&
642
- worker.spawnedBy === 'orchestrator' &&
643
- remainingPendingTaskCount === 0 &&
644
- dismissEphemeralWorker) {
645
- queueMicrotask(() => {
600
+ const nextDispatch = markDispatchReportedByWorker({
601
+ artifacts,
602
+ ...(input.dispatchId ? { dispatchId: input.dispatchId } : {}),
603
+ reportText: text,
604
+ toAgentId: workerId,
605
+ workspaceId,
606
+ });
607
+ if (!nextDispatch) {
608
+ // Post-race recheck: the dispatch closed between the precheck and
609
+ // the ledger write re-query so the 409 lists what is still open.
610
+ throw new ConflictError(formatNoOpenDispatchError(worker.name, input.dispatchId, listOpenWorkspaceDispatches(workspaceId).filter((item) => item.toAgentId === workerId)));
611
+ }
612
+ dispatch = nextDispatch;
613
+ recordProtocolEvent?.('report');
614
+ });
615
+ }
616
+ catch (error) {
617
+ if (!runDataMutation) {
618
+ if (reportQueuedBeforeCommit) {
646
619
  try {
647
- dismissEphemeralWorker(workspaceId, workerId);
620
+ reportOutbox.deletePendingForDispatch(openDispatch.id);
648
621
  }
649
- catch (error) {
650
- console.error('[hive] swallowed:teamReport.ephemeralDismiss', error);
622
+ catch (deleteOutboxError) {
623
+ console.error('[hive] swallowed:teamReport.outboxRollback', deleteOutboxError);
651
624
  }
625
+ }
626
+ if (messageHandle)
627
+ deleteMessage(messageHandle);
628
+ }
629
+ throw error;
630
+ }
631
+ if (!dispatch)
632
+ throw new Error('Report dispatch was not committed');
633
+ const committedDispatch = dispatch;
634
+ workspaceStore.markTaskReported(workspaceId, workerId);
635
+ const remainingPendingTaskCount = workspaceStore.getWorker(workspaceId, workerId).pendingTaskCount;
636
+ let forwardError = null;
637
+ let forwarded = false;
638
+ const pendingWarning = buildPendingWarning(worker.name, remainingPendingTaskCount, 'report');
639
+ // Workflow-sourced dispatches: the source is the in-process runner, not a
640
+ // PTY. Resolve its awaiting Promise instead of injecting into orchestrator
641
+ // stdin (which would do nothing — `__workflow__` has no PTY).
642
+ if (committedDispatch.fromAgentId === getWorkflowAgentId(workspaceId)) {
643
+ try {
644
+ workflowDispatchAwaiter.notifyReport(committedDispatch.id, {
645
+ artifacts,
646
+ text,
647
+ ...(status ? { status } : {}),
652
648
  });
649
+ forwarded = true;
650
+ }
651
+ catch (error) {
652
+ forwardError = reportForwardErrorMessage(error);
653
+ console.error('[hive] swallowed:teamReport.workflowForward', error);
653
654
  }
654
655
  return {
655
- dispatch,
656
+ dispatch: committedDispatch,
656
657
  forwardError,
657
658
  forwarded,
658
659
  ...(pendingWarning ? { pendingWarning } : {}),
659
660
  };
660
661
  }
661
- catch (error) {
662
- deleteMessage(messageHandle);
663
- throw error;
662
+ // Real worker reported (not a workflow-internal step) — fire the
663
+ // outbound completion webhook. Best-effort; never blocks the report.
664
+ notifyWebhook?.({
665
+ type: 'report_received',
666
+ workspaceId,
667
+ agentId: workerId,
668
+ agentName: worker.name,
669
+ summary: text.slice(0, 280),
670
+ at: Date.now(),
671
+ });
672
+ if (input.requireActiveRun === true) {
673
+ if (agentRuntime.getActiveRunByAgentId(workspaceId, orchestratorId)) {
674
+ const drainResult = drainReportOutbox(workspaceId, orchestratorId);
675
+ forwarded = false;
676
+ forwardError =
677
+ drainResult.firstSyncError ??
678
+ (reportQueuedBeforeCommit
679
+ ? 'Report queued for durable delivery; redelivery is in progress.'
680
+ : null);
681
+ }
682
+ else {
683
+ // Orchestrator is down. Queue the report instead of dropping it;
684
+ // the CLI surfaces forwarded:false and the backlog drains on the
685
+ // orchestrator's next `team list` after it restarts.
686
+ forwardError = reportQueuedBeforeCommit
687
+ ? 'Orchestrator is not running; report queued for delivery.'
688
+ : 'Orchestrator is not running; report could not be queued for delivery.';
689
+ }
690
+ }
691
+ // M11: if this worker was spawned with `team spawn --ephemeral`, the
692
+ // report that closes its LAST open dispatch triggers auto-dismiss.
693
+ // Gating on remainingPendingTaskCount === 0 keeps the one-shot
694
+ // semantics for the normal single-dispatch case while not deleting
695
+ // still-queued dispatches un-reported when the orchestrator stacked
696
+ // several sends. (If the last dispatch closes via `team cancel`
697
+ // instead, the worker lingers until the orchestrator-exit cascade /
698
+ // boot cleanup collects it.) Deferred via queueMicrotask so the
699
+ // orchestrator's forward write lands BEFORE the worker's PTY is torn
700
+ // down (otherwise the inject + dismiss race). Skipped for workflow
701
+ // dispatches — workflow workers are managed by the runner's own
702
+ // finally block.
703
+ if (worker.ephemeral === true &&
704
+ worker.spawnedBy === 'orchestrator' &&
705
+ remainingPendingTaskCount === 0 &&
706
+ dismissEphemeralWorker) {
707
+ queueMicrotask(() => {
708
+ if (runtimeClosing())
709
+ return;
710
+ try {
711
+ dismissEphemeralWorker(workspaceId, workerId);
712
+ }
713
+ catch (error) {
714
+ console.error('[hive] swallowed:teamReport.ephemeralDismiss', error);
715
+ }
716
+ });
664
717
  }
718
+ return {
719
+ dispatch: committedDispatch,
720
+ forwardError,
721
+ forwarded,
722
+ ...(pendingWarning ? { pendingWarning } : {}),
723
+ };
665
724
  },
666
725
  };
667
726
  };
@@ -29,7 +29,7 @@ const ALLOWED_METHODS = new Set(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD'
29
29
  // routes-ui refusing tunnel-tagged requests is layer (3).
30
30
  const DENIED_HTTP_PATHS = new Set(['/api/ui/session']);
31
31
  // HARDEN (trust-root defense-in-depth): the device-pairing TRUST-ROOT actions — begin a pairing,
32
- // confirm/approve a device, reject a pending one — are desktop-only at the route layer
32
+ // list pending approvals, confirm/approve a device, reject a pending one — are desktop-only at the route layer
33
33
  // (routes-remote.gateLocalDesktopOnly). The Authority Model says a phone can NEVER self-approve a
34
34
  // new device, so we mirror /api/ui/session's layered defense: layer 1 hard-denies these here on the
35
35
  // bridge (a forwarded frame is Reset(StreamRefused) + audited path_denied), layer 3 is the route gate.
@@ -39,6 +39,8 @@ const DENIED_HTTP_PATHS = new Set(['/api/ui/session']);
39
39
  const isDeniedPairingPath = (pathname) => {
40
40
  if (pathname === '/api/remote/pairings')
41
41
  return true; // begin a pairing (POST)
42
+ if (pathname === '/api/remote/pairings/pending')
43
+ return true; // read pending SAS approvals (GET)
42
44
  // confirm/reject under /api/remote/pairings/:id — match the action suffix on a pairings path.
43
45
  return (pathname.startsWith('/api/remote/pairings/') &&
44
46
  (pathname.endsWith('/confirm') || pathname.endsWith('/reject')));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tt-a1i/hive",
3
- "version": "2.1.6",
3
+ "version": "2.1.7",
4
4
  "description": "Run Claude Code, Codex, Gemini, OpenCode, Qwen, and other CLI agents as a visible local team in your browser.",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@10.30.3",
@@ -1,2 +1,2 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/MarketplaceDrawer-BALuhrnd.js","assets/index-CR1SPGBZ.js","assets/index-CEP_bvOg.css","assets/search-Bl5O-SfR.js"])))=>i.map(i=>d[i]);
2
- import{c as z,j as e,u as j,r as d,C as M,x as L,t as U,J as Y,Q as Z,ag as ee,ah as te,e as ae,i as re,R as se,P as ne,O as oe,k as le,m as ie,a0 as de,z as ce,X as me,T as xe,ai as ue}from"./index-CR1SPGBZ.js";import{S as pe}from"./search-Bl5O-SfR.js";import{S as he}from"./square-terminal-DCDaflg3.js";const fe=[["path",{d:"M12 7v6",key:"lw1j43"}],["path",{d:"M15 10H9",key:"o6yqo3"}],["path",{d:"M17 3a2 2 0 0 1 2 2v15a1 1 0 0 1-1.496.868l-4.512-2.578a2 2 0 0 0-1.984 0l-4.512 2.578A1 1 0 0 1 5 20V5a2 2 0 0 1 2-2z",key:"oz39mx"}]],ge=z("bookmark-plus",fe);const be=[["rect",{width:"12",height:"12",x:"2",y:"10",rx:"2",ry:"2",key:"6agr2n"}],["path",{d:"m17.92 14 3.5-3.5a2.24 2.24 0 0 0 0-3l-5-4.92a2.24 2.24 0 0 0-3 0L10 6",key:"1o487t"}],["path",{d:"M6 18h.01",key:"uhywen"}],["path",{d:"M10 14h.01",key:"ssrbsk"}],["path",{d:"M15 6h.01",key:"cblpky"}],["path",{d:"M18 9h.01",key:"2061c0"}]],ve=z("dices",be);const ke=[["path",{d:"M15 21v-5a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v5",key:"slp6dd"}],["path",{d:"M17.774 10.31a1.12 1.12 0 0 0-1.549 0 2.5 2.5 0 0 1-3.451 0 1.12 1.12 0 0 0-1.548 0 2.5 2.5 0 0 1-3.452 0 1.12 1.12 0 0 0-1.549 0 2.5 2.5 0 0 1-3.77-3.248l2.889-4.184A2 2 0 0 1 7 2h10a2 2 0 0 1 1.653.873l2.895 4.192a2.5 2.5 0 0 1-3.774 3.244",key:"o0xfot"}],["path",{d:"M4 10.95V19a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8.05",key:"wn3emo"}]],je=z("store",ke),ye=[{value:"coder"},{value:"reviewer"},{value:"tester"},{value:"sentinel"},{value:"custom",dashed:!0}],I=t=>`role.${t}`,S=({children:t})=>e.jsx("span",{className:"text-sm font-medium text-sec",children:t}),Ne=({active:t,spec:a,onSelect:n})=>{const{t:s}=j();return e.jsxs("button",{type:"button",onClick:n,"aria-pressed":t,"data-testid":`role-card-${a.value}`,className:`selectable-card${a.dashed?" selectable-card--dashed":""} flex items-center gap-3 px-3 py-2`,children:[e.jsx(ee,{role:a.value,size:20}),e.jsx("span",{className:"flex-1 text-left text-base font-medium text-pri",children:s(I(a.value))}),t?e.jsx(L,{size:14,className:"shrink-0 text-accent","aria-hidden":!0}):null]})},Ce=({onRoleChange:t,workerRole:a})=>{const{t:n}=j();return e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsx(S,{children:n("addWorker.role")}),e.jsx("div",{className:"grid grid-cols-2 gap-2",children:ye.map(s=>e.jsx(Ne,{active:a===s.value,spec:s,onSelect:()=>t(s.value)},s.value))})]})},we=({customTemplates:t,disabledReason:a,onDeleteTemplate:n,onSelect:s,selectedTemplateId:c})=>{const{t:o}=j(),[g,x]=d.useState(!1),[m,u]=d.useState(""),[b,k]=d.useState(null),y=d.useRef(null),N=d.useMemo(()=>t.find(r=>r.id===c)??null,[t,c]),v=d.useMemo(()=>{const r=m.trim().toLowerCase();return r?t.filter(p=>p.name.toLowerCase().includes(r)||p.description.toLowerCase().includes(r)):t},[t,m]);return d.useEffect(()=>{if(!g)return;const r=h=>{h.key==="Escape"&&x(!1)},p=h=>{const l=y.current;l&&!l.contains(h.target)&&x(!1)};return document.addEventListener("keydown",r),document.addEventListener("pointerdown",p),()=>{document.removeEventListener("keydown",r),document.removeEventListener("pointerdown",p)}},[g]),e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsx(S,{children:o("addWorker.template")}),e.jsxs("div",{ref:y,className:"relative",children:[e.jsxs("button",{type:"button","aria-haspopup":"listbox","aria-expanded":g,"data-testid":"role-template-picker-trigger",onClick:()=>x(r=>!r),className:"flex w-full items-center justify-between gap-2 rounded border px-3 py-2 text-left text-sm transition-colors hover:bg-3",style:{borderColor:"var(--border)",background:"var(--bg-1)"},children:[e.jsx("span",{className:"min-w-0 flex-1 truncate text-pri",children:N?N.name:o("addWorker.templatePickPlaceholder")}),e.jsx(M,{size:14,className:"shrink-0 text-ter","aria-hidden":!0})]}),g?e.jsxs("div",{role:"listbox","aria-label":o("addWorker.template"),"data-testid":"role-template-picker-menu",className:"elev-2 absolute left-0 right-0 top-full z-30 mt-1 flex max-h-72 flex-col overflow-hidden rounded border",style:{background:"var(--bg-elevated)",borderColor:"var(--border-bright)"},children:[e.jsxs("div",{className:"flex items-center gap-2 border-b px-2 py-1.5",style:{borderColor:"var(--border)"},children:[e.jsx(pe,{size:14,className:"text-ter","aria-hidden":!0}),e.jsx("input",{value:m,onChange:r=>u(r.currentTarget.value),placeholder:o("addWorker.templateSearchPlaceholder"),"data-testid":"role-template-search-input",className:"w-full bg-transparent text-sm text-pri outline-none placeholder:text-ter",spellCheck:!1})]}),e.jsx("div",{className:"flex-1 overflow-y-auto py-1",children:t.length===0?e.jsx("div",{"data-testid":"role-template-empty-state",className:"px-3 py-3 text-center text-sm text-ter",children:o("addWorker.templateEmpty")}):v.length===0?e.jsx("div",{className:"px-3 py-3 text-center text-sm text-ter",children:o("addWorker.templateNoMatch")}):v.map(r=>{const p=r.id===c;return e.jsxs("div",{className:"relative",children:[e.jsxs("button",{type:"button",role:"option","aria-selected":p,"data-testid":`role-template-option-${r.id}`,onClick:()=>{s(r.id),x(!1),u("")},className:"flex w-full items-center gap-2 px-3 py-1.5 pr-9 text-left text-sm text-pri hover:bg-3",style:p?{background:"var(--bg-3)"}:void 0,children:[e.jsx("span",{className:"min-w-0 flex-1 truncate",children:r.name}),p?e.jsx(L,{size:14,className:"shrink-0 text-accent","aria-hidden":!0}):null]}),e.jsx("button",{type:"button","aria-label":o("addWorker.templateDeleteAria",{name:r.name}),"data-testid":`role-template-delete-${r.id}`,disabled:!!a,title:a??void 0,onClick:h=>{h.preventDefault(),h.stopPropagation(),!a&&k(r)},className:"absolute right-1 top-1/2 flex h-6 w-6 -translate-y-1/2 items-center justify-center rounded text-ter transition-colors hover:bg-3 hover:text-pri",children:e.jsx(U,{size:14,"aria-hidden":!0})})]},r.id)})}),c!==null?e.jsx("button",{type:"button","data-testid":"role-template-clear",onClick:()=>{s(null),x(!1),u("")},className:"border-t px-3 py-1.5 text-left text-sm text-ter transition-colors hover:bg-3 hover:text-pri",style:{borderColor:"var(--border)"},children:o("addWorker.templateClear")}):null]}):null]}),e.jsx(Y,{open:b!==null,onOpenChange:r=>{r||k(null)},title:o("addWorker.templateDeleteTitle"),description:b?o("addWorker.templateDeleteConfirm",{name:b.name}):"",confirmLabel:o("addWorker.templateDeleteConfirmLabel"),confirmKind:"danger",onConfirm:()=>{if(!b||a)return;const r=b.id;k(null),n(r)}})]})},We=({canSaveAsTemplate:t,modified:a,onChange:n,onReset:s,onSaveAsTemplate:c,roleDescription:o,templateBusy:g,workerRole:x,writeDisabledReason:m})=>{const{t:u,language:b}=j(),[k,y]=d.useState(!1),[N,v]=d.useState(!1),[r,p]=d.useState("");d.useEffect(()=>{(x==="custom"||a)&&y(!0)},[a,x]),d.useEffect(()=>{t||(v(!1),p(""))},[t]);const h=b==="zh"?"点击展开":"Click to expand";return e.jsxs("details",{open:k,onToggle:l=>y(l.currentTarget.open),className:"group flex flex-col gap-2",children:[e.jsxs("summary",{className:"flex cursor-pointer select-none items-center justify-between gap-2 list-none rounded-lg p-2 -mx-2 hover:bg-3/50 transition-colors group/summary",children:[e.jsxs("span",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"flex h-5 w-5 items-center justify-center rounded bg-3 border border-bright/30 text-ter transition-colors group-hover/summary:text-pri group-hover/summary:border-accent/40",children:e.jsx(M,{size:12,"aria-hidden":!0,className:"-rotate-90 transition-transform duration-150 group-open:rotate-0"})}),e.jsx("span",{className:"text-sm font-semibold text-pri transition-colors group-hover/summary:text-accent",children:u("addWorker.roleInstructions")}),a?e.jsxs("span",{className:"text-xs text-ter",children:["· ",u("addWorker.modifiedFrom",{role:u(I(x))})]}):null]}),e.jsxs("div",{className:"flex items-center gap-2",children:[k?null:e.jsx("span",{className:"text-[10px] text-ter font-semibold tracking-wider uppercase opacity-60 group-hover/summary:opacity-100 group-hover/summary:text-accent transition-all pr-1",children:h}),t&&!N?e.jsxs("button",{type:"button","data-testid":"role-template-save",disabled:!!m,title:m??void 0,onClick:l=>{l.preventDefault(),l.stopPropagation(),v(!0)},className:"flex items-center gap-1 rounded px-2 py-0.5 text-xs font-medium transition-colors hover:opacity-80 disabled:cursor-not-allowed disabled:opacity-50",style:{color:"var(--accent)",background:"color-mix(in oklab, var(--accent) 14%, transparent)"},children:[e.jsx(ge,{size:12,"aria-hidden":!0}),u("addWorker.saveAsTemplate")]}):null,a?e.jsxs("button",{type:"button",className:"flex items-center gap-1 rounded px-1.5 py-0.5 text-xs text-ter transition-colors hover:bg-3 hover:text-sec",onClick:l=>{l.preventDefault(),l.stopPropagation(),s()},children:[e.jsx(Z,{size:12,"aria-hidden":!0}),u("addWorker.reset")]}):null]})]}),e.jsx("textarea",{"aria-label":"Role instructions",id:"add-worker-role-instructions",value:o,rows:5,onChange:l=>n(l.currentTarget.value),placeholder:x==="custom"?u("addWorker.customPlaceholder"):void 0,title:u("addWorker.roleInstructionsTitle"),className:"input mono resize-y text-sm",style:{minHeight:150},"data-testid":"role-instructions-textarea"}),t&&N?e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("input",{autoFocus:!0,value:r,onChange:l=>p(l.currentTarget.value),placeholder:u("addWorker.templateNamePlaceholder"),"data-testid":"role-template-save-name",className:"input flex-1 text-sm"}),e.jsx("button",{type:"button",disabled:g||!r.trim()||!!m,title:m??void 0,"data-testid":"role-template-save-confirm",onClick:async()=>{if(m)return;const l=r.trim();if(l)try{await c(l),v(!1),p("")}catch{}},className:"icon-btn icon-btn--primary text-xs",children:u("addWorker.templateSaveConfirm")}),e.jsx("button",{type:"button","data-testid":"role-template-save-cancel",onClick:()=>{v(!1),p("")},className:"icon-btn text-xs",children:u("common.cancel")})]}):null]})},D=({active:t,command:a,displayName:n,logoPresetId:s,notFound:c=!1,testId:o,onSelect:g})=>{const{t:x}=j(),m=e.jsx("span",{className:"inline-flex h-5 w-5 shrink-0 items-center justify-center rounded border border-border bg-surface-1 text-ter","data-testid":`${o}-generic-icon`,"aria-hidden":!0,children:e.jsx(he,{size:13})});return e.jsxs("button",{type:"button",onClick:g,"aria-pressed":t,"data-testid":o,className:"selectable-card flex items-center justify-between gap-3 px-3 py-2",children:[e.jsxs("span",{className:"flex min-w-0 items-center gap-3",children:[e.jsx(te,{commandPresetId:s,fallback:m,size:22}),e.jsxs("span",{className:"flex min-w-0 flex-col items-start gap-0.5",children:[e.jsx("span",{className:"truncate text-base font-medium text-pri",children:n}),e.jsxs("span",{className:"mono truncate text-xs text-ter",children:[a,c?` · ${x("addWorker.agentNotFound")}`:""]})]})]}),t?e.jsx(L,{size:14,className:"shrink-0 text-accent","aria-hidden":!0}):null]})},Se=({active:t,preset:a,onSelect:n})=>e.jsx(D,{active:t,command:a.command,displayName:a.displayName,logoPresetId:a.id,notFound:a.available===!1,testId:`agent-radio-${a.id}`,onSelect:n}),ze=({commandPresetId:t,commandPresets:a,onPresetChange:n})=>{const{t:s}=j();return e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsx(S,{children:s("addWorker.agentCli")}),a.length===0?e.jsx("div",{className:"text-sm text-ter",children:s("addWorker.loadingPresets")}):e.jsxs("div",{className:"grid grid-cols-2 gap-2 max-md:grid-cols-1",children:[a.map(c=>e.jsx(Se,{active:t===c.id,preset:c,onSelect:()=>n(c.id)},c.id)),e.jsx(D,{active:t==="",command:s("addWorker.genericCommand"),displayName:s("addWorker.genericAgent"),testId:"agent-radio-generic",onSelect:()=>n("")})]})]})},Me=({onChange:t,value:a})=>{const{t:n,language:s}=j(),[c,o]=d.useState(!1),g=a.trim(),x=s==="zh"?"点击展开":"Click to expand";return e.jsxs("details",{onToggle:m=>o(m.currentTarget.open),className:"group flex flex-col gap-2",children:[e.jsxs("summary",{className:"flex cursor-pointer select-none items-center justify-between gap-2 list-none rounded-lg p-2 -mx-2 hover:bg-3/50 transition-colors group/summary",children:[e.jsxs("span",{className:"flex min-w-0 items-center gap-2",children:[e.jsx("span",{className:"flex h-5 w-5 shrink-0 items-center justify-center rounded bg-3 border border-bright/30 text-ter transition-colors group-hover/summary:text-pri group-hover/summary:border-accent/40",children:e.jsx(M,{size:12,"aria-hidden":!0,className:"-rotate-90 transition-transform duration-150 group-open:rotate-0"})}),e.jsx("span",{className:"text-sm font-semibold text-pri transition-colors group-hover/summary:text-accent",children:n("addWorker.startupCommand")}),g?e.jsxs("span",{className:"truncate text-xs text-ter",children:["· ",n("addWorker.startupOverrides")]}):null]}),c?null:e.jsx("span",{className:"text-[10px] text-ter font-semibold tracking-wider uppercase opacity-60 group-hover/summary:opacity-100 group-hover/summary:text-accent transition-all pr-1",children:x})]}),e.jsxs("div",{className:"flex flex-col gap-2 rounded border bg-2 p-3",style:{borderColor:"var(--border)"},children:[e.jsx("input",{"aria-label":"Startup command",value:a,onChange:m=>t(m.currentTarget.value),placeholder:"qwen --model qwen3-coder",className:"input mono text-sm",spellCheck:!1}),e.jsx("p",{className:"text-sm leading-5 text-ter",children:n("addWorker.startupHelp",{example:"claude --resume <session-id>"})})]})]})},Le=d.lazy(()=>ue(()=>import("./MarketplaceDrawer-BALuhrnd.js"),__vite__mapDeps([0,1,2,3])).then(t=>({default:t.MarketplaceDrawer}))),_e=({commandPresets:t,commandPresetId:a,creating:n=!1,customTemplates:s,onApplyMarketplaceImport:c,onClose:o,onDeleteTemplate:g,onNameChange:x,onPresetChange:m,onRandomName:u,onRoleDescriptionChange:b,onRoleDescriptionReset:k,onRoleChange:y,onSaveAsTemplate:N,onStartupCommandChange:v,onSubmit:r,onTemplateChange:p,roleDescription:h,roleDescriptionDefault:l,selectedTemplateId:P,startupCommand:E,templateBusy:B,workerName:O,workerRole:W,writeDisabledReason:w})=>{const{t:i}=j(),_=ae(),C=re(),[q,A]=d.useState(!1),[H,K]=d.useState(!1),V=d.useMemo(()=>new Set(s.map(f=>f.name)),[s]),Q=f=>{c(f),_.show({kind:"success",message:i("marketplace.imported",{name:f.name})})},J=f=>{f||o()},X=h!==l,$=t.find(f=>f.id===a),T=E.trim(),G=()=>w||(O.trim()?!a&&!T?i("addWorker.pickCliOrStartup"):$?.available===!1&&!T?i("addWorker.unavailable",{name:$.displayName}):h.trim()?null:i("addWorker.emptyInstructions"):i("addWorker.enterName")),R=f=>{const F=G();if(F){f.preventDefault(),_.show({kind:"warning",message:F});return}r(f)};return e.jsxs(se,{open:!0,onOpenChange:J,children:[e.jsxs(ne,{children:[e.jsx(oe,{"data-testid":"add-worker-overlay",className:"app-overlay fixed inset-0 z-40"}),e.jsx("div",{className:"pointer-events-none fixed inset-0 z-50 grid place-items-center p-4 max-md:items-end max-md:p-0",children:e.jsx(le,{"data-testid":"add-worker-content","data-mobile":C||void 0,className:`${C?"dialog-slide-up add-worker-sheet":"dialog-scale-pop"} elev-2 pointer-events-auto flex max-h-[calc(100vh-32px)] w-[560px] max-w-full flex-col overflow-hidden rounded-lg border pointer-coarse:max-h-[85dvh] max-md:w-full max-md:rounded-b-none max-md:rounded-t-xl`,style:{background:"var(--bg-elevated)",borderColor:"var(--border-bright)",...C?{height:"85dvh"}:{}},children:e.jsxs("form",{onSubmit:R,"aria-label":i("addWorker.title"),className:"flex min-h-0 flex-1 flex-col overflow-hidden max-h-full",children:[e.jsxs("div",{className:"flex shrink-0 items-start justify-between gap-3 border-b px-5 py-4 max-md:px-4",style:{borderColor:"var(--border)"},children:[e.jsxs("div",{className:"flex min-w-0 flex-col gap-0.5",children:[e.jsx(ie,{className:"text-lg font-semibold text-pri",children:i("addWorker.title")}),e.jsx(de,{className:"text-sm text-ter",children:i("addWorker.description",{command:"team send"})})]}),C?e.jsx(ce,{asChild:!0,children:e.jsx("button",{type:"button","aria-label":i("common.closeDialog"),"data-testid":"add-worker-close",className:"-mr-1 flex h-10 w-10 shrink-0 items-center justify-center rounded-md text-sec",style:{background:"var(--bg-2)"},children:e.jsx(me,{size:18,"aria-hidden":!0})})}):null]}),e.jsxs("div",{className:"flex flex-1 min-h-0 flex-col gap-4 overflow-y-auto px-5 py-4 max-md:gap-5 max-md:px-4",children:[e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsx(S,{children:i("addWorker.name")}),e.jsxs("div",{className:"relative flex items-center",children:[e.jsx("input",{autoFocus:!C,value:O,onChange:f=>x(f.target.value),placeholder:i("addWorker.namePlaceholder"),className:"input w-full pr-24",style:{borderRadius:"10px"}}),e.jsx("div",{className:"absolute right-1.5 top-1/2 -translate-y-1/2",children:e.jsx(xe,{label:i("addWorker.randomTooltip"),children:e.jsxs("button",{type:"button","aria-label":i("addWorker.randomAria"),className:"flex h-7 items-center gap-1.5 rounded-lg border border-bright/10 bg-3 px-2.5 text-xs font-semibold text-sec hover:text-pri hover:bg-4 active:scale-95 transition-all outline-none",onClick:u,"data-testid":"random-worker-name",children:[e.jsx(ve,{size:13,"aria-hidden":!0}),e.jsx("span",{children:i("addWorker.random")})]})})})]})]}),e.jsx(Ce,{workerRole:W,onRoleChange:y}),e.jsxs("button",{type:"button",onClick:()=>{K(!0),A(!0)},"data-testid":"open-marketplace",className:"marketplace-browse-btn flex cursor-pointer items-center gap-2 self-start rounded-lg border px-3 py-2 text-xs font-semibold text-sec outline-none transition-all duration-200 hover:text-pri hover:-translate-y-0.5 active:scale-98 shadow-sm hover:shadow-md",style:{background:"linear-gradient(to bottom, var(--bg-1), var(--bg-0))",borderColor:"var(--border-bright)","--tw-ring-color":"color-mix(in oklab, var(--accent) 45%, transparent)"},children:[e.jsx(je,{size:14,"aria-hidden":!0,className:"text-accent"}),e.jsx("span",{children:i("marketplace.openFromAddWorker")})]}),W==="custom"?e.jsx(we,{customTemplates:s,disabledReason:w,onDeleteTemplate:g,onSelect:p,selectedTemplateId:P}):null,e.jsx(We,{canSaveAsTemplate:W==="custom"&&!P&&h.trim().length>0,modified:X,onChange:b,onReset:k,onSaveAsTemplate:N,roleDescription:h,templateBusy:B,workerRole:W,writeDisabledReason:w}),e.jsx(ze,{commandPresetId:a,commandPresets:t,onPresetChange:m}),e.jsx(Me,{value:E,onChange:v})]}),e.jsxs("div",{className:"flex shrink-0 items-center justify-end gap-2 border-t px-5 py-3 max-md:px-4 max-md:pb-[max(12px,env(safe-area-inset-bottom))]",style:{borderColor:"var(--border)",background:"var(--bg-2)"},children:[e.jsx("button",{type:"button",onClick:o,className:`icon-btn border border-bright/20 rounded-lg hover:bg-3 hover:text-pri transition-all active:scale-95 ${C?"flex-1":""}`,"data-testid":"add-worker-cancel",children:i("addWorker.cancel")}),e.jsx("button",{type:"submit",disabled:n||!!w,title:w??void 0,className:`icon-btn icon-btn--primary rounded-lg font-bold shadow-md hover:shadow-lg transition-all active:scale-[0.97] hover:-translate-y-0.5 ${C?"flex-[2]":""}`,"data-testid":"add-worker-submit",children:i(n?"addWorker.creating":"addWorker.create")})]})]})})})]}),H?e.jsx(d.Suspense,{fallback:null,children:e.jsx(Le,{open:q,onClose:()=>A(!1),onImport:Q,importedNames:V})}):null]})};export{_e as AddWorkerDialog};
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/MarketplaceDrawer-BdkVJyI0.js","assets/index-B3XoRj0C.js","assets/index-CEP_bvOg.css","assets/search-BdM5IXYB.js"])))=>i.map(i=>d[i]);
2
+ import{c as z,j as e,u as j,r as d,C as M,x as L,t as U,J as Y,Q as Z,ag as ee,ah as te,e as ae,i as re,R as se,P as ne,O as oe,k as le,m as ie,a0 as de,z as ce,X as me,T as xe,ai as ue}from"./index-B3XoRj0C.js";import{S as pe}from"./search-BdM5IXYB.js";import{S as he}from"./square-terminal-DnmshYpr.js";const fe=[["path",{d:"M12 7v6",key:"lw1j43"}],["path",{d:"M15 10H9",key:"o6yqo3"}],["path",{d:"M17 3a2 2 0 0 1 2 2v15a1 1 0 0 1-1.496.868l-4.512-2.578a2 2 0 0 0-1.984 0l-4.512 2.578A1 1 0 0 1 5 20V5a2 2 0 0 1 2-2z",key:"oz39mx"}]],ge=z("bookmark-plus",fe);const be=[["rect",{width:"12",height:"12",x:"2",y:"10",rx:"2",ry:"2",key:"6agr2n"}],["path",{d:"m17.92 14 3.5-3.5a2.24 2.24 0 0 0 0-3l-5-4.92a2.24 2.24 0 0 0-3 0L10 6",key:"1o487t"}],["path",{d:"M6 18h.01",key:"uhywen"}],["path",{d:"M10 14h.01",key:"ssrbsk"}],["path",{d:"M15 6h.01",key:"cblpky"}],["path",{d:"M18 9h.01",key:"2061c0"}]],ve=z("dices",be);const ke=[["path",{d:"M15 21v-5a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v5",key:"slp6dd"}],["path",{d:"M17.774 10.31a1.12 1.12 0 0 0-1.549 0 2.5 2.5 0 0 1-3.451 0 1.12 1.12 0 0 0-1.548 0 2.5 2.5 0 0 1-3.452 0 1.12 1.12 0 0 0-1.549 0 2.5 2.5 0 0 1-3.77-3.248l2.889-4.184A2 2 0 0 1 7 2h10a2 2 0 0 1 1.653.873l2.895 4.192a2.5 2.5 0 0 1-3.774 3.244",key:"o0xfot"}],["path",{d:"M4 10.95V19a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8.05",key:"wn3emo"}]],je=z("store",ke),ye=[{value:"coder"},{value:"reviewer"},{value:"tester"},{value:"sentinel"},{value:"custom",dashed:!0}],I=t=>`role.${t}`,S=({children:t})=>e.jsx("span",{className:"text-sm font-medium text-sec",children:t}),Ne=({active:t,spec:a,onSelect:n})=>{const{t:s}=j();return e.jsxs("button",{type:"button",onClick:n,"aria-pressed":t,"data-testid":`role-card-${a.value}`,className:`selectable-card${a.dashed?" selectable-card--dashed":""} flex items-center gap-3 px-3 py-2`,children:[e.jsx(ee,{role:a.value,size:20}),e.jsx("span",{className:"flex-1 text-left text-base font-medium text-pri",children:s(I(a.value))}),t?e.jsx(L,{size:14,className:"shrink-0 text-accent","aria-hidden":!0}):null]})},Ce=({onRoleChange:t,workerRole:a})=>{const{t:n}=j();return e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsx(S,{children:n("addWorker.role")}),e.jsx("div",{className:"grid grid-cols-2 gap-2",children:ye.map(s=>e.jsx(Ne,{active:a===s.value,spec:s,onSelect:()=>t(s.value)},s.value))})]})},we=({customTemplates:t,disabledReason:a,onDeleteTemplate:n,onSelect:s,selectedTemplateId:c})=>{const{t:o}=j(),[g,x]=d.useState(!1),[m,u]=d.useState(""),[b,k]=d.useState(null),y=d.useRef(null),N=d.useMemo(()=>t.find(r=>r.id===c)??null,[t,c]),v=d.useMemo(()=>{const r=m.trim().toLowerCase();return r?t.filter(p=>p.name.toLowerCase().includes(r)||p.description.toLowerCase().includes(r)):t},[t,m]);return d.useEffect(()=>{if(!g)return;const r=h=>{h.key==="Escape"&&x(!1)},p=h=>{const l=y.current;l&&!l.contains(h.target)&&x(!1)};return document.addEventListener("keydown",r),document.addEventListener("pointerdown",p),()=>{document.removeEventListener("keydown",r),document.removeEventListener("pointerdown",p)}},[g]),e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsx(S,{children:o("addWorker.template")}),e.jsxs("div",{ref:y,className:"relative",children:[e.jsxs("button",{type:"button","aria-haspopup":"listbox","aria-expanded":g,"data-testid":"role-template-picker-trigger",onClick:()=>x(r=>!r),className:"flex w-full items-center justify-between gap-2 rounded border px-3 py-2 text-left text-sm transition-colors hover:bg-3",style:{borderColor:"var(--border)",background:"var(--bg-1)"},children:[e.jsx("span",{className:"min-w-0 flex-1 truncate text-pri",children:N?N.name:o("addWorker.templatePickPlaceholder")}),e.jsx(M,{size:14,className:"shrink-0 text-ter","aria-hidden":!0})]}),g?e.jsxs("div",{role:"listbox","aria-label":o("addWorker.template"),"data-testid":"role-template-picker-menu",className:"elev-2 absolute left-0 right-0 top-full z-30 mt-1 flex max-h-72 flex-col overflow-hidden rounded border",style:{background:"var(--bg-elevated)",borderColor:"var(--border-bright)"},children:[e.jsxs("div",{className:"flex items-center gap-2 border-b px-2 py-1.5",style:{borderColor:"var(--border)"},children:[e.jsx(pe,{size:14,className:"text-ter","aria-hidden":!0}),e.jsx("input",{value:m,onChange:r=>u(r.currentTarget.value),placeholder:o("addWorker.templateSearchPlaceholder"),"data-testid":"role-template-search-input",className:"w-full bg-transparent text-sm text-pri outline-none placeholder:text-ter",spellCheck:!1})]}),e.jsx("div",{className:"flex-1 overflow-y-auto py-1",children:t.length===0?e.jsx("div",{"data-testid":"role-template-empty-state",className:"px-3 py-3 text-center text-sm text-ter",children:o("addWorker.templateEmpty")}):v.length===0?e.jsx("div",{className:"px-3 py-3 text-center text-sm text-ter",children:o("addWorker.templateNoMatch")}):v.map(r=>{const p=r.id===c;return e.jsxs("div",{className:"relative",children:[e.jsxs("button",{type:"button",role:"option","aria-selected":p,"data-testid":`role-template-option-${r.id}`,onClick:()=>{s(r.id),x(!1),u("")},className:"flex w-full items-center gap-2 px-3 py-1.5 pr-9 text-left text-sm text-pri hover:bg-3",style:p?{background:"var(--bg-3)"}:void 0,children:[e.jsx("span",{className:"min-w-0 flex-1 truncate",children:r.name}),p?e.jsx(L,{size:14,className:"shrink-0 text-accent","aria-hidden":!0}):null]}),e.jsx("button",{type:"button","aria-label":o("addWorker.templateDeleteAria",{name:r.name}),"data-testid":`role-template-delete-${r.id}`,disabled:!!a,title:a??void 0,onClick:h=>{h.preventDefault(),h.stopPropagation(),!a&&k(r)},className:"absolute right-1 top-1/2 flex h-6 w-6 -translate-y-1/2 items-center justify-center rounded text-ter transition-colors hover:bg-3 hover:text-pri",children:e.jsx(U,{size:14,"aria-hidden":!0})})]},r.id)})}),c!==null?e.jsx("button",{type:"button","data-testid":"role-template-clear",onClick:()=>{s(null),x(!1),u("")},className:"border-t px-3 py-1.5 text-left text-sm text-ter transition-colors hover:bg-3 hover:text-pri",style:{borderColor:"var(--border)"},children:o("addWorker.templateClear")}):null]}):null]}),e.jsx(Y,{open:b!==null,onOpenChange:r=>{r||k(null)},title:o("addWorker.templateDeleteTitle"),description:b?o("addWorker.templateDeleteConfirm",{name:b.name}):"",confirmLabel:o("addWorker.templateDeleteConfirmLabel"),confirmKind:"danger",onConfirm:()=>{if(!b||a)return;const r=b.id;k(null),n(r)}})]})},We=({canSaveAsTemplate:t,modified:a,onChange:n,onReset:s,onSaveAsTemplate:c,roleDescription:o,templateBusy:g,workerRole:x,writeDisabledReason:m})=>{const{t:u,language:b}=j(),[k,y]=d.useState(!1),[N,v]=d.useState(!1),[r,p]=d.useState("");d.useEffect(()=>{(x==="custom"||a)&&y(!0)},[a,x]),d.useEffect(()=>{t||(v(!1),p(""))},[t]);const h=b==="zh"?"点击展开":"Click to expand";return e.jsxs("details",{open:k,onToggle:l=>y(l.currentTarget.open),className:"group flex flex-col gap-2",children:[e.jsxs("summary",{className:"flex cursor-pointer select-none items-center justify-between gap-2 list-none rounded-lg p-2 -mx-2 hover:bg-3/50 transition-colors group/summary",children:[e.jsxs("span",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"flex h-5 w-5 items-center justify-center rounded bg-3 border border-bright/30 text-ter transition-colors group-hover/summary:text-pri group-hover/summary:border-accent/40",children:e.jsx(M,{size:12,"aria-hidden":!0,className:"-rotate-90 transition-transform duration-150 group-open:rotate-0"})}),e.jsx("span",{className:"text-sm font-semibold text-pri transition-colors group-hover/summary:text-accent",children:u("addWorker.roleInstructions")}),a?e.jsxs("span",{className:"text-xs text-ter",children:["· ",u("addWorker.modifiedFrom",{role:u(I(x))})]}):null]}),e.jsxs("div",{className:"flex items-center gap-2",children:[k?null:e.jsx("span",{className:"text-[10px] text-ter font-semibold tracking-wider uppercase opacity-60 group-hover/summary:opacity-100 group-hover/summary:text-accent transition-all pr-1",children:h}),t&&!N?e.jsxs("button",{type:"button","data-testid":"role-template-save",disabled:!!m,title:m??void 0,onClick:l=>{l.preventDefault(),l.stopPropagation(),v(!0)},className:"flex items-center gap-1 rounded px-2 py-0.5 text-xs font-medium transition-colors hover:opacity-80 disabled:cursor-not-allowed disabled:opacity-50",style:{color:"var(--accent)",background:"color-mix(in oklab, var(--accent) 14%, transparent)"},children:[e.jsx(ge,{size:12,"aria-hidden":!0}),u("addWorker.saveAsTemplate")]}):null,a?e.jsxs("button",{type:"button",className:"flex items-center gap-1 rounded px-1.5 py-0.5 text-xs text-ter transition-colors hover:bg-3 hover:text-sec",onClick:l=>{l.preventDefault(),l.stopPropagation(),s()},children:[e.jsx(Z,{size:12,"aria-hidden":!0}),u("addWorker.reset")]}):null]})]}),e.jsx("textarea",{"aria-label":"Role instructions",id:"add-worker-role-instructions",value:o,rows:5,onChange:l=>n(l.currentTarget.value),placeholder:x==="custom"?u("addWorker.customPlaceholder"):void 0,title:u("addWorker.roleInstructionsTitle"),className:"input mono resize-y text-sm",style:{minHeight:150},"data-testid":"role-instructions-textarea"}),t&&N?e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("input",{autoFocus:!0,value:r,onChange:l=>p(l.currentTarget.value),placeholder:u("addWorker.templateNamePlaceholder"),"data-testid":"role-template-save-name",className:"input flex-1 text-sm"}),e.jsx("button",{type:"button",disabled:g||!r.trim()||!!m,title:m??void 0,"data-testid":"role-template-save-confirm",onClick:async()=>{if(m)return;const l=r.trim();if(l)try{await c(l),v(!1),p("")}catch{}},className:"icon-btn icon-btn--primary text-xs",children:u("addWorker.templateSaveConfirm")}),e.jsx("button",{type:"button","data-testid":"role-template-save-cancel",onClick:()=>{v(!1),p("")},className:"icon-btn text-xs",children:u("common.cancel")})]}):null]})},D=({active:t,command:a,displayName:n,logoPresetId:s,notFound:c=!1,testId:o,onSelect:g})=>{const{t:x}=j(),m=e.jsx("span",{className:"inline-flex h-5 w-5 shrink-0 items-center justify-center rounded border border-border bg-surface-1 text-ter","data-testid":`${o}-generic-icon`,"aria-hidden":!0,children:e.jsx(he,{size:13})});return e.jsxs("button",{type:"button",onClick:g,"aria-pressed":t,"data-testid":o,className:"selectable-card flex items-center justify-between gap-3 px-3 py-2",children:[e.jsxs("span",{className:"flex min-w-0 items-center gap-3",children:[e.jsx(te,{commandPresetId:s,fallback:m,size:22}),e.jsxs("span",{className:"flex min-w-0 flex-col items-start gap-0.5",children:[e.jsx("span",{className:"truncate text-base font-medium text-pri",children:n}),e.jsxs("span",{className:"mono truncate text-xs text-ter",children:[a,c?` · ${x("addWorker.agentNotFound")}`:""]})]})]}),t?e.jsx(L,{size:14,className:"shrink-0 text-accent","aria-hidden":!0}):null]})},Se=({active:t,preset:a,onSelect:n})=>e.jsx(D,{active:t,command:a.command,displayName:a.displayName,logoPresetId:a.id,notFound:a.available===!1,testId:`agent-radio-${a.id}`,onSelect:n}),ze=({commandPresetId:t,commandPresets:a,onPresetChange:n})=>{const{t:s}=j();return e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsx(S,{children:s("addWorker.agentCli")}),a.length===0?e.jsx("div",{className:"text-sm text-ter",children:s("addWorker.loadingPresets")}):e.jsxs("div",{className:"grid grid-cols-2 gap-2 max-md:grid-cols-1",children:[a.map(c=>e.jsx(Se,{active:t===c.id,preset:c,onSelect:()=>n(c.id)},c.id)),e.jsx(D,{active:t==="",command:s("addWorker.genericCommand"),displayName:s("addWorker.genericAgent"),testId:"agent-radio-generic",onSelect:()=>n("")})]})]})},Me=({onChange:t,value:a})=>{const{t:n,language:s}=j(),[c,o]=d.useState(!1),g=a.trim(),x=s==="zh"?"点击展开":"Click to expand";return e.jsxs("details",{onToggle:m=>o(m.currentTarget.open),className:"group flex flex-col gap-2",children:[e.jsxs("summary",{className:"flex cursor-pointer select-none items-center justify-between gap-2 list-none rounded-lg p-2 -mx-2 hover:bg-3/50 transition-colors group/summary",children:[e.jsxs("span",{className:"flex min-w-0 items-center gap-2",children:[e.jsx("span",{className:"flex h-5 w-5 shrink-0 items-center justify-center rounded bg-3 border border-bright/30 text-ter transition-colors group-hover/summary:text-pri group-hover/summary:border-accent/40",children:e.jsx(M,{size:12,"aria-hidden":!0,className:"-rotate-90 transition-transform duration-150 group-open:rotate-0"})}),e.jsx("span",{className:"text-sm font-semibold text-pri transition-colors group-hover/summary:text-accent",children:n("addWorker.startupCommand")}),g?e.jsxs("span",{className:"truncate text-xs text-ter",children:["· ",n("addWorker.startupOverrides")]}):null]}),c?null:e.jsx("span",{className:"text-[10px] text-ter font-semibold tracking-wider uppercase opacity-60 group-hover/summary:opacity-100 group-hover/summary:text-accent transition-all pr-1",children:x})]}),e.jsxs("div",{className:"flex flex-col gap-2 rounded border bg-2 p-3",style:{borderColor:"var(--border)"},children:[e.jsx("input",{"aria-label":"Startup command",value:a,onChange:m=>t(m.currentTarget.value),placeholder:"qwen --model qwen3-coder",className:"input mono text-sm",spellCheck:!1}),e.jsx("p",{className:"text-sm leading-5 text-ter",children:n("addWorker.startupHelp",{example:"claude --resume <session-id>"})})]})]})},Le=d.lazy(()=>ue(()=>import("./MarketplaceDrawer-BdkVJyI0.js"),__vite__mapDeps([0,1,2,3])).then(t=>({default:t.MarketplaceDrawer}))),_e=({commandPresets:t,commandPresetId:a,creating:n=!1,customTemplates:s,onApplyMarketplaceImport:c,onClose:o,onDeleteTemplate:g,onNameChange:x,onPresetChange:m,onRandomName:u,onRoleDescriptionChange:b,onRoleDescriptionReset:k,onRoleChange:y,onSaveAsTemplate:N,onStartupCommandChange:v,onSubmit:r,onTemplateChange:p,roleDescription:h,roleDescriptionDefault:l,selectedTemplateId:P,startupCommand:E,templateBusy:B,workerName:O,workerRole:W,writeDisabledReason:w})=>{const{t:i}=j(),_=ae(),C=re(),[q,A]=d.useState(!1),[H,K]=d.useState(!1),V=d.useMemo(()=>new Set(s.map(f=>f.name)),[s]),Q=f=>{c(f),_.show({kind:"success",message:i("marketplace.imported",{name:f.name})})},J=f=>{f||o()},X=h!==l,$=t.find(f=>f.id===a),T=E.trim(),G=()=>w||(O.trim()?!a&&!T?i("addWorker.pickCliOrStartup"):$?.available===!1&&!T?i("addWorker.unavailable",{name:$.displayName}):h.trim()?null:i("addWorker.emptyInstructions"):i("addWorker.enterName")),R=f=>{const F=G();if(F){f.preventDefault(),_.show({kind:"warning",message:F});return}r(f)};return e.jsxs(se,{open:!0,onOpenChange:J,children:[e.jsxs(ne,{children:[e.jsx(oe,{"data-testid":"add-worker-overlay",className:"app-overlay fixed inset-0 z-40"}),e.jsx("div",{className:"pointer-events-none fixed inset-0 z-50 grid place-items-center p-4 max-md:items-end max-md:p-0",children:e.jsx(le,{"data-testid":"add-worker-content","data-mobile":C||void 0,className:`${C?"dialog-slide-up add-worker-sheet":"dialog-scale-pop"} elev-2 pointer-events-auto flex max-h-[calc(100vh-32px)] w-[560px] max-w-full flex-col overflow-hidden rounded-lg border pointer-coarse:max-h-[85dvh] max-md:w-full max-md:rounded-b-none max-md:rounded-t-xl`,style:{background:"var(--bg-elevated)",borderColor:"var(--border-bright)",...C?{height:"85dvh"}:{}},children:e.jsxs("form",{onSubmit:R,"aria-label":i("addWorker.title"),className:"flex min-h-0 flex-1 flex-col overflow-hidden max-h-full",children:[e.jsxs("div",{className:"flex shrink-0 items-start justify-between gap-3 border-b px-5 py-4 max-md:px-4",style:{borderColor:"var(--border)"},children:[e.jsxs("div",{className:"flex min-w-0 flex-col gap-0.5",children:[e.jsx(ie,{className:"text-lg font-semibold text-pri",children:i("addWorker.title")}),e.jsx(de,{className:"text-sm text-ter",children:i("addWorker.description",{command:"team send"})})]}),C?e.jsx(ce,{asChild:!0,children:e.jsx("button",{type:"button","aria-label":i("common.closeDialog"),"data-testid":"add-worker-close",className:"-mr-1 flex h-10 w-10 shrink-0 items-center justify-center rounded-md text-sec",style:{background:"var(--bg-2)"},children:e.jsx(me,{size:18,"aria-hidden":!0})})}):null]}),e.jsxs("div",{className:"flex flex-1 min-h-0 flex-col gap-4 overflow-y-auto px-5 py-4 max-md:gap-5 max-md:px-4",children:[e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsx(S,{children:i("addWorker.name")}),e.jsxs("div",{className:"relative flex items-center",children:[e.jsx("input",{autoFocus:!C,value:O,onChange:f=>x(f.target.value),placeholder:i("addWorker.namePlaceholder"),className:"input w-full pr-24",style:{borderRadius:"10px"}}),e.jsx("div",{className:"absolute right-1.5 top-1/2 -translate-y-1/2",children:e.jsx(xe,{label:i("addWorker.randomTooltip"),children:e.jsxs("button",{type:"button","aria-label":i("addWorker.randomAria"),className:"flex h-7 items-center gap-1.5 rounded-lg border border-bright/10 bg-3 px-2.5 text-xs font-semibold text-sec hover:text-pri hover:bg-4 active:scale-95 transition-all outline-none",onClick:u,"data-testid":"random-worker-name",children:[e.jsx(ve,{size:13,"aria-hidden":!0}),e.jsx("span",{children:i("addWorker.random")})]})})})]})]}),e.jsx(Ce,{workerRole:W,onRoleChange:y}),e.jsxs("button",{type:"button",onClick:()=>{K(!0),A(!0)},"data-testid":"open-marketplace",className:"marketplace-browse-btn flex cursor-pointer items-center gap-2 self-start rounded-lg border px-3 py-2 text-xs font-semibold text-sec outline-none transition-all duration-200 hover:text-pri hover:-translate-y-0.5 active:scale-98 shadow-sm hover:shadow-md",style:{background:"linear-gradient(to bottom, var(--bg-1), var(--bg-0))",borderColor:"var(--border-bright)","--tw-ring-color":"color-mix(in oklab, var(--accent) 45%, transparent)"},children:[e.jsx(je,{size:14,"aria-hidden":!0,className:"text-accent"}),e.jsx("span",{children:i("marketplace.openFromAddWorker")})]}),W==="custom"?e.jsx(we,{customTemplates:s,disabledReason:w,onDeleteTemplate:g,onSelect:p,selectedTemplateId:P}):null,e.jsx(We,{canSaveAsTemplate:W==="custom"&&!P&&h.trim().length>0,modified:X,onChange:b,onReset:k,onSaveAsTemplate:N,roleDescription:h,templateBusy:B,workerRole:W,writeDisabledReason:w}),e.jsx(ze,{commandPresetId:a,commandPresets:t,onPresetChange:m}),e.jsx(Me,{value:E,onChange:v})]}),e.jsxs("div",{className:"flex shrink-0 items-center justify-end gap-2 border-t px-5 py-3 max-md:px-4 max-md:pb-[max(12px,env(safe-area-inset-bottom))]",style:{borderColor:"var(--border)",background:"var(--bg-2)"},children:[e.jsx("button",{type:"button",onClick:o,className:`icon-btn border border-bright/20 rounded-lg hover:bg-3 hover:text-pri transition-all active:scale-95 ${C?"flex-1":""}`,"data-testid":"add-worker-cancel",children:i("addWorker.cancel")}),e.jsx("button",{type:"submit",disabled:n||!!w,title:w??void 0,className:`icon-btn icon-btn--primary rounded-lg font-bold shadow-md hover:shadow-lg transition-all active:scale-[0.97] hover:-translate-y-0.5 ${C?"flex-[2]":""}`,"data-testid":"add-worker-submit",children:i(n?"addWorker.creating":"addWorker.create")})]})]})})})]}),H?e.jsx(d.Suspense,{fallback:null,children:e.jsx(Le,{open:q,onClose:()=>A(!1),onImport:Q,importedNames:V})}):null]})};export{_e as AddWorkerDialog};