presubmit 0.1.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 (220) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +51 -0
  3. package/THIRD_PARTY_NOTICES.md +24 -0
  4. package/apps/web/dist/assets/FileCode-CZZH52o7.js +5 -0
  5. package/apps/web/dist/assets/FileCode-DovDO7Jh.css +1 -0
  6. package/apps/web/dist/assets/SettingsPage-CRvOwdjt.js +4 -0
  7. package/apps/web/dist/assets/SettingsPage-UbYSCwJj.css +1 -0
  8. package/apps/web/dist/assets/TerminalPanel-0sw-J6YS.css +1 -0
  9. package/apps/web/dist/assets/TerminalPanel-BqUjPWav.js +16 -0
  10. package/apps/web/dist/assets/index-BhqNNFja.js +54 -0
  11. package/apps/web/dist/assets/index-DD8VXy8H.css +1 -0
  12. package/apps/web/dist/assets/presubmit-mark-BBQ19Fmr.svg +7 -0
  13. package/apps/web/dist/assets/presubmit-mark-busy-CwBC-7on.svg +8 -0
  14. package/apps/web/dist/assets/react-vendor-wiHys0m2.js +9 -0
  15. package/apps/web/dist/assets/rolldown-runtime-hePW80VL.js +1 -0
  16. package/apps/web/dist/index.html +6 -0
  17. package/apps/web/dist/service-worker.js +11 -0
  18. package/dist/apps/server/src/agent-builder.js +204 -0
  19. package/dist/apps/server/src/attach.js +163 -0
  20. package/dist/apps/server/src/attachments.js +86 -0
  21. package/dist/apps/server/src/browser-access.js +131 -0
  22. package/dist/apps/server/src/check-provenance.js +95 -0
  23. package/dist/apps/server/src/check-supervisor.js +112 -0
  24. package/dist/apps/server/src/checks.js +402 -0
  25. package/dist/apps/server/src/child-collaboration-guidance.js +2 -0
  26. package/dist/apps/server/src/child-sessions.js +191 -0
  27. package/dist/apps/server/src/cli.js +162 -0
  28. package/dist/apps/server/src/conversation-search.js +12 -0
  29. package/dist/apps/server/src/coordinator-messages.js +72 -0
  30. package/dist/apps/server/src/dev-auth.js +54 -0
  31. package/dist/apps/server/src/dev-server.js +201 -0
  32. package/dist/apps/server/src/dev-worker.js +48 -0
  33. package/dist/apps/server/src/diagnostics.js +105 -0
  34. package/dist/apps/server/src/fast-mode.js +8 -0
  35. package/dist/apps/server/src/folder-picker.js +54 -0
  36. package/dist/apps/server/src/git-blobs.js +62 -0
  37. package/dist/apps/server/src/git-handoff.js +127 -0
  38. package/dist/apps/server/src/history-sources.js +59 -0
  39. package/dist/apps/server/src/hub.js +159 -0
  40. package/dist/apps/server/src/internal-transport.js +38 -0
  41. package/dist/apps/server/src/local-embeddings.js +70 -0
  42. package/dist/apps/server/src/ollama-setup.js +56 -0
  43. package/dist/apps/server/src/planning.js +30 -0
  44. package/dist/apps/server/src/project-agents.js +276 -0
  45. package/dist/apps/server/src/project-memory.js +94 -0
  46. package/dist/apps/server/src/projects.js +106 -0
  47. package/dist/apps/server/src/queued-launch.js +13 -0
  48. package/dist/apps/server/src/reply-search.js +172 -0
  49. package/dist/apps/server/src/review-context.js +60 -0
  50. package/dist/apps/server/src/review-refresh.js +14 -0
  51. package/dist/apps/server/src/reviewers.js +75 -0
  52. package/dist/apps/server/src/search-settings.js +22 -0
  53. package/dist/apps/server/src/semantic-history.js +186 -0
  54. package/dist/apps/server/src/server.js +4338 -0
  55. package/dist/apps/server/src/session-changes.js +181 -0
  56. package/dist/apps/server/src/session-router-settings.js +198 -0
  57. package/dist/apps/server/src/session-workspaces.js +135 -0
  58. package/dist/apps/server/src/sessions.js +579 -0
  59. package/dist/apps/server/src/shared-auth.js +70 -0
  60. package/dist/apps/server/src/shell-evaluator-settings.js +53 -0
  61. package/dist/apps/server/src/store.js +203 -0
  62. package/dist/apps/server/src/tailscale-process.js +115 -0
  63. package/dist/apps/server/src/tailscale-serve-worker.js +33 -0
  64. package/dist/apps/server/src/tailscale-serve.js +276 -0
  65. package/dist/apps/server/src/task-capacity.js +92 -0
  66. package/dist/apps/server/src/task-graph.js +190 -0
  67. package/dist/apps/server/src/task-logs.js +74 -0
  68. package/dist/apps/server/src/task-numbers.js +25 -0
  69. package/dist/apps/server/src/task-orchestrator.js +1088 -0
  70. package/dist/apps/server/src/terminal.js +182 -0
  71. package/dist/apps/server/src/terminals.js +80 -0
  72. package/dist/apps/server/src/tool-safety.js +2 -0
  73. package/dist/apps/server/src/workspace-lock.js +140 -0
  74. package/dist/apps/server/src/workspace-watcher.js +65 -0
  75. package/dist/apps/server/src/workspace.js +517 -0
  76. package/dist/packages/agent-pi/src/agent-builder-tool.js +32 -0
  77. package/dist/packages/agent-pi/src/agent-capabilities.js +44 -0
  78. package/dist/packages/agent-pi/src/ask-user.js +86 -0
  79. package/dist/packages/agent-pi/src/auth.js +510 -0
  80. package/dist/packages/agent-pi/src/check-tools.js +72 -0
  81. package/dist/packages/agent-pi/src/command-policy.js +246 -0
  82. package/dist/packages/agent-pi/src/coordinator-tools.js +122 -0
  83. package/dist/packages/agent-pi/src/fast-mode.js +67 -0
  84. package/dist/packages/agent-pi/src/file-tools.js +163 -0
  85. package/dist/packages/agent-pi/src/history-tool.js +40 -0
  86. package/dist/packages/agent-pi/src/history.js +34 -0
  87. package/dist/packages/agent-pi/src/index.js +177 -0
  88. package/dist/packages/agent-pi/src/ipc.js +314 -0
  89. package/dist/packages/agent-pi/src/jev-session-router.js +408 -0
  90. package/dist/packages/agent-pi/src/jev-tools.js +71 -0
  91. package/dist/packages/agent-pi/src/local-model.js +277 -0
  92. package/dist/packages/agent-pi/src/memory-tools.js +119 -0
  93. package/dist/packages/agent-pi/src/model.js +25 -0
  94. package/dist/packages/agent-pi/src/planning.js +206 -0
  95. package/dist/packages/agent-pi/src/resource-loader.js +23 -0
  96. package/dist/packages/agent-pi/src/review-tools.js +158 -0
  97. package/dist/packages/agent-pi/src/review-transition.js +73 -0
  98. package/dist/packages/agent-pi/src/review.js +40 -0
  99. package/dist/packages/agent-pi/src/routing.js +27 -0
  100. package/dist/packages/agent-pi/src/session-setup.js +118 -0
  101. package/dist/packages/agent-pi/src/shell-context.js +51 -0
  102. package/dist/packages/agent-pi/src/shell-policy.js +281 -0
  103. package/dist/packages/agent-pi/src/shell-safety.js +205 -0
  104. package/dist/packages/agent-pi/src/shell.js +121 -0
  105. package/dist/packages/agent-pi/src/snapshot-permissions.js +12 -0
  106. package/dist/packages/agent-pi/src/spike.js +41 -0
  107. package/dist/packages/agent-pi/src/task-tools.js +53 -0
  108. package/dist/packages/agent-pi/src/types.js +1 -0
  109. package/dist/packages/agent-pi/src/usage.js +30 -0
  110. package/dist/packages/agent-pi/src/worker.js +602 -0
  111. package/dist/packages/protocol/src/activity-summary.js +77 -0
  112. package/dist/packages/protocol/src/agents.js +301 -0
  113. package/dist/packages/protocol/src/browser-access.js +1 -0
  114. package/dist/packages/protocol/src/checks.js +40 -0
  115. package/dist/packages/protocol/src/child-sessions.js +28 -0
  116. package/dist/packages/protocol/src/command-policy.js +3 -0
  117. package/dist/packages/protocol/src/coordinator.js +135 -0
  118. package/dist/packages/protocol/src/delegation.js +40 -0
  119. package/dist/packages/protocol/src/git-diff.js +71 -0
  120. package/dist/packages/protocol/src/git-handoff.js +1 -0
  121. package/dist/packages/protocol/src/index.js +1 -0
  122. package/dist/packages/protocol/src/memory.js +46 -0
  123. package/dist/packages/protocol/src/metrics.js +70 -0
  124. package/dist/packages/protocol/src/planning.js +138 -0
  125. package/dist/packages/protocol/src/retrieval.js +36 -0
  126. package/dist/packages/protocol/src/reviewers.js +17 -0
  127. package/dist/packages/protocol/src/search.js +16 -0
  128. package/dist/packages/protocol/src/session-changes.js +29 -0
  129. package/dist/packages/protocol/src/session-router.js +123 -0
  130. package/dist/packages/protocol/src/shell-evaluator.js +43 -0
  131. package/dist/packages/protocol/src/task-graph.js +1 -0
  132. package/dist/packages/protocol/src/token-usage.js +17 -0
  133. package/dist/packages/protocol/src/user-questions.js +106 -0
  134. package/package.json +71 -0
  135. package/vendor/lancedb/NODEJS_THIRD_PARTY_LICENSES.md +668 -0
  136. package/vendor/lancedb/RUST_THIRD_PARTY_LICENSES.html +14607 -0
  137. package/vendor/lancedb/dist/arrow.d.ts +296 -0
  138. package/vendor/lancedb/dist/arrow.js +1145 -0
  139. package/vendor/lancedb/dist/arrow_type.d.ts +9 -0
  140. package/vendor/lancedb/dist/arrow_type.js +29 -0
  141. package/vendor/lancedb/dist/connection.d.ts +508 -0
  142. package/vendor/lancedb/dist/connection.js +298 -0
  143. package/vendor/lancedb/dist/embedding/embedding_function.d.ts +103 -0
  144. package/vendor/lancedb/dist/embedding/embedding_function.js +192 -0
  145. package/vendor/lancedb/dist/embedding/index.d.ts +37 -0
  146. package/vendor/lancedb/dist/embedding/index.js +108 -0
  147. package/vendor/lancedb/dist/embedding/openai.d.ts +16 -0
  148. package/vendor/lancedb/dist/embedding/openai.js +81 -0
  149. package/vendor/lancedb/dist/embedding/registry.d.ts +94 -0
  150. package/vendor/lancedb/dist/embedding/registry.js +221 -0
  151. package/vendor/lancedb/dist/embedding/transformers.d.ts +36 -0
  152. package/vendor/lancedb/dist/embedding/transformers.js +110 -0
  153. package/vendor/lancedb/dist/header.d.ts +162 -0
  154. package/vendor/lancedb/dist/header.js +217 -0
  155. package/vendor/lancedb/dist/index.d.ts +246 -0
  156. package/vendor/lancedb/dist/index.js +176 -0
  157. package/vendor/lancedb/dist/indices.d.ts +721 -0
  158. package/vendor/lancedb/dist/indices.js +166 -0
  159. package/vendor/lancedb/dist/materialized_view.d.ts +69 -0
  160. package/vendor/lancedb/dist/materialized_view.js +112 -0
  161. package/vendor/lancedb/dist/merge.d.ts +104 -0
  162. package/vendor/lancedb/dist/merge.js +120 -0
  163. package/vendor/lancedb/dist/native.d.ts +1193 -0
  164. package/vendor/lancedb/dist/native.js +688 -0
  165. package/vendor/lancedb/dist/oauth.d.ts +66 -0
  166. package/vendor/lancedb/dist/oauth.js +15 -0
  167. package/vendor/lancedb/dist/otel.d.ts +26 -0
  168. package/vendor/lancedb/dist/otel.js +114 -0
  169. package/vendor/lancedb/dist/permutation.d.ts +143 -0
  170. package/vendor/lancedb/dist/permutation.js +184 -0
  171. package/vendor/lancedb/dist/query.d.ts +663 -0
  172. package/vendor/lancedb/dist/query.js +966 -0
  173. package/vendor/lancedb/dist/rerankers/index.d.ts +5 -0
  174. package/vendor/lancedb/dist/rerankers/index.js +19 -0
  175. package/vendor/lancedb/dist/rerankers/rrf.d.ts +14 -0
  176. package/vendor/lancedb/dist/rerankers/rrf.js +28 -0
  177. package/vendor/lancedb/dist/sanitize.d.ts +32 -0
  178. package/vendor/lancedb/dist/sanitize.js +544 -0
  179. package/vendor/lancedb/dist/scannable.d.ts +92 -0
  180. package/vendor/lancedb/dist/scannable.js +200 -0
  181. package/vendor/lancedb/dist/schema.d.ts +16 -0
  182. package/vendor/lancedb/dist/schema.js +387 -0
  183. package/vendor/lancedb/dist/table.d.ts +1069 -0
  184. package/vendor/lancedb/dist/table.js +498 -0
  185. package/vendor/lancedb/dist/util.d.ts +14 -0
  186. package/vendor/lancedb/dist/util.js +77 -0
  187. package/vendor/lancedb/license_header.txt +2 -0
  188. package/vendor/lancedb/package.json +56 -0
  189. package/vendor/transformers/LICENSE +202 -0
  190. package/vendor/transformers/dist/transformers.cjs +30844 -0
  191. package/vendor/transformers/dist/transformers.mjs +31404 -0
  192. package/vendor/transformers/package.json +55 -0
  193. package/vendor/transformers/types/backends/onnx.d.ts +30 -0
  194. package/vendor/transformers/types/configs.d.ts +85 -0
  195. package/vendor/transformers/types/env.d.ts +110 -0
  196. package/vendor/transformers/types/generation/configuration_utils.d.ts +320 -0
  197. package/vendor/transformers/types/generation/logits_process.d.ts +354 -0
  198. package/vendor/transformers/types/generation/logits_sampler.d.ts +51 -0
  199. package/vendor/transformers/types/generation/parameters.d.ts +47 -0
  200. package/vendor/transformers/types/generation/stopping_criteria.d.ts +81 -0
  201. package/vendor/transformers/types/generation/streamers.d.ts +81 -0
  202. package/vendor/transformers/types/models/whisper/common_whisper.d.ts +8 -0
  203. package/vendor/transformers/types/models/whisper/generation_whisper.d.ts +76 -0
  204. package/vendor/transformers/types/models.d.ts +3684 -0
  205. package/vendor/transformers/types/ops/registry.d.ts +11 -0
  206. package/vendor/transformers/types/pipelines.d.ts +2402 -0
  207. package/vendor/transformers/types/processors.d.ts +924 -0
  208. package/vendor/transformers/types/tokenizers.d.ts +990 -0
  209. package/vendor/transformers/types/transformers.d.ts +13 -0
  210. package/vendor/transformers/types/utils/audio.d.ts +130 -0
  211. package/vendor/transformers/types/utils/constants.d.ts +2 -0
  212. package/vendor/transformers/types/utils/core.d.ts +98 -0
  213. package/vendor/transformers/types/utils/data-structures.d.ts +236 -0
  214. package/vendor/transformers/types/utils/devices.d.ts +18 -0
  215. package/vendor/transformers/types/utils/dtypes.d.ts +19 -0
  216. package/vendor/transformers/types/utils/generic.d.ts +11 -0
  217. package/vendor/transformers/types/utils/hub.d.ts +152 -0
  218. package/vendor/transformers/types/utils/image.d.ts +119 -0
  219. package/vendor/transformers/types/utils/maths.d.ts +280 -0
  220. package/vendor/transformers/types/utils/tensor.d.ts +418 -0
