cjerzak commited on
Commit
1307edc
·
1 Parent(s): 6faa62d

add files

Browse files
Files changed (3) hide show
  1. R/asa_api_helpers.R +47 -30
  2. Tests/api_contract_smoke.R +65 -25
  3. www/index.html +3 -0
R/asa_api_helpers.R CHANGED
@@ -1115,49 +1115,65 @@ asa_api_normalize_result <- function(result, include_raw_output = FALSE, include
1115
  output
1116
  }
1117
 
1118
- asa_api_is_hidden_execution_field <- function(name) {
1119
- field <- asa_api_scalar_chr(name, default = "")
1120
- if (!nzchar(field)) {
1121
- return(FALSE)
1122
  }
1123
-
1124
- field <- tolower(trimws(field))
1125
- field %in% c("base_url", "openai_api_base") ||
1126
- grepl("(^|_)(backend|provider|model|model_id|model_name)$", field)
1127
  }
1128
 
1129
- asa_api_remove_hidden_execution_fields <- function(value) {
1130
- if (!is.list(value)) {
1131
- return(value)
 
1132
  }
 
 
1133
 
1134
- value_names <- names(value) %||% character(0)
1135
- if (length(value_names)) {
1136
- keep <- !vapply(value_names, asa_api_is_hidden_execution_field, logical(1))
1137
- value <- value[keep]
1138
  }
1139
 
1140
- if (!length(value)) {
1141
- return(value)
 
 
1142
  }
1143
 
1144
- for (i in seq_along(value)) {
1145
- value[[i]] <- asa_api_remove_hidden_execution_fields(value[[i]])
1146
- }
1147
 
1148
- value
 
 
 
 
 
 
 
 
 
 
 
1149
  }
1150
 
1151
- asa_api_sanitize_gui_result <- function(result) {
1152
  if (!is.list(result)) {
1153
  return(result)
1154
  }
1155
 
1156
- if (!is.null(result$execution)) {
1157
- result$execution <- asa_api_remove_hidden_execution_fields(result$execution)
1158
- }
1159
-
1160
- result
 
 
 
 
1161
  }
1162
 
1163
  asa_api_is_result_like <- function(value) {
@@ -1378,6 +1394,7 @@ asa_api_run_gui_query <- function(payload, request_context = NULL) {
1378
  log_con <- asa_api_request_context_log_con(request_context)
1379
  stage_ref <- new.env(parent = emptyenv())
1380
  stage_ref$value <- "run_single"
 
1381
  capture <- asa_api_new_runtime_capture()
1382
  capture$prompt <- asa_api_scalar_chr(payload$prompt, default = "")
1383
  run_payload <- payload
@@ -1399,10 +1416,10 @@ asa_api_run_gui_query <- function(payload, request_context = NULL) {
1399
  request_context = list(route = route, log_con = log_con)
1400
  )
1401
 
1402
- stage_ref$value <- "sanitize_gui_result"
1403
- asa_api_sanitize_gui_result(result)
1404
  },
1405
- mode = asa_api_single_mode(run_payload, allow_direct_provider = TRUE),
1406
  route = route,
1407
  payload = run_payload,
1408
  prompt = capture$prompt,
 
1115
  output
1116
  }
1117
 
1118
+ asa_api_optional_scalar_chr <- function(value) {
1119
+ text <- asa_api_scalar_chr(value, default = "")
1120
+ if (nzchar(text)) {
1121
+ return(text)
1122
  }
1123
+ NULL
 
 
 
1124
  }
1125
 
1126
+ asa_api_optional_scalar_int <- function(value) {
1127
+ number <- asa_api_scalar_int(value, default = NA_integer_)
1128
+ if (!is.na(number)) {
1129
+ return(number)
1130
  }
1131
+ NULL
1132
+ }
1133
 
1134
+ asa_api_gui_execution_mode <- function(execution, response_mode = NULL) {
1135
+ response_mode <- asa_api_scalar_chr(response_mode, default = "")
1136
+ if (identical(response_mode, "provider_direct_single")) {
1137
+ return("provider_direct")
1138
  }
1139
 
1140
+ execution <- asa_api_named_list(execution)
1141
+ execution_mode <- asa_api_scalar_chr(execution$mode, default = "")
1142
+ if (identical(execution_mode, "provider_direct")) {
1143
+ return("provider_direct")
1144
  }
1145
 
1146
+ "asa_agent"
1147
+ }
 
1148
 
