mulmoclaude 2.7.0 → 2.8.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.
Files changed (77) hide show
  1. package/client/assets/Graph-ChAxkn9o.js +1 -0
  2. package/client/assets/dist-Bij44LdC.js +2 -0
  3. package/client/assets/echarts-GV3U9sVf.js +1 -0
  4. package/client/assets/echarts-gl-BXx4On0Y.js +4282 -0
  5. package/client/assets/echarts-wordcloud-_9uQUAfp.js +1 -0
  6. package/client/assets/emscripten-module-Q67P5WYC-BU3Hlttz.js +2160 -0
  7. package/client/assets/ffi-4V2b7xu3.js +1 -0
  8. package/client/assets/{index-lkpgbKtk.js → index-D6xzCZhP.js} +600 -589
  9. package/client/assets/index-DzMsXDnj.css +2 -0
  10. package/client/assets/{install-wxcddUsO.js → install-C1moNcrn.js} +1 -1
  11. package/client/assets/{marp-DcTywifN.js → marp-Du5Sym5b.js} +1 -1
  12. package/client/assets/module-ES6BEMUI-CDTIpMiA.js +6 -0
  13. package/client/index.html +4 -3
  14. package/package.json +5 -4
  15. package/server/api/routes/plugins.ts +8 -59
  16. package/server/build/mcp-server.mjs +609 -608
  17. package/server/index.ts +1 -0
  18. package/server/plugins/confined-file-ops.ts +136 -0
  19. package/server/plugins/runtime.ts +8 -115
  20. package/server/plugins/spreadsheet-builtin.ts +26 -0
  21. package/server/plugins/spreadsheet-save-outcome.ts +7 -0
  22. package/server/utils/files/store-resolvers.ts +1 -1
  23. package/src/lang/de.ts +0 -20
  24. package/src/lang/en.ts +0 -20
  25. package/src/lang/es.ts +0 -20
  26. package/src/lang/fr.ts +0 -20
  27. package/src/lang/ja.ts +0 -20
  28. package/src/lang/ko.ts +0 -20
  29. package/src/lang/pt-BR.ts +0 -20
  30. package/src/lang/zh.ts +0 -20
  31. package/src/plugins/spreadsheet/definition.ts +9 -127
  32. package/src/plugins/spreadsheet/index.ts +7 -4
  33. package/src/plugins/spreadsheet/meta.ts +2 -4
  34. package/client/assets/echarts-gl-Cq76Z6DA.js +0 -4282
  35. package/client/assets/index-Cz7JLE0k.css +0 -2
  36. package/server/utils/files/spreadsheet-store.ts +0 -26
  37. package/src/plugins/spreadsheet/Preview.vue +0 -31
  38. package/src/plugins/spreadsheet/View.vue +0 -1007
  39. package/src/plugins/spreadsheet/cellHighlights.ts +0 -78
  40. package/src/plugins/spreadsheet/engine/calculator.ts +0 -427
  41. package/src/plugins/spreadsheet/engine/cellBuilder.ts +0 -89
  42. package/src/plugins/spreadsheet/engine/cellEmpty.ts +0 -26
  43. package/src/plugins/spreadsheet/engine/cellFormatting.ts +0 -59
  44. package/src/plugins/spreadsheet/engine/coerce-boolean.ts +0 -26
  45. package/src/plugins/spreadsheet/engine/condition.ts +0 -182
  46. package/src/plugins/spreadsheet/engine/date-locale.ts +0 -47
  47. package/src/plugins/spreadsheet/engine/date-parser.ts +0 -234
  48. package/src/plugins/spreadsheet/engine/date-utils.ts +0 -73
  49. package/src/plugins/spreadsheet/engine/datedif.ts +0 -93
  50. package/src/plugins/spreadsheet/engine/engine.ts +0 -177
  51. package/src/plugins/spreadsheet/engine/evaluator.ts +0 -494
  52. package/src/plugins/spreadsheet/engine/financial-math.ts +0 -114
  53. package/src/plugins/spreadsheet/engine/formatter.ts +0 -158
  54. package/src/plugins/spreadsheet/engine/formulaError.ts +0 -67
  55. package/src/plugins/spreadsheet/engine/formulaRefs.ts +0 -202
  56. package/src/plugins/spreadsheet/engine/functions/date.ts +0 -212
  57. package/src/plugins/spreadsheet/engine/functions/financial.ts +0 -244
  58. package/src/plugins/spreadsheet/engine/functions/index.ts +0 -16
  59. package/src/plugins/spreadsheet/engine/functions/logical.ts +0 -221
  60. package/src/plugins/spreadsheet/engine/functions/lookup-math.ts +0 -28
  61. package/src/plugins/spreadsheet/engine/functions/lookup.ts +0 -257
  62. package/src/plugins/spreadsheet/engine/functions/mathematical.ts +0 -283
  63. package/src/plugins/spreadsheet/engine/functions/statistical-math.ts +0 -91
  64. package/src/plugins/spreadsheet/engine/functions/statistical.ts +0 -290
  65. package/src/plugins/spreadsheet/engine/functions/text.ts +0 -398
  66. package/src/plugins/spreadsheet/engine/index.ts +0 -34
  67. package/src/plugins/spreadsheet/engine/jsonCellLocator.ts +0 -111
  68. package/src/plugins/spreadsheet/engine/math-ops.ts +0 -98
  69. package/src/plugins/spreadsheet/engine/numericCoercion.ts +0 -61
  70. package/src/plugins/spreadsheet/engine/parser.ts +0 -40
  71. package/src/plugins/spreadsheet/engine/registry.ts +0 -201
  72. package/src/plugins/spreadsheet/engine/responseDecoder.ts +0 -68
  73. package/src/plugins/spreadsheet/engine/spreadsheet-errors.ts +0 -82
  74. package/src/plugins/spreadsheet/engine/textFormat.ts +0 -108
  75. package/src/plugins/spreadsheet/engine/translateFormula.ts +0 -69
  76. package/src/plugins/spreadsheet/engine/types.ts +0 -81
  77. package/src/plugins/spreadsheet/keyboardNav.ts +0 -38
