@bitkyc08/opencodex 2.41.0 → 2.43.0-preview.20260906

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 (260) hide show
  1. package/AGENTS_INSTALL.md +2 -2
  2. package/README.md +31 -0
  3. package/bin/ocx.mjs +10 -1
  4. package/gui/dist/assets/index-DS1NE4Jn.css +1 -0
  5. package/gui/dist/assets/index-VGeQEZ_v.js +112 -0
  6. package/gui/dist/index.html +2 -2
  7. package/package.json +1 -1
  8. package/src/adapters/anthropic-image-codec.ts +304 -0
  9. package/src/adapters/anthropic-image-normalize.ts +8 -298
  10. package/src/adapters/anthropic.ts +30 -7
  11. package/src/adapters/command-code.ts +7 -5
  12. package/src/adapters/cursor/desktop-executor-contract.ts +15 -0
  13. package/src/adapters/cursor/images.ts +36 -6
  14. package/src/adapters/cursor/live-transport.ts +7 -2
  15. package/src/adapters/cursor/native-exec-desktop.ts +2 -15
  16. package/src/adapters/cursor/protobuf-request.ts +54 -24
  17. package/src/adapters/cursor/tool-definitions.ts +5 -670
  18. package/src/adapters/cursor/tool-guidance.ts +236 -0
  19. package/src/adapters/cursor/tool-naming.ts +252 -0
  20. package/src/adapters/cursor/tool-schemas.ts +195 -0
  21. package/src/adapters/cursor/types.ts +6 -3
  22. package/src/adapters/exec-tool-result-normalize.ts +1 -1
  23. package/src/adapters/google-errors.ts +9 -1
  24. package/src/adapters/google.ts +1 -0
  25. package/src/adapters/identity.ts +8 -2
  26. package/src/adapters/kiro-calibration.ts +181 -0
  27. package/src/adapters/kiro.ts +135 -3
  28. package/src/adapters/openai-responses.ts +259 -29
  29. package/src/adapters/responses-code-mode.ts +59 -0
  30. package/src/adapters/tool-catalog-nudge.ts +1 -1
  31. package/src/adapters/xai-schema-analysis.ts +86 -0
  32. package/src/adapters/xai-tool-schema.ts +2 -87
  33. package/src/adapters/xai-web-search.ts +1 -1
  34. package/src/bridge.ts +47 -13
  35. package/src/chat/inbound.ts +11 -3
  36. package/src/claude/inbound-content-options.ts +60 -0
  37. package/src/claude/inbound-model-options.ts +142 -0
  38. package/src/claude/inbound-records.ts +7 -0
  39. package/src/claude/inbound.ts +10 -202
  40. package/src/claude/model-info.ts +45 -0
  41. package/src/cli/account-auth.ts +49 -9
  42. package/src/cli/account-extended.ts +7 -1
  43. package/src/cli/capabilities.ts +15 -4
  44. package/src/cli/claude.ts +232 -39
  45. package/src/cli/config-command.ts +9 -1
  46. package/src/cli/dispatch.ts +5 -1
  47. package/src/cli/doctor.ts +10 -0
  48. package/src/cli/effort.ts +372 -0
  49. package/src/cli/export-command.ts +3 -9
  50. package/src/cli/help.ts +1 -0
  51. package/src/cli/index.ts +13 -0
  52. package/src/cli/init.ts +4 -0
  53. package/src/cli/model-selection-guidance.ts +30 -0
  54. package/src/cli/models-runtime.ts +3 -2
  55. package/src/cli/models.ts +8 -3
  56. package/src/cli/observe.ts +3 -1
  57. package/src/cli/opencode.ts +4 -1
  58. package/src/cli/provider-runtime.ts +65 -0
  59. package/src/cli/provider.ts +8 -0
  60. package/src/cli/registry.ts +16 -2
  61. package/src/cli/runtime-api.ts +3 -1
  62. package/src/cli/star-prompt.ts +22 -6
  63. package/src/cli/status-probes.ts +168 -0
  64. package/src/cli/status.ts +5 -168
  65. package/src/clients/config-export/constants.ts +69 -0
  66. package/src/clients/config-export/contracts.ts +154 -0
  67. package/src/clients/config-export/dsh.ts +132 -0
  68. package/src/clients/config-export/fast-models.ts +29 -0
  69. package/src/clients/config-export/mcode.ts +83 -0
  70. package/src/clients/config-export/model-metadata.ts +108 -0
  71. package/src/clients/config-export/omp.ts +104 -0
  72. package/src/clients/config-export/zcode.ts +92 -0
  73. package/src/clients/config-export.ts +18 -710
  74. package/src/codex/account-lifecycle.ts +20 -3
  75. package/src/codex/account-usability.ts +2 -0
  76. package/src/codex/auth-api.ts +272 -32
  77. package/src/codex/auth-context.ts +328 -24
  78. package/src/codex/catalog/effort.ts +44 -5
  79. package/src/codex/catalog/metadata.ts +149 -14
  80. package/src/codex/catalog/native-models.ts +116 -4
  81. package/src/codex/catalog/parsing.ts +122 -8
  82. package/src/codex/catalog/provider-fetch.ts +154 -23
  83. package/src/codex/catalog/reserve.ts +52 -0
  84. package/src/codex/catalog/sync.ts +89 -16
  85. package/src/codex/catalog.ts +1 -1
  86. package/src/codex/convergence-types.ts +1 -0
  87. package/src/codex/convergence.ts +2 -0
  88. package/src/codex/data/upstream-models.json +169 -0
  89. package/src/codex/forward-transport-headers.ts +25 -0
  90. package/src/codex/inject.ts +99 -34
  91. package/src/codex/injected-marker.ts +30 -4
  92. package/src/codex/journal.ts +14 -0
  93. package/src/codex/legacy-config-keys.ts +68 -0
  94. package/src/codex/log-guard/inspect-schema.ts +137 -0
  95. package/src/codex/log-guard/inspect.ts +2 -134
  96. package/src/codex/loopback-target.ts +54 -0
  97. package/src/codex/main-account-cache.ts +63 -1
  98. package/src/codex/main-account-hard-lock.ts +52 -0
  99. package/src/codex/main-account.ts +3 -1
  100. package/src/codex/management-convergence.ts +3 -0
  101. package/src/codex/model-entitlements.ts +54 -4
  102. package/src/codex/project-config-warnings.ts +92 -2
  103. package/src/codex/prompt-layers/encoding.ts +80 -0
  104. package/src/codex/prompt-layers/paths.ts +54 -0
  105. package/src/codex/prompt-layers/revision.ts +55 -0
  106. package/src/codex/prompt-layers/toml-edit.ts +163 -0
  107. package/src/codex/prompt-layers/toml-read.ts +181 -0
  108. package/src/codex/prompt-layers.ts +14 -520
  109. package/src/codex/quota-auto-refresh-state.ts +16 -0
  110. package/src/codex/quota-auto-refresh.ts +219 -0
  111. package/src/codex/quota-types.ts +51 -0
  112. package/src/codex/quota.ts +252 -93
  113. package/src/codex/reserve-availability.ts +177 -0
  114. package/src/codex/routing.ts +28 -9
  115. package/src/codex/shim.ts +53 -11
  116. package/src/codex/subagent-model-fallback.ts +23 -3
  117. package/src/combos/failover.ts +125 -7
  118. package/src/combos/identifiers.ts +89 -0
  119. package/src/combos/index.ts +4 -0
  120. package/src/combos/resolve.ts +80 -9
  121. package/src/combos/types.ts +20 -93
  122. package/src/config/subagent-models.ts +24 -0
  123. package/src/config.ts +156 -13
  124. package/src/generated/compatibility-version.json +474 -178
  125. package/src/generated/model-metadata.ts +1 -1
  126. package/src/integrations/journal.ts +65 -4
  127. package/src/integrations/store.ts +5 -0
  128. package/src/lab/events/limits.ts +4 -0
  129. package/src/lib/destination-policy.ts +31 -2
  130. package/src/lib/errors.ts +39 -0
  131. package/src/lib/provider-outbound.ts +69 -3
  132. package/src/lib/proxy-env.ts +22 -0
  133. package/src/lib/redact-folding.ts +176 -0
  134. package/src/lib/redact.ts +2 -175
  135. package/src/lib/state-store-sweeper.ts +20 -6
  136. package/src/lib/token-estimate.ts +94 -27
  137. package/src/lib/windows-user-principal.ts +53 -5
  138. package/src/oauth/account-quota-rank.ts +40 -1
  139. package/src/oauth/anthropic-routing.ts +99 -3
  140. package/src/oauth/chatgpt-device.ts +187 -0
  141. package/src/oauth/chatgpt.ts +31 -4
  142. package/src/oauth/generic-account-failover.ts +36 -13
  143. package/src/oauth/index.ts +140 -29
  144. package/src/oauth/log.ts +3 -0
  145. package/src/oauth/login-cli.ts +5 -0
  146. package/src/oauth/meta-muse.ts +117 -15
  147. package/src/oauth/pool-settings-capability.ts +15 -4
  148. package/src/providers/api-keys.ts +8 -10
  149. package/src/providers/default-aliases.ts +39 -0
  150. package/src/providers/derive.ts +10 -2
  151. package/src/providers/fastwire.ts +36 -7
  152. package/src/providers/initial-model-selection-runtime.ts +90 -0
  153. package/src/providers/initial-model-selection.ts +120 -0
  154. package/src/providers/key-failover.ts +134 -54
  155. package/src/providers/key-store.ts +11 -1
  156. package/src/providers/label.ts +1 -1
  157. package/src/providers/model-discovery.ts +76 -0
  158. package/src/providers/model-rename-startup.ts +72 -8
  159. package/src/providers/muse-subscription-usage.ts +95 -0
  160. package/src/providers/openai-sidecar.ts +17 -5
  161. package/src/providers/openai-tiers-destination.ts +102 -0
  162. package/src/providers/openai-tiers.ts +2 -99
  163. package/src/providers/opencode-go-transport.ts +41 -0
  164. package/src/providers/quota-key-accounts.ts +141 -0
  165. package/src/providers/quota-types.ts +9 -0
  166. package/src/providers/quota.ts +625 -98
  167. package/src/providers/registry.ts +60 -17
  168. package/src/providers/xai-responses-opt-in.ts +31 -5
  169. package/src/quota/reset-activation.ts +81 -0
  170. package/src/quota/reset-detector.ts +305 -0
  171. package/src/quota/reset-notify-config.ts +162 -0
  172. package/src/quota/reset-observer.ts +125 -0
  173. package/src/quota/reset-poller.ts +160 -0
  174. package/src/quota/reset-seen-store.ts +385 -0
  175. package/src/quota/reset-sinks.ts +199 -0
  176. package/src/quota/window-mapping.ts +106 -0
  177. package/src/responses/apply-patch-envelope.ts +46 -0
  178. package/src/responses/code-mode-helper-compat.ts +39 -1
  179. package/src/responses/custom-tool-compat.ts +10 -4
  180. package/src/responses/hosted-tool-policy.ts +12 -4
  181. package/src/responses/parser-content.ts +133 -0
  182. package/src/responses/parser-text-format.ts +24 -0
  183. package/src/responses/parser-tools.ts +188 -0
  184. package/src/responses/parser.ts +3 -326
  185. package/src/responses/state.ts +124 -28
  186. package/src/router.ts +48 -13
  187. package/src/routing/analytics.ts +1 -0
  188. package/src/routing/capability.ts +17 -4
  189. package/src/server/auth-cors.ts +7 -1
  190. package/src/server/background-lifecycle.ts +23 -1
  191. package/src/server/chat-completions.ts +25 -3
  192. package/src/server/claude-messages.ts +62 -5
  193. package/src/server/effort-row.ts +1 -1
  194. package/src/server/fast-row.ts +295 -0
  195. package/src/server/gui-static.ts +30 -4
  196. package/src/server/index.ts +122 -28
  197. package/src/server/live.ts +18 -4
  198. package/src/server/management/agent-settings-routes.ts +2 -2
  199. package/src/server/management/combo-routes.ts +37 -9
  200. package/src/server/management/config-routes.ts +93 -2
  201. package/src/server/management/integration-routes.ts +108 -0
  202. package/src/server/management/model-routes.ts +13 -3
  203. package/src/server/management/model-rows.ts +20 -1
  204. package/src/server/management/native-integration-routes.ts +4 -1
  205. package/src/server/management/oauth-account-routes.ts +45 -10
  206. package/src/server/management/provider-routes.ts +34 -3
  207. package/src/server/management/quota-reset-routes.ts +57 -0
  208. package/src/server/management/route-registry.ts +7 -4
  209. package/src/server/management/shared.ts +19 -5
  210. package/src/server/management/system-routes.ts +3 -2
  211. package/src/server/management-api.ts +14 -2
  212. package/src/server/ports.ts +12 -2
  213. package/src/server/relay-eager.ts +38 -23
  214. package/src/server/relay.ts +4 -0
  215. package/src/server/request-log.ts +6 -0
  216. package/src/server/responses/codex-ws-correlation.ts +65 -0
  217. package/src/server/responses/codex-ws-exchange.ts +261 -0
  218. package/src/server/responses/codex-ws-metadata.ts +134 -0
  219. package/src/server/responses/codex-ws-pool.ts +162 -0
  220. package/src/server/responses/codex-ws-request.ts +87 -0
  221. package/src/server/responses/codex-ws-session.ts +93 -0
  222. package/src/server/responses/codex-ws-wire.ts +144 -0
  223. package/src/server/responses/collaboration.ts +41 -1
  224. package/src/server/responses/compact.ts +105 -12
  225. package/src/server/responses/core.ts +510 -57
  226. package/src/server/responses/empty-completion-guard.ts +4 -0
  227. package/src/server/responses/fetch-helpers.ts +10 -3
  228. package/src/server/responses/input-admission.ts +16 -9
  229. package/src/server/responses/responses-field-backfill.ts +1 -1
  230. package/src/server/responses/ws-upstream.ts +34 -318
  231. package/src/server/responses-custom-tool-repair.ts +20 -4
  232. package/src/server/responses-undeclared-tool-guard.ts +100 -8
  233. package/src/server/safe-response-headers.ts +23 -0
  234. package/src/server/search.ts +9 -0
  235. package/src/server/subagent-models-startup.ts +27 -0
  236. package/src/server/system-env-shell.ts +238 -0
  237. package/src/server/system-env.ts +7 -234
  238. package/src/server/ws-bridge.ts +3 -25
  239. package/src/server/xai-responses-startup.ts +21 -0
  240. package/src/service-manager-probe.ts +1 -1
  241. package/src/service.ts +55 -16
  242. package/src/types/config.ts +108 -12
  243. package/src/types/provider.ts +36 -7
  244. package/src/types/request.ts +8 -0
  245. package/src/types/tools.ts +26 -1
  246. package/src/types.ts +2 -0
  247. package/src/update/notify.ts +8 -2
  248. package/src/usage/cost.ts +38 -28
  249. package/src/usage/expected-prices.ts +34 -15
  250. package/src/usage/log.ts +2 -0
  251. package/src/usage/model-identity.ts +26 -0
  252. package/src/usage/summary.ts +15 -1
  253. package/src/vision/describe.ts +6 -0
  254. package/src/vision/image-rewrite.ts +108 -0
  255. package/src/vision/index.ts +19 -306
  256. package/src/vision/plan.ts +205 -0
  257. package/src/web-search/executor.ts +6 -0
  258. package/src/web-search/index.ts +8 -1
  259. package/gui/dist/assets/index-B2YjLA-i.css +0 -1
  260. package/gui/dist/assets/index-aPup8CKb.js +0 -112
