plasalid 0.7.1 → 0.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/README.md +15 -15
  2. package/dist/accounts/taxonomy.d.ts +1 -1
  3. package/dist/accounts/taxonomy.js +1 -1
  4. package/dist/ai/agent.d.ts +9 -10
  5. package/dist/ai/agent.js +31 -15
  6. package/dist/ai/personas.d.ts +1 -1
  7. package/dist/ai/personas.js +57 -55
  8. package/dist/ai/prompt-sections.d.ts +4 -4
  9. package/dist/ai/prompt-sections.js +1 -1
  10. package/dist/ai/system-prompt.d.ts +2 -2
  11. package/dist/ai/system-prompt.js +5 -5
  12. package/dist/ai/tools/account-mutex.d.ts +1 -0
  13. package/dist/ai/tools/account-mutex.js +16 -0
  14. package/dist/ai/tools/clarify.d.ts +2 -0
  15. package/dist/ai/tools/clarify.js +169 -0
  16. package/dist/ai/tools/index.js +10 -18
  17. package/dist/ai/tools/ingest.d.ts +2 -2
  18. package/dist/ai/tools/ingest.js +284 -244
  19. package/dist/ai/tools/merchants.js +1 -28
  20. package/dist/ai/tools/read.js +8 -8
  21. package/dist/ai/tools/record.js +7 -40
  22. package/dist/ai/tools/resolve.js +25 -22
  23. package/dist/ai/tools/scan.js +0 -1
  24. package/dist/ai/tools/types.d.ts +14 -21
  25. package/dist/cli/commands/clarify.d.ts +5 -0
  26. package/dist/cli/commands/clarify.js +44 -0
  27. package/dist/cli/commands/record.js +1 -82
  28. package/dist/cli/commands/resolve.d.ts +5 -2
  29. package/dist/cli/commands/resolve.js +36 -5
  30. package/dist/cli/commands/revert.js +4 -2
  31. package/dist/cli/commands/rules.js +2 -2
  32. package/dist/cli/commands/scan.js +199 -128
  33. package/dist/cli/commands/status.js +6 -6
  34. package/dist/cli/index.js +8 -29
  35. package/dist/cli/ink/ScanDashboard.d.ts +49 -0
  36. package/dist/cli/ink/ScanDashboard.js +214 -0
  37. package/dist/cli/ink/scan_dashboard.d.ts +40 -25
  38. package/dist/cli/ink/scan_dashboard.js +139 -44
  39. package/dist/cli/setup.js +1 -1
  40. package/dist/cli/ux.js +1 -1
  41. package/dist/db/queries/account-balance.d.ts +1 -1
  42. package/dist/db/queries/questions.d.ts +62 -0
  43. package/dist/db/queries/questions.js +110 -0
  44. package/dist/db/queries/transactions.d.ts +1 -1
  45. package/dist/db/queries/unknowns.d.ts +17 -15
  46. package/dist/db/queries/unknowns.js +35 -39
  47. package/dist/db/schema.js +6 -28
  48. package/dist/scanner/audit/auditor.d.ts +31 -0
  49. package/dist/scanner/audit/auditor.js +72 -0
  50. package/dist/scanner/audit/engine.d.ts +10 -0
  51. package/dist/scanner/audit/engine.js +98 -0
  52. package/dist/scanner/audit/eventBus.d.ts +60 -0
  53. package/dist/scanner/audit/eventBus.js +35 -0
  54. package/dist/scanner/audit/passes/index.d.ts +11 -0
  55. package/dist/scanner/audit/passes/index.js +9 -0
  56. package/dist/scanner/audit/passes/types.d.ts +23 -0
  57. package/dist/scanner/audit/passes/types.js +1 -0
  58. package/dist/scanner/audit/types.d.ts +27 -0
  59. package/dist/scanner/audit/types.js +1 -0
  60. package/dist/scanner/auditor.d.ts +51 -0
  61. package/dist/scanner/auditor.js +80 -0
  62. package/dist/scanner/buffer/engine.d.ts +9 -0
  63. package/dist/scanner/buffer/engine.js +110 -0
  64. package/dist/scanner/buffer/sharedBuffer.d.ts +78 -0
  65. package/dist/scanner/buffer/sharedBuffer.js +130 -0
  66. package/dist/scanner/buffer/types.d.ts +67 -0
  67. package/dist/scanner/buffer/types.js +1 -0
  68. package/dist/scanner/buffer.d.ts +45 -38
  69. package/dist/scanner/buffer.js +93 -61
  70. package/dist/scanner/bus/engine.d.ts +11 -0
  71. package/dist/scanner/bus/engine.js +42 -0
  72. package/dist/scanner/bus/types.d.ts +53 -0
  73. package/dist/scanner/bus/types.js +1 -0
  74. package/dist/scanner/bus.d.ts +38 -0
  75. package/dist/scanner/bus.js +37 -0
  76. package/dist/scanner/chunk-worker.d.ts +19 -0
  77. package/dist/scanner/chunk-worker.js +67 -0
  78. package/dist/scanner/chunkWorker.d.ts +20 -0
  79. package/dist/scanner/chunkWorker.js +59 -0
  80. package/dist/scanner/chunker/chunker.d.ts +7 -0
  81. package/dist/scanner/chunker/chunker.js +60 -0
  82. package/dist/scanner/chunker.d.ts +7 -0
  83. package/dist/scanner/chunker.js +60 -0
  84. package/dist/scanner/clarifier-memory.d.ts +8 -0
  85. package/dist/scanner/clarifier-memory.js +24 -0
  86. package/dist/scanner/clarifier.d.ts +39 -0
  87. package/dist/scanner/clarifier.js +196 -0
  88. package/dist/scanner/converge.d.ts +29 -0
  89. package/dist/scanner/converge.js +15 -0
  90. package/dist/scanner/decrypt.d.ts +10 -0
  91. package/dist/scanner/decrypt.js +80 -0
  92. package/dist/scanner/engine/scanEngine.d.ts +24 -0
  93. package/dist/scanner/engine/scanEngine.js +87 -0
  94. package/dist/scanner/engine/types.d.ts +90 -0
  95. package/dist/scanner/engine/types.js +1 -0
  96. package/dist/scanner/engine.d.ts +90 -0
  97. package/dist/scanner/engine.js +84 -0
  98. package/dist/scanner/file-worker.d.ts +33 -0
  99. package/dist/scanner/file-worker.js +28 -0
  100. package/dist/scanner/fileWorker.d.ts +33 -0
  101. package/dist/scanner/fileWorker.js +22 -0
  102. package/dist/scanner/hooks/types.d.ts +25 -0
  103. package/dist/scanner/hooks/types.js +1 -0
  104. package/dist/scanner/hooks.d.ts +23 -0
  105. package/dist/scanner/hooks.js +1 -0
  106. package/dist/scanner/parse.d.ts +10 -0
  107. package/dist/scanner/parse.js +47 -0
  108. package/dist/scanner/passes/index.d.ts +8 -0
  109. package/dist/scanner/passes/index.js +6 -0
  110. package/dist/scanner/passes/types.d.ts +22 -0
  111. package/dist/scanner/passes/types.js +1 -0
  112. package/dist/scanner/pdf/chunker.d.ts +7 -0
  113. package/dist/scanner/pdf/chunker.js +60 -0
  114. package/dist/scanner/pdf/password-store.d.ts +34 -0
  115. package/dist/scanner/pdf/password-store.js +83 -0
  116. package/dist/scanner/pdf/pdf-unlock.d.ts +17 -0
  117. package/dist/scanner/pdf/pdf-unlock.js +50 -0
  118. package/dist/scanner/pdf/pdf.d.ts +17 -0
  119. package/dist/scanner/pdf/pdf.js +36 -0
  120. package/dist/scanner/pdf/state-machine.d.ts +60 -0
  121. package/dist/scanner/pdf/state-machine.js +64 -0
  122. package/dist/scanner/pdf/unlock.d.ts +22 -0
  123. package/dist/scanner/pdf/unlock.js +121 -0
  124. package/dist/scanner/phase-decrypt.d.ts +10 -0
  125. package/dist/scanner/phase-decrypt.js +80 -0
  126. package/dist/scanner/phase-parse.d.ts +10 -0
  127. package/dist/scanner/phase-parse.js +46 -0
  128. package/dist/scanner/phases/chunk.d.ts +8 -0
  129. package/dist/scanner/phases/chunk.js +13 -0
  130. package/dist/scanner/phases/commit.d.ts +12 -0
  131. package/dist/scanner/phases/commit.js +140 -0
  132. package/dist/scanner/phases/decrypt.d.ts +10 -0
  133. package/dist/scanner/phases/decrypt.js +80 -0
  134. package/dist/scanner/phases/parse.d.ts +10 -0
  135. package/dist/scanner/phases/parse.js +46 -0
  136. package/dist/scanner/phases/resolve.d.ts +10 -0
  137. package/dist/scanner/phases/resolve.js +17 -0
  138. package/dist/scanner/phases/review.d.ts +10 -0
  139. package/dist/scanner/phases/review.js +12 -0
  140. package/dist/scanner/progress.d.ts +14 -0
  141. package/dist/scanner/progress.js +21 -0
  142. package/dist/scanner/resolver-memory.d.ts +8 -0
  143. package/dist/scanner/resolver-memory.js +24 -0
  144. package/dist/scanner/resolver.d.ts +39 -0
  145. package/dist/scanner/resolver.js +196 -0
  146. package/dist/scanner/result.d.ts +17 -0
  147. package/dist/scanner/result.js +19 -0
  148. package/dist/scanner/run-passes.d.ts +30 -0
  149. package/dist/scanner/run-passes.js +15 -0
  150. package/dist/scanner/unlock.js +1 -1
  151. package/dist/scanner/worker.d.ts +19 -0
  152. package/dist/scanner/worker.js +67 -0
  153. package/dist/scanner/workers/chunkWorker.d.ts +20 -0
  154. package/dist/scanner/workers/chunkWorker.js +65 -0
  155. package/dist/scanner/workers/fileWorker.d.ts +32 -0
  156. package/dist/scanner/workers/fileWorker.js +22 -0
  157. package/package.json +1 -1
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Lightweight Result helpers shared across scanner subdomains. Use this
3
+ * instead of inline try/catch when a function can fail with a human-readable
4
+ * reason and the caller needs to branch on the outcome (decrypt, chunk parse,
5
+ * commit-one-transaction). Distinct from concurrency.ts `Settled<T>` — that
6
+ * type is owned by `runWithConcurrency` and includes an `error: unknown`;
7
+ * `Result<T>` stringifies the error up front for ergonomic message handling.
8
+ */
9
+ export function errorMessage(err) {
10
+ return err instanceof Error ? err.message : String(err);
11
+ }
12
+ export async function tryExecute(fn) {
13
+ try {
14
+ return { ok: true, value: await fn() };
15
+ }
16
+ catch (err) {
17
+ return { ok: false, error: errorMessage(err) };
18
+ }
19
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Generic "drive a loop with named hooks" helper.
3
+ *
4
+ * The driver owns counting passes, stall detection, and the iteration cap.
5
+ * Everything else (work performed each pass, what to print when, how to react
6
+ * to stall vs success vs failure) lives in the hooks the caller supplies.
7
+ *
8
+ * The state `S` is whatever quantity decides "are we done?" — typically a
9
+ * remaining-work count, but it can be any value you can compare.
10
+ */
11
+ export interface RunPassesOpts<S> {
12
+ /** Initial state (e.g. `countOpenUnknowns(db)`). */
13
+ initial: S;
14
+ /** Maximum number of passes before declaring failure. Must be >= 1. */
15
+ maxAttempts: number;
16
+ /** True when the work is finished and the loop should stop cleanly. */
17
+ isDone: (state: S) => boolean;
18
+ /**
19
+ * True when this pass made no progress vs the previous pass. Fires after
20
+ * the first pass at the earliest.
21
+ */
22
+ isStalled: (curr: S, prev: S) => boolean;
23
+ /** Run one pass; return the new state. Pass numbers are 1-indexed. */
24
+ onPass: (pass: number, state: S) => Promise<S>;
25
+ onStart?: (state: S) => void;
26
+ onStall?: (state: S) => void;
27
+ onSuccess?: (state: S) => void;
28
+ onFail?: (state: S) => void;
29
+ }
30
+ export declare function runPasses<S>(opts: RunPassesOpts<S>): Promise<S>;
@@ -0,0 +1,15 @@
1
+ export async function runPasses(opts) {
2
+ let state = opts.initial;
3
+ let prev = state;
4
+ opts.onStart?.(state);
5
+ for (let pass = 1; pass <= opts.maxAttempts && !opts.isDone(state); pass++) {
6
+ if (pass > 1 && opts.isStalled(state, prev)) {
7
+ opts.onStall?.(state);
8
+ return state;
9
+ }
10
+ prev = state;
11
+ state = await opts.onPass(pass, state);
12
+ }
13
+ (opts.isDone(state) ? opts.onSuccess : opts.onFail)?.(state);
14
+ return state;
15
+ }
@@ -115,7 +115,7 @@ export function persistUnlockOutcome(db, filePath, outcome) {
115
115
  spinner.succeed(`Saved password for pattern ${pattern} in secure vault.`);
116
116
  }
117
117
  catch (err) {
118
- spinner.fail(`Could not save password: ${err.message}`);
118
+ spinner.fail(`Could not save password: ${err instanceof Error ? err.message : String(err)}`);
119
119
  throw err;
120
120
  }
121
121
  }
