@stateforge-labs/herdr 0.0.0-stage → 0.3.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.
Files changed (171) hide show
  1. package/LICENSE +18 -0
  2. package/NOTICE.md +51 -0
  3. package/README.md +211 -2
  4. package/bin/herdr-drift.js +14 -0
  5. package/bin/herdr-skill.js +38 -0
  6. package/dist/admin.d.ts +2 -0
  7. package/dist/admin.js +3 -0
  8. package/dist/constants.d.ts +236 -0
  9. package/dist/constants.js +294 -0
  10. package/dist/core/backoff.d.ts +20 -0
  11. package/dist/core/backoff.js +53 -0
  12. package/dist/core/constants.d.ts +143 -0
  13. package/dist/core/constants.js +98 -0
  14. package/dist/core/errors.d.ts +35 -0
  15. package/dist/core/errors.js +16 -0
  16. package/dist/core/events.d.ts +42 -0
  17. package/dist/core/events.js +128 -0
  18. package/dist/core/kernel.d.ts +65 -0
  19. package/dist/core/kernel.js +138 -0
  20. package/dist/core/link.d.ts +47 -0
  21. package/dist/core/link.js +187 -0
  22. package/dist/core/test-kit/constants.d.ts +51 -0
  23. package/dist/core/test-kit/constants.js +43 -0
  24. package/dist/core/test-kit/fake-core.d.ts +61 -0
  25. package/dist/core/test-kit/fake-core.js +228 -0
  26. package/dist/core/test-kit/frames.d.ts +1 -0
  27. package/dist/core/test-kit/frames.js +480 -0
  28. package/dist/core/test-kit/setup-test.d.ts +18 -0
  29. package/dist/core/test-kit/setup-test.js +35 -0
  30. package/dist/core/wire.d.ts +85 -0
  31. package/dist/core/wire.js +199 -0
  32. package/dist/core-test-kit.d.ts +5 -0
  33. package/dist/core-test-kit.js +5 -0
  34. package/dist/core.d.ts +15 -0
  35. package/dist/core.js +12 -0
  36. package/dist/drift/cli.d.ts +22 -0
  37. package/dist/drift/cli.js +146 -0
  38. package/dist/drift/constants.d.ts +83 -0
  39. package/dist/drift/constants.js +73 -0
  40. package/dist/drift/diff.d.ts +7 -0
  41. package/dist/drift/diff.js +91 -0
  42. package/dist/drift/schema.d.ts +19 -0
  43. package/dist/drift/schema.js +190 -0
  44. package/dist/drift/types.d.ts +76 -0
  45. package/dist/drift/types.js +1 -0
  46. package/dist/drift.d.ts +5 -0
  47. package/dist/drift.js +6 -0
  48. package/dist/effect.d.ts +3 -0
  49. package/dist/effect.js +4 -0
  50. package/dist/herdr/client/connect.d.ts +5 -0
  51. package/dist/herdr/client/connect.js +81 -0
  52. package/dist/herdr/client/held.d.ts +54 -0
  53. package/dist/herdr/client/held.js +100 -0
  54. package/dist/herdr/client/long-poll.d.ts +33 -0
  55. package/dist/herdr/client/long-poll.js +66 -0
  56. package/dist/herdr/client/scoped.d.ts +45 -0
  57. package/dist/herdr/client/scoped.js +241 -0
  58. package/dist/herdr/client/streams.d.ts +9 -0
  59. package/dist/herdr/client/streams.js +40 -0
  60. package/dist/herdr/client/subscribe.d.ts +75 -0
  61. package/dist/herdr/client/subscribe.js +208 -0
  62. package/dist/herdr/client/types.d.ts +150 -0
  63. package/dist/herdr/client/types.js +1 -0
  64. package/dist/herdr/client/watch-pane-set.d.ts +34 -0
  65. package/dist/herdr/client/watch-pane-set.js +271 -0
  66. package/dist/herdr/client/watch.d.ts +117 -0
  67. package/dist/herdr/client/watch.js +138 -0
  68. package/dist/herdr/effect/to-tagged-error.d.ts +2 -0
  69. package/dist/herdr/effect/to-tagged-error.js +54 -0
  70. package/dist/herdr/effect/types.d.ts +51 -0
  71. package/dist/herdr/effect/types.js +26 -0
  72. package/dist/herdr/errors.d.ts +53 -0
  73. package/dist/herdr/errors.js +87 -0
  74. package/dist/herdr/generated/entries/admin.d.ts +2 -0
  75. package/dist/herdr/generated/entries/admin.js +5 -0
  76. package/dist/herdr/generated/entries/client.d.ts +2 -0
  77. package/dist/herdr/generated/entries/client.js +5 -0
  78. package/dist/herdr/generated/entries/held.d.ts +2 -0
  79. package/dist/herdr/generated/entries/held.js +5 -0
  80. package/dist/herdr/generated/entries/prompt.d.ts +2 -0
  81. package/dist/herdr/generated/entries/prompt.js +5 -0
  82. package/dist/herdr/generated/entries/read-only-content.d.ts +2 -0
  83. package/dist/herdr/generated/entries/read-only-content.js +5 -0
  84. package/dist/herdr/generated/entries/read-only.d.ts +2 -0
  85. package/dist/herdr/generated/entries/read-only.js +5 -0
  86. package/dist/herdr/generated/entry-methods.d.ts +9 -0
  87. package/dist/herdr/generated/entry-methods.js +17 -0
  88. package/dist/herdr/generated/errors.d.ts +4 -0
  89. package/dist/herdr/generated/errors.js +3 -0
  90. package/dist/herdr/generated/events.d.ts +274 -0
  91. package/dist/herdr/generated/events.js +3 -0
  92. package/dist/herdr/generated/index.d.ts +20 -0
  93. package/dist/herdr/generated/index.js +19 -0
  94. package/dist/herdr/generated/method-table.d.ts +615 -0
  95. package/dist/herdr/generated/method-table.js +106 -0
  96. package/dist/herdr/generated/names/agent-status.d.ts +10 -0
  97. package/dist/herdr/generated/names/agent-status.js +10 -0
  98. package/dist/herdr/generated/names/capability-class.d.ts +14 -0
  99. package/dist/herdr/generated/names/capability-class.js +15 -0
  100. package/dist/herdr/generated/names/event-kind.d.ts +31 -0
  101. package/dist/herdr/generated/names/event-kind.js +31 -0
  102. package/dist/herdr/generated/names/event-match-kind.d.ts +23 -0
  103. package/dist/herdr/generated/names/event-match-kind.js +24 -0
  104. package/dist/herdr/generated/names/index.d.ts +10 -0
  105. package/dist/herdr/generated/names/index.js +12 -0
  106. package/dist/herdr/generated/names/method.d.ts +209 -0
  107. package/dist/herdr/generated/names/method.js +209 -0
  108. package/dist/herdr/generated/names/result-tag.d.ts +68 -0
  109. package/dist/herdr/generated/names/result-tag.js +68 -0
  110. package/dist/herdr/generated/names/server-capability.d.ts +10 -0
  111. package/dist/herdr/generated/names/server-capability.js +11 -0
  112. package/dist/herdr/generated/names/subscription-event-kind.d.ts +8 -0
  113. package/dist/herdr/generated/names/subscription-event-kind.js +8 -0
  114. package/dist/herdr/generated/names/subscription-type.d.ts +31 -0
  115. package/dist/herdr/generated/names/subscription-type.js +32 -0
  116. package/dist/herdr/generated/names/token-name-pattern.d.ts +2 -0
  117. package/dist/herdr/generated/names/token-name-pattern.js +4 -0
  118. package/dist/herdr/generated/namespaces.d.ts +785 -0
  119. package/dist/herdr/generated/namespaces.js +3 -0
  120. package/dist/herdr/generated/overrides.d.ts +33 -0
  121. package/dist/herdr/generated/overrides.js +20 -0
  122. package/dist/herdr/generated/params.d.ts +799 -0
  123. package/dist/herdr/generated/params.js +3 -0
  124. package/dist/herdr/generated/preset-methods.d.ts +4 -0
  125. package/dist/herdr/generated/preset-methods.js +7 -0
  126. package/dist/herdr/generated/presets/sessions-reader.d.ts +2 -0
  127. package/dist/herdr/generated/presets/sessions-reader.js +5 -0
  128. package/dist/herdr/generated/results.d.ts +978 -0
  129. package/dist/herdr/generated/results.js +52 -0
  130. package/dist/herdr/generated/test-data/defaults.d.ts +739 -0
  131. package/dist/herdr/generated/test-data/defaults.js +741 -0
  132. package/dist/herdr/generated/test-data/shapes.d.ts +1325 -0
  133. package/dist/herdr/generated/test-data/shapes.js +2245 -0
  134. package/dist/herdr/test-kit/fake-herdr.d.ts +13 -0
  135. package/dist/herdr/test-kit/fake-herdr.js +216 -0
  136. package/dist/herdr/test-kit/fake-protocol.d.ts +107 -0
  137. package/dist/herdr/test-kit/fake-protocol.js +436 -0
  138. package/dist/herdr/test-kit/types.d.ts +88 -0
  139. package/dist/herdr/test-kit/types.js +1 -0
  140. package/dist/herdr/wire/codec.d.ts +36 -0
  141. package/dist/herdr/wire/codec.js +62 -0
  142. package/dist/herdr/wire/connection.d.ts +13 -0
  143. package/dist/herdr/wire/connection.js +65 -0
  144. package/dist/herdr/wire/dedicated.d.ts +2 -0
  145. package/dist/herdr/wire/dedicated.js +238 -0
  146. package/dist/herdr/wire/push-decoder.d.ts +2 -0
  147. package/dist/herdr/wire/push-decoder.js +40 -0
  148. package/dist/herdr/wire/rpc.d.ts +3 -0
  149. package/dist/herdr/wire/rpc.js +141 -0
  150. package/dist/herdr/wire/socket-path.d.ts +8 -0
  151. package/dist/herdr/wire/socket-path.js +23 -0
  152. package/dist/herdr/wire/types.d.ts +78 -0
  153. package/dist/herdr/wire/types.js +1 -0
  154. package/dist/index.d.ts +11 -0
  155. package/dist/index.js +7 -0
  156. package/dist/read-only.d.ts +5 -0
  157. package/dist/read-only.js +6 -0
  158. package/dist/schema.d.ts +5 -0
  159. package/dist/schema.js +6 -0
  160. package/dist/test-kit.d.ts +2 -0
  161. package/dist/test-kit.js +3 -0
  162. package/docs/api/events.md +43 -0
  163. package/docs/api/methods.md +232 -0
  164. package/package.json +112 -4
  165. package/schema/herdr-api.schema.json +10759 -0
  166. package/schema/herdr-version.json +5 -0
  167. package/skills/herdr-sdk/SKILL.md +75 -0
  168. package/skills/herdr-sdk/references/api-map.md +28 -0
  169. package/skills/herdr-sdk/references/errors.md +19 -0
  170. package/skills/herdr-sdk/references/recipes.md +171 -0
  171. package/skills/herdr-sdk/references/versions.md +7 -0
