@company-semantics/contracts 0.88.0 → 0.90.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/package.json +1 -1
- package/src/execution/__tests__/lifecycle.test.ts +33 -35
- package/src/execution/errors.ts +4 -9
- package/src/execution/index.ts +1 -2
- package/src/execution/lifecycle.ts +15 -1
- package/src/index.ts +11 -4
- package/src/mcp/index.ts +4 -4
- package/src/usage/types.ts +64 -0
package/package.json
CHANGED
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
} from '../status.js'
|
|
9
9
|
import { LIFECYCLE_DECISIONS, applyIntent } from '../lifecycle.js'
|
|
10
10
|
import type { ExecutionErrorCode } from '../errors.js'
|
|
11
|
-
import { ExecutionError } from '../errors.js'
|
|
12
11
|
import { parseExpiresAt, isConfirmationExpired } from '../expiry.js'
|
|
13
12
|
|
|
14
13
|
const ALL_STATES: ExecutionState[] = [
|
|
@@ -108,6 +107,20 @@ describe('decision table key consistency', () => {
|
|
|
108
107
|
const decisionKeys = Object.keys(LIFECYCLE_DECISIONS.confirm).sort()
|
|
109
108
|
expect(decisionKeys).toEqual(transitionKeys)
|
|
110
109
|
})
|
|
110
|
+
|
|
111
|
+
it('LIFECYCLE_DECISIONS.reject keys match VALID_TRANSITIONS keys', () => {
|
|
112
|
+
const transitionKeys = Object.keys(VALID_TRANSITIONS).sort()
|
|
113
|
+
const decisionKeys = Object.keys(LIFECYCLE_DECISIONS.reject).sort()
|
|
114
|
+
expect(decisionKeys).toEqual(transitionKeys)
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
it('all intent rows have the same set of state keys', () => {
|
|
118
|
+
const intents = Object.keys(LIFECYCLE_DECISIONS) as Array<keyof typeof LIFECYCLE_DECISIONS>
|
|
119
|
+
const referenceKeys = Object.keys(LIFECYCLE_DECISIONS[intents[0]]).sort()
|
|
120
|
+
for (const intent of intents) {
|
|
121
|
+
expect(Object.keys(LIFECYCLE_DECISIONS[intent]).sort()).toEqual(referenceKeys)
|
|
122
|
+
}
|
|
123
|
+
})
|
|
111
124
|
})
|
|
112
125
|
|
|
113
126
|
// ---------------------------------------------------------------------------
|
|
@@ -158,48 +171,37 @@ describe('applyIntent', () => {
|
|
|
158
171
|
it('undone + confirm = conflict', () => {
|
|
159
172
|
expect(applyIntent('undone', 'confirm')).toBe('conflict')
|
|
160
173
|
})
|
|
161
|
-
})
|
|
162
|
-
|
|
163
|
-
// ---------------------------------------------------------------------------
|
|
164
|
-
// 7. EXECUTION_ERROR TESTS
|
|
165
|
-
// ---------------------------------------------------------------------------
|
|
166
|
-
describe('ExecutionError', () => {
|
|
167
|
-
it('has correct name', () => {
|
|
168
|
-
const err = new ExecutionError('execution_expired', 'test', 410)
|
|
169
|
-
expect(err.name).toBe('ExecutionError')
|
|
170
|
-
})
|
|
171
174
|
|
|
172
|
-
it('
|
|
173
|
-
|
|
174
|
-
expect(err.code).toBe('execution_invalid_transition')
|
|
175
|
+
it('pending_confirmation + reject = approve', () => {
|
|
176
|
+
expect(applyIntent('pending_confirmation', 'reject')).toBe('approve')
|
|
175
177
|
})
|
|
176
178
|
|
|
177
|
-
it('
|
|
178
|
-
|
|
179
|
-
expect(err.message).toBe('not found')
|
|
179
|
+
it('expired + reject = expired', () => {
|
|
180
|
+
expect(applyIntent('expired', 'reject')).toBe('expired')
|
|
180
181
|
})
|
|
181
182
|
|
|
182
|
-
it('
|
|
183
|
-
|
|
184
|
-
expect(err.httpStatus).toBe(403)
|
|
183
|
+
it('cancelled + reject = conflict', () => {
|
|
184
|
+
expect(applyIntent('cancelled', 'reject')).toBe('conflict')
|
|
185
185
|
})
|
|
186
186
|
|
|
187
|
-
it('
|
|
188
|
-
|
|
189
|
-
expect(err.httpStatus).toBeUndefined()
|
|
187
|
+
it('ready + reject = conflict', () => {
|
|
188
|
+
expect(applyIntent('ready', 'reject')).toBe('conflict')
|
|
190
189
|
})
|
|
191
190
|
|
|
192
|
-
it('
|
|
193
|
-
|
|
194
|
-
expect(err).toBeInstanceOf(Error)
|
|
191
|
+
it('executing + reject = conflict', () => {
|
|
192
|
+
expect(applyIntent('executing', 'reject')).toBe('conflict')
|
|
195
193
|
})
|
|
196
194
|
|
|
197
|
-
it('
|
|
198
|
-
|
|
199
|
-
expect(err).toBeInstanceOf(ExecutionError)
|
|
195
|
+
it('completed + reject = conflict', () => {
|
|
196
|
+
expect(applyIntent('completed', 'reject')).toBe('conflict')
|
|
200
197
|
})
|
|
198
|
+
})
|
|
201
199
|
|
|
202
|
-
|
|
200
|
+
// ---------------------------------------------------------------------------
|
|
201
|
+
// 7. EXECUTION_ERROR TYPE TESTS
|
|
202
|
+
// ---------------------------------------------------------------------------
|
|
203
|
+
describe('ExecutionErrorCode', () => {
|
|
204
|
+
it('covers all expected error codes', () => {
|
|
203
205
|
const codes: ExecutionErrorCode[] = [
|
|
204
206
|
'execution_expired',
|
|
205
207
|
'execution_already_confirmed',
|
|
@@ -208,11 +210,7 @@ describe('ExecutionError', () => {
|
|
|
208
210
|
'execution_forbidden',
|
|
209
211
|
'execution_invalid_transition',
|
|
210
212
|
]
|
|
211
|
-
|
|
212
|
-
const err = new ExecutionError(code, `msg-${code}`)
|
|
213
|
-
expect(err.code).toBe(code)
|
|
214
|
-
expect(err.name).toBe('ExecutionError')
|
|
215
|
-
}
|
|
213
|
+
expect(codes).toHaveLength(6)
|
|
216
214
|
})
|
|
217
215
|
})
|
|
218
216
|
|
package/src/execution/errors.ts
CHANGED
|
@@ -6,13 +6,8 @@ export type ExecutionErrorCode =
|
|
|
6
6
|
| 'execution_forbidden'
|
|
7
7
|
| 'execution_invalid_transition';
|
|
8
8
|
|
|
9
|
-
export
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
public readonly httpStatus?: number,
|
|
14
|
-
) {
|
|
15
|
-
super(message);
|
|
16
|
-
this.name = 'ExecutionError';
|
|
17
|
-
}
|
|
9
|
+
export interface ExecutionError {
|
|
10
|
+
readonly name: 'ExecutionError';
|
|
11
|
+
readonly code: ExecutionErrorCode;
|
|
12
|
+
readonly message: string;
|
|
18
13
|
}
|
package/src/execution/index.ts
CHANGED
|
@@ -103,8 +103,7 @@ export { parseExpiresAt, isConfirmationExpired } from './expiry'
|
|
|
103
103
|
// Error Types
|
|
104
104
|
// =============================================================================
|
|
105
105
|
|
|
106
|
-
export type { ExecutionErrorCode } from './errors'
|
|
107
|
-
export { ExecutionError } from './errors'
|
|
106
|
+
export type { ExecutionErrorCode, ExecutionError } from './errors'
|
|
108
107
|
|
|
109
108
|
// =============================================================================
|
|
110
109
|
// Definition Types
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ExecutionState } from './status';
|
|
2
2
|
|
|
3
|
-
export type ExecutionIntent = 'confirm';
|
|
3
|
+
export type ExecutionIntent = 'confirm' | 'reject';
|
|
4
4
|
|
|
5
5
|
export type LifecycleDecision =
|
|
6
6
|
| 'approve'
|
|
@@ -29,6 +29,20 @@ export const LIFECYCLE_DECISIONS: DecisionTable = {
|
|
|
29
29
|
failed_with_partial_execution: 'conflict',
|
|
30
30
|
undone: 'conflict',
|
|
31
31
|
},
|
|
32
|
+
reject: {
|
|
33
|
+
pending_confirmation: 'approve',
|
|
34
|
+
expired: 'expired',
|
|
35
|
+
cancelled: 'conflict',
|
|
36
|
+
blocked_pending_approval: 'conflict',
|
|
37
|
+
ready: 'conflict',
|
|
38
|
+
executing: 'conflict',
|
|
39
|
+
completed: 'conflict',
|
|
40
|
+
completed_with_rollbacks: 'conflict',
|
|
41
|
+
failed_retryable: 'conflict',
|
|
42
|
+
failed_terminal: 'conflict',
|
|
43
|
+
failed_with_partial_execution: 'conflict',
|
|
44
|
+
undone: 'conflict',
|
|
45
|
+
},
|
|
32
46
|
};
|
|
33
47
|
|
|
34
48
|
export function applyIntent(
|
package/src/index.ts
CHANGED
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
* @company-semantics/contracts
|
|
3
3
|
*
|
|
4
4
|
* Shared semantic vocabulary across Company Semantics codebases.
|
|
5
|
-
* Types
|
|
5
|
+
* Types and pure deterministic functions — no runtime code, no business logic.
|
|
6
6
|
*
|
|
7
|
-
* This package
|
|
8
|
-
*
|
|
9
|
-
* until they are proven stable.
|
|
7
|
+
* This package contains shared vocabulary and pure derivation functions.
|
|
8
|
+
* Structural types live in individual codebases until they are proven stable.
|
|
10
9
|
*
|
|
11
10
|
* @see https://github.com/company-semantics/company-semantics-contracts
|
|
12
11
|
*/
|
|
@@ -466,6 +465,14 @@ export type {
|
|
|
466
465
|
UsageByFeature,
|
|
467
466
|
UsageByUser,
|
|
468
467
|
OrgUsageResponse,
|
|
468
|
+
// Unified usage types (PRD-00276/277)
|
|
469
|
+
UnifiedUsageSummary,
|
|
470
|
+
UnifiedDailyUsage,
|
|
471
|
+
UnifiedProfileUsage,
|
|
472
|
+
UnifiedUserUsage,
|
|
473
|
+
UnifiedModelUsage,
|
|
474
|
+
UnifiedFeatureUsage,
|
|
475
|
+
UnifiedUsageResponse,
|
|
469
476
|
} from './usage/types'
|
|
470
477
|
|
|
471
478
|
// Runtime execution telemetry types
|
package/src/mcp/index.ts
CHANGED
|
@@ -215,7 +215,7 @@ export interface MCPToolDescriptor {
|
|
|
215
215
|
* Edge in the capability graph connecting two tools via a resource.
|
|
216
216
|
* A tool that produces a resource connects to tools that consume it.
|
|
217
217
|
*
|
|
218
|
-
* @
|
|
218
|
+
* @see capability-graph.ts for buildCapabilityGraph() implementation
|
|
219
219
|
*/
|
|
220
220
|
export interface CapabilityGraphEdge {
|
|
221
221
|
/** Tool ID that produces the resource */
|
|
@@ -232,7 +232,7 @@ export interface CapabilityGraphEdge {
|
|
|
232
232
|
* Named workflow derived from capability graph paths.
|
|
233
233
|
* Represents a common multi-tool sequence (e.g., "Connect Slack → Ingest → Query").
|
|
234
234
|
*
|
|
235
|
-
* @
|
|
235
|
+
* @see capability-graph.ts for buildCapabilityGraph() implementation
|
|
236
236
|
*/
|
|
237
237
|
export interface ToolWorkflow {
|
|
238
238
|
/** Workflow name (e.g., "Slack Onboarding") */
|
|
@@ -247,7 +247,7 @@ export interface ToolWorkflow {
|
|
|
247
247
|
* Capability graph derived from tool resource flow metadata.
|
|
248
248
|
* Built from produces/consumes fields on MCPToolDescriptor.
|
|
249
249
|
*
|
|
250
|
-
* @
|
|
250
|
+
* @see capability-graph.ts for buildCapabilityGraph() implementation
|
|
251
251
|
*/
|
|
252
252
|
export interface CapabilityGraph {
|
|
253
253
|
/** Resource flow edges between tools */
|
|
@@ -270,7 +270,7 @@ export interface ToolDiscoveryResponse {
|
|
|
270
270
|
* Capability graph derived from tool resource flow metadata.
|
|
271
271
|
* Optional — discovery responses may or may not include the computed graph.
|
|
272
272
|
*
|
|
273
|
-
* @
|
|
273
|
+
* @see capability-graph.ts for buildCapabilityGraph() implementation
|
|
274
274
|
*/
|
|
275
275
|
graph?: CapabilityGraph
|
|
276
276
|
}
|
package/src/usage/types.ts
CHANGED
|
@@ -46,6 +46,9 @@ export interface UsageByUser {
|
|
|
46
46
|
requestCount: number;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
/**
|
|
50
|
+
* @deprecated Use UnifiedUsageResponse instead. Will be removed in v1.0.
|
|
51
|
+
*/
|
|
49
52
|
export interface OrgUsageResponse {
|
|
50
53
|
summary: UsageSummary;
|
|
51
54
|
daily: DailyUsage[];
|
|
@@ -53,3 +56,64 @@ export interface OrgUsageResponse {
|
|
|
53
56
|
byFeature: UsageByFeature[];
|
|
54
57
|
topUsers: UsageByUser[];
|
|
55
58
|
}
|
|
59
|
+
|
|
60
|
+
// ---------------------------------------------------------------------------
|
|
61
|
+
// Unified Usage Response (PRD-00276/277)
|
|
62
|
+
// ---------------------------------------------------------------------------
|
|
63
|
+
|
|
64
|
+
export interface UnifiedUsageSummary {
|
|
65
|
+
executions: number;
|
|
66
|
+
totalCostUsd: string;
|
|
67
|
+
totalTokens: number;
|
|
68
|
+
avgDurationMs: number;
|
|
69
|
+
failureRate: number;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface UnifiedDailyUsage {
|
|
73
|
+
date: string;
|
|
74
|
+
executions: number;
|
|
75
|
+
totalCostUsd: string;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface UnifiedProfileUsage {
|
|
79
|
+
profile: string;
|
|
80
|
+
executions: number;
|
|
81
|
+
percentOfTotal: number;
|
|
82
|
+
totalCostUsd: string;
|
|
83
|
+
avgDurationMs: number;
|
|
84
|
+
failureRate: number;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface UnifiedUserUsage {
|
|
88
|
+
userId: string;
|
|
89
|
+
email: string;
|
|
90
|
+
executions: number;
|
|
91
|
+
totalCostUsd: string;
|
|
92
|
+
totalTokens: number;
|
|
93
|
+
favoriteProfile: string;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export interface UnifiedModelUsage {
|
|
97
|
+
model: string;
|
|
98
|
+
provider: string;
|
|
99
|
+
totalTokens: number;
|
|
100
|
+
estimatedCostUsd: string;
|
|
101
|
+
requestCount: number;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export interface UnifiedFeatureUsage {
|
|
105
|
+
feature: string;
|
|
106
|
+
totalTokens: number;
|
|
107
|
+
estimatedCostUsd: string;
|
|
108
|
+
requestCount: number;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export interface UnifiedUsageResponse {
|
|
112
|
+
period: { start: string; end: string };
|
|
113
|
+
summary: UnifiedUsageSummary;
|
|
114
|
+
daily: UnifiedDailyUsage[];
|
|
115
|
+
byProfile: UnifiedProfileUsage[];
|
|
116
|
+
byUser: UnifiedUserUsage[];
|
|
117
|
+
byModel: UnifiedModelUsage[];
|
|
118
|
+
byFeature: UnifiedFeatureUsage[];
|
|
119
|
+
}
|