@fungi.computer/truffle 0.3.0 → 0.4.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 (34) hide show
  1. package/dist/local-extensions.js +108 -33
  2. package/dist/local-login.js +9 -3
  3. package/dist/local-upgrade.d.ts +63 -0
  4. package/dist/local-upgrade.js +358 -0
  5. package/dist/private-local-agent-control.d.ts +3 -0
  6. package/dist/private-local-agent-control.js +5 -1
  7. package/dist/private-local-delegation.js +12 -5
  8. package/dist/private-local-exec-review.d.ts +3 -1
  9. package/dist/private-local-exec-review.js +66 -17
  10. package/dist/private-local-exec-rules.d.ts +5 -3
  11. package/dist/private-local-exec-rules.js +30 -9
  12. package/dist/private-local-extension-archive-notice.d.ts +8 -0
  13. package/dist/private-local-extension-archive-notice.js +108 -0
  14. package/dist/private-local-extension-records.d.ts +25 -0
  15. package/dist/private-local-extension-records.js +51 -0
  16. package/dist/private-local-process-identity.d.ts +14 -0
  17. package/dist/private-local-process-identity.js +51 -0
  18. package/dist/private-local-runtime-host.d.ts +16 -1
  19. package/dist/private-local-runtime-host.js +92 -37
  20. package/dist/private-local-service-discovery.js +2 -3
  21. package/dist/private-local-service-listener.js +1 -1
  22. package/dist/private-local-service-log.d.ts +10 -0
  23. package/dist/private-local-service-log.js +3 -0
  24. package/dist/private-local-service-owner.d.ts +1 -1
  25. package/dist/private-local-service-owner.js +22 -8
  26. package/dist/private-local-service-termination.js +12 -11
  27. package/dist/private-local-service.js +12 -0
  28. package/dist/private-local-session-discovery.d.ts +6 -0
  29. package/dist/private-local-session-discovery.js +31 -0
  30. package/dist/private-mcp-form-contract.d.ts +15 -0
  31. package/dist/private-mcp-form-contract.js +8 -1
  32. package/dist/private-mcp-form-session.d.ts +32 -0
  33. package/dist/private-mcp-form-session.js +8 -5
  34. package/package.json +20 -13
@@ -51,6 +51,7 @@ declare const answerResult: Schema.Union<readonly [Schema.Struct<{
51
51
  readonly kind: Schema.Literal<"policy">;
52
52
  }>]>>;
53
53
  readonly reason: Schema.NullOr<Schema.Literals<readonly ["not-found", "not-eligible", "already-answered", "stale-revision", "expired", "declined", "fenced", "not-granted", "read-only", "pending", "in-flight", "outcome-unknown", "identity-conflict"]>>;
54
+ readonly denialNote: Schema.optionalKey<Schema.String>;
54
55
  readonly requestedAt: Schema.Int;
55
56
  readonly expiresAt: Schema.Int;
56
57
  readonly updatedAt: Schema.Int;
