@ycodium-ai/plugin-team 0.2.3566 → 0.2.3598
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/assets/ui.js +11 -11
- package/dist/index.js +190 -39
- package/locales/en.json +5 -0
- package/locales/zh-CN.json +5 -0
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -7268,6 +7268,7 @@ async function createGoalThread(ctx, goal, thread) {
|
|
|
7268
7268
|
requestId: `thread:${thread.threadId}`,
|
|
7269
7269
|
threadId: thread.threadId,
|
|
7270
7270
|
projectId: goal.projectId,
|
|
7271
|
+
memberId: thread.memberId,
|
|
7271
7272
|
title: goalThreadTitle(goal, thread.name),
|
|
7272
7273
|
...thread.selection,
|
|
7273
7274
|
// 有意写死、不读默认档:带团队的 AI 要无人值守地干活,成员子会话按 YCO-337 只能与负责人同档或更严。
|
|
@@ -7290,6 +7291,7 @@ async function createTeamThread(ctx, thread) {
|
|
|
7290
7291
|
requestId: `thread:${thread.threadId}`,
|
|
7291
7292
|
threadId: thread.threadId,
|
|
7292
7293
|
projectId: thread.projectId,
|
|
7294
|
+
memberId: thread.memberId,
|
|
7293
7295
|
title: thread.title,
|
|
7294
7296
|
...thread.selection,
|
|
7295
7297
|
runtimeMode: "full-access",
|
|
@@ -7411,6 +7413,16 @@ function registerGoalCommands(ctx, service2) {
|
|
|
7411
7413
|
// src/watch.ts
|
|
7412
7414
|
import * as NodeTimers from "node:timers";
|
|
7413
7415
|
|
|
7416
|
+
// src/domain/person.ts
|
|
7417
|
+
var personKey = (person) => person.kind === "account" ? `account:${person.userId}` : `local-owner:${person.environmentId}`;
|
|
7418
|
+
var samePerson = (a, b) => personKey(a) === personKey(b);
|
|
7419
|
+
var personOfMember = (member) => member.identity?.kind === "human" && member.identity.principal !== void 0 ? member.identity.principal : null;
|
|
7420
|
+
var currentPerson = async (invocation) => invocation.viewer === void 0 ? null : (await invocation.viewer.communication.people.current({})).person;
|
|
7421
|
+
async function personDisplayName(ctx, projectId, person, fallback) {
|
|
7422
|
+
const { items } = await ctx.communication.people.list({ projectId, limit: 100 });
|
|
7423
|
+
return items.find((item) => samePerson(item.person, person))?.displayName ?? fallback;
|
|
7424
|
+
}
|
|
7425
|
+
|
|
7414
7426
|
// src/domain/roster.ts
|
|
7415
7427
|
var MEMBER_ID_PATTERN = /^[A-Za-z0-9_-]{1,64}$/;
|
|
7416
7428
|
var MAX_NAME_LENGTH = 40;
|
|
@@ -7535,7 +7547,6 @@ var WorkIdentity = Struct({
|
|
|
7535
7547
|
/** 人的稳定键(见 personKey),界面拿它到快照的人名表里找名字。 */
|
|
7536
7548
|
personKey: optionalKey2(String4)
|
|
7537
7549
|
});
|
|
7538
|
-
var personKey = (principal) => principal.kind === "account" ? `account:${principal.userId}` : `local-owner:${principal.environmentId}`;
|
|
7539
7550
|
var workIdentity = (value) => ({
|
|
7540
7551
|
kind: value.kind,
|
|
7541
7552
|
...value.principalId === void 0 ? {} : { principalId: value.principalId },
|
|
@@ -9487,6 +9498,10 @@ var en_default = {
|
|
|
9487
9498
|
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.",
|
|
9488
9499
|
kindRemoteHint: "An agent that connects from another machine with its own credentials.",
|
|
9489
9500
|
kindPersonHint: "A teammate. People are listed as members but do not run sessions.",
|
|
9501
|
+
thisIsMe: "This is me",
|
|
9502
|
+
thisIsMeHint: "When someone @-mentions this member in a team group, the message goes to your Sent to me.",
|
|
9503
|
+
boundToOther: "This member is another person. Only they can change this.",
|
|
9504
|
+
you: "You",
|
|
9490
9505
|
name: "Name",
|
|
9491
9506
|
memberTitle: "Title",
|
|
9492
9507
|
responsibility: "Responsibility",
|
|
@@ -9533,6 +9548,7 @@ var en_default = {
|
|
|
9533
9548
|
noDefaultModel: "This project has no default model. Choose one in the project settings under New threads \u2192 Model, then try again.",
|
|
9534
9549
|
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.",
|
|
9535
9550
|
duplicateMember: "Another member already has this name or remote agent. Rename or remove that member first.",
|
|
9551
|
+
alreadyYou: "You are already {{name}} on this roster. Clear \u201CThis is me\u201D on {{name}} first.",
|
|
9536
9552
|
staleVersion: "This member was changed elsewhere and has been reloaded. Review it and save again.",
|
|
9537
9553
|
notFound: "This member no longer exists.",
|
|
9538
9554
|
invalidState: "The member's state was changed elsewhere and has been reloaded.",
|
|
@@ -10090,6 +10106,7 @@ import {
|
|
|
10090
10106
|
MEMBER_RESPONSIBILITY_MAX,
|
|
10091
10107
|
MEMBER_TITLE_MAX
|
|
10092
10108
|
} from "@ycodium-ai/plugin-api";
|
|
10109
|
+
var MAX_MEMBER_NAME_LENGTH = MEMBER_NAME_MAX;
|
|
10093
10110
|
var MemberAvatar = Struct({ pattern: String4, color: String4 });
|
|
10094
10111
|
var AgentChoice = Struct({
|
|
10095
10112
|
environmentId: String4,
|
|
@@ -10104,6 +10121,8 @@ var MemberRow = Struct({
|
|
|
10104
10121
|
avatar: NullOr(MemberAvatar),
|
|
10105
10122
|
/** 远端 agent 成员绑的主体;本机 agent 与人是 null。 */
|
|
10106
10123
|
remotePrincipalId: NullOr(String4),
|
|
10124
|
+
/** 人成员绑着的人是不是正在看这一页的人;没绑就没有这一项。 */
|
|
10125
|
+
person: optionalKey2(Literals(["me", "other"])),
|
|
10107
10126
|
agent: NullOr(
|
|
10108
10127
|
Struct({
|
|
10109
10128
|
environmentId: String4,
|
|
@@ -10158,7 +10177,9 @@ var CreateMemberInput = Struct({
|
|
|
10158
10177
|
avatar: optionalKey2(MemberAvatar),
|
|
10159
10178
|
/** 给了就是远端 agent:绑这个主体。 */
|
|
10160
10179
|
remotePrincipalId: optionalKey2(String4),
|
|
10161
|
-
agent: optionalKey2(AgentChoice)
|
|
10180
|
+
agent: optionalKey2(AgentChoice),
|
|
10181
|
+
/** 人成员「这是我」:绑到发起这次调用的人。 */
|
|
10182
|
+
bindToMe: optionalKey2(Boolean3)
|
|
10162
10183
|
});
|
|
10163
10184
|
var UpdateMemberInput = Struct({
|
|
10164
10185
|
...projectAndRequest,
|
|
@@ -10168,7 +10189,9 @@ var UpdateMemberInput = Struct({
|
|
|
10168
10189
|
...memberTextFields,
|
|
10169
10190
|
avatar: optionalKey2(MemberAvatar),
|
|
10170
10191
|
clearAvatar: optionalKey2(Boolean3),
|
|
10171
|
-
agent: optionalKey2(AgentChoice)
|
|
10192
|
+
agent: optionalKey2(AgentChoice),
|
|
10193
|
+
/** 人成员「这是我」:`true` 绑到发起这次调用的人,`false` 解绑。 */
|
|
10194
|
+
bindToMe: optionalKey2(Boolean3)
|
|
10172
10195
|
});
|
|
10173
10196
|
var MemberRefInput = Struct({ ...projectAndRequest, memberId: String4 });
|
|
10174
10197
|
var ImportRosterInput = Struct({ projectId: String4 });
|
|
@@ -10646,24 +10669,30 @@ function startCoordinatorRuntime(ctx, deps) {
|
|
|
10646
10669
|
}
|
|
10647
10670
|
|
|
10648
10671
|
// src/members/snapshot.ts
|
|
10649
|
-
var toMemberRow = (member, trial) =>
|
|
10650
|
-
|
|
10651
|
-
|
|
10652
|
-
|
|
10653
|
-
|
|
10654
|
-
|
|
10655
|
-
|
|
10656
|
-
|
|
10657
|
-
|
|
10658
|
-
|
|
10659
|
-
|
|
10660
|
-
|
|
10661
|
-
|
|
10662
|
-
|
|
10663
|
-
|
|
10664
|
-
|
|
10665
|
-
|
|
10666
|
-
}
|
|
10672
|
+
var toMemberRow = (member, trial, viewer) => {
|
|
10673
|
+
const person = personOfMember(member);
|
|
10674
|
+
return {
|
|
10675
|
+
memberId: member.memberId,
|
|
10676
|
+
kind: member.kind,
|
|
10677
|
+
name: member.name,
|
|
10678
|
+
title: member.title,
|
|
10679
|
+
responsibility: member.responsibility,
|
|
10680
|
+
avatar: member.avatar === null ? null : { pattern: member.avatar.pattern, color: member.avatar.color },
|
|
10681
|
+
remotePrincipalId: member.identity?.kind === "remote-agent" ? member.identity.principalId : null,
|
|
10682
|
+
...person === null ? {} : {
|
|
10683
|
+
person: viewer !== null && samePerson(person, viewer) ? "me" : "other"
|
|
10684
|
+
},
|
|
10685
|
+
agent: member.agent === null ? null : {
|
|
10686
|
+
environmentId: member.agent.environmentId,
|
|
10687
|
+
instanceId: member.agent.modelSelection.instanceId,
|
|
10688
|
+
model: member.agent.modelSelection.model
|
|
10689
|
+
},
|
|
10690
|
+
hasInstructions: member.workInstructionsRevision !== null,
|
|
10691
|
+
version: member.version,
|
|
10692
|
+
removed: member.removedAt !== null,
|
|
10693
|
+
...trial === null ? {} : { trial }
|
|
10694
|
+
};
|
|
10695
|
+
};
|
|
10667
10696
|
var legacyOffer = (stored) => ({
|
|
10668
10697
|
revision: stored.roster.revision,
|
|
10669
10698
|
leadMemberId: stored.roster.leadMemberId,
|
|
@@ -10673,10 +10702,10 @@ var legacyOffer = (stored) => ({
|
|
|
10673
10702
|
principalId: member.principal?.principalId ?? null
|
|
10674
10703
|
}))
|
|
10675
10704
|
});
|
|
10676
|
-
function membersSnapshot(view, trialOf = () => null) {
|
|
10705
|
+
function membersSnapshot(view, trialOf = () => null, viewer = null) {
|
|
10677
10706
|
const { stored } = view;
|
|
10678
10707
|
return {
|
|
10679
|
-
members: view.members.map((member) => toMemberRow(member, trialOf(member.memberId))),
|
|
10708
|
+
members: view.members.map((member) => toMemberRow(member, trialOf(member.memberId), viewer)),
|
|
10680
10709
|
lead: {
|
|
10681
10710
|
memberId: stored?.version === 2 ? stored.roster.leadMemberId : null,
|
|
10682
10711
|
revision: stored?.roster.revision ?? 0
|
|
@@ -10999,10 +11028,18 @@ function registerMemberCommands(ctx, rosters, writer, trials2) {
|
|
|
10999
11028
|
name: "members",
|
|
11000
11029
|
scope: "read",
|
|
11001
11030
|
payloadSchema: payloadSchemaOf(ReadMembersInput),
|
|
11002
|
-
handle: async (payload) => {
|
|
11031
|
+
handle: async (payload, invocation) => {
|
|
11003
11032
|
const { projectId } = decodeReadMembers(payload);
|
|
11004
|
-
const [view, trial] = await Promise.all([
|
|
11005
|
-
|
|
11033
|
+
const [view, trial, viewer] = await Promise.all([
|
|
11034
|
+
rosters.inspect(projectId),
|
|
11035
|
+
trials2.get(),
|
|
11036
|
+
currentPerson(invocation)
|
|
11037
|
+
]);
|
|
11038
|
+
return membersSnapshot(
|
|
11039
|
+
view,
|
|
11040
|
+
(memberId) => trialViewOf(recordOf(trial, projectId, memberId)),
|
|
11041
|
+
viewer
|
|
11042
|
+
);
|
|
11006
11043
|
}
|
|
11007
11044
|
});
|
|
11008
11045
|
ctx.command({
|
|
@@ -11091,14 +11128,21 @@ function createMemberWriter(ctx, rosters, queue = createSerial()) {
|
|
|
11091
11128
|
const serial = queue.run;
|
|
11092
11129
|
const asPerson = (commandType, handler) => (payload, invocation) => serial(async () => {
|
|
11093
11130
|
const person = invocation.asPerson;
|
|
11094
|
-
return person === void 0 ? rejectMember(commandType, "needs-person") : handler(payload, person.members);
|
|
11131
|
+
return person === void 0 ? rejectMember(commandType, "needs-person") : handler(payload, person.members, invocation);
|
|
11095
11132
|
});
|
|
11096
|
-
const
|
|
11133
|
+
const meOf = async (commandType, invocation) => await currentPerson(invocation) ?? rejectMember(commandType, "needs-person");
|
|
11134
|
+
const create = asPerson("createMember", async (payload, members, invocation) => {
|
|
11097
11135
|
const decoded = decodeCreate3(payload);
|
|
11098
11136
|
if (isNone2(decoded)) return rejectMember("createMember", "invalid-payload");
|
|
11099
11137
|
const input = decoded.value;
|
|
11100
|
-
if (input.kind === "human"
|
|
11138
|
+
if (input.kind === "human" ? input.agent !== void 0 || input.remotePrincipalId !== void 0 : input.bindToMe !== void 0)
|
|
11101
11139
|
return rejectMember("createMember", "invalid-payload");
|
|
11140
|
+
let me;
|
|
11141
|
+
if (input.bindToMe === true) {
|
|
11142
|
+
const found = await meOf("createMember", invocation);
|
|
11143
|
+
if ("code" in found) return found;
|
|
11144
|
+
me = found;
|
|
11145
|
+
}
|
|
11102
11146
|
const memberId = createdMemberId(input.projectId, input.requestId);
|
|
11103
11147
|
let agent;
|
|
11104
11148
|
if (input.kind === "agent") {
|
|
@@ -11125,17 +11169,29 @@ function createMemberWriter(ctx, rosters, queue = createSerial()) {
|
|
|
11125
11169
|
...input.avatar === void 0 ? {} : { avatar: input.avatar },
|
|
11126
11170
|
...input.workInstructions === void 0 ? {} : { workInstructions: input.workInstructions },
|
|
11127
11171
|
...input.remotePrincipalId === void 0 ? {} : { identity: { kind: "remote-agent", principalId: input.remotePrincipalId } },
|
|
11172
|
+
...me === void 0 ? {} : { identity: { kind: "human", principal: me } },
|
|
11128
11173
|
...agent === void 0 ? {} : { agent }
|
|
11129
11174
|
})
|
|
11130
11175
|
);
|
|
11131
11176
|
return "code" in result2 ? result2 : written(result2);
|
|
11132
11177
|
});
|
|
11133
|
-
const update = asPerson("updateMember", async (payload, members) => {
|
|
11178
|
+
const update = asPerson("updateMember", async (payload, members, invocation) => {
|
|
11134
11179
|
const decoded = decodeUpdate3(payload);
|
|
11135
11180
|
if (isNone2(decoded)) return rejectMember("updateMember", "invalid-payload");
|
|
11136
11181
|
const input = decoded.value;
|
|
11137
11182
|
if (input.avatar !== void 0 && input.clearAvatar === true)
|
|
11138
11183
|
return rejectMember("updateMember", "invalid-payload");
|
|
11184
|
+
let identity2;
|
|
11185
|
+
if (input.bindToMe !== void 0) {
|
|
11186
|
+
const me = await meOf("updateMember", invocation);
|
|
11187
|
+
if ("code" in me) return me;
|
|
11188
|
+
const member = await findMember(ctx, input.projectId, input.memberId);
|
|
11189
|
+
if (member === null) return rejectMember("updateMember", "not-found");
|
|
11190
|
+
const held = personOfMember(member);
|
|
11191
|
+
if (held !== null && !samePerson(held, me))
|
|
11192
|
+
return rejectMember("updateMember", "bound-to-other");
|
|
11193
|
+
identity2 = input.bindToMe ? { kind: "human", principal: me } : null;
|
|
11194
|
+
}
|
|
11139
11195
|
const result2 = await refused(
|
|
11140
11196
|
"updateMember",
|
|
11141
11197
|
() => members.update({
|
|
@@ -11148,7 +11204,8 @@ function createMemberWriter(ctx, rosters, queue = createSerial()) {
|
|
|
11148
11204
|
...input.responsibility === void 0 ? {} : { responsibility: input.responsibility },
|
|
11149
11205
|
...input.clearAvatar === true ? { avatar: null } : input.avatar === void 0 ? {} : { avatar: input.avatar },
|
|
11150
11206
|
...input.workInstructions === void 0 ? {} : { workInstructions: input.workInstructions },
|
|
11151
|
-
...input.agent === void 0 ? {} : { agent: toEngineAgent(input.agent) }
|
|
11207
|
+
...input.agent === void 0 ? {} : { agent: toEngineAgent(input.agent) },
|
|
11208
|
+
...identity2 === void 0 ? {} : { identity: identity2 }
|
|
11152
11209
|
})
|
|
11153
11210
|
);
|
|
11154
11211
|
return "code" in result2 ? result2 : written(result2);
|
|
@@ -11694,7 +11751,15 @@ function startGroupDeliveryRuntime(ctx, wakes, now3 = () => runPromise2(map5(now
|
|
|
11694
11751
|
};
|
|
11695
11752
|
ctx.reactor({
|
|
11696
11753
|
name: "team-group-delivery",
|
|
11697
|
-
|
|
11754
|
+
// 成员建出或改了(人点「这是我」绑上)也补扫:停在待绑定的人目标立刻投到人。
|
|
11755
|
+
events: [
|
|
11756
|
+
"communication.group-message-sent",
|
|
11757
|
+
"work.line-restored",
|
|
11758
|
+
"plugin.event-appended",
|
|
11759
|
+
"member.created",
|
|
11760
|
+
"member.updated",
|
|
11761
|
+
"member.restored"
|
|
11762
|
+
],
|
|
11698
11763
|
handle: (event) => {
|
|
11699
11764
|
const projectId = decodeProjectEvent(event.payload);
|
|
11700
11765
|
if (isSome2(projectId)) return sweep(projectId.value.projectId);
|
|
@@ -11792,6 +11857,7 @@ function startMemberBindingRuntime(ctx, goals, rosters, wakes, trials2) {
|
|
|
11792
11857
|
if (goal.workLineId !== void 0 && lead !== void 0)
|
|
11793
11858
|
await createTeamThread(ctx, {
|
|
11794
11859
|
projectId,
|
|
11860
|
+
memberId: member.memberId,
|
|
11795
11861
|
threadId,
|
|
11796
11862
|
parentThreadId: lead.threadId,
|
|
11797
11863
|
title: goalThreadTitle(goal, member.name),
|
|
@@ -15184,14 +15250,78 @@ function startLineNameMirror(ctx, queue) {
|
|
|
15184
15250
|
});
|
|
15185
15251
|
}
|
|
15186
15252
|
|
|
15253
|
+
// src/team/freeName.ts
|
|
15254
|
+
var NAME_RETRIES = 3;
|
|
15255
|
+
var nameTag = (seed, attempt) => attempt === 0 ? "" : ` #${stableHash(`${seed}${attempt}`).slice(0, 4)}`;
|
|
15256
|
+
var withNameTag = (name, tag2) => {
|
|
15257
|
+
const base = name.trim().slice(0, MAX_MEMBER_NAME_LENGTH);
|
|
15258
|
+
return tag2 === "" ? base : `${base.slice(0, MAX_MEMBER_NAME_LENGTH - tag2.length)}${tag2}`;
|
|
15259
|
+
};
|
|
15260
|
+
|
|
15261
|
+
// src/team/ownerMember.ts
|
|
15262
|
+
async function ownerOf(ctx, threadId) {
|
|
15263
|
+
const createdBy = (await ctx.threads.get({ threadId })).createdBy ?? null;
|
|
15264
|
+
const person = createdBy === null ? { kind: "local-owner", environmentId: ctx.environment.id } : { kind: "account", userId: createdBy.userId };
|
|
15265
|
+
return { person, createdName: createdBy?.displayName ?? null };
|
|
15266
|
+
}
|
|
15267
|
+
async function boundOwnerMember(ctx, projectId, threadId) {
|
|
15268
|
+
const { person } = await ownerOf(ctx, threadId);
|
|
15269
|
+
const { items } = await readPages(
|
|
15270
|
+
Number.POSITIVE_INFINITY,
|
|
15271
|
+
(page) => ctx.members.list({ projectId, ...page })
|
|
15272
|
+
);
|
|
15273
|
+
return items.find((row) => {
|
|
15274
|
+
const held = row.kind === "human" && row.removedAt === null ? personOfMember(row) : null;
|
|
15275
|
+
return held !== null && samePerson(held, person);
|
|
15276
|
+
})?.memberId ?? null;
|
|
15277
|
+
}
|
|
15278
|
+
async function ensureOwnerMember(ctx, projectId, threadId, chosen) {
|
|
15279
|
+
if (chosen !== null) return chosen;
|
|
15280
|
+
const memberId = `person:${stableHash(JSON.stringify([projectId, threadId])).slice(0, 24)}`;
|
|
15281
|
+
const mine = await findMember(ctx, projectId, memberId);
|
|
15282
|
+
if (mine !== null) return mine.removedAt === null ? memberId : null;
|
|
15283
|
+
const { person, createdName } = await ownerOf(ctx, threadId);
|
|
15284
|
+
const name = await personDisplayName(ctx, projectId, person, createdName);
|
|
15285
|
+
if (name === null) return null;
|
|
15286
|
+
for (let attempt = 0; ; attempt++) {
|
|
15287
|
+
const candidate = withNameTag(name, nameTag(threadId, attempt));
|
|
15288
|
+
try {
|
|
15289
|
+
await ctx.members.create({
|
|
15290
|
+
projectId,
|
|
15291
|
+
requestId: `team-owner-member:${mark(projectId, threadId, "owner")}:${attempt}`,
|
|
15292
|
+
memberId,
|
|
15293
|
+
kind: "human",
|
|
15294
|
+
name: candidate,
|
|
15295
|
+
identity: { kind: "human", principal: person }
|
|
15296
|
+
});
|
|
15297
|
+
return memberId;
|
|
15298
|
+
} catch (error) {
|
|
15299
|
+
const refusal = memberRefusal(error);
|
|
15300
|
+
if (refusal?.code !== "duplicate-member") throw error;
|
|
15301
|
+
const details = refusal.details;
|
|
15302
|
+
if (typeof details === "object" && details !== null && Reflect.get(details, "field") === "identity")
|
|
15303
|
+
return boundOwnerMember(ctx, projectId, threadId);
|
|
15304
|
+
if (attempt >= NAME_RETRIES) throw error;
|
|
15305
|
+
}
|
|
15306
|
+
}
|
|
15307
|
+
}
|
|
15308
|
+
|
|
15187
15309
|
// src/team/open.ts
|
|
15188
15310
|
var decodeOpen = decodeUnknownOption2(TeamOpenInput);
|
|
15311
|
+
var decodeOwner = decodeUnknownOption2(
|
|
15312
|
+
Struct({ ownerMemberId: NullOr(String4) })
|
|
15313
|
+
);
|
|
15189
15314
|
function statusOf2(trials2, projectId, member) {
|
|
15190
15315
|
if (member.kind === "human") return "human";
|
|
15191
15316
|
const view = trialViewOf(recordOf(trials2, projectId, member.memberId));
|
|
15192
15317
|
if (view === null) return "ready";
|
|
15193
15318
|
return view.status === "passed" || view.status === "overridden" ? "ready" : view.status === "failed" ? "trial-failed" : "trial-pending";
|
|
15194
15319
|
}
|
|
15320
|
+
function leadMemberName(leadName, title, tag2) {
|
|
15321
|
+
if (leadName !== void 0) return withNameTag(leadName, tag2);
|
|
15322
|
+
const tail = ` lead${tag2}`;
|
|
15323
|
+
return `${title.trim().slice(0, MAX_MEMBER_NAME_LENGTH - tail.length).trimEnd()}${tail}`.trim();
|
|
15324
|
+
}
|
|
15195
15325
|
var remotePrincipalOf2 = (member) => member.identity?.kind === "remote-agent" ? member.identity.principalId : null;
|
|
15196
15326
|
function createTeamOpener(ctx, deps, runner = createLineChangeRunner(ctx, deps), now3 = factTime) {
|
|
15197
15327
|
const lineIdOf = (projectId, threadId, requestId) => `wl-${mark(projectId, threadId, requestId).slice(0, 24)}`;
|
|
@@ -15211,9 +15341,8 @@ function createTeamOpener(ctx, deps, runner = createLineChangeRunner(ctx, deps),
|
|
|
15211
15341
|
ctx.projections.getThreadExecution(threadId)
|
|
15212
15342
|
]);
|
|
15213
15343
|
if (execution === null) throw new TeamRuleError("not-local", teamMessage("notLocal"));
|
|
15214
|
-
const base = (leadName ?? `${shell.title} lead`).trim().slice(0, 40);
|
|
15215
15344
|
for (let attempt = 0; ; attempt++) {
|
|
15216
|
-
const name =
|
|
15345
|
+
const name = leadMemberName(leadName, shell.title, nameTag(threadId, attempt));
|
|
15217
15346
|
try {
|
|
15218
15347
|
await ctx.members.create({
|
|
15219
15348
|
projectId,
|
|
@@ -15228,7 +15357,7 @@ function createTeamOpener(ctx, deps, runner = createLineChangeRunner(ctx, deps),
|
|
|
15228
15357
|
});
|
|
15229
15358
|
return memberId;
|
|
15230
15359
|
} catch (error) {
|
|
15231
|
-
if (hostRefusalCode(error) !== "duplicate-member" || attempt >=
|
|
15360
|
+
if (hostRefusalCode(error) !== "duplicate-member" || attempt >= NAME_RETRIES) throw error;
|
|
15232
15361
|
}
|
|
15233
15362
|
}
|
|
15234
15363
|
};
|
|
@@ -15265,6 +15394,17 @@ function createTeamOpener(ctx, deps, runner = createLineChangeRunner(ctx, deps),
|
|
|
15265
15394
|
const local = rows.filter((row) => row.kind === "agent" && remotePrincipalOf2(row) === null);
|
|
15266
15395
|
const selections = await resolveLocalSelections(projectId, local);
|
|
15267
15396
|
const leadMemberId = await ensureLeadMember(projectId, callerThreadId, input.leadName);
|
|
15397
|
+
const ownerMemberId = await ensureOwnerMember(
|
|
15398
|
+
ctx,
|
|
15399
|
+
projectId,
|
|
15400
|
+
callerThreadId,
|
|
15401
|
+
match(decodeOwner(intent.input), {
|
|
15402
|
+
onNone: () => null,
|
|
15403
|
+
onSome: (recorded) => recorded.ownerMemberId
|
|
15404
|
+
})
|
|
15405
|
+
);
|
|
15406
|
+
const owner = ownerMemberId === null || rows.some((row) => row.memberId === ownerMemberId) ? null : await findMember(ctx, projectId, ownerMemberId);
|
|
15407
|
+
const team = owner === null ? rows : [owner, ...rows];
|
|
15268
15408
|
try {
|
|
15269
15409
|
const created = await ctx.work.lines.create({
|
|
15270
15410
|
projectId,
|
|
@@ -15272,7 +15412,7 @@ function createTeamOpener(ctx, deps, runner = createLineChangeRunner(ctx, deps),
|
|
|
15272
15412
|
workLineId,
|
|
15273
15413
|
name,
|
|
15274
15414
|
leadMemberId,
|
|
15275
|
-
members: [leadMemberId, ...
|
|
15415
|
+
members: [leadMemberId, ...team.map((row) => row.memberId)],
|
|
15276
15416
|
threadId: callerThreadId
|
|
15277
15417
|
});
|
|
15278
15418
|
await ctx.events.append(baselineMirrored(projectId, workLineId, created.result.version));
|
|
@@ -15317,6 +15457,7 @@ function createTeamOpener(ctx, deps, runner = createLineChangeRunner(ctx, deps),
|
|
|
15317
15457
|
for (const row of local) {
|
|
15318
15458
|
await createTeamThread(ctx, {
|
|
15319
15459
|
projectId,
|
|
15460
|
+
memberId: row.memberId,
|
|
15320
15461
|
threadId: teamThreadId(projectId, goalId, row.memberId),
|
|
15321
15462
|
parentThreadId: callerThreadId,
|
|
15322
15463
|
title: goalThreadTitle(goal, row.name),
|
|
@@ -15335,7 +15476,7 @@ function createTeamOpener(ctx, deps, runner = createLineChangeRunner(ctx, deps),
|
|
|
15335
15476
|
});
|
|
15336
15477
|
await syncLineTitle(ctx, projectId, workLineId);
|
|
15337
15478
|
const trials2 = await deps.trials.get();
|
|
15338
|
-
const roster =
|
|
15479
|
+
const roster = team.map((row) => {
|
|
15339
15480
|
const principalId = remotePrincipalOf2(row);
|
|
15340
15481
|
return {
|
|
15341
15482
|
name: row.name,
|
|
@@ -15416,7 +15557,10 @@ function createTeamOpener(ctx, deps, runner = createLineChangeRunner(ctx, deps),
|
|
|
15416
15557
|
projectId,
|
|
15417
15558
|
rows.filter((row) => row.kind === "agent" && remotePrincipalOf2(row) === null)
|
|
15418
15559
|
);
|
|
15419
|
-
return
|
|
15560
|
+
return {
|
|
15561
|
+
...input,
|
|
15562
|
+
ownerMemberId: await boundOwnerMember(ctx, projectId, callerThreadId)
|
|
15563
|
+
};
|
|
15420
15564
|
}
|
|
15421
15565
|
});
|
|
15422
15566
|
};
|
|
@@ -16278,6 +16422,10 @@ var zh_CN_default = {
|
|
|
16278
16422
|
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",
|
|
16279
16423
|
kindRemoteHint: "\u4ECE\u53E6\u4E00\u53F0\u673A\u5668\u7528\u81EA\u5DF1\u7684\u51ED\u636E\u8FDE\u8FDB\u6765\u7684 agent\u3002",
|
|
16280
16424
|
kindPersonHint: "\u56E2\u961F\u91CC\u7684\u4EBA\u3002\u4EBA\u4F1A\u5217\u5728\u6210\u5458\u91CC\uFF0C\u4F46\u4E0D\u4F1A\u8FD0\u884C\u4F1A\u8BDD\u3002",
|
|
16425
|
+
thisIsMe: "\u8FD9\u662F\u6211",
|
|
16426
|
+
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",
|
|
16427
|
+
boundToOther: "\u8FD9\u4E2A\u6210\u5458\u662F\u53E6\u4E00\u4E2A\u4EBA\uFF0C\u53EA\u6709\u5BF9\u65B9\u672C\u4EBA\u80FD\u6539\u8FD9\u4E00\u9879\u3002",
|
|
16428
|
+
you: "\u6211",
|
|
16281
16429
|
name: "\u540D\u5B57",
|
|
16282
16430
|
memberTitle: "\u5934\u8854",
|
|
16283
16431
|
responsibility: "\u804C\u8D23",
|
|
@@ -16324,6 +16472,7 @@ var zh_CN_default = {
|
|
|
16324
16472
|
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",
|
|
16325
16473
|
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",
|
|
16326
16474
|
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",
|
|
16475
|
+
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",
|
|
16327
16476
|
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",
|
|
16328
16477
|
notFound: "\u8FD9\u540D\u6210\u5458\u5DF2\u4E0D\u5B58\u5728\u3002",
|
|
16329
16478
|
invalidState: "\u8FD9\u540D\u6210\u5458\u7684\u72B6\u6001\u5DF2\u88AB\u522B\u5904\u6539\u8FC7\uFF0C\u5DF2\u91CD\u65B0\u8F7D\u5165\u3002",
|
|
@@ -16742,6 +16891,7 @@ async function ensureSession(env, record2, ensured, prepared) {
|
|
|
16742
16891
|
if (parentThreadId !== void 0)
|
|
16743
16892
|
await createTeamThread(ctx, {
|
|
16744
16893
|
projectId: record2.projectId,
|
|
16894
|
+
memberId: record2.memberId,
|
|
16745
16895
|
threadId: trialId,
|
|
16746
16896
|
parentThreadId,
|
|
16747
16897
|
title: member.name,
|
|
@@ -16752,6 +16902,7 @@ async function ensureSession(env, record2, ensured, prepared) {
|
|
|
16752
16902
|
requestId: `thread:${trialId}`,
|
|
16753
16903
|
threadId: trialId,
|
|
16754
16904
|
projectId: record2.projectId,
|
|
16905
|
+
memberId: record2.memberId,
|
|
16755
16906
|
title: member.name,
|
|
16756
16907
|
...selection,
|
|
16757
16908
|
// 与旧目标的成员一致:不然试跑里的工具调用会卡在审批上。
|
|
@@ -17262,7 +17413,7 @@ function startTrialRuntime(ctx, deps, options = {}) {
|
|
|
17262
17413
|
// src/index.ts
|
|
17263
17414
|
var index_default = definePlugin({
|
|
17264
17415
|
id: "team",
|
|
17265
|
-
apiVersion:
|
|
17416
|
+
apiVersion: 48,
|
|
17266
17417
|
activate(ctx) {
|
|
17267
17418
|
const trialState = ctx.derivedState(trialStateDefinition);
|
|
17268
17419
|
const rosters = createRosterService(ctx);
|
package/locales/en.json
CHANGED
|
@@ -236,6 +236,10 @@
|
|
|
236
236
|
"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.",
|
|
237
237
|
"kindRemoteHint": "An agent that connects from another machine with its own credentials.",
|
|
238
238
|
"kindPersonHint": "A teammate. People are listed as members but do not run sessions.",
|
|
239
|
+
"thisIsMe": "This is me",
|
|
240
|
+
"thisIsMeHint": "When someone @-mentions this member in a team group, the message goes to your Sent to me.",
|
|
241
|
+
"boundToOther": "This member is another person. Only they can change this.",
|
|
242
|
+
"you": "You",
|
|
239
243
|
"name": "Name",
|
|
240
244
|
"memberTitle": "Title",
|
|
241
245
|
"responsibility": "Responsibility",
|
|
@@ -282,6 +286,7 @@
|
|
|
282
286
|
"noDefaultModel": "This project has no default model. Choose one in the project settings under New threads → Model, then try again.",
|
|
283
287
|
"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 → Model.",
|
|
284
288
|
"duplicateMember": "Another member already has this name or remote agent. Rename or remove that member first.",
|
|
289
|
+
"alreadyYou": "You are already {{name}} on this roster. Clear “This is me” on {{name}} first.",
|
|
285
290
|
"staleVersion": "This member was changed elsewhere and has been reloaded. Review it and save again.",
|
|
286
291
|
"notFound": "This member no longer exists.",
|
|
287
292
|
"invalidState": "The member's state was changed elsewhere and has been reloaded.",
|
package/locales/zh-CN.json
CHANGED
|
@@ -236,6 +236,10 @@
|
|
|
236
236
|
"kindAgentHint": "机器选这一台时,用你选的 provider 和模型运行。选了别的机器的成员试跑会出错:改回这一台,或者跳过试跑,它就在这台机器上用项目的默认模型运行。",
|
|
237
237
|
"kindRemoteHint": "从另一台机器用自己的凭据连进来的 agent。",
|
|
238
238
|
"kindPersonHint": "团队里的人。人会列在成员里,但不会运行会话。",
|
|
239
|
+
"thisIsMe": "这是我",
|
|
240
|
+
"thisIsMeHint": "有人在团队群里 @ 这个成员时,消息会进你的「发给我的」。",
|
|
241
|
+
"boundToOther": "这个成员是另一个人,只有对方本人能改这一项。",
|
|
242
|
+
"you": "我",
|
|
239
243
|
"name": "名字",
|
|
240
244
|
"memberTitle": "头衔",
|
|
241
245
|
"responsibility": "职责",
|
|
@@ -282,6 +286,7 @@
|
|
|
282
286
|
"noDefaultModel": "这个项目没设默认模型。到项目设置的「新会话 → 模型」选一个,再重试。",
|
|
283
287
|
"modelUnavailable": "这个项目的默认模型在这台机器上用不了。检查一下 provider,或到项目设置的「新会话 → 模型」换一个。",
|
|
284
288
|
"duplicateMember": "已有成员用了这个名字或这个远端 agent,请先改名或移除它。",
|
|
289
|
+
"alreadyYou": "你在名册上已经是「{{name}}」了,请先在「{{name}}」那里取消「这是我」。",
|
|
285
290
|
"staleVersion": "这名成员已被别处改过,已重新载入。请确认后再保存。",
|
|
286
291
|
"notFound": "这名成员已不存在。",
|
|
287
292
|
"invalidState": "这名成员的状态已被别处改过,已重新载入。",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ycodium-ai/plugin-team",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3598",
|
|
4
4
|
"description": "A project team roster with members, a lead, and goals.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"teams",
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"tailwindcss": "^4.0.0",
|
|
35
35
|
"typescript": "~6.0.3",
|
|
36
36
|
"vite-plus": "0.2.2",
|
|
37
|
-
"
|
|
38
|
-
"ycodium-
|
|
37
|
+
"ycodium-system-text": "0.0.0",
|
|
38
|
+
"@ycodium-ai/plugin-api": "0.2.3598"
|
|
39
39
|
},
|
|
40
40
|
"ycodium": {
|
|
41
41
|
"plugin": "./dist/index.js",
|