@stack-spot/portal-network 0.149.0 → 0.150.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.
Files changed (55) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/api/agent-tools.d.ts +63 -2
  3. package/dist/api/agent-tools.d.ts.map +1 -1
  4. package/dist/api/agent-tools.js +55 -0
  5. package/dist/api/agent-tools.js.map +1 -1
  6. package/dist/api/agent.d.ts +30 -16
  7. package/dist/api/agent.d.ts.map +1 -1
  8. package/dist/api/agent.js +0 -18
  9. package/dist/api/agent.js.map +1 -1
  10. package/dist/client/agent-tools.d.ts +20 -6
  11. package/dist/client/agent-tools.d.ts.map +1 -1
  12. package/dist/client/agent-tools.js +21 -18
  13. package/dist/client/agent-tools.js.map +1 -1
  14. package/dist/client/agent.d.ts +8 -14
  15. package/dist/client/agent.d.ts.map +1 -1
  16. package/dist/client/agent.js +2 -10
  17. package/dist/client/agent.js.map +1 -1
  18. package/dist/client/ai.d.ts +6 -6
  19. package/dist/client/ai.d.ts.map +1 -1
  20. package/dist/client/ai.js +6 -6
  21. package/dist/client/ai.js.map +1 -1
  22. package/dist/client/secrets.d.ts +2 -2
  23. package/dist/client/secrets.d.ts.map +1 -1
  24. package/dist/client/secrets.js +2 -2
  25. package/dist/client/secrets.js.map +1 -1
  26. package/dist/index.d.ts +3 -0
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +2 -0
  29. package/dist/index.js.map +1 -1
  30. package/dist/types.d.ts +2 -0
  31. package/dist/types.d.ts.map +1 -0
  32. package/dist/types.js +2 -0
  33. package/dist/types.js.map +1 -0
  34. package/dist/utils/StreamedArray.d.ts +66 -0
  35. package/dist/utils/StreamedArray.d.ts.map +1 -0
  36. package/dist/utils/StreamedArray.js +148 -0
  37. package/dist/utils/StreamedArray.js.map +1 -0
  38. package/dist/utils/StreamedJson.d.ts +1 -1
  39. package/dist/utils/StreamedJson.d.ts.map +1 -1
  40. package/dist/utils/use-streamed-array.d.ts +4 -0
  41. package/dist/utils/use-streamed-array.d.ts.map +1 -0
  42. package/dist/utils/use-streamed-array.js +15 -0
  43. package/dist/utils/use-streamed-array.js.map +1 -0
  44. package/package.json +1 -1
  45. package/src/api/agent-tools.ts +130 -2
  46. package/src/api/agent.ts +30 -84
  47. package/src/client/agent-tools.ts +16 -17
  48. package/src/client/agent.ts +6 -6
  49. package/src/client/ai.ts +6 -6
  50. package/src/client/secrets.ts +2 -2
  51. package/src/index.ts +3 -1
  52. package/src/types.ts +1 -0
  53. package/src/utils/StreamedArray.tsx +146 -0
  54. package/src/utils/StreamedJson.tsx +1 -1
  55. package/src/utils/use-streamed-array.ts +17 -0
