@tenphi/akno-core 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.
- package/LICENSE +83 -0
- package/README.md +26 -0
- package/config/default.jsonc +548 -0
- package/dist/bench/answer-corpus.d.ts +48 -0
- package/dist/bench/answer-corpus.d.ts.map +1 -0
- package/dist/bench/answer-corpus.js +491 -0
- package/dist/bench/answer-corpus.js.map +1 -0
- package/dist/bench/answer.d.ts +156 -0
- package/dist/bench/answer.d.ts.map +1 -0
- package/dist/bench/answer.js +608 -0
- package/dist/bench/answer.js.map +1 -0
- package/dist/bench/auto-recall-answer-corpus.d.ts +21 -0
- package/dist/bench/auto-recall-answer-corpus.d.ts.map +1 -0
- package/dist/bench/auto-recall-answer-corpus.js +245 -0
- package/dist/bench/auto-recall-answer-corpus.js.map +1 -0
- package/dist/bench/auto-recall-answer.d.ts +198 -0
- package/dist/bench/auto-recall-answer.d.ts.map +1 -0
- package/dist/bench/auto-recall-answer.js +720 -0
- package/dist/bench/auto-recall-answer.js.map +1 -0
- package/dist/bench/auto-recall-corpus.d.ts +45 -0
- package/dist/bench/auto-recall-corpus.d.ts.map +1 -0
- package/dist/bench/auto-recall-corpus.js +221 -0
- package/dist/bench/auto-recall-corpus.js.map +1 -0
- package/dist/bench/auto-recall.d.ts +171 -0
- package/dist/bench/auto-recall.d.ts.map +1 -0
- package/dist/bench/auto-recall.js +651 -0
- package/dist/bench/auto-recall.js.map +1 -0
- package/dist/bench/entity-resolution.d.ts +37 -0
- package/dist/bench/entity-resolution.d.ts.map +1 -0
- package/dist/bench/entity-resolution.js +121 -0
- package/dist/bench/entity-resolution.js.map +1 -0
- package/dist/bench/graph.d.ts +57 -0
- package/dist/bench/graph.d.ts.map +1 -0
- package/dist/bench/graph.js +573 -0
- package/dist/bench/graph.js.map +1 -0
- package/dist/bench/llm-ranking-probe.d.ts +27 -0
- package/dist/bench/llm-ranking-probe.d.ts.map +1 -0
- package/dist/bench/llm-ranking-probe.js +105 -0
- package/dist/bench/llm-ranking-probe.js.map +1 -0
- package/dist/bench/merge-discovery-corpus.d.ts +26 -0
- package/dist/bench/merge-discovery-corpus.d.ts.map +1 -0
- package/dist/bench/merge-discovery-corpus.js +114 -0
- package/dist/bench/merge-discovery-corpus.js.map +1 -0
- package/dist/bench/merge-discovery-review.d.ts +81 -0
- package/dist/bench/merge-discovery-review.d.ts.map +1 -0
- package/dist/bench/merge-discovery-review.js +149 -0
- package/dist/bench/merge-discovery-review.js.map +1 -0
- package/dist/bench/merge-discovery.d.ts +122 -0
- package/dist/bench/merge-discovery.d.ts.map +1 -0
- package/dist/bench/merge-discovery.js +390 -0
- package/dist/bench/merge-discovery.js.map +1 -0
- package/dist/bench/mixed-retrieval.d.ts +35 -0
- package/dist/bench/mixed-retrieval.d.ts.map +1 -0
- package/dist/bench/mixed-retrieval.js +355 -0
- package/dist/bench/mixed-retrieval.js.map +1 -0
- package/dist/bench/ranking-corpus.d.ts +29 -0
- package/dist/bench/ranking-corpus.d.ts.map +1 -0
- package/dist/bench/ranking-corpus.js +514 -0
- package/dist/bench/ranking-corpus.js.map +1 -0
- package/dist/bench/ranking-end-to-end.d.ts +112 -0
- package/dist/bench/ranking-end-to-end.d.ts.map +1 -0
- package/dist/bench/ranking-end-to-end.js +479 -0
- package/dist/bench/ranking-end-to-end.js.map +1 -0
- package/dist/bench/ranking-latency.d.ts +71 -0
- package/dist/bench/ranking-latency.d.ts.map +1 -0
- package/dist/bench/ranking-latency.js +130 -0
- package/dist/bench/ranking-latency.js.map +1 -0
- package/dist/bench/ranking-matrix.d.ts +141 -0
- package/dist/bench/ranking-matrix.d.ts.map +1 -0
- package/dist/bench/ranking-matrix.js +526 -0
- package/dist/bench/ranking-matrix.js.map +1 -0
- package/dist/bench/ranking-review.d.ts +93 -0
- package/dist/bench/ranking-review.d.ts.map +1 -0
- package/dist/bench/ranking-review.js +249 -0
- package/dist/bench/ranking-review.js.map +1 -0
- package/dist/bench/ranking.d.ts +122 -0
- package/dist/bench/ranking.d.ts.map +1 -0
- package/dist/bench/ranking.js +547 -0
- package/dist/bench/ranking.js.map +1 -0
- package/dist/bench.d.ts +60 -0
- package/dist/bench.d.ts.map +1 -0
- package/dist/bench.js +167 -0
- package/dist/bench.js.map +1 -0
- package/dist/config/jsonc.d.ts +8 -0
- package/dist/config/jsonc.d.ts.map +1 -0
- package/dist/config/jsonc.js +85 -0
- package/dist/config/jsonc.js.map +1 -0
- package/dist/config/load.d.ts +43 -0
- package/dist/config/load.d.ts.map +1 -0
- package/dist/config/load.js +608 -0
- package/dist/config/load.js.map +1 -0
- package/dist/config/paths.d.ts +10 -0
- package/dist/config/paths.d.ts.map +1 -0
- package/dist/config/paths.js +38 -0
- package/dist/config/paths.js.map +1 -0
- package/dist/config/schema.d.ts +698 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +394 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/config/write-rules.d.ts +41 -0
- package/dist/config/write-rules.d.ts.map +1 -0
- package/dist/config/write-rules.js +225 -0
- package/dist/config/write-rules.js.map +1 -0
- package/dist/config/write-setup.d.ts +42 -0
- package/dist/config/write-setup.d.ts.map +1 -0
- package/dist/config/write-setup.js +358 -0
- package/dist/config/write-setup.js.map +1 -0
- package/dist/context.d.ts +64 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +14 -0
- package/dist/context.js.map +1 -0
- package/dist/doctor.d.ts +115 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/doctor.js +388 -0
- package/dist/doctor.js.map +1 -0
- package/dist/index/chunk.d.ts +62 -0
- package/dist/index/chunk.d.ts.map +1 -0
- package/dist/index/chunk.js +307 -0
- package/dist/index/chunk.js.map +1 -0
- package/dist/index/defer.d.ts +32 -0
- package/dist/index/defer.d.ts.map +1 -0
- package/dist/index/defer.js +66 -0
- package/dist/index/defer.js.map +1 -0
- package/dist/index/derive.d.ts +99 -0
- package/dist/index/derive.d.ts.map +1 -0
- package/dist/index/derive.js +378 -0
- package/dist/index/derive.js.map +1 -0
- package/dist/index/entity-resolution.d.ts +68 -0
- package/dist/index/entity-resolution.d.ts.map +1 -0
- package/dist/index/entity-resolution.js +305 -0
- package/dist/index/entity-resolution.js.map +1 -0
- package/dist/index/graph.d.ts +46 -0
- package/dist/index/graph.d.ts.map +1 -0
- package/dist/index/graph.js +618 -0
- package/dist/index/graph.js.map +1 -0
- package/dist/index/indexer.d.ts +301 -0
- package/dist/index/indexer.d.ts.map +1 -0
- package/dist/index/indexer.js +1398 -0
- package/dist/index/indexer.js.map +1 -0
- package/dist/index/revision-barrier.d.ts +30 -0
- package/dist/index/revision-barrier.d.ts.map +1 -0
- package/dist/index/revision-barrier.js +140 -0
- package/dist/index/revision-barrier.js.map +1 -0
- package/dist/index.d.ts +55 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/ingest/adoption-eligibility.d.ts +4 -0
- package/dist/ingest/adoption-eligibility.d.ts.map +1 -0
- package/dist/ingest/adoption-eligibility.js +18 -0
- package/dist/ingest/adoption-eligibility.js.map +1 -0
- package/dist/ingest/availability.d.ts +15 -0
- package/dist/ingest/availability.d.ts.map +1 -0
- package/dist/ingest/availability.js +37 -0
- package/dist/ingest/availability.js.map +1 -0
- package/dist/ingest/extract.d.ts +58 -0
- package/dist/ingest/extract.d.ts.map +1 -0
- package/dist/ingest/extract.js +255 -0
- package/dist/ingest/extract.js.map +1 -0
- package/dist/ingest/fetch.d.ts +35 -0
- package/dist/ingest/fetch.d.ts.map +1 -0
- package/dist/ingest/fetch.js +142 -0
- package/dist/ingest/fetch.js.map +1 -0
- package/dist/ingest/inbox.d.ts +53 -0
- package/dist/ingest/inbox.d.ts.map +1 -0
- package/dist/ingest/inbox.js +110 -0
- package/dist/ingest/inbox.js.map +1 -0
- package/dist/ingest/name.d.ts +72 -0
- package/dist/ingest/name.d.ts.map +1 -0
- package/dist/ingest/name.js +208 -0
- package/dist/ingest/name.js.map +1 -0
- package/dist/ingest/parts.d.ts +78 -0
- package/dist/ingest/parts.d.ts.map +1 -0
- package/dist/ingest/parts.js +52 -0
- package/dist/ingest/parts.js.map +1 -0
- package/dist/ingest/rendition.d.ts +75 -0
- package/dist/ingest/rendition.d.ts.map +1 -0
- package/dist/ingest/rendition.js +92 -0
- package/dist/ingest/rendition.js.map +1 -0
- package/dist/ingest/store.d.ts +66 -0
- package/dist/ingest/store.d.ts.map +1 -0
- package/dist/ingest/store.js +92 -0
- package/dist/ingest/store.js.map +1 -0
- package/dist/kb/folders.d.ts +37 -0
- package/dist/kb/folders.d.ts.map +1 -0
- package/dist/kb/folders.js +133 -0
- package/dist/kb/folders.js.map +1 -0
- package/dist/kb/frontmatter.d.ts +91 -0
- package/dist/kb/frontmatter.d.ts.map +1 -0
- package/dist/kb/frontmatter.js +274 -0
- package/dist/kb/frontmatter.js.map +1 -0
- package/dist/kb/line-facts.d.ts +29 -0
- package/dist/kb/line-facts.d.ts.map +1 -0
- package/dist/kb/line-facts.js +23 -0
- package/dist/kb/line-facts.js.map +1 -0
- package/dist/kb/page.d.ts +92 -0
- package/dist/kb/page.d.ts.map +1 -0
- package/dist/kb/page.js +243 -0
- package/dist/kb/page.js.map +1 -0
- package/dist/kb/scan.d.ts +38 -0
- package/dist/kb/scan.d.ts.map +1 -0
- package/dist/kb/scan.js +109 -0
- package/dist/kb/scan.js.map +1 -0
- package/dist/kb/words.d.ts +30 -0
- package/dist/kb/words.d.ts.map +1 -0
- package/dist/kb/words.js +107 -0
- package/dist/kb/words.js.map +1 -0
- package/dist/maintenance/adopt.d.ts +65 -0
- package/dist/maintenance/adopt.d.ts.map +1 -0
- package/dist/maintenance/adopt.js +238 -0
- package/dist/maintenance/adopt.js.map +1 -0
- package/dist/maintenance/budget.d.ts +55 -0
- package/dist/maintenance/budget.d.ts.map +1 -0
- package/dist/maintenance/budget.js +61 -0
- package/dist/maintenance/budget.js.map +1 -0
- package/dist/maintenance/conflicts.d.ts +105 -0
- package/dist/maintenance/conflicts.d.ts.map +1 -0
- package/dist/maintenance/conflicts.js +368 -0
- package/dist/maintenance/conflicts.js.map +1 -0
- package/dist/maintenance/contradictions.d.ts +34 -0
- package/dist/maintenance/contradictions.d.ts.map +1 -0
- package/dist/maintenance/contradictions.js +199 -0
- package/dist/maintenance/contradictions.js.map +1 -0
- package/dist/maintenance/curate.d.ts +156 -0
- package/dist/maintenance/curate.d.ts.map +1 -0
- package/dist/maintenance/curate.js +2070 -0
- package/dist/maintenance/curate.js.map +1 -0
- package/dist/maintenance/dream.d.ts +139 -0
- package/dist/maintenance/dream.d.ts.map +1 -0
- package/dist/maintenance/dream.js +1632 -0
- package/dist/maintenance/dream.js.map +1 -0
- package/dist/maintenance/graph-candidates.d.ts +19 -0
- package/dist/maintenance/graph-candidates.d.ts.map +1 -0
- package/dist/maintenance/graph-candidates.js +120 -0
- package/dist/maintenance/graph-candidates.js.map +1 -0
- package/dist/maintenance/housekeeping.d.ts +81 -0
- package/dist/maintenance/housekeeping.d.ts.map +1 -0
- package/dist/maintenance/housekeeping.js +281 -0
- package/dist/maintenance/housekeeping.js.map +1 -0
- package/dist/maintenance/link-repairs.d.ts +58 -0
- package/dist/maintenance/link-repairs.d.ts.map +1 -0
- package/dist/maintenance/link-repairs.js +281 -0
- package/dist/maintenance/link-repairs.js.map +1 -0
- package/dist/maintenance/log.d.ts +41 -0
- package/dist/maintenance/log.d.ts.map +1 -0
- package/dist/maintenance/log.js +72 -0
- package/dist/maintenance/log.js.map +1 -0
- package/dist/maintenance/managed-item-routing.d.ts +48 -0
- package/dist/maintenance/managed-item-routing.d.ts.map +1 -0
- package/dist/maintenance/managed-item-routing.js +281 -0
- package/dist/maintenance/managed-item-routing.js.map +1 -0
- package/dist/maintenance/managed-item-sources.d.ts +38 -0
- package/dist/maintenance/managed-item-sources.d.ts.map +1 -0
- package/dist/maintenance/managed-item-sources.js +324 -0
- package/dist/maintenance/managed-item-sources.js.map +1 -0
- package/dist/maintenance/managed-items.d.ts +162 -0
- package/dist/maintenance/managed-items.d.ts.map +1 -0
- package/dist/maintenance/managed-items.js +1329 -0
- package/dist/maintenance/managed-items.js.map +1 -0
- package/dist/maintenance/merge-classifier.d.ts +19 -0
- package/dist/maintenance/merge-classifier.d.ts.map +1 -0
- package/dist/maintenance/merge-classifier.js +49 -0
- package/dist/maintenance/merge-classifier.js.map +1 -0
- package/dist/maintenance/model-telemetry.d.ts +45 -0
- package/dist/maintenance/model-telemetry.d.ts.map +1 -0
- package/dist/maintenance/model-telemetry.js +107 -0
- package/dist/maintenance/model-telemetry.js.map +1 -0
- package/dist/maintenance/observe.d.ts +72 -0
- package/dist/maintenance/observe.d.ts.map +1 -0
- package/dist/maintenance/observe.js +265 -0
- package/dist/maintenance/observe.js.map +1 -0
- package/dist/maintenance/path-policy.d.ts +83 -0
- package/dist/maintenance/path-policy.d.ts.map +1 -0
- package/dist/maintenance/path-policy.js +360 -0
- package/dist/maintenance/path-policy.js.map +1 -0
- package/dist/maintenance/plans.d.ts +366 -0
- package/dist/maintenance/plans.d.ts.map +1 -0
- package/dist/maintenance/plans.js +4060 -0
- package/dist/maintenance/plans.js.map +1 -0
- package/dist/maintenance/profile.d.ts +33 -0
- package/dist/maintenance/profile.d.ts.map +1 -0
- package/dist/maintenance/profile.js +99 -0
- package/dist/maintenance/profile.js.map +1 -0
- package/dist/maintenance/recovery.d.ts +38 -0
- package/dist/maintenance/recovery.d.ts.map +1 -0
- package/dist/maintenance/recovery.js +217 -0
- package/dist/maintenance/recovery.js.map +1 -0
- package/dist/maintenance/repair.d.ts +37 -0
- package/dist/maintenance/repair.d.ts.map +1 -0
- package/dist/maintenance/repair.js +183 -0
- package/dist/maintenance/repair.js.map +1 -0
- package/dist/maintenance/rule-drift.d.ts +104 -0
- package/dist/maintenance/rule-drift.d.ts.map +1 -0
- package/dist/maintenance/rule-drift.js +507 -0
- package/dist/maintenance/rule-drift.js.map +1 -0
- package/dist/maintenance/run-verification.d.ts +44 -0
- package/dist/maintenance/run-verification.d.ts.map +1 -0
- package/dist/maintenance/run-verification.js +253 -0
- package/dist/maintenance/run-verification.js.map +1 -0
- package/dist/maintenance/runs.d.ts +142 -0
- package/dist/maintenance/runs.d.ts.map +1 -0
- package/dist/maintenance/runs.js +439 -0
- package/dist/maintenance/runs.js.map +1 -0
- package/dist/maintenance/semantic-merge-discovery.d.ts +54 -0
- package/dist/maintenance/semantic-merge-discovery.d.ts.map +1 -0
- package/dist/maintenance/semantic-merge-discovery.js +308 -0
- package/dist/maintenance/semantic-merge-discovery.js.map +1 -0
- package/dist/maintenance/temporal.d.ts +44 -0
- package/dist/maintenance/temporal.d.ts.map +1 -0
- package/dist/maintenance/temporal.js +295 -0
- package/dist/maintenance/temporal.js.map +1 -0
- package/dist/models/client.d.ts +214 -0
- package/dist/models/client.d.ts.map +1 -0
- package/dist/models/client.js +904 -0
- package/dist/models/client.js.map +1 -0
- package/dist/models/provider-api.d.ts +28 -0
- package/dist/models/provider-api.d.ts.map +1 -0
- package/dist/models/provider-api.js +320 -0
- package/dist/models/provider-api.js.map +1 -0
- package/dist/open.d.ts +163 -0
- package/dist/open.d.ts.map +1 -0
- package/dist/open.js +382 -0
- package/dist/open.js.map +1 -0
- package/dist/ops/adopt.d.ts +12 -0
- package/dist/ops/adopt.d.ts.map +1 -0
- package/dist/ops/adopt.js +138 -0
- package/dist/ops/adopt.js.map +1 -0
- package/dist/ops/answer.d.ts +29 -0
- package/dist/ops/answer.d.ts.map +1 -0
- package/dist/ops/answer.js +557 -0
- package/dist/ops/answer.js.map +1 -0
- package/dist/ops/context.d.ts +18 -0
- package/dist/ops/context.d.ts.map +1 -0
- package/dist/ops/context.js +713 -0
- package/dist/ops/context.js.map +1 -0
- package/dist/ops/folder.d.ts +23 -0
- package/dist/ops/folder.d.ts.map +1 -0
- package/dist/ops/folder.js +130 -0
- package/dist/ops/folder.js.map +1 -0
- package/dist/ops/forget.d.ts +14 -0
- package/dist/ops/forget.d.ts.map +1 -0
- package/dist/ops/forget.js +212 -0
- package/dist/ops/forget.js.map +1 -0
- package/dist/ops/graph.d.ts +10 -0
- package/dist/ops/graph.d.ts.map +1 -0
- package/dist/ops/graph.js +480 -0
- package/dist/ops/graph.js.map +1 -0
- package/dist/ops/ingest.d.ts +40 -0
- package/dist/ops/ingest.d.ts.map +1 -0
- package/dist/ops/ingest.js +434 -0
- package/dist/ops/ingest.js.map +1 -0
- package/dist/ops/list.d.ts +9 -0
- package/dist/ops/list.d.ts.map +1 -0
- package/dist/ops/list.js +217 -0
- package/dist/ops/list.js.map +1 -0
- package/dist/ops/move.d.ts +20 -0
- package/dist/ops/move.d.ts.map +1 -0
- package/dist/ops/move.js +173 -0
- package/dist/ops/move.js.map +1 -0
- package/dist/ops/read.d.ts +9 -0
- package/dist/ops/read.d.ts.map +1 -0
- package/dist/ops/read.js +271 -0
- package/dist/ops/read.js.map +1 -0
- package/dist/ops/recall.d.ts +13 -0
- package/dist/ops/recall.d.ts.map +1 -0
- package/dist/ops/recall.js +297 -0
- package/dist/ops/recall.js.map +1 -0
- package/dist/ops/remember.d.ts +34 -0
- package/dist/ops/remember.d.ts.map +1 -0
- package/dist/ops/remember.js +660 -0
- package/dist/ops/remember.js.map +1 -0
- package/dist/ops/timeline.d.ts +11 -0
- package/dist/ops/timeline.d.ts.map +1 -0
- package/dist/ops/timeline.js +111 -0
- package/dist/ops/timeline.js.map +1 -0
- package/dist/ops/undo.d.ts +9 -0
- package/dist/ops/undo.d.ts.map +1 -0
- package/dist/ops/undo.js +38 -0
- package/dist/ops/undo.js.map +1 -0
- package/dist/ops/write.d.ts +55 -0
- package/dist/ops/write.d.ts.map +1 -0
- package/dist/ops/write.js +463 -0
- package/dist/ops/write.js.map +1 -0
- package/dist/recall/assemble.d.ts +81 -0
- package/dist/recall/assemble.d.ts.map +1 -0
- package/dist/recall/assemble.js +603 -0
- package/dist/recall/assemble.js.map +1 -0
- package/dist/recall/expand.d.ts +55 -0
- package/dist/recall/expand.d.ts.map +1 -0
- package/dist/recall/expand.js +282 -0
- package/dist/recall/expand.js.map +1 -0
- package/dist/recall/graph-arm.d.ts +17 -0
- package/dist/recall/graph-arm.d.ts.map +1 -0
- package/dist/recall/graph-arm.js +227 -0
- package/dist/recall/graph-arm.js.map +1 -0
- package/dist/recall/llm-rerank.d.ts +55 -0
- package/dist/recall/llm-rerank.d.ts.map +1 -0
- package/dist/recall/llm-rerank.js +213 -0
- package/dist/recall/llm-rerank.js.map +1 -0
- package/dist/recall/reranker-calibration.d.ts +23 -0
- package/dist/recall/reranker-calibration.d.ts.map +1 -0
- package/dist/recall/reranker-calibration.js +161 -0
- package/dist/recall/reranker-calibration.js.map +1 -0
- package/dist/recall/search.d.ts +107 -0
- package/dist/recall/search.d.ts.map +1 -0
- package/dist/recall/search.js +530 -0
- package/dist/recall/search.js.map +1 -0
- package/dist/reserved.d.ts +39 -0
- package/dist/reserved.d.ts.map +1 -0
- package/dist/reserved.js +63 -0
- package/dist/reserved.js.map +1 -0
- package/dist/rules/compile.d.ts +27 -0
- package/dist/rules/compile.d.ts.map +1 -0
- package/dist/rules/compile.js +105 -0
- package/dist/rules/compile.js.map +1 -0
- package/dist/setup/model-free.d.ts +15 -0
- package/dist/setup/model-free.d.ts.map +1 -0
- package/dist/setup/model-free.js +26 -0
- package/dist/setup/model-free.js.map +1 -0
- package/dist/setup/openai.d.ts +46 -0
- package/dist/setup/openai.d.ts.map +1 -0
- package/dist/setup/openai.js +165 -0
- package/dist/setup/openai.js.map +1 -0
- package/dist/store/db.d.ts +61 -0
- package/dist/store/db.d.ts.map +1 -0
- package/dist/store/db.js +265 -0
- package/dist/store/db.js.map +1 -0
- package/dist/store/ids.d.ts +29 -0
- package/dist/store/ids.d.ts.map +1 -0
- package/dist/store/ids.js +0 -0
- package/dist/store/ids.js.map +1 -0
- package/dist/store/migrations.d.ts +54 -0
- package/dist/store/migrations.d.ts.map +1 -0
- package/dist/store/migrations.js +923 -0
- package/dist/store/migrations.js.map +1 -0
- package/dist/store/vectors.d.ts +34 -0
- package/dist/store/vectors.d.ts.map +1 -0
- package/dist/store/vectors.js +158 -0
- package/dist/store/vectors.js.map +1 -0
- package/dist/timeline/documents.d.ts +23 -0
- package/dist/timeline/documents.d.ts.map +1 -0
- package/dist/timeline/documents.js +262 -0
- package/dist/timeline/documents.js.map +1 -0
- package/dist/watch/watcher.d.ts +43 -0
- package/dist/watch/watcher.d.ts.map +1 -0
- package/dist/watch/watcher.js +143 -0
- package/dist/watch/watcher.js.map +1 -0
- package/dist/write/atomic.d.ts +34 -0
- package/dist/write/atomic.d.ts.map +1 -0
- package/dist/write/atomic.js +58 -0
- package/dist/write/atomic.js.map +1 -0
- package/dist/write/conflict.d.ts +43 -0
- package/dist/write/conflict.d.ts.map +1 -0
- package/dist/write/conflict.js +149 -0
- package/dist/write/conflict.js.map +1 -0
- package/dist/write/edit.d.ts +59 -0
- package/dist/write/edit.d.ts.map +1 -0
- package/dist/write/edit.js +231 -0
- package/dist/write/edit.js.map +1 -0
- package/dist/write/gate.d.ts +59 -0
- package/dist/write/gate.d.ts.map +1 -0
- package/dist/write/gate.js +99 -0
- package/dist/write/gate.js.map +1 -0
- package/dist/write/journal.d.ts +90 -0
- package/dist/write/journal.d.ts.map +1 -0
- package/dist/write/journal.js +187 -0
- package/dist/write/journal.js.map +1 -0
- package/dist/write/ledger.d.ts +28 -0
- package/dist/write/ledger.d.ts.map +1 -0
- package/dist/write/ledger.js +141 -0
- package/dist/write/ledger.js.map +1 -0
- package/dist/write/placement.d.ts +29 -0
- package/dist/write/placement.d.ts.map +1 -0
- package/dist/write/placement.js +140 -0
- package/dist/write/placement.js.map +1 -0
- package/dist/write/remember-fallback.d.ts +18 -0
- package/dist/write/remember-fallback.d.ts.map +1 -0
- package/dist/write/remember-fallback.js +48 -0
- package/dist/write/remember-fallback.js.map +1 -0
- package/dist/write/retain.d.ts +61 -0
- package/dist/write/retain.d.ts.map +1 -0
- package/dist/write/retain.js +272 -0
- package/dist/write/retain.js.map +1 -0
- package/package.json +50 -0
- package/swift/extract.swift +232 -0
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import fsp from 'node:fs/promises';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { promisify } from 'node:util';
|
|
7
|
+
import { sha256 } from "../store/ids.js";
|
|
8
|
+
const run = promisify(execFile);
|
|
9
|
+
const IMAGE_EXTENSIONS = new Set([
|
|
10
|
+
'.png',
|
|
11
|
+
'.jpg',
|
|
12
|
+
'.jpeg',
|
|
13
|
+
'.heic',
|
|
14
|
+
'.heif',
|
|
15
|
+
'.webp',
|
|
16
|
+
'.tiff',
|
|
17
|
+
'.tif',
|
|
18
|
+
'.gif',
|
|
19
|
+
'.bmp',
|
|
20
|
+
]);
|
|
21
|
+
const PLAIN_EXTENSIONS = new Set([
|
|
22
|
+
'.txt',
|
|
23
|
+
'.md',
|
|
24
|
+
'.markdown',
|
|
25
|
+
'.csv',
|
|
26
|
+
'.tsv',
|
|
27
|
+
'.json',
|
|
28
|
+
'.yaml',
|
|
29
|
+
'.yml',
|
|
30
|
+
'.log',
|
|
31
|
+
]);
|
|
32
|
+
/** Formats `textutil` handles natively — it ships with macOS. */
|
|
33
|
+
const TEXTUTIL_EXTENSIONS = new Set([
|
|
34
|
+
'.rtf',
|
|
35
|
+
'.rtfd',
|
|
36
|
+
'.doc',
|
|
37
|
+
'.docx',
|
|
38
|
+
'.odt',
|
|
39
|
+
'.html',
|
|
40
|
+
'.htm',
|
|
41
|
+
'.webarchive',
|
|
42
|
+
]);
|
|
43
|
+
export async function extract(options) {
|
|
44
|
+
const extension = path.extname(options.absPath).toLowerCase();
|
|
45
|
+
const stat = await fsp.stat(options.absPath).catch(() => null);
|
|
46
|
+
if (!stat)
|
|
47
|
+
return none('the file could not be read');
|
|
48
|
+
if (stat.size === 0)
|
|
49
|
+
return none('the file is empty');
|
|
50
|
+
if (stat.size > options.maxBytes) {
|
|
51
|
+
return none(`the file is ${Math.round(stat.size / 1_048_576)} MB, over the configured limit`);
|
|
52
|
+
}
|
|
53
|
+
if (PLAIN_EXTENSIONS.has(extension)) {
|
|
54
|
+
const text = await fsp.readFile(options.absPath, 'utf8').catch(() => '');
|
|
55
|
+
return { text: text.trim(), pageCount: null, ocr: false, confidence: null, via: 'plain', note: null };
|
|
56
|
+
}
|
|
57
|
+
if (TEXTUTIL_EXTENSIONS.has(extension))
|
|
58
|
+
return textutil(options.absPath);
|
|
59
|
+
if (extension === '.pdf')
|
|
60
|
+
return pdf(options);
|
|
61
|
+
if (IMAGE_EXTENSIONS.has(extension))
|
|
62
|
+
return image(options);
|
|
63
|
+
return none(`no extractor for ${extension || 'a file with no extension'}`);
|
|
64
|
+
}
|
|
65
|
+
function none(note) {
|
|
66
|
+
return { text: '', pageCount: null, ocr: false, confidence: null, via: 'none', note };
|
|
67
|
+
}
|
|
68
|
+
async function pdf(options) {
|
|
69
|
+
const binary = await ensureExtractor();
|
|
70
|
+
if (!binary) {
|
|
71
|
+
return none('the extractor could not be built — is the Xcode command line tools package installed?');
|
|
72
|
+
}
|
|
73
|
+
const result = await callSwift(binary, [
|
|
74
|
+
'pdf',
|
|
75
|
+
options.absPath,
|
|
76
|
+
'--ocr-pages',
|
|
77
|
+
String(options.maxOcrPages),
|
|
78
|
+
]);
|
|
79
|
+
if (!result)
|
|
80
|
+
return none('the extractor did not return a result');
|
|
81
|
+
if (result.error)
|
|
82
|
+
return none(result.error);
|
|
83
|
+
return {
|
|
84
|
+
text: result.text.trim(),
|
|
85
|
+
pageCount: result.pages,
|
|
86
|
+
ocr: result.ocr,
|
|
87
|
+
confidence: result.confidence ?? null,
|
|
88
|
+
via: result.ocr ? 'ocr' : 'text-layer',
|
|
89
|
+
...(result.sections?.length ? { sections: result.sections } : {}),
|
|
90
|
+
note: result.ocr && result.pages > options.maxOcrPages
|
|
91
|
+
? `scanned: OCR read the first ${options.maxOcrPages} of ${result.pages} pages`
|
|
92
|
+
: null,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
async function image(options) {
|
|
96
|
+
const binary = await ensureExtractor();
|
|
97
|
+
const result = binary ? await callSwift(binary, ['image', options.absPath]) : null;
|
|
98
|
+
const text = (result?.text ?? '').trim();
|
|
99
|
+
if (text.length > 0) {
|
|
100
|
+
return {
|
|
101
|
+
text,
|
|
102
|
+
pageCount: 1,
|
|
103
|
+
ocr: true,
|
|
104
|
+
confidence: result?.confidence ?? null,
|
|
105
|
+
via: 'ocr',
|
|
106
|
+
note: null,
|
|
107
|
+
sections: [{ page: 1, text }],
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
// **Photos with no text yield no page; OCR still covers scans and
|
|
111
|
+
// screenshots, which is most of what arrives.** With a vision model configured, a
|
|
112
|
+
// photo can still be described — but that is a different claim about the file, so
|
|
113
|
+
// it is labelled `via: 'vision'` and never confused with OCR of real text.
|
|
114
|
+
if (options.vision?.available) {
|
|
115
|
+
const described = await describeImage(options.absPath, options.vision);
|
|
116
|
+
if (described) {
|
|
117
|
+
return { text: described, pageCount: 1, ocr: false, confidence: null, via: 'vision', note: null };
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return none(binary
|
|
121
|
+
? 'no text found in the image, and no vision model is configured to describe it'
|
|
122
|
+
: 'the extractor could not be built, and no vision model is configured');
|
|
123
|
+
}
|
|
124
|
+
async function describeImage(absPath, vision) {
|
|
125
|
+
const data = await fsp.readFile(absPath).catch(() => null);
|
|
126
|
+
if (!data)
|
|
127
|
+
return null;
|
|
128
|
+
const mime = mimeFor(path.extname(absPath).toLowerCase());
|
|
129
|
+
const images = [{ data, mime }];
|
|
130
|
+
const result = await vision.chat([
|
|
131
|
+
{
|
|
132
|
+
role: 'system',
|
|
133
|
+
content: 'Describe an image for a personal knowledge base index, so it can be found again by search. ' +
|
|
134
|
+
'Two or three sentences. Name what it is, what is in it, and any text, date, place or amount ' +
|
|
135
|
+
'you can read. Do not speculate about who took it or why, and do not describe what you cannot ' +
|
|
136
|
+
'see. If it is a document, transcribe the readable text instead of describing it.',
|
|
137
|
+
},
|
|
138
|
+
{ role: 'user', content: 'Describe this image.' },
|
|
139
|
+
], { images, maxTokens: 600 });
|
|
140
|
+
return result.ok && result.value ? result.value.trim() : null;
|
|
141
|
+
}
|
|
142
|
+
function mimeFor(extension) {
|
|
143
|
+
const table = {
|
|
144
|
+
'.png': 'image/png',
|
|
145
|
+
'.jpg': 'image/jpeg',
|
|
146
|
+
'.jpeg': 'image/jpeg',
|
|
147
|
+
'.heic': 'image/heic',
|
|
148
|
+
'.heif': 'image/heif',
|
|
149
|
+
'.webp': 'image/webp',
|
|
150
|
+
'.tiff': 'image/tiff',
|
|
151
|
+
'.tif': 'image/tiff',
|
|
152
|
+
'.gif': 'image/gif',
|
|
153
|
+
'.bmp': 'image/bmp',
|
|
154
|
+
};
|
|
155
|
+
return table[extension] ?? 'application/octet-stream';
|
|
156
|
+
}
|
|
157
|
+
async function callSwift(binary, args) {
|
|
158
|
+
try {
|
|
159
|
+
// 10 MB: a fully OCR'd 12-page scan runs to a few hundred KB, so this is slack
|
|
160
|
+
// rather than a limit anyone will meet.
|
|
161
|
+
const { stdout } = await run(binary, args, { maxBuffer: 10 * 1_048_576, timeout: 300_000 });
|
|
162
|
+
return JSON.parse(stdout);
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
// ─── textutil, which ships with macOS ───────────────────────────────────────
|
|
169
|
+
async function textutil(absPath) {
|
|
170
|
+
try {
|
|
171
|
+
const { stdout } = await run('/usr/bin/textutil', ['-convert', 'txt', '-stdout', absPath], {
|
|
172
|
+
maxBuffer: 10 * 1_048_576,
|
|
173
|
+
timeout: 60_000,
|
|
174
|
+
});
|
|
175
|
+
const text = stdout.trim();
|
|
176
|
+
return text.length > 0
|
|
177
|
+
? { text, pageCount: null, ocr: false, confidence: null, via: 'textutil', note: null }
|
|
178
|
+
: none('textutil found no text');
|
|
179
|
+
}
|
|
180
|
+
catch (err) {
|
|
181
|
+
return none(`textutil could not read the file: ${err instanceof Error ? err.message : String(err)}`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
// ─── Building and caching the helper ────────────────────────────────────────
|
|
185
|
+
let cachedBinary;
|
|
186
|
+
/**
|
|
187
|
+
* Compiles `swift/extract.swift` on first use and reuses it after, keyed by a hash of
|
|
188
|
+
* the source — so upgrading Akno recompiles, and a hand-edited source is picked up.
|
|
189
|
+
*
|
|
190
|
+
* Cached in `~/Library/Caches`, **not** in the state directory. The binary is an
|
|
191
|
+
* artifact of Akno, identical for every knowledge base, and putting it under
|
|
192
|
+
* `state_dir` meant a second knowledge base compiled its own copy of the same 200
|
|
193
|
+
* lines. `Caches` is also the directory macOS is allowed to reclaim, which is exactly
|
|
194
|
+
* right for something rebuildable in six seconds.
|
|
195
|
+
*
|
|
196
|
+
* No `-O`: every expensive thing here happens inside Vision and PDFKit, so optimizing
|
|
197
|
+
* the glue buys nothing and costs 23 of the 29 seconds.
|
|
198
|
+
*/
|
|
199
|
+
async function ensureExtractor() {
|
|
200
|
+
if (cachedBinary !== undefined)
|
|
201
|
+
return cachedBinary;
|
|
202
|
+
const source = findSwiftSource();
|
|
203
|
+
if (!source) {
|
|
204
|
+
cachedBinary = null;
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
const version = sha256(await fsp.readFile(source, 'utf8')).slice(0, 12);
|
|
208
|
+
const binary = path.join(cacheDir(), `akno-extract-${version}`);
|
|
209
|
+
if (fs.existsSync(binary)) {
|
|
210
|
+
cachedBinary = binary;
|
|
211
|
+
return binary;
|
|
212
|
+
}
|
|
213
|
+
try {
|
|
214
|
+
await fsp.mkdir(path.dirname(binary), { recursive: true });
|
|
215
|
+
// Compile to a temp name and rename, so two processes racing on first use cannot
|
|
216
|
+
// leave a half-written binary that the loser then tries to execute.
|
|
217
|
+
const temp = `${binary}.${process.pid}.tmp`;
|
|
218
|
+
await run('swiftc', ['-o', temp, source], { timeout: 180_000 });
|
|
219
|
+
await fsp.rename(temp, binary);
|
|
220
|
+
await fsp.chmod(binary, 0o755);
|
|
221
|
+
cachedBinary = binary;
|
|
222
|
+
return binary;
|
|
223
|
+
}
|
|
224
|
+
catch {
|
|
225
|
+
// Degrade, never fail: plain text and Office formats still extract, and images
|
|
226
|
+
// fall back to the vision model if one is configured.
|
|
227
|
+
cachedBinary = null;
|
|
228
|
+
return null;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
function cacheDir() {
|
|
232
|
+
return process.env.AKNO_CACHE_DIR ?? path.join(os.homedir(), 'Library', 'Caches', 'akno', 'bin');
|
|
233
|
+
}
|
|
234
|
+
/** Beside `dist` when installed, at the package root when running from source. */
|
|
235
|
+
function findSwiftSource() {
|
|
236
|
+
for (const up of ['..', '../..', '../../..', '../../../..']) {
|
|
237
|
+
const candidate = path.resolve(import.meta.dirname, up, 'swift', 'extract.swift');
|
|
238
|
+
if (fs.existsSync(candidate))
|
|
239
|
+
return candidate;
|
|
240
|
+
}
|
|
241
|
+
return null;
|
|
242
|
+
}
|
|
243
|
+
/** What `doctor` reports, so a missing capability is visible rather than surprising. */
|
|
244
|
+
export async function extractionCapabilities() {
|
|
245
|
+
const binary = await ensureExtractor();
|
|
246
|
+
return {
|
|
247
|
+
swift: binary !== null,
|
|
248
|
+
textutil: fs.existsSync('/usr/bin/textutil'),
|
|
249
|
+
note: binary
|
|
250
|
+
? null
|
|
251
|
+
: 'PDF and image extraction is unavailable: the Swift helper could not be built. ' +
|
|
252
|
+
'Install the Xcode command line tools (`xcode-select --install`).',
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
//# sourceMappingURL=extract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract.js","sourceRoot":"","sources":["../../src/ingest/extract.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ingest` pulls documents from a file, a folder, or a URL. This is the URL.
|
|
3
|
+
*
|
|
4
|
+
* Downloading is the one thing `ingest` does that reaches outside the machine, so the
|
|
5
|
+
* limits are deliberate rather than defensive-by-habit:
|
|
6
|
+
*
|
|
7
|
+
* - **http and https only.** `file://` would make `ingest({url})` a way to read any
|
|
8
|
+
* path on the machine through an interface that looks like it fetches the web, and
|
|
9
|
+
* `data:` would smuggle bytes past the size cap.
|
|
10
|
+
* - **Redirects are followed** by `fetch`, which caps the chain itself; a redirect is
|
|
11
|
+
* normal and an infinite one is already handled below us.
|
|
12
|
+
* - **The size cap applies to what arrives, not to what the server claims.** A
|
|
13
|
+
* `Content-Length` is a promise, and the stream is what actually lands on disk.
|
|
14
|
+
* - **The filename comes from the response, then the URL, then the content type.** A
|
|
15
|
+
* URL path is often `/download` or `/`, which says nothing — and a name adding nothing is
|
|
16
|
+
* exactly what naming-from-content replaces.
|
|
17
|
+
*/
|
|
18
|
+
export interface Fetched {
|
|
19
|
+
/** A temp file. The caller ingests it and is responsible for cleaning up. */
|
|
20
|
+
path: string;
|
|
21
|
+
/** What the server called it, for the rename guard. */
|
|
22
|
+
originalName: string;
|
|
23
|
+
contentType: string | null;
|
|
24
|
+
bytes: number;
|
|
25
|
+
finalUrl: string;
|
|
26
|
+
}
|
|
27
|
+
export interface FetchOptions {
|
|
28
|
+
url: string;
|
|
29
|
+
maxBytes: number;
|
|
30
|
+
timeoutMs?: number;
|
|
31
|
+
}
|
|
32
|
+
export declare function fetchDocument(options: FetchOptions): Promise<Fetched>;
|
|
33
|
+
/** The temp directory a fetch created. Removed once the bytes have been stored. */
|
|
34
|
+
export declare function cleanupFetch(fetched: Fetched): Promise<void>;
|
|
35
|
+
//# sourceMappingURL=fetch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/ingest/fetch.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,WAAW,OAAO;IACtB,6EAA6E;IAC7E,IAAI,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,CA4D3E;AAED,mFAAmF;AACnF,wBAAsB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAElE"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import fsp from 'node:fs/promises';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { AknoError } from '@tenphi/akno-protocol';
|
|
5
|
+
export async function fetchDocument(options) {
|
|
6
|
+
const url = parseUrl(options.url);
|
|
7
|
+
let response;
|
|
8
|
+
try {
|
|
9
|
+
response = await fetch(url, {
|
|
10
|
+
redirect: 'follow',
|
|
11
|
+
signal: AbortSignal.timeout(options.timeoutMs ?? 60_000),
|
|
12
|
+
headers: { accept: '*/*' },
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
const timedOut = err instanceof Error && (err.name === 'TimeoutError' || err.name === 'AbortError');
|
|
17
|
+
throw new AknoError('unavailable', timedOut
|
|
18
|
+
? `fetching ${url.href} timed out`
|
|
19
|
+
: `could not fetch ${url.href}: ${err instanceof Error ? err.message : String(err)}`);
|
|
20
|
+
}
|
|
21
|
+
if (!response.ok) {
|
|
22
|
+
throw new AknoError('unavailable', `${url.href} returned ${response.status} ${response.statusText}`);
|
|
23
|
+
}
|
|
24
|
+
if (!response.body) {
|
|
25
|
+
throw new AknoError('unavailable', `${url.href} returned no body`);
|
|
26
|
+
}
|
|
27
|
+
const contentType = (response.headers.get('content-type') ?? '').split(';')[0].trim() || null;
|
|
28
|
+
const originalName = filenameFor(response, url, contentType);
|
|
29
|
+
const directory = await fsp.mkdtemp(path.join(os.tmpdir(), 'akno-fetch-'));
|
|
30
|
+
const target = path.join(directory, originalName);
|
|
31
|
+
const handle = await fsp.open(target, 'w');
|
|
32
|
+
let written = 0;
|
|
33
|
+
try {
|
|
34
|
+
for await (const chunk of response.body) {
|
|
35
|
+
written += chunk.byteLength;
|
|
36
|
+
// Enforced against the bytes that actually arrive: `Content-Length` is a claim,
|
|
37
|
+
// and a server willing to lie about the size is exactly the one to guard against.
|
|
38
|
+
if (written > options.maxBytes) {
|
|
39
|
+
await handle.close();
|
|
40
|
+
await fsp.rm(directory, { recursive: true, force: true });
|
|
41
|
+
throw new AknoError('invalid', `${url.href} is larger than the configured limit of ${Math.round(options.maxBytes / 1_048_576)} MB`);
|
|
42
|
+
}
|
|
43
|
+
await handle.write(chunk);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
finally {
|
|
47
|
+
await handle.close().catch(() => { });
|
|
48
|
+
}
|
|
49
|
+
if (written === 0) {
|
|
50
|
+
await fsp.rm(directory, { recursive: true, force: true });
|
|
51
|
+
throw new AknoError('unavailable', `${url.href} returned an empty body`);
|
|
52
|
+
}
|
|
53
|
+
return { path: target, originalName, contentType, bytes: written, finalUrl: response.url || url.href };
|
|
54
|
+
}
|
|
55
|
+
/** The temp directory a fetch created. Removed once the bytes have been stored. */
|
|
56
|
+
export async function cleanupFetch(fetched) {
|
|
57
|
+
await fsp.rm(path.dirname(fetched.path), { recursive: true, force: true });
|
|
58
|
+
}
|
|
59
|
+
function parseUrl(raw) {
|
|
60
|
+
let url;
|
|
61
|
+
try {
|
|
62
|
+
url = new URL(raw);
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
throw new AknoError('invalid', `not a usable URL: ${raw}`);
|
|
66
|
+
}
|
|
67
|
+
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
|
|
68
|
+
throw new AknoError('invalid', `only http and https URLs are fetched, not ${url.protocol} — pass a local path instead`);
|
|
69
|
+
}
|
|
70
|
+
return url;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* `Content-Disposition`, then the URL's last path segment, then an extension guessed
|
|
74
|
+
* from the content type. Every one of these can be useless, which is fine: the page is named
|
|
75
|
+
* from the content anyway, and a useless name is what triggers the rename.
|
|
76
|
+
*/
|
|
77
|
+
function filenameFor(response, url, contentType) {
|
|
78
|
+
const disposition = response.headers.get('content-disposition');
|
|
79
|
+
const candidates = [];
|
|
80
|
+
if (disposition) {
|
|
81
|
+
const star = /filename\*=(?:UTF-8'')?([^;]+)/i.exec(disposition);
|
|
82
|
+
const plain = /filename="?([^";]+)"?/i.exec(disposition);
|
|
83
|
+
const raw = star?.[1] ?? plain?.[1];
|
|
84
|
+
// `path.basename` is what stops `../../../etc/passwd` being a path: a server chooses
|
|
85
|
+
// this header, so it is untrusted input that becomes a filename.
|
|
86
|
+
if (raw)
|
|
87
|
+
candidates.push(sanitize(path.basename(safeDecode(raw.trim()))));
|
|
88
|
+
}
|
|
89
|
+
candidates.push(sanitize(path.basename(safeDecode(url.pathname))));
|
|
90
|
+
const extension = extensionFor(contentType);
|
|
91
|
+
for (const candidate of candidates) {
|
|
92
|
+
if (candidate.length === 0 || candidate === '.' || candidate === '..')
|
|
93
|
+
continue;
|
|
94
|
+
// The extractor dispatches on the extension, so a name without one is unusable even
|
|
95
|
+
// though it reads fine. Servers send `filename="report"` often enough that guessing
|
|
96
|
+
// from the content type is the difference between working and skipping.
|
|
97
|
+
return path.extname(candidate) ? candidate : `${candidate}${extension}`;
|
|
98
|
+
}
|
|
99
|
+
return `download${extension}`;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* A server chooses these bytes, so they are untrusted input on their way to becoming a
|
|
103
|
+
* filename: separators and control characters are dropped. Spaces survive, because a
|
|
104
|
+
* filename with spaces is ordinary and the rename handles presentation anyway.
|
|
105
|
+
*/
|
|
106
|
+
function sanitize(name) {
|
|
107
|
+
return [...name]
|
|
108
|
+
.filter((char) => char !== '/' && char !== '\\' && char.codePointAt(0) >= 0x20)
|
|
109
|
+
.join('')
|
|
110
|
+
.trim();
|
|
111
|
+
}
|
|
112
|
+
function safeDecode(value) {
|
|
113
|
+
try {
|
|
114
|
+
return decodeURIComponent(value);
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
return value;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
function extensionFor(contentType) {
|
|
121
|
+
const table = {
|
|
122
|
+
'application/pdf': '.pdf',
|
|
123
|
+
'text/plain': '.txt',
|
|
124
|
+
'text/markdown': '.md',
|
|
125
|
+
'text/html': '.html',
|
|
126
|
+
'text/csv': '.csv',
|
|
127
|
+
'application/json': '.json',
|
|
128
|
+
'image/png': '.png',
|
|
129
|
+
'image/jpeg': '.jpg',
|
|
130
|
+
'image/heic': '.heic',
|
|
131
|
+
'image/webp': '.webp',
|
|
132
|
+
'image/gif': '.gif',
|
|
133
|
+
'image/tiff': '.tiff',
|
|
134
|
+
'application/rtf': '.rtf',
|
|
135
|
+
'application/msword': '.doc',
|
|
136
|
+
'application/vnd.openxmlformats-officedocument.wordprocessingml.document': '.docx',
|
|
137
|
+
};
|
|
138
|
+
// No extension at all is honest: the extractor dispatches on it and will say it has
|
|
139
|
+
// none, which is better than claiming `.bin` and looking like a decision.
|
|
140
|
+
return contentType ? (table[contentType] ?? '') : '';
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=fetch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../src/ingest/fetch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { AknoContext } from '../context.ts';
|
|
2
|
+
/**
|
|
3
|
+
* **The inbox: a folder where you drop anything and it files itself.**
|
|
4
|
+
*
|
|
5
|
+
* ```jsonc
|
|
6
|
+
* "inbox/**": { "ingest": "auto", "route": true }
|
|
7
|
+
* ```
|
|
8
|
+
*
|
|
9
|
+
* `route: true` is what makes it an inbox rather than just a folder. On arrival Akno
|
|
10
|
+
* extracts, names, summarizes, and then **routes** — the same recall-based routing
|
|
11
|
+
* `remember` uses, against the same threshold. Above it, the file and its page move
|
|
12
|
+
* there. Below it, the file **stays in the inbox** with a proposal attached.
|
|
13
|
+
*
|
|
14
|
+
* That failure mode is deliberate: an unrouted file sits visibly where you dropped it,
|
|
15
|
+
* rather than being filed confidently into the wrong place, where you would never look
|
|
16
|
+
* for it. **An inbox with three things in it is a to-do list. A misfiled document is a
|
|
17
|
+
* lost one.**
|
|
18
|
+
*
|
|
19
|
+
* **The inbox is the only place Akno moves files.** A file dropped straight into
|
|
20
|
+
* `documents/` was put there on purpose; Akno will name it, page it and index it, but
|
|
21
|
+
* never relocate it. Automatic filing is opt-in per folder, every move is journalled and
|
|
22
|
+
* reported in `doctor`, and every one is reversible with `undo`.
|
|
23
|
+
*/
|
|
24
|
+
export interface InboxResult {
|
|
25
|
+
/** Files that found a home and moved out. */
|
|
26
|
+
filed: {
|
|
27
|
+
source: string;
|
|
28
|
+
slug: string;
|
|
29
|
+
}[];
|
|
30
|
+
/** Files still sitting in the inbox, each with the reason. */
|
|
31
|
+
waiting: {
|
|
32
|
+
source: string;
|
|
33
|
+
reason: string;
|
|
34
|
+
proposalId?: string;
|
|
35
|
+
}[];
|
|
36
|
+
/** Files skipped by rule or because they are not documents at all. */
|
|
37
|
+
skipped: {
|
|
38
|
+
source: string;
|
|
39
|
+
reason: string;
|
|
40
|
+
}[];
|
|
41
|
+
}
|
|
42
|
+
/** True when a relative path sits inside a configured inbox. */
|
|
43
|
+
export declare function isInInbox(ctx: AknoContext, relPath: string): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Processes everything currently sitting in the inbox. Safe to call repeatedly: a file
|
|
46
|
+
* that could not be routed stays put and is simply reconsidered next time, which is what
|
|
47
|
+
* makes the inbox a to-do list rather than a queue that loses things.
|
|
48
|
+
*/
|
|
49
|
+
export declare function processInbox(ctx: AknoContext, options?: {
|
|
50
|
+
only?: string[];
|
|
51
|
+
limit?: number;
|
|
52
|
+
}): Promise<InboxResult>;
|
|
53
|
+
//# sourceMappingURL=inbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbox.d.ts","sourceRoot":"","sources":["../../src/ingest/inbox.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAIjD;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,MAAM,WAAW,WAAW;IAC1B,6CAA6C;IAC7C,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC1C,8DAA8D;IAC9D,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACnE,sEAAsE;IACtE,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC/C;AAuBD,gEAAgE;AAChE,wBAAgB,SAAS,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAGpE;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,WAAW,EAChB,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAChD,OAAO,CAAC,WAAW,CAAC,CA4EtB"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import fsp from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { effectiveRule } from "../rules/compile.js";
|
|
4
|
+
import { ingestFile } from "../ops/ingest.js";
|
|
5
|
+
/**
|
|
6
|
+
* Folders that behave as an inbox: the reserved `inbox/`, plus any folder whose rule
|
|
7
|
+
* carries `route: true`.
|
|
8
|
+
*
|
|
9
|
+
* The reserved one is always included, not used as a fallback. Akno *creates* it on
|
|
10
|
+
* startup with a README saying its contents are extracted, named and routed — so a user
|
|
11
|
+
* declaring a second inbox somewhere else must not silently turn the first one into a
|
|
12
|
+
* folder that quietly accumulates files nobody looks at again.
|
|
13
|
+
*/
|
|
14
|
+
function inboxFolders(ctx) {
|
|
15
|
+
const folders = new Set([ctx.config.paths.inbox]);
|
|
16
|
+
for (const rule of ctx.config.rules) {
|
|
17
|
+
if (rule.route !== true)
|
|
18
|
+
continue;
|
|
19
|
+
// `inbox/**` → `inbox`. A rule's glob is how the folder is named, so an inbox is
|
|
20
|
+
// wherever the user said it is rather than a hardcoded path.
|
|
21
|
+
const folder = rule.glob.replace(/\/\*\*?$/, '').replace(/\/$/, '');
|
|
22
|
+
if (folder.length > 0 && !folder.includes('*'))
|
|
23
|
+
folders.add(folder);
|
|
24
|
+
}
|
|
25
|
+
return [...folders];
|
|
26
|
+
}
|
|
27
|
+
/** True when a relative path sits inside a configured inbox. */
|
|
28
|
+
export function isInInbox(ctx, relPath) {
|
|
29
|
+
const normalized = relPath.replace(/\\/g, '/');
|
|
30
|
+
return inboxFolders(ctx).some((folder) => normalized === folder || normalized.startsWith(`${folder}/`));
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Processes everything currently sitting in the inbox. Safe to call repeatedly: a file
|
|
34
|
+
* that could not be routed stays put and is simply reconsidered next time, which is what
|
|
35
|
+
* makes the inbox a to-do list rather than a queue that loses things.
|
|
36
|
+
*/
|
|
37
|
+
export async function processInbox(ctx, options = {}) {
|
|
38
|
+
const result = { filed: [], waiting: [], skipped: [] };
|
|
39
|
+
const limit = options.limit ?? 50;
|
|
40
|
+
let processed = 0;
|
|
41
|
+
for (const folder of inboxFolders(ctx)) {
|
|
42
|
+
const absFolder = path.join(ctx.config.aknoPath, folder);
|
|
43
|
+
let entries;
|
|
44
|
+
try {
|
|
45
|
+
entries = (await fsp.readdir(absFolder, { withFileTypes: true }))
|
|
46
|
+
.filter((entry) => entry.isFile() && !entry.name.startsWith('.'))
|
|
47
|
+
.map((entry) => entry.name)
|
|
48
|
+
.sort();
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
continue; // No inbox on disk yet. Nothing to do, and nothing to report.
|
|
52
|
+
}
|
|
53
|
+
for (const name of entries) {
|
|
54
|
+
if (processed >= limit)
|
|
55
|
+
break;
|
|
56
|
+
const relPath = `${folder}/${name}`;
|
|
57
|
+
if (options.only && !options.only.includes(relPath))
|
|
58
|
+
continue;
|
|
59
|
+
// A page written *about* an inbox item, and the README startup puts there, are not
|
|
60
|
+
// arrivals to be filed.
|
|
61
|
+
if (ctx.config.pageExtensions.includes(path.extname(name).toLowerCase())) {
|
|
62
|
+
result.skipped.push({ source: relPath, reason: 'a Markdown page, not a dropped document' });
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
const rule = effectiveRule(relPath.replace(/\.[^.]+$/, ''), ctx.config.rules);
|
|
66
|
+
if (rule.ingest === 'ignore') {
|
|
67
|
+
result.skipped.push({ source: relPath, reason: 'ingest: ignore' });
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
processed++;
|
|
71
|
+
try {
|
|
72
|
+
const ingested = await ingestFile(ctx,
|
|
73
|
+
// No `folder`: the inbox exists precisely so routing decides. Passing one would
|
|
74
|
+
// make it an ordinary folder with extra steps.
|
|
75
|
+
{ route: true }, {
|
|
76
|
+
source: path.join(ctx.config.aknoPath, relPath),
|
|
77
|
+
originalName: name,
|
|
78
|
+
// The one place Akno moves files.
|
|
79
|
+
move: true,
|
|
80
|
+
});
|
|
81
|
+
if (ingested.outcome === 'ok' && ingested.slug) {
|
|
82
|
+
result.filed.push({ source: relPath, slug: ingested.slug });
|
|
83
|
+
}
|
|
84
|
+
else if (ingested.outcome === 'duplicate') {
|
|
85
|
+
// Already stored under another name. Leaving the copy in the inbox is the
|
|
86
|
+
// honest outcome: deleting a file the user put there is not Akno's call.
|
|
87
|
+
result.waiting.push({
|
|
88
|
+
source: relPath,
|
|
89
|
+
reason: `already stored as ${ingested.rel_path} — delete this copy if you meant to`,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
result.waiting.push({
|
|
94
|
+
source: relPath,
|
|
95
|
+
reason: ingested.note ?? ingested.outcome,
|
|
96
|
+
...(ingested.approval ? { proposalId: ingested.approval.proposal_id } : {}),
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
result.waiting.push({
|
|
102
|
+
source: relPath,
|
|
103
|
+
reason: err instanceof Error ? err.message : String(err),
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return result;
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=inbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbox.js","sourceRoot":"","sources":["../../src/ingest/inbox.ts"],"names":[],"mappings":"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"}
|