swarmdo 1.27.0 → 1.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/.claude/helpers/auto-memory-hook.mjs +71 -34
  2. package/.claude-plugin/README.md +3 -3
  3. package/.claude-plugin/docs/INSTALLATION.md +1 -1
  4. package/.claude-plugin/docs/PLUGIN_SUMMARY.md +1 -1
  5. package/.claude-plugin/docs/QUICKSTART.md +3 -3
  6. package/.claude-plugin/hooks/hooks.json +19 -1
  7. package/.claude-plugin/marketplace.json +17 -17
  8. package/.claude-plugin/plugin.json +7 -39
  9. package/.claude-plugin/scripts/install.sh +3 -3
  10. package/.claude-plugin/scripts/swarmdo-hook.sh +1 -1
  11. package/.claude-plugin/scripts/verify.sh +2 -2
  12. package/README.md +11 -9
  13. package/package.json +1 -1
  14. package/v3/@swarmdo/cli/.claude/helpers/auto-memory-hook.mjs +70 -33
  15. package/v3/@swarmdo/cli/bin/cli.js +38 -0
  16. package/v3/@swarmdo/cli/dist/src/apply/apply.d.ts +6 -0
  17. package/v3/@swarmdo/cli/dist/src/apply/apply.js +41 -8
  18. package/v3/@swarmdo/cli/dist/src/commands/apply.js +17 -4
  19. package/v3/@swarmdo/cli/dist/src/commands/compact-snapshot.d.ts +17 -0
  20. package/v3/@swarmdo/cli/dist/src/commands/compact-snapshot.js +133 -0
  21. package/v3/@swarmdo/cli/dist/src/commands/index.js +4 -3
  22. package/v3/@swarmdo/cli/dist/src/commands/pack.d.ts +8 -0
  23. package/v3/@swarmdo/cli/dist/src/commands/pack.js +28 -2
  24. package/v3/@swarmdo/cli/dist/src/commands/usage.js +174 -2
  25. package/v3/@swarmdo/cli/dist/src/compact/compact.js +17 -7
  26. package/v3/@swarmdo/cli/dist/src/compact-snapshot/compact-snapshot.d.ts +58 -0
  27. package/v3/@swarmdo/cli/dist/src/compact-snapshot/compact-snapshot.js +104 -0
  28. package/v3/@swarmdo/cli/dist/src/config-lint/lint.js +16 -2
  29. package/v3/@swarmdo/cli/dist/src/init/helpers-generator.js +33 -3
  30. package/v3/@swarmdo/cli/dist/src/redact/redact.js +1 -1
  31. package/v3/@swarmdo/cli/dist/src/sbom/sbom.js +5 -2
  32. package/v3/@swarmdo/cli/dist/src/swarmvector/model-prices.js +12 -2
  33. package/v3/@swarmdo/cli/dist/src/testreport/testreport.js +11 -2
  34. package/v3/@swarmdo/cli/dist/src/transcript/export.d.ts +5 -0
  35. package/v3/@swarmdo/cli/dist/src/transcript/export.js +8 -1
  36. package/v3/@swarmdo/cli/dist/src/usage/claude-pricing.d.ts +6 -2
  37. package/v3/@swarmdo/cli/dist/src/usage/claude-pricing.js +33 -4
  38. package/v3/@swarmdo/cli/dist/src/usage/limits.d.ts +77 -0
  39. package/v3/@swarmdo/cli/dist/src/usage/limits.js +134 -0
  40. package/v3/@swarmdo/cli/dist/src/usage/reflect-html.d.ts +23 -0
  41. package/v3/@swarmdo/cli/dist/src/usage/reflect-html.js +94 -0
  42. package/v3/@swarmdo/cli/dist/src/usage/reflect.d.ts +105 -0
  43. package/v3/@swarmdo/cli/dist/src/usage/reflect.js +165 -0
  44. package/v3/@swarmdo/cli/dist/src/usage/spend-forecast.d.ts +28 -0
  45. package/v3/@swarmdo/cli/dist/src/usage/spend-forecast.js +33 -0
  46. package/v3/@swarmdo/cli/dist/src/usage/transcript-errors.d.ts +14 -0
  47. package/v3/@swarmdo/cli/dist/src/usage/transcript-errors.js +10 -0
  48. package/v3/@swarmdo/cli/dist/src/usage/transcript-usage.js +1 -1
  49. package/v3/@swarmdo/cli/dist/src/util/csv.d.ts +14 -0
  50. package/v3/@swarmdo/cli/dist/src/util/csv.js +20 -0
  51. package/v3/@swarmdo/cli/package.json +2 -2
