@teamclaws/teamclaw 2026.3.26-2 → 2026.4.2-1
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.
- package/README.md +52 -8
- package/cli.mjs +538 -224
- package/index.ts +76 -27
- package/openclaw.plugin.json +53 -28
- package/package.json +5 -2
- package/skills/teamclaw/SKILL.md +213 -0
- package/skills/teamclaw/references/api-quick-ref.md +117 -0
- package/skills/teamclaw-setup/SKILL.md +81 -0
- package/skills/teamclaw-setup/references/install-modes.md +136 -0
- package/skills/teamclaw-setup/references/validation-checklist.md +73 -0
- package/src/config.ts +44 -16
- package/src/controller/controller-capacity.ts +2 -2
- package/src/controller/controller-service.ts +193 -47
- package/src/controller/controller-tools.ts +102 -2
- package/src/controller/delivery-report.ts +563 -0
- package/src/controller/http-server.ts +1907 -172
- package/src/controller/kickoff-orchestrator.ts +292 -0
- package/src/controller/managed-gateway-process.ts +330 -0
- package/src/controller/orchestration-manifest.ts +69 -1
- package/src/controller/preview-manager.ts +676 -0
- package/src/controller/prompt-injector.ts +116 -67
- package/src/controller/role-inference.ts +41 -0
- package/src/controller/websocket.ts +3 -1
- package/src/controller/worker-provisioning.ts +429 -74
- package/src/discovery.ts +1 -1
- package/src/git-collaboration.ts +198 -47
- package/src/identity.ts +12 -2
- package/src/interaction-contracts.ts +179 -3
- package/src/networking.ts +99 -0
- package/src/openclaw-workspace.ts +478 -11
- package/src/prompt-policy.ts +381 -0
- package/src/roles.ts +37 -36
- package/src/state.ts +40 -1
- package/src/task-executor.ts +282 -78
- package/src/types.ts +150 -7
- package/src/ui/app.js +1403 -175
- package/src/ui/assets/teamclaw-app-icon.png +0 -0
- package/src/ui/index.html +122 -40
- package/src/ui/style.css +829 -143
- package/src/worker/http-handler.ts +40 -4
- package/src/worker/prompt-injector.ts +9 -38
- package/src/worker/skill-installer.ts +2 -2
- package/src/worker/tools.ts +31 -5
- package/src/worker/worker-service.ts +49 -8
- package/src/workspace-browser.ts +20 -7
- package/src/controller/local-worker-manager.ts +0 -533
package/src/types.ts
CHANGED
|
@@ -23,6 +23,10 @@ export type GitSyncMode = "shared" | "bundle" | "remote";
|
|
|
23
23
|
|
|
24
24
|
export type WorkerProvisioningType = "none" | "process" | "docker" | "kubernetes";
|
|
25
25
|
|
|
26
|
+
export type ProcessModel = "multi";
|
|
27
|
+
|
|
28
|
+
export type AgentIsolationMode = "independent" | "main";
|
|
29
|
+
|
|
26
30
|
export type ProvisionedWorkerStatus =
|
|
27
31
|
| "launching"
|
|
28
32
|
| "registered"
|
|
@@ -30,6 +34,11 @@ export type ProvisionedWorkerStatus =
|
|
|
30
34
|
| "terminated"
|
|
31
35
|
| "failed";
|
|
32
36
|
|
|
37
|
+
export type ProvisioningReadinessStatus =
|
|
38
|
+
| "checking"
|
|
39
|
+
| "ready"
|
|
40
|
+
| "degraded";
|
|
41
|
+
|
|
33
42
|
export type GitRepoState = {
|
|
34
43
|
enabled: boolean;
|
|
35
44
|
mode: GitSyncMode;
|
|
@@ -82,7 +91,7 @@ export type WorkerInfo = {
|
|
|
82
91
|
role: RoleId;
|
|
83
92
|
label: string;
|
|
84
93
|
status: WorkerStatus;
|
|
85
|
-
transport?: "http"
|
|
94
|
+
transport?: "http";
|
|
86
95
|
url: string;
|
|
87
96
|
lastHeartbeat: number;
|
|
88
97
|
capabilities: string[];
|
|
@@ -101,6 +110,7 @@ export type TaskInfo = {
|
|
|
101
110
|
createdBy: string;
|
|
102
111
|
recommendedSkills?: string[];
|
|
103
112
|
controllerSessionKey?: string;
|
|
113
|
+
projectDir?: string;
|
|
104
114
|
createdAt: number;
|
|
105
115
|
updatedAt: number;
|
|
106
116
|
startedAt?: number;
|
|
@@ -133,6 +143,7 @@ export type TaskAssignmentPayload = {
|
|
|
133
143
|
description: string;
|
|
134
144
|
priority?: TaskPriority;
|
|
135
145
|
recommendedSkills?: string[];
|
|
146
|
+
projectDir?: string;
|
|
136
147
|
executionSessionKey?: string;
|
|
137
148
|
executionIdempotencyKey?: string;
|
|
138
149
|
repo?: RepoSyncInfo;
|
|
@@ -146,6 +157,29 @@ export type WorkerTaskResultDeliverable = {
|
|
|
146
157
|
kind: "file" | "directory" | "command" | "artifact" | "note";
|
|
147
158
|
value: string;
|
|
148
159
|
summary?: string;
|
|
160
|
+
artifactType?: "web-app" | "static-site" | "rest-api" | "binary" | "document";
|
|
161
|
+
previewCommand?: string;
|
|
162
|
+
previewCwd?: string;
|
|
163
|
+
previewReadyPath?: string;
|
|
164
|
+
liveUrl?: string;
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
export type DynamicPreviewRecord = {
|
|
168
|
+
id: string;
|
|
169
|
+
taskId: string;
|
|
170
|
+
deliverableIndex: number;
|
|
171
|
+
deliverableValue: string;
|
|
172
|
+
targetPort: number;
|
|
173
|
+
previewCommand: string;
|
|
174
|
+
previewCwd: string;
|
|
175
|
+
previewReadyPath: string;
|
|
176
|
+
liveUrl: string;
|
|
177
|
+
status: "launching" | "starting" | "healthy" | "stopped" | "failed";
|
|
178
|
+
pid?: number;
|
|
179
|
+
createdAt: number;
|
|
180
|
+
updatedAt: number;
|
|
181
|
+
lastHealthCheckAt?: number;
|
|
182
|
+
lastError?: string;
|
|
149
183
|
};
|
|
150
184
|
|
|
151
185
|
export type WorkerTaskResultFollowUp = {
|
|
@@ -164,6 +198,8 @@ export type WorkerTaskResultContract = {
|
|
|
164
198
|
followUps: WorkerTaskResultFollowUp[];
|
|
165
199
|
questions: string[];
|
|
166
200
|
notes?: string;
|
|
201
|
+
/** Reusable codebase patterns discovered during this task (consolidated into workspace memory). */
|
|
202
|
+
discoveredPatterns?: string[];
|
|
167
203
|
};
|
|
168
204
|
|
|
169
205
|
export type WorkerProgressContract = {
|
|
@@ -204,6 +240,27 @@ export type TeamMessageContract = {
|
|
|
204
240
|
references: string[];
|
|
205
241
|
};
|
|
206
242
|
|
|
243
|
+
export type KickoffAssessment = {
|
|
244
|
+
role: RoleId;
|
|
245
|
+
needed: boolean;
|
|
246
|
+
scope: string;
|
|
247
|
+
suggestedTasks: string[];
|
|
248
|
+
dependencies: string[];
|
|
249
|
+
risks: string[];
|
|
250
|
+
questions: string[];
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
export type KickoffPlan = {
|
|
254
|
+
/** Complexity level determined by controller's initial analysis. */
|
|
255
|
+
complexity: "simple" | "medium" | "complex";
|
|
256
|
+
/** Roles invited to the kickoff meeting. */
|
|
257
|
+
candidateRoles: RoleId[];
|
|
258
|
+
/** Collected assessments from each role (populated after kickoff). */
|
|
259
|
+
assessments: KickoffAssessment[];
|
|
260
|
+
/** Whether the kickoff phase has completed. */
|
|
261
|
+
completed: boolean;
|
|
262
|
+
};
|
|
263
|
+
|
|
207
264
|
export type ControllerManifestCreatedTask = {
|
|
208
265
|
title: string;
|
|
209
266
|
assignedRole?: RoleId;
|
|
@@ -217,16 +274,45 @@ export type ControllerManifestDeferredTask = {
|
|
|
217
274
|
whenReady: string;
|
|
218
275
|
};
|
|
219
276
|
|
|
277
|
+
export type ClarificationQuestionKind = "single-select" | "multi-select" | "number" | "text";
|
|
278
|
+
|
|
279
|
+
export type ClarificationQuestionOption = {
|
|
280
|
+
value: string;
|
|
281
|
+
label: string;
|
|
282
|
+
hint?: string;
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
export type ClarificationQuestionSchema = {
|
|
286
|
+
kind: ClarificationQuestionKind;
|
|
287
|
+
title: string;
|
|
288
|
+
description?: string;
|
|
289
|
+
required?: boolean;
|
|
290
|
+
options?: ClarificationQuestionOption[];
|
|
291
|
+
allowOther?: boolean;
|
|
292
|
+
placeholder?: string;
|
|
293
|
+
unit?: string;
|
|
294
|
+
min?: number;
|
|
295
|
+
max?: number;
|
|
296
|
+
step?: number;
|
|
297
|
+
};
|
|
298
|
+
|
|
220
299
|
export type ControllerOrchestrationManifest = {
|
|
221
300
|
version: string;
|
|
301
|
+
/** Short, filesystem-safe project name chosen by the controller (e.g. "todo-rest-api", "stripe-payment-integration"). */
|
|
302
|
+
projectName?: string;
|
|
222
303
|
requirementSummary: string;
|
|
223
304
|
requiredRoles: RoleId[];
|
|
224
305
|
clarificationsNeeded: boolean;
|
|
225
306
|
clarificationQuestions: string[];
|
|
307
|
+
clarificationSchemas?: ClarificationQuestionSchema[];
|
|
226
308
|
createdTasks: ControllerManifestCreatedTask[];
|
|
227
309
|
deferredTasks: ControllerManifestDeferredTask[];
|
|
228
310
|
handoffPlan?: string;
|
|
229
311
|
notes?: string;
|
|
312
|
+
/** Controller signals that the entire human requirement is fully satisfied — no more tasks or follow-ups needed. */
|
|
313
|
+
requirementFullyComplete?: boolean;
|
|
314
|
+
/** Team kickoff plan — populated when controller uses collaborative planning. */
|
|
315
|
+
kickoffPlan?: KickoffPlan;
|
|
230
316
|
};
|
|
231
317
|
|
|
232
318
|
export type ControllerRunInfo = {
|
|
@@ -240,6 +326,7 @@ export type ControllerRunInfo = {
|
|
|
240
326
|
request: string;
|
|
241
327
|
reply?: string;
|
|
242
328
|
error?: string;
|
|
329
|
+
projectDir?: string;
|
|
243
330
|
createdTaskIds: string[];
|
|
244
331
|
manifest?: ControllerOrchestrationManifest;
|
|
245
332
|
status: TaskExecutionStatus;
|
|
@@ -289,14 +376,21 @@ export type ClarificationStatus = "pending" | "answered";
|
|
|
289
376
|
export type ClarificationRequest = {
|
|
290
377
|
id: string;
|
|
291
378
|
taskId: string;
|
|
379
|
+
controllerRunId?: string;
|
|
380
|
+
controllerSessionKey?: string;
|
|
292
381
|
requestedBy: string;
|
|
293
382
|
requestedByWorkerId?: string;
|
|
294
383
|
requestedByRole?: RoleId;
|
|
295
384
|
question: string;
|
|
385
|
+
questionSchema?: ClarificationQuestionSchema;
|
|
296
386
|
blockingReason: string;
|
|
297
387
|
context?: string;
|
|
298
388
|
status: ClarificationStatus;
|
|
299
389
|
answer?: string;
|
|
390
|
+
answerValue?: string;
|
|
391
|
+
answerValues?: string[];
|
|
392
|
+
answerNumber?: number;
|
|
393
|
+
answerComment?: string;
|
|
300
394
|
answeredBy?: string;
|
|
301
395
|
createdAt: number;
|
|
302
396
|
updatedAt: number;
|
|
@@ -332,8 +426,19 @@ export type ProvisionedWorkerRecord = {
|
|
|
332
426
|
lastError?: string;
|
|
333
427
|
};
|
|
334
428
|
|
|
429
|
+
export type StartupProvisioningReadiness = {
|
|
430
|
+
status: ProvisioningReadinessStatus;
|
|
431
|
+
startedAt: number;
|
|
432
|
+
checkedAt: number;
|
|
433
|
+
attempts: number;
|
|
434
|
+
requiredRoles: RoleId[];
|
|
435
|
+
readyWorkerIds: string[];
|
|
436
|
+
message?: string;
|
|
437
|
+
};
|
|
438
|
+
|
|
335
439
|
export type TeamProvisioningState = {
|
|
336
440
|
workers: Record<string, ProvisionedWorkerRecord>;
|
|
441
|
+
startupReadiness?: StartupProvisioningReadiness;
|
|
337
442
|
};
|
|
338
443
|
|
|
339
444
|
export type PluginConfig = {
|
|
@@ -343,14 +448,16 @@ export type PluginConfig = {
|
|
|
343
448
|
controllerUrl: string;
|
|
344
449
|
teamName: string;
|
|
345
450
|
heartbeatIntervalMs: number;
|
|
346
|
-
|
|
451
|
+
processModel: ProcessModel;
|
|
347
452
|
taskTimeoutMs: number;
|
|
348
453
|
gitEnabled: boolean;
|
|
349
454
|
gitRemoteUrl: string;
|
|
350
455
|
gitDefaultBranch: string;
|
|
351
456
|
gitAuthorName: string;
|
|
352
457
|
gitAuthorEmail: string;
|
|
458
|
+
agentIsolationMode: AgentIsolationMode;
|
|
353
459
|
workerProvisioningType: WorkerProvisioningType;
|
|
460
|
+
workerProvisioningDisabled: boolean;
|
|
354
461
|
workerProvisioningControllerUrl: string;
|
|
355
462
|
workerProvisioningRoles: RoleId[];
|
|
356
463
|
workerProvisioningMinPerRole: number;
|
|
@@ -367,6 +474,7 @@ export type PluginConfig = {
|
|
|
367
474
|
workerProvisioningKubernetesNamespace: string;
|
|
368
475
|
workerProvisioningKubernetesContext: string;
|
|
369
476
|
workerProvisioningKubernetesServiceAccount: string;
|
|
477
|
+
workerProvisioningKubernetesImagePullSecrets: string[];
|
|
370
478
|
workerProvisioningKubernetesWorkspacePersistentVolumeClaim: string;
|
|
371
479
|
workerProvisioningKubernetesLabels: Record<string, string>;
|
|
372
480
|
workerProvisioningKubernetesAnnotations: Record<string, string>;
|
|
@@ -388,10 +496,24 @@ export type TeamState = {
|
|
|
388
496
|
clarifications: Record<string, ClarificationRequest>;
|
|
389
497
|
repo?: GitRepoState;
|
|
390
498
|
provisioning?: TeamProvisioningState;
|
|
499
|
+
previews?: Record<string, DynamicPreviewRecord>;
|
|
500
|
+
reports?: Record<string, DeliveryReportRecord>;
|
|
391
501
|
createdAt: number;
|
|
392
502
|
updatedAt: number;
|
|
393
503
|
};
|
|
394
504
|
|
|
505
|
+
export type DeliveryReportRecord = {
|
|
506
|
+
id: string;
|
|
507
|
+
sessionKey: string;
|
|
508
|
+
generatedAt: number;
|
|
509
|
+
projectName: string;
|
|
510
|
+
requirementSummary: string;
|
|
511
|
+
status: "completed" | "partial" | "failed";
|
|
512
|
+
taskCount: number;
|
|
513
|
+
deliverableCount: number;
|
|
514
|
+
previewCount: number;
|
|
515
|
+
};
|
|
516
|
+
|
|
395
517
|
export type DiscoveryResult = {
|
|
396
518
|
name: string;
|
|
397
519
|
host: string;
|
|
@@ -434,13 +556,13 @@ export function parsePluginConfig(raw: Record<string, unknown> = {}): PluginConf
|
|
|
434
556
|
|
|
435
557
|
const teamName = typeof raw.teamName === "string" && raw.teamName.trim()
|
|
436
558
|
? raw.teamName.trim()
|
|
437
|
-
: "
|
|
559
|
+
: "TeamClaw";
|
|
438
560
|
|
|
439
561
|
const heartbeatIntervalMs = typeof raw.heartbeatIntervalMs === "number" && raw.heartbeatIntervalMs >= 1000
|
|
440
562
|
? raw.heartbeatIntervalMs
|
|
441
563
|
: 10000;
|
|
442
564
|
|
|
443
|
-
const
|
|
565
|
+
const processModel: ProcessModel = "multi";
|
|
444
566
|
|
|
445
567
|
const taskTimeoutMs = typeof raw.taskTimeoutMs === "number" && raw.taskTimeoutMs >= 1000
|
|
446
568
|
? raw.taskTimeoutMs
|
|
@@ -464,7 +586,24 @@ export function parsePluginConfig(raw: Record<string, unknown> = {}): PluginConf
|
|
|
464
586
|
? raw.gitAuthorEmail.trim()
|
|
465
587
|
: "teamclaw@local";
|
|
466
588
|
|
|
467
|
-
const
|
|
589
|
+
const agentIsolationMode: AgentIsolationMode =
|
|
590
|
+
typeof raw.agentIsolationMode === "string" && (raw.agentIsolationMode === "independent" || raw.agentIsolationMode === "main")
|
|
591
|
+
? raw.agentIsolationMode
|
|
592
|
+
: "independent";
|
|
593
|
+
|
|
594
|
+
const rawWorkerProvisioningType = parseProvisioningType(raw.workerProvisioningType);
|
|
595
|
+
const workerProvisioningDisabled = raw.workerProvisioningDisabled === true;
|
|
596
|
+
// Legacy local installs often persisted workerProvisioningType="none" without
|
|
597
|
+
// distinguishing "manual/no provisioning" from "same-host local controller".
|
|
598
|
+
// Keep an explicit escape hatch via workerProvisioningDisabled, but otherwise
|
|
599
|
+
// default multi-process controllers back to process provisioning.
|
|
600
|
+
const workerProvisioningType: WorkerProvisioningType =
|
|
601
|
+
mode === "controller" &&
|
|
602
|
+
rawWorkerProvisioningType === "none" &&
|
|
603
|
+
processModel === "multi" &&
|
|
604
|
+
!workerProvisioningDisabled
|
|
605
|
+
? "process"
|
|
606
|
+
: rawWorkerProvisioningType;
|
|
468
607
|
const workerProvisioningControllerUrl = typeof raw.workerProvisioningControllerUrl === "string"
|
|
469
608
|
? raw.workerProvisioningControllerUrl.trim()
|
|
470
609
|
: "";
|
|
@@ -474,7 +613,7 @@ export function parsePluginConfig(raw: Record<string, unknown> = {}): PluginConf
|
|
|
474
613
|
: 0;
|
|
475
614
|
const rawProvisioningMaxPerRole = typeof raw.workerProvisioningMaxPerRole === "number" && raw.workerProvisioningMaxPerRole >= 1
|
|
476
615
|
? Math.floor(raw.workerProvisioningMaxPerRole)
|
|
477
|
-
:
|
|
616
|
+
: 3;
|
|
478
617
|
const workerProvisioningMaxPerRole = Math.max(rawProvisioningMaxPerRole, workerProvisioningMinPerRole);
|
|
479
618
|
const workerProvisioningIdleTtlMs = typeof raw.workerProvisioningIdleTtlMs === "number" && raw.workerProvisioningIdleTtlMs >= 1000
|
|
480
619
|
? raw.workerProvisioningIdleTtlMs
|
|
@@ -512,6 +651,7 @@ export function parsePluginConfig(raw: Record<string, unknown> = {}): PluginConf
|
|
|
512
651
|
const workerProvisioningKubernetesServiceAccount = typeof raw.workerProvisioningKubernetesServiceAccount === "string"
|
|
513
652
|
? raw.workerProvisioningKubernetesServiceAccount.trim()
|
|
514
653
|
: "";
|
|
654
|
+
const workerProvisioningKubernetesImagePullSecrets = parseStringArray(raw.workerProvisioningKubernetesImagePullSecrets);
|
|
515
655
|
const workerProvisioningKubernetesWorkspacePersistentVolumeClaim =
|
|
516
656
|
typeof raw.workerProvisioningKubernetesWorkspacePersistentVolumeClaim === "string"
|
|
517
657
|
? raw.workerProvisioningKubernetesWorkspacePersistentVolumeClaim.trim()
|
|
@@ -530,14 +670,16 @@ export function parsePluginConfig(raw: Record<string, unknown> = {}): PluginConf
|
|
|
530
670
|
controllerUrl,
|
|
531
671
|
teamName,
|
|
532
672
|
heartbeatIntervalMs,
|
|
533
|
-
|
|
673
|
+
processModel,
|
|
534
674
|
taskTimeoutMs,
|
|
535
675
|
gitEnabled,
|
|
536
676
|
gitRemoteUrl,
|
|
537
677
|
gitDefaultBranch,
|
|
538
678
|
gitAuthorName,
|
|
539
679
|
gitAuthorEmail,
|
|
680
|
+
agentIsolationMode,
|
|
540
681
|
workerProvisioningType,
|
|
682
|
+
workerProvisioningDisabled,
|
|
541
683
|
workerProvisioningControllerUrl,
|
|
542
684
|
workerProvisioningRoles,
|
|
543
685
|
workerProvisioningMinPerRole,
|
|
@@ -554,6 +696,7 @@ export function parsePluginConfig(raw: Record<string, unknown> = {}): PluginConf
|
|
|
554
696
|
workerProvisioningKubernetesNamespace,
|
|
555
697
|
workerProvisioningKubernetesContext,
|
|
556
698
|
workerProvisioningKubernetesServiceAccount,
|
|
699
|
+
workerProvisioningKubernetesImagePullSecrets,
|
|
557
700
|
workerProvisioningKubernetesWorkspacePersistentVolumeClaim,
|
|
558
701
|
workerProvisioningKubernetesLabels,
|
|
559
702
|
workerProvisioningKubernetesAnnotations,
|