@swarmclawai/swarmclaw 1.9.2 → 1.9.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/README.md +23 -3
  2. package/electron-dist/main.js +218 -0
  3. package/package.json +2 -2
  4. package/src/app/api/extensions/managed-resources/route.test.ts +117 -0
  5. package/src/app/api/extensions/managed-resources/route.ts +116 -0
  6. package/src/app/api/gateways/[id]/environments/[environmentId]/route.ts +16 -0
  7. package/src/app/api/gateways/[id]/environments/route.ts +13 -0
  8. package/src/app/api/gateways/topology-route.test.ts +30 -0
  9. package/src/app/api/tasks/task-workspace-route.test.ts +4 -0
  10. package/src/cli/index.js +4 -0
  11. package/src/cli/spec.js +4 -0
  12. package/src/components/providers/provider-list.tsx +34 -1
  13. package/src/components/tasks/task-sheet.tsx +50 -0
  14. package/src/features/gateways/queries.ts +3 -0
  15. package/src/lib/server/extension-managed-resources.test.ts +159 -0
  16. package/src/lib/server/extension-managed-resources.ts +905 -0
  17. package/src/lib/server/extensions.ts +113 -2
  18. package/src/lib/server/gateways/gateway-profile-service.ts +2 -0
  19. package/src/lib/server/gateways/gateway-topology.test.ts +59 -3
  20. package/src/lib/server/gateways/gateway-topology.ts +129 -3
  21. package/src/lib/server/operations/operation-pulse.test.ts +29 -0
  22. package/src/lib/server/operations/operation-pulse.ts +9 -0
  23. package/src/lib/server/session-tools/extension-creator.ts +50 -0
  24. package/src/lib/server/tasks/task-execution-workspace.test.ts +14 -0
  25. package/src/lib/server/tasks/task-execution-workspace.ts +133 -6
  26. package/src/types/agent.ts +2 -0
  27. package/src/types/app-settings.ts +8 -0
  28. package/src/types/extension.ts +132 -0
  29. package/src/types/misc.ts +31 -0
  30. package/src/types/schedule.ts +3 -0
  31. package/src/types/task.ts +30 -0
  32. package/src/views/settings/extension-manager.tsx +157 -1
@@ -66,10 +66,24 @@ describe('task execution workspaces', () => {
66
66
  assert.match(patch.executionWorkspace.path, /task-alpha-launch-qa-preview/)
67
67
  assert.equal(fs.existsSync(patch.executionWorkspace.path), true)
68
68
  assert.equal(fs.existsSync(patch.executionWorkspace.readmePath || ''), true)
69
+ assert.equal(fs.existsSync(patch.executionWorkspace.contextPath || ''), true)
70
+ assert.equal(fs.existsSync(patch.executionWorkspace.envPath || ''), true)
69
71
  assert.equal(patch.executionWorkspace.sourceCwd, '/repo/source')
72
+ assert.equal(patch.executionWorkspace.context?.taskId, 'task-alpha')
73
+ assert.equal(patch.executionWorkspace.context?.workspacePath, patch.executionWorkspace.path)
74
+ assert.equal(patch.executionWorkspace.envHints?.some((hint) => hint.key === 'WORKSPACE_CWD'), true)
75
+ assert.equal(patch.executionWorkspace.envHints?.some((hint) => hint.key === 'KANBAN_TASK_ID'), true)
70
76
  assert.equal(patch.executionWorkspace.previewLinks[0]?.label, 'Local preview')
71
77
  assert.equal(patch.previewLinks[0]?.url, 'http://127.0.0.1:3456')
72
78
  assert.equal(patch.runtimeServices[0]?.status, 'planned')
79
+
80
+ const context = JSON.parse(fs.readFileSync(patch.executionWorkspace.contextPath || '', 'utf8'))
81
+ assert.equal(context.taskId, 'task-alpha')
82
+ assert.equal(context.previewLinks[0]?.url, 'http://127.0.0.1:3456')
83
+ const envFile = fs.readFileSync(patch.executionWorkspace.envPath || '', 'utf8')
84
+ assert.equal(envFile.includes('SWARMCLAW_TASK_ID="task-alpha"'), true)
85
+ assert.equal(envFile.includes('WORKSPACE_SOURCE="/repo/source"'), true)
86
+ assert.equal(envFile.includes('KANBAN_WORKSPACE='), true)
73
87
  })
