quiver-cli 0.5.0 → 0.7.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/LICENSE +21 -0
- package/dist/cli.js +193 -51
- package/package.json +1 -1
- package/template/.agents/skills/agent-browser/SKILL.md +4 -9
- package/template/.agents/skills/apps/skybridge/SKILL.md +1 -1
- package/template/.agents/skills/code/improve/SKILL.md +9 -5
- package/template/.agents/skills/code/improve/references/audit-playbook.md +10 -10
- package/template/.agents/skills/code/improve/references/closing-the-loop.md +4 -3
- package/template/.agents/skills/code/improve/references/plan-template.md +5 -0
- package/template/.agents/skills/design/impeccable/SKILL.md +14 -24
- package/template/.agents/skills/design/impeccable/reference/animate.md +1 -1
- package/template/.agents/skills/design/impeccable/reference/bolder.md +1 -1
- package/template/.agents/skills/design/impeccable/reference/brand.md +2 -2
- package/template/.agents/skills/design/impeccable/reference/colorize.md +1 -1
- package/template/.agents/skills/design/impeccable/reference/critique.md +6 -6
- package/template/.agents/skills/design/impeccable/reference/delight.md +1 -1
- package/template/.agents/skills/design/impeccable/reference/distill.md +1 -1
- package/template/.agents/skills/design/impeccable/reference/document.md +1 -1
- package/template/.agents/skills/design/impeccable/reference/extract.md +1 -1
- package/template/.agents/skills/design/impeccable/reference/hooks.md +90 -0
- package/template/.agents/skills/design/impeccable/reference/init.md +5 -5
- package/template/.agents/skills/design/impeccable/reference/live.md +16 -16
- package/template/.agents/skills/design/impeccable/reference/overdrive.md +1 -1
- package/template/.agents/skills/design/impeccable/reference/polish.md +2 -2
- package/template/.agents/skills/design/impeccable/reference/quieter.md +1 -1
- package/template/.agents/skills/design/impeccable/reference/shape.md +2 -2
- package/template/.agents/skills/design/impeccable/scripts/context-signals.mjs +1 -1
- package/template/.agents/skills/design/impeccable/scripts/context.mjs +724 -33
- package/template/.agents/skills/design/impeccable/scripts/critique-storage.mjs +1 -1
- package/template/.agents/skills/design/impeccable/scripts/detector/browser/injected/index.mjs +204 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/cli/main.mjs +57 -11
- package/template/.agents/skills/design/impeccable/scripts/detector/design-system.mjs +750 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/detect-antipatterns-browser.js +633 -46
- package/template/.agents/skills/design/impeccable/scripts/detector/detect-antipatterns.mjs +7 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/browser/detect-url.mjs +29 -4
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/regex/detect-text.mjs +43 -10
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/static-html/css-cascade.mjs +29 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/static-html/detect-html.mjs +27 -1
- package/template/.agents/skills/design/impeccable/scripts/detector/node/file-system.mjs +1 -1
- package/template/.agents/skills/design/impeccable/scripts/detector/registry/antipatterns.mjs +29 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/rules/checks.mjs +401 -46
- package/template/.agents/skills/design/impeccable/scripts/detector/shared/inline-ignores.mjs +148 -0
- package/template/.agents/skills/design/impeccable/scripts/hook-admin.mjs +661 -0
- package/template/.agents/skills/design/impeccable/scripts/hook-before-edit.mjs +476 -0
- package/template/.agents/skills/design/impeccable/scripts/hook-lib.mjs +1632 -0
- package/template/.agents/skills/design/impeccable/scripts/hook.mjs +61 -0
- package/template/.agents/skills/design/impeccable/scripts/{design-parser.mjs → lib/design-parser.mjs} +8 -1
- package/template/.agents/skills/design/impeccable/scripts/lib/impeccable-config.mjs +638 -0
- package/template/.agents/skills/design/impeccable/scripts/lib/impeccable-paths.mjs +128 -0
- package/template/.agents/skills/design/impeccable/scripts/lib/target-args.mjs +42 -0
- package/template/.agents/skills/design/impeccable/scripts/live/browser-script-parts.mjs +49 -0
- package/template/.agents/skills/design/impeccable/scripts/{live-event-validation.mjs → live/event-validation.mjs} +6 -5
- package/template/.agents/skills/design/impeccable/scripts/live/manual-apply.mjs +939 -0
- package/template/.agents/skills/design/impeccable/scripts/live/manual-edit-routes.mjs +357 -0
- package/template/.agents/skills/design/impeccable/scripts/{live-manual-edits-buffer.mjs → live/manual-edits-buffer.mjs} +1 -1
- package/template/.agents/skills/design/impeccable/scripts/{live-session-store.mjs → live/session-store.mjs} +1 -1
- package/template/.agents/skills/design/impeccable/scripts/{live-ui-core.mjs → live/ui-core.mjs} +2 -1
- package/template/.agents/skills/design/impeccable/scripts/live/vocabulary.mjs +36 -0
- package/template/.agents/skills/design/impeccable/scripts/live-accept.mjs +3 -3
- package/template/.agents/skills/design/impeccable/scripts/live-browser-dom.js +146 -0
- package/template/.agents/skills/design/impeccable/scripts/live-browser.js +1456 -599
- package/template/.agents/skills/design/impeccable/scripts/live-commit-manual-edits.mjs +2 -2
- package/template/.agents/skills/design/impeccable/scripts/live-complete.mjs +2 -2
- package/template/.agents/skills/design/impeccable/scripts/live-discard-manual-edits.mjs +1 -1
- package/template/.agents/skills/design/impeccable/scripts/live-inject.mjs +35 -9
- package/template/.agents/skills/design/impeccable/scripts/live-insert.mjs +2 -2
- package/template/.agents/skills/design/impeccable/scripts/live-manual-edit-evidence.mjs +2 -2
- package/template/.agents/skills/design/impeccable/scripts/live-poll.mjs +18 -13
- package/template/.agents/skills/design/impeccable/scripts/live-resume.mjs +1 -1
- package/template/.agents/skills/design/impeccable/scripts/live-server.mjs +77 -1264
- package/template/.agents/skills/design/impeccable/scripts/live-status.mjs +2 -2
- package/template/.agents/skills/design/impeccable/scripts/live-target.mjs +30 -0
- package/template/.agents/skills/design/impeccable/scripts/live-wrap.mjs +4 -4
- package/template/.agents/skills/design/impeccable/scripts/live.mjs +73 -22
- package/template/.agents/skills/writing/humanizer/SKILL.md +621 -0
- package/template/.agents/upstreams.json +17 -8
- package/template/.agents/skills/apps/skybridge/references/architecture.md +0 -175
- package/template/.agents/skills/apps/skybridge/references/copy-template.md +0 -24
- package/template/.agents/skills/apps/skybridge/references/csp.md +0 -33
- package/template/.agents/skills/apps/skybridge/references/deploy.md +0 -33
- package/template/.agents/skills/apps/skybridge/references/discover.md +0 -84
- package/template/.agents/skills/apps/skybridge/references/download-file.md +0 -77
- package/template/.agents/skills/apps/skybridge/references/fetch-and-render-data.md +0 -151
- package/template/.agents/skills/apps/skybridge/references/oauth.md +0 -115
- package/template/.agents/skills/apps/skybridge/references/open-external-links.md +0 -71
- package/template/.agents/skills/apps/skybridge/references/prompt-llm.md +0 -20
- package/template/.agents/skills/apps/skybridge/references/publish.md +0 -19
- package/template/.agents/skills/apps/skybridge/references/run-locally.md +0 -51
- package/template/.agents/skills/apps/skybridge/references/state-and-context.md +0 -151
- package/template/.agents/skills/apps/skybridge/references/ui-guidelines.md +0 -205
- package/template/.agents/skills/design/impeccable/scripts/cleanup-deprecated.mjs +0 -284
- package/template/.agents/skills/design/impeccable/scripts/impeccable-paths.mjs +0 -126
- /package/template/.agents/commands/{tf-readme.md → terraform-readme.md} +0 -0
- /package/template/.agents/skills/design/impeccable/scripts/{is-generated.mjs → lib/is-generated.mjs} +0 -0
- /package/template/.agents/skills/design/impeccable/scripts/{live-completion.mjs → live/completion.mjs} +0 -0
- /package/template/.agents/skills/design/impeccable/scripts/{live-insert-ui.mjs → live/insert-ui.mjs} +0 -0
- /package/template/.agents/skills/design/impeccable/scripts/{live-svelte-component.mjs → live/svelte-component.mjs} +0 -0
- /package/template/.agents/skills/design/impeccable/scripts/{live-sveltekit-adapter.mjs → live/sveltekit-adapter.mjs} +0 -0
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
import { buildManualEditEvidence } from './live-manual-edit-evidence.mjs';
|
|
19
|
-
import { readBuffer, readBufferStrict, writeBuffer, countByPage } from './live
|
|
20
|
-
import { isGeneratedFile } from './is-generated.mjs';
|
|
19
|
+
import { readBuffer, readBufferStrict, writeBuffer, countByPage } from './live/manual-edits-buffer.mjs';
|
|
20
|
+
import { isGeneratedFile } from './lib/is-generated.mjs';
|
|
21
21
|
import {
|
|
22
22
|
runCopyEditBatchAgent,
|
|
23
23
|
runCopyEditPostApplyChecks,
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* Canonical durable completion acknowledgement for Impeccable live sessions.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { createLiveSessionStore } from './live
|
|
7
|
-
import { readLiveServerInfo } from './impeccable-paths.mjs';
|
|
6
|
+
import { createLiveSessionStore } from './live/session-store.mjs';
|
|
7
|
+
import { readLiveServerInfo } from './lib/impeccable-paths.mjs';
|
|
8
8
|
|
|
9
9
|
function parseArgs(argv) {
|
|
10
10
|
const out = { status: 'complete' };
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* Output JSON: { discarded: N, entries: [...discardedEntries], totalCount: N }
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import { readBuffer, removeEntries, truncateBuffer } from './live
|
|
19
|
+
import { readBuffer, removeEntries, truncateBuffer } from './live/manual-edits-buffer.mjs';
|
|
20
20
|
|
|
21
21
|
function argVal(args, name) {
|
|
22
22
|
const prefix = name + '=';
|
|
@@ -16,12 +16,12 @@
|
|
|
16
16
|
import fs from 'node:fs';
|
|
17
17
|
import path from 'node:path';
|
|
18
18
|
import { fileURLToPath } from 'node:url';
|
|
19
|
-
import { resolveLiveConfigPath } from './impeccable-paths.mjs';
|
|
19
|
+
import { resolveLiveConfigPath } from './lib/impeccable-paths.mjs';
|
|
20
20
|
import {
|
|
21
21
|
applySvelteKitLiveAdapter,
|
|
22
22
|
detectSvelteKitProject,
|
|
23
23
|
removeSvelteKitLiveAdapter,
|
|
24
|
-
} from './live
|
|
24
|
+
} from './live/sveltekit-adapter.mjs';
|
|
25
25
|
|
|
26
26
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
27
27
|
const CONFIG_PATH = resolveLiveConfigPath({ cwd: process.cwd(), scriptsDir: __dirname });
|
|
@@ -32,6 +32,8 @@ const IGNORE_MARKER_CLOSE = '# impeccable-live-ignore-end';
|
|
|
32
32
|
|
|
33
33
|
export const LIVE_IGNORE_PATTERNS = Object.freeze([
|
|
34
34
|
'.impeccable/hook.cache.json',
|
|
35
|
+
'.impeccable/hook.pending.json',
|
|
36
|
+
'.impeccable/config.local.json',
|
|
35
37
|
'.impeccable/live/server.json',
|
|
36
38
|
'.impeccable/live/sessions/',
|
|
37
39
|
'.impeccable/live/previews/',
|
|
@@ -368,8 +370,26 @@ function buildTagBlock(syntax, port, filePath) {
|
|
|
368
370
|
);
|
|
369
371
|
}
|
|
370
372
|
|
|
373
|
+
function detectLineEnding(content) {
|
|
374
|
+
if (content.includes('\r\n')) return '\r\n';
|
|
375
|
+
if (content.includes('\r')) return '\r';
|
|
376
|
+
return '\n';
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
function normalizeLineEndings(content, lineEnding) {
|
|
380
|
+
return lineEnding === '\n' ? content : content.replace(/\n/g, lineEnding);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
function readLineEndingAt(content, index) {
|
|
384
|
+
if (content[index] === '\r' && content[index + 1] === '\n') return '\r\n';
|
|
385
|
+
if (content[index] === '\n') return '\n';
|
|
386
|
+
if (content[index] === '\r') return '\r';
|
|
387
|
+
return '';
|
|
388
|
+
}
|
|
389
|
+
|
|
371
390
|
function insertTag(content, config, port, filePath) {
|
|
372
|
-
const
|
|
391
|
+
const lineEnding = detectLineEnding(content);
|
|
392
|
+
const block = normalizeLineEndings(buildTagBlock(config.commentSyntax, port, filePath), lineEnding);
|
|
373
393
|
// insertBefore: match the LAST occurrence. Anchors like `</body>` naturally
|
|
374
394
|
// belong at the end, and the same literal can appear earlier in code blocks
|
|
375
395
|
// within rendered documentation pages.
|
|
@@ -383,9 +403,15 @@ function insertTag(content, config, port, filePath) {
|
|
|
383
403
|
const idx = content.indexOf(config.insertAfter);
|
|
384
404
|
if (idx === -1) return content;
|
|
385
405
|
const after = idx + config.insertAfter.length;
|
|
386
|
-
// Preserve
|
|
387
|
-
|
|
388
|
-
|
|
406
|
+
// Preserve an existing trailing newline if the anchor already has one.
|
|
407
|
+
// Slice the remainder from the original anchor offset, not prefix.length:
|
|
408
|
+
// in the no-newline case prefix is one char longer than the anchor (the
|
|
409
|
+
// appended '\n'), so slicing by prefix.length would drop the first real
|
|
410
|
+
// character after the anchor (#227).
|
|
411
|
+
const existingNewline = readLineEndingAt(content, after);
|
|
412
|
+
const prefix = content.slice(0, after) + (existingNewline || lineEnding);
|
|
413
|
+
const rest = content.slice(after + existingNewline.length);
|
|
414
|
+
return prefix + block + rest;
|
|
389
415
|
}
|
|
390
416
|
|
|
391
417
|
/**
|
|
@@ -401,8 +427,8 @@ function insertTag(content, config, port, filePath) {
|
|
|
401
427
|
*/
|
|
402
428
|
function removeTag(content, _syntax) {
|
|
403
429
|
const patterns = [
|
|
404
|
-
/([ \t]*)<!--\s*impeccable-live-start\s*-->[\s\S]*?<!--\s*impeccable-live-end\s*-->([ \t]*(?:\n|$)?)/,
|
|
405
|
-
/([ \t]*)\{\/\*\s*impeccable-live-start\s*\*\/\}[\s\S]*?\{\/\*\s*impeccable-live-end\s*\*\/\}([ \t]*(?:\n|$)?)/,
|
|
430
|
+
/([ \t]*)<!--\s*impeccable-live-start\s*-->[\s\S]*?<!--\s*impeccable-live-end\s*-->([ \t]*(?:\r\n|\n|\r|$)?)/,
|
|
431
|
+
/([ \t]*)\{\/\*\s*impeccable-live-start\s*\*\/\}[\s\S]*?\{\/\*\s*impeccable-live-end\s*\*\/\}([ \t]*(?:\r\n|\n|\r|$)?)/,
|
|
406
432
|
];
|
|
407
433
|
for (const pat of patterns) {
|
|
408
434
|
let changed = false;
|
|
@@ -410,7 +436,7 @@ function removeTag(content, _syntax) {
|
|
|
410
436
|
do {
|
|
411
437
|
content = next;
|
|
412
438
|
next = content.replace(pat, (_match, leadingIndent, trailing = '') => {
|
|
413
|
-
if (
|
|
439
|
+
if (/[\r\n]/.test(trailing)) return leadingIndent;
|
|
414
440
|
return leadingIndent || trailing || '';
|
|
415
441
|
});
|
|
416
442
|
if (next !== content) changed = true;
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
import fs from 'node:fs';
|
|
11
11
|
import path from 'node:path';
|
|
12
|
-
import { isGeneratedFile } from './is-generated.mjs';
|
|
12
|
+
import { isGeneratedFile } from './lib/is-generated.mjs';
|
|
13
13
|
import {
|
|
14
14
|
buildSearchQueries,
|
|
15
15
|
findElement,
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
buildSvelteComponentCssAuthoring,
|
|
26
26
|
scaffoldSvelteComponentInsertSession,
|
|
27
27
|
shouldUseSvelteComponentInjection,
|
|
28
|
-
} from './live
|
|
28
|
+
} from './live/svelte-component.mjs';
|
|
29
29
|
|
|
30
30
|
const INSERT_POSITIONS = new Set(['before', 'after']);
|
|
31
31
|
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
|
|
11
11
|
import fs from 'node:fs';
|
|
12
12
|
import path from 'node:path';
|
|
13
|
-
import { isGeneratedFile } from './is-generated.mjs';
|
|
14
|
-
import { readBuffer, getBufferPath } from './live
|
|
13
|
+
import { isGeneratedFile } from './lib/is-generated.mjs';
|
|
14
|
+
import { readBuffer, getBufferPath } from './live/manual-edits-buffer.mjs';
|
|
15
15
|
|
|
16
16
|
const EVIDENCE_VERSION = 1;
|
|
17
17
|
const TEXT_EXTENSIONS = new Set(['.html', '.jsx', '.tsx', '.vue', '.svelte', '.astro', '.js', '.mjs', '.ts']);
|
|
@@ -2,18 +2,23 @@
|
|
|
2
2
|
* CLI client for the live variant mode poll/reply protocol.
|
|
3
3
|
*
|
|
4
4
|
* Usage:
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* node <scripts_path>/live-poll.mjs # Block until browser event, print JSON
|
|
6
|
+
* node <scripts_path>/live-poll.mjs --stream # Experimental: keep polling; one JSON line per event
|
|
7
|
+
* node <scripts_path>/live-poll.mjs --timeout=600000 # Custom timeout (ms); default is long-poll friendly
|
|
8
|
+
* node <scripts_path>/live-poll.mjs --reply <id> done # Reply "done" to event <id>
|
|
9
|
+
* node <scripts_path>/live-poll.mjs --reply <id> error "msg" # Reply with error
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import { execFileSync } from 'node:child_process';
|
|
13
13
|
import path from 'node:path';
|
|
14
14
|
import { fileURLToPath } from 'node:url';
|
|
15
|
-
import { completionAckForAcceptResult, completionTypeForAcceptResult } from './live
|
|
16
|
-
import { readLiveServerInfo } from './impeccable-paths.mjs';
|
|
15
|
+
import { completionAckForAcceptResult, completionTypeForAcceptResult } from './live/completion.mjs';
|
|
16
|
+
import { readLiveServerInfo } from './lib/impeccable-paths.mjs';
|
|
17
|
+
|
|
18
|
+
// Absolute path to a sibling script in this skill's scripts dir, so runtime
|
|
19
|
+
// error hints print a directly-runnable command instead of a placeholder.
|
|
20
|
+
const SELF_DIR = path.dirname(fileURLToPath(import.meta.url));
|
|
21
|
+
const scriptCmd = (name) => `node "${path.join(SELF_DIR, name)}"`;
|
|
17
22
|
|
|
18
23
|
// Node's built-in fetch (undici under the hood) enforces a 300s headers
|
|
19
24
|
// timeout that can't be lowered per-request. We cap each request below
|
|
@@ -27,7 +32,7 @@ const EVENT_TYPES_NEEDING_AGENT_REPLY = new Set(['generate', 'steer', 'manual_ed
|
|
|
27
32
|
function readServerInfo() {
|
|
28
33
|
const record = readLiveServerInfo(process.cwd());
|
|
29
34
|
if (!record) {
|
|
30
|
-
console.error(
|
|
35
|
+
console.error(`No running live server found. Start one with: ${scriptCmd('live.mjs')}`);
|
|
31
36
|
process.exit(1);
|
|
32
37
|
}
|
|
33
38
|
return record.info;
|
|
@@ -82,7 +87,7 @@ export function parseReplyArgs(args) {
|
|
|
82
87
|
}
|
|
83
88
|
|
|
84
89
|
function validateReplyArgs({ id, status }) {
|
|
85
|
-
const usage =
|
|
90
|
+
const usage = `Usage: ${scriptCmd('live-poll.mjs')} --reply <id> <status> [--file path] [--data '<json>'] [message]`;
|
|
86
91
|
if (!id || id.startsWith('--')) {
|
|
87
92
|
const err = new Error(`${usage}\nMissing event id after --reply.`);
|
|
88
93
|
err.code = 'INVALID_REPLY_ARGS';
|
|
@@ -283,11 +288,11 @@ export async function runPollStream(base, token, {
|
|
|
283
288
|
function handlePollError(err) {
|
|
284
289
|
if (err.code === 'AUTH_FAILED') {
|
|
285
290
|
console.error(err.message);
|
|
286
|
-
console.error(
|
|
291
|
+
console.error(`Try restarting: ${scriptCmd('live-server.mjs')} stop && ${scriptCmd('live.mjs')}`);
|
|
287
292
|
process.exit(1);
|
|
288
293
|
}
|
|
289
294
|
if (err.cause?.code === 'ECONNREFUSED') {
|
|
290
|
-
console.error(
|
|
295
|
+
console.error(`Live server not running. Start one with: ${scriptCmd('live.mjs')}`);
|
|
291
296
|
process.exit(1);
|
|
292
297
|
}
|
|
293
298
|
if (err.code === 'ACK_TIMEOUT') {
|
|
@@ -331,7 +336,7 @@ Harness note:
|
|
|
331
336
|
const info = readServerInfo();
|
|
332
337
|
const base = `http://localhost:${info.port}`;
|
|
333
338
|
|
|
334
|
-
// Reply mode:
|
|
339
|
+
// Reply mode: node <scripts_path>/live-poll.mjs --reply <id> <status> [--file path] [--data '<json>'] [message]
|
|
335
340
|
if (args.includes('--reply')) {
|
|
336
341
|
let reply;
|
|
337
342
|
try {
|
|
@@ -345,7 +350,7 @@ Harness note:
|
|
|
345
350
|
await postReply(base, info.token, reply);
|
|
346
351
|
} catch (err) {
|
|
347
352
|
if (err.cause?.code === 'ECONNREFUSED') {
|
|
348
|
-
console.error(
|
|
353
|
+
console.error(`Live server not running. Start one with: ${scriptCmd('live.mjs')}`);
|
|
349
354
|
} else {
|
|
350
355
|
console.error('Reply failed:', err.message);
|
|
351
356
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Recover the next agent action from the durable live-session journal.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { createLiveSessionStore } from './live
|
|
6
|
+
import { createLiveSessionStore } from './live/session-store.mjs';
|
|
7
7
|
|
|
8
8
|
function manualApplyReplyCommand(eventOrId = 'EVENT_ID') {
|
|
9
9
|
const id = typeof eventOrId === 'string' ? eventOrId : eventOrId?.id || 'EVENT_ID';
|