Conversation
- New AgentBuilderDialog component with chat + live preview panel - System session service: fix session key prefix and text extraction - Three-step serial create flow (createAgent → updateAgent → setAgentFile) - Dialog prevents accidental close with confirmation prompt - Workspace path derived from app config, not bare slug - AI responds in user locale, agent name enforced as ASCII - i18n: 8 new keys across 8 locales Signed-off-by: samzong <samzong.lu@gmail.com>
|
Hi @samzong, DetailsInstructions for interacting with me using comments are available here. |
Deploying cpwa with
|
| Latest commit: |
40c9472
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://12fd2598.cpwa.pages.dev |
| Branch Preview URL: | https://feat-agent-builder-dialog.cpwa.pages.dev |
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces a significant new feature: an AI Builder dialog designed to simplify the creation of new AI Agents. Instead of manually filling out forms, users can now interact with a conversational AI to define an agent's name, model, and identity, making the process more intuitive, especially for non-technical users. The dialog also provides a live preview of the agent's configuration as it's being built. Additionally, the PR includes crucial bug fixes to the underlying system session service, ensuring robust and correct handling of AI-related events. Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces an AI-driven Agent Builder, allowing users to configure new agents through a guided chat interface. Key changes include the implementation of the AgentBuilderDialog component, a useSystemSession hook, and updates to the system-session-service to support agent-specific session keys. Review feedback highlights several discrepancies between the implementation and the intended design specifications, specifically regarding instruction file naming, dialog dimensions, and a missing exit confirmation prompt. Additionally, improvements were suggested for real-time configuration parsing during streaming and more robust sanitization of workspace slugs.
| } | ||
|
|
||
| if (config.identity.trim() && agentId) { | ||
| const fileRes = await window.clawwork.setAgentFile(gatewayId, agentId, 'instructions.md', config.identity.trim()); |
There was a problem hiding this comment.
There is a discrepancy between the code and the PR description. The description states the identity is written to IDENTITY.md (noting it as a Gateway-allowed filename), but the code uses instructions.md. Please verify the correct filename requirement for the Gateway to ensure the identity is correctly persisted and recognized.
| const fileRes = await window.clawwork.setAgentFile(gatewayId, agentId, 'instructions.md', config.identity.trim()); | |
| const fileRes = await window.clawwork.setAgentFile(gatewayId, agentId, 'IDENTITY.md', config.identity.trim()); |
| }, [open, gatewayId, defaultAgentId, models, start, i18n.language]); | ||
|
|
||
| useEffect(() => { | ||
| if (prevStatusRef.current === 'streaming' && status === 'active') { |
There was a problem hiding this comment.
The current implementation only updates the configuration preview when the session transitions from streaming to active (at the end of a message). To provide the "live preview" mentioned in the PR description, the configuration should also be parsed while the status is streaming so the preview updates as the AI generates the JSON block.
| if (prevStatusRef.current === 'streaming' && status === 'active') { | |
| if (status === 'streaming' || (prevStatusRef.current === 'streaming' && status === 'active')) { |
| if (!config.name.trim()) return; | ||
| setCreating(true); | ||
|
|
||
| const slug = deriveWorkspace(config.name) || config.name.trim().toLowerCase(); |
There was a problem hiding this comment.
The fallback for slug uses the raw trimmed name, which may contain characters invalid for file system paths (e.g., /, \). Since deriveWorkspace is intended to sanitize the name into a safe slug, it should be used exclusively or the fallback should be properly sanitized to ensure a valid workspace path is created.
| const slug = deriveWorkspace(config.name) || config.name.trim().toLowerCase(); | |
| const slug = deriveWorkspace(config.name) || 'new-agent'; |
| const handleClose = useCallback( | ||
| (nextOpen: boolean) => { | ||
| if (!nextOpen && !creating) { | ||
| end(); | ||
| onOpenChange(false); | ||
| } | ||
| }, | ||
| [creating, end, onOpenChange], | ||
| ); |
There was a problem hiding this comment.
The handleClose function is missing the confirmation prompt (window.confirm()) mentioned in the PR description. This is important to prevent users from accidentally losing their conversation progress. Note that the corresponding i18n key for the confirmation message also appears to be missing from the locale files.
const handleClose = useCallback(
(nextOpen: boolean) => {
if (!nextOpen && !creating) {
if (messages.length > 1 && !window.confirm(t('settings.agentBuilderConfirmClose'))) {
return;
}
end();
onOpenChange(false);
}
},
[creating, end, messages.length, onOpenChange, t],
);
|
|
||
| return ( | ||
| <Dialog open={open} onOpenChange={handleClose}> | ||
| <DialogContent className="max-w-4xl p-0 overflow-hidden"> |
| <DialogDescription>{t('settings.agentBuilderDesc')}</DialogDescription> | ||
| </DialogHeader> | ||
|
|
||
| <div className="flex h-128 border-t border-[var(--border-subtle)]"> |
- Use IDENTITY.md instead of instructions.md (Gateway whitelist) - Dialog: max-w-5xl, h-144, block outside-click, X requires confirm - try/catch/finally for create flow to prevent dialog vanishing on error - Parse agent-config during streaming for real-time preview - Workspace slug fallback: safe "new-agent" instead of raw name - System prompt: respond in user locale, enforce ASCII agent names - i18n: add agentBuilderCloseConfirm key across 8 locales Signed-off-by: samzong <samzong.lu@gmail.com>
|
/gemini review |
|
I encountered an error while processing your command:
DetailsInstructions for interacting with me using comments are available here. |
There was a problem hiding this comment.
Code Review
This pull request introduces an AI-driven Agent Builder feature, enabling users to create and configure agents through a guided conversation. Key additions include the AgentBuilderDialog component, a useSystemSession hook, and updates to the system session service and session key format to support agent-specific identifiers. The review feedback identifies several critical improvements: ensuring the agent creation process is atomic to avoid partial failures, normalizing file paths for Windows compatibility, replacing native browser dialogs with themed components to follow the style guide, and enforcing ASCII validation for agent names in the UI.
| const createRes = await window.clawwork.createAgent(gatewayId, { | ||
| name: config.name.trim(), | ||
| workspace, | ||
| }); | ||
| if (!createRes.ok) { | ||
| toast.error(createRes.error ?? t('errors.failed')); | ||
| return; | ||
| } | ||
|
|
||
| const created = createRes.result as Record<string, unknown> | undefined; | ||
| const agentId = (created?.agentId as string) ?? ''; | ||
|
|
||
| if (config.model.trim() && agentId) { | ||
| const updateRes = await window.clawwork.updateAgent(gatewayId, { | ||
| agentId, | ||
| model: config.model.trim(), | ||
| }); | ||
| if (!updateRes.ok) { | ||
| toast.error(updateRes.error ?? t('errors.failed')); | ||
| return; | ||
| } | ||
| } | ||
|
|
||
| if (config.identity.trim() && agentId) { | ||
| const fileRes = await window.clawwork.setAgentFile(gatewayId, agentId, 'IDENTITY.md', config.identity.trim()); | ||
| if (!fileRes.ok) { | ||
| toast.error(fileRes.error ?? t('errors.failed')); | ||
| return; | ||
| } | ||
| } |
There was a problem hiding this comment.
The agent creation process is not atomic, as it relies on three separate IPC calls (createAgent, updateAgent, setAgentFile). If the first call succeeds but subsequent ones fail, an incomplete agent is left behind. This can cause issues when the user tries to recreate the agent with the same name/workspace. Consider implementing a rollback mechanism that deletes the agent if configuration fails.
| try { | ||
| const slug = deriveWorkspace(config.name) || 'new-agent'; | ||
| const wsBase = await window.clawwork.getWorkspacePath(); | ||
| const workspace = wsBase ? `${wsBase}/${slug}` : slug; |
There was a problem hiding this comment.
Manual path construction using a hardcoded forward slash can lead to incorrect paths on Windows or double separators if wsBase already ends with one. Since the renderer lacks access to the path module, consider normalizing the base path before joining.
| const workspace = wsBase ? `${wsBase}/${slug}` : slug; | |
| const workspace = wsBase ? `${wsBase.replace(/[\\/]$/, "")}/${slug}` : slug; |
| const requestClose = useCallback(() => { | ||
| if (creating) return; | ||
| const hasConversation = messages.length > 1; | ||
| if (hasConversation && !window.confirm(t('settings.agentBuilderCloseConfirm'))) return; |
There was a problem hiding this comment.
Using window.confirm is discouraged as it blocks the renderer thread and doesn't adhere to the application's styling and design tokens. It's better to use a custom React-based modal or an IPC call to the main process's native dialog API for a more consistent user experience.
References
- Renderer / UI changes should use themed components and design tokens rather than browser natives. (link)
| <input | ||
| type="text" | ||
| value={config.name} | ||
| onChange={(e) => updateConfigField('name', e.target.value)} |
There was a problem hiding this comment.
The system prompt requires the agent name to be ASCII-only for use as a system identifier. While the AI is instructed to follow this, the UI allows the user to manually enter non-ASCII characters in the preview panel. Validation should be added to ensure the name remains compatible with system requirements.
| onChange={(e) => updateConfigField('name', e.target.value)} | |
| onChange={(e) => { const val = e.target.value; if (/^[ -~]*$/.test(val)) updateConfigField("name", val); }} |
Summary
Add an AI Builder dialog that guides users through creating a new Agent via conversational AI. The dialog uses the existing system session service to power a chat interface, with a live preview panel showing the agent configuration as it evolves.
Type of change
[Feat]new feature[Fix]bug fixWhy is this needed?
Creating an Agent currently requires filling out a form manually. The AI Builder provides a guided, conversational experience that helps users define an agent's name, model, and identity through natural language — lowering the barrier for non-technical users.
Along the way, two pre-existing bugs in the system session service were discovered and fixed:
buildSystemSessionKeyomitted theagent:{agentId}:prefix, causing event handler to drop all system session eventspayload.textdirectly instead ofextractText(), missing structured content blocks from the GatewayWhat changed?
AgentBuilderDialogcomponent with left chat panel + right preview carduseSystemSessionhook bridging core store/service to Reactsystem-session-service: useextractText()from protocol layer, import canonicalChatEventPayloadtypebuildSystemSessionKeyin shared: includeagent:{agentId}:prefix to match Gateway event routingisSystemSessionregex updated to match new prefixed formatgetWorkspacePath()+ slug (not bare slug)IDENTITY.md(Gateway-allowed file name)Architecture impact
buildSystemSessionKeysignature changed (new optionalagentIdparam, backward compatible), core service importsextractTextfrom protocol layerdocs/architecture-invariants.md: session key formatagent:{agentId}:prefix convention as task session keys, ensuring Gateway event routing works correctlyLinked issues
Closes #260
Validation
pnpm lintpnpm testpnpm check:ui-contractpnpm check(full gate: lint + architecture + ui-contract + renderer-copy + i18n + dead-code + format + typecheck + test)Commands, screenshots, or notes:
Screenshots or recordings
Dialog layout: left chat panel with AI conversation, right panel with live agent config preview (name, model, identity). CSS variables used for all colors, design tokens for spacing.
max-w-5xlandh-144for dialog dimensions. Close button uses confirmation prompt viawindow.confirm().Release note
Checklist
[Feat],[Fix],[UI],[Docs],[Refactor],[Build], or[Chore]