package/src/client/ai.ts CHANGED
@@ -220,20 +220,20 @@ class AIClient extends ReactQueryNetworkClient {
220
220
  */
221
221
  addFavoriteStackAi = this.mutation(removeAuthorizationParam(addFavoriteV1AiStacksStackIdFavoritePost))
222
222
  /**
223
- * Removes the resource of type Stack AI from the list of favorites.
224
- */
223
+ * Removes the resource of type Stack AI from the list of favorites.
224
+ */
225
225
  removeFavoriteStackAi = this.mutation(removeAuthorizationParam(deleteFavoriteV1AiStacksStackIdFavoriteDelete))
226
226
  /**
227
- * Updates a Quick Command
228
- */
227
+ * Updates a Quick Command
228
+ */
229
229
  updateQuickCommand = this.mutation(removeAuthorizationParam(updateQuickCommandV1QuickCommandsSlugPatch))
230
230
  /**
231
231
  * Adds the resource of type Quick Command to the list of favorites.
232
232
  */
233
233
  addFavoriteQuickCommand = this.mutation(removeAuthorizationParam(addFavoriteV1QuickCommandsSlugFavoritePost))
234
234
  /**
235
- * Removes the resource of type Quick Command from the list of favorites.
236
- */
235
+ * Removes the resource of type Quick Command from the list of favorites.
236
+ */
237
237
  removeFavoriteQuickCommand = this.mutation(removeAuthorizationParam(deleteFavoriteV1QuickCommandsSlugFavoriteDelete))
238
238
 
239
239
  private static async toolsOfAgent(agentId?: string) {
@@ -52,8 +52,8 @@ class SecretClient extends ReactQueryNetworkClient {
52
52
  deleteSecretValue = this.mutation(deleteSecretValue)
53
53
 
54
54
  /**
55
- * Encrypt a value
56
- */
55
+ * Encrypt a value
56
+ */
57
57
  encrypt = this.mutation(encrypt)
58
58
  }
59
59
 
package/src/index.ts CHANGED
@@ -35,6 +35,8 @@ export { StreamJsonError } from './error/StreamJsonError'
35
35
  export { NetworkClient } from './network/NetworkClient'
36
36
  export { queryClient } from './network/react-query-client'
37
37
  export { OperationResult, OperationVariables, UseQueryObjectOptions } from './network/types'
38
+ export { StreamingStatus } from './types'
39
+ export { StreamedArray } from './utils/StreamedArray'
38
40
  export { StreamedJson } from './utils/StreamedJson'
39
41
  export { useExtendedList } from './utils/use-extended-list'
40
-
42
+ export { useStreamedArray } from './utils/use-streamed-array'
package/src/types.ts ADDED
@@ -0,0 +1 @@
1
+ export type StreamingStatus = 'pending' | 'success' | 'error'
@@ -0,0 +1,146 @@
1
+ import { CompletablePromise } from '@stack-spot/opa'
2
+ import { StreamCanceledError } from '../error/StreamCanceledError'
3
+ import { StreamError } from '../error/StreamError'
4
+ import { StreamJsonError } from '../error/StreamJsonError'
5
+ import { FetchEventStream } from '../network/types'
6
+ import { StreamingStatus } from '../types'
7
+
8
+ type OnChangeListener<T> = (value: T[]) => void
9
+
10
+ interface ConstructorParams {
11
+ /**
12
+ * The promises that result in the EventStreams to build the final array.
13
+ */
14
+ eventsPromises: Promise<FetchEventStream>[],
15
+ /**
16
+ * A controller to abort the streaming.
17
+ */
18
+ abortController?: AbortController,
19
+ /**
20
+ * A minimum number of milliseconds to wait before calling onChange listeners.
21
+ * @default 50
22
+ */
23
+ minChangeIntervalMS?: number,
24
+ /***
25
+ * Aborts this stream when the signal is aborted.
26
+ */
27
+ signal?: AbortSignal,
28
+ }
29
+
30
+ /**
31
+ * An array represented by a stream where each event contains an item of the array as a JSON string. This can be watched as the stream runs.
32
+ */
33
+ export class StreamedArray<T> {
34
+ private onChangeListeners: OnChangeListener<T>[] = []
35
+ private error: StreamError | undefined
36
+ private data: T[] = []
37
+ private fullPromise = new CompletablePromise<T[]>()
38
+ private abortController: AbortController | undefined
39
+
40
+ /**
41
+ * @param response the fetch response.
42
+ * @param minChangeIntervalMS a stream can be too fast. This sets a minimum interval between running the listeners. The default is 50ms.
43
+ */
44
+ constructor({ eventsPromises, abortController, minChangeIntervalMS = 50, signal }: ConstructorParams) {
45
+ this.abortController = abortController ?? new AbortController()
46
+ eventsPromises.forEach(eventsPromise => this.run(eventsPromise, minChangeIntervalMS))
47
+ if (signal) {
48
+ signal.addEventListener('abort', () => this.cancel())
49
+ }
50
+ }
51
+
52
+ private async run(eventsPromise: Promise<FetchEventStream>, minChangeIntervalMS: number) {
53
+ let lastChangeCall = 0
54
+ try {
55
+ const events = await eventsPromise
56
+ let flushed = true
57
+ for await (const event of events) {
58
+ if (this.error) return
59
+ if (event.data) {
60
+ this.data.push(JSON.parse(event.data))
61
+ if (new Date().getTime() - lastChangeCall >= minChangeIntervalMS) {
62
+ this.onChangeListeners.forEach(l => l(this.data))
63
+ lastChangeCall = new Date().getTime()
64
+ flushed = true
65
+ } else {
66
+ flushed = false
67
+ }
68
+ }
69
+ }
70
+ if (!flushed) this.onChangeListeners.forEach(l => l(this.data))
71
+ } catch (error: any) {
72
+ if (error instanceof DOMException && error.name === 'AbortError') this.fail(new StreamCanceledError())
73
+ if (error instanceof SyntaxError) this.fail(new StreamJsonError())
74
+ else if (error instanceof StreamError) this.fail(error)
75
+ else this.fail(new StreamError(error?.message || `${error}`))
76
+ }
77
+ if (!this.error) this.complete()
78
+ }
79
+
80
+ private clear() {
81
+ this.onChangeListeners = []
82
+ this.abortController = undefined
83
+ }
84
+
85
+ private fail(error: any) {
86
+ this.error = error
87
+ this.fullPromise.reject(this.error)
88
+ this.clear()
89
+ }
90
+
91
+ private complete() {
92
+ this.fullPromise.resolve(this.data)
93
+ this.clear()
94
+ }
95
+
96
+ /**
97
+ * Returns the full value of the array once the stream finishes.
98
+ */
99
+ getValue(): Promise<T[]> {
100
+ return this.fullPromise.promise
101
+ }
102
+
103
+ /**
104
+ * Returns the streamed array with every item streamed until now. This will be the complete array if the stream has finished.
105
+ */
106
+ getPartialValue(): T[] {
107
+ return this.data
108
+ }
109
+
110
+ /**
111
+ * Watches the array as it's streamed. This doesn't wait for the value to be complete.
112
+ *
113
+ * The listener is called whenever the value changes.
114
+ *
115
+ * @param listener the function to call with the new value.
116
+ * @returns a function that, when called, removes the listener.
117
+ */
118
+ onChange(listener: (value: T[]) => void) {
119
+ if (this.fullPromise.resolved) {
120
+ listener(this.data)
121
+ return () => {}
122
+ }
123
+ this.onChangeListeners.push(listener)
124
+ return () => {
125
+ const index = this.onChangeListeners?.findIndex(l => l === listener)
126
+ if (index !== undefined && index >= 0) this.onChangeListeners?.splice(index, 1)
127
+ }
128
+ }
129
+
130
+ getStatus(): StreamingStatus {
131
+ if (this.error) return 'error'
132
+ if (this.fullPromise.resolved) return 'success'
133
+ return 'pending'
134
+ }
135
+
136
+ getError() {
137
+ return this.error
138
+ }
139
+
140
+ /**
141
+ * If this is a stream and it's not yet finished, calling this function cancels the stream.
142
+ */
143
+ cancel() {
144
+ this.abortController?.abort(new StreamCanceledError())
145
+ }
146
+ }
@@ -3,8 +3,8 @@ import { StreamCanceledError } from '../error/StreamCanceledError'
3
3
  import { StreamError } from '../error/StreamError'
4
4
  import { StreamJsonError } from '../error/StreamJsonError'
5
5
  import { FetchEventStream } from '../network/types'
6
+ import { StreamingStatus } from '../types'
6
7
 
7
- type StreamingStatus = 'pending' | 'success' | 'error'
8
8
  type OnChangeListener<T> = (value: Partial<T>) => void
9
9
 
10
10
  interface ConstructorParams<T> {
@@ -0,0 +1,17 @@
1
+ import { useEffect, useState } from 'react'
2
+ import { StreamingStatus } from '../types'
3
+ import { StreamedArray } from './StreamedArray'
4
+
5
+ export function useStreamedArray<T>(stream: StreamedArray<T> | undefined) {
6
+ const [array, setArray] = useState<T[]>(stream?.getPartialValue() ?? [])
7
+ const [status, setStatus] = useState<StreamingStatus>(stream?.getStatus() ?? 'pending')
8
+ useEffect(() => {
9
+ setArray(stream?.getPartialValue() ?? [])
10
+ setStatus(stream?.getStatus() ?? 'pending')
11
+ return stream?.onChange((values) => {
12
+ setArray(values)
13
+ setStatus(stream.getStatus())
14
+ })
15
+ }, [stream])
16
+ return [array, status]
17
+ }