@mongrov/analytics 0.1.0-alpha.8 → 0.1.0-beta.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 (97) hide show
  1. package/README.md +47 -11
  2. package/dist/core/factory.d.ts.map +1 -1
  3. package/dist/core/factory.js +26 -0
  4. package/dist/core/factory.js.map +1 -1
  5. package/dist/core/schemas.js +18 -18
  6. package/dist/core/warehouse.d.ts.map +1 -1
  7. package/dist/core/warehouse.js +13 -1
  8. package/dist/core/warehouse.js.map +1 -1
  9. package/dist/tools/__fakes__/engine.d.ts +25 -0
  10. package/dist/tools/__fakes__/engine.d.ts.map +1 -0
  11. package/dist/tools/__fakes__/engine.js +37 -0
  12. package/dist/tools/__fakes__/engine.js.map +1 -0
  13. package/dist/tools/audit.d.ts +31 -0
  14. package/dist/tools/audit.d.ts.map +1 -0
  15. package/dist/tools/audit.js +157 -0
  16. package/dist/tools/audit.js.map +1 -0
  17. package/dist/tools/authorize.d.ts +36 -0
  18. package/dist/tools/authorize.d.ts.map +1 -0
  19. package/dist/tools/authorize.js +87 -0
  20. package/dist/tools/authorize.js.map +1 -0
  21. package/dist/tools/budget.d.ts +15 -0
  22. package/dist/tools/budget.d.ts.map +1 -0
  23. package/dist/tools/budget.js +64 -0
  24. package/dist/tools/budget.js.map +1 -0
  25. package/dist/tools/factory.d.ts +43 -0
  26. package/dist/tools/factory.d.ts.map +1 -0
  27. package/dist/tools/factory.js +137 -0
  28. package/dist/tools/factory.js.map +1 -0
  29. package/dist/tools/formatters.d.ts +17 -0
  30. package/dist/tools/formatters.d.ts.map +1 -0
  31. package/dist/tools/formatters.js +30 -0
  32. package/dist/tools/formatters.js.map +1 -0
  33. package/dist/tools/impls/activity.d.ts +15 -0
  34. package/dist/tools/impls/activity.d.ts.map +1 -0
  35. package/dist/tools/impls/activity.js +61 -0
  36. package/dist/tools/impls/activity.js.map +1 -0
  37. package/dist/tools/impls/anomaly.d.ts +21 -0
  38. package/dist/tools/impls/anomaly.d.ts.map +1 -0
  39. package/dist/tools/impls/anomaly.js +70 -0
  40. package/dist/tools/impls/anomaly.js.map +1 -0
  41. package/dist/tools/impls/compare.d.ts +21 -0
  42. package/dist/tools/impls/compare.d.ts.map +1 -0
  43. package/dist/tools/impls/compare.js +68 -0
  44. package/dist/tools/impls/compare.js.map +1 -0
  45. package/dist/tools/impls/hrv.d.ts +15 -0
  46. package/dist/tools/impls/hrv.d.ts.map +1 -0
  47. package/dist/tools/impls/hrv.js +36 -0
  48. package/dist/tools/impls/hrv.js.map +1 -0
  49. package/dist/tools/impls/insights.d.ts +18 -0
  50. package/dist/tools/impls/insights.d.ts.map +1 -0
  51. package/dist/tools/impls/insights.js +41 -0
  52. package/dist/tools/impls/insights.js.map +1 -0
  53. package/dist/tools/impls/sleep.d.ts +15 -0
  54. package/dist/tools/impls/sleep.d.ts.map +1 -0
  55. package/dist/tools/impls/sleep.js +43 -0
  56. package/dist/tools/impls/sleep.js.map +1 -0
  57. package/dist/tools/index.d.ts +13 -1
  58. package/dist/tools/index.d.ts.map +1 -1
  59. package/dist/tools/index.js +21 -1
  60. package/dist/tools/index.js.map +1 -1
  61. package/dist/tools/mcp/adapter.d.ts +33 -0
  62. package/dist/tools/mcp/adapter.d.ts.map +1 -0
  63. package/dist/tools/mcp/adapter.js +56 -0
  64. package/dist/tools/mcp/adapter.js.map +1 -0
  65. package/dist/tools/mcp/guard.d.ts +17 -0
  66. package/dist/tools/mcp/guard.d.ts.map +1 -0
  67. package/dist/tools/mcp/guard.js +22 -0
  68. package/dist/tools/mcp/guard.js.map +1 -0
  69. package/dist/tools/mcp/index.d.ts +20 -0
  70. package/dist/tools/mcp/index.d.ts.map +1 -0
  71. package/dist/tools/mcp/index.js +16 -0
  72. package/dist/tools/mcp/index.js.map +1 -0
  73. package/dist/tools/mcp/server.d.ts +39 -0
  74. package/dist/tools/mcp/server.d.ts.map +1 -0
  75. package/dist/tools/mcp/server.js +70 -0
  76. package/dist/tools/mcp/server.js.map +1 -0
  77. package/dist/tools/mcp/transports/http.d.ts +54 -0
  78. package/dist/tools/mcp/transports/http.d.ts.map +1 -0
  79. package/dist/tools/mcp/transports/http.js +133 -0
  80. package/dist/tools/mcp/transports/http.js.map +1 -0
  81. package/dist/tools/mcp/transports/stdio.d.ts +22 -0
  82. package/dist/tools/mcp/transports/stdio.d.ts.map +1 -0
  83. package/dist/tools/mcp/transports/stdio.js +19 -0
  84. package/dist/tools/mcp/transports/stdio.js.map +1 -0
  85. package/dist/tools/rate-limit.d.ts +26 -0
  86. package/dist/tools/rate-limit.d.ts.map +1 -0
  87. package/dist/tools/rate-limit.js +67 -0
  88. package/dist/tools/rate-limit.js.map +1 -0
  89. package/dist/tools/types.d.ts +121 -0
  90. package/dist/tools/types.d.ts.map +1 -0
  91. package/dist/tools/types.js +16 -0
  92. package/dist/tools/types.js.map +1 -0
  93. package/dist/tools/wrap.d.ts +53 -0
  94. package/dist/tools/wrap.d.ts.map +1 -0
  95. package/dist/tools/wrap.js +135 -0
  96. package/dist/tools/wrap.js.map +1 -0
  97. package/package.json +21 -4
