@fulcrum_io/sdk 0.1.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.
@@ -0,0 +1,316 @@
1
+ // Protocol Buffers definition for Python-Go bridge communication
2
+ // See: ADR-007 (Python-Go Bridge Architecture)
3
+
4
+ syntax = "proto3";
5
+
6
+ package fulcrum.bridge.v1;
7
+
8
+ option go_package = "github.com/fulcrum-io/fulcrum/pkg/bridge/v1";
9
+
10
+ // ExecutionRequest initiates a LangGraph StateGraph execution
11
+ message ExecutionRequest {
12
+ // Unique identifier for this execution envelope
13
+ string envelope_id = 1;
14
+
15
+ // Pickled LangGraph StateGraph definition
16
+ // Format: Python pickle protocol 5
17
+ bytes state_graph = 2;
18
+
19
+ // Configuration for LangGraph execution
20
+ // Examples: temperature, max_tokens, recursion_limit
21
+ map<string, string> config = 3;
22
+
23
+ // Enable callback event streaming
24
+ // If false, only completion/error events are sent
25
+ bool enable_callbacks = 4;
26
+
27
+ // Initial state for execution
28
+ // Format: JSON-encoded state dict
29
+ bytes initial_state = 5;
30
+ }
31
+
32
+ // ExecutionResponse acknowledges execution start
33
+ message ExecutionResponse {
34
+ // Execution identifier (same as envelope_id)
35
+ string execution_id = 1;
36
+
37
+ // Python process ID handling this execution
38
+ int32 pid = 2;
39
+
40
+ // Bridge protocol version
41
+ string version = 3;
42
+ }
43
+
44
+ // CallbackEvent streams execution events from Python to Go
45
+ message CallbackEvent {
46
+ // Envelope identifier
47
+ string envelope_id = 1;
48
+
49
+ // Event timestamp (Unix nanoseconds)
50
+ int64 timestamp_ns = 2;
51
+
52
+ // Event payload (one of)
53
+ oneof event {
54
+ LLMStartEvent llm_start = 3;
55
+ LLMEndEvent llm_end = 4;
56
+ LLMErrorEvent llm_error = 5;
57
+ ToolStartEvent tool_start = 6;
58
+ ToolEndEvent tool_end = 7;
59
+ ToolErrorEvent tool_error = 8;
60
+ ChainStartEvent chain_start = 9;
61
+ ChainEndEvent chain_end = 10;
62
+ StreamingChunkEvent streaming_chunk = 11;
63
+ ErrorEvent error = 12;
64
+ CompleteEvent complete = 13;
65
+ }
66
+ }
67
+
68
+ // LLMStartEvent signals LLM call initiation
69
+ message LLMStartEvent {
70
+ // Model identifier (e.g., "gpt-4", "claude-3-opus")
71
+ string model_id = 1;
72
+
73
+ // Prompt text (truncated to 1000 chars for events)
74
+ string prompt_preview = 2;
75
+
76
+ // Call parameters
77
+ map<string, string> parameters = 3;
78
+ }
79
+
80
+ // LLMEndEvent signals LLM call completion
81
+ message LLMEndEvent {
82
+ // Model identifier
83
+ string model_id = 1;
84
+
85
+ // Token usage
86
+ int64 input_tokens = 2;
87
+ int64 output_tokens = 3;
88
+
89
+ // Response latency in milliseconds
90
+ int64 latency_ms = 4;
91
+
92
+ // Cost in USD (if available)
93
+ double cost_usd = 5;
94
+
95
+ // Completion text preview (truncated to 1000 chars)
96
+ string completion_preview = 6;
97
+ }
98
+
99
+ // LLMErrorEvent signals LLM call failure
100
+ message LLMErrorEvent {
101
+ // Model identifier
102
+ string model_id = 1;
103
+
104
+ // Error message
105
+ string error_message = 2;
106
+
107
+ // Error type (e.g., "RateLimitError", "TimeoutError")
108
+ string error_type = 3;
109
+
110
+ // Whether error is recoverable
111
+ bool recoverable = 4;
112
+ }
113
+
114
+ // ToolStartEvent signals tool invocation
115
+ message ToolStartEvent {
116
+ // Tool name
117
+ string tool_name = 1;
118
+
119
+ // Tool input (JSON-encoded)
120
+ bytes input_data = 2;
121
+
122
+ // Tool call identifier
123
+ string tool_call_id = 3;
124
+ }
125
+
126
+ // ToolEndEvent signals tool completion
127
+ message ToolEndEvent {
128
+ // Tool name
129
+ string tool_name = 1;
130
+
131
+ // Tool output (JSON-encoded)
132
+ bytes output_data = 2;
133
+
134
+ // Tool call identifier
135
+ string tool_call_id = 3;
136
+
137
+ // Execution latency in milliseconds
138
+ int64 latency_ms = 4;
139
+ }
140
+
141
+ // ToolErrorEvent signals tool failure
142
+ message ToolErrorEvent {
143
+ // Tool name
144
+ string tool_name = 1;
145
+
146
+ // Tool call identifier
147
+ string tool_call_id = 2;
148
+
149
+ // Error message
150
+ string error_message = 3;
151
+
152
+ // Whether error is recoverable
153
+ bool recoverable = 4;
154
+ }
155
+
156
+ // ChainStartEvent signals StateGraph node start
157
+ message ChainStartEvent {
158
+ // Node name in StateGraph
159
+ string node_name = 1;
160
+
161
+ // Node identifier
162
+ string node_id = 2;
163
+
164
+ // Input state (JSON-encoded, optional)
165
+ bytes input_state = 3;
166
+ }
167
+
168
+ // ChainEndEvent signals StateGraph node completion
169
+ message ChainEndEvent {
170
+ // Node name in StateGraph
171
+ string node_name = 1;
172
+
173
+ // Node identifier
174
+ string node_id = 2;
175
+
176
+ // Output state (JSON-encoded, optional)
177
+ bytes output_state = 3;
178
+ }
179
+
180
+ // StreamingChunkEvent provides streaming token updates
181
+ message StreamingChunkEvent {
182
+ // Model identifier
183
+ string model_id = 1;
184
+
185
+ // Token chunk text
186
+ string chunk = 2;
187
+
188
+ // Chunk index in stream
189
+ int32 chunk_index = 3;
190
+
191
+ // Whether this is the final chunk
192
+ bool is_final = 4;
193
+ }
194
+
195
+ // ErrorEvent signals execution failure
196
+ message ErrorEvent {
197
+ // Error message
198
+ string message = 1;
199
+
200
+ // Python stack trace
201
+ string stack_trace = 2;
202
+
203
+ // Error type (e.g., "ValueError", "RuntimeError")
204
+ string error_type = 3;
205
+
206
+ // Whether error is recoverable
207
+ bool recoverable = 4;
208
+
209
+ // Exit code (if process crashed)
210
+ int32 exit_code = 5;
211
+ }
212
+
213
+ // CompleteEvent signals successful execution completion
214
+ message CompleteEvent {
215
+ // Execution result (pickled Python object)
216
+ bytes result = 1;
217
+
218
+ // Final StateGraph checkpoint (pickled)
219
+ bytes checkpoint = 2;
220
+
221
+ // Total execution time in milliseconds
222
+ int64 total_time_ms = 3;
223
+
224
+ // Final state (JSON-encoded, optional)
225
+ bytes final_state = 4;
226
+ }
227
+
228
+ // TerminateRequest requests execution termination
229
+ message TerminateRequest {
230
+ // Envelope identifier to terminate
231
+ string envelope_id = 1;
232
+
233
+ // Termination reason
234
+ string reason = 2;
235
+
236
+ // Force kill if graceful shutdown fails
237
+ bool force = 3;
238
+
239
+ // Timeout for graceful shutdown (milliseconds)
240
+ int64 timeout_ms = 4;
241
+ }
242
+
243
+ // TerminateResponse confirms termination
244
+ message TerminateResponse {
245
+ // Whether termination succeeded
246
+ bool success = 1;
247
+
248
+ // Termination message
249
+ string message = 2;
250
+
251
+ // Final state before termination (if captured)
252
+ bytes final_state = 3;
253
+ }
254
+
255
+ // CheckpointRequest requests current execution state
256
+ message CheckpointRequest {
257
+ // Envelope identifier
258
+ string envelope_id = 1;
259
+
260
+ // Include full state in response
261
+ bool include_state = 2;
262
+ }
263
+
264
+ // CheckpointResponse returns execution checkpoint
265
+ message CheckpointResponse {
266
+ // Checkpoint data (pickled StateGraph checkpoint)
267
+ bytes checkpoint = 1;
268
+
269
+ // State hash for deduplication
270
+ string state_hash = 2;
271
+
272
+ // Current cost summary
273
+ CostSnapshot cost = 3;
274
+
275
+ // Current state (JSON-encoded, if requested)
276
+ bytes state = 4;
277
+ }
278
+
279
+ // CostSnapshot captures execution cost at checkpoint time
280
+ message CostSnapshot {
281
+ // Total input tokens consumed
282
+ int64 total_input_tokens = 1;
283
+
284
+ // Total output tokens consumed
285
+ int64 total_output_tokens = 2;
286
+
287
+ // Total cost in USD
288
+ double total_cost_usd = 3;
289
+
290
+ // Number of LLM calls
291
+ int32 llm_call_count = 4;
292
+
293
+ // Number of tool calls
294
+ int32 tool_call_count = 5;
295
+ }
296
+
297
+ // HealthCheckRequest pings Python process
298
+ message HealthCheckRequest {
299
+ // Process ID to check (0 for any process)
300
+ int32 pid = 1;
301
+ }
302
+
303
+ // HealthCheckResponse returns process health
304
+ message HealthCheckResponse {
305
+ // Whether process is healthy
306
+ bool healthy = 1;
307
+
308
+ // Process ID
309
+ int32 pid = 2;
310
+
311
+ // Uptime in seconds
312
+ int64 uptime_seconds = 3;
313
+
314
+ // Memory usage in bytes
315
+ int64 memory_bytes = 4;
316
+ }
@@ -0,0 +1,368 @@
1
+ syntax = "proto3";
2
+
3
+ package fulcrum.checkpoint.v1;
4
+
5
+ option go_package = "github.com/fulcrum-io/fulcrum/pkg/checkpoint/v1";
6
+
7
+ import "google/api/annotations.proto";
8
+ import "google/protobuf/timestamp.proto";
9
+ import "google/protobuf/struct.proto";
10
+
11
+ // CheckpointService provides checkpoint persistence and retrieval capabilities.
12
+ // Supports versioning, metadata indexing, and cross-execution context management.
13
+ service CheckpointService {
14
+ // Checkpoint CRUD operations
15
+ rpc SaveCheckpoint(SaveCheckpointRequest) returns (SaveCheckpointResponse) {
16
+ option (google.api.http) = {
17
+ post: "/v1/checkpoints"
18
+ body: "*"
19
+ };
20
+ }
21
+
22
+ rpc GetCheckpoint(GetCheckpointRequest) returns (GetCheckpointResponse) {
23
+ option (google.api.http) = {
24
+ get: "/v1/checkpoints/{checkpoint_id}"
25
+ };
26
+ }
27
+
28
+ rpc ListCheckpoints(ListCheckpointsRequest) returns (ListCheckpointsResponse) {
29
+ option (google.api.http) = {
30
+ get: "/v1/checkpoints"
31
+ };
32
+ }
33
+
34
+ rpc DeleteCheckpoint(DeleteCheckpointRequest) returns (DeleteCheckpointResponse) {
35
+ option (google.api.http) = {
36
+ delete: "/v1/checkpoints/{checkpoint_id}"
37
+ };
38
+ }
39
+
40
+ // Version management
41
+ rpc ListCheckpointVersions(ListCheckpointVersionsRequest) returns (ListCheckpointVersionsResponse) {
42
+ option (google.api.http) = {
43
+ get: "/v1/checkpoints/{execution_id}/versions"
44
+ };
45
+ }
46
+
47
+ rpc GetCheckpointVersion(GetCheckpointVersionRequest) returns (GetCheckpointVersionResponse) {
48
+ option (google.api.http) = {
49
+ get: "/v1/checkpoints/{execution_id}/versions/{version}"
50
+ };
51
+ }
52
+
53
+ // Query operations
54
+ rpc QueryCheckpoints(QueryCheckpointsRequest) returns (QueryCheckpointsResponse) {
55
+ option (google.api.http) = {
56
+ post: "/v1/checkpoints:query"
57
+ body: "*"
58
+ };
59
+ }
60
+
61
+ // Context operations
62
+ rpc GetExecutionContext(GetExecutionContextRequest) returns (GetExecutionContextResponse) {
63
+ option (google.api.http) = {
64
+ get: "/v1/executions/{execution_id}/context"
65
+ };
66
+ }
67
+
68
+ rpc UpdateExecutionContext(UpdateExecutionContextRequest) returns (UpdateExecutionContextResponse) {
69
+ option (google.api.http) = {
70
+ put: "/v1/executions/{execution_id}/context"
71
+ body: "*"
72
+ };
73
+ }
74
+ }
75
+
76
+ // ===== Checkpoint Messages =====
77
+
78
+ // Checkpoint represents a saved execution state
79
+ message Checkpoint {
80
+ // Unique checkpoint identifier
81
+ string checkpoint_id = 1;
82
+
83
+ // Execution identification
84
+ string envelope_id = 2;
85
+ string execution_id = 3;
86
+ string tenant_id = 4;
87
+
88
+ // Versioning
89
+ int32 version = 5;
90
+ string parent_version = 6; // For version chains
91
+
92
+ // Metadata
93
+ CheckpointMetadata metadata = 7;
94
+
95
+ // Checkpoint data (framework-specific state)
96
+ google.protobuf.Struct data = 8;
97
+
98
+ // Timestamps
99
+ google.protobuf.Timestamp created_at = 9;
100
+ google.protobuf.Timestamp expires_at = 10;
101
+
102
+ // Size and performance metrics
103
+ int64 size_bytes = 11;
104
+ int64 save_duration_ms = 12;
105
+ }
106
+
107
+ // CheckpointMetadata contains indexable metadata
108
+ message CheckpointMetadata {
109
+ // Checkpoint type (manual, auto, pre-terminate, etc.)
110
+ CheckpointType type = 1;
111
+
112
+ // Framework information
113
+ string framework_type = 2;
114
+ string framework_version = 3;
115
+
116
+ // Execution state at checkpoint time
117
+ string execution_status = 4;
118
+ int64 step_count = 5;
119
+ string current_node = 6;
120
+
121
+ // Cost snapshot at checkpoint time
122
+ double cost_snapshot_usd = 7;
123
+ int64 tokens_consumed = 8;
124
+
125
+ // Tags for querying
126
+ map<string, string> tags = 9;
127
+
128
+ // User-provided description
129
+ string description = 10;
130
+
131
+ // Compression info
132
+ bool compressed = 11;
133
+ string compression_algorithm = 12;
134
+ }
135
+
136
+ // CheckpointType categorizes checkpoint creation
137
+ enum CheckpointType {
138
+ CHECKPOINT_TYPE_UNSPECIFIED = 0;
139
+ CHECKPOINT_TYPE_MANUAL = 1; // User-triggered
140
+ CHECKPOINT_TYPE_AUTO = 2; // Auto-save interval
141
+ CHECKPOINT_TYPE_PRE_TERMINATE = 3; // Before termination
142
+ CHECKPOINT_TYPE_ERROR = 4; // On error for debugging
143
+ CHECKPOINT_TYPE_MILESTONE = 5; // At important execution points
144
+ }
145
+
146
+ // CheckpointVersion represents a specific version in the history
147
+ message CheckpointVersion {
148
+ string checkpoint_id = 1;
149
+ int32 version = 2;
150
+ string parent_version = 3;
151
+ google.protobuf.Timestamp created_at = 4;
152
+ CheckpointMetadata metadata = 5;
153
+ int64 size_bytes = 6;
154
+ }
155
+
156
+ // ===== Request/Response Messages =====
157
+
158
+ // SaveCheckpoint
159
+ message SaveCheckpointRequest {
160
+ Checkpoint checkpoint = 1;
161
+
162
+ // Options
163
+ bool auto_version = 2; // Automatically increment version
164
+ int32 max_versions = 3; // Max versions to keep (0 = unlimited)
165
+ }
166
+
167
+ message SaveCheckpointResponse {
168
+ string checkpoint_id = 1;
169
+ int32 version = 2;
170
+ google.protobuf.Timestamp created_at = 3;
171
+ }
172
+
173
+ // GetCheckpoint
174
+ message GetCheckpointRequest {
175
+ string checkpoint_id = 1;
176
+
177
+ // Optional: Get specific version (default: latest)
178
+ int32 version = 2;
179
+ }
180
+
181
+ message GetCheckpointResponse {
182
+ Checkpoint checkpoint = 1;
183
+ }
184
+
185
+ // ListCheckpoints
186
+ message ListCheckpointsRequest {
187
+ // Filtering
188
+ string tenant_id = 1;
189
+ string envelope_id = 2;
190
+ string execution_id = 3;
191
+
192
+ // Pagination
193
+ int32 page_size = 4;
194
+ string page_token = 5;
195
+
196
+ // Sorting
197
+ string order_by = 6; // e.g., "created_at desc"
198
+ }
199
+
200
+ message ListCheckpointsResponse {
201
+ repeated Checkpoint checkpoints = 1;
202
+ string next_page_token = 2;
203
+ int32 total_count = 3;
204
+ }
205
+
206
+ // DeleteCheckpoint
207
+ message DeleteCheckpointRequest {
208
+ string checkpoint_id = 1;
209
+
210
+ // Options
211
+ bool soft_delete = 2; // Mark as deleted but keep data
212
+ bool delete_all_versions = 3; // Delete entire version chain
213
+ }
214
+
215
+ message DeleteCheckpointResponse {
216
+ bool success = 1;
217
+ int32 versions_deleted = 2;
218
+ }
219
+
220
+ // ListCheckpointVersions
221
+ message ListCheckpointVersionsRequest {
222
+ string execution_id = 1;
223
+
224
+ // Pagination
225
+ int32 page_size = 2;
226
+ string page_token = 3;
227
+ }
228
+
229
+ message ListCheckpointVersionsResponse {
230
+ repeated CheckpointVersion versions = 1;
231
+ string next_page_token = 2;
232
+ int32 total_count = 3;
233
+ }
234
+
235
+ // GetCheckpointVersion
236
+ message GetCheckpointVersionRequest {
237
+ string execution_id = 1;
238
+ int32 version = 2;
239
+ }
240
+
241
+ message GetCheckpointVersionResponse {
242
+ Checkpoint checkpoint = 1;
243
+ }
244
+
245
+ // QueryCheckpoints
246
+ message QueryCheckpointsRequest {
247
+ // Query filters
248
+ CheckpointQuery query = 1;
249
+
250
+ // Pagination
251
+ int32 page_size = 2;
252
+ string page_token = 3;
253
+
254
+ // Sorting
255
+ string order_by = 4;
256
+ }
257
+
258
+ message QueryCheckpointsResponse {
259
+ repeated Checkpoint checkpoints = 1;
260
+ string next_page_token = 2;
261
+ int32 total_count = 3;
262
+ }
263
+
264
+ // CheckpointQuery defines checkpoint query filters
265
+ message CheckpointQuery {
266
+ // Basic filters
267
+ repeated string tenant_ids = 1;
268
+ repeated string envelope_ids = 2;
269
+ repeated string execution_ids = 3;
270
+
271
+ // Type filter
272
+ repeated CheckpointType types = 4;
273
+
274
+ // Time range
275
+ google.protobuf.Timestamp created_after = 5;
276
+ google.protobuf.Timestamp created_before = 6;
277
+
278
+ // Framework filter
279
+ repeated string framework_types = 7;
280
+
281
+ // Tag filters (AND logic)
282
+ map<string, string> tags = 8;
283
+
284
+ // Cost range
285
+ double min_cost_usd = 9;
286
+ double max_cost_usd = 10;
287
+
288
+ // Size range
289
+ int64 min_size_bytes = 11;
290
+ int64 max_size_bytes = 12;
291
+ }
292
+
293
+ // ===== Context Management Messages =====
294
+
295
+ // ExecutionContext represents cross-execution shared state
296
+ message ExecutionContext {
297
+ string execution_id = 1;
298
+ string tenant_id = 2;
299
+ string workflow_id = 3;
300
+
301
+ // Context scope
302
+ ContextScope scope = 4;
303
+
304
+ // Context data
305
+ google.protobuf.Struct data = 5;
306
+
307
+ // Inheritance
308
+ string parent_execution_id = 6;
309
+ repeated string inherited_keys = 7;
310
+
311
+ // Versioning for conflict resolution
312
+ int64 version = 8;
313
+ google.protobuf.Timestamp updated_at = 9;
314
+ }
315
+
316
+ // ContextScope defines context visibility
317
+ enum ContextScope {
318
+ CONTEXT_SCOPE_UNSPECIFIED = 0;
319
+ CONTEXT_SCOPE_EXECUTION = 1; // Visible to this execution only
320
+ CONTEXT_SCOPE_WORKFLOW = 2; // Visible to all executions in workflow
321
+ CONTEXT_SCOPE_TENANT = 3; // Visible to all executions for tenant
322
+ }
323
+
324
+ // GetExecutionContext
325
+ message GetExecutionContextRequest {
326
+ string execution_id = 1;
327
+
328
+ // Optional: Get specific keys only
329
+ repeated string keys = 2;
330
+
331
+ // Include inherited context
332
+ bool include_inherited = 3;
333
+ }
334
+
335
+ message GetExecutionContextResponse {
336
+ ExecutionContext context = 1;
337
+ }
338
+
339
+ // UpdateExecutionContext
340
+ message UpdateExecutionContextRequest {
341
+ string execution_id = 1;
342
+
343
+ // Updates to apply (merge into existing context)
344
+ google.protobuf.Struct updates = 2;
345
+
346
+ // Keys to delete
347
+ repeated string delete_keys = 3;
348
+
349
+ // Conflict resolution
350
+ int64 expected_version = 4; // For optimistic locking
351
+ MergeStrategy merge_strategy = 5;
352
+ }
353
+
354
+ message UpdateExecutionContextResponse {
355
+ ExecutionContext context = 1;
356
+ bool conflict_detected = 2;
357
+ string conflict_resolution = 3;
358
+ }
359
+
360
+ // MergeStrategy defines how to handle concurrent updates
361
+ enum MergeStrategy {
362
+ MERGE_STRATEGY_UNSPECIFIED = 0;
363
+ MERGE_STRATEGY_LAST_WRITE_WINS = 1;
364
+ MERGE_STRATEGY_FAIL_ON_CONFLICT = 2;
365
+ MERGE_STRATEGY_MERGE_RECURSIVE = 3;
366
+ MERGE_STRATEGY_CUSTOM = 4;
367
+ }
368
+