@intentic/sandbox-contract 1.334.0 → 1.335.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 (238) hide show
  1. package/README.md +8 -3
  2. package/dist/contracts/accounts.contract.d.ts +11 -11
  3. package/dist/contracts/activity.contract.d.ts +1 -0
  4. package/dist/contracts/activity.contract.d.ts.map +1 -1
  5. package/dist/contracts/activity.contract.js +1 -1
  6. package/dist/contracts/activity.contract.js.map +1 -1
  7. package/dist/contracts/agent.contract.d.ts +102 -18
  8. package/dist/contracts/agent.contract.d.ts.map +1 -1
  9. package/dist/contracts/agents.contract.d.ts +163 -0
  10. package/dist/contracts/agents.contract.d.ts.map +1 -1
  11. package/dist/contracts/agents.contract.js +10 -1
  12. package/dist/contracts/agents.contract.js.map +1 -1
  13. package/dist/contracts/audit.contract.d.ts +84 -0
  14. package/dist/contracts/audit.contract.d.ts.map +1 -0
  15. package/dist/contracts/audit.contract.js +43 -0
  16. package/dist/contracts/audit.contract.js.map +1 -0
  17. package/dist/contracts/automations.contract.d.ts +15 -0
  18. package/dist/contracts/automations.contract.d.ts.map +1 -1
  19. package/dist/contracts/ci.contract.d.ts +10 -0
  20. package/dist/contracts/ci.contract.d.ts.map +1 -1
  21. package/dist/contracts/compliance.contract.d.ts +163 -0
  22. package/dist/contracts/compliance.contract.d.ts.map +1 -0
  23. package/dist/contracts/compliance.contract.js +41 -0
  24. package/dist/contracts/compliance.contract.js.map +1 -0
  25. package/dist/contracts/device.contract.d.ts +6 -0
  26. package/dist/contracts/device.contract.d.ts.map +1 -1
  27. package/dist/contracts/extensions.contract.d.ts +2 -0
  28. package/dist/contracts/extensions.contract.d.ts.map +1 -1
  29. package/dist/contracts/loops.contract.d.ts +15 -0
  30. package/dist/contracts/loops.contract.d.ts.map +1 -1
  31. package/dist/contracts/needs.contract.d.ts +49 -0
  32. package/dist/contracts/needs.contract.d.ts.map +1 -1
  33. package/dist/contracts/offload.contract.d.ts +5 -0
  34. package/dist/contracts/offload.contract.d.ts.map +1 -1
  35. package/dist/contracts/personas.contract.d.ts +10 -0
  36. package/dist/contracts/personas.contract.d.ts.map +1 -1
  37. package/dist/contracts/providers.contract.d.ts +2 -0
  38. package/dist/contracts/providers.contract.d.ts.map +1 -1
  39. package/dist/contracts/providers.contract.js +4 -0
  40. package/dist/contracts/providers.contract.js.map +1 -1
  41. package/dist/contracts/runner.contract.d.ts +42 -10
  42. package/dist/contracts/runner.contract.d.ts.map +1 -1
  43. package/dist/contracts/sessions.contract.d.ts +17 -0
  44. package/dist/contracts/sessions.contract.d.ts.map +1 -1
  45. package/dist/contracts/settings.contract.d.ts +84 -0
  46. package/dist/contracts/settings.contract.d.ts.map +1 -1
  47. package/dist/contracts/settings.contract.js +7 -0
  48. package/dist/contracts/settings.contract.js.map +1 -1
  49. package/dist/contracts/system.contract.d.ts +16 -2
  50. package/dist/contracts/system.contract.d.ts.map +1 -1
  51. package/dist/contracts/workflows.contract.d.ts +30 -0
  52. package/dist/contracts/workflows.contract.d.ts.map +1 -1
  53. package/dist/contracts/workspace.contract.d.ts +3 -0
  54. package/dist/contracts/workspace.contract.d.ts.map +1 -1
  55. package/dist/events/agent-events.d.ts +74 -0
  56. package/dist/events/agent-events.d.ts.map +1 -1
  57. package/dist/events/agent-events.js +1 -0
  58. package/dist/events/agent-events.js.map +1 -1
  59. package/dist/events/requests.d.ts +45 -0
  60. package/dist/events/requests.d.ts.map +1 -1
  61. package/dist/events/system-events.d.ts +12 -0
  62. package/dist/events/system-events.d.ts.map +1 -1
  63. package/dist/events/transcript.d.ts +117 -0
  64. package/dist/events/transcript.d.ts.map +1 -1
  65. package/dist/index.d.ts +828 -73
  66. package/dist/index.d.ts.map +1 -1
  67. package/dist/index.js +11 -0
  68. package/dist/index.js.map +1 -1
  69. package/dist/models/agent-catalog.d.ts +18 -3
  70. package/dist/models/agent-catalog.d.ts.map +1 -1
  71. package/dist/models/agent-catalog.js +61 -12
  72. package/dist/models/agent-catalog.js.map +1 -1
  73. package/dist/models/agent-runtimes.d.ts +5 -2
  74. package/dist/models/agent-runtimes.d.ts.map +1 -1
  75. package/dist/models/agent-runtimes.js +73 -40
  76. package/dist/models/agent-runtimes.js.map +1 -1
  77. package/dist/models/model-setups.d.ts +5 -0
  78. package/dist/models/model-setups.d.ts.map +1 -1
  79. package/dist/models/provider-specs.d.ts +153 -32
  80. package/dist/models/provider-specs.d.ts.map +1 -1
  81. package/dist/models/provider-specs.js +97 -11
  82. package/dist/models/provider-specs.js.map +1 -1
  83. package/dist/policy/reserved-servers.d.ts.map +1 -1
  84. package/dist/policy/reserved-servers.js +1 -0
  85. package/dist/policy/reserved-servers.js.map +1 -1
  86. package/dist/policy/sandbox-power.d.ts +7 -2
  87. package/dist/policy/sandbox-power.d.ts.map +1 -1
  88. package/dist/policy/sandbox-power.js +34 -1
  89. package/dist/policy/sandbox-power.js.map +1 -1
  90. package/dist/policy/turned-away.d.ts.map +1 -1
  91. package/dist/policy/turned-away.js +1 -0
  92. package/dist/policy/turned-away.js.map +1 -1
  93. package/dist/protocol/doors/listener-protocol.d.ts +43 -1
  94. package/dist/protocol/doors/listener-protocol.d.ts.map +1 -1
  95. package/dist/protocol/doors/listener-protocol.js +10 -0
  96. package/dist/protocol/doors/listener-protocol.js.map +1 -1
  97. package/dist/protocol/raw/raw-json-routes.d.ts +92 -0
  98. package/dist/protocol/raw/raw-json-routes.d.ts.map +1 -1
  99. package/dist/protocol/raw/raw-json-routes.js +2 -1
  100. package/dist/protocol/raw/raw-json-routes.js.map +1 -1
  101. package/dist/protocol/raw/raw-routes.d.ts +13 -0
  102. package/dist/protocol/raw/raw-routes.d.ts.map +1 -1
  103. package/dist/protocol/raw/raw-routes.js +3 -0
  104. package/dist/protocol/raw/raw-routes.js.map +1 -1
  105. package/dist/schemas/activity.d.ts +2 -0
  106. package/dist/schemas/activity.d.ts.map +1 -1
  107. package/dist/schemas/agent.d.ts +34 -0
  108. package/dist/schemas/agent.d.ts.map +1 -1
  109. package/dist/schemas/agent.js +7 -6
  110. package/dist/schemas/agent.js.map +1 -1
  111. package/dist/schemas/agents-list.d.ts +7 -0
  112. package/dist/schemas/agents-list.d.ts.map +1 -1
  113. package/dist/schemas/agents.d.ts +18 -0
  114. package/dist/schemas/agents.d.ts.map +1 -1
  115. package/dist/schemas/ai-literacy.d.ts +54 -0
  116. package/dist/schemas/ai-literacy.d.ts.map +1 -0
  117. package/dist/schemas/ai-literacy.js +15 -0
  118. package/dist/schemas/ai-literacy.js.map +1 -0
  119. package/dist/schemas/audit.d.ts +166 -0
  120. package/dist/schemas/audit.d.ts.map +1 -0
  121. package/dist/schemas/audit.js +100 -0
  122. package/dist/schemas/audit.js.map +1 -0
  123. package/dist/schemas/automations.d.ts +27 -0
  124. package/dist/schemas/automations.d.ts.map +1 -1
  125. package/dist/schemas/automations.js +11 -0
  126. package/dist/schemas/automations.js.map +1 -1
  127. package/dist/schemas/ci.d.ts +10 -0
  128. package/dist/schemas/ci.d.ts.map +1 -1
  129. package/dist/schemas/compliance.d.ts +423 -0
  130. package/dist/schemas/compliance.d.ts.map +1 -0
  131. package/dist/schemas/compliance.js +135 -0
  132. package/dist/schemas/compliance.js.map +1 -0
  133. package/dist/schemas/data-protection.d.ts +28 -0
  134. package/dist/schemas/data-protection.d.ts.map +1 -0
  135. package/dist/schemas/data-protection.js +49 -0
  136. package/dist/schemas/data-protection.js.map +1 -0
  137. package/dist/schemas/devices.d.ts +12 -0
  138. package/dist/schemas/devices.d.ts.map +1 -1
  139. package/dist/schemas/engines.d.ts +22 -1
  140. package/dist/schemas/engines.d.ts.map +1 -1
  141. package/dist/schemas/engines.js +1 -1
  142. package/dist/schemas/engines.js.map +1 -1
  143. package/dist/schemas/extension-updates.d.ts +4 -0
  144. package/dist/schemas/extension-updates.d.ts.map +1 -1
  145. package/dist/schemas/git/git.d.ts +33 -0
  146. package/dist/schemas/git/git.d.ts.map +1 -1
  147. package/dist/schemas/git/git.js +29 -0
  148. package/dist/schemas/git/git.js.map +1 -1
  149. package/dist/schemas/hosts.d.ts +36 -0
  150. package/dist/schemas/hosts.d.ts.map +1 -1
  151. package/dist/schemas/hosts.js +2 -0
  152. package/dist/schemas/hosts.js.map +1 -1
  153. package/dist/schemas/intentic-os.d.ts +117 -0
  154. package/dist/schemas/intentic-os.d.ts.map +1 -0
  155. package/dist/schemas/intentic-os.js +66 -0
  156. package/dist/schemas/intentic-os.js.map +1 -0
  157. package/dist/schemas/loops.d.ts +15 -0
  158. package/dist/schemas/loops.d.ts.map +1 -1
  159. package/dist/schemas/members.d.ts +90 -0
  160. package/dist/schemas/members.d.ts.map +1 -1
  161. package/dist/schemas/members.js +73 -3
  162. package/dist/schemas/members.js.map +1 -1
  163. package/dist/schemas/needs.d.ts +56 -0
  164. package/dist/schemas/needs.d.ts.map +1 -1
  165. package/dist/schemas/offload.d.ts +5 -0
  166. package/dist/schemas/offload.d.ts.map +1 -1
  167. package/dist/schemas/personas.d.ts +10 -0
  168. package/dist/schemas/personas.d.ts.map +1 -1
  169. package/dist/schemas/providers/plan-limits.d.ts +20 -0
  170. package/dist/schemas/providers/plan-limits.d.ts.map +1 -1
  171. package/dist/schemas/providers/provider-oauth.js +1 -1
  172. package/dist/schemas/providers/provider-oauth.js.map +1 -1
  173. package/dist/schemas/providers/usage.d.ts +1 -0
  174. package/dist/schemas/providers/usage.d.ts.map +1 -1
  175. package/dist/schemas/providers/usage.js +4 -0
  176. package/dist/schemas/providers/usage.js.map +1 -1
  177. package/dist/schemas/settings.d.ts +48 -0
  178. package/dist/schemas/settings.d.ts.map +1 -1
  179. package/dist/schemas/settings.js +14 -0
  180. package/dist/schemas/settings.js.map +1 -1
  181. package/dist/schemas/system.d.ts +8 -0
  182. package/dist/schemas/system.d.ts.map +1 -1
  183. package/dist/schemas/system.js +2 -0
  184. package/dist/schemas/system.js.map +1 -1
  185. package/dist/schemas/workflows.d.ts +50 -0
  186. package/dist/schemas/workflows.d.ts.map +1 -1
  187. package/dist/schemas/workspace/workspace-tree.d.ts +4 -0
  188. package/dist/schemas/workspace/workspace-tree.d.ts.map +1 -1
  189. package/dist/schemas/workspace/workspace-tree.js +16 -1
  190. package/dist/schemas/workspace/workspace-tree.js.map +1 -1
  191. package/dist/state/definition.d.ts +80 -4
  192. package/dist/state/definition.d.ts.map +1 -1
  193. package/dist/state/history-state.d.ts.map +1 -1
  194. package/dist/state/history-state.js +2 -0
  195. package/dist/state/history-state.js.map +1 -1
  196. package/package.json +5 -5
  197. package/src/contracts/activity.contract.ts +1 -1
  198. package/src/contracts/agents.contract.ts +13 -1
  199. package/src/contracts/audit.contract.ts +48 -0
  200. package/src/contracts/compliance.contract.ts +57 -0
  201. package/src/contracts/providers.contract.ts +9 -0
  202. package/src/contracts/settings.contract.ts +7 -0
  203. package/src/events/agent-events.ts +4 -0
  204. package/src/index.ts +11 -0
  205. package/src/models/agent-catalog.test.ts +317 -53
  206. package/src/models/agent-catalog.ts +115 -22
  207. package/src/models/agent-runtimes.ts +273 -75
  208. package/src/models/capability-ledger.test.ts +12 -1
  209. package/src/models/provider-specs.test.ts +42 -7
  210. package/src/models/provider-specs.ts +160 -20
  211. package/src/policy/reserved-servers.ts +2 -1
  212. package/src/policy/sandbox-power.ts +67 -8
  213. package/src/policy/tests/sandbox-power.test.ts +59 -1
  214. package/src/policy/turned-away.ts +2 -0
  215. package/src/protocol/doors/listener-protocol.ts +74 -6
  216. package/src/protocol/raw/raw-json-routes.ts +2 -1
  217. package/src/protocol/raw/raw-routes.ts +7 -0
  218. package/src/schemas/activity.ts +2 -2
  219. package/src/schemas/agent.ts +22 -9
  220. package/src/schemas/ai-literacy.ts +17 -0
  221. package/src/schemas/audit.ts +131 -0
  222. package/src/schemas/automations.ts +13 -0
  223. package/src/schemas/compliance.ts +195 -0
  224. package/src/schemas/daemon-health.test.ts +2 -0
  225. package/src/schemas/data-protection.ts +99 -0
  226. package/src/schemas/engines.ts +1 -1
  227. package/src/schemas/git/git.ts +46 -0
  228. package/src/schemas/hosts.ts +5 -0
  229. package/src/schemas/intentic-os.test.ts +86 -0
  230. package/src/schemas/intentic-os.ts +130 -0
  231. package/src/schemas/members.test.ts +47 -0
  232. package/src/schemas/members.ts +141 -6
  233. package/src/schemas/providers/provider-oauth.ts +1 -1
  234. package/src/schemas/providers/usage.ts +6 -0
  235. package/src/schemas/settings.ts +32 -0
  236. package/src/schemas/system.ts +2 -0
  237. package/src/schemas/workspace/workspace-tree.ts +26 -1
  238. package/src/state/history-state.ts +7 -0
