mulmoclaude 1.2.0 → 1.3.0
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/client/assets/{PluginScopedRoot-CjiZ2FJI.js → PluginScopedRoot-B53YSjaC.js} +1 -1
- package/client/assets/index-D3czxq1I.css +2 -0
- package/client/assets/{index-yQkLdtMk.js → index-DUdqhWg6.js} +42 -43
- package/client/assets/{marp-Bs_qwoKZ.js → marp-CyWxL3bc.js} +12 -3
- package/client/index.html +3 -3
- package/package.json +6 -5
- package/server/agent/attachmentConverter.ts +0 -25
- package/server/api/auth/viewToken.ts +10 -8
- package/server/api/routes/agent.ts +35 -10
- package/server/api/routes/collections.ts +150 -96
- package/server/api/routes/files.ts +57 -54
- package/server/api/routes/mulmo-script.ts +257 -895
- package/server/api/routes/wiki/history.ts +17 -19
- package/server/events/collection-change.ts +0 -5
- package/server/events/file-change.ts +1 -6
- package/server/index.ts +25 -76
- package/server/plugins/diagnostics.ts +0 -6
- package/server/plugins/mulmoscript-server.ts +58 -0
- package/server/prompts/system/system.md +2 -2
- package/server/remoteHost/handlers/getCollection.ts +5 -4
- package/server/remoteHost/handlers/googleCalendar.ts +50 -3
- package/server/remoteHost/handlers/index.ts +3 -1
- package/server/utils/files/html-store.ts +2 -16
- package/server/utils/files/journal-io.ts +0 -12
- package/server/utils/files/plugins-io.ts +2 -11
- package/server/utils/files/safe.ts +39 -0
- package/server/utils/httpError.ts +6 -0
- package/server/utils/time.ts +0 -3
- package/server/workspace/collections/index.ts +1 -0
- package/server/workspace/collections/remoteView.ts +13 -4
- package/server/workspace/journal/state.ts +1 -9
- package/server/workspace/memory/topic-index-hook.ts +0 -9
- package/server/workspace/memory/topic-io.ts +0 -4
- package/server/workspace/skills/external/catalog.ts +24 -13
- package/server/workspace/skills/writer.ts +20 -16
- package/server/workspace/wiki-pages/snapshot.ts +13 -12
- package/src/composables/useFileDropZone.ts +3 -15
- package/src/config/apiRoutes.ts +6 -0
- package/src/config/roles.ts +0 -4
- package/src/lang/de.ts +0 -30
- package/src/lang/en.ts +0 -30
- package/src/lang/es.ts +0 -30
- package/src/lang/fr.ts +0 -30
- package/src/lang/ja.ts +0 -30
- package/src/lang/ko.ts +0 -30
- package/src/lang/pt-BR.ts +0 -30
- package/src/lang/zh.ts +0 -30
- package/src/plugins/accounting/index.ts +0 -2
- package/src/plugins/api.ts +0 -6
- package/src/plugins/canvas/index.ts +0 -2
- package/src/plugins/chart/index.ts +0 -2
- package/src/plugins/editImages/index.ts +0 -2
- package/src/plugins/generateImage/index.ts +0 -2
- package/src/plugins/manageSkills/index.ts +0 -2
- package/src/plugins/markdown/index.ts +0 -2
- package/src/plugins/photoLocations/index.ts +0 -2
- package/src/plugins/presentCollection/index.ts +0 -2
- package/src/plugins/presentForm/index.ts +0 -2
- package/src/plugins/presentHtml/index.ts +0 -2
- package/src/plugins/presentMulmoScript/definition.ts +11 -116
- package/src/plugins/presentMulmoScript/index.ts +62 -12
- package/src/plugins/presentSVG/index.ts +0 -2
- package/src/plugins/skill/index.ts +0 -3
- package/src/plugins/spreadsheet/engine/parser.ts +0 -103
- package/src/plugins/spreadsheet/index.ts +0 -2
- package/src/plugins/textResponse/index.ts +0 -3
- package/src/plugins/wiki/index.ts +0 -2
- package/src/types/notification.ts +0 -10
- package/src/utils/api.ts +0 -4
- package/client/assets/index-D5nJbMO1.css +0 -2
- package/server/api/routes/mulmoScriptValidate.ts +0 -101
- package/server/utils/mulmoErrorCapture.ts +0 -93
- package/src/plugins/presentMulmoScript/Preview.vue +0 -23
- package/src/plugins/presentMulmoScript/View.vue +0 -1949
- package/src/plugins/presentMulmoScript/helpers.ts +0 -206
|
@@ -46,8 +46,6 @@ const chartPlugin: ToolPlugin<PresentChartData> = {
|
|
|
46
46
|
viewComponent: wrapWithScope("chart", View as unknown as Component),
|
|
47
47
|
previewComponent: wrapWithScope("chart", Preview as unknown as Component),
|
|
48
48
|
};
|
|
49
|
-
|
|
50
|
-
export default chartPlugin;
|
|
51
49
|
export { TOOL_NAME };
|
|
52
50
|
|
|
53
51
|
export const REGISTRATION: PluginRegistration = {
|
|
@@ -33,8 +33,6 @@ const editImagesPlugin: ToolPlugin<ImageToolData> = {
|
|
|
33
33
|
viewComponent: wrapWithScope("image", View),
|
|
34
34
|
previewComponent: wrapWithScope("image", Preview),
|
|
35
35
|
};
|
|
36
|
-
|
|
37
|
-
export default editImagesPlugin;
|
|
38
36
|
export { TOOL_NAME };
|
|
39
37
|
|
|
40
38
|
export const REGISTRATION: PluginRegistration = {
|
|
@@ -55,8 +55,6 @@ const generateImagePlugin: ToolPlugin<ImageToolData> = {
|
|
|
55
55
|
viewComponent: wrapWithScope("image", View),
|
|
56
56
|
previewComponent: wrapWithScope("image", Preview),
|
|
57
57
|
};
|
|
58
|
-
|
|
59
|
-
export default generateImagePlugin;
|
|
60
58
|
export { TOOL_NAME };
|
|
61
59
|
|
|
62
60
|
export const REGISTRATION: PluginRegistration = {
|
|
@@ -47,8 +47,6 @@ const manageSkillsPlugin: ToolPlugin<ManageSkillsData> = {
|
|
|
47
47
|
viewComponent: wrapWithScope("skills", View),
|
|
48
48
|
previewComponent: wrapWithScope("skills", Preview),
|
|
49
49
|
};
|
|
50
|
-
|
|
51
|
-
export default manageSkillsPlugin;
|
|
52
50
|
export { TOOL_NAME };
|
|
53
51
|
|
|
54
52
|
export const REGISTRATION: PluginRegistration = {
|
|
@@ -52,8 +52,6 @@ const markdownPlugin: ToolPlugin<MarkdownToolData> = {
|
|
|
52
52
|
viewComponent: wrapWithScope("markdown", View as unknown as Component),
|
|
53
53
|
previewComponent: wrapWithScope("markdown", Preview as unknown as Component),
|
|
54
54
|
};
|
|
55
|
-
|
|
56
|
-
export default markdownPlugin;
|
|
57
55
|
export { TOOL_NAME };
|
|
58
56
|
|
|
59
57
|
export const REGISTRATION: PluginRegistration = {
|
|
@@ -30,8 +30,6 @@ const photoLocationsPlugin: ToolPlugin<PhotoLocationsActionData> = {
|
|
|
30
30
|
viewComponent: wrapWithScope("photoLocations", View),
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
-
export default photoLocationsPlugin;
|
|
34
|
-
|
|
35
33
|
export const REGISTRATION: PluginRegistration = {
|
|
36
34
|
toolName: META.toolName,
|
|
37
35
|
entry: photoLocationsPlugin,
|
|
@@ -17,8 +17,6 @@ const presentCollectionPlugin: ToolPlugin<PresentCollectionData, PresentCollecti
|
|
|
17
17
|
viewComponent: wrapWithScope("presentCollection", PresentCollectionView),
|
|
18
18
|
previewComponent: wrapWithScope("presentCollection", PresentCollectionPreview),
|
|
19
19
|
};
|
|
20
|
-
|
|
21
|
-
export default presentCollectionPlugin;
|
|
22
20
|
export { TOOL_NAME };
|
|
23
21
|
|
|
24
22
|
export const REGISTRATION: PluginRegistration = {
|
|
@@ -24,8 +24,6 @@ const presentFormPlugin: ToolPlugin<FormData, FormData, FormArgs> = {
|
|
|
24
24
|
viewComponent: wrapWithScope("form", pkg.viewComponent),
|
|
25
25
|
previewComponent: wrapWithScope("form", pkg.previewComponent),
|
|
26
26
|
};
|
|
27
|
-
|
|
28
|
-
export default presentFormPlugin;
|
|
29
27
|
export { TOOL_NAME };
|
|
30
28
|
|
|
31
29
|
export const REGISTRATION: PluginRegistration = {
|
|
@@ -51,8 +51,6 @@ const presentHtmlPlugin: ToolPlugin<PresentHtmlData> = {
|
|
|
51
51
|
viewComponent: wrapWithScope("html", View as unknown as Component),
|
|
52
52
|
previewComponent: wrapWithScope("html", Preview as unknown as Component),
|
|
53
53
|
};
|
|
54
|
-
|
|
55
|
-
export default presentHtmlPlugin;
|
|
56
54
|
export { TOOL_NAME };
|
|
57
55
|
|
|
58
56
|
export const REGISTRATION: PluginRegistration = {
|
|
@@ -1,122 +1,17 @@
|
|
|
1
|
-
import type { ToolDefinition } from "gui-chat-protocol";
|
|
2
1
|
import { META } from "./meta";
|
|
3
2
|
import type { ResolvedRoute } from "../meta-types";
|
|
3
|
+
import { TOOL_DEFINITION } from "@mulmoclaude/mulmoscript-plugin";
|
|
4
4
|
|
|
5
|
+
// presentMulmoScript's tool schema and save/reopen/update logic now live in
|
|
6
|
+
// the shared @mulmoclaude/mulmoscript-plugin package (single source of truth,
|
|
7
|
+
// also consumable by MulmoTerminal — plans/feat-mulmoscript-plugin.md). This
|
|
8
|
+
// built-in is a thin host adapter: it keeps MulmoClaude's host-specific
|
|
9
|
+
// routing META and View while sourcing the schema from the package.
|
|
5
10
|
export const TOOL_NAME = META.toolName;
|
|
6
|
-
export type MulmoScriptEndpoints = { readonly [K in keyof typeof META.apiRoutes]: ResolvedRoute };
|
|
7
|
-
|
|
8
|
-
const toolDefinition: ToolDefinition = {
|
|
9
|
-
type: "function",
|
|
10
|
-
name: META.toolName,
|
|
11
|
-
description: `Save and present a MulmoScript story or presentation as a visual storyboard in the canvas.
|
|
12
|
-
|
|
13
|
-
Two modes — provide EXACTLY ONE of \`script\` or \`filePath\`:
|
|
14
|
-
|
|
15
|
-
1. **Create new** — pass \`script\` (full MulmoScript JSON). Server saves it to disk and presents it.
|
|
16
|
-
2. **Re-display existing** — pass \`filePath\` (workspace-relative path returned by a previous call, e.g. "stories/my-story-1700000000000.json"). Much cheaper than re-sending the full script. Use whenever the user wants to revisit a presentation that was already created in this workspace.
|
|
17
|
-
|
|
18
|
-
Optional \`autoGenerateMovie: true\` kicks off movie generation in the background, so the final video is ready by the time the user opens the canvas. Movie generation is expensive (multiple image + audio API calls + video encoding) — only set this when the user has explicitly asked for the movie. Default \`false\`.
|
|
19
11
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
- \`movieParams.provider\`: \`"google"\`
|
|
24
|
-
- Do NOT add a top-level \`provider\` field to \`speechParams\` — provider belongs per-speaker only.
|
|
25
|
-
|
|
26
|
-
Required structure:
|
|
27
|
-
|
|
28
|
-
{
|
|
29
|
-
"$mulmocast": { "version": "1.1" },
|
|
30
|
-
"title": "The Life of a Star",
|
|
31
|
-
"description": "A short educational explainer about stellar evolution",
|
|
32
|
-
"lang": "en",
|
|
33
|
-
"speechParams": {
|
|
34
|
-
"speakers": {
|
|
35
|
-
"Presenter": {
|
|
36
|
-
"provider": "gemini",
|
|
37
|
-
"voiceId": "Kore",
|
|
38
|
-
"displayName": { "en": "Presenter" }
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
},
|
|
42
|
-
"imageParams": { "provider": "google", "model": "gemini-3.1-flash-image-preview" },
|
|
43
|
-
"movieParams": { "provider": "google", "model": "veo-3.1-generate" },
|
|
44
|
-
"beats": [
|
|
45
|
-
{
|
|
46
|
-
"speaker": "Presenter",
|
|
47
|
-
"text": "Narration spoken aloud for this beat.",
|
|
48
|
-
"imagePrompt": "Detailed description — AI generates the image"
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
"speaker": "Presenter",
|
|
52
|
-
"text": "Bullet point beat.",
|
|
53
|
-
"image": { "type": "textSlide", "slide": { "title": "Slide Title", "bullets": ["Point one", "Point two"] } }
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
"speaker": "Presenter",
|
|
57
|
-
"text": "Markdown beat.",
|
|
58
|
-
"image": { "type": "markdown", "markdown": "## Heading\\n\\nBody text here." }
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
"speaker": "Presenter",
|
|
62
|
-
"text": "Chart beat — use for data, comparisons, trends.",
|
|
63
|
-
"image": { "type": "chart", "title": "Chart Title", "chartData": { "type": "bar", "data": { "labels": ["A", "B", "C"], "datasets": [{ "label": "Series", "data": [10, 20, 30] }] } } }
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
"speaker": "Presenter",
|
|
67
|
-
"text": "Diagram beat — use for flows, architectures, relationships.",
|
|
68
|
-
"image": { "type": "mermaid", "title": "Diagram Title", "code": { "kind": "text", "text": "graph TD\\n A[Start] --> B[Process] --> C[End]" } }
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
"speaker": "Presenter",
|
|
72
|
-
"text": "Rich interactive beat — use for custom layouts, animations, or anything that benefits from HTML/CSS.",
|
|
73
|
-
"image": { "type": "html_tailwind", "html": "<div class=\\"flex items-center justify-center h-full text-4xl font-bold text-blue-600\\">Hello World</div>" }
|
|
74
|
-
},
|
|
75
|
-
{
|
|
76
|
-
"speaker": "Presenter",
|
|
77
|
-
"text": "AI video beat.",
|
|
78
|
-
"moviePrompt": "Detailed description — AI generates the video clip"
|
|
79
|
-
}
|
|
80
|
-
]
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
Beat visual options (choose one per beat):
|
|
84
|
-
- "imagePrompt": "..." → top-level string field — AI generates an image from the prompt
|
|
85
|
-
- "moviePrompt": "..." → top-level string field — AI generates a video clip from the prompt
|
|
86
|
-
- "image": { "type": "textSlide", "slide": { "title", "subtitle"?, "bullets"? } }
|
|
87
|
-
- "image": { "type": "markdown", "markdown": "..." }
|
|
88
|
-
- "image": { "type": "chart", "title": "...", "chartData": { "type": "bar"|"line"|"pie"|..., "data": { "labels": [...], "datasets": [...] } } } ← PREFER for data/numbers/comparisons. chartData is a full Chart.js config: labels/datasets go under "data", not at the top level.
|
|
89
|
-
- "image": { "type": "mermaid", "title": "...", "code": { "kind": "text", "text": "..." } } ← PREFER for flows/diagrams/relationships
|
|
90
|
-
- "image": { "type": "html_tailwind", "html": "...", "script"?: "..." } ← PREFER for rich layouts, animations, custom visuals
|
|
91
|
-
|
|
92
|
-
IMPORTANT: "imagePrompt" and "moviePrompt" are plain string fields on the beat, NOT nested under "image".`,
|
|
93
|
-
parameters: {
|
|
94
|
-
type: "object",
|
|
95
|
-
properties: {
|
|
96
|
-
script: {
|
|
97
|
-
type: "object",
|
|
98
|
-
description:
|
|
99
|
-
"Complete MulmoScript JSON for a NEW presentation. Must include $mulmocast, speechParams, imageParams, movieParams, and beats array. Always populate the top-level 'description' field with a concise 1–2 sentence summary of the presentation. Do NOT pass alongside `filePath`.",
|
|
100
|
-
additionalProperties: true,
|
|
101
|
-
},
|
|
102
|
-
filename: {
|
|
103
|
-
type: "string",
|
|
104
|
-
description:
|
|
105
|
-
"Optional filename without extension. Defaults to a slug of the script title. Only meaningful with `script`; ignored when `filePath` is given.",
|
|
106
|
-
},
|
|
107
|
-
filePath: {
|
|
108
|
-
type: "string",
|
|
109
|
-
description:
|
|
110
|
-
"Workspace-relative path to an EXISTING MulmoScript JSON file (e.g. 'stories/my-story-1700000000000.json'). Use this to re-display a script previously saved in this workspace, instead of resending the full JSON. Do NOT pass alongside `script`.",
|
|
111
|
-
},
|
|
112
|
-
autoGenerateMovie: {
|
|
113
|
-
type: "boolean",
|
|
114
|
-
description:
|
|
115
|
-
"When true, the server starts movie generation in the background after save/load. The user does NOT need to open the canvas — progress streams via the existing session channel. Default false. Only set true when the user has explicitly asked for the movie; generation is expensive.",
|
|
116
|
-
},
|
|
117
|
-
},
|
|
118
|
-
required: [],
|
|
119
|
-
},
|
|
120
|
-
};
|
|
12
|
+
/** Resolved-URL view of the mulmoScript plugin's routes. Plugin code reads
|
|
13
|
+
* `endpoints.<route>.{method, url}` to drive `apiCall`. Auto-derived from META. */
|
|
14
|
+
export type MulmoScriptEndpoints = { readonly [K in keyof typeof META.apiRoutes]: ResolvedRoute };
|
|
121
15
|
|
|
122
|
-
export
|
|
16
|
+
export { TOOL_DEFINITION };
|
|
17
|
+
export default TOOL_DEFINITION;
|
|
@@ -1,21 +1,73 @@
|
|
|
1
|
+
// MulmoClaude's thin built-in adapter for the shared mulmoscript plugin
|
|
2
|
+
// (plans/feat-mulmoscript-plugin.md phase 2). View / Preview /
|
|
3
|
+
// TOOL_DEFINITION come from @mulmoclaude/mulmoscript-plugin; the View
|
|
4
|
+
// reaches host backends via useRuntime().dispatch → the built-in
|
|
5
|
+
// "mulmoScript" dispatch handler (server/plugins/mulmoscript-server.ts)
|
|
6
|
+
// and hears generation progress on the plugin pubsub channel. This adapter
|
|
7
|
+
// keeps MulmoClaude's existing tool-call create path (POST
|
|
8
|
+
// /api/mulmoScript/save) and injects the two host-transport capabilities
|
|
9
|
+
// the generic runtime can't carry: the active chat session id (sidebar
|
|
10
|
+
// generation indicator) and the bearer-authenticated media download.
|
|
11
|
+
import { computed, defineComponent, h, markRaw, provide, type Component } from "vue";
|
|
1
12
|
import type { PluginRegistration, ToolPlugin } from "../../tools/types";
|
|
2
13
|
import type { ToolResult } from "gui-chat-protocol";
|
|
3
|
-
import type
|
|
14
|
+
import { View, Preview, MULMOSCRIPT_HOST_ADAPTER_KEY, type MulmoScriptData, type MulmoScriptHostAdapter } from "@mulmoclaude/mulmoscript-plugin/vue";
|
|
15
|
+
// Lib mode doesn't auto-inject the package's compiled styles; the consumer
|
|
16
|
+
// must import them — same as @mulmoclaude/{markdown,form,chart,html}-plugin.
|
|
17
|
+
import "@mulmoclaude/mulmoscript-plugin/style.css";
|
|
4
18
|
import toolDefinition, { TOOL_NAME, type MulmoScriptEndpoints } from "./definition";
|
|
5
19
|
import { pluginEndpoints } from "../api";
|
|
6
20
|
import { wrapWithScope } from "../scope";
|
|
7
|
-
import
|
|
8
|
-
import Preview from "./Preview.vue";
|
|
9
|
-
import { apiCall } from "../../utils/api";
|
|
21
|
+
import { apiCall, apiFetchRaw } from "../../utils/api";
|
|
10
22
|
import { makeUuid } from "../../utils/id";
|
|
23
|
+
import { useActiveSession } from "../../composables/useActiveSession";
|
|
11
24
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
25
|
+
// Re-exported from the shared package so anything importing the result-data
|
|
26
|
+
// shape from "./index" keeps working while the type stays single-sourced.
|
|
27
|
+
export type { MulmoScriptData };
|
|
28
|
+
|
|
29
|
+
// Bearer-authenticated media download over the host's existing
|
|
30
|
+
// download routes. A plain <video src> / <a href download> can't attach
|
|
31
|
+
// the Authorization header, and the routes stay behind the standard
|
|
32
|
+
// /api/* bearer guard by explicit review decision — so the package View
|
|
33
|
+
// fetches bytes through this injected capability instead.
|
|
34
|
+
async function fetchMediaBlob(query: { moviePath?: string; pdfPath?: string }): Promise<Blob> {
|
|
35
|
+
const endpoints = pluginEndpoints<MulmoScriptEndpoints>("mulmoScript");
|
|
36
|
+
const target = query.pdfPath
|
|
37
|
+
? { url: endpoints.downloadPdf.url, query: { pdfPath: query.pdfPath } }
|
|
38
|
+
: { url: endpoints.downloadMovie.url, query: { moviePath: query.moviePath ?? "" } };
|
|
39
|
+
const res = await apiFetchRaw(target.url, { method: "GET", query: target.query });
|
|
40
|
+
if (!res.ok) {
|
|
41
|
+
throw new Error(`HTTP ${res.status}`);
|
|
42
|
+
}
|
|
43
|
+
return res.blob();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Provide the package's host-adapter injection around the View —
|
|
47
|
+
* mounted INSIDE wrapWithScope's PluginScopedRoot, forwarding every
|
|
48
|
+
* prop / attr / slot through verbatim (same shape as wrapWithScope). */
|
|
49
|
+
function withHostAdapter<TInner extends Component>(inner: TInner): TInner {
|
|
50
|
+
return markRaw(
|
|
51
|
+
defineComponent({
|
|
52
|
+
name: "MulmoScriptHostAdapter",
|
|
53
|
+
inheritAttrs: false,
|
|
54
|
+
setup(_props, { attrs, slots }) {
|
|
55
|
+
const activeSessionRef = useActiveSession();
|
|
56
|
+
const adapter: MulmoScriptHostAdapter = {
|
|
57
|
+
chatSessionId: computed(() => activeSessionRef?.value?.id),
|
|
58
|
+
fetchMediaBlob,
|
|
59
|
+
};
|
|
60
|
+
provide(MULMOSCRIPT_HOST_ADAPTER_KEY, adapter);
|
|
61
|
+
return () => h(inner, attrs, slots);
|
|
62
|
+
},
|
|
63
|
+
}),
|
|
64
|
+
) as unknown as TInner;
|
|
15
65
|
}
|
|
16
66
|
|
|
17
67
|
const presentMulmoScriptPlugin: ToolPlugin<MulmoScriptData> = {
|
|
18
|
-
|
|
68
|
+
// gui-chat-protocol type is externalized but yarn-4's dual-@vue can
|
|
69
|
+
// make the package's nominal types distinct; coerce once here.
|
|
70
|
+
toolDefinition: toolDefinition as ToolPlugin<MulmoScriptData>["toolDefinition"],
|
|
19
71
|
|
|
20
72
|
// Pass-through: the agent (MCP) and GUI dispatcher both end up at the
|
|
21
73
|
// same backend route, which dispatches between create-new (`script`)
|
|
@@ -42,12 +94,10 @@ const presentMulmoScriptPlugin: ToolPlugin<MulmoScriptData> = {
|
|
|
42
94
|
|
|
43
95
|
isEnabled: () => true,
|
|
44
96
|
generatingMessage: "Generating MulmoScript storyboard…",
|
|
45
|
-
viewComponent: wrapWithScope("mulmoScript", View),
|
|
46
|
-
previewComponent: wrapWithScope("mulmoScript", Preview),
|
|
97
|
+
viewComponent: wrapWithScope("mulmoScript", withHostAdapter(View as unknown as Component)),
|
|
98
|
+
previewComponent: wrapWithScope("mulmoScript", Preview as unknown as Component),
|
|
47
99
|
};
|
|
48
100
|
|
|
49
|
-
export default presentMulmoScriptPlugin;
|
|
50
|
-
|
|
51
101
|
export const REGISTRATION: PluginRegistration = {
|
|
52
102
|
toolName: TOOL_NAME,
|
|
53
103
|
entry: presentMulmoScriptPlugin,
|
|
@@ -39,8 +39,6 @@ const presentSvgPlugin: ToolPlugin<PresentSvgData> = {
|
|
|
39
39
|
viewComponent: wrapWithScope("svg", View),
|
|
40
40
|
previewComponent: wrapWithScope("svg", Preview),
|
|
41
41
|
};
|
|
42
|
-
|
|
43
|
-
export default presentSvgPlugin;
|
|
44
42
|
export { TOOL_NAME };
|
|
45
43
|
|
|
46
44
|
export const REGISTRATION: PluginRegistration = {
|
|
@@ -38,106 +38,3 @@ export function indexToColumn(index: number): string {
|
|
|
38
38
|
}
|
|
39
39
|
return col;
|
|
40
40
|
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Parse a cell reference to its components
|
|
44
|
-
* Supports: A1, $A$1, $A1, A$1, Sheet1!A1, 'My Sheet'!A1
|
|
45
|
-
*
|
|
46
|
-
* @param ref - Cell reference string
|
|
47
|
-
* @returns Parsed cell reference object
|
|
48
|
-
*/
|
|
49
|
-
export function parseCellRef(ref: string): CellRef {
|
|
50
|
-
let cellRef = ref;
|
|
51
|
-
let sheetName: string | undefined;
|
|
52
|
-
|
|
53
|
-
// Check for cross-sheet reference (e.g., 'Sheet Name'!B2 or Sheet1!B2)
|
|
54
|
-
const sheetMatch = ref.match(/^(?:'([^']+)'|([^!]+))!(.+)$/);
|
|
55
|
-
if (sheetMatch) {
|
|
56
|
-
sheetName = sheetMatch[1] || sheetMatch[2]; // Quoted or unquoted sheet name
|
|
57
|
-
cellRef = sheetMatch[3]; // Cell reference part
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Parse absolute references ($A$1)
|
|
61
|
-
const absoluteRow = cellRef.includes("$") && cellRef.match(/\$\d+/);
|
|
62
|
-
const absoluteCol = cellRef.includes("$") && cellRef.match(/\$[A-Z]+/);
|
|
63
|
-
|
|
64
|
-
// Remove $ symbols
|
|
65
|
-
const cleanRef = cellRef.replace(/\$/g, "");
|
|
66
|
-
const match = cleanRef.match(/^([A-Z]+)(\d+)$/);
|
|
67
|
-
|
|
68
|
-
if (!match) {
|
|
69
|
-
throw new Error(`Invalid cell reference: ${ref}`);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const col = columnToIndex(match[1]);
|
|
73
|
-
const row = parseInt(match[2]) - 1; // 1-indexed to 0-indexed
|
|
74
|
-
|
|
75
|
-
const result: CellRef = { row, col };
|
|
76
|
-
|
|
77
|
-
if (sheetName) {
|
|
78
|
-
result.sheet = sheetName;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if (absoluteRow || absoluteCol) {
|
|
82
|
-
result.absolute = {
|
|
83
|
-
row: !!absoluteRow,
|
|
84
|
-
col: !!absoluteCol,
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
return result;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Parse a range reference to its components
|
|
93
|
-
* Supports: A1:B10, $A$1:$B$10, Sheet1!A1:B10
|
|
94
|
-
*
|
|
95
|
-
* @param range - Range reference string
|
|
96
|
-
* @returns Parsed range reference object
|
|
97
|
-
*/
|
|
98
|
-
export function parseRangeRef(range: string): RangeRef {
|
|
99
|
-
// Use non-greedy match to improve performance
|
|
100
|
-
const colonIndex = range.lastIndexOf(":");
|
|
101
|
-
if (colonIndex === -1) {
|
|
102
|
-
throw new Error(`Invalid range reference: ${range}`);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
const start = parseCellRef(range.substring(0, colonIndex));
|
|
106
|
-
const end = parseCellRef(range.substring(colonIndex + 1));
|
|
107
|
-
|
|
108
|
-
return { start, end };
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Convert a cell reference object back to A1 notation
|
|
113
|
-
*
|
|
114
|
-
* @param ref - Cell reference object
|
|
115
|
-
* @returns A1 notation string
|
|
116
|
-
*/
|
|
117
|
-
export function cellRefToA1(ref: CellRef): string {
|
|
118
|
-
const col = indexToColumn(ref.col);
|
|
119
|
-
const row = ref.row + 1; // 0-based to 1-based
|
|
120
|
-
|
|
121
|
-
let result = "";
|
|
122
|
-
|
|
123
|
-
if (ref.absolute?.col) {
|
|
124
|
-
result += "$";
|
|
125
|
-
}
|
|
126
|
-
result += col;
|
|
127
|
-
|
|
128
|
-
if (ref.absolute?.row) {
|
|
129
|
-
result += "$";
|
|
130
|
-
}
|
|
131
|
-
result += row;
|
|
132
|
-
|
|
133
|
-
if (ref.sheet) {
|
|
134
|
-
// Quote sheet name if it contains spaces
|
|
135
|
-
if (ref.sheet.includes(" ")) {
|
|
136
|
-
result = `'${ref.sheet}'!${result}`;
|
|
137
|
-
} else {
|
|
138
|
-
result = `${ref.sheet}!${result}`;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
return result;
|
|
143
|
-
}
|
|
@@ -34,8 +34,6 @@ const spreadsheetPlugin: ToolPlugin<SpreadsheetToolData> = {
|
|
|
34
34
|
viewComponent: wrapWithScope("spreadsheet", View),
|
|
35
35
|
previewComponent: wrapWithScope("spreadsheet", Preview),
|
|
36
36
|
};
|
|
37
|
-
|
|
38
|
-
export default spreadsheetPlugin;
|
|
39
37
|
export { TOOL_NAME };
|
|
40
38
|
|
|
41
39
|
export const REGISTRATION: PluginRegistration = {
|
|
@@ -25,16 +25,6 @@ export const NOTIFICATION_KINDS = {
|
|
|
25
25
|
|
|
26
26
|
export type NotificationKind = (typeof NOTIFICATION_KINDS)[keyof typeof NOTIFICATION_KINDS];
|
|
27
27
|
|
|
28
|
-
export const NOTIFICATION_ICONS: Record<NotificationKind, string> = {
|
|
29
|
-
todo: "check_circle",
|
|
30
|
-
scheduler: "event",
|
|
31
|
-
agent: "smart_toy",
|
|
32
|
-
journal: "auto_stories",
|
|
33
|
-
push: "notifications",
|
|
34
|
-
bridge: "chat",
|
|
35
|
-
system: "warning",
|
|
36
|
-
};
|
|
37
|
-
|
|
38
28
|
export const NOTIFICATION_ACTION_TYPES = {
|
|
39
29
|
navigate: "navigate",
|
|
40
30
|
none: "none",
|
package/src/utils/api.ts
CHANGED
|
@@ -226,10 +226,6 @@ export function apiPut<T = unknown>(path: string, body?: unknown, extra: Omit<Ap
|
|
|
226
226
|
return apiCall<T>(path, { ...extra, method: "PUT", body });
|
|
227
227
|
}
|
|
228
228
|
|
|
229
|
-
export function apiPatch<T = unknown>(path: string, body?: unknown, extra: Omit<ApiOptions, "method" | "body"> = {}): Promise<ApiResult<T>> {
|
|
230
|
-
return apiCall<T>(path, { ...extra, method: "PATCH", body });
|
|
231
|
-
}
|
|
232
|
-
|
|
233
229
|
export function apiDelete<T = unknown>(path: string, body?: unknown, extra: Omit<ApiOptions, "method" | "body"> = {}): Promise<ApiResult<T>> {
|
|
234
230
|
return apiCall<T>(path, { ...extra, method: "DELETE", body });
|
|
235
231
|
}
|