@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.
- package/dist/audit/AuditEvent.d.ts +32 -1
- package/dist/audit/AuditEvent.d.ts.map +1 -1
- package/dist/audit/AuditEvent.js +10 -2
- package/dist/audit/AuditEvent.js.map +1 -1
- package/dist/audit/index.d.ts +1 -1
- package/dist/audit/index.d.ts.map +1 -1
- package/dist/audit/service.d.ts +3 -1
- package/dist/audit/service.d.ts.map +1 -1
- package/dist/audit/service.js +2 -1
- package/dist/audit/service.js.map +1 -1
- package/package.json +1 -1
- package/src/audit/AuditEvent.ts +47 -3
- package/src/audit/index.ts +1 -1
- package/src/audit/service.ts +5 -2
|
@@ -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;
|
|
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"}
|
package/dist/audit/AuditEvent.js
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/audit/index.d.ts
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/audit/service.d.ts
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/audit/service.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/audit/service.ts"],"names":[],"mappings":";;;AAAA,
|
|
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
package/src/audit/AuditEvent.ts
CHANGED
|
@@ -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
|
);
|
package/src/audit/index.ts
CHANGED
|
@@ -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';
|
package/src/audit/service.ts
CHANGED
|
@@ -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
|
/**
|