@reticlehq/server 2.7.0 → 2.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/README.md +14 -5
- package/SKILL.md +130 -778
- package/dist/bridge/bridge.d.ts +23 -0
- package/dist/bridge/bridge.js +80 -2
- package/dist/bridge/bridge.test-harness.d.ts +5 -0
- package/dist/bridge/bridge.test-harness.js +6 -4
- package/dist/capsule/causal-summary.d.ts +36 -1
- package/dist/capsule/causal-summary.js +33 -7
- package/dist/capsule/divergence.js +7 -1
- package/dist/cli/chromium-hint.d.ts +33 -5
- package/dist/cli/chromium-hint.js +82 -12
- package/dist/cli/cli-doctor.js +65 -34
- package/dist/cli/cli-flow-commands.js +8 -8
- package/dist/cli/cli-kill.d.ts +58 -0
- package/dist/cli/cli-kill.js +162 -0
- package/dist/cli/cli-parse.d.ts +16 -1
- package/dist/cli/cli-parse.js +32 -9
- package/dist/cli/cli-port.d.ts +32 -0
- package/dist/cli/cli-port.js +82 -35
- package/dist/cli/cli-verify.d.ts +21 -0
- package/dist/cli/cli-verify.js +47 -3
- package/dist/cli/config-discovery.d.ts +35 -0
- package/dist/cli/config-discovery.js +163 -0
- package/dist/cli/doctor-daemon-line.js +4 -1
- package/dist/cli/doctor-project-line.d.ts +37 -0
- package/dist/cli/doctor-project-line.js +35 -0
- package/dist/cli/doctor-rows.d.ts +51 -0
- package/dist/cli/doctor-rows.js +54 -0
- package/dist/cli/doctor-sessions-line.d.ts +12 -0
- package/dist/cli/doctor-sessions-line.js +69 -0
- package/dist/cli/drive-attach.d.ts +99 -0
- package/dist/cli/drive-attach.js +203 -0
- package/dist/cli/drive-command.d.ts +13 -0
- package/dist/cli/drive-command.js +103 -0
- package/dist/cli/open-note.d.ts +20 -0
- package/dist/cli/open-note.js +37 -0
- package/dist/cli/port-holder.d.ts +10 -0
- package/dist/cli/port-holder.js +26 -2
- package/dist/cli/status-next-action.d.ts +37 -0
- package/dist/cli/status-next-action.js +61 -0
- package/dist/cli.js +119 -39
- package/dist/crawl/crawl-tools.js +12 -2
- package/dist/crawl/crawl.d.ts +13 -0
- package/dist/crawl/crawl.js +50 -2
- package/dist/events/contradictions.d.ts +46 -0
- package/dist/events/contradictions.js +35 -22
- package/dist/events/declared.d.ts +45 -0
- package/dist/events/declared.js +73 -0
- package/dist/events/echo-mismatch.d.ts +8 -2
- package/dist/events/echo-mismatch.js +33 -5
- package/dist/events/event-filters.d.ts +1 -1
- package/dist/events/event-filters.js +7 -4
- package/dist/events/predicate-eval.d.ts +17 -72
- package/dist/events/predicate-eval.js +117 -236
- package/dist/events/predicate-parse.js +31 -3
- package/dist/events/predicate-route.d.ts +32 -0
- package/dist/events/predicate-route.js +102 -0
- package/dist/events/predicate-schema.d.ts +99 -0
- package/dist/events/predicate-schema.js +309 -0
- package/dist/events/predicate.d.ts +8 -0
- package/dist/events/predicate.js +296 -22
- package/dist/flows/annotate-tools.js +3 -0
- package/dist/flows/annotate.js +18 -4
- package/dist/flows/coverage.d.ts +38 -5
- package/dist/flows/coverage.js +30 -4
- package/dist/flows/decision.d.ts +15 -0
- package/dist/flows/decision.js +1 -1
- package/dist/flows/flow-classify.js +1 -1
- package/dist/flows/flow-replay-run.js +8 -1
- package/dist/flows/flow-tools.js +21 -5
- package/dist/flows/heal-run.js +1 -1
- package/dist/flows/replay.js +3 -0
- package/dist/honesty/accepted-write.d.ts +3 -0
- package/dist/honesty/accepted-write.js +8 -3
- package/dist/honesty/already-true.js +15 -0
- package/dist/honesty/blind-spots.js +10 -2
- package/dist/honesty/honesty.d.ts +11 -0
- package/dist/honesty/honesty.js +1 -0
- package/dist/honesty/uncaptured-bodies.d.ts +4 -2
- package/dist/honesty/uncaptured-bodies.js +9 -2
- package/dist/honesty/unread-outcome.d.ts +8 -0
- package/dist/honesty/unread-outcome.js +36 -9
- package/dist/honesty/unsettled.d.ts +49 -0
- package/dist/honesty/unsettled.js +82 -0
- package/dist/honesty/verified.d.ts +36 -3
- package/dist/honesty/verified.js +54 -11
- package/dist/http-server.d.ts +19 -0
- package/dist/http-server.js +202 -4
- package/dist/impact/impact-recorder.d.ts +23 -0
- package/dist/impact/impact-recorder.js +76 -0
- package/dist/impact/impact-store.d.ts +47 -0
- package/dist/impact/impact-store.js +171 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +47 -10
- package/dist/init/agent-rules.d.ts +36 -0
- package/dist/init/agent-rules.js +132 -22
- package/dist/init/astro-patch.d.ts +2 -1
- package/dist/init/astro-patch.js +38 -6
- package/dist/init/capabilities.d.ts +22 -0
- package/dist/init/capabilities.js +76 -0
- package/dist/init/confirm.d.ts +114 -0
- package/dist/init/confirm.js +165 -0
- package/dist/init/connect-steps.d.ts +2 -0
- package/dist/init/connect-steps.js +50 -0
- package/dist/init/cra.js +3 -2
- package/dist/init/csp-check.d.ts +38 -0
- package/dist/init/csp-check.js +92 -0
- package/dist/init/csp-doctor.d.ts +25 -0
- package/dist/init/csp-doctor.js +49 -0
- package/dist/init/cursor.js +6 -9
- package/dist/init/detect.d.ts +8 -0
- package/dist/init/detect.js +33 -3
- package/dist/init/mcp-clients.d.ts +1 -0
- package/dist/init/mcp-clients.js +51 -7
- package/dist/init/mcp.d.ts +15 -0
- package/dist/init/mcp.js +19 -0
- package/dist/init/non-js-project.js +29 -5
- package/dist/init/plan-framework.d.ts +10 -0
- package/dist/init/plan-framework.js +78 -16
- package/dist/init/plan.d.ts +47 -6
- package/dist/init/plan.js +228 -69
- package/dist/init/run.d.ts +24 -2
- package/dist/init/run.js +157 -45
- package/dist/init/slash-command.d.ts +1 -1
- package/dist/init/slash-command.js +54 -6
- package/dist/init/snippets.d.ts +45 -5
- package/dist/init/snippets.js +194 -42
- package/dist/init/vite-config.js +53 -5
- package/dist/input/network-mock-tools.d.ts +19 -0
- package/dist/input/network-mock-tools.js +37 -5
- package/dist/input/scroll-find.d.ts +6 -0
- package/dist/input/scroll-find.js +17 -2
- package/dist/input/scroll-tools.js +4 -0
- package/dist/journal/attach-journal.d.ts +9 -1
- package/dist/journal/attach-journal.js +13 -2
- package/dist/journal/journal-query.d.ts +13 -0
- package/dist/journal/journal-query.js +28 -3
- package/dist/journal/workspace-gitignore.d.ts +10 -0
- package/dist/journal/workspace-gitignore.js +59 -0
- package/dist/license/license.js +1 -1
- package/dist/mcp/mcp-proxy.d.ts +35 -30
- package/dist/mcp/mcp-proxy.js +306 -104
- package/dist/mcp/mcp.d.ts +10 -1
- package/dist/mcp/mcp.js +70 -34
- package/dist/mcp/proxy-handshake.d.ts +82 -1
- package/dist/mcp/proxy-handshake.js +109 -2
- package/dist/mcp/proxy-lifecycle.d.ts +11 -2
- package/dist/mcp/proxy-lifecycle.js +12 -3
- package/dist/mcp/proxy-log.d.ts +63 -0
- package/dist/mcp/proxy-log.js +132 -0
- package/dist/mcp/server-instructions.d.ts +17 -0
- package/dist/mcp/server-instructions.js +56 -0
- package/dist/mcp/shared-params.d.ts +27 -0
- package/dist/mcp/shared-params.js +36 -0
- package/dist/pool/browser-pool.d.ts +22 -2
- package/dist/pool/browser-pool.js +44 -4
- package/dist/project/learned-routes.d.ts +24 -0
- package/dist/project/learned-routes.js +63 -0
- package/dist/project/project-store.d.ts +6 -0
- package/dist/project/project-store.js +25 -1
- package/dist/project/reticle-dir.d.ts +2 -0
- package/dist/project/reticle-dir.js +1 -0
- package/dist/session/connection-memory.d.ts +59 -0
- package/dist/session/connection-memory.js +108 -0
- package/dist/session/dev-command.d.ts +26 -0
- package/dist/session/dev-command.js +89 -0
- package/dist/session/dev-server-probe.d.ts +68 -0
- package/dist/session/dev-server-probe.js +102 -7
- package/dist/session/last-act.d.ts +26 -0
- package/dist/session/last-act.js +35 -1
- package/dist/session/live-control-tools.js +42 -5
- package/dist/session/no-session-diagnosis.d.ts +67 -2
- package/dist/session/no-session-diagnosis.js +236 -27
- package/dist/session/no-session-next-action.d.ts +46 -0
- package/dist/session/no-session-next-action.js +85 -0
- package/dist/session/no-session-watch.d.ts +40 -1
- package/dist/session/no-session-watch.js +174 -8
- package/dist/session/pending-commands.d.ts +12 -0
- package/dist/session/pending-commands.js +13 -1
- package/dist/session/ref-provenance.d.ts +54 -0
- package/dist/session/ref-provenance.js +61 -0
- package/dist/session/session-lease.js +1 -1
- package/dist/session/session-manager.d.ts +4 -0
- package/dist/session/session-manager.js +35 -5
- package/dist/session/session.d.ts +10 -1
- package/dist/session/session.js +146 -5
- package/dist/telemetry/app-instrumented.d.ts +8 -0
- package/dist/telemetry/app-instrumented.js +10 -0
- package/dist/telemetry/automation-hint.d.ts +17 -0
- package/dist/telemetry/automation-hint.js +71 -0
- package/dist/telemetry/bug-found.d.ts +15 -17
- package/dist/telemetry/bug-found.js +52 -21
- package/dist/telemetry/cli-telemetry.js +7 -1
- package/dist/telemetry/daemon-telemetry.js +24 -0
- package/dist/telemetry/feedback.js +1 -1
- package/dist/telemetry/init-telemetry.js +9 -1
- package/dist/telemetry/install-source.d.ts +56 -0
- package/dist/telemetry/install-source.js +74 -0
- package/dist/telemetry/instrumentation-stall.d.ts +50 -0
- package/dist/telemetry/instrumentation-stall.js +90 -0
- package/dist/telemetry/run-telemetry.js +4 -1
- package/dist/telemetry/session-metrics.d.ts +8 -0
- package/dist/telemetry/session-metrics.js +15 -0
- package/dist/telemetry/telemetry.d.ts +7 -1
- package/dist/telemetry/telemetry.js +26 -2
- package/dist/telemetry/tool-refused.d.ts +19 -0
- package/dist/telemetry/tool-refused.js +55 -0
- package/dist/telemetry/verification-of.js +46 -7
- package/dist/temp-dir.d.ts +27 -0
- package/dist/temp-dir.js +46 -0
- package/dist/tools/act-tools.js +209 -28
- package/dist/tools/assert-grade.d.ts +1 -1
- package/dist/tools/assert-grade.js +27 -5
- package/dist/tools/assert-verdict.js +49 -7
- package/dist/tools/browser-tools.js +10 -0
- package/dist/tools/contract-tools.js +4 -0
- package/dist/tools/dynamic-tools.js +16 -7
- package/dist/tools/error-recovery.d.ts +10 -0
- package/dist/tools/error-recovery.js +73 -9
- package/dist/tools/feedback-invite.js +1 -1
- package/dist/tools/invoke-tool.js +159 -26
- package/dist/tools/lease-hint.d.ts +30 -8
- package/dist/tools/lease-hint.js +65 -14
- package/dist/tools/lease-tools.d.ts +40 -1
- package/dist/tools/lease-tools.js +181 -83
- package/dist/tools/navigate-result.js +1 -1
- package/dist/tools/observe-tools.js +10 -4
- package/dist/tools/observed-nothing.js +1 -1
- package/dist/tools/react-grace.d.ts +52 -0
- package/dist/tools/react-grace.js +90 -0
- package/dist/tools/read-tools.js +67 -5
- package/dist/tools/resolve-target.d.ts +33 -0
- package/dist/tools/resolve-target.js +53 -0
- package/dist/tools/settle-in-flight.d.ts +94 -0
- package/dist/tools/settle-in-flight.js +146 -0
- package/dist/tools/snapshot-delta.d.ts +10 -0
- package/dist/tools/snapshot-delta.js +194 -9
- package/dist/tools/tool-kit.d.ts +8 -0
- package/dist/tools/tool-surface.d.ts +60 -0
- package/dist/tools/tool-surface.js +86 -1
- package/dist/tools/tools.js +61 -8
- package/dist/tools/unadvertised-help.js +9 -6
- package/docs/README.md +55 -11
- package/docs/actions.mdx +120 -0
- package/docs/agent-cheatsheet.md +95 -29
- package/docs/architecture.md +52 -35
- package/docs/benchmarks.md +127 -75
- package/docs/best-practices.mdx +216 -0
- package/docs/capabilities.mdx +534 -0
- package/docs/cli/affected.mdx +53 -0
- package/docs/cli/capsules.mdx +70 -0
- package/docs/cli/cloud.mdx +153 -0
- package/docs/cli/doctor.mdx +109 -0
- package/docs/cli/drive.mdx +74 -0
- package/docs/cli/feedback.mdx +67 -0
- package/docs/cli/gate.mdx +64 -0
- package/docs/cli/help.mdx +94 -0
- package/docs/cli/hunt.mdx +73 -0
- package/docs/cli/identify.mdx +76 -0
- package/docs/cli/init.mdx +121 -0
- package/docs/cli/kill.mdx +91 -0
- package/docs/cli/license.mdx +48 -0
- package/docs/cli/mcp.mdx +61 -0
- package/docs/cli/open.mdx +74 -0
- package/docs/cli/restart.mdx +60 -0
- package/docs/cli/rollback.mdx +35 -0
- package/docs/cli/serve.mdx +69 -0
- package/docs/cli/status.mdx +88 -0
- package/docs/cli/stop.mdx +64 -0
- package/docs/cli/telemetry.mdx +57 -0
- package/docs/cli/update.mdx +52 -0
- package/docs/cli/verify.mdx +76 -0
- package/docs/cli/version.mdx +39 -0
- package/docs/cli/watch.mdx +62 -0
- package/docs/cli.mdx +241 -0
- package/docs/debugging.md +16 -10
- package/docs/deploy-checks.md +45 -12
- package/docs/desktop.mdx +384 -0
- package/docs/docs.json +364 -0
- package/docs/enterprise.md +22 -16
- package/docs/faq.mdx +102 -0
- package/docs/fixtures.md +13 -7
- package/docs/flows.md +29 -23
- package/docs/for-agents.md +71 -0
- package/docs/frameworks.mdx +238 -0
- package/docs/gate-plan.md +48 -42
- package/docs/gates.md +28 -22
- package/docs/getting-started.md +129 -77
- package/docs/human-control.md +24 -18
- package/docs/index.mdx +143 -0
- package/docs/install-agentic.mdx +224 -0
- package/docs/install-manual.mdx +196 -0
- package/docs/instrumentation.mdx +238 -0
- package/docs/integration-patterns.md +41 -35
- package/docs/local-registry.md +19 -13
- package/docs/multi-agent-testing.md +19 -13
- package/docs/packages/babel-plugin.mdx +79 -0
- package/docs/packages/browser.mdx +111 -0
- package/docs/packages/core.mdx +116 -0
- package/docs/packages/electron.mdx +85 -0
- package/docs/packages/eslint-plugin.mdx +86 -0
- package/docs/packages/next.mdx +89 -0
- package/docs/packages/react.mdx +91 -0
- package/docs/packages/server.mdx +98 -0
- package/docs/packages/tauri.mdx +63 -0
- package/docs/packages/test.mdx +119 -0
- package/docs/packages/vite-plugin.mdx +94 -0
- package/docs/packages.mdx +218 -0
- package/docs/platform-integration.md +35 -26
- package/docs/predicates.mdx +248 -0
- package/docs/quickstart.mdx +257 -0
- package/docs/recipes.mdx +282 -0
- package/docs/skill-file.mdx +107 -0
- package/docs/state-management.mdx +199 -0
- package/docs/style.css +14 -0
- package/docs/system-map.md +50 -33
- package/docs/telemetry-contract.md +106 -52
- package/docs/telemetry-events.mdx +475 -0
- package/docs/telemetry.md +63 -55
- package/docs/testing.md +44 -6
- package/docs/token-efficiency.md +37 -27
- package/docs/tools-act-and-wait.mdx +173 -0
- package/docs/tools-act-sequence.mdx +137 -0
- package/docs/tools-act.mdx +95 -0
- package/docs/tools-assert.mdx +129 -0
- package/docs/tools-console.mdx +63 -0
- package/docs/tools-inspect.mdx +88 -0
- package/docs/tools-navigate.mdx +99 -0
- package/docs/tools-network.mdx +119 -0
- package/docs/tools-observe.mdx +145 -0
- package/docs/tools-overview.mdx +160 -0
- package/docs/tools-query.mdx +126 -0
- package/docs/tools-session-and-feedback.mdx +112 -0
- package/docs/tools-sessions.mdx +94 -0
- package/docs/tools-snapshot.mdx +129 -0
- package/docs/tools-state.mdx +104 -0
- package/docs/tools-tools-and-run.mdx +156 -0
- package/docs/tools-wait-for.mdx +85 -0
- package/docs/troubleshooting.mdx +263 -0
- package/docs/usage.md +209 -165
- package/docs/vs-chrome-devtools-mcp.mdx +123 -0
- package/docs/vs-playwright-mcp.mdx +125 -0
- package/docs/vs-screenshots.mdx +137 -0
- package/docs/what-is-reticle.mdx +63 -0
- package/docs/why-reticle.mdx +109 -0
- package/package.json +5 -5
- package/docs/desktop-apps.md +0 -256
- package/docs/matrix/2.5.0/claude-code-machine.json +0 -19
- package/docs/matrix/2.5.0/codex-machine.json +0 -20
- package/docs/matrix/2.5.0/cursor-machine.json +0 -22
- package/docs/matrix/2.5.0/gemini-machine.json +0 -22
- package/docs/matrix/2.5.0/opencode-machine.json +0 -22
- package/docs/matrix/2.5.0/vscode-machine.json +0 -22
- package/docs/matrix/2.5.0/windsurf-machine.json +0 -22
- package/docs/matrix/MATRIX.md +0 -26
- package/docs/matrix/README.md +0 -59
- package/docs/mint.json +0 -61
|
@@ -1,17 +1,28 @@
|
|
|
1
|
+
import { log } from '../log.js';
|
|
1
2
|
import { isValidSessionId } from '../project/reticle-dir.js';
|
|
2
3
|
import { JournalRecorder } from './journal-recorder.js';
|
|
3
4
|
import { SessionJournal } from './session-journal.js';
|
|
4
5
|
/**
|
|
5
6
|
* Build the per-session journal attachment the bridge fires on session creation. Off when disabled;
|
|
6
|
-
*
|
|
7
|
+
* skips a session whose id is not a safe path segment (never crashes the live session over a
|
|
7
8
|
* journaling concern). The recorder's clock is the session's own elapsed time.
|
|
9
|
+
*
|
|
10
|
+
* That skip used to be SILENT, which is the part that mattered. The id becomes a directory name, so
|
|
11
|
+
* one that is not a safe path segment cannot be journalled — but the session itself connects and
|
|
12
|
+
* drives perfectly well, so the only observable difference is that the durable causal record for it
|
|
13
|
+
* does not exist. Every query that reads back through the journal then returns nothing, and nothing
|
|
14
|
+
* anywhere says why. An app self-assigning an unusual id gets a quietly degraded session; a hostile
|
|
15
|
+
* one gets the same, which is why this is worth a line either way. Nothing escapes the directory —
|
|
16
|
+
* the guard holds, and that is exactly why the failure is invisible rather than loud.
|
|
8
17
|
*/
|
|
9
18
|
export function makeJournalAttach(deps) {
|
|
10
19
|
return (session) => {
|
|
11
20
|
if (!deps.enabled)
|
|
12
21
|
return;
|
|
13
|
-
if (!isValidSessionId(session.id))
|
|
22
|
+
if (!isValidSessionId(session.id)) {
|
|
23
|
+
log('journal_skipped_unsafe_session_id', { sessionId: session.id });
|
|
14
24
|
return;
|
|
25
|
+
}
|
|
15
26
|
const journal = new SessionJournal(deps.fs, deps.reticleRoot, session.id);
|
|
16
27
|
// Same SessionJournal is both the write sink and the read fall-through for queries after eviction.
|
|
17
28
|
session.setJournal(new JournalRecorder(journal, { now: () => session.elapsed() }), journal);
|
|
@@ -13,6 +13,19 @@ export interface EventQueryOptions {
|
|
|
13
13
|
* session), ordered by `seq` (falling back to `t` for any pre-2.2 event without one). Neither source is
|
|
14
14
|
* a strict superset — the journal holds everything already flushed (incl. evicted), the buffer holds the
|
|
15
15
|
* most-recent tail that may not be flushed yet — so the union is the complete picture.
|
|
16
|
+
*
|
|
17
|
+
* ...for THIS connection. The session id survives a reload (it lives in sessionStorage), so the next
|
|
18
|
+
* connection reopens the same journal file while `seq` and `t` both restart at zero in the fresh
|
|
19
|
+
* page. Once the buffer has evicted anything — permanent about a minute into any session — every
|
|
20
|
+
* query falls through to that file and the PREVIOUS connection's tail arrives carrying timestamps
|
|
21
|
+
* that look like this connection's. Field reports: contradictions from before an explicit
|
|
22
|
+
* `reticle_session end`, two logins from different runs counted as one duplicate write, and findings
|
|
23
|
+
* from before a `since` cursor the caller had passed explicitly (`since` filters on `t`, which is
|
|
24
|
+
* exactly the field that restarted).
|
|
25
|
+
*
|
|
26
|
+
* The buffer is the authority on what this connection has emitted: the journal is written from the
|
|
27
|
+
* same stream and can only lag it, so nothing beyond the buffer's newest seq can belong here.
|
|
28
|
+
* Overlapping seqs need no rule — appends are ordered, so the newest write already wins the dedupe.
|
|
16
29
|
*/
|
|
17
30
|
export declare function mergeEventsBySeq(journal: readonly ReticleEvent[], buffer: readonly ReticleEvent[]): ReticleEvent[];
|
|
18
31
|
/** Apply since/until/actionId bounds to an event list. */
|
|
@@ -3,15 +3,40 @@
|
|
|
3
3
|
* session), ordered by `seq` (falling back to `t` for any pre-2.2 event without one). Neither source is
|
|
4
4
|
* a strict superset — the journal holds everything already flushed (incl. evicted), the buffer holds the
|
|
5
5
|
* most-recent tail that may not be flushed yet — so the union is the complete picture.
|
|
6
|
+
*
|
|
7
|
+
* ...for THIS connection. The session id survives a reload (it lives in sessionStorage), so the next
|
|
8
|
+
* connection reopens the same journal file while `seq` and `t` both restart at zero in the fresh
|
|
9
|
+
* page. Once the buffer has evicted anything — permanent about a minute into any session — every
|
|
10
|
+
* query falls through to that file and the PREVIOUS connection's tail arrives carrying timestamps
|
|
11
|
+
* that look like this connection's. Field reports: contradictions from before an explicit
|
|
12
|
+
* `reticle_session end`, two logins from different runs counted as one duplicate write, and findings
|
|
13
|
+
* from before a `since` cursor the caller had passed explicitly (`since` filters on `t`, which is
|
|
14
|
+
* exactly the field that restarted).
|
|
15
|
+
*
|
|
16
|
+
* The buffer is the authority on what this connection has emitted: the journal is written from the
|
|
17
|
+
* same stream and can only lag it, so nothing beyond the buffer's newest seq can belong here.
|
|
18
|
+
* Overlapping seqs need no rule — appends are ordered, so the newest write already wins the dedupe.
|
|
6
19
|
*/
|
|
7
20
|
export function mergeEventsBySeq(journal, buffer) {
|
|
21
|
+
// ponytail: an EMPTY buffer cannot say where this connection has got to, so nothing is dropped
|
|
22
|
+
// there — a fresh connection emits page-health immediately, so the window is small and the safe
|
|
23
|
+
// direction is keeping evidence rather than inventing a boundary.
|
|
24
|
+
let newest;
|
|
25
|
+
for (const event of buffer) {
|
|
26
|
+
if ('number' === typeof event.seq && (newest === undefined || event.seq > newest)) {
|
|
27
|
+
newest = event.seq;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
8
30
|
const bySeq = new Map();
|
|
9
31
|
const noSeq = [];
|
|
10
32
|
for (const event of [...journal, ...buffer]) {
|
|
11
|
-
if ('number'
|
|
12
|
-
bySeq.set(event.seq, event);
|
|
13
|
-
else
|
|
33
|
+
if ('number' !== typeof event.seq) {
|
|
14
34
|
noSeq.push(event);
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
if (newest !== undefined && event.seq > newest)
|
|
38
|
+
continue;
|
|
39
|
+
bySeq.set(event.seq, event);
|
|
15
40
|
}
|
|
16
41
|
return [...bySeq.values(), ...noSeq].sort((a, b) => {
|
|
17
42
|
if (a.seq !== undefined && b.seq !== undefined)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { FileSystemPort } from '../project/fs-port.js';
|
|
2
|
+
/**
|
|
3
|
+
* Write `.reticle/.gitignore` if it is not already there.
|
|
4
|
+
*
|
|
5
|
+
* Never overwrites — once the file exists it belongs to whoever edited it last, and silently
|
|
6
|
+
* reverting somebody's change to a file we placed in their repository is worse than not having
|
|
7
|
+
* written it. Best-effort throughout: this runs on the daemon's start path, and a workspace that
|
|
8
|
+
* cannot be written must not stop a daemon coming up. Nothing about verification depends on it.
|
|
9
|
+
*/
|
|
10
|
+
export declare function ensureWorkspaceGitignore(fs: FileSystemPort, root: string): Promise<void>;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { ReticleDir } from '@reticlehq/core';
|
|
3
|
+
/**
|
|
4
|
+
* The `.reticle/` entries that are LOCAL state, and must never be committed by accident.
|
|
5
|
+
*
|
|
6
|
+
* Split from the durable half deliberately, and the split is the whole design: `contract.json`,
|
|
7
|
+
* `flows/`, `baselines/` and `capsules/` are meant to be checked in — a flow that cannot be shared
|
|
8
|
+
* is not a regression check anybody else can run — while everything below is per-machine churn.
|
|
9
|
+
*
|
|
10
|
+
* The reason this matters beyond tidiness: a session journal carries URLs, request and response
|
|
11
|
+
* bodies, and DOM text from the app under test. `.reticle/` is created by the daemon rather than by
|
|
12
|
+
* the user, so it arrives untracked and unexplained, and one `git add -A` puts an app's traffic into
|
|
13
|
+
* a shared repository. Reticle created the directory; the ignore for it is Reticle's to write.
|
|
14
|
+
*/
|
|
15
|
+
const TRANSIENT = [
|
|
16
|
+
`${ReticleDir.SESSIONS_SUBDIR}/`,
|
|
17
|
+
`${ReticleDir.RUNS_SUBDIR}/`,
|
|
18
|
+
`${ReticleDir.VISUAL_SUBDIR}/`,
|
|
19
|
+
ReticleDir.PROJECT_FILE,
|
|
20
|
+
ReticleDir.AMBIENT_FILE,
|
|
21
|
+
ReticleDir.ENVELOPES_FILE,
|
|
22
|
+
ReticleDir.FLAKE_FILE,
|
|
23
|
+
ReticleDir.TIERS_FILE,
|
|
24
|
+
'*.log',
|
|
25
|
+
'*.tmp',
|
|
26
|
+
];
|
|
27
|
+
const HEADER = [
|
|
28
|
+
'# Written by Reticle, and only about the directory Reticle owns.',
|
|
29
|
+
'#',
|
|
30
|
+
'# The entries below are per-machine state — session journals, run artifacts, learned envelopes.',
|
|
31
|
+
'# Journals contain URLs, request and response bodies and page text from the app under test, so',
|
|
32
|
+
'# they are worth keeping out of a shared repository on their own account.',
|
|
33
|
+
'#',
|
|
34
|
+
`# Deliberately NOT ignored: ${ReticleDir.CONTRACT_FILE}, ${ReticleDir.FLOWS_SUBDIR}/, ${ReticleDir.BASELINES_SUBDIR}/ and`,
|
|
35
|
+
`# ${ReticleDir.CAPSULES_SUBDIR}/. Those are meant to be committed — a saved flow only earns its keep`,
|
|
36
|
+
'# when a teammate or CI can replay it.',
|
|
37
|
+
'#',
|
|
38
|
+
'# Edit freely: Reticle writes this once and never rewrites it.',
|
|
39
|
+
];
|
|
40
|
+
/**
|
|
41
|
+
* Write `.reticle/.gitignore` if it is not already there.
|
|
42
|
+
*
|
|
43
|
+
* Never overwrites — once the file exists it belongs to whoever edited it last, and silently
|
|
44
|
+
* reverting somebody's change to a file we placed in their repository is worse than not having
|
|
45
|
+
* written it. Best-effort throughout: this runs on the daemon's start path, and a workspace that
|
|
46
|
+
* cannot be written must not stop a daemon coming up. Nothing about verification depends on it.
|
|
47
|
+
*/
|
|
48
|
+
export async function ensureWorkspaceGitignore(fs, root) {
|
|
49
|
+
const path = join(root, '.gitignore');
|
|
50
|
+
try {
|
|
51
|
+
if (await fs.exists(path))
|
|
52
|
+
return;
|
|
53
|
+
await fs.mkdir(root);
|
|
54
|
+
await fs.writeFile(path, `${[...HEADER, '', ...TRANSIENT].join('\n')}\n`);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
/* a workspace we cannot write is not a reason to fail a session */
|
|
58
|
+
}
|
|
59
|
+
}
|
package/dist/license/license.js
CHANGED
|
@@ -161,7 +161,7 @@ export function describeLicense(now, env = process.env, baked = BAKED_ISSUER_PUB
|
|
|
161
161
|
}
|
|
162
162
|
: {
|
|
163
163
|
status: 'eval',
|
|
164
|
-
detail: 'evaluation mode
|
|
164
|
+
detail: 'evaluation mode: enterprise features run free (no issuer key configured)',
|
|
165
165
|
};
|
|
166
166
|
}
|
|
167
167
|
const publicKey = loadPublicKey(pem);
|
package/dist/mcp/mcp-proxy.d.ts
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Re-exported so every existing caller (and every spec) keeps importing the proxy's log from the
|
|
3
|
+
* proxy. Where the code lives is a file-size decision; where it is imported from is an API.
|
|
4
|
+
*/
|
|
5
|
+
export { accountProxyLogWrite, proxyLog, proxyLogPath, PROXY_LOG_CHECK_BYTES, recoverOversizedProxyLog, setProxyLogPort, } from './proxy-log.js';
|
|
1
6
|
/**
|
|
2
7
|
* Overridable so the survival spec can reach exhaustion in seconds instead of minutes — the same
|
|
3
8
|
* reason the idle windows take an env override. A positive integer only; anything else falls back,
|
|
@@ -7,23 +12,6 @@ export declare const MAX_RECONNECT_ATTEMPTS: number;
|
|
|
7
12
|
export declare function reconnectDelayMs(attempt: number): number;
|
|
8
13
|
/** JSON-RPC id the proxy uses for its own replayed `initialize` — never one the client could send. */
|
|
9
14
|
export declare const RECONNECT_INITIALIZE_ID = "__reticle_proxy_reinit";
|
|
10
|
-
/** Name the proxy log after the port it serves. Called before anything can log. */
|
|
11
|
-
export declare function setProxyLogPort(port: number): void;
|
|
12
|
-
/** The proxy's own log file, so a silent drop leaves a readable trace the agent can go read. */
|
|
13
|
-
export declare function proxyLogPath(port?: number | undefined): string;
|
|
14
|
-
/**
|
|
15
|
-
* Log to stderr (which the agent host usually swallows) AND to ~/.reticle/proxy-<port>.log, which it
|
|
16
|
-
* does not. A dropped MCP connection is invisible from the agent's side — no message, no exit code —
|
|
17
|
-
* so the one thing that makes it diagnosable at all is a file somebody can read afterwards.
|
|
18
|
-
*
|
|
19
|
-
* EXPORTED because the crash handlers need it. `installProxyResilience` was wired to the bare stderr
|
|
20
|
-
* logger, so the proxy's own uncaught exceptions and unhandled rejections — the exact events that
|
|
21
|
-
* present to a human as "the MCP server disconnected" — were written to a stream the editor throws
|
|
22
|
-
* away. The handler ran, the process kept serving, and the reason went nowhere. Reported as "the
|
|
23
|
-
* proxy has no log file… when it dies the diagnostic dies with it", which was half right: the file
|
|
24
|
-
* existed, and the one path that most needed it was not using it.
|
|
25
|
-
*/
|
|
26
|
-
export declare function proxyLog(event: string, fields?: Record<string, unknown>): void;
|
|
27
15
|
/**
|
|
28
16
|
* JSON-RPC requests forwarded on behalf of the client that have not been answered yet.
|
|
29
17
|
*
|
|
@@ -56,9 +44,36 @@ export declare class PendingRequests {
|
|
|
56
44
|
* daemon under a live client left 20 of 20 concurrent calls hanging until the client's own timeout,
|
|
57
45
|
* with the MCP server still perfectly alive. An agent cannot tell that apart from "still working".
|
|
58
46
|
*/
|
|
59
|
-
export declare function streamLossReplies(pending: PendingRequests, reason: string): string[];
|
|
60
|
-
/**
|
|
61
|
-
|
|
47
|
+
export declare function streamLossReplies(pending: PendingRequests, reason: string, nextStep?: string): string[];
|
|
48
|
+
/**
|
|
49
|
+
* The one shape every "the transport ate your call" answer takes, whichever leg died.
|
|
50
|
+
*
|
|
51
|
+
* `nextStep` is appended when the caller knows one. Without it this reply describes a condition and
|
|
52
|
+
* stops there, which is all a first-run user got out of their first ever tool call.
|
|
53
|
+
*/
|
|
54
|
+
export declare function transportLossReply(id: unknown, reason: string, nextStep?: string): string;
|
|
55
|
+
/**
|
|
56
|
+
* How long a request may sit in the queue, unsent, before the proxy answers it itself.
|
|
57
|
+
*
|
|
58
|
+
* The second population the stress test found. A request that was FORWARDED and lost is failed when
|
|
59
|
+
* the stream drops; one that never got forwarded — queued while dormant or reconnecting — was
|
|
60
|
+
* waiting for a session that, with a squatter holding the port, never arrives. It then hung until
|
|
61
|
+
* the client's own timeout, or forever if the client has none.
|
|
62
|
+
*
|
|
63
|
+
* Comfortably longer than a daemon restart (~1-2s) so a normal blip still flushes and succeeds, and
|
|
64
|
+
* well under the 60s an MCP client typically allows, so the answer comes from us with a reason
|
|
65
|
+
* rather than from their timer with none.
|
|
66
|
+
*/
|
|
67
|
+
export declare const QUEUE_WAIT_MS = 20000;
|
|
68
|
+
/** Retry a first connect, or report it? Pure, so the window can be held against the queue's. */
|
|
69
|
+
export declare function shouldRetryFirstConnect(error: unknown, elapsedMs: number): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* What to do about it, carried on the reply the queue expiry sends.
|
|
72
|
+
*
|
|
73
|
+
* A bare -32001 on the first call after an install says nothing a user can act on: not whether to
|
|
74
|
+
* wait, not whether to retry, not whether the install itself is broken.
|
|
75
|
+
*/
|
|
76
|
+
export declare function queueExpiryNextStep(port: number): string;
|
|
62
77
|
/**
|
|
63
78
|
* Makes a reconnect invisible to the client.
|
|
64
79
|
*
|
|
@@ -115,15 +130,6 @@ export declare function waitForDaemon(port: number): Promise<void>;
|
|
|
115
130
|
* to reconnect and how to answer what it cannot send.
|
|
116
131
|
*/
|
|
117
132
|
export declare function buildSessionUrl(rawData: string, port: number): string | null;
|
|
118
|
-
/**
|
|
119
|
-
* Bridge stdio ↔ SSE: connects to the running daemon's MCP endpoint and forwards
|
|
120
|
-
* Claude Code's stdin/stdout JSON-RPC through it. Never resolves — runs until stdin closes.
|
|
121
|
-
*
|
|
122
|
-
* A dropped SSE stream used to exit the process, which is what made the agent's `reticle_*` tools
|
|
123
|
-
* vanish mid-session with no message and no way for the agent to get them back — only a human running
|
|
124
|
-
* `/mcp` could. The daemon demonstrably stays up across these drops, so the stream ending is a
|
|
125
|
-
* transport event, not a shutdown: reconnect to it and replay the handshake instead of dying.
|
|
126
|
-
*/
|
|
127
133
|
export declare function startMcpProxy(port: number,
|
|
128
134
|
/**
|
|
129
135
|
* Bring a daemon back before reconnecting. Without it the proxy retried a DEAD port until the
|
|
@@ -131,4 +137,3 @@ export declare function startMcpProxy(port: number,
|
|
|
131
137
|
* failure mode for a daemon that crashed, was stopped, or shut itself down as idle.
|
|
132
138
|
*/
|
|
133
139
|
ensureDaemon?: () => Promise<void>): Promise<never>;
|
|
134
|
-
export {};
|