@@ -0,0 +1,28 @@
1
+ /**
2
+ * spend-forecast.ts — project month-end Claude Code spend from month-to-date
3
+ * burn, for budgeting ("on pace for ~$420 this month").
4
+ *
5
+ * The quota forecaster (limits.ts) answers "will I hit the rolling cap"; this
6
+ * answers "what will the calendar month cost at the current daily average".
7
+ * Pure + deterministic: month-to-date total, the day-of-month, and the days in
8
+ * the month are passed in, so it's unit-tested without a clock.
9
+ */
10
+ export interface SpendProjection {
11
+ monthToDateUsd: number;
12
+ dayOfMonth: number;
13
+ daysInMonth: number;
14
+ /** month-to-date / day-of-month */
15
+ dailyAverageUsd: number;
16
+ /** dailyAverage × daysInMonth — projected month-end total */
17
+ projectedUsd: number;
18
+ /** projectedUsd − monthToDateUsd — the remaining projected spend */
19
+ remainingUsd: number;
20
+ }
21
+ /** Days in the calendar month of an ISO `YYYY-MM` (or `YYYY-MM-DD`). Pure. */
22
+ export declare function daysInMonthOf(iso: string): number;
23
+ /**
24
+ * Project month-end spend at the current daily average. `dayOfMonth` is how many
25
+ * days (inclusive of today) have accrued the month-to-date total. Pure.
26
+ */
27
+ export declare function projectMonthEnd(monthToDateUsd: number, dayOfMonth: number, daysInMonth: number): SpendProjection;
28
+ //# sourceMappingURL=spend-forecast.d.ts.map
@@ -0,0 +1,33 @@
1
+ /**
2
+ * spend-forecast.ts — project month-end Claude Code spend from month-to-date
3
+ * burn, for budgeting ("on pace for ~$420 this month").
4
+ *
5
+ * The quota forecaster (limits.ts) answers "will I hit the rolling cap"; this
6
+ * answers "what will the calendar month cost at the current daily average".
7
+ * Pure + deterministic: month-to-date total, the day-of-month, and the days in
8
+ * the month are passed in, so it's unit-tested without a clock.
9
+ */
10
+ /** Days in the calendar month of an ISO `YYYY-MM` (or `YYYY-MM-DD`). Pure. */
11
+ export function daysInMonthOf(iso) {
12
+ const [y, m] = iso.split('-').map(Number);
13
+ if (!Number.isFinite(y) || !Number.isFinite(m) || m < 1 || m > 12)
14
+ return NaN;
15
+ return new Date(y, m, 0).getDate(); // day 0 of the next month = last day of this one
16
+ }
17
+ /**
18
+ * Project month-end spend at the current daily average. `dayOfMonth` is how many
19
+ * days (inclusive of today) have accrued the month-to-date total. Pure.
20
+ */
21
+ export function projectMonthEnd(monthToDateUsd, dayOfMonth, daysInMonth) {
22
+ const dailyAverageUsd = dayOfMonth > 0 ? monthToDateUsd / dayOfMonth : 0;
23
+ const projectedUsd = dailyAverageUsd * daysInMonth;
24
+ return {
25
+ monthToDateUsd,
26
+ dayOfMonth,
27
+ daysInMonth,
28
+ dailyAverageUsd,
29
+ projectedUsd,
30
+ remainingUsd: Math.max(0, projectedUsd - monthToDateUsd),
31
+ };
32
+ }
33
+ //# sourceMappingURL=spend-forecast.js.map
@@ -31,6 +31,20 @@ export interface ToolErrorReport {
31
31
  filesScanned: number;
32
32
  sessionsWithErrors: number;
33
33
  }
