@ai-workbench/remote-agent 0.8.15 → 0.8.17
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 +11 -5
- package/dist/acp.js +1 -1
- package/dist/claude-local.js +2 -0
- package/dist/close-diagnostics.d.ts +1 -6
- package/dist/close-diagnostics.js +4 -34
- package/dist/connect-contract.d.ts +5 -4
- package/dist/connect-need.d.ts +12 -0
- package/dist/connect-need.js +34 -0
- package/dist/conversation-details.js +1 -1
- package/dist/employee-location.js +2 -1
- package/dist/employee-provider.js +16 -7
- package/dist/failure-evidence.d.ts +12 -0
- package/dist/failure-evidence.js +83 -0
- package/dist/host-workspace.d.ts +13 -0
- package/dist/host-workspace.js +110 -0
- package/dist/index.js +38 -20
- package/dist/model-catalog.d.ts +11 -1
- package/dist/model-catalog.js +35 -7
- package/dist/preflight-diagnostic.js +4 -3
- package/dist/presentation.js +4 -0
- package/dist/provider.d.ts +2 -1
- package/dist/provider.js +124 -71
- package/dist/remote-details.js +55 -27
- package/dist/remote.d.ts +2 -0
- package/dist/remote.js +1 -0
- package/dist/workspace-source.js +4 -2
- package/package.json +3 -3
package/dist/remote-details.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { closeCode, withFailureEvidence } from "./close-diagnostics.js";
|
|
1
2
|
import { createHash, randomUUID } from 'node:crypto';
|
|
2
3
|
import { constants } from 'node:fs';
|
|
3
4
|
import { mkdir, open, lstat, realpath, readdir } from 'node:fs/promises';
|
|
@@ -362,40 +363,67 @@ export function createRemoteDetails(options) {
|
|
|
362
363
|
scope.maximum = sequence;
|
|
363
364
|
const detail = Object.freeze({ ...safe, payload: wire(safe.payload), version: 1, eventId: randomUUID(), instanceId: request.connection.instanceId, epoch: request.connection.epoch, sessionId: request.sessionId, provider: request.provider, turn, step, sequence, kind: kind(observation) });
|
|
364
365
|
enqueue(async () => {
|
|
365
|
-
//
|
|
366
|
+
// Pending is not a delivery verdict. Keep the exact failed stage separately.
|
|
366
367
|
const file = join(dir, sequence + '-' + detail.eventId + '.json');
|
|
368
|
+
let phase = 'journal', appendAttempted = false, outcomeKnown = false;
|
|
367
369
|
try {
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
try {
|
|
376
|
-
response = await (localScope === undefined ? api.appendRemoteConversationDetail(structuredClone(detail)) : api.appendRemoteConversationDetail(structuredClone(detail), localScope));
|
|
377
|
-
}
|
|
378
|
-
catch {
|
|
370
|
+
try {
|
|
371
|
+
await durableWrite(file, { state: 'pending', detail });
|
|
372
|
+
}
|
|
373
|
+
catch {
|
|
374
|
+
throw failure('REMOTE_DETAIL_STORAGE_FAILED');
|
|
375
|
+
}
|
|
376
|
+
phase = 'append-scope';
|
|
379
377
|
stable();
|
|
380
|
-
|
|
378
|
+
let response;
|
|
379
|
+
try {
|
|
380
|
+
phase = 'append';
|
|
381
|
+
appendAttempted = true;
|
|
382
|
+
response = await (localScope === undefined ? api.appendRemoteConversationDetail(structuredClone(detail)) : api.appendRemoteConversationDetail(structuredClone(detail), localScope));
|
|
383
|
+
}
|
|
384
|
+
catch {
|
|
385
|
+
phase = 'receipt-scope';
|
|
386
|
+
stable();
|
|
387
|
+
phase = 'receipt';
|
|
388
|
+
const receipt = unwrap(await api.getRemoteConversationDetailReceipt({ eventId: detail.eventId, sessionId: detail.sessionId, provider: detail.provider }));
|
|
389
|
+
phase = 'receipt-scope';
|
|
390
|
+
stable();
|
|
391
|
+
if (receipt.eventId !== detail.eventId)
|
|
392
|
+
throw failure('REMOTE_DETAIL_RECEIPT_INVALID');
|
|
393
|
+
if (!receipt.recorded)
|
|
394
|
+
throw failure('REMOTE_DETAIL_DELIVERY_UNKNOWN');
|
|
395
|
+
if (!isDeepStrictEqual(receipt.detail, detail))
|
|
396
|
+
throw failure('REMOTE_DETAIL_RECEIPT_INVALID');
|
|
397
|
+
phase = 'settlement';
|
|
398
|
+
await durableWrite(join(dir, 'settled-' + detail.eventId + '.json'), { eventId: detail.eventId, state: 'recorded' });
|
|
399
|
+
outcomeKnown = true;
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
phase = 'ack-scope';
|
|
381
403
|
stable();
|
|
382
|
-
if (
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
404
|
+
if (response?.ok === false) {
|
|
405
|
+
phase = 'settlement';
|
|
406
|
+
await durableWrite(join(dir, 'settled-' + detail.eventId + '.json'), { eventId: detail.eventId, state: 'rejected', code: response.error.code });
|
|
407
|
+
outcomeKnown = true;
|
|
408
|
+
}
|
|
409
|
+
const ack = unwrap(response);
|
|
410
|
+
if (ack.eventId !== detail.eventId || ack.recorded !== true)
|
|
411
|
+
throw failure('REMOTE_DETAIL_RESPONSE_INVALID');
|
|
412
|
+
phase = 'settlement';
|
|
388
413
|
await durableWrite(join(dir, 'settled-' + detail.eventId + '.json'), { eventId: detail.eventId, state: 'recorded' });
|
|
389
|
-
|
|
414
|
+
outcomeKnown = true;
|
|
390
415
|
}
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
416
|
+
catch (error) {
|
|
417
|
+
if (!outcomeKnown) {
|
|
418
|
+
try {
|
|
419
|
+
await durableWrite(join(dir, 'unconfirmed-' + detail.eventId + '.json'), { version: 1, eventId: detail.eventId, state: 'unconfirmed', phase, appendAttempted, code: closeCode(error, 'REMOTE_DETAIL_STORAGE_FAILED') });
|
|
420
|
+
}
|
|
421
|
+
catch {
|
|
422
|
+
throw withFailureEvidence(error, [failure('REMOTE_DETAIL_STORAGE_FAILED')], 'diagnostic');
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
throw error;
|
|
394
426
|
}
|
|
395
|
-
const ack = unwrap(response);
|
|
396
|
-
if (ack.eventId !== detail.eventId || ack.recorded !== true)
|
|
397
|
-
throw failure('REMOTE_DETAIL_RESPONSE_INVALID');
|
|
398
|
-
await durableWrite(join(dir, 'settled-' + detail.eventId + '.json'), { eventId: detail.eventId, state: 'recorded' });
|
|
399
427
|
});
|
|
400
428
|
},
|
|
401
429
|
async flush() { await tail; if (firstFailure)
|
package/dist/remote.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ConnectNeed } from '@ai-workbench/connect/api';
|
|
1
2
|
import type { LoginDiagnostic } from './login-diagnostic.ts';
|
|
2
3
|
import type { ChildProcessWithoutNullStreams } from 'node:child_process';
|
|
3
4
|
/** Development-only direct SSH. Product transports must consume L's exported sshArgs (v0.2). */
|
|
@@ -19,6 +20,7 @@ export declare class NeedError extends Error {
|
|
|
19
20
|
requires: string;
|
|
20
21
|
technical?: LoginDiagnostic;
|
|
21
22
|
officialReason?: string;
|
|
23
|
+
connectNeed?: Readonly<ConnectNeed>;
|
|
22
24
|
constructor(code: string, message: string, requires: string);
|
|
23
25
|
}
|
|
24
26
|
export declare function shellQuote(value: string): string;
|
package/dist/remote.js
CHANGED
package/dist/workspace-source.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { withFailureEvidence } from "./failure-evidence.js";
|
|
2
|
+
import { connectNeedError } from "./connect-need.js";
|
|
1
3
|
import { isDeepStrictEqual } from 'node:util';
|
|
2
4
|
import { sanitizeDisplayLabel } from "./conversation-details.js";
|
|
3
5
|
import { NeedError } from "./remote.js";
|
|
4
6
|
const fail = (code) => new NeedError(code, '工作区来源尚未确认,本轮未执行;你的原话仍保留。', '当前工作区来源及原始员工输入');
|
|
5
7
|
const codeOf = (value) => value instanceof NeedError ? value.code : 'WORKSPACE_SOURCE_CONFIRMATION_FAILED';
|
|
6
|
-
const diagnosticFailure = (error, diagnostic) =>
|
|
8
|
+
const diagnosticFailure = (error, diagnostic) => withFailureEvidence(error, [diagnostic], 'diagnostic', undefined, codeOf(error));
|
|
7
9
|
/** Explicit human source transition only. No source selection is inferred from a folder path. */
|
|
8
10
|
export async function confirmLegacyWorkspaceSource(get, api, request, hooks) {
|
|
9
11
|
let initialContext = { workspaceId: null, bindingId: null, source: null, status: null };
|
|
@@ -81,7 +83,7 @@ export async function confirmLegacyWorkspaceSource(get, api, request, hooks) {
|
|
|
81
83
|
const selected = await api.selectWorkspaceLocation({ instanceId: connection.instanceId, epoch: connection.epoch, workspaceId: workspace.id, expectedBindingId: frozen.bindingId, source: 'local' });
|
|
82
84
|
request.signal?.throwIfAborted();
|
|
83
85
|
if (!selected.ok)
|
|
84
|
-
throw
|
|
86
|
+
throw connectNeedError(selected.error);
|
|
85
87
|
const current = await stable(false), value = selected.value, returned = value.items.filter(item => item.workspaceId === workspace.id);
|
|
86
88
|
if (value.phase !== 'ready' || value.instanceId !== connection.instanceId || value.epoch !== connection.epoch || returned.length !== 1 || returned[0].source !== 'local' || returned[0].status !== 'selected' || !returned[0].bindingId || returned[0].bindingId === frozen.bindingId || returned[0].localPath !== workspace.path || current.source !== 'local' || current.status !== 'selected' || current.bindingId !== returned[0].bindingId)
|
|
87
89
|
throw fail('WORKSPACE_SOURCE_SELECTION_UNCONFIRMED');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-workbench/remote-agent",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.17",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"zod": "4.6.7"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@ai-workbench/connect": "file:test/fixtures/ai-workbench-connect-0.7.
|
|
42
|
+
"@ai-workbench/connect": "file:test/fixtures/ai-workbench-connect-0.7.20.tgz",
|
|
43
43
|
"@ai-workbench/network": "file:test/fixtures/ai-workbench-network-0.4.4.tgz",
|
|
44
44
|
"@deepseek-ai/cordis": "4.0.4",
|
|
45
45
|
"@deepseek-ai/cordis-plugin-group": "1.0.4",
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"zustand": "4.4.7"
|
|
69
69
|
},
|
|
70
70
|
"peerDependencies": {
|
|
71
|
-
"@ai-workbench/connect": "~0.7.
|
|
71
|
+
"@ai-workbench/connect": "~0.7.20",
|
|
72
72
|
"@ai-workbench/network": "~0.4.4",
|
|
73
73
|
"@deepseek-ai/cordis": "4.0.4",
|
|
74
74
|
"@deepseek-ai/dsh-agent": "0.2.0-rc.2",
|