@sema-agent/cli 1.0.13 → 1.0.15
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/npm-shrinkwrap.json +17 -17
- package/package.json +5 -5
- package/sema.js +172 -18
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sema-agent/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.15",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@sema-agent/cli",
|
|
9
|
-
"version": "1.0.
|
|
9
|
+
"version": "1.0.15",
|
|
10
10
|
"license": "BUSL-1.1",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@sema-agent/sdk": "0.0.53",
|
|
13
|
-
"@sema-agent/server": "1.
|
|
13
|
+
"@sema-agent/server": "1.220.0"
|
|
14
14
|
},
|
|
15
15
|
"bin": {
|
|
16
16
|
"sema": "sema.js"
|
|
@@ -629,9 +629,9 @@
|
|
|
629
629
|
}
|
|
630
630
|
},
|
|
631
631
|
"node_modules/@sema-agent/core": {
|
|
632
|
-
"version": "1.
|
|
633
|
-
"resolved": "https://registry.npmjs.org/@sema-agent/core/-/core-1.
|
|
634
|
-
"integrity": "sha512-
|
|
632
|
+
"version": "1.312.0",
|
|
633
|
+
"resolved": "https://registry.npmjs.org/@sema-agent/core/-/core-1.312.0.tgz",
|
|
634
|
+
"integrity": "sha512-a50syYHBa3TT1FjqZCGwK2YH3gt6o4YiyamJYGwY4ABdwCaj8wGBJZmkQw48J+1XEDo7NL/rV5xtaNzxn656Gw==",
|
|
635
635
|
"license": "BUSL-1.1",
|
|
636
636
|
"dependencies": {
|
|
637
637
|
"@modelcontextprotocol/sdk": "1.29.0",
|
|
@@ -645,9 +645,9 @@
|
|
|
645
645
|
}
|
|
646
646
|
},
|
|
647
647
|
"node_modules/@sema-agent/registry-core": {
|
|
648
|
-
"version": "0.10.
|
|
649
|
-
"resolved": "https://registry.npmjs.org/@sema-agent/registry-core/-/registry-core-0.10.
|
|
650
|
-
"integrity": "sha512-
|
|
648
|
+
"version": "0.10.15",
|
|
649
|
+
"resolved": "https://registry.npmjs.org/@sema-agent/registry-core/-/registry-core-0.10.15.tgz",
|
|
650
|
+
"integrity": "sha512-nOwzBLFSMSgpkP9ftPLPj68IzhsP8fHrT+isCojNPF9oywFsROpFiNzNszmFsTt53eBnpQ+tHwxdsJXU0vV1xA==",
|
|
651
651
|
"license": "BUSL-1.1",
|
|
652
652
|
"dependencies": {
|
|
653
653
|
"zod": "^3.24.0"
|
|
@@ -678,13 +678,13 @@
|
|
|
678
678
|
}
|
|
679
679
|
},
|
|
680
680
|
"node_modules/@sema-agent/server": {
|
|
681
|
-
"version": "1.
|
|
682
|
-
"resolved": "https://registry.npmjs.org/@sema-agent/server/-/server-1.
|
|
683
|
-
"integrity": "sha512-
|
|
681
|
+
"version": "1.220.0",
|
|
682
|
+
"resolved": "https://registry.npmjs.org/@sema-agent/server/-/server-1.220.0.tgz",
|
|
683
|
+
"integrity": "sha512-3i1zW48+gxS6Csb7YDD8PiLInphHtFeLBKTTexwoBCA6bYKqwHSJeO1Zr3YzHTzSm/+gqmOs2VGRCqNYbOz8gg==",
|
|
684
684
|
"license": "BUSL-1.1",
|
|
685
685
|
"dependencies": {
|
|
686
|
-
"@sema-agent/core": "^1.
|
|
687
|
-
"@sema-agent/registry-core": "^0.10.
|
|
686
|
+
"@sema-agent/core": "^1.311.0",
|
|
687
|
+
"@sema-agent/registry-core": "^0.10.14",
|
|
688
688
|
"e2b": "^2.28.0",
|
|
689
689
|
"libsodium-wrappers": "^0.8.4",
|
|
690
690
|
"mysql2": "^3.22.4",
|
|
@@ -1077,9 +1077,9 @@
|
|
|
1077
1077
|
}
|
|
1078
1078
|
},
|
|
1079
1079
|
"node_modules/e2b": {
|
|
1080
|
-
"version": "2.
|
|
1081
|
-
"resolved": "https://registry.npmjs.org/e2b/-/e2b-2.
|
|
1082
|
-
"integrity": "sha512-
|
|
1080
|
+
"version": "2.35.0",
|
|
1081
|
+
"resolved": "https://registry.npmjs.org/e2b/-/e2b-2.35.0.tgz",
|
|
1082
|
+
"integrity": "sha512-ZOu2aNbnTtUcMBbLMB6houapLJxACco+PbmybzP42Id3H7ud8Z1HkQAVKj9nXwSH4g8llojwsRx6Ro6asQGJrg==",
|
|
1083
1083
|
"license": "MIT",
|
|
1084
1084
|
"dependencies": {
|
|
1085
1085
|
"@bufbuild/protobuf": "^2.12.1",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sema-agent/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.15",
|
|
4
4
|
"description": "Sema — your own Claude Code-grade coding agent, in the terminal.",
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"bin": {
|
|
@@ -22,13 +22,13 @@
|
|
|
22
22
|
],
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@sema-agent/sdk": "0.0.53",
|
|
25
|
-
"@sema-agent/server": "1.
|
|
25
|
+
"@sema-agent/server": "1.220.0"
|
|
26
26
|
},
|
|
27
27
|
"overrides": {
|
|
28
|
-
"@sema-agent/core": "1.
|
|
29
|
-
"@sema-agent/registry-core": "0.10.
|
|
28
|
+
"@sema-agent/core": "1.312.0",
|
|
29
|
+
"@sema-agent/registry-core": "0.10.15"
|
|
30
30
|
},
|
|
31
|
-
"semaEngineVersion": "server 1.
|
|
31
|
+
"semaEngineVersion": "server 1.220.0 / core 1.312.0 / registry-core 0.10.15",
|
|
32
32
|
"engines": {
|
|
33
33
|
"node": ">=18"
|
|
34
34
|
}
|
package/sema.js
CHANGED
|
@@ -107341,6 +107341,8 @@ var init_ink = __esm({
|
|
|
107341
107341
|
// screen readers / screen magnifiers track it — so parking at the text
|
|
107342
107342
|
// input's caret makes CJK input appear inline and lets a11y tools follow.
|
|
107343
107343
|
cursorDeclaration = null;
|
|
107344
|
+
/** sema 光标/IME:声明光标当前是否已 ?25h 显示(防每帧重复写显隐序)。 */
|
|
107345
|
+
declaredCursorShown = false;
|
|
107344
107346
|
// Main-screen: physical cursor position after the declared-cursor move,
|
|
107345
107347
|
// tracked separately from frame.cursor (which must stay at content-bottom
|
|
107346
107348
|
// for log-update's relative-move invariants). Alt-screen doesn't need
|
|
@@ -107627,6 +107629,10 @@ var init_ink = __esm({
|
|
|
107627
107629
|
});
|
|
107628
107630
|
}
|
|
107629
107631
|
}
|
|
107632
|
+
if (!this.declaredCursorShown) {
|
|
107633
|
+
optimized.push({ type: "stdout", content: "\x1B[?25h" });
|
|
107634
|
+
this.declaredCursorShown = true;
|
|
107635
|
+
}
|
|
107630
107636
|
this.displayCursor = target;
|
|
107631
107637
|
} else {
|
|
107632
107638
|
if (parked !== null && !this.altScreenActive && !hasDiff) {
|
|
@@ -107639,6 +107645,10 @@ var init_ink = __esm({
|
|
|
107639
107645
|
});
|
|
107640
107646
|
}
|
|
107641
107647
|
}
|
|
107648
|
+
if (this.declaredCursorShown) {
|
|
107649
|
+
optimized.push({ type: "stdout", content: "\x1B[?25l" });
|
|
107650
|
+
this.declaredCursorShown = false;
|
|
107651
|
+
}
|
|
107642
107652
|
this.displayCursor = null;
|
|
107643
107653
|
}
|
|
107644
107654
|
}
|
|
@@ -157477,8 +157487,23 @@ var init_selfOrchestrationWireCaps = __esm({
|
|
|
157477
157487
|
}
|
|
157478
157488
|
});
|
|
157479
157489
|
|
|
157480
|
-
// build-src/src/sema/
|
|
157490
|
+
// build-src/src/sema/retainBackgroundWireCaps.ts
|
|
157481
157491
|
function isTruthy(v2) {
|
|
157492
|
+
const s = typeof v2 === "string" ? v2.trim().toLowerCase() : "";
|
|
157493
|
+
return s === "1" || s === "true" || s === "yes" || s === "on";
|
|
157494
|
+
}
|
|
157495
|
+
function retainBackgroundFromEnv(env5 = process.env) {
|
|
157496
|
+
return isTruthy(env5[RETAIN_BACKGROUND_ENV]) ? true : void 0;
|
|
157497
|
+
}
|
|
157498
|
+
var RETAIN_BACKGROUND_ENV;
|
|
157499
|
+
var init_retainBackgroundWireCaps = __esm({
|
|
157500
|
+
"build-src/src/sema/retainBackgroundWireCaps.ts"() {
|
|
157501
|
+
RETAIN_BACKGROUND_ENV = "SEMA_RETAIN_BACKGROUND";
|
|
157502
|
+
}
|
|
157503
|
+
});
|
|
157504
|
+
|
|
157505
|
+
// build-src/src/sema/forkWireCaps.ts
|
|
157506
|
+
function isTruthy2(v2) {
|
|
157482
157507
|
const s = v2.trim().toLowerCase();
|
|
157483
157508
|
return s === "1" || s === "true" || s === "yes" || s === "on";
|
|
157484
157509
|
}
|
|
@@ -157489,7 +157514,7 @@ function isFalsy2(v2) {
|
|
|
157489
157514
|
function enableForkFromEnv(env5 = process.env) {
|
|
157490
157515
|
const raw2 = env5[ENABLE_FORK_ENV];
|
|
157491
157516
|
if (typeof raw2 !== "string" || raw2.trim() === "") return void 0;
|
|
157492
|
-
if (
|
|
157517
|
+
if (isTruthy2(raw2)) return true;
|
|
157493
157518
|
if (isFalsy2(raw2)) return false;
|
|
157494
157519
|
return void 0;
|
|
157495
157520
|
}
|
|
@@ -331848,9 +331873,9 @@ function streamingTailWrap(unstableSuffix) {
|
|
|
331848
331873
|
var import_compiler_runtime43, import_react43, import_jsx_runtime53, TOKEN_CACHE_MAX, tokenCache, MD_SYNTAX_RE;
|
|
331849
331874
|
var init_Markdown = __esm({
|
|
331850
331875
|
"build-src/src/components/Markdown.tsx"() {
|
|
331851
|
-
import_compiler_runtime43 = __toESM(require_compiler_runtime());
|
|
331876
|
+
import_compiler_runtime43 = __toESM(require_compiler_runtime(), 1);
|
|
331852
331877
|
init_marked_esm();
|
|
331853
|
-
import_react43 = __toESM(require_react());
|
|
331878
|
+
import_react43 = __toESM(require_react(), 1);
|
|
331854
331879
|
init_useSettings();
|
|
331855
331880
|
init_ink2();
|
|
331856
331881
|
init_cliHighlight();
|
|
@@ -331858,7 +331883,7 @@ var init_Markdown = __esm({
|
|
|
331858
331883
|
init_markdown();
|
|
331859
331884
|
init_messages4();
|
|
331860
331885
|
init_MarkdownTable();
|
|
331861
|
-
import_jsx_runtime53 = __toESM(require_jsx_runtime());
|
|
331886
|
+
import_jsx_runtime53 = __toESM(require_jsx_runtime(), 1);
|
|
331862
331887
|
TOKEN_CACHE_MAX = 500;
|
|
331863
331888
|
tokenCache = /* @__PURE__ */ new Map();
|
|
331864
331889
|
MD_SYNTAX_RE = /[#*`|[>\-_~]|\n\n|^\d+\. |\n\d+\. /;
|
|
@@ -433312,6 +433337,10 @@ function toTaskRequest(params) {
|
|
|
433312
433337
|
if (selfOrchestration && process.env.SEMA_DEBUG) {
|
|
433313
433338
|
console.error("[sema][seamQuery] selfOrchestration wire: SEMA_SELF_ORCHESTRATION \u2192 TaskRequest.selfOrchestration=true (run_workflow)");
|
|
433314
433339
|
}
|
|
433340
|
+
const retainBackground = process.env.SEMA_LIVE_BASEURL ? retainBackgroundFromEnv() : void 0;
|
|
433341
|
+
if (retainBackground && process.env.SEMA_DEBUG) {
|
|
433342
|
+
console.error("[sema][seamQuery] retainBackground wire: SEMA_RETAIN_BACKGROUND \u2192 TaskRequest.retainBackgroundProcesses=true");
|
|
433343
|
+
}
|
|
433315
433344
|
const attachments = process.env.SEMA_LIVE_BASEURL ? attachmentsForRequest() : void 0;
|
|
433316
433345
|
if (attachments && process.env.SEMA_DEBUG) {
|
|
433317
433346
|
console.error(`[sema][seamQuery] attachments wire: ${Object.keys(attachments).join("+")} \u2192 TaskRequest.attachments`);
|
|
@@ -433391,6 +433420,7 @@ ${objective}`;
|
|
|
433391
433420
|
// Workflow super-set: the top-level selfOrchestration flag (SEMA_SELF_ORCHESTRATION env opt-in, live-gated).
|
|
433392
433421
|
// Present ⇒ the SERVICE mounts core run_workflow (gated on its deployment/tenant policy); absent ⇒ no stamp.
|
|
433393
433422
|
...selfOrchestration ? { selfOrchestration } : {},
|
|
433423
|
+
...retainBackground ? { retainBackgroundProcesses: retainBackground } : {},
|
|
433394
433424
|
// Fork super-set: the top-level enableFork flag — EXPLICIT boolean on live (core ≥1.257 treats absent
|
|
433395
433425
|
// as granted; the shell's default-OFF product decision must be spelled out). Mock path stays unstamped.
|
|
433396
433426
|
...enableFork !== void 0 ? { enableFork } : {},
|
|
@@ -433711,6 +433741,7 @@ var init_seamQuery = __esm({
|
|
|
433711
433741
|
init_imagesWireCaps();
|
|
433712
433742
|
init_webSearchWireCaps();
|
|
433713
433743
|
init_selfOrchestrationWireCaps();
|
|
433744
|
+
init_retainBackgroundWireCaps();
|
|
433714
433745
|
init_forkWireCaps();
|
|
433715
433746
|
init_attachmentsWireCaps();
|
|
433716
433747
|
init_clientContextWireCaps();
|
|
@@ -450640,7 +450671,7 @@ function Settings({
|
|
|
450640
450671
|
var import_react113, import_jsx_runtime192;
|
|
450641
450672
|
var init_cmd_config = __esm({
|
|
450642
450673
|
"build-src/src/sema/overrides/cmd-config.tsx"() {
|
|
450643
|
-
import_react113 = __toESM(require_react());
|
|
450674
|
+
import_react113 = __toESM(require_react(), 1);
|
|
450644
450675
|
init_useKeybinding();
|
|
450645
450676
|
init_useExitOnCtrlCDWithKeybindings();
|
|
450646
450677
|
init_useTerminalSize();
|
|
@@ -450651,7 +450682,7 @@ var init_cmd_config = __esm({
|
|
|
450651
450682
|
init_Config();
|
|
450652
450683
|
init_settings_usage();
|
|
450653
450684
|
init_Stats();
|
|
450654
|
-
import_jsx_runtime192 = __toESM(require_jsx_runtime());
|
|
450685
|
+
import_jsx_runtime192 = __toESM(require_jsx_runtime(), 1);
|
|
450655
450686
|
}
|
|
450656
450687
|
});
|
|
450657
450688
|
|
|
@@ -479518,8 +479549,8 @@ var init_sema_brand = __esm({
|
|
|
479518
479549
|
"Slash-command gating wired to the fleet capability handshake"
|
|
479519
479550
|
]
|
|
479520
479551
|
},
|
|
479521
|
-
productVersion: "1.0.
|
|
479522
|
-
announcement: "sema 1.0.
|
|
479552
|
+
productVersion: "1.0.15",
|
|
479553
|
+
announcement: "sema 1.0.15 \u2014 headless (-p) runs stop mounting scheduler tools they can never honor (leaner prompts, faster turns), the init frame reports the tools actually mounted, and background processes can be retained past teardown with SEMA_RETAIN_BACKGROUND=1"
|
|
479523
479554
|
};
|
|
479524
479555
|
}
|
|
479525
479556
|
});
|
|
@@ -482453,8 +482484,8 @@ var require_sema_brand = __commonJS({
|
|
|
482453
482484
|
"Slash-command gating wired to the fleet capability handshake"
|
|
482454
482485
|
]
|
|
482455
482486
|
},
|
|
482456
|
-
productVersion: "1.0.
|
|
482457
|
-
announcement: "sema 1.0.
|
|
482487
|
+
productVersion: "1.0.15",
|
|
482488
|
+
announcement: "sema 1.0.15 \u2014 headless (-p) runs stop mounting scheduler tools they can never honor (leaner prompts, faster turns), the init frame reports the tools actually mounted, and background processes can be retained past teardown with SEMA_RETAIN_BACKGROUND=1"
|
|
482458
482489
|
};
|
|
482459
482490
|
}
|
|
482460
482491
|
});
|
|
@@ -556862,6 +556893,98 @@ var init_fs_write_gate_policy = __esm({
|
|
|
556862
556893
|
}
|
|
556863
556894
|
});
|
|
556864
556895
|
|
|
556896
|
+
// node_modules/@sema-agent/core/dist/tools/loop-tick.js
|
|
556897
|
+
function pushNotificationAppendix(persistentVariant) {
|
|
556898
|
+
const r = persistentVariant ? "newly blocked on a decision you won't make alone, you're ending the loop" : "newly blocked on a decision you won't make alone, third straight tick with nothing to do, you're ending the loop";
|
|
556899
|
+
return `
|
|
556900
|
+
|
|
556901
|
+
Use PushNotification when the loop can't move further without the user, or when something landed that they'd want to act on now: ${r}, or a major update arrived (CI went red, a review changes the plan). Progress you made yourself isn't a trigger \u2014 the transcript covers that. One ping per state, not per tick.`;
|
|
556902
|
+
}
|
|
556903
|
+
function cronTick(push) {
|
|
556904
|
+
return `# Autonomous loop tick
|
|
556905
|
+
|
|
556906
|
+
Run the autonomous check using the loop instructions established earlier in this conversation. If you cannot find them, treat this as a no-op tick. The recurring cron will fire the next tick automatically \u2014 do not call ${SCHEDULE_WAKEUP_TOOL_NAME} from this tick.${push}`;
|
|
556907
|
+
}
|
|
556908
|
+
function dynamicTick(push) {
|
|
556909
|
+
return `# Autonomous loop tick (dynamic pacing)
|
|
556910
|
+
|
|
556911
|
+
Run the autonomous check using the loop instructions established earlier in this conversation. If you cannot find them, treat this as a no-op tick.
|
|
556912
|
+
|
|
556913
|
+
You scheduled this tick via the ${SCHEDULE_WAKEUP_TOOL_NAME} tool (not a recurring cron). To keep the loop alive, call ${SCHEDULE_WAKEUP_TOOL_NAME} again at the end of this turn with \`prompt\` set to the literal sentinel \`${AUTONOMOUS_LOOP_DYNAMIC_SENTINEL}\` \u2014 otherwise the loop ends after this tick.${DYNAMIC_APPENDIX}${push}`;
|
|
556914
|
+
}
|
|
556915
|
+
function resolveAutonomousLoopPrompt(prompt, opts) {
|
|
556916
|
+
if (prompt !== AUTONOMOUS_LOOP_SENTINEL && prompt !== AUTONOMOUS_LOOP_DYNAMIC_SENTINEL)
|
|
556917
|
+
return null;
|
|
556918
|
+
const persistent = opts?.persistentVariant === true;
|
|
556919
|
+
const push = opts?.pushNotification === true ? pushNotificationAppendix(persistent) : "";
|
|
556920
|
+
const tick = prompt === AUTONOMOUS_LOOP_DYNAMIC_SENTINEL ? dynamicTick(push) : cronTick(push);
|
|
556921
|
+
if (opts?.firstTick !== true)
|
|
556922
|
+
return tick;
|
|
556923
|
+
const preamble = persistent ? AUTONOMOUS_LOOP_PREAMBLE_PERSISTENT : AUTONOMOUS_LOOP_PREAMBLE;
|
|
556924
|
+
return `${preamble}
|
|
556925
|
+
|
|
556926
|
+
---
|
|
556927
|
+
|
|
556928
|
+
${tick}`;
|
|
556929
|
+
}
|
|
556930
|
+
var AUTONOMOUS_LOOP_PREAMBLE, AUTONOMOUS_LOOP_PREAMBLE_PERSISTENT, DYNAMIC_APPENDIX;
|
|
556931
|
+
var init_loop_tick = __esm({
|
|
556932
|
+
"node_modules/@sema-agent/core/dist/tools/loop-tick.js"() {
|
|
556933
|
+
init_scheduler_tools();
|
|
556934
|
+
AUTONOMOUS_LOOP_PREAMBLE = `# Autonomous loop check
|
|
556935
|
+
|
|
556936
|
+
You're being invoked on a timer while the user is away or occupied. The point is to keep work moving forward without the user driving every step \u2014 finishing things they started, maintaining PRs they're building, catching problems before they come back to find them. You're a steward, not an initiator. The user set you loose on their work, and the value you provide comes from reliably advancing things they've already set in motion, not from finding new things to do.
|
|
556937
|
+
|
|
556938
|
+
The key tension to navigate: the user trusts you enough to run autonomously, but that trust is easily lost. Acting on what the conversation already established is safe and valuable. Inventing new work or making irreversible changes without clear authorization erodes trust fast. When you're unsure whether something falls into "continuing established work" or "inventing new work," lean toward the former only when the transcript provides clear evidence the user wanted it done. If you find yourself reaching for justifications about why a push is probably fine, that's a signal to wait.
|
|
556939
|
+
|
|
556940
|
+
## What to act on
|
|
556941
|
+
|
|
556942
|
+
The current conversation is your highest-signal source \u2014 re-read the transcript above, since everything there is something the user was actively engaged with. The strongest signal is an in-progress PR you've been building together: review comments to address and resolve, failing CI checks to diagnose (and re-enqueue if they're flakes), merge conflicts to fix. The goal is to get the PR into a state where it's ready to merge pending only human review \u2014 the user shouldn't come back to find a PR blocked on things you could have handled. After that, look for unfinished implementation where the last exchange left something half-done, and explicit "I'll also..." or "next I'll..." commitments the conversation made and didn't honor. Weaker but still real: dangling questions you could now answer, verification steps that were skipped, edge cases that were mentioned but not handled, and natural continuations that don't require new decisions.
|
|
556943
|
+
|
|
556944
|
+
If you find anything in this category, act on it \u2014 actually do the work, don't describe what could be done. Run the tests, don't say "you could run the tests." The whole point of autonomous operation is that work gets done while the user is away.
|
|
556945
|
+
|
|
556946
|
+
When the conversation transcript has nothing left, the current branch's pull/merge request on the user's SCM is the next-best place to look. This is maintenance work \u2014 valuable, but lower priority than continuing the user's active work. Find the PR/MR for the current branch via the SCM's CLI, then check three things: CI status, unresolved review threads, and whether the branch has fallen behind the base. For failing CI, pull the failing job's logs and diagnose before acting \u2014 flaky-shaped failures (timeout, runner died, transient network) can be re-enqueued; real failures need a reproduction and a minimal fix. For unresolved review threads, fetch the comment, address the feedback, push, and resolve the thread via, for example, the GitHub GraphQL \`resolveReviewThread\` mutation (or the equivalent for whichever SCM the project uses). Before pushing anything, check whether someone else has pushed to the branch while you were working \u2014 if so, rebase (don't merge) to keep history clean.
|
|
556947
|
+
|
|
556948
|
+
When CI is green, threads are clear, and there's idle time, sweeping the branch for issues is a good use of that time \u2014 bug-hunt or simplification passes catch problems before reviewers do, saving everyone a round-trip.
|
|
556949
|
+
|
|
556950
|
+
If everything is genuinely quiet \u2014 no conversation work, no PR maintenance \u2014 say so in one sentence and stop. No summary of what you checked, no list of what you might do later. The user will see your message in the transcript when they come back; three consecutive "nothing to do" results means you should scale back to a quick CI check and stop, not narrate.
|
|
556951
|
+
|
|
556952
|
+
## Repeated invocations
|
|
556953
|
+
|
|
556954
|
+
If you see earlier autonomous checks in this conversation, adjust your scope accordingly. If a previous check left a question the user hasn't answered, the cost of acting depends on reversibility: for reversible actions (local edits, running tests), make your best call and proceed; for irreversible ones (pushing, deleting, sending), keep waiting \u2014 the cost of acting wrongly on something irreversible is much higher than the cost of waiting one more cycle. If three or more consecutive checks have found nothing actionable, things are quiet \u2014 do one quick CI/threads check and stop in a single line. Repeated "nothing to do" messages clutter the transcript and waste the user's attention when they come back to review.
|
|
556955
|
+
|
|
556956
|
+
Read and analyze freely \u2014 understanding the state of things has no blast radius. Make edits and run tests when you're confident they continue established work. Commit and push only when you're clearly continuing something the user authorized, or when the work pattern makes the intent obvious \u2014 like fixing CI on a PR you've been building together.
|
|
556957
|
+
`;
|
|
556958
|
+
AUTONOMOUS_LOOP_PREAMBLE_PERSISTENT = `# Autonomous loop check
|
|
556959
|
+
|
|
556960
|
+
You're being invoked on a timer while the user is away or occupied. The point is to keep work moving forward without the user driving every step \u2014 finishing things they started, maintaining PRs they're building, catching problems before they come back to find them, and following through on the *spirit* of the task they gave you, not just its literal scope. The user set you loose on their work, and the value you provide comes from reliably advancing things they've already set in motion.
|
|
556961
|
+
|
|
556962
|
+
The key tension to navigate: the user trusts you enough to run autonomously, but that trust is easily lost. Acting on what the conversation already established is safe and valuable. For irreversible actions (push, delete, send), require clear authorization in the transcript or use a reversible alternative (a draft, a local commit, a queued message). For reversible actions (edits, tests, drafts, exploration), bias toward acting \u2014 the cost of an unneeded local edit is near zero, and the cost of a stalled loop is high. When you're unsure whether something falls into "continuing established work" or "inventing new work," lean toward continuing whenever the transcript gives you any reasonable thread to pull on.
|
|
556963
|
+
|
|
556964
|
+
## What to act on
|
|
556965
|
+
|
|
556966
|
+
The current conversation is your highest-signal source \u2014 re-read the transcript above, since everything there is something the user was actively engaged with. The strongest signal is an in-progress PR you've been building together: review comments to address and resolve, failing CI checks to diagnose (and re-enqueue if they're flakes), merge conflicts to fix. The goal is to get the PR into a state where it's ready to merge pending only human review \u2014 the user shouldn't come back to find a PR blocked on things you could have handled. After that, look for unfinished implementation where the last exchange left something half-done, and explicit "I'll also..." or "next I'll..." commitments the conversation made and didn't honor. Weaker but still real: dangling questions you could now answer, verification steps that were skipped, edge cases that were mentioned but not handled, and natural continuations that don't require new decisions.
|
|
556967
|
+
|
|
556968
|
+
If you find anything in this category, act on it \u2014 actually do the work, don't describe what could be done. Run the tests, don't say "you could run the tests." The whole point of autonomous operation is that work gets done while the user is away.
|
|
556969
|
+
|
|
556970
|
+
When the conversation transcript has nothing left, the current branch's pull/merge request on the user's SCM is the next-best place to look. This is maintenance work \u2014 valuable, but lower priority than continuing the user's active work. Find the PR/MR for the current branch via the SCM's CLI, then check three things: CI status, unresolved review threads, and whether the branch has fallen behind the base. For failing CI, pull the failing job's logs and diagnose before acting \u2014 flaky-shaped failures (timeout, runner died, transient network) can be re-enqueued; real failures need a reproduction and a minimal fix. For unresolved review threads, fetch the comment, address the feedback, push, and resolve the thread via, for example, the GitHub GraphQL \`resolveReviewThread\` mutation (or the equivalent for whichever SCM the project uses). Before pushing anything, check whether someone else has pushed to the branch while you were working \u2014 if so, rebase (don't merge) to keep history clean.
|
|
556971
|
+
|
|
556972
|
+
When CI is green, threads are clear, and there's idle time, sweeping the branch for issues is a good use of that time \u2014 bug-hunt or simplification passes catch problems before reviewers do, saving everyone a round-trip.
|
|
556973
|
+
|
|
556974
|
+
If everything is genuinely quiet \u2014 no conversation work, no PR maintenance \u2014 say so in one sentence and keep the loop alive. Before stopping, broaden once: re-read the original task framing, check whether earlier ticks deferred anything ("I'll wait for X"), and look at sibling PRs/branches the user owns. Persistence is the point of autonomous mode. Only stop if the original task is provably complete or the user said to stop. (Pacing \u2014 how long to wait before the next tick \u2014 is handled by the per-mode reminder appended to this preamble; don't try to manage delay from here.)
|
|
556975
|
+
|
|
556976
|
+
## Repeated invocations
|
|
556977
|
+
|
|
556978
|
+
If you see earlier autonomous checks in this conversation, adjust your scope accordingly. If a previous check left a question the user hasn't answered, the cost of acting depends on reversibility: for reversible actions (local edits, running tests), make your best call and proceed; for irreversible ones (pushing, deleting, sending), keep waiting \u2014 the cost of acting wrongly on something irreversible is much higher than the cost of waiting one more cycle. If three or more consecutive checks have found nothing actionable, broaden scope once before considering stopping \u2014 re-read the original task, check sibling work, look for verification or polish steps that were skipped. A loop that quits the moment work goes quiet is less useful than one that waits.
|
|
556979
|
+
|
|
556980
|
+
Read and analyze freely \u2014 understanding the state of things has no blast radius. Make edits and run tests when you're confident they continue established work. Commit and push only when you're clearly continuing something the user authorized, or when the work pattern makes the intent obvious \u2014 like fixing CI on a PR you've been building together.
|
|
556981
|
+
`;
|
|
556982
|
+
DYNAMIC_APPENDIX = `
|
|
556983
|
+
|
|
556984
|
+
If a Monitor is armed (check TaskList), keep \`delaySeconds\` at 1200\u20131800s \u2014 the Monitor is the wake signal and this is only the fallback heartbeat. If you were woken by a \`<task-notification>\`, handle the event before deciding whether to re-arm. To stop the loop, call ${SCHEDULE_WAKEUP_TOOL_NAME} with \`stop: true\` and TaskStop the monitor (use TaskList to find its task ID if no longer in context).`;
|
|
556985
|
+
}
|
|
556986
|
+
});
|
|
556987
|
+
|
|
556865
556988
|
// node_modules/@sema-agent/core/dist/core/permission-rules.js
|
|
556866
556989
|
var init_permission_rules = __esm({
|
|
556867
556990
|
"node_modules/@sema-agent/core/dist/core/permission-rules.js"() {
|
|
@@ -557231,6 +557354,7 @@ var init_dist9 = __esm({
|
|
|
557231
557354
|
init_background_shell();
|
|
557232
557355
|
init_scheduler();
|
|
557233
557356
|
init_scheduler_tools();
|
|
557357
|
+
init_loop_tick();
|
|
557234
557358
|
init_tighten_task_spec();
|
|
557235
557359
|
init_tool_policy();
|
|
557236
557360
|
init_auto_mode();
|
|
@@ -628841,8 +628965,19 @@ __export(liveInitToolFace_exports, {
|
|
|
628841
628965
|
ENGINE_SCENARIO_EXTRAS_DEFAULT: () => ENGINE_SCENARIO_EXTRAS_DEFAULT,
|
|
628842
628966
|
_resetLiveInitToolFaceForTest: () => _resetLiveInitToolFaceForTest,
|
|
628843
628967
|
probeScenarioTools: () => probeScenarioTools,
|
|
628844
|
-
resolveLiveInitToolFace: () => resolveLiveInitToolFace
|
|
628968
|
+
resolveLiveInitToolFace: () => resolveLiveInitToolFace,
|
|
628969
|
+
runnerFaceForEnv: () => runnerFaceForEnv
|
|
628845
628970
|
});
|
|
628971
|
+
function runnerFaceForEnv(env5) {
|
|
628972
|
+
let face = [...ENGINE_RUNNER_FACE];
|
|
628973
|
+
if (env5.SCHEDULER_ENABLED === "false") {
|
|
628974
|
+
face = face.filter((n2) => !["CronCreate", "CronDelete", "CronList", "ScheduleWakeup"].includes(n2));
|
|
628975
|
+
}
|
|
628976
|
+
if (env5.SELF_ORCHESTRATION_ENABLED === "false") {
|
|
628977
|
+
face = face.filter((n2) => n2 !== "Workflow");
|
|
628978
|
+
}
|
|
628979
|
+
return face;
|
|
628980
|
+
}
|
|
628846
628981
|
function _resetLiveInitToolFaceForTest() {
|
|
628847
628982
|
cached4 = null;
|
|
628848
628983
|
}
|
|
@@ -628896,7 +629031,7 @@ async function resolveLiveInitToolFace(argv, env5, opts) {
|
|
|
628896
629031
|
...askUserQuestion ? ["AskUserQuestion"] : [],
|
|
628897
629032
|
...webSearch ? ["WebSearch"] : []
|
|
628898
629033
|
];
|
|
628899
|
-
const key = `${baseUrl}::${scenario2 ?? ""}::${askUserQuestion ? "q" : ""}${webSearch ? "w" : ""}`;
|
|
629034
|
+
const key = `${baseUrl}::${scenario2 ?? ""}::${askUserQuestion ? "q" : ""}${webSearch ? "w" : ""}::${env5.SCHEDULER_ENABLED === "false" ? "ns" : ""}${env5.SELF_ORCHESTRATION_ENABLED === "false" ? "nw" : ""}`;
|
|
628900
629035
|
if (cached4 && cached4.key === key) return cached4.face;
|
|
628901
629036
|
let names;
|
|
628902
629037
|
let source = "wire-vocabulary";
|
|
@@ -628916,7 +629051,7 @@ async function resolveLiveInitToolFace(argv, env5, opts) {
|
|
|
628916
629051
|
});
|
|
628917
629052
|
if (probed) {
|
|
628918
629053
|
const handsBand = probed.toolset === "full-body" ? ENGINE_HANDS_BAND : [];
|
|
628919
|
-
names = [.../* @__PURE__ */ new Set([...probed.tools, ...handsBand, ...
|
|
629054
|
+
names = [.../* @__PURE__ */ new Set([...probed.tools, ...handsBand, ...runnerFaceForEnv(env5), ...knobTools])];
|
|
628920
629055
|
source = "scenario-probe";
|
|
628921
629056
|
if (env5.SEMA_DEBUG) {
|
|
628922
629057
|
console.error(
|
|
@@ -628924,7 +629059,7 @@ async function resolveLiveInitToolFace(argv, env5, opts) {
|
|
|
628924
629059
|
);
|
|
628925
629060
|
}
|
|
628926
629061
|
} else {
|
|
628927
|
-
names = [...ENGINE_HANDS_BAND, ...ENGINE_SCENARIO_EXTRAS_DEFAULT, ...
|
|
629062
|
+
names = [...ENGINE_HANDS_BAND, ...ENGINE_SCENARIO_EXTRAS_DEFAULT, ...runnerFaceForEnv(env5), ...knobTools];
|
|
628928
629063
|
if (env5.SEMA_DEBUG) {
|
|
628929
629064
|
console.error(
|
|
628930
629065
|
`[sema] init tool face: scenario "${scenario2}" detail probe unavailable \u2014 falling back to the default wire vocabulary (may not match this scenario's roster)`
|
|
@@ -628932,7 +629067,7 @@ async function resolveLiveInitToolFace(argv, env5, opts) {
|
|
|
628932
629067
|
}
|
|
628933
629068
|
}
|
|
628934
629069
|
} else {
|
|
628935
|
-
names = [...ENGINE_HANDS_BAND, ...ENGINE_SCENARIO_EXTRAS_DEFAULT, ...
|
|
629070
|
+
names = [...ENGINE_HANDS_BAND, ...ENGINE_SCENARIO_EXTRAS_DEFAULT, ...runnerFaceForEnv(env5), ...knobTools];
|
|
628936
629071
|
}
|
|
628937
629072
|
const face = { tools: names.map((name) => ({ name })), source };
|
|
628938
629073
|
cached4 = { key, face };
|
|
@@ -629393,6 +629528,10 @@ async function* ask(params) {
|
|
|
629393
629528
|
if (selfOrchestration && process.env.SEMA_DEBUG) {
|
|
629394
629529
|
console.error("[sema] print-mode ask: selfOrchestration wire \u2192 TaskRequest.selfOrchestration=true (run_workflow)");
|
|
629395
629530
|
}
|
|
629531
|
+
const retainBackground = process.env.SEMA_LIVE_BASEURL ? retainBackgroundFromEnv() : void 0;
|
|
629532
|
+
if (retainBackground && process.env.SEMA_DEBUG) {
|
|
629533
|
+
console.error("[sema] print-mode ask: retainBackground wire \u2192 TaskRequest.retainBackgroundProcesses=true");
|
|
629534
|
+
}
|
|
629396
629535
|
const attachments = process.env.SEMA_LIVE_BASEURL ? attachmentsForRequest() : void 0;
|
|
629397
629536
|
if (attachments && process.env.SEMA_DEBUG) {
|
|
629398
629537
|
console.error(`[sema] print-mode ask: attachments wire \u2192 TaskRequest.attachments (${Object.keys(attachments).join("+")})`);
|
|
@@ -629584,6 +629723,7 @@ async function* ask(params) {
|
|
|
629584
629723
|
...interactiveToolsField.interactiveTools === false ? { interactiveTools: false } : {},
|
|
629585
629724
|
...webSearch || wireHooks ? { settings: { ...webSearch ? { webSearch } : {}, ...wireHooks ? { hooks: wireHooks } : {} } } : {},
|
|
629586
629725
|
...selfOrchestration ? { selfOrchestration } : {},
|
|
629726
|
+
...retainBackground ? { retainBackgroundProcesses: retainBackground } : {},
|
|
629587
629727
|
...enableFork !== void 0 ? { enableFork } : {},
|
|
629588
629728
|
...attachments ? { attachments } : {},
|
|
629589
629729
|
...skillsMcpFields
|
|
@@ -629774,6 +629914,7 @@ var init_seamQueryEngine = __esm({
|
|
|
629774
629914
|
init_mockClient();
|
|
629775
629915
|
init_webSearchWireCaps();
|
|
629776
629916
|
init_selfOrchestrationWireCaps();
|
|
629917
|
+
init_retainBackgroundWireCaps();
|
|
629777
629918
|
init_forkWireCaps();
|
|
629778
629919
|
init_attachmentsWireCaps();
|
|
629779
629920
|
init_hooksWireCaps();
|
|
@@ -640435,6 +640576,7 @@ async function ensurePrintModeEngine() {
|
|
|
640435
640576
|
async function ensureLocalEngineOneShot(label = "one-shot") {
|
|
640436
640577
|
seedUserSettingsEnv();
|
|
640437
640578
|
process.env.SCHEDULER_SESSION_WAKEUP ??= "false";
|
|
640579
|
+
process.env.SCHEDULER_ENABLED ??= "false";
|
|
640438
640580
|
try {
|
|
640439
640581
|
const { applyPersistedTlsTrust: applyPersistedTlsTrust2 } = await Promise.resolve().then(() => (init_tlsTrust(), tlsTrust_exports));
|
|
640440
640582
|
await applyPersistedTlsTrust2();
|
|
@@ -653687,7 +653829,7 @@ Auth: unix socket -R \u2192 local proxy`, "info");
|
|
|
653687
653829
|
pendingHookMessages
|
|
653688
653830
|
}, renderAndRun);
|
|
653689
653831
|
}
|
|
653690
|
-
}).version("sema 1.0.
|
|
653832
|
+
}).version("sema 1.0.15", "-v, --version", "Output the version number");
|
|
653691
653833
|
program2.option("-w, --worktree [name]", "Create a new git worktree for this session (optionally specify a name)");
|
|
653692
653834
|
program2.option("--tmux", "Create a tmux session for the worktree (requires --worktree). Uses iTerm2 native panes when available; use --tmux=classic for traditional tmux.");
|
|
653693
653835
|
if (canUserConfigureAdvisor()) {
|
|
@@ -657618,8 +657760,18 @@ function effectiveFirePrompt(fire) {
|
|
|
657618
657760
|
substituted: true
|
|
657619
657761
|
};
|
|
657620
657762
|
}
|
|
657763
|
+
function makeSentinelResolver() {
|
|
657764
|
+
const ticked = /* @__PURE__ */ new Set();
|
|
657765
|
+
return (prompt, recordId) => {
|
|
657766
|
+
const firstTick = !ticked.has(recordId);
|
|
657767
|
+
const resolved = resolveAutonomousLoopPrompt(prompt, { firstTick });
|
|
657768
|
+
if (resolved !== null) ticked.add(recordId);
|
|
657769
|
+
return resolved ?? prompt;
|
|
657770
|
+
};
|
|
657771
|
+
}
|
|
657621
657772
|
var init_firePrompt = __esm({
|
|
657622
657773
|
"build-src/src/sema/scheduler/firePrompt.ts"() {
|
|
657774
|
+
init_dist9();
|
|
657623
657775
|
}
|
|
657624
657776
|
});
|
|
657625
657777
|
|
|
@@ -657858,8 +658010,10 @@ function wireSchedulerSessionLifecycle(opts = {}) {
|
|
|
657858
658010
|
};
|
|
657859
658011
|
}
|
|
657860
658012
|
function submitViaQueue(onWarn) {
|
|
658013
|
+
const resolveSentinel = makeSentinelResolver();
|
|
657861
658014
|
return async (fire) => {
|
|
657862
|
-
const { prompt, substituted } = effectiveFirePrompt(fire);
|
|
658015
|
+
const { prompt: rawPrompt, substituted } = effectiveFirePrompt(fire);
|
|
658016
|
+
const prompt = resolveSentinel(rawPrompt, fire.recordId);
|
|
657863
658017
|
if (substituted) {
|
|
657864
658018
|
onWarn?.(`scheduler: record ${fire.recordId} fired with an EMPTY prompt \u2014 substituted a placeholder (never inject empty user content)`);
|
|
657865
658019
|
}
|