@@ -62,6 +63,7 @@ declare const answerResult: Schema.Union<readonly [Schema.Struct<{
62
63
  }>, Schema.Struct<{
63
64
  readonly kind: Schema.Literal<"refused">;
64
65
  readonly reason: Schema.Literals<readonly ["not-found", "not-eligible", "already-answered", "stale-revision", "expired", "declined", "fenced", "not-granted", "read-only", "pending", "in-flight", "outcome-unknown", "identity-conflict"]>;
66
+ readonly denialNote: Schema.optionalKey<Schema.String>;
65
67
  }>, Schema.Struct<{
66
68
  readonly kind: Schema.Literal<"submitted">;
67
69
  }>, Schema.Struct<{
@@ -79,6 +81,7 @@ export declare const mcpFormApprovalContract: {
79
81
  readonly id: Schema.String;
80
82
  readonly decision: Schema.Literals<readonly ["approve", "deny", "always-allow"]>;
81
83
  readonly expectedRevision: Schema.Int;
84
+ readonly denialNote: Schema.optionalKey<Schema.String>;
82
85
  }>;
83
86
  output: Schema.Union<readonly [Schema.Struct<{
84
87
  readonly kind: Schema.Literal<"answered">;
@@ -115,6 +118,7 @@ export declare const mcpFormApprovalContract: {
115
118
  readonly kind: Schema.Literal<"policy">;
116
119
  }>]>>;
117
120
  readonly reason: Schema.NullOr<Schema.Literals<readonly ["not-found", "not-eligible", "already-answered", "stale-revision", "expired", "declined", "fenced", "not-granted", "read-only", "pending", "in-flight", "outcome-unknown", "identity-conflict"]>>;
121
+ readonly denialNote: Schema.optionalKey<Schema.String>;
118
122
  readonly requestedAt: Schema.Int;
119
123
  readonly expiresAt: Schema.Int;
120
124
  readonly updatedAt: Schema.Int;
@@ -126,6 +130,7 @@ export declare const mcpFormApprovalContract: {
126
130
  }>, Schema.Struct<{
127
131
  readonly kind: Schema.Literal<"refused">;
128
132
  readonly reason: Schema.Literals<readonly ["not-found", "not-eligible", "already-answered", "stale-revision", "expired", "declined", "fenced", "not-granted", "read-only", "pending", "in-flight", "outcome-unknown", "identity-conflict"]>;
133
+ readonly denialNote: Schema.optionalKey<Schema.String>;
129
134
  }>, Schema.Struct<{
130
135
  readonly kind: Schema.Literal<"submitted">;
131
136
  }>, Schema.Struct<{
@@ -171,6 +176,7 @@ export declare const mcpFormApprovalContract: {
171
176
  readonly kind: Schema.Literal<"policy">;
172
177
  }>]>>;
173
178
  readonly reason: Schema.NullOr<Schema.Literals<readonly ["not-found", "not-eligible", "already-answered", "stale-revision", "expired", "declined", "fenced", "not-granted", "read-only", "pending", "in-flight", "outcome-unknown", "identity-conflict"]>>;
179
+ readonly denialNote: Schema.optionalKey<Schema.String>;
174
180
  readonly requestedAt: Schema.Int;
175
181
  readonly expiresAt: Schema.Int;
176
182
  readonly updatedAt: Schema.Int;
@@ -183,8 +189,17 @@ export declare const mcpFormApprovalContract: {
183
189
  readonly command: Schema.String;
184
190
  readonly cwd: Schema.String;
185
191
  readonly justification: Schema.String;
192
+ readonly form: Schema.Literals<readonly ["direct", "shell"]>;
193
+ readonly kind: Schema.Literals<readonly ["exec", "extension-install"]>;
194
+ readonly argv: Schema.optionalKey<Schema.$Array<Schema.String>>;
186
195
  readonly prefix: Schema.optionalKey<Schema.$Array<Schema.String>>;
187
196
  readonly warning: Schema.optionalKey<Schema.String>;
197
+ readonly alwaysAllowCoverage: Schema.optionalKey<Schema.String>;
198
+ readonly alwaysAllowUnavailableReason: Schema.optionalKey<Schema.String>;
199
+ readonly risk: Schema.optionalKey<Schema.Struct<{
200
+ readonly summary: Schema.String;
201
+ readonly detail: Schema.String;
202
+ }>>;
188
203
  }>>;
189
204
  }>>;
190
205
  }>;
@@ -1,6 +1,6 @@
1
1
  import { ExtensionId, } from "@fungi.computer/shiitake/extensions";
2
2
  import * as Schema from "effect/Schema";
3
- import { ApprovalAnswerInputSchema, ApprovalRefusalSchema, ApprovalViewSchema, } from "@fungi.computer/approvals";
3
+ import { ApprovalAnswerInputSchema, ApprovalDenialNoteSchema, ApprovalRefusalSchema, ApprovalViewSchema, } from "@fungi.computer/approvals";
4
4
  /** The actual MCP form, not a ledger record or an authorization decision. */
5
5
  export const McpFormApprovalRequestSchema = Schema.Struct({
6
6
  message: Schema.String,
@@ -36,8 +36,14 @@ const McpFormPendingSchema = Schema.Struct({
36
36
  command: Schema.String,
37
37
  cwd: Schema.String,
38
38
  justification: Schema.String,
39
+ form: Schema.Literals(["direct", "shell"]),
40
+ kind: Schema.Literals(["exec", "extension-install"]),
41
+ argv: Schema.optionalKey(Schema.Array(Schema.String)),
39
42
  prefix: Schema.optionalKey(Schema.Array(Schema.String)),
40
43
  warning: Schema.optionalKey(Schema.String),
44
+ alwaysAllowCoverage: Schema.optionalKey(Schema.String),
45
+ alwaysAllowUnavailableReason: Schema.optionalKey(Schema.String),
46
+ risk: Schema.optionalKey(Schema.Struct({ summary: Schema.String, detail: Schema.String })),
41
47
  })),
42
48
  });
