lark-remote 0.4.4 → 0.4.5
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/CHANGELOG.md +10 -0
- package/dist/binder.d.ts +11 -10
- package/dist/binder.js +17 -16
- package/dist/bridge/inbound-media.d.ts +1 -27
- package/dist/bridge/inbound-media.js +13 -14
- package/dist/bridge/index.d.ts +49 -49
- package/dist/bridge/index.js +99 -92
- package/dist/bridge/queue-manager.d.ts +33 -26
- package/dist/bridge/queue-manager.js +117 -117
- package/dist/card/bash-renderer.js +4 -4
- package/dist/card/card-shared.d.ts +1 -1
- package/dist/card/card-shared.js +2 -2
- package/dist/card/run-renderer.js +8 -8
- package/dist/cli.js +5 -6
- package/dist/clone.d.ts +1 -6
- package/dist/clone.js +4 -4
- package/dist/common/clamp.d.ts +2 -0
- package/dist/common/clamp.js +5 -0
- package/dist/common/fs.d.ts +4 -3
- package/dist/common/fs.js +5 -4
- package/dist/config/dir.d.ts +4 -5
- package/dist/config/dir.js +7 -8
- package/dist/config/wizard.js +2 -2
- package/dist/connector/index.d.ts +0 -2
- package/dist/connector/index.js +5 -5
- package/dist/inbound/receipt.d.ts +1 -3
- package/dist/inbound/receipt.js +2 -2
- package/dist/inbound/turn-assembler.d.ts +1 -3
- package/dist/inbound/turn-assembler.js +2 -2
- package/dist/index.js +30 -22
- package/dist/instance-lock.js +4 -4
- package/dist/persistence/atomic-write.js +3 -3
- package/dist/platform/agent-stopper.d.ts +1 -1
- package/dist/platform/terminator-posix.js +5 -5
- package/dist/platform/terminator-win32.js +1 -1
- package/dist/router/card-helpers.d.ts +1 -3
- package/dist/router/card-helpers.js +2 -2
- package/dist/router/config/codex.js +1 -1
- package/dist/router/config/common/model-patch.d.ts +1 -2
- package/dist/router/config/common/model-patch.js +1 -2
- package/dist/router/config/opencode.js +1 -1
- package/dist/router/config/pi.js +1 -1
- package/dist/router/index.d.ts +22 -22
- package/dist/router/index.js +71 -52
- package/dist/router/order-exec-dispatch.d.ts +3 -10
- package/dist/router/order-exec-dispatch.js +3 -3
- package/dist/router/{utils.d.ts → usage-format.d.ts} +2 -4
- package/dist/router/{utils.js → usage-format.js} +3 -8
- package/dist/runner/claude/runner.d.ts +1 -1
- package/dist/runner/claude/runner.js +1 -2
- package/dist/runner/claude/session.d.ts +2 -4
- package/dist/runner/claude/session.js +7 -9
- package/dist/runner/common/acp/{protocol-helpers.d.ts → acp-approval.d.ts} +2 -8
- package/dist/runner/common/acp/{protocol-helpers.js → acp-approval.js} +4 -3
- package/dist/runner/common/acp/base-acp-runner.d.ts +1 -1
- package/dist/runner/common/acp/base-acp-runner.js +1 -1
- package/dist/runner/common/connection-based-runner.d.ts +4 -4
- package/dist/runner/common/connection-based-runner.js +3 -3
- package/dist/runner/common/jsonrpc/connection-manager.d.ts +12 -12
- package/dist/runner/common/jsonrpc/connection-manager.js +36 -36
- package/dist/runner/common/{usage.d.ts → result-usage.d.ts} +1 -1
- package/dist/runner/common/{usage.js → result-usage.js} +2 -2
- package/dist/runner/common/spawning-runner.d.ts +2 -2
- package/dist/runner/common/spawning-runner.js +8 -8
- package/dist/runner/common/{runner-utils.d.ts → synthetic-events.d.ts} +4 -4
- package/dist/runner/common/{runner-utils.js → synthetic-events.js} +5 -5
- package/dist/runner/dsh/client.d.ts +1 -1
- package/dist/runner/dsh/client.js +1 -1
- package/dist/runner/dsh/runner.js +1 -1
- package/dist/runner/kimi/acp/runner.d.ts +1 -1
- package/dist/runner/kimi/acp/runner.js +1 -1
- package/dist/runner/kimi/acp/translator.js +1 -1
- package/dist/runner/opencode/acp/runner.d.ts +2 -2
- package/dist/runner/opencode/acp/runner.js +1 -1
- package/dist/runner/opencode/acp/translator.js +1 -1
- package/dist/runner/pi/rpc/runner.d.ts +1 -1
- package/dist/runner/pi/rpc/translator.d.ts +0 -1
- package/dist/runner/pi/rpc/translator.js +0 -2
- package/dist/runner/registry.d.ts +3 -3
- package/dist/runner/registry.js +3 -3
- package/dist/session/claude/session-index.d.ts +1 -1
- package/dist/session/claude/session-index.js +1 -1
- package/dist/session/claude/session-reader.d.ts +1 -1
- package/dist/session/claude/session-reader.js +1 -1
- package/dist/session/codex/rollout-reader.js +2 -2
- package/dist/session/dsh/sessions.d.ts +1 -1
- package/dist/session/dsh/sessions.js +1 -1
- package/dist/session/kimi/sessions.d.ts +0 -4
- package/dist/session/kimi/sessions.js +2 -8
- package/dist/session/opencode/sessions.js +3 -3
- package/dist/session/registry.d.ts +1 -1
- package/dist/session/registry.js +1 -1
- package/dist/session/session-store.d.ts +2 -3
- package/dist/session/session-store.js +2 -4
- package/dist/update/index.d.ts +1 -1
- package/dist/update/index.js +1 -1
- package/dist/update/version-check.d.ts +5 -3
- package/dist/update/version-check.js +10 -8
- package/dist/workspace/index.d.ts +4 -4
- package/dist/workspace/index.js +5 -5
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { AgentKind, Runner } from './index.js';
|
|
2
2
|
/**
|
|
3
3
|
* Registry of agent factories, keyed by `AgentKind`. `index.ts` registers one
|
|
4
|
-
* factory per available agent at startup; `Bridge.getRunner(
|
|
4
|
+
* factory per available agent at startup; `Bridge.getRunner(cwd)` looks
|
|
5
5
|
* up `config.defaultAgent` here to pick the concrete runner.
|
|
6
6
|
*
|
|
7
7
|
* Singleton caching: the factory MAY cache its instance internally. All
|
|
@@ -17,7 +17,7 @@ export declare class AgentRegistry {
|
|
|
17
17
|
private readonly displayNames;
|
|
18
18
|
/** Container for runtime config updates (pi provider dynamic reload). */
|
|
19
19
|
private configContainer?;
|
|
20
|
-
register(kind: AgentKind, factory: (
|
|
20
|
+
register(kind: AgentKind, factory: (cwd: string) => Runner): void;
|
|
21
21
|
/**
|
|
22
22
|
* 注册 agent 的显示名。应在 register(kind, factory) 后调用。
|
|
23
23
|
* 用于 agentDisplayName 等全局查询,实现单点真相。
|
|
@@ -50,5 +50,5 @@ export declare class AgentRegistry {
|
|
|
50
50
|
getConfigContainer(): {
|
|
51
51
|
current: unknown;
|
|
52
52
|
} | undefined;
|
|
53
|
-
get(kind: AgentKind,
|
|
53
|
+
get(kind: AgentKind, cwd: string): Runner;
|
|
54
54
|
}
|
package/dist/runner/registry.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
let globalRegistry;
|
|
6
6
|
/**
|
|
7
7
|
* Registry of agent factories, keyed by `AgentKind`. `index.ts` registers one
|
|
8
|
-
* factory per available agent at startup; `Bridge.getRunner(
|
|
8
|
+
* factory per available agent at startup; `Bridge.getRunner(cwd)` looks
|
|
9
9
|
* up `config.defaultAgent` here to pick the concrete runner.
|
|
10
10
|
*
|
|
11
11
|
* Singleton caching: the factory MAY cache its instance internally. All
|
|
@@ -64,12 +64,12 @@ export class AgentRegistry {
|
|
|
64
64
|
getConfigContainer() {
|
|
65
65
|
return this.configContainer;
|
|
66
66
|
}
|
|
67
|
-
get(kind,
|
|
67
|
+
get(kind, cwd) {
|
|
68
68
|
const factory = this.factories.get(kind);
|
|
69
69
|
if (!factory) {
|
|
70
70
|
throw new Error(`agent not registered: ${kind}`);
|
|
71
71
|
}
|
|
72
|
-
return factory(
|
|
72
|
+
return factory(cwd);
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
//# sourceMappingURL=registry.js.map
|
|
@@ -36,7 +36,7 @@ export interface ParsedSession {
|
|
|
36
36
|
/**
|
|
37
37
|
* Unified parser: single streaming scan of a JSONL file producing both
|
|
38
38
|
* the complete set of cwd values AND the first real user message summary.
|
|
39
|
-
* Replaces the split readCwdFromJsonl (first-cwd) +
|
|
39
|
+
* Replaces the split readCwdFromJsonl (first-cwd) + fileContainsCwd (any-cwd).
|
|
40
40
|
*/
|
|
41
41
|
export declare function parseSessionJsonl(filePath: string): ParsedSession;
|
|
42
42
|
/**
|
|
@@ -42,7 +42,7 @@ export function extractText(content) {
|
|
|
42
42
|
/**
|
|
43
43
|
* Unified parser: single streaming scan of a JSONL file producing both
|
|
44
44
|
* the complete set of cwd values AND the first real user message summary.
|
|
45
|
-
* Replaces the split readCwdFromJsonl (first-cwd) +
|
|
45
|
+
* Replaces the split readCwdFromJsonl (first-cwd) + fileContainsCwd (any-cwd).
|
|
46
46
|
*/
|
|
47
47
|
export function parseSessionJsonl(filePath) {
|
|
48
48
|
const cwdSet = new Set();
|
|
@@ -8,7 +8,7 @@ import type { AgentSession, AgentSessionReader, SessionContent } from '../../run
|
|
|
8
8
|
* injects a reader configured with its test `projectsDir`; production code
|
|
9
9
|
* uses the default (`~/.claude/projects/`).
|
|
10
10
|
*
|
|
11
|
-
* All methods are thin wrappers around `
|
|
11
|
+
* All methods are thin wrappers around `sessions.ts` exports — zero
|
|
12
12
|
* behavior change. Router and bridge reach session data exclusively through
|
|
13
13
|
* this reader (via `SessionReaderRegistry`); the underlying functions remain
|
|
14
14
|
* exported for tests and the reader itself.
|
|
@@ -9,7 +9,7 @@ import { listClaudeSessions, getNewestSession, readSessionContent, isClaudeSessi
|
|
|
9
9
|
* injects a reader configured with its test `projectsDir`; production code
|
|
10
10
|
* uses the default (`~/.claude/projects/`).
|
|
11
11
|
*
|
|
12
|
-
* All methods are thin wrappers around `
|
|
12
|
+
* All methods are thin wrappers around `sessions.ts` exports — zero
|
|
13
13
|
* behavior change. Router and bridge reach session data exclusively through
|
|
14
14
|
* this reader (via `SessionReaderRegistry`); the underlying functions remain
|
|
15
15
|
* exported for tests and the reader itself.
|
|
@@ -399,9 +399,9 @@ export function readCodexSessionContent(sessionId, opts = {}) {
|
|
|
399
399
|
}
|
|
400
400
|
// Cwd guard: when a cwd is provided, the session's working directory must
|
|
401
401
|
// match. Without this, /resume <id> finds sessions by global ID lookup and
|
|
402
|
-
// allows resuming a session from
|
|
402
|
+
// allows resuming a session from cwd B while the user is in cwd A.
|
|
403
403
|
// Codex has no relocation (no EnterWorktree equivalent), so a simple equality
|
|
404
|
-
// check suffices — unlike claude which needs
|
|
404
|
+
// check suffices — unlike claude which needs fileContainsCwd to handle
|
|
405
405
|
// relocated sessions with multiple cwd values.
|
|
406
406
|
if (opts.cwd && !samePath(entry.cwd, opts.cwd)) {
|
|
407
407
|
return { events: [] };
|
|
@@ -36,7 +36,7 @@ export declare class DshSessionReader implements AgentSessionReader {
|
|
|
36
36
|
total: number;
|
|
37
37
|
};
|
|
38
38
|
getNewestSession(cwd: string): AgentSession | null;
|
|
39
|
-
readSessionContent(sessionId: string,
|
|
39
|
+
readSessionContent(sessionId: string, _cwd: string, opts?: {
|
|
40
40
|
maxEvents?: number;
|
|
41
41
|
}): SessionContent;
|
|
42
42
|
isSessionActive(sessionId: string, cwd: string): boolean;
|
|
@@ -102,7 +102,7 @@ export class DshSessionReader {
|
|
|
102
102
|
getNewestSession(cwd) {
|
|
103
103
|
return this.listSessions(cwd, { limit: 1 }).sessions[0] ?? null;
|
|
104
104
|
}
|
|
105
|
-
readSessionContent(sessionId,
|
|
105
|
+
readSessionContent(sessionId, _cwd, opts) {
|
|
106
106
|
try {
|
|
107
107
|
const value = this.unary('session.history', {
|
|
108
108
|
sessionId,
|
|
@@ -66,10 +66,6 @@ export declare class KimiSessionReader implements AgentSessionReader {
|
|
|
66
66
|
* Find a single index entry by sessionId, or undefined if not found.
|
|
67
67
|
*/
|
|
68
68
|
private findSessionIndexEntry;
|
|
69
|
-
/**
|
|
70
|
-
* Convenience wrapper: find sessionDir from index, or null if not found.
|
|
71
|
-
*/
|
|
72
|
-
private findSessionDirFromIndex;
|
|
73
69
|
/**
|
|
74
70
|
* Extract the last turn.prompt text from a wire.jsonl file.
|
|
75
71
|
* Used as a fallback summary source when state.json has no title/lastPrompt
|
|
@@ -163,12 +163,6 @@ export class KimiSessionReader {
|
|
|
163
163
|
findSessionIndexEntry(sessionId) {
|
|
164
164
|
return this.scanSessionIndex().find((e) => e.sessionId === sessionId);
|
|
165
165
|
}
|
|
166
|
-
/**
|
|
167
|
-
* Convenience wrapper: find sessionDir from index, or null if not found.
|
|
168
|
-
*/
|
|
169
|
-
findSessionDirFromIndex(sessionId) {
|
|
170
|
-
return this.findSessionIndexEntry(sessionId)?.sessionDir ?? null;
|
|
171
|
-
}
|
|
172
166
|
/**
|
|
173
167
|
* Extract the last turn.prompt text from a wire.jsonl file.
|
|
174
168
|
* Used as a fallback summary source when state.json has no title/lastPrompt
|
|
@@ -596,7 +590,7 @@ export class KimiSessionReader {
|
|
|
596
590
|
// Fallback: when state.json is missing, unparseable, or has no workDir/cwd,
|
|
597
591
|
// use the workDir from the session index entry as a secondary guard.
|
|
598
592
|
// This prevents /resume <id> from accessing a session belonging to a
|
|
599
|
-
// different
|
|
593
|
+
// different cwd when state.json is unavailable.
|
|
600
594
|
if (!cwdGuardPassed) {
|
|
601
595
|
const indexWorkDir = indexEntry?.workDir;
|
|
602
596
|
if (indexWorkDir && indexWorkDir !== realCwd) {
|
|
@@ -604,7 +598,7 @@ export class KimiSessionReader {
|
|
|
604
598
|
}
|
|
605
599
|
// v2 sessions have empty index workDir (v1-only field) and may lack
|
|
606
600
|
// state.json cwd. When no cwd source can verify the session belongs to
|
|
607
|
-
// the requested
|
|
601
|
+
// the requested cwd, fail-closed to prevent cross-workspace access
|
|
608
602
|
// (aligned with claude's fail-closed cwd guard).
|
|
609
603
|
if (!indexWorkDir) {
|
|
610
604
|
getLogger().warn(`[kimi-session-reader] no cwd source (state.json + index) for session ${sessionId}, rejecting (fail-closed)`);
|
|
@@ -15,16 +15,16 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import { spawnProcessSync } from '../../platform/spawn.js';
|
|
17
17
|
import fs from 'node:fs';
|
|
18
|
-
import {
|
|
18
|
+
import { bestEffortUnlink } from '../../common/fs.js';
|
|
19
19
|
import os from 'node:os';
|
|
20
20
|
import path from 'node:path';
|
|
21
21
|
import { truncateUtf8, TOOL_RESULT_MAX_BYTES } from '../../common/truncate.js';
|
|
22
|
-
import { getLogger } from '../../logger/index.js';
|
|
23
22
|
import { isStale } from '../common/constants.js';
|
|
24
23
|
import { samePath } from '../../platform/path.js';
|
|
25
24
|
import { paginate, capEvents } from '../common/pagination.js';
|
|
26
25
|
import { sortByRecencyDesc } from '../common/recency.js';
|
|
27
26
|
import { TtlCache } from '../../common/ttl-cache.js';
|
|
27
|
+
import { getLogger } from '../../logger/index.js';
|
|
28
28
|
export class OpencodeSessionReader {
|
|
29
29
|
binary;
|
|
30
30
|
cacheTtlMs;
|
|
@@ -401,7 +401,7 @@ export class OpencodeSessionReader {
|
|
|
401
401
|
}
|
|
402
402
|
catch { }
|
|
403
403
|
}
|
|
404
|
-
|
|
404
|
+
bestEffortUnlink(tmp);
|
|
405
405
|
}
|
|
406
406
|
}
|
|
407
407
|
}
|
|
@@ -3,7 +3,7 @@ import type { AgentKind, AgentSessionReader } from '../runner/index.js';
|
|
|
3
3
|
* Registry of `AgentSessionReader` instances, keyed by `AgentKind`. Mirrors
|
|
4
4
|
* `AgentRegistry` but for session-history reads. `index.ts` registers one
|
|
5
5
|
* reader per available agent at startup; router/bridge look up readers here
|
|
6
|
-
* instead of importing `
|
|
6
|
+
* instead of importing `sessions.ts` directly.
|
|
7
7
|
*/
|
|
8
8
|
export declare class SessionReaderRegistry {
|
|
9
9
|
private readonly readers;
|
package/dist/session/registry.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Registry of `AgentSessionReader` instances, keyed by `AgentKind`. Mirrors
|
|
3
3
|
* `AgentRegistry` but for session-history reads. `index.ts` registers one
|
|
4
4
|
* reader per available agent at startup; router/bridge look up readers here
|
|
5
|
-
* instead of importing `
|
|
5
|
+
* instead of importing `sessions.ts` directly.
|
|
6
6
|
*/
|
|
7
7
|
export class SessionReaderRegistry {
|
|
8
8
|
readers = new Map();
|
|
@@ -13,7 +13,7 @@ interface SessionEntry {
|
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
15
|
* Per-user session store. Persists cwd + per-agent sessions to disk so that
|
|
16
|
-
* the last
|
|
16
|
+
* the last cwd AND the last-used sessionId per agent are restored after
|
|
17
17
|
* a lark-remote restart.
|
|
18
18
|
*
|
|
19
19
|
* Persistence strategy:
|
|
@@ -29,7 +29,6 @@ interface SessionEntry {
|
|
|
29
29
|
export declare class SessionStore {
|
|
30
30
|
private sessions;
|
|
31
31
|
private readonly persistPath?;
|
|
32
|
-
private readonly defaultAgent?;
|
|
33
32
|
/**
|
|
34
33
|
* 进程内会话代际(2026-08-09 /new 被在途 run init 写回撤销事故):
|
|
35
34
|
* 每次「用户意图移动 session 指针」+1。system.init 写回通道不 bump。
|
|
@@ -47,7 +46,7 @@ export declare class SessionStore {
|
|
|
47
46
|
bumpSessionEpoch(userId: string, agent: AgentKind): void;
|
|
48
47
|
/** 用户意图移动了全部 agent 的 session 指针(/cd、/ws use 的 setCwd)。 */
|
|
49
48
|
private bumpUserEpoch;
|
|
50
|
-
constructor(persistPath?: string
|
|
49
|
+
constructor(persistPath?: string);
|
|
51
50
|
/** A fresh, empty session entry (default factory). */
|
|
52
51
|
private static emptyEntry;
|
|
53
52
|
/**
|
|
@@ -3,7 +3,7 @@ import { getLogger } from '../logger/index.js';
|
|
|
3
3
|
import { atomicWriteJson } from '../persistence/atomic-write.js';
|
|
4
4
|
/**
|
|
5
5
|
* Per-user session store. Persists cwd + per-agent sessions to disk so that
|
|
6
|
-
* the last
|
|
6
|
+
* the last cwd AND the last-used sessionId per agent are restored after
|
|
7
7
|
* a lark-remote restart.
|
|
8
8
|
*
|
|
9
9
|
* Persistence strategy:
|
|
@@ -19,7 +19,6 @@ import { atomicWriteJson } from '../persistence/atomic-write.js';
|
|
|
19
19
|
export class SessionStore {
|
|
20
20
|
sessions = new Map();
|
|
21
21
|
persistPath;
|
|
22
|
-
defaultAgent;
|
|
23
22
|
/**
|
|
24
23
|
* 进程内会话代际(2026-08-09 /new 被在途 run init 写回撤销事故):
|
|
25
24
|
* 每次「用户意图移动 session 指针」+1。system.init 写回通道不 bump。
|
|
@@ -47,9 +46,8 @@ export class SessionStore {
|
|
|
47
46
|
bumpUserEpoch(userId) {
|
|
48
47
|
this.userEpochs.set(userId, (this.userEpochs.get(userId) ?? 0) + 1);
|
|
49
48
|
}
|
|
50
|
-
constructor(persistPath
|
|
49
|
+
constructor(persistPath) {
|
|
51
50
|
this.persistPath = persistPath;
|
|
52
|
-
this.defaultAgent = defaultAgent;
|
|
53
51
|
if (persistPath)
|
|
54
52
|
this.load();
|
|
55
53
|
}
|
package/dist/update/index.d.ts
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* package installation (detect package manager + global install),
|
|
6
6
|
* and the combined workflow for the /update command and --update CLI flag.
|
|
7
7
|
*/
|
|
8
|
-
export {
|
|
8
|
+
export { compareVersions, checkLatestVersion, formatUpdateHint, type VersionCheckResult, } from './version-check.js';
|
|
9
9
|
export { runInstallLatest, type InstallResult } from './install.js';
|
package/dist/update/index.js
CHANGED
|
@@ -5,6 +5,6 @@
|
|
|
5
5
|
* package installation (detect package manager + global install),
|
|
6
6
|
* and the combined workflow for the /update command and --update CLI flag.
|
|
7
7
|
*/
|
|
8
|
-
export {
|
|
8
|
+
export { compareVersions, checkLatestVersion, formatUpdateHint, } from './version-check.js';
|
|
9
9
|
export { runInstallLatest } from './install.js';
|
|
10
10
|
//# sourceMappingURL=index.js.map
|
|
@@ -12,10 +12,12 @@ export interface VersionCheckResult {
|
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
14
14
|
* Compare two semver strings (major.minor.patch).
|
|
15
|
-
*
|
|
16
|
-
*
|
|
15
|
+
*
|
|
16
|
+
* Returns the sign of `latest - current`: `1` if latest is newer, `-1` if it
|
|
17
|
+
* is older, `0` if equal. Returns `null` if either version is not a valid
|
|
18
|
+
* semver string (callers should treat `null` as "not newer").
|
|
17
19
|
*/
|
|
18
|
-
export declare function
|
|
20
|
+
export declare function compareVersions(current: string, latest: string): -1 | 0 | 1 | null;
|
|
19
21
|
/**
|
|
20
22
|
* Check the latest available version of lark-remote.
|
|
21
23
|
* Uses a local cache file with 1-hour TTL to avoid frequent network requests.
|
|
@@ -10,10 +10,12 @@ export const CACHE_TTL_MS = 60 * 60 * 1000;
|
|
|
10
10
|
const DEFAULT_REGISTRY_URL = 'https://registry.npmjs.org/lark-remote/latest';
|
|
11
11
|
/**
|
|
12
12
|
* Compare two semver strings (major.minor.patch).
|
|
13
|
-
*
|
|
14
|
-
*
|
|
13
|
+
*
|
|
14
|
+
* Returns the sign of `latest - current`: `1` if latest is newer, `-1` if it
|
|
15
|
+
* is older, `0` if equal. Returns `null` if either version is not a valid
|
|
16
|
+
* semver string (callers should treat `null` as "not newer").
|
|
15
17
|
*/
|
|
16
|
-
export function
|
|
18
|
+
export function compareVersions(current, latest) {
|
|
17
19
|
const parse = (v) => {
|
|
18
20
|
// Split core and pre-release suffix; compare the core numerically and treat
|
|
19
21
|
// a release as newer than any pre-release of the same core version.
|
|
@@ -32,14 +34,14 @@ export function isNewer(current, latest) {
|
|
|
32
34
|
return null;
|
|
33
35
|
for (let i = 0; i < 3; i++) {
|
|
34
36
|
if (l.nums[i] > c.nums[i])
|
|
35
|
-
return
|
|
37
|
+
return 1;
|
|
36
38
|
if (l.nums[i] < c.nums[i])
|
|
37
|
-
return
|
|
39
|
+
return -1;
|
|
38
40
|
}
|
|
39
41
|
// Equal core version: a release beats a pre-release of the same version.
|
|
40
42
|
if (c.pre !== l.pre)
|
|
41
|
-
return l.pre === '';
|
|
42
|
-
return
|
|
43
|
+
return l.pre === '' ? 1 : -1;
|
|
44
|
+
return 0;
|
|
43
45
|
}
|
|
44
46
|
/**
|
|
45
47
|
* Fetch the latest version from npm registry.
|
|
@@ -151,7 +153,7 @@ export async function checkLatestVersion(opts) {
|
|
|
151
153
|
* Returns null if no newer version is available.
|
|
152
154
|
*/
|
|
153
155
|
export function formatUpdateHint(current, latest) {
|
|
154
|
-
if (
|
|
156
|
+
if (compareVersions(current, latest) !== 1)
|
|
155
157
|
return null;
|
|
156
158
|
return `📦 有新版本 ${latest} 可用(当前 ${current}),发送 /update 升级`;
|
|
157
159
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
/** Public view of a
|
|
1
|
+
/** Public view of a cwd entry returned by list(). */
|
|
2
2
|
export interface WorkspaceEntry {
|
|
3
3
|
name: string;
|
|
4
4
|
path: string;
|
|
5
5
|
lastUsedAt: number;
|
|
6
6
|
}
|
|
7
7
|
/**
|
|
8
|
-
* Persistent named-alias store for
|
|
8
|
+
* Persistent named-alias store for cwd directories.
|
|
9
9
|
*
|
|
10
10
|
* Atomic write (§9.10): writes a temp file then `fs.rename` so a crash
|
|
11
11
|
* mid-write cannot leave a truncated JSON file. On load, a corrupt file
|
|
@@ -13,7 +13,7 @@ export interface WorkspaceEntry {
|
|
|
13
13
|
*
|
|
14
14
|
* lastUsedAt 语义(2026-08-19 语义对齐):保存(save)与使用(use/touch)
|
|
15
15
|
* 都会把时间戳更新为当前时间。save 内部调用 touch,保证「最近使用」排序
|
|
16
|
-
* 对新保存的
|
|
16
|
+
* 对新保存的 cwd 同样生效(新条目应排在列表最前,而非沉底)。
|
|
17
17
|
* 同一毫秒内连续操作时 touch 会用 max+1 保证严格递增,避免 Date.now 相同
|
|
18
18
|
* 导致最近排序退化为字母序。
|
|
19
19
|
*
|
|
@@ -42,7 +42,7 @@ export declare class WorkspaceStore {
|
|
|
42
42
|
*/
|
|
43
43
|
touch(name: string): void;
|
|
44
44
|
/**
|
|
45
|
-
* List all
|
|
45
|
+
* List all cwd entries in insertion order.
|
|
46
46
|
* Sorting is the caller's responsibility (view concern).
|
|
47
47
|
*/
|
|
48
48
|
list(): WorkspaceEntry[];
|
package/dist/workspace/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { atomicWriteJson } from '../persistence/atomic-write.js';
|
|
|
4
4
|
import { loadJsonFile } from '../persistence/load-json-file.js';
|
|
5
5
|
import { getLogger } from '../logger/index.js';
|
|
6
6
|
/**
|
|
7
|
-
* Persistent named-alias store for
|
|
7
|
+
* Persistent named-alias store for cwd directories.
|
|
8
8
|
*
|
|
9
9
|
* Atomic write (§9.10): writes a temp file then `fs.rename` so a crash
|
|
10
10
|
* mid-write cannot leave a truncated JSON file. On load, a corrupt file
|
|
@@ -12,7 +12,7 @@ import { getLogger } from '../logger/index.js';
|
|
|
12
12
|
*
|
|
13
13
|
* lastUsedAt 语义(2026-08-19 语义对齐):保存(save)与使用(use/touch)
|
|
14
14
|
* 都会把时间戳更新为当前时间。save 内部调用 touch,保证「最近使用」排序
|
|
15
|
-
* 对新保存的
|
|
15
|
+
* 对新保存的 cwd 同样生效(新条目应排在列表最前,而非沉底)。
|
|
16
16
|
* 同一毫秒内连续操作时 touch 会用 max+1 保证严格递增,避免 Date.now 相同
|
|
17
17
|
* 导致最近排序退化为字母序。
|
|
18
18
|
*
|
|
@@ -46,7 +46,7 @@ export class WorkspaceStore {
|
|
|
46
46
|
const lastUsedAt = typeof obj.lastUsedAt === 'number' ? obj.lastUsedAt : 0;
|
|
47
47
|
if (typeof obj.lastUsedAt !== 'number') {
|
|
48
48
|
if (obj.lastUsedAt !== undefined) {
|
|
49
|
-
getLogger().warn(`[
|
|
49
|
+
getLogger().warn(`[cwd] "${k}" has invalid lastUsedAt (${JSON.stringify(obj.lastUsedAt)}), resetting to 0`);
|
|
50
50
|
}
|
|
51
51
|
needsMigration = true;
|
|
52
52
|
}
|
|
@@ -66,7 +66,7 @@ export class WorkspaceStore {
|
|
|
66
66
|
atomicWriteJson(this.filePath, obj);
|
|
67
67
|
}
|
|
68
68
|
save(name, dirPath) {
|
|
69
|
-
// 保存即视为使用(语义对齐):新建/覆盖的
|
|
69
|
+
// 保存即视为使用(语义对齐):新建/覆盖的 cwd 都应拿到当前
|
|
70
70
|
// lastUsedAt,而不是 0,否则「最近使用」排序下新条目会沉底。
|
|
71
71
|
// touch() 负责统一写入时间戳并 persist,消除 save 写 0 / use 写 now 的不对称。
|
|
72
72
|
this.data.set(name, { path: dirPath, lastUsedAt: 0 });
|
|
@@ -111,7 +111,7 @@ export class WorkspaceStore {
|
|
|
111
111
|
this.persist();
|
|
112
112
|
}
|
|
113
113
|
/**
|
|
114
|
-
* List all
|
|
114
|
+
* List all cwd entries in insertion order.
|
|
115
115
|
* Sorting is the caller's responsibility (view concern).
|
|
116
116
|
*/
|
|
117
117
|
list() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lark-remote",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.5",
|
|
4
4
|
"description": "Feishu (Lark) private-chat bridge to local coding agents — Claude Code / Codex / opencode / pi / kimi, with live-streaming CardKit 2.0 cards",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|