@pellux/goodvibes-daemon 1.28.19 → 1.28.21
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/CHANGELOG.md +119 -63
- package/README.md +24 -19
- package/bin/launcher-support.js +5 -5
- package/package.json +6 -4
- package/scripts/postinstall.js +8 -8
- package/src/cli/command-catalog.ts +22 -22
- package/src/cli/completion.ts +4 -4
- package/src/cli/help.ts +5 -5
- package/src/cli/index.ts +3 -3
- package/src/cli/parser.ts +2 -2
- package/src/cli/surface-catalog.ts +1 -1
- package/src/cli/types.ts +2 -2
- package/src/cluster/daemon-ws-call.ts +5 -5
- package/src/cluster/raw-reply-route.ts +5 -5
- package/src/config/checkpoint-settings.ts +7 -7
- package/src/config/config-key-guard.ts +22 -0
- package/src/config/run-daemon-config-migration.ts +3 -3
- package/src/config/secret-config.ts +7 -7
- package/src/config/surface.ts +3 -3
- package/src/core/pairing-banner.ts +5 -5
- package/src/daemon/cli.ts +45 -43
- package/src/daemon/config-command.ts +15 -15
- package/src/daemon/handlers/context.ts +1 -1
- package/src/daemon/handlers/contracts.ts +19 -4
- package/src/daemon/handlers/credentials.ts +1 -1
- package/src/daemon/handlers/drafts/draft-store.ts +3 -3
- package/src/daemon/handlers/drafts/register.ts +4 -4
- package/src/daemon/handlers/inbox/aggregator.ts +8 -8
- package/src/daemon/handlers/inbox/cursor-store.ts +10 -10
- package/src/daemon/handlers/inbox/index.ts +7 -7
- package/src/daemon/handlers/inbox/mapping.ts +2 -2
- package/src/daemon/handlers/inbox/poller.ts +5 -5
- package/src/daemon/handlers/inbox/provider-adapter.ts +8 -8
- package/src/daemon/handlers/inbox/providers/discord.ts +6 -6
- package/src/daemon/handlers/inbox/providers/email.ts +3 -3
- package/src/daemon/handlers/inbox/providers/imap-client.ts +1 -1
- package/src/daemon/handlers/inbox/providers/slack.ts +4 -4
- package/src/daemon/handlers/index.ts +18 -8
- package/src/daemon/handlers/payments/address-store.ts +54 -0
- package/src/daemon/handlers/payments/budget-store.ts +356 -0
- package/src/daemon/handlers/payments/card-store.ts +486 -0
- package/src/daemon/handlers/payments/checkout-handlers.ts +526 -0
- package/src/daemon/handlers/payments/index.ts +38 -0
- package/src/daemon/handlers/payments/merchant-judge.ts +57 -0
- package/src/daemon/handlers/payments/notifier.ts +112 -0
- package/src/daemon/handlers/payments/purchase-ledger.ts +108 -0
- package/src/daemon/handlers/payments/register.ts +518 -0
- package/src/daemon/handlers/register.ts +3 -3
- package/src/daemon/handlers/remote/backends/cloud-terminal.ts +9 -1
- package/src/daemon/handlers/remote/backends/process-runner.ts +1 -1
- package/src/daemon/handlers/remote/backends/ssh.ts +9 -1
- package/src/daemon/handlers/remote/backends/types.ts +2 -2
- package/src/daemon/handlers/remote/dispatcher.ts +3 -3
- package/src/daemon/handlers/remote/index.ts +1 -1
- package/src/daemon/handlers/remote/peer-registry.ts +62 -13
- package/src/daemon/handlers/routing/inbox-bridge.ts +5 -5
- package/src/daemon/handlers/routing/index.ts +1 -1
- package/src/daemon/handlers/routing/route-store.ts +1 -1
- package/src/daemon/handlers/routing/routing-resolver.ts +3 -3
- package/src/daemon/handlers/sqlite-store.ts +9 -9
- package/src/daemon/handlers/triage/index.ts +1 -1
- package/src/daemon/handlers/triage/integration.ts +3 -3
- package/src/daemon/handlers/triage/pipeline.ts +2 -2
- package/src/daemon/handlers/triage/scorer.ts +2 -2
- package/src/daemon/handlers/triage/tagger/discord.ts +3 -3
- package/src/daemon/handlers/triage/tagger/imap.ts +7 -7
- package/src/daemon/handlers/triage/tagger/index.ts +1 -1
- package/src/daemon/handlers/triage/tagger/shared.ts +3 -3
- package/src/daemon/handlers/triage/tagger/slack.ts +1 -1
- package/src/daemon/handlers/triage/types.ts +2 -2
- package/src/daemon/lifecycle.ts +5 -5
- package/src/daemon/local-daemon-state.ts +7 -7
- package/src/daemon/pair-command.ts +14 -14
- package/src/daemon/provision-wake-model.ts +5 -5
- package/src/daemon/send/channels.ts +7 -7
- package/src/daemon/send/command.ts +11 -11
- package/src/daemon/send/composition.ts +5 -5
- package/src/daemon/send/failure-text.ts +6 -6
- package/src/daemon/send/inert-text.ts +18 -18
- package/src/daemon/send/stdin.ts +3 -3
- package/src/daemon/service-commands.ts +32 -32
- package/src/daemon/sessions-command.ts +7 -7
- package/src/daemon/status-command.ts +22 -22
- package/src/daemon/webui-command.ts +14 -14
- package/src/runtime/boot-tasks.ts +1 -1
- package/src/runtime/browser-checkout-seam-holder.ts +55 -0
- package/src/runtime/cluster-composition.ts +9 -9
- package/src/runtime/cluster-group-composition.ts +7 -7
- package/src/runtime/conversation-rewind-port.ts +8 -8
- package/src/runtime/credential-composition.ts +2 -2
- package/src/runtime/daemon-handler-composition.ts +61 -4
- package/src/runtime/device-posture-composition.ts +10 -10
- package/src/runtime/disposal-wiring.ts +8 -8
- package/src/runtime/fleet-needs-input-push.ts +4 -4
- package/src/runtime/fleet-services.ts +1 -1
- package/src/runtime/hosted-session-composition.ts +13 -13
- package/src/runtime/index.ts +1 -1
- package/src/runtime/knowledge-services.ts +2 -2
- package/src/runtime/legacy-daemon-migration.ts +43 -43
- package/src/runtime/legacy-daemon-reconcile.ts +30 -30
- package/src/runtime/mail-composition.ts +6 -6
- package/src/runtime/notification-dispatch.ts +7 -7
- package/src/runtime/payments-composition.ts +187 -0
- package/src/runtime/plugin-composition.ts +7 -7
- package/src/runtime/runtime-services-types.ts +9 -9
- package/src/runtime/services.ts +41 -32
- package/src/runtime/trigger-services.ts +1 -1
- package/src/runtime/trust/checkpoint-eligibility.ts +5 -5
- package/src/runtime/trust/trust-gated-approvals.ts +9 -9
- package/src/runtime/update-check.ts +4 -4
- package/src/runtime/workspace-checkpointing.ts +6 -6
- package/src/testing/daemon-fixture.ts +11 -11
- package/src/testing/hosted-session-failures.ts +4 -4
- package/src/version.ts +2 -2
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
*
|
|
24
24
|
* This read is synchronous by design. The decision is made per lifecycle event,
|
|
25
25
|
* inside a subscription callback that cannot await, and it has to reflect the
|
|
26
|
-
* store as it is on disk RIGHT NOW
|
|
26
|
+
* store as it is on disk RIGHT NOW, registering a workspace while the daemon is
|
|
27
27
|
* running has to take effect on the next eligible event, not on the next
|
|
28
28
|
* restart. The SDK's resolver is pure, so the only I/O is one small JSON read
|
|
29
29
|
* plus a single git worktree probe amortized at construction.
|
|
@@ -32,13 +32,13 @@ import {
|
|
|
32
32
|
export type StoreShellPaths = Pick<ShellPathService, 'resolveUserPath' | 'homeDirectory'>;
|
|
33
33
|
|
|
34
34
|
/**
|
|
35
|
-
* Path of the shared store's JSON document
|
|
35
|
+
* Path of the shared store's JSON document, the same path the SDK's gateway
|
|
36
36
|
* verb group constructs its own store over.
|
|
37
37
|
*
|
|
38
38
|
* "The same path" is the whole contract, and it is why this goes through the
|
|
39
39
|
* SDK's resolver rather than spelling any location out. goodvibes-agent reads
|
|
40
40
|
* and writes this same file directly and the SDK's gateway writes it, so the
|
|
41
|
-
* register is cross-product state rather than the daemon's own
|
|
41
|
+
* register is cross-product state rather than the daemon's own, it lives in
|
|
42
42
|
* the shared tier (~/.goodvibes/shared/), which takes no surface root, so all
|
|
43
43
|
* three resolve one identical path. Until the boot fold has moved it, the
|
|
44
44
|
* resolver falls back to the pre-split location read-only, so this reader never
|
|
@@ -92,7 +92,7 @@ interface SharedRegistrationSnapshot {
|
|
|
92
92
|
/**
|
|
93
93
|
* Synchronous read of the shared store's on-disk JSON, mirroring the store's own
|
|
94
94
|
* validation exactly (version 1, workspaces[], declines[]). A missing or
|
|
95
|
-
* unparsable file reads as empty
|
|
95
|
+
* unparsable file reads as empty, never throws.
|
|
96
96
|
*/
|
|
97
97
|
export function readSharedWorkspaceRegistrationSnapshotSync(shellPaths: StoreShellPaths): SharedRegistrationSnapshot {
|
|
98
98
|
const path = sharedWorkspaceRegistrationStorePath(shellPaths);
|
|
@@ -116,7 +116,7 @@ export function readSharedWorkspaceRegistrationSnapshotSync(shellPaths: StoreShe
|
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
/**
|
|
119
|
-
* Resolve `path` against ONLY the checkpoint-eligible registrations
|
|
119
|
+
* Resolve `path` against ONLY the checkpoint-eligible registrations, the
|
|
120
120
|
* boundary the automatic and explicit checkpoint gates consume. Worktree-link
|
|
121
121
|
* inheritance still applies: a linked worktree of a checkpoint-eligible main
|
|
122
122
|
* repository resolves as covered.
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* trust-gated-approvals.ts
|
|
2
|
+
* trust-gated-approvals.ts, how a headless daemon asks the workspace trust
|
|
3
3
|
* question, and how the answer reaches the runs it hosts.
|
|
4
4
|
*
|
|
5
5
|
* The terminal app composes the trust gate at the permission machinery's final
|
|
6
6
|
* ask layer and raises the question as a modal on its own screen. The daemon
|
|
7
|
-
* has the same gate
|
|
8
|
-
* `<cwd>/.goodvibes/<surface>/trust.json` the terminal app writes
|
|
7
|
+
* has the same gate, `trustGatedAsk` next door, reading the same
|
|
8
|
+
* `<cwd>/.goodvibes/<surface>/trust.json` the terminal app writes, and no
|
|
9
9
|
* screen to raise anything on. Before this module it therefore
|
|
10
10
|
* did neither: the gate was constructed, never loaded, never consulted, and no
|
|
11
11
|
* hosted run passed through it.
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* ordinary approval record. That is the whole point of the approval-raise
|
|
17
17
|
* path: a process with no screen states the question, publishes it on
|
|
18
18
|
* `approval-update`, and whichever surface is attached answers it. Approved
|
|
19
|
-
* means "trusted", denied means "restricted"
|
|
19
|
+
* means "trusted", denied means "restricted", a real decision either way,
|
|
20
20
|
* persisted by the gate, and never asked again for this workspace.
|
|
21
21
|
*
|
|
22
22
|
* 2. `trustGatedApprovalRaiser` puts the gate in front of the raiser the
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
*
|
|
31
31
|
* What the daemon does NOT do here is decide by default. An untrusted
|
|
32
32
|
* workspace's hosted run neither runs as if trusted nor fails as if refused: it
|
|
33
|
-
* asks. If the ask cannot be answered
|
|
34
|
-
* failed
|
|
33
|
+
* asks. If the ask cannot be answered, nothing attached, or the broker itself
|
|
34
|
+
* failed, the workspace stays undecided and this run is refused, with the
|
|
35
35
|
* reason in the log rather than in a silence. A refusal that records nothing is
|
|
36
36
|
* the failure mode this whole seam exists to remove.
|
|
37
37
|
*/
|
|
@@ -44,7 +44,7 @@ type WorkspaceTrustLevel = operations.WorkspaceTrustLevel;
|
|
|
44
44
|
type WorkspaceTrustManager = operations.WorkspaceTrustManager;
|
|
45
45
|
|
|
46
46
|
/**
|
|
47
|
-
* The extra fields a raise carries beside the request itself
|
|
47
|
+
* The extra fields a raise carries beside the request itself, the attribution
|
|
48
48
|
* routing/metadata a background-agent ask is stamped with before it reaches the
|
|
49
49
|
* broker. The gate only reads `request.category`, so these ride around it.
|
|
50
50
|
*/
|
|
@@ -73,7 +73,7 @@ export const WORKSPACE_TRUST_ASK_TIMEOUT_MS = 10 * 60 * 1000;
|
|
|
73
73
|
|
|
74
74
|
export interface WorkspaceTrustDecisionAskDeps {
|
|
75
75
|
readonly requestApproval: ApprovalRaise;
|
|
76
|
-
/** The workspace the question is about
|
|
76
|
+
/** The workspace the question is about, it names the directory being trusted. */
|
|
77
77
|
readonly workingDirectory: string;
|
|
78
78
|
readonly timeoutMs?: number | undefined;
|
|
79
79
|
}
|
|
@@ -118,7 +118,7 @@ export function createWorkspaceTrustDecisionAsk(
|
|
|
118
118
|
return decision.approved ? 'trusted' : 'restricted';
|
|
119
119
|
} catch (error) {
|
|
120
120
|
// Nothing attached, or the broker failed. Say so and leave the workspace
|
|
121
|
-
// undecided
|
|
121
|
+
// undecided, the next run asks again rather than inheriting a decision
|
|
122
122
|
// nobody made.
|
|
123
123
|
logger.warn('Workspace trust question could not be answered; this run is refused and the workspace stays undecided', {
|
|
124
124
|
workspace: deps.workingDirectory,
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Version comparison and the release-tag lookup are re-exported from the
|
|
6
6
|
* SDK's canonical update policy module (platform/runtime/self-update), which
|
|
7
|
-
* was hoisted from this file's semantics
|
|
7
|
+
* was hoisted from this file's semantics, one mechanism everywhere.
|
|
8
8
|
* Install-kind detection stays local: it encodes how THIS package is
|
|
9
9
|
* installed (compiled binary vs bun/npm package vs source run) and what
|
|
10
10
|
* command replaces a swap for each kind.
|
|
@@ -27,14 +27,14 @@ export {
|
|
|
27
27
|
* How this running process was installed, detected honestly from
|
|
28
28
|
* process.execPath rather than assumed:
|
|
29
29
|
* - "binary": a standalone `bun build --compile` executable with no
|
|
30
|
-
* package-manager ancestry
|
|
30
|
+
* package-manager ancestry, the scripts/install.sh install path.
|
|
31
31
|
* Swappable in place.
|
|
32
32
|
* - "bun-global-package": running the vendored binary shipped inside an
|
|
33
33
|
* npm/bun-managed package install (execPath contains a "node_modules"
|
|
34
|
-
* path segment
|
|
34
|
+
* path segment, true for both `bun add -g` and a local project
|
|
35
35
|
* dependency). Managed by the package manager; swapping the vendored
|
|
36
36
|
* file in place would fight the next `bun add -g` upgrade, so this is
|
|
37
|
-
* never swapped
|
|
37
|
+
* never swapped, the user re-runs their package manager instead.
|
|
38
38
|
* - "source": running directly via the `bun` interpreter (`bun run
|
|
39
39
|
* src/main.ts`), not a compiled binary at all.
|
|
40
40
|
*/
|
|
@@ -17,19 +17,19 @@ import { createWorkspaceRegistrationLiveChecker, type StoreShellPaths } from './
|
|
|
17
17
|
* runtime bus, so building it without one for an unregistered workspace would
|
|
18
18
|
* mean registering that workspace mid-run had no effect until a restart. It is
|
|
19
19
|
* always built WITH the bus and each individual automatic snapshot attempt is
|
|
20
|
-
* refused instead
|
|
20
|
+
* refused instead, by overriding this one instance's own `create`, since the
|
|
21
21
|
* manager has no predicate hook and `create` is the single seam both the
|
|
22
22
|
* automatic subscription and every explicit caller pass through.
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
25
|
export interface WorkspaceCheckpointing {
|
|
26
|
-
/** The manager itself
|
|
26
|
+
/** The manager itself, automatic snapshots gated, explicit creates unrestricted. */
|
|
27
27
|
readonly manager: WorkspaceCheckpointManager;
|
|
28
28
|
/**
|
|
29
29
|
* The narrower surface handed to the `checkpoints.*` gateway verbs: identical
|
|
30
30
|
* except that an explicit create refuses, with an actionable message, when the
|
|
31
31
|
* workspace is not checkpoint-eligible. Reads (list/diff/sessionChanges) and
|
|
32
|
-
* restore stay unrestricted
|
|
32
|
+
* restore stay unrestricted, they operate over checkpoints that may already
|
|
33
33
|
* exist, including from a since-unregistered workspace.
|
|
34
34
|
*/
|
|
35
35
|
readonly gatewayManager: Pick<WorkspaceCheckpointManager, 'list' | 'create' | 'diff' | 'restore' | 'sessionChanges' | 'workspaceRoot'>;
|
|
@@ -69,7 +69,7 @@ export function createWorkspaceCheckpointing(opts: {
|
|
|
69
69
|
});
|
|
70
70
|
|
|
71
71
|
// Automatic snapshots ('turn' | 'agent-run', fired by the manager's own bus
|
|
72
|
-
// subscription) resolve to null quietly when the workspace is not eligible
|
|
72
|
+
// subscription) resolve to null quietly when the workspace is not eligible,
|
|
73
73
|
// there is no caller to throw to, and the manager already documents a null
|
|
74
74
|
// return as the cheap no-op for an unchanged tree. Explicit ('manual') creates
|
|
75
75
|
// are NOT re-gated here: they go through the gateway surface below, which
|
|
@@ -82,7 +82,7 @@ export function createWorkspaceCheckpointing(opts: {
|
|
|
82
82
|
|
|
83
83
|
// Eagerly initialize so the automatic-snapshot subscription is live before the
|
|
84
84
|
// first turn completes. If init() rejects, the manager caches that rejection
|
|
85
|
-
// forever and every later call re-throws it
|
|
85
|
+
// forever and every later call re-throws it, the catch here only prevents an
|
|
86
86
|
// unhandled rejection at startup; the checkpoint verbs report the failure to
|
|
87
87
|
// whoever calls them.
|
|
88
88
|
void manager.init().catch((error: unknown) => {
|
|
@@ -104,7 +104,7 @@ export function createWorkspaceCheckpointing(opts: {
|
|
|
104
104
|
);
|
|
105
105
|
}
|
|
106
106
|
// Default the session stamp from the live resolver when the caller omits
|
|
107
|
-
// it
|
|
107
|
+
// it, the resolveSessionId hook only auto-stamps automatic snapshots, so
|
|
108
108
|
// without this an explicit checkpoint made this launch would be written
|
|
109
109
|
// unstamped and excluded by the session-scoped restore lookup.
|
|
110
110
|
const sessionId = createOpts.sessionId ?? opts.resolveSessionId?.({});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* daemon-fixture.ts
|
|
2
|
+
* daemon-fixture.ts, a real, running daemon, composed the way this product
|
|
3
3
|
* composes one, for a test to drive.
|
|
4
4
|
*
|
|
5
5
|
* ── Why this is a shipped module and not a test helper ────────────────────
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* and each of them hand-builds a composition to test against: a stub session
|
|
9
9
|
* broker here, a fake approval broker there, a catalog with the handlers
|
|
10
10
|
* somebody remembered to attach. They are large (several hundred lines each),
|
|
11
|
-
* they duplicate each other, and
|
|
11
|
+
* they duplicate each other, and, the part that matters, they are each a
|
|
12
12
|
* SECOND idea of what a daemon is. A client contract test passing against a
|
|
13
13
|
* hand-rolled stand-in tells you the stand-in agrees with the client, which is
|
|
14
14
|
* the one agreement that was never in doubt.
|
|
@@ -43,19 +43,19 @@
|
|
|
43
43
|
* can do for itself:
|
|
44
44
|
*
|
|
45
45
|
* 1. A NAMED ENTRY POINT. `goodvibes-daemon/testing` instead of the deep
|
|
46
|
-
* path. That means adding an `exports` map to package.json
|
|
46
|
+
* path. That means adding an `exports` map to package.json, and adding
|
|
47
47
|
* one is not additive: an `exports` map REPLACES path-based resolution, so
|
|
48
48
|
* every existing deep import into this package (its own `bin` shim
|
|
49
49
|
* included) stops resolving unless the map enumerates them. That is a
|
|
50
50
|
* packaging change with a blast radius, made once, deliberately, by
|
|
51
|
-
* whoever owns distribution
|
|
51
|
+
* whoever owns distribution, not a side effect of adding a test helper.
|
|
52
52
|
*
|
|
53
53
|
* 2. THE CONSUMER DEPENDENCY. A consumer repo has to depend on
|
|
54
54
|
* `goodvibes-daemon` to import this at all. Today the agent does (it is
|
|
55
55
|
* what makes its own install fail against an unpublished version); the
|
|
56
56
|
* terminal app and the webui do not. For the terminal app that is a
|
|
57
57
|
* devDependency and a version pin. For the webui, whose suites run in a
|
|
58
|
-
* browser context, the fixture cannot run in-process at all
|
|
58
|
+
* browser context, the fixture cannot run in-process at all, it needs a
|
|
59
59
|
* launcher script that starts the fixture in a node process and hands the
|
|
60
60
|
* Playwright suite `baseUrl` and `token`. That launcher does not exist and
|
|
61
61
|
* should be written on the webui side, where its runner lives.
|
|
@@ -65,12 +65,12 @@
|
|
|
65
65
|
* per test file pays about a second each and must `stop()` every one; the
|
|
66
66
|
* three hand-built stand-ins it replaces cost nothing and leak nothing.
|
|
67
67
|
* The honest guidance is one fixture per FILE (`beforeAll`/`afterAll`),
|
|
68
|
-
* which is how this repository's own suites use it
|
|
68
|
+
* which is how this repository's own suites use it, not one per test.
|
|
69
69
|
*
|
|
70
70
|
* 4. WHAT IT DOES NOT REPLACE. A stand-in is still the right tool for
|
|
71
71
|
* driving a client through a daemon state that is hard to reach for real:
|
|
72
72
|
* a wedged session, a specific 500, a torn connection. This fixture
|
|
73
|
-
* replaces the stand-ins that exist only to answer normally
|
|
73
|
+
* replaces the stand-ins that exist only to answer normally, which is
|
|
74
74
|
* most of the several hundred lines in each consumer, and all of the part
|
|
75
75
|
* that silently drifts. The refusal shapes it cannot easily produce live
|
|
76
76
|
* are exported separately and pinned against the real engine; see
|
|
@@ -145,7 +145,7 @@ export interface DaemonFixtureOptions {
|
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
export interface DaemonFixture {
|
|
148
|
-
/** The composed runtime graph
|
|
148
|
+
/** The composed runtime graph, the same object `DaemonServer` was handed. */
|
|
149
149
|
readonly services: RuntimeServices;
|
|
150
150
|
/** The running server. */
|
|
151
151
|
readonly daemon: DaemonServer;
|
|
@@ -159,7 +159,7 @@ export interface DaemonFixture {
|
|
|
159
159
|
fetch(path: string, init?: RequestInit): Promise<Response>;
|
|
160
160
|
/**
|
|
161
161
|
* Fetch a path with NO credential. A route that exists answers 401; a path
|
|
162
|
-
* nothing serves answers 404
|
|
162
|
+
* nothing serves answers 404, which is what makes this the side-effect-free
|
|
163
163
|
* way to ask whether a route exists, even for a write verb.
|
|
164
164
|
*/
|
|
165
165
|
fetchAnonymous(path: string, init?: RequestInit): Promise<Response>;
|
|
@@ -170,7 +170,7 @@ export interface DaemonFixture {
|
|
|
170
170
|
}
|
|
171
171
|
|
|
172
172
|
/**
|
|
173
|
-
* Compose and start a daemon. Always `await fixture.stop()
|
|
173
|
+
* Compose and start a daemon. Always `await fixture.stop()`, the runtime graph
|
|
174
174
|
* starts pollers while it builds, and abandoning it leaves every one of them
|
|
175
175
|
* firing for the rest of the process.
|
|
176
176
|
*/
|
|
@@ -234,7 +234,7 @@ export async function startDaemonFixture(options: DaemonFixtureOptions = {}): Pr
|
|
|
234
234
|
// What the real entrypoint states, for the same reason it states it: the
|
|
235
235
|
// hosted-session verbs are registered by this composition and by nothing
|
|
236
236
|
// else, so a fixture that leaves it out is a daemon a client cannot start a
|
|
237
|
-
// session on
|
|
237
|
+
// session on, and every contract test written against it would agree.
|
|
238
238
|
...(options.hostSessions === false ? {} : { hostedSessions: createHostedSessionOptions(services) }),
|
|
239
239
|
});
|
|
240
240
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* hosted-session-failures.ts
|
|
2
|
+
* hosted-session-failures.ts, what `sessions.hosted.*` answers when it refuses.
|
|
3
3
|
*
|
|
4
4
|
* ── Why this is a shipped module ─────────────────────────────────────────
|
|
5
5
|
*
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* These are the three refusals a client has to handle and could not previously
|
|
20
20
|
* mock. They are declared here rather than hand-written in each consumer, and
|
|
21
21
|
* `src/test/daemon/gateway-hosted-session-failures.test.ts` drives the REAL
|
|
22
|
-
* engine to produce each one and asserts it still matches
|
|
22
|
+
* engine to produce each one and asserts it still matches, so a fixture that
|
|
23
23
|
* drifts from the daemon fails in this repository, not in a consumer's CI six
|
|
24
24
|
* weeks later.
|
|
25
25
|
*/
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
export interface HostedSessionFailureFixture {
|
|
29
29
|
/** The verb whose refusal this is. */
|
|
30
30
|
readonly methodId: string;
|
|
31
|
-
/** Machine-readable code
|
|
31
|
+
/** Machine-readable code, the field a client branches on. */
|
|
32
32
|
readonly code: string;
|
|
33
33
|
/** HTTP status the control plane maps this refusal to. */
|
|
34
34
|
readonly status: number;
|
|
@@ -65,7 +65,7 @@ export const HOSTED_SESSION_UNAVAILABLE: HostedSessionFailureFixture = {
|
|
|
65
65
|
|
|
66
66
|
/**
|
|
67
67
|
* At the configured cap. 429: the request is well-formed and the daemon is not
|
|
68
|
-
* broken
|
|
68
|
+
* broken, there is no room. Retrying after a kill succeeds.
|
|
69
69
|
*/
|
|
70
70
|
export const HOSTED_SESSION_LIMIT_REACHED: HostedSessionFailureFixture = {
|
|
71
71
|
methodId: 'sessions.hosted.create',
|
package/src/version.ts
CHANGED
|
@@ -13,14 +13,14 @@ try {
|
|
|
13
13
|
// compiled binary resolves import.meta.dir to a virtual root where the
|
|
14
14
|
// `../package.json` path can land on a DIFFERENT package.json (a bundled
|
|
15
15
|
// dependency's, or the embedded runtime's) that reports a placeholder like
|
|
16
|
-
// "0.0.0"
|
|
16
|
+
// "0.0.0", exactly the wrong-version banner a bare daemon launch showed in
|
|
17
17
|
// the field. Guarding on the package name means the prebuild-baked fallback
|
|
18
18
|
// above wins in that case instead of a stray version.
|
|
19
19
|
if (pkg?.name === 'goodvibes-daemon' && typeof pkg.version === 'string' && pkg.version.length > 0) {
|
|
20
20
|
_version = pkg.version;
|
|
21
21
|
}
|
|
22
22
|
} catch {
|
|
23
|
-
// Compiled binary or missing package.json
|
|
23
|
+
// Compiled binary or missing package.json, use fallback
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
export const VERSION = _version;
|