Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 71 additions & 1 deletion apps/apollo-vertex/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,21 @@
"access_denied": "Access Denied",
"access_denied_description": "You don't have access to this application. Ask your administrator to add you to the users group.",
"actions": "Actions",
"actual_input": "Actual input",
"actual_output": "Actual output",
"actual_version": "Actual version",
"add_attachment": "Add attachment",
"add_to_expected_result": "Add to expected results",
"agent_adopted_successfully": "Agent added to expected results",
"agent_has_no_expected_output": "Agent has no expected output",
"agent_name": "Agent name",
"agent_produced_no_output": "Agent produced no output",
"agent_removed_from_expected_results": "Agent removed from expected results",
"agents_passed": "Agents passed",
"ai_assistant": "AI Assistant",
"ai_response_disclaimer": "AI-generated responses should be reviewed for accuracy.",
"all": "All",
"all_tests_triggered": "All tests triggered",
"analytics": "Analytics",
"apollo_vertex": "Apollo Vertex",
"apollo_vertex_description": "- UiPath Apollo Vertex",
Expand All @@ -15,6 +26,8 @@
"assistant": "Assistant",
"autopilot_empty_description": "Ask me anything about your automation data.",
"bad_response": "Bad response",
"baseline_updated_successfully": "Expected result updated",
"baseline_version": "Baseline version",
"business_user": "Business user",
"cancel": "Cancel",
"card_component": "Card Component",
Expand All @@ -28,35 +41,57 @@
"click_me": "Click me",
"close": "Close",
"close_sidebar": "Close sidebar",
"collapse": "Collapse",
"collapse_tool_calls": "Collapse tool calls",
"confirm_delete_test": "Delete this test?",
"confirm_delete_test_description": "This permanently removes the test and its baselines. This action cannot be undone.",
"copied": "Copied!",
"copy": "Copy",
"copy_code": "Copy code",
"copy_conversation": "Copy conversation",
"copy_conversation_failed": "Couldn't copy conversation",
"copy_failed": "Couldn't copy",
"copy_payment_id": "Copy payment ID",
"current_baseline": "Current baseline",
"custom": "Custom",
"dark": "Dark",
"dark_mode": "Dark Mode",
"dashboard": "Dashboard",
"delete": "Delete",
"desc": "Desc",
"destructive": "Destructive",
"details": "Details",
"disabled": "Disabled",
"displays_mobile_sidebar": "Displays the mobile sidebar.",
"edit": "Edit",
"enabled": "Enabled",
"english": "English",
"enter_full_screen": "Enter full screen",
"error": "Error",
"exit_full_screen": "Exit full screen",
"expand": "Expand",
"expand_tool_calls": "Expand tool calls",
"expected_input": "Expected input",
"expected_output": "Expected output",
"export": "Export",
"failed_to_adopt_agent": "Failed to add agent to expected results",
"failed_to_delete_test": "Failed to delete test",
"failed_to_force_stop_batch": "Failed to force stop run batch",
"failed_to_force_stop_run": "Failed to force stop run",
"failed_to_load_run_details": "Failed to load run details",
"failed_to_remove_agent_baseline": "Failed to remove agent from expected results",
"failed_to_run_test": "Failed to run test",
"failed_to_run_tests": "Failed to run tests",
"failed_to_update_baseline": "Failed to update expected result",
"feedback_comment_placeholder": "What could the AI have done better?",
"feedback_demo_default_label": "Default — buttons only",
"feedback_demo_disabled_label": "Disabled",
"feedback_demo_small_size_label": "Small size",
"feedback_demo_with_comment_label": "With comment textarea",
"feedback_vote_down": "Vote down",
"feedback_vote_up": "Vote up",
"force_stop": "Force stop",
"force_stop_initiated": "Force stop initiated",
"french": "French",
"german": "German",
"go_to_first_page": "Go to first page",
Expand All @@ -68,10 +103,12 @@
"how_can_i_help_you": "How can I help you?",
"image_preview": "Image preview",
"import": "Import",
"in_baseline": "In baseline",
"info": "Info",
"japanese": "Japanese",
"korean": "Korean",
"language": "Language",
"last_run_score": "Last run score",
"light": "Light",
"light_mode": "Light Mode",
"load_from_preset": "Load from preset:",
Expand All @@ -88,14 +125,19 @@
"new_conversation_confirm_title": "Start a new conversation?",
"next": "Next",
"next_slide": "Next slide",
"no_agents_configured": "No agents configured",
"no_countable_in_entity": "{{entity}} has no field that can be counted.",
"no_countable_in_joined": "No countable field is available on {{primary}} or the joined entities.",
"no_data_available": "No data available",
"no_frameworks_found": "No frameworks found.",
"no_results": "No results.",
"no_results_available": "No results available",
"of": "of",
"open_menu": "Open menu",
"open_sidebar": "Open sidebar",
"outline": "Outline",
"output_evaluator_results": "Output evaluator results",
"overall_score": "Overall score",
"page": "Page",
"pick_a_date": "Pick a date",
"portuguese": "Portuguese",
Expand All @@ -107,14 +149,23 @@
"primary_button": "Primary Button",
"projects": "Projects",
"remove_file": "Remove {{name}}",
"remove_from_expected_result": "Remove from expected results",
"remove_quoted_text": "Remove quoted text",
"removed": "Removed",
"reset_to_default": "Reset to Default",
"retry": "Retry",
"romanian": "Romanian",
"rows_per_page": "Rows per page",
"rows_selected": "{{selected}} of {{total}} row(s) selected.",
"run": "Run",
"run_all": "Run all",
"run_date": "Run date",
"run_results": "Run results",
"runs_in_progress": "Runs in progress",
"russian": "Russian",
"save_and_rerun": "Save & re-run",
"score": "Score",
"score_trend": "Score trend",
"scroll_to_bottom": "Scroll to bottom",
"search": "Search...",
"search_frameworks": "Search frameworks",
Expand All @@ -131,20 +182,35 @@
"sign_in_with_uipath": "Sign in with UiPath",
"sign_out": "Sign out",
"signed_in_as": "Signed in as {{email}}",
"solution_tests": "Solution tests",
"sort_by_column": "Sort by {{column}}",
"sort_by_column_sorted_ascending": "Sort by {{column}} (sorted ascending)",
"sort_by_column_sorted_descending": "Sort by {{column}} (sorted descending)",
"spanish": "Spanish",
"spanish-mx": "Spanish (Mexico)",
"start_conversation_with": "Start a conversation with {{name}}",
"status": "Status",
"stop": "Stop",
"subject_passed": "{{subject}} passed",
"subject_passing": "{{subject}} passing",
"subject_run_results": "{{subject}} {{id}}",
"success": "Success",
"system": "System",
"table_no_valid_fields": "None of the requested fields exist on {{entity}}: {{fields}}.",
"team": "Team",
"test_cases": "Test cases",
"test_creation_failed": "Test creation failed",
"test_deleted": "Test deleted",
"test_disabled": "Test disabled",
"test_enabled": "Test enabled",
"test_name": "Test name",
"test_runs": "Test runs",
"test_triggered": "Test triggered",
"tests_passed": "Tests passed",
"tests_passing": "Tests passing",
"theme_editor": "Theme Editor",
"thinking": "Thinking",
"theme_preview_description": "This is a preview of the card component with your custom theme.",
"thinking": "Thinking",
"toggle_columns": "Toggle columns",
"toggle_sidebar": "Toggle Sidebar",
"toggle_theme": "Toggle theme",
Expand All @@ -158,12 +224,16 @@
"unknown_entity": "Entity \"{{entity}}\" doesn't exist.",
"unknown_field_in_entity": "Field \"{{field}}\" doesn't exist on {{entity}}.",
"unknown_field_in_joined": "Field \"{{field}}\" doesn't exist on the joined entities.",
"update_expected_result": "Update expected result",
"upload_files": "Upload files",
"user_email_placeholder": "user@company.com",
"user_profile": "Profile and settings",
"verifying_access": "Verifying access…",
"version": "Version",
"version_differs_from_baseline": "Version differs from baseline",
"view": "View",
"view_customer": "View customer",
"view_expected": "View expected",
"view_payment_details": "View payment details",
"warning": "Warning",
"wrong_dimension_type_in_entity": "Field \"{{field}}\" on {{entity}} is {{actual}}; this chart needs a {{expected}} field.",
Expand Down
52 changes: 52 additions & 0 deletions apps/apollo-vertex/registry/solution-tests/actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* The Solution Tests write surface. The smart container resolves these from
* the `SolutionTestsProvider`'s `actions` prop; supply your own implementation,
* or use `createSolutionTestActions` for the standard Solution Test framework
* contract (see `create-actions`).
*/

