diff --git a/docs/internal/events.md b/docs/internal/events.md index 2920159e0..dfc7403b4 100644 --- a/docs/internal/events.md +++ b/docs/internal/events.md @@ -77,7 +77,7 @@ Emitted when the run record is created. | `source_directory` | string? | Submitter-side source directory | | `workflow_slug` | string? | Workflow slug | | `provenance` | object | Actor and request provenance | -| `manifest_blob` | string? | Blob id for the submitted manifest | +| `manifest_blob` | string? | Blob hash for the submitted manifest | | `git` | object? | Git provenance observed before the run: normalized `origin_url`, `branch`, optional `sha`, and `dirty` status | | `fork_source_ref` | object? | Source run/checkpoint reference when this run was forked | | `in_place` | boolean | Whether the run was created with `--in-place` (no git checkpoints) | diff --git a/docs/public/agents/outputs.mdx b/docs/public/agents/outputs.mdx index b36259b25..004c4f0e8 100644 --- a/docs/public/agents/outputs.mdx +++ b/docs/public/agents/outputs.mdx @@ -219,10 +219,10 @@ When Fabro builds a [preamble](/execution/context#preamble-construction) for a d - **plan**: success - Model: claude-sonnet-4-5, 12.4k tokens in / 3.2k out - Files: src/main.rs, tests/api_test.rs - - Response: See: /path/to/runtime/blobs/.json + - Response: See: /path/to/runtime/blobs/.json - **test**: success - Script: `cargo test 2>&1 || true` - - Stdout: See: /path/to/runtime/blobs/.json + - Stdout: See: /path/to/runtime/blobs/.json ``` This keeps preambles concise while still giving agents a path to read the full output if needed. @@ -237,7 +237,7 @@ Captured stage artifacts such as screenshots, videos, reports, and traces still For remote sandboxes (Docker, Daytona), execution-time file access happens inside the sandbox filesystem. -- Blob refs are materialized into `{working_directory}/.fabro/blobs/{blob_id}.json` +- Blob refs are materialized into `{working_directory}/.fabro/blobs/{blob_hash}.json` - Explicit non-blob `file://` refs keep the existing copy-on-demand behavior and are copied into `{working_directory}/.fabro/artifacts/{filename}` when needed In both cases, downstream handlers and agents continue to consume ordinary `file://` pointers during execution. diff --git a/docs/public/api-reference/fabro-api.yaml b/docs/public/api-reference/fabro-api.yaml index 274282e72..b788fd713 100644 --- a/docs/public/api-reference/fabro-api.yaml +++ b/docs/public/api-reference/fabro-api.yaml @@ -3092,7 +3092,7 @@ paths: operationId: writeRunBlob tags: [Run Internals] summary: Write Run Blob - description: Writes an opaque binary blob and returns its content-addressed blob identifier. + description: Writes an opaque binary blob and returns its content-addressed blob hash. parameters: - $ref: "#/components/parameters/RunId" requestBody: @@ -3137,15 +3137,15 @@ paths: schema: $ref: "#/components/schemas/ErrorResponse" - /api/v1/runs/{id}/blobs/{blobId}: + /api/v1/runs/{id}/blobs/{blobHash}: get: operationId: readRunBlob tags: [Run Internals] summary: Read Run Blob - description: Reads a previously stored blob by identifier. + description: Reads a previously stored blob by hash. parameters: - $ref: "#/components/parameters/RunId" - - $ref: "#/components/parameters/BlobId" + - $ref: "#/components/parameters/BlobHash" responses: "200": description: Blob contents @@ -5974,11 +5974,11 @@ components: default: 65536 example: 65536 - BlobId: - name: blobId + BlobHash: + name: blobHash in: path required: true - description: Content-addressed blob identifier. + description: Content-addressed blob hash. schema: type: string pattern: '^[0-9a-f]{64}$' @@ -10284,15 +10284,15 @@ components: example: 42 WriteBlobResponse: - description: Content-addressed identifier for a stored blob. + description: Content-addressed hash of a stored blob. type: object required: - - id + - hash properties: - id: + hash: type: string - description: Blob identifier. - example: 550e8400-e29b-41d4-a716-446655440000 + description: Content-addressed hash of the stored blob. + example: 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 CommandTermination: description: Terminal state for a command execution. diff --git a/docs/public/execution/context.mdx b/docs/public/execution/context.mdx index 2ef5b0bbb..19f9c1d2c 100644 --- a/docs/public/execution/context.mdx +++ b/docs/public/execution/context.mdx @@ -243,8 +243,8 @@ Checkpoints and checkpoint-completed events persist these `blob://` refs, not ho Before Fabro builds a preamble or starts the next stage, it resolves any blob refs into execution-local files so handlers and agents still see normal `file://` references: -- Local execution materializes blobs under `{run_dir}/runtime/blobs/{blob_id}.json` -- Remote sandboxes materialize blobs under `{working_directory}/.fabro/blobs/{blob_id}.json` +- Local execution materializes blobs under `{run_dir}/runtime/blobs/{blob_hash}.json` +- Remote sandboxes materialize blobs under `{working_directory}/.fabro/blobs/{blob_hash}.json` These materialized `file://` paths are runtime-only. They are not written back into durable context snapshots. diff --git a/lib/apps/fabro-cli/src/commands/dump.rs b/lib/apps/fabro-cli/src/commands/dump.rs index b3938e12a..9c0454da8 100644 --- a/lib/apps/fabro-cli/src/commands/dump.rs +++ b/lib/apps/fabro-cli/src/commands/dump.rs @@ -86,8 +86,8 @@ async fn write_run_dump( dump.add_file_bytes("run.log", log); } - dump.hydrate_referenced_blobs_with_reader(|blob_id| { - Box::pin(async move { client.read_run_blob(run_id, &blob_id).await }) + dump.hydrate_referenced_blobs_with_reader(|blob_hash| { + Box::pin(async move { client.read_run_blob(run_id, &blob_hash).await }) }) .await?; diff --git a/lib/apps/fabro-cli/src/commands/run/output.rs b/lib/apps/fabro-cli/src/commands/run/output.rs index 0e5ba2d42..14d0e7c6f 100644 --- a/lib/apps/fabro-cli/src/commands/run/output.rs +++ b/lib/apps/fabro-cli/src/commands/run/output.rs @@ -325,11 +325,11 @@ async fn resolve_response_string( run_id: &RunId, response: &str, ) -> Result> { - let Some(blob_id) = blob_id_from_response(response) else { + let Some(blob_hash) = blob_hash_from_response(response) else { return Ok(Some(response.to_string())); }; - let Some(bytes) = client.read_run_blob(run_id, &blob_id).await? else { + let Some(bytes) = client.read_run_blob(run_id, &blob_hash).await? else { return Ok(None); }; let value: serde_json::Value = @@ -341,7 +341,7 @@ async fn resolve_response_string( })) } -fn blob_id_from_response(response: &str) -> Option { +fn blob_hash_from_response(response: &str) -> Option { parse_blob_ref(response) } diff --git a/lib/apps/fabro-cli/src/commands/run/runner.rs b/lib/apps/fabro-cli/src/commands/run/runner.rs index 446888e7e..72044458d 100644 --- a/lib/apps/fabro-cli/src/commands/run/runner.rs +++ b/lib/apps/fabro-cli/src/commands/run/runner.rs @@ -1022,8 +1022,8 @@ impl RunStoreBackend for HttpRunStore { self.with_retries("read run blob", || { let client = self.client.clone_for_reuse(); let run_id = self.run_id; - let blob_id = *id; - async move { client.read_run_blob(&run_id, &blob_id).await } + let blob_hash = *id; + async move { client.read_run_blob(&run_id, &blob_hash).await } }) .await } diff --git a/lib/apps/fabro-cli/tests/it/cmd/attach.rs b/lib/apps/fabro-cli/tests/it/cmd/attach.rs index 813bf7424..c2434f79d 100644 --- a/lib/apps/fabro-cli/tests/it/cmd/attach.rs +++ b/lib/apps/fabro-cli/tests/it/cmd/attach.rs @@ -70,13 +70,13 @@ fn normalize_attach_json_progress_event(mut event: Value) -> Value { if properties.contains_key("manifest_blob") { properties.insert( "manifest_blob".to_string(), - Value::String("[BLOB_ID]".to_string()), + Value::String("[BLOB_HASH]".to_string()), ); } if properties.contains_key("definition_blob") { properties.insert( "definition_blob".to_string(), - Value::String("[BLOB_ID]".to_string()), + Value::String("[BLOB_HASH]".to_string()), ); } } @@ -896,7 +896,7 @@ fn attach_json_errors_without_prompting_for_human_input() { } } }, - "manifest_blob": "[BLOB_ID]", + "manifest_blob": "[BLOB_HASH]", "provenance": { "client": { "name": "fabro-cli", @@ -1036,7 +1036,7 @@ fn attach_json_errors_without_prompting_for_human_input() { "event": "run.submitted", "id": "[EVENT_ID]", "properties": { - "definition_blob": "[BLOB_ID]" + "definition_blob": "[BLOB_HASH]" }, "run_id": "[ULID]", "ts": "[TIMESTAMP]" diff --git a/lib/apps/fabro-server/src/principal_middleware.rs b/lib/apps/fabro-server/src/principal_middleware.rs index 2db165547..3d9bb0542 100644 --- a/lib/apps/fabro-server/src/principal_middleware.rs +++ b/lib/apps/fabro-server/src/principal_middleware.rs @@ -14,7 +14,7 @@ use strum::IntoStaticStr; use crate::auth::{AuthErrorCode, JwtError, REFRESH_TOKEN_PREFIX}; use crate::error::ApiError; use crate::jwt_auth::{self, AuthMode, ConfiguredAuth}; -use crate::server::{AppState, parse_blob_id_path, parse_run_id_path, parse_stage_id_path}; +use crate::server::{AppState, parse_blob_hash_path, parse_run_id_path, parse_stage_id_path}; use crate::worker_token::{self, WORKER_TOKEN_KID, WorkerScopeSet}; #[derive(Clone, Debug)] @@ -295,14 +295,14 @@ impl FromRequestParts> for RequireRunBlob { parts: &mut Parts, state: &Arc, ) -> Result { - let Path((id, blob_id)): Path<(String, String)> = Path::from_request_parts(parts, state) + let Path((id, blob_hash)): Path<(String, String)> = Path::from_request_parts(parts, state) .await .map_err(IntoResponse::into_response)?; let run_id = parse_run_id_path(&id)?; - let blob_id = parse_blob_id_path(&blob_id)?; + let blob_hash = parse_blob_hash_path(&blob_hash)?; require_worker_or_user_for_run(&auth_slot_from_parts(parts), &run_id) .map_err(IntoResponse::into_response)?; - Ok(Self(run_id, blob_id)) + Ok(Self(run_id, blob_hash)) } } diff --git a/lib/apps/fabro-server/src/server.rs b/lib/apps/fabro-server/src/server.rs index fa8af18c8..67ae1f32f 100644 --- a/lib/apps/fabro-server/src/server.rs +++ b/lib/apps/fabro-server/src/server.rs @@ -2889,11 +2889,11 @@ pub(crate) fn parse_stage_id_path(stage_id: &str) -> Result { #[allow( clippy::result_large_err, - reason = "Blob ID parsing returns HTTP 400 responses directly." + reason = "Blob hash parsing returns HTTP 400 responses directly." )] -pub(crate) fn parse_blob_id_path(blob_id: &str) -> Result { - BlobHash::from_str(blob_id) - .map_err(|_| ApiError::bad_request("Invalid blob ID.").into_response()) +pub(crate) fn parse_blob_hash_path(blob_hash: &str) -> Result { + BlobHash::from_str(blob_hash) + .map_err(|_| ApiError::bad_request("Invalid blob hash.").into_response()) } #[allow( diff --git a/lib/apps/fabro-server/src/server/handler/artifacts.rs b/lib/apps/fabro-server/src/server/handler/artifacts.rs index f426a0007..c203bdec0 100644 --- a/lib/apps/fabro-server/src/server/handler/artifacts.rs +++ b/lib/apps/fabro-server/src/server/handler/artifacts.rs @@ -32,7 +32,7 @@ pub(super) fn routes() -> Router> { Router::new() .route("/runs/{id}/checkpoint", get(get_checkpoint)) .route("/runs/{id}/blobs", post(write_run_blob)) - .route("/runs/{id}/blobs/{blobId}", get(read_run_blob)) + .route("/runs/{id}/blobs/{blobHash}", get(read_run_blob)) .route("/runs/{id}/artifacts", get(list_run_artifacts)) .route("/runs/{id}/artifacts/download", get(download_run_artifacts)) .route( @@ -105,8 +105,8 @@ async fn write_run_blob( } match state.stores.runs.open_run(&id).await { Ok(run_store) => match run_store.write_blob(&body).await { - Ok(blob_id) => Json(WriteBlobResponse { - id: blob_id.to_string(), + Ok(blob_hash) => Json(WriteBlobResponse { + hash: blob_hash.to_string(), }) .into_response(), Err(err) => { @@ -118,11 +118,11 @@ async fn write_run_blob( } async fn read_run_blob( - RequireRunBlob(id, blob_id): RequireRunBlob, + RequireRunBlob(id, blob_hash): RequireRunBlob, State(state): State>, ) -> Response { match state.stores.runs.open_run_reader(&id).await { - Ok(run_store) => match run_store.read_blob(&blob_id).await { + Ok(run_store) => match run_store.read_blob(&blob_hash).await { Ok(Some(bytes)) => octet_stream_response(bytes), Ok(None) => ApiError::not_found("Blob not found.").into_response(), Err(err) => { diff --git a/lib/apps/fabro-server/src/server/handler/mod.rs b/lib/apps/fabro-server/src/server/handler/mod.rs index bcb7f9ef1..d42999c74 100644 --- a/lib/apps/fabro-server/src/server/handler/mod.rs +++ b/lib/apps/fabro-server/src/server/handler/mod.rs @@ -101,7 +101,7 @@ pub(super) fn demo_routes() -> Router> { ) .route("/runs/{id}/attach", get(demo::run_events_stub)) .route("/runs/{id}/blobs", post(not_implemented)) - .route("/runs/{id}/blobs/{blobId}", get(not_implemented)) + .route("/runs/{id}/blobs/{blobHash}", get(not_implemented)) .route( "/runs/{id}/stages/{stageId}/logs/output", get(not_implemented), diff --git a/lib/apps/fabro-server/src/server/tests.rs b/lib/apps/fabro-server/src/server/tests.rs index 2ffec61de..f97892272 100644 --- a/lib/apps/fabro-server/src/server/tests.rs +++ b/lib/apps/fabro-server/src/server/tests.rs @@ -11057,11 +11057,11 @@ async fn write_and_read_run_blob_round_trip() { .unwrap(); let response = app.clone().oneshot(req).await.unwrap(); let body = response_json!(response, StatusCode::OK).await; - let blob_id = body["id"].as_str().unwrap(); + let blob_hash = body["hash"].as_str().unwrap(); let req = Request::builder() .method("GET") - .uri(api(&format!("/runs/{run_id}/blobs/{blob_id}"))) + .uri(api(&format!("/runs/{run_id}/blobs/{blob_hash}"))) .body(Body::empty()) .unwrap(); let response = app.oneshot(req).await.unwrap(); @@ -11459,7 +11459,7 @@ async fn worker_token_accepts_run_scoped_routes_and_falls_back_to_user_jwt() { let worker_token = issue_test_worker_token(&run_id); let other_run_id = create_run_with_bearer(&app, &user_jwt).await; let other_worker_token = issue_test_worker_token(&other_run_id); - let blob_id = state + let blob_hash = state .stores .runs .open_run(&run_id) @@ -11553,7 +11553,7 @@ async fn worker_token_accepts_run_scoped_routes_and_falls_back_to_user_jwt() { .clone() .oneshot(bearer_request( Method::GET, - &format!("/runs/{run_id}/blobs/{blob_id}"), + &format!("/runs/{run_id}/blobs/{blob_hash}"), &worker_token, Body::empty(), )) @@ -12058,7 +12058,7 @@ async fn worker_token_is_rejected_on_user_only_routes() { let user_jwt = issue_test_user_jwt(); let run_id = create_run_with_bearer(&app, &user_jwt).await; let worker_token = issue_test_worker_token(&run_id); - let blob_id = BlobHash::new(b"blob"); + let blob_hash = BlobHash::new(b"blob"); let user_only_routes = vec![ (Method::GET, "/runs".to_string()), (Method::POST, "/runs".to_string()), @@ -12121,7 +12121,7 @@ async fn worker_token_is_rejected_on_user_only_routes() { .clone() .oneshot(bearer_request( Method::GET, - &format!("/runs/{run_id}/blobs/{blob_id}"), + &format!("/runs/{run_id}/blobs/{blob_hash}"), &worker_token, Body::empty(), )) diff --git a/lib/components/fabro-dump/src/lib.rs b/lib/components/fabro-dump/src/lib.rs index 1028408e0..9210a695d 100644 --- a/lib/components/fabro-dump/src/lib.rs +++ b/lib/components/fabro-dump/src/lib.rs @@ -214,30 +214,30 @@ impl RunDump { for entry in &mut self.entries { match &mut entry.contents { RunDumpContents::Json(value) => { - let mut blob_ids = Vec::new(); - collect_blob_refs_in_value(value, &mut blob_ids); - for blob_id in blob_ids { - if cache.contains_key(&blob_id) { + let mut blob_hashes = Vec::new(); + collect_blob_refs_in_value(value, &mut blob_hashes); + for blob_hash in blob_hashes { + if cache.contains_key(&blob_hash) { continue; } - let blob = read_blob(blob_id).await?.with_context(|| { - format!("blob {blob_id:?} is missing from the store") + let blob = read_blob(blob_hash).await?.with_context(|| { + format!("blob {blob_hash:?} is missing from the store") })?; let hydrated: serde_json::Value = serde_json::from_slice(&blob) - .with_context(|| format!("blob {blob_id:?} is not valid JSON"))?; - cache.insert(blob_id, hydrated); + .with_context(|| format!("blob {blob_hash:?} is not valid JSON"))?; + cache.insert(blob_hash, hydrated); } replace_blob_refs_in_value(value, &cache)?; } RunDumpContents::Text(text) => { - let Some(blob_id) = parse_blob_ref(text) else { + let Some(blob_hash) = parse_blob_ref(text) else { continue; }; - let blob = read_blob(blob_id) + let blob = read_blob(blob_hash) .await? - .with_context(|| format!("blob {blob_id:?} is missing from the store"))?; + .with_context(|| format!("blob {blob_hash:?} is missing from the store"))?; *text = serde_json::from_slice::(&blob).with_context(|| { - format!("blob {blob_id:?} is not a JSON string text log") + format!("blob {blob_hash:?} is not a JSON string text log") })?; } RunDumpContents::Bytes(_) => {} @@ -386,21 +386,21 @@ fn validate_relative_path(kind: &str, value: &str) -> Result { Ok(normalized) } -fn collect_blob_refs_in_value(value: &serde_json::Value, blob_ids: &mut Vec) { +fn collect_blob_refs_in_value(value: &serde_json::Value, blob_hashes: &mut Vec) { match value { serde_json::Value::String(current) => { - if let Some(blob_id) = parse_blob_ref(current) { - blob_ids.push(blob_id); + if let Some(blob_hash) = parse_blob_ref(current) { + blob_hashes.push(blob_hash); } } serde_json::Value::Array(items) => { for item in items { - collect_blob_refs_in_value(item, blob_ids); + collect_blob_refs_in_value(item, blob_hashes); } } serde_json::Value::Object(map) => { for item in map.values() { - collect_blob_refs_in_value(item, blob_ids); + collect_blob_refs_in_value(item, blob_hashes); } } serde_json::Value::Null | serde_json::Value::Bool(_) | serde_json::Value::Number(_) => {} @@ -413,13 +413,12 @@ fn replace_blob_refs_in_value( ) -> Result<()> { match value { serde_json::Value::String(current) => { - let Some(blob_id) = parse_blob_ref(current) else { + let Some(blob_hash) = parse_blob_ref(current) else { return Ok(()); }; - let hydrated = cache - .get(&blob_id) - .cloned() - .with_context(|| format!("blob {blob_id:?} is missing from the hydration cache"))?; + let hydrated = cache.get(&blob_hash).cloned().with_context(|| { + format!("blob {blob_hash:?} is missing from the hydration cache") + })?; *value = hydrated; } serde_json::Value::Array(items) => { @@ -724,8 +723,8 @@ mod tests { #[test] fn hydrate_referenced_blobs_ignores_legacy_artifact_file_refs() { let blob = serde_json::to_vec("hydrated legacy text").unwrap(); - let blob_id = fabro_types::BlobHash::new(&blob); - let legacy_ref = format!("file:///sandbox/.fabro/artifacts/{blob_id}.json"); + let blob_hash = fabro_types::BlobHash::new(&blob); + let legacy_ref = format!("file:///sandbox/.fabro/artifacts/{blob_hash}.json"); let mut dump = RunDump { entries: vec![RunDumpEntry::json( "run.json", @@ -736,10 +735,10 @@ mod tests { }; executor::block_on(async { - dump.hydrate_referenced_blobs_with_reader(|read_blob_id| { + dump.hydrate_referenced_blobs_with_reader(|read_blob_hash| { let blob = blob.clone(); Box::pin(async move { - assert_eq!(read_blob_id, blob_id); + assert_eq!(read_blob_hash, blob_hash); Ok(Some(bytes::Bytes::from(blob))) }) }) diff --git a/lib/components/fabro-store/src/slate/mod.rs b/lib/components/fabro-store/src/slate/mod.rs index 21e410c71..e0b66d6e8 100644 --- a/lib/components/fabro-store/src/slate/mod.rs +++ b/lib/components/fabro-store/src/slate/mod.rs @@ -836,12 +836,12 @@ mod tests { append_created(&run_2, "run-2", dt("2026-03-27T12:00:10Z")).await; let shared_blob = br#"{"summary":"shared"}"#; - let shared_blob_id = run_1.write_blob(shared_blob).await.unwrap(); + let shared_blob_hash = run_1.write_blob(shared_blob).await.unwrap(); store.delete_run(&test_run_id("run-1")).await.unwrap(); let reopened = store.open_run(&test_run_id("run-2")).await.unwrap(); - let read = reopened.read_blob(&shared_blob_id).await.unwrap(); + let read = reopened.read_blob(&shared_blob_hash).await.unwrap(); assert_eq!(read.as_deref(), Some(shared_blob.as_slice())); } @@ -851,7 +851,7 @@ mod tests { let run = store.create_run(&test_run_id("run-1")).await.unwrap(); append_created(&run, "run-1", dt("2026-03-27T12:00:00Z")).await; let blob = br#"{"summary":"readable"}"#; - let blob_id = run.write_blob(blob).await.unwrap(); + let blob_hash = run.write_blob(blob).await.unwrap(); // Evict the cached writer so the reader is built through the real // `open_run_reader` construction path, not a clone of the writer. @@ -859,7 +859,7 @@ mod tests { let reader = store.open_run_reader(&test_run_id("run-1")).await.unwrap(); assert_eq!( - reader.read_blob(&blob_id).await.unwrap().as_deref(), + reader.read_blob(&blob_hash).await.unwrap().as_deref(), Some(blob.as_slice()) ); let err = reader.write_blob(b"blocked").await.unwrap_err(); diff --git a/lib/components/fabro-workflow-version/src/store.rs b/lib/components/fabro-workflow-version/src/store.rs index 80dcebd53..47a8c6299 100644 --- a/lib/components/fabro-workflow-version/src/store.rs +++ b/lib/components/fabro-workflow-version/src/store.rs @@ -86,10 +86,10 @@ impl WorkflowVersionStore { &self, id: &WorkflowVersionId, ) -> Result, WorkflowVersionStoreError> { - let blob_id = (*id).into(); + let blob_hash = (*id).into(); let Some(bytes) = self .blobs - .read(&blob_id) + .read(&blob_hash) .await .map_err(|source| WorkflowVersionStoreError::Storage { source })? else { @@ -201,8 +201,11 @@ mod tests { let id = store.put(&version).await.unwrap(); assert_eq!(id, expected_id); - let blob_id = id.into(); - assert_eq!(blobs.read(&blob_id).await.unwrap().unwrap(), expected_bytes); + let blob_hash = id.into(); + assert_eq!( + blobs.read(&blob_hash).await.unwrap().unwrap(), + expected_bytes + ); assert_eq!(store.get(&id).await.unwrap(), Some(version)); } diff --git a/lib/components/fabro-workflow/src/artifact.rs b/lib/components/fabro-workflow/src/artifact.rs index ef892b442..a35714064 100644 --- a/lib/components/fabro-workflow/src/artifact.rs +++ b/lib/components/fabro-workflow/src/artifact.rs @@ -26,7 +26,7 @@ const ARTIFACT_POINTER_PREFIX: &str = "file://"; /// /// For each entry in `updates` whose serialized JSON exceeds /// `BLOB_OFFLOAD_THRESHOLD`, the value is persisted as a blob in `run_store` -/// and replaced with a `"blob://sha256/{blob_id}"` reference. +/// and replaced with a `"blob://sha256/{blob_hash}"` reference. /// Small values are left untouched. /// /// `parallel.results` is offloaded at each branch context-update boundary @@ -102,11 +102,11 @@ async fn offload_value(value: &mut Value, run_store: &RunStoreHandle) -> Result< .map_err(|e| Error::engine_with_source("artifact serialize failed", e))?; if bytes.len() > BLOB_OFFLOAD_THRESHOLD { - let blob_id = run_store + let blob_hash = run_store .write_blob(&bytes) .await .map_err(|e| Error::engine_with_anyhow("artifact blob write failed", e))?; - *value = Value::String(format_blob_ref(&blob_id)); + *value = Value::String(format_blob_ref(&blob_hash)); } Ok(()) } @@ -232,17 +232,17 @@ pub async fn resolve_text_or_blob_ref(value: &Value, run_store: &RunStoreHandle) /// blob reference. /// /// Managed `file://` references are normalized through their content-addressed -/// blob id instead of reading an execution-local path. Ordinary strings and +/// blob hash instead of reading an execution-local path. Ordinary strings and /// ordinary file references remain unchanged for the caller to validate. pub(crate) async fn resolve_json_value(value: Value, run_store: &RunStoreHandle) -> Result { - let blob_id = value.as_str().and_then(|reference| { + let blob_hash = value.as_str().and_then(|reference| { parse_blob_ref(reference).or_else(|| parse_managed_blob_file_ref(reference)) }); - let Some(blob_id) = blob_id else { + let Some(blob_hash) = blob_hash else { return Ok(value); }; - let bytes = read_required_blob(&blob_id, run_store).await?; + let bytes = read_required_blob(&blob_hash, run_store).await?; serde_json::from_slice(&bytes) .map_err(|err| Error::engine_with_source("artifact blob was not valid JSON", err)) } @@ -267,14 +267,14 @@ pub async fn resolve_text_or_blob_ref_str( current: &str, run_store: &RunStoreHandle, ) -> Result { - let Some(blob_id) = parse_blob_ref(current) else { + let Some(blob_hash) = parse_blob_ref(current) else { return Ok(current.to_string()); }; let bytes = run_store - .read_blob(&blob_id) + .read_blob(&blob_hash) .await .map_err(|e| Error::engine_with_anyhow("text blob read failed", e))? - .ok_or_else(|| Error::engine(format!("text blob missing: {blob_id}")))?; + .ok_or_else(|| Error::engine(format!("text blob missing: {blob_hash}")))?; serde_json::from_slice::(&bytes) .map_err(|e| Error::engine_with_source("text blob was not a JSON string", e)) } @@ -334,8 +334,8 @@ pub async fn sync_artifacts_to_env( fn normalize_durable_value(value: &mut Value) { match value { Value::String(current) => { - if let Some(blob_id) = parse_managed_blob_file_ref(current) { - *current = format_blob_ref(&blob_id); + if let Some(blob_hash) = parse_managed_blob_file_ref(current) { + *current = format_blob_ref(&blob_hash); } } Value::Array(items) => { @@ -382,8 +382,8 @@ fn resolve_execution_value<'a>( Value::String(current) => { if key.is_some_and(is_text_context_key) { *current = resolve_text_or_blob_ref_str(current, run_store).await?; - } else if let Some(blob_id) = parse_blob_ref(current) { - *current = materialize_blob_ref(&blob_id, run_store, env, run_dir).await?; + } else if let Some(blob_hash) = parse_blob_ref(current) { + *current = materialize_blob_ref(&blob_hash, run_store, env, run_dir).await?; } else if current.starts_with(ARTIFACT_POINTER_PREFIX) && parse_managed_blob_file_ref(current).is_none() { @@ -413,7 +413,7 @@ fn resolve_execution_value<'a>( } async fn materialize_blob_ref( - blob_id: &BlobHash, + blob_hash: &BlobHash, run_store: &RunStoreHandle, env: &dyn Sandbox, run_dir: &Path, @@ -421,9 +421,9 @@ async fn materialize_blob_ref( // Blobs are content-addressed, so an existing materialized file is always // current — check before paying for the store read. if is_local_execution(env, run_dir).await? { - let path = local_materialized_blob_path(run_dir, blob_id); + let path = local_materialized_blob_path(run_dir, blob_hash); if !path.exists() { - let bytes = read_required_blob(blob_id, run_store).await?; + let bytes = read_required_blob(blob_hash, run_store).await?; if let Some(parent) = path.parent() { fs::create_dir_all(parent).await.map_err(|err| { Error::Io(format!( @@ -439,13 +439,13 @@ async fn materialize_blob_ref( return Ok(format!("{ARTIFACT_POINTER_PREFIX}{}", path.display())); } - let remote_path = format!("{}/.fabro/blobs/{blob_id}.json", env.working_directory()); + let remote_path = format!("{}/.fabro/blobs/{blob_hash}.json", env.working_directory()); if !env .file_exists(&remote_path) .await .map_err(|e| Error::engine_with_source("failed to check blob existence", e))? { - let bytes = read_required_blob(blob_id, run_store).await?; + let bytes = read_required_blob(blob_hash, run_store).await?; let content = String::from_utf8(bytes.to_vec()) .map_err(|e| Error::engine_with_source("artifact blob was not valid UTF-8 JSON", e))?; env.write_file(&remote_path, &content).await.map_err(|e| { @@ -457,14 +457,14 @@ async fn materialize_blob_ref( } async fn read_required_blob( - blob_id: &BlobHash, + blob_hash: &BlobHash, run_store: &RunStoreHandle, ) -> Result { run_store - .read_blob(blob_id) + .read_blob(blob_hash) .await .map_err(|e| Error::engine_with_anyhow("artifact blob read failed", e))? - .ok_or_else(|| Error::engine(format!("artifact blob missing: {blob_id}"))) + .ok_or_else(|| Error::engine(format!("artifact blob missing: {blob_hash}"))) } async fn resolve_explicit_file_ref(value: &str, env: &dyn Sandbox) -> Result { @@ -508,11 +508,11 @@ async fn is_local_execution(env: &dyn Sandbox, run_dir: &Path) -> Result { .map_err(|e| Error::engine_with_source("failed to inspect sandbox locality", e)) } -fn local_materialized_blob_path(run_dir: &Path, blob_id: &BlobHash) -> PathBuf { +fn local_materialized_blob_path(run_dir: &Path, blob_hash: &BlobHash) -> PathBuf { RunScratch::new(run_dir) .runtime_dir() .join("blobs") - .join(format!("{blob_id}.json")) + .join(format!("{blob_hash}.json")) } #[cfg(test)] @@ -549,7 +549,7 @@ mod tests { let large_string = "x".repeat(BLOB_OFFLOAD_THRESHOLD + 1); let serialized = serde_json::to_vec(&serde_json::json!(large_string.clone())).unwrap(); - let expected_blob_id = fabro_types::BlobHash::new(&serialized); + let expected_blob_hash = fabro_types::BlobHash::new(&serialized); let mut updates = HashMap::new(); updates.insert("response.plan".to_string(), serde_json::json!(large_string)); @@ -561,11 +561,11 @@ mod tests { let pointer = updates.get("response.plan").unwrap(); assert_eq!( pointer, - &serde_json::json!(fabro_types::format_blob_ref(&expected_blob_id)) + &serde_json::json!(fabro_types::format_blob_ref(&expected_blob_hash)) ); let blob = run_store - .read_blob(&expected_blob_id) + .read_blob(&expected_blob_hash) .await .unwrap() .expect("blob should exist"); @@ -591,21 +591,21 @@ mod tests { async fn resolve_json_value_hydrates_blob_and_managed_file_references() { let run_store = make_run_store("structured-json-resolution").await; let value = serde_json::json!([{"name": "api"}, {"name": "web"}]); - let blob_id = run_store + let blob_hash = run_store .write_blob(&serde_json::to_vec(&value).unwrap()) .await .unwrap(); let handle = run_store.clone().into(); assert_eq!( - resolve_json_value(serde_json::json!(format_blob_ref(&blob_id)), &handle) + resolve_json_value(serde_json::json!(format_blob_ref(&blob_hash)), &handle) .await .unwrap(), value ); assert_eq!( resolve_json_value( - serde_json::json!(format!("file:///sandbox/.fabro/blobs/{blob_id}.json")), + serde_json::json!(format!("file:///sandbox/.fabro/blobs/{blob_hash}.json")), &handle, ) .await @@ -789,13 +789,13 @@ mod tests { #[test] fn normalize_durable_updates_rewrites_managed_blob_file_refs_recursively() { - let blob_id = fabro_types::BlobHash::new(b"hello"); + let blob_hash = fabro_types::BlobHash::new(b"hello"); let mut updates = HashMap::from([( "nested".to_string(), serde_json::json!({ "items": [ - format!("file:///tmp/run/runtime/blobs/{blob_id}.json"), - format!("file:///sandbox/.fabro/blobs/{blob_id}.json"), + format!("file:///tmp/run/runtime/blobs/{blob_hash}.json"), + format!("file:///sandbox/.fabro/blobs/{blob_hash}.json"), "file:///tmp/report.json", ] }), @@ -807,8 +807,8 @@ mod tests { updates["nested"], serde_json::json!({ "items": [ - fabro_types::format_blob_ref(&blob_id), - fabro_types::format_blob_ref(&blob_id), + fabro_types::format_blob_ref(&blob_hash), + fabro_types::format_blob_ref(&blob_hash), "file:///tmp/report.json", ] }) @@ -870,7 +870,7 @@ mod tests { #[test] fn normalize_checkpoint_for_resume_converts_managed_blob_file_refs_and_drops_preamble() { - let blob_id = fabro_types::BlobHash::new(b"managed"); + let blob_hash = fabro_types::BlobHash::new(b"managed"); let mut checkpoint = crate::records::Checkpoint { timestamp: chrono::Utc::now(), current_node: "work".to_string(), @@ -883,7 +883,7 @@ mod tests { ), ( "response.work".to_string(), - serde_json::json!(format!("file:///sandbox/.fabro/blobs/{blob_id}.json")), + serde_json::json!(format!("file:///sandbox/.fabro/blobs/{blob_hash}.json")), ), ]), node_outcomes: HashMap::from([( @@ -891,7 +891,7 @@ mod tests { crate::outcome::Outcome { context_updates: HashMap::from([( "response.work".to_string(), - serde_json::json!(format!("file:///sandbox/.fabro/blobs/{blob_id}.json")), + serde_json::json!(format!("file:///sandbox/.fabro/blobs/{blob_hash}.json")), )]), ..crate::outcome::Outcome::success() }, @@ -912,14 +912,14 @@ mod tests { ); assert_eq!( checkpoint.context_values.get("response.work"), - Some(&serde_json::json!(fabro_types::format_blob_ref(&blob_id))) + Some(&serde_json::json!(fabro_types::format_blob_ref(&blob_hash))) ); assert_eq!( checkpoint .node_outcomes .get("work") .and_then(|outcome| outcome.context_updates.get("response.work")), - Some(&serde_json::json!(fabro_types::format_blob_ref(&blob_id))) + Some(&serde_json::json!(fabro_types::format_blob_ref(&blob_hash))) ); } diff --git a/lib/components/fabro-workflow/src/command_log.rs b/lib/components/fabro-workflow/src/command_log.rs index 67c4373e1..ed998d208 100644 --- a/lib/components/fabro-workflow/src/command_log.rs +++ b/lib/components/fabro-workflow/src/command_log.rs @@ -109,14 +109,14 @@ pub async fn read_json_string_blob( run_store: &RunStoreHandle, blob_ref: &str, ) -> Result> { - let Some(blob_id) = fabro_types::parse_blob_ref(blob_ref) else { + let Some(blob_hash) = fabro_types::parse_blob_ref(blob_ref) else { return Ok(None); }; let bytes = run_store - .read_blob(&blob_id) + .read_blob(&blob_hash) .await .map_err(|err| Error::engine_with_anyhow("command log blob read failed", err))? - .ok_or_else(|| Error::engine(format!("command log blob missing: {blob_id}")))?; + .ok_or_else(|| Error::engine(format!("command log blob missing: {blob_hash}")))?; let text = serde_json::from_slice::(&bytes) .map_err(|err| Error::engine_with_source("command log blob was not a JSON string", err))?; Ok(Some(text)) @@ -155,9 +155,9 @@ async fn write_json_string_blob(run_store: &RunStoreHandle, text: &str) -> Resul let value = Value::String(text.to_string()); let bytes = serde_json::to_vec(&value) .map_err(|err| Error::engine_with_source("command log JSON serialization failed", err))?; - let blob_id = run_store + let blob_hash = run_store .write_blob(&bytes) .await .map_err(|err| Error::engine_with_anyhow("command log blob write failed", err))?; - Ok(format_blob_ref(&blob_id)) + Ok(format_blob_ref(&blob_hash)) } diff --git a/lib/components/fabro-workflow/src/handler/command.rs b/lib/components/fabro-workflow/src/handler/command.rs index f4fef254c..828a56101 100644 --- a/lib/components/fabro-workflow/src/handler/command.rs +++ b/lib/components/fabro-workflow/src/handler/command.rs @@ -390,12 +390,12 @@ mod tests { } async fn write_blob(&self, data: &[u8]) -> anyhow::Result { - let blob_id = fabro_types::BlobHash::new(data); + let blob_hash = fabro_types::BlobHash::new(data); self.blobs .lock() .await - .insert(blob_id, Bytes::copy_from_slice(data)); - Ok(blob_id) + .insert(blob_hash, Bytes::copy_from_slice(data)); + Ok(blob_hash) } async fn read_blob(&self, id: &fabro_types::BlobHash) -> anyhow::Result> { diff --git a/lib/components/fabro-workflow/src/handler/parallel.rs b/lib/components/fabro-workflow/src/handler/parallel.rs index f20d5d5f5..9da654d1d 100644 --- a/lib/components/fabro-workflow/src/handler/parallel.rs +++ b/lib/components/fabro-workflow/src/handler/parallel.rs @@ -1917,7 +1917,7 @@ mod tests { "name": "large-item", "body": "x".repeat(101 * 1024) }]); - let blob_id = run_store + let blob_hash = run_store .write_blob(&serde_json::to_vec(&items).unwrap()) .await .unwrap(); @@ -1933,7 +1933,7 @@ mod tests { ))); let (node, graph) = for_each_graph("items", 1); let context = test_context(); - context.set("items", serde_json::json!(format_blob_ref(&blob_id))); + context.set("items", serde_json::json!(format_blob_ref(&blob_hash))); let outcome = ParallelHandler .execute(&node, &context, &graph, sandbox_dir.path(), &services) diff --git a/lib/components/fabro-workflow/src/operations/start.rs b/lib/components/fabro-workflow/src/operations/start.rs index adbaab3f9..c295ae145 100644 --- a/lib/components/fabro-workflow/src/operations/start.rs +++ b/lib/components/fabro-workflow/src/operations/start.rs @@ -359,8 +359,8 @@ impl RunSession { let git = git_checkpoint_options_from_start(settings, &record.run_id, state.start); let definition_blob = state.spec.definition_blob; let accepted_definition = match definition_blob { - Some(blob_id) => { - Some(load_accepted_run_definition(&services.run_store, blob_id).await?) + Some(blob_hash) => { + Some(load_accepted_run_definition(&services.run_store, blob_hash).await?) } None => None, }; @@ -570,15 +570,15 @@ fn vault_token_lookup(vault: &Vault, name: &str) -> Option { async fn load_accepted_run_definition( run_store: &RunStoreHandle, - blob_id: fabro_types::BlobHash, + blob_hash: fabro_types::BlobHash, ) -> Result { let bytes = run_store - .read_blob(&blob_id) + .read_blob(&blob_hash) .await .map_err(|err| Error::engine(err.to_string()))? .ok_or_else(|| { Error::engine(format!( - "run definition blob is missing from the run store: {blob_id}" + "run definition blob is missing from the run store: {blob_hash}" )) })?; serde_json::from_slice(&bytes).map_err(|err| Error::Parse(err.to_string())) diff --git a/lib/components/fabro-workflow/src/pipeline/execute/tests.rs b/lib/components/fabro-workflow/src/pipeline/execute/tests.rs index 118767be8..5aadd6018 100644 --- a/lib/components/fabro-workflow/src/pipeline/execute/tests.rs +++ b/lib/components/fabro-workflow/src/pipeline/execute/tests.rs @@ -751,11 +751,11 @@ impl HandlerTrait for BlobCommandOutputHandler { services: &crate::handler::EngineServices, ) -> std::result::Result { let blob = serde_json::to_vec("routed-ok").unwrap(); - let blob_id = services.run.run_store.write_blob(&blob).await.unwrap(); + let blob_hash = services.run.run_store.write_blob(&blob).await.unwrap(); let mut outcome = Outcome::success(); outcome.context_updates.insert( context::keys::COMMAND_OUTPUT.to_string(), - serde_json::json!(format_blob_ref(&blob_id)), + serde_json::json!(format_blob_ref(&blob_hash)), ); Ok(outcome) } diff --git a/lib/components/fabro-workflow/src/runtime_store.rs b/lib/components/fabro-workflow/src/runtime_store.rs index 45252d5d3..a12a7c85a 100644 --- a/lib/components/fabro-workflow/src/runtime_store.rs +++ b/lib/components/fabro-workflow/src/runtime_store.rs @@ -217,8 +217,8 @@ mod tests { }; handle.append_run_event(&event).await.unwrap(); - let blob_id = handle.write_blob(br#"{"ok":true}"#).await.unwrap(); - let blob = handle.read_blob(&blob_id).await.unwrap().unwrap(); + let blob_hash = handle.write_blob(br#"{"ok":true}"#).await.unwrap(); + let blob = handle.read_blob(&blob_hash).await.unwrap().unwrap(); let events = handle.list_events().await.unwrap(); assert_eq!(events.len(), 2); diff --git a/lib/components/fabro-workflow/tests/it/daytona_integration.rs b/lib/components/fabro-workflow/tests/it/daytona_integration.rs index 021eecf11..0acfb0f60 100644 --- a/lib/components/fabro-workflow/tests/it/daytona_integration.rs +++ b/lib/components/fabro-workflow/tests/it/daytona_integration.rs @@ -544,13 +544,13 @@ async fn daytona_pipeline_artifact_offload_and_sync() { .get("response.big_output") .expect("context should have response.big_output"); let pointer_str = pointer_value.as_str().expect("pointer should be a string"); - let expected_blob_id = fabro_types::BlobHash::new( + let expected_blob_hash = fabro_types::BlobHash::new( &serde_json::to_vec(&serde_json::json!("x".repeat(150 * 1024))) .expect("large value should serialize"), ); assert_eq!( pointer_str, - fabro_types::format_blob_ref(&expected_blob_id), + fabro_types::format_blob_ref(&expected_blob_hash), "checkpoint should persist a blob ref" ); diff --git a/lib/components/fabro-workflow/tests/it/integration.rs b/lib/components/fabro-workflow/tests/it/integration.rs index 0206d2c38..02e0e74fb 100644 --- a/lib/components/fabro-workflow/tests/it/integration.rs +++ b/lib/components/fabro-workflow/tests/it/integration.rs @@ -233,7 +233,7 @@ fn resolve_checkpoint_text( let Some(current) = value.as_str() else { return Ok(value.to_string()); }; - let Some(blob_id) = parse_blob_ref(current) else { + let Some(blob_hash) = parse_blob_ref(current) else { return Ok(current.to_string()); }; @@ -272,7 +272,7 @@ fn resolve_checkpoint_text( }; let run = runtime.block_on(store.open_run_reader(&run_id))?; let bytes = runtime - .block_on(run.read_blob(&blob_id))? + .block_on(run.read_blob(&blob_hash))? .ok_or("checkpoint blob should exist")?; Ok(serde_json::from_slice::(&bytes)?) }, @@ -10059,13 +10059,13 @@ async fn large_context_values_are_offloaded_to_artifact_store() { .expect("context should have response.big_output"); let pointer_str = pointer_value.as_str().expect("pointer should be a string"); - let expected_blob_id = fabro_types::BlobHash::new( + let expected_blob_hash = fabro_types::BlobHash::new( &serde_json::to_vec(&serde_json::json!("x".repeat(150 * 1024))) .expect("large value should serialize"), ); assert_eq!( pointer_str, - fabro_types::format_blob_ref(&expected_blob_id), + fabro_types::format_blob_ref(&expected_blob_hash), "value should be a durable blob ref" ); @@ -10258,13 +10258,13 @@ async fn artifact_pointers_rewritten_for_remote_sandbox() { .get("response.big_output") .expect("context should have response.big_output"); let pointer_str = pointer_value.as_str().expect("pointer should be a string"); - let expected_blob_id = fabro_types::BlobHash::new( + let expected_blob_hash = fabro_types::BlobHash::new( &serde_json::to_vec(&serde_json::json!("x".repeat(150 * 1024))) .expect("large value should serialize"), ); assert_eq!( pointer_str, - fabro_types::format_blob_ref(&expected_blob_id), + fabro_types::format_blob_ref(&expected_blob_hash), "checkpoint should persist a blob ref" ); diff --git a/lib/foundation/fabro-client/src/client.rs b/lib/foundation/fabro-client/src/client.rs index 4ece0a9de..8e1c3a1b2 100644 --- a/lib/foundation/fabro-client/src/client.rs +++ b/lib/foundation/fabro-client/src/client.rs @@ -1841,18 +1841,22 @@ impl Client { .await?; response .into_inner() - .id + .hash .parse() - .context("write_run_blob returned invalid blob id") + .context("write_run_blob returned invalid blob hash") } - pub async fn read_run_blob(&self, run_id: &RunId, blob_id: &BlobHash) -> Result> { + pub async fn read_run_blob( + &self, + run_id: &RunId, + blob_hash: &BlobHash, + ) -> Result> { let response = self .current_state() .client .read_run_blob() .id(run_id.to_string()) - .blob_id(blob_id.to_string()) + .blob_hash(blob_hash.to_string()) .send() .await; match response { diff --git a/lib/foundation/fabro-test/src/lib.rs b/lib/foundation/fabro-test/src/lib.rs index 74a5f6727..cf0cc669a 100644 --- a/lib/foundation/fabro-test/src/lib.rs +++ b/lib/foundation/fabro-test/src/lib.rs @@ -1957,11 +1957,11 @@ pub fn json_snapshot_filters(mut filters: Vec<(String, String)>) -> Vec<(String, filters = json_elapsed_ms_snapshot_filters(filters); filters.push(( r#""manifest_blob":\s*"[0-9a-f]{64}""#.to_string(), - r#""manifest_blob": "[BLOB_ID]""#.to_string(), + r#""manifest_blob": "[BLOB_HASH]""#.to_string(), )); filters.push(( r#""definition_blob":\s*"[0-9a-f]{64}""#.to_string(), - r#""definition_blob": "[BLOB_ID]""#.to_string(), + r#""definition_blob": "[BLOB_HASH]""#.to_string(), )); filters.push(( r#""run_dir":\s*"\[STORAGE_DIR\]/scratch/\d{8}-\[ULID\]""#.to_string(), @@ -2562,8 +2562,8 @@ mod tests { "inference_time_ms": "[INFERENCE_TIME_MS]", "tool_time_ms": "[TOOL_TIME_MS]", "active_time_ms": "[ACTIVE_TIME_MS]", - "manifest_blob": "[BLOB_ID]", - "definition_blob": "[BLOB_ID]", + "manifest_blob": "[BLOB_HASH]", + "definition_blob": "[BLOB_HASH]", "run_dir": "[RUN_DIR]", "message": "[CUSTOM]" }"# diff --git a/lib/foundation/fabro-types/src/workflow_version_id.rs b/lib/foundation/fabro-types/src/workflow_version_id.rs index 4bf597f47..7e19f5333 100644 --- a/lib/foundation/fabro-types/src/workflow_version_id.rs +++ b/lib/foundation/fabro-types/src/workflow_version_id.rs @@ -63,10 +63,10 @@ mod tests { #[test] fn conversion_preserves_digest_and_display() { - let blob_id = BlobHash::new(b"workflow"); - let version_id = WorkflowVersionId::from(blob_id); - assert_eq!(version_id.to_string(), blob_id.to_string()); - assert_eq!(BlobHash::from(version_id), blob_id); + let blob_hash = BlobHash::new(b"workflow"); + let version_id = WorkflowVersionId::from(blob_hash); + assert_eq!(version_id.to_string(), blob_hash.to_string()); + assert_eq!(BlobHash::from(version_id), blob_hash); } #[test] diff --git a/lib/packages/fabro-api-client/src/api/run-internals-api.ts b/lib/packages/fabro-api-client/src/api/run-internals-api.ts index 403e2eb05..668200fbe 100644 --- a/lib/packages/fabro-api-client/src/api/run-internals-api.ts +++ b/lib/packages/fabro-api-client/src/api/run-internals-api.ts @@ -781,21 +781,21 @@ export const RunInternalsApiAxiosParamCreator = function (configuration?: Config }; }, /** - * Reads a previously stored blob by identifier. + * Reads a previously stored blob by hash. * @summary Read Run Blob * @param {string} id Unique run identifier (ULID). - * @param {string} blobId Content-addressed blob identifier. + * @param {string} blobHash Content-addressed blob hash. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - readRunBlob: async (id: string, blobId: string, options: RawAxiosRequestConfig = {}): Promise => { + readRunBlob: async (id: string, blobHash: string, options: RawAxiosRequestConfig = {}): Promise => { // verify required parameter 'id' is not null or undefined assertParamExists('readRunBlob', 'id', id) - // verify required parameter 'blobId' is not null or undefined - assertParamExists('readRunBlob', 'blobId', blobId) - const localVarPath = `/api/v1/runs/{id}/blobs/{blobId}` + // verify required parameter 'blobHash' is not null or undefined + assertParamExists('readRunBlob', 'blobHash', blobHash) + const localVarPath = `/api/v1/runs/{id}/blobs/{blobHash}` .replace(`{${"id"}}`, encodeURIComponent(String(id))) - .replace(`{${"blobId"}}`, encodeURIComponent(String(blobId))); + .replace(`{${"blobHash"}}`, encodeURIComponent(String(blobHash))); // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); let baseOptions; @@ -905,7 +905,7 @@ export const RunInternalsApiAxiosParamCreator = function (configuration?: Config }; }, /** - * Writes an opaque binary blob and returns its content-addressed blob identifier. + * Writes an opaque binary blob and returns its content-addressed blob hash. * @summary Write Run Blob * @param {string} id Unique run identifier (ULID). * @param {File} body @@ -1179,15 +1179,15 @@ export const RunInternalsApiFp = function(configuration?: Configuration) { return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** - * Reads a previously stored blob by identifier. + * Reads a previously stored blob by hash. * @summary Read Run Blob * @param {string} id Unique run identifier (ULID). - * @param {string} blobId Content-addressed blob identifier. + * @param {string} blobHash Content-addressed blob hash. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async readRunBlob(id: string, blobId: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.readRunBlob(id, blobId, options); + async readRunBlob(id: string, blobHash: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.readRunBlob(id, blobHash, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['RunInternalsApi.readRunBlob']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); @@ -1219,7 +1219,7 @@ export const RunInternalsApiFp = function(configuration?: Configuration) { return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** - * Writes an opaque binary blob and returns its content-addressed blob identifier. + * Writes an opaque binary blob and returns its content-addressed blob hash. * @summary Write Run Blob * @param {string} id Unique run identifier (ULID). * @param {File} body @@ -1417,15 +1417,15 @@ export const RunInternalsApiFactory = function (configuration?: Configuration, b return localVarFp.putStageArtifact(id, stageId, retry, body, filename, options).then((request) => request(axios, basePath)); }, /** - * Reads a previously stored blob by identifier. + * Reads a previously stored blob by hash. * @summary Read Run Blob * @param {string} id Unique run identifier (ULID). - * @param {string} blobId Content-addressed blob identifier. + * @param {string} blobHash Content-addressed blob hash. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - readRunBlob(id: string, blobId: string, options?: RawAxiosRequestConfig): AxiosPromise { - return localVarFp.readRunBlob(id, blobId, options).then((request) => request(axios, basePath)); + readRunBlob(id: string, blobHash: string, options?: RawAxiosRequestConfig): AxiosPromise { + return localVarFp.readRunBlob(id, blobHash, options).then((request) => request(axios, basePath)); }, /** * Returns the latest checkpoint data for a run, or null if no checkpoint has been recorded yet. @@ -1448,7 +1448,7 @@ export const RunInternalsApiFactory = function (configuration?: Configuration, b return localVarFp.retrieveRunSettings(id, options).then((request) => request(axios, basePath)); }, /** - * Writes an opaque binary blob and returns its content-addressed blob identifier. + * Writes an opaque binary blob and returns its content-addressed blob hash. * @summary Write Run Blob * @param {string} id Unique run identifier (ULID). * @param {File} body @@ -1656,15 +1656,15 @@ export class RunInternalsApi extends BaseAPI { } /** - * Reads a previously stored blob by identifier. + * Reads a previously stored blob by hash. * @summary Read Run Blob * @param {string} id Unique run identifier (ULID). - * @param {string} blobId Content-addressed blob identifier. + * @param {string} blobHash Content-addressed blob hash. * @param {*} [options] Override http request option. * @throws {RequiredError} */ - public readRunBlob(id: string, blobId: string, options?: RawAxiosRequestConfig) { - return RunInternalsApiFp(this.configuration).readRunBlob(id, blobId, options).then((request) => request(this.axios, this.basePath)); + public readRunBlob(id: string, blobHash: string, options?: RawAxiosRequestConfig) { + return RunInternalsApiFp(this.configuration).readRunBlob(id, blobHash, options).then((request) => request(this.axios, this.basePath)); } /** @@ -1690,7 +1690,7 @@ export class RunInternalsApi extends BaseAPI { } /** - * Writes an opaque binary blob and returns its content-addressed blob identifier. + * Writes an opaque binary blob and returns its content-addressed blob hash. * @summary Write Run Blob * @param {string} id Unique run identifier (ULID). * @param {File} body diff --git a/lib/packages/fabro-api-client/src/models/write-blob-response.ts b/lib/packages/fabro-api-client/src/models/write-blob-response.ts index 295ff9874..17a0ecad9 100644 --- a/lib/packages/fabro-api-client/src/models/write-blob-response.ts +++ b/lib/packages/fabro-api-client/src/models/write-blob-response.ts @@ -15,11 +15,11 @@ /** - * Content-addressed identifier for a stored blob. + * Content-addressed hash of a stored blob. */ export interface WriteBlobResponse { /** - * Blob identifier. + * Content-addressed hash of the stored blob. */ - 'id': string; + 'hash': string; }