@getpaseo/server 0.1.96 → 0.1.97-beta.2
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/dist/server/{utils/executable.d.ts → executable-resolution/executable-resolution.d.ts} +2 -2
- package/dist/server/{utils/executable.js → executable-resolution/executable-resolution.js} +16 -14
- package/dist/server/executable-resolution/windows.d.ts +18 -0
- package/dist/server/executable-resolution/windows.js +62 -0
- package/dist/server/server/agent/agent-loading.js +4 -1
- package/dist/server/server/agent/agent-manager.d.ts +10 -2
- package/dist/server/server/agent/agent-manager.js +34 -46
- package/dist/server/server/agent/agent-projections.js +3 -0
- package/dist/server/server/agent/agent-prompt.js +19 -1
- package/dist/server/server/agent/agent-response-loop.js +2 -4
- package/dist/server/server/agent/agent-storage.d.ts +18 -19
- package/dist/server/server/agent/agent-storage.js +6 -23
- package/dist/server/server/agent/create-agent/create.d.ts +2 -12
- package/dist/server/server/agent/create-agent/create.js +28 -30
- package/dist/server/server/agent/create-agent-lifecycle-dispatch.d.ts +4 -2
- package/dist/server/server/agent/create-agent-lifecycle-dispatch.js +31 -22
- package/dist/server/server/agent/create-agent-title.d.ts +2 -0
- package/dist/server/server/agent/create-agent-title.js +5 -0
- package/dist/server/server/agent/import-sessions.d.ts +1 -10
- package/dist/server/server/agent/import-sessions.js +1 -53
- package/dist/server/server/agent/lifecycle-command.js +5 -4
- package/dist/server/server/agent/mcp-server.d.ts +8 -5
- package/dist/server/server/agent/mcp-server.js +41 -14
- package/dist/server/server/agent/mcp-shared.d.ts +6 -3
- package/dist/server/server/agent/mcp-shared.js +3 -0
- package/dist/server/server/agent/provider-launch-config.js +1 -1
- package/dist/server/server/agent/providers/acp-agent.d.ts +5 -0
- package/dist/server/server/agent/providers/acp-agent.js +31 -26
- package/dist/server/server/agent/providers/claude/agent.js +45 -6
- package/dist/server/server/agent/providers/codex-app-server-agent.js +1 -1
- package/dist/server/server/agent/providers/copilot-acp-agent.js +1 -0
- package/dist/server/server/agent/providers/cursor-acp-agent.d.ts +0 -7
- package/dist/server/server/agent/providers/cursor-acp-agent.js +0 -78
- package/dist/server/server/agent/providers/mock-load-test-agent.d.ts +2 -0
- package/dist/server/server/agent/providers/mock-load-test-agent.js +73 -1
- package/dist/server/server/agent/providers/opencode/server-manager.js +1 -1
- package/dist/server/server/agent/structured-generation-providers.js +45 -1
- package/dist/server/server/agent-attention-policy.d.ts +12 -3
- package/dist/server/server/agent-attention-policy.js +15 -3
- package/dist/server/server/auto-archive-on-merge/archive-if-safe.d.ts +7 -6
- package/dist/server/server/auto-archive-on-merge/archive-if-safe.js +21 -16
- package/dist/server/server/bootstrap.d.ts +3 -0
- package/dist/server/server/bootstrap.js +125 -64
- package/dist/server/server/config.js +1 -0
- package/dist/server/server/daemon-config-store.js +1 -0
- package/dist/server/server/exports.d.ts +1 -1
- package/dist/server/server/exports.js +1 -1
- package/dist/server/server/loop-service.d.ts +24 -24
- package/dist/server/server/migrations/backfill-workspace-id.migration.d.ts +9 -0
- package/dist/server/server/migrations/backfill-workspace-id.migration.js +60 -0
- package/dist/server/server/paseo-worktree-service.d.ts +9 -0
- package/dist/server/server/paseo-worktree-service.js +74 -12
- package/dist/server/server/path-utils.d.ts +1 -0
- package/dist/server/server/path-utils.js +6 -1
- package/dist/server/server/persisted-config.d.ts +7 -0
- package/dist/server/server/persisted-config.js +1 -0
- package/dist/server/server/persistence-hooks.d.ts +1 -0
- package/dist/server/server/persistence-hooks.js +13 -5
- package/dist/server/server/resolve-workspace-id-for-path.d.ts +3 -0
- package/dist/server/server/resolve-workspace-id-for-path.js +41 -0
- package/dist/server/server/script-proxy.d.ts +1 -1
- package/dist/server/server/script-proxy.js +1 -1
- package/dist/server/server/service-proxy.js +1 -1
- package/dist/server/server/session.d.ts +33 -6
- package/dist/server/server/session.js +691 -202
- package/dist/server/server/websocket-server.d.ts +5 -0
- package/dist/server/server/websocket-server.js +137 -3
- package/dist/server/server/workspace-archive-service.d.ts +60 -3
- package/dist/server/server/workspace-archive-service.js +217 -4
- package/dist/server/server/workspace-directory.d.ts +20 -2
- package/dist/server/server/workspace-directory.js +148 -70
- package/dist/server/server/workspace-git-service.js +21 -21
- package/dist/server/server/workspace-reconciliation-service.d.ts +1 -1
- package/dist/server/server/workspace-reconciliation-service.js +21 -22
- package/dist/server/server/workspace-registry-bootstrap.js +23 -10
- package/dist/server/server/workspace-registry-model.d.ts +3 -3
- package/dist/server/server/workspace-registry-model.js +9 -10
- package/dist/server/server/workspace-registry.d.ts +17 -4
- package/dist/server/server/workspace-registry.js +27 -0
- package/dist/server/server/worktree/commands.d.ts +7 -5
- package/dist/server/server/worktree/commands.js +38 -18
- package/dist/server/server/worktree-bootstrap.d.ts +1 -0
- package/dist/server/server/worktree-bootstrap.js +4 -1
- package/dist/server/server/worktree-branch-name-generator.d.ts +5 -1
- package/dist/server/server/worktree-branch-name-generator.js +29 -7
- package/dist/server/server/worktree-session.d.ts +4 -5
- package/dist/server/server/worktree-session.js +9 -3
- package/dist/server/services/github-service.js +1 -1
- package/dist/server/terminal/activity/terminal-activity-tracker.d.ts +20 -0
- package/dist/server/terminal/activity/terminal-activity-tracker.js +59 -0
- package/dist/server/terminal/agent-hooks/agent-hook-installer.d.ts +62 -0
- package/dist/server/terminal/agent-hooks/agent-hook-installer.js +117 -0
- package/dist/server/terminal/agent-hooks/claude/claude-settings.d.ts +7 -0
- package/dist/server/terminal/agent-hooks/claude/claude-settings.js +88 -0
- package/dist/server/terminal/agent-hooks/claude/claude.d.ts +4 -0
- package/dist/server/terminal/agent-hooks/claude/claude.js +47 -0
- package/dist/server/terminal/agent-hooks/codex/codex-settings.d.ts +7 -0
- package/dist/server/terminal/agent-hooks/codex/codex-settings.js +99 -0
- package/dist/server/terminal/agent-hooks/codex/codex.d.ts +4 -0
- package/dist/server/terminal/agent-hooks/codex/codex.js +30 -0
- package/dist/server/terminal/agent-hooks/opencode/opencode-plugin.d.ts +4 -0
- package/dist/server/terminal/agent-hooks/opencode/opencode-plugin.js +46 -0
- package/dist/server/terminal/agent-hooks/opencode/opencode.d.ts +3 -0
- package/dist/server/terminal/agent-hooks/opencode/opencode.js +23 -0
- package/dist/server/terminal/agent-hooks/provider-registry.d.ts +24 -0
- package/dist/server/terminal/agent-hooks/provider-registry.js +36 -0
- package/dist/server/terminal/agent-hooks/terminal-agent-hook-setting.d.ts +10 -0
- package/dist/server/terminal/agent-hooks/terminal-agent-hook-setting.js +26 -0
- package/dist/server/terminal/terminal-manager-factory.d.ts +4 -1
- package/dist/server/terminal/terminal-manager-factory.js +2 -2
- package/dist/server/terminal/terminal-manager.d.ts +33 -2
- package/dist/server/terminal/terminal-manager.js +144 -18
- package/dist/server/terminal/terminal-output-coalescer.d.ts +4 -0
- package/dist/server/terminal/terminal-output-coalescer.js +18 -0
- package/dist/server/terminal/terminal-restore.d.ts +1 -0
- package/dist/server/terminal/terminal-restore.js +6 -0
- package/dist/server/terminal/terminal-session-controller.d.ts +4 -2
- package/dist/server/terminal/terminal-session-controller.js +65 -24
- package/dist/server/terminal/terminal-worker-process.js +146 -63
- package/dist/server/terminal/terminal-worker-protocol.d.ts +19 -14
- package/dist/server/terminal/terminal.d.ts +42 -0
- package/dist/server/terminal/terminal.js +235 -16
- package/dist/server/terminal/worker-terminal-manager.d.ts +1 -0
- package/dist/server/terminal/worker-terminal-manager.js +220 -36
- package/dist/server/utils/build-metadata-prompt.d.ts +8 -3
- package/dist/server/utils/build-metadata-prompt.js +10 -9
- package/dist/server/utils/github-remote.js +1 -1
- package/dist/server/utils/tree-kill.d.ts +2 -2
- package/dist/src/{utils/executable.js → executable-resolution/executable-resolution.js} +16 -14
- package/dist/src/executable-resolution/windows.js +62 -0
- package/dist/src/server/agent/provider-launch-config.js +1 -1
- package/dist/src/server/persisted-config.js +1 -0
- package/package.json +10 -5
- package/dist/server/server/agent/agent-metadata-generator.d.ts +0 -36
- package/dist/server/server/agent/agent-metadata-generator.js +0 -112
- package/dist/server/server/paseo-worktree-archive-service.d.ts +0 -41
- package/dist/server/server/paseo-worktree-archive-service.js +0 -144
- package/dist/server/utils/wrap-user-instructions.d.ts +0 -2
- package/dist/server/utils/wrap-user-instructions.js +0 -13
package/dist/server/{utils/executable.d.ts → executable-resolution/executable-resolution.d.ts}
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
|
-
export { quoteWindowsArgument, quoteWindowsCommand } from "
|
|
2
|
+
export { quoteWindowsArgument, quoteWindowsCommand } from "../utils/windows-command.js";
|
|
3
3
|
export declare function probeExecutable(executablePath: string, timeoutMs?: number): Promise<boolean>;
|
|
4
4
|
/**
|
|
5
5
|
* Check a literal executable path. PATH search is handled by findExecutable().
|
|
@@ -7,4 +7,4 @@ export declare function probeExecutable(executablePath: string, timeoutMs?: numb
|
|
|
7
7
|
export declare function executableExists(executablePath: string, exists?: typeof existsSync): string | null;
|
|
8
8
|
export declare function findExecutable(name: string, probeTimeoutMs?: number): Promise<string | null>;
|
|
9
9
|
export declare function isCommandAvailable(command: string): Promise<boolean>;
|
|
10
|
-
//# sourceMappingURL=executable.d.ts.map
|
|
10
|
+
//# sourceMappingURL=executable-resolution.d.ts.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
import { existsSync } from "node:fs";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
export { quoteWindowsArgument, quoteWindowsCommand } from "
|
|
3
|
+
import { execCommand } from "../utils/spawn.js";
|
|
4
|
+
import { isWindowsCommandScript } from "../utils/windows-command.js";
|
|
5
|
+
import { windowsExecutableResolution } from "./windows.js";
|
|
6
|
+
export { quoteWindowsArgument, quoteWindowsCommand } from "../utils/windows-command.js";
|
|
7
7
|
const require = createRequire(import.meta.url);
|
|
8
8
|
const which = require("which");
|
|
9
9
|
const PROBE_TIMEOUT_MS = 2000;
|
|
@@ -83,22 +83,24 @@ function classifyProbeError(error) {
|
|
|
83
83
|
* Check a literal executable path. PATH search is handled by findExecutable().
|
|
84
84
|
*/
|
|
85
85
|
export function executableExists(executablePath, exists = existsSync) {
|
|
86
|
-
if (
|
|
87
|
-
return executablePath;
|
|
88
|
-
if (process.platform === "win32" && !extname(executablePath)) {
|
|
89
|
-
for (const ext of [".exe", ".cmd"]) {
|
|
90
|
-
const candidate = executablePath + ext;
|
|
91
|
-
if (exists(candidate))
|
|
92
|
-
return candidate;
|
|
93
|
-
}
|
|
86
|
+
if (process.platform === "win32") {
|
|
87
|
+
return windowsExecutableResolution.exists(executablePath, { exists });
|
|
94
88
|
}
|
|
95
|
-
return null;
|
|
89
|
+
return exists(executablePath) ? executablePath : null;
|
|
96
90
|
}
|
|
97
91
|
export async function findExecutable(name, probeTimeoutMs = PROBE_TIMEOUT_MS) {
|
|
98
92
|
const trimmed = name.trim();
|
|
99
93
|
if (!trimmed) {
|
|
100
94
|
return null;
|
|
101
95
|
}
|
|
96
|
+
if (process.platform === "win32") {
|
|
97
|
+
return windowsExecutableResolution.find(trimmed, {
|
|
98
|
+
enumeratePathCandidates: enumerateCandidates,
|
|
99
|
+
probeExecutable,
|
|
100
|
+
exists: existsSync,
|
|
101
|
+
probeTimeoutMs,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
102
104
|
if (hasPathSeparator(trimmed)) {
|
|
103
105
|
return (await probeExecutable(trimmed, probeTimeoutMs)) ? trimmed : null;
|
|
104
106
|
}
|
|
@@ -113,4 +115,4 @@ export async function findExecutable(name, probeTimeoutMs = PROBE_TIMEOUT_MS) {
|
|
|
113
115
|
export async function isCommandAvailable(command) {
|
|
114
116
|
return (await findExecutable(command)) !== null;
|
|
115
117
|
}
|
|
116
|
-
//# sourceMappingURL=executable.js.map
|
|
118
|
+
//# sourceMappingURL=executable-resolution.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
interface WindowsFindExecutableOptions {
|
|
2
|
+
enumeratePathCandidates: (name: string) => Promise<string[]>;
|
|
3
|
+
probeExecutable: (executablePath: string, timeoutMs: number) => Promise<boolean>;
|
|
4
|
+
exists: (path: string) => boolean;
|
|
5
|
+
localAppData?: string;
|
|
6
|
+
probeTimeoutMs: number;
|
|
7
|
+
}
|
|
8
|
+
interface WindowsExecutableExistsOptions {
|
|
9
|
+
exists: (path: string) => boolean;
|
|
10
|
+
}
|
|
11
|
+
declare function find(input: string, options: WindowsFindExecutableOptions): Promise<string | null>;
|
|
12
|
+
declare function exists(executablePath: string, options: WindowsExecutableExistsOptions): string | null;
|
|
13
|
+
export declare const windowsExecutableResolution: {
|
|
14
|
+
exists: typeof exists;
|
|
15
|
+
find: typeof find;
|
|
16
|
+
};
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=windows.d.ts.map
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { readdirSync } from "node:fs";
|
|
2
|
+
import { extname, join } from "node:path";
|
|
3
|
+
function hasPathSeparator(value) {
|
|
4
|
+
return value.includes("/") || value.includes("\\");
|
|
5
|
+
}
|
|
6
|
+
function enumerateLiteralPathCandidates(executablePath) {
|
|
7
|
+
if (extname(executablePath)) {
|
|
8
|
+
return [executablePath];
|
|
9
|
+
}
|
|
10
|
+
return [executablePath, `${executablePath}.exe`, `${executablePath}.cmd`];
|
|
11
|
+
}
|
|
12
|
+
function enumerateWingetPackageCandidates(name, localAppData) {
|
|
13
|
+
if (!localAppData) {
|
|
14
|
+
return [];
|
|
15
|
+
}
|
|
16
|
+
const wingetPackages = join(localAppData, "Microsoft", "WinGet", "Packages");
|
|
17
|
+
let packageDirs;
|
|
18
|
+
try {
|
|
19
|
+
packageDirs = readdirSync(wingetPackages, { withFileTypes: true })
|
|
20
|
+
.filter((entry) => entry.isDirectory())
|
|
21
|
+
.map((entry) => entry.name);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return [];
|
|
25
|
+
}
|
|
26
|
+
const exeName = `${name}.exe`;
|
|
27
|
+
return packageDirs.map((packageDir) => join(wingetPackages, packageDir, exeName));
|
|
28
|
+
}
|
|
29
|
+
async function find(input, options) {
|
|
30
|
+
if (hasPathSeparator(input)) {
|
|
31
|
+
return findFirstProbeable(enumerateLiteralPathCandidates(input), options);
|
|
32
|
+
}
|
|
33
|
+
const pathCandidates = await options.enumeratePathCandidates(input);
|
|
34
|
+
const wingetCandidates = enumerateWingetPackageCandidates(input, options.localAppData ?? process.env.LOCALAPPDATA).filter(options.exists);
|
|
35
|
+
return findFirstProbeable([...pathCandidates, ...wingetCandidates], options);
|
|
36
|
+
}
|
|
37
|
+
async function findFirstProbeable(candidates, options) {
|
|
38
|
+
const seen = new Set();
|
|
39
|
+
for (const candidate of candidates) {
|
|
40
|
+
if (seen.has(candidate)) {
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
seen.add(candidate);
|
|
44
|
+
if (await options.probeExecutable(candidate, options.probeTimeoutMs)) {
|
|
45
|
+
return candidate;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
function exists(executablePath, options) {
|
|
51
|
+
for (const candidate of enumerateLiteralPathCandidates(executablePath)) {
|
|
52
|
+
if (options.exists(candidate)) {
|
|
53
|
+
return candidate;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
export const windowsExecutableResolution = {
|
|
59
|
+
exists,
|
|
60
|
+
find,
|
|
61
|
+
};
|
|
62
|
+
//# sourceMappingURL=windows.js.map
|
|
@@ -31,7 +31,10 @@ export async function ensureAgentLoaded(agentId, deps) {
|
|
|
31
31
|
if (!config) {
|
|
32
32
|
throw new Error(`Agent ${agentId} references unavailable provider '${record.provider}'`);
|
|
33
33
|
}
|
|
34
|
-
snapshot = await deps.agentManager.createAgent(config, agentId, {
|
|
34
|
+
snapshot = await deps.agentManager.createAgent(config, agentId, {
|
|
35
|
+
labels: record.labels,
|
|
36
|
+
workspaceId: record.workspaceId,
|
|
37
|
+
});
|
|
35
38
|
deps.logger.info({ agentId, provider: record.provider }, "Agent created from stored config");
|
|
36
39
|
}
|
|
37
40
|
await deps.agentManager.hydrateTimelineFromProvider(agentId);
|
|
@@ -100,6 +100,12 @@ interface ManagedAgentBase {
|
|
|
100
100
|
id: string;
|
|
101
101
|
provider: AgentProvider;
|
|
102
102
|
cwd: string;
|
|
103
|
+
/**
|
|
104
|
+
* Workspace this agent belongs to, stamped at creation. Independent of cwd:
|
|
105
|
+
* cwd answers "where does it run", workspaceId answers "which workspace owns it".
|
|
106
|
+
* Null/undefined for legacy agents created before ownership stamping.
|
|
107
|
+
*/
|
|
108
|
+
workspaceId?: string;
|
|
103
109
|
capabilities: AgentCapabilityFlags;
|
|
104
110
|
config: AgentSessionConfig;
|
|
105
111
|
runtimeInfo?: AgentRuntimeInfo;
|
|
@@ -217,6 +223,7 @@ export declare class AgentManager {
|
|
|
217
223
|
listImportableSessions(options?: ImportablePersistedAgentQueryOptions): Promise<ManagedImportableProviderSession[]>;
|
|
218
224
|
private isProviderImportable;
|
|
219
225
|
listProviderAvailability(): Promise<ProviderAvailability[]>;
|
|
226
|
+
getProviderAvailability(provider: AgentProvider): Promise<ProviderAvailability>;
|
|
220
227
|
listDraftCommands(config: AgentSessionConfig): Promise<AgentSlashCommand[]>;
|
|
221
228
|
listDraftFeatures(config: AgentSessionConfig): Promise<AgentFeature[]>;
|
|
222
229
|
getAgent(id: string): ManagedAgent | null;
|
|
@@ -225,11 +232,11 @@ export declare class AgentManager {
|
|
|
225
232
|
fetchTimeline(id: string, options?: AgentTimelineFetchOptions): AgentTimelineFetchResult;
|
|
226
233
|
createAgent(config: AgentSessionConfig, agentId?: string, options?: {
|
|
227
234
|
labels?: Record<string, string>;
|
|
228
|
-
workspaceId?: string;
|
|
229
235
|
initialPrompt?: string;
|
|
230
236
|
env?: Record<string, string>;
|
|
231
237
|
persistSession?: boolean;
|
|
232
238
|
initialTitle?: string | null;
|
|
239
|
+
workspaceId?: string;
|
|
233
240
|
}): Promise<ManagedAgent>;
|
|
234
241
|
private buildCreateSessionOptions;
|
|
235
242
|
resumeAgentFromPersistence(handle: AgentPersistenceHandle, overrides?: Partial<AgentSessionConfig>, agentId?: string, options?: {
|
|
@@ -237,11 +244,13 @@ export declare class AgentManager {
|
|
|
237
244
|
updatedAt?: Date;
|
|
238
245
|
lastUserMessageAt?: Date | null;
|
|
239
246
|
labels?: Record<string, string>;
|
|
247
|
+
workspaceId?: string;
|
|
240
248
|
}): Promise<ManagedAgent>;
|
|
241
249
|
importProviderSession(input: {
|
|
242
250
|
provider: AgentProvider;
|
|
243
251
|
providerHandleId: string;
|
|
244
252
|
cwd: string;
|
|
253
|
+
workspaceId: string;
|
|
245
254
|
labels?: Record<string, string>;
|
|
246
255
|
}): Promise<ManagedAgent>;
|
|
247
256
|
reloadAgentSession(agentId: string, overrides?: Partial<AgentSessionConfig>, options?: {
|
|
@@ -262,7 +271,6 @@ export declare class AgentManager {
|
|
|
262
271
|
setAgentThinkingOption(agentId: string, thinkingOptionId: string | null): Promise<void>;
|
|
263
272
|
setAgentFeature(agentId: string, featureId: string, value: unknown): Promise<void>;
|
|
264
273
|
setTitle(agentId: string, title: string): Promise<void>;
|
|
265
|
-
setGeneratedTitle(agentId: string, title: string): Promise<void>;
|
|
266
274
|
setLabels(agentId: string, labels: Record<string, string>): Promise<void>;
|
|
267
275
|
notifyAgentState(agentId: string): void;
|
|
268
276
|
clearAgentAttention(agentId: string): Promise<void>;
|
|
@@ -361,34 +361,34 @@ export class AgentManager {
|
|
|
361
361
|
return true;
|
|
362
362
|
}
|
|
363
363
|
async listProviderAvailability() {
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
364
|
+
return Promise.all(Array.from(this.clients.keys()).map((provider) => this.getProviderAvailability(provider)));
|
|
365
|
+
}
|
|
366
|
+
async getProviderAvailability(provider) {
|
|
367
|
+
const client = this.clients.get(provider);
|
|
368
|
+
if (!client) {
|
|
369
|
+
return {
|
|
370
|
+
provider,
|
|
371
|
+
available: false,
|
|
372
|
+
error: `No client registered for provider '${provider}'`,
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
try {
|
|
376
|
+
const available = await client.isAvailable();
|
|
377
|
+
return {
|
|
378
|
+
provider,
|
|
379
|
+
available,
|
|
380
|
+
error: null,
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
catch (error) {
|
|
384
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
385
|
+
this.logger.warn({ err: error, provider }, "Failed to check provider availability");
|
|
386
|
+
return {
|
|
387
|
+
provider,
|
|
388
|
+
available: false,
|
|
389
|
+
error: message,
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
392
|
}
|
|
393
393
|
async listDraftCommands(config) {
|
|
394
394
|
const normalizedConfig = await this.normalizeConfig(config);
|
|
@@ -470,8 +470,8 @@ export class AgentManager {
|
|
|
470
470
|
const session = await client.createSession(launchConfig, launchContext, createOptions);
|
|
471
471
|
return this.registerSession(session, storedConfig, resolvedAgentId, {
|
|
472
472
|
labels: options?.labels,
|
|
473
|
-
workspaceId: options?.workspaceId,
|
|
474
473
|
initialTitle: options?.initialTitle,
|
|
474
|
+
workspaceId: options?.workspaceId,
|
|
475
475
|
});
|
|
476
476
|
}
|
|
477
477
|
buildCreateSessionOptions(options) {
|
|
@@ -520,6 +520,7 @@ export class AgentManager {
|
|
|
520
520
|
const initialTitle = resolveImportedAgentTitle(importedConfig, timelineRows);
|
|
521
521
|
return this.registerSession(imported.session, importedConfig, resolvedAgentId, {
|
|
522
522
|
labels: input.labels,
|
|
523
|
+
workspaceId: input.workspaceId,
|
|
523
524
|
timelineRows,
|
|
524
525
|
timelineNextSeq: timelineRows.length + 1,
|
|
525
526
|
persistence: imported.persistence,
|
|
@@ -577,6 +578,7 @@ export class AgentManager {
|
|
|
577
578
|
// Preserve existing labels and timeline during reload.
|
|
578
579
|
return this.registerSession(session, storedConfig, agentId, {
|
|
579
580
|
labels: existing.labels,
|
|
581
|
+
workspaceId: existing.workspaceId,
|
|
580
582
|
createdAt: existing.createdAt,
|
|
581
583
|
updatedAt: existing.updatedAt,
|
|
582
584
|
lastUserMessageAt: existing.lastUserMessageAt,
|
|
@@ -734,6 +736,7 @@ export class AgentManager {
|
|
|
734
736
|
id: record.id,
|
|
735
737
|
provider: record.provider,
|
|
736
738
|
cwd: record.cwd,
|
|
739
|
+
workspaceId: record.workspaceId,
|
|
737
740
|
session: null,
|
|
738
741
|
capabilities: STORED_AGENT_CAPABILITIES,
|
|
739
742
|
config: buildStoredAgentConfig(record),
|
|
@@ -832,17 +835,6 @@ export class AgentManager {
|
|
|
832
835
|
await this.persistSnapshot(agent, { title: normalizedTitle });
|
|
833
836
|
this.emitState(agent, { persist: false });
|
|
834
837
|
}
|
|
835
|
-
async setGeneratedTitle(agentId, title) {
|
|
836
|
-
const agent = this.requireAgent(agentId);
|
|
837
|
-
const normalizedTitle = title.trim();
|
|
838
|
-
if (!normalizedTitle) {
|
|
839
|
-
return;
|
|
840
|
-
}
|
|
841
|
-
const registry = this.requireRegistry();
|
|
842
|
-
const persisted = await registry.setGeneratedTitle(agent.id, normalizedTitle);
|
|
843
|
-
agent.updatedAt = new Date(persisted.updatedAt);
|
|
844
|
-
this.emitState(agent, { persist: false });
|
|
845
|
-
}
|
|
846
838
|
async setLabels(agentId, labels) {
|
|
847
839
|
const agent = this.requireAgent(agentId);
|
|
848
840
|
agent.labels = { ...agent.labels, ...labels };
|
|
@@ -1677,7 +1669,6 @@ export class AgentManager {
|
|
|
1677
1669
|
this.previousStatuses.set(resolvedAgentId, managed.lifecycle);
|
|
1678
1670
|
await this.refreshRuntimeInfo(managed, { emit: !options?.publishWhenReady });
|
|
1679
1671
|
await this.persistSnapshot(managed, {
|
|
1680
|
-
workspaceId: options?.workspaceId,
|
|
1681
1672
|
title: initialPersistedTitle,
|
|
1682
1673
|
});
|
|
1683
1674
|
if (!options?.publishWhenReady) {
|
|
@@ -1685,7 +1676,7 @@ export class AgentManager {
|
|
|
1685
1676
|
}
|
|
1686
1677
|
await this.refreshSessionState(managed, { emit: !options?.publishWhenReady });
|
|
1687
1678
|
managed.lifecycle = "idle";
|
|
1688
|
-
await this.persistSnapshot(managed
|
|
1679
|
+
await this.persistSnapshot(managed);
|
|
1689
1680
|
this.emitState(managed, { persist: false });
|
|
1690
1681
|
this.subscribeToSession(managed);
|
|
1691
1682
|
return { ...managed };
|
|
@@ -1715,6 +1706,7 @@ export class AgentManager {
|
|
|
1715
1706
|
id: resolvedAgentId,
|
|
1716
1707
|
provider: config.provider,
|
|
1717
1708
|
cwd: config.cwd,
|
|
1709
|
+
workspaceId: options?.workspaceId,
|
|
1718
1710
|
session,
|
|
1719
1711
|
capabilities: session.capabilities,
|
|
1720
1712
|
config,
|
|
@@ -1872,10 +1864,6 @@ export class AgentManager {
|
|
|
1872
1864
|
if (agent.internal) {
|
|
1873
1865
|
return;
|
|
1874
1866
|
}
|
|
1875
|
-
if (options?.workspaceId !== undefined) {
|
|
1876
|
-
await this.registry.applySnapshot(agent, options.workspaceId, options);
|
|
1877
|
-
return;
|
|
1878
|
-
}
|
|
1879
1867
|
await this.registry.applySnapshot(agent, options);
|
|
1880
1868
|
}
|
|
1881
1869
|
requireRegistry() {
|
|
@@ -27,6 +27,7 @@ export function toStoredAgentRecord(agent, options) {
|
|
|
27
27
|
id: agent.id,
|
|
28
28
|
provider: agent.provider,
|
|
29
29
|
cwd: agent.cwd,
|
|
30
|
+
workspaceId: agent.workspaceId,
|
|
30
31
|
createdAt,
|
|
31
32
|
updatedAt: agent.updatedAt.toISOString(),
|
|
32
33
|
lastActivityAt: agent.updatedAt.toISOString(),
|
|
@@ -59,6 +60,7 @@ export function toAgentPayload(agent, options) {
|
|
|
59
60
|
id: agent.id,
|
|
60
61
|
provider: agent.provider,
|
|
61
62
|
cwd: agent.cwd,
|
|
63
|
+
...(agent.workspaceId ? { workspaceId: agent.workspaceId } : {}),
|
|
62
64
|
model: agent.config.model ?? null,
|
|
63
65
|
thinkingOptionId,
|
|
64
66
|
effectiveThinkingOptionId,
|
|
@@ -145,6 +147,7 @@ export function buildStoredAgentPayload(record, validProviders) {
|
|
|
145
147
|
id: record.id,
|
|
146
148
|
provider: record.provider,
|
|
147
149
|
cwd: record.cwd,
|
|
150
|
+
...(record.workspaceId ? { workspaceId: record.workspaceId } : {}),
|
|
148
151
|
model: record.config?.model ?? null,
|
|
149
152
|
thinkingOptionId: record.config?.thinkingOptionId ?? null,
|
|
150
153
|
effectiveThinkingOptionId: resolveEffectiveThinkingOptionId({
|
|
@@ -148,6 +148,14 @@ export async function startCreatedAgentInitialPrompt(params) {
|
|
|
148
148
|
}
|
|
149
149
|
return refreshedSnapshot;
|
|
150
150
|
}
|
|
151
|
+
function formatFinishNotificationBody(params) {
|
|
152
|
+
const statusLine = `Agent ${params.childAgentId} (${params.title}) ${params.reason}.`;
|
|
153
|
+
const lastAssistantMessage = params.lastAssistantMessage?.trim();
|
|
154
|
+
if (!lastAssistantMessage) {
|
|
155
|
+
return statusLine;
|
|
156
|
+
}
|
|
157
|
+
return `${statusLine}\n\n<agent-response>\n${lastAssistantMessage}\n</agent-response>`;
|
|
158
|
+
}
|
|
151
159
|
export function setupFinishNotification(params) {
|
|
152
160
|
const { agentManager, agentStorage, childAgentId, callerAgentId, logger } = params;
|
|
153
161
|
let hasSeenRunning = false;
|
|
@@ -159,9 +167,19 @@ export function setupFinishNotification(params) {
|
|
|
159
167
|
}
|
|
160
168
|
fired = true;
|
|
161
169
|
unsubscribe?.();
|
|
170
|
+
const callerRecord = await agentStorage.get(callerAgentId);
|
|
171
|
+
if (callerRecord?.archivedAt) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
162
174
|
const record = await agentStorage.get(childAgentId);
|
|
163
175
|
const title = record?.title ?? childAgentId;
|
|
164
|
-
const
|
|
176
|
+
const lastAssistantMessage = await agentManager.getLastAssistantMessage(childAgentId);
|
|
177
|
+
const body = formatFinishNotificationBody({
|
|
178
|
+
childAgentId,
|
|
179
|
+
title,
|
|
180
|
+
reason,
|
|
181
|
+
lastAssistantMessage,
|
|
182
|
+
});
|
|
165
183
|
await sendPromptToAgent({
|
|
166
184
|
agentManager,
|
|
167
185
|
agentStorage,
|
|
@@ -265,12 +265,10 @@ export async function generateStructuredAgentResponseWithFallback(options) {
|
|
|
265
265
|
}
|
|
266
266
|
const runStructured = runner ??
|
|
267
267
|
((input) => generateStructuredAgentResponse(input));
|
|
268
|
-
const availability = await manager.listProviderAvailability();
|
|
269
|
-
const availabilityByProvider = new Map(availability.map((entry) => [entry.provider, entry]));
|
|
270
268
|
const attempts = [];
|
|
271
269
|
for (const candidate of providers) {
|
|
272
|
-
const availabilityEntry =
|
|
273
|
-
if (
|
|
270
|
+
const availabilityEntry = await manager.getProviderAvailability(candidate.provider);
|
|
271
|
+
if (!availabilityEntry.available) {
|
|
274
272
|
const reason = availabilityEntry.error ?? "unavailable";
|
|
275
273
|
attempts.push({
|
|
276
274
|
provider: candidate.provider,
|
|
@@ -6,6 +6,7 @@ declare const STORED_AGENT_SCHEMA: z.ZodObject<{
|
|
|
6
6
|
id: z.ZodString;
|
|
7
7
|
provider: z.ZodString;
|
|
8
8
|
cwd: z.ZodString;
|
|
9
|
+
workspaceId: z.ZodOptional<z.ZodString>;
|
|
9
10
|
createdAt: z.ZodString;
|
|
10
11
|
updatedAt: z.ZodString;
|
|
11
12
|
lastActivityAt: z.ZodOptional<z.ZodString>;
|
|
@@ -70,16 +71,16 @@ declare const STORED_AGENT_SCHEMA: z.ZodObject<{
|
|
|
70
71
|
icon: z.ZodOptional<z.ZodString>;
|
|
71
72
|
value: z.ZodBoolean;
|
|
72
73
|
}, "strip", z.ZodTypeAny, {
|
|
73
|
-
type: "toggle";
|
|
74
74
|
value: boolean;
|
|
75
|
+
type: "toggle";
|
|
75
76
|
id: string;
|
|
76
77
|
label: string;
|
|
77
78
|
description?: string | undefined;
|
|
78
79
|
icon?: string | undefined;
|
|
79
80
|
tooltip?: string | undefined;
|
|
80
81
|
}, {
|
|
81
|
-
type: "toggle";
|
|
82
82
|
value: boolean;
|
|
83
|
+
type: "toggle";
|
|
83
84
|
id: string;
|
|
84
85
|
label: string;
|
|
85
86
|
description?: string | undefined;
|
|
@@ -113,7 +114,6 @@ declare const STORED_AGENT_SCHEMA: z.ZodObject<{
|
|
|
113
114
|
isDefault?: boolean | undefined;
|
|
114
115
|
}>, "many">;
|
|
115
116
|
}, "strip", z.ZodTypeAny, {
|
|
116
|
-
type: "select";
|
|
117
117
|
value: string | null;
|
|
118
118
|
options: {
|
|
119
119
|
id: string;
|
|
@@ -122,13 +122,13 @@ declare const STORED_AGENT_SCHEMA: z.ZodObject<{
|
|
|
122
122
|
metadata?: Record<string, unknown> | undefined;
|
|
123
123
|
isDefault?: boolean | undefined;
|
|
124
124
|
}[];
|
|
125
|
+
type: "select";
|
|
125
126
|
id: string;
|
|
126
127
|
label: string;
|
|
127
128
|
description?: string | undefined;
|
|
128
129
|
icon?: string | undefined;
|
|
129
130
|
tooltip?: string | undefined;
|
|
130
131
|
}, {
|
|
131
|
-
type: "select";
|
|
132
132
|
value: string | null;
|
|
133
133
|
options: {
|
|
134
134
|
id: string;
|
|
@@ -137,6 +137,7 @@ declare const STORED_AGENT_SCHEMA: z.ZodObject<{
|
|
|
137
137
|
metadata?: Record<string, unknown> | undefined;
|
|
138
138
|
isDefault?: boolean | undefined;
|
|
139
139
|
}[];
|
|
140
|
+
type: "select";
|
|
140
141
|
id: string;
|
|
141
142
|
label: string;
|
|
142
143
|
description?: string | undefined;
|
|
@@ -172,7 +173,10 @@ declare const STORED_AGENT_SCHEMA: z.ZodObject<{
|
|
|
172
173
|
createdAt: string;
|
|
173
174
|
updatedAt: string;
|
|
174
175
|
labels: Record<string, string>;
|
|
175
|
-
lastStatus: "error" | "
|
|
176
|
+
lastStatus: "error" | "idle" | "running" | "initializing" | "closed";
|
|
177
|
+
workspaceId?: string | undefined;
|
|
178
|
+
internal?: boolean | undefined;
|
|
179
|
+
attentionReason?: "finished" | "error" | "permission" | null | undefined;
|
|
176
180
|
title?: string | null | undefined;
|
|
177
181
|
persistence?: {
|
|
178
182
|
provider: string;
|
|
@@ -201,15 +205,14 @@ declare const STORED_AGENT_SCHEMA: z.ZodObject<{
|
|
|
201
205
|
extra?: Record<string, unknown> | undefined;
|
|
202
206
|
} | undefined;
|
|
203
207
|
features?: ({
|
|
204
|
-
type: "toggle";
|
|
205
208
|
value: boolean;
|
|
209
|
+
type: "toggle";
|
|
206
210
|
id: string;
|
|
207
211
|
label: string;
|
|
208
212
|
description?: string | undefined;
|
|
209
213
|
icon?: string | undefined;
|
|
210
214
|
tooltip?: string | undefined;
|
|
211
215
|
} | {
|
|
212
|
-
type: "select";
|
|
213
216
|
value: string | null;
|
|
214
217
|
options: {
|
|
215
218
|
id: string;
|
|
@@ -218,6 +221,7 @@ declare const STORED_AGENT_SCHEMA: z.ZodObject<{
|
|
|
218
221
|
metadata?: Record<string, unknown> | undefined;
|
|
219
222
|
isDefault?: boolean | undefined;
|
|
220
223
|
}[];
|
|
224
|
+
type: "select";
|
|
221
225
|
id: string;
|
|
222
226
|
label: string;
|
|
223
227
|
description?: string | undefined;
|
|
@@ -226,9 +230,7 @@ declare const STORED_AGENT_SCHEMA: z.ZodObject<{
|
|
|
226
230
|
})[] | undefined;
|
|
227
231
|
lastError?: string | null | undefined;
|
|
228
232
|
requiresAttention?: boolean | undefined;
|
|
229
|
-
attentionReason?: "finished" | "error" | "permission" | null | undefined;
|
|
230
233
|
attentionTimestamp?: string | null | undefined;
|
|
231
|
-
internal?: boolean | undefined;
|
|
232
234
|
archivedAt?: string | null | undefined;
|
|
233
235
|
}, {
|
|
234
236
|
cwd: string;
|
|
@@ -236,6 +238,9 @@ declare const STORED_AGENT_SCHEMA: z.ZodObject<{
|
|
|
236
238
|
provider: string;
|
|
237
239
|
createdAt: string;
|
|
238
240
|
updatedAt: string;
|
|
241
|
+
workspaceId?: string | undefined;
|
|
242
|
+
internal?: boolean | undefined;
|
|
243
|
+
attentionReason?: "finished" | "error" | "permission" | null | undefined;
|
|
239
244
|
title?: string | null | undefined;
|
|
240
245
|
persistence?: {
|
|
241
246
|
provider: string;
|
|
@@ -246,7 +251,7 @@ declare const STORED_AGENT_SCHEMA: z.ZodObject<{
|
|
|
246
251
|
lastActivityAt?: string | undefined;
|
|
247
252
|
lastUserMessageAt?: string | null | undefined;
|
|
248
253
|
labels?: Record<string, string> | undefined;
|
|
249
|
-
lastStatus?: "error" | "
|
|
254
|
+
lastStatus?: "error" | "idle" | "running" | "initializing" | "closed" | undefined;
|
|
250
255
|
lastModeId?: string | null | undefined;
|
|
251
256
|
config?: {
|
|
252
257
|
modeId?: string | null | undefined;
|
|
@@ -266,15 +271,14 @@ declare const STORED_AGENT_SCHEMA: z.ZodObject<{
|
|
|
266
271
|
extra?: Record<string, unknown> | undefined;
|
|
267
272
|
} | undefined;
|
|
268
273
|
features?: ({
|
|
269
|
-
type: "toggle";
|
|
270
274
|
value: boolean;
|
|
275
|
+
type: "toggle";
|
|
271
276
|
id: string;
|
|
272
277
|
label: string;
|
|
273
278
|
description?: string | undefined;
|
|
274
279
|
icon?: string | undefined;
|
|
275
280
|
tooltip?: string | undefined;
|
|
276
281
|
} | {
|
|
277
|
-
type: "select";
|
|
278
282
|
value: string | null;
|
|
279
283
|
options: {
|
|
280
284
|
id: string;
|
|
@@ -283,6 +287,7 @@ declare const STORED_AGENT_SCHEMA: z.ZodObject<{
|
|
|
283
287
|
metadata?: Record<string, unknown> | undefined;
|
|
284
288
|
isDefault?: boolean | undefined;
|
|
285
289
|
}[];
|
|
290
|
+
type: "select";
|
|
286
291
|
id: string;
|
|
287
292
|
label: string;
|
|
288
293
|
description?: string | undefined;
|
|
@@ -291,9 +296,7 @@ declare const STORED_AGENT_SCHEMA: z.ZodObject<{
|
|
|
291
296
|
})[] | undefined;
|
|
292
297
|
lastError?: string | null | undefined;
|
|
293
298
|
requiresAttention?: boolean | undefined;
|
|
294
|
-
attentionReason?: "finished" | "error" | "permission" | null | undefined;
|
|
295
299
|
attentionTimestamp?: string | null | undefined;
|
|
296
|
-
internal?: boolean | undefined;
|
|
297
300
|
archivedAt?: string | null | undefined;
|
|
298
301
|
}>;
|
|
299
302
|
export type SerializableAgentConfig = Pick<AgentSessionConfig, "modeId" | "model" | "thinkingOptionId" | "featureValues" | "extra" | "systemPrompt" | "mcpServers">;
|
|
@@ -318,15 +321,11 @@ export declare class AgentStorage {
|
|
|
318
321
|
private writeRecord;
|
|
319
322
|
beginDelete(agentId: string): void;
|
|
320
323
|
remove(agentId: string): Promise<void>;
|
|
321
|
-
applySnapshot(agent: ManagedAgent,
|
|
322
|
-
title?: string | null;
|
|
323
|
-
internal?: boolean;
|
|
324
|
-
}, options?: {
|
|
324
|
+
applySnapshot(agent: ManagedAgent, options?: {
|
|
325
325
|
title?: string | null;
|
|
326
326
|
internal?: boolean;
|
|
327
327
|
}): Promise<void>;
|
|
328
328
|
setTitle(agentId: string, title: string): Promise<void>;
|
|
329
|
-
setGeneratedTitle(agentId: string, title: string): Promise<StoredAgentRecord>;
|
|
330
329
|
flush(): Promise<void>;
|
|
331
330
|
private load;
|
|
332
331
|
private doLoad;
|
|
@@ -29,6 +29,7 @@ const STORED_AGENT_SCHEMA = z.object({
|
|
|
29
29
|
id: z.string(),
|
|
30
30
|
provider: z.string(),
|
|
31
31
|
cwd: z.string(),
|
|
32
|
+
workspaceId: z.string().optional(),
|
|
32
33
|
createdAt: z.string(),
|
|
33
34
|
updatedAt: z.string(),
|
|
34
35
|
lastActivityAt: z.string().optional(),
|
|
@@ -146,19 +147,16 @@ export class AgentStorage {
|
|
|
146
147
|
this.pathById.delete(agentId);
|
|
147
148
|
this.pathsById.delete(agentId);
|
|
148
149
|
}
|
|
149
|
-
async applySnapshot(agent,
|
|
150
|
-
const nextOptions = typeof workspaceIdOrOptions === "string" ? options : workspaceIdOrOptions;
|
|
150
|
+
async applySnapshot(agent, options) {
|
|
151
151
|
await this.load();
|
|
152
152
|
await this.waitForPendingWrite(agent.id);
|
|
153
153
|
const existing = (await this.get(agent.id)) ?? null;
|
|
154
|
-
const hasTitleOverride =
|
|
155
|
-
const hasInternalOverride =
|
|
154
|
+
const hasTitleOverride = options !== undefined && Object.prototype.hasOwnProperty.call(options, "title");
|
|
155
|
+
const hasInternalOverride = options !== undefined && Object.prototype.hasOwnProperty.call(options, "internal");
|
|
156
156
|
const record = toStoredAgentRecord(agent, {
|
|
157
|
-
title: hasTitleOverride ? (
|
|
157
|
+
title: hasTitleOverride ? (options?.title ?? null) : (existing?.title ?? null),
|
|
158
158
|
createdAt: existing?.createdAt,
|
|
159
|
-
internal: hasInternalOverride
|
|
160
|
-
? nextOptions?.internal
|
|
161
|
-
: (agent.internal ?? existing?.internal),
|
|
159
|
+
internal: hasInternalOverride ? options?.internal : (agent.internal ?? existing?.internal),
|
|
162
160
|
});
|
|
163
161
|
// Preserve soft-delete/archive status across snapshot flushes.
|
|
164
162
|
// `archivedAt` is not part of the ManagedAgent snapshot, so a naive projection
|
|
@@ -177,21 +175,6 @@ export class AgentStorage {
|
|
|
177
175
|
}
|
|
178
176
|
await this.upsert({ ...record, title });
|
|
179
177
|
}
|
|
180
|
-
async setGeneratedTitle(agentId, title) {
|
|
181
|
-
await this.load();
|
|
182
|
-
await this.waitForPendingWrite(agentId);
|
|
183
|
-
const record = this.cache.get(agentId) ?? null;
|
|
184
|
-
if (!record) {
|
|
185
|
-
throw new Error(`Agent ${agentId} not found`);
|
|
186
|
-
}
|
|
187
|
-
const nextRecord = {
|
|
188
|
-
...record,
|
|
189
|
-
title,
|
|
190
|
-
updatedAt: new Date().toISOString(),
|
|
191
|
-
};
|
|
192
|
-
await this.queueRecordWrite(nextRecord);
|
|
193
|
-
return nextRecord;
|
|
194
|
-
}
|
|
195
178
|
async flush() {
|
|
196
179
|
await this.load().catch(() => undefined);
|
|
197
180
|
const writes = Array.from(this.pendingWrites.values());
|