@selesai/code 0.8.10 → 0.8.12
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 +36 -0
- package/dist/core/agent-session.d.ts +24 -0
- package/dist/core/agent-session.js +151 -1
- package/dist/core/package-manager.d.ts +1 -0
- package/dist/core/package-manager.js +8 -8
- package/dist/core/package-manager.test.js +41 -2
- package/dist/core/resource-loader.d.ts +10 -1
- package/dist/core/resource-loader.js +45 -1
- package/dist/core/settings-manager.d.ts +6 -0
- package/dist/core/settings-manager.js +27 -0
- package/dist/core/tools/read-vision.test.d.ts +1 -0
- package/dist/core/tools/read-vision.test.js +122 -0
- package/dist/core/tools/read.d.ts +13 -1
- package/dist/core/tools/read.js +51 -1
- package/dist/core/vision-caption.d.ts +30 -0
- package/dist/core/vision-caption.js +62 -0
- package/dist/defaults/models.json +28 -5
- package/dist/extensions/model-prompt-injector/config.json +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +15 -0
- package/dist/modes/interactive/components/settings-selector.js +85 -2
- package/dist/modes/interactive/components/status-indicator.d.ts +4 -1
- package/dist/modes/interactive/components/status-indicator.js +5 -0
- package/dist/modes/interactive/interactive-mode.d.ts +4 -0
- package/dist/modes/interactive/interactive-mode.js +97 -1
- package/docs/settings.md +2 -0
- package/package.json +3 -1
|
@@ -61,7 +61,7 @@ import { ScopedModelsSelectorComponent } from "./components/scoped-models-select
|
|
|
61
61
|
import { SessionSelectorComponent } from "./components/session-selector.js";
|
|
62
62
|
import { SettingsSelectorComponent } from "./components/settings-selector.js";
|
|
63
63
|
import { SkillInvocationMessageComponent } from "./components/skill-invocation-message.js";
|
|
64
|
-
import { BranchSummaryStatusIndicator, CompactionStatusIndicator, IdleStatus, RetryStatusIndicator, WorkingStatusIndicator, } from "./components/status-indicator.js";
|
|
64
|
+
import { BranchSummaryStatusIndicator, CompactionStatusIndicator, IdleStatus, ImageCaptioningStatusIndicator, RetryStatusIndicator, WorkingStatusIndicator, } from "./components/status-indicator.js";
|
|
65
65
|
import { ToolExecutionComponent } from "./components/tool-execution.js";
|
|
66
66
|
import { TreeSelectorComponent } from "./components/tree-selector.js";
|
|
67
67
|
import { TrustSelectorComponent } from "./components/trust-selector.js";
|
|
@@ -2723,6 +2723,17 @@ export class InteractiveMode {
|
|
|
2723
2723
|
case "agent_settled":
|
|
2724
2724
|
await this.checkShutdownRequested();
|
|
2725
2725
|
break;
|
|
2726
|
+
case "image_captioning_start":
|
|
2727
|
+
this.showStatusIndicator(new ImageCaptioningStatusIndicator(this.ui));
|
|
2728
|
+
this.ui.requestRender();
|
|
2729
|
+
break;
|
|
2730
|
+
case "image_captioning_end":
|
|
2731
|
+
this.clearStatusIndicator("imageCaptioning");
|
|
2732
|
+
if (!event.ok) {
|
|
2733
|
+
this.showStatus("Image captioning failed; image omitted");
|
|
2734
|
+
}
|
|
2735
|
+
this.ui.requestRender();
|
|
2736
|
+
break;
|
|
2726
2737
|
case "compaction_start": {
|
|
2727
2738
|
if (this.settingsManager.getShowTerminalProgress()) {
|
|
2728
2739
|
this.ui.terminal.setProgress(true);
|
|
@@ -3668,6 +3679,9 @@ export class InteractiveMode {
|
|
|
3668
3679
|
imageWidthCells: this.settingsManager.getImageWidthCells(),
|
|
3669
3680
|
autoResizeImages: this.settingsManager.getImageAutoResize(),
|
|
3670
3681
|
blockImages: this.settingsManager.getBlockImages(),
|
|
3682
|
+
imageCaptionModel: this.settingsManager.getImageCaptionModel(),
|
|
3683
|
+
imageCaptionContextTokens: this.settingsManager.getImageCaptionContextTokens(),
|
|
3684
|
+
visionModels: this.getVisionModels(),
|
|
3671
3685
|
steeringMode: this.session.steeringMode,
|
|
3672
3686
|
followUpMode: this.session.followUpMode,
|
|
3673
3687
|
transport: this.settingsManager.getTransport(),
|
|
@@ -3695,6 +3709,7 @@ export class InteractiveMode {
|
|
|
3695
3709
|
fullscreenExitOutput: this.settingsManager.getFullscreenExitOutput(),
|
|
3696
3710
|
fullscreenScrollbar: this.settingsManager.getFullscreenScrollbar(),
|
|
3697
3711
|
warnings: this.settingsManager.getWarnings(),
|
|
3712
|
+
skills: this.buildSkillToggleItems(),
|
|
3698
3713
|
}, {
|
|
3699
3714
|
onAutoCompactChange: (enabled) => {
|
|
3700
3715
|
this.session.setAutoCompactionEnabled(enabled);
|
|
@@ -3728,6 +3743,14 @@ export class InteractiveMode {
|
|
|
3728
3743
|
onBlockImagesChange: (blocked) => {
|
|
3729
3744
|
this.settingsManager.setBlockImages(blocked);
|
|
3730
3745
|
},
|
|
3746
|
+
onImageCaptionModelChange: (modelId) => {
|
|
3747
|
+
this.settingsManager.setImageCaptionModel(modelId);
|
|
3748
|
+
this.showStatus(modelId ? `Vision caption model: ${modelId}` : "Vision captioning disabled");
|
|
3749
|
+
},
|
|
3750
|
+
onImageCaptionContextTokensChange: (tokens) => {
|
|
3751
|
+
this.settingsManager.setImageCaptionContextTokens(tokens);
|
|
3752
|
+
this.showStatus(`Vision caption context: ${tokens} tokens`);
|
|
3753
|
+
},
|
|
3731
3754
|
onSteeringModeChange: (mode) => {
|
|
3732
3755
|
this.session.setSteeringMode(mode);
|
|
3733
3756
|
},
|
|
@@ -3855,6 +3878,12 @@ export class InteractiveMode {
|
|
|
3855
3878
|
onWarningsChange: (warnings) => {
|
|
3856
3879
|
this.settingsManager.setWarnings(warnings);
|
|
3857
3880
|
},
|
|
3881
|
+
onSkillsToggle: (item, enabled) => {
|
|
3882
|
+
this.toggleSkillSetting(item, enabled);
|
|
3883
|
+
},
|
|
3884
|
+
onSkillsReload: () => {
|
|
3885
|
+
void this.reloadAfterSkillChange();
|
|
3886
|
+
},
|
|
3858
3887
|
onCancel: () => {
|
|
3859
3888
|
done();
|
|
3860
3889
|
this.ui.requestRender();
|
|
@@ -3863,6 +3892,73 @@ export class InteractiveMode {
|
|
|
3863
3892
|
return { component: selector, focus: selector.getSettingsList() };
|
|
3864
3893
|
});
|
|
3865
3894
|
}
|
|
3895
|
+
getVisionModels() {
|
|
3896
|
+
try {
|
|
3897
|
+
const models = this.session.scopedModels.length > 0
|
|
3898
|
+
? this.session.scopedModels.map((s) => s.model)
|
|
3899
|
+
: this.session.modelRuntime.getAvailableSnapshot();
|
|
3900
|
+
return models
|
|
3901
|
+
.filter((m) => m.input.includes("image"))
|
|
3902
|
+
.map((m) => `${m.provider}/${m.id}`)
|
|
3903
|
+
.sort();
|
|
3904
|
+
}
|
|
3905
|
+
catch {
|
|
3906
|
+
return [];
|
|
3907
|
+
}
|
|
3908
|
+
}
|
|
3909
|
+
buildSkillToggleItems() {
|
|
3910
|
+
const resolvedSkills = this.session.resourceLoader.getResolvedSkills();
|
|
3911
|
+
const agentDir = getAgentDir();
|
|
3912
|
+
const items = [];
|
|
3913
|
+
for (const resource of resolvedSkills) {
|
|
3914
|
+
const pathStr = resource.path;
|
|
3915
|
+
const isSkillFile = path.basename(pathStr) === "SKILL.md";
|
|
3916
|
+
const name = isSkillFile ? path.basename(path.dirname(pathStr)) : path.basename(pathStr);
|
|
3917
|
+
const scope = resource.metadata.scope === "project" ? "project" : "user";
|
|
3918
|
+
const baseDir = resource.metadata.baseDir ??
|
|
3919
|
+
(scope === "project" ? path.join(this.sessionManager.getCwd(), CONFIG_DIR_NAME) : agentDir);
|
|
3920
|
+
const pattern = path.relative(baseDir, pathStr) || name;
|
|
3921
|
+
items.push({
|
|
3922
|
+
name,
|
|
3923
|
+
pattern,
|
|
3924
|
+
scope,
|
|
3925
|
+
id: `${scope}:${pattern}`,
|
|
3926
|
+
enabled: resource.enabled,
|
|
3927
|
+
});
|
|
3928
|
+
}
|
|
3929
|
+
items.sort((a, b) => a.name.localeCompare(b.name));
|
|
3930
|
+
return items;
|
|
3931
|
+
}
|
|
3932
|
+
toggleSkillSetting(item, enabled) {
|
|
3933
|
+
if (item.scope === "project" && !this.settingsManager.isProjectTrusted()) {
|
|
3934
|
+
this.showError("Project is not trusted; cannot change project skills. Trust the project first.");
|
|
3935
|
+
return;
|
|
3936
|
+
}
|
|
3937
|
+
const settings = item.scope === "project"
|
|
3938
|
+
? this.settingsManager.getProjectSettings()
|
|
3939
|
+
: this.settingsManager.getGlobalSettings();
|
|
3940
|
+
const current = [...(settings.skills ?? [])];
|
|
3941
|
+
const updated = current.filter((p) => {
|
|
3942
|
+
const stripped = p.startsWith("!") || p.startsWith("+") || p.startsWith("-") ? p.slice(1) : p;
|
|
3943
|
+
return stripped !== item.pattern;
|
|
3944
|
+
});
|
|
3945
|
+
updated.push(enabled ? `+${item.pattern}` : `-${item.pattern}`);
|
|
3946
|
+
if (item.scope === "project") {
|
|
3947
|
+
this.settingsManager.setProjectSkillPaths(updated);
|
|
3948
|
+
}
|
|
3949
|
+
else {
|
|
3950
|
+
this.settingsManager.setSkillPaths(updated);
|
|
3951
|
+
}
|
|
3952
|
+
}
|
|
3953
|
+
async reloadAfterSkillChange() {
|
|
3954
|
+
try {
|
|
3955
|
+
await this.session.reload();
|
|
3956
|
+
this.ui.requestRender();
|
|
3957
|
+
}
|
|
3958
|
+
catch (error) {
|
|
3959
|
+
this.showError(`Failed to reload after skill change: ${error instanceof Error ? error.message : String(error)}`);
|
|
3960
|
+
}
|
|
3961
|
+
}
|
|
3866
3962
|
async handleModelCommand(searchTerm) {
|
|
3867
3963
|
if (!searchTerm) {
|
|
3868
3964
|
this.showModelSelector();
|
package/docs/settings.md
CHANGED
|
@@ -171,6 +171,8 @@ Keep `retry.provider.maxRetries` at `0` unless provider-level retries are explic
|
|
|
171
171
|
| `terminal.clearOnShrink` | boolean | `false` | Clear empty rows when content shrinks (can cause flicker) |
|
|
172
172
|
| `images.autoResize` | boolean | `true` | Resize images to 2000x2000 max |
|
|
173
173
|
| `images.blockImages` | boolean | `false` | Block all images from being sent to LLM |
|
|
174
|
+
| `images.imageCaptionModel` | string | unset | Vision model (`provider/model`) to describe images when the active model cannot accept images; the caption text is used in place of the image (e.g. `tokenin/gemma-4`, `tokenin/kimi-k3`) |
|
|
175
|
+
| `images.imageCaptionContextTokens` | number | `16384` | Max token budget (approx) for the recent-conversation context sent to the caption model. Messages are kept whole (cut at message boundaries only); the user's current prompt is always included |
|
|
174
176
|
|
|
175
177
|
### Shell
|
|
176
178
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@selesai/code",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.12",
|
|
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
|
"repository": {
|
|
@@ -50,6 +50,8 @@
|
|
|
50
50
|
],
|
|
51
51
|
"scripts": {
|
|
52
52
|
"clean": "shx rm -rf dist",
|
|
53
|
+
"dev": "tsx src/cli.ts",
|
|
54
|
+
"dev:print": "tsx src/cli.ts --print",
|
|
53
55
|
"test": "vitest run src/extensions/undo.test.ts src/extensions/agent-browser.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/model-prompt-injector/index.test.ts src/extensions/web-agent-onboarding.test.ts src/extensions/handoff-new.test.ts src/extensions/question/tests src/extensions/ponytail/test src/__tests__/tokenin-onboarding.test.ts src/__tests__/workflow-modes.test.ts src/__tests__/model-registry-defaults.test.ts src/cli/args.test.ts",
|
|
54
56
|
"test:coverage": "vitest run --coverage src/extensions/undo.test.ts src/extensions/agent-browser.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/model-prompt-injector/index.test.ts src/extensions/web-agent-onboarding.test.ts src/extensions/handoff-new.test.ts src/extensions/question/tests src/extensions/ponytail/test src/__tests__/tokenin-onboarding.test.ts src/__tests__/workflow-modes.test.ts src/__tests__/model-registry-defaults.test.ts src/cli/args.test.ts",
|
|
55
57
|
"prepare": "npm run build",
|