sigit-code 1.4.1__tar.gz → 1.5.1__tar.gz
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.
- {sigit_code-1.4.1 → sigit_code-1.5.1}/.agents/AGENTS.md +64 -12
- {sigit_code-1.4.1 → sigit_code-1.5.1}/.github/workflows/ci.yml +4 -0
- sigit_code-1.5.1/.github/workflows/release-mcp-registry.yml +79 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/AGENTS.md +64 -12
- {sigit_code-1.4.1 → sigit_code-1.5.1}/CHANGELOG.md +78 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/CLAUDE.md +64 -12
- {sigit_code-1.4.1 → sigit_code-1.5.1}/Cargo.lock +543 -113
- {sigit_code-1.4.1 → sigit_code-1.5.1}/Cargo.toml +3 -3
- {sigit_code-1.4.1 → sigit_code-1.5.1}/PKG-INFO +2 -2
- {sigit_code-1.4.1 → sigit_code-1.5.1}/README.md +26 -1
- sigit_code-1.5.1/docs/hooks.md +92 -0
- sigit_code-1.5.1/docs/mcp.md +68 -0
- sigit_code-1.5.1/examples/settings-with-hooks.toml +49 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/pypi/pyproject.toml +5 -1
- {sigit_code-1.4.1 → sigit_code-1.5.1}/pyproject.toml +5 -1
- sigit_code-1.5.1/server.json +39 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/src/chat.rs +923 -38
- sigit_code-1.5.1/src/commands.rs +436 -0
- sigit_code-1.5.1/src/frontmatter.rs +200 -0
- sigit_code-1.5.1/src/hooks.rs +507 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/src/main.rs +298 -77
- {sigit_code-1.4.1 → sigit_code-1.5.1}/src/mcp.rs +170 -11
- {sigit_code-1.4.1 → sigit_code-1.5.1}/src/permissions.rs +179 -18
- {sigit_code-1.4.1 → sigit_code-1.5.1}/src/settings.rs +17 -2
- {sigit_code-1.4.1 → sigit_code-1.5.1}/src/skills.rs +6 -149
- sigit_code-1.5.1/src/subagents.rs +327 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/src/tools.rs +530 -71
- {sigit_code-1.4.1 → sigit_code-1.5.1}/.agents/skills/agent-client-protocol/SKILL.md +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/.agents/skills/ai-assisted-coding/SKILL.md +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/.agents/skills/branding/SKILL.md +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/.agents/skills/run-sigit/SKILL.md +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/.agents/skills/run-sigit/driver.mjs +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/.agents/skills/run-sigit/tui-smoke.sh +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/.agents/skills/sigit-code-release/SKILL.md +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/.agents/skills/tool-calling/SKILL.md +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/.claude/skills/agent-client-protocol/SKILL.md +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/.claude/skills/ai-assisted-coding/SKILL.md +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/.claude/skills/branding/SKILL.md +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/.claude/skills/run-sigit/SKILL.md +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/.claude/skills/run-sigit/driver.mjs +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/.claude/skills/run-sigit/tui-smoke.sh +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/.claude/skills/sigit-code-release/SKILL.md +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/.claude/skills/tool-calling/SKILL.md +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/.github/workflows/release-crates.yml +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/.github/workflows/release-github.yml +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/.github/workflows/release-homebrew.yml +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/.github/workflows/release-npm.yml +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/.github/workflows/release-pypi.yml +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/.gitignore +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/.nvmrc +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/LICENSE +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/examples/skills/README.md +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/examples/skills/commit-message/SKILL.md +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/npm/README.md.tmpl +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/npm/package-main.json.tmpl +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/npm/package.json.tmpl +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/npm/scripts/render-main-package.cjs +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/npm/scripts/render-platform-package.cjs +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/npm/sigit/.gitignore +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/npm/sigit/README.md +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/npm/sigit/package.json +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/npm/sigit/src/index.ts +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/npm/sigit/tsconfig.json +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/pypi/README.md +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/rust-toolchain.toml +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/src/account.rs +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/src/backend.rs +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/src/credentials.rs +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/src/headless.rs +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/src/instructions.rs +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/src/models.rs +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/src/provider.rs +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/src/session_store.rs +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/src/setup.rs +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/tests/acp_permissions.rs +0 -0
- {sigit_code-1.4.1 → sigit_code-1.5.1}/tests/headless_mode.rs +0 -0
|
@@ -110,7 +110,23 @@ feeds results back. Neither the loop nor ACP/TUI surfaces depend on a concrete b
|
|
|
110
110
|
spec list (`all_tools`) and the execute `match` (`execute_tool`). `run_command` also enforces
|
|
111
111
|
commit attribution: when a command creates a new commit that lacks the
|
|
112
112
|
`Co-Authored-By: siGit Code` trailer (`COMMIT_CO_AUTHOR_TRAILER`), it amends the trailer in —
|
|
113
|
-
unless the commit already exists on a remote, which is never rewritten.
|
|
113
|
+
unless the commit already exists on a remote, which is never rewritten. Also owns the `task`
|
|
114
|
+
tool: a nested agent loop in a fresh conversation, offered only when `subagent_available()`
|
|
115
|
+
(a subagent factory is registered — see `register_subagent_factory_for` in `main.rs`; on-device
|
|
116
|
+
registers a `None`-returning factory since onde has a single shared history). A subagent's
|
|
117
|
+
toolset is a hard-gated read-only allow-list (`SUBAGENT_TOOL_NAMES`) that is never expanded by a
|
|
118
|
+
configurable subagent type (see `src/subagents.rs`) — only ever narrowed — so a `.sigit/agents/*.md`
|
|
119
|
+
file can't grant itself `edit_file`/`run_command` and bypass the permission system. Also owns
|
|
120
|
+
`web_search`: a thin native wrapper around the official MCP server's Brave-Search-backed
|
|
121
|
+
`web_search` tool (`mcp__sigit__web_search`, implemented server-side in `sigit-si`'s
|
|
122
|
+
`WebSearchService` + `Mcp::Tools::WebSearch`), offered only when that MCP tool was actually
|
|
123
|
+
discovered (i.e. the user is signed in to siGit Code Cloud — see `web_search_available`).
|
|
124
|
+
Wrapping it natively rather than leaving it as a raw `mcp__*` tool matters for two reasons:
|
|
125
|
+
`permissions::classify` treats every `mcp__*` tool as mutating (an "ask" prompt on every call),
|
|
126
|
+
while `web_search` is read-only like `read_website`; and the raw delegate name is filtered out
|
|
127
|
+
of the assembled tool list (`is_web_search_delegate`) so the model sees one clean option, not
|
|
128
|
+
two names for the same tool. Execution still forwards verbatim to `mcp::call_tool` — no second
|
|
129
|
+
HTTP/JSON-RPC implementation.
|
|
114
130
|
- **`src/skills.rs`** — [Agent Skills](https://agentskills.io) support. Discovers skill
|
|
115
131
|
folders (each with a `SKILL.md`: YAML frontmatter `name` + `description`, then Markdown
|
|
116
132
|
instructions) from `.sigit/skills/` and `.claude/skills/` in the cwd, `$SIGIT_CONFIG_DIR/skills/`,
|
|
@@ -119,6 +135,31 @@ feeds results back. Neither the loop nor ACP/TUI surfaces depend on a concrete b
|
|
|
119
135
|
calls `skill` with a name) loads the full `SKILL.md` body. The `skill` tool is appended in the
|
|
120
136
|
`*_as_specs`/`build_tool_specs` layer (not in `all_tools()`) so its description can be dynamic,
|
|
121
137
|
and only when at least one skill exists.
|
|
138
|
+
- **`src/commands.rs`** — user-defined slash commands. Discovers Markdown files (each an
|
|
139
|
+
optional YAML frontmatter block — `description`, `argument-hint` — followed by a prompt-template
|
|
140
|
+
body) from `.sigit/commands/` and `.claude/commands/` in the cwd, `$SIGIT_CONFIG_DIR/commands/`,
|
|
141
|
+
and `~/.claude/commands/`. A subdirectory namespaces the command with `:`
|
|
142
|
+
(`.sigit/commands/git/commit.md` → `/git:commit`). Unlike skills there's no tool-call
|
|
143
|
+
indirection: invoking one works exactly like the built-in `/init` — `commands::render`
|
|
144
|
+
substitutes `$ARGUMENTS`/`$1..$9` in the body against whatever followed the command on the
|
|
145
|
+
input line, and the result is fed to the model as a normal turn through the ordinary tools and
|
|
146
|
+
permission checks. Resolution happens where each surface (`main.rs`/`chat.rs`) already
|
|
147
|
+
special-cases `/init`: an unrecognized slash command is tried against `commands::resolve_command`
|
|
148
|
+
before falling back to "unknown command". A custom command sharing a name with a built-in is
|
|
149
|
+
unreachable (built-ins match first in `parse_slash`) and is skipped when advertised to ACP
|
|
150
|
+
clients, with a warning logged.
|
|
151
|
+
- **`src/subagents.rs`** — configurable subagent types for the `task` tool. Discovers Markdown
|
|
152
|
+
files (YAML frontmatter `name` + `description`, optional comma-separated `tools:` allow-list,
|
|
153
|
+
then a Markdown body that becomes the subagent's system prompt) from `.sigit/agents/` and
|
|
154
|
+
`.claude/agents/` in the cwd, `$SIGIT_CONFIG_DIR/agents/`, and `~/.claude/agents/`. Passing a
|
|
155
|
+
type's `name` as `task`'s `subagent_type` argument swaps in that system prompt and, if `tools:`
|
|
156
|
+
is set, narrows the offered toolset to its *intersection* with `SUBAGENT_TOOL_NAMES` — the
|
|
157
|
+
security-relevant narrowing logic lives in `tools.rs` next to that constant, not here; this
|
|
158
|
+
module only discovers and parses files. `SubagentFactory` (in `tools.rs`) takes the resolved
|
|
159
|
+
system prompt per call rather than baking one in at registration, so a single registered
|
|
160
|
+
factory serves both the default research subagent and every configured type.
|
|
161
|
+
- **`src/frontmatter.rs`** — shared "YAML frontmatter + Markdown body" parsing used by both
|
|
162
|
+
`src/skills.rs` (`SKILL.md`) and `src/commands.rs` (`.sigit/commands/*.md`).
|
|
122
163
|
- **`src/mcp.rs`** — [Model Context Protocol](https://modelcontextprotocol.io) *client*. Two
|
|
123
164
|
transports: **Streamable HTTP** (one JSON-RPC POST endpoint, `url` in `mcp.toml`; replies are
|
|
124
165
|
`application/json` or SSE) and **stdio** (`command` + optional `args`/`[server.env]` in
|
|
@@ -131,12 +172,20 @@ feeds results back. Neither the loop nor ACP/TUI surfaces depend on a concrete b
|
|
|
131
172
|
both read it; `/reload` does *not* re-run it, so config changes need a restart. stdio children
|
|
132
173
|
live for the process; a dead child fails calls with an in-band error string (no auto-restart).
|
|
133
174
|
Tools are namespaced `mcp__<server>__<tool>`, appended in the `*_as_specs`/`build_tool_specs`
|
|
134
|
-
layer and routed in `tools::execute_tool` via `mcp::is_mcp_tool`.
|
|
135
|
-
(`<cloud>/mcp`, default `https://sigit.si/api/v1/mcp
|
|
136
|
-
with the cloud session token
|
|
175
|
+
layer and routed in `tools::execute_tool` via `mcp::is_mcp_tool`. Two servers are baked in:
|
|
176
|
+
the official server (`<cloud>/mcp`, default `https://sigit.si/api/v1/mcp`, always HTTP, authed
|
|
177
|
+
with the cloud session token) and the smbCloud CLI server (`smb --mcp`, stdio, added only when
|
|
178
|
+
the `smb` binary is on `PATH`; opt out with `smbcloud = false` in `mcp.toml` or
|
|
179
|
+
`SIGIT_MCP_SMBCLOUD=off`). A user-defined entry named `sigit` or `smbcloud` overrides the
|
|
180
|
+
corresponding baked-in one. Extra servers live in `mcp.toml` (global
|
|
137
181
|
`$SIGIT_CONFIG_DIR/mcp.toml` and project-local `.sigit/mcp.toml`). The stdio path is covered by
|
|
138
182
|
`tests/mcp_stdio.rs`, driven by the test-only `src/bin/mcp_stdio_stub.rs` helper binary
|
|
139
|
-
(excluded from the published crate via `exclude` in `Cargo.toml`).
|
|
183
|
+
(excluded from the published crate via `exclude` in `Cargo.toml`). The baked-in official
|
|
184
|
+
server is *also* listed in the public MCP Registry as `si.sigit/sigit` — a **remote**
|
|
185
|
+
Streamable-HTTP listing (`server.json` at the repo root, published by
|
|
186
|
+
`release-mcp-registry.yml`). Because it's a remote server, the registry's URL-match rule
|
|
187
|
+
forces a domain namespace (`si.sigit` ↔ `sigit.si`) verified by a DNS TXT record, not the
|
|
188
|
+
GitHub-OIDC scheme `smbcloud-cli` uses for its package listing.
|
|
140
189
|
- **`src/permissions.rs`** — tool permission policy. Every tool call passes through
|
|
141
190
|
`decision_for` before executing: read-only tools always run; mutating tools (and all
|
|
142
191
|
`mcp__*`/unknown tools) are governed by, in order: per-session plan mode (`/plan` — deny all
|
|
@@ -165,12 +214,14 @@ feeds results back. Neither the loop nor ACP/TUI surfaces depend on a concrete b
|
|
|
165
214
|
- **`src/credentials.rs`** — local session-token store (TOML, `0600` on Unix).
|
|
166
215
|
- **`src/models.rs`** — model-picker types shared across platforms.
|
|
167
216
|
|
|
168
|
-
Slash commands (`/help`, `/models`, `/skills`, `/
|
|
169
|
-
`/plan`, `/permissions`, `/init`, `/clear`, `/status`) are advertised via
|
|
170
|
-
`main.rs` and handled in both the TUI and ACP sessions. `/init` is
|
|
171
|
-
directly it substitutes `instructions::INIT_PROMPT` for the user
|
|
172
|
-
turn that explores the repo and writes (or improves) `AGENTS.md`
|
|
173
|
-
permission checks.
|
|
217
|
+
Slash commands (`/help`, `/models`, `/skills`, `/agents`, `/commands`, `/mcp`, `/login`, `/logout`,
|
|
218
|
+
`/whoami`, `/reload`, `/plan`, `/permissions`, `/init`, `/clear`, `/status`) are advertised via
|
|
219
|
+
`advertise_commands` in `main.rs` and handled in both the TUI and ACP sessions. `/init` is
|
|
220
|
+
special: instead of replying directly it substitutes `instructions::INIT_PROMPT` for the user
|
|
221
|
+
text and runs a normal agent turn that explores the repo and writes (or improves) `AGENTS.md`
|
|
222
|
+
through the ordinary tools and permission checks. User-defined commands (see `src/commands.rs`)
|
|
223
|
+
get the same treatment via the `SlashCommand::Unknown` fallback path, so anyone can add their own
|
|
224
|
+
`/name` commands without touching the built-in command list.
|
|
174
225
|
|
|
175
226
|
## Model cache (macOS)
|
|
176
227
|
|
|
@@ -190,7 +241,8 @@ verbosity with `RUST_LOG`.
|
|
|
190
241
|
|
|
191
242
|
`OPENAI_BASE_URL` / `OPENAI_API_KEY` (provider override), `SIGIT_API_URL` (account API base,
|
|
192
243
|
default `https://sigit.si`), `SIGIT_CLOUD_URL`, `SIGIT_CONFIG_DIR` (default `~/.config/sigit`),
|
|
193
|
-
`SIGIT_MODEL`, `SIGIT_MCP` (`off` disables MCP), `
|
|
244
|
+
`SIGIT_MODEL`, `SIGIT_MCP` (`off` disables MCP), `SIGIT_MCP_SMBCLOUD` (`off` drops the baked-in
|
|
245
|
+
smbCloud CLI server), `SIGIT_MCP_OFFICIAL` (`off` drops the baked-in
|
|
194
246
|
server), `SIGIT_PERMISSIONS` (`allow`/`ask`/`deny` — overrides the default permission mode for
|
|
195
247
|
mutating tools; the escape hatch for clients without permission-request support),
|
|
196
248
|
`HF_HOME` / `HF_HUB_CACHE`, `RUST_LOG`.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
name: MCP Registry Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
version:
|
|
7
|
+
description: "Override the version in server.json (e.g. 0.2.0); leave blank to publish as-is"
|
|
8
|
+
required: false
|
|
9
|
+
|
|
10
|
+
# A remote server proves namespace ownership through domain (DNS) verification,
|
|
11
|
+
# not GitHub OIDC: the registry checks a v=MCPv1 TXT record on sigit.si against
|
|
12
|
+
# a request signed with the matching Ed25519 private key. See the MCP Registry
|
|
13
|
+
# doc in the sigit-si repo for the one-time key/DNS setup.
|
|
14
|
+
permissions:
|
|
15
|
+
contents: read
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
publish:
|
|
19
|
+
name: Publish server.json to the MCP Registry
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
steps:
|
|
22
|
+
- name: Checkout
|
|
23
|
+
uses: actions/checkout@v6
|
|
24
|
+
|
|
25
|
+
- name: Optionally override the version in server.json
|
|
26
|
+
shell: bash
|
|
27
|
+
run: |
|
|
28
|
+
version="${{ github.event.inputs.version }}"
|
|
29
|
+
if [ -n "${version}" ]; then
|
|
30
|
+
jq --arg v "${version}" '.version = $v' server.json > server.tmp
|
|
31
|
+
mv server.tmp server.json
|
|
32
|
+
fi
|
|
33
|
+
cat server.json
|
|
34
|
+
|
|
35
|
+
- name: Check the remote URL matches the namespace domain
|
|
36
|
+
shell: bash
|
|
37
|
+
run: |
|
|
38
|
+
# The registry rejects a remote server whose URL isn't under the
|
|
39
|
+
# namespace's domain. si.sigit -> sigit.si, so every listed remote
|
|
40
|
+
# must live on sigit.si (or a subdomain).
|
|
41
|
+
server_name="$(jq -r '.name' server.json)"
|
|
42
|
+
domain="$(echo "${server_name%%/*}" | awk -F. '{ for (i=NF; i>=1; i--) printf "%s%s", $i, (i>1 ? "." : "") }')"
|
|
43
|
+
echo "Server: ${server_name} Domain: ${domain}"
|
|
44
|
+
|
|
45
|
+
bad="$(jq -r --arg d "${domain}" '
|
|
46
|
+
.remotes // []
|
|
47
|
+
| map(.url | sub("^[a-z]+://"; "") | sub("/.*$"; ""))
|
|
48
|
+
| map(select(. != $d and (endswith("." + $d) | not)))
|
|
49
|
+
| .[]' server.json)"
|
|
50
|
+
if [ -n "${bad}" ]; then
|
|
51
|
+
echo "Remote URL host(s) not under ${domain}: ${bad}" >&2
|
|
52
|
+
exit 1
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
- name: Install mcp-publisher
|
|
56
|
+
shell: bash
|
|
57
|
+
run: |
|
|
58
|
+
curl -L "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" | tar xz mcp-publisher
|
|
59
|
+
|
|
60
|
+
- name: Authenticate to the MCP Registry
|
|
61
|
+
shell: bash
|
|
62
|
+
env:
|
|
63
|
+
MCP_REGISTRY_DNS_PRIVATE_KEY: ${{ secrets.MCP_REGISTRY_DNS_PRIVATE_KEY }}
|
|
64
|
+
run: |
|
|
65
|
+
if [ -z "${MCP_REGISTRY_DNS_PRIVATE_KEY}" ]; then
|
|
66
|
+
echo "MCP_REGISTRY_DNS_PRIVATE_KEY secret is not set. See the MCP Registry doc in the sigit-si repo." >&2
|
|
67
|
+
exit 1
|
|
68
|
+
fi
|
|
69
|
+
./mcp-publisher login dns --domain=sigit.si --private-key="${MCP_REGISTRY_DNS_PRIVATE_KEY}"
|
|
70
|
+
|
|
71
|
+
- name: Publish
|
|
72
|
+
shell: bash
|
|
73
|
+
run: ./mcp-publisher publish
|
|
74
|
+
|
|
75
|
+
- name: Verify the server is listed
|
|
76
|
+
shell: bash
|
|
77
|
+
run: |
|
|
78
|
+
server_name="$(jq -r '.name' server.json)"
|
|
79
|
+
curl -fsSL "https://registry.modelcontextprotocol.io/v0.1/servers?search=${server_name}" | jq .
|
|
@@ -110,7 +110,23 @@ feeds results back. Neither the loop nor ACP/TUI surfaces depend on a concrete b
|
|
|
110
110
|
spec list (`all_tools`) and the execute `match` (`execute_tool`). `run_command` also enforces
|
|
111
111
|
commit attribution: when a command creates a new commit that lacks the
|
|
112
112
|
`Co-Authored-By: siGit Code` trailer (`COMMIT_CO_AUTHOR_TRAILER`), it amends the trailer in —
|
|
113
|
-
unless the commit already exists on a remote, which is never rewritten.
|
|
113
|
+
unless the commit already exists on a remote, which is never rewritten. Also owns the `task`
|
|
114
|
+
tool: a nested agent loop in a fresh conversation, offered only when `subagent_available()`
|
|
115
|
+
(a subagent factory is registered — see `register_subagent_factory_for` in `main.rs`; on-device
|
|
116
|
+
registers a `None`-returning factory since onde has a single shared history). A subagent's
|
|
117
|
+
toolset is a hard-gated read-only allow-list (`SUBAGENT_TOOL_NAMES`) that is never expanded by a
|
|
118
|
+
configurable subagent type (see `src/subagents.rs`) — only ever narrowed — so a `.sigit/agents/*.md`
|
|
119
|
+
file can't grant itself `edit_file`/`run_command` and bypass the permission system. Also owns
|
|
120
|
+
`web_search`: a thin native wrapper around the official MCP server's Brave-Search-backed
|
|
121
|
+
`web_search` tool (`mcp__sigit__web_search`, implemented server-side in `sigit-si`'s
|
|
122
|
+
`WebSearchService` + `Mcp::Tools::WebSearch`), offered only when that MCP tool was actually
|
|
123
|
+
discovered (i.e. the user is signed in to siGit Code Cloud — see `web_search_available`).
|
|
124
|
+
Wrapping it natively rather than leaving it as a raw `mcp__*` tool matters for two reasons:
|
|
125
|
+
`permissions::classify` treats every `mcp__*` tool as mutating (an "ask" prompt on every call),
|
|
126
|
+
while `web_search` is read-only like `read_website`; and the raw delegate name is filtered out
|
|
127
|
+
of the assembled tool list (`is_web_search_delegate`) so the model sees one clean option, not
|
|
128
|
+
two names for the same tool. Execution still forwards verbatim to `mcp::call_tool` — no second
|
|
129
|
+
HTTP/JSON-RPC implementation.
|
|
114
130
|
- **`src/skills.rs`** — [Agent Skills](https://agentskills.io) support. Discovers skill
|
|
115
131
|
folders (each with a `SKILL.md`: YAML frontmatter `name` + `description`, then Markdown
|
|
116
132
|
instructions) from `.sigit/skills/` and `.claude/skills/` in the cwd, `$SIGIT_CONFIG_DIR/skills/`,
|
|
@@ -119,6 +135,31 @@ feeds results back. Neither the loop nor ACP/TUI surfaces depend on a concrete b
|
|
|
119
135
|
calls `skill` with a name) loads the full `SKILL.md` body. The `skill` tool is appended in the
|
|
120
136
|
`*_as_specs`/`build_tool_specs` layer (not in `all_tools()`) so its description can be dynamic,
|
|
121
137
|
and only when at least one skill exists.
|
|
138
|
+
- **`src/commands.rs`** — user-defined slash commands. Discovers Markdown files (each an
|
|
139
|
+
optional YAML frontmatter block — `description`, `argument-hint` — followed by a prompt-template
|
|
140
|
+
body) from `.sigit/commands/` and `.claude/commands/` in the cwd, `$SIGIT_CONFIG_DIR/commands/`,
|
|
141
|
+
and `~/.claude/commands/`. A subdirectory namespaces the command with `:`
|
|
142
|
+
(`.sigit/commands/git/commit.md` → `/git:commit`). Unlike skills there's no tool-call
|
|
143
|
+
indirection: invoking one works exactly like the built-in `/init` — `commands::render`
|
|
144
|
+
substitutes `$ARGUMENTS`/`$1..$9` in the body against whatever followed the command on the
|
|
145
|
+
input line, and the result is fed to the model as a normal turn through the ordinary tools and
|
|
146
|
+
permission checks. Resolution happens where each surface (`main.rs`/`chat.rs`) already
|
|
147
|
+
special-cases `/init`: an unrecognized slash command is tried against `commands::resolve_command`
|
|
148
|
+
before falling back to "unknown command". A custom command sharing a name with a built-in is
|
|
149
|
+
unreachable (built-ins match first in `parse_slash`) and is skipped when advertised to ACP
|
|
150
|
+
clients, with a warning logged.
|
|
151
|
+
- **`src/subagents.rs`** — configurable subagent types for the `task` tool. Discovers Markdown
|
|
152
|
+
files (YAML frontmatter `name` + `description`, optional comma-separated `tools:` allow-list,
|
|
153
|
+
then a Markdown body that becomes the subagent's system prompt) from `.sigit/agents/` and
|
|
154
|
+
`.claude/agents/` in the cwd, `$SIGIT_CONFIG_DIR/agents/`, and `~/.claude/agents/`. Passing a
|
|
155
|
+
type's `name` as `task`'s `subagent_type` argument swaps in that system prompt and, if `tools:`
|
|
156
|
+
is set, narrows the offered toolset to its *intersection* with `SUBAGENT_TOOL_NAMES` — the
|
|
157
|
+
security-relevant narrowing logic lives in `tools.rs` next to that constant, not here; this
|
|
158
|
+
module only discovers and parses files. `SubagentFactory` (in `tools.rs`) takes the resolved
|
|
159
|
+
system prompt per call rather than baking one in at registration, so a single registered
|
|
160
|
+
factory serves both the default research subagent and every configured type.
|
|
161
|
+
- **`src/frontmatter.rs`** — shared "YAML frontmatter + Markdown body" parsing used by both
|
|
162
|
+
`src/skills.rs` (`SKILL.md`) and `src/commands.rs` (`.sigit/commands/*.md`).
|
|
122
163
|
- **`src/mcp.rs`** — [Model Context Protocol](https://modelcontextprotocol.io) *client*. Two
|
|
123
164
|
transports: **Streamable HTTP** (one JSON-RPC POST endpoint, `url` in `mcp.toml`; replies are
|
|
124
165
|
`application/json` or SSE) and **stdio** (`command` + optional `args`/`[server.env]` in
|
|
@@ -131,12 +172,20 @@ feeds results back. Neither the loop nor ACP/TUI surfaces depend on a concrete b
|
|
|
131
172
|
both read it; `/reload` does *not* re-run it, so config changes need a restart. stdio children
|
|
132
173
|
live for the process; a dead child fails calls with an in-band error string (no auto-restart).
|
|
133
174
|
Tools are namespaced `mcp__<server>__<tool>`, appended in the `*_as_specs`/`build_tool_specs`
|
|
134
|
-
layer and routed in `tools::execute_tool` via `mcp::is_mcp_tool`.
|
|
135
|
-
(`<cloud>/mcp`, default `https://sigit.si/api/v1/mcp
|
|
136
|
-
with the cloud session token
|
|
175
|
+
layer and routed in `tools::execute_tool` via `mcp::is_mcp_tool`. Two servers are baked in:
|
|
176
|
+
the official server (`<cloud>/mcp`, default `https://sigit.si/api/v1/mcp`, always HTTP, authed
|
|
177
|
+
with the cloud session token) and the smbCloud CLI server (`smb --mcp`, stdio, added only when
|
|
178
|
+
the `smb` binary is on `PATH`; opt out with `smbcloud = false` in `mcp.toml` or
|
|
179
|
+
`SIGIT_MCP_SMBCLOUD=off`). A user-defined entry named `sigit` or `smbcloud` overrides the
|
|
180
|
+
corresponding baked-in one. Extra servers live in `mcp.toml` (global
|
|
137
181
|
`$SIGIT_CONFIG_DIR/mcp.toml` and project-local `.sigit/mcp.toml`). The stdio path is covered by
|
|
138
182
|
`tests/mcp_stdio.rs`, driven by the test-only `src/bin/mcp_stdio_stub.rs` helper binary
|
|
139
|
-
(excluded from the published crate via `exclude` in `Cargo.toml`).
|
|
183
|
+
(excluded from the published crate via `exclude` in `Cargo.toml`). The baked-in official
|
|
184
|
+
server is *also* listed in the public MCP Registry as `si.sigit/sigit` — a **remote**
|
|
185
|
+
Streamable-HTTP listing (`server.json` at the repo root, published by
|
|
186
|
+
`release-mcp-registry.yml`). Because it's a remote server, the registry's URL-match rule
|
|
187
|
+
forces a domain namespace (`si.sigit` ↔ `sigit.si`) verified by a DNS TXT record, not the
|
|
188
|
+
GitHub-OIDC scheme `smbcloud-cli` uses for its package listing.
|
|
140
189
|
- **`src/permissions.rs`** — tool permission policy. Every tool call passes through
|
|
141
190
|
`decision_for` before executing: read-only tools always run; mutating tools (and all
|
|
142
191
|
`mcp__*`/unknown tools) are governed by, in order: per-session plan mode (`/plan` — deny all
|
|
@@ -165,12 +214,14 @@ feeds results back. Neither the loop nor ACP/TUI surfaces depend on a concrete b
|
|
|
165
214
|
- **`src/credentials.rs`** — local session-token store (TOML, `0600` on Unix).
|
|
166
215
|
- **`src/models.rs`** — model-picker types shared across platforms.
|
|
167
216
|
|
|
168
|
-
Slash commands (`/help`, `/models`, `/skills`, `/
|
|
169
|
-
`/plan`, `/permissions`, `/init`, `/clear`, `/status`) are advertised via
|
|
170
|
-
`main.rs` and handled in both the TUI and ACP sessions. `/init` is
|
|
171
|
-
directly it substitutes `instructions::INIT_PROMPT` for the user
|
|
172
|
-
turn that explores the repo and writes (or improves) `AGENTS.md`
|
|
173
|
-
permission checks.
|
|
217
|
+
Slash commands (`/help`, `/models`, `/skills`, `/agents`, `/commands`, `/mcp`, `/login`, `/logout`,
|
|
218
|
+
`/whoami`, `/reload`, `/plan`, `/permissions`, `/init`, `/clear`, `/status`) are advertised via
|
|
219
|
+
`advertise_commands` in `main.rs` and handled in both the TUI and ACP sessions. `/init` is
|
|
220
|
+
special: instead of replying directly it substitutes `instructions::INIT_PROMPT` for the user
|
|
221
|
+
text and runs a normal agent turn that explores the repo and writes (or improves) `AGENTS.md`
|
|
222
|
+
through the ordinary tools and permission checks. User-defined commands (see `src/commands.rs`)
|
|
223
|
+
get the same treatment via the `SlashCommand::Unknown` fallback path, so anyone can add their own
|
|
224
|
+
`/name` commands without touching the built-in command list.
|
|
174
225
|
|
|
175
226
|
## Model cache (macOS)
|
|
176
227
|
|
|
@@ -190,7 +241,8 @@ verbosity with `RUST_LOG`.
|
|
|
190
241
|
|
|
191
242
|
`OPENAI_BASE_URL` / `OPENAI_API_KEY` (provider override), `SIGIT_API_URL` (account API base,
|
|
192
243
|
default `https://sigit.si`), `SIGIT_CLOUD_URL`, `SIGIT_CONFIG_DIR` (default `~/.config/sigit`),
|
|
193
|
-
`SIGIT_MODEL`, `SIGIT_MCP` (`off` disables MCP), `
|
|
244
|
+
`SIGIT_MODEL`, `SIGIT_MCP` (`off` disables MCP), `SIGIT_MCP_SMBCLOUD` (`off` drops the baked-in
|
|
245
|
+
smbCloud CLI server), `SIGIT_MCP_OFFICIAL` (`off` drops the baked-in
|
|
194
246
|
server), `SIGIT_PERMISSIONS` (`allow`/`ask`/`deny` — overrides the default permission mode for
|
|
195
247
|
mutating tools; the escape hatch for clients without permission-request support),
|
|
196
248
|
`HF_HOME` / `HF_HUB_CACHE`, `RUST_LOG`.
|
|
@@ -1,5 +1,83 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.5.1
|
|
4
|
+
|
|
5
|
+
Makes siGit Code work as an Xcode custom agent, and updates the Onde SDK.
|
|
6
|
+
|
|
7
|
+
### What changed
|
|
8
|
+
|
|
9
|
+
- Xcode can now run siGit Code as a custom agent. Point it at the binary with
|
|
10
|
+
`--acp` as the argument, and that explicit mode loads the selected on-device
|
|
11
|
+
model on the first prompt, since Xcode's chat has no equivalent of `/load`.
|
|
12
|
+
The README covers the setup, including wiring up `xcrun mcpbridge` in
|
|
13
|
+
`mcp.toml` so the agent can use Xcode's build, test, and project tools
|
|
14
|
+
- MCP calls to the `xcode` server time out after 30 seconds instead of 120, so
|
|
15
|
+
a request Xcode cannot service no longer leaves the prompt looking busy for
|
|
16
|
+
two minutes. String JSON-RPC ids from the bridge are handled too
|
|
17
|
+
- The agent stops repeating itself: a tool call made three times with identical
|
|
18
|
+
arguments now forces a text reply instead of looping
|
|
19
|
+
- Onde SDK bumped to 1.2.2
|
|
20
|
+
- The registry listing in `server.json` matches what sigit.si publishes
|
|
21
|
+
|
|
22
|
+
## 1.5.0
|
|
23
|
+
|
|
24
|
+
Opens the agent up to user extension: lifecycle hooks, custom slash commands,
|
|
25
|
+
and configurable subagent types. Also adds web search, a Repo tab in the TUI,
|
|
26
|
+
and a baked-in smbCloud MCP server.
|
|
27
|
+
|
|
28
|
+
### What changed
|
|
29
|
+
|
|
30
|
+
- Hooks let you run shell commands at three points in the agent's lifecycle:
|
|
31
|
+
`session_start`, `pre_tool_use`, and `post_tool_use`, configured under
|
|
32
|
+
`[hooks]` in `settings.toml`. Commands get context through variable
|
|
33
|
+
substitution (`{cwd}`, `{tool_name}`, `{tool_result_len}`) and run in the
|
|
34
|
+
session working directory. A hook that fails is logged and the session
|
|
35
|
+
continues; a hook that hangs is killed on a timeout, along with its whole
|
|
36
|
+
process group
|
|
37
|
+
- User-defined slash commands: drop a Markdown file in `.sigit/commands/` or
|
|
38
|
+
`.claude/commands/` (or the personal `$SIGIT_CONFIG_DIR/commands/` and
|
|
39
|
+
`~/.claude/commands/`) with optional `description` and `argument-hint`
|
|
40
|
+
frontmatter, and the body becomes a prompt template. `$ARGUMENTS` takes the
|
|
41
|
+
whole argument string and `$1`..`$9` the positional words. A subdirectory
|
|
42
|
+
namespaces the command with `:`, so `.sigit/commands/git/commit.md` becomes
|
|
43
|
+
`/git:commit`. They run as ordinary agent turns through the usual tools and
|
|
44
|
+
permission checks, and are advertised to ACP clients like Zed. `/commands`
|
|
45
|
+
lists what was discovered
|
|
46
|
+
- Configurable subagent types for the `task` tool: a Markdown file in
|
|
47
|
+
`.sigit/agents/` or `.claude/agents/` with `name`, `description`, and an
|
|
48
|
+
optional `tools:` allow-list, whose body becomes that subagent's system
|
|
49
|
+
prompt. Pass its name as `subagent_type` to swap the prompt in. The
|
|
50
|
+
`tools:` list can only narrow the subagent's read-only ceiling, never widen
|
|
51
|
+
it, so a config file cannot grant itself `edit_file` or `run_command` and
|
|
52
|
+
route around the permission system. `/agents` lists the discovered types
|
|
53
|
+
- New `web_search` tool, backed by the Brave-Search-backed search on siGit
|
|
54
|
+
Code Cloud's MCP server. It is offered only when you are signed in, and it
|
|
55
|
+
is classified read-only, so searching never triggers a permission prompt
|
|
56
|
+
- The TUI gains a Repo tab, shown when the session's `origin` remote points at
|
|
57
|
+
the sigit.si host. It lists issues and pull requests fetched through the
|
|
58
|
+
official MCP server: Up and Down select, Enter opens a scrollable detail,
|
|
59
|
+
`i`, `p`, Left and Right switch sections, `r` refreshes. The tab is hidden
|
|
60
|
+
and skipped in the cycle for any other remote
|
|
61
|
+
- The smbCloud CLI's stdio MCP server (`smb --mcp`) is now baked in, so
|
|
62
|
+
smbCloud project and deployment tools work with no `mcp.toml` setup. It is
|
|
63
|
+
added only when the `smb` binary is on `PATH`, its read-only tools (`me`,
|
|
64
|
+
`deployments`, `project_list`, `project_show`) skip permission prompts, and
|
|
65
|
+
you can opt out with `smbcloud = false` in `mcp.toml` or
|
|
66
|
+
`SIGIT_MCP_SMBCLOUD=off`
|
|
67
|
+
- siGit Code Cloud's MCP server is now listed in the public MCP Registry as
|
|
68
|
+
`si.sigit/sigit`, published from `server.json` at the repository root
|
|
69
|
+
|
|
70
|
+
### Fixes
|
|
71
|
+
|
|
72
|
+
- An explicit `deny` rule now applies to read-only first-party tools instead
|
|
73
|
+
of being skipped
|
|
74
|
+
- A subagent type whose `tools:` list resolves to an empty set is rejected
|
|
75
|
+
rather than producing a subagent with no tools
|
|
76
|
+
- Command templates render in a single substitution pass, so an argument that
|
|
77
|
+
contains something like `$1` is no longer re-substituted
|
|
78
|
+
- Frontmatter is stripped with the same leniency it is parsed with
|
|
79
|
+
- The Repo tab's detail view no longer shows stale data after a refresh
|
|
80
|
+
|
|
3
81
|
## 1.4.1
|
|
4
82
|
|
|
5
83
|
Two small fixes: correct co-author attribution and a Homebrew tap fix.
|
|
@@ -110,7 +110,23 @@ feeds results back. Neither the loop nor ACP/TUI surfaces depend on a concrete b
|
|
|
110
110
|
spec list (`all_tools`) and the execute `match` (`execute_tool`). `run_command` also enforces
|
|
111
111
|
commit attribution: when a command creates a new commit that lacks the
|
|
112
112
|
`Co-Authored-By: siGit Code` trailer (`COMMIT_CO_AUTHOR_TRAILER`), it amends the trailer in —
|
|
113
|
-
unless the commit already exists on a remote, which is never rewritten.
|
|
113
|
+
unless the commit already exists on a remote, which is never rewritten. Also owns the `task`
|
|
114
|
+
tool: a nested agent loop in a fresh conversation, offered only when `subagent_available()`
|
|
115
|
+
(a subagent factory is registered — see `register_subagent_factory_for` in `main.rs`; on-device
|
|
116
|
+
registers a `None`-returning factory since onde has a single shared history). A subagent's
|
|
117
|
+
toolset is a hard-gated read-only allow-list (`SUBAGENT_TOOL_NAMES`) that is never expanded by a
|
|
118
|
+
configurable subagent type (see `src/subagents.rs`) — only ever narrowed — so a `.sigit/agents/*.md`
|
|
119
|
+
file can't grant itself `edit_file`/`run_command` and bypass the permission system. Also owns
|
|
120
|
+
`web_search`: a thin native wrapper around the official MCP server's Brave-Search-backed
|
|
121
|
+
`web_search` tool (`mcp__sigit__web_search`, implemented server-side in `sigit-si`'s
|
|
122
|
+
`WebSearchService` + `Mcp::Tools::WebSearch`), offered only when that MCP tool was actually
|
|
123
|
+
discovered (i.e. the user is signed in to siGit Code Cloud — see `web_search_available`).
|
|
124
|
+
Wrapping it natively rather than leaving it as a raw `mcp__*` tool matters for two reasons:
|
|
125
|
+
`permissions::classify` treats every `mcp__*` tool as mutating (an "ask" prompt on every call),
|
|
126
|
+
while `web_search` is read-only like `read_website`; and the raw delegate name is filtered out
|
|
127
|
+
of the assembled tool list (`is_web_search_delegate`) so the model sees one clean option, not
|
|
128
|
+
two names for the same tool. Execution still forwards verbatim to `mcp::call_tool` — no second
|
|
129
|
+
HTTP/JSON-RPC implementation.
|
|
114
130
|
- **`src/skills.rs`** — [Agent Skills](https://agentskills.io) support. Discovers skill
|
|
115
131
|
folders (each with a `SKILL.md`: YAML frontmatter `name` + `description`, then Markdown
|
|
116
132
|
instructions) from `.sigit/skills/` and `.claude/skills/` in the cwd, `$SIGIT_CONFIG_DIR/skills/`,
|
|
@@ -119,6 +135,31 @@ feeds results back. Neither the loop nor ACP/TUI surfaces depend on a concrete b
|
|
|
119
135
|
calls `skill` with a name) loads the full `SKILL.md` body. The `skill` tool is appended in the
|
|
120
136
|
`*_as_specs`/`build_tool_specs` layer (not in `all_tools()`) so its description can be dynamic,
|
|
121
137
|
and only when at least one skill exists.
|
|
138
|
+
- **`src/commands.rs`** — user-defined slash commands. Discovers Markdown files (each an
|
|
139
|
+
optional YAML frontmatter block — `description`, `argument-hint` — followed by a prompt-template
|
|
140
|
+
body) from `.sigit/commands/` and `.claude/commands/` in the cwd, `$SIGIT_CONFIG_DIR/commands/`,
|
|
141
|
+
and `~/.claude/commands/`. A subdirectory namespaces the command with `:`
|
|
142
|
+
(`.sigit/commands/git/commit.md` → `/git:commit`). Unlike skills there's no tool-call
|
|
143
|
+
indirection: invoking one works exactly like the built-in `/init` — `commands::render`
|
|
144
|
+
substitutes `$ARGUMENTS`/`$1..$9` in the body against whatever followed the command on the
|
|
145
|
+
input line, and the result is fed to the model as a normal turn through the ordinary tools and
|
|
146
|
+
permission checks. Resolution happens where each surface (`main.rs`/`chat.rs`) already
|
|
147
|
+
special-cases `/init`: an unrecognized slash command is tried against `commands::resolve_command`
|
|
148
|
+
before falling back to "unknown command". A custom command sharing a name with a built-in is
|
|
149
|
+
unreachable (built-ins match first in `parse_slash`) and is skipped when advertised to ACP
|
|
150
|
+
clients, with a warning logged.
|
|
151
|
+
- **`src/subagents.rs`** — configurable subagent types for the `task` tool. Discovers Markdown
|
|
152
|
+
files (YAML frontmatter `name` + `description`, optional comma-separated `tools:` allow-list,
|
|
153
|
+
then a Markdown body that becomes the subagent's system prompt) from `.sigit/agents/` and
|
|
154
|
+
`.claude/agents/` in the cwd, `$SIGIT_CONFIG_DIR/agents/`, and `~/.claude/agents/`. Passing a
|
|
155
|
+
type's `name` as `task`'s `subagent_type` argument swaps in that system prompt and, if `tools:`
|
|
156
|
+
is set, narrows the offered toolset to its *intersection* with `SUBAGENT_TOOL_NAMES` — the
|
|
157
|
+
security-relevant narrowing logic lives in `tools.rs` next to that constant, not here; this
|
|
158
|
+
module only discovers and parses files. `SubagentFactory` (in `tools.rs`) takes the resolved
|
|
159
|
+
system prompt per call rather than baking one in at registration, so a single registered
|
|
160
|
+
factory serves both the default research subagent and every configured type.
|
|
161
|
+
- **`src/frontmatter.rs`** — shared "YAML frontmatter + Markdown body" parsing used by both
|
|
162
|
+
`src/skills.rs` (`SKILL.md`) and `src/commands.rs` (`.sigit/commands/*.md`).
|
|
122
163
|
- **`src/mcp.rs`** — [Model Context Protocol](https://modelcontextprotocol.io) *client*. Two
|
|
123
164
|
transports: **Streamable HTTP** (one JSON-RPC POST endpoint, `url` in `mcp.toml`; replies are
|
|
124
165
|
`application/json` or SSE) and **stdio** (`command` + optional `args`/`[server.env]` in
|
|
@@ -131,12 +172,20 @@ feeds results back. Neither the loop nor ACP/TUI surfaces depend on a concrete b
|
|
|
131
172
|
both read it; `/reload` does *not* re-run it, so config changes need a restart. stdio children
|
|
132
173
|
live for the process; a dead child fails calls with an in-band error string (no auto-restart).
|
|
133
174
|
Tools are namespaced `mcp__<server>__<tool>`, appended in the `*_as_specs`/`build_tool_specs`
|
|
134
|
-
layer and routed in `tools::execute_tool` via `mcp::is_mcp_tool`.
|
|
135
|
-
(`<cloud>/mcp`, default `https://sigit.si/api/v1/mcp
|
|
136
|
-
with the cloud session token
|
|
175
|
+
layer and routed in `tools::execute_tool` via `mcp::is_mcp_tool`. Two servers are baked in:
|
|
176
|
+
the official server (`<cloud>/mcp`, default `https://sigit.si/api/v1/mcp`, always HTTP, authed
|
|
177
|
+
with the cloud session token) and the smbCloud CLI server (`smb --mcp`, stdio, added only when
|
|
178
|
+
the `smb` binary is on `PATH`; opt out with `smbcloud = false` in `mcp.toml` or
|
|
179
|
+
`SIGIT_MCP_SMBCLOUD=off`). A user-defined entry named `sigit` or `smbcloud` overrides the
|
|
180
|
+
corresponding baked-in one. Extra servers live in `mcp.toml` (global
|
|
137
181
|
`$SIGIT_CONFIG_DIR/mcp.toml` and project-local `.sigit/mcp.toml`). The stdio path is covered by
|
|
138
182
|
`tests/mcp_stdio.rs`, driven by the test-only `src/bin/mcp_stdio_stub.rs` helper binary
|
|
139
|
-
(excluded from the published crate via `exclude` in `Cargo.toml`).
|
|
183
|
+
(excluded from the published crate via `exclude` in `Cargo.toml`). The baked-in official
|
|
184
|
+
server is *also* listed in the public MCP Registry as `si.sigit/sigit` — a **remote**
|
|
185
|
+
Streamable-HTTP listing (`server.json` at the repo root, published by
|
|
186
|
+
`release-mcp-registry.yml`). Because it's a remote server, the registry's URL-match rule
|
|
187
|
+
forces a domain namespace (`si.sigit` ↔ `sigit.si`) verified by a DNS TXT record, not the
|
|
188
|
+
GitHub-OIDC scheme `smbcloud-cli` uses for its package listing.
|
|
140
189
|
- **`src/permissions.rs`** — tool permission policy. Every tool call passes through
|
|
141
190
|
`decision_for` before executing: read-only tools always run; mutating tools (and all
|
|
142
191
|
`mcp__*`/unknown tools) are governed by, in order: per-session plan mode (`/plan` — deny all
|
|
@@ -165,12 +214,14 @@ feeds results back. Neither the loop nor ACP/TUI surfaces depend on a concrete b
|
|
|
165
214
|
- **`src/credentials.rs`** — local session-token store (TOML, `0600` on Unix).
|
|
166
215
|
- **`src/models.rs`** — model-picker types shared across platforms.
|
|
167
216
|
|
|
168
|
-
Slash commands (`/help`, `/models`, `/skills`, `/
|
|
169
|
-
`/plan`, `/permissions`, `/init`, `/clear`, `/status`) are advertised via
|
|
170
|
-
`main.rs` and handled in both the TUI and ACP sessions. `/init` is
|
|
171
|
-
directly it substitutes `instructions::INIT_PROMPT` for the user
|
|
172
|
-
turn that explores the repo and writes (or improves) `AGENTS.md`
|
|
173
|
-
permission checks.
|
|
217
|
+
Slash commands (`/help`, `/models`, `/skills`, `/agents`, `/commands`, `/mcp`, `/login`, `/logout`,
|
|
218
|
+
`/whoami`, `/reload`, `/plan`, `/permissions`, `/init`, `/clear`, `/status`) are advertised via
|
|
219
|
+
`advertise_commands` in `main.rs` and handled in both the TUI and ACP sessions. `/init` is
|
|
220
|
+
special: instead of replying directly it substitutes `instructions::INIT_PROMPT` for the user
|
|
221
|
+
text and runs a normal agent turn that explores the repo and writes (or improves) `AGENTS.md`
|
|
222
|
+
through the ordinary tools and permission checks. User-defined commands (see `src/commands.rs`)
|
|
223
|
+
get the same treatment via the `SlashCommand::Unknown` fallback path, so anyone can add their own
|
|
224
|
+
`/name` commands without touching the built-in command list.
|
|
174
225
|
|
|
175
226
|
## Model cache (macOS)
|
|
176
227
|
|
|
@@ -190,7 +241,8 @@ verbosity with `RUST_LOG`.
|
|
|
190
241
|
|
|
191
242
|
`OPENAI_BASE_URL` / `OPENAI_API_KEY` (provider override), `SIGIT_API_URL` (account API base,
|
|
192
243
|
default `https://sigit.si`), `SIGIT_CLOUD_URL`, `SIGIT_CONFIG_DIR` (default `~/.config/sigit`),
|
|
193
|
-
`SIGIT_MODEL`, `SIGIT_MCP` (`off` disables MCP), `
|
|
244
|
+
`SIGIT_MODEL`, `SIGIT_MCP` (`off` disables MCP), `SIGIT_MCP_SMBCLOUD` (`off` drops the baked-in
|
|
245
|
+
smbCloud CLI server), `SIGIT_MCP_OFFICIAL` (`off` drops the baked-in
|
|
194
246
|
server), `SIGIT_PERMISSIONS` (`allow`/`ask`/`deny` — overrides the default permission mode for
|
|
195
247
|
mutating tools; the escape hatch for clients without permission-request support),
|
|
196
248
|
`HF_HOME` / `HF_HUB_CACHE`, `RUST_LOG`.
|