twinclaw 1.0.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 (132) hide show
  1. package/README.md +66 -0
  2. package/bin/npm-twinclaw.js +17 -0
  3. package/bin/run-twinbot-cli.js +36 -0
  4. package/bin/twinbot.js +4 -0
  5. package/bin/twinclaw.js +4 -0
  6. package/dist/api/handlers/browser.js +160 -0
  7. package/dist/api/handlers/callback.js +80 -0
  8. package/dist/api/handlers/config-validate.js +19 -0
  9. package/dist/api/handlers/health.js +117 -0
  10. package/dist/api/handlers/local-state-backup.js +118 -0
  11. package/dist/api/handlers/persona-state.js +59 -0
  12. package/dist/api/handlers/skill-packages.js +94 -0
  13. package/dist/api/router.js +278 -0
  14. package/dist/api/runtime-event-producer.js +99 -0
  15. package/dist/api/shared.js +82 -0
  16. package/dist/api/websocket-hub.js +305 -0
  17. package/dist/config/config-loader.js +2 -0
  18. package/dist/config/env-schema.js +202 -0
  19. package/dist/config/env-validator.js +223 -0
  20. package/dist/config/identity-bootstrap.js +115 -0
  21. package/dist/config/json-config.js +344 -0
  22. package/dist/config/workspace.js +186 -0
  23. package/dist/core/channels-cli.js +77 -0
  24. package/dist/core/cli.js +119 -0
  25. package/dist/core/context-assembly.js +33 -0
  26. package/dist/core/doctor.js +365 -0
  27. package/dist/core/gateway-cli.js +323 -0
  28. package/dist/core/gateway.js +416 -0
  29. package/dist/core/heartbeat.js +54 -0
  30. package/dist/core/install-cli.js +320 -0
  31. package/dist/core/lane-executor.js +134 -0
  32. package/dist/core/logs-cli.js +70 -0
  33. package/dist/core/onboarding.js +760 -0
  34. package/dist/core/pairing-cli.js +78 -0
  35. package/dist/core/secret-vault-cli.js +204 -0
  36. package/dist/core/types.js +1 -0
  37. package/dist/index.js +404 -0
  38. package/dist/interfaces/dispatcher.js +214 -0
  39. package/dist/interfaces/telegram_handler.js +82 -0
  40. package/dist/interfaces/tui-dashboard.js +53 -0
  41. package/dist/interfaces/whatsapp_handler.js +94 -0
  42. package/dist/release/cli.js +97 -0
  43. package/dist/release/mvp-gate-cli.js +118 -0
  44. package/dist/release/twinbot-config-schema.js +162 -0
  45. package/dist/release/twinclaw-config-schema.js +162 -0
  46. package/dist/services/block-chunker.js +174 -0
  47. package/dist/services/browser-service.js +334 -0
  48. package/dist/services/context-lifecycle.js +314 -0
  49. package/dist/services/db.js +1055 -0
  50. package/dist/services/delivery-tracker.js +110 -0
  51. package/dist/services/dm-pairing.js +245 -0
  52. package/dist/services/embedding-service.js +125 -0
  53. package/dist/services/file-watcher.js +125 -0
  54. package/dist/services/inbound-debounce.js +92 -0
  55. package/dist/services/incident-manager.js +516 -0
  56. package/dist/services/job-scheduler.js +176 -0
  57. package/dist/services/local-state-backup.js +682 -0
  58. package/dist/services/mcp-client-adapter.js +291 -0
  59. package/dist/services/mcp-server-manager.js +143 -0
  60. package/dist/services/model-router.js +927 -0
  61. package/dist/services/mvp-gate.js +845 -0
  62. package/dist/services/orchestration-service.js +422 -0
  63. package/dist/services/persona-state.js +256 -0
  64. package/dist/services/policy-engine.js +92 -0
  65. package/dist/services/proactive-notifier.js +94 -0
  66. package/dist/services/queue-service.js +146 -0
  67. package/dist/services/release-pipeline.js +652 -0
  68. package/dist/services/runtime-budget-governor.js +415 -0
  69. package/dist/services/secret-vault.js +704 -0
  70. package/dist/services/semantic-memory.js +249 -0
  71. package/dist/services/skill-package-manager.js +806 -0
  72. package/dist/services/skill-registry.js +122 -0
  73. package/dist/services/streaming-output.js +75 -0
  74. package/dist/services/stt-service.js +39 -0
  75. package/dist/services/tts-service.js +44 -0
  76. package/dist/skills/builtin.js +250 -0
  77. package/dist/skills/shell.js +87 -0
  78. package/dist/skills/types.js +1 -0
  79. package/dist/types/api.js +1 -0
  80. package/dist/types/context-budget.js +1 -0
  81. package/dist/types/doctor.js +1 -0
  82. package/dist/types/file-watcher.js +1 -0
  83. package/dist/types/incident.js +1 -0
  84. package/dist/types/local-state-backup.js +1 -0
  85. package/dist/types/mcp.js +1 -0
  86. package/dist/types/messaging.js +1 -0
  87. package/dist/types/model-routing.js +1 -0
  88. package/dist/types/mvp-gate.js +2 -0
  89. package/dist/types/orchestration.js +1 -0
  90. package/dist/types/persona-state.js +22 -0
  91. package/dist/types/policy.js +1 -0
  92. package/dist/types/reasoning-graph.js +1 -0
  93. package/dist/types/release.js +1 -0
  94. package/dist/types/reliability.js +1 -0
  95. package/dist/types/runtime-budget.js +1 -0
  96. package/dist/types/scheduler.js +1 -0
  97. package/dist/types/secret-vault.js +1 -0
  98. package/dist/types/skill-packages.js +1 -0
  99. package/dist/types/websocket.js +14 -0
  100. package/dist/utils/logger.js +57 -0
  101. package/dist/utils/retry.js +61 -0
  102. package/dist/utils/secret-scan.js +208 -0
  103. package/mcp-servers.json +179 -0
  104. package/package.json +81 -0
  105. package/skill-packages.json +92 -0
  106. package/skill-packages.lock.json +5 -0
  107. package/src/skills/builtin.ts +275 -0
  108. package/src/skills/shell.ts +118 -0
  109. package/src/skills/types.ts +30 -0
  110. package/src/types/api.ts +252 -0
  111. package/src/types/blessed-contrib.d.ts +4 -0
  112. package/src/types/context-budget.ts +76 -0
  113. package/src/types/doctor.ts +29 -0
  114. package/src/types/file-watcher.ts +26 -0
  115. package/src/types/incident.ts +57 -0
  116. package/src/types/local-state-backup.ts +121 -0
  117. package/src/types/mcp.ts +106 -0
  118. package/src/types/messaging.ts +35 -0
  119. package/src/types/model-routing.ts +61 -0
  120. package/src/types/mvp-gate.ts +99 -0
  121. package/src/types/orchestration.ts +65 -0
  122. package/src/types/persona-state.ts +61 -0
  123. package/src/types/policy.ts +27 -0
  124. package/src/types/reasoning-graph.ts +58 -0
  125. package/src/types/release.ts +115 -0
  126. package/src/types/reliability.ts +43 -0
  127. package/src/types/runtime-budget.ts +85 -0
  128. package/src/types/scheduler.ts +47 -0
  129. package/src/types/secret-vault.ts +62 -0
  130. package/src/types/skill-packages.ts +81 -0
  131. package/src/types/sqlite-vec.d.ts +5 -0
  132. package/src/types/websocket.ts +122 -0
