diff --git a/apps/arc-web/app/lib/time.ts b/apps/arc-web/app/lib/time.ts index abe6a6a98..cddcd4b16 100644 --- a/apps/arc-web/app/lib/time.ts +++ b/apps/arc-web/app/lib/time.ts @@ -11,3 +11,47 @@ export function timeAgo(iso: string): string { const days = Math.floor(hours / 24); return `${days}d ago`; } + +/** + * Return a human-readable date label for grouping (e.g. "Today", "Yesterday", "Previous 7 days"). + */ +function dateLabel(iso: string): string { + const now = new Date(); + const date = new Date(iso); + const startOfToday = new Date(now.getFullYear(), now.getMonth(), now.getDate()); + const startOfYesterday = new Date(startOfToday.getTime() - 86_400_000); + const startOf7DaysAgo = new Date(startOfToday.getTime() - 7 * 86_400_000); + + if (date >= startOfToday) return "Today"; + if (date >= startOfYesterday) return "Yesterday"; + if (date >= startOf7DaysAgo) return "Previous 7 days"; + return "Older"; +} + +interface SessionItem { + id: string; + title: string; + created_at: string; +} + +interface SessionGroup { + label: string; + sessions: SessionItem[]; +} + +/** + * Group a flat list of sessions (already sorted newest-first) into date-labeled groups. + */ +export function groupSessionsByDate(sessions: SessionItem[]): SessionGroup[] { + const groups: SessionGroup[] = []; + let current: SessionGroup | undefined; + for (const s of sessions) { + const label = dateLabel(s.created_at); + if (!current || current.label !== label) { + current = { label, sessions: [] }; + groups.push(current); + } + current.sessions.push(s); + } + return groups; +} diff --git a/apps/arc-web/app/routes/run-stages.tsx b/apps/arc-web/app/routes/run-stages.tsx index dd33e23c8..0f36c4ff9 100644 --- a/apps/arc-web/app/routes/run-stages.tsx +++ b/apps/arc-web/app/routes/run-stages.tsx @@ -47,9 +47,12 @@ const statusConfig: Record {tool.toolName} - {tool.args} + {tool.durationMs != null && {tool.durationMs}ms} + {tool.input} {open && (
-
Args
-
{tool.args}
+
Input
+
{tool.input}
Result
-
{tool.result}
+
{tool.result}
)} @@ -137,9 +141,12 @@ export default function RunStages({ loaderData }: Route.ComponentProps) { return { kind: "tool" as const, tools: t.tools.map((tu) => ({ + id: tu.id, toolName: tu.tool_name, - args: tu.args, + input: tu.input, result: tu.result, + isError: tu.is_error, + durationMs: tu.duration_ms, })), }; } diff --git a/apps/arc-web/app/routes/session-detail.tsx b/apps/arc-web/app/routes/session-detail.tsx index 5a078fd42..440e86527 100644 --- a/apps/arc-web/app/routes/session-detail.tsx +++ b/apps/arc-web/app/routes/session-detail.tsx @@ -9,9 +9,9 @@ import { UserIcon, WrenchScrewdriverIcon, } from "@heroicons/react/24/outline"; -import { timeAgo } from "../lib/time"; +import { timeAgo, groupSessionsByDate } from "../lib/time"; import { apiJson } from "../api-client"; -import type { SessionDetail as ApiSessionDetail, PaginatedSessionGroupList } from "@qltysh/arc-api-client"; +import type { SessionDetail as ApiSessionDetail, PaginatedSessionList } from "@qltysh/arc-api-client"; import type { Route } from "./+types/session-detail"; export const handle = { hideHeader: true, wide: true }; @@ -21,9 +21,9 @@ export function meta({}: Route.MetaArgs) { } export async function loader({ request, params }: Route.LoaderArgs) { - const [apiSession, { data: apiGroups }] = await Promise.all([ + const [apiSession, { data: apiSessions }] = await Promise.all([ apiJson(`/sessions/${params.sessionId}`, { request }), - apiJson("/sessions", { request }), + apiJson("/sessions", { request }), ]); const session: Session = { id: apiSession.id, @@ -36,30 +36,31 @@ export async function loader({ request, params }: Route.LoaderArgs) { return { kind: "tool" as const, tools: t.tools.map((tu) => ({ + id: tu.id, toolName: tu.tool_name, - args: tu.args, + input: tu.input, result: tu.result, + isError: tu.is_error, + durationMs: tu.duration_ms, })), }; } return { kind: t.kind as "user" | "assistant", content: t.content ?? "", created_at: t.created_at }; }), }; - const sessionGroups = apiGroups.map((g) => ({ - label: g.label, - sessions: g.sessions.map((s) => ({ - id: s.id, - title: s.title, - created_at: s.created_at, - })), - })); + const sessionGroups = groupSessionsByDate( + apiSessions.map((s) => ({ id: s.id, title: s.title, created_at: s.created_at })) + ); return { session, sessionGroups }; } interface ToolUse { + id: string; toolName: string; - args: string; + input: string; result: string; + isError: boolean; + durationMs?: number; } type Turn = @@ -98,19 +99,28 @@ const sessions: Record = { kind: "tool", tools: [ { + id: "toolu_s1_01", toolName: "read_file", - args: `{ "path": "src/routes/auth.ts" }`, + input: `{ "path": "src/routes/auth.ts" }`, result: `import { Router } from "express";\nimport { loginHandler } from "../handlers/auth";\nimport { registerHandler } from "../handlers/auth";\n\nconst router = Router();\nrouter.post("/login", loginHandler);\nrouter.post("/register", registerHandler);\n\nexport default router;`, + isError: false, + durationMs: 45, }, { + id: "toolu_s1_02", toolName: "read_file", - args: `{ "path": "src/middleware/index.ts" }`, + input: `{ "path": "src/middleware/index.ts" }`, result: `export { authMiddleware } from "./auth";\nexport { corsMiddleware } from "./cors";\nexport { loggingMiddleware } from "./logging";`, + isError: false, + durationMs: 38, }, { + id: "toolu_s1_03", toolName: "search_files", - args: `{ "pattern": "redis", "path": "src/" }`, + input: `{ "pattern": "redis", "path": "src/" }`, result: `src/lib/redis.ts:1: import Redis from "ioredis";\nsrc/lib/redis.ts:3: export const redis = new Redis(process.env.REDIS_URL);`, + isError: false, + durationMs: 210, }, ], }, @@ -122,19 +132,28 @@ const sessions: Record = { kind: "tool", tools: [ { + id: "toolu_s1_04", toolName: "write_file", - args: `{ "path": "src/middleware/rate-limit.ts" }`, + input: `{ "path": "src/middleware/rate-limit.ts" }`, result: `File written: src/middleware/rate-limit.ts (47 lines)`, + isError: false, + durationMs: 65, }, { + id: "toolu_s1_05", toolName: "edit_file", - args: `{ "path": "src/routes/auth.ts", "operations": [{ "type": "insert", "line": 3 }] }`, + input: `{ "path": "src/routes/auth.ts", "operations": [{ "type": "insert", "line": 3 }] }`, result: `Applied 1 edit to src/routes/auth.ts`, + isError: false, + durationMs: 42, }, { + id: "toolu_s1_06", toolName: "edit_file", - args: `{ "path": "src/middleware/index.ts", "operations": [{ "type": "append" }] }`, + input: `{ "path": "src/middleware/index.ts", "operations": [{ "type": "append" }] }`, result: `Applied 1 edit to src/middleware/index.ts`, + isError: false, + durationMs: 55, }, ], }, @@ -164,9 +183,12 @@ const sessions: Record = { kind: "tool", tools: [ { + id: "toolu_s2_01", toolName: "read_file", - args: `{ "path": "src/config/parser.ts" }`, + input: `{ "path": "src/config/parser.ts" }`, result: `export function parseConfig(raw: string): Record {\n const result: Record = {};\n for (const line of raw.split("\\n")) {\n const match = line.match(/^(\\w+)\\s*=\\s*(.+)$/);\n if (match) result[match[1]] = match[2].trim();\n }\n return result;\n}`, + isError: false, + durationMs: 52, }, ], }, @@ -178,14 +200,20 @@ const sessions: Record = { kind: "tool", tools: [ { + id: "toolu_s2_02", toolName: "write_file", - args: `{ "path": "src/config/parser.ts" }`, + input: `{ "path": "src/config/parser.ts" }`, result: `File written: src/config/parser.ts (62 lines)`, + isError: false, + durationMs: 78, }, { + id: "toolu_s2_03", toolName: "run_command", - args: `{ "command": "npm test -- --grep 'config parser'" }`, + input: `{ "command": "npm test -- --grep 'config parser'" }`, result: `PASS src/config/__tests__/parser.test.ts\n config parser\n ✓ parses flat keys (2ms)\n ✓ parses section headers (1ms)\n ✓ parses dotted keys (1ms)\n ✓ handles nested sections (1ms)\n\nTest Suites: 1 passed\nTests: 4 passed`, + isError: false, + durationMs: 2150, }, ], }, @@ -207,8 +235,8 @@ const sessions: Record = { { kind: "tool", tools: [ - { toolName: "search_files", args: `{ "pattern": "createBrowserRouter" }`, result: `src/main.tsx:5: import { createBrowserRouter } from "react-router-dom";\nsrc/main.tsx:8: const router = createBrowserRouter([` }, - { toolName: "read_file", args: `{ "path": "package.json" }`, result: `"react-router-dom": "^6.22.0"` }, + { id: "toolu_s3_01", toolName: "search_files", input: `{ "pattern": "createBrowserRouter" }`, result: `src/main.tsx:5: import { createBrowserRouter } from "react-router-dom";\nsrc/main.tsx:8: const router = createBrowserRouter([`, isError: false, durationMs: 180 }, + { id: "toolu_s3_02", toolName: "read_file", input: `{ "path": "package.json" }`, result: `"react-router-dom": "^6.22.0"`, isError: false, durationMs: 35 }, ], }, { kind: "assistant", content: "You're on React Router 6.22. The migration to v7 involves:\n\n1. Replace `react-router-dom` with `react-router` (single package)\n2. Update `createBrowserRouter` import path\n3. Migrate data loaders to the new `Route.LoaderArgs` type\n4. Update any `useLoaderData` calls to be type-safe\n\nLet me make these changes." }, @@ -275,17 +303,18 @@ function ToolRow({ tool }: { tool: ToolUse }) { {tool.toolName} - {tool.args} + {tool.durationMs != null && {tool.durationMs}ms} + {tool.input} {open && (
-
Args
-
{tool.args}
+
Input
+
{tool.input}
Result
-
{tool.result}
+
{tool.result}
)} diff --git a/apps/arc-web/app/routes/start.tsx b/apps/arc-web/app/routes/start.tsx index 7acd20c15..7c8bae253 100644 --- a/apps/arc-web/app/routes/start.tsx +++ b/apps/arc-web/app/routes/start.tsx @@ -20,10 +20,10 @@ import { XMarkIcon, } from "@heroicons/react/24/outline"; import { Link } from "react-router"; -import { timeAgo } from "../lib/time"; +import { timeAgo, groupSessionsByDate } from "../lib/time"; import { apiJson } from "../api-client"; import { getAppConfig } from "../lib/config.server"; -import type { PaginatedProjectList, PaginatedSessionGroupList } from "@qltysh/arc-api-client"; +import type { PaginatedProjectList, PaginatedSessionList } from "@qltysh/arc-api-client"; import type { Route } from "./+types/start"; export const handle = { hideHeader: true, wide: true }; @@ -36,17 +36,12 @@ export async function loader({ request }: Route.LoaderArgs) { const { feature_flags } = getAppConfig(); const [{ data: apiProjects }, { data: apiSessions }] = await Promise.all([ apiJson("/projects", { request }), - apiJson("/sessions", { request }), + apiJson("/sessions", { request }), ]); const projects = apiProjects.map((p) => ({ id: p.id, name: p.name })); - const sessionGroups = apiSessions.map((g) => ({ - label: g.label, - sessions: g.sessions.map((s) => ({ - id: s.id, - title: s.title, - created_at: s.created_at, - })), - })); + const sessionGroups = groupSessionsByDate( + apiSessions.map((s) => ({ id: s.id, title: s.title, created_at: s.created_at })) + ); return { projects, sessionGroups, feature_flags }; } diff --git a/crates/arc-api/src/demo/mod.rs b/crates/arc-api/src/demo/mod.rs index 52022ad80..a0f8ee553 100644 --- a/crates/arc-api/src/demo/mod.rs +++ b/crates/arc-api/src/demo/mod.rs @@ -494,7 +494,7 @@ pub async fn list_sessions( State(_state): State>, Query(pagination): Query, ) -> Response { - paginated_response(sessions::groups(), &pagination) + paginated_response(sessions::list_items(), &pagination) } pub async fn create_session_stub( @@ -1033,8 +1033,8 @@ mod runs { StageTurn { kind: StageTurnKind::Tool, content: None, tools: vec![ - ToolUse { tool_name: "read_file".into(), args: r#"{ "path": "environments/production/config.toml" }"#.into(), result: "[redis]\nhost = \"redis-prod.internal\"\nport = 6379".into() }, - ToolUse { tool_name: "read_file".into(), args: r#"{ "path": "environments/staging/config.toml" }"#.into(), result: "[redis]\nhost = \"redis-staging.internal\"\nport = 6379".into() }, + ToolUse { id: "toolu_01".into(), tool_name: "read_file".into(), input: r#"{ "path": "environments/production/config.toml" }"#.into(), result: "[redis]\nhost = \"redis-prod.internal\"\nport = 6379".into(), is_error: false, duration_ms: Some(45) }, + ToolUse { id: "toolu_02".into(), tool_name: "read_file".into(), input: r#"{ "path": "environments/staging/config.toml" }"#.into(), result: "[redis]\nhost = \"redis-staging.internal\"\nport = 6379".into(), is_error: false, duration_ms: Some(38) }, ], }, StageTurn { kind: StageTurnKind::Assistant, content: Some("I've detected drift in 3 resources between production and staging:\n\n1. **redis.max_connections** — production has 200, staging has 100\n2. **redis.tls** — enabled in production, disabled in staging\n3. **iam.session_duration** — production uses 3600s, staging uses 1800s".into()), tools: vec![] }, @@ -2367,62 +2367,47 @@ mod retros { mod sessions { use arc_types::*; - pub fn groups() -> Vec { + pub fn list_items() -> Vec { vec![ - SessionGroup { - label: "Today".into(), - sessions: vec![ - SessionListItem { - id: "s1".into(), - title: "Add rate limiting to auth endpoints".into(), - created_at: "2026-03-06T14:30:00Z".into(), - }, - SessionListItem { - id: "s2".into(), - title: "Fix config parsing for nested values".into(), - created_at: "2026-03-06T12:30:00Z".into(), - }, - ], + SessionListItem { + id: "s1".into(), + title: "Add rate limiting to auth endpoints".into(), + created_at: "2026-03-06T14:30:00Z".into(), }, - SessionGroup { - label: "Yesterday".into(), - sessions: vec![ - SessionListItem { - id: "s3".into(), - title: "Migrate to React Router v7".into(), - created_at: "2026-03-05T10:00:00Z".into(), - }, - SessionListItem { - id: "s4".into(), - title: "Add dark mode toggle".into(), - created_at: "2026-03-05T09:00:00Z".into(), - }, - SessionListItem { - id: "s5".into(), - title: "Update OpenAPI spec for v3".into(), - created_at: "2026-03-05T08:00:00Z".into(), - }, - ], + SessionListItem { + id: "s2".into(), + title: "Fix config parsing for nested values".into(), + created_at: "2026-03-06T12:30:00Z".into(), }, - SessionGroup { - label: "Previous 7 days".into(), - sessions: vec![ - SessionListItem { - id: "s6".into(), - title: "Terraform module for Redis cluster".into(), - created_at: "2026-03-03T15:00:00Z".into(), - }, - SessionListItem { - id: "s7".into(), - title: "Add pipeline event types".into(), - created_at: "2026-03-01T11:00:00Z".into(), - }, - SessionListItem { - id: "s8".into(), - title: "Implement webhook retry logic".into(), - created_at: "2026-02-28T09:00:00Z".into(), - }, - ], + SessionListItem { + id: "s3".into(), + title: "Migrate to React Router v7".into(), + created_at: "2026-03-05T10:00:00Z".into(), + }, + SessionListItem { + id: "s4".into(), + title: "Add dark mode toggle".into(), + created_at: "2026-03-05T09:00:00Z".into(), + }, + SessionListItem { + id: "s5".into(), + title: "Update OpenAPI spec for v3".into(), + created_at: "2026-03-05T08:00:00Z".into(), + }, + SessionListItem { + id: "s6".into(), + title: "Terraform module for Redis cluster".into(), + created_at: "2026-03-03T15:00:00Z".into(), + }, + SessionListItem { + id: "s7".into(), + title: "Add pipeline event types".into(), + created_at: "2026-03-01T11:00:00Z".into(), + }, + SessionListItem { + id: "s8".into(), + title: "Implement webhook retry logic".into(), + created_at: "2026-02-28T09:00:00Z".into(), }, ] } @@ -2435,15 +2420,15 @@ mod sessions { SessionTurn { kind: SessionTurnKind::User, content: Some("Add rate limiting to the auth endpoints. We're getting hit with brute force attempts on /api/auth/login and /api/auth/register. Use a sliding window approach with Redis, 10 requests per minute per IP.".into()), created_at: Some("2026-02-28T10:00:00Z".into()), tools: vec![] }, SessionTurn { kind: SessionTurnKind::Assistant, content: Some("I'll implement sliding window rate limiting using Redis. Let me first look at the existing auth routes and middleware setup.".into()), created_at: None, tools: vec![] }, SessionTurn { kind: SessionTurnKind::Tool, content: None, created_at: None, tools: vec![ - ToolUse { tool_name: "read_file".into(), args: r#"{ "path": "src/routes/auth.ts" }"#.into(), result: "import { Router } from \"express\";\nimport { loginHandler } from \"../handlers/auth\";\nimport { registerHandler } from \"../handlers/auth\";\n\nconst router = Router();\nrouter.post(\"/login\", loginHandler);\nrouter.post(\"/register\", registerHandler);\n\nexport default router;".into() }, - ToolUse { tool_name: "read_file".into(), args: r#"{ "path": "src/middleware/index.ts" }"#.into(), result: "export { authMiddleware } from \"./auth\";\nexport { corsMiddleware } from \"./cors\";\nexport { loggingMiddleware } from \"./logging\";".into() }, - ToolUse { tool_name: "search_files".into(), args: r#"{ "pattern": "redis", "path": "src/" }"#.into(), result: "src/lib/redis.ts:1: import Redis from \"ioredis\";\nsrc/lib/redis.ts:3: export const redis = new Redis(process.env.REDIS_URL);".into() }, + ToolUse { id: "toolu_03".into(), tool_name: "read_file".into(), input: r#"{ "path": "src/routes/auth.ts" }"#.into(), result: "import { Router } from \"express\";\nimport { loginHandler } from \"../handlers/auth\";\nimport { registerHandler } from \"../handlers/auth\";\n\nconst router = Router();\nrouter.post(\"/login\", loginHandler);\nrouter.post(\"/register\", registerHandler);\n\nexport default router;".into(), is_error: false, duration_ms: Some(52) }, + ToolUse { id: "toolu_04".into(), tool_name: "read_file".into(), input: r#"{ "path": "src/middleware/index.ts" }"#.into(), result: "export { authMiddleware } from \"./auth\";\nexport { corsMiddleware } from \"./cors\";\nexport { loggingMiddleware } from \"./logging\";".into(), is_error: false, duration_ms: Some(35) }, + ToolUse { id: "toolu_05".into(), tool_name: "search_files".into(), input: r#"{ "pattern": "redis", "path": "src/" }"#.into(), result: "src/lib/redis.ts:1: import Redis from \"ioredis\";\nsrc/lib/redis.ts:3: export const redis = new Redis(process.env.REDIS_URL);".into(), is_error: false, duration_ms: Some(180) }, ] }, SessionTurn { kind: SessionTurnKind::Assistant, content: Some("Good \u{2014} there's already a Redis client at `src/lib/redis.ts`. I'll create a rate limiting middleware using the sliding window algorithm and apply it to the auth routes.\n\nHere's the plan:\n1. Create `src/middleware/rate-limit.ts` with sliding window logic\n2. Apply it to `/login` and `/register` routes\n3. Return `429 Too Many Requests` when the limit is exceeded".into()), created_at: None, tools: vec![] }, SessionTurn { kind: SessionTurnKind::Tool, content: None, created_at: None, tools: vec![ - ToolUse { tool_name: "write_file".into(), args: r#"{ "path": "src/middleware/rate-limit.ts" }"#.into(), result: "File written: src/middleware/rate-limit.ts (47 lines)".into() }, - ToolUse { tool_name: "edit_file".into(), args: r#"{ "path": "src/routes/auth.ts", "operations": [{ "type": "insert", "line": 3 }] }"#.into(), result: "Applied 1 edit to src/routes/auth.ts".into() }, - ToolUse { tool_name: "edit_file".into(), args: r#"{ "path": "src/middleware/index.ts", "operations": [{ "type": "append" }] }"#.into(), result: "Applied 1 edit to src/middleware/index.ts".into() }, + ToolUse { id: "toolu_06".into(), tool_name: "write_file".into(), input: r#"{ "path": "src/middleware/rate-limit.ts" }"#.into(), result: "File written: src/middleware/rate-limit.ts (47 lines)".into(), is_error: false, duration_ms: Some(62) }, + ToolUse { id: "toolu_07".into(), tool_name: "edit_file".into(), input: r#"{ "path": "src/routes/auth.ts", "operations": [{ "type": "insert", "line": 3 }] }"#.into(), result: "Applied 1 edit to src/routes/auth.ts".into(), is_error: false, duration_ms: Some(41) }, + ToolUse { id: "toolu_08".into(), tool_name: "edit_file".into(), input: r#"{ "path": "src/middleware/index.ts", "operations": [{ "type": "append" }] }"#.into(), result: "Applied 1 edit to src/middleware/index.ts".into(), is_error: false, duration_ms: Some(55) }, ] }, SessionTurn { kind: SessionTurnKind::Assistant, content: Some("Done. I've created the rate limiter and wired it up:\n\n- **`src/middleware/rate-limit.ts`** \u{2014} Sliding window rate limiter using Redis sorted sets. Each request adds a timestamped entry, expired entries are pruned, and the count is checked against the limit.\n- **`src/routes/auth.ts`** \u{2014} Applied `rateLimit({ windowMs: 60_000, max: 10 })` to both `/login` and `/register`.\n- **`src/middleware/index.ts`** \u{2014} Re-exported the new middleware.\n\nWhen the limit is exceeded, clients get a `429` response with a `Retry-After` header indicating seconds until the window resets.".into()), created_at: None, tools: vec![] }, ], @@ -2454,12 +2439,12 @@ mod sessions { SessionTurn { kind: SessionTurnKind::User, content: Some("The CLI crashes when parsing nested TOML config values like [database.connection]. Can you debug and fix this?".into()), created_at: Some("2026-02-28T10:00:00Z".into()), tools: vec![] }, SessionTurn { kind: SessionTurnKind::Assistant, content: Some("Let me look at the config parser to understand how nested keys are handled.".into()), created_at: None, tools: vec![] }, SessionTurn { kind: SessionTurnKind::Tool, content: None, created_at: None, tools: vec![ - ToolUse { tool_name: "read_file".into(), args: r#"{ "path": "src/config/parser.ts" }"#.into(), result: "export function parseConfig(raw: string): Record {\n const result: Record = {};\n for (const line of raw.split(\"\\n\")) {\n const match = line.match(/^(\\w+)\\s*=\\s*(.+)$/);\n if (match) result[match[1]] = match[2].trim();\n }\n return result;\n}".into() }, + ToolUse { id: "toolu_09".into(), tool_name: "read_file".into(), input: r#"{ "path": "src/config/parser.ts" }"#.into(), result: "export function parseConfig(raw: string): Record {\n const result: Record = {};\n for (const line of raw.split(\"\\n\")) {\n const match = line.match(/^(\\w+)\\s*=\\s*(.+)$/);\n if (match) result[match[1]] = match[2].trim();\n }\n return result;\n}".into(), is_error: false, duration_ms: Some(67) }, ] }, SessionTurn { kind: SessionTurnKind::Assistant, content: Some("Found the issue. The parser uses a flat `Record` and the regex `^(\\w+)` only matches simple keys \u{2014} it can't handle TOML section headers like `[database.connection]` or dotted keys like `database.host`.\n\nI'll rewrite the parser to support nested sections and dotted keys, producing a properly nested object.".into()), created_at: None, tools: vec![] }, SessionTurn { kind: SessionTurnKind::Tool, content: None, created_at: None, tools: vec![ - ToolUse { tool_name: "write_file".into(), args: r#"{ "path": "src/config/parser.ts" }"#.into(), result: "File written: src/config/parser.ts (62 lines)".into() }, - ToolUse { tool_name: "run_command".into(), args: r#"{ "command": "npm test -- --grep 'config parser'" }"#.into(), result: "PASS src/config/__tests__/parser.test.ts\n config parser\n \u{2713} parses flat keys (2ms)\n \u{2713} parses section headers (1ms)\n \u{2713} parses dotted keys (1ms)\n \u{2713} handles nested sections (1ms)\n\nTest Suites: 1 passed\nTests: 4 passed".into() }, + ToolUse { id: "toolu_10".into(), tool_name: "write_file".into(), input: r#"{ "path": "src/config/parser.ts" }"#.into(), result: "File written: src/config/parser.ts (62 lines)".into(), is_error: false, duration_ms: Some(78) }, + ToolUse { id: "toolu_11".into(), tool_name: "run_command".into(), input: r#"{ "command": "npm test -- --grep 'config parser'" }"#.into(), result: "PASS src/config/__tests__/parser.test.ts\n config parser\n \u{2713} parses flat keys (2ms)\n \u{2713} parses section headers (1ms)\n \u{2713} parses dotted keys (1ms)\n \u{2713} handles nested sections (1ms)\n\nTest Suites: 1 passed\nTests: 4 passed".into(), is_error: false, duration_ms: Some(2150) }, ] }, SessionTurn { kind: SessionTurnKind::Assistant, content: Some("Fixed. The parser now:\n\n1. Tracks the current section header (e.g. `[database.connection]`)\n2. Constructs nested objects from dotted paths\n3. Handles both `key = value` within sections and bare `dotted.key = value` syntax\n\nAll 4 tests pass, including the new nested section case.".into()), created_at: None, tools: vec![] }, ], @@ -2470,8 +2455,8 @@ mod sessions { SessionTurn { kind: SessionTurnKind::User, content: Some("Help me migrate our app from React Router v6 to v7. We're using createBrowserRouter with data loaders.".into()), created_at: Some("2026-02-26T10:00:00Z".into()), tools: vec![] }, SessionTurn { kind: SessionTurnKind::Assistant, content: Some("I'll audit your current router setup and identify what needs to change for v7. Let me scan the codebase.".into()), created_at: None, tools: vec![] }, SessionTurn { kind: SessionTurnKind::Tool, content: None, created_at: None, tools: vec![ - ToolUse { tool_name: "search_files".into(), args: r#"{ "pattern": "createBrowserRouter" }"#.into(), result: "src/main.tsx:5: import { createBrowserRouter } from \"react-router-dom\";\nsrc/main.tsx:8: const router = createBrowserRouter([".into() }, - ToolUse { tool_name: "read_file".into(), args: r#"{ "path": "package.json" }"#.into(), result: "\"react-router-dom\": \"^6.22.0\"".into() }, + ToolUse { id: "toolu_12".into(), tool_name: "search_files".into(), input: r#"{ "pattern": "createBrowserRouter" }"#.into(), result: "src/main.tsx:5: import { createBrowserRouter } from \"react-router-dom\";\nsrc/main.tsx:8: const router = createBrowserRouter([".into(), is_error: false, duration_ms: Some(220) }, + ToolUse { id: "toolu_13".into(), tool_name: "read_file".into(), input: r#"{ "path": "package.json" }"#.into(), result: "\"react-router-dom\": \"^6.22.0\"".into(), is_error: false, duration_ms: Some(30) }, ] }, SessionTurn { kind: SessionTurnKind::Assistant, content: Some("You're on React Router 6.22. The migration to v7 involves:\n\n1. Replace `react-router-dom` with `react-router` (single package)\n2. Update `createBrowserRouter` import path\n3. Migrate data loaders to the new `Route.LoaderArgs` type\n4. Update any `useLoaderData` calls to be type-safe\n\nLet me make these changes.".into()), created_at: None, tools: vec![] }, ], diff --git a/docs/api-reference/arc-api.yaml b/docs/api-reference/arc-api.yaml deleted file mode 100644 index e3c58c57b..000000000 --- a/docs/api-reference/arc-api.yaml +++ /dev/null @@ -1,2381 +0,0 @@ -openapi: "3.1.0" -info: - title: Arc Run API - version: "0.1.0" - description: HTTP API for managing Arc workflow run executions. - -tags: - - name: Discovery - description: API discovery and health - - name: Runs - description: Run management operations - - name: Human-in-the-Loop - description: Questions, answers, and steering for runs - - name: Run Outputs - description: Files and verifications produced by runs - - name: Run Internals - description: Internal run details (stages, turns, context, configuration) - - name: Workflows - description: Workflow definitions and execution - - name: Verifications - description: Verification categories and controls - - name: Usage - description: Token and cost usage - - name: Insights - description: SQL query editor and history - - name: Sessions - description: Interactive chat sessions - - name: Retros - description: Run retrospectives - - name: Projects - description: Project and branch management - - name: Settings - description: Platform configuration - -paths: - # ── Discovery ──────────────────────────────────────────────────────── - - /: - get: - operationId: getRoot - tags: [Discovery] - summary: API Discovery - description: Returns discovery URLs for the API. - responses: - "200": - description: Discovery URLs - content: - application/json: - schema: - $ref: "#/components/schemas/RootResponse" - - /health: - get: - operationId: getHealth - tags: [Discovery] - summary: Health Check - responses: - "200": - description: Service is healthy - content: - application/json: - schema: - $ref: "#/components/schemas/HealthResponse" - - /openapi.json: - get: - operationId: getOpenApiSpec - tags: [Discovery] - summary: OpenAPI Specification - description: Returns the OpenAPI spec as JSON. - responses: - "200": - description: OpenAPI specification - content: - application/json: - schema: - type: object - - /user: - get: - operationId: getUser - tags: [Discovery] - summary: Current User - description: Returns info about the authenticated user. - responses: - "200": - description: User info - content: - application/json: - schema: - $ref: "#/components/schemas/UserResponse" - "401": - description: Not authenticated - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - # ── Runs ────────────────────────────────────────────────────────────── - - /runs: - get: - operationId: listRuns - tags: [Runs] - summary: List Runs - parameters: - - $ref: "#/components/parameters/PageLimit" - - $ref: "#/components/parameters/PageOffset" - responses: - "200": - description: Paginated list of runs for the board view - content: - application/json: - schema: - $ref: "#/components/schemas/PaginatedRunList" - post: - operationId: startRun - tags: [Runs] - summary: Start Run - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/StartRunRequest" - responses: - "201": - description: Run created - content: - application/json: - schema: - $ref: "#/components/schemas/StartRunResponse" - "400": - description: Invalid DOT source - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /runs/{id}: - get: - operationId: retrieveRun - tags: [Runs] - summary: Retrieve Run - parameters: - - $ref: "#/components/parameters/RunId" - responses: - "200": - description: Run status - content: - application/json: - schema: - $ref: "#/components/schemas/RunStatusResponse" - "404": - description: Run not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /runs/{id}/cancel: - post: - operationId: cancelRun - tags: [Runs] - summary: Cancel Run - parameters: - - $ref: "#/components/parameters/RunId" - responses: - "200": - description: Run cancelled - content: - application/json: - schema: - type: object - properties: - cancelled: - type: boolean - required: - - cancelled - "404": - description: Run not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "409": - description: Run is not running - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /runs/{id}/graph: - get: - operationId: retrieveRunSvg - tags: [Runs] - summary: Render SVG - parameters: - - $ref: "#/components/parameters/RunId" - responses: - "200": - description: SVG image of the workflow graph - content: - image/svg+xml: - schema: - type: string - "404": - description: Run not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "502": - description: Graphviz not available - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /runs/{id}/checkpoint: - get: - operationId: retrieveRunCheckpoint - tags: [Run Internals] - summary: Retrieve Run Checkpoint - parameters: - - $ref: "#/components/parameters/RunId" - responses: - "200": - description: Checkpoint data (null if not yet available) - content: - application/json: - schema: {} - "404": - description: Run not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /runs/{id}/context: - get: - operationId: retrieveRunContext - tags: [Run Internals] - summary: Retrieve Run Context - parameters: - - $ref: "#/components/parameters/RunId" - responses: - "200": - description: Context key-value map - content: - application/json: - schema: - type: object - "404": - description: Run not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /runs/{id}/events: - get: - operationId: streamRunEvents - tags: [Runs] - summary: Stream Run Events - parameters: - - $ref: "#/components/parameters/RunId" - responses: - "200": - description: Server-sent event stream - content: - text/event-stream: - schema: - type: string - "404": - description: Run not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "410": - description: Event stream closed - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /runs/{id}/questions: - get: - operationId: listRunQuestions - tags: [Human-in-the-Loop] - summary: List Run Questions - parameters: - - $ref: "#/components/parameters/RunId" - responses: - "200": - description: Array of pending questions - content: - application/json: - schema: - $ref: "#/components/schemas/PaginatedApiQuestionList" - "404": - description: Run not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /runs/{id}/questions/{qid}/answer: - post: - operationId: submitRunAnswer - tags: [Human-in-the-Loop] - summary: Submit Run Answer - parameters: - - $ref: "#/components/parameters/RunId" - - name: qid - in: path - required: true - schema: - type: string - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/SubmitAnswerRequest" - responses: - "200": - description: Answer accepted or rejected - content: - application/json: - schema: - $ref: "#/components/schemas/SubmitAnswerResponse" - "400": - description: Invalid option key - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - "404": - description: Run not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /runs/{id}/retro: - get: - operationId: retrieveRetro - tags: [Retros] - summary: Retrieve Retro - parameters: - - $ref: "#/components/parameters/RunId" - responses: - "200": - description: Retro data (null if not yet available) - content: - application/json: - schema: {} - "404": - description: Run not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /runs/{id}/stages: - get: - operationId: listRunStages - tags: [Run Internals] - summary: List Run Stages - parameters: - - $ref: "#/components/parameters/RunId" - responses: - "200": - description: Array of run stages - content: - application/json: - schema: - $ref: "#/components/schemas/PaginatedRunStageList" - "404": - description: Run not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /runs/{id}/stages/{stageId}/turns: - get: - operationId: listStageTurns - tags: [Run Internals] - summary: List Stage Turns - parameters: - - $ref: "#/components/parameters/RunId" - - name: stageId - in: path - required: true - schema: - type: string - - $ref: "#/components/parameters/PageLimit" - - $ref: "#/components/parameters/PageOffset" - responses: - "200": - description: Paginated list of conversation turns - content: - application/json: - schema: - $ref: "#/components/schemas/PaginatedStageTurnList" - "404": - description: Run or stage not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /runs/{id}/compare: - get: - operationId: listRunCompare - tags: [Run Outputs] - summary: List Run Compare - parameters: - - $ref: "#/components/parameters/RunId" - - name: checkpoint - in: query - schema: - type: string - default: "all" - responses: - "200": - description: File changes with checkpoint metadata - content: - application/json: - schema: - $ref: "#/components/schemas/RunCompare" - "404": - description: Run not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /runs/{id}/usage: - get: - operationId: retrieveRunUsage - tags: [Run Outputs] - summary: Retrieve Run Usage - parameters: - - $ref: "#/components/parameters/RunId" - responses: - "200": - description: Usage data - content: - application/json: - schema: - $ref: "#/components/schemas/RunUsage" - "404": - description: Run not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /runs/{id}/verifications: - get: - operationId: listRunVerifications - tags: [Run Outputs] - summary: List Run Verifications - parameters: - - $ref: "#/components/parameters/RunId" - responses: - "200": - description: Array of verification categories with controls - content: - application/json: - schema: - $ref: "#/components/schemas/PaginatedRunVerificationList" - "404": - description: Run not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /runs/{id}/configuration: - get: - operationId: retrieveRunConfiguration - tags: [Run Internals] - summary: Retrieve Run Configuration - parameters: - - $ref: "#/components/parameters/RunId" - responses: - "200": - description: Configuration content - content: - text/plain: - schema: - type: string - "404": - description: Run not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /runs/{id}/steer: - post: - operationId: steerRun - tags: [Human-in-the-Loop] - summary: Steer Run - parameters: - - $ref: "#/components/parameters/RunId" - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/SteerRequest" - responses: - "200": - description: Steering accepted - content: - application/json: - schema: - type: object - properties: - accepted: - type: boolean - required: - - accepted - "404": - description: Run not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /runs/{id}/preview: - post: - operationId: generatePreviewUrl - tags: [Human-in-the-Loop] - summary: Preview URL - parameters: - - $ref: "#/components/parameters/RunId" - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/PreviewUrlRequest" - responses: - "200": - description: Preview URL generated - content: - application/json: - schema: - $ref: "#/components/schemas/PreviewUrlResponse" - "404": - description: Run not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - # ── Workflows ───────────────────────────────────────────────────────── - - /workflows: - get: - operationId: listWorkflows - tags: [Workflows] - summary: List Workflows - parameters: - - $ref: "#/components/parameters/PageLimit" - - $ref: "#/components/parameters/PageOffset" - responses: - "200": - description: Paginated list of workflows - content: - application/json: - schema: - $ref: "#/components/schemas/PaginatedWorkflowList" - - /workflows/{name}: - get: - operationId: retrieveWorkflow - tags: [Workflows] - summary: Retrieve Workflow - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - "200": - description: Workflow detail - content: - application/json: - schema: - $ref: "#/components/schemas/WorkflowDetail" - "404": - description: Workflow not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /workflows/{name}/runs: - get: - operationId: listWorkflowRuns - tags: [Workflows] - summary: List Workflow Runs - parameters: - - name: name - in: path - required: true - schema: - type: string - - $ref: "#/components/parameters/PageLimit" - - $ref: "#/components/parameters/PageOffset" - responses: - "200": - description: Paginated list of runs - content: - application/json: - schema: - $ref: "#/components/schemas/PaginatedRunList" - "404": - description: Workflow not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - post: - operationId: startWorkflowRun - tags: [Workflows] - summary: Start Workflow Run - parameters: - - name: name - in: path - required: true - schema: - type: string - responses: - "201": - description: Run created - content: - application/json: - schema: - $ref: "#/components/schemas/StartRunResponse" - "404": - description: Workflow not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - # ── Verifications ───────────────────────────────────────────────────── - - /verifications: - get: - operationId: listVerifications - tags: [Verifications] - summary: List Verifications - responses: - "200": - description: Array of verification categories - content: - application/json: - schema: - $ref: "#/components/schemas/PaginatedVerificationCategoryList" - - /verifications/{slug}: - get: - operationId: retrieveVerification - tags: [Verifications] - summary: Retrieve Verification - parameters: - - name: slug - in: path - required: true - schema: - type: string - responses: - "200": - description: Verification control detail - content: - application/json: - schema: - $ref: "#/components/schemas/VerificationDetailResponse" - "404": - description: Control not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - # ── Retros ──────────────────────────────────────────────────────────── - - /retros: - get: - operationId: listRetros - tags: [Retros] - summary: List Retros - parameters: - - $ref: "#/components/parameters/PageLimit" - - $ref: "#/components/parameters/PageOffset" - responses: - "200": - description: Paginated list of retros - content: - application/json: - schema: - $ref: "#/components/schemas/PaginatedRetroList" - - # ── Sessions ────────────────────────────────────────────────────────── - - /sessions: - get: - operationId: listSessions - tags: [Sessions] - summary: List Sessions - description: Returns sessions grouped by recency (e.g. "Today", "Yesterday"). Each group contains a flat list of session summaries. - parameters: - - $ref: "#/components/parameters/PageLimit" - - $ref: "#/components/parameters/PageOffset" - responses: - "200": - description: Paginated list of session groups - content: - application/json: - schema: - $ref: "#/components/schemas/PaginatedSessionGroupList" - post: - operationId: createSession - tags: [Sessions] - summary: Create Session - description: Start a new interactive chat session. The initial user prompt is required; a model may optionally be specified. - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/CreateSessionRequest" - responses: - "201": - description: Session created - content: - application/json: - schema: - $ref: "#/components/schemas/CreateSessionResponse" - - /sessions/{id}: - get: - operationId: retrieveSession - tags: [Sessions] - summary: Retrieve Session - description: Returns the full session detail including all conversation turns. - parameters: - - name: id - in: path - required: true - description: Unique session identifier. - schema: - type: string - example: s1 - responses: - "200": - description: Session detail - content: - application/json: - schema: - $ref: "#/components/schemas/SessionDetail" - "404": - description: Session not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /sessions/{id}/messages: - post: - operationId: sendSessionMessage - tags: [Sessions] - summary: Send Session Message - description: Append a user message to an existing session. The server will process it and produce assistant and tool turns asynchronously via the event stream. - parameters: - - name: id - in: path - required: true - description: Unique session identifier. - schema: - type: string - example: s1 - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/SendMessageRequest" - responses: - "200": - description: Message accepted - content: - application/json: - schema: - type: object - properties: - accepted: - type: boolean - description: Whether the message was accepted for processing. - example: true - required: - - accepted - "404": - description: Session not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /sessions/{id}/events: - get: - operationId: streamSessionEvents - tags: [Sessions] - summary: Stream Session Events - description: Opens a server-sent event (SSE) stream for real-time session updates. Events include new assistant turns, tool invocations, and completion signals. - parameters: - - name: id - in: path - required: true - description: Unique session identifier. - schema: - type: string - example: s1 - responses: - "200": - description: Server-sent event stream - content: - text/event-stream: - schema: - type: string - "404": - description: Session not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - # ── Insights ────────────────────────────────────────────────────────── - - /insights/queries: - get: - operationId: listSavedQueries - tags: [Insights] - summary: List Saved Queries - parameters: - - $ref: "#/components/parameters/PageLimit" - - $ref: "#/components/parameters/PageOffset" - responses: - "200": - description: Paginated list of saved queries - content: - application/json: - schema: - $ref: "#/components/schemas/PaginatedSavedQueryList" - post: - operationId: createSavedQuery - tags: [Insights] - summary: Create Saved Query - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/SaveQueryRequest" - responses: - "201": - description: Query saved - content: - application/json: - schema: - $ref: "#/components/schemas/SavedQuery" - - /insights/queries/{id}: - put: - operationId: updateSavedQuery - tags: [Insights] - summary: Update Saved Query - parameters: - - name: id - in: path - required: true - schema: - type: string - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/SaveQueryRequest" - responses: - "200": - description: Query updated - content: - application/json: - schema: - $ref: "#/components/schemas/SavedQuery" - "404": - description: Query not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - delete: - operationId: deleteSavedQuery - tags: [Insights] - summary: Delete Saved Query - parameters: - - name: id - in: path - required: true - schema: - type: string - responses: - "204": - description: Query deleted - "404": - description: Query not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - - /insights/execute: - post: - operationId: executeQuery - tags: [Insights] - summary: Execute Query - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/ExecuteQueryRequest" - responses: - "200": - description: Query results - content: - application/json: - schema: - $ref: "#/components/schemas/ExecuteQueryResponse" - - /insights/history: - get: - operationId: listQueryHistory - tags: [Insights] - summary: List Query History - parameters: - - $ref: "#/components/parameters/PageLimit" - - $ref: "#/components/parameters/PageOffset" - responses: - "200": - description: Paginated list of history entries - content: - application/json: - schema: - $ref: "#/components/schemas/PaginatedHistoryEntryList" - - # ── Usage ──────────────────────────────────────────────────────────── - - /usage: - get: - operationId: getAggregateUsage - tags: [Usage] - summary: Aggregate Usage - description: Returns aggregate token/cost usage across all completed runs since server start. - responses: - "200": - description: Aggregate usage data - content: - application/json: - schema: - $ref: "#/components/schemas/AggregateUsage" - - # ── Settings ────────────────────────────────────────────────────────── - - /settings: - get: - operationId: retrieveServerSettings - tags: [Settings] - summary: Retrieve Server Settings - responses: - "200": - description: Array of setting groups - content: - application/json: - schema: - type: array - items: - $ref: "#/components/schemas/SettingGroup" - - # ── Projects ────────────────────────────────────────────────────────── - - /projects: - get: - operationId: listProjects - tags: [Projects] - summary: List Projects - parameters: - - $ref: "#/components/parameters/PageLimit" - - $ref: "#/components/parameters/PageOffset" - responses: - "200": - description: Paginated list of projects - content: - application/json: - schema: - $ref: "#/components/schemas/PaginatedProjectList" - - /projects/{id}/branches: - get: - operationId: listBranches - tags: [Projects] - summary: List Branches - parameters: - - name: id - in: path - required: true - schema: - type: string - - $ref: "#/components/parameters/PageLimit" - - $ref: "#/components/parameters/PageOffset" - responses: - "200": - description: Paginated list of branches - content: - application/json: - schema: - $ref: "#/components/schemas/PaginatedBranchList" - "404": - description: Project not found - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - -components: - parameters: - RunId: - name: id - in: path - required: true - schema: - type: string - - PageLimit: - name: page[limit] - in: query - required: false - schema: - type: integer - minimum: 1 - maximum: 100 - default: 20 - - PageOffset: - name: page[offset] - in: query - required: false - schema: - type: integer - minimum: 0 - default: 0 - - schemas: - PaginationMeta: - type: object - required: - - has_more - properties: - has_more: - type: boolean - - PaginatedRunList: - type: object - required: - - data - - meta - properties: - data: - type: array - items: - $ref: "#/components/schemas/RunListItem" - meta: - $ref: "#/components/schemas/PaginationMeta" - - PaginatedWorkflowList: - type: object - required: - - data - - meta - properties: - data: - type: array - items: - $ref: "#/components/schemas/WorkflowListItem" - meta: - $ref: "#/components/schemas/PaginationMeta" - - PaginatedRetroList: - type: object - required: - - data - - meta - properties: - data: - type: array - items: - $ref: "#/components/schemas/RetroListItem" - meta: - $ref: "#/components/schemas/PaginationMeta" - - PaginatedSessionGroupList: - type: object - required: - - data - - meta - properties: - data: - type: array - items: - $ref: "#/components/schemas/SessionGroup" - meta: - $ref: "#/components/schemas/PaginationMeta" - - PaginatedProjectList: - type: object - required: - - data - - meta - properties: - data: - type: array - items: - $ref: "#/components/schemas/Project" - meta: - $ref: "#/components/schemas/PaginationMeta" - - PaginatedBranchList: - type: object - required: - - data - - meta - properties: - data: - type: array - items: - $ref: "#/components/schemas/Branch" - meta: - $ref: "#/components/schemas/PaginationMeta" - - PaginatedSavedQueryList: - type: object - required: - - data - - meta - properties: - data: - type: array - items: - $ref: "#/components/schemas/SavedQuery" - meta: - $ref: "#/components/schemas/PaginationMeta" - - PaginatedHistoryEntryList: - type: object - required: - - data - - meta - properties: - data: - type: array - items: - $ref: "#/components/schemas/HistoryEntry" - meta: - $ref: "#/components/schemas/PaginationMeta" - - PaginatedStageTurnList: - type: object - required: - - data - - meta - properties: - data: - type: array - items: - $ref: "#/components/schemas/StageTurn" - meta: - $ref: "#/components/schemas/PaginationMeta" - - PaginatedApiQuestionList: - type: object - required: - - data - - meta - properties: - data: - type: array - items: - $ref: "#/components/schemas/ApiQuestion" - meta: - $ref: "#/components/schemas/PaginationMeta" - - PaginatedRunStageList: - type: object - required: - - data - - meta - properties: - data: - type: array - items: - $ref: "#/components/schemas/RunStage" - meta: - $ref: "#/components/schemas/PaginationMeta" - - PaginatedRunVerificationList: - type: object - required: - - data - - meta - properties: - data: - type: array - items: - $ref: "#/components/schemas/RunVerification" - meta: - $ref: "#/components/schemas/PaginationMeta" - - PaginatedVerificationCategoryList: - type: object - required: - - data - - meta - properties: - data: - type: array - items: - $ref: "#/components/schemas/VerificationCategory" - meta: - $ref: "#/components/schemas/PaginationMeta" - - # ── Existing Run Schemas ──────────────────────────────────────────── - - RunStatus: - type: string - enum: - - queued - - starting - - running - - completed - - failed - - cancelled - - StartRunRequest: - type: object - required: - - dot_source - properties: - dot_source: - type: string - - StartRunResponse: - type: object - required: - - id - properties: - id: - type: string - - RunStatusResponse: - type: object - required: - - id - - status - properties: - id: - type: string - status: - $ref: "#/components/schemas/RunStatus" - error: - type: string - queue_position: - type: integer - - ApiQuestionOption: - type: object - required: - - key - - label - properties: - key: - type: string - label: - type: string - - ApiQuestion: - type: object - required: - - id - - text - - question_type - - options - - allow_freeform - properties: - id: - type: string - text: - type: string - question_type: - $ref: "#/components/schemas/QuestionType" - options: - type: array - items: - $ref: "#/components/schemas/ApiQuestionOption" - allow_freeform: - type: boolean - - QuestionType: - type: string - enum: - - yes_no - - multiple_choice - - multi_select - - freeform - - confirmation - - SubmitAnswerRequest: - type: object - required: - - value - properties: - value: - type: string - selected_option_key: - type: string - - SubmitAnswerResponse: - type: object - required: - - accepted - properties: - accepted: - type: boolean - - ErrorResponseEntry: - type: object - required: - - status - - title - - detail - properties: - status: - type: string - title: - type: string - detail: - type: string - - ErrorResponse: - type: object - required: - - errors - properties: - errors: - type: array - items: - $ref: "#/components/schemas/ErrorResponseEntry" - - # ── New Run Schemas ───────────────────────────────────────────────── - - RunListItemStatus: - type: string - enum: - - working - - pending - - review - - merge - - CheckRunStatus: - type: string - enum: - - success - - failure - - skipped - - pending - - queued - - CheckRun: - type: object - required: - - name - - status - properties: - name: - type: string - status: - $ref: "#/components/schemas/CheckRunStatus" - duration_secs: - type: number - - RunListItem: - type: object - required: - - id - - repo - - title - - workflow - - status - properties: - id: - type: string - repo: - type: string - title: - type: string - workflow: - type: string - status: - $ref: "#/components/schemas/RunListItemStatus" - number: - type: integer - additions: - type: integer - deletions: - type: integer - checks: - type: array - items: - $ref: "#/components/schemas/CheckRun" - elapsed_secs: - type: number - elapsed_warning: - type: boolean - resources: - type: string - comments: - type: integer - question: - type: string - sandbox_id: - type: string - - StageStatus: - type: string - enum: - - completed - - running - - pending - - failed - - RunStage: - type: object - required: - - id - - name - - status - properties: - id: - type: string - name: - type: string - status: - $ref: "#/components/schemas/StageStatus" - duration_secs: - type: number - dot_id: - type: string - - ToolUse: - description: A single tool invocation with its arguments and result. - type: object - required: - - tool_name - - args - - result - properties: - tool_name: - type: string - description: Name of the tool that was invoked. - example: read_file - args: - type: string - description: JSON-encoded arguments passed to the tool. - example: '{ "path": "src/routes/auth.ts" }' - result: - type: string - description: Output returned by the tool. - example: 'import { Router } from "express";' - - StageTurn: - type: object - required: - - kind - properties: - kind: - type: string - enum: - - system - - assistant - - tool - content: - type: string - tools: - type: array - items: - $ref: "#/components/schemas/ToolUse" - - FileCheckpoint: - type: object - required: - - id - - label - properties: - id: - type: string - label: - type: string - - DiffFile: - type: object - required: - - name - - contents - properties: - name: - type: string - contents: - type: string - - FileDiff: - type: object - required: - - old_file - - new_file - properties: - old_file: - $ref: "#/components/schemas/DiffFile" - new_file: - $ref: "#/components/schemas/DiffFile" - - DiffStats: - type: object - required: - - additions - - deletions - properties: - additions: - type: integer - deletions: - type: integer - - RunCompare: - type: object - required: - - checkpoints - - files - - stats - properties: - checkpoints: - type: array - items: - $ref: "#/components/schemas/FileCheckpoint" - files: - type: array - items: - $ref: "#/components/schemas/FileDiff" - stats: - $ref: "#/components/schemas/DiffStats" - - UsageStage: - type: object - required: - - stage - - model - - input_tokens - - output_tokens - - runtime_secs - - cost - properties: - stage: - type: string - model: - type: string - input_tokens: - type: integer - output_tokens: - type: integer - runtime_secs: - type: number - cost: - type: number - - UsageTotals: - type: object - required: - - runtime_secs - - input_tokens - - output_tokens - - cost - properties: - runtime_secs: - type: number - input_tokens: - type: integer - output_tokens: - type: integer - cost: - type: number - - UsageByModel: - type: object - required: - - model - - stages - - input_tokens - - output_tokens - - cost - properties: - model: - type: string - stages: - type: integer - input_tokens: - type: integer - output_tokens: - type: integer - cost: - type: number - - RunUsage: - type: object - required: - - stages - - totals - - by_model - properties: - stages: - type: array - items: - $ref: "#/components/schemas/UsageStage" - totals: - $ref: "#/components/schemas/UsageTotals" - by_model: - type: array - items: - $ref: "#/components/schemas/UsageByModel" - - AggregateUsage: - type: object - required: - - total_runs - - total_input_tokens - - total_output_tokens - - total_cost - - total_runtime_secs - - by_model - properties: - total_runs: - type: integer - total_input_tokens: - type: integer - total_output_tokens: - type: integer - total_cost: - type: number - total_runtime_secs: - type: number - by_model: - type: array - items: - $ref: "#/components/schemas/UsageByModel" - - VerificationStatus: - type: string - enum: - - pass - - fail - - na - - VerificationType: - type: string - enum: - - ai - - automated - - analysis - - ai-analysis - - RunVerificationControl: - type: object - required: - - name - - description - - status - properties: - name: - type: string - description: - type: string - type: - $ref: "#/components/schemas/VerificationType" - status: - $ref: "#/components/schemas/VerificationStatus" - - RunVerification: - type: object - required: - - name - - question - - status - - controls - properties: - name: - type: string - question: - type: string - status: - $ref: "#/components/schemas/VerificationStatus" - controls: - type: array - items: - $ref: "#/components/schemas/RunVerificationControl" - - SteerRequest: - type: object - required: - - file - - line - - guidance - properties: - file: - type: string - line: - type: integer - guidance: - type: string - - PreviewUrlRequest: - type: object - required: - - port - - expires_in_secs - properties: - port: - type: integer - expires_in_secs: - type: integer - - PreviewUrlResponse: - type: object - required: - - url - properties: - url: - type: string - - # ── Workflow Schemas ───────────────────────────────────────────────── - - WorkflowListItem: - type: object - required: - - name - - slug - - filename - properties: - name: - type: string - slug: - type: string - filename: - type: string - last_run: - type: string - schedule: - type: string - next_run: - type: string - - WorkflowDetail: - type: object - required: - - title - - slug - - filename - - description - - config - - graph - properties: - title: - type: string - slug: - type: string - filename: - type: string - description: - type: string - config: - type: string - graph: - type: string - - # ── Verification Schemas ──────────────────────────────────────────── - - EvaluationResult: - type: string - enum: - - pass - - fail - - skip - - VerificationMode: - type: string - enum: - - active - - evaluate - - disabled - - VerificationControl: - type: object - required: - - name - - slug - - description - properties: - name: - type: string - slug: - type: string - description: - type: string - type: - $ref: "#/components/schemas/VerificationType" - mode: - $ref: "#/components/schemas/VerificationMode" - f1: - type: number - pass_at_1: - type: number - evaluations: - type: array - items: - $ref: "#/components/schemas/EvaluationResult" - - VerificationCategory: - type: object - required: - - name - - question - - controls - properties: - name: - type: string - question: - type: string - controls: - type: array - items: - $ref: "#/components/schemas/VerificationControl" - - ControlInfo: - type: object - required: - - name - - slug - - description - - category - properties: - name: - type: string - slug: - type: string - description: - type: string - type: - $ref: "#/components/schemas/VerificationType" - category: - type: string - - ControlPerformance: - type: object - required: - - mode - - evaluations - properties: - mode: - $ref: "#/components/schemas/VerificationMode" - f1: - type: number - pass_at_1: - type: number - evaluations: - type: array - items: - $ref: "#/components/schemas/EvaluationResult" - - ControlDetail: - type: object - required: - - description - - checks - - pass_example - - fail_example - properties: - description: - type: string - checks: - type: array - items: - type: string - pass_example: - type: string - fail_example: - type: string - - RecentControlResult: - type: object - required: - - run_id - - run_title - - workflow - - result - - timestamp - properties: - run_id: - type: string - run_title: - type: string - workflow: - type: string - result: - $ref: "#/components/schemas/VerificationStatus" - timestamp: - type: string - - SiblingControl: - type: object - required: - - name - - slug - properties: - name: - type: string - slug: - type: string - type: - $ref: "#/components/schemas/VerificationType" - mode: - $ref: "#/components/schemas/VerificationMode" - - VerificationDetailResponse: - type: object - required: - - control - - performance - - control_detail - - recent_results - - siblings - properties: - control: - $ref: "#/components/schemas/ControlInfo" - performance: - $ref: "#/components/schemas/ControlPerformance" - control_detail: - $ref: "#/components/schemas/ControlDetail" - recent_results: - type: array - items: - $ref: "#/components/schemas/RecentControlResult" - siblings: - type: array - items: - $ref: "#/components/schemas/SiblingControl" - - # ── Retro Schemas ─────────────────────────────────────────────────── - - SmoothnessRating: - type: string - enum: - - effortless - - smooth - - bumpy - - struggled - - failed - - RetroStats: - type: object - required: - - total_duration_ms - - total_retries - - files_touched - - stages_completed - - stages_failed - properties: - total_duration_ms: - type: integer - total_cost: - type: number - total_retries: - type: integer - files_touched: - type: array - items: - type: string - stages_completed: - type: integer - stages_failed: - type: integer - - RetroListItem: - type: object - required: - - run_id - - workflow_name - - goal - - timestamp - - stats - - friction_point_count - properties: - run_id: - type: string - workflow_name: - type: string - goal: - type: string - timestamp: - type: string - smoothness: - $ref: "#/components/schemas/SmoothnessRating" - stats: - $ref: "#/components/schemas/RetroStats" - friction_point_count: - type: integer - - # ── Session Schemas ───────────────────────────────────────────────── - - SessionListItem: - description: Summary of a session shown in list views. - type: object - required: - - id - - title - - created_at - properties: - id: - type: string - description: Unique session identifier. - example: s1 - title: - type: string - description: Short title summarizing the session topic. - example: Add rate limiting to auth endpoints - created_at: - type: string - description: ISO 8601 timestamp when the session was created. - example: "2026-03-06T14:30:00Z" - - SessionGroup: - description: A group of sessions sharing a time-based label (e.g. "Today", "Yesterday"). - type: object - required: - - label - - sessions - properties: - label: - type: string - description: Human-readable group heading. - example: Today - sessions: - type: array - description: Sessions belonging to this group, ordered by recency. - items: - $ref: "#/components/schemas/SessionListItem" - - SessionTurn: - description: A single turn in a session conversation — a user message, assistant response, or tool invocation block. - type: object - required: - - kind - properties: - kind: - type: string - description: The type of turn. - enum: - - user - - assistant - - tool - example: user - content: - type: string - description: Text content of the turn. Present for user and assistant turns, absent for tool turns. - example: Add rate limiting to the auth endpoints using a sliding window approach with Redis. - created_at: - type: string - description: ISO 8601 timestamp when the turn was created. Typically present for user turns. - example: "2026-02-28T10:00:00Z" - tools: - type: array - description: Tool invocations for this turn. Present only when kind is "tool". - items: - $ref: "#/components/schemas/ToolUse" - - SessionDetail: - description: Full session record including metadata and the complete conversation history. - type: object - required: - - id - - title - - model - - created_at - - updated_at - - turns - properties: - id: - type: string - description: Unique session identifier. - example: s1 - title: - type: string - description: Short title summarizing the session topic. - example: Add rate limiting to auth endpoints - model: - type: string - description: The LLM model used for this session. - example: Opus 4.6 - created_at: - type: string - description: ISO 8601 timestamp when the session was created. - example: "2026-03-06T14:30:00Z" - updated_at: - type: string - description: ISO 8601 timestamp when the session was last updated (e.g. new turn added). - example: "2026-03-06T15:45:00Z" - turns: - type: array - description: Ordered list of conversation turns. - items: - $ref: "#/components/schemas/SessionTurn" - - CreateSessionRequest: - description: Request body for starting a new session. - type: object - required: - - prompt - properties: - prompt: - type: string - description: The initial user message to start the session. - example: Add rate limiting to the auth endpoints using a sliding window approach with Redis, 10 requests per minute per IP. - model: - type: string - description: LLM model to use. If omitted, the server default is used. - example: Opus 4.6 - - CreateSessionResponse: - description: Response returned after successfully creating a session. - type: object - required: - - id - - created_at - properties: - id: - type: string - description: Unique identifier for the newly created session. - example: s42 - created_at: - type: string - description: ISO 8601 timestamp when the session was created. - example: "2026-03-06T16:00:00Z" - - SendMessageRequest: - description: Request body for sending a follow-up message in an existing session. - type: object - required: - - content - properties: - content: - type: string - description: The user message text. - example: Can you also add a bypass for internal health-check IPs? - - # ── Insights Schemas ──────────────────────────────────────────────── - - SavedQuery: - type: object - required: - - id - - name - - sql - properties: - id: - type: string - name: - type: string - sql: - type: string - - SaveQueryRequest: - type: object - required: - - name - - sql - properties: - name: - type: string - sql: - type: string - - ExecuteQueryRequest: - type: object - required: - - sql - properties: - sql: - type: string - - ExecuteQueryResponse: - type: object - required: - - columns - - rows - - elapsed - - row_count - properties: - columns: - type: array - items: - type: string - rows: - type: array - items: - type: array - items: {} - elapsed: - type: number - row_count: - type: integer - - HistoryEntry: - type: object - required: - - id - - sql - - timestamp - - elapsed - - row_count - properties: - id: - type: string - sql: - type: string - timestamp: - type: string - elapsed: - type: number - row_count: - type: integer - - # ── Settings Schemas ──────────────────────────────────────────────── - - SettingFieldType: - type: string - enum: - - text - - select - - toggle - - SettingField: - type: object - required: - - key - - label - - value - - type - properties: - key: - type: string - label: - type: string - value: - type: string - type: - $ref: "#/components/schemas/SettingFieldType" - options: - type: array - items: - type: string - description: - type: string - - SettingGroup: - type: object - required: - - id - - name - - description - - fields - properties: - id: - type: string - name: - type: string - description: - type: string - fields: - type: array - items: - $ref: "#/components/schemas/SettingField" - - # ── Project Schemas ───────────────────────────────────────────────── - - Project: - type: object - required: - - id - - name - properties: - id: - type: string - name: - type: string - - Branch: - type: object - required: - - id - - name - properties: - id: - type: string - name: - type: string - - # ── Discovery Schemas ────────────────────────────────────────────── - - RootResponseUrls: - type: object - required: - - openapi_url - - current_user_url - - health_url - properties: - openapi_url: - type: string - current_user_url: - type: string - health_url: - type: string - - RootResponse: - type: object - required: - - urls - properties: - urls: - $ref: "#/components/schemas/RootResponseUrls" - - HealthResponse: - type: object - required: - - status - properties: - status: - type: string - - UserResponse: - type: object - required: - - login - properties: - login: - type: string diff --git a/docs/api-reference/arc-api.yaml b/docs/api-reference/arc-api.yaml new file mode 120000 index 000000000..3f32abfbd --- /dev/null +++ b/docs/api-reference/arc-api.yaml @@ -0,0 +1 @@ +../../openapi/arc-api.yaml \ No newline at end of file diff --git a/openapi/arc-api.yaml b/openapi/arc-api.yaml index e3c58c57b..2fed54edf 100644 --- a/openapi/arc-api.yaml +++ b/openapi/arc-api.yaml @@ -719,17 +719,17 @@ paths: operationId: listSessions tags: [Sessions] summary: List Sessions - description: Returns sessions grouped by recency (e.g. "Today", "Yesterday"). Each group contains a flat list of session summaries. + description: Returns sessions ordered by recency (newest first). parameters: - $ref: "#/components/parameters/PageLimit" - $ref: "#/components/parameters/PageOffset" responses: "200": - description: Paginated list of session groups + description: Paginated list of sessions content: application/json: schema: - $ref: "#/components/schemas/PaginatedSessionGroupList" + $ref: "#/components/schemas/PaginatedSessionList" post: operationId: createSession tags: [Sessions] @@ -1120,7 +1120,7 @@ components: meta: $ref: "#/components/schemas/PaginationMeta" - PaginatedSessionGroupList: + PaginatedSessionList: type: object required: - data @@ -1129,7 +1129,7 @@ components: data: type: array items: - $ref: "#/components/schemas/SessionGroup" + $ref: "#/components/schemas/SessionListItem" meta: $ref: "#/components/schemas/PaginationMeta" @@ -1478,25 +1478,39 @@ components: type: string ToolUse: - description: A single tool invocation with its arguments and result. + description: A single tool invocation with its input, result, and execution metadata. type: object required: + - id - tool_name - - args + - input - result + - is_error properties: + id: + type: string + description: Unique identifier for this tool invocation. Enables correlation in parallel tool use. + example: toolu_01A09q90qw90lq917835lq9 tool_name: type: string description: Name of the tool that was invoked. example: read_file - args: + input: type: string - description: JSON-encoded arguments passed to the tool. + description: JSON-encoded input passed to the tool. example: '{ "path": "src/routes/auth.ts" }' result: type: string - description: Output returned by the tool. + description: Output returned by the tool. Contains the error message when is_error is true. example: 'import { Router } from "express";' + is_error: + type: boolean + description: Whether the tool invocation failed. When true, the result field contains the error message. + example: false + duration_ms: + type: integer + description: Wall-clock execution time of the tool invocation in milliseconds. + example: 142 StageTurn: type: object @@ -2064,22 +2078,6 @@ components: description: ISO 8601 timestamp when the session was created. example: "2026-03-06T14:30:00Z" - SessionGroup: - description: A group of sessions sharing a time-based label (e.g. "Today", "Yesterday"). - type: object - required: - - label - - sessions - properties: - label: - type: string - description: Human-readable group heading. - example: Today - sessions: - type: array - description: Sessions belonging to this group, ordered by recency. - items: - $ref: "#/components/schemas/SessionListItem" SessionTurn: description: A single turn in a session conversation — a user message, assistant response, or tool invocation block. diff --git a/packages/arc-api-client/src/.openapi-generator/FILES b/packages/arc-api-client/src/.openapi-generator/FILES index 7f6e4c830..79c109885 100644 --- a/packages/arc-api-client/src/.openapi-generator/FILES +++ b/packages/arc-api-client/src/.openapi-generator/FILES @@ -49,7 +49,7 @@ models/paginated-run-list.ts models/paginated-run-stage-list.ts models/paginated-run-verification-list.ts models/paginated-saved-query-list.ts -models/paginated-session-group-list.ts +models/paginated-session-list.ts models/paginated-stage-turn-list.ts models/paginated-verification-category-list.ts models/paginated-workflow-list.ts @@ -75,8 +75,8 @@ models/run-verification.ts models/save-query-request.ts models/saved-query.ts models/send-message-request.ts +models/send-session-message200-response.ts models/session-detail.ts -models/session-group.ts models/session-list-item.ts models/session-turn.ts models/setting-field-type.ts diff --git a/packages/arc-api-client/src/api/sessions-api.ts b/packages/arc-api-client/src/api/sessions-api.ts index 08623201f..1fbd95fad 100644 --- a/packages/arc-api-client/src/api/sessions-api.ts +++ b/packages/arc-api-client/src/api/sessions-api.ts @@ -28,20 +28,20 @@ import type { CreateSessionResponse } from '../models'; // @ts-ignore import type { ErrorResponse } from '../models'; // @ts-ignore -import type { PaginatedSessionGroupList } from '../models'; +import type { PaginatedSessionList } from '../models'; // @ts-ignore import type { SendMessageRequest } from '../models'; // @ts-ignore -import type { SessionDetail } from '../models'; +import type { SendSessionMessage200Response } from '../models'; // @ts-ignore -import type { SteerRun200Response } from '../models'; +import type { SessionDetail } from '../models'; /** * SessionsApi - axios parameter creator */ export const SessionsApiAxiosParamCreator = function (configuration?: Configuration) { return { /** - * + * Start a new interactive chat session. The initial user prompt is required; a model may optionally be specified. * @summary Create Session * @param {CreateSessionRequest} createSessionRequest * @param {*} [options] Override http request option. @@ -76,7 +76,7 @@ export const SessionsApiAxiosParamCreator = function (configuration?: Configurat }; }, /** - * + * Returns sessions ordered by recency (newest first). * @summary List Sessions * @param {number} [pageLimit] * @param {number} [pageOffset] @@ -116,9 +116,9 @@ export const SessionsApiAxiosParamCreator = function (configuration?: Configurat }; }, /** - * + * Returns the full session detail including all conversation turns. * @summary Retrieve Session - * @param {string} id + * @param {string} id Unique session identifier. * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -150,9 +150,9 @@ export const SessionsApiAxiosParamCreator = function (configuration?: Configurat }; }, /** - * + * Append a user message to an existing session. The server will process it and produce assistant and tool turns asynchronously via the event stream. * @summary Send Session Message - * @param {string} id + * @param {string} id Unique session identifier. * @param {SendMessageRequest} sendMessageRequest * @param {*} [options] Override http request option. * @throws {RequiredError} @@ -189,9 +189,9 @@ export const SessionsApiAxiosParamCreator = function (configuration?: Configurat }; }, /** - * + * Opens a server-sent event (SSE) stream for real-time session updates. Events include new assistant turns, tool invocations, and completion signals. * @summary Stream Session Events - * @param {string} id + * @param {string} id Unique session identifier. * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -232,7 +232,7 @@ export const SessionsApiFp = function(configuration?: Configuration) { const localVarAxiosParamCreator = SessionsApiAxiosParamCreator(configuration) return { /** - * + * Start a new interactive chat session. The initial user prompt is required; a model may optionally be specified. * @summary Create Session * @param {CreateSessionRequest} createSessionRequest * @param {*} [options] Override http request option. @@ -245,23 +245,23 @@ export const SessionsApiFp = function(configuration?: Configuration) { return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** - * + * Returns sessions ordered by recency (newest first). * @summary List Sessions * @param {number} [pageLimit] * @param {number} [pageOffset] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async listSessions(pageLimit?: number, pageOffset?: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async listSessions(pageLimit?: number, pageOffset?: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.listSessions(pageLimit, pageOffset, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['SessionsApi.listSessions']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** - * + * Returns the full session detail including all conversation turns. * @summary Retrieve Session - * @param {string} id + * @param {string} id Unique session identifier. * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -272,23 +272,23 @@ export const SessionsApiFp = function(configuration?: Configuration) { return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** - * + * Append a user message to an existing session. The server will process it and produce assistant and tool turns asynchronously via the event stream. * @summary Send Session Message - * @param {string} id + * @param {string} id Unique session identifier. * @param {SendMessageRequest} sendMessageRequest * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async sendSessionMessage(id: string, sendMessageRequest: SendMessageRequest, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async sendSessionMessage(id: string, sendMessageRequest: SendMessageRequest, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.sendSessionMessage(id, sendMessageRequest, options); const localVarOperationServerIndex = configuration?.serverIndex ?? 0; const localVarOperationServerBasePath = operationServerMap['SessionsApi.sendSessionMessage']?.[localVarOperationServerIndex]?.url; return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); }, /** - * + * Opens a server-sent event (SSE) stream for real-time session updates. Events include new assistant turns, tool invocations, and completion signals. * @summary Stream Session Events - * @param {string} id + * @param {string} id Unique session identifier. * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -308,7 +308,7 @@ export const SessionsApiFactory = function (configuration?: Configuration, baseP const localVarFp = SessionsApiFp(configuration) return { /** - * + * Start a new interactive chat session. The initial user prompt is required; a model may optionally be specified. * @summary Create Session * @param {CreateSessionRequest} createSessionRequest * @param {*} [options] Override http request option. @@ -318,20 +318,20 @@ export const SessionsApiFactory = function (configuration?: Configuration, baseP return localVarFp.createSession(createSessionRequest, options).then((request) => request(axios, basePath)); }, /** - * + * Returns sessions ordered by recency (newest first). * @summary List Sessions * @param {number} [pageLimit] * @param {number} [pageOffset] * @param {*} [options] Override http request option. * @throws {RequiredError} */ - listSessions(pageLimit?: number, pageOffset?: number, options?: RawAxiosRequestConfig): AxiosPromise { + listSessions(pageLimit?: number, pageOffset?: number, options?: RawAxiosRequestConfig): AxiosPromise { return localVarFp.listSessions(pageLimit, pageOffset, options).then((request) => request(axios, basePath)); }, /** - * + * Returns the full session detail including all conversation turns. * @summary Retrieve Session - * @param {string} id + * @param {string} id Unique session identifier. * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -339,20 +339,20 @@ export const SessionsApiFactory = function (configuration?: Configuration, baseP return localVarFp.retrieveSession(id, options).then((request) => request(axios, basePath)); }, /** - * + * Append a user message to an existing session. The server will process it and produce assistant and tool turns asynchronously via the event stream. * @summary Send Session Message - * @param {string} id + * @param {string} id Unique session identifier. * @param {SendMessageRequest} sendMessageRequest * @param {*} [options] Override http request option. * @throws {RequiredError} */ - sendSessionMessage(id: string, sendMessageRequest: SendMessageRequest, options?: RawAxiosRequestConfig): AxiosPromise { + sendSessionMessage(id: string, sendMessageRequest: SendMessageRequest, options?: RawAxiosRequestConfig): AxiosPromise { return localVarFp.sendSessionMessage(id, sendMessageRequest, options).then((request) => request(axios, basePath)); }, /** - * + * Opens a server-sent event (SSE) stream for real-time session updates. Events include new assistant turns, tool invocations, and completion signals. * @summary Stream Session Events - * @param {string} id + * @param {string} id Unique session identifier. * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -367,7 +367,7 @@ export const SessionsApiFactory = function (configuration?: Configuration, baseP */ export class SessionsApi extends BaseAPI { /** - * + * Start a new interactive chat session. The initial user prompt is required; a model may optionally be specified. * @summary Create Session * @param {CreateSessionRequest} createSessionRequest * @param {*} [options] Override http request option. @@ -378,7 +378,7 @@ export class SessionsApi extends BaseAPI { } /** - * + * Returns sessions ordered by recency (newest first). * @summary List Sessions * @param {number} [pageLimit] * @param {number} [pageOffset] @@ -390,9 +390,9 @@ export class SessionsApi extends BaseAPI { } /** - * + * Returns the full session detail including all conversation turns. * @summary Retrieve Session - * @param {string} id + * @param {string} id Unique session identifier. * @param {*} [options] Override http request option. * @throws {RequiredError} */ @@ -401,9 +401,9 @@ export class SessionsApi extends BaseAPI { } /** - * + * Append a user message to an existing session. The server will process it and produce assistant and tool turns asynchronously via the event stream. * @summary Send Session Message - * @param {string} id + * @param {string} id Unique session identifier. * @param {SendMessageRequest} sendMessageRequest * @param {*} [options] Override http request option. * @throws {RequiredError} @@ -413,9 +413,9 @@ export class SessionsApi extends BaseAPI { } /** - * + * Opens a server-sent event (SSE) stream for real-time session updates. Events include new assistant turns, tool invocations, and completion signals. * @summary Stream Session Events - * @param {string} id + * @param {string} id Unique session identifier. * @param {*} [options] Override http request option. * @throws {RequiredError} */ diff --git a/packages/arc-api-client/src/models/create-session-request.ts b/packages/arc-api-client/src/models/create-session-request.ts index ec352d207..2a1028542 100644 --- a/packages/arc-api-client/src/models/create-session-request.ts +++ b/packages/arc-api-client/src/models/create-session-request.ts @@ -14,8 +14,17 @@ +/** + * Request body for starting a new session. + */ export interface CreateSessionRequest { + /** + * The initial user message to start the session. + */ 'prompt': string; + /** + * LLM model to use. If omitted, the server default is used. + */ 'model'?: string; } diff --git a/packages/arc-api-client/src/models/create-session-response.ts b/packages/arc-api-client/src/models/create-session-response.ts index 922847e54..1d0938e67 100644 --- a/packages/arc-api-client/src/models/create-session-response.ts +++ b/packages/arc-api-client/src/models/create-session-response.ts @@ -14,8 +14,17 @@ +/** + * Response returned after successfully creating a session. + */ export interface CreateSessionResponse { + /** + * Unique identifier for the newly created session. + */ 'id': string; + /** + * ISO 8601 timestamp when the session was created. + */ 'created_at': string; } diff --git a/packages/arc-api-client/src/models/index.ts b/packages/arc-api-client/src/models/index.ts index 95c40a7bb..86c20dfc7 100644 --- a/packages/arc-api-client/src/models/index.ts +++ b/packages/arc-api-client/src/models/index.ts @@ -30,7 +30,7 @@ export * from './paginated-run-list'; export * from './paginated-run-stage-list'; export * from './paginated-run-verification-list'; export * from './paginated-saved-query-list'; -export * from './paginated-session-group-list'; +export * from './paginated-session-list'; export * from './paginated-stage-turn-list'; export * from './paginated-verification-category-list'; export * from './paginated-workflow-list'; @@ -56,8 +56,8 @@ export * from './run-verification-control'; export * from './save-query-request'; export * from './saved-query'; export * from './send-message-request'; +export * from './send-session-message200-response'; export * from './session-detail'; -export * from './session-group'; export * from './session-list-item'; export * from './session-turn'; export * from './setting-field'; diff --git a/packages/arc-api-client/src/models/paginated-session-list.ts b/packages/arc-api-client/src/models/paginated-session-list.ts new file mode 100644 index 000000000..1997ccb14 --- /dev/null +++ b/packages/arc-api-client/src/models/paginated-session-list.ts @@ -0,0 +1,27 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Arc Run API + * HTTP API for managing Arc workflow run executions. + * + * The version of the OpenAPI document: 0.1.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +// May contain unused imports in some cases +// @ts-ignore +import type { PaginationMeta } from './pagination-meta'; +// May contain unused imports in some cases +// @ts-ignore +import type { SessionListItem } from './session-list-item'; + +export interface PaginatedSessionList { + 'data': Array; + 'meta': PaginationMeta; +} + diff --git a/packages/arc-api-client/src/models/send-message-request.ts b/packages/arc-api-client/src/models/send-message-request.ts index 21dc454ad..e0769b24f 100644 --- a/packages/arc-api-client/src/models/send-message-request.ts +++ b/packages/arc-api-client/src/models/send-message-request.ts @@ -14,7 +14,13 @@ +/** + * Request body for sending a follow-up message in an existing session. + */ export interface SendMessageRequest { + /** + * The user message text. + */ 'content': string; } diff --git a/packages/arc-api-client/src/models/send-session-message200-response.ts b/packages/arc-api-client/src/models/send-session-message200-response.ts new file mode 100644 index 000000000..f59e634d4 --- /dev/null +++ b/packages/arc-api-client/src/models/send-session-message200-response.ts @@ -0,0 +1,23 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Arc Run API + * HTTP API for managing Arc workflow run executions. + * + * The version of the OpenAPI document: 0.1.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +export interface SendSessionMessage200Response { + /** + * Whether the message was accepted for processing. + */ + 'accepted': boolean; +} + diff --git a/packages/arc-api-client/src/models/session-detail.ts b/packages/arc-api-client/src/models/session-detail.ts index 4b6c3fca2..66fbdd085 100644 --- a/packages/arc-api-client/src/models/session-detail.ts +++ b/packages/arc-api-client/src/models/session-detail.ts @@ -17,12 +17,33 @@ // @ts-ignore import type { SessionTurn } from './session-turn'; +/** + * Full session record including metadata and the complete conversation history. + */ export interface SessionDetail { + /** + * Unique session identifier. + */ 'id': string; + /** + * Short title summarizing the session topic. + */ 'title': string; + /** + * The LLM model used for this session. + */ 'model': string; + /** + * ISO 8601 timestamp when the session was created. + */ 'created_at': string; + /** + * ISO 8601 timestamp when the session was last updated (e.g. new turn added). + */ 'updated_at': string; + /** + * Ordered list of conversation turns. + */ 'turns': Array; } diff --git a/packages/arc-api-client/src/models/session-group.ts b/packages/arc-api-client/src/models/session-group.ts index c9f6a546f..967666b59 100644 --- a/packages/arc-api-client/src/models/session-group.ts +++ b/packages/arc-api-client/src/models/session-group.ts @@ -17,8 +17,17 @@ // @ts-ignore import type { SessionListItem } from './session-list-item'; +/** + * A group of sessions sharing a time-based label (e.g. \"Today\", \"Yesterday\"). + */ export interface SessionGroup { + /** + * Human-readable group heading. + */ 'label': string; + /** + * Sessions belonging to this group, ordered by recency. + */ 'sessions': Array; } diff --git a/packages/arc-api-client/src/models/session-list-item.ts b/packages/arc-api-client/src/models/session-list-item.ts index aabe1169b..26dfcaa5f 100644 --- a/packages/arc-api-client/src/models/session-list-item.ts +++ b/packages/arc-api-client/src/models/session-list-item.ts @@ -14,9 +14,21 @@ +/** + * Summary of a session shown in list views. + */ export interface SessionListItem { + /** + * Unique session identifier. + */ 'id': string; + /** + * Short title summarizing the session topic. + */ 'title': string; + /** + * ISO 8601 timestamp when the session was created. + */ 'created_at': string; } diff --git a/packages/arc-api-client/src/models/session-turn.ts b/packages/arc-api-client/src/models/session-turn.ts index 207102692..20d21f64f 100644 --- a/packages/arc-api-client/src/models/session-turn.ts +++ b/packages/arc-api-client/src/models/session-turn.ts @@ -17,10 +17,25 @@ // @ts-ignore import type { ToolUse } from './tool-use'; +/** + * A single turn in a session conversation — a user message, assistant response, or tool invocation block. + */ export interface SessionTurn { + /** + * The type of turn. + */ 'kind': SessionTurnKindEnum; + /** + * Text content of the turn. Present for user and assistant turns, absent for tool turns. + */ 'content'?: string; + /** + * ISO 8601 timestamp when the turn was created. Typically present for user turns. + */ 'created_at'?: string; + /** + * Tool invocations for this turn. Present only when kind is \"tool\". + */ 'tools'?: Array; } diff --git a/packages/arc-api-client/src/models/tool-use.ts b/packages/arc-api-client/src/models/tool-use.ts index 33f697c54..28a878d1a 100644 --- a/packages/arc-api-client/src/models/tool-use.ts +++ b/packages/arc-api-client/src/models/tool-use.ts @@ -14,9 +14,33 @@ +/** + * A single tool invocation with its input, result, and execution metadata. + */ export interface ToolUse { + /** + * Unique identifier for this tool invocation. Enables correlation in parallel tool use. + */ + 'id': string; + /** + * Name of the tool that was invoked. + */ 'tool_name': string; - 'args': string; + /** + * JSON-encoded input passed to the tool. + */ + 'input': string; + /** + * Output returned by the tool. Contains the error message when is_error is true. + */ 'result': string; + /** + * Whether the tool invocation failed. When true, the result field contains the error message. + */ + 'is_error': boolean; + /** + * Wall-clock execution time of the tool invocation in milliseconds. + */ + 'duration_ms'?: number; }