import { notImplemented } from "./mutations";
import type { MutationResult, ResultAttachmentField } from "./types";

export interface SolutionTestsActions {
/** Run the given tests, or all active Ready tests when omitted. */
runTests(testIds?: string[]): Promise<MutationResult>;
/** Toggle a test's active flag. */
toggleTestActive(testId: string, isActive: boolean): Promise<void>;
/** Delete a test. */
deleteTest(testId: string): Promise<MutationResult>;
/** Force-stop every active run in a batch. */
forceStopBatch(batchId: string): Promise<MutationResult>;
/** Force-stop a single run. */
forceStopRun(runId: string): Promise<MutationResult>;
/** Adopt a run result's job as the test baseline. */
adoptJob(runResultId: string): Promise<MutationResult>;
/** Update the test baseline from a run result. */
updateBaseline(runResultId: string): Promise<MutationResult>;
/** Remove a job from the test's expected (baseline) results. */
removeJobBaseline(jobBaselineId: string): Promise<MutationResult>;
/** Expected-output attachment for a baseline job (Agents expansion). */
getJobExpectedOutput(jobId: string): Promise<unknown>;
/** One attachment slot for a run result (run-details expansion). */
getResultAttachment(
resultId: string,
field: ResultAttachmentField,
): Promise<unknown>;
}