@@ -1,82 +0,0 @@
1
- /**
2
- * Formula errors as a distinct VALUE type.
3
- *
4
- * A `#NUM!` produced by `SQRT(-1)` and the text `"#NUM!"` produced by
5
- * `CONCAT("#N","UM!")` used to be the same string, so IFERROR could not tell a
6
- * real error from text that merely spells one (#2451). An error is now its own
7
- * value carrying the code, which is what the error-aware functions check; the
8
- * display pass renders it back to `#NUM!` so cells look unchanged.
9
- */
10
-
11
- export const SPREADSHEET_ERRORS = ["#NULL!", "#DIV/0!", "#VALUE!", "#REF!", "#NAME?", "#NUM!", "#N/A", "#ERROR!"] as const;
12
-
13
- export type SpreadsheetErrorCode = (typeof SPREADSHEET_ERRORS)[number];
14
-
15
- /** A formula error, distinct from any string. `toString` yields the code so the
16
- * value renders as `#NUM!` wherever the engine coerces a cell value to text. */
17
- export class SpreadsheetError {
18
- constructor(readonly code: SpreadsheetErrorCode) {}
19
-
20
- toString(): string {
21
- return this.code;
22
- }
23
-
24
- toJSON(): string {
25
- return this.code;
26
- }
27
- }
28
-
29
- export const NULL_ERROR = new SpreadsheetError("#NULL!");
30
- export const DIV_ZERO_ERROR = new SpreadsheetError("#DIV/0!");
31
- export const VALUE_ERROR = new SpreadsheetError("#VALUE!");
32
- export const REF_ERROR = new SpreadsheetError("#REF!");
33
- export const NAME_ERROR = new SpreadsheetError("#NAME?");
34
- export const NUM_ERROR = new SpreadsheetError("#NUM!");
35
- export const NA_ERROR = new SpreadsheetError("#N/A");
36
- export const UNKNOWN_ERROR = new SpreadsheetError("#ERROR!");
37
-
38
- // One instance per code: two errors of the same kind compare equal, which is how
39
- // error strings behaved and what the condition/comparison paths still rely on.
40
- const ERROR_VALUES: Record<SpreadsheetErrorCode, SpreadsheetError> = {
41
- "#NULL!": NULL_ERROR,
42
- "#DIV/0!": DIV_ZERO_ERROR,
43
- "#VALUE!": VALUE_ERROR,
44
- "#REF!": REF_ERROR,
45
- "#NAME?": NAME_ERROR,
46
- "#NUM!": NUM_ERROR,
47
- "#N/A": NA_ERROR,
48
- "#ERROR!": UNKNOWN_ERROR,
49
- };
50
-
51
- /** The error value for a code. */
52
- export const spreadsheetError = (code: SpreadsheetErrorCode): SpreadsheetError => ERROR_VALUES[code];
53
-
54
- const errorSet: ReadonlySet<string> = new Set(SPREADSHEET_ERRORS);
55
-
56
- /** Whether a value is one of the error CODES as a plain string. Text that spells
57
- * an error is not an error value — see `isSpreadsheetErrorValue`. */
58
- export function isSpreadsheetError(value: unknown): value is SpreadsheetErrorCode {
59
- return typeof value === "string" && errorSet.has(value);
60
- }
61
-
62
- /** Whether a value IS a formula error, as opposed to text that spells one. */
63
- export function isSpreadsheetErrorValue(value: unknown): value is SpreadsheetError {
64
- return value instanceof SpreadsheetError;
65
- }
66
-
67
- /** The code behind a value: an error value's own code, or the code a plain
68
- * string spells. Used where a literal `#REF!` written into a cell must still
69
- * poison the arithmetic that reads it, provenance aside. */
70
- export function errorCodeOf(value: unknown): SpreadsheetErrorCode | null {
71
- if (isSpreadsheetErrorValue(value)) return value.code;
72
- return isSpreadsheetError(value) ? value : null;
73
- }
74
-
75
- /** Whether an evaluated result should be treated as an error: a formula error
76
- * VALUE, a NaN / infinite number, or a missing value. This is what IFERROR
77
- * catches — deliberately NOT a look-alike string, which is ordinary text. */
78
- export function isErrorResult(value: unknown): boolean {
79
- if (value === null || value === undefined) return true;
80
- if (typeof value === "number") return Number.isNaN(value) || !Number.isFinite(value);
81
- return isSpreadsheetErrorValue(value);
82
- }
@@ -1,108 +0,0 @@
1
- /**
2
- * Excel number-format patterns for the TEXT function.
3
- *
4
- * Deliberately separate from `formatter.formatNumber`, which renders CELL
5
- * display values: the two disagree on defaults — Excel's `TEXT(0.5,"0%")` is
6
- * `"50%"`, while a cell carrying the format `0%` has always displayed
7
- * `"50.00%"` — so sharing the whole path would move every formatted cell in
8
- * every stored workbook. Only the digit-grouping primitive is shared.
9
- */
10
-
11
- import { groupThousands } from "./formatter";
12
-
13
- const PERCENT_SCALE = 100;
14
-
15
- // Characters that introduce an Excel format feature this module does not
16
- // render (quoted literals, fill/skip, fractions, dates, text placeholder,
17
- // negative/zero sections). Seeing one means the caller keeps its own fallback.
18
- const UNSUPPORTED_LITERAL_CHARS = `?\\*_[]"@;/`;
19
-
20
- // One run of digit placeholders, optionally carrying grouping commas and a
21
- // decimal point: the `#,##0.00` family.
22
- const NUMERIC_CORE_RE = /[#0][#0,.]*/;
23
- const PLACEHOLDER_RE = /[#0]/;
24
- const TRAILING_ZEROS_RE = /0+$/;
25
-
26
- export interface NumberPattern {
27
- prefix: string;
28
- suffix: string;
29
- useGrouping: boolean;
30
- integerMinDigits: number;
31
- minDecimals: number;
32
- maxDecimals: number;
33
- isPercent: boolean;
34
- }
35
-
36
- const countOf = (text: string, chars: string): number => Array.from(text).filter((char) => chars.includes(char)).length;
37
-
38
- const hasUnsupportedLiteral = (text: string): boolean => Array.from(text).some((char) => UNSUPPORTED_LITERAL_CHARS.includes(char));
39
-
40
- /**
41
- * Split a format code into a leading literal, one numeric core and a trailing
42
- * literal, or `null` when the code uses a feature this module does not render.
43
- */
44
- export const parseNumberPattern = (pattern: string): NumberPattern | null => {
45
- const core = NUMERIC_CORE_RE.exec(pattern);
46
- if (!core) return null;
47
- // A comma AFTER the last placeholder scales by a thousand in Excel.
48
- if (core[0].endsWith(",")) return null;
49
-
50
- const prefix = pattern.slice(0, core.index);
51
- const suffix = pattern.slice(core.index + core[0].length);
52
- // A second placeholder run (`0.00E+00`, `# ?/?`) is a format of its own kind.
53
- if (PLACEHOLDER_RE.test(suffix)) return null;
54
- if (hasUnsupportedLiteral(prefix) || hasUnsupportedLiteral(suffix)) return null;
55
-
56
- const [integerPart, decimalPart = "", ...extraParts] = core[0].split(".");
57
- if (integerPart === undefined || extraParts.length > 0) return null;
58
-
59
- return {
60
- prefix,
61
- suffix,
62
- useGrouping: integerPart.includes(","),
63
- integerMinDigits: countOf(integerPart, "0"),
64
- minDecimals: countOf(decimalPart, "0"),
65
- maxDecimals: countOf(decimalPart, "#0"),
66
- isPercent: prefix.includes("%") || suffix.includes("%"),
67
- };
68
- };
69
-
70
- // `0` keeps a decimal digit, `#` drops it once it is a trailing zero — so
71
- // `0.0#` renders 0.5 as "0.5" but 0.25 as "0.25".
72
- const trimOptionalZeros = (decimals: string, minDecimals: number): string => {
73
- const kept = decimals.replace(TRAILING_ZEROS_RE, "");
74
- return kept.length >= minDecimals ? kept : decimals.slice(0, minDecimals);
75
- };
76
-
77
- const renderDigits = (absValue: number, pattern: NumberPattern): string => {
78
- const fixed = absValue.toFixed(pattern.maxDecimals);
79
- const point = fixed.indexOf(".");
80
- const wholeDigits = point === -1 ? fixed : fixed.slice(0, point);
81
- const decimalDigits = point === -1 ? "" : fixed.slice(point + 1);
82
- const padded = wholeDigits.padStart(pattern.integerMinDigits, "0");
83
- const whole = pattern.useGrouping ? groupThousands(padded) : padded;
84
- const decimals = trimOptionalZeros(decimalDigits, pattern.minDecimals);
85
- return decimals ? `${whole}.${decimals}` : whole;
86
- };
87
-
88
- const isZeroText = (digits: string): boolean => Array.from(digits).every((char) => char === "0" || char === "," || char === ".");
89
-
90
- /**
91
- * Render a number the way Excel's TEXT does for the common numeric format
92
- * codes: `#,##0` grouping, `0.00` fixed decimals, `0.##` optional decimals, a
93
- * literal prefix/suffix such as `$`, and a `%` that scales by 100.
94
- *
95
- * Returns `null` for a format code it does not render, so the caller can keep
96
- * its own fallback rather than inventing a plausible wrong string.
97
- */
98
- export const formatWithPattern = (value: number, pattern: string): string | null => {
99
- if (!Number.isFinite(value)) return null;
100
- const spec = parseNumberPattern(pattern);
101
- if (!spec) return null;
102
-
103
- const scaled = spec.isPercent ? value * PERCENT_SCALE : value;
104
- const digits = renderDigits(Math.abs(scaled), spec);
105
- // The sign follows the ROUNDED digits: -0.001 under "0.00" reads "0.00", not "-0.00".
106
- const sign = scaled < 0 && !isZeroText(digits) ? "-" : "";
107
- return `${sign}${spec.prefix}${digits}${spec.suffix}`;
108
- };
@@ -1,69 +0,0 @@
1
- /**
2
- * Excel-formula → JS-expression translation
3
- *
4
- * Pure string transforms that turn the Excel-operator form of an
5
- * already-substituted expression (cell references resolved, functions replaced)
6
- * into the JavaScript form handed to `new Function`, plus the character
7
- * allowlists that gate that evaluation. No engine or evaluator state is
8
- * captured — every function here is input → output only.
9
- */
10
-
11
- /** Excel `^` exponentiation → JS `**`.
12
- *
13
- * Excel's `^` is left-associative (`2^3^2` = `(2^3)^2` = 64); JS `**` is
14
- * right-associative (`2**3**2` = `2**(3**2)` = 512). This transform does not
15
- * bridge that difference, so a chained `^` still evaluates the JS way — a known
16
- * limitation tracked separately (#2359), pinned by the tests. */
17
- export function caretToPow(expr: string): string {
18
- return expr.replace(/\^/g, "**");
19
- }
20
-
21
- /** Move the "inside a string literal" marker across one quote character.
22
- * Empty marker means "not in a literal"; otherwise it holds the opening quote. */
23
- function toggleQuote(openQuote: string, char: string): string {
24
- if (openQuote === "") return char;
25
- return char === openQuote ? "" : openQuote;
26
- }
27
-
28
- /** Excel `&` string concatenation → JS `+`, leaving any `&` inside a quoted
29
- * string literal untouched. A quote toggles the "inside a literal" state only
30
- * when it is not backslash-escaped. */
31
- export function replaceConcatOperator(expr: string): string {
32
- const chars = expr.split("");
33
- const out: string[] = [];
34
- let openQuote = "";
35
- chars.forEach((char, index) => {
36
- const escaped = index > 0 && chars[index - 1] === "\\";
37
- if (!escaped && (char === '"' || char === "'")) {
38
- openQuote = toggleQuote(openQuote, char);
39
- }
40
- out.push(char === "&" && openQuote === "" ? "+" : char);
41
- });
42
- return out.join("");
43
- }
44
-
45
- /** Excel `=` equality → JS `==`, without disturbing `<=`, `>=` or `!=`. A single
46
- * `=` is rewritten only when flanked by a non-`<>!` char on the left and a
47
- * non-`=` on the right.
48
- *
49
- * Known limitations, pinned by the tests and tracked separately (#2359): the
50
- * match consumes both flanking characters so replacements do not overlap
51
- * (`5=6=7` → `5==6=7`, only the first rewritten); a `=` at either end of the
52
- * expression has no left/right neighbour and is left alone (`5=` → `5=`); and a
53
- * hand-typed `==` becomes `===` (its second `=` matches). Excel never emits the
54
- * last two, so they only bite malformed input. */
55
- export function rewriteComparisonEq(expr: string): string {
56
- return expr.replace(/([^<>!])=([^=])/g, "$1==$2");
57
- }
58
-
59
- /** Whether an expression contains only the characters an arithmetic evaluation
60
- * may see: digits, ` + - * / ( ) . ` and spaces. Gates `new Function`. */
61
- export function isSafeArithmetic(expr: string): boolean {
62
- return /^[\d+\-*/(). ]+$/.test(expr);
63
- }
64
-
65
- /** Whether an expression contains only the characters a comparison evaluation
66
- * may see: the arithmetic set plus ` < > ! = `. Gates `new Function`. */
67
- export function isSafeComparison(expr: string): boolean {
68
- return /^[\d+\-*/(). <>!=]+$/.test(expr);
69
- }
@@ -1,81 +0,0 @@
1
- /**
2
- * Spreadsheet Engine Type Definitions
3
- */
4
-
5
- import type { SpreadsheetError } from "./spreadsheet-errors";
6
-
7
- /** A value as it is STORED in a cell and serialized to the workbook JSON. A
8
- * formula error is never stored — it only exists as a computed result. */
9
- export type StoredCellValue = number | string | boolean;
10
-
11
- /** A value as the engine COMPUTES it: a stored value, or a formula error. */
12
- export type CellValue = StoredCellValue | SpreadsheetError;
13
-
14
- export interface SpreadsheetCell {
15
- v: StoredCellValue; // Value or formula (formulas start with "=")
16
- f?: string; // Format code (e.g., "$#,##0.00")
17
- }
18
-
19
- export interface SheetData {
20
- name: string;
21
- data: SpreadsheetCell[][];
22
- }
23
-
24
- export interface CalculatedSheet {
25
- name: string;
26
- data: CellValue[][]; // Calculated values
27
- formulas: FormulaInfo[]; // Formula metadata
28
- errors: CalculationError[]; // Any errors encountered
29
- }
30
-
31
- export interface CellRef {
32
- row: number;
33
- col: number;
34
- sheet?: string; // For cross-sheet refs
35
- absolute?: {
36
- // For $A$1 style
37
- row: boolean;
38
- col: boolean;
39
- };
40
- }
41
-
42
- export interface RangeRef {
43
- start: CellRef;
44
- end: CellRef;
45
- }
46
-
47
- export interface EvaluationContext {
48
- currentSheet: string;
49
- sheets: Map<string, SpreadsheetCell[][]>;
50
- calculatedValues?: Map<string, CellValue>; // Cache
51
- }
52
-
53
- export interface FormulaInfo {
54
- cell: CellRef;
55
- formula: string;
56
- dependencies: CellRef[];
57
- result: CellValue;
58
- }
59
-
60
- export interface CalculationError {
61
- cell: CellRef;
62
- formula: string;
63
- error: string;
64
- type: "circular" | "invalid_ref" | "div_zero" | "syntax" | "unknown";
65
- }
66
-
67
- /** Per-calculation settings that change how cell CONTENT is read, as opposed
68
- * to how the engine runs. Passed down explicitly so the engine stays pure —
69
- * no ambient locale, no import-time state. */
70
- export interface CalculateOptions {
71
- /** Read an ambiguous `A/B/YYYY` date as day-first. Only affects dates whose
72
- * two leading numbers are both 12 or under; anything else decides itself.
73
- * See engine/date-locale.ts for how a locale maps onto this. */
74
- preferDDMMYYYY?: boolean;
75
- }
76
-
77
- export interface EngineOptions extends CalculateOptions {
78
- maxIterations?: number; // For circular reference detection
79
- enableCrossSheetRefs?: boolean; // Default: true
80
- strictMode?: boolean; // Throw on errors vs. return 0
81
- }
@@ -1,38 +0,0 @@
1
- // Pure helpers behind the spreadsheet mini-editor's arrow-key
2
- // navigation. Lifted out of View.vue so each rule can be unit-tested
3
- // without spinning up Vue or a DOM.
4
-
5
- export interface CellPosition {
6
- row: number;
7
- col: number;
8
- }
9
-
10
- // Sheet shape we actually rely on — the mini-editor only reads
11
- // `data` as a 2D array, so the type is intentionally loose to match
12
- // what arrives from `JSON.parse(editableData.value)`.
13
- export interface SheetLike {
14
- data?: unknown[][];
15
- }
16
-
17
- export function getArrowKeyOffset(key: string, row: number, col: number): CellPosition | null {
18
- switch (key) {
19
- case "ArrowUp":
20
- return { row: Math.max(0, row - 1), col };
21
- case "ArrowDown":
22
- return { row: row + 1, col };
23
- case "ArrowLeft":
24
- return { row, col: Math.max(0, col - 1) };
25
- case "ArrowRight":
26
- return { row, col: col + 1 };
27
- default:
28
- return null;
29
- }
30
- }
31
-
32
- export function isWithinSheetBounds(sheet: SheetLike | null | undefined, row: number, col: number): boolean {
33
- if (!sheet?.data) return false;
34
- if (row < 0 || row >= sheet.data.length) return false;
35
- const rowData = sheet.data[row];
36
- if (!rowData) return false;
37
- return col >= 0 && col < rowData.length;
38
- }