@fungi.computer/truffle 0.0.0-stage → 0.1.1

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 (116) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +294 -2
  3. package/computerd-loopback.cjs +16 -0
  4. package/dist/auth-cli.d.ts +36 -0
  5. package/dist/auth-cli.js +351 -0
  6. package/dist/fungi-account-command.d.ts +18 -0
  7. package/dist/fungi-account-command.js +92 -0
  8. package/dist/index.d.ts +19 -0
  9. package/dist/index.js +17 -0
  10. package/dist/internal/private-workerd-sandbox-worker.mjs +27488 -0
  11. package/dist/internal/sandbox-metafile.json +6726 -0
  12. package/dist/linear-auth.d.ts +4 -0
  13. package/dist/linear-auth.js +72 -0
  14. package/dist/local-extensions.d.ts +97 -0
  15. package/dist/local-extensions.js +484 -0
  16. package/dist/local-login.d.ts +55 -0
  17. package/dist/local-login.js +167 -0
  18. package/dist/local-models.d.ts +14 -0
  19. package/dist/local-models.js +77 -0
  20. package/dist/local-skill-source.d.ts +6 -0
  21. package/dist/local-skill-source.js +357 -0
  22. package/dist/log-event.d.ts +2 -0
  23. package/dist/log-event.js +9 -0
  24. package/dist/private-bun-shiitake-host.d.ts +11 -0
  25. package/dist/private-bun-shiitake-host.js +66 -0
  26. package/dist/private-file-credential-store.d.ts +33 -0
  27. package/dist/private-file-credential-store.js +283 -0
  28. package/dist/private-files-patch.d.ts +3 -0
  29. package/dist/private-files-patch.js +86 -0
  30. package/dist/private-fungi-account.d.ts +235 -0
  31. package/dist/private-fungi-account.js +1149 -0
  32. package/dist/private-fungi-auth-error.d.ts +5 -0
  33. package/dist/private-fungi-auth-error.js +7 -0
  34. package/dist/private-fungi-mcp-connection.d.ts +22 -0
  35. package/dist/private-fungi-mcp-connection.js +143 -0
  36. package/dist/private-fungi-mcp-endpoint.d.ts +2 -0
  37. package/dist/private-fungi-mcp-endpoint.js +15 -0
  38. package/dist/private-fungi-mcp-selection.d.ts +14 -0
  39. package/dist/private-fungi-mcp-selection.js +36 -0
  40. package/dist/private-fungi-model-api.d.ts +6 -0
  41. package/dist/private-fungi-model-api.js +125 -0
  42. package/dist/private-fungi-model-catalog.d.ts +6 -0
  43. package/dist/private-fungi-model-catalog.js +78 -0
  44. package/dist/private-fungi-model-provider.d.ts +6 -0
  45. package/dist/private-fungi-model-provider.js +46 -0
  46. package/dist/private-fungi-pending-logouts.d.ts +34 -0
  47. package/dist/private-fungi-pending-logouts.js +136 -0
  48. package/dist/private-invocation-computer.d.ts +37 -0
  49. package/dist/private-invocation-computer.js +459 -0
  50. package/dist/private-invocation-files.d.ts +15 -0
  51. package/dist/private-invocation-files.js +449 -0
  52. package/dist/private-local-acp-stdio.d.ts +17 -0
  53. package/dist/private-local-acp-stdio.js +142 -0
  54. package/dist/private-local-auth-rpc.d.ts +69 -0
  55. package/dist/private-local-auth-rpc.js +273 -0
  56. package/dist/private-local-computer-attach.d.ts +49 -0
  57. package/dist/private-local-computer-attach.js +216 -0
  58. package/dist/private-local-computer-backend.d.ts +282 -0
  59. package/dist/private-local-computer-backend.js +402 -0
  60. package/dist/private-local-computer-processes.d.ts +199 -0
  61. package/dist/private-local-computer-processes.js +589 -0
  62. package/dist/private-local-default-model.d.ts +11 -0
  63. package/dist/private-local-default-model.js +45 -0
  64. package/dist/private-local-delegation.d.ts +29 -0
  65. package/dist/private-local-delegation.js +78 -0
  66. package/dist/private-local-effective-model.d.ts +19 -0
  67. package/dist/private-local-effective-model.js +14 -0
  68. package/dist/private-local-exec-launch.d.ts +41 -0
  69. package/dist/private-local-exec-launch.js +51 -0
  70. package/dist/private-local-exec-path.d.ts +6 -0
  71. package/dist/private-local-exec-path.js +40 -0
  72. package/dist/private-local-git-exclude.d.ts +2 -0
  73. package/dist/private-local-git-exclude.js +33 -0
  74. package/dist/private-local-http-dispatch.d.ts +5 -0
  75. package/dist/private-local-http-dispatch.js +14 -0
  76. package/dist/private-local-mail.d.ts +11 -0
  77. package/dist/private-local-mail.js +69 -0
  78. package/dist/private-local-model-settings.d.ts +5 -0
  79. package/dist/private-local-model-settings.js +31 -0
  80. package/dist/private-local-runtime-host.d.ts +141 -0
  81. package/dist/private-local-runtime-host.js +988 -0
  82. package/dist/private-local-service-contract.d.ts +90 -0
  83. package/dist/private-local-service-contract.js +1 -0
  84. package/dist/private-local-service-discovery.d.ts +101 -0
  85. package/dist/private-local-service-discovery.js +221 -0
  86. package/dist/private-local-service-ids.d.ts +3 -0
  87. package/dist/private-local-service-ids.js +8 -0
  88. package/dist/private-local-service-listener.d.ts +15 -0
  89. package/dist/private-local-service-listener.js +211 -0
  90. package/dist/private-local-service-owner.d.ts +1567 -0
  91. package/dist/private-local-service-owner.js +371 -0
  92. package/dist/private-local-service-process.d.ts +1 -0
  93. package/dist/private-local-service-process.js +6 -0
  94. package/dist/private-local-service.d.ts +17 -0
  95. package/dist/private-local-service.js +330 -0
  96. package/dist/private-local-session-discovery.d.ts +19 -0
  97. package/dist/private-local-session-discovery.js +157 -0
  98. package/dist/private-local-shiitake-host.d.ts +44 -0
  99. package/dist/private-local-shiitake-host.js +143 -0
  100. package/dist/private-local-subagents.d.ts +27 -0
  101. package/dist/private-local-subagents.js +77 -0
  102. package/dist/private-local-worker-server.d.ts +15 -0
  103. package/dist/private-local-worker-server.js +136 -0
  104. package/dist/private-sqlite-owner.d.ts +7 -0
  105. package/dist/private-sqlite-owner.js +103 -0
  106. package/dist/private-team-computers.d.ts +38 -0
  107. package/dist/private-team-computers.js +101 -0
  108. package/dist/private-workerd-sandbox.d.ts +3 -0
  109. package/dist/private-workerd-sandbox.js +347 -0
  110. package/dist/team-apps.d.ts +24 -0
  111. package/dist/team-apps.js +123 -0
  112. package/dist/tracker-git-credential.d.ts +15 -0
  113. package/dist/tracker-git-credential.js +87 -0
  114. package/native/bin/build.json +4037 -0
  115. package/native/bin/fungi-apply-patch +0 -0
  116. package/package.json +148 -3
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jamstack Consulting LLC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,295 @@
1
- # Temporary Holding Version
1
+ # Local runtime
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ This private runtime hosts Agents and saved Sessions on the same user's machine.
4
+ The Fungi terminal consumes it through a persistent local service. It owns
5
+ SQLite storage, model credentials, project Files and shell operations, not
6
+ terminal rendering. It is an internal workspace, not a standalone npm
7
+ installation path.
8
+
9
+ ## Source setup
10
+
11
+ Use a configured repository checkout with the pinned Node, Bun and pnpm tools.
12
+ Local runs its own host build of the native `apply_patch` engine, which
13
+ [`@fungi.computer/cordyceps`](../../packages/cordyceps/README.md#native-patch-engine)
14
+ owns; Cordyceps' build prerequisites apply. Run from the repository root:
15
+
16
+ ```sh
17
+ pnpm turbo:run run build --filter=@fungi.computer/truffle
18
+ pnpm --filter @fungi.computer/truffle test
19
+ ```
20
+
21
+ The build places the engine in `native/bin` through Cordyceps'
22
+ `fungi-apply-patch-build` and Local's dependency closure, then the tests run its
23
+ unit and native patch tests. They do not sign in to a provider or start a
24
+ customer Agent. Build outputs and test fixtures are disposable. Without a built
25
+ engine, Local offers no `apply_patch` tool.
26
+
27
+ ## Host and Session lifetime
28
+
29
+ [openPrivateLocalRuntimeHost](src/private-local-runtime-host.ts) captures the
30
+ canonical project root and opens the Agent's SQLite store, Shiitake owner, model
31
+ source and tool resources. A fresh Agent store lives under the project's
32
+ `.fungi/agents/`. Reopening a store retains its Agent identity and Sessions.
33
+ Corrupt, unreadable or already-owned stores remain explicit failures, not
34
+ reasons to silently create a replacement.
35
+
36
+ [openPrivateLocalShiitakeHost](src/private-local-shiitake-host.ts) mounts the
37
+ ordinary Shiitake HTTP routes through an injected loopback server opener and
38
+ returns the neutral client and `main` Session. Closing it releases the client,
39
+ transport and owner. The worker-batch variant owns several named routes on one
40
+ server. Closing the batch closes their resources.
41
+
42
+ The [service manager](src/private-local-service.ts) discovers or starts the same
43
+ user's shared background service. It selects project stores and creates or
44
+ resumes Sessions through that owner. Closing a client connection does not stop
45
+ the service or erase its Session. Explicit service shutdown drains its owners.
46
+ The CLI's `fungi stop` requests that shutdown. Clients only reconnect to a
47
+ service from the same build. After an upgrade, finish active turns, run
48
+ `fungi stop`, then reopen with `fungi resume --last` from the original project.
49
+ Saved Sessions remain on disk. This avoids running a service whose installed
50
+ sandbox executable was removed by the upgrade; the client never stops an older
51
+ service automatically.
52
+
53
+ A Session keeps its invoking client's validated executable PATH while its owner
54
+ is live. Reconnecting the same live Session with a different PATH is a conflict.
55
+ Stop the service before deliberately rebinding that Session to a different
56
+ toolchain. Other caller environment variables are not imported.
57
+
58
+ ## Files, tools and models
59
+
60
+ The local Computer is explicit in execute: `env.computers.local.exec(...)` and
61
+ `env.computers.local.files.read/list/glob/grep/edit(...)`. There is no shared
62
+ `files` module or Computer role named Home. The host grants the product Home
63
+ extension its already-rooted port; Home adopts the single local attachment and
64
+ supplies direct `read`, `list`, `glob`, `grep` and native `apply_patch` tools.
65
+ The same tool gate admits each direct call. `/home local` is a human command;
66
+ there is no model operation that changes Home.
67
+
68
+ - [Files](src/private-invocation-files.ts) captures the project root and rejects
69
+ path or symlink escapes. Native patch follows its own stricter rooted
70
+ contract.
71
+ - [Shell commands](src/private-invocation-computer.ts) run POSIX `sh` with the
72
+ OS user's access, a rooted cwd and bounded output. Files containment is not a
73
+ claim that arbitrary shell commands are an OS sandbox. `exec`'s `run` input is
74
+ one Zod boundary over two mutually exclusive forms: the shell form (`command`,
75
+ interpreted by `sh -c`) and a direct form (`executable` and `args`, run with
76
+ no shell interpretation at all, through the same bounded native process owner
77
+ `runPrivateInvocationProcess`). Zod refuses a request carrying both or
78
+ neither. Either form accepts optional `stdin`
79
+ ([its own bound](src/private-local-exec-launch.ts), not borrowed from Files),
80
+ written to the child once, then closed; there is no interactive stdin. An
81
+ omitted `stdin` closes immediately rather than leaving an open pipe, so a
82
+ reader such as `cat` sees EOF instead of hanging. A direct-form executable the
83
+ host cannot find or run reports a typed refusal naming it, rather than a
84
+ generic sandbox failure.
85
+ - [Background processes](src/private-local-computer-processes.ts) support start,
86
+ poll, wait, list and kill on the existing exec surface. `start` takes the same
87
+ shell-or-direct, optional-stdin input as `run`, through the existing
88
+ background process owner (`ManagedProcess`/`spawn`, not `run`'s
89
+ `runPrivateInvocationProcess`). Wait is bounded to 60 seconds. Cancelling a
90
+ wait does not kill the process. Output retains a bounded tail with offsets.
91
+ Session deletion or owner close stops its groups. Process IDs do not survive
92
+ host restart.
93
+ - [Guest execution](src/private-workerd-sandbox.ts) uses the maintained workerd
94
+ sandbox and admitted Mycelium capabilities. It reports typed boundary failures
95
+ separately from the native command's result.
96
+ - [Models](src/local-models.ts) uses Pi's registry and Veil's allowed login
97
+ methods with the local credential store. Fungi's provider reads its hosted
98
+ catalog through the selected Team and uses Hub billing. Model choice follows
99
+ explicit Session, explicit Agent, the person's remembered model in
100
+ `~/.config/fungi/shiitake.json`, a host's Team default, then an available
101
+ provider login. A Session `/model` switch is only that Session's override; it
102
+ never changes an Agent default or another Agent. Agent defaults stay in their
103
+ Agent store. The host validates offered models and supported thinking levels.
104
+ `agents.models` lists the `provider/model` addresses offered by signed-in or
105
+ configured providers. `agents.create` accepts an optional address from that
106
+ list, and `agents.setModel` changes future runs without replacing Session
107
+ overrides. An address Local does not offer fails as a typed `model:rejected`
108
+ capability failure and changes nothing. Creation and sends refuse missing
109
+ provider login; failed runs keep a safe, actionable diagnostic for
110
+ `agents.wait`. A hosted Team's key-source choice remains an explicit
111
+ restriction, including when a manual model is selected.
112
+ - [Delegation](src/private-local-delegation.ts) gives each project Agent the
113
+ Hub's `followUp` delegation over its own store. `agents.send` freezes BirdDog
114
+ mail through `fleet.start` and returns the child's `commandId`. The
115
+ [service owner](src/private-local-service-owner.ts) routes mail between its
116
+ project Agents and opens an idle addressee, so a reply wakes an idle parent;
117
+ an active parent runs it next, after its current work. An Agent admits only
118
+ new work that replies to its sender, or a reply that `fleet.authenticateReply`
119
+ verifies against the mail it sent. That reply is authored by the child,
120
+ carries `meta.delegation.reply`, and reaches the model inside
121
+ `<fungi_agent_reply>`. Every other mail is refused.
122
+
123
+ Root `AGENTS.md` is captured through the rooted Files owner for run
124
+ instructions. Missing optional instructions are different from unreadable,
125
+ oversized or escaping files. This instruction port stays tied to the project
126
+ root independently of Home.
127
+
128
+ [Skills](src/local-skill-source.ts) use the product extension's `prompt` and
129
+ `run_tools` hooks. The prompt lists names and descriptions;
130
+ `skill.load({name, file?})` reads instructions or a supporting file through
131
+ `execute`. Bodies stay tool output. Discovery diagnostics distinguish empty
132
+ roots from skipped or rejected entries and explain them in the skills section.
133
+ Raw causes remain redacted in local service logs.
134
+
135
+ Discovery follows Pi 0.73.1: project `.fungi/skills`, then `.agents/skills` from
136
+ the project folder up to its git root, then personal `~/.fungi/skills` and
137
+ `~/.agents/skills`. Project roots precede personal roots. Claude and Pi folders
138
+ are not defaults. Extra folders are opt-in through a `skills` list in
139
+ `.fungi/settings.json` or `~/.fungi/settings.json`, for example:
140
+
141
+ ```json
142
+ { "skills": ["~/.claude/skills"] }
143
+ ```
144
+
145
+ Project settings paths are relative to the project; personal settings paths are
146
+ relative to `~/.fungi`. `~/` expands to the user's home. Project extra folders
147
+ precede personal roots. The first name wins; collisions warn. A directory with
148
+ `SKILL.md` is one skill and stops discovery below it; other directories are
149
+ searched recursively, excluding dot directories and `node_modules`. This also
150
+ finds Claude's `synced/<id-pair>/<skill>/SKILL.md` layout when opted in.
151
+
152
+ A non-empty description is required. Name-rule violations and descriptions over
153
+ 1,024 characters warn without rejecting the skill. Only a literal YAML
154
+ `disable-model-invocation: true` hides it from model discovery. Discovery stays
155
+ inside the canonical root, including symlink targets, with a 16-level depth and
156
+ 512-entry limit per root. Reads remain inside each selected skill's real
157
+ directory, with the existing file and catalog size limits. Scripts are listed,
158
+ never executed by this source.
159
+
160
+ ## Installed extensions
161
+
162
+ `@fungi.computer/truffle/extensions` is the one owner of installed extensions.
163
+ It keeps package bytes and the install record in `~/.fungi/extensions`, and the
164
+ activations its own operations write in `~/.fungi/extensions/activations.json`.
165
+ Files in a project or an Agent store never enable anything, so a copied folder
166
+ starts disabled.
167
+
168
+ - `add(source)` installs a Git URL, npm spec or path with the shipped Bun
169
+ package manager, lifecycle scripts disabled and a private cache. A Git source
170
+ is pinned to the commit Bun resolved; updating is another `add`. A package
171
+ whose declared `./host` entry or terminal program is not built is refused.
172
+ - `enableProject(root, id)` turns on the extension's client entry and programs
173
+ for that folder, whichever Agent is selected.
174
+ - `enableAgent(store, id)` grants one Agent store the capabilities the current
175
+ revision declares. The Agent keeps an older accepted revision until it is
176
+ enabled again, so an upgrade never widens it silently.
177
+ - `remove(id)` deletes the package and every activation that references it.
178
+
179
+ The package declares itself in `package.json`:
180
+
181
+ ```json
182
+ {
183
+ "exports": { "./host": "./host.mjs" },
184
+ "fungi": {
185
+ "id": "counter",
186
+ "capabilities": ["run_tools"],
187
+ "terminals": [
188
+ { "id": "counter", "name": "Counter", "command": ["./bin/counter.mjs"] }
189
+ ]
190
+ }
191
+ }
192
+ ```
193
+
194
+ `./host` exports a factory. Local calls it with its own `defineExtension`,
195
+ `Mycelium` and `z`, and a 0700 runtime directory for the project. The Agent
196
+ store's roster takes the result when that Agent opens, with exactly the accepted
197
+ capabilities. The same directory reaches the extension's programs as
198
+ `FUNGI_EXTENSION_RUNTIME_DIR`, so a tool can talk to the program a person opened
199
+ in a pane. Installed code is trusted and runs as you.
200
+ [`local-extensions.bun.test.ts`](test/local-extensions.bun.test.ts) installs the
201
+ [counter fixture](test/fixtures/extension-counter/) from a disposable bare Git
202
+ repository and calls its tools through the real workerd `execute`.
203
+
204
+ ## Team connections and ACP
205
+
206
+ A Team MCP connection adds admitted hosted Computer tools to a local Agent. It
207
+ does not move the local Files root or Session storage into the Hub.
208
+
209
+ [Fungi account custody](src/private-fungi-account.ts) supplies the same OAuth
210
+ login and locked refresh to MCP and models. `fungi login --provider fungi` opens
211
+ browser sign-in and selects a current Team for model billing. The Local model
212
+ picker refreshes that Team's live hosted catalog. A fresh Local Agent defaults
213
+ to Fungi's catalog default, with `@fungi/luna` as the initial selection before
214
+ the catalog is available. A saved Session override takes precedence; signing in
215
+ does not replace it. The project MCP endpoint and the model's selected Team are
216
+ independent. Switching one does not rewrite the other.
217
+
218
+ `fungi logout` and Pi logout share Local's sign-out owner: it attempts every
219
+ Computer detach before clearing the credential, then retries unconfirmed OAuth
220
+ revocation once. Sign-out always removes local credentials. It names Computers
221
+ whose detach is unconfirmed and links their Hub Computers pages; a running
222
+ backend may still serve until detached there or stopped locally.
223
+
224
+ The private `credentials.json.pending-logouts.json` journal retains only issuer,
225
+ account, login-family, Team, Computer and attach-request IDs plus cleanup
226
+ status, never keys, tokens or folder paths. After the next successful
227
+ same-account sign-in, Local retries cleanup with the new session before Team
228
+ selection. Another account or issuer discards pending intents. The journal
229
+ evicts oldest entries above 128 records or 256 KiB with a diagnostic. There is
230
+ no startup prompt; Computers and Connected logins provide manual recovery. See
231
+ the current
232
+ [Computer backend custody](../../wiki/2-areas/computer-execution-backends.md).
233
+
234
+ [The Fungi provider](src/private-fungi-model-provider.ts) uses Pi's maintained
235
+ completion API through the selected Team. It validates the hosted catalog and
236
+ does not expose supplier credentials to Local. Sign-in, credit, paused-service
237
+ and reachability refusals remain actionable failures. They do not trigger a
238
+ supplier fallback. Local key/subscription providers remain available separately.
239
+
240
+ Attaching a local folder to a Team Computer is a separate dial-out connection
241
+ with its own device key, sync and confirmation. It runs commands as the member's
242
+ OS user. Offline conflicts keep the Computer's version. The absolute folder path
243
+ and private key stay local.
244
+
245
+ [The ACP stdio adapter](src/private-local-acp-stdio.ts) exports
246
+ `runPrivateLocalAcpStdio` through `@fungi.computer/truffle/acp-stdio`. It serves
247
+ stable ACP v1 over the maintained NDJSON stream and the persistent service's
248
+ Sessions. The CLI launches this adapter with `fungi acp`; editor configuration
249
+ uses executable `fungi` and arguments `["acp"]`. It supports text and image
250
+ prompts, embedded text/image resources and resource links, plus Session listing,
251
+ loading and cancellation. Terminal-auth clients invoke `fungi acp login` for the
252
+ ordinary Fungi login. Nonempty additional directories and supplied MCP servers
253
+ are rejected. The admitted directory owns authorization, and closing a client
254
+ lease retains durable Session data.
255
+
256
+ ## Check this runtime
257
+
258
+ From the repository root:
259
+
260
+ ```sh
261
+ pnpm --filter @fungi.computer/truffle typecheck
262
+ pnpm --filter @fungi.computer/truffle lint
263
+ pnpm --filter @fungi.computer/truffle test:full
264
+ ```
265
+
266
+ [Runtime-host tests](test/private-local-runtime-host.test.ts) exercise native
267
+ SQLite, provider fixtures, instruction snapshots, replay and close.
268
+ [Computer tests](test/private-invocation-computer.test.ts) cover process-group
269
+ cleanup and deadlines.
270
+ [Background-process tests](test/private-local-computer-processes.test.ts) cover
271
+ bounded waits and output tails.
272
+ [ACP stdio tests](test/private-local-acp-stdio.test.ts) cover protocol
273
+ initialization. [Fungi model tests](test/private-fungi-model-provider.test.ts)
274
+ cover the live catalog contract, selected-Team billing, streamed fixture replies
275
+ and refusal recovery. [Account tests](test/private-fungi-account.test.ts) cover
276
+ shared refresh and sign-out custody, including competing processes. Bun service
277
+ tests and separate scripts are listed in [package.json](package.json).
278
+ Controlled replies do not prove a live provider login, a published CLI release
279
+ or a hosted Team deployment.
280
+
281
+ ## Selected-Team App reads
282
+
283
+ `openLocalTeamApps` from `@fungi.computer/truffle/apps` opens the saved
284
+ account's selected Team. Its `read`, `requestGill`, `surfaceUrl` and
285
+ `openSession` operations keep credentials inside Local and recheck account
286
+ selection around reads. Gill requests resolve current directory selectors and
287
+ declared actions through the ordinary admitted App door. Hosted Session
288
+ transport uses the Local OAuth door and the same Team/resource capability rule
289
+ as browser Sessions. Closing a Session client releases observation; it does not
290
+ cancel durable work.
291
+
292
+ The directory grammar lives in `@fungi.computer/oyster/shell/app-directory`. UI
293
+ handoff resolves the selected App's published surface on the saved Hub origin,
294
+ without putting an access token in the URL. A later account/Team selection
295
+ retires this client; open a new client for the new selection.
@@ -0,0 +1,16 @@
1
+ /*
2
+ * Preloaded into the computerd 0.2.1 daemon that Fungi Local starts for an
3
+ * attached folder. computerd binds 0.0.0.0 with no option to change it; its
4
+ * RPC runs commands as this user, so it must never be reachable from the
5
+ * network. Rebind every listener that asks for all interfaces to loopback.
6
+ * Remove this once computerd accepts a listen host.
7
+ */
8
+ "use strict";
9
+ const net = require("node:net");
10
+
11
+ // computerd calls listen(port, "0.0.0.0", callback).
12
+ const listen = net.Server.prototype.listen;
13
+ net.Server.prototype.listen = function loopbackListen(...args) {
14
+ if (args[1] === "0.0.0.0") args[1] = "127.0.0.1";
15
+ return listen.apply(this, args);
16
+ };
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env node
2
+ export { linearAuthInteraction } from "./linear-auth.js";
3
+ import type { AuthInteraction, AuthType, Models } from "@earendil-works/pi-ai";
4
+ export { maximumCredentialStringLength as localAuthInputLimit } from "./private-file-credential-store.js";
5
+ export type LocalAuthModels = Pick<Models, "checkAuth" | "getProviders" | "login" | "logout">;
6
+ /** Typed provider configuration returned to local status callers. */
7
+ export type LocalAuthStatus = Readonly<{
8
+ providerId: string;
9
+ providerName: string;
10
+ state: "unconfigured";
11
+ }> | Readonly<{
12
+ providerId: string;
13
+ providerName: string;
14
+ state: "configured";
15
+ type: AuthType;
16
+ }>;
17
+ export type LocalAuthResult = Readonly<{
18
+ kind: "completed";
19
+ }> | Readonly<{
20
+ kind: "status";
21
+ providers: readonly LocalAuthStatus[];
22
+ }>;
23
+ export type SignalProcess = {
24
+ once(signal: NodeJS.Signals, listener: () => void): void;
25
+ removeListener(signal: NodeJS.Signals, listener: () => void): void;
26
+ };
27
+ export type LocalAuthCliOptions = {
28
+ models?: LocalAuthModels;
29
+ input?: NodeJS.ReadableStream;
30
+ output?: NodeJS.WritableStream;
31
+ signals?: SignalProcess;
32
+ interaction?: AuthInteraction;
33
+ /** Stable host identity for Pi's ChatGPT sign-in. Defaults to the local store's. */
34
+ getDeviceId?: () => Promise<string>;
35
+ };
36
+ export declare function runLocalAuthCli(argv: readonly string[], options?: LocalAuthCliOptions): Promise<LocalAuthResult>;