@@ -0,0 +1,135 @@
1
+ /**
2
+ * `makeTool` — compose an AI SDK `tool()` from a raw impl plus the
3
+ * rate → auth → execute → budget → audit chain.
4
+ *
5
+ * The chain order is load-bearing:
6
+ * 1. Rate limit → cheap, no I/O; short-circuits abusive callers.
7
+ * 2. Authorize → may hit SQL/provider; runs after rate cap.
8
+ * 3. Execute → real tool work.
9
+ * 4. Budget → truncate oversized text before returning.
10
+ * 5. Audit → record every terminal state (success / reject
11
+ * / rate-limited / error).
12
+ *
13
+ * Every branch records exactly one audit entry. The wrapper never
14
+ * throws — errors resolve to a short LLM-friendly string. Because
15
+ * the AI SDK `execute(input)` signature has no per-call context arg,
16
+ * the caller supplies a `ctxProvider()` closure that returns the
17
+ * current `ToolContext` at invocation time (the factory backs this
18
+ * with a mutable container updated per request).
19
+ */
20
+ import { tool } from 'ai';
21
+ import { applyOutputBudget } from './budget';
22
+ const RATE_LIMIT_MESSAGE = 'Rate limit exceeded. Try again shortly.';
23
+ const AUTHZ_MESSAGE = 'Not authorized to access that user\'s data.';
24
+ const ERROR_MESSAGE = 'Tool call failed.';
25
+ const NO_CONTEXT_MESSAGE = 'Tool call failed: request context not set.';
26
+ export function makeTool(cfg) {
27
+ const clock = cfg.clock ?? Date.now;
28
+ return tool({
29
+ description: cfg.description,
30
+ parameters: cfg.inputSchema,
31
+ execute: async (input) => {
32
+ const startMs = clock();
33
+ const ctx = cfg.ctxProvider();
34
+ // 0. Ctx guard — audit as error, no rate/auth/execute performed.
35
+ if (!ctx) {
36
+ cfg.audit.record({
37
+ ts: new Date(clock()),
38
+ brand: '',
39
+ familyId: '',
40
+ requesterUserId: '',
41
+ toolName: cfg.name,
42
+ args: input,
43
+ resultBytes: null,
44
+ resultRowCount: null,
45
+ latencyMs: clock() - startMs,
46
+ outcome: 'error',
47
+ errorMessage: 'context not set',
48
+ });
49
+ cfg.logger?.warn('tool invoked without context', { toolName: cfg.name });
50
+ return NO_CONTEXT_MESSAGE;
51
+ }
52
+ // 1. Rate limit.
53
+ if (cfg.rateLimiter && !cfg.rateLimiter.check(cfg.name, ctx.requesterUserId)) {
54
+ cfg.audit.record({
55
+ ts: new Date(clock()),
56
+ brand: ctx.brand,
57
+ familyId: ctx.familyId,
58
+ requesterUserId: ctx.requesterUserId,
59
+ toolName: cfg.name,
60
+ args: input,
61
+ resultBytes: null,
62
+ resultRowCount: null,
63
+ latencyMs: clock() - startMs,
64
+ outcome: 'rate_limited',
65
+ errorMessage: null,
66
+ });
67
+ return RATE_LIMIT_MESSAGE;
68
+ }
69
+ // 2. Authorize.
70
+ if (cfg.authorize) {
71
+ const ok = await cfg.authorize(cfg.name, input, ctx);
72
+ if (!ok) {
73
+ cfg.audit.record({
74
+ ts: new Date(clock()),
75
+ brand: ctx.brand,
76
+ familyId: ctx.familyId,
77
+ requesterUserId: ctx.requesterUserId,
78
+ toolName: cfg.name,
79
+ args: input,
80
+ resultBytes: null,
81
+ resultRowCount: null,
82
+ latencyMs: clock() - startMs,
83
+ outcome: 'authorized_reject',
84
+ errorMessage: null,
85
+ });
86
+ return AUTHZ_MESSAGE;
87
+ }
88
+ }
89
+ // 3. Execute + 4. Budget + 5. Audit success/error.
90
+ try {
91
+ const raw = await cfg.impl(input, {
92
+ ...ctx,
93
+ analytics: cfg.analytics,
94
+ });
95
+ const capped = applyOutputBudget(raw, cfg.budget);
96
+ cfg.audit.record({
97
+ ts: new Date(clock()),
98
+ brand: ctx.brand,
99
+ familyId: ctx.familyId,
100
+ requesterUserId: ctx.requesterUserId,
101
+ toolName: cfg.name,
102
+ args: input,
103
+ resultBytes: capped.bytes,
104
+ resultRowCount: capped.rowCount,
105
+ latencyMs: clock() - startMs,
106
+ outcome: 'success',
107
+ errorMessage: null,
108
+ });
109
+ return capped.text;
110
+ }
111
+ catch (err) {
112
+ const errorMessage = err instanceof Error ? err.message : String(err);
113
+ cfg.audit.record({
114
+ ts: new Date(clock()),
115
+ brand: ctx.brand,
116
+ familyId: ctx.familyId,
117
+ requesterUserId: ctx.requesterUserId,
118
+ toolName: cfg.name,
119
+ args: input,
120
+ resultBytes: null,
121
+ resultRowCount: null,
122
+ latencyMs: clock() - startMs,
123
+ outcome: 'error',
124
+ errorMessage,
125
+ });
126
+ cfg.logger?.warn('tool execution failed', {
127
+ toolName: cfg.name,
128
+ err: errorMessage,
129
+ });
130
+ return ERROR_MESSAGE;
131
+ }
132
+ },
133
+ });
134
+ }
135
+ //# sourceMappingURL=wrap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wrap.js","sourceRoot":"","sources":["../../src/tools/wrap.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@mongrov/analytics",
3
- "version": "0.1.0-alpha.8",
3
+ "version": "0.1.0-beta.0",
4
+ "sideEffects": false,
4
5
  "description": "DuckDB + R2 Iceberg local analytics for @mongrov apps",