34
+ export interface Delegation {
35
+ /** tool_use calls to the `Task` tool (subagent spawns) */
36
+ taskCalls: number;
37
+ /** all tool_use calls */
38
+ toolCalls: number;
39
+ /** taskCalls / toolCalls, 0..1 (0 when no tool calls) */
40
+ ratio: number;
41
+ }
42
+ /**
43
+ * Delegation ratio: what fraction of tool calls spawned a subagent (the `Task`
44
+ * tool), from an already-collected tool report. The report's parsing/counting
45
+ * is the tested collectToolErrors path — this just extracts the Task share. Pure.
46
+ */
47
+ export declare function delegationFromReport(report: Pick<ToolErrorReport, 'tools' | 'totalCalls'>): Delegation;
34
48
  export interface ParsedLine {
35
49
  type?: string;
36
50
  timestamp?: string;
@@ -12,6 +12,16 @@
12
12
  */
13
13
  import * as fs from 'node:fs';
14
14
  import { defaultClaudeProjectDirs, findTranscriptFiles, normalizeDateBound } from './transcript-usage.js';
15
+ /**
16
+ * Delegation ratio: what fraction of tool calls spawned a subagent (the `Task`
17
+ * tool), from an already-collected tool report. The report's parsing/counting
18
+ * is the tested collectToolErrors path — this just extracts the Task share. Pure.
19
+ */
20
+ export function delegationFromReport(report) {
21
+ const taskCalls = report.tools.find((t) => t.tool === 'Task')?.calls ?? 0;
22
+ const toolCalls = report.totalCalls;
23
+ return { taskCalls, toolCalls, ratio: toolCalls > 0 ? taskCalls / toolCalls : 0 };
24
+ }
15
25
  export function newAccum() {
16
26
  return { idToTool: new Map(), calls: new Map(), errors: new Map(), sigs: new Map(), sessionsWithErrors: new Set() };
17
27
  }
@@ -182,7 +182,7 @@ function toUsageEvent(line, project, seen, unpriced) {
182
182
  const cacheWrite1hTokens = usage.cache_creation?.ephemeral_1h_input_tokens ?? 0;
183
183
  let costUsd;
184
184
  let costSource;
185
- const price = resolveTranscriptPrice(model);
185
+ const price = resolveTranscriptPrice(model, ts.getTime());
186
186
  if (typeof line.costUSD === 'number') {
187
187
  costUsd = line.costUSD;
188
188
  costSource = 'transcript';
@@ -0,0 +1,14 @@
1
+ /**
2
+ * csv.ts — minimal RFC 4180 CSV serialization for exporting tabular command
3
+ * output (e.g. `usage --csv` into a spreadsheet / expense report).
4
+ *
5
+ * Pure and dependency-free. A field is quoted only when it must be — it contains
6
+ * a comma, a double-quote, or a line break — and interior double-quotes are
7
+ * doubled. Rows are joined with '\n' (LF), which every spreadsheet importer
8
+ * accepts.
9
+ */
10
+ /** Quote + escape a single CSV field per RFC 4180 (only when necessary). Pure. */
11
+ export declare function escapeCsvField(value: string | number | boolean | null | undefined): string;
12
+ /** Serialize a header row + data rows to a CSV string. Pure. */
13
+ export declare function toCsv(headers: string[], rows: Array<Array<string | number | boolean | null | undefined>>): string;
14
+ //# sourceMappingURL=csv.d.ts.map
@@ -0,0 +1,20 @@
1
+ /**
2
+ * csv.ts — minimal RFC 4180 CSV serialization for exporting tabular command
3
+ * output (e.g. `usage --csv` into a spreadsheet / expense report).
4
+ *
5
+ * Pure and dependency-free. A field is quoted only when it must be — it contains
6
+ * a comma, a double-quote, or a line break — and interior double-quotes are
7
+ * doubled. Rows are joined with '\n' (LF), which every spreadsheet importer
8
+ * accepts.
9
+ */
10
+ /** Quote + escape a single CSV field per RFC 4180 (only when necessary). Pure. */
11
+ export function escapeCsvField(value) {
12
+ const s = value === null || value === undefined ? '' : String(value);
13
+ return /[",\r\n]/.test(s) ? `"${s.replace(/"/g, '""')}"` : s;
14
+ }
15
+ /** Serialize a header row + data rows to a CSV string. Pure. */
16
+ export function toCsv(headers, rows) {
17
+ const line = (cells) => cells.map(escapeCsvField).join(',');
18
+ return [line(headers), ...rows.map(line)].join('\n');
19
+ }
20
+ //# sourceMappingURL=csv.js.map
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swarmdo/cli",
3
- "version": "1.27.0",
3
+ "version": "1.30.0",
4
4
  "type": "module",
5
5
  "description": "Swarmdo CLI - Enterprise AI agent orchestration with 60+ specialized agents, swarm coordination, MCP server, self-learning hooks, and vector memory for Claude Code",
6
6
  "main": "dist/src/index.js",
@@ -83,7 +83,7 @@
83
83
  "test:pattern-store": "npx tsx src/transfer/store/tests/standalone-test.ts",
84
84
  "postinstall": "node ./scripts/postinstall.cjs",
85
85
  "build:standalone": "node scripts/build-standalone.mjs",
86
- "prepublishOnly": "node -e \"if (process.env.npm_command === 'publish') { console.error('\\n@swarmdo/cli must be published from the self-contained staging dir (file:../ siblings do not ship from here):\\n\\n npm run build && npm run build:standalone && npm publish dist-standalone/\\n'); process.exit(1); } // pnpm runs prepublishOnly when packing local directory deps during install \u2014 that path must not fail\""
86
+ "prepublishOnly": "node -e \"if (process.env.npm_command === 'publish') { console.error('\\n@swarmdo/cli must be published from the self-contained staging dir (file:../ siblings do not ship from here):\\n\\n npm run build && npm run build:standalone && npm publish dist-standalone/\\n'); process.exit(1); } // pnpm runs prepublishOnly when packing local directory deps during install that path must not fail\""
87
87
  },
88
88
  "devDependencies": {
89
89
  "@types/better-sqlite3": "^7.6.0",