@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,143 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* **FSEvents, not polling.** Node's recursive `fs.watch` uses FSEvents on
|
|
5
|
+
* macOS: native, cheap, and it reports renames as renames.
|
|
6
|
+
*
|
|
7
|
+
* But FSEvents coalesces under load and can drop events after a sleep/wake or a
|
|
8
|
+
* large sync, so a **periodic hash sweep is the backstop.** Watching alone is not
|
|
9
|
+
* a correctness guarantee; hashing is. At ~10ms for a typical knowledge base the
|
|
10
|
+
* sweep can run every few minutes and cost nothing.
|
|
11
|
+
*/
|
|
12
|
+
export class Watcher {
|
|
13
|
+
watcher = null;
|
|
14
|
+
sweepTimer = null;
|
|
15
|
+
verifyTimer = null;
|
|
16
|
+
debounceTimer = null;
|
|
17
|
+
pending = new Set();
|
|
18
|
+
running = false;
|
|
19
|
+
/** Set when a change arrived mid-index; guarantees one more pass after it. */
|
|
20
|
+
dirty = false;
|
|
21
|
+
#config;
|
|
22
|
+
#indexer;
|
|
23
|
+
#events;
|
|
24
|
+
constructor(config, indexer, events = {}) {
|
|
25
|
+
this.#config = config;
|
|
26
|
+
this.#indexer = indexer;
|
|
27
|
+
this.#events = events;
|
|
28
|
+
}
|
|
29
|
+
start() {
|
|
30
|
+
if (this.watcher)
|
|
31
|
+
return;
|
|
32
|
+
try {
|
|
33
|
+
this.watcher = fs.watch(this.#config.aknoPath, { recursive: true, persistent: true }, (_type, filename) => {
|
|
34
|
+
if (!filename) {
|
|
35
|
+
// A null filename means FSEvents coalesced and cannot say what moved.
|
|
36
|
+
// The only correct response is to treat the whole tree as suspect.
|
|
37
|
+
this.dirty = true;
|
|
38
|
+
this.schedule();
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const relPath = filename.split(path.sep).join('/');
|
|
42
|
+
if (this.shouldIgnore(relPath))
|
|
43
|
+
return;
|
|
44
|
+
this.pending.add(relPath);
|
|
45
|
+
this.schedule();
|
|
46
|
+
});
|
|
47
|
+
this.watcher.on('error', (error) => this.#events.onError?.(error));
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
// A watch that cannot be established is not fatal: the sweep below still
|
|
51
|
+
// reconciles, just with more latency.
|
|
52
|
+
this.#events.onError?.(error);
|
|
53
|
+
}
|
|
54
|
+
if (this.#config.watch.sweepIntervalMs > 0) {
|
|
55
|
+
this.sweepTimer = setInterval(() => {
|
|
56
|
+
this.dirty = true;
|
|
57
|
+
void this.flush();
|
|
58
|
+
}, this.#config.watch.sweepIntervalMs);
|
|
59
|
+
this.sweepTimer.unref();
|
|
60
|
+
}
|
|
61
|
+
if (this.#config.watch.verifyIntervalMs > 0) {
|
|
62
|
+
// The correctness path: a full hash sweep that catches a sync client or a
|
|
63
|
+
// restored backup which preserved mtime across a real content change.
|
|
64
|
+
this.verifyTimer = setInterval(() => {
|
|
65
|
+
void this.flush({ verify: true });
|
|
66
|
+
}, this.#config.watch.verifyIntervalMs);
|
|
67
|
+
this.verifyTimer.unref();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* The service reconciles on wake — the gap where a laptop was closed is
|
|
72
|
+
* exactly when the folder gets edited on another device. A host that knows about
|
|
73
|
+
* sleep/wake calls this; the periodic sweep covers the case where nothing does.
|
|
74
|
+
*/
|
|
75
|
+
reconcileNow() {
|
|
76
|
+
this.dirty = true;
|
|
77
|
+
return this.flush({ verify: true });
|
|
78
|
+
}
|
|
79
|
+
async stop() {
|
|
80
|
+
this.watcher?.close();
|
|
81
|
+
this.watcher = null;
|
|
82
|
+
if (this.sweepTimer)
|
|
83
|
+
clearInterval(this.sweepTimer);
|
|
84
|
+
if (this.verifyTimer)
|
|
85
|
+
clearInterval(this.verifyTimer);
|
|
86
|
+
if (this.debounceTimer)
|
|
87
|
+
clearTimeout(this.debounceTimer);
|
|
88
|
+
this.sweepTimer = this.verifyTimer = this.debounceTimer = null;
|
|
89
|
+
}
|
|
90
|
+
shouldIgnore(relPath) {
|
|
91
|
+
const segments = relPath.split('/');
|
|
92
|
+
if (segments.some((segment) => segment.startsWith('.')))
|
|
93
|
+
return true;
|
|
94
|
+
if (segments.some((segment) => this.#config.ignore.includes(segment)))
|
|
95
|
+
return true;
|
|
96
|
+
// Editors and sync clients write to a temp name then rename. Indexing the
|
|
97
|
+
// temp file wastes a pass and briefly indexes a partial page.
|
|
98
|
+
const base = segments.at(-1) ?? '';
|
|
99
|
+
return /(^~|\.tmp$|\.swp$|\.crdownload$|\.part$|^\.#|~$)/.test(base);
|
|
100
|
+
}
|
|
101
|
+
schedule() {
|
|
102
|
+
if (this.debounceTimer)
|
|
103
|
+
clearTimeout(this.debounceTimer);
|
|
104
|
+
// FSEvents coalesces, but an editor still produces a write storm on save.
|
|
105
|
+
this.debounceTimer = setTimeout(() => void this.flush(), this.#config.watch.debounceMs);
|
|
106
|
+
}
|
|
107
|
+
async flush(options = {}) {
|
|
108
|
+
if (this.running) {
|
|
109
|
+
// A change that arrived while indexing must not be lost to the guard.
|
|
110
|
+
this.dirty = true;
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const changed = [...this.pending];
|
|
114
|
+
const wholeTree = this.dirty || options.verify;
|
|
115
|
+
if (changed.length === 0 && !wholeTree)
|
|
116
|
+
return;
|
|
117
|
+
this.pending.clear();
|
|
118
|
+
this.dirty = false;
|
|
119
|
+
this.running = true;
|
|
120
|
+
try {
|
|
121
|
+
const report = await this.#indexer.run({
|
|
122
|
+
...(options.verify ? { verify: true } : {}),
|
|
123
|
+
// A targeted pass cannot conclude anything about deletions, so a
|
|
124
|
+
// coalesced or swept run deliberately walks the whole tree.
|
|
125
|
+
...(wholeTree ? {} : { only: changed }),
|
|
126
|
+
});
|
|
127
|
+
this.#events.onIndexed?.(report, changed);
|
|
128
|
+
// After indexing, so an inbox handler sees a knowledge base that already knows
|
|
129
|
+
// about the file it is about to move.
|
|
130
|
+
if (this.#events.onArrival)
|
|
131
|
+
await this.#events.onArrival(changed);
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
this.#events.onError?.(error);
|
|
135
|
+
}
|
|
136
|
+
finally {
|
|
137
|
+
this.running = false;
|
|
138
|
+
if (this.dirty || this.pending.size > 0)
|
|
139
|
+
this.schedule();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=watcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watcher.js","sourceRoot":"","sources":["../../src/watch/watcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Store } from '../store/db.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Every byte Akno writes into the knowledge base goes through here.
|
|
4
|
+
*
|
|
5
|
+
* Two properties, both of which matter more than they look:
|
|
6
|
+
*
|
|
7
|
+
* **Atomic.** Write a sibling temp file, fsync it, rename over the target. A
|
|
8
|
+
* rename within one APFS directory is atomic, so a reader — the watcher, an
|
|
9
|
+
* editor, a sync client, `recall` reading lines off disk — never sees a half-
|
|
10
|
+
* written page. Writing in place would let a crash or a concurrent read catch a
|
|
11
|
+
* truncated file, and the truncated version is what gets indexed and cited.
|
|
12
|
+
*
|
|
13
|
+
* **Self-aware.** The resulting hash, size and mtime are recorded in `files`
|
|
14
|
+
* immediately, so the watcher recognises Akno's own write and does not schedule
|
|
15
|
+
* a re-index of a page it already has. That promise about the `id`
|
|
16
|
+
* write; it has to hold for every write or the watcher chases its own tail.
|
|
17
|
+
*/
|
|
18
|
+
export interface WriteResult {
|
|
19
|
+
relPath: string;
|
|
20
|
+
absPath: string;
|
|
21
|
+
/** Bytes before the write. Null when the file did not exist. */
|
|
22
|
+
before: string | null;
|
|
23
|
+
after: string;
|
|
24
|
+
created: boolean;
|
|
25
|
+
}
|
|
26
|
+
export declare function writeFileAtomic(aknoPath: string, relPath: string, content: string): Promise<WriteResult>;
|
|
27
|
+
/**
|
|
28
|
+
* Records Akno's own write in `files` so the next sweep sees nothing changed.
|
|
29
|
+
* Called after the write and inside the same transaction as the journal entry.
|
|
30
|
+
*/
|
|
31
|
+
export declare function recordOwnWrite(store: Store, aknoPath: string, relPath: string, content: string, pageId: string | null): void;
|
|
32
|
+
/** Restores a file to exact prior bytes, or removes it if there were none. */
|
|
33
|
+
export declare function restoreFile(aknoPath: string, relPath: string, before: string | null): Promise<void>;
|
|
34
|
+
//# sourceMappingURL=atomic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atomic.d.ts","sourceRoot":"","sources":["../../src/write/atomic.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAE5C;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;CAClB;AAKD,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,WAAW,CAAC,CAyBtB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GAAG,IAAI,GACpB,IAAI,CAqBN;AAED,8EAA8E;AAC9E,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAMzG"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import fsp from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { sha256 } from "../store/ids.js";
|
|
5
|
+
/** The temp suffix the watcher already ignores, so a write never wakes it twice. */
|
|
6
|
+
const TEMP_SUFFIX = '.akno.tmp';
|
|
7
|
+
export async function writeFileAtomic(aknoPath, relPath, content) {
|
|
8
|
+
const absPath = path.join(aknoPath, relPath);
|
|
9
|
+
await fsp.mkdir(path.dirname(absPath), { recursive: true });
|
|
10
|
+
let before = null;
|
|
11
|
+
try {
|
|
12
|
+
before = await fsp.readFile(absPath, 'utf8');
|
|
13
|
+
}
|
|
14
|
+
catch (err) {
|
|
15
|
+
if (err.code !== 'ENOENT')
|
|
16
|
+
throw err;
|
|
17
|
+
}
|
|
18
|
+
const tempPath = `${absPath}${TEMP_SUFFIX}`;
|
|
19
|
+
const handle = await fsp.open(tempPath, 'w', 0o644);
|
|
20
|
+
try {
|
|
21
|
+
await handle.writeFile(content, 'utf8');
|
|
22
|
+
// Without the fsync the rename can land before the data does, and a crash in
|
|
23
|
+
// that window leaves a correctly-named empty file — the worst outcome, because
|
|
24
|
+
// it looks like a page the user emptied on purpose.
|
|
25
|
+
await handle.sync();
|
|
26
|
+
}
|
|
27
|
+
finally {
|
|
28
|
+
await handle.close();
|
|
29
|
+
}
|
|
30
|
+
await fsp.rename(tempPath, absPath);
|
|
31
|
+
return { relPath, absPath, before, after: content, created: before === null };
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Records Akno's own write in `files` so the next sweep sees nothing changed.
|
|
35
|
+
* Called after the write and inside the same transaction as the journal entry.
|
|
36
|
+
*/
|
|
37
|
+
export function recordOwnWrite(store, aknoPath, relPath, content, pageId) {
|
|
38
|
+
// `bigint: true` to match the scanner exactly. A float mtime loses precision
|
|
39
|
+
// above ~2^53 ns, and a value that differs from what the scanner would read is
|
|
40
|
+
// worse than none — it defeats the stat fast path on every single sweep.
|
|
41
|
+
const stat = fs.statSync(path.join(aknoPath, relPath), { bigint: true, throwIfNoEntry: false });
|
|
42
|
+
store.db
|
|
43
|
+
.prepare(`INSERT INTO files(rel_path, size, mtime_ns, sha256, kind, page_id, indexed_at)
|
|
44
|
+
VALUES(?, ?, ?, ?, 'page', ?, ?)
|
|
45
|
+
ON CONFLICT(rel_path) DO UPDATE SET
|
|
46
|
+
size = excluded.size, mtime_ns = excluded.mtime_ns, sha256 = excluded.sha256,
|
|
47
|
+
page_id = excluded.page_id, indexed_at = excluded.indexed_at`)
|
|
48
|
+
.run(relPath, Buffer.byteLength(content, 'utf8'), stat ? String(stat.mtimeNs) : '0', sha256(content), pageId, new Date().toISOString());
|
|
49
|
+
}
|
|
50
|
+
/** Restores a file to exact prior bytes, or removes it if there were none. */
|
|
51
|
+
export async function restoreFile(aknoPath, relPath, before) {
|
|
52
|
+
if (before === null) {
|
|
53
|
+
await fsp.rm(path.join(aknoPath, relPath), { force: true });
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
await writeFileAtomic(aknoPath, relPath, before);
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=atomic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atomic.js","sourceRoot":"","sources":["../../src/write/atomic.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,GAAG,MAAM,kBAAkB,CAAC;AACnC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AA6BzC,oFAAoF;AACpF,MAAM,WAAW,GAAG,WAAW,CAAC;AAEhC,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,QAAgB,EAChB,OAAe,EACf,OAAe;IAEf,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC7C,MAAM,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE5D,IAAI,MAAM,GAAkB,IAAI,CAAC;IACjC,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC/C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ;YAAE,MAAM,GAAG,CAAC;IAClE,CAAC;IAED,MAAM,QAAQ,GAAG,GAAG,OAAO,GAAG,WAAW,EAAE,CAAC;IAC5C,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;IACpD,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACxC,6EAA6E;QAC7E,+EAA+E;QAC/E,oDAAoD;QACpD,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;IACtB,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;IACD,MAAM,GAAG,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAEpC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,EAAE,CAAC;AAChF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAC5B,KAAY,EACZ,QAAgB,EAChB,OAAe,EACf,OAAe,EACf,MAAqB;IAErB,6EAA6E;IAC7E,+EAA+E;IAC/E,yEAAyE;IACzE,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAC;IAChG,KAAK,CAAC,EAAE;SACL,OAAO,CACN;;;;sEAIgE,CACjE;SACA,GAAG,CACF,OAAO,EACP,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,EAClC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,EACjC,MAAM,CAAC,OAAO,CAAC,EACf,MAAM,EACN,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CACzB,CAAC;AACN,CAAC;AAED,8EAA8E;AAC9E,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,QAAgB,EAAE,OAAe,EAAE,MAAqB;IACxF,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACpB,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,OAAO;IACT,CAAC;IACD,MAAM,eAAe,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AACnD,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { ConflictReport } from '@tenphi/akno-protocol';
|
|
2
|
+
import type { Store } from '../store/db.ts';
|
|
3
|
+
/**
|
|
4
|
+
* Two values differ *meaningfully* when their comparable cores differ. Reached
|
|
5
|
+
* only for values that already contain a number or a decisive word, so this is
|
|
6
|
+
* about "€33 vs €33/month" (same) against "€33 vs €47" (different).
|
|
7
|
+
*
|
|
8
|
+
* Exported for the thorough pass, which joins facts across the whole knowledge base and
|
|
9
|
+
* has to decide "differ" exactly the way the inline check does. Two answers to that question
|
|
10
|
+
* would mean the cycle reporting conflicts a write would have allowed, or missing ones it
|
|
11
|
+
* would have blocked.
|
|
12
|
+
*/
|
|
13
|
+
export declare function valuesConflict(existing: string, incoming: string): boolean;
|
|
14
|
+
export interface ConflictOptions {
|
|
15
|
+
store: Store;
|
|
16
|
+
pageId: string;
|
|
17
|
+
slug: string;
|
|
18
|
+
/** The page as it stands. Compared against, line for line. */
|
|
19
|
+
body: string;
|
|
20
|
+
/** Line number the body starts at, so a report addresses the real line. */
|
|
21
|
+
bodyStartLine: number;
|
|
22
|
+
/** The text being written. */
|
|
23
|
+
incoming: string;
|
|
24
|
+
/** Echo of a token the caller already resolved with the user. */
|
|
25
|
+
resolveToken?: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Returns the first genuine conflict, or null. First rather than all: a caller has
|
|
29
|
+
* to take this to the user, and one clear question beats a list.
|
|
30
|
+
*
|
|
31
|
+
* Both sides go through the **same extractor**, which is the whole trick. The first
|
|
32
|
+
* implementation compared a structurally-extracted attribute from the incoming text
|
|
33
|
+
* against the `attribute` a model had assigned to an existing fact — and those are
|
|
34
|
+
* different vocabularies. Appending `- Nights: 5` over an existing `- Nights: 3`
|
|
35
|
+
* produced no conflict at all, because the model had labelled the existing line's
|
|
36
|
+
* attribute `total` while the extractor read the new one as `nights`. Two names for
|
|
37
|
+
* the same thing never join.
|
|
38
|
+
*
|
|
39
|
+
* Comparing the page's own lines against the incoming lines also means conflict
|
|
40
|
+
* detection **works with no chat model at all**, which is what makes it cheap.
|
|
41
|
+
*/
|
|
42
|
+
export declare function detectConflict(options: ConflictOptions): ConflictReport | null;
|
|
43
|
+
//# sourceMappingURL=conflict.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conflict.d.ts","sourceRoot":"","sources":["../../src/write/conflict.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAqE5C;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAc1E;AAWD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,KAAK,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,8DAA8D;IAC9D,IAAI,EAAE,MAAM,CAAC;IACb,2EAA2E;IAC3E,aAAa,EAAE,MAAM,CAAC;IACtB,8BAA8B;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,iEAAiE;IACjE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe,GAAG,cAAc,GAAG,IAAI,CA0C9E"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
/**
|
|
3
|
+
* **Cheap inline, thorough offline.**
|
|
4
|
+
*
|
|
5
|
+
* On every write: compare only against facts on the target page, flag only when
|
|
6
|
+
* two claims share a subject and attribute but differ in value, and bias toward
|
|
7
|
+
* numbers, dates, names and identifiers — where conflicts are real and detectable.
|
|
8
|
+
* Free prose rarely conflicts meaningfully, and a detector that thinks it does
|
|
9
|
+
* will block half of all writes.
|
|
10
|
+
*
|
|
11
|
+
* **When uncertain, write — do not block.** A false block costs a turn; a false
|
|
12
|
+
* pass costs a duplicate, and the maintenance cycle finds duplicates later.
|
|
13
|
+
*
|
|
14
|
+
* Deliberately no model call: correctness that requires one per write belongs in the
|
|
15
|
+
* background, not in the turn.
|
|
16
|
+
*/
|
|
17
|
+
/** `- **Premium:** €33/month`, `Premium: €33/month`, `| Premium | €33 |`. */
|
|
18
|
+
const KEY_VALUE = /^\s*(?:[-*+]\s*)?(?:\*\*|__)?([A-Za-z][\w\s'/-]{1,40}?)(?:\*\*|__)?\s*:\s*(.+?)\s*$/;
|
|
19
|
+
const TABLE_ROW = /^\s*\|\s*(?:\*\*)?([A-Za-z][\w\s'/-]{1,40}?)(?:\*\*)?\s*\|\s*(.+?)\s*\|/;
|
|
20
|
+
/**
|
|
21
|
+
* A value worth fighting over. A conflict between two prose sentences is usually
|
|
22
|
+
* two ways of saying the same thing; a conflict between two numbers is a fact
|
|
23
|
+
* that changed.
|
|
24
|
+
*/
|
|
25
|
+
const HARD_VALUE = /\d|\b(yes|no|true|false|none|active|inactive|expired|cancelled|monthly|weekly|annual|annually)\b/i;
|
|
26
|
+
/**
|
|
27
|
+
* Pulls `attribute: value` shapes out of text about to be written. Structural
|
|
28
|
+
* only — this is what makes the check affordable on every write.
|
|
29
|
+
*/
|
|
30
|
+
function extractCandidates(text, startLine = 1) {
|
|
31
|
+
const out = [];
|
|
32
|
+
const lines = text.split('\n');
|
|
33
|
+
for (let i = 0; i < lines.length; i++) {
|
|
34
|
+
const raw = lines[i];
|
|
35
|
+
if (raw.trim().length === 0 || /^\s*#{1,6}\s/.test(raw))
|
|
36
|
+
continue;
|
|
37
|
+
const match = TABLE_ROW.exec(raw) ?? KEY_VALUE.exec(raw);
|
|
38
|
+
if (!match)
|
|
39
|
+
continue;
|
|
40
|
+
const attribute = normalizeAttribute(match[1]);
|
|
41
|
+
const value = match[2].trim();
|
|
42
|
+
if (attribute.length === 0 || value.length === 0)
|
|
43
|
+
continue;
|
|
44
|
+
// A URL or a wikilink is not an attribute assignment, whatever the colon says.
|
|
45
|
+
if (/^\/\/|^https?:|^\[\[/.test(value))
|
|
46
|
+
continue;
|
|
47
|
+
if (!HARD_VALUE.test(value))
|
|
48
|
+
continue;
|
|
49
|
+
out.push({ attribute, value, line: startLine + i, text: raw.trim() });
|
|
50
|
+
}
|
|
51
|
+
return out;
|
|
52
|
+
}
|
|
53
|
+
function normalizeAttribute(raw) {
|
|
54
|
+
return raw.toLowerCase().replace(/[*_`]/g, '').replace(/\s+/g, ' ').trim();
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Two values differ *meaningfully* when their comparable cores differ. Reached
|
|
58
|
+
* only for values that already contain a number or a decisive word, so this is
|
|
59
|
+
* about "€33 vs €33/month" (same) against "€33 vs €47" (different).
|
|
60
|
+
*
|
|
61
|
+
* Exported for the thorough pass, which joins facts across the whole knowledge base and
|
|
62
|
+
* has to decide "differ" exactly the way the inline check does. Two answers to that question
|
|
63
|
+
* would mean the cycle reporting conflicts a write would have allowed, or missing ones it
|
|
64
|
+
* would have blocked.
|
|
65
|
+
*/
|
|
66
|
+
export function valuesConflict(existing, incoming) {
|
|
67
|
+
const left = comparableCore(existing);
|
|
68
|
+
const right = comparableCore(incoming);
|
|
69
|
+
if (left === right)
|
|
70
|
+
return false;
|
|
71
|
+
const leftNumbers = numbersIn(existing);
|
|
72
|
+
const rightNumbers = numbersIn(incoming);
|
|
73
|
+
// Both carry numbers: the numbers decide. This is the case to bias toward, and the only
|
|
74
|
+
// one where "differ" is unambiguous.
|
|
75
|
+
if (leftNumbers.length > 0 && rightNumbers.length > 0) {
|
|
76
|
+
return leftNumbers.join(',') !== rightNumbers.join(',');
|
|
77
|
+
}
|
|
78
|
+
// Only one side has a number, or neither does. When uncertain, write.
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
function comparableCore(value) {
|
|
82
|
+
return value.toLowerCase().replace(/[*_`]/g, '').replace(/[\s,]/g, '').replace(/\.$/, '');
|
|
83
|
+
}
|
|
84
|
+
function numbersIn(value) {
|
|
85
|
+
// Thousands separators removed first, so `1,450` reads as one number.
|
|
86
|
+
return [...value.replace(/(\d),(\d{3})\b/g, '$1$2').matchAll(/\d+(?:[.]\d+)?/g)].map((m) => m[0]);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Returns the first genuine conflict, or null. First rather than all: a caller has
|
|
90
|
+
* to take this to the user, and one clear question beats a list.
|
|
91
|
+
*
|
|
92
|
+
* Both sides go through the **same extractor**, which is the whole trick. The first
|
|
93
|
+
* implementation compared a structurally-extracted attribute from the incoming text
|
|
94
|
+
* against the `attribute` a model had assigned to an existing fact — and those are
|
|
95
|
+
* different vocabularies. Appending `- Nights: 5` over an existing `- Nights: 3`
|
|
96
|
+
* produced no conflict at all, because the model had labelled the existing line's
|
|
97
|
+
* attribute `total` while the extractor read the new one as `nights`. Two names for
|
|
98
|
+
* the same thing never join.
|
|
99
|
+
*
|
|
100
|
+
* Comparing the page's own lines against the incoming lines also means conflict
|
|
101
|
+
* detection **works with no chat model at all**, which is what makes it cheap.
|
|
102
|
+
*/
|
|
103
|
+
export function detectConflict(options) {
|
|
104
|
+
const incoming = extractCandidates(options.incoming, 1);
|
|
105
|
+
if (incoming.length === 0)
|
|
106
|
+
return null;
|
|
107
|
+
const existing = extractCandidates(options.body, options.bodyStartLine);
|
|
108
|
+
if (existing.length === 0)
|
|
109
|
+
return null;
|
|
110
|
+
// A low-confidence fact is never used for conflict detection, where a shaky
|
|
111
|
+
// claim would fight a solid one. Lines the deriver was unsure about are excluded
|
|
112
|
+
// by line number — the one thing the facts table is genuinely authoritative on.
|
|
113
|
+
const shaky = new Set(options.store.db
|
|
114
|
+
.prepare(`SELECT f.line_start FROM facts f JOIN pages p ON p.id = f.page_id
|
|
115
|
+
WHERE f.page_id = ? AND f.valid_to IS NULL AND f.confidence < 0.5
|
|
116
|
+
AND p.derived_hash = p.body_hash`)
|
|
117
|
+
.all(options.pageId).map((row) => row.line_start));
|
|
118
|
+
for (const candidate of incoming) {
|
|
119
|
+
for (const current of existing) {
|
|
120
|
+
if (shaky.has(current.line))
|
|
121
|
+
continue;
|
|
122
|
+
if (current.attribute !== candidate.attribute)
|
|
123
|
+
continue;
|
|
124
|
+
if (!valuesConflict(current.value, candidate.value))
|
|
125
|
+
continue;
|
|
126
|
+
const token = conflictToken(options.slug, current.line, candidate.value);
|
|
127
|
+
if (options.resolveToken === token)
|
|
128
|
+
continue; // The caller already asked.
|
|
129
|
+
return {
|
|
130
|
+
slug: options.slug,
|
|
131
|
+
line: current.line,
|
|
132
|
+
existing: current.text,
|
|
133
|
+
incoming: candidate.text,
|
|
134
|
+
subject: candidate.attribute,
|
|
135
|
+
token,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Ties an override to the exact conflict it resolves. A plain boolean flag would
|
|
143
|
+
* let a caller wave through a *different* conflict discovered on the next attempt
|
|
144
|
+
* — which is the same as not checking.
|
|
145
|
+
*/
|
|
146
|
+
function conflictToken(slug, line, incoming) {
|
|
147
|
+
return createHash('sha256').update(`${slug}:${line}:${incoming}`).digest('hex').slice(0, 12);
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=conflict.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conflict.js","sourceRoot":"","sources":["../../src/write/conflict.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAIzC;;;;;;;;;;;;;;GAcG;AAEH,6EAA6E;AAC7E,MAAM,SAAS,GAAG,qFAAqF,CAAC;AACxG,MAAM,SAAS,GAAG,yEAAyE,CAAC;AAE5F;;;;GAIG;AACH,MAAM,UAAU,GACd,mGAAmG,CAAC;AAUtG;;;GAGG;AACH,SAAS,iBAAiB,CAAC,IAAY,EAAE,SAAS,GAAG,CAAC;IACpD,MAAM,GAAG,GAAqB,EAAE,CAAC;IACjC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAE/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;QACtB,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,IAAI,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,SAAS;QAElE,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACzD,IAAI,CAAC,KAAK;YAAE,SAAS;QAErB,MAAM,SAAS,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC;QAChD,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,CAAC;QAC/B,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAC3D,+EAA+E;QAC/E,IAAI,sBAAsB,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,SAAS;QACjD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,SAAS;QAEtC,GAAG,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,GAAG,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACxE,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,kBAAkB,CAAC,GAAW;IACrC,OAAO,GAAG,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AAC7E,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgB,EAAE,QAAgB;IAC/D,MAAM,IAAI,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IACtC,MAAM,KAAK,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,IAAI,KAAK,KAAK;QAAE,OAAO,KAAK,CAAC;IAEjC,MAAM,WAAW,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;IACxC,MAAM,YAAY,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;IACzC,wFAAwF;IACxF,qCAAqC;IACrC,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtD,OAAO,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC1D,CAAC;IACD,sEAAsE;IACtE,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,cAAc,CAAC,KAAa;IACnC,OAAO,KAAK,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAC5F,CAAC;AAED,SAAS,SAAS,CAAC,KAAa;IAC9B,sEAAsE;IACtE,OAAO,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC;AACrG,CAAC;AAgBD;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,cAAc,CAAC,OAAwB;IACrD,MAAM,QAAQ,GAAG,iBAAiB,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IACxD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEvC,MAAM,QAAQ,GAAG,iBAAiB,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;IACxE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEvC,4EAA4E;IAC5E,iFAAiF;IACjF,gFAAgF;IAChF,MAAM,KAAK,GAAG,IAAI,GAAG,CAEjB,OAAO,CAAC,KAAK,CAAC,EAAE;SACb,OAAO,CACN;;+CAEqC,CACtC;SACA,GAAG,CAAC,OAAO,CAAC,MAAM,CACtB,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAC/B,CAAC;IAEF,KAAK,MAAM,SAAS,IAAI,QAAQ,EAAE,CAAC;QACjC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC;gBAAE,SAAS;YACtC,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,SAAS;gBAAE,SAAS;YACxD,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,KAAK,EAAE,SAAS,CAAC,KAAK,CAAC;gBAAE,SAAS;YAE9D,MAAM,KAAK,GAAG,aAAa,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC;YACzE,IAAI,OAAO,CAAC,YAAY,KAAK,KAAK;gBAAE,SAAS,CAAC,4BAA4B;YAE1E,OAAO;gBACL,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,QAAQ,EAAE,OAAO,CAAC,IAAI;gBACtB,QAAQ,EAAE,SAAS,CAAC,IAAI;gBACxB,OAAO,EAAE,SAAS,CAAC,SAAS;gBAC5B,KAAK;aACN,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,SAAS,aAAa,CAAC,IAAY,EAAE,IAAY,EAAE,QAAgB;IACjE,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,IAAI,IAAI,IAAI,IAAI,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC/F,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The four ways `write` can change a body, and the rule they obey: **never touch the
|
|
3
|
+
* frontmatter, unless the caller sent one.** Every key is preserved byte for byte, so an
|
|
4
|
+
* edit here operates on the body and splices it back under the original head.
|
|
5
|
+
*
|
|
6
|
+
* The exception is `content` — a whole-page write — and it is not a loophole. `read` returns
|
|
7
|
+
* the file including its frontmatter, so a caller that read a page, revised it and sent the
|
|
8
|
+
* result back arrives holding a block; and `role`, `management` and `temporal` are declarable
|
|
9
|
+
* nowhere else in the write API, so rewriting the declaration is a thing a caller legitimately
|
|
10
|
+
* means. The old behaviour spliced that block under the existing head and produced a page with
|
|
11
|
+
* two, the second invisible to everything that reads frontmatter. Adopting it is both what the
|
|
12
|
+
* caller asked for and the only reading that cannot silently accumulate.
|
|
13
|
+
*/
|
|
14
|
+
export type BodyEdit = {
|
|
15
|
+
kind: 'content';
|
|
16
|
+
content: string;
|
|
17
|
+
} | {
|
|
18
|
+
kind: 'append';
|
|
19
|
+
text: string;
|
|
20
|
+
section?: string;
|
|
21
|
+
} | {
|
|
22
|
+
kind: 'patch';
|
|
23
|
+
patch: string;
|
|
24
|
+
} | {
|
|
25
|
+
kind: 'replace';
|
|
26
|
+
find: string;
|
|
27
|
+
with: string;
|
|
28
|
+
};
|
|
29
|
+
export interface EditResult {
|
|
30
|
+
content: string;
|
|
31
|
+
/** Lines that changed, for the journal summary and the write report. */
|
|
32
|
+
firstChangedLine: number | null;
|
|
33
|
+
/**
|
|
34
|
+
* Set when the write carried its own frontmatter block and it replaced the page's.
|
|
35
|
+
* `dropped` names the keys the old block declared and the new one does not, because a
|
|
36
|
+
* caller rewriting a declaration from memory is the likeliest way to lose a key nobody
|
|
37
|
+
* meant to remove — and a rewrite nobody can see is the failure this whole path exists
|
|
38
|
+
* to stop repeating.
|
|
39
|
+
*/
|
|
40
|
+
frontmatter?: {
|
|
41
|
+
adopted: true;
|
|
42
|
+
dropped: string[];
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
export declare function applyEdit(original: string, edit: BodyEdit): EditResult;
|
|
46
|
+
/**
|
|
47
|
+
* A strict unified-diff applier: every context and removal line must match the
|
|
48
|
+
* file exactly, or the whole patch is refused.
|
|
49
|
+
*
|
|
50
|
+
* Strictness is the feature. A fuzzy applier that "finds the nearest match" will
|
|
51
|
+
* eventually apply a hunk to the wrong place, and in a knowledge base that means a
|
|
52
|
+
* value silently attached to the wrong subject — the exact failure Akno exists
|
|
53
|
+
* to prevent. Refusing costs the caller a re-read; guessing costs correctness.
|
|
54
|
+
*
|
|
55
|
+
* The `@@` line numbers are treated as a hint, not as truth: agents get them wrong
|
|
56
|
+
* constantly, and the context lines identify the location unambiguously anyway.
|
|
57
|
+
*/
|
|
58
|
+
export declare function applyUnifiedDiff(body: string, patch: string): string;
|
|
59
|
+
//# sourceMappingURL=edit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edit.d.ts","sourceRoot":"","sources":["../../src/write/edit.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;GAYG;AAEH,MAAM,MAAM,QAAQ,GAChB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAClD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpD,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC;;;;;;OAMG;IACH,WAAW,CAAC,EAAE;QAAE,OAAO,EAAE,IAAI,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CACpD;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,UAAU,CA8BtE;AA2ID;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAkBpE"}
|