From ca465f630204d2e6faf90b8ea330ecfb650e17ce Mon Sep 17 00:00:00 2001 From: Luka Forder Date: Tue, 16 Jun 2026 13:32:12 +0100 Subject: [PATCH 1/6] fix: update api_v1 json --- api_v1.json | 232 +++++++++++++++++++++++++--------------------------- 1 file changed, 112 insertions(+), 120 deletions(-) diff --git a/api_v1.json b/api_v1.json index 852cedc..82815bf 100644 --- a/api_v1.json +++ b/api_v1.json @@ -1274,30 +1274,19 @@ } ] } }, - "/api/v1/agent-rpc/rental-claim" : { + "/api/v1/agent-rpc/claim" : { "post" : { "tags" : [ "agent-rpc" ], - "summary" : "Submit rental agent claim", - "description" : "Requests a certain amount of money to be paid for a work done by a rental agent", - "operationId" : "submitRentalClaim", - "parameters" : [ { - "name" : "remoteSessionId", - "in" : "path", - "description" : "The remote session ID", - "required" : true, - "deprecated" : false, - "explode" : false, - "schema" : { - "type" : "string", - "title" : "String" - } - } ], + "summary" : "Submit an agent claim", + "description" : "Submits a claim for work performed", + "operationId" : "submitClaim", + "parameters" : [ ], "requestBody" : { "description" : "A description of the work done and the payment required", "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/AgentPaymentClaimRequest" + "$ref" : "#/components/schemas/AgentClaimRequest" } } }, @@ -1310,24 +1299,13 @@ "content" : { "application/json" : { "schema" : { - "$ref" : "#/components/schemas/AgentRemainingBudget" + "$ref" : "#/components/schemas/AgentClaimResponse" } } } }, - "404" : { - "description" : "Remote session not found", - "headers" : { }, - "content" : { - "application/json" : { - "schema" : { - "$ref" : "#/components/schemas/RouteException" - } - } - } - }, - "400" : { - "description" : "No payment associated with the session", + "401" : { + "description" : "Bad agent secret provided", "headers" : { }, "content" : { "application/json" : { @@ -3198,9 +3176,13 @@ "$ref" : "#/components/schemas/SessionThread" }, "title" : "ArrayList" + }, + "runningBudget" : { + "$ref" : "#/components/schemas/SessionRunningBudget", + "description" : "A counter for the session's running budget. See SessionRunningBudget for more information" } }, - "required" : [ "agents", "base", "threads" ], + "required" : [ "agents", "base", "runningBudget", "threads" ], "title" : "SessionStateExtended" }, "SessionAgentState" : { @@ -3359,6 +3341,10 @@ "title" : "LinkedHashSet", "uniqueItems" : true }, + "runningBudget" : { + "$ref" : "#/components/schemas/SessionRunningBudget", + "description" : "A counter for the agent's running budget. See SessionRunningBudget for more information" + }, "annotations" : { "type" : "object", "additionalProperties" : { @@ -3366,17 +3352,9 @@ "title" : "String" }, "title" : "LinkedHashMap" - }, - "tokensByModel" : { - "type" : "object", - "additionalProperties" : { - "$ref" : "#/components/schemas/TokenUsage" - }, - "description" : "Token usage broken down by provider/model (e.g. 'openai/gpt-4.1')", - "title" : "LinkedHashMap" } }, - "required" : [ "annotations", "links", "name", "registryAgentIdentifier", "status", "tokensByModel" ], + "required" : [ "annotations", "links", "name", "registryAgentIdentifier", "runningBudget", "status" ], "title" : "SessionAgentState" }, "RegistryAgentIdentifier" : { @@ -3441,22 +3419,54 @@ "required" : [ "name", "registrySourceId", "version" ], "title" : "RegistryAgentIdentifier" }, - "TokenUsage" : { + "SessionRunningBudget" : { "type" : "object", "properties" : { - "inputTokens" : { + "startBudget" : { "type" : "integer", - "format" : "int64", - "title" : "Long" + "title" : "AgentBudgetUnit" }, - "outputTokens" : { + "clamp" : { + "type" : "boolean", + "title" : "Boolean" + }, + "remaining" : { "type" : "integer", - "format" : "int64", - "title" : "Long" + "title" : "AgentBudgetUnit" + }, + "overclaim" : { + "type" : "integer", + "title" : "AgentBudgetUnit" + }, + "claims" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/SessionBudgetClaim" + }, + "title" : "ArrayList" + } + }, + "required" : [ "claims", "clamp", "overclaim", "remaining", "startBudget" ], + "title" : "SessionRunningBudget" + }, + "SessionBudgetClaim" : { + "type" : "object", + "properties" : { + "amount" : { + "type" : "integer", + "title" : "AgentBudgetUnit" + }, + "description" : { + "type" : "string", + "title" : "String" + }, + "timestamp" : { + "type" : "string", + "title" : "UTC timestamp ISO-8601" } }, - "required" : [ "inputTokens", "outputTokens" ], - "title" : "TokenUsage" + "required" : [ "amount", "description", "timestamp" ], + "title" : "SessionBudgetClaim" }, "SessionAgentUsageReport" : { "type" : "object", @@ -4706,6 +4716,11 @@ "type" : "boolean", "description" : "If this is true, the agent will be killed immediately. If this is false, the agent will only be killed if the claim requests for automatic closing.", "title" : "Boolean" + }, + "forceDelay" : { + "type" : "string", + "description" : "If force killing is enabled, it will be delayed by this amount before the agent is killed. If this delay is too low the agent may be killed before it handles to response to a claim", + "title" : "Duration" } }, "required" : [ "force", "minimum", "type" ], @@ -4985,6 +5000,11 @@ "type" : "boolean", "description" : "If this is true, when an agent claims from the session budget that is below the minimum, the agent will be killed immediately. If this is false, the agent will only be killed if the agent requests for automatic closing.", "title" : "Boolean" + }, + "forceDelay" : { + "type" : "string", + "description" : "If force killing is enabled, it will be delayed by this amount before the agent is killed. If this delay is too low the agent may be killed before it handles to response to a claim", + "title" : "Duration" } }, "required" : [ "force", "minimum", "type" ], @@ -5002,6 +5022,11 @@ "type" : "integer", "description" : "The minimum value, specified in micro cents. $1.00 is 100000000 and $0.01 is 1000000.", "title" : "AgentBudgetUnit" + }, + "delay" : { + "type" : "string", + "description" : "The delay before the session is killed. If this delay is too low, the agent whose claim triggered this may be killed before it receives the response to that claim", + "title" : "Duration" } }, "required" : [ "minimum", "type" ], @@ -7783,88 +7808,55 @@ "required" : [ "participantName", "threadId" ], "title" : "RemoveParticipantInput" }, - "AgentPaymentClaimRequest" : { + "AgentClaimRequest" : { "type" : "object", "properties" : { "amount" : { - "anyOf" : [ { - "type" : "object", - "properties" : { - "type" : { - "type" : "string", - "enum" : [ "coral" ], - "title" : "String" - }, - "amount" : { - "type" : "number", - "format" : "double", - "title" : "Double" - } - }, - "required" : [ "amount", "type" ], - "title" : "coral" - }, { - "type" : "object", - "properties" : { - "type" : { - "type" : "string", - "enum" : [ "micro_coral" ], - "title" : "String" - }, - "amount" : { - "type" : "integer", - "format" : "int64", - "title" : "Long" - } - }, - "required" : [ "amount", "type" ], - "title" : "micro_coral" - }, { - "type" : "object", - "properties" : { - "type" : { - "type" : "string", - "enum" : [ "usd" ], - "title" : "String" - }, - "amount" : { - "type" : "number", - "format" : "double", - "title" : "Double" - } - }, - "required" : [ "amount", "type" ], - "title" : "usd" - } ], - "description" : "The amount to claim. This will be converted to Coral when received", - "discriminator" : { - "propertyName" : "type" - }, - "title" : "AgentClaimAmount" + "type" : "integer", + "description" : "The claim amount, specified in micro cents. $1.00 is 100000000 and $0.01 is 1000000.", + "title" : "AgentBudgetUnit" + }, + "description" : { + "type" : "string", + "description" : "A description of the claim, must be at most 256 characters long", + "title" : "String" + }, + "autoKill" : { + "type" : "boolean", + "description" : "Set this to false if the agent wants to handle budget exhaustion itself. Budget settings may kill agents on budget exhaustion even if this is set to false", + "title" : "Boolean" } }, - "required" : [ "amount" ], - "title" : "AgentPaymentClaimRequest" + "required" : [ "amount", "autoKill", "description" ], + "title" : "AgentClaimRequest" }, - "AgentRemainingBudget" : { + "AgentClaimResponse" : { "type" : "object", - "description" : "\n This object is returned by the agent claim endpoint and represents the remaining budget for the agent. The agent \n should use this respond to decide whether whether it can continue providing services with the remaining budget.\n \n This object attaches a USD price for a Coral to it so that agents do not have to make multiple calls to the pricing \n endpoint to determine the price of a Coral. This field is an 'estimate', it can be based off cached data and may not \n be accurate, so this should only be used if the agent represented it's rates in USD.\n \n If better accuracy is required agent-side, the budget should only use micro-corals.\n", + "description" : "A response to a claim request.", "properties" : { - "remainingBudget" : { + "requestedAmount" : { "type" : "integer", - "format" : "int64", - "description" : "The remaining budget for the agent, represented in micro-corals", - "title" : "Long" + "description" : "The amount requested, echoed back to the agent", + "title" : "AgentBudgetUnit" }, - "coralUsdPrice" : { - "type" : "number", - "format" : "double", - "description" : "Current USD price for one whole Coral", - "title" : "Double" + "fulfilledAmount" : { + "type" : "integer", + "description" : "The amount of the budget that could be fulfilled. If this is not equal to the requested amount, the budget was exhausted.", + "title" : "AgentBudgetUnit" + }, + "remainingAmount" : { + "type" : "integer", + "description" : "\n The remaining budget available to the agent. This includes the agent budget and the session budget, if the agent is configured to use it. \n \n NOTE: It is possible that the budgets are configured to warn when empty, which will allow claims to exceed the defined budgets. It is possible that the remaining amount reaches zero but claiming is still possible.\n ", + "title" : "AgentBudgetUnit" + }, + "shouldExit" : { + "type" : "boolean", + "description" : "If this is true, the claim resulted in a budget exhaustion that should cause the agent to exit.", + "title" : "Boolean" } }, - "required" : [ "coralUsdPrice", "remainingBudget" ], - "title" : "AgentRemainingBudget" + "required" : [ "fulfilledAmount", "remainingAmount", "requestedAmount", "shouldExit" ], + "title" : "AgentClaimResponse" }, "X402ProxyRequest" : { "type" : "object", From d4e639af4bc67050b0acf05753da34505becf5a8 Mon Sep 17 00:00:00 2001 From: Luka Forder Date: Tue, 16 Jun 2026 13:32:22 +0100 Subject: [PATCH 2/6] feat: workbench persistence --- src/lib/components/app-sidebar.svelte | 9 +- src/lib/sessionDraftData.ts | 10 + src/routes/(app)/workbench/+page.svelte | 482 +++++++++++++----------- 3 files changed, 270 insertions(+), 231 deletions(-) create mode 100644 src/lib/sessionDraftData.ts diff --git a/src/lib/components/app-sidebar.svelte b/src/lib/components/app-sidebar.svelte index 674c8a8..7d3527a 100644 --- a/src/lib/components/app-sidebar.svelte +++ b/src/lib/components/app-sidebar.svelte @@ -35,6 +35,7 @@ import IconEnvelopeOpen from 'phosphor-icons-svelte/IconEnvelopeOpenRegular.svelte'; import IconDotsThree from 'phosphor-icons-svelte/IconDotsThreeRegular.svelte'; import IconCheckRegular from 'phosphor-icons-svelte/IconCheckRegular.svelte'; + import { sessionDraft, recentSession } from '$lib/sessionDraftData'; import * as Popover from '@coral-os/component-library/ui/popover/index.js'; @@ -358,8 +359,14 @@ -
+
+ {#if sessionDraft.current && sessionDraft.current.agents.length > 0} + draft + {/if}
diff --git a/src/lib/sessionDraftData.ts b/src/lib/sessionDraftData.ts new file mode 100644 index 0000000..4131849 --- /dev/null +++ b/src/lib/sessionDraftData.ts @@ -0,0 +1,10 @@ +import { type FormSchema } from '$lib/sessionSchema/types'; +import { PersistedState } from 'runed'; +import type z from 'zod'; + +export const sessionDraft = new PersistedState | null>( + 'sessionDraftData', + null +); + +export const recentSession = new PersistedState('recentSession', false, { storage: 'session' }); diff --git a/src/routes/(app)/workbench/+page.svelte b/src/routes/(app)/workbench/+page.svelte index 8c2fc50..bf890d6 100644 --- a/src/routes/(app)/workbench/+page.svelte +++ b/src/routes/(app)/workbench/+page.svelte @@ -22,10 +22,7 @@ + + + + Overwrite current session? + + This action cannot be undone. This will delete any unsaved progress in the Workbench. + + + + Close + + + + + {#if sessCtx.payload} {/if} @@ -641,7 +662,7 @@ - {#if emptySession} + {#if emptySession && initialised}
@@ -692,6 +713,8 @@
+ {:else if !initialised} + {/if} @@ -805,7 +828,6 @@ removeAgent(i)} From 4b392ec2f97378cb281931571800d61947f49a07 Mon Sep 17 00:00:00 2001 From: Luka Forder Date: Tue, 16 Jun 2026 16:54:33 +0100 Subject: [PATCH 3/6] feat: badge fix --- src/lib/components/app-sidebar.svelte | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/components/app-sidebar.svelte b/src/lib/components/app-sidebar.svelte index 7d3527a..97e054f 100644 --- a/src/lib/components/app-sidebar.svelte +++ b/src/lib/components/app-sidebar.svelte @@ -361,10 +361,10 @@
- {#if sessionDraft.current && sessionDraft.current.agents.length > 0} + {#if sessionDraft.current && sessionDraft.current.agentGraphRequest.agents.length > 0} draftdraft {/if}
From 40ebea71c37aa0ee137bded8dbdb63284ec58c9b Mon Sep 17 00:00:00 2001 From: Luka Forder Date: Tue, 16 Jun 2026 16:54:41 +0100 Subject: [PATCH 4/6] fix: export types --- src/lib/sessionCreatorContext.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/sessionCreatorContext.ts b/src/lib/sessionCreatorContext.ts index 4d588e9..ea0fbf5 100644 --- a/src/lib/sessionCreatorContext.ts +++ b/src/lib/sessionCreatorContext.ts @@ -8,9 +8,9 @@ import type { CoralServer } from './CoralServer.svelte'; import { z } from 'zod'; import type { SuperForm, SuperFormData, SuperFormErrors } from 'sveltekit-superforms/client'; -type AgentSource = 'marketplace' | 'linked' | 'local'; +export type AgentSource = 'marketplace' | 'linked' | 'local'; -type SessionCreatorContext = { +export type SessionCreatorContext = { payload: CreateSessionRequest | null; importSession: (options: { success?: string; from: string }) => boolean; addAgent: (name: string, source: AgentSource, version: string) => Promise; From 82503bd124195da76e895b9cf89742b909273479 Mon Sep 17 00:00:00 2001 From: Luka Forder Date: Tue, 16 Jun 2026 16:54:53 +0100 Subject: [PATCH 5/6] fix: fix types --- src/lib/sessionDraftData.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/lib/sessionDraftData.ts b/src/lib/sessionDraftData.ts index 4131849..0c57b63 100644 --- a/src/lib/sessionDraftData.ts +++ b/src/lib/sessionDraftData.ts @@ -1,8 +1,12 @@ -import { type FormSchema } from '$lib/sessionSchema/types'; import { PersistedState } from 'runed'; import type z from 'zod'; +import { + makeFormSchema, + type CreateSessionRequest, + type FormSchema +} from '$lib/sessionSchema/types'; -export const sessionDraft = new PersistedState | null>( +export const sessionDraft = new PersistedState( 'sessionDraftData', null ); From 41d10b1d34199615876c05cf9df8edf546022413 Mon Sep 17 00:00:00 2001 From: Luka Forder Date: Tue, 16 Jun 2026 16:55:01 +0100 Subject: [PATCH 6/6] fix: overhaul to change sync --- src/routes/(app)/workbench/+page.svelte | 77 ++++++++++++------------- 1 file changed, 37 insertions(+), 40 deletions(-) diff --git a/src/routes/(app)/workbench/+page.svelte b/src/routes/(app)/workbench/+page.svelte index bf890d6..ee3dbf8 100644 --- a/src/routes/(app)/workbench/+page.svelte +++ b/src/routes/(app)/workbench/+page.svelte @@ -1,26 +1,3 @@ - -