mulmoclaude 0.6.2 → 0.6.4
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 +26 -0
- package/bin/mulmoclaude.js +11 -1
- package/client/assets/JsonEditor-D6WBWLoa.js +10 -0
- package/client/assets/JsonEditor-Di5xGeZY.css +1 -0
- package/client/assets/_plugin-vue_export-helper-BOai-rQB.js +1 -0
- package/client/assets/chunk-D8eiyYIV-LcKZGJv5.js +1 -0
- package/client/assets/{html2canvas-CDGcmOD3-Bkf2uOth.js → html2canvas-CDGcmOD3-XVrO-eyz.js} +1 -1
- package/client/assets/index-CyBr8Mkr.css +2 -0
- package/client/assets/index-zZIqEbNX.js +5106 -0
- package/client/assets/{index.es-DqtpmBm8-D9mAh_KQ.js → index.es-DqtpmBm8-DHT6q10o.js} +1 -1
- package/client/assets/material-symbols-outlined-DtIK7AQn.woff2 +0 -0
- package/client/assets/runtime-protocol-vue-D6kcV0wa.js +1 -0
- package/client/assets/{runtime-vue-BVUzgYGA.js → runtime-vue-fFYhnNg3.js} +1 -1
- package/client/assets/{vue-C8UuIO9J.js → vue-D4w8THF_.js} +1 -1
- package/client/assets/vue-i18n-CQbxVmNs.js +3 -0
- package/client/assets/vue.runtime.esm-bundler-BTyIdNAI.js +4 -0
- package/client/index.html +10 -10
- package/package.json +9 -8
- package/server/agent/backend/claude-code.ts +34 -0
- package/server/agent/backend/fake-echo.ts +370 -0
- package/server/agent/backend/index.ts +16 -1
- package/server/agent/config.ts +74 -24
- package/server/agent/index.ts +104 -80
- package/server/agent/mcpFailureMonitor.ts +167 -0
- package/server/agent/mcpPreflight.ts +185 -0
- package/server/agent/prompt.ts +50 -359
- package/server/agent/stdioHttpShim.ts +171 -0
- package/server/agent/stream.ts +12 -1
- package/server/api/routes/encore.ts +55 -0
- package/server/api/routes/files.ts +22 -0
- package/server/api/routes/mulmo-script.ts +19 -1
- package/server/api/routes/schedulerHandlers.ts +52 -4
- package/server/api/routes/sessions.ts +15 -0
- package/server/api/routes/skills.ts +263 -0
- package/server/build/dispatcher.mjs +299 -0
- package/server/encore/INVARIANTS.md +272 -0
- package/server/encore/boot.ts +39 -0
- package/server/encore/closure.ts +36 -0
- package/server/encore/cycle.ts +276 -0
- package/server/encore/dispatch.ts +103 -0
- package/server/encore/handlers/amend.ts +99 -0
- package/server/encore/handlers/appendNote.ts +74 -0
- package/server/encore/handlers/defineEncore.ts +42 -0
- package/server/encore/handlers/listTickets.ts +107 -0
- package/server/encore/handlers/markStepDone.ts +41 -0
- package/server/encore/handlers/markTargetSkipped.ts +33 -0
- package/server/encore/handlers/query.ts +138 -0
- package/server/encore/handlers/recordValues.ts +44 -0
- package/server/encore/handlers/resolveNotification.ts +121 -0
- package/server/encore/handlers/setup.ts +81 -0
- package/server/encore/handlers/shared.ts +137 -0
- package/server/encore/handlers/snooze.ts +87 -0
- package/server/encore/handlers/startObligationChat.ts +64 -0
- package/server/encore/handlers/startSetupChat.ts +50 -0
- package/server/encore/lock.ts +61 -0
- package/server/encore/notifier.ts +123 -0
- package/server/encore/obligation.ts +25 -0
- package/server/encore/paths.ts +78 -0
- package/server/encore/reconcile.ts +661 -0
- package/server/encore/tick.ts +191 -0
- package/server/encore/yaml-fm.ts +63 -0
- package/server/events/notifications.ts +19 -91
- package/server/index.ts +94 -9
- package/server/notifier/engine.ts +102 -1
- package/server/notifier/macosReminderAdapter.ts +30 -0
- package/server/notifier/runtime-api.ts +41 -1
- package/server/notifier/types.ts +15 -2
- package/server/plugins/runtime.ts +11 -2
- package/server/prompts/index.ts +39 -0
- package/server/prompts/system/journal-pointer.md +12 -0
- package/server/prompts/system/memory-management-atomic.md +33 -0
- package/server/prompts/system/memory-management-topic.md +60 -0
- package/server/prompts/system/news-concierge.md +24 -0
- package/server/prompts/system/sandbox-tools.md +10 -0
- package/server/prompts/system/sources-context.md +16 -0
- package/server/prompts/system/system.md +91 -0
- package/server/system/announceOptionalDeps.ts +57 -0
- package/server/system/appVersion.ts +34 -0
- package/server/system/config.ts +17 -1
- package/server/system/docker.ts +14 -6
- package/server/system/env.ts +18 -5
- package/server/system/optionalDeps.ts +129 -0
- package/server/utils/cli-flags.d.mts +14 -0
- package/server/utils/cli-flags.mjs +53 -0
- package/server/utils/files/encore-io.ts +111 -0
- package/server/utils/time.ts +6 -0
- package/server/workspace/helps/business.md +2 -2
- package/server/workspace/helps/encore-dsl.md +482 -0
- package/server/workspace/helps/index.md +15 -13
- package/server/workspace/helps/mulmoscript.md +3 -3
- package/server/workspace/helps/sandbox.md +2 -2
- package/server/workspace/hooks/dispatcher.ts +7 -5
- package/server/workspace/hooks/provision.ts +6 -3
- package/server/workspace/paths.ts +13 -4
- package/server/workspace/skills/catalog.ts +355 -0
- package/server/workspace/skills/external/catalog.ts +283 -0
- package/server/workspace/skills/external/clone.ts +129 -0
- package/server/workspace/skills/external/id.ts +194 -0
- package/server/workspace/skills/external/install.ts +417 -0
- package/server/workspace/skills/external/presets.ts +50 -0
- package/server/workspace/skills-preset.ts +29 -17
- package/server/workspace/workspace.ts +10 -5
- package/src/App.vue +37 -8
- package/src/components/FileContentRenderer.vue +102 -9
- package/src/components/JsonEditor.vue +160 -0
- package/src/components/NotificationBell.vue +35 -3
- package/src/components/PluginLauncher.vue +20 -41
- package/src/components/RightSidebar.vue +19 -0
- package/src/components/SettingsMcpTab.vue +58 -11
- package/src/components/SettingsModal.vue +22 -1
- package/src/components/StackView.vue +10 -1
- package/src/components/TodoExplorer.vue +16 -0
- package/src/components/todo/TodoKanbanView.vue +34 -6
- package/src/composables/useNotifications.ts +21 -1
- package/src/config/apiRoutes.ts +0 -6
- package/src/config/mcpCatalog.ts +12 -7
- package/src/config/mcpTypes.ts +5 -0
- package/src/config/roles.ts +52 -15
- package/src/config/systemFileDescriptors.ts +12 -0
- package/src/lang/de.ts +108 -12
- package/src/lang/en.ts +105 -11
- package/src/lang/es.ts +106 -11
- package/src/lang/fr.ts +106 -11
- package/src/lang/ja.ts +104 -11
- package/src/lang/ko.ts +105 -11
- package/src/lang/pt-BR.ts +106 -11
- package/src/lang/zh.ts +103 -11
- package/src/main.ts +1 -0
- package/src/plugins/_generated/metas.ts +4 -0
- package/src/plugins/_generated/registrations.ts +2 -0
- package/src/plugins/_generated/server-bindings.ts +5 -0
- package/src/plugins/encore/EncoreDashboard.vue +504 -0
- package/src/plugins/encore/EncoreRedirect.vue +116 -0
- package/src/plugins/encore/View.vue +36 -0
- package/src/plugins/encore/defineEncoreDefinition.ts +74 -0
- package/src/plugins/encore/defineEncoreMeta.ts +13 -0
- package/src/plugins/encore/index.ts +93 -0
- package/src/plugins/encore/manageEncoreDefinition.ts +100 -0
- package/src/plugins/encore/manageEncoreMeta.ts +36 -0
- package/src/plugins/manageSkills/View.vue +832 -30
- package/src/plugins/manageSkills/categories.ts +125 -0
- package/src/plugins/manageSkills/meta.ts +30 -0
- package/src/plugins/markdown/definition.ts +3 -3
- package/src/plugins/meta-types.ts +5 -0
- package/src/plugins/presentMulmoScript/Preview.vue +3 -3
- package/src/plugins/presentMulmoScript/View.vue +157 -33
- package/src/plugins/presentMulmoScript/meta.ts +4 -0
- package/src/plugins/scheduler/View.vue +45 -9
- package/src/plugins/scheduler/calendarDefinition.ts +6 -2
- package/src/plugins/scheduler/multiDayHelpers.ts +95 -0
- package/src/plugins/skill/View.vue +1 -5
- package/src/plugins/spreadsheet/View.vue +3 -3
- package/src/plugins/spreadsheet/definition.ts +1 -1
- package/src/plugins/textResponse/Preview.vue +14 -1
- package/src/plugins/textResponse/View.vue +39 -24
- package/src/plugins/wiki/components/WikiPageBody.vue +4 -0
- package/src/router/index.ts +11 -0
- package/src/router/pageRoutes.ts +1 -0
- package/src/types/encore-dsl/at-expression.ts +120 -0
- package/src/types/encore-dsl/at-resolver.ts +32 -0
- package/src/types/encore-dsl/cadence.ts +289 -0
- package/src/types/encore-dsl/schema.ts +288 -0
- package/src/types/notification.ts +2 -1
- package/src/types/session.ts +6 -0
- package/src/types/sse.ts +5 -0
- package/src/types/toolCallHistory.ts +7 -0
- package/src/utils/agent/eventDispatch.ts +26 -5
- package/src/utils/agent/mcpHint.ts +50 -0
- package/src/utils/image/htmlSrcAttrs.ts +117 -13
- package/src/utils/session/sessionEntries.ts +8 -32
- package/client/assets/PluginScopedRoot-YjvQq0Nn.js +0 -3
- package/client/assets/chunk-CernVdwh.js +0 -1
- package/client/assets/chunk-D8eiyYIV-CAXpUwLd.js +0 -1
- package/client/assets/index-BwrlMMHr.js +0 -5005
- package/client/assets/index-CvvNuegU.css +0 -2
- package/client/assets/material-symbols-outlined-BOZVWuR3.woff2 +0 -0
- package/client/assets/runtime-protocol-vue-C1To4M3t.js +0 -1
- package/client/assets/vue.runtime.esm-bundler-DQ8Kjjui.js +0 -4
- package/server/api/routes/notifications.ts +0 -195
- package/server/notifier/legacy-adapters.ts +0 -76
- package/server/workspace/hooks/dispatcher.mjs +0 -300
- package/src/composables/useSelectedResult.ts +0 -49
|
@@ -483,7 +483,16 @@ onUnmounted(() => {
|
|
|
483
483
|
.stack-natural :deep(.overflow-x-auto) {
|
|
484
484
|
overflow: visible !important;
|
|
485
485
|
}
|
|
486
|
-
|
|
486
|
+
/* Scope the flex-1 neutralisation to VERTICAL flex contexts only
|
|
487
|
+
(#1277). The intent was always "don't let a column child's
|
|
488
|
+
flex-1 collapse the natural content height in stack mode". The
|
|
489
|
+
old bare `:deep(.flex-1)` also hit `.flex-1` children of ROW
|
|
490
|
+
containers (e.g. a plugin `<summary>`'s description wrapper),
|
|
491
|
+
freezing them at `flex: 0 0 auto` so they stopped growing /
|
|
492
|
+
wrapping horizontally (PR #1276 had to work around this
|
|
493
|
+
plugin-side). Restricting to `.flex-col > .flex-1` keeps the
|
|
494
|
+
column fix and leaves row layouts alone. */
|
|
495
|
+
.stack-natural :deep(.flex-col > .flex-1) {
|
|
487
496
|
flex: 0 0 auto !important;
|
|
488
497
|
}
|
|
489
498
|
/* presentHtml's View.vue uses CSS-defined (not Tailwind class)
|
|
@@ -95,6 +95,7 @@
|
|
|
95
95
|
@rename-column="onRenameColumn"
|
|
96
96
|
@delete-column="onDeleteColumn"
|
|
97
97
|
@mark-done="onMarkDone"
|
|
98
|
+
@remove-all-items="onRemoveAllItemsInColumn"
|
|
98
99
|
@reorder-columns="onReorderColumns"
|
|
99
100
|
/>
|
|
100
101
|
<TodoTableView
|
|
@@ -401,6 +402,21 @@ function onMarkDone(columnId: string): void {
|
|
|
401
402
|
void patchColumn(columnId, { isDone: true });
|
|
402
403
|
}
|
|
403
404
|
|
|
405
|
+
async function onRemoveAllItemsInColumn(columnId: string): Promise<void> {
|
|
406
|
+
const col = columns.value.find((column) => column.id === columnId);
|
|
407
|
+
if (!col) return;
|
|
408
|
+
// Items without an explicit status render in the first column in
|
|
409
|
+
// the kanban view, so apply the same fallback here.
|
|
410
|
+
const fallbackColumnId = columns.value[0]?.id;
|
|
411
|
+
const idsToDelete = items.value.filter((item) => (item.status ?? fallbackColumnId) === columnId).map((item) => item.id);
|
|
412
|
+
if (idsToDelete.length === 0) return;
|
|
413
|
+
const confirmed = window.confirm(t("todoKanban.removeAllItemsConfirm", { column: col.label, count: idsToDelete.length }));
|
|
414
|
+
if (!confirmed) return;
|
|
415
|
+
for (const itemId of idsToDelete) {
|
|
416
|
+
await deleteItem(itemId);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
404
420
|
function onReorderColumns(ids: string[]): void {
|
|
405
421
|
void reorderColumns(ids);
|
|
406
422
|
}
|
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
starts a column drag. -->
|
|
19
19
|
<div class="flex items-center justify-between px-3 py-2 border-b border-gray-200 col-handle cursor-grab active:cursor-grabbing">
|
|
20
20
|
<div class="flex items-center gap-2 min-w-0">
|
|
21
|
-
<span class="
|
|
21
|
+
<span v-if="col.isDone" class="material-icons text-base text-gray-700 shrink-0 leading-none" aria-hidden="true">check</span>
|
|
22
|
+
<span v-else class="w-2 h-2 rounded-full shrink-0 bg-gray-400" />
|
|
22
23
|
<span v-if="renamingId !== col.id" class="font-semibold text-sm text-gray-700 truncate" :title="col.label">{{ col.label }}</span>
|
|
23
24
|
<input
|
|
24
25
|
v-else
|
|
@@ -31,7 +32,7 @@
|
|
|
31
32
|
/>
|
|
32
33
|
<span class="text-xs text-gray-500 shrink-0">{{ itemsByColumn(col.id).length }}</span>
|
|
33
34
|
</div>
|
|
34
|
-
<div class="relative">
|
|
35
|
+
<div class="relative" data-todo-column-menu>
|
|
35
36
|
<button class="text-gray-400 hover:text-gray-600 px-1" :title="t('todoKanban.columnActions')" @click="toggleMenu(col.id)">
|
|
36
37
|
<span class="material-icons text-base">more_horiz</span>
|
|
37
38
|
</button>
|
|
@@ -41,10 +42,17 @@
|
|
|
41
42
|
@click.stop
|
|
42
43
|
>
|
|
43
44
|
<button class="w-full text-left px-3 py-1.5 hover:bg-gray-50" @click="startRename(col)">{{ t("todoKanban.rename") }}</button>
|
|
44
|
-
<button class="w-full text-left px-3 py-1.5 hover:bg-gray-50" @click="markAsDone(col.id)">
|
|
45
|
-
{{
|
|
45
|
+
<button v-if="!col.isDone" class="w-full text-left px-3 py-1.5 hover:bg-gray-50" @click="markAsDone(col.id)">
|
|
46
|
+
{{ t("todoKanban.markAsDoneColumn") }}
|
|
46
47
|
</button>
|
|
47
|
-
<button class="w-full text-left px-3 py-1.5
|
|
48
|
+
<button v-if="col.isDone" class="w-full text-left px-3 py-1.5 hover:bg-gray-50" @click="removeAllItems(col.id)">
|
|
49
|
+
{{ t("todoKanban.removeAllItems") }}
|
|
50
|
+
</button>
|
|
51
|
+
<button
|
|
52
|
+
class="w-full text-left px-3 py-1.5 text-red-600 hover:bg-red-50 disabled:text-gray-300 disabled:cursor-not-allowed disabled:hover:bg-transparent"
|
|
53
|
+
:disabled="col.isDone"
|
|
54
|
+
@click="deleteColumn(col.id)"
|
|
55
|
+
>
|
|
48
56
|
{{ t("todoKanban.deleteColumn") }}
|
|
49
57
|
</button>
|
|
50
58
|
</div>
|
|
@@ -119,7 +127,7 @@
|
|
|
119
127
|
</template>
|
|
120
128
|
|
|
121
129
|
<script setup lang="ts">
|
|
122
|
-
import { computed, nextTick, ref, watch } from "vue";
|
|
130
|
+
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from "vue";
|
|
123
131
|
import { useI18n } from "vue-i18n";
|
|
124
132
|
import draggable from "vuedraggable";
|
|
125
133
|
import type { StatusColumn, TodoItem } from "@mulmoclaude/todo-plugin/shared";
|
|
@@ -153,6 +161,7 @@ const emit = defineEmits<{
|
|
|
153
161
|
renameColumn: [id: string, label: string];
|
|
154
162
|
deleteColumn: [id: string];
|
|
155
163
|
markDone: [id: string];
|
|
164
|
+
removeAllItems: [id: string];
|
|
156
165
|
reorderColumns: [ids: string[]];
|
|
157
166
|
}>();
|
|
158
167
|
|
|
@@ -259,4 +268,23 @@ function markAsDone(columnId: string): void {
|
|
|
259
268
|
menuOpenId.value = null;
|
|
260
269
|
emit("markDone", columnId);
|
|
261
270
|
}
|
|
271
|
+
|
|
272
|
+
function removeAllItems(columnId: string): void {
|
|
273
|
+
menuOpenId.value = null;
|
|
274
|
+
emit("removeAllItems", columnId);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Close any open column menu when the user clicks outside of its
|
|
278
|
+
// wrapper. We tag each menu wrapper (toggle button + popover) with
|
|
279
|
+
// data-todo-column-menu, so a click on either the toggle or a menu
|
|
280
|
+
// entry is treated as "inside" and won't dismiss; everything else does.
|
|
281
|
+
function onDocumentClickOutsideMenu(event: MouseEvent): void {
|
|
282
|
+
if (menuOpenId.value === null) return;
|
|
283
|
+
const target = event.target as Element | null;
|
|
284
|
+
if (target?.closest("[data-todo-column-menu]")) return;
|
|
285
|
+
menuOpenId.value = null;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
onMounted(() => document.addEventListener("click", onDocumentClickOutsideMenu));
|
|
289
|
+
onUnmounted(() => document.removeEventListener("click", onDocumentClickOutsideMenu));
|
|
262
290
|
</script>
|
|
@@ -39,7 +39,11 @@ export interface NotifierHistoryEntry extends NotifierEntry {
|
|
|
39
39
|
terminalAt: string;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
type NotifierEvent =
|
|
42
|
+
type NotifierEvent =
|
|
43
|
+
| { type: "published"; entry: NotifierEntry }
|
|
44
|
+
| { type: "cleared"; id: string }
|
|
45
|
+
| { type: "cancelled"; id: string }
|
|
46
|
+
| { type: "updated"; entry: NotifierEntry };
|
|
43
47
|
|
|
44
48
|
const HISTORY_CAP = 50;
|
|
45
49
|
|
|
@@ -74,6 +78,22 @@ function applyEvent(event: NotifierEvent): void {
|
|
|
74
78
|
entries.value = [...entries.value, event.entry];
|
|
75
79
|
}
|
|
76
80
|
return;
|
|
81
|
+
case "updated": {
|
|
82
|
+
// In-place replacement: same id, fresh title/body/severity.
|
|
83
|
+
// No history record — the entry is still active. If the id
|
|
84
|
+
// isn't in our local set (subscribed mid-flight, or the
|
|
85
|
+
// entry was optimistically cleared elsewhere), fall back to
|
|
86
|
+
// append so the bell at least surfaces live state.
|
|
87
|
+
const index = entries.value.findIndex((entry) => entry.id === event.entry.id);
|
|
88
|
+
if (index >= 0) {
|
|
89
|
+
const next = entries.value.slice();
|
|
90
|
+
next[index] = event.entry;
|
|
91
|
+
entries.value = next;
|
|
92
|
+
} else {
|
|
93
|
+
entries.value = [...entries.value, event.entry];
|
|
94
|
+
}
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
77
97
|
case "cleared":
|
|
78
98
|
case "cancelled": {
|
|
79
99
|
const removed = entries.value.find((entry) => entry.id === event.id);
|
package/src/config/apiRoutes.ts
CHANGED
|
@@ -128,12 +128,6 @@ const HOST_API_ROUTES = {
|
|
|
128
128
|
invoke: "/api/mcp-tools/:tool",
|
|
129
129
|
},
|
|
130
130
|
|
|
131
|
-
notifications: {
|
|
132
|
-
// PoC endpoint for scheduled push fan-out (Web pub-sub + bridge).
|
|
133
|
-
// Scaffolding for #144 / #142 — see plans/done/feat-notification-push-scaffold.md.
|
|
134
|
-
test: "/api/notifications/test",
|
|
135
|
-
},
|
|
136
|
-
|
|
137
131
|
/** Notifier dispatch — single endpoint, body carries `{ action,
|
|
138
132
|
* ... }`. Matches the `manage*` tool pattern used elsewhere
|
|
139
133
|
* (manageEncore / manageAccounting / manageSkills). */
|
package/src/config/mcpCatalog.ts
CHANGED
|
@@ -406,14 +406,19 @@ export const MCP_CATALOG: McpCatalogEntry[] = [
|
|
|
406
406
|
displayName: "settingsMcpTab.catalog.entry.github.displayName",
|
|
407
407
|
description: "settingsMcpTab.catalog.entry.github.description",
|
|
408
408
|
audience: "general",
|
|
409
|
-
upstreamUrl: "https://github.com/
|
|
410
|
-
setupGuideUrl: "https://docs.github.com/en/
|
|
409
|
+
upstreamUrl: "https://github.com/github/github-mcp-server",
|
|
410
|
+
setupGuideUrl: "https://docs.github.com/en/copilot/how-tos/provide-context/use-mcp/set-up-the-github-mcp-server",
|
|
411
|
+
// Switched stdio (@modelcontextprotocol/server-github) → the
|
|
412
|
+
// provider-hosted remote MCP (#1421 A1). HTTP transport works
|
|
413
|
+
// under the Docker sandbox, where the stdio reference server is
|
|
414
|
+
// dropped (server/agent/config.ts — no npx in the minimal
|
|
415
|
+
// image). PAT auth keeps it OAuth-free; the configSchema key
|
|
416
|
+
// and its i18n are unchanged so installs/migrations stay valid.
|
|
411
417
|
spec: {
|
|
412
|
-
type: "
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
GITHUB_PERSONAL_ACCESS_TOKEN: "${GITHUB_PERSONAL_ACCESS_TOKEN}",
|
|
418
|
+
type: "http",
|
|
419
|
+
url: "https://api.githubcopilot.com/mcp/",
|
|
420
|
+
headers: {
|
|
421
|
+
Authorization: "Bearer ${GITHUB_PERSONAL_ACCESS_TOKEN}",
|
|
417
422
|
},
|
|
418
423
|
},
|
|
419
424
|
configSchema: [
|
package/src/config/mcpTypes.ts
CHANGED
|
@@ -16,6 +16,11 @@ export interface StdioSpec {
|
|
|
16
16
|
args?: string[];
|
|
17
17
|
env?: Record<string, string>;
|
|
18
18
|
enabled?: boolean;
|
|
19
|
+
/** Opt-in (#1421 Phase B): run on the HOST behind a stdio↔HTTP
|
|
20
|
+
* gateway even in Docker sandbox mode, instead of being dropped.
|
|
21
|
+
* Deliberately escapes the sandbox for this server — the MCP
|
|
22
|
+
* settings UI gates this behind an explicit risk acknowledgment. */
|
|
23
|
+
hostExecInDocker?: boolean;
|
|
19
24
|
}
|
|
20
25
|
|
|
21
26
|
export type McpServerSpec = HttpSpec | StdioSpec;
|
package/src/config/roles.ts
CHANGED
|
@@ -58,21 +58,46 @@ export const ROLES: Role[] = [
|
|
|
58
58
|
"- **Browse / lint**: direct the user to the `/wiki` UI — catalog at `/wiki`, a specific page at `/wiki/pages/<slug>`, activity log at `/wiki/log`, or the Lint button on `/wiki` for a health check.\n\n" +
|
|
59
59
|
"Page format: YAML frontmatter (title, created, updated, tags) + markdown body + `[[wiki links]]` for cross-references. Slugs are lowercase hyphen-separated. Always keep `data/wiki/index.md` current and append to `data/wiki/log.md` after any change. The page-list section of `index.md` is a flat, recency-ordered log: prepend new pages at the top, and when a page is updated (content, description, tags, or rename) move its entry to the top — don't group by category. The Tags section (if present) still needs its per-tag page lists updated on add / rename / delete, but the tag order itself is not reordered by recency. Read `config/helps/wiki.md` for full details.",
|
|
60
60
|
availablePlugins: [
|
|
61
|
-
TOOL_NAMES.manageCalendar,
|
|
62
61
|
TOOL_NAMES.presentDocument,
|
|
63
62
|
TOOL_NAMES.presentForm,
|
|
64
63
|
TOOL_NAMES.presentMulmoScript,
|
|
65
64
|
TOOL_NAMES.generateImage,
|
|
66
65
|
TOOL_NAMES.presentHtml,
|
|
67
|
-
TOOL_NAMES.mapControl,
|
|
68
|
-
TOOL_NAMES.managePhotoLocations,
|
|
69
66
|
TOOL_NAMES.readXPost,
|
|
70
67
|
TOOL_NAMES.searchX,
|
|
68
|
+
],
|
|
69
|
+
queries: [
|
|
70
|
+
"Tell me about this app, MulmoClaude.",
|
|
71
|
+
"What is the wiki in this app and how do I use it?",
|
|
72
|
+
"Tell me about the sandbox feature of this app.",
|
|
73
|
+
"What is the role of the Gemini API key in this app?",
|
|
74
|
+
"How do I use the Telegram bridge to talk to MulmoClaude from my phone?",
|
|
75
|
+
"Show my wiki index",
|
|
76
|
+
"Lint my wiki",
|
|
77
|
+
],
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
id: "personal",
|
|
81
|
+
name: "Personal",
|
|
82
|
+
icon: "person",
|
|
83
|
+
prompt:
|
|
84
|
+
"You are a personal assistant focused on the user's daily life — calendar, todos, recurring obligations (Encore), bookmarks, music, places, and notifications. Help the user organize, track, and recall personal information.\n\n" +
|
|
85
|
+
"## Asking the user to choose\n\n" +
|
|
86
|
+
"When the user must pick from a small set of options, toggle features, or answer yes/no, call presentForm with the appropriate fields (radio for one-of, checkbox for many-of, text/textarea for free-form). Group related questions into one form. Prefer this strongly over phrasing the choice in plain prose — the form gives the user clickable controls and sends the answers back as a markdown bullet list.\n\n" +
|
|
87
|
+
"Mark every field the user must answer as `required: true`. The form blocks submission until required fields are filled, which prevents the LLM from receiving partial responses.",
|
|
88
|
+
availablePlugins: [
|
|
89
|
+
TOOL_NAMES.manageCalendar,
|
|
90
|
+
TOOL_NAMES.defineEncore,
|
|
91
|
+
TOOL_NAMES.manageEncore,
|
|
92
|
+
TOOL_NAMES.managePhotoLocations,
|
|
93
|
+
TOOL_NAMES.mapControl,
|
|
71
94
|
TOOL_NAMES.notify,
|
|
95
|
+
TOOL_NAMES.presentDocument,
|
|
96
|
+
TOOL_NAMES.presentForm,
|
|
72
97
|
// Preset runtime plugins (server/plugins/preset-list.ts).
|
|
73
98
|
// Runtime plugins are gated by `availablePlugins` like the
|
|
74
99
|
// static-GUI / static-MCP entries above; listed here so the
|
|
75
|
-
// out-of-the-box "
|
|
100
|
+
// out-of-the-box "personal" role keeps exposing them. User-
|
|
76
101
|
// installed runtime plugins (`~/mulmoclaude/plugins/*`) are
|
|
77
102
|
// added to roles via Settings → Roles.
|
|
78
103
|
TOOL_NAMES.manageBookmarks,
|
|
@@ -80,15 +105,13 @@ export const ROLES: Role[] = [
|
|
|
80
105
|
TOOL_NAMES.manageSpotify,
|
|
81
106
|
],
|
|
82
107
|
queries: [
|
|
83
|
-
"Tell me about this app, MulmoClaude.",
|
|
84
|
-
"What is the wiki in this app and how do I use it?",
|
|
85
|
-
"Tell me about the sandbox feature of this app.",
|
|
86
|
-
"What is the role of the Gemini API key in this app?",
|
|
87
|
-
"How do I use the Telegram bridge to talk to MulmoClaude from my phone?",
|
|
88
|
-
"Show my wiki index",
|
|
89
|
-
"Lint my wiki",
|
|
90
|
-
"Show my todo list",
|
|
91
108
|
"Show me my calendar",
|
|
109
|
+
"Show my todo list",
|
|
110
|
+
"What recurring obligations do I have?",
|
|
111
|
+
"Add a bookmark for this URL",
|
|
112
|
+
"Where are the photos I took last weekend?",
|
|
113
|
+
"Play some focus music on Spotify",
|
|
114
|
+
"Remind me to call mom this evening",
|
|
92
115
|
],
|
|
93
116
|
},
|
|
94
117
|
{
|
|
@@ -97,7 +120,7 @@ export const ROLES: Role[] = [
|
|
|
97
120
|
icon: "business_center",
|
|
98
121
|
prompt:
|
|
99
122
|
"You are a professional office assistant. Create and edit documents, spreadsheets, and presentations. Read existing files in the workspace for context.\n\n" +
|
|
100
|
-
"For multi-slide presentations, use presentMulmoScript.
|
|
123
|
+
"For multi-slide presentations, use presentMulmoScript — first Read `config/helps/business.md` for the template and rules, then follow them exactly.\n\n" +
|
|
101
124
|
"Use presentHtml for rich interactive output such as dashboards, reports with live controls, or data visualizations. Recommended libraries (load via CDN):\n" +
|
|
102
125
|
"- **UI / layout**: Tailwind CSS — https://cdn.tailwindcss.com\n" +
|
|
103
126
|
"- **Data visualization**: D3.js — https://cdnjs.cloudflare.com/ajax/libs/d3/7.8.5/d3.min.js",
|
|
@@ -131,7 +154,7 @@ export const ROLES: Role[] = [
|
|
|
131
154
|
prompt:
|
|
132
155
|
"You are a knowledgeable guide and planner. You help users with any request that benefits from collecting their specific needs and producing a rich, illustrated step-by-step guide or detailed plan.\n\n" +
|
|
133
156
|
"Supported guide types: recipe, travel itinerary, fitness program, event plan, study guide, DIY / home project — or any other scenario where a structured, illustrated document adds value.\n\n" +
|
|
134
|
-
"
|
|
157
|
+
"Read `config/helps/guide.md` first; follow the templates and rules there exactly.\n\n" +
|
|
135
158
|
"## Workflow\n\n" +
|
|
136
159
|
"1. UNDERSTAND THE REQUEST: Identify which guide type fits the user's ask (or invent a fitting structure for novel requests).\n\n" +
|
|
137
160
|
"2. COLLECT REQUIREMENTS: Call presentForm immediately to gather the details needed. Tailor the form fields to the specific request — see guide.md for per-type field suggestions. Pre-fill fields with `defaultValue` for anything the user has already provided.\n\n" +
|
|
@@ -201,7 +224,7 @@ export const ROLES: Role[] = [
|
|
|
201
224
|
icon: "auto_stories",
|
|
202
225
|
prompt:
|
|
203
226
|
"You are a creative storyteller who crafts vivid, imaginative stories with consistent, named characters across every beat.\n\n" +
|
|
204
|
-
"For multi-beat narrated stories, use presentMulmoScript.
|
|
227
|
+
"For multi-beat narrated stories, use presentMulmoScript — first Read `config/helps/storyteller.md` for the template and rules, then follow them exactly.\n\n" +
|
|
205
228
|
"When asked to create a story:\n" +
|
|
206
229
|
"1. Decide on 2–5 main characters. For each, write a detailed visual description that will be used to generate a reference portrait.\n" +
|
|
207
230
|
"2. Define every character in `imageParams.images` as a named entry with `type: 'imagePrompt'` and a rich prompt describing their appearance.\n" +
|
|
@@ -310,6 +333,8 @@ export const ROLES: Role[] = [
|
|
|
310
333
|
TOOL_NAMES.presentDocument,
|
|
311
334
|
TOOL_NAMES.presentChart,
|
|
312
335
|
TOOL_NAMES.presentHtml,
|
|
336
|
+
TOOL_NAMES.readXPost,
|
|
337
|
+
TOOL_NAMES.searchX,
|
|
313
338
|
],
|
|
314
339
|
queries: [
|
|
315
340
|
"Summarise the key risk factors from AAPL's latest 10-K",
|
|
@@ -395,6 +420,7 @@ export const BUILTIN_ROLES = ROLES;
|
|
|
395
420
|
// updating this map fails the test.
|
|
396
421
|
export const BUILTIN_ROLE_IDS = {
|
|
397
422
|
general: "general",
|
|
423
|
+
personal: "personal",
|
|
398
424
|
office: "office",
|
|
399
425
|
guide: "guide",
|
|
400
426
|
artist: "artist",
|
|
@@ -414,6 +440,17 @@ export type BuiltInRoleId = (typeof BUILTIN_ROLE_IDS)[keyof typeof BUILTIN_ROLE_
|
|
|
414
440
|
|
|
415
441
|
export const DEFAULT_ROLE_ID: BuiltInRoleId = BUILTIN_ROLE_IDS.general;
|
|
416
442
|
|
|
443
|
+
// Role id that Encore's `resolveNotification` flow seeds new chats
|
|
444
|
+
// with. Pinned to `personal` because that role owns the Encore tool
|
|
445
|
+
// pair (`defineEncore` for DSL composition / amendment,
|
|
446
|
+
// `manageEncore` for operational kinds like markStepDone / snooze).
|
|
447
|
+
// Seeding into a role without these tools leaves the agent unable
|
|
448
|
+
// to drive the obligation it was just woken up for. Guarded by
|
|
449
|
+
// `test/roles/test_encore_seed_role.ts` so renaming the role or
|
|
450
|
+
// dropping either tool from its `availablePlugins` fails CI rather
|
|
451
|
+
// than silently breaking the seeded chat.
|
|
452
|
+
export const ENCORE_SEED_ROLE_ID: BuiltInRoleId = BUILTIN_ROLE_IDS.personal;
|
|
453
|
+
|
|
417
454
|
export function getRole(roleId: string): Role {
|
|
418
455
|
return ROLES.find((role) => role.id === roleId) ?? ROLES[0];
|
|
419
456
|
}
|
|
@@ -155,6 +155,18 @@ export function descriptorForPath(filePath: string): SystemFileDescriptor | null
|
|
|
155
155
|
return null;
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
+
// editPolicy values for which the Files Explorer offers an inline
|
|
159
|
+
// JSON editor (#833 Phase 1). A path with no descriptor is a plain
|
|
160
|
+
// user-owned file → editable. `agent-managed` / `fragile-format` /
|
|
161
|
+
// `ephemeral` are withheld: hand-edits there risk corrupting state the
|
|
162
|
+
// agent or app owns, or a format too brittle for free-text editing.
|
|
163
|
+
const JSON_EDITABLE_POLICIES: ReadonlySet<EditPolicy> = new Set<EditPolicy>(["user-editable", "agent-managed-but-hand-editable"]);
|
|
164
|
+
|
|
165
|
+
export function jsonEditableByPolicy(filePath: string): boolean {
|
|
166
|
+
const descriptor = descriptorForPath(filePath);
|
|
167
|
+
return descriptor === null || JSON_EDITABLE_POLICIES.has(descriptor.editPolicy);
|
|
168
|
+
}
|
|
169
|
+
|
|
158
170
|
// Tailwind text colors used to tint a file-icon (or any single-color
|
|
159
171
|
// glyph) according to the system file's edit policy. Same hue as the
|
|
160
172
|
// banner's chip but text-only (no background) — the chip uses a
|
package/src/lang/de.ts
CHANGED
|
@@ -28,7 +28,7 @@ const deMessages = {
|
|
|
28
28
|
},
|
|
29
29
|
},
|
|
30
30
|
chatInput: {
|
|
31
|
-
placeholder: "
|
|
31
|
+
placeholder: "Nachricht an Claude…",
|
|
32
32
|
send: "Senden",
|
|
33
33
|
attachFile: "Datei anhängen",
|
|
34
34
|
fileTooLarge: "Datei zu groß ({sizeMB} MB). Das Maximum beträgt 30 MB.",
|
|
@@ -68,6 +68,8 @@ const deMessages = {
|
|
|
68
68
|
clearAll: "Alle löschen",
|
|
69
69
|
dismiss: "Verwerfen",
|
|
70
70
|
cancel: "Abbrechen",
|
|
71
|
+
showMore: "Mehr anzeigen ({count})",
|
|
72
|
+
showLess: "Weniger anzeigen",
|
|
71
73
|
},
|
|
72
74
|
pluginDiagnostics: {
|
|
73
75
|
title: "Plugin-Konfigurationsproblem",
|
|
@@ -76,6 +78,18 @@ const deMessages = {
|
|
|
76
78
|
intraBody:
|
|
77
79
|
"Die Plugins „{first}“ und „{second}“ registrieren beide {dimension} „{key}“. „{first}“ hat ihn zuerst beansprucht, daher wird die Registrierung von „{second}“ ignoriert.",
|
|
78
80
|
},
|
|
81
|
+
optionalDeps: {
|
|
82
|
+
// Generischer `title` aus Abwärtskompatibilität für persistierte
|
|
83
|
+
// History-Einträge vor der Aufteilung nach Grund; neue Pfade
|
|
84
|
+
// verwenden `titleNotFound` / `titleNotResponding`.
|
|
85
|
+
title: "Optionale Abhängigkeit nicht verfügbar",
|
|
86
|
+
titleNotFound: "{command} ist nicht installiert",
|
|
87
|
+
titleNotResponding: "{command} läuft nicht",
|
|
88
|
+
notFound:
|
|
89
|
+
"{command} nicht gefunden — zugehörige Funktionen wurden deaktiviert. Installieren Sie {command} und starten Sie MulmoClaude neu, um sie zu aktivieren.",
|
|
90
|
+
notResponding:
|
|
91
|
+
"{command} ist installiert, läuft aber nicht — zugehörige Funktionen wurden deaktiviert. Starten Sie {command} und starten Sie MulmoClaude neu, um sie zu aktivieren.",
|
|
92
|
+
},
|
|
79
93
|
pluginErrorBoundary: {
|
|
80
94
|
title: "Plugin {pkg} ist abgestürzt",
|
|
81
95
|
subtitle: "Das Plugin konnte nicht gerendert werden. Der Fehler wurde in der Konsole protokolliert.",
|
|
@@ -105,6 +119,11 @@ const deMessages = {
|
|
|
105
119
|
error: "Fehler",
|
|
106
120
|
result: "Ergebnis",
|
|
107
121
|
running: "Läuft...",
|
|
122
|
+
mcpHint: {
|
|
123
|
+
title: (ctx: { named: (key: "server") => string }) => `Einrichtungshinweis: ${ctx.named("server")}`,
|
|
124
|
+
requiredKeys: "Erforderliche Schlüssel",
|
|
125
|
+
setupGuide: "Einrichtungsanleitung öffnen",
|
|
126
|
+
},
|
|
108
127
|
},
|
|
109
128
|
fileTreePane: {
|
|
110
129
|
sort: "Sortieren:",
|
|
@@ -141,6 +160,7 @@ const deMessages = {
|
|
|
141
160
|
},
|
|
142
161
|
settingsModal: {
|
|
143
162
|
title: "Einstellungen",
|
|
163
|
+
version: "MulmoClaude v{version}",
|
|
144
164
|
tabs: {
|
|
145
165
|
gemini: "Gemini-API-Schlüssel",
|
|
146
166
|
tools: "Erlaubte Tools",
|
|
@@ -254,15 +274,43 @@ const deMessages = {
|
|
|
254
274
|
errLabelConflict: 'Label "{label}" existiert bereits',
|
|
255
275
|
},
|
|
256
276
|
pluginLauncher: {
|
|
257
|
-
todos: { label: "To-dos"
|
|
258
|
-
calendar: { label: "Kalender"
|
|
259
|
-
automations: { label: "Aktionen"
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
277
|
+
todos: { label: "To-dos" },
|
|
278
|
+
calendar: { label: "Kalender" },
|
|
279
|
+
automations: { label: "Aktionen" },
|
|
280
|
+
encore: { label: "Encore" },
|
|
281
|
+
wiki: { label: "Wiki" },
|
|
282
|
+
sources: { label: "Quellen" },
|
|
283
|
+
news: { label: "Nachrichten" },
|
|
284
|
+
skills: { label: "Skills" },
|
|
285
|
+
roles: { label: "Rollen" },
|
|
286
|
+
files: { label: "Dateien" },
|
|
287
|
+
},
|
|
288
|
+
encoreDashboard: {
|
|
289
|
+
title: "Encore",
|
|
290
|
+
subtitle: "Wiederkehrende Verpflichtungen, die Encore verfolgt.",
|
|
291
|
+
loading: "Verpflichtungen werden geladen…",
|
|
292
|
+
errorPrefix: "Verpflichtungen konnten nicht geladen werden: ",
|
|
293
|
+
empty: "Noch keine Verpflichtungen. Frage im Chat nach, um eine einzurichten.",
|
|
294
|
+
noCycles: "Noch keine Zyklen erfasst.",
|
|
295
|
+
cyclesSuffix: "Zyklen",
|
|
296
|
+
targetCount: "{count} Ziel | {count} Ziele",
|
|
297
|
+
cycleClosed: "Erledigt",
|
|
298
|
+
chatButtonTitle: "Diese Verpflichtung in einem neuen Chat besprechen",
|
|
299
|
+
bellButtonTitle: "Diesen Zyklus besprechen",
|
|
300
|
+
addButtonLabel: "Hinzufügen",
|
|
301
|
+
unexpectedResponse: "Encore hat eine unerwartete Antwort zurückgegeben.",
|
|
302
|
+
status: {
|
|
303
|
+
active: "Aktiv",
|
|
304
|
+
paused: "Pausiert",
|
|
305
|
+
retired: "Beendet",
|
|
306
|
+
},
|
|
307
|
+
cadence: {
|
|
308
|
+
daily: "Täglich",
|
|
309
|
+
weekly: "Wöchentlich",
|
|
310
|
+
monthly: "Monatlich",
|
|
311
|
+
biannual: "Halbjährlich",
|
|
312
|
+
annual: "Jährlich",
|
|
313
|
+
},
|
|
266
314
|
},
|
|
267
315
|
fileContentHeader: {
|
|
268
316
|
showRendered: "Gerendertes Markdown anzeigen",
|
|
@@ -276,6 +324,11 @@ const deMessages = {
|
|
|
276
324
|
htmlPreview: "HTML-Vorschau",
|
|
277
325
|
pdfPreview: "PDF-Vorschau",
|
|
278
326
|
parseError: "Parse-Fehler",
|
|
327
|
+
editJson: "JSON bearbeiten",
|
|
328
|
+
jsonEditorLabel: "JSON-Editor",
|
|
329
|
+
invalidJson: "Ungültiges JSON",
|
|
330
|
+
undo: "Rückgängig",
|
|
331
|
+
redo: "Wiederholen",
|
|
279
332
|
},
|
|
280
333
|
filesView: {
|
|
281
334
|
chatPlaceholder: "Frage zu dieser Datei stellen…",
|
|
@@ -396,6 +449,9 @@ const deMessages = {
|
|
|
396
449
|
urlLabel: "URL:",
|
|
397
450
|
commandLabel: "Befehl:",
|
|
398
451
|
dockerStdioUnsupported: "⚠ Wird nicht ausgeführt, solange die Docker-Sandbox aktiv ist.",
|
|
452
|
+
dockerStdioHostExecActive: "⚠ Läuft auf dem Host — dieser Server verlässt die Docker-Sandbox.",
|
|
453
|
+
dockerStdioHostExecOptIn:
|
|
454
|
+
"Trotzdem auf dem Host ausführen (fortgeschritten). Dieser Server läuft über ein lokales HTTP-Gateway außerhalb der Docker-Sandbox und kann auf Ihren Rechner zugreifen.",
|
|
399
455
|
learnMore: "Mehr erfahren",
|
|
400
456
|
addServerButton: "+ MCP-Server hinzufügen",
|
|
401
457
|
nameLabel: "Name",
|
|
@@ -579,6 +635,7 @@ const deMessages = {
|
|
|
579
635
|
yamlParseError: "YAML konnte nicht geparst werden — stellen Sie sicher, dass 'title' vorhanden ist",
|
|
580
636
|
propLabel: "{key}:",
|
|
581
637
|
moreCount: "+{count} weitere",
|
|
638
|
+
invalidRange: "Ungültiger Datumsbereich (endDate: {endDate})",
|
|
582
639
|
previewIcon: "📅",
|
|
583
640
|
previewUpcoming: "{count} anstehend",
|
|
584
641
|
previewAutomations: "{count} Automatisierung | {count} Automatisierungen",
|
|
@@ -871,8 +928,9 @@ const deMessages = {
|
|
|
871
928
|
},
|
|
872
929
|
todoKanban: {
|
|
873
930
|
rename: "Umbenennen",
|
|
874
|
-
|
|
875
|
-
|
|
931
|
+
markAsDoneColumn: "Als Spalte „Erledigt“ markieren",
|
|
932
|
+
removeAllItems: "Alle Elemente entfernen",
|
|
933
|
+
removeAllItemsConfirm: "Alle {count} Elemente in „{column}“ entfernen? Diese Aktion kann nicht rückgängig gemacht werden.",
|
|
876
934
|
deleteColumn: "Spalte löschen",
|
|
877
935
|
columnActions: "Spaltenaktionen",
|
|
878
936
|
addCard: "+ Karte hinzufügen",
|
|
@@ -1089,6 +1147,42 @@ const deMessages = {
|
|
|
1089
1147
|
errSaveFailed: "Speichern fehlgeschlagen: {error}",
|
|
1090
1148
|
errDeleteFailed: "Löschen fehlgeschlagen",
|
|
1091
1149
|
confirmDelete: 'Skill "{name}" löschen? Dies entfernt ~/mulmoclaude/.claude/skills/{name}/SKILL.md.',
|
|
1150
|
+
sectionActive: "Aktiv",
|
|
1151
|
+
sectionCatalog: "Katalog",
|
|
1152
|
+
sectionLegend:
|
|
1153
|
+
"Aktiv: in den Prompt geladen ({system} System = mc- mitgeliefert · {project} Projekt = bearbeitbar · {user} Benutzer = ~/.claude/skills/). Katalog: durchsuchen, ★markieren oder ▶einmal ausführen, ohne den Prompt aufzublähen.",
|
|
1154
|
+
catalogEmpty: "Keine Preset-Skills verfügbar.",
|
|
1155
|
+
catalogPresetHeading: "Presets",
|
|
1156
|
+
catalogStar: "Markieren",
|
|
1157
|
+
catalogStarred: "Markiert",
|
|
1158
|
+
catalogRunOnce: "Einmalig ausführen",
|
|
1159
|
+
sourceUserTitle: "Benutzer-Skill (~/.claude/skills/, in allen Workspaces verfügbar)",
|
|
1160
|
+
sourceSystemTitle: "System-Skill (mitgeliefert, mc- Präfix — schreibgeschützt, vom Launcher überschrieben)",
|
|
1161
|
+
sourceProjectTitle: "Projekt-Skill (.claude/skills/ des Workspaces, nur dieser Workspace)",
|
|
1162
|
+
sourcePresetTitle: "Preset-Katalog — Markieren anklicken, um in diesem Workspace zu aktivieren",
|
|
1163
|
+
errCatalogListFailed: "Katalog konnte nicht geladen werden: {error}",
|
|
1164
|
+
errCatalogStarFailed: "Skill konnte nicht markiert werden: {error}",
|
|
1165
|
+
errCatalogPreviewFailed: "Skill-Vorschau konnte nicht geladen werden: {error}",
|
|
1166
|
+
errCatalogRunOnceEmpty: "Diese Skill hat keinen Inhalt zum Ausführen.",
|
|
1167
|
+
catalogAddRepo: "Skill-Repository hinzufügen",
|
|
1168
|
+
catalogAddRepoTitle: "Ein Skill-Repository hinzufügen",
|
|
1169
|
+
catalogRepoUrlLabel: "GitHub-URL",
|
|
1170
|
+
catalogRepoUrlPlaceholder: "https://github.com/owner/repo",
|
|
1171
|
+
catalogRepoSubpathLabel: "Unterpfad (optional)",
|
|
1172
|
+
catalogRepoSubpathPlaceholder: "skills",
|
|
1173
|
+
catalogAddRepoSubmit: "Installieren",
|
|
1174
|
+
catalogAddRepoSuggestions: "Vorgeschlagene Repositories",
|
|
1175
|
+
catalogUninstallRepo: "Repository deinstallieren",
|
|
1176
|
+
catalogUpdateRepo: "Repository aktualisieren (neueste Version erneut laden)",
|
|
1177
|
+
catalogRepoOpenLink: "Repository auf GitHub öffnen (neuer Tab)",
|
|
1178
|
+
catalogUninstallConfirm: "Dieses Repository deinstallieren? Bereits mit Stern markierte Skills bleiben in deiner aktiven Liste.",
|
|
1179
|
+
catalogRepoInstalling: "Installiere…",
|
|
1180
|
+
catalogRepoEmpty: "In diesem Repository wurden keine Skills gefunden.",
|
|
1181
|
+
sourceExternalTitle: "Externe Skill (aus einem GitHub-Repository installiert — zum Aktivieren auf den Stern klicken)",
|
|
1182
|
+
errCatalogRepoListFailed: "Installierte Repositories konnten nicht geladen werden: {error}",
|
|
1183
|
+
errCatalogRepoInstallFailed: "Repository konnte nicht installiert werden: {error}",
|
|
1184
|
+
errCatalogRepoUninstallFailed: "Repository konnte nicht deinstalliert werden: {error}",
|
|
1185
|
+
errCatalogRepoInvalidUrl: "Gib eine GitHub-Repository-URL ein.",
|
|
1092
1186
|
},
|
|
1093
1187
|
pluginManageRoles: {
|
|
1094
1188
|
heading: "Benutzerdefinierte Rollen",
|
|
@@ -1143,6 +1237,8 @@ const deMessages = {
|
|
|
1143
1237
|
stop: "■ Stoppen",
|
|
1144
1238
|
playPresentation: "Präsentation abspielen",
|
|
1145
1239
|
regenerateMovie: "Video neu generieren",
|
|
1240
|
+
movieGenerationFailed: "Videoerstellung fehlgeschlagen",
|
|
1241
|
+
retry: "Erneut versuchen",
|
|
1146
1242
|
errPrefix: "⚠ Fehler",
|
|
1147
1243
|
noBeats: "Keine Beats im Skript gefunden",
|
|
1148
1244
|
editSource: "Skript-Quelle bearbeiten",
|