1149
+ asa_api_gui_execution_summary <- function(execution, response_mode = NULL) {
1150
+ execution <- asa_api_named_list(asa_api_to_plain(execution))
1151
+
1152
+ asa_api_drop_nulls(list(
1153
+ mode = asa_api_gui_execution_mode(execution, response_mode = response_mode),
1154
+ thread_id = asa_api_optional_scalar_chr(execution$thread_id),
1155
+ backend_status = asa_api_optional_scalar_chr(execution$backend_status),
1156
+ status_code = asa_api_optional_scalar_int(execution$status_code),
1157
+ tool_calls_used = asa_api_optional_scalar_int(execution$tool_calls_used),
1158
+ search_calls_used = asa_api_optional_scalar_int(execution$search_calls_used),
1159
+ action_step_count = asa_api_optional_scalar_int(execution$action_step_count)
1160
+ ))
1161
  }
1162
 
1163
+ asa_api_project_gui_result <- function(result, response_mode = NULL) {
1164
  if (!is.list(result)) {
1165
  return(result)
1166
  }
1167
 
1168
+ asa_api_drop_nulls(list(
1169
+ status = result$status %||% NULL,
1170
+ message = result$message %||% NULL,
1171
+ parsed = result$parsed %||% NULL,
1172
+ elapsed_time_min = result$elapsed_time_min %||% NULL,
1173
+ search_tier = result$search_tier %||% NULL,
1174
+ parsing_status = result$parsing_status %||% NULL,
1175
+ execution = asa_api_gui_execution_summary(result$execution, response_mode = response_mode)
1176
+ ))
1177
  }
1178
 
1179
  asa_api_is_result_like <- function(value) {
 
1394
  log_con <- asa_api_request_context_log_con(request_context)
1395
  stage_ref <- new.env(parent = emptyenv())
1396
  stage_ref$value <- "run_single"
1397
+ response_mode <- asa_api_single_mode(payload, allow_direct_provider = TRUE)
1398
  capture <- asa_api_new_runtime_capture()
1399
  capture$prompt <- asa_api_scalar_chr(payload$prompt, default = "")
1400
  run_payload <- payload
 
1416
  request_context = list(route = route, log_con = log_con)
1417
  )
1418
 
1419
+ stage_ref$value <- "project_gui_result"
1420
+ asa_api_project_gui_result(result, response_mode = response_mode)
1421
  },
1422
+ mode = response_mode,
1423
  route = route,
1424
  payload = run_payload,
1425
  prompt = capture$prompt,
Tests/api_contract_smoke.R CHANGED
@@ -452,7 +452,7 @@ assert_true(
452
 
453
  {
454
  original_run_single <- asa_api_run_single
455
- original_sanitize_gui_result <- asa_api_sanitize_gui_result
456
  gui_log_lines <- character(0)
457
  gui_log_con <- textConnection("gui_log_lines", "w", local = TRUE)
458
  gui_error <- NULL
@@ -464,7 +464,7 @@ assert_true(
464
  execution = list(mode = "asa_agent")
465
  )
466
  }
467
- asa_api_sanitize_gui_result <- function(result) {
468
  stop("subscript out of bounds", call. = FALSE)
469
  }
470
 
@@ -480,7 +480,7 @@ assert_true(
480
  )
481
  close(gui_log_con)
482
  asa_api_run_single <- original_run_single
483
- asa_api_sanitize_gui_result <- original_sanitize_gui_result
484
 
485
  gui_failure <- asa_api_error_failure(gui_error)
486
  gui_res_env <- new.env(parent = emptyenv())
@@ -489,10 +489,10 @@ assert_true(
489
  assert_true(
490
  inherits(gui_error, "asa_api_runtime_error") &&
491
  identical(gui_failure$details$route, "/gui/query") &&
492
- identical(gui_failure$details$stage, "sanitize_gui_result") &&
493
- identical(gui_payload$details$stage, "sanitize_gui_result") &&
494
- grepl("stage=sanitize_gui_result", gui_log_text, fixed = TRUE),
495
- "GUI sanitization failures should return the safe diagnostic summary and emit matching logs."
496
  )
497
  }
498
 
@@ -574,31 +574,71 @@ asa_api_refresh_auth_cache(force = TRUE)
574
  asa_api_run_single_via_direct <- original_direct
575
  }
576
 
577
- gui_result <- asa_api_sanitize_gui_result(list(
578
  status = "success",
 
 
 
 
 
579
  execution = list(
580
- mode = "provider_direct",
581
- config_snapshot = list(backend = "gemini", model = "gemini-3-flash-preview"),
582
- payload_integrity = list(
583
- backend = "gemini",
584
- model = "gemini-3-flash-preview",
585
- released_from = "message_text"
586
- ),
587
- trace_metadata = list(
588
- structured_output_backend = "gemini",
589
- model_name = "gemini-3-flash-preview"
590
- )
 
 
 
 
 
 
591
  )
592
  ))
593
  assert_true(
594
- is.null(gui_result$execution$config_snapshot$backend) &&
595
- is.null(gui_result$execution$config_snapshot$model),
596
- "GUI responses should not expose backend/model selection in execution metadata."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
597
  )
