@nathanvale/chatline 0.0.1
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/CHANGELOG.md +1 -0
- package/LICENSE +21 -0
- package/README.md +1535 -0
- package/dist/bin/index.js +5121 -0
- package/dist/cli/commands/clean.d.ts +17 -0
- package/dist/cli/commands/clean.d.ts.map +1 -0
- package/dist/cli/commands/clean.js +142 -0
- package/dist/cli/commands/clean.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +17 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +202 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/enrich-ai.d.ts +17 -0
- package/dist/cli/commands/enrich-ai.d.ts.map +1 -0
- package/dist/cli/commands/enrich-ai.js +371 -0
- package/dist/cli/commands/enrich-ai.js.map +1 -0
- package/dist/cli/commands/index.d.ts +16 -0
- package/dist/cli/commands/index.d.ts.map +1 -0
- package/dist/cli/commands/index.js +16 -0
- package/dist/cli/commands/index.js.map +1 -0
- package/dist/cli/commands/ingest-csv.d.ts +17 -0
- package/dist/cli/commands/ingest-csv.d.ts.map +1 -0
- package/dist/cli/commands/ingest-csv.js +138 -0
- package/dist/cli/commands/ingest-csv.js.map +1 -0
- package/dist/cli/commands/ingest-db.d.ts +17 -0
- package/dist/cli/commands/ingest-db.d.ts.map +1 -0
- package/dist/cli/commands/ingest-db.js +159 -0
- package/dist/cli/commands/ingest-db.js.map +1 -0
- package/dist/cli/commands/init.d.ts +17 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +110 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/normalize-link.d.ts +16 -0
- package/dist/cli/commands/normalize-link.d.ts.map +1 -0
- package/dist/cli/commands/normalize-link.js +144 -0
- package/dist/cli/commands/normalize-link.js.map +1 -0
- package/dist/cli/commands/render-markdown.d.ts +17 -0
- package/dist/cli/commands/render-markdown.d.ts.map +1 -0
- package/dist/cli/commands/render-markdown.js +218 -0
- package/dist/cli/commands/render-markdown.js.map +1 -0
- package/dist/cli/commands/stats.d.ts +17 -0
- package/dist/cli/commands/stats.d.ts.map +1 -0
- package/dist/cli/commands/stats.js +175 -0
- package/dist/cli/commands/stats.js.map +1 -0
- package/dist/cli/commands/validate.d.ts +17 -0
- package/dist/cli/commands/validate.d.ts.map +1 -0
- package/dist/cli/commands/validate.js +152 -0
- package/dist/cli/commands/validate.js.map +1 -0
- package/dist/cli/index.d.ts +13 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +121 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/types.d.ts +93 -0
- package/dist/cli/types.d.ts.map +1 -0
- package/dist/cli/types.js +7 -0
- package/dist/cli/types.js.map +1 -0
- package/dist/cli/utils.d.ts +29 -0
- package/dist/cli/utils.d.ts.map +1 -0
- package/dist/cli/utils.js +53 -0
- package/dist/cli/utils.js.map +1 -0
- package/dist/cli.d.ts +9 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +1805 -0
- package/dist/config/generator.d.ts +90 -0
- package/dist/config/generator.d.ts.map +1 -0
- package/dist/config/generator.js +320 -0
- package/dist/config/generator.js.map +1 -0
- package/dist/config/loader.d.ts +107 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +251 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/schema.d.ts +107 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +169 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/enrich/audio-transcription.d.ts +77 -0
- package/dist/enrich/audio-transcription.d.ts.map +1 -0
- package/dist/enrich/audio-transcription.js +370 -0
- package/dist/enrich/audio-transcription.js.map +1 -0
- package/dist/enrich/checkpoint.d.ts +137 -0
- package/dist/enrich/checkpoint.d.ts.map +1 -0
- package/dist/enrich/checkpoint.js +205 -0
- package/dist/enrich/checkpoint.js.map +1 -0
- package/dist/enrich/idempotency.d.ts +90 -0
- package/dist/enrich/idempotency.d.ts.map +1 -0
- package/dist/enrich/idempotency.js +188 -0
- package/dist/enrich/idempotency.js.map +1 -0
- package/dist/enrich/image-analysis.d.ts +62 -0
- package/dist/enrich/image-analysis.d.ts.map +1 -0
- package/dist/enrich/image-analysis.js +264 -0
- package/dist/enrich/image-analysis.js.map +1 -0
- package/dist/enrich/index.d.ts +60 -0
- package/dist/enrich/index.d.ts.map +1 -0
- package/dist/enrich/index.js +74 -0
- package/dist/enrich/index.js.map +1 -0
- package/dist/enrich/link-enrichment.d.ts +37 -0
- package/dist/enrich/link-enrichment.d.ts.map +1 -0
- package/dist/enrich/link-enrichment.js +202 -0
- package/dist/enrich/link-enrichment.js.map +1 -0
- package/dist/enrich/pdf-video-handling.d.ts +49 -0
- package/dist/enrich/pdf-video-handling.d.ts.map +1 -0
- package/dist/enrich/pdf-video-handling.js +325 -0
- package/dist/enrich/pdf-video-handling.js.map +1 -0
- package/dist/enrich/progress-tracker.d.ts +120 -0
- package/dist/enrich/progress-tracker.d.ts.map +1 -0
- package/dist/enrich/progress-tracker.js +220 -0
- package/dist/enrich/progress-tracker.js.map +1 -0
- package/dist/enrich/providers/firecrawl.d.ts +18 -0
- package/dist/enrich/providers/firecrawl.d.ts.map +1 -0
- package/dist/enrich/providers/firecrawl.js +48 -0
- package/dist/enrich/providers/firecrawl.js.map +1 -0
- package/dist/enrich/providers/generic.d.ts +16 -0
- package/dist/enrich/providers/generic.d.ts.map +1 -0
- package/dist/enrich/providers/generic.js +36 -0
- package/dist/enrich/providers/generic.js.map +1 -0
- package/dist/enrich/providers/index.d.ts +14 -0
- package/dist/enrich/providers/index.d.ts.map +1 -0
- package/dist/enrich/providers/index.js +13 -0
- package/dist/enrich/providers/index.js.map +1 -0
- package/dist/enrich/providers/instagram.d.ts +16 -0
- package/dist/enrich/providers/instagram.d.ts.map +1 -0
- package/dist/enrich/providers/instagram.js +43 -0
- package/dist/enrich/providers/instagram.js.map +1 -0
- package/dist/enrich/providers/spotify.d.ts +16 -0
- package/dist/enrich/providers/spotify.d.ts.map +1 -0
- package/dist/enrich/providers/spotify.js +45 -0
- package/dist/enrich/providers/spotify.js.map +1 -0
- package/dist/enrich/providers/twitter.d.ts +16 -0
- package/dist/enrich/providers/twitter.d.ts.map +1 -0
- package/dist/enrich/providers/twitter.js +43 -0
- package/dist/enrich/providers/twitter.js.map +1 -0
- package/dist/enrich/providers/types.d.ts +47 -0
- package/dist/enrich/providers/types.d.ts.map +1 -0
- package/dist/enrich/providers/types.js +15 -0
- package/dist/enrich/providers/types.js.map +1 -0
- package/dist/enrich/providers/youtube.d.ts +16 -0
- package/dist/enrich/providers/youtube.d.ts.map +1 -0
- package/dist/enrich/providers/youtube.js +43 -0
- package/dist/enrich/providers/youtube.js.map +1 -0
- package/dist/enrich/rate-limiting.d.ts +118 -0
- package/dist/enrich/rate-limiting.d.ts.map +1 -0
- package/dist/enrich/rate-limiting.js +258 -0
- package/dist/enrich/rate-limiting.js.map +1 -0
- package/dist/index.d.ts +688 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1729 -0
- package/dist/index.js.map +1 -0
- package/dist/ingest/dedup-merge.d.ts +82 -0
- package/dist/ingest/dedup-merge.d.ts.map +1 -0
- package/dist/ingest/dedup-merge.js +262 -0
- package/dist/ingest/dedup-merge.js.map +1 -0
- package/dist/ingest/ingest-csv.d.ts +62 -0
- package/dist/ingest/ingest-csv.d.ts.map +1 -0
- package/dist/ingest/ingest-csv.js +300 -0
- package/dist/ingest/ingest-csv.js.map +1 -0
- package/dist/ingest/ingest-db.d.ts +64 -0
- package/dist/ingest/ingest-db.d.ts.map +1 -0
- package/dist/ingest/ingest-db.js +172 -0
- package/dist/ingest/ingest-db.js.map +1 -0
- package/dist/ingest/link-replies-and-tapbacks.d.ts +53 -0
- package/dist/ingest/link-replies-and-tapbacks.d.ts.map +1 -0
- package/dist/ingest/link-replies-and-tapbacks.js +381 -0
- package/dist/ingest/link-replies-and-tapbacks.js.map +1 -0
- package/dist/normalize/date-converters.d.ts +45 -0
- package/dist/normalize/date-converters.d.ts.map +1 -0
- package/dist/normalize/date-converters.js +166 -0
- package/dist/normalize/date-converters.js.map +1 -0
- package/dist/normalize/path-validator.d.ts +65 -0
- package/dist/normalize/path-validator.d.ts.map +1 -0
- package/dist/normalize/path-validator.js +221 -0
- package/dist/normalize/path-validator.js.map +1 -0
- package/dist/normalize/validate-normalized.d.ts +45 -0
- package/dist/normalize/validate-normalized.d.ts.map +1 -0
- package/dist/normalize/validate-normalized.js +144 -0
- package/dist/normalize/validate-normalized.js.map +1 -0
- package/dist/render/embeds-blockquotes.d.ts +84 -0
- package/dist/render/embeds-blockquotes.d.ts.map +1 -0
- package/dist/render/embeds-blockquotes.js +204 -0
- package/dist/render/embeds-blockquotes.js.map +1 -0
- package/dist/render/grouping.d.ts +78 -0
- package/dist/render/grouping.d.ts.map +1 -0
- package/dist/render/grouping.js +134 -0
- package/dist/render/grouping.js.map +1 -0
- package/dist/render/index.d.ts +47 -0
- package/dist/render/index.d.ts.map +1 -0
- package/dist/render/index.js +245 -0
- package/dist/render/index.js.map +1 -0
- package/dist/render/reply-rendering.d.ts +88 -0
- package/dist/render/reply-rendering.d.ts.map +1 -0
- package/dist/render/reply-rendering.js +196 -0
- package/dist/render/reply-rendering.js.map +1 -0
- package/dist/schema/message.d.ts +125 -0
- package/dist/schema/message.d.ts.map +1 -0
- package/dist/schema/message.js +331 -0
- package/dist/schema/message.js.map +1 -0
- package/dist/utils/delta-detection.d.ts +107 -0
- package/dist/utils/delta-detection.d.ts.map +1 -0
- package/dist/utils/delta-detection.js +199 -0
- package/dist/utils/delta-detection.js.map +1 -0
- package/dist/utils/enrichment-merge.d.ts +135 -0
- package/dist/utils/enrichment-merge.d.ts.map +1 -0
- package/dist/utils/enrichment-merge.js +280 -0
- package/dist/utils/enrichment-merge.js.map +1 -0
- package/dist/utils/human.d.ts +15 -0
- package/dist/utils/human.d.ts.map +1 -0
- package/dist/utils/human.js +27 -0
- package/dist/utils/human.js.map +1 -0
- package/dist/utils/incremental-state.d.ts +133 -0
- package/dist/utils/incremental-state.d.ts.map +1 -0
- package/dist/utils/incremental-state.js +237 -0
- package/dist/utils/incremental-state.js.map +1 -0
- package/dist/utils/logger.d.ts +40 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +176 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +165 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../src/schema/message.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAMvB,MAAM,MAAM,WAAW,GAAG,MAAM,CAAA;AAChC,MAAM,MAAM,MAAM,GAAG,MAAM,CAAA;AAM3B,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,KAAK,GAAG,SAAS,CAAA;AAEvE,MAAM,MAAM,eAAe,GAAG;IAC7B,IAAI,EACD,SAAS,GACT,MAAM,GACN,eAAe,GACf,aAAa,GACb,gBAAgB,GAChB,cAAc,GACd,gBAAgB,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IAEjB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IAEzB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB,UAAU,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAEtE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,aAAa,CAAC,EAAE;QACf,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,QAAQ,CAAC,EAAE,OAAO,CAAA;QAClB,IAAI,CAAC,EAAE,MAAM,CAAA;KACb,CAAA;IACD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;IAE1B,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAEhB,QAAQ,EACL,QAAQ,GACR,WAAW,GACX,OAAO,GACP,SAAS,GACT,SAAS,GACT,SAAS,GACT,WAAW,GACX,SAAS,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CACf,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC7B,MAAM,EAAE,KAAK,GAAG,IAAI,GAAG,QAAQ,CAAA;IAC/B,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,SAAS,GAAG;IAEvB,EAAE,EAAE,MAAM,CAAA;IACV,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,UAAU,CAAC,EAAE,KAAK,CAAC,eAAe,CAAC,CAAA;IACnC,UAAU,CAAC,EAAE,eAAe,CAAA;CAC5B,CAAA;AAMD,MAAM,MAAM,SAAS,GAAG;IACvB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,iBAAiB,CAAC,EAAE,WAAW,CAAA;CAC/B,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACzB,IAAI,EACD,OAAO,GACP,OAAO,GACP,UAAU,GACV,SAAS,GACT,YAAY,GACZ,YAAY,GACZ,OAAO,CAAA;IACV,MAAM,EAAE,OAAO,GAAG,SAAS,CAAA;IAC3B,iBAAiB,CAAC,EAAE,WAAW,CAAA;IAC/B,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAMD,MAAM,MAAM,WAAW,GAAG;IACzB,IAAI,EAAE,WAAW,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACnC,QAAQ,EAAE,OAAO,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,cAAc,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;IAC/B,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrC,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACpC,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACpC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC3B,CAAA;AAED,MAAM,MAAM,OAAO,GAAG;IACrB,WAAW,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,cAAc,CAAA;IAC1D,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,OAAO,CAAC,EAAE,WAAW,GAAG,IAAI,CAAA;IAC5B,UAAU,CAAC,EAAE,SAAS,GAAG,IAAI,CAAA;IAC7B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAE7B,KAAK,CAAC,EAAE,SAAS,GAAG,IAAI,CAAA;IACxB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;CAClB,GAAG,WAAW,CAAA;AAMf,MAAM,MAAM,cAAc,GAAG;IAC5B,aAAa,EAAE,MAAM,CAAA;IACrB,MAAM,EAAE,KAAK,GAAG,IAAI,GAAG,QAAQ,CAAA;IAC/B,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC9B,CAAA;AAOD,eAAO,MAAM,qBAAqB,EAAE,CAAC,CAAC,OAAO,CAAC,eAAe,CAoE1D,CAAA;AAGH,eAAO,MAAM,qBAAqB,EAAE,CAAC,CAAC,OAAO,CAAC,eAAe,CAsB1D,CAAA;AAGH,eAAO,MAAM,eAAe,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAuB9C,CAAA;AAGH,eAAO,MAAM,eAAe,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAyB9C,CAAA;AAGH,eAAO,MAAM,iBAAiB,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,CAgBnD,CAAA;AAGF,eAAO,MAAM,iBAAiB,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,CA2BnD,CAAA;AAGF,eAAO,MAAM,aAAa,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAuH1C,CAAA;AAGH,eAAO,MAAM,oBAAoB,EAAE,CAAC,CAAC,OAAO,CAAC,cAAc,CAiBxD,CAAA"}
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
// src/schema/message.ts
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// Zod Schemas
|
|
5
|
+
// ============================================================================
|
|
6
|
+
// Media Enrichment Schema
|
|
7
|
+
export const MediaEnrichmentSchema = z
|
|
8
|
+
.object({
|
|
9
|
+
kind: z.enum([
|
|
10
|
+
'image',
|
|
11
|
+
'audio',
|
|
12
|
+
'link',
|
|
13
|
+
'video',
|
|
14
|
+
'pdf',
|
|
15
|
+
'unknown',
|
|
16
|
+
'transcription',
|
|
17
|
+
'pdf_summary',
|
|
18
|
+
'video_metadata',
|
|
19
|
+
'link_context',
|
|
20
|
+
'image_analysis',
|
|
21
|
+
]),
|
|
22
|
+
model: z.string().optional(),
|
|
23
|
+
createdAt: z.string().datetime(),
|
|
24
|
+
visionSummary: z.string().optional(),
|
|
25
|
+
shortDescription: z.string().optional(),
|
|
26
|
+
transcription: z.string().optional(),
|
|
27
|
+
transcript: z.string().optional(),
|
|
28
|
+
speakers: z.array(z.string()).optional(),
|
|
29
|
+
timestamps: z
|
|
30
|
+
.array(z.object({
|
|
31
|
+
time: z.string(),
|
|
32
|
+
speaker: z.string(),
|
|
33
|
+
content: z.string(),
|
|
34
|
+
}))
|
|
35
|
+
.optional(),
|
|
36
|
+
pdfSummary: z.string().optional(),
|
|
37
|
+
videoMetadata: z
|
|
38
|
+
.object({
|
|
39
|
+
filename: z.string().optional(),
|
|
40
|
+
size: z.number().optional(),
|
|
41
|
+
duration: z.number().optional(),
|
|
42
|
+
analyzed: z.boolean().optional(),
|
|
43
|
+
note: z.string().optional(),
|
|
44
|
+
})
|
|
45
|
+
.optional(),
|
|
46
|
+
error: z.string().optional(),
|
|
47
|
+
usedFallback: z.boolean().optional(),
|
|
48
|
+
failedProviders: z.array(z.string()).optional(),
|
|
49
|
+
url: z.string().url().optional(),
|
|
50
|
+
title: z.string().optional(),
|
|
51
|
+
summary: z.string().optional(),
|
|
52
|
+
provider: z.enum([
|
|
53
|
+
'gemini',
|
|
54
|
+
'firecrawl',
|
|
55
|
+
'local',
|
|
56
|
+
'youtube',
|
|
57
|
+
'spotify',
|
|
58
|
+
'twitter',
|
|
59
|
+
'instagram',
|
|
60
|
+
'generic',
|
|
61
|
+
]),
|
|
62
|
+
version: z.string(),
|
|
63
|
+
})
|
|
64
|
+
.superRefine((enrichment, ctx) => {
|
|
65
|
+
// Ensure enrichment.createdAt has Z suffix (UTC)
|
|
66
|
+
// Note: Zod's datetime() already validates format, this adds additional check
|
|
67
|
+
if (enrichment.createdAt && !enrichment.createdAt.match(/Z$/)) {
|
|
68
|
+
ctx.addIssue({
|
|
69
|
+
code: z.ZodIssueCode.custom,
|
|
70
|
+
message: 'enrichment.createdAt must be ISO 8601 with Z suffix (UTC)',
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
// Media Provenance Schema
|
|
75
|
+
export const MediaProvenanceSchema = z
|
|
76
|
+
.object({
|
|
77
|
+
source: z.enum(['csv', 'db', 'merged']),
|
|
78
|
+
lastSeen: z.string().datetime(),
|
|
79
|
+
resolvedAt: z.string().datetime(),
|
|
80
|
+
})
|
|
81
|
+
.superRefine((prov, ctx) => {
|
|
82
|
+
// Ensure all provenance timestamps have Z suffix (UTC)
|
|
83
|
+
if (prov.lastSeen && !prov.lastSeen.match(/Z$/)) {
|
|
84
|
+
ctx.addIssue({
|
|
85
|
+
code: z.ZodIssueCode.custom,
|
|
86
|
+
message: 'lastSeen must be ISO 8601 with Z suffix (UTC)',
|
|
87
|
+
path: ['lastSeen'],
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
if (prov.resolvedAt && !prov.resolvedAt.match(/Z$/)) {
|
|
91
|
+
ctx.addIssue({
|
|
92
|
+
code: z.ZodIssueCode.custom,
|
|
93
|
+
message: 'resolvedAt must be ISO 8601 with Z suffix (UTC)',
|
|
94
|
+
path: ['resolvedAt'],
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
// Media Meta Schema
|
|
99
|
+
export const MediaMetaSchema = z
|
|
100
|
+
.object({
|
|
101
|
+
id: z.string(),
|
|
102
|
+
filename: z.string(),
|
|
103
|
+
path: z.string(),
|
|
104
|
+
size: z.number().optional(),
|
|
105
|
+
mimeType: z.string().optional(),
|
|
106
|
+
uti: z.string().nullable().optional(),
|
|
107
|
+
isSticker: z.boolean().optional(),
|
|
108
|
+
hidden: z.boolean().optional(),
|
|
109
|
+
mediaKind: z.enum(['image', 'audio', 'video', 'pdf', 'unknown']).optional(),
|
|
110
|
+
enrichment: z.array(MediaEnrichmentSchema).optional(),
|
|
111
|
+
provenance: MediaProvenanceSchema.optional(),
|
|
112
|
+
})
|
|
113
|
+
.superRefine((media, ctx) => {
|
|
114
|
+
// SCHEMA-T01-AC06: Absolute path validation when file exists
|
|
115
|
+
if (media.path && !media.path.startsWith('/')) {
|
|
116
|
+
ctx.addIssue({
|
|
117
|
+
code: z.ZodIssueCode.custom,
|
|
118
|
+
message: 'media.path must be an absolute path (starting with /)',
|
|
119
|
+
path: ['path'],
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
// Reply Info Schema
|
|
124
|
+
export const ReplyInfoSchema = z
|
|
125
|
+
.object({
|
|
126
|
+
sender: z.string().optional(),
|
|
127
|
+
date: z.string().datetime().optional(),
|
|
128
|
+
text: z.string().optional(),
|
|
129
|
+
targetMessageGuid: z.string().optional(),
|
|
130
|
+
})
|
|
131
|
+
.superRefine((reply, ctx) => {
|
|
132
|
+
// SCHEMA-T01-AC05: ISO 8601 date validation with Z suffix enforced
|
|
133
|
+
if (reply.date) {
|
|
134
|
+
if (!reply.date.match(/Z$/)) {
|
|
135
|
+
ctx.addIssue({
|
|
136
|
+
code: z.ZodIssueCode.custom,
|
|
137
|
+
message: 'replyingTo.date must be ISO 8601 with Z suffix (UTC)',
|
|
138
|
+
path: ['date'],
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
if (Number.isNaN(Date.parse(reply.date))) {
|
|
142
|
+
ctx.addIssue({
|
|
143
|
+
code: z.ZodIssueCode.custom,
|
|
144
|
+
message: 'replyingTo.date must be a valid ISO 8601 date',
|
|
145
|
+
path: ['date'],
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
// Tapback Info Schema
|
|
151
|
+
export const TapbackInfoSchema = z.object({
|
|
152
|
+
type: z.enum([
|
|
153
|
+
'loved',
|
|
154
|
+
'liked',
|
|
155
|
+
'disliked',
|
|
156
|
+
'laughed',
|
|
157
|
+
'emphasized',
|
|
158
|
+
'questioned',
|
|
159
|
+
'emoji',
|
|
160
|
+
]),
|
|
161
|
+
action: z.enum(['added', 'removed']),
|
|
162
|
+
targetMessageGuid: z.string().optional(),
|
|
163
|
+
targetMessagePart: z.number().int().optional(),
|
|
164
|
+
targetText: z.string().optional(),
|
|
165
|
+
isMedia: z.boolean().optional(),
|
|
166
|
+
emoji: z.string().optional(),
|
|
167
|
+
});
|
|
168
|
+
// Message Core Schema (without refinements to allow extending)
|
|
169
|
+
export const MessageCoreSchema = z.object({
|
|
170
|
+
guid: z.string(),
|
|
171
|
+
rowid: z.number().optional(),
|
|
172
|
+
chatId: z.string().nullable().optional(),
|
|
173
|
+
service: z.string().nullable().optional(),
|
|
174
|
+
subject: z.string().nullable().optional(),
|
|
175
|
+
handleId: z.number().nullable().optional(),
|
|
176
|
+
handle: z.string().nullable().optional(),
|
|
177
|
+
destinationCallerId: z.string().nullable().optional(),
|
|
178
|
+
isFromMe: z.boolean(),
|
|
179
|
+
otherHandle: z.number().nullable().optional(),
|
|
180
|
+
date: z.string().datetime(),
|
|
181
|
+
dateRead: z.string().datetime().nullable().optional(),
|
|
182
|
+
dateDelivered: z.string().datetime().nullable().optional(),
|
|
183
|
+
dateEdited: z.string().datetime().nullable().optional(),
|
|
184
|
+
isRead: z.boolean().optional(),
|
|
185
|
+
itemType: z.number().optional(),
|
|
186
|
+
groupActionType: z.number().optional(),
|
|
187
|
+
groupTitle: z.string().nullable().optional(),
|
|
188
|
+
shareStatus: z.boolean().optional(),
|
|
189
|
+
shareDirection: z.boolean().nullable().optional(),
|
|
190
|
+
expressiveSendStyleId: z.string().nullable().optional(),
|
|
191
|
+
balloonBundleId: z.string().nullable().optional(),
|
|
192
|
+
threadOriginatorGuid: z.string().nullable().optional(),
|
|
193
|
+
threadOriginatorPart: z.number().nullable().optional(),
|
|
194
|
+
numReplies: z.number().optional(),
|
|
195
|
+
deletedFrom: z.number().nullable().optional(),
|
|
196
|
+
});
|
|
197
|
+
// Message Schema with discriminated union and cross-field invariants
|
|
198
|
+
export const MessageSchema = z
|
|
199
|
+
.object({
|
|
200
|
+
// Core fields from MessageCoreSchema
|
|
201
|
+
guid: z.string(),
|
|
202
|
+
rowid: z.number().optional(),
|
|
203
|
+
chatId: z.string().nullable().optional(),
|
|
204
|
+
service: z.string().nullable().optional(),
|
|
205
|
+
subject: z.string().nullable().optional(),
|
|
206
|
+
handleId: z.number().nullable().optional(),
|
|
207
|
+
handle: z.string().nullable().optional(),
|
|
208
|
+
destinationCallerId: z.string().nullable().optional(),
|
|
209
|
+
isFromMe: z.boolean(),
|
|
210
|
+
otherHandle: z.number().nullable().optional(),
|
|
211
|
+
date: z.string().datetime(),
|
|
212
|
+
dateRead: z.string().datetime().nullable().optional(),
|
|
213
|
+
dateDelivered: z.string().datetime().nullable().optional(),
|
|
214
|
+
dateEdited: z.string().datetime().nullable().optional(),
|
|
215
|
+
isRead: z.boolean().optional(),
|
|
216
|
+
itemType: z.number().optional(),
|
|
217
|
+
groupActionType: z.number().optional(),
|
|
218
|
+
groupTitle: z.string().nullable().optional(),
|
|
219
|
+
shareStatus: z.boolean().optional(),
|
|
220
|
+
shareDirection: z.boolean().nullable().optional(),
|
|
221
|
+
expressiveSendStyleId: z.string().nullable().optional(),
|
|
222
|
+
balloonBundleId: z.string().nullable().optional(),
|
|
223
|
+
threadOriginatorGuid: z.string().nullable().optional(),
|
|
224
|
+
threadOriginatorPart: z.number().nullable().optional(),
|
|
225
|
+
numReplies: z.number().optional(),
|
|
226
|
+
deletedFrom: z.number().nullable().optional(),
|
|
227
|
+
// Message-specific fields
|
|
228
|
+
messageKind: z.enum(['text', 'media', 'tapback', 'notification']),
|
|
229
|
+
text: z.string().nullable().optional(),
|
|
230
|
+
tapback: TapbackInfoSchema.nullable().optional(),
|
|
231
|
+
replyingTo: ReplyInfoSchema.nullable().optional(),
|
|
232
|
+
replyingToRaw: z.string().nullable().optional(),
|
|
233
|
+
media: MediaMetaSchema.nullable().optional(),
|
|
234
|
+
groupGuid: z.string().nullable().optional(),
|
|
235
|
+
exportTimestamp: z.string().datetime().optional(),
|
|
236
|
+
exportVersion: z.string().optional(),
|
|
237
|
+
isUnsent: z.boolean().optional(),
|
|
238
|
+
isEdited: z.boolean().optional(),
|
|
239
|
+
})
|
|
240
|
+
.superRefine((msg, ctx) => {
|
|
241
|
+
// SCHEMA-T01-AC02: Cross-field invariants using superRefine
|
|
242
|
+
// SCHEMA-T01-AC05: ISO 8601 date validation with Z suffix enforced for all date fields
|
|
243
|
+
const dateFields = [
|
|
244
|
+
'date',
|
|
245
|
+
'dateRead',
|
|
246
|
+
'dateDelivered',
|
|
247
|
+
'dateEdited',
|
|
248
|
+
'exportTimestamp',
|
|
249
|
+
];
|
|
250
|
+
for (const field of dateFields) {
|
|
251
|
+
const value = msg[field];
|
|
252
|
+
if (value && typeof value === 'string') {
|
|
253
|
+
if (!value.match(/Z$/)) {
|
|
254
|
+
ctx.addIssue({
|
|
255
|
+
code: z.ZodIssueCode.custom,
|
|
256
|
+
message: `${field} must be ISO 8601 with Z suffix (UTC)`,
|
|
257
|
+
path: [field],
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
// SCHEMA-T01-AC04: Tapback payload validation (exists when messageKind='tapback')
|
|
263
|
+
if (msg.messageKind === 'tapback' && !msg.tapback) {
|
|
264
|
+
ctx.addIssue({
|
|
265
|
+
code: z.ZodIssueCode.custom,
|
|
266
|
+
message: 'tapback kind requires tapback payload',
|
|
267
|
+
path: ['tapback'],
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
// SCHEMA-T01-AC03: Media payload validation (exists and complete when messageKind='media')
|
|
271
|
+
if (msg.messageKind === 'media' && !msg.media) {
|
|
272
|
+
ctx.addIssue({
|
|
273
|
+
code: z.ZodIssueCode.custom,
|
|
274
|
+
message: 'media kind requires media payload',
|
|
275
|
+
path: ['media'],
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
// Non-media messages must NOT carry media payload
|
|
279
|
+
if (msg.messageKind !== 'media' && msg.media) {
|
|
280
|
+
ctx.addIssue({
|
|
281
|
+
code: z.ZodIssueCode.custom,
|
|
282
|
+
message: 'media payload present on non-media message',
|
|
283
|
+
path: ['media'],
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
// Additional validation: if media payload exists and is complete
|
|
287
|
+
if (msg.messageKind === 'media' && msg.media) {
|
|
288
|
+
// Ensure media has required fields
|
|
289
|
+
if (!msg.media.id) {
|
|
290
|
+
ctx.addIssue({
|
|
291
|
+
code: z.ZodIssueCode.custom,
|
|
292
|
+
message: 'media.id is required when messageKind is media',
|
|
293
|
+
path: ['media', 'id'],
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
if (!msg.media.filename) {
|
|
297
|
+
ctx.addIssue({
|
|
298
|
+
code: z.ZodIssueCode.custom,
|
|
299
|
+
message: 'media.filename is required when messageKind is media',
|
|
300
|
+
path: ['media', 'filename'],
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
if (!msg.media.path) {
|
|
304
|
+
ctx.addIssue({
|
|
305
|
+
code: z.ZodIssueCode.custom,
|
|
306
|
+
message: 'media.path is required when messageKind is media',
|
|
307
|
+
path: ['media', 'path'],
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
// Export Envelope Schema
|
|
313
|
+
export const ExportEnvelopeSchema = z
|
|
314
|
+
.object({
|
|
315
|
+
schemaVersion: z.string(),
|
|
316
|
+
source: z.enum(['csv', 'db', 'merged']),
|
|
317
|
+
createdAt: z.string().datetime(),
|
|
318
|
+
messages: z.array(MessageSchema),
|
|
319
|
+
meta: z.record(z.any()).optional(),
|
|
320
|
+
})
|
|
321
|
+
.superRefine((envelope, ctx) => {
|
|
322
|
+
// SCHEMA-T01-AC05: ISO 8601 validation for createdAt
|
|
323
|
+
if (envelope.createdAt && !envelope.createdAt.match(/Z$/)) {
|
|
324
|
+
ctx.addIssue({
|
|
325
|
+
code: z.ZodIssueCode.custom,
|
|
326
|
+
message: 'createdAt must be ISO 8601 with Z suffix (UTC)',
|
|
327
|
+
path: ['createdAt'],
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
//# sourceMappingURL=message.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message.js","sourceRoot":"","sources":["../../src/schema/message.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Delta Detection Module (INCREMENTAL--T02)
|
|
3
|
+
*
|
|
4
|
+
* Identifies new messages for enrichment by comparing current normalized state
|
|
5
|
+
* with previous enrichment state.
|
|
6
|
+
*
|
|
7
|
+
* Implements:
|
|
8
|
+
* - AC01: Load previous state from .imessage-state.json
|
|
9
|
+
* - AC02: Diff normalized messages against enrichedGuids
|
|
10
|
+
* - AC03: Return only new GUIDs for enrichment
|
|
11
|
+
* - AC04: Handle state file missing (treat as first run)
|
|
12
|
+
* - AC05: Log delta summary: Found X new messages to enrich
|
|
13
|
+
*
|
|
14
|
+
* Architecture:
|
|
15
|
+
* - DeltaResult: Complete delta detection output
|
|
16
|
+
* - detectDelta: Main entry point for delta detection
|
|
17
|
+
* - extractGuidsFromMessages: Convert messages to GUID set
|
|
18
|
+
* - computeDelta: Core diff logic
|
|
19
|
+
* - logDeltaSummary: Human-readable delta report
|
|
20
|
+
*/
|
|
21
|
+
import type { Message } from '#schema/message';
|
|
22
|
+
import type { IncrementalState } from './incremental-state';
|
|
23
|
+
/**
|
|
24
|
+
* Result of delta detection
|
|
25
|
+
*
|
|
26
|
+
* Provides:
|
|
27
|
+
* - newGuids: Message GUIDs to enrich
|
|
28
|
+
* - totalMessages: Total current messages
|
|
29
|
+
* - previousEnrichedCount: Messages enriched in prior run
|
|
30
|
+
* - newCount: Number of new messages found
|
|
31
|
+
* - isFirstRun: Whether state file was missing
|
|
32
|
+
* - state: Loaded or created state for update after enrichment
|
|
33
|
+
*/
|
|
34
|
+
export type DeltaResult = {
|
|
35
|
+
/** GUIDs of messages to enrich (new since last run) */
|
|
36
|
+
newGuids: string[];
|
|
37
|
+
/** Total messages in normalized dataset */
|
|
38
|
+
totalMessages: number;
|
|
39
|
+
/** Count of previously enriched messages */
|
|
40
|
+
previousEnrichedCount: number;
|
|
41
|
+
/** Number of new messages found in delta */
|
|
42
|
+
newCount: number;
|
|
43
|
+
/** true if no prior state file found */
|
|
44
|
+
isFirstRun: boolean;
|
|
45
|
+
/** IncrementalState to update and save after enrichment */
|
|
46
|
+
state: IncrementalState;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* AC02 + AC03: Extract message GUIDs from normalized messages
|
|
50
|
+
*
|
|
51
|
+
* Converts Message[] to Set<guid> for efficient delta computation
|
|
52
|
+
*
|
|
53
|
+
* @param messages - Normalized messages to process
|
|
54
|
+
* @returns Set of unique message GUIDs
|
|
55
|
+
*/
|
|
56
|
+
export declare function extractGuidsFromMessages(messages: Message[]): Set<string>;
|
|
57
|
+
/**
|
|
58
|
+
* AC05: Log human-readable delta summary
|
|
59
|
+
*
|
|
60
|
+
* Outputs lines like:
|
|
61
|
+
* - "Found 142 new messages to enrich"
|
|
62
|
+
* - "Previously enriched: 358"
|
|
63
|
+
* - "This is your first enrichment run"
|
|
64
|
+
* - "Delta: 28.3% of 500 total messages"
|
|
65
|
+
*
|
|
66
|
+
* @param result - DeltaResult to summarize
|
|
67
|
+
*/
|
|
68
|
+
export declare function logDeltaSummary(result: DeltaResult): void;
|
|
69
|
+
/**
|
|
70
|
+
* AC01-AC05: Perform complete delta detection
|
|
71
|
+
*
|
|
72
|
+
* Workflow:
|
|
73
|
+
* 1. AC04: Load previous state (null if missing)
|
|
74
|
+
* 2. AC02: Extract current message GUIDs
|
|
75
|
+
* 3. AC03: Compute delta (new GUIDs only)
|
|
76
|
+
* 4. AC05: Log summary
|
|
77
|
+
*
|
|
78
|
+
* Returns DeltaResult with:
|
|
79
|
+
* - newGuids to enrich
|
|
80
|
+
* - metadata for progress tracking
|
|
81
|
+
* - state to update after enrichment
|
|
82
|
+
*
|
|
83
|
+
* @param messages - Normalized messages from normalize-link stage
|
|
84
|
+
* @param stateFilePath - Path to .imessage-state.json
|
|
85
|
+
* @returns DeltaResult with new GUIDs and metadata
|
|
86
|
+
* @throws Error if state file can't be read (permission denied, etc.)
|
|
87
|
+
*/
|
|
88
|
+
export declare function detectDelta(messages: Message[], stateFilePath: string): Promise<DeltaResult>;
|
|
89
|
+
/**
|
|
90
|
+
* Calculate delta statistics for progress monitoring
|
|
91
|
+
*
|
|
92
|
+
* Useful for:
|
|
93
|
+
* - Progress bars (show percentage to enrich)
|
|
94
|
+
* - ETA calculation
|
|
95
|
+
* - Summary reports
|
|
96
|
+
*
|
|
97
|
+
* @param result - DeltaResult to analyze
|
|
98
|
+
* @returns Statistics object with counts and percentages
|
|
99
|
+
*/
|
|
100
|
+
export declare function getDeltaStats(result: DeltaResult): {
|
|
101
|
+
total: number;
|
|
102
|
+
new: number;
|
|
103
|
+
previous: number;
|
|
104
|
+
percentNew: number;
|
|
105
|
+
percentPrevious: number;
|
|
106
|
+
};
|
|
107
|
+
//# sourceMappingURL=delta-detection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delta-detection.d.ts","sourceRoot":"","sources":["../../src/utils/delta-detection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAG9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAO3D;;;;;;;;;;GAUG;AACH,MAAM,MAAM,WAAW,GAAG;IACzB,uDAAuD;IACvD,QAAQ,EAAE,MAAM,EAAE,CAAA;IAElB,2CAA2C;IAC3C,aAAa,EAAE,MAAM,CAAA;IAErB,4CAA4C;IAC5C,qBAAqB,EAAE,MAAM,CAAA;IAE7B,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAA;IAEhB,wCAAwC;IACxC,UAAU,EAAE,OAAO,CAAA;IAEnB,2DAA2D;IAC3D,KAAK,EAAE,gBAAgB,CAAA;CACvB,CAAA;AA2BD;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAMzE;AAgCD;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CA6BzD;AAMD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,WAAW,CAChC,QAAQ,EAAE,OAAO,EAAE,EACnB,aAAa,EAAE,MAAM,GACnB,OAAO,CAAC,WAAW,CAAC,CAgCtB;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,WAAW,GAAG;IACnD,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,eAAe,EAAE,MAAM,CAAA;CACvB,CAYA"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Delta Detection Module (INCREMENTAL--T02)
|
|
3
|
+
*
|
|
4
|
+
* Identifies new messages for enrichment by comparing current normalized state
|
|
5
|
+
* with previous enrichment state.
|
|
6
|
+
*
|
|
7
|
+
* Implements:
|
|
8
|
+
* - AC01: Load previous state from .imessage-state.json
|
|
9
|
+
* - AC02: Diff normalized messages against enrichedGuids
|
|
10
|
+
* - AC03: Return only new GUIDs for enrichment
|
|
11
|
+
* - AC04: Handle state file missing (treat as first run)
|
|
12
|
+
* - AC05: Log delta summary: Found X new messages to enrich
|
|
13
|
+
*
|
|
14
|
+
* Architecture:
|
|
15
|
+
* - DeltaResult: Complete delta detection output
|
|
16
|
+
* - detectDelta: Main entry point for delta detection
|
|
17
|
+
* - extractGuidsFromMessages: Convert messages to GUID set
|
|
18
|
+
* - computeDelta: Core diff logic
|
|
19
|
+
* - logDeltaSummary: Human-readable delta report
|
|
20
|
+
*/
|
|
21
|
+
import { humanInfo } from '#utils/human';
|
|
22
|
+
import { createLogger } from '#utils/logger';
|
|
23
|
+
import { detectNewMessages, loadIncrementalState } from './incremental-state';
|
|
24
|
+
// ============================================================================
|
|
25
|
+
// AC01 + AC04: Load previous state safely
|
|
26
|
+
// ============================================================================
|
|
27
|
+
/**
|
|
28
|
+
* AC01 + AC04: Load incremental state from disk
|
|
29
|
+
*
|
|
30
|
+
* Handles missing state file gracefully:
|
|
31
|
+
* - Returns null if file doesn't exist (first run)
|
|
32
|
+
* - Returns null if JSON is corrupted
|
|
33
|
+
* - Returns parsed state if valid
|
|
34
|
+
*
|
|
35
|
+
* @param stateFilePath - Path to .imessage-state.json
|
|
36
|
+
* @returns IncrementalState if found and valid, null if missing or corrupted
|
|
37
|
+
*/
|
|
38
|
+
async function loadPreviousState(stateFilePath) {
|
|
39
|
+
return loadIncrementalState(stateFilePath);
|
|
40
|
+
}
|
|
41
|
+
// ============================================================================
|
|
42
|
+
// AC02 + AC03: Extract GUIDs and compute delta
|
|
43
|
+
// ============================================================================
|
|
44
|
+
/**
|
|
45
|
+
* AC02 + AC03: Extract message GUIDs from normalized messages
|
|
46
|
+
*
|
|
47
|
+
* Converts Message[] to Set<guid> for efficient delta computation
|
|
48
|
+
*
|
|
49
|
+
* @param messages - Normalized messages to process
|
|
50
|
+
* @returns Set of unique message GUIDs
|
|
51
|
+
*/
|
|
52
|
+
export function extractGuidsFromMessages(messages) {
|
|
53
|
+
const guids = new Set();
|
|
54
|
+
for (const msg of messages) {
|
|
55
|
+
guids.add(msg.guid);
|
|
56
|
+
}
|
|
57
|
+
return guids;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* AC02 + AC03: Compute delta between current and previous state
|
|
61
|
+
*
|
|
62
|
+
* Performance: O(n + m) where:
|
|
63
|
+
* - n = number of current messages
|
|
64
|
+
* - m = number of previously enriched messages
|
|
65
|
+
*
|
|
66
|
+
* Uses Set-based deduplication for O(1) lookup
|
|
67
|
+
*
|
|
68
|
+
* @param currentGuids - Set of message GUIDs from normalized state
|
|
69
|
+
* @param previousState - Prior state with enriched GUIDs (null if first run)
|
|
70
|
+
* @returns New GUIDs not in previous state
|
|
71
|
+
*/
|
|
72
|
+
function computeDelta(currentGuids, previousState) {
|
|
73
|
+
if (!previousState) {
|
|
74
|
+
// First run: all current messages are "new"
|
|
75
|
+
return Array.from(currentGuids);
|
|
76
|
+
}
|
|
77
|
+
// Use existing delta detection from incremental-state module
|
|
78
|
+
return detectNewMessages(currentGuids, previousState);
|
|
79
|
+
}
|
|
80
|
+
// ============================================================================
|
|
81
|
+
// AC05: Delta Summary Logging
|
|
82
|
+
// ============================================================================
|
|
83
|
+
/**
|
|
84
|
+
* AC05: Log human-readable delta summary
|
|
85
|
+
*
|
|
86
|
+
* Outputs lines like:
|
|
87
|
+
* - "Found 142 new messages to enrich"
|
|
88
|
+
* - "Previously enriched: 358"
|
|
89
|
+
* - "This is your first enrichment run"
|
|
90
|
+
* - "Delta: 28.3% of 500 total messages"
|
|
91
|
+
*
|
|
92
|
+
* @param result - DeltaResult to summarize
|
|
93
|
+
*/
|
|
94
|
+
export function logDeltaSummary(result) {
|
|
95
|
+
const logger = createLogger('utils:delta-detection');
|
|
96
|
+
const newCount = result.newCount;
|
|
97
|
+
const totalCount = result.totalMessages;
|
|
98
|
+
const previousCount = result.previousEnrichedCount;
|
|
99
|
+
// Log delta summary (AC05)
|
|
100
|
+
if (result.isFirstRun) {
|
|
101
|
+
// Structured log (machine consumption)
|
|
102
|
+
logger.info('First enrichment run', { totalMessages: totalCount });
|
|
103
|
+
// Human-friendly console output retained for tests & CLI UX
|
|
104
|
+
// Format expected by tests: contains both 'First enrichment run' and '<N> messages'
|
|
105
|
+
humanInfo(`First enrichment run: ${totalCount} messages`);
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
const percentNew = totalCount > 0 ? (newCount / totalCount) * 100 : 0;
|
|
109
|
+
// Structured log
|
|
110
|
+
logger.info('Delta detected', {
|
|
111
|
+
newMessages: newCount,
|
|
112
|
+
percentNew,
|
|
113
|
+
totalMessages: totalCount,
|
|
114
|
+
previouslyEnriched: previousCount,
|
|
115
|
+
});
|
|
116
|
+
// Human-readable lines expected by tests
|
|
117
|
+
// Includes phrases: 'Delta detected', '<X> new messages', '<Y.Y%>' and 'Previously enriched: <N>'
|
|
118
|
+
humanInfo(`Delta detected: ${newCount} new messages (${percentNew.toFixed(1)}%) of ${totalCount} total messages`);
|
|
119
|
+
humanInfo(`Previously enriched: ${previousCount}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// ============================================================================
|
|
123
|
+
// AC01-AC05: Main entry point for delta detection
|
|
124
|
+
// ============================================================================
|
|
125
|
+
/**
|
|
126
|
+
* AC01-AC05: Perform complete delta detection
|
|
127
|
+
*
|
|
128
|
+
* Workflow:
|
|
129
|
+
* 1. AC04: Load previous state (null if missing)
|
|
130
|
+
* 2. AC02: Extract current message GUIDs
|
|
131
|
+
* 3. AC03: Compute delta (new GUIDs only)
|
|
132
|
+
* 4. AC05: Log summary
|
|
133
|
+
*
|
|
134
|
+
* Returns DeltaResult with:
|
|
135
|
+
* - newGuids to enrich
|
|
136
|
+
* - metadata for progress tracking
|
|
137
|
+
* - state to update after enrichment
|
|
138
|
+
*
|
|
139
|
+
* @param messages - Normalized messages from normalize-link stage
|
|
140
|
+
* @param stateFilePath - Path to .imessage-state.json
|
|
141
|
+
* @returns DeltaResult with new GUIDs and metadata
|
|
142
|
+
* @throws Error if state file can't be read (permission denied, etc.)
|
|
143
|
+
*/
|
|
144
|
+
export async function detectDelta(messages, stateFilePath) {
|
|
145
|
+
// AC01 + AC04: Load previous state (null if missing)
|
|
146
|
+
const previousState = await loadPreviousState(stateFilePath);
|
|
147
|
+
const isFirstRun = previousState === null;
|
|
148
|
+
// AC02 + AC03: Extract current GUIDs and compute delta
|
|
149
|
+
const currentGuids = extractGuidsFromMessages(messages);
|
|
150
|
+
const newGuids = computeDelta(currentGuids, previousState);
|
|
151
|
+
// Build result
|
|
152
|
+
const result = {
|
|
153
|
+
newGuids,
|
|
154
|
+
totalMessages: messages.length,
|
|
155
|
+
previousEnrichedCount: previousState?.enrichedGuids.length ?? 0,
|
|
156
|
+
newCount: newGuids.length,
|
|
157
|
+
isFirstRun,
|
|
158
|
+
state: previousState ?? {
|
|
159
|
+
version: '1.0',
|
|
160
|
+
lastEnrichedAt: new Date().toISOString(),
|
|
161
|
+
totalMessages: messages.length,
|
|
162
|
+
enrichedGuids: [],
|
|
163
|
+
pipelineConfig: {
|
|
164
|
+
configHash: '',
|
|
165
|
+
},
|
|
166
|
+
enrichmentStats: null,
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
// AC05: Log summary
|
|
170
|
+
logDeltaSummary(result);
|
|
171
|
+
return result;
|
|
172
|
+
}
|
|
173
|
+
// ============================================================================
|
|
174
|
+
// Utility: Get delta statistics for progress reporting
|
|
175
|
+
// ============================================================================
|
|
176
|
+
/**
|
|
177
|
+
* Calculate delta statistics for progress monitoring
|
|
178
|
+
*
|
|
179
|
+
* Useful for:
|
|
180
|
+
* - Progress bars (show percentage to enrich)
|
|
181
|
+
* - ETA calculation
|
|
182
|
+
* - Summary reports
|
|
183
|
+
*
|
|
184
|
+
* @param result - DeltaResult to analyze
|
|
185
|
+
* @returns Statistics object with counts and percentages
|
|
186
|
+
*/
|
|
187
|
+
export function getDeltaStats(result) {
|
|
188
|
+
const total = result.totalMessages;
|
|
189
|
+
const newCount = result.newCount;
|
|
190
|
+
const previousCount = result.previousEnrichedCount;
|
|
191
|
+
return {
|
|
192
|
+
total,
|
|
193
|
+
new: newCount,
|
|
194
|
+
previous: previousCount,
|
|
195
|
+
percentNew: total > 0 ? (newCount / total) * 100 : 0,
|
|
196
|
+
percentPrevious: total > 0 ? (previousCount / total) * 100 : 0,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=delta-detection.js.map
|