shortcutxl 0.3.51 → 0.3.52

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/CHANGELOG.md CHANGED
@@ -1,8 +1,14 @@
1
- # Changelog
2
-
3
- ## [0.3.51]
4
-
5
- - **TUI rendering and text selection** - Improved TUI rendering, scrolling. Fixed text highlighting and selection for copy pastes.
1
+ # Changelog
2
+
3
+ ## [0.3.52]
4
+
5
+ - **Team fast mode policy** - Fast Mode is now automatically disabled for team accounts, with a clear message when your team policy blocks it.
6
+ - **Cleaner footer and shortcuts** - The footer now uses shorter model names, shows model/thinking hotkeys inline, and moves model cycling to `alt+p`, thinking to `alt+t`, and runtime permission bypass to `alt+r`.
7
+ - **Copy selection hint** - Selecting transcript text now shows a `Ctrl+C to copy` hint while preserving the exact copied text.
8
+
9
+ ## [0.3.51]
10
+
11
+ - **TUI rendering and text selection** - Improved TUI rendering, scrolling. Fixed text highlighting and selection for copy pastes.
6
12
  - **Agentic MCP setup** - Agents can now help set up MCP servers through `shortcut mcp add/list/get/login/logout/remove`, with clearer login, logs, and OAuth settings.
7
13
  - **User-requested session settings** - When asked, agents can inspect available models and thinking levels or apply your requested session change.
8
14
  - **Skill sync clarity** - Skill sync now shows startup differences plus per-file upload/download changes, source, and visibility.