5
6
  "license": "MIT",
6
7
  "repository": {
@@ -38,6 +39,11 @@
38
39
  "import": "./dist/tools/index.js",
39
40
  "default": "./dist/tools/index.js"
40
41
  },
42
+ "./tools/mcp": {
43
+ "types": "./dist/tools/mcp/index.d.ts",
44
+ "import": "./dist/tools/mcp/index.js",
45
+ "default": "./dist/tools/mcp/index.js"
46
+ },
41
47
  "./sync": {
42
48
  "types": "./dist/sync/index.d.ts",
43
49
  "import": "./dist/sync/index.js",
@@ -53,13 +59,18 @@
53
59
  "dist"
54
60
  ],
55
61
  "peerDependencies": {
62
+ "@modelcontextprotocol/sdk": ">=1.20.0",
56
63
  "@mongrov/types": "^0.4.0",
64
+ "ai": ">=4",
57
65
  "react": ">=19",
58
66
  "react-native": ">=0.81",
59
67
  "react-native-duckdb": ">=1.0.0",
60
68
  "@mongrov/db": "0.3.0"
61
69
  },
62
70
  "peerDependenciesMeta": {
71
+ "@modelcontextprotocol/sdk": {
72
+ "optional": true
73
+ },
63
74
  "react": {
64
75
  "optional": true
65
76
  },
@@ -74,12 +85,17 @@
74
85
  "@iarna/toml": "^2.2.5",
75
86
  "date-fns-tz": "^3.2.0",
76
87
  "p-queue": "^8.0.1",
77
- "xstate": "^5.30.0"
88
+ "xstate": "^5.30.0",
89
+ "zod-to-json-schema": "^3.25.2"
78
90
  },
