@tumbaland/backend-core 1.39.0 → 1.40.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.
@@ -8,11 +8,40 @@ import type { ActorKind } from './actor';
8
8
  * question or an album question. Every service writes into the same collection,
9
9
  * and `service` says which one.
10
10
  */
11
+ /**
12
+ * What one MCP tool call cost.
13
+ *
14
+ * Kept beside the trail rather than in a metrics system because the question it
15
+ * answers is the same one the trail answers — what did the assistant do — with
16
+ * the part that turned out to matter added: how much text came back. A tool
17
+ * result is not a page a person closes. It stays in the conversation and is
18
+ * resent with every message after it, so a single answer of ten thousand tokens
19
+ * is paid for again on every turn that follows. Nothing in the product made
20
+ * that visible until a bill did.
21
+ */
22
+ export interface ToolCall {
23
+ /** the tool as the model called it — 'get_net_worth', 'log_day' */
24
+ name: string;
25
+ /** how long the handler took, end to end, including the calls it made */
26
+ ms: number;
27
+ /** characters of text handed back to the model */
28
+ chars: number;
29
+ /**
30
+ * Roughly what those characters cost, at four to a token.
31
+ *
32
+ * An estimate on purpose: the real count depends on a tokeniser this server
33
+ * has no reason to carry, and the decision it informs — which tool is the
34
+ * expensive one — is nowhere near close enough for the difference to matter.
35
+ */
36
+ tokens: number;
37
+ /** the call came back as an error, so the size is a message rather than data */
38
+ failed?: boolean;
39
+ }
11
40
  export interface IAuditEvent extends Document {
12
41
  at: Date;
13
42
  /** which service handled it — 'relationship-service', 'album-service' */
14
43
  service: string;
15
- action: 'create' | 'update' | 'delete' | 'read';
44
+ action: 'create' | 'update' | 'delete' | 'read' | 'call';
16
45
  /** what kind of thing — 'activity', 'activity_type', 'photo' */
17
46
  resource: string;
18
47
  resourceId?: string;
@@ -39,6 +68,8 @@ export interface IAuditEvent extends Document {
39
68
  snapshot?: Record<string, unknown>;
40
69
  /** how many records a read returned — the size of what left the server */
41
70
  count?: number;
71
+ /** present on 'call': the tool, and what it cost */
72
+ tool?: ToolCall;
42
73
  createdAt: Date;
43
74
  }
44
75
  export declare const AuditEvent: mongoose.Model<IAuditEvent, {}, {}, {}, mongoose.Document<unknown, {}, IAuditEvent, {}, mongoose.DefaultSchemaOptions> & IAuditEvent & Required<{
@@ -1 +1 @@
1
- {"version":3,"file":"AuditEvent.d.ts","sourceRoot":"","sources":["../../src/audit/AuditEvent.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,EAAE,EAAE,QAAQ,EAAU,MAAM,UAAU,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC;;;;;;;GAOG;AACH,MAAM,WAAW,WAAY,SAAQ,QAAQ;IAC3C,EAAE,EAAE,IAAI,CAAC;IACT,yEAAyE;IACzE,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;IAChD,gEAAgE;IAChE,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,SAAS,CAAC;IACrB,6DAA6D;IAC7D,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,4EAA4E;IAC5E,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,EAAE,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACzD,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,0EAA0E;IAC1E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,IAAI,CAAC;CACjB;AAoCD,eAAO,MAAM,UAAU;;;;;;oBAEwC,CAAC"}
1
+ {"version":3,"file":"AuditEvent.d.ts","sourceRoot":"","sources":["../../src/audit/AuditEvent.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,EAAE,EAAE,QAAQ,EAAU,MAAM,UAAU,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC;;;;;;;GAOG;AACH;;;;;;;;;;GAUG;AACH,MAAM,WAAW,QAAQ;IACvB,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;IACb,yEAAyE;IACzE,EAAE,EAAE,MAAM,CAAC;IACX,kDAAkD;IAClD,KAAK,EAAE,MAAM,CAAC;IACd;;;;;;OAMG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,gFAAgF;IAChF,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,WAAY,SAAQ,QAAQ;IAC3C,EAAE,EAAE,IAAI,CAAC;IACT,yEAAyE;IACzE,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;IACzD,gEAAgE;IAChE,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,SAAS,CAAC;IACrB,6DAA6D;IAC7D,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,4EAA4E;IAC5E,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,EAAE,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACzD,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,0EAA0E;IAC1E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB;AAgDD,eAAO,MAAM,UAAU;;;;;;oBAEwC,CAAC"}
@@ -35,10 +35,17 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.AuditEvent = void 0;
37
37
  const mongoose_1 = __importStar(require("mongoose"));
38
+ const ToolCallSchema = new mongoose_1.Schema({
39
+ name: { type: String, required: true },
40
+ ms: { type: Number, required: true },
41
+ chars: { type: Number, required: true },
42
+ tokens: { type: Number, required: true },
43
+ failed: { type: Boolean }
44
+ }, { _id: false });
38
45
  const AuditEventSchema = new mongoose_1.Schema({
39
46
  at: { type: Date, required: true, default: Date.now },
40
47
  service: { type: String, required: true },
41
- action: { type: String, required: true, enum: ['create', 'update', 'delete', 'read'] },
48
+ action: { type: String, required: true, enum: ['create', 'update', 'delete', 'read', 'call'] },
42
49
  resource: { type: String, required: true },
43
50
  resourceId: { type: String },
44
51
  actorKind: { type: String, required: true, enum: ['person', 'key', 'assistant'] },
@@ -48,7 +55,8 @@ const AuditEventSchema = new mongoose_1.Schema({
48
55
  tenant: { type: String, required: true },
49
56
  changes: { type: mongoose_1.Schema.Types.Mixed },
50
57
  snapshot: { type: mongoose_1.Schema.Types.Mixed },
51
- count: { type: Number }
58
+ count: { type: Number },
59
+ tool: { type: ToolCallSchema }
52
60
  }, { timestamps: { createdAt: true, updatedAt: false }, collection: 'audit_events' });
53
61
  // Every listing is one account's trail, newest first.
54
62
  AuditEventSchema.index({ userId: 1, at: -1 });
@@ -1 +1 @@
1
- {"version":3,"file":"AuditEvent.js","sourceRoot":"","sources":["../../src/audit/AuditEvent.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,qDAAsD;AA0CtD,MAAM,gBAAgB,GAAG,IAAI,iBAAM,CACjC;IACE,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE;IACrD,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;IACzC,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE;IACtF,QAAQ,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;IAC1C,UAAU,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;IAC5B,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,WAAW,CAAC,EAAE;IACjF,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;IACrD,UAAU,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;IAC5C,iBAAiB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;IACnC,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;IACxC,OAAO,EAAE,EAAE,IAAI,EAAE,iBAAM,CAAC,KAAK,CAAC,KAAK,EAAE;IACrC,QAAQ,EAAE,EAAE,IAAI,EAAE,iBAAM,CAAC,KAAK,CAAC,KAAK,EAAE;IACtC,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;CACxB,EACD,EAAE,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,cAAc,EAAE,CAClF,CAAC;AAEF,sDAAsD;AACtD,gBAAgB,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;AAE9C;;;;;;;;GAQG;AACH,MAAM,cAAc,GAAG,GAAG,CAAC;AAC3B,gBAAgB,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,kBAAkB,EAAE,cAAc,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;AAE5E,QAAA,UAAU,GAAG,kBAAQ,CAAC,MAAM,CAAC,UAAU;IAClD,CAAC,CAAE,kBAAQ,CAAC,MAAM,CAAC,UAA0C;IAC7D,CAAC,CAAC,kBAAQ,CAAC,KAAK,CAAc,YAAY,EAAE,gBAAgB,CAAC,CAAC"}
1
+ {"version":3,"file":"AuditEvent.js","sourceRoot":"","sources":["../../src/audit/AuditEvent.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,qDAAsD;AA0EtD,MAAM,cAAc,GAAG,IAAI,iBAAM,CAC/B;IACE,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;IACtC,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;IACpC,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;IACvC,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;IACxC,MAAM,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;CAC1B,EACD,EAAE,GAAG,EAAE,KAAK,EAAE,CACf,CAAC;AAEF,MAAM,gBAAgB,GAAG,IAAI,iBAAM,CACjC;IACE,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE;IACrD,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;IACzC,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE;IAC9F,QAAQ,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;IAC1C,UAAU,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;IAC5B,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,WAAW,CAAC,EAAE;IACjF,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;IACrD,UAAU,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;IAC5C,iBAAiB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;IACnC,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;IACxC,OAAO,EAAE,EAAE,IAAI,EAAE,iBAAM,CAAC,KAAK,CAAC,KAAK,EAAE;IACrC,QAAQ,EAAE,EAAE,IAAI,EAAE,iBAAM,CAAC,KAAK,CAAC,KAAK,EAAE;IACtC,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;IACvB,IAAI,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE;CAC/B,EACD,EAAE,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,cAAc,EAAE,CAClF,CAAC;AAEF,sDAAsD;AACtD,gBAAgB,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;AAE9C;;;;;;;;GAQG;AACH,MAAM,cAAc,GAAG,GAAG,CAAC;AAC3B,gBAAgB,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,kBAAkB,EAAE,cAAc,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;AAE5E,QAAA,UAAU,GAAG,kBAAQ,CAAC,MAAM,CAAC,UAAU;IAClD,CAAC,CAAE,kBAAQ,CAAC,MAAM,CAAC,UAA0C;IAC7D,CAAC,CAAC,kBAAQ,CAAC,KAAK,CAAc,YAAY,EAAE,gBAAgB,CAAC,CAAC"}
@@ -1,7 +1,7 @@
1
1
  export { actorOf, describeActor } from './actor';
2
2
  export type { Actor, ActorKind } from './actor';
3
3
  export { AuditEvent } from './AuditEvent';
4
- export type { IAuditEvent } from './AuditEvent';
4
+ export type { IAuditEvent, ToolCall } from './AuditEvent';
5
5
  export { auditContext, beginAudit, currentAuditContext, withAuditContext } from './context';
6
6
  export type { AuditContext } from './context';
7
7
  export { auditPlugin } from './plugin';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/audit/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACjD,YAAY,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC5F,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,YAAY,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/audit/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACjD,YAAY,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC5F,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,YAAY,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC"}
@@ -1,4 +1,4 @@
1
- import { type IAuditEvent } from './AuditEvent';
1
+ import { type IAuditEvent, type ToolCall } from './AuditEvent';
2
2
  import type { ActorKind } from './actor';
3
3
  export interface AuditQuery {
4
4
  userId: string;
@@ -31,6 +31,8 @@ export interface AuditEntry {
31
31
  }>;
32
32
  snapshot?: Record<string, unknown>;
33
33
  count?: number;
34
+ /** present on 'call': which tool ran, how long it took, and what it cost */
35
+ tool?: ToolCall;
34
36
  }
35
37
  /**
36
38
  * One account's trail, newest first.
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/audit/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,MAAM,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,EAAE,CAAC,EAAE,IAAI,CAAC;IACV,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,EAAE,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACzD,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAkBD;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,GAC1B,OAAO,UAAU,KAChB,OAAO,CAAC;IAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CA+BnF,CAAC"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/audit/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,WAAW,EAAE,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC3E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,MAAM,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,EAAE,CAAC,EAAE,IAAI,CAAC;IACV,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,EAAE,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACzD,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,IAAI,CAAC,EAAE,QAAQ,CAAC;CACjB;AAmBD;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,GAC1B,OAAO,UAAU,KAChB,OAAO,CAAC;IAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CA+BnF,CAAC"}
@@ -15,7 +15,8 @@ const toEntry = (event) => ({
15
15
  tenant: event.tenant,
16
16
  changes: event.changes,
17
17
  snapshot: event.snapshot,
18
- count: event.count
18
+ count: event.count,
19
+ tool: event.tool
19
20
  });
20
21
  /**
21
22
  * One account's trail, newest first.
@@ -1 +1 @@
1
- {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/audit/service.ts"],"names":[],"mappings":";;;AAAA,6CAA4D;AAkC5D,MAAM,OAAO,GAAG,CAAC,KAAkB,EAAc,EAAE,CAAC,CAAC;IACnD,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC;IACrB,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,EAAE;IAC1B,OAAO,EAAE,KAAK,CAAC,OAAO;IACtB,MAAM,EAAE,KAAK,CAAC,MAAM;IACpB,QAAQ,EAAE,KAAK,CAAC,QAAQ;IACxB,UAAU,EAAE,KAAK,CAAC,UAAU;IAC5B,SAAS,EAAE,KAAK,CAAC,SAAS;IAC1B,UAAU,EAAE,KAAK,CAAC,UAAU;IAC5B,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;IAC1C,MAAM,EAAE,KAAK,CAAC,MAAM;IACpB,OAAO,EAAE,KAAK,CAAC,OAAO;IACtB,QAAQ,EAAE,KAAK,CAAC,QAAQ;IACxB,KAAK,EAAE,KAAK,CAAC,KAAK;CACnB,CAAC,CAAC;AAEH;;;;;;;GAOG;AACI,MAAM,eAAe,GAAG,KAAK,EAClC,KAAiB,EACmE,EAAE;IACtF,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC;IAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IAE1C,MAAM,MAAM,GAA4B,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;IACjE,IAAI,KAAK,CAAC,YAAY;QAAE,MAAM,CAAC,iBAAiB,GAAG,KAAK,CAAC,YAAY,CAAC;IACtE,IAAI,KAAK,CAAC,SAAS;QAAE,MAAM,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC;IACxD,IAAI,KAAK,CAAC,MAAM;QAAE,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAC/C,IAAI,KAAK,CAAC,QAAQ;QAAE,MAAM,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;IACrD,IAAI,KAAK,CAAC,OAAO;QAAE,MAAM,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAClD,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,EAAE,EAAE,CAAC;QAC3B,MAAM,EAAE,GAAyB,EAAE,CAAC;QACpC,IAAI,KAAK,CAAC,IAAI;YAAE,EAAE,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QACrC,IAAI,KAAK,CAAC,EAAE;YAAE,EAAE,CAAC,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC;QACjC,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC;IACjB,CAAC;IAED,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACxC,uBAAU,CAAC,IAAI,CAAC,MAAM,CAAC;aACpB,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC;aAChB,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;aACxB,KAAK,CAAC,KAAK,CAAC;QACf,uBAAU,CAAC,cAAc,CAAC,MAAM,CAAC;KAClC,CAAC,CAAC;IAEH,OAAO;QACL,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC;QAC3B,KAAK;QACL,IAAI;QACJ,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;KACrC,CAAC;AACJ,CAAC,CAAC;AAjCW,QAAA,eAAe,mBAiC1B"}
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/audit/service.ts"],"names":[],"mappings":";;;AAAA,6CAA2E;AAoC3E,MAAM,OAAO,GAAG,CAAC,KAAkB,EAAc,EAAE,CAAC,CAAC;IACnD,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC;IACrB,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,EAAE;IAC1B,OAAO,EAAE,KAAK,CAAC,OAAO;IACtB,MAAM,EAAE,KAAK,CAAC,MAAM;IACpB,QAAQ,EAAE,KAAK,CAAC,QAAQ;IACxB,UAAU,EAAE,KAAK,CAAC,UAAU;IAC5B,SAAS,EAAE,KAAK,CAAC,SAAS;IAC1B,UAAU,EAAE,KAAK,CAAC,UAAU;IAC5B,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;IAC1C,MAAM,EAAE,KAAK,CAAC,MAAM;IACpB,OAAO,EAAE,KAAK,CAAC,OAAO;IACtB,QAAQ,EAAE,KAAK,CAAC,QAAQ;IACxB,KAAK,EAAE,KAAK,CAAC,KAAK;IAClB,IAAI,EAAE,KAAK,CAAC,IAAI;CACjB,CAAC,CAAC;AAEH;;;;;;;GAOG;AACI,MAAM,eAAe,GAAG,KAAK,EAClC,KAAiB,EACmE,EAAE;IACtF,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC;IAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IAE1C,MAAM,MAAM,GAA4B,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;IACjE,IAAI,KAAK,CAAC,YAAY;QAAE,MAAM,CAAC,iBAAiB,GAAG,KAAK,CAAC,YAAY,CAAC;IACtE,IAAI,KAAK,CAAC,SAAS;QAAE,MAAM,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC;IACxD,IAAI,KAAK,CAAC,MAAM;QAAE,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAC/C,IAAI,KAAK,CAAC,QAAQ;QAAE,MAAM,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;IACrD,IAAI,KAAK,CAAC,OAAO;QAAE,MAAM,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAClD,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,EAAE,EAAE,CAAC;QAC3B,MAAM,EAAE,GAAyB,EAAE,CAAC;QACpC,IAAI,KAAK,CAAC,IAAI;YAAE,EAAE,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QACrC,IAAI,KAAK,CAAC,EAAE;YAAE,EAAE,CAAC,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC;QACjC,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC;IACjB,CAAC;IAED,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACxC,uBAAU,CAAC,IAAI,CAAC,MAAM,CAAC;aACpB,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC;aAChB,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;aACxB,KAAK,CAAC,KAAK,CAAC;QACf,uBAAU,CAAC,cAAc,CAAC,MAAM,CAAC;KAClC,CAAC,CAAC;IAEH,OAAO;QACL,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC;QAC3B,KAAK;QACL,IAAI;QACJ,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;KACrC,CAAC;AACJ,CAAC,CAAC;AAjCW,QAAA,eAAe,mBAiC1B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tumbaland/backend-core",
3
- "version": "1.39.0",
3
+ "version": "1.40.0",
4
4
  "description": "Core shared functionality for Tumbaland backend services",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -9,11 +9,41 @@ import type { ActorKind } from './actor';
9
9
  * question or an album question. Every service writes into the same collection,
10
10
  * and `service` says which one.
11
11
  */
12
+ /**
13
+ * What one MCP tool call cost.
14
+ *
15
+ * Kept beside the trail rather than in a metrics system because the question it
16
+ * answers is the same one the trail answers — what did the assistant do — with
17
+ * the part that turned out to matter added: how much text came back. A tool
18
+ * result is not a page a person closes. It stays in the conversation and is
19
+ * resent with every message after it, so a single answer of ten thousand tokens
20
+ * is paid for again on every turn that follows. Nothing in the product made
21
+ * that visible until a bill did.
22
+ */
23
+ export interface ToolCall {
24
+ /** the tool as the model called it — 'get_net_worth', 'log_day' */
25
+ name: string;
26
+ /** how long the handler took, end to end, including the calls it made */
27
+ ms: number;
28
+ /** characters of text handed back to the model */
29
+ chars: number;
30
+ /**
31
+ * Roughly what those characters cost, at four to a token.
32
+ *
33
+ * An estimate on purpose: the real count depends on a tokeniser this server
34
+ * has no reason to carry, and the decision it informs — which tool is the
35
+ * expensive one — is nowhere near close enough for the difference to matter.
36
+ */
37
+ tokens: number;
38
+ /** the call came back as an error, so the size is a message rather than data */
39
+ failed?: boolean;
40
+ }
41
+
12
42
  export interface IAuditEvent extends Document {
13
43
  at: Date;
14
44
  /** which service handled it — 'relationship-service', 'album-service' */
15
45
  service: string;
16
- action: 'create' | 'update' | 'delete' | 'read';
46
+ action: 'create' | 'update' | 'delete' | 'read' | 'call';
17
47
  /** what kind of thing — 'activity', 'activity_type', 'photo' */
18
48
  resource: string;
19
49
  resourceId?: string;
@@ -37,14 +67,27 @@ export interface IAuditEvent extends Document {
37
67
  snapshot?: Record<string, unknown>;
38
68
  /** how many records a read returned — the size of what left the server */
39
69
  count?: number;
70
+ /** present on 'call': the tool, and what it cost */
71
+ tool?: ToolCall;
40
72
  createdAt: Date;
41
73
  }
42
74
 
75
+ const ToolCallSchema = new Schema<ToolCall>(
76
+ {
77
+ name: { type: String, required: true },
78
+ ms: { type: Number, required: true },
79
+ chars: { type: Number, required: true },
80
+ tokens: { type: Number, required: true },
81
+ failed: { type: Boolean }
82
+ },
83
+ { _id: false }
84
+ );
85
+
43
86
  const AuditEventSchema = new Schema<IAuditEvent>(
44
87
  {
45
88
  at: { type: Date, required: true, default: Date.now },
46
89
  service: { type: String, required: true },
47
- action: { type: String, required: true, enum: ['create', 'update', 'delete', 'read'] },
90
+ action: { type: String, required: true, enum: ['create', 'update', 'delete', 'read', 'call'] },
48
91
  resource: { type: String, required: true },
49
92
  resourceId: { type: String },
50
93
  actorKind: { type: String, required: true, enum: ['person', 'key', 'assistant'] },
@@ -54,7 +97,8 @@ const AuditEventSchema = new Schema<IAuditEvent>(
54
97
  tenant: { type: String, required: true },
55
98
  changes: { type: Schema.Types.Mixed },
56
99
  snapshot: { type: Schema.Types.Mixed },
57
- count: { type: Number }
100
+ count: { type: Number },
101
+ tool: { type: ToolCallSchema }
58
102
  },
59
103
  { timestamps: { createdAt: true, updatedAt: false }, collection: 'audit_events' }
60
104
  );
@@ -1,7 +1,7 @@
1
1
  export { actorOf, describeActor } from './actor';
2
2
  export type { Actor, ActorKind } from './actor';
3
3
  export { AuditEvent } from './AuditEvent';
4
- export type { IAuditEvent } from './AuditEvent';
4
+ export type { IAuditEvent, ToolCall } from './AuditEvent';
5
5
  export { auditContext, beginAudit, currentAuditContext, withAuditContext } from './context';
6
6
  export type { AuditContext } from './context';
7
7
  export { auditPlugin } from './plugin';
@@ -1,4 +1,4 @@
1
- import { AuditEvent, type IAuditEvent } from './AuditEvent';
1
+ import { AuditEvent, type IAuditEvent, type ToolCall } from './AuditEvent';
2
2
  import type { ActorKind } from './actor';
3
3
 
4
4
  export interface AuditQuery {
@@ -30,6 +30,8 @@ export interface AuditEntry {
30
30
  changes?: Record<string, { from: unknown; to: unknown }>;
31
31
  snapshot?: Record<string, unknown>;
32
32
  count?: number;
33
+ /** present on 'call': which tool ran, how long it took, and what it cost */
34
+ tool?: ToolCall;
33
35
  }
34
36
 
35
37
  const toEntry = (event: IAuditEvent): AuditEntry => ({
@@ -45,7 +47,8 @@ const toEntry = (event: IAuditEvent): AuditEntry => ({
45
47
  tenant: event.tenant,
46
48
  changes: event.changes,
47
49
  snapshot: event.snapshot,
48
- count: event.count
50
+ count: event.count,
51
+ tool: event.tool
49
52
  });
50
53
 
51
54
  /**