toolroll 0.9.65 → 0.9.68

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 (264) hide show
  1. package/CHANGELOG.md +93 -0
  2. package/README.md +20 -2
  3. package/dist/acp-client.js +1 -3
  4. package/dist/agent-board.d.ts +0 -1
  5. package/dist/agent-board.js +0 -1
  6. package/dist/agent-fence.d.ts +69 -2
  7. package/dist/agent-fence.js +294 -11
  8. package/dist/agentconfig.js +4 -1
  9. package/dist/batch-checks.js +3 -2
  10. package/dist/browser/THIRD_PARTY_NOTICES.txt +46 -0
  11. package/dist/browser/terminal.js +134 -23
  12. package/dist/browser/workspace.css +2 -2
  13. package/dist/browser/workspace.js +31 -29
  14. package/dist/builder.d.ts +4 -0
  15. package/dist/builder.js +56 -37
  16. package/dist/canonical-json.d.ts +14 -0
  17. package/dist/canonical-json.js +36 -0
  18. package/dist/chat-actions.js +1 -2
  19. package/dist/chat-admission.d.ts +19 -0
  20. package/dist/chat-admission.js +22 -0
  21. package/dist/chat-channel.js +1 -1
  22. package/dist/chat-delivery.js +0 -1
  23. package/dist/chat-follow.d.ts +17 -0
  24. package/dist/chat-follow.js +32 -0
  25. package/dist/chat-messages.js +0 -1
  26. package/dist/chat-settings-page.d.ts +23 -0
  27. package/dist/chat-settings-page.js +41 -0
  28. package/dist/claim.js +3 -6
  29. package/dist/claude-print.d.ts +12 -0
  30. package/dist/claude-print.js +34 -0
  31. package/dist/cli-http.d.ts +0 -7
  32. package/dist/cli-http.js +0 -21
  33. package/dist/cli.d.ts +3 -10
  34. package/dist/cli.js +15 -24
  35. package/dist/coding-provider.js +2 -1
  36. package/dist/coding-workspace.js +1 -1
  37. package/dist/{team-cli.d.ts → connect-cli.d.ts} +5 -9
  38. package/dist/connect-cli.js +331 -0
  39. package/dist/containment.d.ts +0 -2
  40. package/dist/containment.js +2 -6
  41. package/dist/contracts/chat-actions.d.ts +0 -1
  42. package/dist/contracts/chat-content.d.ts +0 -4
  43. package/dist/contracts/chat-content.js +0 -2
  44. package/dist/contracts/chat-tables.d.ts +0 -1
  45. package/dist/contracts/cli.d.ts +0 -62
  46. package/dist/contracts/cli.js +0 -4
  47. package/dist/contracts/coding-workspace.js +1 -1
  48. package/dist/contracts/console-api.d.ts +1 -0
  49. package/dist/contracts/console-api.js +1 -0
  50. package/dist/contracts/contract.js +1 -1
  51. package/dist/contracts/flow-card.d.ts +0 -1
  52. package/dist/contracts/flow-propose.d.ts +0 -1
  53. package/dist/contracts/flow-send.js +1 -1
  54. package/dist/contracts/gateway-tools.d.ts +0 -1
  55. package/dist/contracts/integration-metadata.js +1 -1
  56. package/dist/contracts/lead-tools.d.ts +0 -1
  57. package/dist/contracts/memory-pass.d.ts +0 -1
  58. package/dist/contracts/memory-pass.js +1 -1
  59. package/dist/contracts/plan.js +1 -1
  60. package/dist/contracts/project-knowledge.js +1 -1
  61. package/dist/contracts/project-skills.d.ts +0 -1
  62. package/dist/contracts/proof.js +1 -1
  63. package/dist/contracts/recipes.js +1 -1
  64. package/dist/contracts/scope.js +1 -1
  65. package/dist/contracts/scout-report.js +1 -1
  66. package/dist/contracts/teams-callback.d.ts +0 -1
  67. package/dist/converse.d.ts +0 -6
  68. package/dist/converse.js +0 -19
  69. package/dist/daemon.js +3 -2
  70. package/dist/decision.d.ts +1 -3
  71. package/dist/deprecations.d.ts +12 -4
  72. package/dist/deprecations.js +27 -4
  73. package/dist/desktop-update-recovery.js +1 -1
  74. package/dist/desktop-update.js +3 -2
  75. package/dist/discord-chat.js +4 -15
  76. package/dist/discord-settings.d.ts +2 -6
  77. package/dist/discord-settings.js +10 -38
  78. package/dist/discord.js +12 -23
  79. package/dist/evidence.d.ts +0 -1
  80. package/dist/evidence.js +0 -3
  81. package/dist/exec.d.ts +0 -9
  82. package/dist/exec.js +3 -81
  83. package/dist/flow-actions.js +0 -3
  84. package/dist/flow-draft.d.ts +1 -3
  85. package/dist/flow-draft.js +15 -28
  86. package/dist/flow-scripts.d.ts +1 -8
  87. package/dist/flow-scripts.js +0 -13
  88. package/dist/flow-send.js +1 -1
  89. package/dist/flow-share.d.ts +0 -2
  90. package/dist/flow-share.js +1 -6
  91. package/dist/flow-steps.js +1 -1
  92. package/dist/flow-triggers.d.ts +0 -1
  93. package/dist/flow-triggers.js +1 -2
  94. package/dist/flow-unattended.js +1 -12
  95. package/dist/flows.js +1 -1
  96. package/dist/health-cli.d.ts +2 -2
  97. package/dist/health-cli.js +1 -1
  98. package/dist/invoke.d.ts +18 -3
  99. package/dist/invoke.js +142 -17
  100. package/dist/is-record.d.ts +2 -0
  101. package/dist/is-record.js +2 -0
  102. package/dist/lead-doors.d.ts +1 -5
  103. package/dist/lead-doors.js +0 -4
  104. package/dist/lead-tools.js +3 -6
  105. package/dist/live-detail.d.ts +0 -1
  106. package/dist/live-detail.js +0 -6
  107. package/dist/live-terminal.d.ts +24 -13
  108. package/dist/live-terminal.js +81 -43
  109. package/dist/live.d.ts +0 -1
  110. package/dist/live.js +1 -2
  111. package/dist/mcp-core.js +0 -2
  112. package/dist/memory-pass.js +1 -1
  113. package/dist/model-catalog.js +1 -1
  114. package/dist/modes.js +1 -12
  115. package/dist/operate.d.ts +2 -0
  116. package/dist/operate.js +436 -745
  117. package/dist/password-bearer.d.ts +0 -2
  118. package/dist/password-bearer.js +0 -4
  119. package/dist/peek-cli.js +2 -1
  120. package/dist/peek.d.ts +2 -26
  121. package/dist/peek.js +2 -168
  122. package/dist/phase-routing.d.ts +0 -4
  123. package/dist/phase-routing.js +2 -21
  124. package/dist/planner-source.d.ts +2 -1
  125. package/dist/planner-source.js +2 -12
  126. package/dist/planner.js +2 -14
  127. package/dist/process-tree.d.ts +0 -2
  128. package/dist/process-tree.js +0 -10
  129. package/dist/project-delete-ui.d.ts +6 -0
  130. package/dist/project-delete-ui.js +20 -1
  131. package/dist/project-delete.d.ts +0 -2
  132. package/dist/project-delete.js +1 -3
  133. package/dist/project-learning.d.ts +0 -14
  134. package/dist/project-skills.d.ts +0 -1
  135. package/dist/project-skills.js +0 -14
  136. package/dist/project-tools.js +2 -10
  137. package/dist/provider.d.ts +0 -17
  138. package/dist/provider.js +0 -26
  139. package/dist/pulls.d.ts +0 -2
  140. package/dist/pulls.js +0 -9
  141. package/dist/release-adapters.d.ts +9 -0
  142. package/dist/release-adapters.js +81 -4
  143. package/dist/release.d.ts +7 -1
  144. package/dist/release.js +20 -7
  145. package/dist/remote-exec.d.ts +3 -2
  146. package/dist/remote-exec.js +3 -2
  147. package/dist/repos.d.ts +0 -5
  148. package/dist/repos.js +2 -10
  149. package/dist/repository-context.d.ts +0 -2
  150. package/dist/repository-context.js +0 -4
  151. package/dist/restart-certification.d.ts +0 -2
  152. package/dist/restart-certification.js +1 -5
  153. package/dist/result-follow-ups.d.ts +1 -4
  154. package/dist/result-follow-ups.js +4 -8
  155. package/dist/result-review.d.ts +0 -2
  156. package/dist/result-review.js +0 -2
  157. package/dist/retention.d.ts +0 -1
  158. package/dist/retention.js +0 -1
  159. package/dist/review-context.d.ts +0 -1
  160. package/dist/review-context.js +1 -12
  161. package/dist/reviewer.d.ts +0 -16
  162. package/dist/reviewer.js +0 -18
  163. package/dist/run-closeout.js +2 -1
  164. package/dist/scope.d.ts +13 -0
  165. package/dist/scope.js +11 -18
  166. package/dist/scout-browser.js +2 -1
  167. package/dist/serve.js +3 -2
  168. package/dist/server/chrome.d.ts +10 -1
  169. package/dist/server/chrome.js +45 -4
  170. package/dist/server/console.css +60 -137
  171. package/dist/server/flows.js +2 -2
  172. package/dist/server/http.d.ts +2 -0
  173. package/dist/server/http.js +5 -0
  174. package/dist/server/pages.js +2 -2
  175. package/dist/server/people-tokens.js +3 -4
  176. package/dist/server/remote.js +1 -6
  177. package/dist/server/render-chat.d.ts +9 -2
  178. package/dist/server/render-chat.js +53 -7
  179. package/dist/server/render-pages.d.ts +28 -3
  180. package/dist/server/render-pages.js +78 -9
  181. package/dist/server/render-results.d.ts +0 -6
  182. package/dist/server/render-results.js +3 -9
  183. package/dist/server/render-tasks.js +6 -6
  184. package/dist/server/route-table.d.ts +0 -4
  185. package/dist/server/route-table.js +1 -6
  186. package/dist/server/settings.js +43 -22
  187. package/dist/server/task-views.js +1 -1
  188. package/dist/server/tasks.js +10 -7
  189. package/dist/setup-guide.d.ts +2 -2
  190. package/dist/skills.d.ts +0 -6
  191. package/dist/skills.js +0 -8
  192. package/dist/slack-chat.d.ts +1 -7
  193. package/dist/slack-chat.js +5 -18
  194. package/dist/slack-settings.d.ts +2 -6
  195. package/dist/slack-settings.js +10 -38
  196. package/dist/slack.js +12 -23
  197. package/dist/sleep.d.ts +2 -0
  198. package/dist/sleep.js +2 -0
  199. package/dist/store.d.ts +11 -74
  200. package/dist/store.js +36 -179
  201. package/dist/structured-output.d.ts +0 -1
  202. package/dist/structured-output.js +0 -1
  203. package/dist/subagent-work.d.ts +0 -2
  204. package/dist/subagent-work.js +0 -2
  205. package/dist/subagents.d.ts +1 -3
  206. package/dist/subagents.js +20 -33
  207. package/dist/subscription-chat.d.ts +1 -3
  208. package/dist/subscription-chat.js +2 -3
  209. package/dist/task-sizing.d.ts +1 -4
  210. package/dist/task-sizing.js +3 -10
  211. package/dist/teams-chat.js +4 -11
  212. package/dist/teams.js +12 -19
  213. package/dist/teardown-git.d.ts +22 -0
  214. package/dist/teardown-git.js +136 -2
  215. package/dist/telegram-lead.js +2 -2
  216. package/dist/telegram.js +1 -1
  217. package/dist/token-notices.d.ts +0 -11
  218. package/dist/token-notices.js +1 -5
  219. package/dist/tool-broker.d.ts +12 -0
  220. package/dist/tool-broker.js +66 -2
  221. package/dist/tool-secret-store.d.ts +0 -3
  222. package/dist/tool-secret-store.js +2 -11
  223. package/dist/toolroll-update.d.ts +0 -2
  224. package/dist/toolroll-update.js +2 -2
  225. package/dist/unfenced-test-support.d.ts +2 -0
  226. package/dist/unfenced-test-support.js +11 -0
  227. package/dist/verification-evidence.d.ts +0 -1
  228. package/dist/verification-evidence.js +0 -1
  229. package/dist/webhooks.d.ts +0 -1
  230. package/dist/webhooks.js +0 -1
  231. package/dist/workspace-ui.d.ts +0 -8
  232. package/dist/workspace-ui.js +1 -6
  233. package/dist/writes-mode.d.ts +9 -0
  234. package/dist/writes-mode.js +8 -0
  235. package/package.json +5 -1
  236. package/dist/contracts/native-census.d.ts +0 -42
  237. package/dist/contracts/native-census.js +0 -36
  238. package/dist/process-recovery-anchor.d.ts +0 -75
  239. package/dist/process-recovery-anchor.js +0 -188
  240. package/dist/process-recovery-coalition.d.ts +0 -25
  241. package/dist/process-recovery-coalition.js +0 -105
  242. package/dist/process-recovery-eligibility.d.ts +0 -179
  243. package/dist/process-recovery-eligibility.js +0 -174
  244. package/dist/process-recovery-native.d.ts +0 -161
  245. package/dist/process-recovery-native.js +0 -595
  246. package/dist/process-recovery-provenance.d.ts +0 -163
  247. package/dist/process-recovery-provenance.js +0 -292
  248. package/dist/process-recovery-services.d.ts +0 -56
  249. package/dist/process-recovery-services.js +0 -191
  250. package/dist/process-recovery-settlement.d.ts +0 -32
  251. package/dist/process-recovery-settlement.js +0 -133
  252. package/dist/process-recovery.d.ts +0 -41
  253. package/dist/process-recovery.js +0 -91
  254. package/dist/session-brief.d.ts +0 -8
  255. package/dist/session-brief.js +0 -24
  256. package/dist/session-cli.d.ts +0 -42
  257. package/dist/session-cli.js +0 -271
  258. package/dist/session-contract.d.ts +0 -183
  259. package/dist/session-contract.js +0 -122
  260. package/dist/session-remote.d.ts +0 -19
  261. package/dist/session-remote.js +0 -86
  262. package/dist/session-service.d.ts +0 -22
  263. package/dist/session-service.js +0 -157
  264. package/dist/team-cli.js +0 -692
