@ycodium-ai/plugin-team 0.2.3635 → 0.2.3681

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.
package/dist/index.js CHANGED
@@ -7,78 +7,6 @@ var __export = (target, all3) => {
7
7
  // src/index.ts
8
8
  import { definePlugin } from "@ycodium-ai/plugin-api";
9
9
 
10
- // ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=78523ded7c3dfc3efd3cec0247f4960d00eaa3d3c96a2077457694a4d8b453c6/node_modules/effect/dist/Option.js
11
- var Option_exports = {};
12
- __export(Option_exports, {
13
- Do: () => Do,
14
- all: () => all,
15
- andThen: () => andThen,
16
- as: () => as,
17
- asVoid: () => asVoid,
18
- bind: () => bind2,
19
- bindTo: () => bindTo2,
20
- composeK: () => composeK,
21
- contains: () => contains,
22
- containsWith: () => containsWith,
23
- exists: () => exists,
24
- filter: () => filter,
25
- filterMap: () => filterMap,
26
- firstSomeOf: () => firstSomeOf,
27
- flatMap: () => flatMap,
28
- flatMapNullishOr: () => flatMapNullishOr,
29
- flatten: () => flatten,
30
- fromIterable: () => fromIterable,
31
- fromNullOr: () => fromNullOr,
32
- fromNullishOr: () => fromNullishOr,
33
- fromUndefinedOr: () => fromUndefinedOr,
34
- gen: () => gen,
35
- getFailure: () => getFailure2,
36
- getOrElse: () => getOrElse,
37
- getOrNull: () => getOrNull,
38
- getOrThrow: () => getOrThrow,
39
- getOrThrowWith: () => getOrThrowWith,
40
- getOrUndefined: () => getOrUndefined,
41
- getSuccess: () => getSuccess2,
42
- isNone: () => isNone2,
43
- isOption: () => isOption2,
44
- isSome: () => isSome2,
45
- let: () => let_2,
46
- lift2: () => lift2,
47
- liftNullishOr: () => liftNullishOr,
48
- liftPredicate: () => liftPredicate,
49
- liftThrowable: () => liftThrowable,
50
- makeCombinerFailFast: () => makeCombinerFailFast,
51
- makeEquivalence: () => makeEquivalence,
52
- makeOrder: () => makeOrder,
53
- makeReducer: () => makeReducer,
54
- makeReducerFailFast: () => makeReducerFailFast,
55
- map: () => map,
56
- match: () => match,
57
- none: () => none2,
58
- orElse: () => orElse,
59
- orElseResult: () => orElseResult,
60
- orElseSome: () => orElseSome,
61
- partitionMap: () => partitionMap,
62
- product: () => product,
63
- productMany: () => productMany,
64
- reduceCompact: () => reduceCompact,
65
- some: () => some2,
66
- tap: () => tap,
67
- toArray: () => toArray,
68
- toRefinement: () => toRefinement,
69
- void: () => void_,
70
- zipLeft: () => zipLeft,
71
- zipRight: () => zipRight,
72
- zipWith: () => zipWith
73
- });
74
-
75
- // ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=78523ded7c3dfc3efd3cec0247f4960d00eaa3d3c96a2077457694a4d8b453c6/node_modules/effect/dist/Combiner.js
76
- function make(combine2) {
77
- return {
78
- combine: combine2
79
- };
80
- }
81
-
82
10
  // ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=78523ded7c3dfc3efd3cec0247f4960d00eaa3d3c96a2077457694a4d8b453c6/node_modules/effect/dist/Pipeable.js
83
11
  var pipeArguments = (self, args2) => {
84
12
  switch (args2.length) {
@@ -548,7 +476,7 @@ var isEqual = (u) => hasProperty(u, symbol2);
548
476
  var asEquivalence = () => equals;
549
477
 
550
478
  // ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=78523ded7c3dfc3efd3cec0247f4960d00eaa3d3c96a2077457694a4d8b453c6/node_modules/effect/dist/Reducer.js
551
- function make2(combine2, initialValue, combineAll) {
479
+ function make(combine2, initialValue, combineAll) {
552
480
  return {
553
481
  combine: combine2,
554
482
  initialValue,
@@ -563,7 +491,10 @@ function make2(combine2, initialValue, combineAll) {
563
491
  }
564
492
 
565
493
  // ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=78523ded7c3dfc3efd3cec0247f4960d00eaa3d3c96a2077457694a4d8b453c6/node_modules/effect/dist/Equivalence.js
566
- var make3 = (isEquivalent) => (self, that) => self === that || isEquivalent(self, that);
494
+ var make2 = (isEquivalent) => (self, that) => self === that || isEquivalent(self, that);
495
+
496
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=78523ded7c3dfc3efd3cec0247f4960d00eaa3d3c96a2077457694a4d8b453c6/node_modules/effect/dist/internal/array.js
497
+ var isArrayNonEmpty = (self) => self.length > 0;
567
498
 
568
499
  // ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=78523ded7c3dfc3efd3cec0247f4960d00eaa3d3c96a2077457694a4d8b453c6/node_modules/effect/dist/internal/doNotation.js
569
500
  var let_ = (map7) => dual(3, (self, name, f) => map7(self, (a) => ({
@@ -578,6 +509,100 @@ var bind = (map7, flatMap4) => dual(3, (self, name, f) => flatMap4(self, (a) =>
578
509
  [name]: b
579
510
  }))));
580
511
 
512
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=78523ded7c3dfc3efd3cec0247f4960d00eaa3d3c96a2077457694a4d8b453c6/node_modules/effect/dist/internal/record.js
513
+ function assignProperty(self, key, value) {
514
+ if (key === "__proto__") {
515
+ Object.defineProperty(self, key, {
516
+ value,
517
+ writable: true,
518
+ enumerable: true,
519
+ configurable: true
520
+ });
521
+ } else {
522
+ ;
523
+ self[key] = value;
524
+ }
525
+ }
526
+ function assignProperties(self, source) {
527
+ for (const key of Reflect.ownKeys(source)) {
528
+ if (Object.prototype.propertyIsEnumerable.call(source, key)) {
529
+ assignProperty(self, key, source[key]);
530
+ }
531
+ }
532
+ }
533
+
534
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=78523ded7c3dfc3efd3cec0247f4960d00eaa3d3c96a2077457694a4d8b453c6/node_modules/effect/dist/Option.js
535
+ var Option_exports = {};
536
+ __export(Option_exports, {
537
+ Do: () => Do,
538
+ all: () => all,
539
+ andThen: () => andThen,
540
+ as: () => as,
541
+ asVoid: () => asVoid,
542
+ bind: () => bind2,
543
+ bindTo: () => bindTo2,
544
+ composeK: () => composeK,
545
+ contains: () => contains,
546
+ containsWith: () => containsWith,
547
+ exists: () => exists,
548
+ filter: () => filter,
549
+ filterMap: () => filterMap,
550
+ firstSomeOf: () => firstSomeOf,
551
+ flatMap: () => flatMap,
552
+ flatMapNullishOr: () => flatMapNullishOr,
553
+ flatten: () => flatten,
554
+ fromIterable: () => fromIterable,
555
+ fromNullOr: () => fromNullOr,
556
+ fromNullishOr: () => fromNullishOr,
557
+ fromUndefinedOr: () => fromUndefinedOr,
558
+ gen: () => gen,
559
+ getFailure: () => getFailure2,
560
+ getOrElse: () => getOrElse,
561
+ getOrNull: () => getOrNull,
562
+ getOrThrow: () => getOrThrow,
563
+ getOrThrowWith: () => getOrThrowWith,
564
+ getOrUndefined: () => getOrUndefined,
565
+ getSuccess: () => getSuccess2,
566
+ isNone: () => isNone2,
567
+ isOption: () => isOption2,
568
+ isSome: () => isSome2,
569
+ let: () => let_2,
570
+ lift2: () => lift2,
571
+ liftNullishOr: () => liftNullishOr,
572
+ liftPredicate: () => liftPredicate,
573
+ liftThrowable: () => liftThrowable,
574
+ makeCombinerFailFast: () => makeCombinerFailFast,
575
+ makeEquivalence: () => makeEquivalence,
576
+ makeOrder: () => makeOrder,
577
+ makeReducer: () => makeReducer,
578
+ makeReducerFailFast: () => makeReducerFailFast,
579
+ map: () => map,
580
+ match: () => match,
581
+ none: () => none2,
582
+ orElse: () => orElse,
583
+ orElseResult: () => orElseResult,
584
+ orElseSome: () => orElseSome,
585
+ partitionMap: () => partitionMap,
586
+ product: () => product,
587
+ productMany: () => productMany,
588
+ reduceCompact: () => reduceCompact,
589
+ some: () => some2,
590
+ tap: () => tap,
591
+ toArray: () => toArray,
592
+ toRefinement: () => toRefinement,
593
+ void: () => void_,
594
+ zipLeft: () => zipLeft,
595
+ zipRight: () => zipRight,
596
+ zipWith: () => zipWith
597
+ });
598
+
599
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=78523ded7c3dfc3efd3cec0247f4960d00eaa3d3c96a2077457694a4d8b453c6/node_modules/effect/dist/Combiner.js
600
+ function make3(combine2) {
601
+ return {
602
+ combine: combine2
603
+ };
604
+ }
605
+
581
606
  // ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=78523ded7c3dfc3efd3cec0247f4960d00eaa3d3c96a2077457694a4d8b453c6/node_modules/effect/dist/Redactable.js
582
607
  var symbolRedactable = /* @__PURE__ */ Symbol.for("~effect/Redactable");
583
608
  var isRedactable = (u) => hasProperty(u, symbolRedactable);
@@ -800,28 +825,6 @@ var pickInternalCall = () => {
800
825
  };
801
826
  var internalCall = /* @__PURE__ */ pickInternalCall();
802
827
 
803
- // ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=78523ded7c3dfc3efd3cec0247f4960d00eaa3d3c96a2077457694a4d8b453c6/node_modules/effect/dist/internal/record.js
804
- function assignProperty(self, key, value) {
805
- if (key === "__proto__") {
806
- Object.defineProperty(self, key, {
807
- value,
808
- writable: true,
809
- enumerable: true,
810
- configurable: true
811
- });
812
- } else {
813
- ;
814
- self[key] = value;
815
- }
816
- }
817
- function assignProperties(self, source) {
818
- for (const key of Reflect.ownKeys(source)) {
819
- if (Object.prototype.propertyIsEnumerable.call(source, key)) {
820
- assignProperty(self, key, source[key]);
821
- }
822
- }
823
- }
824
-
825
828
  // ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=78523ded7c3dfc3efd3cec0247f4960d00eaa3d3c96a2077457694a4d8b453c6/node_modules/effect/dist/internal/core.js
826
829
  var EffectTypeId = `~effect/Effect`;
827
830
  var ExitTypeId = `~effect/Exit`;
@@ -1440,7 +1443,7 @@ var filterMap = /* @__PURE__ */ dual(2, (self, f) => {
1440
1443
  return isSuccess(next) ? some2(next.success) : none2();
1441
1444
  });
1442
1445
  var filter = /* @__PURE__ */ dual(2, (self, predicate) => isNone2(self) ? none2() : predicate(self.value) ? some2(self.value) : none2());
1443
- var makeEquivalence = (isEquivalent) => make3((x, y) => isNone2(x) ? isNone2(y) : isNone2(y) ? false : isEquivalent(x.value, y.value));
1446
+ var makeEquivalence = (isEquivalent) => make2((x, y) => isNone2(x) ? isNone2(y) : isNone2(y) ? false : isEquivalent(x.value, y.value));
1444
1447
  var makeOrder = (O) => make4((self, that) => isSome2(self) ? isSome2(that) ? O(self.value, that.value) : 1 : -1);
1445
1448
  var lift2 = (f) => dual(2, (self, that) => zipWith(self, that, f));
1446
1449
  var liftPredicate = /* @__PURE__ */ dual(2, (b, predicate) => predicate(b) ? some2(b) : none2());
@@ -1465,14 +1468,14 @@ var gen = (...args2) => {
1465
1468
  return some2(state.value);
1466
1469
  };
1467
1470
  function makeReducer(combiner) {
1468
- return make2((self, that) => {
1471
+ return make((self, that) => {
1469
1472
  if (isNone2(self)) return that;
1470
1473
  if (isNone2(that)) return self;
1471
1474
  return some2(combiner.combine(self.value, that.value));
1472
1475
  }, none2());
1473
1476
  }
1474
1477
  function makeCombinerFailFast(combiner) {
1475
- return make((self, that) => {
1478
+ return make3((self, that) => {
1476
1479
  if (isNone2(self) || isNone2(that)) return none2();
1477
1480
  return some2(combiner.combine(self.value, that.value));
1478
1481
  });
@@ -1480,7 +1483,7 @@ function makeCombinerFailFast(combiner) {
1480
1483
  function makeReducerFailFast(reducer) {
1481
1484
  const combine2 = makeCombinerFailFast(reducer).combine;
1482
1485
  const initialValue = some2(reducer.initialValue);
1483
- return make2(combine2, initialValue, (collection) => {
1486
+ return make(combine2, initialValue, (collection) => {
1484
1487
  let out = initialValue;
1485
1488
  for (const value of collection) {
1486
1489
  out = combine2(out, value);
@@ -1490,9 +1493,6 @@ function makeReducerFailFast(reducer) {
1490
1493
  });
1491
1494
  }
1492
1495
 
1493
- // ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=78523ded7c3dfc3efd3cec0247f4960d00eaa3d3c96a2077457694a4d8b453c6/node_modules/effect/dist/internal/array.js
1494
- var isArrayNonEmpty = (self) => self.length > 0;
1495
-
1496
1496
  // ../../node_modules/.pnpm/effect@4.0.0-beta.103_patch_hash=78523ded7c3dfc3efd3cec0247f4960d00eaa3d3c96a2077457694a4d8b453c6/node_modules/effect/dist/Result.js
1497
1497
  var succeed2 = succeed;
1498
1498
  var fail2 = fail;
@@ -7158,7 +7158,6 @@ var TrialSessionClosed = Struct({
7158
7158
  var AUTO_RETRY_CATEGORIES = /* @__PURE__ */ new Set(["rate-limit", "transport"]);
7159
7159
  var NEEDS_CHANGE_CATEGORIES = /* @__PURE__ */ new Set([
7160
7160
  "no-route",
7161
- "other-machine",
7162
7161
  "toolkit-off",
7163
7162
  "model-unavailable",
7164
7163
  "start-failed",
@@ -7431,8 +7430,10 @@ var TeamMember = Struct({
7431
7430
  name: String4,
7432
7431
  principal: optionalKey2(
7433
7432
  Struct({ kind: Literal2("remote-agent"), principalId: String4 })
7434
- )
7433
+ ),
7434
+ remote: optionalKey2(Literal2(true))
7435
7435
  });
7436
+ var isRemoteTeamMember = (member) => member.remote === true || member.principal !== void 0;
7436
7437
  var TeamRuleCode = Literals([
7437
7438
  "member-count",
7438
7439
  "lead-not-member",
@@ -7465,13 +7466,8 @@ function rosterRuleError(input) {
7465
7466
  }
7466
7467
  function teamRuleError(input) {
7467
7468
  if (input.members.length < 1) return "member-count";
7468
- const principals = /* @__PURE__ */ new Set();
7469
7469
  for (const member of input.members) {
7470
- if (member.principal === void 0) continue;
7471
- const { principalId } = member.principal;
7472
- if (principals.has(principalId)) return "duplicate-principal";
7473
- principals.add(principalId);
7474
- if (member.memberId === input.leadMemberId) return "lead-remote";
7470
+ if (isRemoteTeamMember(member) && member.memberId === input.leadMemberId) return "lead-remote";
7475
7471
  }
7476
7472
  return input.members.some((member) => member.memberId === input.leadMemberId) ? null : "lead-not-member";
7477
7473
  }
@@ -7556,14 +7552,15 @@ var workIdentity = (value) => ({
7556
7552
  ...value.principal === void 0 ? {} : { personKey: personKey(value.principal) }
7557
7553
  });
7558
7554
  var BoardPerson = Struct({ key: String4, displayName: String4 });
7559
- var BoardRemoteAgent = Struct({
7555
+ var BoardMachine = Struct({
7560
7556
  principalId: String4,
7561
- label: String4,
7562
- state: Literals(["active", "disabled", "revoked"]),
7563
- lastUsedAt: optionalKey2(String4)
7557
+ environmentId: String4,
7558
+ name: String4,
7559
+ online: Boolean3,
7560
+ lastSeenAt: optionalKey2(String4)
7564
7561
  });
7565
7562
  var BoardRemoteWork = Struct({
7566
- principalId: String4,
7563
+ memberId: String4,
7567
7564
  pending: NullOr(
7568
7565
  Struct({
7569
7566
  count: Number5,
@@ -7631,8 +7628,8 @@ var BoardSnapshot = Struct({
7631
7628
  // 指派菜单的选项:项目里还在队的成员(人和 agent)。引擎里的成员读不出来时省略并标 membersUnavailable。
7632
7629
  assignableMembers: optionalKey2(ArraySchema(AssignableMember)),
7633
7630
  membersUnavailable: optionalKey2(Literal2(true)),
7634
- remoteAgents: ArraySchema(BoardRemoteAgent),
7635
- remoteAgentsUnavailable: optionalKey2(Literal2(true)),
7631
+ machines: ArraySchema(BoardMachine),
7632
+ machinesUnavailable: optionalKey2(Literal2(true)),
7636
7633
  remoteWork: ArraySchema(BoardRemoteWork),
7637
7634
  viewerKey: optionalKey2(String4),
7638
7635
  // 负责人要用看板与项目记忆两组工具;开关由宿主控件拨,这里只读来提示。
@@ -7643,38 +7640,6 @@ var ReadBoardInput = Struct({
7643
7640
  projectId: String4,
7644
7641
  workLineId: optionalKey2(String4)
7645
7642
  });
7646
- var CreateItemInput = Struct({
7647
- projectId: String4,
7648
- title: String4,
7649
- description: optionalKey2(String4),
7650
- /** 指派给的项目成员(引擎成员号);成员存在、未移除由引擎核。 */
7651
- assigneeMemberId: optionalKey2(String4),
7652
- /** 件建在哪条线上;团队层的看板带它,项目层不带(没分线)。 */
7653
- workLineId: optionalKey2(String4),
7654
- requestId: String4
7655
- });
7656
- var UpdateItemInput = Struct({
7657
- projectId: String4,
7658
- workItemId: String4,
7659
- expectedVersion: Int.check(isGreaterThanOrEqualTo3(1)),
7660
- stateId: optionalKey2(String4),
7661
- assigneeMemberId: optionalKey2(String4),
7662
- unassign: optionalKey2(Boolean3)
7663
- });
7664
- var BoardRejection = Struct({
7665
- _tag: Literal2("TeamBoardRejection"),
7666
- commandType: Literals(["createItem", "updateItem", "postComment"]),
7667
- code: String4,
7668
- details: optionalKey2(Unknown2)
7669
- });
7670
- var CreateItemResult = Union2([
7671
- Struct({ workItemId: String4 }),
7672
- BoardRejection
7673
- ]);
7674
- var UpdateItemResult = Union2([
7675
- Struct({ workItemId: String4, version: Number5 }),
7676
- BoardRejection
7677
- ]);
7678
7643
 
7679
7644
  // src/watch.ts
7680
7645
  var emptyChanges = () => ({ cursor: 0, handbookCursor: 0, membersCursor: 0 });
@@ -7872,6 +7837,18 @@ function registerTeamWatch(ctx, hasMember, options) {
7872
7837
  });
7873
7838
  }
7874
7839
 
7840
+ // src/domain/machines.ts
7841
+ async function readMachines(ctx, projectId) {
7842
+ try {
7843
+ const { items } = await ctx.projects.machines.list({ projectId, includeModels: true });
7844
+ return new Map(items.map((machine) => [machine.environmentId, machine]));
7845
+ } catch {
7846
+ return null;
7847
+ }
7848
+ }
7849
+ var memberEnvironment = (member) => member.agent?.environmentId ?? null;
7850
+ var isRemoteMember = (member, localEnvironmentId) => member.kind === "agent" && memberEnvironment(member) !== localEnvironmentId;
7851
+
7875
7852
  // src/workReads.ts
7876
7853
  var PAGE_SIZE = 200;
7877
7854
  async function readPages(maximum, read, keep = "oldest") {
@@ -8052,7 +8029,7 @@ var lineScopeOfThread = (project2, threadId) => {
8052
8029
  var scopeOfPrincipal = (project2, principalId) => scopesOf(project2).find((scope2) => scope2.remoteMembers.includes(principalId));
8053
8030
  var isGoalThread = (project2, threadId) => scopeOfThread(project2, threadId) !== void 0;
8054
8031
  var isLeadThread = (project2, threadId) => scopesOf(project2).some((scope2) => scope2.leadThreads?.includes(threadId) === true);
8055
- var isRemoteMember = (project2, principalId) => scopeOfPrincipal(project2, principalId) !== void 0;
8032
+ var isRemoteMember2 = (project2, principalId) => scopeOfPrincipal(project2, principalId) !== void 0;
8056
8033
  var leadOfThread = (project2, threadId) => scopeOfThread(project2, threadId)?.leadThreads?.[0];
8057
8034
  var placeOfRecipient = (project2, who, workLineId) => {
8058
8035
  if ("threadId" in who) {
@@ -8140,7 +8117,7 @@ var memberLookup = (project2) => {
8140
8117
  let pinned;
8141
8118
  return (threadId) => isGoalThread(project2, threadId) || (pinned ??= pinnedOpenThreads(project2)).has(threadId);
8142
8119
  };
8143
- var isMember = (project2, recipient) => "threadId" in recipient ? isGoalThread(project2, recipient.threadId) || hasPinnedOpenItem(project2, recipient.threadId) : isRemoteMember(project2, recipient.principalId);
8120
+ var isMember = (project2, recipient) => "threadId" in recipient ? isGoalThread(project2, recipient.threadId) || hasPinnedOpenItem(project2, recipient.threadId) : isRemoteMember2(project2, recipient.principalId);
8144
8121
  var isQueuedUnclaimed = (item, threadId) => item.wakeStatus?.[threadId] === "pending" && !item.claimedBy.includes(threadId);
8145
8122
  var isDeferredWake = (project2, item, threadId) => isGoalThread(project2, threadId) && !isLeadThread(project2, threadId) && item.assigneeThreads.includes(threadId) && isQueuedUnclaimed(item, threadId) && !isClosed(item);
8146
8123
  function countDeferredWakes(project2, threadId) {
@@ -8327,34 +8304,6 @@ async function readPinnedSessions(ctx, rows, wakeProject, listed) {
8327
8304
  );
8328
8305
  }
8329
8306
 
8330
- // src/workWrites.ts
8331
- var decodeHostRefusal = decodeUnknownOption2(
8332
- Struct({
8333
- rejection: Struct({
8334
- code: String4,
8335
- details: optionalKey2(Unknown2)
8336
- })
8337
- })
8338
- );
8339
- var rejectWork = (commandType, code) => ({ _tag: "TeamBoardRejection", commandType, code });
8340
- async function writeWork(invocation, commandType, write) {
8341
- if (invocation.asPerson === void 0) return rejectWork(commandType, "needs-person");
8342
- try {
8343
- return await write(invocation.asPerson.work);
8344
- } catch (error) {
8345
- const refusal = decodeHostRefusal(error);
8346
- if (isNone2(refusal)) throw error;
8347
- const { code, details } = refusal.value.rejection;
8348
- return {
8349
- ...rejectWork(
8350
- commandType,
8351
- commandType !== "postComment" && code === "version-conflict" ? "stale-version" : code
8352
- ),
8353
- ...details === void 0 ? {} : { details }
8354
- };
8355
- }
8356
- }
8357
-
8358
8307
  // src/domain/goalItem.ts
8359
8308
  var teamGoalItemId = (projectId, goalId) => `team-goal:${projectId}:${goalId}`;
8360
8309
  var GOAL_ITEM_TITLE_MAX = 120;
@@ -8366,10 +8315,7 @@ var goalItemTitle = (goal) => {
8366
8315
  // src/board.ts
8367
8316
  var ITEM_LIMIT = 500;
8368
8317
  var PEOPLE_LIMIT = 200;
8369
- var REMOTE_AGENT_LIMIT = 1e3;
8370
8318
  var decodeRead2 = decodeUnknownSync(ReadBoardInput);
8371
- var decodeCreate = decodeUnknownOption2(CreateItemInput);
8372
- var decodeUpdate = decodeUnknownOption2(UpdateItemInput);
8373
8319
  function registerBoardCommands(ctx, goals, rosters, wakes, options = {}) {
8374
8320
  const hasMember = async (projectId, threadIds) => {
8375
8321
  const members = (await goals.allOf(projectId)).flatMap((goal) => goalExecution(goal).members);
@@ -8395,11 +8341,6 @@ function registerBoardCommands(ctx, goals, rosters, wakes, options = {}) {
8395
8341
  goal: read !== null && workLineId !== void 0 && read.workLineId !== workLineId ? null : read
8396
8342
  };
8397
8343
  };
8398
- const memberUnavailable = (result2) => {
8399
- const details = result2.details;
8400
- const field = (key) => typeof details === "object" && details !== null ? Reflect.get(details, key) : void 0;
8401
- return result2.code === "not-found" && field("entity") === "member" || result2.code === "not-permitted" && field("reason") === "invalid-state" ? { ...result2, code: "member-unavailable" } : result2;
8402
- };
8403
8344
  ctx.command({
8404
8345
  name: "board",
8405
8346
  scope: "read",
@@ -8411,7 +8352,7 @@ function registerBoardCommands(ctx, goals, rosters, wakes, options = {}) {
8411
8352
  { goal, roster, members, aliases },
8412
8353
  toolkitStates,
8413
8354
  people,
8414
- remoteAgents,
8355
+ machines,
8415
8356
  viewer,
8416
8357
  lines,
8417
8358
  everyGoal
@@ -8422,11 +8363,8 @@ function registerBoardCommands(ctx, goals, rosters, wakes, options = {}) {
8422
8363
  ctx.projects.toolkits.get({ projectId }),
8423
8364
  // 人名只用来显示作者;本机所有者排第一,后面是这个项目认识的账号。
8424
8365
  readPages(PEOPLE_LIMIT, (page) => ctx.communication.people.list({ projectId, ...page })),
8425
- // 主体目录只用于名字与选择器;任何一页读失败都退回空目录,不连累看板。
8426
- readPages(
8427
- REMOTE_AGENT_LIMIT,
8428
- (page) => ctx.auth.remoteAgents.list({ projectId, ...page })
8429
- ).catch(() => null),
8366
+ // 项目里的别的机器:远端作者(那台机器上的 agent)的名字与在线状态;读不出来退回空,不连累看板。
8367
+ readMachines(ctx, projectId),
8430
8368
  // 认出当前读者只为把作者显示成「你」:读不出来就当没有,不连累整张看板。
8431
8369
  invocation.viewer?.communication.people.current({}).catch(() => null),
8432
8370
  // 团队层只核这条线还在(读不到照抛,界面显示读取失败);项目层要全部线(含已归档)来分道,线不设上限。
@@ -8455,9 +8393,15 @@ function registerBoardCommands(ctx, goals, rosters, wakes, options = {}) {
8455
8393
  (roster?.members ?? []).flatMap(
8456
8394
  (member) => member.principal === void 0 ? [] : [
8457
8395
  ctx.work.remoteAgentPending.get({ projectId, principalId: member.principal.principalId }).then(
8458
- ({ work }) => ({ count: work.count, items: work.items }),
8396
+ // 一台机器上可能有好几个成员:只算派给这个成员的(与直接派给那台机器的)。
8397
+ ({ work }) => {
8398
+ const items2 = work.items.filter(
8399
+ (item) => item.memberId === void 0 || item.memberId === member.memberId
8400
+ ).map(({ workItemId, blocked }) => ({ workItemId, blocked }));
8401
+ return { count: items2.length, items: items2 };
8402
+ },
8459
8403
  () => null
8460
- ).then((pending) => ({ principalId: member.principal.principalId, pending }))
8404
+ ).then((pending) => ({ memberId: member.memberId, pending }))
8461
8405
  ]
8462
8406
  )
8463
8407
  ),
@@ -8560,14 +8504,14 @@ function registerBoardCommands(ctx, goals, rosters, wakes, options = {}) {
8560
8504
  }))
8561
8505
  },
8562
8506
  ...roster?.aliases === void 0 ? {} : { rosterAliases: roster.aliases },
8563
- // 读不出来时记一笔,添加菜单要说「读不出来」而不是「还没有」。
8564
- ...remoteAgents === null ? { remoteAgentsUnavailable: true } : {},
8565
- remoteAgents: (remoteAgents?.items ?? []).map(
8566
- ({ principalId, label: label2, state, lastUsedAt }) => ({
8507
+ ...machines === null ? { machinesUnavailable: true } : {},
8508
+ machines: [...machines?.values() ?? []].map(
8509
+ ({ principalId, environmentId, name, online, lastSeenAt }) => ({
8567
8510
  principalId,
8568
- label: label2,
8569
- state,
8570
- ...lastUsedAt === void 0 ? {} : { lastUsedAt }
8511
+ environmentId,
8512
+ name,
8513
+ online,
8514
+ ...lastSeenAt === void 0 ? {} : { lastSeenAt }
8571
8515
  })
8572
8516
  ),
8573
8517
  remoteWork,
@@ -8577,289 +8521,9 @@ function registerBoardCommands(ctx, goals, rosters, wakes, options = {}) {
8577
8521
  };
8578
8522
  }
8579
8523
  });
8580
- ctx.command({
8581
- name: "createItem",
8582
- scope: "operate",
8583
- payloadSchema: payloadSchemaOf(CreateItemInput),
8584
- handle: async (payload, invocation) => {
8585
- const decoded = decodeCreate(payload);
8586
- if (isNone2(decoded)) return rejectWork("createItem", "invalid-payload");
8587
- const input = decoded.value;
8588
- if (input.title.trim().length === 0) return rejectWork("createItem", "invalid-title");
8589
- const result2 = await writeWork(
8590
- invocation,
8591
- "createItem",
8592
- (work) => work.items.create({
8593
- projectId: input.projectId,
8594
- title: input.title.trim(),
8595
- requestId: input.requestId,
8596
- ...input.description === void 0 ? {} : { description: input.description },
8597
- ...input.workLineId === void 0 ? {} : { workLineId: input.workLineId },
8598
- ...input.assigneeMemberId === void 0 ? {} : { assignees: [{ kind: "member", memberId: input.assigneeMemberId }] }
8599
- })
8600
- );
8601
- return "code" in result2 ? memberUnavailable(result2) : { workItemId: result2.result.workItemId };
8602
- }
8603
- });
8604
- ctx.command({
8605
- name: "updateItem",
8606
- scope: "operate",
8607
- payloadSchema: payloadSchemaOf(UpdateItemInput),
8608
- handle: async (payload, invocation) => {
8609
- const decoded = decodeUpdate(payload);
8610
- if (isNone2(decoded)) return rejectWork("updateItem", "invalid-payload");
8611
- const input = decoded.value;
8612
- if (input.unassign === true && input.assigneeMemberId !== void 0) {
8613
- return rejectWork("updateItem", "invalid-payload");
8614
- }
8615
- const result2 = await writeWork(
8616
- invocation,
8617
- "updateItem",
8618
- (work) => work.items.update({
8619
- projectId: input.projectId,
8620
- workItemId: input.workItemId,
8621
- expectedVersion: input.expectedVersion,
8622
- ...input.stateId === void 0 ? {} : { stateId: input.stateId },
8623
- ...input.unassign === true ? { assignees: [] } : input.assigneeMemberId === void 0 ? {} : { assignees: [{ kind: "member", memberId: input.assigneeMemberId }] }
8624
- })
8625
- );
8626
- return "code" in result2 ? memberUnavailable(result2) : { workItemId: result2.result.workItemId, version: result2.result.version };
8627
- }
8628
- });
8629
8524
  registerTeamWatch(ctx, hasMember, options);
8630
8525
  }
8631
8526
 
8632
- // src/detailContracts.ts
8633
- var ReadItemDetailInput = Struct({
8634
- projectId: String4,
8635
- workItemId: String4
8636
- });
8637
- var commentText = (raw) => {
8638
- const text = raw.trim();
8639
- return text.length >= 1 && text.length <= 8e3 ? text : null;
8640
- };
8641
- var PostCommentInput = Struct({
8642
- projectId: String4,
8643
- workItemId: String4,
8644
- body: String4,
8645
- parentId: optionalKey2(String4),
8646
- mentions: optionalKey2(
8647
- ArraySchema(
8648
- Struct({
8649
- threadId: optionalKey2(String4),
8650
- principalId: optionalKey2(String4)
8651
- })
8652
- )
8653
- ),
8654
- requestId: String4
8655
- });
8656
- var mentionPrincipal = (mention) => mention.threadId !== void 0 ? mention.principalId === void 0 ? { kind: "agent", threadId: mention.threadId } : null : mention.principalId !== void 0 ? { kind: "remote-agent", principalId: mention.principalId } : null;
8657
- var PostCommentResult = Union2([
8658
- Struct({ commentId: String4 }),
8659
- BoardRejection
8660
- ]);
8661
- var DetailComment = Struct({
8662
- commentId: String4,
8663
- author: WorkIdentity,
8664
- mentions: optionalKey2(ArraySchema(WorkIdentity)),
8665
- body: NullOr(String4),
8666
- parentId: NullOr(String4),
8667
- createdAt: String4
8668
- });
8669
- var DetailActivity = Struct({
8670
- sequence: Number5,
8671
- actor: WorkIdentity,
8672
- /** 经哪个插件代人写的;作者仍是人,没有来源的活动省略。 */
8673
- viaPlugin: optionalKey2(String4),
8674
- at: String4,
8675
- verb: String4,
8676
- // old/new 随 field 变化;正文变化只映射修订号,指派对象仍用开放的 kind。
8677
- changes: ArraySchema(
8678
- Struct({ field: String4, old: Unknown2, new: Unknown2 })
8679
- )
8680
- });
8681
- var Dependency = Struct({
8682
- workItemId: String4,
8683
- sequenceId: Number5,
8684
- title: NullOr(String4),
8685
- stateId: String4,
8686
- stateName: String4
8687
- });
8688
- var ItemDetailSnapshot = Struct({
8689
- // 这件的指派和历史里出现过的项目成员的名字(含人和已移除的);没有成员、或读不出来就省略。
8690
- memberNames: optionalKey2(ArraySchema(MemberName)),
8691
- item: Struct({
8692
- workItemId: String4,
8693
- sequenceId: Number5,
8694
- title: NullOr(String4),
8695
- description: NullOr(String4),
8696
- state: Struct({ stateId: String4, name: String4 }),
8697
- assignees: ArraySchema(WorkIdentity),
8698
- version: Number5
8699
- }),
8700
- blockedBy: ArraySchema(Dependency),
8701
- blocking: ArraySchema(Dependency),
8702
- comments: ArraySchema(DetailComment),
8703
- commentsTruncated: Boolean3,
8704
- history: ArraySchema(DetailActivity),
8705
- historyTruncated: Boolean3
8706
- });
8707
- var ReadItemDetailResult = NullOr(ItemDetailSnapshot);
8708
-
8709
- // src/detail.ts
8710
- var RELATION_LIMIT = 100;
8711
- var COMMENT_LIMIT = 200;
8712
- var HISTORY_LIMIT = 200;
8713
- var GET_BATCH_SIZE = 50;
8714
- var decodeRead3 = decodeUnknownSync(ReadItemDetailInput);
8715
- var decodePost = decodeUnknownOption2(PostCommentInput);
8716
- function registerDetailCommands(ctx, goals, rosters) {
8717
- ctx.command({
8718
- name: "itemDetail",
8719
- scope: "read",
8720
- payloadSchema: payloadSchemaOf(ReadItemDetailInput),
8721
- handle: async (payload) => {
8722
- const { projectId, workItemId } = decodeRead3(payload);
8723
- const result2 = await ctx.work.items.get({ projectId, workItemIds: [workItemId] });
8724
- const item = result2.items.find((row) => row.workItemId === workItemId);
8725
- if (item === void 0) return null;
8726
- const base = { projectId, workItemId };
8727
- const relations = (type) => readPages(
8728
- RELATION_LIMIT,
8729
- (page) => ctx.work.relations.list({ ...base, types: [type], ...page })
8730
- );
8731
- const [blockedBy, blocking, comments, history] = await Promise.all([
8732
- relations("blocked_by"),
8733
- relations("blocking"),
8734
- // 评论与历史宿主按旧到新给;留最近的,刚发生的提问和动作不能被挤掉。
8735
- readPages(COMMENT_LIMIT, (page) => ctx.work.comments.list({ ...base, ...page }), "newest"),
8736
- readPages(HISTORY_LIMIT, (page) => ctx.work.history.list({ ...base, ...page }), "newest")
8737
- ]);
8738
- const relatedIds = [
8739
- ...new Set([...blockedBy.items, ...blocking.items].map((row) => row.workItemId))
8740
- ];
8741
- const related = /* @__PURE__ */ new Map();
8742
- for (let offset = 0; offset < relatedIds.length; offset += GET_BATCH_SIZE) {
8743
- const page = await ctx.work.items.get({
8744
- projectId,
8745
- workItemIds: relatedIds.slice(offset, offset + GET_BATCH_SIZE)
8746
- });
8747
- for (const row of page.items) {
8748
- related.set(row.workItemId, {
8749
- workItemId: row.workItemId,
8750
- sequenceId: row.sequenceId,
8751
- title: row.bodyState === "present" ? row.title : null,
8752
- stateId: row.state.stateId,
8753
- stateName: row.state.name
8754
- });
8755
- }
8756
- }
8757
- const assignedMembers = /* @__PURE__ */ new Set();
8758
- const collect = (people) => {
8759
- for (const who of people)
8760
- if (who.kind === "member" && who.memberId !== void 0)
8761
- assignedMembers.add(who.memberId);
8762
- };
8763
- collect(item.assignees);
8764
- for (const activity of history.items)
8765
- for (const change of activity.changes)
8766
- if (change.field === "assignees" || change.field === "mentions") {
8767
- collect(change.old);
8768
- collect(change.new);
8769
- }
8770
- const memberNames = assignedMembers.size === 0 ? [] : await rosters.memberNames(projectId, [...assignedMembers]).catch(() => []);
8771
- const dependencies = (rows) => rows.flatMap((row) => {
8772
- const other = related.get(row.workItemId);
8773
- return other === void 0 ? [] : [other];
8774
- });
8775
- return {
8776
- ...memberNames.length === 0 ? {} : { memberNames },
8777
- item: {
8778
- workItemId: item.workItemId,
8779
- sequenceId: item.sequenceId,
8780
- title: item.bodyState === "present" ? item.title : null,
8781
- description: item.bodyState === "present" ? item.description : null,
8782
- state: { stateId: item.state.stateId, name: item.state.name },
8783
- assignees: item.assignees.map(workIdentity),
8784
- version: item.version
8785
- },
8786
- blockedBy: dependencies(blockedBy.items),
8787
- blocking: dependencies(blocking.items),
8788
- comments: comments.items.map((comment) => ({
8789
- commentId: comment.commentId,
8790
- author: workIdentity(comment.author),
8791
- mentions: comment.mentions.map(workIdentity),
8792
- body: comment.bodyState === "present" ? comment.body : null,
8793
- parentId: comment.parentId,
8794
- createdAt: comment.createdAt
8795
- })).sort((a, b) => a.createdAt.localeCompare(b.createdAt)),
8796
- commentsTruncated: comments.truncated,
8797
- history: history.items.map((activity) => ({
8798
- sequence: activity.sequence,
8799
- actor: workIdentity(activity.actor),
8800
- ...activity.viaPlugin === void 0 ? {} : { viaPlugin: activity.viaPlugin },
8801
- at: activity.at,
8802
- verb: activity.verb,
8803
- // 工作线自己的成员组变化只有加、减两批,没有前后值,也不会出现在一件工作项的历史里:不转。
8804
- changes: activity.changes.filter((change) => change.field !== "members").map((change) => {
8805
- if ("oldRevision" in change) {
8806
- return { field: change.field, old: change.oldRevision, new: change.newRevision };
8807
- }
8808
- if (change.field === "assignees" || change.field === "mentions") {
8809
- return {
8810
- field: change.field,
8811
- old: change.old.map(workIdentity),
8812
- new: change.new.map(workIdentity)
8813
- };
8814
- }
8815
- if (change.field === "state") {
8816
- return {
8817
- field: change.field,
8818
- old: change.old === null ? null : { stateId: change.old.stateId },
8819
- new: change.new === null ? null : { stateId: change.new.stateId }
8820
- };
8821
- }
8822
- return { field: change.field, old: change.old, new: change.new };
8823
- })
8824
- })),
8825
- historyTruncated: history.truncated
8826
- };
8827
- }
8828
- });
8829
- ctx.command({
8830
- name: "postComment",
8831
- scope: "operate",
8832
- payloadSchema: payloadSchemaOf(PostCommentInput),
8833
- handle: async (payload, invocation) => {
8834
- const decoded = decodePost(payload);
8835
- if (isNone2(decoded)) return rejectWork("postComment", "invalid-payload");
8836
- const { mentions, ...input } = decoded.value;
8837
- const body = commentText(input.body);
8838
- if (body === null) return rejectWork("postComment", "invalid-body");
8839
- const principals = mentions?.flatMap((mention) => mentionPrincipal(mention) ?? []);
8840
- if (principals?.length !== mentions?.length)
8841
- return rejectWork("postComment", "invalid-payload");
8842
- if (principals !== void 0 && principals.length > 0) {
8843
- const members = (await goals.allOf(input.projectId)).flatMap(
8844
- (goal) => goalExecution(goal).members
8845
- );
8846
- if (principals.some((principal) => findGoalMember(members, principal) === void 0))
8847
- return rejectWork("postComment", "not-a-member");
8848
- }
8849
- const result2 = await writeWork(
8850
- invocation,
8851
- "postComment",
8852
- (work) => work.comments.post({
8853
- ...input,
8854
- body,
8855
- ...principals === void 0 ? {} : { mentions: principals }
8856
- })
8857
- );
8858
- return "code" in result2 ? result2 : { commentId: result2.result.commentId };
8859
- }
8860
- });
8861
- }
8862
-
8863
8527
  // src/runtime/serial.ts
8864
8528
  function createSerial(closedMessage = "team-serial-closed") {
8865
8529
  let pending = Promise.resolve();
@@ -8885,7 +8549,7 @@ function createSerial(closedMessage = "team-serial-closed") {
8885
8549
  }
8886
8550
 
8887
8551
  // src/domain/service.ts
8888
- var HISTORY_LIMIT2 = 500;
8552
+ var HISTORY_LIMIT = 500;
8889
8553
  var ACTIVE_LIMIT = 2e3;
8890
8554
  var MEMBER_NAMES_LIMIT = 50;
8891
8555
  var FactEnvelope = Struct({
@@ -8910,7 +8574,7 @@ async function listMembers(ctx, projectId) {
8910
8574
  }
8911
8575
  async function listMemberHistory(ctx, projectId) {
8912
8576
  const { items } = await readPages(
8913
- HISTORY_LIMIT2,
8577
+ HISTORY_LIMIT,
8914
8578
  (page) => ctx.members.list({ projectId, includeRemoved: true, ...page }),
8915
8579
  "newest"
8916
8580
  );
@@ -8927,18 +8591,23 @@ async function findMember(ctx, projectId, memberId, window) {
8927
8591
  }
8928
8592
  }
8929
8593
  var isActiveAgent = (member) => member.kind === "agent" && member.removedAt === null;
8930
- var toTeamMember = (member) => ({
8931
- memberId: member.memberId,
8932
- name: member.name,
8933
- ...member.identity?.kind === "remote-agent" ? { principal: { kind: "remote-agent", principalId: member.identity.principalId } } : {}
8934
- });
8935
- function resolveTeam(stored, members) {
8594
+ var toTeamMember = (member, where) => {
8595
+ if (!isRemoteMember(member, where.local)) return { memberId: member.memberId, name: member.name };
8596
+ const machine = member.agent === null ? void 0 : where.machines?.get(member.agent.environmentId);
8597
+ return {
8598
+ memberId: member.memberId,
8599
+ name: member.name,
8600
+ remote: true,
8601
+ ...machine === void 0 ? {} : { principal: { kind: "remote-agent", principalId: machine.principalId } }
8602
+ };
8603
+ };
8604
+ function resolveTeam(stored, members, where) {
8936
8605
  if (stored === null) return { team: null, problem: null };
8937
8606
  if (stored.version === 1) return { team: stored.roster, problem: null };
8938
8607
  const { roster: lead } = stored;
8939
8608
  const team = {
8940
8609
  projectId: lead.projectId,
8941
- members: members.filter(isActiveAgent).map(toTeamMember),
8610
+ members: members.filter(isActiveAgent).map((member) => toTeamMember(member, where)),
8942
8611
  leadMemberId: lead.leadMemberId,
8943
8612
  revision: lead.revision,
8944
8613
  updatedAt: lead.updatedAt,
@@ -8957,9 +8626,17 @@ function createRosterService(ctx, options = {}) {
8957
8626
  });
8958
8627
  const now3 = options.now ?? factTime;
8959
8628
  const storedOf = async (projectId) => readFact(await rosters.get(), projectId);
8629
+ const machinesOf = async (projectId) => ({
8630
+ local: ctx.environment.id,
8631
+ machines: await readMachines(ctx, projectId)
8632
+ });
8960
8633
  const activeView = async (projectId) => {
8961
- const [stored, active] = await Promise.all([storedOf(projectId), listMembers(ctx, projectId)]);
8962
- return { stored, active, ...resolveTeam(stored, active) };
8634
+ const [stored, active, where] = await Promise.all([
8635
+ storedOf(projectId),
8636
+ listMembers(ctx, projectId),
8637
+ machinesOf(projectId)
8638
+ ]);
8639
+ return { stored, active, machines: where.machines, ...resolveTeam(stored, active, where) };
8963
8640
  };
8964
8641
  const inspect = async (projectId) => {
8965
8642
  const [view, history] = await Promise.all([
@@ -8984,8 +8661,8 @@ function createRosterService(ctx, options = {}) {
8984
8661
  const stored = await storedOf(projectId);
8985
8662
  if (stored === null) return { team: null };
8986
8663
  if (stored.version === 1) return { team: stored.roster };
8987
- const active = await listMembers(ctx, projectId);
8988
- return { team: resolveTeam(stored, active).team, active };
8664
+ const [active, where] = await Promise.all([listMembers(ctx, projectId), machinesOf(projectId)]);
8665
+ return { team: resolveTeam(stored, active, where).team, active };
8989
8666
  };
8990
8667
  const read = async (projectId) => (await readTeam(projectId)).team;
8991
8668
  const append2 = async (projectId, expectedRevision, lead) => {
@@ -9018,7 +8695,7 @@ function createRosterService(ctx, options = {}) {
9018
8695
  if (expectedRevision !== (stored?.roster.revision ?? 0)) return rejectRoster("stale-revision");
9019
8696
  const lead = active.find((member) => member.memberId === leadMemberId);
9020
8697
  if (lead === void 0 || !isActiveAgent(lead)) return rejectRoster("lead-not-member");
9021
- if (lead.identity?.kind === "remote-agent") return rejectRoster("lead-remote");
8698
+ if (isRemoteMember(lead, ctx.environment.id)) return rejectRoster("lead-remote");
9022
8699
  return append2(projectId, expectedRevision, {
9023
8700
  leadMemberId,
9024
8701
  ...stored?.roster.aliases === void 0 ? {} : { aliases: stored.roster.aliases }
@@ -9288,25 +8965,43 @@ var specKeyOf = (spec) => stableHash(
9288
8965
  JSON.stringify([
9289
8966
  spec.environmentId ?? null,
9290
8967
  canonical(spec.modelSelection ?? null),
9291
- canonical(spec.identity ?? null)
8968
+ // 第三格原是主体(合一之前按远端主体记的成员才有),留着空位让本机成员的旧键不变。
8969
+ null
9292
8970
  ])
9293
8971
  );
9294
8972
  var specOfMember = (member) => ({
9295
8973
  environmentId: member.agent?.environmentId ?? null,
9296
- modelSelection: member.agent?.modelSelection ?? null,
9297
- identity: member.identity ?? null
8974
+ modelSelection: member.agent?.modelSelection ?? null
9298
8975
  });
9299
8976
  var trialIdOf = (projectId, memberId, specKey, attempt) => `team-trial:${stableHash(JSON.stringify([projectId, memberId, specKey, attempt]))}`;
9300
- var remotePrincipalOf = (identity2) => typeof identity2 === "object" && identity2 !== null && "kind" in identity2 && identity2.kind === "remote-agent" && "principalId" in identity2 && typeof identity2.principalId === "string" ? identity2.principalId : null;
9301
8977
 
9302
8978
  // src/domain/defaultModel.ts
9303
8979
  var isSelectionUnavailable = isTagged("ProviderSelectionError");
9304
- async function resolveModel(ctx, base) {
9305
- const selection = await ctx.providers.selection.resolve({ base }).catch((error) => {
9306
- if (isSelectionUnavailable(error)) return null;
8980
+ var MODEL_UNAVAILABLE_REASONS = /* @__PURE__ */ new Set([
8981
+ "instance-not-found",
8982
+ "instance-unavailable",
8983
+ "model-not-in-catalog"
8984
+ ]);
8985
+ var UNAVAILABLE_MESSAGE_KEYS = {
8986
+ "instance-not-found": "instanceNotFound",
8987
+ "instance-unavailable": "instanceUnavailable",
8988
+ "model-not-in-catalog": "modelNotInCatalog"
8989
+ };
8990
+ var unavailableFrom = (error) => {
8991
+ const reason = Reflect.get(error, "reason");
8992
+ return typeof reason === "string" && MODEL_UNAVAILABLE_REASONS.has(reason) ? { code: "model-unavailable", reason } : { code: "model-unavailable" };
8993
+ };
8994
+ async function resolveModel(ctx, base, named = false) {
8995
+ try {
8996
+ return {
8997
+ selection: await ctx.providers.selection.resolve(
8998
+ named && base !== null ? { base, instanceId: base.instanceId, model: base.model } : { base }
8999
+ )
9000
+ };
9001
+ } catch (error) {
9002
+ if (isSelectionUnavailable(error)) return unavailableFrom(error);
9307
9003
  throw error;
9308
- });
9309
- return selection === null ? { code: "model-unavailable" } : { selection };
9004
+ }
9310
9005
  }
9311
9006
  async function resolveDefaultSelection(ctx, projectId) {
9312
9007
  const project2 = await ctx.projects.get({ projectId });
@@ -9335,7 +9030,7 @@ var en_default = {
9335
9030
  handbook: {
9336
9031
  requestConflict: "This requestId was already used for a different handbook request. Use a new requestId.",
9337
9032
  requestVoided: "This requestId was abandoned before the handbook received it. Use a new requestId.",
9338
- ackTool: "Acknowledge the currently required handbook release for your member seat in the current goal. Reading alone does not acknowledge it. Without a goal there are no team members, acknowledgement gates or reminders.",
9033
+ ackTool: "Acknowledge the currently required handbook release as a member of the current goal. Reading alone does not acknowledge it. Without a goal there are no team members, acknowledgement gates or reminders.",
9339
9034
  publishTool: "Publish handbook pages as the local team lead. Reuse requestId only for the same request. Rules changes require acknowledgement; for decisions changes choose requireAck (default false).",
9340
9035
  revertTool: "Restore a handbook release as the local team lead. Reuse requestId only for the same request. Rules changes require acknowledgement; for decisions changes choose requireAck (default false).",
9341
9036
  unknownMember: "Your verified caller identity is not mapped to a member of this project's current goal.",
@@ -9353,9 +9048,9 @@ var en_default = {
9353
9048
  leadBrief: "Read the handbook with wiki_read_handbook and explicitly acknowledge its currently required release with team_acknowledge_handbook before taking new work. Publish or revert it through team_publish_handbook or team_revert_handbook; publishing a release that requires acknowledgement also acknowledges it for you."
9354
9049
  },
9355
9050
  team: {
9356
- openTool: "Turn this conversation into a team. Call it only after the person has agreed, in this conversation, to the team you proposed: who joins (members already in the project, including agents on other machines you can see with work_list_remote_agents) and which new members you will create after the team is open. A member that does not exist yet comes after this call: create it with team_create_member, then add it with team_set_members. This conversation becomes the team's lead and its group chat and is renamed to the team's name: the members you list are added to it, and each local agent member gets its own conversation under yours. Pass a new requestId, and reuse it only to retry the same call. name is the team's name (at most 80 characters); goal is a summary of what was agreed (at most 4000 characters); memberIds are the memberIds of the project members to bring in (not yourself; you are added as the lead); leadName optionally names you as a project member (1-40 characters). The call returns the team's work line, the members and whether each one is ready, and your brief. A conversation that already is a team, or belongs to one, cannot open another.",
9051
+ openTool: "Turn this conversation into a team. Call it only after the person has agreed, in this conversation, to the team you proposed: who joins (members already in the project, including agents on the other machines that joined this project; work_list_machines lists those machines) and which new members you will create after the team is open. A member that does not exist yet comes after this call: create it with team_create_member, then add it with team_set_members. This conversation becomes the team's lead and its group chat and is renamed to the team's name: the members you list are added to it, and each local agent member gets its own conversation under yours. Pass a new requestId, and reuse it only to retry the same call. name is the team's name (at most 80 characters); goal is a summary of what was agreed (at most 4000 characters); memberIds are the memberIds of the project members to bring in (not yourself; you are added as the lead); leadName optionally names you as a project member (1-40 characters). The call returns the team's work line, the members and whether each one is ready, and your brief. A conversation that already is a team, or belongs to one, cannot open another.",
9357
9052
  setMembersTool: "Change who is on this team (only the team's lead conversation can). add: memberIds of project members to bring in; remove: memberIds to take out. Work assigned to a removed member that has not reached it yet is taken back and given to you; work already in their hands stays with them until you decide. You cannot remove yourself, and you cannot change members or leads of other teams. Pass a new requestId, and reuse it only to retry the same call.",
9358
- rosterOverviewTool: "Read everything you need to plan a team: every member of this project with their kind, machine, model, how their trial run stands (trial is none when no trial applies, such as a person; unverified for a remote agent whose machine you cannot test from here; pending until the trial passes; ready once it passed or was skipped; failed; invoked for the conversation that is itself the lead and needs no trial), and the teams they are in (with whether they lead it). Read it before you propose a team and before you create a member.",
9053
+ rosterOverviewTool: "Read everything you need to plan a team: every member of this project with their kind, machine, model, how their trial run stands (trial is none when no trial applies, such as a person; unverified for an agent on another machine with no trial record here; pending until the trial passes; ready once it passed or was skipped; failed; invoked for the conversation that is itself the lead and needs no trial), and the teams they are in (with whether they lead it). Read it before you propose a team and before you create a member.",
9359
9054
  noProject: "This call is not tied to a project, so there is no team to open or change.",
9360
9055
  notLocal: "Only a conversation on this machine can open a team.",
9361
9056
  invalidInput: "Check the arguments: requestId is 1-64 letters, digits, underscores or hyphens; name is 1-80 characters; goal is 1-4000 characters; leadName, if given, is 1-40 characters.",
@@ -9365,6 +9060,9 @@ var en_default = {
9365
9060
  memberNotFound: "There is no member {{memberId}} in this project. List the members with team_roster_overview.",
9366
9061
  memberRemoved: "Member {{memberId}} was removed from the project. Restore them first with team_restore_member.",
9367
9062
  modelUnavailable: "The model chosen for member {{memberId}} is not available on this machine. Check list_providers and list_models, then change it with team_update_member.",
9063
+ instanceNotFound: "The provider instance chosen for member {{memberId}} does not exist on this machine. Check list_providers, then change it with team_update_member.",
9064
+ instanceUnavailable: "The provider instance chosen for member {{memberId}} is turned off or cannot run on this machine. Check list_providers, then change it with team_update_member.",
9065
+ modelNotInCatalog: "The model chosen for member {{memberId}} is not in that provider instance's model list. Check list_models, then change it with team_update_member.",
9368
9066
  noDefaultModel: "Member {{memberId}} has no model of its own and the project has no default model. Give them one with team_update_member.",
9369
9067
  duplicateTeamName: "A team named {{name}} already exists in this project. Choose another name and use a new requestId.",
9370
9068
  leadOnly: "Only the lead conversation of a team can change its members.",
@@ -9384,6 +9082,9 @@ var en_default = {
9384
9082
  requestVoided: "This requestId was abandoned before the change reached the engine. Use a new requestId.",
9385
9083
  invalidAgent: "Give both instanceId and model, or neither.",
9386
9084
  modelUnavailable: "That provider instance or model is not available on this machine. Check list_providers and list_models, then try again.",
9085
+ instanceNotFound: "That provider instance does not exist on this machine. Check list_providers, then try again.",
9086
+ instanceUnavailable: "That provider instance is turned off or cannot run on this machine. Check list_providers, then try again.",
9087
+ modelNotInCatalog: "That model is not in the provider instance's model list. Check list_models, then try again.",
9387
9088
  noDefaultModel: "The project has no default model. Give instanceId and model.",
9388
9089
  notAgentMember: "Only agent members can be changed with this tool.",
9389
9090
  memberInOtherTeam: "Another team is using this member. You can only change or remove members who are on no team, or only on yours. See which teams each member is on with team_roster_overview.",
@@ -9392,100 +9093,13 @@ var en_default = {
9392
9093
  cannotReplaceLead: "You cannot change your own provider or model."
9393
9094
  },
9394
9095
  board: {
9395
- title: "Project board",
9396
- newItem: "New work item",
9397
- itemTitle: "Title",
9398
- description: "Description (optional)",
9399
- assignee: "Assign to (optional)",
9400
- create: "Create work item",
9401
- retryCreate: "Retry creation",
9402
- saving: "Saving\u2026",
9403
- moveTo: "Move to\u2026",
9404
- goalItem: "Goal",
9405
- moveItem: "Move work item #{{number}}",
9406
- moveItemTo: "Move work item #{{number}} to {{state}}",
9407
- assignTo: "Assign to\u2026",
9408
- assignItem: "Assign work item #{{number}}",
9409
- assignItemTo: "Assign work item #{{number}} to {{name}}",
9410
- unassign: "Unassign",
9411
- unassignItem: "Unassign work item #{{number}}",
9412
- dragItem: "Drag work item #{{number}} to another state",
9413
- untitled: "(Untitled)",
9096
+ openTeam: "Open this team on the board",
9097
+ openProject: "Open board",
9414
9098
  other: "Other",
9415
- unassigned: "Unassigned",
9416
- sessionRunning: "Session running",
9417
- sessionFailed: "Failed",
9418
- sessionWaiting: "Needs input",
9419
- sessionStopped: "Stopped",
9420
- sessionStoppedAt: "Stopped at {{time}}",
9421
- queued: "Queued",
9422
- dateLocale: "en",
9423
- queuedTitle: "Assigned but not woken yet: waits until their current item is done",
9424
- blockedBy: "Blocked by {{count}} work items",
9425
- noMembers: "There are no members to assign to yet. Add one under Members.",
9426
- membersUnavailable: "Members could not be read, so work cannot be assigned right now. Try reloading the board.",
9427
- loading: "Loading board\u2026",
9428
- loadFailed: "The board could not be loaded. Try reloading it.",
9429
- watchFailed: "Live board updates are unavailable. Reload to reconnect.",
9430
- createFailed: "The work item could not be created. Retry with the same request.",
9431
- updateFailed: "The work item could not be changed. Reloading the board.",
9432
- staleVersion: "The work item was changed elsewhere. Your change was rolled back and the board is being reloaded.",
9433
- memberUnavailable: "That member was removed or no longer exists, so nothing was assigned. Choose another member.",
9434
- invalidTitle: "Enter a title for the work item.",
9435
- reload: "Reload board",
9436
- truncated: "Showing the first 500 work items in this project.",
9437
- teamTitle: "Team board",
9438
- lane: {
9439
- unlined: "No team",
9440
- archived: "Archived",
9441
- openTeam: "Open team",
9442
- openTeamFor: "Open team {{name}}"
9443
- },
9444
- noTeamHint: "To start a team, agree on the plan in a conversation; the agent opens the team from there."
9099
+ untitled: "(Untitled)"
9445
9100
  },
9446
9101
  detail: {
9447
- title: "Work item details",
9448
9102
  open: "Details",
9449
- openItem: "Open details for work item #{{number}}",
9450
- close: "Close",
9451
- via: "via {{source}}",
9452
- description: "Description",
9453
- noDescription: "(No description)",
9454
- blockedBy: "Blocked by these work items",
9455
- blocking: "Blocking these work items",
9456
- dependency: "#{{number}} {{title}}, {{state}}",
9457
- comments: "Comments",
9458
- noComments: "No comments yet.",
9459
- deletedComment: "(This comment has been deleted)",
9460
- commentsTruncated: "Showing the latest 200 comments, including replies.",
9461
- reply: "Reply",
9462
- replyTo: "Reply to comment {{number}}",
9463
- newComment: "Post a comment",
9464
- commentHint: "To wake a member, choose it under Mention\u2026 (or type @), or choose Reply under its comment. Commenting on an open work item assigned to a remote member also wakes it.",
9465
- mention: "Mention\u2026",
9466
- mentionLabel: "Mention a member \u2014 {{comment}}",
9467
- mentionMember: "Mention {{name}} \u2014 {{comment}}",
9468
- mentionMemberSelected: "{{name}} (mentioned) \u2014 {{comment}}",
9469
- mentionSelected: "{{name}} (mentioned)",
9470
- mentionRemove: "Remove mention of {{name}} \u2014 {{comment}}",
9471
- mentionNone: "Start a goal to mention members.",
9472
- mentionNoneLabel: "Start a goal to mention members \u2014 {{comment}}",
9473
- mentioned: "Mentioned: {{names}}",
9474
- mentionSeparator: ", ",
9475
- notAMember: "One of the mentioned members is not in the current goal. Remove it and try again.",
9476
- send: "Send",
9477
- sendComment: "Send comment",
9478
- sendReply: "Send reply to comment {{number}}",
9479
- sending: "Sending\u2026",
9480
- retry: "Retry",
9481
- retryComment: "Retry comment",
9482
- retryReply: "Retry reply to comment {{number}}",
9483
- invalidBody: "The comment must be 1\u20138000 characters after trimming spaces.",
9484
- commentFailed: "The comment couldn't be posted. Try again.",
9485
- loading: "Loading work item details\u2026",
9486
- loadFailed: "The work item details could not be loaded. Try reloading them.",
9487
- reload: "Reload details",
9488
- notFound: "This work item was not found in this project.",
9489
9103
  actor: {
9490
9104
  you: "You",
9491
9105
  human: "A person",
@@ -9494,24 +9108,7 @@ var en_default = {
9494
9108
  plugin: "Plugin {{pluginId}}",
9495
9109
  localCli: "Local command line",
9496
9110
  system: "System",
9497
- remoteAgentFallback: "Remote agent"
9498
- },
9499
- history: {
9500
- title: "Activity history",
9501
- empty: "No activity yet.",
9502
- truncated: "Showing the latest 200 activities.",
9503
- deletedState: "(Deleted state)",
9504
- created: "{{author}} created this work item",
9505
- createdAssigned: "{{author}} created this work item and assigned it to {{names}}",
9506
- stateChanged: "{{author}} changed the state from {{old}} to {{new}}",
9507
- assigned: "{{author}} assigned this work item to {{names}}",
9508
- unassigned: "{{author}} removed the assignment",
9509
- titleChanged: "{{author}} changed the title",
9510
- descriptionChanged: "{{author}} changed the description",
9511
- claimed: "{{author}} claimed this work item",
9512
- commented: "{{author}} posted a comment",
9513
- relationAdded: "{{author}} added a dependency",
9514
- relationRemoved: "{{author}} removed a dependency"
9111
+ remoteAgentFallback: "Another machine"
9515
9112
  }
9516
9113
  },
9517
9114
  goal: {
@@ -9519,7 +9116,7 @@ var en_default = {
9519
9116
  lead: "Lead: {{name}}",
9520
9117
  unknownLead: "This member is no longer on the team",
9521
9118
  openLead: "Open lead thread",
9522
- remoteMembers: "Remote members:",
9119
+ remoteMembers: "Members on other machines:",
9523
9120
  item: "Goal work item #{{number}}: {{state}}",
9524
9121
  openItem: "Open details for goal work item #{{number}}"
9525
9122
  },
@@ -9546,7 +9143,6 @@ var en_default = {
9546
9143
  makeLeadFor: "Make {{name}} the lead",
9547
9144
  person: "Person",
9548
9145
  agent: "Agent",
9549
- remote: "Remote agent",
9550
9146
  edit: "Edit",
9551
9147
  editFor: "Edit {{name}}",
9552
9148
  remove: "Remove",
@@ -9564,8 +9160,7 @@ var en_default = {
9564
9160
  restoredNotice: "Member restored.",
9565
9161
  leadChosen: "Lead chosen.",
9566
9162
  kind: "Type",
9567
- kindAgentHint: "Runs with the provider and model you pick when the machine is this one. A member set to another machine fails its trial run: set it back to this machine, or skip the trial run, and it runs on this machine with the project's default model.",
9568
- kindRemoteHint: "An agent that connects from another machine with its own credentials.",
9163
+ kindAgentHint: "Runs on the machine you pick, with that machine's provider and model. Other machines appear here after they join this project.",
9569
9164
  kindPersonHint: "People are listed as members but do not run sessions.",
9570
9165
  thisIsMe: "This is me",
9571
9166
  thisIsMeHint: "When someone @-mentions this member in a team group, the message goes to your Sent to me.",
@@ -9594,20 +9189,14 @@ var en_default = {
9594
9189
  providersFailed: "The providers on this machine could not be read.",
9595
9190
  noProviders: "This machine has no provider that is ready to use.",
9596
9191
  modelsFailed: "The models of this provider could not be read.",
9597
- remoteAgent: "Remote agent",
9598
- chooseRemote: "Choose a remote agent",
9599
- remoteBound: "Remote agent: {{label}}",
9600
- noRemoteAgents: "There are no available remote agents on this machine yet.",
9601
- allRemoteAgentsAdded: "All available remote agents are already members.",
9602
- remoteAgentsUnavailable: "Could not read the remote agents on this machine. Try again later.",
9603
9192
  save: "Save",
9604
9193
  saving: "Saving\u2026",
9605
9194
  adding: "Adding\u2026",
9606
9195
  problem: {
9607
9196
  memberCount: "A team needs at least one agent member.",
9608
9197
  leadNotMember: "Choose a lead from the agent members.",
9609
- leadRemote: "The lead must be a local member.",
9610
- duplicatePrincipal: "Each remote agent can be a member only once."
9198
+ leadRemote: "The lead must run on this machine.",
9199
+ duplicatePrincipal: "A machine can appear only once in this team list."
9611
9200
  },
9612
9201
  errors: {
9613
9202
  generic: "The change could not be saved. Try again.",
@@ -9615,7 +9204,10 @@ var en_default = {
9615
9204
  invalidPayload: "Check the member fields and try again.",
9616
9205
  noDefaultModel: "This project has no default model. Choose one in the project settings under New threads \u2192 Model, then try again.",
9617
9206
  modelUnavailable: "The project's default model isn't available on this machine. Check the provider, or choose another model in the project settings under New threads \u2192 Model.",
9618
- duplicateMember: "Another member already has this name or remote agent. Rename or remove that member first.",
9207
+ instanceNotFound: "The project's default model belongs to a provider instance that does not exist on this machine. Choose another model in the project settings under New threads \u2192 Model.",
9208
+ instanceUnavailable: "The provider instance of the project's default model is turned off or cannot run on this machine. Check the provider, or choose another model in the project settings under New threads \u2192 Model.",
9209
+ modelNotInCatalog: "The project's default model is not in its provider instance's model list. Choose another model in the project settings under New threads \u2192 Model.",
9210
+ duplicateMember: "Another member already has this name or stands for this person. Rename or remove that member first.",
9619
9211
  alreadyYou: "You are already {{name}} on this roster. Clear \u201CThis is me\u201D on {{name}} first.",
9620
9212
  staleVersion: "This member was changed elsewhere and has been reloaded. Review it and save again.",
9621
9213
  notFound: "This member no longer exists.",
@@ -9628,9 +9220,9 @@ var en_default = {
9628
9220
  importDuplicate: "A member named {{name}} already exists, so the import stopped. Rename or remove it, then import again.",
9629
9221
  importResume: "Members already added are kept. Import again to continue.",
9630
9222
  nameRequired: "Enter a name.",
9631
- remoteRequired: "Choose a remote agent.",
9632
9223
  modelRequired: "Choose a provider and a model.",
9633
- instructionsTooLong: "The work instructions are too long."
9224
+ instructionsTooLong: "The work instructions are too long.",
9225
+ machineMissing: "The machine that {{memberName}} ran on has not joined this project. Add that machine to the project, then import again."
9634
9226
  },
9635
9227
  legacy: {
9636
9228
  title: "This project still uses an older roster",
@@ -9643,7 +9235,7 @@ var en_default = {
9643
9235
  trial: {
9644
9236
  passed: "Trial passed",
9645
9237
  skipped: "Trial skipped",
9646
- remoteVerified: "Remote connection verified",
9238
+ remoteVerified: "Verified on its machine",
9647
9239
  invoked: "Lead conversation, no trial needed",
9648
9240
  pending: "Trial run pending",
9649
9241
  running: "Trial run in progress",
@@ -9651,7 +9243,7 @@ var en_default = {
9651
9243
  failed: "Trial run failed",
9652
9244
  waiting: "Waiting for the other side to pick it up.",
9653
9245
  waitingSeen: "Waiting for the other side to pick it up (last seen {{time}}).",
9654
- remoteNote: "A remote agent runs with its own seat's settings; the trial run only checked the connection and the tool calls.",
9246
+ remoteNote: "The trial ran on its own machine with the model chosen for it: it checked the connection, the tool calls and the handbook.",
9655
9247
  failedDetail: "Reason: {{category}}",
9656
9248
  failedWithText: "Reason: {{category}} ({{detail}})",
9657
9249
  failedSummary: "Trial run failed: {{count}}",
@@ -9673,15 +9265,18 @@ var en_default = {
9673
9265
  transport: "the connection dropped",
9674
9266
  unknown: "an unclassified error",
9675
9267
  timeout: "it did not report back in time",
9676
- "no-route": "there is no usable machine or remote credential for it; reconnect the remote agent, or choose a machine for the member, then retry",
9677
- "other-machine": "it is set to another machine, which this machine cannot run a trial for; set it back to this machine, or skip the trial run to run it here with the project's default model",
9268
+ "no-route": "the machine it runs on has not joined this project; add that machine to the project, or choose another machine for the member, then retry",
9678
9269
  "start-failed": "the trial run could not be started",
9679
9270
  "toolkit-off": "the board and project memory switches are not both on; turn them on, then retry"
9680
9271
  }
9681
9272
  },
9682
9273
  teams: "Teams: {{names}}",
9683
9274
  remoteApprovals: "Approvals are handled on their machine",
9684
- teamsSeparator: ", "
9275
+ teamsSeparator: ", ",
9276
+ thisMachine: "This machine",
9277
+ machineOffline: "{{name}} (offline)",
9278
+ machineRemoved: "A machine that left this project",
9279
+ noMachine: "No machine chosen"
9685
9280
  },
9686
9281
  handbookPanel: {
9687
9282
  title: "Handbook",
@@ -9742,21 +9337,20 @@ var en_default = {
9742
9337
  discard: "Discard edits"
9743
9338
  },
9744
9339
  remoteStatus: {
9745
- title: "Remote members",
9340
+ title: "Members on other machines",
9746
9341
  lastSeen: "Last seen {{time}}",
9747
9342
  neverSeen: "Not seen yet",
9748
9343
  workUnavailable: "Could not read this member's work. Try again later.",
9749
9344
  noWork: "No work assigned.",
9750
9345
  item: "#{{number}} {{title}}",
9751
- disabled: "Disabled",
9752
- revoked: "No active credentials",
9753
9346
  lastSeenUnavailable: "Could not read when it was last seen",
9754
9347
  blocked: "Blocked",
9755
- more: "{{count}} more not listed here"
9348
+ more: "{{count}} more not listed here",
9349
+ machineMissing: "Its machine has not joined this project"
9756
9350
  },
9757
9351
  trial: {
9758
9352
  localPrompt: `This is a trial run for you as a member of this project's team. It only checks that you can reach the team's tools and read its handbook, so do not change any file and do not start other work. Do exactly this, then stop. 1. Call wiki_read_handbook with no arguments. If it returns a head, note head.current.release (a number); if head is null, the project has no handbook yet. 2. Call team_trial_done with trialId "{{trialId}}", and with release set to the number you read when there is one (leave release out when head is null). Report only what you really read: a release you did not read is refused.`,
9759
- remotePrompt: `Trial run for you as a member of this project's team. It only checks that your seat can reach the team's tools and read its handbook, so do not start any work item for it. Do exactly this, then stop. 1. Call team_trial_started with trialId "{{trialId}}". 2. Call wiki_read_handbook with no arguments. If it returns a head, note head.current.release (a number); if head is null, the project has no handbook yet. 3. Call team_trial_done with trialId "{{trialId}}", and with release set to the number you read when there is one (leave release out when head is null). Report only what you really read: a release you did not read is refused.`,
9353
+ remotePrompt: `Trial run for you as a member of this project's team. It only checks that you can reach the team's tools and read its handbook, so do not start any work item for it. Do exactly this, then stop. 1. Call team_trial_started with trialId "{{trialId}}". 2. Call wiki_read_handbook with no arguments. If it returns a head, note head.current.release (a number); if head is null, the project has no handbook yet. 3. Call team_trial_done with trialId "{{trialId}}", and with release set to the number you read when there is one (leave release out when head is null). Report only what you really read: a release you did not read is refused.`,
9760
9354
  startedTool: "Report that you picked up a trial run. Use the trialId from the trial message. A trial run only checks that you can reach the team's tools and read its handbook.",
9761
9355
  doneTool: "Finish a trial run: report the handbook release you read with wiki_read_handbook (leave release out when the project has no handbook). Use the trialId from the trial message. The host checks who is calling; a report for a trial run that was replaced, ended, or was not sent to you is refused.",
9762
9356
  retryTool: "Ask for another trial run of an agent member, as the lead of the current goal, for example when its last trial run failed or never finished. A trial run that is already queued or running is left alone and you are told so. Changing the member's provider or model with team_update_member also starts a new trial run by itself.",
@@ -9773,7 +9367,7 @@ var en_default = {
9773
9367
  retryReady: "This member is ready: its trial run passed or a person skipped it, so there is nothing to retry. A new trial run starts by itself when you change its provider or model with team_update_member.",
9774
9368
  retryFutile: "Another trial run will not help here: this member's trial run failed {{limit}} times in a row with the same setup, or it failed in a way that only changes when something is changed. Change its provider or model with team_update_member, or write to a person with send_message, explaining what is wrong and asking them to fix it or to skip the trial run on the Teams page.",
9775
9369
  failedForLeadNoRetry: "Trial run failed for {{name}} (memberId {{memberId}}): {{reason}}. {{name}} gets no work until a trial run passes, and asking again will not help until something changes. You can: change their provider or model with team_update_member (a new trial run starts by itself); or write to a person with send_message, explaining what is wrong and asking them to fix it or to skip the trial run on the Teams page.",
9776
- waitingForLead: "The trial run for {{name}} (memberId {{memberId}}) was sent {{minutes}} minutes ago and the remote agent has not picked it up. {{name}} may be offline or signed out. Until it picks the trial run up, work assigned to {{name}} will not start. You can: assign the work to another member for now; or write to a person with send_message, so they can check that the remote agent is running or skip the trial run on the Teams page.",
9370
+ waitingForLead: "The trial run for {{name}} (memberId {{memberId}}) was sent {{minutes}} minutes ago and the machine it runs on has not picked it up. That machine may be offline, or its provider may be signed out. Until the trial run is picked up, work assigned to {{name}} will not start. You can: assign the work to another member for now; or write to a person with send_message, so they can check that machine or skip the trial run on the Teams page.",
9777
9371
  failedHeadline: "Trial run failed: {{name}}.",
9778
9372
  failedHeadlineAgain: "Trial run failed again: {{name}}.",
9779
9373
  failedForPerson: "{{reason}}. {{name}} gets no work until a trial run passes. Fix the cause, then choose Retry trial run for that member on the Teams page, or choose Skip trial run.",
@@ -9787,8 +9381,7 @@ var en_default = {
9787
9381
  transport: "the connection to the provider dropped",
9788
9382
  unknown: "an unclassified error",
9789
9383
  timeout: "it did not report back in time",
9790
- "no-route": "there is no usable machine or remote credential for it (a person has to reconnect the remote agent, or choose a machine for the member)",
9791
- "other-machine": "it is set to another machine, which this machine cannot run a trial for (a person can set it back to this machine, or skip the trial run so that it runs here with the project's default model)",
9384
+ "no-route": "the machine it runs on has not joined this project (a person has to add that machine to the project, or choose another machine for the member)",
9792
9385
  "start-failed": "the trial run could not be started",
9793
9386
  "toolkit-off": "the project's board and project memory switches are not both on"
9794
9387
  },
@@ -9862,7 +9455,7 @@ function leadBrief(goal, roster, options = {}) {
9862
9455
  });
9863
9456
  const remoteMembers = (goal.remoteMembers ?? []).map((member) => {
9864
9457
  const name = rosterMemberName(roster, member.memberId) ?? member.memberId;
9865
- return byMember ? `| ${tableCell(name)} | ${tableCell(member.memberId)} | remote-agent: ${tableCell(member.principalId)} |` : `| ${tableCell(name)} | remote-agent: ${tableCell(member.principalId)} |`;
9458
+ return byMember ? `| ${tableCell(name)} | ${tableCell(member.memberId)} | another machine |` : `| ${tableCell(name)} | remote-agent: ${tableCell(member.principalId)} |`;
9866
9459
  });
9867
9460
  const assign2 = memberAssignRule(byMember);
9868
9461
  return [
@@ -9871,7 +9464,7 @@ function leadBrief(goal, roster, options = {}) {
9871
9464
  handbookMessage("leadBrief"),
9872
9465
  "Team members and their assignment identities (your own conversation is omitted):",
9873
9466
  [
9874
- byMember ? "| Member | memberId | threadId / remote principalId |" : "| Member | threadId / remote principalId |",
9467
+ byMember ? "| Member | memberId | threadId / machine |" : "| Member | threadId / remote principalId |",
9875
9468
  byMember ? "| --- | --- | --- |" : "| --- | --- |",
9876
9469
  ...localMembers,
9877
9470
  ...remoteMembers
@@ -10187,8 +9780,6 @@ var MemberRow = Struct({
10187
9780
  title: String4,
10188
9781
  responsibility: String4,
10189
9782
  avatar: NullOr(MemberAvatar),
10190
- /** 远端 agent 成员绑的主体;本机 agent 与人是 null。 */
10191
- remotePrincipalId: NullOr(String4),
10192
9783
  /** 人成员绑着的人是不是正在看这一页的人;没绑就没有这一项。 */
10193
9784
  person: optionalKey2(Literals(["me", "other"])),
10194
9785
  agent: NullOr(
@@ -10216,8 +9807,24 @@ var LegacyOffer = Struct({
10216
9807
  })
10217
9808
  )
10218
9809
  });
9810
+ var MachineRow = Struct({
9811
+ environmentId: String4,
9812
+ name: String4,
9813
+ online: Boolean3,
9814
+ lastSeenAt: optionalKey2(String4),
9815
+ providers: ArraySchema(
9816
+ Struct({
9817
+ instanceId: String4,
9818
+ displayName: String4,
9819
+ models: ArraySchema(Struct({ slug: String4, name: String4 })),
9820
+ defaultModel: optionalKey2(String4)
9821
+ })
9822
+ )
9823
+ });
10219
9824
  var MembersSnapshot = Struct({
10220
9825
  members: ArraySchema(MemberRow),
9826
+ /** 项目里的别的机器;读不出来是 null(表单只给这台机器)。 */
9827
+ machines: NullOr(ArraySchema(MachineRow)),
10221
9828
  /** 存着的带队记录;旧名单与还没设过时 memberId 是 null。 */
10222
9829
  lead: Struct({ memberId: NullOr(String4), revision: Int }),
10223
9830
  /** 开目标能用的团队;成不了队时是 null,原因在 `problem`。 */
@@ -10243,8 +9850,6 @@ var CreateMemberInput = Struct({
10243
9850
  name: String4,
10244
9851
  ...memberTextFields,
10245
9852
  avatar: optionalKey2(MemberAvatar),
10246
- /** 给了就是远端 agent:绑这个主体。 */
10247
- remotePrincipalId: optionalKey2(String4),
10248
9853
  agent: optionalKey2(AgentChoice),
10249
9854
  /** 人成员「这是我」:绑到发起这次调用的人。 */
10250
9855
  bindToMe: optionalKey2(Boolean3)
@@ -10354,8 +9959,8 @@ var MemberChangeCompleted = Struct({
10354
9959
  var coordinatorMessage = (key) => en_default.coordinator[key];
10355
9960
 
10356
9961
  // src/coordinator/entry.ts
10357
- var decodeCreate2 = decodeUnknownSync(CreateMemberToolInput);
10358
- var decodeUpdate2 = decodeUnknownSync(UpdateMemberToolInput);
9962
+ var decodeCreate = decodeUnknownSync(CreateMemberToolInput);
9963
+ var decodeUpdate = decodeUnknownSync(UpdateMemberToolInput);
10359
9964
  var decodeRef = decodeUnknownSync(MemberRefToolInput);
10360
9965
  function registerCoordinator(ctx, runtime) {
10361
9966
  ctx.toolkit({
@@ -10365,13 +9970,13 @@ function registerCoordinator(ctx, runtime) {
10365
9970
  name: "create_member",
10366
9971
  description: coordinatorMessage("createTool"),
10367
9972
  inputSchema: toolSchema(CreateMemberToolInput),
10368
- handle: (input, invocation) => runTool(() => runtime.create(decodeCreate2(input), invocation))
9973
+ handle: (input, invocation) => runTool(() => runtime.create(decodeCreate(input), invocation))
10369
9974
  },
10370
9975
  {
10371
9976
  name: "update_member",
10372
9977
  description: coordinatorMessage("updateTool"),
10373
9978
  inputSchema: toolSchema(UpdateMemberToolInput),
10374
- handle: (input, invocation) => runTool(() => runtime.update(decodeUpdate2(input), invocation))
9979
+ handle: (input, invocation) => runTool(() => runtime.update(decodeUpdate(input), invocation))
10375
9980
  },
10376
9981
  {
10377
9982
  name: "remove_member",
@@ -10403,6 +10008,16 @@ function dataCommandReason(error) {
10403
10008
  }
10404
10009
  var CONFLICT_REASONS = ["request-conflict", "command-id-conflict"];
10405
10010
 
10011
+ // src/workWrites.ts
10012
+ var decodeHostRefusal = decodeUnknownOption2(
10013
+ Struct({
10014
+ rejection: Struct({
10015
+ code: String4,
10016
+ details: optionalKey2(Unknown2)
10017
+ })
10018
+ })
10019
+ );
10020
+
10406
10021
  // src/members/refusal.ts
10407
10022
  function memberRefusal(error) {
10408
10023
  const refusal = decodeHostRefusal(error);
@@ -10481,10 +10096,12 @@ var GUARD_MESSAGES = {
10481
10096
  "model-unavailable": "modelUnavailable",
10482
10097
  "no-default-model": "noDefaultModel"
10483
10098
  };
10484
- var refuse = (code) => ({
10099
+ var refuse = (code, reason) => ({
10485
10100
  status: "rejected",
10486
10101
  code,
10487
- detail: coordinatorMessage(GUARD_MESSAGES[code])
10102
+ detail: coordinatorMessage(
10103
+ code === "model-unavailable" && reason !== void 0 ? UNAVAILABLE_MESSAGE_KEYS[reason] : GUARD_MESSAGES[code]
10104
+ )
10488
10105
  });
10489
10106
  function terminalRefusal(error) {
10490
10107
  const refusal = memberRefusal(error);
@@ -10605,14 +10222,14 @@ function startCoordinatorRuntime(ctx, deps) {
10605
10222
  if (instanceId === void 0 && model === void 0) {
10606
10223
  if (change.op === "update") return {};
10607
10224
  const fallback = await defaultAgent(ctx, projectId);
10608
- return "code" in fallback ? refuse(fallback.code) : { agent: fallback.agent };
10225
+ return "code" in fallback ? refuse(fallback.code, "reason" in fallback ? fallback.reason : void 0) : { agent: fallback.agent };
10609
10226
  }
10610
10227
  if (instanceId === void 0 || model === void 0) return refuse("invalid-agent");
10611
10228
  const environmentId = target?.agent?.environmentId ?? ctx.environment.id;
10612
10229
  if (environmentId !== ctx.environment.id)
10613
10230
  return { agent: { environmentId, modelSelection: { instanceId, model } } };
10614
- const resolved = await resolveModel(ctx, { instanceId, model });
10615
- return "code" in resolved ? refuse(resolved.code) : { agent: { environmentId, modelSelection: resolved.selection.modelSelection } };
10231
+ const resolved = await resolveModel(ctx, { instanceId, model }, true);
10232
+ return "code" in resolved ? refuse(resolved.code, "reason" in resolved ? resolved.reason : void 0) : { agent: { environmentId, modelSelection: resolved.selection.modelSelection } };
10616
10233
  };
10617
10234
  const plan = async (change, requestId, projectId, target) => {
10618
10235
  if (change.op === "create") {
@@ -10746,7 +10363,6 @@ var toMemberRow = (member, trial, viewer) => {
10746
10363
  title: member.title,
10747
10364
  responsibility: member.responsibility,
10748
10365
  avatar: member.avatar === null ? null : { pattern: member.avatar.pattern, color: member.avatar.color },
10749
- remotePrincipalId: member.identity?.kind === "remote-agent" ? member.identity.principalId : null,
10750
10366
  ...person === null ? {} : {
10751
10367
  person: viewer !== null && samePerson(person, viewer) ? "me" : "other"
10752
10368
  },
@@ -10774,6 +10390,18 @@ function membersSnapshot(view, trialOf = () => null, viewer = null) {
10774
10390
  const { stored } = view;
10775
10391
  return {
10776
10392
  members: view.members.map((member) => toMemberRow(member, trialOf(member.memberId), viewer)),
10393
+ machines: view.machines === null ? null : [...view.machines.values()].map((machine) => ({
10394
+ environmentId: machine.environmentId,
10395
+ name: machine.name,
10396
+ online: machine.online,
10397
+ ...machine.lastSeenAt === void 0 ? {} : { lastSeenAt: machine.lastSeenAt },
10398
+ providers: machine.providers.map((provider) => ({
10399
+ instanceId: provider.instanceId,
10400
+ displayName: provider.displayName,
10401
+ models: provider.models.map(({ slug, name }) => ({ slug, name })),
10402
+ ...provider.defaultModel === void 0 ? {} : { defaultModel: provider.defaultModel }
10403
+ }))
10404
+ })),
10777
10405
  lead: {
10778
10406
  memberId: stored?.version === 2 ? stored.roster.leadMemberId : null,
10779
10407
  revision: stored?.roster.revision ?? 0
@@ -10865,8 +10493,8 @@ function foldMemberEvent(state, event) {
10865
10493
  if (event.type === "member.created") {
10866
10494
  const created = decodeCreated(event.payload);
10867
10495
  if (isNone2(created) || created.value.kind !== "agent") return state;
10868
- const { projectId: projectId2, memberId: memberId2, agent, identity: identity2, actor: actor2 } = created.value;
10869
- const spec = specOfMember({ agent, identity: identity2 });
10496
+ const { projectId: projectId2, memberId: memberId2, agent, actor: actor2 } = created.value;
10497
+ const spec = specOfMember({ agent });
10870
10498
  const previous = recordOf(state, projectId2, memberId2);
10871
10499
  const record3 = triggered(
10872
10500
  { projectId: projectId2, memberId: memberId2, removed: false, spec, specKey: specKeyOf(spec) },
@@ -10881,13 +10509,12 @@ function foldMemberEvent(state, event) {
10881
10509
  if (event.type === "member.updated") {
10882
10510
  const updated = decodeUpdated(event.payload);
10883
10511
  if (isNone2(updated)) return state;
10884
- const { projectId: projectId2, memberId: memberId2, agent, identity: identity2, actor: actor2 } = updated.value;
10512
+ const { projectId: projectId2, memberId: memberId2, agent, actor: actor2 } = updated.value;
10885
10513
  const record3 = recordOf(state, projectId2, memberId2);
10886
- if (record3 === null || agent === void 0 && identity2 === void 0) return state;
10514
+ if (record3 === null || agent === void 0) return state;
10887
10515
  const spec = {
10888
- environmentId: agent?.environmentId ?? record3.spec.environmentId,
10889
- modelSelection: agent?.modelSelection ?? record3.spec.modelSelection,
10890
- identity: identity2 === void 0 ? record3.spec.identity : identity2 ?? null
10516
+ environmentId: agent.environmentId,
10517
+ modelSelection: agent.modelSelection
10891
10518
  };
10892
10519
  const specKey = specKeyOf(spec);
10893
10520
  if (specKey === record3.specKey) return state;
@@ -11169,8 +10796,8 @@ function registerMemberCommands(ctx, rosters, writer, trials2) {
11169
10796
  }
11170
10797
 
11171
10798
  // src/members/writes.ts
11172
- var decodeCreate3 = decodeUnknownOption2(CreateMemberInput);
11173
- var decodeUpdate3 = decodeUnknownOption2(UpdateMemberInput);
10799
+ var decodeCreate2 = decodeUnknownOption2(CreateMemberInput);
10800
+ var decodeUpdate2 = decodeUnknownOption2(UpdateMemberInput);
11174
10801
  var decodeRef2 = decodeUnknownOption2(MemberRefInput);
11175
10802
  var decodeImport = decodeUnknownOption2(ImportRosterInput);
11176
10803
  var importedMemberId = (projectId, legacyMemberId) => `imp-${stableHash(JSON.stringify([projectId, legacyMemberId])).slice(0, 24)}`;
@@ -11179,6 +10806,11 @@ var toEngineAgent = (agent) => ({
11179
10806
  environmentId: agent.environmentId,
11180
10807
  modelSelection: agent.modelSelection
11181
10808
  });
10809
+ var rejectDefault = (commandType, refusal) => rejectMember(
10810
+ commandType,
10811
+ refusal.code,
10812
+ "reason" in refusal && refusal.reason !== void 0 ? { reason: refusal.reason } : void 0
10813
+ );
11182
10814
  async function refused(commandType, run2) {
11183
10815
  try {
11184
10816
  return await run2();
@@ -11200,10 +10832,10 @@ function createMemberWriter(ctx, rosters, queue = createSerial()) {
11200
10832
  });
11201
10833
  const meOf = async (commandType, invocation) => await currentPerson(invocation) ?? rejectMember(commandType, "needs-person");
11202
10834
  const create = asPerson("createMember", async (payload, members, invocation) => {
11203
- const decoded = decodeCreate3(payload);
10835
+ const decoded = decodeCreate2(payload);
11204
10836
  if (isNone2(decoded)) return rejectMember("createMember", "invalid-payload");
11205
10837
  const input = decoded.value;
11206
- if (input.kind === "human" ? input.agent !== void 0 || input.remotePrincipalId !== void 0 : input.bindToMe !== void 0)
10838
+ if (input.kind === "human" ? input.agent !== void 0 : input.bindToMe !== void 0)
11207
10839
  return rejectMember("createMember", "invalid-payload");
11208
10840
  let me;
11209
10841
  if (input.bindToMe === true) {
@@ -11214,14 +10846,12 @@ function createMemberWriter(ctx, rosters, queue = createSerial()) {
11214
10846
  const memberId = createdMemberId(input.projectId, input.requestId);
11215
10847
  let agent;
11216
10848
  if (input.kind === "agent") {
11217
- if (input.remotePrincipalId === void 0) {
11218
- if (input.agent !== void 0) {
11219
- agent = toEngineAgent(input.agent);
11220
- } else {
11221
- const fallback = await defaultAgent(ctx, input.projectId);
11222
- if ("code" in fallback) return rejectMember("createMember", fallback.code);
11223
- agent = fallback.agent;
11224
- }
10849
+ if (input.agent !== void 0) {
10850
+ agent = toEngineAgent(input.agent);
10851
+ } else {
10852
+ const fallback = await defaultAgent(ctx, input.projectId);
10853
+ if ("code" in fallback) return rejectDefault("createMember", fallback);
10854
+ agent = fallback.agent;
11225
10855
  }
11226
10856
  }
11227
10857
  const result2 = await refused(
@@ -11236,7 +10866,6 @@ function createMemberWriter(ctx, rosters, queue = createSerial()) {
11236
10866
  ...input.responsibility === void 0 ? {} : { responsibility: input.responsibility },
11237
10867
  ...input.avatar === void 0 ? {} : { avatar: input.avatar },
11238
10868
  ...input.workInstructions === void 0 ? {} : { workInstructions: input.workInstructions },
11239
- ...input.remotePrincipalId === void 0 ? {} : { identity: { kind: "remote-agent", principalId: input.remotePrincipalId } },
11240
10869
  ...me === void 0 ? {} : { identity: { kind: "human", principal: me } },
11241
10870
  ...agent === void 0 ? {} : { agent }
11242
10871
  })
@@ -11244,7 +10873,7 @@ function createMemberWriter(ctx, rosters, queue = createSerial()) {
11244
10873
  return "code" in result2 ? result2 : written(result2);
11245
10874
  });
11246
10875
  const update = asPerson("updateMember", async (payload, members, invocation) => {
11247
- const decoded = decodeUpdate3(payload);
10876
+ const decoded = decodeUpdate2(payload);
11248
10877
  if (isNone2(decoded)) return rejectMember("updateMember", "invalid-payload");
11249
10878
  const input = decoded.value;
11250
10879
  if (input.avatar !== void 0 && input.clearAvatar === true)
@@ -11317,10 +10946,23 @@ function createMemberWriter(ctx, rosters, queue = createSerial()) {
11317
10946
  let local;
11318
10947
  if (missing2.some(({ member }) => member.principal === void 0)) {
11319
10948
  const fallback = await defaultAgent(ctx, projectId);
11320
- if ("code" in fallback) return rejectMember("importRoster", fallback.code);
10949
+ if ("code" in fallback) return rejectDefault("importRoster", fallback);
11321
10950
  local = fallback;
11322
10951
  }
10952
+ const machines = missing2.some(({ member }) => member.principal !== void 0) ? [...(await readMachines(ctx, projectId))?.values() ?? []] : [];
10953
+ const remoteAgentOf = (principalId) => {
10954
+ const machine = machines.find((entry) => entry.principalId === principalId);
10955
+ const provider = machine?.providers[0];
10956
+ const model = provider?.defaultModel ?? provider?.models[0]?.slug;
10957
+ return machine === void 0 || provider === void 0 || model === void 0 ? void 0 : {
10958
+ environmentId: machine.environmentId,
10959
+ modelSelection: { instanceId: provider.instanceId, model }
10960
+ };
10961
+ };
11323
10962
  for (const { member, memberId } of missing2) {
10963
+ const remote = member.principal === void 0 ? void 0 : remoteAgentOf(member.principal.principalId);
10964
+ if (member.principal !== void 0 && remote === void 0)
10965
+ return rejectMember("importRoster", "machine-missing", { memberName: member.name });
11324
10966
  const created = await refused(
11325
10967
  "importRoster",
11326
10968
  () => members.create({
@@ -11328,12 +10970,7 @@ function createMemberWriter(ctx, rosters, queue = createSerial()) {
11328
10970
  memberId,
11329
10971
  kind: "agent",
11330
10972
  name: member.name,
11331
- ...member.principal === void 0 ? local : {
11332
- identity: {
11333
- kind: "remote-agent",
11334
- principalId: member.principal.principalId
11335
- }
11336
- }
10973
+ ...remote === void 0 ? local : { agent: remote }
11337
10974
  })
11338
10975
  );
11339
10976
  if ("code" in created)
@@ -11406,6 +11043,7 @@ var isMentionStart = (text, index) => {
11406
11043
  };
11407
11044
 
11408
11045
  // src/runtime/mentionedMembers.ts
11046
+ var mentionPrincipal = (member) => member.threadId !== void 0 ? member.principalId === void 0 ? { kind: "agent", threadId: member.threadId } : null : member.principalId !== void 0 ? { kind: "remote-agent", principalId: member.principalId } : null;
11409
11047
  var ASCII_WORD = /[A-Za-z0-9_-]/;
11410
11048
  function mentionedMembers(body, members) {
11411
11049
  const aliases = members.flatMap((member) => {
@@ -11642,6 +11280,33 @@ function startCommentMentionRuntime(ctx, goals) {
11642
11280
  ctx.reactor({ name: "team-comment-mentions", events: ["work.comment-posted"], handle });
11643
11281
  }
11644
11282
 
11283
+ // src/runtime/dispatchClaim.ts
11284
+ var allow = { allowed: true };
11285
+ var claim = (detail) => ({ allowed: false, detail });
11286
+ function registerDispatchClaim(ctx, wakes) {
11287
+ const check = async (input) => {
11288
+ const project2 = readFact(
11289
+ await wakes.get({ throughSequence: input.throughSequence }),
11290
+ input.projectId
11291
+ );
11292
+ if (project2 === null) return allow;
11293
+ if (input.workLineId !== null && project2.lineScopes?.[input.workLineId] !== void 0)
11294
+ return claim("the team on this work line dispatches its members");
11295
+ if (project2.goalId === void 0) return allow;
11296
+ if (readFact(project2.bindings ?? {}, input.memberId) !== null)
11297
+ return claim("the project's team goal dispatches this member");
11298
+ if (isClosed(readFact(project2.items, teamGoalItemId(input.projectId, project2.goalId))))
11299
+ return allow;
11300
+ const lines = await ctx.work.lines.list({
11301
+ projectId: input.projectId,
11302
+ includeArchived: true,
11303
+ limit: 1
11304
+ });
11305
+ return lines.items.length === 0 ? claim("the project's team goal takes this member in and dispatches it") : allow;
11306
+ };
11307
+ return ctx.operations.guard({ operations: ["work.dispatch"], check });
11308
+ }
11309
+
11645
11310
  // src/runtime/deliveryPacing.ts
11646
11311
  function foldProgress(state, event) {
11647
11312
  const decoded = decodeWorkEvent(event);
@@ -11823,6 +11488,8 @@ function startGroupDeliveryRuntime(ctx, wakes, now3 = () => runPromise2(map5(now
11823
11488
  events: [
11824
11489
  "communication.group-message-sent",
11825
11490
  "work.line-restored",
11491
+ // 线或成员恢复:暂停期间没绑的目标补扫出去。
11492
+ "work.line-resumed",
11826
11493
  "plugin.event-appended",
11827
11494
  "member.created",
11828
11495
  "member.updated",
@@ -11903,8 +11570,14 @@ function startMemberBindingRuntime(ctx, goals, rosters, wakes, trials2) {
11903
11570
  const { projectId } = goal;
11904
11571
  const base = baseOf(goal, member);
11905
11572
  let bound;
11906
- if (member.identity?.kind === "remote-agent") {
11907
- bound = { ...base, principalId: member.identity.principalId };
11573
+ if (isRemoteMember(member, ctx.environment.id)) {
11574
+ const machine = member.agent === null ? void 0 : (await readMachines(ctx, projectId))?.get(member.agent.environmentId);
11575
+ if (machine === void 0)
11576
+ return {
11577
+ code: "no-machine",
11578
+ detail: "the machine they run on has not joined this project, so there is nowhere to send their work"
11579
+ };
11580
+ bound = { ...base, principalId: machine.principalId };
11908
11581
  } else {
11909
11582
  const resolved = await resolveMemberSelection(ctx, projectId, member.agent, defaultSelection);
11910
11583
  if ("code" in resolved) {
@@ -12846,9 +12519,63 @@ function memberStarter(previous, settled, moved) {
12846
12519
  return threadId !== void 0 && Object.values(settled.memberThreads ?? {}).includes(threadId) ? threadId : void 0;
12847
12520
  }
12848
12521
 
12522
+ // src/runtime/linePauseFold.ts
12523
+ var EnginePause = Struct({
12524
+ projectId: String4,
12525
+ workLineId: String4,
12526
+ memberId: optionalKey2(String4)
12527
+ });
12528
+ var decodeEnginePause = decodeUnknownOption2(EnginePause);
12529
+ var pauseOfEngineEvent = (event) => {
12530
+ if (event.type !== "work.line-paused" && event.type !== "work.line-resumed") return null;
12531
+ const decoded = decodeEnginePause(event.payload);
12532
+ if (isNone2(decoded)) return null;
12533
+ return { ...decoded.value, paused: event.type === "work.line-paused" };
12534
+ };
12535
+ function applyPause(project2, change) {
12536
+ const { workLineId, memberId, paused } = change;
12537
+ if (memberId === void 0) {
12538
+ const known = project2.linePauses ?? {};
12539
+ if (paused === (known[workLineId] === true)) return project2;
12540
+ return {
12541
+ ...project2,
12542
+ linePauses: paused ? { ...known, [workLineId]: true } : without(known, workLineId)
12543
+ };
12544
+ }
12545
+ const list = project2.pausedMembers?.[workLineId] ?? [];
12546
+ if (paused === list.includes(memberId)) return project2;
12547
+ const remaining = paused ? [...list, memberId] : list.filter((id) => id !== memberId);
12548
+ const pausedMembers = { ...project2.pausedMembers };
12549
+ if (remaining.length === 0) delete pausedMembers[workLineId];
12550
+ else pausedMembers[workLineId] = remaining;
12551
+ return { ...project2, pausedMembers };
12552
+ }
12553
+ var legacyPauseId = (project2, workLineId, memberId) => memberId === void 0 ? project2.legacyLinePauses?.[workLineId] : project2.legacyMemberPauses?.[workLineId]?.[memberId];
12554
+ function withPause(project2, change, legacyEventId) {
12555
+ const { workLineId, memberId, paused } = change;
12556
+ const previous = legacyPauseId(project2, workLineId, memberId);
12557
+ if (!paused && legacyEventId !== void 0 && previous === void 0) return project2;
12558
+ const next = applyPause(project2, change);
12559
+ const legacy = paused ? legacyEventId : void 0;
12560
+ if (legacy === previous) return next;
12561
+ if (memberId === void 0) {
12562
+ const known2 = project2.legacyLinePauses ?? {};
12563
+ return {
12564
+ ...next,
12565
+ legacyLinePauses: legacy === void 0 ? without(known2, workLineId) : { ...known2, [workLineId]: legacy }
12566
+ };
12567
+ }
12568
+ const known = project2.legacyMemberPauses?.[workLineId] ?? {};
12569
+ const members = legacy === void 0 ? without(known, memberId) : { ...known, [memberId]: legacy };
12570
+ const legacyMemberPauses = { ...project2.legacyMemberPauses };
12571
+ if (Object.keys(members).length === 0) delete legacyMemberPauses[workLineId];
12572
+ else legacyMemberPauses[workLineId] = members;
12573
+ return { ...next, legacyMemberPauses };
12574
+ }
12575
+
12849
12576
  // src/runtime/wakeState.ts
12850
12577
  var WAKE_STATE_KEY = "wakes";
12851
- var WAKE_STATE_VERSION = 8;
12578
+ var WAKE_STATE_VERSION = 9;
12852
12579
  var WAKE_EVENTS = [
12853
12580
  "work.item-created",
12854
12581
  "work.item-updated",
@@ -12858,6 +12585,9 @@ var WAKE_EVENTS = [
12858
12585
  "work.comment-posted",
12859
12586
  "plugin.event-appended",
12860
12587
  "thread.session-set",
12588
+ // 线与线上成员的暂停:引擎的看板事实,派发闸读它(见 `linePauses` / `pausedMembers`)。
12589
+ "work.line-paused",
12590
+ "work.line-resumed",
12861
12591
  // 团队的线归档、恢复,负责人会话被删:这个团队停工(见 `lineStops`)。
12862
12592
  "work.line-archived",
12863
12593
  "work.line-restored",
@@ -12994,28 +12724,17 @@ function foldWorkWakes(state, event) {
12994
12724
  if (fact.name === "team/line-paused" || fact.name === "team/line-member-paused") {
12995
12725
  const { projectId: projectId3, workLineId, status } = fact.data;
12996
12726
  const project4 = readFact(state, projectId3) ?? emptyProject();
12997
- const paused = status === "paused";
12998
- if (fact.name === "team/line-paused") {
12999
- const known = project4.linePauses ?? {};
13000
- if (paused === (known[workLineId] === true)) return state;
13001
- return {
13002
- ...state,
13003
- [projectId3]: {
13004
- ...project4,
13005
- linePauses: paused ? { ...known, [workLineId]: true } : without(known, workLineId)
13006
- }
13007
- };
13008
- }
13009
- const list = project4.pausedMembers?.[workLineId] ?? [];
13010
- if (paused === list.includes(fact.data.memberId)) return state;
13011
- const remaining = paused ? [...list, fact.data.memberId] : list.filter((memberId) => memberId !== fact.data.memberId);
13012
- const pausedMembers = { ...project4.pausedMembers };
13013
- if (remaining.length === 0) delete pausedMembers[workLineId];
13014
- else pausedMembers[workLineId] = remaining;
13015
- return {
13016
- ...state,
13017
- [projectId3]: { ...project4, pausedMembers }
13018
- };
12727
+ const next2 = withPause(
12728
+ project4,
12729
+ {
12730
+ projectId: projectId3,
12731
+ workLineId,
12732
+ ...fact.name === "team/line-member-paused" ? { memberId: fact.data.memberId } : {},
12733
+ paused: status === "paused"
12734
+ },
12735
+ event.eventId
12736
+ );
12737
+ return next2 === project4 ? state : { ...state, [projectId3]: next2 };
13019
12738
  }
13020
12739
  if (fact.name === COMMENT_MENTIONS_EVENT) {
13021
12740
  const { projectId: projectId3, workItemId: workItemId2, commentId, recipients } = fact.data;
@@ -13283,7 +13002,16 @@ function foldLineStops(state, event) {
13283
13002
  }
13284
13003
  return next;
13285
13004
  }
13005
+ function foldEnginePause(state, event) {
13006
+ const change = pauseOfEngineEvent(event);
13007
+ if (change === null) return state;
13008
+ const project2 = readFact(state, change.projectId) ?? emptyProject();
13009
+ const next = withPause(project2, change);
13010
+ return next === project2 ? state : { ...state, [change.projectId]: next };
13011
+ }
13286
13012
  function foldWakes(state, event) {
13013
+ if (event.type === "work.line-paused" || event.type === "work.line-resumed")
13014
+ return foldEnginePause(state, event);
13287
13015
  return foldRecovery(
13288
13016
  pruneReviews(state, foldLineStops(foldWorkWakes(state, event), event)),
13289
13017
  event,
@@ -13323,7 +13051,7 @@ var leadReviewText = (workItemId, sequenceId, title, by, facts) => [
13323
13051
  ...facts.idle.length > 0 && facts.queued.length > 0 ? [LEAD_REBALANCE_RULE] : [],
13324
13052
  LEAD_NO_MEMBER_TASKS
13325
13053
  ].join(" ");
13326
- var commentText2 = (workItemId, sequenceId) => `There is a new comment for you on ${workLabel(workItemId, sequenceId)}. Read it with work_list_comments, passing workItemId: "${workItemId}", and reply there if needed.`;
13054
+ var commentText = (workItemId, sequenceId) => `There is a new comment for you on ${workLabel(workItemId, sequenceId)}. Read it with work_list_comments, passing workItemId: "${workItemId}", and reply there if needed.`;
13327
13055
  function startWakeRuntime(ctx, goals, options = {}) {
13328
13056
  const wakes = ctx.derivedState({
13329
13057
  key: WAKE_STATE_KEY,
@@ -13351,7 +13079,7 @@ function startWakeRuntime(ctx, goals, options = {}) {
13351
13079
  };
13352
13080
  const baseText = async (wake, state) => {
13353
13081
  if ("principalId" in wake || wake.kind === "comment")
13354
- return commentText2(wake.workItemId, wake.sequenceId);
13082
+ return commentText(wake.workItemId, wake.sequenceId);
13355
13083
  const item = await readItem(wake.projectId, wake.workItemId);
13356
13084
  const title = item?.title;
13357
13085
  if (wake.kind === "review") {
@@ -13692,7 +13420,9 @@ function startRecoveryRuntime(ctx, goals, state, worktrees) {
13692
13420
  "thread.turn-intent-transitioned",
13693
13421
  "thread.turn-queue-updated",
13694
13422
  "thread.request-resolved",
13695
- "thread.user-input-pending"
13423
+ "thread.user-input-pending",
13424
+ // 线或成员恢复:暂停期间扣下的恢复计划补发。
13425
+ "work.line-resumed"
13696
13426
  ],
13697
13427
  handle: (event) => flush(recoveryEventScopeOf(event))
13698
13428
  });
@@ -14492,7 +14222,7 @@ function startHandbookRuntime(ctx, worktrees) {
14492
14222
  const flush = () => serial(execute);
14493
14223
  ctx.reactor({
14494
14224
  name: "team-handbook",
14495
- events: [...HANDBOOK_EVENTS2, "work.item-updated"],
14225
+ events: [...HANDBOOK_EVENTS2, "work.item-updated", "work.line-resumed"],
14496
14226
  handle: () => flush()
14497
14227
  });
14498
14228
  ctx.onDispose(queue.close);
@@ -14659,7 +14389,7 @@ var currentSeat = (project2, memberId, wake) => {
14659
14389
  var decodeAcknowledgement = decodeUnknownSync(AcknowledgeInput);
14660
14390
  var decodePublish = decodeUnknownSync(PublishInput);
14661
14391
  var decodeRevert = decodeUnknownSync(RevertInput);
14662
- var decodeRead4 = decodeUnknownSync(ReadHandbookInput);
14392
+ var decodeRead3 = decodeUnknownSync(ReadHandbookInput);
14663
14393
  function registerHandbook(ctx, runtime) {
14664
14394
  ctx.toolkit({
14665
14395
  name: "handbook",
@@ -14693,7 +14423,7 @@ function registerHandbook(ctx, runtime) {
14693
14423
  name: "handbook",
14694
14424
  scope: "read",
14695
14425
  payloadSchema: payloadSchemaOf(ReadHandbookInput),
14696
- handle: (input) => runtime.read(decodeRead4(input).projectId)
14426
+ handle: (input) => runtime.read(decodeRead3(input).projectId)
14697
14427
  });
14698
14428
  ctx.operations.guard({ operations: ["work.start"], check: runtime.startCheck });
14699
14429
  }
@@ -15238,15 +14968,16 @@ function createLineChangeRunner(ctx, deps) {
15238
14968
  }
15239
14969
 
15240
14970
  // src/team/brief.ts
14971
+ var REMOTE_WHERE_PREFIX = "machine: ";
15241
14972
  function teamLeadBrief(team) {
15242
14973
  const table = [
15243
- "| Member | memberId | threadId / remote principalId | Ready |",
14974
+ "| Member | memberId | threadId / machine | Ready |",
15244
14975
  "| --- | --- | --- | --- |",
15245
14976
  ...team.members.map(
15246
14977
  (member) => `| ${tableCell(member.name)} | ${tableCell(member.memberId)} | ${tableCell(member.where)} | ${member.status} |`
15247
14978
  )
15248
14979
  ].join("\n");
15249
- const hasRemote = team.members.some((member) => member.where.startsWith("remote-agent"));
14980
+ const hasRemote = team.members.some((member) => member.where.startsWith(REMOTE_WHERE_PREFIX));
15250
14981
  return [
15251
14982
  `You are now the lead of the team "${team.name}". This conversation is the team: the person talks to you here, and your members are woken from here.`,
15252
14983
  "What was agreed:",
@@ -15260,7 +14991,7 @@ function teamLeadBrief(team) {
15260
14991
  'Then use work_add_relation with type "blocked_by" to record dependencies: the dependent workItemId is blocked by the prerequisite relatedWorkItemId.',
15261
14992
  LEAD_OWN_ITEM_RULE,
15262
14993
  memberAssignRule(true),
15263
- "Add or remove members of the team with team_set_members. To add someone who is not in the project yet, create them first with team_create_member (it starts their trial run), then add them. Use team_roster_overview to see everyone in the project and which teams they are in; work_list_remote_agents lists the agents from other machines that this project has authorized.",
14994
+ "Add or remove members of the team with team_set_members. To add someone who is not in the project yet, create them first with team_create_member (it starts their trial run), then add them. Use team_roster_overview to see everyone in the project and which teams they are in; work_list_machines lists the other machines that joined this project and the providers and models each one offers, for creating a member on one of them.",
15264
14995
  LEAD_SEND_BACK_RULE,
15265
14996
  LEAD_ACCEPT_RULE,
15266
14997
  LEAD_STUCK_RULE,
@@ -15269,7 +15000,7 @@ function teamLeadBrief(team) {
15269
15000
  LEAD_START_CHECK_RULE,
15270
15001
  LEAD_REBALANCE_RULE,
15271
15002
  ...hasRemote ? [
15272
- "Remote members are on another machine. Assign them work like the others; they pick it up from their own machine. Do not create conversations, start turns, or send wake-up signals for them on this machine. A comment that mentions a remote member wakes them on their machine; once they mark an item done they stop working on it, so to send work back you reopen the item as described above. Whatever a remote member needs a person for is handled on their machine, not in this conversation."
15003
+ "Members marked with a machine run on that other machine. Assign them work like the others; their machine picks it up and runs them with the model in their member record. Do not create conversations, start turns, or send wake-up signals for them on this machine; if their machine is offline, the work waits until it is back. A comment that mentions a remote member wakes them on their machine; once they mark an item done they stop working on it, so to send work back you reopen the item as described above. Whatever a remote member needs a person for is handled on their machine, not in this conversation."
15273
15004
  ] : [],
15274
15005
  "How the group works: when a member is woken it is shown what was said in this group since it last looked (the person's words and yours, plus group records, at most about 30 messages; never any tool call or thinking), so you do not have to repeat what was agreed. Older messages are read with list_thread_messages on this conversation, and older group records with message_list { groupThreadId: this conversation }. Members cannot see anything else you do, so put what a member needs into the work item description.",
15275
15006
  "To ask a member something in the group, use send_message with to: { group: { threadId: this conversation } } and mentions: [{ memberId }] for each member your text addresses with @name. Each mentioned member is woken; other group messages and members' replies reach you as a quiet copy in your inbox and never start a turn for you. Members answer in the group with replyTo to the record they are answering; a reply on its own wakes nobody, so a member who needs you mentions you in the text.",
@@ -15399,7 +15130,6 @@ function leadMemberName(leadName, title, tag2) {
15399
15130
  const tail = ` lead${tag2}`;
15400
15131
  return `${title.trim().slice(0, MAX_MEMBER_NAME_LENGTH - tail.length).trimEnd()}${tail}`.trim();
15401
15132
  }
15402
- var remotePrincipalOf2 = (member) => member.identity?.kind === "remote-agent" ? member.identity.principalId : null;
15403
15133
  function createTeamOpener(ctx, deps, runner = createLineChangeRunner(ctx, deps), now3 = factTime) {
15404
15134
  const lineIdOf = (projectId, threadId, requestId) => `wl-${mark(projectId, threadId, requestId).slice(0, 24)}`;
15405
15135
  const goalIdOf = (projectId, threadId, requestId) => `tg-${mark(projectId, threadId, requestId).slice(0, 24)}`;
@@ -15447,7 +15177,7 @@ function createTeamOpener(ctx, deps, runner = createLineChangeRunner(ctx, deps),
15447
15177
  throw new TeamRuleError(
15448
15178
  resolved.code,
15449
15179
  teamMessage(
15450
- resolved.code === "no-default-model" ? "noDefaultModel" : "modelUnavailable",
15180
+ resolved.code === "no-default-model" ? "noDefaultModel" : resolved.reason === void 0 ? "modelUnavailable" : UNAVAILABLE_MESSAGE_KEYS[resolved.reason],
15451
15181
  { memberId: row.memberId }
15452
15182
  )
15453
15183
  );
@@ -15468,7 +15198,11 @@ function createTeamOpener(ctx, deps, runner = createLineChangeRunner(ctx, deps),
15468
15198
  );
15469
15199
  const members = await Promise.all(memberIds.map((id) => findMember(ctx, projectId, id)));
15470
15200
  const rows = members.flatMap((row) => row === null ? [] : [row]);
15471
- const local = rows.filter((row) => row.kind === "agent" && remotePrincipalOf2(row) === null);
15201
+ const local = rows.filter(
15202
+ (row) => row.kind === "agent" && !isRemoteMember(row, ctx.environment.id)
15203
+ );
15204
+ const machines = await readMachines(ctx, projectId);
15205
+ const machineOf = (row) => row.agent === null ? void 0 : machines?.get(row.agent.environmentId);
15472
15206
  const selections = await resolveLocalSelections(projectId, local);
15473
15207
  const leadMemberId = await ensureLeadMember(projectId, callerThreadId, input.leadName);
15474
15208
  const ownerMemberId = await ensureOwnerMember(
@@ -15499,8 +15233,8 @@ function createTeamOpener(ctx, deps, runner = createLineChangeRunner(ctx, deps),
15499
15233
  throw error;
15500
15234
  }
15501
15235
  const remote = rows.flatMap((row) => {
15502
- const principalId = remotePrincipalOf2(row);
15503
- return principalId === null ? [] : [{ memberId: row.memberId, principalId }];
15236
+ const machine = isRemoteMember(row, ctx.environment.id) ? machineOf(row) : void 0;
15237
+ return machine === void 0 ? [] : [{ memberId: row.memberId, principalId: machine.principalId }];
15504
15238
  });
15505
15239
  const lead = await findMember(ctx, projectId, leadMemberId);
15506
15240
  const specKeys = Object.fromEntries(
@@ -15554,11 +15288,10 @@ function createTeamOpener(ctx, deps, runner = createLineChangeRunner(ctx, deps),
15554
15288
  await syncLineTitle(ctx, projectId, workLineId);
15555
15289
  const trials2 = await deps.trials.get();
15556
15290
  const roster = team.map((row) => {
15557
- const principalId = remotePrincipalOf2(row);
15558
15291
  return {
15559
15292
  name: row.name,
15560
15293
  memberId: row.memberId,
15561
- where: principalId !== null ? `remote-agent: ${principalId}` : row.kind === "human" ? "person" : teamThreadId(projectId, goalId, row.memberId),
15294
+ where: isRemoteMember(row, ctx.environment.id) ? `${REMOTE_WHERE_PREFIX}${machineOf(row)?.name ?? "not joined"}` : row.kind === "human" ? "person" : teamThreadId(projectId, goalId, row.memberId),
15562
15295
  status: statusOf2(trials2, projectId, row)
15563
15296
  };
15564
15297
  });
@@ -15632,7 +15365,7 @@ function createTeamOpener(ctx, deps, runner = createLineChangeRunner(ctx, deps),
15632
15365
  }
15633
15366
  await resolveLocalSelections(
15634
15367
  projectId,
15635
- rows.filter((row) => row.kind === "agent" && remotePrincipalOf2(row) === null)
15368
+ rows.filter((row) => row.kind === "agent" && !isRemoteMember(row, ctx.environment.id))
15636
15369
  );
15637
15370
  return {
15638
15371
  ...input,
@@ -15649,13 +15382,11 @@ var MEMBER_LIMIT = 500;
15649
15382
  var TEAM_LIMIT = 200;
15650
15383
  function createTeamOverview(ctx, deps) {
15651
15384
  return async (projectId) => {
15652
- const [members, lines, trials2, wakes] = await Promise.all([
15385
+ const [members, lines, trials2] = await Promise.all([
15653
15386
  readPages(MEMBER_LIMIT, (page) => ctx.members.list({ projectId, ...page })),
15654
15387
  readPages(TEAM_LIMIT, (page) => ctx.work.lines.list({ projectId, ...page })),
15655
- deps.trials.get(),
15656
- deps.wakes.get()
15388
+ deps.trials.get()
15657
15389
  ]);
15658
- const paused = wakes[projectId] ?? {};
15659
15390
  const teamsOf = (memberId) => lines.items.flatMap(
15660
15391
  (line) => line.memberIds.includes(memberId) ? [
15661
15392
  {
@@ -15669,7 +15400,7 @@ function createTeamOverview(ctx, deps) {
15669
15400
  projectId,
15670
15401
  members: members.items.filter((member) => member.removedAt === null).map((member) => {
15671
15402
  const trial = trialViewOf(recordOf(trials2, projectId, member.memberId));
15672
- const principalId = member.identity?.kind === "remote-agent" ? member.identity.principalId : null;
15403
+ const remote = isRemoteMember(member, ctx.environment.id);
15673
15404
  return {
15674
15405
  memberId: member.memberId,
15675
15406
  name: member.name,
@@ -15677,14 +15408,14 @@ function createTeamOverview(ctx, deps) {
15677
15408
  machine: member.agent?.environmentId ?? null,
15678
15409
  model: member.agent === null ? null : member.agent.modelSelection.model,
15679
15410
  provider: member.agent === null ? null : member.agent.modelSelection.instanceId,
15680
- remoteAgent: principalId,
15411
+ remote,
15681
15412
  // 人没有试跑;远端成员没有本机试跑记录时读不出对方机器的情况,标明。
15682
- trial: member.kind === "human" ? "none" : trial === null ? principalId === null ? "none" : "unverified" : trial.evidence === "invoked" ? "invoked" : trial.status === "failed" ? "failed" : trial.status === "passed" || trial.status === "overridden" ? "ready" : "pending",
15413
+ trial: member.kind === "human" ? "none" : trial === null ? remote ? "unverified" : "none" : trial.evidence === "invoked" ? "invoked" : trial.status === "failed" ? "failed" : trial.status === "passed" || trial.status === "overridden" ? "ready" : "pending",
15683
15414
  trialFailure: trial?.failure?.category ?? null,
15684
15415
  teams: teamsOf(member.memberId),
15685
- // 这名成员被暂停的团队:整线暂停,或它在这条线上被单独暂停(ADR-0027:371);判定与派发闸同一份。
15416
+ // 这名成员被暂停的团队:整线暂停,或它在这条线上被单独暂停(ADR-0027:371);读线上的引擎事实。
15686
15417
  pausedOnLines: lines.items.filter(
15687
- (line) => line.memberIds.includes(member.memberId) && (isLinePaused(paused, line.workLineId) || isMemberPausedOnLine(paused, line.workLineId, member.memberId))
15418
+ (line) => line.memberIds.includes(member.memberId) && (line.pause !== void 0 || (line.memberPauses ?? []).some((pause) => pause.memberId === member.memberId))
15688
15419
  ).map((line) => line.workLineId)
15689
15420
  };
15690
15421
  }),
@@ -15694,7 +15425,7 @@ function createTeamOverview(ctx, deps) {
15694
15425
  leadMemberId: line.leadMemberId,
15695
15426
  memberCount: line.memberIds.length,
15696
15427
  conversation: line.threadId,
15697
- paused: isLinePaused(paused, line.workLineId)
15428
+ paused: line.pause !== void 0
15698
15429
  })),
15699
15430
  truncated: members.truncated || lines.truncated
15700
15431
  };
@@ -15890,96 +15621,134 @@ var LineMemberPauseInput = Struct({
15890
15621
  memberId: String4
15891
15622
  });
15892
15623
  var decodeLine = decodeUnknownSync(LinePauseInput);
15624
+ var decodeRestored = decodeUnknownOption2(
15625
+ Struct({ projectId: String4, workLineId: String4 })
15626
+ );
15893
15627
  var decodeMember = decodeUnknownSync(LineMemberPauseInput);
15894
- var appendOf = (name, key) => ({
15895
- commandId: `team-${name}:${stableHash(JSON.stringify([...key]))}`,
15896
- name
15897
- });
15898
- function registerPauseCommands(ctx) {
15899
- const asPerson = (run2) => async (payload, invocation) => {
15628
+ var engineRequestId = (status, target, requestId) => `team-pause:${stableHash(JSON.stringify([status, target.projectId, target.workLineId, target.memberId ?? null, requestId]))}`;
15629
+ function registerPauseCommands(ctx, deps) {
15630
+ const write = async (invocation, status, target, requestId) => {
15631
+ const lines = invocation.asPerson.work.lines;
15632
+ const input = { ...target, requestId: engineRequestId(status, target, requestId) };
15633
+ try {
15634
+ await (status === "paused" ? lines.pause(input) : lines.resume(input));
15635
+ } catch (error) {
15636
+ const code = hostRefusalCode(error);
15637
+ if (code === "not-permitted")
15638
+ throw new Error("This team is archived; restore it instead of pausing", { cause: error });
15639
+ if (code === "invalid-input")
15640
+ throw new Error("This member is not on that team's work line", { cause: error });
15641
+ throw error;
15642
+ }
15643
+ };
15644
+ const handler = (status, withMember) => async (payload, invocation) => {
15900
15645
  if (invocation.asPerson === void 0)
15901
15646
  throw Object.assign(new Error("Only a person can pause or resume a team"), {
15902
15647
  code: "needs-person"
15903
15648
  });
15904
- return run2(payload);
15905
- };
15906
- const setLinePaused = async (input, paused) => {
15907
- const { line } = await ctx.work.lines.get({
15908
- projectId: input.projectId,
15909
- workLineId: input.workLineId
15649
+ const { requestId, ...target } = withMember ? decodeMember(payload) : decodeLine(payload);
15650
+ await deps.queue.run(async () => {
15651
+ await backfillLine(ctx, deps.wakes, target.projectId, target.workLineId);
15652
+ await write(invocation, status, target, requestId);
15653
+ if (status === "resumed") await releaseLegacyLeftover(ctx, deps.wakes, target, requestId);
15910
15654
  });
15911
- if (line.archivedAt !== null)
15912
- throw new Error("This team is archived; restore it instead of pausing");
15913
- await ctx.events.append({
15914
- ...appendOf("line-paused", [input.projectId, input.workLineId, input.requestId]),
15915
- aggregate: { kind: "project", id: input.projectId },
15916
- data: {
15917
- version: 1,
15918
- status: paused ? "paused" : "resumed",
15919
- projectId: input.projectId,
15920
- workLineId: input.workLineId
15921
- }
15922
- });
15923
- return {
15924
- projectId: input.projectId,
15925
- workLineId: input.workLineId,
15926
- status: paused ? "paused" : "resumed"
15927
- };
15928
- };
15929
- const setLineMemberPaused = async (input, paused) => {
15930
- const { line } = await ctx.work.lines.get({
15931
- projectId: input.projectId,
15932
- workLineId: input.workLineId
15933
- });
15934
- if (!line.memberIds.includes(input.memberId))
15935
- throw new Error("This member is not on that team's work line");
15936
- await ctx.events.append({
15937
- ...appendOf("line-member-paused", [
15938
- input.projectId,
15939
- input.workLineId,
15940
- input.memberId,
15941
- input.requestId
15942
- ]),
15943
- aggregate: { kind: "project", id: input.projectId },
15944
- data: {
15945
- version: 1,
15946
- status: paused ? "paused" : "resumed",
15947
- projectId: input.projectId,
15948
- workLineId: input.workLineId,
15949
- memberId: input.memberId
15950
- }
15951
- });
15952
- return {
15953
- projectId: input.projectId,
15954
- workLineId: input.workLineId,
15955
- memberId: input.memberId,
15956
- status: paused ? "paused" : "resumed"
15957
- };
15655
+ return { ...target, status };
15958
15656
  };
15959
15657
  ctx.command({
15960
15658
  name: "pauseLine",
15961
15659
  scope: "operate",
15962
15660
  payloadSchema: payloadSchemaOf(LinePauseInput),
15963
- handle: asPerson((input) => setLinePaused(decodeLine(input), true))
15661
+ handle: handler("paused", false)
15964
15662
  });
15965
15663
  ctx.command({
15966
15664
  name: "resumeLine",
15967
15665
  scope: "operate",
15968
15666
  payloadSchema: payloadSchemaOf(LinePauseInput),
15969
- handle: asPerson((input) => setLinePaused(decodeLine(input), false))
15667
+ handle: handler("resumed", false)
15970
15668
  });
15971
15669
  ctx.command({
15972
15670
  name: "pauseLineMember",
15973
15671
  scope: "operate",
15974
15672
  payloadSchema: payloadSchemaOf(LineMemberPauseInput),
15975
- handle: asPerson((input) => setLineMemberPaused(decodeMember(input), true))
15673
+ handle: handler("paused", true)
15976
15674
  });
15977
15675
  ctx.command({
15978
15676
  name: "resumeLineMember",
15979
15677
  scope: "operate",
15980
15678
  payloadSchema: payloadSchemaOf(LineMemberPauseInput),
15981
- handle: asPerson((input) => setLineMemberPaused(decodeMember(input), false))
15679
+ handle: handler("resumed", true)
15680
+ });
15681
+ ctx.reactor({
15682
+ name: "team-pause-backfill",
15683
+ events: ["work.line-restored"],
15684
+ handle: (event) => match(decodeRestored(event.payload), {
15685
+ onNone: () => Promise.resolve(),
15686
+ onSome: ({ projectId, workLineId }) => deps.queue.run(() => backfillLine(ctx, deps.wakes, projectId, workLineId))
15687
+ })
15688
+ });
15689
+ const ready = deps.queue.run(() => backfillLegacyPauses(ctx, deps.wakes));
15690
+ void ready.catch((error) => ctx.log.warn("team pause backfill failed", { error }));
15691
+ return { ready };
15692
+ }
15693
+ async function backfillLine(ctx, wakes, projectId, workLineId) {
15694
+ try {
15695
+ const { line, snapshotSequence } = await ctx.work.lines.get({ projectId, workLineId });
15696
+ if (line.archivedAt !== null) return;
15697
+ const caught = readFact(await wakes.get({ throughSequence: snapshotSequence }), projectId);
15698
+ if (caught === null) return;
15699
+ const targets = [
15700
+ ...isLinePaused(caught, workLineId) && line.pause === void 0 ? [{ projectId, workLineId }] : [],
15701
+ ...(caught.pausedMembers?.[workLineId] ?? []).filter(
15702
+ (memberId) => isMemberPausedOnLine(caught, workLineId, memberId) && line.memberIds.includes(memberId) && !(line.memberPauses ?? []).some((pause) => pause.memberId === memberId)
15703
+ ).map((memberId) => ({ projectId, workLineId, memberId }))
15704
+ ];
15705
+ for (const target of targets)
15706
+ await ctx.work.lines.pause({
15707
+ ...target,
15708
+ requestId: `team-pause-backfill:${stableHash(JSON.stringify([target.workLineId, target.memberId ?? null, line.version]))}`
15709
+ });
15710
+ } catch (error) {
15711
+ ctx.log.warn("team pause could not be recorded on the work line", {
15712
+ projectId,
15713
+ workLineId,
15714
+ error
15715
+ });
15716
+ }
15717
+ }
15718
+ async function backfillLegacyPauses(ctx, wakes) {
15719
+ const state = await wakes.get();
15720
+ for (const [projectId, project2] of Object.entries(state)) {
15721
+ const lineIds = /* @__PURE__ */ new Set([
15722
+ ...Object.keys(project2.linePauses ?? {}),
15723
+ ...Object.keys(project2.pausedMembers ?? {})
15724
+ ]);
15725
+ for (const workLineId of lineIds) await backfillLine(ctx, wakes, projectId, workLineId);
15726
+ }
15727
+ }
15728
+ async function releaseLegacyLeftover(ctx, wakes, target, requestId) {
15729
+ const { line, snapshotSequence } = await ctx.work.lines.get({
15730
+ projectId: target.projectId,
15731
+ workLineId: target.workLineId
15732
+ });
15733
+ const engineHolds = target.memberId === void 0 ? line.pause !== void 0 : (line.memberPauses ?? []).some((pause) => pause.memberId === target.memberId);
15734
+ if (engineHolds) return;
15735
+ const caught = readFact(await wakes.get({ throughSequence: snapshotSequence }), target.projectId);
15736
+ if (caught === null) return;
15737
+ if (legacyPauseId(caught, target.workLineId, target.memberId) === void 0) return;
15738
+ const name = target.memberId === void 0 ? "line-paused" : "line-member-paused";
15739
+ const receipt = await ctx.events.append({
15740
+ commandId: `team-${name}:${stableHash(JSON.stringify([target, requestId]))}`,
15741
+ name,
15742
+ aggregate: { kind: "project", id: target.projectId },
15743
+ data: {
15744
+ version: 1,
15745
+ status: "resumed",
15746
+ projectId: target.projectId,
15747
+ workLineId: target.workLineId,
15748
+ ...target.memberId === void 0 ? {} : { memberId: target.memberId }
15749
+ }
15982
15750
  });
15751
+ await wakes.get({ throughSequence: receipt.sequence });
15983
15752
  }
15984
15753
 
15985
15754
  // src/team/waiting.ts
@@ -16232,11 +16001,11 @@ var zh_CN_default = {
16232
16001
  handbook: {
16233
16002
  requestConflict: "\u8FD9\u4E2A requestId \u5DF2\u7528\u4E8E\u53E6\u4E00\u4EFD\u624B\u518C\u8BF7\u6C42\uFF0C\u8BF7\u6362\u4E00\u4E2A\u65B0\u7684 requestId\u3002",
16234
16003
  requestVoided: "\u8FD9\u4E2A requestId \u5728\u624B\u518C\u6536\u5230\u4E4B\u524D\u5C31\u4F5C\u5E9F\u4E86\uFF0C\u8BF7\u6362\u4E00\u4E2A\u65B0\u7684 requestId\u3002",
16235
- ackTool: "\u4EE5\u4F60\u5728\u5F53\u524D\u76EE\u6807\u4E2D\u7684\u6210\u5458\u5E2D\u4F4D\u786E\u8BA4\u5F53\u524D\u8981\u6C42\u786E\u8BA4\u7684\u624B\u518C\u7248\u672C\u3002\u53EA\u8BFB\u4E0D\u7B97\u786E\u8BA4\u3002\u6CA1\u6709\u76EE\u6807\u65F6\u6CA1\u6709\u56E2\u961F\u6210\u5458\uFF0C\u786E\u8BA4\u95E8\u69DB\u4E0E\u63D0\u9192\u5747\u4E0D\u4F5C\u7528\u3002",
16004
+ ackTool: "\u4EE5\u4F60\u5728\u5F53\u524D\u76EE\u6807\u4E2D\u7684\u6210\u5458\u8EAB\u4EFD\u786E\u8BA4\u5F53\u524D\u8981\u6C42\u786E\u8BA4\u7684\u624B\u518C\u7248\u672C\u3002\u53EA\u8BFB\u4E0D\u7B97\u786E\u8BA4\u3002\u6CA1\u6709\u76EE\u6807\u65F6\u6CA1\u6709\u56E2\u961F\u6210\u5458\uFF0C\u786E\u8BA4\u95E8\u69DB\u4E0E\u63D0\u9192\u5747\u4E0D\u4F5C\u7528\u3002",
16236
16005
  publishTool: "\u7531\u672C\u673A\u56E2\u961F\u8D1F\u8D23\u4EBA\u53D1\u5E03\u624B\u518C\u9875\u3002\u540C\u4E00 requestId \u53EA\u80FD\u91CD\u8BD5\u540C\u4E00\u8BF7\u6C42\u3002\u89C4\u77E9\u53D8\u5316\u5FC5\u987B\u786E\u8BA4\uFF1B\u5B9A\u8FC7\u4EC0\u4E48\u53D8\u5316\u65F6\u7528 requireAck \u9009\u62E9\uFF0C\u9ED8\u8BA4 false\u3002",
16237
16006
  revertTool: "\u7531\u672C\u673A\u56E2\u961F\u8D1F\u8D23\u4EBA\u6062\u590D\u6307\u5B9A\u624B\u518C\u7248\u672C\u3002\u540C\u4E00 requestId \u53EA\u80FD\u91CD\u8BD5\u540C\u4E00\u8BF7\u6C42\u3002\u89C4\u77E9\u53D8\u5316\u5FC5\u987B\u786E\u8BA4\uFF1B\u5B9A\u8FC7\u4EC0\u4E48\u53D8\u5316\u65F6\u7528 requireAck \u9009\u62E9\uFF0C\u9ED8\u8BA4 false\u3002",
16238
16007
  unknownMember: "\u5BBF\u4E3B\u6838\u5B9E\u7684\u8C03\u7528\u8005\u8EAB\u4EFD\u672A\u6620\u5C04\u5230\u672C\u9879\u76EE\u5F53\u524D\u76EE\u6807\u7684\u6210\u5458\u3002",
16239
- leadOnly: "\u53EA\u6709\u5F53\u524D\u76EE\u6807\u4E2D\u7684\u672C\u673A\u8D1F\u8D23\u4EBA\u5E2D\u4F4D\u53EF\u4EE5\u53D1\u5E03\u6216\u9000\u56DE\u624B\u518C\u3002",
16008
+ leadOnly: "\u53EA\u6709\u5F53\u524D\u76EE\u6807\u4E2D\u7684\u672C\u673A\u8D1F\u8D23\u4EBA\u53EF\u4EE5\u53D1\u5E03\u6216\u9000\u56DE\u624B\u518C\u3002",
16240
16009
  noGoal: "\u8BF7\u5148\u5F00\u59CB\u4E00\u4E2A\u76EE\u6807\uFF0C\u518D\u53D1\u5E03\u6216\u9000\u56DE\u624B\u518C\u3002\u6CA1\u6709\u76EE\u6807\u65F6\u6CA1\u6709\u56E2\u961F\u6210\u5458\uFF0C\u786E\u8BA4\u95E8\u69DB\u4E0E\u63D0\u9192\u5747\u4E0D\u4F5C\u7528\u3002",
16241
16010
  noRequirement: "\u76EE\u524D\u8FD8\u6CA1\u6709\u8981\u6C42\u786E\u8BA4\u7684\u624B\u518C\u7248\u672C\u3002",
16242
16011
  wrongRelease: "\u8BF7\u786E\u8BA4\u624B\u518C\u7B2C {{release}} \u7248\uFF0C\u8FD9\u662F\u5F53\u524D\u8981\u6C42\u786E\u8BA4\u7684\u7248\u672C\u3002",
@@ -16250,9 +16019,9 @@ var zh_CN_default = {
16250
16019
  leadBrief: "\u5148\u7528 wiki_read_handbook \u8BFB\u624B\u518C\uFF0C\u518D\u7528 team_acknowledge_handbook \u660E\u786E\u786E\u8BA4\u5F53\u524D\u8981\u6C42\u786E\u8BA4\u7684\u7248\u672C\uFF0C\u624D\u80FD\u9886\u65B0\u6D3B\u3002\u7528 team_publish_handbook \u6216 team_revert_handbook \u53D1\u5E03\u6216\u9000\u56DE\uFF1B\u53D1\u5E03\u8981\u6C42\u786E\u8BA4\u7684\u7248\u672C\u4E5F\u4F1A\u4E3A\u4F60\u8BB0\u4E0B\u786E\u8BA4\u3002"
16251
16020
  },
16252
16021
  team: {
16253
- openTool: "\u628A\u8FD9\u6761\u4F1A\u8BDD\u53D8\u6210\u4E00\u4E2A\u56E2\u961F\u3002\u53EA\u5728\u4EBA\u5DF2\u7ECF\u5728\u8FD9\u6761\u4F1A\u8BDD\u91CC\u540C\u610F\u4E86\u4F60\u63D0\u7684\u56E2\u961F\u65B9\u6848\u4E4B\u540E\u624D\u8C03\uFF1A\u8C01\u52A0\u5165\uFF08\u9879\u76EE\u91CC\u5DF2\u6709\u7684\u6210\u5458\uFF0C\u5305\u62EC\u7528 work_list_remote_agents \u770B\u5230\u7684\u522B\u7684\u673A\u5668\u4E0A\u7684 agent\uFF09\u3001\u56E2\u961F\u5F00\u597D\u4E4B\u540E\u8981\u65B0\u5EFA\u54EA\u4E9B\u6210\u5458\u3002\u8FD8\u4E0D\u5B58\u5728\u7684\u6210\u5458\u5728\u8FD9\u6B21\u8C03\u7528\u4E4B\u540E\u518D\u6765\uFF1A\u5148\u7528 team_create_member \u65B0\u5EFA\uFF0C\u518D\u7528 team_set_members \u62C9\u8FDB\u6765\u3002\u8FD9\u6761\u4F1A\u8BDD\u4ECE\u6B64\u662F\u56E2\u961F\u7684\u8D1F\u8D23\u4EBA\u548C\u7FA4\u804A\uFF0C\u5E76\u6539\u540D\u4E3A\u56E2\u961F\u540D\uFF1A\u4F60\u5217\u7684\u6210\u5458\u52A0\u8FDB\u6765\uFF0C\u6BCF\u4E2A\u672C\u673A agent \u6210\u5458\u5728\u4F60\u7684\u4F1A\u8BDD\u540D\u4E0B\u5F97\u5230\u81EA\u5DF1\u7684\u4F1A\u8BDD\u3002requestId \u8981\u7528\u65B0\u7684\uFF0C\u53EA\u6709\u91CD\u8BD5\u540C\u4E00\u6B21\u8C03\u7528\u65F6\u624D\u6CBF\u7528\u3002name \u662F\u56E2\u961F\u540D\uFF08\u6700\u591A 80 \u5B57\uFF09\uFF1Bgoal \u662F\u8C08\u59A5\u5185\u5BB9\u7684\u6458\u8981\uFF08\u6700\u591A 4000 \u5B57\uFF09\uFF1BmemberIds \u662F\u8981\u62C9\u8FDB\u6765\u7684\u9879\u76EE\u6210\u5458\u7684 memberId\uFF08\u4E0D\u542B\u4F60\u81EA\u5DF1\uFF0C\u4F60\u4F1A\u4F5C\u4E3A\u8D1F\u8D23\u4EBA\u52A0\u8FDB\u6765\uFF09\uFF1BleadName \u53EF\u9009\uFF0C\u662F\u4F60\u4F5C\u4E3A\u9879\u76EE\u6210\u5458\u7684\u540D\u5B57\uFF081-40 \u5B57\uFF09\u3002\u8FD4\u56DE\u56E2\u961F\u7684\u5DE5\u4F5C\u7EBF\u3001\u6210\u5458\u548C\u6BCF\u4E2A\u6210\u5458\u662F\u5426\u5C31\u7EEA\uFF0C\u4EE5\u53CA\u4F60\u7684\u5F00\u5DE5\u8BF4\u660E\u3002\u5DF2\u7ECF\u662F\u56E2\u961F\u3001\u6216\u5C5E\u4E8E\u67D0\u4E2A\u56E2\u961F\u7684\u4F1A\u8BDD\u4E0D\u80FD\u518D\u5F00\u56E2\u961F\u3002",
16022
+ openTool: "\u628A\u8FD9\u6761\u4F1A\u8BDD\u53D8\u6210\u4E00\u4E2A\u56E2\u961F\u3002\u53EA\u5728\u4EBA\u5DF2\u7ECF\u5728\u8FD9\u6761\u4F1A\u8BDD\u91CC\u540C\u610F\u4E86\u4F60\u63D0\u7684\u56E2\u961F\u65B9\u6848\u4E4B\u540E\u624D\u8C03\uFF1A\u8C01\u52A0\u5165\uFF08\u5DF2\u5728\u9879\u76EE\u91CC\u7684\u6210\u5458\uFF0C\u5305\u62EC\u52A0\u8FDB\u8FD9\u4E2A\u9879\u76EE\u7684\u5176\u4ED6\u673A\u5668\u4E0A\u7684 agent\uFF1Bwork_list_machines \u5217\u51FA\u8FD9\u4E9B\u673A\u5668\uFF09\u3001\u56E2\u961F\u5F00\u597D\u4E4B\u540E\u8981\u65B0\u5EFA\u54EA\u4E9B\u6210\u5458\u3002\u8FD8\u4E0D\u5B58\u5728\u7684\u6210\u5458\u5728\u8FD9\u6B21\u8C03\u7528\u4E4B\u540E\u518D\u6765\uFF1A\u5148\u7528 team_create_member \u65B0\u5EFA\uFF0C\u518D\u7528 team_set_members \u62C9\u8FDB\u6765\u3002\u8FD9\u6761\u4F1A\u8BDD\u4ECE\u6B64\u662F\u56E2\u961F\u7684\u8D1F\u8D23\u4EBA\u548C\u7FA4\u804A\uFF0C\u5E76\u6539\u540D\u4E3A\u56E2\u961F\u540D\uFF1A\u4F60\u5217\u7684\u6210\u5458\u52A0\u8FDB\u6765\uFF0C\u6BCF\u4E2A\u672C\u673A agent \u6210\u5458\u5728\u4F60\u7684\u4F1A\u8BDD\u540D\u4E0B\u5F97\u5230\u81EA\u5DF1\u7684\u4F1A\u8BDD\u3002requestId \u8981\u7528\u65B0\u7684\uFF0C\u53EA\u6709\u91CD\u8BD5\u540C\u4E00\u6B21\u8C03\u7528\u65F6\u624D\u6CBF\u7528\u3002name \u662F\u56E2\u961F\u540D\uFF08\u6700\u591A 80 \u5B57\uFF09\uFF1Bgoal \u662F\u8C08\u59A5\u5185\u5BB9\u7684\u6458\u8981\uFF08\u6700\u591A 4000 \u5B57\uFF09\uFF1BmemberIds \u662F\u8981\u62C9\u8FDB\u6765\u7684\u9879\u76EE\u6210\u5458\u7684 memberId\uFF08\u4E0D\u542B\u4F60\u81EA\u5DF1\uFF0C\u4F60\u4F1A\u4F5C\u4E3A\u8D1F\u8D23\u4EBA\u52A0\u8FDB\u6765\uFF09\uFF1BleadName \u53EF\u9009\uFF0C\u662F\u4F60\u4F5C\u4E3A\u9879\u76EE\u6210\u5458\u7684\u540D\u5B57\uFF081-40 \u5B57\uFF09\u3002\u8FD4\u56DE\u56E2\u961F\u7684\u5DE5\u4F5C\u7EBF\u3001\u6210\u5458\u548C\u6BCF\u4E2A\u6210\u5458\u662F\u5426\u5C31\u7EEA\uFF0C\u4EE5\u53CA\u4F60\u7684\u5F00\u5DE5\u8BF4\u660E\u3002\u5DF2\u7ECF\u662F\u56E2\u961F\u3001\u6216\u5C5E\u4E8E\u67D0\u4E2A\u56E2\u961F\u7684\u4F1A\u8BDD\u4E0D\u80FD\u518D\u5F00\u56E2\u961F\u3002",
16254
16023
  setMembersTool: "\u6539\u8FD9\u4E2A\u56E2\u961F\u91CC\u6709\u8C01\uFF08\u53EA\u6709\u56E2\u961F\u7684\u8D1F\u8D23\u4EBA\u4F1A\u8BDD\u80FD\u8C03\uFF09\u3002add\uFF1A\u8981\u62C9\u8FDB\u6765\u7684\u9879\u76EE\u6210\u5458\u7684 memberId\uFF1Bremove\uFF1A\u8981\u79FB\u51FA\u7684 memberId\u3002\u79FB\u51FA\u7684\u6210\u5458\u540D\u4E0B\u8FD8\u6CA1\u5230\u5B83\u624B\u4E0A\u7684\u6D3B\u4F1A\u6536\u56DE\u5E76\u4EA4\u7ED9\u4F60\uFF0C\u5DF2\u7ECF\u5728\u5B83\u624B\u4E0A\u7684\u6D3B\u7559\u7ED9\u5B83\uFF0C\u7531\u4F60\u51B3\u5B9A\u3002\u4F60\u4E0D\u80FD\u79FB\u51FA\u81EA\u5DF1\uFF0C\u4E5F\u4E0D\u80FD\u52A8\u522B\u7684\u56E2\u961F\u7684\u6210\u5458\u548C\u8D1F\u8D23\u4EBA\u3002requestId \u8981\u7528\u65B0\u7684\uFF0C\u53EA\u6709\u91CD\u8BD5\u540C\u4E00\u6B21\u8C03\u7528\u65F6\u624D\u6CBF\u7528\u3002",
16255
- rosterOverviewTool: "\u8BFB\u51FA\u89C4\u5212\u56E2\u961F\u9700\u8981\u7684\u5168\u90E8\u4FE1\u606F\uFF1A\u8FD9\u4E2A\u9879\u76EE\u7684\u6BCF\u4E2A\u6210\u5458\uFF0C\u542B\u79CD\u7C7B\u3001\u673A\u5668\u3001\u6A21\u578B\u3001\u8BD5\u8DD1\u8FDB\u5EA6\uFF08trial \u53D6\u503C\uFF1Anone \u8868\u793A\u4E0D\u9002\u7528\uFF0C\u6BD4\u5982\u4EBA\uFF1Bunverified \u662F\u522B\u7684\u673A\u5668\u4E0A\u7684 agent\uFF0C\u4ECE\u8FD9\u91CC\u6D4B\u4E0D\u5230\uFF1Bpending \u662F\u8FD8\u6CA1\u901A\u8FC7\uFF1Bready \u662F\u5DF2\u901A\u8FC7\u6216\u5DF2\u8DF3\u8FC7\uFF1Bfailed \u662F\u5931\u8D25\uFF1Binvoked \u662F\u8FD9\u6761\u4F1A\u8BDD\u672C\u8EAB\u5C31\u662F\u8D1F\u8D23\u4EBA\uFF0C\u65E0\u9700\u8BD5\u8DD1\uFF09\uFF0C\u4EE5\u53CA\u6240\u5728\u7684\u56E2\u961F\uFF08\u662F\u4E0D\u662F\u90A3\u4E2A\u56E2\u961F\u7684\u8D1F\u8D23\u4EBA\uFF09\u3002\u63D0\u56E2\u961F\u65B9\u6848\u4E4B\u524D\u3001\u65B0\u5EFA\u6210\u5458\u4E4B\u524D\u5148\u8BFB\u5B83\u3002",
16024
+ rosterOverviewTool: "\u8BFB\u51FA\u89C4\u5212\u56E2\u961F\u9700\u8981\u7684\u5168\u90E8\u4FE1\u606F\uFF1A\u8FD9\u4E2A\u9879\u76EE\u7684\u6BCF\u4E2A\u6210\u5458\uFF0C\u542B\u79CD\u7C7B\u3001\u673A\u5668\u3001\u6A21\u578B\u3001\u8BD5\u8DD1\u8FDB\u5EA6\uFF08trial \u53D6\u503C\uFF1Anone \u8868\u793A\u4E0D\u9002\u7528\uFF0C\u6BD4\u5982\u4EBA\uFF1Bunverified \u662F\u522B\u7684\u673A\u5668\u4E0A\u3001\u8FD9\u91CC\u8FD8\u6CA1\u6709\u8BD5\u8DD1\u8BB0\u5F55\u7684 agent\uFF1Bpending \u662F\u8FD8\u6CA1\u901A\u8FC7\uFF1Bready \u662F\u5DF2\u901A\u8FC7\u6216\u5DF2\u8DF3\u8FC7\uFF1Bfailed \u662F\u5931\u8D25\uFF1Binvoked \u662F\u8FD9\u6761\u4F1A\u8BDD\u672C\u8EAB\u5C31\u662F\u8D1F\u8D23\u4EBA\uFF0C\u65E0\u9700\u8BD5\u8DD1\uFF09\uFF0C\u4EE5\u53CA\u6240\u5728\u7684\u56E2\u961F\uFF08\u662F\u4E0D\u662F\u90A3\u4E2A\u56E2\u961F\u7684\u8D1F\u8D23\u4EBA\uFF09\u3002\u63D0\u56E2\u961F\u65B9\u6848\u4E4B\u524D\u3001\u65B0\u5EFA\u6210\u5458\u4E4B\u524D\u5148\u8BFB\u5B83\u3002",
16256
16025
  noProject: "\u8FD9\u6B21\u8C03\u7528\u4E0D\u5C5E\u4E8E\u4EFB\u4F55\u9879\u76EE\uFF0C\u6CA1\u6709\u53EF\u5F00\u6216\u53EF\u6539\u7684\u56E2\u961F\u3002",
16257
16026
  notLocal: "\u53EA\u6709\u8FD9\u53F0\u673A\u5668\u4E0A\u7684\u4F1A\u8BDD\u80FD\u5F00\u56E2\u961F\u3002",
16258
16027
  invalidInput: "\u8BF7\u68C0\u67E5\u53C2\u6570\uFF1ArequestId \u662F 1-64 \u4F4D\u5B57\u6BCD\u3001\u6570\u5B57\u3001\u4E0B\u5212\u7EBF\u6216\u8FDE\u5B57\u7B26\uFF1Bname 1-80 \u5B57\uFF1Bgoal 1-4000 \u5B57\uFF1BleadName \u82E5\u7ED9\u51FA\u4E3A 1-40 \u5B57\u3002",
@@ -16262,6 +16031,9 @@ var zh_CN_default = {
16262
16031
  memberNotFound: "\u8FD9\u4E2A\u9879\u76EE\u91CC\u6CA1\u6709\u6210\u5458 {{memberId}}\u3002\u7528 team_roster_overview \u5217\u51FA\u6210\u5458\u3002",
16263
16032
  memberRemoved: "\u6210\u5458 {{memberId}} \u5DF2\u4ECE\u9879\u76EE\u91CC\u79FB\u9664\u3002\u5148\u7528 team_restore_member \u628A\u5B83\u8BF7\u56DE\u6765\u3002",
16264
16033
  modelUnavailable: "\u7ED9\u6210\u5458 {{memberId}} \u9009\u7684\u6A21\u578B\u5728\u8FD9\u53F0\u673A\u5668\u4E0A\u7528\u4E0D\u4E86\u3002\u67E5 list_providers \u548C list_models\uFF0C\u518D\u7528 team_update_member \u6539\u3002",
16034
+ instanceNotFound: "\u7ED9\u6210\u5458 {{memberId}} \u9009\u7684 provider \u5B9E\u4F8B\u5728\u8FD9\u53F0\u673A\u5668\u4E0A\u4E0D\u5B58\u5728\u3002\u67E5 list_providers\uFF0C\u518D\u7528 team_update_member \u6539\u3002",
16035
+ instanceUnavailable: "\u7ED9\u6210\u5458 {{memberId}} \u9009\u7684 provider \u5B9E\u4F8B\u5DF2\u505C\u7528\u6216\u5728\u8FD9\u53F0\u673A\u5668\u4E0A\u8DD1\u4E0D\u4E86\u3002\u67E5 list_providers\uFF0C\u518D\u7528 team_update_member \u6539\u3002",
16036
+ modelNotInCatalog: "\u7ED9\u6210\u5458 {{memberId}} \u9009\u7684\u6A21\u578B\u4E0D\u5728\u8BE5 provider \u5B9E\u4F8B\u7684\u6A21\u578B\u6E05\u5355\u91CC\u3002\u67E5 list_models\uFF0C\u518D\u7528 team_update_member \u6539\u3002",
16265
16037
  noDefaultModel: "\u6210\u5458 {{memberId}} \u6CA1\u6709\u81EA\u5DF1\u7684\u6A21\u578B\uFF0C\u9879\u76EE\u4E5F\u6CA1\u6709\u9ED8\u8BA4\u6A21\u578B\u3002\u7528 team_update_member \u7ED9\u5B83\u4E00\u4E2A\u3002",
16266
16038
  duplicateTeamName: "\u8FD9\u4E2A\u9879\u76EE\u91CC\u5DF2\u7ECF\u6709\u540D\u4E3A {{name}} \u7684\u56E2\u961F\u3002\u6362\u4E2A\u540D\u5B57\uFF0C\u5E76\u7528\u65B0\u7684 requestId\u3002",
16267
16039
  leadOnly: "\u53EA\u6709\u56E2\u961F\u7684\u8D1F\u8D23\u4EBA\u4F1A\u8BDD\u80FD\u6539\u5B83\u7684\u6210\u5458\u3002",
@@ -16281,6 +16053,9 @@ var zh_CN_default = {
16281
16053
  requestVoided: "\u8FD9\u4E2A requestId \u5728\u6539\u52A8\u5230\u8FBE\u5F15\u64CE\u4E4B\u524D\u5C31\u4F5C\u5E9F\u4E86\u3002\u8BF7\u6362\u4E00\u4E2A\u65B0\u7684 requestId\u3002",
16282
16054
  invalidAgent: "instanceId \u548C model \u8981\u4E48\u90FD\u7ED9\uFF0C\u8981\u4E48\u90FD\u4E0D\u7ED9\u3002",
16283
16055
  modelUnavailable: "\u8FD9\u53F0\u673A\u5668\u4E0A\u6CA1\u6709\u8FD9\u4E2A provider \u5B9E\u4F8B\u6216\u6A21\u578B\u3002\u5148\u770B list_providers \u548C list_models\uFF0C\u518D\u91CD\u8BD5\u3002",
16056
+ instanceNotFound: "\u8FD9\u53F0\u673A\u5668\u4E0A\u6CA1\u6709\u8FD9\u4E2A provider \u5B9E\u4F8B\u3002\u5148\u770B list_providers\uFF0C\u518D\u91CD\u8BD5\u3002",
16057
+ instanceUnavailable: "\u8FD9\u4E2A provider \u5B9E\u4F8B\u5DF2\u505C\u7528\u6216\u5728\u8FD9\u53F0\u673A\u5668\u4E0A\u8DD1\u4E0D\u4E86\u3002\u5148\u770B list_providers\uFF0C\u518D\u91CD\u8BD5\u3002",
16058
+ modelNotInCatalog: "\u8FD9\u4E2A\u6A21\u578B\u4E0D\u5728\u8BE5 provider \u5B9E\u4F8B\u7684\u6A21\u578B\u6E05\u5355\u91CC\u3002\u5148\u770B list_models\uFF0C\u518D\u91CD\u8BD5\u3002",
16284
16059
  noDefaultModel: "\u9879\u76EE\u6CA1\u6709\u8BBE\u9ED8\u8BA4\u6A21\u578B\uFF0C\u8BF7\u7ED9\u51FA instanceId \u548C model\u3002",
16285
16060
  memberInOtherTeam: "\u8FD9\u4E2A\u6210\u5458\u5DF2\u5728\u522B\u7684\u56E2\u961F\u91CC\u3002\u4F60\u53EA\u80FD\u4FEE\u6539\u6216\u79FB\u9664\u4E0D\u5728\u4EFB\u4F55\u56E2\u961F\u3001\u6216\u53EA\u5728\u4F60\u8FD9\u4E2A\u56E2\u961F\u91CC\u7684\u6210\u5458\u3002\u7528 team_roster_overview \u770B\u6BCF\u4E2A\u6210\u5458\u5728\u54EA\u4E2A\u56E2\u961F\u3002",
16286
16061
  notAgentMember: "\u8FD9\u4E2A\u5DE5\u5177\u53EA\u80FD\u6539 agent \u6210\u5458\u3002",
@@ -16289,100 +16064,13 @@ var zh_CN_default = {
16289
16064
  cannotReplaceLead: "\u4E0D\u80FD\u6539\u81EA\u5DF1\u7684 provider \u548C\u6A21\u578B\u3002"
16290
16065
  },
16291
16066
  board: {
16292
- title: "\u9879\u76EE\u770B\u677F",
16293
- newItem: "\u65B0\u5EFA\u5DE5\u4F5C\u9879",
16294
- itemTitle: "\u6807\u9898",
16295
- description: "\u8BF4\u660E\uFF08\u53EF\u9009\uFF09",
16296
- assignee: "\u6307\u6D3E\u7ED9\uFF08\u53EF\u9009\uFF09",
16297
- create: "\u521B\u5EFA\u5DE5\u4F5C\u9879",
16298
- retryCreate: "\u91CD\u8BD5\u521B\u5EFA",
16299
- saving: "\u4FDD\u5B58\u4E2D\u2026",
16300
- moveTo: "\u79FB\u5230\u2026",
16301
- goalItem: "\u76EE\u6807",
16302
- moveItem: "\u79FB\u52A8\u5DE5\u4F5C\u9879 #{{number}}",
16303
- moveItemTo: "\u5C06\u5DE5\u4F5C\u9879 #{{number}} \u79FB\u5230 {{state}}",
16304
- assignTo: "\u6307\u6D3E\u7ED9\u2026",
16305
- assignItem: "\u6307\u6D3E\u5DE5\u4F5C\u9879 #{{number}}",
16306
- assignItemTo: "\u5C06\u5DE5\u4F5C\u9879 #{{number}} \u6307\u6D3E\u7ED9 {{name}}",
16307
- unassign: "\u53D6\u6D88\u6307\u6D3E",
16308
- unassignItem: "\u53D6\u6D88\u5DE5\u4F5C\u9879 #{{number}} \u7684\u6307\u6D3E",
16309
- dragItem: "\u5C06\u5DE5\u4F5C\u9879 #{{number}} \u62D6\u5230\u5176\u4ED6\u72B6\u6001",
16310
- untitled: "\uFF08\u65E0\u6807\u9898\uFF09",
16067
+ openTeam: "\u5728\u770B\u677F\u4E0A\u6253\u5F00\u8FD9\u4E2A\u56E2\u961F",
16068
+ openProject: "\u6253\u5F00\u770B\u677F",
16311
16069
  other: "\u5176\u4ED6",
16312
- unassigned: "\u672A\u6307\u6D3E",
16313
- sessionRunning: "\u4F1A\u8BDD\u5728\u8DD1",
16314
- sessionFailed: "\u51FA\u9519",
16315
- sessionWaiting: "\u7B49\u4EBA\u5904\u7406",
16316
- sessionStopped: "\u505C\u7740",
16317
- sessionStoppedAt: "\u505C\u4E8E {{time}}",
16318
- queued: "\u6392\u7740",
16319
- dateLocale: "zh-CN",
16320
- queuedTitle: "\u5DF2\u6D3E\u3001\u8FD8\u6CA1\u53EB\u9192\uFF1A\u7B49\u5BF9\u65B9\u624B\u4E0A\u90A3\u4EF6\u505A\u5B8C\u518D\u53EB",
16321
- blockedBy: "\u88AB {{count}} \u4EF6\u6321\u7740",
16322
- noMembers: "\u8FD8\u6CA1\u6709\u53EF\u4EE5\u6307\u6D3E\u7684\u6210\u5458\uFF0C\u8BF7\u5148\u5728\u300C\u6210\u5458\u300D\u91CC\u6DFB\u52A0\u3002",
16323
- membersUnavailable: "\u672A\u80FD\u8BFB\u53D6\u6210\u5458\uFF0C\u6682\u65F6\u4E0D\u80FD\u6307\u6D3E\u3002\u8BF7\u91CD\u65B0\u8F7D\u5165\u770B\u677F\u3002",
16324
- loading: "\u6B63\u5728\u8F7D\u5165\u770B\u677F\u2026",
16325
- loadFailed: "\u672A\u80FD\u8F7D\u5165\u770B\u677F\uFF0C\u8BF7\u91CD\u65B0\u8F7D\u5165\u3002",
16326
- watchFailed: "\u770B\u677F\u5B9E\u65F6\u66F4\u65B0\u6682\u4E0D\u53EF\u7528\uFF0C\u8BF7\u91CD\u65B0\u8F7D\u5165\u4EE5\u6062\u590D\u8BA2\u9605\u3002",
16327
- createFailed: "\u672A\u80FD\u521B\u5EFA\u5DE5\u4F5C\u9879\uFF0C\u8BF7\u7528\u540C\u4E00\u4E2A\u8BF7\u6C42\u91CD\u8BD5\u3002",
16328
- updateFailed: "\u672A\u80FD\u4FEE\u6539\u5DE5\u4F5C\u9879\uFF0C\u6B63\u5728\u91CD\u65B0\u8BFB\u53D6\u770B\u677F\u3002",
16329
- staleVersion: "\u5DE5\u4F5C\u9879\u5DF2\u88AB\u522B\u5904\u6539\u8FC7\uFF0C\u672C\u6B21\u4FEE\u6539\u5DF2\u9000\u56DE\uFF0C\u6B63\u5728\u91CD\u65B0\u8F7D\u5165\u770B\u677F\u3002",
16330
- memberUnavailable: "\u8FD9\u4E2A\u6210\u5458\u5DF2\u88AB\u79FB\u9664\u6216\u5DF2\u4E0D\u5B58\u5728\uFF0C\u6CA1\u6709\u6307\u6D3E\u6210\u529F\u3002\u8BF7\u9009\u62E9\u5176\u4ED6\u6210\u5458\u3002",
16331
- invalidTitle: "\u8BF7\u586B\u5199\u5DE5\u4F5C\u9879\u6807\u9898\u3002",
16332
- reload: "\u91CD\u65B0\u8F7D\u5165\u770B\u677F",
16333
- truncated: "\u5F53\u524D\u53EA\u663E\u793A\u8FD9\u4E2A\u9879\u76EE\u7684\u524D 500 \u4EF6\u5DE5\u4F5C\u9879\u3002",
16334
- teamTitle: "\u56E2\u961F\u770B\u677F",
16335
- lane: {
16336
- unlined: "\u6CA1\u5206\u7EBF",
16337
- archived: "\u5DF2\u5F52\u6863",
16338
- openTeam: "\u6253\u5F00\u56E2\u961F",
16339
- openTeamFor: "\u6253\u5F00\u56E2\u961F\u300C{{name}}\u300D"
16340
- },
16341
- noTeamHint: "\u8981\u5F00\u56E2\u961F\uFF0C\u5148\u5728\u4F1A\u8BDD\u91CC\u8C08\u59A5\uFF0C\u518D\u7531 agent \u5728\u4F1A\u8BDD\u91CC\u5F00\u56E2\u961F\u3002"
16070
+ untitled: "\uFF08\u65E0\u6807\u9898\uFF09"
16342
16071
  },
16343
16072
  detail: {
16344
- title: "\u5DE5\u4F5C\u9879\u8BE6\u60C5",
16345
16073
  open: "\u8BE6\u60C5",
16346
- openItem: "\u6253\u5F00\u5DE5\u4F5C\u9879 #{{number}} \u7684\u8BE6\u60C5",
16347
- close: "\u5173\u95ED",
16348
- via: "\u7ECF{{source}}",
16349
- description: "\u8BF4\u660E",
16350
- noDescription: "\uFF08\u6CA1\u6709\u8BF4\u660E\uFF09",
16351
- blockedBy: "\u88AB\u8FD9\u4E9B\u6321\u7740",
16352
- blocking: "\u6321\u7740\u8FD9\u4E9B",
16353
- dependency: "#{{number}} {{title}}\uFF0C{{state}}",
16354
- comments: "\u8BC4\u8BBA",
16355
- noComments: "\u8FD8\u6CA1\u6709\u8BC4\u8BBA",
16356
- deletedComment: "\uFF08\u8FD9\u6761\u8BC4\u8BBA\u5DF2\u5220\u9664\uFF09",
16357
- commentsTruncated: "\u53EA\u663E\u793A\u6700\u8FD1 200 \u6761\u8BC4\u8BBA\uFF08\u542B\u56DE\u590D\uFF09\u3002",
16358
- reply: "\u56DE\u590D",
16359
- replyTo: "\u56DE\u590D\u7B2C {{number}} \u6761\u8BC4\u8BBA",
16360
- newComment: "\u53D1\u8868\u8BC4\u8BBA",
16361
- commentHint: "\u8981\u53EB\u9192\u6210\u5458\uFF0C\u7528\u300C\u63D0\u53CA\u2026\u300D\u9009\u62E9\u5B83\uFF08\u6216\u8F93\u5165 @\uFF09\uFF0C\u6216\u5728\u5B83\u7684\u8BC4\u8BBA\u4E0B\u70B9\u300C\u56DE\u590D\u300D\uFF1B\u5728\u6307\u6D3E\u7ED9\u8FDC\u7AEF\u6210\u5458\u3001\u8FD8\u6CA1\u7ED3\u675F\u7684\u5DE5\u4F5C\u9879\u4E0A\u8BC4\u8BBA\u4E5F\u4F1A\u53EB\u9192\u5B83\u3002",
16362
- mention: "\u63D0\u53CA\u2026",
16363
- mentionLabel: "\u63D0\u53CA\u6210\u5458\uFF08{{comment}}\uFF09",
16364
- mentionMember: "\u63D0\u53CA {{name}}\uFF08{{comment}}\uFF09",
16365
- mentionMemberSelected: "{{name}}\uFF08\u5DF2\u63D0\u53CA\uFF09\uFF08{{comment}}\uFF09",
16366
- mentionSelected: "{{name}}\uFF08\u5DF2\u63D0\u53CA\uFF09",
16367
- mentionRemove: "\u79FB\u9664\u5BF9 {{name}} \u7684\u63D0\u53CA\uFF08{{comment}}\uFF09",
16368
- mentionNone: "\u5148\u5F00\u59CB\u4E00\u4E2A\u76EE\u6807\uFF0C\u624D\u80FD\u63D0\u53CA\u6210\u5458\u3002",
16369
- mentionNoneLabel: "\u5148\u5F00\u59CB\u4E00\u4E2A\u76EE\u6807\uFF0C\u624D\u80FD\u63D0\u53CA\u6210\u5458\uFF08{{comment}}\uFF09",
16370
- mentioned: "\u63D0\u53CA\uFF1A{{names}}",
16371
- mentionSeparator: "\u3001",
16372
- notAMember: "\u88AB\u63D0\u53CA\u7684\u6210\u5458\u91CC\u6709\u4EBA\u4E0D\u5728\u5F53\u524D\u76EE\u6807\u4E2D\uFF0C\u8BF7\u79FB\u9664\u540E\u91CD\u8BD5\u3002",
16373
- send: "\u53D1\u9001",
16374
- sendComment: "\u53D1\u9001\u8BC4\u8BBA",
16375
- sendReply: "\u53D1\u9001\u7B2C {{number}} \u6761\u8BC4\u8BBA\u7684\u56DE\u590D",
16376
- sending: "\u53D1\u9001\u4E2D\u2026",
16377
- retry: "\u91CD\u8BD5",
16378
- retryComment: "\u91CD\u8BD5\u8BC4\u8BBA",
16379
- retryReply: "\u91CD\u8BD5\u7B2C {{number}} \u6761\u8BC4\u8BBA\u7684\u56DE\u590D",
16380
- invalidBody: "\u8BC4\u8BBA\u53BB\u6389\u9996\u5C3E\u7A7A\u767D\u540E\u9700\u4E3A 1 \u5230 8000 \u4E2A\u5B57\u7B26\u3002",
16381
- commentFailed: "\u8BC4\u8BBA\u6CA1\u53D1\u51FA\u53BB\uFF0C\u53EF\u4EE5\u91CD\u8BD5\u3002",
16382
- loading: "\u6B63\u5728\u8F7D\u5165\u5DE5\u4F5C\u9879\u8BE6\u60C5\u2026",
16383
- loadFailed: "\u672A\u80FD\u8F7D\u5165\u5DE5\u4F5C\u9879\u8BE6\u60C5\uFF0C\u8BF7\u91CD\u65B0\u8F7D\u5165\u3002",
16384
- reload: "\u91CD\u65B0\u8F7D\u5165\u8BE6\u60C5",
16385
- notFound: "\u8FD9\u4E2A\u9879\u76EE\u4E2D\u627E\u4E0D\u5230\u8FD9\u4EF6\u5DE5\u4F5C\u9879\u3002",
16386
16074
  actor: {
16387
16075
  you: "\u4F60",
16388
16076
  human: "\u4EBA",
@@ -16391,24 +16079,7 @@ var zh_CN_default = {
16391
16079
  plugin: "\u63D2\u4EF6 {{pluginId}}",
16392
16080
  localCli: "\u672C\u673A\u547D\u4EE4\u884C",
16393
16081
  system: "\u7CFB\u7EDF",
16394
- remoteAgentFallback: "\u8FDC\u7AEF agent"
16395
- },
16396
- history: {
16397
- title: "\u6D3B\u52A8\u5386\u53F2",
16398
- empty: "\u8FD8\u6CA1\u6709\u6D3B\u52A8\u5386\u53F2",
16399
- truncated: "\u53EA\u663E\u793A\u6700\u8FD1 200 \u6761\u6D3B\u52A8\u3002",
16400
- deletedState: "\uFF08\u5DF2\u5220\u9664\u7684\u72B6\u6001\uFF09",
16401
- created: "{{author}} \u5EFA\u4E86\u8FD9\u4EF6\u6D3B",
16402
- createdAssigned: "{{author}} \u5EFA\u4E86\u8FD9\u4EF6\u6D3B\uFF0C\u6307\u6D3E\u7ED9 {{names}}",
16403
- stateChanged: "{{author}} \u628A\u72B6\u6001\u4ECE {{old}} \u6539\u6210 {{new}}",
16404
- assigned: "{{author}} \u6307\u6D3E\u7ED9 {{names}}",
16405
- unassigned: "{{author}} \u53D6\u6D88\u4E86\u6307\u6D3E",
16406
- titleChanged: "{{author}} \u6539\u4E86\u6807\u9898",
16407
- descriptionChanged: "{{author}} \u6539\u4E86\u8BF4\u660E",
16408
- claimed: "{{author}} \u9886\u4E86\u8FD9\u4EF6\u6D3B",
16409
- commented: "{{author}} \u53D1\u4E86\u4E00\u6761\u8BC4\u8BBA",
16410
- relationAdded: "{{author}} \u52A0\u4E86\u4E00\u6761\u4F9D\u8D56",
16411
- relationRemoved: "{{author}} \u53BB\u6389\u4E86\u4E00\u6761\u4F9D\u8D56"
16082
+ remoteAgentFallback: "\u53E6\u4E00\u53F0\u673A\u5668"
16412
16083
  }
16413
16084
  },
16414
16085
  goal: {
@@ -16416,7 +16087,7 @@ var zh_CN_default = {
16416
16087
  lead: "\u8D1F\u8D23\u4EBA\uFF1A{{name}}",
16417
16088
  unknownLead: "\u8FD9\u540D\u6210\u5458\u5DF2\u4E0D\u5728\u56E2\u961F\u91CC",
16418
16089
  openLead: "\u6253\u5F00\u8D1F\u8D23\u4EBA\u4F1A\u8BDD",
16419
- remoteMembers: "\u8FDC\u7AEF\u6210\u5458\uFF1A",
16090
+ remoteMembers: "\u522B\u7684\u673A\u5668\u4E0A\u7684\u6210\u5458\uFF1A",
16420
16091
  item: "\u76EE\u6807\u5DE5\u4F5C\u9879 #{{number}}\uFF1A{{state}}",
16421
16092
  openItem: "\u6253\u5F00\u76EE\u6807\u5DE5\u4F5C\u9879 #{{number}} \u7684\u8BE6\u60C5"
16422
16093
  },
@@ -16443,7 +16114,6 @@ var zh_CN_default = {
16443
16114
  makeLeadFor: "\u5C06 {{name}} \u8BBE\u4E3A\u8D1F\u8D23\u4EBA",
16444
16115
  person: "\u4EBA",
16445
16116
  agent: "agent",
16446
- remote: "\u8FDC\u7AEF agent",
16447
16117
  edit: "\u7F16\u8F91",
16448
16118
  editFor: "\u7F16\u8F91 {{name}}",
16449
16119
  remove: "\u79FB\u9664",
@@ -16461,8 +16131,7 @@ var zh_CN_default = {
16461
16131
  restoredNotice: "\u5DF2\u6062\u590D\u6210\u5458\u3002",
16462
16132
  leadChosen: "\u5DF2\u9009\u5B9A\u8D1F\u8D23\u4EBA\u3002",
16463
16133
  kind: "\u7C7B\u578B",
16464
- kindAgentHint: "\u673A\u5668\u9009\u8FD9\u4E00\u53F0\u65F6\uFF0C\u7528\u4F60\u9009\u7684 provider \u548C\u6A21\u578B\u8FD0\u884C\u3002\u9009\u4E86\u522B\u7684\u673A\u5668\u7684\u6210\u5458\u8BD5\u8DD1\u4F1A\u51FA\u9519\uFF1A\u6539\u56DE\u8FD9\u4E00\u53F0\uFF0C\u6216\u8005\u8DF3\u8FC7\u8BD5\u8DD1\uFF0C\u5B83\u5C31\u5728\u8FD9\u53F0\u673A\u5668\u4E0A\u7528\u9879\u76EE\u7684\u9ED8\u8BA4\u6A21\u578B\u8FD0\u884C\u3002",
16465
- kindRemoteHint: "\u4ECE\u53E6\u4E00\u53F0\u673A\u5668\u7528\u81EA\u5DF1\u7684\u51ED\u636E\u8FDE\u8FDB\u6765\u7684 agent\u3002",
16134
+ kindAgentHint: "\u5728\u4F60\u9009\u7684\u673A\u5668\u4E0A\uFF0C\u7528\u90A3\u53F0\u673A\u5668\u7684 provider \u548C\u6A21\u578B\u8FD0\u884C\u3002\u522B\u7684\u673A\u5668\u52A0\u8FDB\u8FD9\u4E2A\u9879\u76EE\u540E\u624D\u4F1A\u51FA\u73B0\u5728\u8FD9\u91CC\u3002",
16466
16135
  kindPersonHint: "\u4EBA\u4F1A\u5217\u5728\u6210\u5458\u91CC\uFF0C\u4F46\u4E0D\u4F1A\u8FD0\u884C\u4F1A\u8BDD\u3002",
16467
16136
  thisIsMe: "\u8FD9\u662F\u6211",
16468
16137
  thisIsMeHint: "\u6709\u4EBA\u5728\u56E2\u961F\u7FA4\u91CC @ \u8FD9\u4E2A\u6210\u5458\u65F6\uFF0C\u6D88\u606F\u4F1A\u8FDB\u4F60\u7684\u300C\u53D1\u7ED9\u6211\u7684\u300D\u3002",
@@ -16491,20 +16160,14 @@ var zh_CN_default = {
16491
16160
  providersFailed: "\u672A\u80FD\u8BFB\u53D6\u8FD9\u53F0\u673A\u5668\u4E0A\u7684 provider\u3002",
16492
16161
  noProviders: "\u8FD9\u53F0\u673A\u5668\u4E0A\u6CA1\u6709\u53EF\u7528\u7684 provider\u3002",
16493
16162
  modelsFailed: "\u672A\u80FD\u8BFB\u53D6\u8FD9\u4E2A provider \u7684\u6A21\u578B\u3002",
16494
- remoteAgent: "\u8FDC\u7AEF agent",
16495
- chooseRemote: "\u9009\u62E9\u8FDC\u7AEF agent",
16496
- remoteBound: "\u8FDC\u7AEF agent\uFF1A{{label}}",
16497
- noRemoteAgents: "\u8FD9\u53F0\u673A\u5668\u4E0A\u8FD8\u6CA1\u6709\u53EF\u7528\u7684\u8FDC\u7AEF agent\u3002",
16498
- allRemoteAgentsAdded: "\u53EF\u7528\u7684\u8FDC\u7AEF agent \u90FD\u5DF2\u662F\u6210\u5458\u3002",
16499
- remoteAgentsUnavailable: "\u6682\u65F6\u8BFB\u4E0D\u51FA\u8FD9\u53F0\u673A\u5668\u4E0A\u7684\u8FDC\u7AEF agent\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5\u3002",
16500
16163
  save: "\u4FDD\u5B58",
16501
16164
  saving: "\u4FDD\u5B58\u4E2D\u2026",
16502
16165
  adding: "\u6B63\u5728\u6DFB\u52A0\u2026",
16503
16166
  problem: {
16504
16167
  memberCount: "\u56E2\u961F\u81F3\u5C11\u9700\u8981\u4E00\u540D agent \u6210\u5458\u3002",
16505
16168
  leadNotMember: "\u8BF7\u4ECE agent \u6210\u5458\u91CC\u9009\u4E00\u540D\u8D1F\u8D23\u4EBA\u3002",
16506
- leadRemote: "\u8D1F\u8D23\u4EBA\u5FC5\u987B\u662F\u672C\u673A\u6210\u5458\u3002",
16507
- duplicatePrincipal: "\u540C\u4E00\u4E2A\u8FDC\u7AEF agent \u53EA\u80FD\u662F\u4E00\u540D\u6210\u5458\u3002"
16169
+ leadRemote: "\u8D1F\u8D23\u4EBA\u5FC5\u987B\u5728\u8FD9\u53F0\u673A\u5668\u4E0A\u8FD0\u884C\u3002",
16170
+ duplicatePrincipal: "\u540C\u4E00\u53F0\u673A\u5668\u5728\u8FD9\u4EFD\u56E2\u961F\u540D\u5355\u91CC\u53EA\u80FD\u51FA\u73B0\u4E00\u6B21\u3002"
16508
16171
  },
16509
16172
  errors: {
16510
16173
  generic: "\u672A\u80FD\u4FDD\u5B58\u6539\u52A8\uFF0C\u8BF7\u91CD\u8BD5\u3002",
@@ -16512,7 +16175,10 @@ var zh_CN_default = {
16512
16175
  invalidPayload: "\u8BF7\u68C0\u67E5\u6210\u5458\u5B57\u6BB5\u540E\u91CD\u8BD5\u3002",
16513
16176
  noDefaultModel: "\u8FD9\u4E2A\u9879\u76EE\u6CA1\u8BBE\u9ED8\u8BA4\u6A21\u578B\u3002\u5230\u9879\u76EE\u8BBE\u7F6E\u7684\u300C\u65B0\u4F1A\u8BDD \u2192 \u6A21\u578B\u300D\u9009\u4E00\u4E2A\uFF0C\u518D\u91CD\u8BD5\u3002",
16514
16177
  modelUnavailable: "\u8FD9\u4E2A\u9879\u76EE\u7684\u9ED8\u8BA4\u6A21\u578B\u5728\u8FD9\u53F0\u673A\u5668\u4E0A\u7528\u4E0D\u4E86\u3002\u68C0\u67E5\u4E00\u4E0B provider\uFF0C\u6216\u5230\u9879\u76EE\u8BBE\u7F6E\u7684\u300C\u65B0\u4F1A\u8BDD \u2192 \u6A21\u578B\u300D\u6362\u4E00\u4E2A\u3002",
16515
- duplicateMember: "\u5DF2\u6709\u6210\u5458\u7528\u4E86\u8FD9\u4E2A\u540D\u5B57\u6216\u8FD9\u4E2A\u8FDC\u7AEF agent\uFF0C\u8BF7\u5148\u6539\u540D\u6216\u79FB\u9664\u5B83\u3002",
16178
+ instanceNotFound: "\u8FD9\u4E2A\u9879\u76EE\u7684\u9ED8\u8BA4\u6A21\u578B\u6240\u5C5E\u7684 provider \u5B9E\u4F8B\u5728\u8FD9\u53F0\u673A\u5668\u4E0A\u4E0D\u5B58\u5728\u3002\u5230\u9879\u76EE\u8BBE\u7F6E\u7684\u300C\u65B0\u4F1A\u8BDD \u2192 \u6A21\u578B\u300D\u6362\u4E00\u4E2A\u3002",
16179
+ instanceUnavailable: "\u8FD9\u4E2A\u9879\u76EE\u9ED8\u8BA4\u6A21\u578B\u6240\u5C5E\u7684 provider \u5B9E\u4F8B\u5DF2\u505C\u7528\u6216\u5728\u8FD9\u53F0\u673A\u5668\u4E0A\u8DD1\u4E0D\u4E86\u3002\u68C0\u67E5\u4E00\u4E0B provider\uFF0C\u6216\u5230\u9879\u76EE\u8BBE\u7F6E\u7684\u300C\u65B0\u4F1A\u8BDD \u2192 \u6A21\u578B\u300D\u6362\u4E00\u4E2A\u3002",
16180
+ modelNotInCatalog: "\u8FD9\u4E2A\u9879\u76EE\u7684\u9ED8\u8BA4\u6A21\u578B\u4E0D\u5728\u5176 provider \u5B9E\u4F8B\u7684\u6A21\u578B\u6E05\u5355\u91CC\u3002\u5230\u9879\u76EE\u8BBE\u7F6E\u7684\u300C\u65B0\u4F1A\u8BDD \u2192 \u6A21\u578B\u300D\u6362\u4E00\u4E2A\u3002",
16181
+ duplicateMember: "\u5DF2\u6709\u6210\u5458\u7528\u4E86\u8FD9\u4E2A\u540D\u5B57\u6216\u7ED1\u7740\u8FD9\u4E2A\u4EBA\uFF0C\u8BF7\u5148\u6539\u540D\u6216\u79FB\u9664\u5B83\u3002",
16516
16182
  alreadyYou: "\u4F60\u5728\u540D\u518C\u4E0A\u5DF2\u7ECF\u662F\u300C{{name}}\u300D\u4E86\uFF0C\u8BF7\u5148\u5728\u300C{{name}}\u300D\u90A3\u91CC\u53D6\u6D88\u300C\u8FD9\u662F\u6211\u300D\u3002",
16517
16183
  staleVersion: "\u8FD9\u540D\u6210\u5458\u5DF2\u88AB\u522B\u5904\u6539\u8FC7\uFF0C\u5DF2\u91CD\u65B0\u8F7D\u5165\u3002\u8BF7\u786E\u8BA4\u540E\u518D\u4FDD\u5B58\u3002",
16518
16184
  notFound: "\u8FD9\u540D\u6210\u5458\u5DF2\u4E0D\u5B58\u5728\u3002",
@@ -16525,9 +16191,9 @@ var zh_CN_default = {
16525
16191
  importDuplicate: "\u5DF2\u6709\u540D\u4E3A {{name}} \u7684\u6210\u5458\uFF0C\u5BFC\u5165\u5DF2\u505C\u4E0B\u3002\u8BF7\u5148\u6539\u540D\u6216\u79FB\u9664\u5B83\uFF0C\u518D\u91CD\u65B0\u5BFC\u5165\u3002",
16526
16192
  importResume: "\u5DF2\u6DFB\u52A0\u7684\u6210\u5458\u4F1A\u4FDD\u7559\uFF0C\u518D\u6B21\u5BFC\u5165\u5373\u53EF\u7EE7\u7EED\u3002",
16527
16193
  nameRequired: "\u8BF7\u586B\u5199\u540D\u5B57\u3002",
16528
- remoteRequired: "\u8BF7\u9009\u62E9\u8FDC\u7AEF agent\u3002",
16529
16194
  modelRequired: "\u8BF7\u9009\u62E9 provider \u548C\u6A21\u578B\u3002",
16530
- instructionsTooLong: "\u5DE5\u4F5C\u8BF4\u660E\u592A\u957F\u4E86\u3002"
16195
+ instructionsTooLong: "\u5DE5\u4F5C\u8BF4\u660E\u592A\u957F\u4E86\u3002",
16196
+ machineMissing: "{{memberName}} \u539F\u6765\u6240\u5728\u7684\u673A\u5668\u8FD8\u6CA1\u52A0\u8FDB\u8FD9\u4E2A\u9879\u76EE\u3002\u5148\u628A\u90A3\u53F0\u673A\u5668\u52A0\u8FDB\u9879\u76EE\uFF0C\u518D\u5BFC\u5165\u3002"
16531
16197
  },
16532
16198
  legacy: {
16533
16199
  title: "\u8FD9\u4E2A\u9879\u76EE\u8FD8\u5728\u7528\u65E7\u540D\u5355",
@@ -16540,7 +16206,7 @@ var zh_CN_default = {
16540
16206
  trial: {
16541
16207
  passed: "\u8BD5\u8DD1\u901A\u8FC7",
16542
16208
  skipped: "\u5DF2\u8DF3\u8FC7\u8BD5\u8DD1",
16543
- remoteVerified: "\u8FDC\u7AEF\u8FDE\u901A\u5DF2\u9A8C\u8BC1",
16209
+ remoteVerified: "\u5DF2\u5728\u5B83\u7684\u673A\u5668\u4E0A\u9A8C\u8BC1",
16544
16210
  invoked: "\u8D1F\u8D23\u4EBA\u4F1A\u8BDD\uFF0C\u65E0\u9700\u8BD5\u8DD1",
16545
16211
  pending: "\u7B49\u5F85\u8BD5\u8DD1",
16546
16212
  running: "\u8BD5\u8DD1\u4E2D",
@@ -16548,7 +16214,7 @@ var zh_CN_default = {
16548
16214
  failed: "\u8BD5\u8DD1\u51FA\u9519",
16549
16215
  waiting: "\u7B49\u5BF9\u65B9\u53D6\u8D70\u3002",
16550
16216
  waitingSeen: "\u7B49\u5BF9\u65B9\u53D6\u8D70\uFF08\u6700\u540E\u8054\u7CFB {{time}}\uFF09\u3002",
16551
- remoteNote: "\u8FDC\u7AEF agent \u7528\u5B83\u5E2D\u4F4D\u81EA\u5DF1\u7684\u8BBE\u7F6E\u8FD0\u884C\uFF0C\u8FD9\u6B21\u8BD5\u8DD1\u53EA\u9A8C\u8BC1\u4E86\u8FDE\u901A\u548C\u5DE5\u5177\u8C03\u7528\u3002",
16217
+ remoteNote: "\u8BD5\u8DD1\u5728\u5B83\u81EA\u5DF1\u7684\u673A\u5668\u4E0A\u3001\u7528\u4E3A\u5B83\u9009\u7684\u6A21\u578B\u8FD0\u884C\uFF0C\u9A8C\u8BC1\u4E86\u8FDE\u901A\u3001\u5DE5\u5177\u8C03\u7528\u548C\u624B\u518C\u3002",
16552
16218
  failedDetail: "\u539F\u56E0\uFF1A{{category}}",
16553
16219
  failedWithText: "\u539F\u56E0\uFF1A{{category}}\uFF08{{detail}}\uFF09",
16554
16220
  failedSummary: "\u8BD5\u8DD1\u51FA\u9519\uFF1A{{count}}",
@@ -16570,15 +16236,18 @@ var zh_CN_default = {
16570
16236
  transport: "\u8FDE\u63A5\u65AD\u4E86",
16571
16237
  unknown: "\u672A\u5F52\u7C7B\u7684\u9519\u8BEF",
16572
16238
  timeout: "\u6CA1\u6709\u53CA\u65F6\u62A5\u56DE",
16573
- "no-route": "\u6CA1\u6709\u53EF\u7528\u7684\u673A\u5668\u6216\u8FDC\u7AEF\u51ED\u636E\uFF1B\u91CD\u65B0\u63A5\u5165\u8FD9\u4E2A\u8FDC\u7AEF agent\uFF0C\u6216\u4E3A\u6210\u5458\u9009\u4E00\u53F0\u673A\u5668\uFF0C\u7136\u540E\u91CD\u8BD5",
16574
- "other-machine": "\u5B83\u9009\u7684\u662F\u53E6\u4E00\u53F0\u673A\u5668\uFF0C\u8FD9\u53F0\u673A\u5668\u6CA1\u6CD5\u4E3A\u5B83\u8BD5\u8DD1\uFF1B\u6539\u56DE\u8FD9\u4E00\u53F0\uFF0C\u6216\u8005\u8DF3\u8FC7\u8BD5\u8DD1\uFF0C\u8BA9\u5B83\u5728\u8FD9\u53F0\u673A\u5668\u4E0A\u7528\u9879\u76EE\u7684\u9ED8\u8BA4\u6A21\u578B\u8FD0\u884C",
16239
+ "no-route": "\u5B83\u6240\u5728\u7684\u673A\u5668\u8FD8\u6CA1\u52A0\u8FDB\u8FD9\u4E2A\u9879\u76EE\uFF1B\u628A\u90A3\u53F0\u673A\u5668\u52A0\u8FDB\u9879\u76EE\uFF0C\u6216\u4E3A\u6210\u5458\u6362\u4E00\u53F0\u673A\u5668\uFF0C\u7136\u540E\u91CD\u8BD5",
16575
16240
  "start-failed": "\u8BD5\u8DD1\u6CA1\u80FD\u5F00\u59CB",
16576
16241
  "toolkit-off": "\u9879\u76EE\u7684\u770B\u677F\u548C\u9879\u76EE\u8BB0\u5FC6\u5F00\u5173\u6CA1\u6709\u540C\u65F6\u6253\u5F00\uFF0C\u6253\u5F00\u540E\u518D\u91CD\u8BD5"
16577
16242
  }
16578
16243
  },
16579
16244
  teams: "\u6240\u5C5E\u56E2\u961F\uFF1A{{names}}",
16580
16245
  remoteApprovals: "\u5BA1\u6279\u5728\u5BF9\u65B9\u673A\u5668\u5904\u7406",
16581
- teamsSeparator: "\u3001"
16246
+ teamsSeparator: "\u3001",
16247
+ thisMachine: "\u8FD9\u53F0\u673A\u5668",
16248
+ machineOffline: "{{name}}\uFF08\u79BB\u7EBF\uFF09",
16249
+ machineRemoved: "\u5DF2\u79FB\u51FA\u9879\u76EE\u7684\u673A\u5668",
16250
+ noMachine: "\u8FD8\u6CA1\u9009\u673A\u5668"
16582
16251
  },
16583
16252
  handbookPanel: {
16584
16253
  title: "\u624B\u518C",
@@ -16606,7 +16275,7 @@ var zh_CN_default = {
16606
16275
  restoredFrom: "\u9000\u56DE\u81EA\u7B2C {{version}} \u7248",
16607
16276
  moreReleases: "\u52A0\u8F7D\u66F4\u65E9\u7248\u672C",
16608
16277
  members: "\u6210\u5458\u786E\u8BA4\u60C5\u51B5",
16609
- noMembers: "\u8FD8\u6CA1\u6709\u6267\u884C\u6210\u5458\uFF0C\u4ECE\u4F1A\u8BDD\u5F00\u56E2\u961F\u540E\u624D\u6709\u56E2\u961F\u5E2D\u4F4D",
16278
+ noMembers: "\u8FD8\u6CA1\u6709\u6267\u884C\u6210\u5458\uFF0C\u4ECE\u4F1A\u8BDD\u5F00\u56E2\u961F\u540E\u624D\u6709\u56E2\u961F\u6210\u5458",
16610
16279
  member: "\u6210\u5458 {{id}}",
16611
16280
  neverAck: "\u8FD8\u6CA1\u6709\u786E\u8BA4\u8FC7\u624B\u518C",
16612
16281
  acked: "\u5DF2\u786E\u8BA4\u5230\u7B2C {{version}} \u7248",
@@ -16639,21 +16308,20 @@ var zh_CN_default = {
16639
16308
  discard: "\u653E\u5F03\u4FEE\u6539"
16640
16309
  },
16641
16310
  remoteStatus: {
16642
- title: "\u8FDC\u7AEF\u6210\u5458",
16311
+ title: "\u5728\u522B\u7684\u673A\u5668\u4E0A\u7684\u6210\u5458",
16643
16312
  lastSeen: "\u6700\u8FD1\u6765\u8FC7\uFF1A{{time}}",
16644
16313
  neverSeen: "\u8FD8\u6CA1\u6765\u8FC7",
16645
16314
  workUnavailable: "\u6682\u65F6\u8BFB\u4E0D\u51FA\u5B83\u624B\u4E0A\u7684\u6D3B\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5\u3002",
16646
16315
  noWork: "\u624B\u4E0A\u6CA1\u6709\u6D3B\u3002",
16647
16316
  item: "#{{number}} {{title}}",
16648
- disabled: "\u5DF2\u505C\u7528",
16649
- revoked: "\u6CA1\u6709\u53EF\u7528\u51ED\u636E",
16650
16317
  lastSeenUnavailable: "\u6682\u65F6\u8BFB\u4E0D\u51FA\u6700\u8FD1\u6765\u8FC7\u7684\u65F6\u95F4",
16651
16318
  blocked: "\u88AB\u6321\u7740",
16652
- more: "\u8FD8\u6709 {{count}} \u4EF6\u6CA1\u5728\u8FD9\u91CC\u5217\u51FA"
16319
+ more: "\u8FD8\u6709 {{count}} \u4EF6\u6CA1\u5728\u8FD9\u91CC\u5217\u51FA",
16320
+ machineMissing: "\u5B83\u6240\u5728\u7684\u673A\u5668\u8FD8\u6CA1\u52A0\u8FDB\u8FD9\u4E2A\u9879\u76EE"
16653
16321
  },
16654
16322
  trial: {
16655
16323
  localPrompt: '\u8FD9\u662F\u4F60\u4F5C\u4E3A\u8FD9\u4E2A\u9879\u76EE\u56E2\u961F\u6210\u5458\u7684\u8BD5\u8DD1\u3002\u5B83\u53EA\u68C0\u67E5\u4F60\u80FD\u4E0D\u80FD\u7528\u4E0A\u56E2\u961F\u7684\u5DE5\u5177\u3001\u8BFB\u5230\u56E2\u961F\u7684\u624B\u518C\uFF0C\u6240\u4EE5\u4E0D\u8981\u6539\u4EFB\u4F55\u6587\u4EF6\uFF0C\u4E5F\u4E0D\u8981\u5F00\u59CB\u522B\u7684\u5DE5\u4F5C\u3002\u7167\u4E0B\u9762\u505A\u5B8C\u5C31\u505C\u30021. \u4E0D\u5E26\u53C2\u6570\u8C03\u7528 wiki_read_handbook\u3002\u8FD4\u56DE\u91CC\u6709 head \u5C31\u8BB0\u4E0B head.current.release\uFF08\u4E00\u4E2A\u6570\u5B57\uFF09\uFF1Bhead \u662F null \u8BF4\u660E\u9879\u76EE\u8FD8\u6CA1\u6709\u624B\u518C\u30022. \u8C03\u7528 team_trial_done\uFF0CtrialId \u586B "{{trialId}}"\uFF1B\u8BFB\u5230\u4E86\u7248\u672C\u53F7\u5C31\u628A release \u8BBE\u6210\u8FD9\u4E2A\u6570\u5B57\uFF08head \u662F null \u65F6\u4E0D\u8981\u586B release\uFF09\u3002\u53EA\u62A5\u4F60\u771F\u8BFB\u5230\u7684\uFF1A\u6CA1\u8BFB\u8FC7\u7684\u7248\u672C\u53F7\u4F1A\u88AB\u62D2\u7EDD\u3002',
16656
- remotePrompt: '\u8FD9\u662F\u4F60\u4F5C\u4E3A\u8FD9\u4E2A\u9879\u76EE\u56E2\u961F\u6210\u5458\u7684\u8BD5\u8DD1\u3002\u5B83\u53EA\u68C0\u67E5\u4F60\u7684\u5E2D\u4F4D\u80FD\u4E0D\u80FD\u7528\u4E0A\u56E2\u961F\u7684\u5DE5\u5177\u3001\u8BFB\u5230\u56E2\u961F\u7684\u624B\u518C\uFF0C\u6240\u4EE5\u4E0D\u8981\u4E3A\u5B83\u5F00\u59CB\u4EFB\u4F55\u5DE5\u4F5C\u9879\u3002\u7167\u4E0B\u9762\u505A\u5B8C\u5C31\u505C\u30021. \u8C03\u7528 team_trial_started\uFF0CtrialId \u586B "{{trialId}}"\u30022. \u4E0D\u5E26\u53C2\u6570\u8C03\u7528 wiki_read_handbook\u3002\u8FD4\u56DE\u91CC\u6709 head \u5C31\u8BB0\u4E0B head.current.release\uFF08\u4E00\u4E2A\u6570\u5B57\uFF09\uFF1Bhead \u662F null \u8BF4\u660E\u9879\u76EE\u8FD8\u6CA1\u6709\u624B\u518C\u30023. \u8C03\u7528 team_trial_done\uFF0CtrialId \u586B "{{trialId}}"\uFF1B\u8BFB\u5230\u4E86\u7248\u672C\u53F7\u5C31\u628A release \u8BBE\u6210\u8FD9\u4E2A\u6570\u5B57\uFF08head \u662F null \u65F6\u4E0D\u8981\u586B release\uFF09\u3002\u53EA\u62A5\u4F60\u771F\u8BFB\u5230\u7684\uFF1A\u6CA1\u8BFB\u8FC7\u7684\u7248\u672C\u53F7\u4F1A\u88AB\u62D2\u7EDD\u3002',
16324
+ remotePrompt: '\u8FD9\u662F\u4F60\u4F5C\u4E3A\u8FD9\u4E2A\u9879\u76EE\u56E2\u961F\u6210\u5458\u7684\u8BD5\u8DD1\u3002\u5B83\u53EA\u68C0\u67E5\u4F60\u80FD\u4E0D\u80FD\u7528\u4E0A\u56E2\u961F\u7684\u5DE5\u5177\u3001\u8BFB\u5230\u56E2\u961F\u7684\u624B\u518C\uFF0C\u6240\u4EE5\u4E0D\u8981\u4E3A\u5B83\u5F00\u59CB\u4EFB\u4F55\u5DE5\u4F5C\u9879\u3002\u7167\u4E0B\u9762\u505A\u5B8C\u5C31\u505C\u30021. \u8C03\u7528 team_trial_started\uFF0CtrialId \u586B "{{trialId}}"\u30022. \u4E0D\u5E26\u53C2\u6570\u8C03\u7528 wiki_read_handbook\u3002\u8FD4\u56DE\u91CC\u6709 head \u5C31\u8BB0\u4E0B head.current.release\uFF08\u4E00\u4E2A\u6570\u5B57\uFF09\uFF1Bhead \u662F null \u8BF4\u660E\u9879\u76EE\u8FD8\u6CA1\u6709\u624B\u518C\u30023. \u8C03\u7528 team_trial_done\uFF0CtrialId \u586B "{{trialId}}"\uFF1B\u8BFB\u5230\u4E86\u7248\u672C\u53F7\u5C31\u628A release \u8BBE\u6210\u8FD9\u4E2A\u6570\u5B57\uFF08head \u662F null \u65F6\u4E0D\u8981\u586B release\uFF09\u3002\u53EA\u62A5\u4F60\u771F\u8BFB\u5230\u7684\uFF1A\u6CA1\u8BFB\u8FC7\u7684\u7248\u672C\u53F7\u4F1A\u88AB\u62D2\u7EDD\u3002',
16657
16325
  startedTool: "\u62A5\u544A\u4F60\u5DF2\u7ECF\u63A5\u4E0B\u4E00\u6B21\u8BD5\u8DD1\u3002trialId \u7528\u8BD5\u8DD1\u6D88\u606F\u91CC\u7ED9\u7684\u90A3\u4E2A\u3002\u8BD5\u8DD1\u53EA\u68C0\u67E5\u4F60\u80FD\u4E0D\u80FD\u7528\u4E0A\u56E2\u961F\u7684\u5DE5\u5177\u3001\u8BFB\u5230\u56E2\u961F\u7684\u624B\u518C\u3002",
16658
16326
  doneTool: "\u5B8C\u6210\u4E00\u6B21\u8BD5\u8DD1\uFF1A\u62A5\u56DE\u4F60\u7528 wiki_read_handbook \u8BFB\u5230\u7684\u624B\u518C\u7248\u672C\u53F7\uFF08\u9879\u76EE\u8FD8\u6CA1\u6709\u624B\u518C\u65F6\u4E0D\u586B release\uFF09\u3002trialId \u7528\u8BD5\u8DD1\u6D88\u606F\u91CC\u7ED9\u7684\u90A3\u4E2A\u3002\u5BBF\u4E3B\u4F1A\u6838\u5B9E\u8C01\u5728\u8C03\u7528\uFF1B\u5BF9\u5DF2\u88AB\u66FF\u6362\u3001\u5DF2\u7ED3\u675F\u6216\u4E0D\u662F\u53D1\u7ED9\u4F60\u7684\u8BD5\u8DD1\u7684\u62A5\u544A\u4F1A\u88AB\u62D2\u7EDD\u3002",
16659
16327
  retryTool: "\u4EE5\u5F53\u524D\u76EE\u6807\u8D1F\u8D23\u4EBA\u7684\u8EAB\u4EFD\uFF0C\u4E3A agent \u6210\u5458\u8981\u6C42\u518D\u8BD5\u8DD1\u4E00\u6B21\uFF0C\u4F8B\u5982\u4E0A\u4E00\u6B21\u8BD5\u8DD1\u5931\u8D25\u6216\u4E00\u76F4\u6CA1\u5B8C\u6210\u65F6\u3002\u5DF2\u7ECF\u5728\u6392\u961F\u6216\u6B63\u5728\u8DD1\u7684\u8BD5\u8DD1\u4E0D\u4F1A\u518D\u52A0\u4E00\u6B21\uFF0C\u4F1A\u5982\u5B9E\u544A\u8BC9\u4F60\u3002\u7528 team_update_member \u6539\u8FD9\u4E2A\u6210\u5458\u7684 provider \u6216\u6A21\u578B\uFF0C\u4E5F\u4F1A\u81EA\u52A8\u5F00\u59CB\u65B0\u7684\u8BD5\u8DD1\u3002",
@@ -16670,7 +16338,7 @@ var zh_CN_default = {
16670
16338
  retryReady: "\u8FD9\u4E2A\u6210\u5458\u5DF2\u5C31\u7EEA\uFF1A\u5B83\u7684\u8BD5\u8DD1\u901A\u8FC7\u4E86\uFF0C\u6216\u6709\u4EBA\u8DF3\u8FC7\u4E86\u5B83\uFF0C\u6240\u4EE5\u6CA1\u6709\u8981\u91CD\u8BD5\u7684\u3002\u7528 team_update_member \u6539\u5B83\u7684 provider \u6216\u6A21\u578B\uFF0C\u4F1A\u81EA\u52A8\u5F00\u59CB\u65B0\u7684\u8BD5\u8DD1\u3002",
16671
16339
  retryFutile: "\u8FD9\u91CC\u518D\u8BD5\u4E00\u6B21\u4E5F\u6CA1\u6709\u7528\uFF1A\u8FD9\u4E2A\u6210\u5458\u7684\u8BD5\u8DD1\u5728\u540C\u6837\u7684\u8BBE\u7F6E\u4E0B\u8FDE\u7740\u5931\u8D25\u4E86 {{limit}} \u6B21\uFF0C\u6216\u8005\u5931\u8D25\u7684\u539F\u56E0\u8981\u6539\u4E86\u4EC0\u4E48\u624D\u4F1A\u597D\u3002\u7528 team_update_member \u6539\u5B83\u7684 provider \u6216\u6A21\u578B\uFF0C\u6216\u8005\u7528 send_message \u5199\u7ED9\u4EBA\uFF0C\u8BF4\u660E\u51FA\u4E86\u4EC0\u4E48\u95EE\u9898\uFF0C\u8BF7\u4ED6\u4FEE\u597D\uFF0C\u6216\u8005\u5728\u56E2\u961F\u9875\u8DF3\u8FC7\u8FD9\u6B21\u8BD5\u8DD1\u3002",
16672
16340
  failedForLeadNoRetry: "{{name}}\uFF08memberId {{memberId}}\uFF09\u7684\u8BD5\u8DD1\u5931\u8D25\uFF1A{{reason}}\u3002\u8BD5\u8DD1\u901A\u8FC7\u4E4B\u524D\uFF0C{{name}} \u4E0D\u4F1A\u6536\u5230\u4EFB\u4F55\u6D3B\uFF0C\u800C\u4E14\u5728\u6709\u4E1C\u897F\u6539\u53D8\u4E4B\u524D\uFF0C\u518D\u8BD5\u4E00\u6B21\u4E5F\u4E0D\u4F1A\u597D\u3002\u4F60\u53EF\u4EE5\uFF1A\u7528 team_update_member \u6539\u5B83\u7684 provider \u6216\u6A21\u578B\uFF08\u4F1A\u81EA\u52A8\u5F00\u59CB\u65B0\u7684\u8BD5\u8DD1\uFF09\uFF1B\u6216\u8005\u7528 send_message \u5199\u7ED9\u4EBA\uFF0C\u8BF4\u660E\u51FA\u4E86\u4EC0\u4E48\u95EE\u9898\uFF0C\u8BF7\u4ED6\u4FEE\u597D\uFF0C\u6216\u8005\u5728\u56E2\u961F\u9875\u8DF3\u8FC7\u8FD9\u6B21\u8BD5\u8DD1\u3002",
16673
- waitingForLead: "{{name}}\uFF08memberId {{memberId}}\uFF09\u7684\u8BD5\u8DD1\u5DF2\u7ECF\u53D1\u51FA {{minutes}} \u5206\u949F\uFF0C\u8FDC\u7AEF agent \u8FD8\u6CA1\u6709\u53D6\u8D70\u3002{{name}} \u53EF\u80FD\u4E0D\u5728\u7EBF\u6216\u6CA1\u6709\u767B\u5F55\u3002\u5728\u5B83\u53D6\u8D70\u8BD5\u8DD1\u4E4B\u524D\uFF0C\u6D3E\u7ED9 {{name}} \u7684\u6D3B\u4E0D\u4F1A\u5F00\u59CB\u3002\u4F60\u53EF\u4EE5\uFF1A\u5148\u628A\u6D3B\u6D3E\u7ED9\u522B\u7684\u6210\u5458\uFF1B\u6216\u8005\u7528 send_message \u5199\u7ED9\u4EBA\uFF0C\u8BF7\u4ED6\u770B\u770B\u8FD9\u4E2A\u8FDC\u7AEF agent \u6709\u6CA1\u6709\u5728\u8FD0\u884C\uFF0C\u6216\u8005\u5728\u56E2\u961F\u9875\u8DF3\u8FC7\u8FD9\u6B21\u8BD5\u8DD1\u3002",
16341
+ waitingForLead: "{{name}}\uFF08memberId {{memberId}}\uFF09\u7684\u8BD5\u8DD1\u5DF2\u7ECF\u53D1\u51FA {{minutes}} \u5206\u949F\uFF0C\u5B83\u6240\u5728\u7684\u673A\u5668\u8FD8\u6CA1\u6709\u53D6\u8D70\u3002\u90A3\u53F0\u673A\u5668\u53EF\u80FD\u4E0D\u5728\u7EBF\uFF0C\u6216\u8005\u5B83\u7684 provider \u6CA1\u6709\u767B\u5F55\u3002\u5728\u8BD5\u8DD1\u88AB\u53D6\u8D70\u4E4B\u524D\uFF0C\u6D3E\u7ED9 {{name}} \u7684\u6D3B\u4E0D\u4F1A\u5F00\u59CB\u3002\u4F60\u53EF\u4EE5\uFF1A\u5148\u628A\u6D3B\u6D3E\u7ED9\u522B\u7684\u6210\u5458\uFF1B\u6216\u8005\u7528 send_message \u5199\u7ED9\u4EBA\uFF0C\u8BF7\u4ED6\u770B\u770B\u90A3\u53F0\u673A\u5668\uFF0C\u6216\u8005\u5728\u56E2\u961F\u9875\u8DF3\u8FC7\u8FD9\u6B21\u8BD5\u8DD1\u3002",
16674
16342
  failedHeadline: "\u8BD5\u8DD1\u51FA\u9519\uFF1A{{name}}\u3002",
16675
16343
  failedHeadlineAgain: "\u8BD5\u8DD1\u518D\u6B21\u51FA\u9519\uFF1A{{name}}\u3002",
16676
16344
  failedForPerson: "{{reason}}\u3002\u8BD5\u8DD1\u901A\u8FC7\u4E4B\u524D\uFF0C{{name}} \u4E0D\u4F1A\u6536\u5230\u4EFB\u4F55\u6D3B\u3002\u8BF7\u5148\u6392\u9664\u539F\u56E0\uFF0C\u7136\u540E\u5728\u56E2\u961F\u9875\u5BF9\u8FD9\u4E2A\u6210\u5458\u9009\u300C\u91CD\u65B0\u8BD5\u8DD1\u300D\uFF0C\u6216\u8005\u9009\u300C\u8DF3\u8FC7\u8BD5\u8DD1\u300D\u3002",
@@ -16684,8 +16352,7 @@ var zh_CN_default = {
16684
16352
  transport: "\u5230 provider \u7684\u8FDE\u63A5\u65AD\u4E86",
16685
16353
  unknown: "\u672A\u5F52\u7C7B\u7684\u9519\u8BEF",
16686
16354
  timeout: "\u6CA1\u6709\u53CA\u65F6\u62A5\u56DE",
16687
- "no-route": "\u6CA1\u6709\u53EF\u7528\u7684\u673A\u5668\u6216\u8FDC\u7AEF\u51ED\u636E\uFF08\u8981\u7531\u4EBA\u91CD\u65B0\u63A5\u5165\u8FD9\u4E2A\u8FDC\u7AEF agent\uFF0C\u6216\u4E3A\u6210\u5458\u9009\u4E00\u53F0\u673A\u5668\uFF09",
16688
- "other-machine": "\u5B83\u9009\u7684\u662F\u53E6\u4E00\u53F0\u673A\u5668\uFF0C\u8FD9\u53F0\u673A\u5668\u6CA1\u6CD5\u4E3A\u5B83\u8BD5\u8DD1\uFF08\u4EBA\u53EF\u4EE5\u628A\u5B83\u6539\u56DE\u8FD9\u4E00\u53F0\uFF0C\u6216\u8005\u8DF3\u8FC7\u8BD5\u8DD1\uFF0C\u8BA9\u5B83\u5728\u8FD9\u53F0\u673A\u5668\u4E0A\u7528\u9879\u76EE\u7684\u9ED8\u8BA4\u6A21\u578B\u8FD0\u884C\uFF09",
16355
+ "no-route": "\u5B83\u6240\u5728\u7684\u673A\u5668\u8FD8\u6CA1\u52A0\u8FDB\u8FD9\u4E2A\u9879\u76EE\uFF08\u8981\u7531\u4EBA\u628A\u90A3\u53F0\u673A\u5668\u52A0\u8FDB\u9879\u76EE\uFF0C\u6216\u4E3A\u6210\u5458\u6362\u4E00\u53F0\u673A\u5668\uFF09",
16689
16356
  "start-failed": "\u8BD5\u8DD1\u6CA1\u80FD\u5F00\u59CB",
16690
16357
  "toolkit-off": "\u9879\u76EE\u7684\u770B\u677F\u548C\u9879\u76EE\u8BB0\u5FC6\u5F00\u5173\u6CA1\u6709\u540C\u65F6\u6253\u5F00"
16691
16358
  },
@@ -16783,6 +16450,107 @@ function registerTrial(ctx, runtime) {
16783
16450
  });
16784
16451
  }
16785
16452
 
16453
+ // src/trial/mirror.ts
16454
+ var SUMMARY_MAX = 500;
16455
+ var MEMBER_LIMIT2 = 500;
16456
+ var RECONCILE_MS2 = 12e4;
16457
+ var cut = (text) => text.length > SUMMARY_MAX ? `${text.slice(0, SUMMARY_MAX - 1)}\u2026` : text;
16458
+ var desiredTrialOf = (view) => {
16459
+ if (view === null) return null;
16460
+ switch (view.status) {
16461
+ case "passed":
16462
+ return {
16463
+ outcome: "passed",
16464
+ summary: view.evidence === "remote" ? "Remote connection verified" : view.evidence === "invoked" ? "Proved by the conversation that opened the team" : "Passed in a local session"
16465
+ };
16466
+ case "overridden":
16467
+ return { outcome: "skipped", summary: "Skipped by a person" };
16468
+ case "failed":
16469
+ return {
16470
+ outcome: "failed",
16471
+ summary: cut(
16472
+ view.failure === null ? "Failed" : `${view.failure.category}: ${view.failure.reason.replace(/\s+/g, " ").trim()}`
16473
+ )
16474
+ };
16475
+ case "pending":
16476
+ return { outcome: "not-run", summary: "Waiting to run" };
16477
+ case "waiting":
16478
+ return { outcome: "not-run", summary: "Sent to the remote agent" };
16479
+ case "running":
16480
+ return { outcome: "not-run", summary: "Running" };
16481
+ }
16482
+ };
16483
+ var TRIAL_FACT = /^team\/member-trial-/u;
16484
+ var isTrialTrigger = (event) => event.type !== "plugin.event-appended" || TRIAL_FACT.test(String(event.payload?.name ?? ""));
16485
+ function startTrialMirror(ctx, deps) {
16486
+ const queue = createSerial("team-trial-mirror-closed");
16487
+ ctx.onDispose(queue.close);
16488
+ const reconcile = async (onlyProjectId, throughSequence) => {
16489
+ const state = await deps.state.get(
16490
+ throughSequence === void 0 ? void 0 : { throughSequence }
16491
+ );
16492
+ const projects = /* @__PURE__ */ new Map();
16493
+ for (const record2 of Object.values(state.members)) {
16494
+ if (onlyProjectId !== void 0 && record2.projectId !== onlyProjectId) continue;
16495
+ const desired = desiredTrialOf(trialViewOf(record2));
16496
+ if (desired === null) continue;
16497
+ const rows = projects.get(record2.projectId) ?? [];
16498
+ rows.push({
16499
+ memberId: record2.memberId,
16500
+ desired,
16501
+ key: JSON.stringify([record2.specKey, record2.attempt])
16502
+ });
16503
+ projects.set(record2.projectId, rows);
16504
+ }
16505
+ for (const [projectId, rows] of projects) {
16506
+ try {
16507
+ const members = await readPages(
16508
+ MEMBER_LIMIT2,
16509
+ (page) => ctx.members.list({ projectId, ...page })
16510
+ );
16511
+ const recorded = new Map(members.items.map((member) => [member.memberId, member]));
16512
+ for (const row of rows) {
16513
+ const member = recorded.get(row.memberId);
16514
+ if (member === void 0 || member.removedAt !== null || member.kind !== "agent")
16515
+ continue;
16516
+ if (member.trial?.outcome === row.desired.outcome && (member.trial.summary ?? "") === row.desired.summary)
16517
+ continue;
16518
+ await ctx.members.trial.record({
16519
+ projectId,
16520
+ memberId: row.memberId,
16521
+ outcome: row.desired.outcome,
16522
+ summary: row.desired.summary,
16523
+ requestId: `team-trial-record:${stableHash(
16524
+ JSON.stringify([projectId, row.memberId, row.key, row.desired])
16525
+ )}`
16526
+ }).catch(
16527
+ (error) => ctx.log.warn("team trial result could not be recorded on the member", {
16528
+ projectId,
16529
+ memberId: row.memberId,
16530
+ error
16531
+ })
16532
+ );
16533
+ }
16534
+ } catch (error) {
16535
+ ctx.log.warn("team trial results could not be compared with the members", {
16536
+ projectId,
16537
+ error
16538
+ });
16539
+ }
16540
+ }
16541
+ };
16542
+ const flush = (onlyProjectId, throughSequence) => queue.run(() => reconcile(onlyProjectId, throughSequence));
16543
+ ctx.reactor({
16544
+ name: "team-trial-mirror",
16545
+ events: ["plugin.event-appended", "member.created", "member.updated", "member.restored"],
16546
+ handle: (event) => isTrialTrigger(event) ? flush(event.aggregateKind === "project" ? event.aggregateId : void 0, event.sequence) : Promise.resolve()
16547
+ });
16548
+ ctx.interval({ name: "team-trial-mirror", everyMs: RECONCILE_MS2, handle: () => flush() });
16549
+ const ready = flush();
16550
+ void ready.catch((error) => ctx.log.warn("team trial mirror catch-up failed", { error }));
16551
+ return { ready, flush };
16552
+ }
16553
+
16786
16554
  // src/trial/env.ts
16787
16555
  var factKey = (record2) => ({
16788
16556
  version: 1,
@@ -16816,17 +16584,11 @@ var REJECTED_REASONS = /* @__PURE__ */ new Set(["rejected", ...CONFLICT_REASONS]
16816
16584
  var isRejection = (error) => REJECTED_REASONS.has(dataCommandReason(error) ?? "");
16817
16585
 
16818
16586
  // src/trial/dispatch.ts
16819
- async function remoteUsable(env, projectId, principalId) {
16820
- try {
16821
- const { items, truncated } = await readPages(
16822
- 500,
16823
- (page) => env.ctx.auth.remoteAgents.list({ projectId, ...page })
16824
- );
16825
- const found = items.find((row) => row.principalId === principalId);
16826
- return found === void 0 ? truncated ? null : false : found.state === "active";
16827
- } catch {
16828
- return null;
16829
- }
16587
+ async function remoteRoute(env, projectId, environmentId) {
16588
+ const machines = await readMachines(env.ctx, projectId);
16589
+ if (machines === null) return { kind: "unknown" };
16590
+ const machine = machines.get(environmentId);
16591
+ return machine === void 0 ? { kind: "missing" } : { kind: "found", principalId: machine.principalId };
16830
16592
  }
16831
16593
  async function toolkitsOn(env, projectId) {
16832
16594
  try {
@@ -16843,16 +16605,21 @@ async function dispatchTrial(env, record2, slots, ensured) {
16843
16605
  const { ctx } = env;
16844
16606
  const member = await findMember(ctx, record2.projectId, record2.memberId, { textLimit: 2 });
16845
16607
  if (!specMatches(member, record2)) return "stuck";
16846
- const principalId = member.identity?.kind === "remote-agent" ? member.identity.principalId : null;
16847
- const local = principalId === null && member.agent !== null && member.agent.environmentId === ctx.environment.id;
16848
- if (principalId === null && !local) {
16849
- await env.fail(record2, member.agent === null ? "no-route" : "other-machine", "");
16608
+ const local = member.agent !== null && !isRemoteMember(member, ctx.environment.id);
16609
+ if (member.agent === null) {
16610
+ await env.fail(record2, "no-route", "");
16850
16611
  return "done";
16851
16612
  }
16852
16613
  if (local && slots.local <= 0) return "wait";
16853
- if (principalId !== null && await remoteUsable(env, record2.projectId, principalId) === false) {
16854
- await env.fail(record2, "no-route", "");
16855
- return "done";
16614
+ let principalId = null;
16615
+ if (!local) {
16616
+ const route = await remoteRoute(env, record2.projectId, member.agent.environmentId);
16617
+ if (route.kind === "unknown") return "stuck";
16618
+ if (route.kind === "missing") {
16619
+ await env.fail(record2, "no-route", "");
16620
+ return "done";
16621
+ }
16622
+ principalId = route.principalId;
16856
16623
  }
16857
16624
  if (!await toolkitsOn(env, record2.projectId)) {
16858
16625
  await env.fail(record2, "toolkit-off", "");
@@ -16910,7 +16677,7 @@ async function ensureSession(env, record2, ensured, prepared) {
16910
16677
  await ctx.communication.records.send({
16911
16678
  projectId: record2.projectId,
16912
16679
  requestId: `team-trial-wake:${key}`,
16913
- to: { principalId: record2.principalId },
16680
+ to: { principalId: record2.principalId, memberId: record2.memberId },
16914
16681
  text: trialMessage("remotePrompt", { trialId }),
16915
16682
  delivery: "wake"
16916
16683
  });
@@ -17085,8 +16852,11 @@ async function tellWaiting(env, record2, told, minutes2) {
17085
16852
  if (await tellLeads(env, leadThreads, record2.projectId, key, text)) told.add(key);
17086
16853
  }
17087
16854
  async function tellReady(env, record2, told) {
17088
- const principalId = remotePrincipalOf(record2.spec.identity);
17089
- if (principalId === null) return;
16855
+ const environmentId = record2.spec.environmentId;
16856
+ if (environmentId === null || environmentId === env.ctx.environment.id) return;
16857
+ const machine = (await readMachines(env.ctx, record2.projectId))?.get(environmentId);
16858
+ if (machine === void 0) return;
16859
+ const { principalId } = machine;
17090
16860
  const key = `team-trial-ready:${stableHash(
17091
16861
  JSON.stringify([
17092
16862
  record2.projectId,
@@ -17099,11 +16869,13 @@ async function tellReady(env, record2, told) {
17099
16869
  if (told.has(key)) return;
17100
16870
  const pending = await env.ctx.work.remoteAgentPending.get({ projectId: record2.projectId, principalId }).catch(() => null);
17101
16871
  if (pending === null) return;
17102
- if (pending.work.items.some((item) => !item.blocked))
16872
+ if (pending.work.items.some(
16873
+ (item) => !item.blocked && (item.memberId === void 0 || item.memberId === record2.memberId)
16874
+ ))
17103
16875
  await env.ctx.communication.records.send({
17104
16876
  projectId: record2.projectId,
17105
16877
  requestId: key,
17106
- to: { principalId },
16878
+ to: { principalId, memberId: record2.memberId },
17107
16879
  text: trialMessage("readyForRemote"),
17108
16880
  delivery: "wake"
17109
16881
  });
@@ -17134,7 +16906,7 @@ var decodeHuman2 = decodeUnknownOption2(HumanPrincipal);
17134
16906
  var decodeFactName = decodeUnknownOption2(
17135
16907
  Struct({ pluginId: Literal2("team"), name: String4 })
17136
16908
  );
17137
- var isTrialTrigger = (event) => {
16909
+ var isTrialTrigger2 = (event) => {
17138
16910
  if (event.type.startsWith("member.")) return true;
17139
16911
  if (event.type !== "plugin.event-appended") return false;
17140
16912
  const fact = decodeFactName(event.payload);
@@ -17321,7 +17093,7 @@ function startTrialRuntime(ctx, deps, options = {}) {
17321
17093
  const threadId = event.payload?.threadId;
17322
17094
  return typeof threadId === "string" && threadId.startsWith("team-trial:") ? failOnSessionError(event).then(() => flush()) : Promise.resolve();
17323
17095
  }
17324
- return isTrialTrigger(event) ? flush() : Promise.resolve();
17096
+ return isTrialTrigger2(event) ? flush() : Promise.resolve();
17325
17097
  }
17326
17098
  });
17327
17099
  ctx.interval({ name: "team-trial", everyMs: options.tickMs ?? TICK_MS2, handle: () => flush() });
@@ -17452,7 +17224,7 @@ function startTrialRuntime(ctx, deps, options = {}) {
17452
17224
  // src/index.ts
17453
17225
  var index_default = definePlugin({
17454
17226
  id: "team",
17455
- apiVersion: 50,
17227
+ apiVersion: 52,
17456
17228
  activate(ctx) {
17457
17229
  const trialState = ctx.derivedState(trialStateDefinition);
17458
17230
  const rosters = createRosterService(ctx);
@@ -17484,7 +17256,8 @@ var index_default = definePlugin({
17484
17256
  },
17485
17257
  memberQueue
17486
17258
  );
17487
- registerPauseCommands(ctx);
17259
+ registerDispatchClaim(ctx, wakes.state);
17260
+ registerPauseCommands(ctx, { wakes: wakes.state, queue: memberQueue });
17488
17261
  startArchiveMirror(
17489
17262
  ctx,
17490
17263
  { state: ctx.derivedState(archiveStateDefinition), wakes: wakes.state },
@@ -17498,7 +17271,6 @@ var index_default = definePlugin({
17498
17271
  startCommentMentionRuntime(ctx, goals);
17499
17272
  startGroupDeliveryRuntime(ctx, wakes.state);
17500
17273
  registerBoardCommands(ctx, goals, rosters, wakes.state);
17501
- registerDetailCommands(ctx, goals, rosters);
17502
17274
  startRecoveryRuntime(ctx, goals, wakes.state, wakes.worktrees);
17503
17275
  startLeadCheckinRuntime(ctx, wakes.state, goals);
17504
17276
  startProgressCheckinRuntime(ctx, goals, wakes.state);
@@ -17512,6 +17284,7 @@ var index_default = definePlugin({
17512
17284
  handbookRelease: async (projectId) => (await handbook.read(projectId)).currentRelease
17513
17285
  });
17514
17286
  registerTrial(ctx, trials2);
17287
+ startTrialMirror(ctx, { state: trialState });
17515
17288
  }
17516
17289
  });
17517
17290
  export {