svamp-cli 0.2.346 → 0.2.356
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/bin/skills/artifact/SKILL.md +19 -5
- package/bin/skills/crew/SKILL.md +42 -11
- package/dist/{acpBackend-BZ1MJhQV.mjs → acpBackend-UaBD4zL3.mjs} +3 -0
- package/dist/{agentCommands-B2Nl7Fof.mjs → agentCommands-D91RcjqQ.mjs} +4 -4
- package/dist/{claudeAuth-iAerdaMr.mjs → claudeAuth-C0wc1GTM.mjs} +45 -1
- package/dist/cli.mjs +78 -69
- package/dist/{commands-D1pZq3d4.mjs → commands-B-yczgz_.mjs} +14 -10
- package/dist/{commands-BOpoVBOM.mjs → commands-BMeDrpSv.mjs} +3 -3
- package/dist/{commands-H4PsTGn8.mjs → commands-BbmypSgx.mjs} +5 -2
- package/dist/{commands-C2aODeVc.mjs → commands-BkdbelFo.mjs} +26 -11
- package/dist/{commands-BB1Kcyt-.mjs → commands-C13-yE2R.mjs} +32 -3
- package/dist/{commands-D69mnkYu.mjs → commands-CoOc4qiw.mjs} +2 -2
- package/dist/{commands-CiRCwjkJ.mjs → commands-sPvRcG3J.mjs} +9 -9
- package/dist/{detectIsolation-CzoDCEnh.mjs → detectIsolation-CrV8IFDv.mjs} +36 -16
- package/dist/{fleet-DM_Q7w69.mjs → fleet-Ca-UjJNL.mjs} +40 -15
- package/dist/{hookSettings-DYMTUgVA.mjs → hookSettings-FFc1pi8j.mjs} +174 -27
- package/dist/index.mjs +8 -8
- package/dist/{loopVerify-B47sSjxe.mjs → loopVerify-DALtTk2V.mjs} +1 -1
- package/dist/{notifyCommands-D-IKIxiq.mjs → notifyCommands-CCUE18Q-.mjs} +1 -1
- package/dist/package-BrsiNutS.mjs +64 -0
- package/dist/{rpc-BB6RF4-F.mjs → rpc-CBkSkzsI.mjs} +8 -8
- package/dist/{rpc-Cf0grcru.mjs → rpc-ccY7xvlo.mjs} +6 -3
- package/dist/{run-ChdsgaSD.mjs → run-DCq3aEiF.mjs} +3 -3
- package/dist/{run-DkjwF-zA.mjs → run-DDmeV9K3.mjs} +190 -59
- package/dist/{scheduler-BY30ZrB9.mjs → scheduler-BkVJ27Ki.mjs} +8 -8
- package/dist/{serveAuth-DbVLRCRR.mjs → serveAuth-4M0vwMyj.mjs} +53 -11
- package/dist/{serveCommands-CUHUiYnZ.mjs → serveCommands-CLhkccJM.mjs} +8 -8
- package/dist/{store-Bn0ByYev.mjs → store-B4E6NzG6.mjs} +10 -1
- package/package.json +2 -2
- package/dist/package-DtuINqf5.mjs +0 -64
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: artifact
|
|
3
|
-
version: 1.3.
|
|
3
|
+
version: 1.3.2
|
|
4
4
|
description: Embed a rendered HTML file or live URL inline in chat via a single self-closing `<artifact src="..." />` tag — the Svamp client renders it as a sandboxed iframe with modes for inline, card, bare, and immersive.
|
|
5
5
|
tags:
|
|
6
6
|
- svamp
|
|
@@ -134,16 +134,30 @@ This means you can iterate freely without polluting the chat with stale renders.
|
|
|
134
134
|
To share with a colleague, run `svamp serve`:
|
|
135
135
|
|
|
136
136
|
```bash
|
|
137
|
-
#
|
|
137
|
+
# DEFAULT is the `link` tier — a capability URL. NO login required:
|
|
138
|
+
# anyone who has the URL can read it. The hostname IS the secret.
|
|
138
139
|
svamp serve dashboard ./outputs
|
|
139
140
|
|
|
140
|
-
#
|
|
141
|
-
svamp serve dashboard ./outputs --
|
|
141
|
+
# Login-gated (only you, via Hypha) — opt IN to this
|
|
142
|
+
svamp serve dashboard ./outputs --access owner
|
|
142
143
|
|
|
143
|
-
# Restrict to specific emails
|
|
144
|
+
# Restrict to specific emails (they log in via Hypha)
|
|
144
145
|
svamp serve dashboard ./outputs --access alice@x.com,bob@y.com
|
|
146
|
+
|
|
147
|
+
# Listed publicly (anyone, no URL secrecy assumed)
|
|
148
|
+
svamp serve dashboard ./outputs --public
|
|
145
149
|
```
|
|
146
150
|
|
|
151
|
+
⚠️ **Do not assume the default is login-gated.** It is not — `svamp serve` prints the tier back to
|
|
152
|
+
you as `link (capability URL — anyone with the URL can view)`. Before serving anything internal,
|
|
153
|
+
either pass `--access owner` or accept that possession of the URL is possession of the content.
|
|
154
|
+
Because the hostname is the secret, there is no way to revoke access to a `link` mount other than
|
|
155
|
+
`--regenerate-url`, which mints a new one; deleting the mount does not un-publish what was already
|
|
156
|
+
fetched.
|
|
157
|
+
|
|
158
|
+
Use the URL exactly as `serve`/`serve list` prints it — never compose it by hand, and never append a
|
|
159
|
+
path to it.
|
|
160
|
+
|
|
147
161
|
Post the resulting URL as a normal markdown link. The svamp client doesn't manage shares — `svamp serve` is the dedicated tool.
|
|
148
162
|
|
|
149
163
|
## Rendering environment
|
package/bin/skills/crew/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: crew
|
|
3
|
-
version: 0.3.
|
|
3
|
+
version: 0.3.4
|
|
4
4
|
description: Coordinate work as a lead delegating features to managed worktree children — spawn a child per feature on its own branch, run it as a loop until done, and pull finished work back to the base branch with merge-and-close. Use when one session should run a project and farm out features instead of piling many sessions on one working tree.
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -13,10 +13,27 @@ the same working tree.
|
|
|
13
13
|
|
|
14
14
|
A **crew** is emergent, not a heavy object: it is just plain sessions linked by
|
|
15
15
|
`parentSessionId` + a `crew.role`. A **feature child** always (a) has the lead as its
|
|
16
|
-
parent
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
parent and (b) lives in its own `.dev/worktree/<n>` on its own branch.
|
|
17
|
+
|
|
18
|
+
> **⚠ Whether the child is GATED depends on how you started it (#1604).**
|
|
19
|
+
>
|
|
20
|
+
> | You ran | Gate |
|
|
21
|
+
> |---|---|
|
|
22
|
+
> | `crew start "<brief>"` (no `--oracle`) | **none** — the child works, then runs `feature done` when *it* decides it is complete. Nothing judges it. |
|
|
23
|
+
> | `crew start "<brief>" --oracle "<cmd>"` | a loop with `parent: <lead>` — the oracle gates each stop and **the lead is the judge** of done. |
|
|
24
|
+
>
|
|
25
|
+
> The CLI tells you which you got: it prints `gate: none — child runs 'feature done' when complete`
|
|
26
|
+
> on the ungated path. This is deliberate, not an oversight — `featureStart` attaches the loop only
|
|
27
|
+
> when there is an oracle, because a no-oracle child would otherwise fire `approved` on its very
|
|
28
|
+
> first stop, which is worse than no gate at all.
|
|
29
|
+
>
|
|
30
|
+
> **What this means for you as a lead:** if the feature has any objective success condition, pass
|
|
31
|
+
> `--oracle`. Without one you are the only thing standing between a child and a premature
|
|
32
|
+
> `feature done`, so read the merge request rather than trusting the verdict.
|
|
33
|
+
>
|
|
34
|
+
> This block used to claim every feature child runs as a loop with the lead as judge. It did not,
|
|
35
|
+
> and an agent that believed it would skip `--oracle`, skip checking on the child, and read "no
|
|
36
|
+
> verdict yet" as "still working" rather than "nothing will ever judge this".
|
|
20
37
|
|
|
21
38
|
## The verbs (these are your tools)
|
|
22
39
|
|
|
@@ -29,10 +46,17 @@ svamp feature start "<brief>" [--oracle "<test cmd>"] [--base <branch>] [--actio
|
|
|
29
46
|
# nudge (default) = normal urgency, the lead sees it on its next idle turn;
|
|
30
47
|
# block = urgent, which WAKES the lead. Use block for a child whose result
|
|
31
48
|
# gates your next step; nudge for one you will collect when convenient.
|
|
32
|
-
# --issue <id> links the child to an
|
|
33
|
-
# ONTO that issue. This is the seam that joins crew
|
|
34
|
-
# oracle (`svamp issue pending`) reads
|
|
35
|
-
#
|
|
49
|
+
# --issue <id> links the child to an EXISTING backlog issue: its verdict routes
|
|
50
|
+
# ONTO that issue instead of onto a new one. This is the seam that joins crew
|
|
51
|
+
# to the backlog the loop oracle (`svamp issue pending`) reads.
|
|
52
|
+
# Pass it whenever the feature came from an issue, so the verdict lands on the
|
|
53
|
+
# item you are already tracking rather than creating a second one to reconcile.
|
|
54
|
+
# NOT passing it does NOT make the child invisible: `crew start` auto-creates a
|
|
55
|
+
# tracking issue at status `in_progress`, and `isPendingIssue` counts anything
|
|
56
|
+
# that is neither `archived` nor `paused` — so an unlinked child still holds the
|
|
57
|
+
# loop oracle RED until its issue is resolved. Do not treat an unlinked child as
|
|
58
|
+
# fire-and-forget; a lead waiting for `svamp issue pending` to empty will wait
|
|
59
|
+
# for it.
|
|
36
60
|
# --max N bounds the child's loop iterations (a hard stop, unlike the soft
|
|
37
61
|
# progress-based cap); --model <id> picks the child's model.
|
|
38
62
|
svamp feature start "<brief>" --no-worktree --dir <folder>
|
|
@@ -81,8 +105,15 @@ You coordinate the project. Keep your own working tree (the base branch, e.g. `m
|
|
|
81
105
|
|
|
82
106
|
## If you are a FEATURE CHILD
|
|
83
107
|
|
|
84
|
-
You own one feature in an isolated worktree on your own branch, reporting to your lead.
|
|
85
|
-
|
|
108
|
+
You own one feature in an isolated worktree on your own branch, reporting to your lead.
|
|
109
|
+
|
|
110
|
+
**Your brief arrives ONCE, as the first message of this session — it is not repeated (#1607).**
|
|
111
|
+
Nothing re-injects it, so keeping it in view is your job: re-read it before you decide you are done,
|
|
112
|
+
and restate it in your own words in `feature report` notes so drift is visible to your lead. (If your
|
|
113
|
+
lead started you *with* `--oracle`, the native `/goal` gate does restate the "until" criteria at each
|
|
114
|
+
turn-end — but on the default no-oracle path there is no loop at all. See the gate table above.)
|
|
115
|
+
This line previously promised per-turn injection of both; no such mechanism was ever built, and
|
|
116
|
+
`docs/crew-design.md` §7 already recorded those hooks as never shipped.
|
|
86
117
|
|
|
87
118
|
- **Work in your worktree.** Implement the feature. Commit as you go. Keep the oracle/tests green.
|
|
88
119
|
- **Report.** Use `svamp feature report "<note>"` for milestones and `--blocker` when stuck —
|
|
@@ -558,6 +558,9 @@ class AcpBackend {
|
|
|
558
558
|
return { outcome: { outcome: "selected", optionId: "cancel" } };
|
|
559
559
|
}
|
|
560
560
|
}
|
|
561
|
+
if (!this.options.permissionHandler) {
|
|
562
|
+
return { outcome: { outcome: "cancelled" } };
|
|
563
|
+
}
|
|
561
564
|
const proceedOnceOption = options.find(
|
|
562
565
|
(opt) => opt.optionId === "proceed_once" || typeof opt.name === "string" && opt.name.toLowerCase().includes("once")
|
|
563
566
|
);
|
|
@@ -79,7 +79,7 @@ async function sessionSetTitle(title) {
|
|
|
79
79
|
}
|
|
80
80
|
async function sessionSetProjectDescription(description) {
|
|
81
81
|
const dir = process.cwd();
|
|
82
|
-
const { projectName, writeProjectInfo, sanitizeDescription, projectInfoPath } = await import('./run-
|
|
82
|
+
const { projectName, writeProjectInfo, sanitizeDescription, projectInfoPath } = await import('./run-DDmeV9K3.mjs').then(function (n) { return n.p; });
|
|
83
83
|
const desc = sanitizeDescription(description, 240);
|
|
84
84
|
if (!desc) {
|
|
85
85
|
console.error("Project description is empty.");
|
|
@@ -382,7 +382,7 @@ async function sessionBroadcast(action, args) {
|
|
|
382
382
|
console.log(`Broadcast sent: ${action}`);
|
|
383
383
|
}
|
|
384
384
|
async function connectToMachineService() {
|
|
385
|
-
const { connectAndGetMachine } = await import('./commands-
|
|
385
|
+
const { connectAndGetMachine } = await import('./commands-B-yczgz_.mjs');
|
|
386
386
|
return connectAndGetMachine();
|
|
387
387
|
}
|
|
388
388
|
function buildInboxMessage(args) {
|
|
@@ -465,7 +465,7 @@ async function inboxSend(targetSessionId, opts) {
|
|
|
465
465
|
console.error("Message body is required.");
|
|
466
466
|
process.exit(1);
|
|
467
467
|
}
|
|
468
|
-
const { connectAndResolveSession } = await import('./commands-
|
|
468
|
+
const { connectAndResolveSession } = await import('./commands-B-yczgz_.mjs');
|
|
469
469
|
let server;
|
|
470
470
|
try {
|
|
471
471
|
const { targetId, messageId } = await inboxSendCore(
|
|
@@ -520,7 +520,7 @@ async function inboxReply(messageId, body, opts) {
|
|
|
520
520
|
console.error("SVAMP_SESSION_ID not set. This command must be run inside a Svamp session.");
|
|
521
521
|
process.exit(1);
|
|
522
522
|
}
|
|
523
|
-
const { connectAndResolveSession } = await import('./commands-
|
|
523
|
+
const { connectAndResolveSession } = await import('./commands-B-yczgz_.mjs');
|
|
524
524
|
const { server: localServer, machine: localMachine } = await connectToMachineService();
|
|
525
525
|
let localDisconnected = false;
|
|
526
526
|
const disconnectLocal = async () => {
|
|
@@ -182,8 +182,52 @@ function applyPromptCacheTtl(spawnEnv) {
|
|
|
182
182
|
if (explicit1h === void 0) spawnEnv.ENABLE_PROMPT_CACHING_1H = "1";
|
|
183
183
|
}
|
|
184
184
|
const BETA_1M_TOKEN = "context-1m-2025-08-07";
|
|
185
|
+
let longContext1MEntitlement = "unknown";
|
|
186
|
+
function setLongContext1MEntitlement(state) {
|
|
187
|
+
longContext1MEntitlement = state;
|
|
188
|
+
}
|
|
189
|
+
function getLongContext1MEntitlement() {
|
|
190
|
+
return longContext1MEntitlement;
|
|
191
|
+
}
|
|
192
|
+
function isLongContextBetaUnavailableError(err) {
|
|
193
|
+
const text = typeof err === "string" ? err : err?.message ?? String(err ?? "");
|
|
194
|
+
return /long context beta is not (yet )?available/i.test(text);
|
|
195
|
+
}
|
|
196
|
+
const LONG_CONTEXT_ENTITLEMENT_RECHECK_MS = Number(process.env.SVAMP_1M_ENTITLEMENT_RECHECK_MS || 60 * 60 * 1e3);
|
|
197
|
+
async function probeLongContext1MEntitlement(baseUrl, apiKey, fetchImpl = fetch) {
|
|
198
|
+
if (!baseUrl || !apiKey) return longContext1MEntitlement;
|
|
199
|
+
try {
|
|
200
|
+
const resp = await fetchImpl(`${baseUrl.replace(/\/$/, "")}/v1/messages`, {
|
|
201
|
+
method: "POST",
|
|
202
|
+
headers: {
|
|
203
|
+
"content-type": "application/json",
|
|
204
|
+
authorization: `Bearer ${apiKey}`,
|
|
205
|
+
"anthropic-beta": BETA_1M_TOKEN
|
|
206
|
+
},
|
|
207
|
+
body: JSON.stringify({
|
|
208
|
+
model: "claude-haiku-4-5-20251001",
|
|
209
|
+
max_tokens: 1,
|
|
210
|
+
messages: [{ role: "user", content: "x" }]
|
|
211
|
+
}),
|
|
212
|
+
signal: AbortSignal.timeout(2e4)
|
|
213
|
+
});
|
|
214
|
+
if (resp.ok) {
|
|
215
|
+
setLongContext1MEntitlement("entitled");
|
|
216
|
+
return "entitled";
|
|
217
|
+
}
|
|
218
|
+
const text = await resp.text().catch(() => "");
|
|
219
|
+
if (isLongContextBetaUnavailableError(text)) {
|
|
220
|
+
setLongContext1MEntitlement("not-entitled");
|
|
221
|
+
return "not-entitled";
|
|
222
|
+
}
|
|
223
|
+
return longContext1MEntitlement;
|
|
224
|
+
} catch {
|
|
225
|
+
return longContext1MEntitlement;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
185
228
|
function applyLongContext1M(spawnEnv) {
|
|
186
229
|
if (envFlagEnabled(spawnEnv.CLAUDE_CODE_DISABLE_1M_CONTEXT) || envFlagEnabled(process.env.CLAUDE_CODE_DISABLE_1M_CONTEXT)) return;
|
|
230
|
+
if (longContext1MEntitlement !== "entitled") return;
|
|
187
231
|
const existing = spawnEnv.ANTHROPIC_BETAS ?? process.env.ANTHROPIC_BETAS ?? "";
|
|
188
232
|
const betas = existing.split(",").map((b) => b.trim()).filter(Boolean);
|
|
189
233
|
if (!betas.includes(BETA_1M_TOKEN)) betas.push(BETA_1M_TOKEN);
|
|
@@ -244,4 +288,4 @@ function applyClaudeProxyEnv(spawnEnv) {
|
|
|
244
288
|
}
|
|
245
289
|
const MANAGED_ENV_KEYS = Array.from(MANAGED_KEYS);
|
|
246
290
|
|
|
247
|
-
export { BETA_1M_TOKEN, EXAMPLE_HYPHA_PROXY_URL, MANAGED_ENV_KEYS, applyClaudeProxyEnv, getClaudeAuthStatus, normalizeProxyUrl, resolveHyphaProxyUrl, setClaudeAuthCustom, setClaudeAuthHyphaProxy, setClaudeAuthLogin, updateEnvFile };
|
|
291
|
+
export { BETA_1M_TOKEN, EXAMPLE_HYPHA_PROXY_URL, LONG_CONTEXT_ENTITLEMENT_RECHECK_MS, MANAGED_ENV_KEYS, applyClaudeProxyEnv, getClaudeAuthStatus, getLongContext1MEntitlement, isLongContextBetaUnavailableError, normalizeProxyUrl, probeLongContext1MEntitlement, resolveHyphaProxyUrl, setClaudeAuthCustom, setClaudeAuthHyphaProxy, setClaudeAuthLogin, setLongContext1MEntitlement, updateEnvFile };
|