@pikku/core 0.7.8 → 0.8.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/CHANGELOG.md +10 -1
- package/dist/errors/error-handler.d.ts +2 -0
- package/dist/errors/errors.js +2 -0
- package/dist/{channel → events/channel}/channel-handler.d.ts +1 -1
- package/dist/{channel → events/channel}/channel-handler.js +2 -2
- package/dist/{channel → events/channel}/channel-runner.d.ts +1 -1
- package/dist/{channel → events/channel}/channel-runner.js +4 -4
- package/dist/{channel → events/channel}/channel-store.d.ts +1 -1
- package/dist/{channel → events/channel}/channel.types.d.ts +3 -3
- package/dist/{channel → events/channel}/local/local-channel-runner.js +6 -6
- package/dist/{channel → events/channel}/log-channels.d.ts +1 -1
- package/dist/{channel → events/channel}/log-channels.js +1 -1
- package/dist/{channel → events/channel}/serverless/serverless-channel-runner.js +7 -7
- package/dist/{http → events/http}/http-runner.d.ts +1 -1
- package/dist/{http → events/http}/http-runner.js +8 -8
- package/dist/{http → events/http}/http.types.d.ts +3 -3
- package/dist/{http → events/http}/index.d.ts +0 -1
- package/dist/{http → events/http}/index.js +0 -1
- package/dist/{http → events/http}/log-http-routes.d.ts +1 -1
- package/dist/{http → events/http}/log-http-routes.js +1 -1
- package/dist/{http → events/http}/pikku-fetch-http-request.js +1 -1
- package/dist/events/mcp/index.d.ts +2 -0
- package/dist/events/mcp/index.js +2 -0
- package/dist/events/mcp/mcp-runner.d.ts +30 -0
- package/dist/events/mcp/mcp-runner.js +192 -0
- package/dist/events/mcp/mcp.types.d.ts +117 -0
- package/dist/events/queue/index.d.ts +6 -0
- package/dist/events/queue/index.js +6 -0
- package/dist/events/queue/queue-runner.d.ts +24 -0
- package/dist/events/queue/queue-runner.js +83 -0
- package/dist/events/queue/queue.types.d.ts +154 -0
- package/dist/events/queue/register-queue-helper.d.ts +17 -0
- package/dist/events/queue/register-queue-helper.js +34 -0
- package/dist/events/queue/validate-worker-config.d.ts +41 -0
- package/dist/events/queue/validate-worker-config.js +50 -0
- package/dist/events/rpc/index.d.ts +2 -0
- package/dist/events/rpc/rpc-runner.d.ts +28 -0
- package/dist/{rpc → events/rpc}/rpc-runner.js +2 -2
- package/dist/events/scheduler/index.d.ts +3 -0
- package/dist/events/scheduler/index.js +3 -0
- package/dist/{scheduler → events/scheduler}/log-schedulers.d.ts +1 -1
- package/dist/{scheduler → events/scheduler}/log-schedulers.js +1 -1
- package/dist/{scheduler → events/scheduler}/scheduler-runner.d.ts +4 -3
- package/dist/{scheduler → events/scheduler}/scheduler-runner.js +7 -4
- package/dist/{scheduler → events/scheduler}/scheduler.types.d.ts +3 -4
- package/dist/function/function-runner.js +8 -0
- package/dist/function/functions.types.d.ts +3 -2
- package/dist/handle-error.d.ts +2 -2
- package/dist/handle-error.js +1 -1
- package/dist/index.d.ts +10 -6
- package/dist/index.js +10 -6
- package/dist/middleware-runner.d.ts +4 -4
- package/dist/middleware-runner.js +3 -1
- package/dist/pikku-state.d.ts +18 -4
- package/dist/pikku-state.js +12 -0
- package/dist/services/user-session-service.d.ts +1 -1
- package/dist/types/core.types.d.ts +17 -5
- package/dist/types/core.types.js +2 -0
- package/lcov.info +3191 -3123
- package/package.json +8 -7
- package/src/errors/error-handler.ts +2 -1
- package/src/errors/errors.ts +2 -0
- package/src/{channel → events/channel}/channel-handler.ts +3 -3
- package/src/{channel → events/channel}/channel-runner.ts +5 -5
- package/src/{channel → events/channel}/channel-store.ts +1 -1
- package/src/{channel → events/channel}/channel.types.ts +3 -3
- package/src/{channel → events/channel}/local/local-channel-runner.test.ts +1 -1
- package/src/{channel → events/channel}/local/local-channel-runner.ts +7 -7
- package/src/{channel → events/channel}/local/local-eventhub-service.test.ts +1 -1
- package/src/{channel → events/channel}/log-channels.ts +2 -2
- package/src/{channel → events/channel}/serverless/serverless-channel-runner.ts +8 -8
- package/src/{http → events/http}/http-runner.test.ts +4 -4
- package/src/{http → events/http}/http-runner.ts +9 -9
- package/src/{http → events/http}/http.types.ts +3 -3
- package/src/{http → events/http}/index.ts +0 -1
- package/src/{http → events/http}/log-http-routes.ts +2 -2
- package/src/{http → events/http}/pikku-fetch-http-request.ts +1 -1
- package/src/events/mcp/index.ts +2 -0
- package/src/events/mcp/mcp-runner.ts +321 -0
- package/src/events/mcp/mcp.types.ts +150 -0
- package/src/events/queue/index.ts +18 -0
- package/src/events/queue/queue-runner.ts +125 -0
- package/src/events/queue/queue.types.ts +176 -0
- package/src/events/queue/register-queue-helper.ts +62 -0
- package/src/events/queue/validate-worker-config.ts +113 -0
- package/src/events/rpc/index.ts +2 -0
- package/src/{rpc → events/rpc}/rpc-runner.ts +3 -3
- package/src/events/scheduler/index.ts +9 -0
- package/src/{scheduler → events/scheduler}/log-schedulers.ts +2 -2
- package/src/{scheduler → events/scheduler}/scheduler-runner.ts +11 -10
- package/src/{scheduler → events/scheduler}/scheduler.types.ts +2 -4
- package/src/function/function-runner.ts +19 -1
- package/src/function/functions.types.ts +3 -1
- package/src/handle-error.ts +2 -2
- package/src/index.ts +23 -6
- package/src/middleware-runner.ts +14 -7
- package/src/pikku-state.ts +40 -4
- package/src/services/user-session-service.ts +1 -1
- package/src/types/core.types.ts +24 -4
- package/tsconfig.json +3 -2
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/rpc/index.d.ts +0 -2
- package/dist/rpc/rpc-runner.d.ts +0 -27
- package/dist/scheduler/index.d.ts +0 -3
- package/dist/scheduler/index.js +0 -3
- package/src/http/incomingmessage-to-request-convertor.ts +0 -0
- package/src/rpc/index.ts +0 -2
- package/src/scheduler/index.ts +0 -5
- /package/dist/{channel → events/channel}/channel-store.js +0 -0
- /package/dist/{channel → events/channel}/channel.types.js +0 -0
- /package/dist/{channel → events/channel}/eventhub-service.d.ts +0 -0
- /package/dist/{channel → events/channel}/eventhub-service.js +0 -0
- /package/dist/{channel → events/channel}/eventhub-store.d.ts +0 -0
- /package/dist/{channel → events/channel}/eventhub-store.js +0 -0
- /package/dist/{channel → events/channel}/index.d.ts +0 -0
- /package/dist/{channel → events/channel}/index.js +0 -0
- /package/dist/{channel → events/channel}/local/index.d.ts +0 -0
- /package/dist/{channel → events/channel}/local/index.js +0 -0
- /package/dist/{channel → events/channel}/local/local-channel-handler.d.ts +0 -0
- /package/dist/{channel → events/channel}/local/local-channel-handler.js +0 -0
- /package/dist/{channel → events/channel}/local/local-channel-runner.d.ts +0 -0
- /package/dist/{channel → events/channel}/local/local-eventhub-service.d.ts +0 -0
- /package/dist/{channel → events/channel}/local/local-eventhub-service.js +0 -0
- /package/dist/{channel → events/channel}/pikku-abstract-channel-handler.d.ts +0 -0
- /package/dist/{channel → events/channel}/pikku-abstract-channel-handler.js +0 -0
- /package/dist/{channel → events/channel}/serverless/index.d.ts +0 -0
- /package/dist/{channel → events/channel}/serverless/index.js +0 -0
- /package/dist/{channel → events/channel}/serverless/serverless-channel-runner.d.ts +0 -0
- /package/dist/{http → events/http}/http.types.js +0 -0
- /package/dist/{http → events/http}/pikku-fetch-http-request.d.ts +0 -0
- /package/dist/{http → events/http}/pikku-fetch-http-response.d.ts +0 -0
- /package/dist/{http → events/http}/pikku-fetch-http-response.js +0 -0
- /package/dist/{http/incomingmessage-to-request-convertor.d.ts → events/mcp/mcp.types.js} +0 -0
- /package/dist/{http/incomingmessage-to-request-convertor.js → events/queue/queue.types.js} +0 -0
- /package/dist/{rpc → events/rpc}/index.js +0 -0
- /package/dist/{rpc → events/rpc}/rpc-types.d.ts +0 -0
- /package/dist/{rpc → events/rpc}/rpc-types.js +0 -0
- /package/dist/{scheduler → events/scheduler}/scheduler.types.js +0 -0
- /package/src/{channel → events/channel}/eventhub-service.ts +0 -0
- /package/src/{channel → events/channel}/eventhub-store.ts +0 -0
- /package/src/{channel → events/channel}/index.ts +0 -0
- /package/src/{channel → events/channel}/local/index.ts +0 -0
- /package/src/{channel → events/channel}/local/local-channel-handler.ts +0 -0
- /package/src/{channel → events/channel}/local/local-eventhub-service.ts +0 -0
- /package/src/{channel → events/channel}/pikku-abstract-channel-handler.test.ts +0 -0
- /package/src/{channel → events/channel}/pikku-abstract-channel-handler.ts +0 -0
- /package/src/{channel → events/channel}/serverless/index.ts +0 -0
- /package/src/{http → events/http}/pikku-fetch-http-request.test.ts +0 -0
- /package/src/{http → events/http}/pikku-fetch-http-response.test.ts +0 -0
- /package/src/{http → events/http}/pikku-fetch-http-response.ts +0 -0
- /package/src/{rpc → events/rpc}/rpc-types.ts +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pikku/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"author": "yasser.fadl@gmail.com",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -20,13 +20,14 @@
|
|
|
20
20
|
".": "./dist/index.js",
|
|
21
21
|
"./middleware": "./dist/middleware/index.js",
|
|
22
22
|
"./function": "./dist/function/index.js",
|
|
23
|
-
"./channel": "./dist/channel/index.js",
|
|
24
|
-
"./channel/local": "./dist/channel/local/index.js",
|
|
25
|
-
"./channel/serverless": "./dist/channel/serverless/index.js",
|
|
26
|
-
"./http": "./dist/http/index.js",
|
|
27
|
-
"./
|
|
23
|
+
"./channel": "./dist/events/channel/index.js",
|
|
24
|
+
"./channel/local": "./dist/events/channel/local/index.js",
|
|
25
|
+
"./channel/serverless": "./dist/events/channel/serverless/index.js",
|
|
26
|
+
"./http": "./dist/events/http/index.js",
|
|
27
|
+
"./queue": "./dist/events/queue/index.js",
|
|
28
|
+
"./scheduler": "./dist/events/scheduler/index.js",
|
|
29
|
+
"./rpc": "./dist/events/rpc/index.js",
|
|
28
30
|
"./errors": "./dist/errors/index.js",
|
|
29
|
-
"./scheduler": "./dist/scheduler/index.js",
|
|
30
31
|
"./services": "./dist/services/index.js",
|
|
31
32
|
"./schema": "./dist/schema.js",
|
|
32
33
|
"./types": "./dist/types/index.d.ts"
|
|
@@ -21,6 +21,7 @@ export class PikkuError extends Error {
|
|
|
21
21
|
export interface ErrorDetails {
|
|
22
22
|
status: number
|
|
23
23
|
message: string
|
|
24
|
+
mcpCode?: number
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
/**
|
|
@@ -51,7 +52,7 @@ export const addErrors = (
|
|
|
51
52
|
*/
|
|
52
53
|
export const getErrorResponse = (
|
|
53
54
|
error: Error
|
|
54
|
-
): { status: number; message: string } | undefined => {
|
|
55
|
+
): { status: number; message: string; mcpCode?: number } | undefined => {
|
|
55
56
|
const errors = Array.from(pikkuState('misc', 'errors').entries())
|
|
56
57
|
const foundError = errors.find(([e]) => e.name === error.constructor.name)
|
|
57
58
|
if (foundError) {
|
package/src/errors/errors.ts
CHANGED
|
@@ -10,6 +10,7 @@ import { addError, PikkuError } from './error-handler.js'
|
|
|
10
10
|
export class BadRequestError extends PikkuError {}
|
|
11
11
|
addError(BadRequestError, {
|
|
12
12
|
status: 400,
|
|
13
|
+
mcpCode: -32600,
|
|
13
14
|
message:
|
|
14
15
|
'The server cannot or will not process the request due to client error (e.g., malformed request syntax).',
|
|
15
16
|
})
|
|
@@ -85,6 +86,7 @@ export class NotFoundError extends PikkuError {}
|
|
|
85
86
|
*/
|
|
86
87
|
addError(NotFoundError, {
|
|
87
88
|
status: 404,
|
|
89
|
+
mcpCode: -32601,
|
|
88
90
|
message: 'The server cannot find the requested resource.',
|
|
89
91
|
})
|
|
90
92
|
|
|
@@ -2,14 +2,14 @@ import {
|
|
|
2
2
|
CoreServices,
|
|
3
3
|
JSONValue,
|
|
4
4
|
CoreUserSession,
|
|
5
|
-
} from '
|
|
5
|
+
} from '../../types/core.types.js'
|
|
6
6
|
import {
|
|
7
7
|
ChannelMessageMeta,
|
|
8
8
|
CoreAPIChannel,
|
|
9
9
|
PikkuChannelHandler,
|
|
10
10
|
} from './channel.types.js'
|
|
11
|
-
import { pikkuState } from '
|
|
12
|
-
import { runPikkuFunc } from '
|
|
11
|
+
import { pikkuState } from '../../pikku-state.js'
|
|
12
|
+
import { runPikkuFunc } from '../../function/function-runner.js'
|
|
13
13
|
|
|
14
14
|
const getRouteMeta = (
|
|
15
15
|
channelName: string,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { NotFoundError } from '
|
|
2
|
-
import { addFunction } from '
|
|
3
|
-
import { pikkuState } from '
|
|
4
|
-
import { coerceTopLevelDataFromSchema, validateSchema } from '
|
|
5
|
-
import { UserSessionService } from '
|
|
1
|
+
import { NotFoundError } from '../../errors/errors.js'
|
|
2
|
+
import { addFunction } from '../../function/function-runner.js'
|
|
3
|
+
import { pikkuState } from '../../pikku-state.js'
|
|
4
|
+
import { coerceTopLevelDataFromSchema, validateSchema } from '../../schema.js'
|
|
5
|
+
import { UserSessionService } from '../../services/user-session-service.js'
|
|
6
6
|
import {
|
|
7
7
|
ChannelMeta,
|
|
8
8
|
CoreAPIChannel,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PikkuError } from '
|
|
1
|
+
import { PikkuError } from '../../errors/error-handler.js'
|
|
2
2
|
import {
|
|
3
3
|
HTTPFunctionMetaInputTypes,
|
|
4
4
|
PikkuHTTPRequest,
|
|
@@ -9,12 +9,12 @@ import {
|
|
|
9
9
|
CoreSingletonServices,
|
|
10
10
|
CreateSessionServices,
|
|
11
11
|
PikkuMiddleware,
|
|
12
|
-
} from '
|
|
12
|
+
} from '../../types/core.types.js'
|
|
13
13
|
import {
|
|
14
14
|
CoreAPIFunction,
|
|
15
15
|
CoreAPIFunctionSessionless,
|
|
16
16
|
CoreAPIPermission,
|
|
17
|
-
} from '
|
|
17
|
+
} from '../../function/functions.types.js'
|
|
18
18
|
|
|
19
19
|
export type RunChannelOptions = Partial<{
|
|
20
20
|
skipUserSession: boolean
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { test, beforeEach, afterEach } from 'node:test'
|
|
2
2
|
import * as assert from 'node:assert/strict'
|
|
3
3
|
import { runLocalChannel } from './local-channel-runner.js'
|
|
4
|
-
import { pikkuState, resetPikkuState } from '
|
|
4
|
+
import { pikkuState, resetPikkuState } from '../../../pikku-state.js'
|
|
5
5
|
import { addChannel } from '../channel-runner.js'
|
|
6
6
|
import {
|
|
7
7
|
HTTPMethod,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { openChannel } from '../channel-runner.js'
|
|
2
2
|
import { createHTTPInteraction } from '../../http/http-runner.js'
|
|
3
|
-
import { closeSessionServices } from '
|
|
3
|
+
import { closeSessionServices } from '../../../utils.js'
|
|
4
4
|
import { processMessageHandlers } from '../channel-handler.js'
|
|
5
5
|
import {
|
|
6
6
|
CoreAPIChannel,
|
|
@@ -8,12 +8,12 @@ import {
|
|
|
8
8
|
RunChannelParams,
|
|
9
9
|
} from '../channel.types.js'
|
|
10
10
|
import { PikkuLocalChannelHandler } from './local-channel-handler.js'
|
|
11
|
-
import { SessionServices } from '
|
|
12
|
-
import {
|
|
13
|
-
import { runMiddleware } from '
|
|
14
|
-
import { PikkuUserSessionService } from '
|
|
11
|
+
import { SessionServices } from '../../../types/core.types.js'
|
|
12
|
+
import { handleHTTPError } from '../../../handle-error.js'
|
|
13
|
+
import { runMiddleware } from '../../../middleware-runner.js'
|
|
14
|
+
import { PikkuUserSessionService } from '../../../services/user-session-service.js'
|
|
15
15
|
import { PikkuHTTP } from '../../http/http.types.js'
|
|
16
|
-
import { runPikkuFuncDirectly } from '
|
|
16
|
+
import { runPikkuFuncDirectly } from '../../../function/function-runner.js'
|
|
17
17
|
import { rpcService } from '../../rpc/rpc-runner.js'
|
|
18
18
|
|
|
19
19
|
export const runLocalChannel = async ({
|
|
@@ -110,7 +110,7 @@ export const runLocalChannel = async ({
|
|
|
110
110
|
)
|
|
111
111
|
)
|
|
112
112
|
} catch (e: any) {
|
|
113
|
-
|
|
113
|
+
handleHTTPError(
|
|
114
114
|
e,
|
|
115
115
|
http,
|
|
116
116
|
channelId,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as assert from 'assert'
|
|
2
2
|
import { test } from 'node:test'
|
|
3
3
|
import { PikkuChannelHandler } from '../channel.types.js'
|
|
4
|
-
import { CoreUserSession } from '
|
|
4
|
+
import { CoreUserSession } from '../../../types/core.types.js'
|
|
5
5
|
import { LocalEventHubService } from './local-eventhub-service.js'
|
|
6
6
|
|
|
7
7
|
class MockChannelHandler implements PikkuChannelHandler {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { SessionServices } from '
|
|
2
|
-
import { closeSessionServices } from '
|
|
1
|
+
import { SessionServices } from '../../../types/core.types.js'
|
|
2
|
+
import { closeSessionServices } from '../../../utils.js'
|
|
3
3
|
import { processMessageHandlers } from '../channel-handler.js'
|
|
4
4
|
import { openChannel } from '../channel-runner.js'
|
|
5
5
|
import type {
|
|
@@ -10,13 +10,13 @@ import type {
|
|
|
10
10
|
} from '../channel.types.js'
|
|
11
11
|
import { createHTTPInteraction } from '../../http/http-runner.js'
|
|
12
12
|
import { ChannelStore } from '../channel-store.js'
|
|
13
|
-
import {
|
|
14
|
-
import { PikkuUserSessionService } from '
|
|
15
|
-
import { runMiddleware } from '
|
|
16
|
-
import { pikkuState } from '
|
|
13
|
+
import { handleHTTPError } from '../../../handle-error.js'
|
|
14
|
+
import { PikkuUserSessionService } from '../../../services/user-session-service.js'
|
|
15
|
+
import { runMiddleware } from '../../../middleware-runner.js'
|
|
16
|
+
import { pikkuState } from '../../../pikku-state.js'
|
|
17
17
|
import { PikkuFetchHTTPRequest } from '../../http/pikku-fetch-http-request.js'
|
|
18
18
|
import { PikkuHTTP } from '../../http/http.types.js'
|
|
19
|
-
import { runPikkuFuncDirectly } from '
|
|
19
|
+
import { runPikkuFuncDirectly } from '../../../function/function-runner.js'
|
|
20
20
|
|
|
21
21
|
export interface RunServerlessChannelParams<ChannelData>
|
|
22
22
|
extends RunChannelParams<ChannelData> {
|
|
@@ -124,7 +124,7 @@ export const runChannelConnect = async ({
|
|
|
124
124
|
}
|
|
125
125
|
http?.response?.status(101)
|
|
126
126
|
} catch (e: any) {
|
|
127
|
-
|
|
127
|
+
handleHTTPError(
|
|
128
128
|
e,
|
|
129
129
|
http,
|
|
130
130
|
channelId,
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { test, describe, beforeEach, afterEach } from 'node:test'
|
|
2
2
|
import * as assert from 'assert'
|
|
3
|
-
import { NotFoundError } from '
|
|
4
|
-
import { JSONValue, PikkuMiddleware } from '
|
|
3
|
+
import { NotFoundError } from '../../errors/errors.js'
|
|
4
|
+
import { JSONValue, PikkuMiddleware } from '../../types/core.types.js'
|
|
5
5
|
import { fetch, addHTTPRoute } from './http-runner.js'
|
|
6
|
-
import { pikkuState, resetPikkuState } from '
|
|
6
|
+
import { pikkuState, resetPikkuState } from '../../pikku-state.js'
|
|
7
7
|
import {
|
|
8
8
|
PikkuMockRequest,
|
|
9
9
|
PikkuMockResponse,
|
|
10
10
|
} from '../channel/local/local-channel-runner.test.js'
|
|
11
|
-
import { addFunction } from '
|
|
11
|
+
import { addFunction } from '../../function/function-runner.js'
|
|
12
12
|
|
|
13
13
|
const sessionMiddleware: PikkuMiddleware = async (services, _, next) => {
|
|
14
14
|
services.userSession.set({ userId: 'test' } as any)
|
|
@@ -12,25 +12,25 @@ import {
|
|
|
12
12
|
CoreUserSession,
|
|
13
13
|
PikkuMiddleware,
|
|
14
14
|
SessionServices,
|
|
15
|
-
} from '
|
|
15
|
+
} from '../../types/core.types.js'
|
|
16
16
|
import { match } from 'path-to-regexp'
|
|
17
|
-
import { MissingSessionError, NotFoundError } from '
|
|
17
|
+
import { MissingSessionError, NotFoundError } from '../../errors/errors.js'
|
|
18
18
|
import {
|
|
19
19
|
closeSessionServices,
|
|
20
20
|
createWeakUID,
|
|
21
21
|
isSerializable,
|
|
22
|
-
} from '
|
|
22
|
+
} from '../../utils.js'
|
|
23
23
|
import {
|
|
24
24
|
PikkuUserSessionService,
|
|
25
25
|
UserSessionService,
|
|
26
|
-
} from '
|
|
27
|
-
import { runMiddleware } from '
|
|
28
|
-
import {
|
|
29
|
-
import { pikkuState } from '
|
|
26
|
+
} from '../../services/user-session-service.js'
|
|
27
|
+
import { runMiddleware } from '../../middleware-runner.js'
|
|
28
|
+
import { handleHTTPError } from '../../handle-error.js'
|
|
29
|
+
import { pikkuState } from '../../pikku-state.js'
|
|
30
30
|
import { PikkuFetchHTTPResponse } from './pikku-fetch-http-response.js'
|
|
31
31
|
import { PikkuFetchHTTPRequest } from './pikku-fetch-http-request.js'
|
|
32
32
|
import { PikkuChannel } from '../channel/channel.types.js'
|
|
33
|
-
import { addFunction, runPikkuFunc } from '
|
|
33
|
+
import { addFunction, runPikkuFunc } from '../../function/function-runner.js'
|
|
34
34
|
import { rpcService } from '../rpc/rpc-runner.js'
|
|
35
35
|
|
|
36
36
|
/**
|
|
@@ -499,7 +499,7 @@ export const fetchData = async <In, Out>(
|
|
|
499
499
|
return result
|
|
500
500
|
} catch (e: any) {
|
|
501
501
|
// Handle errors and, depending on configuration, bubble them up or respond with an error
|
|
502
|
-
|
|
502
|
+
handleHTTPError(
|
|
503
503
|
e,
|
|
504
504
|
http,
|
|
505
505
|
requestId,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { SerializeOptions } from 'cookie'
|
|
2
|
-
import type { PikkuError } from '
|
|
2
|
+
import type { PikkuError } from '../../errors/error-handler.js'
|
|
3
3
|
import type {
|
|
4
4
|
APIDocs,
|
|
5
5
|
CoreServices,
|
|
@@ -7,13 +7,13 @@ import type {
|
|
|
7
7
|
CoreUserSession,
|
|
8
8
|
CreateSessionServices,
|
|
9
9
|
PikkuMiddleware,
|
|
10
|
-
} from '
|
|
10
|
+
} from '../../types/core.types.js'
|
|
11
11
|
import type {
|
|
12
12
|
CoreAPIFunction,
|
|
13
13
|
CoreAPIFunctionSessionless,
|
|
14
14
|
CoreAPIPermission,
|
|
15
15
|
CorePermissionGroup,
|
|
16
|
-
} from '
|
|
16
|
+
} from '../../function/functions.types.js'
|
|
17
17
|
|
|
18
18
|
type ExtractRouteParams<S extends string> =
|
|
19
19
|
S extends `${string}:${infer Param}/${infer Rest}`
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { parse as parseQuery } from 'picoquery'
|
|
2
2
|
import { parse as parseCookie } from 'cookie'
|
|
3
3
|
import { HTTPMethod, PikkuHTTPRequest, PikkuQuery } from './http.types.js'
|
|
4
|
-
import { UnprocessableContentError } from '
|
|
4
|
+
import { UnprocessableContentError } from '../../errors/errors.js'
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Abstract class representing a pikku request.
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
CoreServices,
|
|
3
|
+
CoreSingletonServices,
|
|
4
|
+
CoreUserSession,
|
|
5
|
+
CreateSessionServices,
|
|
6
|
+
} from '../../types/core.types.js'
|
|
7
|
+
import type {
|
|
8
|
+
CoreMCPResource,
|
|
9
|
+
CoreMCPTool,
|
|
10
|
+
CoreMCPPrompt,
|
|
11
|
+
JsonRpcRequest,
|
|
12
|
+
JsonRpcResponse,
|
|
13
|
+
JsonRpcErrorResponse,
|
|
14
|
+
PikkuMCP,
|
|
15
|
+
} from './mcp.types.js'
|
|
16
|
+
import type { CoreAPIFunctionSessionless } from '../../function/functions.types.js'
|
|
17
|
+
import { getErrorResponse } from '../../errors/error-handler.js'
|
|
18
|
+
import { closeSessionServices } from '../../utils.js'
|
|
19
|
+
import { pikkuState } from '../../pikku-state.js'
|
|
20
|
+
import { addFunction, runPikkuFunc } from '../../function/function-runner.js'
|
|
21
|
+
import { rpcService } from '../rpc/rpc-runner.js'
|
|
22
|
+
import { BadRequestError, NotFoundError } from '../../errors/errors.js'
|
|
23
|
+
|
|
24
|
+
export class MCPError extends Error {
|
|
25
|
+
constructor(public readonly error: JsonRpcErrorResponse) {
|
|
26
|
+
super(error?.message || 'MCP Error')
|
|
27
|
+
this.name = 'MCPError'
|
|
28
|
+
this.stack = new Error().stack
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export type RunMCPEndpointParams<Tools extends string = any> = {
|
|
33
|
+
session?: CoreUserSession
|
|
34
|
+
singletonServices: CoreSingletonServices
|
|
35
|
+
mcp?: PikkuMCP<Tools>
|
|
36
|
+
createSessionServices?: CreateSessionServices<
|
|
37
|
+
CoreSingletonServices,
|
|
38
|
+
CoreServices<CoreSingletonServices>,
|
|
39
|
+
CoreUserSession
|
|
40
|
+
>
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export type JsonRpcError = {
|
|
44
|
+
code: number
|
|
45
|
+
message: string
|
|
46
|
+
data?: any
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export const addMCPResource = <
|
|
50
|
+
APIFunction extends CoreAPIFunctionSessionless<any, any>,
|
|
51
|
+
>(
|
|
52
|
+
mcpResource: CoreMCPResource<APIFunction>
|
|
53
|
+
) => {
|
|
54
|
+
const resourcesMeta = pikkuState('mcp', 'resourcesMeta')
|
|
55
|
+
const mcpResourceMeta = resourcesMeta[mcpResource.uri]
|
|
56
|
+
if (!mcpResourceMeta) {
|
|
57
|
+
throw new Error(`MCP resource metadata not found for '${mcpResource.uri}'`)
|
|
58
|
+
}
|
|
59
|
+
addFunction(mcpResourceMeta.pikkuFuncName, {
|
|
60
|
+
func: mcpResource.func,
|
|
61
|
+
})
|
|
62
|
+
const resources = pikkuState('mcp', 'resources')
|
|
63
|
+
if (resources.has(mcpResource.uri)) {
|
|
64
|
+
throw new Error(`MCP resource already exists: ${mcpResource.uri}`)
|
|
65
|
+
}
|
|
66
|
+
resources.set(mcpResource.uri, mcpResource)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export const addMCPTool = <
|
|
70
|
+
APIFunction extends CoreAPIFunctionSessionless<any, any>,
|
|
71
|
+
>(
|
|
72
|
+
mcpTool: CoreMCPTool<APIFunction>
|
|
73
|
+
) => {
|
|
74
|
+
const toolsMeta = pikkuState('mcp', 'toolsMeta')
|
|
75
|
+
const mcpToolMeta = toolsMeta[mcpTool.name]
|
|
76
|
+
if (!mcpToolMeta) {
|
|
77
|
+
throw new Error(`MCP tool metadata not found for '${mcpTool.name}'`)
|
|
78
|
+
}
|
|
79
|
+
addFunction(mcpToolMeta.pikkuFuncName, {
|
|
80
|
+
func: mcpTool.func,
|
|
81
|
+
})
|
|
82
|
+
const tools = pikkuState('mcp', 'tools')
|
|
83
|
+
if (tools.has(mcpTool.name)) {
|
|
84
|
+
throw new Error(`MCP tool already exists: ${mcpTool.name}`)
|
|
85
|
+
}
|
|
86
|
+
tools.set(mcpTool.name, mcpTool)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export const addMCPPrompt = <
|
|
90
|
+
APIFunction extends CoreAPIFunctionSessionless<any, any>,
|
|
91
|
+
>(
|
|
92
|
+
mcpPrompt: CoreMCPPrompt<APIFunction>
|
|
93
|
+
) => {
|
|
94
|
+
const promptsMeta = pikkuState('mcp', 'promptsMeta')
|
|
95
|
+
const mcpPromptMeta = promptsMeta[mcpPrompt.name]
|
|
96
|
+
if (!mcpPromptMeta) {
|
|
97
|
+
throw new Error(`MCP prompt metadata not found for '${mcpPrompt.name}'`)
|
|
98
|
+
}
|
|
99
|
+
addFunction(mcpPromptMeta.pikkuFuncName, {
|
|
100
|
+
func: mcpPrompt.func,
|
|
101
|
+
})
|
|
102
|
+
const prompts = pikkuState('mcp', 'prompts')
|
|
103
|
+
if (prompts.has(mcpPrompt.name)) {
|
|
104
|
+
throw new Error(`MCP prompt already exists: ${mcpPrompt.name}`)
|
|
105
|
+
}
|
|
106
|
+
prompts.set(mcpPrompt.name, mcpPrompt)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export async function runMCPResource(
|
|
110
|
+
request: JsonRpcRequest,
|
|
111
|
+
params: RunMCPEndpointParams,
|
|
112
|
+
uri: string
|
|
113
|
+
) {
|
|
114
|
+
let endpoint: CoreMCPResource | undefined
|
|
115
|
+
let pikkuFuncName: string | undefined
|
|
116
|
+
let extractedParams: Record<string, string> = {}
|
|
117
|
+
|
|
118
|
+
const metas = pikkuState('mcp', 'resourcesMeta')
|
|
119
|
+
const endpoints = pikkuState('mcp', 'resources')
|
|
120
|
+
|
|
121
|
+
if (endpoints.has(uri)) {
|
|
122
|
+
endpoint = endpoints.get(uri)
|
|
123
|
+
pikkuFuncName = metas[uri]?.pikkuFuncName
|
|
124
|
+
} else {
|
|
125
|
+
for (const [uriTemplate, value] of endpoints.entries()) {
|
|
126
|
+
// Extract parameter names from the template
|
|
127
|
+
const paramNames = Array.from(
|
|
128
|
+
uriTemplate.matchAll(/\{([^}]+)\}/g),
|
|
129
|
+
(m) => m[1]
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
// Create regex pattern to match and capture parameter values
|
|
133
|
+
const regexPattern = uriTemplate.replace(/\{[^}]+\}/g, '([^/]+)')
|
|
134
|
+
const regex = new RegExp(`^${regexPattern}$`)
|
|
135
|
+
const match = uri.match(regex)
|
|
136
|
+
|
|
137
|
+
if (match) {
|
|
138
|
+
endpoint = value
|
|
139
|
+
pikkuFuncName = metas[uriTemplate]?.pikkuFuncName
|
|
140
|
+
|
|
141
|
+
// Extract parameter values and create params object
|
|
142
|
+
for (let i = 0; i < paramNames.length; i++) {
|
|
143
|
+
extractedParams[paramNames[i]!] = match[i + 1]! // match[0] is the full match
|
|
144
|
+
}
|
|
145
|
+
break
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return await runMCPPikkuFunc(
|
|
151
|
+
{
|
|
152
|
+
...request,
|
|
153
|
+
params: { ...request.params, ...extractedParams },
|
|
154
|
+
},
|
|
155
|
+
'resource',
|
|
156
|
+
uri,
|
|
157
|
+
endpoint,
|
|
158
|
+
pikkuFuncName,
|
|
159
|
+
{ ...params, mcp: { uri } } as RunMCPEndpointParams<keyof CoreMCPResource>
|
|
160
|
+
)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export async function runMCPTool(
|
|
164
|
+
request: JsonRpcRequest,
|
|
165
|
+
params: RunMCPEndpointParams,
|
|
166
|
+
name: string
|
|
167
|
+
) {
|
|
168
|
+
const endpoint = pikkuState('mcp', 'tools').get(name)
|
|
169
|
+
const meta = pikkuState('mcp', 'toolsMeta')[name]
|
|
170
|
+
return await runMCPPikkuFunc(
|
|
171
|
+
request,
|
|
172
|
+
'tool',
|
|
173
|
+
name,
|
|
174
|
+
endpoint,
|
|
175
|
+
meta?.pikkuFuncName,
|
|
176
|
+
params
|
|
177
|
+
)
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export async function runMCPPrompt(
|
|
181
|
+
request: JsonRpcRequest,
|
|
182
|
+
params: RunMCPEndpointParams,
|
|
183
|
+
name: string
|
|
184
|
+
) {
|
|
185
|
+
const endpoint = pikkuState('mcp', 'prompts').get(name)
|
|
186
|
+
const meta = pikkuState('mcp', 'promptsMeta')[name]
|
|
187
|
+
return await runMCPPikkuFunc(
|
|
188
|
+
request,
|
|
189
|
+
'prompt',
|
|
190
|
+
name,
|
|
191
|
+
endpoint,
|
|
192
|
+
meta?.pikkuFuncName,
|
|
193
|
+
params
|
|
194
|
+
)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* JSON-RPC 2.0 compatible MCP endpoint runner
|
|
199
|
+
*/
|
|
200
|
+
async function runMCPPikkuFunc(
|
|
201
|
+
request: JsonRpcRequest,
|
|
202
|
+
type: 'resource' | 'tool' | 'prompt',
|
|
203
|
+
name: string,
|
|
204
|
+
mcp: CoreMCPResource | CoreMCPTool | CoreMCPPrompt | undefined,
|
|
205
|
+
pikkuFuncName: string | undefined,
|
|
206
|
+
{
|
|
207
|
+
session,
|
|
208
|
+
singletonServices,
|
|
209
|
+
createSessionServices,
|
|
210
|
+
mcp: interaction,
|
|
211
|
+
}: RunMCPEndpointParams
|
|
212
|
+
): Promise<JsonRpcResponse> {
|
|
213
|
+
let sessionServices: any
|
|
214
|
+
|
|
215
|
+
try {
|
|
216
|
+
// Validate JSON-RPC request structure
|
|
217
|
+
if (request.jsonrpc !== '2.0') {
|
|
218
|
+
throw new BadRequestError(
|
|
219
|
+
'Invalid JSON-RPC version, only supoorted version is 2.0'
|
|
220
|
+
)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (!mcp) {
|
|
224
|
+
throw new NotFoundError(
|
|
225
|
+
`MCP '${type}' registration not found for '${name}'`
|
|
226
|
+
)
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (!pikkuFuncName) {
|
|
230
|
+
throw new NotFoundError(
|
|
231
|
+
`MCP '${type}' PikkuFunction Mapping not found for '${name}'`
|
|
232
|
+
)
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
singletonServices.logger.debug(`Running MCP ${type}: ${name}`)
|
|
236
|
+
|
|
237
|
+
const getAllServices = async () => {
|
|
238
|
+
if (createSessionServices) {
|
|
239
|
+
const services = await createSessionServices(
|
|
240
|
+
singletonServices,
|
|
241
|
+
{ mcp: interaction },
|
|
242
|
+
session
|
|
243
|
+
)
|
|
244
|
+
sessionServices = services
|
|
245
|
+
return rpcService.injectRPCService({
|
|
246
|
+
...singletonServices,
|
|
247
|
+
...services,
|
|
248
|
+
mcp: interaction,
|
|
249
|
+
})
|
|
250
|
+
}
|
|
251
|
+
return rpcService.injectRPCService({
|
|
252
|
+
...singletonServices,
|
|
253
|
+
mcp: interaction,
|
|
254
|
+
})
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const result = await runPikkuFunc(pikkuFuncName, {
|
|
258
|
+
getAllServices,
|
|
259
|
+
session,
|
|
260
|
+
data: request.params,
|
|
261
|
+
})
|
|
262
|
+
|
|
263
|
+
return {
|
|
264
|
+
id: request.id,
|
|
265
|
+
result,
|
|
266
|
+
}
|
|
267
|
+
} catch (e: any) {
|
|
268
|
+
singletonServices.logger.error(
|
|
269
|
+
`Error running MCP ${type} '${name}':`,
|
|
270
|
+
e.constructor
|
|
271
|
+
)
|
|
272
|
+
const errorResponse = getErrorResponse(e)
|
|
273
|
+
if (errorResponse?.mcpCode) {
|
|
274
|
+
throw new MCPError({
|
|
275
|
+
id: request.id,
|
|
276
|
+
code: errorResponse.mcpCode,
|
|
277
|
+
message: errorResponse.message,
|
|
278
|
+
})
|
|
279
|
+
} else {
|
|
280
|
+
if (errorResponse) {
|
|
281
|
+
singletonServices.logger.warn(
|
|
282
|
+
`Got error without a mapping: ${errorResponse.message}`
|
|
283
|
+
)
|
|
284
|
+
}
|
|
285
|
+
throw new MCPError({
|
|
286
|
+
id: request.id,
|
|
287
|
+
code: -32603,
|
|
288
|
+
message: 'Internal error',
|
|
289
|
+
data: { message: e.message, stack: e.stack },
|
|
290
|
+
})
|
|
291
|
+
}
|
|
292
|
+
} finally {
|
|
293
|
+
if (sessionServices) {
|
|
294
|
+
await closeSessionServices(singletonServices.logger, sessionServices)
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
export const getMCPTools = () => {
|
|
300
|
+
return pikkuState('mcp', 'tools')
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
export const getMCPResources = () => {
|
|
304
|
+
return pikkuState('mcp', 'resources')
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
export const getMCPResourcesMeta = () => {
|
|
308
|
+
return pikkuState('mcp', 'resourcesMeta')
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
export const getMCPToolsMeta = () => {
|
|
312
|
+
return pikkuState('mcp', 'toolsMeta')
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
export const getMCPPrompts = () => {
|
|
316
|
+
return pikkuState('mcp', 'prompts')
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
export const getMCPPromptsMeta = () => {
|
|
320
|
+
return pikkuState('mcp', 'promptsMeta')
|
|
321
|
+
}
|