74
88
 
75
89
  it('deduplicates preview URLs and computes blocked, stale, and retrying liveness', () => {
@@ -7,6 +7,8 @@ import type {
7
7
  TaskExecutionWorkspace,
8
8
  TaskLivenessSnapshot,
9
9
  TaskPreviewLink,
10
+ TaskRuntimeContextPacket,
11
+ TaskRuntimeEnvHint,
10
12
  TaskRuntimeService,
11
13
  } from '@/types'
12
14
 
@@ -182,11 +184,106 @@ function writeWorkspaceReadme(task: BoardTask, workspacePath: string, now: numbe
182
184
  ]
183
185
  if (task.projectId) lines.push(`Project ID: ${task.projectId}`)
184
186
  if (task.cwd) lines.push(`Source cwd: ${task.cwd}`)
185
- lines.push('', 'Use this directory for task-local notes, generated artifacts, and preview handoff files.')
187
+ lines.push(
188
+ '',
189
+ 'Runtime context: ./context.json',
190
+ 'Environment hints: ./.env.swarmclaw',
191
+ '',
192
+ 'Use this directory for task-local notes, generated artifacts, and preview handoff files.',
193
+ )
186
194
  fs.writeFileSync(readmePath, `${lines.join('\n')}\n`, 'utf8')
187
195
  return readmePath
188
196
  }
189
197
 
198
+ function addEnvHint(out: TaskRuntimeEnvHint[], key: string, value: unknown, description?: string) {
199
+ if (typeof value !== 'string' || !value) return
200
+ out.push({ key, value, ...(description ? { description } : {}) })
201
+ }
202
+
203
+ function buildRuntimeEnvHints(params: {
204
+ task: BoardTask
205
+ workspacePath: string
206
+ sourceCwd?: string | null
207
+ mode: TaskExecutionWorkspace['mode']
208
+ contextPath: string
209
+ envPath: string
210
+ }): TaskRuntimeEnvHint[] {
211
+ const { task, workspacePath, sourceCwd, mode, contextPath, envPath } = params
212
+ const hints: TaskRuntimeEnvHint[] = []
213
+ const workspaceId = taskWorkspaceSlug(task)
214
+ addEnvHint(hints, 'SWARMCLAW_TASK_ID', task.id, 'SwarmClaw task id')
215
+ addEnvHint(hints, 'SWARMCLAW_TASK_TITLE', task.title || 'Task', 'SwarmClaw task title')
216
+ addEnvHint(hints, 'SWARMCLAW_TASK_STATUS', task.status, 'SwarmClaw task status')
217
+ addEnvHint(hints, 'SWARMCLAW_TASK_AGENT_ID', task.agentId, 'Assigned SwarmClaw agent id')
218
+ addEnvHint(hints, 'SWARMCLAW_WORKSPACE_ID', workspaceId, 'Stable task workspace id')
219
+ addEnvHint(hints, 'SWARMCLAW_WORKSPACE_CWD', workspacePath, 'Task workspace directory')
220
+ addEnvHint(hints, 'SWARMCLAW_WORKSPACE_MODE', mode, 'Task workspace mode')
221
+ addEnvHint(hints, 'SWARMCLAW_WORKSPACE_CONTEXT', contextPath, 'Runtime context packet path')
222
+ addEnvHint(hints, 'SWARMCLAW_WORKSPACE_ENV', envPath, 'Reusable runtime env file')
223
+ addEnvHint(hints, 'SWARMCLAW_PROJECT_ID', task.projectId || '', 'SwarmClaw project id')
224
+ addEnvHint(hints, 'SWARMCLAW_SOURCE_CWD', sourceCwd || '', 'Original source directory')
225
+ addEnvHint(hints, 'AGENT_HOME', workspacePath, 'Agent-local home directory')
226
+ addEnvHint(hints, 'TASK_ID', task.id, 'Portable task id')
227
+ addEnvHint(hints, 'TASK_TITLE', task.title || 'Task', 'Portable task title')
228
+ addEnvHint(hints, 'WORKSPACE_ID', workspaceId, 'Portable workspace id')
229
+ addEnvHint(hints, 'WORKSPACE_CWD', workspacePath, 'Portable workspace cwd')
230
+ addEnvHint(hints, 'WORKSPACE_SOURCE', sourceCwd || workspacePath, 'Portable source path')
231
+ addEnvHint(
232
+ hints,
233
+ 'WORKSPACE_STRATEGY',
234
+ mode === 'project' ? 'project-task-workspace' : 'task-workspace',
235
+ 'Portable workspace strategy',
236
+ )
237
+ addEnvHint(hints, 'KANBAN_TASK_ID', task.id, 'Portable board task id')
238
+ addEnvHint(hints, 'KANBAN_WORKSPACE', workspacePath, 'Portable board workspace path')
239
+ return hints
240
+ }
241
+
242
+ function envLine(hint: TaskRuntimeEnvHint): string {
243
+ return `${hint.key}=${JSON.stringify(hint.value)}`
244
+ }
245
+
246
+ function writeWorkspaceEnv(envPath: string, hints: TaskRuntimeEnvHint[]) {
247
+ const lines = [
248
+ '# Generated by SwarmClaw. Contains task context only, not secrets.',
249
+ ...hints.map(envLine),
250
+ ]
251
+ fs.writeFileSync(envPath, `${lines.join('\n')}\n`, 'utf8')
252
+ }
253
+
254
+ function buildTaskRuntimeContext(params: {
255
+ task: BoardTask
256
+ executionWorkspace: Omit<TaskExecutionWorkspace, 'context'>
257
+ previewLinks: TaskPreviewLink[]
258
+ runtimeServices: TaskRuntimeService[]
259
+ generatedAt: number
260
+ }): TaskRuntimeContextPacket {
261
+ const { task, executionWorkspace, previewLinks, runtimeServices, generatedAt } = params
262
+ return {
263
+ taskId: task.id,
264
+ title: task.title || 'Task',
265
+ description: task.description || undefined,
266
+ status: task.status,
267
+ agentId: task.agentId,
268
+ projectId: executionWorkspace.projectId || null,
269
+ workspacePath: executionWorkspace.path,
270
+ sourceCwd: executionWorkspace.sourceCwd || null,
271
+ mode: executionWorkspace.mode,
272
+ preparedAt: executionWorkspace.preparedAt,
273
+ generatedAt,
274
+ previewLinks,
275
+ runtimeServices,
276
+ blockedBy: task.blockedBy,
277
+ blocks: task.blocks,
278
+ tags: task.tags,
279
+ upstreamResults: task.upstreamResults,
280
+ }
281
+ }
282
+
283
+ function writeWorkspaceContext(contextPath: string, context: TaskRuntimeContextPacket) {
284
+ fs.writeFileSync(contextPath, `${JSON.stringify(context, null, 2)}\n`, 'utf8')
285
+ }
286
+
190
287
  export function computeTaskLiveness(
191
288
  task: BoardTask,
192
289
  tasks: Record<string, BoardTask> = {},
@@ -284,6 +381,8 @@ export function prepareTaskExecutionWorkspace(
284
381
  const existing = task.executionWorkspace || null
285
382
  const workspacePath = existing?.path || path.join(taskWorkspaceRoot(task, workspaceRoot), taskWorkspaceSlug(task))
286
383
  fs.mkdirSync(workspacePath, { recursive: true })
384
+ const contextPath = path.join(workspacePath, 'context.json')
385
+ const envPath = path.join(workspacePath, '.env.swarmclaw')
287
386
  const readmePath = writeWorkspaceReadme(task, workspacePath, now)
288
387
  const previewLinks = normalizeTaskPreviewLinks(
289
388
  task.previewLinks || existing?.previewLinks,
@@ -295,17 +394,45 @@ export function prepareTaskExecutionWorkspace(
295
394
  options.runtimeServices,
296
395
  now,
297
396
  )
298
- const executionWorkspace: TaskExecutionWorkspace = {
397
+ const mode: TaskExecutionWorkspace['mode'] = task.projectId ? 'project' : 'task'
398
+ const sourceCwd = task.cwd || existing?.sourceCwd || null
399
+ const projectId = task.projectId || existing?.projectId || null
400
+ const preparedAt = existing?.preparedAt || now
401
+ const envHints = buildRuntimeEnvHints({
402
+ task,
403
+ workspacePath,
404
+ sourceCwd,
405
+ mode,
406
+ contextPath,
407
+ envPath,
408
+ })
409
+ const executionWorkspaceBase: Omit<TaskExecutionWorkspace, 'context'> = {
299
410
  path: workspacePath,
300
- mode: task.projectId ? 'project' : 'task',
301
- sourceCwd: task.cwd || existing?.sourceCwd || null,
302
- projectId: task.projectId || existing?.projectId || null,
303
- preparedAt: existing?.preparedAt || now,
411
+ mode,
412
+ sourceCwd,
413
+ projectId,
414
+ preparedAt,
304
415
  preparedBy: options.actor || existing?.preparedBy || null,
305
416
  readmePath,
417
+ contextPath,
418
+ envPath,
419
+ envHints,
306
420
  previewLinks,
307
421
  runtimeServices,
308
422
  }
423
+ const context = buildTaskRuntimeContext({
424
+ task,
425
+ executionWorkspace: executionWorkspaceBase,
426
+ previewLinks,
427
+ runtimeServices,
428
+ generatedAt: now,
429
+ })
430
+ writeWorkspaceContext(contextPath, context)
431
+ writeWorkspaceEnv(envPath, envHints)
432
+ const executionWorkspace: TaskExecutionWorkspace = {
433
+ ...executionWorkspaceBase,
434
+ context,
435
+ }
309
436
  const taskForLiveness = {
310
437
  ...task,
311
438
  executionWorkspace,
@@ -2,6 +2,7 @@ import type { ProviderId, ProviderType, OllamaMode } from './provider'
2
2
  import type { SessionResetMode, IdentityContinuityState } from './session'
3
3
  import type { SkillAllowlistMode } from './skill'
4
4
  import type { DreamConfig } from './dream'
5
+ import type { ExtensionManagedResourceMarker } from './extension'
5
6
 
6
7
  // --- SwarmFeed Heartbeat ---
7
8
 
@@ -237,6 +238,7 @@ export interface Agent {
237
238
  swarmfeedLastAutoPostAt?: number | null
238
239
  origin?: 'swarmdock' | 'swarmfeed' | 'swarmclaw' | 'external'
239
240
  swarmfeedHeartbeat?: SwarmFeedHeartbeatConfig | null
241
+ managedByExtension?: ExtensionManagedResourceMarker | null
240
242
 
241
243
  // SwarmDock (marketplace integration)
242
244
  swarmdockEnabled?: boolean
@@ -1,4 +1,5 @@
1
1
  import type { SessionResetMode } from './session'
2
+ import type { ExtensionManagedLocalFolderDeclaration } from './extension'
2
3
 
3
4
  // --- App Settings ---
4
5
  export type LoopMode = 'bounded' | 'ongoing'
@@ -150,6 +151,13 @@ export interface AppSettings {
150
151
  toolLoopCircuitBreaker?: number
151
152
  // Per-extension settings (keyed by extensionId)
152
153
  extensionSettings?: Record<string, Record<string, unknown>>
154
+ // Extension-managed resource settings such as trusted local folder roots.
155
+ extensionManagedResources?: Record<string, {
156
+ localFolders?: Record<string, ExtensionManagedLocalFolderDeclaration & {
157
+ path?: string | null
158
+ updatedAt?: number
159
+ }>
160
+ }>
153
161
  // Approval policies — opt-in governance gates for sensitive operations
154
162
  approvalPolicies?: {
155
163
  requireApprovalForAgentCreate?: boolean
@@ -251,6 +251,125 @@ export interface ExtensionUIDefinition {
251
251
  }>
252
252
  }
253
253
 
254
+ export type ExtensionManagedResourceKind = 'agent' | 'schedule' | 'local_folder'
255
+
256
+ export interface ExtensionManagedResourceRef {
257
+ extensionId?: string
258
+ resourceKind: 'agent' | 'schedule'
259
+ resourceKey: string
260
+ }
261
+
262
+ export interface ExtensionManagedResourceMarker {
263
+ extensionId: string
264
+ extensionName?: string | null
265
+ resourceKind: ExtensionManagedResourceKind
266
+ resourceKey: string
267
+ declarationHash?: string | null
268
+ reconciledAt: number
269
+ }
270
+
271
+ export interface ExtensionManagedAgentDeclaration {
272
+ agentKey: string
273
+ displayName: string
274
+ description?: string | null
275
+ systemPrompt?: string | null
276
+ instructions?: {
277
+ content?: string | null
278
+ entryFile?: string | null
279
+ assetPath?: string | null
280
+ } | null
281
+ provider?: ProviderId | string | null
282
+ model?: string | null
283
+ apiEndpoint?: string | null
284
+ credentialId?: string | null
285
+ fallbackCredentialIds?: string[]
286
+ gatewayProfileId?: string | null
287
+ preferredGatewayTags?: string[]
288
+ preferredGatewayUseCase?: string | null
289
+ capabilities?: string[] | string | null
290
+ tools?: string[]
291
+ extensions?: string[]
292
+ skills?: string[]
293
+ skillIds?: string[]
294
+ mcpServerIds?: string[]
295
+ monthlyBudget?: number | null
296
+ dailyBudget?: number | null
297
+ hourlyBudget?: number | null
298
+ disabled?: boolean
299
+ heartbeatEnabled?: boolean
300
+ planningMode?: 'off' | 'strict' | null
301
+ }
302
+
303
+ export interface ExtensionManagedScheduleTrigger {
304
+ kind?: 'schedule' | 'api' | 'webhook'
305
+ label?: string | null
306
+ enabled?: boolean
307
+ cronExpression?: string | null
308
+ timezone?: string | null
309
+ }
310
+
311
+ export interface ExtensionManagedScheduleDeclaration {
312
+ scheduleKey?: string
313
+ routineKey?: string
314
+ displayName?: string
315
+ title?: string
316
+ description?: string | null
317
+ taskPrompt?: string | null
318
+ message?: string | null
319
+ taskMode?: 'task' | 'wake_only' | 'protocol'
320
+ agentId?: string | null
321
+ agentRef?: ExtensionManagedResourceRef | null
322
+ assigneeRef?: ExtensionManagedResourceRef | null
323
+ scheduleType?: 'cron' | 'interval' | 'once'
324
+ cron?: string | null
325
+ intervalMs?: number | null
326
+ runAt?: number | null
327
+ timezone?: string | null
328
+ status?: 'active' | 'paused' | 'completed' | 'failed' | 'archived'
329
+ priority?: string | null
330
+ triggers?: ExtensionManagedScheduleTrigger[]
331
+ }
332
+
333
+ export interface ExtensionManagedLocalFolderDeclaration {
334
+ folderKey: string
335
+ displayName: string
336
+ description?: string | null
337
+ access?: 'read' | 'readWrite'
338
+ requiredDirectories?: string[]
339
+ requiredFiles?: string[]
340
+ }
341
+
342
+ export interface ExtensionGatewayPlatformDeclaration {
343
+ platformKey: string
344
+ displayName: string
345
+ description?: string | null
346
+ transport?: 'http' | 'ws' | 'stdio' | 'cli' | 'gateway' | 'custom'
347
+ endpoint?: string | null
348
+ authMode?: 'none' | 'bearer' | 'api_key' | 'oauth' | 'custom'
349
+ setupCheckKey?: string | null
350
+ capabilities?: string[]
351
+ }
352
+
353
+ export interface ExtensionSetupCheckDeclaration {
354
+ checkKey: string
355
+ displayName: string
356
+ description?: string | null
357
+ kind: 'env' | 'command' | 'url' | 'manual'
358
+ target?: string | null
359
+ required?: boolean
360
+ }
361
+
362
+ export interface ExtensionManagedResources {
363
+ agents?: ExtensionManagedAgentDeclaration[]
364
+ schedules?: ExtensionManagedScheduleDeclaration[]
365
+ /** Paperclip-compatible alias. SwarmClaw reconciles routines as managed schedules. */
366
+ routines?: ExtensionManagedScheduleDeclaration[]
367
+ localFolders?: ExtensionManagedLocalFolderDeclaration[]
368
+ /** Hermes-style gateway/platform declaration metadata for setup and diagnostics surfaces. */
369
+ gatewayPlatforms?: ExtensionGatewayPlatformDeclaration[]
370
+ setupChecks?: ExtensionSetupCheckDeclaration[]
371
+ }
372
+
254
373
  export interface ExtensionProviderDefinition {
255
374
  id: string
256
375
  name: string
@@ -300,6 +419,14 @@ export interface Extension {
300
419
  ui?: ExtensionUIDefinition
301
420
  providers?: ExtensionProviderDefinition[]
302
421
  connectors?: ExtensionConnectorDefinition[]
422
+ managedResources?: ExtensionManagedResources
423
+ /** Paperclip-compatible top-level aliases. Prefer managedResources for new SwarmClaw extensions. */
424
+ agents?: ExtensionManagedAgentDeclaration[]
425
+ schedules?: ExtensionManagedScheduleDeclaration[]
426
+ routines?: ExtensionManagedScheduleDeclaration[]
427
+ localFolders?: ExtensionManagedLocalFolderDeclaration[]
428
+ gatewayPlatforms?: ExtensionGatewayPlatformDeclaration[]
429
+ setupChecks?: ExtensionSetupCheckDeclaration[]
303
430
  }
304
431
 
305
432
  export interface ExtensionMeta {
@@ -325,6 +452,11 @@ export interface ExtensionMeta {
325
452
  hasUI?: boolean
326
453
  providerCount?: number
327
454
  connectorCount?: number
455
+ managedAgentCount?: number
456
+ managedScheduleCount?: number
457
+ localFolderCount?: number
458
+ gatewayPlatformCount?: number
459
+ setupCheckCount?: number
328
460
  createdByAgentId?: string | null
329
461
  settingsFields?: ExtensionSettingsField[]
330
462
  hasDependencyManifest?: boolean
package/src/types/misc.ts CHANGED
@@ -672,6 +672,8 @@ export interface OpenClawGatewayStats {
672
672
  externalRuntimeCount?: number
673
673
  sessionCount?: number
674
674
  presenceCount?: number
675
+ environmentCount?: number
676
+ availableEnvironmentCount?: number
675
677
  lastTopologyCheckedAt?: number
676
678
  lastTopologyErrorCount?: number
677
679
  lastTopologyError?: string | null
@@ -803,7 +805,19 @@ export interface OpenClawGatewayPresenceEntry {
803
805
  updatedAt?: number | null
804
806
  }
805
807
 
808
+ export type OpenClawEnvironmentStatus = 'available' | 'unavailable' | 'starting' | 'stopping' | 'error'
809
+
810
+ export interface OpenClawEnvironmentSummary {
811
+ id: string
812
+ type: string
813
+ label?: string | null
814
+ status: OpenClawEnvironmentStatus
815
+ capabilities?: string[]
816
+ }
817
+
806
818
  export interface OpenClawGatewayTopologyStats extends OpenClawGatewayStats {
819
+ environmentCount: number
820
+ availableEnvironmentCount: number
807
821
  pendingPairingCount: number
808
822
  hasErrors: boolean
809
823
  }
@@ -819,6 +833,23 @@ export interface OpenClawGatewayTopology {
819
833
  pairedDevices: OpenClawPairedDevice[]
820
834
  sessions: OpenClawGatewaySession[]
821
835
  presence: OpenClawGatewayPresenceEntry[]
836
+ environments: OpenClawEnvironmentSummary[]
837
+ errors: OpenClawGatewayRpcError[]
838
+ }
839
+
840
+ export interface OpenClawGatewayEnvironmentList {
841
+ profile: GatewayProfile
842
+ connected: boolean
843
+ refreshedAt: number
844
+ environments: OpenClawEnvironmentSummary[]
845
+ errors: OpenClawGatewayRpcError[]
846
+ }
847
+
848
+ export interface OpenClawGatewayEnvironmentStatusSnapshot {
849
+ profile: GatewayProfile
850
+ connected: boolean
851
+ refreshedAt: number
852
+ environment: OpenClawEnvironmentSummary | null
822
853
  errors: OpenClawGatewayRpcError[]
823
854
  }
824
855
 
@@ -1,3 +1,5 @@
1
+ import type { ExtensionManagedResourceMarker } from './extension'
2
+
1
3
  export type ScheduleType = 'cron' | 'interval' | 'once'
2
4
  export type ScheduleStatus = 'active' | 'paused' | 'completed' | 'failed' | 'archived'
3
5
  export type ScheduleTaskMode = 'task' | 'wake_only' | 'protocol'
@@ -54,6 +56,7 @@ export interface Schedule {
54
56
  followupThreadId?: string | null
55
57
  followupSenderId?: string | null
56
58
  followupSenderName?: string | null
59
+ managedByExtension?: ExtensionManagedResourceMarker | null
57
60
  createdAt: number
58
61
  updatedAt?: number
59
62
  }
package/src/types/task.ts CHANGED
@@ -43,6 +43,32 @@ export interface TaskRuntimeService {
43
43
  updatedAt: number
44
44
  }
45
45
 
46
+ export interface TaskRuntimeEnvHint {
47
+ key: string
48
+ value: string
49
+ description?: string
50
+ }
51
+
52
+ export interface TaskRuntimeContextPacket {
53
+ taskId: string
54
+ title: string
55
+ description?: string
56
+ status: BoardTaskStatus
57
+ agentId: string
58
+ projectId?: string | null
59
+ workspacePath: string
60
+ sourceCwd?: string | null
61
+ mode: TaskExecutionWorkspaceMode
62
+ preparedAt: number
63
+ generatedAt: number
64
+ previewLinks: TaskPreviewLink[]
65
+ runtimeServices: TaskRuntimeService[]
66
+ blockedBy?: string[]
67
+ blocks?: string[]
68
+ tags?: string[]
69
+ upstreamResults?: BoardTask['upstreamResults']
70
+ }
71
+
46
72
  export interface TaskExecutionWorkspace {
47
73
  path: string
48
74
  mode: TaskExecutionWorkspaceMode
@@ -51,6 +77,10 @@ export interface TaskExecutionWorkspace {
51
77
  preparedAt: number
52
78
  preparedBy?: string | null
53
79
  readmePath?: string | null
80
+ contextPath?: string | null
81
+ envPath?: string | null
82
+ envHints?: TaskRuntimeEnvHint[]
83
+ context?: TaskRuntimeContextPacket
54
84
  previewLinks: TaskPreviewLink[]
55
85
  runtimeServices: TaskRuntimeService[]
56
86
  }