|
@@ -9,7 +9,7 @@ import { HttpError } from './errors.js'
|
|
|
import { isVisibleMessageFile } from '../shared/messageFiles.js'
|
|
import { isVisibleMessageFile } from '../shared/messageFiles.js'
|
|
|
import type { StoredWorkspaceFile } from './workspaceAssets.js'
|
|
import type { StoredWorkspaceFile } from './workspaceAssets.js'
|
|
|
import { notificationPlainText } from './notificationText.js'
|
|
import { notificationPlainText } from './notificationText.js'
|
|
|
-import {supportsHostEnvironment} from '../shared/workspace.js'
|
|
|
|
|
|
|
+import {supportsHostEnvironment,deriveComputer} from '../shared/workspace.js'
|
|
|
import type { WorkspaceLifecycleAction, WorkspaceLifecyclePreview } from '../shared/workspaceLifecycle.js'
|
|
import type { WorkspaceLifecycleAction, WorkspaceLifecyclePreview } from '../shared/workspaceLifecycle.js'
|
|
|
import { decodeAgentMascotAvatar, isAgentImageAvatar, defaultAgentIdentity, encodeAgentAvatar, normalizeAvatar, randomAgentIdentity, MAX_AVATAR_DESCRIPTOR_LENGTH } from '../shared/agentIdentity.js'
|
|
import { decodeAgentMascotAvatar, isAgentImageAvatar, defaultAgentIdentity, encodeAgentAvatar, normalizeAvatar, randomAgentIdentity, MAX_AVATAR_DESCRIPTOR_LENGTH } from '../shared/agentIdentity.js'
|
|
|
import type {
|
|
import type {
|
|
@@ -35,6 +35,7 @@ const avatar = z
|
|
|
'请选择有效的内置头像或 PNG、JPEG、WebP 图片',
|
|
'请选择有效的内置头像或 PNG、JPEG、WebP 图片',
|
|
|
)
|
|
)
|
|
|
const taskTitle = z.string().trim().min(1).max(100).refine((v) => !/[\u0000-\u001f]/.test(v), '标题不能包含控制字符')
|
|
const taskTitle = z.string().trim().min(1).max(100).refine((v) => !/[\u0000-\u001f]/.test(v), '标题不能包含控制字符')
|
|
|
|
|
+const envsInput = z.object({ vm: z.boolean().optional(), cloud: z.boolean().optional(), desktop: z.boolean().optional(), browser: z.boolean().optional() }).strict()
|
|
|
export const agentInput = z
|
|
export const agentInput = z
|
|
|
.object({
|
|
.object({
|
|
|
name,
|
|
name,
|
|
@@ -42,6 +43,7 @@ export const agentInput = z
|
|
|
instructions: z.string().max(24_000).default(''),
|
|
instructions: z.string().max(24_000).default(''),
|
|
|
execution:z.enum(['profile','computer']).default('profile'),
|
|
execution:z.enum(['profile','computer']).default('profile'),
|
|
|
computer:z.enum(['auto','cloud','vm','local','browser','off']).optional(),
|
|
computer:z.enum(['auto','cloud','vm','local','browser','off']).optional(),
|
|
|
|
|
+ envs:envsInput.optional(),
|
|
|
desktopHost:z.union([z.literal('local'),z.string().uuid(),z.null()]).optional(),
|
|
desktopHost:z.union([z.literal('local'),z.string().uuid(),z.null()]).optional(),
|
|
|
allowHostEnvironment:z.boolean().default(false),
|
|
allowHostEnvironment:z.boolean().default(false),
|
|
|
vmExecution:z.enum(['worker','profile']).optional(),
|
|
vmExecution:z.enum(['worker','profile']).optional(),
|
|
@@ -61,6 +63,7 @@ export const agentPatch = z
|
|
|
instructions: z.string().max(24_000).optional(),
|
|
instructions: z.string().max(24_000).optional(),
|
|
|
execution:z.enum(['profile','computer']).optional(),
|
|
execution:z.enum(['profile','computer']).optional(),
|
|
|
computer:z.enum(['auto','cloud','vm','local','browser','off']).optional(),
|
|
computer:z.enum(['auto','cloud','vm','local','browser','off']).optional(),
|
|
|
|
|
+ envs:envsInput.optional(),
|
|
|
desktopHost:z.union([z.literal('local'),z.string().uuid(),z.null()]).optional(),
|
|
desktopHost:z.union([z.literal('local'),z.string().uuid(),z.null()]).optional(),
|
|
|
allowHostEnvironment:z.boolean().optional(),
|
|
allowHostEnvironment:z.boolean().optional(),
|
|
|
vmExecution:z.enum(['worker','profile']).optional(),
|
|
vmExecution:z.enum(['worker','profile']).optional(),
|
|
@@ -446,6 +449,18 @@ export class WorkspaceStore {
|
|
|
if (patch.desktopHost === null) patch.desktopHost = undefined
|
|
if (patch.desktopHost === null) patch.desktopHost = undefined
|
|
|
return this.atomic(() => {
|
|
return this.atomic(() => {
|
|
|
const agent = this.require<Agent>(owner, 'agent', id)
|
|
const agent = this.require<Agent>(owner, 'agent', id)
|
|
|
|
|
+ // Parallel-environment agents keep their set; a raw computer write only
|
|
|
|
|
+ // toggles the VM leg (local-vm enable/disable and Compose bindings).
|
|
|
|
|
+ if(patch.computer!==undefined&&agent.envs){
|
|
|
|
|
+ const envs={...agent.envs}
|
|
|
|
|
+ if(patch.computer==='vm')envs.vm=true
|
|
|
|
|
+ else if(patch.computer==='off'||patch.computer==='auto')envs.vm=false
|
|
|
|
|
+ patch.envs=envs
|
|
|
|
|
+ }
|
|
|
|
|
+ if(patch.envs){
|
|
|
|
|
+ patch.computer=deriveComputer({vm:patch.envs.vm===true,cloud:patch.envs.cloud===true,desktop:patch.envs.desktop===true,browser:patch.envs.browser===true})
|
|
|
|
|
+ patch.execution=patch.computer==='vm'?'computer':'profile'
|
|
|
|
|
+ }
|
|
|
const desktopHostChanged = patch.desktopHost !== undefined && patch.desktopHost !== (agent.desktopHost ?? null)
|
|
const desktopHostChanged = patch.desktopHost !== undefined && patch.desktopHost !== (agent.desktopHost ?? null)
|
|
|
if(patch.vmExecution==='profile'&&patch.allowHostEnvironment===false)throw new HttpError(400,'本机协作模式需要本机环境,请选择虚拟机模式','computer_profile_host_required')
|
|
if(patch.vmExecution==='profile'&&patch.allowHostEnvironment===false)throw new HttpError(400,'本机协作模式需要本机环境,请选择虚拟机模式','computer_profile_host_required')
|
|
|
if(agent.vmExecution==='profile'){
|
|
if(agent.vmExecution==='profile'){
|