shortcutxl 0.3.50 → 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.
Files changed (132) hide show
  1. package/CHANGELOG.md +16 -1
  2. package/dist/app/agent-session-runtime-adapter.d.ts +1 -0
  3. package/dist/app/agent-session-runtime-adapter.js +1 -0
  4. package/dist/app/agent-session.d.ts +8 -0
  5. package/dist/app/agent-session.js +57 -17
  6. package/dist/app/approvals/types.d.ts +5 -0
  7. package/dist/app/auth/auth-storage.js +2 -7
  8. package/dist/app/extensions/slash-commands.js +1 -0
  9. package/dist/app/index.d.ts +3 -1
  10. package/dist/app/index.js +2 -1
  11. package/dist/app/local/tools/execute-code/observability.d.ts +4 -0
  12. package/dist/app/local/tools/execute-code/observability.js +57 -0
  13. package/dist/app/mcp/auth-status.d.ts +9 -1
  14. package/dist/app/mcp/auth-status.js +27 -16
  15. package/dist/app/mcp/catalog.d.ts +2 -1
  16. package/dist/app/mcp/catalog.js +15 -3
  17. package/dist/app/mcp/config.d.ts +14 -9
  18. package/dist/app/mcp/config.js +47 -61
  19. package/dist/app/mcp/connection.d.ts +1 -0
  20. package/dist/app/mcp/connection.js +100 -5
  21. package/dist/app/mcp/hosted-oauth-id.js +1 -4
  22. package/dist/app/mcp/hosted-oauth-provider.js +1 -1
  23. package/dist/app/mcp/index.js +24 -6
  24. package/dist/app/mcp/install.d.ts +21 -0
  25. package/dist/app/mcp/install.js +68 -0
  26. package/dist/app/mcp/oauth-discovery.d.ts +1 -0
  27. package/dist/app/mcp/oauth-discovery.js +45 -5
  28. package/dist/app/mcp/types.d.ts +2 -0
  29. package/dist/app/modes/action/agent.d.ts +3 -3
  30. package/dist/app/modes/action/agent.js +4 -9
  31. package/dist/app/modes/action/prompt.js +5 -5
  32. package/dist/app/modes/ask/agent.js +2 -1
  33. package/dist/app/modes/plan/agent.js +2 -1
  34. package/dist/app/modes/switch-mode.d.ts +8 -0
  35. package/dist/app/modes/switch-mode.js +9 -5
  36. package/dist/app/providers/model-resolver.d.ts +12 -0
  37. package/dist/app/providers/model-resolver.js +30 -0
  38. package/dist/app/providers/shortcut-stream.js +5 -1
  39. package/dist/app/session/permission-context.d.ts +3 -0
  40. package/dist/app/session/permission-context.js +4 -0
  41. package/dist/app/session/system-reminder-context.d.ts +2 -0
  42. package/dist/app/session/system-reminder-context.js +8 -0
  43. package/dist/app/session/tool-registry.js +13 -2
  44. package/dist/app/settings-manager.js +3 -3
  45. package/dist/app/sync/skills-download.d.ts +16 -0
  46. package/dist/app/sync/skills-download.js +65 -6
  47. package/dist/app/sync/skills-status.d.ts +44 -0
  48. package/dist/app/sync/skills-status.js +279 -0
  49. package/dist/app/sync/skills-upload.d.ts +15 -0
  50. package/dist/app/sync/skills-upload.js +62 -6
  51. package/dist/app/tools/get-tool-info.js +1 -0
  52. package/dist/app/tools/index.d.ts +1 -0
  53. package/dist/app/tools/index.js +1 -0
  54. package/dist/app/tools/session-settings/get-session-settings.d.ts +11 -0
  55. package/dist/app/tools/session-settings/get-session-settings.js +36 -0
  56. package/dist/app/tools/session-settings/index.d.ts +3 -0
  57. package/dist/app/tools/session-settings/index.js +3 -0
  58. package/dist/app/tools/session-settings/update-session-settings.d.ts +15 -0
  59. package/dist/app/tools/session-settings/update-session-settings.js +77 -0
  60. package/dist/app/tools/switch-mode.d.ts +4 -3
  61. package/dist/app/tools/switch-mode.js +26 -8
  62. package/dist/app/tools/task/manager.js +0 -2
  63. package/dist/app/tools/task/send-message.js +10 -3
  64. package/dist/app/tools/task/task.js +4 -1
  65. package/dist/app/workbook-context/workbook-summary.d.ts +1 -1
  66. package/dist/app/workbook-context/workbook-summary.js +6 -8
  67. package/dist/cli/args.js +3 -1
  68. package/dist/cli/mcp-commands.d.ts +2 -0
  69. package/dist/cli/mcp-commands.js +358 -0
  70. package/dist/cli.js +1085 -1069
  71. package/dist/config.js +2 -1
  72. package/dist/main.js +64 -77
  73. package/dist/model-ids.d.ts +4 -0
  74. package/dist/model-ids.js +3 -0
  75. package/dist/shared/files/lock-utils.d.ts +10 -0
  76. package/dist/shared/files/lock-utils.js +32 -0
  77. package/dist/shared/logging/agent-log.d.ts +1 -0
  78. package/dist/shared/logging/agent-log.js +4 -1
  79. package/dist/shared/platform/open.js +12 -5
  80. package/dist/shell/approvals/approval.d.ts +3 -19
  81. package/dist/shell/approvals/approval.js +2 -59
  82. package/dist/shell/approvals/excel-approval.d.ts +14 -3
  83. package/dist/shell/approvals/excel-approval.js +77 -7
  84. package/dist/shell/approvals/switch-mode-approval.d.ts +10 -0
  85. package/dist/shell/approvals/switch-mode-approval.js +35 -0
  86. package/dist/shell/approvals/task-spawn-approval.d.ts +6 -7
  87. package/dist/shell/approvals/task-spawn-approval.js +7 -29
  88. package/dist/shell/commands/mcp-command.d.ts +7 -1
  89. package/dist/shell/commands/mcp-command.js +93 -69
  90. package/dist/shell/components/interactive-shell-layout.d.ts +13 -2
  91. package/dist/shell/components/line-selection-scroll-container.d.ts +43 -0
  92. package/dist/shell/components/line-selection-scroll-container.js +257 -0
  93. package/dist/shell/components/primitives/footer.js +59 -13
  94. package/dist/shell/components/primitives/grid-table.d.ts +8 -1
  95. package/dist/shell/components/primitives/grid-table.js +45 -7
  96. package/dist/shell/export-html/canonical-trace-html.js +1 -1
  97. package/dist/shell/export-html/template.css +1124 -1110
  98. package/dist/shell/export-html/template.js +15 -11
  99. package/dist/shell/extension-ui.d.ts +1 -0
  100. package/dist/shell/index.d.ts +1 -0
  101. package/dist/shell/index.js +1 -0
  102. package/dist/shell/interactive/interactive-actions.d.ts +1 -0
  103. package/dist/shell/interactive/interactive-actions.js +1 -0
  104. package/dist/shell/interactive/interactive-mode-options.d.ts +8 -0
  105. package/dist/shell/interactive/interactive-mode.d.ts +18 -0
  106. package/dist/shell/interactive/interactive-mode.js +319 -11
  107. package/dist/shell/interactive/skills-workflow.d.ts +10 -2
  108. package/dist/shell/interactive/skills-workflow.js +66 -2
  109. package/dist/shell/keybindings.d.ts +1 -1
  110. package/dist/shell/keybindings.js +6 -4
  111. package/dist/shell/presentation/slash-command-rendering.js +4 -0
  112. package/dist/shell/session-client.d.ts +9 -0
  113. package/dist/shell/session-client.js +14 -1
  114. package/dist/shell/tools/presentation/registry.js +2 -2
  115. package/dist/shell/tools/presentation/renderers/tool-meta.d.ts +2 -2
  116. package/dist/shell/tools/presentation/renderers/tool-meta.js +4 -3
  117. package/dist/startup/interactive-commands.d.ts +8 -0
  118. package/dist/startup/interactive-commands.js +30 -0
  119. package/dist/tool-names.d.ts +2 -0
  120. package/dist/tool-names.js +2 -0
  121. package/dist/tui/terminal.js +2 -2
  122. package/package.json +1 -1
  123. package/skills/mcp/SKILL.md +94 -186
  124. package/user-docs/dist/index.html +13 -10
  125. package/user-docs/dist/shortcutxl-docs.pdf +0 -0
  126. package/xll/ShortcutXL.xll +0 -0
  127. package/xll/python/Lib/site-packages/httpx-0.28.1.dist-info/RECORD +1 -1
  128. package/xll/python/Lib/site-packages/pip-26.1.1.dist-info/RECORD +3 -3
  129. package/xll/python/Scripts/httpx.exe +0 -0
  130. package/xll/python/Scripts/pip.exe +0 -0
  131. package/xll/python/Scripts/pip3.12.exe +0 -0
  132. package/xll/python/Scripts/pip3.exe +0 -0
