omgbase 0.1.0

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.
Files changed (80) hide show
  1. package/LICENSE +21 -0
  2. package/dist/src/cmd/_embed.d.ts +55 -0
  3. package/dist/src/cmd/_embed.js +102 -0
  4. package/dist/src/cmd/_mutate.d.ts +47 -0
  5. package/dist/src/cmd/_mutate.js +211 -0
  6. package/dist/src/cmd/_remote.d.ts +8 -0
  7. package/dist/src/cmd/_remote.js +61 -0
  8. package/dist/src/cmd/_source.d.ts +13 -0
  9. package/dist/src/cmd/_source.js +47 -0
  10. package/dist/src/cmd/admin.d.ts +6 -0
  11. package/dist/src/cmd/admin.js +289 -0
  12. package/dist/src/cmd/bootstrap.d.ts +3 -0
  13. package/dist/src/cmd/bootstrap.js +252 -0
  14. package/dist/src/cmd/cat.d.ts +2 -0
  15. package/dist/src/cmd/cat.js +80 -0
  16. package/dist/src/cmd/diff.d.ts +2 -0
  17. package/dist/src/cmd/diff.js +76 -0
  18. package/dist/src/cmd/docs.d.ts +6 -0
  19. package/dist/src/cmd/docs.js +154 -0
  20. package/dist/src/cmd/edit.d.ts +2 -0
  21. package/dist/src/cmd/edit.js +74 -0
  22. package/dist/src/cmd/find.d.ts +2 -0
  23. package/dist/src/cmd/find.js +98 -0
  24. package/dist/src/cmd/help.d.ts +2 -0
  25. package/dist/src/cmd/help.js +47 -0
  26. package/dist/src/cmd/hist.d.ts +2 -0
  27. package/dist/src/cmd/hist.js +58 -0
  28. package/dist/src/cmd/links.d.ts +2 -0
  29. package/dist/src/cmd/links.js +76 -0
  30. package/dist/src/cmd/log.d.ts +2 -0
  31. package/dist/src/cmd/log.js +109 -0
  32. package/dist/src/cmd/ls.d.ts +2 -0
  33. package/dist/src/cmd/ls.js +88 -0
  34. package/dist/src/cmd/mcp.d.ts +2 -0
  35. package/dist/src/cmd/mcp.js +192 -0
  36. package/dist/src/cmd/mutate.d.ts +10 -0
  37. package/dist/src/cmd/mutate.js +352 -0
  38. package/dist/src/cmd/node.d.ts +2 -0
  39. package/dist/src/cmd/node.js +66 -0
  40. package/dist/src/cmd/oqx.d.ts +2 -0
  41. package/dist/src/cmd/oqx.js +193 -0
  42. package/dist/src/cmd/outline.d.ts +2 -0
  43. package/dist/src/cmd/outline.js +87 -0
  44. package/dist/src/cmd/retarget.d.ts +2 -0
  45. package/dist/src/cmd/retarget.js +91 -0
  46. package/dist/src/cmd/run.d.ts +2 -0
  47. package/dist/src/cmd/run.js +135 -0
  48. package/dist/src/cmd/shell.d.ts +2 -0
  49. package/dist/src/cmd/shell.js +159 -0
  50. package/dist/src/cmd/show.d.ts +2 -0
  51. package/dist/src/cmd/show.js +107 -0
  52. package/dist/src/cmd/source.d.ts +2 -0
  53. package/dist/src/cmd/source.js +231 -0
  54. package/dist/src/cmd/status.d.ts +2 -0
  55. package/dist/src/cmd/status.js +95 -0
  56. package/dist/src/cmd/sync.d.ts +2 -0
  57. package/dist/src/cmd/sync.js +176 -0
  58. package/dist/src/cmd/update.d.ts +2 -0
  59. package/dist/src/cmd/update.js +100 -0
  60. package/dist/src/commands.d.ts +18 -0
  61. package/dist/src/commands.js +112 -0
  62. package/dist/src/context.d.ts +73 -0
  63. package/dist/src/context.js +80 -0
  64. package/dist/src/dispatch.d.ts +8 -0
  65. package/dist/src/dispatch.js +148 -0
  66. package/dist/src/main.d.ts +3 -0
  67. package/dist/src/main.js +67 -0
  68. package/dist/src/output.d.ts +60 -0
  69. package/dist/src/output.js +131 -0
  70. package/dist/src/render.d.ts +44 -0
  71. package/dist/src/render.js +116 -0
  72. package/dist/src/shell/refs.d.ts +37 -0
  73. package/dist/src/shell/refs.js +111 -0
  74. package/dist/src/shell/session.d.ts +71 -0
  75. package/dist/src/shell/session.js +317 -0
  76. package/dist/src/shell/tokenize.d.ts +3 -0
  77. package/dist/src/shell/tokenize.js +79 -0
  78. package/dist/src/style.d.ts +58 -0
  79. package/dist/src/style.js +159 -0
  80. package/package.json +63 -0