@@ -0,0 +1,181 @@
1
+ import { OCX_SECTION_MARKER } from "../injected-marker";
2
+ import { decodeBasicString } from "./encoding";
3
+
4
+ /**
5
+ * Decoded string entries of a root-scope TOML array.
6
+ *
7
+ * Parsed, not pattern-matched. Three successive review rounds each found another
8
+ * valid spelling a hand-rolled reader missed — multi-line arrays, a comment after the
9
+ * opening bracket, a quoted key — and every miss was a rendered document whose edits
10
+ * moved no admission key. The pattern was the defect: TOML is not a line format, so
11
+ * no regex over lines can enumerate what a parser accepts.
12
+ *
13
+ * The module header's warning about JS TOML parsers does apply here, and a review
14
+ * round proved it against an earlier version of this comment that claimed otherwise.
15
+ * Bun rejects an entire document containing an integer outside JavaScript's safe
16
+ * range, such as `model_context_window = 9223372036854775807`, which Rust accepts as
17
+ * an ordinary `i64`. A whole-document parse turned that into BOTH arrays disappearing
18
+ * — a worse failure than any single missed spelling, and one the old regex did not
19
+ * have.
20
+ *
21
+ * So the parse is the preferred reader, not the only one. When it fails, the scan
22
+ * below runs, and it is deliberately loose: it accepts any spelling it recognises and
23
+ * over-reports rather than under-reports, because an extra hashed filename costs one
24
+ * redundant probe while a missing one costs stale text.
25
+ */
26
+ export function rootArrayEntries(configBytes: string | null, key: string): string[] {
27
+ const value = rootValue(configBytes, key);
28
+ if (value === PARSE_FAILED) return scanRootArrayEntries(configBytes, key);
29
+ if (!Array.isArray(value)) return [];
30
+ return value.filter((entry): entry is string => typeof entry === "string");
31
+ }
32
+
33
+ /**
34
+ * Distinguishes "the parser could not read this file" from "the key is absent".
35
+ * Collapsing the two is what made an unrelated large integer silently empty the
36
+ * project-document set.
37
+ */
38
+ const PARSE_FAILED = Symbol("toml-parse-failed");
39
+
40
+ /** A root-scope value, `undefined` when the key is absent, `PARSE_FAILED` when the file will not parse. */
41
+ function rootValue(configBytes: string | null, key: string): unknown {
42
+ if (configBytes === null) return undefined;
43
+ let parsed: unknown;
44
+ try {
45
+ parsed = Bun.TOML.parse(configBytes);
46
+ } catch {
47
+ return PARSE_FAILED;
48
+ }
49
+ if (typeof parsed !== "object" || parsed === null) return PARSE_FAILED;
50
+ return (parsed as Record<string, unknown>)[key];
51
+ }
52
+
53
+ /**
54
+ * Fallback reader for a config this parser will not accept but Codex will.
55
+ *
56
+ * Not a second attempt at being a TOML parser — that approach failed three review
57
+ * rounds. It is a deliberately over-eager scan: it takes the first bracketed group for
58
+ * the key under either spelling, spans lines, strips comments, and keeps anything that
59
+ * decodes. Over-reporting is the safe direction here.
60
+ */
61
+ function scanRootArrayEntries(configBytes: string | null, key: string): string[] {
62
+ const lines = rootLines(configBytes ?? "");
63
+ const opener = new RegExp(`^\\s*"?${key}"?\\s*=\\s*\\[(.*)$`);
64
+ for (let i = 0; i < lines.length; i += 1) {
65
+ const m = opener.exec(lines[i]!);
66
+ if (!m) continue;
67
+ let body = m[1]!.replace(/#.*$/, "");
68
+ for (let j = i; !body.includes("]"); ) {
69
+ j += 1;
70
+ if (j >= lines.length) return [];
71
+ body += lines[j]!.replace(/#.*$/, "");
72
+ }
73
+ const out: string[] = [];
74
+ for (const raw of body.slice(0, body.indexOf("]")).split(",")) {
75
+ const trimmed = raw.trim();
76
+ if (trimmed === "") continue;
77
+ const decoded = trimmed.startsWith("'") && trimmed.endsWith("'") && trimmed.length >= 2
78
+ ? trimmed.slice(1, -1)
79
+ : decodeBasicString(trimmed);
80
+ if (decoded !== null) out.push(decoded);
81
+ }
82
+ return out;
83
+ }
84
+ return [];
85
+ }
86
+
87
+ /**
88
+ * Whether a root-scope key is present at all, regardless of what it holds.
89
+ *
90
+ * A parse failure is not an answer, so it falls through to the scan rather than
91
+ * counting as present: reading `PARSE_FAILED` as "present" would report an empty
92
+ * marker list and disable root detection on a config Codex reads fine.
93
+ */
94
+ export function hasRootKey(configBytes: string | null, key: string): boolean {
95
+ const value = rootValue(configBytes, key);
96
+ if (value === PARSE_FAILED) return scanHasRootKey(configBytes, key);
97
+ return value !== undefined;
98
+ }
99
+
100
+ /** Textual presence check, used only when the parser cannot read the file. */
101
+ function scanHasRootKey(configBytes: string | null, key: string): boolean {
102
+ const probe = new RegExp(`^\\s*"?${key}"?\\s*=`);
103
+ return rootLines(configBytes ?? "").some(line => probe.test(line));
104
+ }
105
+
106
+ // ---------------------------------------------------------------------------
107
+ // Scoped TOML scanning. Line-based like `features.ts:80-93`: booleans need no
108
+ // escaping, and line editing preserves the user's comments and formatting
109
+ // exactly where a re-serialize would not.
110
+ // ---------------------------------------------------------------------------
111
+
112
+ export const TABLE_HEADER = /^\s*\[/;
113
+
114
+ /** Lines of the root scope: everything before the first `[table]` header. */
115
+ export function rootLines(content: string): string[] {
116
+ const lines = content.split("\n");
117
+ const first = lines.findIndex(l => TABLE_HEADER.test(l));
118
+ return first === -1 ? lines : lines.slice(0, first);
119
+ }
120
+
121
+ /** Lines of `[header]`'s body, up to the next table header. */
122
+ export function tableLines(content: string, header: string): string[] | null {
123
+ const lines = content.split("\n");
124
+ const escaped = header.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
125
+ const start = lines.findIndex(l => new RegExp(`^\\s*\\[${escaped}\\]\\s*(?:#.*)?$`).test(l));
126
+ if (start === -1) return null;
127
+ const rest = lines.slice(start + 1);
128
+ const end = rest.findIndex(l => TABLE_HEADER.test(l));
129
+ return end === -1 ? rest : rest.slice(0, end);
130
+ }
131
+
132
+ export function boolInLines(lines: string[], key: string): boolean | null {
133
+ const escaped = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
134
+ const pattern = new RegExp(`^\\s*${escaped}\\s*=\\s*(true|false)\\s*(?:#.*)?$`);
135
+ for (const line of lines) {
136
+ const m = pattern.exec(line);
137
+ if (m) return m[1] === "true";
138
+ }
139
+ return null;
140
+ }
141
+
142
+ // ---------------------------------------------------------------------------
143
+ // Ownership of the generated projection.
144
+ //
145
+ // Canonical physical form, always exactly two lines at the top of the document:
146
+ //
147
+ // # Auto-injected by opencodex
148
+ // developer_instructions = "<single-line basic string>"
149
+ //
150
+ // Replacement is "find the marker, replace the next line" — never a span search.
151
+ // Adjacency mirrors `injected-marker.ts:53-60`, tightened by a shape check.
152
+ // ---------------------------------------------------------------------------
153
+
154
+ export const DEV_INSTRUCTIONS_KEY = "developer_instructions";
155
+ const CANONICAL_LINE = /^developer_instructions = "(?:[^"\\]|\\.)*"$/;
156
+ export const ANY_DEV_INSTRUCTIONS = /^\s*(?:developer_instructions|"developer_instructions"|'developer_instructions')\s*=/;
157
+
158
+ export type Ownership =
159
+ /** no such key anywhere in the root scope */
160
+ | { state: "absent" }
161
+ /** marker-adjacent and canonically shaped: ours to rewrite */
162
+ | { state: "owned"; line: number; literal: string }
163
+ /** marker-adjacent but reshaped: refuse, offer repair */
164
+ | { state: "owned-malformed"; line: number; raw: string }
165
+ /** no marker: externally authored, refuse and offer adoption */
166
+ | { state: "external"; line: number; raw: string };
167
+
168
+ export function inspectOwnership(configBytes: string | null): Ownership {
169
+ if (configBytes === null) return { state: "absent" };
170
+ const lines = rootLines(configBytes);
171
+ for (let i = 0; i < lines.length; i += 1) {
172
+ const raw = lines[i]!;
173
+ if (!ANY_DEV_INSTRUCTIONS.test(raw)) continue;
174
+ const marked = i > 0 && lines[i - 1]!.includes(OCX_SECTION_MARKER);
175
+ if (!marked) return { state: "external", line: i + 1, raw };
176
+ if (!CANONICAL_LINE.test(raw)) return { state: "owned-malformed", line: i + 1, raw };
177
+ const literal = raw.slice(`${DEV_INSTRUCTIONS_KEY} = `.length);
178
+ return { state: "owned", line: i + 1, literal };
179
+ }
180
+ return { state: "absent" };
181
+ }