refactor/app-thread-key
This commit is contained in:
parent
495af092c5
commit
ea781b5206
@ -7,7 +7,7 @@ Repo chain: openclaw-multi-session-plugins ↔ xworkmate-bridge ↔ xworkmate-ap
|
||||
```
|
||||
[prepare] → [execute] → [collect-and-snapshot] → [export] → [snapshot] → [download] → [sync]
|
||||
|
||||
prepare: mkdir tasks/<session>/<run>/ (multi-session-plugins)
|
||||
prepare: map session + mkdir tasks/<session>/<run>/ (multi-session-plugins)
|
||||
execute: tools write files (openclaw.svc.plus)
|
||||
collect: copy media/tmp outputs into task scope (multi-session-plugins)
|
||||
export: scan + manifest + sign (multi-session-plugins)
|
||||
@ -25,32 +25,42 @@ App terminal rule:
|
||||
## State 1: Prepare
|
||||
|
||||
```
|
||||
Caller: xworkmate-bridge → gateway.request('xworkmate.artifacts.prepare')
|
||||
Handler: openclaw-multi-session-plugins → prepareXWorkmateArtifacts()
|
||||
Caller: xworkmate-bridge → gateway.request('xworkmate.session.prepare')
|
||||
Handler: openclaw-multi-session-plugins → recordXWorkmateSessionMapping() + prepareXWorkmateArtifacts()
|
||||
|
||||
Inputs:
|
||||
sessionKey: string // "agent:default:abc123"
|
||||
runId: string // "20260605-001"
|
||||
workspaceDir?: string // optional explicit path
|
||||
schemaVersion: 1
|
||||
appThreadKey: string // "draft:1780658097668838-1"
|
||||
openclawSessionKey: string // "agent:main:draft:1780658097668838-1"
|
||||
runId: string // "20260605-001"
|
||||
expectedArtifactDirs?: string[]
|
||||
workspaceDir?: string
|
||||
|
||||
Process:
|
||||
1. resolveWorkspaceDir({ sessionKey, params, pluginConfig, config })
|
||||
1. Validate typed mapping metadata.
|
||||
|
||||
2. Patch SessionEntry.pluginExtensions:
|
||||
["openclaw-multi-session-plugins"]["xworkmate.sessionMapping"]
|
||||
→ schemaVersion, appThreadKey, openclawSessionKey, expectedArtifactDirs
|
||||
|
||||
3. resolveWorkspaceDir({ openclawSessionKey, params, pluginConfig, config })
|
||||
→ Falls back through: explicit → pluginConfig → agent config
|
||||
→ profile env → ~/.openclaw/workspace
|
||||
|
||||
2. safeScopeSegment(sessionKey)
|
||||
4. safeScopeSegment(openclawSessionKey)
|
||||
→ replace [/\\:*?"<>|] with "-", truncate to 96 chars
|
||||
|
||||
3. safeScopeSegment(runId) → same rules
|
||||
5. safeScopeSegment(runId) → same rules
|
||||
|
||||
4. scopeRoot = <workspace>/tasks/<safeSessionKey>/<safeRunId>/
|
||||
6. scopeRoot = <workspace>/tasks/<safeSessionKey>/<safeRunId>/
|
||||
→ fs.mkdir(scopeRoot, { recursive: true })
|
||||
|
||||
5. Validate: isWithinRoot(workspaceRoot, scopeRoot)
|
||||
7. Validate: isWithinRoot(workspaceRoot, scopeRoot)
|
||||
|
||||
Output:
|
||||
artifactScope: "tasks/<safeSessionKey>/<safeRunId>/"
|
||||
artifactDirectory: "<workspace>/tasks/<safeSessionKey>/<safeRunId>/"
|
||||
mapping: { appThreadKey, openclawSessionKey, expectedArtifactDirs }
|
||||
|
||||
Fragile:
|
||||
- workspace resolution chain has 5 ordered sources
|
||||
@ -99,13 +109,13 @@ Caller: xworkmate-bridge → gateway.request('xworkmate.artifacts.collect-and-
|
||||
Handler: openclaw-multi-session-plugins → collectAndSnapshotXWorkmateArtifacts()
|
||||
|
||||
Inputs:
|
||||
sessionKey: mapped OpenClaw session key
|
||||
openclawSessionKey: mapped OpenClaw session key
|
||||
runId: OpenClaw run id
|
||||
artifactScope: tasks/<session>/<run>/
|
||||
sinceUnixMs: task start timestamp
|
||||
|
||||
Process:
|
||||
1. Validate artifactScope matches sessionKey/runId.
|
||||
1. Validate artifactScope matches openclawSessionKey/runId.
|
||||
2. Scan fixed OpenClaw output roots:
|
||||
- ~/.openclaw/media/
|
||||
- /tmp/openclaw/
|
||||
@ -127,11 +137,12 @@ Handler: openclaw-multi-session-plugins → exportXWorkmateArtifacts()
|
||||
|
||||
Inputs:
|
||||
artifactScope: "tasks/<session>/<run>/"
|
||||
openclawSessionKey?: string
|
||||
workspaceDir?: string
|
||||
artifactRef?: string // alternative: read single artifact
|
||||
maxFiles?: number // default: 200
|
||||
maxInlineBytes?: number // default: 512KB, files larger are omitted
|
||||
expectedArtifactDirs?: string[] // from session.start metadata.xworkmateTaskArtifactContract only
|
||||
expectedArtifactDirs?: string[] // from typed mapping/session.prepare only
|
||||
|
||||
Process:
|
||||
1. resolveScopeRoot(workspaceRoot, artifactScope)
|
||||
@ -153,7 +164,7 @@ Process:
|
||||
Protocol boundary:
|
||||
`expectedArtifactDirs` is bridge artifact-contract data, not agent execution
|
||||
data. Bridge must not put it in `chat.send` params. Bridge must not probe old
|
||||
root-level or metadata-root compatibility keys.
|
||||
root-level, metadata-root, prompt-text, or `sessionKey` compatibility keys.
|
||||
|
||||
3. For each file under maxFiles limit:
|
||||
→ Read content (up to maxInlineBytes)
|
||||
|
||||
@ -23,8 +23,9 @@ xworkmate-app
|
||||
└─ AppController.sendChatMessage()
|
||||
├─ Resolve/create TaskThread by sessionKey/threadId
|
||||
├─ Prepare local workspace: ~/.xworkmate/threads/<session>/
|
||||
├─ Build task context prompt (sessionKey, workspace, contract)
|
||||
├─ Build task context prompt (TaskThread.sessionKey, workspace, contract)
|
||||
├─ Attach metadata.xworkmateTaskArtifactContract
|
||||
│ └─ schemaVersion, appThreadKey, expectedArtifactDirs
|
||||
└─ Select execution path:
|
||||
├─ Agent providers (codex/opencode/gemini/hermes)
|
||||
│ └─ DesktopGoTaskService.startSession()
|
||||
@ -72,11 +73,16 @@ xworkmate-bridge
|
||||
└─ startOpenClawGatewayTask()
|
||||
├─ ensureProductionGatewayConnected()
|
||||
├─ openClawArtifactPrepare()
|
||||
│ └─ gateway.request('xworkmate.artifacts.prepare')
|
||||
│ └─ scope: tasks/<sessionKey>/<runId>/
|
||||
│ └─ gateway.request('xworkmate.session.prepare')
|
||||
│ ├─ schemaVersion: 1
|
||||
│ ├─ appThreadKey: App TaskThread key
|
||||
│ ├─ openclawSessionKey: OpenClaw SessionEntry key
|
||||
│ ├─ expectedArtifactDirs: typed artifact contract
|
||||
│ └─ scope: tasks/<openclawSessionKey>/<runId>/
|
||||
│
|
||||
├─ gateway.request('chat.send')
|
||||
│ └─ payload: sessionKey, message, attachments, idempotencyKey
|
||||
│ sessionKey is the OpenClaw native field and equals openclawSessionKey
|
||||
│ (no expectedArtifactDirs root field)
|
||||
│
|
||||
├─ Create OpenClawTaskRecord
|
||||
@ -116,10 +122,17 @@ openclaw.svc.plus
|
||||
└─ tasks/<session>/<run>/output.md ← MAY be written here
|
||||
|
||||
openclaw-multi-session-plugins
|
||||
Receives gateway RPC: xworkmate.artifacts.prepare
|
||||
Receives gateway RPC: xworkmate.session.prepare
|
||||
recordXWorkmateSessionMapping()
|
||||
├─ Validate schemaVersion=1 typed metadata
|
||||
├─ Require appThreadKey and openclawSessionKey
|
||||
├─ Write SessionEntry.pluginExtensions
|
||||
│ └─ ["openclaw-multi-session-plugins"]["xworkmate.sessionMapping"]
|
||||
└─ Fail closed on appThreadKey/openclawSessionKey conflicts
|
||||
|
||||
prepareXWorkmateArtifacts()
|
||||
├─ resolveWorkspaceDir() → workspace root
|
||||
├─ safeScopeSegment(sessionKey) → sanitize
|
||||
├─ safeScopeSegment(openclawSessionKey) → sanitize
|
||||
├─ safeScopeSegment(runId) → sanitize
|
||||
└─ mkdir <workspace>/tasks/<safeSessionKey>/<safeRunId>/
|
||||
|
||||
@ -139,13 +152,15 @@ openclaw-multi-session-plugins
|
||||
`expectedArtifactDirs` source:
|
||||
session.start.metadata.xworkmateTaskArtifactContract.expectedArtifactDirs
|
||||
→ bridge artifact contract
|
||||
→ xworkmate.session.prepare mapping
|
||||
→ xworkmate.artifacts.collect-and-snapshot / export only
|
||||
|
||||
Forbidden compatibility paths:
|
||||
session.start.metadata.xworkmateTaskArtifactContract.sessionKey
|
||||
session.start.expectedArtifactDirs
|
||||
session.start.metadata.expectedArtifactDirs
|
||||
chat.send.expectedArtifactDirs
|
||||
xworkmate.tasks.get.expectedArtifactDirs
|
||||
xworkmate.tasks.get.sessionKey
|
||||
|
||||
Receives gateway RPC: xworkmate.artifacts.collect-and-snapshot
|
||||
collectAndSnapshotXWorkmateArtifacts()
|
||||
@ -230,7 +245,7 @@ etc.), not by extending the task execution lifecycle.
|
||||
## Fragile Points
|
||||
|
||||
1. **F1: Tool output path mismatch** — Tools save to media/, plugin exports from tasks/ → gap
|
||||
2. **F2: Session key mismatch** — Bridge maps App threadId to an explicit OpenClaw sessionKey before prepare/chat/export
|
||||
2. **F2: Session key mismatch** — Bridge maps App `appThreadKey` to an explicit `openclawSessionKey` before prepare/chat/export and the plugin persists that mapping in SessionEntry.pluginExtensions
|
||||
3. **F3: Prepare timing** — If prepare fails after send, no scope directory exists
|
||||
4. **F4: Admission gate rejection** — Queue full → OPENCLAW_GATEWAY_BUSY → app must handle
|
||||
5. **F5: Bridge restart** — In-memory sessions lost → app must detect and recover
|
||||
|
||||
@ -2,6 +2,18 @@
|
||||
|
||||
这个 case 固化 5 个真实 OpenClaw Gateway 提示词,用于验证 XWorkmate App -> XWorkmate Bridge -> OpenClaw Gateway 的 5 并发稳定性、任务隔离和 artifact 同步。
|
||||
|
||||
Related key-mapping regression:
|
||||
|
||||
- App thread: `~/.xworkmate/threads/draft-1780658097668838-1`
|
||||
- `appThreadKey`: `draft:1780658097668838-1`
|
||||
- `openclawSessionKey`: `agent:main:draft:1780658097668838-1`
|
||||
- OpenClaw URL: `https://openclaw.svc.plus/chat?session=agent%3Amain%3Adraft%3A1780658097668838-1`
|
||||
|
||||
The durable source of truth is
|
||||
`SessionEntry.pluginExtensions["openclaw-multi-session-plugins"]["xworkmate.sessionMapping"]`.
|
||||
Bridge/App must not recover this mapping by replacing `agent:main:` or by using a
|
||||
legacy `sessionKey` compatibility field.
|
||||
|
||||
## 覆盖目标
|
||||
|
||||
- 连续出图:7 张连续风格 PNG。
|
||||
@ -15,8 +27,9 @@
|
||||
| 仓库 | 文件 | 覆盖点 |
|
||||
| --- | --- | --- |
|
||||
| `xworkmate-bridge` | `internal/acp/web_contract_test.go` | `TestHTTPHandlerGatewayOpenClawHandlesFiveConcurrentE2ECases` 通过 HTTP SSE 同时提交 5 个 OpenClaw Gateway 请求,断言不出现 queued、invalid handshake、socket closed、ACP_HTTP_CONNECTION_CLOSED、GATEWAY_CONNECT_FAILED。 |
|
||||
| `xworkmate-app` | `test/runtime/assistant_execution_target_test.dart` | `OpenClaw gateway admits five representative E2E tasks without queueing` 断言 App 侧 5 个代表任务同时进入 running,复用各自 session/thread,不进入 queued。 |
|
||||
| `openclaw-multi-session-plugins` | `src/exportArtifacts.test.ts` | 同线程 `assets/images/**/*.png`、manifest、视频/PDF 交付物能被 export 到当前 task artifact scope,不串到旧线程或旧 run。 |
|
||||
| `xworkmate-app` | `test/runtime/assistant_execution_target_test.dart` | `OpenClaw gateway admits five representative E2E tasks without queueing` 断言 App 侧 5 个代表任务同时进入 running,复用各自 session/thread,不进入 queued,并且 artifact contract 使用 `schemaVersion/appThreadKey/expectedArtifactDirs`,不再写 `sessionKey` 兼容字段。 |
|
||||
| `openclaw-multi-session-plugins` | `src/taskState.test.ts` | `appThreadKey -> openclawSessionKey` 写入 `pluginExtensions`,`xworkmate.tasks.get` 通过 mapping 查询 OpenClaw native task-registry,查不到时返回 `no_native_task_record`。 |
|
||||
| `openclaw-multi-session-plugins` | `src/exportArtifacts.test.ts` | 同线程 `assets/images/**/*.png`、manifest、视频/PDF 交付物能被 export 到当前 task artifact scope,不串到旧线程或旧 run,`expectedArtifactDirs` 不存在也保留字段,路径 traversal 被拒绝。 |
|
||||
|
||||
## 5 个提示词
|
||||
|
||||
@ -119,6 +132,9 @@
|
||||
- 不出现 `ACP_HTTP_CONNECTION_CLOSED`。
|
||||
- 当前任务没有 artifact 时显示明确空态,不显示旧 run 文件。
|
||||
- 当前任务生成 PNG/PDF/视频文件时,右侧 artifact 自动同步并只显示当前任务本轮文件。
|
||||
- `xworkmate.session.prepare` 写入的 mapping 同时包含 `appThreadKey` 和 `openclawSessionKey`。
|
||||
- `xworkmate.tasks.get` 使用 `appThreadKey/openclawSessionKey/runId`,不发送旧 `sessionKey` lookup 参数。
|
||||
- `expectedArtifactDirs` 从 App metadata 到 Bridge prepare/export/snapshot 到 Plugin artifact resolver 全链路保留。
|
||||
|
||||
## 回归命令
|
||||
|
||||
|
||||
@ -955,8 +955,8 @@ extension AppControllerDesktopThreadActions on AppController {
|
||||
return <String, dynamic>{
|
||||
...baseMetadata,
|
||||
'xworkmateTaskArtifactContract': <String, dynamic>{
|
||||
'version': 1,
|
||||
'sessionKey': sessionKey,
|
||||
'schemaVersion': 1,
|
||||
'appThreadKey': sessionKey,
|
||||
'scopeKind': 'task',
|
||||
'finalDeliverableDetection': 'remote-runtime',
|
||||
'requiresExportBeforeFinalResponse': true,
|
||||
|
||||
@ -923,8 +923,9 @@ class OpenClawTaskAssociation {
|
||||
required this.gatewayProviderId,
|
||||
required this.startedAtMs,
|
||||
required this.status,
|
||||
required this.appThreadKey,
|
||||
required this.openclawSessionKey,
|
||||
this.taskLoadClass = '',
|
||||
this.sessionKey = '',
|
||||
this.requiredArtifactExtensions = const <String>[],
|
||||
this.expectedArtifactExtensions = const <String>[],
|
||||
});
|
||||
@ -938,8 +939,9 @@ class OpenClawTaskAssociation {
|
||||
final String gatewayProviderId;
|
||||
final double startedAtMs;
|
||||
final String status;
|
||||
final String appThreadKey;
|
||||
final String openclawSessionKey;
|
||||
final String taskLoadClass;
|
||||
final String sessionKey;
|
||||
final List<String> requiredArtifactExtensions;
|
||||
final List<String> expectedArtifactExtensions;
|
||||
|
||||
@ -962,8 +964,9 @@ class OpenClawTaskAssociation {
|
||||
gatewayProviderId: gatewayProviderId,
|
||||
startedAtMs: startedAtMs,
|
||||
status: status ?? this.status,
|
||||
appThreadKey: appThreadKey,
|
||||
openclawSessionKey: openclawSessionKey,
|
||||
taskLoadClass: taskLoadClass,
|
||||
sessionKey: sessionKey,
|
||||
requiredArtifactExtensions: requiredArtifactExtensions,
|
||||
expectedArtifactExtensions: expectedArtifactExtensions,
|
||||
);
|
||||
@ -980,8 +983,9 @@ class OpenClawTaskAssociation {
|
||||
'gatewayProviderId': gatewayProviderId,
|
||||
'startedAtMs': startedAtMs,
|
||||
'status': status,
|
||||
'appThreadKey': appThreadKey,
|
||||
'openclawSessionKey': openclawSessionKey,
|
||||
'taskLoadClass': taskLoadClass,
|
||||
'sessionKey': sessionKey,
|
||||
'requiredArtifactExtensions': requiredArtifactExtensions,
|
||||
'expectedArtifactExtensions': expectedArtifactExtensions,
|
||||
};
|
||||
@ -997,7 +1001,9 @@ class OpenClawTaskAssociation {
|
||||
'artifactDirectory': artifactDirectory,
|
||||
'gatewayProviderId': gatewayProviderId,
|
||||
'taskLoadClass': taskLoadClass,
|
||||
'sessionKey': sessionKey,
|
||||
'appThreadKey': appThreadKey,
|
||||
'openclawSessionKey': openclawSessionKey,
|
||||
'includeArtifacts': true,
|
||||
'requiredArtifactExtensions': requiredArtifactExtensions,
|
||||
'expectedArtifactExtensions': expectedArtifactExtensions,
|
||||
};
|
||||
@ -1010,7 +1016,13 @@ class OpenClawTaskAssociation {
|
||||
final json = value.cast<String, dynamic>();
|
||||
final runId = json['runId']?.toString().trim() ?? '';
|
||||
final artifactScope = json['artifactScope']?.toString().trim() ?? '';
|
||||
if (runId.isEmpty || artifactScope.isEmpty) {
|
||||
final appThreadKey = json['appThreadKey']?.toString().trim() ?? '';
|
||||
final openclawSessionKey =
|
||||
json['openclawSessionKey']?.toString().trim() ?? '';
|
||||
if (runId.isEmpty ||
|
||||
artifactScope.isEmpty ||
|
||||
appThreadKey.isEmpty ||
|
||||
openclawSessionKey.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
double asDouble(Object? raw) {
|
||||
@ -1038,8 +1050,9 @@ class OpenClawTaskAssociation {
|
||||
status: json['status']?.toString().trim().isNotEmpty == true
|
||||
? json['status'].toString().trim()
|
||||
: 'running',
|
||||
appThreadKey: appThreadKey,
|
||||
openclawSessionKey: openclawSessionKey,
|
||||
taskLoadClass: json['taskLoadClass']?.toString().trim() ?? '',
|
||||
sessionKey: json['sessionKey']?.toString().trim() ?? '',
|
||||
requiredArtifactExtensions: _stringListFromJson(
|
||||
json['requiredArtifactExtensions'],
|
||||
),
|
||||
|
||||
@ -64,6 +64,32 @@ void main() {
|
||||
);
|
||||
});
|
||||
|
||||
test('OpenClaw task lookup params use typed session mapping keys', () {
|
||||
const association = OpenClawTaskAssociation(
|
||||
sessionId: 'draft:1780658097668838-1',
|
||||
threadId: 'draft:1780658097668838-1',
|
||||
turnId: 'turn-1',
|
||||
runId: 'run-1',
|
||||
artifactScope: 'tasks/agent:main:draft:1780658097668838-1/run-1',
|
||||
artifactDirectory:
|
||||
'/tmp/tasks/agent:main:draft:1780658097668838-1/run-1',
|
||||
gatewayProviderId: 'openclaw',
|
||||
startedAtMs: 0,
|
||||
status: 'running',
|
||||
appThreadKey: 'draft:1780658097668838-1',
|
||||
openclawSessionKey: 'agent:main:draft:1780658097668838-1',
|
||||
);
|
||||
|
||||
final params = association.toTaskGetParams();
|
||||
|
||||
expect(params['appThreadKey'], 'draft:1780658097668838-1');
|
||||
expect(
|
||||
params['openclawSessionKey'],
|
||||
'agent:main:draft:1780658097668838-1',
|
||||
);
|
||||
expect(params, isNot(contains('sessionKey')));
|
||||
});
|
||||
|
||||
test('recognizes openclaw as the canonical gateway provider', () {
|
||||
final provider = SingleAgentProvider.fromJsonValue('openclaw');
|
||||
|
||||
@ -1310,19 +1336,19 @@ void main() {
|
||||
final artifactContract =
|
||||
(request.metadata['xworkmateTaskArtifactContract'] as Map)
|
||||
.cast<String, dynamic>();
|
||||
expect(artifactContract['schemaVersion'], 1);
|
||||
expect(artifactContract['appThreadKey'], request.sessionId);
|
||||
expect(artifactContract, isNot(contains('sessionKey')));
|
||||
expect(artifactContract['finalDeliverableDetection'], 'remote-runtime');
|
||||
expect(artifactContract['requiresExportBeforeFinalResponse'], isTrue);
|
||||
expect(
|
||||
artifactContract['expectedArtifactDirs'],
|
||||
const <String>[
|
||||
'artifacts/',
|
||||
'reports/',
|
||||
'exports/',
|
||||
'assets/',
|
||||
'assets/images/',
|
||||
'dist/',
|
||||
],
|
||||
);
|
||||
expect(artifactContract['expectedArtifactDirs'], const <String>[
|
||||
'artifacts/',
|
||||
'reports/',
|
||||
'exports/',
|
||||
'assets/',
|
||||
'assets/images/',
|
||||
'dist/',
|
||||
]);
|
||||
expect(artifactContract, isNot(contains('expectedArtifactExtensions')));
|
||||
expect(request.prompt, isNot(contains('Task load classification:')));
|
||||
expect(
|
||||
@ -1366,19 +1392,19 @@ void main() {
|
||||
final artifactContract =
|
||||
(request.metadata['xworkmateTaskArtifactContract'] as Map)
|
||||
.cast<String, dynamic>();
|
||||
expect(artifactContract['schemaVersion'], 1);
|
||||
expect(artifactContract['appThreadKey'], request.sessionId);
|
||||
expect(artifactContract, isNot(contains('sessionKey')));
|
||||
expect(artifactContract['scopeKind'], 'task');
|
||||
expect(artifactContract['rejectTextOnlyFileClaims'], isTrue);
|
||||
expect(
|
||||
artifactContract['expectedArtifactDirs'],
|
||||
const <String>[
|
||||
'artifacts/',
|
||||
'reports/',
|
||||
'exports/',
|
||||
'assets/',
|
||||
'assets/images/',
|
||||
'dist/',
|
||||
],
|
||||
);
|
||||
expect(artifactContract['expectedArtifactDirs'], const <String>[
|
||||
'artifacts/',
|
||||
'reports/',
|
||||
'exports/',
|
||||
'assets/',
|
||||
'assets/images/',
|
||||
'dist/',
|
||||
]);
|
||||
expect(
|
||||
artifactContract['currentTaskWorkspace'],
|
||||
request.workingDirectory,
|
||||
@ -3930,12 +3956,14 @@ void main() {
|
||||
'status': 'running',
|
||||
'sessionId': 'openclaw-poll-failed-task',
|
||||
'threadId': 'openclaw-poll-failed-task',
|
||||
'appThreadKey': 'openclaw-poll-failed-task',
|
||||
'openclawSessionKey': 'agent:main:openclaw-poll-failed-task',
|
||||
'turnId': 'turn-openclaw-poll-failed',
|
||||
'runId': 'run-openclaw-poll-failed',
|
||||
'artifactScope':
|
||||
'tasks/openclaw-poll-failed-task/run-openclaw-poll-failed',
|
||||
'tasks/agent:main:openclaw-poll-failed-task/run-openclaw-poll-failed',
|
||||
'artifactDirectory':
|
||||
'/tmp/tasks/openclaw-poll-failed-task/run-openclaw-poll-failed',
|
||||
'/tmp/tasks/agent:main:openclaw-poll-failed-task/run-openclaw-poll-failed',
|
||||
'gatewayProviderId': 'openclaw',
|
||||
'runtimeBudgetMinutes': 1,
|
||||
},
|
||||
@ -3998,12 +4026,14 @@ void main() {
|
||||
'status': 'running',
|
||||
'sessionId': 'openclaw-missing-screenshot',
|
||||
'threadId': 'openclaw-missing-screenshot',
|
||||
'appThreadKey': 'openclaw-missing-screenshot',
|
||||
'openclawSessionKey': 'agent:main:openclaw-missing-screenshot',
|
||||
'turnId': 'turn-openclaw-missing-screenshot',
|
||||
'runId': 'run-openclaw-missing-screenshot',
|
||||
'artifactScope':
|
||||
'tasks/openclaw-missing-screenshot/run-openclaw-missing-screenshot',
|
||||
'tasks/agent:main:openclaw-missing-screenshot/run-openclaw-missing-screenshot',
|
||||
'artifactDirectory':
|
||||
'/tmp/tasks/openclaw-missing-screenshot/run-openclaw-missing-screenshot',
|
||||
'/tmp/tasks/agent:main:openclaw-missing-screenshot/run-openclaw-missing-screenshot',
|
||||
'gatewayProviderId': 'openclaw',
|
||||
'runtimeBudgetMinutes': 1,
|
||||
'requiredArtifactExtensions': <String>['.png'],
|
||||
@ -4623,7 +4653,7 @@ Future<List<String>> _startOpenClawActiveTasks(
|
||||
await expectLater(
|
||||
controller
|
||||
.sendChatMessage('active task $index')
|
||||
.timeout(const Duration(seconds: 2)),
|
||||
.timeout(_openClawE2ESubmitTimeout),
|
||||
completes,
|
||||
);
|
||||
await fakeGoTaskService.waitForRequestCount(index + 1);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user