superun-ai-cli 0.1.32 → 0.1.34
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.en.md +2 -0
- package/README.md +24 -1
- package/dist/api/agent-friendly-api.d.ts +16 -0
- package/dist/api/agent-friendly-api.js +83 -0
- package/dist/api/agent-friendly-api.js.map +1 -0
- package/dist/commands/chat/agent-friendly.d.ts +4 -0
- package/dist/commands/chat/agent-friendly.js +97 -0
- package/dist/commands/chat/agent-friendly.js.map +1 -0
- package/dist/commands/chat/index.js +2 -0
- package/dist/commands/chat/index.js.map +1 -1
- package/dist/commands/chat/publish.js +7 -0
- package/dist/commands/chat/publish.js.map +1 -1
- package/dist/commands/shared.d.ts +4 -0
- package/dist/commands/shared.js +46 -28
- package/dist/commands/shared.js.map +1 -1
- package/dist/config/state-directory.d.ts +1 -0
- package/dist/config/state-directory.js +13 -0
- package/dist/config/state-directory.js.map +1 -0
- package/dist/conversation/agent-friendly-prompts.d.ts +11 -0
- package/dist/conversation/agent-friendly-prompts.js +57 -0
- package/dist/conversation/agent-friendly-prompts.js.map +1 -0
- package/dist/conversation/agent-friendly.d.ts +24 -0
- package/dist/conversation/agent-friendly.js +165 -0
- package/dist/conversation/agent-friendly.js.map +1 -0
- package/dist/interactions/draft-store.d.ts +8 -0
- package/dist/interactions/draft-store.js +163 -70
- package/dist/interactions/draft-store.js.map +1 -1
- package/dist/interactions/state-storage.d.ts +4 -0
- package/dist/interactions/state-storage.js +65 -0
- package/dist/interactions/state-storage.js.map +1 -0
- package/dist/output/exit-codes.d.ts +4 -0
- package/dist/output/exit-codes.js +4 -0
- package/dist/output/exit-codes.js.map +1 -1
- package/dist/program.js +4 -1
- package/dist/program.js.map +1 -1
- package/dist/session/binding.d.ts +6 -4
- package/dist/session/binding.js +68 -22
- package/dist/session/binding.js.map +1 -1
- package/dist/session/remember-worker.d.ts +1 -0
- package/dist/session/remember-worker.js +43 -0
- package/dist/session/remember-worker.js.map +1 -0
- package/dist/session/remember.d.ts +9 -0
- package/dist/session/remember.js +14 -0
- package/dist/session/remember.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/** 保留状态操作与清理失败的诊断信息,不输出状态内容。@author xiuyu.yi */
|
|
2
|
+
import { CliError } from '../output/exit-codes.js';
|
|
3
|
+
export function filesystemCode(error) {
|
|
4
|
+
return error && typeof error === 'object' && 'code' in error && typeof error.code === 'string'
|
|
5
|
+
? error.code
|
|
6
|
+
: undefined;
|
|
7
|
+
}
|
|
8
|
+
export async function stateOperation(operation, path, run) {
|
|
9
|
+
try {
|
|
10
|
+
return await run();
|
|
11
|
+
}
|
|
12
|
+
catch (error) {
|
|
13
|
+
if (error instanceof CliError)
|
|
14
|
+
throw error;
|
|
15
|
+
const code = filesystemCode(error);
|
|
16
|
+
const denied = code === 'EPERM' || code === 'EACCES';
|
|
17
|
+
throw new CliError(denied ? 'LOCAL_STATE_PERMISSION_DENIED' : 'LOCAL_STATE_IO_ERROR', denied
|
|
18
|
+
? '本地状态目录权限不足,请由宿主授权所需文件操作,或配置可用的持久化 SUPERUN_STATE_DIR;不要重复提交业务请求'
|
|
19
|
+
: '本地状态文件操作失败,请根据操作和路径排查;不要重复提交业务请求', { filesystemCode: code, operation, path });
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/** 所有清理均尝试执行;清理异常不能覆盖首次异常。 */
|
|
23
|
+
export async function withStateCleanup(run, cleanup) {
|
|
24
|
+
let failed = false;
|
|
25
|
+
let primary;
|
|
26
|
+
let result;
|
|
27
|
+
try {
|
|
28
|
+
result = await run();
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
failed = true;
|
|
32
|
+
primary = error;
|
|
33
|
+
}
|
|
34
|
+
const errors = [];
|
|
35
|
+
for (const clean of cleanup) {
|
|
36
|
+
try {
|
|
37
|
+
await clean();
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
errors.push(error instanceof CliError ? error : new CliError('LOCAL_STATE_IO_ERROR', '本地状态清理失败'));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (errors.length) {
|
|
44
|
+
const first = failed
|
|
45
|
+
? primary instanceof CliError
|
|
46
|
+
? primary
|
|
47
|
+
: new CliError('PROTOCOL_ERROR', '操作失败且本地状态清理失败,请保留现场排查')
|
|
48
|
+
: errors.shift();
|
|
49
|
+
throw new CliError(first.code, first.message, {
|
|
50
|
+
...first.details,
|
|
51
|
+
...(errors.length
|
|
52
|
+
? {
|
|
53
|
+
cleanupErrors: [
|
|
54
|
+
...(Array.isArray(first.details.cleanupErrors) ? first.details.cleanupErrors : []),
|
|
55
|
+
...errors.map((error) => ({ ...error.details, code: error.code })),
|
|
56
|
+
],
|
|
57
|
+
}
|
|
58
|
+
: {}),
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
if (failed)
|
|
62
|
+
throw primary;
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=state-storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-storage.js","sourceRoot":"","sources":["../../src/interactions/state-storage.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,6 +12,10 @@ export declare const EXIT_CODES: {
|
|
|
12
12
|
readonly UNSUPPORTED_INTERACTION: 6;
|
|
13
13
|
readonly LOCAL_WAIT_TIMEOUT: 7;
|
|
14
14
|
readonly PROTOCOL_ERROR: 8;
|
|
15
|
+
readonly LOCAL_STATE_PERMISSION_DENIED: 9;
|
|
16
|
+
readonly LOCAL_STATE_IO_ERROR: 9;
|
|
17
|
+
readonly LOCAL_STATE_LOCKED: 9;
|
|
18
|
+
readonly LOCAL_STATE_RECOVERY_REQUIRED: 9;
|
|
15
19
|
readonly INTERRUPTED: 130;
|
|
16
20
|
};
|
|
17
21
|
export type ErrorCode = keyof typeof EXIT_CODES;
|
|
@@ -12,6 +12,10 @@ export const EXIT_CODES = {
|
|
|
12
12
|
UNSUPPORTED_INTERACTION: 6,
|
|
13
13
|
LOCAL_WAIT_TIMEOUT: 7,
|
|
14
14
|
PROTOCOL_ERROR: 8,
|
|
15
|
+
LOCAL_STATE_PERMISSION_DENIED: 9,
|
|
16
|
+
LOCAL_STATE_IO_ERROR: 9,
|
|
17
|
+
LOCAL_STATE_LOCKED: 9,
|
|
18
|
+
LOCAL_STATE_RECOVERY_REQUIRED: 9,
|
|
15
19
|
INTERRUPTED: 130,
|
|
16
20
|
};
|
|
17
21
|
export class CliError extends Error {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exit-codes.js","sourceRoot":"","sources":["../../src/output/exit-codes.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,gBAAgB,EAAE,CAAC;IACnB,aAAa,EAAE,CAAC;IAChB,eAAe,EAAE,CAAC;IAClB,aAAa,EAAE,CAAC;IAChB,oBAAoB,EAAE,CAAC;IACvB,cAAc,EAAE,CAAC;IACjB,iBAAiB,EAAE,CAAC;IACpB,qBAAqB,EAAE,CAAC;IACxB,eAAe,EAAE,CAAC;IAClB,uBAAuB,EAAE,CAAC;IAC1B,kBAAkB,EAAE,CAAC;IACrB,cAAc,EAAE,CAAC;IACjB,WAAW,EAAE,GAAG;CACR,CAAC;AAIX,MAAM,OAAO,QAAS,SAAQ,KAAK;IAEtB;IAEA;IAHX,YACW,IAAe,EACxB,OAAe,EACN,UAAmC,EAAE;QAE9C,KAAK,CAAC,OAAO,CAAC,CAAC;QAJN,SAAI,GAAJ,IAAI,CAAW;QAEf,YAAO,GAAP,OAAO,CAA8B;QAG9C,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF"}
|
|
1
|
+
{"version":3,"file":"exit-codes.js","sourceRoot":"","sources":["../../src/output/exit-codes.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,gBAAgB,EAAE,CAAC;IACnB,aAAa,EAAE,CAAC;IAChB,eAAe,EAAE,CAAC;IAClB,aAAa,EAAE,CAAC;IAChB,oBAAoB,EAAE,CAAC;IACvB,cAAc,EAAE,CAAC;IACjB,iBAAiB,EAAE,CAAC;IACpB,qBAAqB,EAAE,CAAC;IACxB,eAAe,EAAE,CAAC;IAClB,uBAAuB,EAAE,CAAC;IAC1B,kBAAkB,EAAE,CAAC;IACrB,cAAc,EAAE,CAAC;IACjB,6BAA6B,EAAE,CAAC;IAChC,oBAAoB,EAAE,CAAC;IACvB,kBAAkB,EAAE,CAAC;IACrB,6BAA6B,EAAE,CAAC;IAChC,WAAW,EAAE,GAAG;CACR,CAAC;AAIX,MAAM,OAAO,QAAS,SAAQ,KAAK;IAEtB;IAEA;IAHX,YACW,IAAe,EACxB,OAAe,EACN,UAAmC,EAAE;QAE9C,KAAK,CAAC,OAAO,CAAC,CAAC;QAJN,SAAI,GAAJ,IAAI,CAAW;QAEf,YAAO,GAAP,OAAO,CAA8B;QAG9C,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF"}
|
package/dist/program.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** 命令树与公共选项。@author xiuyu.yi */
|
|
2
2
|
import { Command } from 'commander';
|
|
3
3
|
import { COMMAND_NAME, PACKAGE_VERSION } from './config/constants.js';
|
|
4
|
-
import { requireCredentials } from './commands/shared.js';
|
|
4
|
+
import { requireCredentials, rememberExplicitSession } from './commands/shared.js';
|
|
5
5
|
import { registerAuth } from './commands/auth/index.js';
|
|
6
6
|
import { registerSession } from './commands/session/index.js';
|
|
7
7
|
import { registerChat } from './commands/chat/index.js';
|
|
@@ -20,6 +20,8 @@ export function createProgram(context, hooks) {
|
|
|
20
20
|
context.connection = undefined;
|
|
21
21
|
context.sessionBinding = undefined;
|
|
22
22
|
context.selectedSessionId = undefined;
|
|
23
|
+
context.selectionRequestedAt = new Date().toISOString();
|
|
24
|
+
context.rememberSession = undefined;
|
|
23
25
|
const rootCommand = action.parent === program;
|
|
24
26
|
const authCommand = action.parent?.name() === 'auth' && action.parent.parent === program;
|
|
25
27
|
const offline = (rootCommand && (action.name() === 'version' || action.name() === 'update')) ||
|
|
@@ -29,6 +31,7 @@ export function createProgram(context, hooks) {
|
|
|
29
31
|
await hooks.beforeBusiness();
|
|
30
32
|
if (!(authCommand && action.name() === 'login'))
|
|
31
33
|
await requireCredentials(context, action, !authCommand);
|
|
34
|
+
rememberExplicitSession(context, action);
|
|
32
35
|
});
|
|
33
36
|
registerAuth(program, context);
|
|
34
37
|
registerSession(program, context);
|
package/dist/program.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"program.js","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAEtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"program.js","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAEtE,OAAO,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AACnF,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAE/D,MAAM,UAAU,aAAa,CAC3B,OAAuB,EACvB,KAGC;IAED,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE;SAC1B,IAAI,CAAC,YAAY,CAAC;SAClB,WAAW,CACV,iDAAiD,CAClD;SACA,OAAO,CAAC,eAAe,CAAC;SACxB,MAAM,CAAC,kBAAkB,EAAE,QAAQ,CAAC;SACpC,MAAM,CAAC,qBAAqB,EAAE,MAAM,EAAE,OAAO,CAAC;SAC9C,YAAY,EAAE;SACd,eAAe,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE,CAAC,CAAC;IAClD,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QAChD,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;QAC/B,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC;QACnC,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC;QACtC,OAAO,CAAC,oBAAoB,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACxD,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC;QACpC,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,KAAK,OAAO,CAAC;QAC9C,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,OAAO,CAAC;QACzF,MAAM,OAAO,GACX,CAAC,WAAW,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,SAAS,IAAI,MAAM,CAAC,IAAI,EAAE,KAAK,QAAQ,CAAC,CAAC;YAC5E,CAAC,WAAW,IAAI,MAAM,CAAC,IAAI,EAAE,KAAK,QAAQ,CAAC,CAAC;QAC9C,IAAI,OAAO,IAAI,MAAM,KAAK,OAAO;YAAE,OAAO;QAC1C,MAAM,KAAK,CAAC,cAAc,EAAE,CAAC;QAC7B,IAAI,CAAC,CAAC,WAAW,IAAI,MAAM,CAAC,IAAI,EAAE,KAAK,OAAO,CAAC;YAAE,MAAM,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC,WAAW,CAAC,CAAC;QACzG,uBAAuB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IACH,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC/B,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAClC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC/B,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACtD,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IACrC,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -33,14 +33,15 @@ declare const recordSchema: z.ZodEffects<z.ZodObject<{
|
|
|
33
33
|
sessionId?: string | undefined;
|
|
34
34
|
}>;
|
|
35
35
|
type BindingRecord = z.infer<typeof recordSchema>;
|
|
36
|
-
type BindingValue = Pick<BindingRecord, 'state' | 'sessionId'>;
|
|
37
36
|
export declare class SessionBinding {
|
|
38
37
|
readonly host: HostContext;
|
|
39
38
|
private readonly store;
|
|
39
|
+
private readonly creationStore;
|
|
40
40
|
private readonly key;
|
|
41
41
|
constructor(host: HostContext, endpoint: string, userCode: string, root?: string);
|
|
42
|
-
static connect(service: CreationRuntime, host: HostContext): Promise<SessionBinding>;
|
|
42
|
+
static connect(service: Pick<CreationRuntime, 'client'>, host: HostContext): Promise<SessionBinding>;
|
|
43
43
|
private storage;
|
|
44
|
+
private readRecord;
|
|
44
45
|
read(): Promise<BindingRecord | undefined>;
|
|
45
46
|
current(): Promise<{
|
|
46
47
|
version: 1;
|
|
@@ -68,7 +69,8 @@ export declare class SessionBinding {
|
|
|
68
69
|
state: "UNBOUND" | "BOUND" | "CREATING" | "CREATE_FAILED" | "CREATE_UNKNOWN";
|
|
69
70
|
sessionId?: string | undefined;
|
|
70
71
|
}>;
|
|
71
|
-
|
|
72
|
-
|
|
72
|
+
remember(sessionId: string, requestedAt: string): Promise<void>;
|
|
73
|
+
beginCreation(requestedAt?: string): Promise<string>;
|
|
74
|
+
finishCreation(revision: string, state: 'CREATE_FAILED' | 'CREATE_UNKNOWN' | 'UNBOUND'): Promise<boolean>;
|
|
73
75
|
}
|
|
74
76
|
export {};
|
package/dist/session/binding.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** 当前宿主会话唯一的项目绑定;创建回执按修订号提交。@author xiuyu.yi */
|
|
2
2
|
import { randomUUID } from 'node:crypto';
|
|
3
|
-
import { homedir } from 'node:os';
|
|
4
3
|
import { join } from 'node:path';
|
|
4
|
+
import { stateDirectory } from '../config/state-directory.js';
|
|
5
5
|
import { z } from 'zod';
|
|
6
6
|
import { InteractionDraftStore, fingerprint } from '../interactions/draft-store.js';
|
|
7
7
|
import { CliError } from '../output/exit-codes.js';
|
|
@@ -19,10 +19,13 @@ const recordSchema = z
|
|
|
19
19
|
export class SessionBinding {
|
|
20
20
|
host;
|
|
21
21
|
store;
|
|
22
|
+
creationStore;
|
|
22
23
|
key;
|
|
23
|
-
constructor(host, endpoint, userCode, root =
|
|
24
|
+
constructor(host, endpoint, userCode, root = stateDirectory('sessions')) {
|
|
24
25
|
this.host = host;
|
|
25
|
-
|
|
26
|
+
const scope = fingerprint([endpoint, userCode]);
|
|
27
|
+
this.store = new InteractionDraftStore(scope, root);
|
|
28
|
+
this.creationStore = new InteractionDraftStore(scope, join(root, 'creation'));
|
|
26
29
|
this.key = `${host.host}:${host.conversationId}`;
|
|
27
30
|
}
|
|
28
31
|
static async connect(service, host) {
|
|
@@ -38,59 +41,102 @@ export class SessionBinding {
|
|
|
38
41
|
return await run();
|
|
39
42
|
}
|
|
40
43
|
catch (error) {
|
|
41
|
-
if (error instanceof CliError
|
|
44
|
+
if (error instanceof CliError)
|
|
42
45
|
throw error;
|
|
43
|
-
throw new CliError(
|
|
46
|
+
throw new CliError('PROTOCOL_ERROR', '当前会话的项目绑定格式无效,请保留状态文件排查;不要重复提交创作请求');
|
|
44
47
|
}
|
|
45
48
|
}
|
|
46
|
-
async
|
|
49
|
+
async readRecord(store) {
|
|
47
50
|
return this.storage(async () => {
|
|
48
|
-
const raw = await
|
|
51
|
+
const raw = await store.read(this.key);
|
|
49
52
|
if (raw === undefined)
|
|
50
53
|
return undefined;
|
|
51
54
|
return recordSchema.parse(raw);
|
|
52
55
|
});
|
|
53
56
|
}
|
|
57
|
+
async read() {
|
|
58
|
+
const creation = await this.readRecord(this.creationStore);
|
|
59
|
+
if (creation?.state === 'CREATING' || creation?.state === 'CREATE_UNKNOWN')
|
|
60
|
+
return creation;
|
|
61
|
+
const binding = await this.readRecord(this.store);
|
|
62
|
+
// 创建后的辅助保存尚未完成时,也不能重新暴露之前项目的旧绑定。
|
|
63
|
+
if (creation && (!binding || creation.updatedAt > binding.updatedAt))
|
|
64
|
+
return creation;
|
|
65
|
+
return binding;
|
|
66
|
+
}
|
|
54
67
|
async current() {
|
|
55
68
|
return { host: this.host, ...((await this.read()) ?? { state: 'UNBOUND' }) };
|
|
56
69
|
}
|
|
57
|
-
async save(value) {
|
|
70
|
+
async save(value, updatedAt = new Date().toISOString(), store = this.store) {
|
|
58
71
|
const record = recordSchema.parse({
|
|
59
72
|
version: 1,
|
|
60
73
|
revision: randomUUID(),
|
|
61
|
-
updatedAt
|
|
74
|
+
updatedAt,
|
|
62
75
|
...value,
|
|
63
76
|
});
|
|
64
|
-
await
|
|
77
|
+
await store.write(this.key, record);
|
|
65
78
|
return record;
|
|
66
79
|
}
|
|
67
80
|
async select(service, sessionId) {
|
|
68
|
-
const revision = (await this.
|
|
81
|
+
const revision = (await this.readRecord(this.store))?.revision;
|
|
82
|
+
const creation = await this.readRecord(this.creationStore);
|
|
69
83
|
const result = await service.conversation.recently(sessionId);
|
|
70
84
|
if (result.session.sessionId !== sessionId)
|
|
71
85
|
throw new CliError('PROTOCOL_ERROR', '项目校验返回了不同的 sessionId,未切换绑定');
|
|
72
|
-
|
|
73
|
-
if ((await this.
|
|
86
|
+
const selected = await this.storage(() => this.store.locked(this.key, async () => {
|
|
87
|
+
if ((await this.readRecord(this.store))?.revision !== revision)
|
|
74
88
|
throw new CliError('STALE_INTERACTION', '校验项目期间当前绑定已变化,请重新读取绑定后再操作');
|
|
89
|
+
if ((await this.readRecord(this.creationStore))?.revision !== creation?.revision)
|
|
90
|
+
throw new CliError('STALE_INTERACTION', '校验项目期间创建状态已变化,请先查询原创建结果');
|
|
75
91
|
return this.save({ state: 'BOUND', sessionId });
|
|
76
92
|
}));
|
|
93
|
+
if (creation && ['CREATING', 'CREATE_UNKNOWN'].includes(creation.state)) {
|
|
94
|
+
if (!(await this.finishCreation(creation.revision, 'UNBOUND')))
|
|
95
|
+
throw new CliError('STALE_INTERACTION', '恢复绑定期间创建状态已变化,请先查询原创建结果');
|
|
96
|
+
}
|
|
97
|
+
return selected;
|
|
77
98
|
}
|
|
78
99
|
async clear() {
|
|
79
|
-
return this.storage(() => this.store.locked(this.key, () => this.save({ state: 'UNBOUND' })));
|
|
80
|
-
}
|
|
81
|
-
async beginCreation() {
|
|
82
100
|
return this.storage(() => this.store.locked(this.key, async () => {
|
|
83
101
|
const current = await this.read();
|
|
84
102
|
if (current?.state === 'CREATING' || current?.state === 'CREATE_UNKNOWN')
|
|
85
|
-
throw new CliError('OUTCOME_UNKNOWN', '
|
|
86
|
-
return
|
|
103
|
+
throw new CliError('OUTCOME_UNKNOWN', '创建结果尚未确认,请先查询原请求;确认项目 ID 后可用 session use 恢复绑定');
|
|
104
|
+
return this.save({ state: 'UNBOUND' });
|
|
87
105
|
}));
|
|
88
106
|
}
|
|
89
|
-
async
|
|
107
|
+
async remember(sessionId, requestedAt) {
|
|
90
108
|
await this.storage(() => this.store.locked(this.key, async () => {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
109
|
+
const current = await this.readRecord(this.store);
|
|
110
|
+
const creation = await this.readRecord(this.creationStore);
|
|
111
|
+
if (creation && creation.updatedAt > requestedAt)
|
|
112
|
+
return;
|
|
113
|
+
// 后台任务可能乱序完成;旧操作不能覆盖较新的选择、清除或创建状态。
|
|
114
|
+
if (current &&
|
|
115
|
+
(current.updatedAt >= requestedAt ||
|
|
116
|
+
current.state === 'CREATING' ||
|
|
117
|
+
current.state === 'CREATE_UNKNOWN'))
|
|
118
|
+
return;
|
|
119
|
+
await this.save({ state: 'BOUND', sessionId }, requestedAt);
|
|
120
|
+
}));
|
|
121
|
+
}
|
|
122
|
+
async beginCreation(requestedAt = new Date().toISOString()) {
|
|
123
|
+
return this.storage(() => this.creationStore.locked(this.key, async () => {
|
|
124
|
+
const current = await this.readRecord(this.creationStore);
|
|
125
|
+
// 升级前的未决创建可能仍在旧绑定文件中,不能忽略后重新创建。
|
|
126
|
+
const legacy = await this.readRecord(this.store);
|
|
127
|
+
if ([current, legacy].some((record) => record?.state === 'CREATING' || record?.state === 'CREATE_UNKNOWN'))
|
|
128
|
+
throw new CliError('OUTCOME_UNKNOWN', '上次创建尚未确认结果,请先查询原请求;不要重复创建');
|
|
129
|
+
return (await this.save({ state: 'CREATING' }, requestedAt, this.creationStore)).revision;
|
|
130
|
+
}));
|
|
131
|
+
}
|
|
132
|
+
async finishCreation(revision, state) {
|
|
133
|
+
return this.storage(() => this.creationStore.locked(this.key, async () => {
|
|
134
|
+
const current = await this.readRecord(this.creationStore);
|
|
135
|
+
if (current?.revision !== revision)
|
|
136
|
+
return false;
|
|
137
|
+
// 保护记录只保存创建状态,不保存项目 ID;时间保留原请求顺序。
|
|
138
|
+
await this.save({ state }, current.updatedAt, this.creationStore);
|
|
139
|
+
return true;
|
|
94
140
|
}));
|
|
95
141
|
}
|
|
96
142
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"binding.js","sourceRoot":"","sources":["../../src/session/binding.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"binding.js","sourceRoot":"","sources":["../../src/session/binding.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/** 单次后台绑定保存;只查询身份与写本地状态,不执行创作或登录。@author xiuyu.yi */
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { PatStore } from '../auth/pat-store.js';
|
|
4
|
+
import { runtimeConfig } from '../config/runtime-config.js';
|
|
5
|
+
import { ApiClient } from '../transport/api-client.js';
|
|
6
|
+
import { detectHostContext } from './host-context.js';
|
|
7
|
+
import { SessionBinding } from './binding.js';
|
|
8
|
+
import { ConversationApi } from '../api/conversation-api.js';
|
|
9
|
+
try {
|
|
10
|
+
const request = z
|
|
11
|
+
.object({
|
|
12
|
+
sessionId: z.string().trim().min(1).max(500),
|
|
13
|
+
requestedAt: z.string().datetime(),
|
|
14
|
+
endpoint: z.string(),
|
|
15
|
+
locale: z.string(),
|
|
16
|
+
credentialScope: z.string().regex(/^[a-f0-9]{64}$/),
|
|
17
|
+
creationRevision: z.string().uuid().optional(),
|
|
18
|
+
})
|
|
19
|
+
.strict()
|
|
20
|
+
.parse(JSON.parse(process.argv[2] ?? ''));
|
|
21
|
+
const host = await detectHostContext();
|
|
22
|
+
if (host) {
|
|
23
|
+
const credential = await new PatStore().readIfPresent();
|
|
24
|
+
if (credential) {
|
|
25
|
+
const config = { ...runtimeConfig(request), timeoutMs: 5_000 };
|
|
26
|
+
const client = new ApiClient(config, credential.pat, undefined, AbortSignal.timeout(5_000));
|
|
27
|
+
// 凭据可能在主命令结束后变更;不能把旧操作写入另一个账号的绑定。
|
|
28
|
+
if (client.interactionScope === request.credentialScope) {
|
|
29
|
+
const binding = await SessionBinding.connect({ client }, host);
|
|
30
|
+
const project = await new ConversationApi(client).recently(request.sessionId);
|
|
31
|
+
if (project.session.sessionId === request.sessionId) {
|
|
32
|
+
const resolved = !request.creationRevision || (await binding.finishCreation(request.creationRevision, 'UNBOUND'));
|
|
33
|
+
if (resolved)
|
|
34
|
+
await binding.remember(request.sessionId, request.requestedAt);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
// 保存失败静默结束,不重新派发、不输出提示、不提交任何业务请求。
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=remember-worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remember-worker.js","sourceRoot":"","sources":["../../src/session/remember-worker.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAE7D,IAAI,CAAC;IACH,MAAM,OAAO,GAAG,CAAC;SACd,MAAM,CAAC;QACN,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;QAC5C,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAClC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;QACpB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;QAClB,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC;QACnD,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE;KAC/C,CAAC;SACD,MAAM,EAAE;SACR,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAG,MAAM,iBAAiB,EAAE,CAAC;IACvC,IAAI,IAAI,EAAE,CAAC;QACT,MAAM,UAAU,GAAG,MAAM,IAAI,QAAQ,EAAE,CAAC,aAAa,EAAE,CAAC;QACxD,IAAI,UAAU,EAAE,CAAC;YACf,MAAM,MAAM,GAAG,EAAE,GAAG,aAAa,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;YAC/D,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,EAAE,SAAS,EAAE,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;YAC5F,kCAAkC;YAClC,IAAI,MAAM,CAAC,gBAAgB,KAAK,OAAO,CAAC,eAAe,EAAE,CAAC;gBACxD,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,CAAC;gBAC/D,MAAM,OAAO,GAAG,MAAM,IAAI,eAAe,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;gBAC9E,IAAI,OAAO,CAAC,OAAO,CAAC,SAAS,KAAK,OAAO,CAAC,SAAS,EAAE,CAAC;oBACpD,MAAM,QAAQ,GACZ,CAAC,OAAO,CAAC,gBAAgB,IAAI,CAAC,MAAM,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,gBAAgB,EAAE,SAAS,CAAC,CAAC,CAAC;oBACnG,IAAI,QAAQ;wBAAE,MAAM,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;gBAC/E,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAAC,MAAM,CAAC;IACP,kCAAkC;AACpC,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** 后台保存辅助项目绑定,不占用业务命令的生命周期。@author xiuyu.yi */
|
|
2
|
+
import { spawn } from 'node:child_process';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
export function scheduleRemember(request) {
|
|
5
|
+
try {
|
|
6
|
+
const child = spawn(process.execPath, [fileURLToPath(new URL('./remember-worker.js', import.meta.url)), JSON.stringify(request)], { detached: true, stdio: 'ignore', windowsHide: true });
|
|
7
|
+
child.once('error', () => undefined);
|
|
8
|
+
child.unref();
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
// 宿主不允许后台进程时放弃辅助保存,不改变业务结果,也不绕过权限。
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=remember.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remember.js","sourceRoot":"","sources":["../../src/session/remember.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAWzC,MAAM,UAAU,gBAAgB,CAAC,OAAwB;IACvD,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,KAAK,CACjB,OAAO,CAAC,QAAQ,EAChB,CAAC,aAAa,CAAC,IAAI,GAAG,CAAC,sBAAsB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,EAC1F,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,CACvD,CAAC;QACF,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACrC,KAAK,CAAC,KAAK,EAAE,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,mCAAmC;IACrC,CAAC;AACH,CAAC"}
|