@@ -0,0 +1,19 @@
1
+ import type Database from "libsql";
2
+ import type { Chunk } from "./engine.js";
3
+ import type { ScanHooks } from "./hooks.js";
4
+ import type { ScanProgress } from "./progress.js";
5
+ export interface ScanWorkerDeps {
6
+ readonly db: Database.Database;
7
+ readonly scanId: string;
8
+ readonly scannedFileId: string | undefined;
9
+ readonly progress: ScanProgress;
10
+ readonly chunk: Chunk;
11
+ }
12
+ /**
13
+ * Process one chunk: run the LLM scan agent over a single-page PDF blob with
14
+ * scanId + progress sink + scanned_files row injected through the agent
15
+ * context. Agent's record_transactions / note_question calls write directly to
16
+ * the DB; per-row ticks fan out via `progress.emit`. Failures land in the DB
17
+ * as a `chunk_failed` question so the clarifier can pick them up.
18
+ */
19
+ export declare function runScanWorker(deps: ScanWorkerDeps, hooks: ScanHooks): Promise<void>;
@@ -0,0 +1,67 @@
1
+ import { randomUUID } from "crypto";
2
+ import { runScanAgent } from "../ai/agent.js";
3
+ import { recordQuestion } from "../db/queries/questions.js";
4
+ import { buildDocumentBlock } from "./pdf/pdf.js";
5
+ import { tryExecute } from "./result.js";
6
+ /**
7
+ * Process one chunk: run the LLM scan agent over a single-page PDF blob with
8
+ * scanId + progress sink + scanned_files row injected through the agent
9
+ * context. Agent's record_transactions / note_question calls write directly to
10
+ * the DB; per-row ticks fan out via `progress.emit`. Failures land in the DB
11
+ * as a `chunk_failed` question so the clarifier can pick them up.
12
+ */
13
+ export async function runScanWorker(deps, hooks) {
14
+ const workerId = `cw:${randomUUID()}`;
15
+ hooks.onWorkerStart?.(workerId, deps.chunk);
16
+ const outcome = await tryExecute(() => runScanAgent({
17
+ db: deps.db,
18
+ initialMessages: [
19
+ {
20
+ role: "user",
21
+ content: [
22
+ buildDocumentBlock(deps.chunk.bytes, deps.chunk.fileName, deps.chunk.mime),
23
+ { type: "text", text: buildChunkPrompt(deps.chunk) },
24
+ ],
25
+ },
26
+ ],
27
+ prompt: { fileName: deps.chunk.fileName },
28
+ agentCtx: {
29
+ interactive: false,
30
+ scanId: deps.scanId,
31
+ fileId: deps.scannedFileId,
32
+ chunkId: deps.chunk.chunkId,
33
+ progress: deps.progress,
34
+ },
35
+ }));
36
+ hooks.onWorkerEnd?.(workerId, deps.chunk, outcome.ok);
37
+ if (!outcome.ok)
38
+ recordChunkFailure(deps, outcome.error);
39
+ }
40
+ function recordChunkFailure(deps, error) {
41
+ try {
42
+ recordQuestion(deps.db, {
43
+ file_id: deps.scannedFileId ?? null,
44
+ scan_id: deps.scanId,
45
+ transaction_id: null,
46
+ account_id: null,
47
+ kind: "chunk_failed",
48
+ prompt: `Chunk ${deps.chunk.fileName} p${deps.chunk.pageNumber} failed to parse: ${error}.`,
49
+ });
50
+ deps.progress.emit({ chunkId: deps.chunk.chunkId, kind: "question" });
51
+ }
52
+ catch {
53
+ // failure to record a failure shouldn't crash the file worker
54
+ }
55
+ }
56
+ function buildChunkPrompt(chunk) {
57
+ return [
58
+ `You are parsing page ${chunk.pageNumber} of ${chunk.totalPages} of ${chunk.fileName}.`,
59
+ ``,
60
+ `Steps:`,
61
+ `1. Call list_accounts to see what already exists.`,
62
+ `2. If this page reveals an account that isn't in the chart yet, call create_account once.`,
63
+ `3. For every transaction on this page, call record_transactions (plural) with all rows in one batch.`,
64
+ `4. If the first or last row looks incomplete (no date, or no amount column visible — the row likely continues onto an adjacent page), call note_question with kind="boundary_continuation" and the raw row text. Do NOT invent missing fields.`,
65
+ `5. When done with this page, call mark_file_scanned with a short summary.`,
66
+ ].join("\n");
67
+ }
@@ -0,0 +1,20 @@
1
+ import type Database from "libsql";
2
+ import type { ScanBuffer } from "../buffer/types.js";
3
+ import type { Chunk, ScanHooks } from "../engine/types.js";
4
+ export interface ChunkWorkerDeps {
5
+ readonly db: Database.Database;
6
+ readonly buffer: ScanBuffer;
7
+ readonly chunk: Chunk;
8
+ }
9
+ export interface ChunkWorkerResult {
10
+ readonly workerId: string;
11
+ readonly ok: boolean;
12
+ readonly error?: string;
13
+ }
14
+ /**
15
+ * Process one chunk: run the LLM scan agent over a single-page PDF blob with
16
+ * the shared Buffer + chunkId injected. The agent's `record_transactions`
17
+ * calls land in the shared buffer; events fan out to the auditor and the
18
+ * dashboard.
19
+ */
20
+ export declare function runChunkWorker(deps: ChunkWorkerDeps, hooks: ScanHooks): Promise<ChunkWorkerResult>;
@@ -0,0 +1,65 @@
1
+ import { randomUUID } from "crypto";
2
+ import { runScanAgent } from "../../ai/agent.js";
3
+ import { buildDocumentBlock } from "../pdf.js";
4
+ /**
5
+ * Process one chunk: run the LLM scan agent over a single-page PDF blob with
6
+ * the shared Buffer + chunkId injected. The agent's `record_transactions`
7
+ * calls land in the shared buffer; events fan out to the auditor and the
8
+ * dashboard.
9
+ */
10
+ export async function runChunkWorker(deps, hooks) {
11
+ const workerId = `cw:${randomUUID()}`;
12
+ hooks.onWorkerStart?.(workerId, deps.chunk);
13
+ const outcome = await tryParseChunk(deps);
14
+ hooks.onWorkerEnd?.(workerId, deps.chunk, outcome.ok);
15
+ if (!outcome.ok)
16
+ await recordChunkFailure(deps.buffer, deps.chunk, outcome.error);
17
+ return { workerId, ...outcome };
18
+ }
19
+ async function tryParseChunk(deps) {
20
+ try {
21
+ await runScanAgent({
22
+ db: deps.db,
23
+ initialMessages: [
24
+ {
25
+ role: "user",
26
+ content: [
27
+ buildDocumentBlock(deps.chunk.bytes, deps.chunk.fileName, deps.chunk.mime),
28
+ { type: "text", text: buildChunkPrompt(deps.chunk) },
29
+ ],
30
+ },
31
+ ],
32
+ prompt: { fileName: deps.chunk.fileName },
33
+ agentCtx: {
34
+ interactive: false,
35
+ buffer: deps.buffer,
36
+ chunkId: deps.chunk.chunkId,
37
+ },
38
+ });
39
+ return { ok: true };
40
+ }
41
+ catch (err) {
42
+ return { ok: false, error: err instanceof Error ? err.message : String(err) };
43
+ }
44
+ }
45
+ async function recordChunkFailure(buffer, chunk, error) {
46
+ await buffer.appendUnknown({
47
+ chunkId: chunk.chunkId,
48
+ transaction_id: null,
49
+ account_id: null,
50
+ kind: "chunk_failed",
51
+ prompt: `Chunk ${chunk.fileName} p${chunk.pageNumber} failed to parse: ${error}.`,
52
+ });
53
+ }
54
+ function buildChunkPrompt(chunk) {
55
+ return [
56
+ `You are parsing page ${chunk.pageNumber} of ${chunk.totalPages} of ${chunk.fileName}.`,
57
+ ``,
58
+ `Steps:`,
59
+ `1. Call list_accounts to see what already exists.`,
60
+ `2. If this page reveals an account that isn't in the chart yet, call create_account once.`,
61
+ `3. For every transaction on this page, call record_transactions (plural) with all rows in one batch.`,
62
+ `4. If the first or last row looks incomplete (no date, or no amount column visible — the row likely continues onto an adjacent page), call note_unknown with kind="boundary_continuation" and the raw row text. Do NOT invent missing fields.`,
63
+ `5. When done with this page, call mark_file_scanned with a short summary.`,
64
+ ].join("\n");
65
+ }
@@ -0,0 +1,32 @@
1
+ import type Database from "libsql";
2
+ import { type ChunkWorkerDeps, type ChunkWorkerResult } from "./chunkWorker.js";
3
+ import type { ScanBuffer } from "../buffer/types.js";
4
+ import type { Chunk, ScanHooks } from "../engine/types.js";
5
+ /**
6
+ * Strategy hook — pluggable parser for one chunk. Default is the LLM-driven
7
+ * runChunkWorker; tests and alternate flows (OCR-only, mock, dry-run) inject
8
+ * their own without modifying the file worker. Open for extension; closed
9
+ * for modification.
10
+ */
11
+ export type ChunkWorkerFn = (deps: ChunkWorkerDeps, hooks: ScanHooks) => Promise<ChunkWorkerResult>;
12
+ export interface FileWorkerDeps {
13
+ readonly db: Database.Database;
14
+ readonly buffer: ScanBuffer;
15
+ readonly fileId: string;
16
+ readonly chunks: readonly Chunk[];
17
+ readonly maxChunkWorkers: number;
18
+ /** Optional override; defaults to the LLM-backed runChunkWorker. */
19
+ readonly chunkWorkerFn?: ChunkWorkerFn;
20
+ }
21
+ export interface FileWorkerResult {
22
+ readonly workerId: string;
23
+ readonly fileId: string;
24
+ readonly ok: number;
25
+ readonly failed: number;
26
+ }
27
+ /**
28
+ * Process every chunk of one file in parallel up to `maxChunkWorkers`. The
29
+ * shared buffer + bus are dependency-injected; this function has no global
30
+ * state and never reaches outside its args.
31
+ */
32
+ export declare function runFileWorker(deps: FileWorkerDeps, hooks: ScanHooks): Promise<FileWorkerResult>;
@@ -0,0 +1,22 @@
1
+ import { randomUUID } from "crypto";
2
+ import { runWithConcurrency } from "../concurrency.js";
3
+ import { runChunkWorker } from "./chunkWorker.js";
4
+ /**
5
+ * Process every chunk of one file in parallel up to `maxChunkWorkers`. The
6
+ * shared buffer + bus are dependency-injected; this function has no global
7
+ * state and never reaches outside its args.
8
+ */
9
+ export async function runFileWorker(deps, hooks) {
10
+ const workerId = `fw:${randomUUID()}`;
11
+ const chunkFn = deps.chunkWorkerFn ?? runChunkWorker;
12
+ const tasks = deps.chunks.map(chunk => () => chunkFn({ db: deps.db, buffer: deps.buffer, chunk }, hooks));
13
+ const settled = await runWithConcurrency(tasks, deps.maxChunkWorkers);
14
+ let ok = 0, failed = 0;
15
+ for (const r of settled) {
16
+ if (!r.ok || !r.value.ok)
17
+ failed++;
18
+ else
19
+ ok++;
20
+ }
21
+ return { workerId, fileId: deps.fileId, ok, failed };
22
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "plasalid",
3
- "version": "0.7.1",
3
+ "version": "0.7.3",
4
4
  "description": "Plasalid — The Harness Layer for Personal Finance",
5
5
  "keywords": [
6
6
  "finance",