scalix 1.5.1 → 1.6.0

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/.env.example CHANGED
@@ -1,8 +1,10 @@
1
1
  # Required — your Scalix API key
2
- SCALIX_API_KEY=sk-...
2
+ SCALIX_API_KEY=scalix_sk_...
3
3
 
4
- # Optional — custom API base URL (defaults to Scalix cloud)
5
- # SCALIX_BASE_URL=https://api.scalix.world/v1
4
+ # Optional — API base URL. This is the host root, NOT the /v1 endpoint: the
5
+ # client appends /v1/ai/... itself. Point it at a self-hosted gateway if you
6
+ # have one; the default is Scalix cloud.
7
+ # SCALIX_BASE_URL=https://api.scalix.world
6
8
 
7
9
  # Optional — override the default model
8
10
  # SCALIX_MODEL=
package/CHANGELOG.md CHANGED
@@ -2,6 +2,46 @@
2
2
 
3
3
  All notable changes to Scalix Coder will be documented in this file.
4
4
 
5
+ ## [1.6.0] - 2026-11-11
6
+
7
+ ### Added
8
+ - **`/marketplace` — the Scalix curated plugin catalog.** Browse, inspect and install catalog listings from the TUI: MCP servers into `mcp-services.json`, skills into `.scalix/skills/`, rules into `.scalix/rules/`, subagents into `.scalix/agents/`. Every listing is re-validated client-side before anything touches disk (https-only public-host remote entries, bare stdio command names, relative file paths, env-var names only — never credential values), stdio installs require explicit confirmation, and install telemetry is best-effort and anonymous. New module `src/marketplace.ts`; 21 unit tests.
9
+
10
+ ### Security
11
+ - **Repo-supplied slash commands are trust-gated and run with a sanitized environment.** `.scalix/commands/*.md` templates were loaded in every front end without the workspace-trust check that plugins and hooks get, and their `` !`cmd` `` inline-bash expansions executed with the full parent environment — API keys readable. Inline bash now runs with `sanitizeEnvForCommand()`, loading is gated on `isWorkspaceTrusted()` (with a skip notice), and a repo carrying `commands/` now triggers the trust prompt. (Audit F1)
12
+ - **`browser_session_save` / `restore` reject traversal names.** The `name` argument became a filename via `path.join` without validation, so `../../..` wrote and read JSON outside the sandbox. Names are now restricted to `[A-Za-z0-9._-]` at the schema and in `saveSessionState`. (F2)
13
+ - **`search_files` ripgrep fast path is sandbox-contained.** The rg branch took any absolute `path` and read it; the JS fallback already validated. The target now goes through `sandboxPath()` before any backend runs, with rg output relativized to preserve the old shape. (F3)
14
+ - **Project `settings.local.json` can no longer escalate permissions.** A trusted repo could set `permissionMode: "yolo"`, reclassify tools via `toolOverrides`, disable blocklist/injection patterns, or add scoped "allow" rules. Project files may now only tighten: `plan` mode, deny-only scoped rules, and a whitelist of tightening security fields; escalation attempts are ignored with a notice. Managed settings (`managed-settings.json`) are now validated with the same validators as user config. (F4)
15
+ - **`@file` prompt references are sandbox-contained.** `@/abs/path.ext` in a prompt read any file on disk in the TUI and was attacker-influenceable via `--pipe`; both `agent.ts` and `commands.ts` expansion now route through the sandbox check. (F5)
16
+ - **Alibaba Cloud metadata IP `100.100.100.200` is treated as private** by `web_fetch` and the browser tools — it sits outside every previously-listed range and exposed instance credentials on ECS. (F9)
17
+ - MCP `serverUrl` values are redacted (userinfo stripped) before logging; MCP fetch now downgrades 301/302/303 redirects of POST requests to GET and drops the body per the fetch spec. (F12 + redirect semantics)
18
+ - IPC `setPermissionMode` validates the mode against `PERMISSION_MODES` instead of applying any string. (F14)
19
+
20
+ ### Fixed
21
+ - **A user abort no longer pollutes the model circuit breaker.** Aborting mid-request was recorded as a model failure — five Escapes within the reset window silently rotated the model. The abort path now returns `'[interrupted]'` consistently whether it lands between tool calls or mid-request. (Audit: agent abort contract)
22
+ - **Retry backoff, stream-fallback waits, and tool-confirmation prompts are abort-aware.** Cancelling during a Retry-After wait (up to 60s) or a pending confirmation (up to 300s) returns immediately instead of parking the loop.
23
+ - **Conflicted sub-agent worktree merges keep their branch.** Teardown ran `git branch -D` unconditionally, destroying the sub-agent's unmerged commits right after reporting the conflict; removal now uses a safe delete and keeps unmerged `scalix-agent/*` branches for recovery. A failed merge probe is reported as a failure (with `error`) instead of `{merged: true, commitCount: 0}`.
24
+ - **`/delegate` works on BYOK sessions.** The headless sub-agent config omitted `provider` (and cloud credentials), so the sub-agent called the Scalix URL shape against a third-party base URL and 404'd on every request.
25
+ - **Per-request timeout defaults to 300s.** The comment promised it but unset `SCALIX_REQUEST_TIMEOUT_MS` meant *no* timeout; a wedged connection hung the turn forever.
26
+ - The capability probe (`streamsToolCalls`) can no longer fail a turn — errors default to the conservative non-streaming answer.
27
+ - `clearHistory()` / `loadMessages()` reset the output-format instruction index, so a `/load` followed by a JSON-format request can no longer overwrite an unrelated system message.
28
+ - Streaming TTFT and per-turn metrics reset each loop iteration, so `turn:summary` reports the turn that produced the final response.
29
+ - `scalix run` no longer double-prints errors (REPORTED_ERROR dedup applied to headless).
30
+
31
+ ### VS Code extension
32
+ - **Fixed the send dead-latch.** The chat panel set the tab's `isRunning` flag before reading it, so the direct-send branch was dead code: every message queued as "Queued: …" and was only released when an unrelated engine status event arrived.
33
+ - **Chat tabs stay in sync with the engine.** Switching tabs now posts `switchSession` (the host previously kept sending to the previous tab's session, and background-tab streams were dropped); `send`/`abort` honor the message's own `sessionId` with the host value as fallback. Queued messages now carry their images through the queue.
34
+ - **Feedback is actually stored.** The submit-feedback flow thanked the user and discarded everything; it now records through `FeedbackService` (local history, capped at 100 — nothing leaves the machine).
35
+ - **Tool-approval handler cleanup on dispose.** With a sidebar and an editor-tab chat open, closing the editor tab left its dead confirm handler registered, so in-panel approvals silently stopped for the surviving surface.
36
+ - `scalix.cliPath`, `scalix.baseUrl`, `scalix.openaiBaseUrl`, `scalix.provider`, and `scalix.permissionMode` are now machine-scoped — a repo's `.vscode/settings.json` can no longer point the engine spawn at arbitrary code or redirect the API key's destination endpoint.
37
+
38
+ ### Known issues (from the 2026-10-14 audit, not yet addressed)
39
+ - The webview's per-tab `innerHTML` cache destroys event listeners on restored tabs (dead confirm-card buttons after a tab round-trip) — needs the data-driven re-render refactor.
40
+ - Background-tab stream events are still dropped rather than buffered per session.
41
+ - The OS command sandbox (seatbelt/bwrap) remains opt-in and default-off; the regex command blocklist is explicitly not a security boundary.
42
+ - DNS-rebinding TOCTOU remains in `web_fetch`/MCP fetch (validation and fetch resolve DNS independently).
43
+ - `vscode-extension/tests` are still not wired into either publish workflow.
44
+
5
45
  ## [1.5.1] - 2026-08-08
6
46
 
7
47
  ### Added
package/LICENSE CHANGED
@@ -2,7 +2,6 @@ SCALIX WORLD PRIVATE LIMITED
2
2
  END USER LICENSE AGREEMENT (EULA)
3
3
 
4
4
  Copyright (c) 2025-2026 Scalix World Pvt Ltd. All rights reserved.
5
- A subsidiary of Energy FW Ltd (UK Company No. 14600160)
6
5
 
7
6
  IMPORTANT — READ CAREFULLY BEFORE USING THIS SOFTWARE.
8
7
 
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  AI-powered coding agent for the terminal and [VS Code](https://marketplace.visualstudio.com/items?itemName=scalix.scalix) — built by [Scalix World](https://scalix.world).
4
4
 
5
- ![Version](https://img.shields.io/badge/version-1.4.0-blue)
5
+ [![npm](https://img.shields.io/npm/v/scalix?color=blue)](https://www.npmjs.com/package/scalix)
6
6
  ![Node](https://img.shields.io/badge/node-%3E%3D18-green)
7
7
  ![License](https://img.shields.io/badge/license-EULA-orange)
8
8
 
@@ -61,12 +61,28 @@ Notes:
61
61
 
62
62
  ### Install
63
63
 
64
+ ```bash
65
+ npm install -g scalix
66
+ ```
67
+
68
+ Requires Node 18 or newer. If `npm install -g` needs `sudo` on your machine, that
69
+ is a sign npm's global prefix points somewhere root-owned — point it at your home
70
+ directory (`npm config set prefix ~/.npm-global`) rather than installing as root.
71
+
72
+ <details>
73
+ <summary>From source (contributors)</summary>
74
+
75
+ The repository is private; you need access before this will clone.
76
+
64
77
  ```bash
65
78
  git clone https://github.com/scalixworld/scalix-coder.git && cd scalix-coder
66
79
  npm install
67
- sudo npm link
80
+ npm run build
81
+ npm link
68
82
  ```
69
83
 
84
+ </details>
85
+
70
86
  ### Run
71
87
 
72
88
  ```bash
@@ -83,6 +99,7 @@ First launch opens a setup wizard to configure your Scalix API key, endpoint, an
83
99
  | `SCALIX_MODEL` | Comma-separated model IDs |
84
100
  | `SCALIX_BASE_URL` | API base URL |
85
101
  | `SCALIX_PROJECT` | Project ID for org-wide keys (sent as `x-scalix-project` on platform tool calls) |
102
+ | `SCALIX_COMMAND_SANDBOX` | OS-level command sandbox: `off` \| `filesystem` \| `strict` (overrides config) |
86
103
  | `BRAVE_API_KEY` | Brave Search API key |
87
104
  | `TAVILY_API_KEY` | Tavily Search API key |
88
105
 
@@ -106,6 +123,7 @@ scalix run "generate a migration" --output migration.sql --format patch
106
123
  | `/models` | List active models |
107
124
  | `/model` | Switch model |
108
125
  | `/mode` | Set permission mode |
126
+ | `/sandbox` | Set the OS command sandbox (off \| filesystem \| strict) |
109
127
  | `/compact` | Compress context |
110
128
  | `/cost` | Token usage & cost |
111
129
  | `/budget` | Budget status |
@@ -208,7 +226,9 @@ scalix run "generate a migration" --output migration.sql --format patch
208
226
  | `notebook_edit` | Jupyter notebook operations |
209
227
  | `monitor` | Background process output |
210
228
  | `agent` | Spawn sub-agents |
211
- | `add_mcp_server` | Register MCP servers |
229
+ | `write_artifact` | Write a reviewable plan / walkthrough / tasklist / summary to `.scalix/artifacts/` |
230
+ | `list_artifacts` | List previously written artifacts (newest first) |
231
+ | `add_mcp_server` | Register MCP servers |
212
232
 
213
233
  ## Configuration
214
234
 
@@ -239,6 +259,74 @@ Config is stored in `~/.scalix-coder/config.json`.
239
259
  | `.scalix/rules/*.md` | Scoped rules |
240
260
  | `mcp-services.json` | MCP server config |
241
261
 
262
+ ### Command sandbox (opt-in)
263
+
264
+ `run_command` can execute inside a kernel-enforced sandbox — the OS-level wall
265
+ behind the logical checks (blocklist, injection detection, path containment).
266
+ Set `commandSandbox` in `~/.scalix-coder/config.json` (or `SCALIX_COMMAND_SANDBOX`):
267
+
268
+ | Mode | What it does |
269
+ | ------------ | ------------ |
270
+ | `off` | Default. No sandbox — behaviour unchanged. |
271
+ | `filesystem` | macOS seatbelt / Linux bubblewrap: writes confined to the workspace + system temp, reads unrestricted, network allowed. |
272
+ | `strict` | `filesystem` plus no network (unshared netns / seatbelt `deny network*`). For untrusted builds. |
273
+
274
+ Notes: Windows is not supported — with a mode set there, commands fail closed
275
+ with the reason instead of running unsandboxed. Package managers that cache in
276
+ `$HOME` (pip, cargo) will fail cache writes in `filesystem` mode; that is the
277
+ wall working. The backend binary must exist (`sandbox-exec` on macOS ships with
278
+ the OS; `bwrap` must be installed on Linux) — a missing backend is reported,
279
+ never skipped.
280
+
281
+ ### MCP servers
282
+
283
+ Servers listed in `mcp-services.json` (project root, or `.scalix/` as a
284
+ fallback) are connected at startup and their tools are offered to the model as
285
+ `mcp__<server>__<tool>`. Both transports are supported:
286
+
287
+ ```json
288
+ {
289
+ "mcpServers": [
290
+ { "serverLabel": "github", "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"],
291
+ "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_…" } },
292
+ { "serverLabel": "docs", "serverUrl": "https://docs.example.com/mcp", "authorizationEnv": "DOCS_TOKEN" }
293
+ ]
294
+ }
295
+ ```
296
+
297
+ The Claude Desktop / VS Code object-map dialect (`"mcpServers": {"github": {…}}`)
298
+ is accepted too, so an existing config can be dropped in unchanged.
299
+
300
+ - `disabled: true` skips an entry without deleting it; `allowedTools.toolNames`
301
+ registers only the named tools from that server.
302
+ - A server that fails to start is logged and skipped — it never takes the run
303
+ down with it. `/mcp` lists the status of each.
304
+ - **Command (stdio) servers only start in a trusted workspace**, because
305
+ spawning one runs arbitrary local code. They get a clean environment, not the
306
+ agent's, so they cannot read its API keys.
307
+ - MCP tools are external, so they require confirmation under the default
308
+ permission mode.
309
+
310
+ ### Scalix Marketplace (`/marketplace`)
311
+
312
+ Browse the curated plugin catalog and install it in one command:
313
+
314
+ ```
315
+ /marketplace featured listings
316
+ /marketplace <query> search the catalog
317
+ /marketplace info <id> detail + what an install would write
318
+ /marketplace install <id> install (stdio MCP needs `--confirm`)
319
+ ```
320
+
321
+ Four artifact kinds are installed into this workspace: **MCP servers**
322
+ (`mcp-services.json`), **skills** (`.scalix/skills/<name>/`), **rules**
323
+ (`.scalix/rules/`) and **subagents** (`.scalix/agents/`). Every listing carries
324
+ a trust tier — ★ official, ✔ verified, · community — and an env-var reference
325
+ is stored by NAME only (you set the value in your environment). The catalog is
326
+ fetched from `https://api.scalix.world/v1/marketplace` (override with
327
+ `SCALIX_MARKETPLACE_URL`); payloads are re-validated before anything is
328
+ written to disk. Full contract: `scalix-cloud/docs/MARKETPLACE.md`.
329
+
242
330
  ## VS Code Extension
243
331
 
244
332
  Install from the [VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=scalix.scalix) — or from [Open VSX](https://open-vsx.org/extension/scalix/scalix) if you use Cursor, Windsurf, or VSCodium:
@@ -0,0 +1,33 @@
1
+ export const AGENT_PRESETS = [
2
+ {
3
+ id: 'cloud-architect',
4
+ name: 'Cloud Architect',
5
+ description: 'Full Scalix Cloud tools access with architecture-first planning',
6
+ systemPromptAdditions: 'You are an expert Scalix Cloud Architect. Prioritize robust, scalable infrastructure. Plan changes carefully.',
7
+ permissionMode: 'default'
8
+ },
9
+ {
10
+ id: 'dba',
11
+ name: 'Database Administrator',
12
+ description: 'Focused on database migrations and SQL optimization',
13
+ systemPromptAdditions: 'You are a Senior DBA. Prioritize data integrity and query performance. Always verify schemas before altering.',
14
+ permissionMode: 'default'
15
+ },
16
+ {
17
+ id: 'devops',
18
+ name: 'DevOps Engineer',
19
+ description: 'CI/CD, deployments, and infrastructure management',
20
+ systemPromptAdditions: 'You are a DevOps engineer focused on CI/CD pipelines, containerization, and safe deployments.',
21
+ permissionMode: 'default'
22
+ },
23
+ {
24
+ id: 'full-access',
25
+ name: 'Full Access (Auto)',
26
+ description: 'All tools enabled, autonomous execution mode',
27
+ systemPromptAdditions: 'You are fully autonomous. Execute the required steps directly.',
28
+ permissionMode: 'auto'
29
+ }
30
+ ];
31
+ export function getPreset(id) {
32
+ return AGENT_PRESETS.find(p => p.id === id);
33
+ }