Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
c8a1874
feat(studio): add DevEnv Skill workbench
Aug 4, 2026
4561ad5
fix(studio): support repeat source deployment
Aug 4, 2026
c532f01
fix(studio): expose background Skill task progress
Aug 5, 2026
2025f0a
fix(vefaas): expose safe upload diagnostics
Aug 5, 2026
6e22663
fix(studio): show DevEnv provisioning progress
Aug 5, 2026
9711430
feat(studio): make Skill workbench conversation-first
Aug 5, 2026
f2cd48b
fix(studio): stage clean source deployment wheel
Aug 5, 2026
da0cbe7
style: apply repository formatter
Aug 5, 2026
d375222
feat(studio): refine Skill workbench experience
Aug 5, 2026
9561aea
fix(studio): harden Skill workbench lifecycle UX
Aug 6, 2026
38f8369
fix(studio): make Skill workbench failures actionable
Aug 6, 2026
3a1193d
fix(studio): stabilize Skill workbench DevEnv lifecycle
Aug 6, 2026
ebc6df9
fix(studio): harden AI-native Skill workbench flow
Aug 6, 2026
7e50c0d
fix(studio): harden Skill workbench runtime flow
Aug 6, 2026
0eb45a6
fix(studio): bind Skill artifacts to immutable revisions
Aug 6, 2026
838ee7f
fix(studio): reconcile asynchronous session snapshots
Aug 6, 2026
9befd91
fix(studio): recover Skill artifacts and chat navigation
Aug 6, 2026
f5c1a4c
fix(studio): finalize expired Skill session handling
Aug 6, 2026
4e7142f
fix(studio): isolate Skill refinement revisions
Aug 6, 2026
9359f80
chore(studio): rebuild frontend after main rebase
Aug 6, 2026
add4705
fix(studio): harden Skill delegation contract
Aug 6, 2026
b803acd
test(vefaas): patch active upload client
Aug 6, 2026
ee524bc
test(vefaas): use structured upload log assertions
Aug 6, 2026
3ef6d99
fix(auth): preserve HTTPS origin after OAuth login
Aug 7, 2026
40bfe69
fix(studio): enable Skill workbench on BytePlus
Aug 7, 2026
c626516
fix(studio): select DevEnv image by provider
Aug 7, 2026
a336b1d
refactor(studio): share Dev Sandbox with Skill Workbench
Aug 7, 2026
73ba978
fix(studio): use BytePlus identity branding
Aug 7, 2026
dc5f72a
fix(studio): update BytePlus sandbox model
Aug 7, 2026
f8492c7
fix(studio): publish Skills with provider storage credentials
Aug 7, 2026
52dc698
chore(studio): rebuild frontend after main rebase
Aug 7, 2026
8ec24b5
fix(studio): rebind BytePlus Dev model on update
Aug 7, 2026
54f5ffd
test(studio): isolate provider-dependent CI tests
Aug 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions frontend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,21 @@ server that `veadk frontend` launches — no separate backend.
the normal conversation renderer; leaving the conversation only disconnects
it, so the Agent remains available until the user deletes it. OpenClaw and
Hermes expose their main interface and Terminal through Studio.
- **AgentKit Skill center**: browse Skill Spaces and their skills with
server-side pagination by region, then inspect the selected Skill content.
- **AgentKit Skill center**: browse Skill Spaces and complete Skill packages
with server-side pagination by region. A new-chat-style composer starts
create or optimize conversations directly from the center, using either a
selected Skill or an uploaded ZIP as the optimization source. Skill
conversations share the normal sidebar history, preserve DevEnv progress
across navigation, and expose the complete generated file tree in a
read-only browser. Cloud deployment binds the active provider's hosted model
credential to both the chat CodeEnv and Skill Workbench DevEnv. Studio uses
the VeFaaS IAM role's temporary credentials for AgentKit control-plane calls;
deployer AK/SK are not copied into the function environment. Skill sources
and publication regions come from the active provider (Beijing/Shanghai for
Volcengine and Singapore for BytePlus). Publishing streams each AgentKit
stage, requires a concrete Skill Space destination, and links the completed
version back to that destination in the center. Preview, ZIP download, and
publishing are bound to the same immutable revision and content digest.
- **Automation directory**: browse development and message-channel integrations
from the Studio sidebar. The local Coding Agents integration detects Trae,
Claude Code, and Codex across macOS, Linux, and Windows, then globally installs
Expand Down
1 change: 1 addition & 0 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"@codemirror/lang-markdown": "^6.5.1",
"@codemirror/lang-python": "^6.2.1",
"@codemirror/lang-yaml": "^6.1.3",
"@codemirror/legacy-modes": "^6.5.3",
"@dagrejs/dagre": "^3.0.0",
"@mdxeditor/editor": "^4.1.0",
"@openai/apps-sdk-ui": "^0.2.2",
Expand Down
97 changes: 94 additions & 3 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ import {
import { Sidebar, type SidebarPage } from "./ui/Sidebar";
import { AgentInfoPanel } from "./ui/AgentTopology";
import { SkillCenterView } from "./ui/SkillCenter";
import { SkillWorkbench } from "./ui/skill-workbench/SkillWorkbench";
import { useSkillWorkbenchTasks } from "./ui/skill-workbench/useSkillWorkbenchTasks";
import type { SkillWorkbenchPublishResult } from "./ui/skill-workbench/types";
import { AddAgentKitView } from "./ui/AddAgentKit";
import { AgentWorkspace } from "./ui/AgentWorkspace";
import {
Expand Down Expand Up @@ -1145,6 +1148,13 @@ export default function App() {
// flashing the notice in the common, configured case).
const [hasCreds, setHasCreds] = useState(true);
const [skillCenter, setSkillCenter] = useState(false);
const [skillWorkbenchOpen, setSkillWorkbenchOpen] = useState(false);
const [skillCenterFocus, setSkillCenterFocus] =
useState<SkillWorkbenchPublishResult | null>(null);
const skillWorkbenchTasks = useSkillWorkbenchTasks(
features.skillCenter !== false,
userId,
);
const [addAgent, setAddAgent] = useState(false);
// The "添加 Agent" chooser (two cards: AgentKit / 从 0 快速创建).
const [addMenu, setAddMenu] = useState(false);
Expand Down Expand Up @@ -1203,7 +1213,7 @@ export default function App() {
appName?: string;
currentVersion?: number | null;
} | null>(null);
const [newRuntimeRegion, setNewRuntimeRegion] = useState(
const [newRuntimeRegion, setNewRuntimeRegion] = useState<string>(
defaultCloudRegion(cloudProvider),
);
const [focusedDeploymentTaskId, setFocusedDeploymentTaskId] = useState("");
Expand Down Expand Up @@ -1733,6 +1743,7 @@ export default function App() {
setAppName("");
setCreateView(null);
setSkillCenter(false);
setSkillWorkbenchOpen(false);
setAddAgent(false);
setAddMenu(false);
setSearchView(false);
Expand Down Expand Up @@ -3015,6 +3026,7 @@ export default function App() {
setPlatformFeedbackOrigin(null);
setCreateView(null);
setSkillCenter(false);
setSkillWorkbenchOpen(false);
setAddAgent(false);
setAddMenu(false);
setSearchView(false);
Expand Down Expand Up @@ -3997,6 +4009,7 @@ export default function App() {
setManageAgents(false);
setCreateView(null);
setSkillCenter(false);
setSkillWorkbenchOpen(false);
setAddAgent(false);
setAddMenu(false);
setSearchView(false);
Expand Down Expand Up @@ -4192,10 +4205,18 @@ export default function App() {
? "search"
: myAgents || manageAgents || sandboxAgentDetailTarget || sandboxAgentWorkspace
? "agents"
: sessionId || createView || skillCenter || addAgent || addMenu
: sessionId || createView || skillCenter || skillWorkbenchOpen || addAgent || addMenu
? null
: "new-chat";

const deleteSkillConversation = async (jobId: string) => {
await skillWorkbenchTasks.deleteTask(jobId);
if (skillWorkbenchTasks.activeJobId === jobId) {
setSkillWorkbenchOpen(false);
setSkillCenter(true);
}
};

return (
<div className="layout">
<Sidebar
Expand All @@ -4208,12 +4229,38 @@ export default function App() {
activePage={sidebarActivePage}
streamingSids={streamingSids}
evaluatingSids={evaluatingSids}
skillConversations={skillWorkbenchTasks.tasks}
skillConversationsLoading={skillWorkbenchTasks.tasksLoading}
skillConversationsError={skillWorkbenchTasks.tasksError}
activeSkillConversationId={skillWorkbenchOpen ? skillWorkbenchTasks.activeJobId : ""}
onRetrySkillConversations={() => void skillWorkbenchTasks.refreshTasks()}
onDeleteSkillConversation={deleteSkillConversation}
onOpenSkillConversation={(jobId) => {
if (sandboxSession) exitSandboxSession();
viewSidRef.current = "";
setSessionId("");
setCreateView(null);
setAddAgent(false);
setAddMenu(false);
setSearchView(false);
setManageAgents(false);
setAgentDetailTarget(null);
setSandboxAgentDetailTarget(null);
setSandboxAgentWorkspace(null);
setMyAgents(false);
setApplicationsView(null);
setSkillCenter(false);
skillWorkbenchTasks.selectTask(jobId);
setSkillWorkbenchOpen(true);
setError("");
}}
onNewChat={openNewChat}
onSearch={() => {
setPlatformFeedbackOrigin(null);
if (sandboxSession) exitSandboxSession();
setCreateView(null);
setSkillCenter(false);
setSkillWorkbenchOpen(false);
setAddAgent(false);
setAddMenu(false);
setManageAgents(false);
Expand All @@ -4235,6 +4282,7 @@ export default function App() {
viewSidRef.current = "";
setSessionId("");
setSkillCenter(false);
setSkillWorkbenchOpen(false);
setAddAgent(false);
setSearchView(false);
setManageAgents(false);
Expand All @@ -4261,6 +4309,8 @@ export default function App() {
setSandboxAgentWorkspace(null);
setMyAgents(false);
setApplicationsView(null);
setSkillWorkbenchOpen(false);
setSkillCenterFocus(null);
setSkillCenter(true);
setError("");
}}
Expand Down Expand Up @@ -4303,6 +4353,7 @@ export default function App() {
setPlatformFeedbackOrigin(null);
setCreateView(null);
setSkillCenter(false);
setSkillWorkbenchOpen(false);
setAddAgent(false);
setAddMenu(false);
setSearchView(false);
Expand Down Expand Up @@ -4820,8 +4871,48 @@ export default function App() {
}}
onCancel={() => setAddAgent(false)}
/>
) : skillWorkbenchOpen ? (
<SkillWorkbench
cloudProvider={cloudProvider}
task={skillWorkbenchTasks.activeTask}
provisioningTask={skillWorkbenchTasks.activeProvisioningTask}
taskLoading={skillWorkbenchTasks.activeTaskLoading || skillWorkbenchTasks.startingTask}
taskError={skillWorkbenchTasks.activeTaskError || skillWorkbenchTasks.startError}
taskRecovering={skillWorkbenchTasks.activeTaskRecovering}
artifact={skillWorkbenchTasks.activeArtifact}
artifactLoading={skillWorkbenchTasks.activeArtifactLoading}
artifactError={skillWorkbenchTasks.activeArtifactError}
onTaskChanged={skillWorkbenchTasks.upsertTask}
onCancelProvisioning={skillWorkbenchTasks.cancelProvisioning}
onStopTask={skillWorkbenchTasks.stopTask}
onRetryTask={() => void skillWorkbenchTasks.refreshActiveTask()}
onRetryArtifact={() => {
void skillWorkbenchTasks.refreshActiveArtifact().catch(() => undefined);
}}
onBack={() => {
setSkillWorkbenchOpen(false);
setSkillCenter(true);
}}
onViewPublished={(result) => {
setSkillCenterFocus(result);
setSkillWorkbenchOpen(false);
setSkillCenter(true);
}}
/>
) : skillCenter ? (
<SkillCenterView cloudProvider={cloudProvider} />
<SkillCenterView
cloudProvider={cloudProvider}
focus={skillCenterFocus}
onFocusHandled={() => setSkillCenterFocus(null)}
onStartTask={(args) => {
skillWorkbenchTasks.clearActiveTask();
setSkillCenterFocus(null);
const pending = skillWorkbenchTasks.startTask(args);
setSkillCenter(false);
setSkillWorkbenchOpen(true);
return pending;
}}
/>
) : visibleCreateView !== null && !hasCreds ? (
<div
style={{
Expand Down
12 changes: 10 additions & 2 deletions frontend/src/adk/cloudProvider.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
export type CloudProvider = "volcengine" | "byteplus";
export type CloudRegion = "cn-beijing" | "cn-shanghai" | "ap-southeast-1";

export interface CloudRegionOption {
value: string;
value: CloudRegion;
label: string;
}

Expand All @@ -24,15 +25,22 @@ const VOLCENGINE_REGIONS: CloudRegionOption[] = [
const BYTEPLUS_REGIONS: CloudRegionOption[] = [
{ value: BYTEPLUS_DEFAULT_REGION, label: BYTEPLUS_DEFAULT_REGION },
];
const SUPPORTED_CLOUD_REGIONS: ReadonlySet<string> = new Set(
[...VOLCENGINE_REGIONS, ...BYTEPLUS_REGIONS].map((option) => option.value),
);

export function cloudRegionOptions(provider: CloudProvider): CloudRegionOption[] {
return provider === "byteplus" ? BYTEPLUS_REGIONS : VOLCENGINE_REGIONS;
}

export function defaultCloudRegion(provider: CloudProvider): string {
export function defaultCloudRegion(provider: CloudProvider): CloudRegion {
return cloudRegionOptions(provider)[0]?.value || VOLCENGINE_DEFAULT_REGION;
}

export function isSupportedCloudRegion(value: unknown): value is CloudRegion {
return typeof value === "string" && SUPPORTED_CLOUD_REGIONS.has(value);
}

export function formatCloudRegion(region: string, provider?: CloudProvider): string {
const options = provider
? cloudRegionOptions(provider)
Expand Down
5 changes: 5 additions & 0 deletions frontend/src/create/skills/skillspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ export interface SkillSpacePageOptions {
project?: string;
}

export function formatSkillVersion(version?: string): string {
const normalized = (version || "").trim().replace(/^v+/i, "");
return normalized ? `v${normalized}` : "—";
}

async function jfetch<T>(url: string): Promise<T> {
const res = await fetch(url, {
headers: { accept: "application/json" },
Expand Down
Loading
Loading