@markii/host 0.17.0-next.2 → 0.17.0-next.4
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 +10 -2
- package/dist/browser-worker.classic.js +640 -0
- package/dist/browser-worker.js +40 -40
- package/dist/browser.d.ts +7 -3
- package/dist/browser.js +16 -4
- package/dist/conformance/host/05-export-html-pack-directive/expected.json +2 -0
- package/dist/conformance/host/06-install-pack-then-render/expected.json +6 -1
- package/dist/conformance/host/README.md +4 -2
- package/dist/export/note-export.d.ts +1 -1
- package/dist/host/adapter.d.ts +22 -25
- package/dist/host/conformance-runner.d.ts +1 -1
- package/dist/host/conformance-runner.js +21 -11
- package/dist/host/create-host.d.ts +29 -11
- package/dist/host/create-host.js +34 -23
- package/dist/host/editor-behavior.d.ts +2 -6
- package/dist/host/editor-behavior.js +5 -9
- package/dist/host/export-behavior.d.ts +6 -7
- package/dist/host/export-behavior.js +1 -1
- package/dist/host/labels.d.ts +5 -15
- package/dist/host/labels.js +8 -22
- package/dist/host/pack-archive.d.ts +4 -10
- package/dist/host/pack-archive.js +12 -21
- package/dist/host/pack-install.d.ts +11 -23
- package/dist/host/pack-install.js +26 -23
- package/dist/host/pack-load.d.ts +1 -2
- package/dist/host/pack-trust-behavior.js +1 -1
- package/dist/host/refresh-interval.d.ts +1 -3
- package/dist/host/refresh-interval.js +1 -3
- package/dist/host/run-behavior.d.ts +3 -4
- package/dist/host/run-behavior.js +23 -2
- package/dist/host/script-execution.d.ts +1 -1
- package/dist/html-engine.js +4 -4
- package/dist/index.d.ts +15 -80
- package/dist/index.js +18 -63
- package/dist/internal.d.ts +30 -0
- package/dist/internal.js +31 -0
- package/dist/node-fs.d.ts +0 -3
- package/dist/node-fs.js +1 -21
- package/dist/node-worker.d.ts +8 -0
- package/dist/node-worker.js +20678 -0
- package/dist/node.d.ts +3 -3
- package/dist/node.js +5 -4
- package/dist/packs/discover.d.ts +2 -0
- package/dist/packs/discover.js +2 -1
- package/dist/packs/pack-diagnostics.d.ts +6 -8
- package/dist/packs/pack-diagnostics.js +6 -8
- package/dist/packs/pack-paths.js +1 -2
- package/dist/packs/pack-render-registry.d.ts +9 -10
- package/dist/run/browser-isolate.d.ts +5 -5
- package/dist/run/browser-isolate.js +5 -1
- package/dist/run/isolate.d.ts +3 -1
- package/dist/run/net-bridge.d.ts +5 -5
- package/dist/run/net-bridge.js +7 -5
- package/dist/run/net-pinning.d.ts +2 -0
- package/dist/run/net-pinning.js +17 -3
- package/dist/run/net-provider.d.ts +3 -1
- package/dist/run/net-provider.js +40 -15
- package/dist/run/net-refusal.d.ts +4 -0
- package/dist/run/net-refusal.js +24 -0
- package/dist/run/node-isolate.d.ts +13 -21
- package/dist/run/node-isolate.js +31 -80
- package/dist/run/run-flow.d.ts +1 -2
- package/dist/run/run-host.d.ts +3 -3
- package/dist/run/worker-entry-browser.d.ts +24 -4
- package/dist/run/worker-entry-browser.js +99 -4
- package/dist/run/worker-entry.js +2 -0
- package/package.json +31 -12
package/dist/host/labels.d.ts
CHANGED
|
@@ -1,21 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* collapses the survey's near-identical wording pairs (`tmp/W11-survey.md`,
|
|
7
|
-
* section A4) into one template.
|
|
2
|
+
* The shared wording templates a host's shared behaviors interpolate
|
|
3
|
+
* `HostLabels` into live beside each behavior. This module holds the one
|
|
4
|
+
* label sentence that has no per-host noun. Each app owns its own
|
|
5
|
+
* `HostLabels` record and passes it as `HostAdapter.labels`.
|
|
8
6
|
*
|
|
9
|
-
* Pure and dependency-free
|
|
10
|
-
* `../index.ts` so VS Code's Node-free webview bundle can read it too.
|
|
7
|
+
* Pure and dependency-free.
|
|
11
8
|
*/
|
|
12
|
-
import type { HostLabels } from './adapter.js';
|
|
13
|
-
/** The VS Code extension's labels, taken from its current wording (`apps/vscode/src/script-execution.ts`, `apps/vscode/src/extension.ts`'s output channel). */
|
|
14
|
-
export declare const VSCODE_LABELS: HostLabels;
|
|
15
|
-
/** The Obsidian plugin's labels, taken from its current wording (`apps/obsidian/src/script-execution.ts`, docs/integration.md's host checklist). */
|
|
16
|
-
export declare const OBSIDIAN_LABELS: HostLabels;
|
|
17
|
-
/** The `markii` command line tool's labels: it has no persistent preview panel, and its diagnostics surface is stderr, gated behind `--verbose` for anything short of a failure (`apps/cli/src/main.ts`). */
|
|
18
|
-
export declare const CLI_LABELS: HostLabels;
|
|
19
9
|
/**
|
|
20
10
|
* The quiet marker a rendered note shows when its `uses:` list names packs
|
|
21
11
|
* this host has not installed (docs/packs.md). One sentence for every host;
|
package/dist/host/labels.js
CHANGED
|
@@ -1,25 +1,11 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
/** The Obsidian plugin's labels, taken from its current wording (`apps/obsidian/src/script-execution.ts`, docs/integration.md's host checklist). */
|
|
10
|
-
export const OBSIDIAN_LABELS = {
|
|
11
|
-
appNoun: 'plugin',
|
|
12
|
-
previewNoun: 'the Markii preview',
|
|
13
|
-
diagnosticsSurface: 'the Markii diagnostics',
|
|
14
|
-
deviceNoun: 'this device',
|
|
15
|
-
};
|
|
16
|
-
/** The `markii` command line tool's labels: it has no persistent preview panel, and its diagnostics surface is stderr, gated behind `--verbose` for anything short of a failure (`apps/cli/src/main.ts`). */
|
|
17
|
-
export const CLI_LABELS = {
|
|
18
|
-
appNoun: 'command line tool',
|
|
19
|
-
previewNoun: 'the rendered note',
|
|
20
|
-
diagnosticsSurface: 'stderr',
|
|
21
|
-
deviceNoun: 'this device',
|
|
22
|
-
};
|
|
1
|
+
/**
|
|
2
|
+
* The shared wording templates a host's shared behaviors interpolate
|
|
3
|
+
* `HostLabels` into live beside each behavior. This module holds the one
|
|
4
|
+
* label sentence that has no per-host noun. Each app owns its own
|
|
5
|
+
* `HostLabels` record and passes it as `HostAdapter.labels`.
|
|
6
|
+
*
|
|
7
|
+
* Pure and dependency-free.
|
|
8
|
+
*/
|
|
23
9
|
/**
|
|
24
10
|
* The quiet marker a rendered note shows when its `uses:` list names packs
|
|
25
11
|
* this host has not installed (docs/packs.md). One sentence for every host;
|
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
import type { PackArchiveContents, PackArchiveError } from '@markii/pack';
|
|
2
2
|
/** One line describing why `openPackArchive` rejected an archive, for a host's install-diagnostics wording. Passes `kind: 'zip'`'s and `kind: 'missing-entry'`'s message through verbatim (already specific); summarizes a manifest failure plainly. */
|
|
3
3
|
export declare function describeArchiveError(error: PackArchiveError): string;
|
|
4
|
-
/**
|
|
5
|
-
export
|
|
6
|
-
/** Removes `absolutePath` and everything under it, or resolves quietly if it does not exist. Never rejects: a directory that fails to clear is treated the same as a fresh one, and the write that follows fails loudly on its own if the path is genuinely unusable. */
|
|
7
|
-
readonly removeDirectory: (absolutePath: string) => Promise<void>;
|
|
8
|
-
/** Creates a directory and any missing parents. May reject on a genuine I/O failure. */
|
|
9
|
-
readonly makeDirectory: (absolutePath: string) => Promise<void>;
|
|
10
|
-
readonly writeFile: (absolutePath: string, bytes: Uint8Array) => Promise<void>;
|
|
11
|
-
}
|
|
4
|
+
/** Writes one file and creates its missing parent folders: `HostAdapter.writeFile`. */
|
|
5
|
+
export type ArchiveFileWriter = (absolutePath: string, bytes: Uint8Array) => Promise<void>;
|
|
12
6
|
/**
|
|
13
7
|
* Writes a validated archive's contents into `destinationDir`: `pack.json`
|
|
14
8
|
* (the parsed manifest, re-serialized: `openPackArchive` keeps only the
|
|
@@ -17,7 +11,7 @@ export interface ArchiveExtractFs {
|
|
|
17
11
|
* copy), `webview.js`, `webview.css` and `terminal.js` when the archive has them, and
|
|
18
12
|
* `scripts/*` when it ships any. Does NOT clear `destinationDir` first;
|
|
19
13
|
* a caller that needs a clean re-extract (a reinstall replacing an
|
|
20
|
-
* existing pack)
|
|
14
|
+
* existing pack) removes the folder itself before this.
|
|
21
15
|
*
|
|
22
16
|
* PATH JAIL: `@markii/pack`'s `openPackArchive` has already rejected any
|
|
23
17
|
* entry whose name escapes the archive (`../`, an absolute path) or
|
|
@@ -27,4 +21,4 @@ export interface ArchiveExtractFs {
|
|
|
27
21
|
* `webview.css`, or a `scripts/`-relative Lua module name), never from
|
|
28
22
|
* anything read back out of the zip's raw entry names.
|
|
29
23
|
*/
|
|
30
|
-
export declare function writeArchiveContents(archive: PackArchiveContents, destinationDir: string,
|
|
24
|
+
export declare function writeArchiveContents(archive: PackArchiveContents, destinationDir: string, writeFile: ArchiveFileWriter): Promise<void>;
|
|
@@ -1,24 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `.mkp` pack archive handling, merged from `apps/vscode/src/packs/archive-packs.ts`
|
|
3
|
-
* and `apps/obsidian/src/packs/archive-packs.ts
|
|
4
|
-
*
|
|
5
|
-
* earlier, unverified guess) and found them functionally byte-identical:
|
|
6
|
-
* the same three exports (`describeArchiveError`, `writeArchiveContents`,
|
|
7
|
-
* `ArchiveExtractFs`), the same implementation, the same path-jail
|
|
8
|
-
* reasoning. They differed only in doc-comment wording (which host's
|
|
9
|
-
* install command they described) and one em dash in a comment, which
|
|
10
|
-
* carries no behavior. See `tmp/W11-phase1b.md` for the exact diff output.
|
|
3
|
+
* and `apps/obsidian/src/packs/archive-packs.ts`. It exports
|
|
4
|
+
* `describeArchiveError`, `writeArchiveContents` and `ArchiveFileWriter`.
|
|
11
5
|
*
|
|
12
6
|
* This module bridges `@markii/pack`'s in-memory archive reader
|
|
13
7
|
* (`openPackArchive`, never modified here) into the write a pack install
|
|
14
8
|
* needs: extracting a validated archive's contents onto disk, under
|
|
15
9
|
* whichever install root the calling host names (`HostPackSource.installRoot`).
|
|
16
10
|
*
|
|
17
|
-
* Environment-free
|
|
18
|
-
*
|
|
19
|
-
* and is exported from `@markii/host/node`.
|
|
11
|
+
* Environment-free: the write goes through the host adapter's `writeFile`,
|
|
12
|
+
* which creates any missing parent folder.
|
|
20
13
|
*/
|
|
21
|
-
import {
|
|
14
|
+
import { joinPath } from '../path-util.js';
|
|
22
15
|
/** One line describing why `openPackArchive` rejected an archive, for a host's install-diagnostics wording. Passes `kind: 'zip'`'s and `kind: 'missing-entry'`'s message through verbatim (already specific); summarizes a manifest failure plainly. */
|
|
23
16
|
export function describeArchiveError(error) {
|
|
24
17
|
if (error.kind === 'zip')
|
|
@@ -35,7 +28,7 @@ export function describeArchiveError(error) {
|
|
|
35
28
|
* copy), `webview.js`, `webview.css` and `terminal.js` when the archive has them, and
|
|
36
29
|
* `scripts/*` when it ships any. Does NOT clear `destinationDir` first;
|
|
37
30
|
* a caller that needs a clean re-extract (a reinstall replacing an
|
|
38
|
-
* existing pack)
|
|
31
|
+
* existing pack) removes the folder itself before this.
|
|
39
32
|
*
|
|
40
33
|
* PATH JAIL: `@markii/pack`'s `openPackArchive` has already rejected any
|
|
41
34
|
* entry whose name escapes the archive (`../`, an absolute path) or
|
|
@@ -45,24 +38,22 @@ export function describeArchiveError(error) {
|
|
|
45
38
|
* `webview.css`, or a `scripts/`-relative Lua module name), never from
|
|
46
39
|
* anything read back out of the zip's raw entry names.
|
|
47
40
|
*/
|
|
48
|
-
export async function writeArchiveContents(archive, destinationDir,
|
|
49
|
-
await fs.makeDirectory(destinationDir);
|
|
41
|
+
export async function writeArchiveContents(archive, destinationDir, writeFile) {
|
|
50
42
|
const encoder = new TextEncoder();
|
|
51
|
-
await
|
|
52
|
-
await
|
|
43
|
+
await writeFile(joinPath(destinationDir, 'pack.json'), encoder.encode(JSON.stringify(archive.manifest, null, 2) + '\n'));
|
|
44
|
+
await writeFile(joinPath(destinationDir, 'webview.js'), archive.scriptBytes);
|
|
53
45
|
if (archive.stylesheetBytes !== undefined) {
|
|
54
|
-
await
|
|
46
|
+
await writeFile(joinPath(destinationDir, 'webview.css'), archive.stylesheetBytes);
|
|
55
47
|
}
|
|
56
48
|
if (archive.terminalScriptBytes !== undefined) {
|
|
57
|
-
await
|
|
49
|
+
await writeFile(joinPath(destinationDir, 'terminal.js'), archive.terminalScriptBytes);
|
|
58
50
|
}
|
|
59
51
|
const moduleNames = Object.keys(archive.scriptModules);
|
|
60
52
|
if (moduleNames.length > 0) {
|
|
61
53
|
const scriptsDir = joinPath(destinationDir, 'scripts');
|
|
62
54
|
for (const name of moduleNames) {
|
|
63
55
|
const target = joinPath(scriptsDir, name);
|
|
64
|
-
await
|
|
65
|
-
await fs.writeFile(target, archive.scriptModules[name]);
|
|
56
|
+
await writeFile(target, archive.scriptModules[name]);
|
|
66
57
|
}
|
|
67
58
|
}
|
|
68
59
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { ArchiveExtractFs } from './pack-archive.js';
|
|
2
1
|
import type { HostAdapter, HostLabels } from './adapter.js';
|
|
2
|
+
import type { InstallPackOutcome as HostInstallPackOutcome } from './create-host.js';
|
|
3
3
|
/** Whether a directory already exists under the install root, injected so this module needs no real disk to test. */
|
|
4
4
|
export type PackDirectoryExists = (absolutePath: string) => Promise<boolean>;
|
|
5
5
|
export interface InstallPackFromArchiveOptions {
|
|
@@ -9,7 +9,8 @@ export interface InstallPackFromArchiveOptions {
|
|
|
9
9
|
/** This host's own pack-install directory (`HostPackSource.installRoot()`). Each installed pack gets a subdirectory named by its namespace, since two packs can never share one (docs/packs.md's collision rule), which makes "is this namespace already installed" a plain directory check. */
|
|
10
10
|
readonly installRoot: string;
|
|
11
11
|
readonly exists: PackDirectoryExists;
|
|
12
|
-
|
|
12
|
+
/** Removes the installed folder before a replacing install (`HostPackSource.removeFolder`). Called only when the namespace is already installed. */
|
|
13
|
+
readonly removeFolder: (absolutePath: string) => Promise<void>;
|
|
13
14
|
/**
|
|
14
15
|
* Namespaces this install may never claim (`HostPackSource.reservedNamespaces()`).
|
|
15
16
|
* Empty for a host with no reserved set (VS Code). Checked before the
|
|
@@ -17,22 +18,10 @@ export interface InstallPackFromArchiveOptions {
|
|
|
17
18
|
*/
|
|
18
19
|
readonly reservedNamespaces: ReadonlySet<string>;
|
|
19
20
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
readonly
|
|
23
|
-
|
|
24
|
-
readonly replaced: boolean;
|
|
25
|
-
} | {
|
|
26
|
-
readonly kind: 'declined';
|
|
27
|
-
readonly step: 'consent' | 'replace';
|
|
28
|
-
readonly packName: string;
|
|
29
|
-
} | {
|
|
30
|
-
readonly kind: 'reserved';
|
|
31
|
-
readonly packName: string;
|
|
32
|
-
} | {
|
|
33
|
-
readonly kind: 'rejected';
|
|
34
|
-
readonly reason: string;
|
|
35
|
-
};
|
|
21
|
+
/** What one install attempt produced, in the shape `createMarkiiHost(...).installPack` returns (minus `unsupported`, which only the host behavior can say). */
|
|
22
|
+
export type InstallAttemptOutcome = Exclude<HostInstallPackOutcome, {
|
|
23
|
+
readonly kind: 'unsupported';
|
|
24
|
+
}>;
|
|
36
25
|
/**
|
|
37
26
|
* Never throws: a validation failure, a declined prompt, or a write
|
|
38
27
|
* failure all come back as a structured outcome. Order: validate the
|
|
@@ -47,7 +36,7 @@ export type InstallPackOutcome = {
|
|
|
47
36
|
* a host that can only show a non-blocking surface must deny rather than
|
|
48
37
|
* assume yes.
|
|
49
38
|
*/
|
|
50
|
-
export declare function installPackFromArchive(adapter: HostAdapter, options: InstallPackFromArchiveOptions): Promise<
|
|
39
|
+
export declare function installPackFromArchive(adapter: HostAdapter, options: InstallPackFromArchiveOptions): Promise<InstallAttemptOutcome>;
|
|
51
40
|
/**
|
|
52
41
|
* The consent prompt's wording (AGENTS.md's product principles: "clean is
|
|
53
42
|
* not silent," and a consent step must say plainly what it authorizes).
|
|
@@ -67,8 +56,7 @@ export declare function installConsentMessage(packName: string, labels: HostLabe
|
|
|
67
56
|
/**
|
|
68
57
|
* The collision confirmation's wording: a namespace already installed,
|
|
69
58
|
* asked before replacing it. CANONICAL WORDING: "removes" (VS Code's prior
|
|
70
|
-
* wording) over Obsidian's prior "deletes"
|
|
71
|
-
* before/after table for the exact strings this replaces.
|
|
59
|
+
* wording) over Obsidian's prior "deletes".
|
|
72
60
|
*/
|
|
73
61
|
export declare function installReplaceConfirmMessage(packName: string): string;
|
|
74
62
|
/**
|
|
@@ -83,6 +71,6 @@ export declare function installReplaceConfirmMessage(packName: string): string;
|
|
|
83
71
|
* `markii.packs` before anything loads it), so it doesn't. Defaults to
|
|
84
72
|
* `false`.
|
|
85
73
|
*/
|
|
86
|
-
export declare function installPackMessage(outcome:
|
|
74
|
+
export declare function installPackMessage(outcome: HostInstallPackOutcome, archivePath: string, labels: HostLabels, reloadsAutomatically?: boolean): string;
|
|
87
75
|
/** The full diagnostics-surface detail for one install attempt (AGENTS.md's "clean is not silent": the other of a failure's two homes). */
|
|
88
|
-
export declare function installPackDiagnosticLines(outcome:
|
|
76
|
+
export declare function installPackDiagnosticLines(outcome: InstallAttemptOutcome, archivePath: string): string[];
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The `.mkp` pack-install decision logic, merged from
|
|
3
3
|
* `apps/vscode/src/packs/install-pack.ts` and
|
|
4
|
-
* `apps/obsidian/src/packs/install-pack.ts
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* Obsidian refuses a bundled-namespace archive before the consent prompt
|
|
8
|
-
* and VS Code has no such concept).
|
|
4
|
+
* `apps/obsidian/src/packs/install-pack.ts`. Obsidian refuses a
|
|
5
|
+
* bundled-namespace archive before the consent prompt and VS Code has no
|
|
6
|
+
* such concept.
|
|
9
7
|
*
|
|
10
8
|
* `reservedNamespaces` generalizes Obsidian's `bundledNamespaces`: it
|
|
11
9
|
* defaults to empty, so VS Code's behavior is byte-identical to before
|
|
@@ -41,7 +39,7 @@ function describeThrown(err) {
|
|
|
41
39
|
* assume yes.
|
|
42
40
|
*/
|
|
43
41
|
export async function installPackFromArchive(adapter, options) {
|
|
44
|
-
const { archiveBytes, archivePath, installRoot, exists,
|
|
42
|
+
const { archiveBytes, archivePath, installRoot, exists, removeFolder, reservedNamespaces, } = options;
|
|
45
43
|
const opened = await openPackArchive(archiveBytes);
|
|
46
44
|
if (!opened.ok) {
|
|
47
45
|
return {
|
|
@@ -51,7 +49,7 @@ export async function installPackFromArchive(adapter, options) {
|
|
|
51
49
|
}
|
|
52
50
|
const packName = opened.archive.manifest.name;
|
|
53
51
|
if (reservedNamespaces.has(packName)) {
|
|
54
|
-
return { kind: 'reserved', packName };
|
|
52
|
+
return { kind: 'reserved', namespace: packName };
|
|
55
53
|
}
|
|
56
54
|
let consented;
|
|
57
55
|
try {
|
|
@@ -67,7 +65,7 @@ export async function installPackFromArchive(adapter, options) {
|
|
|
67
65
|
return { kind: 'rejected', reason: describeThrown(err) };
|
|
68
66
|
}
|
|
69
67
|
if (!consented) {
|
|
70
|
-
return { kind: 'declined', step: 'consent', packName };
|
|
68
|
+
return { kind: 'declined', step: 'consent', namespace: packName };
|
|
71
69
|
}
|
|
72
70
|
const targetDir = joinPath(installRoot, packName);
|
|
73
71
|
let alreadyInstalled;
|
|
@@ -93,13 +91,14 @@ export async function installPackFromArchive(adapter, options) {
|
|
|
93
91
|
return { kind: 'rejected', reason: describeThrown(err) };
|
|
94
92
|
}
|
|
95
93
|
if (!proceed) {
|
|
96
|
-
return { kind: 'declined', step: 'replace', packName };
|
|
94
|
+
return { kind: 'declined', step: 'replace', namespace: packName };
|
|
97
95
|
}
|
|
98
96
|
replaced = true;
|
|
99
97
|
}
|
|
100
98
|
try {
|
|
101
|
-
|
|
102
|
-
|
|
99
|
+
if (alreadyInstalled)
|
|
100
|
+
await removeFolder(targetDir);
|
|
101
|
+
await writeArchiveContents(opened.archive, targetDir, (path, bytes) => adapter.writeFile(path, bytes));
|
|
103
102
|
}
|
|
104
103
|
catch (err) {
|
|
105
104
|
return {
|
|
@@ -108,7 +107,12 @@ export async function installPackFromArchive(adapter, options) {
|
|
|
108
107
|
};
|
|
109
108
|
}
|
|
110
109
|
await trustInstalledPack(adapter, packName, targetDir);
|
|
111
|
-
return {
|
|
110
|
+
return {
|
|
111
|
+
kind: 'installed',
|
|
112
|
+
namespace: packName,
|
|
113
|
+
installedDir: targetDir,
|
|
114
|
+
replaced,
|
|
115
|
+
};
|
|
112
116
|
}
|
|
113
117
|
/**
|
|
114
118
|
* The consent prompt's wording (AGENTS.md's product principles: "clean is
|
|
@@ -131,8 +135,7 @@ export function installConsentMessage(packName, labels) {
|
|
|
131
135
|
/**
|
|
132
136
|
* The collision confirmation's wording: a namespace already installed,
|
|
133
137
|
* asked before replacing it. CANONICAL WORDING: "removes" (VS Code's prior
|
|
134
|
-
* wording) over Obsidian's prior "deletes"
|
|
135
|
-
* before/after table for the exact strings this replaces.
|
|
138
|
+
* wording) over Obsidian's prior "deletes".
|
|
136
139
|
*/
|
|
137
140
|
export function installReplaceConfirmMessage(packName) {
|
|
138
141
|
return `A pack named "${packName}" is already installed. Replacing it removes the installed copy and cannot be undone.`;
|
|
@@ -150,21 +153,21 @@ export function installReplaceConfirmMessage(packName) {
|
|
|
150
153
|
* `false`.
|
|
151
154
|
*/
|
|
152
155
|
export function installPackMessage(outcome, archivePath, labels, reloadsAutomatically = false) {
|
|
153
|
-
if (outcome.kind === 'rejected') {
|
|
156
|
+
if (outcome.kind === 'rejected' || outcome.kind === 'unsupported') {
|
|
154
157
|
return `Markii: could not install a pack from "${archivePath}". Open ${labels.diagnosticsSurface} for details.`;
|
|
155
158
|
}
|
|
156
159
|
if (outcome.kind === 'reserved') {
|
|
157
|
-
return `Markii: "${outcome.
|
|
160
|
+
return `Markii: "${outcome.namespace}" is built in and cannot be installed. Nothing was installed.`;
|
|
158
161
|
}
|
|
159
162
|
if (outcome.kind === 'declined') {
|
|
160
163
|
return outcome.step === 'consent'
|
|
161
|
-
? `Markii: install of "${outcome.
|
|
162
|
-
: `Markii: install of "${outcome.
|
|
164
|
+
? `Markii: install of "${outcome.namespace}" cancelled. Nothing was installed.`
|
|
165
|
+
: `Markii: install of "${outcome.namespace}" cancelled. The existing pack was kept.`;
|
|
163
166
|
}
|
|
164
167
|
const reloadSuffix = reloadsAutomatically ? ' Markii packs reloaded.' : '';
|
|
165
168
|
return outcome.replaced
|
|
166
|
-
? `Markii: reinstalled pack "${outcome.
|
|
167
|
-
: `Markii: installed pack "${outcome.
|
|
169
|
+
? `Markii: reinstalled pack "${outcome.namespace}".${reloadSuffix}`
|
|
170
|
+
: `Markii: installed pack "${outcome.namespace}".${reloadSuffix}`;
|
|
168
171
|
}
|
|
169
172
|
/** The full diagnostics-surface detail for one install attempt (AGENTS.md's "clean is not silent": the other of a failure's two homes). */
|
|
170
173
|
export function installPackDiagnosticLines(outcome, archivePath) {
|
|
@@ -175,15 +178,15 @@ export function installPackDiagnosticLines(outcome, archivePath) {
|
|
|
175
178
|
}
|
|
176
179
|
if (outcome.kind === 'reserved') {
|
|
177
180
|
return [
|
|
178
|
-
`Install pack from file refused "${archivePath}": pack "${outcome.
|
|
181
|
+
`Install pack from file refused "${archivePath}": pack "${outcome.namespace}" is a reserved namespace and cannot be installed.`,
|
|
179
182
|
];
|
|
180
183
|
}
|
|
181
184
|
if (outcome.kind === 'declined') {
|
|
182
185
|
return [
|
|
183
|
-
`Install pack from file cancelled for "${archivePath}" (pack "${outcome.
|
|
186
|
+
`Install pack from file cancelled for "${archivePath}" (pack "${outcome.namespace}") at the ${outcome.step} step; nothing was installed.`,
|
|
184
187
|
];
|
|
185
188
|
}
|
|
186
189
|
return [
|
|
187
|
-
`Install pack from file installed pack "${outcome.
|
|
190
|
+
`Install pack from file installed pack "${outcome.namespace}" from "${archivePath}" to ${outcome.installedDir}${outcome.replaced ? ' (replacing the previous install)' : ''}.`,
|
|
188
191
|
];
|
|
189
192
|
}
|
package/dist/host/pack-load.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The shared discovery path behind `loadPacks`, merged from
|
|
3
3
|
* `apps/vscode/src/packs/discover-configured-packs.ts` and
|
|
4
|
-
* `apps/obsidian/src/packs/discover-configured-packs.ts`
|
|
5
|
-
* A3) plus the discovery-and-namespace-collection half both apps'
|
|
4
|
+
* `apps/obsidian/src/packs/discover-configured-packs.ts` plus the discovery-and-namespace-collection half both apps'
|
|
6
5
|
* `packs/pack-context.ts` also duplicate on top of it.
|
|
7
6
|
*
|
|
8
7
|
* Pack POLICY — which folders are even candidates before any content is
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* already asked), enabling a present folder asks the same prompt, and
|
|
13
13
|
* disabling or removing withdraws the entry.
|
|
14
14
|
*
|
|
15
|
-
* A host that declares `trust: 'none'`
|
|
15
|
+
* A host that declares `trust: 'none'` trusts every
|
|
16
16
|
* folder its own policy authorizes, and every function here is inert for
|
|
17
17
|
* it. Neutral on purpose: only the adapter's file and state primitives
|
|
18
18
|
* are used.
|
|
@@ -3,9 +3,7 @@
|
|
|
3
3
|
* merged from `apps/vscode/src/refresh-interval.ts` (the input-box
|
|
4
4
|
* parse/validate half) and `apps/obsidian/src/local-settings.ts`'s
|
|
5
5
|
* `refreshIntervalMsFromSeconds`/`MIN_REFRESH_INTERVAL_SECONDS` (the
|
|
6
|
-
* read-side clamp half)
|
|
7
|
-
* verbatim, with Obsidian's own comment noting it mirrors VS Code's, and
|
|
8
|
-
* the clamp-not-reject policy was duplicated as both prose and behavior.
|
|
6
|
+
* read-side clamp half).
|
|
9
7
|
*
|
|
10
8
|
* The policy: a positive value under `MIN_REFRESH_INTERVAL_SECONDS` is
|
|
11
9
|
* still ACCEPTED as typed (a host's own settings UI must not silently
|
|
@@ -3,9 +3,7 @@
|
|
|
3
3
|
* merged from `apps/vscode/src/refresh-interval.ts` (the input-box
|
|
4
4
|
* parse/validate half) and `apps/obsidian/src/local-settings.ts`'s
|
|
5
5
|
* `refreshIntervalMsFromSeconds`/`MIN_REFRESH_INTERVAL_SECONDS` (the
|
|
6
|
-
* read-side clamp half)
|
|
7
|
-
* verbatim, with Obsidian's own comment noting it mirrors VS Code's, and
|
|
8
|
-
* the clamp-not-reject policy was duplicated as both prose and behavior.
|
|
6
|
+
* read-side clamp half).
|
|
9
7
|
*
|
|
10
8
|
* The policy: a positive value under `MIN_REFRESH_INTERVAL_SECONDS` is
|
|
11
9
|
* still ACCEPTED as typed (a host's own settings UI must not silently
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The `run` behavior's host-shaped seams, built from a `HostAdapter`:
|
|
3
|
-
*
|
|
4
|
-
* times over.
|
|
3
|
+
* the grant prompts and the isolate spawn live here once for every host.
|
|
5
4
|
*
|
|
6
5
|
* A1: `apps/vscode/src/preview-panel.ts`'s `promptHostAdapter` /
|
|
7
6
|
* `promptUnknownHostsAdapter` / `promptManyHostsAdapter`,
|
|
@@ -24,7 +23,7 @@
|
|
|
24
23
|
* `runOnce` (the existing, already-shared grant-flow-plus-spawn
|
|
25
24
|
* orchestration) and writes the `RunTrace` through `adapter.now()` rather
|
|
26
25
|
* than `Date.now()`, so a fixed clock in a test fake makes the trace
|
|
27
|
-
* byte-stable
|
|
26
|
+
* byte-stable.
|
|
28
27
|
*/
|
|
29
28
|
import type { RunTrigger } from '@markii/runtime';
|
|
30
29
|
import { type PromptHost, type PromptManyHosts, type PromptUnknownHosts } from '../run/grant-flow.js';
|
|
@@ -54,7 +53,7 @@ export declare function promptsFromAdapter(adapter: HostAdapter): {
|
|
|
54
53
|
};
|
|
55
54
|
/**
|
|
56
55
|
* The one `spawnRun` adapter every Node host (`apps/vscode`, `apps/cli`)
|
|
57
|
-
*
|
|
56
|
+
* needs, plus the browser-isolate path Obsidian's
|
|
58
57
|
* own `spawnRun` wrapper needed. Dispatches on `HostIsolate`'s
|
|
59
58
|
* discriminated union: a `'node'` host supplies only a worker path; a
|
|
60
59
|
* `'browser'` host supplies an async, disposable `IsolateSpawner` factory,
|
|
@@ -63,9 +63,23 @@ function noIsolateResult(cacheSnapshot) {
|
|
|
63
63
|
cacheSnapshot,
|
|
64
64
|
};
|
|
65
65
|
}
|
|
66
|
+
/** A synthetic `RunResult` for a node isolate whose worker file cannot be located. The run never throws. */
|
|
67
|
+
function workerMissingResult(cacheSnapshot, error) {
|
|
68
|
+
return {
|
|
69
|
+
values: {},
|
|
70
|
+
failures: [
|
|
71
|
+
{
|
|
72
|
+
name: '<document>',
|
|
73
|
+
message: `the script worker could not be located: ${error instanceof Error ? error.message : String(error)}`,
|
|
74
|
+
kind: 'capability-denied',
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
cacheSnapshot,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
66
80
|
/**
|
|
67
81
|
* The one `spawnRun` adapter every Node host (`apps/vscode`, `apps/cli`)
|
|
68
|
-
*
|
|
82
|
+
* needs, plus the browser-isolate path Obsidian's
|
|
69
83
|
* own `spawnRun` wrapper needed. Dispatches on `HostIsolate`'s
|
|
70
84
|
* discriminated union: a `'node'` host supplies only a worker path; a
|
|
71
85
|
* `'browser'` host supplies an async, disposable `IsolateSpawner` factory,
|
|
@@ -75,9 +89,16 @@ export async function spawnRunViaAdapter(isolate, options) {
|
|
|
75
89
|
if (!isolate)
|
|
76
90
|
return noIsolateResult(options.cacheSnapshot);
|
|
77
91
|
if (isolate.kind === 'node') {
|
|
92
|
+
let workerPath;
|
|
93
|
+
try {
|
|
94
|
+
workerPath = isolate.workerPath();
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
return workerMissingResult(options.cacheSnapshot, error);
|
|
98
|
+
}
|
|
78
99
|
return spawnRunHost({
|
|
79
100
|
...options,
|
|
80
|
-
workerPath
|
|
101
|
+
workerPath,
|
|
81
102
|
spawnIsolate: isolate.spawnIsolate,
|
|
82
103
|
});
|
|
83
104
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The device-level script-execution switch and every sentence it can
|
|
3
3
|
* produce, merged from `apps/vscode/src/script-execution.ts` and
|
|
4
|
-
* `apps/obsidian/src/script-execution.ts` (
|
|
4
|
+
* `apps/obsidian/src/script-execution.ts` (same file
|
|
5
5
|
* name, same four exports, doc comments sharing the same "WHAT IT IS /
|
|
6
6
|
* WHY DEVICE-LOCAL / WHY THE WORDING LIVES HERE" structure, differing
|
|
7
7
|
* only in a handful of words).
|
package/dist/html-engine.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The `@markii/html
|
|
3
|
-
*
|
|
2
|
+
* The `@markii/host/html-engine` entry: the `@markii/html`-backed
|
|
3
|
+
* `HtmlExportEngine`. Kept out of the main and `/node` entries (it is the
|
|
4
|
+
* one module that needs the optional `@markii/html` peer); a host that
|
|
4
5
|
* exports HTML builds it here and hands it to `createMarkiiHost`'s
|
|
5
|
-
* `htmlEngine` option or to `buildNoteExport`.
|
|
6
|
-
* `@markii/host/node`.
|
|
6
|
+
* `htmlEngine` option or to `buildNoteExport`.
|
|
7
7
|
*/
|
|
8
8
|
import { escapeHtml, exportHtmlDocument, renderMarkToHtml } from '@markii/html';
|
|
9
9
|
import { defaultHtmlRegistry } from '@markii/html/components';
|