/**
* Fallback used when the provider is given no `actions` — every method throws
* *when invoked* (not at hook-call time, so smart containers still render).
*/
export const notImplementedActions: SolutionTestsActions = {
runTests: () => notImplemented("runTests"),
toggleTestActive: () => notImplemented("toggleTestActive"),
deleteTest: () => notImplemented("deleteTest"),
forceStopBatch: () => notImplemented("forceStopBatch"),
forceStopRun: () => notImplemented("forceStopRun"),
adoptJob: () => notImplemented("adoptJob"),
updateBaseline: () => notImplemented("updateBaseline"),
removeJobBaseline: () => notImplemented("removeJobBaseline"),
getJobExpectedOutput: () => notImplemented("getJobExpectedOutput"),
getResultAttachment: () => notImplemented("getResultAttachment"),
};
41 changes: 41 additions & 0 deletions apps/apollo-vertex/registry/solution-tests/collections.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import type { Collection } from "@tanstack/react-db";

/**
* Well-known Solution Test entity collection names. The collections live on the
* dedicated, name-keyed `solutionTests` namespace of the vs-core solution
* (`solution.api.collections.solutionTests[NAME]`, added in @uipath/vs-core 2.x).
*/
export const ENTITY = {
tests: "UiPathSTTests",
batchRuns: "UiPathSTBatchRuns",
runs: "UiPathSTRuns",
jobs: "UiPathSTJobs",
runResults: "UiPathSTRunResults",
} as const;

/** Structural subset of the vs-core solution we touch — keeps this file free
* of a hard `@uipath/vs-core` type dependency. */
interface SolutionLike {
api: { collections: { solutionTests: unknown } };
}

