@pikku/core 0.10.1 → 0.10.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/CHANGELOG.md +38 -0
- package/dist/function/function-runner.js +2 -2
- package/dist/services/file-channel-store.d.ts +19 -0
- package/dist/services/file-channel-store.js +69 -0
- package/dist/services/file-eventhub-store.d.ts +17 -0
- package/dist/services/file-eventhub-store.js +71 -0
- package/dist/wirings/channel/channel-common.d.ts +28 -0
- package/dist/wirings/channel/channel-common.js +42 -0
- package/dist/wirings/channel/channel-handler.js +37 -11
- package/dist/wirings/channel/channel-runner.js +9 -4
- package/dist/wirings/channel/channel.types.d.ts +8 -2
- package/dist/wirings/channel/local/local-channel-handler.js +3 -0
- package/dist/wirings/channel/local/local-channel-runner.js +47 -14
- package/dist/wirings/channel/serverless/serverless-channel-runner.js +90 -41
- package/dist/wirings/cli/channel/cli-channel-runner.js +9 -0
- package/dist/wirings/cli/cli-runner.d.ts +1 -1
- package/dist/wirings/http/http-runner.js +0 -1
- package/dist/wirings/mcp/mcp-runner.js +3 -2
- package/dist/wirings/rpc/rpc-runner.d.ts +11 -0
- package/dist/wirings/rpc/rpc-runner.js +1 -1
- package/package.json +3 -3
- package/src/function/function-runner.ts +2 -2
- package/src/services/file-channel-store.ts +86 -0
- package/src/services/file-eventhub-store.ts +90 -0
- package/src/wirings/channel/channel-common.ts +80 -0
- package/src/wirings/channel/channel-handler.ts +48 -18
- package/src/wirings/channel/channel-runner.ts +15 -4
- package/src/wirings/channel/channel.types.ts +12 -2
- package/src/wirings/channel/local/local-channel-handler.ts +3 -0
- package/src/wirings/channel/local/local-channel-runner.ts +48 -36
- package/src/wirings/channel/serverless/serverless-channel-runner.ts +134 -66
- package/src/wirings/cli/channel/cli-channel-runner.ts +12 -0
- package/src/wirings/cli/cli-runner.ts +1 -1
- package/src/wirings/http/http-runner.ts +0 -2
- package/src/wirings/mcp/mcp-runner.ts +5 -2
- package/src/wirings/rpc/rpc-runner.ts +1 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -56,7 +56,12 @@ export const wireChannel = <
|
|
|
56
56
|
|
|
57
57
|
// Register onMessage function if provided
|
|
58
58
|
if (channel.onMessage && channelMeta.message?.pikkuFuncName) {
|
|
59
|
-
addFunction(
|
|
59
|
+
addFunction(
|
|
60
|
+
channelMeta.message.pikkuFuncName,
|
|
61
|
+
(channel.onMessage as any).func instanceof Function
|
|
62
|
+
? channel.onMessage
|
|
63
|
+
: (channel.onMessage as any).func
|
|
64
|
+
)
|
|
60
65
|
}
|
|
61
66
|
|
|
62
67
|
// Register functions in onMessageWiring
|
|
@@ -72,7 +77,13 @@ export const wireChannel = <
|
|
|
72
77
|
if (!wiringMeta) return
|
|
73
78
|
|
|
74
79
|
// Register the function using the pikku name from metadata
|
|
75
|
-
|
|
80
|
+
// It could be a FuncConfig or a wiring override with a funcConfig
|
|
81
|
+
addFunction(
|
|
82
|
+
wiringMeta.pikkuFuncName,
|
|
83
|
+
(handler as any).func instanceof Function
|
|
84
|
+
? handler
|
|
85
|
+
: (handler as any).func
|
|
86
|
+
)
|
|
76
87
|
})
|
|
77
88
|
})
|
|
78
89
|
}
|
|
@@ -81,8 +92,8 @@ export const wireChannel = <
|
|
|
81
92
|
pikkuState('channel', 'channels').set(channel.name, channel as any)
|
|
82
93
|
}
|
|
83
94
|
|
|
84
|
-
const getMatchingChannelConfig = (
|
|
85
|
-
const matchedPath = httpRouter.match('get',
|
|
95
|
+
const getMatchingChannelConfig = (path: string) => {
|
|
96
|
+
const matchedPath = httpRouter.match('get', path)
|
|
86
97
|
if (!matchedPath) {
|
|
87
98
|
return null
|
|
88
99
|
}
|
|
@@ -88,8 +88,18 @@ export type CoreChannel<
|
|
|
88
88
|
> = {
|
|
89
89
|
name: string
|
|
90
90
|
route: Channel
|
|
91
|
-
onConnect?:
|
|
92
|
-
|
|
91
|
+
onConnect?:
|
|
92
|
+
| ChannelConnect
|
|
93
|
+
| {
|
|
94
|
+
func?: ChannelConnect
|
|
95
|
+
middleware?: PikkuMiddleware[]
|
|
96
|
+
}
|
|
97
|
+
onDisconnect?:
|
|
98
|
+
| ChannelDisconnect
|
|
99
|
+
| {
|
|
100
|
+
func?: ChannelDisconnect
|
|
101
|
+
middleware?: PikkuMiddleware[]
|
|
102
|
+
}
|
|
93
103
|
onMessage?: ChannelFunctionMessage
|
|
94
104
|
onMessageWiring?: Record<
|
|
95
105
|
string,
|
|
@@ -8,17 +8,12 @@ import {
|
|
|
8
8
|
RunChannelParams,
|
|
9
9
|
} from '../channel.types.js'
|
|
10
10
|
import { PikkuLocalChannelHandler } from './local-channel-handler.js'
|
|
11
|
-
import {
|
|
12
|
-
PikkuInteraction,
|
|
13
|
-
PikkuWiringTypes,
|
|
14
|
-
SessionServices,
|
|
15
|
-
} from '../../../types/core.types.js'
|
|
11
|
+
import { PikkuInteraction, SessionServices } from '../../../types/core.types.js'
|
|
16
12
|
import { handleHTTPError } from '../../../handle-error.js'
|
|
17
|
-
import { combineMiddleware, runMiddleware } from '../../../middleware-runner.js'
|
|
18
13
|
import { PikkuUserSessionService } from '../../../services/user-session-service.js'
|
|
19
14
|
import { PikkuHTTP } from '../../http/http.types.js'
|
|
20
|
-
import { runPikkuFuncDirectly } from '../../../function/function-runner.js'
|
|
21
15
|
import { rpcService } from '../../rpc/rpc-runner.js'
|
|
16
|
+
import { runChannelLifecycleWithMiddleware } from '../channel-common.js'
|
|
22
17
|
|
|
23
18
|
export const runLocalChannel = async ({
|
|
24
19
|
singletonServices,
|
|
@@ -95,6 +90,7 @@ export const runLocalChannel = async ({
|
|
|
95
90
|
{
|
|
96
91
|
...singletonServices,
|
|
97
92
|
...sessionServices,
|
|
93
|
+
channel,
|
|
98
94
|
userSession,
|
|
99
95
|
},
|
|
100
96
|
interaction,
|
|
@@ -103,23 +99,43 @@ export const runLocalChannel = async ({
|
|
|
103
99
|
|
|
104
100
|
const interaction: PikkuInteraction = { channel }
|
|
105
101
|
|
|
106
|
-
channelHandler.registerOnOpen(() => {
|
|
102
|
+
channelHandler.registerOnOpen(async () => {
|
|
107
103
|
if (channelConfig.onConnect && meta.connect) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
104
|
+
try {
|
|
105
|
+
const result = await runChannelLifecycleWithMiddleware({
|
|
106
|
+
channelConfig,
|
|
107
|
+
meta: meta.connect,
|
|
108
|
+
lifecycleConfig: channelConfig.onConnect,
|
|
109
|
+
lifecycleType: 'connect',
|
|
110
|
+
services: getAllServices(channel, false),
|
|
111
|
+
channel,
|
|
112
|
+
data: openingData,
|
|
113
|
+
})
|
|
114
|
+
if (result !== undefined) {
|
|
115
|
+
await channel.send(result)
|
|
116
|
+
}
|
|
117
|
+
} catch (e) {
|
|
118
|
+
singletonServices.logger.error(`Error handling onConnect: ${e}`)
|
|
119
|
+
channel.send({ error: e.message || 'Unknown error' })
|
|
120
|
+
}
|
|
113
121
|
}
|
|
114
122
|
})
|
|
115
123
|
|
|
116
124
|
channelHandler.registerOnClose(async () => {
|
|
117
125
|
if (channelConfig.onDisconnect && meta.disconnect) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
126
|
+
try {
|
|
127
|
+
await runChannelLifecycleWithMiddleware({
|
|
128
|
+
channelConfig,
|
|
129
|
+
meta: meta.disconnect,
|
|
130
|
+
lifecycleConfig: channelConfig.onDisconnect,
|
|
131
|
+
lifecycleType: 'disconnect',
|
|
132
|
+
services: getAllServices(channel, false),
|
|
133
|
+
channel,
|
|
134
|
+
})
|
|
135
|
+
} catch (e) {
|
|
136
|
+
singletonServices.logger.error(`Error handling onDisconnect: ${e}`)
|
|
137
|
+
channel.send({ error: e.message || 'Unknown error' })
|
|
138
|
+
}
|
|
123
139
|
}
|
|
124
140
|
|
|
125
141
|
if (sessionServices) {
|
|
@@ -127,13 +143,20 @@ export const runLocalChannel = async ({
|
|
|
127
143
|
}
|
|
128
144
|
})
|
|
129
145
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
channelHandler
|
|
135
|
-
)
|
|
146
|
+
const onMessage = processMessageHandlers(
|
|
147
|
+
getAllServices(channel),
|
|
148
|
+
channelConfig as any,
|
|
149
|
+
channelHandler
|
|
136
150
|
)
|
|
151
|
+
channelHandler.registerOnMessage(async (data) => {
|
|
152
|
+
try {
|
|
153
|
+
const result = await onMessage(data)
|
|
154
|
+
await channel.send(result)
|
|
155
|
+
} catch (e) {
|
|
156
|
+
singletonServices.logger.error(`Error handling message: ${e.message}`)
|
|
157
|
+
channel.send({ error: e.message || 'Unknown error' })
|
|
158
|
+
}
|
|
159
|
+
})
|
|
137
160
|
} catch (e: any) {
|
|
138
161
|
handleHTTPError(
|
|
139
162
|
e,
|
|
@@ -151,18 +174,7 @@ export const runLocalChannel = async ({
|
|
|
151
174
|
}
|
|
152
175
|
}
|
|
153
176
|
|
|
154
|
-
await
|
|
155
|
-
{
|
|
156
|
-
...singletonServices,
|
|
157
|
-
userSession,
|
|
158
|
-
},
|
|
159
|
-
{ http },
|
|
160
|
-
combineMiddleware(PikkuWiringTypes.channel, channelConfig.name, {
|
|
161
|
-
wireInheritedMiddleware: meta.middleware,
|
|
162
|
-
wireMiddleware: channelConfig.middleware,
|
|
163
|
-
}),
|
|
164
|
-
main
|
|
165
|
-
)
|
|
177
|
+
await main()
|
|
166
178
|
|
|
167
179
|
return channelHandler
|
|
168
180
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PikkuInteraction, SessionServices } from '../../../types/core.types.js'
|
|
2
2
|
import { closeSessionServices } from '../../../utils.js'
|
|
3
3
|
import { processMessageHandlers } from '../channel-handler.js'
|
|
4
4
|
import { openChannel } from '../channel-runner.js'
|
|
@@ -12,11 +12,11 @@ import { createHTTPInteraction } from '../../http/http-runner.js'
|
|
|
12
12
|
import { ChannelStore } from '../channel-store.js'
|
|
13
13
|
import { handleHTTPError } from '../../../handle-error.js'
|
|
14
14
|
import { PikkuUserSessionService } from '../../../services/user-session-service.js'
|
|
15
|
-
import { combineMiddleware, runMiddleware } from '../../../middleware-runner.js'
|
|
16
15
|
import { pikkuState } from '../../../pikku-state.js'
|
|
17
16
|
import { PikkuFetchHTTPRequest } from '../../http/pikku-fetch-http-request.js'
|
|
18
17
|
import { PikkuHTTP } from '../../http/http.types.js'
|
|
19
|
-
import {
|
|
18
|
+
import { runChannelLifecycleWithMiddleware } from '../channel-common.js'
|
|
19
|
+
import { rpcService } from '../../rpc/rpc-runner.js'
|
|
20
20
|
|
|
21
21
|
export interface RunServerlessChannelParams<ChannelData>
|
|
22
22
|
extends RunChannelParams<ChannelData> {
|
|
@@ -37,7 +37,7 @@ const getVariablesForChannel = ({
|
|
|
37
37
|
openingData?: unknown
|
|
38
38
|
}) => {
|
|
39
39
|
const channels = pikkuState('channel', 'channels')
|
|
40
|
-
const channelConfig = channels
|
|
40
|
+
const channelConfig = channels.get(channelName)
|
|
41
41
|
const channelsMeta = pikkuState('channel', 'meta')
|
|
42
42
|
const meta = channelsMeta[channelName]
|
|
43
43
|
if (!channelConfig) {
|
|
@@ -95,63 +95,66 @@ export const runChannelConnect = async ({
|
|
|
95
95
|
userSession,
|
|
96
96
|
})
|
|
97
97
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
await userSession.get()
|
|
116
|
-
)
|
|
117
|
-
}
|
|
118
|
-
if (channelConfig.onConnect && meta.connect) {
|
|
119
|
-
await runPikkuFuncDirectly(
|
|
120
|
-
meta.connect.pikkuFuncName,
|
|
121
|
-
{ ...singletonServices, ...sessionServices, channel },
|
|
122
|
-
openingData
|
|
123
|
-
)
|
|
124
|
-
}
|
|
125
|
-
http?.response?.status(101)
|
|
126
|
-
} catch (e: any) {
|
|
127
|
-
handleHTTPError(
|
|
128
|
-
e,
|
|
129
|
-
http,
|
|
130
|
-
channelId,
|
|
131
|
-
singletonServices.logger,
|
|
132
|
-
logWarningsForStatusCodes,
|
|
133
|
-
respondWith404,
|
|
134
|
-
bubbleErrors
|
|
98
|
+
try {
|
|
99
|
+
await channelStore.addChannel({
|
|
100
|
+
channelId,
|
|
101
|
+
channelName: channelConfig.name,
|
|
102
|
+
openingData,
|
|
103
|
+
channelObject,
|
|
104
|
+
})
|
|
105
|
+
const { channel } = getVariablesForChannel({
|
|
106
|
+
channelId,
|
|
107
|
+
channelHandlerFactory,
|
|
108
|
+
channelName: channelConfig.name,
|
|
109
|
+
})
|
|
110
|
+
if (createSessionServices) {
|
|
111
|
+
sessionServices = await createSessionServices(
|
|
112
|
+
singletonServices,
|
|
113
|
+
{ http },
|
|
114
|
+
await userSession.get()
|
|
135
115
|
)
|
|
136
|
-
} finally {
|
|
137
|
-
if (sessionServices) {
|
|
138
|
-
await closeSessionServices(singletonServices.logger, sessionServices)
|
|
139
|
-
}
|
|
140
116
|
}
|
|
141
|
-
}
|
|
142
117
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
118
|
+
const interaction: PikkuInteraction = { channel }
|
|
119
|
+
const getAllServices = (requiresAuth?: boolean) =>
|
|
120
|
+
rpcService.injectRPCService(
|
|
121
|
+
{
|
|
122
|
+
...singletonServices,
|
|
123
|
+
...sessionServices,
|
|
124
|
+
channel,
|
|
125
|
+
userSession,
|
|
126
|
+
},
|
|
127
|
+
interaction,
|
|
128
|
+
requiresAuth
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
if (channelConfig.onConnect && meta.connect) {
|
|
132
|
+
await runChannelLifecycleWithMiddleware({
|
|
133
|
+
channelConfig,
|
|
134
|
+
meta: meta.connect,
|
|
135
|
+
lifecycleConfig: channelConfig.onConnect,
|
|
136
|
+
lifecycleType: 'connect',
|
|
137
|
+
services: getAllServices(false),
|
|
138
|
+
channel,
|
|
139
|
+
data: openingData,
|
|
140
|
+
})
|
|
141
|
+
}
|
|
142
|
+
http?.response?.status(101)
|
|
143
|
+
} catch (e: any) {
|
|
144
|
+
handleHTTPError(
|
|
145
|
+
e,
|
|
146
|
+
http,
|
|
147
|
+
channelId,
|
|
148
|
+
singletonServices.logger,
|
|
149
|
+
logWarningsForStatusCodes,
|
|
150
|
+
respondWith404,
|
|
151
|
+
bubbleErrors
|
|
152
|
+
)
|
|
153
|
+
} finally {
|
|
154
|
+
if (sessionServices) {
|
|
155
|
+
await closeSessionServices(singletonServices.logger, sessionServices)
|
|
156
|
+
}
|
|
157
|
+
}
|
|
155
158
|
}
|
|
156
159
|
|
|
157
160
|
export const runChannelDisconnect = async ({
|
|
@@ -159,13 +162,33 @@ export const runChannelDisconnect = async ({
|
|
|
159
162
|
...params
|
|
160
163
|
}: RunServerlessChannelParams<unknown>): Promise<void> => {
|
|
161
164
|
let sessionServices: SessionServices | undefined
|
|
162
|
-
|
|
163
|
-
|
|
165
|
+
|
|
166
|
+
// Try to get channel from store. In serverless environments (especially with
|
|
167
|
+
// serverless-offline or worker threads), disconnect can be called multiple times
|
|
168
|
+
// or after the channel has already been cleaned up. If channel doesn't exist,
|
|
169
|
+
// there's nothing to disconnect, so we can return early.
|
|
170
|
+
let channelData
|
|
171
|
+
try {
|
|
172
|
+
channelData = await params.channelStore.getChannelAndSession(
|
|
173
|
+
params.channelId
|
|
174
|
+
)
|
|
175
|
+
} catch (error) {
|
|
176
|
+
singletonServices.logger.info(
|
|
177
|
+
`Channel ${params.channelId} not found during disconnect - already cleaned up`
|
|
178
|
+
)
|
|
179
|
+
return
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const { openingData, channelName, session } = channelData
|
|
164
183
|
const { channel, channelConfig, meta } = getVariablesForChannel({
|
|
165
184
|
...params,
|
|
166
185
|
openingData,
|
|
167
186
|
channelName,
|
|
168
187
|
})
|
|
188
|
+
const userSession = new PikkuUserSessionService(
|
|
189
|
+
params.channelStore,
|
|
190
|
+
params.channelId
|
|
191
|
+
)
|
|
169
192
|
if (!sessionServices && params.createSessionServices) {
|
|
170
193
|
sessionServices = await params.createSessionServices(
|
|
171
194
|
singletonServices,
|
|
@@ -173,12 +196,35 @@ export const runChannelDisconnect = async ({
|
|
|
173
196
|
session
|
|
174
197
|
)
|
|
175
198
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
199
|
+
|
|
200
|
+
const interaction: PikkuInteraction = { channel }
|
|
201
|
+
const getAllServices = (requiresAuth?: boolean) =>
|
|
202
|
+
rpcService.injectRPCService(
|
|
203
|
+
{
|
|
204
|
+
...singletonServices,
|
|
205
|
+
...sessionServices,
|
|
206
|
+
channel,
|
|
207
|
+
userSession,
|
|
208
|
+
},
|
|
209
|
+
interaction,
|
|
210
|
+
requiresAuth
|
|
181
211
|
)
|
|
212
|
+
|
|
213
|
+
if (channelConfig.onDisconnect && meta.disconnect) {
|
|
214
|
+
try {
|
|
215
|
+
await runChannelLifecycleWithMiddleware({
|
|
216
|
+
channelConfig,
|
|
217
|
+
meta: meta.disconnect,
|
|
218
|
+
lifecycleConfig: channelConfig.onDisconnect,
|
|
219
|
+
lifecycleType: 'disconnect',
|
|
220
|
+
services: getAllServices(false),
|
|
221
|
+
channel,
|
|
222
|
+
})
|
|
223
|
+
} catch (e: any) {
|
|
224
|
+
singletonServices.logger.error(
|
|
225
|
+
`Error handling onDisconnect: ${e.message || e}`
|
|
226
|
+
)
|
|
227
|
+
}
|
|
182
228
|
}
|
|
183
229
|
await params.channelStore.removeChannels([channel.channelId])
|
|
184
230
|
if (sessionServices) {
|
|
@@ -199,6 +245,10 @@ export const runChannelMessage = async (
|
|
|
199
245
|
openingData,
|
|
200
246
|
channelName,
|
|
201
247
|
})
|
|
248
|
+
const userSession = new PikkuUserSessionService(
|
|
249
|
+
params.channelStore,
|
|
250
|
+
params.channelId
|
|
251
|
+
)
|
|
202
252
|
if (params.createSessionServices) {
|
|
203
253
|
sessionServices = await params.createSessionServices(
|
|
204
254
|
singletonServices,
|
|
@@ -206,14 +256,32 @@ export const runChannelMessage = async (
|
|
|
206
256
|
session
|
|
207
257
|
)
|
|
208
258
|
}
|
|
259
|
+
|
|
260
|
+
const interaction: PikkuInteraction = { channel }
|
|
261
|
+
const getAllServices = () =>
|
|
262
|
+
rpcService.injectRPCService(
|
|
263
|
+
{
|
|
264
|
+
...singletonServices,
|
|
265
|
+
...sessionServices,
|
|
266
|
+
channel,
|
|
267
|
+
userSession,
|
|
268
|
+
},
|
|
269
|
+
interaction
|
|
270
|
+
)
|
|
271
|
+
|
|
209
272
|
let response: unknown
|
|
210
273
|
try {
|
|
211
274
|
const onMessage = processMessageHandlers(
|
|
212
|
-
|
|
275
|
+
getAllServices(),
|
|
213
276
|
channelConfig,
|
|
214
277
|
channelHandler
|
|
215
278
|
)
|
|
216
279
|
response = await onMessage(data)
|
|
280
|
+
} catch (e: any) {
|
|
281
|
+
singletonServices.logger.error(
|
|
282
|
+
`Error processing message: ${e.message || e}`
|
|
283
|
+
)
|
|
284
|
+
return { error: e.message || 'Unknown error' }
|
|
217
285
|
} finally {
|
|
218
286
|
if (sessionServices) {
|
|
219
287
|
await closeSessionServices(singletonServices.logger, sessionServices)
|
|
@@ -92,6 +92,18 @@ export async function executeCLIViaChannel({
|
|
|
92
92
|
const commandRoute = pikkuWS.getRoute('command')
|
|
93
93
|
|
|
94
94
|
const responseHandler = (response: any) => {
|
|
95
|
+
// Check if this is a control message
|
|
96
|
+
if (
|
|
97
|
+
response?.action === 'cli-control' &&
|
|
98
|
+
response?.event === 'complete'
|
|
99
|
+
) {
|
|
100
|
+
// Server signals command is complete, close the connection client-side
|
|
101
|
+
commandRoute.unsubscribe(commandId, responseHandler)
|
|
102
|
+
pikkuWS.ws.close()
|
|
103
|
+
resolve(undefined)
|
|
104
|
+
return
|
|
105
|
+
}
|
|
106
|
+
|
|
95
107
|
// Call renderer for any output
|
|
96
108
|
renderer(null as any, response, undefined)
|
|
97
109
|
}
|
|
@@ -434,7 +434,7 @@ export async function executeCLI({
|
|
|
434
434
|
args?: string[]
|
|
435
435
|
createConfig: CreateConfig<any, any>
|
|
436
436
|
createSingletonServices: CreateSingletonServices<any, any>
|
|
437
|
-
createSessionServices?: CreateSessionServices<any, any>
|
|
437
|
+
createSessionServices?: CreateSessionServices<any, any, any>
|
|
438
438
|
}): Promise<void> {
|
|
439
439
|
if (!args) {
|
|
440
440
|
throw new Error(
|
|
@@ -327,8 +327,6 @@ const executeRoute = async (
|
|
|
327
327
|
const interaction: PikkuInteraction = { http, channel }
|
|
328
328
|
|
|
329
329
|
const getAllServices = async (session?: CoreUserSession) => {
|
|
330
|
-
let channel: PikkuChannel<unknown, unknown> | undefined
|
|
331
|
-
|
|
332
330
|
// Create session-specific services for handling the request
|
|
333
331
|
sessionServices = await createSessionServices(
|
|
334
332
|
{ ...singletonServices, userSession, channel },
|
|
@@ -62,7 +62,7 @@ export const wireMCPResource = <
|
|
|
62
62
|
if (!mcpResourceMeta) {
|
|
63
63
|
throw new Error(`MCP resource metadata not found for '${mcpResource.uri}'`)
|
|
64
64
|
}
|
|
65
|
-
addFunction(mcpResourceMeta.pikkuFuncName, mcpResource)
|
|
65
|
+
addFunction(mcpResourceMeta.pikkuFuncName, mcpResource.func as any)
|
|
66
66
|
const resources = pikkuState('mcp', 'resources')
|
|
67
67
|
if (resources.has(mcpResource.uri)) {
|
|
68
68
|
throw new Error(`MCP resource already exists: ${mcpResource.uri}`)
|
|
@@ -160,7 +160,9 @@ export async function runMCPResource(
|
|
|
160
160
|
uri,
|
|
161
161
|
endpoint,
|
|
162
162
|
pikkuFuncName,
|
|
163
|
-
{ ...params, mcp: { uri } } as RunMCPEndpointParams<
|
|
163
|
+
{ ...params, mcp: { ...params.mcp, uri } } as RunMCPEndpointParams<
|
|
164
|
+
keyof CoreMCPResource
|
|
165
|
+
>
|
|
164
166
|
)
|
|
165
167
|
}
|
|
166
168
|
|
|
@@ -250,6 +252,7 @@ async function runMCPPikkuFunc(
|
|
|
250
252
|
{
|
|
251
253
|
...singletonServices,
|
|
252
254
|
...sessionServices,
|
|
255
|
+
mcp: mcpInteraction,
|
|
253
256
|
},
|
|
254
257
|
interaction
|
|
255
258
|
)
|
|
@@ -23,7 +23,7 @@ const getPikkuFunctionName = (rpcName: string): string => {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
// Context-aware RPC client for use within services
|
|
26
|
-
class ContextAwareRPCService {
|
|
26
|
+
export class ContextAwareRPCService {
|
|
27
27
|
constructor(
|
|
28
28
|
private services: CoreServices,
|
|
29
29
|
private interaction: PikkuInteraction,
|