shortcutxl 0.3.88 → 0.3.90
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/BINARY-INVENTORY.json +13 -13
- package/CHANGELOG.md +6 -0
- package/dist/app/agent-session-runtime-adapter.js +4 -1
- package/dist/app/background-agents/shorty/fix-prompts.d.ts +2 -2
- package/dist/app/background-agents/shorty/inspector/runtime.d.ts +1 -0
- package/dist/app/background-agents/shorty/inspector/runtime.js +25 -12
- package/dist/app/background-agents/shorty/runtime.js +3 -0
- package/dist/app/background-agents/shorty/types.d.ts +3 -2
- package/dist/app/local/tools/execute-code/approval-payload.d.ts +5 -1
- package/dist/app/local/tools/execute-code/executor.d.ts +4 -15
- package/dist/app/local/tools/execute-code/executor.js +56 -146
- package/dist/app/local/tools/execute-code/observability.js +0 -20
- package/dist/app/local/tools/execute-code/tool.js +0 -17
- package/dist/app/local/tools/execute-code/write-analyzer.js +2 -0
- package/dist/app/local/tools/take-screenshot/com-screenshot.js +8 -1
- package/dist/app/local/tools/take-screenshot/mog-screenshot.d.ts +0 -1
- package/dist/app/local/tools/take-screenshot/mog-screenshot.js +10 -17
- package/dist/app/modes/action/prompt.js +1 -1
- package/dist/app/modes/index.d.ts +1 -0
- package/dist/app/modes/index.js +4 -1
- package/dist/app/modes/installation/prompt-windows.js +1 -1
- package/dist/app/modes/manage/prompt.js +1 -1
- package/dist/app/modes/skill-forge/agent.d.ts +13 -0
- package/dist/app/modes/skill-forge/agent.js +33 -0
- package/dist/app/modes/skill-forge/prompt.d.ts +3 -0
- package/dist/app/modes/skill-forge/prompt.js +102 -0
- package/dist/app/prompts/spreadjs-api-reference.json +0 -6
- package/dist/app/providers/model-resolver.js +1 -0
- package/dist/app/session/session-catalog.d.ts +3 -0
- package/dist/app/session/session-catalog.js +2 -1
- package/dist/app/session/session-metadata.js +11 -0
- package/dist/app/session/session-models.js +1 -1
- package/dist/app/session/session-reader.d.ts +3 -0
- package/dist/app/session/session-reader.js +1 -0
- package/dist/app/subagents/defaults.d.ts +2 -1
- package/dist/app/subagents/defaults.js +1 -1
- package/dist/app/tools/skill-forge.d.ts +9 -0
- package/dist/app/tools/skill-forge.js +24 -0
- package/dist/app/tools/take-screenshot.d.ts +3 -0
- package/dist/app/tools/take-screenshot.js +5 -2
- package/dist/app/tools/task/manager.js +2 -1
- package/dist/app/tools/task/task.d.ts +3 -0
- package/dist/app/tools/task/task.js +31 -9
- package/dist/cli.js +843 -388
- package/dist/contracts/agent-api.d.ts +30 -24
- package/dist/contracts/agent-api.js +17 -13
- package/dist/contracts/agent-session-store.d.ts +3 -0
- package/dist/contracts/agent-skill-forge.d.ts +67 -0
- package/dist/contracts/agent-skill-forge.js +53 -0
- package/dist/contracts/agent-snapshot.d.ts +14 -0
- package/dist/contracts/agent-snapshot.js +6 -0
- package/dist/core/agent-snapshot-builder.js +6 -2
- package/dist/core/embedded-agent-facade.d.ts +2 -1
- package/dist/core/embedded-agent-facade.js +5 -2
- package/dist/core/pending-host-tool-requests.d.ts +1 -1
- package/dist/core/pending-host-tool-requests.js +1 -1
- package/dist/core/prompts/agent-guidelines.d.ts +3 -3
- package/dist/core/prompts/agent-guidelines.js +23 -14
- package/dist/core/prompts/take-screenshot.d.ts +1 -1
- package/dist/core/prompts/take-screenshot.js +1 -0
- package/dist/core/skill-forge/index.d.ts +3 -0
- package/dist/core/skill-forge/index.js +3 -0
- package/dist/core/skill-forge/skill-forge-state-manager.d.ts +20 -0
- package/dist/core/skill-forge/skill-forge-state-manager.js +39 -0
- package/dist/credits/shortcut-credits.d.ts +15 -0
- package/dist/credits/shortcut-credits.js +53 -0
- package/dist/embedded-agent/ai-invoke.d.ts +1 -1
- package/dist/embedded-agent/ai-invoke.js +6 -5
- package/dist/embedded-agent/compose.js +58 -41
- package/dist/embedded-agent/host-runtime-options.d.ts +1 -1
- package/dist/embedded-agent/host-runtime-options.js +12 -12
- package/dist/embedded-agent/host-tools/execute-bash-command/contract.js +4 -2
- package/dist/embedded-agent/host-tools/execute-code/allowed-functions.json +0 -2
- package/dist/embedded-agent/host-tools/take-screenshot/contract.d.ts +1 -1
- package/dist/embedded-agent/index.d.ts +3 -3
- package/dist/embedded-agent/inspector/agent.d.ts +14 -0
- package/dist/embedded-agent/{review → inspector}/agent.js +14 -7
- package/dist/embedded-agent/{review → inspector}/coordinator.d.ts +17 -11
- package/dist/embedded-agent/{review → inspector}/coordinator.js +49 -29
- package/dist/embedded-agent/inspector/findings.d.ts +7 -0
- package/dist/embedded-agent/{review → inspector}/findings.js +9 -9
- package/dist/embedded-agent/model-registry.d.ts +1 -0
- package/dist/embedded-agent/model-registry.js +1 -0
- package/dist/embedded-agent/prompt/modes/action.js +1 -1
- package/dist/embedded-agent/prompt/modes/ask.js +1 -1
- package/dist/embedded-agent/suggestions.js +2 -1
- package/dist/embedded-agent/worker-bridge/dispatch.js +7 -4
- package/dist/embedded-agent/worker-bridge/host-client.d.ts +3 -1
- package/dist/embedded-agent/worker-bridge/host-client.js +31 -14
- package/dist/endpoints.d.ts +1 -0
- package/dist/endpoints.js +1 -0
- package/dist/main.js +37 -4
- package/dist/mode-names.d.ts +5 -0
- package/dist/mode-names.js +4 -2
- package/dist/model-ids.d.ts +4 -0
- package/dist/model-ids.js +10 -1
- package/dist/rpc/index.d.ts +1 -1
- package/dist/rpc/rpc-host.d.ts +30 -1
- package/dist/rpc/rpc-host.js +129 -25
- package/dist/rpc/rpc-mode.d.ts +1 -1
- package/dist/rpc/rpc-types.d.ts +21 -2
- package/dist/shell/components/shorty-issues.d.ts +3 -3
- package/dist/shell/components/shorty-issues.js +5 -5
- package/dist/shell/interactive/interactive-mode.js +11 -11
- package/dist/shortcut-model-catalog.js +12 -6
- package/dist/subagent-model-policy.d.ts +12 -2
- package/dist/subagent-model-policy.js +38 -2
- package/dist/subagent-thinking-policy.d.ts +5 -3
- package/dist/subagent-thinking-policy.js +5 -4
- package/dist/tool-names.d.ts +1 -0
- package/dist/tool-names.js +1 -0
- package/native-app/main/index.js +39 -7
- package/native-app/package.json +1 -1
- package/native-app/renderer/assets/Alegreya-Italic-Variable-BNGsTFBD.woff2 +0 -0
- package/native-app/renderer/assets/Alegreya-Variable-BCUEsrKK.woff2 +0 -0
- package/native-app/renderer/assets/AvQest-DwQOLw3s.woff2 +0 -0
- package/native-app/renderer/assets/Cinzel-Variable-BOqWLKHx.woff2 +0 -0
- package/native-app/renderer/assets/DiabloHeavy-aRIenZkJ.woff2 +0 -0
- package/native-app/renderer/assets/anvil-BULXnOOB.png +3 -0
- package/native-app/renderer/assets/frame-DDQ6ScMl.png +3 -0
- package/native-app/renderer/assets/{index-DI6nQ3aM.js → index-Dep1w85F.js} +4261 -298
- package/native-app/renderer/assets/{index-DNnVuJQL.css → index-DsYjsaRU.css} +1448 -67
- package/native-app/renderer/assets/plaque-C6n7SCaF.png +3 -0
- package/native-app/renderer/assets/rock-CXFUiLgi.png +3 -0
- package/native-app/renderer/index.html +2 -2
- package/package.json +6 -2
- package/skills/skill-creator/SKILL.md +89 -440
- package/user-docs/dist/index.html +13 -25
- package/user-docs/security.md +4 -9
- package/xll/modules/shortcut_xl/_exec_entry.py +19 -4
- package/xll/modules/shortcut_xl/_exec_sandbox.py +2 -2
- package/xll/modules/shortcut_xl/_log.py +9 -2
- package/xll/modules/shortcut_xl/_threading.py +1 -1
- package/xll/python/Lib/site-packages/httpx-0.28.1.dist-info/RECORD +1 -1
- package/xll/python/Lib/site-packages/idna-3.18.dist-info/RECORD +1 -1
- package/xll/python/Lib/site-packages/pip-26.2.dist-info/RECORD +3 -3
- package/xll/python/Lib/site-packages/pywin32-311.dist-info/RECORD +2 -2
- package/xll/python/Scripts/httpx.exe +0 -0
- package/xll/python/Scripts/idna.exe +0 -0
- package/xll/python/Scripts/pip.exe +0 -0
- package/xll/python/Scripts/pip3.13.exe +0 -0
- package/xll/python/Scripts/pip3.exe +0 -0
- package/xll/python/Scripts/pywin32_postinstall.exe +0 -0
- package/xll/python/Scripts/pywin32_testall.exe +0 -0
- package/dist/embedded-agent/review/agent.d.ts +0 -14
- package/dist/embedded-agent/review/findings.d.ts +0 -7
- package/skills/skill-creator/LICENSE.txt +0 -202
- package/skills/skill-creator/agents/analyzer.md +0 -274
- package/skills/skill-creator/agents/comparator.md +0 -202
- package/skills/skill-creator/agents/grader.md +0 -223
- package/skills/skill-creator/assets/eval_review.html +0 -292
- package/skills/skill-creator/eval-viewer/generate_review.py +0 -471
- package/skills/skill-creator/eval-viewer/viewer.html +0 -1478
- package/skills/skill-creator/references/schemas.md +0 -430
- package/skills/skill-creator/scripts/__init__.py +0 -0
- package/skills/skill-creator/scripts/aggregate_benchmark.py +0 -401
- package/skills/skill-creator/scripts/generate_report.py +0 -326
- package/skills/skill-creator/scripts/improve_description.py +0 -232
- package/skills/skill-creator/scripts/package_skill.py +0 -136
- package/skills/skill-creator/scripts/quick_validate.py +0 -103
- package/skills/skill-creator/scripts/run_eval.py +0 -223
- package/skills/skill-creator/scripts/run_loop.py +0 -324
- package/skills/skill-creator/scripts/utils.py +0 -47
package/BINARY-INVENTORY.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"generatedAt": "2026-
|
|
3
|
+
"generatedAt": "2026-09-02T05:35:16.912Z",
|
|
4
4
|
"package": "shortcutxl",
|
|
5
5
|
"build": {
|
|
6
6
|
"builder": "github-actions",
|
|
7
7
|
"repository": "lyfegame/shortcut",
|
|
8
|
-
"sourceRef": "refs/heads/
|
|
9
|
-
"sourceCommit": "
|
|
10
|
-
"workflowRef": "lyfegame/shortcut/.github/workflows/release-shortcut-cli-npm-package.yml@refs/heads/
|
|
11
|
-
"runId": "
|
|
8
|
+
"sourceRef": "refs/heads/codex/excel-preexecution-approval",
|
|
9
|
+
"sourceCommit": "2520273120cc4b4024d877790eacf6f41fefdd7c",
|
|
10
|
+
"workflowRef": "lyfegame/shortcut/.github/workflows/release-shortcut-cli-npm-package.yml@refs/heads/codex/excel-preexecution-approval",
|
|
11
|
+
"runId": "33595155271",
|
|
12
12
|
"runnerOs": "Windows",
|
|
13
13
|
"runnerImage": "win25-vs2026",
|
|
14
|
-
"runnerImageVersion": "
|
|
14
|
+
"runnerImageVersion": "20260824.214.3"
|
|
15
15
|
},
|
|
16
16
|
"binaryExtensions": [
|
|
17
17
|
".dll",
|
|
@@ -550,7 +550,7 @@
|
|
|
550
550
|
},
|
|
551
551
|
{
|
|
552
552
|
"path": "xll/python/Scripts/httpx.exe",
|
|
553
|
-
"sha256": "
|
|
553
|
+
"sha256": "a7f8d80085b1d17fdf993cd7246d55f05726e3eb624859a8ba3b69b76368bd4c",
|
|
554
554
|
"source": "httpx console launcher installed into embedded Python",
|
|
555
555
|
"version": "see packaged httpx distribution",
|
|
556
556
|
"builtBy": "third-party",
|
|
@@ -558,7 +558,7 @@
|
|
|
558
558
|
},
|
|
559
559
|
{
|
|
560
560
|
"path": "xll/python/Scripts/idna.exe",
|
|
561
|
-
"sha256": "
|
|
561
|
+
"sha256": "75e2f1c65f561084f603823794d6ad5877ef0a5b1ef0b1fffff096603479642a",
|
|
562
562
|
"source": "Python package console launcher installed into embedded Python",
|
|
563
563
|
"version": "see owning Python package metadata in site-packages",
|
|
564
564
|
"builtBy": "third-party",
|
|
@@ -566,7 +566,7 @@
|
|
|
566
566
|
},
|
|
567
567
|
{
|
|
568
568
|
"path": "xll/python/Scripts/pip.exe",
|
|
569
|
-
"sha256": "
|
|
569
|
+
"sha256": "f68ea8e144f74e0f9748750a5fc21b73e11d63486c905730aa474e28f3bab8e7",
|
|
570
570
|
"source": "pip console launcher installed into embedded Python",
|
|
571
571
|
"version": "see packaged pip distribution",
|
|
572
572
|
"builtBy": "third-party",
|
|
@@ -574,7 +574,7 @@
|
|
|
574
574
|
},
|
|
575
575
|
{
|
|
576
576
|
"path": "xll/python/Scripts/pip3.13.exe",
|
|
577
|
-
"sha256": "
|
|
577
|
+
"sha256": "f68ea8e144f74e0f9748750a5fc21b73e11d63486c905730aa474e28f3bab8e7",
|
|
578
578
|
"source": "pip console launcher installed into embedded Python",
|
|
579
579
|
"version": "see packaged pip distribution",
|
|
580
580
|
"builtBy": "third-party",
|
|
@@ -582,7 +582,7 @@
|
|
|
582
582
|
},
|
|
583
583
|
{
|
|
584
584
|
"path": "xll/python/Scripts/pip3.exe",
|
|
585
|
-
"sha256": "
|
|
585
|
+
"sha256": "f68ea8e144f74e0f9748750a5fc21b73e11d63486c905730aa474e28f3bab8e7",
|
|
586
586
|
"source": "pip console launcher installed into embedded Python",
|
|
587
587
|
"version": "see packaged pip distribution",
|
|
588
588
|
"builtBy": "third-party",
|
|
@@ -590,7 +590,7 @@
|
|
|
590
590
|
},
|
|
591
591
|
{
|
|
592
592
|
"path": "xll/python/Scripts/pywin32_postinstall.exe",
|
|
593
|
-
"sha256": "
|
|
593
|
+
"sha256": "3d5142d3d301b5b22ec9f9ba2d29c9f8a4a73bad069389a73dafbd61e2b37696",
|
|
594
594
|
"source": "Python package console launcher installed into embedded Python",
|
|
595
595
|
"version": "see owning Python package metadata in site-packages",
|
|
596
596
|
"builtBy": "third-party",
|
|
@@ -598,7 +598,7 @@
|
|
|
598
598
|
},
|
|
599
599
|
{
|
|
600
600
|
"path": "xll/python/Scripts/pywin32_testall.exe",
|
|
601
|
-
"sha256": "
|
|
601
|
+
"sha256": "494be3de764340437d1fb12aaaefaf8f47c5a482f14834da3a17b080c71d6e16",
|
|
602
602
|
"source": "Python package console launcher installed into embedded Python",
|
|
603
603
|
"version": "see owning Python package metadata in site-packages",
|
|
604
604
|
"builtBy": "third-party",
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.3.90]
|
|
4
|
+
|
|
5
|
+
- **Skill Forge** - A recursive self-improvement loop for skills. Create or improve personal skills by giving Skill Forge tasks and a grading bar to train, evaluate, and refine against.
|
|
6
|
+
- **Safer, more reliable Excel changes** - Shortcut now asks for approval before making workbook changes and allows longer operations to finish without timing out.
|
|
7
|
+
- **Credit usage at a glance** - See today's personal credit usage for non-teams users.
|
|
8
|
+
|
|
3
9
|
## [0.3.88]
|
|
4
10
|
|
|
5
11
|
- **More reliable app startup** - Fixed startup failures on slower or managed Windows computers.
|
|
@@ -68,9 +68,12 @@ function createAgentSessionCore(session, pendingHostToolRequests, shortyRuntime)
|
|
|
68
68
|
session.replaceToolsByName(configuration.toolNames);
|
|
69
69
|
session.agent.setSystemPrompt(configuration.systemPrompt);
|
|
70
70
|
},
|
|
71
|
-
async
|
|
71
|
+
async configureInspector(enabled) {
|
|
72
72
|
shortyRuntime.configureInspector(enabled);
|
|
73
73
|
},
|
|
74
|
+
async runReviewBuddy() {
|
|
75
|
+
shortyRuntime.runInspector();
|
|
76
|
+
},
|
|
74
77
|
async runContextReview(input) {
|
|
75
78
|
await shortyRuntime.runDoctor(input.trigger);
|
|
76
79
|
},
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AgentContextReviewRecommendation,
|
|
2
|
-
export declare function formatInspectorFixRequest(findings: readonly
|
|
1
|
+
import type { AgentContextReviewRecommendation, AgentInspectorFinding } from '../../../contracts/agent-api.js';
|
|
2
|
+
export declare function formatInspectorFixRequest(findings: readonly AgentInspectorFinding[]): string;
|
|
3
3
|
export declare function formatDoctorFixRequest(recommendations: readonly AgentContextReviewRecommendation[]): string;
|
|
4
4
|
//# sourceMappingURL=fix-prompts.d.ts.map
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { CreateLocalShortyRuntimeOptions, LocalShortyEvent } from '../types.js';
|
|
2
2
|
export interface LocalInspectorRuntime {
|
|
3
3
|
configure(enabled: boolean): void;
|
|
4
|
+
run(): void;
|
|
4
5
|
dispose(): void;
|
|
5
6
|
}
|
|
6
7
|
export declare function createLocalInspectorRuntime(options: CreateLocalShortyRuntimeOptions, emit: (event: LocalShortyEvent) => void): LocalInspectorRuntime;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { AgentEventKind } from '../../../../contracts/agent-api.js';
|
|
2
2
|
import { AgentLoopEventType } from '../../../../core/core-types.js';
|
|
3
3
|
import { getActiveUserMessageId } from '../../../../core/user-message-id.js';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { INSPECTOR_QUERY, INSPECTOR_SYSTEM_PROMPT } from '../../../../embedded-agent/inspector/agent.js';
|
|
5
|
+
import { InspectorCoordinator } from '../../../../embedded-agent/inspector/coordinator.js';
|
|
6
6
|
import { EXECUTE_CODE } from '../../../../tool-names.js';
|
|
7
7
|
import { convertToLlm } from '../../../messages.js';
|
|
8
8
|
import { runLocalShortyAgent } from '../execution.js';
|
|
@@ -38,10 +38,10 @@ function createLinkedTimeoutSignal(parent) {
|
|
|
38
38
|
}
|
|
39
39
|
export function createLocalInspectorRuntime(options, emit) {
|
|
40
40
|
const isAvailable = options.isInspectorAvailable ?? (() => true);
|
|
41
|
-
const coordinator = new
|
|
41
|
+
const coordinator = new InspectorCoordinator({
|
|
42
42
|
enabled: options.enabled ?? false,
|
|
43
43
|
emit: (event) => {
|
|
44
|
-
if (event.kind === AgentEventKind.
|
|
44
|
+
if (event.kind === AgentEventKind.InspectorUpdated)
|
|
45
45
|
emit(event);
|
|
46
46
|
},
|
|
47
47
|
hasCredits: options.hasCredits ?? (() => true),
|
|
@@ -65,7 +65,7 @@ export function createLocalInspectorRuntime(options, emit) {
|
|
|
65
65
|
const result = await runLocalShortyAgent({
|
|
66
66
|
modelRegistry: options.modelRegistry,
|
|
67
67
|
parent: {
|
|
68
|
-
systemPrompt:
|
|
68
|
+
systemPrompt: INSPECTOR_SYSTEM_PROMPT,
|
|
69
69
|
messages: convertToLlm([...input.mainContext.messages]),
|
|
70
70
|
tools: [executeCode],
|
|
71
71
|
continuationRunId: input.reviewId,
|
|
@@ -77,8 +77,8 @@ export function createLocalInspectorRuntime(options, emit) {
|
|
|
77
77
|
})
|
|
78
78
|
},
|
|
79
79
|
controller: {
|
|
80
|
-
kind: 'inspector
|
|
81
|
-
instruction:
|
|
80
|
+
kind: 'inspector',
|
|
81
|
+
instruction: INSPECTOR_QUERY,
|
|
82
82
|
effortLevel: 'low',
|
|
83
83
|
maxTurns: 6,
|
|
84
84
|
signal: timed.signal,
|
|
@@ -116,22 +116,22 @@ export function createLocalInspectorRuntime(options, emit) {
|
|
|
116
116
|
}
|
|
117
117
|
}
|
|
118
118
|
});
|
|
119
|
-
let
|
|
119
|
+
let inspectorTurnHadWorkbookWrite = false;
|
|
120
120
|
const unsubscribeSession = options.session.subscribe((event) => {
|
|
121
121
|
if (event.type === AgentLoopEventType.AgentStart) {
|
|
122
|
-
|
|
122
|
+
inspectorTurnHadWorkbookWrite = false;
|
|
123
123
|
return;
|
|
124
124
|
}
|
|
125
125
|
if (event.type === AgentLoopEventType.ToolExecutionEnd &&
|
|
126
126
|
event.toolName === EXECUTE_CODE &&
|
|
127
127
|
isAvailable() &&
|
|
128
128
|
hasWorkbookChanges(event.result?.details)) {
|
|
129
|
-
|
|
129
|
+
inspectorTurnHadWorkbookWrite = true;
|
|
130
130
|
return;
|
|
131
131
|
}
|
|
132
|
-
if (event.type !== AgentLoopEventType.AgentEnd || !
|
|
132
|
+
if (event.type !== AgentLoopEventType.AgentEnd || !inspectorTurnHadWorkbookWrite)
|
|
133
133
|
return;
|
|
134
|
-
|
|
134
|
+
inspectorTurnHadWorkbookWrite = false;
|
|
135
135
|
if (!isAvailable())
|
|
136
136
|
return;
|
|
137
137
|
const userMessageId = getActiveUserMessageId(event.messages);
|
|
@@ -147,6 +147,19 @@ export function createLocalInspectorRuntime(options, emit) {
|
|
|
147
147
|
configure(enabled) {
|
|
148
148
|
coordinator.configure(enabled);
|
|
149
149
|
},
|
|
150
|
+
run() {
|
|
151
|
+
if (!isAvailable())
|
|
152
|
+
return;
|
|
153
|
+
const messages = options.session.messages;
|
|
154
|
+
const userMessageId = getActiveUserMessageId(messages);
|
|
155
|
+
if (!userMessageId)
|
|
156
|
+
return;
|
|
157
|
+
coordinator.run({
|
|
158
|
+
continuationRunId: userMessageId,
|
|
159
|
+
userMessageId,
|
|
160
|
+
mainContext: { messages: [...messages] }
|
|
161
|
+
});
|
|
162
|
+
},
|
|
150
163
|
dispose() {
|
|
151
164
|
unsubscribeSession();
|
|
152
165
|
coordinator.dispose();
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import type { AgentContextReviewRecommendation, AgentContextReviewTrigger, AgentContextReviewUpdatedEvent,
|
|
1
|
+
import type { AgentContextReviewRecommendation, AgentContextReviewTrigger, AgentContextReviewUpdatedEvent, AgentInspectorUpdatedEvent } from '../../../contracts/agent-api.js';
|
|
2
2
|
import type { AgentModelRegistry } from '../../../contracts/agent-model.js';
|
|
3
3
|
import type { AgentSession } from '../../agent-session.js';
|
|
4
|
-
export type LocalShortyEvent = AgentContextReviewUpdatedEvent |
|
|
4
|
+
export type LocalShortyEvent = AgentContextReviewUpdatedEvent | AgentInspectorUpdatedEvent;
|
|
5
5
|
export type LocalContextReviewDecision = 'apply_requested' | 'closed' | 'dismissed';
|
|
6
6
|
export type LocalShortyEventListener = (event: LocalShortyEvent) => void;
|
|
7
7
|
export interface LocalShortyRuntime {
|
|
8
8
|
subscribe(listener: LocalShortyEventListener): () => void;
|
|
9
9
|
configureInspector(enabled: boolean): void;
|
|
10
|
+
runInspector(): void;
|
|
10
11
|
configureDoctor(enabled: boolean): void;
|
|
11
12
|
runDoctor(trigger: AgentContextReviewTrigger): Promise<void>;
|
|
12
13
|
runAutomaticDoctorIfDue(now?: Date): Promise<boolean>;
|
|
@@ -6,6 +6,10 @@ export interface ExcelDiffApprovalPayload {
|
|
|
6
6
|
kind: 'diff';
|
|
7
7
|
description: string;
|
|
8
8
|
}
|
|
9
|
+
export interface ExcelWriteApprovalPayload {
|
|
10
|
+
kind: 'write';
|
|
11
|
+
description: string;
|
|
12
|
+
}
|
|
9
13
|
export interface OfficeDangerousApprovalPayload {
|
|
10
14
|
kind: 'dangerous';
|
|
11
15
|
description: string;
|
|
@@ -13,5 +17,5 @@ export interface OfficeDangerousApprovalPayload {
|
|
|
13
17
|
summary: string;
|
|
14
18
|
operations: OfficeApprovalOperation[];
|
|
15
19
|
}
|
|
16
|
-
export type OfficeApprovalPayload = ExcelDiffApprovalPayload | OfficeDangerousApprovalPayload;
|
|
20
|
+
export type OfficeApprovalPayload = ExcelDiffApprovalPayload | ExcelWriteApprovalPayload | OfficeDangerousApprovalPayload;
|
|
17
21
|
//# sourceMappingURL=approval-payload.d.ts.map
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* COM execute_code executor — local XLL-backed execution lifecycle.
|
|
3
3
|
*
|
|
4
4
|
* Owns the COM-specific execution flow:
|
|
5
|
-
* 1.
|
|
6
|
-
* 2.
|
|
7
|
-
* 3.
|
|
5
|
+
* 1. Classify code and request write approval before execution
|
|
6
|
+
* 2. Send approved code to the local XLL via xllFetch
|
|
7
|
+
* 3. Parse and validate the response
|
|
8
8
|
*
|
|
9
9
|
* Used by:
|
|
10
10
|
* - `createExcelExecTool()` (COM ToolDefinition wrapper)
|
|
@@ -23,7 +23,7 @@ export interface ComExecResult {
|
|
|
23
23
|
cfTxId?: string;
|
|
24
24
|
editMode?: boolean;
|
|
25
25
|
}
|
|
26
|
-
export type ApprovalOutcome = 'accepted' | 'approval-unavailable' | 'failed' | '
|
|
26
|
+
export type ApprovalOutcome = 'accepted' | 'approval-unavailable' | 'failed' | 'rejected';
|
|
27
27
|
export interface LocalExecResult {
|
|
28
28
|
result: ComExecResult;
|
|
29
29
|
outcome: ApprovalOutcome;
|
|
@@ -33,19 +33,9 @@ export interface ExcelExecApprovalObservability {
|
|
|
33
33
|
onRequested?: (request: ApprovalRequest<OfficeApprovalPayload>) => void;
|
|
34
34
|
onAccepted?: (request: ApprovalRequest<OfficeApprovalPayload>, choice: ApprovalChoice) => void;
|
|
35
35
|
onRejected?: (request: ApprovalRequest<OfficeApprovalPayload>) => void;
|
|
36
|
-
onReverted?: (request: ApprovalRequest<OfficeApprovalPayload>) => void;
|
|
37
|
-
onRevertFailed?: (request: ApprovalRequest<OfficeApprovalPayload>) => void;
|
|
38
|
-
}
|
|
39
|
-
interface ApprovalResolution {
|
|
40
|
-
outcome: ApprovalOutcome;
|
|
41
|
-
approvalSummaries?: string[];
|
|
42
36
|
}
|
|
43
37
|
/** Validate that a parsed JSON value has the COM execute result shape. */
|
|
44
38
|
export declare function isComExecResult(v: unknown): v is ComExecResult;
|
|
45
|
-
/**
|
|
46
|
-
* Resolve approval for cell changes: show UI if needed, then revert or cleanup.
|
|
47
|
-
*/
|
|
48
|
-
export declare function resolveApproval(result: ComExecResult, approval: ApprovalGate<OfficeApprovalPayload> | undefined, postControl: (body: object) => Promise<Response>, ctx: ExtensionContext, description?: string, observability?: ExcelExecApprovalObservability, priorApprovalSummaries?: string[]): Promise<ApprovalResolution>;
|
|
49
39
|
/**
|
|
50
40
|
* Execute code against the local XLL and run approval.
|
|
51
41
|
*
|
|
@@ -60,5 +50,4 @@ export declare function executeComLocally(excelTarget: ExcelHostEndpoint, code:
|
|
|
60
50
|
observability?: ExcelExecApprovalObservability;
|
|
61
51
|
editModeTiming?: Partial<EditModeRetryTiming>;
|
|
62
52
|
}): Promise<LocalExecResult>;
|
|
63
|
-
export {};
|
|
64
53
|
//# sourceMappingURL=executor.d.ts.map
|
|
@@ -2,14 +2,13 @@
|
|
|
2
2
|
* COM execute_code executor — local XLL-backed execution lifecycle.
|
|
3
3
|
*
|
|
4
4
|
* Owns the COM-specific execution flow:
|
|
5
|
-
* 1.
|
|
6
|
-
* 2.
|
|
7
|
-
* 3.
|
|
5
|
+
* 1. Classify code and request write approval before execution
|
|
6
|
+
* 2. Send approved code to the local XLL via xllFetch
|
|
7
|
+
* 3. Parse and validate the response
|
|
8
8
|
*
|
|
9
9
|
* Used by:
|
|
10
10
|
* - `createExcelExecTool()` (COM ToolDefinition wrapper)
|
|
11
11
|
*/
|
|
12
|
-
import { log } from '../../../../shared/logging/agent-log.js';
|
|
13
12
|
import { INTERACTIVE_APPROVAL_UNAVAILABLE_MESSAGE } from '../../../approvals/approval-errors.js';
|
|
14
13
|
import { APPROVAL } from '../../../approvals/types.js';
|
|
15
14
|
import { getApprovalSurface, resolveApprovalExecutionDecision } from '../../../permissions/approval-surface.js';
|
|
@@ -31,13 +30,6 @@ export function isComExecResult(v) {
|
|
|
31
30
|
(r.error === undefined || typeof r.error === 'string') &&
|
|
32
31
|
(r.editMode === undefined || typeof r.editMode === 'boolean'));
|
|
33
32
|
}
|
|
34
|
-
// ---------------------------------------------------------------------------
|
|
35
|
-
// Control constants
|
|
36
|
-
// ---------------------------------------------------------------------------
|
|
37
|
-
const CONTROL = {
|
|
38
|
-
REVERT: 'revert',
|
|
39
|
-
CLEANUP: 'cleanup'
|
|
40
|
-
};
|
|
41
33
|
function describeExcelApprovalChoice(choice) {
|
|
42
34
|
switch (choice) {
|
|
43
35
|
case APPROVAL.ACCEPT:
|
|
@@ -97,95 +89,41 @@ async function requestAlwaysConfirmApproval(approval, ctx, description, dangerou
|
|
|
97
89
|
return { choice, unavailable: false };
|
|
98
90
|
}
|
|
99
91
|
// ---------------------------------------------------------------------------
|
|
100
|
-
//
|
|
92
|
+
// Pre-execution write approval
|
|
101
93
|
// ---------------------------------------------------------------------------
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
kind: 'execute_code',
|
|
111
|
-
title: 'Review Excel changes',
|
|
112
|
-
choices: [APPROVAL.ACCEPT, APPROVAL.ACCEPT_ALL, APPROVAL.REJECT],
|
|
113
|
-
payload: {
|
|
114
|
-
kind: 'diff',
|
|
115
|
-
description: description?.trim() || 'Updating Excel'
|
|
116
|
-
}
|
|
117
|
-
};
|
|
118
|
-
const decision = resolveApprovalExecutionDecision({
|
|
119
|
-
surface: getApprovalSurface(ctx),
|
|
120
|
-
gateAvailable: approval !== undefined,
|
|
121
|
-
isSafe: false,
|
|
122
|
-
isAutoApproved: approval?.isAutoApproved() ?? false,
|
|
123
|
-
alwaysRequireExplicitApproval: false,
|
|
124
|
-
allowHeadlessApproval: ctx.permissionPolicy?.office.allowHeadlessApproval ?? false
|
|
125
|
-
});
|
|
126
|
-
if (decision === 'prompt') {
|
|
127
|
-
if (!approval) {
|
|
128
|
-
observability?.onRejected?.(request);
|
|
129
|
-
try {
|
|
130
|
-
await postControl({ control: CONTROL.REVERT, cfTxId });
|
|
131
|
-
observability?.onReverted?.(request);
|
|
132
|
-
return { outcome: 'reverted' };
|
|
133
|
-
}
|
|
134
|
-
catch {
|
|
135
|
-
if (cfTxId != null) {
|
|
136
|
-
await postControl({ control: CONTROL.CLEANUP, cfTxId }).catch(() => { });
|
|
137
|
-
}
|
|
138
|
-
observability?.onRevertFailed?.(request);
|
|
139
|
-
return { outcome: 'revert-failed' };
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
observability?.onRequested?.(request);
|
|
143
|
-
const choice = await approval.requestApproval(request, ctx);
|
|
144
|
-
if (choice === APPROVAL.REJECT || choice === undefined) {
|
|
145
|
-
observability?.onRejected?.(request);
|
|
146
|
-
try {
|
|
147
|
-
await postControl({ control: CONTROL.REVERT, cfTxId });
|
|
148
|
-
observability?.onReverted?.(request);
|
|
149
|
-
return { outcome: 'rejected' };
|
|
150
|
-
}
|
|
151
|
-
catch {
|
|
152
|
-
if (cfTxId != null) {
|
|
153
|
-
await postControl({ control: CONTROL.CLEANUP, cfTxId }).catch(() => { });
|
|
154
|
-
}
|
|
155
|
-
observability?.onRevertFailed?.(request);
|
|
156
|
-
return { outcome: 'revert-failed' };
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
observability?.onAccepted?.(request, choice);
|
|
160
|
-
if (choice === APPROVAL.ACCEPT_ALL) {
|
|
161
|
-
approval.onAcceptAll();
|
|
162
|
-
}
|
|
163
|
-
approvalSummaries = appendApprovalSummary(approvalSummaries, choice);
|
|
164
|
-
}
|
|
165
|
-
else if (decision === 'deny') {
|
|
166
|
-
observability?.onRejected?.(request);
|
|
167
|
-
try {
|
|
168
|
-
await postControl({ control: CONTROL.REVERT, cfTxId });
|
|
169
|
-
observability?.onReverted?.(request);
|
|
170
|
-
return { outcome: 'reverted' };
|
|
171
|
-
}
|
|
172
|
-
catch {
|
|
173
|
-
if (cfTxId != null) {
|
|
174
|
-
await postControl({ control: CONTROL.CLEANUP, cfTxId }).catch(() => { });
|
|
175
|
-
}
|
|
176
|
-
observability?.onRevertFailed?.(request);
|
|
177
|
-
return { outcome: 'revert-failed' };
|
|
178
|
-
}
|
|
94
|
+
async function requestWriteApproval(approval, ctx, description, observability) {
|
|
95
|
+
const request = {
|
|
96
|
+
kind: 'execute_code',
|
|
97
|
+
title: 'Review Excel changes',
|
|
98
|
+
choices: [APPROVAL.ACCEPT, APPROVAL.ACCEPT_ALL, APPROVAL.REJECT],
|
|
99
|
+
payload: {
|
|
100
|
+
kind: 'write',
|
|
101
|
+
description: description?.trim() || 'Updating Excel'
|
|
179
102
|
}
|
|
103
|
+
};
|
|
104
|
+
const decision = resolveApprovalExecutionDecision({
|
|
105
|
+
surface: getApprovalSurface(ctx),
|
|
106
|
+
gateAvailable: approval !== undefined,
|
|
107
|
+
isSafe: false,
|
|
108
|
+
isAutoApproved: approval?.isAutoApproved() ?? false,
|
|
109
|
+
alwaysRequireExplicitApproval: false,
|
|
110
|
+
allowHeadlessApproval: ctx?.permissionPolicy?.office.allowHeadlessApproval ?? false
|
|
111
|
+
});
|
|
112
|
+
if (decision === 'allow') {
|
|
113
|
+
return { choice: APPROVAL.ACCEPT, unavailable: false, prompted: false };
|
|
180
114
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
115
|
+
if (decision === 'deny' || !approval || !ctx) {
|
|
116
|
+
observability?.onRejected?.(request);
|
|
117
|
+
return { choice: APPROVAL.REJECT, unavailable: true, prompted: false };
|
|
118
|
+
}
|
|
119
|
+
observability?.onRequested?.(request);
|
|
120
|
+
const choice = await approval.requestApproval(request, ctx);
|
|
121
|
+
if (choice === APPROVAL.REJECT || choice === undefined) {
|
|
122
|
+
observability?.onRejected?.(request);
|
|
123
|
+
return { choice, unavailable: false, prompted: true };
|
|
187
124
|
}
|
|
188
|
-
|
|
125
|
+
observability?.onAccepted?.(request, choice);
|
|
126
|
+
return { choice, unavailable: false, prompted: true };
|
|
189
127
|
}
|
|
190
128
|
// ---------------------------------------------------------------------------
|
|
191
129
|
// Core executor
|
|
@@ -200,7 +138,7 @@ export async function executeComLocally(excelTarget, code, options) {
|
|
|
200
138
|
const resolvedExcelHttpUrl = excelTarget.url;
|
|
201
139
|
const { approval, ctx, description, signal, observability, editModeTiming } = options ?? {};
|
|
202
140
|
let approvalSummaries;
|
|
203
|
-
const
|
|
141
|
+
const postExec = (body, sig) => xllFetch(`${resolvedExcelHttpUrl}/exec`, {
|
|
204
142
|
method: 'POST',
|
|
205
143
|
headers: { 'Content-Type': 'application/json' },
|
|
206
144
|
body: JSON.stringify(body),
|
|
@@ -224,7 +162,7 @@ export async function executeComLocally(excelTarget, code, options) {
|
|
|
224
162
|
const sendExecRequest = async () => {
|
|
225
163
|
let response;
|
|
226
164
|
try {
|
|
227
|
-
response = await
|
|
165
|
+
response = await postExec({ code, autoApprove: true }, signal);
|
|
228
166
|
}
|
|
229
167
|
catch (e) {
|
|
230
168
|
if (signal?.aborted || isEditModeAbortError(e)) {
|
|
@@ -237,7 +175,6 @@ export async function executeComLocally(excelTarget, code, options) {
|
|
|
237
175
|
};
|
|
238
176
|
// Static analysis: skip approval for code with no detectable writes.
|
|
239
177
|
const analysis = analyzeComWriteCode(code);
|
|
240
|
-
const dangerousLifecycleBypassed = analysis.alwaysRequireApproval && isDangerousExcelLifecycleBypassed(ctx);
|
|
241
178
|
if (analysis.alwaysRequireApproval) {
|
|
242
179
|
const approvalResult = await requestAlwaysConfirmApproval(approval, ctx, description, analysis.dangerousOperations, observability);
|
|
243
180
|
const { choice } = approvalResult;
|
|
@@ -257,25 +194,26 @@ export async function executeComLocally(excelTarget, code, options) {
|
|
|
257
194
|
}
|
|
258
195
|
approvalSummaries = appendApprovalSummary(approvalSummaries, choice);
|
|
259
196
|
}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
197
|
+
else if (!analysis.isReadOnly) {
|
|
198
|
+
const approvalResult = await requestWriteApproval(approval, ctx, description, observability);
|
|
199
|
+
const { choice } = approvalResult;
|
|
200
|
+
if (choice !== APPROVAL.ACCEPT && choice !== APPROVAL.ACCEPT_ALL) {
|
|
201
|
+
return {
|
|
202
|
+
result: {
|
|
203
|
+
ok: true,
|
|
204
|
+
output: approvalResult.unavailable
|
|
205
|
+
? INTERACTIVE_APPROVAL_UNAVAILABLE_MESSAGE
|
|
206
|
+
: 'Excel operation rejected by user.'
|
|
207
|
+
},
|
|
208
|
+
outcome: approvalResult.unavailable ? 'approval-unavailable' : 'rejected'
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
if (approvalResult.prompted && choice === APPROVAL.ACCEPT_ALL) {
|
|
212
|
+
approval?.onAcceptAll();
|
|
213
|
+
}
|
|
214
|
+
if (approvalResult.prompted) {
|
|
215
|
+
approvalSummaries = appendApprovalSummary(approvalSummaries, choice);
|
|
216
|
+
}
|
|
279
217
|
}
|
|
280
218
|
let result = await sendExecRequest();
|
|
281
219
|
if (result.editMode) {
|
|
@@ -289,34 +227,6 @@ export async function executeComLocally(excelTarget, code, options) {
|
|
|
289
227
|
if (!result.ok) {
|
|
290
228
|
return { result, outcome: 'failed' };
|
|
291
229
|
}
|
|
292
|
-
if (ctx) {
|
|
293
|
-
const { outcome, approvalSummaries: resolvedApprovalSummaries } = await resolveApproval(result, approval, (b) => postControl(b), ctx, description, observability, approvalSummaries);
|
|
294
|
-
return { result, outcome, approvalSummaries: resolvedApprovalSummaries };
|
|
295
|
-
}
|
|
296
|
-
if (result.diff) {
|
|
297
|
-
try {
|
|
298
|
-
await postControl({ control: CONTROL.REVERT, cfTxId: result.cfTxId });
|
|
299
|
-
return {
|
|
300
|
-
result: { ...result, output: 'Excel operation rejected by user.' },
|
|
301
|
-
outcome: 'reverted'
|
|
302
|
-
};
|
|
303
|
-
}
|
|
304
|
-
catch {
|
|
305
|
-
if (result.cfTxId != null) {
|
|
306
|
-
await postControl({ control: CONTROL.CLEANUP, cfTxId: result.cfTxId }).catch(() => { });
|
|
307
|
-
}
|
|
308
|
-
return {
|
|
309
|
-
result: { ...result, output: 'Excel operation rejected by user.' },
|
|
310
|
-
outcome: 'revert-failed'
|
|
311
|
-
};
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
if (result.cfTxId != null) {
|
|
315
|
-
await postControl({ control: CONTROL.CLEANUP, cfTxId: result.cfTxId }).catch((e) => {
|
|
316
|
-
const msg = e instanceof Error ? e.message : String(e);
|
|
317
|
-
log.error('excel-exec', `CF cleanup failed for tx ${result.cfTxId}: ${msg}`);
|
|
318
|
-
});
|
|
319
|
-
}
|
|
320
230
|
return { result, outcome: 'accepted', approvalSummaries };
|
|
321
231
|
}
|
|
322
232
|
//# sourceMappingURL=executor.js.map
|
|
@@ -31,26 +31,6 @@ export function createExecuteCodeApprovalObservability(clientLogger) {
|
|
|
31
31
|
approval_kind: request.payload.kind
|
|
32
32
|
}
|
|
33
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
34
|
}
|
|
55
35
|
};
|
|
56
36
|
}
|
|
@@ -81,23 +81,6 @@ export function createExcelExecTool(resolveTarget, approval, observability) {
|
|
|
81
81
|
ctx: ctx,
|
|
82
82
|
signal: signal ?? undefined
|
|
83
83
|
});
|
|
84
|
-
if (outcome === 'revert-failed') {
|
|
85
|
-
return {
|
|
86
|
-
content: [
|
|
87
|
-
{
|
|
88
|
-
type: 'text',
|
|
89
|
-
text: 'Revert failed — changes are still applied in Excel. You may need to undo manually (Ctrl+Z).'
|
|
90
|
-
}
|
|
91
|
-
],
|
|
92
|
-
details: result
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
if (outcome === 'reverted') {
|
|
96
|
-
return {
|
|
97
|
-
content: [{ type: 'text', text: 'Changes reverted by user.' }],
|
|
98
|
-
details: result
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
84
|
if (outcome === 'rejected') {
|
|
102
85
|
return {
|
|
103
86
|
content: [{ type: 'text', text: USER_REJECTED_APPROVAL_MESSAGE }],
|