@@ -0,0 +1,109 @@
1
+ import { parseArgs } from "node:util";
2
+ import { changesSince } from "@omgbase/core";
3
+ import { CliUsageError, truncationFooter, EXIT_OK, renderHelp } from "../output.js";
4
+ import { remoteCall } from "./_remote.js";
5
+ // `omg log` (11 §5.5) — changes_since, one digest summary per line. Relative
6
+ // --since (24h/7d) is resolved to a literal ISO timestamp client-side, then to
7
+ // the commit seq at/just-before that time (the query language stays clock-free).
8
+ function resolveSinceSeq(cli, repoId, since) {
9
+ if (!since)
10
+ return 0;
11
+ const iso = relativeToIso(since);
12
+ const ws = cli.workspace();
13
+ const row = ws.store.db
14
+ .prepare("SELECT MAX(seq) AS seq FROM commits WHERE repo_id = ? AND ts < ?")
15
+ .get(repoId, iso);
16
+ return row.seq ?? 0;
17
+ }
18
+ function relativeToIso(since) {
19
+ const m = /^(\d+)([hdwm])$/.exec(since.trim());
20
+ if (m) {
21
+ const n = Number(m[1]);
22
+ const unit = m[2];
23
+ const ms = unit === "h" ? 3600e3 : unit === "d" ? 86400e3 : unit === "w" ? 7 * 86400e3 : 30 * 86400e3;
24
+ return new Date(Date.now() - n * ms).toISOString();
25
+ }
26
+ // Absolute timestamp: pass through (Date normalizes).
27
+ const t = Date.parse(since);
28
+ return Number.isNaN(t) ? new Date(0).toISOString() : new Date(t).toISOString();
29
+ }
30
+ async function runLog(cli, args) {
31
+ const { values } = parseArgs({
32
+ args,
33
+ allowPositionals: true,
34
+ options: {
35
+ since: { type: "string" },
36
+ cursor: { type: "string" },
37
+ origin: { type: "string" },
38
+ n: { type: "string", short: "n" },
39
+ help: { type: "boolean" },
40
+ },
41
+ });
42
+ if (values.help) {
43
+ return renderHelp(cli, {
44
+ name: "log",
45
+ summary: "What changed: one digest per commit, newest first",
46
+ usage: "log [--since <24h|7d|ISO>] [--cursor <n>] [--origin api|observed] [-n <N>]",
47
+ options: [
48
+ ["--since <t>", "only commits after a relative age (24h, 7d) or an ISO timestamp"],
49
+ ["--cursor <n>", "continue from a commit sequence number"],
50
+ ["--origin <o>", "api (agent/CLI writes) | observed (file edits picked up by sync)"],
51
+ ["-n <N>", "max commits"],
52
+ ],
53
+ });
54
+ }
55
+ let result;
56
+ if (cli.flags.server) {
57
+ // Remote: changes_since by cursor/limit/origin. `--since` resolves a
58
+ // timestamp against the local commits table, which a remote client lacks —
59
+ // use `--cursor` remotely.
60
+ if (values.since)
61
+ throw new CliUsageError("--since is not supported with --server; use --cursor <seq>");
62
+ result = await remoteCall(cli, "changes_since", {
63
+ ...(values.cursor ? { cursor: Number(values.cursor) } : {}),
64
+ ...(values.n ? { limit: Number(values.n) } : {}),
65
+ ...(values.origin ? { origin: values.origin } : {}),
66
+ });
67
+ }
68
+ else {
69
+ const ws = cli.workspace();
70
+ const repo = cli.repo(ws);
71
+ const cursor = values.cursor ? Number(values.cursor) : resolveSinceSeq(cli, repo.repoId, values.since);
72
+ const opts = { cursor };
73
+ if (values.n)
74
+ opts.limit = Number(values.n);
75
+ if (values.origin)
76
+ opts.origin = values.origin;
77
+ result = changesSince(ws.store, repo.repoId, opts);
78
+ }
79
+ if (cli.flags.mode === "json") {
80
+ cli.io.out(JSON.stringify(result));
81
+ return EXIT_OK;
82
+ }
83
+ if (cli.flags.mode === "jsonl") {
84
+ for (const d of result.digests)
85
+ cli.io.out(JSON.stringify(d));
86
+ if (result.truncated)
87
+ truncationFooter(cli.io, cli.style, result.cursor);
88
+ return EXIT_OK;
89
+ }
90
+ if (cli.flags.mode === "ids") {
91
+ for (const d of result.digests)
92
+ cli.io.out(d.commit);
93
+ return EXIT_OK;
94
+ }
95
+ const { style, io } = cli;
96
+ if (result.digests.length === 0) {
97
+ io.err(style.dim(" no changes"));
98
+ return EXIT_OK;
99
+ }
100
+ for (const d of result.digests) {
101
+ const origin = d.origin === "observed" ? style.accent(d.origin.padEnd(8)) : style.warn(d.origin.padEnd(8));
102
+ io.out(`${style.dim(`#${d.seq}`)} ${origin} ${d.summary}`);
103
+ }
104
+ if (result.truncated)
105
+ truncationFooter(io, style, result.cursor);
106
+ return EXIT_OK;
107
+ }
108
+ export const cmdLog = { name: "log", summary: "Commit digests (change feed)", run: (cli, a) => runLog(cli, a) };
109
+ //# sourceMappingURL=log.js.map
@@ -0,0 +1,2 @@
1
+ import type { Command } from "../commands.js";
2
+ export declare const cmdLs: Command;
@@ -0,0 +1,88 @@
1
+ import { parseArgs } from "node:util";
2
+ import { docsList } from "@omgbase/core";
3
+ import { columns } from "../render.js";
4
+ import { EXIT_OK, renderHelp } from "../output.js";
5
+ import { remoteCall } from "./_remote.js";
6
+ // `omg ls [glob]` (11 §5.2) — live documents: path, block count, last-commit
7
+ // time. glob is a simple prefix/suffix match on the path (SQL LIKE with * → %).
8
+ //
9
+ // The engine pages docs_list (uniform truncated+cursor contract, mcp-api §1);
10
+ // a terminal `ls` is complete by definition, so this walks every page — local
11
+ // or `--server` — and renders the concatenation.
12
+ async function runLs(cli, args) {
13
+ const { values, positionals } = parseArgs({ args, allowPositionals: true, options: { help: { type: "boolean" } } });
14
+ if (values.help) {
15
+ return renderHelp(cli, {
16
+ name: "ls",
17
+ summary: "List live documents: path, block count, last-commit time (always the complete listing)",
18
+ usage: "ls [<glob>] [--ids|--json|--jsonl]",
19
+ options: [
20
+ ["<glob>", "path filter; `*` matches any run of characters (`notes/*.md`)"],
21
+ ["--ids", "paths only, one per line (pipe fuel)"],
22
+ ],
23
+ });
24
+ }
25
+ const glob = positionals[0];
26
+ const rows = [];
27
+ let cursor = null;
28
+ do {
29
+ let page;
30
+ if (cli.flags.server) {
31
+ page = await remoteCall(cli, "docs_list", { ...(glob ? { path_glob: glob } : {}), ...(cursor ? { cursor } : {}) });
32
+ }
33
+ else {
34
+ const ws = cli.workspace();
35
+ const repo = cli.repo(ws);
36
+ page = docsList(ws.store, repo.repoId, { ...(glob ? { pathGlob: glob } : {}), ...(cursor ? { cursor } : {}) });
37
+ }
38
+ rows.push(...page.items);
39
+ cursor = page.truncated ? page.cursor : null;
40
+ } while (cursor);
41
+ cli.capture?.(rows); // shell: docs become the addressable frame (ref = path)
42
+ if (cli.flags.mode === "ids") {
43
+ for (const r of rows)
44
+ cli.io.out(r.path);
45
+ return EXIT_OK;
46
+ }
47
+ if (cli.flags.mode === "json") {
48
+ cli.io.out(JSON.stringify(rows));
49
+ return EXIT_OK;
50
+ }
51
+ if (cli.flags.mode === "jsonl") {
52
+ for (const r of rows)
53
+ cli.io.out(JSON.stringify(r));
54
+ return EXIT_OK;
55
+ }
56
+ const { style, io } = cli;
57
+ if (rows.length === 0) {
58
+ io.err(style.dim(" no documents"));
59
+ return EXIT_OK;
60
+ }
61
+ const table = rows.map((r) => [
62
+ style.accent(r.path),
63
+ style.dim(`${r.blocks} blocks`),
64
+ style.dim(relTime(r.ts)),
65
+ ]);
66
+ for (const line of columns(table, [{}, { align: "right" }, { align: "right" }]))
67
+ io.out(line);
68
+ return EXIT_OK;
69
+ }
70
+ function relTime(ts) {
71
+ if (!ts)
72
+ return "—";
73
+ const then = Date.parse(ts);
74
+ if (Number.isNaN(then))
75
+ return ts;
76
+ const secs = Math.max(0, Math.floor((Date.now() - then) / 1000));
77
+ if (secs < 60)
78
+ return `${secs}s ago`;
79
+ const mins = Math.floor(secs / 60);
80
+ if (mins < 60)
81
+ return `${mins}m ago`;
82
+ const hrs = Math.floor(mins / 60);
83
+ if (hrs < 24)
84
+ return `${hrs}h ago`;
85
+ return `${Math.floor(hrs / 24)}d ago`;
86
+ }
87
+ export const cmdLs = { name: "ls", summary: "List live documents", run: (cli, a) => runLs(cli, a) };
88
+ //# sourceMappingURL=ls.js.map
@@ -0,0 +1,2 @@
1
+ import type { Command } from "../commands.js";
2
+ export declare const cmdMcp: Command;
@@ -0,0 +1,192 @@
1
+ import { parseArgs } from "node:util";
2
+ import { serveStdio, Watcher, WatchLease, watchLeaseLive, freshnessSweep, EmbedDrainer, EngineError } from "@omgbase/core";
3
+ import { EngineErrorLike, EXIT_OK, renderHelp } from "../output.js";
4
+ import { loadEmbedding } from "./_embed.js";
5
+ import { openRepoSource } from "./_source.js";
6
+ // `omg mcp [--no-watch]` (11 §5.8) — MCP server on stdio; the host owns the
7
+ // process lifetime. Runs an in-process watcher by default so a lone session is
8
+ // always fresh, auto-disabled when another live watch lease exists; --no-watch
9
+ // forces it off.
10
+ //
11
+ // CRITICAL: on stdio, stdout is the MCP protocol channel. Nothing may write to
12
+ // stdout here — every diagnostic goes to stderr (cli.io.err).
13
+ async function runMcp(cli, args) {
14
+ const { values } = parseArgs({
15
+ args,
16
+ allowPositionals: true,
17
+ options: { "no-watch": { type: "boolean" }, help: { type: "boolean" } },
18
+ });
19
+ if (values.help) {
20
+ return renderHelp(cli, {
21
+ name: "mcp",
22
+ summary: "Serve the MCP tool surface on stdio for an MCP host (Claude Code, Cursor, …); the host owns the process lifetime",
23
+ usage: "mcp [-C <workspace-dir>] [--repo <slug>] [--no-watch]",
24
+ options: [
25
+ ["-C <dir>", "the workspace to serve — a directory at or below one containing .omgbase/ (the host rarely starts you inside it)"],
26
+ ["--repo <slug>", "which repo, when the workspace has several"],
27
+ ["--no-watch", "don't run the in-process file watcher (it is auto-off when another live watcher holds the lease)"],
28
+ ],
29
+ notes: [`host config: {"command": "${cli.prog}", "args": ["mcp", "-C", "/path/to/notes"]}`],
30
+ });
31
+ }
32
+ // The host launches us from its own cwd, so a missing workspace here almost
33
+ // always means the host config lacks `-C <dir>` — say so, rather than the
34
+ // generic "run init" hint (which would create an empty workspace in the wrong place).
35
+ let ws;
36
+ try {
37
+ ws = cli.workspace();
38
+ }
39
+ catch (err) {
40
+ if (err instanceof EngineErrorLike && err.code === "repo_not_found") {
41
+ throw new EngineErrorLike("repo_not_found", err.message, {
42
+ hint: `\`${cli.prog} mcp\` serves one workspace: point it there with -C, e.g. {"command": "${cli.prog}", "args": ["mcp", "-C", "/path/to/notes"]} in the MCP host config — or create one first with \`${cli.prog} init <dir>\` and \`${cli.prog} -C <dir> source add .\``,
43
+ });
44
+ }
45
+ throw err;
46
+ }
47
+ const repo = cli.repo(ws);
48
+ // Connect the configured embedder once (if any) so the query tool's
49
+ // `semantic` mode has a vectorizer for the session. Unset ⇒ semantic queries
50
+ // return semantic_unavailable. The spawned process lives for the session and
51
+ // is released on shutdown.
52
+ //
53
+ // A CONFIGURED-but-broken embedder must never be mistaken for "no embedder":
54
+ // we don't take the whole server down over it (non-semantic tools work fine),
55
+ // but we complain loudly at startup and make every semantic access fail with a
56
+ // clear `embedder_failed` (see the throwing embedQuery below), so the fault is
57
+ // impossible to miss instead of silently degrading to keyword-only search.
58
+ let embedding = null;
59
+ let embedderError = null;
60
+ try {
61
+ embedding = await loadEmbedding(ws, repo.repoId);
62
+ if (embedding)
63
+ cli.io.err(cli.style.dim(`[mcp] semantic query enabled via ${embedding.providerName}`));
64
+ }
65
+ catch (err) {
66
+ embedderError = err instanceof EngineError && err.code === "embedder_failed" ? err : null;
67
+ if (!embedderError)
68
+ throw err; // an unexpected failure is still fatal
69
+ const d = (embedderError.data ?? {});
70
+ cli.io.err(cli.style.err("[mcp] ✖ EMBEDDER NONFUNCTIONAL — semantic search + auto-embed disabled"));
71
+ cli.io.err(cli.style.err(` provider: ${d.provider ?? "?"}`));
72
+ cli.io.err(cli.style.err(` reason: ${d.reason ?? embedderError.message}`));
73
+ cli.io.err(cli.style.err(" semantic queries will fail with embedder_failed until this is fixed."));
74
+ }
75
+ // Keep embeddings timely: a background drainer embeds blocks touched by a
76
+ // mutation (or a watcher checkpoint) without blocking the tool's response.
77
+ // Only meaningful when a provider is configured.
78
+ const drainer = embedding
79
+ ? new EmbedDrainer(ws.store, repo.repoId, embedding.worker, {
80
+ onDrain: ({ embedded }) => cli.io.err(cli.style.dim(`[mcp] embedded ${embedded} block(s)`)),
81
+ onError: (err) => cli.io.err(cli.style.dim(`[mcp] embed drain failed: ${String(err)}`)),
82
+ })
83
+ : null;
84
+ // Decide whether to run the in-process watcher. Off if --no-watch, or if a
85
+ // live watcher already holds the lease (another `omg watch`/`omg mcp`).
86
+ const leaseHeld = watchLeaseLive(ws.omgbaseDir);
87
+ const wantWatch = !values["no-watch"] && !leaseHeld;
88
+ let lease = null;
89
+ let watcher = null;
90
+ let source = null;
91
+ if (wantWatch) {
92
+ lease = WatchLease.tryAcquire(ws.omgbaseDir);
93
+ if (lease) {
94
+ // Prime with a one-shot sweep so the session starts fresh, then watch via
95
+ // the external fs-adapter process (chokidar lives there, not in-engine).
96
+ if (repo.rootPath)
97
+ freshnessSweep(ws.store, repo.repoId, repo.rootPath);
98
+ source = await openRepoSource(ws.store, repo);
99
+ if (source) {
100
+ watcher = new Watcher(ws.store, repo.repoId, source, {
101
+ onCheckpoint: (r) => {
102
+ if (r.ingested.length > 0 || r.deleted.length > 0) {
103
+ cli.io.err(cli.style.dim(`[watch] checkpoint: +${r.ingested.length} -${r.deleted.length}`));
104
+ // A file change the watcher ingested may also need (re-)embedding.
105
+ drainer?.schedule();
106
+ }
107
+ },
108
+ onError: (err) => cli.io.err(cli.style.dim(`[watch] error: ${String(err)}`)),
109
+ });
110
+ await watcher.start();
111
+ cli.io.err(cli.style.dim(`[mcp] serving ${repo.slug} on stdio · watcher live`));
112
+ }
113
+ else {
114
+ cli.io.err(cli.style.dim(`[mcp] serving ${repo.slug} on stdio · sourceless (no watch)`));
115
+ }
116
+ }
117
+ else {
118
+ // Lost the race for the lease; another watcher is live — serve without one.
119
+ cli.io.err(cli.style.dim(`[mcp] serving ${repo.slug} on stdio · watcher elsewhere`));
120
+ }
121
+ }
122
+ else {
123
+ const why = values["no-watch"] ? "watcher off (--no-watch)" : "watcher elsewhere";
124
+ cli.io.err(cli.style.dim(`[mcp] serving ${repo.slug} on stdio · ${why}`));
125
+ }
126
+ if (drainer)
127
+ cli.io.err(cli.style.dim(`[mcp] auto-embed on mutation enabled`));
128
+ // The query surface's `embedQuery`: a live vectorizer when the embedder loaded,
129
+ // or — when it's configured-but-broken — a hook that throws `embedder_failed`
130
+ // so semantic access fails loudly and specifically (not the misleading
131
+ // `semantic_unavailable`, which the server emits only when embedQuery is
132
+ // absent, i.e. genuinely no provider configured). `const` captures satisfy
133
+ // closure narrowing over the `let`-bound state above.
134
+ const loaded = embedding;
135
+ const failed = embedderError;
136
+ const embedQuery = loaded
137
+ ? async (text) => ({ model: loaded.provider.model, vec: await loaded.worker.embedQuery(text) })
138
+ : failed
139
+ ? (_text) => Promise.reject(failed)
140
+ : undefined;
141
+ const handle = await serveStdio({
142
+ store: ws.store,
143
+ repoId: repo.repoId,
144
+ ...(repo.rootPath ? { rootPath: repo.rootPath } : {}),
145
+ ...(drainer ? { onMutation: () => drainer.schedule() } : {}),
146
+ ...(embedQuery ? { embedQuery } : {}),
147
+ });
148
+ let shuttingDown = false;
149
+ const shutdown = async () => {
150
+ if (shuttingDown)
151
+ return;
152
+ shuttingDown = true;
153
+ if (watcher)
154
+ await watcher.stop();
155
+ if (source)
156
+ await source.close();
157
+ lease?.release();
158
+ // Drain any pending embeds before killing the provider process. flush()
159
+ // runs a debounced-but-not-yet-fired drain; close() then awaits in-flight.
160
+ if (drainer) {
161
+ try {
162
+ await drainer.flush();
163
+ }
164
+ catch { /* reported via onError */ }
165
+ await drainer.close();
166
+ }
167
+ if (embedding)
168
+ await embedding.close();
169
+ await handle.close();
170
+ ws.close();
171
+ };
172
+ // Host-owned lifetime: end on client disconnect or a signal. The in-process
173
+ // watcher keeps the event loop alive, so we can't rely on the loop draining —
174
+ // exit explicitly once cleanup completes. Three end triggers: the transport's
175
+ // onclose (handle.closed), stdin EOF, and SIGINT/SIGTERM.
176
+ const finish = () => {
177
+ void shutdown().finally(() => process.exit(0));
178
+ };
179
+ process.once("SIGINT", finish);
180
+ process.once("SIGTERM", finish);
181
+ process.stdin.once("end", finish);
182
+ process.stdin.once("close", finish);
183
+ handle.closed.then(finish, finish);
184
+ await handle.closed;
185
+ return EXIT_OK;
186
+ }
187
+ export const cmdMcp = {
188
+ name: "mcp",
189
+ summary: "Serve the MCP tool surface on stdio",
190
+ run: (cli, a) => runMcp(cli, a),
191
+ };
192
+ //# sourceMappingURL=mcp.js.map
@@ -0,0 +1,10 @@
1
+ import type { Command } from "../commands.js";
2
+ export declare const cmdApply: Command;
3
+ export declare const cmdInsert: Command;
4
+ export declare const cmdUpdate: Command;
5
+ export declare const cmdMove: Command;
6
+ export declare const cmdRm: Command;
7
+ export declare const cmdDone: Command;
8
+ export declare const cmdAppend: Command;
9
+ export declare const cmdSplit: Command;
10
+ export declare const cmdMerge: Command;