79
91
  "devDependencies": {
92
+ "@duckdb/node-api": "1.5.4-r.1",
93
+ "@duckdb/node-bindings": "1.5.4-r.1",
94
+ "@modelcontextprotocol/sdk": "^1.29.0",
80
95
  "@testing-library/react": "^14.3.1",
81
96
  "@types/react": "^18.3.12",
82
97
  "@types/react-dom": "^18.3.1",
98
+ "ai": "^4.3.0",
83
99
  "fast-check": "^4.9.0",
84
100
  "jsdom": "^25.0.1",
85
101
  "react": "^18.3.1",
@@ -87,8 +103,8 @@
87
103
  "typescript": "^5.9.3",
88
104
  "vitest": "^2.1.9",
89
105
  "zod": "^3.23.8",
90
- "@mongrov/db": "0.3.0",
91
- "@mongrov/types": "0.4.0"
106
+ "@mongrov/types": "0.4.0",
107
+ "@mongrov/db": "0.3.0"
92
108
  },
93
109
  "scripts": {
94
110
  "build": "tsc -p tsconfig.build.json",
@@ -96,6 +112,7 @@
96
112
  "prebuild": "pnpm run clean",
97
113
  "test": "vitest run",
98
114
  "test:watch": "vitest",
115
+ "test:integration": "vitest run --config vitest.integration.config.ts",
99
116
  "typecheck": "tsc --noEmit"
100
117
  }
101
118
  }