Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.
| Agents mode: an overview of every agent's work and spend, and each agent's sessions, memory, routines, spend, activity and versions | 1 | import { data } from "react-router"; |
| 2 | ||
| 3 | import type { Result, User } from "@g1t/contracts"; | |
| 4 | ||
| 5 | import { assertSameOrigin, requireUser, roleIn } from "../../lib/session.server"; | |
| 6 | import type { ActionResult } from "./dialogs"; | |
| 7 | ||
| 8 | /** What an Agents action knows first: who is asking, in which workspace, whether they own it, and the form. */ | |
| 9 | export async function agentsAction( | |
| 10 | request: Request, | |
| 11 | context: Parameters<typeof requireUser>[0], | |
| 12 | owner: string, | |
| 13 | ): Promise<{ viewer: User; slug: string; isOwner: boolean; form: FormData }> { | |
| 14 | assertSameOrigin(request); | |
| 15 | const viewer = requireUser(context, request); | |
| 16 | const slug = owner.toLowerCase(); | |
| 17 | const role = roleIn(viewer, slug); | |
| 18 | if (!role) throw data(null, { status: 404 }); | |
| 19 | return { viewer, slug, isOwner: role === "owner", form: await request.formData() }; | |
| 20 | } | |
| 21 | ||
| 22 | /** An agents-service call as an action's answer: worked, or why not. */ | |
| 23 | export async function answer<T>(intent: string, call: Promise<Result<T>>): Promise<ActionResult> { | |
| 24 | const result = await call.catch(() => null); | |
| 25 | if (!result) return { ok: false, intent, error: "The agents service didn't answer. Try again in a moment." }; | |
| An archived agent can be found, brought back, or deleted for good. The Agents page ends with Archived, folded, where owners see every archived agent and members their own personal ones, each with when and by whom it was archived and what deleting it would take; Restore brings it back, under a new handle when a live agent has taken its old one, and Delete permanently asks for the handle to be typed and then removes its sessions, replies, memories, routines, versions, drafts, skills and its computer's home, leaving its messages in chat under its saved name, the workspace's spend totals and the audit log. In Chat an archived agent is deactivated the way people expect: never offered as someone to message or mention, never woken, a conversation with it kept in the list, dimmed and marked Archived, open to read with a note in place of the composer and a way to restore it for owners; after deletion the conversation still reads, its messages marked as a deleted agent's. The agents, chat and agent budgets guides say so. | 26 | if (!result.ok) return { ok: false, intent, error: result.error.message, code: result.error.code }; |
| Agents mode: an overview of every agent's work and spend, and each agent's sessions, memory, routines, spend, activity and versions | 27 | return { ok: true, intent }; |
| 28 | } | |
| 29 | ||
| 30 | /** A loader's agents-service read: its value, or null when it failed (the page says so). */ | |
| 31 | export async function readOrNull<T>(call: Promise<Result<T>>): Promise<T | null> { | |
| 32 | const result = await call.catch(() => null); | |
| 33 | return result?.ok ? result.value : null; | |
| 34 | } |