quiver-cli 0.8.0 → 1.0.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/README.md +110 -45
- package/bin/quiver-cli.mjs +3 -1
- package/dist/cli.js +546 -458
- package/package.json +2 -2
- package/template/.agents/AGENTS.md +4 -3
- package/template/.agents/config.json +7 -0
- package/template/.agents/plugins/opencode/rtk.ts +34 -0
- package/template/.agents/skills/agent-browser/SKILL.md +1 -0
- package/template/.agents/skills/apps/skybridge/SKILL.md +4 -0
- package/template/.agents/skills/design/impeccable/SKILL.md +36 -118
- package/template/.agents/skills/design/impeccable/reference/adapt.md +1 -0
- package/template/.agents/skills/design/impeccable/reference/adapt.native.md +58 -0
- package/template/.agents/skills/design/impeccable/reference/android.md +40 -0
- package/template/.agents/skills/design/impeccable/reference/animate.md +73 -188
- package/template/.agents/skills/design/impeccable/reference/audit.md +12 -9
- package/template/.agents/skills/design/impeccable/reference/audit.native.md +139 -0
- package/template/.agents/skills/design/impeccable/reference/bolder.md +19 -101
- package/template/.agents/skills/design/impeccable/reference/clarify.md +59 -253
- package/template/.agents/skills/design/impeccable/reference/colorize.md +51 -222
- package/template/.agents/skills/design/impeccable/reference/craft-floor.md +42 -0
- package/template/.agents/skills/design/impeccable/reference/craft.md +3 -121
- package/template/.agents/skills/design/impeccable/reference/critique.md +44 -23
- package/template/.agents/skills/design/impeccable/reference/degraded/asset-producer.md +90 -0
- package/template/.agents/skills/design/impeccable/reference/degraded/documenter.md +24 -0
- package/template/.agents/skills/design/impeccable/reference/degraded/finish-reviewer.md +37 -0
- package/template/.agents/skills/design/impeccable/reference/degraded/manual-edit-applier.md +92 -0
- package/template/.agents/skills/design/impeccable/reference/delight.md +47 -279
- package/template/.agents/skills/design/impeccable/reference/distill.md +2 -2
- package/template/.agents/skills/design/impeccable/reference/doctor.md +53 -0
- package/template/.agents/skills/design/impeccable/reference/document.md +60 -73
- package/template/.agents/skills/design/impeccable/reference/harden.md +1 -12
- package/template/.agents/skills/design/impeccable/reference/hooks.md +20 -5
- package/template/.agents/skills/design/impeccable/reference/init.md +72 -119
- package/template/.agents/skills/design/impeccable/reference/ios.md +45 -0
- package/template/.agents/skills/design/impeccable/reference/layout.md +54 -131
- package/template/.agents/skills/design/impeccable/reference/live-setup.md +102 -0
- package/template/.agents/skills/design/impeccable/reference/live.md +116 -511
- package/template/.agents/skills/design/impeccable/reference/new-work.md +105 -0
- package/template/.agents/skills/design/impeccable/reference/{product.md → operate.md} +6 -5
- package/template/.agents/skills/design/impeccable/reference/optimize.md +4 -4
- package/template/.agents/skills/design/impeccable/reference/overdrive.md +1 -4
- package/template/.agents/skills/design/impeccable/reference/polish.md +68 -212
- package/template/.agents/skills/design/impeccable/reference/quieter.md +3 -3
- package/template/.agents/skills/design/impeccable/reference/routing.md +18 -0
- package/template/.agents/skills/design/impeccable/reference/shape.md +38 -144
- package/template/.agents/skills/design/impeccable/reference/typeset.md +51 -250
- package/template/.agents/skills/design/impeccable/reference/visualize.md +47 -0
- package/template/.agents/skills/design/impeccable/scripts/command-metadata.json +1 -1
- package/template/.agents/skills/design/impeccable/scripts/concept-seed.mjs +558 -0
- package/template/.agents/skills/design/impeccable/scripts/context-signals.mjs +119 -10
- package/template/.agents/skills/design/impeccable/scripts/context.mjs +534 -45
- package/template/.agents/skills/design/impeccable/scripts/critique-storage.mjs +18 -47
- package/template/.agents/skills/design/impeccable/scripts/detector/browser/injected/index.mjs +96 -10
- package/template/.agents/skills/design/impeccable/scripts/detector/cli/main.mjs +174 -26
- package/template/.agents/skills/design/impeccable/scripts/detector/design-system.mjs +233 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/detect-antipatterns-browser.js +3348 -203
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/browser/detect-url.mjs +102 -7
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/regex/detect-text.mjs +297 -97
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/static-html/css-cascade.mjs +187 -16
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/static-html/detect-html.mjs +41 -11
- package/template/.agents/skills/design/impeccable/scripts/detector/findings.mjs +7 -1
- package/template/.agents/skills/design/impeccable/scripts/detector/node/file-system.mjs +16 -2
- package/template/.agents/skills/design/impeccable/scripts/detector/registry/antipatterns.mjs +207 -38
- package/template/.agents/skills/design/impeccable/scripts/detector/rules/checks.mjs +3082 -173
- package/template/.agents/skills/design/impeccable/scripts/detector/shared/constants.mjs +11 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/shared/fonts.mjs +30 -0
- package/template/.agents/skills/design/impeccable/scripts/doctor.mjs +336 -0
- package/template/.agents/skills/design/impeccable/scripts/embed-prompt.mjs +133 -0
- package/template/.agents/skills/design/impeccable/scripts/generate-image.mjs +240 -0
- package/template/.agents/skills/design/impeccable/scripts/hook-admin.mjs +98 -18
- package/template/.agents/skills/design/impeccable/scripts/hook-before-edit.mjs +46 -6
- package/template/.agents/skills/design/impeccable/scripts/hook-lib.mjs +518 -50
- package/template/.agents/skills/design/impeccable/scripts/hook.mjs +25 -8
- package/template/.agents/skills/design/impeccable/scripts/lib/artifact-schema.mjs +93 -0
- package/template/.agents/skills/design/impeccable/scripts/lib/composition-catalog.mjs +200 -0
- package/template/.agents/skills/design/impeccable/scripts/lib/concept-catalog.mjs +357 -0
- package/template/.agents/skills/design/impeccable/scripts/lib/impeccable-config.mjs +27 -7
- package/template/.agents/skills/design/impeccable/scripts/lib/impeccable-paths.mjs +17 -8
- package/template/.agents/skills/design/impeccable/scripts/lib/provider.mjs +5 -0
- package/template/.agents/skills/design/impeccable/scripts/lib/roll-selection.mjs +362 -0
- package/template/.agents/skills/design/impeccable/scripts/lib/staleness-deep.mjs +457 -0
- package/template/.agents/skills/design/impeccable/scripts/lib/staleness-notice.mjs +169 -0
- package/template/.agents/skills/design/impeccable/scripts/lib/staleness.mjs +457 -0
- package/template/.agents/skills/design/impeccable/scripts/lib/surface-briefs.mjs +151 -0
- package/template/.agents/skills/design/impeccable/scripts/lib/target-slug.mjs +33 -0
- package/template/.agents/skills/design/impeccable/scripts/lib/template-extensions.mjs +146 -0
- package/template/.agents/skills/design/impeccable/scripts/live/accept-css.mjs +617 -0
- package/template/.agents/skills/design/impeccable/scripts/live/accept-verify.mjs +60 -0
- package/template/.agents/skills/design/impeccable/scripts/live/browser-script-parts.mjs +7 -1
- package/template/.agents/skills/design/impeccable/scripts/live/completion.mjs +10 -1
- package/template/.agents/skills/design/impeccable/scripts/live/event-validation.mjs +67 -5
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/astro.mjs +47 -0
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/detect-utils.mjs +73 -0
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/index.mjs +143 -0
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/journal.mjs +197 -0
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/nextjs.mjs +49 -0
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/nuxt.mjs +161 -0
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/script-src.mjs +17 -0
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/static-html.mjs +26 -0
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/sveltekit.mjs +71 -0
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/tag-strategy.mjs +247 -0
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/tanstack-start.mjs +70 -0
- package/template/.agents/skills/design/impeccable/scripts/live/frameworks/vite-generic.mjs +42 -0
- package/template/.agents/skills/design/impeccable/scripts/live/generation-preflight.mjs +149 -0
- package/template/.agents/skills/design/impeccable/scripts/live/instructions.mjs +142 -0
- package/template/.agents/skills/design/impeccable/scripts/live/poll-lanes.mjs +14 -0
- package/template/.agents/skills/design/impeccable/scripts/live/roots.mjs +508 -0
- package/template/.agents/skills/design/impeccable/scripts/live/session-store.mjs +324 -50
- package/template/.agents/skills/design/impeccable/scripts/live/source-lock.mjs +105 -0
- package/template/.agents/skills/design/impeccable/scripts/live/source-search.mjs +105 -0
- package/template/.agents/skills/design/impeccable/scripts/live/svelte-ast.mjs +961 -0
- package/template/.agents/skills/design/impeccable/scripts/live/svelte-component.mjs +588 -72
- package/template/.agents/skills/design/impeccable/scripts/live/sveltekit-adapter.mjs +59 -17
- package/template/.agents/skills/design/impeccable/scripts/live/tanstack-adapter.mjs +280 -0
- package/template/.agents/skills/design/impeccable/scripts/live/vocabulary.mjs +135 -0
- package/template/.agents/skills/design/impeccable/scripts/live-accept.mjs +210 -68
- package/template/.agents/skills/design/impeccable/scripts/live-browser.js +1562 -223
- package/template/.agents/skills/design/impeccable/scripts/live-commit-manual-edits.mjs +3 -0
- package/template/.agents/skills/design/impeccable/scripts/live-complete.mjs +33 -1
- package/template/.agents/skills/design/impeccable/scripts/live-inject.mjs +175 -255
- package/template/.agents/skills/design/impeccable/scripts/live-insert.mjs +26 -6
- package/template/.agents/skills/design/impeccable/scripts/live-manual-edit-evidence.mjs +6 -1
- package/template/.agents/skills/design/impeccable/scripts/live-poll.mjs +61 -16
- package/template/.agents/skills/design/impeccable/scripts/live-resume.mjs +39 -10
- package/template/.agents/skills/design/impeccable/scripts/live-server.mjs +573 -47
- package/template/.agents/skills/design/impeccable/scripts/live-status.mjs +17 -7
- package/template/.agents/skills/design/impeccable/scripts/live-wrap.mjs +124 -91
- package/template/.agents/skills/design/impeccable/scripts/live.mjs +88 -26
- package/template/.agents/skills/design/impeccable/scripts/palette.mjs +76 -81
- package/template/.agents/skills/design/impeccable/scripts/pin.mjs +18 -11
- package/template/.agents/skills/design/impeccable/scripts/serve-question.mjs +932 -0
- package/template/.agents/skills/design/impeccable/scripts/surface-brief.mjs +74 -0
- package/template/.agents/skills/design/shadcn/SKILL.md +46 -11
- package/template/.agents/skills/design/shadcn/cli.md +49 -16
- package/template/.agents/skills/design/shadcn/customization.md +14 -7
- package/template/.agents/skills/design/shadcn/evals/evals.json +30 -0
- package/template/.agents/skills/design/shadcn/mcp.md +27 -16
- package/template/.agents/skills/design/shadcn/registry.md +277 -0
- package/template/.agents/skills/design/shadcn/rules/chat.md +224 -0
- package/template/.agents/skills/design/shadcn/rules/composition.md +20 -2
- package/template/.agents/skills/design/shadcn/rules/styling.md +23 -0
- package/template/.agents/skills/find-skills/SKILL.md +2 -3
- package/template/.agents/skills/hono/SKILL.md +579 -0
- package/template/.agents/skills/integrations/langfuse/SKILL.md +10 -6
- package/template/.agents/skills/integrations/langfuse/references/ci-cd.md +41 -0
- package/template/.agents/skills/integrations/langfuse/references/cli.md +8 -0
- package/template/.agents/skills/integrations/langfuse/references/error-analysis.md +15 -27
- package/template/.agents/skills/integrations/langfuse/references/instrumentation.md +39 -52
- package/template/.agents/skills/integrations/langfuse/references/judge-calibration.md +5 -2
- package/template/.agents/skills/integrations/langfuse/references/prompt-engineering.md +35 -0
- package/template/.agents/skills/integrations/langfuse/references/prompt-migration.md +41 -196
- package/template/.agents/skills/integrations/langfuse/references/skill-feedback.md +3 -0
- package/template/.agents/skills/integrations/langfuse/references/trace-evaluator-upgrade.md +76 -0
- package/template/.agents/skills/integrations/langfuse/references/user-feedback.md +4 -0
- package/template/.agents/skills/integrations/langfuse/references/v4-project-migration.md +73 -0
- package/template/.agents/skills/supabase/CHANGELOG.md +71 -0
- package/template/.agents/skills/supabase/SKILL.md +145 -0
- package/template/.agents/skills/supabase/assets/feedback-issue-template.md +17 -0
- package/template/.agents/skills/supabase/references/skill-feedback.md +17 -0
- package/template/.agents/skills/supabase-postgres-best-practices/CHANGELOG.md +73 -0
- package/template/.agents/skills/supabase-postgres-best-practices/SKILL.md +64 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/_contributing.md +170 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/_sections.md +39 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/_template.md +34 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/advanced-full-text-search.md +55 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/advanced-jsonb-indexing.md +49 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/conn-idle-timeout.md +46 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/conn-limits.md +44 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/conn-pooling.md +41 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/conn-prepared-statements.md +46 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/data-batch-inserts.md +54 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/data-n-plus-one.md +53 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/data-pagination.md +50 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/data-upsert.md +50 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/lock-advisory.md +56 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/lock-deadlock-prevention.md +68 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/lock-short-transactions.md +50 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/lock-skip-locked.md +54 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/monitor-explain-analyze.md +45 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/monitor-pg-stat-statements.md +55 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/monitor-vacuum-analyze.md +55 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/query-composite-indexes.md +44 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/query-covering-indexes.md +40 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/query-index-types.md +48 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/query-missing-indexes.md +43 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/query-partial-indexes.md +45 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/schema-constraints.md +80 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/schema-data-types.md +46 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/schema-foreign-key-indexes.md +59 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/schema-lowercase-identifiers.md +55 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/schema-partitioning.md +55 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/schema-primary-keys.md +61 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/security-privileges.md +54 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/security-rls-basics.md +50 -0
- package/template/.agents/skills/supabase-postgres-best-practices/references/security-rls-performance.md +63 -0
- package/template/.agents/upstreams.json +34 -12
- package/template/.agents/skills/design/impeccable/reference/brand.md +0 -108
- package/template/.agents/skills/design/impeccable/reference/codex.md +0 -105
- package/template/.agents/skills/design/impeccable/reference/interaction-design.md +0 -189
- package/template/.agents/skills/integrations/langfuse/references/sdk-upgrade.md +0 -175
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
scaffoldSvelteComponentInsertSession,
|
|
27
27
|
shouldUseSvelteComponentInjection,
|
|
28
28
|
} from './live/svelte-component.mjs';
|
|
29
|
+
import { enterLiveRoot } from './live/roots.mjs';
|
|
29
30
|
|
|
30
31
|
const INSERT_POSITIONS = new Set(['before', 'after']);
|
|
31
32
|
|
|
@@ -131,6 +132,9 @@ Output (JSON):
|
|
|
131
132
|
const query = argVal(args, '--query');
|
|
132
133
|
const filePath = argVal(args, '--file');
|
|
133
134
|
const text = argVal(args, '--text');
|
|
135
|
+
// See live-wrap.mjs: preflight computes the scaffold but leaves source
|
|
136
|
+
// untouched so the agent's single edit is the only framework reload.
|
|
137
|
+
const deferSourceWrite = args.includes('--defer-source-write');
|
|
134
138
|
|
|
135
139
|
if (!id) { console.error('Missing --id'); process.exit(1); }
|
|
136
140
|
if (!position) { console.error('Missing --position (before | after)'); process.exit(1); }
|
|
@@ -244,12 +248,23 @@ Output (JSON):
|
|
|
244
248
|
isJsx,
|
|
245
249
|
});
|
|
246
250
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
251
|
+
let deferredWrapper = null;
|
|
252
|
+
if (deferSourceWrite) {
|
|
253
|
+
// Insert-as-empty-range: the agent inserts `wrapperBlock` (variants spliced
|
|
254
|
+
// at the marker) at spliceIndex without removing any source line.
|
|
255
|
+
deferredWrapper = {
|
|
256
|
+
block: wrapperLines.join('\n'),
|
|
257
|
+
replaceStartLine: spliceIndex + 1,
|
|
258
|
+
replaceEndLine: spliceIndex, // empty range (endLine < startLine) => insertion
|
|
259
|
+
};
|
|
260
|
+
} else {
|
|
261
|
+
const newLines = [
|
|
262
|
+
...lines.slice(0, spliceIndex),
|
|
263
|
+
...wrapperLines,
|
|
264
|
+
...lines.slice(spliceIndex),
|
|
265
|
+
];
|
|
266
|
+
fs.writeFileSync(targetFile, newLines.join('\n'), 'utf-8');
|
|
267
|
+
}
|
|
253
268
|
|
|
254
269
|
const insertLine = spliceIndex + 3;
|
|
255
270
|
|
|
@@ -257,6 +272,10 @@ Output (JSON):
|
|
|
257
272
|
mode: 'insert',
|
|
258
273
|
position,
|
|
259
274
|
file: relTargetFile,
|
|
275
|
+
sourceWritten: deferredWrapper ? false : undefined,
|
|
276
|
+
wrapperBlock: deferredWrapper ? deferredWrapper.block : undefined,
|
|
277
|
+
replaceStartLine: deferredWrapper ? deferredWrapper.replaceStartLine : undefined,
|
|
278
|
+
replaceEndLine: deferredWrapper ? deferredWrapper.replaceEndLine : undefined,
|
|
260
279
|
insertLine: insertLine + 1,
|
|
261
280
|
commentSyntax,
|
|
262
281
|
styleMode: styleMode.mode,
|
|
@@ -268,5 +287,6 @@ Output (JSON):
|
|
|
268
287
|
|
|
269
288
|
const _running = process.argv[1];
|
|
270
289
|
if (_running?.endsWith('live-insert.mjs') || _running?.endsWith('live-insert.mjs/')) {
|
|
290
|
+
enterLiveRoot();
|
|
271
291
|
insertCli();
|
|
272
292
|
}
|
|
@@ -14,7 +14,12 @@ import { isGeneratedFile } from './lib/is-generated.mjs';
|
|
|
14
14
|
import { readBuffer, getBufferPath } from './live/manual-edits-buffer.mjs';
|
|
15
15
|
|
|
16
16
|
const EVIDENCE_VERSION = 1;
|
|
17
|
-
const TEXT_EXTENSIONS = new Set([
|
|
17
|
+
const TEXT_EXTENSIONS = new Set([
|
|
18
|
+
'.html', '.jsx', '.tsx', '.vue', '.svelte', '.astro', '.js', '.mjs', '.ts',
|
|
19
|
+
// Phoenix keeps `~H"""` markup in .ex alongside standalone .heex/.eex
|
|
20
|
+
// templates, so copy edits land in all three.
|
|
21
|
+
'.ex', '.heex', '.eex',
|
|
22
|
+
]);
|
|
18
23
|
const SEARCH_DIRS = ['src', 'app', 'pages', 'components', 'public', 'views', 'templates', 'site', 'lib', 'data'];
|
|
19
24
|
const STRONG_LITERAL_MATCH_LIMIT = 8;
|
|
20
25
|
const WEAK_LITERAL_MATCH_LIMIT = 4;
|
|
@@ -14,6 +14,8 @@ import path from 'node:path';
|
|
|
14
14
|
import { fileURLToPath } from 'node:url';
|
|
15
15
|
import { completionAckForAcceptResult, completionTypeForAcceptResult } from './live/completion.mjs';
|
|
16
16
|
import { readLiveServerInfo } from './lib/impeccable-paths.mjs';
|
|
17
|
+
import { enterLiveRoot } from './live/roots.mjs';
|
|
18
|
+
import { instructionsForEvent } from './live/instructions.mjs';
|
|
17
19
|
|
|
18
20
|
// Absolute path to a sibling script in this skill's scripts dir, so runtime
|
|
19
21
|
// error hints print a directly-runnable command instead of a placeholder.
|
|
@@ -27,7 +29,7 @@ const scriptCmd = (name) => `node "${path.join(SELF_DIR, name)}"`;
|
|
|
27
29
|
export const PER_REQUEST_TIMEOUT_MS = 270_000;
|
|
28
30
|
export const DEFAULT_EVENT_LEASE_MS = 600_000;
|
|
29
31
|
|
|
30
|
-
const EVENT_TYPES_NEEDING_AGENT_REPLY = new Set(['generate', 'steer', 'manual_edit_apply']);
|
|
32
|
+
const EVENT_TYPES_NEEDING_AGENT_REPLY = new Set(['generate', 'steer', 'manual_edit_apply', 'carbonize_cleanup', 'variant_mount_failed']);
|
|
31
33
|
|
|
32
34
|
function readServerInfo() {
|
|
33
35
|
const record = readLiveServerInfo(process.cwd());
|
|
@@ -38,8 +40,8 @@ function readServerInfo() {
|
|
|
38
40
|
return record.info;
|
|
39
41
|
}
|
|
40
42
|
|
|
41
|
-
export function buildPollReplyPayload(token, { id, type, message, file, data }) {
|
|
42
|
-
return { token, id, type, message, file, data };
|
|
43
|
+
export function buildPollReplyPayload(token, { id, type, message, file, data, sourceEventType }) {
|
|
44
|
+
return { token, id, type, message, file, data, sourceEventType };
|
|
43
45
|
}
|
|
44
46
|
|
|
45
47
|
export function manualApplyPollBanner(event = {}) {
|
|
@@ -117,8 +119,11 @@ export async function postReply(base, token, reply) {
|
|
|
117
119
|
});
|
|
118
120
|
if (!res.ok) {
|
|
119
121
|
const body = await res.json().catch(() => ({}));
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
+
const failureLines = Array.isArray(body.failures)
|
|
123
|
+
? body.failures.map((f) => ` ${f.file}${f.line != null ? `:${f.line}` : ''} ${f.message}`).join('\n')
|
|
124
|
+
: null;
|
|
125
|
+
const parts = [body.error || res.statusText, body.reason, body.hint, failureLines, body._instructions].filter(Boolean);
|
|
126
|
+
throw new Error(parts.join('\n'));
|
|
122
127
|
}
|
|
123
128
|
}
|
|
124
129
|
|
|
@@ -152,7 +157,14 @@ export async function waitForEventAck(base, token, eventId, {
|
|
|
152
157
|
return false;
|
|
153
158
|
}
|
|
154
159
|
|
|
155
|
-
export async function fetchNextEvent(base, token, {
|
|
160
|
+
export async function fetchNextEvent(base, token, {
|
|
161
|
+
totalDeadline,
|
|
162
|
+
types,
|
|
163
|
+
resolveTypes,
|
|
164
|
+
perRequestTimeoutMs = PER_REQUEST_TIMEOUT_MS,
|
|
165
|
+
leaseMs = DEFAULT_EVENT_LEASE_MS,
|
|
166
|
+
signal,
|
|
167
|
+
} = {}) {
|
|
156
168
|
while (true) {
|
|
157
169
|
if (totalDeadline && Date.now() >= totalDeadline) {
|
|
158
170
|
return { type: 'timeout' };
|
|
@@ -161,8 +173,15 @@ export async function fetchNextEvent(base, token, { totalDeadline } = {}) {
|
|
|
161
173
|
const remaining = totalDeadline
|
|
162
174
|
? totalDeadline - Date.now()
|
|
163
175
|
: PER_REQUEST_TIMEOUT_MS;
|
|
164
|
-
const slice = Math.min(Math.max(remaining, 1000),
|
|
165
|
-
const
|
|
176
|
+
const slice = Math.min(Math.max(remaining, 1000), perRequestTimeoutMs);
|
|
177
|
+
const query = new URLSearchParams({
|
|
178
|
+
token,
|
|
179
|
+
timeout: String(slice),
|
|
180
|
+
leaseMs: String(leaseMs),
|
|
181
|
+
});
|
|
182
|
+
const normalizedTypes = normalizePollTypes(resolveTypes ? await resolveTypes() : types);
|
|
183
|
+
if (normalizedTypes.length > 0) query.set('types', normalizedTypes.join(','));
|
|
184
|
+
const res = await fetch(`${base}/poll?${query}`, { signal });
|
|
166
185
|
|
|
167
186
|
if (res.status === 401) {
|
|
168
187
|
const err = new Error('Authentication failed. The server token may have changed.');
|
|
@@ -202,11 +221,17 @@ export async function augmentEventWithAcceptHandling(event, base, token) {
|
|
|
202
221
|
event._acceptResult = { handled: false, mode: 'error', error: err.message };
|
|
203
222
|
}
|
|
204
223
|
|
|
224
|
+
await completeAcceptHandling(event, base, token);
|
|
225
|
+
return event;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export async function completeAcceptHandling(event, base, token) {
|
|
205
229
|
const completionType = completionTypeForAcceptResult(event.type, event._acceptResult);
|
|
206
230
|
try {
|
|
207
231
|
await postReply(base, token, {
|
|
208
232
|
id: event.id,
|
|
209
233
|
type: completionType,
|
|
234
|
+
sourceEventType: event.type,
|
|
210
235
|
message: event._acceptResult?.error,
|
|
211
236
|
file: event._acceptResult?.file,
|
|
212
237
|
data: event._acceptResult?.carbonize === true ? { carbonize: true } : undefined,
|
|
@@ -217,7 +242,6 @@ export async function augmentEventWithAcceptHandling(event, base, token) {
|
|
|
217
242
|
if (!event._completionAck) {
|
|
218
243
|
event._completionAck = completionAckForAcceptResult(event.id, completionType, event._acceptResult);
|
|
219
244
|
}
|
|
220
|
-
|
|
221
245
|
return event;
|
|
222
246
|
}
|
|
223
247
|
|
|
@@ -242,12 +266,19 @@ export function writeCarbonizeBanner(event) {
|
|
|
242
266
|
}
|
|
243
267
|
|
|
244
268
|
export function printPollEvent(event) {
|
|
269
|
+
// Situational plumbing rides with the event itself: `_instructions` is the
|
|
270
|
+
// authoritative next step, with real ids and paths substituted, so the
|
|
271
|
+
// reference doc can stay lean and can never drift from script behavior.
|
|
272
|
+
if (event && typeof event === 'object' && !event._instructions) {
|
|
273
|
+
const instructions = instructionsForEvent(event, { scriptsPath: SELF_DIR });
|
|
274
|
+
if (instructions) event._instructions = instructions;
|
|
275
|
+
}
|
|
245
276
|
console.log(JSON.stringify(event));
|
|
246
277
|
}
|
|
247
278
|
|
|
248
|
-
export async function runPollOnce(base, token, { totalTimeout = 600_000 } = {}) {
|
|
279
|
+
export async function runPollOnce(base, token, { totalTimeout = 600_000, types, resolveTypes, perRequestTimeoutMs } = {}) {
|
|
249
280
|
const deadline = Date.now() + totalTimeout;
|
|
250
|
-
const event = await fetchNextEvent(base, token, { totalDeadline: deadline });
|
|
281
|
+
const event = await fetchNextEvent(base, token, { totalDeadline: deadline, types, resolveTypes, perRequestTimeoutMs });
|
|
251
282
|
await augmentEventWithAcceptHandling(event, base, token);
|
|
252
283
|
writeCarbonizeBanner(event);
|
|
253
284
|
printPollEvent(event);
|
|
@@ -258,11 +289,14 @@ export async function runPollStream(base, token, {
|
|
|
258
289
|
ackTimeoutMs = 600_000,
|
|
259
290
|
ackPollIntervalMs = 400,
|
|
260
291
|
shouldContinue = () => true,
|
|
292
|
+
types,
|
|
293
|
+
resolveTypes,
|
|
294
|
+
perRequestTimeoutMs,
|
|
261
295
|
} = {}) {
|
|
262
296
|
process.stderr.write('[impeccable-poll] stream mode: one JSON object per line on stdout; use --reply while this process stays running\n');
|
|
263
297
|
|
|
264
298
|
while (shouldContinue()) {
|
|
265
|
-
const event = await fetchNextEvent(base, token);
|
|
299
|
+
const event = await fetchNextEvent(base, token, { types, resolveTypes, perRequestTimeoutMs });
|
|
266
300
|
await augmentEventWithAcceptHandling(event, base, token);
|
|
267
301
|
writeCarbonizeBanner(event);
|
|
268
302
|
printPollEvent(event);
|
|
@@ -322,14 +356,17 @@ Modes:
|
|
|
322
356
|
|
|
323
357
|
Options:
|
|
324
358
|
--timeout=MS One-shot poll timeout in ms (default: 600000). Ignored in --stream mode
|
|
359
|
+
--types=A,B Lease only these event types
|
|
325
360
|
--ack-timeout=MS Stream mode: max wait for --reply after generate/steer (default: 600000)
|
|
326
361
|
--file PATH Attach a source file path to the reply (generate/steer flow)
|
|
327
362
|
--data JSON Attach a JSON result object to the reply (manual_edit_apply flow). Must be valid JSON
|
|
328
363
|
--help Show this help message
|
|
329
364
|
|
|
330
365
|
Harness note:
|
|
331
|
-
Default one-shot mode is the
|
|
332
|
-
|
|
366
|
+
Default one-shot mode is the primary contract, including Codex foreground polling.
|
|
367
|
+
Claude Code may run it as a background task; Cursor uses a background terminal with exit notification.
|
|
368
|
+
--stream is retained for harnesses with measured, reliable incremental stdout.
|
|
369
|
+
Do not use --stream on Cursor.`);
|
|
333
370
|
process.exit(0);
|
|
334
371
|
}
|
|
335
372
|
|
|
@@ -360,25 +397,33 @@ Harness note:
|
|
|
360
397
|
}
|
|
361
398
|
|
|
362
399
|
const streamMode = args.includes('--stream');
|
|
400
|
+
const typesArg = args.find((a) => a.startsWith('--types='));
|
|
401
|
+
const types = normalizePollTypes(typesArg ? typesArg.slice('--types='.length) : null);
|
|
363
402
|
const ackTimeoutArg = args.find((a) => a.startsWith('--ack-timeout='));
|
|
364
403
|
const ackTimeoutMs = ackTimeoutArg ? parseInt(ackTimeoutArg.split('=')[1], 10) : 600_000;
|
|
365
404
|
|
|
366
405
|
try {
|
|
367
406
|
if (streamMode) {
|
|
368
|
-
await runPollStream(base, info.token, { ackTimeoutMs });
|
|
407
|
+
await runPollStream(base, info.token, { ackTimeoutMs, types });
|
|
369
408
|
return;
|
|
370
409
|
}
|
|
371
410
|
|
|
372
411
|
const timeoutArg = args.find((a) => a.startsWith('--timeout='));
|
|
373
412
|
const totalTimeout = timeoutArg ? parseInt(timeoutArg.split('=')[1], 10) : 600_000;
|
|
374
|
-
await runPollOnce(base, info.token, { totalTimeout });
|
|
413
|
+
await runPollOnce(base, info.token, { totalTimeout, types });
|
|
375
414
|
} catch (err) {
|
|
376
415
|
handlePollError(err);
|
|
377
416
|
}
|
|
378
417
|
}
|
|
379
418
|
|
|
419
|
+
export function normalizePollTypes(value) {
|
|
420
|
+
const values = Array.isArray(value) ? value : String(value || '').split(',');
|
|
421
|
+
return [...new Set(values.map((type) => String(type).trim()).filter(Boolean))];
|
|
422
|
+
}
|
|
423
|
+
|
|
380
424
|
// Auto-execute when run directly
|
|
381
425
|
const _running = process.argv[1];
|
|
382
426
|
if (_running?.endsWith('live-poll.mjs') || _running?.endsWith('live-poll.mjs/')) {
|
|
427
|
+
enterLiveRoot();
|
|
383
428
|
pollCli();
|
|
384
429
|
}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { createLiveSessionStore } from './live/session-store.mjs';
|
|
7
|
+
import { enterLiveRoot } from './live/roots.mjs';
|
|
7
8
|
|
|
8
9
|
function manualApplyReplyCommand(eventOrId = 'EVENT_ID') {
|
|
9
10
|
const id = typeof eventOrId === 'string' ? eventOrId : eventOrId?.id || 'EVENT_ID';
|
|
@@ -49,6 +50,28 @@ function collectManualApplyFiles(batch) {
|
|
|
49
50
|
return [...new Set(files.filter((file) => typeof file === 'string' && file.length > 0))].sort();
|
|
50
51
|
}
|
|
51
52
|
|
|
53
|
+
/**
|
|
54
|
+
* The browser's render truth, folded into a small block the agent reads before
|
|
55
|
+
* it decides what to do. `arrivedVariants` only says the agent published;
|
|
56
|
+
* `renderState` says whether any of it reached a screen.
|
|
57
|
+
*/
|
|
58
|
+
export function renderSummary(snapshot = {}) {
|
|
59
|
+
return {
|
|
60
|
+
renderState: snapshot.renderState ?? null,
|
|
61
|
+
mountedVariants: Array.isArray(snapshot.mountedVariants) ? snapshot.mountedVariants : [],
|
|
62
|
+
mountFailures: Array.isArray(snapshot.mountFailures) ? snapshot.mountFailures : [],
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function mountFailureAction(snapshot = {}) {
|
|
67
|
+
const failures = Array.isArray(snapshot.mountFailures) ? snapshot.mountFailures : [];
|
|
68
|
+
const latest = failures[failures.length - 1];
|
|
69
|
+
if (!latest) return null;
|
|
70
|
+
const where = latest.url ? ` from ${latest.url}` : '';
|
|
71
|
+
const why = latest.error ? ` (${latest.error})` : '';
|
|
72
|
+
return `The browser failed to mount variant ${latest.variant}${where}${why}; nothing is on screen. Fix the variant files, then reply with live-poll.mjs --reply ${snapshot?.pendingEvent?.id || snapshot?.id || 'SESSION_ID'} done --file <manifest or source path> for the queued variant_mount_failed event (or republish) so the browser retries.`;
|
|
73
|
+
}
|
|
74
|
+
|
|
52
75
|
function parseArgs(argv) {
|
|
53
76
|
const out = { id: null };
|
|
54
77
|
for (let i = 0; i < argv.length; i++) {
|
|
@@ -75,20 +98,26 @@ export async function resumeCli() {
|
|
|
75
98
|
}
|
|
76
99
|
|
|
77
100
|
const pending = snapshot.pendingEvent || null;
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
101
|
+
const render = renderSummary(snapshot);
|
|
102
|
+
// A failed render outranks the generic pending-event hint: the agent needs to
|
|
103
|
+
// know the user is staring at an error card, not at variants. A leased manual
|
|
104
|
+
// Apply still outranks both, because abandoning that lease loses user edits.
|
|
105
|
+
const mountAction = render.renderState === 'failed' ? mountFailureAction(snapshot) : null;
|
|
106
|
+
const nextAction = pending?.type === 'manual_edit_apply'
|
|
107
|
+
? manualApplyResumeHint(pending)
|
|
108
|
+
: mountAction || (pending
|
|
109
|
+
? `Run live-poll.mjs, handle ${pending.type} ${pending.id}, then acknowledge with live-poll.mjs --reply ${pending.id} done.`
|
|
110
|
+
: snapshot.phase === 'carbonize_required'
|
|
111
|
+
? `Finish carbonize cleanup${snapshot.sourceFile ? ` in ${snapshot.sourceFile}` : ''}, then run live-complete.mjs --id ${snapshot.id}.`
|
|
112
|
+
: snapshot.phase === 'accept_requested'
|
|
113
|
+
? `Run live-complete.mjs --id ${snapshot.id} after verifying the accepted variant is written.`
|
|
114
|
+
: `Inspect ${snapshot.id}; no pending agent event is currently queued.`);
|
|
87
115
|
|
|
88
|
-
console.log(JSON.stringify({ active: true, snapshot, pendingEvent: pending, nextAction }, null, 2));
|
|
116
|
+
console.log(JSON.stringify({ active: true, snapshot, pendingEvent: pending, render, nextAction }, null, 2));
|
|
89
117
|
}
|
|
90
118
|
|
|
91
119
|
const _running = process.argv[1];
|
|
92
120
|
if (_running?.endsWith('live-resume.mjs') || _running?.endsWith('live-resume.mjs/')) {
|
|
121
|
+
enterLiveRoot();
|
|
93
122
|
resumeCli();
|
|
94
123
|
}
|