598
  assert_true(
599
- is.null(gui_result$execution$payload_integrity$backend) &&
600
- is.null(gui_result$execution$payload_integrity$model),
601
- "GUI payload integrity metadata should hide backend/model fields."
602
  )
603
 
604
  cat("asa-api contract smoke checks passed\n")
 
452
 
453
  {
454
  original_run_single <- asa_api_run_single
455
+ original_project_gui_result <- asa_api_project_gui_result
456
  gui_log_lines <- character(0)
457
  gui_log_con <- textConnection("gui_log_lines", "w", local = TRUE)
458
  gui_error <- NULL
 
464
  execution = list(mode = "asa_agent")
465
  )
466
  }
467
+ asa_api_project_gui_result <- function(result, response_mode = NULL) {
468
  stop("subscript out of bounds", call. = FALSE)
469
  }
470
 
 
480
  )
481
  close(gui_log_con)
482
  asa_api_run_single <- original_run_single
483
+ asa_api_project_gui_result <- original_project_gui_result
484
 
485
  gui_failure <- asa_api_error_failure(gui_error)
486
  gui_res_env <- new.env(parent = emptyenv())
 
489
  assert_true(
490
  inherits(gui_error, "asa_api_runtime_error") &&
491
  identical(gui_failure$details$route, "/gui/query") &&
492
+ identical(gui_failure$details$stage, "project_gui_result") &&
493
+ identical(gui_payload$details$stage, "project_gui_result") &&
494
+ grepl("stage=project_gui_result", gui_log_text, fixed = TRUE),
495
+ "GUI projection failures should return the safe diagnostic summary and emit matching logs."
496
  )
497
  }
498
 
 
574
  asa_api_run_single_via_direct <- original_direct
575
  }
576
 
577
+ gui_result <- asa_api_project_gui_result(list(
578
  status = "success",
579
+ message = "ok",
580
+ parsed = list(capital = "Paris"),
581
+ elapsed_time_min = 0.25,
582
+ search_tier = "unknown",
583
+ parsing_status = list(valid = TRUE),
584
  execution = list(
585
+ thread_id = list("asa_123"),
586
+ backend_status = list("success"),
587
+ status_code = list(200L),
588
+ tool_calls_used = list(2L),
589
+ search_calls_used = list(1L),
590
+ action_step_count = list(6L),
591
+ tool_quality_events = list(list(
592
+ message_index_in_round = list(1L),
593
+ tool_name = list("update_plan"),
594
+ is_empty = list(FALSE),
595
+ is_off_target = list(FALSE),
596
+ is_error = list(FALSE),
597
+ error_type = NULL,
598
+ elapsed_ms_estimate = list(0L),
599
+ quality_version = list("v1")
600
+ )),
601
+ config_snapshot = list(backend = "gemini", model = "gemini-3-flash-preview")
602
  )
603
  ))
604
  assert_true(
605
+ identical(
606
+ names(gui_result$execution),
607
+ c(
608
+ "mode",
609
+ "thread_id",
610
+ "backend_status",
611
+ "status_code",
612
+ "tool_calls_used",
613
+ "search_calls_used",
614
+ "action_step_count"
615
+ )
616
+ ) &&
617
+ identical(gui_result$execution$mode, "asa_agent") &&
618
+ identical(gui_result$execution$thread_id, "asa_123") &&
619
+ identical(gui_result$execution$tool_calls_used, 2L),
620
+ "GUI success responses should expose only a compact execution summary."
621
+ )
622
+ assert_true(
623
+ !("tool_quality_events" %in% names(gui_result$execution)) &&
624
+ !("config_snapshot" %in% names(gui_result$execution)),
625
+ "GUI projection should avoid recursing through nested execution diagnostics."
626
+ )
627
+
628
+ gui_direct_result <- asa_api_project_gui_result(
629
+ list(
630
+ status = "success",
631
+ execution = list(
632
+ mode = list("provider_direct"),
633
+ status_code = list(200L)
634
+ )
635
+ ),
636
+ response_mode = "provider_direct_single"
637
  )
638
  assert_true(
639
+ identical(gui_direct_result$execution$mode, "provider_direct") &&
640
+ identical(gui_direct_result$execution$status_code, 200L),
641
+ "GUI projection should preserve direct-provider mode in the compact execution summary."
642
  )
643
 
644
  cat("asa-api contract smoke checks passed\n")
www/index.html CHANGED
@@ -404,6 +404,9 @@
404
  if (data && data.execution && data.execution.mode === "provider_direct") {
405
  return "Mode: direct provider";
406
  }
 
 
 
407
 
408
  return "Mode: ASA agent";
409
  }
 
404
  if (data && data.execution && data.execution.mode === "provider_direct") {
405
  return "Mode: direct provider";
406
  }
407
+ if (data && data.execution && data.execution.mode === "asa_agent") {
408
+ return "Mode: ASA agent";
409
+ }
410
 
411
  return "Mode: ASA agent";
412
  }