@caplets/pi 0.1.3 → 0.1.5
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/index.js +49 -23
- package/package.json +7 -3
package/dist/index.js
CHANGED
|
@@ -1,26 +1,16 @@
|
|
|
1
|
+
import { keyText } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import { generatedToolInputJsonSchema } from "@caplets/core/generated-tool-input-schema";
|
|
1
3
|
import { createNativeCapletsService, registerNativeCapletsProcessCleanup } from "@caplets/core/native";
|
|
2
|
-
import { Type } from "@sinclair/typebox";
|
|
3
|
-
import { operations } from "@caplets/core/generated-tool-input-schema";
|
|
4
|
-
//#region src/schema.ts
|
|
5
|
-
function capletsPiParameters() {
|
|
6
|
-
return Type.Object({
|
|
7
|
-
operation: Type.Union(operations.map((operation) => Type.Literal(operation))),
|
|
8
|
-
query: Type.Optional(Type.String()),
|
|
9
|
-
limit: Type.Optional(Type.Integer({ minimum: 1 })),
|
|
10
|
-
tool: Type.Optional(Type.String()),
|
|
11
|
-
arguments: Type.Optional(Type.Record(Type.String(), Type.Unknown())),
|
|
12
|
-
fields: Type.Optional(Type.Array(Type.String({ minLength: 1 }), { minItems: 1 }))
|
|
13
|
-
}, { additionalProperties: false });
|
|
14
|
-
}
|
|
15
|
-
//#endregion
|
|
16
4
|
//#region src/index.ts
|
|
17
5
|
function capletsPiExtension(pi, options = {}) {
|
|
18
6
|
const ownsService = !options.service;
|
|
19
7
|
const service = options.service ?? createNativeCapletsService();
|
|
20
8
|
if (ownsService) registerNativeCapletsProcessCleanup(service);
|
|
21
9
|
const registeredCapletToolSignatures = /* @__PURE__ */ new Map();
|
|
22
|
-
let
|
|
23
|
-
|
|
10
|
+
let currentCapletTools = /* @__PURE__ */ new Set();
|
|
11
|
+
let knownCapletTools = /* @__PURE__ */ new Set();
|
|
12
|
+
let canSyncActiveTools = false;
|
|
13
|
+
const syncToolRegistrations = (caplets = service.listTools()) => {
|
|
24
14
|
const nextCapletTools = new Set(caplets.map((caplet) => caplet.toolName));
|
|
25
15
|
for (const [toolName] of registeredCapletToolSignatures) if (!nextCapletTools.has(toolName)) registeredCapletToolSignatures.delete(toolName);
|
|
26
16
|
for (const caplet of caplets) {
|
|
@@ -29,14 +19,24 @@ function capletsPiExtension(pi, options = {}) {
|
|
|
29
19
|
registeredCapletToolSignatures.set(caplet.toolName, signature);
|
|
30
20
|
pi.registerTool(createPiTool(service, caplet));
|
|
31
21
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
22
|
+
currentCapletTools = nextCapletTools;
|
|
23
|
+
return nextCapletTools;
|
|
24
|
+
};
|
|
25
|
+
const syncActiveTools = (nextCapletTools = currentCapletTools) => {
|
|
26
|
+
if (!canSyncActiveTools || !pi.getActiveTools || !pi.setActiveTools) return;
|
|
27
|
+
const activeNonCaplets = pi.getActiveTools().filter((name) => !knownCapletTools.has(name) && !nextCapletTools.has(name));
|
|
28
|
+
pi.setActiveTools([...activeNonCaplets, ...nextCapletTools]);
|
|
36
29
|
knownCapletTools = nextCapletTools;
|
|
37
30
|
};
|
|
38
|
-
|
|
39
|
-
const unsubscribe = service.onToolsChanged(
|
|
31
|
+
currentCapletTools = syncToolRegistrations();
|
|
32
|
+
const unsubscribe = service.onToolsChanged((caplets) => {
|
|
33
|
+
syncActiveTools(syncToolRegistrations(caplets));
|
|
34
|
+
});
|
|
35
|
+
pi.on?.("session_start", () => {
|
|
36
|
+
canSyncActiveTools = true;
|
|
37
|
+
knownCapletTools = new Set(pi.getActiveTools?.().filter((name) => name.startsWith("caplets_")) ?? []);
|
|
38
|
+
syncActiveTools();
|
|
39
|
+
});
|
|
40
40
|
pi.on?.("session_shutdown", () => {
|
|
41
41
|
unsubscribe();
|
|
42
42
|
if (ownsService) service.close();
|
|
@@ -57,7 +57,7 @@ function createPiTool(service, caplet) {
|
|
|
57
57
|
description: caplet.description,
|
|
58
58
|
promptSnippet: `Use ${caplet.toolName} for the ${caplet.title} Caplet capability domain.`,
|
|
59
59
|
promptGuidelines: caplet.promptGuidance,
|
|
60
|
-
parameters:
|
|
60
|
+
parameters: generatedToolInputJsonSchema(),
|
|
61
61
|
async execute(_toolCallId, params) {
|
|
62
62
|
const result = await service.execute(caplet.caplet, params);
|
|
63
63
|
const serialized = serializeResult(result);
|
|
@@ -71,9 +71,35 @@ function createPiTool(service, caplet) {
|
|
|
71
71
|
serializationError: serialized.serializationError
|
|
72
72
|
} : { result }
|
|
73
73
|
};
|
|
74
|
+
},
|
|
75
|
+
renderCall(args, theme) {
|
|
76
|
+
const suffix = [stringProperty(args, "operation"), stringProperty(args, "tool")].filter(Boolean).join(" ");
|
|
77
|
+
return textComponent(theme.fg("toolTitle", theme.bold(caplet.title)) + (suffix ? ` ${theme.fg("muted", suffix)}` : ""));
|
|
78
|
+
},
|
|
79
|
+
renderResult(result, { expanded, isPartial }, theme) {
|
|
80
|
+
if (isPartial) return textComponent(theme.fg("warning", `${caplet.title} running...`));
|
|
81
|
+
const output = result.content.filter((item) => item.type === "text").map((item) => item.text).join("\n");
|
|
82
|
+
if (expanded) return textComponent(theme.fg("success", `✓ ${caplet.title} complete`) + theme.fg("dim", ` (${toolExpandKeyText()} to collapse)`) + (output ? `\n${theme.fg("toolOutput", output)}` : ""));
|
|
83
|
+
return textComponent(theme.fg("success", `✓ ${caplet.title} complete`) + theme.fg("dim", ` (${toolExpandKeyText()} to expand)`));
|
|
74
84
|
}
|
|
75
85
|
};
|
|
76
86
|
}
|
|
87
|
+
function toolExpandKeyText() {
|
|
88
|
+
return keyText("app.tools.expand") || "ctrl+o";
|
|
89
|
+
}
|
|
90
|
+
function textComponent(text) {
|
|
91
|
+
return {
|
|
92
|
+
render(_width) {
|
|
93
|
+
return text.split("\n");
|
|
94
|
+
},
|
|
95
|
+
invalidate() {}
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function stringProperty(value, key) {
|
|
99
|
+
if (!value || typeof value !== "object" || !(key in value)) return;
|
|
100
|
+
const property = value[key];
|
|
101
|
+
return typeof property === "string" && property.length > 0 ? property : void 0;
|
|
102
|
+
}
|
|
77
103
|
function serializeResult(result) {
|
|
78
104
|
try {
|
|
79
105
|
return { text: JSON.stringify(result, null, 2) ?? "null" };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@caplets/pi",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Native Pi extension for Caplets.",
|
|
5
5
|
"homepage": "https://github.com/spiritledsoftware/caplets#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -26,8 +26,7 @@
|
|
|
26
26
|
"access": "public"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@
|
|
30
|
-
"@caplets/core": "0.12.1"
|
|
29
|
+
"@caplets/core": "0.13.0"
|
|
31
30
|
},
|
|
32
31
|
"devDependencies": {
|
|
33
32
|
"@types/node": "^25.7.0",
|
|
@@ -41,6 +40,11 @@
|
|
|
41
40
|
"engines": {
|
|
42
41
|
"node": ">=22"
|
|
43
42
|
},
|
|
43
|
+
"pi": {
|
|
44
|
+
"extensions": [
|
|
45
|
+
"dist/index.js"
|
|
46
|
+
]
|
|
47
|
+
},
|
|
44
48
|
"scripts": {
|
|
45
49
|
"build": "rm -rf dist && rolldown -c",
|
|
46
50
|
"typecheck": "tsc --noEmit",
|