@pikku/core 0.12.145 → 0.12.147
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/dist/crypto-utils.d.ts +3 -3
- package/dist/crypto-utils.js +3 -3
- package/dist/function/function-meta.types.d.ts +1 -1
- package/dist/function/function-runner.js +7 -0
- package/dist/function/functions.types.d.ts +8 -0
- package/dist/{remote.d.ts → mesh.d.ts} +2 -2
- package/dist/{remote.js → mesh.js} +12 -12
- package/dist/middleware/index.d.ts +2 -2
- package/dist/middleware/index.js +2 -2
- package/dist/middleware/{remote-auth.d.ts → mesh-auth.d.ts} +6 -6
- package/dist/middleware/{remote-auth.js → mesh-auth.js} +20 -20
- package/dist/types/core.types.d.ts +3 -3
- package/dist/types/state.types.d.ts +12 -7
- package/dist/wirings/addon/addon-reach.d.ts +10 -0
- package/dist/wirings/addon/addon-reach.js +29 -0
- package/dist/wirings/addon/index.d.ts +2 -2
- package/dist/wirings/addon/index.js +1 -1
- package/dist/wirings/addon/pikku-studio.d.ts +60 -0
- package/dist/wirings/addon/pikku-studio.js +7 -0
- package/dist/wirings/addon/remote-addon-auth.d.ts +10 -2
- package/dist/wirings/addon/remote-addon-auth.js +6 -1
- package/dist/wirings/addon/remote-addon-package.d.ts +13 -0
- package/dist/wirings/addon/remote-addon-package.js +21 -0
- package/dist/wirings/addon/wire-addon.d.ts +17 -13
- package/dist/wirings/addon/wire-addon.js +6 -6
- package/dist/wirings/addon/wire-remote-addon.d.ts +37 -3
- package/dist/wirings/addon/wire-remote-addon.js +18 -1
- package/dist/wirings/agent/agent-rpc.js +6 -3
- package/dist/wirings/channel/channel-rpc-service.d.ts +1 -1
- package/dist/wirings/channel/channel-rpc-service.js +1 -1
- package/dist/wirings/rpc/index.d.ts +1 -1
- package/dist/wirings/rpc/index.js +1 -1
- package/dist/wirings/rpc/rpc-runner.d.ts +15 -9
- package/dist/wirings/rpc/rpc-runner.js +215 -49
- package/dist/wirings/rpc/rpc-types.d.ts +8 -5
- package/dist/wirings/workflow/graph/graph-runner.js +2 -2
- package/dist/wirings/workflow/pikku-workflow-service.js +3 -4
- package/dist/wirings/workflow/workflow-compensation.js +2 -2
- package/dist/wirings/workflow/workflow-meta-resolver.d.ts +5 -0
- package/dist/wirings/workflow/workflow-meta-resolver.js +5 -0
- package/dist/wirings/workflow/workflow-queue-routing.js +2 -2
- package/package.json +3 -2
- package/dist/wirings/addon/define-screens.d.ts +0 -34
- package/dist/wirings/addon/define-screens.js +0 -5
|
@@ -23,10 +23,10 @@ export type WireAddonConfig = {
|
|
|
23
23
|
mcp?: boolean | string[];
|
|
24
24
|
/**
|
|
25
25
|
* Which of the addon's functions `rpc.exposed` may call, under
|
|
26
|
-
* `<name>:<function>`.
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
26
|
+
* `<name>:<function>`. Only functions the addon itself declared
|
|
27
|
+
* `expose: true` can ever be exposed: `true` exposes all of them, a list
|
|
28
|
+
* only those it names, and unset or `false` none. A listed function the
|
|
29
|
+
* addon did not declare stays unexposed.
|
|
30
30
|
*
|
|
31
31
|
* knowledge: decisions/security/wire-addon-expose-selects-the-rpc-surface.md
|
|
32
32
|
*/
|
|
@@ -46,18 +46,22 @@ export type WireAddonConfig = {
|
|
|
46
46
|
/** Filters this addon in and out of a build — see the `tags` option on `pikku all`. It has no effect at runtime. */
|
|
47
47
|
tags?: string[];
|
|
48
48
|
/**
|
|
49
|
-
* Mounts the screens the addon ships (see `
|
|
50
|
-
*
|
|
51
|
-
* must declare at least one, or `pikku all` rejects the wiring.
|
|
49
|
+
* Mounts the screens the addon ships (see `pikkuStudio`) in the host, each at
|
|
50
|
+
* the path its `scope` gives it. Without it the addon's screens are ignored.
|
|
51
|
+
* The package must declare at least one, or `pikku all` rejects the wiring.
|
|
52
52
|
*/
|
|
53
53
|
ui?: boolean;
|
|
54
54
|
/** Required of every function in the addon, on top of the function's own. */
|
|
55
55
|
scopes?: string[];
|
|
56
56
|
/**
|
|
57
|
-
* The other addons this one may call, as `{ '<
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
57
|
+
* The other addons this one may call, as `{ '<alias>': '<name>' }`: the name
|
|
58
|
+
* the addon calls another by, and the name that addon is wired under in this
|
|
59
|
+
* app — by `wireAddon` or `wireRemoteAddon`, either serves. The alias is the
|
|
60
|
+
* one the addon's package.json declares under `pikku.uses`
|
|
61
|
+
* (`{ "stripe": "@acme/addon-stripe@^1.0.0" }`), or, for an addon that lists
|
|
62
|
+
* plain names, the package name itself. The addon calls
|
|
63
|
+
* `'<alias>:<function>'`; anything it did not declare, or this app did not
|
|
64
|
+
* map, is refused, whatever else the app has wired.
|
|
61
65
|
*/
|
|
62
66
|
uses?: Record<string, string>;
|
|
63
67
|
/** Points a secret the addon reads at a different key in this deployment, so two instances can hold different credentials. */
|
|
@@ -106,8 +110,8 @@ export type WireAddonConfig = {
|
|
|
106
110
|
export declare const wireAddon: (config: WireAddonConfig) => void;
|
|
107
111
|
/**
|
|
108
112
|
* Whether `rpc.exposed` may reach an addon function through the instance that
|
|
109
|
-
* resolved it.
|
|
110
|
-
*
|
|
113
|
+
* resolved it. Both sides must agree: the addon declares the function
|
|
114
|
+
* `expose: true`, and the wiring opts in with `true` or a list naming it.
|
|
111
115
|
*
|
|
112
116
|
* knowledge: decisions/security/wire-addon-expose-selects-the-rpc-surface.md
|
|
113
117
|
*/
|
|
@@ -39,19 +39,19 @@ export const wireAddon = (config) => {
|
|
|
39
39
|
};
|
|
40
40
|
/**
|
|
41
41
|
* Whether `rpc.exposed` may reach an addon function through the instance that
|
|
42
|
-
* resolved it.
|
|
43
|
-
*
|
|
42
|
+
* resolved it. Both sides must agree: the addon declares the function
|
|
43
|
+
* `expose: true`, and the wiring opts in with `true` or a list naming it.
|
|
44
44
|
*
|
|
45
45
|
* knowledge: decisions/security/wire-addon-expose-selects-the-rpc-surface.md
|
|
46
46
|
*/
|
|
47
47
|
export const isAddonFunctionExposed = (expose, functionName, declaredExpose) => {
|
|
48
|
+
if (declaredExpose !== true) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
48
51
|
if (Array.isArray(expose)) {
|
|
49
52
|
return expose.includes(functionName);
|
|
50
53
|
}
|
|
51
|
-
|
|
52
|
-
return false;
|
|
53
|
-
}
|
|
54
|
-
return declaredExpose === true;
|
|
54
|
+
return expose === true;
|
|
55
55
|
};
|
|
56
56
|
/**
|
|
57
57
|
* The addon configs a running function is governed by: the named instance when
|
|
@@ -5,22 +5,56 @@ export type RemoteAddonAuth = {
|
|
|
5
5
|
} | {
|
|
6
6
|
secretId: string;
|
|
7
7
|
} | {
|
|
8
|
-
|
|
8
|
+
/** `null` sends this call without a credential, for a public surface. */
|
|
9
|
+
resolve: (services: CoreServices, wire: PikkuWire) => string | null | Promise<string | null>;
|
|
9
10
|
};
|
|
11
|
+
/**
|
|
12
|
+
* Sent on every call to a hosted addon. The host's `rpc.exposed` then answers
|
|
13
|
+
* only functions in the addon's remote contract (`remote: true`), so a consumer
|
|
14
|
+
* holding a token cannot reach the host's other exposed functions through it.
|
|
15
|
+
* It can only narrow what the host answers, never widen it.
|
|
16
|
+
*
|
|
17
|
+
* knowledge: decisions/security/wire-addon-expose-selects-the-rpc-surface.md
|
|
18
|
+
*/
|
|
19
|
+
export declare const REMOTE_CONTRACT_HEADER = "x-pikku-remote-contract";
|
|
20
|
+
/** How long a call to a hosted addon may take when `timeoutMs` is not set. */
|
|
21
|
+
export declare const DEFAULT_REMOTE_ADDON_TIMEOUT_MS = 30000;
|
|
10
22
|
/** Options for `wireRemoteAddon`: the namespace, the contract package, where the addon is deployed and how calls authenticate. */
|
|
11
23
|
export type WireRemoteAddonConfig = {
|
|
12
24
|
/** Consumer-facing namespace, e.g. `registry` → `rpc('registry:getOpenApi')` */
|
|
13
25
|
name: string;
|
|
14
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* The contract package, as a string literal. `@scope/name@^1.4.0` pins a
|
|
28
|
+
* range: `pikku all` downloads the addon's SDK from the registry and
|
|
29
|
+
* records it in `pikku-addons.lock`. A bare `@scope/name` must be installed
|
|
30
|
+
* as a devDependency instead — `pikku verify` enforces both.
|
|
31
|
+
*/
|
|
15
32
|
package: string;
|
|
16
33
|
/** Where the addon is deployed, e.g. `https://registry.example.com`. A function when it varies per environment. */
|
|
17
34
|
serverUrl: string | ((services: CoreServices) => string | Promise<string>);
|
|
18
35
|
/** Omit when the addon declares its remote surface public. */
|
|
19
36
|
auth?: RemoteAddonAuth;
|
|
20
|
-
/**
|
|
37
|
+
/**
|
|
38
|
+
* Map a consumer-facing fn name → the remote fn name, when they differ (rare).
|
|
39
|
+
* It gets the base name; a versioned call appends `@vN` to what it returns.
|
|
40
|
+
*/
|
|
21
41
|
remoteName?: (fn: string) => string;
|
|
22
42
|
/** Applied to every function the addon contributes, so tag middleware and permissions reach them. */
|
|
23
43
|
tags?: string[];
|
|
44
|
+
/**
|
|
45
|
+
* Which of the addon's contract functions this app's `rpc.exposed` — and so
|
|
46
|
+
* its public `POST /rpc/:rpcName` — forwards to the host, under
|
|
47
|
+
* `<name>:<function>`. `true` forwards every contract function, a list only
|
|
48
|
+
* those named, and unset or `false` none: server-side `rpc('<name>:fn')`
|
|
49
|
+
* calls are unaffected.
|
|
50
|
+
*
|
|
51
|
+
* knowledge: decisions/security/wire-addon-expose-selects-the-rpc-surface.md
|
|
52
|
+
*/
|
|
53
|
+
expose?: boolean | string[];
|
|
54
|
+
/** Milliseconds a call may take before it is aborted. Defaults to {@link DEFAULT_REMOTE_ADDON_TIMEOUT_MS}. */
|
|
55
|
+
timeoutMs?: number;
|
|
56
|
+
/** Extra headers for every call to the host. Cannot replace the auth, trace or contract headers. */
|
|
57
|
+
headers?: (services: CoreServices, wire: PikkuWire) => Record<string, string> | Promise<Record<string, string>>;
|
|
24
58
|
};
|
|
25
59
|
/**
|
|
26
60
|
* Installs an addon that runs as its own deployed service: the contract is
|
|
@@ -1,15 +1,32 @@
|
|
|
1
1
|
import { pikkuState } from '../../pikku-state.js';
|
|
2
|
+
import { parseRemoteAddonPackage } from './remote-addon-package.js';
|
|
3
|
+
/**
|
|
4
|
+
* Sent on every call to a hosted addon. The host's `rpc.exposed` then answers
|
|
5
|
+
* only functions in the addon's remote contract (`remote: true`), so a consumer
|
|
6
|
+
* holding a token cannot reach the host's other exposed functions through it.
|
|
7
|
+
* It can only narrow what the host answers, never widen it.
|
|
8
|
+
*
|
|
9
|
+
* knowledge: decisions/security/wire-addon-expose-selects-the-rpc-surface.md
|
|
10
|
+
*/
|
|
11
|
+
export const REMOTE_CONTRACT_HEADER = 'x-pikku-remote-contract';
|
|
12
|
+
/** How long a call to a hosted addon may take when `timeoutMs` is not set. */
|
|
13
|
+
export const DEFAULT_REMOTE_ADDON_TIMEOUT_MS = 30_000;
|
|
2
14
|
/**
|
|
3
15
|
* Installs an addon that runs as its own deployed service: the contract is
|
|
4
16
|
* local, the calls go over the wire to the addon's own host.
|
|
5
17
|
*/
|
|
6
18
|
export const wireRemoteAddon = (config) => {
|
|
7
19
|
pikkuState(null, 'addons', 'packages').set(config.name, {
|
|
8
|
-
package: config.package,
|
|
20
|
+
package: parseRemoteAddonPackage(config.package).name,
|
|
9
21
|
tags: config.tags,
|
|
10
22
|
remote: true,
|
|
11
23
|
serverUrl: config.serverUrl,
|
|
24
|
+
...(config.expose !== undefined ? { expose: config.expose } : {}),
|
|
12
25
|
...(config.auth ? { remoteAuth: config.auth } : {}),
|
|
13
26
|
...(config.remoteName ? { remoteName: config.remoteName } : {}),
|
|
27
|
+
...(config.timeoutMs !== undefined
|
|
28
|
+
? { remoteTimeoutMs: config.timeoutMs }
|
|
29
|
+
: {}),
|
|
30
|
+
...(config.headers ? { remoteHeaders: config.headers } : {}),
|
|
14
31
|
});
|
|
15
32
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { pikkuState } from '../../pikku-state.js';
|
|
2
|
+
import { mapAddonCall } from '../addon/addon-reach.js';
|
|
2
3
|
import { runAgent, resumeAgentSync } from './agent-runner.js';
|
|
3
4
|
import { streamAgent, resumeAgent, interruptAgent } from './agent-stream.js';
|
|
4
5
|
import { wrapChannelWithAGUI } from './agent-agui.js';
|
|
@@ -31,10 +32,10 @@ export const createAgentRPC = (wire, options) => {
|
|
|
31
32
|
}),
|
|
32
33
|
});
|
|
33
34
|
return {
|
|
34
|
-
run: async (agentName, input) => asRunResult(await runAgent(agentName, input, params())),
|
|
35
|
+
run: async (agentName, input) => asRunResult(await runAgent(mapAddonCall(wire.addonNamespace, agentName), input, params())),
|
|
35
36
|
stream: async (agentName, input, streamOptions) => {
|
|
36
37
|
let currentRunId;
|
|
37
|
-
await streamAgent(agentName, input, wrapChannelWithAGUI(streamingChannel(), {
|
|
38
|
+
await streamAgent(mapAddonCall(wire.addonNamespace, agentName), input, wrapChannelWithAGUI(streamingChannel(), {
|
|
38
39
|
threadId: input.threadId,
|
|
39
40
|
getRunId: () => currentRunId,
|
|
40
41
|
}), params(), undefined, {
|
|
@@ -49,7 +50,9 @@ export const createAgentRPC = (wire, options) => {
|
|
|
49
50
|
await resumeAgent({ runId, ...input }, wrapChannelWithAGUI(streamingChannel(), { runId }), params(), streamOptions);
|
|
50
51
|
},
|
|
51
52
|
interrupt: async (runId, reason) => interruptAgent({ runId, ...(reason ? { reason } : {}) }, { sessionService: options.sessionService }),
|
|
52
|
-
approve: async (runId, approvals, expectedAgentName) => asRunResult(await resumeAgentSync(runId, approvals, { sessionService: options.sessionService }, expectedAgentName
|
|
53
|
+
approve: async (runId, approvals, expectedAgentName) => asRunResult(await resumeAgentSync(runId, approvals, { sessionService: options.sessionService }, expectedAgentName === undefined
|
|
54
|
+
? undefined
|
|
55
|
+
: mapAddonCall(wire.addonNamespace, expectedAgentName))),
|
|
53
56
|
};
|
|
54
57
|
};
|
|
55
58
|
/**
|
|
@@ -7,7 +7,7 @@ import { type ChannelRPCValidator } from './channel-rpc.types.js';
|
|
|
7
7
|
* inbound route of its own.
|
|
8
8
|
*
|
|
9
9
|
* It slots into the existing `services.deploymentService` hole, leaving
|
|
10
|
-
* `rpc.
|
|
10
|
+
* `rpc.mesh` resolution, session propagation and traceId plumbing unchanged.
|
|
11
11
|
*/
|
|
12
12
|
export declare class ChannelDeploymentService implements DeploymentService {
|
|
13
13
|
private readonly send;
|
|
@@ -6,7 +6,7 @@ import { CHANNEL_RPC_REQUEST, CHANNEL_RPC_RESPONSE, ChannelRPCError, isChannelRP
|
|
|
6
6
|
* inbound route of its own.
|
|
7
7
|
*
|
|
8
8
|
* It slots into the existing `services.deploymentService` hole, leaving
|
|
9
|
-
* `rpc.
|
|
9
|
+
* `rpc.mesh` resolution, session propagation and traceId plumbing unchanged.
|
|
10
10
|
*/
|
|
11
11
|
export class ChannelDeploymentService {
|
|
12
12
|
send;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { PikkuRPCService, rpcService, RPCNotFoundError, RemoteAddonConfigError,
|
|
1
|
+
export { PikkuRPCService, rpcService, RPCNotFoundError, RemoteAddonConfigError, RemoteAddonFailedError, RemoteAddonTimeoutError, } from './rpc-runner.js';
|
|
2
2
|
export type { PikkuRPC, RPCMeta } from './rpc-types.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { PikkuRPCService, rpcService, RPCNotFoundError, RemoteAddonConfigError,
|
|
1
|
+
export { PikkuRPCService, rpcService, RPCNotFoundError, RemoteAddonConfigError, RemoteAddonFailedError, RemoteAddonTimeoutError, } from './rpc-runner.js';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { AddonNotUsedError } from '../addon/addon-reach.js';
|
|
1
2
|
import type { CoreServices, PikkuRawWire } from '../../types/core.types.js';
|
|
2
3
|
import type { SessionService } from '../../services/user-session-service.js';
|
|
3
4
|
import type { CoreUserSession } from '../../types/core.types.js';
|
|
@@ -11,20 +12,25 @@ import type { PikkuRPC, ResolvedFunction } from './rpc-types.js';
|
|
|
11
12
|
*/
|
|
12
13
|
export declare class RPCNotFoundError extends PikkuError {
|
|
13
14
|
readonly rpcName: string;
|
|
14
|
-
constructor(rpcName: string);
|
|
15
|
+
constructor(rpcName: string, message?: string);
|
|
15
16
|
}
|
|
16
17
|
/** Thrown when a remote addon's configuration cannot be used, for example when its `serverUrl` resolves empty. Maps to HTTP 500. */
|
|
17
18
|
export declare class RemoteAddonConfigError extends PikkuError {
|
|
18
19
|
constructor(namespace: string, detail: string);
|
|
19
20
|
}
|
|
20
|
-
/**
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Thrown when a remote addon fails on its own side — a 5xx, an unreachable
|
|
23
|
+
* host, or a response that is not JSON. Maps to HTTP 502. What went wrong is
|
|
24
|
+
* logged on this host; none of it reaches the caller.
|
|
25
|
+
*/
|
|
26
|
+
export declare class RemoteAddonFailedError extends PikkuError {
|
|
27
|
+
constructor(namespace: string, fnName: string);
|
|
24
28
|
}
|
|
25
|
-
|
|
26
|
-
|
|
29
|
+
/** Thrown when a remote addon does not answer within the wiring's `timeoutMs`. Maps to HTTP 504. */
|
|
30
|
+
export declare class RemoteAddonTimeoutError extends PikkuError {
|
|
31
|
+
constructor(namespace: string, fnName: string, timeoutMs: number);
|
|
27
32
|
}
|
|
33
|
+
export { AddonNotUsedError };
|
|
28
34
|
export declare const resolveNamespace: (namespacedFunction: string) => ResolvedFunction | null;
|
|
29
35
|
export declare class ContextAwareRPCService {
|
|
30
36
|
private services;
|
|
@@ -72,7 +78,7 @@ export declare class ContextAwareRPCService {
|
|
|
72
78
|
* the tree behind it.
|
|
73
79
|
*/
|
|
74
80
|
get agent(): PikkuRPC['agent'];
|
|
75
|
-
|
|
81
|
+
mesh<In = any, Out = any>(funcName: string, data: In): Promise<Out>;
|
|
76
82
|
}
|
|
77
83
|
/**
|
|
78
84
|
* Builds the `rpc` object handed to every function on its wire.
|
|
@@ -81,7 +87,7 @@ export declare class ContextAwareRPCService {
|
|
|
81
87
|
* `DeploymentService` when the function lives in another deployment unit.
|
|
82
88
|
* `rpc.exposed` does the same but only reaches functions marked `expose: true`
|
|
83
89
|
* (and, for addons, those the consuming app exposes), which is what the public
|
|
84
|
-
* RPC endpoint uses. `rpc.
|
|
90
|
+
* RPC endpoint uses. `rpc.mesh` always goes through the `DeploymentService`.
|
|
85
91
|
* Calls carry the caller's wire, so the session and trace ID propagate. An addon
|
|
86
92
|
* can only call the addons it lists in `uses`.
|
|
87
93
|
*
|