svamp-cli 0.2.204 → 0.2.206
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/loop/bin/stop-gate.mjs +84 -3
- package/bin/skills/loop/test/test-loop-gate.mjs +65 -12
- package/dist/{agentCommands-D92DfTGP.mjs → agentCommands-akIoZemu.mjs} +5 -5
- package/dist/{auth-BvO7QtaP.mjs → auth-Dzf0cndq.mjs} +1 -1
- package/dist/cli.mjs +63 -61
- package/dist/{commands-CHqMRENk.mjs → commands-8Rd6p4B4.mjs} +1 -1
- package/dist/{commands-wtMi-xJY.mjs → commands-BPhgtKi2.mjs} +2 -2
- package/dist/{commands-u68ODpBt.mjs → commands-BRmWVCNf.mjs} +34 -11
- package/dist/{commands-BduSUevP.mjs → commands-BfakuMvA.mjs} +2 -2
- package/dist/{commands-5AerKSMm.mjs → commands-Dp7BFqYl.mjs} +1 -1
- package/dist/{commands-DwWuWW99.mjs → commands-OMKB5-oS.mjs} +29 -11
- package/dist/{commands-Dyy_1c0I.mjs → commands-V6wL2BtU.mjs} +5 -5
- package/dist/{fleet-CFe5Kt6k.mjs → fleet-Ci190s0w.mjs} +1 -1
- package/dist/{frpc-DMV0fZBM.mjs → frpc-H52IJYcb.mjs} +1 -1
- package/dist/{headlessCli-COLHIWk8.mjs → headlessCli-tLrOER4U.mjs} +2 -2
- package/dist/index.mjs +1 -1
- package/dist/{package-CqGr9_jQ.mjs → package-MNPXOWOP.mjs} +1 -1
- package/dist/{rpc-CoNLjY5x.mjs → rpc-BHUHF_Mv.mjs} +10 -3
- package/dist/{rpc-DBpyHJUs.mjs → rpc-CFrVMETs.mjs} +1 -1
- package/dist/{run-CR8y6yQ7.mjs → run-C4OsABqC.mjs} +1 -1
- package/dist/{run-BfgkuBEg.mjs → run-C9ZeF2iG.mjs} +101 -18
- package/dist/{scheduler-C1_HeBdn.mjs → scheduler-ErjEISCv.mjs} +1 -1
- package/dist/{serveCommands-d3t4RkrF.mjs → serveCommands-feGogIWC.mjs} +5 -5
- package/dist/{serveManager-DA9elK4m.mjs → serveManager-Be-R7R8_.mjs} +2 -2
- package/dist/{sideband-DNLuglX3.mjs → sideband-cU4KDceu.mjs} +1 -1
- package/package.json +1 -1
|
@@ -155,17 +155,70 @@ if (done) {
|
|
|
155
155
|
const inboxBlocks = Number(state.inbox_blocks) || 0;
|
|
156
156
|
if (cfg.inbox_guard !== false && inboxBlocks < INBOX_BLOCK_CAP) {
|
|
157
157
|
let pending = 0;
|
|
158
|
+
let pendingIds = [];
|
|
158
159
|
try {
|
|
159
160
|
const arr = readJSON(join(LOOP_DIR, '..', 'inbox.json'), []);
|
|
160
161
|
const msgs = Array.isArray(arr) ? arr : (Array.isArray(arr?.messages) ? arr.messages : []);
|
|
161
|
-
|
|
162
|
+
const pendingMsgs = msgs.filter((m) => m && !m.handled && !m.read);
|
|
163
|
+
pending = pendingMsgs.length;
|
|
164
|
+
pendingIds = pendingMsgs.map((m) => m.messageId).filter(Boolean);
|
|
162
165
|
} catch { pending = 0; } // fail-open: no/corrupt inbox file → never block
|
|
163
166
|
if (pending > 0) {
|
|
167
|
+
// #0146: this guard already surfaced these messages — record them in the shared hint ledger so
|
|
168
|
+
// the non-urgent settle hint below won't re-surface the same ids on the next iteration.
|
|
169
|
+
try {
|
|
170
|
+
const HINTED = join(LOOP_DIR, 'hinted-inbox.json');
|
|
171
|
+
const hintedRaw = readJSON(HINTED, []);
|
|
172
|
+
const merged = new Set([...(Array.isArray(hintedRaw) ? hintedRaw : []), ...pendingIds]);
|
|
173
|
+
writeJSONAtomic(HINTED, [...merged]);
|
|
174
|
+
} catch {}
|
|
164
175
|
writeJSONAtomic(STATE, { ...state, inbox_blocks: inboxBlocks + 1, last_oracle: oracleDetail });
|
|
165
176
|
appendHistory({ ts: now, iteration: iterNum, decision: 'inbox-block', pending, detail: oracleDetail });
|
|
166
177
|
block(`The loop's exit conditions are met (oracle empty + evaluator done), but you have ${pending} UNHANDLED inbox message(s). Handle them first — read/reply/triage/merge each (\`svamp session inbox list\`), then finish your turn. (This guard fires at most once per loop, then allows stop, so a flood can't trap the loop.)`);
|
|
167
178
|
}
|
|
168
179
|
}
|
|
180
|
+
// #0146: NON-URGENT inbox hint at the settle point. We only reach here when the gate would
|
|
181
|
+
// OTHERWISE ALLOW the end (oracle pass + evaluator done) AND the urgent/unhandled guard above did
|
|
182
|
+
// not block. Surface UNREAD, NON-URGENT, NOT-awaiting-reply inbox messages the agent hasn't been
|
|
183
|
+
// hinted about yet so they don't pile up unseen while the loop grinds. Reads the same durable
|
|
184
|
+
// inbox.json (sibling of the loop dir) — no subprocess/daemon round-trip. Hint-once-per-message:
|
|
185
|
+
// we record the hinted ids in <LOOP_DIR>/hinted-inbox.json and BLOCK ONCE so the agent sees the
|
|
186
|
+
// hint this turn; the next settle won't re-hint the same ids → it allows the end (non-blocking
|
|
187
|
+
// thereafter). Fully defensive: any error → fall through to the normal allow (never trap the loop).
|
|
188
|
+
// Disable with `inbox_hint: false` in loop.config.json.
|
|
189
|
+
if (cfg.inbox_hint !== false) {
|
|
190
|
+
try {
|
|
191
|
+
const HINTED = join(LOOP_DIR, 'hinted-inbox.json');
|
|
192
|
+
const arr = readJSON(join(LOOP_DIR, '..', 'inbox.json'), []);
|
|
193
|
+
const msgs = Array.isArray(arr) ? arr : (Array.isArray(arr?.messages) ? arr.messages : []);
|
|
194
|
+
const hintedRaw = readJSON(HINTED, []);
|
|
195
|
+
const hintedIds = new Set(Array.isArray(hintedRaw) ? hintedRaw : []);
|
|
196
|
+
// unread + not-handled-by-agent + NOT urgent + NOT awaiting-reply (those already interrupt the
|
|
197
|
+
// loop) + not yet hinted. `handled` means the agent already consumed the message into a turn, so
|
|
198
|
+
// it's not "unseen" — only genuinely-unseen non-urgent mail deserves a settle-point nudge.
|
|
199
|
+
const fresh = msgs.filter((m) => m
|
|
200
|
+
&& m.read !== true
|
|
201
|
+
&& m.handled !== true
|
|
202
|
+
&& m.urgency !== 'urgent'
|
|
203
|
+
&& !(m.channelId && m.correlationId) // awaiting-reply markers
|
|
204
|
+
&& m.messageId && !hintedIds.has(m.messageId));
|
|
205
|
+
if (fresh.length > 0) {
|
|
206
|
+
const preview = fresh.slice(0, 3).map((m) => {
|
|
207
|
+
const who = m.from || m.fromSession || 'unknown';
|
|
208
|
+
const subj = m.subject ? ` re "${m.subject}"` : '';
|
|
209
|
+
return `from ${who}${subj}`;
|
|
210
|
+
}).join('; ');
|
|
211
|
+
const more = fresh.length > 3 ? ` (+${fresh.length - 3} more)` : '';
|
|
212
|
+
// Record BEFORE blocking so the next settle won't re-hint these ids (hint-once guarantee).
|
|
213
|
+
for (const m of fresh) hintedIds.add(m.messageId);
|
|
214
|
+
try { writeJSONAtomic(HINTED, [...hintedIds]); } catch {}
|
|
215
|
+
process.stderr.write(`[loop] 📥 ${fresh.length} unread inbox message(s) while you worked: ${preview}${more}\n`);
|
|
216
|
+
writeJSONAtomic(STATE, { ...state, last_oracle: oracleDetail });
|
|
217
|
+
appendHistory({ ts: now, iteration: iterNum, decision: 'inbox-hint', count: fresh.length, detail: preview });
|
|
218
|
+
block(`📥 ${fresh.length} unread inbox message(s) arrived while you worked: ${preview}${more}. Consider reading them (\`svamp session inbox list\`) before settling. (This hint fires once per message — finish your turn again to be re-checked; it won't block on these again.)`);
|
|
219
|
+
}
|
|
220
|
+
} catch { /* fail-open: any inbox-hint error → never block, fall through to allow */ }
|
|
221
|
+
}
|
|
169
222
|
// #0128: NON-BLOCKING open-crew hint. The loop is about to STOP — surface any active crew children
|
|
170
223
|
// the lead hasn't merged/closed so an orphaned/forgotten crew is visible at the natural checkpoint.
|
|
171
224
|
// Purely informational: it NEVER blocks or affects the decision (the loop still stops). Computed
|
|
@@ -203,14 +256,42 @@ const giveUp = overIters || overTime || overTokens;
|
|
|
203
256
|
const tokenField = maxTokens ? { tokens_used: tokensUsed } : {};
|
|
204
257
|
|
|
205
258
|
if (giveUp) {
|
|
206
|
-
// Bounded out: let it stop so we never block forever. (Single state write.)
|
|
207
259
|
const why = overTokens ? `token budget (${tokensUsed}/${maxTokens} tokens)`
|
|
208
260
|
: overTime ? `runtime budget (${cfg.budget.max_runtime_sec}s)`
|
|
209
261
|
: `max_iterations (${max})`;
|
|
262
|
+
const limitName = overTokens ? 'token budget' : overTime ? 'runtime budget' : 'iteration limit';
|
|
263
|
+
// #0156: reaching the cap here means the exit conditions are NOT met (the `done` path above
|
|
264
|
+
// already handled the met case) — i.e. work is STILL REMAINING. Going silently dormant
|
|
265
|
+
// (active:false) makes a STALL indistinguishable from 'completed' (idle-pike's 11h-dormant bug).
|
|
266
|
+
// So block ONCE to make the agent surface the stall LOUDLY + offer extend/resume <options>;
|
|
267
|
+
// then on the next stop allow it (a stall must never trap the loop forever).
|
|
268
|
+
if (!state.stall_hinted) {
|
|
269
|
+
writeJSONAtomic(STATE, { ...state, iteration: nextIter, stall_hinted: true,
|
|
270
|
+
last_iteration_at: now, last_oracle: oracleDetail, ...tokenField });
|
|
271
|
+
appendHistory({ ts: now, iteration: nextIter, decision: 'stall_hint', reason: why, oracle: oraclePass, detail: oracleDetail });
|
|
272
|
+
const suggested = (overIters && max != null) ? Math.max(max * 2, nextIter + 10) : null;
|
|
273
|
+
const sess = SID || '<session>';
|
|
274
|
+
const resumeCmd = suggested != null
|
|
275
|
+
? `svamp session loop ${sess} --max ${suggested}`
|
|
276
|
+
: `svamp session loop ${sess} --budget <bigger>`;
|
|
277
|
+
const firstLine = String(oracleDetail || 'oracle still failing').split('\n')[0];
|
|
278
|
+
block(
|
|
279
|
+
`⚠️ LOOP STALLED — hit the ${limitName} (${why}) but the exit conditions are NOT met: ${firstLine}. `
|
|
280
|
+
+ `Work is still remaining; do NOT keep grinding, and do NOT just stop silently. In ONE final message:\n`
|
|
281
|
+
+ `1) Tell the user the loop hit its ${limitName} with work still pending, and briefly why it didn't finish.\n`
|
|
282
|
+
+ `2) Present clickable options so they can extend+resume or stop — exactly like:\n`
|
|
283
|
+
+ `<options>\n`
|
|
284
|
+
+ ` <option>Extend the limit${suggested != null ? ` to ${suggested}` : ''} and resume the loop</option>\n`
|
|
285
|
+
+ ` <option>Stop the loop here</option>\n`
|
|
286
|
+
+ `</options>\n`
|
|
287
|
+
+ `If the user picks an extend option, run: ${resumeCmd} (this reactivates + extends the loop). Then end your turn.`,
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
// Already surfaced the stall once → allow stop so it can never trap the loop.
|
|
210
291
|
writeJSONAtomic(STATE, { ...state, active: false, phase: 'gave_up', iteration: nextIter,
|
|
211
292
|
completed_at: now, last_oracle: oracleDetail, gave_up_reason: why, ...tokenField });
|
|
212
293
|
appendHistory({ ts: now, iteration: nextIter, decision: 'gave_up', reason: why, oracle: oraclePass, detail: oracleDetail });
|
|
213
|
-
process.stderr.write(`[loop] reached ${why}; allowing stop.\n`);
|
|
294
|
+
process.stderr.write(`[loop] reached ${why}; allowing stop after stall hint.\n`);
|
|
214
295
|
allow();
|
|
215
296
|
}
|
|
216
297
|
|
|
@@ -113,13 +113,21 @@ try {
|
|
|
113
113
|
ok(!r.blocked, 'gate allows when evaluator off and oracle passes');
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
-
// ---- Test 7: max_iterations bound ->
|
|
117
|
-
console.log('Test 7: max_iterations
|
|
116
|
+
// ---- Test 7: max_iterations bound -> STALL hint once, then allows (never infinite) ----
|
|
117
|
+
console.log('Test 7: max_iterations → stall hint once, then allows');
|
|
118
118
|
{ const d = newProject({ evaluator: 'off', max: 1 }); dirs.push(d); // oracle keeps failing (answer.txt=TODO)
|
|
119
|
-
const r1 = runGate(d); // iteration -> 1, block
|
|
120
|
-
const r2 = runGate(d, true); // iteration -> 2 > max ->
|
|
119
|
+
const r1 = runGate(d); // iteration -> 1, block (oracle fails)
|
|
120
|
+
const r2 = runGate(d, true); // iteration -> 2 > max -> #0156 STALL: block ONCE with options
|
|
121
|
+
const r3 = runGate(d, true); // already hinted -> give up, allow
|
|
121
122
|
ok(r1.blocked, 'first failing attempt blocks');
|
|
122
|
-
|
|
123
|
+
// #0156: exceeding the cap with the oracle still failing is a STALL — surface it loudly ONCE
|
|
124
|
+
// (don't go silently dormant), presenting extend/resume <options>.
|
|
125
|
+
ok(r2.blocked, '#0156: exceeding max_iterations blocks ONCE with a stall hint (not silent)');
|
|
126
|
+
ok(/STALL/i.test(r2.reason) && /<options>/.test(r2.reason), '#0156: stall hint explains + presents <options>');
|
|
127
|
+
ok(/loop .* --max/.test(r2.reason), '#0156: stall hint gives the resume+extend command');
|
|
128
|
+
ok(readState(d).stall_hinted === true, '#0156: state records stall_hinted after the hint');
|
|
129
|
+
ok(!r3.blocked, 'after the stall hint the gate allows stop (no infinite loop)');
|
|
130
|
+
ok(readState(d).phase === 'gave_up' && readState(d).active === false, 'finally marked gave_up/inactive');
|
|
123
131
|
}
|
|
124
132
|
|
|
125
133
|
// ---- Test 8: inactive loop -> no-op allow ----
|
|
@@ -152,8 +160,10 @@ try {
|
|
|
152
160
|
const cfg = JSON.parse(readFileSync(cfgP, 'utf8')); cfg.budget = { max_runtime_sec: 1 }; writeFileSync(cfgP, JSON.stringify(cfg));
|
|
153
161
|
const spP = join(d, '.svamp', SID, 'loop', 'loop-state.json');
|
|
154
162
|
const sp = JSON.parse(readFileSync(spP, 'utf8')); sp.started_at = new Date(Date.now() - 5000).toISOString(); writeFileSync(spP, JSON.stringify(sp));
|
|
155
|
-
const r = runGate(d);
|
|
156
|
-
|
|
163
|
+
const r = runGate(d); // #0156: first over-budget hit → stall hint (block once)
|
|
164
|
+
const r2 = runGate(d); // already hinted → allow
|
|
165
|
+
ok(r.blocked && /STALL/i.test(r.reason), 'runtime over-budget surfaces a stall hint first (not silent)');
|
|
166
|
+
ok(!r2.blocked, 'gate allows stop once runtime budget is exceeded (after the stall hint)');
|
|
157
167
|
ok(readState(d).gave_up_reason?.includes('runtime'), 'state records runtime give-up reason');
|
|
158
168
|
}
|
|
159
169
|
|
|
@@ -180,8 +190,10 @@ try {
|
|
|
180
190
|
JSON.stringify({ message: { usage: { input_tokens: 400, output_tokens: 300 } } }),
|
|
181
191
|
JSON.stringify({ message: { usage: { input_tokens: 500, output_tokens: 200, cache_read_input_tokens: 50 } } }),
|
|
182
192
|
].join('\n')); // total = 1450 > 1000
|
|
183
|
-
const r = runGate(d, false, tp);
|
|
184
|
-
|
|
193
|
+
const r = runGate(d, false, tp); // #0156: first over-budget hit → stall hint
|
|
194
|
+
const r2 = runGate(d, false, tp); // already hinted → allow
|
|
195
|
+
ok(r.blocked && /STALL/i.test(r.reason), 'token over-budget surfaces a stall hint first (not silent)');
|
|
196
|
+
ok(!r2.blocked, 'gate allows stop once token budget is exceeded (after the stall hint)');
|
|
185
197
|
ok(readState(d).gave_up_reason?.includes('token'), 'state records token give-up reason');
|
|
186
198
|
ok(readState(d).tokens_used === 1450, 'tokens summed from transcript');
|
|
187
199
|
}
|
|
@@ -193,8 +205,10 @@ try {
|
|
|
193
205
|
const cfg = JSON.parse(readFileSync(cfgP, 'utf8')); cfg.max_iterations = null; writeFileSync(cfgP, JSON.stringify(cfg));
|
|
194
206
|
const spP = join(d, '.svamp', SID, 'loop', 'loop-state.json');
|
|
195
207
|
const sp = JSON.parse(readFileSync(spP, 'utf8')); sp.iteration = 200; writeFileSync(spP, JSON.stringify(sp)); // at the hard ceiling
|
|
196
|
-
const r = runGate(d);
|
|
197
|
-
|
|
208
|
+
const r = runGate(d); // #0156: stall hint first
|
|
209
|
+
const r2 = runGate(d); // then allow
|
|
210
|
+
ok(r.blocked && /STALL/i.test(r.reason), 'hard-ceiling hit surfaces a stall hint first');
|
|
211
|
+
ok(!r2.blocked, 'gate allows stop at the hard fallback ceiling even with null max_iterations');
|
|
198
212
|
}
|
|
199
213
|
|
|
200
214
|
// ---- Test 14: non-git project fingerprint is content-sensitive (CRITICAL #1) ----
|
|
@@ -225,7 +239,8 @@ try {
|
|
|
225
239
|
const cfg = JSON.parse(readFileSync(cfgP, 'utf8')); cfg.max_iterations = 1e9; writeFileSync(cfgP, JSON.stringify(cfg));
|
|
226
240
|
const spP = join(d, '.svamp', SID, 'loop', 'loop-state.json');
|
|
227
241
|
const sp = JSON.parse(readFileSync(spP, 'utf8')); sp.iteration = 201; writeFileSync(spP, JSON.stringify(sp));
|
|
228
|
-
|
|
242
|
+
runGate(d); // #0156: stall hint first
|
|
243
|
+
const r = runGate(d); // then allow
|
|
229
244
|
ok(!r.blocked && /max_iterations \(200\)/.test(readState(d).gave_up_reason || ''), 'max_iterations 1e9 clamped to 200 → gives up');
|
|
230
245
|
}
|
|
231
246
|
|
|
@@ -374,6 +389,44 @@ try {
|
|
|
374
389
|
ok(!r.blocked && readState(d).phase === 'done', 'all-handled inbox allows the loop to complete');
|
|
375
390
|
}
|
|
376
391
|
|
|
392
|
+
// ---- Test 25: NON-URGENT inbox hint at settle — blocks ONCE, then allows (de-duped) (#0146) ----
|
|
393
|
+
console.log('Test 25: non-urgent inbox hint blocks once at settle, then allows (de-duped)');
|
|
394
|
+
{ const d = newProject({ evaluator: 'on' }); dirs.push(d);
|
|
395
|
+
writeFileSync(join(d, 'answer.txt'), 'DONE\n'); // oracle passes
|
|
396
|
+
writeVerdict(d, { verdict: 'done', reason: 'ok', state_fp: fp(d) });
|
|
397
|
+
// Disable the #0103 urgent/unhandled guard so we exercise the non-urgent hint in isolation
|
|
398
|
+
// (otherwise the #0103 guard would block first on the same genuinely-pending message).
|
|
399
|
+
const cfgP = join(d, '.svamp', SID, 'loop', 'loop.config.json');
|
|
400
|
+
writeFileSync(cfgP, JSON.stringify({ ...JSON.parse(readFileSync(cfgP, 'utf8')), inbox_guard: false }));
|
|
401
|
+
// A genuinely-unseen (read=false, handled=false), non-urgent, non-awaiting-reply message.
|
|
402
|
+
writeFileSync(join(d, '.svamp', SID, 'inbox.json'), JSON.stringify([
|
|
403
|
+
{ messageId: 'n1', from: 'agent:peer', subject: 'fyi', read: false, handled: false, urgency: 'normal' },
|
|
404
|
+
]));
|
|
405
|
+
const r1 = runGate(d);
|
|
406
|
+
ok(r1.blocked && /unread inbox message/i.test(r1.reason), 'non-urgent unread message hints (blocks once) at the settle point');
|
|
407
|
+
ok(/fyi/.test(r1.reason), 'hint names the subject');
|
|
408
|
+
const hinted = JSON.parse(readFileSync(join(d, '.svamp', SID, 'loop', 'hinted-inbox.json'), 'utf8'));
|
|
409
|
+
ok(hinted.includes('n1'), 'hinted id recorded for de-dupe');
|
|
410
|
+
// Second settle: same message id already hinted → allows the loop to end (non-blocking thereafter).
|
|
411
|
+
const r2 = runGate(d);
|
|
412
|
+
ok(!r2.blocked && readState(d).phase === 'done', 'already-hinted message does not re-block — loop completes');
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// ---- Test 26: urgent + awaiting-reply messages are NOT hinted by the non-urgent path (#0146) ----
|
|
416
|
+
console.log('Test 26: urgent / awaiting-reply messages skip the non-urgent hint');
|
|
417
|
+
{ const d = newProject({ evaluator: 'on' }); dirs.push(d);
|
|
418
|
+
writeFileSync(join(d, 'answer.txt'), 'DONE\n');
|
|
419
|
+
writeVerdict(d, { verdict: 'done', reason: 'ok', state_fp: fp(d) });
|
|
420
|
+
// All handled (no #0103 block); one urgent, one awaiting-reply, one already-read → none qualify.
|
|
421
|
+
writeFileSync(join(d, '.svamp', SID, 'inbox.json'), JSON.stringify([
|
|
422
|
+
{ messageId: 'u1', read: false, handled: true, urgency: 'urgent' },
|
|
423
|
+
{ messageId: 'a1', read: false, handled: true, channelId: 'c', correlationId: 'x' },
|
|
424
|
+
{ messageId: 'r1', read: true, handled: true, urgency: 'normal' },
|
|
425
|
+
]));
|
|
426
|
+
const r = runGate(d);
|
|
427
|
+
ok(!r.blocked && readState(d).phase === 'done', 'no qualifying non-urgent unread message → loop completes (no noise)');
|
|
428
|
+
}
|
|
429
|
+
|
|
377
430
|
console.log(`\n${fail === 0 ? '✅' : '❌'} ${pass} passed, ${fail} failed`);
|
|
378
431
|
process.exit(fail === 0 ? 0 : 1);
|
|
379
432
|
} finally {
|
|
@@ -2,7 +2,7 @@ import { existsSync, readFileSync, mkdirSync, writeFileSync, renameSync } from '
|
|
|
2
2
|
import { join, dirname } from 'node:path';
|
|
3
3
|
import os from 'node:os';
|
|
4
4
|
import { requireNotSandboxed } from './sandboxDetect-DNTcbgWD.mjs';
|
|
5
|
-
import { A as shortId } from './run-
|
|
5
|
+
import { A as shortId } from './run-C9ZeF2iG.mjs';
|
|
6
6
|
import 'os';
|
|
7
7
|
import 'fs/promises';
|
|
8
8
|
import 'fs';
|
|
@@ -96,7 +96,7 @@ async function sessionSetTitle(title) {
|
|
|
96
96
|
}
|
|
97
97
|
async function sessionSetProjectDescription(description) {
|
|
98
98
|
const dir = process.cwd();
|
|
99
|
-
const { projectName, writeProjectInfo, sanitizeDescription, projectInfoPath } = await import('./run-
|
|
99
|
+
const { projectName, writeProjectInfo, sanitizeDescription, projectInfoPath } = await import('./run-C9ZeF2iG.mjs').then(function (n) { return n.a8; });
|
|
100
100
|
const desc = sanitizeDescription(description, 240);
|
|
101
101
|
if (!desc) {
|
|
102
102
|
console.error("Project description is empty.");
|
|
@@ -180,7 +180,7 @@ async function sessionBroadcast(action, args) {
|
|
|
180
180
|
console.log(`Broadcast sent: ${action}`);
|
|
181
181
|
}
|
|
182
182
|
async function connectToMachineService() {
|
|
183
|
-
const { connectAndGetMachine } = await import('./commands-
|
|
183
|
+
const { connectAndGetMachine } = await import('./commands-BRmWVCNf.mjs');
|
|
184
184
|
return connectAndGetMachine();
|
|
185
185
|
}
|
|
186
186
|
function buildInboxMessage(args) {
|
|
@@ -258,7 +258,7 @@ async function inboxSend(targetSessionId, opts) {
|
|
|
258
258
|
console.error("Message body is required.");
|
|
259
259
|
process.exit(1);
|
|
260
260
|
}
|
|
261
|
-
const { connectAndResolveSession } = await import('./commands-
|
|
261
|
+
const { connectAndResolveSession } = await import('./commands-BRmWVCNf.mjs');
|
|
262
262
|
let server;
|
|
263
263
|
try {
|
|
264
264
|
const { targetId, messageId } = await inboxSendCore(
|
|
@@ -312,7 +312,7 @@ async function inboxReply(messageId, body) {
|
|
|
312
312
|
console.error("SVAMP_SESSION_ID not set. This command must be run inside a Svamp session.");
|
|
313
313
|
process.exit(1);
|
|
314
314
|
}
|
|
315
|
-
const { connectAndResolveSession } = await import('./commands-
|
|
315
|
+
const { connectAndResolveSession } = await import('./commands-BRmWVCNf.mjs');
|
|
316
316
|
const { server: localServer, machine: localMachine } = await connectToMachineService();
|
|
317
317
|
let localDisconnected = false;
|
|
318
318
|
const disconnectLocal = async () => {
|