@@ -38,6 +38,7 @@ export interface CreateAgentSessionRuntimeAdapterOptions {
38
38
  approvalState?: AgentApprovalState;
39
39
  budgetLimits?: RuntimeBudgetLimits;
40
40
  enableToolSummaries?: boolean;
41
+ fastModeAllowed?: boolean;
41
42
  modeName?: string;
42
43
  model?: Model<Api>;
43
44
  observability?: RuntimeObservability;
@@ -211,6 +211,7 @@ export async function createAgentSessionRuntimeAdapter(options) {
211
211
  initialModeName: options.modeName,
212
212
  initialPermissionPolicy: options.permissionPolicy,
213
213
  modelRegistry,
214
+ fastModeAllowed: options.fastModeAllowed,
214
215
  extensionRunnerRef,
215
216
  prePromptContext: options.prePromptContext,
216
217
  budgetLimits: options.budgetLimits,
@@ -105,6 +105,7 @@ export interface AgentSessionConfig {
105
105
  initialPermissionPolicy?: RuntimePermissionPolicy;
106
106
  /** Model registry for API key resolution and model discovery */
107
107
  modelRegistry: AgentModelRegistry;
108
+ fastModeAllowed?: boolean;
108
109
  /** Mutable ref used by AgentController to access the current ExtensionRunner */
109
110
  extensionRunnerRef?: {
110
111
  current?: ExtensionRunner;
@@ -182,6 +183,7 @@ export declare class AgentSession {
182
183
  private _observability?;
183
184
  private _tools;
184
185
  private _models;
186
+ private _fastModeAllowed;
185
187
  private _extensions;
186
188
  private _compactionActions;
187
189
  private _compactionTriggerDeps;
@@ -262,7 +264,9 @@ export declare class AgentSession {
262
264
  /** Current thinking level */
263
265
  get thinkingLevel(): ThinkingLevel;
264
266
  get isFastModeEnabled(): boolean;
267
+ get isFastModeAllowed(): boolean;
265
268
  get isFastModeAvailable(): boolean;
269
+ setFastModeAllowed(allowed: boolean): void;
266
270
  setFastModeEnabled(enabled: boolean): void;
267
271
  toggleFastMode(): boolean;
268
272
  /** Whether agent is currently streaming a response */
@@ -27,7 +27,7 @@ import { emitExtensionEvent } from './session/extension-emitter.js';
27
27
  import { ExtensionLifecycle } from './session/extension-lifecycle.js';
28
28
  import { ModelManager } from './session/model-manager.js';
29
29
  import { resolvePendingRefreshOverride } from './session/pending-refresh-overrides.js';
30
- import { formatRuntimePermissionBypassContext } from './session/permission-context.js';
30
+ import { formatRuntimePermissionBypassReminder } from './session/permission-context.js';
31
31
  import { PersistenceHandler } from './session/persistence-handler.js';
32
32
  import { assertNotExtensionCommand, buildMessageContent, normalizeUserContent, tryExtensionCommand } from './session/prompt-pipeline.js';
33
33
  import { QueueTracker } from './session/queue-tracker.js';
@@ -37,6 +37,7 @@ import { executeNewSession, executeSwitchSession } from './session/session-lifec
37
37
  import { getAvailableThinkingLevels, supportsThinking, supportsXhighThinking } from './session/session-models.js';
38
38
  import { computeContextUsage, computeSessionStats } from './session/session-stats.js';
39
39
  import { expandSkillCommand } from './session/skill-expansion.js';
40
+ import { formatSystemReminderContext } from './session/system-reminder-context.js';
40
41
  import { ToolRegistry } from './session/tool-registry.js';
41
42
  import { ToolSummaryEmitter } from './session/tool-summary-emitter.js';
42
43
  import { isToolSummaryEligible } from './session/tool-summary-policy.js';
@@ -109,6 +110,7 @@ export class AgentSession {
109
110
  _tools;
110
111
  // Model manager — model switching, cycling, thinking level
111
112
  _models;
113
+ _fastModeAllowed = true;
112
114
  // Extension lifecycle — owns extension runner, bindings, reload
113
115
  _extensions;
114
116
  // Bridge objects for compaction/recovery/budget subsystems
@@ -127,6 +129,7 @@ export class AgentSession {
127
129
  this._prePromptContext = config.prePromptContext;
128
130
  this._budgetLimits = config.budgetLimits;
129
131
  this._observability = config.observability;
132
+ this._fastModeAllowed = config.fastModeAllowed ?? true;
130
133
  this._summaryEmitter = new ToolSummaryEmitter({
131
134
  enabled: config.enableToolSummaries ?? true,
132
135
  isFeatureEnabled: () => this.settingsManager.getToolSummariesEnabled(),
@@ -587,8 +590,16 @@ export class AgentSession {
587
590
  get isFastModeEnabled() {
588
591
  return this.isFastModeAvailable && this.agent.speed === 'fast';
589
592
  }
593
+ get isFastModeAllowed() {
594
+ return this._fastModeAllowed;
595
+ }
590
596
  get isFastModeAvailable() {
591
- return isShortcutFastModeModel(this.model);
597
+ return this._fastModeAllowed && isShortcutFastModeModel(this.model);
598
+ }
599
+ setFastModeAllowed(allowed) {
600
+ this._fastModeAllowed = allowed;
601
+ if (!allowed)
602
+ this.setFastModeEnabled(false);
592
603
  }
593
604
  setFastModeEnabled(enabled) {
594
605
  this.agent.speed = enabled && this.isFastModeAvailable ? 'fast' : undefined;
@@ -801,18 +812,8 @@ export class AgentSession {
801
812
  }
802
813
  // Build messages array (custom message if any, then user message)
803
814
  const messages = [];
804
- // Add user message
805
- const userContent = [{ type: 'text', text: expandedText }];
806
- if (currentImages) {
807
- userContent.push(...currentImages);
808
- }
809
- messages.push({
810
- role: 'user',
811
- content: userContent,
812
- timestamp: Date.now()
813
- });
814
815
  this.lastPrePromptDetails = undefined;
815
- const prePromptContextParts = [formatRuntimePermissionBypassContext(this.permissionPolicy)];
816
+ const prePromptContextParts = [formatRuntimePermissionBypassReminder(this.permissionPolicy)];
816
817
  let prePromptDetails;
817
818
  if (this._prePromptContext) {
818
819
  const ctx = await this._prePromptContext();
@@ -825,19 +826,21 @@ export class AgentSession {
825
826
  messages.push({
826
827
  role: 'custom',
827
828
  customType: 'prePromptContext',
828
- content: prePromptContextParts.join('\n\n'),
829
+ content: formatSystemReminderContext(prePromptContextParts),
829
830
  display: false,
830
831
  details: prePromptDetails,
831
832
  timestamp: Date.now()
832
833
  });
833
- for (const message of messages) {
834
- if (message.role === 'custom') {
835
- this.sessionManager.appendCustomMessageEntry(message.customType, message.content, message.display, message.details);
836
- }
837
- else if (message.role === 'user') {
838
- this.sessionManager.appendMessage(message);
839
- }
834
+ // Add user message
835
+ const userContent = [{ type: 'text', text: expandedText }];
836
+ if (currentImages) {
837
+ userContent.push(...currentImages);
840
838
  }
839
+ messages.push({
840
+ role: 'user',
841
+ content: userContent,
842
+ timestamp: Date.now()
843
+ });
841
844
  // Inject any pending "nextTurn" messages as context alongside the user message
842
845
  for (const msg of this._pendingNextTurnMessages) {
843
846
  messages.push(msg);
@@ -53,6 +53,6 @@ export type { SkillSyncStatusItem, SkillsSyncStatus } from './sync/skills-status
53
53
  export { uploadSkills } from './sync/skills-upload.js';
54
54
  export type { SkillUploadApprovalRequest, SkillsUploadResult } from './sync/skills-upload.js';
55
55
  export * from './tools/index.js';
56
- export { buildWorkbookPromptContext, fetchWorkbookConnectionState, formatWorkbookScopePromptContext } from './workbook-context/workbook-summary.js';
56
+ export { buildWorkbookPromptContext, fetchWorkbookConnectionState, formatWorkbookScopeReminder } from './workbook-context/workbook-summary.js';
57
57
  export { SCOPE_UNSET, type WorkbookConnectionState, type WorkbookScopeDetails, type WorkbookScopeStateRef } from './workbook-scope.js';
58
58
  //# sourceMappingURL=index.d.ts.map
package/dist/app/index.js CHANGED
@@ -40,6 +40,6 @@ export { downloadSkillsWithApproval } from './sync/skills-download.js';
40
40
  export { checkSkillsSyncStatus } from './sync/skills-status.js';
41
41
  export { uploadSkills } from './sync/skills-upload.js';
42
42
  export * from './tools/index.js';
43
- export { buildWorkbookPromptContext, fetchWorkbookConnectionState, formatWorkbookScopePromptContext } from './workbook-context/workbook-summary.js';
43
+ export { buildWorkbookPromptContext, fetchWorkbookConnectionState, formatWorkbookScopeReminder } from './workbook-context/workbook-summary.js';
44
44
  export { SCOPE_UNSET } from './workbook-scope.js';
45
45
  //# sourceMappingURL=index.js.map
@@ -1,215 +1,146 @@
1
- {
2
- "interfaces": {
3
- "Workbook": {
4
- "docstring": "Workbook wrapper.\nUsage:\n wb = Workbook(app.Workbooks(\"MyFile.xlsx\"))\n\nRaw COM access:\n wb._wb \u2014 the underlying COM Workbook object for direct platform API calls.\n Example: wb._wb.Worksheets(\"Sheet1\").Visible = False",
5
- "functions": {
6
- "getSheetNames": {
7
- "signature": "def getSheetNames() -> list[str]",
8
- "docstring": "Get the names of all sheets in the workbook.",
9
- "tags": [
10
- "action",
11
- "ask"
12
- ]
13
- },
14
- "getWorkbookSummary": {
15
- "signature": "def getWorkbookSummary() -> str",
16
- "docstring": "Get sheet names and used ranges for this workbook.\nReturns lines like:\n Sheets and their used ranges:\n Sheet1: A1:D10 (active)\n Inputs: (empty)",
17
- "tags": [
18
- "action",
19
- "ask"
20
- ]
21
- },
22
- "getSheet": {
23
- "signature": "def getSheet(name: str) -> 'Worksheet'",
24
- "docstring": "Get a sheet by name, returned as a wrapped Worksheet.",
25
- "tags": [
26
- "action",
27
- "ask"
28
- ]
29
- },
30
- "addSheet": {
31
- "signature": "def addSheet(name: str, index: int | None = None) -> 'Worksheet'",
32
- "docstring": "Add a new sheet at 0-based index. index=0 inserts before the first sheet.\nOmit index for Excel's default position.\nExample: wb.addSheet(\"NewSheet\", 0) # insert as first sheet",
33
- "tags": [
34
- "action"
35
- ]
36
- },
37
- "moveSheet": {
38
- "signature": "def moveSheet(name: str, index: int) -> None",
39
- "docstring": "Move a sheet to 0-based index. index=0 moves to first, index=Count-1 moves to last.\nExample: wb.moveSheet(\"Data\", 0) # move to first position",
40
- "tags": [
41
- "action"
42
- ]
43
- },
44
- "calculate": {
45
- "signature": "def calculate() -> None",
46
- "docstring": "Recalculate the entire workbook.\nDependent formulas don't update until after code block completes \u2014 read in a follow-up block.",
47
- "tags": [
48
- "action"
49
- ]
50
- },
51
- "errorCheck": {
52
- "signature": "def errorCheck(ranges: list[str] | None = None) -> str",
53
- "docstring": "Scan for errors (#REF!, #DIV/0!, #NAME?, #VALUE!, #N/A, #NULL!, #NUM!). Ranges MUST include a sheet name (\"Sheet1\" or \"Sheet1!A1:D50\") \u2014 bare ranges like \"A1:D50\" will fail.\n Args:\n ranges: Optional sheet names (\"Sheet1\") or ranges (\"Sheet1!A1:D50\"). Omit to check all.\n Returns:\n \"No issues found.\" or \"Errors (N):\nSheet1!A1: #REF!\n...\"",
54
- "tags": [
55
- "action",
56
- "ask"
57
- ]
58
- },
59
- "copyPasteRange": {
60
- "signature": "def copyPasteRange(from_range: str, to_address: str, paste_type: str = 'all', ) -> None",
61
- "docstring": "Copy range within same workbook via range.Copy + PasteSpecial.\nAddresses must include sheet name. Do NOT use Sheet.Copy (broken via pywin32).\nExample: wb.copyPasteRange(\"Sheet1!A1:D10\", \"Sheet2!A1\", paste_type=\"values\")",
62
- "tags": [
63
- "action"
64
- ]
65
- },
66
- "getNamedRangeInfo": {
67
- "signature": "def getNamedRangeInfo(max_count: int = 50) -> str",
68
- "docstring": "Get named ranges. Returns formatted string with name, reference, scope, and comment.\nExample output: \"Named Ranges (2):\\n Name: TaxRate | Ref: =Settings!$B$2 | Scope: workbook | Comment: ...\"\nReturns \"No named ranges found.\" if none exist.",
69
- "tags": [
70
- "action",
71
- "ask"
72
- ]
73
- }
74
- }
75
- },
76
- "Worksheet": {
77
- "docstring": "Worksheet wrapper.\nUsage:\n sheet = wb.getSheet(\"Sheet1\")\n\nRaw COM access:\n sheet._ws \u2014 the underlying COM Worksheet object for direct platform API calls.\n Use for borders, text orientation, cell protection, and other properties not covered by the wrapper.\n Example: sheet._ws.Range(\"A1\").Borders(9).LineStyle = 1 # xlEdgeBottom, xlContinuous",
78
- "functions": {
79
- "getSheetSummary": {
80
- "signature": "def getSheetSummary() -> str",
81
- "docstring": "Overview: name, used range, tables (with style/banded/header/total props),\npivots (with range), conditional formats (type/range/priority/stopIfTrue),\nautofilter (with filtering status), charts (with type).",
82
- "tags": [
83
- "action",
84
- "ask"
85
- ]
86
- },
87
- "getUsedRange": {
88
- "signature": "def getUsedRange() -> str",
89
- "docstring": "Get the used range address like \"A1:F20\", or \"\" if empty.",
90
- "tags": [
91
- "action",
92
- "ask"
93
- ]
94
- },
95
- "getCell": {
96
- "signature": "def getCell(address: str, include_style: bool = True) -> str",
97
- "docstring": "Formatted cell string: \"value(=FORMULA) (style_json)\". Formula always included.\nZero with custom format appends [0]: \"$ - [0]\".\nExample:\n print(sheet.getCell(\"A1\"))\n print(sheet.getCell(\"A1\", include_style=False))",
98
- "tags": [
99
- "action",
100
- "ask"
101
- ]
102
- },
103
- "getCellRange": {
104
- "signature": "def getCellRange(range_addr: str, include_style: bool = True) -> str",
105
- "docstring": "Markdown-like range: \"A1:Name | B1:Value\\nA2:Alice | B2:100\". Uses display text. Max 3000 cells; read larger areas in smaller chunks.\nAppends \"--- Style patterns ---\" section when include_style=True.",
106
- "tags": [
107
- "action",
108
- "ask"
109
- ]
110
- },
111
- "getRawCellData": {
112
- "signature": "def getRawCellData(address: str, formula: bool = False) -> Any",
113
- "docstring": "Get raw data value from a cell, preserving data type. Set formula=True to get the formula string.",
114
- "tags": [
115
- "action",
116
- "ask"
117
- ]
118
- },
119
- "getRawRangeData": {
120
- "signature": "def getRawRangeData(range_addr: str, formula: bool = False) -> list[list[Any]]",
121
- "docstring": "Get raw data for a range as 2D list. Always returns 2D list even for single row/column.",
122
- "tags": [
123
- "action",
124
- "ask"
125
- ]
126
- },
127
- "regexSearch": {
128
- "signature": "def regexSearch(patterns: list[str], match_case: bool = False) -> list[dict]",
129
- "docstring": "Regex search across used range using display text. Returns [{\"address\": \"A1\", \"value\": \"display text\"}, ...].\nExample: sheet.regexSearch([\"revenue\", \"cost\"])",
130
- "tags": [
131
- "action",
132
- "ask"
133
- ]
134
- },
135
- "setCell": {
136
- "signature": "def setCell(address: str, value: Any, number_format: str | None = None, note: str | None = None, ) -> None",
137
- "docstring": "Write value or formula. \"=\" prefix = formula. None or \"\" clears the cell.\nExamples:\n sheet.setCell(\"A1\", 8000)\n sheet.setCell(\"C1\", 0.15, number_format=\"0%\", note=\"Tax rate\")\n sheet.setCell(\"B1\", \"=SUM(A1:A10)\")",
138
- "tags": [
139
- "action"
140
- ]
141
- },
142
- "setCellRange": {
143
- "signature": "def setCellRange(range_addr: str, values: list[list[Any]], number_format: str | None = None, ) -> None",
144
- "docstring": "Bulk write \u2014 ALWAYS use for >100 cells. \"=\" prefix = formula.\nExamples:\n sheet.setCellRange(\"A1:B2\", [[1, 2], [3, 4]])\n sheet.setCellRange(\"A1:B2\", [[\"=SUM(C1)\", \"=SUM(D1)\"], [5, 6]], number_format=\"$#,##0\")",
145
- "tags": [
146
- "action"
147
- ]
148
- },
149
- "autoFill": {
150
- "signature": "def autoFill(source_range: str, target_range: str, fill_mode: str = 'auto', ) -> None",
151
- "docstring": "Drag-fill. Source must be contained within target. Default \"auto\" increments hardcoded numeric literals; use fill_mode=\"constant\" to copy literal values, then read back destination cells and check for empty/NaN values.\nUse fill_mode=\"constant\" when copying a single value without incrementing.\nWARNING: Single numeric value with \"auto\" creates incrementing sequence (0,1,2,3...).\nExample: sheet.autoFill(\"A1:A2\", \"A1:A10\")",
152
- "tags": [
153
- "action"
154
- ]
155
- },
156
- "addPicture": {
157
- "signature": "def addPicture(name: str, base64_data: str, anchor_cell: str) -> None",
158
- "docstring": "Add a picture from base64-encoded PNG or JPEG data. No data URI prefix.\nExample: sheet.addPicture(\"chart1\", base64_string, \"F2\")",
159
- "tags": [
160
- "action"
161
- ]
162
- },
163
- "setIBTextColors": {
164
- "signature": "def setIBTextColors(range_addr: str, ignored_constants: list[int] | None = None, colors: dict | None = None, ) -> None",
165
- "docstring": "IB text colors for numeric inputs only. Text strings and booleans are left untouched.\n- Blue/16711680: hard-coded numeric constants (int/float)\n- Black/0: formulas (same-sheet references)\n- Green/32768: formulas with cross-sheet references (contains '!')\nColors are BGR integers (native COM format).\nExample: sheet.setIBTextColors(\"A1:D10\", ignored_constants=[0])",
166
- "tags": [
167
- "action"
168
- ]
169
- }
170
- }
171
- }
172
- },
173
- "helpers": {
174
- "hex_to_bgr": {
175
- "signature": "def hex_to_bgr(hex_str: str) -> int",
176
- "docstring": "Convert \"#RRGGBB\" hex string to BGR integer for Excel COM.\nExample: ws.Range(\"A1\").Font.Color = hex_to_bgr(\"#FF0000\") # red",
177
- "tags": [
178
- "action",
179
- "ask"
180
- ]
181
- },
182
- "index_to_address": {
183
- "signature": "def index_to_address(row: int, col: int) -> str",
184
- "docstring": "Convert 0-based (row, col) to Excel address: index_to_address(0, 0) \u2192 \"A1\".",
185
- "tags": [
186
- "action",
187
- "ask"
188
- ]
189
- },
190
- "address_to_index": {
191
- "signature": "def address_to_index(address: str) -> tuple[int, int]",
192
- "docstring": "Parse \"A1\" into (row, col) 0-based tuple: address_to_index(\"B3\") \u2192 (2, 1).",
193
- "tags": [
194
- "action",
195
- "ask"
196
- ]
197
- },
198
- "col_letter": {
199
- "signature": "def col_letter(index: int) -> str",
200
- "docstring": "Convert 0-based column index to letter: col_letter(26) \u2192 \"AA\".",
201
- "tags": [
202
- "action",
203
- "ask"
204
- ]
205
- },
206
- "col_index": {
207
- "signature": "def col_index(letter: str) -> int",
208
- "docstring": "Convert column letter to 0-based index: col_index(\"AA\") \u2192 26.",
209
- "tags": [
210
- "action",
211
- "ask"
212
- ]
213
- }
214
- }
215
- }
1
+ {
2
+ "interfaces": {
3
+ "Workbook": {
4
+ "docstring": "Workbook wrapper.\nUsage:\n wb = Workbook(app.Workbooks(\"MyFile.xlsx\"))\n\nRaw COM access:\n wb._wb \u2014 the underlying COM Workbook object for direct platform API calls.\n Example: wb._wb.Worksheets(\"Sheet1\").Visible = False",
5
+ "functions": {
6
+ "getSheetNames": {
7
+ "signature": "def getSheetNames() -> list[str]",
8
+ "docstring": "Get the names of all sheets in the workbook.",
9
+ "tags": ["action", "ask"]
10
+ },
11
+ "getWorkbookSummary": {
12
+ "signature": "def getWorkbookSummary() -> str",
13
+ "docstring": "Get sheet names and used ranges for this workbook.\nReturns lines like:\n Sheets and their used ranges:\n Sheet1: A1:D10 (active)\n Inputs: (empty)",
14
+ "tags": ["action", "ask"]
15
+ },
16
+ "getSheet": {
17
+ "signature": "def getSheet(name: str) -> 'Worksheet'",
18
+ "docstring": "Get a sheet by name, returned as a wrapped Worksheet.",
19
+ "tags": ["action", "ask"]
20
+ },
21
+ "addSheet": {
22
+ "signature": "def addSheet(name: str, index: int | None = None) -> 'Worksheet'",
23
+ "docstring": "Add a new sheet at 0-based index. index=0 inserts before the first sheet.\nOmit index for Excel's default position.\nExample: wb.addSheet(\"NewSheet\", 0) # insert as first sheet",
24
+ "tags": ["action"]
25
+ },
26
+ "moveSheet": {
27
+ "signature": "def moveSheet(name: str, index: int) -> None",
28
+ "docstring": "Move a sheet to 0-based index. index=0 moves to first, index=Count-1 moves to last.\nExample: wb.moveSheet(\"Data\", 0) # move to first position",
29
+ "tags": ["action"]
30
+ },
31
+ "calculate": {
32
+ "signature": "def calculate() -> None",
33
+ "docstring": "Recalculate the entire workbook.\nDependent formulas don't update until after code block completes \u2014 read in a follow-up block.",
34
+ "tags": ["action"]
35
+ },
36
+ "errorCheck": {
37
+ "signature": "def errorCheck(ranges: list[str] | None = None) -> str",
38
+ "docstring": "Scan for errors (#REF!, #DIV/0!, #NAME?, #VALUE!, #N/A, #NULL!, #NUM!). Ranges MUST include a sheet name (\"Sheet1\" or \"Sheet1!A1:D50\") \u2014 bare ranges like \"A1:D50\" will fail.\n Args:\n ranges: Optional sheet names (\"Sheet1\") or ranges (\"Sheet1!A1:D50\"). Omit to check all.\n Returns:\n \"No issues found.\" or \"Errors (N):\nSheet1!A1: #REF!\n...\"",
39
+ "tags": ["action", "ask"]
40
+ },
41
+ "copyPasteRange": {
42
+ "signature": "def copyPasteRange(from_range: str, to_address: str, paste_type: str = 'all', ) -> None",
43
+ "docstring": "Copy range within same workbook via range.Copy + PasteSpecial.\nAddresses must include sheet name. Do NOT use Sheet.Copy (broken via pywin32).\nExample: wb.copyPasteRange(\"Sheet1!A1:D10\", \"Sheet2!A1\", paste_type=\"values\")",
44
+ "tags": ["action"]
45
+ },
46
+ "getNamedRangeInfo": {
47
+ "signature": "def getNamedRangeInfo(max_count: int = 50) -> str",
48
+ "docstring": "Get named ranges. Returns formatted string with name, reference, scope, and comment.\nExample output: \"Named Ranges (2):\\n Name: TaxRate | Ref: =Settings!$B$2 | Scope: workbook | Comment: ...\"\nReturns \"No named ranges found.\" if none exist.",
49
+ "tags": ["action", "ask"]
50
+ }
51
+ }
52
+ },
53
+ "Worksheet": {
54
+ "docstring": "Worksheet wrapper.\nUsage:\n sheet = wb.getSheet(\"Sheet1\")\n\nRaw COM access:\n sheet._ws \u2014 the underlying COM Worksheet object for direct platform API calls.\n Use for borders, text orientation, cell protection, and other properties not covered by the wrapper.\n Example: sheet._ws.Range(\"A1\").Borders(9).LineStyle = 1 # xlEdgeBottom, xlContinuous",
55
+ "functions": {
56
+ "getSheetSummary": {
57
+ "signature": "def getSheetSummary() -> str",
58
+ "docstring": "Overview: name, used range, tables (with style/banded/header/total props),\npivots (with range), conditional formats (type/range/priority/stopIfTrue),\nautofilter (with filtering status), charts (with type).",
59
+ "tags": ["action", "ask"]
60
+ },
61
+ "getUsedRange": {
62
+ "signature": "def getUsedRange() -> str",
63
+ "docstring": "Get the used range address like \"A1:F20\", or \"\" if empty.",
64
+ "tags": ["action", "ask"]
65
+ },
66
+ "getCell": {
67
+ "signature": "def getCell(address: str, include_style: bool = True) -> str",
68
+ "docstring": "Formatted cell string: \"value(=FORMULA) (style_json)\". Formula always included.\nZero with custom format appends [0]: \"$ - [0]\".\nExample:\n print(sheet.getCell(\"A1\"))\n print(sheet.getCell(\"A1\", include_style=False))",
69
+ "tags": ["action", "ask"]
70
+ },
71
+ "getCellRange": {
72
+ "signature": "def getCellRange(range_addr: str, include_style: bool = True) -> str",
73
+ "docstring": "Markdown-like range: \"A1:Name | B1:Value\\nA2:Alice | B2:100\". Uses display text. Max 3000 cells; read larger areas in smaller chunks.\nAppends \"--- Style patterns ---\" section when include_style=True.",
74
+ "tags": ["action", "ask"]
75
+ },
76
+ "getRawCellData": {
77
+ "signature": "def getRawCellData(address: str, formula: bool = False) -> Any",
78
+ "docstring": "Get raw data value from a cell, preserving data type. Set formula=True to get the formula string.",
79
+ "tags": ["action", "ask"]
80
+ },
81
+ "getRawRangeData": {
82
+ "signature": "def getRawRangeData(range_addr: str, formula: bool = False) -> list[list[Any]]",
83
+ "docstring": "Get raw data for a range as 2D list. Always returns 2D list even for single row/column.",
84
+ "tags": ["action", "ask"]
85
+ },
86
+ "regexSearch": {
87
+ "signature": "def regexSearch(patterns: list[str], match_case: bool = False) -> list[dict]",
88
+ "docstring": "Regex search across used range using display text. Returns [{\"address\": \"A1\", \"value\": \"display text\"}, ...].\nExample: sheet.regexSearch([\"revenue\", \"cost\"])",
89
+ "tags": ["action", "ask"]
90
+ },
91
+ "setCell": {
92
+ "signature": "def setCell(address: str, value: Any, number_format: str | None = None, note: str | None = None, ) -> None",
93
+ "docstring": "Write value or formula. \"=\" prefix = formula. None or \"\" clears the cell.\nExamples:\n sheet.setCell(\"A1\", 8000)\n sheet.setCell(\"C1\", 0.15, number_format=\"0%\", note=\"Tax rate\")\n sheet.setCell(\"B1\", \"=SUM(A1:A10)\")",
94
+ "tags": ["action"]
95
+ },
96
+ "setCellRange": {
97
+ "signature": "def setCellRange(range_addr: str, values: list[list[Any]], number_format: str | None = None, ) -> None",
98
+ "docstring": "Bulk write \u2014 ALWAYS use for >100 cells. \"=\" prefix = formula.\nExamples:\n sheet.setCellRange(\"A1:B2\", [[1, 2], [3, 4]])\n sheet.setCellRange(\"A1:B2\", [[\"=SUM(C1)\", \"=SUM(D1)\"], [5, 6]], number_format=\"$#,##0\")",
99
+ "tags": ["action"]
100
+ },
101
+ "autoFill": {
102
+ "signature": "def autoFill(source_range: str, target_range: str, fill_mode: str = 'auto', ) -> None",
103
+ "docstring": "Drag-fill. Source must be contained within target. Default \"auto\" increments hardcoded numeric literals; use fill_mode=\"constant\" to copy literal values, then read back destination cells and check for empty/NaN values.\nUse fill_mode=\"constant\" when copying a single value without incrementing.\nWARNING: Single numeric value with \"auto\" creates incrementing sequence (0,1,2,3...).\nExample: sheet.autoFill(\"A1:A2\", \"A1:A10\")",
104
+ "tags": ["action"]
105
+ },
106
+ "addPicture": {
107
+ "signature": "def addPicture(name: str, base64_data: str, anchor_cell: str) -> None",
108
+ "docstring": "Add a picture from base64-encoded PNG or JPEG data. No data URI prefix.\nExample: sheet.addPicture(\"chart1\", base64_string, \"F2\")",
109
+ "tags": ["action"]
110
+ },
111
+ "setIBTextColors": {
112
+ "signature": "def setIBTextColors(range_addr: str, ignored_constants: list[int] | None = None, colors: dict | None = None, ) -> None",
113
+ "docstring": "IB text colors for numeric inputs only. Text strings and booleans are left untouched.\n- Blue/16711680: hard-coded numeric constants (int/float)\n- Black/0: formulas (same-sheet references)\n- Green/32768: formulas with cross-sheet references (contains '!')\nColors are BGR integers (native COM format).\nExample: sheet.setIBTextColors(\"A1:D10\", ignored_constants=[0])",
114
+ "tags": ["action"]
115
+ }
116
+ }
117
+ }
118
+ },
119
+ "helpers": {
120
+ "hex_to_bgr": {
121
+ "signature": "def hex_to_bgr(hex_str: str) -> int",
122
+ "docstring": "Convert \"#RRGGBB\" hex string to BGR integer for Excel COM.\nExample: ws.Range(\"A1\").Font.Color = hex_to_bgr(\"#FF0000\") # red",
123
+ "tags": ["action", "ask"]
124
+ },
125
+ "index_to_address": {
126
+ "signature": "def index_to_address(row: int, col: int) -> str",
127
+ "docstring": "Convert 0-based (row, col) to Excel address: index_to_address(0, 0) \u2192 \"A1\".",
128
+ "tags": ["action", "ask"]
129
+ },
130
+ "address_to_index": {
131
+ "signature": "def address_to_index(address: str) -> tuple[int, int]",
132
+ "docstring": "Parse \"A1\" into (row, col) 0-based tuple: address_to_index(\"B3\") \u2192 (2, 1).",
133
+ "tags": ["action", "ask"]
134
+ },
135
+ "col_letter": {
136
+ "signature": "def col_letter(index: int) -> str",
137
+ "docstring": "Convert 0-based column index to letter: col_letter(26) \u2192 \"AA\".",
138
+ "tags": ["action", "ask"]
139
+ },
140
+ "col_index": {
141
+ "signature": "def col_index(letter: str) -> int",
142
+ "docstring": "Convert column letter to 0-based index: col_index(\"AA\") \u2192 26.",
143
+ "tags": ["action", "ask"]
144
+ }
145
+ }
146
+ }
@@ -1,3 +1,3 @@
1
1
  import type { RuntimePermissionPolicy } from '../../core/index.js';
2
- export declare function formatRuntimePermissionBypassContext(policy: RuntimePermissionPolicy): string;
2
+ export declare function formatRuntimePermissionBypassReminder(policy: RuntimePermissionPolicy): string;
3
3
  //# sourceMappingURL=permission-context.d.ts.map
@@ -1,4 +1,4 @@
1
- export function formatRuntimePermissionBypassContext(policy) {
2
- return `Runtime permissions bypass: ${policy.dangerouslySkipRuntimePermissions ? 'enabled' : 'disabled'}`;
1
+ export function formatRuntimePermissionBypassReminder(policy) {
2
+ return `Runtime permissions bypass: ${policy.dangerouslySkipRuntimePermissions ? 'enabled' : 'disabled'}.`;
3
3
  }
4
4
  //# sourceMappingURL=permission-context.js.map
@@ -0,0 +1,2 @@
1
+ export declare function formatSystemReminderContext(lines: string[]): string;
2
+ //# sourceMappingURL=system-reminder-context.d.ts.map
@@ -0,0 +1,8 @@
1
+ export function formatSystemReminderContext(lines) {
2
+ const text = lines
3
+ .map((line) => line.trim())
4
+ .filter(Boolean)
5
+ .join('\n');
6
+ return `<system_reminder>\n${text}\n</system_reminder>`;
7
+ }
8
+ //# sourceMappingURL=system-reminder-context.js.map
@@ -13,7 +13,7 @@ export interface WorkbookPromptContext {
13
13
  type WorkbookPromptReminderDetails = WorkbookConnectionState & {
14
14
  scopeMode?: ActiveScopeMode;
15
15
  };
16
- export declare function formatWorkbookScopePromptContext(details: WorkbookPromptReminderDetails): string;
16
+ export declare function formatWorkbookScopeReminder(details: WorkbookPromptReminderDetails): string;
17
17
  export declare function fetchWorkbookConnectionState(httpUrl?: string): Promise<WorkbookConnectionState>;
18
18
  export declare function buildWorkbookPromptContext(connectionState: WorkbookConnectionState, scope: WorkbookScope): WorkbookPromptContext;
19
19
  export {};