@pikku/core 0.12.148 → 0.12.150
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/wirings/addon/define-plugin.d.ts +10 -0
- package/dist/wirings/agent/agent-prepare.d.ts +9 -2
- package/dist/wirings/agent/agent-prepare.js +14 -6
- package/dist/wirings/agent/agent-rpc.js +1 -1
- package/dist/wirings/agent/agent-runner.js +2 -6
- package/dist/wirings/agent/agent-stream.js +2 -6
- package/package.json +1 -1
|
@@ -22,6 +22,16 @@ type StudioScreenBase = {
|
|
|
22
22
|
layout?: 'bare';
|
|
23
23
|
/** Hides the screen and its nav for viewers without access. The addon's functions must enforce the same scopes: hiding a screen is not access control. */
|
|
24
24
|
scopes?: string[];
|
|
25
|
+
/**
|
|
26
|
+
* The agent that answers in Studio's chat panel while this screen is open.
|
|
27
|
+
* `'studio:<name>'` names an agent Studio ships (e.g. `'studio:knowledge'`);
|
|
28
|
+
* `pikku all` only checks its format. A bare name is an agent the addon ships:
|
|
29
|
+
* it resolves to `agents/<name>.md` in the addon package: the agent's
|
|
30
|
+
* instructions, which name the skills it follows. Its frontmatter has a
|
|
31
|
+
* `title` and a `description`, both message keys in the addon's catalog.
|
|
32
|
+
* Lowercase letters, digits and hyphens, starting with a letter. Leave it out and the chat is unchanged.
|
|
33
|
+
*/
|
|
34
|
+
agent?: string;
|
|
25
35
|
} & ({
|
|
26
36
|
/** `'studio'` gives `/<path>`, `'team'` gives `/<team>/<path>`. */
|
|
27
37
|
scope: 'studio' | 'team';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { CoreUserSession, GetCredential } from '../../types/core.types.js';
|
|
2
2
|
import type { CoreAgent, AgentInput, AgentToolDef, AgentMessage, AgentStreamChannel, PikkuAgentMiddlewareHooks, SessionScope } from './agent.types.js';
|
|
3
|
-
import type { AgentRunnerParams } from '../../services/agent-runner-service.js';
|
|
3
|
+
import type { AgentRunnerParams, AgentRunnerService } from '../../services/agent-runner-service.js';
|
|
4
4
|
import { PikkuError } from '../../errors/error-handler.js';
|
|
5
5
|
import type { SessionService } from '../../services/user-session-service.js';
|
|
6
6
|
/**
|
|
@@ -155,11 +155,18 @@ export declare function buildToolDefs(params: RunAgentParams, agentSessionMap: M
|
|
|
155
155
|
tools: AgentToolDef[];
|
|
156
156
|
missingRpcs: string[];
|
|
157
157
|
}>;
|
|
158
|
+
/**
|
|
159
|
+
* The singleton `agentRunner`, keyed with the caller's `AI_API_KEY` credential when one is set.
|
|
160
|
+
* Every entry that calls the model (run, stream, approve, resume) goes through this.
|
|
161
|
+
*/
|
|
162
|
+
export declare function resolveAgentRunner(singletonServices: {
|
|
163
|
+
agentRunner?: AgentRunnerService;
|
|
164
|
+
}, params: RunAgentParams): Promise<AgentRunnerService>;
|
|
158
165
|
export declare function prepareAgentRun(agentName: string, input: AgentInput, params: RunAgentParams, agentSessionMap: Map<string, string>, streamContext?: StreamContext): Promise<{
|
|
159
166
|
agent: CoreAgent;
|
|
160
167
|
packageName: string | null;
|
|
161
168
|
resolvedName: string;
|
|
162
|
-
agentRunner:
|
|
169
|
+
agentRunner: AgentRunnerService;
|
|
163
170
|
storage: import("../../services/agent-storage-service.js").AgentStorageService | undefined;
|
|
164
171
|
memoryConfig: import("./agent.types.js").AgentMemoryConfig | undefined;
|
|
165
172
|
threadId: string;
|
|
@@ -679,20 +679,28 @@ export async function buildToolDefs(params, agentSessionMap, resourceId, agentNa
|
|
|
679
679
|
}
|
|
680
680
|
return { tools, missingRpcs };
|
|
681
681
|
}
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
682
|
+
/**
|
|
683
|
+
* The singleton `agentRunner`, keyed with the caller's `AI_API_KEY` credential when one is set.
|
|
684
|
+
* Every entry that calls the model (run, stream, approve, resume) goes through this.
|
|
685
|
+
*/
|
|
686
|
+
export async function resolveAgentRunner(singletonServices, params) {
|
|
687
|
+
const agentRunner = singletonServices.agentRunner;
|
|
687
688
|
if (!agentRunner) {
|
|
688
689
|
throw new AIProviderNotConfiguredError();
|
|
689
690
|
}
|
|
690
691
|
if (params.getCredential && agentRunner.withApiKey) {
|
|
691
692
|
const aiCredential = await params.getCredential('AI_API_KEY');
|
|
692
693
|
if (aiCredential?.apiKey?.trim()) {
|
|
693
|
-
|
|
694
|
+
return agentRunner.withApiKey(aiCredential.apiKey);
|
|
694
695
|
}
|
|
695
696
|
}
|
|
697
|
+
return agentRunner;
|
|
698
|
+
}
|
|
699
|
+
export async function prepareAgentRun(agentName, input, params, agentSessionMap, streamContext) {
|
|
700
|
+
const singletonServices = getSingletonServices();
|
|
701
|
+
const { agent, packageName, resolvedName } = resolveAgent(agentName);
|
|
702
|
+
await assertAgentAuthorized(agent, params, packageName);
|
|
703
|
+
const agentRunner = await resolveAgentRunner(singletonServices, params);
|
|
696
704
|
const { storage } = resolveMemoryServices(agent, singletonServices);
|
|
697
705
|
const memoryConfig = agent.memory;
|
|
698
706
|
const threadId = input.threadId;
|
|
@@ -50,7 +50,7 @@ export const createAgentRPC = (wire, options) => {
|
|
|
50
50
|
await resumeAgent({ runId, ...input }, wrapChannelWithAGUI(streamingChannel(), { runId }), params(), streamOptions);
|
|
51
51
|
},
|
|
52
52
|
interrupt: async (runId, reason) => interruptAgent({ runId, ...(reason ? { reason } : {}) }, { sessionService: options.sessionService }),
|
|
53
|
-
approve: async (runId, approvals, expectedAgentName) => asRunResult(await resumeAgentSync(runId, approvals,
|
|
53
|
+
approve: async (runId, approvals, expectedAgentName) => asRunResult(await resumeAgentSync(runId, approvals, params(), expectedAgentName === undefined
|
|
54
54
|
? undefined
|
|
55
55
|
: mapAddonCall(wire.addonNamespace, expectedAgentName))),
|
|
56
56
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { saveMessages, resolveMemoryServices, loadContextMessages, trimMessages, getWorkingMemoryMiddleware, } from './agent-memory.js';
|
|
2
|
-
import { prepareAgentRun, resolveAgent, buildInstructions, buildToolDefs, resolveOwnerResourceId, agentSessionScope, assertResourcePrincipalOwner, assertRunBelongsToAgent, assertAgentAuthorized, } from './agent-prepare.js';
|
|
2
|
+
import { prepareAgentRun, resolveAgent, buildInstructions, buildToolDefs, resolveOwnerResourceId, agentSessionScope, assertResourcePrincipalOwner, assertRunBelongsToAgent, assertAgentAuthorized, resolveAgentRunner, } from './agent-prepare.js';
|
|
3
3
|
import { checkForApprovals, appendStepMessages } from './agent-stream.js';
|
|
4
4
|
import { AgentInterruptedError, isAbortError, persistOrphanedToolResults, registerInterruptibleRun, trackInterruptNote, trackToolExecution, } from './agent-interrupt.js';
|
|
5
5
|
import { pikkuState, getSingletonServices } from '../../pikku-state.js';
|
|
@@ -7,7 +7,6 @@ import { applyInputMiddleware, describeApprovals, notifyAfterStep, toAccumulated
|
|
|
7
7
|
import { applyOutputMiddleware, finalizeAgentRun, lastUserMessageText, } from './agent-finalize.js';
|
|
8
8
|
import { resolveModelConfig } from './agent-model-config.js';
|
|
9
9
|
import { validateAgentOutput } from './agent-output.js';
|
|
10
|
-
import { AIProviderNotConfiguredError } from '../../errors/errors.js';
|
|
11
10
|
import { deniedToolResult, randomUUID } from './agent-utils.js';
|
|
12
11
|
function stripNulls(obj) {
|
|
13
12
|
if (obj === null)
|
|
@@ -308,10 +307,7 @@ export async function resumeAgentSync(runId, approvals, params, expectedAgentNam
|
|
|
308
307
|
await assertAgentAuthorized(agent, params, packageName);
|
|
309
308
|
const { storage } = resolveMemoryServices(agent, singletonServices);
|
|
310
309
|
const memoryConfig = agent.memory;
|
|
311
|
-
const agentRunner = singletonServices
|
|
312
|
-
if (!agentRunner) {
|
|
313
|
-
throw new AIProviderNotConfiguredError();
|
|
314
|
-
}
|
|
310
|
+
const agentRunner = await resolveAgentRunner(singletonServices, params);
|
|
315
311
|
const approvedIds = new Set(approvals.filter((a) => a.approved).map((a) => a.toolCallId));
|
|
316
312
|
const rejectedIds = new Set(approvals.filter((a) => !a.approved).map((a) => a.toolCallId));
|
|
317
313
|
const savedPendingApprovals = [...(run.pendingApprovals ?? [])];
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { finalizeAgentRun, lastUserMessageText } from './agent-finalize.js';
|
|
2
2
|
import { pikkuState, getSingletonServices } from '../../pikku-state.js';
|
|
3
3
|
import { applyInputMiddleware, describeApprovals } from './agent-turn.js';
|
|
4
|
-
import { AIProviderNotConfiguredError } from '../../errors/errors.js';
|
|
5
4
|
import { deniedToolResult, randomUUID } from './agent-utils.js';
|
|
6
5
|
import { SPOKEN_TRANSCRIPT } from './voice-input.js';
|
|
7
6
|
import { combineChannelMiddleware, wrapChannelWithMiddleware, } from '../../channel-middleware-runner.js';
|
|
8
7
|
import { resolveMemoryServices, loadContextMessages, trimMessages, getWorkingMemoryMiddleware, } from './agent-memory.js';
|
|
9
|
-
import { prepareAgentRun, resolveAgent, buildInstructions, buildToolDefs, createScopedChannel, resolveOwnerResourceId, agentSessionScope, assertResourceOwner, assertResourcePrincipalOwner, assertAgentAuthorized, ToolApprovalRequired, ToolCredentialRequired, APPROVAL_REQUIRED, CREDENTIAL_REQUIRED, } from './agent-prepare.js';
|
|
8
|
+
import { prepareAgentRun, resolveAgent, buildInstructions, buildToolDefs, createScopedChannel, resolveOwnerResourceId, agentSessionScope, assertResourceOwner, assertResourcePrincipalOwner, assertAgentAuthorized, resolveAgentRunner, ToolApprovalRequired, ToolCredentialRequired, APPROVAL_REQUIRED, CREDENTIAL_REQUIRED, } from './agent-prepare.js';
|
|
10
9
|
import { resolveModelConfig } from './agent-model-config.js';
|
|
11
10
|
import { getInFlightTools, isAbortError, persistOrphanedToolResults, registerInterruptibleRun, signalRunInterrupt, trackInterruptNote, trackToolExecution, } from './agent-interrupt.js';
|
|
12
11
|
function createPersistingChannel(parent, storage, threadId, logger) {
|
|
@@ -752,6 +751,7 @@ export async function resumeAgent(input, channel, params, options) {
|
|
|
752
751
|
}
|
|
753
752
|
const { agent, packageName, resolvedName } = resolveAgent(run.agentName);
|
|
754
753
|
await assertAgentAuthorized(agent, params, packageName);
|
|
754
|
+
const agentRunner = await resolveAgentRunner(singletonServices, params);
|
|
755
755
|
// The read above is not a claim — concurrent resumes all see the same pending
|
|
756
756
|
// approval. `resolveApproval` is the claim, and the loser must not go on to
|
|
757
757
|
// run the tool a second time.
|
|
@@ -761,10 +761,6 @@ export async function resumeAgent(input, channel, params, options) {
|
|
|
761
761
|
}
|
|
762
762
|
const { storage } = resolveMemoryServices(agent, singletonServices);
|
|
763
763
|
const memoryConfig = agent.memory;
|
|
764
|
-
const agentRunner = singletonServices.agentRunner;
|
|
765
|
-
if (!agentRunner) {
|
|
766
|
-
throw new AIProviderNotConfiguredError();
|
|
767
|
-
}
|
|
768
764
|
if (!input.approved) {
|
|
769
765
|
if (pending.type === 'agent-call') {
|
|
770
766
|
await agentRunState.updateRun(pending.agentRunId, { status: 'failed' });
|