@@ -0,0 +1,294 @@
1
+ // Role: every literal the library uses outside the generated modules, as as-const objects; no consumers in phase 1b.
2
+ // Informs HERDR-ADR-0003 (layering) and plan section 3 ("every literal lives in constants.ts"), 3.1, 3.3 and 3.6.
3
+ import { ServerCapability, SubscriptionType } from './herdr/generated/index.js';
4
+ export { TOKEN_NAME_PATTERN } from './herdr/generated/names/token-name-pattern.js';
5
+ // Environment variable names and the default socket location.
6
+ export const HerdrEnv = {
7
+ Socket: 'HERDR_SOCKET',
8
+ Home: 'HOME',
9
+ Live: 'HERDR_LIVE',
10
+ };
11
+ // Path parts of the default herdr socket, ~/.config/herdr/herdr.sock.
12
+ export const SocketPathPart = {
13
+ ConfigDir: '.config',
14
+ HerdrDir: 'herdr',
15
+ SocketFile: 'herdr.sock',
16
+ };
17
+ // Request timeout and the margin added to a long-poll timeout (plan 3.3 gives 10 s; the margin is new, the owner may tune it).
18
+ export const Timeout = {
19
+ DefaultMs: 10_000,
20
+ LongPollMarginMs: 5_000,
21
+ };
22
+ // Reconnect backoff for held and subscription connections.
23
+ export const Backoff = {
24
+ InitialMs: 1_000,
25
+ MaxMs: 30_000,
26
+ Factor: 2,
27
+ // A connection that stayed up this long resets the backoff to InitialMs.
28
+ StableResetMs: 60_000,
29
+ };
30
+ // Protocol compatibility policy: exact match by default, minimum is optional.
31
+ export const ProtocolPolicy = {
32
+ Exact: 'exact',
33
+ Minimum: 'minimum',
34
+ };
35
+ // Queue overflow behaviour of a subscription (plan 3.6).
36
+ export const Overflow = {
37
+ DropOldest: 'drop-oldest',
38
+ Fail: 'fail',
39
+ };
40
+ // Kinds of watch handle (plan 3.6; hand-kept, not generated).
41
+ export const WatchKind = {
42
+ Live: 'live',
43
+ Frame: 'frame',
44
+ };
45
+ // Keys of PRESET_METHODS in names.ts.
46
+ export const Presets = {
47
+ SessionsReader: 'SessionsReader',
48
+ };
49
+ // Prefix of subscription request ids.
50
+ export const SUBSCRIBE_ID_PREFIX = 'sub';
51
+ // Error message builders; functions, so the wording lives in one place.
52
+ export const ErrorText = {
53
+ NoAck: (ms) => `no ack within ${ms}ms`,
54
+ Unavailable: (method, what) => `${method}: ${what}`,
55
+ NoResponse: (method, ms) => `${method}: no response within ${ms}ms`,
56
+ Aborted: (method) => `${method}: aborted`,
57
+ Unparseable: (method) => `${method}: unparseable response`,
58
+ ClosedBeforeResponse: (method) => `${method}: connection closed before a response`,
59
+ ClientClosed: (method) => `${method}: client is closed`,
60
+ SocketError: (method) => `${method}: socket error`,
61
+ CannotConnect: (path) => `cannot connect to herdr socket at ${path}`,
62
+ NoSocket: (path) => `no herdr socket at ${path}`,
63
+ ProtocolMismatch: (expected, actual) => `herdr protocol ${actual} is not supported (expected ${expected})`,
64
+ Unsupported: (method, capability) => `${method}: server lacks capability ${capability}`,
65
+ Refused: (method, message, code) => `${method}: ${message} [${code}]`,
66
+ SubscriptionEnded: (method) => `${method}: the server closed the subscription`,
67
+ NotImplemented: (what, lane) => `${what} is not implemented yet (owned by lane ${lane}, HERDR-ADR-0017)`,
68
+ NotAllowed: (method) => `${method}: not allowed on this client`,
69
+ };
70
+ // Error class names, set as `name` on each wire error class (so the names are not typed twice).
71
+ export const ErrorName = {
72
+ Herdr: 'HerdrError',
73
+ Transport: 'HerdrTransportError',
74
+ ProtocolMismatch: 'ProtocolMismatchError',
75
+ UnsupportedByServer: 'UnsupportedByServerError',
76
+ SubscriptionEnded: 'SubscriptionEnded',
77
+ NotImplemented: 'NotImplementedError',
78
+ MalformedSchema: 'MalformedSchemaError',
79
+ UnsupportedWatch: 'UnsupportedWatchError',
80
+ };
81
+ // JSON field names of the NDJSON wire envelopes.
82
+ export const WireField = {
83
+ Id: 'id',
84
+ Method: 'method',
85
+ Params: 'params',
86
+ Result: 'result',
87
+ Error: 'error',
88
+ Code: 'code',
89
+ Message: 'message',
90
+ Type: 'type',
91
+ Protocol: 'protocol',
92
+ Version: 'version',
93
+ Capabilities: 'capabilities',
94
+ Event: 'event',
95
+ };
96
+ // Prefix of request ids The id is an echo, not a correlation key (HERDR-ADR-0016 W1).
97
+ export const REQUEST_ID_PREFIX = 'sdk';
98
+ // Id herdr returns for an unparseable request, followed by a close (HERDR-ADR-0016 W3).
99
+ export const EMPTY_REPLY_ID = '';
100
+ // One NDJSON line ends with a newline.
101
+ export const LINE_SEPARATOR = '\n';
102
+ // Socket text encoding.
103
+ export const TEXT_ENCODING = 'utf8';
104
+ // Outcome of one call, reported to the onCall hook.
105
+ export const CallOutcome = {
106
+ Answered: 'answered',
107
+ Refused: 'refused',
108
+ Transport: 'transport',
109
+ };
110
+ // Results of `typeof x`: a JSON object envelope, and a text value (the fake writes a string line as it is).
111
+ export const TypeofTag = {
112
+ Object: 'object',
113
+ String: 'string',
114
+ };
115
+ // Test-kit facts of the minimal fake (not herdr facts). F6 and W3 values are the fake's own choice, not measured.
116
+ export const Fake = {
117
+ DirPrefix: 'herdr-fake-',
118
+ SocketFile: 'herdr.sock',
119
+ Version: '0.9.5-fake',
120
+ UnknownMethodCode: 'unknown_method',
121
+ InvalidRequestCode: 'invalid_request',
122
+ // Delay between the two halves of a split subscribe ack (test convenience, splitAck).
123
+ SplitAckDelayMs: 5,
124
+ };
125
+ // Texts the fake puts in its own error envelopes.
126
+ export const FakeText = {
127
+ UnknownMethod: (method) => `unknown method ${method}`,
128
+ InvalidRequest: 'unparseable request',
129
+ };
130
+ // Capabilities the fake's pong advertises when a test does not choose (the fake's own choice, not herdr's).
131
+ export const DEFAULT_CAPABILITIES = {
132
+ [ServerCapability.DetachedServerDaemon]: true,
133
+ [ServerCapability.HealthCheck]: true,
134
+ [ServerCapability.LiveHandoff]: true,
135
+ [ServerCapability.SshAgentRegistration]: true,
136
+ [ServerCapability.SurfaceInterest]: true,
137
+ };
138
+ // What the fake does with one request line: stay silent, write a raw line, or write an envelope.
139
+ export const AnswerKind = {
140
+ Silent: 'silent',
141
+ Raw: 'raw',
142
+ Envelope: 'envelope',
143
+ };
144
+ // Where one fake connection stands after its last answer (test-kit only): still open for requests, answered and ended,
145
+ // a subscriber after its ack (pushes flow), or a held connection (class C; answers every request, stays open).
146
+ export const ServedState = {
147
+ Fresh: 'fresh',
148
+ Answered: 'answered',
149
+ Subscriber: 'subscriber',
150
+ Held: 'held',
151
+ };
152
+ // ---------------------------------------------------------------------------------------------
153
+ // Contract constants (HERDR-ADR-0017, docs/architecture/contracts.md). Locked: lanes read them, the architect amends them.
154
+ // ---------------------------------------------------------------------------------------------
155
+ // The `event` of a push frame whose kind this library does not know (HERDR-ADR-0016 P3). Not a herdr value, so it cannot collide.
156
+ export const UNKNOWN_EVENT = '@stateforge-labs/herdr:unknown-event';
157
+ // Kinds of change watchPaneSet emits (plan 3.6, HERDR-ADR-0016 W6).
158
+ export const PaneSetKind = {
159
+ Added: 'added',
160
+ Removed: 'removed',
161
+ Frame: 'frame',
162
+ };
163
+ // Subscription types that need pane_id (HERDR-ADR-0016 W6). Not a hand copy that can drift: the contract test
164
+ // test/types/contract/subscription-lists.ts fails to compile unless this list equals PerPaneSubscriptionType exactly.
165
+ export const PER_PANE_SUBSCRIPTION_TYPES = [
166
+ SubscriptionType.PaneOutputMatched,
167
+ SubscriptionType.PaneAgentStatusChanged,
168
+ SubscriptionType.PaneScrollChanged,
169
+ ];
170
+ // Every other subscription type: watch()'s default `subscriptions` (plan 3.6).
171
+ export const GLOBAL_SUBSCRIPTION_TYPES = Object.values(SubscriptionType).filter((type) => !PER_PANE_SUBSCRIPTION_TYPES.includes(type));
172
+ // herdr-drift exit codes (HERDR-ADR-0009; P5: could not look is 3, never 0).
173
+ export const DriftExitCode = {
174
+ Clean: 0,
175
+ Drift: 1,
176
+ Usage: 2,
177
+ NotCovered: 3,
178
+ };
179
+ // What a schema source found (drift; HERDR-ADR-0009).
180
+ export const SchemaReadKind = {
181
+ Found: 'found',
182
+ NotFound: 'not-found',
183
+ Unreadable: 'unreadable',
184
+ };
185
+ // The drift CLI outcome before its exit code (drift; HERDR-ADR-0009).
186
+ export const DriftOutcomeKind = {
187
+ Usage: 'usage',
188
+ NotCovered: 'not-covered',
189
+ Report: 'report',
190
+ };
191
+ // _tag of each Effect error.
192
+ export const EffectErrorTag = {
193
+ Refused: 'HerdrRefused',
194
+ Unavailable: 'HerdrUnavailable',
195
+ ProtocolMismatch: 'ProtocolMismatch',
196
+ Unsupported: 'HerdrUnsupported',
197
+ };
198
+ // Measured herdr wire facts the full fake reproduces (HERDR-ADR-0016 W1-W6).
199
+ export const WireFact = {
200
+ W1CloseAfterResponse: 'W1',
201
+ W2AckThenStream: 'W2',
202
+ W3EmptyIdOnUnparseable: 'W3',
203
+ W4SchemaOverSocketIsEmpty: 'W4',
204
+ W5NoHistoryReplay: 'W5',
205
+ W6PerPaneNeedsPaneId: 'W6',
206
+ };
207
+ // Lanes of the parallel build (contracts.md). Used by notImplemented() so a stub names its owner.
208
+ export const Lane = {
209
+ P2a: 'P2a',
210
+ P2b: 'P2b',
211
+ P3: 'P3',
212
+ P4a: 'P4a',
213
+ P4b: 'P4b',
214
+ P5a: 'P5a',
215
+ P5c: 'P5c',
216
+ P6a: 'P6a',
217
+ };
218
+ // ---------------------------------------------------------------------------------------------
219
+ // Lane sections: a lane adds constants ONLY between its own `--- lane Px ---` and `--- end Px ---` lines (append-only;
220
+ // contracts.md "shared files"). The blank lines between sections keep two lanes' inserts in separate merge hunks.
221
+ // ---------------------------------------------------------------------------------------------
222
+ // --- lane P2a ---
223
+ // --- end P2a ---
224
+ // --- lane P2b ---
225
+ // Entry names of the scoped clients: the keys of the generated ENTRY_METHODS table (contracts.md, client/types.ts EntryName).
226
+ export const EntryKey = {
227
+ client: 'client',
228
+ admin: 'admin',
229
+ prompt: 'prompt',
230
+ readOnly: 'readOnly',
231
+ readOnlyContent: 'readOnlyContent',
232
+ held: 'held',
233
+ };
234
+ // Separates the segments of a method name: `agent.view.set` is the leaf `set` under `agent` then `view`.
235
+ export const METHOD_SEPARATOR = '.';
236
+ // Keys of the namespace tree that the client composes by hand (events.subscribe is not a tree leaf).
237
+ export const TreeKey = {
238
+ Events: 'events',
239
+ Subscribe: 'subscribe',
240
+ };
241
+ // Results of `typeof` that the namespace tree tells a branch from a leaf by.
242
+ export const TypeofKind = {
243
+ Function: 'function',
244
+ Object: 'object',
245
+ };
246
+ // --- end P2b ---
247
+ // --- lane P3 ---
248
+ // --- end P3 ---
249
+ // --- lane P4a ---
250
+ // --- end P4a ---
251
+ // --- lane P4b ---
252
+ // Messages of the watch layer (plan 3.6, HERDR-ADR-0016 W5/W6). Codes stay in ErrorName; these are the texts only.
253
+ export const WatchText = {
254
+ ReplayOverflow: (max) => `replay buffer overflowed at ${max} frames`,
255
+ OutputMatchUnsupported: 'watchPaneSet does not subscribe to pane.output_matched: its match and source are not options yet (HERDR-ADR-0016 open issue 8)',
256
+ };
257
+ // Messages of the held connection layer (plan 3.6).
258
+ export const HeldText = {
259
+ Ended: (method) => `${method}: the held connection is closed`,
260
+ };
261
+ // Subscription types that keep watchPaneSet's set of panes (W6): a pane is created or closed.
262
+ export const PANE_LIFECYCLE_SUBSCRIPTION_TYPES = [SubscriptionType.PaneCreated, SubscriptionType.PaneClosed];
263
+ // --- end P4b ---
264
+ // --- lane P5a ---
265
+ // Error code the fake returns for params that break the generated shape, or a per-pane spec without pane_id (HERDR-ADR-0016 W6: herdr answers invalid_params).
266
+ export const FakeErrorCode = { InvalidParams: 'invalid_params' };
267
+ // Texts of the fake's invalid_params errors.
268
+ export const FakeCheckText = {
269
+ NotAnObject: (method) => `${method}: params must be an object`,
270
+ MissingField: (method, field) => `${method}: missing required field ${field}`,
271
+ WrongKind: (method, field) => `${method}: field ${field} has the wrong type`,
272
+ NotInEnum: (method, field) => `${method}: field ${field} is not an allowed value`,
273
+ KeyNotAllowed: (method, field) => `${method}: a key of field ${field} is not allowed`,
274
+ NeedsPaneId: (type) => `${type} needs pane_id`,
275
+ };
276
+ // JavaScript typeof results the request checker compares a value against (the number and boolean ones; TypeofTag has the rest).
277
+ export const TypeofValue = { Number: 'number', Boolean: 'boolean' };
278
+ // The result herdr gives api.schema over the socket (HERDR-ADR-0016 W4, measured): an empty object.
279
+ export const EMPTY_SCHEMA_RESULT = {};
280
+ // Field names of a subscription spec (subscriptions, pane_id) that the fake reads.
281
+ export const SpecField = { Subscriptions: 'subscriptions', PaneId: 'pane_id' };
282
+ // Methods the fake answers that the generated schema does not list (api.schema is not in generated Method; W4).
283
+ export const FakeMethod = { ApiSchema: 'api.schema' };
284
+ // How an event kind is named as a subscription type: pane_created is subscription pane.created; a frame already named as a subscription type (pane.output_matched) keeps its name.
285
+ export const NameSeparator = { Event: '_', Subscription: '.' };
286
+ // --- end P5a ---
287
+ // --- lane P5c ---
288
+ // --- end P5c ---
289
+ // --- lane P6a ---
290
+ // Message of a tagged error whose source carries no message (a thrown string, undefined, a plain object).
291
+ export const EffectFallbackMessage = {
292
+ UnknownError: 'unknown herdr error',
293
+ };
294
+ // --- end P6a ---
@@ -0,0 +1,20 @@
1
+ import type { Duration } from './kernel.js';
2
+ import { RetryPhase, TimerHold } from './constants.js';
3
+ export interface BackoffTiming {
4
+ readonly backoffBase: Duration;
5
+ readonly backoffCap: Duration;
6
+ }
7
+ export declare class Backoff {
8
+ private readonly timing;
9
+ private readonly hold;
10
+ private failures;
11
+ private retry;
12
+ private proven;
13
+ constructor(timing: BackoffTiming, hold: TimerHold);
14
+ get phase(): RetryPhase;
15
+ schedule(run: () => void): void;
16
+ survive(): void;
17
+ stop(): void;
18
+ private timer;
19
+ private clear;
20
+ }
@@ -0,0 +1,53 @@
1
+ // Role: the capped exponential backoff of the core link and events.
2
+ // Informs HERDR-ADR-0020 (the herdr-core client); ported from the desktop work in herdr-plugins.
3
+ import { must } from './kernel.js';
4
+ import { parseCount } from './kernel.js';
5
+ import { RetryPhase, TimerHold } from './constants.js';
6
+ import { nextBackoff } from './wire.js';
7
+ const ZERO = must(parseCount(0));
8
+ const ONE = must(parseCount(1));
9
+ const HOLD = {
10
+ [TimerHold.HoldsProcess]: () => undefined,
11
+ [TimerHold.LetsProcessEnd]: (timer) => { timer.unref(); },
12
+ };
13
+ export class Backoff {
14
+ timing;
15
+ hold;
16
+ failures = ZERO;
17
+ retry = null;
18
+ proven = null;
19
+ constructor(timing, hold) {
20
+ this.timing = timing;
21
+ this.hold = hold;
22
+ }
23
+ get phase() {
24
+ return this.retry === null ? RetryPhase.Idle : RetryPhase.Waiting;
25
+ }
26
+ schedule(run) {
27
+ this.stop();
28
+ const delay = nextBackoff(this.failures, this.timing.backoffBase, this.timing.backoffCap);
29
+ this.failures = must(parseCount(this.failures + ONE));
30
+ this.retry = this.timer(() => { this.retry = null; run(); }, delay);
31
+ }
32
+ survive() {
33
+ this.clear(this.proven);
34
+ this.proven = setTimeout(() => { this.proven = null; this.failures = ZERO; }, this.timing.backoffCap);
35
+ this.proven.unref();
36
+ }
37
+ stop() {
38
+ this.clear(this.retry);
39
+ this.clear(this.proven);
40
+ this.retry = null;
41
+ this.proven = null;
42
+ }
43
+ timer(run, delay) {
44
+ const timer = setTimeout(run, delay);
45
+ HOLD[this.hold](timer);
46
+ return timer;
47
+ }
48
+ clear(timer) {
49
+ if (timer !== null) {
50
+ clearTimeout(timer);
51
+ }
52
+ }
53
+ }
@@ -0,0 +1,143 @@
1
+ import type { Count, Duration, NonEmptyText, Text } from './kernel.js';
2
+ export declare const HC_SOCKET_ENV: NonEmptyText;
3
+ export declare const HC_RUNTIME_ENV: NonEmptyText;
4
+ export declare const HC_SESSION_ENV: NonEmptyText;
5
+ export declare const HC_DEFAULT_SESSION: NonEmptyText;
6
+ export declare const HC_SOCKET_FOLDER: NonEmptyText;
7
+ export declare const HC_RUN_ROOT: NonEmptyText;
8
+ export declare const HC_SOCKET_SUFFIX: NonEmptyText;
9
+ export declare const HC_GENERATION: Count;
10
+ export declare const HC_HELLO_METHOD: NonEmptyText;
11
+ export declare const HC_SUBSCRIBE_METHOD: NonEmptyText;
12
+ export declare const HC_LIST_METHOD: NonEmptyText;
13
+ export declare const HC_GET_METHOD: NonEmptyText;
14
+ export declare const HC_READ_METHOD: NonEmptyText;
15
+ export declare const HC_HELLO_TIMEOUT: Duration;
16
+ export declare const HC_BACKOFF_BASE: Duration;
17
+ export declare const HC_BACKOFF_CAP: Duration;
18
+ export declare const HC_BACKOFF_MAX_DOUBLINGS = 20;
19
+ export declare const HC_HEARTBEAT_EVERY: Duration;
20
+ export declare const HC_HEARTBEAT_MISSES: Count;
21
+ export declare const HC_CALL_TIMEOUT: Duration;
22
+ export declare const HC_LINE_CAP: Count;
23
+ export declare const HC_JSONRPC_VERSION = "2.0";
24
+ export declare const HC_LINE_SEPARATOR = "\n";
25
+ export declare const EMPTY_TEXT: Text;
26
+ export declare const UTF8 = "utf8";
27
+ export declare const FIRST_CALL_ID = 1;
28
+ export declare const CoreText: {
29
+ readonly NoConnection: Text;
30
+ readonly Closed: Text;
31
+ readonly Dropped: Text;
32
+ readonly Down: Text;
33
+ readonly Connecting: Text;
34
+ readonly HelloUnreadable: Text;
35
+ readonly OddResult: Text;
36
+ readonly Generation: (generation: Count) => Text;
37
+ readonly Fault: (reason: Text, message: Text) => Text;
38
+ readonly Invariant: (detail: string) => string;
39
+ };
40
+ export declare const JsType: {
41
+ readonly Object: 'object';
42
+ readonly Number: 'number';
43
+ readonly String: 'string';
44
+ };
45
+ export declare const ResultKind: {
46
+ readonly Ok: 'ok';
47
+ readonly Err: 'err';
48
+ };
49
+ export type ResultKind = (typeof ResultKind)[keyof typeof ResultKind];
50
+ export declare const ParseFailureKind: {
51
+ readonly NotAString: 'not-a-string';
52
+ readonly NotANumber: 'not-a-number';
53
+ readonly Empty: 'empty';
54
+ readonly NotAnInteger: 'not-an-integer';
55
+ readonly NotARow: 'not-a-row';
56
+ readonly OutOfRange: 'out-of-range';
57
+ };
58
+ export type ParseFailureKind = (typeof ParseFailureKind)[keyof typeof ParseFailureKind];
59
+ export declare const CoreErrorName: {
60
+ readonly Invariant: 'CoreInvariantError';
61
+ };
62
+ export declare const UnknownWhy: {
63
+ readonly Timeout: 'timeout';
64
+ readonly Unreadable: 'unreadable';
65
+ readonly Unreachable: 'unreachable';
66
+ readonly NotFound: 'not-found';
67
+ readonly Failed: 'failed';
68
+ };
69
+ export type UnknownWhy = (typeof UnknownWhy)[keyof typeof UnknownWhy];
70
+ export declare const OutcomeKind: {
71
+ readonly Answer: 'answer';
72
+ readonly Unknown: 'unknown';
73
+ };
74
+ export type OutcomeKind = (typeof OutcomeKind)[keyof typeof OutcomeKind];
75
+ export declare const HcKind: {
76
+ readonly Reply: 'reply';
77
+ readonly Odd: 'odd';
78
+ readonly Fault: 'fault';
79
+ readonly Event: 'event';
80
+ readonly Heartbeat: 'heartbeat';
81
+ readonly Missed: 'missed';
82
+ readonly Snapshot: 'snapshot';
83
+ };
84
+ export type HcKind = (typeof HcKind)[keyof typeof HcKind];
85
+ export declare const HcNotificationMethod: {
86
+ readonly Event: 'event';
87
+ readonly Heartbeat: 'heartbeat';
88
+ readonly Missed: 'missed';
89
+ };
90
+ export type HcNotificationMethod = (typeof HcNotificationMethod)[keyof typeof HcNotificationMethod];
91
+ export declare const HcField: {
92
+ readonly JsonRpc: 'jsonrpc';
93
+ readonly Id: 'id';
94
+ readonly Method: 'method';
95
+ readonly Params: 'params';
96
+ readonly Result: 'result';
97
+ readonly Error: 'error';
98
+ readonly Seq: 'seq';
99
+ readonly Terminals: 'terminals';
100
+ readonly Terminal: 'terminal';
101
+ readonly Generation: 'generation';
102
+ readonly Version: 'version';
103
+ readonly Methods: 'methods';
104
+ readonly Code: 'code';
105
+ readonly Message: 'message';
106
+ readonly Data: 'data';
107
+ readonly Kind: 'kind';
108
+ readonly Type: 'type';
109
+ };
110
+ export declare const LinkState: {
111
+ readonly Idle: 'idle';
112
+ readonly Connecting: 'connecting';
113
+ readonly Ready: 'ready';
114
+ readonly Backoff: 'backoff';
115
+ readonly Closed: 'closed';
116
+ };
117
+ export type LinkState = (typeof LinkState)[keyof typeof LinkState];
118
+ export declare const EventsPhase: {
119
+ readonly Waiting: 'waiting';
120
+ readonly Subscribed: 'subscribed';
121
+ };
122
+ export type EventsPhase = (typeof EventsPhase)[keyof typeof EventsPhase];
123
+ export declare const Life: {
124
+ readonly Open: 'open';
125
+ readonly Closed: 'closed';
126
+ };
127
+ export type Life = (typeof Life)[keyof typeof Life];
128
+ export declare const RetryPhase: {
129
+ readonly Idle: 'idle';
130
+ readonly Waiting: 'waiting';
131
+ };
132
+ export type RetryPhase = (typeof RetryPhase)[keyof typeof RetryPhase];
133
+ export declare const TimerHold: {
134
+ readonly HoldsProcess: 'holds-process';
135
+ readonly LetsProcessEnd: 'lets-process-end';
136
+ };
137
+ export type TimerHold = (typeof TimerHold)[keyof typeof TimerHold];
138
+ export declare const SocketEvent: {
139
+ readonly Data: 'data';
140
+ readonly Error: 'error';
141
+ readonly Close: 'close';
142
+ readonly Connect: 'connect';
143
+ };
@@ -0,0 +1,98 @@
1
+ export const HC_SOCKET_ENV = 'HC_SOCKET';
2
+ export const HC_RUNTIME_ENV = 'XDG_RUNTIME_DIR';
3
+ export const HC_SESSION_ENV = 'HC_SESSION';
4
+ export const HC_DEFAULT_SESSION = 'default';
5
+ export const HC_SOCKET_FOLDER = 'herdr-core';
6
+ export const HC_RUN_ROOT = '/run/user';
7
+ export const HC_SOCKET_SUFFIX = '.sock';
8
+ export const HC_GENERATION = 1;
9
+ export const HC_HELLO_METHOD = 'hello';
10
+ export const HC_SUBSCRIBE_METHOD = 'events.subscribe';
11
+ export const HC_LIST_METHOD = 'terminal.list';
12
+ export const HC_GET_METHOD = 'terminal.get';
13
+ export const HC_READ_METHOD = 'terminal.read';
14
+ export const HC_HELLO_TIMEOUT = 5000;
15
+ export const HC_BACKOFF_BASE = 500;
16
+ export const HC_BACKOFF_CAP = 15_000;
17
+ export const HC_BACKOFF_MAX_DOUBLINGS = 20;
18
+ export const HC_HEARTBEAT_EVERY = 15_000;
19
+ export const HC_HEARTBEAT_MISSES = 2;
20
+ export const HC_CALL_TIMEOUT = 10_000;
21
+ export const HC_LINE_CAP = 33_554_432;
22
+ export const HC_JSONRPC_VERSION = '2.0';
23
+ export const HC_LINE_SEPARATOR = '\n';
24
+ export const EMPTY_TEXT = '';
25
+ export const UTF8 = 'utf8';
26
+ export const FIRST_CALL_ID = 1;
27
+ // The messages the core client puts in an Unknown or an error.
28
+ export const CoreText = {
29
+ NoConnection: 'no connection',
30
+ Closed: 'link closed',
31
+ Dropped: 'connection dropped',
32
+ Down: 'the core is down; reconnecting',
33
+ Connecting: 'connecting',
34
+ HelloUnreadable: 'hello reply',
35
+ OddResult: 'a result that is not an object',
36
+ Generation: (generation) => `generation ${generation}`,
37
+ Fault: (reason, message) => `${reason}: ${message}`,
38
+ Invariant: (detail) => `a load-time constant was refused: ${detail}`,
39
+ };
40
+ export const JsType = { Object: 'object', Number: 'number', String: 'string' };
41
+ export const ResultKind = { Ok: 'ok', Err: 'err' };
42
+ export const ParseFailureKind = {
43
+ NotAString: 'not-a-string',
44
+ NotANumber: 'not-a-number',
45
+ Empty: 'empty',
46
+ NotAnInteger: 'not-an-integer',
47
+ NotARow: 'not-a-row',
48
+ OutOfRange: 'out-of-range',
49
+ };
50
+ export const CoreErrorName = { Invariant: 'CoreInvariantError' };
51
+ export const UnknownWhy = {
52
+ Timeout: 'timeout',
53
+ Unreadable: 'unreadable',
54
+ Unreachable: 'unreachable',
55
+ NotFound: 'not-found',
56
+ Failed: 'failed',
57
+ };
58
+ // What a call settled as: an answer from the core, or Unknown.
59
+ export const OutcomeKind = { Answer: 'answer', Unknown: 'unknown' };
60
+ // The kinds of a parsed message and of a feed item.
61
+ export const HcKind = {
62
+ Reply: 'reply',
63
+ Odd: 'odd',
64
+ Fault: 'fault',
65
+ Event: 'event',
66
+ Heartbeat: 'heartbeat',
67
+ Missed: 'missed',
68
+ Snapshot: 'snapshot',
69
+ };
70
+ // The notification methods the core pushes on a subscription.
71
+ export const HcNotificationMethod = { Event: 'event', Heartbeat: 'heartbeat', Missed: 'missed' };
72
+ // The JSON fields of the core's wire.
73
+ export const HcField = {
74
+ JsonRpc: 'jsonrpc',
75
+ Id: 'id',
76
+ Method: 'method',
77
+ Params: 'params',
78
+ Result: 'result',
79
+ Error: 'error',
80
+ Seq: 'seq',
81
+ Terminals: 'terminals',
82
+ Terminal: 'terminal',
83
+ Generation: 'generation',
84
+ Version: 'version',
85
+ Methods: 'methods',
86
+ Code: 'code',
87
+ Message: 'message',
88
+ Data: 'data',
89
+ Kind: 'kind',
90
+ Type: 'type',
91
+ };
92
+ export const LinkState = { Idle: 'idle', Connecting: 'connecting', Ready: 'ready', Backoff: 'backoff', Closed: 'closed' };
93
+ export const EventsPhase = { Waiting: 'waiting', Subscribed: 'subscribed' };
94
+ export const Life = { Open: 'open', Closed: 'closed' };
95
+ export const RetryPhase = { Idle: 'idle', Waiting: 'waiting' };
96
+ // Whether a retry timer keeps the process alive.
97
+ export const TimerHold = { HoldsProcess: 'holds-process', LetsProcessEnd: 'lets-process-end' };
98
+ export const SocketEvent = { Data: 'data', Error: 'error', Close: 'close', Connect: 'connect' };
@@ -0,0 +1,35 @@
1
+ import { OutcomeKind } from './constants.js';
2
+ import type { ParseFailureKind, UnknownWhy } from './constants.js';
3
+ import type { Duration } from './kernel.js';
4
+ export type ParseFailure = {
5
+ readonly kind: ParseFailureKind;
6
+ };
7
+ export declare class CoreInvariantError extends Error {
8
+ readonly name: string;
9
+ constructor(detail: string);
10
+ }
11
+ export type Unknowable = {
12
+ readonly why: typeof UnknownWhy.Timeout;
13
+ readonly after: Duration;
14
+ } | {
15
+ readonly why: typeof UnknownWhy.Unreadable;
16
+ readonly detail: string;
17
+ } | {
18
+ readonly why: typeof UnknownWhy.Unreachable;
19
+ readonly detail: string;
20
+ } | {
21
+ readonly why: typeof UnknownWhy.NotFound;
22
+ readonly what: string;
23
+ } | {
24
+ readonly why: typeof UnknownWhy.Failed;
25
+ readonly code: number;
26
+ readonly detail: string;
27
+ };
28
+ export type Unknown = {
29
+ readonly kind: typeof OutcomeKind.Unknown;
30
+ readonly why: Unknowable;
31
+ };
32
+ export declare function unknown(why: Unknowable): Unknown;
33
+ export declare function isUnknown<T extends {
34
+ readonly kind: string;
35
+ }>(value: T | Unknown): value is Unknown;
@@ -0,0 +1,16 @@
1
+ // Role: every failure of the herdr-core client ; its kinds live in constants.ts: Unknown (a call whose outcome cannot be known), ParseFailure (why a parser refused) and CoreInvariantError (a load-time constant refused, a bug).
2
+ // Informs HERDR-ADR-0020; merged by HERDR-ADR-0021 from parse-failure.ts, unknown.ts.
3
+ import { CoreErrorName, CoreText, OutcomeKind } from './constants.js';
4
+ // A load-time constant failed its own parser: a bug in the SDK, never a runtime condition.
5
+ export class CoreInvariantError extends Error {
6
+ name = CoreErrorName.Invariant;
7
+ constructor(detail) {
8
+ super(CoreText.Invariant(detail));
9
+ }
10
+ }
11
+ export function unknown(why) {
12
+ return { kind: OutcomeKind.Unknown, why };
13
+ }
14
+ export function isUnknown(value) {
15
+ return value.kind === OutcomeKind.Unknown;
16
+ }