@crouton-kit/crouter 0.3.70 → 0.3.79
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/build-root.d.ts +12 -4
- package/dist/build-root.js +25 -6
- package/dist/builtin-memory/00-runtime-base.md +3 -10
- package/dist/builtin-memory/04-base-worker.md +18 -0
- package/dist/builtin-memory/04-orchestration-kernel.md +1 -1
- package/dist/builtin-memory/crouter-development/plugins.md +82 -5
- package/dist/builtin-pi-packages/pi-crtr-extensions/README.md +13 -34
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/provider-rotation.test.ts +1115 -1
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +234 -71
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/statusline.ts +2 -9
- package/dist/builtin-pi-packages/pi-crtr-extensions/lib/subscription-state.ts +2 -516
- package/dist/builtin-pi-packages/pi-crtr-extensions/package-lock.json +2 -2
- package/dist/builtin-pi-packages/pi-mode-switch/README.md +11 -39
- package/dist/builtin-pi-packages/pi-mode-switch/extensions/index.ts +20 -15
- package/dist/builtin-pi-packages/pi-mode-switch/package.json +1 -1
- package/dist/builtin-views/canvas/tui.mjs +8 -9
- package/dist/builtin-views/chat/tui.mjs +12 -12
- package/dist/builtin-views/git-pr/tui.mjs +7 -8
- package/dist/builtin-views/inbox/tui.mjs +27 -41
- package/dist/builtin-views/linkedin/tui.mjs +23 -37
- package/dist/builtin-views/prompt-review/tui.mjs +11 -11
- package/dist/builtin-views/settings/tui.mjs +11 -11
- package/dist/builtin-views/workspace-sidebar/tui.mjs +8 -9
- package/dist/clients/attach/__tests__/attach-chrome-remote.test.js +11 -6
- package/dist/clients/attach/__tests__/attach-keybindings.test.d.ts +1 -0
- package/dist/clients/attach/__tests__/attach-keybindings.test.js +113 -0
- package/dist/clients/attach/__tests__/crtr-output-render.test.js +1 -1
- package/dist/clients/attach/__tests__/mermaid-render.test.d.ts +1 -0
- package/dist/clients/attach/__tests__/mermaid-render.test.js +28 -0
- package/dist/clients/attach/__tests__/oauth-dialog-lifecycle.test.d.ts +1 -0
- package/dist/clients/attach/__tests__/oauth-dialog-lifecycle.test.js +110 -0
- package/dist/clients/attach/attach-cmd.d.ts +9 -1
- package/dist/clients/attach/attach-cmd.js +841 -792
- package/dist/clients/attach/auth-pickers.d.ts +0 -12
- package/dist/clients/attach/auth-pickers.js +64 -15
- package/dist/clients/attach/canvas-panels.js +2 -3
- package/dist/clients/attach/chat-view.d.ts +7 -8
- package/dist/clients/attach/chat-view.js +119 -79
- package/dist/clients/attach/edit-diff-render.d.ts +6 -0
- package/dist/clients/attach/edit-diff-render.js +263 -0
- package/dist/clients/attach/graph-overlay.d.ts +12 -2
- package/dist/clients/attach/graph-overlay.js +83 -33
- package/dist/clients/attach/input-controller.d.ts +28 -2
- package/dist/clients/attach/input-controller.js +38 -5
- package/dist/clients/attach/mermaid-render.js +5 -2
- package/dist/clients/attach/pickers.d.ts +8 -7
- package/dist/clients/attach/pickers.js +11 -17
- package/dist/clients/attach/slash-commands.d.ts +9 -0
- package/dist/clients/attach/slash-commands.js +127 -7
- package/dist/clients/attach/titled-editor.d.ts +12 -1
- package/dist/clients/attach/titled-editor.js +103 -8
- package/dist/commands/canvas-browse.js +2 -2
- package/dist/commands/human/queue.js +3 -4
- package/dist/commands/memory/lint.js +39 -5
- package/dist/commands/memory/write.js +1 -0
- package/dist/commands/node.js +9 -2
- package/dist/commands/pkg/plugin-inspect.js +22 -1
- package/dist/commands/pkg/plugin-manage.js +31 -9
- package/dist/commands/surface-tmux-spread.js +1 -3
- package/dist/commands/sys/__tests__/config-keybindings.test.d.ts +1 -0
- package/dist/commands/sys/__tests__/config-keybindings.test.js +55 -0
- package/dist/commands/sys/__tests__/config-model-ladders.test.d.ts +1 -0
- package/dist/commands/sys/__tests__/config-model-ladders.test.js +121 -0
- package/dist/commands/sys/__tests__/setup-core.test.js +158 -1
- package/dist/commands/sys/config.js +18 -21
- package/dist/commands/sys/doctor.js +42 -4
- package/dist/commands/sys/setup-core.d.ts +49 -1
- package/dist/commands/sys/setup-core.js +161 -4
- package/dist/commands/sys/setup.d.ts +88 -0
- package/dist/commands/sys/setup.js +943 -169
- package/dist/commands/view-pick.d.ts +4 -0
- package/dist/commands/view-pick.js +17 -7
- package/dist/core/__tests__/base-worker-prompt.test.d.ts +1 -0
- package/dist/core/__tests__/base-worker-prompt.test.js +24 -0
- package/dist/core/__tests__/canvas-inbox-watcher-hold.test.js +232 -1
- package/dist/core/__tests__/canvas-inbox-watcher.test.js +34 -9
- package/dist/core/__tests__/command-plugins-surfaces.test.d.ts +1 -0
- package/dist/core/__tests__/command-plugins-surfaces.test.js +298 -0
- package/dist/core/__tests__/command-plugins.test.d.ts +1 -0
- package/dist/core/__tests__/command-plugins.test.js +444 -0
- package/dist/core/__tests__/fault-classifier.test.js +15 -0
- package/dist/core/__tests__/fixtures/fake-engine.d.ts +6 -0
- package/dist/core/__tests__/fixtures/fake-engine.js +9 -1
- package/dist/core/__tests__/full/broker-dialogs.test.js +7 -2
- package/dist/core/__tests__/host-teardown-process-group.test.js +15 -4
- package/dist/core/__tests__/preview-registry-sync.test.js +30 -1
- package/dist/core/__tests__/scope-crouter-home-fence.test.d.ts +1 -0
- package/dist/core/__tests__/scope-crouter-home-fence.test.js +55 -0
- package/dist/core/__tests__/stream-watchdog.test.d.ts +1 -0
- package/dist/core/__tests__/stream-watchdog.test.js +70 -0
- package/dist/core/__tests__/tmux-surface.test.js +72 -0
- package/dist/core/canvas/browse/__tests__/model.test.js +23 -5
- package/dist/core/canvas/browse/__tests__/render.test.js +1 -0
- package/dist/core/canvas/browse/app.d.ts +6 -0
- package/dist/core/canvas/browse/app.js +230 -41
- package/dist/core/canvas/browse/model.d.ts +10 -6
- package/dist/core/canvas/browse/model.js +20 -12
- package/dist/core/canvas/browse/pins.d.ts +4 -0
- package/dist/core/canvas/browse/pins.js +29 -0
- package/dist/core/canvas/browse/render.d.ts +13 -1
- package/dist/core/canvas/browse/render.js +72 -15
- package/dist/core/canvas/nav-model.js +5 -11
- package/dist/core/canvas/paths.d.ts +5 -0
- package/dist/core/canvas/paths.js +7 -0
- package/dist/core/command-plugins/adapter.d.ts +15 -0
- package/dist/core/command-plugins/adapter.js +145 -0
- package/dist/core/command-plugins/compose.d.ts +5 -0
- package/dist/core/command-plugins/compose.js +56 -0
- package/dist/core/command-plugins/discovery.d.ts +104 -0
- package/dist/core/command-plugins/discovery.js +565 -0
- package/dist/core/config.d.ts +48 -0
- package/dist/core/config.js +228 -110
- package/dist/core/fault-classifier.js +1 -1
- package/dist/core/fs-utils.d.ts +1 -0
- package/dist/core/fs-utils.js +15 -1
- package/dist/core/keybindings/__tests__/bespoke-consumers.test.d.ts +1 -0
- package/dist/core/keybindings/__tests__/bespoke-consumers.test.js +40 -0
- package/dist/core/keybindings/__tests__/resolve.test.d.ts +1 -0
- package/dist/core/keybindings/__tests__/resolve.test.js +224 -0
- package/dist/core/keybindings/catalog.d.ts +14 -0
- package/dist/core/keybindings/catalog.js +257 -0
- package/dist/core/keybindings/index.d.ts +5 -0
- package/dist/core/keybindings/index.js +4 -0
- package/dist/core/keybindings/match.d.ts +29 -0
- package/dist/core/keybindings/match.js +99 -0
- package/dist/core/keybindings/persistence.d.ts +14 -0
- package/dist/core/keybindings/persistence.js +31 -0
- package/dist/core/keybindings/resolve.d.ts +14 -0
- package/dist/core/keybindings/resolve.js +305 -0
- package/dist/core/keybindings/types.d.ts +37 -0
- package/dist/core/keybindings/types.js +1 -0
- package/dist/core/memory-resolver.d.ts +1 -1
- package/dist/core/memory-resolver.js +10 -3
- package/dist/core/predicate.d.ts +5 -3
- package/dist/core/predicate.js +5 -3
- package/dist/core/profiles/select.d.ts +6 -0
- package/dist/core/profiles/select.js +86 -52
- package/dist/core/provider-management.d.ts +12 -0
- package/dist/core/provider-management.js +24 -0
- package/dist/core/runtime/broker-protocol.d.ts +33 -5
- package/dist/core/runtime/broker.js +164 -14
- package/dist/core/runtime/launch.d.ts +39 -6
- package/dist/core/runtime/launch.js +78 -20
- package/dist/core/runtime/naming.js +3 -3
- package/dist/core/runtime/pi-cli.d.ts +6 -0
- package/dist/core/runtime/pi-cli.js +16 -2
- package/dist/core/runtime/pi-vendored.d.ts +8 -0
- package/dist/core/runtime/pi-vendored.js +14 -0
- package/dist/core/runtime/placement.d.ts +2 -2
- package/dist/core/runtime/placement.js +4 -1
- package/dist/core/runtime/promote.js +4 -0
- package/dist/core/runtime/recap.d.ts +3 -3
- package/dist/core/runtime/recap.js +75 -47
- package/dist/core/runtime/recycle.js +6 -1
- package/dist/core/runtime/reset.js +5 -0
- package/dist/core/runtime/session-list-cache.d.ts +33 -0
- package/dist/core/runtime/session-list-cache.js +338 -0
- package/dist/core/runtime/spawn.js +52 -45
- package/dist/core/runtime/stream-watchdog.d.ts +26 -0
- package/dist/core/runtime/stream-watchdog.js +75 -0
- package/dist/core/runtime/tmux-chrome.d.ts +1 -1
- package/dist/core/runtime/tmux-chrome.js +2 -2
- package/dist/core/runtime/tmux.d.ts +18 -15
- package/dist/core/runtime/tmux.js +217 -110
- package/dist/core/scope.js +27 -4
- package/dist/core/subscription-state.d.ts +90 -0
- package/dist/core/subscription-state.js +762 -0
- package/dist/core/tui/__tests__/host-keybindings.test.d.ts +1 -0
- package/dist/core/tui/__tests__/host-keybindings.test.js +112 -0
- package/dist/core/tui/host.d.ts +30 -1
- package/dist/core/tui/host.js +148 -34
- package/dist/core/view/contract.d.ts +17 -3
- package/dist/daemon/crtrd.js +253 -12
- package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +41 -0
- package/dist/pi-extensions/__tests__/canvas-stophook-context-nudge.test.d.ts +1 -0
- package/dist/pi-extensions/__tests__/canvas-stophook-context-nudge.test.js +121 -0
- package/dist/pi-extensions/canvas-inbox-watcher.d.ts +1 -1
- package/dist/pi-extensions/canvas-inbox-watcher.js +203 -25
- package/dist/pi-extensions/canvas-recap.d.ts +4 -0
- package/dist/pi-extensions/canvas-recap.js +73 -46
- package/dist/pi-extensions/canvas-stophook.d.ts +11 -0
- package/dist/pi-extensions/canvas-stophook.js +33 -4
- package/dist/types.d.ts +9 -26
- package/dist/types.js +1 -28
- package/dist/web-client/assets/{index-DiFuLcp6.js → index--md2ylfi.js} +1 -1
- package/dist/web-client/index.html +1 -1
- package/dist/web-client/sw.js +1 -1
- package/package.json +8 -4
- package/dist/pi-extensions/canvas-nav.d.ts +0 -43
- package/dist/pi-extensions/canvas-nav.js +0 -640
- package/dist/pi-extensions/widget-order-bus.d.ts +0 -6
- package/dist/pi-extensions/widget-order-bus.js +0 -34
|
@@ -1,7 +1,164 @@
|
|
|
1
1
|
import { test } from 'node:test';
|
|
2
2
|
import assert from 'node:assert/strict';
|
|
3
|
-
import { existsSync } from 'node:fs';
|
|
3
|
+
import { existsSync, mkdtempSync } from 'node:fs';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import { join } from 'node:path';
|
|
4
6
|
import { resolveBundledPiCliPath } from '../../../core/runtime/pi-cli.js';
|
|
7
|
+
import { BINDING_CATALOG, resolveKeybindings } from '../../../core/keybindings/index.js';
|
|
8
|
+
import { SetupKeybindingsDraft, buildSetupManifest } from '../setup-core.js';
|
|
9
|
+
import { SetupWizard } from '../setup.js';
|
|
10
|
+
import { applyTheme } from '../../../clients/attach/config-load.js';
|
|
11
|
+
import { stripVTControlCharacters } from 'node:util';
|
|
12
|
+
// The provider panel only touches the TUI on async OAuth transitions (never in
|
|
13
|
+
// these keybindings-tab render/input tests) and reads auth from `agentDir`; a
|
|
14
|
+
// no-op TUI stub and an empty temp agent dir keep the wizard headless.
|
|
15
|
+
const stubTui = { requestRender() { } };
|
|
16
|
+
const agentDir = mkdtempSync(join(tmpdir(), 'setup-wizard-test-'));
|
|
17
|
+
test('setup keybinding draft edits, disables, resets, and discards transactionally', () => {
|
|
18
|
+
const draft = new SetupKeybindingsDraft({ 'crtr.attach.graph.toggle': ['alt+x'] });
|
|
19
|
+
assert.equal(draft.expression('crtr.attach.graph.toggle'), 'alt+x');
|
|
20
|
+
assert.equal(draft.dirty, false);
|
|
21
|
+
assert.equal(draft.edit('crtr.attach.graph.toggle', 'M-Y, ctrl+g').ok, true);
|
|
22
|
+
assert.deepEqual(draft.overrides()['crtr.attach.graph.toggle'], ['alt+shift+y', 'ctrl+g']);
|
|
23
|
+
assert.equal(draft.dirty, true);
|
|
24
|
+
assert.equal(draft.unbind('crtr.attach.graph.toggle').ok, true);
|
|
25
|
+
assert.deepEqual(draft.overrides()['crtr.attach.graph.toggle'], []);
|
|
26
|
+
draft.resetRow('crtr.attach.graph.toggle');
|
|
27
|
+
assert.equal(Object.hasOwn(draft.overrides(), 'crtr.attach.graph.toggle'), false);
|
|
28
|
+
draft.edit('crtr.attach.graph.toggle', 'alt+y');
|
|
29
|
+
draft.discard();
|
|
30
|
+
assert.deepEqual(draft.overrides(), { 'crtr.attach.graph.toggle': ['alt+x'] });
|
|
31
|
+
assert.equal(draft.dirty, false);
|
|
32
|
+
});
|
|
33
|
+
test('setup keybinding draft drops a member when the committed value equals the catalog default (N2 sparseness)', () => {
|
|
34
|
+
const draft = new SetupKeybindingsDraft(undefined);
|
|
35
|
+
const definition = BINDING_CATALOG.find((entry) => entry.id === 'crtr.attach.graph.toggle');
|
|
36
|
+
const defaultExpression = draft.expression(definition.id);
|
|
37
|
+
// Committing the seeded default verbatim must NOT record an override: the row
|
|
38
|
+
// stays sparse (no member) and the draft stays clean — no spurious unsaved/dot.
|
|
39
|
+
const result = draft.edit(definition.id, defaultExpression);
|
|
40
|
+
assert.equal(result.ok, true);
|
|
41
|
+
assert.equal(Object.hasOwn(draft.overrides(), definition.id), false);
|
|
42
|
+
assert.equal(draft.dirty, false);
|
|
43
|
+
// Editing to a real value records the member; re-committing the default drops it.
|
|
44
|
+
assert.equal(draft.edit(definition.id, 'ctrl+g').ok, true);
|
|
45
|
+
assert.deepEqual(draft.overrides()[definition.id], ['ctrl+g']);
|
|
46
|
+
assert.equal(draft.dirty, true);
|
|
47
|
+
assert.equal(draft.edit(definition.id, defaultExpression).ok, true);
|
|
48
|
+
assert.equal(Object.hasOwn(draft.overrides(), definition.id), false);
|
|
49
|
+
assert.equal(draft.dirty, false);
|
|
50
|
+
});
|
|
51
|
+
test('setup keybinding draft keeps the last valid cell value on syntax, collision, and safety errors', () => {
|
|
52
|
+
const draft = new SetupKeybindingsDraft(undefined);
|
|
53
|
+
const syntax = draft.edit('crtr.attach.graph.toggle', 'ctrl+not-a-key');
|
|
54
|
+
assert.equal(syntax.ok, false);
|
|
55
|
+
assert.deepEqual(draft.overrides(), {});
|
|
56
|
+
const collision = draft.edit('crtr.attach.graph.toggle', 'alt+m');
|
|
57
|
+
assert.equal(collision.ok, false);
|
|
58
|
+
assert.match(collision.diagnostics[0].message, /crtr\.mode\.cycle/);
|
|
59
|
+
assert.deepEqual(draft.overrides(), {});
|
|
60
|
+
const unsafe = draft.unbind('crtr.setup.keybindings.save');
|
|
61
|
+
assert.equal(unsafe.ok, false);
|
|
62
|
+
assert.match(unsafe.diagnostics[0].message, /save-keybindings/);
|
|
63
|
+
assert.deepEqual(draft.overrides(), {});
|
|
64
|
+
});
|
|
65
|
+
test('setup reset-all removes invalid and unknown raw members without cataloging pi bindings', () => {
|
|
66
|
+
const invalidRoot = new SetupKeybindingsDraft('alt+x');
|
|
67
|
+
assert.equal(invalidRoot.resolution().diagnostics[0]?.code, 'invalid-keybindings');
|
|
68
|
+
invalidRoot.resetAll();
|
|
69
|
+
assert.equal(invalidRoot.dirty, true);
|
|
70
|
+
assert.equal(invalidRoot.resolution().diagnostics.length, 0);
|
|
71
|
+
const draft = new SetupKeybindingsDraft({
|
|
72
|
+
'crtr.unknown': ['x'],
|
|
73
|
+
'crtr.attach.graph.toggle': 'alt+x',
|
|
74
|
+
});
|
|
75
|
+
assert.equal(draft.resolution().diagnostics.length, 2);
|
|
76
|
+
draft.resetAll();
|
|
77
|
+
assert.deepEqual(draft.overrides(), {});
|
|
78
|
+
assert.equal(draft.resolution().diagnostics.length, 0);
|
|
79
|
+
assert.equal(BINDING_CATALOG.some((entry) => entry.id.includes('app.') || entry.id.includes('tui.')), false);
|
|
80
|
+
});
|
|
81
|
+
test('setup keybinding draft refuses edits while the raw root is invalid until reset-all', () => {
|
|
82
|
+
const draft = new SetupKeybindingsDraft('alt+x');
|
|
83
|
+
assert.equal(draft.hasInvalidRoot(), true);
|
|
84
|
+
// An edit against an invalid root must NOT commit (the prior bug: it returned
|
|
85
|
+
// ok:true against an empty `current` while the row kept showing the default).
|
|
86
|
+
const rejected = draft.edit('crtr.attach.graph.toggle', 'ctrl+g');
|
|
87
|
+
assert.equal(rejected.ok, false);
|
|
88
|
+
assert.equal(rejected.diagnostics[0].code, 'invalid-keybindings');
|
|
89
|
+
assert.deepEqual(draft.overrides(), {});
|
|
90
|
+
// reset-all clears the invalid root; edits then succeed and display.
|
|
91
|
+
draft.resetAll();
|
|
92
|
+
assert.equal(draft.hasInvalidRoot(), false);
|
|
93
|
+
const accepted = draft.edit('crtr.attach.graph.toggle', 'ctrl+g');
|
|
94
|
+
assert.equal(accepted.ok, true);
|
|
95
|
+
assert.deepEqual(draft.overrides()['crtr.attach.graph.toggle'], ['ctrl+g']);
|
|
96
|
+
});
|
|
97
|
+
test('setup keybindings editor stays visible while paging moves the selection (m3)', () => {
|
|
98
|
+
applyTheme({ cwd: process.cwd() });
|
|
99
|
+
const openingBindings = resolveKeybindings(undefined);
|
|
100
|
+
// A short terminal forces a small scroll window so paging past the edit row
|
|
101
|
+
// is the reproducible m3 scenario (editor was blind-typing off-screen before).
|
|
102
|
+
const wizard = new SetupWizard(buildSetupManifest(), new Set(), [], stubTui, agentDir, openingBindings, undefined, () => 14);
|
|
103
|
+
wizard.focused = true;
|
|
104
|
+
const render = () => stripVTControlCharacters(wizard.render(100).join('\n'));
|
|
105
|
+
// Drive to the Keybindings tab (tab-next = Tab), open the editor on row 0 (Enter).
|
|
106
|
+
for (let i = 0; i < 5; i += 1)
|
|
107
|
+
wizard.handleInput('\t');
|
|
108
|
+
assert.match(render(), /Keybindings/);
|
|
109
|
+
wizard.handleInput('\r');
|
|
110
|
+
// Type a distinctive marker into the live editor buffer.
|
|
111
|
+
wizard.handleInput('zzz');
|
|
112
|
+
assert.match(render(), /zzz/, 'editor should echo typed input before paging');
|
|
113
|
+
// PageDown twice: selection moves off, but the editor row must remain on screen.
|
|
114
|
+
wizard.handleInput('\x1b[6~');
|
|
115
|
+
wizard.handleInput('\x1b[6~');
|
|
116
|
+
assert.match(render(), /zzz/, 'editor must stay visible (and keep capturing) after paging');
|
|
117
|
+
});
|
|
118
|
+
test('setup keybindings q-cancel with a dirty draft routes through discard-confirm, not a silent exit (N3)', () => {
|
|
119
|
+
applyTheme({ cwd: process.cwd() });
|
|
120
|
+
const wizard = new SetupWizard(buildSetupManifest(), new Set(), [], stubTui, agentDir, resolveKeybindings(undefined), undefined, () => 40);
|
|
121
|
+
wizard.focused = true;
|
|
122
|
+
let cancelled = false;
|
|
123
|
+
wizard.onCancel = () => { cancelled = true; };
|
|
124
|
+
const render = () => stripVTControlCharacters(wizard.render(100).join('\n'));
|
|
125
|
+
for (let i = 0; i < 5; i += 1)
|
|
126
|
+
wizard.handleInput('\t');
|
|
127
|
+
// Make the draft dirty: unbind the selected row (delete key) so it has a real
|
|
128
|
+
// pending override.
|
|
129
|
+
wizard.handleInput('\x1b[3~');
|
|
130
|
+
assert.match(render(), /unsaved/, 'draft should be dirty after unbind');
|
|
131
|
+
// q (crtr.setup.cancel) in list mode must NOT drop the edits: it opens the same
|
|
132
|
+
// discard-confirm the Escape path uses.
|
|
133
|
+
wizard.handleInput('q');
|
|
134
|
+
assert.equal(cancelled, false, 'dirty draft must not silently exit on q');
|
|
135
|
+
assert.match(render(), /Discard every unsaved keybinding change\?/);
|
|
136
|
+
// A clean draft still exits on q (cancel elsewhere is unchanged).
|
|
137
|
+
const clean = new SetupWizard(buildSetupManifest(), new Set(), [], stubTui, agentDir, resolveKeybindings(undefined), undefined, () => 40);
|
|
138
|
+
let cleanCancelled = false;
|
|
139
|
+
clean.onCancel = () => { cleanCancelled = true; };
|
|
140
|
+
clean.focused = true;
|
|
141
|
+
for (let i = 0; i < 5; i += 1)
|
|
142
|
+
clean.handleInput('\t');
|
|
143
|
+
clean.handleInput('q');
|
|
144
|
+
assert.equal(cleanCancelled, true, 'clean draft still exits on q');
|
|
145
|
+
});
|
|
146
|
+
test('setup keybindings selection always renders across group boundaries in a short window (m4 residual)', () => {
|
|
147
|
+
applyTheme({ cwd: process.cwd() });
|
|
148
|
+
// Small viewport so a window spans several group headings + a diagnostic line —
|
|
149
|
+
// the fixed-reserve page math used to let the selected row fail to render here.
|
|
150
|
+
const wizard = new SetupWizard(buildSetupManifest(), new Set(), [], stubTui, agentDir, resolveKeybindings(undefined), undefined, () => 13);
|
|
151
|
+
wizard.focused = true;
|
|
152
|
+
const render = () => stripVTControlCharacters(wizard.render(100).join('\n'));
|
|
153
|
+
for (let i = 0; i < 5; i += 1)
|
|
154
|
+
wizard.handleInput('\t');
|
|
155
|
+
// Page/step down through the whole catalog; the selection marker must always render.
|
|
156
|
+
for (let step = 0; step < BINDING_CATALOG.length + 5; step += 1) {
|
|
157
|
+
assert.match(render(), /\u25b6/, `selection marker must render at step ${step}`);
|
|
158
|
+
wizard.handleInput('\x1b[6~'); // PageDown
|
|
159
|
+
wizard.handleInput('j'); // and a single-row step to hit every boundary alignment
|
|
160
|
+
}
|
|
161
|
+
});
|
|
5
162
|
test('resolveBundledPiCliPath uses crouter bundled pi instead of a standalone pi on PATH', () => {
|
|
6
163
|
const prevPath = process.env.PATH;
|
|
7
164
|
process.env.PATH = '';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { defineBranch, defineLeaf } from '../../core/command.js';
|
|
2
|
-
import { readConfig,
|
|
2
|
+
import { readConfig, updateConfig, configPath as coreConfigPath } from '../../core/config.js';
|
|
3
3
|
import { usage, notFound } from '../../core/errors.js';
|
|
4
4
|
import { scopeRoot, listScopes } from '../../core/scope.js';
|
|
5
5
|
import { resolveScope } from './shared.js';
|
|
@@ -11,7 +11,6 @@ const TOP_LEVEL_KEYS = new Set([
|
|
|
11
11
|
'marketplaces',
|
|
12
12
|
'plugins',
|
|
13
13
|
'max_panes_per_window',
|
|
14
|
-
'canvasNav',
|
|
15
14
|
'modelLadders',
|
|
16
15
|
]);
|
|
17
16
|
const MODEL_PROVIDERS = new Set(['anthropic', 'openai']);
|
|
@@ -44,6 +43,9 @@ function parseConfigValue(raw) {
|
|
|
44
43
|
function setNestedValue(cfg, key, rawValue, value) {
|
|
45
44
|
const parts = key.split('.');
|
|
46
45
|
const topKey = parts[0];
|
|
46
|
+
if (topKey === 'keybindings') {
|
|
47
|
+
throw usage('keybindings are edited only through `crtr sys setup`');
|
|
48
|
+
}
|
|
47
49
|
if (!TOP_LEVEL_KEYS.has(topKey)) {
|
|
48
50
|
throw usage(`unknown config key: ${topKey} (expected: ${[...TOP_LEVEL_KEYS].join('|')})`);
|
|
49
51
|
}
|
|
@@ -69,16 +71,6 @@ function setNestedValue(cfg, key, rawValue, value) {
|
|
|
69
71
|
cfg.max_panes_per_window = Math.floor(value);
|
|
70
72
|
return;
|
|
71
73
|
}
|
|
72
|
-
if (topKey === 'canvasNav') {
|
|
73
|
-
// Only the scalar prefixKey is settable here; the prefixBinds/graphBinds
|
|
74
|
-
// record tables are edited directly in config.json (run `crtr sys config
|
|
75
|
-
// path` to locate it).
|
|
76
|
-
if (key === 'canvasNav.prefixKey') {
|
|
77
|
-
cfg.canvasNav.prefixKey = rawValue;
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
throw usage(`canvasNav.${parts.slice(1).join('.') || '*'} is a record table — edit config.json directly (run \`crtr sys config path\`). Only canvasNav.prefixKey is settable via this command.`);
|
|
81
|
-
}
|
|
82
74
|
if (topKey === 'modelLadders') {
|
|
83
75
|
if (parts.length === 2 && parts[1] === 'defaultProvider') {
|
|
84
76
|
if (!isModelProvider(rawValue)) {
|
|
@@ -121,12 +113,12 @@ function setNestedValue(cfg, key, rawValue, value) {
|
|
|
121
113
|
const configGet = defineLeaf({
|
|
122
114
|
name: 'get',
|
|
123
115
|
description: 'read a config value by key',
|
|
124
|
-
whenToUse: 'you want to
|
|
116
|
+
whenToUse: 'you want to inspect one config value — including the whole user keybindings object — optionally from a specific scope. Use sys setup to edit keybindings and sys config set for supported scalar settings.',
|
|
125
117
|
help: {
|
|
126
118
|
name: 'sys config get',
|
|
127
119
|
summary: 'read a config value by dotted key',
|
|
128
120
|
params: [
|
|
129
|
-
{ kind: 'positional', name: 'key', type: 'string', required: true, constraint: 'Dotted key path. Top-level keys: auto_update, marketplaces, plugins, max_panes_per_window,
|
|
121
|
+
{ kind: 'positional', name: 'key', type: 'string', required: true, constraint: 'Dotted key path. Top-level keys: auto_update, marketplaces, plugins, max_panes_per_window, modelLadders, or the whole keybindings object. Keybindings are edited only through sys setup.' },
|
|
130
122
|
{ kind: 'flag', name: 'scope', type: 'enum', choices: ['user', 'project'], required: false, constraint: 'Scope to read from. Default: user.' },
|
|
131
123
|
],
|
|
132
124
|
output: [
|
|
@@ -140,6 +132,9 @@ const configGet = defineLeaf({
|
|
|
140
132
|
run: async (input) => {
|
|
141
133
|
const key = input['key'];
|
|
142
134
|
const scope = resolveScope(input['scope']);
|
|
135
|
+
if (key.startsWith('keybindings.') || (key === 'keybindings' && scope !== 'user')) {
|
|
136
|
+
throw notFound('keybindings are available only as the whole user-scope object');
|
|
137
|
+
}
|
|
143
138
|
const cfg = readConfig(scope);
|
|
144
139
|
const value = getNestedValue(cfg, key);
|
|
145
140
|
if (value === undefined) {
|
|
@@ -151,12 +146,12 @@ const configGet = defineLeaf({
|
|
|
151
146
|
const configSet = defineLeaf({
|
|
152
147
|
name: 'set',
|
|
153
148
|
description: 'write a config value by key',
|
|
154
|
-
whenToUse: 'you want to change a
|
|
149
|
+
whenToUse: 'you want to change a supported scalar crtr setting in user or project scope. Use sys setup instead for keybindings, and sys config get to inspect values.',
|
|
155
150
|
help: {
|
|
156
151
|
name: 'sys config set',
|
|
157
152
|
summary: 'write a config value by dotted key',
|
|
158
153
|
params: [
|
|
159
|
-
{ kind: 'positional', name: 'key', type: 'string', required: true, constraint: 'Dotted key path. Supported: auto_update.crtr, auto_update.content, auto_update.interval_hours, max_panes_per_window,
|
|
154
|
+
{ kind: 'positional', name: 'key', type: 'string', required: true, constraint: 'Dotted key path. Supported: auto_update.crtr, auto_update.content, auto_update.interval_hours, max_panes_per_window, modelLadders.defaultProvider, modelLadders.<anthropic|openai>.<ultra|strong|medium|light>. Keybindings are edited only through sys setup.' },
|
|
160
155
|
{ kind: 'flag', name: 'value', type: 'string', required: true, constraint: 'value VALUE — string, required. Stored as-is if quoted; coerced to number or boolean when unambiguous.' },
|
|
161
156
|
{ kind: 'flag', name: 'scope', type: 'enum', choices: ['user', 'project'], required: false, constraint: 'Scope to write to. Default: user.' },
|
|
162
157
|
],
|
|
@@ -174,9 +169,11 @@ const configSet = defineLeaf({
|
|
|
174
169
|
const scope = resolveScope(input['scope']);
|
|
175
170
|
// Flags are stringly-typed; coerce to number or boolean when unambiguous
|
|
176
171
|
const parsed = parseConfigValue(rawValue);
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
172
|
+
// Mutate + persist through the central raw-partial path. `updateConfig`
|
|
173
|
+
// writes only the keys this set actually touched -- a non-ladder set never
|
|
174
|
+
// freezes a materialized `modelLadders`, and a direct
|
|
175
|
+
// `modelLadders.<provider>.<strength>` set persists only the touched rung.
|
|
176
|
+
const cfg = updateConfig(scope, (c) => setNestedValue(c, key, rawValue, parsed));
|
|
180
177
|
// Read back the written value for echo
|
|
181
178
|
const written = getNestedValue(cfg, key);
|
|
182
179
|
return { key, value: written, scope };
|
|
@@ -185,7 +182,7 @@ const configSet = defineLeaf({
|
|
|
185
182
|
const configPath = defineLeaf({
|
|
186
183
|
name: 'path',
|
|
187
184
|
description: 'print path(s) to config.json',
|
|
188
|
-
whenToUse: 'you need the absolute path to
|
|
185
|
+
whenToUse: 'you need the absolute path to a user or project config.json for inspection or backup.',
|
|
189
186
|
help: {
|
|
190
187
|
name: 'sys config path',
|
|
191
188
|
summary: 'print absolute path(s) to config.json',
|
|
@@ -225,7 +222,7 @@ const configPath = defineLeaf({
|
|
|
225
222
|
export const configBranch = defineBranch({
|
|
226
223
|
name: 'config',
|
|
227
224
|
description: 'read and write configuration',
|
|
228
|
-
whenToUse: 'inspecting
|
|
225
|
+
whenToUse: 'inspecting crtr settings, changing supported scalar values, or locating config.json. Keybinding changes belong in sys setup.',
|
|
229
226
|
help: {
|
|
230
227
|
name: 'sys config',
|
|
231
228
|
summary: 'read and write crtr configuration, including model ladders',
|
|
@@ -8,6 +8,8 @@ import { lsRemote } from '../../core/git.js';
|
|
|
8
8
|
import { listNodes } from '../../core/canvas/index.js';
|
|
9
9
|
import { activeFaultForDisplay } from '../../core/canvas/render.js';
|
|
10
10
|
import { readFault } from '../../core/runtime/fault.js';
|
|
11
|
+
import { validateEffectiveCommandPlugins } from '../../core/command-plugins/discovery.js';
|
|
12
|
+
import { SUBTREE_NAMES } from '../../build-root.js';
|
|
11
13
|
function pass(scope, name, message) {
|
|
12
14
|
return { scope, name, status: 'pass', message };
|
|
13
15
|
}
|
|
@@ -89,6 +91,41 @@ function faultRemediation(fault) {
|
|
|
89
91
|
logPath: fault.logPath,
|
|
90
92
|
};
|
|
91
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* Validate the command manifest + executable path of every effective command
|
|
96
|
+
* plugin (the deduped, enabled set that actually composes into the tree).
|
|
97
|
+
* Purely static — the plugin binary is NEVER executed, and no remediation ever
|
|
98
|
+
* chmods or rewrites third-party plugin content (every fix is a human_action:
|
|
99
|
+
* disable/update/remove the plugin). Only plugins whose scope is in `scopes`
|
|
100
|
+
* are reported, so `--scope` narrows these checks too.
|
|
101
|
+
*/
|
|
102
|
+
function runCommandPluginChecks(scopes) {
|
|
103
|
+
const results = [];
|
|
104
|
+
const inScope = new Set(scopes);
|
|
105
|
+
const reserved = new Set(SUBTREE_NAMES);
|
|
106
|
+
// Validate the whole effective set together so cross-plugin top-level name
|
|
107
|
+
// collisions surface here — a collided command is NOT mounted, and every
|
|
108
|
+
// claimant must fail, not pass.
|
|
109
|
+
for (const v of validateEffectiveCommandPlugins(reserved)) {
|
|
110
|
+
const plugin = v.plugin;
|
|
111
|
+
if (!inScope.has(plugin.scope))
|
|
112
|
+
continue;
|
|
113
|
+
if (v.issues.length === 0) {
|
|
114
|
+
const mounts = v.contributions.map((c) => c.node.name).join(', ');
|
|
115
|
+
results.push(pass(plugin.scope, `plugin:${plugin.name}:commands`, mounts.length > 0 ? `contributes top-level command(s): ${mounts}` : `command manifest valid`));
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
v.issues.forEach((issue, i) => {
|
|
119
|
+
const remediation = {
|
|
120
|
+
kind: 'human_action',
|
|
121
|
+
description: `${issue.next} If unfixable, disable (pkg plugin disable ${plugin.name}), update (pkg plugin update --name ${plugin.name}), or remove (pkg plugin remove ${plugin.name}) the plugin.`,
|
|
122
|
+
};
|
|
123
|
+
const detail = issue.path !== undefined ? ` at ${issue.path}` : '';
|
|
124
|
+
results.push(failCheck(plugin.scope, `plugin:${plugin.name}:commands[${i}]`, `${issue.code}${detail}: ${issue.message} (received ${issue.received}, expected ${issue.expected})`, remediation));
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
return results;
|
|
128
|
+
}
|
|
92
129
|
function runFaultChecks() {
|
|
93
130
|
const results = [];
|
|
94
131
|
for (const node of listNodes()) {
|
|
@@ -240,7 +277,7 @@ function runChecksForScope(scope, opts) {
|
|
|
240
277
|
export const sysDoctorLeaf = defineLeaf({
|
|
241
278
|
name: 'doctor',
|
|
242
279
|
description: 'diagnose installation health',
|
|
243
|
-
whenToUse: 'something in your crtr install looks off and you want it diagnosed — a plugin or marketplace manifest is missing,
|
|
280
|
+
whenToUse: 'something in your crtr install looks off and you want it diagnosed — a plugin or marketplace manifest is missing, a config entry points at a directory that no longer exists, or a command-plugin manifest/executable is malformed. Reports each problem with a structured remediation, and can apply the safe repairs for you.',
|
|
244
281
|
help: {
|
|
245
282
|
name: 'sys doctor',
|
|
246
283
|
summary: 'diagnose missing manifests and broken config entries',
|
|
@@ -250,13 +287,13 @@ export const sysDoctorLeaf = defineLeaf({
|
|
|
250
287
|
{ kind: 'flag', name: 'remote', type: 'bool', required: false, constraint: 'Check git remotes with ls-remote (slow — makes network calls).' },
|
|
251
288
|
],
|
|
252
289
|
output: [
|
|
253
|
-
{ name: 'checks', type: 'object[]', required: true, constraint: 'Each: {scope, name, status, message, fixed?, remediation?}. status: pass | fail. scope may be user | project | canvas. remediation (when present) is {kind, description, ...payload} where kind is remove_config_key | rm_path | human_action. Sorted by scope then name.' },
|
|
290
|
+
{ name: 'checks', type: 'object[]', required: true, constraint: 'Each: {scope, name, status, message, fixed?, remediation?}. status: pass | fail. scope may be user | project | canvas. Command-plugin manifest checks appear as plugin:<name>:commands (validated statically, never executed); their remediation is always a human_action (disable/update/remove the plugin). remediation (when present) is {kind, description, ...payload} where kind is remove_config_key | rm_path | human_action. Sorted by scope then name.' },
|
|
254
291
|
{ name: 'ok', type: 'boolean', required: true, constraint: 'True when no unresolved fail checks remain.' },
|
|
255
292
|
],
|
|
256
293
|
outputKind: 'object',
|
|
257
294
|
effects: [
|
|
258
|
-
'Read-only unless --fix is passed.',
|
|
259
|
-
'With --fix: applies each non-pass check\'s `remediation` — removes stale config entries and deletes dangling plugin/marketplace directories; canvas fault findings stay read-only.',
|
|
295
|
+
'Read-only unless --fix is passed. Command-plugin manifests are validated statically — the plugin executable is never run, at any time.',
|
|
296
|
+
'With --fix: applies each non-pass check\'s `remediation` — removes stale config entries and deletes dangling plugin/marketplace directories; canvas fault findings and command-plugin findings stay read-only (--fix never chmods or rewrites third-party plugin content).',
|
|
260
297
|
'Each non-pass result carries a structured `remediation` describing the fix action (absolute paths, exact config keys, or a human_action with logPath) so callers can apply it directly without --fix.',
|
|
261
298
|
],
|
|
262
299
|
},
|
|
@@ -270,6 +307,7 @@ export const sysDoctorLeaf = defineLeaf({
|
|
|
270
307
|
const results = runChecksForScope(scope, { fix, remote });
|
|
271
308
|
allResults.push(...results);
|
|
272
309
|
}
|
|
310
|
+
allResults.push(...runCommandPluginChecks(scopes));
|
|
273
311
|
allResults.push(...runFaultChecks());
|
|
274
312
|
// Sort by scope then name (mirrors old printResults grouping)
|
|
275
313
|
const scopeOrder = { user: 0, project: 1, builtin: 2, canvas: 3 };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type BindingId, type BindingResolution, type KeybindingDiagnostic, type SparseKeybindingOverrides } from '../../core/keybindings/index.js';
|
|
1
2
|
export type SetupPackageId = 'crtr-extensions' | 'mode-switch' | 'oauth-adapter';
|
|
2
3
|
export type SetupTool = 'tmux' | 'nvim';
|
|
3
4
|
export type SetupPackageSourceKind = 'local-path' | 'npm';
|
|
@@ -31,6 +32,7 @@ export interface SetupStaticInstructions {
|
|
|
31
32
|
packageLines: string[];
|
|
32
33
|
systemLines: string[];
|
|
33
34
|
exaLine: string;
|
|
35
|
+
composioLine: string;
|
|
34
36
|
footer: string;
|
|
35
37
|
}
|
|
36
38
|
export interface SetupSubmission {
|
|
@@ -39,18 +41,50 @@ export interface SetupSubmission {
|
|
|
39
41
|
systemDeps: SetupSystemInstallPlan[];
|
|
40
42
|
exaKey: string;
|
|
41
43
|
exaKeyPath: string;
|
|
44
|
+
composioKey: string;
|
|
45
|
+
composioKeyPath: string;
|
|
42
46
|
}
|
|
43
47
|
export interface SetupExecutionSummary {
|
|
44
48
|
installed: string[];
|
|
45
49
|
skipped: string[];
|
|
46
50
|
exaKeyWritten: boolean;
|
|
47
51
|
exaKeyPath: string;
|
|
52
|
+
composioKeyWritten: boolean;
|
|
53
|
+
composioKeyPath: string;
|
|
48
54
|
}
|
|
49
55
|
export interface SetupInitialState {
|
|
50
56
|
manifest: SetupPackageManifestEntry[];
|
|
51
57
|
installedPackageIds: Set<SetupPackageId>;
|
|
52
58
|
systemTools: SetupSystemToolState[];
|
|
53
59
|
exaKeyPath: string;
|
|
60
|
+
composioKeyPath: string;
|
|
61
|
+
}
|
|
62
|
+
export interface KeybindingEditResult {
|
|
63
|
+
readonly ok: boolean;
|
|
64
|
+
readonly diagnostics: readonly KeybindingDiagnostic[];
|
|
65
|
+
}
|
|
66
|
+
/** Transactional sparse keybinding draft used by the full-screen setup tab. */
|
|
67
|
+
export declare class SetupKeybindingsDraft {
|
|
68
|
+
private expected;
|
|
69
|
+
private baseline;
|
|
70
|
+
private current;
|
|
71
|
+
private baselineInvalidRoot;
|
|
72
|
+
private invalidRoot;
|
|
73
|
+
constructor(rawKeybindings: unknown);
|
|
74
|
+
get dirty(): boolean;
|
|
75
|
+
overrides(): Record<string, unknown>;
|
|
76
|
+
expectedKeybindings(): unknown;
|
|
77
|
+
resolution(): BindingResolution<BindingId>;
|
|
78
|
+
/** True while the persisted `keybindings` root is a non-object (e.g. a string):
|
|
79
|
+
* edits cannot be layered onto an invalid root, so the tab must reset-all first. */
|
|
80
|
+
hasInvalidRoot(): boolean;
|
|
81
|
+
expression(id: BindingId): string;
|
|
82
|
+
edit(id: BindingId, expression: string): KeybindingEditResult;
|
|
83
|
+
unbind(id: BindingId): KeybindingEditResult;
|
|
84
|
+
resetRow(id: BindingId): void;
|
|
85
|
+
resetAll(): void;
|
|
86
|
+
discard(): void;
|
|
87
|
+
markSaved(overrides: SparseKeybindingOverrides<BindingId>): void;
|
|
54
88
|
}
|
|
55
89
|
export declare function buildSetupManifest(resolveBuiltinPackageDir?: (name: string) => string): SetupPackageManifestEntry[];
|
|
56
90
|
export declare function normalizePackageIdentity(source: string, settingsDir: string, homeDir: string): SetupPackageIdentity;
|
|
@@ -61,6 +95,16 @@ export declare function buildSystemInstallPlan(tool: SetupTool, packageManager:
|
|
|
61
95
|
export declare function buildSystemToolState(tool: SetupTool, packageManager: PackageManager, commandExists?: (command: string) => boolean): SetupSystemToolState;
|
|
62
96
|
export declare function resolveSettingsPath(homeDir?: string): string;
|
|
63
97
|
export declare function resolveExaKeyPath(homeDir?: string): string;
|
|
98
|
+
export declare function resolveComposioKeyPath(homeDir?: string): string;
|
|
99
|
+
/** Where an already-present API key is resolved from — env var wins over the
|
|
100
|
+
* key file, matching the runtime resolvers (search/exa.ts, connectors). */
|
|
101
|
+
export type ApiKeySource = 'env' | 'file';
|
|
102
|
+
export interface ApiKeyPresence {
|
|
103
|
+
present: boolean;
|
|
104
|
+
source?: ApiKeySource;
|
|
105
|
+
}
|
|
106
|
+
export declare function detectExaKey(homeDir?: string): ApiKeyPresence;
|
|
107
|
+
export declare function detectComposioKey(homeDir?: string): ApiKeyPresence;
|
|
64
108
|
export declare function buildSetupInitialState(opts?: {
|
|
65
109
|
manifest?: SetupPackageManifestEntry[];
|
|
66
110
|
settingsPath?: string;
|
|
@@ -73,9 +117,11 @@ export declare function buildSetupStaticInstructions(opts: {
|
|
|
73
117
|
installedPackageIds: Set<SetupPackageId>;
|
|
74
118
|
systemPlans: SetupSystemInstallPlan[];
|
|
75
119
|
exaKeyPath: string;
|
|
120
|
+
composioKeyPath: string;
|
|
76
121
|
}): SetupStaticInstructions;
|
|
77
|
-
export declare function renderSetupStaticInstructions(state: Pick<SetupInitialState, 'manifest' | 'installedPackageIds' | 'systemTools' | 'exaKeyPath'>): string;
|
|
122
|
+
export declare function renderSetupStaticInstructions(state: Pick<SetupInitialState, 'manifest' | 'installedPackageIds' | 'systemTools' | 'exaKeyPath' | 'composioKeyPath'>): string;
|
|
78
123
|
export declare function writeExaKey(exaKeyPath: string, exaKey: string): Promise<void>;
|
|
124
|
+
export declare function writeComposioKey(composioKeyPath: string, composioKey: string): Promise<void>;
|
|
79
125
|
export declare function summarizeSetupExecution(result: {
|
|
80
126
|
installedPackages: string[];
|
|
81
127
|
skippedPackages: string[];
|
|
@@ -83,6 +129,8 @@ export declare function summarizeSetupExecution(result: {
|
|
|
83
129
|
skippedSystemDeps: string[];
|
|
84
130
|
exaKeyWritten: boolean;
|
|
85
131
|
exaKeyPath: string;
|
|
132
|
+
composioKeyWritten: boolean;
|
|
133
|
+
composioKeyPath: string;
|
|
86
134
|
}): SetupExecutionSummary;
|
|
87
135
|
export declare function formatSetupExecutionSummary(summary: SetupExecutionSummary): string;
|
|
88
136
|
export declare function executeSetupSubmission(submission: SetupSubmission): Promise<SetupExecutionSummary>;
|