@tt-a1i/hive 2.1.3 → 2.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 (70) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/src/cli/team.d.ts +4 -1
  3. package/dist/src/cli/team.js +95 -6
  4. package/dist/src/server/agent-startup-instructions.js +1 -1
  5. package/dist/src/server/hive-team-guidance.js +2 -2
  6. package/dist/src/server/routes-team-memory.js +53 -2
  7. package/dist/src/server/routes-workspace-memory.js +31 -2
  8. package/dist/src/server/runtime-store-contract.d.ts +2 -0
  9. package/dist/src/server/runtime-store-dream.d.ts +2 -5
  10. package/dist/src/server/runtime-store-dream.js +2 -12
  11. package/dist/src/server/runtime-store-helpers.d.ts +4 -0
  12. package/dist/src/server/runtime-store-helpers.js +21 -1
  13. package/dist/src/server/runtime-store-memory.d.ts +6 -0
  14. package/dist/src/server/runtime-store-memory.js +1 -0
  15. package/dist/src/server/sqlite-schema-v36.d.ts +3 -0
  16. package/dist/src/server/sqlite-schema-v36.js +21 -0
  17. package/dist/src/server/sqlite-schema.d.ts +1 -1
  18. package/dist/src/server/sqlite-schema.js +6 -1
  19. package/dist/src/server/team-memory-diagnostics.d.ts +86 -0
  20. package/dist/src/server/team-memory-diagnostics.js +87 -0
  21. package/dist/src/server/team-memory-digest.d.ts +7 -0
  22. package/dist/src/server/team-memory-digest.js +22 -5
  23. package/dist/src/server/team-memory-dream-applier.js +20 -3
  24. package/dist/src/server/team-memory-dream-cli.d.ts +13 -0
  25. package/dist/src/server/team-memory-dream-cli.js +115 -0
  26. package/dist/src/server/team-memory-dream-input.d.ts +15 -0
  27. package/dist/src/server/team-memory-dream-input.js +14 -0
  28. package/dist/src/server/team-memory-dream-ops.d.ts +4 -1
  29. package/dist/src/server/team-memory-dream-ops.js +32 -3
  30. package/dist/src/server/team-memory-dream-prompt.js +5 -3
  31. package/dist/src/server/team-memory-dream-reverter.js +13 -3
  32. package/dist/src/server/team-memory-dream-run-store.d.ts +1 -0
  33. package/dist/src/server/team-memory-dream-run-store.js +20 -0
  34. package/dist/src/server/team-memory-dream-runner.d.ts +10 -1
  35. package/dist/src/server/team-memory-dream-runner.js +34 -5
  36. package/dist/src/server/team-memory-dream-scheduler.js +2 -2
  37. package/dist/src/server/team-memory-dream-store.d.ts +2 -1
  38. package/dist/src/server/team-memory-dream-store.js +1 -1
  39. package/dist/src/server/team-memory-dream-types.d.ts +5 -1
  40. package/dist/src/server/team-memory-export.js +7 -0
  41. package/dist/src/server/team-memory-http-serializers.d.ts +15 -0
  42. package/dist/src/server/team-memory-http-serializers.js +7 -0
  43. package/dist/src/server/team-memory-provider.d.ts +33 -0
  44. package/dist/src/server/team-memory-provider.js +54 -0
  45. package/dist/src/server/team-memory-store.d.ts +10 -3
  46. package/dist/src/server/team-memory-store.js +134 -58
  47. package/dist/src/shared/team-memory.d.ts +13 -0
  48. package/dist/src/shared/team-memory.js +12 -0
  49. package/package.json +3 -2
  50. package/web/dist/assets/{AddWorkerDialog-DHwOZ75i.js → AddWorkerDialog-AxzWv2T8.js} +2 -2
  51. package/web/dist/assets/AddWorkspaceFlow-D-Yh_kk_.js +1 -0
  52. package/web/dist/assets/{FirstRunWizard-D5kGMD_V.js → FirstRunWizard-nAK4Eprj.js} +1 -1
  53. package/web/dist/assets/{MarketplaceDrawer-BuCbtqFk.js → MarketplaceDrawer-B8JW-znT.js} +1 -1
  54. package/web/dist/assets/{TaskGraphDrawer-e_bg3f5u.js → TaskGraphDrawer-BQ9Wr41D.js} +1 -1
  55. package/web/dist/assets/{WhatsNewDialog-BB9ieq3T.js → WhatsNewDialog-D7DwCnTR.js} +1 -1
  56. package/web/dist/assets/{WorkerModal-CGeWO3Dg.js → WorkerModal-tU-XkiFG.js} +1 -1
  57. package/web/dist/assets/{WorkflowsDrawer-CVvGxxdR.js → WorkflowsDrawer-DCa-HN3D.js} +1 -1
  58. package/web/dist/assets/WorkspaceMemoryDrawer-4hLlu8BO.js +1 -0
  59. package/web/dist/assets/WorkspaceTaskDrawer-D3LcLkw_.js +1 -0
  60. package/web/dist/assets/index-B8tv0NRK.js +84 -0
  61. package/web/dist/assets/index-CG2TurwT.css +1 -0
  62. package/web/dist/assets/{search-DKgM9IgX.js → search-CcRvD2Q5.js} +1 -1
  63. package/web/dist/assets/{square-terminal-DMWazpEv.js → square-terminal-zBgH6nhI.js} +1 -1
  64. package/web/dist/index.html +2 -2
  65. package/web/dist/sw.js +1 -1
  66. package/web/dist/assets/AddWorkspaceFlow-qOI1CmqC.js +0 -1
  67. package/web/dist/assets/WorkspaceMemoryDrawer-BamHuJEp.js +0 -1
  68. package/web/dist/assets/WorkspaceTaskDrawer-CqntbH9-.js +0 -1
  69. package/web/dist/assets/index-BOpmn5Ij.js +0 -84
  70. package/web/dist/assets/index-rPYd0MUk.css +0 -1