@@ -0,0 +1,92 @@
1
+ import { Table as ArrowTable, RecordBatch, RecordBatchReader, Schema } from "apache-arrow";
2
+ import { NapiScannable } from "./native.js";
3
+ export interface ScannableOptions {
4
+ /** Hint about the number of rows. Not validated against the stream. */
5
+ numRows?: number;
6
+ /**
7
+ * Whether the source can be scanned more than once. Defaults to `true` for
8
+ * `fromTable` / `fromFactory` and `false` for `fromIterable` /
9
+ * `fromRecordBatchReader`.
10
+ */
11
+ rescannable?: boolean;
12
+ }
13
+ /**
14
+ * A data source that can be scanned as a stream of Arrow `RecordBatch`es.
15
+ *
16
+ * `Scannable` wraps the schema + optional row count + rescannable flag and
17
+ * a callback that yields batches one at a time. It is passed to consumers
18
+ * (e.g. `Table.add`, `createTable`, `mergeInsert` — follow-up work) that
19
+ * need to pull data without materializing the full dataset in JS memory.
20
+ *
21
+ * Batches cross the JS↔Rust boundary as Arrow IPC Stream messages; a fresh
22
+ * writer serializes each batch, and the Rust side decodes it with
23
+ * `arrow_ipc::reader::StreamReader`. One batch is in flight at a time.
24
+ */
25
+ export declare class Scannable {
26
+ readonly schema: Schema;
27
+ readonly numRows: number | null;
28
+ readonly rescannable: boolean;
29
+ /** @hidden */
30
+ private readonly native;
31
+ private constructor();
32
+ /** @hidden Access the native handle for passing through to Rust consumers. */
33
+ get inner(): NapiScannable;
34
+ /**
35
+ * Build a Scannable from an explicit schema and a factory that returns a
36
+ * fresh batch iterator on each call.
37
+ *
38
+ * The factory is invoked once per scan. Each iterator yields
39
+ * `RecordBatch`es matching the declared schema. Use this when you need
40
+ * direct control over the pull loop — for example, to wrap a streaming
41
+ * source whose batches are produced lazily.
42
+ *
43
+ * @param schema - The Arrow schema of the produced batches.
44
+ * @param factory - Called at the start of each scan to produce a batch
45
+ * iterator. Must be idempotent when `rescannable` is true.
46
+ * @param opts - Optional hints. `rescannable` defaults to `true`; set to
47
+ * `false` if calling `factory()` twice would not reproduce the same data.
48
+ */
49
+ static fromFactory(schema: Schema, factory: () => AsyncIterable<RecordBatch> | Iterable<RecordBatch> | AsyncIterator<RecordBatch> | Iterator<RecordBatch>, opts?: ScannableOptions): Promise<Scannable>;
50
+ /**
51
+ * Build a Scannable from an in-memory Arrow `Table`. Always rescannable;
52
+ * the table's batches are replayed on each scan.
53
+ *
54
+ * The table's row count is authoritative: `opts.numRows` must either be
55
+ * omitted or equal to `table.numRows`. `opts.rescannable` of `false` is
56
+ * rejected because in-memory Tables are always rescannable.
57
+ */
58
+ static fromTable(table: ArrowTable, opts?: ScannableOptions): Promise<Scannable>;
59
+ /**
60
+ * Build a Scannable from an iterable of `RecordBatch`es. `rescannable`
61
+ * defaults to `false`. Pass an explicit schema so the consumer can
62
+ * validate before any batch is pulled.
63
+ *
64
+ * `opts.rescannable: true` is honest for replayable iterables (Arrays,
65
+ * Sets, or custom iterables whose `[Symbol.iterator]()` returns a fresh
66
+ * iterator each call). It is rejected for one-shot iterables (generators,
67
+ * async generators, or already-an-iterator inputs) because their
68
+ * `[Symbol.iterator]()` returns the same exhausted object on the second
69
+ * scan. For replayable sources outside this shape, use
70
+ * `fromFactory(schema, () => createIter(), { rescannable: true })`.
71
+ *
72
+ * Note: when `opts.rescannable` is `true`, the constructor calls
73
+ * `[Symbol.iterator]()` once on the input to perform the structural check.
74
+ */
75
+ static fromIterable(schema: Schema, iter: AsyncIterable<RecordBatch> | Iterable<RecordBatch>, opts?: ScannableOptions): Promise<Scannable>;
76
+ /**
77
+ * Build a Scannable from an Arrow `RecordBatchReader`. A reader can only
78
+ * be consumed once; `rescannable` defaults to `false`.
79
+ *
80
+ * The reader must already be opened (via `.open()`) so its `.schema` is
81
+ * populated. `RecordBatchReader.from(...)` returns an unopened reader.
82
+ *
83
+ * `opts.rescannable: true` is rejected because `RecordBatchReader` is a
84
+ * self-iterator (its `[Symbol.iterator]()` returns itself), and this
85
+ * constructor does not call `reader.reset()` between scans, so a second
86
+ * scan would always see an exhausted reader. For genuinely replayable
87
+ * sources, use
88
+ * `fromFactory(schema, () => openReader(), { rescannable: true })`,
89
+ * which mints a fresh reader on each scan.
90
+ */
91
+ static fromRecordBatchReader(reader: RecordBatchReader, opts?: ScannableOptions): Promise<Scannable>;
92
+ }
@@ -0,0 +1,200 @@
1
+ "use strict";
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ // SPDX-FileCopyrightText: Copyright The LanceDB Authors
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.Scannable = void 0;
6
+ const arrow_1 = require("./arrow");
7
+ const native_js_1 = require("./native.js");
8
+ /**
9
+ * A data source that can be scanned as a stream of Arrow `RecordBatch`es.
10
+ *
11
+ * `Scannable` wraps the schema + optional row count + rescannable flag and
12
+ * a callback that yields batches one at a time. It is passed to consumers
13
+ * (e.g. `Table.add`, `createTable`, `mergeInsert` — follow-up work) that
14
+ * need to pull data without materializing the full dataset in JS memory.
15
+ *
16
+ * Batches cross the JS↔Rust boundary as Arrow IPC Stream messages; a fresh
17
+ * writer serializes each batch, and the Rust side decodes it with
18
+ * `arrow_ipc::reader::StreamReader`. One batch is in flight at a time.
19
+ */
20
+ class Scannable {
21
+ schema;
22
+ numRows;
23
+ rescannable;
24
+ /** @hidden */
25
+ native;
26
+ constructor(native, schema, numRows, rescannable) {
27
+ this.native = native;
28
+ this.schema = schema;
29
+ this.numRows = numRows;
30
+ this.rescannable = rescannable;
31
+ }
32
+ /** @hidden Access the native handle for passing through to Rust consumers. */
33
+ get inner() {
34
+ return this.native;
35
+ }
36
+ /**
37
+ * Build a Scannable from an explicit schema and a factory that returns a
38
+ * fresh batch iterator on each call.
39
+ *
40
+ * The factory is invoked once per scan. Each iterator yields
41
+ * `RecordBatch`es matching the declared schema. Use this when you need
42
+ * direct control over the pull loop — for example, to wrap a streaming
43
+ * source whose batches are produced lazily.
44
+ *
45
+ * @param schema - The Arrow schema of the produced batches.
46
+ * @param factory - Called at the start of each scan to produce a batch
47
+ * iterator. Must be idempotent when `rescannable` is true.
48
+ * @param opts - Optional hints. `rescannable` defaults to `true`; set to
49
+ * `false` if calling `factory()` twice would not reproduce the same data.
50
+ */
51
+ static async fromFactory(schema, factory, opts = {}) {
52
+ const numRows = opts.numRows ?? null;
53
+ if (numRows != null && !Number.isInteger(numRows)) {
54
+ throw new TypeError("numRows must be an integer");
55
+ }
56
+ const rescannable = opts.rescannable ?? true;
57
+ let iter = null;
58
+ const getNextBatch = async (isStart) => {
59
+ // `isStart` is true on the first pull of every new scan_as_stream.
60
+ // Drop any cached iterator so factory() is re-invoked for the next scan
61
+ if (isStart) {
62
+ iter = null;
63
+ }
64
+ if (iter === null) {
65
+ iter = normalizeIterator(factory());
66
+ }
67
+ const result = await iter.next();
68
+ if (result.done) {
69
+ iter = null;
70
+ return null;
71
+ }
72
+ return (0, arrow_1.fromRecordBatchToStreamBuffer)(result.value);
73
+ };
74
+ const schemaBuf = await (0, arrow_1.fromTableToBuffer)((0, arrow_1.makeEmptyTable)(schema));
75
+ const native = new native_js_1.NapiScannable(schemaBuf, numRows, rescannable, getNextBatch);
76
+ return new Scannable(native, schema, numRows, rescannable);
77
+ }
78
+ /**
79
+ * Build a Scannable from an in-memory Arrow `Table`. Always rescannable;
80
+ * the table's batches are replayed on each scan.
81
+ *
82
+ * The table's row count is authoritative: `opts.numRows` must either be
83
+ * omitted or equal to `table.numRows`. `opts.rescannable` of `false` is
84
+ * rejected because in-memory Tables are always rescannable.
85
+ */
86
+ static async fromTable(table, opts = {}) {
87
+ if (opts.numRows != null && opts.numRows !== table.numRows) {
88
+ throw new TypeError(`opts.numRows (${opts.numRows}) does not match table.numRows (${table.numRows}). ` +
89
+ `The table's row count is authoritative; omit numRows or pass the matching value.`);
90
+ }
91
+ if (opts.rescannable === false) {
92
+ throw new TypeError(`fromTable does not accept rescannable: false. ` +
93
+ `In-memory Arrow Tables are always rescannable; omit the option or pass true.`);
94
+ }
95
+ return Scannable.fromFactory(table.schema, () => table.batches, {
96
+ numRows: table.numRows,
97
+ rescannable: true,
98
+ });
99
+ }
100
+ /**
101
+ * Build a Scannable from an iterable of `RecordBatch`es. `rescannable`
102
+ * defaults to `false`. Pass an explicit schema so the consumer can
103
+ * validate before any batch is pulled.
104
+ *
105
+ * `opts.rescannable: true` is honest for replayable iterables (Arrays,
106
+ * Sets, or custom iterables whose `[Symbol.iterator]()` returns a fresh
107
+ * iterator each call). It is rejected for one-shot iterables (generators,
108
+ * async generators, or already-an-iterator inputs) because their
109
+ * `[Symbol.iterator]()` returns the same exhausted object on the second
110
+ * scan. For replayable sources outside this shape, use
111
+ * `fromFactory(schema, () => createIter(), { rescannable: true })`.
112
+ *
113
+ * Note: when `opts.rescannable` is `true`, the constructor calls
114
+ * `[Symbol.iterator]()` once on the input to perform the structural check.
115
+ */
116
+ static async fromIterable(schema, iter, opts = {}) {
117
+ if (opts.rescannable === true && isOneShotIterable(iter)) {
118
+ throw new TypeError(`fromIterable: rescannable: true is not honest for one-shot iterables ` +
119
+ `(generators, async generators, or iterators where [Symbol.iterator]() ` +
120
+ `returns the same object). The source would be exhausted after the first scan. ` +
121
+ `Use fromFactory(schema, () => createIter(), { rescannable: true }) for sources ` +
122
+ `where each call mints a fresh iterator.`);
123
+ }
124
+ return Scannable.fromFactory(schema, () => iter, {
125
+ numRows: opts.numRows,
126
+ rescannable: opts.rescannable ?? false,
127
+ });
128
+ }
129
+ /**
130
+ * Build a Scannable from an Arrow `RecordBatchReader`. A reader can only
131
+ * be consumed once; `rescannable` defaults to `false`.
132
+ *
133
+ * The reader must already be opened (via `.open()`) so its `.schema` is
134
+ * populated. `RecordBatchReader.from(...)` returns an unopened reader.
135
+ *
136
+ * `opts.rescannable: true` is rejected because `RecordBatchReader` is a
137
+ * self-iterator (its `[Symbol.iterator]()` returns itself), and this
138
+ * constructor does not call `reader.reset()` between scans, so a second
139
+ * scan would always see an exhausted reader. For genuinely replayable
140
+ * sources, use
141
+ * `fromFactory(schema, () => openReader(), { rescannable: true })`,
142
+ * which mints a fresh reader on each scan.
143
+ */
144
+ static async fromRecordBatchReader(reader, opts = {}) {
145
+ if (opts.rescannable === true) {
146
+ throw new TypeError(`fromRecordBatchReader does not accept rescannable: true. ` +
147
+ `RecordBatchReader is a self-iterator (its [Symbol.iterator]() ` +
148
+ `returns itself) and would be exhausted after the first scan. ` +
149
+ `Use fromFactory(schema, () => openReader(), { rescannable: true }) ` +
150
+ `for sources where each call mints a fresh reader.`);
151
+ }
152
+ return Scannable.fromFactory(reader.schema, () => reader, {
153
+ numRows: opts.numRows,
154
+ rescannable: false,
155
+ });
156
+ }
157
+ }
158
+ exports.Scannable = Scannable;
159
+ function normalizeIterator(source) {
160
+ if (source == null) {
161
+ throw new TypeError("Scannable factory returned null/undefined");
162
+ }
163
+ if (typeof source[Symbol.asyncIterator] === "function") {
164
+ return source[Symbol.asyncIterator]();
165
+ }
166
+ if (typeof source[Symbol.iterator] === "function") {
167
+ return source[Symbol.iterator]();
168
+ }
169
+ // Already an iterator (has `.next`).
170
+ if (typeof source.next === "function") {
171
+ return source;
172
+ }
173
+ throw new TypeError("Scannable factory returned a non-iterable value");
174
+ }
175
+ // A "self-iterator" returns the same object from `[Symbol.iterator]()` /
176
+ // `[Symbol.asyncIterator]()`. Generators behave this way, so they exhaust
177
+ // after one pass. Replayable iterables (Array, Set, custom) return a fresh
178
+ // iterator each call. Detection mirrors `normalizeIterator`'s ordering so
179
+ // classification matches scan-time behavior.
180
+ function isOneShotIterable(source) {
181
+ // null/undefined are not one-shot in any meaningful sense; let
182
+ // `normalizeIterator` raise the actual error at scan time.
183
+ if (source == null)
184
+ return false;
185
+ const ref = source;
186
+ if (typeof source[Symbol.asyncIterator] ===
187
+ "function") {
188
+ const it = source[Symbol.asyncIterator]();
189
+ return it === ref;
190
+ }
191
+ if (typeof source[Symbol.iterator] === "function") {
192
+ const it = source[Symbol.iterator]();
193
+ return it === ref;
194
+ }
195
+ // Already-an-iterator (has `.next` but no `Symbol.iterator`) is by
196
+ // definition one-shot.
197
+ if (typeof source.next === "function")
198
+ return true;
199
+ return false;
200
+ }
@@ -0,0 +1,16 @@
1
+ import { Schema } from "apache-arrow";
2
+ type InferenceOptions = {
3
+ dictionaryEncodeStrings: boolean;
4
+ vectorColumns: Record<string, {
5
+ type: unknown;
6
+ }>;
7
+ };
8
+ /**
9
+ * Infer the Arrow schema represented by a set of records.
10
+ *
11
+ * This is the intentionally small interface to schema inference. The stateful
12
+ * details of combining partial type evidence are encapsulated below so callers
13
+ * only need to provide records, an optional schema, and inference options.
14
+ */
15
+ export declare function inferSchema(data: Array<Record<string, unknown>>, schema: Schema | undefined, options: InferenceOptions): Schema;
16
+ export {};
@@ -0,0 +1,387 @@
1
+ "use strict";
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ // SPDX-FileCopyrightText: Copyright The LanceDB Authors
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.inferSchema = inferSchema;
6
+ const apache_arrow_1 = require("apache-arrow");
7
+ const arrow_type_1 = require("./arrow_type");
8
+ const sanitize_1 = require("./sanitize");
9
+ /**
10
+ * Infer the Arrow schema represented by a set of records.
11
+ *
12
+ * This is the intentionally small interface to schema inference. The stateful
13
+ * details of combining partial type evidence are encapsulated below so callers
14
+ * only need to provide records, an optional schema, and inference options.
15
+ */
16
+ function inferSchema(data, schema, options) {
17
+ return new SchemaInferrer(schema, options).infer(data);
18
+ }
19
+ class SchemaInferrer {
20
+ providedSchema;
21
+ options;
22
+ fields = new FieldTree();
23
+ constructor(providedSchema, options) {
24
+ this.providedSchema = providedSchema;
25
+ this.options = options;
26
+ }
27
+ infer(data) {
28
+ for (const [row, record] of data.entries()) {
29
+ for (const [path, value] of recordPathsAndValues(record)) {
30
+ this.observe(path, value, row);
31
+ }
32
+ }
33
+ return this.providedSchema === undefined
34
+ ? new apache_arrow_1.Schema(fieldsFromTree(this.fields))
35
+ : new apache_arrow_1.Schema(matchingFields(this.providedSchema.fields, this.fields));
36
+ }
37
+ observe(path, value, row) {
38
+ const current = this.fields.get(path);
39
+ if (current === undefined) {
40
+ this.addField(path, value, row);
41
+ }
42
+ else if (this.providedSchema === undefined) {
43
+ this.updateInferredField(path, value, row, current);
44
+ }
45
+ }
46
+ addField(path, value, row) {
47
+ if (this.providedSchema !== undefined) {
48
+ this.addSchemaField(this.providedSchema, path, row);
49
+ return;
50
+ }
51
+ const evidence = this.inferType(value, path) ?? DeferredTypeEvidence.from(value, row);
52
+ if (evidence === undefined) {
53
+ throw typeInferenceError(path, row);
54
+ }
55
+ const conflict = this.fields.set(path, evidence, (existing) => existing instanceof DeferredTypeEvidence && existing.isOnlyNulls());
56
+ if (conflict !== undefined) {
57
+ throw branchConflictError(conflict, row, "Struct");
58
+ }
59
+ }
60
+ addSchemaField(schema, path, row) {
61
+ const field = fieldAtPath(schema, path);
62
+ if (field === undefined) {
63
+ throw new Error(`Found field not in schema: ${path.join(".")} at row ${row}`);
64
+ }
65
+ const conflict = this.fields.set(path, field.type);
66
+ if (conflict !== undefined) {
67
+ throw branchConflictError(conflict, row, "Struct");
68
+ }
69
+ }
70
+ updateInferredField(path, value, row, current) {
71
+ const newType = this.inferType(value, path);
72
+ const deferred = DeferredTypeEvidence.from(value, row);
73
+ if (current instanceof FieldTree) {
74
+ if (deferred?.isOnlyNulls()) {
75
+ return;
76
+ }
77
+ throw schemaInferenceError(path, row, "Struct", describeEvidence(newType ?? deferred));
78
+ }
79
+ if (current instanceof DeferredTypeEvidence) {
80
+ this.resolveDeferredField(path, row, current, newType, deferred);
81
+ return;
82
+ }
83
+ if (newType !== undefined) {
84
+ if (!inferredTypesEqual(current, newType)) {
85
+ throw schemaInferenceError(path, row, describeEvidence(current), describeEvidence(newType));
86
+ }
87
+ return;
88
+ }
89
+ if (deferred === undefined || !deferred.matches(current)) {
90
+ throw schemaInferenceError(path, row, describeEvidence(current), describeEvidence(deferred));
91
+ }
92
+ }
93
+ resolveDeferredField(path, row, current, newType, deferred) {
94
+ if (newType !== undefined) {
95
+ if (!current.matches(newType)) {
96
+ throw schemaInferenceError(path, row, current.describe(), describeEvidence(newType));
97
+ }
98
+ this.fields.set(path, newType);
99
+ return;
100
+ }
101
+ if (deferred !== undefined) {
102
+ this.fields.set(path, current.merge(deferred));
103
+ return;
104
+ }
105
+ throw schemaInferenceError(path, row, current.describe(), describeEvidence(newType));
106
+ }
107
+ inferType(value, path) {
108
+ if (typeof value === "bigint") {
109
+ return new apache_arrow_1.Int64();
110
+ }
111
+ if (typeof value === "number") {
112
+ return new apache_arrow_1.Float64();
113
+ }
114
+ if (typeof value === "string") {
115
+ return this.options.dictionaryEncodeStrings
116
+ ? new apache_arrow_1.Dictionary(new apache_arrow_1.Utf8(), new apache_arrow_1.Int32())
117
+ : new apache_arrow_1.Utf8();
118
+ }
119
+ if (typeof value === "boolean") {
120
+ return new apache_arrow_1.Bool();
121
+ }
122
+ if (value instanceof Buffer) {
123
+ return new apache_arrow_1.Binary();
124
+ }
125
+ if (ArrayBuffer.isView(value) && !(value instanceof DataView)) {
126
+ const typedArray = (0, arrow_type_1.typedArrayToArrowType)(value);
127
+ return typedArray === undefined
128
+ ? undefined
129
+ : new apache_arrow_1.FixedSizeList(typedArray.length, new apache_arrow_1.Field("item", typedArray.elementType, true));
130
+ }
131
+ if (!Array.isArray(value) || value.length === 0) {
132
+ return undefined;
133
+ }
134
+ const configuredVector = path.length === 1 ? this.options.vectorColumns[path[0]] : undefined;
135
+ if (configuredVector !== undefined) {
136
+ return new apache_arrow_1.FixedSizeList(value.length, new apache_arrow_1.Field("item", (0, sanitize_1.sanitizeType)(configuredVector.type), true));
137
+ }
138
+ const itemType = this.inferArrayItemType(value, path);
139
+ if (itemType === undefined) {
140
+ return undefined;
141
+ }
142
+ return nameSuggestsVectorColumn(path[path.length - 1])
143
+ ? new apache_arrow_1.FixedSizeList(value.length, new apache_arrow_1.Field("item", new apache_arrow_1.Float32(), true))
144
+ : new apache_arrow_1.List(new apache_arrow_1.Field("item", itemType, true));
145
+ }
146
+ inferArrayItemType(values, path) {
147
+ let itemType;
148
+ const deferredItems = [];
149
+ for (const value of values) {
150
+ const candidate = this.inferType(value, path);
151
+ if (candidate === undefined) {
152
+ if (!isDeferredValue(value)) {
153
+ return undefined;
154
+ }
155
+ deferredItems.push(value);
156
+ }
157
+ else if (itemType === undefined) {
158
+ itemType = candidate;
159
+ }
160
+ else if (!inferredTypesEqual(itemType, candidate)) {
161
+ return undefined;
162
+ }
163
+ }
164
+ if (itemType === undefined) {
165
+ return undefined;
166
+ }
167
+ return deferredItems.every((value) => deferredValueMatchesType(value, itemType))
168
+ ? itemType
169
+ : undefined;
170
+ }
171
+ }
172
+ /** Nulls and empty/all-null lists that do not determine a type by themselves. */
173
+ class DeferredTypeEvidence {
174
+ values;
175
+ constructor(values) {
176
+ this.values = values;
177
+ }
178
+ static from(value, row) {
179
+ return isDeferredValue(value)
180
+ ? new DeferredTypeEvidence([{ value, row }])
181
+ : undefined;
182
+ }
183
+ isOnlyNulls() {
184
+ return this.values.every(({ value }) => value == null);
185
+ }
186
+ matches(type) {
187
+ return this.values.every(({ value }) => deferredValueMatchesType(value, type));
188
+ }
189
+ merge(other) {
190
+ return new DeferredTypeEvidence([...this.values, ...other.values]);
191
+ }
192
+ describe() {
193
+ const list = this.values.find(({ value }) => Array.isArray(value));
194
+ return list === undefined
195
+ ? "null"
196
+ : `List[${list.value.length}]`;
197
+ }
198
+ firstRow() {
199
+ return this.values[0].row;
200
+ }
201
+ }
202
+ /** Nested field state, kept separate from Arrow's eventual Struct types. */
203
+ class FieldTree {
204
+ children = new Map();
205
+ get(path) {
206
+ let current = this;
207
+ for (const part of path) {
208
+ if (!(current instanceof FieldTree)) {
209
+ return undefined;
210
+ }
211
+ const child = current.children.get(part);
212
+ if (child === undefined) {
213
+ return undefined;
214
+ }
215
+ current = child;
216
+ }
217
+ return current;
218
+ }
219
+ set(path, value, canReplaceLeaf = () => false) {
220
+ let branch = this;
221
+ for (const [index, part] of path.slice(0, -1).entries()) {
222
+ const child = branch.children.get(part);
223
+ if (child === undefined || (isLeaf(child) && canReplaceLeaf(child))) {
224
+ const nextBranch = new FieldTree();
225
+ branch.children.set(part, nextBranch);
226
+ branch = nextBranch;
227
+ }
228
+ else if (child instanceof FieldTree) {
229
+ branch = child;
230
+ }
231
+ else {
232
+ return { path: path.slice(0, index + 1), value: child };
233
+ }
234
+ }
235
+ const name = path[path.length - 1];
236
+ const current = branch.children.get(name);
237
+ if (current instanceof FieldTree) {
238
+ return { path, value: current };
239
+ }
240
+ branch.children.set(name, value);
241
+ return undefined;
242
+ }
243
+ entries() {
244
+ return this.children.entries();
245
+ }
246
+ has(name) {
247
+ return this.children.has(name);
248
+ }
249
+ }
250
+ function isLeaf(value) {
251
+ return !(value instanceof FieldTree);
252
+ }
253
+ function fieldsFromTree(tree, path = []) {
254
+ const fields = [];
255
+ for (const [name, value] of tree.entries()) {
256
+ if (value instanceof FieldTree) {
257
+ fields.push(new apache_arrow_1.Field(name, new apache_arrow_1.Struct(fieldsFromTree(value, [...path, name])), true));
258
+ }
259
+ else if (value instanceof DeferredTypeEvidence) {
260
+ throw typeInferenceError([...path, name], value.firstRow());
261
+ }
262
+ else {
263
+ fields.push(new apache_arrow_1.Field(name, value, true));
264
+ }
265
+ }
266
+ return fields;
267
+ }
268
+ function matchingFields(fields, tree) {
269
+ const matches = [];
270
+ for (const field of fields) {
271
+ if (!tree.has(field.name)) {
272
+ continue;
273
+ }
274
+ const value = tree.get([field.name]);
275
+ if (value instanceof FieldTree) {
276
+ const struct = field.type;
277
+ matches.push(new apache_arrow_1.Field(field.name, new apache_arrow_1.Struct(matchingFields(struct.children, value)), field.nullable, field.metadata));
278
+ }
279
+ else {
280
+ matches.push(field);
281
+ }
282
+ }
283
+ return matches;
284
+ }
285
+ function* recordPathsAndValues(record, path = []) {
286
+ for (const [name, value] of Object.entries(record)) {
287
+ if (isRecord(value)) {
288
+ yield* recordPathsAndValues(value, [...path, name]);
289
+ }
290
+ else if (value !== undefined) {
291
+ yield [[...path, name], value];
292
+ }
293
+ }
294
+ }
295
+ function isRecord(value) {
296
+ return (typeof value === "object" &&
297
+ value !== null &&
298
+ !Array.isArray(value) &&
299
+ !(value instanceof RegExp) &&
300
+ !(value instanceof Date) &&
301
+ !(value instanceof Set) &&
302
+ !(value instanceof Map) &&
303
+ !(value instanceof Buffer) &&
304
+ !ArrayBuffer.isView(value));
305
+ }
306
+ function fieldAtPath(schema, path) {
307
+ let fields = schema.fields;
308
+ let field;
309
+ for (const [index, name] of path.entries()) {
310
+ field = fields.find((candidate) => candidate.name === name);
311
+ if (field === undefined || index === path.length - 1) {
312
+ return field;
313
+ }
314
+ if (!apache_arrow_1.DataType.isStruct(field.type)) {
315
+ return undefined;
316
+ }
317
+ fields = field.type.children;
318
+ }
319
+ return field;
320
+ }
321
+ function isDeferredValue(value) {
322
+ return (value == null || (Array.isArray(value) && value.every(isDeferredValue)));
323
+ }
324
+ function deferredValueMatchesType(value, type) {
325
+ if (value == null) {
326
+ return true;
327
+ }
328
+ if (!Array.isArray(value)) {
329
+ return false;
330
+ }
331
+ if (apache_arrow_1.DataType.isList(type)) {
332
+ return value.every((item) => deferredValueMatchesType(item, type.valueType));
333
+ }
334
+ if (apache_arrow_1.DataType.isFixedSizeList(type)) {
335
+ return (value.length === type.listSize &&
336
+ value.every((item) => deferredValueMatchesType(item, type.valueType)));
337
+ }
338
+ return false;
339
+ }
340
+ function inferredTypesEqual(current, candidate) {
341
+ if (apache_arrow_1.DataType.isDictionary(current)) {
342
+ return (apache_arrow_1.DataType.isDictionary(candidate) &&
343
+ current.isOrdered === candidate.isOrdered &&
344
+ inferredTypesEqual(current.indices, candidate.indices) &&
345
+ inferredTypesEqual(current.dictionary, candidate.dictionary));
346
+ }
347
+ if (apache_arrow_1.DataType.isList(current)) {
348
+ return (apache_arrow_1.DataType.isList(candidate) &&
349
+ current.valueField.name === candidate.valueField.name &&
350
+ current.valueField.nullable === candidate.valueField.nullable &&
351
+ inferredTypesEqual(current.valueType, candidate.valueType));
352
+ }
353
+ if (apache_arrow_1.DataType.isFixedSizeList(current)) {
354
+ return (apache_arrow_1.DataType.isFixedSizeList(candidate) &&
355
+ current.listSize === candidate.listSize &&
356
+ current.valueField.name === candidate.valueField.name &&
357
+ current.valueField.nullable === candidate.valueField.nullable &&
358
+ inferredTypesEqual(current.valueType, candidate.valueType));
359
+ }
360
+ return apache_arrow_1.util.compareTypes(current, candidate);
361
+ }
362
+ function describeEvidence(evidence) {
363
+ if (evidence === undefined) {
364
+ return "an unsupported value";
365
+ }
366
+ return evidence instanceof DeferredTypeEvidence
367
+ ? evidence.describe()
368
+ : evidence.toString();
369
+ }
370
+ function branchConflictError(conflict, row, candidate) {
371
+ return schemaInferenceError(conflict.path, row, conflict.value instanceof FieldTree
372
+ ? "Struct"
373
+ : describeEvidence(conflict.value), candidate);
374
+ }
375
+ function schemaInferenceError(path, row, currentType, newType) {
376
+ return new Error(`Failed to infer schema for data. Previously inferred type ${currentType} ` +
377
+ `but found ${newType} for field ${path.join(".")} at row ${row}. ` +
378
+ "Consider providing an explicit schema.");
379
+ }
380
+ function typeInferenceError(path, row) {
381
+ return new Error(`Failed to infer data type for field ${path.join(".")} at row ${row}. ` +
382
+ "Consider providing an explicit schema.");
383
+ }
384
+ function nameSuggestsVectorColumn(name) {
385
+ const normalized = name.toLowerCase();
386
+ return normalized.includes("vector") || normalized.includes("embedding");
387
+ }