@selesai/code 0.13.31 → 0.13.32
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 +5 -0
- package/dist/core/remote-catalog-provider.js +5 -1
- package/dist/core/remote-catalog-provider.test.d.ts +1 -0
- package/dist/core/remote-catalog-provider.test.js +29 -0
- package/dist/extensions/capability-gateway/index.ts +9 -4
- package/dist/extensions/capability-gateway/integration.test.ts +33 -3
- package/dist/extensions/pi-web-agent/src/extension.ts +2 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `@selesai/code` will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.13.32] - 2026-09-24
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- **Cached provider model catalogs are no longer discarded when `Last-Modified` is missing.** Models such as `openai-codex/gpt-6-sol` and `openai-codex/gpt-6-luna` remain available after a catalog refresh when the cached catalog is newer than the bundled metadata.
|
|
9
|
+
|
|
5
10
|
## [0.13.31] - 2026-09-23
|
|
6
11
|
|
|
7
12
|
### Changed
|
|
@@ -30,7 +30,11 @@ function parseCatalog(providerId, value) {
|
|
|
30
30
|
function remoteModels(entry, localGeneratedAt) {
|
|
31
31
|
if (!entry)
|
|
32
32
|
return [];
|
|
33
|
-
|
|
33
|
+
// Some catalog responses (and the 404/501 fallback) have no usable
|
|
34
|
+
// Last-Modified value. Use the completed check time instead so a cached
|
|
35
|
+
// catalog is not discarded merely because that header was absent.
|
|
36
|
+
const remoteGeneratedAt = entry.lastModified && entry.lastModified > 0 ? entry.lastModified : entry.checkedAt;
|
|
37
|
+
if (localGeneratedAt !== undefined && (remoteGeneratedAt === undefined || remoteGeneratedAt <= localGeneratedAt)) {
|
|
34
38
|
return [];
|
|
35
39
|
}
|
|
36
40
|
return entry.models;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { withRemoteCatalog } from "./remote-catalog-provider.js";
|
|
3
|
+
const cachedModel = {
|
|
4
|
+
id: "gpt-6-sol",
|
|
5
|
+
provider: "openai-codex",
|
|
6
|
+
};
|
|
7
|
+
function refreshContext(stored) {
|
|
8
|
+
return {
|
|
9
|
+
stored,
|
|
10
|
+
allowNetwork: false,
|
|
11
|
+
signal: new AbortController().signal,
|
|
12
|
+
publish: async ({ update }) => {
|
|
13
|
+
update?.();
|
|
14
|
+
return true;
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
describe("remote model catalog cache", () => {
|
|
19
|
+
it("keeps a newer cached catalog when Last-Modified is unavailable", async () => {
|
|
20
|
+
const localGeneratedAt = 100;
|
|
21
|
+
const provider = {
|
|
22
|
+
id: "openai-codex",
|
|
23
|
+
getModels: () => [],
|
|
24
|
+
};
|
|
25
|
+
const wrapped = withRemoteCatalog(provider, "https://example.test", localGeneratedAt);
|
|
26
|
+
await wrapped.refreshModels?.(refreshContext({ models: [cachedModel], checkedAt: localGeneratedAt + 1, lastModified: 0 }));
|
|
27
|
+
expect(wrapped.getModels().map((model) => model.id)).toEqual(["gpt-6-sol"]);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
@@ -94,14 +94,19 @@ function catalogEntries(pi: ExtensionAPI): CatalogEntry[] {
|
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
const EMBEDDED_SKILL_BLOCK = /<skill\s+name="([^"]+)"[^>]*>[\s\S]*?<\/skill>/gi;
|
|
97
|
+
const GITHUB_OR_OPEN_SOURCE_QUERY = /\b(?:github|open[\s-]*source)\b/i;
|
|
97
98
|
|
|
98
99
|
function routePrompt(prompt: string, entries: CatalogEntry[]): ReturnType<typeof route> {
|
|
99
100
|
const loadedSkills = new Set([...prompt.matchAll(EMBEDDED_SKILL_BLOCK)].map((match) => match[1]!.toLowerCase()));
|
|
100
101
|
const query = prompt.replace(EMBEDDED_SKILL_BLOCK, " ");
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
102
|
+
const candidates = entries.filter((entry) => entry.kind !== "skill" || !loadedSkills.has(entry.name.toLowerCase()));
|
|
103
|
+
if (GITHUB_OR_OPEN_SOURCE_QUERY.test(query)) {
|
|
104
|
+
const grepAppSearch = candidates.find(
|
|
105
|
+
(entry) => entry.kind === "tool" && entry.eligible && entry.name === "grep_app_search",
|
|
106
|
+
);
|
|
107
|
+
if (grepAppSearch) return { action: "activate", entry: grepAppSearch };
|
|
108
|
+
}
|
|
109
|
+
return route(query, candidates);
|
|
105
110
|
}
|
|
106
111
|
|
|
107
112
|
function formatCatalog(entries: CatalogEntry[]): string {
|
|
@@ -19,6 +19,7 @@ import { allowNetwork } from "../../../test/test-network-env.ts";
|
|
|
19
19
|
const EXTENSIONS_DIR = fileURLToPath(new URL("../../", import.meta.url));
|
|
20
20
|
const GATEWAY_DIR = fileURLToPath(new URL(".", import.meta.url));
|
|
21
21
|
const GREP_APP_DIR = fileURLToPath(new URL("../grep-app", import.meta.url));
|
|
22
|
+
const WEB_AGENT_DIR = fileURLToPath(new URL("../pi-web-agent", import.meta.url));
|
|
22
23
|
const GRAFT_DIR = fileURLToPath(new URL("../pi-graft", import.meta.url));
|
|
23
24
|
const INLINE_SKILLS_FILE = fileURLToPath(new URL("../inline-skills.ts", import.meta.url));
|
|
24
25
|
|
|
@@ -337,9 +338,9 @@ describe("capability gateway integration", () => {
|
|
|
337
338
|
// ---------------------------------------------------------------------------
|
|
338
339
|
|
|
339
340
|
describe("capability gateway Jev routing", () => {
|
|
340
|
-
// "
|
|
341
|
-
// two-candidate hint, which is the only Jev trigger.
|
|
342
|
-
const HINT_PROMPT = "
|
|
341
|
+
// "search fetch" weakly suggests both grep-app tools: the deterministic router returns a
|
|
342
|
+
// two-candidate hint, which is the only Jev trigger. GitHub/open-source mentions route directly.
|
|
343
|
+
const HINT_PROMPT = "search fetch";
|
|
343
344
|
// No tool name, alias, or summary token matches: the router has no lexical signal and Jev
|
|
344
345
|
// must never be consulted.
|
|
345
346
|
const NO_SIGNAL_PROMPT = "continue where we left off last time";
|
|
@@ -393,6 +394,35 @@ describe("capability gateway Jev routing", () => {
|
|
|
393
394
|
return h.telemetry.filter((event) => event.event === "route");
|
|
394
395
|
}
|
|
395
396
|
|
|
397
|
+
it("routes only GitHub/open-source mentions to grep.app; other web searches stay on web_explore", async () => {
|
|
398
|
+
allowNetwork();
|
|
399
|
+
const { fetchMock } = stubJev("none", 1);
|
|
400
|
+
const h = await createGatewaySession({
|
|
401
|
+
enabled: true,
|
|
402
|
+
extensions: [GATEWAY_DIR, GREP_APP_DIR, WEB_AGENT_DIR],
|
|
403
|
+
jev: jevSettings(),
|
|
404
|
+
});
|
|
405
|
+
harnesses.push(h);
|
|
406
|
+
|
|
407
|
+
for (const prompt of [
|
|
408
|
+
"search GitHub code",
|
|
409
|
+
"find open-source implementations",
|
|
410
|
+
"find open source implementations",
|
|
411
|
+
"find opensource examples",
|
|
412
|
+
]) {
|
|
413
|
+
await route(h, prompt);
|
|
414
|
+
expect(h.session.getActiveToolNames()).toContain("grep_app_search");
|
|
415
|
+
expect(h.session.getActiveToolNames()).not.toContain("web_explore");
|
|
416
|
+
expect(fetchMock).not.toHaveBeenCalled();
|
|
417
|
+
await h.session.extensionRunner.emit({ type: "agent_settled" });
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
await route(h, "web search for release notes");
|
|
421
|
+
expect(h.session.getActiveToolNames()).toContain("web_explore");
|
|
422
|
+
expect(h.session.getActiveToolNames()).not.toContain("grep_app_search");
|
|
423
|
+
expect(fetchMock).not.toHaveBeenCalled();
|
|
424
|
+
});
|
|
425
|
+
|
|
396
426
|
// Telemetry may carry route metadata and canonical tool names, never prompt
|
|
397
427
|
// text, conversation turns, credentials, raw Jev output, or tool arguments.
|
|
398
428
|
const TELEMETRY_KEYS = new Set([
|
|
@@ -104,7 +104,8 @@ export default function extension(pi: ExtensionAPI) {
|
|
|
104
104
|
pi.on('before_agent_start', async (event) => ({
|
|
105
105
|
systemPrompt:
|
|
106
106
|
`${event.systemPrompt}\n\n` +
|
|
107
|
-
'For
|
|
107
|
+
'For requests explicitly mentioning GitHub or open source, use grep_app_search instead of web_explore. ' +
|
|
108
|
+
'For all other web research questions that require finding and comparing sources, use web_explore. ' +
|
|
108
109
|
'web_explore handles search, fetch, source ranking, and headless escalation internally. ' +
|
|
109
110
|
'If more web evidence is needed after web_explore, call web_explore again with a narrower query; do not use shell/network commands such as curl, Invoke-WebRequest, npm view/search/pack, or direct HTTP URLs for web research.'
|
|
110
111
|
}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@selesai/code",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.32",
|
|
4
4
|
"description": "Maintained, extension-first Pi coding agent with built-in workflows, subagents, web research, questions, skills, and an enhanced terminal UI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -55,8 +55,8 @@
|
|
|
55
55
|
"clean": "shx rm -rf dist",
|
|
56
56
|
"dev": "tsx src/cli.ts",
|
|
57
57
|
"dev:print": "tsx src/cli.ts --print",
|
|
58
|
-
"test": "vitest run src/__tests__/model-registry-completion.test.ts src/extensions/jev/decisions.test.ts src/extensions/capability-gateway/routing.test.ts src/core/settings-manager-auto-handoff.test.ts src/extensions/jev-advisory-memory.test.ts src/extensions/jev-advisory-recommendations.test.ts src/extensions/jev-advisory-lifecycle.test.ts src/extensions/undo.test.ts src/extensions/tps.test.ts src/extensions/pi-graft src/extensions/agent-browser.test.ts src/extensions/auto-session-name.test.ts src/extensions/context-compaction-reminder.test.ts src/extensions/copy-turn.test.ts src/extensions/grep-app/index.test.ts src/extensions/inline-skills.test.ts src/extensions/rtk.test.ts src/extensions/handoff-new.test.ts src/extensions/question/tests src/extensions/ponytail/test src/__tests__/tokenin-search.test.ts src/__tests__/tokenin-onboarding.test.ts src/__tests__/model-registry-defaults.test.ts src/core/system-prompt.test.ts src/core/session-format.test.ts test/settings-manager-compaction.test.ts test/suite/agent-session-runtime.test.ts test/suite/agent-session-prompt.test.ts test/suite/agent-session-queue.test.ts test/suite/agent-session-retry-events.test.ts test/suite/agent-session-compaction.test.ts test/suite/agent-session-compaction-model-overrides.test.ts test/suite/agent-session-bash-persistence.test.ts test/suite/agent-session-model-extension.test.ts test/clipboard.test.ts test/clipboard-command.test.ts test/clipboard-image.test.ts test/clipboard-image-bmp-conversion.test.ts test/clipboard-image-native-errors.test.ts src/cli/args.test.ts",
|
|
59
|
-
"test:coverage": "vitest run --coverage src/__tests__/model-registry-completion.test.ts src/extensions/jev/decisions.test.ts src/extensions/capability-gateway/routing.test.ts src/core/settings-manager-auto-handoff.test.ts src/extensions/jev-advisory-memory.test.ts src/extensions/jev-advisory-recommendations.test.ts src/extensions/jev-advisory-lifecycle.test.ts src/extensions/undo.test.ts src/extensions/tps.test.ts src/extensions/agent-browser.test.ts src/extensions/auto-session-name.test.ts src/extensions/context-compaction-reminder.test.ts src/extensions/copy-turn.test.ts src/extensions/grep-app/index.test.ts src/extensions/inline-skills.test.ts src/extensions/rtk.test.ts src/extensions/handoff-new.test.ts src/extensions/question/tests src/extensions/ponytail/test src/__tests__/tokenin-search.test.ts src/__tests__/tokenin-onboarding.test.ts src/__tests__/model-registry-defaults.test.ts src/core/system-prompt.test.ts src/core/session-format.test.ts test/settings-manager-compaction.test.ts test/suite/agent-session-runtime.test.ts test/suite/agent-session-prompt.test.ts test/suite/agent-session-queue.test.ts test/suite/agent-session-retry-events.test.ts test/suite/agent-session-compaction.test.ts test/suite/agent-session-compaction-model-overrides.test.ts test/suite/agent-session-bash-persistence.test.ts test/suite/agent-session-model-extension.test.ts test/clipboard.test.ts test/clipboard-command.test.ts test/clipboard-image.test.ts test/clipboard-image-bmp-conversion.test.ts test/clipboard-image-native-errors.test.ts src/cli/args.test.ts",
|
|
58
|
+
"test": "vitest run src/__tests__/model-registry-completion.test.ts src/extensions/jev/decisions.test.ts src/extensions/capability-gateway/routing.test.ts src/core/settings-manager-auto-handoff.test.ts src/core/remote-catalog-provider.test.ts src/extensions/jev-advisory-memory.test.ts src/extensions/jev-advisory-recommendations.test.ts src/extensions/jev-advisory-lifecycle.test.ts src/extensions/undo.test.ts src/extensions/tps.test.ts src/extensions/pi-graft src/extensions/agent-browser.test.ts src/extensions/auto-session-name.test.ts src/extensions/context-compaction-reminder.test.ts src/extensions/copy-turn.test.ts src/extensions/grep-app/index.test.ts src/extensions/inline-skills.test.ts src/extensions/rtk.test.ts src/extensions/handoff-new.test.ts src/extensions/question/tests src/extensions/ponytail/test src/__tests__/tokenin-search.test.ts src/__tests__/tokenin-onboarding.test.ts src/__tests__/model-registry-defaults.test.ts src/core/system-prompt.test.ts src/core/session-format.test.ts test/settings-manager-compaction.test.ts test/suite/agent-session-runtime.test.ts test/suite/agent-session-prompt.test.ts test/suite/agent-session-queue.test.ts test/suite/agent-session-retry-events.test.ts test/suite/agent-session-compaction.test.ts test/suite/agent-session-compaction-model-overrides.test.ts test/suite/agent-session-bash-persistence.test.ts test/suite/agent-session-model-extension.test.ts test/clipboard.test.ts test/clipboard-command.test.ts test/clipboard-image.test.ts test/clipboard-image-bmp-conversion.test.ts test/clipboard-image-native-errors.test.ts src/cli/args.test.ts",
|
|
59
|
+
"test:coverage": "vitest run --coverage src/__tests__/model-registry-completion.test.ts src/extensions/jev/decisions.test.ts src/extensions/capability-gateway/routing.test.ts src/core/settings-manager-auto-handoff.test.ts src/core/remote-catalog-provider.test.ts src/extensions/jev-advisory-memory.test.ts src/extensions/jev-advisory-recommendations.test.ts src/extensions/jev-advisory-lifecycle.test.ts src/extensions/undo.test.ts src/extensions/tps.test.ts src/extensions/agent-browser.test.ts src/extensions/auto-session-name.test.ts src/extensions/context-compaction-reminder.test.ts src/extensions/copy-turn.test.ts src/extensions/grep-app/index.test.ts src/extensions/inline-skills.test.ts src/extensions/rtk.test.ts src/extensions/handoff-new.test.ts src/extensions/question/tests src/extensions/ponytail/test src/__tests__/tokenin-search.test.ts src/__tests__/tokenin-onboarding.test.ts src/__tests__/model-registry-defaults.test.ts src/core/system-prompt.test.ts src/core/session-format.test.ts test/settings-manager-compaction.test.ts test/suite/agent-session-runtime.test.ts test/suite/agent-session-prompt.test.ts test/suite/agent-session-queue.test.ts test/suite/agent-session-retry-events.test.ts test/suite/agent-session-compaction.test.ts test/suite/agent-session-compaction-model-overrides.test.ts test/suite/agent-session-bash-persistence.test.ts test/suite/agent-session-model-extension.test.ts test/clipboard.test.ts test/clipboard-command.test.ts test/clipboard-image.test.ts test/clipboard-image-bmp-conversion.test.ts test/clipboard-image-native-errors.test.ts src/cli/args.test.ts",
|
|
60
60
|
"prepare": "npm run build",
|
|
61
61
|
"build": "npm run clean && tsgo -p tsconfig.build.json && shx chmod +x dist/cli.js dist/rpc-entry.js && npm run copy-assets",
|
|
62
62
|
"copy-assets": "shx mkdir -p dist/modes/interactive/theme && shx cp src/modes/interactive/theme/*.json dist/modes/interactive/theme/ && shx mkdir -p dist/modes/interactive/assets && shx cp src/modes/interactive/assets/*.png dist/modes/interactive/assets/ && shx mkdir -p dist/core/export-html/vendor && shx cp src/core/export-html/template.html src/core/export-html/template.css src/core/export-html/template.js dist/core/export-html/ && shx cp src/core/export-html/vendor/*.js dist/core/export-html/vendor/ && shx mkdir -p dist/defaults && shx cp src/defaults/* dist/defaults/ && shx mkdir -p dist/extensions && node scripts/copy-extensions.mjs && shx mkdir -p dist/themes && shx cp -r src/themes/. dist/themes/ && shx mkdir -p dist/skills && shx cp -r src/skills/. dist/skills/"
|