/**
* Resolve a Solution Test collection by its well-known name and bridge it to the
* row type the view expects.
*
* vs-core types the `solutionTests` namespace by the *consumer's* entity
* generic (`Partial<Collections<TEntities>>`), which a domain-neutral component
* can't supply — so the map isn't statically indexable to a known row type.
* This is the single, deliberate boundary where we assert the row shape; the
* read hooks stay assertion-free and feed the result straight to `useLiveQuery`.
*/
export function solutionTestCollection<T extends object>(
solution: SolutionLike | null,
name: string,
): Collection<T> | undefined {
// oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- the one deliberate boundary: vs-core types this map by the consumer's entity generic, unknowable to a domain-neutral component
const map = solution?.api.collections.solutionTests as
| Record<string, Collection<T> | undefined>
| undefined;
return map?.[name];
}
75 changes: 75 additions & 0 deletions apps/apollo-vertex/registry/solution-tests/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/**
* Presentation config for the Solution Tests view.
*
* The view fetches generic Solution Test entities; everything that varies by
* vertical is parameterized here. In practice the only required customization
* is `subjectColumns` (the vertical's own columns). Framework strings are
* translated with i18n inside the components.
*/

import type { ColumnDef } from "@tanstack/react-table";
import type { SolutionTest } from "./types";

/** Optional override maps for the numeric status enums (e.g. localized labels). */
export interface StatusLabelOverrides {
test?: Record<number, string>;
run?: Record<number, string>;
runResult?: Record<number, string>;
}

export interface SolutionTestsConfig {
/** Extra subject columns inserted between the Test Name and Version columns. */
subjectColumns?: ColumnDef<SolutionTest>[];
/** Navigation href for a test's subject; when set, the test name is a link. */
getSubjectHref?: (test: SolutionTest) => string | undefined;
/**
* The subject entity's noun, e.g. `{ singular: "Loan", plural: "Loans" }`.
* Drives the "{subject} passing" KPI card, the "{subject} passed" run column,
* and the run-results dialog title. When omitted, generic "Tests" wording is
* used. Both forms are interpolated into translated strings.
*/
subjectNoun?: { singular: string; plural: string };
/** Maps evaluator ids to display labels in the evaluator-results panel. */
evaluatorLabels?: Record<string, string>;
/** Override the numeric status enum labels (defaults are English fallbacks). */
statusLabels?: StatusLabelOverrides;
/** Score >= threshold renders as a pass; also the KPI trend line. Default 0.9. */
passThreshold?: number;
/** Polling cadence while runs are active, in ms. Default 5000. */
pollIntervalMs?: number;
/** Show the expected/actual input panels in run-result details. Default false. */
showInputs?: boolean;
}

/** Config with all defaults applied — what components consume from context. */
export interface ResolvedSolutionTestsConfig
extends Required<
Pick<
SolutionTestsConfig,
"passThreshold" | "pollIntervalMs" | "showInputs" | "evaluatorLabels"
>
> {
subjectColumns: ColumnDef<SolutionTest>[];
getSubjectHref?: (test: SolutionTest) => string | undefined;
subjectNoun?: { singular: string; plural: string };
statusLabels: Required<StatusLabelOverrides>;
}

export function resolveConfig(
config: SolutionTestsConfig = {},
): ResolvedSolutionTestsConfig {
return {
subjectColumns: config.subjectColumns ?? [],
getSubjectHref: config.getSubjectHref,
subjectNoun: config.subjectNoun,
evaluatorLabels: config.evaluatorLabels ?? {},
statusLabels: {
test: config.statusLabels?.test ?? {},
run: config.statusLabels?.run ?? {},
runResult: config.statusLabels?.runResult ?? {},
},
passThreshold: config.passThreshold ?? 0.9,
pollIntervalMs: config.pollIntervalMs ?? 5000,
showInputs: config.showInputs ?? false,
};
}
Loading