@company-semantics/contracts 0.81.0 → 0.82.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/chat/runtime-profile.ts +1 -1
- package/src/execution/index.ts +7 -0
- package/src/execution/kinds.ts +2 -0
- package/src/execution/registry.ts +42 -0
- package/src/execution/status.ts +57 -0
- package/src/execution/types.ts +33 -2
- package/src/index.ts +31 -31
- package/src/message-parts/__tests__/confirmation.test.ts +45 -49
- package/src/message-parts/confirmation.ts +33 -36
- package/src/message-parts/index.ts +4 -4
- package/src/message-parts/types.ts +1 -5
- package/src/message-parts/wire.ts +0 -20
package/package.json
CHANGED
|
@@ -27,7 +27,7 @@ export interface ChatRuntimeProfileInfo {
|
|
|
27
27
|
export const CHAT_RUNTIME_PROFILES: readonly ChatRuntimeProfileInfo[] = [
|
|
28
28
|
{ id: 'fast', label: 'Fast', description: 'Single-step, no tools', model: 'gpt-3.5-turbo' },
|
|
29
29
|
{ id: 'balanced', label: 'Balanced', description: 'Multi-step with tools', model: 'gpt-4o' },
|
|
30
|
-
{ id: 'agentic', label: 'Agentic', description: 'Agent loop, full reasoning', model: 'claude-sonnet-4' },
|
|
30
|
+
{ id: 'agentic', label: 'Agentic', description: 'Agent loop, full reasoning', model: 'claude-sonnet-4-20250514' },
|
|
31
31
|
] as const
|
|
32
32
|
|
|
33
33
|
/**
|
package/src/execution/index.ts
CHANGED
|
@@ -13,6 +13,12 @@
|
|
|
13
13
|
|
|
14
14
|
export type { ExecutionKind } from './kinds'
|
|
15
15
|
|
|
16
|
+
// =============================================================================
|
|
17
|
+
// Lifecycle State
|
|
18
|
+
// =============================================================================
|
|
19
|
+
|
|
20
|
+
export type { ExecutionState } from './status'
|
|
21
|
+
|
|
16
22
|
// =============================================================================
|
|
17
23
|
// Definition Types
|
|
18
24
|
// =============================================================================
|
|
@@ -22,6 +28,7 @@ export type {
|
|
|
22
28
|
IconName,
|
|
23
29
|
ExecutionDomain,
|
|
24
30
|
ExecutionKindDefinition,
|
|
31
|
+
ExecutionIntent,
|
|
25
32
|
} from './types'
|
|
26
33
|
|
|
27
34
|
// =============================================================================
|
package/src/execution/kinds.ts
CHANGED
|
@@ -76,6 +76,48 @@ export const EXECUTION_KINDS = {
|
|
|
76
76
|
templateId: 'integration.disconnect',
|
|
77
77
|
},
|
|
78
78
|
},
|
|
79
|
+
'profile.update': {
|
|
80
|
+
kind: 'profile.update',
|
|
81
|
+
domain: 'profile',
|
|
82
|
+
display: {
|
|
83
|
+
label: 'Update Profile',
|
|
84
|
+
pastTenseLabel: 'Profile updated',
|
|
85
|
+
icon: 'pencil',
|
|
86
|
+
},
|
|
87
|
+
governance: {
|
|
88
|
+
visibility: 'user',
|
|
89
|
+
requiresAdmin: false,
|
|
90
|
+
},
|
|
91
|
+
ui: {
|
|
92
|
+
showInAdmin: false,
|
|
93
|
+
showInTimeline: true,
|
|
94
|
+
confirmBeforeRun: true,
|
|
95
|
+
},
|
|
96
|
+
explanation: {
|
|
97
|
+
templateId: 'profile.update',
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
'slack.send': {
|
|
101
|
+
kind: 'slack.send',
|
|
102
|
+
domain: 'communication',
|
|
103
|
+
display: {
|
|
104
|
+
label: 'Send Slack Message',
|
|
105
|
+
pastTenseLabel: 'Slack message sent',
|
|
106
|
+
icon: 'send',
|
|
107
|
+
},
|
|
108
|
+
governance: {
|
|
109
|
+
visibility: 'user',
|
|
110
|
+
requiresAdmin: false,
|
|
111
|
+
},
|
|
112
|
+
ui: {
|
|
113
|
+
showInAdmin: false,
|
|
114
|
+
showInTimeline: true,
|
|
115
|
+
confirmBeforeRun: true,
|
|
116
|
+
},
|
|
117
|
+
explanation: {
|
|
118
|
+
templateId: 'slack.send',
|
|
119
|
+
},
|
|
120
|
+
},
|
|
79
121
|
} as const satisfies Record<ExecutionKind, ExecutionKindDefinition>
|
|
80
122
|
|
|
81
123
|
// =============================================================================
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ExecutionState — First-class contract for execution lifecycle state.
|
|
3
|
+
*
|
|
4
|
+
* This type is the sole authority (INV-1) for lifecycle state across all repos.
|
|
5
|
+
* Backend MUST import from contracts, not define locally.
|
|
6
|
+
*
|
|
7
|
+
* ## State Machine
|
|
8
|
+
*
|
|
9
|
+
* ```
|
|
10
|
+
* pending_confirmation ──→ blocked_pending_approval ──→ ready ──→ executing
|
|
11
|
+
* │ │ ↑ │
|
|
12
|
+
* │ │ │ ├──→ completed
|
|
13
|
+
* │ │ │ ├──→ completed_with_rollbacks
|
|
14
|
+
* │ │ │ ├──→ failed_retryable ──→ ready (retry)
|
|
15
|
+
* │ │ │ ├──→ failed_terminal
|
|
16
|
+
* │ │ │ ├──→ failed_with_partial_execution
|
|
17
|
+
* │ │ │ └──→ cancelled
|
|
18
|
+
* └──→ cancelled └──→ cancelled │
|
|
19
|
+
* └──→ expired └──→ expired └──→ expired
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* ## Key Semantics
|
|
23
|
+
*
|
|
24
|
+
* - **pending_confirmation** and **blocked_pending_approval** are orthogonal
|
|
25
|
+
* stackable gates that compose. pending_confirmation is the self-attestation
|
|
26
|
+
* gate; blocked_pending_approval is the cross-principal authorization gate.
|
|
27
|
+
*
|
|
28
|
+
* - **ready** is a distinct state separating authorization from execution.
|
|
29
|
+
* All governance gates are cleared. Enables future queueing, backpressure,
|
|
30
|
+
* rate limiting, and scheduling.
|
|
31
|
+
*
|
|
32
|
+
* - **execution_started** is the sole event transitioning to **executing**.
|
|
33
|
+
* Mandatory for all execution paths including retries.
|
|
34
|
+
*
|
|
35
|
+
* - Retry is same-execution: failed_retryable → ready → executing reuses
|
|
36
|
+
* the same executionId.
|
|
37
|
+
*
|
|
38
|
+
* ## Ordering Invariant
|
|
39
|
+
*
|
|
40
|
+
* State transitions are ordered by event_sequence (monotonic per-execution
|
|
41
|
+
* bigint), not timestamps. UNIQUE(execution_id, event_sequence) enforced
|
|
42
|
+
* at database level. event_sequence for ordering, created_at for duration —
|
|
43
|
+
* distinct concerns.
|
|
44
|
+
*/
|
|
45
|
+
export type ExecutionState =
|
|
46
|
+
| 'pending_confirmation'
|
|
47
|
+
| 'blocked_pending_approval'
|
|
48
|
+
| 'ready'
|
|
49
|
+
| 'executing'
|
|
50
|
+
| 'completed'
|
|
51
|
+
| 'completed_with_rollbacks'
|
|
52
|
+
| 'failed_retryable'
|
|
53
|
+
| 'failed_terminal'
|
|
54
|
+
| 'failed_with_partial_execution'
|
|
55
|
+
| 'cancelled'
|
|
56
|
+
| 'expired'
|
|
57
|
+
| 'undone';
|
package/src/execution/types.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import type { ExecutionKind } from './kinds'
|
|
10
|
+
import type { ConfirmationRiskLevel } from '../message-parts/confirmation'
|
|
10
11
|
|
|
11
12
|
// =============================================================================
|
|
12
13
|
// Utility Types
|
|
@@ -22,7 +23,7 @@ export type ISO8601Timestamp = string
|
|
|
22
23
|
* Icon names for execution kinds.
|
|
23
24
|
* Must be supported by the frontend icon system.
|
|
24
25
|
*/
|
|
25
|
-
export type IconName = 'plug' | 'unlink'
|
|
26
|
+
export type IconName = 'plug' | 'unlink' | 'pencil' | 'send'
|
|
26
27
|
|
|
27
28
|
// =============================================================================
|
|
28
29
|
// Execution Domain
|
|
@@ -31,7 +32,7 @@ export type IconName = 'plug' | 'unlink'
|
|
|
31
32
|
/**
|
|
32
33
|
* Domain categories for execution kinds.
|
|
33
34
|
*/
|
|
34
|
-
export type ExecutionDomain = 'integration' | 'policy' | 'data' | 'system'
|
|
35
|
+
export type ExecutionDomain = 'integration' | 'policy' | 'data' | 'system' | 'profile' | 'communication'
|
|
35
36
|
|
|
36
37
|
// =============================================================================
|
|
37
38
|
// Execution Kind Definition
|
|
@@ -90,3 +91,33 @@ export interface ExecutionKindDefinition {
|
|
|
90
91
|
templateId: string
|
|
91
92
|
}
|
|
92
93
|
}
|
|
94
|
+
|
|
95
|
+
// =============================================================================
|
|
96
|
+
// Execution Intent
|
|
97
|
+
// =============================================================================
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Governance requirements for an execution.
|
|
101
|
+
*
|
|
102
|
+
* Executors declare this explicitly when proposing an execution.
|
|
103
|
+
* The bridge transports ExecutionIntent as-is — it never infers governance
|
|
104
|
+
* requirements. The system fails loudly if ExecutionIntent is missing.
|
|
105
|
+
*
|
|
106
|
+
* Invariants:
|
|
107
|
+
* - executionKind MUST exist in EXECUTION_KINDS registry
|
|
108
|
+
* - If requiresConfirmation is false, no confirmation part is emitted
|
|
109
|
+
* and execution starts at 'ready'
|
|
110
|
+
* - If requiresApproval is true, a 'blocked_pending_approval' gate is
|
|
111
|
+
* inserted after confirmation (cross-principal authorization)
|
|
112
|
+
* - risk is used for UI styling and future behavioral hooks
|
|
113
|
+
*
|
|
114
|
+
* NAMING NOTE: This is DIFFERENT from the CI Envelope ExecutionIntent
|
|
115
|
+
* (a string union in ci-envelope/types.ts). This interface is exported
|
|
116
|
+
* from the execution domain barrel only, NOT from root index.ts.
|
|
117
|
+
*/
|
|
118
|
+
export interface ExecutionIntent {
|
|
119
|
+
executionKind: ExecutionKind
|
|
120
|
+
requiresConfirmation: boolean
|
|
121
|
+
requiresApproval: boolean
|
|
122
|
+
risk: ConfirmationRiskLevel
|
|
123
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -303,12 +303,9 @@ export type {
|
|
|
303
303
|
PreviewDataPart,
|
|
304
304
|
// Confirmation types (Phase 4)
|
|
305
305
|
ConfirmationChoice,
|
|
306
|
-
|
|
306
|
+
ConfirmationRiskLevel,
|
|
307
307
|
ConfirmationData,
|
|
308
308
|
ConfirmationDataPart,
|
|
309
|
-
ConfirmationResponseData,
|
|
310
|
-
ConfirmationResponsePart,
|
|
311
|
-
ConfirmationResponseDataPart,
|
|
312
309
|
// Execution result types (Phase 5)
|
|
313
310
|
ExecutionArtifactStatus,
|
|
314
311
|
ExecutionResultSummary,
|
|
@@ -344,12 +341,15 @@ export {
|
|
|
344
341
|
buildParts,
|
|
345
342
|
getDroppedCount,
|
|
346
343
|
WireSurfaceBuilder,
|
|
344
|
+
CONFIRMATION_LABELS,
|
|
345
|
+
getConfirmationLabel,
|
|
347
346
|
} from './message-parts/index'
|
|
348
347
|
|
|
349
348
|
// Execution kind types and registry
|
|
350
349
|
// @see ADR-CONT-029 for design rationale
|
|
351
350
|
export type {
|
|
352
351
|
ExecutionKind,
|
|
352
|
+
ExecutionState,
|
|
353
353
|
ISO8601Timestamp,
|
|
354
354
|
IconName,
|
|
355
355
|
ExecutionDomain,
|
|
@@ -370,33 +370,6 @@ export {
|
|
|
370
370
|
isValidExecutionKind,
|
|
371
371
|
} from './execution/index'
|
|
372
372
|
|
|
373
|
-
// CI Execution Envelope types
|
|
374
|
-
// @see ADR-CONT-033 for contracts boundary rationale
|
|
375
|
-
export type {
|
|
376
|
-
// Actor & Session
|
|
377
|
-
CIActorInfo,
|
|
378
|
-
CISessionInfo,
|
|
379
|
-
// Intent
|
|
380
|
-
ExecutionIntent,
|
|
381
|
-
CIIntentDeclaration,
|
|
382
|
-
// Scope
|
|
383
|
-
CIChangeKind,
|
|
384
|
-
CIExecutionScope,
|
|
385
|
-
// Authority
|
|
386
|
-
CIAuthorityGrant,
|
|
387
|
-
// Guard Plan
|
|
388
|
-
CIGuardPlan,
|
|
389
|
-
// Status
|
|
390
|
-
CIEnvelopeStatus,
|
|
391
|
-
// Outcome
|
|
392
|
-
CIGuardViolation,
|
|
393
|
-
CIExecutionOutcome,
|
|
394
|
-
// Core Envelope
|
|
395
|
-
CIExecutionEnvelope,
|
|
396
|
-
} from './ci-envelope/index'
|
|
397
|
-
|
|
398
|
-
export { ENVELOPE_TRANSITIONS } from './ci-envelope/index'
|
|
399
|
-
|
|
400
373
|
// Ralph autonomous coding loop types
|
|
401
374
|
// @see company-semantics-control/docs/ralph.md for usage
|
|
402
375
|
export type {
|
|
@@ -493,3 +466,30 @@ export type {
|
|
|
493
466
|
BudgetCheck,
|
|
494
467
|
OrgBudgetSettings,
|
|
495
468
|
} from './usage/execution-types'
|
|
469
|
+
|
|
470
|
+
// CI Execution Envelope types
|
|
471
|
+
// @see ADR-CONT-033 for contracts boundary rationale
|
|
472
|
+
export type {
|
|
473
|
+
// Actor & Session
|
|
474
|
+
CIActorInfo,
|
|
475
|
+
CISessionInfo,
|
|
476
|
+
// Intent
|
|
477
|
+
ExecutionIntent,
|
|
478
|
+
CIIntentDeclaration,
|
|
479
|
+
// Scope
|
|
480
|
+
CIChangeKind,
|
|
481
|
+
CIExecutionScope,
|
|
482
|
+
// Authority
|
|
483
|
+
CIAuthorityGrant,
|
|
484
|
+
// Guard Plan
|
|
485
|
+
CIGuardPlan,
|
|
486
|
+
// Status
|
|
487
|
+
CIEnvelopeStatus,
|
|
488
|
+
// Outcome
|
|
489
|
+
CIGuardViolation,
|
|
490
|
+
CIExecutionOutcome,
|
|
491
|
+
// Core Envelope
|
|
492
|
+
CIExecutionEnvelope,
|
|
493
|
+
} from './ci-envelope/index'
|
|
494
|
+
|
|
495
|
+
export { ENVELOPE_TRANSITIONS } from './ci-envelope/index'
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest'
|
|
2
2
|
import { WireSurfaceBuilder } from '../wire.js'
|
|
3
|
-
import type { ConfirmationData,
|
|
3
|
+
import type { ConfirmationData, ConfirmationRiskLevel } from '../confirmation.js'
|
|
4
|
+
import { CONFIRMATION_LABELS, getConfirmationLabel } from '../confirmation.js'
|
|
5
|
+
import type { ExecutionKind } from '../../execution/kinds.js'
|
|
6
|
+
import { EXECUTION_KINDS } from '../../execution/registry.js'
|
|
4
7
|
|
|
5
8
|
describe('WireSurfaceBuilder.confirmation', () => {
|
|
6
|
-
it('creates a confirmation data part', () => {
|
|
9
|
+
it('creates a confirmation data part with new shape', () => {
|
|
7
10
|
const data: ConfirmationData = {
|
|
8
11
|
actionId: 'msg-123',
|
|
9
|
-
|
|
10
|
-
prompt: 'Confirm sending this message?',
|
|
12
|
+
executorKind: 'slack.send',
|
|
11
13
|
risk: 'low',
|
|
14
|
+
executionId: 'exec-abc-001',
|
|
12
15
|
}
|
|
13
16
|
|
|
14
17
|
const result = WireSurfaceBuilder.confirmation(data)
|
|
@@ -20,8 +23,9 @@ describe('WireSurfaceBuilder.confirmation', () => {
|
|
|
20
23
|
it('preserves actionId exactly', () => {
|
|
21
24
|
const data: ConfirmationData = {
|
|
22
25
|
actionId: 'complex-action-id-12345',
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
executorKind: 'integration.connect',
|
|
27
|
+
risk: 'moderate',
|
|
28
|
+
executionId: 'exec-xyz-789',
|
|
25
29
|
}
|
|
26
30
|
|
|
27
31
|
const result = WireSurfaceBuilder.confirmation(data)
|
|
@@ -29,28 +33,15 @@ describe('WireSurfaceBuilder.confirmation', () => {
|
|
|
29
33
|
expect(result.data.actionId).toBe('complex-action-id-12345')
|
|
30
34
|
})
|
|
31
35
|
|
|
32
|
-
it('
|
|
33
|
-
const
|
|
34
|
-
actionId: 'no-risk-specified',
|
|
35
|
-
title: 'Simple action',
|
|
36
|
-
prompt: 'Do you want to proceed?',
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const result = WireSurfaceBuilder.confirmation(data)
|
|
40
|
-
|
|
41
|
-
expect(result.type).toBe('data-confirmation')
|
|
42
|
-
expect(result.data.risk).toBeUndefined()
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
it('preserves all risk levels', () => {
|
|
46
|
-
const risks: Array<'low' | 'medium' | 'high'> = ['low', 'medium', 'high']
|
|
36
|
+
it('preserves all ConfirmationRiskLevel values', () => {
|
|
37
|
+
const risks: ConfirmationRiskLevel[] = ['low', 'moderate', 'high', 'irreversible']
|
|
47
38
|
|
|
48
39
|
for (const risk of risks) {
|
|
49
40
|
const data: ConfirmationData = {
|
|
50
41
|
actionId: `risk-${risk}`,
|
|
51
|
-
|
|
52
|
-
prompt: 'Confirm?',
|
|
42
|
+
executorKind: 'profile.update',
|
|
53
43
|
risk,
|
|
44
|
+
executionId: `exec-risk-${risk}`,
|
|
54
45
|
}
|
|
55
46
|
|
|
56
47
|
const result = WireSurfaceBuilder.confirmation(data)
|
|
@@ -58,42 +49,47 @@ describe('WireSurfaceBuilder.confirmation', () => {
|
|
|
58
49
|
expect(result.data.risk).toBe(risk)
|
|
59
50
|
}
|
|
60
51
|
})
|
|
61
|
-
})
|
|
62
52
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
53
|
+
it('preserves executionId and executorKind', () => {
|
|
54
|
+
const data: ConfirmationData = {
|
|
55
|
+
actionId: 'action-001',
|
|
56
|
+
executorKind: 'integration.disconnect',
|
|
57
|
+
risk: 'high',
|
|
58
|
+
executionId: 'exec-lifecycle-001',
|
|
68
59
|
}
|
|
69
60
|
|
|
70
|
-
const result = WireSurfaceBuilder.
|
|
61
|
+
const result = WireSurfaceBuilder.confirmation(data)
|
|
71
62
|
|
|
72
|
-
expect(result.
|
|
73
|
-
expect(result.data.
|
|
74
|
-
expect(result.data.choice).toBe('confirm')
|
|
63
|
+
expect(result.data.executionId).toBe('exec-lifecycle-001')
|
|
64
|
+
expect(result.data.executorKind).toBe('integration.disconnect')
|
|
75
65
|
})
|
|
66
|
+
})
|
|
76
67
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
68
|
+
describe('getConfirmationLabel', () => {
|
|
69
|
+
it('returns correct label for known ExecutionKind', () => {
|
|
70
|
+
expect(getConfirmationLabel('integration.connect')).toBe('Connect Integration')
|
|
71
|
+
expect(getConfirmationLabel('integration.disconnect')).toBe('Disconnect Integration')
|
|
72
|
+
expect(getConfirmationLabel('profile.update')).toBe('Update Profile')
|
|
73
|
+
expect(getConfirmationLabel('slack.send')).toBe('Send Slack Message')
|
|
74
|
+
})
|
|
84
75
|
|
|
85
|
-
|
|
86
|
-
expect(
|
|
76
|
+
it('returns default fallback for undefined', () => {
|
|
77
|
+
expect(getConfirmationLabel(undefined)).toBe('Confirm Action')
|
|
87
78
|
})
|
|
88
79
|
|
|
89
|
-
it('
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
80
|
+
it('returns custom fallback title when provided', () => {
|
|
81
|
+
expect(getConfirmationLabel(undefined, 'Custom Fallback')).toBe('Custom Fallback')
|
|
82
|
+
})
|
|
83
|
+
})
|
|
94
84
|
|
|
95
|
-
|
|
85
|
+
describe('CONFIRMATION_LABELS', () => {
|
|
86
|
+
it('has an entry for every ExecutionKind', () => {
|
|
87
|
+
const executionKinds = Object.keys(EXECUTION_KINDS) as ExecutionKind[]
|
|
96
88
|
|
|
97
|
-
|
|
89
|
+
for (const kind of executionKinds) {
|
|
90
|
+
expect(CONFIRMATION_LABELS[kind]).toBeDefined()
|
|
91
|
+
expect(typeof CONFIRMATION_LABELS[kind]).toBe('string')
|
|
92
|
+
expect(CONFIRMATION_LABELS[kind].length).toBeGreaterThan(0)
|
|
93
|
+
}
|
|
98
94
|
})
|
|
99
95
|
})
|
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
* @see DECISIONS.md for design rationale
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
+
import type { ExecutionKind } from '../execution/kinds'
|
|
21
|
+
|
|
20
22
|
/**
|
|
21
23
|
* Choice options for confirmation.
|
|
22
24
|
*/
|
|
@@ -24,21 +26,44 @@ export type ConfirmationChoice = 'confirm' | 'cancel';
|
|
|
24
26
|
|
|
25
27
|
/**
|
|
26
28
|
* Risk level for confirmation prompts.
|
|
29
|
+
* Uses 'moderate' (not 'medium') for semantic precision.
|
|
30
|
+
* 'irreversible' indicates destructive operations that cannot be undone.
|
|
27
31
|
*/
|
|
28
|
-
export type
|
|
32
|
+
export type ConfirmationRiskLevel = 'low' | 'moderate' | 'high' | 'irreversible';
|
|
29
33
|
|
|
30
34
|
/**
|
|
31
|
-
*
|
|
35
|
+
* Human-readable confirmation dialog titles for each execution kind.
|
|
36
|
+
* Exhaustive — TypeScript enforces completeness via Record type.
|
|
32
37
|
*/
|
|
38
|
+
export const CONFIRMATION_LABELS: Record<ExecutionKind, string> = {
|
|
39
|
+
'integration.connect': 'Connect Integration',
|
|
40
|
+
'integration.disconnect': 'Disconnect Integration',
|
|
41
|
+
'profile.update': 'Update Profile',
|
|
42
|
+
'slack.send': 'Send Slack Message',
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Look up the human-readable confirmation label for an execution kind.
|
|
47
|
+
*/
|
|
48
|
+
export function getConfirmationLabel(
|
|
49
|
+
executorKind: ExecutionKind | undefined,
|
|
50
|
+
fallbackTitle?: string,
|
|
51
|
+
): string {
|
|
52
|
+
if (executorKind && executorKind in CONFIRMATION_LABELS) {
|
|
53
|
+
return CONFIRMATION_LABELS[executorKind];
|
|
54
|
+
}
|
|
55
|
+
return fallbackTitle ?? 'Confirm Action';
|
|
56
|
+
}
|
|
57
|
+
|
|
33
58
|
export interface ConfirmationData {
|
|
34
59
|
/** Must match the active preview's actionId */
|
|
35
60
|
actionId: string;
|
|
36
|
-
/**
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
|
|
61
|
+
/** Execution kind for label derivation via getConfirmationLabel() */
|
|
62
|
+
executorKind: ExecutionKind;
|
|
63
|
+
/** Risk level — required for UI styling and future governance hooks */
|
|
64
|
+
risk: ConfirmationRiskLevel;
|
|
65
|
+
/** Lifecycle record ID — must exist before confirmation part is emitted */
|
|
66
|
+
executionId: string;
|
|
42
67
|
}
|
|
43
68
|
|
|
44
69
|
/**
|
|
@@ -57,31 +82,3 @@ export interface ConfirmationDataPart {
|
|
|
57
82
|
data: ConfirmationData;
|
|
58
83
|
}
|
|
59
84
|
|
|
60
|
-
// === Confirmation Response Types (New in Phase 4) ===
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Confirmation response data payload.
|
|
64
|
-
* Sent by the user (via UI button or structured message) to confirm/cancel.
|
|
65
|
-
*/
|
|
66
|
-
export interface ConfirmationResponseData {
|
|
67
|
-
/** Must match the active confirmation's actionId */
|
|
68
|
-
actionId: string;
|
|
69
|
-
/** The user's decision */
|
|
70
|
-
choice: ConfirmationChoice;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Confirmation response message part (semantic type).
|
|
75
|
-
*/
|
|
76
|
-
export interface ConfirmationResponsePart {
|
|
77
|
-
type: 'confirmation-response';
|
|
78
|
-
data: ConfirmationResponseData;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Confirmation response data part (wire format).
|
|
83
|
-
*/
|
|
84
|
-
export interface ConfirmationResponseDataPart {
|
|
85
|
-
type: 'data-confirmation-response';
|
|
86
|
-
data: ConfirmationResponseData;
|
|
87
|
-
}
|
|
@@ -33,15 +33,15 @@ export type {
|
|
|
33
33
|
// Confirmation types
|
|
34
34
|
export type {
|
|
35
35
|
ConfirmationChoice,
|
|
36
|
-
|
|
36
|
+
ConfirmationRiskLevel,
|
|
37
37
|
ConfirmationData,
|
|
38
38
|
ConfirmationPart,
|
|
39
39
|
ConfirmationDataPart,
|
|
40
|
-
ConfirmationResponseData,
|
|
41
|
-
ConfirmationResponsePart,
|
|
42
|
-
ConfirmationResponseDataPart,
|
|
43
40
|
} from './confirmation'
|
|
44
41
|
|
|
42
|
+
// Confirmation runtime values
|
|
43
|
+
export { CONFIRMATION_LABELS, getConfirmationLabel } from './confirmation'
|
|
44
|
+
|
|
45
45
|
// Execution result types
|
|
46
46
|
export type {
|
|
47
47
|
ExecutionArtifactStatus,
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
import type { ToolListMessagePart } from '../mcp/index'
|
|
17
17
|
import type { PreviewPart } from './preview'
|
|
18
|
-
import type { ConfirmationPart
|
|
18
|
+
import type { ConfirmationPart } from './confirmation'
|
|
19
19
|
|
|
20
20
|
// =============================================================================
|
|
21
21
|
// Narrative Parts (Streamable)
|
|
@@ -111,9 +111,6 @@ export interface TablePart {
|
|
|
111
111
|
/**
|
|
112
112
|
* Surface parts are rendered atomically (never streamed).
|
|
113
113
|
* Extensible: add new surface types to this union.
|
|
114
|
-
*
|
|
115
|
-
* Note: ConfirmationResponsePart is user-originated but included
|
|
116
|
-
* here for uniform parsing. Do not render as UI surface.
|
|
117
114
|
*/
|
|
118
115
|
export type SurfacePart =
|
|
119
116
|
| ToolListPart
|
|
@@ -121,7 +118,6 @@ export type SurfacePart =
|
|
|
121
118
|
| ChartPart
|
|
122
119
|
| TablePart
|
|
123
120
|
| ConfirmationPart
|
|
124
|
-
| ConfirmationResponsePart
|
|
125
121
|
| PreviewPart
|
|
126
122
|
|
|
127
123
|
/**
|
|
@@ -15,8 +15,6 @@ import type { PreviewDataPart, PreviewData } from './preview'
|
|
|
15
15
|
import type {
|
|
16
16
|
ConfirmationData,
|
|
17
17
|
ConfirmationDataPart,
|
|
18
|
-
ConfirmationResponseData,
|
|
19
|
-
ConfirmationResponseDataPart,
|
|
20
18
|
} from './confirmation'
|
|
21
19
|
import type {
|
|
22
20
|
ExecutionResultData,
|
|
@@ -92,24 +90,6 @@ export const WireSurfaceBuilder = {
|
|
|
92
90
|
}
|
|
93
91
|
},
|
|
94
92
|
|
|
95
|
-
/**
|
|
96
|
-
* Build a confirmation response data part.
|
|
97
|
-
* Used when processing user's confirm/cancel decision.
|
|
98
|
-
*
|
|
99
|
-
* INVARIANTS:
|
|
100
|
-
* - actionId must match the active confirmation
|
|
101
|
-
* - choice must be 'confirm' or 'cancel'
|
|
102
|
-
*
|
|
103
|
-
* @param data - Response data containing actionId and choice
|
|
104
|
-
* @returns Wire-format confirmation response part
|
|
105
|
-
*/
|
|
106
|
-
confirmationResponse(data: ConfirmationResponseData): ConfirmationResponseDataPart {
|
|
107
|
-
return {
|
|
108
|
-
type: 'data-confirmation-response',
|
|
109
|
-
data,
|
|
110
|
-
}
|
|
111
|
-
},
|
|
112
|
-
|
|
113
93
|
/**
|
|
114
94
|
* Build an execution result data part for streaming.
|
|
115
95
|
* Reports the outcome of an executed action.
|