@@ -54,37 +54,6 @@ export declare const commandRowSchema: z.ZodReadonly<z.ZodObject<{
54
54
  meaning: z.ZodString;
55
55
  }, z.core.$loose>>>>>;
56
56
  notableReasons: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
57
- inputSchema: z.ZodOptional<z.ZodCustom<{
58
- type: 'object';
59
- additionalProperties: false;
60
- required: readonly string[];
61
- properties: Record<string, {
62
- type: 'string' | 'integer' | readonly ['string', 'null'];
63
- minLength?: number;
64
- maxLength?: number;
65
- pattern?: string;
66
- minimum?: number;
67
- maximum?: number;
68
- maxBytes?: number;
69
- nonblank?: boolean;
70
- const?: number;
71
- }>;
72
- }, {
73
- type: 'object';
74
- additionalProperties: false;
75
- required: readonly string[];
76
- properties: Record<string, {
77
- type: 'string' | 'integer' | readonly ['string', 'null'];
78
- minLength?: number;
79
- maxLength?: number;
80
- pattern?: string;
81
- minimum?: number;
82
- maximum?: number;
83
- maxBytes?: number;
84
- nonblank?: boolean;
85
- const?: number;
86
- }>;
87
- }>>;
88
57
  remote: z.ZodEnum<{
89
58
  no: "no";
90
59
  "step-up": "step-up";
@@ -134,37 +103,6 @@ export declare const COMMAND_OUTPUTS: {
134
103
  meaning: z.ZodString;
135
104
  }, z.core.$loose>>>>>;
136
105
  notableReasons: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
137
- inputSchema: z.ZodOptional<z.ZodCustom<{
138
- type: 'object';
139
- additionalProperties: false;
140
- required: readonly string[];
141
- properties: Record<string, {
142
- type: 'string' | 'integer' | readonly ['string', 'null'];
143
- minLength?: number;
144
- maxLength?: number;
145
- pattern?: string;
146
- minimum?: number;
147
- maximum?: number;
148
- maxBytes?: number;
149
- nonblank?: boolean;
150
- const?: number;
151
- }>;
152
- }, {
153
- type: 'object';
154
- additionalProperties: false;
155
- required: readonly string[];
156
- properties: Record<string, {
157
- type: 'string' | 'integer' | readonly ['string', 'null'];
158
- minLength?: number;
159
- maxLength?: number;
160
- pattern?: string;
161
- minimum?: number;
162
- maximum?: number;
163
- maxBytes?: number;
164
- nonblank?: boolean;
165
- const?: number;
166
- }>;
167
- }>>;
168
106
  remote: z.ZodEnum<{
169
107
  no: "no";
170
108
  "step-up": "step-up";
@@ -38,8 +38,6 @@ function answers(command, shape) {
38
38
  export const commandFlagSchema = z.looseObject({ name: str, takesValue: z.boolean(), meaning: str }).readonly();
39
39
  /** The remote policy every command row states; see `remote` below. */
40
40
  export const REMOTE_POLICIES = ["yes", "no", "step-up"];
41
- /** A session operation's executable input schema, as session-contract.ts states it. */
42
- const sessionInputSchema = z.custom(value => typeof value === "object" && value !== null && !Array.isArray(value));
43
41
  export const commandRowSchema = z.looseObject({
44
42
  /** What you type after `toolroll` (subcommands included). */
45
43
  invocation: str,
@@ -62,8 +60,6 @@ export const commandRowSchema = z.looseObject({
62
60
  positionals: z.array(z.looseObject({ name: str, required: z.boolean(), meaning: str }).readonly()).readonly().optional(),
63
61
  flags: z.array(commandFlagSchema).readonly().optional(),
64
62
  notableReasons: z.array(str).readonly().optional(),
65
- /** Session schemas are executable input contracts, not a grant of authority. */
66
- inputSchema: sessionInputSchema.optional(),
67
63
  /** Whether a person signed in to a central server with their own API token may run it there (`runOperateAs`):
68
64
  * yes — runs as that person, within their token's scope and project access.
69
65
  * no — this machine's own infrastructure, credentials or files; never run for a remote caller.
@@ -6,6 +6,7 @@
6
6
  import { z } from "zod";
7
7
  import { readVersioned, versioned } from "./contract.js";
8
8
  import { CODING_CONTEXT_VERSION, codingContextSchema } from "./coding-context.js";
9
+ import { isRecord } from "../is-record.js";
9
10
  export const CODING_STATUSES = ["starting", "ready", "working", "needs-input", "stopping", "interrupted", "failed", "uncertain", "closed"];
10
11
  export const codingSessionSchema = z.strictObject({
11
12
  id: z.string(),
@@ -33,7 +34,6 @@ export const codingSessionSchema = z.strictObject({
33
34
  });
34
35
  export const CODING_SESSION_VERSION = 1;
35
36
  export const codingSessionRecordSchema = versioned(CODING_SESSION_VERSION, codingSessionSchema.shape);
36
- const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
37
37
  /**
38
38
  * Unversioned records were read as a cast, including partial fields, nulls and unknown nested keys. Preserve that
39
39
  * boundary exactly; only records explicitly written as version 1 are subject to its strict schema.
@@ -83,6 +83,7 @@ export declare const CONSOLE_FORMS: {
83
83
  readonly projectConcurrency: FormContract<"concurrency" | "repo">;
84
84
  readonly projectLiveView: FormContract<"act" | "nonce" | "password" | "repo">;
85
85
  readonly projectNetwork: FormContract<"hosts" | "local" | "mode" | "password" | "repo">;
86
+ readonly projectWrites: FormContract<"password" | "repo" | "writes">;
86
87
  readonly projectDelete: FormContract<"name" | "password" | "repo" | "step">;
87
88
  readonly policy: FormContract<"ceiling" | "models" | "password" | "provider" | "tools">;
88
89
  readonly approval: FormContract<"not_requester" | "password" | "paths" | "protect" | "repo">;
@@ -92,6 +92,7 @@ export const CONSOLE_FORMS = {
92
92
  projectConcurrency: formContract("POST /settings/project/concurrency", ["repo", "concurrency"]),
93
93
  projectLiveView: formContract("POST /settings/project/live-view", ["repo", "act", "password", "nonce"]),
94
94
  projectNetwork: formContract("POST /settings/project/network", ["repo", "mode", "local", "hosts", "password"]),
95
+ projectWrites: formContract("POST /settings/project/writes", ["repo", "writes", "password"]),
95
96
  projectDelete: formContract("POST /settings/project/delete", ["repo", "name", "step", "password"]),
96
97
  policy: formContract("POST /settings/policy", ["password", "provider", "models", "tools", "ceiling"]),
97
98
  approval: formContract("POST /settings/approval", ["repo", "password", "protect", "paths", "not_requester"]),
@@ -8,6 +8,7 @@
8
8
  */
9
9
  import { z } from "zod";
10
10
  import { limitRule, TEXT_LIMITS } from "../text-limits.js";
11
+ import { isRecord } from "../is-record.js";
11
12
  /**
12
13
  * A string bounded by its TEXT_LIMITS entry, never a literal. The limit rule rides along as the field's description,
13
14
  * so a model reads the bound before it writes. Zod counts UTF-16 code units; for a limit named in bytes this is the
@@ -42,7 +43,6 @@ function got(input) {
42
43
  return "an array";
43
44
  return typeof input === "object" ? "an object" : `a ${typeof input}`;
44
45
  }
45
- const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
46
46
  /** The schema at `path`, including whether that value may be omitted, following arrays, wrappers and unions. */
47
47
  function nodeAt(schema, input, path) {
48
48
  let node = schema, value = input;
@@ -9,7 +9,6 @@
9
9
  */
10
10
  import { z } from "zod";
11
11
  export declare const FLOW_CARD_STATES: readonly ["active", "done", "cancelled"];
12
- export type FlowCardState = (typeof FLOW_CARD_STATES)[number];
13
12
  export declare const flowCardSchema: z.ZodObject<{
14
13
  id: z.ZodInt;
15
14
  flow: z.ZodInt;
@@ -320,6 +320,5 @@ export declare const proposeFlowInputSchema: z.ZodObject<{
320
320
  timeZone: z.ZodOptional<z.ZodString>;
321
321
  }, z.core.$strict>], "kind">>;
322
322
  }, z.core.$strict>;
323
- export type ProposeFlowInput = z.infer<typeof proposeFlowInputSchema>;
324
323
  /** What the lead is told propose_flow takes: exactly the schema its call is read with. */
325
324
  export declare const PROPOSE_FLOW_MODEL_SCHEMA: Readonly<Record<string, unknown>>;
@@ -12,6 +12,7 @@
12
12
  */
13
13
  import { z } from "zod";
14
14
  import { parseContract, readVersioned, versioned } from "./contract.js";
15
+ import { isRecord } from "../is-record.js";
15
16
  /** A link the message carries: a page of Toolroll's (a button) or the one outside page, a pull request. */
16
17
  export const flowSendLinkSchema = z.union([
17
18
  z.strictObject({ label: z.string(), path: z.string().regex(/^\//, { error: "must be a path in Toolroll, starting with /" }) }),
@@ -51,7 +52,6 @@ export const flowChoosePayloadSchema = versioned(FLOW_SEND_VERSION, {
51
52
  /** Whether a reply is taken instead (the zone has somewhere replies go). */
52
53
  reply: z.boolean(),
53
54
  });
54
- const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
55
55
  /** A kept item as 0.9.36 read it: its five words (a web link), and a screenshot id only when it is a whole number. */
56
56
  const savedItemSchema = z.object({ ...flowSendItemSchema.shape, shot: z.unknown() });
57
57
  export function readFlowItems(raw) {
@@ -371,7 +371,6 @@ export declare const GATEWAY_TOOL_OUTPUTS: {
371
371
  admission: z.ZodString;
372
372
  }, z.core.$loose>;
373
373
  };
374
- export type GatewayToolOutput<N extends GatewayToolName> = z.infer<(typeof GATEWAY_TOOL_OUTPUTS)[N]>;
375
374
  export declare const PERSON_TOOL_INPUTS: {
376
375
  readonly status: z.ZodObject<{}, z.core.$strict>;
377
376
  readonly list_tasks: z.ZodObject<{
@@ -14,9 +14,9 @@
14
14
  */
15
15
  import { z } from "zod";
16
16
  import { parseContract } from "./contract.js";
17
+ import { isRecord } from "../is-record.js";
17
18
  /** RFC 6749 scope tokens. */
18
19
  export const SCOPE_TOKEN = /^[\x21\x23-\x5b\x5d-\x7e]{1,128}$/;
19
- const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
20
20
  /** A field's schema without its optional wrapper. */
21
21
  const inner = (field) => (field instanceof z.ZodOptional ? field.unwrap() : field);
22
22
  /**
@@ -2003,7 +2003,6 @@ export declare const LEAD_TOOL_OUTPUTS: {
2003
2003
  awaiting: z.ZodString;
2004
2004
  }, z.core.$loose>;
2005
2005
  };
2006
- export type LeadToolOutput<N extends LeadToolName> = z.infer<(typeof LEAD_TOOL_OUTPUTS)[N]>;
2007
2006
  /**
2008
2007
  * Report a result that disagrees with its output schema without hiding the actual result, including under Vitest.
2009
2008
  * Contract tests assert output shapes directly; executing a tool always writes the diagnostic and returns its result.
@@ -131,7 +131,6 @@ export declare const memoryEvidenceSchema: z.ZodArray<z.ZodObject<{
131
131
  session: z.ZodString;
132
132
  quote: z.ZodString;
133
133
  }, z.core.$strict>>;
134
- export type MemoryEvidence = z.infer<typeof memoryEvidenceSchema>;
135
134
  /** A proposal as its row reads; its evidence is a JSON list (an older runtime reads it as one, so it has no envelope). */
136
135
  export declare const memoryProposalSchema: z.ZodObject<{
137
136
  id: z.ZodInt;
@@ -7,6 +7,7 @@
7
7
  import { z } from "zod";
8
8
  import { TEXT_LIMITS } from "../text-limits.js";
9
9
  import { limited, readVersioned, toModelSchema, versioned } from "./contract.js";
10
+ import { isRecord } from "../is-record.js";
10
11
  export const MEMORY_EFFECTS = ["harm", "non-compliance", "irrelevant"];
11
12
  export const MEMORY_DOMAINS = ["project", "orchestration"];
12
13
  export const MEMORY_PROPOSAL_KINDS = ["instruction-add", "instruction-remove", "decision-add"];
@@ -64,7 +65,6 @@ export const memoryVerdictReadSchema = memoryVerdictSchema.strip().extend({
64
65
  export const MEMORY_VERDICT_VERSION = 1;
65
66
  /** A verdict as a session keeps it. */
66
67
  export const savedVerdictSchema = versioned(MEMORY_VERDICT_VERSION, verdictShape(saved));
67
- const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
68
68
  /**
69
69
  * A verdict kept before it carried `version` (through 0.9.36), as version 1. Those left a gap's `matchesGap` out when
70
70
  * there was none; that reads as null. Values are never rewritten.
@@ -7,6 +7,7 @@
7
7
  import { z } from "zod";
8
8
  import { ACCEPTANCE_LIMITS, EVIDENCE_KINDS } from "../scope.js";
9
9
  import { limited, readVersioned, toModelSchema, versioned } from "./contract.js";
10
+ import { isRecord } from "../is-record.js";
10
11
  /** How many paths a plan may say it touches. */
11
12
  export const PLAN_TOUCHES = 32;
12
13
  /** One acceptance criterion: the scope's own shape (scope.ts `AcceptanceCriterion`), `how` advisory and unsigned. */
@@ -37,7 +38,6 @@ function pick(body, fields) {
37
38
  }
38
39
  return out;
39
40
  }
40
- const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
41
41
  /**
42
42
  * A plan written before plans carried `version` (every plan through 0.9.33), as version 1. The old parser read only
43
43
  * the fields it knew and ignored any others, read a null goal, plan or acceptance as missing and null touches as
@@ -8,6 +8,7 @@
8
8
  import { z } from "zod";
9
9
  import { limited, readVersioned, versioned } from "./contract.js";
10
10
  import { decisionLineSchema } from "./project-memory.js";
11
+ import { isRecord } from "../is-record.js";
11
12
  /** How many references a project keeps, and how many a run is given. Text limits live in TEXT_LIMITS. */
12
13
  export const KNOWLEDGE_COUNTS = { references: 12, selected: 3, decisions: 8 };
13
14
  const written = limited;
@@ -30,7 +31,6 @@ export const KNOWLEDGE_VERSION = 1;
30
31
  export const knowledgeSchema = versioned(KNOWLEDGE_VERSION, knowledgeShape(written));
31
32
  /** Knowledge as it is read back. */
32
33
  export const savedKnowledgeSchema = versioned(KNOWLEDGE_VERSION, knowledgeShape(saved));
33
- const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
34
34
  function pick(body, fields) {
35
35
  const out = {};
36
36
  for (const field of fields)
@@ -83,7 +83,6 @@ export declare const skillSelectionSchema: z.ZodRecord<z.ZodString, z.ZodObject<
83
83
  sha: z.ZodString;
84
84
  enabled: z.ZodBoolean;
85
85
  }, z.core.$strict>>;
86
- export type SkillChoice = z.infer<typeof skillChoiceSchema>;
87
86
  export type SkillSelection = z.infer<typeof skillSelectionSchema>;
88
87
  export declare const SKILLS_SNAPSHOT_VERSION = 1;
89
88
  /** The versions a run is pinned to, as frozen: the packages by digest. */
@@ -8,6 +8,7 @@ import { z } from "zod";
8
8
  import { TEXT_LIMITS } from "../text-limits.js";
9
9
  import { EVIDENCE_KINDS } from "../scope.js";
10
10
  import { limited, readVersioned, versioned } from "./contract.js";
11
+ import { isRecord } from "../is-record.js";
11
12
  /** How many entries each proof list may hold. Text limits live in TEXT_LIMITS. */
12
13
  export const PROOF_COUNTS = { criteria: 12, evidencePerCriterion: 4, checks: 12, changed: 64, caveats: 8, screenshots: 8 };
13
14
  /** Every proof limit by its long-standing name: the counts above and the byte limits from TEXT_LIMITS. */
@@ -62,7 +63,6 @@ export const proofSchema = versioned(PROOF_VERSION, {
62
63
  caveats: z.array(line("caveat")).max(PROOF_COUNTS.caveats),
63
64
  screenshots: z.array(proofScreenshotSchema).max(PROOF_COUNTS.screenshots),
64
65
  });
65
- const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
66
66
  /** The listed fields of `body`, a null or missing one left out (the old parser read null text as missing). */
67
67
  function pick(body, fields) {
68
68
  const out = {};
@@ -13,6 +13,7 @@
13
13
  import { z } from "zod";
14
14
  import { parseContract, versioned } from "./contract.js";
15
15
  import { savedCriterionSchema } from "./scope.js";
16
+ import { isRecord } from "../is-record.js";
16
17
  export const RECIPE_FORMAT = "standing-orders-recipe";
17
18
  /** Numbers the recipe rules use, in plain code after parsing (bytes of the whole document, characters of a field). */
18
19
  export const RECIPE_LIMITS = { documentBytes: 32_768, description: 400, inputs: 8, label: 80, answer: 500 };
@@ -38,7 +39,6 @@ const recipeFields = {
38
39
  export const recipeV1Schema = versioned(1, recipeFields);
39
40
  export const recipeV2Schema = versioned(2, { ...recipeFields, inputs: z.array(recipeInputSchema).min(1).max(RECIPE_LIMITS.inputs) });
40
41
  export const recipeDocumentSchema = z.discriminatedUnion("version", [recipeV1Schema, recipeV2Schema]);
41
- const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
42
42
  /** A success check as the scope reader reads it: an absent or empty `how` is null; every other key, known or not, as given. */
43
43
  function checkBody(entry) {
44
44
  if (!isRecord(entry) || (entry["how"] !== undefined && entry["how"] !== ""))
@@ -18,6 +18,7 @@ import { TEXT_LIMITS } from "../text-limits.js";
18
18
  import { ACCEPTANCE_LIMITS } from "./acceptance-terms.js";
19
19
  import { contractProblemOf, parseContract } from "./contract.js";
20
20
  import { acceptanceCriterionSchema as planCriterionSchema, planSchema } from "./plan.js";
21
+ import { isRecord } from "../is-record.js";
21
22
  /** A criterion as saved and as every reader returns it: the plan's criterion with `how` always present (null for none). */
22
23
  export const savedCriterionSchema = z.lazy(() => planCriterionSchema.extend({ how: planCriterionSchema.shape.how.unwrap() }));
23
24
  /** A rubric as saved: at most twelve criteria (an empty one is a scope filed before rubrics, or by a road with none). */
@@ -33,7 +34,6 @@ export const scopeTermsSchema = z.lazy(() => z.strictObject({
33
34
  touches: z.array(planSchema.shape.touches.unwrap().element).max(TEXT_LIMITS.scopeTouches).optional(),
34
35
  acceptance: rubricSchema.optional(),
35
36
  }));
36
- const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
37
37
  /** A criterion as the reader takes it: only the fields it knows, a null or empty `how` as null. Anything else as is. */
38
38
  function criterionBody(entry) {
39
39
  if (!isRecord(entry))
@@ -8,6 +8,7 @@
8
8
  import { z } from "zod";
9
9
  import { limitRule, TEXT_LIMITS } from "../text-limits.js";
10
10
  import { limited, readVersioned, toModelSchema, versioned } from "./contract.js";
11
+ import { isRecord } from "../is-record.js";
11
12
  /** How many follow-ups, items and screenshots a report may carry. */
12
13
  export const REPORT_COUNTS = { followUps: 5, items: 6, images: 8 };
13
14
  /** Caps are BYTES of UTF-8 (v4 review, finding 11): a 64 KiB report is 64 KiB whatever script it is written in. They
@@ -96,7 +97,6 @@ export const scoutHandbackSchema = z.strictObject({
96
97
  decision: scoutDecisionSchema.optional(),
97
98
  });
98
99
  export const SCOUT_OUTPUT_JSON_SCHEMA = toModelSchema(scoutHandbackSchema);
99
- const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
100
100
  function pick(body, fields) {
101
101
  const out = {};
102
102
  for (const field of fields) {
@@ -9,6 +9,5 @@ import { type ContractResult } from "./contract.js";
9
9
  export declare const teamsSubmitSchema: z.ZodObject<{
10
10
  so: z.ZodString;
11
11
  }, z.core.$strip>;
12
- export type TeamsSubmit = z.infer<typeof teamsSubmitSchema>;
13
12
  /** A submit's one-time token. */
14
13
  export declare function readTeamsSubmit(value: unknown): ContractResult<string>;
@@ -66,10 +66,6 @@ export declare function priceForConfig(config: {
66
66
  }): ModelPrice | null;
67
67
  export declare function worstCaseForPrice(price: ModelPrice, promptBytes: number): number;
68
68
  export declare function settleForPrice(price: ModelPrice, tokensIn: number, tokensOut: number): number;
69
- /** The worst a turn can cost, in integer micro-dollars: every prompt byte
70
- * as a token-third (generous) plus the full output allowance. */
71
- export declare function worstCaseMicrousd(model: string, promptBytes: number): number | null;
72
- export declare function settleMicrousd(model: string, tokensIn: number, tokensOut: number): number | null;
73
69
  export declare const DIRECT_CHAT_PROVIDERS: readonly DirectChatProviderId[];
74
70
  export declare const SUBSCRIPTION_CHAT_PROVIDERS: readonly SubscriptionChatProviderId[];
75
71
  export declare function isDirectChatProvider(provider: ChatProviderId): provider is DirectChatProviderId;
@@ -167,8 +163,6 @@ export declare function leadWorstCaseForPrice(price: ModelPrice, baseBytes: numb
167
163
  callCap?: number;
168
164
  textCap?: number;
169
165
  }): number;
170
- /** The bytes a tool result costs on the wire: its JSON string form. */
171
- export declare function embeddedBytes(text: string): number;
172
166
  export type LeadToolSchema = {
173
167
  name: string;
174
168
  description: string;
package/dist/converse.js CHANGED
@@ -131,21 +131,6 @@ export function worstCaseForPrice(price, promptBytes) {
131
131
  export function settleForPrice(price, tokensIn, tokensOut) {
132
132
  return tokensIn * price.inMicrousd + tokensOut * price.outMicrousd;
133
133
  }
134
- /** The worst a turn can cost, in integer micro-dollars: every prompt byte
135
- * as a token-third (generous) plus the full output allowance. */
136
- export function worstCaseMicrousd(model, promptBytes) {
137
- const price = priceOf(model);
138
- if (price === null)
139
- return null;
140
- const inputTokens = Math.ceil(promptBytes / 3);
141
- return inputTokens * price.inMicrousd + MAX_OUTPUT_TOKENS * price.outMicrousd;
142
- }
143
- export function settleMicrousd(model, tokensIn, tokensOut) {
144
- const price = priceOf(model);
145
- if (price === null)
146
- return null;
147
- return tokensIn * price.inMicrousd + tokensOut * price.outMicrousd;
148
- }
149
134
  // ---------------------------------------------------------------- keys
150
135
  export const DIRECT_CHAT_PROVIDERS = ["anthropic-api", "openrouter-api"];
151
136
  export const SUBSCRIPTION_CHAT_PROVIDERS = ["claude-subscription", "codex-subscription"];
@@ -389,10 +374,6 @@ export function leadWorstCaseForPrice(price, baseBytes, caps = {}) {
389
374
  }
390
375
  return input * price.inMicrousd + S * MAX_OUTPUT_TOKENS * price.outMicrousd;
391
376
  }
392
- /** The bytes a tool result costs on the wire: its JSON string form. */
393
- export function embeddedBytes(text) {
394
- return Buffer.byteLength(JSON.stringify(text), "utf8");
395
- }
396
377
  /** Anthropic prices a cache write at 1.25x and a cache read at 0.1x the input price (5-minute cache). */
397
378
  export const CACHE_WRITE_RATIO = 1.25;
398
379
  export const CACHE_READ_RATIO = 0.1;
package/dist/daemon.js CHANGED
@@ -42,6 +42,7 @@ import { fileURLToPath } from "node:url";
42
42
  import { dirname, join } from "node:path";
43
43
  import { isAlive } from "./runner.js";
44
44
  import { envTwins } from "./names.js";
45
+ import { sleep as defaultSleep } from "./sleep.js";
45
46
  /** A stable fingerprint of a unit's text: the changed-definition test. */
46
47
  export function definitionDigest(unitContent) {
47
48
  return createHash("sha256").update(unitContent).digest("hex").slice(0, 16);
@@ -52,7 +53,7 @@ export function definitionDigest(unitContent) {
52
53
  * appears to succeed, then the pending bootout removes the new job too. Wait
53
54
  * for the observable supervisor boundary before loading the replacement.
54
55
  */
55
- async function waitForLaunchdBootout(run, service, attempts = 50, sleep = ms => new Promise(resolve => setTimeout(resolve, ms))) {
56
+ async function waitForLaunchdBootout(run, service, attempts = 50, sleep = defaultSleep) {
56
57
  for (let attempt = 0; attempt < attempts; attempt += 1) {
57
58
  const status = await run("launchctl", ["print", service]);
58
59
  if (status.code !== 0)
@@ -624,7 +625,7 @@ export async function daemonStatus(plan, run) {
624
625
  * FRESH one, newer than what stood before the start, so a stale row from
625
626
  * the previous incarnation cannot pass for the new controller.
626
627
  */
627
- export async function awaitFreshHeartbeat(store, runnerName, heartbeatBefore, deadlineMs = 5_000, sleep = ms => new Promise(resolve => setTimeout(resolve, ms))) {
628
+ export async function awaitFreshHeartbeat(store, runnerName, heartbeatBefore, deadlineMs = 5_000, sleep = defaultSleep) {
628
629
  const deadline = Date.now() + deadlineMs;
629
630
  for (;;) {
630
631
  const live = store.getRunner(runnerName)?.runner ?? null;
@@ -14,9 +14,7 @@
14
14
  * caps also keep one screen one screen: an option list that needs scrolling
15
15
  * has already failed the milestone sentence.
16
16
  */
17
- import { type DecisionOption, type DecisionPayload } from "./contracts/decision.js";
18
- /** One option as a decision keeps it (src/contracts/decision.ts). */
19
- export type ParsedOption = DecisionOption;
17
+ import { type DecisionPayload } from "./contracts/decision.js";
20
18
  /** A decision as read: the payload's fields, its text trimmed, and the optional ones present or null. */
21
19
  export type ParsedDecision = Omit<DecisionPayload, "assignee" | "deadline"> & {
22
20
  assignee: string | null;
@@ -1,12 +1,20 @@
1
1
  /**
2
- * D5 (schema v117): one AI concept, the lead. The central team service (`connect`, the central `lead list|create|update|
2
+ * D5 (schema v117): one AI concept, the lead. The central team service's CLI (the central `lead list|create|update|
3
3
  * member|transfer`, `conversation …`, and `chat`/`brief` with --lead, --conversation or a saved profile) and native
4
- * coding sessions (`session …`) are deprecated. For this release they still work exactly as before, but they are
5
- * hidden from help, the command contract and the console, and each run says so once on stderr — never on stdout, so a
6
- * `--json` answer stays one envelope. Their code goes in the next minor release.
4
+ * coding sessions (`session …`) were deprecated in 0.9.56 and are removed now: each answers with one line naming what
5
+ * to use instead, changing nothing. `connect` stays — remote commands and `toolroll health` use the profile it saves.
7
6
  */
8
7
  export type Deprecated = "team" | "session";
9
8
  /** The one line a deprecated command prints on stderr: what it is, when it goes, and what to use instead. */
10
9
  export declare function deprecationWarning(command: string, kind: Deprecated): string;
11
10
  /** What a deprecated console page or API says about itself. */
12
11
  export declare const DEPRECATED_PAGE: Record<Deprecated, string>;
12
+ /** The removed command an invocation names, as `{ named, kind }`; null when it is a live command. `chat`/`brief`
13
+ * without --local went to the central service whenever a profile was saved (`savedProfile`, asked only then): that
14
+ * invocation is removed too, never quietly run against this computer's lead instead. */
15
+ export declare function removedCommand(argv: readonly string[], savedProfile?: () => boolean): {
16
+ named: string;
17
+ kind: Deprecated;
18
+ } | null;
19
+ /** The one line a removed command answers with. */
20
+ export declare function removedMessage(named: string, kind: Deprecated): string;
@@ -1,9 +1,8 @@
1
1
  /**
2
- * D5 (schema v117): one AI concept, the lead. The central team service (`connect`, the central `lead list|create|update|
2
+ * D5 (schema v117): one AI concept, the lead. The central team service's CLI (the central `lead list|create|update|
3
3
  * member|transfer`, `conversation …`, and `chat`/`brief` with --lead, --conversation or a saved profile) and native
4
- * coding sessions (`session …`) are deprecated. For this release they still work exactly as before, but they are
5
- * hidden from help, the command contract and the console, and each run says so once on stderr — never on stdout, so a
6
- * `--json` answer stays one envelope. Their code goes in the next minor release.
4
+ * coding sessions (`session …`) were deprecated in 0.9.56 and are removed now: each answers with one line naming what
5
+ * to use instead, changing nothing. `connect` stays — remote commands and `toolroll health` use the profile it saves.
7
6
  */
8
7
  const NEXT_STEP = {
9
8
  team: "Talk to your lead with `toolroll chat`.",
@@ -18,3 +17,27 @@ export const DEPRECATED_PAGE = {
18
17
  team: "Team chat is deprecated and will be removed in the next minor release. Your lead in Chat does the same work.",
19
18
  session: "Coding sessions are deprecated and will be removed in the next minor release. Queue work as a task instead.",
20
19
  };
20
+ const CENTRAL_LEAD_ACTIONS = ["list", "create", "update", "member", "transfer"];
21
+ const CENTRAL_CHAT_FLAGS = ["--profile", "--lead", "--conversation", "--authorize", "--terms-digest", "--request-id"];
22
+ /** The removed command an invocation names, as `{ named, kind }`; null when it is a live command. `chat`/`brief`
23
+ * without --local went to the central service whenever a profile was saved (`savedProfile`, asked only then): that
24
+ * invocation is removed too, never quietly run against this computer's lead instead. */
25
+ export function removedCommand(argv, savedProfile = () => false) {
26
+ const [first, second] = argv;
27
+ const verb = () => argv.slice(1).find(arg => !arg.startsWith("-")) ?? "";
28
+ if (first === "session")
29
+ return { named: `session ${verb()}`.trim(), kind: "session" };
30
+ if (first === "conversation")
31
+ return { named: `conversation ${verb()}`.trim(), kind: "team" };
32
+ if (first === "lead" && second !== "token" && second !== "say" && argv.some(arg => arg === "--profile" || CENTRAL_LEAD_ACTIONS.includes(arg)))
33
+ return { named: `lead ${verb()}`.trim(), kind: "team" };
34
+ if ((first === "chat" || first === "brief") && argv.some(arg => CENTRAL_CHAT_FLAGS.includes(arg)))
35
+ return { named: `${first} --conversation`, kind: "team" };
36
+ if ((first === "chat" || first === "brief") && !argv.includes("--local") && savedProfile())
37
+ return { named: `${first} --conversation`, kind: "team" };
38
+ return null;
39
+ }
40
+ /** The one line a removed command answers with. */
41
+ export function removedMessage(named, kind) {
42
+ return `\`toolroll ${named}\` was removed. ${NEXT_STEP[kind]}`;
43
+ }
@@ -8,9 +8,9 @@ import { bundleHash } from "./desktop-bundle.js";
8
8
  import { installLaunchdService, launchdPlist } from "./daemon.js";
9
9
  import { run } from "./exec.js";
10
10
  import { desktopUpdateStatus, durableJson, installationLock, pauseUpdateRecovery, readUpdateJournal, requestUpdateRestore, sqliteLock, updateTerminal } from "./desktop-update.js";
11
+ import { sleep } from "./sleep.js";
11
12
  const recordFile = (j) => join(j.workDir, "recovery.json");
12
13
  const app = (j) => join(j.workDir, "Updater.app");
13
- const sleep = (ms) => new Promise(done => setTimeout(done, ms));
14
14
  function readRecovery(j) {
15
15
  const file = recordFile(j);
16
16
  if (!existsSync(file))
@@ -1,5 +1,5 @@
1
1
  import { createHash, randomUUID } from "node:crypto";
2
- import { closeSync, chmodSync, copyFileSync, cpSync, existsSync, fsyncSync, lstatSync, mkdirSync, openSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
2
+ import { closeSync, chmodSync, copyFileSync, cpSync, existsSync, fsyncSync, lstatSync, mkdirSync, openSync, readFileSync, renameSync, writeFileSync } from "node:fs";
3
3
  import { homedir } from "node:os";
4
4
  import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
5
5
  import { createRequire } from "node:module";
@@ -14,6 +14,7 @@ import { currentDesktopAccess } from "./desktop-access.js";
14
14
  import { assertCodingUpdateStopped, backupCodingCatalog, codingCatalogExists, releaseStaleCodingOwner } from "./coding-update.js";
15
15
  import { processMayBeAlive } from "./process-liveness.js";
16
16
  import { readDesktopRecoveryView, readDesktopUpdateJournal, supervisorPidsOf, updateRequestIs } from "./contracts/update-journal.js";
17
+ import { sleep as defaultSleep } from "./sleep.js";
17
18
  /** Loaded on first use (as backup.ts and store.ts do), so modules that only import this one (the console,
18
19
  * and tests that load it in a browser-like environment) never need `node:sqlite` itself. */
19
20
  function sqlite() {
@@ -657,7 +658,7 @@ export async function runDesktopUpdate(stateDir, hooks = {}) {
657
658
  lock.close();
658
659
  throw Error("Another updater is working on this app. Its operation was not interrupted.");
659
660
  }
660
- const sleep = hooks.sleep ?? (ms => new Promise(done => setTimeout(done, ms)));
661
+ const sleep = hooks.sleep ?? defaultSleep;
661
662
  const control = async (action, bundle, journal) => {
662
663
  if (action === "start" && updateStopRequested(journal))
663
664
  throw Error("You stopped the background service. Automatic restart is disabled for this update.");
@@ -3,8 +3,7 @@ import { chatQuestionButtons } from "./subagent-question.js";
3
3
  import { chatAskButtons } from "./chat-ask.js";
4
4
  import { chatFlowButtons } from "./chat-flow.js";
5
5
  import { refuseResultShots, resultShotsPruned, shotWaitsUntil } from "./result-shots.js";
6
- import { channelInbox } from "./chat-inbox.js";
7
- import { roomCommand } from "./chat-rooms.js";
6
+ import { admitChatEvent } from "./chat-admission.js";
8
7
  import { ChatState, ChatDeliveryError, chatHash, partContent, } from "./chat-delivery-state.js";
9
8
  import { readChatPart } from "./contracts/chat-content.js";
10
9
  import { readDiscordButtonToken, readDiscordComponentInteraction } from "./contracts/discord-callback.js";
@@ -100,20 +99,10 @@ export function receiveDiscord(state, identity, type, raw, now) {
100
99
  !discordId(thread) ||
101
100
  member === identity.bot)
102
101
  return false;
103
- const words = "text" in payload ? payload.text ?? "" : "";
104
- // v89: a channel that feeds a flow takes anyone's message (as a card, with no say over anything); "flow 12" connects one.
105
- const inbox = isRoom && kind === "message" ? channelInbox(state.store, "discord", identity.installation, String(channel), words) : { watched: false, command: false };
106
- const roomish = isRoom && (state.room(identity.installation, String(channel)) !== null || (kind === "message" && roomCommand(words) !== null) || inbox.watched || inbox.command);
107
- if (isRoom && !roomish)
108
- return false;
109
- const binding = state.bindingFor(identity.installation, member);
110
- const open = inbox.watched && !inbox.command;
111
- if (kind === "pair"
112
- ? !!binding || isRoom
113
- : !open && (!binding ||
114
- !state.live(binding) ||
115
- (binding.channel !== channel && !roomish)))
102
+ const admitted = admitChatEvent(state, "discord", identity.installation, { kind, member, channel, isRoom, payload });
103
+ if (admitted === null)
116
104
  return false;
105
+ const { binding } = admitted;
117
106
  return state.enqueue({
118
107
  id: chatHash(`${identity.installation}:${kind === "action" ? "interaction" : "message"}:${id}`),
119
108
  installation: identity.installation,
@@ -1,8 +1,4 @@
1
1
  import type { Store } from "./store.js";
2
2
  import { type Html } from "./html.js";
3
- export declare function discordSettingsHtml(store: Store, dir: string, options?: {
4
- code?: string;
5
- problem?: string;
6
- now?: Date;
7
- who?: string;
8
- }): Html;
3
+ import { type ChatSettingsOptions } from "./chat-settings-page.js";
4
+ export declare function discordSettingsHtml(store: Store, dir: string, options?: ChatSettingsOptions): Html;