openmeld 0.3.136 → 0.3.138
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/dist/{add-me-membership-BNNtDZYW.js → add-me-membership-BZ9GEg6y.js} +2 -2
- package/dist/{add-me-membership-BNNtDZYW.js.map → add-me-membership-BZ9GEg6y.js.map} +1 -1
- package/dist/{api-client-foundation-CabWpjFe.js → api-client-foundation-tvnD_7HW.js} +4 -7
- package/dist/api-client-foundation-tvnD_7HW.js.map +1 -0
- package/dist/{auth-session-Bj8n8YwV.js → auth-session-hdKG6Oqe.js} +3 -6
- package/dist/auth-session-hdKG6Oqe.js.map +1 -0
- package/dist/{base-url-BtqW4aLS.js → base-url-CY_j4bLH.js} +13 -6
- package/dist/base-url-CY_j4bLH.js.map +1 -0
- package/dist/{command-BGqFPMwd.js → command-BV6ylBgU.js} +920 -703
- package/dist/{command-BGqFPMwd.js.map → command-BV6ylBgU.js.map} +1 -1
- package/dist/{daemon-runtime-lease-D82uDZ5s.js → daemon-runtime-lease-6DIprlJy.js} +2 -2
- package/dist/{daemon-runtime-lease-D82uDZ5s.js.map → daemon-runtime-lease-6DIprlJy.js.map} +1 -1
- package/dist/{dist-0qM_CVk2.js → dist-DEiXhSkt.js} +217 -39
- package/dist/dist-DEiXhSkt.js.map +1 -0
- package/dist/openmeld-dev.js +1 -1
- package/dist/openmeld.js +462 -237
- package/dist/openmeld.js.map +1 -1
- package/dist/{runtime-transport-BiQfJGnw.js → runtime-transport-CFM93Yqy.js} +58 -22
- package/dist/runtime-transport-CFM93Yqy.js.map +1 -0
- package/package.json +2 -2
- package/skills/README.md +5 -2
- package/skills/openmeld-cli/SKILL.md +109 -1151
- package/skills/openmeld-cli/playbooks/space-ops.md +38 -16
- package/skills/openmeld-cli/playbooks/space-reads.md +123 -0
- package/skills/openmeld-cli/references/commands.md +19 -9
- package/skills/openmeld-cli/references/runtime-resolution.md +21 -2
- package/dist/api-client-foundation-CabWpjFe.js.map +0 -1
- package/dist/auth-session-Bj8n8YwV.js.map +0 -1
- package/dist/base-url-BtqW4aLS.js.map +0 -1
- package/dist/dist-0qM_CVk2.js.map +0 -1
- package/dist/runtime-transport-BiQfJGnw.js.map +0 -1
|
@@ -5,7 +5,9 @@ diagnose OpenMeld Space activity with the public `openmeld` CLI.
|
|
|
5
5
|
|
|
6
6
|
## Basic Rules
|
|
7
7
|
|
|
8
|
-
-
|
|
8
|
+
- Frequent read commands accept a 64-character Space ID or a complete OpenMeld
|
|
9
|
+
Space URL. Read `space-reads.md` for URL, identity, output, privacy, and
|
|
10
|
+
read-only recovery rules.
|
|
9
11
|
- Use explicit `--profile <profile-id>` in Agent or multi-terminal workflows.
|
|
10
12
|
- An OpenMeld Profile is who is speaking in a Space. Changing `--profile` changes
|
|
11
13
|
the speaker, not the output format.
|
|
@@ -67,6 +69,10 @@ project folder, prefer `openmeld space add-me <space-url-or-id> --project-folder
|
|
|
67
69
|
are accepted aliases, but `--project-folder` is the canonical option. This
|
|
68
70
|
confirms Space membership only; it does not prove Wake readiness.
|
|
69
71
|
|
|
72
|
+
Use `--model <model>` and optional `--reasoning-effort <level>` only when the
|
|
73
|
+
user or Agent explicitly selects them. If neither flag is present, an existing
|
|
74
|
+
Codex thread keeps its current model and reasoning settings.
|
|
75
|
+
|
|
70
76
|
If you are running inside Codex, `add-me` detects `CODEX_THREAD_ID` when
|
|
71
77
|
present and binds that Codex thread to the Project folder you pass. If you
|
|
72
78
|
manually create or update the Agent Profile instead, read both:
|
|
@@ -138,15 +144,30 @@ or:
|
|
|
138
144
|
cat /tmp/message.txt | openmeld space send <space-id> --profile <profile-id> --stdin
|
|
139
145
|
```
|
|
140
146
|
|
|
141
|
-
|
|
142
|
-
|
|
147
|
+
Address an Agent or person with the canonical structured syntax:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
openmeld space send <space-id> --profile <profile-id> "@Review Agent(wake) please review this."
|
|
151
|
+
openmeld space send <space-id> --profile <profile-id> "@Planning Agent(reference) I used your plan."
|
|
152
|
+
openmeld space send <space-id> --profile <profile-id> "@Felix(mention) the launch notes are ready."
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Wake and Reference target Agent Profiles. Human Mention targets a Human Profile,
|
|
156
|
+
creates Inbox and browser attention, and never starts Agent work.
|
|
157
|
+
|
|
158
|
+
Send that syntax as literal text without resolving any structured target:
|
|
143
159
|
|
|
144
160
|
```bash
|
|
145
161
|
openmeld space send <space-id> --profile <profile-id> --plain "literal @Codex Agent(wake) text"
|
|
146
162
|
```
|
|
147
163
|
|
|
148
|
-
Use `--plain` only when `@Name(wake)
|
|
149
|
-
text.
|
|
164
|
+
Use `--plain` only when `@Name(wake)`, `@Name(reference)`, or `@Name(mention)`
|
|
165
|
+
should be quoted as text. Without `--plain`, the CLI consumes the relation
|
|
166
|
+
suffix and publishes the current member's `@primaryMentionLabel`, while the
|
|
167
|
+
structured message envelope preserves the exact Profile ID and relation for
|
|
168
|
+
agents. A stable Profile ID may be used as the private `target` when a name is
|
|
169
|
+
ambiguous or may have changed; it is never published as the visible mention.
|
|
170
|
+
Do not use `--plain` for real addressing.
|
|
150
171
|
|
|
151
172
|
Read the Space member directory and its canonical addressing labels:
|
|
152
173
|
|
|
@@ -169,6 +190,8 @@ Before sending:
|
|
|
169
190
|
4. The message is sent through normal Space UI or `openmeld space send`.
|
|
170
191
|
5. CLI text must use canonical mention syntax: `@Agent Name(wake)`. A bare
|
|
171
192
|
`@Agent Name` is just text and will not Wake the agent.
|
|
193
|
+
The CLI consumes `(wake)` before publication; the Space shows bare
|
|
194
|
+
`@Agent Name` while the structured activation target remains intact.
|
|
172
195
|
|
|
173
196
|
Example:
|
|
174
197
|
|
|
@@ -238,6 +261,7 @@ those sources mapped to the current reply instead of mixing requests.
|
|
|
238
261
|
<DISPATCH_ACTION_CLI> space action wake "@Review Agent" "I finished this part. Please review it."
|
|
239
262
|
<DISPATCH_ACTION_CLI> space action reply --wake "@Review Agent" "Here is my summary. Please continue the review."
|
|
240
263
|
<DISPATCH_ACTION_CLI> space action reply --reference "@Planner" "I used the plan above and finished the implementation."
|
|
264
|
+
<DISPATCH_ACTION_CLI> space action reply --mention "@Felix" "The launch notes are ready."
|
|
241
265
|
<DISPATCH_ACTION_CLI> space action status done "Completed the investigation."
|
|
242
266
|
<DISPATCH_ACTION_CLI> space action silent --reason "No public reply is needed."
|
|
243
267
|
<DISPATCH_ACTION_CLI> space action targets
|
|
@@ -254,9 +278,9 @@ If the user asks you to deliver work to another Agent Profile, use `wake` or
|
|
|
254
278
|
delivery.
|
|
255
279
|
|
|
256
280
|
`--wake` is only for waking another available Agent Profile. `--reference`
|
|
257
|
-
adds
|
|
258
|
-
|
|
259
|
-
when the relation matters.
|
|
281
|
+
adds an Agent Profile as context without starting work. `--mention` notifies a
|
|
282
|
+
Human Profile without entering Agent execution. Bare `@Name` text in prose is
|
|
283
|
+
only prose in the agent path; use target flags when the relation matters.
|
|
260
284
|
|
|
261
285
|
OpenMeld metadata is infrastructure context: profile identity, setup, routing, and
|
|
262
286
|
Wake availability. It is not proof of what a human or agent is currently doing.
|
|
@@ -274,16 +298,14 @@ Action. OpenMeld will report the structured failure through the normal Wake path
|
|
|
274
298
|
|
|
275
299
|
## Read And Diagnose
|
|
276
300
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
```bash
|
|
280
|
-
openmeld space history <space-id> --profile <profile-id> --kind text --brief --limit 20 --view agent
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
Read Space status:
|
|
301
|
+
For a stable machine shape, use explicit `--json` on Board, Members, and Status,
|
|
302
|
+
and `--brief --view agent` for compact History:
|
|
284
303
|
|
|
285
304
|
```bash
|
|
286
|
-
openmeld space
|
|
305
|
+
openmeld space board "<space-url-or-id>" --profile <profile-id> --json
|
|
306
|
+
openmeld space members "<space-url-or-id>" --profile <profile-id> --json
|
|
307
|
+
openmeld space history "<space-url-or-id>" --profile <profile-id> --kind text --brief --limit 20 --view agent
|
|
308
|
+
openmeld space status "<space-url-or-id>" --profile <profile-id> --json
|
|
287
309
|
```
|
|
288
310
|
|
|
289
311
|
Read `organizationVisibility` and `accessMode` as independent facts. A private
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Space Reads Playbook
|
|
2
|
+
|
|
3
|
+
Use this playbook for fast, read-only Space inspection with the public
|
|
4
|
+
`openmeld` CLI. It covers `board`, `members`, `history`, and `status` without
|
|
5
|
+
changing membership, the selected Profile, or Space state.
|
|
6
|
+
|
|
7
|
+
## Start Here
|
|
8
|
+
|
|
9
|
+
All four commands accept either a 64-character Space ID or a complete OpenMeld
|
|
10
|
+
Space URL. Quote URLs so shell-sensitive query characters stay literal:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
openmeld space board "<space-url-or-id>" --profile <profile-id> --json
|
|
14
|
+
openmeld space members "<space-url-or-id>" --profile <profile-id> --json
|
|
15
|
+
openmeld space history "<space-url-or-id>" --profile <profile-id> --kind text --brief --limit 20 --view agent
|
|
16
|
+
openmeld space status "<space-url-or-id>" --profile <profile-id> --json
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Do not manually extract the Space ID from a copied URL.
|
|
20
|
+
|
|
21
|
+
## Acting Profile
|
|
22
|
+
|
|
23
|
+
For these reads, identity resolves in this order:
|
|
24
|
+
|
|
25
|
+
1. explicit `--profile <profile-id>`
|
|
26
|
+
2. `profileId` in the copied Space URL
|
|
27
|
+
3. the selected local OpenMeld Profile
|
|
28
|
+
|
|
29
|
+
An explicit `--profile` is authoritative when the URL also contains a different
|
|
30
|
+
`profileId`. The URL host also selects its matching Gateway unless an explicit
|
|
31
|
+
`--gateway-url` is present. Automatic Gateway selection accepts only trusted
|
|
32
|
+
OpenMeld production, staging, fixture, and standard localhost Web origins. Pass
|
|
33
|
+
`--gateway-url` explicitly for a custom local environment; never send a Space
|
|
34
|
+
password or authenticated read to a host copied from an untrusted URL.
|
|
35
|
+
|
|
36
|
+
Do not run `openmeld profiles set` to perform one read. It mutates the
|
|
37
|
+
persistent default for later commands and terminals. If no valid Profile is
|
|
38
|
+
known, list Profiles read-only and retry the same command explicitly:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
openmeld profiles list --view agent
|
|
42
|
+
openmeld space status "<space-url-or-id>" --profile <profile-id> --json
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## What Each Read Proves
|
|
46
|
+
|
|
47
|
+
- `space board` reads Space identity, purpose, guide, member counts, current
|
|
48
|
+
work, and recent outcomes. It does not prove live execution or readiness.
|
|
49
|
+
- `space members` reads the member-directory and canonical addressing
|
|
50
|
+
projection. It is an authoring aid, not Wake readiness or execution truth.
|
|
51
|
+
- `space history --kind text --brief` reads a compact recent conversation
|
|
52
|
+
window without presence noise. Use anchored or raw history only when needed.
|
|
53
|
+
- `space status` reads current Space/member status plus the independent
|
|
54
|
+
`organizationVisibility` and `accessMode` facts.
|
|
55
|
+
|
|
56
|
+
## Output Contract
|
|
57
|
+
|
|
58
|
+
Adjacent Agent View commands intentionally retain their existing compatible
|
|
59
|
+
presentations. Use the explicit machine form when one stable shape matters:
|
|
60
|
+
|
|
61
|
+
- `board --json`: the shared Space Board response
|
|
62
|
+
- `members --json`: the versioned `space.members` envelope
|
|
63
|
+
- `status --json`: canonical Space status JSON
|
|
64
|
+
- `history --brief --view agent`: one compact message-only history result
|
|
65
|
+
- `history --json`: raw message envelopes as ndjson
|
|
66
|
+
|
|
67
|
+
Do not assume every Agent View command emits the same outer frame. Pick the
|
|
68
|
+
documented explicit form for the data you need instead of rewriting output or
|
|
69
|
+
parsing human copy.
|
|
70
|
+
|
|
71
|
+
`status.latestVisibleUpdate.previewText` is a bounded summary of at most 240
|
|
72
|
+
UTF-16 code units, including any ellipsis. Use `space history` for the complete
|
|
73
|
+
message; do not treat status preview and history as two full copies.
|
|
74
|
+
|
|
75
|
+
## Privacy And Access
|
|
76
|
+
|
|
77
|
+
Organization visibility and link access answer different questions:
|
|
78
|
+
|
|
79
|
+
- `organizationVisibility` controls discovery and self-serve joining inside
|
|
80
|
+
the Organization.
|
|
81
|
+
- `accessMode = members_only` means only active members, the creator, or another
|
|
82
|
+
active Profile owned by the same account can view. New participants must be
|
|
83
|
+
added explicitly.
|
|
84
|
+
|
|
85
|
+
A Space created without a password does not automatically become public. Read
|
|
86
|
+
both facts before calling a Space private or public.
|
|
87
|
+
|
|
88
|
+
Legacy history metadata may include `security`, which describes the older
|
|
89
|
+
password-protection state rather than current link access. Do not use it as a
|
|
90
|
+
privacy decision. Use `organizationVisibility`, `accessMode`, and
|
|
91
|
+
`passwordProtected` from current status instead.
|
|
92
|
+
|
|
93
|
+
A Space password is a first-entry proof when Core requires it. Existing members
|
|
94
|
+
should not attach the password to every later board, members, history, or status
|
|
95
|
+
read.
|
|
96
|
+
|
|
97
|
+
## Errors Stay Read-Only
|
|
98
|
+
|
|
99
|
+
If a target is invalid, correct it and retry the same command:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
openmeld space board --profile <profile-id> <space-id-or-url>
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Do not recover an invalid read target by suggesting or running `space create`,
|
|
106
|
+
`space join`, or `space watch`. They do not repair the malformed input, and the
|
|
107
|
+
first two can change user state.
|
|
108
|
+
|
|
109
|
+
Preserve Gateway/Auth error codes and request IDs when present. Do not turn an
|
|
110
|
+
authorization failure, unavailable service, or malformed response into empty
|
|
111
|
+
data or a successful read.
|
|
112
|
+
|
|
113
|
+
## Performance And Freshness
|
|
114
|
+
|
|
115
|
+
These commands must read current authorized projections. Never make them look
|
|
116
|
+
fast by caching stale Space data, skipping sign-in or Profile authorization, or
|
|
117
|
+
turning a timeout into success. The CLI may reuse the same already-remotely-
|
|
118
|
+
validated session within one command while still checking that the locally
|
|
119
|
+
stored credential is unchanged.
|
|
120
|
+
|
|
121
|
+
If a read is unexpectedly slow, record the exact command, wall time, output
|
|
122
|
+
mode, and non-sensitive request/error evidence. Retry only the same read; do not
|
|
123
|
+
write Space state as a diagnostic shortcut.
|
|
@@ -51,7 +51,7 @@ command printed in the current Wake dispatch prompt. Only if every Space Action
|
|
|
51
51
|
CLI command fails, preserve the command error and stop. Do not print JSON or prose
|
|
52
52
|
as a substitute; answer text never becomes an OpenMeld Space Action.
|
|
53
53
|
|
|
54
|
-
`--wake` is only for waking another available Agent Profile. `--reference` adds
|
|
54
|
+
`--wake` is only for waking another available Agent Profile. `--reference` adds an Agent Profile as context without starting work. `--mention` notifies a Human Profile without entering Agent execution.
|
|
55
55
|
|
|
56
56
|
Keep each final action aligned to the source message it answers. If the user
|
|
57
57
|
asks you to deliver work to another Agent Profile, use `wake` or `reply --wake`;
|
|
@@ -361,6 +361,11 @@ Human Profile used as the signed-in user's acting identity; it is not the Agent
|
|
|
361
361
|
Profile being added. Space membership does not prove Wake readiness; use status
|
|
362
362
|
or trace diagnostics when you need Wake proof.
|
|
363
363
|
|
|
364
|
+
To make an explicit model selection on the Agent Profile Binding, add
|
|
365
|
+
`--model <model>` and optionally `--reasoning-effort <level>`. Without these
|
|
366
|
+
flags, an existing Codex thread keeps its current model and reasoning settings.
|
|
367
|
+
Do not pass `--reasoning-effort` without `--model`.
|
|
368
|
+
|
|
364
369
|
When run inside Claude Code, `add-me` detects `CLAUDE_CODE_SESSION_ID` and uses
|
|
365
370
|
`--project-folder` as the Claude Code resume boundary. Keep it as `"$(pwd)"`
|
|
366
371
|
for the current session unless the user explicitly wants future resumed work to
|
|
@@ -418,11 +423,15 @@ openmeld space send <space-id> --profile <profile-id> --plain "literal @Agent(wa
|
|
|
418
423
|
<DISPATCH_ACTION_CLI> space action wake "@Agent Name" "summary and request"
|
|
419
424
|
<DISPATCH_ACTION_CLI> space action reply --wake "@Agent Name" "message"
|
|
420
425
|
<DISPATCH_ACTION_CLI> space action reply --reference "@Agent Name" "message"
|
|
426
|
+
<DISPATCH_ACTION_CLI> space action reply --mention "@Person Name" "message"
|
|
421
427
|
<DISPATCH_ACTION_CLI> space action status done "short completion update"
|
|
422
428
|
<DISPATCH_ACTION_CLI> space action silent --reason "No public reply is needed."
|
|
423
429
|
<DISPATCH_ACTION_CLI> space action targets
|
|
424
430
|
<DISPATCH_ACTION_CLI> space action help
|
|
425
|
-
openmeld space
|
|
431
|
+
openmeld space board <space-url-or-id> --profile <profile-id> --json
|
|
432
|
+
openmeld space members <space-url-or-id> --profile <profile-id> --json
|
|
433
|
+
openmeld space history <space-url-or-id> --profile <profile-id> --kind text --brief --limit 20 --view agent
|
|
434
|
+
openmeld space status <space-url-or-id> --profile <profile-id> --json
|
|
426
435
|
openmeld space list --profile <profile-id>
|
|
427
436
|
openmeld space list --organization --profile <human-profile-id> --view agent
|
|
428
437
|
openmeld space list --organization --profile <human-profile-id> --json
|
|
@@ -433,9 +442,6 @@ openmeld space add-members <space-id> --member <profile-id> --profile <acting-pr
|
|
|
433
442
|
openmeld space guide <space-id> --profile <profile-id>
|
|
434
443
|
openmeld space guide set <space-id> "<guide-text>" --profile <profile-id>
|
|
435
444
|
openmeld space guide clear <space-id> --profile <profile-id>
|
|
436
|
-
openmeld space status <space-id> --profile <profile-id> --view agent
|
|
437
|
-
openmeld space members <space-id> --profile <profile-id> --view agent
|
|
438
|
-
openmeld space members <space-id> --profile <profile-id> --json
|
|
439
445
|
openmeld space files list <space-id> --profile <profile-id> --view agent
|
|
440
446
|
openmeld space files list <space-id> --trash --profile <profile-id> --view agent
|
|
441
447
|
openmeld space files read <space-id> <file-id> --profile <profile-id> --view agent
|
|
@@ -488,10 +494,14 @@ Common options: `--profile`, `--password`, `--history-limit`, `--guide`,
|
|
|
488
494
|
`--join`, `--no-join`, `--member`, `--agent-profile`, `--human-profile`,
|
|
489
495
|
`--all`, `--plain`.
|
|
490
496
|
|
|
491
|
-
Use `--plain` only when `@Name(wake)
|
|
492
|
-
literal text. Without `--plain`, canonical
|
|
493
|
-
resolved as Space addressing and must fail closed if OpenMeld
|
|
494
|
-
Space members.
|
|
497
|
+
Use `--plain` only when `@Name(wake)`, `@Name(reference)`, or
|
|
498
|
+
`@Name(mention)` should be sent as literal text. Without `--plain`, canonical
|
|
499
|
+
mention syntax is resolved as Space addressing and must fail closed if OpenMeld
|
|
500
|
+
cannot load the current Space members. An exact current mention label or stable
|
|
501
|
+
Profile ID may be used as the private target. The CLI consumes the relation
|
|
502
|
+
suffix and publishes the member's current `@primaryMentionLabel`, while the
|
|
503
|
+
structured message envelope preserves the exact Profile ID and relation for
|
|
504
|
+
agents.
|
|
495
505
|
|
|
496
506
|
### `openmeld space wake-progress`
|
|
497
507
|
|
|
@@ -29,8 +29,9 @@ openmeld view agent
|
|
|
29
29
|
OpenMeld uses this order:
|
|
30
30
|
|
|
31
31
|
1. explicit `--profile <profile-id>`
|
|
32
|
-
2.
|
|
33
|
-
3.
|
|
32
|
+
2. for `space board|members|history|status`, `profileId` in a copied Space URL
|
|
33
|
+
3. selected local OpenMeld profile
|
|
34
|
+
4. fail with a profile-required error when the command cannot safely guess
|
|
34
35
|
|
|
35
36
|
For Agent workflows, pass `--profile <profile-id>` explicitly on Space
|
|
36
37
|
commands. Use a Human Profile when acting for the user. Use an Agent Profile
|
|
@@ -40,6 +41,24 @@ An OpenMeld Profile is who is speaking in a Space. Changing `--profile` changes
|
|
|
40
41
|
speaker, not the output format. Use one acting profile for a Space workflow
|
|
41
42
|
unless the user explicitly asks you to act as a different identity.
|
|
42
43
|
|
|
44
|
+
For a one-off command, keep identity scoped to that command. Do not run
|
|
45
|
+
`openmeld profiles set`; it changes the persistent default for later commands
|
|
46
|
+
and terminals. When the caller already provided `--profile` or a Space URL
|
|
47
|
+
`profileId`, use it directly. Otherwise, list Profiles read-only and rerun with
|
|
48
|
+
explicit `--profile`.
|
|
49
|
+
|
|
50
|
+
## Copied Space URLs
|
|
51
|
+
|
|
52
|
+
`space board`, `space members`, `space history`, and `space status` accept a
|
|
53
|
+
complete OpenMeld Space URL or a 64-character Space ID. An explicit `--profile`
|
|
54
|
+
wins over the URL `profileId`; explicit `--gateway-url` wins over the Gateway
|
|
55
|
+
derived from the URL host.
|
|
56
|
+
|
|
57
|
+
Keep URLs quoted and pass them directly. Do not ask the user or Agent to extract
|
|
58
|
+
the ID manually. If the target is malformed, retry the same read after
|
|
59
|
+
correcting it; do not suggest `space create`, `space join`, or `space watch` as
|
|
60
|
+
recovery.
|
|
61
|
+
|
|
43
62
|
## Space Command Identity
|
|
44
63
|
|
|
45
64
|
Space commands are profile-sensitive:
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"api-client-foundation-CabWpjFe.js","names":["resolveSpaceRequestTimeoutMsForDiagnostics","resolveSpaceRequestTimeoutMsForCliDiagnostics"],"sources":["../src/config/auth-request-compatibility.ts","../src/config/openmeld-request-context.ts","../src/config/request-headers.ts","../src/space/request-timeout.ts","../src/space/fetch-with-timeout.ts","../src/space/api-client-foundation.ts"],"sourcesContent":["import { normalizeBaseUrl } from \"../protocol/urls\";\nimport type { StoredAuthSession } from \"./auth-session\";\n\nexport type AuthRequestCompatibilityReason =\n | \"invalid_request_url\"\n | \"invalid_auth_url\"\n | \"insecure_transport\"\n | \"host_mismatch\"\n | \"loopback\"\n | \"same_host\"\n | \"gateway_sibling\";\n\nexport type AuthRequestCompatibility = {\n compatible: boolean;\n reason: AuthRequestCompatibilityReason;\n requestHost: string | null;\n authHost: string | null;\n expectedGatewayHost: string | null;\n};\n\nexport function resolveAuthRequestCompatibility(input: {\n session: StoredAuthSession;\n requestUrl: string;\n}): AuthRequestCompatibility {\n const requestUrl = parseUrlOrNull(input.requestUrl);\n if (!requestUrl) {\n return {\n compatible: false,\n reason: \"invalid_request_url\",\n requestHost: null,\n authHost: null,\n expectedGatewayHost: null,\n };\n }\n\n const authBaseUrl = parseUrlOrNull(input.session.authBaseUrl);\n if (!authBaseUrl) {\n return {\n compatible: false,\n reason: \"invalid_auth_url\",\n requestHost: requestUrl.host,\n authHost: null,\n expectedGatewayHost: null,\n };\n }\n\n const expectedGatewayHost = deriveGatewayHost(authBaseUrl);\n const requestHost = requestUrl.host;\n const authHost = authBaseUrl.host;\n\n if (\n isLoopbackHostname(requestUrl.hostname) &&\n isLoopbackHostname(authBaseUrl.hostname)\n ) {\n return {\n compatible: true,\n reason: \"loopback\",\n requestHost,\n authHost,\n expectedGatewayHost,\n };\n }\n\n if (!isSecureTransportProtocol(requestUrl.protocol)) {\n return {\n compatible: false,\n reason: \"insecure_transport\",\n requestHost,\n authHost,\n expectedGatewayHost,\n };\n }\n\n if (requestHost === authHost) {\n return {\n compatible: true,\n reason: \"same_host\",\n requestHost,\n authHost,\n expectedGatewayHost,\n };\n }\n\n if (expectedGatewayHost && requestHost === expectedGatewayHost) {\n return {\n compatible: true,\n reason: \"gateway_sibling\",\n requestHost,\n authHost,\n expectedGatewayHost,\n };\n }\n\n return {\n compatible: false,\n reason: \"host_mismatch\",\n requestHost,\n authHost,\n expectedGatewayHost,\n };\n}\n\nexport function deriveAuthBaseUrlFromGatewayUrl(\n gatewayUrl: string\n): string | null {\n const parsed = parseUrlOrNull(gatewayUrl);\n if (!parsed) {\n return null;\n }\n if (!isHttpTransportProtocol(parsed.protocol)) {\n return null;\n }\n if (!parsed.hostname.startsWith(\"gateway.\")) {\n return null;\n }\n\n const authUrl = new URL(parsed.toString());\n authUrl.hostname = `auth.${parsed.hostname.slice(\"gateway.\".length)}`;\n authUrl.pathname = \"/\";\n authUrl.search = \"\";\n authUrl.hash = \"\";\n return normalizeBaseUrl(authUrl.toString());\n}\n\nfunction deriveGatewayHost(authBaseUrl: URL): string | null {\n if (!authBaseUrl.hostname.startsWith(\"auth.\")) {\n return null;\n }\n\n const gatewayUrl = new URL(authBaseUrl.toString());\n gatewayUrl.hostname = `gateway.${authBaseUrl.hostname.slice(\"auth.\".length)}`;\n return gatewayUrl.host;\n}\n\nfunction parseUrlOrNull(value: string): URL | null {\n try {\n return new URL(value);\n } catch {\n return null;\n }\n}\n\nfunction isLoopbackHostname(hostname: string): boolean {\n return (\n hostname === \"localhost\" || hostname === \"127.0.0.1\" || hostname === \"::1\"\n );\n}\n\nfunction isSecureTransportProtocol(protocol: string): boolean {\n return protocol === \"https:\" || protocol === \"wss:\";\n}\n\nfunction isHttpTransportProtocol(protocol: string): boolean {\n return protocol === \"http:\" || protocol === \"https:\";\n}\n","import crypto from \"node:crypto\";\nimport type { OpenMeldRequestContext } from \"@openmeld/schemas/types\";\nimport type { OpenMeldProfile } from \"./openmeld-profiles-api\";\n\nexport type OpenMeldRequestContextProfileIdentity = {\n openMeldProfileId: string;\n profileKind?: \"human\" | \"agent\" | \"system\";\n kind?: \"human\" | \"agent\";\n profileHandle?: string;\n profileName: string;\n ownerUserId?: string;\n ownerName?: string;\n agentControllerConversationId?: string;\n};\n\nexport function buildOpenMeldRequestContextFromProfile(input: {\n openMeldProfile: OpenMeldProfile;\n requestId?: string;\n agentControllerConversationId?: string;\n}): OpenMeldRequestContext {\n const requestId =\n normalizeOptionalText(input.requestId) ?? crypto.randomUUID();\n const agentControllerConversationId = normalizeOptionalText(\n input.agentControllerConversationId\n );\n const ownerName = normalizeOptionalText(input.openMeldProfile.ownerName);\n\n return {\n actorContext: {\n requestId,\n openMeldProfileId: input.openMeldProfile.openMeldProfileId,\n profileKind: input.openMeldProfile.profileKind,\n profileHandle: input.openMeldProfile.profileHandle,\n profileName: input.openMeldProfile.profileName,\n ownerUserId: input.openMeldProfile.ownerUserId,\n ...(ownerName ? { ownerName } : {}),\n },\n ...(agentControllerConversationId ? { agentControllerConversationId } : {}),\n };\n}\n\nexport function buildOpenMeldRequestContextFromProfileIdentity(input: {\n profileIdentity: OpenMeldRequestContextProfileIdentity;\n requestId?: string;\n}): OpenMeldRequestContext {\n const requestId =\n normalizeOptionalText(input.requestId) ?? crypto.randomUUID();\n const profileHandle = normalizeOptionalText(\n input.profileIdentity.profileHandle\n );\n const ownerUserId = normalizeOptionalText(input.profileIdentity.ownerUserId);\n const ownerName = normalizeOptionalText(input.profileIdentity.ownerName);\n const agentControllerConversationId = normalizeOptionalText(\n input.profileIdentity.agentControllerConversationId\n );\n const profileKind =\n input.profileIdentity.profileKind ??\n (input.profileIdentity.kind === \"human\" ||\n input.profileIdentity.kind === \"agent\"\n ? input.profileIdentity.kind\n : \"system\");\n\n return {\n actorContext: {\n requestId,\n openMeldProfileId: input.profileIdentity.openMeldProfileId,\n profileKind,\n ...(profileHandle ? { profileHandle } : {}),\n profileName: input.profileIdentity.profileName,\n ...(ownerUserId ? { ownerUserId } : {}),\n ...(ownerName ? { ownerName } : {}),\n },\n ...(agentControllerConversationId ? { agentControllerConversationId } : {}),\n };\n}\n\nfunction normalizeOptionalText(value: unknown): string | null {\n const normalized = String(value ?? \"\").trim();\n return normalized.length > 0 ? normalized : null;\n}\n","import {\n buildOpenMeldRequestContextHeaders,\n type OpenMeldRequestContextHeadersInput,\n} from \"@openmeld/gateway-contract\";\nimport type { OpenMeldRequestContext } from \"@openmeld/schemas/types\";\nimport {\n type AuthRequestCompatibilityReason,\n resolveAuthRequestCompatibility,\n} from \"./auth-request-compatibility\";\nimport {\n type AuthSessionStateReasonCode,\n getAuthSessionState,\n type StoredAuthSession,\n} from \"./auth-session\";\nimport { resolveAuthSessionExpiryEligibility } from \"./auth-session-expiry\";\nimport type { OpenMeldProfile } from \"./openmeld-profiles-api\";\nimport {\n buildOpenMeldRequestContextFromProfile,\n buildOpenMeldRequestContextFromProfileIdentity,\n type OpenMeldRequestContextProfileIdentity,\n} from \"./openmeld-request-context\";\n\nconst DEFAULT_TOKEN_TYPE = \"Bearer\";\nconst AUTHORIZATION_HEADER = \"Authorization\";\n\ntype RequestAuthHeadersInput = {\n authSession?: StoredAuthSession | null;\n requestUrl: string;\n};\n\ntype OpenMeldRequestContextHeadersWithAuthInput =\n OpenMeldRequestContextHeadersInput & {\n authSession?: StoredAuthSession | null;\n requestUrl: string;\n };\n\nexport type AuthTokenAttachment =\n | {\n status: \"attachable\";\n token: string;\n tokenType: string;\n }\n | {\n status: \"dropped\";\n reason:\n | \"empty_token\"\n | \"session_expired\"\n | \"session_expiry_invalid\"\n | AuthRequestCompatibilityReason;\n requestHost: string | null;\n authHost: string | null;\n expectedGatewayHost: string | null;\n };\n\nexport type DroppedAuthTokenAttachment = Extract<\n AuthTokenAttachment,\n { status: \"dropped\" }\n>;\n\nexport type AuthRequestCredentialFailureReason =\n | DroppedAuthTokenAttachment[\"reason\"]\n | AuthSessionStateReasonCode\n | \"session_invalid\"\n | \"session_revoked\";\n\nexport class AuthRequestCredentialError extends Error {\n readonly authHost: string | null;\n readonly expectedGatewayHost: string | null;\n readonly reason: AuthRequestCredentialFailureReason;\n readonly requestHost: string | null;\n readonly droppedAttachment?: DroppedAuthTokenAttachment;\n\n constructor(input: {\n authHost: string | null;\n expectedGatewayHost: string | null;\n reason: AuthRequestCredentialFailureReason;\n requestHost: string | null;\n droppedAttachment?: DroppedAuthTokenAttachment;\n }) {\n super(\n `OpenMeld refused to send a request with unusable stored credentials (${input.reason}).`\n );\n this.name = \"AuthRequestCredentialError\";\n this.authHost = input.authHost;\n this.expectedGatewayHost = input.expectedGatewayHost;\n this.reason = input.reason;\n this.requestHost = input.requestHost;\n this.droppedAttachment = input.droppedAttachment;\n }\n}\n\nexport async function buildRequestAuthHeaders(\n input: RequestAuthHeadersInput\n): Promise<Record<string, string>> {\n const headers: Record<string, string> = {};\n await attachAuthHeader(headers, input);\n return headers;\n}\n\nexport async function buildOpenMeldRequestContextHeadersWithAuth(\n input: OpenMeldRequestContextHeadersWithAuthInput\n): Promise<Record<string, string>> {\n const headers = buildOpenMeldRequestContextHeaders(input);\n await attachAuthHeader(headers, input);\n return headers;\n}\n\nexport async function buildOpenMeldProfileRequestHeadersWithAuth(input: {\n openMeldProfile: OpenMeldProfile;\n requestUrl: string;\n authSession?: StoredAuthSession | null;\n agentControllerConversationId?: string;\n spacePassword?: string;\n}): Promise<Record<string, string>> {\n return await buildOpenMeldRequestContextHeadersWithAuth({\n requestContext: buildOpenMeldRequestContextFromProfile({\n openMeldProfile: input.openMeldProfile,\n agentControllerConversationId: input.agentControllerConversationId,\n }),\n requestUrl: input.requestUrl,\n ...(input.authSession === undefined\n ? {}\n : { authSession: input.authSession }),\n ...(input.spacePassword === undefined\n ? {}\n : { spacePassword: input.spacePassword }),\n });\n}\n\nexport async function buildOpenMeldProfileIdentityRequestHeadersWithAuth(input: {\n profileIdentity: OpenMeldRequestContextProfileIdentity;\n requestUrl: string;\n authSession?: StoredAuthSession | null;\n spacePassword?: string;\n}): Promise<Record<string, string>> {\n return await buildOpenMeldRequestContextHeadersWithAuth({\n requestContext: buildOpenMeldRequestContextFromProfileIdentity({\n profileIdentity: input.profileIdentity,\n }),\n requestUrl: input.requestUrl,\n ...(input.authSession === undefined\n ? {}\n : { authSession: input.authSession }),\n ...(input.spacePassword === undefined\n ? {}\n : { spacePassword: input.spacePassword }),\n });\n}\n\nexport function withSpacePassword(\n requestContext: OpenMeldRequestContext,\n spacePassword?: string\n): OpenMeldRequestContextHeadersInput {\n return {\n requestContext,\n ...(spacePassword === undefined ? {} : { spacePassword }),\n };\n}\n\n// One decision for \"can this stored session authenticate this request\", with\n// the drop reason preserved. Header building and the daemon stream connect\n// gate must share this so they cannot drift apart.\nexport function resolveAuthTokenAttachment(input: {\n session: StoredAuthSession;\n requestUrl: string;\n}): AuthTokenAttachment {\n const compatibility = resolveAuthRequestCompatibility({\n session: input.session,\n requestUrl: input.requestUrl,\n });\n const token = normalizeAccessToken(input.session);\n if (!token) {\n return {\n status: \"dropped\",\n reason: \"empty_token\",\n requestHost: compatibility.requestHost,\n authHost: compatibility.authHost,\n expectedGatewayHost: compatibility.expectedGatewayHost,\n };\n }\n if (!compatibility.compatible) {\n return {\n status: \"dropped\",\n reason: compatibility.reason,\n requestHost: compatibility.requestHost,\n authHost: compatibility.authHost,\n expectedGatewayHost: compatibility.expectedGatewayHost,\n };\n }\n const expiryReason = resolveSessionExpiryReason(input.session);\n if (expiryReason) {\n return {\n status: \"dropped\",\n reason: expiryReason,\n requestHost: compatibility.requestHost,\n authHost: compatibility.authHost,\n expectedGatewayHost: compatibility.expectedGatewayHost,\n };\n }\n return {\n status: \"attachable\",\n token,\n tokenType: normalizeTokenType(input.session.tokenType),\n };\n}\n\nexport function requireAuthTokenAttachment(input: {\n session: StoredAuthSession;\n requestUrl: string;\n}): Extract<AuthTokenAttachment, { status: \"attachable\" }> {\n const attachment = resolveAuthTokenAttachment(input);\n if (attachment.status === \"dropped\") {\n throw createAuthRequestCredentialError(attachment);\n }\n return attachment;\n}\n\nasync function attachAuthHeader(\n headers: Record<string, string>,\n input: RequestAuthHeadersInput\n): Promise<void> {\n const session = await resolveAuthSessionForHeaders(input);\n if (session === null) {\n // No stored credentials exist, so there is nothing to strip: the caller\n // is knowingly sending an unauthenticated request.\n return;\n }\n\n let attachment: Extract<AuthTokenAttachment, { status: \"attachable\" }>;\n try {\n attachment = requireAuthTokenAttachment({\n session,\n requestUrl: input.requestUrl,\n });\n } catch (error) {\n if (error instanceof AuthRequestCredentialError) {\n logRejectedAuthRequestCredential(error);\n }\n throw error;\n }\n headers[AUTHORIZATION_HEADER] = `${attachment.tokenType} ${attachment.token}`;\n}\n\nfunction logRejectedAuthRequestCredential(\n error: AuthRequestCredentialError\n): void {\n console.error(\"[openmeld.auth.request_credential_rejected]\", {\n authHost: error.authHost,\n expectedGatewayHost: error.expectedGatewayHost,\n reason: error.reason,\n requestHost: error.requestHost,\n });\n}\n\nasync function resolveAuthSessionForHeaders(\n input: RequestAuthHeadersInput\n): Promise<StoredAuthSession | null> {\n if (input.authSession !== undefined) {\n return input.authSession;\n }\n\n const sessionState = await getAuthSessionState({ refreshExpired: true });\n if (sessionState.state === \"missing\") {\n return null;\n }\n if (sessionState.state !== \"valid\" || sessionState.session === null) {\n const error = new AuthRequestCredentialError({\n authHost: null,\n expectedGatewayHost: null,\n reason:\n sessionState.reasonCode ??\n (sessionState.state === \"revoked\"\n ? \"session_revoked\"\n : \"session_invalid\"),\n requestHost: parseRequestHost(input.requestUrl),\n });\n logRejectedAuthRequestCredential(error);\n throw error;\n }\n\n return sessionState.session;\n}\n\nfunction createAuthRequestCredentialError(\n attachment: DroppedAuthTokenAttachment\n): AuthRequestCredentialError {\n return new AuthRequestCredentialError({\n authHost: attachment.authHost,\n expectedGatewayHost: attachment.expectedGatewayHost,\n reason: attachment.reason,\n requestHost: attachment.requestHost,\n droppedAttachment: attachment,\n });\n}\n\nfunction parseRequestHost(requestUrl: string): string | null {\n try {\n return new URL(requestUrl).host || null;\n } catch {\n return null;\n }\n}\n\nfunction normalizeAccessToken(session: StoredAuthSession): string {\n return String(session.accessToken ?? \"\").trim();\n}\n\nfunction normalizeTokenType(tokenType: string | undefined): string {\n const normalized = String(tokenType ?? \"\").trim();\n return normalized.length > 0 ? normalized : DEFAULT_TOKEN_TYPE;\n}\n\nfunction resolveSessionExpiryReason(\n session: StoredAuthSession\n): \"session_expired\" | \"session_expiry_invalid\" | null {\n const eligibility = resolveAuthSessionExpiryEligibility(session.expiresAt);\n if (eligibility.status === \"invalid\") {\n return \"session_expiry_invalid\";\n }\n return eligibility.status === \"expired\" ? \"session_expired\" : null;\n}\n\nexport function canAttachAuthTokenToRequest(\n session: StoredAuthSession,\n requestUrl: string\n): boolean {\n return (\n resolveAuthTokenAttachment({\n session,\n requestUrl,\n }).status === \"attachable\"\n );\n}\n","import {\n DEFAULT_SPACE_CONVERSATION_VALIDATE_TIMEOUT_MS,\n DEFAULT_SPACE_REQUEST_TIMEOUT_MS,\n MAX_SPACE_REQUEST_TIMEOUT_MS,\n MIN_SPACE_REQUEST_TIMEOUT_MS,\n} from \"../strategy-constants\";\n\nconst SPACE_REQUEST_TIMEOUT_ENV_KEY = \"OPENMELD_SPACE_REQUEST_TIMEOUT_MS\";\n\nexport function resolveSpaceRequestTimeoutMs(override?: number): number {\n if (isFinitePositiveNumber(override)) {\n return clampSpaceRequestTimeoutMs(override);\n }\n\n const fromEnv = Number.parseInt(\n String(process.env[SPACE_REQUEST_TIMEOUT_ENV_KEY] ?? \"\"),\n 10\n );\n if (isFinitePositiveNumber(fromEnv)) {\n return clampSpaceRequestTimeoutMs(fromEnv);\n }\n\n return DEFAULT_SPACE_REQUEST_TIMEOUT_MS;\n}\n\nexport function resolveSpaceRequestTimeoutMsForDiagnostics(): number {\n return resolveSpaceRequestTimeoutMs(undefined);\n}\n\nexport function resolveSpaceConversationValidateTimeoutMs(): number {\n return Math.max(\n resolveSpaceRequestTimeoutMs(undefined),\n DEFAULT_SPACE_CONVERSATION_VALIDATE_TIMEOUT_MS\n );\n}\n\nfunction clampSpaceRequestTimeoutMs(value: number): number {\n const normalized = Math.trunc(value);\n return Math.max(\n MIN_SPACE_REQUEST_TIMEOUT_MS,\n Math.min(MAX_SPACE_REQUEST_TIMEOUT_MS, normalized)\n );\n}\n\nfunction isFinitePositiveNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value) && value > 0;\n}\n","import {\n resolveSpaceRequestTimeoutMs,\n resolveSpaceRequestTimeoutMsForDiagnostics as resolveSpaceRequestTimeoutMsForCliDiagnostics,\n} from \"./request-timeout\";\n\nexport async function fetchSpaceRequestWithTimeout(input: {\n url: string;\n operation: string;\n init?: RequestInit;\n timeoutMs?: number;\n}): Promise<Response> {\n const timeoutMs = resolveSpaceRequestTimeoutMs(input.timeoutMs);\n const timeoutSignal = AbortSignal.timeout(timeoutMs);\n const composed = composeAbortSignals(input.init?.signal, timeoutSignal);\n\n try {\n try {\n return await fetch(input.url, {\n ...input.init,\n signal: composed.signal,\n });\n } catch (error) {\n // A keep-alive connection that a proxy silently dropped fails exactly\n // once and undici evicts it; the retry rides a fresh connection. This\n // is what keeps a long-lived service working behind flaky proxies\n // without asking users to touch their network config.\n if (\n timeoutSignal.aborted ||\n composed.signal.aborted ||\n !shouldWrapNetworkRequestError(error)\n ) {\n throw error;\n }\n return await fetch(input.url, {\n ...input.init,\n signal: composed.signal,\n });\n }\n } catch (error) {\n if (timeoutSignal.aborted) {\n throw createSpaceRequestTimeoutError({\n operation: input.operation,\n timeoutMs,\n cause: error,\n });\n }\n if (shouldWrapNetworkRequestError(error)) {\n throw createSpaceRequestNetworkError({\n operation: input.operation,\n url: input.url,\n cause: error,\n });\n }\n throw error;\n } finally {\n composed.cleanup();\n }\n}\n\nexport function resolveSpaceRequestTimeoutMsForDiagnostics(): number {\n return resolveSpaceRequestTimeoutMsForCliDiagnostics();\n}\n\nfunction createSpaceRequestTimeoutError(input: {\n operation: string;\n timeoutMs: number;\n cause: unknown;\n}): Error {\n const error = new Error(\n `${input.operation} request timed out after ${input.timeoutMs}ms`,\n { cause: input.cause }\n ) as Error & { code?: string };\n error.code = \"network.timeout\";\n return error;\n}\n\nfunction createSpaceRequestNetworkError(input: {\n operation: string;\n url: string;\n cause: unknown;\n}): Error {\n const error = new Error(\n `${input.operation} request could not reach ${describeRequestTarget(input.url)} (${toErrorMessage(input.cause)})`,\n { cause: input.cause }\n ) as Error & { code?: string };\n error.code = \"network.request_failed\";\n return error;\n}\n\nfunction composeAbortSignals(\n parent: AbortSignal | null | undefined,\n timeout: AbortSignal\n): { signal: AbortSignal; cleanup: () => void } {\n if (!parent) {\n return {\n signal: timeout,\n cleanup: () => undefined,\n };\n }\n\n if (parent.aborted || timeout.aborted) {\n const controller = new AbortController();\n controller.abort();\n return {\n signal: controller.signal,\n cleanup: () => undefined,\n };\n }\n\n const controller = new AbortController();\n const abort = () => {\n controller.abort();\n };\n\n parent.addEventListener(\"abort\", abort, { once: true });\n timeout.addEventListener(\"abort\", abort, { once: true });\n\n return {\n signal: controller.signal,\n cleanup: () => {\n parent.removeEventListener(\"abort\", abort);\n timeout.removeEventListener(\"abort\", abort);\n },\n };\n}\n\nfunction describeRequestTarget(url: string): string {\n try {\n return new URL(url).origin;\n } catch {\n return url;\n }\n}\n\nfunction toErrorMessage(error: unknown): string {\n if (error instanceof Error) {\n const message = error.message.trim();\n return message.length > 0 ? message : \"request failed\";\n }\n const message = String(error ?? \"\").trim();\n return message.length > 0 ? message : \"request failed\";\n}\n\nfunction shouldWrapNetworkRequestError(error: unknown): boolean {\n if (error instanceof TypeError) {\n return true;\n }\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n typeof error.code === \"string\" &&\n error.code.startsWith(\"ERR_SSL_\")\n ) {\n return true;\n }\n const message = toErrorMessage(error).toLowerCase();\n return (\n message.includes(\"fetch failed\") ||\n message.includes(\"failed to fetch\") ||\n message.includes(\"network request failed\") ||\n message.includes(\"ssl_decryption_failed_or_bad_record_mac\")\n );\n}\n","import {\n createOpenMeldApiClient,\n type OpenMeldApiClientFoundation,\n} from \"@openmeld/api-client\";\nimport {\n buildOpenMeldRequestContextHeaders,\n OPENMELD_HEADER_REQUESTED_ORGANIZATION_ID,\n} from \"@openmeld/gateway-contract\";\nimport { buildRequestAuthHeaders } from \"../config/request-headers\";\nimport { fetchSpaceRequestWithTimeout } from \"./fetch-with-timeout\";\n\nexport function createCliApiClientFoundation(\n baseUrl: string,\n options: {\n onAuthHeadersResolved?: (headers: Record<string, string>) => void;\n organizationId?: string;\n } = {}\n): OpenMeldApiClientFoundation {\n return createOpenMeldApiClient({\n baseUrl,\n transport: async (request) =>\n await fetchSpaceRequestWithTimeout({\n url: request.url,\n operation: request.operation,\n init: request.init,\n timeoutMs: request.timeoutMs,\n }),\n getAuthHeaders: async ({ requestUrl }) => {\n const headers = await buildRequestAuthHeaders({\n requestUrl,\n });\n if (options.organizationId) {\n headers[OPENMELD_HEADER_REQUESTED_ORGANIZATION_ID] =\n options.organizationId;\n }\n options.onAuthHeadersResolved?.(headers);\n return headers;\n },\n getRequestContextHeaders: async ({ requestContext, spacePassword }) =>\n buildOpenMeldRequestContextHeaders({\n requestContext,\n ...(spacePassword === undefined ? {} : { spacePassword }),\n }),\n });\n}\n"],"mappings":"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"}
|