@@ -52,7 +52,42 @@ const parseTags = (value) => {
52
52
  const parsed = JSON.parse(value);
53
53
  return Array.isArray(parsed) ? parsed.filter((tag) => typeof tag === 'string') : [];
54
54
  };
55
- const toEntryRecord = (row) => ({
55
+ const normalizeScopes = (scopes) => {
56
+ if (scopes === undefined)
57
+ return ['workspace'];
58
+ const result = [];
59
+ for (const scope of scopes) {
60
+ if (!result.includes(scope))
61
+ result.push(scope);
62
+ }
63
+ return result;
64
+ };
65
+ const scopePredicate = (alias, workspaceId, scopes) => {
66
+ const prefix = alias ? `${alias}.` : '';
67
+ const clauses = [];
68
+ const params = [];
69
+ for (const scope of normalizeScopes(scopes)) {
70
+ if (scope === 'workspace') {
71
+ clauses.push(`(${prefix}scope = 'workspace' AND ${prefix}workspace_id = ?)`);
72
+ params.push(workspaceId);
73
+ }
74
+ if (scope === 'user') {
75
+ clauses.push(`(${prefix}scope = 'user' AND ${prefix}workspace_id IS NULL)`);
76
+ }
77
+ }
78
+ return { params, sql: clauses.length > 0 ? `(${clauses.join(' OR ')})` : '0 = 1' };
79
+ };
80
+ const lastInjectedAtForContext = (db, row, workspaceId) => {
81
+ if (row.scope !== 'user' || !workspaceId)
82
+ return row.last_injected_at;
83
+ return db
84
+ .prepare(`SELECT MAX(injected_at) AS last
85
+ FROM memory_injections
86
+ WHERE memory_id = ?
87
+ AND workspace_id = ?`)
88
+ .get(row.id, workspaceId).last;
89
+ };
90
+ const toEntryRecord = (db, row, contextWorkspaceId) => ({
56
91
  archivedAt: row.archived_at,
57
92
  body: row.body,
58
93
  confidence: row.confidence,
@@ -60,8 +95,15 @@ const toEntryRecord = (row) => ({
60
95
  disabled: row.disabled === 1,
61
96
  id: row.id,
62
97
  kind: row.kind,
63
- lastInjectedAt: row.last_injected_at,
98
+ lastInjectedAt: lastInjectedAtForContext(db, row, contextWorkspaceId),
64
99
  pinned: row.pinned === 1,
100
+ procedureRef: row.ref_type && row.ref_id
101
+ ? {
102
+ id: row.ref_id,
103
+ title: row.ref_title,
104
+ type: row.ref_type,
105
+ }
106
+ : null,
65
107
  scope: row.scope,
66
108
  source: row.source,
67
109
  status: row.status,
@@ -90,22 +132,22 @@ export const createTeamMemoryStore = (db) => {
90
132
  WHERE memory_id = ?
91
133
  ORDER BY created_at ASC, id ASC`)
92
134
  .all(memoryId).map(toSourceRecord);
93
- const toEntryWithSources = (row) => ({
94
- ...toEntryRecord(row),
135
+ const toEntryWithSources = (row, contextWorkspaceId) => ({
136
+ ...toEntryRecord(db, row, contextWorkspaceId),
95
137
  sources: listSources(row.id),
96
138
  });
97
139
  const getEntryWithSources = (workspaceId, memoryId) => {
140
+ const scope = scopePredicate('', workspaceId, ['workspace', 'user']);
98
141
  const row = db
99
142
  .prepare(`SELECT *
100
143
  FROM memory_entries
101
144
  WHERE id = ?
102
- AND scope = 'workspace'
103
- AND workspace_id = ?
145
+ AND ${scope.sql}
104
146
  LIMIT 1`)
105
- .get(memoryId, workspaceId);
147
+ .get(memoryId, ...scope.params);
106
148
  if (!row)
107
149
  return undefined;
108
- return toEntryWithSources(row);
150
+ return toEntryWithSources(row, workspaceId);
109
151
  };
110
152
  const requireEntryWithSources = (workspaceId, memoryId) => {
111
153
  const entry = getEntryWithSources(workspaceId, memoryId);
@@ -113,11 +155,12 @@ export const createTeamMemoryStore = (db) => {
113
155
  throw new MemoryEntryNotFoundError(memoryId, workspaceId);
114
156
  return entry;
115
157
  };
116
- const searchFts = (table, workspaceId, ftsQuery, statuses, includeDisabled) => {
158
+ const searchFts = (table, workspaceId, ftsQuery, statuses, includeDisabled, scopes) => {
117
159
  if (statuses.length === 0)
118
160
  return [];
119
161
  const indexName = table === 'memory_fts' ? 'unicode' : 'trigram';
120
162
  const statusPlaceholders = statuses.map(() => '?').join(', ');
163
+ const scope = scopePredicate('e', workspaceId, scopes);
121
164
  return db
122
165
  .prepare(`SELECT
123
166
  e.*,
@@ -126,31 +169,30 @@ export const createTeamMemoryStore = (db) => {
126
169
  FROM ${table}
127
170
  JOIN memory_entries e ON e.fts_rowid = ${table}.rowid
128
171
  WHERE ${table} MATCH ?
129
- AND e.scope = 'workspace'
130
- AND e.workspace_id = ?
172
+ AND ${scope.sql}
131
173
  ${includeDisabled ? '' : 'AND e.disabled = 0'}
132
174
  AND e.status IN (${statusPlaceholders})`)
133
- .all(indexName, ftsQuery, workspaceId, ...statuses);
175
+ .all(indexName, ftsQuery, ...scope.params, ...statuses);
134
176
  };
135
- const searchLike = (workspaceId, terms, statuses, includeDisabled) => {
177
+ const searchLike = (workspaceId, terms, statuses, includeDisabled, scopes) => {
136
178
  if (terms.length === 0 || statuses.length === 0)
137
179
  return [];
138
180
  const predicates = terms
139
181
  .map(() => "(e.body LIKE ? ESCAPE '\\' OR COALESCE(e.tags, '') LIKE ? ESCAPE '\\')")
140
182
  .join(' AND ');
141
183
  const statusPlaceholders = statuses.map(() => '?').join(', ');
184
+ const scope = scopePredicate('e', workspaceId, scopes);
142
185
  return db
143
186
  .prepare(`SELECT
144
187
  e.*,
145
188
  'like' AS index_name,
146
189
  0 AS score
147
190
  FROM memory_entries e
148
- WHERE e.scope = 'workspace'
149
- AND e.workspace_id = ?
191
+ WHERE ${scope.sql}
150
192
  ${includeDisabled ? '' : 'AND e.disabled = 0'}
151
193
  AND e.status IN (${statusPlaceholders})
152
194
  AND ${predicates}`)
153
- .all(workspaceId, ...statuses, ...terms.flatMap((term) => [escapeLike(term), escapeLike(term)]));
195
+ .all(...scope.params, ...statuses, ...terms.flatMap((term) => [escapeLike(term), escapeLike(term)]));
154
196
  };
155
197
  const searchEntries = (workspaceId, query, options = {}) => {
156
198
  if ([...query].length > MEMORY_QUERY_MAX_CHARS)
@@ -162,9 +204,11 @@ export const createTeamMemoryStore = (db) => {
162
204
  const statuses = options.statuses ?? ['active'];
163
205
  const includeDisabled = options.includeDisabled ?? false;
164
206
  const rows = [
165
- ...searchFts('memory_fts', workspaceId, ftsQuery, statuses, includeDisabled),
166
- ...searchFts('memory_fts_trigram', workspaceId, ftsQuery, statuses, includeDisabled),
167
- ...(hasShortTerm(terms) ? searchLike(workspaceId, terms, statuses, includeDisabled) : []),
207
+ ...searchFts('memory_fts', workspaceId, ftsQuery, statuses, includeDisabled, options.scopes),
208
+ ...searchFts('memory_fts_trigram', workspaceId, ftsQuery, statuses, includeDisabled, options.scopes),
209
+ ...(hasShortTerm(terms)
210
+ ? searchLike(workspaceId, terms, statuses, includeDisabled, options.scopes)
211
+ : []),
168
212
  ];
169
213
  const byId = new Map();
170
214
  for (const row of rows) {
@@ -176,7 +220,7 @@ export const createTeamMemoryStore = (db) => {
176
220
  .sort((a, b) => a.score - b.score || b.updated_at - a.updated_at)
177
221
  .slice(0, clampLimit(options.limit))
178
222
  .map((row) => ({
179
- ...toEntryWithSources(row),
223
+ ...toEntryWithSources(row, workspaceId),
180
224
  indexName: row.index_name,
181
225
  score: row.score,
182
226
  }));
@@ -186,11 +230,11 @@ export const createTeamMemoryStore = (db) => {
186
230
  if (statuses.length === 0)
187
231
  return [];
188
232
  const statusPlaceholders = statuses.map(() => '?').join(', ');
233
+ const scope = scopePredicate('', workspaceId, options.scopes);
189
234
  return db
190
235
  .prepare(`SELECT *
191
236
  FROM memory_entries
192
- WHERE scope = 'workspace'
193
- AND workspace_id = ?
237
+ WHERE ${scope.sql}
194
238
  AND status IN (${statusPlaceholders})
195
239
  ORDER BY
196
240
  CASE status
@@ -204,13 +248,14 @@ export const createTeamMemoryStore = (db) => {
204
248
  created_at DESC,
205
249
  id ASC
206
250
  LIMIT ?`)
207
- .all(workspaceId, ...statuses, clampListLimit(options.limit)).map(toEntryWithSources);
251
+ .all(...scope.params, ...statuses, clampListLimit(options.limit)).map((row) => toEntryWithSources(row, workspaceId));
208
252
  };
209
- const listAllEntries = (workspaceId) => db
210
- .prepare(`SELECT *
253
+ const listAllEntries = (workspaceId, options = {}) => {
254
+ const scope = scopePredicate('', workspaceId, options.scopes);
255
+ return db
256
+ .prepare(`SELECT *
211
257
  FROM memory_entries
212
- WHERE scope = 'workspace'
213
- AND workspace_id = ?
258
+ WHERE ${scope.sql}
214
259
  ORDER BY
215
260
  CASE status
216
261
  WHEN 'candidate' THEN 0
@@ -222,15 +267,18 @@ export const createTeamMemoryStore = (db) => {
222
267
  updated_at DESC,
223
268
  created_at DESC,
224
269
  id ASC`)
225
- .all(workspaceId).map(toEntryWithSources);
226
- const listDigestEntries = (workspaceId, options = {}) => db
227
- .prepare(`SELECT *
270
+ .all(...scope.params).map((row) => toEntryWithSources(row, workspaceId));
271
+ };
272
+ const listDigestEntries = (workspaceId, options = {}) => {
273
+ const scope = scopePredicate('', workspaceId, options.scopes);
274
+ return db
275
+ .prepare(`SELECT *
228
276
  FROM memory_entries
229
- WHERE scope = 'workspace'
230
- AND workspace_id = ?
277
+ WHERE ${scope.sql}
231
278
  AND status = 'active'
232
279
  AND disabled = 0
233
280
  ORDER BY
281
+ CASE scope WHEN 'user' THEN 0 ELSE 1 END ASC,
234
282
  pinned DESC,
235
283
  CASE source WHEN 'manual' THEN 0 ELSE 1 END ASC,
236
284
  COALESCE(confidence, 0) DESC,
@@ -238,7 +286,8 @@ export const createTeamMemoryStore = (db) => {
238
286
  created_at DESC,
239
287
  id ASC
240
288
  LIMIT ?`)
241
- .all(workspaceId, clampDigestLimit(options.limit)).map(toEntryWithSources);
289
+ .all(...scope.params, clampDigestLimit(options.limit)).map((row) => toEntryWithSources(row, workspaceId));
290
+ };
242
291
  const listExportEntries = (workspaceId) => db
243
292
  .prepare(`SELECT *
244
293
  FROM memory_entries
@@ -253,7 +302,12 @@ export const createTeamMemoryStore = (db) => {
253
302
  updated_at DESC,
254
303
  created_at DESC,
255
304
  id ASC`)
256
- .all(workspaceId).map(toEntryWithSources);
305
+ .all(workspaceId).map((row) => toEntryWithSources(row, workspaceId));
306
+ const requireProcedureRefForProcedureKind = (kind, procedureRef) => {
307
+ if (kind === 'procedure_ref' && !procedureRef) {
308
+ throw new Error('procedure_ref memory entries require procedureRef');
309
+ }
310
+ };
257
311
  const addEntry = (input) => {
258
312
  const id = randomUUID();
259
313
  const sourceId = randomUUID();
@@ -262,6 +316,10 @@ export const createTeamMemoryStore = (db) => {
262
316
  const source = input.source ?? 'manual';
263
317
  const confidence = input.confidence ?? (source === 'manual' ? 1 : null);
264
318
  const tags = JSON.stringify(input.tags ?? []);
319
+ const scope = input.scope ?? 'workspace';
320
+ const entryWorkspaceId = scope === 'workspace' ? input.workspaceId : null;
321
+ const procedureRef = input.procedureRef ?? null;
322
+ requireProcedureRefForProcedureKind(input.kind, procedureRef);
265
323
  db.transaction(() => {
266
324
  const ftsRowid = nextFtsRowid();
267
325
  db.prepare(`INSERT INTO memory_entries (
@@ -280,8 +338,11 @@ export const createTeamMemoryStore = (db) => {
280
338
  created_at,
281
339
  updated_at,
282
340
  archived_at,
283
- last_injected_at
284
- ) VALUES (?, ?, 'workspace', ?, ?, ?, ?, ?, ?, ?, 0, 0, ?, ?, NULL, NULL)`).run(id, input.workspaceId, ftsRowid, input.kind, input.body, tags, status, source, confidence, now, now);
341
+ last_injected_at,
342
+ ref_type,
343
+ ref_id,
344
+ ref_title
345
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, 0, ?, ?, NULL, NULL, ?, ?, ?)`).run(id, entryWorkspaceId, scope, ftsRowid, input.kind, input.body, tags, status, source, confidence, now, now, procedureRef?.type ?? null, procedureRef?.id ?? null, procedureRef?.title ?? null);
285
346
  db.prepare(`INSERT INTO memory_sources (
286
347
  id,
287
348
  memory_id,
@@ -307,15 +368,15 @@ export const createTeamMemoryStore = (db) => {
307
368
  const injectedAt = Date.now();
308
369
  const ids = input.memoryIds.map(() => randomUUID());
309
370
  db.transaction(() => {
371
+ const scope = scopePredicate('', input.workspaceId, ['workspace', 'user']);
310
372
  for (const [index, memoryId] of input.memoryIds.entries()) {
311
373
  const memory = db
312
374
  .prepare(`SELECT id
313
375
  FROM memory_entries
314
376
  WHERE id = ?
315
- AND scope = 'workspace'
316
- AND workspace_id = ?
377
+ AND ${scope.sql}
317
378
  LIMIT 1`)
318
- .get(memoryId, input.workspaceId);
379
+ .get(memoryId, ...scope.params);
319
380
  if (!memory) {
320
381
  throw new MemoryEntryNotFoundError(memoryId, input.workspaceId);
321
382
  }
@@ -330,7 +391,7 @@ export const createTeamMemoryStore = (db) => {
330
391
  ) VALUES (?, ?, ?, ?, ?, ?, ?)`).run(ids[index], memoryId, input.workspaceId, input.targetAgentIdSnapshot ?? null, input.contextType, input.dispatchId ?? null, injectedAt);
331
392
  db.prepare(`UPDATE memory_entries
332
393
  SET last_injected_at = ?
333
- WHERE id = ? AND workspace_id = ?`).run(injectedAt, memoryId, input.workspaceId);
394
+ WHERE id = ?`).run(injectedAt, memoryId);
334
395
  }
335
396
  })();
336
397
  return ids;
@@ -352,10 +413,8 @@ export const createTeamMemoryStore = (db) => {
352
413
  SELECT MAX(injected_at)
353
414
  FROM memory_injections
354
415
  WHERE memory_id = ?
355
- AND workspace_id = ?
356
416
  )
357
- WHERE id = ?
358
- AND workspace_id = ?`).run(row.memory_id, row.workspace_id, row.memory_id, row.workspace_id);
417
+ WHERE id = ?`).run(row.memory_id, row.memory_id);
359
418
  }
360
419
  })();
361
420
  };
@@ -367,16 +426,16 @@ export const createTeamMemoryStore = (db) => {
367
426
  throw new MemoryEntryStatusError(memoryId, 'active', current.status);
368
427
  }
369
428
  const now = Date.now();
429
+ const scope = scopePredicate('', workspaceId, ['workspace', 'user']);
370
430
  const result = db
371
431
  .prepare(`UPDATE memory_entries
372
432
  SET status = 'archived',
373
433
  archived_at = ?,
374
434
  updated_at = ?
375
435
  WHERE id = ?
376
- AND scope = 'workspace'
377
- AND workspace_id = ?
436
+ AND ${scope.sql}
378
437
  AND status = 'active'`)
379
- .run(now, now, memoryId, workspaceId);
438
+ .run(now, now, memoryId, ...scope.params);
380
439
  if (result.changes === 0)
381
440
  throw new MemoryEntryNotFoundError(memoryId, workspaceId);
382
441
  return requireEntryWithSources(workspaceId, memoryId);
@@ -387,16 +446,16 @@ export const createTeamMemoryStore = (db) => {
387
446
  throw new MemoryEntryStatusError(memoryId, 'candidate', current.status);
388
447
  }
389
448
  const now = Date.now();
449
+ const scope = scopePredicate('', workspaceId, ['workspace', 'user']);
390
450
  const result = db
391
451
  .prepare(`UPDATE memory_entries
392
452
  SET status = 'active',
393
453
  archived_at = NULL,
394
454
  updated_at = ?
395
455
  WHERE id = ?
396
- AND scope = 'workspace'
397
- AND workspace_id = ?
456
+ AND ${scope.sql}
398
457
  AND status = 'candidate'`)
399
- .run(now, memoryId, workspaceId);
458
+ .run(now, memoryId, ...scope.params);
400
459
  if (result.changes === 0)
401
460
  throw new MemoryEntryNotFoundError(memoryId, workspaceId);
402
461
  return requireEntryWithSources(workspaceId, memoryId);
@@ -407,15 +466,15 @@ export const createTeamMemoryStore = (db) => {
407
466
  throw new MemoryEntryStatusError(memoryId, 'candidate', current.status);
408
467
  }
409
468
  const now = Date.now();
469
+ const scope = scopePredicate('', workspaceId, ['workspace', 'user']);
410
470
  const result = db
411
471
  .prepare(`UPDATE memory_entries
412
472
  SET status = 'rejected',
413
473
  updated_at = ?
414
474
  WHERE id = ?
415
- AND scope = 'workspace'
416
- AND workspace_id = ?
475
+ AND ${scope.sql}
417
476
  AND status = 'candidate'`)
418
- .run(now, memoryId, workspaceId);
477
+ .run(now, memoryId, ...scope.params);
419
478
  if (result.changes === 0)
420
479
  throw new MemoryEntryNotFoundError(memoryId, workspaceId);
421
480
  return requireEntryWithSources(workspaceId, memoryId);
@@ -426,15 +485,15 @@ export const createTeamMemoryStore = (db) => {
426
485
  throw new MemoryEntryStatusError(memoryId, 'active', current.status);
427
486
  }
428
487
  const now = Date.now();
488
+ const scope = scopePredicate('', workspaceId, ['workspace', 'user']);
429
489
  const result = db
430
490
  .prepare(`UPDATE memory_entries
431
491
  SET pinned = ?,
432
492
  updated_at = ?
433
493
  WHERE id = ?
434
- AND scope = 'workspace'
435
- AND workspace_id = ?
494
+ AND ${scope.sql}
436
495
  AND status = 'active'`)
437
- .run(pinned ? 1 : 0, now, memoryId, workspaceId);
496
+ .run(pinned ? 1 : 0, now, memoryId, ...scope.params);
438
497
  if (result.changes === 0)
439
498
  throw new MemoryEntryNotFoundError(memoryId, workspaceId);
440
499
  return requireEntryWithSources(workspaceId, memoryId);
@@ -445,15 +504,15 @@ export const createTeamMemoryStore = (db) => {
445
504
  throw new MemoryEntryStatusError(memoryId, 'active', current.status);
446
505
  }
447
506
  const now = Date.now();
507
+ const scope = scopePredicate('', workspaceId, ['workspace', 'user']);
448
508
  const result = db
449
509
  .prepare(`UPDATE memory_entries
450
510
  SET disabled = ?,
451
511
  updated_at = ?
452
512
  WHERE id = ?
453
- AND scope = 'workspace'
454
- AND workspace_id = ?
513
+ AND ${scope.sql}
455
514
  AND status = 'active'`)
456
- .run(disabled ? 1 : 0, now, memoryId, workspaceId);
515
+ .run(disabled ? 1 : 0, now, memoryId, ...scope.params);
457
516
  if (result.changes === 0)
458
517
  throw new MemoryEntryNotFoundError(memoryId, workspaceId);
459
518
  return requireEntryWithSources(workspaceId, memoryId);
@@ -492,6 +551,22 @@ export const createTeamMemoryStore = (db) => {
492
551
  targetAgentIdSnapshot: row.target_agent_id_snapshot,
493
552
  workspaceId: row.workspace_id,
494
553
  }));
554
+ const listInjections = (workspaceId, limit = 200) => db
555
+ .prepare(`SELECT *
556
+ FROM memory_injections
557
+ WHERE workspace_id = ?
558
+ ORDER BY injected_at DESC, id DESC
559
+ LIMIT ?`)
560
+ .all(workspaceId, Math.min(Math.max(Math.trunc(limit), 0), 1000)).map((row) => ({
561
+ contextType: row.context_type,
562
+ dispatchId: row.dispatch_id,
563
+ id: row.id,
564
+ injectedAt: row.injected_at,
565
+ memory: requireEntryWithSources(workspaceId, row.memory_id),
566
+ memoryId: row.memory_id,
567
+ targetAgentIdSnapshot: row.target_agent_id_snapshot,
568
+ workspaceId: row.workspace_id,
569
+ }));
495
570
  return {
496
571
  addEntry,
497
572
  approveCandidate,
@@ -503,6 +578,7 @@ export const createTeamMemoryStore = (db) => {
503
578
  listExportEntries,
504
579
  listAllEntries,
505
580
  listEntries,
581
+ listInjections,
506
582
  listInjectionsForDispatch,
507
583
  logInjections,
508
584
  rejectCandidate,
@@ -6,6 +6,19 @@ export declare const MEMORY_SEARCH_DEFAULT_LIMIT = 10;
6
6
  export declare const MEMORY_SEARCH_MAX_LIMIT = 50;
7
7
  export declare const MEMORY_TAG_MAX_CHARS = 64;
8
8
  export declare const MEMORY_TAG_MAX_COUNT = 20;
9
+ export declare const MEMORY_PROCEDURE_REF_ID_MAX_CHARS = 256;
10
+ export declare const MEMORY_PROCEDURE_REF_TITLE_MAX_CHARS = 160;
9
11
  export declare const MEMORY_KINDS: readonly ["fact", "preference", "decision", "pitfall", "procedure_ref"];
10
12
  export type MemoryKind = (typeof MEMORY_KINDS)[number];
11
13
  export declare const isMemoryKind: (value: unknown) => value is MemoryKind;
14
+ export declare const MEMORY_SCOPES: readonly ["workspace", "user"];
15
+ export type MemoryScope = (typeof MEMORY_SCOPES)[number];
16
+ export declare const isMemoryScope: (value: unknown) => value is MemoryScope;
17
+ export declare const MEMORY_PROCEDURE_REF_TYPES: readonly ["workflow", "skill", "procedure", "template", "doc"];
18
+ export type MemoryProcedureRefType = (typeof MEMORY_PROCEDURE_REF_TYPES)[number];
19
+ export interface MemoryProcedureRef {
20
+ id: string;
21
+ title: string | null;
22
+ type: MemoryProcedureRefType;
23
+ }
24
+ export declare const isMemoryProcedureRefType: (value: unknown) => value is MemoryProcedureRefType;
@@ -6,5 +6,17 @@ export const MEMORY_SEARCH_DEFAULT_LIMIT = 10;
6
6
  export const MEMORY_SEARCH_MAX_LIMIT = 50;
7
7
  export const MEMORY_TAG_MAX_CHARS = 64;
8
8
  export const MEMORY_TAG_MAX_COUNT = 20;
9
+ export const MEMORY_PROCEDURE_REF_ID_MAX_CHARS = 256;
10
+ export const MEMORY_PROCEDURE_REF_TITLE_MAX_CHARS = 160;
9
11
  export const MEMORY_KINDS = ['fact', 'preference', 'decision', 'pitfall', 'procedure_ref'];
10
12
  export const isMemoryKind = (value) => typeof value === 'string' && MEMORY_KINDS.includes(value);
13
+ export const MEMORY_SCOPES = ['workspace', 'user'];
14
+ export const isMemoryScope = (value) => typeof value === 'string' && MEMORY_SCOPES.includes(value);
15
+ export const MEMORY_PROCEDURE_REF_TYPES = [
16
+ 'workflow',
17
+ 'skill',
18
+ 'procedure',
19
+ 'template',
20
+ 'doc',
21
+ ];
22
+ export const isMemoryProcedureRefType = (value) => typeof value === 'string' && MEMORY_PROCEDURE_REF_TYPES.includes(value);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tt-a1i/hive",
3
- "version": "2.1.3",
3
+ "version": "2.1.5",
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",
@@ -63,7 +63,8 @@
63
63
  "pack:check": "npm pack --dry-run --json",
64
64
  "pack:smoke": "node scripts/pack-smoke.mjs",
65
65
  "postinstall": "node scripts/postinstall-native-artifacts.mjs",
66
- "release:dry": "pnpm check && pnpm build && pnpm test && pnpm pack:check && pnpm pack:smoke",
66
+ "release:dry": "pnpm check && pnpm build && pnpm pack:check && pnpm pack:smoke",
67
+ "release:full": "pnpm check && pnpm build && pnpm test && pnpm pack:check && pnpm pack:smoke",
67
68
  "stress:multidevice": "tsx scripts/remote-stress-multidevice.ts",
68
69
  "stress:throughput": "tsx --expose-gc scripts/remote-stress-throughput.ts",
69
70
  "sync:marketplace": "node scripts/sync-marketplace.mjs",
@@ -1,2 +1,2 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/MarketplaceDrawer-BuCbtqFk.js","assets/index-BOpmn5Ij.js","assets/index-rPYd0MUk.css","assets/search-DKgM9IgX.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,ai as ee,aj as te,e as ae,i as re,R as se,P as ne,O as oe,k as le,m as ie,a2 as de,z as ce,X as me,T as xe,ak as ue}from"./index-BOpmn5Ij.js";import{S as pe}from"./search-DKgM9IgX.js";import{S as he}from"./square-terminal-DMWazpEv.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"}]],be=z("bookmark-plus",fe);const ge=[["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",ge);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(),[b,x]=d.useState(!1),[m,u]=d.useState(""),[g,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(!b)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)}},[b]),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":b,"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})]}),b?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:g!==null,onOpenChange:r=>{r||k(null)},title:o("addWorker.templateDeleteTitle"),description:g?o("addWorker.templateDeleteConfirm",{name:g.name}):"",confirmLabel:o("addWorker.templateDeleteConfirmLabel"),confirmKind:"danger",onConfirm:()=>{if(!g||a)return;const r=g.id;k(null),n(r)}})]})},We=({canSaveAsTemplate:t,modified:a,onChange:n,onReset:s,onSaveAsTemplate:c,roleDescription:o,templateBusy:b,workerRole:x,writeDisabledReason:m})=>{const{t:u,language:g}=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=g==="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(be,{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:b||!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:b})=>{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:b,"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),b=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")}),b?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-BuCbtqFk.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:b,onNameChange:x,onPresetChange:m,onRandomName:u,onRoleDescriptionChange:g,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:b,onSelect:p,selectedTemplateId:P}):null,e.jsx(We,{canSaveAsTemplate:W==="custom"&&!P&&h.trim().length>0,modified:X,onChange:g,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-B8JW-znT.js","assets/index-B8tv0NRK.js","assets/index-CG2TurwT.css","assets/search-CcRvD2Q5.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-B8tv0NRK.js";import{S as pe}from"./search-CcRvD2Q5.js";import{S as he}from"./square-terminal-zBgH6nhI.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-B8JW-znT.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};