@carljia/omd-dsh 0.1.7 → 0.1.9
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 +36 -15
- package/cordis.patch.yml +13 -6
- package/lib/boot.d.ts +4 -4
- package/lib/boot.js +6 -11
- package/lib/cli.js +9 -21
- package/lib/client.d.ts +11 -0
- package/lib/client.js +427 -0
- package/lib/host.d.ts +42 -0
- package/lib/host.js +103 -0
- package/lib/index.js +4 -5
- package/lib/mode.js +1 -4
- package/lib/omd-matrix-controller.d.ts +108 -0
- package/lib/omd-matrix-controller.js +180 -0
- package/lib/plan.js +1 -4
- package/lib/startwork.js +1 -4
- package/lib/sync.d.ts +38 -20
- package/lib/sync.js +68 -215
- package/lib/task.js +1 -4
- package/lib/vendor/omd-mode-switch.mjs +967 -127
- package/lib/vendor/omd-mode.mjs +889 -174
- package/lib/vendor/omd-plan.mjs +95 -177
- package/lib/vendor/omd-start-work.mjs +96 -132
- package/lib/vendor/omd-task.mjs +20735 -265
- package/lib/vendor/omd-ulw.mjs +44 -49
- package/package.json +23 -7
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import type { Matrix } from "./sync.js";
|
|
2
|
+
/**
|
|
3
|
+
* Client-side edit state machine for the omd model matrix — deliberately free
|
|
4
|
+
* of React and DOM so it can be unit-tested against fake wire faces
|
|
5
|
+
* (test/client-store.test.ts).
|
|
6
|
+
*
|
|
7
|
+
* The controller mirrors one settings namespace scope (`ctx.settingsScope`
|
|
8
|
+
* bind) and writes through `api.settings.replace` with the scope's revision
|
|
9
|
+
* as `expectedRevision` — a stale editor is refused rather than silently
|
|
10
|
+
* overwriting a concurrent change (`settings-rejected` on the wire).
|
|
11
|
+
*/
|
|
12
|
+
/** Settings namespace the host row registers (src/host.ts) — must stay in step. */
|
|
13
|
+
export declare const OMD_SETTINGS_NS = "omd-model-allocation";
|
|
14
|
+
/** Client-side sync state of one settings namespace (wire-contract subset). */
|
|
15
|
+
export interface OmdScopeSnapshot {
|
|
16
|
+
status: "loading" | "ready" | "unavailable";
|
|
17
|
+
value: Matrix | undefined;
|
|
18
|
+
revision: number | undefined;
|
|
19
|
+
writable: boolean;
|
|
20
|
+
mode: "host" | "memory";
|
|
21
|
+
}
|
|
22
|
+
/** The `settings.replace` wire face this controller needs. */
|
|
23
|
+
export interface OmdSettingsApi {
|
|
24
|
+
settings: {
|
|
25
|
+
replace(request: {
|
|
26
|
+
ns: string;
|
|
27
|
+
section: object;
|
|
28
|
+
expectedRevision?: number;
|
|
29
|
+
}): Promise<{
|
|
30
|
+
result: {
|
|
31
|
+
ok: true;
|
|
32
|
+
value: unknown;
|
|
33
|
+
};
|
|
34
|
+
} | {
|
|
35
|
+
result: {
|
|
36
|
+
ok: false;
|
|
37
|
+
error: {
|
|
38
|
+
message: string;
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
}>;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/** The shared describe mirror face (used to reload Host state after a rejected write). */
|
|
45
|
+
export interface OmdDescribeFace {
|
|
46
|
+
load(): Promise<unknown>;
|
|
47
|
+
}
|
|
48
|
+
/** The bound scope as the controller consumes it. */
|
|
49
|
+
export interface OmdScope {
|
|
50
|
+
getSnapshot(): OmdScopeSnapshot;
|
|
51
|
+
subscribe(listener: () => void): () => void;
|
|
52
|
+
}
|
|
53
|
+
export interface OmdControllerSnapshot {
|
|
54
|
+
draft: Matrix | null;
|
|
55
|
+
status: "idle" | "saving";
|
|
56
|
+
error: string | null;
|
|
57
|
+
saved: boolean;
|
|
58
|
+
}
|
|
59
|
+
type ModeField = "provider" | "model" | "reasoningEffort";
|
|
60
|
+
export declare class OmdMatrixController {
|
|
61
|
+
private readonly api;
|
|
62
|
+
private readonly scope;
|
|
63
|
+
private readonly describe;
|
|
64
|
+
draft: Matrix | null;
|
|
65
|
+
status: "idle" | "saving";
|
|
66
|
+
error: string | null;
|
|
67
|
+
saved: boolean;
|
|
68
|
+
private readonly listeners;
|
|
69
|
+
private readonly unsubscribeScope;
|
|
70
|
+
/**
|
|
71
|
+
* Cached snapshot handed to `useSyncExternalStore`. React requires
|
|
72
|
+
* `getSnapshot()` to return the SAME reference between changes — a fresh
|
|
73
|
+
* object per call throws "The result of getSnapshot should be cached" and
|
|
74
|
+
* crashes the whole settings entry (blank page). Rebuilt only in `emit()`.
|
|
75
|
+
*/
|
|
76
|
+
private snapshot;
|
|
77
|
+
constructor(api: OmdSettingsApi, scope: OmdScope, describe: OmdDescribeFace);
|
|
78
|
+
/** Release the scope subscription (plugin fiber teardown). */
|
|
79
|
+
dispose(): void;
|
|
80
|
+
/** Stable snapshot reference (uSES-safe): the SAME object until state changes. */
|
|
81
|
+
getSnapshot(): OmdControllerSnapshot;
|
|
82
|
+
subscribe(listener: () => void): () => void;
|
|
83
|
+
private emit;
|
|
84
|
+
/** External change (mirror reload after a rejected write, another window):
|
|
85
|
+
* rebuild the draft from the fresh value, unless a save is in flight. */
|
|
86
|
+
private onScopeChange;
|
|
87
|
+
private refreshDraft;
|
|
88
|
+
/** Whether the Save / Reset controls may run. */
|
|
89
|
+
get canSave(): boolean;
|
|
90
|
+
/** Whether the namespace accepts writes at all (read-only provider / memory mode). */
|
|
91
|
+
get writable(): boolean;
|
|
92
|
+
/** Edit one mode's top-level field; an empty string removes the override
|
|
93
|
+
* (the field re-inherits the composition base / schema default). */
|
|
94
|
+
patchMode(modeId: string, field: ModeField, value: string): void;
|
|
95
|
+
/** Edit one tier's provider/model; an empty string removes the override. */
|
|
96
|
+
patchTier(modeId: string, tier: string, field: "provider" | "model", value: string): void;
|
|
97
|
+
/**
|
|
98
|
+
* Persist the whole draft matrix through `settings.replace` (wholesale
|
|
99
|
+
* section replacement — the removal/reset path merge cannot express). The
|
|
100
|
+
* revision fence makes a stale editor fail loudly instead of overwriting.
|
|
101
|
+
* @returns once the write settled and the snapshot reflects the outcome.
|
|
102
|
+
*/
|
|
103
|
+
save(): Promise<void>;
|
|
104
|
+
/** Restore the shipped default matrix: replace with an empty section. */
|
|
105
|
+
reset(): Promise<void>;
|
|
106
|
+
private replace;
|
|
107
|
+
}
|
|
108
|
+
export {};
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-side edit state machine for the omd model matrix — deliberately free
|
|
3
|
+
* of React and DOM so it can be unit-tested against fake wire faces
|
|
4
|
+
* (test/client-store.test.ts).
|
|
5
|
+
*
|
|
6
|
+
* The controller mirrors one settings namespace scope (`ctx.settingsScope`
|
|
7
|
+
* bind) and writes through `api.settings.replace` with the scope's revision
|
|
8
|
+
* as `expectedRevision` — a stale editor is refused rather than silently
|
|
9
|
+
* overwriting a concurrent change (`settings-rejected` on the wire).
|
|
10
|
+
*/
|
|
11
|
+
/** Settings namespace the host row registers (src/host.ts) — must stay in step. */
|
|
12
|
+
export const OMD_SETTINGS_NS = "omd-model-allocation";
|
|
13
|
+
function cloneMatrix(value) {
|
|
14
|
+
if (value === undefined)
|
|
15
|
+
return null;
|
|
16
|
+
return JSON.parse(JSON.stringify(value));
|
|
17
|
+
}
|
|
18
|
+
function messageOf(error) {
|
|
19
|
+
return error instanceof Error ? error.message : String(error);
|
|
20
|
+
}
|
|
21
|
+
export class OmdMatrixController {
|
|
22
|
+
api;
|
|
23
|
+
scope;
|
|
24
|
+
describe;
|
|
25
|
+
draft;
|
|
26
|
+
status = "idle";
|
|
27
|
+
error = null;
|
|
28
|
+
saved = false;
|
|
29
|
+
listeners = new Set();
|
|
30
|
+
unsubscribeScope;
|
|
31
|
+
/**
|
|
32
|
+
* Cached snapshot handed to `useSyncExternalStore`. React requires
|
|
33
|
+
* `getSnapshot()` to return the SAME reference between changes — a fresh
|
|
34
|
+
* object per call throws "The result of getSnapshot should be cached" and
|
|
35
|
+
* crashes the whole settings entry (blank page). Rebuilt only in `emit()`.
|
|
36
|
+
*/
|
|
37
|
+
snapshot;
|
|
38
|
+
constructor(api, scope, describe) {
|
|
39
|
+
this.api = api;
|
|
40
|
+
this.scope = scope;
|
|
41
|
+
this.describe = describe;
|
|
42
|
+
this.draft = cloneMatrix(scope.getSnapshot().value);
|
|
43
|
+
this.snapshot = { draft: this.draft, status: this.status, error: this.error, saved: this.saved };
|
|
44
|
+
this.unsubscribeScope = scope.subscribe(() => this.onScopeChange());
|
|
45
|
+
}
|
|
46
|
+
/** Release the scope subscription (plugin fiber teardown). */
|
|
47
|
+
dispose() {
|
|
48
|
+
this.unsubscribeScope();
|
|
49
|
+
this.listeners.clear();
|
|
50
|
+
}
|
|
51
|
+
/** Stable snapshot reference (uSES-safe): the SAME object until state changes. */
|
|
52
|
+
getSnapshot() {
|
|
53
|
+
return this.snapshot;
|
|
54
|
+
}
|
|
55
|
+
subscribe(listener) {
|
|
56
|
+
this.listeners.add(listener);
|
|
57
|
+
return () => { this.listeners.delete(listener); };
|
|
58
|
+
}
|
|
59
|
+
emit() {
|
|
60
|
+
this.snapshot = { draft: this.draft, status: this.status, error: this.error, saved: this.saved };
|
|
61
|
+
for (const listener of [...this.listeners])
|
|
62
|
+
listener();
|
|
63
|
+
}
|
|
64
|
+
/** External change (mirror reload after a rejected write, another window):
|
|
65
|
+
* rebuild the draft from the fresh value, unless a save is in flight. */
|
|
66
|
+
onScopeChange() {
|
|
67
|
+
if (this.status === "saving")
|
|
68
|
+
return;
|
|
69
|
+
this.refreshDraft();
|
|
70
|
+
this.emit();
|
|
71
|
+
}
|
|
72
|
+
refreshDraft() {
|
|
73
|
+
const value = this.scope.getSnapshot().value;
|
|
74
|
+
if (value !== undefined)
|
|
75
|
+
this.draft = cloneMatrix(value);
|
|
76
|
+
}
|
|
77
|
+
/** Whether the Save / Reset controls may run. */
|
|
78
|
+
get canSave() {
|
|
79
|
+
const snap = this.scope.getSnapshot();
|
|
80
|
+
return snap.status === "ready" && snap.writable && this.status !== "saving" && this.draft !== null;
|
|
81
|
+
}
|
|
82
|
+
/** Whether the namespace accepts writes at all (read-only provider / memory mode). */
|
|
83
|
+
get writable() {
|
|
84
|
+
return this.scope.getSnapshot().writable;
|
|
85
|
+
}
|
|
86
|
+
/** Edit one mode's top-level field; an empty string removes the override
|
|
87
|
+
* (the field re-inherits the composition base / schema default). */
|
|
88
|
+
patchMode(modeId, field, value) {
|
|
89
|
+
const draft = this.draft;
|
|
90
|
+
if (draft === null)
|
|
91
|
+
return;
|
|
92
|
+
const modes = { ...draft.modes };
|
|
93
|
+
const cfg = { ...(modes[modeId] ?? {}) };
|
|
94
|
+
if (value === "")
|
|
95
|
+
delete cfg[field];
|
|
96
|
+
else
|
|
97
|
+
cfg[field] = value;
|
|
98
|
+
modes[modeId] = cfg;
|
|
99
|
+
this.draft = { ...draft, modes };
|
|
100
|
+
this.saved = false;
|
|
101
|
+
this.emit();
|
|
102
|
+
}
|
|
103
|
+
/** Edit one tier's provider/model; an empty string removes the override. */
|
|
104
|
+
patchTier(modeId, tier, field, value) {
|
|
105
|
+
const draft = this.draft;
|
|
106
|
+
if (draft === null)
|
|
107
|
+
return;
|
|
108
|
+
const modes = { ...draft.modes };
|
|
109
|
+
const cfg = { ...(modes[modeId] ?? {}) };
|
|
110
|
+
const tiers = { ...(cfg.tiers ?? {}) };
|
|
111
|
+
const tierCfg = { ...(tiers[tier] ?? {}) };
|
|
112
|
+
if (value === "")
|
|
113
|
+
delete tierCfg[field];
|
|
114
|
+
else
|
|
115
|
+
tierCfg[field] = value;
|
|
116
|
+
tiers[tier] = tierCfg;
|
|
117
|
+
cfg.tiers = tiers;
|
|
118
|
+
modes[modeId] = cfg;
|
|
119
|
+
this.draft = { ...draft, modes };
|
|
120
|
+
this.saved = false;
|
|
121
|
+
this.emit();
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Persist the whole draft matrix through `settings.replace` (wholesale
|
|
125
|
+
* section replacement — the removal/reset path merge cannot express). The
|
|
126
|
+
* revision fence makes a stale editor fail loudly instead of overwriting.
|
|
127
|
+
* @returns once the write settled and the snapshot reflects the outcome.
|
|
128
|
+
*/
|
|
129
|
+
async save() {
|
|
130
|
+
if (!this.canSave || this.draft === null)
|
|
131
|
+
return;
|
|
132
|
+
const snap = this.scope.getSnapshot();
|
|
133
|
+
this.status = "saving";
|
|
134
|
+
this.error = null;
|
|
135
|
+
this.emit();
|
|
136
|
+
const response = await this.replace({ section: this.draft, revision: snap.revision });
|
|
137
|
+
if (response.ok)
|
|
138
|
+
this.saved = true;
|
|
139
|
+
else {
|
|
140
|
+
this.error = response.message;
|
|
141
|
+
await this.describe.load();
|
|
142
|
+
}
|
|
143
|
+
this.refreshDraft();
|
|
144
|
+
this.status = "idle";
|
|
145
|
+
this.emit();
|
|
146
|
+
}
|
|
147
|
+
/** Restore the shipped default matrix: replace with an empty section. */
|
|
148
|
+
async reset() {
|
|
149
|
+
if (!this.canSave)
|
|
150
|
+
return;
|
|
151
|
+
const snap = this.scope.getSnapshot();
|
|
152
|
+
this.status = "saving";
|
|
153
|
+
this.error = null;
|
|
154
|
+
this.emit();
|
|
155
|
+
const response = await this.replace({ section: {}, revision: snap.revision });
|
|
156
|
+
if (response.ok)
|
|
157
|
+
this.saved = true;
|
|
158
|
+
else
|
|
159
|
+
this.error = response.message;
|
|
160
|
+
await this.describe.load();
|
|
161
|
+
this.refreshDraft();
|
|
162
|
+
this.status = "idle";
|
|
163
|
+
this.emit();
|
|
164
|
+
}
|
|
165
|
+
async replace(request) {
|
|
166
|
+
try {
|
|
167
|
+
const response = await this.api.settings.replace({
|
|
168
|
+
ns: OMD_SETTINGS_NS,
|
|
169
|
+
section: request.section,
|
|
170
|
+
...(request.revision === undefined ? {} : { expectedRevision: request.revision }),
|
|
171
|
+
});
|
|
172
|
+
if (response.result.ok)
|
|
173
|
+
return { ok: true };
|
|
174
|
+
return { ok: false, message: response.result.error.message };
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
return { ok: false, message: messageOf(error) };
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
package/lib/plan.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
2
2
|
import { basename, join } from "node:path";
|
|
3
|
-
import { scopeOf } from "@deepseek-ai/dsh-scope";
|
|
4
3
|
/**
|
|
5
4
|
* @module @carljia/omd-dsh/plan
|
|
6
5
|
*
|
|
@@ -96,9 +95,7 @@ function planModeActive(events) {
|
|
|
96
95
|
return active;
|
|
97
96
|
}
|
|
98
97
|
function apply(ctx) {
|
|
99
|
-
|
|
100
|
-
throw new Error("omd-plan: refusing to mount outside a scoped context; mount this row inside an agent preset");
|
|
101
|
-
}
|
|
98
|
+
// 无 scope 守卫:见 src/index.ts 的说明(自包含 bundle 无法读取 harness 的 kScope)。
|
|
102
99
|
// Scoped .md-only write guard: the planner may write/edit only markdown
|
|
103
100
|
// files, keeping it read-only for every other path. The plan file itself is
|
|
104
101
|
// written by this row via node:fs (not through the model's write/edit tools),
|
package/lib/startwork.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { access, readFile } from "node:fs/promises";
|
|
2
2
|
import { isAbsolute, join } from "node:path";
|
|
3
|
-
import { scopeOf } from "@deepseek-ai/dsh-scope";
|
|
4
3
|
/**
|
|
5
4
|
* @module @carljia/omd-dsh/startwork
|
|
6
5
|
*
|
|
@@ -129,9 +128,7 @@ async function executeStartWork(ctx, invocation) {
|
|
|
129
128
|
}
|
|
130
129
|
}
|
|
131
130
|
function apply(ctx) {
|
|
132
|
-
|
|
133
|
-
throw new Error("omd-start-work: refusing to mount outside a scoped context; mount this row inside an agent preset");
|
|
134
|
-
}
|
|
131
|
+
// 无 scope 守卫:见 src/index.ts 的说明(自包含 bundle 无法读取 harness 的 kScope)。
|
|
135
132
|
ctx.inject(["commands"], (commandCtx) => {
|
|
136
133
|
commandCtx.commands.register({
|
|
137
134
|
name: "start-work",
|
package/lib/sync.d.ts
CHANGED
|
@@ -1,15 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* omd-dsh sync core — materialize the OMD presets into <DSH_HOME>/.agent-presets.
|
|
3
3
|
*
|
|
4
|
-
* Shared by the CLI (
|
|
5
|
-
* + restart)
|
|
6
|
-
* omd-mode / omd-task rows from the
|
|
7
|
-
* vendored row modules into .agent-presets
|
|
8
|
-
*
|
|
9
|
-
*
|
|
4
|
+
* Shared by the CLI (`omd-dsh sync`), the bundle boot row (`dsh plugin add`
|
|
5
|
+
* + restart), and the host settings row (lib/host.js): render each preset's
|
|
6
|
+
* omd-mode / omd-task rows from the model matrix, and copy the presets plus
|
|
7
|
+
* the vendored row modules into .agent-presets.
|
|
8
|
+
*
|
|
9
|
+
* The matrix has two faces: `runSync` reads/writes the CLI face
|
|
10
|
+
* (<DSH_HOME>/omd-matrix.json, the `omd-dsh setup` target), while the host
|
|
11
|
+
* settings row resolves the matrix from the settings namespace
|
|
12
|
+
* (`omd-model-allocation` in settings.yaml) and feeds it to
|
|
13
|
+
* `runSyncWithMatrix` — the file becomes an exported mirror of the namespace
|
|
14
|
+
* plus the CLI compatibility face (see src/host.ts).
|
|
15
|
+
*
|
|
16
|
+
* The vendored rows are SELF-CONTAINED bundles (see scripts/postbuild.mjs):
|
|
17
|
+
* every dependency is bundled in and they carry no @deepseek-ai imports, so
|
|
18
|
+
* the sync needs NO harness tree knowledge — the rows work regardless of
|
|
19
|
+
* whether the harness's agent machinery loads from an npx cache, a profile,
|
|
20
|
+
* or a global npm install, and no `--harness` configuration is ever needed.
|
|
21
|
+
* Bare package rows in the preset compositions (e.g. @deepseek-ai/dsh-persona)
|
|
22
|
+
* are resolved by the harness's own loader at runtime against the host base.
|
|
10
23
|
*/
|
|
11
24
|
export type SyncFlags = {
|
|
12
|
-
harness?: string;
|
|
13
25
|
dryRun: boolean;
|
|
14
26
|
verbose: boolean;
|
|
15
27
|
};
|
|
@@ -43,20 +55,26 @@ export declare const VENDOR_SOURCES: string[];
|
|
|
43
55
|
/** User-owned model matrix: lives under DSH_HOME, never inside the package or the repo. */
|
|
44
56
|
export declare const MATRIX_PATH: string;
|
|
45
57
|
export declare function dshHome(): string;
|
|
58
|
+
export declare const MatrixSchema: any;
|
|
59
|
+
export declare function readDefaultMatrix(): Matrix;
|
|
46
60
|
/**
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
|
|
52
|
-
export declare function resolveHarness(flags: SyncFlags): string | undefined;
|
|
53
|
-
/**
|
|
54
|
-
* Resolve the harness node_modules from THIS module's own location, walking up
|
|
55
|
-
* the Node resolution path for @deepseek-ai/dsh-scope. This is the reliable
|
|
56
|
-
* anchor when the package runs as a bundle inside a DSH profile: the profile's
|
|
57
|
-
* flat module fallback (or its hoisted node_modules) exposes the harness tree.
|
|
61
|
+
* Read the user's matrix file (<DSH_HOME>/omd-matrix.json) without touching
|
|
62
|
+
* the filesystem beyond the read: missing or malformed returns undefined and
|
|
63
|
+
* NEVER auto-generates — the caller decides what to fall back to (settings
|
|
64
|
+
* namespace resolved value / default matrix). This is the host row's
|
|
65
|
+
* "import CLI / legacy edits into the settings namespace" read.
|
|
58
66
|
*/
|
|
59
|
-
export declare function
|
|
67
|
+
export declare function readMatrixFileIfExists(): Matrix | undefined;
|
|
68
|
+
/** Structural equality over the small JSON matrix (stringify equality suffices). */
|
|
69
|
+
export declare function matrixEquals(a: Matrix, b: Matrix): boolean;
|
|
60
70
|
export declare function loadMatrix(flags: SyncFlags, log?: (msg: string) => void): Matrix;
|
|
61
71
|
export declare function saveMatrix(m: Matrix): void;
|
|
62
|
-
|
|
72
|
+
/**
|
|
73
|
+
* Render and materialize the presets from an ALREADY-RESOLVED matrix. This is
|
|
74
|
+
* the shared core between the CLI file path (`runSync`) and the settings
|
|
75
|
+
* namespace path (host row): the matrix comes from the caller, everything
|
|
76
|
+
* after `loadMatrix(...)` is here.
|
|
77
|
+
*/
|
|
78
|
+
export declare function runSyncWithMatrix(matrix: Matrix, flags: SyncFlags, log?: (msg: string) => void): Promise<void>;
|
|
79
|
+
/** CLI / manual-fallback path: load the matrix from <DSH_HOME>/omd-matrix.json (generating/migrating it on first run), then render. */
|
|
80
|
+
export declare function runSync(flags: SyncFlags, log?: (msg: string) => void): Promise<void>;
|