43
49
  /** The existing Session extension slot carries only display-safe form data. */
@@ -50,6 +56,7 @@ export const mcpFormApprovalContract = {
50
56
  id: Schema.String,
51
57
  decision: Schema.Literals(["approve", "deny", "always-allow"]),
52
58
  expectedRevision: ApprovalAnswerInputSchema.fields.expectedRevision,
59
+ denialNote: Schema.optionalKey(ApprovalDenialNoteSchema),
53
60
  }),
54
61
  output: answerResult,
55
62
  },
@@ -5,8 +5,17 @@ export type LocalApprovalReview = {
5
5
  command: string;
6
6
  cwd: string;
7
7
  justification: string;
8
+ form: "direct" | "shell";
9
+ kind: "exec" | "extension-install";
10
+ argv?: string[];
8
11
  prefix?: readonly string[];
9
12
  warning?: string;
13
+ alwaysAllowCoverage?: string;
14
+ alwaysAllowUnavailableReason?: string;
15
+ risk?: {
16
+ summary: string;
17
+ detail: string;
18
+ };
10
19
  };
11
20
  type Pending = {
12
21
  sessionId: string;
@@ -25,6 +34,7 @@ export declare function createMcpFormSession(): {
25
34
  readonly id: import("effect/Schema").String;
26
35
  readonly decision: import("effect/Schema").Literals<readonly ["approve", "deny", "always-allow"]>;
27
36
  readonly expectedRevision: import("effect/Schema").Int;
37
+ readonly denialNote: import("effect/Schema").optionalKey<import("effect/Schema").String>;
28
38
  }>;
29
39
  output: import("effect/Schema").Union<readonly [import("effect/Schema").Struct<{
30
40
  readonly kind: import("effect/Schema").Literal<"answered">;
@@ -61,6 +71,7 @@ export declare function createMcpFormSession(): {
61
71
  readonly kind: import("effect/Schema").Literal<"policy">;
62
72
  }>]>>;
63
73
  readonly reason: import("effect/Schema").NullOr<import("effect/Schema").Literals<readonly ["not-found", "not-eligible", "already-answered", "stale-revision", "expired", "declined", "fenced", "not-granted", "read-only", "pending", "in-flight", "outcome-unknown", "identity-conflict"]>>;
74
+ readonly denialNote: import("effect/Schema").optionalKey<import("effect/Schema").String>;
64
75
  readonly requestedAt: import("effect/Schema").Int;
65
76
  readonly expiresAt: import("effect/Schema").Int;
66
77
  readonly updatedAt: import("effect/Schema").Int;
@@ -72,6 +83,7 @@ export declare function createMcpFormSession(): {
72
83
  }>, import("effect/Schema").Struct<{
73
84
  readonly kind: import("effect/Schema").Literal<"refused">;
74
85
  readonly reason: import("effect/Schema").Literals<readonly ["not-found", "not-eligible", "already-answered", "stale-revision", "expired", "declined", "fenced", "not-granted", "read-only", "pending", "in-flight", "outcome-unknown", "identity-conflict"]>;
86
+ readonly denialNote: import("effect/Schema").optionalKey<import("effect/Schema").String>;
75
87
  }>, import("effect/Schema").Struct<{
76
88
  readonly kind: import("effect/Schema").Literal<"submitted">;
77
89
  }>, import("effect/Schema").Struct<{
@@ -113,6 +125,7 @@ export declare function createMcpFormSession(): {
113
125
  readonly expiresAt: number;
114
126
  readonly updatedAt: number;
115
127
  readonly revision: number;
128
+ readonly denialNote?: string;
116
129
  readonly evidence?: readonly {
117
130
  readonly kind: "artifact";
118
131
  readonly ref: string;
@@ -124,11 +137,20 @@ export declare function createMcpFormSession(): {
124
137
  readonly canSetAutoApprove: boolean;
125
138
  };
126
139
  readonly review?: {
140
+ readonly kind: "exec" | "extension-install";
141
+ readonly form: "direct" | "shell";
127
142
  readonly command: string;
128
143
  readonly cwd: string;
129
144
  readonly justification: string;
145
+ readonly argv?: readonly string[];
130
146
  readonly prefix?: readonly string[];
131
147
  readonly warning?: string;
148
+ readonly alwaysAllowCoverage?: string;
149
+ readonly alwaysAllowUnavailableReason?: string;
150
+ readonly risk?: {
151
+ readonly summary: string;
152
+ readonly detail: string;
153
+ };
132
154
  };
133
155
  }[];
134
156
  }, {
@@ -165,6 +187,7 @@ export declare function createMcpFormSession(): {
165
187
  readonly expiresAt: number;
166
188
  readonly updatedAt: number;
167
189
  readonly revision: number;
190
+ readonly denialNote?: string;
168
191
  readonly evidence?: readonly {
169
192
  readonly kind: "artifact";
170
193
  readonly ref: string;
@@ -176,11 +199,20 @@ export declare function createMcpFormSession(): {
176
199
  readonly canSetAutoApprove: boolean;
177
200
  };
178
201
  readonly review?: {
202
+ readonly kind: "exec" | "extension-install";
203
+ readonly form: "direct" | "shell";
179
204
  readonly command: string;
180
205
  readonly cwd: string;
181
206
  readonly justification: string;
207
+ readonly argv?: readonly string[];
182
208
  readonly prefix?: readonly string[];
183
209
  readonly warning?: string;
210
+ readonly alwaysAllowCoverage?: string;
211
+ readonly alwaysAllowUnavailableReason?: string;
212
+ readonly risk?: {
213
+ readonly summary: string;
214
+ readonly detail: string;
215
+ };
184
216
  };
185
217
  }[];
186
218
  }>;
@@ -49,15 +49,18 @@ export function createMcpFormSession() {
49
49
  if (input.decision === "always-allow" &&
50
50
  entry.alwaysAllow === undefined)
51
51
  return { kind: "refused", reason: "not-pending" };
52
+ if (input.denialNote !== undefined && input.decision !== "deny")
53
+ return { kind: "refused", reason: "not-pending" };
52
54
  if (input.decision === "always-allow")
53
55
  entry.alwaysAllow?.("prefix");
54
- const result = await entry.approvals.answer({
56
+ const answer = {
55
57
  recordId: entry.approval.record.recordId,
56
- decision: input.decision === "always-allow"
57
- ? "approve"
58
- : input.decision,
58
+ decision: input.decision === "deny" ? "deny" : "approve",
59
59
  expectedRevision: input.expectedRevision,
60
- });
60
+ };
61
+ const result = await entry.approvals.answer(input.denialNote === undefined
62
+ ? answer
63
+ : { ...answer, denialNote: input.denialNote });
61
64
  return result;
62
65
  }
63
66
  finally {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fungi.computer/truffle",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "private": false,
5
5
  "description": "Truffle: Fungi's local Agent runtime, bundled into the fungi command",
6
6
  "type": "module",
@@ -50,6 +50,10 @@
50
50
  "types": "./dist/local-extensions.d.ts",
51
51
  "import": "./dist/local-extensions.js"
52
52
  },
53
+ "./upgrade": {
54
+ "types": "./dist/local-upgrade.d.ts",
55
+ "import": "./dist/local-upgrade.js"
56
+ },
53
57
  "./rules": {
54
58
  "types": "./dist/private-local-exec-rules.d.ts",
55
59
  "import": "./dist/private-local-exec-rules.js"
@@ -65,26 +69,26 @@
65
69
  "@cf-wasm/photon": "0.4.0",
66
70
  "@earendil-works/pi-ai": "1.3.0",
67
71
  "@effect/platform-node": "4.0.2",
68
- "@fungi.computer/agar": "0.3.1",
69
- "@fungi.computer/approvals": "0.1.0",
70
- "@fungi.computer/bird-dog": "0.2.0",
72
+ "@fungi.computer/agar": "0.4.0",
73
+ "@fungi.computer/approvals": "0.2.0",
74
+ "@fungi.computer/bird-dog": "0.2.1",
71
75
  "@fungi.computer/cairn": "0.1.0",
72
76
  "@fungi.computer/capnweb": "0.12.0",
73
77
  "@fungi.computer/carrier": "0.2.0",
74
78
  "@fungi.computer/cordyceps": "0.4.0",
75
79
  "@fungi.computer/gills": "0.2.0",
76
- "@fungi.computer/graft": "0.1.2",
77
- "@fungi.computer/knapsack": "0.3.0",
80
+ "@fungi.computer/graft": "0.1.3",
81
+ "@fungi.computer/knapsack": "0.3.1",
78
82
  "@fungi.computer/lantern": "0.3.0",
79
83
  "@fungi.computer/mycelium": "0.2.2",
80
- "@fungi.computer/nacre": "0.0.2",
84
+ "@fungi.computer/nacre": "0.0.3",
81
85
  "@fungi.computer/seam": "0.2.0",
82
- "@fungi.computer/shiitake": "0.4.0",
83
- "@fungi.computer/shiitake-extensions": "0.2.0",
84
- "@fungi.computer/veil": "0.2.0",
86
+ "@fungi.computer/shiitake": "0.5.0",
87
+ "@fungi.computer/shiitake-extensions": "0.3.0",
88
+ "@fungi.computer/veil": "0.2.1",
85
89
  "@fungi.computer/watchdog": "0.1.0",
86
- "@fungi.computer/whistle": "0.1.0",
87
- "@fungi.computer/zookeeper": "0.0.3",
90
+ "@fungi.computer/whistle": "0.2.0",
91
+ "@fungi.computer/zookeeper": "0.0.4",
88
92
  "@jellybrick/dbus-next": "0.11.4",
89
93
  "@modelcontextprotocol/client": "2.0.0",
90
94
  "@napi-rs/keyring": "2.1.2",
@@ -97,6 +101,8 @@
97
101
  "miniflare": "5.20260828.0-alpha",
98
102
  "proper-lockfile": "4.1.2",
99
103
  "re2js": "1.3.3",
104
+ "semver": "7.8.5",
105
+ "shell-quote": "1.10.0",
100
106
  "write-file-atomic": "8.0.0",
101
107
  "yaml": "2.9.0",
102
108
  "zod": "4.4.3"
@@ -107,6 +113,7 @@
107
113
  "@modelcontextprotocol/server": "2.0.0",
108
114
  "@types/node": "24.13.3",
109
115
  "@types/proper-lockfile": "4.1.4",
116
+ "@types/semver": "7.8.0",
110
117
  "@types/write-file-atomic": "4.0.3",
111
118
  "bun": "1.4.2",
112
119
  "bun-types": "1.4.1",
@@ -154,7 +161,7 @@
154
161
  "test:node": "../../node_modules/.bin/vitest run",
155
162
  "test:bun": "pnpm run test:mesh-link && pnpm run test:bun:batch && bun test ./test/private-workerd-deadline.bun.test.ts",
156
163
  "test:mesh-link": "bun test ./test/private-local-mesh-links.bun.test.ts",
157
- "test:bun:batch": "bun test ./test/private-sqlite-approval-driver.bun.test.ts ./test/mcp-form-service.bun.test.ts ./test/private-local-service-discovery.bun.test.ts ./test/private-local-service-listener.bun.test.ts ./test/private-local-service-manager.bun.test.ts ./test/private-local-service-rebind.bun.test.ts ./test/private-local-service-stop.bun.test.ts ./test/private-local-service-ensure.bun.test.ts ./test/private-local-service-identity.bun.test.ts ./test/private-local-service-kill-resume.bun.test.ts ./test/private-local-service-idle-owners.bun.test.ts ./test/private-local-service-idle-delegation.bun.test.ts ./test/private-local-mail-retry.bun.test.ts ./test/private-local-service-log-native.bun.test.ts ./test/private-local-service-log.bun.test.ts ./test/private-local-sqlite-lifetime.bun.test.ts ./test/private-sqlite-driver.bun.test.ts ./test/private-local-reload.bun.test.ts ./test/private-local-auth-rpc.bun.test.ts ./test/private-workerd-forage.bun.test.ts ./test/local-extensions.bun.test.ts ./test/local-zookeeper-slot.bun.test.ts ./test/local-extension-skills.bun.test.ts ./test/private-local-sandbox-service.bun.test.ts ./test/private-local-native-service.bun.test.ts",
164
+ "test:bun:batch": "bun test ./test/private-sqlite-approval-driver.bun.test.ts ./test/mcp-form-service.bun.test.ts ./test/private-local-service-discovery.bun.test.ts ./test/private-local-service-listener.bun.test.ts ./test/private-local-service-manager.bun.test.ts ./test/private-local-service-rebind.bun.test.ts ./test/private-local-service-stop.bun.test.ts ./test/private-local-service-ensure.bun.test.ts ./test/private-local-service-identity.bun.test.ts ./test/private-local-service-kill-resume.bun.test.ts ./test/private-local-service-idle-owners.bun.test.ts ./test/private-local-service-idle-delegation.bun.test.ts ./test/private-local-mail-retry.bun.test.ts ./test/private-local-service-log-native.bun.test.ts ./test/private-local-service-log.bun.test.ts ./test/private-local-sqlite-lifetime.bun.test.ts ./test/private-sqlite-driver.bun.test.ts ./test/private-local-reload.bun.test.ts ./test/private-local-auth-rpc.bun.test.ts ./test/private-workerd-forage.bun.test.ts ./test/local-extensions.bun.test.ts ./test/local-extension-archive.bun.test.ts ./test/local-zookeeper-slot.bun.test.ts ./test/local-extension-skills.bun.test.ts ./test/private-local-sandbox-service.bun.test.ts ./test/private-local-native-service.bun.test.ts",
158
165
  "build:native": "fungi-apply-patch-build --out native/bin && node scripts/build-bwrap.mjs --out native/bin && node scripts/generate-native-digests.mjs",
159
166
  "test:patch": "node --test --test-timeout=30000 test/apply-patch.native.mjs",
160
167
  "test:sandbox:linux": "node --import tsx test/fixtures/local-sandbox-proof.mts",