@pikku/core 0.12.80 → 0.12.82
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 +312 -0
- package/dist/errors/index.d.ts +1 -1
- package/dist/errors/index.js +1 -1
- package/dist/function/function-runner.js +2 -5
- package/dist/function/index.d.ts +1 -1
- package/dist/index.d.ts +11 -11
- package/dist/index.js +3 -3
- package/dist/pikku-state.js +4 -0
- package/dist/services/ai-agent-runner-service.d.ts +7 -0
- package/dist/services/ai-run-state-service.d.ts +10 -0
- package/dist/services/in-memory-ai-run-state-service.d.ts +5 -1
- package/dist/services/in-memory-ai-run-state-service.js +9 -0
- package/dist/services/index.d.ts +15 -15
- package/dist/services/index.js +5 -5
- package/dist/services/scoped-credential-service.d.ts +21 -0
- package/dist/services/scoped-credential-service.js +53 -0
- package/dist/testing/service-tests/ai-storage-service-tests.js +76 -0
- package/dist/types/core.types.d.ts +0 -2
- package/dist/types/state.types.d.ts +13 -0
- package/dist/wirings/actor-flow/index.d.ts +1 -1
- package/dist/wirings/ai-agent/ai-agent-finalize.d.ts +58 -0
- package/dist/wirings/ai-agent/ai-agent-finalize.js +138 -0
- package/dist/wirings/ai-agent/ai-agent-interrupt.js +1 -0
- package/dist/wirings/ai-agent/ai-agent-memory.d.ts +2 -8
- package/dist/wirings/ai-agent/ai-agent-memory.js +34 -17
- package/dist/wirings/ai-agent/ai-agent-model-config.d.ts +7 -0
- package/dist/wirings/ai-agent/ai-agent-model-config.js +44 -1
- package/dist/wirings/ai-agent/ai-agent-prepare.js +2 -0
- package/dist/wirings/ai-agent/ai-agent-runner.js +61 -40
- package/dist/wirings/ai-agent/ai-agent-stream.js +89 -36
- package/dist/wirings/ai-agent/ai-agent-turn.d.ts +1 -0
- package/dist/wirings/ai-agent/ai-agent-turn.js +1 -0
- package/dist/wirings/ai-agent/ai-agent.types.d.ts +46 -1
- package/dist/wirings/ai-agent/index.d.ts +8 -7
- package/dist/wirings/ai-agent/index.js +5 -4
- package/dist/wirings/ai-scorer/ai-scorer-grade.d.ts +26 -0
- package/dist/wirings/ai-scorer/ai-scorer-grade.js +33 -0
- package/dist/wirings/ai-scorer/ai-scorer-judge.d.ts +17 -0
- package/dist/wirings/ai-scorer/ai-scorer-judge.js +92 -0
- package/dist/wirings/ai-scorer/ai-scorer-live.d.ts +15 -0
- package/dist/wirings/ai-scorer/ai-scorer-live.js +38 -0
- package/dist/wirings/ai-scorer/ai-scorer-registry.d.ts +18 -0
- package/dist/wirings/ai-scorer/ai-scorer-registry.js +46 -0
- package/dist/wirings/ai-scorer/ai-scorer-sampling.d.ts +8 -0
- package/dist/wirings/ai-scorer/ai-scorer-sampling.js +31 -0
- package/dist/wirings/ai-scorer/ai-scorer-snapshots.d.ts +10 -0
- package/dist/wirings/ai-scorer/ai-scorer-snapshots.js +40 -0
- package/dist/wirings/ai-scorer/ai-scorer-worker.d.ts +15 -0
- package/dist/wirings/ai-scorer/ai-scorer-worker.js +58 -0
- package/dist/wirings/ai-scorer/ai-scorer.d.ts +39 -0
- package/dist/wirings/ai-scorer/ai-scorer.js +40 -0
- package/dist/wirings/ai-scorer/ai-scorer.types.d.ts +90 -0
- package/dist/wirings/ai-scorer/ai-scorer.types.js +4 -0
- package/dist/wirings/ai-scorer/index.d.ts +6 -0
- package/dist/wirings/ai-scorer/index.js +5 -0
- package/dist/wirings/channel/index.d.ts +5 -6
- package/dist/wirings/channel/index.js +3 -4
- package/dist/wirings/channel/local/local-channel-runner.js +8 -1
- package/dist/wirings/cli/channel/cli-raw-channel-runner.js +9 -1
- package/dist/wirings/cli/channel/index.d.ts +1 -2
- package/dist/wirings/cli/channel/index.js +0 -1
- package/dist/wirings/cli/cli-runner.js +13 -1
- package/dist/wirings/credential/index.d.ts +1 -1
- package/dist/wirings/gateway/index.d.ts +1 -1
- package/dist/wirings/http/http-runner.js +8 -2
- package/dist/wirings/http/index.d.ts +1 -2
- package/dist/wirings/mcp/index.d.ts +1 -1
- package/dist/wirings/mcp/mcp-runner.d.ts +15 -0
- package/dist/wirings/mcp/mcp-runner.js +18 -5
- package/dist/wirings/persona/index.d.ts +3 -4
- package/dist/wirings/persona/index.js +2 -3
- package/dist/wirings/queue/index.d.ts +1 -3
- package/dist/wirings/queue/index.js +1 -3
- package/dist/wirings/rpc/addon-runner.d.ts +4 -0
- package/dist/wirings/rpc/addon-runner.js +19 -3
- package/dist/wirings/rpc/rpc-runner.js +2 -0
- package/dist/wirings/rpc/rpc-types.d.ts +4 -0
- package/dist/wirings/rpc/wire-addon.d.ts +13 -0
- package/dist/wirings/rpc/wire-addon.js +4 -0
- package/dist/wirings/scheduler/index.d.ts +1 -1
- package/dist/wirings/trigger/index.d.ts +1 -1
- package/dist/wirings/virtual-user/index.d.ts +5 -6
- package/dist/wirings/virtual-user/index.js +2 -4
- package/dist/wirings/workflow/dsl/workflow-dsl.types.d.ts +85 -15
- package/dist/wirings/workflow/index.d.ts +6 -6
- package/dist/wirings/workflow/index.js +2 -2
- package/dist/wirings/workflow/pikku-scenario-service.d.ts +7 -7
- package/dist/wirings/workflow/pikku-scenario-service.js +39 -13
- package/dist/wirings/workflow/pikku-workflow-service.js +17 -3
- package/dist/wirings/workflow/scenario-step.types.d.ts +8 -0
- package/dist/wirings/workflow/workflow-approval-audit.d.ts +16 -0
- package/dist/wirings/workflow/workflow-approval-audit.js +40 -0
- package/dist/wirings/workflow/workflow-approval-policy.d.ts +20 -0
- package/dist/wirings/workflow/workflow-approval-policy.js +48 -0
- package/dist/wirings/workflow/workflow-approval.d.ts +29 -1
- package/dist/wirings/workflow/workflow-approval.js +65 -2
- package/dist/wirings/workflow/workflow-run-ownership.d.ts +2 -1
- package/dist/wirings/workflow/workflow-run-ownership.js +2 -1
- package/dist/wirings/workflow/workflow.types.d.ts +1 -1
- package/knowledge/decisions/internals/addon-pikku-meta-ships-at-the-package-root-or-under-dist.md +32 -0
- package/knowledge/decisions/internals/an-addon-scope-root-loses-to-a-root-the-host-already-declares.md +39 -0
- package/knowledge/decisions/internals/index.md +30 -3
- package/knowledge/decisions/internals/validate-runs-checks-by-precondition.md +115 -0
- package/knowledge/decisions/security/a-function-never-receives-the-secret-service.md +37 -0
- package/knowledge/decisions/security/a-workflow-run-is-read-and-approved-by-its-owner.md +30 -14
- package/knowledge/decisions/security/an-approval-answer-outlives-the-run-it-answered.md +59 -0
- package/knowledge/decisions/security/index.md +3 -1
- package/knowledge/questions/index.md +1 -1
- package/package.json +3 -1
- package/scripts/generate-api-report.mts +143 -18
- package/src/api-report.test.ts +2 -2
- package/src/errors/index.ts +1 -1
- package/src/function/function-runner.test.ts +52 -0
- package/src/function/function-runner.ts +5 -9
- package/src/function/index.ts +0 -2
- package/src/index.ts +0 -35
- package/src/pikku-state.ts +5 -0
- package/src/public-surface.json +70 -94
- package/src/services/ai-agent-runner-service.ts +12 -1
- package/src/services/ai-run-state-service.ts +11 -0
- package/src/services/in-memory-ai-run-state-service.ts +13 -0
- package/src/services/index.ts +3 -43
- package/src/services/scoped-credential-service.test.ts +86 -0
- package/src/services/scoped-credential-service.ts +63 -0
- package/src/testing/service-tests/ai-storage-service-tests.ts +93 -0
- package/src/types/core.types.ts +3 -6
- package/src/types/state.types.ts +16 -0
- package/src/wirings/actor-flow/index.ts +0 -3
- package/src/wirings/ai-agent/ai-agent-finalize.test.ts +186 -0
- package/src/wirings/ai-agent/ai-agent-finalize.ts +197 -0
- package/src/wirings/ai-agent/ai-agent-interrupt.ts +1 -0
- package/src/wirings/ai-agent/ai-agent-memory.ts +54 -38
- package/src/wirings/ai-agent/ai-agent-model-config.test.ts +72 -3
- package/src/wirings/ai-agent/ai-agent-model-config.ts +49 -1
- package/src/wirings/ai-agent/ai-agent-prepare.ts +2 -0
- package/src/wirings/ai-agent/ai-agent-runner.ts +71 -40
- package/src/wirings/ai-agent/ai-agent-stream-output-hooks.test.ts +353 -0
- package/src/wirings/ai-agent/ai-agent-stream.ts +116 -54
- package/src/wirings/ai-agent/ai-agent-turn.test.ts +67 -0
- package/src/wirings/ai-agent/ai-agent-turn.ts +1 -0
- package/src/wirings/ai-agent/ai-agent.types.ts +64 -4
- package/src/wirings/ai-agent/index.ts +2 -16
- package/src/wirings/ai-scorer/ai-scorer-grade.test.ts +106 -0
- package/src/wirings/ai-scorer/ai-scorer-grade.ts +55 -0
- package/src/wirings/ai-scorer/ai-scorer-judge.test.ts +143 -0
- package/src/wirings/ai-scorer/ai-scorer-judge.ts +120 -0
- package/src/wirings/ai-scorer/ai-scorer-live.test.ts +174 -0
- package/src/wirings/ai-scorer/ai-scorer-live.ts +56 -0
- package/src/wirings/ai-scorer/ai-scorer-registry.ts +63 -0
- package/src/wirings/ai-scorer/ai-scorer-sampling.test.ts +34 -0
- package/src/wirings/ai-scorer/ai-scorer-sampling.ts +36 -0
- package/src/wirings/ai-scorer/ai-scorer-snapshots.test.ts +49 -0
- package/src/wirings/ai-scorer/ai-scorer-snapshots.ts +46 -0
- package/src/wirings/ai-scorer/ai-scorer-worker.test.ts +122 -0
- package/src/wirings/ai-scorer/ai-scorer-worker.ts +69 -0
- package/src/wirings/ai-scorer/ai-scorer.ts +76 -0
- package/src/wirings/ai-scorer/ai-scorer.types.ts +107 -0
- package/src/wirings/ai-scorer/index.ts +24 -0
- package/src/wirings/channel/index.ts +1 -20
- package/src/wirings/channel/local/local-channel-runner.test.ts +68 -0
- package/src/wirings/channel/local/local-channel-runner.ts +8 -1
- package/src/wirings/cli/channel/cli-raw-channel-runner.test.ts +23 -0
- package/src/wirings/cli/channel/cli-raw-channel-runner.ts +12 -1
- package/src/wirings/cli/channel/index.ts +0 -7
- package/src/wirings/cli/cli-runner.test.ts +68 -0
- package/src/wirings/cli/cli-runner.ts +18 -1
- package/src/wirings/credential/index.ts +0 -1
- package/src/wirings/gateway/index.ts +0 -3
- package/src/wirings/http/http-runner.test.ts +66 -0
- package/src/wirings/http/http-runner.ts +10 -2
- package/src/wirings/http/index.ts +1 -1
- package/src/wirings/mcp/index.ts +0 -1
- package/src/wirings/mcp/mcp-runner.test.ts +181 -0
- package/src/wirings/mcp/mcp-runner.ts +35 -5
- package/src/wirings/persona/index.ts +0 -8
- package/src/wirings/queue/index.ts +0 -14
- package/src/wirings/rpc/addon-runner.ts +34 -3
- package/src/wirings/rpc/addon-secrets.test.ts +261 -0
- package/src/wirings/rpc/rpc-runner.test.ts +2 -0
- package/src/wirings/rpc/rpc-runner.ts +2 -0
- package/src/wirings/rpc/rpc-types.ts +4 -0
- package/src/wirings/rpc/wire-addon.ts +17 -0
- package/src/wirings/scheduler/index.ts +0 -1
- package/src/wirings/trigger/index.ts +0 -1
- package/src/wirings/virtual-user/index.ts +0 -16
- package/src/wirings/workflow/dsl/workflow-dsl.types.ts +96 -16
- package/src/wirings/workflow/graph/graph-runner.test.ts +72 -0
- package/src/wirings/workflow/index.ts +2 -20
- package/src/wirings/workflow/pikku-scenario-service.ts +60 -15
- package/src/wirings/workflow/pikku-workflow-service.test.ts +13 -12
- package/src/wirings/workflow/pikku-workflow-service.ts +28 -4
- package/src/wirings/workflow/scenario-expectations.test.ts +75 -0
- package/src/wirings/workflow/scenario-hooks.test.ts +3 -2
- package/src/wirings/workflow/scenario-step.types.ts +8 -0
- package/src/wirings/workflow/workflow-approval-audit.ts +47 -0
- package/src/wirings/workflow/workflow-approval-policy.test.ts +524 -0
- package/src/wirings/workflow/workflow-approval-policy.ts +68 -0
- package/src/wirings/workflow/workflow-approval.ts +113 -9
- package/src/wirings/workflow/workflow-run-authority.test.ts +12 -15
- package/src/wirings/workflow/workflow-run-ownership.ts +2 -1
- package/src/wirings/workflow/workflow.types.ts +0 -9
- package/src/wirings-stay-decoupled.test.ts +6 -2
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/internal.d.ts +0 -3
- package/dist/internal.js +0 -2
- package/dist/middleware/timeout.d.ts +0 -9
- package/dist/middleware/timeout.js +0 -15
- package/dist/pikku-response.d.ts +0 -6
- package/dist/pikku-response.js +0 -6
- package/dist/services/gopass-secrets.d.ts +0 -15
- package/dist/services/gopass-secrets.js +0 -76
- package/dist/services/http-scenario-actors.d.ts +0 -75
- package/dist/services/http-scenario-actors.js +0 -195
- package/dist/services/http-user-flow-actors.d.ts +0 -67
- package/dist/services/http-user-flow-actors.js +0 -193
- package/dist/services/scenario-actors-service.d.ts +0 -127
- package/dist/services/scenario-actors-service.js +0 -40
- package/dist/services/user-flow-actors-service.d.ts +0 -39
- package/dist/services/user-flow-actors-service.js +0 -1
- package/dist/wirings/credential/wire-credential.d.ts +0 -48
- package/dist/wirings/credential/wire-credential.js +0 -47
- package/dist/wirings/oauth2/oauth2-client.d.ts +0 -47
- package/dist/wirings/oauth2/oauth2-client.js +0 -263
- package/dist/wirings/oauth2/oauth2-routes.d.ts +0 -35
- package/dist/wirings/oauth2/oauth2-routes.js +0 -146
- package/dist/wirings/scope/wire-scope.d.ts +0 -33
- package/dist/wirings/scope/wire-scope.js +0 -32
- package/dist/wirings/workflow/dsl/index.d.ts +0 -5
- package/dist/wirings/workflow/dsl/index.js +0 -4
- package/dist/wirings/workflow/graph/index.d.ts +0 -5
- package/dist/wirings/workflow/graph/index.js +0 -4
|
@@ -1,4 +1,3 @@
|
|
|
1
1
|
export { executeCLIViaChannel } from './cli-channel-runner.js';
|
|
2
2
|
export { handleRawCLI } from './cli-raw-channel-runner.js';
|
|
3
3
|
export { executeRawCLIViaChannel } from './cli-raw-client-runner.js';
|
|
4
|
-
export { APPROVAL_FLAGS, approverForMode, createTerminalApprover, takeApprovalFlags, } from './cli-approval.js';
|
|
@@ -87,7 +87,19 @@ function registerCLICommands(commands, path = [], inheritedOptions = {}, program
|
|
|
87
87
|
programs[program].commandMiddleware[commandId] = command.middleware;
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
|
-
|
|
90
|
+
// Merge the command-level auth/permissions into the registered config so
|
|
91
|
+
// they are actually enforced by the function runner. They were accepted by
|
|
92
|
+
// the types but dropped here, making a command's declared access control a
|
|
93
|
+
// silent no-op. Command-level wins over the handler's own, then falls back
|
|
94
|
+
// to it.
|
|
95
|
+
const unwrapped = unwrapFunc(command);
|
|
96
|
+
const commandAuth = typeof command === 'object' ? command.auth : undefined;
|
|
97
|
+
const commandPermissions = typeof command === 'object' ? command.permissions : undefined;
|
|
98
|
+
addFunction(funcName, {
|
|
99
|
+
...unwrapped,
|
|
100
|
+
auth: commandAuth ?? unwrapped.auth,
|
|
101
|
+
permissions: commandPermissions ?? unwrapped.permissions,
|
|
102
|
+
}, currentMeta?.packageName);
|
|
91
103
|
if (typeof command === 'object' && command.render) {
|
|
92
104
|
if (programs[program]) {
|
|
93
105
|
programs[program].renderers[commandId] = command.render;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { defineCredential } from './define-credential.js';
|
|
2
2
|
export { validateAndBuildCredentialDefinitionsMeta } from './validate-credential-definitions.js';
|
|
3
|
-
export type { CoreCredential,
|
|
3
|
+
export type { CoreCredential, CredentialDefinitionsMeta, CredentialDefinitions, } from './credential.types.js';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { wireGateway, createListenerMessageHandler, resolveGatewayAdapter, } from './gateway-runner.js';
|
|
2
|
-
export type { GatewayAdapter, GatewayAdapterFactory,
|
|
2
|
+
export type { GatewayAdapter, GatewayAdapterFactory, GatewayInboundMessage, GatewayOutboundMessage, GatewaysMeta, GatewayTransportType, CoreGateway, WebhookVerificationResult, } from './gateway.types.js';
|
|
@@ -173,6 +173,7 @@ const executeRoute = async (services, matchedRoute, http, options) => {
|
|
|
173
173
|
getSession: () => userSession.get(),
|
|
174
174
|
hasSessionChanged: () => userSession.sessionChanged,
|
|
175
175
|
};
|
|
176
|
+
const statusBeforeRoute = http?.response?.statusCode;
|
|
176
177
|
try {
|
|
177
178
|
result = await runPikkuFunc('http', `${meta.method}:${meta.route}`, meta.pikkuFuncId, {
|
|
178
179
|
singletonServices,
|
|
@@ -209,17 +210,22 @@ const executeRoute = async (services, matchedRoute, http, options) => {
|
|
|
209
210
|
http?.response?.flushHeaders?.();
|
|
210
211
|
}
|
|
211
212
|
else {
|
|
213
|
+
const statusSetByRoute = http?.response?.statusCode !== statusBeforeRoute;
|
|
212
214
|
if (result instanceof Response) {
|
|
213
215
|
await applyWebResponse(http.response, result);
|
|
214
216
|
}
|
|
215
217
|
else if (result === undefined || result === null) {
|
|
216
|
-
|
|
218
|
+
if (!statusSetByRoute) {
|
|
219
|
+
http?.response?.status(204);
|
|
220
|
+
}
|
|
217
221
|
}
|
|
218
222
|
else if (route.returnsJSON === false) {
|
|
219
223
|
http?.response?.arrayBuffer(result);
|
|
220
224
|
}
|
|
221
225
|
else {
|
|
222
|
-
|
|
226
|
+
if (!statusSetByRoute) {
|
|
227
|
+
http?.response?.status(200);
|
|
228
|
+
}
|
|
223
229
|
http?.response?.json(result);
|
|
224
230
|
}
|
|
225
231
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
export { PikkuFetchHTTPRequest, DEFAULT_MAX_BODY_SIZE, } from './pikku-fetch-http-request.js';
|
|
2
|
-
export type { PikkuFetchHTTPRequestOptions } from './pikku-fetch-http-request.js';
|
|
3
2
|
export { PikkuFetchHTTPResponse } from './pikku-fetch-http-response.js';
|
|
4
3
|
export { logRoutes } from './log-http-routes.js';
|
|
5
4
|
export { fetch, fetchData, wireHTTP, addHTTPMiddleware } from './http-runner.js';
|
|
6
5
|
export { wireHTTPRoutes, defineHTTPRoutes } from './http-routes.js';
|
|
7
6
|
export { toWebRequest, applyWebResponse } from './web-request.js';
|
|
8
|
-
export type { AssertHTTPWiringParams, CoreHTTPFunctionWiring, HTTPMethod, HTTPRouteBaseConfig, HTTPRouteContract, HTTPRouteMap, HTTPWiringsMeta, PikkuHTTPRequest, PikkuHTTPResponse, PikkuQuery, RunHTTPWiringOptions, } from './http.types.js';
|
|
7
|
+
export type { AssertHTTPWiringParams, CoreHTTPFunctionWiring, HTTPMethod, HTTPRouteBaseConfig, HTTPRouteContract, HTTPRouteMap, HTTPWiringsMeta, PikkuHTTP, PikkuHTTPRequest, PikkuHTTPResponse, PikkuQuery, RunHTTPWiringOptions, } from './http.types.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { MCPEndpointRegistry } from './mcp-endpoint-registry.js';
|
|
2
2
|
export { MCPError, wireMCPResource, wireMCPPrompt, runMCPResource, runMCPTool, runMCPPrompt, } from './mcp-runner.js';
|
|
3
3
|
export { getMCPResourcesMeta, getMCPToolsMeta, getMCPPromptsMeta, } from './mcp-runner.js';
|
|
4
|
-
export type { AssertMCPResourceURIParams, CoreMCPPrompt, CoreMCPResource,
|
|
4
|
+
export type { AssertMCPResourceURIParams, CoreMCPPrompt, CoreMCPResource, MCPPromptResponse, MCPResourceMeta, MCPResourceResponse, MCPToolMeta, MCPToolResponse, MCPPromptMeta, PikkuMCP, } from './mcp.types.js';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { PikkuHTTP } from '../http/http.types.js';
|
|
1
2
|
import type { CoreMCPResource, CoreMCPPrompt, JsonRpcRequest, JsonRpcResponse, JsonRpcErrorResponse, PikkuMCP } from './mcp.types.js';
|
|
2
3
|
import type { CorePikkuFunctionConfig, CorePikkuFunctionSessionless } from '../../function/functions.types.js';
|
|
3
4
|
export declare class MCPError extends Error {
|
|
@@ -6,6 +7,20 @@ export declare class MCPError extends Error {
|
|
|
6
7
|
}
|
|
7
8
|
export type RunMCPEndpointParams<Tools extends string = any> = {
|
|
8
9
|
mcp?: PikkuMCP<Tools>;
|
|
10
|
+
/**
|
|
11
|
+
* The HTTP request the MCP call arrived on, when it arrived over HTTP.
|
|
12
|
+
*
|
|
13
|
+
* Auth middleware reads the session off `wire.http.request` — every
|
|
14
|
+
* implementation opens with `if (!http?.request) return` — so without this an
|
|
15
|
+
* MCP call reaches the function unauthenticated no matter what middleware the
|
|
16
|
+
* app has registered, and a tool fronting a session-requiring function can
|
|
17
|
+
* only ever answer 'Authentication required'.
|
|
18
|
+
*
|
|
19
|
+
* Left undefined for transports that have no request to offer, such as stdio.
|
|
20
|
+
* Those remain anonymous, which is a property of the transport rather than a
|
|
21
|
+
* default chosen here.
|
|
22
|
+
*/
|
|
23
|
+
http?: PikkuHTTP;
|
|
9
24
|
/** Defaults to enabled outside production. */
|
|
10
25
|
exposeErrors?: boolean;
|
|
11
26
|
};
|
|
@@ -48,6 +48,11 @@ export async function runMCPResource(request, params, uri) {
|
|
|
48
48
|
let extractedParams = {};
|
|
49
49
|
const metas = pikkuState(null, 'mcp', 'resourcesMeta');
|
|
50
50
|
const endpoints = pikkuState(null, 'mcp', 'resources');
|
|
51
|
+
// The key the resource's meta (and its middleware) is stored under. For a
|
|
52
|
+
// templated resource this is the template, not the concrete request URI — so
|
|
53
|
+
// it must be carried forward, or the meta lookup downstream misses and the
|
|
54
|
+
// resource's declared middleware (including auth) is silently skipped.
|
|
55
|
+
let metaKey = uri;
|
|
51
56
|
if (endpoints.has(uri)) {
|
|
52
57
|
endpoint = endpoints.get(uri);
|
|
53
58
|
pikkuFuncId = metas[uri]?.pikkuFuncId;
|
|
@@ -60,6 +65,7 @@ export async function runMCPResource(request, params, uri) {
|
|
|
60
65
|
const match = uri.match(regex);
|
|
61
66
|
if (match) {
|
|
62
67
|
endpoint = value;
|
|
68
|
+
metaKey = uriTemplate;
|
|
63
69
|
pikkuFuncId = metas[uriTemplate]?.pikkuFuncId;
|
|
64
70
|
for (let i = 0; i < paramNames.length; i++) {
|
|
65
71
|
extractedParams[paramNames[i]] = match[i + 1]; // match[0] is the full match
|
|
@@ -71,7 +77,7 @@ export async function runMCPResource(request, params, uri) {
|
|
|
71
77
|
return await runMCPPikkuFunc({
|
|
72
78
|
...request,
|
|
73
79
|
params: { ...request.params, ...extractedParams },
|
|
74
|
-
}, 'resource', uri, endpoint, pikkuFuncId, { ...params, mcp: { ...params.mcp, uri } });
|
|
80
|
+
}, 'resource', uri, endpoint, pikkuFuncId, { ...params, mcp: { ...params.mcp, uri } }, metaKey);
|
|
75
81
|
}
|
|
76
82
|
export async function runMCPTool(request, params, name) {
|
|
77
83
|
const meta = pikkuState(null, 'mcp', 'toolsMeta')[name];
|
|
@@ -82,7 +88,11 @@ export async function runMCPPrompt(request, params, name) {
|
|
|
82
88
|
const meta = pikkuState(null, 'mcp', 'promptsMeta')[name];
|
|
83
89
|
return await runMCPPikkuFunc(request, 'prompt', name, endpoint, meta?.pikkuFuncId, params);
|
|
84
90
|
}
|
|
85
|
-
async function runMCPPikkuFunc(request, type, name, mcp, pikkuFuncId, { mcp: mcpWire, exposeErrors = !isProduction() }
|
|
91
|
+
async function runMCPPikkuFunc(request, type, name, mcp, pikkuFuncId, { mcp: mcpWire, http, exposeErrors = !isProduction() },
|
|
92
|
+
// The key the endpoint's meta is stored under. Differs from `name` only for a
|
|
93
|
+
// templated resource, where `name` is the concrete URI and the meta lives
|
|
94
|
+
// under the template. Defaults to `name` for tools and prompts.
|
|
95
|
+
metaKey = name) {
|
|
86
96
|
const singletonServices = getSingletonServices();
|
|
87
97
|
const createWireServices = getCreateWireServices();
|
|
88
98
|
try {
|
|
@@ -99,17 +109,20 @@ async function runMCPPikkuFunc(request, type, name, mcp, pikkuFuncId, { mcp: mcp
|
|
|
99
109
|
const mcpSessionService = new PikkuSessionService(singletonServices.sessionStore);
|
|
100
110
|
const wire = {
|
|
101
111
|
mcp: mcpWire,
|
|
112
|
+
// Only when the transport supplied one. Setting `http: undefined`
|
|
113
|
+
// explicitly would be the same to a reader and different to a spread.
|
|
114
|
+
...(http ? { http } : {}),
|
|
102
115
|
...createMiddlewareSessionWireProps(mcpSessionService),
|
|
103
116
|
};
|
|
104
117
|
let meta;
|
|
105
118
|
if (type === 'resource') {
|
|
106
|
-
meta = pikkuState(null, 'mcp', 'resourcesMeta')[
|
|
119
|
+
meta = pikkuState(null, 'mcp', 'resourcesMeta')[metaKey];
|
|
107
120
|
}
|
|
108
121
|
else if (type === 'tool') {
|
|
109
|
-
meta = pikkuState(null, 'mcp', 'toolsMeta')[
|
|
122
|
+
meta = pikkuState(null, 'mcp', 'toolsMeta')[metaKey];
|
|
110
123
|
}
|
|
111
124
|
else if (type === 'prompt') {
|
|
112
|
-
meta = pikkuState(null, 'mcp', 'promptsMeta')[
|
|
125
|
+
meta = pikkuState(null, 'mcp', 'promptsMeta')[metaKey];
|
|
113
126
|
}
|
|
114
127
|
let resolvedFuncName = pikkuFuncId;
|
|
115
128
|
let resolvedPackageName = meta?.packageName ?? null;
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
export { definePersonas } from './define-personas.js';
|
|
2
2
|
export { isRunnablePersona, roleMismatchMessage, runnablePersonas, validateAndBuildPersonasMeta, verifyPersonaRoles, } from './validate-personas.js';
|
|
3
3
|
export type { RoleVerification } from './validate-personas.js';
|
|
4
|
-
export { personaEnvironmentErrors, personaEnvironmentRefusal,
|
|
4
|
+
export { personaEnvironmentErrors, personaEnvironmentRefusal, } from './persona-environments.js';
|
|
5
5
|
export type { PersonaEnvironment, PersonaEnvironmentSubject, } from './persona-environments.js';
|
|
6
|
-
export { personaEmail,
|
|
7
|
-
export { allowedLinks, applyMailboxAllowlist, isAllowedSender, } from './persona-mailbox.js';
|
|
6
|
+
export { personaEmail, personaEmails, } from './persona-email.js';
|
|
8
7
|
export type { MailboxAllowlist, PersonaMailbox, ReceivedEmail, } from './persona-mailbox.js';
|
|
9
|
-
export type { CorePersona,
|
|
8
|
+
export type { CorePersona, CorePersonas, PersonaAccountMeta, PersonaDefinitions, PersonaMeta, PersonasMeta, } from './persona.types.js';
|
|
10
9
|
/**
|
|
11
10
|
* Signing in as a persona and talking to a stage over HTTP.
|
|
12
11
|
*
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
export { definePersonas } from './define-personas.js';
|
|
2
2
|
export { isRunnablePersona, roleMismatchMessage, runnablePersonas, validateAndBuildPersonasMeta, verifyPersonaRoles, } from './validate-personas.js';
|
|
3
|
-
export { personaEnvironmentErrors, personaEnvironmentRefusal,
|
|
4
|
-
export { personaEmail,
|
|
5
|
-
export { allowedLinks, applyMailboxAllowlist, isAllowedSender, } from './persona-mailbox.js';
|
|
3
|
+
export { personaEnvironmentErrors, personaEnvironmentRefusal, } from './persona-environments.js';
|
|
4
|
+
export { personaEmail, personaEmails, } from './persona-email.js';
|
|
6
5
|
/**
|
|
7
6
|
* Signing in as a persona and talking to a stage over HTTP.
|
|
8
7
|
*
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
export type { ConfigValidationResult, CoreQueueWorker, GroupConcurrencyConfig, JobGroup, JobOptions, PikkuJobConfig, PikkuWorkerConfig, PikkuQueue, QueueJob, QueueJobStatus, QueueService, QueueWorkers, QueueWorkersMeta, } from './queue.types.js';
|
|
2
|
-
export { wireQueueWorker, runQueueJob,
|
|
3
|
-
export { QUEUE_IDENTITY_CLAIM_VERSION, QUEUE_IDENTITY_INFO, QUEUE_IDENTITY_SECRET_NAME, getQueueIdentitySecret, resolveQueueJobIdentity, signQueueIdentity, verifyQueueIdentity, } from './queue-identity.js';
|
|
2
|
+
export { wireQueueWorker, runQueueJob, QueueJobDiscardedError, QueueJobFailedError, } from './queue-runner.js';
|
|
4
3
|
export type { QueueIdentityBinding } from './queue-identity.js';
|
|
5
4
|
export { SignedQueueService } from './signed-queue-service.js';
|
|
6
|
-
export { validateWorkerConfig } from './validate-worker-config.js';
|
|
7
5
|
export type { QueueConfigMapping } from './validate-worker-config.js';
|
|
8
6
|
export { registerQueueWorkers } from './register-queue-helper.js';
|
|
9
7
|
export type { QueueRegistrationCallback } from './register-queue-helper.js';
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
export { wireQueueWorker, runQueueJob,
|
|
2
|
-
export { QUEUE_IDENTITY_CLAIM_VERSION, QUEUE_IDENTITY_INFO, QUEUE_IDENTITY_SECRET_NAME, getQueueIdentitySecret, resolveQueueJobIdentity, signQueueIdentity, verifyQueueIdentity, } from './queue-identity.js';
|
|
1
|
+
export { wireQueueWorker, runQueueJob, QueueJobDiscardedError, QueueJobFailedError, } from './queue-runner.js';
|
|
3
2
|
export { SignedQueueService } from './signed-queue-service.js';
|
|
4
|
-
export { validateWorkerConfig } from './validate-worker-config.js';
|
|
5
3
|
export { registerQueueWorkers } from './register-queue-helper.js';
|
|
@@ -4,6 +4,10 @@ export type AddonInstance = {
|
|
|
4
4
|
secretOverrides?: Record<string, string>;
|
|
5
5
|
variableOverrides?: Record<string, string>;
|
|
6
6
|
credentialOverrides?: Record<string, string>;
|
|
7
|
+
/** Set by the consuming app to opt this instance out of secret scoping. */
|
|
8
|
+
globalSecrets?: string;
|
|
9
|
+
/** Set by the consuming app to opt this instance out of credential scoping. */
|
|
10
|
+
globalCredentials?: string;
|
|
7
11
|
};
|
|
8
12
|
export declare const getOrCreatePackageSingletonServices: (packageName: string, parentServices: CoreSingletonServices, addonInstance?: AddonInstance) => Promise<CoreSingletonServices>;
|
|
9
13
|
export declare const addonInstanceForNamespace: (namespace: string | undefined, expectedPackage: string) => AddonInstance | undefined;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { pikkuState } from '../../pikku-state.js';
|
|
2
|
+
import { ScopedSecretService } from '../../services/scoped-secret-service.js';
|
|
3
|
+
import { ScopedCredentialService } from '../../services/scoped-credential-service.js';
|
|
2
4
|
const aliasSecretService = (secrets, overrides) => {
|
|
3
5
|
const map = (key) => overrides[key] ?? key;
|
|
4
6
|
return {
|
|
@@ -79,9 +81,6 @@ export const getOrCreatePackageSingletonServices = async (packageName, parentSer
|
|
|
79
81
|
return cachedServices;
|
|
80
82
|
}
|
|
81
83
|
const factories = pikkuState(packageName, 'package', 'factories');
|
|
82
|
-
if (!factories || !factories.createSingletonServices) {
|
|
83
|
-
return parentServices;
|
|
84
|
-
}
|
|
85
84
|
let existingServices = parentServices;
|
|
86
85
|
if (addonInstance?.secretOverrides && parentServices.secrets) {
|
|
87
86
|
existingServices = {
|
|
@@ -95,6 +94,21 @@ export const getOrCreatePackageSingletonServices = async (packageName, parentSer
|
|
|
95
94
|
variables: aliasVariablesService(parentServices.variables, addonInstance.variableOverrides),
|
|
96
95
|
};
|
|
97
96
|
}
|
|
97
|
+
if (!addonInstance?.globalSecrets && existingServices.secrets) {
|
|
98
|
+
existingServices = {
|
|
99
|
+
...existingServices,
|
|
100
|
+
secrets: new ScopedSecretService(existingServices.secrets, new Set(pikkuState(packageName, 'package', 'declaredSecrets') ?? [])),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
if (!addonInstance?.globalCredentials && existingServices.credentialService) {
|
|
104
|
+
existingServices = {
|
|
105
|
+
...existingServices,
|
|
106
|
+
credentialService: new ScopedCredentialService(existingServices.credentialService, new Set(Object.keys(pikkuState(packageName, 'package', 'credentialsMeta') ?? {}))),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
if (!factories || !factories.createSingletonServices) {
|
|
110
|
+
return existingServices;
|
|
111
|
+
}
|
|
98
112
|
let config = existingServices.config;
|
|
99
113
|
if (factories.createConfig) {
|
|
100
114
|
config = await factories.createConfig(existingServices.variables);
|
|
@@ -118,5 +132,7 @@ export const addonInstanceForNamespace = (namespace, expectedPackage) => {
|
|
|
118
132
|
secretOverrides: cfg.secretOverrides,
|
|
119
133
|
variableOverrides: cfg.variableOverrides,
|
|
120
134
|
credentialOverrides: cfg.credentialOverrides,
|
|
135
|
+
globalSecrets: cfg.globalSecrets,
|
|
136
|
+
globalCredentials: cfg.globalCredentials,
|
|
121
137
|
};
|
|
122
138
|
};
|
|
@@ -203,6 +203,8 @@ export class ContextAwareRPCService {
|
|
|
203
203
|
secretOverrides: resolved.addonConfig?.secretOverrides,
|
|
204
204
|
variableOverrides: resolved.addonConfig?.variableOverrides,
|
|
205
205
|
credentialOverrides: resolved.addonConfig?.credentialOverrides,
|
|
206
|
+
globalSecrets: resolved.addonConfig?.globalSecrets,
|
|
207
|
+
globalCredentials: resolved.addonConfig?.globalCredentials,
|
|
206
208
|
},
|
|
207
209
|
};
|
|
208
210
|
}
|
|
@@ -48,6 +48,10 @@ export interface ResolvedFunction {
|
|
|
48
48
|
secretOverrides?: Record<string, string>;
|
|
49
49
|
variableOverrides?: Record<string, string>;
|
|
50
50
|
credentialOverrides?: Record<string, string>;
|
|
51
|
+
/** Set by the consuming app: hand this instance the unscoped `SecretService` */
|
|
52
|
+
globalSecrets?: string;
|
|
53
|
+
/** Set by the consuming app: hand this instance the unscoped `CredentialService` */
|
|
54
|
+
globalCredentials?: string;
|
|
51
55
|
/** Set by `wireRemoteAddon`: dispatch this namespace's RPCs over HTTP */
|
|
52
56
|
remote?: boolean;
|
|
53
57
|
serverUrl?: string | ((services: any) => string | Promise<string>);
|
|
@@ -11,6 +11,19 @@ export type WireAddonConfig = {
|
|
|
11
11
|
secretOverrides?: Record<string, string>;
|
|
12
12
|
variableOverrides?: Record<string, string>;
|
|
13
13
|
credentialOverrides?: Record<string, string>;
|
|
14
|
+
/**
|
|
15
|
+
* Hands this instance the whole `SecretService` instead of one scoped to the
|
|
16
|
+
* secrets it declared. The value is the reason, recorded in the deploy
|
|
17
|
+
* manifest — an addon that names secrets at runtime cannot be scoped, and
|
|
18
|
+
* only the consuming app, never the addon, can grant it.
|
|
19
|
+
*/
|
|
20
|
+
globalSecrets?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Hands this instance the whole `CredentialService` instead of one narrowed
|
|
23
|
+
* to the credentials it declared. The value is the reason, recorded in the
|
|
24
|
+
* deploy manifest, and only the consuming app can grant it.
|
|
25
|
+
*/
|
|
26
|
+
globalCredentials?: string;
|
|
14
27
|
};
|
|
15
28
|
export declare const wireAddon: (config: WireAddonConfig) => void;
|
|
16
29
|
/**
|
|
@@ -16,6 +16,10 @@ export const wireAddon = (config) => {
|
|
|
16
16
|
...(config.credentialOverrides
|
|
17
17
|
? { credentialOverrides: config.credentialOverrides }
|
|
18
18
|
: {}),
|
|
19
|
+
...(config.globalSecrets ? { globalSecrets: config.globalSecrets } : {}),
|
|
20
|
+
...(config.globalCredentials
|
|
21
|
+
? { globalCredentials: config.globalCredentials }
|
|
22
|
+
: {}),
|
|
19
23
|
});
|
|
20
24
|
};
|
|
21
25
|
/**
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { runScheduledTask, wireScheduler, getScheduledTasks, } from './scheduler-runner.js';
|
|
2
2
|
export { logSchedulers } from './log-schedulers.js';
|
|
3
|
-
export type { CoreScheduledTask, ScheduledTasksMeta,
|
|
3
|
+
export type { CoreScheduledTask, ScheduledTasksMeta, } from './scheduler.types.js';
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { wireTrigger, wireTriggerSource } from './trigger-runner.js';
|
|
2
2
|
export { PikkuTriggerService } from './pikku-trigger-service.js';
|
|
3
|
-
export type { TriggerMeta, TriggerSourceMeta, CorePikkuTriggerFunction, CorePikkuTriggerFunctionConfig, CoreTrigger,
|
|
3
|
+
export type { TriggerMeta, TriggerSourceMeta, CorePikkuTriggerFunction, CorePikkuTriggerFunctionConfig, CoreTrigger, } from './trigger.types.js';
|
|
@@ -16,15 +16,14 @@
|
|
|
16
16
|
* {@link VirtualUserTarget}, which in production is an `HttpPersona`
|
|
17
17
|
* signed in as a real user against staging or production.
|
|
18
18
|
*/
|
|
19
|
-
export type { ApiCatalogueEntry,
|
|
19
|
+
export type { ApiCatalogueEntry, IntentSource, VirtualUserDisposition, VirtualUserFinding, VirtualUserRunResult, VirtualUserTarget, } from './virtual-user.types.js';
|
|
20
20
|
export { PRODUCTION_DISPOSITION } from './virtual-user.types.js';
|
|
21
|
-
export { runVirtualUser,
|
|
21
|
+
export { runVirtualUser, type RunVirtualUserParams, } from './run-virtual-user.js';
|
|
22
22
|
export { personaScopes, prepareVirtualUserRun, type VirtualUserPreparation, } from './prepare-virtual-user-run.js';
|
|
23
23
|
export type { VirtualUserRunOutcome, VirtualUserRunRecord, VirtualUserRunStart, VirtualUserRunStore, } from './virtual-user-run-store.js';
|
|
24
24
|
export { DISPOSITIONS, dispositionProfile, type DispositionProfile, type VirtualUserTuning, } from './virtual-user-dispositions.js';
|
|
25
|
-
export { catalogueClassification,
|
|
26
|
-
export {
|
|
27
|
-
export { IntentStack, intentsForPersona,
|
|
28
|
-
export { createRng, type VirtualUserRng } from './virtual-user-rng.js';
|
|
25
|
+
export { catalogueClassification, catalogueLookup, isReadOnly, reachableCatalogue, unreachableCatalogue, } from './virtual-user-catalogue.js';
|
|
26
|
+
export { type AgentReachability, type ReachableAgent, } from './virtual-user-agents.js';
|
|
27
|
+
export { IntentStack, intentsForPersona, } from './virtual-user-intents.js';
|
|
29
28
|
export { deriveCatalogue, deriveIntents, type SchemaMap, } from './virtual-user-derive.js';
|
|
30
29
|
export { personaVirtualUserTarget, type PersonaTargetOptions, } from './virtual-user-target.js';
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
export { PRODUCTION_DISPOSITION } from './virtual-user.types.js';
|
|
2
|
-
export { runVirtualUser,
|
|
2
|
+
export { runVirtualUser, } from './run-virtual-user.js';
|
|
3
3
|
export { personaScopes, prepareVirtualUserRun, } from './prepare-virtual-user-run.js';
|
|
4
4
|
export { DISPOSITIONS, dispositionProfile, } from './virtual-user-dispositions.js';
|
|
5
|
-
export { catalogueClassification,
|
|
6
|
-
export { reachableAgents, } from './virtual-user-agents.js';
|
|
5
|
+
export { catalogueClassification, catalogueLookup, isReadOnly, reachableCatalogue, unreachableCatalogue, } from './virtual-user-catalogue.js';
|
|
7
6
|
export { IntentStack, intentsForPersona, } from './virtual-user-intents.js';
|
|
8
|
-
export { createRng } from './virtual-user-rng.js';
|
|
9
7
|
export { deriveCatalogue, deriveIntents, } from './virtual-user-derive.js';
|
|
10
8
|
export { personaVirtualUserTarget, } from './virtual-user-target.js';
|
|
@@ -53,6 +53,19 @@ export interface WorkflowExpectServiceOptions extends WorkflowStepOptions {
|
|
|
53
53
|
/** Assert the exact number of matching calls. Default: at least one. */
|
|
54
54
|
times?: number;
|
|
55
55
|
}
|
|
56
|
+
/** Options for workflow.expectScore() */
|
|
57
|
+
export interface WorkflowExpectScoreOptions extends WorkflowStepOptions {
|
|
58
|
+
/** Fail below this score. Defaults to 0.5 — a scorer that answered at all. */
|
|
59
|
+
atLeast?: number;
|
|
60
|
+
/** Fail above this score, for a scorer where high is the failure. */
|
|
61
|
+
atMost?: number;
|
|
62
|
+
/**
|
|
63
|
+
* The known-correct answer, which is what a reference-based judge grades
|
|
64
|
+
* against. Live traffic has no answer key, so a judge declared
|
|
65
|
+
* `requiresReference` is only ever reachable from a scenario.
|
|
66
|
+
*/
|
|
67
|
+
reference?: string;
|
|
68
|
+
}
|
|
56
69
|
/**
|
|
57
70
|
* Type signature for workflow.do() RPC form - used by inspector
|
|
58
71
|
*/
|
|
@@ -80,10 +93,50 @@ export type WorkflowWireSleep = (stepName: string, duration: string) => Promise<
|
|
|
80
93
|
* loops, like dynamic `do()` step names.
|
|
81
94
|
*/
|
|
82
95
|
export type WorkflowWireSuspend = (reason: string) => Promise<void>;
|
|
96
|
+
/**
|
|
97
|
+
* Who is allowed to answer an approval gate, relative to the user who started
|
|
98
|
+
* the run.
|
|
99
|
+
*
|
|
100
|
+
* - `any` — anyone the approve entrypoint lets through. The gate is a pause for
|
|
101
|
+
* a decision, not an authorization boundary.
|
|
102
|
+
* - `owner` — only the user who started the run, so a gate can be used to
|
|
103
|
+
* confirm an action against the same person who requested it.
|
|
104
|
+
* - `not-initiator` — anyone *except* the user who started the run: four-eyes.
|
|
105
|
+
* A run with no recorded initiator has nobody to exclude, so this degrades to
|
|
106
|
+
* requiring a signed-in decider.
|
|
107
|
+
*/
|
|
108
|
+
export type WorkflowApprovalApprovers = 'any' | 'owner' | 'not-initiator';
|
|
109
|
+
/**
|
|
110
|
+
* Who may answer an approval gate. Declared on the gate rather than the
|
|
111
|
+
* entrypoint because it is a property of the decision being made, and because
|
|
112
|
+
* one workflow can hold several gates with different requirements.
|
|
113
|
+
*/
|
|
114
|
+
export interface WorkflowApprovalPolicy {
|
|
115
|
+
/**
|
|
116
|
+
* Defaults to `any`. See {@link WorkflowApprovalApprovers}.
|
|
117
|
+
*/
|
|
118
|
+
approvers?: WorkflowApprovalApprovers;
|
|
119
|
+
/**
|
|
120
|
+
* Additionally require the decider's session to hold this scope, so
|
|
121
|
+
* "a second pair of eyes" can be narrowed to "a second pair of *senior*
|
|
122
|
+
* eyes". Combines with `approvers` — both must pass.
|
|
123
|
+
*/
|
|
124
|
+
approverScope?: string;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* The decider, reduced to the two facts a policy can be expressed in terms of.
|
|
128
|
+
* Recorded alongside the decision so the gate can be judged on replay — the
|
|
129
|
+
* session itself is long gone by then — and carried into the settled outcome so
|
|
130
|
+
* the answer keeps its provenance.
|
|
131
|
+
*/
|
|
132
|
+
export interface ApprovalDecider {
|
|
133
|
+
userId?: string;
|
|
134
|
+
scopes?: string[];
|
|
135
|
+
}
|
|
83
136
|
/**
|
|
84
137
|
* Options for workflow.approval().
|
|
85
138
|
*/
|
|
86
|
-
export interface WorkflowApprovalOptions<TSchema extends StandardSchemaV1 = StandardSchemaV1> {
|
|
139
|
+
export interface WorkflowApprovalOptions<TSchema extends StandardSchemaV1 = StandardSchemaV1> extends WorkflowApprovalPolicy {
|
|
87
140
|
/**
|
|
88
141
|
* Schema the decision payload is validated against. This is a VALUE, not a
|
|
89
142
|
* type generic: the payload arrives from an untrusted caller over the approve
|
|
@@ -107,6 +160,14 @@ export interface WorkflowApprovalOptions<TSchema extends StandardSchemaV1 = Stan
|
|
|
107
160
|
export type ApprovalOutcome<T> = {
|
|
108
161
|
status: 'decided';
|
|
109
162
|
data: T;
|
|
163
|
+
/**
|
|
164
|
+
* Who answered, and when. Run state holds the decision only while the gate
|
|
165
|
+
* is open — it is overwritten by the next write and cleared outright when a
|
|
166
|
+
* decision is refused — so the settled answer carries its own provenance
|
|
167
|
+
* into the step result, which is append-only.
|
|
168
|
+
*/
|
|
169
|
+
decidedBy?: ApprovalDecider;
|
|
170
|
+
decidedAt?: string;
|
|
110
171
|
} | {
|
|
111
172
|
status: 'expired';
|
|
112
173
|
};
|
|
@@ -386,6 +447,10 @@ export interface ApprovalStepMeta {
|
|
|
386
447
|
outputVar?: string;
|
|
387
448
|
/** Expiry duration, when one was given */
|
|
388
449
|
expiry?: string | number;
|
|
450
|
+
/** Who may answer the gate, when the default was not used */
|
|
451
|
+
approvers?: WorkflowApprovalApprovers;
|
|
452
|
+
/** Scope the decider must hold, when one was required */
|
|
453
|
+
approverScope?: string;
|
|
389
454
|
}
|
|
390
455
|
/**
|
|
391
456
|
* Filter step metadata (array.filter)
|
|
@@ -476,25 +541,21 @@ export interface PikkuWorkflowWire {
|
|
|
476
541
|
/**
|
|
477
542
|
* What a scenario has accumulated so far, shared by its body and its hooks.
|
|
478
543
|
*
|
|
479
|
-
*
|
|
480
|
-
*
|
|
481
|
-
*
|
|
482
|
-
* object output gets an open record rather than `Partial<never>`.
|
|
544
|
+
* `Partial` because a scenario can fail at any step: `Out` describes what a
|
|
545
|
+
* *completed* run produces, and the context holds however much of it this run
|
|
546
|
+
* reached.
|
|
483
547
|
*
|
|
484
|
-
* `
|
|
485
|
-
*
|
|
486
|
-
* and a constraint carrying a concrete
|
|
487
|
-
* scenario output differs from it.
|
|
548
|
+
* The `0 extends 1 & Out` branch keeps `any` collapsing to `any` rather than to
|
|
549
|
+
* the union of the other two. `PikkuWire` and `PikkuFunctionConfig` both use
|
|
550
|
+
* this type as a generic *constraint*, and a constraint carrying a concrete
|
|
551
|
+
* context would reject every wire whose scenario output differs from it.
|
|
488
552
|
*/
|
|
489
553
|
export type ScenarioContext<Out = unknown> = 0 extends 1 & Out ? any : Out extends object ? Partial<Out> : Record<string, unknown>;
|
|
490
554
|
export interface PikkuScenarioWire<Out = unknown> extends PikkuWorkflowWire {
|
|
491
555
|
/**
|
|
492
|
-
* Scratch the body writes and the `before`/`after` hooks read.
|
|
493
|
-
*
|
|
494
|
-
*
|
|
495
|
-
* is why teardown had nowhere to learn the ids the body minted. Assigning
|
|
496
|
-
* them here (`scenario.context.projectId = project.projectId`) hands them to
|
|
497
|
-
* `after`, which runs in a `finally` and so cleans up on a failed run too.
|
|
556
|
+
* Scratch the body writes and the `before`/`after` hooks read. A hook is a
|
|
557
|
+
* separate function and cannot see the body's locals, so this is how teardown
|
|
558
|
+
* learns the ids the body minted.
|
|
498
559
|
*
|
|
499
560
|
* Deliberately *not* a world: it is scoped to one run, and scenario steps
|
|
500
561
|
* cannot reach it. Steps stay pure functions of their declared inputs, so the
|
|
@@ -510,6 +571,15 @@ export interface PikkuScenarioWire<Out = unknown> extends PikkuWorkflowWire {
|
|
|
510
571
|
expectError: <TInput = any>(stepName: string, rpcName: string, data: TInput, options?: WorkflowExpectErrorOptions) => Promise<string>;
|
|
511
572
|
/** Stub-assertion step: asserts `service.method` was called on the target server */
|
|
512
573
|
expectService: (stepName: string, serviceMethod: string, options?: WorkflowExpectServiceOptions) => Promise<void>;
|
|
574
|
+
/**
|
|
575
|
+
* Grade-assertion step: runs one declared scorer against a finished agent run
|
|
576
|
+
* and asserts the score. Returns the grade, so a scenario can report the
|
|
577
|
+
* reason a judge gave rather than only that it fell short.
|
|
578
|
+
*/
|
|
579
|
+
expectScore: (stepName: string, runId: string, scorerName: string, options?: WorkflowExpectScoreOptions) => Promise<{
|
|
580
|
+
score: number;
|
|
581
|
+
reason?: string;
|
|
582
|
+
}>;
|
|
513
583
|
/**
|
|
514
584
|
* Run a registered scenario step, as the setup the scenario starts from.
|
|
515
585
|
*
|
|
@@ -2,23 +2,23 @@ export { PikkuWorkflowService } from './pikku-workflow-service.js';
|
|
|
2
2
|
export { WorkflowCancelledException, WorkflowSuspendedException, WorkflowDispatchException, WorkflowNotFoundError, WorkflowRunNotFoundError, WorkflowApprovalResolvedError, WorkflowStepFunctionMismatchError, } from './workflow-errors.js';
|
|
3
3
|
export { DEFAULT_STEP_RETRIES } from './workflow-constants.js';
|
|
4
4
|
export { assertWorkflowRunOwner, WorkflowRunForbiddenError, } from './workflow-run-ownership.js';
|
|
5
|
-
export
|
|
5
|
+
export { WorkflowApprovalForbiddenError } from './workflow-approval-policy.js';
|
|
6
|
+
export type { WorkflowRunEngine, WorkflowRunExtension, } from './workflow-run-engine.types.js';
|
|
6
7
|
export { deriveInvocationId, uuidv5 } from './workflow-invocation-id.js';
|
|
7
8
|
export { isRef } from './graph/workflow-graph.types.js';
|
|
8
9
|
export type { RefValue } from './graph/workflow-graph.types.js';
|
|
9
10
|
export { buildRunTimeline, reconstructStateAt, reconstructFinalState, } from './run-timeline.js';
|
|
10
|
-
export type { RunTimeline,
|
|
11
|
+
export type { RunTimeline, ReconstructedRunState, } from './run-timeline.js';
|
|
11
12
|
export { addWorkflow } from './dsl/workflow-runner.js';
|
|
12
13
|
export { addFeature, resolveFeatureScenarios } from './feature.js';
|
|
13
14
|
export { template, type TemplateString } from './graph/template.js';
|
|
14
15
|
export { pikkuWorkflowGraph, type PikkuWorkflowGraphConfig, type PikkuWorkflowGraphResult, } from './graph/wire-workflow-graph.js';
|
|
15
|
-
export { pikkuWorkflowWorkerFunc, pikkuWorkflowOrchestratorFunc, pikkuWorkflowSleeperFunc, } from './workflow-queue-workers.js';
|
|
16
16
|
export type { WorkflowStepInput as WorkflowStepQueueInput, PikkuWorkflowOrchestratorInput, PikkuWorkflowSleeperInput, } from './workflow-queue-workers.js';
|
|
17
|
-
export type { WorkflowService, WorkflowQueueOptions, WorkflowServiceConfig, WorkflowPlannedStep, WorkflowRunWire, WorkflowStatus, WorkflowVersionStatus, StepStatus, WorkflowRun, WorkflowRunStatus, StepState, WorkflowRunService, WorkflowRunMirror, CoreWorkflow, CoreFeature,
|
|
18
|
-
export type { WorkflowStepOptions, WorkflowWireDoRPC,
|
|
17
|
+
export type { WorkflowService, WorkflowQueueOptions, WorkflowServiceConfig, WorkflowPlannedStep, WorkflowRunWire, WorkflowStatus, WorkflowVersionStatus, StepStatus, WorkflowRun, WorkflowRunStatus, StepState, WorkflowRunService, WorkflowRunMirror, CoreWorkflow, CoreFeature, FeatureMeta, FeaturesMeta, FeaturePlanEntry, PikkuWorkflow, ContextVariable, WorkflowContext, WorkflowsMeta, WorkflowsRuntimeMeta, } from './workflow.types.js';
|
|
18
|
+
export type { WorkflowStepOptions, WorkflowWireDoRPC, WorkflowApprovalOptions, ApprovalOutcome, InputSource, OutputBinding, RpcStepMeta, Condition, BranchStepMeta, ParallelGroupStepMeta, FanoutStepMeta, ReturnStepMeta, InlineStepMeta, SleepStepMeta, CancelStepMeta, SuspendStepMeta, ApprovalStepMeta, SetStepMeta, SwitchCaseMeta, SwitchStepMeta, FilterStepMeta, ArrayPredicateStepMeta, ScenarioStepInvocation, ScenarioStepMeta, WorkflowStepMeta, WorkflowStepWire, PikkuWorkflowWire, PikkuScenarioWire, } from './workflow.types.js';
|
|
19
19
|
export type { ScenarioStepPhase, ScenarioStepKind, ScenarioStepOptions, PikkuScenarioStepWire, ScenarioEnvironment, ScenarioSurface, ScenarioSurfaceResolution, } from './scenario-step.types.js';
|
|
20
20
|
export { SCENARIO_SURFACES } from './scenario-step.types.js';
|
|
21
|
-
export { resolveScenarioSurfaces
|
|
21
|
+
export { resolveScenarioSurfaces } from './scenario-surface.js';
|
|
22
22
|
export { requireActor, requireScenarioEnv } from './scenario-step-guards.js';
|
|
23
23
|
export { pollUntil, type PollOptions } from './scenario-poll.js';
|
|
24
24
|
export { createCookieJar } from './scenario-cookie-jar.js';
|
|
@@ -2,6 +2,7 @@ export { PikkuWorkflowService } from './pikku-workflow-service.js';
|
|
|
2
2
|
export { WorkflowCancelledException, WorkflowSuspendedException, WorkflowDispatchException, WorkflowNotFoundError, WorkflowRunNotFoundError, WorkflowApprovalResolvedError, WorkflowStepFunctionMismatchError, } from './workflow-errors.js';
|
|
3
3
|
export { DEFAULT_STEP_RETRIES } from './workflow-constants.js';
|
|
4
4
|
export { assertWorkflowRunOwner, WorkflowRunForbiddenError, } from './workflow-run-ownership.js';
|
|
5
|
+
export { WorkflowApprovalForbiddenError } from './workflow-approval-policy.js';
|
|
5
6
|
export { deriveInvocationId, uuidv5 } from './workflow-invocation-id.js';
|
|
6
7
|
export { isRef } from './graph/workflow-graph.types.js';
|
|
7
8
|
export { buildRunTimeline, reconstructStateAt, reconstructFinalState, } from './run-timeline.js';
|
|
@@ -9,10 +10,9 @@ export { addWorkflow } from './dsl/workflow-runner.js';
|
|
|
9
10
|
export { addFeature, resolveFeatureScenarios } from './feature.js';
|
|
10
11
|
export { template } from './graph/template.js';
|
|
11
12
|
export { pikkuWorkflowGraph, } from './graph/wire-workflow-graph.js';
|
|
12
|
-
export { pikkuWorkflowWorkerFunc, pikkuWorkflowOrchestratorFunc, pikkuWorkflowSleeperFunc, } from './workflow-queue-workers.js';
|
|
13
13
|
export { SCENARIO_SURFACES } from './scenario-step.types.js';
|
|
14
14
|
// Which of a step's bindings run: one for an action, every witness for a `then`
|
|
15
|
-
export { resolveScenarioSurfaces
|
|
15
|
+
export { resolveScenarioSurfaces } from './scenario-surface.js';
|
|
16
16
|
export { requireActor, requireScenarioEnv } from './scenario-step-guards.js';
|
|
17
17
|
export { pollUntil } from './scenario-poll.js';
|
|
18
18
|
export { createCookieJar } from './scenario-cookie-jar.js';
|