@@ -0,0 +1,252 @@
1
+ import type { IncidentRecord, IncidentTimelineEntry } from './incident.js';
2
+ import type {
3
+ PersonaStateSnapshot,
4
+ PersonaStateUpdateResult,
5
+ } from './persona-state.js';
6
+ import type {
7
+ LocalStateBackupDiagnostics,
8
+ LocalStateRestoreRequest,
9
+ LocalStateRestoreResult,
10
+ LocalStateSnapshotManifest,
11
+ } from './local-state-backup.js';
12
+ import type {
13
+ RuntimeBudgetAction,
14
+ RuntimeBudgetEvent,
15
+ RuntimeBudgetLimits,
16
+ RuntimeBudgetProfile,
17
+ RuntimeBudgetSeverity,
18
+ RuntimeUsageAggregate,
19
+ RuntimeProviderUsageAggregate,
20
+ } from './runtime-budget.js';
21
+ import type { ModelRoutingFallbackMode, ModelRoutingTelemetrySnapshot } from './model-routing.js';
22
+
23
+ export interface ApiEnvelope<T = unknown> {
24
+ ok: boolean;
25
+ data?: T;
26
+ error?: string;
27
+ correlationId?: string;
28
+ timestamp: string;
29
+ }
30
+
31
+ // ── Config / Env Validation ──────────────────────────────────────────────────
32
+
33
+ export interface ConfigIssueData {
34
+ key: string;
35
+ class: 'missing_required' | 'missing_conditional' | 'format_error';
36
+ message: string;
37
+ remediation: string;
38
+ }
39
+
40
+ export interface ConfigValidationData {
41
+ ok: boolean;
42
+ presentKeys: string[];
43
+ issues: ConfigIssueData[];
44
+ activeFeatures: string[];
45
+ fatalIssues: ConfigIssueData[];
46
+ validatedAt: string;
47
+ }
48
+
49
+ // ── Health ──────────────────────────────────────────────────────────────────
50
+
51
+ export interface HealthData {
52
+ status: 'ok' | 'degraded';
53
+ uptimeSec: number;
54
+ memoryUsageMb: number;
55
+ heartbeat: { running: boolean };
56
+ skills: { builtin: number; mcp: number; total: number };
57
+ skillPackages: {
58
+ installed: number;
59
+ active: number;
60
+ blocked: number;
61
+ warnings: string[];
62
+ violations: Array<{
63
+ packageName: string;
64
+ version: string;
65
+ code: string;
66
+ message: string;
67
+ remediation: string;
68
+ }>;
69
+ };
70
+ secrets?: {
71
+ status: 'ok' | 'degraded';
72
+ missingRequired: string[];
73
+ expired: string[];
74
+ warnings: string[];
75
+ total: number;
76
+ active: number;
77
+ dueForRotation: string[];
78
+ };
79
+ budget?: {
80
+ severity: RuntimeBudgetSeverity;
81
+ profile: RuntimeBudgetProfile;
82
+ pacingDelayMs: number;
83
+ manualProfile: RuntimeBudgetProfile | null;
84
+ daily: RuntimeUsageAggregate;
85
+ session: RuntimeUsageAggregate;
86
+ providers: RuntimeProviderUsageAggregate[];
87
+ };
88
+ routing?: ModelRoutingTelemetrySnapshot;
89
+ backups?: {
90
+ status: 'ok' | 'degraded';
91
+ lastSnapshotAt: string | null;
92
+ lastRestoreAt: string | null;
93
+ validationFailureCount: number;
94
+ recommendationCount: number;
95
+ };
96
+ mcpServers: Array<{
97
+ id: string;
98
+ name: string;
99
+ state: string;
100
+ toolCount: number;
101
+ health?: {
102
+ circuit: string;
103
+ failureCount: number;
104
+ remainingCooldownMs: number;
105
+ };
106
+ }>;
107
+ }
108
+
109
+ // ── Browser ─────────────────────────────────────────────────────────────────
110
+
111
+ export interface BrowserSnapshotRequest {
112
+ url?: string;
113
+ fullPage?: boolean;
114
+ }
115
+
116
+ export interface BrowserReferenceMapEntry {
117
+ ref: string;
118
+ selector: string;
119
+ role: string;
120
+ name: string;
121
+ bounds: {
122
+ x: number;
123
+ y: number;
124
+ width: number;
125
+ height: number;
126
+ };
127
+ }
128
+
129
+ export interface BrowserSnapshotData {
130
+ snapshotId: string;
131
+ screenshotPath: string;
132
+ viewport: { width: number; height: number };
133
+ accessibilityTree: string;
134
+ references: BrowserReferenceMapEntry[];
135
+ }
136
+
137
+ export interface BrowserClickRequest {
138
+ ref?: string;
139
+ snapshotId?: string;
140
+ selector?: string;
141
+ x?: number;
142
+ y?: number;
143
+ }
144
+
145
+ export interface BrowserClickData {
146
+ clicked: true;
147
+ method: 'reference' | 'selector' | 'coordinates';
148
+ detail: string;
149
+ ref?: string;
150
+ snapshotId?: string;
151
+ }
152
+
153
+ // ── Webhook Callback ────────────────────────────────────────────────────────
154
+
155
+ export interface WebhookCallbackPayload {
156
+ eventType: string;
157
+ taskId: string;
158
+ status: 'completed' | 'failed' | 'progress';
159
+ result?: unknown;
160
+ error?: string;
161
+ }
162
+
163
+ export interface WebhookCallbackData {
164
+ accepted: true;
165
+ eventType: string;
166
+ taskId: string;
167
+ outcome?: 'accepted' | 'duplicate';
168
+ }
169
+
170
+ // ── Incident Self-Healing ────────────────────────────────────────────────────
171
+
172
+ export interface IncidentCurrentData {
173
+ safeMode: boolean;
174
+ incidents: IncidentRecord[];
175
+ }
176
+
177
+ export interface IncidentHistoryData {
178
+ incidents: IncidentRecord[];
179
+ timeline: IncidentTimelineEntry[];
180
+ }
181
+
182
+ // ── Persona State ─────────────────────────────────────────────────────────────
183
+
184
+ export type PersonaStateData = PersonaStateSnapshot;
185
+
186
+ export interface PersonaStateUpdateRequest {
187
+ expectedRevision: string;
188
+ soul: string;
189
+ identity: string;
190
+ user: string;
191
+ }
192
+
193
+ export type PersonaStateUpdateData = PersonaStateUpdateResult;
194
+
195
+ export interface PersonaStateErrorDiagnostics {
196
+ hints: string[];
197
+ latestRevision?: string;
198
+ }
199
+
200
+ // ── Local State Backup & Recovery ─────────────────────────────────────────────
201
+
202
+ export interface LocalStateSnapshotRequest {
203
+ retentionLimit?: number;
204
+ }
205
+
206
+ export interface LocalStateSnapshotData {
207
+ snapshot: LocalStateSnapshotManifest;
208
+ }
209
+
210
+ export interface LocalStateRestoreData {
211
+ request: LocalStateRestoreRequest;
212
+ result: LocalStateRestoreResult;
213
+ }
214
+
215
+ export interface LocalStateBackupDiagnosticsData {
216
+ diagnostics: LocalStateBackupDiagnostics;
217
+ }
218
+
219
+ // ── Runtime Budget Governance ────────────────────────────────────────────────
220
+
221
+ export interface BudgetStateData {
222
+ sessionId: string;
223
+ manualProfile: RuntimeBudgetProfile | null;
224
+ limits: RuntimeBudgetLimits;
225
+ daily: RuntimeUsageAggregate;
226
+ session: RuntimeUsageAggregate;
227
+ providers: RuntimeProviderUsageAggregate[];
228
+ directive: {
229
+ profile: RuntimeBudgetProfile;
230
+ severity: RuntimeBudgetSeverity;
231
+ actions: RuntimeBudgetAction[];
232
+ pacingDelayMs: number;
233
+ blockedModelIds: string[];
234
+ blockedProviders: string[];
235
+ reason: string;
236
+ evaluatedAt: string;
237
+ };
238
+ recentEvents: RuntimeBudgetEvent[];
239
+ }
240
+
241
+ // ── Model Routing Telemetry ───────────────────────────────────────────────────
242
+
243
+ export type RoutingTelemetryData = ModelRoutingTelemetrySnapshot;
244
+
245
+ export interface RoutingModeUpdateRequest {
246
+ mode: ModelRoutingFallbackMode;
247
+ }
248
+
249
+ export interface RoutingModeUpdateData {
250
+ message: string;
251
+ snapshot: ModelRoutingTelemetrySnapshot;
252
+ }
@@ -0,0 +1,4 @@
1
+ declare module 'blessed-contrib' {
2
+ const contrib: any;
3
+ export default contrib;
4
+ }
@@ -0,0 +1,76 @@
1
+ import type { Message } from '../core/types.js';
2
+
3
+ export interface ContextBudgetConfig {
4
+ totalBudgetTokens: number;
5
+ systemBudgetTokens: number;
6
+ historyBudgetTokens: number;
7
+ memoryBudgetTokens: number;
8
+ delegationBudgetTokens: number;
9
+ lifecycleBudgetTokens: number;
10
+ hotMessageLimit: number;
11
+ warmMessageLimit: number;
12
+ memoryTopKMin: number;
13
+ memoryTopKMax: number;
14
+ tokensPerMemoryItem: number;
15
+ maxSummaryEntries: number;
16
+ summarySnippetChars: number;
17
+ }
18
+
19
+ export interface IndexedConversationMessage {
20
+ index: number;
21
+ message: Message;
22
+ }
23
+
24
+ export interface ContextSectionResult {
25
+ label: string;
26
+ content: string;
27
+ originalTokens: number;
28
+ usedTokens: number;
29
+ wasCompacted: boolean;
30
+ wasOmitted: boolean;
31
+ note?: string;
32
+ }
33
+
34
+ export interface ContextHistoryStats {
35
+ totalHistoryMessages: number;
36
+ hotMessages: number;
37
+ warmMessages: number;
38
+ archivedMessages: number;
39
+ hotTokens: number;
40
+ warmSummaryTokens: number;
41
+ archivedSummaryTokens: number;
42
+ historyBudgetTokens: number;
43
+ memoryBudgetTokens: number;
44
+ memoryTopK: number;
45
+ wasCompacted: boolean;
46
+ }
47
+
48
+ export interface ContextHistoryPlan {
49
+ hotHistory: Message[];
50
+ warmSummary: string;
51
+ archivedSummary: string;
52
+ memoryTopK: number;
53
+ diagnostics: string[];
54
+ stats: ContextHistoryStats;
55
+ }
56
+
57
+ export interface RuntimeContextStats {
58
+ memoryTokens: number;
59
+ delegationTokens: number;
60
+ warmTokens: number;
61
+ archivedTokens: number;
62
+ totalTokens: number;
63
+ wasCompacted: boolean;
64
+ }
65
+
66
+ export interface RuntimeContextPlan {
67
+ runtimeContext: string;
68
+ diagnostics: string[];
69
+ sections: {
70
+ memory: ContextSectionResult;
71
+ delegation: ContextSectionResult;
72
+ warm: ContextSectionResult;
73
+ archived: ContextSectionResult;
74
+ };
75
+ stats: RuntimeContextStats;
76
+ }
@@ -0,0 +1,29 @@
1
+ export type DoctorCheckKind = 'binary' | 'env-var' | 'filesystem' | 'service-endpoint' | 'channel-auth' | 'config-schema';
2
+
3
+ export type DoctorSeverity = 'critical' | 'warning' | 'info';
4
+
5
+ export interface DoctorCheck {
6
+ kind: DoctorCheckKind;
7
+ name: string;
8
+ description: string;
9
+ severity: DoctorSeverity;
10
+ remediation: string;
11
+ }
12
+
13
+ export interface DoctorCheckResult {
14
+ check: DoctorCheck;
15
+ passed: boolean;
16
+ /** Masked or descriptive actual value when relevant. */
17
+ actual?: string;
18
+ message: string;
19
+ }
20
+
21
+ export type DoctorStatus = 'ok' | 'degraded' | 'critical';
22
+
23
+ export interface DoctorReport {
24
+ status: DoctorStatus;
25
+ results: DoctorCheckResult[];
26
+ checkedAt: string;
27
+ passed: number;
28
+ failed: number;
29
+ }
@@ -0,0 +1,26 @@
1
+ /** Types of filesystem changes the watcher emits. */
2
+ export type FileEventType = 'add' | 'change' | 'unlink' | 'addDir' | 'unlinkDir';
3
+
4
+ /** Normalized filesystem event payload. */
5
+ export interface FileEvent {
6
+ type: FileEventType;
7
+ /** Absolute path of the affected file or directory. */
8
+ path: string;
9
+ /** ISO-8601 timestamp when the event was detected. */
10
+ timestamp: string;
11
+ }
12
+
13
+ /** Callback invoked when a watched filesystem event occurs. */
14
+ export type FileEventListener = (event: FileEvent) => Promise<void> | void;
15
+
16
+ /** Configuration for a watched directory entry. */
17
+ export interface WatchTarget {
18
+ /** Unique label for this watch (e.g. 'workspace', 'identity'). */
19
+ id: string;
20
+ /** Absolute path to the directory to monitor. */
21
+ directory: string;
22
+ /** Glob patterns to include. If omitted, all files are watched. */
23
+ include?: string[];
24
+ /** Glob patterns to exclude (e.g. 'node_modules/**'). */
25
+ exclude?: string[];
26
+ }
@@ -0,0 +1,57 @@
1
+ export type IncidentType =
2
+ | 'queue_backpressure'
3
+ | 'callback_failure_storm'
4
+ | 'context_budget_degradation'
5
+ | 'model_routing_instability';
6
+
7
+ export type IncidentSeverity = 'warning' | 'critical';
8
+
9
+ export type IncidentStatus = 'active' | 'remediating' | 'escalated' | 'resolved';
10
+
11
+ export type IncidentRemediationAction =
12
+ | 'none'
13
+ | 'throttle'
14
+ | 'drain'
15
+ | 'failover'
16
+ | 'retry_window_adjustment'
17
+ | 'halt_safe_mode';
18
+
19
+ export interface IncidentEvidence {
20
+ signal: string;
21
+ observedValue: number;
22
+ threshold: number;
23
+ detail?: string;
24
+ metadata?: Record<string, unknown>;
25
+ }
26
+
27
+ export interface IncidentRecord {
28
+ id: string;
29
+ incidentType: IncidentType;
30
+ severity: IncidentSeverity;
31
+ status: IncidentStatus;
32
+ summary: string;
33
+ evidence: IncidentEvidence[];
34
+ remediationAction: IncidentRemediationAction;
35
+ remediationAttempts: number;
36
+ cooldownUntil: string | null;
37
+ escalated: boolean;
38
+ recommendedActions: string[];
39
+ createdAt: string;
40
+ updatedAt: string;
41
+ resolvedAt: string | null;
42
+ }
43
+
44
+ export interface IncidentTimelineEntry {
45
+ id: string;
46
+ incidentId: string;
47
+ incidentType: IncidentType;
48
+ eventType: string;
49
+ detail: Record<string, unknown>;
50
+ createdAt: string;
51
+ }
52
+
53
+ export interface CallbackOutcomeCounts {
54
+ accepted: number;
55
+ duplicate: number;
56
+ rejected: number;
57
+ }
@@ -0,0 +1,121 @@
1
+ import type { JobSnapshot } from './scheduler.js';
2
+
3
+ export type LocalStateBackupTrigger = 'manual' | 'scheduled';
4
+
5
+ export type LocalStateBackupScope =
6
+ | 'identity'
7
+ | 'memory'
8
+ | 'runtime-db'
9
+ | 'config'
10
+ | 'policy-profiles'
11
+ | 'mcp-config'
12
+ | 'skill-packages';
13
+
14
+ export type LocalStateEntryKind = 'file' | 'directory';
15
+
16
+ export type LocalStateRestoreStatus = 'dry-run' | 'restored' | 'failed';
17
+
18
+ export interface LocalStateSnapshotEntry {
19
+ id: string;
20
+ scope: LocalStateBackupScope;
21
+ relativePath: string;
22
+ kind: LocalStateEntryKind;
23
+ exists: boolean;
24
+ checksum: string | null;
25
+ fileCount: number;
26
+ byteSize: number;
27
+ }
28
+
29
+ export interface LocalStateSnapshotManifest {
30
+ manifestVersion: 1;
31
+ snapshotId: string;
32
+ trigger: LocalStateBackupTrigger;
33
+ createdAt: string;
34
+ retentionLimit: number;
35
+ entries: LocalStateSnapshotEntry[];
36
+ }
37
+
38
+ export interface LocalStateSnapshotRecord {
39
+ snapshotId: string;
40
+ trigger: LocalStateBackupTrigger;
41
+ status: 'ready' | 'failed' | 'pruned';
42
+ scopes: LocalStateBackupScope[];
43
+ entryCount: number;
44
+ manifestPath: string;
45
+ checksum: string | null;
46
+ detail: string | null;
47
+ createdAt: string;
48
+ updatedAt: string;
49
+ }
50
+
51
+ export interface LocalStateValidationIssue {
52
+ entryId: string;
53
+ message: string;
54
+ }
55
+
56
+ export interface LocalStateValidationResult {
57
+ snapshotId: string;
58
+ scopes: LocalStateBackupScope[];
59
+ entries: LocalStateSnapshotEntry[];
60
+ issues: LocalStateValidationIssue[];
61
+ }
62
+
63
+ export interface LocalStateRestoreOptions {
64
+ snapshotId?: string;
65
+ dryRun?: boolean;
66
+ scopes?: LocalStateBackupScope[];
67
+ }
68
+
69
+ export interface LocalStateRestoreResult {
70
+ status: LocalStateRestoreStatus;
71
+ snapshotId: string;
72
+ dryRun: boolean;
73
+ scopes: LocalStateBackupScope[];
74
+ restoredPaths: string[];
75
+ skippedPaths: string[];
76
+ validationErrors: string[];
77
+ rollbackApplied: boolean;
78
+ startedAt: string;
79
+ completedAt: string;
80
+ }
81
+
82
+ export interface LocalStateRestoreEvent {
83
+ id: string;
84
+ snapshotId: string | null;
85
+ outcome: LocalStateRestoreStatus;
86
+ dryRun: boolean;
87
+ scopes: LocalStateBackupScope[];
88
+ restoredPaths: string[];
89
+ skippedPaths: string[];
90
+ validationErrors: string[];
91
+ rollbackApplied: boolean;
92
+ detail: string | null;
93
+ createdAt: string;
94
+ }
95
+
96
+ export interface LocalStateBackupDiagnostics {
97
+ status: 'ok' | 'degraded';
98
+ scheduler: {
99
+ enabled: boolean;
100
+ jobId: string;
101
+ job: JobSnapshot | null;
102
+ cronExpression: string;
103
+ };
104
+ lastSnapshotAt: string | null;
105
+ lastRestoreAt: string | null;
106
+ validationFailureCount: number;
107
+ snapshots: LocalStateSnapshotRecord[];
108
+ restoreEvents: LocalStateRestoreEvent[];
109
+ recommendations: string[];
110
+ }
111
+
112
+ export interface LocalStateSnapshotRequest {
113
+ retentionLimit?: number;
114
+ }
115
+
116
+ export interface LocalStateRestoreRequest {
117
+ snapshotId?: string;
118
+ dryRun?: boolean;
119
+ scopes?: LocalStateBackupScope[];
120
+ }
121
+
@@ -0,0 +1,106 @@
1
+ import type { Tool as McpTool } from '@modelcontextprotocol/sdk/types.js';
2
+
3
+ /** JSON Schema object for describing tool parameters. */
4
+ export interface JsonSchema {
5
+ type: string;
6
+ properties?: Record<string, JsonSchema>;
7
+ required?: string[];
8
+ description?: string;
9
+ items?: JsonSchema;
10
+ enum?: string[];
11
+ default?: unknown;
12
+ [key: string]: unknown;
13
+ }
14
+
15
+ /** Capability scope limiting the operations an MCP tool can perform. */
16
+ export type McpCapabilityScope = 'read-only' | 'write-limited' | 'high-risk' | 'unclassified';
17
+
18
+ /** Configuration for capability scopes on an MCP server. */
19
+ export interface McpServerCapabilities {
20
+ /** Default scope for tools that aren't explicitly configured. @default 'unclassified' -> blocks by default */
21
+ defaultScope?: McpCapabilityScope;
22
+ /** Map of explicit tool names to their granted capability scope. */
23
+ tools?: Record<string, McpCapabilityScope>;
24
+ }
25
+
26
+ /** Transport mechanism for connecting to an MCP server. */
27
+ export type McpTransportType = 'stdio' | 'sse';
28
+
29
+ /** Configuration for a single MCP server connection. */
30
+ export interface McpServerConfig {
31
+ /** Unique identifier for this server (e.g. 'github', 'filesystem'). */
32
+ id: string;
33
+ /** Human-readable name for display. */
34
+ name: string;
35
+ /** Description of what this server provides. */
36
+ description: string;
37
+ /** Transport type. Currently only 'stdio' is implemented. */
38
+ transport: McpTransportType;
39
+ /** Command to launch the server (e.g. 'npx', 'node'). */
40
+ command: string;
41
+ /** Arguments to pass to the command. */
42
+ args: string[];
43
+ /** Optional environment variables to set for the subprocess. */
44
+ env?: Record<string, string>;
45
+ /** Whether to auto-connect this server on startup. @default true */
46
+ autoConnect?: boolean;
47
+ /** Whether this server is currently enabled. @default true */
48
+ enabled?: boolean;
49
+ /** Explicit capability scopes for this server. */
50
+ capabilities?: McpServerCapabilities;
51
+ }
52
+
53
+ /** Top-level configuration file shape for MCP servers. */
54
+ export interface McpConfig {
55
+ servers: McpServerConfig[];
56
+ }
57
+
58
+ /** Represents a tool discovered from an MCP server. */
59
+ export interface McpDiscoveredTool {
60
+ /** Which MCP server this tool came from. */
61
+ serverId: string;
62
+ /** The raw MCP tool metadata from list_tools(). */
63
+ mcpTool: McpTool;
64
+ }
65
+
66
+ /** Connection state for an MCP server. */
67
+ export type McpConnectionState = 'disconnected' | 'connecting' | 'connected' | 'error';
68
+
69
+ /** Health circuit state for an MCP server. */
70
+ export type McpCircuitState = 'closed' | 'open' | 'half-open';
71
+
72
+ /** Health metrics for an MCP server. */
73
+ export interface McpHealthMetrics {
74
+ failureCount: number;
75
+ latencySpikes: number;
76
+ timeoutCount: number;
77
+ lastFailureTime: string | null;
78
+ consecutiveSuccesses: number;
79
+ }
80
+
81
+ /** Read-only snapshot of an MCP server's health. */
82
+ export interface McpHealthSnapshot {
83
+ state: McpCircuitState;
84
+ metrics: McpHealthMetrics;
85
+ remainingCooldownMs: number;
86
+ }
87
+
88
+ /** Read-only snapshot of an MCP server's status. */
89
+ export interface McpServerSnapshot {
90
+ id: string;
91
+ name: string;
92
+ state: McpConnectionState;
93
+ toolCount: number;
94
+ lastError: string | null;
95
+ health: McpHealthSnapshot;
96
+ }
97
+
98
+ /**
99
+ * Minimal audit interface for MCP scope enforcement.
100
+ * Implemented by McpClientAdapter — typed here to break the circular dependency
101
+ * between lane-executor/skills and the services layer.
102
+ */
103
+ export interface McpScopeAuditAdapter {
104
+ auditScopeBlock(sessionId: string | null, toolName: string, scope: string, reason: string): void;
105
+ auditScopeAllow(sessionId: string | null, toolName: string, scope: string): void;
106
+ }