package/CHANGELOG.md CHANGED
@@ -1,4 +1,19 @@
1
- # Changelog
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.
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.
13
+ - **User-requested session settings** - When asked, agents can inspect available models and thinking levels or apply your requested session change.
14
+ - **Skill sync clarity** - Skill sync now shows startup differences plus per-file upload/download changes, source, and visibility.
15
+ - **Fast mode toggle** - Fast Mode now shows in the footer and can be toggled with `alt+f` or `/fast`, with clearer availability warnings.
16
+ - **Scrollable approvals** - Large approval and permission dialogs now scroll properly, including spreadsheet change tables in small terminals.
2
17
 
3
18
  ## [0.3.50]
4
19
 
@@ -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;
@@ -261,6 +263,12 @@ export declare class AgentSession {
261
263
  get model(): Model<any> | undefined;
262
264
  /** Current thinking level */
263
265
  get thinkingLevel(): ThinkingLevel;
266
+ get isFastModeEnabled(): boolean;
267
+ get isFastModeAllowed(): boolean;
268
+ get isFastModeAvailable(): boolean;
269
+ setFastModeAllowed(allowed: boolean): void;
270
+ setFastModeEnabled(enabled: boolean): void;
271
+ toggleFastMode(): boolean;
264
272
  /** Whether agent is currently streaming a response */
265
273
  get isStreaming(): boolean;
266
274
  /** Current effective system prompt (includes any per-turn extension modifications) */
@@ -16,6 +16,7 @@ import { isContextOverflow } from '@mariozechner/pi-ai';
16
16
  import { SessionState } from '../core/session-state.js';
17
17
  import { createCompactionActions, createErrorRecoveryActions, triggerCompactionIfNeeded } from '../core/session/compaction-bridge.js';
18
18
  import { SessionCompaction } from '../core/session/session-compaction.js';
19
+ import { isShortcutFastModeModel } from '../model-ids.js';
19
20
  import { formatFileUploadsContext, mergeFileUploads } from './file-uploads.js';
20
21
  import { expandPromptTemplate } from './resources/prompt-template-expansion.js';
21
22
  import { parseSkillBlock } from './resources/skill-block.js';
@@ -26,6 +27,7 @@ import { emitExtensionEvent } from './session/extension-emitter.js';
26
27
  import { ExtensionLifecycle } from './session/extension-lifecycle.js';
27
28
  import { ModelManager } from './session/model-manager.js';
28
29
  import { resolvePendingRefreshOverride } from './session/pending-refresh-overrides.js';
30
+ import { formatRuntimePermissionBypassReminder } from './session/permission-context.js';
29
31
  import { PersistenceHandler } from './session/persistence-handler.js';
30
32
  import { assertNotExtensionCommand, buildMessageContent, normalizeUserContent, tryExtensionCommand } from './session/prompt-pipeline.js';
31
33
  import { QueueTracker } from './session/queue-tracker.js';
@@ -35,6 +37,7 @@ import { executeNewSession, executeSwitchSession } from './session/session-lifec
35
37
  import { getAvailableThinkingLevels, supportsThinking, supportsXhighThinking } from './session/session-models.js';
36
38
  import { computeContextUsage, computeSessionStats } from './session/session-stats.js';
37
39
  import { expandSkillCommand } from './session/skill-expansion.js';
40
+ import { formatSystemReminderContext } from './session/system-reminder-context.js';
38
41
  import { ToolRegistry } from './session/tool-registry.js';
39
42
  import { ToolSummaryEmitter } from './session/tool-summary-emitter.js';
40
43
  import { isToolSummaryEligible } from './session/tool-summary-policy.js';
@@ -107,6 +110,7 @@ export class AgentSession {
107
110
  _tools;
108
111
  // Model manager — model switching, cycling, thinking level
109
112
  _models;
113
+ _fastModeAllowed = true;
110
114
  // Extension lifecycle — owns extension runner, bindings, reload
111
115
  _extensions;
112
116
  // Bridge objects for compaction/recovery/budget subsystems
@@ -125,6 +129,7 @@ export class AgentSession {
125
129
  this._prePromptContext = config.prePromptContext;
126
130
  this._budgetLimits = config.budgetLimits;
127
131
  this._observability = config.observability;
132
+ this._fastModeAllowed = config.fastModeAllowed ?? true;
128
133
  this._summaryEmitter = new ToolSummaryEmitter({
129
134
  enabled: config.enableToolSummaries ?? true,
130
135
  isFeatureEnabled: () => this.settingsManager.getToolSummariesEnabled(),
@@ -582,6 +587,32 @@ export class AgentSession {
582
587
  get thinkingLevel() {
583
588
  return this.agent.state.thinkingLevel;
584
589
  }
590
+ get isFastModeEnabled() {
591
+ return this.isFastModeAvailable && this.agent.speed === 'fast';
592
+ }
593
+ get isFastModeAllowed() {
594
+ return this._fastModeAllowed;
595
+ }
596
+ get isFastModeAvailable() {
597
+ return this._fastModeAllowed && isShortcutFastModeModel(this.model);
598
+ }
599
+ setFastModeAllowed(allowed) {
600
+ this._fastModeAllowed = allowed;
601
+ if (!allowed)
602
+ this.setFastModeEnabled(false);
603
+ }
604
+ setFastModeEnabled(enabled) {
605
+ this.agent.speed = enabled && this.isFastModeAvailable ? 'fast' : undefined;
606
+ }
607
+ toggleFastMode() {
608
+ if (!this.isFastModeAvailable) {
609
+ this.agent.speed = undefined;
610
+ return false;
611
+ }
612
+ const enabled = !this.isFastModeEnabled;
613
+ this.setFastModeEnabled(enabled);
614
+ return enabled;
615
+ }
585
616
  /** Whether agent is currently streaming a response */
586
617
  get isStreaming() {
587
618
  return this.agent.state.isStreaming;
@@ -781,6 +812,25 @@ export class AgentSession {
781
812
  }
782
813
  // Build messages array (custom message if any, then user message)
783
814
  const messages = [];
815
+ this.lastPrePromptDetails = undefined;
816
+ const prePromptContextParts = [formatRuntimePermissionBypassReminder(this.permissionPolicy)];
817
+ let prePromptDetails;
818
+ if (this._prePromptContext) {
819
+ const ctx = await this._prePromptContext();
820
+ if (ctx) {
821
+ this.lastPrePromptDetails = ctx.details;
822
+ prePromptDetails = ctx.details;
823
+ prePromptContextParts.unshift(ctx.text);
824
+ }
825
+ }
826
+ messages.push({
827
+ role: 'custom',
828
+ customType: 'prePromptContext',
829
+ content: formatSystemReminderContext(prePromptContextParts),
830
+ display: false,
831
+ details: prePromptDetails,
832
+ timestamp: Date.now()
833
+ });
784
834
  // Add user message
785
835
  const userContent = [{ type: 'text', text: expandedText }];
786
836
  if (currentImages) {
@@ -791,21 +841,6 @@ export class AgentSession {
791
841
  content: userContent,
792
842
  timestamp: Date.now()
793
843
  });
794
- this.lastPrePromptDetails = undefined;
795
- if (this._prePromptContext) {
796
- const ctx = await this._prePromptContext();
797
- if (ctx) {
798
- this.lastPrePromptDetails = ctx.details;
799
- messages.push({
800
- role: 'custom',
801
- customType: 'prePromptContext',
802
- content: ctx.text,
803
- display: false,
804
- details: ctx.details,
805
- timestamp: Date.now()
806
- });
807
- }
808
- }
809
844
  // Inject any pending "nextTurn" messages as context alongside the user message
810
845
  for (const msg of this._pendingNextTurnMessages) {
811
846
  messages.push(msg);
@@ -1149,11 +1184,16 @@ export class AgentSession {
1149
1184
  // =========================================================================
1150
1185
  /** Switch the session's active LLM to `model`, persisting the change. */
1151
1186
  async setModel(model) {
1152
- return this._models.setModel(model);
1187
+ await this._models.setModel(model);
1188
+ if (!this.isFastModeAvailable)
1189
+ this.setFastModeEnabled(false);
1153
1190
  }
1154
1191
  /** Cycle to the next configured model and report the switch result. */
1155
1192
  async cycleModel(direction = 'forward') {
1156
- return this._models.cycleModel(direction);
1193
+ const result = await this._models.cycleModel(direction);
1194
+ if (!this.isFastModeAvailable)
1195
+ this.setFastModeEnabled(false);
1196
+ return result;
1157
1197
  }
1158
1198
  /** Set the model's reasoning/thinking level for subsequent turns. */
1159
1199
  setThinkingLevel(level) {
@@ -66,4 +66,9 @@ export interface TaskSpawnApprovalData {
66
66
  /** Launch mode requested by the tool call before user approval overrides. */
67
67
  requestedRunInBackground: boolean;
68
68
  }
69
+ export interface SwitchModeApprovalData {
70
+ currentMode: string;
71
+ targetMode: string;
72
+ reason?: string;
73
+ }
69
74
  //# sourceMappingURL=types.d.ts.map
@@ -10,12 +10,7 @@ import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'f
10
10
  import { dirname, join } from 'path';
11
11
  import lockfile from 'proper-lockfile';
12
12
  import { getAgentDir } from '../../config.js';
13
- /**
14
- * Shared lock options so sync and async locks always use the same lock path.
15
- * realpath: false ensures both create the same .lock directory on Windows,
16
- * where fs.realpath can normalize paths differently.
17
- */
18
- const LOCK_BASE_OPTIONS = { realpath: false };
13
+ import { LOCK_BASE_OPTIONS, lockSyncWithRetries } from '../../shared/files/lock-utils.js';
19
14
  export class FileAuthStorageBackend {
20
15
  authPath;
21
16
  constructor(authPath = join(getAgentDir(), 'auth.json')) {
@@ -38,7 +33,7 @@ export class FileAuthStorageBackend {
38
33
  this.ensureFileExists();
39
34
  let release;
40
35
  try {
41
- release = lockfile.lockSync(this.authPath, LOCK_BASE_OPTIONS);
36
+ release = lockSyncWithRetries(this.authPath);
42
37
  const current = existsSync(this.authPath) ? readFileSync(this.authPath, 'utf-8') : undefined;
43
38
  const { result, next } = fn(current);
44
39
  if (next !== undefined) {
@@ -15,6 +15,7 @@ const ALL_BUILTIN_SLASH_COMMANDS = [
15
15
  // Model
16
16
  { name: 'model', description: 'Select model' },
17
17
  { name: 'thinking', description: 'Select thinking level' },
18
+ { name: 'fast', description: 'Toggle fast mode for subsequent turns' },
18
19
  { name: 'hide-thinking', description: 'Toggle visibility of thinking blocks' },
19
20
  // Checkpointing
20
21
  { name: 'resume', description: 'Resume a different session' },
@@ -48,9 +48,11 @@ export { readSkillProposalReviewSnapshot, type SkillProposalReviewSnapshot } fro
48
48
  export type { StartupInfoEntry } from './startup-info.js';
49
49
  export { downloadSkillsWithApproval } from './sync/skills-download.js';
50
50
  export type { SkillDownloadApprovalHandler, SkillDownloadApprovalRequest, SkillsDownloadResult } from './sync/skills-download.js';
51
+ export { checkSkillsSyncStatus } from './sync/skills-status.js';
52
+ export type { SkillSyncStatusItem, SkillsSyncStatus } from './sync/skills-status.js';
51
53
  export { uploadSkills } from './sync/skills-upload.js';
52
54
  export type { SkillUploadApprovalRequest, SkillsUploadResult } from './sync/skills-upload.js';
53
55
  export * from './tools/index.js';
54
- export { buildWorkbookPromptContext, fetchWorkbookConnectionState, formatWorkbookScopePromptContext } from './workbook-context/workbook-summary.js';
56
+ export { buildWorkbookPromptContext, fetchWorkbookConnectionState, formatWorkbookScopeReminder } from './workbook-context/workbook-summary.js';
55
57
  export { SCOPE_UNSET, type WorkbookConnectionState, type WorkbookScopeDetails, type WorkbookScopeStateRef } from './workbook-scope.js';
56
58
  //# sourceMappingURL=index.d.ts.map
package/dist/app/index.js CHANGED
@@ -37,8 +37,9 @@ export { default as skillProposalsExtension } from './skill-proposals/extension.
37
37
  export { getSkillProposalRoots } from './skill-proposals/proposal-fs.js';
38
38
  export { readSkillProposalReviewSnapshot } from './skill-proposals/review.js';
39
39
  export { downloadSkillsWithApproval } from './sync/skills-download.js';
40
+ export { checkSkillsSyncStatus } from './sync/skills-status.js';
40
41
  export { uploadSkills } from './sync/skills-upload.js';
41
42
  export * from './tools/index.js';
42
- export { buildWorkbookPromptContext, fetchWorkbookConnectionState, formatWorkbookScopePromptContext } from './workbook-context/workbook-summary.js';
43
+ export { buildWorkbookPromptContext, fetchWorkbookConnectionState, formatWorkbookScopeReminder } from './workbook-context/workbook-summary.js';
43
44
  export { SCOPE_UNSET } from './workbook-scope.js';
44
45
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,4 @@
1
+ import type { ShortcutClientLogger } from '../../../observability/index.js';
2
+ import type { ExcelExecApprovalObservability } from './executor.js';
3
+ export declare function createExecuteCodeApprovalObservability(clientLogger: ShortcutClientLogger): ExcelExecApprovalObservability;
4
+ //# sourceMappingURL=observability.d.ts.map
@@ -0,0 +1,57 @@
1
+ const TOOL_NAME = 'execute_code';
2
+ export function createExecuteCodeApprovalObservability(clientLogger) {
3
+ return {
4
+ onRequested: (request) => {
5
+ clientLogger.info({
6
+ module: 'tool',
7
+ event: 'tool_approval_requested',
8
+ data: {
9
+ tool_name: TOOL_NAME,
10
+ approval_kind: request.payload.kind
11
+ }
12
+ });
13
+ },
14
+ onAccepted: (request, choice) => {
15
+ clientLogger.info({
16
+ module: 'tool',
17
+ event: 'tool_approval_accepted',
18
+ data: {
19
+ tool_name: TOOL_NAME,
20
+ approval_kind: request.payload.kind,
21
+ accept_all: choice === 'Accept All'
22
+ }
23
+ });
24
+ },
25
+ onRejected: (request) => {
26
+ clientLogger.warn({
27
+ module: 'tool',
28
+ event: 'tool_approval_rejected',
29
+ data: {
30
+ tool_name: TOOL_NAME,
31
+ approval_kind: request.payload.kind
32
+ }
33
+ });
34
+ },
35
+ onReverted: (request) => {
36
+ clientLogger.info({
37
+ module: 'tool',
38
+ event: 'tool_approval_reverted',
39
+ data: {
40
+ tool_name: TOOL_NAME,
41
+ approval_kind: request.payload.kind
42
+ }
43
+ });
44
+ },
45
+ onRevertFailed: (request) => {
46
+ clientLogger.error({
47
+ module: 'tool',
48
+ event: 'tool_approval_revert_failed',
49
+ data: {
50
+ tool_name: TOOL_NAME,
51
+ approval_kind: request.payload.kind
52
+ }
53
+ });
54
+ }
55
+ };
56
+ }
57
+ //# sourceMappingURL=observability.js.map
@@ -1,4 +1,12 @@
1
1
  import type { AuthStorage } from '../auth/auth-storage.js';
2
+ import type { McpOAuthStore } from './oauth-state-store.js';
2
3
  import { type McpAuthStatus, type McpServerConfig } from './types.js';
3
- export declare function getMcpAuthStatus(serverName: string, config: McpServerConfig, authStorage?: AuthStorage): Promise<McpAuthStatus>;
4
+ export type McpAuthDiscoveryMode = 'never' | 'cached' | 'network';
5
+ export interface ResolveMcpAuthStatusOptions {
6
+ authStorage?: AuthStorage;
7
+ mcpOAuthStore?: McpOAuthStore;
8
+ discovery?: McpAuthDiscoveryMode;
9
+ }
10
+ export declare function resolveMcpAuthStatus(serverName: string, config: McpServerConfig, options?: ResolveMcpAuthStatusOptions): Promise<McpAuthStatus>;
11
+ export declare function getMcpAuthStatus(serverName: string, config: McpServerConfig, authStorage?: AuthStorage, mcpOAuthStore?: McpOAuthStore): Promise<McpAuthStatus>;
4
12
  //# sourceMappingURL=auth-status.d.ts.map
@@ -1,33 +1,44 @@
1
1
  import { getSecret } from '../connectors/secret-store.js';
2
2
  import { getHostedMcpOAuthProviderId } from './hosted-oauth-id.js';
3
+ import { resolveHostedMcpOAuthTimeoutMs, supportsHostedMcpOAuth } from './oauth-discovery.js';
3
4
  import { isHostedServerConfig, isStdioServerConfig } from './types.js';
4
5
  function hasConfiguredHeaders(headers) {
5
6
  return !!headers && Object.keys(headers).length > 0;
6
7
  }
7
- export async function getMcpAuthStatus(serverName, config, authStorage) {
8
+ export async function resolveMcpAuthStatus(serverName, config, options = {}) {
8
9
  if (isStdioServerConfig(config)) {
9
10
  return 'unsupported';
10
11
  }
11
12
  const staticHeaders = { ...(config.headers ?? {}) };
12
13
  const secretHeaders = config.connection ? getSecret(config.connection) : undefined;
13
- if (isHostedServerConfig(config) && config.oauth) {
14
- if (!authStorage) {
15
- return hasConfiguredHeaders(staticHeaders) || hasConfiguredHeaders(secretHeaders)
16
- ? 'configured'
17
- : 'not_logged_in';
18
- }
19
- const credential = authStorage.get(getHostedMcpOAuthProviderId(serverName, config));
20
- if (credential?.type === 'oauth') {
14
+ if (hasConfiguredHeaders(staticHeaders) || hasConfiguredHeaders(secretHeaders)) {
15
+ return 'configured';
16
+ }
17
+ if (isHostedServerConfig(config)) {
18
+ const discovery = options.discovery ?? 'cached';
19
+ const providerId = getHostedMcpOAuthProviderId(serverName, config);
20
+ if (options.authStorage?.get(providerId)?.type === 'oauth') {
21
21
  return 'oauth';
22
22
  }
23
- return hasConfiguredHeaders(staticHeaders) || hasConfiguredHeaders(secretHeaders)
24
- ? 'configured'
25
- : 'not_logged_in';
26
- }
27
- if (Object.keys(staticHeaders).length > 0 ||
28
- (secretHeaders && Object.keys(secretHeaders).length > 0)) {
29
- return 'configured';
23
+ if (config.oauth ||
24
+ (discovery !== 'never' && options.mcpOAuthStore?.getDiscoveryState(providerId))) {
25
+ return 'not_logged_in';
26
+ }
27
+ if (discovery === 'network' &&
28
+ (await supportsHostedMcpOAuth(serverName, config, options.mcpOAuthStore, {
29
+ timeoutMs: resolveHostedMcpOAuthTimeoutMs(config)
30
+ }).catch(() => false))) {
31
+ return 'not_logged_in';
32
+ }
33
+ return 'unsupported';
30
34
  }
31
35
  return 'unsupported';
32
36
  }
37
+ export async function getMcpAuthStatus(serverName, config, authStorage, mcpOAuthStore) {
38
+ return resolveMcpAuthStatus(serverName, config, {
39
+ authStorage,
40
+ mcpOAuthStore,
41
+ discovery: 'cached'
42
+ });
43
+ }
33
44
  //# sourceMappingURL=auth-status.js.map
@@ -7,7 +7,7 @@
7
7
  *
8
8
  * Use mcp_describe(server) to get full tool details.
9
9
  */
10
- import type { McpAuthStatus, McpConnection, McpServerStatus } from './types.js';
10
+ import type { McpAuthStatus, McpConnection, McpFailureKind, McpServerStatus } from './types.js';
11
11
  /**
12
12
  * Build a compact tool catalog — just server names and tool names.
13
13
  * Detailed descriptions are available via mcp_describe.
@@ -21,6 +21,7 @@ export declare function buildStatusLine(entries: Array<{
21
21
  name: string;
22
22
  connected?: McpConnection;
23
23
  failure?: string;
24
+ failureKind?: McpFailureKind;
24
25
  authStatus: McpAuthStatus;
25
26
  transport: McpServerStatus['transport'];
26
27
  }>): string;
@@ -7,6 +7,7 @@
7
7
  *
8
8
  * Use mcp_describe(server) to get full tool details.
9
9
  */
10
+ import { getAgentLogPath } from '../../shared/logging/agent-log.js';
10
11
  /**
11
12
  * Build a compact tool catalog — just server names and tool names.
12
13
  * Detailed descriptions are available via mcp_describe.
@@ -41,7 +42,7 @@ function formatAuthSuffix(authStatus) {
41
42
  case 'oauth':
42
43
  return 'oauth';
43
44
  case 'not_logged_in':
44
- return 'login required';
45
+ return 'needs login';
45
46
  case 'unsupported':
46
47
  default:
47
48
  return 'no auth';
@@ -49,6 +50,7 @@ function formatAuthSuffix(authStatus) {
49
50
  }
50
51
  export function buildStatusLine(entries) {
51
52
  const parts = [];
53
+ let hasFailure = false;
52
54
  for (const entry of entries) {
53
55
  const authSuffix = entry.transport === 'streamable_http' && entry.authStatus !== 'unsupported'
54
56
  ? `, ${formatAuthSuffix(entry.authStatus)}`
@@ -57,12 +59,22 @@ export function buildStatusLine(entries) {
57
59
  parts.push(`${entry.name} (${entry.connected.tools.length} tools${authSuffix})`);
58
60
  }
59
61
  else if (entry.failure) {
60
- parts.push(`${entry.name} (failed${authSuffix})`);
62
+ hasFailure = true;
63
+ if (entry.failureKind === 'auth_required') {
64
+ parts.push(`${entry.name} (needs login - run /login -> MCP: ${entry.name})`);
65
+ }
66
+ else {
67
+ parts.push(`${entry.name} (failed)`);
68
+ }
61
69
  }
62
70
  else {
63
71
  parts.push(`${entry.name} (${formatAuthSuffix(entry.authStatus)})`);
64
72
  }
65
73
  }
66
- return parts.length > 0 ? `[MCP] ${parts.join(', ')}` : '';
74
+ if (parts.length === 0) {
75
+ return '';
76
+ }
77
+ const logSuffix = hasFailure ? `; logs: ${getAgentLogPath()}` : '';
78
+ return `[MCP] ${parts.join(', ')}${logSuffix}`;
67
79
  }
68
80
  //# sourceMappingURL=catalog.js.map
@@ -1,20 +1,25 @@
1
1
  /**
2
- * Load and merge MCP server configs from global + project paths.
2
+ * Load MCP server config from the global agent directory.
3
3
  *
4
- * Global: ~/.shortcut/agent/mcp.json
5
- * Project: .shortcut/mcp.json (in cwd)
6
- *
7
- * Project servers override global servers with the same name.
4
+ * MCPs are user-level integrations for ShortcutXL spreadsheet sessions, not
5
+ * project-local coding config.
8
6
  */
9
- import { type McpServerConfig } from './types.js';
7
+ import { type McpConfig, type McpServerConfig } from './types.js';
8
+ export declare function getMcpConfigPath(globalConfigDir: string): string;
9
+ export declare function readMcpConfigFile(path: string): McpConfig;
10
+ export declare function writeMcpConfigFile(path: string, config: McpConfig): void;
11
+ export declare function upsertMcpServerConfig(path: string, name: string, config: McpServerConfig, options?: {
12
+ force?: boolean;
13
+ }): void;
14
+ export declare function removeMcpServerConfig(path: string, name: string): boolean;
15
+ export declare function validateServerConfig(name: string, cfg: unknown): cfg is McpServerConfig;
16
+ export declare function normalizeServerConfig(name: string, cfg: McpServerConfig): McpServerConfig;
10
17
  interface LoadConfigOptions {
11
18
  cwd: string;
12
19
  globalConfigDir: string;
13
20
  }
14
21
  /**
15
- * Load and merge MCP server configs from global and project paths.
16
- * Project-local servers override global servers with the same name.
17
- * Warns on secrets found in project-local config.
22
+ * Load MCP server configs from the global agent path only.
18
23
  */
19
24
  export declare function loadMcpConfig(options: LoadConfigOptions): Record<string, McpServerConfig>;
20
25
  export {};