@@ -1,6 +1,6 @@
1
- import { ACP, type AgentCapabilities, CLAUDE_CODE, PI } from "./agent-runtimes.js";
2
- import { type NativeProvider, PROVIDER_SPECS, type ProviderAccess, providerSpec } from "./provider-specs.js";
3
- import type { AgentHarness, AgentProvider, PermissionMode } from "../schemas/agent.js";
1
+ import { ACP, type AgentCapabilities, CLAUDE_CODE, CODEX, MUSE, OPENCODE, PI } from "./agent-runtimes.js";
2
+ import { type LoopTerms, type NativeProvider, PROVIDER_SPECS, type ProviderAccess, type ProviderLoops, providerSpec } from "./provider-specs.js";
3
+ import type { AgentHarness, AgentLoop, AgentProvider, PermissionMode } from "../schemas/agent.js";
4
4
  import type { Model, ModelBadge } from "../schemas/providers/provider-oauth.js";
5
5
 
6
6
  // The provider/harness/model catalog every picker shares, pure data keyed by the wire vocabulary in schemas/agent.ts.
@@ -64,37 +64,128 @@ export const providerLabel = (provider: AgentProvider): string => providerSpec(p
64
64
  export const PLAN_LIMIT_PROVIDERS: readonly NativeProvider[] = PROVIDER_SPECS.filter((spec) => spec.planLimits).map((spec) => spec.id);
65
65
  export const reportsPlanLimits = (provider: AgentProvider): boolean => PLAN_LIMIT_PROVIDERS.includes(provider as NativeProvider);
66
66
 
67
- // `native` is the provider's own runtime; `claude-code` runs it through that loop instead, for any provider.
67
+ // Every value the harness axis takes, in the wire enum's order; `native` names whichever loop the provider defaults to.
68
+ // Labels are the loops' own names, except `vendor`, which only a provider can name (loopLabel).
68
69
  export const HARNESSES: readonly { label: string; value: AgentHarness }[] = [
69
70
  { label: "Native", value: "native" },
70
71
  { label: "Claude Code", value: "claude-code" },
72
+ { label: "Codex", value: "codex" },
73
+ { label: "OpenCode", value: "opencode" },
74
+ { label: "Pi", value: "pi" },
75
+ { label: "Muse Code", value: "muse" },
76
+ { label: "Own agent", value: "vendor" },
71
77
  ];
72
78
 
73
- // Whether the harness axis is a real choice for this provider, or a switch whose two positions run the same loop.
74
- // Derived, so a provider that gains a native runtime tomorrow gains the switch with it.
75
- export const harnessChoosable = (provider: AgentProvider): boolean => {
76
- const spec = providerSpec(provider);
77
- return spec !== undefined && spec.runtimes.native.runtime !== spec.runtimes.claudeCode.runtime;
79
+ // Reserved like a native id: an `agent`-kind capability installed under it is served over Pi's RPC, not ACP.
80
+ export const PI_PROVIDER = "pi";
81
+
82
+ // The loops of everything that is not a spec row, said once: an `endpoint/<id>` defaults to Claude Code (the loop that
83
+ // speaks Anthropic Messages to any base) and also runs on Codex (Responses, through the translator's entry for it),
84
+ // OpenCode (straight at the endpoint, in its own protocol) and Muse Code (whose provider speaks Responses, which the
85
+ // translator serves for an OpenAI-protocol endpoint); the owner's own key, so no vendor terms. The free trial is the
86
+ // exception, fixed to Claude Code: its one model id is the translator's, its disclosure is that loop's, and its pool
87
+ // refuses a replayed tool call without its own reasoning signature. `pi` runs on its own RPC runtime, and any other id
88
+ // is an installed ACP agent's own.
89
+ const ENDPOINT_LOOPS: ProviderLoops = {
90
+ default: "claude-code",
91
+ offered: {
92
+ "claude-code": { capabilities: CLAUDE_CODE },
93
+ codex: { capabilities: CODEX },
94
+ opencode: { capabilities: OPENCODE },
95
+ muse: { capabilities: MUSE },
96
+ },
78
97
  };
98
+ const TRIAL_LOOPS: ProviderLoops = { default: "claude-code", offered: { "claude-code": { capabilities: CLAUDE_CODE } } };
99
+ const PI_LOOPS: ProviderLoops = { default: "pi", offered: { pi: { capabilities: PI } } };
100
+ const ACP_LOOPS: ProviderLoops = { default: "vendor", offered: { vendor: { capabilities: ACP } } };
79
101
 
80
- // Maps (provider, harness) to a record: a native spec row, an `endpoint/<id>` at the Claude Code loop's ceiling, `pi`
81
- // at its own RPC runtime, anything else over ACP. Naming one record on both harnesses is a fact, not a preference.
82
- export const capabilitiesOf = (provider: AgentProvider, harness: AgentHarness): AgentCapabilities => {
102
+ // The loop table for any provider id: its spec row's, or the rule for an endpoint, Pi or an ACP agent.
103
+ export const providerLoops = (provider: AgentProvider): ProviderLoops => {
83
104
  const spec = providerSpec(provider);
84
105
  if (spec !== undefined) {
85
- return harness === "claude-code" ? spec.runtimes.claudeCode : spec.runtimes.native;
106
+ return spec.loops;
86
107
  }
87
108
  if (isEndpointProvider(provider)) {
88
- return CLAUDE_CODE;
109
+ return isTrialProvider(provider) ? TRIAL_LOOPS : ENDPOINT_LOOPS;
89
110
  }
90
- if (provider === PI_PROVIDER) {
91
- return PI;
111
+ return provider === PI_PROVIDER ? PI_LOOPS : ACP_LOOPS;
112
+ };
113
+
114
+ const LOOP_ORDER: readonly AgentLoop[] = HARNESSES.flatMap((entry) => (entry.value === "native" ? [] : [entry.value]));
115
+
116
+ // The loops this provider offers, its default first and the rest in the wire enum's order.
117
+ export const loopsOf = (provider: AgentProvider): readonly AgentLoop[] => {
118
+ const loops = providerLoops(provider);
119
+ return [loops.default, ...LOOP_ORDER.filter((loop) => loop !== loops.default && loops.offered[loop] !== undefined)];
120
+ };
121
+
122
+ // The loop a turn actually runs on: `native` is the provider's default, an offered loop is itself, and a loop the
123
+ // provider does not offer (a composer setting left over from another provider) runs the default rather than refusing.
124
+ export const loopOf = (provider: AgentProvider, harness: AgentHarness): AgentLoop => {
125
+ const loops = providerLoops(provider);
126
+ return harness !== "native" && loops.offered[harness] !== undefined ? harness : loops.default;
127
+ };
128
+
129
+ // The one spelling of a harness on a turn: `native` wherever it resolves to the default loop, so a turn naming its
130
+ // provider's own loop outright and one naming none are recorded alike.
131
+ export const canonicalHarness = (provider: AgentProvider, harness: AgentHarness | undefined): AgentHarness => {
132
+ if (harness === undefined) {
133
+ return "native";
92
134
  }
93
- return ACP;
135
+ const loop = loopOf(provider, harness);
136
+ return loop === providerLoops(provider).default ? "native" : loop;
94
137
  };
95
138
 
96
- // Reserved like a native id: an `agent`-kind capability installed under it is served over Pi's RPC, not ACP.
97
- export const PI_PROVIDER = "pi";
139
+ // Whether the loop is a real choice for this provider; derived, so a provider offered a second loop gains the chips.
140
+ export const harnessChoosable = (provider: AgentProvider): boolean => loopsOf(provider).length > 1;
141
+
142
+ // What a chip or a pill calls the loop. `vendor` is the provider's own agent, so it takes the provider's name, unless
143
+ // the offer names the program (Grok Build, Kimi CLI) because the provider's name is on its other loops too.
144
+ export const loopLabel = (provider: AgentProvider, loop: AgentLoop): string =>
145
+ providerLoops(provider).offered[loop]?.label ??
146
+ (loop === "vendor" ? providerLabel(provider) : (HARNESSES.find((entry) => entry.value === loop)?.label ?? loop));
147
+
148
+ // The account-door variant the loop a turn runs on signs in under (LoopOffer.door), resolved as the turn is; undefined
149
+ // where it spends the provider's default credential.
150
+ export const loopDoor = (provider: AgentProvider, harness: AgentHarness): string | undefined =>
151
+ providerLoops(provider).offered[loopOf(provider, harness)]?.door;
152
+
153
+ // The loops whose own sign-in the provider's account door holds beside its default one, in loop order.
154
+ export const loopDoors = (provider: AgentProvider): readonly { readonly loop: AgentLoop; readonly door: string }[] =>
155
+ loopsOf(provider).flatMap((loop) => {
156
+ const door = providerLoops(provider).offered[loop]?.door;
157
+ return door === undefined ? [] : [{ loop, door }];
158
+ });
159
+
160
+ // Whether one of the provider's own accounts can serve a turn on this loop: where any loop signs in through a door of its
161
+ // own, an account serves the loop whose door its variant names, and an account naming none serves the default
162
+ // credential's loops; elsewhere (Z.ai's estates are variants too) every account serves every loop.
163
+ export const accountServesLoop = (provider: AgentProvider, harness: AgentHarness, account: { readonly variant?: string | undefined }): boolean => {
164
+ const doors = loopDoors(provider);
165
+ if (doors.length === 0) {
166
+ return true;
167
+ }
168
+ const own = doors.some((entry) => entry.door === account.variant) ? account.variant : undefined;
169
+ return own === loopDoor(provider, harness);
170
+ };
171
+
172
+ // What (provider, harness) can do, resolved as the turn is (loopOf).
173
+ export const capabilitiesOf = (provider: AgentProvider, harness: AgentHarness): AgentCapabilities => {
174
+ const loops = providerLoops(provider);
175
+ // loopOf only answers an offered loop or the default, and a row's default is offered (provider-specs.test.ts).
176
+ return (loops.offered[loopOf(provider, harness)] ?? loops.offered[loops.default])!.capabilities;
177
+ };
178
+
179
+ // Where the daemon's runtime health map files one pair's own answer, beside the runtime's (keyed by runtime alone): a
180
+ // loop hosting a provider not its own can be ready for one and not another (Codex signed in to ChatGPT, but no Grok
181
+ // sign-in on the translator for Grok on Codex). A reader asks the pair's key first and the runtime's after it.
182
+ export const pairHealthKey = (runtime: AgentCapabilities["runtime"], provider: AgentProvider): string => `${runtime}:${provider}`;
183
+
184
+ // What the provider's own terms say about the loop serving it, when they say anything worth a quiet note; undefined
185
+ // where the vendor sanctions it or nothing is on record. Resolved as the turn is: a loop the provider does not offer
186
+ // reads as the one it runs.
187
+ export const termsOf = (provider: AgentProvider, harness: AgentHarness): LoopTerms | undefined =>
188
+ providerLoops(provider).offered[loopOf(provider, harness)]?.terms;
98
189
 
99
190
  // Which permission modes a runtime can actually be put in. Under "plan" every other mode collapses onto the autonomous
100
191
  // posture the runtime already runs, so offering them would be three names for two behaviours.
@@ -132,6 +223,7 @@ export const limitationsOf = (capabilities: AgentCapabilities): string[] => [
132
223
  ...(capabilities.rulebook === "approval" ? ["command rules apply only to calls this agent raises"] : []),
133
224
  ...(capabilities.rulebook === "refuse-only" ? ["command rules can refuse but not hold"] : []),
134
225
  ...(capabilities.rulebook === "none" ? ["command rules not applied"] : []),
226
+ ...(capabilities.secrets === "shell" ? ["secrets masked in shell output only, not in files the agent reads"] : []),
135
227
  ...(capabilities.secrets === "none" ? ["secrets reach the model unmasked"] : []),
136
228
  ...(capabilities.toolAllowlist ? [] : ["no tool lists: an automation limited to some tools won't run here"]),
137
229
  ];
@@ -173,7 +265,8 @@ export const sendableEffort = (effort: string | undefined, thinking: boolean | u
173
265
  export const sendableThinking = (effort: string | undefined, thinking: boolean | undefined): boolean | undefined =>
174
266
  effort === "max" && thinking === undefined ? true : thinking;
175
267
 
176
- // Fast speed needs all three: the runtime can ask (Claude Code loop only), the route is first-party (not the translator
177
- // or a non-Anthropic endpoint), and the model publishes the `fast` badge. Absent badges reads as false.
268
+ // Fast speed needs the runtime to be able to ask and the model to publish the `fast` badge (absent badges read as
269
+ // false). The Claude Code loop also needs a first-party route, since it serves translated and non-Anthropic endpoints
270
+ // that refuse it; any other loop that can ask speaks to its own vendor, whose catalog is where the badge came from.
178
271
  export const fastAllowed = (capabilities: AgentCapabilities, provider: AgentProvider, badges: readonly ModelBadge[] | undefined): boolean =>
179
- capabilities.fastMode && provider === "claude" && (badges ?? []).includes("fast");
272
+ capabilities.fastMode && (capabilities.runtime !== "claude-code" || provider === "claude") && (badges ?? []).includes("fast");