@gui-chat-plugin/spreadsheet 4.0.0 → 4.0.2

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 CHANGED
@@ -1,6 +1,7 @@
1
1
  # @gui-chat-plugin/spreadsheet
2
2
 
3
3
  [![npm version](https://badge.fury.io/js/%40gui-chat-plugin%2Fspreadsheet.svg)](https://www.npmjs.com/package/@gui-chat-plugin/spreadsheet)
4
+ [![scoria](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/receptron/GUIChatPluginSpreadsheet/badges/scoria.json)](https://github.com/receptron/GUIChatPluginSpreadsheet/actions/workflows/scoria.yml)
4
5
 
5
6
  A spreadsheet plugin for [MulmoChat](https://github.com/receptron/MulmoChat) - a multi-modal voice chat application with OpenAI's GPT-4 Realtime API.
6
7
 
@@ -102,25 +103,25 @@ The View must be rendered inside the host's `PLUGIN_RUNTIME_KEY` provider to loa
102
103
  ## Supported Functions
103
104
 
104
105
  ### Mathematical
105
- `SUM`, `AVERAGE`, `MIN`, `MAX`, `COUNT`, `COUNTA`, `ABS`, `ROUND`, `FLOOR`, `CEILING`, `POWER`, `SQRT`, `MOD`, `RAND`, `RANDBETWEEN`, `PI`
106
+ `ABS`, `CEILING`, `EXP`, `FLOOR`, `INT`, `LN`, `LOG`, `LOG10`, `MOD`, `PI`, `POWER`, `ROUND`, `ROUNDDOWN`, `ROUNDUP`, `SIGN`, `SQRT`, `TRUNC`
106
107
 
107
108
  ### Text
108
- `CONCATENATE`, `LEFT`, `RIGHT`, `MID`, `LEN`, `UPPER`, `LOWER`, `PROPER`, `TRIM`, `SUBSTITUTE`, `REPLACE`, `TEXT`, `VALUE`, `FIND`, `SEARCH`, `REPT`
109
+ `CONCAT`, `CONCATENATE`, `EXACT`, `FIND`, `LEFT`, `LEN`, `LOWER`, `MID`, `PROPER`, `REPLACE`, `RIGHT`, `SEARCH`, `SUBSTITUTE`, `TEXT`, `TRIM`, `UPPER`, `VALUE`
109
110
 
110
111
  ### Date & Time
111
- `TODAY`, `NOW`, `DATE`, `YEAR`, `MONTH`, `DAY`, `HOUR`, `MINUTE`, `SECOND`, `WEEKDAY`, `DAYS`, `EDATE`, `EOMONTH`, `WORKDAY`, `NETWORKDAYS`, `DATEDIF`
112
+ `DATE`, `DATEDIF`, `DAY`, `HOUR`, `MINUTE`, `MONTH`, `NOW`, `SECOND`, `TIME`, `TODAY`, `YEAR`
112
113
 
113
114
  ### Logical
114
- `IF`, `AND`, `OR`, `NOT`, `TRUE`, `FALSE`, `IFERROR`, `IFNA`, `IFS`, `SWITCH`, `XOR`
115
+ `AND`, `FALSE`, `IF`, `IFERROR`, `IFNA`, `IFS`, `NOT`, `OR`, `TRUE`
115
116
 
116
- ### Lookup
117
- `VLOOKUP`, `HLOOKUP`, `INDEX`, `MATCH`, `OFFSET`, `INDIRECT`, `ROW`, `COLUMN`, `ROWS`, `COLUMNS`, `TRANSPOSE`
117
+ ### Lookup & Reference
118
+ `HLOOKUP`, `INDEX`, `MATCH`, `VLOOKUP`, `XLOOKUP`
118
119
 
119
120
  ### Statistical
120
- `MEDIAN`, `MODE`, `STDEV`, `STDEVP`, `VAR`, `VARP`, `LARGE`, `SMALL`, `RANK`, `PERCENTILE`, `QUARTILE`, `CORREL`, `COUNTIF`, `COUNTIFS`, `SUMIF`, `SUMIFS`, `AVERAGEIF`, `AVERAGEIFS`
121
+ `AVERAGE`, `AVERAGEIF`, `COUNT`, `COUNTA`, `COUNTIF`, `MAX`, `MEDIAN`, `MIN`, `MODE`, `STDEV`, `SUM`, `SUMIF`, `VAR`
121
122
 
122
123
  ### Financial
123
- `PMT`, `PV`, `FV`, `NPV`, `IRR`, `RATE`, `NPER`, `IPMT`, `PPMT`, `SLN`, `DB`, `DDB`
124
+ `FV`, `IPMT`, `IRR`, `NPER`, `NPV`, `PMT`, `PPMT`, `PV`, `RATE`
124
125
 
125
126
  ## Development
126
127
 
package/dist/core.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./samples-BzI0GdUj.cjs");exports.SYSTEM_PROMPT=e.d,exports.TOOL_DEFINITION=e.f,exports.TOOL_NAME=e.p,exports.executeSpreadsheet=e.n,exports.executeSpreadsheetDispatch=e.i,exports.isSpreadsheetArtifactPath=e.s,exports.isSpreadsheetDispatchArgs=e.a,exports.pluginCore=e.r,exports.samples=e.t;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./samples-DUNRjoGw.cjs");exports.SYSTEM_PROMPT=e.d,exports.TOOL_DEFINITION=e.f,exports.TOOL_NAME=e.p,exports.executeSpreadsheet=e.n,exports.executeSpreadsheetDispatch=e.i,exports.isSpreadsheetArtifactPath=e.s,exports.isSpreadsheetDispatchArgs=e.a,exports.pluginCore=e.r,exports.samples=e.t;
package/dist/core.js CHANGED
@@ -1 +1 @@
1
- export { d as SYSTEM_PROMPT, f as TOOL_DEFINITION, p as TOOL_NAME, n as executeSpreadsheet, i as executeSpreadsheetDispatch, s as isSpreadsheetArtifactPath, a as isSpreadsheetDispatchArgs, r as pluginCore, t as samples } from "./samples-Cylf7cMw.js";
1
+ export { d as SYSTEM_PROMPT, f as TOOL_DEFINITION, p as TOOL_NAME, n as executeSpreadsheet, i as executeSpreadsheetDispatch, s as isSpreadsheetArtifactPath, a as isSpreadsheetDispatchArgs, r as pluginCore, t as samples } from "./samples-CaAbe1tF.js";
@@ -10,6 +10,7 @@
10
10
  * `test/plugins/spreadsheet/engine/test_cellBuilder.ts`.
11
11
  */
12
12
  import type { SpreadsheetCell } from "./types.js";
13
+ import "./functions/index.js";
13
14
  /** Inputs to the cell builder. Mirrors the mini editor refs in the
14
15
  * View but as plain values so unit tests don't need a Vue runtime. */
15
16
  export interface MiniEditorInput {
@@ -60,6 +60,10 @@ declare class FunctionRegistry {
60
60
  getFunctionsByCategory(): Map<string, FunctionDefinition[]>;
61
61
  }
62
62
  export declare const functionRegistry: FunctionRegistry;
63
+ /** Whether `name` written before "(" is a function call. A letters-only name is,
64
+ * registered or not (an unknown one reports #NAME?). A name with digits is only
65
+ * when registered: LOG10 is also shaped like a cell reference, so `A1(2)` is not. */
66
+ export declare const isCallableName: (name: string) => boolean;
63
67
  /**
64
68
  * Lenient numeric coercion for range aggregation: anything unreadable is 0.
65
69
  * PINNED behaviour (booleans are 0, not Excel's 1/0) — the string parsing lives
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./samples-BzI0GdUj.cjs");require("./core.cjs"),exports.SYSTEM_PROMPT=e.d,exports.TOOL_DEFINITION=e.f,exports.TOOL_NAME=e.p,exports.executeSpreadsheet=e.n,exports.executeSpreadsheetDispatch=e.i,exports.isSpreadsheetArtifactPath=e.s,exports.isSpreadsheetDispatchArgs=e.a,exports.pluginCore=e.r,exports.samples=e.t;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./samples-DUNRjoGw.cjs");require("./core.cjs"),exports.SYSTEM_PROMPT=e.d,exports.TOOL_DEFINITION=e.f,exports.TOOL_NAME=e.p,exports.executeSpreadsheet=e.n,exports.executeSpreadsheetDispatch=e.i,exports.isSpreadsheetArtifactPath=e.s,exports.isSpreadsheetDispatchArgs=e.a,exports.pluginCore=e.r,exports.samples=e.t;
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- export { d as SYSTEM_PROMPT, f as TOOL_DEFINITION, p as TOOL_NAME, n as executeSpreadsheet, i as executeSpreadsheetDispatch, s as isSpreadsheetArtifactPath, a as isSpreadsheetDispatchArgs, r as pluginCore, t as samples } from "./samples-Cylf7cMw.js";
1
+ export { d as SYSTEM_PROMPT, f as TOOL_DEFINITION, p as TOOL_NAME, n as executeSpreadsheet, i as executeSpreadsheetDispatch, s as isSpreadsheetArtifactPath, a as isSpreadsheetDispatchArgs, r as pluginCore, t as samples } from "./samples-CaAbe1tF.js";
2
2
  import "./core.js";
@@ -124,7 +124,7 @@ function O(e) {
124
124
  let t = JSON.parse(e);
125
125
  return console.warn("Sheets was provided as a string and has been parsed to an array"), t;
126
126
  } catch (e) {
127
- throw Error(`Invalid sheets format: sheets must be an array, not a string. Parse error: ${e instanceof Error ? e.message : String(e)}`);
127
+ throw Error(`Invalid sheets format: sheets must be an array, not a string. Parse error: ${e instanceof Error ? e.message : String(e)}`, { cause: e });
128
128
  }
129
129
  }
130
130
  function k(e) {
@@ -1 +1 @@
1
- let e=require("gui-chat-protocol");var t=`presentSpreadsheet`,n={type:`function`,name:t,description:`Display an Excel-like spreadsheet with formulas and calculations.`,parameters:{type:`object`,properties:{title:{type:`string`,description:`Title for the spreadsheet`},sheets:{type:`array`,description:`Sheets to render as spreadsheet tabs. Each sheet includes a name and 2D array of cells (rows x columns).`,items:{type:`object`,properties:{name:{type:`string`,description:`Sheet name (e.g., 'Sales Q1', 'Summary')`},data:{type:`array`,description:`Rows of cells. Each cell is an object with 'v' (value) and 'f' (format). Use Excel-style A1 notation in formulas: columns are letters (A, B, C...), rows are 1-based numbers (1, 2, 3...). Values can be text, numbers, dates, or formulas. Examples: [{"v": "Product"}, {"v": 2024, "f": "#,##0"}, {"v": "01/15/2025", "f": "MM/DD/YYYY"}, {"v": "=B2*1.05", "f": "$#,##0.00"}]. Format codes: '$#,##0.00' (currency), '#,##0' (integer), '0.00%' (percent), '0.00' (decimal), 'MM/DD/YYYY' (date), 'DD-MMM-YYYY' (date), 'YYYY-MM-DD' (ISO date).`,items:{type:`array`,description:`Row of cells. Each cell is an object with value and format.`,items:{type:`object`,description:`Cell object with value and optional format. If value is a string starting with '=', it's treated as a formula.`,properties:{v:{oneOf:[{type:`string`},{type:`number`},{type:`boolean`}],description:`Cell value. Can be text, number, date, or formula (string starting with '='). Examples: 'Revenue', 1500000, '01/15/2025', '=SUM(A1:A10)', '=B2-TODAY()'. Date strings like '01/15/2025' are automatically parsed to date serial numbers.`},f:{type:`string`,description:`Optional format code for displaying the value. Common formats: '$#,##0.00' (currency), '#,##0' (integer), '0.00%' (percent), '0.00' (decimal), 'MM/DD/YYYY' (date), 'DD-MMM-YYYY' (date), 'YYYY-MM-DD' (ISO date)`}},required:[`v`]}}}},required:[`name`,`data`]}}},required:[`title`,`sheets`]}},r=`Use ${t} whenever the user needs a spreadsheet-style table, multi-step math, or dynamic what-if analysis—do not summarize in text. Build LIVE sheets where every cell is an object {"v": value, "f": format}. For formulas, set "v" to a string starting with "=" (e.g., {"v": "=B2*1.05", "f": "$#,##0.00"}). For dates, use date strings like "01/15/2025" or date formulas like "=TODAY()" or "=DATE(2025,1,15)". The spreadsheet auto-parses common date formats (MM/DD/YYYY, YYYY-MM-DD, DD-MMM-YYYY) into date serial numbers for calculations. Date arithmetic works: "=B2-TODAY()" calculates days between dates. Never pre-calculate; let the spreadsheet compute using cell refs, functions (SUM, AVERAGE, IF, TODAY, DATE, DATEDIF, etc.), and arithmetic. Standard formats: "$#,##0.00" currency, "#,##0" integer, "0.00%" percent, "0.00" decimal, "MM/DD/YYYY" date, "DD-MMM-YYYY" date, "YYYY-MM-DD" ISO date. Format is optional for plain text/numbers.`;function i(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function a(e){return typeof e==`object`&&!!e}var o=(e,t)=>i(e)&&typeof e[t]==`string`;function s(e,t){return e instanceof Error?e.message:o(e,`details`)&&e.details?e.details:o(e,`message`)&&e.message?e.message:t===void 0?String(e):t}var c=`spreadsheets`,l=`.json`,u=16,d=2,f=e=>`${e.getUTCFullYear()}/${String(e.getUTCMonth()+1).padStart(d,`0`)}`,p=()=>globalThis.crypto.randomUUID().split(`-`).join(``).slice(0,u);function m(t=new Date,n=p()){let r=`${c}/${f(t)}/${n}${l}`;return{relPath:r,filePath:`${e.ARTIFACTS_ROOT}/${r}`}}var h=new Set([``,`.`,`..`]);function g(t){return typeof t!=`string`||!t.startsWith(`${e.ARTIFACTS_ROOT}/${c}/`)||!t.endsWith(l)||t.includes(`\\`)?!1:!t.split(`/`).some(e=>h.has(e))}var _=t=>t.slice(e.ARTIFACTS_ROOT.length+1),v=e=>typeof e==`string`||typeof e==`number`||typeof e==`boolean`,y=e=>e===null||v(e)||i(e)&&(e.v===void 0||e.v===null||v(e.v))&&(e.f===void 0||typeof e.f==`string`),b=e=>Array.isArray(e)&&e.every(y),x=e=>i(e)&&typeof e.name==`string`&&Array.isArray(e.data)&&e.data.every(b);function S(e){return Array.isArray(e)&&e.every(x)?e:null}function C(e){return!i(e)||typeof e.path!=`string`?!1:e.kind===`loadSpreadsheet`||e.kind===`saveSpreadsheet`&&Array.isArray(e.sheets)&&e.sheets.every(x)}var w=e=>i(e)&&typeof e.read==`function`&&typeof e.write==`function`;function T(e){if(!i(e)||!i(e.files))return null;let t=e.files.artifacts;return w(t)?t:null}async function E(e,t){let n=await e.read(_(t)),r=S(JSON.parse(n));if(!r)throw Error(`${t} does not hold an array of sheets`);return{message:`Loaded spreadsheet ${t}`,data:{sheets:r}}}async function D(e,t){if(!g(t.path))throw Error(`path must be a .json file under artifacts/spreadsheets/`);return t.kind===`loadSpreadsheet`?E(e,t.path):(await e.write(_(t.path),JSON.stringify(t.sheets)),{message:`Saved spreadsheet ${t.path}`,data:{sheets:t.path}})}function O(e){if(typeof e!=`string`)return e;try{let t=JSON.parse(e);return console.warn(`Sheets was provided as a string and has been parsed to an array`),t}catch(e){throw Error(`Invalid sheets format: sheets must be an array, not a string. Parse error: ${e instanceof Error?e.message:String(e)}`)}}function k(e){if(!Array.isArray(e)||e.length===0)throw Error(`At least one sheet is required. Sheets must be an array of sheet objects.`);e.forEach(e=>{if(!e.name||!e.data||e.data.length===0)throw Error(`Invalid sheet: ${e.name||`unnamed`}. Each sheet must have a name and data array.`)})}var A=async(e,t)=>{let{title:n}=t,r=O(t.sheets);k(r);let i=`Acknowledge that the spreadsheet has been created and is displayed to the user.`,a=T(e);if(!a)return{message:`Created spreadsheet: ${n}`,title:n,data:{sheets:r},instructions:i};let{relPath:o,filePath:s}=m();return await a.write(o,JSON.stringify(r)),{message:`Created spreadsheet: ${n}. Saved to ${s}; the user can edit cells there, so read that file for the current values.`,title:n,data:{sheets:s},instructions:i}};async function j(e,t){if(!(`kind`in t))return A(e,t);let n=T(e);if(!n)throw Error(`This host does not provide files.artifacts, so spreadsheets cannot be loaded or saved`);if(!C(t))throw Error(`Invalid spreadsheet dispatch`);return D(n,t)}var M={toolDefinition:n,execute:j,generatingMessage:`Creating spreadsheet...`,waitingMessage:`Tell the user that the spreadsheet was created and will be presented shortly.`,isEnabled:()=>!0,systemPrompt:r},N=[{name:`Simple Budget`,args:{title:`Monthly Budget`,sheets:[{name:`Budget`,data:[[{v:`Category`},{v:`Amount`}],[{v:`Income`},{v:5e3,f:`$#,##0.00`}],[{v:`Rent`},{v:-1500,f:`$#,##0.00`}],[{v:`Utilities`},{v:-200,f:`$#,##0.00`}],[{v:`Food`},{v:-600,f:`$#,##0.00`}],[{v:`Transport`},{v:-300,f:`$#,##0.00`}],[{v:`Total`},{v:`=SUM(B2:B6)`,f:`$#,##0.00`}]]}]}},{name:`Sales Report`,args:{title:`Q1 Sales Report`,sheets:[{name:`Sales`,data:[[{v:`Product`},{v:`Jan`},{v:`Feb`},{v:`Mar`},{v:`Total`}],[{v:`Widget A`},{v:1200},{v:1350},{v:1500},{v:`=SUM(B2:D2)`}],[{v:`Widget B`},{v:800},{v:920},{v:1100},{v:`=SUM(B3:D3)`}],[{v:`Widget C`},{v:450},{v:480},{v:520},{v:`=SUM(B4:D4)`}],[{v:`Total`},{v:`=SUM(B2:B4)`},{v:`=SUM(C2:C4)`},{v:`=SUM(D2:D4)`},{v:`=SUM(E2:E4)`}]]}]}},{name:`Loan Calculator`,args:{title:`Loan Calculator`,sheets:[{name:`Calculator`,data:[[{v:`Loan Amount`},{v:25e4,f:`$#,##0`}],[{v:`Interest Rate`},{v:.065,f:`0.00%`}],[{v:`Term (Years)`},{v:30}],[{v:``},{v:``}],[{v:`Monthly Payment`},{v:`=PMT(B2/12, B3*12, -B1)`,f:`$#,##0.00`}],[{v:`Total Interest`},{v:`=B5*B3*12-B1`,f:`$#,##0.00`}]]}]}},{name:`World Population`,args:{title:`世界人口(上位10)`,sheets:[{name:`世界人口(上位10)`,data:[[{v:`順位`},{v:`国・地域`},{v:`人口(概数)`,f:`#,##0`},{v:`上位10合計に占める割合`},{v:`世界人口に占める割合`}],[{v:1,f:`#,##0`},{v:`インド`},{v:1428627e3,f:`#,##0`},{v:`=C2/$C$12`,f:`0.00%`},{v:`=C2/$C$13`,f:`0.00%`}],[{v:2,f:`#,##0`},{v:`中国`},{v:1425671e3,f:`#,##0`},{v:`=C3/$C$12`,f:`0.00%`},{v:`=C3/$C$13`,f:`0.00%`}],[{v:3,f:`#,##0`},{v:`アメリカ合衆国`},{v:334e6,f:`#,##0`},{v:`=C4/$C$12`,f:`0.00%`},{v:`=C4/$C$13`,f:`0.00%`}],[{v:4,f:`#,##0`},{v:`インドネシア`},{v:277e6,f:`#,##0`},{v:`=C5/$C$12`,f:`0.00%`},{v:`=C5/$C$13`,f:`0.00%`}],[{v:5,f:`#,##0`},{v:`パキスタン`},{v:24e7,f:`#,##0`},{v:`=C6/$C$12`,f:`0.00%`},{v:`=C6/$C$13`,f:`0.00%`}],[{v:6,f:`#,##0`},{v:`ナイジェリア`},{v:219e6,f:`#,##0`},{v:`=C7/$C$12`,f:`0.00%`},{v:`=C7/$C$13`,f:`0.00%`}],[{v:7,f:`#,##0`},{v:`ブラジル`},{v:216e6,f:`#,##0`},{v:`=C8/$C$12`,f:`0.00%`},{v:`=C8/$C$13`,f:`0.00%`}],[{v:8,f:`#,##0`},{v:`バングラデシュ`},{v:172e6,f:`#,##0`},{v:`=C9/$C$12`,f:`0.00%`},{v:`=C9/$C$13`,f:`0.00%`}],[{v:9,f:`#,##0`},{v:`ロシア`},{v:146e6,f:`#,##0`},{v:`=C10/$C$12`,f:`0.00%`},{v:`=C10/$C$13`,f:`0.00%`}],[{v:10,f:`#,##0`},{v:`メキシコ`},{v:13e7,f:`#,##0`},{v:`=C11/$C$12`,f:`0.00%`},{v:`=C11/$C$13`,f:`0.00%`}],[{v:``},{v:`合計(上位10)`},{v:`=SUM(C2:C11)`,f:`#,##0`},{v:``},{v:``}],[{v:``},{v:`世界推定人口(例)`},{v:805e7,f:`#,##0`},{v:``},{v:``}]]}]}}];Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return C}}),Object.defineProperty(exports,"c",{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,"d",{enumerable:!0,get:function(){return r}}),Object.defineProperty(exports,"f",{enumerable:!0,get:function(){return n}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return D}}),Object.defineProperty(exports,"l",{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return A}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return S}}),Object.defineProperty(exports,"p",{enumerable:!0,get:function(){return t}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return M}}),Object.defineProperty(exports,"s",{enumerable:!0,get:function(){return g}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return N}}),Object.defineProperty(exports,"u",{enumerable:!0,get:function(){return i}});
1
+ let e=require("gui-chat-protocol");var t=`presentSpreadsheet`,n={type:`function`,name:t,description:`Display an Excel-like spreadsheet with formulas and calculations.`,parameters:{type:`object`,properties:{title:{type:`string`,description:`Title for the spreadsheet`},sheets:{type:`array`,description:`Sheets to render as spreadsheet tabs. Each sheet includes a name and 2D array of cells (rows x columns).`,items:{type:`object`,properties:{name:{type:`string`,description:`Sheet name (e.g., 'Sales Q1', 'Summary')`},data:{type:`array`,description:`Rows of cells. Each cell is an object with 'v' (value) and 'f' (format). Use Excel-style A1 notation in formulas: columns are letters (A, B, C...), rows are 1-based numbers (1, 2, 3...). Values can be text, numbers, dates, or formulas. Examples: [{"v": "Product"}, {"v": 2024, "f": "#,##0"}, {"v": "01/15/2025", "f": "MM/DD/YYYY"}, {"v": "=B2*1.05", "f": "$#,##0.00"}]. Format codes: '$#,##0.00' (currency), '#,##0' (integer), '0.00%' (percent), '0.00' (decimal), 'MM/DD/YYYY' (date), 'DD-MMM-YYYY' (date), 'YYYY-MM-DD' (ISO date).`,items:{type:`array`,description:`Row of cells. Each cell is an object with value and format.`,items:{type:`object`,description:`Cell object with value and optional format. If value is a string starting with '=', it's treated as a formula.`,properties:{v:{oneOf:[{type:`string`},{type:`number`},{type:`boolean`}],description:`Cell value. Can be text, number, date, or formula (string starting with '='). Examples: 'Revenue', 1500000, '01/15/2025', '=SUM(A1:A10)', '=B2-TODAY()'. Date strings like '01/15/2025' are automatically parsed to date serial numbers.`},f:{type:`string`,description:`Optional format code for displaying the value. Common formats: '$#,##0.00' (currency), '#,##0' (integer), '0.00%' (percent), '0.00' (decimal), 'MM/DD/YYYY' (date), 'DD-MMM-YYYY' (date), 'YYYY-MM-DD' (ISO date)`}},required:[`v`]}}}},required:[`name`,`data`]}}},required:[`title`,`sheets`]}},r=`Use ${t} whenever the user needs a spreadsheet-style table, multi-step math, or dynamic what-if analysis—do not summarize in text. Build LIVE sheets where every cell is an object {"v": value, "f": format}. For formulas, set "v" to a string starting with "=" (e.g., {"v": "=B2*1.05", "f": "$#,##0.00"}). For dates, use date strings like "01/15/2025" or date formulas like "=TODAY()" or "=DATE(2025,1,15)". The spreadsheet auto-parses common date formats (MM/DD/YYYY, YYYY-MM-DD, DD-MMM-YYYY) into date serial numbers for calculations. Date arithmetic works: "=B2-TODAY()" calculates days between dates. Never pre-calculate; let the spreadsheet compute using cell refs, functions (SUM, AVERAGE, IF, TODAY, DATE, DATEDIF, etc.), and arithmetic. Standard formats: "$#,##0.00" currency, "#,##0" integer, "0.00%" percent, "0.00" decimal, "MM/DD/YYYY" date, "DD-MMM-YYYY" date, "YYYY-MM-DD" ISO date. Format is optional for plain text/numbers.`;function i(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function a(e){return typeof e==`object`&&!!e}var o=(e,t)=>i(e)&&typeof e[t]==`string`;function s(e,t){return e instanceof Error?e.message:o(e,`details`)&&e.details?e.details:o(e,`message`)&&e.message?e.message:t===void 0?String(e):t}var c=`spreadsheets`,l=`.json`,u=16,d=2,f=e=>`${e.getUTCFullYear()}/${String(e.getUTCMonth()+1).padStart(d,`0`)}`,p=()=>globalThis.crypto.randomUUID().split(`-`).join(``).slice(0,u);function m(t=new Date,n=p()){let r=`${c}/${f(t)}/${n}${l}`;return{relPath:r,filePath:`${e.ARTIFACTS_ROOT}/${r}`}}var h=new Set([``,`.`,`..`]);function g(t){return typeof t!=`string`||!t.startsWith(`${e.ARTIFACTS_ROOT}/${c}/`)||!t.endsWith(l)||t.includes(`\\`)?!1:!t.split(`/`).some(e=>h.has(e))}var _=t=>t.slice(e.ARTIFACTS_ROOT.length+1),v=e=>typeof e==`string`||typeof e==`number`||typeof e==`boolean`,y=e=>e===null||v(e)||i(e)&&(e.v===void 0||e.v===null||v(e.v))&&(e.f===void 0||typeof e.f==`string`),b=e=>Array.isArray(e)&&e.every(y),x=e=>i(e)&&typeof e.name==`string`&&Array.isArray(e.data)&&e.data.every(b);function S(e){return Array.isArray(e)&&e.every(x)?e:null}function C(e){return!i(e)||typeof e.path!=`string`?!1:e.kind===`loadSpreadsheet`||e.kind===`saveSpreadsheet`&&Array.isArray(e.sheets)&&e.sheets.every(x)}var w=e=>i(e)&&typeof e.read==`function`&&typeof e.write==`function`;function T(e){if(!i(e)||!i(e.files))return null;let t=e.files.artifacts;return w(t)?t:null}async function E(e,t){let n=await e.read(_(t)),r=S(JSON.parse(n));if(!r)throw Error(`${t} does not hold an array of sheets`);return{message:`Loaded spreadsheet ${t}`,data:{sheets:r}}}async function D(e,t){if(!g(t.path))throw Error(`path must be a .json file under artifacts/spreadsheets/`);return t.kind===`loadSpreadsheet`?E(e,t.path):(await e.write(_(t.path),JSON.stringify(t.sheets)),{message:`Saved spreadsheet ${t.path}`,data:{sheets:t.path}})}function O(e){if(typeof e!=`string`)return e;try{let t=JSON.parse(e);return console.warn(`Sheets was provided as a string and has been parsed to an array`),t}catch(e){throw Error(`Invalid sheets format: sheets must be an array, not a string. Parse error: ${e instanceof Error?e.message:String(e)}`,{cause:e})}}function k(e){if(!Array.isArray(e)||e.length===0)throw Error(`At least one sheet is required. Sheets must be an array of sheet objects.`);e.forEach(e=>{if(!e.name||!e.data||e.data.length===0)throw Error(`Invalid sheet: ${e.name||`unnamed`}. Each sheet must have a name and data array.`)})}var A=async(e,t)=>{let{title:n}=t,r=O(t.sheets);k(r);let i=`Acknowledge that the spreadsheet has been created and is displayed to the user.`,a=T(e);if(!a)return{message:`Created spreadsheet: ${n}`,title:n,data:{sheets:r},instructions:i};let{relPath:o,filePath:s}=m();return await a.write(o,JSON.stringify(r)),{message:`Created spreadsheet: ${n}. Saved to ${s}; the user can edit cells there, so read that file for the current values.`,title:n,data:{sheets:s},instructions:i}};async function j(e,t){if(!(`kind`in t))return A(e,t);let n=T(e);if(!n)throw Error(`This host does not provide files.artifacts, so spreadsheets cannot be loaded or saved`);if(!C(t))throw Error(`Invalid spreadsheet dispatch`);return D(n,t)}var M={toolDefinition:n,execute:j,generatingMessage:`Creating spreadsheet...`,waitingMessage:`Tell the user that the spreadsheet was created and will be presented shortly.`,isEnabled:()=>!0,systemPrompt:r},N=[{name:`Simple Budget`,args:{title:`Monthly Budget`,sheets:[{name:`Budget`,data:[[{v:`Category`},{v:`Amount`}],[{v:`Income`},{v:5e3,f:`$#,##0.00`}],[{v:`Rent`},{v:-1500,f:`$#,##0.00`}],[{v:`Utilities`},{v:-200,f:`$#,##0.00`}],[{v:`Food`},{v:-600,f:`$#,##0.00`}],[{v:`Transport`},{v:-300,f:`$#,##0.00`}],[{v:`Total`},{v:`=SUM(B2:B6)`,f:`$#,##0.00`}]]}]}},{name:`Sales Report`,args:{title:`Q1 Sales Report`,sheets:[{name:`Sales`,data:[[{v:`Product`},{v:`Jan`},{v:`Feb`},{v:`Mar`},{v:`Total`}],[{v:`Widget A`},{v:1200},{v:1350},{v:1500},{v:`=SUM(B2:D2)`}],[{v:`Widget B`},{v:800},{v:920},{v:1100},{v:`=SUM(B3:D3)`}],[{v:`Widget C`},{v:450},{v:480},{v:520},{v:`=SUM(B4:D4)`}],[{v:`Total`},{v:`=SUM(B2:B4)`},{v:`=SUM(C2:C4)`},{v:`=SUM(D2:D4)`},{v:`=SUM(E2:E4)`}]]}]}},{name:`Loan Calculator`,args:{title:`Loan Calculator`,sheets:[{name:`Calculator`,data:[[{v:`Loan Amount`},{v:25e4,f:`$#,##0`}],[{v:`Interest Rate`},{v:.065,f:`0.00%`}],[{v:`Term (Years)`},{v:30}],[{v:``},{v:``}],[{v:`Monthly Payment`},{v:`=PMT(B2/12, B3*12, -B1)`,f:`$#,##0.00`}],[{v:`Total Interest`},{v:`=B5*B3*12-B1`,f:`$#,##0.00`}]]}]}},{name:`World Population`,args:{title:`世界人口(上位10)`,sheets:[{name:`世界人口(上位10)`,data:[[{v:`順位`},{v:`国・地域`},{v:`人口(概数)`,f:`#,##0`},{v:`上位10合計に占める割合`},{v:`世界人口に占める割合`}],[{v:1,f:`#,##0`},{v:`インド`},{v:1428627e3,f:`#,##0`},{v:`=C2/$C$12`,f:`0.00%`},{v:`=C2/$C$13`,f:`0.00%`}],[{v:2,f:`#,##0`},{v:`中国`},{v:1425671e3,f:`#,##0`},{v:`=C3/$C$12`,f:`0.00%`},{v:`=C3/$C$13`,f:`0.00%`}],[{v:3,f:`#,##0`},{v:`アメリカ合衆国`},{v:334e6,f:`#,##0`},{v:`=C4/$C$12`,f:`0.00%`},{v:`=C4/$C$13`,f:`0.00%`}],[{v:4,f:`#,##0`},{v:`インドネシア`},{v:277e6,f:`#,##0`},{v:`=C5/$C$12`,f:`0.00%`},{v:`=C5/$C$13`,f:`0.00%`}],[{v:5,f:`#,##0`},{v:`パキスタン`},{v:24e7,f:`#,##0`},{v:`=C6/$C$12`,f:`0.00%`},{v:`=C6/$C$13`,f:`0.00%`}],[{v:6,f:`#,##0`},{v:`ナイジェリア`},{v:219e6,f:`#,##0`},{v:`=C7/$C$12`,f:`0.00%`},{v:`=C7/$C$13`,f:`0.00%`}],[{v:7,f:`#,##0`},{v:`ブラジル`},{v:216e6,f:`#,##0`},{v:`=C8/$C$12`,f:`0.00%`},{v:`=C8/$C$13`,f:`0.00%`}],[{v:8,f:`#,##0`},{v:`バングラデシュ`},{v:172e6,f:`#,##0`},{v:`=C9/$C$12`,f:`0.00%`},{v:`=C9/$C$13`,f:`0.00%`}],[{v:9,f:`#,##0`},{v:`ロシア`},{v:146e6,f:`#,##0`},{v:`=C10/$C$12`,f:`0.00%`},{v:`=C10/$C$13`,f:`0.00%`}],[{v:10,f:`#,##0`},{v:`メキシコ`},{v:13e7,f:`#,##0`},{v:`=C11/$C$12`,f:`0.00%`},{v:`=C11/$C$13`,f:`0.00%`}],[{v:``},{v:`合計(上位10)`},{v:`=SUM(C2:C11)`,f:`#,##0`},{v:``},{v:``}],[{v:``},{v:`世界推定人口(例)`},{v:805e7,f:`#,##0`},{v:``},{v:``}]]}]}}];Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return C}}),Object.defineProperty(exports,"c",{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,"d",{enumerable:!0,get:function(){return r}}),Object.defineProperty(exports,"f",{enumerable:!0,get:function(){return n}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return D}}),Object.defineProperty(exports,"l",{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return A}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return S}}),Object.defineProperty(exports,"p",{enumerable:!0,get:function(){return t}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return M}}),Object.defineProperty(exports,"s",{enumerable:!0,get:function(){return g}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return N}}),Object.defineProperty(exports,"u",{enumerable:!0,get:function(){return i}});