@neta-art/cohub-cli 6.8.2 → 6.9.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.
- package/dist/commands/board-domain.js +2 -0
- package/dist/commands/boards/appearance.js +31 -0
- package/dist/commands/boards/examples.js +19 -1
- package/dist/commands/boards/transactions.d.ts +12 -0
- package/dist/commands/boards/transactions.js +69 -0
- package/dist/commands/desktop.d.ts +7 -0
- package/dist/commands/desktop.js +22 -0
- package/package.json +2 -2
|
@@ -4,6 +4,7 @@ import { registerBoardExampleCommands } from "./boards/examples.js";
|
|
|
4
4
|
import { registerBoardBatchCommand } from "./boards/batch.js";
|
|
5
5
|
import { registerBoardConnectionCommands } from "./boards/connections.js";
|
|
6
6
|
import { registerBoardItemCommands } from "./boards/items.js";
|
|
7
|
+
import { registerBoardTransactionCommands } from "./boards/transactions.js";
|
|
7
8
|
export function registerBoardDomainCommands(boards) {
|
|
8
9
|
registerBoardExampleCommands(boards);
|
|
9
10
|
registerBoardAppearanceCommands(boards);
|
|
@@ -11,4 +12,5 @@ export function registerBoardDomainCommands(boards) {
|
|
|
11
12
|
registerBoardConnectionCommands(boards);
|
|
12
13
|
registerBoardItemCommands(boards);
|
|
13
14
|
registerBoardAnimationCommands(boards);
|
|
15
|
+
registerBoardTransactionCommands(boards);
|
|
14
16
|
}
|
|
@@ -65,6 +65,37 @@ Examples:
|
|
|
65
65
|
handleHttp(cause);
|
|
66
66
|
}
|
|
67
67
|
});
|
|
68
|
+
withJson(boards.command("motion <board>")
|
|
69
|
+
.description("Configure the default Board motion for newly added nodes")
|
|
70
|
+
.option("--preset <preset>", "Enter motion preset (deal)")
|
|
71
|
+
.option("--clear", "Disable the default enter motion")
|
|
72
|
+
.addHelpText("after", `
|
|
73
|
+
Examples:
|
|
74
|
+
cohub boards motion plan.board --preset deal
|
|
75
|
+
cohub boards motion plan.board --clear`))
|
|
76
|
+
.action(async (target, options) => {
|
|
77
|
+
try {
|
|
78
|
+
if (Boolean(options.clear) === Boolean(options.preset))
|
|
79
|
+
throw new Error("Use --preset or --clear");
|
|
80
|
+
if (options.preset && options.preset !== "deal")
|
|
81
|
+
throw new Error("--preset must be deal");
|
|
82
|
+
const board = await resolvedBoard(boards, target);
|
|
83
|
+
const current = await board.summary();
|
|
84
|
+
const appearance = appearanceFrom(current.board.metadata);
|
|
85
|
+
const next = patchBoardAppearance(appearance, {
|
|
86
|
+
motion: options.clear
|
|
87
|
+
? undefined
|
|
88
|
+
: { enter: { kind: "effects.deal", kindVersion: 1, params: {} } },
|
|
89
|
+
});
|
|
90
|
+
showUpdated(await mutateSemantic(board, [{
|
|
91
|
+
type: "board.patch",
|
|
92
|
+
patch: { metadataPatch: { appearance: next } },
|
|
93
|
+
}], { baseVersion: current.board.version }), options);
|
|
94
|
+
}
|
|
95
|
+
catch (cause) {
|
|
96
|
+
handleHttp(cause);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
68
99
|
withJson(boards.command("playback-policy <board>")
|
|
69
100
|
.description("Configure automatic Board playback")
|
|
70
101
|
.option("--composition <id>", "Composition to play")
|
|
@@ -269,6 +269,23 @@ const templates = {
|
|
|
269
269
|
seed: "float-hero",
|
|
270
270
|
params: { distance: 8, period: 2200 },
|
|
271
271
|
},
|
|
272
|
+
"effect:deal": {
|
|
273
|
+
id: "deal-title",
|
|
274
|
+
target: { type: "item", itemId: "title" },
|
|
275
|
+
kind: "effects.deal",
|
|
276
|
+
kindVersion: 1,
|
|
277
|
+
lifecycle: "on-enter",
|
|
278
|
+
timeOrigin: "activation",
|
|
279
|
+
seed: "deal-title",
|
|
280
|
+
params: {},
|
|
281
|
+
},
|
|
282
|
+
"motion:enter-deal": {
|
|
283
|
+
enter: {
|
|
284
|
+
kind: "effects.deal",
|
|
285
|
+
kindVersion: 1,
|
|
286
|
+
params: {},
|
|
287
|
+
},
|
|
288
|
+
},
|
|
272
289
|
"composition:fade": {
|
|
273
290
|
id: "intro",
|
|
274
291
|
name: "Intro",
|
|
@@ -392,7 +409,8 @@ Kinds:
|
|
|
392
409
|
create [workflow|media|animation]
|
|
393
410
|
batch basic
|
|
394
411
|
item text|image|video|audio|file|task|geo|frame|draw|arrow
|
|
395
|
-
effect pulse|float
|
|
412
|
+
effect pulse|float|deal
|
|
413
|
+
motion enter-deal
|
|
396
414
|
composition fade|reveal|draw-reveal|motion-path|trail|impact|flash|particles|camera-shake|camera-focus
|
|
397
415
|
|
|
398
416
|
Examples:
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { BoardTransactionRecord } from "@neta-art/cohub";
|
|
2
|
+
import type { Command } from "commander";
|
|
3
|
+
/** Compact `type×count` summary, e.g. `node.patch×3 connection.create`. */
|
|
4
|
+
export declare function summarizeOperations(operations: BoardTransactionRecord["operations"]): string;
|
|
5
|
+
export declare function transactionRows(transactions: BoardTransactionRecord[]): {
|
|
6
|
+
version: number;
|
|
7
|
+
createdAt: string;
|
|
8
|
+
actor: string;
|
|
9
|
+
via: import("@neta-art/cohub/board").BoardReplayActorKind;
|
|
10
|
+
changes: string;
|
|
11
|
+
}[];
|
|
12
|
+
export declare function registerBoardTransactionCommands(boards: Command): void;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { boardReplayActorKind } from "@neta-art/cohub/board";
|
|
2
|
+
import { handleHttp, json, jsonRequested, table } from "../../output.js";
|
|
3
|
+
import { finite, resolvedBoard, withJson } from "./context.js";
|
|
4
|
+
const columns = [
|
|
5
|
+
{ key: "version", label: "VERSION" },
|
|
6
|
+
{ key: "createdAt", label: "AT" },
|
|
7
|
+
{ key: "actor", label: "ACTOR" },
|
|
8
|
+
{ key: "via", label: "VIA" },
|
|
9
|
+
{ key: "changes", label: "CHANGES" },
|
|
10
|
+
];
|
|
11
|
+
/** Compact `type×count` summary, e.g. `node.patch×3 connection.create`. */
|
|
12
|
+
export function summarizeOperations(operations) {
|
|
13
|
+
const counts = new Map();
|
|
14
|
+
for (const operation of operations)
|
|
15
|
+
counts.set(operation.type, (counts.get(operation.type) ?? 0) + 1);
|
|
16
|
+
return [...counts.entries()].map(([type, count]) => (count > 1 ? `${type}×${count}` : type)).join(" ");
|
|
17
|
+
}
|
|
18
|
+
export function transactionRows(transactions) {
|
|
19
|
+
return transactions.map((transaction) => ({
|
|
20
|
+
version: transaction.version,
|
|
21
|
+
createdAt: transaction.createdAt,
|
|
22
|
+
actor: transaction.actorId,
|
|
23
|
+
via: boardReplayActorKind(transaction.source),
|
|
24
|
+
changes: summarizeOperations(transaction.operations),
|
|
25
|
+
}));
|
|
26
|
+
}
|
|
27
|
+
export function registerBoardTransactionCommands(boards) {
|
|
28
|
+
withJson(boards
|
|
29
|
+
.command("transactions <board>")
|
|
30
|
+
.alias("history")
|
|
31
|
+
.description("List the Board transaction log, newest first")
|
|
32
|
+
.option("--before <version>", "Only transactions below this version")
|
|
33
|
+
.option("--limit <count>", "Page size (max 500)", "50")
|
|
34
|
+
.option("--operations", "Include full operations and inverses in --json output")
|
|
35
|
+
.addHelpText("after", `
|
|
36
|
+
Every applied mutation is one transaction. --json prints the page summary; add
|
|
37
|
+
--operations for the full payloads, inverses and (on the newest page) the current
|
|
38
|
+
node and connection rows, which is what the web replay view consumes.`)).action(async (target, options) => {
|
|
39
|
+
try {
|
|
40
|
+
const board = await resolvedBoard(boards, target);
|
|
41
|
+
// The snapshot is only ever printed in full --json --operations output;
|
|
42
|
+
// every other mode would fetch the whole Board just to drop it.
|
|
43
|
+
const full = jsonRequested(options) && Boolean(options.operations);
|
|
44
|
+
const page = await board.transactions({
|
|
45
|
+
...(options.before !== undefined ? { before: finite(options.before, "--before") } : {}),
|
|
46
|
+
limit: finite(options.limit, "--limit", 50),
|
|
47
|
+
snapshot: full,
|
|
48
|
+
});
|
|
49
|
+
if (jsonRequested(options)) {
|
|
50
|
+
return json(full
|
|
51
|
+
? page
|
|
52
|
+
: {
|
|
53
|
+
...page,
|
|
54
|
+
transactions: page.transactions.map(({ operations, ...transaction }) => ({
|
|
55
|
+
...transaction,
|
|
56
|
+
operationCount: operations.length,
|
|
57
|
+
})),
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
table(transactionRows(page.transactions), columns);
|
|
61
|
+
if (page.nextBefore !== null) {
|
|
62
|
+
console.log(`\nOlder transactions: --before ${page.nextBefore}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch (cause) {
|
|
66
|
+
handleHttp(cause);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
import { type DesktopSurface } from "@neta-art/cohub";
|
|
1
2
|
import type { Command } from "commander";
|
|
3
|
+
/**
|
|
4
|
+
* The surface a desktop.open should request: an explicit `--as` wins, then
|
|
5
|
+
* whatever the App declared at publish time. `window` is the implicit default
|
|
6
|
+
* and yields `undefined` so the command stays compact.
|
|
7
|
+
*/
|
|
8
|
+
export declare function resolveOpenSurface(requested: string | undefined, declared: unknown): DesktopSurface | undefined;
|
|
2
9
|
export declare function registerDesktop(program: Command): void;
|
|
3
10
|
export declare function registerLegacyUi(program: Command): void;
|
package/dist/commands/desktop.js
CHANGED
|
@@ -65,10 +65,19 @@ function parseTimeout(value) {
|
|
|
65
65
|
}
|
|
66
66
|
return parsed;
|
|
67
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* The surface a desktop.open should request: an explicit `--as` wins, then
|
|
70
|
+
* whatever the App declared at publish time. `window` is the implicit default
|
|
71
|
+
* and yields `undefined` so the command stays compact.
|
|
72
|
+
*/
|
|
73
|
+
export function resolveOpenSurface(requested, declared) {
|
|
74
|
+
return (requested ?? declared) === "overlay" ? "overlay" : undefined;
|
|
75
|
+
}
|
|
68
76
|
async function resolveAppTarget(client, ref) {
|
|
69
77
|
const normalized = hasAppScheme(ref) ? ref.replace(/^[a-zA-Z]+:\/\//, "") : ref;
|
|
70
78
|
const parsed = parseAppRef(normalized);
|
|
71
79
|
const detail = await getAppByRef(client, normalized);
|
|
80
|
+
const declared = detail.app.meta?.presentation?.surface;
|
|
72
81
|
return {
|
|
73
82
|
kind: "app",
|
|
74
83
|
appId: detail.app.id,
|
|
@@ -77,6 +86,7 @@ async function resolveAppTarget(client, ref) {
|
|
|
77
86
|
...(parsed.search ? { search: parsed.search } : {}),
|
|
78
87
|
...(parsed.hash ? { hash: parsed.hash } : {}),
|
|
79
88
|
},
|
|
89
|
+
...(declared === "overlay" || declared === "window" ? { surface: declared } : {}),
|
|
80
90
|
};
|
|
81
91
|
}
|
|
82
92
|
async function resolveOpenTarget(client, command, value) {
|
|
@@ -122,6 +132,9 @@ async function openWindow(target, opts, command) {
|
|
|
122
132
|
if (opts.noWait && opts.timeoutMs !== undefined) {
|
|
123
133
|
return error("Conflicting wait options", "Use either --no-wait or --timeout-ms, not both.");
|
|
124
134
|
}
|
|
135
|
+
if (opts.as !== undefined && opts.as !== "window" && opts.as !== "overlay") {
|
|
136
|
+
return error("Invalid surface", "--as must be one of: window, overlay.");
|
|
137
|
+
}
|
|
125
138
|
const timeoutMs = parseTimeout(opts.timeoutMs);
|
|
126
139
|
const client = createClient();
|
|
127
140
|
try {
|
|
@@ -129,6 +142,9 @@ async function openWindow(target, opts, command) {
|
|
|
129
142
|
if (resolved.kind === "file" && opts.call) {
|
|
130
143
|
return error("Unsupported option", "--call only applies to app targets.");
|
|
131
144
|
}
|
|
145
|
+
if (resolved.kind === "file" && opts.as) {
|
|
146
|
+
return error("Unsupported option", "--as only applies to app targets.");
|
|
147
|
+
}
|
|
132
148
|
const call = opts.call
|
|
133
149
|
? { method: opts.call, ...(callInput === undefined ? {} : { input: callInput }) }
|
|
134
150
|
: undefined;
|
|
@@ -142,6 +158,7 @@ async function openWindow(target, opts, command) {
|
|
|
142
158
|
appId: resolved.appId,
|
|
143
159
|
label: resolved.label,
|
|
144
160
|
...(resolved.launch.search || resolved.launch.hash ? { launch: resolved.launch } : {}),
|
|
161
|
+
...(resolveOpenSurface(opts.as, resolved.surface) ? { surface: "overlay" } : {}),
|
|
145
162
|
},
|
|
146
163
|
...(call ? { call } : {}),
|
|
147
164
|
},
|
|
@@ -173,6 +190,7 @@ Examples:
|
|
|
173
190
|
cohub desktop open app://alice/studio/launch
|
|
174
191
|
cohub desktop open alice/studio/launch
|
|
175
192
|
cohub desktop open https://cohub.live/alice/studio/w/launch?view=timeline
|
|
193
|
+
cohub desktop open <app-id> --as overlay
|
|
176
194
|
cohub desktop open <app-id> --call selection.get
|
|
177
195
|
cohub desktop open <app-id> --call board.focus --data '{"nodeId":"n1"}'
|
|
178
196
|
`;
|
|
@@ -182,6 +200,9 @@ Notes:
|
|
|
182
200
|
scheme is still accepted.
|
|
183
201
|
- A plain target checks the current Space for a file before resolving an app.
|
|
184
202
|
- Opening a window is idempotent; repeating it re-activates the same tab.
|
|
203
|
+
- --as picks the surface: window (a preview tab) or overlay (a transparent
|
|
204
|
+
layer above the workspace). Without it, an App published with
|
|
205
|
+
<meta name="cohub:surface" content="overlay"> opens as an overlay.
|
|
185
206
|
- --call waits for the app to announce readiness, then invokes the method.
|
|
186
207
|
- Which methods exist is up to the app author.
|
|
187
208
|
`;
|
|
@@ -195,6 +216,7 @@ function registerOpen(parent, deprecated) {
|
|
|
195
216
|
.option("--client <clientId>", "Target a specific desktop instance of your account")
|
|
196
217
|
.option("--command-id <id>", "Stable id so retries never dispatch twice")
|
|
197
218
|
.option("--no-wait", "Dispatch the command and exit without waiting for a result")
|
|
219
|
+
.option("--as <surface>", "Surface role for app targets: window (default) or overlay")
|
|
198
220
|
.option("--timeout-ms <ms>", `How long to wait for the desktop (default: ${DESKTOP_COMMAND_DEFAULT_TIMEOUT_MS}; max: ${DESKTOP_COMMAND_MAX_TIMEOUT_MS})`)
|
|
199
221
|
.option("--json", "Output as JSON")
|
|
200
222
|
.action(async (target, opts, thisCommand) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neta-art/cohub-cli",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.9.0",
|
|
4
4
|
"description": "CLI for Cohub — spaces, sessions, and agent collaboration.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"commander": "^15.0.0",
|
|
20
20
|
"pixi.js": "^8.20.1",
|
|
21
21
|
"sharp": "^0.35.4",
|
|
22
|
-
"@neta-art/cohub": "8.
|
|
22
|
+
"@neta-art/cohub": "8.12.0"
|
|
23
23
|
},
|
|
24
24
|
"publishConfig": {
|
|
25
25
|
"access": "public"
|