@selesai/code 0.13.29 → 0.13.30
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 +10 -0
- package/README.md +8 -2
- package/dist/core/model-registry.d.ts +13 -1
- package/dist/core/model-registry.js +16 -0
- package/dist/defaults/settings.json +8 -13
- package/dist/extensions/capability-gateway/catalog.ts +2 -2
- package/dist/extensions/capability-gateway/index.ts +103 -18
- package/dist/extensions/capability-gateway/integration.test.ts +394 -8
- package/dist/extensions/capability-gateway/routing.test.ts +415 -0
- package/dist/extensions/capability-gateway/routing.ts +221 -0
- package/dist/extensions/grep-app/index.ts +10 -0
- package/dist/extensions/jev/decisions.test.ts +316 -0
- package/dist/extensions/jev/decisions.ts +527 -0
- package/dist/extensions/jev/test-support.ts +233 -0
- package/dist/extensions/jev-advisory-lifecycle.test.ts +206 -0
- package/dist/extensions/jev-advisory-memory.test.ts +191 -0
- package/dist/extensions/jev-advisory-recommendations.test.ts +240 -0
- package/dist/extensions/jev-advisory-routing.ts +539 -0
- package/dist/extensions/package.json +2 -2
- package/dist/extensions/pi-hermes-memory/src/memory-search-bridge.ts +40 -0
- package/dist/extensions/pi-hermes-memory/src/tools/memory-search-tool.ts +57 -46
- package/dist/extensions/pi-hermes-memory/src/tools/memory-tool.ts +17 -0
- package/dist/extensions/pi-hermes-memory/src/tools/session-search-tool.ts +10 -0
- package/dist/extensions/pi-hermes-memory/src/tools/skill-tool.ts +5 -0
- package/dist/extensions/pi-hermes-memory/tests/tools/memory-search-tool.test.ts +25 -0
- package/dist/extensions/pi-intercom/index.ts +10 -0
- package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +5 -0
- package/dist/extensions/pi-subagents/src/extension/index.ts +5 -0
- package/dist/extensions/pi-subagents/src/intercom/native-supervisor-channel.ts +10 -0
- package/dist/extensions/pi-subagents/src/runs/background/wait-tool.ts +10 -0
- package/dist/extensions/pi-web-agent/src/extension.ts +5 -0
- package/dist/extensions/question/index.ts +5 -0
- package/dist/extensions/tokenin-onboarding.ts +185 -0
- package/dist/skills/code-review-and-quality/SKILL.md +396 -0
- package/dist/skills/code-simplification/SKILL.md +331 -0
- package/dist/skills/incremental-implementation/SKILL.md +249 -0
- package/dist/skills/planning-and-task-breakdown/SKILL.md +257 -0
- package/dist/skills/references/agent-skills-LICENSE +21 -0
- package/dist/skills/references/definition-of-done.md +67 -0
- package/dist/skills/references/performance-checklist.md +236 -0
- package/dist/skills/references/security-checklist.md +248 -0
- package/docs/settings.md +68 -31
- package/package.json +3 -3
- package/dist/extensions/auto-model.test.ts +0 -438
- package/dist/extensions/auto-model.ts +0 -357
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The workflow, skill, and verification route.
|
|
3
|
+
*
|
|
4
|
+
* Only discovered, eligible, canonically named items may be recommended; the
|
|
5
|
+
* advisory must stay a recommendation (no skill body read, no workflow started,
|
|
6
|
+
* no command emitted, mandatory gates untouched); and an oversized catalog or an
|
|
7
|
+
* unavailable classifier publishes nothing at all.
|
|
8
|
+
*/
|
|
9
|
+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
10
|
+
import { tmpdir } from "node:os";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
|
13
|
+
|
|
14
|
+
const state = vi.hoisted(() => ({ settingsPath: "" }));
|
|
15
|
+
|
|
16
|
+
vi.mock("@selesai/code", () => ({ getSettingsPath: () => state.settingsPath }));
|
|
17
|
+
// The client speaks through pi's completion transport (the Token-In provider
|
|
18
|
+
// layer owns the non-streaming decisions request), so a suite stubs that.
|
|
19
|
+
import jevAdvisoryRoutingExtension, {
|
|
20
|
+
MAX_CANDIDATE_DESCRIPTION_CHARS,
|
|
21
|
+
recommendationCandidates,
|
|
22
|
+
} from "./jev-advisory-routing.ts";
|
|
23
|
+
const completeMock = vi.fn();
|
|
24
|
+
|
|
25
|
+
import {
|
|
26
|
+
enabledAdvisoryRoutes,
|
|
27
|
+
jevAnswers,
|
|
28
|
+
jevResponse,
|
|
29
|
+
makeHarness,
|
|
30
|
+
makeRepo,
|
|
31
|
+
sentPayload,
|
|
32
|
+
writeJevSettings,
|
|
33
|
+
type CommandStub,
|
|
34
|
+
type SkillStub,
|
|
35
|
+
} from "./jev/test-support.ts";
|
|
36
|
+
|
|
37
|
+
const SKILL_BODY_SENTINEL = "SKILL_BODY_MUST_NOT_APPEAR";
|
|
38
|
+
|
|
39
|
+
let root: string;
|
|
40
|
+
let repo: string;
|
|
41
|
+
let skills: SkillStub[];
|
|
42
|
+
|
|
43
|
+
beforeAll(() => {
|
|
44
|
+
const created = makeRepo("jev-recommend-");
|
|
45
|
+
root = created.root;
|
|
46
|
+
repo = created.repo;
|
|
47
|
+
state.settingsPath = join(root, "agent", "settings.json");
|
|
48
|
+
mkdirSync(join(root, "agent"), { recursive: true });
|
|
49
|
+
|
|
50
|
+
const skillDir = join(root, "agent", "skills", "implanger");
|
|
51
|
+
mkdirSync(skillDir, { recursive: true });
|
|
52
|
+
writeFileSync(join(skillDir, "SKILL.md"), `# implanger\n\n${SKILL_BODY_SENTINEL}\n`, "utf-8");
|
|
53
|
+
skills = [
|
|
54
|
+
{ name: "implanger", description: "Turn a described UI change into an implementation plan.", filePath: join(skillDir, "SKILL.md") },
|
|
55
|
+
{ name: "hidden-tool", description: "Not offered to the model.", filePath: join(skillDir, "SKILL.md"), disableModelInvocation: true },
|
|
56
|
+
];
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
afterAll(() => rmSync(root, { recursive: true, force: true }));
|
|
60
|
+
|
|
61
|
+
const WORKFLOWS: CommandStub[] = [
|
|
62
|
+
{ name: "deploy", description: "Deploy the project.", source: "prompt" },
|
|
63
|
+
{ name: "memory-insights", description: "An extension command, not a workflow.", source: "extension" },
|
|
64
|
+
{ name: "skill:implanger", description: "Duplicate listing of the same skill.", source: "skill" },
|
|
65
|
+
];
|
|
66
|
+
|
|
67
|
+
function harness(
|
|
68
|
+
options: {
|
|
69
|
+
advisory?: unknown;
|
|
70
|
+
skills?: SkillStub[];
|
|
71
|
+
commands?: CommandStub[];
|
|
72
|
+
credential?: boolean;
|
|
73
|
+
template?: boolean;
|
|
74
|
+
answer?: { recommendation: string; confidence?: number; verification?: string };
|
|
75
|
+
} = {},
|
|
76
|
+
) {
|
|
77
|
+
writeJevSettings(
|
|
78
|
+
state.settingsPath,
|
|
79
|
+
options.advisory ?? { routes: enabledAdvisoryRoutes(["recommendations"]) },
|
|
80
|
+
);
|
|
81
|
+
const session = makeHarness({
|
|
82
|
+
settingsPath: state.settingsPath,
|
|
83
|
+
extension: jevAdvisoryRoutingExtension,
|
|
84
|
+
cwd: repo,
|
|
85
|
+
skills: options.skills ?? skills,
|
|
86
|
+
commands: options.commands ?? WORKFLOWS,
|
|
87
|
+
credential: options.credential,
|
|
88
|
+
template: options.template,
|
|
89
|
+
complete: completeMock,
|
|
90
|
+
});
|
|
91
|
+
const answer = options.answer ?? { recommendation: "skill:implanger" };
|
|
92
|
+
completeMock.mockResolvedValue(
|
|
93
|
+
jevResponse(
|
|
94
|
+
jevAnswers({
|
|
95
|
+
recommendation: { choice: answer.recommendation, confidence: answer.confidence ?? 0.9 },
|
|
96
|
+
verification: { choice: answer.verification ?? "targeted", confidence: answer.confidence ?? 0.9 },
|
|
97
|
+
}),
|
|
98
|
+
),
|
|
99
|
+
);
|
|
100
|
+
return session;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
beforeEach(() => {
|
|
104
|
+
vi.clearAllMocks();
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
describe("candidate discovery", () => {
|
|
108
|
+
it("offers only model-invocable skills and registered prompt workflows, by canonical name", () => {
|
|
109
|
+
const candidates = recommendationCandidates({
|
|
110
|
+
getResolvedSkills: () => skills,
|
|
111
|
+
getCommands: () => WORKFLOWS,
|
|
112
|
+
} as never);
|
|
113
|
+
expect(candidates.map((candidate) => candidate.key)).toEqual(["skill:implanger", "workflow:deploy"]);
|
|
114
|
+
expect(candidates[0]).toMatchObject({ kind: "skill", name: "implanger" });
|
|
115
|
+
expect(candidates[1]).toMatchObject({ kind: "workflow", name: "deploy" });
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it("compacts long descriptions and replaces a missing one with a neutral label", () => {
|
|
119
|
+
const candidates = recommendationCandidates({
|
|
120
|
+
getResolvedSkills: () => [
|
|
121
|
+
{ name: "verbose", description: ` ${"word ".repeat(60)} `, filePath: "/tmp/SKILL.md" },
|
|
122
|
+
{ name: "silent", description: "", filePath: "/tmp/SKILL.md" },
|
|
123
|
+
],
|
|
124
|
+
getCommands: () => [],
|
|
125
|
+
} as never);
|
|
126
|
+
const verbose = candidates[0].description;
|
|
127
|
+
expect(verbose.length).toBe(MAX_CANDIDATE_DESCRIPTION_CHARS + 1);
|
|
128
|
+
expect(verbose.endsWith("…")).toBe(true);
|
|
129
|
+
expect(verbose.startsWith("word word")).toBe(true);
|
|
130
|
+
expect(candidates[1].description).toBe("Installed skill (no description recorded).");
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
describe("accepted recommendations", () => {
|
|
135
|
+
it("publishes the canonical skill or workflow and its confidence as advisory context", async () => {
|
|
136
|
+
const session = harness({ answer: { recommendation: "skill:implanger", confidence: 0.83, verification: "none" } });
|
|
137
|
+
await session.fire("session_start");
|
|
138
|
+
const message = await session.advise("turn this mockup into a plan");
|
|
139
|
+
|
|
140
|
+
expect(message?.customType).toBe("jev-advisory");
|
|
141
|
+
expect(message?.content).toContain('<jev-advisory source="jev" route="recommendation" confidence="0.83">');
|
|
142
|
+
expect(message?.content).toContain("Suggested skill: `implanger`");
|
|
143
|
+
expect(message?.content).toContain("nothing was loaded, started, permitted, or executed");
|
|
144
|
+
expect(message?.content).not.toContain(SKILL_BODY_SENTINEL);
|
|
145
|
+
expect(session.telemetry.at(-1)).toMatchObject({ route: "recommendations", outcome: "jev", item: "skill:implanger" });
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it("publishes a workflow without pretending it ran", async () => {
|
|
149
|
+
const session = harness({ answer: { recommendation: "workflow:deploy", confidence: 0.7, verification: "none" } });
|
|
150
|
+
await session.fire("session_start");
|
|
151
|
+
const message = await session.advise("ship this to production");
|
|
152
|
+
expect(message?.content).toContain("Suggested workflow prompt: `deploy`");
|
|
153
|
+
expect(message?.content).toContain("nothing was loaded, started, permitted, or executed");
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it("publishes a verification level without inventing a command or weakening a gate", async () => {
|
|
157
|
+
const session = harness({ answer: { recommendation: "none", verification: "project-required" } });
|
|
158
|
+
await session.fire("session_start");
|
|
159
|
+
const message = await session.advise("refactor the session runtime");
|
|
160
|
+
expect(message?.content).toContain("Verification suggestion: project-required");
|
|
161
|
+
expect(message?.content).toContain("mandatory project, workflow, and acceptance verification is unchanged");
|
|
162
|
+
expect(message?.content).not.toContain("npm");
|
|
163
|
+
expect(message?.content).not.toContain("$ ");
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it("reports adoption when the parent reads the recommended skill file", async () => {
|
|
167
|
+
const session = harness({ answer: { recommendation: "skill:implanger", verification: "none" } });
|
|
168
|
+
await session.fire("session_start");
|
|
169
|
+
await session.advise("turn this mockup into a plan");
|
|
170
|
+
await session.fire("tool_execution_start", {
|
|
171
|
+
type: "tool_execution_start",
|
|
172
|
+
toolName: "read",
|
|
173
|
+
toolCallId: "t1",
|
|
174
|
+
args: { path: skills[0].filePath },
|
|
175
|
+
});
|
|
176
|
+
await session.fire("agent_settled");
|
|
177
|
+
expect(session.telemetry.at(-1)).toEqual({
|
|
178
|
+
event: "adoption",
|
|
179
|
+
route: "recommendations",
|
|
180
|
+
item: "skill:implanger",
|
|
181
|
+
adopted: true,
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
describe("abstentions", () => {
|
|
187
|
+
it("publishes nothing when no candidate fits and no level is warranted", async () => {
|
|
188
|
+
const session = harness({ answer: { recommendation: "none", verification: "none" } });
|
|
189
|
+
await session.fire("session_start");
|
|
190
|
+
expect(await session.advise("what is the weather?")).toBeUndefined();
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it("never publishes a candidate the discovery surface did not offer", async () => {
|
|
194
|
+
const session = harness({ answer: { recommendation: "skill:hidden-tool", verification: "none" } });
|
|
195
|
+
await session.fire("session_start");
|
|
196
|
+
expect(await session.advise("do something hidden")).toBeUndefined();
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it("never publishes a raw command as a verification level", async () => {
|
|
200
|
+
const session = harness({ answer: { recommendation: "none", verification: "rm -rf /" } });
|
|
201
|
+
await session.fire("session_start");
|
|
202
|
+
expect(await session.advise("clean up")).toBeUndefined();
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
it("skips Jev entirely when the candidate catalog cannot fit its payload budget", async () => {
|
|
206
|
+
const huge = Array.from({ length: 200 }, (_, index) => ({
|
|
207
|
+
name: `skill-${index}`,
|
|
208
|
+
description: "x".repeat(MAX_CANDIDATE_DESCRIPTION_CHARS),
|
|
209
|
+
filePath: `/tmp/skill-${index}/SKILL.md`,
|
|
210
|
+
}));
|
|
211
|
+
const session = harness({
|
|
212
|
+
advisory: { routes: { recommendations: { enabled: true, payloadBytes: 1_024 } } },
|
|
213
|
+
skills: huge,
|
|
214
|
+
});
|
|
215
|
+
await session.fire("session_start");
|
|
216
|
+
expect(await session.advise("use one of the many skills")).toBeUndefined();
|
|
217
|
+
expect(completeMock).not.toHaveBeenCalled();
|
|
218
|
+
expect(session.telemetry.at(-1)).toMatchObject({ route: "recommendations", outcome: "fallback", reason: "overflow" });
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
it("asks only the verification question when nothing is discoverable", async () => {
|
|
222
|
+
const session = harness({ skills: [], commands: [], answer: { recommendation: "none", verification: "targeted" } });
|
|
223
|
+
await session.fire("session_start");
|
|
224
|
+
const message = await session.advise("fix the flaky test");
|
|
225
|
+
expect(message?.content).toContain("Verification suggestion: targeted");
|
|
226
|
+
const questions = sentPayload(completeMock)?.questions as Record<string, unknown>;
|
|
227
|
+
expect(Object.keys(questions)).toEqual(["verification"]);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
it("stays silent without a credential or a provider template", async () => {
|
|
231
|
+
const noCredential = harness({ credential: false });
|
|
232
|
+
await noCredential.fire("session_start");
|
|
233
|
+
expect(await noCredential.advise("turn this mockup into a plan")).toBeUndefined();
|
|
234
|
+
expect(completeMock).not.toHaveBeenCalled();
|
|
235
|
+
|
|
236
|
+
const noTemplate = harness({ template: false });
|
|
237
|
+
await noTemplate.fire("session_start");
|
|
238
|
+
expect(await noTemplate.advise("turn this mockup into a plan")).toBeUndefined();
|
|
239
|
+
});
|
|
240
|
+
});
|