@link-assistant/agent 0.5.2 → 0.6.0
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/package.json +5 -3
- package/src/auth/claude-oauth.ts +50 -24
- package/src/auth/plugins.ts +28 -16
- package/src/bun/index.ts +33 -27
- package/src/bus/index.ts +3 -5
- package/src/config/config.ts +39 -22
- package/src/file/ripgrep.ts +1 -1
- package/src/file/time.ts +1 -1
- package/src/file/watcher.ts +10 -5
- package/src/format/index.ts +12 -10
- package/src/index.js +30 -35
- package/src/mcp/index.ts +32 -15
- package/src/patch/index.ts +8 -4
- package/src/project/project.ts +1 -1
- package/src/project/state.ts +15 -7
- package/src/provider/cache.ts +259 -0
- package/src/provider/echo.ts +174 -0
- package/src/provider/models.ts +4 -5
- package/src/provider/provider.ts +164 -29
- package/src/server/server.ts +4 -5
- package/src/session/agent.js +16 -2
- package/src/session/compaction.ts +4 -6
- package/src/session/index.ts +2 -2
- package/src/session/processor.ts +3 -7
- package/src/session/prompt.ts +95 -60
- package/src/session/revert.ts +1 -1
- package/src/session/summary.ts +2 -2
- package/src/snapshot/index.ts +27 -12
- package/src/storage/storage.ts +18 -18
- package/src/util/log-lazy.ts +291 -0
- package/src/util/log.ts +205 -28
package/src/session/prompt.ts
CHANGED
|
@@ -216,7 +216,7 @@ export namespace SessionPrompt {
|
|
|
216
216
|
}
|
|
217
217
|
|
|
218
218
|
export function cancel(sessionID: string) {
|
|
219
|
-
log.info('cancel',
|
|
219
|
+
log.info(() => ({ message: 'cancel', sessionID }));
|
|
220
220
|
const s = state();
|
|
221
221
|
const match = s[sessionID];
|
|
222
222
|
if (!match) return;
|
|
@@ -242,7 +242,7 @@ export namespace SessionPrompt {
|
|
|
242
242
|
|
|
243
243
|
let step = 0;
|
|
244
244
|
while (true) {
|
|
245
|
-
log.info('loop',
|
|
245
|
+
log.info(() => ({ message: 'loop', step, sessionID }));
|
|
246
246
|
if (abort.aborted) break;
|
|
247
247
|
let msgs = await MessageV2.filterCompacted(MessageV2.stream(sessionID));
|
|
248
248
|
|
|
@@ -276,7 +276,7 @@ export namespace SessionPrompt {
|
|
|
276
276
|
lastAssistant.finish !== 'tool-calls' &&
|
|
277
277
|
lastUser.id < lastAssistant.id
|
|
278
278
|
) {
|
|
279
|
-
log.info('exiting loop',
|
|
279
|
+
log.info(() => ({ message: 'exiting loop', sessionID }));
|
|
280
280
|
break;
|
|
281
281
|
}
|
|
282
282
|
|
|
@@ -297,14 +297,13 @@ export namespace SessionPrompt {
|
|
|
297
297
|
lastUser.model.modelID
|
|
298
298
|
);
|
|
299
299
|
} catch (error) {
|
|
300
|
-
log.warn(
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
);
|
|
300
|
+
log.warn(() => ({
|
|
301
|
+
message:
|
|
302
|
+
'Failed to initialize specified model, falling back to default model',
|
|
303
|
+
providerID: lastUser.model.providerID,
|
|
304
|
+
modelID: lastUser.model.modelID,
|
|
305
|
+
error: error instanceof Error ? error.message : String(error),
|
|
306
|
+
}));
|
|
308
307
|
const defaultModel = await Provider.defaultModel();
|
|
309
308
|
model = await Provider.getModel(
|
|
310
309
|
defaultModel.providerID,
|
|
@@ -447,7 +446,7 @@ export namespace SessionPrompt {
|
|
|
447
446
|
lastFinished.summary !== true &&
|
|
448
447
|
SessionCompaction.isOverflow({
|
|
449
448
|
tokens: lastFinished.tokens,
|
|
450
|
-
model: model.info,
|
|
449
|
+
model: model.info ?? { id: model.modelID },
|
|
451
450
|
})
|
|
452
451
|
) {
|
|
453
452
|
await SessionCompaction.create({
|
|
@@ -488,13 +487,13 @@ export namespace SessionPrompt {
|
|
|
488
487
|
sessionID,
|
|
489
488
|
})) as MessageV2.Assistant,
|
|
490
489
|
sessionID: sessionID,
|
|
491
|
-
model: model.info,
|
|
490
|
+
model: model.info ?? { id: model.modelID },
|
|
492
491
|
providerID: model.providerID,
|
|
493
492
|
abort,
|
|
494
493
|
});
|
|
495
494
|
const system = await resolveSystemPrompt({
|
|
496
495
|
providerID: model.providerID,
|
|
497
|
-
modelID: model.info.
|
|
496
|
+
modelID: model.info?.id ?? model.modelID,
|
|
498
497
|
agent,
|
|
499
498
|
system: lastUser.system,
|
|
500
499
|
appendSystem: lastUser.appendSystem,
|
|
@@ -507,10 +506,11 @@ export namespace SessionPrompt {
|
|
|
507
506
|
processor,
|
|
508
507
|
});
|
|
509
508
|
const params = {
|
|
510
|
-
temperature:
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
509
|
+
temperature:
|
|
510
|
+
(model.info?.temperature ?? false)
|
|
511
|
+
? (agent.temperature ??
|
|
512
|
+
ProviderTransform.temperature(model.providerID, model.modelID))
|
|
513
|
+
: undefined,
|
|
514
514
|
topP:
|
|
515
515
|
agent.topP ?? ProviderTransform.topP(model.providerID, model.modelID),
|
|
516
516
|
options: {
|
|
@@ -520,7 +520,7 @@ export namespace SessionPrompt {
|
|
|
520
520
|
model.npm ?? '',
|
|
521
521
|
sessionID
|
|
522
522
|
),
|
|
523
|
-
...model.info
|
|
523
|
+
...(model.info?.options ?? {}),
|
|
524
524
|
...agent.options,
|
|
525
525
|
},
|
|
526
526
|
};
|
|
@@ -550,51 +550,79 @@ export namespace SessionPrompt {
|
|
|
550
550
|
);
|
|
551
551
|
const totalEstimatedTokens = systemTokens + userTokens;
|
|
552
552
|
|
|
553
|
-
log.info(
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
log.info(
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
553
|
+
log.info(() => ({
|
|
554
|
+
message: '=== VERBOSE: API Request Details ===',
|
|
555
|
+
}));
|
|
556
|
+
log.info(() => ({
|
|
557
|
+
message: 'Model',
|
|
558
|
+
model: `${model.providerID}/${model.modelID}`,
|
|
559
|
+
}));
|
|
560
|
+
log.info(() => ({ message: 'Session ID', sessionID }));
|
|
561
|
+
log.info(() => ({ message: 'Agent', agent: agent.name }));
|
|
562
|
+
log.info(() => ({
|
|
563
|
+
message: 'Temperature',
|
|
564
|
+
temperature: params.temperature ?? 'default',
|
|
565
|
+
}));
|
|
566
|
+
log.info(() => ({
|
|
567
|
+
message: 'Top P',
|
|
568
|
+
topP: params.topP ?? 'default',
|
|
569
|
+
}));
|
|
570
|
+
log.info(() => ({
|
|
571
|
+
message: 'Active Tools',
|
|
572
|
+
tools: Object.keys(tools).filter((x) => x !== 'invalid'),
|
|
573
|
+
}));
|
|
574
|
+
log.info(() => ({ message: '--- System Prompt ---' }));
|
|
565
575
|
for (let i = 0; i < system.length; i++) {
|
|
566
576
|
const tokens = Token.estimate(system[i]);
|
|
567
|
-
log.info(
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
);
|
|
577
|
+
log.info(() => ({
|
|
578
|
+
message: 'System Message',
|
|
579
|
+
index: i + 1,
|
|
580
|
+
tokens,
|
|
581
|
+
}));
|
|
582
|
+
log.info(() => ({
|
|
583
|
+
message: 'System Message Content',
|
|
584
|
+
content:
|
|
585
|
+
system[i].slice(0, 2000) +
|
|
586
|
+
(system[i].length > 2000 ? '... [truncated]' : ''),
|
|
587
|
+
}));
|
|
572
588
|
}
|
|
573
|
-
log.info('--- Token Summary ---');
|
|
574
|
-
log.info(
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
589
|
+
log.info(() => ({ message: '--- Token Summary ---' }));
|
|
590
|
+
log.info(() => ({
|
|
591
|
+
message: 'System prompt tokens (estimated)',
|
|
592
|
+
systemTokens,
|
|
593
|
+
}));
|
|
594
|
+
log.info(() => ({
|
|
595
|
+
message: 'User message tokens (estimated)',
|
|
596
|
+
userTokens,
|
|
597
|
+
}));
|
|
598
|
+
log.info(() => ({
|
|
599
|
+
message: 'Total estimated tokens',
|
|
600
|
+
totalEstimatedTokens,
|
|
601
|
+
}));
|
|
602
|
+
log.info(() => ({
|
|
603
|
+
message: 'Model context limit',
|
|
604
|
+
contextLimit: model.info?.limit?.context || 'unknown',
|
|
605
|
+
}));
|
|
606
|
+
log.info(() => ({
|
|
607
|
+
message: 'Model output limit',
|
|
608
|
+
outputLimit: model.info?.limit?.output || 'unknown',
|
|
609
|
+
}));
|
|
610
|
+
log.info(() => ({ message: '=== END VERBOSE ===' }));
|
|
582
611
|
}
|
|
583
612
|
|
|
584
613
|
const result = await processor.process(() =>
|
|
585
614
|
streamText({
|
|
586
615
|
onError(error) {
|
|
587
|
-
log.error('stream error',
|
|
588
|
-
error,
|
|
589
|
-
});
|
|
616
|
+
log.error(() => ({ message: 'stream error', error }));
|
|
590
617
|
},
|
|
591
618
|
async experimental_repairToolCall(input) {
|
|
592
619
|
const lower = input.toolCall.toolName.toLowerCase();
|
|
593
620
|
if (lower !== input.toolCall.toolName && tools[lower]) {
|
|
594
|
-
log.info(
|
|
621
|
+
log.info(() => ({
|
|
622
|
+
message: 'repairing tool call',
|
|
595
623
|
tool: input.toolCall.toolName,
|
|
596
624
|
repaired: lower,
|
|
597
|
-
});
|
|
625
|
+
}));
|
|
598
626
|
return {
|
|
599
627
|
...input.toolCall,
|
|
600
628
|
toolName: lower,
|
|
@@ -616,7 +644,7 @@ export namespace SessionPrompt {
|
|
|
616
644
|
'x-opencode-request': lastUser.id,
|
|
617
645
|
}
|
|
618
646
|
: undefined),
|
|
619
|
-
...model.info
|
|
647
|
+
...(model.info?.headers ?? {}),
|
|
620
648
|
},
|
|
621
649
|
// set to 0, we handle loop
|
|
622
650
|
maxRetries: 0,
|
|
@@ -624,7 +652,7 @@ export namespace SessionPrompt {
|
|
|
624
652
|
maxOutputTokens: ProviderTransform.maxOutputTokens(
|
|
625
653
|
model.providerID,
|
|
626
654
|
params.options,
|
|
627
|
-
model.info
|
|
655
|
+
model.info?.limit?.output ?? 100000,
|
|
628
656
|
OUTPUT_TOKEN_MAX
|
|
629
657
|
),
|
|
630
658
|
abortSignal: abort,
|
|
@@ -662,7 +690,7 @@ export namespace SessionPrompt {
|
|
|
662
690
|
})
|
|
663
691
|
),
|
|
664
692
|
],
|
|
665
|
-
tools: model.info
|
|
693
|
+
tools: model.info?.tool_call === false ? undefined : tools,
|
|
666
694
|
model: wrapLanguageModel({
|
|
667
695
|
model: model.language,
|
|
668
696
|
middleware: [
|
|
@@ -942,7 +970,7 @@ export namespace SessionPrompt {
|
|
|
942
970
|
}
|
|
943
971
|
break;
|
|
944
972
|
case 'file:':
|
|
945
|
-
log.info('file',
|
|
973
|
+
log.info(() => ({ message: 'file', mime: part.mime }));
|
|
946
974
|
// have to normalize, symbol search returns absolute paths
|
|
947
975
|
// Decode the pathname since URL constructor doesn't automatically decode it
|
|
948
976
|
const filepath = fileURLToPath(part.url);
|
|
@@ -1009,7 +1037,10 @@ export namespace SessionPrompt {
|
|
|
1009
1037
|
);
|
|
1010
1038
|
})
|
|
1011
1039
|
.catch((error) => {
|
|
1012
|
-
log.error(
|
|
1040
|
+
log.error(() => ({
|
|
1041
|
+
message: 'failed to read file',
|
|
1042
|
+
error,
|
|
1043
|
+
}));
|
|
1013
1044
|
const message =
|
|
1014
1045
|
error instanceof Error ? error.message : error.toString();
|
|
1015
1046
|
Bus.publish(Session.Event.Error, {
|
|
@@ -1373,7 +1404,7 @@ export namespace SessionPrompt {
|
|
|
1373
1404
|
*/
|
|
1374
1405
|
|
|
1375
1406
|
export async function command(input: CommandInput) {
|
|
1376
|
-
log.info('command', input);
|
|
1407
|
+
log.info(() => ({ message: 'command', ...input }));
|
|
1377
1408
|
const command = await Command.get(input.command);
|
|
1378
1409
|
const agentName = command.agent ?? input.agent ?? 'build';
|
|
1379
1410
|
|
|
@@ -1494,7 +1525,7 @@ export namespace SessionPrompt {
|
|
|
1494
1525
|
small.npm ?? '',
|
|
1495
1526
|
input.session.id
|
|
1496
1527
|
),
|
|
1497
|
-
...small.info
|
|
1528
|
+
...(small.info?.options ?? {}),
|
|
1498
1529
|
};
|
|
1499
1530
|
if (small.providerID === 'openai' || small.modelID.includes('gpt-5')) {
|
|
1500
1531
|
if (small.modelID.includes('5.1')) {
|
|
@@ -1509,7 +1540,7 @@ export namespace SessionPrompt {
|
|
|
1509
1540
|
};
|
|
1510
1541
|
}
|
|
1511
1542
|
await generateText({
|
|
1512
|
-
maxOutputTokens: small.info
|
|
1543
|
+
maxOutputTokens: small.info?.reasoning ? 1500 : 20,
|
|
1513
1544
|
providerOptions: ProviderTransform.providerOptions(
|
|
1514
1545
|
small.npm,
|
|
1515
1546
|
small.providerID,
|
|
@@ -1550,7 +1581,7 @@ export namespace SessionPrompt {
|
|
|
1550
1581
|
},
|
|
1551
1582
|
]),
|
|
1552
1583
|
],
|
|
1553
|
-
headers: small.info
|
|
1584
|
+
headers: small.info?.headers ?? {},
|
|
1554
1585
|
model: small.language,
|
|
1555
1586
|
})
|
|
1556
1587
|
.then((result) => {
|
|
@@ -1569,7 +1600,11 @@ export namespace SessionPrompt {
|
|
|
1569
1600
|
});
|
|
1570
1601
|
})
|
|
1571
1602
|
.catch((error) => {
|
|
1572
|
-
log.error(
|
|
1603
|
+
log.error(() => ({
|
|
1604
|
+
message: 'failed to generate title',
|
|
1605
|
+
error,
|
|
1606
|
+
model: small.info?.id ?? small.modelID,
|
|
1607
|
+
}));
|
|
1573
1608
|
});
|
|
1574
1609
|
}
|
|
1575
1610
|
}
|
package/src/session/revert.ts
CHANGED
|
@@ -72,7 +72,7 @@ export namespace SessionRevert {
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
export async function unrevert(input: { sessionID: string }) {
|
|
75
|
-
log.info('unreverting', input);
|
|
75
|
+
log.info(() => ({ message: 'unreverting', ...input }));
|
|
76
76
|
SessionPrompt.assertNotBusy(input.sessionID);
|
|
77
77
|
const session = await Session.get(input.sessionID);
|
|
78
78
|
if (!session.revert) return session;
|
package/src/session/summary.ts
CHANGED
|
@@ -115,7 +115,7 @@ export namespace SessionSummary {
|
|
|
115
115
|
headers: small.info.headers,
|
|
116
116
|
model: small.language,
|
|
117
117
|
});
|
|
118
|
-
log.info('title',
|
|
118
|
+
log.info(() => ({ message: 'title', title: result.text }));
|
|
119
119
|
userMsg.summary.title = result.text;
|
|
120
120
|
await Session.updateMessage(userMsg);
|
|
121
121
|
}
|
|
@@ -152,7 +152,7 @@ export namespace SessionSummary {
|
|
|
152
152
|
if (result) summary = result.text;
|
|
153
153
|
}
|
|
154
154
|
userMsg.summary.body = summary;
|
|
155
|
-
log.info('body',
|
|
155
|
+
log.info(() => ({ message: 'body', body: summary }));
|
|
156
156
|
await Session.updateMessage(userMsg);
|
|
157
157
|
}
|
|
158
158
|
}
|
package/src/snapshot/index.ts
CHANGED
|
@@ -28,7 +28,7 @@ export namespace Snapshot {
|
|
|
28
28
|
await $`git --git-dir ${git} config core.autocrlf false`
|
|
29
29
|
.quiet()
|
|
30
30
|
.nothrow();
|
|
31
|
-
log.info('initialized');
|
|
31
|
+
log.info(() => ({ message: 'initialized' }));
|
|
32
32
|
}
|
|
33
33
|
await $`git --git-dir ${git} --work-tree ${Instance.worktree} add .`
|
|
34
34
|
.quiet()
|
|
@@ -40,7 +40,12 @@ export namespace Snapshot {
|
|
|
40
40
|
.cwd(Instance.directory)
|
|
41
41
|
.nothrow()
|
|
42
42
|
.text();
|
|
43
|
-
log.info(
|
|
43
|
+
log.info(() => ({
|
|
44
|
+
message: 'tracking',
|
|
45
|
+
hash,
|
|
46
|
+
cwd: Instance.directory,
|
|
47
|
+
git,
|
|
48
|
+
}));
|
|
44
49
|
return hash.trim();
|
|
45
50
|
}
|
|
46
51
|
|
|
@@ -64,7 +69,11 @@ export namespace Snapshot {
|
|
|
64
69
|
|
|
65
70
|
// If git diff fails, return empty patch
|
|
66
71
|
if (result.exitCode !== 0) {
|
|
67
|
-
log.warn(
|
|
72
|
+
log.warn(() => ({
|
|
73
|
+
message: 'failed to get diff',
|
|
74
|
+
hash,
|
|
75
|
+
exitCode: result.exitCode,
|
|
76
|
+
}));
|
|
68
77
|
return { hash, files: [] };
|
|
69
78
|
}
|
|
70
79
|
|
|
@@ -81,7 +90,7 @@ export namespace Snapshot {
|
|
|
81
90
|
}
|
|
82
91
|
|
|
83
92
|
export async function restore(snapshot: string) {
|
|
84
|
-
log.info('restore',
|
|
93
|
+
log.info(() => ({ message: 'restore', commit: snapshot }));
|
|
85
94
|
const git = gitdir();
|
|
86
95
|
const result =
|
|
87
96
|
await $`git --git-dir ${git} --work-tree ${Instance.worktree} read-tree ${snapshot} && git --git-dir ${git} --work-tree ${Instance.worktree} checkout-index -a -f`
|
|
@@ -90,12 +99,13 @@ export namespace Snapshot {
|
|
|
90
99
|
.nothrow();
|
|
91
100
|
|
|
92
101
|
if (result.exitCode !== 0) {
|
|
93
|
-
log.error(
|
|
102
|
+
log.error(() => ({
|
|
103
|
+
message: 'failed to restore snapshot',
|
|
94
104
|
snapshot,
|
|
95
105
|
exitCode: result.exitCode,
|
|
96
106
|
stderr: result.stderr.toString(),
|
|
97
107
|
stdout: result.stdout.toString(),
|
|
98
|
-
});
|
|
108
|
+
}));
|
|
99
109
|
}
|
|
100
110
|
}
|
|
101
111
|
|
|
@@ -105,7 +115,7 @@ export namespace Snapshot {
|
|
|
105
115
|
for (const item of patches) {
|
|
106
116
|
for (const file of item.files) {
|
|
107
117
|
if (files.has(file)) continue;
|
|
108
|
-
log.info('reverting',
|
|
118
|
+
log.info(() => ({ message: 'reverting', file, hash: item.hash }));
|
|
109
119
|
const result =
|
|
110
120
|
await $`git --git-dir ${git} --work-tree ${Instance.worktree} checkout ${item.hash} -- ${file}`
|
|
111
121
|
.quiet()
|
|
@@ -119,11 +129,15 @@ export namespace Snapshot {
|
|
|
119
129
|
.cwd(Instance.worktree)
|
|
120
130
|
.nothrow();
|
|
121
131
|
if (checkTree.exitCode === 0 && checkTree.text().trim()) {
|
|
122
|
-
log.info(
|
|
132
|
+
log.info(() => ({
|
|
133
|
+
message: 'file existed in snapshot but checkout failed, keeping',
|
|
123
134
|
file,
|
|
124
|
-
});
|
|
135
|
+
}));
|
|
125
136
|
} else {
|
|
126
|
-
log.info(
|
|
137
|
+
log.info(() => ({
|
|
138
|
+
message: 'file did not exist in snapshot, deleting',
|
|
139
|
+
file,
|
|
140
|
+
}));
|
|
127
141
|
await fs.unlink(file).catch(() => {});
|
|
128
142
|
}
|
|
129
143
|
}
|
|
@@ -145,12 +159,13 @@ export namespace Snapshot {
|
|
|
145
159
|
.nothrow();
|
|
146
160
|
|
|
147
161
|
if (result.exitCode !== 0) {
|
|
148
|
-
log.warn(
|
|
162
|
+
log.warn(() => ({
|
|
163
|
+
message: 'failed to get diff',
|
|
149
164
|
hash,
|
|
150
165
|
exitCode: result.exitCode,
|
|
151
166
|
stderr: result.stderr.toString(),
|
|
152
167
|
stdout: result.stdout.toString(),
|
|
153
|
-
});
|
|
168
|
+
}));
|
|
154
169
|
return '';
|
|
155
170
|
}
|
|
156
171
|
|
package/src/storage/storage.ts
CHANGED
|
@@ -28,7 +28,7 @@ export namespace Storage {
|
|
|
28
28
|
cwd: project,
|
|
29
29
|
onlyFiles: false,
|
|
30
30
|
})) {
|
|
31
|
-
log.info(
|
|
31
|
+
log.info(() => ({ message: 'migrating project', projectDir }));
|
|
32
32
|
let projectID = projectDir;
|
|
33
33
|
const fullProjectDir = path.join(project, projectDir);
|
|
34
34
|
let worktree = '/';
|
|
@@ -74,7 +74,10 @@ export namespace Storage {
|
|
|
74
74
|
})
|
|
75
75
|
);
|
|
76
76
|
|
|
77
|
-
log.info(
|
|
77
|
+
log.info(() => ({
|
|
78
|
+
message: 'migrating sessions for project',
|
|
79
|
+
projectID,
|
|
80
|
+
}));
|
|
78
81
|
for await (const sessionFile of new Bun.Glob(
|
|
79
82
|
'storage/session/info/*.json'
|
|
80
83
|
).scan({
|
|
@@ -87,13 +90,13 @@ export namespace Storage {
|
|
|
87
90
|
projectID,
|
|
88
91
|
path.basename(sessionFile)
|
|
89
92
|
);
|
|
90
|
-
log.info('copying',
|
|
91
|
-
sessionFile,
|
|
92
|
-
dest,
|
|
93
|
-
});
|
|
93
|
+
log.info(() => ({ message: 'copying', sessionFile, dest }));
|
|
94
94
|
const session = await Bun.file(sessionFile).json();
|
|
95
95
|
await Bun.write(dest, JSON.stringify(session));
|
|
96
|
-
log.info(
|
|
96
|
+
log.info(() => ({
|
|
97
|
+
message: 'migrating messages for session',
|
|
98
|
+
sessionID: session.id,
|
|
99
|
+
}));
|
|
97
100
|
for await (const msgFile of new Bun.Glob(
|
|
98
101
|
`storage/session/message/${session.id}/*.json`
|
|
99
102
|
).scan({
|
|
@@ -106,14 +109,14 @@ export namespace Storage {
|
|
|
106
109
|
session.id,
|
|
107
110
|
path.basename(msgFile)
|
|
108
111
|
);
|
|
109
|
-
log.info('copying',
|
|
110
|
-
msgFile,
|
|
111
|
-
dest,
|
|
112
|
-
});
|
|
112
|
+
log.info(() => ({ message: 'copying', msgFile, dest }));
|
|
113
113
|
const message = await Bun.file(msgFile).json();
|
|
114
114
|
await Bun.write(dest, JSON.stringify(message));
|
|
115
115
|
|
|
116
|
-
log.info(
|
|
116
|
+
log.info(() => ({
|
|
117
|
+
message: 'migrating parts for message',
|
|
118
|
+
messageID: message.id,
|
|
119
|
+
}));
|
|
117
120
|
for await (const partFile of new Bun.Glob(
|
|
118
121
|
`storage/session/part/${session.id}/${message.id}/*.json`
|
|
119
122
|
).scan({
|
|
@@ -127,10 +130,7 @@ export namespace Storage {
|
|
|
127
130
|
path.basename(partFile)
|
|
128
131
|
);
|
|
129
132
|
const part = await Bun.file(partFile).json();
|
|
130
|
-
log.info('copying',
|
|
131
|
-
partFile,
|
|
132
|
-
dest,
|
|
133
|
-
});
|
|
133
|
+
log.info(() => ({ message: 'copying', partFile, dest }));
|
|
134
134
|
await Bun.write(dest, JSON.stringify(part));
|
|
135
135
|
}
|
|
136
136
|
}
|
|
@@ -178,10 +178,10 @@ export namespace Storage {
|
|
|
178
178
|
.then((x) => parseInt(x))
|
|
179
179
|
.catch(() => 0);
|
|
180
180
|
for (let index = migration; index < MIGRATIONS.length; index++) {
|
|
181
|
-
log.info('running migration',
|
|
181
|
+
log.info(() => ({ message: 'running migration', index }));
|
|
182
182
|
const migration = MIGRATIONS[index];
|
|
183
183
|
await migration(dir).catch(() =>
|
|
184
|
-
log.error('failed to run migration',
|
|
184
|
+
log.error(() => ({ message: 'failed to run migration', index }))
|
|
185
185
|
);
|
|
186
186
|
await Bun.write(path.join(dir, 'migration'), (index + 1).toString());
|
|
187
187
|
}
|