@kapeta/local-cluster-service 0.73.0 → 0.74.1

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.
@@ -3,9 +3,9 @@ import { glob } from 'glob';
3
3
  import { filesystemManager } from './filesystemManager';
4
4
  import path from 'path';
5
5
  import { existsSync } from 'fs';
6
- import { StormEvent, StormEventPromptImprove, StormEventUIShell } from './storm/events';
6
+ import { StormEvent, StormEventModelResponse, StormEventPromptImprove, StormEventUIShell } from './storm/events';
7
7
  import * as tar from 'tar';
8
- import { stormClient } from './storm/stormClient';
8
+ import { StormClient } from './storm/stormClient';
9
9
 
10
10
  export class StormService {
11
11
  private getConversationFile(conversationId: string) {
@@ -28,39 +28,61 @@ export class StormService {
28
28
  absolute: true,
29
29
  });
30
30
  // Returns list of UUIDs - probably want to make it more useful than that
31
- const conversations: { id: string; description: string; title: string }[] = [];
31
+ const conversations: { id: string; description: string; title: string; url?: string }[] = [];
32
32
  for (const file of eventFiles) {
33
- const nldContents = await fs.readFile(file as string, 'utf8');
34
- const events = nldContents.split('\n').map((e) => JSON.parse(e)) as {
35
- // | { type: 'USER'; event: any } // IS stupid!
36
- type: 'AI';
37
- systemId: string;
38
- event: StormEvent;
39
- }[];
40
- // find the shell and get the title tag
41
- const shellEvent = events.find((e) => e.type === 'AI' && e.event.type === 'UI_SHELL')?.event as
42
- | StormEventUIShell
43
- | undefined;
44
- const html = shellEvent?.payload.content;
45
- const title = html?.match(/<title>(.*?)<\/title>/)?.[1];
46
- const id = events.find((e) => e.type === 'AI')?.systemId;
47
-
48
- const initialPrompt =
49
- (
50
- events.find((e) => e.type === 'AI' && e.event.type === 'PROMPT_IMPROVE')?.event as
51
- | StormEventPromptImprove
52
- | undefined
53
- )?.payload?.prompt || (events[0] as any).text;
54
-
55
- if (!id) {
56
- continue;
33
+ try {
34
+ const nldContents = await fs.readFile(file as string, 'utf8');
35
+ const events = nldContents.split('\n').map((e) => JSON.parse(e)) as {
36
+ // | { type: 'USER'; event: any } // IS stupid!
37
+ type: 'AI';
38
+ systemId: string;
39
+ event: StormEvent;
40
+ reason: string;
41
+ }[];
42
+ // find the shell and get the title tag
43
+ const shellEvent = events.find((e) => e.type === 'AI' && e.event.type === 'UI_SHELL')?.event as
44
+ | StormEventUIShell
45
+ | undefined;
46
+ const html = shellEvent?.payload.content;
47
+ const title = html?.match(/<title>(.*?)<\/title>/)?.[1];
48
+ const id = events.find((e) => e.type === 'AI')?.systemId;
49
+
50
+ const initialPrompt =
51
+ (
52
+ events.find((e) => e.type === 'AI' && e.event.type === 'PROMPT_IMPROVE')?.event as
53
+ | StormEventPromptImprove
54
+ | undefined
55
+ )?.payload?.prompt || (events[0] as any).text;
56
+
57
+ if (!id) {
58
+ continue;
59
+ }
60
+
61
+ let url = undefined;
62
+ // Find the last model response event that has a URL in the payload (in case it changed over time)
63
+ for (const evt of [...events].reverse()) {
64
+ const event = evt.event;
65
+ if (evt.type === 'AI' && event.type === 'MODEL_RESPONSE') {
66
+ // Look for a URL in the model response markdown
67
+ const regex = /\[(.*?)\]\((.*?)\)/g;
68
+ const match = regex.exec(event.payload.text);
69
+ const [, _linkText, linkUrl] = match || [];
70
+ if (linkUrl?.startsWith('http')) {
71
+ url = linkUrl;
72
+ break;
73
+ }
74
+ }
75
+ }
76
+
77
+ conversations.push({
78
+ id,
79
+ description: initialPrompt,
80
+ title: title || 'New system',
81
+ url,
82
+ });
83
+ } catch (e) {
84
+ console.error('Failed to load conversation at %s', file, e);
57
85
  }
58
-
59
- conversations.push({
60
- id,
61
- description: initialPrompt,
62
- title: title || 'New system',
63
- });
64
86
  }
65
87
 
66
88
  return conversations;
@@ -96,8 +118,8 @@ export class StormService {
96
118
  }
97
119
  }
98
120
 
99
- async uploadConversation(handle: string, conversationId: string) {
100
- const tarballFile = this.getConversationTarball(conversationId);
121
+ async uploadConversation(handle: string, systemId: string) {
122
+ const tarballFile = this.getConversationTarball(systemId);
101
123
  const destDir = path.dirname(tarballFile);
102
124
  const tarballName = path.basename(tarballFile);
103
125
  await tar.create(
@@ -109,13 +131,15 @@ export class StormService {
109
131
  },
110
132
  ['.']
111
133
  );
112
- await stormClient.uploadSystem(handle, conversationId, await fs.readFile(tarballFile));
134
+ const stormClient = new StormClient(systemId);
135
+ await stormClient.uploadSystem(handle, systemId, await fs.readFile(tarballFile));
113
136
  }
114
137
 
115
- async installProjectById(handle: string, conversationId: string) {
116
- const tarballFile = this.getConversationTarball(conversationId);
138
+ async installProjectById(handle: string, systemId: string) {
139
+ const tarballFile = this.getConversationTarball(systemId);
117
140
  const destDir = path.dirname(tarballFile);
118
- const buffer = await stormClient.downloadSystem(handle, conversationId);
141
+ const stormClient = new StormClient(systemId);
142
+ const buffer = await stormClient.downloadSystem(handle, systemId);
119
143
  await fs.mkdir(destDir, { recursive: true });
120
144
  await fs.writeFile(tarballFile, buffer);
121
145
  await tar.extract({