mulmoclaude 2.1.0 → 2.2.1
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/README.md +1 -1
- package/client/assets/JsonEditor-BC9ITErx.js +10 -0
- package/client/assets/{index-k-aOQrSm.js → index-168151sv.js} +368 -368
- package/client/assets/{marp-12IgaShm.js → marp-BvWwTP5d.js} +1 -1
- package/client/index.html +1 -1
- package/package.json +5 -5
- package/server/agent/activeTools.ts +9 -5
- package/server/agent/backend/claude-code.ts +3 -0
- package/server/agent/backend/types.ts +3 -0
- package/server/agent/config.ts +11 -1
- package/server/agent/dispatchableMcpTool.ts +19 -0
- package/server/agent/index.ts +2 -1
- package/server/agent/mcp-server.ts +7 -5
- package/server/agent/skillListing.ts +34 -0
- package/server/agent/skillListingState.ts +40 -0
- package/server/api/routes/config.ts +5 -0
- package/server/api/routes/roles.ts +1 -0
- package/server/build/mcp-server.mjs +491 -491
- package/server/prompts/system/memory-management-atomic.md +1 -27
- package/server/prompts/system/memory-management-topic.md +4 -53
- package/server/prompts/system/system.md +2 -5
- package/server/system/config.ts +25 -3
- package/server/workspace/journal/archivist-schemas.ts +3 -2
- package/server/workspace/journal/htmlBlock.ts +41 -0
- package/server/workspace/journal/replaceIfUnchanged.ts +10 -0
- package/server/workspace/journal/sessionLinkRepair.ts +244 -0
- package/src/components/SettingsModelTab.vue +58 -1
- package/src/config/roles.ts +6 -1
- package/src/lang/de.ts +6 -0
- package/src/lang/en.ts +6 -0
- package/src/lang/es.ts +6 -0
- package/src/lang/fr.ts +6 -0
- package/src/lang/ja.ts +6 -0
- package/src/lang/ko.ts +6 -0
- package/src/lang/pt-BR.ts +6 -0
- package/src/lang/zh.ts +6 -0
- package/src/plugins/manageRoles/definition.ts +6 -0
- package/src/plugins/manageRoles/index.ts +3 -0
- package/src/plugins/manageRoles/roleForm.ts +8 -2
- package/src/plugins/manageSkills/definition.ts +1 -1
- package/src/utils/path/workspaceLinkRouter.ts +5 -6
- package/client/assets/JsonEditor-zdl4EA3_.js +0 -10
- package/server/system/logs/aaa +0 -737
- package/server/system/logs/bb +0 -446
package/src/lang/en.ts
CHANGED
|
@@ -406,6 +406,12 @@ const enMessages = {
|
|
|
406
406
|
helperText: "Higher levels allow more thinking time but increase latency and token usage.",
|
|
407
407
|
configured: "Effort: {level}",
|
|
408
408
|
notConfigured: "Not set",
|
|
409
|
+
userSettingsLabel: "Load Claude Code's user settings and plugins",
|
|
410
|
+
userSettingsHint:
|
|
411
|
+
"Reads skills, plugins and hooks from ~/.claude, the same ones Claude Code uses. Turn this off if your installed plugins carry so many skills that every request gets heavy; the workspace's own skills keep working. Takes effect from the next message. When off, an unset model no longer follows ~/.claude/settings.json either.",
|
|
412
|
+
skillListingSummary: "Skills listed on the last turn: {count}.",
|
|
413
|
+
skillListingPlugins: "From plugins: {plugins}.",
|
|
414
|
+
skillListingHeavy: "That many skills make every request heavy; turning this off drops the ones from ~/.claude.",
|
|
409
415
|
loadError: "Failed to load settings",
|
|
410
416
|
saveError: "Failed to save",
|
|
411
417
|
},
|
package/src/lang/es.ts
CHANGED
|
@@ -390,6 +390,12 @@ const esMessages = {
|
|
|
390
390
|
helperText: "Niveles más altos permiten más tiempo de pensamiento pero aumentan la latencia y el uso de tokens.",
|
|
391
391
|
configured: "Esfuerzo: {level}",
|
|
392
392
|
notConfigured: "Sin configurar",
|
|
393
|
+
userSettingsLabel: "Cargar los ajustes de usuario y los plugins de Claude Code",
|
|
394
|
+
userSettingsHint:
|
|
395
|
+
"Lee las skills, los plugins y los hooks de ~/.claude, los mismos que usa Claude Code. Desactívalo si los plugins instalados traen tantas skills que cada petición se vuelve pesada; las skills del propio espacio de trabajo siguen funcionando. Se aplica desde el siguiente mensaje. Si está desactivado, un modelo sin configurar ya no sigue ~/.claude/settings.json.",
|
|
396
|
+
skillListingSummary: "Skills cargadas en el último turno: {count}.",
|
|
397
|
+
skillListingPlugins: "De los plugins: {plugins}.",
|
|
398
|
+
skillListingHeavy: "Con tantas skills cada petición pesa más; al desactivarlo se quitan las de ~/.claude.",
|
|
393
399
|
loadError: "Error al cargar los ajustes",
|
|
394
400
|
saveError: "Error al guardar",
|
|
395
401
|
},
|
package/src/lang/fr.ts
CHANGED
|
@@ -386,6 +386,12 @@ const frMessages = {
|
|
|
386
386
|
helperText: "Les niveaux plus élevés autorisent plus de temps de réflexion mais augmentent la latence et la consommation de tokens.",
|
|
387
387
|
configured: "Effort : {level}",
|
|
388
388
|
notConfigured: "Non défini",
|
|
389
|
+
userSettingsLabel: "Charger les réglages utilisateur et les plugins de Claude Code",
|
|
390
|
+
userSettingsHint:
|
|
391
|
+
"Lit les skills, plugins et hooks de ~/.claude, les mêmes que ceux de Claude Code. Désactivez-le si les plugins installés apportent tant de skills que chaque requête devient lourde ; les skills de l'espace de travail restent disponibles. Prend effet à partir du message suivant. Désactivé, un modèle non défini ne suit plus non plus ~/.claude/settings.json.",
|
|
392
|
+
skillListingSummary: "Skills chargées au dernier tour : {count}.",
|
|
393
|
+
skillListingPlugins: "Depuis les plugins : {plugins}.",
|
|
394
|
+
skillListingHeavy: "Autant de skills alourdissent chaque requête ; le désactiver retire celles de ~/.claude.",
|
|
389
395
|
loadError: "Échec du chargement des paramètres",
|
|
390
396
|
saveError: "Échec de l'enregistrement",
|
|
391
397
|
},
|
package/src/lang/ja.ts
CHANGED
|
@@ -385,6 +385,12 @@ const jaMessages = {
|
|
|
385
385
|
helperText: "高いレベルほど思考時間が長くなりますが、レイテンシとトークン消費も増えます。",
|
|
386
386
|
configured: "Effort: {level}",
|
|
387
387
|
notConfigured: "未設定",
|
|
388
|
+
userSettingsLabel: "Claude Code のユーザー設定とプラグインを読み込む",
|
|
389
|
+
userSettingsHint:
|
|
390
|
+
"~/.claude にある、Claude Code と共通のスキル・プラグイン・フックを読み込みます。インストールしたプラグインのスキルが多く、毎回の依頼が重くなるときはオフにしてください。ワークスペースのスキルはそのまま使えます。次のメッセージから反映されます。オフのときは、モデルが未設定でも ~/.claude/settings.json のモデル指定は使われません。",
|
|
391
|
+
skillListingSummary: "前回のターンで読み込まれたスキル: {count} 個。",
|
|
392
|
+
skillListingPlugins: "プラグイン: {plugins}。",
|
|
393
|
+
skillListingHeavy: "スキルが多いため、毎回の依頼が重くなっています。オフにすると ~/.claude の分が外れます。",
|
|
388
394
|
loadError: "設定の読み込みに失敗しました",
|
|
389
395
|
saveError: "保存に失敗しました",
|
|
390
396
|
},
|
package/src/lang/ko.ts
CHANGED
|
@@ -385,6 +385,12 @@ const koMessages = {
|
|
|
385
385
|
helperText: "레벨이 높을수록 사고 시간이 늘어나지만 지연 시간과 토큰 사용량도 증가합니다.",
|
|
386
386
|
configured: "Effort: {level}",
|
|
387
387
|
notConfigured: "미설정",
|
|
388
|
+
userSettingsLabel: "Claude Code 사용자 설정과 플러그인 불러오기",
|
|
389
|
+
userSettingsHint:
|
|
390
|
+
"~/.claude에 있는, Claude Code와 공유하는 스킬·플러그인·훅을 불러옵니다. 설치한 플러그인의 스킬이 너무 많아 요청마다 무거워진다면 끄세요. 워크스페이스 자체 스킬은 그대로 사용할 수 있습니다. 다음 메시지부터 적용됩니다. 끄면 모델이 미설정이어도 ~/.claude/settings.json의 모델 지정을 따르지 않습니다.",
|
|
391
|
+
skillListingSummary: "지난 턴에 불러온 스킬: {count}개.",
|
|
392
|
+
skillListingPlugins: "플러그인: {plugins}.",
|
|
393
|
+
skillListingHeavy: "스킬이 많아 요청마다 무거워지고 있습니다. 끄면 ~/.claude의 스킬이 빠집니다.",
|
|
388
394
|
loadError: "설정을 불러오지 못했습니다",
|
|
389
395
|
saveError: "저장에 실패했습니다",
|
|
390
396
|
},
|
package/src/lang/pt-BR.ts
CHANGED
|
@@ -384,6 +384,12 @@ const ptBRMessages = {
|
|
|
384
384
|
helperText: "Níveis mais altos permitem mais tempo de pensamento mas aumentam latência e uso de tokens.",
|
|
385
385
|
configured: "Esforço: {level}",
|
|
386
386
|
notConfigured: "Sem configurar",
|
|
387
|
+
userSettingsLabel: "Carregar as configurações de usuário e os plugins do Claude Code",
|
|
388
|
+
userSettingsHint:
|
|
389
|
+
"Lê as skills, os plugins e os hooks de ~/.claude, os mesmos que o Claude Code usa. Desative se os plugins instalados trazem tantas skills que toda solicitação fica pesada; as skills do próprio workspace continuam funcionando. Vale a partir da próxima mensagem. Desativado, um modelo não definido também deixa de seguir ~/.claude/settings.json.",
|
|
390
|
+
skillListingSummary: "Skills carregadas no último turno: {count}.",
|
|
391
|
+
skillListingPlugins: "Dos plugins: {plugins}.",
|
|
392
|
+
skillListingHeavy: "Com tantas skills toda solicitação fica pesada; ao desativar, as de ~/.claude saem.",
|
|
387
393
|
loadError: "Falha ao carregar as configurações",
|
|
388
394
|
saveError: "Falha ao salvar",
|
|
389
395
|
},
|
package/src/lang/zh.ts
CHANGED
|
@@ -375,6 +375,12 @@ const zhMessages = {
|
|
|
375
375
|
helperText: "更高的等级会带来更多思考时间,但也会增加延迟和 token 消耗。",
|
|
376
376
|
configured: "推理强度:{level}",
|
|
377
377
|
notConfigured: "未设置",
|
|
378
|
+
userSettingsLabel: "加载 Claude Code 的用户设置和插件",
|
|
379
|
+
userSettingsHint:
|
|
380
|
+
"读取 ~/.claude 中与 Claude Code 共用的技能、插件和钩子。如果已安装插件的技能太多、导致每次请求都很重,请关闭此项;工作区自己的技能仍可使用。从下一条消息开始生效。关闭时,即使未设置模型,也不会再使用 ~/.claude/settings.json 中的模型。",
|
|
381
|
+
skillListingSummary: "上一轮加载的技能:{count} 个。",
|
|
382
|
+
skillListingPlugins: "来自插件:{plugins}。",
|
|
383
|
+
skillListingHeavy: "技能太多会让每次请求都变重;关闭此项可去掉来自 ~/.claude 的技能。",
|
|
378
384
|
loadError: "加载设置失败",
|
|
379
385
|
saveError: "保存失败",
|
|
380
386
|
},
|
|
@@ -45,6 +45,12 @@ const toolDefinition: ToolDefinition = {
|
|
|
45
45
|
description:
|
|
46
46
|
"Optional model family for this role's sessions — one of the aliases offered in Settings \u2192 Model. Omit it to follow the app-wide choice. A value that is not a known alias is ignored. ALWAYS echo back the role's existing value when updating a role, or the setting is lost.",
|
|
47
47
|
},
|
|
48
|
+
excludedAlwaysActiveTools: {
|
|
49
|
+
type: "array",
|
|
50
|
+
items: { type: "string" },
|
|
51
|
+
description:
|
|
52
|
+
"Optional names of always-active tools (offered to every role regardless of availablePlugins) that this role opts out of. ALWAYS echo back the role's existing value when updating a role, or the setting is lost.",
|
|
53
|
+
},
|
|
48
54
|
},
|
|
49
55
|
required: ["id", "name", "icon", "prompt", "availablePlugins"],
|
|
50
56
|
},
|
|
@@ -18,6 +18,9 @@ export interface CustomRole {
|
|
|
18
18
|
* Must survive every edit path — the reason this is a declared field at all
|
|
19
19
|
* is that the role object is rebuilt field by field in several places. */
|
|
20
20
|
model?: string;
|
|
21
|
+
/** Always-active tools this role opts out of. No editor in the form, so it
|
|
22
|
+
* is carried through every edit path the same way `model` is. */
|
|
23
|
+
excludedAlwaysActiveTools?: string[];
|
|
21
24
|
}
|
|
22
25
|
|
|
23
26
|
export interface ManageRolesData {
|
|
@@ -17,13 +17,14 @@ const ROLE_ID_PATTERN = /^[a-zA-Z0-9_-]+$/;
|
|
|
17
17
|
// the DOM, so a missing field has to fail here, not in a template.
|
|
18
18
|
const parseCustomRole = (value: unknown): CustomRole | null => {
|
|
19
19
|
if (!isRecord(value)) return null;
|
|
20
|
-
const { id, name, icon, prompt, availablePlugins, queries, model } = value;
|
|
20
|
+
const { id, name, icon, prompt, availablePlugins, queries, model, excludedAlwaysActiveTools } = value;
|
|
21
21
|
if (typeof id !== "string" || typeof name !== "string" || typeof icon !== "string" || typeof prompt !== "string") return null;
|
|
22
22
|
if (!isStringArray(availablePlugins)) return null;
|
|
23
23
|
const base: CustomRole = { id, name, icon, prompt, availablePlugins };
|
|
24
24
|
// A non-string model is dropped, not fatal: a malformed field should cost
|
|
25
25
|
// that field, not make the whole role vanish from the list.
|
|
26
|
-
const
|
|
26
|
+
const withModel: CustomRole = isStoredModel(model) ? { ...base, model } : base;
|
|
27
|
+
const role: CustomRole = isStringArray(excludedAlwaysActiveTools) ? { ...withModel, excludedAlwaysActiveTools } : withModel;
|
|
27
28
|
return isStringArray(queries) ? { ...role, queries } : role;
|
|
28
29
|
};
|
|
29
30
|
|
|
@@ -54,6 +55,8 @@ export interface RoleForm {
|
|
|
54
55
|
queriesText: string;
|
|
55
56
|
/** `""` is "not set" — the app-wide setting decides. */
|
|
56
57
|
model: string;
|
|
58
|
+
/** Not editable in the form; carried so saving an edit does not drop it. */
|
|
59
|
+
excludedAlwaysActiveTools: string[];
|
|
57
60
|
}
|
|
58
61
|
|
|
59
62
|
export type RoleFormErrorCode = "idRequired" | "idInvalid" | "nameRequired" | "idDuplicate";
|
|
@@ -87,6 +90,7 @@ export const formToRole = (form: RoleForm): CustomRole => ({
|
|
|
87
90
|
// Omitted rather than set to "" when unset: the role file should carry no
|
|
88
91
|
// key at all, so `role.model ?? settings.chatModel` falls through cleanly.
|
|
89
92
|
...(form.model ? { model: form.model } : {}),
|
|
93
|
+
...(form.excludedAlwaysActiveTools.length > 0 ? { excludedAlwaysActiveTools: form.excludedAlwaysActiveTools } : {}),
|
|
90
94
|
});
|
|
91
95
|
|
|
92
96
|
/** A blank form. One factory so a field added to `RoleForm` cannot be
|
|
@@ -107,6 +111,7 @@ export const emptyRoleForm = (): RoleForm => ({
|
|
|
107
111
|
selectedPlugins: [],
|
|
108
112
|
queriesText: "",
|
|
109
113
|
model: "",
|
|
114
|
+
excludedAlwaysActiveTools: [],
|
|
110
115
|
});
|
|
111
116
|
|
|
112
117
|
export const roleToForm = (role: CustomRole): RoleForm => ({
|
|
@@ -117,6 +122,7 @@ export const roleToForm = (role: CustomRole): RoleForm => ({
|
|
|
117
122
|
selectedPlugins: [...role.availablePlugins],
|
|
118
123
|
queriesText: (role.queries ?? []).join("\n"),
|
|
119
124
|
model: role.model ?? "",
|
|
125
|
+
excludedAlwaysActiveTools: [...(role.excludedAlwaysActiveTools ?? [])],
|
|
120
126
|
});
|
|
121
127
|
|
|
122
128
|
// `excludeId` lets rename skip the role's own id when checking for duplicates.
|
|
@@ -14,7 +14,7 @@ const toolDefinition: ToolDefinition = {
|
|
|
14
14
|
`Use the ${TOOL_NAME} tool for the user's skill library:\n\n` +
|
|
15
15
|
`- **list** (default, no args): show every available skill in the canvas.\n` +
|
|
16
16
|
`- **save**: when the user asks to turn the current conversation into a skill (e.g. "skill 化して" / "save this as a skill"), do these steps:\n` +
|
|
17
|
-
` 1. Read the current chat transcript via the Read tool. The path is \`chat/<session-id>.jsonl\` under the workspace; if you don't know the session id, list \`chat/\` first.\n` +
|
|
17
|
+
` 1. Read the current chat transcript via the Read tool. The path is \`conversations/chat/<session-id>.jsonl\` under the workspace; if you don't know the session id, list \`conversations/chat/\` first.\n` +
|
|
18
18
|
` 2. Distill the conversation into a short markdown body explaining the steps you took, in second person ("First, do X. Then, do Y."). Keep it focused on the reusable workflow, not the one-off details.\n` +
|
|
19
19
|
` 3. Pick a kebab-case slug (lowercase letters, digits, hyphens; no leading/trailing hyphen; 1-64 chars). If the user gave a name in the request, use it.\n` +
|
|
20
20
|
` 4. Write a one-line description for the YAML frontmatter.\n` +
|
|
@@ -90,12 +90,11 @@ export function classifyWorkspacePath(href: string): WorkspaceLinkTarget | null
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
// Chat session log: conversations/chat/<id>.jsonl
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
93
|
+
// Summaries written before the prompt used `conversations/chat/` carry `chat/<id>.jsonl`, which only exists on legacy layouts, so accept both.
|
|
94
|
+
const chatPath = normalized.startsWith(CHAT_LOG_PREFIX) ? normalized.slice(CHAT_LOG_PREFIX.length) : normalized;
|
|
95
|
+
const sessionId = extractSessionIdFromPath(chatPath);
|
|
96
|
+
if (sessionId) {
|
|
97
|
+
return { kind: "session", sessionId };
|
|
99
98
|
}
|
|
100
99
|
|
|
101
100
|
// Top-level SPA route: leading segment names one of the host's
|