duclaw-cli 1.9.8 → 1.9.9
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/bundle.js +2160 -2098
- package/dist/main.js +1 -1
- package/dist/web/assets/{index-BYLnL8Rp.js → index-CiEOENzL.js} +2 -2
- package/dist/web/index.html +1 -1
- package/dist/worker-main.js +1 -1
- package/package.json +1 -1
package/dist/bundle.js
CHANGED
|
@@ -30242,7 +30242,7 @@ function printHelp() {
|
|
|
30242
30242
|
`);
|
|
30243
30243
|
}
|
|
30244
30244
|
function printVersion() {
|
|
30245
|
-
console.log(`duclaw-cli v${true ? "1.9.
|
|
30245
|
+
console.log(`duclaw-cli v${true ? "1.9.9" : "unknown"}`);
|
|
30246
30246
|
}
|
|
30247
30247
|
function getDuclawTemplate() {
|
|
30248
30248
|
return {
|
|
@@ -41782,9 +41782,9 @@ var imageUnderstand = {
|
|
|
41782
41782
|
};
|
|
41783
41783
|
|
|
41784
41784
|
// src/skill/SkillRegistry.ts
|
|
41785
|
-
var
|
|
41785
|
+
var import_fs13 = require("fs");
|
|
41786
41786
|
var import_os3 = require("os");
|
|
41787
|
-
var
|
|
41787
|
+
var import_path18 = __toESM(require("path"));
|
|
41788
41788
|
|
|
41789
41789
|
// src/runtime/paths.ts
|
|
41790
41790
|
var import_fs10 = require("fs");
|
|
@@ -41829,2322 +41829,2346 @@ var resolveWebDistRoot = () => {
|
|
|
41829
41829
|
return candidates[0];
|
|
41830
41830
|
};
|
|
41831
41831
|
|
|
41832
|
-
// src/
|
|
41833
|
-
var
|
|
41834
|
-
|
|
41835
|
-
|
|
41832
|
+
// src/department/Department.ts
|
|
41833
|
+
var import_path16 = __toESM(require("path"));
|
|
41834
|
+
var import_fs11 = require("fs");
|
|
41835
|
+
var legacyMigrationChecked = false;
|
|
41836
|
+
var getDepartmentBaseDir = () => {
|
|
41837
|
+
return import_path16.default.join(getDuclawHomeDir(), "department");
|
|
41836
41838
|
};
|
|
41837
|
-
var
|
|
41838
|
-
|
|
41839
|
-
const seenPaths = /* @__PURE__ */ new Set();
|
|
41840
|
-
const pushPath = (candidate) => {
|
|
41841
|
-
if (!(0, import_fs11.existsSync)(candidate) || !(0, import_fs11.statSync)(candidate).isDirectory()) return;
|
|
41842
|
-
const normalized = import_path16.default.resolve(candidate);
|
|
41843
|
-
if (seenPaths.has(normalized)) return;
|
|
41844
|
-
seenPaths.add(normalized);
|
|
41845
|
-
paths.push(normalized);
|
|
41846
|
-
};
|
|
41847
|
-
const projectSkillsPath = getProjectSkillsPath();
|
|
41848
|
-
if (projectSkillsPath) {
|
|
41849
|
-
pushPath(projectSkillsPath);
|
|
41850
|
-
}
|
|
41851
|
-
pushPath((0, import_path16.join)((0, import_os3.homedir)(), ".duclaw", "skills"));
|
|
41852
|
-
pushPath((0, import_path16.join)((0, import_os3.homedir)(), ".agents", "skills"));
|
|
41853
|
-
return paths;
|
|
41839
|
+
var getLegacyTeamBaseDir = () => {
|
|
41840
|
+
return import_path16.default.join(getDuclawHomeDir(), "team");
|
|
41854
41841
|
};
|
|
41855
|
-
var
|
|
41856
|
-
return
|
|
41842
|
+
var getDepartmentWorkSpaceDir = (departmentName) => {
|
|
41843
|
+
return import_path16.default.join(getDepartmentBaseDir(), "workspace", departmentName);
|
|
41857
41844
|
};
|
|
41858
|
-
var
|
|
41859
|
-
|
|
41860
|
-
|
|
41861
|
-
|
|
41862
|
-
|
|
41863
|
-
|
|
41864
|
-
|
|
41865
|
-
|
|
41866
|
-
|
|
41867
|
-
|
|
41868
|
-
|
|
41869
|
-
|
|
41870
|
-
|
|
41871
|
-
|
|
41872
|
-
|
|
41873
|
-
|
|
41874
|
-
|
|
41875
|
-
|
|
41876
|
-
|
|
41877
|
-
|
|
41878
|
-
|
|
41879
|
-
|
|
41880
|
-
|
|
41881
|
-
const projectSkillsPath = getProjectSkillsPath();
|
|
41882
|
-
const normalizedSkillDir = import_path16.default.resolve(skillDir);
|
|
41883
|
-
const deletable = projectSkillsPath ? normalizedSkillDir === import_path16.default.resolve(projectSkillsPath, import_path16.default.basename(normalizedSkillDir)) && normalizedSkillDir.startsWith(import_path16.default.resolve(projectSkillsPath) + import_path16.default.sep) : false;
|
|
41845
|
+
var getLegacyTeamWorkSpaceDir = (teamName) => {
|
|
41846
|
+
return import_path16.default.join(getLegacyTeamBaseDir(), "workspace", teamName);
|
|
41847
|
+
};
|
|
41848
|
+
var getDepartmentJsonPath = (departmentName) => {
|
|
41849
|
+
return import_path16.default.join(getDepartmentWorkSpaceDir(departmentName), "department.json");
|
|
41850
|
+
};
|
|
41851
|
+
var getLegacyTeamJsonPath = (teamName) => {
|
|
41852
|
+
return import_path16.default.join(getLegacyTeamWorkSpaceDir(teamName), "team.json");
|
|
41853
|
+
};
|
|
41854
|
+
var mapLegacyRole = (role) => {
|
|
41855
|
+
return role === "team_manager" ? "department_head" : "executor";
|
|
41856
|
+
};
|
|
41857
|
+
var mapLegacyDepartment = (legacy) => {
|
|
41858
|
+
const departmentMembers = (legacy.teamMembers ?? []).map((member) => ({
|
|
41859
|
+
id: member.id,
|
|
41860
|
+
name: member.name,
|
|
41861
|
+
departmentId: legacy.id,
|
|
41862
|
+
mailBoxId: member.mailBoxId,
|
|
41863
|
+
workspaceId: member.workspaceId,
|
|
41864
|
+
role: mapLegacyRole(member.role),
|
|
41865
|
+
focusOn: member.focusOn
|
|
41866
|
+
}));
|
|
41867
|
+
const headMemberId = legacy.managerMemberId ?? departmentMembers.find((member) => member.role === "department_head")?.id;
|
|
41884
41868
|
return {
|
|
41885
|
-
|
|
41886
|
-
|
|
41887
|
-
|
|
41888
|
-
|
|
41889
|
-
|
|
41890
|
-
|
|
41891
|
-
|
|
41892
|
-
|
|
41893
|
-
${content}`;
|
|
41894
|
-
}
|
|
41869
|
+
id: legacy.id,
|
|
41870
|
+
name: legacy.name,
|
|
41871
|
+
sourceGoalId: legacy.goalId,
|
|
41872
|
+
charter: legacy.goalId ? `Legacy department migrated from team goal ${legacy.goalId}.` : "Legacy department migrated from team data.",
|
|
41873
|
+
workpath: legacy.workpath,
|
|
41874
|
+
headMemberId,
|
|
41875
|
+
departmentMembers
|
|
41895
41876
|
};
|
|
41896
41877
|
};
|
|
41897
|
-
var
|
|
41898
|
-
|
|
41899
|
-
|
|
41900
|
-
const
|
|
41901
|
-
|
|
41902
|
-
for (const
|
|
41903
|
-
const
|
|
41904
|
-
|
|
41905
|
-
|
|
41906
|
-
|
|
41907
|
-
|
|
41908
|
-
|
|
41909
|
-
|
|
41910
|
-
|
|
41911
|
-
|
|
41878
|
+
var migrateLegacyTeamsToDepartments = () => {
|
|
41879
|
+
if (legacyMigrationChecked) return;
|
|
41880
|
+
legacyMigrationChecked = true;
|
|
41881
|
+
const legacyWorkspaceDir = import_path16.default.join(getLegacyTeamBaseDir(), "workspace");
|
|
41882
|
+
if (!(0, import_fs11.existsSync)(legacyWorkspaceDir)) return;
|
|
41883
|
+
for (const legacyName of (0, import_fs11.readdirSync)(legacyWorkspaceDir)) {
|
|
41884
|
+
const legacyJsonPath = getLegacyTeamJsonPath(legacyName);
|
|
41885
|
+
if (!(0, import_fs11.existsSync)(legacyJsonPath)) continue;
|
|
41886
|
+
const departmentJsonPath = getDepartmentJsonPath(legacyName);
|
|
41887
|
+
if ((0, import_fs11.existsSync)(departmentJsonPath)) continue;
|
|
41888
|
+
try {
|
|
41889
|
+
const legacy = JSON.parse((0, import_fs11.readFileSync)(legacyJsonPath, "utf-8"));
|
|
41890
|
+
const department = mapLegacyDepartment(legacy);
|
|
41891
|
+
(0, import_fs11.mkdirSync)(getDepartmentWorkSpaceDir(department.name), { recursive: true });
|
|
41892
|
+
(0, import_fs11.writeFileSync)(departmentJsonPath, JSON.stringify(department, null, " "), "utf-8");
|
|
41893
|
+
} catch (err) {
|
|
41894
|
+
console.warn(`[department] Failed to migrate legacy team ${legacyName}: ${err.message}`);
|
|
41912
41895
|
}
|
|
41913
41896
|
}
|
|
41914
|
-
return skills;
|
|
41915
41897
|
};
|
|
41916
|
-
var
|
|
41917
|
-
|
|
41918
|
-
const
|
|
41919
|
-
|
|
41920
|
-
(0, import_fs11.
|
|
41921
|
-
return
|
|
41898
|
+
var createDepartment = (departmentDefinition) => {
|
|
41899
|
+
if (!departmentDefinition) throw new Error(`[createDepartment] departmentDefinition\u4E0D\u80FD\u4E3A\u7A7A`);
|
|
41900
|
+
const departmentPath = getDepartmentWorkSpaceDir(departmentDefinition.name);
|
|
41901
|
+
(0, import_fs11.mkdirSync)(departmentPath, { recursive: true });
|
|
41902
|
+
(0, import_fs11.writeFileSync)(getDepartmentJsonPath(departmentDefinition.name), JSON.stringify(departmentDefinition, null, " "), "utf-8");
|
|
41903
|
+
return departmentDefinition;
|
|
41922
41904
|
};
|
|
41923
|
-
var
|
|
41924
|
-
|
|
41925
|
-
|
|
41926
|
-
|
|
41927
|
-
const
|
|
41928
|
-
|
|
41929
|
-
const skillXmls = skills.map((skill) => {
|
|
41930
|
-
return [
|
|
41931
|
-
" <skill>",
|
|
41932
|
-
` <name>${skill.name}</name>`,
|
|
41933
|
-
` <description>`,
|
|
41934
|
-
` ${skill.description}`,
|
|
41935
|
-
` </description>`,
|
|
41936
|
-
` <location>user</location>`,
|
|
41937
|
-
" </skill>"
|
|
41938
|
-
].join("\n");
|
|
41939
|
-
});
|
|
41940
|
-
return [
|
|
41941
|
-
"<available_skills>",
|
|
41942
|
-
...skillXmls,
|
|
41943
|
-
"</available_skills>"
|
|
41944
|
-
].join("\n");
|
|
41905
|
+
var getDepartment = (name) => {
|
|
41906
|
+
migrateLegacyTeamsToDepartments();
|
|
41907
|
+
const departmentJsonPath = getDepartmentJsonPath(name);
|
|
41908
|
+
if (!(0, import_fs11.existsSync)(departmentJsonPath)) return null;
|
|
41909
|
+
const text2 = (0, import_fs11.readFileSync)(departmentJsonPath, "utf-8");
|
|
41910
|
+
return JSON.parse(text2);
|
|
41945
41911
|
};
|
|
41946
|
-
var
|
|
41947
|
-
|
|
41948
|
-
|
|
41949
|
-
|
|
41950
|
-
|
|
41951
|
-
|
|
41912
|
+
var listDepartments = () => {
|
|
41913
|
+
migrateLegacyTeamsToDepartments();
|
|
41914
|
+
const workspaceDir = import_path16.default.join(getDepartmentBaseDir(), "workspace");
|
|
41915
|
+
if (!(0, import_fs11.existsSync)(workspaceDir)) return [];
|
|
41916
|
+
const departments = [];
|
|
41917
|
+
for (const departmentName of (0, import_fs11.readdirSync)(workspaceDir)) {
|
|
41918
|
+
const department = getDepartment(departmentName);
|
|
41919
|
+
if (department) departments.push(department);
|
|
41952
41920
|
}
|
|
41953
|
-
return
|
|
41921
|
+
return departments;
|
|
41922
|
+
};
|
|
41923
|
+
var getDepartmentById = (id) => {
|
|
41924
|
+
const department = listDepartments().find((item) => item.id === id);
|
|
41925
|
+
return department ?? null;
|
|
41926
|
+
};
|
|
41927
|
+
var deleteDepartment = (name) => {
|
|
41928
|
+
if (!(0, import_fs11.existsSync)(getDepartmentJsonPath(name))) {
|
|
41929
|
+
throw new Error(`[deleteDepartment] \u4E0D\u5B58\u5728\u5BF9\u5E94\u7684\u90E8\u95E8 ${name} \u7684 department.json \u6587\u4EF6`);
|
|
41930
|
+
}
|
|
41931
|
+
(0, import_fs11.rmSync)(getDepartmentJsonPath(name));
|
|
41954
41932
|
};
|
|
41955
41933
|
|
|
41956
|
-
// src/
|
|
41957
|
-
var
|
|
41958
|
-
|
|
41959
|
-
|
|
41960
|
-
<skills_instructions>
|
|
41961
|
-
When users ask you to perform tasks, check if any of the available skills
|
|
41962
|
-
below can help complete the task more effectively. Skills provide specialized
|
|
41963
|
-
capabilities and domain knowledge.
|
|
41964
|
-
|
|
41965
|
-
How to use skills:
|
|
41966
|
-
- Invoke skills using this tool with the skill name only (no arguments)
|
|
41967
|
-
- When you invoke a skill, you will see <command-message>The "{name}" skill is loading</command-message>
|
|
41968
|
-
- The skill's prompt will expand and provide detailed instructions on how to complete the task
|
|
41969
|
-
- Examples:
|
|
41970
|
-
- \`command: "pdf"\` - invoke the pdf skill
|
|
41971
|
-
- \`command: "xlsx"\` - invoke the xlsx skill
|
|
41972
|
-
- \`command: "ms-office-suite:pdf"\` - invoke using fully qualified name
|
|
41973
|
-
|
|
41974
|
-
Important:
|
|
41975
|
-
- Only use skills listed in <available_skills> below
|
|
41976
|
-
- Do not invoke a skill that is already running
|
|
41977
|
-
- Do not use this tool for built-in CLI commands (like /help, /clear, etc.)
|
|
41978
|
-
</skills_instructions>
|
|
41979
|
-
|
|
41980
|
-
${getSkillMeta()}
|
|
41981
|
-
`;
|
|
41982
|
-
var skillTool = {
|
|
41983
|
-
name: `skill`,
|
|
41984
|
-
description: DESCRIPTION15,
|
|
41985
|
-
input_schema: {
|
|
41986
|
-
type: `object`,
|
|
41987
|
-
properties: {
|
|
41988
|
-
command: {
|
|
41989
|
-
type: `string`,
|
|
41990
|
-
description: `The skill name (no arguments). E.g., "pdf" or "xlsx"`
|
|
41991
|
-
}
|
|
41992
|
-
},
|
|
41993
|
-
required: [`command`]
|
|
41994
|
-
},
|
|
41995
|
-
async execute(input, userRequest) {
|
|
41996
|
-
console.log(`[\u6267\u884C\u5DE5\u5177]${input.command} skill`);
|
|
41997
|
-
const command = input.command;
|
|
41998
|
-
const detail = getSkillDetail(command);
|
|
41999
|
-
if (!detail) return `<command-message> skill name: \u201C${command}\u201D \u4E0D\u5B58\u5728</command-message>
|
|
42000
|
-
<command-name>${command}</command-name>`;
|
|
42001
|
-
const skillXml = `
|
|
42002
|
-
<command-message>The "${command}" skill is running</command-message>
|
|
41934
|
+
// src/department/learning.ts
|
|
41935
|
+
var import_node_fs4 = require("node:fs");
|
|
41936
|
+
var import_node_path13 = __toESM(require("node:path"));
|
|
41937
|
+
var import_node_crypto4 = require("node:crypto");
|
|
42003
41938
|
|
|
42004
|
-
|
|
41939
|
+
// src/department/DepartmentMember.ts
|
|
41940
|
+
var import_fs12 = require("fs");
|
|
41941
|
+
var import_path17 = __toESM(require("path"));
|
|
42005
41942
|
|
|
42006
|
-
|
|
42007
|
-
|
|
42008
|
-
|
|
42009
|
-
}
|
|
41943
|
+
// src/department/workspace/workspace.ts
|
|
41944
|
+
var db = createSqliteDB();
|
|
41945
|
+
var getWorkspaceId = (departmentName, memberName) => {
|
|
41946
|
+
return `${departmentName}::${memberName}`;
|
|
41947
|
+
};
|
|
41948
|
+
var createWorkspace = (workspace) => {
|
|
41949
|
+
const stmt = db.prepare(`INSERT INTO workspace (id, team_name, teammate_name, team_workpath) VALUES (?, ?, ?, ?) `);
|
|
41950
|
+
stmt.run(
|
|
41951
|
+
workspace.id,
|
|
41952
|
+
workspace.departmentName,
|
|
41953
|
+
workspace.memberName,
|
|
41954
|
+
workspace.departmentWorkPath
|
|
41955
|
+
);
|
|
41956
|
+
};
|
|
41957
|
+
var deleteWorkspace = (workspaceId) => {
|
|
41958
|
+
const stmt = db.prepare(`delete from workspace where id = ?`);
|
|
41959
|
+
stmt.run(workspaceId);
|
|
42010
41960
|
};
|
|
42011
41961
|
|
|
42012
|
-
// src/
|
|
42013
|
-
var
|
|
42014
|
-
|
|
42015
|
-
|
|
42016
|
-
|
|
42017
|
-
|
|
42018
|
-
|
|
42019
|
-
|
|
42020
|
-
|
|
42021
|
-
|
|
42022
|
-
|
|
42023
|
-
|
|
42024
|
-
|
|
42025
|
-
|
|
42026
|
-
|
|
42027
|
-
|
|
42028
|
-
|
|
42029
|
-
},
|
|
42030
|
-
async execute(input, userRequest) {
|
|
42031
|
-
const subject = input.subject;
|
|
42032
|
-
const description = input.description;
|
|
42033
|
-
const taskGoal = await createGoal(subject, description);
|
|
42034
|
-
if (userRequest) {
|
|
42035
|
-
ensureGoalConversationContext(taskGoal.id, {
|
|
42036
|
-
threadId: userRequest.userId,
|
|
42037
|
-
originPlatform: userRequest.platform,
|
|
42038
|
-
originUserId: userRequest.userId,
|
|
42039
|
-
syncReplyToOrigin: userRequest.platform === "feishu"
|
|
42040
|
-
});
|
|
42041
|
-
}
|
|
42042
|
-
if (taskGoal) {
|
|
42043
|
-
return `[GoalCreate] \u521B\u5EFA\u4EFB\u52A1\u76EE\u6807\u6210\u529F: ${JSON.stringify(taskGoal)}`;
|
|
42044
|
-
}
|
|
42045
|
-
return `[GoalCreate] \u521B\u5EFA\u4EFB\u52A1\u76EE\u6807\u5931\u8D25: ${taskGoal}`;
|
|
41962
|
+
// src/department/DepartmentMember.ts
|
|
41963
|
+
var createDepartmentMember = (departmentMemberDefinition) => {
|
|
41964
|
+
if (!departmentMemberDefinition) throw new Error(`[createDepartmentMember] departmentMemberDefinition\u4E0D\u80FD\u4E3A\u7A7A`);
|
|
41965
|
+
const { name, departmentId, workspaceId } = departmentMemberDefinition;
|
|
41966
|
+
const department = getDepartmentById(departmentId);
|
|
41967
|
+
if (!department) throw new Error(`[createDepartmentMember] \u627E\u4E0D\u5230\u5BF9\u5E94\u7684 department: ${departmentId}`);
|
|
41968
|
+
const memberPath = import_path17.default.join(getDepartmentWorkSpaceDir(department.name), name);
|
|
41969
|
+
(0, import_fs12.mkdirSync)(memberPath, { recursive: true });
|
|
41970
|
+
const workspace = {
|
|
41971
|
+
id: getWorkspaceId(department.name, departmentMemberDefinition.name),
|
|
41972
|
+
departmentName: department.name,
|
|
41973
|
+
memberName: name,
|
|
41974
|
+
departmentWorkPath: memberPath
|
|
41975
|
+
};
|
|
41976
|
+
createWorkspace(workspace);
|
|
41977
|
+
if (!department.departmentMembers) {
|
|
41978
|
+
department.departmentMembers = [];
|
|
42046
41979
|
}
|
|
42047
|
-
|
|
42048
|
-
|
|
42049
|
-
// src/tools/tools/tasks/GoalGet.ts
|
|
42050
|
-
var DESCRIPTION16 = `
|
|
42051
|
-
\u83B7\u53D6\u4EFB\u52A1\u7CFB\u7EDF\u4E2D\u6307\u5B9A\u7684Goal
|
|
42052
|
-
`;
|
|
42053
|
-
var goalGet = {
|
|
42054
|
-
name: `goal_get`,
|
|
42055
|
-
description: DESCRIPTION16,
|
|
42056
|
-
input_schema: {
|
|
42057
|
-
type: `object`,
|
|
42058
|
-
properties: {
|
|
42059
|
-
id: {
|
|
42060
|
-
type: `string`,
|
|
42061
|
-
description: `\u6839\u636Eid\u83B7\u53D6\u6307\u5B9A\u76EE\u6807,\u53EF\u9009`
|
|
42062
|
-
},
|
|
42063
|
-
subject: {
|
|
42064
|
-
type: `string`,
|
|
42065
|
-
description: `\u6839\u636Esubject\u83B7\u53D6\u7279\u5B9A\u76EE\u6807,\u53EF\u9009`
|
|
42066
|
-
}
|
|
42067
|
-
}
|
|
42068
|
-
},
|
|
42069
|
-
async execute(input, userRequest) {
|
|
42070
|
-
const id = input.id;
|
|
42071
|
-
const subject = input.subject;
|
|
42072
|
-
let goal = void 0;
|
|
42073
|
-
if (id) {
|
|
42074
|
-
goal = getGoalById(id);
|
|
42075
|
-
} else if (subject) {
|
|
42076
|
-
goal = getGoalBySubject(subject);
|
|
42077
|
-
}
|
|
42078
|
-
if (!goal) {
|
|
42079
|
-
return `[GetGoal] \u627E\u4E0D\u5230\u6307\u5B9A\u7684\u76EE\u6807`;
|
|
42080
|
-
}
|
|
42081
|
-
return `[GetGoal] \u627E\u5230\u76EE\u6807: ${JSON.stringify(goal)}`;
|
|
41980
|
+
if (department.departmentMembers.some((member) => member.id === departmentMemberDefinition.id || member.name === departmentMemberDefinition.name)) {
|
|
41981
|
+
throw new Error(`[createDepartmentMember] \u90E8\u95E8 ${department.name} \u5DF2\u5B58\u5728\u540C\u540D\u6216\u540C id \u6210\u5458: ${departmentMemberDefinition.name}/${departmentMemberDefinition.id}`);
|
|
42082
41982
|
}
|
|
42083
|
-
|
|
42084
|
-
|
|
42085
|
-
|
|
42086
|
-
|
|
42087
|
-
\u5728\u4EFB\u52A1\u7CFB\u7EDF\u4E2D\u5217\u51FA\u6240\u6709\u76EE\u6807
|
|
42088
|
-
`;
|
|
42089
|
-
var goalList = {
|
|
42090
|
-
name: `goal_list`,
|
|
42091
|
-
description: DESCRIPTION17,
|
|
42092
|
-
input_schema: {
|
|
42093
|
-
type: `object`,
|
|
42094
|
-
properties: {}
|
|
42095
|
-
},
|
|
42096
|
-
async execute(input, userRequest) {
|
|
42097
|
-
const goals = listGoal();
|
|
42098
|
-
if (goals.length > 0) {
|
|
42099
|
-
return `[GoalList]goals\u5217\u8868: ${JSON.stringify(goals)}`;
|
|
41983
|
+
if (departmentMemberDefinition.role === "department_head") {
|
|
41984
|
+
const existingHead = department.headMemberId ? department.departmentMembers.find((member) => member.id === department.headMemberId) : department.departmentMembers.find((member) => member.role === "department_head");
|
|
41985
|
+
if (existingHead) {
|
|
41986
|
+
throw new Error(`[createDepartmentMember] \u90E8\u95E8 ${department.name} \u5DF2\u5B58\u5728 Department Head: ${existingHead.name}`);
|
|
42100
41987
|
}
|
|
42101
|
-
|
|
41988
|
+
department.headMemberId = departmentMemberDefinition.id;
|
|
42102
41989
|
}
|
|
41990
|
+
department.departmentMembers.push(departmentMemberDefinition);
|
|
41991
|
+
(0, import_fs12.writeFileSync)(getDepartmentJsonPath(department.name), JSON.stringify(department, null, " "), "utf-8");
|
|
41992
|
+
return departmentMemberDefinition;
|
|
42103
41993
|
};
|
|
42104
|
-
|
|
42105
|
-
|
|
42106
|
-
|
|
42107
|
-
|
|
42108
|
-
|
|
42109
|
-
\
|
|
42110
|
-
|
|
42111
|
-
|
|
42112
|
-
|
|
42113
|
-
|
|
42114
|
-
|
|
42115
|
-
|
|
42116
|
-
|
|
42117
|
-
|
|
42118
|
-
|
|
42119
|
-
|
|
42120
|
-
|
|
42121
|
-
|
|
42122
|
-
|
|
42123
|
-
|
|
42124
|
-
|
|
42125
|
-
|
|
42126
|
-
|
|
42127
|
-
|
|
42128
|
-
|
|
42129
|
-
description: `\u66F4\u65B0\u540E\u7684goal\u7684\u8BE6\u7EC6\u8BF4\u660E`
|
|
42130
|
-
},
|
|
42131
|
-
status: {
|
|
42132
|
-
type: `string`,
|
|
42133
|
-
description: `pending | in_progress | completed | failed`,
|
|
42134
|
-
enum: [`pending`, `in_progress`, `completed`, `failed`]
|
|
42135
|
-
}
|
|
42136
|
-
},
|
|
42137
|
-
required: [`id`]
|
|
42138
|
-
},
|
|
42139
|
-
async execute(input, userRequest) {
|
|
42140
|
-
const id = input.id;
|
|
42141
|
-
const subject = input.subject;
|
|
42142
|
-
const description = input.description;
|
|
42143
|
-
const status = input.status;
|
|
42144
|
-
const validStatuses = ["pending", "in_progress", "completed", "failed"];
|
|
42145
|
-
if (status && !validStatuses.includes(status)) {
|
|
42146
|
-
return `[UpdateGoal] status\u53C2\u6570\u9519\u8BEF,status\u5FC5\u987B\u8981\u662F pending | in_progress | completed | failed \u4E2D\u7684\u4EFB\u610F\u4E00\u4E2A`;
|
|
42147
|
-
}
|
|
42148
|
-
const goal = getGoalById(id);
|
|
42149
|
-
if (!goal) {
|
|
42150
|
-
return `[UpdateGoal] \u627E\u4E0D\u5230\u6307\u5B9Aid\u7684\u76EE\u6807`;
|
|
42151
|
-
}
|
|
42152
|
-
const updatedGoal = {
|
|
42153
|
-
...goal,
|
|
42154
|
-
subject: subject || goal.subject,
|
|
42155
|
-
description: description !== void 0 ? description : goal.description,
|
|
42156
|
-
status: status || goal.status,
|
|
42157
|
-
updateAt: getDate()
|
|
42158
|
-
};
|
|
42159
|
-
try {
|
|
42160
|
-
updateGoal(id, updatedGoal);
|
|
42161
|
-
} catch (err) {
|
|
42162
|
-
if (err instanceof GoalCompletionBlockedError) {
|
|
42163
|
-
return err.message;
|
|
42164
|
-
}
|
|
42165
|
-
throw err;
|
|
42166
|
-
}
|
|
42167
|
-
return `[UpdateGoal] \u66F4\u65B0\u76EE\u6807\u6210\u529F: ${JSON.stringify(updatedGoal)}`;
|
|
41994
|
+
var listDepartmentMembers = (departmentName) => {
|
|
41995
|
+
const departmentJsonPath = getDepartmentJsonPath(departmentName);
|
|
41996
|
+
if (!(0, import_fs12.existsSync)(departmentJsonPath)) return [];
|
|
41997
|
+
const text2 = (0, import_fs12.readFileSync)(departmentJsonPath, "utf-8");
|
|
41998
|
+
const department = JSON.parse(text2);
|
|
41999
|
+
if (!department) throw new Error(`[listDepartmentMembers] \u627E\u4E0D\u5230\u5BF9\u5E94\u7684 department: ${departmentName}`);
|
|
42000
|
+
return department.departmentMembers ?? [];
|
|
42001
|
+
};
|
|
42002
|
+
var getDepartmentMember = (departmentName, departmentMemberId) => {
|
|
42003
|
+
const members = listDepartmentMembers(departmentName);
|
|
42004
|
+
return members.find((member) => member.id === departmentMemberId) || null;
|
|
42005
|
+
};
|
|
42006
|
+
var getDepartmentMemberByName = (departmentName, departmentMemberName) => {
|
|
42007
|
+
const members = listDepartmentMembers(departmentName);
|
|
42008
|
+
return members.find((member) => member.name === departmentMemberName) || null;
|
|
42009
|
+
};
|
|
42010
|
+
var getDepartmentMemberByMailboxId = (mailboxId) => {
|
|
42011
|
+
const [departmentName, memberName] = mailboxId.split("::");
|
|
42012
|
+
if (!departmentName || !memberName) return null;
|
|
42013
|
+
return getDepartmentMemberByName(departmentName, memberName);
|
|
42014
|
+
};
|
|
42015
|
+
var getDepartmentMemberById = (memberId) => {
|
|
42016
|
+
for (const department of listDepartments()) {
|
|
42017
|
+
const targetMember = department.departmentMembers.find((member) => member.id === memberId);
|
|
42018
|
+
if (targetMember) return targetMember;
|
|
42168
42019
|
}
|
|
42020
|
+
return null;
|
|
42169
42021
|
};
|
|
42170
|
-
|
|
42171
|
-
|
|
42172
|
-
|
|
42173
|
-
|
|
42174
|
-
|
|
42175
|
-
\
|
|
42176
|
-
|
|
42177
|
-
|
|
42178
|
-
|
|
42179
|
-
|
|
42180
|
-
name: `goal_delete`,
|
|
42181
|
-
description: DESCRIPTION19,
|
|
42182
|
-
input_schema: {
|
|
42183
|
-
type: `object`,
|
|
42184
|
-
properties: {
|
|
42185
|
-
id: {
|
|
42186
|
-
type: `string`,
|
|
42187
|
-
description: `\u8981\u5220\u9664\u7684\u76EE\u6807ID`
|
|
42188
|
-
}
|
|
42189
|
-
},
|
|
42190
|
-
required: [`id`]
|
|
42191
|
-
},
|
|
42192
|
-
async execute(input, userRequest) {
|
|
42193
|
-
const id = input.id;
|
|
42194
|
-
const goal = getGoalById(id);
|
|
42195
|
-
if (!goal) {
|
|
42196
|
-
return `[GoalDelete] \u627E\u4E0D\u5230\u6307\u5B9Aid\u7684\u76EE\u6807`;
|
|
42197
|
-
}
|
|
42198
|
-
const deleted = deleteGoal(id);
|
|
42199
|
-
if (deleted) {
|
|
42200
|
-
return `[GoalDelete] \u76EE\u6807\u5DF2\u5220\u9664: id=${id}, subject=${goal.subject}`;
|
|
42201
|
-
}
|
|
42202
|
-
return `[GoalDelete] \u5220\u9664\u76EE\u6807\u5931\u8D25: id=${id}`;
|
|
42022
|
+
var deleteDepartmentMemberById = (departmentName, memberId) => {
|
|
42023
|
+
const department = getDepartment(departmentName);
|
|
42024
|
+
if (!department) throw new Error(`[deleteDepartmentMemberById] \u627E\u4E0D\u5230\u5BF9\u5E94\u7684 department: ${departmentName}`);
|
|
42025
|
+
const memberIdx = department.departmentMembers.findIndex((member) => member.id === memberId);
|
|
42026
|
+
if (memberIdx === -1) {
|
|
42027
|
+
throw new Error(`[deleteDepartmentMemberById] \u627E\u4E0D\u5230\u5BF9\u5E94 id \u7684 department member: ${memberId}`);
|
|
42028
|
+
}
|
|
42029
|
+
const workspaceId = department.departmentMembers[memberIdx].workspaceId;
|
|
42030
|
+
if (department.headMemberId === memberId) {
|
|
42031
|
+
delete department.headMemberId;
|
|
42203
42032
|
}
|
|
42033
|
+
department.departmentMembers = department.departmentMembers.filter((_, index) => index !== memberIdx);
|
|
42034
|
+
(0, import_fs12.writeFileSync)(getDepartmentJsonPath(departmentName), JSON.stringify(department, null, " "), "utf-8");
|
|
42035
|
+
deleteWorkspace(workspaceId);
|
|
42204
42036
|
};
|
|
42205
42037
|
|
|
42206
|
-
// src/
|
|
42207
|
-
var
|
|
42208
|
-
|
|
42209
|
-
|
|
42210
|
-
var
|
|
42211
|
-
|
|
42212
|
-
|
|
42213
|
-
|
|
42214
|
-
var
|
|
42215
|
-
const
|
|
42216
|
-
if (
|
|
42217
|
-
|
|
42218
|
-
return;
|
|
42038
|
+
// src/skill/SkillValidator.ts
|
|
42039
|
+
var import_node_fs3 = require("node:fs");
|
|
42040
|
+
var import_node_path12 = __toESM(require("node:path"));
|
|
42041
|
+
var SKILL_NAME_PATTERN = /^[a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?$/;
|
|
42042
|
+
var REQUIRED_SECTIONS = [
|
|
42043
|
+
/(^|\n)##\s+(when to use|何时使用|trigger|triggers)\b/i,
|
|
42044
|
+
/(^|\n)##\s+(steps|workflow|procedure|执行步骤|工作流)\b/i
|
|
42045
|
+
];
|
|
42046
|
+
var stripYamlQuotes = (value) => {
|
|
42047
|
+
const trimmed = value.trim();
|
|
42048
|
+
if (trimmed.startsWith(`"`) && trimmed.endsWith(`"`) || trimmed.startsWith(`'`) && trimmed.endsWith(`'`)) {
|
|
42049
|
+
return trimmed.slice(1, -1).trim();
|
|
42219
42050
|
}
|
|
42220
|
-
|
|
42051
|
+
return trimmed;
|
|
42221
42052
|
};
|
|
42222
|
-
var
|
|
42223
|
-
|
|
42053
|
+
var addError = (errors, code, message) => {
|
|
42054
|
+
errors.push({ code, message });
|
|
42224
42055
|
};
|
|
42225
|
-
var
|
|
42226
|
-
|
|
42056
|
+
var addWarning = (warnings, code, message) => {
|
|
42057
|
+
warnings.push({ code, message });
|
|
42227
42058
|
};
|
|
42228
|
-
var
|
|
42229
|
-
|
|
42230
|
-
|
|
42231
|
-
|
|
42232
|
-
|
|
42233
|
-
|
|
42234
|
-
for (const listener of entry.listeners) {
|
|
42235
|
-
try {
|
|
42236
|
-
listener();
|
|
42237
|
-
} catch (err) {
|
|
42238
|
-
console.warn(`[interrupt] \u7528\u6237 ${userId} \u4E2D\u65AD\u76D1\u542C\u5668\u6267\u884C\u5931\u8D25: ${err.message}`);
|
|
42239
|
-
}
|
|
42059
|
+
var isValidSkillName = (name) => {
|
|
42060
|
+
return SKILL_NAME_PATTERN.test(name) && !name.includes(`--`);
|
|
42061
|
+
};
|
|
42062
|
+
var assertSafeSkillTarget = (rootDir, skillName) => {
|
|
42063
|
+
if (!isValidSkillName(skillName)) {
|
|
42064
|
+
throw new Error(`Invalid skill name "${skillName}". Use lowercase letters, digits, and single hyphens only.`);
|
|
42240
42065
|
}
|
|
42241
|
-
|
|
42066
|
+
const root = import_node_path12.default.resolve(rootDir);
|
|
42067
|
+
const target = import_node_path12.default.resolve(root, skillName);
|
|
42068
|
+
if (target !== import_node_path12.default.join(root, skillName) || !target.startsWith(root + import_node_path12.default.sep)) {
|
|
42069
|
+
throw new Error(`Invalid skill install target for "${skillName}".`);
|
|
42070
|
+
}
|
|
42071
|
+
return target;
|
|
42242
42072
|
};
|
|
42243
|
-
var
|
|
42244
|
-
const
|
|
42245
|
-
if (!
|
|
42246
|
-
|
|
42247
|
-
|
|
42248
|
-
|
|
42073
|
+
var parseSkillDocument = (skillMd) => {
|
|
42074
|
+
const fmMatch = skillMd.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/);
|
|
42075
|
+
if (!fmMatch) return null;
|
|
42076
|
+
const frontmatter = {};
|
|
42077
|
+
for (const rawLine of fmMatch[1].split(/\r?\n/)) {
|
|
42078
|
+
const line = rawLine.trim();
|
|
42079
|
+
if (!line || line.startsWith(`#`)) continue;
|
|
42080
|
+
const match2 = line.match(/^([A-Za-z0-9_-]+):\s*(.*)$/);
|
|
42081
|
+
if (!match2) {
|
|
42082
|
+
frontmatter[`__invalid__${Object.keys(frontmatter).length}`] = line;
|
|
42083
|
+
continue;
|
|
42084
|
+
}
|
|
42085
|
+
frontmatter[match2[1]] = stripYamlQuotes(match2[2]);
|
|
42086
|
+
}
|
|
42087
|
+
return {
|
|
42088
|
+
name: frontmatter.name ?? ``,
|
|
42089
|
+
description: frontmatter.description ?? ``,
|
|
42090
|
+
body: skillMd.slice(fmMatch[0].length).trim(),
|
|
42091
|
+
frontmatter
|
|
42249
42092
|
};
|
|
42250
42093
|
};
|
|
42251
|
-
var
|
|
42252
|
-
const
|
|
42253
|
-
|
|
42254
|
-
const
|
|
42255
|
-
|
|
42256
|
-
|
|
42257
|
-
|
|
42094
|
+
var validateSkillDocument = (input) => {
|
|
42095
|
+
const errors = [];
|
|
42096
|
+
const warnings = [];
|
|
42097
|
+
const skillMd = input.skillMd;
|
|
42098
|
+
if (!skillMd || !skillMd.trim()) {
|
|
42099
|
+
addError(errors, `empty_skill_md`, `SKILL.md content is required.`);
|
|
42100
|
+
return { ok: false, errors, warnings };
|
|
42101
|
+
}
|
|
42102
|
+
const parsed = parseSkillDocument(skillMd);
|
|
42103
|
+
if (!parsed) {
|
|
42104
|
+
addError(errors, `missing_frontmatter`, `SKILL.md must start with YAML frontmatter delimited by "---".`);
|
|
42105
|
+
return { ok: false, errors, warnings };
|
|
42106
|
+
}
|
|
42107
|
+
const invalidFrontmatterLines = Object.keys(parsed.frontmatter).filter((key) => key.startsWith(`__invalid__`));
|
|
42108
|
+
if (invalidFrontmatterLines.length > 0) {
|
|
42109
|
+
addError(errors, `invalid_frontmatter`, `Frontmatter must contain simple "key: value" lines.`);
|
|
42110
|
+
}
|
|
42111
|
+
if (!parsed.name) {
|
|
42112
|
+
addError(errors, `missing_name`, `Frontmatter field "name" is required.`);
|
|
42113
|
+
} else if (!isValidSkillName(parsed.name)) {
|
|
42114
|
+
addError(errors, `invalid_name`, `Skill name "${parsed.name}" must be kebab-case, under 64 characters, and path-safe.`);
|
|
42115
|
+
}
|
|
42116
|
+
if (!parsed.description) {
|
|
42117
|
+
addError(errors, `missing_description`, `Frontmatter field "description" is required.`);
|
|
42118
|
+
} else if (parsed.description.length > 500) {
|
|
42119
|
+
addWarning(warnings, `long_description`, `Skill description is long; keep trigger metadata concise.`);
|
|
42120
|
+
}
|
|
42121
|
+
if (input.skillName && parsed.name && input.skillName !== parsed.name) {
|
|
42122
|
+
addError(errors, `name_mismatch`, `Input skillName "${input.skillName}" must match frontmatter name "${parsed.name}".`);
|
|
42123
|
+
}
|
|
42124
|
+
if (input.description && parsed.description && input.description !== parsed.description) {
|
|
42125
|
+
addError(errors, `description_mismatch`, `Input description must match frontmatter description.`);
|
|
42126
|
+
}
|
|
42127
|
+
if (!parsed.body) {
|
|
42128
|
+
addError(errors, `empty_body`, `SKILL.md body is required.`);
|
|
42129
|
+
} else {
|
|
42130
|
+
if (!/(^|\n)#\s+\S/.test(parsed.body)) {
|
|
42131
|
+
addWarning(warnings, `missing_title`, `Skill body should start with a Markdown H1 title.`);
|
|
42132
|
+
}
|
|
42133
|
+
for (const sectionPattern of REQUIRED_SECTIONS) {
|
|
42134
|
+
if (!sectionPattern.test(parsed.body)) {
|
|
42135
|
+
addWarning(warnings, `missing_recommended_section`, `Skill body should include when-to-use and execution workflow sections.`);
|
|
42136
|
+
break;
|
|
42137
|
+
}
|
|
42138
|
+
}
|
|
42139
|
+
}
|
|
42140
|
+
if (input.baseDir) {
|
|
42141
|
+
const normalizedBase = import_node_path12.default.resolve(input.baseDir);
|
|
42142
|
+
for (const match2 of parsed.body.matchAll(/\]\(([^)]+)\)/g)) {
|
|
42143
|
+
const href = match2[1].trim();
|
|
42144
|
+
if (!href || /^[a-z][a-z0-9+.-]*:/i.test(href) || href.startsWith(`#`)) continue;
|
|
42145
|
+
const target = import_node_path12.default.resolve(normalizedBase, href.split(`#`)[0]);
|
|
42146
|
+
if (!target.startsWith(normalizedBase + import_node_path12.default.sep) && target !== normalizedBase) {
|
|
42147
|
+
addError(errors, `unsafe_reference`, `Relative link "${href}" escapes the skill directory.`);
|
|
42148
|
+
} else if (!(0, import_node_fs3.existsSync)(target)) {
|
|
42149
|
+
addError(errors, `missing_reference`, `Relative link "${href}" does not exist in the skill directory.`);
|
|
42150
|
+
}
|
|
42151
|
+
}
|
|
42152
|
+
}
|
|
42153
|
+
return {
|
|
42154
|
+
ok: errors.length === 0,
|
|
42155
|
+
skill: parsed,
|
|
42156
|
+
errors,
|
|
42157
|
+
warnings
|
|
42158
|
+
};
|
|
42258
42159
|
};
|
|
42259
|
-
|
|
42260
|
-
|
|
42261
|
-
|
|
42262
|
-
var rowToEvent = (row) => ({
|
|
42263
|
-
id: row.id,
|
|
42264
|
-
userId: row.userId,
|
|
42265
|
-
type: row.type,
|
|
42266
|
-
source: row.source,
|
|
42267
|
-
sourceId: row.sourceId,
|
|
42268
|
-
status: row.status,
|
|
42269
|
-
payload: JSON.parse(row.payloadJson || "{}"),
|
|
42270
|
-
createdAt: row.createdAt,
|
|
42271
|
-
injectedAt: row.injectedAt ?? void 0,
|
|
42272
|
-
handledAt: row.handledAt ?? void 0,
|
|
42273
|
-
updatedAt: row.updatedAt
|
|
42274
|
-
});
|
|
42275
|
-
var recordAgentEvent = (input) => {
|
|
42276
|
-
const db3 = createSqliteDB();
|
|
42277
|
-
const now = Date.now();
|
|
42278
|
-
const id = `evt_${(0, import_node_crypto4.randomUUID)().slice(0, 12)}`;
|
|
42279
|
-
const payloadJson = JSON.stringify(input.payload);
|
|
42280
|
-
db3.prepare(`
|
|
42281
|
-
INSERT INTO agent_events (
|
|
42282
|
-
id, user_id, type, source, source_id, status, payload_json, created_at, updated_at
|
|
42283
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
42284
|
-
ON CONFLICT(type, source, source_id) DO UPDATE SET
|
|
42285
|
-
user_id = excluded.user_id,
|
|
42286
|
-
status = CASE
|
|
42287
|
-
WHEN agent_events.status IN ('handled', 'ignored') THEN agent_events.status
|
|
42288
|
-
ELSE excluded.status
|
|
42289
|
-
END,
|
|
42290
|
-
payload_json = excluded.payload_json,
|
|
42291
|
-
updated_at = excluded.updated_at
|
|
42292
|
-
`).run(
|
|
42293
|
-
id,
|
|
42294
|
-
input.userId,
|
|
42295
|
-
input.type,
|
|
42296
|
-
input.source,
|
|
42297
|
-
input.sourceId,
|
|
42298
|
-
input.status ?? "pending",
|
|
42299
|
-
payloadJson,
|
|
42300
|
-
now,
|
|
42301
|
-
now
|
|
42302
|
-
);
|
|
42303
|
-
const row = db3.prepare(`
|
|
42304
|
-
SELECT
|
|
42305
|
-
id,
|
|
42306
|
-
user_id as userId,
|
|
42307
|
-
type,
|
|
42308
|
-
source,
|
|
42309
|
-
source_id as sourceId,
|
|
42310
|
-
status,
|
|
42311
|
-
payload_json as payloadJson,
|
|
42312
|
-
created_at as createdAt,
|
|
42313
|
-
injected_at as injectedAt,
|
|
42314
|
-
handled_at as handledAt,
|
|
42315
|
-
updated_at as updatedAt
|
|
42316
|
-
FROM agent_events
|
|
42317
|
-
WHERE type = ? AND source = ? AND source_id = ?
|
|
42318
|
-
`).get(input.type, input.source, input.sourceId);
|
|
42319
|
-
return rowToEvent(row);
|
|
42160
|
+
var mergeIssues = (target, source) => {
|
|
42161
|
+
target.errors.push(...source.errors);
|
|
42162
|
+
target.warnings.push(...source.warnings);
|
|
42320
42163
|
};
|
|
42321
|
-
var
|
|
42322
|
-
const
|
|
42323
|
-
|
|
42324
|
-
|
|
42325
|
-
|
|
42326
|
-
|
|
42327
|
-
|
|
42328
|
-
source,
|
|
42329
|
-
source_id as sourceId,
|
|
42330
|
-
status,
|
|
42331
|
-
payload_json as payloadJson,
|
|
42332
|
-
created_at as createdAt,
|
|
42333
|
-
injected_at as injectedAt,
|
|
42334
|
-
handled_at as handledAt,
|
|
42335
|
-
updated_at as updatedAt
|
|
42336
|
-
FROM agent_events
|
|
42337
|
-
WHERE user_id = ?
|
|
42338
|
-
AND status IN ('pending', 'processing')
|
|
42339
|
-
ORDER BY created_at ASC
|
|
42340
|
-
LIMIT ?
|
|
42341
|
-
`).all(userId, limit);
|
|
42342
|
-
return rows.map(rowToEvent);
|
|
42164
|
+
var validateScriptsDirectory = (skillDir, warnings) => {
|
|
42165
|
+
const scriptsDir = import_node_path12.default.join(skillDir, `scripts`);
|
|
42166
|
+
if (!(0, import_node_fs3.existsSync)(scriptsDir)) return;
|
|
42167
|
+
const entries = (0, import_node_fs3.readdirSync)(scriptsDir, { withFileTypes: true }).filter((entry) => entry.isFile());
|
|
42168
|
+
if (entries.length === 0) {
|
|
42169
|
+
addWarning(warnings, `empty_scripts_dir`, `scripts/ exists but contains no files.`);
|
|
42170
|
+
}
|
|
42343
42171
|
};
|
|
42344
|
-
var
|
|
42345
|
-
|
|
42346
|
-
const
|
|
42347
|
-
const
|
|
42348
|
-
const
|
|
42349
|
-
|
|
42350
|
-
|
|
42351
|
-
|
|
42352
|
-
|
|
42353
|
-
|
|
42354
|
-
|
|
42355
|
-
|
|
42356
|
-
|
|
42357
|
-
|
|
42172
|
+
var validateSkillDirectory = (skillDir, options = {}) => {
|
|
42173
|
+
const errors = [];
|
|
42174
|
+
const warnings = [];
|
|
42175
|
+
const normalizedSkillDir = import_node_path12.default.resolve(skillDir);
|
|
42176
|
+
const skillMdPath = import_node_path12.default.join(normalizedSkillDir, `SKILL.md`);
|
|
42177
|
+
if (!(0, import_node_fs3.existsSync)(normalizedSkillDir) || !(0, import_node_fs3.statSync)(normalizedSkillDir).isDirectory()) {
|
|
42178
|
+
addError(errors, `missing_skill_dir`, `Skill directory does not exist: ${normalizedSkillDir}`);
|
|
42179
|
+
return { ok: false, errors, warnings, skillDir: normalizedSkillDir, skillMdPath };
|
|
42180
|
+
}
|
|
42181
|
+
if (!(0, import_node_fs3.existsSync)(skillMdPath) || !(0, import_node_fs3.statSync)(skillMdPath).isFile()) {
|
|
42182
|
+
addError(errors, `missing_skill_md`, `Skill directory must contain SKILL.md.`);
|
|
42183
|
+
return { ok: false, errors, warnings, skillDir: normalizedSkillDir, skillMdPath };
|
|
42184
|
+
}
|
|
42185
|
+
const raw2 = (0, import_node_fs3.readFileSync)(skillMdPath, `utf-8`);
|
|
42186
|
+
const documentResult = validateSkillDocument({
|
|
42187
|
+
skillName: options.expectedName ?? import_node_path12.default.basename(normalizedSkillDir),
|
|
42188
|
+
skillMd: raw2,
|
|
42189
|
+
baseDir: normalizedSkillDir
|
|
42358
42190
|
});
|
|
42359
|
-
|
|
42360
|
-
|
|
42361
|
-
|
|
42362
|
-
|
|
42363
|
-
|
|
42364
|
-
|
|
42365
|
-
|
|
42366
|
-
|
|
42367
|
-
|
|
42368
|
-
|
|
42369
|
-
updated_at = ?
|
|
42370
|
-
WHERE id = ?
|
|
42371
|
-
AND status IN ('pending', 'processing')
|
|
42372
|
-
`);
|
|
42373
|
-
const tx = db3.transaction((ids) => {
|
|
42374
|
-
for (const id of ids) stmt.run(status, now, now, id);
|
|
42375
|
-
});
|
|
42376
|
-
tx(eventIds);
|
|
42377
|
-
};
|
|
42378
|
-
var renderAgentEventReminder = (events) => {
|
|
42379
|
-
if (events.length === 0) return "";
|
|
42380
|
-
const lines = events.map((event) => {
|
|
42381
|
-
const owner = typeof event.payload.ownerMailboxId === "string" ? event.payload.ownerMailboxId : void 0;
|
|
42382
|
-
const mailboxMessageId = typeof event.payload.mailboxMessageId === "string" ? event.payload.mailboxMessageId : event.sourceId;
|
|
42383
|
-
const summary = typeof event.payload.summary === "string" ? event.payload.summary : typeof event.payload.contentPreview === "string" ? event.payload.contentPreview : "";
|
|
42384
|
-
return [
|
|
42385
|
-
`- eventId=${event.id}`,
|
|
42386
|
-
`type=${event.type}`,
|
|
42387
|
-
owner ? `owner=${owner}` : "",
|
|
42388
|
-
mailboxMessageId ? `mailboxMessageId=${mailboxMessageId}` : "",
|
|
42389
|
-
summary ? `summary=${summary}` : ""
|
|
42390
|
-
].filter(Boolean).join(" ");
|
|
42391
|
-
}).join("\n");
|
|
42392
|
-
const hasCeoFollowup = events.some((event) => event.type === "ceo.followup_required");
|
|
42393
|
-
const ceoFollowupInstruction = hasCeoFollowup ? [
|
|
42394
|
-
``,
|
|
42395
|
-
`\u5176\u4E2D type=ceo.followup_required \u7684\u4E8B\u4EF6\uFF0C\u662F\u56E2\u961F\u5DF2\u7ECF\u628A\u7ED3\u679C\u56DE\u5230\u4E86\u4F60\u8FD9\u91CC\u2014\u2014\u8001\u677F\u8FD8\u5728\u7B49\u4F60\u628A\u8FD9\u4E9B\u7ED3\u679C\u8F6C\u8FBE\u7ED9\u4ED6\u3002`,
|
|
42396
|
-
`\u8BFB\u4E00\u904D\uFF0C\u7528\u4F60\u81EA\u5DF1\u7684\u8BDD\u7ED9\u8001\u677F\u6C47\u62A5\u4E00\u6B21\uFF1A\u6709\u591A\u6761\u5C31\u5408\u5E76\u6210\u4E00\u6761\u8BF4\u6E05\u695A\uFF0C\u522B\u4E00\u6761\u4E8B\u4EF6\u56DE\u4E00\u53E5\u3001\u628A\u540C\u4E00\u4EF6\u4E8B\u91CD\u590D\u53D1\u7ED9\u8001\u677F\u3002`,
|
|
42397
|
-
`\u5982\u679C\u7ED3\u679C\u8BF4\u660E\u4E8B\u60C5\u8FD8\u6CA1\u505A\u5B8C\u6216\u5361\u4F4F\u4E86\uFF0C\u5C31\u5982\u5B9E\u8FD9\u4E48\u8BB2\uFF0C\u800C\u4E0D\u662F\u542B\u7CCA\u5730\u201C\u7A0D\u540E\u540C\u6B65\u201D\u3002`
|
|
42398
|
-
].join("\n") : "";
|
|
42399
|
-
return `<system-reminder>
|
|
42400
|
-
\u672C\u8F6E\u6709 ${events.length} \u6761\u5185\u90E8\u4E8B\u4EF6\u53EF\u7528\uFF1A
|
|
42401
|
-
${lines}
|
|
42402
|
-
|
|
42403
|
-
\u8FD9\u4E9B\u4E8B\u4EF6\u4E0D\u662F\u7528\u6237\u7684\u65B0\u8BF7\u6C42\uFF0C\u4E5F\u4E0D\u5E94\u8BE5\u4F5C\u4E3A\u7528\u6237\u786E\u8BA4\u3002\u82E5\u4E8B\u4EF6\u7C7B\u578B\u662F mailbox.message_received\uFF0C\u8868\u793A\u4F60\u7684 mailbox \u5728\u5F53\u524D\u5DE5\u4F5C\u671F\u95F4\u6536\u5230\u65B0\u5185\u90E8\u534F\u4F5C\u6D88\u606F\uFF1B\u8BF7\u5C3D\u5FEB\u8C03\u7528 list_mailbox \u67E5\u770B\u961F\u5217\uFF0C\u5E76\u5728\u9700\u8981\u65F6\u7528 get_mailbox(message_id) \u9886\u53D6\u5173\u8054\u6D88\u606F\u3002\u4E0D\u8981\u76F4\u63A5\u628A\u4E8B\u4EF6\u5F53\u4F5C\u5DF2\u9886\u53D6\u90AE\u4EF6\u3002\u8BF7\u53EA\u5728\u9700\u8981\u65F6\u81EA\u7136\u5730\u6C47\u603B\u7ED9\u7528\u6237\uFF1B\u5982\u9700\u7EE7\u7EED\u534F\u4F5C\uFF0C\u4F18\u5148\u4F7F\u7528\u4E8B\u4EF6\u4E2D\u5173\u8054\u7684 mailboxMessageId/thread \u7EE7\u7EED\u5904\u7406\u3002\u4E0D\u8981\u590D\u8FF0\u672C system-reminder\u3002
|
|
42404
|
-
${ceoFollowupInstruction}
|
|
42405
|
-
</system-reminder>`;
|
|
42191
|
+
mergeIssues({ errors, warnings }, documentResult);
|
|
42192
|
+
validateScriptsDirectory(normalizedSkillDir, warnings);
|
|
42193
|
+
return {
|
|
42194
|
+
ok: errors.length === 0,
|
|
42195
|
+
skill: documentResult.skill,
|
|
42196
|
+
errors,
|
|
42197
|
+
warnings,
|
|
42198
|
+
skillDir: normalizedSkillDir,
|
|
42199
|
+
skillMdPath
|
|
42200
|
+
};
|
|
42406
42201
|
};
|
|
42202
|
+
var smokeTestSkillDirectory = (skillDir, options = {}) => {
|
|
42203
|
+
const directoryResult = validateSkillDirectory(skillDir, options);
|
|
42204
|
+
const errors = [...directoryResult.errors];
|
|
42205
|
+
const warnings = [...directoryResult.warnings];
|
|
42206
|
+
let detail;
|
|
42207
|
+
if (directoryResult.ok && directoryResult.skill) {
|
|
42208
|
+
detail = `Base directory for this skill: ${directoryResult.skillDir}
|
|
42407
42209
|
|
|
42408
|
-
|
|
42409
|
-
|
|
42410
|
-
|
|
42411
|
-
|
|
42412
|
-
|
|
42413
|
-
|
|
42414
|
-
|
|
42415
|
-
|
|
42210
|
+
${directoryResult.skill.body}`;
|
|
42211
|
+
if (!detail.includes(directoryResult.skillDir)) {
|
|
42212
|
+
addError(errors, `smoke_missing_base_dir`, `Skill detail does not include its base directory.`);
|
|
42213
|
+
}
|
|
42214
|
+
if (!detail.includes(directoryResult.skill.body)) {
|
|
42215
|
+
addError(errors, `smoke_missing_body`, `Skill detail does not include the SKILL.md body.`);
|
|
42216
|
+
}
|
|
42217
|
+
if (detail.length < 80) {
|
|
42218
|
+
addWarning(warnings, `smoke_short_detail`, `Skill detail is unusually short.`);
|
|
42416
42219
|
}
|
|
42417
|
-
} catch {
|
|
42418
|
-
return void 0;
|
|
42419
42220
|
}
|
|
42420
|
-
return void 0;
|
|
42421
|
-
};
|
|
42422
|
-
var mapMailboxEventRow = (row) => {
|
|
42423
|
-
const hasMessage = typeof row.toMailboxId === "string" && typeof row.fromMailboxId === "string" && typeof row.content === "string" && typeof row.sendTime === "number" && typeof row.status === "string";
|
|
42424
42221
|
return {
|
|
42425
|
-
|
|
42426
|
-
|
|
42427
|
-
|
|
42428
|
-
|
|
42429
|
-
|
|
42430
|
-
eventType: row.eventType,
|
|
42431
|
-
detail: parseDetail(row.detailJson),
|
|
42432
|
-
createdAt: row.createdAt,
|
|
42433
|
-
message: hasMessage ? {
|
|
42434
|
-
id: row.messageId || "",
|
|
42435
|
-
toMailboxId: row.toMailboxId,
|
|
42436
|
-
fromMailboxId: row.fromMailboxId,
|
|
42437
|
-
content: row.content,
|
|
42438
|
-
sendTime: row.sendTime,
|
|
42439
|
-
status: row.status,
|
|
42440
|
-
originUserId: row.originUserId || void 0,
|
|
42441
|
-
originPlatform: row.originPlatform || void 0,
|
|
42442
|
-
threadId: row.threadId || void 0,
|
|
42443
|
-
parentMessageId: row.parentMessageId || void 0
|
|
42444
|
-
} : null
|
|
42222
|
+
...directoryResult,
|
|
42223
|
+
ok: errors.length === 0,
|
|
42224
|
+
errors,
|
|
42225
|
+
warnings,
|
|
42226
|
+
detail
|
|
42445
42227
|
};
|
|
42446
42228
|
};
|
|
42447
|
-
var
|
|
42448
|
-
const
|
|
42449
|
-
|
|
42450
|
-
|
|
42451
|
-
|
|
42452
|
-
|
|
42453
|
-
|
|
42454
|
-
counterpartMailboxId: input.counterpartMailboxId,
|
|
42455
|
-
eventType: input.eventType,
|
|
42456
|
-
detail: input.detail,
|
|
42457
|
-
createdAt: input.createdAt ?? Date.now()
|
|
42458
|
-
};
|
|
42459
|
-
const stmt = db3.prepare(
|
|
42460
|
-
`INSERT INTO mailbox_events (
|
|
42461
|
-
id,
|
|
42462
|
-
message_id,
|
|
42463
|
-
mailbox_id,
|
|
42464
|
-
actor_mailbox_id,
|
|
42465
|
-
counterpart_mailbox_id,
|
|
42466
|
-
event_type,
|
|
42467
|
-
detail_json,
|
|
42468
|
-
created_at
|
|
42469
|
-
) VALUES (?,?,?,?,?,?,?,?)`
|
|
42470
|
-
);
|
|
42471
|
-
stmt.run(
|
|
42472
|
-
event.id,
|
|
42473
|
-
event.messageId || null,
|
|
42474
|
-
event.mailboxId,
|
|
42475
|
-
event.actorMailboxId || null,
|
|
42476
|
-
event.counterpartMailboxId || null,
|
|
42477
|
-
event.eventType,
|
|
42478
|
-
event.detail ? JSON.stringify(event.detail) : null,
|
|
42479
|
-
event.createdAt
|
|
42480
|
-
);
|
|
42481
|
-
return event;
|
|
42229
|
+
var formatSkillValidationIssues = (result) => {
|
|
42230
|
+
const lines = [
|
|
42231
|
+
...result.errors.map((issue) => `- [${issue.code}] ${issue.message}`),
|
|
42232
|
+
...result.warnings.map((issue) => `- [warning:${issue.code}] ${issue.message}`)
|
|
42233
|
+
];
|
|
42234
|
+
return lines.join(`
|
|
42235
|
+
`);
|
|
42482
42236
|
};
|
|
42483
|
-
|
|
42484
|
-
|
|
42485
|
-
|
|
42486
|
-
|
|
42487
|
-
return
|
|
42488
|
-
|
|
42489
|
-
mailboxId: params.mailboxId,
|
|
42490
|
-
actorMailboxId: params.actorMailboxId,
|
|
42491
|
-
counterpartMailboxId: params.counterpartMailboxId,
|
|
42492
|
-
eventType: "message_status_changed",
|
|
42493
|
-
detail: {
|
|
42494
|
-
previousStatus: params.previousStatus,
|
|
42495
|
-
nextStatus: params.nextStatus,
|
|
42496
|
-
reason: params.reason
|
|
42497
|
-
}
|
|
42498
|
-
});
|
|
42237
|
+
|
|
42238
|
+
// src/department/learning.ts
|
|
42239
|
+
var ensureDir = (dir) => (0, import_node_fs4.mkdirSync)(dir, { recursive: true });
|
|
42240
|
+
var readJsonArray = (filePath) => {
|
|
42241
|
+
if (!(0, import_node_fs4.existsSync)(filePath)) return [];
|
|
42242
|
+
return JSON.parse((0, import_node_fs4.readFileSync)(filePath, "utf-8"));
|
|
42499
42243
|
};
|
|
42500
|
-
var
|
|
42501
|
-
|
|
42502
|
-
|
|
42503
|
-
const stmt = db3.prepare(
|
|
42504
|
-
`SELECT
|
|
42505
|
-
e.id as id,
|
|
42506
|
-
e.message_id as messageId,
|
|
42507
|
-
e.mailbox_id as mailboxId,
|
|
42508
|
-
e.actor_mailbox_id as actorMailboxId,
|
|
42509
|
-
e.counterpart_mailbox_id as counterpartMailboxId,
|
|
42510
|
-
e.event_type as eventType,
|
|
42511
|
-
e.detail_json as detailJson,
|
|
42512
|
-
e.created_at as createdAt,
|
|
42513
|
-
m.to_mailbox_id as toMailboxId,
|
|
42514
|
-
m.from_mailbox_id as fromMailboxId,
|
|
42515
|
-
m.content as content,
|
|
42516
|
-
m.send_time as sendTime,
|
|
42517
|
-
m.status as status,
|
|
42518
|
-
m.origin_user_id as originUserId,
|
|
42519
|
-
m.origin_platform as originPlatform,
|
|
42520
|
-
m.thread_id as threadId,
|
|
42521
|
-
m.parent_message_id as parentMessageId
|
|
42522
|
-
FROM mailbox_events e
|
|
42523
|
-
LEFT JOIN mailbox m ON m.id = e.message_id
|
|
42524
|
-
WHERE e.mailbox_id = ? OR e.actor_mailbox_id = ? OR e.counterpart_mailbox_id = ?
|
|
42525
|
-
ORDER BY e.created_at DESC
|
|
42526
|
-
LIMIT ?`
|
|
42527
|
-
);
|
|
42528
|
-
const rows = stmt.all(params.mailboxId, params.mailboxId, params.mailboxId, limit);
|
|
42529
|
-
return rows.map(mapMailboxEventRow);
|
|
42244
|
+
var writeJsonArray = (filePath, records) => {
|
|
42245
|
+
ensureDir(import_node_path13.default.dirname(filePath));
|
|
42246
|
+
(0, import_node_fs4.writeFileSync)(filePath, JSON.stringify(records, null, " "), "utf-8");
|
|
42530
42247
|
};
|
|
42531
|
-
|
|
42532
|
-
|
|
42533
|
-
var import_fs13 = require("fs");
|
|
42534
|
-
var import_path18 = __toESM(require("path"));
|
|
42535
|
-
|
|
42536
|
-
// src/department/Department.ts
|
|
42537
|
-
var import_path17 = __toESM(require("path"));
|
|
42538
|
-
var import_fs12 = require("fs");
|
|
42539
|
-
var legacyMigrationChecked = false;
|
|
42540
|
-
var getDepartmentBaseDir = () => {
|
|
42541
|
-
return import_path17.default.join(getDuclawHomeDir(), "department");
|
|
42248
|
+
var departmentMemoryPath = (departmentName) => {
|
|
42249
|
+
return import_node_path13.default.join(getDepartmentWorkSpaceDir(departmentName), "department-memory.json");
|
|
42542
42250
|
};
|
|
42543
|
-
var
|
|
42544
|
-
return
|
|
42251
|
+
var departmentSkillPath = (departmentName) => {
|
|
42252
|
+
return import_node_path13.default.join(getDepartmentWorkSpaceDir(departmentName), "department-skills.json");
|
|
42545
42253
|
};
|
|
42546
|
-
var
|
|
42547
|
-
return
|
|
42254
|
+
var departmentSkillDir = (departmentName, skillName) => {
|
|
42255
|
+
return assertSafeSkillTarget(import_node_path13.default.join(getDepartmentWorkSpaceDir(departmentName), "skills"), skillName);
|
|
42548
42256
|
};
|
|
42549
|
-
var
|
|
42550
|
-
return
|
|
42257
|
+
var proposalsPath = () => {
|
|
42258
|
+
return import_node_path13.default.join(getDepartmentBaseDir(), "department-proposals.json");
|
|
42551
42259
|
};
|
|
42552
|
-
var
|
|
42553
|
-
|
|
42260
|
+
var getDepartmentNameForHead = (request) => {
|
|
42261
|
+
const mailboxId = request?.departmentAgentId;
|
|
42262
|
+
if (!mailboxId) return null;
|
|
42263
|
+
const member = getDepartmentMemberByMailboxId(mailboxId);
|
|
42264
|
+
if (!member || member.role !== "department_head") return null;
|
|
42265
|
+
const [departmentName] = mailboxId.split("::");
|
|
42266
|
+
return departmentName || null;
|
|
42554
42267
|
};
|
|
42555
|
-
var
|
|
42556
|
-
return
|
|
42268
|
+
var listDepartmentMemories = (departmentName) => {
|
|
42269
|
+
return readJsonArray(departmentMemoryPath(departmentName)).sort((a, b) => b.updatedAt - a.updatedAt);
|
|
42557
42270
|
};
|
|
42558
|
-
var
|
|
42559
|
-
|
|
42271
|
+
var createDepartmentMemory = (departmentName, input) => {
|
|
42272
|
+
const now = Date.now();
|
|
42273
|
+
const memory = {
|
|
42274
|
+
id: (0, import_node_crypto4.randomUUID)().slice(0, 8),
|
|
42275
|
+
departmentName,
|
|
42276
|
+
title: input.title,
|
|
42277
|
+
content: input.content,
|
|
42278
|
+
sourceMailboxId: input.sourceMailboxId,
|
|
42279
|
+
createdAt: now,
|
|
42280
|
+
updatedAt: now
|
|
42281
|
+
};
|
|
42282
|
+
const records = listDepartmentMemories(departmentName);
|
|
42283
|
+
records.push(memory);
|
|
42284
|
+
writeJsonArray(departmentMemoryPath(departmentName), records);
|
|
42285
|
+
return memory;
|
|
42560
42286
|
};
|
|
42561
|
-
var
|
|
42562
|
-
const
|
|
42563
|
-
|
|
42564
|
-
|
|
42565
|
-
|
|
42566
|
-
|
|
42567
|
-
|
|
42568
|
-
|
|
42569
|
-
|
|
42570
|
-
}));
|
|
42571
|
-
const headMemberId = legacy.managerMemberId ?? departmentMembers.find((member) => member.role === "department_head")?.id;
|
|
42572
|
-
return {
|
|
42573
|
-
id: legacy.id,
|
|
42574
|
-
name: legacy.name,
|
|
42575
|
-
sourceGoalId: legacy.goalId,
|
|
42576
|
-
charter: legacy.goalId ? `Legacy department migrated from team goal ${legacy.goalId}.` : "Legacy department migrated from team data.",
|
|
42577
|
-
workpath: legacy.workpath,
|
|
42578
|
-
headMemberId,
|
|
42579
|
-
departmentMembers
|
|
42287
|
+
var updateDepartmentMemory = (departmentName, id, patch) => {
|
|
42288
|
+
const records = listDepartmentMemories(departmentName);
|
|
42289
|
+
const idx = records.findIndex((record) => record.id === id);
|
|
42290
|
+
if (idx < 0) return null;
|
|
42291
|
+
records[idx] = {
|
|
42292
|
+
...records[idx],
|
|
42293
|
+
...patch.title !== void 0 ? { title: patch.title } : {},
|
|
42294
|
+
...patch.content !== void 0 ? { content: patch.content } : {},
|
|
42295
|
+
updatedAt: Date.now()
|
|
42580
42296
|
};
|
|
42297
|
+
writeJsonArray(departmentMemoryPath(departmentName), records);
|
|
42298
|
+
return records[idx];
|
|
42581
42299
|
};
|
|
42582
|
-
var
|
|
42583
|
-
|
|
42584
|
-
|
|
42585
|
-
|
|
42586
|
-
|
|
42587
|
-
for (const legacyName of (0, import_fs12.readdirSync)(legacyWorkspaceDir)) {
|
|
42588
|
-
const legacyJsonPath = getLegacyTeamJsonPath(legacyName);
|
|
42589
|
-
if (!(0, import_fs12.existsSync)(legacyJsonPath)) continue;
|
|
42590
|
-
const departmentJsonPath = getDepartmentJsonPath(legacyName);
|
|
42591
|
-
if ((0, import_fs12.existsSync)(departmentJsonPath)) continue;
|
|
42592
|
-
try {
|
|
42593
|
-
const legacy = JSON.parse((0, import_fs12.readFileSync)(legacyJsonPath, "utf-8"));
|
|
42594
|
-
const department = mapLegacyDepartment(legacy);
|
|
42595
|
-
(0, import_fs12.mkdirSync)(getDepartmentWorkSpaceDir(department.name), { recursive: true });
|
|
42596
|
-
(0, import_fs12.writeFileSync)(departmentJsonPath, JSON.stringify(department, null, " "), "utf-8");
|
|
42597
|
-
} catch (err) {
|
|
42598
|
-
console.warn(`[department] Failed to migrate legacy team ${legacyName}: ${err.message}`);
|
|
42599
|
-
}
|
|
42600
|
-
}
|
|
42601
|
-
};
|
|
42602
|
-
var createDepartment = (departmentDefinition) => {
|
|
42603
|
-
if (!departmentDefinition) throw new Error(`[createDepartment] departmentDefinition\u4E0D\u80FD\u4E3A\u7A7A`);
|
|
42604
|
-
const departmentPath = getDepartmentWorkSpaceDir(departmentDefinition.name);
|
|
42605
|
-
(0, import_fs12.mkdirSync)(departmentPath, { recursive: true });
|
|
42606
|
-
(0, import_fs12.writeFileSync)(getDepartmentJsonPath(departmentDefinition.name), JSON.stringify(departmentDefinition, null, " "), "utf-8");
|
|
42607
|
-
return departmentDefinition;
|
|
42300
|
+
var deleteDepartmentMemory = (departmentName, id) => {
|
|
42301
|
+
const records = listDepartmentMemories(departmentName);
|
|
42302
|
+
const target = records.find((record) => record.id === id) ?? null;
|
|
42303
|
+
writeJsonArray(departmentMemoryPath(departmentName), records.filter((record) => record.id !== id));
|
|
42304
|
+
return target;
|
|
42608
42305
|
};
|
|
42609
|
-
var
|
|
42610
|
-
|
|
42611
|
-
const departmentJsonPath = getDepartmentJsonPath(name);
|
|
42612
|
-
if (!(0, import_fs12.existsSync)(departmentJsonPath)) return null;
|
|
42613
|
-
const text2 = (0, import_fs12.readFileSync)(departmentJsonPath, "utf-8");
|
|
42614
|
-
return JSON.parse(text2);
|
|
42306
|
+
var listDepartmentSkills = (departmentName) => {
|
|
42307
|
+
return readJsonArray(departmentSkillPath(departmentName)).sort((a, b) => b.updatedAt - a.updatedAt);
|
|
42615
42308
|
};
|
|
42616
|
-
var
|
|
42617
|
-
|
|
42618
|
-
|
|
42619
|
-
|
|
42620
|
-
|
|
42621
|
-
|
|
42622
|
-
|
|
42623
|
-
|
|
42309
|
+
var proposeDepartmentSkill = (departmentName, input) => {
|
|
42310
|
+
const validation = validateSkillDocument({
|
|
42311
|
+
skillName: input.skillName,
|
|
42312
|
+
description: input.description,
|
|
42313
|
+
skillMd: input.skillMd
|
|
42314
|
+
});
|
|
42315
|
+
if (!validation.ok) {
|
|
42316
|
+
throw new Error(`[departmentSkill] Skill \u8349\u7A3F\u6821\u9A8C\u5931\u8D25\uFF1A
|
|
42317
|
+
${formatSkillValidationIssues(validation)}`);
|
|
42624
42318
|
}
|
|
42625
|
-
|
|
42626
|
-
|
|
42627
|
-
|
|
42628
|
-
|
|
42629
|
-
|
|
42319
|
+
const records = listDepartmentSkills(departmentName);
|
|
42320
|
+
if (records.some((record) => record.skillName === input.skillName && record.status !== "dropped")) {
|
|
42321
|
+
return null;
|
|
42322
|
+
}
|
|
42323
|
+
const now = Date.now();
|
|
42324
|
+
const skill = {
|
|
42325
|
+
id: (0, import_node_crypto4.randomUUID)().slice(0, 8),
|
|
42326
|
+
departmentName,
|
|
42327
|
+
skillName: input.skillName,
|
|
42328
|
+
description: input.description,
|
|
42329
|
+
skillMd: input.skillMd,
|
|
42330
|
+
status: "pending",
|
|
42331
|
+
createdByMailboxId: input.createdByMailboxId,
|
|
42332
|
+
createdAt: now,
|
|
42333
|
+
updatedAt: now
|
|
42334
|
+
};
|
|
42335
|
+
records.push(skill);
|
|
42336
|
+
writeJsonArray(departmentSkillPath(departmentName), records);
|
|
42337
|
+
return skill;
|
|
42630
42338
|
};
|
|
42631
|
-
var
|
|
42632
|
-
|
|
42633
|
-
|
|
42339
|
+
var keepDepartmentSkill = (departmentName, id) => {
|
|
42340
|
+
const records = listDepartmentSkills(departmentName);
|
|
42341
|
+
const idx = records.findIndex((record) => record.id === id);
|
|
42342
|
+
if (idx < 0) return null;
|
|
42343
|
+
records[idx] = { ...records[idx], status: "active", updatedAt: Date.now() };
|
|
42344
|
+
const skillDir = departmentSkillDir(departmentName, records[idx].skillName);
|
|
42345
|
+
const validation = validateSkillDocument({
|
|
42346
|
+
skillName: records[idx].skillName,
|
|
42347
|
+
description: records[idx].description,
|
|
42348
|
+
skillMd: records[idx].skillMd,
|
|
42349
|
+
baseDir: skillDir
|
|
42350
|
+
});
|
|
42351
|
+
if (!validation.ok) {
|
|
42352
|
+
throw new Error(`[departmentSkill] Skill \u8349\u7A3F\u6821\u9A8C\u5931\u8D25\uFF0C\u62D2\u7EDD\u4FDD\u7559\uFF1A
|
|
42353
|
+
${formatSkillValidationIssues(validation)}`);
|
|
42354
|
+
}
|
|
42355
|
+
ensureDir(skillDir);
|
|
42356
|
+
(0, import_node_fs4.writeFileSync)(import_node_path13.default.join(skillDir, "SKILL.md"), records[idx].skillMd, "utf-8");
|
|
42357
|
+
const smokeTest = smokeTestSkillDirectory(skillDir, { expectedName: records[idx].skillName });
|
|
42358
|
+
if (!smokeTest.ok) {
|
|
42359
|
+
throw new Error(`[departmentSkill] Skill smoke test \u5931\u8D25\uFF1A
|
|
42360
|
+
${formatSkillValidationIssues(smokeTest)}`);
|
|
42634
42361
|
}
|
|
42635
|
-
(
|
|
42362
|
+
writeJsonArray(departmentSkillPath(departmentName), records);
|
|
42363
|
+
return records[idx];
|
|
42636
42364
|
};
|
|
42637
|
-
|
|
42638
|
-
|
|
42639
|
-
|
|
42640
|
-
|
|
42641
|
-
|
|
42365
|
+
var dropDepartmentSkill = (departmentName, id) => {
|
|
42366
|
+
const records = listDepartmentSkills(departmentName);
|
|
42367
|
+
const idx = records.findIndex((record) => record.id === id);
|
|
42368
|
+
if (idx < 0) return null;
|
|
42369
|
+
records[idx] = { ...records[idx], status: "dropped", updatedAt: Date.now() };
|
|
42370
|
+
writeJsonArray(departmentSkillPath(departmentName), records);
|
|
42371
|
+
return records[idx];
|
|
42642
42372
|
};
|
|
42643
|
-
var
|
|
42644
|
-
const
|
|
42645
|
-
|
|
42646
|
-
|
|
42647
|
-
|
|
42648
|
-
|
|
42649
|
-
|
|
42650
|
-
|
|
42373
|
+
var createDepartmentProposal = (input) => {
|
|
42374
|
+
const records = readJsonArray(proposalsPath());
|
|
42375
|
+
const proposal = {
|
|
42376
|
+
...input,
|
|
42377
|
+
id: (0, import_node_crypto4.randomUUID)().slice(0, 8),
|
|
42378
|
+
status: "pending",
|
|
42379
|
+
createdAt: Date.now()
|
|
42380
|
+
};
|
|
42381
|
+
records.push(proposal);
|
|
42382
|
+
writeJsonArray(proposalsPath(), records);
|
|
42383
|
+
return proposal;
|
|
42651
42384
|
};
|
|
42652
|
-
var
|
|
42653
|
-
|
|
42654
|
-
|
|
42385
|
+
var buildDepartmentLearningContext = (departmentName) => {
|
|
42386
|
+
if (!departmentName) return "";
|
|
42387
|
+
const memories = listDepartmentMemories(departmentName);
|
|
42388
|
+
const activeSkills = listDepartmentSkills(departmentName).filter((skill) => skill.status === "active");
|
|
42389
|
+
if (memories.length === 0 && activeSkills.length === 0) return "";
|
|
42390
|
+
const memoryLines = memories.map(
|
|
42391
|
+
(memory) => ` - [id=${memory.id}] ${memory.title}
|
|
42392
|
+
${memory.content.replace(/\n/g, "\n ")}`
|
|
42393
|
+
).join("\n");
|
|
42394
|
+
const skillLines = activeSkills.map(
|
|
42395
|
+
(skill) => ` - ${skill.skillName}: ${skill.description}`
|
|
42396
|
+
).join("\n");
|
|
42397
|
+
return [
|
|
42398
|
+
`<department-learning-context department="${departmentName}">`,
|
|
42399
|
+
memories.length > 0 ? `Department memories:
|
|
42400
|
+
${memoryLines}` : "",
|
|
42401
|
+
activeSkills.length > 0 ? `Department skills:
|
|
42402
|
+
${skillLines}` : "",
|
|
42403
|
+
`</department-learning-context>`
|
|
42404
|
+
].filter(Boolean).join("\n");
|
|
42655
42405
|
};
|
|
42656
42406
|
|
|
42657
|
-
// src/
|
|
42658
|
-
var
|
|
42659
|
-
|
|
42660
|
-
|
|
42661
|
-
|
|
42662
|
-
|
|
42663
|
-
const
|
|
42664
|
-
|
|
42665
|
-
const
|
|
42666
|
-
|
|
42667
|
-
|
|
42668
|
-
|
|
42669
|
-
|
|
42407
|
+
// src/skill/SkillRegistry.ts
|
|
42408
|
+
var getProjectSkillsPath = () => {
|
|
42409
|
+
const projectRoot = findProjectRoot();
|
|
42410
|
+
return projectRoot ? (0, import_path18.join)(projectRoot, "skills") : null;
|
|
42411
|
+
};
|
|
42412
|
+
var getSkillPaths = () => {
|
|
42413
|
+
const paths = [];
|
|
42414
|
+
const seenPaths = /* @__PURE__ */ new Set();
|
|
42415
|
+
const pushPath = (candidate) => {
|
|
42416
|
+
if (!(0, import_fs13.existsSync)(candidate) || !(0, import_fs13.statSync)(candidate).isDirectory()) return;
|
|
42417
|
+
const normalized = import_path18.default.resolve(candidate);
|
|
42418
|
+
if (seenPaths.has(normalized)) return;
|
|
42419
|
+
seenPaths.add(normalized);
|
|
42420
|
+
paths.push(normalized);
|
|
42670
42421
|
};
|
|
42671
|
-
|
|
42672
|
-
if (
|
|
42673
|
-
|
|
42422
|
+
const projectSkillsPath = getProjectSkillsPath();
|
|
42423
|
+
if (projectSkillsPath) {
|
|
42424
|
+
pushPath(projectSkillsPath);
|
|
42674
42425
|
}
|
|
42675
|
-
|
|
42676
|
-
|
|
42426
|
+
pushPath((0, import_path18.join)((0, import_os3.homedir)(), ".duclaw", "skills"));
|
|
42427
|
+
pushPath((0, import_path18.join)((0, import_os3.homedir)(), ".agents", "skills"));
|
|
42428
|
+
return paths;
|
|
42429
|
+
};
|
|
42430
|
+
var getDirectories = (dirPath) => {
|
|
42431
|
+
return (0, import_fs13.readdirSync)(dirPath).filter((name) => (0, import_fs13.statSync)((0, import_path18.join)(dirPath, name)).isDirectory());
|
|
42432
|
+
};
|
|
42433
|
+
var parseSkill = (mdPath, skillDir, options = {}) => {
|
|
42434
|
+
if (!(0, import_fs13.existsSync)(mdPath)) return null;
|
|
42435
|
+
const raw2 = (0, import_fs13.readFileSync)(mdPath, "utf-8");
|
|
42436
|
+
let name = "";
|
|
42437
|
+
let description = "";
|
|
42438
|
+
let body = raw2;
|
|
42439
|
+
const fmMatch = raw2.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
42440
|
+
if (fmMatch) {
|
|
42441
|
+
const frontmatter = fmMatch[1];
|
|
42442
|
+
body = raw2.slice(fmMatch[0].length).trim();
|
|
42443
|
+
for (const line of frontmatter.split("\n")) {
|
|
42444
|
+
const [key, ...rest] = line.split(":");
|
|
42445
|
+
const value = rest.join(":").trim();
|
|
42446
|
+
if (key.trim() === "name") name = value;
|
|
42447
|
+
if (key.trim() === "description") description = value;
|
|
42448
|
+
}
|
|
42677
42449
|
}
|
|
42678
|
-
if (
|
|
42679
|
-
|
|
42680
|
-
|
|
42681
|
-
|
|
42450
|
+
if (!name) {
|
|
42451
|
+
name = import_path18.default.basename(import_path18.default.dirname(mdPath));
|
|
42452
|
+
}
|
|
42453
|
+
if (!description && body) {
|
|
42454
|
+
description = body.split("\n")[0].replace(/^#+\s*/, "").trim();
|
|
42455
|
+
}
|
|
42456
|
+
const normalizedSkillDir = import_path18.default.resolve(skillDir);
|
|
42457
|
+
const projectSkillsPath = getProjectSkillsPath();
|
|
42458
|
+
const isProjectSkill = projectSkillsPath ? normalizedSkillDir === import_path18.default.resolve(projectSkillsPath, import_path18.default.basename(normalizedSkillDir)) && normalizedSkillDir.startsWith(import_path18.default.resolve(projectSkillsPath) + import_path18.default.sep) : false;
|
|
42459
|
+
const scope = options.scope ?? (isProjectSkill ? "project" : "global");
|
|
42460
|
+
const deletable = options.deletable ?? (scope === "project" && isProjectSkill);
|
|
42461
|
+
return {
|
|
42462
|
+
name,
|
|
42463
|
+
description,
|
|
42464
|
+
baseDir: skillDir,
|
|
42465
|
+
scope,
|
|
42466
|
+
departmentName: options.departmentName,
|
|
42467
|
+
deletable,
|
|
42468
|
+
getDetail: () => {
|
|
42469
|
+
let content = body.replace(/<Skill目录>/g, skillDir).replace(/\$\{CLAUDE_SKILL_DIR\}/g, skillDir);
|
|
42470
|
+
return `Base directory for this skill: ${skillDir}
|
|
42471
|
+
|
|
42472
|
+
${content}`;
|
|
42473
|
+
}
|
|
42474
|
+
};
|
|
42475
|
+
};
|
|
42476
|
+
var loadDepartmentSkills = (seen) => {
|
|
42477
|
+
const skills = [];
|
|
42478
|
+
for (const department of listDepartments()) {
|
|
42479
|
+
const activeSkills = listDepartmentSkills(department.name).filter((skill) => skill.status === "active");
|
|
42480
|
+
for (const departmentSkill of activeSkills) {
|
|
42481
|
+
if (seen.has(departmentSkill.skillName)) continue;
|
|
42482
|
+
const skillDir = (0, import_path18.join)(getDepartmentWorkSpaceDir(department.name), "skills", departmentSkill.skillName);
|
|
42483
|
+
const skill = parseSkill((0, import_path18.join)(skillDir, "SKILL.md"), skillDir, {
|
|
42484
|
+
scope: "department",
|
|
42485
|
+
departmentName: department.name,
|
|
42486
|
+
deletable: false
|
|
42487
|
+
});
|
|
42488
|
+
if (skill) {
|
|
42489
|
+
seen.add(skill.name);
|
|
42490
|
+
skills.push(skill);
|
|
42491
|
+
}
|
|
42682
42492
|
}
|
|
42683
|
-
department.headMemberId = departmentMemberDefinition.id;
|
|
42684
42493
|
}
|
|
42685
|
-
|
|
42686
|
-
(0, import_fs13.writeFileSync)(getDepartmentJsonPath(department.name), JSON.stringify(department, null, " "), "utf-8");
|
|
42687
|
-
return departmentMemberDefinition;
|
|
42494
|
+
return skills;
|
|
42688
42495
|
};
|
|
42689
|
-
var
|
|
42690
|
-
const
|
|
42691
|
-
|
|
42692
|
-
const
|
|
42693
|
-
const
|
|
42694
|
-
|
|
42695
|
-
|
|
42696
|
-
|
|
42697
|
-
|
|
42698
|
-
|
|
42699
|
-
|
|
42496
|
+
var loadSkill = () => {
|
|
42497
|
+
const skillPaths = getSkillPaths();
|
|
42498
|
+
const seen = /* @__PURE__ */ new Set();
|
|
42499
|
+
const skills = [];
|
|
42500
|
+
for (const skillPath of skillPaths) {
|
|
42501
|
+
const dirs = getDirectories(skillPath);
|
|
42502
|
+
for (const skillName of dirs) {
|
|
42503
|
+
const eachSkillPath = (0, import_path18.join)(skillPath, skillName);
|
|
42504
|
+
const eachSkillMdPath = (0, import_path18.join)(eachSkillPath, "SKILL.md");
|
|
42505
|
+
const skill = parseSkill(eachSkillMdPath, eachSkillPath);
|
|
42506
|
+
if (skill && !seen.has(skill.name)) {
|
|
42507
|
+
seen.add(skill.name);
|
|
42508
|
+
skills.push(skill);
|
|
42509
|
+
}
|
|
42510
|
+
}
|
|
42511
|
+
}
|
|
42512
|
+
skills.push(...loadDepartmentSkills(seen));
|
|
42513
|
+
return skills;
|
|
42700
42514
|
};
|
|
42701
|
-
var
|
|
42702
|
-
const
|
|
42703
|
-
|
|
42515
|
+
var deleteSkill = (name) => {
|
|
42516
|
+
const skills = loadSkill();
|
|
42517
|
+
const skill = skills.find((s) => s.name === name);
|
|
42518
|
+
if (!skill || !skill.deletable) return false;
|
|
42519
|
+
(0, import_fs13.rmSync)(skill.baseDir, { recursive: true, force: false });
|
|
42520
|
+
return true;
|
|
42704
42521
|
};
|
|
42705
|
-
var
|
|
42706
|
-
|
|
42707
|
-
|
|
42708
|
-
|
|
42522
|
+
var SkillRegistry_default = loadSkill;
|
|
42523
|
+
|
|
42524
|
+
// src/skill/index.ts
|
|
42525
|
+
var getSkillMeta = () => {
|
|
42526
|
+
const skills = SkillRegistry_default();
|
|
42527
|
+
if (skills.length === 0) return "";
|
|
42528
|
+
const skillXmls = skills.map((skill) => {
|
|
42529
|
+
return [
|
|
42530
|
+
" <skill>",
|
|
42531
|
+
` <name>${skill.name}</name>`,
|
|
42532
|
+
` <description>`,
|
|
42533
|
+
` ${skill.description}`,
|
|
42534
|
+
` </description>`,
|
|
42535
|
+
` <location>user</location>`,
|
|
42536
|
+
" </skill>"
|
|
42537
|
+
].join("\n");
|
|
42538
|
+
});
|
|
42539
|
+
return [
|
|
42540
|
+
"<available_skills>",
|
|
42541
|
+
...skillXmls,
|
|
42542
|
+
"</available_skills>"
|
|
42543
|
+
].join("\n");
|
|
42709
42544
|
};
|
|
42710
|
-
var
|
|
42711
|
-
|
|
42712
|
-
|
|
42713
|
-
if (
|
|
42545
|
+
var getSkillDetail = (skillName) => {
|
|
42546
|
+
const skills = SkillRegistry_default();
|
|
42547
|
+
for (let skill of skills) {
|
|
42548
|
+
if (skill.name === skillName) {
|
|
42549
|
+
return skill.getDetail();
|
|
42550
|
+
}
|
|
42714
42551
|
}
|
|
42715
|
-
return
|
|
42552
|
+
return void 0;
|
|
42716
42553
|
};
|
|
42717
|
-
|
|
42718
|
-
|
|
42719
|
-
|
|
42720
|
-
|
|
42721
|
-
|
|
42722
|
-
|
|
42554
|
+
|
|
42555
|
+
// src/tools/tools/Skill.ts
|
|
42556
|
+
var DESCRIPTION15 = `
|
|
42557
|
+
Execute a skill within the main conversation
|
|
42558
|
+
|
|
42559
|
+
<skills_instructions>
|
|
42560
|
+
When users ask you to perform tasks, check if any of the available skills
|
|
42561
|
+
below can help complete the task more effectively. Skills provide specialized
|
|
42562
|
+
capabilities and domain knowledge.
|
|
42563
|
+
|
|
42564
|
+
How to use skills:
|
|
42565
|
+
- Invoke skills using this tool with the skill name only (no arguments)
|
|
42566
|
+
- When you invoke a skill, you will see <command-message>The "{name}" skill is loading</command-message>
|
|
42567
|
+
- The skill's prompt will expand and provide detailed instructions on how to complete the task
|
|
42568
|
+
- Examples:
|
|
42569
|
+
- \`command: "pdf"\` - invoke the pdf skill
|
|
42570
|
+
- \`command: "xlsx"\` - invoke the xlsx skill
|
|
42571
|
+
- \`command: "ms-office-suite:pdf"\` - invoke using fully qualified name
|
|
42572
|
+
|
|
42573
|
+
Important:
|
|
42574
|
+
- Only use skills listed in <available_skills> below
|
|
42575
|
+
- Do not invoke a skill that is already running
|
|
42576
|
+
- Do not use this tool for built-in CLI commands (like /help, /clear, etc.)
|
|
42577
|
+
</skills_instructions>
|
|
42578
|
+
|
|
42579
|
+
${getSkillMeta()}
|
|
42580
|
+
`;
|
|
42581
|
+
var skillTool = {
|
|
42582
|
+
name: `skill`,
|
|
42583
|
+
description: DESCRIPTION15,
|
|
42584
|
+
input_schema: {
|
|
42585
|
+
type: `object`,
|
|
42586
|
+
properties: {
|
|
42587
|
+
command: {
|
|
42588
|
+
type: `string`,
|
|
42589
|
+
description: `The skill name (no arguments). E.g., "pdf" or "xlsx"`
|
|
42590
|
+
}
|
|
42591
|
+
},
|
|
42592
|
+
required: [`command`]
|
|
42593
|
+
},
|
|
42594
|
+
async execute(input, userRequest) {
|
|
42595
|
+
console.log(`[\u6267\u884C\u5DE5\u5177]${input.command} skill`);
|
|
42596
|
+
const command = input.command;
|
|
42597
|
+
const detail = getSkillDetail(command);
|
|
42598
|
+
if (!detail) return `<command-message> skill name: \u201C${command}\u201D \u4E0D\u5B58\u5728</command-message>
|
|
42599
|
+
<command-name>${command}</command-name>`;
|
|
42600
|
+
const skillXml = `
|
|
42601
|
+
<command-message>The "${command}" skill is running</command-message>
|
|
42602
|
+
|
|
42603
|
+
<command-name>${command}</command-name>
|
|
42604
|
+
|
|
42605
|
+
<command-detail>${detail}</command-detail>
|
|
42606
|
+
`;
|
|
42607
|
+
return skillXml;
|
|
42723
42608
|
}
|
|
42724
|
-
|
|
42725
|
-
|
|
42726
|
-
|
|
42609
|
+
};
|
|
42610
|
+
|
|
42611
|
+
// src/tools/tools/tasks/GoalCreate.ts
|
|
42612
|
+
var goalCreate = {
|
|
42613
|
+
name: `goal_create`,
|
|
42614
|
+
description: `\u5728\u4EFB\u52A1\u7CFB\u7EDF\u4E2D\u521B\u5EFA\u4E00\u4E2A\u4EFB\u52A1\u76EE\u6807\uFF0C\u5F53\u8981\u8C03\u7528 task_ \u7CFB\u5217\u5DE5\u5177\u65F6\uFF0C\u5148\u8C03\u7528\u6B64\u5DE5\u5177\u521B\u5EFA\u4EFB\u52A1\u76EE\u6807`,
|
|
42615
|
+
input_schema: {
|
|
42616
|
+
type: `object`,
|
|
42617
|
+
properties: {
|
|
42618
|
+
subject: {
|
|
42619
|
+
type: `string`,
|
|
42620
|
+
description: `\u4EFB\u52A1\u76EE\u6807\u7684\u6838\u5FC3\u6807\u9898\uFF0C\u7B80\u6D01\u660E\u4E86`
|
|
42621
|
+
},
|
|
42622
|
+
description: {
|
|
42623
|
+
type: `string`,
|
|
42624
|
+
description: `\u4EFB\u52A1\u76EE\u6807\u7684\u8BE6\u7EC6\u8BF4\u660E`
|
|
42625
|
+
}
|
|
42626
|
+
},
|
|
42627
|
+
required: [`subject`]
|
|
42628
|
+
},
|
|
42629
|
+
async execute(input, userRequest) {
|
|
42630
|
+
const subject = input.subject;
|
|
42631
|
+
const description = input.description;
|
|
42632
|
+
const taskGoal = await createGoal(subject, description);
|
|
42633
|
+
if (userRequest) {
|
|
42634
|
+
ensureGoalConversationContext(taskGoal.id, {
|
|
42635
|
+
threadId: userRequest.userId,
|
|
42636
|
+
originPlatform: userRequest.platform,
|
|
42637
|
+
originUserId: userRequest.userId,
|
|
42638
|
+
syncReplyToOrigin: userRequest.platform === "feishu"
|
|
42639
|
+
});
|
|
42640
|
+
}
|
|
42641
|
+
if (taskGoal) {
|
|
42642
|
+
return `[GoalCreate] \u521B\u5EFA\u4EFB\u52A1\u76EE\u6807\u6210\u529F: ${JSON.stringify(taskGoal)}`;
|
|
42643
|
+
}
|
|
42644
|
+
return `[GoalCreate] \u521B\u5EFA\u4EFB\u52A1\u76EE\u6807\u5931\u8D25: ${taskGoal}`;
|
|
42727
42645
|
}
|
|
42728
|
-
department.departmentMembers = department.departmentMembers.filter((_, index) => index !== memberIdx);
|
|
42729
|
-
(0, import_fs13.writeFileSync)(getDepartmentJsonPath(departmentName), JSON.stringify(department, null, " "), "utf-8");
|
|
42730
|
-
deleteWorkspace(workspaceId);
|
|
42731
42646
|
};
|
|
42732
42647
|
|
|
42733
|
-
// src/
|
|
42734
|
-
var
|
|
42735
|
-
|
|
42736
|
-
|
|
42737
|
-
|
|
42738
|
-
|
|
42739
|
-
|
|
42740
|
-
|
|
42741
|
-
|
|
42742
|
-
|
|
42743
|
-
|
|
42744
|
-
|
|
42745
|
-
|
|
42746
|
-
|
|
42747
|
-
|
|
42748
|
-
|
|
42749
|
-
|
|
42750
|
-
|
|
42751
|
-
}
|
|
42752
|
-
|
|
42753
|
-
|
|
42754
|
-
|
|
42755
|
-
|
|
42756
|
-
|
|
42757
|
-
|
|
42758
|
-
|
|
42759
|
-
|
|
42760
|
-
|
|
42761
|
-
|
|
42762
|
-
|
|
42763
|
-
|
|
42764
|
-
|
|
42765
|
-
|
|
42766
|
-
|
|
42767
|
-
last_error as lastError,
|
|
42768
|
-
created_at as createdAt,
|
|
42769
|
-
updated_at as updatedAt,
|
|
42770
|
-
completed_at as completedAt
|
|
42771
|
-
FROM ceo_followups
|
|
42772
|
-
WHERE id = ?
|
|
42773
|
-
`).get(id);
|
|
42774
|
-
return row ? rowToFollowup(row) : null;
|
|
42648
|
+
// src/tools/tools/tasks/GoalGet.ts
|
|
42649
|
+
var DESCRIPTION16 = `
|
|
42650
|
+
\u83B7\u53D6\u4EFB\u52A1\u7CFB\u7EDF\u4E2D\u6307\u5B9A\u7684Goal
|
|
42651
|
+
`;
|
|
42652
|
+
var goalGet = {
|
|
42653
|
+
name: `goal_get`,
|
|
42654
|
+
description: DESCRIPTION16,
|
|
42655
|
+
input_schema: {
|
|
42656
|
+
type: `object`,
|
|
42657
|
+
properties: {
|
|
42658
|
+
id: {
|
|
42659
|
+
type: `string`,
|
|
42660
|
+
description: `\u6839\u636Eid\u83B7\u53D6\u6307\u5B9A\u76EE\u6807,\u53EF\u9009`
|
|
42661
|
+
},
|
|
42662
|
+
subject: {
|
|
42663
|
+
type: `string`,
|
|
42664
|
+
description: `\u6839\u636Esubject\u83B7\u53D6\u7279\u5B9A\u76EE\u6807,\u53EF\u9009`
|
|
42665
|
+
}
|
|
42666
|
+
}
|
|
42667
|
+
},
|
|
42668
|
+
async execute(input, userRequest) {
|
|
42669
|
+
const id = input.id;
|
|
42670
|
+
const subject = input.subject;
|
|
42671
|
+
let goal = void 0;
|
|
42672
|
+
if (id) {
|
|
42673
|
+
goal = getGoalById(id);
|
|
42674
|
+
} else if (subject) {
|
|
42675
|
+
goal = getGoalBySubject(subject);
|
|
42676
|
+
}
|
|
42677
|
+
if (!goal) {
|
|
42678
|
+
return `[GetGoal] \u627E\u4E0D\u5230\u6307\u5B9A\u7684\u76EE\u6807`;
|
|
42679
|
+
}
|
|
42680
|
+
return `[GetGoal] \u627E\u5230\u76EE\u6807: ${JSON.stringify(goal)}`;
|
|
42681
|
+
}
|
|
42775
42682
|
};
|
|
42776
|
-
|
|
42777
|
-
|
|
42778
|
-
|
|
42779
|
-
|
|
42780
|
-
|
|
42781
|
-
|
|
42782
|
-
|
|
42783
|
-
|
|
42784
|
-
|
|
42785
|
-
|
|
42786
|
-
|
|
42787
|
-
|
|
42788
|
-
|
|
42789
|
-
|
|
42790
|
-
|
|
42791
|
-
|
|
42792
|
-
|
|
42793
|
-
|
|
42794
|
-
|
|
42795
|
-
|
|
42796
|
-
|
|
42797
|
-
|
|
42683
|
+
|
|
42684
|
+
// src/tools/tools/tasks/GoalList.ts
|
|
42685
|
+
var DESCRIPTION17 = `
|
|
42686
|
+
\u5728\u4EFB\u52A1\u7CFB\u7EDF\u4E2D\u5217\u51FA\u6240\u6709\u76EE\u6807
|
|
42687
|
+
`;
|
|
42688
|
+
var goalList = {
|
|
42689
|
+
name: `goal_list`,
|
|
42690
|
+
description: DESCRIPTION17,
|
|
42691
|
+
input_schema: {
|
|
42692
|
+
type: `object`,
|
|
42693
|
+
properties: {}
|
|
42694
|
+
},
|
|
42695
|
+
async execute(input, userRequest) {
|
|
42696
|
+
const goals = listGoal();
|
|
42697
|
+
if (goals.length > 0) {
|
|
42698
|
+
return `[GoalList]goals\u5217\u8868: ${JSON.stringify(goals)}`;
|
|
42699
|
+
}
|
|
42700
|
+
return `[GoalList]\u6CA1\u6709goals\u6570\u636E`;
|
|
42701
|
+
}
|
|
42702
|
+
};
|
|
42703
|
+
|
|
42704
|
+
// src/tools/tools/tasks/GoalUpdate.ts
|
|
42705
|
+
var DESCRIPTION18 = `
|
|
42706
|
+
\u66F4\u65B0\u4EFB\u52A1\u7CFB\u7EDF\u4E2D\u6307\u5B9A\u7684Goal
|
|
42707
|
+
|
|
42708
|
+
\u5DE5\u5177\u4F7F\u7528\u89C4\u5219:
|
|
42709
|
+
- \u5F53\u76EE\u6807\u7684\u72B6\u6001status\u9700\u8981\u66F4\u65B0\u65F6;
|
|
42710
|
+
- \u5F53\u76EE\u6807\u7684subject\u6216description\u9700\u8981\u4FEE\u6539\u65F6;
|
|
42711
|
+
`;
|
|
42712
|
+
var goalUpdate = {
|
|
42713
|
+
name: `goal_update`,
|
|
42714
|
+
description: DESCRIPTION18,
|
|
42715
|
+
input_schema: {
|
|
42716
|
+
type: `object`,
|
|
42717
|
+
properties: {
|
|
42718
|
+
id: {
|
|
42719
|
+
type: `string`,
|
|
42720
|
+
description: `\u6839\u636Eid\u627E\u5230\u5BF9\u5E94goal\u8FDB\u884C\u66F4\u65B0`
|
|
42721
|
+
},
|
|
42722
|
+
subject: {
|
|
42723
|
+
type: `string`,
|
|
42724
|
+
description: `\u66F4\u65B0\u540Egoal\u7684\u6838\u5FC3\u6807\u9898\uFF0C\u7B80\u6D01\u660E\u4E86`
|
|
42725
|
+
},
|
|
42726
|
+
description: {
|
|
42727
|
+
type: `string`,
|
|
42728
|
+
description: `\u66F4\u65B0\u540E\u7684goal\u7684\u8BE6\u7EC6\u8BF4\u660E`
|
|
42729
|
+
},
|
|
42730
|
+
status: {
|
|
42731
|
+
type: `string`,
|
|
42732
|
+
description: `pending | in_progress | completed | failed`,
|
|
42733
|
+
enum: [`pending`, `in_progress`, `completed`, `failed`]
|
|
42734
|
+
}
|
|
42735
|
+
},
|
|
42736
|
+
required: [`id`]
|
|
42737
|
+
},
|
|
42738
|
+
async execute(input, userRequest) {
|
|
42739
|
+
const id = input.id;
|
|
42740
|
+
const subject = input.subject;
|
|
42741
|
+
const description = input.description;
|
|
42742
|
+
const status = input.status;
|
|
42743
|
+
const validStatuses = ["pending", "in_progress", "completed", "failed"];
|
|
42744
|
+
if (status && !validStatuses.includes(status)) {
|
|
42745
|
+
return `[UpdateGoal] status\u53C2\u6570\u9519\u8BEF,status\u5FC5\u987B\u8981\u662F pending | in_progress | completed | failed \u4E2D\u7684\u4EFB\u610F\u4E00\u4E2A`;
|
|
42746
|
+
}
|
|
42747
|
+
const goal = getGoalById(id);
|
|
42748
|
+
if (!goal) {
|
|
42749
|
+
return `[UpdateGoal] \u627E\u4E0D\u5230\u6307\u5B9Aid\u7684\u76EE\u6807`;
|
|
42750
|
+
}
|
|
42751
|
+
const updatedGoal = {
|
|
42752
|
+
...goal,
|
|
42753
|
+
subject: subject || goal.subject,
|
|
42754
|
+
description: description !== void 0 ? description : goal.description,
|
|
42755
|
+
status: status || goal.status,
|
|
42756
|
+
updateAt: getDate()
|
|
42757
|
+
};
|
|
42758
|
+
try {
|
|
42759
|
+
updateGoal(id, updatedGoal);
|
|
42760
|
+
} catch (err) {
|
|
42761
|
+
if (err instanceof GoalCompletionBlockedError) {
|
|
42762
|
+
return err.message;
|
|
42763
|
+
}
|
|
42764
|
+
throw err;
|
|
42765
|
+
}
|
|
42766
|
+
return `[UpdateGoal] \u66F4\u65B0\u76EE\u6807\u6210\u529F: ${JSON.stringify(updatedGoal)}`;
|
|
42767
|
+
}
|
|
42768
|
+
};
|
|
42769
|
+
|
|
42770
|
+
// src/tools/tools/tasks/GoalDelete.ts
|
|
42771
|
+
var DESCRIPTION19 = `
|
|
42772
|
+
\u5220\u9664\u4EFB\u52A1\u7CFB\u7EDF\u4E2D\u6307\u5B9A\u7684Goal\u53CA\u5176\u5BF9\u5E94\u7684JSON\u6587\u4EF6
|
|
42773
|
+
|
|
42774
|
+
\u5DE5\u5177\u4F7F\u7528\u89C4\u5219:
|
|
42775
|
+
- \u5F53\u76EE\u6807\u5DF2\u7ECF\u5B8C\u6210(completed)\u6216\u5931\u8D25(failed)\u540E,\u9700\u8981\u6E05\u7406\u65F6\u8C03\u7528;
|
|
42776
|
+
- \u5220\u9664\u540E\u4E0D\u53EF\u6062\u590D,\u8BF7\u8C28\u614E\u4F7F\u7528;
|
|
42777
|
+
`;
|
|
42778
|
+
var goalDelete = {
|
|
42779
|
+
name: `goal_delete`,
|
|
42780
|
+
description: DESCRIPTION19,
|
|
42781
|
+
input_schema: {
|
|
42782
|
+
type: `object`,
|
|
42783
|
+
properties: {
|
|
42784
|
+
id: {
|
|
42785
|
+
type: `string`,
|
|
42786
|
+
description: `\u8981\u5220\u9664\u7684\u76EE\u6807ID`
|
|
42787
|
+
}
|
|
42788
|
+
},
|
|
42789
|
+
required: [`id`]
|
|
42790
|
+
},
|
|
42791
|
+
async execute(input, userRequest) {
|
|
42792
|
+
const id = input.id;
|
|
42793
|
+
const goal = getGoalById(id);
|
|
42794
|
+
if (!goal) {
|
|
42795
|
+
return `[GoalDelete] \u627E\u4E0D\u5230\u6307\u5B9Aid\u7684\u76EE\u6807`;
|
|
42796
|
+
}
|
|
42797
|
+
const deleted = deleteGoal(id);
|
|
42798
|
+
if (deleted) {
|
|
42799
|
+
return `[GoalDelete] \u76EE\u6807\u5DF2\u5220\u9664: id=${id}, subject=${goal.subject}`;
|
|
42800
|
+
}
|
|
42801
|
+
return `[GoalDelete] \u5220\u9664\u76EE\u6807\u5931\u8D25: id=${id}`;
|
|
42802
|
+
}
|
|
42803
|
+
};
|
|
42804
|
+
|
|
42805
|
+
// src/tools/tools/department/DepartmentCreate.ts
|
|
42806
|
+
var import_node_crypto9 = require("node:crypto");
|
|
42807
|
+
|
|
42808
|
+
// src/department/mailbox/mailbox.ts
|
|
42809
|
+
var import_node_crypto8 = require("node:crypto");
|
|
42810
|
+
|
|
42811
|
+
// src/agent/interruptRegistry.ts
|
|
42812
|
+
var registry = /* @__PURE__ */ new Map();
|
|
42813
|
+
var markRunning = (userId) => {
|
|
42814
|
+
const current = registry.get(userId);
|
|
42815
|
+
if (current) {
|
|
42816
|
+
current.startedAt = Date.now();
|
|
42817
|
+
return;
|
|
42818
|
+
}
|
|
42819
|
+
registry.set(userId, { messages: [], startedAt: Date.now(), listeners: /* @__PURE__ */ new Set() });
|
|
42820
|
+
};
|
|
42821
|
+
var markDone = (userId) => {
|
|
42822
|
+
registry.delete(userId);
|
|
42823
|
+
};
|
|
42824
|
+
var hasRunningAgent = (userId) => {
|
|
42825
|
+
return registry.has(userId);
|
|
42826
|
+
};
|
|
42827
|
+
var queueInterrupt = (userId, message) => {
|
|
42828
|
+
const entry = registry.get(userId);
|
|
42829
|
+
if (!entry) return false;
|
|
42830
|
+
const interruptMessage = typeof message === "string" ? { content: message } : message;
|
|
42831
|
+
entry.messages.push(interruptMessage);
|
|
42832
|
+
console.log(`[interrupt] \u7528\u6237 ${userId} \u65B0\u6D88\u606F\u5DF2\u5165\u961F\uFF0C\u5F53\u524D\u961F\u5217\u957F\u5EA6: ${entry.messages.length}`);
|
|
42833
|
+
for (const listener of entry.listeners) {
|
|
42834
|
+
try {
|
|
42835
|
+
listener();
|
|
42836
|
+
} catch (err) {
|
|
42837
|
+
console.warn(`[interrupt] \u7528\u6237 ${userId} \u4E2D\u65AD\u76D1\u542C\u5668\u6267\u884C\u5931\u8D25: ${err.message}`);
|
|
42838
|
+
}
|
|
42839
|
+
}
|
|
42840
|
+
return true;
|
|
42841
|
+
};
|
|
42842
|
+
var registerInterruptListener = (userId, listener) => {
|
|
42843
|
+
const entry = registry.get(userId);
|
|
42844
|
+
if (!entry) return () => void 0;
|
|
42845
|
+
entry.listeners.add(listener);
|
|
42846
|
+
return () => {
|
|
42847
|
+
entry.listeners.delete(listener);
|
|
42848
|
+
};
|
|
42849
|
+
};
|
|
42850
|
+
var drainInterrupts = (userId) => {
|
|
42851
|
+
const entry = registry.get(userId);
|
|
42852
|
+
if (!entry || entry.messages.length === 0) return [];
|
|
42853
|
+
const messages = [...entry.messages];
|
|
42854
|
+
entry.messages.length = 0;
|
|
42855
|
+
console.log(`[interrupt] \u7528\u6237 ${userId} drain ${messages.length} \u6761\u4E2D\u65AD\u6D88\u606F`);
|
|
42856
|
+
return messages;
|
|
42857
|
+
};
|
|
42858
|
+
|
|
42859
|
+
// src/agent/events.ts
|
|
42860
|
+
var import_node_crypto5 = require("node:crypto");
|
|
42861
|
+
var rowToEvent = (row) => ({
|
|
42862
|
+
id: row.id,
|
|
42863
|
+
userId: row.userId,
|
|
42864
|
+
type: row.type,
|
|
42865
|
+
source: row.source,
|
|
42866
|
+
sourceId: row.sourceId,
|
|
42867
|
+
status: row.status,
|
|
42868
|
+
payload: JSON.parse(row.payloadJson || "{}"),
|
|
42869
|
+
createdAt: row.createdAt,
|
|
42870
|
+
injectedAt: row.injectedAt ?? void 0,
|
|
42871
|
+
handledAt: row.handledAt ?? void 0,
|
|
42872
|
+
updatedAt: row.updatedAt
|
|
42873
|
+
});
|
|
42874
|
+
var recordAgentEvent = (input) => {
|
|
42875
|
+
const db3 = createSqliteDB();
|
|
42876
|
+
const now = Date.now();
|
|
42877
|
+
const id = `evt_${(0, import_node_crypto5.randomUUID)().slice(0, 12)}`;
|
|
42878
|
+
const payloadJson = JSON.stringify(input.payload);
|
|
42879
|
+
db3.prepare(`
|
|
42880
|
+
INSERT INTO agent_events (
|
|
42881
|
+
id, user_id, type, source, source_id, status, payload_json, created_at, updated_at
|
|
42882
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
42883
|
+
ON CONFLICT(type, source, source_id) DO UPDATE SET
|
|
42884
|
+
user_id = excluded.user_id,
|
|
42798
42885
|
status = CASE
|
|
42799
|
-
WHEN
|
|
42800
|
-
ELSE
|
|
42886
|
+
WHEN agent_events.status IN ('handled', 'ignored') THEN agent_events.status
|
|
42887
|
+
ELSE excluded.status
|
|
42801
42888
|
END,
|
|
42802
|
-
|
|
42803
|
-
origin_platform = excluded.origin_platform,
|
|
42804
|
-
from_mailbox_id = excluded.from_mailbox_id,
|
|
42805
|
-
thread_id = excluded.thread_id,
|
|
42806
|
-
parent_message_id = excluded.parent_message_id,
|
|
42807
|
-
work_item_id = excluded.work_item_id,
|
|
42808
|
-
content = excluded.content,
|
|
42889
|
+
payload_json = excluded.payload_json,
|
|
42809
42890
|
updated_at = excluded.updated_at
|
|
42810
42891
|
`).run(
|
|
42811
42892
|
id,
|
|
42812
|
-
|
|
42813
|
-
|
|
42814
|
-
|
|
42815
|
-
|
|
42816
|
-
|
|
42817
|
-
|
|
42818
|
-
message.workItemId ?? null,
|
|
42819
|
-
message.content,
|
|
42893
|
+
input.userId,
|
|
42894
|
+
input.type,
|
|
42895
|
+
input.source,
|
|
42896
|
+
input.sourceId,
|
|
42897
|
+
input.status ?? "pending",
|
|
42898
|
+
payloadJson,
|
|
42820
42899
|
now,
|
|
42821
42900
|
now
|
|
42822
42901
|
);
|
|
42823
42902
|
const row = db3.prepare(`
|
|
42824
|
-
SELECT
|
|
42825
|
-
|
|
42826
|
-
|
|
42903
|
+
SELECT
|
|
42904
|
+
id,
|
|
42905
|
+
user_id as userId,
|
|
42906
|
+
type,
|
|
42907
|
+
source,
|
|
42908
|
+
source_id as sourceId,
|
|
42909
|
+
status,
|
|
42910
|
+
payload_json as payloadJson,
|
|
42911
|
+
created_at as createdAt,
|
|
42912
|
+
injected_at as injectedAt,
|
|
42913
|
+
handled_at as handledAt,
|
|
42914
|
+
updated_at as updatedAt
|
|
42915
|
+
FROM agent_events
|
|
42916
|
+
WHERE type = ? AND source = ? AND source_id = ?
|
|
42917
|
+
`).get(input.type, input.source, input.sourceId);
|
|
42918
|
+
return rowToEvent(row);
|
|
42827
42919
|
};
|
|
42828
|
-
var
|
|
42920
|
+
var listPendingAgentEvents = (userId, limit = 10) => {
|
|
42829
42921
|
const db3 = createSqliteDB();
|
|
42830
42922
|
const rows = db3.prepare(`
|
|
42831
42923
|
SELECT
|
|
42832
42924
|
id,
|
|
42833
|
-
|
|
42925
|
+
user_id as userId,
|
|
42926
|
+
type,
|
|
42927
|
+
source,
|
|
42928
|
+
source_id as sourceId,
|
|
42834
42929
|
status,
|
|
42835
|
-
|
|
42836
|
-
origin_platform as originPlatform,
|
|
42837
|
-
from_mailbox_id as fromMailboxId,
|
|
42838
|
-
thread_id as threadId,
|
|
42839
|
-
parent_message_id as parentMessageId,
|
|
42840
|
-
work_item_id as workItemId,
|
|
42841
|
-
content,
|
|
42842
|
-
attempts,
|
|
42843
|
-
last_error as lastError,
|
|
42930
|
+
payload_json as payloadJson,
|
|
42844
42931
|
created_at as createdAt,
|
|
42845
|
-
|
|
42846
|
-
|
|
42847
|
-
|
|
42848
|
-
|
|
42932
|
+
injected_at as injectedAt,
|
|
42933
|
+
handled_at as handledAt,
|
|
42934
|
+
updated_at as updatedAt
|
|
42935
|
+
FROM agent_events
|
|
42936
|
+
WHERE user_id = ?
|
|
42937
|
+
AND status IN ('pending', 'processing')
|
|
42849
42938
|
ORDER BY created_at ASC
|
|
42850
42939
|
LIMIT ?
|
|
42851
|
-
`).all(limit);
|
|
42852
|
-
return rows.map(
|
|
42940
|
+
`).all(userId, limit);
|
|
42941
|
+
return rows.map(rowToEvent);
|
|
42853
42942
|
};
|
|
42854
|
-
var
|
|
42943
|
+
var markAgentEventsInjected = (eventIds) => {
|
|
42944
|
+
if (eventIds.length === 0) return;
|
|
42855
42945
|
const db3 = createSqliteDB();
|
|
42856
42946
|
const now = Date.now();
|
|
42857
|
-
const
|
|
42858
|
-
UPDATE
|
|
42859
|
-
SET status = 'processing',
|
|
42860
|
-
|
|
42947
|
+
const stmt = db3.prepare(`
|
|
42948
|
+
UPDATE agent_events
|
|
42949
|
+
SET status = CASE WHEN status = 'pending' THEN 'processing' ELSE status END,
|
|
42950
|
+
injected_at = COALESCE(injected_at, ?),
|
|
42861
42951
|
updated_at = ?
|
|
42862
42952
|
WHERE id = ?
|
|
42863
|
-
AND status IN ('pending', '
|
|
42864
|
-
`)
|
|
42865
|
-
|
|
42866
|
-
|
|
42867
|
-
};
|
|
42868
|
-
|
|
42869
|
-
const db3 = createSqliteDB();
|
|
42870
|
-
const now = Date.now();
|
|
42871
|
-
db3.prepare(`
|
|
42872
|
-
UPDATE ceo_followups
|
|
42873
|
-
SET status = 'completed',
|
|
42874
|
-
completed_at = COALESCE(completed_at, ?),
|
|
42875
|
-
updated_at = ?,
|
|
42876
|
-
last_error = NULL
|
|
42877
|
-
WHERE id = ?
|
|
42878
|
-
AND status IN ('pending', 'processing', 'failed')
|
|
42879
|
-
`).run(now, now, id);
|
|
42880
|
-
db3.prepare(`
|
|
42881
|
-
UPDATE mailbox
|
|
42882
|
-
SET status = 'done',
|
|
42883
|
-
updated_at = ?
|
|
42884
|
-
WHERE id = (SELECT source_message_id FROM ceo_followups WHERE id = ?)
|
|
42885
|
-
AND status IN ('pending', 'processing', 'read')
|
|
42886
|
-
`).run(now, id);
|
|
42953
|
+
AND status IN ('pending', 'processing')
|
|
42954
|
+
`);
|
|
42955
|
+
const tx = db3.transaction((ids) => {
|
|
42956
|
+
for (const id of ids) stmt.run(now, now, id);
|
|
42957
|
+
});
|
|
42958
|
+
tx(eventIds);
|
|
42887
42959
|
};
|
|
42888
|
-
var
|
|
42960
|
+
var markAgentEventsHandled = (eventIds, status = "handled") => {
|
|
42961
|
+
if (eventIds.length === 0) return;
|
|
42889
42962
|
const db3 = createSqliteDB();
|
|
42890
42963
|
const now = Date.now();
|
|
42891
|
-
db3.prepare(`
|
|
42892
|
-
UPDATE
|
|
42893
|
-
SET status =
|
|
42894
|
-
|
|
42964
|
+
const stmt = db3.prepare(`
|
|
42965
|
+
UPDATE agent_events
|
|
42966
|
+
SET status = ?,
|
|
42967
|
+
handled_at = COALESCE(handled_at, ?),
|
|
42895
42968
|
updated_at = ?
|
|
42896
42969
|
WHERE id = ?
|
|
42897
|
-
AND status IN ('pending', 'processing'
|
|
42898
|
-
`)
|
|
42899
|
-
|
|
42900
|
-
|
|
42901
|
-
const db3 = createSqliteDB();
|
|
42902
|
-
const now = Date.now();
|
|
42903
|
-
const result = db3.prepare(`
|
|
42904
|
-
UPDATE ceo_followups
|
|
42905
|
-
SET status = 'failed',
|
|
42906
|
-
last_error = 'stale_processing_recovered',
|
|
42907
|
-
updated_at = ?
|
|
42908
|
-
WHERE status = 'processing'
|
|
42909
|
-
AND updated_at < ?
|
|
42910
|
-
`).run(now, staleBefore);
|
|
42911
|
-
return result.changes;
|
|
42912
|
-
};
|
|
42913
|
-
var completePendingCeoFollowupsForUser = (originUserId) => {
|
|
42914
|
-
const db3 = createSqliteDB();
|
|
42915
|
-
const now = Date.now();
|
|
42916
|
-
const rows = db3.prepare(`
|
|
42917
|
-
SELECT id, source_message_id as sourceMessageId
|
|
42918
|
-
FROM ceo_followups
|
|
42919
|
-
WHERE origin_user_id = ?
|
|
42920
|
-
AND status IN ('pending', 'processing', 'failed')
|
|
42921
|
-
`).all(originUserId);
|
|
42922
|
-
const tx = db3.transaction((items) => {
|
|
42923
|
-
const completeStmt = db3.prepare(`
|
|
42924
|
-
UPDATE ceo_followups
|
|
42925
|
-
SET status = 'completed',
|
|
42926
|
-
completed_at = COALESCE(completed_at, ?),
|
|
42927
|
-
updated_at = ?,
|
|
42928
|
-
last_error = NULL
|
|
42929
|
-
WHERE id = ?
|
|
42930
|
-
AND status IN ('pending', 'processing', 'failed')
|
|
42931
|
-
`);
|
|
42932
|
-
const doneStmt = db3.prepare(`
|
|
42933
|
-
UPDATE mailbox
|
|
42934
|
-
SET status = 'done',
|
|
42935
|
-
updated_at = ?
|
|
42936
|
-
WHERE id = ?
|
|
42937
|
-
AND status IN ('pending', 'processing', 'read')
|
|
42938
|
-
`);
|
|
42939
|
-
for (const item of items) {
|
|
42940
|
-
completeStmt.run(now, now, item.id);
|
|
42941
|
-
doneStmt.run(now, item.sourceMessageId);
|
|
42942
|
-
}
|
|
42970
|
+
AND status IN ('pending', 'processing')
|
|
42971
|
+
`);
|
|
42972
|
+
const tx = db3.transaction((ids) => {
|
|
42973
|
+
for (const id of ids) stmt.run(status, now, now, id);
|
|
42943
42974
|
});
|
|
42944
|
-
tx(
|
|
42945
|
-
return rows.length;
|
|
42975
|
+
tx(eventIds);
|
|
42946
42976
|
};
|
|
42977
|
+
var renderAgentEventReminder = (events) => {
|
|
42978
|
+
if (events.length === 0) return "";
|
|
42979
|
+
const lines = events.map((event) => {
|
|
42980
|
+
const owner = typeof event.payload.ownerMailboxId === "string" ? event.payload.ownerMailboxId : void 0;
|
|
42981
|
+
const mailboxMessageId = typeof event.payload.mailboxMessageId === "string" ? event.payload.mailboxMessageId : event.sourceId;
|
|
42982
|
+
const summary = typeof event.payload.summary === "string" ? event.payload.summary : typeof event.payload.contentPreview === "string" ? event.payload.contentPreview : "";
|
|
42983
|
+
return [
|
|
42984
|
+
`- eventId=${event.id}`,
|
|
42985
|
+
`type=${event.type}`,
|
|
42986
|
+
owner ? `owner=${owner}` : "",
|
|
42987
|
+
mailboxMessageId ? `mailboxMessageId=${mailboxMessageId}` : "",
|
|
42988
|
+
summary ? `summary=${summary}` : ""
|
|
42989
|
+
].filter(Boolean).join(" ");
|
|
42990
|
+
}).join("\n");
|
|
42991
|
+
const hasCeoFollowup = events.some((event) => event.type === "ceo.followup_required");
|
|
42992
|
+
const ceoFollowupInstruction = hasCeoFollowup ? [
|
|
42993
|
+
``,
|
|
42994
|
+
`\u5176\u4E2D type=ceo.followup_required \u7684\u4E8B\u4EF6\uFF0C\u662F\u56E2\u961F\u5DF2\u7ECF\u628A\u7ED3\u679C\u56DE\u5230\u4E86\u4F60\u8FD9\u91CC\u2014\u2014\u8001\u677F\u8FD8\u5728\u7B49\u4F60\u628A\u8FD9\u4E9B\u7ED3\u679C\u8F6C\u8FBE\u7ED9\u4ED6\u3002`,
|
|
42995
|
+
`\u8BFB\u4E00\u904D\uFF0C\u7528\u4F60\u81EA\u5DF1\u7684\u8BDD\u7ED9\u8001\u677F\u6C47\u62A5\u4E00\u6B21\uFF1A\u6709\u591A\u6761\u5C31\u5408\u5E76\u6210\u4E00\u6761\u8BF4\u6E05\u695A\uFF0C\u522B\u4E00\u6761\u4E8B\u4EF6\u56DE\u4E00\u53E5\u3001\u628A\u540C\u4E00\u4EF6\u4E8B\u91CD\u590D\u53D1\u7ED9\u8001\u677F\u3002`,
|
|
42996
|
+
`\u5982\u679C\u7ED3\u679C\u8BF4\u660E\u4E8B\u60C5\u8FD8\u6CA1\u505A\u5B8C\u6216\u5361\u4F4F\u4E86\uFF0C\u5C31\u5982\u5B9E\u8FD9\u4E48\u8BB2\uFF0C\u800C\u4E0D\u662F\u542B\u7CCA\u5730\u201C\u7A0D\u540E\u540C\u6B65\u201D\u3002`
|
|
42997
|
+
].join("\n") : "";
|
|
42998
|
+
return `<system-reminder>
|
|
42999
|
+
\u672C\u8F6E\u6709 ${events.length} \u6761\u5185\u90E8\u4E8B\u4EF6\u53EF\u7528\uFF1A
|
|
43000
|
+
${lines}
|
|
42947
43001
|
|
|
42948
|
-
|
|
42949
|
-
|
|
42950
|
-
|
|
43002
|
+
\u8FD9\u4E9B\u4E8B\u4EF6\u4E0D\u662F\u7528\u6237\u7684\u65B0\u8BF7\u6C42\uFF0C\u4E5F\u4E0D\u5E94\u8BE5\u4F5C\u4E3A\u7528\u6237\u786E\u8BA4\u3002\u82E5\u4E8B\u4EF6\u7C7B\u578B\u662F mailbox.message_received\uFF0C\u8868\u793A\u4F60\u7684 mailbox \u5728\u5F53\u524D\u5DE5\u4F5C\u671F\u95F4\u6536\u5230\u65B0\u5185\u90E8\u534F\u4F5C\u6D88\u606F\uFF1B\u8BF7\u5C3D\u5FEB\u8C03\u7528 list_mailbox \u67E5\u770B\u961F\u5217\uFF0C\u5E76\u5728\u9700\u8981\u65F6\u7528 get_mailbox(message_id) \u9886\u53D6\u5173\u8054\u6D88\u606F\u3002\u4E0D\u8981\u76F4\u63A5\u628A\u4E8B\u4EF6\u5F53\u4F5C\u5DF2\u9886\u53D6\u90AE\u4EF6\u3002\u8BF7\u53EA\u5728\u9700\u8981\u65F6\u81EA\u7136\u5730\u6C47\u603B\u7ED9\u7528\u6237\uFF1B\u5982\u9700\u7EE7\u7EED\u534F\u4F5C\uFF0C\u4F18\u5148\u4F7F\u7528\u4E8B\u4EF6\u4E2D\u5173\u8054\u7684 mailboxMessageId/thread \u7EE7\u7EED\u5904\u7406\u3002\u4E0D\u8981\u590D\u8FF0\u672C system-reminder\u3002
|
|
43003
|
+
${ceoFollowupInstruction}
|
|
43004
|
+
</system-reminder>`;
|
|
42951
43005
|
};
|
|
42952
|
-
|
|
42953
|
-
|
|
42954
|
-
|
|
42955
|
-
|
|
42956
|
-
if (!
|
|
42957
|
-
|
|
43006
|
+
|
|
43007
|
+
// src/department/mailbox/events.ts
|
|
43008
|
+
var import_node_crypto6 = require("node:crypto");
|
|
43009
|
+
var parseDetail = (detailJson) => {
|
|
43010
|
+
if (!detailJson) return void 0;
|
|
43011
|
+
try {
|
|
43012
|
+
const parsed = JSON.parse(detailJson);
|
|
43013
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
43014
|
+
return parsed;
|
|
43015
|
+
}
|
|
43016
|
+
} catch {
|
|
43017
|
+
return void 0;
|
|
43018
|
+
}
|
|
43019
|
+
return void 0;
|
|
42958
43020
|
};
|
|
42959
|
-
var
|
|
43021
|
+
var mapMailboxEventRow = (row) => {
|
|
43022
|
+
const hasMessage = typeof row.toMailboxId === "string" && typeof row.fromMailboxId === "string" && typeof row.content === "string" && typeof row.sendTime === "number" && typeof row.status === "string";
|
|
43023
|
+
return {
|
|
43024
|
+
id: row.id,
|
|
43025
|
+
messageId: row.messageId || void 0,
|
|
43026
|
+
mailboxId: row.mailboxId,
|
|
43027
|
+
actorMailboxId: row.actorMailboxId || void 0,
|
|
43028
|
+
counterpartMailboxId: row.counterpartMailboxId || void 0,
|
|
43029
|
+
eventType: row.eventType,
|
|
43030
|
+
detail: parseDetail(row.detailJson),
|
|
43031
|
+
createdAt: row.createdAt,
|
|
43032
|
+
message: hasMessage ? {
|
|
43033
|
+
id: row.messageId || "",
|
|
43034
|
+
toMailboxId: row.toMailboxId,
|
|
43035
|
+
fromMailboxId: row.fromMailboxId,
|
|
43036
|
+
content: row.content,
|
|
43037
|
+
sendTime: row.sendTime,
|
|
43038
|
+
status: row.status,
|
|
43039
|
+
originUserId: row.originUserId || void 0,
|
|
43040
|
+
originPlatform: row.originPlatform || void 0,
|
|
43041
|
+
threadId: row.threadId || void 0,
|
|
43042
|
+
parentMessageId: row.parentMessageId || void 0
|
|
43043
|
+
} : null
|
|
43044
|
+
};
|
|
43045
|
+
};
|
|
43046
|
+
var recordMailboxEvent = (input) => {
|
|
42960
43047
|
const db3 = createSqliteDB();
|
|
43048
|
+
const event = {
|
|
43049
|
+
id: (0, import_node_crypto6.randomUUID)().slice(0, 12),
|
|
43050
|
+
messageId: input.messageId,
|
|
43051
|
+
mailboxId: input.mailboxId,
|
|
43052
|
+
actorMailboxId: input.actorMailboxId,
|
|
43053
|
+
counterpartMailboxId: input.counterpartMailboxId,
|
|
43054
|
+
eventType: input.eventType,
|
|
43055
|
+
detail: input.detail,
|
|
43056
|
+
createdAt: input.createdAt ?? Date.now()
|
|
43057
|
+
};
|
|
42961
43058
|
const stmt = db3.prepare(
|
|
42962
|
-
`
|
|
42963
|
-
|
|
42964
|
-
|
|
43059
|
+
`INSERT INTO mailbox_events (
|
|
43060
|
+
id,
|
|
43061
|
+
message_id,
|
|
43062
|
+
mailbox_id,
|
|
43063
|
+
actor_mailbox_id,
|
|
43064
|
+
counterpart_mailbox_id,
|
|
43065
|
+
event_type,
|
|
43066
|
+
detail_json,
|
|
43067
|
+
created_at
|
|
43068
|
+
) VALUES (?,?,?,?,?,?,?,?)`
|
|
42965
43069
|
);
|
|
42966
|
-
|
|
42967
|
-
|
|
42968
|
-
|
|
42969
|
-
|
|
42970
|
-
|
|
42971
|
-
|
|
42972
|
-
|
|
42973
|
-
|
|
43070
|
+
stmt.run(
|
|
43071
|
+
event.id,
|
|
43072
|
+
event.messageId || null,
|
|
43073
|
+
event.mailboxId,
|
|
43074
|
+
event.actorMailboxId || null,
|
|
43075
|
+
event.counterpartMailboxId || null,
|
|
43076
|
+
event.eventType,
|
|
43077
|
+
event.detail ? JSON.stringify(event.detail) : null,
|
|
43078
|
+
event.createdAt
|
|
43079
|
+
);
|
|
43080
|
+
return event;
|
|
42974
43081
|
};
|
|
42975
|
-
var
|
|
42976
|
-
if (
|
|
42977
|
-
|
|
42978
|
-
const row = db3.prepare(
|
|
42979
|
-
`SELECT
|
|
42980
|
-
work_item_id as workItemId,
|
|
42981
|
-
work_item_role as workItemRole,
|
|
42982
|
-
upstream_message_id as upstreamMessageId
|
|
42983
|
-
FROM mailbox
|
|
42984
|
-
WHERE id = ?`
|
|
42985
|
-
).get(messageId);
|
|
42986
|
-
if (!row?.workItemId) return null;
|
|
42987
|
-
return row;
|
|
42988
|
-
};
|
|
42989
|
-
var getWorkItemContextFromThread = (threadId) => {
|
|
42990
|
-
if (!threadId) return null;
|
|
42991
|
-
const db3 = createSqliteDB();
|
|
42992
|
-
const row = db3.prepare(
|
|
42993
|
-
`SELECT
|
|
42994
|
-
work_item_id as workItemId,
|
|
42995
|
-
work_item_role as workItemRole,
|
|
42996
|
-
upstream_message_id as upstreamMessageId
|
|
42997
|
-
FROM mailbox
|
|
42998
|
-
WHERE thread_id = ?
|
|
42999
|
-
AND work_item_id IS NOT NULL
|
|
43000
|
-
ORDER BY send_time ASC
|
|
43001
|
-
LIMIT 1`
|
|
43002
|
-
).get(threadId);
|
|
43003
|
-
if (!row?.workItemId) return null;
|
|
43004
|
-
return row;
|
|
43005
|
-
};
|
|
43006
|
-
var mailboxLooksLikeRole = (mailboxId, role) => {
|
|
43007
|
-
const lower = mailboxId.toLowerCase();
|
|
43008
|
-
if (role === "department_head") {
|
|
43009
|
-
return lower.includes("department-head") || mailboxId.includes("\u8D1F\u8D23\u4EBA");
|
|
43010
|
-
}
|
|
43011
|
-
return lower.includes("executor") || mailboxId.includes("\u6267\u884C\u8005") || mailboxId.includes("\u4E13\u5458");
|
|
43012
|
-
};
|
|
43013
|
-
var inferWorkItemRole = (fromMailboxId, toMailboxId, inherited) => {
|
|
43014
|
-
if (fromMailboxId === "manager") return "upstream_request";
|
|
43015
|
-
if (toMailboxId === "manager") return "upstream_report";
|
|
43016
|
-
const fromMember = getDepartmentMemberByMailboxId(fromMailboxId);
|
|
43017
|
-
const toMember = getDepartmentMemberByMailboxId(toMailboxId);
|
|
43018
|
-
const fromIsHead = fromMember?.role === "department_head" || mailboxLooksLikeRole(fromMailboxId, "department_head");
|
|
43019
|
-
const toIsHead = toMember?.role === "department_head" || mailboxLooksLikeRole(toMailboxId, "department_head");
|
|
43020
|
-
const fromIsExecutor = fromMember?.role === "executor" || mailboxLooksLikeRole(fromMailboxId, "executor");
|
|
43021
|
-
const toIsExecutor = toMember?.role === "executor" || mailboxLooksLikeRole(toMailboxId, "executor");
|
|
43022
|
-
if (fromIsHead && toIsExecutor) {
|
|
43023
|
-
return inherited?.workItemRole === "executor_result" ? "downstream_reply" : "delegation";
|
|
43024
|
-
}
|
|
43025
|
-
if (fromIsExecutor && toIsHead) return "executor_result";
|
|
43026
|
-
return inherited?.workItemRole ? "followup" : "message";
|
|
43027
|
-
};
|
|
43028
|
-
var resolveWorkItemContext = (fromMailboxId, toMailboxId, id, options) => {
|
|
43029
|
-
if (options?.workItemId) {
|
|
43030
|
-
return {
|
|
43031
|
-
workItemId: options.workItemId,
|
|
43032
|
-
workItemRole: options.workItemRole ?? inferWorkItemRole(fromMailboxId, toMailboxId),
|
|
43033
|
-
upstreamMessageId: options.upstreamMessageId ?? options.workItemId
|
|
43034
|
-
};
|
|
43035
|
-
}
|
|
43036
|
-
const inherited = getWorkItemContextFromMessage(options?.parentMessageId) ?? getWorkItemContextFromThread(options?.threadId);
|
|
43037
|
-
if (inherited?.workItemId) {
|
|
43038
|
-
return {
|
|
43039
|
-
workItemId: inherited.workItemId,
|
|
43040
|
-
workItemRole: options?.workItemRole ?? inferWorkItemRole(fromMailboxId, toMailboxId, inherited),
|
|
43041
|
-
upstreamMessageId: inherited.upstreamMessageId ?? inherited.workItemId
|
|
43042
|
-
};
|
|
43043
|
-
}
|
|
43044
|
-
const targetMember = getDepartmentMemberByMailboxId(toMailboxId);
|
|
43045
|
-
if (fromMailboxId === "manager" && targetMember?.role === "department_head") {
|
|
43046
|
-
return {
|
|
43047
|
-
workItemId: id,
|
|
43048
|
-
workItemRole: "upstream_request",
|
|
43049
|
-
upstreamMessageId: id
|
|
43050
|
-
};
|
|
43051
|
-
}
|
|
43052
|
-
return {
|
|
43053
|
-
workItemRole: options?.workItemRole ?? inferWorkItemRole(fromMailboxId, toMailboxId)
|
|
43054
|
-
};
|
|
43055
|
-
};
|
|
43056
|
-
var buildMailboxInterruptContent = (msg) => {
|
|
43057
|
-
const from = msg.fromMailboxId;
|
|
43058
|
-
return [
|
|
43059
|
-
`<system_reminder>`,
|
|
43060
|
-
`\u4F60\u7684 mailbox \u6536\u5230\u4E00\u5C01\u65B0\u7684\u5185\u90E8\u534F\u4F5C\u6D88\u606F\u3002`,
|
|
43061
|
-
``,
|
|
43062
|
-
`message_id: ${msg.id}`,
|
|
43063
|
-
`from: ${from}`,
|
|
43064
|
-
`thread: ${msg.threadId || msg.id}`,
|
|
43065
|
-
``,
|
|
43066
|
-
`\u8FD9\u662F\u4E00\u6761\u4E2D\u65AD\u63D0\u9192\uFF0C\u4E0D\u4EE3\u8868\u90AE\u4EF6\u5DF2\u88AB\u9886\u53D6\u3002\u8BF7\u5C3D\u5FEB\u91CD\u65B0\u8BC4\u4F30\u5F53\u524D\u5DE5\u4F5C\u4F18\u5148\u7EA7\uFF1A`,
|
|
43067
|
-
`1. \u8C03\u7528 list_mailbox \u67E5\u770B\u5F85\u5904\u7406\u961F\u5217\u3002`,
|
|
43068
|
-
`2. \u5982\u8BE5\u6D88\u606F\u66F4\u7D27\u6025\uFF0C\u8C03\u7528 get_mailbox(message_id="${msg.id}") \u9886\u53D6\u5E76\u8BFB\u53D6\u3002`,
|
|
43069
|
-
`3. \u5982\u679C\u4F60\u6B63\u5728\u8FD0\u884C\u957F\u4EFB\u52A1\uFF0C\u5E94\u5148\u8BB0\u5F55\u5F53\u524D\u8FDB\u5C55\uFF0C\u5FC5\u8981\u65F6\u7528 mailbox_followup \u540C\u6B65\u72B6\u6001\uFF0C\u518D\u5904\u7406\u8FD9\u5C01\u65B0\u6D88\u606F\u3002`,
|
|
43070
|
-
`4. \u5F62\u6210\u6B63\u5F0F\u7B54\u590D\u540E\u5FC5\u987B\u7528 reply_mailbox \u56DE\u590D\u5BF9\u5E94 message_id\u3002`,
|
|
43071
|
-
`</system_reminder>`
|
|
43072
|
-
].join("\n");
|
|
43073
|
-
};
|
|
43074
|
-
var queueMailboxInterruptIfRunning = (msg) => {
|
|
43075
|
-
if (msg.toMailboxId === "manager") return;
|
|
43076
|
-
if (!hasRunningAgent(msg.toMailboxId)) return;
|
|
43077
|
-
const queued = queueInterrupt(msg.toMailboxId, {
|
|
43078
|
-
content: buildMailboxInterruptContent(msg),
|
|
43079
|
-
metadata: {
|
|
43080
|
-
trigger: "mailbox.message_received",
|
|
43081
|
-
mailboxMessageId: msg.id,
|
|
43082
|
-
fromMailboxId: msg.fromMailboxId,
|
|
43083
|
-
toMailboxId: msg.toMailboxId,
|
|
43084
|
-
threadId: msg.threadId || msg.id
|
|
43085
|
-
}
|
|
43086
|
-
});
|
|
43087
|
-
if (queued) {
|
|
43088
|
-
console.log(`[mailbox] \u76EE\u6807 agent ${msg.toMailboxId} \u6B63\u5728\u8FD0\u884C\uFF0C\u5DF2\u5C06\u65B0\u90AE\u4EF6 ${msg.id} \u4F5C\u4E3A\u4E2D\u65AD\u63D0\u9192\u5165\u961F`);
|
|
43082
|
+
var recordMailboxStatusChange = (params) => {
|
|
43083
|
+
if (params.previousStatus === params.nextStatus) {
|
|
43084
|
+
return null;
|
|
43089
43085
|
}
|
|
43090
|
-
|
|
43091
|
-
|
|
43092
|
-
|
|
43093
|
-
|
|
43094
|
-
|
|
43095
|
-
|
|
43096
|
-
|
|
43097
|
-
|
|
43098
|
-
|
|
43099
|
-
|
|
43100
|
-
mailboxMessageId: msg.id,
|
|
43101
|
-
fromMailboxId: msg.fromMailboxId,
|
|
43102
|
-
toMailboxId: msg.toMailboxId,
|
|
43103
|
-
threadId: msg.threadId || msg.id,
|
|
43104
|
-
contentPreview: msg.content.slice(0, 160),
|
|
43105
|
-
summary: `\u6536\u5230\u6765\u81EA ${msg.fromMailboxId} \u7684\u65B0\u5185\u90E8\u534F\u4F5C\u6D88\u606F\uFF0C\u8BF7\u7528 list_mailbox/get_mailbox \u8BC4\u4F30\u5E76\u9886\u53D6\u3002`
|
|
43086
|
+
return recordMailboxEvent({
|
|
43087
|
+
messageId: params.messageId,
|
|
43088
|
+
mailboxId: params.mailboxId,
|
|
43089
|
+
actorMailboxId: params.actorMailboxId,
|
|
43090
|
+
counterpartMailboxId: params.counterpartMailboxId,
|
|
43091
|
+
eventType: "message_status_changed",
|
|
43092
|
+
detail: {
|
|
43093
|
+
previousStatus: params.previousStatus,
|
|
43094
|
+
nextStatus: params.nextStatus,
|
|
43095
|
+
reason: params.reason
|
|
43106
43096
|
}
|
|
43107
43097
|
});
|
|
43108
43098
|
};
|
|
43109
|
-
var
|
|
43099
|
+
var listMailboxEvents = (params) => {
|
|
43110
43100
|
const db3 = createSqliteDB();
|
|
43111
|
-
const
|
|
43112
|
-
const
|
|
43113
|
-
|
|
43114
|
-
|
|
43115
|
-
|
|
43116
|
-
|
|
43117
|
-
|
|
43118
|
-
|
|
43119
|
-
|
|
43120
|
-
|
|
43121
|
-
|
|
43122
|
-
|
|
43123
|
-
|
|
43124
|
-
|
|
43125
|
-
|
|
43126
|
-
|
|
43127
|
-
|
|
43128
|
-
|
|
43129
|
-
|
|
43130
|
-
|
|
43131
|
-
|
|
43132
|
-
|
|
43133
|
-
|
|
43134
|
-
|
|
43135
|
-
|
|
43136
|
-
originUserId: options?.originUserId,
|
|
43137
|
-
originPlatform: options?.originPlatform,
|
|
43138
|
-
threadId,
|
|
43139
|
-
parentMessageId: options?.parentMessageId,
|
|
43140
|
-
workItemId: workItemContext.workItemId,
|
|
43141
|
-
workItemRole: workItemContext.workItemRole,
|
|
43142
|
-
upstreamMessageId: workItemContext.upstreamMessageId
|
|
43143
|
-
};
|
|
43144
|
-
const result = stmt.run(
|
|
43145
|
-
mailboxMsg.id,
|
|
43146
|
-
mailboxMsg.toMailboxId,
|
|
43147
|
-
mailboxMsg.fromMailboxId,
|
|
43148
|
-
mailboxMsg.content,
|
|
43149
|
-
mailboxMsg.sendTime,
|
|
43150
|
-
mailboxMsg.status,
|
|
43151
|
-
mailboxMsg.originUserId || null,
|
|
43152
|
-
mailboxMsg.originPlatform || null,
|
|
43153
|
-
mailboxMsg.threadId || mailboxMsg.id,
|
|
43154
|
-
mailboxMsg.parentMessageId || null,
|
|
43155
|
-
mailboxMsg.workItemId || null,
|
|
43156
|
-
mailboxMsg.workItemRole || null,
|
|
43157
|
-
mailboxMsg.upstreamMessageId || null
|
|
43101
|
+
const limit = Math.max(1, Math.min(params.limit ?? 100, 500));
|
|
43102
|
+
const stmt = db3.prepare(
|
|
43103
|
+
`SELECT
|
|
43104
|
+
e.id as id,
|
|
43105
|
+
e.message_id as messageId,
|
|
43106
|
+
e.mailbox_id as mailboxId,
|
|
43107
|
+
e.actor_mailbox_id as actorMailboxId,
|
|
43108
|
+
e.counterpart_mailbox_id as counterpartMailboxId,
|
|
43109
|
+
e.event_type as eventType,
|
|
43110
|
+
e.detail_json as detailJson,
|
|
43111
|
+
e.created_at as createdAt,
|
|
43112
|
+
m.to_mailbox_id as toMailboxId,
|
|
43113
|
+
m.from_mailbox_id as fromMailboxId,
|
|
43114
|
+
m.content as content,
|
|
43115
|
+
m.send_time as sendTime,
|
|
43116
|
+
m.status as status,
|
|
43117
|
+
m.origin_user_id as originUserId,
|
|
43118
|
+
m.origin_platform as originPlatform,
|
|
43119
|
+
m.thread_id as threadId,
|
|
43120
|
+
m.parent_message_id as parentMessageId
|
|
43121
|
+
FROM mailbox_events e
|
|
43122
|
+
LEFT JOIN mailbox m ON m.id = e.message_id
|
|
43123
|
+
WHERE e.mailbox_id = ? OR e.actor_mailbox_id = ? OR e.counterpart_mailbox_id = ?
|
|
43124
|
+
ORDER BY e.created_at DESC
|
|
43125
|
+
LIMIT ?`
|
|
43158
43126
|
);
|
|
43159
|
-
|
|
43160
|
-
|
|
43161
|
-
mailboxId: toMailboxId,
|
|
43162
|
-
actorMailboxId: fromMailboxId,
|
|
43163
|
-
counterpartMailboxId: fromMailboxId,
|
|
43164
|
-
eventType: "message_sent",
|
|
43165
|
-
detail: {
|
|
43166
|
-
initialStatus: mailboxMsg.status,
|
|
43167
|
-
workItemId: mailboxMsg.workItemId ?? null,
|
|
43168
|
-
workItemRole: mailboxMsg.workItemRole ?? null,
|
|
43169
|
-
upstreamMessageId: mailboxMsg.upstreamMessageId ?? null,
|
|
43170
|
-
...options?.auditDetail ?? {}
|
|
43171
|
-
},
|
|
43172
|
-
createdAt: mailboxMsg.sendTime
|
|
43173
|
-
});
|
|
43174
|
-
recordMailboxReceivedAgentEvent(mailboxMsg);
|
|
43175
|
-
queueMailboxInterruptIfRunning(mailboxMsg);
|
|
43176
|
-
enqueueCeoFollowupFromMailbox(mailboxMsg);
|
|
43177
|
-
return mailboxMsg;
|
|
43127
|
+
const rows = stmt.all(params.mailboxId, params.mailboxId, params.mailboxId, limit);
|
|
43128
|
+
return rows.map(mapMailboxEventRow);
|
|
43178
43129
|
};
|
|
43179
|
-
|
|
43130
|
+
|
|
43131
|
+
// src/department/mailbox/ceoFollowup.ts
|
|
43132
|
+
var import_node_crypto7 = require("node:crypto");
|
|
43133
|
+
var rowToFollowup = (row) => ({
|
|
43134
|
+
id: row.id,
|
|
43135
|
+
sourceMessageId: row.sourceMessageId,
|
|
43136
|
+
status: row.status,
|
|
43137
|
+
originUserId: row.originUserId,
|
|
43138
|
+
originPlatform: row.originPlatform,
|
|
43139
|
+
fromMailboxId: row.fromMailboxId,
|
|
43140
|
+
threadId: row.threadId ?? void 0,
|
|
43141
|
+
parentMessageId: row.parentMessageId ?? void 0,
|
|
43142
|
+
workItemId: row.workItemId ?? void 0,
|
|
43143
|
+
content: row.content,
|
|
43144
|
+
attempts: row.attempts,
|
|
43145
|
+
lastError: row.lastError ?? void 0,
|
|
43146
|
+
createdAt: row.createdAt,
|
|
43147
|
+
updatedAt: row.updatedAt,
|
|
43148
|
+
completedAt: row.completedAt ?? void 0
|
|
43149
|
+
});
|
|
43150
|
+
var selectById = (id) => {
|
|
43180
43151
|
const db3 = createSqliteDB();
|
|
43181
|
-
const
|
|
43182
|
-
|
|
43183
|
-
|
|
43184
|
-
|
|
43185
|
-
|
|
43186
|
-
|
|
43187
|
-
|
|
43188
|
-
|
|
43189
|
-
|
|
43190
|
-
|
|
43191
|
-
|
|
43192
|
-
|
|
43193
|
-
|
|
43194
|
-
|
|
43195
|
-
|
|
43196
|
-
|
|
43197
|
-
|
|
43198
|
-
|
|
43199
|
-
|
|
43200
|
-
|
|
43201
|
-
|
|
43202
|
-
previousStatus: existing.status,
|
|
43203
|
-
nextStatus,
|
|
43204
|
-
actorMailboxId: options?.actorMailboxId,
|
|
43205
|
-
counterpartMailboxId: options?.counterpartMailboxId || existing.fromMailboxId,
|
|
43206
|
-
reason: options?.reason
|
|
43207
|
-
});
|
|
43208
|
-
return true;
|
|
43209
|
-
};
|
|
43210
|
-
|
|
43211
|
-
// src/tools/tools/department/DepartmentCreate.ts
|
|
43212
|
-
var DESCRIPTION20 = `
|
|
43213
|
-
\u521B\u5EFA\u90E8\u95E8\u3002Department \u662F\u516C\u53F8\u7EC4\u7EC7\u4E2D\u7684\u957F\u671F\u804C\u8D23\u5355\u5143\uFF0C\u4E0D\u662F\u4E00\u6B21\u6027\u9879\u76EE\u5C0F\u961F\u3002
|
|
43214
|
-
|
|
43215
|
-
\u5DE5\u5177\u8C03\u7528\u89C4\u5219\uFF1A
|
|
43216
|
-
- \u5F53\u4E00\u4E2A\u590D\u6742\u3001\u957F\u671F\u3001\u4E13\u4E1A\u804C\u8D23\u9700\u8981\u7A33\u5B9A\u7EC4\u7EC7\u627F\u63A5\u65F6\u8C03\u7528\u6B64\u5DE5\u5177\u3002
|
|
43217
|
-
- sourceGoalId \u662F\u53EF\u9009\u6765\u6E90\u76EE\u6807\uFF1B\u90E8\u95E8\u804C\u8D23\u5E94\u5199\u5165 charter\uFF0C\u4E0D\u8981\u628A\u4E00\u6B21\u6027\u4EFB\u52A1\u7EC6\u8282\u5199\u8FDB charter\u3002
|
|
43218
|
-
- \u521B\u5EFA\u90E8\u95E8\u540E\uFF0CCEO \u5E94\u4F7F\u7528 department_member_create \u4EFB\u547D Department Head\uFF0C\u518D\u7528 department_communicate \u53D1\u9001\u672C\u6B21\u5177\u4F53\u4EFB\u52A1\u3002
|
|
43219
|
-
`;
|
|
43220
|
-
var departmentCreate = {
|
|
43221
|
-
name: `department_create`,
|
|
43222
|
-
description: DESCRIPTION20,
|
|
43223
|
-
input_schema: {
|
|
43224
|
-
type: `object`,
|
|
43225
|
-
properties: {
|
|
43226
|
-
name: {
|
|
43227
|
-
type: `string`,
|
|
43228
|
-
description: `\u90E8\u95E8\u540D\u79F0`
|
|
43229
|
-
},
|
|
43230
|
-
charter: {
|
|
43231
|
-
type: `string`,
|
|
43232
|
-
description: `\u90E8\u95E8\u957F\u671F\u804C\u8D23\u8FB9\u754C\uFF0C\u4E0D\u80FD\u5199\u4E00\u6B21\u6027\u4EFB\u52A1\u7EC6\u8282`
|
|
43233
|
-
},
|
|
43234
|
-
sourceGoalId: {
|
|
43235
|
-
type: `string`,
|
|
43236
|
-
description: `\u53EF\u9009\uFF1A\u521B\u5EFA\u8BE5\u90E8\u95E8\u65F6\u5173\u8054\u7684\u76EE\u6807 id`
|
|
43237
|
-
},
|
|
43238
|
-
workpath: {
|
|
43239
|
-
type: `string`,
|
|
43240
|
-
description: `\u90E8\u95E8\u9879\u76EE\u5DE5\u4F5C\u76EE\u5F55\uFF08\u7EDD\u5BF9\u8DEF\u5F84\uFF09\uFF0C\u90E8\u95E8\u6210\u5458\u7684\u6587\u4EF6\u4FEE\u6539\u5E94\u9650\u5236\u5728\u6B64\u76EE\u5F55\u8303\u56F4\u5185`
|
|
43241
|
-
}
|
|
43242
|
-
},
|
|
43243
|
-
required: [`name`, `charter`, `workpath`]
|
|
43244
|
-
},
|
|
43245
|
-
async execute(input) {
|
|
43246
|
-
const name = input.name;
|
|
43247
|
-
const charter = input.charter;
|
|
43248
|
-
const sourceGoalId = input.sourceGoalId;
|
|
43249
|
-
const workpath = input.workpath;
|
|
43250
|
-
if (sourceGoalId && !getGoalById(sourceGoalId)) {
|
|
43251
|
-
return `[departmentCreate] \u4E0D\u5B58\u5728 id=${sourceGoalId} \u7684\u76EE\u6807`;
|
|
43252
|
-
}
|
|
43253
|
-
let departmentDefinition = {
|
|
43254
|
-
id: (0, import_node_crypto8.randomUUID)().slice(0, 8),
|
|
43255
|
-
name,
|
|
43256
|
-
charter,
|
|
43257
|
-
sourceGoalId,
|
|
43258
|
-
workpath,
|
|
43259
|
-
departmentMembers: []
|
|
43260
|
-
};
|
|
43261
|
-
try {
|
|
43262
|
-
departmentDefinition = createDepartment(departmentDefinition);
|
|
43263
|
-
} catch (err) {
|
|
43264
|
-
return `[departmentCreate] \u521B\u5EFA\u90E8\u95E8\u5931\u8D25: ${err.message}`;
|
|
43265
|
-
}
|
|
43266
|
-
return `[departmentCreate] \u521B\u5EFA\u90E8\u95E8\u6210\u529F: ${JSON.stringify(departmentDefinition)}`;
|
|
43267
|
-
}
|
|
43152
|
+
const row = db3.prepare(`
|
|
43153
|
+
SELECT
|
|
43154
|
+
id,
|
|
43155
|
+
source_message_id as sourceMessageId,
|
|
43156
|
+
status,
|
|
43157
|
+
origin_user_id as originUserId,
|
|
43158
|
+
origin_platform as originPlatform,
|
|
43159
|
+
from_mailbox_id as fromMailboxId,
|
|
43160
|
+
thread_id as threadId,
|
|
43161
|
+
parent_message_id as parentMessageId,
|
|
43162
|
+
work_item_id as workItemId,
|
|
43163
|
+
content,
|
|
43164
|
+
attempts,
|
|
43165
|
+
last_error as lastError,
|
|
43166
|
+
created_at as createdAt,
|
|
43167
|
+
updated_at as updatedAt,
|
|
43168
|
+
completed_at as completedAt
|
|
43169
|
+
FROM ceo_followups
|
|
43170
|
+
WHERE id = ?
|
|
43171
|
+
`).get(id);
|
|
43172
|
+
return row ? rowToFollowup(row) : null;
|
|
43268
43173
|
};
|
|
43269
|
-
|
|
43270
|
-
|
|
43271
|
-
|
|
43272
|
-
|
|
43273
|
-
|
|
43274
|
-
|
|
43275
|
-
|
|
43276
|
-
|
|
43174
|
+
var enqueueCeoFollowupFromMailbox = (message) => {
|
|
43175
|
+
if (message.toMailboxId !== "manager") return null;
|
|
43176
|
+
if (!message.originUserId || !message.originPlatform) return null;
|
|
43177
|
+
const db3 = createSqliteDB();
|
|
43178
|
+
const now = Date.now();
|
|
43179
|
+
const id = `cfu_${(0, import_node_crypto7.randomUUID)().slice(0, 12)}`;
|
|
43180
|
+
db3.prepare(`
|
|
43181
|
+
INSERT INTO ceo_followups (
|
|
43182
|
+
id,
|
|
43183
|
+
source_message_id,
|
|
43184
|
+
status,
|
|
43185
|
+
origin_user_id,
|
|
43186
|
+
origin_platform,
|
|
43187
|
+
from_mailbox_id,
|
|
43188
|
+
thread_id,
|
|
43189
|
+
parent_message_id,
|
|
43190
|
+
work_item_id,
|
|
43191
|
+
content,
|
|
43192
|
+
created_at,
|
|
43193
|
+
updated_at
|
|
43194
|
+
) VALUES (?, ?, 'pending', ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
43195
|
+
ON CONFLICT(source_message_id) DO UPDATE SET
|
|
43196
|
+
status = CASE
|
|
43197
|
+
WHEN ceo_followups.status = 'completed' THEN ceo_followups.status
|
|
43198
|
+
ELSE 'pending'
|
|
43199
|
+
END,
|
|
43200
|
+
origin_user_id = excluded.origin_user_id,
|
|
43201
|
+
origin_platform = excluded.origin_platform,
|
|
43202
|
+
from_mailbox_id = excluded.from_mailbox_id,
|
|
43203
|
+
thread_id = excluded.thread_id,
|
|
43204
|
+
parent_message_id = excluded.parent_message_id,
|
|
43205
|
+
work_item_id = excluded.work_item_id,
|
|
43206
|
+
content = excluded.content,
|
|
43207
|
+
updated_at = excluded.updated_at
|
|
43208
|
+
`).run(
|
|
43209
|
+
id,
|
|
43210
|
+
message.id,
|
|
43211
|
+
message.originUserId,
|
|
43212
|
+
message.originPlatform,
|
|
43213
|
+
message.fromMailboxId,
|
|
43214
|
+
message.threadId ?? message.id,
|
|
43215
|
+
message.parentMessageId ?? null,
|
|
43216
|
+
message.workItemId ?? null,
|
|
43217
|
+
message.content,
|
|
43218
|
+
now,
|
|
43219
|
+
now
|
|
43220
|
+
);
|
|
43221
|
+
const row = db3.prepare(`
|
|
43222
|
+
SELECT id FROM ceo_followups WHERE source_message_id = ?
|
|
43223
|
+
`).get(message.id);
|
|
43224
|
+
return row ? selectById(row.id) : null;
|
|
43277
43225
|
};
|
|
43278
|
-
var
|
|
43279
|
-
`[departmentCommunicate] \u62D2\u7EDD\u53D1\u9001\u5230\u4F2A manager mailbox\u3002`,
|
|
43280
|
-
`Main Manager/CEO \u4E0D\u662F\u90E8\u95E8\u6210\u5458\uFF0C\u4E0D\u80FD\u7528 department_communicate \u53D1\u9001\u5230 manager\u3001Department::Manager\u3001CEO::Manager \u7B49\u5730\u5740\u3002`,
|
|
43281
|
-
activeContext ? `\u5982\u679C\u8981\u5411\u4E0A\u6E38 CEO \u6C47\u62A5\uFF0C\u8BF7\u8C03\u7528 reply_mailbox(message_id="${activeContext.id}", content="...") \u6B63\u5F0F\u56DE\u590D\u539F\u90AE\u4EF6\uFF1B\u82E5\u53EA\u662F\u540C\u6B65\u9636\u6BB5\u8FDB\u5C55\uFF0C\u8BF7\u8C03\u7528 mailbox_followup(message_id="${activeContext.id}", content="...", kind="progress")\u3002` : `\u5982\u679C\u8981\u5411\u4E0A\u6E38 CEO \u6C47\u62A5\uFF0C\u8BF7\u56DE\u5230\u539F manager \u90AE\u4EF6\uFF0C\u4F7F\u7528 reply_mailbox(message_id="\u539F\u90AE\u4EF6ID", content="...") \u6216 mailbox_followup(message_id="\u539F\u90AE\u4EF6ID", content="...", kind="progress")\u3002`
|
|
43282
|
-
].join(`
|
|
43283
|
-
`);
|
|
43284
|
-
var getActiveMailboxContext = (actorMailboxId, messageId) => {
|
|
43285
|
-
if (!messageId) return null;
|
|
43226
|
+
var listPendingCeoFollowups = (limit = 10) => {
|
|
43286
43227
|
const db3 = createSqliteDB();
|
|
43287
|
-
const
|
|
43288
|
-
|
|
43228
|
+
const rows = db3.prepare(`
|
|
43229
|
+
SELECT
|
|
43289
43230
|
id,
|
|
43290
|
-
|
|
43291
|
-
|
|
43231
|
+
source_message_id as sourceMessageId,
|
|
43232
|
+
status,
|
|
43292
43233
|
origin_user_id as originUserId,
|
|
43293
43234
|
origin_platform as originPlatform,
|
|
43235
|
+
from_mailbox_id as fromMailboxId,
|
|
43294
43236
|
thread_id as threadId,
|
|
43237
|
+
parent_message_id as parentMessageId,
|
|
43295
43238
|
work_item_id as workItemId,
|
|
43296
|
-
|
|
43297
|
-
|
|
43298
|
-
|
|
43299
|
-
|
|
43300
|
-
|
|
43301
|
-
|
|
43239
|
+
content,
|
|
43240
|
+
attempts,
|
|
43241
|
+
last_error as lastError,
|
|
43242
|
+
created_at as createdAt,
|
|
43243
|
+
updated_at as updatedAt,
|
|
43244
|
+
completed_at as completedAt
|
|
43245
|
+
FROM ceo_followups
|
|
43246
|
+
WHERE status IN ('pending', 'failed')
|
|
43247
|
+
ORDER BY created_at ASC
|
|
43248
|
+
LIMIT ?
|
|
43249
|
+
`).all(limit);
|
|
43250
|
+
return rows.map(rowToFollowup);
|
|
43302
43251
|
};
|
|
43303
|
-
var
|
|
43304
|
-
|
|
43305
|
-
|
|
43306
|
-
|
|
43307
|
-
|
|
43308
|
-
|
|
43309
|
-
|
|
43310
|
-
|
|
43311
|
-
|
|
43312
|
-
|
|
43313
|
-
|
|
43314
|
-
|
|
43315
|
-
|
|
43316
|
-
|
|
43317
|
-
var
|
|
43318
|
-
|
|
43319
|
-
|
|
43320
|
-
|
|
43321
|
-
|
|
43322
|
-
|
|
43323
|
-
|
|
43324
|
-
|
|
43325
|
-
|
|
43326
|
-
|
|
43327
|
-
|
|
43328
|
-
|
|
43329
|
-
|
|
43330
|
-
|
|
43331
|
-
|
|
43332
|
-
|
|
43333
|
-
|
|
43334
|
-
|
|
43335
|
-
|
|
43336
|
-
|
|
43337
|
-
|
|
43338
|
-
|
|
43339
|
-
|
|
43340
|
-
|
|
43341
|
-
|
|
43342
|
-
|
|
43343
|
-
|
|
43344
|
-
|
|
43345
|
-
|
|
43346
|
-
|
|
43347
|
-
|
|
43348
|
-
|
|
43349
|
-
|
|
43350
|
-
|
|
43351
|
-
|
|
43352
|
-
|
|
43353
|
-
|
|
43354
|
-
|
|
43355
|
-
|
|
43356
|
-
|
|
43357
|
-
|
|
43358
|
-
|
|
43359
|
-
)
|
|
43360
|
-
|
|
43361
|
-
|
|
43362
|
-
|
|
43363
|
-
|
|
43364
|
-
|
|
43365
|
-
|
|
43366
|
-
|
|
43367
|
-
|
|
43368
|
-
|
|
43369
|
-
|
|
43370
|
-
|
|
43371
|
-
|
|
43372
|
-
|
|
43373
|
-
|
|
43374
|
-
|
|
43375
|
-
|
|
43376
|
-
|
|
43377
|
-
|
|
43378
|
-
|
|
43379
|
-
|
|
43380
|
-
|
|
43381
|
-
`
|
|
43382
|
-
|
|
43383
|
-
|
|
43384
|
-
|
|
43385
|
-
|
|
43386
|
-
|
|
43387
|
-
|
|
43388
|
-
|
|
43389
|
-
|
|
43390
|
-
|
|
43391
|
-
toMailboxId = getMailBoxId(departmentName, memberName);
|
|
43252
|
+
var claimCeoFollowup = (id) => {
|
|
43253
|
+
const db3 = createSqliteDB();
|
|
43254
|
+
const now = Date.now();
|
|
43255
|
+
const result = db3.prepare(`
|
|
43256
|
+
UPDATE ceo_followups
|
|
43257
|
+
SET status = 'processing',
|
|
43258
|
+
attempts = attempts + 1,
|
|
43259
|
+
updated_at = ?
|
|
43260
|
+
WHERE id = ?
|
|
43261
|
+
AND status IN ('pending', 'failed')
|
|
43262
|
+
`).run(now, id);
|
|
43263
|
+
if (result.changes === 0) return null;
|
|
43264
|
+
return selectById(id);
|
|
43265
|
+
};
|
|
43266
|
+
var completeCeoFollowup = (id) => {
|
|
43267
|
+
const db3 = createSqliteDB();
|
|
43268
|
+
const now = Date.now();
|
|
43269
|
+
db3.prepare(`
|
|
43270
|
+
UPDATE ceo_followups
|
|
43271
|
+
SET status = 'completed',
|
|
43272
|
+
completed_at = COALESCE(completed_at, ?),
|
|
43273
|
+
updated_at = ?,
|
|
43274
|
+
last_error = NULL
|
|
43275
|
+
WHERE id = ?
|
|
43276
|
+
AND status IN ('pending', 'processing', 'failed')
|
|
43277
|
+
`).run(now, now, id);
|
|
43278
|
+
db3.prepare(`
|
|
43279
|
+
UPDATE mailbox
|
|
43280
|
+
SET status = 'done',
|
|
43281
|
+
updated_at = ?
|
|
43282
|
+
WHERE id = (SELECT source_message_id FROM ceo_followups WHERE id = ?)
|
|
43283
|
+
AND status IN ('pending', 'processing', 'read')
|
|
43284
|
+
`).run(now, id);
|
|
43285
|
+
};
|
|
43286
|
+
var failCeoFollowup = (id, error) => {
|
|
43287
|
+
const db3 = createSqliteDB();
|
|
43288
|
+
const now = Date.now();
|
|
43289
|
+
db3.prepare(`
|
|
43290
|
+
UPDATE ceo_followups
|
|
43291
|
+
SET status = 'failed',
|
|
43292
|
+
last_error = ?,
|
|
43293
|
+
updated_at = ?
|
|
43294
|
+
WHERE id = ?
|
|
43295
|
+
AND status IN ('pending', 'processing', 'failed')
|
|
43296
|
+
`).run(error.slice(0, 1e3), now, id);
|
|
43297
|
+
};
|
|
43298
|
+
var recoverStaleProcessingCeoFollowups = (staleBefore) => {
|
|
43299
|
+
const db3 = createSqliteDB();
|
|
43300
|
+
const now = Date.now();
|
|
43301
|
+
const result = db3.prepare(`
|
|
43302
|
+
UPDATE ceo_followups
|
|
43303
|
+
SET status = 'failed',
|
|
43304
|
+
last_error = 'stale_processing_recovered',
|
|
43305
|
+
updated_at = ?
|
|
43306
|
+
WHERE status = 'processing'
|
|
43307
|
+
AND updated_at < ?
|
|
43308
|
+
`).run(now, staleBefore);
|
|
43309
|
+
return result.changes;
|
|
43310
|
+
};
|
|
43311
|
+
var completePendingCeoFollowupsForUser = (originUserId) => {
|
|
43312
|
+
const db3 = createSqliteDB();
|
|
43313
|
+
const now = Date.now();
|
|
43314
|
+
const rows = db3.prepare(`
|
|
43315
|
+
SELECT id, source_message_id as sourceMessageId
|
|
43316
|
+
FROM ceo_followups
|
|
43317
|
+
WHERE origin_user_id = ?
|
|
43318
|
+
AND status IN ('pending', 'processing', 'failed')
|
|
43319
|
+
`).all(originUserId);
|
|
43320
|
+
const tx = db3.transaction((items) => {
|
|
43321
|
+
const completeStmt = db3.prepare(`
|
|
43322
|
+
UPDATE ceo_followups
|
|
43323
|
+
SET status = 'completed',
|
|
43324
|
+
completed_at = COALESCE(completed_at, ?),
|
|
43325
|
+
updated_at = ?,
|
|
43326
|
+
last_error = NULL
|
|
43327
|
+
WHERE id = ?
|
|
43328
|
+
AND status IN ('pending', 'processing', 'failed')
|
|
43329
|
+
`);
|
|
43330
|
+
const doneStmt = db3.prepare(`
|
|
43331
|
+
UPDATE mailbox
|
|
43332
|
+
SET status = 'done',
|
|
43333
|
+
updated_at = ?
|
|
43334
|
+
WHERE id = ?
|
|
43335
|
+
AND status IN ('pending', 'processing', 'read')
|
|
43336
|
+
`);
|
|
43337
|
+
for (const item of items) {
|
|
43338
|
+
completeStmt.run(now, now, item.id);
|
|
43339
|
+
doneStmt.run(now, item.sourceMessageId);
|
|
43392
43340
|
}
|
|
43393
|
-
|
|
43394
|
-
|
|
43395
|
-
|
|
43396
|
-
|
|
43397
|
-
|
|
43398
|
-
|
|
43399
|
-
|
|
43400
|
-
|
|
43401
|
-
|
|
43402
|
-
|
|
43403
|
-
|
|
43341
|
+
});
|
|
43342
|
+
tx(rows);
|
|
43343
|
+
return rows.length;
|
|
43344
|
+
};
|
|
43345
|
+
|
|
43346
|
+
// src/department/mailbox/mailbox.ts
|
|
43347
|
+
var getMailBoxId = (departmentName, memberName) => {
|
|
43348
|
+
return `${departmentName}::${memberName}`;
|
|
43349
|
+
};
|
|
43350
|
+
var getMailBoxIdFromDepartmentMemberId = (memberId) => {
|
|
43351
|
+
const member = getDepartmentMemberById(memberId);
|
|
43352
|
+
if (!member) return null;
|
|
43353
|
+
const department = getDepartmentById(member.departmentId);
|
|
43354
|
+
if (!department) throw new Error(`[getMailBoxIdFromDepartmentMemberId] \u6B64\u6210\u5458\u4E0D\u5C5E\u4E8E\u4EFB\u4F55\u90E8\u95E8: ${member.departmentId}`);
|
|
43355
|
+
return getMailBoxId(department.name, member.name);
|
|
43356
|
+
};
|
|
43357
|
+
var cancelMailboxMessages = (mailboxId) => {
|
|
43358
|
+
const db3 = createSqliteDB();
|
|
43359
|
+
const stmt = db3.prepare(
|
|
43360
|
+
`SELECT id, to_mailbox_id as toMailboxId, from_mailbox_id as fromMailboxId, status
|
|
43361
|
+
FROM mailbox
|
|
43362
|
+
WHERE (to_mailbox_id = ? or from_mailbox_id = ?) AND status in ('pending', 'processing')`
|
|
43363
|
+
);
|
|
43364
|
+
const messages = stmt.all(mailboxId, mailboxId);
|
|
43365
|
+
for (const message of messages) {
|
|
43366
|
+
updateMailboxMessageStatus(message.id, "cancelled", {
|
|
43367
|
+
counterpartMailboxId: message.fromMailboxId,
|
|
43368
|
+
reason: "mailbox_cancelled"
|
|
43369
|
+
});
|
|
43370
|
+
}
|
|
43371
|
+
return messages.length;
|
|
43372
|
+
};
|
|
43373
|
+
var getWorkItemContextFromMessage = (messageId) => {
|
|
43374
|
+
if (!messageId) return null;
|
|
43375
|
+
const db3 = createSqliteDB();
|
|
43376
|
+
const row = db3.prepare(
|
|
43377
|
+
`SELECT
|
|
43378
|
+
work_item_id as workItemId,
|
|
43379
|
+
work_item_role as workItemRole,
|
|
43380
|
+
upstream_message_id as upstreamMessageId
|
|
43381
|
+
FROM mailbox
|
|
43382
|
+
WHERE id = ?`
|
|
43383
|
+
).get(messageId);
|
|
43384
|
+
if (!row?.workItemId) return null;
|
|
43385
|
+
return row;
|
|
43386
|
+
};
|
|
43387
|
+
var getWorkItemContextFromThread = (threadId) => {
|
|
43388
|
+
if (!threadId) return null;
|
|
43389
|
+
const db3 = createSqliteDB();
|
|
43390
|
+
const row = db3.prepare(
|
|
43391
|
+
`SELECT
|
|
43392
|
+
work_item_id as workItemId,
|
|
43393
|
+
work_item_role as workItemRole,
|
|
43394
|
+
upstream_message_id as upstreamMessageId
|
|
43395
|
+
FROM mailbox
|
|
43396
|
+
WHERE thread_id = ?
|
|
43397
|
+
AND work_item_id IS NOT NULL
|
|
43398
|
+
ORDER BY send_time ASC
|
|
43399
|
+
LIMIT 1`
|
|
43400
|
+
).get(threadId);
|
|
43401
|
+
if (!row?.workItemId) return null;
|
|
43402
|
+
return row;
|
|
43403
|
+
};
|
|
43404
|
+
var mailboxLooksLikeRole = (mailboxId, role) => {
|
|
43405
|
+
const lower = mailboxId.toLowerCase();
|
|
43406
|
+
if (role === "department_head") {
|
|
43407
|
+
return lower.includes("department-head") || mailboxId.includes("\u8D1F\u8D23\u4EBA");
|
|
43408
|
+
}
|
|
43409
|
+
return lower.includes("executor") || mailboxId.includes("\u6267\u884C\u8005") || mailboxId.includes("\u4E13\u5458");
|
|
43410
|
+
};
|
|
43411
|
+
var inferWorkItemRole = (fromMailboxId, toMailboxId, inherited) => {
|
|
43412
|
+
if (fromMailboxId === "manager") return "upstream_request";
|
|
43413
|
+
if (toMailboxId === "manager") return "upstream_report";
|
|
43414
|
+
const fromMember = getDepartmentMemberByMailboxId(fromMailboxId);
|
|
43415
|
+
const toMember = getDepartmentMemberByMailboxId(toMailboxId);
|
|
43416
|
+
const fromIsHead = fromMember?.role === "department_head" || mailboxLooksLikeRole(fromMailboxId, "department_head");
|
|
43417
|
+
const toIsHead = toMember?.role === "department_head" || mailboxLooksLikeRole(toMailboxId, "department_head");
|
|
43418
|
+
const fromIsExecutor = fromMember?.role === "executor" || mailboxLooksLikeRole(fromMailboxId, "executor");
|
|
43419
|
+
const toIsExecutor = toMember?.role === "executor" || mailboxLooksLikeRole(toMailboxId, "executor");
|
|
43420
|
+
if (fromIsHead && toIsExecutor) {
|
|
43421
|
+
return inherited?.workItemRole === "executor_result" ? "downstream_reply" : "delegation";
|
|
43422
|
+
}
|
|
43423
|
+
if (fromIsExecutor && toIsHead) return "executor_result";
|
|
43424
|
+
return inherited?.workItemRole ? "followup" : "message";
|
|
43425
|
+
};
|
|
43426
|
+
var resolveWorkItemContext = (fromMailboxId, toMailboxId, id, options) => {
|
|
43427
|
+
if (options?.workItemId) {
|
|
43428
|
+
return {
|
|
43429
|
+
workItemId: options.workItemId,
|
|
43430
|
+
workItemRole: options.workItemRole ?? inferWorkItemRole(fromMailboxId, toMailboxId),
|
|
43431
|
+
upstreamMessageId: options.upstreamMessageId ?? options.workItemId
|
|
43432
|
+
};
|
|
43433
|
+
}
|
|
43434
|
+
const inherited = getWorkItemContextFromMessage(options?.parentMessageId) ?? getWorkItemContextFromThread(options?.threadId);
|
|
43435
|
+
if (inherited?.workItemId) {
|
|
43436
|
+
return {
|
|
43437
|
+
workItemId: inherited.workItemId,
|
|
43438
|
+
workItemRole: options?.workItemRole ?? inferWorkItemRole(fromMailboxId, toMailboxId, inherited),
|
|
43439
|
+
upstreamMessageId: inherited.upstreamMessageId ?? inherited.workItemId
|
|
43404
43440
|
};
|
|
43405
|
-
if (!departmentAgentId) {
|
|
43406
|
-
options.originUserId = userRequest.userId;
|
|
43407
|
-
options.originPlatform = userRequest.platform;
|
|
43408
|
-
} else {
|
|
43409
|
-
if (activeContext) {
|
|
43410
|
-
options.originUserId = activeContext.originUserId;
|
|
43411
|
-
options.originPlatform = activeContext.originPlatform;
|
|
43412
|
-
options.threadId = activeContext.threadId || activeContext.id;
|
|
43413
|
-
options.parentMessageId = activeContext.id;
|
|
43414
|
-
options.workItemId = activeContext.workItemId;
|
|
43415
|
-
options.upstreamMessageId = activeContext.upstreamMessageId;
|
|
43416
|
-
}
|
|
43417
|
-
}
|
|
43418
|
-
try {
|
|
43419
|
-
sendMessage2(fromMailboxId, toMailboxId, content, options);
|
|
43420
|
-
} catch (err) {
|
|
43421
|
-
return `[departmentCommunicate] \u53D1\u9001\u6D88\u606F\u5931\u8D25: ${err.message}`;
|
|
43422
|
-
}
|
|
43423
|
-
return `[departmentCommunicate] \u6D88\u606F\u5DF2\u53D1\u9001\u5230 ${toMailboxId}`;
|
|
43424
43441
|
}
|
|
43442
|
+
const targetMember = getDepartmentMemberByMailboxId(toMailboxId);
|
|
43443
|
+
if (fromMailboxId === "manager" && targetMember?.role === "department_head") {
|
|
43444
|
+
return {
|
|
43445
|
+
workItemId: id,
|
|
43446
|
+
workItemRole: "upstream_request",
|
|
43447
|
+
upstreamMessageId: id
|
|
43448
|
+
};
|
|
43449
|
+
}
|
|
43450
|
+
return {
|
|
43451
|
+
workItemRole: options?.workItemRole ?? inferWorkItemRole(fromMailboxId, toMailboxId)
|
|
43452
|
+
};
|
|
43453
|
+
};
|
|
43454
|
+
var buildMailboxInterruptContent = (msg) => {
|
|
43455
|
+
const from = msg.fromMailboxId;
|
|
43456
|
+
return [
|
|
43457
|
+
`<system_reminder>`,
|
|
43458
|
+
`\u4F60\u7684 mailbox \u6536\u5230\u4E00\u5C01\u65B0\u7684\u5185\u90E8\u534F\u4F5C\u6D88\u606F\u3002`,
|
|
43459
|
+
``,
|
|
43460
|
+
`message_id: ${msg.id}`,
|
|
43461
|
+
`from: ${from}`,
|
|
43462
|
+
`thread: ${msg.threadId || msg.id}`,
|
|
43463
|
+
``,
|
|
43464
|
+
`\u8FD9\u662F\u4E00\u6761\u4E2D\u65AD\u63D0\u9192\uFF0C\u4E0D\u4EE3\u8868\u90AE\u4EF6\u5DF2\u88AB\u9886\u53D6\u3002\u8BF7\u5C3D\u5FEB\u91CD\u65B0\u8BC4\u4F30\u5F53\u524D\u5DE5\u4F5C\u4F18\u5148\u7EA7\uFF1A`,
|
|
43465
|
+
`1. \u8C03\u7528 list_mailbox \u67E5\u770B\u5F85\u5904\u7406\u961F\u5217\u3002`,
|
|
43466
|
+
`2. \u5982\u8BE5\u6D88\u606F\u66F4\u7D27\u6025\uFF0C\u8C03\u7528 get_mailbox(message_id="${msg.id}") \u9886\u53D6\u5E76\u8BFB\u53D6\u3002`,
|
|
43467
|
+
`3. \u5982\u679C\u4F60\u6B63\u5728\u8FD0\u884C\u957F\u4EFB\u52A1\uFF0C\u5E94\u5148\u8BB0\u5F55\u5F53\u524D\u8FDB\u5C55\uFF0C\u5FC5\u8981\u65F6\u7528 mailbox_followup \u540C\u6B65\u72B6\u6001\uFF0C\u518D\u5904\u7406\u8FD9\u5C01\u65B0\u6D88\u606F\u3002`,
|
|
43468
|
+
`4. \u5F62\u6210\u6B63\u5F0F\u7B54\u590D\u540E\u5FC5\u987B\u7528 reply_mailbox \u56DE\u590D\u5BF9\u5E94 message_id\u3002`,
|
|
43469
|
+
`</system_reminder>`
|
|
43470
|
+
].join("\n");
|
|
43425
43471
|
};
|
|
43426
|
-
|
|
43427
|
-
|
|
43428
|
-
|
|
43429
|
-
|
|
43430
|
-
|
|
43431
|
-
|
|
43432
|
-
|
|
43433
|
-
|
|
43434
|
-
|
|
43435
|
-
|
|
43436
|
-
|
|
43437
|
-
name: `department_delete`,
|
|
43438
|
-
description: DESCRIPTION22,
|
|
43439
|
-
input_schema: {
|
|
43440
|
-
type: `object`,
|
|
43441
|
-
properties: {
|
|
43442
|
-
name: {
|
|
43443
|
-
type: `string`,
|
|
43444
|
-
description: `\u8981\u5220\u9664\u7684\u90E8\u95E8\u540D\u79F0`
|
|
43445
|
-
},
|
|
43446
|
-
confirmed: {
|
|
43447
|
-
type: `boolean`,
|
|
43448
|
-
description: `\u7528\u6237\u662F\u5426\u5DF2\u660E\u786E\u786E\u8BA4\u89E3\u6563\u8BE5\u90E8\u95E8`
|
|
43449
|
-
}
|
|
43450
|
-
},
|
|
43451
|
-
required: [`name`]
|
|
43452
|
-
},
|
|
43453
|
-
async execute(input) {
|
|
43454
|
-
const name = input.name;
|
|
43455
|
-
const confirmed = input.confirmed ?? false;
|
|
43456
|
-
if (!confirmed) {
|
|
43457
|
-
return `[departmentDelete] \u89E3\u6563\u90E8\u95E8\u662F\u4E0D\u53EF\u9006\u64CD\u4F5C\uFF0C\u8BF7\u5148\u7528 send_message \u5411\u7528\u6237\u786E\u8BA4"\u662F\u5426\u89E3\u6563\u90E8\u95E8 ${name}"\uFF0C\u5F97\u5230\u7528\u6237\u660E\u786E\u540C\u610F\u540E\uFF0C\u518D\u4EE5 confirmed=true \u91CD\u65B0\u8C03\u7528\u672C\u5DE5\u5177\u3002`;
|
|
43458
|
-
}
|
|
43459
|
-
try {
|
|
43460
|
-
const members = listDepartmentMembers(name);
|
|
43461
|
-
let totalCancelled = 0;
|
|
43462
|
-
for (const member of members) {
|
|
43463
|
-
const mailboxId = getMailBoxId(name, member.name);
|
|
43464
|
-
totalCancelled += cancelMailboxMessages(mailboxId);
|
|
43465
|
-
}
|
|
43466
|
-
if (totalCancelled > 0) {
|
|
43467
|
-
console.log(`[departmentDelete] \u5DF2\u53D6\u6D88\u90E8\u95E8 ${name} \u7684 ${totalCancelled} \u6761\u6B8B\u7559 mailbox \u6D88\u606F`);
|
|
43468
|
-
}
|
|
43469
|
-
deleteDepartment(name);
|
|
43470
|
-
} catch (err) {
|
|
43471
|
-
return `[departmentDelete] \u5220\u9664\u90E8\u95E8\u5931\u8D25: ${err.message}`;
|
|
43472
|
+
var queueMailboxInterruptIfRunning = (msg) => {
|
|
43473
|
+
if (msg.toMailboxId === "manager") return;
|
|
43474
|
+
if (!hasRunningAgent(msg.toMailboxId)) return;
|
|
43475
|
+
const queued = queueInterrupt(msg.toMailboxId, {
|
|
43476
|
+
content: buildMailboxInterruptContent(msg),
|
|
43477
|
+
metadata: {
|
|
43478
|
+
trigger: "mailbox.message_received",
|
|
43479
|
+
mailboxMessageId: msg.id,
|
|
43480
|
+
fromMailboxId: msg.fromMailboxId,
|
|
43481
|
+
toMailboxId: msg.toMailboxId,
|
|
43482
|
+
threadId: msg.threadId || msg.id
|
|
43472
43483
|
}
|
|
43473
|
-
|
|
43484
|
+
});
|
|
43485
|
+
if (queued) {
|
|
43486
|
+
console.log(`[mailbox] \u76EE\u6807 agent ${msg.toMailboxId} \u6B63\u5728\u8FD0\u884C\uFF0C\u5DF2\u5C06\u65B0\u90AE\u4EF6 ${msg.id} \u4F5C\u4E3A\u4E2D\u65AD\u63D0\u9192\u5165\u961F`);
|
|
43474
43487
|
}
|
|
43475
43488
|
};
|
|
43476
|
-
|
|
43477
|
-
|
|
43478
|
-
|
|
43479
|
-
|
|
43480
|
-
|
|
43481
|
-
|
|
43482
|
-
|
|
43483
|
-
|
|
43484
|
-
|
|
43485
|
-
|
|
43486
|
-
|
|
43487
|
-
|
|
43488
|
-
|
|
43489
|
-
|
|
43490
|
-
|
|
43491
|
-
required: []
|
|
43492
|
-
},
|
|
43493
|
-
async execute() {
|
|
43494
|
-
const departments = listDepartments();
|
|
43495
|
-
if (departments.length === 0) {
|
|
43496
|
-
return `[departmentList] \u5F53\u524D\u6CA1\u6709\u4EFB\u4F55\u90E8\u95E8\u3002`;
|
|
43489
|
+
var recordMailboxReceivedAgentEvent = (msg) => {
|
|
43490
|
+
if (msg.toMailboxId === "manager") return;
|
|
43491
|
+
recordAgentEvent({
|
|
43492
|
+
userId: msg.toMailboxId,
|
|
43493
|
+
type: "mailbox.message_received",
|
|
43494
|
+
source: "mailbox",
|
|
43495
|
+
sourceId: msg.id,
|
|
43496
|
+
payload: {
|
|
43497
|
+
ownerMailboxId: msg.toMailboxId,
|
|
43498
|
+
mailboxMessageId: msg.id,
|
|
43499
|
+
fromMailboxId: msg.fromMailboxId,
|
|
43500
|
+
toMailboxId: msg.toMailboxId,
|
|
43501
|
+
threadId: msg.threadId || msg.id,
|
|
43502
|
+
contentPreview: msg.content.slice(0, 160),
|
|
43503
|
+
summary: `\u6536\u5230\u6765\u81EA ${msg.fromMailboxId} \u7684\u65B0\u5185\u90E8\u534F\u4F5C\u6D88\u606F\uFF0C\u8BF7\u7528 list_mailbox/get_mailbox \u8BC4\u4F30\u5E76\u9886\u53D6\u3002`
|
|
43497
43504
|
}
|
|
43498
|
-
|
|
43499
|
-
|
|
43500
|
-
|
|
43501
|
-
|
|
43502
|
-
|
|
43503
|
-
|
|
43504
|
-
|
|
43505
|
-
|
|
43506
|
-
|
|
43507
|
-
|
|
43508
|
-
|
|
43509
|
-
|
|
43510
|
-
|
|
43511
|
-
|
|
43512
|
-
|
|
43513
|
-
|
|
43514
|
-
|
|
43515
|
-
|
|
43516
|
-
|
|
43505
|
+
});
|
|
43506
|
+
};
|
|
43507
|
+
var sendMessage2 = (fromMailboxId, toMailboxId, content, options) => {
|
|
43508
|
+
const db3 = createSqliteDB();
|
|
43509
|
+
const id = (0, import_node_crypto8.randomUUID)().slice(0, 8);
|
|
43510
|
+
const threadId = options?.threadId || id;
|
|
43511
|
+
const workItemContext = resolveWorkItemContext(fromMailboxId, toMailboxId, id, options);
|
|
43512
|
+
const stmt = db3.prepare(`insert into mailbox (
|
|
43513
|
+
id,
|
|
43514
|
+
to_mailbox_id,
|
|
43515
|
+
from_mailbox_id,
|
|
43516
|
+
content,
|
|
43517
|
+
send_time,
|
|
43518
|
+
status,
|
|
43519
|
+
origin_user_id,
|
|
43520
|
+
origin_platform,
|
|
43521
|
+
thread_id,
|
|
43522
|
+
parent_message_id,
|
|
43523
|
+
work_item_id,
|
|
43524
|
+
work_item_role,
|
|
43525
|
+
upstream_message_id
|
|
43526
|
+
) values (?,?,?,?,?,?,?,?,?,?,?,?,?) `);
|
|
43527
|
+
let mailboxMsg = {
|
|
43528
|
+
id,
|
|
43529
|
+
toMailboxId,
|
|
43530
|
+
fromMailboxId,
|
|
43531
|
+
content,
|
|
43532
|
+
sendTime: (/* @__PURE__ */ new Date()).getTime(),
|
|
43533
|
+
status: "pending",
|
|
43534
|
+
originUserId: options?.originUserId,
|
|
43535
|
+
originPlatform: options?.originPlatform,
|
|
43536
|
+
threadId,
|
|
43537
|
+
parentMessageId: options?.parentMessageId,
|
|
43538
|
+
workItemId: workItemContext.workItemId,
|
|
43539
|
+
workItemRole: workItemContext.workItemRole,
|
|
43540
|
+
upstreamMessageId: workItemContext.upstreamMessageId
|
|
43541
|
+
};
|
|
43542
|
+
const result = stmt.run(
|
|
43543
|
+
mailboxMsg.id,
|
|
43544
|
+
mailboxMsg.toMailboxId,
|
|
43545
|
+
mailboxMsg.fromMailboxId,
|
|
43546
|
+
mailboxMsg.content,
|
|
43547
|
+
mailboxMsg.sendTime,
|
|
43548
|
+
mailboxMsg.status,
|
|
43549
|
+
mailboxMsg.originUserId || null,
|
|
43550
|
+
mailboxMsg.originPlatform || null,
|
|
43551
|
+
mailboxMsg.threadId || mailboxMsg.id,
|
|
43552
|
+
mailboxMsg.parentMessageId || null,
|
|
43553
|
+
mailboxMsg.workItemId || null,
|
|
43554
|
+
mailboxMsg.workItemRole || null,
|
|
43555
|
+
mailboxMsg.upstreamMessageId || null
|
|
43556
|
+
);
|
|
43557
|
+
recordMailboxEvent({
|
|
43558
|
+
messageId: mailboxMsg.id,
|
|
43559
|
+
mailboxId: toMailboxId,
|
|
43560
|
+
actorMailboxId: fromMailboxId,
|
|
43561
|
+
counterpartMailboxId: fromMailboxId,
|
|
43562
|
+
eventType: "message_sent",
|
|
43563
|
+
detail: {
|
|
43564
|
+
initialStatus: mailboxMsg.status,
|
|
43565
|
+
workItemId: mailboxMsg.workItemId ?? null,
|
|
43566
|
+
workItemRole: mailboxMsg.workItemRole ?? null,
|
|
43567
|
+
upstreamMessageId: mailboxMsg.upstreamMessageId ?? null,
|
|
43568
|
+
...options?.auditDetail ?? {}
|
|
43569
|
+
},
|
|
43570
|
+
createdAt: mailboxMsg.sendTime
|
|
43571
|
+
});
|
|
43572
|
+
recordMailboxReceivedAgentEvent(mailboxMsg);
|
|
43573
|
+
queueMailboxInterruptIfRunning(mailboxMsg);
|
|
43574
|
+
enqueueCeoFollowupFromMailbox(mailboxMsg);
|
|
43575
|
+
return mailboxMsg;
|
|
43576
|
+
};
|
|
43577
|
+
var updateMailboxMessageStatus = (messageId, nextStatus, options) => {
|
|
43578
|
+
const db3 = createSqliteDB();
|
|
43579
|
+
const selectStmt2 = db3.prepare(
|
|
43580
|
+
`SELECT id, to_mailbox_id as toMailboxId, from_mailbox_id as fromMailboxId, status
|
|
43581
|
+
FROM mailbox WHERE id = ?`
|
|
43582
|
+
);
|
|
43583
|
+
const existing = selectStmt2.get(messageId);
|
|
43584
|
+
if (!existing) return false;
|
|
43585
|
+
if (existing.status === nextStatus) return false;
|
|
43586
|
+
const allowedFrom = options?.fromStatus ? Array.isArray(options.fromStatus) ? options.fromStatus : [options.fromStatus] : null;
|
|
43587
|
+
if (allowedFrom && !allowedFrom.includes(existing.status)) {
|
|
43588
|
+
return false;
|
|
43517
43589
|
}
|
|
43590
|
+
const updateStmt = db3.prepare(
|
|
43591
|
+
`UPDATE mailbox
|
|
43592
|
+
SET status = ?, updated_at = ?
|
|
43593
|
+
WHERE id = ? AND status = ?`
|
|
43594
|
+
);
|
|
43595
|
+
const result = updateStmt.run(nextStatus, Date.now(), messageId, existing.status);
|
|
43596
|
+
if (result.changes === 0) return false;
|
|
43597
|
+
recordMailboxStatusChange({
|
|
43598
|
+
messageId,
|
|
43599
|
+
mailboxId: existing.toMailboxId,
|
|
43600
|
+
previousStatus: existing.status,
|
|
43601
|
+
nextStatus,
|
|
43602
|
+
actorMailboxId: options?.actorMailboxId,
|
|
43603
|
+
counterpartMailboxId: options?.counterpartMailboxId || existing.fromMailboxId,
|
|
43604
|
+
reason: options?.reason
|
|
43605
|
+
});
|
|
43606
|
+
return true;
|
|
43518
43607
|
};
|
|
43519
43608
|
|
|
43520
|
-
// src/tools/tools/department/
|
|
43521
|
-
var
|
|
43522
|
-
|
|
43523
|
-
\u521B\u5EFA\u90E8\u95E8\u6210\u5458\u3002
|
|
43609
|
+
// src/tools/tools/department/DepartmentCreate.ts
|
|
43610
|
+
var DESCRIPTION20 = `
|
|
43611
|
+
\u521B\u5EFA\u90E8\u95E8\u3002Department \u662F\u516C\u53F8\u7EC4\u7EC7\u4E2D\u7684\u957F\u671F\u804C\u8D23\u5355\u5143\uFF0C\u4E0D\u662F\u4E00\u6B21\u6027\u9879\u76EE\u5C0F\u961F\u3002
|
|
43524
43612
|
|
|
43525
|
-
\
|
|
43526
|
-
-
|
|
43527
|
-
-
|
|
43528
|
-
-
|
|
43613
|
+
\u5DE5\u5177\u8C03\u7528\u89C4\u5219\uFF1A
|
|
43614
|
+
- \u5F53\u4E00\u4E2A\u590D\u6742\u3001\u957F\u671F\u3001\u4E13\u4E1A\u804C\u8D23\u9700\u8981\u7A33\u5B9A\u7EC4\u7EC7\u627F\u63A5\u65F6\u8C03\u7528\u6B64\u5DE5\u5177\u3002
|
|
43615
|
+
- sourceGoalId \u662F\u53EF\u9009\u6765\u6E90\u76EE\u6807\uFF1B\u90E8\u95E8\u804C\u8D23\u5E94\u5199\u5165 charter\uFF0C\u4E0D\u8981\u628A\u4E00\u6B21\u6027\u4EFB\u52A1\u7EC6\u8282\u5199\u8FDB charter\u3002
|
|
43616
|
+
- \u521B\u5EFA\u90E8\u95E8\u540E\uFF0CCEO \u5E94\u4F7F\u7528 department_member_create \u4EFB\u547D Department Head\uFF0C\u518D\u7528 department_communicate \u53D1\u9001\u672C\u6B21\u5177\u4F53\u4EFB\u52A1\u3002
|
|
43529
43617
|
`;
|
|
43530
|
-
var
|
|
43531
|
-
name: `
|
|
43532
|
-
description:
|
|
43618
|
+
var departmentCreate = {
|
|
43619
|
+
name: `department_create`,
|
|
43620
|
+
description: DESCRIPTION20,
|
|
43533
43621
|
input_schema: {
|
|
43534
43622
|
type: `object`,
|
|
43535
43623
|
properties: {
|
|
43536
43624
|
name: {
|
|
43537
43625
|
type: `string`,
|
|
43538
|
-
description: `\u90E8\u95E8\
|
|
43626
|
+
description: `\u90E8\u95E8\u540D\u79F0`
|
|
43539
43627
|
},
|
|
43540
|
-
|
|
43628
|
+
charter: {
|
|
43541
43629
|
type: `string`,
|
|
43542
|
-
description: `\
|
|
43630
|
+
description: `\u90E8\u95E8\u957F\u671F\u804C\u8D23\u8FB9\u754C\uFF0C\u4E0D\u80FD\u5199\u4E00\u6B21\u6027\u4EFB\u52A1\u7EC6\u8282`
|
|
43543
43631
|
},
|
|
43544
|
-
|
|
43632
|
+
sourceGoalId: {
|
|
43545
43633
|
type: `string`,
|
|
43546
|
-
description: `\
|
|
43634
|
+
description: `\u53EF\u9009\uFF1A\u521B\u5EFA\u8BE5\u90E8\u95E8\u65F6\u5173\u8054\u7684\u76EE\u6807 id`
|
|
43547
43635
|
},
|
|
43548
|
-
|
|
43636
|
+
workpath: {
|
|
43549
43637
|
type: `string`,
|
|
43550
|
-
|
|
43551
|
-
description: `\u6210\u5458\u89D2\u8272\u3002CEO \u521B\u5EFA\u90E8\u95E8\u8D1F\u8D23\u4EBA\u65F6\u4F20 department_head\uFF1BDepartment Head \u521B\u5EFA\u6267\u884C\u8005\u65F6\u4F20 executor`
|
|
43638
|
+
description: `\u90E8\u95E8\u9879\u76EE\u5DE5\u4F5C\u76EE\u5F55\uFF08\u7EDD\u5BF9\u8DEF\u5F84\uFF09\uFF0C\u90E8\u95E8\u6210\u5458\u7684\u6587\u4EF6\u4FEE\u6539\u5E94\u9650\u5236\u5728\u6B64\u76EE\u5F55\u8303\u56F4\u5185`
|
|
43552
43639
|
}
|
|
43553
43640
|
},
|
|
43554
|
-
required: [`name`, `
|
|
43641
|
+
required: [`name`, `charter`, `workpath`]
|
|
43555
43642
|
},
|
|
43556
|
-
async execute(input
|
|
43643
|
+
async execute(input) {
|
|
43557
43644
|
const name = input.name;
|
|
43558
|
-
const
|
|
43559
|
-
const
|
|
43560
|
-
const
|
|
43561
|
-
if (!
|
|
43562
|
-
|
|
43563
|
-
const currentMailboxId = userRequest?.departmentAgentId;
|
|
43564
|
-
let role;
|
|
43565
|
-
if (currentMailboxId) {
|
|
43566
|
-
const currentMember = getDepartmentMemberByMailboxId(currentMailboxId);
|
|
43567
|
-
if (!currentMember) {
|
|
43568
|
-
return `[departmentMemberCreate] \u65E0\u6CD5\u8BC6\u522B\u5F53\u524D\u90E8\u95E8\u6210\u5458: ${currentMailboxId}`;
|
|
43569
|
-
}
|
|
43570
|
-
if (currentMember.role !== "department_head") {
|
|
43571
|
-
return `[departmentMemberCreate] \u53EA\u6709 Department Head \u53EF\u4EE5\u521B\u5EFA Executor`;
|
|
43572
|
-
}
|
|
43573
|
-
if (currentMember.departmentId !== department.id) {
|
|
43574
|
-
return `[departmentMemberCreate] Department Head \u53EA\u80FD\u5728\u81EA\u5DF1\u6240\u5C5E\u90E8\u95E8\u5185\u521B\u5EFA\u6210\u5458`;
|
|
43575
|
-
}
|
|
43576
|
-
role = requestedRole ?? "executor";
|
|
43577
|
-
if (role === "department_head") {
|
|
43578
|
-
return `[departmentMemberCreate] \u90E8\u95E8\u5DF2\u7531\u5F53\u524D Department Head \u7BA1\u7406\uFF0C\u4E0D\u80FD\u7531 Department Head \u518D\u521B\u5EFA Department Head`;
|
|
43579
|
-
}
|
|
43580
|
-
} else {
|
|
43581
|
-
role = requestedRole ?? "department_head";
|
|
43582
|
-
if (role !== "department_head") {
|
|
43583
|
-
return `[departmentMemberCreate] CEO \u53EA\u80FD\u521B\u5EFA Department Head\uFF1BExecutor \u5E94\u7531 Department Head \u521B\u5EFA`;
|
|
43584
|
-
}
|
|
43645
|
+
const charter = input.charter;
|
|
43646
|
+
const sourceGoalId = input.sourceGoalId;
|
|
43647
|
+
const workpath = input.workpath;
|
|
43648
|
+
if (sourceGoalId && !getGoalById(sourceGoalId)) {
|
|
43649
|
+
return `[departmentCreate] \u4E0D\u5B58\u5728 id=${sourceGoalId} \u7684\u76EE\u6807`;
|
|
43585
43650
|
}
|
|
43586
|
-
let
|
|
43651
|
+
let departmentDefinition = {
|
|
43587
43652
|
id: (0, import_node_crypto9.randomUUID)().slice(0, 8),
|
|
43588
43653
|
name,
|
|
43589
|
-
|
|
43590
|
-
|
|
43591
|
-
|
|
43592
|
-
|
|
43593
|
-
focusOn
|
|
43654
|
+
charter,
|
|
43655
|
+
sourceGoalId,
|
|
43656
|
+
workpath,
|
|
43657
|
+
departmentMembers: []
|
|
43594
43658
|
};
|
|
43595
43659
|
try {
|
|
43596
|
-
|
|
43660
|
+
departmentDefinition = createDepartment(departmentDefinition);
|
|
43597
43661
|
} catch (err) {
|
|
43598
|
-
return `[
|
|
43662
|
+
return `[departmentCreate] \u521B\u5EFA\u90E8\u95E8\u5931\u8D25: ${err.message}`;
|
|
43599
43663
|
}
|
|
43600
|
-
return `[
|
|
43664
|
+
return `[departmentCreate] \u521B\u5EFA\u90E8\u95E8\u6210\u529F: ${JSON.stringify(departmentDefinition)}`;
|
|
43601
43665
|
}
|
|
43602
43666
|
};
|
|
43603
43667
|
|
|
43604
|
-
// src/tools/tools/department/
|
|
43605
|
-
var
|
|
43606
|
-
\
|
|
43668
|
+
// src/tools/tools/department/DepartmentCommunicate.ts
|
|
43669
|
+
var CEO_MAILBOX_ID = `manager`;
|
|
43670
|
+
var MANAGER_ALIAS_PATTERN = /(^|::)(manager|main[-_\s]?manager|ceo)$/i;
|
|
43671
|
+
var looksLikePseudoManagerMailbox = (mailboxId) => {
|
|
43672
|
+
if (mailboxId === CEO_MAILBOX_ID) return true;
|
|
43673
|
+
if (!mailboxId.includes(`::`)) return false;
|
|
43674
|
+
return MANAGER_ALIAS_PATTERN.test(mailboxId.trim());
|
|
43675
|
+
};
|
|
43676
|
+
var buildManagerRoutingRejection = (activeContext) => [
|
|
43677
|
+
`[departmentCommunicate] \u62D2\u7EDD\u53D1\u9001\u5230\u4F2A manager mailbox\u3002`,
|
|
43678
|
+
`Main Manager/CEO \u4E0D\u662F\u90E8\u95E8\u6210\u5458\uFF0C\u4E0D\u80FD\u7528 department_communicate \u53D1\u9001\u5230 manager\u3001Department::Manager\u3001CEO::Manager \u7B49\u5730\u5740\u3002`,
|
|
43679
|
+
activeContext ? `\u5982\u679C\u8981\u5411\u4E0A\u6E38 CEO \u6C47\u62A5\uFF0C\u8BF7\u8C03\u7528 reply_mailbox(message_id="${activeContext.id}", content="...") \u6B63\u5F0F\u56DE\u590D\u539F\u90AE\u4EF6\uFF1B\u82E5\u53EA\u662F\u540C\u6B65\u9636\u6BB5\u8FDB\u5C55\uFF0C\u8BF7\u8C03\u7528 mailbox_followup(message_id="${activeContext.id}", content="...", kind="progress")\u3002` : `\u5982\u679C\u8981\u5411\u4E0A\u6E38 CEO \u6C47\u62A5\uFF0C\u8BF7\u56DE\u5230\u539F manager \u90AE\u4EF6\uFF0C\u4F7F\u7528 reply_mailbox(message_id="\u539F\u90AE\u4EF6ID", content="...") \u6216 mailbox_followup(message_id="\u539F\u90AE\u4EF6ID", content="...", kind="progress")\u3002`
|
|
43680
|
+
].join(`
|
|
43681
|
+
`);
|
|
43682
|
+
var getActiveMailboxContext = (actorMailboxId, messageId) => {
|
|
43683
|
+
if (!messageId) return null;
|
|
43684
|
+
const db3 = createSqliteDB();
|
|
43685
|
+
const row = db3.prepare(
|
|
43686
|
+
`SELECT
|
|
43687
|
+
id,
|
|
43688
|
+
from_mailbox_id as fromMailboxId,
|
|
43689
|
+
to_mailbox_id as toMailboxId,
|
|
43690
|
+
origin_user_id as originUserId,
|
|
43691
|
+
origin_platform as originPlatform,
|
|
43692
|
+
thread_id as threadId,
|
|
43693
|
+
work_item_id as workItemId,
|
|
43694
|
+
upstream_message_id as upstreamMessageId
|
|
43695
|
+
FROM mailbox
|
|
43696
|
+
WHERE id = ?
|
|
43697
|
+
AND (from_mailbox_id = ? OR to_mailbox_id = ?)`
|
|
43698
|
+
).get(messageId, actorMailboxId, actorMailboxId);
|
|
43699
|
+
return row ?? null;
|
|
43700
|
+
};
|
|
43701
|
+
var DESCRIPTION21 = `
|
|
43702
|
+
\u5411\u90E8\u95E8\u6210\u5458\u53D1\u9001\u6D88\u606F\u6216\u6307\u4EE4\uFF0C\u662F\u516C\u53F8\u5185\u90E8\u5F02\u6B65\u534F\u4F5C\u901A\u4FE1\u6E20\u9053\u3002
|
|
43607
43703
|
|
|
43608
|
-
\
|
|
43609
|
-
- \
|
|
43610
|
-
- Department Head \
|
|
43611
|
-
-
|
|
43704
|
+
\u9ED8\u8BA4\u7EC4\u7EC7\u6CBB\u7406\uFF1A
|
|
43705
|
+
- CEO \u9ED8\u8BA4\u901A\u8FC7 department_list \u53EA\u770B\u5230\u90E8\u95E8\u548C Department Head\uFF0C\u4E0D\u4E3B\u52A8\u66B4\u9732 Executor\u3002
|
|
43706
|
+
- Department Head \u9ED8\u8BA4\u7BA1\u7406\u672C\u90E8\u95E8\u6210\u5458\u3002
|
|
43707
|
+
- \u5982\u679C\u667A\u80FD\u4F53\u5DF2\u7ECF\u901A\u8FC7\u6B63\u5E38\u6C9F\u901A\u77E5\u9053\u4E86\u5176\u4ED6\u6210\u5458\u7684 mailbox \u5730\u5740\uFF0C\u5DE5\u5177\u4E0D\u4F1A\u786C\u6027\u963B\u6B62\u901A\u4FE1\uFF1B\u8FD9\u7C7B\u975E\u9ED8\u8BA4\u8DEF\u5F84\u4F1A\u5199\u5165\u5BA1\u8BA1\u4FE1\u606F\u3002
|
|
43708
|
+
- Main Manager/CEO \u7684 mailbox id \u56FA\u5B9A\u662F manager\u3002Department agent \u4E0D\u5E94\u4F7F\u7528 department_communicate \u7ED9 manager \u6216 Department::Manager \u53D1\u4FE1\uFF1B\u8981\u56DE\u590D\u4E0A\u6E38\u5FC5\u987B\u4F7F\u7528\u539F\u90AE\u4EF6\u7684 reply_mailbox \u6216 mailbox_followup\u3002
|
|
43709
|
+
|
|
43710
|
+
\u53C2\u6570\u8BF4\u660E\uFF1A
|
|
43711
|
+
- department_name + member_name: \u9ED8\u8BA4\u5BFB\u5740\u65B9\u5F0F\u3002
|
|
43712
|
+
- target_mailbox_id: \u53EF\u9009\uFF0C\u5DF2\u77E5\u5BF9\u65B9 mailbox \u5730\u5740\u65F6\u4F7F\u7528\uFF1B\u4F7F\u7528\u65F6\u5EFA\u8BAE\u586B\u5199 reason\u3002
|
|
43713
|
+
- content: \u8981\u53D1\u9001\u7684\u6D88\u606F\u5185\u5BB9\u3002
|
|
43612
43714
|
`;
|
|
43613
|
-
var
|
|
43614
|
-
name: `
|
|
43615
|
-
description:
|
|
43715
|
+
var departmentCommunicate = {
|
|
43716
|
+
name: `department_communicate`,
|
|
43717
|
+
description: DESCRIPTION21,
|
|
43616
43718
|
input_schema: {
|
|
43617
43719
|
type: `object`,
|
|
43618
43720
|
properties: {
|
|
43619
43721
|
department_name: {
|
|
43620
43722
|
type: `string`,
|
|
43621
|
-
description: `\
|
|
43723
|
+
description: `\u76EE\u6807\u6210\u5458\u6240\u5C5E\u90E8\u95E8\u540D\u79F0\uFF1B\u4F7F\u7528 target_mailbox_id \u65F6\u53EF\u7701\u7565`
|
|
43622
43724
|
},
|
|
43623
|
-
|
|
43725
|
+
member_name: {
|
|
43624
43726
|
type: `string`,
|
|
43625
|
-
description: `\
|
|
43727
|
+
description: `\u76EE\u6807\u6210\u5458\u540D\u79F0\uFF1B\u4F7F\u7528 target_mailbox_id \u65F6\u53EF\u7701\u7565`
|
|
43728
|
+
},
|
|
43729
|
+
target_mailbox_id: {
|
|
43730
|
+
type: `string`,
|
|
43731
|
+
description: `\u53EF\u9009\uFF1A\u5DF2\u77E5\u5BF9\u65B9 mailbox \u5730\u5740\u65F6\u76F4\u63A5\u586B\u5199\uFF0C\u4F8B\u5982 Department::Member`
|
|
43732
|
+
},
|
|
43733
|
+
content: {
|
|
43734
|
+
type: `string`,
|
|
43735
|
+
description: `\u8981\u6295\u9001\u7ED9\u5BF9\u65B9\u7684\u4FE1\u606F\u5185\u5BB9`
|
|
43736
|
+
},
|
|
43737
|
+
reason: {
|
|
43738
|
+
type: `string`,
|
|
43739
|
+
description: `\u53EF\u9009\uFF1A\u8DE8\u9ED8\u8BA4\u7EC4\u7EC7\u94FE\u8DEF\u6C9F\u901A\u7684\u539F\u56E0\uFF0C\u4FBF\u4E8E\u5BA1\u8BA1`
|
|
43626
43740
|
}
|
|
43627
43741
|
},
|
|
43628
|
-
required: [`
|
|
43742
|
+
required: [`content`]
|
|
43629
43743
|
},
|
|
43630
43744
|
async execute(input, userRequest) {
|
|
43631
|
-
|
|
43632
|
-
|
|
43633
|
-
const department = getDepartment(departmentName);
|
|
43634
|
-
if (!department) return `[departmentMemberDelete] \u4E0D\u5B58\u5728\u540D\u79F0\u4E3A ${departmentName} \u7684\u90E8\u95E8`;
|
|
43635
|
-
const member = getDepartmentMember(departmentName, memberId);
|
|
43636
|
-
if (!member) return `[departmentMemberDelete] \u627E\u4E0D\u5230\u6210\u5458: ${memberId}`;
|
|
43637
|
-
const currentMailboxId = userRequest?.departmentAgentId;
|
|
43638
|
-
if (currentMailboxId) {
|
|
43639
|
-
const currentMember = getDepartmentMemberByMailboxId(currentMailboxId);
|
|
43640
|
-
if (!currentMember) return `[departmentMemberDelete] \u65E0\u6CD5\u8BC6\u522B\u5F53\u524D\u90E8\u95E8\u6210\u5458: ${currentMailboxId}`;
|
|
43641
|
-
if (currentMember.role !== "department_head") return `[departmentMemberDelete] \u53EA\u6709 Department Head \u53EF\u4EE5\u5220\u9664 Executor`;
|
|
43642
|
-
if (currentMember.departmentId !== department.id) return `[departmentMemberDelete] Department Head \u53EA\u80FD\u7BA1\u7406\u81EA\u5DF1\u6240\u5C5E\u90E8\u95E8`;
|
|
43643
|
-
if (member.role === "department_head") return `[departmentMemberDelete] Department Head \u4E0D\u80FD\u5220\u9664 Department Head`;
|
|
43745
|
+
if (!userRequest) {
|
|
43746
|
+
throw new Error(`[departmentCommunicate] userRequest\u4E0D\u80FD\u4E3A\u7A7A`);
|
|
43644
43747
|
}
|
|
43645
|
-
|
|
43646
|
-
|
|
43647
|
-
|
|
43648
|
-
|
|
43649
|
-
|
|
43650
|
-
|
|
43748
|
+
const departmentName = input.department_name;
|
|
43749
|
+
const memberName = input.member_name;
|
|
43750
|
+
const targetMailboxId = input.target_mailbox_id;
|
|
43751
|
+
const content = input.content;
|
|
43752
|
+
const reason = input.reason;
|
|
43753
|
+
let fromMailboxId;
|
|
43754
|
+
const departmentAgentId = userRequest.departmentAgentId;
|
|
43755
|
+
const actorMember = departmentAgentId ? getDepartmentMemberByMailboxId(
|
|
43756
|
+
departmentAgentId.includes(`::`) ? departmentAgentId : getMailBoxIdFromDepartmentMemberId(departmentAgentId) ?? departmentAgentId
|
|
43757
|
+
) : null;
|
|
43758
|
+
if (departmentAgentId) {
|
|
43759
|
+
const resolved = departmentAgentId.includes(`::`) ? departmentAgentId : getMailBoxIdFromDepartmentMemberId(departmentAgentId);
|
|
43760
|
+
if (!resolved) {
|
|
43761
|
+
return `[departmentCommunicate] \u65E0\u6CD5\u83B7\u53D6\u5F53\u524D agent \u7684 mailboxId\uFF0CdepartmentAgentId: ${departmentAgentId}`;
|
|
43651
43762
|
}
|
|
43652
|
-
|
|
43653
|
-
|
|
43763
|
+
fromMailboxId = resolved;
|
|
43764
|
+
} else {
|
|
43765
|
+
fromMailboxId = CEO_MAILBOX_ID;
|
|
43654
43766
|
}
|
|
43655
|
-
|
|
43656
|
-
|
|
43657
|
-
|
|
43658
|
-
|
|
43659
|
-
|
|
43660
|
-
var DESCRIPTION26 = `
|
|
43661
|
-
\u67E5\u770B\u5F53\u524D Department Head \u6240\u5C5E\u90E8\u95E8\u7684\u6210\u5458\u76EE\u5F55\u3002
|
|
43662
|
-
|
|
43663
|
-
\u4F7F\u7528\u8FB9\u754C\uFF1A
|
|
43664
|
-
- \u4EC5 Department Head \u53EF\u4EE5\u4F7F\u7528\u3002
|
|
43665
|
-
- CEO \u9ED8\u8BA4\u901A\u8FC7 department_list \u53EA\u770B\u5230\u90E8\u95E8\u4E0E\u8D1F\u8D23\u4EBA\u6458\u8981\u3002
|
|
43666
|
-
- Department Head \u53EA\u80FD\u67E5\u770B\u81EA\u5DF1\u6240\u5C5E\u90E8\u95E8\u7684\u6210\u5458\uFF0C\u7528\u4E8E\u590D\u7528\u5DF2\u6709\u6210\u5458\u3001\u5224\u65AD\u662F\u5426\u9700\u8981\u521B\u5EFA\u65B0\u6210\u5458\u3001\u4E86\u89E3\u6210\u5458\u804C\u8D23\u3002
|
|
43667
|
-
`;
|
|
43668
|
-
var departmentMemberList = {
|
|
43669
|
-
name: `department_member_list`,
|
|
43670
|
-
description: DESCRIPTION26,
|
|
43671
|
-
input_schema: {
|
|
43672
|
-
type: `object`,
|
|
43673
|
-
properties: {},
|
|
43674
|
-
required: []
|
|
43675
|
-
},
|
|
43676
|
-
async execute(input, userRequest) {
|
|
43677
|
-
const mailboxId = userRequest?.departmentAgentId;
|
|
43678
|
-
if (!mailboxId) {
|
|
43679
|
-
return `[departmentMemberList] \u53EA\u6709 Department Head \u53EF\u4EE5\u67E5\u770B\u90E8\u95E8\u6210\u5458\u76EE\u5F55`;
|
|
43767
|
+
const activeContext = departmentAgentId ? getActiveMailboxContext(fromMailboxId, userRequest.requestId) : null;
|
|
43768
|
+
let toMailboxId = targetMailboxId;
|
|
43769
|
+
let targetMember = targetMailboxId ? getDepartmentMemberByMailboxId(targetMailboxId) : null;
|
|
43770
|
+
if (departmentAgentId && targetMailboxId && looksLikePseudoManagerMailbox(targetMailboxId)) {
|
|
43771
|
+
return buildManagerRoutingRejection(activeContext);
|
|
43680
43772
|
}
|
|
43681
|
-
|
|
43682
|
-
|
|
43683
|
-
|
|
43773
|
+
if (departmentAgentId && targetMailboxId && !targetMember) {
|
|
43774
|
+
return [
|
|
43775
|
+
`[departmentCommunicate] \u62D2\u7EDD\u53D1\u9001\u5230\u4E0D\u5B58\u5728\u7684 mailbox: ${targetMailboxId}`,
|
|
43776
|
+
`Department agent \u4F7F\u7528 target_mailbox_id \u65F6\uFF0C\u76EE\u6807\u5FC5\u987B\u662F\u5DF2\u5B58\u5728\u7684\u90E8\u95E8\u6210\u5458 mailbox\u3002`,
|
|
43777
|
+
`\u5982\u679C\u4F60\u60F3\u56DE\u590D\u4E0A\u6E38 CEO/Main Manager\uFF0C\u8BF7\u4E0D\u8981\u4F2A\u9020 manager \u5730\u5740\uFF1B\u8BF7\u4F7F\u7528\u539F\u90AE\u4EF6\u7684 reply_mailbox \u6216 mailbox_followup\u3002`
|
|
43778
|
+
].join(`
|
|
43779
|
+
`);
|
|
43684
43780
|
}
|
|
43685
|
-
if (
|
|
43686
|
-
|
|
43781
|
+
if (!toMailboxId) {
|
|
43782
|
+
if (!departmentName || !memberName) {
|
|
43783
|
+
return `[departmentCommunicate] department_name/member_name \u6216 target_mailbox_id \u81F3\u5C11\u9700\u8981\u63D0\u4F9B\u4E00\u79CD`;
|
|
43784
|
+
}
|
|
43785
|
+
targetMember = getDepartmentMemberByName(departmentName, memberName);
|
|
43786
|
+
if (!targetMember) {
|
|
43787
|
+
return `[departmentCommunicate] \u4E0D\u5B58\u5728 ${departmentName} \u90E8\u95E8\u7684\u6210\u5458: ${memberName}`;
|
|
43788
|
+
}
|
|
43789
|
+
toMailboxId = getMailBoxId(departmentName, memberName);
|
|
43790
|
+
}
|
|
43791
|
+
const isCrossDepartment = Boolean(actorMember && targetMember && actorMember.departmentId !== targetMember.departmentId);
|
|
43792
|
+
const isKnownAddressPath = Boolean(targetMailboxId);
|
|
43793
|
+
const options = {
|
|
43794
|
+
auditDetail: {
|
|
43795
|
+
communicationPolicy: "allowed_known_address",
|
|
43796
|
+
isKnownAddressPath,
|
|
43797
|
+
isCrossDepartment,
|
|
43798
|
+
actorRole: actorMember?.role ?? "ceo",
|
|
43799
|
+
targetRole: targetMember?.role ?? "unknown",
|
|
43800
|
+
reason: reason ?? null
|
|
43801
|
+
}
|
|
43802
|
+
};
|
|
43803
|
+
if (!departmentAgentId) {
|
|
43804
|
+
options.originUserId = userRequest.userId;
|
|
43805
|
+
options.originPlatform = userRequest.platform;
|
|
43806
|
+
} else {
|
|
43807
|
+
if (activeContext) {
|
|
43808
|
+
options.originUserId = activeContext.originUserId;
|
|
43809
|
+
options.originPlatform = activeContext.originPlatform;
|
|
43810
|
+
options.threadId = activeContext.threadId || activeContext.id;
|
|
43811
|
+
options.parentMessageId = activeContext.id;
|
|
43812
|
+
options.workItemId = activeContext.workItemId;
|
|
43813
|
+
options.upstreamMessageId = activeContext.upstreamMessageId;
|
|
43814
|
+
}
|
|
43687
43815
|
}
|
|
43688
|
-
|
|
43689
|
-
|
|
43690
|
-
|
|
43816
|
+
try {
|
|
43817
|
+
sendMessage2(fromMailboxId, toMailboxId, content, options);
|
|
43818
|
+
} catch (err) {
|
|
43819
|
+
return `[departmentCommunicate] \u53D1\u9001\u6D88\u606F\u5931\u8D25: ${err.message}`;
|
|
43691
43820
|
}
|
|
43692
|
-
|
|
43693
|
-
id: member.id,
|
|
43694
|
-
name: member.name,
|
|
43695
|
-
role: member.role ?? "executor",
|
|
43696
|
-
mailBoxId: member.mailBoxId,
|
|
43697
|
-
workspaceId: member.workspaceId,
|
|
43698
|
-
focusOn: member.focusOn
|
|
43699
|
-
}));
|
|
43700
|
-
return `[departmentMemberList] ${department.name} \u90E8\u95E8\u6210\u5458\u76EE\u5F55: ${JSON.stringify(members)}`;
|
|
43821
|
+
return `[departmentCommunicate] \u6D88\u606F\u5DF2\u53D1\u9001\u5230 ${toMailboxId}`;
|
|
43701
43822
|
}
|
|
43702
43823
|
};
|
|
43703
43824
|
|
|
43704
|
-
// src/tools/tools/department/
|
|
43705
|
-
var
|
|
43706
|
-
\
|
|
43825
|
+
// src/tools/tools/department/DepartmentDelete.ts
|
|
43826
|
+
var DESCRIPTION22 = `
|
|
43827
|
+
\u5220\u9664\u90E8\u95E8\u3002
|
|
43707
43828
|
|
|
43708
|
-
\
|
|
43829
|
+
\u5DE5\u5177\u8C03\u7528\u89C4\u5219\uFF1A
|
|
43830
|
+
- \u89E3\u6563\u90E8\u95E8\u662F\u4E0D\u53EF\u9006\u64CD\u4F5C\uFF0C\u5FC5\u987B\u5148\u5F81\u5F97\u7528\u6237\u660E\u786E\u786E\u8BA4\u3002
|
|
43831
|
+
- \u9996\u6B21\u8C03\u7528 confirmed \u5FC5\u987B\u4E3A false \u6216\u4E0D\u4F20\uFF1B\u5F97\u5230\u7528\u6237\u660E\u786E\u540C\u610F\u540E\uFF0C\u518D\u4EE5 confirmed=true \u8C03\u7528\u3002
|
|
43832
|
+
- \u4E25\u7981\u5728\u672A\u5F97\u5230\u7528\u6237\u660E\u786E\u786E\u8BA4\u7684\u60C5\u51B5\u4E0B\u76F4\u63A5\u4F20 confirmed=true\u3002
|
|
43709
43833
|
`;
|
|
43710
|
-
var
|
|
43711
|
-
name: `
|
|
43712
|
-
description:
|
|
43834
|
+
var departmentDelete = {
|
|
43835
|
+
name: `department_delete`,
|
|
43836
|
+
description: DESCRIPTION22,
|
|
43713
43837
|
input_schema: {
|
|
43714
43838
|
type: `object`,
|
|
43715
43839
|
properties: {
|
|
43716
|
-
|
|
43840
|
+
name: {
|
|
43717
43841
|
type: `string`,
|
|
43718
|
-
description: `\
|
|
43842
|
+
description: `\u8981\u5220\u9664\u7684\u90E8\u95E8\u540D\u79F0`
|
|
43843
|
+
},
|
|
43844
|
+
confirmed: {
|
|
43845
|
+
type: `boolean`,
|
|
43846
|
+
description: `\u7528\u6237\u662F\u5426\u5DF2\u660E\u786E\u786E\u8BA4\u89E3\u6563\u8BE5\u90E8\u95E8`
|
|
43719
43847
|
}
|
|
43720
43848
|
},
|
|
43721
|
-
required: []
|
|
43849
|
+
required: [`name`]
|
|
43722
43850
|
},
|
|
43723
43851
|
async execute(input) {
|
|
43724
|
-
const
|
|
43725
|
-
const
|
|
43726
|
-
|
|
43727
|
-
|
|
43728
|
-
const stmt = db3.prepare(
|
|
43729
|
-
`SELECT id, to_mailbox_id as toMailboxId, from_mailbox_id as fromMailboxId, content, send_time as sendTime, status
|
|
43730
|
-
FROM mailbox
|
|
43731
|
-
WHERE to_mailbox_id = 'manager' AND from_mailbox_id = ? AND status in ('pending', 'processing')
|
|
43732
|
-
ORDER BY send_time ASC`
|
|
43733
|
-
);
|
|
43734
|
-
msgs = stmt.all(fromMember);
|
|
43735
|
-
} else {
|
|
43736
|
-
const stmt = db3.prepare(
|
|
43737
|
-
`SELECT id, to_mailbox_id as toMailboxId, from_mailbox_id as fromMailboxId, content, send_time as sendTime, status
|
|
43738
|
-
FROM mailbox
|
|
43739
|
-
WHERE to_mailbox_id = 'manager' AND status in ('pending', 'processing')
|
|
43740
|
-
ORDER BY send_time ASC`
|
|
43741
|
-
);
|
|
43742
|
-
msgs = stmt.all();
|
|
43743
|
-
}
|
|
43744
|
-
if (msgs.length === 0) {
|
|
43745
|
-
return [
|
|
43746
|
-
`[checkDepartmentReplies] \u56E2\u961F\u8FD9\u4F1A\u513F\u8FD8\u6CA1\u56DE\u4FE1\uFF0C\u591A\u534A\u662F\u8D1F\u8D23\u4EBA\u4ECD\u5728\u5904\u7406\uFF0C\u8FC7\u4F1A\u513F\u518D\u6765\u770B\u3002`,
|
|
43747
|
-
``,
|
|
43748
|
-
`\u51E0\u53E5\u63D0\u9192\uFF1A`,
|
|
43749
|
-
`- \u8FD9\u4E0D\u4EE3\u8868\u8981\u4F60\u4EB2\u81EA\u4E0B\u573A read/bash/\u6D4B\u8BD5/\u6539\u4EE3\u7801\u2014\u2014\u56E2\u961F\u6CA1\u56DE\uFF0C\u4E0D\u662F\u4F60\u8BE5\u63A5\u624B\u7684\u4FE1\u53F7\u3002`,
|
|
43750
|
-
`- \u8001\u677F\u8981\u662F\u6B63\u7B49\u7740\uFF0C\u5148\u7528 send_message \u5982\u5B9E\u8DDF\u4ED6\u8BF4\u4E00\u53E5\u201C\u8D1F\u8D23\u4EBA\u8FD8\u5728\u5904\u7406\uFF0C\u6211\u62FF\u5230\u7ED3\u679C\u5C31\u540C\u6B65\u201D\u3002`,
|
|
43751
|
-
`- \u5982\u679C\u4EFB\u52A1\u521A\u6D3E\u51FA\u53BB\uFF0C\u4E0D\u8981\u5728\u540C\u4E00\u8F6E\u9A6C\u4E0A\u50AC\u529E\uFF1B\u7ED9\u8D1F\u8D23\u4EBA\u5408\u7406\u5904\u7406\u65F6\u95F4\u3002`,
|
|
43752
|
-
`- \u5DF2\u7ECF\u7B49\u4E86\u4E00\u9635\u3001\u8001\u677F\u53C8\u8FFD\u95EE\uFF0C\u6216\u53D1\u73B0\u660E\u786E\u98CE\u9669\u65F6\uFF0C\u518D\u7528 mailbox_followup \u6216 department_communicate \u53BB\u95EE\u5BF9\u5E94 Department Head \u771F\u5B9E\u8FDB\u5C55\u3001\u5361\u5728\u54EA\u3001\u5927\u6982\u4EC0\u4E48\u65F6\u5019\u597D\u3002`,
|
|
43753
|
-
`- \u522B\u5728\u8FD9\u4E00\u8F6E\u91CC\u53CD\u590D\u7A7A\u67E5 check_department_replies\uFF1B\u7B49\u56E2\u961F\u56DE\u4FE1\u3001\u8001\u677F\u8FFD\u95EE\u6216\u50AC\u529E\u6709\u4E86\u56DE\u97F3\uFF0C\u518D\u6765\u770B\u3002`
|
|
43754
|
-
].join("\n");
|
|
43755
|
-
}
|
|
43756
|
-
const updateStmt = db3.prepare(`UPDATE mailbox SET status = 'read' WHERE id = ?`);
|
|
43757
|
-
for (const msg of msgs) {
|
|
43758
|
-
updateStmt.run(msg.id);
|
|
43759
|
-
}
|
|
43760
|
-
const replies = msgs.map((msg, i) => {
|
|
43761
|
-
const time = new Date(msg.sendTime).toLocaleString("zh-CN", { timeZone: "Asia/Shanghai" });
|
|
43762
|
-
return `--- \u56DE\u4FE1 ${i + 1} ---
|
|
43763
|
-
id: ${msg.id}
|
|
43764
|
-
\u6765\u81EA: ${msg.fromMailboxId}
|
|
43765
|
-
\u65F6\u95F4: ${time}
|
|
43766
|
-
\u72B6\u6001: ${msg.status}
|
|
43767
|
-
\u5185\u5BB9:
|
|
43768
|
-
${msg.content}`;
|
|
43769
|
-
}).join("\n\n");
|
|
43770
|
-
return `[checkDepartmentReplies] \u6536\u5230 ${msgs.length} \u6761\u90E8\u95E8\u56DE\u4FE1\uFF1A
|
|
43771
|
-
|
|
43772
|
-
${replies}`;
|
|
43773
|
-
}
|
|
43774
|
-
};
|
|
43775
|
-
|
|
43776
|
-
// src/department/learning.ts
|
|
43777
|
-
var import_node_fs4 = require("node:fs");
|
|
43778
|
-
var import_node_path13 = __toESM(require("node:path"));
|
|
43779
|
-
var import_node_crypto10 = require("node:crypto");
|
|
43780
|
-
|
|
43781
|
-
// src/skill/SkillValidator.ts
|
|
43782
|
-
var import_node_fs3 = require("node:fs");
|
|
43783
|
-
var import_node_path12 = __toESM(require("node:path"));
|
|
43784
|
-
var SKILL_NAME_PATTERN = /^[a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?$/;
|
|
43785
|
-
var REQUIRED_SECTIONS = [
|
|
43786
|
-
/(^|\n)##\s+(when to use|何时使用|trigger|triggers)\b/i,
|
|
43787
|
-
/(^|\n)##\s+(steps|workflow|procedure|执行步骤|工作流)\b/i
|
|
43788
|
-
];
|
|
43789
|
-
var stripYamlQuotes = (value) => {
|
|
43790
|
-
const trimmed = value.trim();
|
|
43791
|
-
if (trimmed.startsWith(`"`) && trimmed.endsWith(`"`) || trimmed.startsWith(`'`) && trimmed.endsWith(`'`)) {
|
|
43792
|
-
return trimmed.slice(1, -1).trim();
|
|
43793
|
-
}
|
|
43794
|
-
return trimmed;
|
|
43795
|
-
};
|
|
43796
|
-
var addError = (errors, code, message) => {
|
|
43797
|
-
errors.push({ code, message });
|
|
43798
|
-
};
|
|
43799
|
-
var addWarning = (warnings, code, message) => {
|
|
43800
|
-
warnings.push({ code, message });
|
|
43801
|
-
};
|
|
43802
|
-
var isValidSkillName = (name) => {
|
|
43803
|
-
return SKILL_NAME_PATTERN.test(name) && !name.includes(`--`);
|
|
43804
|
-
};
|
|
43805
|
-
var assertSafeSkillTarget = (rootDir, skillName) => {
|
|
43806
|
-
if (!isValidSkillName(skillName)) {
|
|
43807
|
-
throw new Error(`Invalid skill name "${skillName}". Use lowercase letters, digits, and single hyphens only.`);
|
|
43808
|
-
}
|
|
43809
|
-
const root = import_node_path12.default.resolve(rootDir);
|
|
43810
|
-
const target = import_node_path12.default.resolve(root, skillName);
|
|
43811
|
-
if (target !== import_node_path12.default.join(root, skillName) || !target.startsWith(root + import_node_path12.default.sep)) {
|
|
43812
|
-
throw new Error(`Invalid skill install target for "${skillName}".`);
|
|
43813
|
-
}
|
|
43814
|
-
return target;
|
|
43815
|
-
};
|
|
43816
|
-
var parseSkillDocument = (skillMd) => {
|
|
43817
|
-
const fmMatch = skillMd.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/);
|
|
43818
|
-
if (!fmMatch) return null;
|
|
43819
|
-
const frontmatter = {};
|
|
43820
|
-
for (const rawLine of fmMatch[1].split(/\r?\n/)) {
|
|
43821
|
-
const line = rawLine.trim();
|
|
43822
|
-
if (!line || line.startsWith(`#`)) continue;
|
|
43823
|
-
const match2 = line.match(/^([A-Za-z0-9_-]+):\s*(.*)$/);
|
|
43824
|
-
if (!match2) {
|
|
43825
|
-
frontmatter[`__invalid__${Object.keys(frontmatter).length}`] = line;
|
|
43826
|
-
continue;
|
|
43827
|
-
}
|
|
43828
|
-
frontmatter[match2[1]] = stripYamlQuotes(match2[2]);
|
|
43829
|
-
}
|
|
43830
|
-
return {
|
|
43831
|
-
name: frontmatter.name ?? ``,
|
|
43832
|
-
description: frontmatter.description ?? ``,
|
|
43833
|
-
body: skillMd.slice(fmMatch[0].length).trim(),
|
|
43834
|
-
frontmatter
|
|
43835
|
-
};
|
|
43836
|
-
};
|
|
43837
|
-
var validateSkillDocument = (input) => {
|
|
43838
|
-
const errors = [];
|
|
43839
|
-
const warnings = [];
|
|
43840
|
-
const skillMd = input.skillMd;
|
|
43841
|
-
if (!skillMd || !skillMd.trim()) {
|
|
43842
|
-
addError(errors, `empty_skill_md`, `SKILL.md content is required.`);
|
|
43843
|
-
return { ok: false, errors, warnings };
|
|
43844
|
-
}
|
|
43845
|
-
const parsed = parseSkillDocument(skillMd);
|
|
43846
|
-
if (!parsed) {
|
|
43847
|
-
addError(errors, `missing_frontmatter`, `SKILL.md must start with YAML frontmatter delimited by "---".`);
|
|
43848
|
-
return { ok: false, errors, warnings };
|
|
43849
|
-
}
|
|
43850
|
-
const invalidFrontmatterLines = Object.keys(parsed.frontmatter).filter((key) => key.startsWith(`__invalid__`));
|
|
43851
|
-
if (invalidFrontmatterLines.length > 0) {
|
|
43852
|
-
addError(errors, `invalid_frontmatter`, `Frontmatter must contain simple "key: value" lines.`);
|
|
43853
|
-
}
|
|
43854
|
-
if (!parsed.name) {
|
|
43855
|
-
addError(errors, `missing_name`, `Frontmatter field "name" is required.`);
|
|
43856
|
-
} else if (!isValidSkillName(parsed.name)) {
|
|
43857
|
-
addError(errors, `invalid_name`, `Skill name "${parsed.name}" must be kebab-case, under 64 characters, and path-safe.`);
|
|
43858
|
-
}
|
|
43859
|
-
if (!parsed.description) {
|
|
43860
|
-
addError(errors, `missing_description`, `Frontmatter field "description" is required.`);
|
|
43861
|
-
} else if (parsed.description.length > 500) {
|
|
43862
|
-
addWarning(warnings, `long_description`, `Skill description is long; keep trigger metadata concise.`);
|
|
43863
|
-
}
|
|
43864
|
-
if (input.skillName && parsed.name && input.skillName !== parsed.name) {
|
|
43865
|
-
addError(errors, `name_mismatch`, `Input skillName "${input.skillName}" must match frontmatter name "${parsed.name}".`);
|
|
43866
|
-
}
|
|
43867
|
-
if (input.description && parsed.description && input.description !== parsed.description) {
|
|
43868
|
-
addError(errors, `description_mismatch`, `Input description must match frontmatter description.`);
|
|
43869
|
-
}
|
|
43870
|
-
if (!parsed.body) {
|
|
43871
|
-
addError(errors, `empty_body`, `SKILL.md body is required.`);
|
|
43872
|
-
} else {
|
|
43873
|
-
if (!/(^|\n)#\s+\S/.test(parsed.body)) {
|
|
43874
|
-
addWarning(warnings, `missing_title`, `Skill body should start with a Markdown H1 title.`);
|
|
43875
|
-
}
|
|
43876
|
-
for (const sectionPattern of REQUIRED_SECTIONS) {
|
|
43877
|
-
if (!sectionPattern.test(parsed.body)) {
|
|
43878
|
-
addWarning(warnings, `missing_recommended_section`, `Skill body should include when-to-use and execution workflow sections.`);
|
|
43879
|
-
break;
|
|
43880
|
-
}
|
|
43881
|
-
}
|
|
43882
|
-
}
|
|
43883
|
-
if (input.baseDir) {
|
|
43884
|
-
const normalizedBase = import_node_path12.default.resolve(input.baseDir);
|
|
43885
|
-
for (const match2 of parsed.body.matchAll(/\]\(([^)]+)\)/g)) {
|
|
43886
|
-
const href = match2[1].trim();
|
|
43887
|
-
if (!href || /^[a-z][a-z0-9+.-]*:/i.test(href) || href.startsWith(`#`)) continue;
|
|
43888
|
-
const target = import_node_path12.default.resolve(normalizedBase, href.split(`#`)[0]);
|
|
43889
|
-
if (!target.startsWith(normalizedBase + import_node_path12.default.sep) && target !== normalizedBase) {
|
|
43890
|
-
addError(errors, `unsafe_reference`, `Relative link "${href}" escapes the skill directory.`);
|
|
43891
|
-
} else if (!(0, import_node_fs3.existsSync)(target)) {
|
|
43892
|
-
addError(errors, `missing_reference`, `Relative link "${href}" does not exist in the skill directory.`);
|
|
43893
|
-
}
|
|
43852
|
+
const name = input.name;
|
|
43853
|
+
const confirmed = input.confirmed ?? false;
|
|
43854
|
+
if (!confirmed) {
|
|
43855
|
+
return `[departmentDelete] \u89E3\u6563\u90E8\u95E8\u662F\u4E0D\u53EF\u9006\u64CD\u4F5C\uFF0C\u8BF7\u5148\u7528 send_message \u5411\u7528\u6237\u786E\u8BA4"\u662F\u5426\u89E3\u6563\u90E8\u95E8 ${name}"\uFF0C\u5F97\u5230\u7528\u6237\u660E\u786E\u540C\u610F\u540E\uFF0C\u518D\u4EE5 confirmed=true \u91CD\u65B0\u8C03\u7528\u672C\u5DE5\u5177\u3002`;
|
|
43894
43856
|
}
|
|
43857
|
+
try {
|
|
43858
|
+
const members = listDepartmentMembers(name);
|
|
43859
|
+
let totalCancelled = 0;
|
|
43860
|
+
for (const member of members) {
|
|
43861
|
+
const mailboxId = getMailBoxId(name, member.name);
|
|
43862
|
+
totalCancelled += cancelMailboxMessages(mailboxId);
|
|
43863
|
+
}
|
|
43864
|
+
if (totalCancelled > 0) {
|
|
43865
|
+
console.log(`[departmentDelete] \u5DF2\u53D6\u6D88\u90E8\u95E8 ${name} \u7684 ${totalCancelled} \u6761\u6B8B\u7559 mailbox \u6D88\u606F`);
|
|
43866
|
+
}
|
|
43867
|
+
deleteDepartment(name);
|
|
43868
|
+
} catch (err) {
|
|
43869
|
+
return `[departmentDelete] \u5220\u9664\u90E8\u95E8\u5931\u8D25: ${err.message}`;
|
|
43870
|
+
}
|
|
43871
|
+
return `[departmentDelete] \u5220\u9664\u90E8\u95E8\u6210\u529F: ${name}`;
|
|
43895
43872
|
}
|
|
43896
|
-
return {
|
|
43897
|
-
ok: errors.length === 0,
|
|
43898
|
-
skill: parsed,
|
|
43899
|
-
errors,
|
|
43900
|
-
warnings
|
|
43901
|
-
};
|
|
43902
|
-
};
|
|
43903
|
-
var mergeIssues = (target, source) => {
|
|
43904
|
-
target.errors.push(...source.errors);
|
|
43905
|
-
target.warnings.push(...source.warnings);
|
|
43906
|
-
};
|
|
43907
|
-
var validateScriptsDirectory = (skillDir, warnings) => {
|
|
43908
|
-
const scriptsDir = import_node_path12.default.join(skillDir, `scripts`);
|
|
43909
|
-
if (!(0, import_node_fs3.existsSync)(scriptsDir)) return;
|
|
43910
|
-
const entries = (0, import_node_fs3.readdirSync)(scriptsDir, { withFileTypes: true }).filter((entry) => entry.isFile());
|
|
43911
|
-
if (entries.length === 0) {
|
|
43912
|
-
addWarning(warnings, `empty_scripts_dir`, `scripts/ exists but contains no files.`);
|
|
43913
|
-
}
|
|
43914
|
-
};
|
|
43915
|
-
var validateSkillDirectory = (skillDir, options = {}) => {
|
|
43916
|
-
const errors = [];
|
|
43917
|
-
const warnings = [];
|
|
43918
|
-
const normalizedSkillDir = import_node_path12.default.resolve(skillDir);
|
|
43919
|
-
const skillMdPath = import_node_path12.default.join(normalizedSkillDir, `SKILL.md`);
|
|
43920
|
-
if (!(0, import_node_fs3.existsSync)(normalizedSkillDir) || !(0, import_node_fs3.statSync)(normalizedSkillDir).isDirectory()) {
|
|
43921
|
-
addError(errors, `missing_skill_dir`, `Skill directory does not exist: ${normalizedSkillDir}`);
|
|
43922
|
-
return { ok: false, errors, warnings, skillDir: normalizedSkillDir, skillMdPath };
|
|
43923
|
-
}
|
|
43924
|
-
if (!(0, import_node_fs3.existsSync)(skillMdPath) || !(0, import_node_fs3.statSync)(skillMdPath).isFile()) {
|
|
43925
|
-
addError(errors, `missing_skill_md`, `Skill directory must contain SKILL.md.`);
|
|
43926
|
-
return { ok: false, errors, warnings, skillDir: normalizedSkillDir, skillMdPath };
|
|
43927
|
-
}
|
|
43928
|
-
const raw2 = (0, import_node_fs3.readFileSync)(skillMdPath, `utf-8`);
|
|
43929
|
-
const documentResult = validateSkillDocument({
|
|
43930
|
-
skillName: options.expectedName ?? import_node_path12.default.basename(normalizedSkillDir),
|
|
43931
|
-
skillMd: raw2,
|
|
43932
|
-
baseDir: normalizedSkillDir
|
|
43933
|
-
});
|
|
43934
|
-
mergeIssues({ errors, warnings }, documentResult);
|
|
43935
|
-
validateScriptsDirectory(normalizedSkillDir, warnings);
|
|
43936
|
-
return {
|
|
43937
|
-
ok: errors.length === 0,
|
|
43938
|
-
skill: documentResult.skill,
|
|
43939
|
-
errors,
|
|
43940
|
-
warnings,
|
|
43941
|
-
skillDir: normalizedSkillDir,
|
|
43942
|
-
skillMdPath
|
|
43943
|
-
};
|
|
43944
43873
|
};
|
|
43945
|
-
var smokeTestSkillDirectory = (skillDir, options = {}) => {
|
|
43946
|
-
const directoryResult = validateSkillDirectory(skillDir, options);
|
|
43947
|
-
const errors = [...directoryResult.errors];
|
|
43948
|
-
const warnings = [...directoryResult.warnings];
|
|
43949
|
-
let detail;
|
|
43950
|
-
if (directoryResult.ok && directoryResult.skill) {
|
|
43951
|
-
detail = `Base directory for this skill: ${directoryResult.skillDir}
|
|
43952
43874
|
|
|
43953
|
-
|
|
43954
|
-
|
|
43955
|
-
|
|
43956
|
-
|
|
43957
|
-
|
|
43958
|
-
|
|
43959
|
-
|
|
43960
|
-
|
|
43961
|
-
|
|
43875
|
+
// src/tools/tools/department/DepartmentList.ts
|
|
43876
|
+
var DESCRIPTION23 = `
|
|
43877
|
+
\u5217\u51FA\u6240\u6709\u90E8\u95E8\u3002\u8BE5\u5DE5\u5177\u9762\u5411 CEO\uFF0C\u53EA\u8FD4\u56DE\u90E8\u95E8\u4E0E Department Head \u4FE1\u606F\uFF0C\u4E0D\u66B4\u9732 Executor \u660E\u7EC6\u3002
|
|
43878
|
+
|
|
43879
|
+
\u5DE5\u5177\u8C03\u7528\u89C4\u5219\uFF1A
|
|
43880
|
+
- \u5F53\u7528\u6237\u8981\u6C42\u5217\u51FA\u6240\u6709\u90E8\u95E8\u65F6\u8C03\u7528\u6B64\u5DE5\u5177\u3002
|
|
43881
|
+
- \u5F53\u590D\u6742\u4EFB\u52A1\u9700\u8981\u5224\u65AD\u73B0\u6709\u90E8\u95E8\u804C\u8D23\u65F6\u8C03\u7528\u6B64\u5DE5\u5177\u3002
|
|
43882
|
+
`;
|
|
43883
|
+
var departmentList = {
|
|
43884
|
+
name: `department_list`,
|
|
43885
|
+
description: DESCRIPTION23,
|
|
43886
|
+
input_schema: {
|
|
43887
|
+
type: `object`,
|
|
43888
|
+
properties: {},
|
|
43889
|
+
required: []
|
|
43890
|
+
},
|
|
43891
|
+
async execute() {
|
|
43892
|
+
const departments = listDepartments();
|
|
43893
|
+
if (departments.length === 0) {
|
|
43894
|
+
return `[departmentList] \u5F53\u524D\u6CA1\u6709\u4EFB\u4F55\u90E8\u95E8\u3002`;
|
|
43962
43895
|
}
|
|
43896
|
+
const visibleDepartments = departments.map((department) => {
|
|
43897
|
+
const head = department.headMemberId ? department.departmentMembers.find((member) => member.id === department.headMemberId) : department.departmentMembers.find((member) => member.role === "department_head");
|
|
43898
|
+
const executors = department.departmentMembers.filter((member) => member.id !== head?.id);
|
|
43899
|
+
return {
|
|
43900
|
+
id: department.id,
|
|
43901
|
+
name: department.name,
|
|
43902
|
+
sourceGoalId: department.sourceGoalId,
|
|
43903
|
+
charter: department.charter,
|
|
43904
|
+
workpath: department.workpath,
|
|
43905
|
+
head: head ? {
|
|
43906
|
+
id: head.id,
|
|
43907
|
+
name: head.name,
|
|
43908
|
+
mailBoxId: head.mailBoxId,
|
|
43909
|
+
focusOn: head.focusOn
|
|
43910
|
+
} : null,
|
|
43911
|
+
executorCount: executors.length
|
|
43912
|
+
};
|
|
43913
|
+
});
|
|
43914
|
+
return `[departmentList] \u627E\u5230\u90E8\u95E8: ${JSON.stringify(visibleDepartments)}`;
|
|
43963
43915
|
}
|
|
43964
|
-
return {
|
|
43965
|
-
...directoryResult,
|
|
43966
|
-
ok: errors.length === 0,
|
|
43967
|
-
errors,
|
|
43968
|
-
warnings,
|
|
43969
|
-
detail
|
|
43970
|
-
};
|
|
43971
|
-
};
|
|
43972
|
-
var formatSkillValidationIssues = (result) => {
|
|
43973
|
-
const lines = [
|
|
43974
|
-
...result.errors.map((issue) => `- [${issue.code}] ${issue.message}`),
|
|
43975
|
-
...result.warnings.map((issue) => `- [warning:${issue.code}] ${issue.message}`)
|
|
43976
|
-
];
|
|
43977
|
-
return lines.join(`
|
|
43978
|
-
`);
|
|
43979
43916
|
};
|
|
43980
43917
|
|
|
43981
|
-
// src/department/
|
|
43982
|
-
var
|
|
43983
|
-
var
|
|
43984
|
-
|
|
43985
|
-
|
|
43986
|
-
|
|
43987
|
-
|
|
43988
|
-
|
|
43989
|
-
|
|
43990
|
-
|
|
43991
|
-
var
|
|
43992
|
-
|
|
43993
|
-
|
|
43994
|
-
|
|
43995
|
-
|
|
43996
|
-
|
|
43997
|
-
|
|
43998
|
-
|
|
43999
|
-
|
|
44000
|
-
|
|
44001
|
-
|
|
44002
|
-
|
|
44003
|
-
|
|
44004
|
-
|
|
44005
|
-
|
|
44006
|
-
|
|
44007
|
-
|
|
44008
|
-
|
|
44009
|
-
|
|
44010
|
-
|
|
44011
|
-
|
|
44012
|
-
|
|
44013
|
-
}
|
|
44014
|
-
|
|
44015
|
-
|
|
44016
|
-
|
|
44017
|
-
|
|
44018
|
-
|
|
44019
|
-
|
|
44020
|
-
|
|
44021
|
-
|
|
44022
|
-
|
|
44023
|
-
|
|
44024
|
-
|
|
44025
|
-
|
|
44026
|
-
|
|
44027
|
-
|
|
44028
|
-
|
|
44029
|
-
}
|
|
44030
|
-
|
|
44031
|
-
|
|
44032
|
-
|
|
44033
|
-
|
|
44034
|
-
|
|
44035
|
-
|
|
44036
|
-
|
|
44037
|
-
|
|
44038
|
-
|
|
44039
|
-
|
|
44040
|
-
|
|
44041
|
-
|
|
44042
|
-
|
|
44043
|
-
|
|
44044
|
-
|
|
44045
|
-
|
|
44046
|
-
|
|
44047
|
-
|
|
44048
|
-
|
|
44049
|
-
|
|
44050
|
-
|
|
44051
|
-
|
|
44052
|
-
|
|
44053
|
-
|
|
44054
|
-
|
|
44055
|
-
|
|
44056
|
-
|
|
44057
|
-
|
|
44058
|
-
|
|
44059
|
-
|
|
44060
|
-
|
|
44061
|
-
|
|
44062
|
-
const records = listDepartmentSkills(departmentName);
|
|
44063
|
-
if (records.some((record) => record.skillName === input.skillName && record.status !== "dropped")) {
|
|
44064
|
-
return null;
|
|
43918
|
+
// src/tools/tools/department/DepartmentMemberCreate.ts
|
|
43919
|
+
var import_node_crypto10 = require("node:crypto");
|
|
43920
|
+
var DESCRIPTION24 = `
|
|
43921
|
+
\u521B\u5EFA\u90E8\u95E8\u6210\u5458\u3002
|
|
43922
|
+
|
|
43923
|
+
\u7BA1\u7406\u6743\u9650\uFF1A
|
|
43924
|
+
- CEO \u53EA\u80FD\u521B\u5EFA Department Head\u3002
|
|
43925
|
+
- Department Head \u53EF\u4EE5\u5728\u81EA\u5DF1\u90E8\u95E8\u5185\u521B\u5EFA Executor\u3002
|
|
43926
|
+
- Executor \u4E0D\u80FD\u521B\u5EFA\u6210\u5458\u3002
|
|
43927
|
+
`;
|
|
43928
|
+
var departmentMemberCreate = {
|
|
43929
|
+
name: `department_member_create`,
|
|
43930
|
+
description: DESCRIPTION24,
|
|
43931
|
+
input_schema: {
|
|
43932
|
+
type: `object`,
|
|
43933
|
+
properties: {
|
|
43934
|
+
name: {
|
|
43935
|
+
type: `string`,
|
|
43936
|
+
description: `\u90E8\u95E8\u6210\u5458\u540D\u79F0`
|
|
43937
|
+
},
|
|
43938
|
+
departmentName: {
|
|
43939
|
+
type: `string`,
|
|
43940
|
+
description: `\u6210\u5458\u6240\u5C5E\u90E8\u95E8\u540D\u79F0\uFF0C\u4E0D\u8981\u81C6\u9020`
|
|
43941
|
+
},
|
|
43942
|
+
focusOn: {
|
|
43943
|
+
type: `string`,
|
|
43944
|
+
description: `\u8BE5\u6210\u5458\u7684\u957F\u671F\u5C97\u4F4D\u804C\u8D23\u4E0E\u884C\u4E3A\u8FB9\u754C\uFF0C\u4E0D\u8981\u5199\u4E00\u6B21\u6027\u4EFB\u52A1\u7EC6\u8282`
|
|
43945
|
+
},
|
|
43946
|
+
role: {
|
|
43947
|
+
type: `string`,
|
|
43948
|
+
enum: [`department_head`, `executor`],
|
|
43949
|
+
description: `\u6210\u5458\u89D2\u8272\u3002CEO \u521B\u5EFA\u90E8\u95E8\u8D1F\u8D23\u4EBA\u65F6\u4F20 department_head\uFF1BDepartment Head \u521B\u5EFA\u6267\u884C\u8005\u65F6\u4F20 executor`
|
|
43950
|
+
}
|
|
43951
|
+
},
|
|
43952
|
+
required: [`name`, `departmentName`, `focusOn`]
|
|
43953
|
+
},
|
|
43954
|
+
async execute(input, userRequest) {
|
|
43955
|
+
const name = input.name;
|
|
43956
|
+
const departmentName = input.departmentName;
|
|
43957
|
+
const requestedRole = input.role;
|
|
43958
|
+
const department = getDepartment(departmentName);
|
|
43959
|
+
if (!department) return `[departmentMemberCreate] \u4E0D\u5B58\u5728\u540D\u79F0\u4E3A ${departmentName} \u7684\u90E8\u95E8`;
|
|
43960
|
+
const focusOn = input.focusOn;
|
|
43961
|
+
const currentMailboxId = userRequest?.departmentAgentId;
|
|
43962
|
+
let role;
|
|
43963
|
+
if (currentMailboxId) {
|
|
43964
|
+
const currentMember = getDepartmentMemberByMailboxId(currentMailboxId);
|
|
43965
|
+
if (!currentMember) {
|
|
43966
|
+
return `[departmentMemberCreate] \u65E0\u6CD5\u8BC6\u522B\u5F53\u524D\u90E8\u95E8\u6210\u5458: ${currentMailboxId}`;
|
|
43967
|
+
}
|
|
43968
|
+
if (currentMember.role !== "department_head") {
|
|
43969
|
+
return `[departmentMemberCreate] \u53EA\u6709 Department Head \u53EF\u4EE5\u521B\u5EFA Executor`;
|
|
43970
|
+
}
|
|
43971
|
+
if (currentMember.departmentId !== department.id) {
|
|
43972
|
+
return `[departmentMemberCreate] Department Head \u53EA\u80FD\u5728\u81EA\u5DF1\u6240\u5C5E\u90E8\u95E8\u5185\u521B\u5EFA\u6210\u5458`;
|
|
43973
|
+
}
|
|
43974
|
+
role = requestedRole ?? "executor";
|
|
43975
|
+
if (role === "department_head") {
|
|
43976
|
+
return `[departmentMemberCreate] \u90E8\u95E8\u5DF2\u7531\u5F53\u524D Department Head \u7BA1\u7406\uFF0C\u4E0D\u80FD\u7531 Department Head \u518D\u521B\u5EFA Department Head`;
|
|
43977
|
+
}
|
|
43978
|
+
} else {
|
|
43979
|
+
role = requestedRole ?? "department_head";
|
|
43980
|
+
if (role !== "department_head") {
|
|
43981
|
+
return `[departmentMemberCreate] CEO \u53EA\u80FD\u521B\u5EFA Department Head\uFF1BExecutor \u5E94\u7531 Department Head \u521B\u5EFA`;
|
|
43982
|
+
}
|
|
43983
|
+
}
|
|
43984
|
+
let departmentMember = {
|
|
43985
|
+
id: (0, import_node_crypto10.randomUUID)().slice(0, 8),
|
|
43986
|
+
name,
|
|
43987
|
+
departmentId: department.id,
|
|
43988
|
+
mailBoxId: getMailBoxId(department.name, name),
|
|
43989
|
+
workspaceId: getWorkspaceId(department.name, name),
|
|
43990
|
+
role,
|
|
43991
|
+
focusOn
|
|
43992
|
+
};
|
|
43993
|
+
try {
|
|
43994
|
+
departmentMember = createDepartmentMember(departmentMember);
|
|
43995
|
+
} catch (err) {
|
|
43996
|
+
return `[departmentMemberCreate] \u521B\u5EFA\u90E8\u95E8\u6210\u5458\u5931\u8D25: ${err.message}`;
|
|
43997
|
+
}
|
|
43998
|
+
return `[departmentMemberCreate] \u521B\u5EFA\u90E8\u95E8\u6210\u5458\u6210\u529F: ${JSON.stringify(departmentMember)}`;
|
|
44065
43999
|
}
|
|
44066
|
-
const now = Date.now();
|
|
44067
|
-
const skill = {
|
|
44068
|
-
id: (0, import_node_crypto10.randomUUID)().slice(0, 8),
|
|
44069
|
-
departmentName,
|
|
44070
|
-
skillName: input.skillName,
|
|
44071
|
-
description: input.description,
|
|
44072
|
-
skillMd: input.skillMd,
|
|
44073
|
-
status: "pending",
|
|
44074
|
-
createdByMailboxId: input.createdByMailboxId,
|
|
44075
|
-
createdAt: now,
|
|
44076
|
-
updatedAt: now
|
|
44077
|
-
};
|
|
44078
|
-
records.push(skill);
|
|
44079
|
-
writeJsonArray(departmentSkillPath(departmentName), records);
|
|
44080
|
-
return skill;
|
|
44081
44000
|
};
|
|
44082
|
-
|
|
44083
|
-
|
|
44084
|
-
|
|
44085
|
-
|
|
44086
|
-
|
|
44087
|
-
|
|
44088
|
-
|
|
44089
|
-
|
|
44090
|
-
|
|
44091
|
-
|
|
44092
|
-
|
|
44093
|
-
|
|
44094
|
-
|
|
44095
|
-
|
|
44096
|
-
|
|
44097
|
-
|
|
44098
|
-
|
|
44099
|
-
|
|
44100
|
-
|
|
44101
|
-
|
|
44102
|
-
|
|
44103
|
-
|
|
44001
|
+
|
|
44002
|
+
// src/tools/tools/department/DepartmentMemberDelete.ts
|
|
44003
|
+
var DESCRIPTION25 = `
|
|
44004
|
+
\u5220\u9664\u90E8\u95E8\u6210\u5458\u3002
|
|
44005
|
+
|
|
44006
|
+
\u5DE5\u5177\u8C03\u7528\u89C4\u5219\uFF1A
|
|
44007
|
+
- \u5FC5\u987B\u662F\u7528\u6237\u660E\u786E\u8981\u6C42\u5220\u9664\u6210\u5458\u65F6\u4F7F\u7528\u3002
|
|
44008
|
+
- Department Head \u53EA\u80FD\u5220\u9664\u81EA\u5DF1\u90E8\u95E8\u5185\u7684 Executor\uFF0C\u4E0D\u80FD\u5220\u9664 Department Head\u3002
|
|
44009
|
+
- CEO \u53EF\u4EE5\u5728\u7528\u6237\u660E\u786E\u8981\u6C42\u65F6\u5220\u9664\u90E8\u95E8\u6210\u5458\u3002
|
|
44010
|
+
`;
|
|
44011
|
+
var departmentMemberDelete = {
|
|
44012
|
+
name: `department_member_delete`,
|
|
44013
|
+
description: DESCRIPTION25,
|
|
44014
|
+
input_schema: {
|
|
44015
|
+
type: `object`,
|
|
44016
|
+
properties: {
|
|
44017
|
+
department_name: {
|
|
44018
|
+
type: `string`,
|
|
44019
|
+
description: `\u5F85\u5220\u9664\u6210\u5458\u6240\u5C5E\u90E8\u95E8\u540D\u79F0`
|
|
44020
|
+
},
|
|
44021
|
+
member_id: {
|
|
44022
|
+
type: `string`,
|
|
44023
|
+
description: `\u5F85\u5220\u9664\u6210\u5458 id`
|
|
44024
|
+
}
|
|
44025
|
+
},
|
|
44026
|
+
required: [`department_name`, `member_id`]
|
|
44027
|
+
},
|
|
44028
|
+
async execute(input, userRequest) {
|
|
44029
|
+
const departmentName = input.department_name;
|
|
44030
|
+
const memberId = input.member_id;
|
|
44031
|
+
const department = getDepartment(departmentName);
|
|
44032
|
+
if (!department) return `[departmentMemberDelete] \u4E0D\u5B58\u5728\u540D\u79F0\u4E3A ${departmentName} \u7684\u90E8\u95E8`;
|
|
44033
|
+
const member = getDepartmentMember(departmentName, memberId);
|
|
44034
|
+
if (!member) return `[departmentMemberDelete] \u627E\u4E0D\u5230\u6210\u5458: ${memberId}`;
|
|
44035
|
+
const currentMailboxId = userRequest?.departmentAgentId;
|
|
44036
|
+
if (currentMailboxId) {
|
|
44037
|
+
const currentMember = getDepartmentMemberByMailboxId(currentMailboxId);
|
|
44038
|
+
if (!currentMember) return `[departmentMemberDelete] \u65E0\u6CD5\u8BC6\u522B\u5F53\u524D\u90E8\u95E8\u6210\u5458: ${currentMailboxId}`;
|
|
44039
|
+
if (currentMember.role !== "department_head") return `[departmentMemberDelete] \u53EA\u6709 Department Head \u53EF\u4EE5\u5220\u9664 Executor`;
|
|
44040
|
+
if (currentMember.departmentId !== department.id) return `[departmentMemberDelete] Department Head \u53EA\u80FD\u7BA1\u7406\u81EA\u5DF1\u6240\u5C5E\u90E8\u95E8`;
|
|
44041
|
+
if (member.role === "department_head") return `[departmentMemberDelete] Department Head \u4E0D\u80FD\u5220\u9664 Department Head`;
|
|
44042
|
+
}
|
|
44043
|
+
try {
|
|
44044
|
+
deleteDepartmentMemberById(departmentName, memberId);
|
|
44045
|
+
const mailboxId = getMailBoxId(departmentName, member.name);
|
|
44046
|
+
const cancelled = cancelMailboxMessages(mailboxId);
|
|
44047
|
+
if (cancelled > 0) {
|
|
44048
|
+
console.log(`[departmentMemberDelete] \u5DF2\u53D6\u6D88 ${cancelled} \u6761\u6B8B\u7559 mailbox \u6D88\u606F: ${mailboxId}`);
|
|
44049
|
+
}
|
|
44050
|
+
} catch (err) {
|
|
44051
|
+
return `[departmentMemberDelete] \u5220\u9664\u90E8\u95E8\u6210\u5458\u5931\u8D25: ${err.message}`;
|
|
44052
|
+
}
|
|
44053
|
+
return `[departmentMemberDelete] \u5220\u9664\u90E8\u95E8\u6210\u5458\u6210\u529F: ${JSON.stringify(memberId)}`;
|
|
44104
44054
|
}
|
|
44105
|
-
writeJsonArray(departmentSkillPath(departmentName), records);
|
|
44106
|
-
return records[idx];
|
|
44107
|
-
};
|
|
44108
|
-
var dropDepartmentSkill = (departmentName, id) => {
|
|
44109
|
-
const records = listDepartmentSkills(departmentName);
|
|
44110
|
-
const idx = records.findIndex((record) => record.id === id);
|
|
44111
|
-
if (idx < 0) return null;
|
|
44112
|
-
records[idx] = { ...records[idx], status: "dropped", updatedAt: Date.now() };
|
|
44113
|
-
writeJsonArray(departmentSkillPath(departmentName), records);
|
|
44114
|
-
return records[idx];
|
|
44115
44055
|
};
|
|
44116
|
-
|
|
44117
|
-
|
|
44118
|
-
|
|
44119
|
-
|
|
44120
|
-
|
|
44121
|
-
|
|
44122
|
-
|
|
44123
|
-
|
|
44124
|
-
|
|
44125
|
-
|
|
44126
|
-
|
|
44056
|
+
|
|
44057
|
+
// src/tools/tools/department/DepartmentMemberList.ts
|
|
44058
|
+
var DESCRIPTION26 = `
|
|
44059
|
+
\u67E5\u770B\u5F53\u524D Department Head \u6240\u5C5E\u90E8\u95E8\u7684\u6210\u5458\u76EE\u5F55\u3002
|
|
44060
|
+
|
|
44061
|
+
\u4F7F\u7528\u8FB9\u754C\uFF1A
|
|
44062
|
+
- \u4EC5 Department Head \u53EF\u4EE5\u4F7F\u7528\u3002
|
|
44063
|
+
- CEO \u9ED8\u8BA4\u901A\u8FC7 department_list \u53EA\u770B\u5230\u90E8\u95E8\u4E0E\u8D1F\u8D23\u4EBA\u6458\u8981\u3002
|
|
44064
|
+
- Department Head \u53EA\u80FD\u67E5\u770B\u81EA\u5DF1\u6240\u5C5E\u90E8\u95E8\u7684\u6210\u5458\uFF0C\u7528\u4E8E\u590D\u7528\u5DF2\u6709\u6210\u5458\u3001\u5224\u65AD\u662F\u5426\u9700\u8981\u521B\u5EFA\u65B0\u6210\u5458\u3001\u4E86\u89E3\u6210\u5458\u804C\u8D23\u3002
|
|
44065
|
+
`;
|
|
44066
|
+
var departmentMemberList = {
|
|
44067
|
+
name: `department_member_list`,
|
|
44068
|
+
description: DESCRIPTION26,
|
|
44069
|
+
input_schema: {
|
|
44070
|
+
type: `object`,
|
|
44071
|
+
properties: {},
|
|
44072
|
+
required: []
|
|
44073
|
+
},
|
|
44074
|
+
async execute(input, userRequest) {
|
|
44075
|
+
const mailboxId = userRequest?.departmentAgentId;
|
|
44076
|
+
if (!mailboxId) {
|
|
44077
|
+
return `[departmentMemberList] \u53EA\u6709 Department Head \u53EF\u4EE5\u67E5\u770B\u90E8\u95E8\u6210\u5458\u76EE\u5F55`;
|
|
44078
|
+
}
|
|
44079
|
+
const currentMember = getDepartmentMemberByMailboxId(mailboxId);
|
|
44080
|
+
if (!currentMember) {
|
|
44081
|
+
return `[departmentMemberList] \u65E0\u6CD5\u8BC6\u522B\u5F53\u524D\u90E8\u95E8\u6210\u5458: ${mailboxId}`;
|
|
44082
|
+
}
|
|
44083
|
+
if (currentMember.role !== "department_head") {
|
|
44084
|
+
return `[departmentMemberList] \u5F53\u524D\u6210\u5458\u4E0D\u662F Department Head\uFF0C\u4E0D\u80FD\u67E5\u770B\u5B8C\u6574\u90E8\u95E8\u6210\u5458\u76EE\u5F55`;
|
|
44085
|
+
}
|
|
44086
|
+
const department = getDepartmentById(currentMember.departmentId);
|
|
44087
|
+
if (!department) {
|
|
44088
|
+
return `[departmentMemberList] \u627E\u4E0D\u5230\u5F53\u524D\u6210\u5458\u6240\u5C5E\u90E8\u95E8: ${currentMember.departmentId}`;
|
|
44089
|
+
}
|
|
44090
|
+
const members = department.departmentMembers.map((member) => ({
|
|
44091
|
+
id: member.id,
|
|
44092
|
+
name: member.name,
|
|
44093
|
+
role: member.role ?? "executor",
|
|
44094
|
+
mailBoxId: member.mailBoxId,
|
|
44095
|
+
workspaceId: member.workspaceId,
|
|
44096
|
+
focusOn: member.focusOn
|
|
44097
|
+
}));
|
|
44098
|
+
return `[departmentMemberList] ${department.name} \u90E8\u95E8\u6210\u5458\u76EE\u5F55: ${JSON.stringify(members)}`;
|
|
44099
|
+
}
|
|
44127
44100
|
};
|
|
44128
|
-
|
|
44129
|
-
|
|
44130
|
-
|
|
44131
|
-
|
|
44132
|
-
|
|
44133
|
-
|
|
44134
|
-
|
|
44135
|
-
|
|
44136
|
-
|
|
44137
|
-
|
|
44138
|
-
|
|
44139
|
-
|
|
44140
|
-
|
|
44141
|
-
|
|
44142
|
-
|
|
44143
|
-
|
|
44144
|
-
|
|
44145
|
-
|
|
44146
|
-
|
|
44147
|
-
|
|
44101
|
+
|
|
44102
|
+
// src/tools/tools/department/CheckDepartmentReplies.ts
|
|
44103
|
+
var DESCRIPTION27 = `
|
|
44104
|
+
\u67E5\u770B Department Head \u6216\u90E8\u95E8\u6210\u5458\u53D1\u7ED9 CEO \u7684\u5DE5\u4F5C\u56DE\u590D\u3002
|
|
44105
|
+
|
|
44106
|
+
\u5F53 CEO \u5411 Department Head \u6D3E\u53D1\u4EFB\u52A1\u540E\uFF0C\u5BF9\u65B9\u5B8C\u6210\u5DE5\u4F5C\u4F1A\u901A\u8FC7 mailbox \u56DE\u4FE1\u3002\u4F7F\u7528\u6B64\u5DE5\u5177\u53EF\u4EE5\u67E5\u770B\u672A\u8BFB\u7684\u90E8\u95E8\u56DE\u4FE1\u5185\u5BB9\uFF0C\u4E86\u89E3\u5DE5\u4F5C\u8FDB\u5C55\u548C\u6210\u679C\u3002
|
|
44107
|
+
`;
|
|
44108
|
+
var checkDepartmentReplies = {
|
|
44109
|
+
name: `check_department_replies`,
|
|
44110
|
+
description: DESCRIPTION27,
|
|
44111
|
+
input_schema: {
|
|
44112
|
+
type: `object`,
|
|
44113
|
+
properties: {
|
|
44114
|
+
from_member: {
|
|
44115
|
+
type: `string`,
|
|
44116
|
+
description: `\u53EF\u9009\uFF1A\u53EA\u67E5\u770B\u6307\u5B9A mailboxId \u7684\u56DE\u4FE1\uFF0C\u4E0D\u586B\u5219\u67E5\u770B\u6240\u6709\u56DE\u4FE1`
|
|
44117
|
+
}
|
|
44118
|
+
},
|
|
44119
|
+
required: []
|
|
44120
|
+
},
|
|
44121
|
+
async execute(input) {
|
|
44122
|
+
const db3 = createSqliteDB();
|
|
44123
|
+
const fromMember = input.from_member;
|
|
44124
|
+
let msgs;
|
|
44125
|
+
if (fromMember) {
|
|
44126
|
+
const stmt = db3.prepare(
|
|
44127
|
+
`SELECT id, to_mailbox_id as toMailboxId, from_mailbox_id as fromMailboxId, content, send_time as sendTime, status
|
|
44128
|
+
FROM mailbox
|
|
44129
|
+
WHERE to_mailbox_id = 'manager' AND from_mailbox_id = ? AND status in ('pending', 'processing')
|
|
44130
|
+
ORDER BY send_time ASC`
|
|
44131
|
+
);
|
|
44132
|
+
msgs = stmt.all(fromMember);
|
|
44133
|
+
} else {
|
|
44134
|
+
const stmt = db3.prepare(
|
|
44135
|
+
`SELECT id, to_mailbox_id as toMailboxId, from_mailbox_id as fromMailboxId, content, send_time as sendTime, status
|
|
44136
|
+
FROM mailbox
|
|
44137
|
+
WHERE to_mailbox_id = 'manager' AND status in ('pending', 'processing')
|
|
44138
|
+
ORDER BY send_time ASC`
|
|
44139
|
+
);
|
|
44140
|
+
msgs = stmt.all();
|
|
44141
|
+
}
|
|
44142
|
+
if (msgs.length === 0) {
|
|
44143
|
+
return [
|
|
44144
|
+
`[checkDepartmentReplies] \u56E2\u961F\u8FD9\u4F1A\u513F\u8FD8\u6CA1\u56DE\u4FE1\uFF0C\u591A\u534A\u662F\u8D1F\u8D23\u4EBA\u4ECD\u5728\u5904\u7406\uFF0C\u8FC7\u4F1A\u513F\u518D\u6765\u770B\u3002`,
|
|
44145
|
+
``,
|
|
44146
|
+
`\u51E0\u53E5\u63D0\u9192\uFF1A`,
|
|
44147
|
+
`- \u8FD9\u4E0D\u4EE3\u8868\u8981\u4F60\u4EB2\u81EA\u4E0B\u573A read/bash/\u6D4B\u8BD5/\u6539\u4EE3\u7801\u2014\u2014\u56E2\u961F\u6CA1\u56DE\uFF0C\u4E0D\u662F\u4F60\u8BE5\u63A5\u624B\u7684\u4FE1\u53F7\u3002`,
|
|
44148
|
+
`- \u8001\u677F\u8981\u662F\u6B63\u7B49\u7740\uFF0C\u5148\u7528 send_message \u5982\u5B9E\u8DDF\u4ED6\u8BF4\u4E00\u53E5\u201C\u8D1F\u8D23\u4EBA\u8FD8\u5728\u5904\u7406\uFF0C\u6211\u62FF\u5230\u7ED3\u679C\u5C31\u540C\u6B65\u201D\u3002`,
|
|
44149
|
+
`- \u5982\u679C\u4EFB\u52A1\u521A\u6D3E\u51FA\u53BB\uFF0C\u4E0D\u8981\u5728\u540C\u4E00\u8F6E\u9A6C\u4E0A\u50AC\u529E\uFF1B\u7ED9\u8D1F\u8D23\u4EBA\u5408\u7406\u5904\u7406\u65F6\u95F4\u3002`,
|
|
44150
|
+
`- \u5DF2\u7ECF\u7B49\u4E86\u4E00\u9635\u3001\u8001\u677F\u53C8\u8FFD\u95EE\uFF0C\u6216\u53D1\u73B0\u660E\u786E\u98CE\u9669\u65F6\uFF0C\u518D\u7528 mailbox_followup \u6216 department_communicate \u53BB\u95EE\u5BF9\u5E94 Department Head \u771F\u5B9E\u8FDB\u5C55\u3001\u5361\u5728\u54EA\u3001\u5927\u6982\u4EC0\u4E48\u65F6\u5019\u597D\u3002`,
|
|
44151
|
+
`- \u522B\u5728\u8FD9\u4E00\u8F6E\u91CC\u53CD\u590D\u7A7A\u67E5 check_department_replies\uFF1B\u7B49\u56E2\u961F\u56DE\u4FE1\u3001\u8001\u677F\u8FFD\u95EE\u6216\u50AC\u529E\u6709\u4E86\u56DE\u97F3\uFF0C\u518D\u6765\u770B\u3002`
|
|
44152
|
+
].join("\n");
|
|
44153
|
+
}
|
|
44154
|
+
const updateStmt = db3.prepare(`UPDATE mailbox SET status = 'read' WHERE id = ?`);
|
|
44155
|
+
for (const msg of msgs) {
|
|
44156
|
+
updateStmt.run(msg.id);
|
|
44157
|
+
}
|
|
44158
|
+
const replies = msgs.map((msg, i) => {
|
|
44159
|
+
const time = new Date(msg.sendTime).toLocaleString("zh-CN", { timeZone: "Asia/Shanghai" });
|
|
44160
|
+
return `--- \u56DE\u4FE1 ${i + 1} ---
|
|
44161
|
+
id: ${msg.id}
|
|
44162
|
+
\u6765\u81EA: ${msg.fromMailboxId}
|
|
44163
|
+
\u65F6\u95F4: ${time}
|
|
44164
|
+
\u72B6\u6001: ${msg.status}
|
|
44165
|
+
\u5185\u5BB9:
|
|
44166
|
+
${msg.content}`;
|
|
44167
|
+
}).join("\n\n");
|
|
44168
|
+
return `[checkDepartmentReplies] \u6536\u5230 ${msgs.length} \u6761\u90E8\u95E8\u56DE\u4FE1\uFF1A
|
|
44169
|
+
|
|
44170
|
+
${replies}`;
|
|
44171
|
+
}
|
|
44148
44172
|
};
|
|
44149
44173
|
|
|
44150
44174
|
// src/tools/tools/department/DepartmentLearning.ts
|
|
@@ -44569,6 +44593,34 @@ function validateProtectedRuntimeCommand(command) {
|
|
|
44569
44593
|
}
|
|
44570
44594
|
return null;
|
|
44571
44595
|
}
|
|
44596
|
+
function listProtectedRuntimeProcesses() {
|
|
44597
|
+
try {
|
|
44598
|
+
const output = (0, import_node_child_process.execFileSync)("ps", ["-eo", "pid=,ppid=,args="], { encoding: "utf8" });
|
|
44599
|
+
const currentPid = process.pid;
|
|
44600
|
+
return output.split("\n").map((line) => line.trim().match(/^(\d+)\s+(\d+)\s+(.*)$/)).filter((match2) => Boolean(match2)).map((match2) => ({
|
|
44601
|
+
pid: Number(match2[1]),
|
|
44602
|
+
command: match2[3] ?? ""
|
|
44603
|
+
})).filter(
|
|
44604
|
+
(processInfo) => Number.isFinite(processInfo.pid) && processInfo.pid !== currentPid && (processInfo.command.includes("duclaw-cli start") || processInfo.command.includes("duclaw-worker"))
|
|
44605
|
+
).map(({ pid, command }) => ({ pid, command }));
|
|
44606
|
+
} catch {
|
|
44607
|
+
return [];
|
|
44608
|
+
}
|
|
44609
|
+
}
|
|
44610
|
+
function validateProtectedRuntimePidCommand(command) {
|
|
44611
|
+
if (!/\bkill\b/.test(command)) return null;
|
|
44612
|
+
const protectedProcesses = listProtectedRuntimeProcesses();
|
|
44613
|
+
for (const protectedProcess of protectedProcesses) {
|
|
44614
|
+
const pidRef = new RegExp(`(^|[^\\d])${protectedProcess.pid}([^\\d]|$)`);
|
|
44615
|
+
if (!pidRef.test(command)) continue;
|
|
44616
|
+
return [
|
|
44617
|
+
`[bash] \u62D2\u7EDD\u6267\u884C: \u547D\u4EE4\u8BD5\u56FE\u7EC8\u6B62 Duclaw runtime \u8FDB\u7A0B PID ${protectedProcess.pid}\u3002`,
|
|
44618
|
+
`\u5339\u914D\u8FDB\u7A0B: ${protectedProcess.command}`,
|
|
44619
|
+
`\u8BF7\u53EA\u7EC8\u6B62\u660E\u786E\u5C5E\u4E8E\u5F53\u524D\u9879\u76EE\u7684\u5F00\u53D1\u670D\u52A1 PID\uFF0C\u4E0D\u8981\u6740 duclaw-cli start \u6216 duclaw-worker\u3002`
|
|
44620
|
+
].join("\n");
|
|
44621
|
+
}
|
|
44622
|
+
return null;
|
|
44623
|
+
}
|
|
44572
44624
|
function truncateOutput(output, limit = MAX_OUTPUT_LENGTH) {
|
|
44573
44625
|
if (output.length <= limit) return output;
|
|
44574
44626
|
return output.slice(0, limit) + `
|
|
@@ -44692,6 +44744,8 @@ var bashTool = {
|
|
|
44692
44744
|
}
|
|
44693
44745
|
const protectedCommandError = validateProtectedRuntimeCommand(command);
|
|
44694
44746
|
if (protectedCommandError) return protectedCommandError;
|
|
44747
|
+
const protectedRuntimePidError = validateProtectedRuntimePidCommand(command);
|
|
44748
|
+
if (protectedRuntimePidError) return protectedRuntimePidError;
|
|
44695
44749
|
if (userRequest?.workspacePath && explicitCwd) {
|
|
44696
44750
|
const rejection = validateWorkspacePath(explicitCwd, userRequest.workspacePath);
|
|
44697
44751
|
if (rejection) return `[bash] ${rejection}`;
|
|
@@ -53500,7 +53554,13 @@ toolRoutes.get("/tools", (c) => {
|
|
|
53500
53554
|
toolRoutes.get("/skills", (c) => {
|
|
53501
53555
|
try {
|
|
53502
53556
|
const skills = SkillRegistry_default();
|
|
53503
|
-
return c.json(skills.map((s) => ({
|
|
53557
|
+
return c.json(skills.map((s) => ({
|
|
53558
|
+
name: s.name,
|
|
53559
|
+
description: s.description,
|
|
53560
|
+
deletable: !!s.deletable,
|
|
53561
|
+
scope: s.scope ?? (s.deletable ? "project" : "global"),
|
|
53562
|
+
departmentName: s.departmentName
|
|
53563
|
+
})));
|
|
53504
53564
|
} catch (err) {
|
|
53505
53565
|
return c.json({ error: err.message || "Failed to list skills" }, 500);
|
|
53506
53566
|
}
|
|
@@ -53515,6 +53575,8 @@ toolRoutes.get("/skills/:name", (c) => {
|
|
|
53515
53575
|
name: skill.name,
|
|
53516
53576
|
description: skill.description,
|
|
53517
53577
|
deletable: !!skill.deletable,
|
|
53578
|
+
scope: skill.scope ?? (skill.deletable ? "project" : "global"),
|
|
53579
|
+
departmentName: skill.departmentName,
|
|
53518
53580
|
detail: skill.getDetail()
|
|
53519
53581
|
});
|
|
53520
53582
|
} catch (err) {
|
|
@@ -53537,7 +53599,7 @@ var systemRoutes = new Hono2();
|
|
|
53537
53599
|
var startTime = Date.now();
|
|
53538
53600
|
systemRoutes.get("/system/info", (c) => {
|
|
53539
53601
|
return c.json({
|
|
53540
|
-
version: true ? "1.9.
|
|
53602
|
+
version: true ? "1.9.9" : "unknown",
|
|
53541
53603
|
uptime: Math.floor((Date.now() - startTime) / 1e3),
|
|
53542
53604
|
env: process.env.NODE_ENV || "development",
|
|
53543
53605
|
nodeVersion: process.version
|