@fungi.computer/oyster 0.2.0 → 0.3.1
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 +396 -72
- package/dist/agents.d.ts +3 -2
- package/dist/agents.js +4 -2
- package/dist/app-builds.d.ts +81 -8
- package/dist/app-builds.js +213 -60
- package/dist/app-storage.d.ts +3 -3
- package/dist/approval-capability.d.ts +5 -0
- package/dist/approval-capability.js +46 -0
- package/dist/approval-home.d.ts +51 -0
- package/dist/approval-home.js +226 -0
- package/dist/apps/catalog.d.ts +335 -0
- package/dist/apps/catalog.js +46 -0
- package/dist/apps/gate.d.ts +20 -6
- package/dist/apps/gate.js +42 -16
- package/dist/apps/index.d.ts +3 -1
- package/dist/apps/index.js +3 -1
- package/dist/apps/installation.d.ts +132 -51
- package/dist/apps/installation.js +176 -70
- package/dist/apps/permissions.d.ts +247 -0
- package/dist/apps/permissions.js +255 -0
- package/dist/boot-capability-route.d.ts +15 -0
- package/dist/boot-capability-route.js +196 -0
- package/dist/boot-capability.d.ts +103 -0
- package/dist/boot-capability.js +141 -0
- package/dist/boot-construction.d.ts +12 -0
- package/dist/boot-construction.js +175 -0
- package/dist/boot-gate.d.ts +267 -0
- package/dist/boot-gate.js +236 -0
- package/dist/boot-host-script.d.ts +2 -0
- package/dist/boot-host-script.js +1 -0
- package/dist/boot-mount.d.ts +21 -0
- package/dist/boot-mount.js +65 -0
- package/dist/browser/boot.d.ts +73 -0
- package/dist/browser/boot.js +502 -0
- package/dist/browser/browser.d.ts +104 -0
- package/dist/browser/browser.js +374 -0
- package/dist/browser/capability-source.d.ts +76 -0
- package/dist/browser/capability-source.js +338 -0
- package/dist/browser/cdp-client.d.ts +56 -0
- package/dist/browser/cdp-client.js +184 -0
- package/dist/browser/errors.d.ts +79 -0
- package/dist/browser/errors.js +32 -0
- package/dist/browser/index.d.ts +16 -0
- package/dist/browser/index.js +14 -0
- package/dist/browser/lease-registry.d.ts +61 -0
- package/dist/browser/lease-registry.js +101 -0
- package/dist/browser/operations.d.ts +225 -0
- package/dist/browser/operations.js +137 -0
- package/dist/browser/page.d.ts +25 -0
- package/dist/browser/page.js +172 -0
- package/dist/browser/quick-reads.d.ts +29 -0
- package/dist/browser/quick-reads.js +160 -0
- package/dist/browser/sessions.d.ts +52 -0
- package/dist/browser/sessions.js +118 -0
- package/dist/browser/url-policy.d.ts +18 -0
- package/dist/browser/url-policy.js +58 -0
- package/dist/build/app-imports.d.ts +12 -0
- package/dist/build/app-imports.js +105 -0
- package/dist/build/build-policy.d.ts +5 -3
- package/dist/build/build-policy.js +5 -3
- package/dist/build/candidate-builder.d.ts +1 -1
- package/dist/build/candidate-cli.mjs +8375 -334
- package/dist/build/local-build.d.ts +2 -0
- package/dist/build/local-build.js +28 -6
- package/dist/build/snapshot-package-store.d.ts +1 -1
- package/dist/build/snapshot-package-store.js +7 -2
- package/dist/build/workspace-build.d.ts +92 -5
- package/dist/build/workspace-build.js +93 -19
- package/dist/build.d.ts +1 -1
- package/dist/build.js +1 -1
- package/dist/catalog-frame.js +1 -1
- package/dist/cloudflare.d.ts +13 -3
- package/dist/cloudflare.js +102 -4
- package/dist/frame-binding-wire-script.js +1 -1
- package/dist/frame-binding-wire.js +4 -2
- package/dist/git-auth.d.ts +0 -2
- package/dist/git-auth.js +0 -2
- package/dist/git.d.ts +0 -1
- package/dist/git.js +0 -2
- package/dist/host.d.ts +39 -13
- package/dist/host.js +268 -142
- package/dist/index.d.ts +25 -15
- package/dist/index.js +39 -16
- package/dist/install-release-cli.d.ts +2 -0
- package/dist/install-release-cli.js +46 -0
- package/dist/installation-client.d.ts +43 -0
- package/dist/installation-client.js +178 -0
- package/dist/installation-execution.d.ts +11 -0
- package/dist/installation-execution.js +184 -0
- package/dist/installation-operations.d.ts +1437 -0
- package/dist/installation-operations.js +664 -0
- package/dist/installation-store-generation.d.ts +3 -0
- package/dist/installation-store-generation.js +16 -0
- package/dist/instance-id.d.ts +10 -0
- package/dist/instance-id.js +10 -0
- package/dist/instance-refusal.d.ts +11 -0
- package/dist/instance-refusal.js +21 -0
- package/dist/internal/delivery.js +4 -2
- package/dist/internal/host-gate.js +7 -1
- package/dist/internal/registry-installations.js +4 -4
- package/dist/keys.d.ts +5 -1
- package/dist/keys.js +10 -2
- package/dist/machine-link/authority.d.ts +89 -0
- package/dist/machine-link/authority.js +37 -0
- package/dist/machine-link/client.d.ts +66 -0
- package/dist/machine-link/client.js +94 -0
- package/dist/machine-link/delivery.d.ts +18 -0
- package/dist/machine-link/delivery.js +55 -0
- package/dist/machine-link/enrollment.d.ts +111 -0
- package/dist/machine-link/enrollment.js +286 -0
- package/dist/machine-link/fences.d.ts +37 -0
- package/dist/machine-link/fences.js +166 -0
- package/dist/machine-link/home.d.ts +20 -0
- package/dist/machine-link/home.js +24 -0
- package/dist/machine-link/host.d.ts +43 -0
- package/dist/machine-link/host.js +189 -0
- package/dist/machine-link/index.d.ts +15 -0
- package/dist/machine-link/index.js +15 -0
- package/dist/machine-link/link.d.ts +48 -0
- package/dist/machine-link/link.js +223 -0
- package/dist/machine-link/presence.d.ts +10 -0
- package/dist/machine-link/presence.js +25 -0
- package/dist/machine-link/workers.d.ts +6 -0
- package/dist/machine-link/workers.js +6 -0
- package/dist/mcp-owner.d.ts +2 -2
- package/dist/mcp-owner.js +41 -33
- package/dist/mcp.d.ts +15 -3
- package/dist/mcp.js +146 -25
- package/dist/older-oyster-store-refusal.d.ts +4 -0
- package/dist/older-oyster-store-refusal.js +18 -0
- package/dist/older-oyster-store.d.ts +21 -0
- package/dist/older-oyster-store.js +43 -0
- package/dist/pack.d.ts +14 -3
- package/dist/pack.js +44 -19
- package/dist/page/app-access.d.ts +7 -0
- package/dist/page/app-access.js +75 -0
- package/dist/page/boot-host.js +57 -0
- package/dist/page/capabilities.d.ts +3 -3
- package/dist/page/capabilities.js +16 -12
- package/dist/page/computer-handles.d.ts +3 -3
- package/dist/page/computer-target.d.ts +3 -0
- package/dist/page/computer-target.js +9 -0
- package/dist/page/mount.d.ts +23 -3
- package/dist/page/mount.js +152 -16
- package/dist/page-assets.d.ts +22 -0
- package/dist/page-assets.js +28 -0
- package/dist/page-script.d.ts +3 -0
- package/dist/page-script.js +5 -4
- package/dist/release.d.ts +13 -6
- package/dist/release.js +10 -7
- package/dist/root-data.d.ts +16 -6
- package/dist/root-data.js +2 -2
- package/dist/source/index.d.ts +1 -1
- package/dist/source/team-source.d.ts +20 -8
- package/dist/source/team-source.js +39 -10
- package/dist/source/template-seed.d.ts +2 -2
- package/dist/standalone/agent-mail.d.ts +24 -0
- package/dist/standalone/agent-mail.js +62 -0
- package/dist/standalone/agent-store.d.ts +9 -0
- package/dist/standalone/agent-store.js +30 -0
- package/dist/standalone/agents.d.ts +68 -9
- package/dist/standalone/agents.js +428 -56
- package/dist/standalone/app-builds-binding.d.ts +20 -2
- package/dist/standalone/app-builds-binding.js +147 -23
- package/dist/standalone/app-set.d.ts +5 -2
- package/dist/standalone/app-set.js +186 -144
- package/dist/standalone/browser.d.ts +11 -0
- package/dist/standalone/browser.js +72 -0
- package/dist/standalone/builds.d.ts +13 -4
- package/dist/standalone/builds.js +28 -44
- package/dist/standalone/computer-egress.d.ts +2 -0
- package/dist/standalone/computer-egress.js +13 -4
- package/dist/standalone/computer-fleet.d.ts +43 -0
- package/dist/standalone/computer-fleet.js +200 -0
- package/dist/standalone/computer.d.ts +44 -9
- package/dist/standalone/computer.js +129 -22
- package/dist/standalone/install-apps-cli.js +43 -6
- package/dist/standalone/instance.d.ts +2 -2
- package/dist/standalone/instance.js +8 -11
- package/dist/standalone/machine-link.d.ts +354 -0
- package/dist/standalone/machine-link.js +368 -0
- package/dist/standalone/media.d.ts +2 -2
- package/dist/standalone/media.js +19 -16
- package/dist/standalone/preview.d.ts +2 -2
- package/dist/standalone/preview.js +37 -10
- package/dist/standalone/registry.d.ts +151 -9
- package/dist/standalone/registry.js +305 -8
- package/dist/standalone/worker.d.ts +19 -5
- package/dist/standalone/worker.js +90 -54
- package/dist/standalone/workflow-binding.d.ts +18 -22
- package/dist/standalone/workflow-binding.js +18 -18
- package/dist/standalone/workflow-control.d.ts +4 -0
- package/dist/standalone/workflow-control.js +40 -0
- package/dist/standalone/workflow-events.d.ts +2 -2
- package/dist/standalone/workflow-events.js +9 -10
- package/dist/standalone/workflow-git-capture.js +4 -3
- package/dist/standalone/workflow-host.d.ts +162 -161
- package/dist/standalone/workflow-host.js +101 -21
- package/dist/standalone/workflow-node-capture.js +11 -4
- package/dist/standalone/workflow-schedules.d.ts +5 -2
- package/dist/standalone/workflow-schedules.js +9 -10
- package/dist/standalone/workflow-trigger-host.d.ts +65 -5
- package/dist/standalone/workflow-trigger-host.js +2 -2
- package/dist/standalone/workflow-webhooks.d.ts +22 -0
- package/dist/standalone/workflow-webhooks.js +39 -0
- package/dist/standalone/workflows.d.ts +140 -43
- package/dist/standalone/workflows.js +198 -39
- package/dist/storage-frame.d.ts +6 -6
- package/dist/testing/capabilities.js +14 -3
- package/dist/testing/installation.js +26 -2
- package/dist/testing/worker.js +1 -1
- package/dist/testing/workers-runtime.d.ts +8 -2
- package/dist/testing/workers-runtime.js +20 -2
- package/dist/webhook-abuse.d.ts +25 -0
- package/dist/webhook-abuse.js +54 -0
- package/dist/webhook-custody.d.ts +144 -0
- package/dist/webhook-custody.js +222 -0
- package/dist/webhook-ingress.d.ts +36 -0
- package/dist/webhook-ingress.js +146 -0
- package/dist/webhooks.d.ts +111 -0
- package/dist/webhooks.js +189 -0
- package/dist/workers-git.d.ts +12 -17
- package/dist/workers-git.js +64 -52
- package/dist/workers.d.ts +226 -13
- package/dist/workers.js +363 -51
- package/dist/workflow-agent-authority.d.ts +8 -0
- package/dist/workflow-agent-authority.js +42 -0
- package/dist/workflows.d.ts +66 -0
- package/dist/workflows.js +97 -0
- package/docs/api/README.md +63 -37
- package/docs/api/agents.md +17 -0
- package/docs/api/app-storage.md +1 -1
- package/docs/api/apps.md +1394 -543
- package/docs/api/browser/boot.md +132 -0
- package/docs/api/browser.md +1440 -0
- package/docs/api/build-contract.md +38 -25
- package/docs/api/build.md +263 -84
- package/docs/api/cloudflare.md +93 -7
- package/docs/api/git.md +3 -13
- package/docs/api/host.md +944 -118
- package/docs/api/index.md +320 -18
- package/docs/api/keys.md +24 -1
- package/docs/api/mcp.md +59 -12
- package/docs/api/modules.md +33 -40
- package/docs/api/pack.md +57 -8
- package/docs/api/page/mount.md +92 -4
- package/docs/api/workers-git.md +103 -24
- package/docs/api/workers.md +1594 -244
- package/docs/site/agent-quickstart.mdx +28 -14
- package/examples/standalone/worker.ts +3 -1
- package/examples/standalone/wrangler.jsonc +2 -0
- package/package.json +73 -71
- package/dist/installation-consent.d.ts +0 -81
- package/dist/installation-consent.js +0 -84
- package/dist/shell/app-directory.d.ts +0 -542
- package/dist/shell/app-directory.js +0 -196
- package/dist/shell/browser-actions.d.ts +0 -7
- package/dist/shell/browser-actions.js +0 -56
- package/dist/shell/command-host.d.ts +0 -112
- package/dist/shell/command-host.js +0 -502
- package/dist/shell/commands.d.ts +0 -25
- package/dist/shell/commands.js +0 -78
- package/dist/shell/index.d.ts +0 -8
- package/dist/shell/index.js +0 -8
- package/dist/shell/keys.d.ts +0 -41
- package/dist/shell/keys.js +0 -134
- package/dist/shell/shell-module.d.ts +0 -55
- package/dist/shell/shell-module.js +0 -86
- package/dist/shell/window-manager.d.ts +0 -128
- package/dist/shell/window-manager.js +0 -730
- package/dist/shell/workbench-contract.d.ts +0 -68
- package/dist/shell/workbench-directory.d.ts +0 -332
- package/dist/shell/workbench-directory.js +0 -35
- package/dist/shell/workbench-host-types.d.ts +0 -96
- package/dist/shell/workbench-host-types.js +0 -1
- package/dist/shell/workbench-host.d.ts +0 -34
- package/dist/shell/workbench-host.js +0 -352
- package/dist/shell/workbench-model.d.ts +0 -194
- package/dist/shell/workbench-model.js +0 -53
- package/dist/shell/workbench.d.ts +0 -4
- package/dist/shell/workbench.js +0 -2
- package/docs/api/shell/app-directory.md +0 -599
- package/docs/api/shell/command-host.md +0 -224
- package/docs/api/shell/commands.md +0 -197
- package/docs/api/shell/keys.md +0 -183
- package/docs/api/shell/shell-module.md +0 -204
- package/docs/api/shell/window-manager.md +0 -267
- package/docs/api/shell/workbench-directory.md +0 -119
- package/docs/api/shell/workbench.md +0 -205
- package/docs/api/shell.md +0 -1915
- /package/dist/{shell/workbench-contract.js → page/boot-host.d.ts} +0 -0
|
@@ -1,502 +0,0 @@
|
|
|
1
|
-
import { AppError } from "@fungi.computer/agar/errors";
|
|
2
|
-
import { createWhistle, scopeSnapshot, } from "@fungi.computer/whistle";
|
|
3
|
-
const emptyMenu = Object.freeze([]);
|
|
4
|
-
const commandPaletteReservedChord = Object.freeze({
|
|
5
|
-
altKey: false,
|
|
6
|
-
ctrlKey: false,
|
|
7
|
-
id: "shell:show-command-palette",
|
|
8
|
-
key: "k",
|
|
9
|
-
metaKey: true,
|
|
10
|
-
shiftKey: false,
|
|
11
|
-
});
|
|
12
|
-
/** Select the shell command-palette chord for a Mac or non-Mac keyboard. */
|
|
13
|
-
export function commandPaletteReservedChordForPlatform(mac) {
|
|
14
|
-
return Object.freeze({
|
|
15
|
-
...commandPaletteReservedChord,
|
|
16
|
-
ctrlKey: !mac,
|
|
17
|
-
metaKey: mac,
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
/** Select the shell command-palette chord from the embedding browser user agent. */
|
|
21
|
-
export function commandPaletteReservedChordForUserAgent(userAgent) {
|
|
22
|
-
return commandPaletteReservedChordForPlatform(/Mac|iPhone|iPad/u.test(userAgent));
|
|
23
|
-
}
|
|
24
|
-
/** Whistle source of Release-advertised rows for Apps not yet mounted. */
|
|
25
|
-
export const appDirectorySourceId = "app-directory";
|
|
26
|
-
/** Bindings an App may never claim: the leader chord crosses every iframe. */
|
|
27
|
-
const reservedBindings = new Set([
|
|
28
|
-
"super+k",
|
|
29
|
-
"meta+k",
|
|
30
|
-
"cmd+k",
|
|
31
|
-
"mod+k",
|
|
32
|
-
"ctrl+k",
|
|
33
|
-
"control+k",
|
|
34
|
-
]);
|
|
35
|
-
function sameValues(left, right) {
|
|
36
|
-
return left === undefined || right === undefined
|
|
37
|
-
? left === right
|
|
38
|
-
: left.length === right.length &&
|
|
39
|
-
left.every((value, index) => value === right[index]);
|
|
40
|
-
}
|
|
41
|
-
function matchesBindings(actual, declared) {
|
|
42
|
-
return (actual?.bindings?.order === declared?.bindings?.order &&
|
|
43
|
-
sameValues(actual?.bindings?.values, declared?.bindings?.values));
|
|
44
|
-
}
|
|
45
|
-
function matchesSlash(actual, declared) {
|
|
46
|
-
return (actual?.slash?.order === declared?.slash?.order &&
|
|
47
|
-
sameValues(actual?.slash?.aliases, declared?.slash?.aliases));
|
|
48
|
-
}
|
|
49
|
-
function matchesAgent(actual, declared) {
|
|
50
|
-
return (actual?.agent?.order === declared?.agent?.order &&
|
|
51
|
-
actual?.agent?.keybind === declared?.agent?.keybind);
|
|
52
|
-
}
|
|
53
|
-
function matchesHelp(actual, declared) {
|
|
54
|
-
return actual?.help?.order === declared?.help?.order;
|
|
55
|
-
}
|
|
56
|
-
function matchesMenu(actual, declared) {
|
|
57
|
-
return actual?.menu?.order === declared?.menu?.order;
|
|
58
|
-
}
|
|
59
|
-
function matchesPalette(actual, declared) {
|
|
60
|
-
return actual?.palette?.order === declared?.palette?.order;
|
|
61
|
-
}
|
|
62
|
-
function matchesDeclaration(command, declaration) {
|
|
63
|
-
const actual = command.projections;
|
|
64
|
-
const declared = declaration.projections;
|
|
65
|
-
return (command.id === declaration.id &&
|
|
66
|
-
command.title === declaration.title &&
|
|
67
|
-
command.category === declaration.category &&
|
|
68
|
-
command.description === declaration.description &&
|
|
69
|
-
matchesBindings(actual, declared) &&
|
|
70
|
-
matchesAgent(actual, declared) &&
|
|
71
|
-
matchesHelp(actual, declared) &&
|
|
72
|
-
matchesMenu(actual, declared) &&
|
|
73
|
-
matchesPalette(actual, declared) &&
|
|
74
|
-
matchesSlash(actual, declared));
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Own one shell's Whistle runtime for mounted Apps and local panes. The
|
|
78
|
-
* embedding host supplies verified Release declarations and decides which
|
|
79
|
-
* App or pane has focus.
|
|
80
|
-
*
|
|
81
|
-
* Agar invokes `registerCommands` once for the aggregate command set of a
|
|
82
|
-
* mount. The adapter keeps that aggregate as one Whistle generation, so an
|
|
83
|
-
* Agar update replaces the generation atomically and disposal releases only
|
|
84
|
-
* that App. Command handlers remain the App's callback; the shell only adds
|
|
85
|
-
* the Whistle identity and routes focused menu execution to it.
|
|
86
|
-
*/
|
|
87
|
-
export function createAppSurfaceCommandHost(whistle = createWhistle()) {
|
|
88
|
-
const mounts = new Map();
|
|
89
|
-
const panes = new Map();
|
|
90
|
-
const listeners = new Set();
|
|
91
|
-
let focusedMount = null;
|
|
92
|
-
let activeSnapshot = scopeSnapshot(whistle.snapshot(), null);
|
|
93
|
-
let focusedMenu = emptyMenu;
|
|
94
|
-
let shellContribution;
|
|
95
|
-
let directoryContribution;
|
|
96
|
-
let disposed = false;
|
|
97
|
-
let disposePresenter;
|
|
98
|
-
const refreshPresenter = () => {
|
|
99
|
-
disposePresenter?.();
|
|
100
|
-
disposePresenter = undefined;
|
|
101
|
-
if (disposed)
|
|
102
|
-
return;
|
|
103
|
-
const presenter = focusedMount === null
|
|
104
|
-
? undefined
|
|
105
|
-
: panes.get(focusedMount)?.presenters.at(-1)?.presenter;
|
|
106
|
-
if (presenter !== undefined)
|
|
107
|
-
disposePresenter = whistle.present(presenter);
|
|
108
|
-
};
|
|
109
|
-
const publish = () => {
|
|
110
|
-
for (const listener of listeners)
|
|
111
|
-
listener();
|
|
112
|
-
};
|
|
113
|
-
// One atomic recomputation per graph or focus change: subscribers never see
|
|
114
|
-
// two Apps active at once.
|
|
115
|
-
const refreshMenu = () => {
|
|
116
|
-
activeSnapshot = scopeSnapshot(whistle.snapshot(), focusedMount);
|
|
117
|
-
for (const [id, pane] of panes) {
|
|
118
|
-
if (pane.disposed)
|
|
119
|
-
continue;
|
|
120
|
-
pane.snapshot = scopeSnapshot(whistle.snapshot(), id);
|
|
121
|
-
for (const listener of pane.listeners)
|
|
122
|
-
listener();
|
|
123
|
-
}
|
|
124
|
-
focusedMenu =
|
|
125
|
-
focusedMount === null
|
|
126
|
-
? emptyMenu
|
|
127
|
-
: Object.freeze(activeSnapshot.menu.filter((command) => command.scope === focusedMount));
|
|
128
|
-
publish();
|
|
129
|
-
};
|
|
130
|
-
const unsubscribeWhistle = whistle.subscribe(refreshMenu);
|
|
131
|
-
const assertLive = () => {
|
|
132
|
-
if (disposed)
|
|
133
|
-
throw new Error("App command host is disposed");
|
|
134
|
-
};
|
|
135
|
-
const contributionFor = (mount, input, commands) => {
|
|
136
|
-
for (const command of commands) {
|
|
137
|
-
const declaration = mount.declarations.get(command.id);
|
|
138
|
-
if (declaration === undefined ||
|
|
139
|
-
!matchesDeclaration(command, declaration))
|
|
140
|
-
throw new AppError(`App command ${command.id} does not match its Release declaration`, { code: "COMMAND_NOT_DECLARED", retryable: false });
|
|
141
|
-
for (const binding of command.projections?.bindings?.values ?? [])
|
|
142
|
-
if (reservedBindings.has(binding.trim().toLowerCase()))
|
|
143
|
-
throw new Error("App commands cannot bind the reserved leader chord");
|
|
144
|
-
}
|
|
145
|
-
return {
|
|
146
|
-
sourceId: mount.id,
|
|
147
|
-
namespace: encodeURIComponent(mount.id),
|
|
148
|
-
scope: mount.id,
|
|
149
|
-
commands: commands.map((command) => {
|
|
150
|
-
// Agar carries a static availability fact; Whistle evaluates availability
|
|
151
|
-
// through its existing function-shaped runtime contract.
|
|
152
|
-
const { availability, projections, description, action, ...metadata } = command;
|
|
153
|
-
const converted = {
|
|
154
|
-
...metadata,
|
|
155
|
-
handler: (execution) => {
|
|
156
|
-
const invocation = {
|
|
157
|
-
origin: execution.origin,
|
|
158
|
-
};
|
|
159
|
-
if (execution.arguments !== undefined)
|
|
160
|
-
Object.assign(invocation, { arguments: execution.arguments });
|
|
161
|
-
if (execution.signal !== undefined)
|
|
162
|
-
Object.assign(invocation, { signal: execution.signal });
|
|
163
|
-
return input.invoke(command.id, invocation);
|
|
164
|
-
},
|
|
165
|
-
};
|
|
166
|
-
if (availability !== undefined)
|
|
167
|
-
Object.assign(converted, { availability: () => availability });
|
|
168
|
-
// Whistle's optional fields reject explicit undefined; copy only present ones.
|
|
169
|
-
if (projections !== undefined)
|
|
170
|
-
Object.assign(converted, { projections });
|
|
171
|
-
if (description !== undefined)
|
|
172
|
-
Object.assign(converted, { description });
|
|
173
|
-
if (action !== undefined)
|
|
174
|
-
Object.assign(converted, { action });
|
|
175
|
-
return converted;
|
|
176
|
-
}),
|
|
177
|
-
};
|
|
178
|
-
};
|
|
179
|
-
const mount = (mountId, declarations) => {
|
|
180
|
-
assertLive();
|
|
181
|
-
if (mountId.trim().length === 0)
|
|
182
|
-
throw new Error("App command mount ID must not be blank");
|
|
183
|
-
if (mounts.has(mountId) || panes.has(mountId))
|
|
184
|
-
throw new Error("App command mount ID is already active");
|
|
185
|
-
const state = {
|
|
186
|
-
id: mountId,
|
|
187
|
-
declarations: new Map(declarations.map((command) => [command.id, command])),
|
|
188
|
-
disposed: false,
|
|
189
|
-
contribution: undefined,
|
|
190
|
-
};
|
|
191
|
-
mounts.set(mountId, state);
|
|
192
|
-
const registerCommands = (input) => Promise.resolve().then(() => {
|
|
193
|
-
assertLive();
|
|
194
|
-
if (state.disposed)
|
|
195
|
-
throw new Error("App command mount is disposed");
|
|
196
|
-
if (state.contribution !== undefined)
|
|
197
|
-
throw new Error("App command mount already registered commands");
|
|
198
|
-
const lease = whistle.contribute(contributionFor(state, input, input.commands));
|
|
199
|
-
let active = true;
|
|
200
|
-
const contribution = {
|
|
201
|
-
update: (commands) => {
|
|
202
|
-
if (!active || state.disposed || disposed)
|
|
203
|
-
return;
|
|
204
|
-
lease.update(contributionFor(state, input, commands).commands);
|
|
205
|
-
},
|
|
206
|
-
dispose: () => {
|
|
207
|
-
if (!active)
|
|
208
|
-
return;
|
|
209
|
-
active = false;
|
|
210
|
-
lease.dispose();
|
|
211
|
-
if (state.contribution === contribution)
|
|
212
|
-
state.contribution = undefined;
|
|
213
|
-
},
|
|
214
|
-
};
|
|
215
|
-
state.contribution = contribution;
|
|
216
|
-
return contribution;
|
|
217
|
-
});
|
|
218
|
-
const invokeReservedChord = async (input) => {
|
|
219
|
-
assertLive();
|
|
220
|
-
if (state.disposed || input.id !== commandPaletteReservedChord.id)
|
|
221
|
-
throw new Error("App reserved chord is unavailable");
|
|
222
|
-
if (input.repeat)
|
|
223
|
-
return;
|
|
224
|
-
const outcome = await execute(input.id, { origin: "browser" });
|
|
225
|
-
if (outcome.status !== "handled")
|
|
226
|
-
throw new Error("App reserved chord could not run");
|
|
227
|
-
};
|
|
228
|
-
return Object.freeze({
|
|
229
|
-
handlers: Object.freeze({ registerCommands, invokeReservedChord }),
|
|
230
|
-
dispose: () => {
|
|
231
|
-
if (state.disposed)
|
|
232
|
-
return;
|
|
233
|
-
state.disposed = true;
|
|
234
|
-
state.contribution?.dispose();
|
|
235
|
-
state.contribution = undefined;
|
|
236
|
-
mounts.delete(state.id);
|
|
237
|
-
if (focusedMount === state.id) {
|
|
238
|
-
focusedMount = null;
|
|
239
|
-
refreshMenu();
|
|
240
|
-
}
|
|
241
|
-
},
|
|
242
|
-
});
|
|
243
|
-
};
|
|
244
|
-
const mountPane = (paneId) => {
|
|
245
|
-
assertLive();
|
|
246
|
-
if (paneId.trim().length === 0)
|
|
247
|
-
throw new Error("Pane command mount ID must not be blank");
|
|
248
|
-
if (mounts.has(paneId) || panes.has(paneId))
|
|
249
|
-
throw new Error("Pane command mount ID is already active");
|
|
250
|
-
const namespace = `pane-${encodeURIComponent(paneId)}`;
|
|
251
|
-
const ownedCommands = new Map();
|
|
252
|
-
const state = {
|
|
253
|
-
disposed: false,
|
|
254
|
-
snapshot: scopeSnapshot(whistle.snapshot(), paneId),
|
|
255
|
-
leases: new Set(),
|
|
256
|
-
listeners: new Set(),
|
|
257
|
-
presenters: [],
|
|
258
|
-
dispose: () => {
|
|
259
|
-
if (state.disposed)
|
|
260
|
-
return;
|
|
261
|
-
state.disposed = true;
|
|
262
|
-
state.listeners.clear();
|
|
263
|
-
state.presenters.length = 0;
|
|
264
|
-
for (const lease of state.leases)
|
|
265
|
-
lease.dispose();
|
|
266
|
-
state.leases.clear();
|
|
267
|
-
ownedCommands.clear();
|
|
268
|
-
state.snapshot = scopeSnapshot(whistle.snapshot(), paneId);
|
|
269
|
-
panes.delete(paneId);
|
|
270
|
-
if (focusedMount === paneId) {
|
|
271
|
-
focusedMount = null;
|
|
272
|
-
refreshMenu();
|
|
273
|
-
}
|
|
274
|
-
refreshPresenter();
|
|
275
|
-
},
|
|
276
|
-
};
|
|
277
|
-
panes.set(paneId, state);
|
|
278
|
-
const assertPaneLive = () => {
|
|
279
|
-
assertLive();
|
|
280
|
-
if (state.disposed)
|
|
281
|
-
throw new Error("Pane command mount is disposed");
|
|
282
|
-
};
|
|
283
|
-
const checkBindings = (commands) => {
|
|
284
|
-
for (const command of commands)
|
|
285
|
-
for (const binding of command.projections?.bindings?.values ?? [])
|
|
286
|
-
if (reservedBindings.has(binding.trim().toLowerCase()))
|
|
287
|
-
throw new Error("Pane commands cannot bind the reserved leader chord");
|
|
288
|
-
};
|
|
289
|
-
return Object.freeze({
|
|
290
|
-
commandId: (id) => `${namespace}:${id}`,
|
|
291
|
-
contribute: (commands) => {
|
|
292
|
-
assertPaneLive();
|
|
293
|
-
checkBindings(commands);
|
|
294
|
-
const underlying = whistle.contribute({
|
|
295
|
-
sourceId: `pane:${paneId}`,
|
|
296
|
-
namespace,
|
|
297
|
-
scope: paneId,
|
|
298
|
-
commands,
|
|
299
|
-
});
|
|
300
|
-
let active = true;
|
|
301
|
-
const lease = Object.freeze({
|
|
302
|
-
update: (replacement) => {
|
|
303
|
-
if (!active || state.disposed || disposed)
|
|
304
|
-
return;
|
|
305
|
-
checkBindings(replacement);
|
|
306
|
-
underlying.update(replacement);
|
|
307
|
-
ownedCommands.set(lease, new Set(replacement.map((command) => `${namespace}:${command.id}`)));
|
|
308
|
-
},
|
|
309
|
-
dispose: () => {
|
|
310
|
-
if (!active)
|
|
311
|
-
return;
|
|
312
|
-
active = false;
|
|
313
|
-
state.leases.delete(lease);
|
|
314
|
-
ownedCommands.delete(lease);
|
|
315
|
-
underlying.dispose();
|
|
316
|
-
},
|
|
317
|
-
});
|
|
318
|
-
state.leases.add(lease);
|
|
319
|
-
ownedCommands.set(lease, new Set(commands.map((command) => `${namespace}:${command.id}`)));
|
|
320
|
-
return lease;
|
|
321
|
-
},
|
|
322
|
-
execute: (commandId, input) => {
|
|
323
|
-
const snapshot = state.snapshot;
|
|
324
|
-
const rows = input.origin === "agent"
|
|
325
|
-
? [snapshot.agent]
|
|
326
|
-
: [
|
|
327
|
-
snapshot.bindings,
|
|
328
|
-
snapshot.palette,
|
|
329
|
-
snapshot.slash,
|
|
330
|
-
snapshot.help,
|
|
331
|
-
snapshot.menu,
|
|
332
|
-
snapshot.agent,
|
|
333
|
-
];
|
|
334
|
-
// A catalog action can be callable from an admitted row without a menu
|
|
335
|
-
// or palette projection. Its contribution still belongs to this pane.
|
|
336
|
-
const owned = input.origin !== "agent" &&
|
|
337
|
-
[...ownedCommands.values()].some((ids) => ids.has(commandId));
|
|
338
|
-
const admitted = owned ||
|
|
339
|
-
rows.some((projection) => projection.some((row) => row.commandId === commandId));
|
|
340
|
-
const human = input.origin !== "programmatic" && input.origin !== "agent";
|
|
341
|
-
if (state.disposed ||
|
|
342
|
-
disposed ||
|
|
343
|
-
!admitted ||
|
|
344
|
-
(human && focusedMount !== paneId))
|
|
345
|
-
return Promise.resolve({ status: "missing" });
|
|
346
|
-
return whistle.execute(commandId, input);
|
|
347
|
-
},
|
|
348
|
-
snapshot: () => state.snapshot,
|
|
349
|
-
subscribe: (listener) => {
|
|
350
|
-
if (state.disposed || disposed)
|
|
351
|
-
return () => undefined;
|
|
352
|
-
state.listeners.add(listener);
|
|
353
|
-
return () => {
|
|
354
|
-
state.listeners.delete(listener);
|
|
355
|
-
};
|
|
356
|
-
},
|
|
357
|
-
present: (presenter) => {
|
|
358
|
-
assertPaneLive();
|
|
359
|
-
const entry = { presenter };
|
|
360
|
-
state.presenters.push(entry);
|
|
361
|
-
refreshPresenter();
|
|
362
|
-
return () => {
|
|
363
|
-
const index = state.presenters.indexOf(entry);
|
|
364
|
-
if (index === -1)
|
|
365
|
-
return;
|
|
366
|
-
state.presenters.splice(index, 1);
|
|
367
|
-
refreshPresenter();
|
|
368
|
-
};
|
|
369
|
-
},
|
|
370
|
-
dispose: state.dispose,
|
|
371
|
-
});
|
|
372
|
-
};
|
|
373
|
-
const focus = (mountId) => {
|
|
374
|
-
const state = mountId === null
|
|
375
|
-
? undefined
|
|
376
|
-
: (mounts.get(mountId) ?? panes.get(mountId));
|
|
377
|
-
const nextFocus = mountId !== null && state !== undefined && !state.disposed
|
|
378
|
-
? mountId
|
|
379
|
-
: null;
|
|
380
|
-
if (focusedMount === nextFocus)
|
|
381
|
-
return;
|
|
382
|
-
focusedMount = nextFocus;
|
|
383
|
-
refreshPresenter();
|
|
384
|
-
refreshMenu();
|
|
385
|
-
};
|
|
386
|
-
const registerShellCommands = (commands) => {
|
|
387
|
-
assertLive();
|
|
388
|
-
shellContribution?.dispose();
|
|
389
|
-
const contribution = whistle.contribute({
|
|
390
|
-
sourceId: "shell",
|
|
391
|
-
namespace: "shell",
|
|
392
|
-
commands,
|
|
393
|
-
});
|
|
394
|
-
shellContribution = contribution;
|
|
395
|
-
let active = true;
|
|
396
|
-
return () => {
|
|
397
|
-
if (!active)
|
|
398
|
-
return;
|
|
399
|
-
active = false;
|
|
400
|
-
contribution.dispose();
|
|
401
|
-
if (shellContribution === contribution)
|
|
402
|
-
shellContribution = undefined;
|
|
403
|
-
};
|
|
404
|
-
};
|
|
405
|
-
const registerDirectoryCommands = (rows, run) => {
|
|
406
|
-
assertLive();
|
|
407
|
-
directoryContribution?.dispose();
|
|
408
|
-
const contribution = whistle.contribute({
|
|
409
|
-
sourceId: appDirectorySourceId,
|
|
410
|
-
namespace: "app-directory",
|
|
411
|
-
commands: rows.flatMap(({ surfaceId, appTitle, command }) => {
|
|
412
|
-
const palette = command.projections?.palette;
|
|
413
|
-
if (palette === undefined)
|
|
414
|
-
return [];
|
|
415
|
-
const projected = {
|
|
416
|
-
id: `${encodeURIComponent(surfaceId)}-${encodeURIComponent(command.id)}`,
|
|
417
|
-
title: command.title,
|
|
418
|
-
category: `${appTitle} · ${command.category}`,
|
|
419
|
-
projections: {
|
|
420
|
-
palette: palette.order === undefined ? {} : { order: palette.order },
|
|
421
|
-
},
|
|
422
|
-
handler: () => run(surfaceId, command.id),
|
|
423
|
-
};
|
|
424
|
-
return command.description === undefined
|
|
425
|
-
? [projected]
|
|
426
|
-
: [{ ...projected, description: command.description }];
|
|
427
|
-
}),
|
|
428
|
-
});
|
|
429
|
-
directoryContribution = contribution;
|
|
430
|
-
let active = true;
|
|
431
|
-
return () => {
|
|
432
|
-
if (!active)
|
|
433
|
-
return;
|
|
434
|
-
active = false;
|
|
435
|
-
contribution.dispose();
|
|
436
|
-
if (directoryContribution === contribution)
|
|
437
|
-
directoryContribution = undefined;
|
|
438
|
-
};
|
|
439
|
-
};
|
|
440
|
-
const menu = () => focusedMenu;
|
|
441
|
-
const isActive = (commandId) => {
|
|
442
|
-
const { bindings, palette, slash, help, menu: rows } = activeSnapshot;
|
|
443
|
-
return [bindings, palette, slash, help, rows].some((projection) => projection.some((row) => row.commandId === commandId));
|
|
444
|
-
};
|
|
445
|
-
const execute = async (commandId, input) => {
|
|
446
|
-
if (input.origin === "agent" &&
|
|
447
|
-
!whistle
|
|
448
|
-
.snapshot()
|
|
449
|
-
.agent.some((command) => command.commandId === commandId))
|
|
450
|
-
return { status: "missing" };
|
|
451
|
-
if (input.origin !== "programmatic" &&
|
|
452
|
-
input.origin !== "agent" &&
|
|
453
|
-
!isActive(commandId))
|
|
454
|
-
return { status: "missing" };
|
|
455
|
-
return whistle.execute(commandId, input);
|
|
456
|
-
};
|
|
457
|
-
const dispose = () => {
|
|
458
|
-
if (disposed)
|
|
459
|
-
return;
|
|
460
|
-
disposed = true;
|
|
461
|
-
disposePresenter?.();
|
|
462
|
-
disposePresenter = undefined;
|
|
463
|
-
for (const pane of panes.values())
|
|
464
|
-
pane.dispose();
|
|
465
|
-
for (const state of mounts.values()) {
|
|
466
|
-
state.disposed = true;
|
|
467
|
-
state.contribution?.dispose();
|
|
468
|
-
state.contribution = undefined;
|
|
469
|
-
}
|
|
470
|
-
shellContribution?.dispose();
|
|
471
|
-
shellContribution = undefined;
|
|
472
|
-
directoryContribution?.dispose();
|
|
473
|
-
directoryContribution = undefined;
|
|
474
|
-
mounts.clear();
|
|
475
|
-
focusedMount = null;
|
|
476
|
-
focusedMenu = emptyMenu;
|
|
477
|
-
whistle.close();
|
|
478
|
-
activeSnapshot = whistle.snapshot();
|
|
479
|
-
unsubscribeWhistle();
|
|
480
|
-
listeners.clear();
|
|
481
|
-
};
|
|
482
|
-
return Object.freeze({
|
|
483
|
-
mount,
|
|
484
|
-
mountPane,
|
|
485
|
-
focus,
|
|
486
|
-
registerShellCommands,
|
|
487
|
-
registerDirectoryCommands,
|
|
488
|
-
menu,
|
|
489
|
-
active: () => activeSnapshot,
|
|
490
|
-
execute,
|
|
491
|
-
snapshot: whistle.snapshot,
|
|
492
|
-
subscribe: (listener) => {
|
|
493
|
-
if (disposed)
|
|
494
|
-
return () => undefined;
|
|
495
|
-
listeners.add(listener);
|
|
496
|
-
return () => {
|
|
497
|
-
listeners.delete(listener);
|
|
498
|
-
};
|
|
499
|
-
},
|
|
500
|
-
dispose,
|
|
501
|
-
});
|
|
502
|
-
}
|
package/dist/shell/commands.d.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import type { WhistleCommand } from "@fungi.computer/whistle";
|
|
2
|
-
/** The Back binding, also shown by the shell in window chrome. */
|
|
3
|
-
export declare const backBinding = "<leader> [";
|
|
4
|
-
/** The behavior supplied by either a browser or terminal workspace shell. */
|
|
5
|
-
export type ShellActions = Readonly<{
|
|
6
|
-
/** Show the host-owned App picker. */
|
|
7
|
-
openApp: () => void;
|
|
8
|
-
/** Show the active command and key reference. */
|
|
9
|
-
showKeys: () => void;
|
|
10
|
-
/** Show the focused window command search. */
|
|
11
|
-
showCommandLine: () => void;
|
|
12
|
-
/** Move focus to the previous or next window. */
|
|
13
|
-
focusStep: (step: -1 | 1) => void;
|
|
14
|
-
/** Swap the focused window with its previous or next neighbor. */
|
|
15
|
-
swapStep: (step: -1 | 1) => void;
|
|
16
|
-
/** Toggle the focused window between normal and zoomed presentation. */
|
|
17
|
-
toggleZoom: () => void;
|
|
18
|
-
/** Ask the focused view to go back in its own history. */
|
|
19
|
-
back?: () => void;
|
|
20
|
-
}>;
|
|
21
|
-
/**
|
|
22
|
-
* Shared workspace declarations. Window moves have direct Alt chords and
|
|
23
|
-
* leader keys; global actions live behind the shell-owned leader.
|
|
24
|
-
*/
|
|
25
|
-
export declare function shellCommands(actions: ShellActions): readonly WhistleCommand<never>[];
|
package/dist/shell/commands.js
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
/** The Back binding, also shown by the shell in window chrome. */
|
|
2
|
-
export const backBinding = "<leader> [";
|
|
3
|
-
/**
|
|
4
|
-
* Shared workspace declarations. Window moves have direct Alt chords and
|
|
5
|
-
* leader keys; global actions live behind the shell-owned leader.
|
|
6
|
-
*/
|
|
7
|
-
export function shellCommands(actions) {
|
|
8
|
-
const windowCommand = (id, title, keys, order, run) => ({
|
|
9
|
-
id,
|
|
10
|
-
title,
|
|
11
|
-
category: "Window",
|
|
12
|
-
projections: {
|
|
13
|
-
bindings: { values: keys, order },
|
|
14
|
-
palette: { order: 10 + order },
|
|
15
|
-
help: { order },
|
|
16
|
-
},
|
|
17
|
-
handler: () => {
|
|
18
|
-
run();
|
|
19
|
-
},
|
|
20
|
-
});
|
|
21
|
-
return [
|
|
22
|
-
{
|
|
23
|
-
id: "open-app",
|
|
24
|
-
title: "Open App",
|
|
25
|
-
category: "Apps",
|
|
26
|
-
description: "Show available Apps.",
|
|
27
|
-
projections: {
|
|
28
|
-
bindings: { values: ["<leader> o"], order: 0 },
|
|
29
|
-
palette: { order: 0 },
|
|
30
|
-
},
|
|
31
|
-
handler: () => {
|
|
32
|
-
actions.openApp();
|
|
33
|
-
},
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
id: "show-command-palette",
|
|
37
|
-
title: "Show keys",
|
|
38
|
-
category: "System",
|
|
39
|
-
description: "Show the keys and commands available here.",
|
|
40
|
-
projections: { bindings: { values: ["mod+k"], order: 0 } },
|
|
41
|
-
handler: () => {
|
|
42
|
-
actions.showKeys();
|
|
43
|
-
},
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
id: "command-line",
|
|
47
|
-
title: "Command line",
|
|
48
|
-
category: "System",
|
|
49
|
-
description: "Search the focused window's commands.",
|
|
50
|
-
projections: { bindings: { values: ["<leader> :"], order: 1 } },
|
|
51
|
-
handler: () => {
|
|
52
|
-
actions.showCommandLine();
|
|
53
|
-
},
|
|
54
|
-
},
|
|
55
|
-
windowCommand("focus-previous", "Focus previous window", ["alt+left", "<leader> h"], 2, () => {
|
|
56
|
-
actions.focusStep(-1);
|
|
57
|
-
}),
|
|
58
|
-
windowCommand("focus-next", "Focus next window", ["alt+right", "<leader> l"], 3, () => {
|
|
59
|
-
actions.focusStep(1);
|
|
60
|
-
}),
|
|
61
|
-
windowCommand("swap-previous", "Swap window left", ["alt+shift+left", "<leader> {"], 4, () => {
|
|
62
|
-
actions.swapStep(-1);
|
|
63
|
-
}),
|
|
64
|
-
windowCommand("swap-next", "Swap window right", ["alt+shift+right", "<leader> }"], 5, () => {
|
|
65
|
-
actions.swapStep(1);
|
|
66
|
-
}),
|
|
67
|
-
windowCommand("zoom", "Zoom window", ["alt+enter", "<leader> z"], 6, () => {
|
|
68
|
-
actions.toggleZoom();
|
|
69
|
-
}),
|
|
70
|
-
// Alt+Left focuses the previous window. The leader crosses App iframes;
|
|
71
|
-
// Cmd+[ is the Mac browser Back chord while the shell has focus.
|
|
72
|
-
...(actions.back === undefined
|
|
73
|
-
? []
|
|
74
|
-
: [
|
|
75
|
-
windowCommand("back", "Back", [backBinding, "cmd+["], 7, actions.back),
|
|
76
|
-
]),
|
|
77
|
-
];
|
|
78
|
-
}
|
package/dist/shell/index.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/** Client-side tools for embedding and arranging Apps in a host-owned shell. */
|
|
2
|
-
export * from "./workbench.js";
|
|
3
|
-
export * from "./command-host.js";
|
|
4
|
-
export * from "./keys.js";
|
|
5
|
-
export * from "./commands.js";
|
|
6
|
-
export * from "./window-manager.js";
|
|
7
|
-
export * from "./app-directory.js";
|
|
8
|
-
export { createBrowserActionHandler } from "./browser-actions.js";
|
package/dist/shell/index.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/** Client-side tools for embedding and arranging Apps in a host-owned shell. */
|
|
2
|
-
export * from "./workbench.js";
|
|
3
|
-
export * from "./command-host.js";
|
|
4
|
-
export * from "./keys.js";
|
|
5
|
-
export * from "./commands.js";
|
|
6
|
-
export * from "./window-manager.js";
|
|
7
|
-
export * from "./app-directory.js";
|
|
8
|
-
export { createBrowserActionHandler } from "./browser-actions.js";
|
package/dist/shell/keys.d.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import type { WhistleBindingProjection, WhistleExecutionInput, WhistleExecutionOutcome, WhistleSnapshot } from "@fungi.computer/whistle";
|
|
2
|
-
/** One physical chord parsed from a Whistle binding such as `alt+left`. */
|
|
3
|
-
export type ShellChord = Readonly<{
|
|
4
|
-
key: string;
|
|
5
|
-
alt: boolean;
|
|
6
|
-
ctrl: boolean;
|
|
7
|
-
meta: boolean;
|
|
8
|
-
shift: boolean;
|
|
9
|
-
}>;
|
|
10
|
-
/** Keyboard facts shared by DOM events and terminal adapters. */
|
|
11
|
-
export type KeyEventFacts = Pick<KeyboardEvent, "altKey" | "ctrlKey" | "key" | "metaKey" | "shiftKey">;
|
|
12
|
-
/**
|
|
13
|
-
* Parse one single-chord binding. Sequences (including `<leader> x`) and
|
|
14
|
-
* unknown modifiers return `null`; they are never matched as one chord.
|
|
15
|
-
*/
|
|
16
|
-
export declare function parseChord(binding: string, mac: boolean): ShellChord | null;
|
|
17
|
-
/** Whether one key event is exactly this chord. */
|
|
18
|
-
export declare function chordMatches(event: KeyEventFacts, chord: ShellChord): boolean;
|
|
19
|
-
/** One key offered after the leader chord, with the command it runs. */
|
|
20
|
-
export type LeaderKey = WhistleBindingProjection & Readonly<{
|
|
21
|
-
key: string;
|
|
22
|
-
}>;
|
|
23
|
-
/** The `<leader> x` rows of the active view, first binding per key. */
|
|
24
|
-
export declare function leaderKeys(active: WhistleSnapshot): readonly LeaderKey[];
|
|
25
|
-
/** Whether one key event (after the leader) selects this leader key. */
|
|
26
|
-
export declare function leaderKeyMatches(event: Pick<KeyboardEvent, "altKey" | "ctrlKey" | "key" | "metaKey">, key: string): boolean;
|
|
27
|
-
/** The shell host operations the key dispatcher reads. */
|
|
28
|
-
export type ShellKeyHost = Readonly<{
|
|
29
|
-
/** Read the commands currently available to the focused view. */
|
|
30
|
-
active: () => WhistleSnapshot;
|
|
31
|
-
/** Observe command changes; call the returned disposer to stop listening. */
|
|
32
|
-
subscribe: (listener: () => void) => () => void;
|
|
33
|
-
/** Run a command through the host with the original input origin. */
|
|
34
|
-
execute: (commandId: string, input: WhistleExecutionInput) => Promise<WhistleExecutionOutcome>;
|
|
35
|
-
}>;
|
|
36
|
-
/**
|
|
37
|
-
* Dispatch the active view's single-chord bindings from the shell document.
|
|
38
|
-
* Text entry is a mode: while an input is focused only Ctrl/Cmd chords fire,
|
|
39
|
-
* so Alt-arrows keep their word-navigation meaning.
|
|
40
|
-
*/
|
|
41
|
-
export declare function installShellKeys(root: HTMLElement, host: ShellKeyHost, mac: boolean): () => void;
|