@alint-js/agent-pi 0.0.4
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/README.md +32 -0
- package/dist/index.d.mts +20 -0
- package/dist/index.mjs +74 -0
- package/package.json +33 -0
package/README.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# `@alint-js/agent-pi`
|
|
2
|
+
|
|
3
|
+
> [!IMPORTANT]
|
|
4
|
+
> This package is a WIP. APIs may be subject to major changes.
|
|
5
|
+
|
|
6
|
+
A [Pi](https://github.com/earendil-works/pi)-backed `AgentAdapter` for alint. One of the swappable vendor adapters behind `@alint-js/agent`.
|
|
7
|
+
|
|
8
|
+
## What it does
|
|
9
|
+
|
|
10
|
+
`createPiAdapter()` returns an `AgentAdapter` that runs a rule's request through a Pi
|
|
11
|
+
`Agent`: it translates the framework-agnostic `AgentTool`s to Pi's TypeBox tools, runs
|
|
12
|
+
the tool loop, and reads back the final assistant message.
|
|
13
|
+
|
|
14
|
+
## How to use
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
import { createPiAdapter } from '@alint-js/agent-pi'
|
|
18
|
+
|
|
19
|
+
const adapter = createPiAdapter()
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Pass `{ run }` to inject a custom Pi run.
|
|
23
|
+
|
|
24
|
+
## When to use
|
|
25
|
+
|
|
26
|
+
- You want tool-using rules powered by Pi (`pi-ai` and `pi-agent-core`).
|
|
27
|
+
|
|
28
|
+
## When not to use
|
|
29
|
+
|
|
30
|
+
- You use a different agent framework. Pick that vendor's adapter (e.g.
|
|
31
|
+
`@alint-js/agent-apeira`) or write your own `AgentAdapter`.
|
|
32
|
+
- Your rule needs no tools. Keep it on the plain `@alint-js/core` rule DSL.
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { AgentTool } from "@earendil-works/pi-agent-core";
|
|
2
|
+
import { Model } from "@earendil-works/pi-ai";
|
|
3
|
+
import { AgentAdapter, AgentRequest, AgentTool as AgentTool$1 } from "@alint-js/agent";
|
|
4
|
+
import { ResolvedModel } from "@alint-js/core";
|
|
5
|
+
|
|
6
|
+
//#region src/index.d.ts
|
|
7
|
+
interface PiAdapterOptions {
|
|
8
|
+
run: (request: AgentRequest) => Promise<PiMessage[]>;
|
|
9
|
+
}
|
|
10
|
+
interface PiMessage {
|
|
11
|
+
content?: unknown;
|
|
12
|
+
role?: unknown;
|
|
13
|
+
}
|
|
14
|
+
declare function apiKeyFromModel(model: ResolvedModel): string;
|
|
15
|
+
declare function createPiAdapter(options?: Partial<PiAdapterOptions>): AgentAdapter;
|
|
16
|
+
declare function createPiModel(model: ResolvedModel): Model<'openai-completions'>;
|
|
17
|
+
declare function extractPiText(message?: PiMessage): string;
|
|
18
|
+
declare function toPiTools(tools: AgentTool$1[]): AgentTool[];
|
|
19
|
+
//#endregion
|
|
20
|
+
export { PiAdapterOptions, apiKeyFromModel, createPiAdapter, createPiModel, extractPiText, toPiTools };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { Agent } from "@earendil-works/pi-agent-core";
|
|
2
|
+
import { Type } from "@earendil-works/pi-ai";
|
|
3
|
+
//#region src/index.ts
|
|
4
|
+
function apiKeyFromModel(model) {
|
|
5
|
+
return (model.provider.headers.Authorization ?? model.provider.headers.authorization)?.replace(/^Bearer\s+/i, "") ?? "unused";
|
|
6
|
+
}
|
|
7
|
+
function createPiAdapter(options = {}) {
|
|
8
|
+
const run = options.run ?? runPiAgent;
|
|
9
|
+
return async (request) => {
|
|
10
|
+
return {
|
|
11
|
+
answer: extractPiText([...await run(request)].reverse().find((message) => message.role === "assistant")),
|
|
12
|
+
usage: void 0
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function createPiModel(model) {
|
|
17
|
+
return {
|
|
18
|
+
api: "openai-completions",
|
|
19
|
+
baseUrl: model.provider.endpoint,
|
|
20
|
+
contextWindow: model.contextWindow ?? 32768,
|
|
21
|
+
cost: {
|
|
22
|
+
cacheRead: 0,
|
|
23
|
+
cacheWrite: 0,
|
|
24
|
+
input: 0,
|
|
25
|
+
output: 0
|
|
26
|
+
},
|
|
27
|
+
id: model.id,
|
|
28
|
+
input: ["text"],
|
|
29
|
+
maxTokens: 4096,
|
|
30
|
+
name: model.name,
|
|
31
|
+
provider: model.provider.id,
|
|
32
|
+
reasoning: false
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function extractPiText(message) {
|
|
36
|
+
if (!message) return "";
|
|
37
|
+
const { content } = message;
|
|
38
|
+
if (typeof content === "string") return content;
|
|
39
|
+
if (Array.isArray(content)) return content.filter((part) => isTextPart(part)).map((part) => part.text).join("");
|
|
40
|
+
return "";
|
|
41
|
+
}
|
|
42
|
+
function toPiTools(tools) {
|
|
43
|
+
return tools.map((agentTool) => ({
|
|
44
|
+
description: agentTool.description,
|
|
45
|
+
execute: async (_toolCallId, params) => ({
|
|
46
|
+
content: [{
|
|
47
|
+
text: String(await agentTool.execute(params)),
|
|
48
|
+
type: "text"
|
|
49
|
+
}],
|
|
50
|
+
details: void 0
|
|
51
|
+
}),
|
|
52
|
+
label: agentTool.name,
|
|
53
|
+
name: agentTool.name,
|
|
54
|
+
parameters: Type.Unsafe(agentTool.parameters)
|
|
55
|
+
}));
|
|
56
|
+
}
|
|
57
|
+
function isTextPart(part) {
|
|
58
|
+
return typeof part === "object" && part !== null && part.type === "text" && typeof part.text === "string";
|
|
59
|
+
}
|
|
60
|
+
async function runPiAgent(request) {
|
|
61
|
+
const agent = new Agent({
|
|
62
|
+
getApiKey: () => apiKeyFromModel(request.model),
|
|
63
|
+
initialState: {
|
|
64
|
+
model: createPiModel(request.model),
|
|
65
|
+
systemPrompt: request.instructions,
|
|
66
|
+
tools: toPiTools(request.tools)
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
await agent.prompt(request.prompt);
|
|
70
|
+
await agent.waitForIdle();
|
|
71
|
+
return agent.state.messages;
|
|
72
|
+
}
|
|
73
|
+
//#endregion
|
|
74
|
+
export { apiKeyFromModel, createPiAdapter, createPiModel, extractPiText, toPiTools };
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@alint-js/agent-pi",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.0.4",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": {
|
|
7
|
+
"types": "./dist/index.d.mts",
|
|
8
|
+
"default": "./dist/index.mjs"
|
|
9
|
+
},
|
|
10
|
+
"./package.json": "./package.json"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist"
|
|
14
|
+
],
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@earendil-works/pi-agent-core": "^0.80.2",
|
|
17
|
+
"@earendil-works/pi-ai": "^0.80.2",
|
|
18
|
+
"@smithy/node-http-handler": "^4.9.1",
|
|
19
|
+
"@alint-js/core": "0.0.4",
|
|
20
|
+
"@alint-js/agent": "0.0.4"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/node": "^26.0.1",
|
|
24
|
+
"tsdown": "^0.22.3",
|
|
25
|
+
"typescript": "^6.0.3",
|
|
26
|
+
"vitest": "^4.1.9"
|
|
27
|
+
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "tsdown",
|
|
30
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
31
|
+
"test": "vitest run --config vitest.config.ts"
|
|
32
|
+
}
|
|
33
|
+
}
|