@codeagentswarm/cas-cloud 0.0.15 → 0.0.17
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/dist/antigravity-mcp-launcher.js +42 -14
- package/dist/cas.js +514 -191
- package/dist/mcp-stdio-server.js +42 -14
- package/dist/templates/antigravity-md-titles-section.md +3 -3
- package/dist/templates/codex-md-titles-section.md +3 -3
- package/dist/templates/grok-md-titles-section.md +16 -19
- package/dist/templates/kimi-md-titles-section.md +11 -12
- package/dist/templates/opencode-md-titles-section.md +3 -3
- package/package.json +1 -1
package/dist/cas.js
CHANGED
|
@@ -101,12 +101,11 @@ var require_provider_login = __commonJS({
|
|
|
101
101
|
verified: "2026-08-10 \xB7 opencode 1.18.11"
|
|
102
102
|
},
|
|
103
103
|
kimi: {
|
|
104
|
-
mode: LOGIN_MODES.
|
|
104
|
+
mode: LOGIN_MODES.CLI,
|
|
105
105
|
label: "Kimi Code",
|
|
106
106
|
command: ["kimi", "login"],
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
verified: null
|
|
107
|
+
acceptsCode: false,
|
|
108
|
+
verified: "2026-09-04 \xB7 kimi 0.36.1; device flow captured on 0.38.0"
|
|
110
109
|
},
|
|
111
110
|
antigravity: {
|
|
112
111
|
mode: LOGIN_MODES.UNAVAILABLE,
|
|
@@ -128,6 +127,16 @@ var require_provider_login = __commonJS({
|
|
|
128
127
|
function canLoginFromChat(agent) {
|
|
129
128
|
return loginStrategyForAgent(agent).mode === LOGIN_MODES.CLI;
|
|
130
129
|
}
|
|
130
|
+
function loginStrategyForRemoteAgent(agent) {
|
|
131
|
+
const strategy = loginStrategyForAgent(agent);
|
|
132
|
+
if (agent === "codex") return { ...strategy, command: ["codex", "login", "--device-auth"] };
|
|
133
|
+
if (strategy.mode !== LOGIN_MODES.CLI) return {
|
|
134
|
+
...strategy,
|
|
135
|
+
terminalHint: null,
|
|
136
|
+
reason: `${strategy.reason || ""} Complete sign-in on the remote computer.`
|
|
137
|
+
};
|
|
138
|
+
return strategy;
|
|
139
|
+
}
|
|
131
140
|
function canSwitchAccount(agent) {
|
|
132
141
|
const strategy = loginStrategyForAgent(agent);
|
|
133
142
|
return strategy.mode === LOGIN_MODES.CLI && Array.isArray(strategy.logoutCommand) && strategy.logoutCommand.length > 0 && Array.isArray(strategy.statusCommand) && strategy.statusCommand.length > 0;
|
|
@@ -143,6 +152,7 @@ var require_provider_login = __commonJS({
|
|
|
143
152
|
LOGIN_MODES,
|
|
144
153
|
PROVIDER_LOGIN,
|
|
145
154
|
loginStrategyForAgent,
|
|
155
|
+
loginStrategyForRemoteAgent,
|
|
146
156
|
canLoginFromChat,
|
|
147
157
|
canSwitchAccount,
|
|
148
158
|
loginCommandLine,
|
|
@@ -616,6 +626,7 @@ var require_provider_login_manager = __commonJS({
|
|
|
616
626
|
"src/infrastructure/agent-drivers/provider-login-manager.js"(exports2, module2) {
|
|
617
627
|
var EventEmitter = require("events");
|
|
618
628
|
var { spawn } = require("child_process");
|
|
629
|
+
var { randomUUID } = require("crypto");
|
|
619
630
|
var { LOGIN_MODES, loginStrategyForAgent } = require_provider_login();
|
|
620
631
|
var { isNativeExe, quoteForCmd } = require_windows_direct_spawn();
|
|
621
632
|
var DEFAULT_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
@@ -640,7 +651,6 @@ var require_provider_login_manager = __commonJS({
|
|
|
640
651
|
this._resolveBinary = resolveBinary || (() => null);
|
|
641
652
|
this._resolveStrategy = resolveStrategy || loginStrategyForAgent;
|
|
642
653
|
this._timeoutMs = timeoutMs || DEFAULT_TIMEOUT_MS;
|
|
643
|
-
this._nextId = 0;
|
|
644
654
|
this._flows = /* @__PURE__ */ new Map();
|
|
645
655
|
this._registry = spawnFn ? null : safeRequireRegistry();
|
|
646
656
|
}
|
|
@@ -665,7 +675,7 @@ var require_provider_login_manager = __commonJS({
|
|
|
665
675
|
if (replaceAccount) await this._logout(agent, strategy, env);
|
|
666
676
|
const [defaultBinary, ...args] = strategy.command;
|
|
667
677
|
const binary = await this._resolveBinary({ agent }) || defaultBinary;
|
|
668
|
-
const loginId = `login-${
|
|
678
|
+
const loginId = `login-${randomUUID()}`;
|
|
669
679
|
const child = this._spawnCommand(binary, args, {
|
|
670
680
|
env,
|
|
671
681
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -13947,8 +13957,7 @@ var require_headless_provider_service = __commonJS({
|
|
|
13947
13957
|
var { ProviderLoginManager } = require_provider_login_manager();
|
|
13948
13958
|
var {
|
|
13949
13959
|
canSwitchAccount,
|
|
13950
|
-
|
|
13951
|
-
terminalLoginHint
|
|
13960
|
+
loginStrategyForRemoteAgent: headlessLoginStrategy
|
|
13952
13961
|
} = require_provider_login();
|
|
13953
13962
|
var { initializeCliAgentRegistry } = require_cli_agent_registry_bootstrap();
|
|
13954
13963
|
var AGENT_IDS = Object.freeze(["claude", "codex", "antigravity", "opencode", "kimi", "grok", "cursor"]);
|
|
@@ -13989,16 +13998,12 @@ ${stderr || ""}`.trim() });
|
|
|
13989
13998
|
acceptsCode: strategy.acceptsCode === true,
|
|
13990
13999
|
codeHint: String(strategy.codeHint || "").slice(0, 200),
|
|
13991
14000
|
command: Array.isArray(strategy.command) ? strategy.command.join(" ").slice(0, 300) : null,
|
|
13992
|
-
terminalHint:
|
|
14001
|
+
terminalHint: strategy.terminalHint || null,
|
|
13993
14002
|
reason: String(strategy.reason || "").slice(0, 500),
|
|
13994
14003
|
canSwitchAccount: false,
|
|
13995
14004
|
status
|
|
13996
14005
|
};
|
|
13997
14006
|
}
|
|
13998
|
-
function headlessLoginStrategy(agent) {
|
|
13999
|
-
const strategy = loginStrategyForAgent(agent);
|
|
14000
|
-
return agent === "codex" ? { ...strategy, command: ["codex", "login", "--device-auth"] } : strategy;
|
|
14001
|
-
}
|
|
14002
14007
|
var HeadlessProviderService = class extends EventEmitter {
|
|
14003
14008
|
constructor({ registry, env = process.env, fsImpl = fs, execFileImpl = execFile, loginManager } = {}) {
|
|
14004
14009
|
super();
|
|
@@ -14790,33 +14795,30 @@ CodeAgentSwarm shows two different things per agent:
|
|
|
14790
14795
|
the context stays clear at a glance \u2014 name the feature, NOT a low-level step or file,
|
|
14791
14796
|
and NOT a work PHASE (testing, e2e, validating, reviewing, deploying). Running the e2e
|
|
14792
14797
|
suite for a settings redesign is titled "Settings Redesign", never "Settings E2E Tests".
|
|
14793
|
-
|
|
14794
|
-
and it
|
|
14795
|
-
|
|
14798
|
+
Derive it from the **first user request** that established this conversation's
|
|
14799
|
+
functionality and set it ONCE per conversation. It stays stable across follow-ups,
|
|
14800
|
+
new turns, tasks, reviews, tests, validation, finishing, and context compaction.
|
|
14796
14801
|
2. **Current activity** = the product-focused step you are doing RIGHT NOW. Example:
|
|
14797
14802
|
"Implementing the analytics tracking backend". It is shown only when the user hovers
|
|
14798
14803
|
the agent, and it accumulates as the activity log behind the clock button.
|
|
14799
14804
|
|
|
14800
14805
|
## \u{1F4E2} THE RULE
|
|
14801
14806
|
|
|
14802
|
-
**\u{1F6A6} FIRST ACTION
|
|
14803
|
-
|
|
14804
|
-
the user manually renamed the agent the app keeps their name (a manual rename always wins
|
|
14805
|
-
over an MCP title). Never leave an agent with no meaningful title.
|
|
14807
|
+
**\u{1F6A6} FIRST ACTION in a new conversation:** set the GENERAL title from the first user
|
|
14808
|
+
request. On later turns, do NOT call \`set_terminal_title\`; update activity instead.
|
|
14806
14809
|
|
|
14807
14810
|
**\u{1F4CD} ALWAYS leave a CURRENT SUMMARY before acting.** Right after the title, call
|
|
14808
14811
|
\`update_terminal_activity\` with your first product-focused step, BEFORE running any other
|
|
14809
14812
|
tool. If an agent has no activity yet, set one before you do anything else \u2014 so at every
|
|
14810
14813
|
moment the user can see what each agent is doing. Never start working with no activity set.
|
|
14811
14814
|
|
|
14812
|
-
**
|
|
14815
|
+
**First request \u2192 set the title ONCE. Every turn \u2192 update the ACTIVITY.**
|
|
14813
14816
|
|
|
14814
|
-
- \u2705
|
|
14815
|
-
|
|
14816
|
-
expands the feature), or to REPLACE it when the topic changes RADICALLY.
|
|
14817
|
+
- \u2705 Keep the title from the first user request. Refining, extending, fixing, reviewing,
|
|
14818
|
+
validating, or finishing that request changes the activity, not the title.
|
|
14817
14819
|
- \u2705 RADICAL topic change \u2192 NEW general title, MANDATORY. When the user switches this
|
|
14818
14820
|
agent to a completely different topic (e.g. from "Minimize Agents" to preparing
|
|
14819
|
-
a release), call \`set_terminal_title\` again with
|
|
14821
|
+
a release), call \`set_terminal_title\` again with \`replace_existing=true\`. Updating only the
|
|
14820
14822
|
activity and leaving the old title is WRONG: the tab would keep describing work that
|
|
14821
14823
|
is no longer happening.
|
|
14822
14824
|
- \u2705 Update the activity every time your focus moves to a new step. This is what the user
|
|
@@ -14830,7 +14832,7 @@ the app's own static UI stays in English; these agent-written labels follow the
|
|
|
14830
14832
|
|
|
14831
14833
|
**\u{1F527} THE TWO TOOLS:**
|
|
14832
14834
|
\`\`\`
|
|
14833
|
-
# 1) ONCE
|
|
14835
|
+
# 1) ONCE on the conversation's first request - the sticky tab title
|
|
14834
14836
|
mcp__codeagentswarm-tasks__set_terminal_title(
|
|
14835
14837
|
title="Promo Video",
|
|
14836
14838
|
long_title="Promotional video for the Twitter launch"
|
|
@@ -14851,9 +14853,8 @@ mcp__codeagentswarm-tasks__update_terminal_activity(
|
|
|
14851
14853
|
in the tab. \`long_title\` is the **GOAL**: one sentence on what this agent is FOR \u2014 the
|
|
14852
14854
|
outcome the work aims at, not the step you are on. The user reads it in the hover under
|
|
14853
14855
|
the title, labelled GOAL, and it is the ONLY place that answers "why does this agent
|
|
14854
|
-
exist"; six words cannot carry that.
|
|
14855
|
-
|
|
14856
|
-
single step here.
|
|
14856
|
+
exist"; six words cannot carry that. Repeated calls preserve the first title. Pass
|
|
14857
|
+
\`replace_existing=true\` only after the user pivots to completely different functionality.
|
|
14857
14858
|
\`\`\`
|
|
14858
14859
|
\u2705 title="Orden notificaci\xF3n"
|
|
14859
14860
|
long_title="Que las notificaciones no salgan antes de que cambie el status del agente"
|
|
@@ -14879,7 +14880,7 @@ mcp__codeagentswarm-tasks__update_terminal_activity(
|
|
|
14879
14880
|
1. find_related_active_tasks(...) \u2190 Check first
|
|
14880
14881
|
2. create_task(...) \u2190 If needed
|
|
14881
14882
|
3. start_task(task_id=123)
|
|
14882
|
-
4. set_terminal_title( \u2190
|
|
14883
|
+
4. set_terminal_title( \u2190 only if this conversation has no title
|
|
14883
14884
|
title="Minimize Agents",
|
|
14884
14885
|
long_title="Add the ability to minimize and restore agents"
|
|
14885
14886
|
)
|
|
@@ -14888,7 +14889,7 @@ mcp__codeagentswarm-tasks__update_terminal_activity(
|
|
|
14888
14889
|
7. ...keep calling update_terminal_activity as your focus moves to new steps...
|
|
14889
14890
|
\`\`\`
|
|
14890
14891
|
|
|
14891
|
-
**\u{1F6A8} CRITICAL:**
|
|
14892
|
+
**\u{1F6A8} CRITICAL:** starting another task in the same conversation does not justify retitling it.
|
|
14892
14893
|
|
|
14893
14894
|
### \u2705 WITHOUT A TASK (research/investigation):
|
|
14894
14895
|
\`\`\`
|
|
@@ -14907,13 +14908,10 @@ update_terminal_activity(activity="Implementing restore-from-minimized")
|
|
|
14907
14908
|
update_terminal_activity(activity="Persisting minimized state across restarts")
|
|
14908
14909
|
\`\`\`
|
|
14909
14910
|
|
|
14910
|
-
### \u2705 THE GOAL
|
|
14911
|
+
### \u2705 THE ORIGINAL GOAL EXPANDS \u2192 keep the title and update ACTIVITY:
|
|
14911
14912
|
\`\`\`
|
|
14912
|
-
# The user expanded the feature
|
|
14913
|
-
|
|
14914
|
-
title="Minimize & Restore",
|
|
14915
|
-
long_title="Minimize agents and restore them later from a tray"
|
|
14916
|
-
)
|
|
14913
|
+
# The user expanded the same feature; the first title remains "Minimize Agents":
|
|
14914
|
+
update_terminal_activity(activity="Adding restore from the tray")
|
|
14917
14915
|
\`\`\`
|
|
14918
14916
|
|
|
14919
14917
|
### \u2705 RADICAL TOPIC CHANGE \u2192 set a NEW general title (mandatory):
|
|
@@ -14922,7 +14920,8 @@ set_terminal_title(
|
|
|
14922
14920
|
User: "leave that, now let's prepare the release notes"
|
|
14923
14921
|
set_terminal_title(
|
|
14924
14922
|
title="Release Notes",
|
|
14925
|
-
long_title="Preparing the release notes for the next version"
|
|
14923
|
+
long_title="Preparing the release notes for the next version",
|
|
14924
|
+
replace_existing=true
|
|
14926
14925
|
)
|
|
14927
14926
|
update_terminal_activity(activity="Drafting the release notes")
|
|
14928
14927
|
# \u274C WRONG: calling only update_terminal_activity here \u2014 the tab would still
|
|
@@ -14931,9 +14930,8 @@ update_terminal_activity(activity="Drafting the release notes")
|
|
|
14931
14930
|
|
|
14932
14931
|
## \u26A0\uFE0F WHEN TO USE WHICH
|
|
14933
14932
|
|
|
14934
|
-
- **General title (set_terminal_title):** once
|
|
14935
|
-
|
|
14936
|
-
session \u2014 but NEVER leave a stale title on an agent that moved to another topic.
|
|
14933
|
+
- **General title (set_terminal_title):** once per conversation from the first request.
|
|
14934
|
+
Replace only after a radical functionality pivot, with \`replace_existing=true\`.
|
|
14937
14935
|
- **Current activity (update_terminal_activity):** every time you move to a new product
|
|
14938
14936
|
step. Call it freely - it never disturbs the tab.
|
|
14939
14937
|
|
|
@@ -15011,14 +15009,14 @@ update_terminal_activity(activity="Investigating the output handler cost") \u
|
|
|
15011
15009
|
**Bad 3 - Never setting a general title:**
|
|
15012
15010
|
\`\`\`
|
|
15013
15011
|
# Only calling update_terminal_activity, so the tab never gets a product label.
|
|
15014
|
-
\u2705
|
|
15012
|
+
\u2705 Set the title ONCE from the first user request so the tab is meaningful.
|
|
15015
15013
|
\`\`\`
|
|
15016
15014
|
|
|
15017
15015
|
**Bad 4 - Radical topic change but the title never changes:**
|
|
15018
15016
|
\`\`\`
|
|
15019
15017
|
# Title: "Promo Video". The user then says: "now let's debug the login crash"
|
|
15020
15018
|
update_terminal_activity(activity="Debugging the login crash") \u2190 \u274C tab still says "Promo Video"
|
|
15021
|
-
\u2705 set_terminal_title(title="Login Crash", long_title="Debugging the crash when logging in")
|
|
15019
|
+
\u2705 set_terminal_title(title="Login Crash", long_title="Debugging the crash when logging in", replace_existing=true)
|
|
15022
15020
|
\u2705 update_terminal_activity(activity="Reproducing the login crash")
|
|
15023
15021
|
\`\`\`
|
|
15024
15022
|
|
|
@@ -15059,22 +15057,21 @@ Rules:
|
|
|
15059
15057
|
|
|
15060
15058
|
` : ""}## \u{1F6A8} FINAL REMINDER
|
|
15061
15059
|
|
|
15062
|
-
- Set the **general title AND
|
|
15063
|
-
|
|
15064
|
-
radically \u2014 never leave a stale title.
|
|
15060
|
+
- Set the **general title AND GOAL once per conversation**, from the first user request.
|
|
15061
|
+
Follow-ups never retitle; a radical functionality pivot uses \`replace_existing=true\`.
|
|
15065
15062
|
- Keep the **current activity** flowing with \`update_terminal_activity\` (product-level),
|
|
15066
15063
|
one short sentence per step.
|
|
15067
15064
|
${includeStatus ? `- Keep the **status badge** honest with \`set_terminal_status\` at every phase change.
|
|
15068
15065
|
` : ""}- The tab should stay stable; the hover + clock-button log carry the detail.
|
|
15069
15066
|
|
|
15070
15067
|
**MEMORIZE:**
|
|
15071
|
-
${includeStatus ? `1. **
|
|
15068
|
+
${includeStatus ? `1. **First request \u2192 \`set_terminal_title(title, long_title)\` once + \`set_terminal_status(status="working")\`**
|
|
15072
15069
|
2. **New step \u2192 \`update_terminal_activity\` (product step)**
|
|
15073
15070
|
3. **Phase changed (waiting / testing / done) \u2192 \`set_terminal_status\`**
|
|
15074
|
-
4. **
|
|
15075
|
-
5. **\u{1F3C1} Finishing \u2192 final \`update_terminal_activity\` summary + \`set_terminal_status\` \u2192 \`complete_task\`**` : `1. **
|
|
15071
|
+
4. **Radical functionality pivot \u2192 \`set_terminal_title(..., replace_existing=true)\`**
|
|
15072
|
+
5. **\u{1F3C1} Finishing \u2192 final \`update_terminal_activity\` summary + \`set_terminal_status\` \u2192 \`complete_task\`**` : `1. **First request \u2192 \`set_terminal_title(title, long_title)\` once**
|
|
15076
15073
|
2. **New step \u2192 \`update_terminal_activity\` (product step)**
|
|
15077
|
-
3. **
|
|
15074
|
+
3. **Radical functionality pivot \u2192 \`set_terminal_title(..., replace_existing=true)\`**
|
|
15078
15075
|
4. **\u{1F3C1} Finishing \u2192 final \`update_terminal_activity\` summary \u2192 \`complete_task\`**`}
|
|
15079
15076
|
|
|
15080
15077
|
### \u{1F4DD} Task Plan Management
|
|
@@ -15322,8 +15319,9 @@ Avoid token limits:
|
|
|
15322
15319
|
- Creating new? \u2192 YES
|
|
15323
15320
|
|
|
15324
15321
|
**Agent Title?**
|
|
15325
|
-
-
|
|
15326
|
-
-
|
|
15322
|
+
- Set it from the first user request, once per conversation
|
|
15323
|
+
- Follow-up work changes activity, never the title
|
|
15324
|
+
- Radical functionality pivot \u2192 replace with \`replace_existing=true\`
|
|
15327
15325
|
|
|
15328
15326
|
**Task Continuation?**
|
|
15329
15327
|
- Same work <24h \u2192 Continue
|
|
@@ -15364,33 +15362,30 @@ CodeAgentSwarm shows two different things per agent:
|
|
|
15364
15362
|
the context stays clear at a glance \u2014 name the feature, NOT a low-level step or file,
|
|
15365
15363
|
and NOT a work PHASE (testing, e2e, validating, reviewing, deploying). Running the e2e
|
|
15366
15364
|
suite for a settings redesign is titled "Settings Redesign", never "Settings E2E Tests".
|
|
15367
|
-
|
|
15368
|
-
and it
|
|
15369
|
-
|
|
15365
|
+
Derive it from the **first user request** that established this conversation's
|
|
15366
|
+
functionality and set it ONCE per conversation. It stays stable across follow-ups,
|
|
15367
|
+
new turns, tasks, reviews, tests, validation, finishing, and context compaction.
|
|
15370
15368
|
2. **Current activity** = the product-focused step you are doing RIGHT NOW. Example:
|
|
15371
15369
|
"Implementing the analytics tracking backend". It is shown only when the user hovers
|
|
15372
15370
|
the agent, and it accumulates as the activity log behind the clock button.
|
|
15373
15371
|
|
|
15374
15372
|
## \u{1F4E2} THE RULE
|
|
15375
15373
|
|
|
15376
|
-
**\u{1F6A6} FIRST ACTION
|
|
15377
|
-
|
|
15378
|
-
the user manually renamed the agent the app keeps their name (a manual rename always wins
|
|
15379
|
-
over an MCP title). Never leave an agent with no meaningful title.
|
|
15374
|
+
**\u{1F6A6} FIRST ACTION in a new conversation:** set the GENERAL title from the first user
|
|
15375
|
+
request. On later turns, do NOT call \`set_terminal_title\`; update activity instead.
|
|
15380
15376
|
|
|
15381
15377
|
**\u{1F4CD} ALWAYS leave a CURRENT SUMMARY before acting.** Right after the title, call
|
|
15382
15378
|
\`update_terminal_activity\` with your first product-focused step, BEFORE running any other
|
|
15383
15379
|
tool. If an agent has no activity yet, set one before you do anything else \u2014 so at every
|
|
15384
15380
|
moment the user can see what each agent is doing. Never start working with no activity set.
|
|
15385
15381
|
|
|
15386
|
-
**
|
|
15382
|
+
**First request \u2192 set the title ONCE. Every turn \u2192 update the ACTIVITY.**
|
|
15387
15383
|
|
|
15388
|
-
- \u2705
|
|
15389
|
-
|
|
15390
|
-
expands the feature), or to REPLACE it when the topic changes RADICALLY.
|
|
15384
|
+
- \u2705 Keep the title from the first user request. Refining, extending, fixing, reviewing,
|
|
15385
|
+
validating, or finishing that request changes the activity, not the title.
|
|
15391
15386
|
- \u2705 RADICAL topic change \u2192 NEW general title, MANDATORY. When the user switches this
|
|
15392
15387
|
agent to a completely different topic (e.g. from "Minimize Agents" to preparing
|
|
15393
|
-
a release), call \`set_terminal_title\` again with
|
|
15388
|
+
a release), call \`set_terminal_title\` again with \`replace_existing=true\`. Updating only the
|
|
15394
15389
|
activity and leaving the old title is WRONG: the tab would keep describing work that
|
|
15395
15390
|
is no longer happening.
|
|
15396
15391
|
- \u2705 Update the activity every time your focus moves to a new step. This is what the user
|
|
@@ -15404,7 +15399,7 @@ the app's own static UI stays in English; these agent-written labels follow the
|
|
|
15404
15399
|
|
|
15405
15400
|
**\u{1F527} THE TWO TOOLS:**
|
|
15406
15401
|
\`\`\`
|
|
15407
|
-
# 1) ONCE
|
|
15402
|
+
# 1) ONCE on the conversation's first request - the sticky tab title
|
|
15408
15403
|
mcp__codeagentswarm-tasks__set_terminal_title(
|
|
15409
15404
|
title="Promo Video",
|
|
15410
15405
|
long_title="Promotional video for the Twitter launch"
|
|
@@ -15425,9 +15420,8 @@ mcp__codeagentswarm-tasks__update_terminal_activity(
|
|
|
15425
15420
|
in the tab. \`long_title\` is the **GOAL**: one sentence on what this agent is FOR \u2014 the
|
|
15426
15421
|
outcome the work aims at, not the step you are on. The user reads it in the hover under
|
|
15427
15422
|
the title, labelled GOAL, and it is the ONLY place that answers "why does this agent
|
|
15428
|
-
exist"; six words cannot carry that.
|
|
15429
|
-
|
|
15430
|
-
single step here.
|
|
15423
|
+
exist"; six words cannot carry that. Repeated calls preserve the first title. Pass
|
|
15424
|
+
\`replace_existing=true\` only after the user pivots to completely different functionality.
|
|
15431
15425
|
\`\`\`
|
|
15432
15426
|
\u2705 title="Orden notificaci\xF3n"
|
|
15433
15427
|
long_title="Que las notificaciones no salgan antes de que cambie el status del agente"
|
|
@@ -15446,9 +15440,9 @@ mcp__codeagentswarm-tasks__update_terminal_activity(
|
|
|
15446
15440
|
|
|
15447
15441
|
## \u{1F3AF} WORKFLOW
|
|
15448
15442
|
|
|
15449
|
-
### \u2705
|
|
15443
|
+
### \u2705 ON THE CONVERSATION'S FIRST REQUEST:
|
|
15450
15444
|
\`\`\`
|
|
15451
|
-
1. set_terminal_title( \u2190
|
|
15445
|
+
1. set_terminal_title( \u2190 once per conversation
|
|
15452
15446
|
title="Minimize Agents",
|
|
15453
15447
|
long_title="Add the ability to minimize and restore agents"
|
|
15454
15448
|
)
|
|
@@ -15463,13 +15457,10 @@ update_terminal_activity(activity="Implementing restore-from-minimized")
|
|
|
15463
15457
|
update_terminal_activity(activity="Persisting minimized state across restarts")
|
|
15464
15458
|
\`\`\`
|
|
15465
15459
|
|
|
15466
|
-
### \u2705 THE GOAL
|
|
15460
|
+
### \u2705 THE ORIGINAL GOAL EXPANDS \u2192 keep the title and update ACTIVITY:
|
|
15467
15461
|
\`\`\`
|
|
15468
|
-
# The user expanded the feature
|
|
15469
|
-
|
|
15470
|
-
title="Minimize & Restore",
|
|
15471
|
-
long_title="Minimize agents and restore them later from a tray"
|
|
15472
|
-
)
|
|
15462
|
+
# The user expanded the same feature; the first title remains "Minimize Agents":
|
|
15463
|
+
update_terminal_activity(activity="Adding restore from the tray")
|
|
15473
15464
|
\`\`\`
|
|
15474
15465
|
|
|
15475
15466
|
### \u2705 RADICAL TOPIC CHANGE \u2192 set a NEW general title (mandatory):
|
|
@@ -15478,7 +15469,8 @@ set_terminal_title(
|
|
|
15478
15469
|
User: "leave that, now let's prepare the release notes"
|
|
15479
15470
|
set_terminal_title(
|
|
15480
15471
|
title="Release Notes",
|
|
15481
|
-
long_title="Preparing the release notes for the next version"
|
|
15472
|
+
long_title="Preparing the release notes for the next version",
|
|
15473
|
+
replace_existing=true
|
|
15482
15474
|
)
|
|
15483
15475
|
update_terminal_activity(activity="Drafting the release notes")
|
|
15484
15476
|
# \u274C WRONG: calling only update_terminal_activity here \u2014 the tab would still
|
|
@@ -15487,9 +15479,8 @@ update_terminal_activity(activity="Drafting the release notes")
|
|
|
15487
15479
|
|
|
15488
15480
|
## \u26A0\uFE0F WHEN TO USE WHICH
|
|
15489
15481
|
|
|
15490
|
-
- **General title (set_terminal_title):** once
|
|
15491
|
-
|
|
15492
|
-
session \u2014 but NEVER leave a stale title on an agent that moved to another topic.
|
|
15482
|
+
- **General title (set_terminal_title):** once per conversation from the first request.
|
|
15483
|
+
Replace only after a radical functionality pivot, with \`replace_existing=true\`.
|
|
15493
15484
|
- **Current activity (update_terminal_activity):** every time you move to a new product
|
|
15494
15485
|
step. Call it freely - it never disturbs the tab.
|
|
15495
15486
|
|
|
@@ -15565,14 +15556,14 @@ update_terminal_activity(activity="Investigating the output handler cost") \u
|
|
|
15565
15556
|
**Bad 3 - Never setting a general title:**
|
|
15566
15557
|
\`\`\`
|
|
15567
15558
|
# Only calling update_terminal_activity, so the tab never gets a product label.
|
|
15568
|
-
\u2705
|
|
15559
|
+
\u2705 Set the title ONCE from the first user request so the tab is meaningful.
|
|
15569
15560
|
\`\`\`
|
|
15570
15561
|
|
|
15571
15562
|
**Bad 4 - Radical topic change but the title never changes:**
|
|
15572
15563
|
\`\`\`
|
|
15573
15564
|
# Title: "Promo Video". The user then says: "now let's debug the login crash"
|
|
15574
15565
|
update_terminal_activity(activity="Debugging the login crash") \u2190 \u274C tab still says "Promo Video"
|
|
15575
|
-
\u2705 set_terminal_title(title="Login Crash", long_title="Debugging the crash when logging in")
|
|
15566
|
+
\u2705 set_terminal_title(title="Login Crash", long_title="Debugging the crash when logging in", replace_existing=true)
|
|
15576
15567
|
\u2705 update_terminal_activity(activity="Reproducing the login crash")
|
|
15577
15568
|
\`\`\`
|
|
15578
15569
|
|
|
@@ -15587,26 +15578,25 @@ set_terminal_title(title="Settings E2E Tests") \u2190 \u274C testing is a STEP
|
|
|
15587
15578
|
|
|
15588
15579
|
## \u{1F6A8} FINAL REMINDER
|
|
15589
15580
|
|
|
15590
|
-
- Set the **general title AND
|
|
15591
|
-
|
|
15592
|
-
radically \u2014 never leave a stale title.
|
|
15581
|
+
- Set the **general title AND GOAL once per conversation**, from the first user request.
|
|
15582
|
+
Follow-ups never retitle; a radical functionality pivot uses \`replace_existing=true\`.
|
|
15593
15583
|
- Keep the **current activity** flowing with \`update_terminal_activity\` (product-level),
|
|
15594
15584
|
one short sentence per step.
|
|
15595
15585
|
- The tab should stay stable; the hover + clock-button log carry the detail.
|
|
15596
15586
|
- Do NOT create or manage tasks \u2014 automatic task management is disabled.
|
|
15597
15587
|
|
|
15598
15588
|
**MEMORIZE:**
|
|
15599
|
-
1. **
|
|
15589
|
+
1. **First request \u2192 \`set_terminal_title(title, long_title)\` once**
|
|
15600
15590
|
2. **New step \u2192 \`update_terminal_activity\` (product step)**
|
|
15601
|
-
3. **
|
|
15591
|
+
3. **Radical functionality pivot \u2192 \`set_terminal_title(..., replace_existing=true)\`**
|
|
15602
15592
|
4. **\u{1F3C1} Finishing \u2192 final \`update_terminal_activity\` summary**
|
|
15603
15593
|
|
|
15604
15594
|
## Quick Decision Guide
|
|
15605
15595
|
|
|
15606
15596
|
**Agent Title?**
|
|
15607
|
-
-
|
|
15608
|
-
-
|
|
15609
|
-
- Radical
|
|
15597
|
+
- Set it from the first user request, once per conversation
|
|
15598
|
+
- Follow-up work changes activity, never the title
|
|
15599
|
+
- Radical functionality pivot \u2192 replace with \`replace_existing=true\`
|
|
15610
15600
|
|
|
15611
15601
|
**Tasks?**
|
|
15612
15602
|
- Automatic task management is DISABLED \u2014 never create or manage tasks
|
|
@@ -18774,7 +18764,8 @@ var require_session_communication_env = __commonJS({
|
|
|
18774
18764
|
// src/infrastructure/agent-drivers/provider-auth.js
|
|
18775
18765
|
var require_provider_auth = __commonJS({
|
|
18776
18766
|
"src/infrastructure/agent-drivers/provider-auth.js"(exports2, module2) {
|
|
18777
|
-
var { canLoginFromChat } = require_provider_login();
|
|
18767
|
+
var { canLoginFromChat, canSwitchAccount } = require_provider_login();
|
|
18768
|
+
var { isModelUsageLimitError } = require_provider_error_presentation();
|
|
18778
18769
|
var PROVIDER_AUTH = Object.freeze({
|
|
18779
18770
|
claude: {
|
|
18780
18771
|
label: "Claude Code",
|
|
@@ -18807,6 +18798,7 @@ var require_provider_auth = __commonJS({
|
|
|
18807
18798
|
});
|
|
18808
18799
|
var AUTH_ERROR_PATTERNS = Object.freeze([
|
|
18809
18800
|
/\bnot logged in\b/i,
|
|
18801
|
+
/\bnot signed in\b/i,
|
|
18810
18802
|
/\bnot authenticated\b/i,
|
|
18811
18803
|
/\bunauthenticated\b/i,
|
|
18812
18804
|
/\bauthentication required\b/i,
|
|
@@ -18909,6 +18901,16 @@ var require_provider_auth = __commonJS({
|
|
|
18909
18901
|
}
|
|
18910
18902
|
return createProviderUnavailableStatus(agent);
|
|
18911
18903
|
}
|
|
18904
|
+
function providerErrorLoginAction(agent, message) {
|
|
18905
|
+
const auth = classifyProviderAuthError(agent, message);
|
|
18906
|
+
const usageLimit = isModelUsageLimitError({ provider: agent, payload: { message } });
|
|
18907
|
+
if (!auth && !usageLimit) return null;
|
|
18908
|
+
const replaceAccount = (auth == null ? void 0 : auth.switchAccount) === true || usageLimit && canSwitchAccount(agent);
|
|
18909
|
+
return {
|
|
18910
|
+
action: replaceAccount ? "switch-account" : "start",
|
|
18911
|
+
label: replaceAccount ? "Change account" : canLoginFromChat(agent) ? "Sign in" : "Sign-in options"
|
|
18912
|
+
};
|
|
18913
|
+
}
|
|
18912
18914
|
function serializeProviderError(agent, error) {
|
|
18913
18915
|
const message = String(error && error.message ? error.message : error || "Provider error");
|
|
18914
18916
|
const providerStatus = classifyProviderStartupError(agent, error);
|
|
@@ -18930,6 +18932,7 @@ var require_provider_auth = __commonJS({
|
|
|
18930
18932
|
createProviderUnavailableStatus,
|
|
18931
18933
|
createUnauthenticatedStatus,
|
|
18932
18934
|
providerAuthMetadata,
|
|
18935
|
+
providerErrorLoginAction,
|
|
18933
18936
|
serializeProviderError
|
|
18934
18937
|
};
|
|
18935
18938
|
}
|
|
@@ -19169,7 +19172,6 @@ var require_codex_app_server_driver = __commonJS({
|
|
|
19169
19172
|
var DEFAULT_SERVICE_TIER_ID = "default";
|
|
19170
19173
|
var EPHEMERAL_CODEX_HOME_PREFIX = "codeagentswarm-codex-home-";
|
|
19171
19174
|
var EPHEMERAL_CODEX_HOME_MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
19172
|
-
var REQUIRED_TASK_MCP_TOOL = "check_active";
|
|
19173
19175
|
var TEXT_ONLY_INSTRUCTIONS = "Answer with plain text only. Do not call tools, commands, apps, skills, web search, MCP servers, or subagents.";
|
|
19174
19176
|
var IMAGE_ONLY_INSTRUCTIONS = "Generate exactly one image with the built-in image generation capability. Do not call commands, apps, skills, web search, MCP servers, subagents, or any other tool. Do not return prose.";
|
|
19175
19177
|
var TEXT_ONLY_CONFIG_OVERRIDES = Object.freeze([
|
|
@@ -19326,10 +19328,6 @@ var require_codex_app_server_driver = __commonJS({
|
|
|
19326
19328
|
* @param {{name: string, title: string, version: string}} [options.clientInfo]
|
|
19327
19329
|
* @param {number} [options.requestTimeoutMs=30000] Per-request timeout.
|
|
19328
19330
|
* @param {Function} [options.spawnFn] Injectable spawn, for tests.
|
|
19329
|
-
* @param {string} [options.requiredMcpServer] MCP server whose activation
|
|
19330
|
-
* check is repaired before the first turn when possible.
|
|
19331
|
-
* @param {Function} [options.repairMcpConfig] Repairs the on-disk MCP config
|
|
19332
|
-
* before the running app-server reloads it.
|
|
19333
19331
|
* @param {{register: Function, unregister: Function}} [options.processRegistry]
|
|
19334
19332
|
* PID registry the child is tracked in; injectable for tests.
|
|
19335
19333
|
*/
|
|
@@ -19339,9 +19337,7 @@ var require_codex_app_server_driver = __commonJS({
|
|
|
19339
19337
|
clientInfo,
|
|
19340
19338
|
requestTimeoutMs = DEFAULT_REQUEST_TIMEOUT_MS,
|
|
19341
19339
|
spawnFn,
|
|
19342
|
-
processRegistry
|
|
19343
|
-
requiredMcpServer,
|
|
19344
|
-
repairMcpConfig
|
|
19340
|
+
processRegistry
|
|
19345
19341
|
} = {}) {
|
|
19346
19342
|
super();
|
|
19347
19343
|
this._binaryPath = binaryPath;
|
|
@@ -19350,10 +19346,11 @@ var require_codex_app_server_driver = __commonJS({
|
|
|
19350
19346
|
this._requestTimeoutMs = requestTimeoutMs;
|
|
19351
19347
|
this._spawnFn = spawnFn || spawn;
|
|
19352
19348
|
this._processRegistry = processRegistry || require_spawned_process_registry();
|
|
19353
|
-
this._requiredMcpServer = requiredMcpServer || null;
|
|
19354
|
-
this._repairMcpConfig = repairMcpConfig || null;
|
|
19355
19349
|
this._child = null;
|
|
19356
19350
|
this._pendingRequests = /* @__PURE__ */ new Map();
|
|
19351
|
+
this._taskMcpStartup = null;
|
|
19352
|
+
this._taskMcpWaiters = /* @__PURE__ */ new Set();
|
|
19353
|
+
this._inputInterruptVersion = 0;
|
|
19357
19354
|
this._pendingApprovals = /* @__PURE__ */ new Map();
|
|
19358
19355
|
this._pendingQuestions = /* @__PURE__ */ new Map();
|
|
19359
19356
|
this._nextRequestId = 1;
|
|
@@ -19488,6 +19485,10 @@ var require_codex_app_server_driver = __commonJS({
|
|
|
19488
19485
|
});
|
|
19489
19486
|
return { turnId: activeTurnId, steered: true };
|
|
19490
19487
|
}
|
|
19488
|
+
const interruptVersion = this._inputInterruptVersion;
|
|
19489
|
+
await this._waitForTaskMcp();
|
|
19490
|
+
if (interruptVersion !== this._inputInterruptVersion) throw new Error("CodeAgentSwarm message cancelled while tools were starting.");
|
|
19491
|
+
if (this._stopping || this._exited) throw new Error("Codex session stopped");
|
|
19491
19492
|
const result = await this._request("turn/start", {
|
|
19492
19493
|
threadId: this._threadId,
|
|
19493
19494
|
input,
|
|
@@ -19496,6 +19497,35 @@ var require_codex_app_server_driver = __commonJS({
|
|
|
19496
19497
|
this._activeTurnId = (_a = result == null ? void 0 : result.turn) == null ? void 0 : _a.id;
|
|
19497
19498
|
return { turnId: this._activeTurnId };
|
|
19498
19499
|
}
|
|
19500
|
+
async _waitForTaskMcp() {
|
|
19501
|
+
var _a;
|
|
19502
|
+
if (!this._taskMcpStartup) {
|
|
19503
|
+
const { config } = await this._request("config/read", { cwd: this._sessionCwd, includeLayers: false });
|
|
19504
|
+
const server = (_a = config == null ? void 0 : config.mcp_servers) == null ? void 0 : _a["codeagentswarm-tasks"];
|
|
19505
|
+
this._taskMcpStartup ||= {
|
|
19506
|
+
threadId: this._threadId,
|
|
19507
|
+
status: server && server.enabled !== false ? "starting" : "ready"
|
|
19508
|
+
};
|
|
19509
|
+
}
|
|
19510
|
+
if (this._taskMcpStartup.threadId !== this._threadId) return;
|
|
19511
|
+
if (this._taskMcpStartup.status === "starting") {
|
|
19512
|
+
await new Promise((resolve, reject) => {
|
|
19513
|
+
const finish = (error) => {
|
|
19514
|
+
clearTimeout(timer);
|
|
19515
|
+
this._taskMcpWaiters.delete(finish);
|
|
19516
|
+
if (error) reject(error);
|
|
19517
|
+
else resolve();
|
|
19518
|
+
};
|
|
19519
|
+
const timer = setTimeout(() => finish(new Error(
|
|
19520
|
+
"CodeAgentSwarm tools are still starting. Retry sending your message."
|
|
19521
|
+
)), this._requestTimeoutMs);
|
|
19522
|
+
this._taskMcpWaiters.add(finish);
|
|
19523
|
+
});
|
|
19524
|
+
}
|
|
19525
|
+
if (this._taskMcpStartup.status !== "ready") {
|
|
19526
|
+
throw new Error("CodeAgentSwarm tools could not start. Reopen this conversation to retry.");
|
|
19527
|
+
}
|
|
19528
|
+
}
|
|
19499
19529
|
async _flushQueuedTurnInputs() {
|
|
19500
19530
|
if (this._flushingQueuedTurnInputs || this._activeTurnId) return;
|
|
19501
19531
|
this._flushingQueuedTurnInputs = true;
|
|
@@ -19520,6 +19550,8 @@ var require_codex_app_server_driver = __commonJS({
|
|
|
19520
19550
|
* @returns {Promise<void>}
|
|
19521
19551
|
*/
|
|
19522
19552
|
async interruptTurn() {
|
|
19553
|
+
this._inputInterruptVersion += 1;
|
|
19554
|
+
for (const finish of this._taskMcpWaiters) finish(new Error("CodeAgentSwarm message cancelled while tools were starting."));
|
|
19523
19555
|
if (!this._activeTurnId) return void 0;
|
|
19524
19556
|
await this._request("turn/interrupt", {
|
|
19525
19557
|
threadId: this._threadId,
|
|
@@ -19898,7 +19930,7 @@ var require_codex_app_server_driver = __commonJS({
|
|
|
19898
19930
|
initialTurnsPage: {
|
|
19899
19931
|
limit: INITIAL_HISTORY_TURN_PAGE_SIZE,
|
|
19900
19932
|
sortDirection: "desc",
|
|
19901
|
-
itemsView: "
|
|
19933
|
+
itemsView: "full"
|
|
19902
19934
|
},
|
|
19903
19935
|
...threadParams
|
|
19904
19936
|
});
|
|
@@ -19924,13 +19956,6 @@ var require_codex_app_server_driver = __commonJS({
|
|
|
19924
19956
|
}
|
|
19925
19957
|
}
|
|
19926
19958
|
this._threadId = ((_a = result == null ? void 0 : result.thread) == null ? void 0 : _a.id) || (result == null ? void 0 : result.threadId) || (resumeSessionId || null);
|
|
19927
|
-
if (!toolsDisabled && !imageGenerationOnly) {
|
|
19928
|
-
try {
|
|
19929
|
-
await this._ensureRequiredMcpServer(this._threadId);
|
|
19930
|
-
} catch (error) {
|
|
19931
|
-
console.warn(`[CodexAppServerDriver] Continuing without verified task MCP tools: ${error.message}`);
|
|
19932
|
-
}
|
|
19933
|
-
}
|
|
19934
19959
|
this._sessionCwd = (result == null ? void 0 : result.cwd) || ((_b = result == null ? void 0 : result.thread) == null ? void 0 : _b.cwd) || cwd;
|
|
19935
19960
|
let historyPage = result == null ? void 0 : result.initialTurnsPage;
|
|
19936
19961
|
const returnedTurns = Array.isArray((_c = result == null ? void 0 : result.thread) == null ? void 0 : _c.turns) ? result.thread.turns : [];
|
|
@@ -19940,7 +19965,7 @@ var require_codex_app_server_driver = __commonJS({
|
|
|
19940
19965
|
threadId: this._threadId,
|
|
19941
19966
|
limit: INITIAL_HISTORY_TURN_PAGE_SIZE,
|
|
19942
19967
|
sortDirection: "desc",
|
|
19943
|
-
itemsView: "
|
|
19968
|
+
itemsView: "full"
|
|
19944
19969
|
});
|
|
19945
19970
|
} catch (_) {
|
|
19946
19971
|
}
|
|
@@ -19989,15 +20014,6 @@ var require_codex_app_server_driver = __commonJS({
|
|
|
19989
20014
|
} while (cursor);
|
|
19990
20015
|
return servers;
|
|
19991
20016
|
}
|
|
19992
|
-
async _ensureRequiredMcpServer(threadId) {
|
|
19993
|
-
if (!this._requiredMcpServer) return;
|
|
19994
|
-
const connected = (servers) => servers.some((server) => (server == null ? void 0 : server.name) === this._requiredMcpServer && Object.values(server.tools || {}).some((tool) => (tool == null ? void 0 : tool.name) === REQUIRED_TASK_MCP_TOOL));
|
|
19995
|
-
if (connected(await this._listMcpServers(threadId))) return;
|
|
19996
|
-
if (this._repairMcpConfig && await this._repairMcpConfig() === false) {
|
|
19997
|
-
throw new Error("CodeAgentSwarm could not repair the Codex MCP configuration. Restart CodeAgentSwarm and retry Chat.");
|
|
19998
|
-
}
|
|
19999
|
-
await this._request("config/mcpServer/reload", null);
|
|
20000
|
-
}
|
|
20001
20017
|
/**
|
|
20002
20018
|
* Build a resumed thread's past items as historical `item.completed` events.
|
|
20003
20019
|
*
|
|
@@ -20224,6 +20240,7 @@ var require_codex_app_server_driver = __commonJS({
|
|
|
20224
20240
|
* @param {Error} error
|
|
20225
20241
|
*/
|
|
20226
20242
|
_rejectAllPending(error) {
|
|
20243
|
+
for (const finish of this._taskMcpWaiters) finish(error);
|
|
20227
20244
|
for (const pending of this._pendingRequests.values()) {
|
|
20228
20245
|
clearTimeout(pending.timer);
|
|
20229
20246
|
pending.reject(error);
|
|
@@ -20305,6 +20322,15 @@ var require_codex_app_server_driver = __commonJS({
|
|
|
20305
20322
|
*/
|
|
20306
20323
|
_handleNotification({ method, params }) {
|
|
20307
20324
|
const notifThreadId = params && (params.threadId || params.thread && params.thread.id);
|
|
20325
|
+
if (method === "mcpServer/startupStatus/updated") {
|
|
20326
|
+
if ((params == null ? void 0 : params.name) === "codeagentswarm-tasks" && notifThreadId && (!this._threadId || notifThreadId === this._threadId)) {
|
|
20327
|
+
this._taskMcpStartup = params;
|
|
20328
|
+
if (params.status !== "starting") {
|
|
20329
|
+
for (const finish of this._taskMcpWaiters) finish();
|
|
20330
|
+
}
|
|
20331
|
+
}
|
|
20332
|
+
return;
|
|
20333
|
+
}
|
|
20308
20334
|
if (notifThreadId && this._threadId && notifThreadId !== this._threadId) {
|
|
20309
20335
|
this._handleChildNotification(notifThreadId, method, params);
|
|
20310
20336
|
return;
|
|
@@ -27641,7 +27667,7 @@ var require_database_mcp_standalone = __commonJS({
|
|
|
27641
27667
|
{ status_key: "needs_testing", label: "Needs testing", color: "#3b82f6", icon: "flask-conical", sort_order: 2, is_default: 1, agent_settable: 1, prompt: "Set it when you finish the implementation and the work is pending the user testing it manually. Do not set it if there are still things left to implement." },
|
|
27642
27668
|
{ status_key: "working", label: "Working", color: "#fbbf24", icon: "hammer", sort_order: 3, is_default: 1, agent_settable: 1, prompt: "Set it when you start working on any request and while you are implementing, investigating or fixing something." },
|
|
27643
27669
|
{ status_key: "done", label: "Done", color: "#22c55e", icon: "circle-check", sort_order: 4, is_default: 1, agent_settable: 1, prompt: "Set it when the work is completely finished: implemented, validated and with its commit/push done when applicable. It is the final state." },
|
|
27644
|
-
{ status_key: "idle", label: "Idle", color: "#6b7280", icon: "circle-dashed", sort_order: 5, is_default: 1, agent_settable: 0, prompt: "Set by the app
|
|
27670
|
+
{ status_key: "idle", label: "Idle", color: "#6b7280", icon: "circle-dashed", sort_order: 5, is_default: 1, agent_settable: 0, prompt: "Set by the app when an agent is resting without an explicit work status, including after a reply finishes. It does not mean the work is complete or that user input is required. Agents cannot set this status." }
|
|
27645
27671
|
];
|
|
27646
27672
|
var IDLE_TERMINAL_STATUS_KEY = "idle";
|
|
27647
27673
|
var IDLE_STATUS_SEEDED_SETTING = "terminal_status_idle_seeded";
|
|
@@ -27653,7 +27679,8 @@ var require_database_mcp_standalone = __commonJS({
|
|
|
27653
27679
|
blocked: 5,
|
|
27654
27680
|
done: 6
|
|
27655
27681
|
};
|
|
27656
|
-
var
|
|
27682
|
+
var LEGACY_DEFAULT_PROMPTS = {
|
|
27683
|
+
idle: "Set by the app on an agent that has just been opened and has not been given any work yet. Agents cannot set this status; it clears itself as soon as you send the agent something.",
|
|
27657
27684
|
working: "Ponlo al empezar a trabajar en cualquier petici\xF3n y mientras est\xE9s implementando, investigando o arreglando algo.",
|
|
27658
27685
|
needs_input: "Ponlo cuando pares porque necesites una respuesta o decisi\xF3n del usuario para continuar (una pregunta, una elecci\xF3n de dise\xF1o, un permiso).",
|
|
27659
27686
|
needs_testing: "Ponlo cuando termines la implementaci\xF3n y el trabajo quede pendiente de que el usuario lo pruebe a mano. No lo pongas si a\xFAn quedan cosas por implementar.",
|
|
@@ -27667,14 +27694,14 @@ var require_database_mcp_standalone = __commonJS({
|
|
|
27667
27694
|
label: "Blocked",
|
|
27668
27695
|
color: "#ef4444",
|
|
27669
27696
|
prompt_en: "Set it when you cannot make progress due to something external that does not depend on you or the user: broken CI, a dependency that is down, failing permissions, a third-party bug.",
|
|
27670
|
-
prompt_es:
|
|
27697
|
+
prompt_es: LEGACY_DEFAULT_PROMPTS.blocked
|
|
27671
27698
|
},
|
|
27672
27699
|
{
|
|
27673
27700
|
status_key: "pending_commit",
|
|
27674
27701
|
label: "Pending commit/push",
|
|
27675
27702
|
color: "#a78bfa",
|
|
27676
27703
|
prompt_en: "Set it when the user has already validated the work and only the commit or push remains.",
|
|
27677
|
-
prompt_es:
|
|
27704
|
+
prompt_es: LEGACY_DEFAULT_PROMPTS.pending_commit
|
|
27678
27705
|
}
|
|
27679
27706
|
];
|
|
27680
27707
|
function findSqlite3Path() {
|
|
@@ -28011,13 +28038,13 @@ SELECT COUNT(*) AS count FROM terminal_statuses`);
|
|
|
28011
28038
|
console.error("[MCP Database] Error migrating idle terminal status:", error.message);
|
|
28012
28039
|
}
|
|
28013
28040
|
}
|
|
28014
|
-
// Migration: upgrade the legacy
|
|
28041
|
+
// Migration: upgrade the legacy factory prompts to the English ones.
|
|
28015
28042
|
// Only default statuses whose prompt is still the legacy string VERBATIM (never
|
|
28016
28043
|
// edited by the user) are touched. Idempotent. Mirrors database.js.
|
|
28017
28044
|
migrateLegacyTerminalStatusPrompts() {
|
|
28018
28045
|
try {
|
|
28019
28046
|
for (const status of DEFAULT_TERMINAL_STATUSES) {
|
|
28020
|
-
const legacy =
|
|
28047
|
+
const legacy = LEGACY_DEFAULT_PROMPTS[status.status_key];
|
|
28021
28048
|
if (!legacy) continue;
|
|
28022
28049
|
this.execSQL(
|
|
28023
28050
|
`UPDATE terminal_statuses SET prompt = ?
|
|
@@ -30375,6 +30402,18 @@ var require_mcp_stdio_server = __commonJS({
|
|
|
30375
30402
|
} catch (e) {
|
|
30376
30403
|
}
|
|
30377
30404
|
}
|
|
30405
|
+
_hasNudgeMarker(kind) {
|
|
30406
|
+
try {
|
|
30407
|
+
const os2 = require("os");
|
|
30408
|
+
const fs2 = require("fs");
|
|
30409
|
+
const stateDir = path.join(os2.homedir(), ".codeagentswarm", "terminal-nudge-state");
|
|
30410
|
+
const rawKey = process.env.CODEAGENTSWARM_TERMINAL_ID || process.env.CODEAGENTSWARM_CURRENT_QUADRANT;
|
|
30411
|
+
const key = String(rawKey || "").replace(/[^A-Za-z0-9_-]/g, "_");
|
|
30412
|
+
return !!key && fs2.existsSync(path.join(stateDir, `${key}.${kind}`));
|
|
30413
|
+
} catch (e) {
|
|
30414
|
+
return false;
|
|
30415
|
+
}
|
|
30416
|
+
}
|
|
30378
30417
|
// Resolve the current terminal id (1-based) from the environment.
|
|
30379
30418
|
_getCurrentTerminalId() {
|
|
30380
30419
|
const terminalId = process.env.CODEAGENTSWARM_CURRENT_QUADRANT;
|
|
@@ -30393,20 +30432,30 @@ var require_mcp_stdio_server = __commonJS({
|
|
|
30393
30432
|
}
|
|
30394
30433
|
// Set the GENERAL terminal title: the sticky tab label that represents the
|
|
30395
30434
|
// product-level goal of what this terminal is working on. Set it ONCE at the
|
|
30396
|
-
// start of
|
|
30397
|
-
//
|
|
30398
|
-
//
|
|
30399
|
-
// for that.
|
|
30435
|
+
// start of the conversation. Later calls preserve it unless the caller explicitly
|
|
30436
|
+
// declares a radical topic change. It does NOT represent the current step — use
|
|
30437
|
+
// update_terminal_activity for that.
|
|
30400
30438
|
async setTerminalTitle(params) {
|
|
30401
|
-
const { title, long_title } = params;
|
|
30439
|
+
const { title, long_title, replace_existing } = params;
|
|
30402
30440
|
if (!title) {
|
|
30403
30441
|
throw new Error("title is required");
|
|
30404
30442
|
}
|
|
30405
30443
|
if (isPlaceholderTitle(title)) {
|
|
30406
30444
|
throw new Error(`"${title}" looks like example text copied from the tool documentation, not a real title. Call the tool again with a title that describes the ACTUAL feature or goal you are working on in this agent (max 6 words).`);
|
|
30407
30445
|
}
|
|
30408
|
-
|
|
30446
|
+
if (replace_existing !== void 0 && typeof replace_existing !== "boolean") {
|
|
30447
|
+
throw new Error("replace_existing must be a boolean");
|
|
30448
|
+
}
|
|
30409
30449
|
const terminalId = this._getCurrentTerminalId();
|
|
30450
|
+
if (replace_existing !== true && this._hasNudgeMarker("title")) {
|
|
30451
|
+
return {
|
|
30452
|
+
terminal_id: terminalId,
|
|
30453
|
+
updated: false,
|
|
30454
|
+
preserved: true,
|
|
30455
|
+
message: "The existing conversation title was preserved. Use update_terminal_activity for follow-up work; set replace_existing=true only after the user pivots to a completely different functionality."
|
|
30456
|
+
};
|
|
30457
|
+
}
|
|
30458
|
+
const shortTitle = this.generateShortTitle(title);
|
|
30410
30459
|
const currentTask = this._getCurrentTask(terminalId);
|
|
30411
30460
|
const taskId = currentTask ? currentTask.id : null;
|
|
30412
30461
|
let longTitle = long_title;
|
|
@@ -31304,7 +31353,7 @@ Use 'clear' to remove the status.`;
|
|
|
31304
31353
|
},
|
|
31305
31354
|
{
|
|
31306
31355
|
name: "set_terminal_title",
|
|
31307
|
-
description:
|
|
31356
|
+
description: "Set the GENERAL agent title AND the agent GOAL from the first user request that established this conversation's topic. Pass BOTH text arguments because the user sees them together. This is once per conversation, NOT once per user message, turn, task, review, validation, or resumed session. Follow-up work belongs in update_terminal_activity and repeated calls preserve the original title. Only a user pivot to a completely different functionality may replace it, by passing replace_existing=true. LANGUAGE: write both text fields in the SAME language the user is speaking.",
|
|
31308
31357
|
inputSchema: {
|
|
31309
31358
|
type: "object",
|
|
31310
31359
|
properties: {
|
|
@@ -31315,6 +31364,10 @@ Use 'clear' to remove the status.`;
|
|
|
31315
31364
|
long_title: {
|
|
31316
31365
|
type: "string",
|
|
31317
31366
|
description: `The agent GOAL: one sentence saying what this agent is FOR \u2014 the outcome the work is aiming at, not the current step. ALWAYS provide it: the user reads it in the Agent hover, labelled GOAL, under the short title. Write the real goal in the user's language. Do NOT restate the title or prefix it with "Working on:".`
|
|
31367
|
+
},
|
|
31368
|
+
replace_existing: {
|
|
31369
|
+
type: "boolean",
|
|
31370
|
+
description: "Leave false or omit for normal follow-up work. Set true ONLY when the user explicitly pivots this existing conversation to a completely different functionality; reviews, tests, fixes, implementation phases, and refinements of the original request are activities and must not replace the title."
|
|
31318
31371
|
}
|
|
31319
31372
|
},
|
|
31320
31373
|
// long_title is NOT in `required` on purpose: some agent clients
|
|
@@ -31768,7 +31821,8 @@ Use 'clear' to remove the status.`;
|
|
|
31768
31821
|
case "set_terminal_title":
|
|
31769
31822
|
result = await this.setTerminalTitle({
|
|
31770
31823
|
title: args.title,
|
|
31771
|
-
long_title: args.long_title
|
|
31824
|
+
long_title: args.long_title,
|
|
31825
|
+
replace_existing: args.replace_existing
|
|
31772
31826
|
});
|
|
31773
31827
|
break;
|
|
31774
31828
|
case "update_terminal_activity":
|
|
@@ -33593,18 +33647,13 @@ var require_driver_chat_manager = __commonJS({
|
|
|
33593
33647
|
});
|
|
33594
33648
|
});
|
|
33595
33649
|
}
|
|
33596
|
-
function defaultCreateDriver({ agent, env, binaryPath
|
|
33650
|
+
function defaultCreateDriver({ agent, env, binaryPath }) {
|
|
33597
33651
|
if (agent === "claude") return new ClaudeAgentSdkDriver({ env, binaryPath });
|
|
33598
33652
|
if (agent === "antigravity") return new AntigravityPrintDriver({ env, binaryPath });
|
|
33599
33653
|
if (agent === "opencode" || agent === "kimi" || agent === "grok" || agent === "cursor") {
|
|
33600
33654
|
return new AcpAgentDriver({ provider: agent, env, binaryPath });
|
|
33601
33655
|
}
|
|
33602
|
-
return new CodexAppServerDriver({
|
|
33603
|
-
env,
|
|
33604
|
-
binaryPath,
|
|
33605
|
-
requiredMcpServer,
|
|
33606
|
-
repairMcpConfig
|
|
33607
|
-
});
|
|
33656
|
+
return new CodexAppServerDriver({ env, binaryPath });
|
|
33608
33657
|
}
|
|
33609
33658
|
var DriverChatManager = class extends EventEmitter {
|
|
33610
33659
|
/**
|
|
@@ -33731,12 +33780,11 @@ var require_driver_chat_manager = __commonJS({
|
|
|
33731
33780
|
useWorktree = false,
|
|
33732
33781
|
worktreeTitle,
|
|
33733
33782
|
clientRequestId
|
|
33734
|
-
} = {}, { signal } = {}) {
|
|
33783
|
+
} = {}, { signal, sessionId = crypto.randomUUID() } = {}) {
|
|
33735
33784
|
var _a, _b, _c;
|
|
33736
33785
|
if (!SUPPORTED_AGENTS.includes(agent)) {
|
|
33737
33786
|
throw new Error(`Unsupported driver chat agent: ${agent}`);
|
|
33738
33787
|
}
|
|
33739
|
-
const sessionId = crypto.randomUUID();
|
|
33740
33788
|
if (clientRequestId) {
|
|
33741
33789
|
this.emit(SESSION_STARTING, {
|
|
33742
33790
|
sessionId,
|
|
@@ -33871,6 +33919,7 @@ var require_driver_chat_manager = __commonJS({
|
|
|
33871
33919
|
// main-process placeholder, so return that same UUID for persistence
|
|
33872
33920
|
// and instance-safe MCP notification routing.
|
|
33873
33921
|
terminalUuid: env.CODEAGENTSWARM_TERMINAL_ID || null,
|
|
33922
|
+
communicationEnabled: env.CODEAGENTSWARM_SESSION_COMMUNICATION_ENABLED === "1",
|
|
33874
33923
|
model: session.model,
|
|
33875
33924
|
effort: session.effort || resolvedEffort,
|
|
33876
33925
|
serviceTier: session.serviceTier ?? (rejected.has("serviceTier") ? null : (_a = selections.find((selection) => (selection == null ? void 0 : selection.id) === "serviceTier")) == null ? void 0 : _a.value) ?? null,
|
|
@@ -34210,6 +34259,11 @@ var require_driver_chat_manager = __commonJS({
|
|
|
34210
34259
|
await this._teardownSession(sessionId);
|
|
34211
34260
|
return { stopped: true };
|
|
34212
34261
|
}
|
|
34262
|
+
/** Replace the process while keeping the host-owned conversation identity. */
|
|
34263
|
+
async restartSession(sessionId, options) {
|
|
34264
|
+
await this._teardownSession(sessionId);
|
|
34265
|
+
return this.startSession(options, { sessionId });
|
|
34266
|
+
}
|
|
34213
34267
|
/**
|
|
34214
34268
|
* Stops every live session (app quit).
|
|
34215
34269
|
*
|
|
@@ -34629,11 +34683,13 @@ var require_chat_history_pagination = __commonJS({
|
|
|
34629
34683
|
return Date.parse(value);
|
|
34630
34684
|
}
|
|
34631
34685
|
function normalizeConversationMessages(messages) {
|
|
34686
|
+
let internalTurn = false;
|
|
34632
34687
|
return (Array.isArray(messages) ? messages : []).flatMap((message) => {
|
|
34633
34688
|
const role = (message == null ? void 0 : message.role) === "assistant" ? "assistant_message" : (message == null ? void 0 : message.role) === "user" ? "user_message" : null;
|
|
34634
34689
|
const text = [message == null ? void 0 : message.content, message == null ? void 0 : message.text, message == null ? void 0 : message.displayText].find((value) => typeof value === "string" && value.trim());
|
|
34635
34690
|
const attachments = Array.isArray(message == null ? void 0 : message.attachments) ? message.attachments : [];
|
|
34636
|
-
|
|
34691
|
+
if (role === "user_message") internalTurn = Boolean(text && parseSessionCoordinationPrompt(text));
|
|
34692
|
+
return role && (text || attachments.length) && !internalTurn ? [{ role, text: text || "", attachments, timestamp: message.timestamp }] : [];
|
|
34637
34693
|
});
|
|
34638
34694
|
}
|
|
34639
34695
|
function boundedConversationMessages(messages, { limit = 30, maxMessageChars = 8e3, maxBytes = 22e4 } = {}) {
|
|
@@ -34684,12 +34740,14 @@ var require_chat_history_pagination = __commonJS({
|
|
|
34684
34740
|
before,
|
|
34685
34741
|
anchor,
|
|
34686
34742
|
knownCount = 0,
|
|
34743
|
+
hydratedCount = 0,
|
|
34687
34744
|
limit = DEFAULT_HISTORY_PAGE_SIZE
|
|
34688
34745
|
} = {}) {
|
|
34689
34746
|
const normalized = normalizeConversationMessages(messages);
|
|
34690
34747
|
const safeLimit = Number.isSafeInteger(limit) && limit > 0 ? limit : DEFAULT_HISTORY_PAGE_SIZE;
|
|
34691
34748
|
const anchorIndex = findConversationAnchor(normalized, anchor);
|
|
34692
|
-
const
|
|
34749
|
+
const hydratedEnd = Math.max(0, normalized.length - Math.max(0, Number(hydratedCount) || 0));
|
|
34750
|
+
const end = Number.isSafeInteger(before) ? Math.max(0, Math.min(before, normalized.length)) : Math.min(hydratedEnd, anchorIndex ?? Math.max(0, normalized.length - Math.max(0, Number(knownCount) || 0)));
|
|
34693
34751
|
const start = Math.max(0, end - safeLimit);
|
|
34694
34752
|
return {
|
|
34695
34753
|
messages: normalized.slice(start, end).map((message, offset) => ({
|
|
@@ -34950,10 +35008,12 @@ var require_mobile_runtime = __commonJS({
|
|
|
34950
35008
|
var { parseSessionCoordinationPrompt } = require_session_coordination_message();
|
|
34951
35009
|
var {
|
|
34952
35010
|
conversationMessagesToEvents,
|
|
35011
|
+
normalizeConversationMessages,
|
|
34953
35012
|
pageConversationMessages
|
|
34954
35013
|
} = require_chat_history_pagination();
|
|
34955
35014
|
var PROTOCOL_VERSION = 2;
|
|
34956
35015
|
var SESSION_SUBSCRIPTIONS_FEATURE = "session-subscriptions";
|
|
35016
|
+
var SNAPSHOT_PROJECT_ICONS_FEATURE = "snapshot-project-icons";
|
|
34957
35017
|
var SUBSCRIPTION_ONLY_EVENT_TYPES = /* @__PURE__ */ new Set([
|
|
34958
35018
|
"session.config.updated",
|
|
34959
35019
|
"session.commands.updated",
|
|
@@ -35255,6 +35315,7 @@ var require_mobile_runtime = __commonJS({
|
|
|
35255
35315
|
listProjectDirectories = null,
|
|
35256
35316
|
createProject = null,
|
|
35257
35317
|
updateProject = null,
|
|
35318
|
+
gitAvailability = null,
|
|
35258
35319
|
projectIconAvailability = null,
|
|
35259
35320
|
generateProjectIcon = null,
|
|
35260
35321
|
registerProject = null,
|
|
@@ -35325,6 +35386,7 @@ var require_mobile_runtime = __commonJS({
|
|
|
35325
35386
|
this.listProjectDirectories = listProjectDirectories;
|
|
35326
35387
|
this.createProject = createProject;
|
|
35327
35388
|
this.updateProject = updateProject;
|
|
35389
|
+
this.gitAvailability = gitAvailability;
|
|
35328
35390
|
this.projectIconAvailability = projectIconAvailability;
|
|
35329
35391
|
this.generateProjectIcon = generateProjectIcon;
|
|
35330
35392
|
this.registerProject = registerProject;
|
|
@@ -35470,6 +35532,7 @@ var require_mobile_runtime = __commonJS({
|
|
|
35470
35532
|
accountLabel: session.accountLabel,
|
|
35471
35533
|
threadId: session.threadId,
|
|
35472
35534
|
terminalUuid: session.terminalUuid,
|
|
35535
|
+
communicationEnabled: session.communicationEnabled === true,
|
|
35473
35536
|
terminalOrder: session.terminalOrder,
|
|
35474
35537
|
cwd: session.cwd,
|
|
35475
35538
|
model: session.model,
|
|
@@ -35533,7 +35596,8 @@ var require_mobile_runtime = __commonJS({
|
|
|
35533
35596
|
compact.items = selected.sort((left, right) => left.sourceIndex - right.sourceIndex).map(({ item }) => item);
|
|
35534
35597
|
return compact;
|
|
35535
35598
|
}
|
|
35536
|
-
snapshot() {
|
|
35599
|
+
snapshot({ projectIcons = false } = {}) {
|
|
35600
|
+
var _a;
|
|
35537
35601
|
const allProjects = this._projects();
|
|
35538
35602
|
const projects = allProjects.slice(0, 100);
|
|
35539
35603
|
const snapshot = {
|
|
@@ -35552,6 +35616,17 @@ var require_mobile_runtime = __commonJS({
|
|
|
35552
35616
|
terminalStatuses: compactTerminalStatuses(this.getTerminalStatuses()),
|
|
35553
35617
|
sessions: Array.from(this.sessions.values(), (session) => this._snapshotSession(session))
|
|
35554
35618
|
};
|
|
35619
|
+
const referencedProjectIcons = /* @__PURE__ */ new Set();
|
|
35620
|
+
if (projectIcons) {
|
|
35621
|
+
for (const session of snapshot.sessions) {
|
|
35622
|
+
if (!((_a = session.project) == null ? void 0 : _a.iconDataUrl)) continue;
|
|
35623
|
+
const projectIconIndex = projects.findIndex((project2) => project2.path === session.project.path && project2.iconDataUrl === session.project.iconDataUrl);
|
|
35624
|
+
if (projectIconIndex < 0) continue;
|
|
35625
|
+
const { iconDataUrl, ...project } = session.project;
|
|
35626
|
+
session.project = { ...project, projectIconIndex };
|
|
35627
|
+
referencedProjectIcons.add(projectIconIndex);
|
|
35628
|
+
}
|
|
35629
|
+
}
|
|
35555
35630
|
if (jsonBytes(snapshot) <= MAX_SNAPSHOT_BYTES) return snapshot;
|
|
35556
35631
|
const compact = {
|
|
35557
35632
|
computerName: snapshot.computerName,
|
|
@@ -35572,10 +35647,11 @@ var require_mobile_runtime = __commonJS({
|
|
|
35572
35647
|
truncated: true
|
|
35573
35648
|
};
|
|
35574
35649
|
let iconChars = compact.projects.reduce((total, project) => {
|
|
35575
|
-
var
|
|
35576
|
-
return total + (((
|
|
35650
|
+
var _a2;
|
|
35651
|
+
return total + (((_a2 = project.iconDataUrl) == null ? void 0 : _a2.length) || 0);
|
|
35577
35652
|
}, 0);
|
|
35578
35653
|
for (let index = compact.projects.length - 1; iconChars > MAX_SNAPSHOT_PROJECT_ICON_CHARS && index >= 0; index -= 1) {
|
|
35654
|
+
if (referencedProjectIcons.has(index)) continue;
|
|
35579
35655
|
const icon = compact.projects[index].iconDataUrl;
|
|
35580
35656
|
if (!icon) continue;
|
|
35581
35657
|
delete compact.projects[index].iconDataUrl;
|
|
@@ -35583,6 +35659,7 @@ var require_mobile_runtime = __commonJS({
|
|
|
35583
35659
|
}
|
|
35584
35660
|
let used = jsonBytes(compact);
|
|
35585
35661
|
for (let index = compact.projects.length - 1; used > MAX_SNAPSHOT_BYTES && index >= 0; index -= 1) {
|
|
35662
|
+
if (referencedProjectIcons.has(index)) continue;
|
|
35586
35663
|
if (!compact.projects[index].iconDataUrl) continue;
|
|
35587
35664
|
delete compact.projects[index].iconDataUrl;
|
|
35588
35665
|
used = jsonBytes(compact);
|
|
@@ -35777,13 +35854,16 @@ var require_mobile_runtime = __commonJS({
|
|
|
35777
35854
|
});
|
|
35778
35855
|
}
|
|
35779
35856
|
publishProjectIconEvent(event = {}) {
|
|
35857
|
+
const iconDataUrl = typeof event.iconDataUrl === "string" && event.iconDataUrl.length <= 1e5 ? event.iconDataUrl : null;
|
|
35780
35858
|
return this._publish("project.icon.generated", {
|
|
35781
35859
|
jobId: cleanText(event.jobId, 100),
|
|
35782
35860
|
projectId: cleanText(event.projectId, 128),
|
|
35783
35861
|
success: event.success === true,
|
|
35784
35862
|
applied: event.applied === true,
|
|
35785
35863
|
unavailable: event.unavailable === true,
|
|
35786
|
-
...cleanText(event.error, 500) ? { error: cleanText(event.error, 500) } : {}
|
|
35864
|
+
...cleanText(event.error, 500) ? { error: cleanText(event.error, 500) } : {},
|
|
35865
|
+
...cleanText(event.icon, 300) ? { icon: cleanText(event.icon, 300) } : {},
|
|
35866
|
+
...iconDataUrl ? { iconDataUrl } : {}
|
|
35787
35867
|
});
|
|
35788
35868
|
}
|
|
35789
35869
|
publishProviderLoginEvent(event = {}) {
|
|
@@ -35831,7 +35911,9 @@ var require_mobile_runtime = __commonJS({
|
|
|
35831
35911
|
});
|
|
35832
35912
|
}
|
|
35833
35913
|
_registerSession(started) {
|
|
35914
|
+
var _a;
|
|
35834
35915
|
if (!started || typeof started.sessionId !== "string") return;
|
|
35916
|
+
const restarting = ((_a = this.sessions.get(started.sessionId)) == null ? void 0 : _a.restarting) === true;
|
|
35835
35917
|
const clientRequestId = cleanText(started.clientRequestId, 128);
|
|
35836
35918
|
this._session(started.sessionId, {
|
|
35837
35919
|
clientRequestId,
|
|
@@ -35841,6 +35923,7 @@ var require_mobile_runtime = __commonJS({
|
|
|
35841
35923
|
accountLabel: started.accountLabel || null,
|
|
35842
35924
|
threadId: started.threadId,
|
|
35843
35925
|
terminalUuid: started.terminalUuid,
|
|
35926
|
+
communicationEnabled: started.communicationEnabled === true,
|
|
35844
35927
|
terminalOrder: Number.isSafeInteger(started.terminalId) && started.terminalId > 0 ? started.terminalId : null,
|
|
35845
35928
|
desktopTerminalId: Number.isSafeInteger(started.terminalId) && started.terminalId > 0 ? started.terminalId : null,
|
|
35846
35929
|
cwd: started.cwd,
|
|
@@ -35866,6 +35949,7 @@ var require_mobile_runtime = __commonJS({
|
|
|
35866
35949
|
accountLabel: started.accountLabel || null,
|
|
35867
35950
|
threadId: started.threadId,
|
|
35868
35951
|
terminalUuid: started.terminalUuid,
|
|
35952
|
+
communicationEnabled: started.communicationEnabled === true,
|
|
35869
35953
|
terminalOrder: Number.isSafeInteger(started.terminalId) && started.terminalId > 0 ? started.terminalId : null,
|
|
35870
35954
|
cwd: started.cwd,
|
|
35871
35955
|
model: started.model,
|
|
@@ -35882,7 +35966,7 @@ var require_mobile_runtime = __commonJS({
|
|
|
35882
35966
|
hasEarlierHistory: started.resumed === true
|
|
35883
35967
|
}
|
|
35884
35968
|
});
|
|
35885
|
-
for (const event of started.historyEvents || []) {
|
|
35969
|
+
for (const event of restarting ? [] : started.historyEvents || []) {
|
|
35886
35970
|
this._publishProviderEvent(started.sessionId, event);
|
|
35887
35971
|
}
|
|
35888
35972
|
this._sessionsChanged();
|
|
@@ -35921,11 +36005,11 @@ var require_mobile_runtime = __commonJS({
|
|
|
35921
36005
|
return;
|
|
35922
36006
|
}
|
|
35923
36007
|
if (!Array.isArray(messages) || !messages.length) return;
|
|
35924
|
-
const recent = messages.slice(-200);
|
|
36008
|
+
const recent = normalizeConversationMessages(messages).slice(-200);
|
|
35925
36009
|
recent.forEach((message, index) => {
|
|
35926
36010
|
var _a2, _b2;
|
|
35927
|
-
const role =
|
|
35928
|
-
const text = cleanText(
|
|
36011
|
+
const role = message.role;
|
|
36012
|
+
const text = cleanText(message.text, MAX_INITIAL_PROMPT_CHARS);
|
|
35929
36013
|
const attachments = Array.isArray(message == null ? void 0 : message.attachments) ? message.attachments : [];
|
|
35930
36014
|
if (!role || !text && !attachments.length) return;
|
|
35931
36015
|
const key = `${role}\0${text}`;
|
|
@@ -35961,6 +36045,7 @@ var require_mobile_runtime = __commonJS({
|
|
|
35961
36045
|
var _a, _b, _c, _d, _e, _f;
|
|
35962
36046
|
if (!this.sessions.has(sessionId)) return;
|
|
35963
36047
|
if (!event || !isProviderEventType(event.type)) return;
|
|
36048
|
+
if (this.sessions.get(sessionId).restarting && ["item.started", "item.updated", "item.completed", "content.delta", "turn.started", "turn.completed"].includes(event.type)) return;
|
|
35964
36049
|
if (event.visibility === "internal" && ![
|
|
35965
36050
|
"request.opened",
|
|
35966
36051
|
"request.updated",
|
|
@@ -36217,6 +36302,7 @@ var require_mobile_runtime = __commonJS({
|
|
|
36217
36302
|
accountLabel: null,
|
|
36218
36303
|
threadId: null,
|
|
36219
36304
|
terminalUuid: null,
|
|
36305
|
+
communicationEnabled: false,
|
|
36220
36306
|
terminalOrder: null,
|
|
36221
36307
|
desktopTerminalId: null,
|
|
36222
36308
|
cwd: null,
|
|
@@ -36363,6 +36449,7 @@ var require_mobile_runtime = __commonJS({
|
|
|
36363
36449
|
return;
|
|
36364
36450
|
}
|
|
36365
36451
|
client.selective = Array.isArray(message.features) && message.features.slice(0, 20).includes(SESSION_SUBSCRIPTIONS_FEATURE);
|
|
36452
|
+
const projectIcons = Array.isArray(message.features) && message.features.slice(0, 20).includes(SNAPSHOT_PROJECT_ICONS_FEATURE);
|
|
36366
36453
|
client.subscriptions = new Set(client.selective && Array.isArray(message.subscriptions) ? message.subscriptions.slice(0, 20).filter((sessionId) => typeof sessionId === "string" && sessionId.length > 0 && sessionId.length <= 128) : []);
|
|
36367
36454
|
client.skippedSeq = 0;
|
|
36368
36455
|
this.streamMetrics.helloMessages += 1;
|
|
@@ -36376,10 +36463,13 @@ var require_mobile_runtime = __commonJS({
|
|
|
36376
36463
|
runtimeId: this.runtimeId,
|
|
36377
36464
|
latestSeq: this.sequence,
|
|
36378
36465
|
reset: !replayable,
|
|
36379
|
-
features:
|
|
36466
|
+
features: [
|
|
36467
|
+
...client.selective ? [SESSION_SUBSCRIPTIONS_FEATURE] : [],
|
|
36468
|
+
...projectIcons ? [SNAPSHOT_PROJECT_ICONS_FEATURE] : []
|
|
36469
|
+
],
|
|
36380
36470
|
desktop: this.getClientMetadata(),
|
|
36381
36471
|
capabilities: (this.getCapabilities() || []).slice(0, 50).flatMap((capability) => typeof capability === "string" && capability.length <= 100 ? [capability] : []),
|
|
36382
|
-
...!replayable ? { snapshot: this.snapshot() } : {}
|
|
36472
|
+
...!replayable ? { snapshot: this.snapshot({ projectIcons }) } : {}
|
|
36383
36473
|
};
|
|
36384
36474
|
this.streamMetrics[replayable ? "replayWelcomes" : "resetWelcomes"] += 1;
|
|
36385
36475
|
welcome.builtMs = Math.max(0, Math.round(Date.now() - helloReceivedAt));
|
|
@@ -36481,7 +36571,7 @@ var require_mobile_runtime = __commonJS({
|
|
|
36481
36571
|
}
|
|
36482
36572
|
}
|
|
36483
36573
|
async _executeCommand(command = {}, context = {}) {
|
|
36484
|
-
var _a, _b, _c, _d, _e, _f;
|
|
36574
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
36485
36575
|
this._pruneAttachmentUploads();
|
|
36486
36576
|
const sessionId = command.sessionId;
|
|
36487
36577
|
const payload = command.payload || {};
|
|
@@ -36591,10 +36681,15 @@ var require_mobile_runtime = __commonJS({
|
|
|
36591
36681
|
this.publishProjects();
|
|
36592
36682
|
return result;
|
|
36593
36683
|
}
|
|
36684
|
+
if (command.type === "project.git.availability") {
|
|
36685
|
+
if (typeof this.gitAvailability !== "function") return { available: false };
|
|
36686
|
+
exactPayload(["rootId"]);
|
|
36687
|
+
return this.gitAvailability({ rootId: cleanText(payload.rootId, 128) });
|
|
36688
|
+
}
|
|
36594
36689
|
if (command.type === "project.icon.availability") {
|
|
36595
36690
|
if (typeof this.projectIconAvailability !== "function") return { available: false };
|
|
36596
|
-
exactPayload([]);
|
|
36597
|
-
return this.projectIconAvailability();
|
|
36691
|
+
exactPayload(["projectId"]);
|
|
36692
|
+
return this.projectIconAvailability({ projectId: cleanText(payload.projectId, 128) });
|
|
36598
36693
|
}
|
|
36599
36694
|
if (command.type === "project.icon.generate") {
|
|
36600
36695
|
if (typeof this.generateProjectIcon !== "function") throw new Error("Codex icon generation is unavailable");
|
|
@@ -36608,7 +36703,9 @@ var require_mobile_runtime = __commonJS({
|
|
|
36608
36703
|
if (command.type === "project.register") {
|
|
36609
36704
|
if (typeof this.registerProject !== "function") throw new Error("Remote project registration is unavailable");
|
|
36610
36705
|
exactPayload(["rootId", "relativePath", "requestId"]);
|
|
36611
|
-
|
|
36706
|
+
const result = await this.registerProject({ rootId: payload.rootId, relativePath: payload.relativePath, requestId: mutationRequestId() });
|
|
36707
|
+
this.publishProjects();
|
|
36708
|
+
return result;
|
|
36612
36709
|
}
|
|
36613
36710
|
if (command.type === "project.clone") {
|
|
36614
36711
|
if (typeof this.cloneProject !== "function") throw new Error("Remote project cloning is unavailable");
|
|
@@ -36720,7 +36817,9 @@ var require_mobile_runtime = __commonJS({
|
|
|
36720
36817
|
if (typeof this.describeProviderLogin !== "function") throw new Error("Remote provider sign-in is unavailable");
|
|
36721
36818
|
exactPayload(["agent"]);
|
|
36722
36819
|
if (!MOBILE_AGENTS.has(payload.agent)) throw new Error("Choose a supported provider");
|
|
36723
|
-
|
|
36820
|
+
const session = sessionId ? this.sessions.get(sessionId) : null;
|
|
36821
|
+
if (sessionId && (!session || session.agent !== payload.agent)) throw new Error("Remote sign-in session is invalid");
|
|
36822
|
+
return this.describeProviderLogin(payload.agent, { accountId: (session == null ? void 0 : session.accountId) || "current" });
|
|
36724
36823
|
}
|
|
36725
36824
|
if (command.type === "provider.login.start") {
|
|
36726
36825
|
if (typeof this.startProviderLogin !== "function") throw new Error("Remote provider sign-in is unavailable");
|
|
@@ -36728,7 +36827,10 @@ var require_mobile_runtime = __commonJS({
|
|
|
36728
36827
|
if (!MOBILE_AGENTS.has(payload.agent) || payload.replaceAccount !== void 0 && typeof payload.replaceAccount !== "boolean") {
|
|
36729
36828
|
throw new Error("Remote provider sign-in is invalid");
|
|
36730
36829
|
}
|
|
36731
|
-
|
|
36830
|
+
const session = sessionId ? this.sessions.get(sessionId) : null;
|
|
36831
|
+
if (sessionId && (!session || session.agent !== payload.agent)) throw new Error("Remote sign-in session is invalid");
|
|
36832
|
+
if (((_b = session == null ? void 0 : session.currentTurn) == null ? void 0 : _b.state) === "running") throw new Error("Wait for the current response to finish");
|
|
36833
|
+
return this.startProviderLogin({ agent: payload.agent, accountId: (session == null ? void 0 : session.accountId) || "current", replaceAccount: payload.replaceAccount === true });
|
|
36732
36834
|
}
|
|
36733
36835
|
if (command.type === "provider.login.submit") {
|
|
36734
36836
|
if (typeof this.submitProviderLogin !== "function") throw new Error("Remote provider sign-in is unavailable");
|
|
@@ -36855,7 +36957,7 @@ var require_mobile_runtime = __commonJS({
|
|
|
36855
36957
|
if (payload.useWorktree !== void 0 && typeof payload.useWorktree !== "boolean") {
|
|
36856
36958
|
throw new Error("The worktree preference is invalid");
|
|
36857
36959
|
}
|
|
36858
|
-
const clientRequestId = ((
|
|
36960
|
+
const clientRequestId = ((_c = payload.clientRequestId) == null ? void 0 : _c.trim()) || null;
|
|
36859
36961
|
try {
|
|
36860
36962
|
const result = await this.createSession({
|
|
36861
36963
|
agent: payload.agent,
|
|
@@ -36894,6 +36996,7 @@ var require_mobile_runtime = __commonJS({
|
|
|
36894
36996
|
agent: session.agent
|
|
36895
36997
|
});
|
|
36896
36998
|
const knownCount = Array.from(session.items.values()).filter(isConversationItem).length;
|
|
36999
|
+
const hydratedCount = ((_e = (_d = context.client) == null ? void 0 : _d.subscriptions) == null ? void 0 : _e.has(sessionId)) ? this._subscriptionSnapshot(session).items.filter(isConversationItem).length : 0;
|
|
36897
37000
|
const page = pageConversationMessages(messages, {
|
|
36898
37001
|
before: Number.isSafeInteger(payload.before) ? payload.before : void 0,
|
|
36899
37002
|
anchor: payload.anchor && typeof payload.anchor === "object" ? {
|
|
@@ -36902,6 +37005,7 @@ var require_mobile_runtime = __commonJS({
|
|
|
36902
37005
|
timestamp: cleanText(payload.anchor.timestamp, 64)
|
|
36903
37006
|
} : null,
|
|
36904
37007
|
knownCount: Number.isSafeInteger(payload.knownCount) ? payload.knownCount : knownCount,
|
|
37008
|
+
hydratedCount,
|
|
36905
37009
|
limit: 30
|
|
36906
37010
|
});
|
|
36907
37011
|
const events = conversationMessagesToEvents(page.messages, {
|
|
@@ -36958,6 +37062,41 @@ var require_mobile_runtime = __commonJS({
|
|
|
36958
37062
|
...retained.thumbnailDataUrl ? { thumbnailDataUrl: retained.thumbnailDataUrl } : {}
|
|
36959
37063
|
};
|
|
36960
37064
|
}
|
|
37065
|
+
case "session.restart": {
|
|
37066
|
+
exactPayload([]);
|
|
37067
|
+
const session = this.sessions.get(sessionId);
|
|
37068
|
+
if (!session || !session.cwd) throw new Error("The remote conversation is unavailable");
|
|
37069
|
+
if (((_f = session.currentTurn) == null ? void 0 : _f.state) === "running" || session.state === "starting") {
|
|
37070
|
+
throw new Error("Wait for the current response to finish");
|
|
37071
|
+
}
|
|
37072
|
+
if (session.threadId && session.supportsResume === false) {
|
|
37073
|
+
throw new Error("This provider cannot resume this conversation after sign-in");
|
|
37074
|
+
}
|
|
37075
|
+
session.state = "starting";
|
|
37076
|
+
session.restarting = true;
|
|
37077
|
+
try {
|
|
37078
|
+
await this.manager.restartSession(sessionId, {
|
|
37079
|
+
agent: session.agent,
|
|
37080
|
+
accountId: session.accountId || "current",
|
|
37081
|
+
cwd: session.cwd,
|
|
37082
|
+
resumeSessionId: session.threadId || void 0,
|
|
37083
|
+
model: session.model,
|
|
37084
|
+
effort: session.effort,
|
|
37085
|
+
permissionMode: session.permissionMode,
|
|
37086
|
+
interactionMode: session.interactionMode,
|
|
37087
|
+
terminalId: session.desktopTerminalId,
|
|
37088
|
+
terminalUuid: session.terminalUuid,
|
|
37089
|
+
clientRequestId: session.clientRequestId,
|
|
37090
|
+
providerOptions: session.serviceTier ? [{ id: "serviceTier", value: session.serviceTier }] : []
|
|
37091
|
+
});
|
|
37092
|
+
return { restarted: true };
|
|
37093
|
+
} catch (error) {
|
|
37094
|
+
session.state = "error";
|
|
37095
|
+
throw error;
|
|
37096
|
+
} finally {
|
|
37097
|
+
delete session.restarting;
|
|
37098
|
+
}
|
|
37099
|
+
}
|
|
36961
37100
|
case "session.models":
|
|
36962
37101
|
return {
|
|
36963
37102
|
models: compactModels(await this.manager.listModels(sessionId)),
|
|
@@ -36973,7 +37112,7 @@ var require_mobile_runtime = __commonJS({
|
|
|
36973
37112
|
const value = typeof payload.value === "boolean" && REASONING_CONFIG_IDS.has(configId) ? payload.value : cleanText(payload.value, 200);
|
|
36974
37113
|
if (value === null || value === "") throw new Error("Choose a configuration value");
|
|
36975
37114
|
const session = this._session(sessionId);
|
|
36976
|
-
if (((
|
|
37115
|
+
if (((_g = session.currentTurn) == null ? void 0 : _g.state) === "running") {
|
|
36977
37116
|
throw new Error("Wait for the current response to finish");
|
|
36978
37117
|
}
|
|
36979
37118
|
return this.manager.setConfigOption(sessionId, configId, value);
|
|
@@ -37119,11 +37258,11 @@ var require_mobile_runtime = __commonJS({
|
|
|
37119
37258
|
for (const uploadId of uploadIds) this.attachmentUploads.delete(uploadId);
|
|
37120
37259
|
return { accepted: true, ...(delivered == null ? void 0 : delivered.turnId) ? { turnId: delivered.turnId } : {} };
|
|
37121
37260
|
} catch (error) {
|
|
37122
|
-
const localEcho = (
|
|
37261
|
+
const localEcho = (_h = this.sessions.get(sessionId)) == null ? void 0 : _h.items.get(localEchoId);
|
|
37123
37262
|
if (localEcho == null ? void 0 : localEcho.providerItemId) return { accepted: true };
|
|
37124
37263
|
this._publishProviderEvent(sessionId, {
|
|
37125
37264
|
eventId: crypto.randomUUID(),
|
|
37126
|
-
provider: (
|
|
37265
|
+
provider: (_i = this.sessions.get(sessionId)) == null ? void 0 : _i.provider,
|
|
37127
37266
|
type: "item.completed",
|
|
37128
37267
|
executionOrigin: "main",
|
|
37129
37268
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -37133,7 +37272,7 @@ var require_mobile_runtime = __commonJS({
|
|
|
37133
37272
|
status: "failed",
|
|
37134
37273
|
localEcho: true,
|
|
37135
37274
|
remoteCommand: true,
|
|
37136
|
-
data: { text, attachments: ((
|
|
37275
|
+
data: { text, attachments: ((_j = localEcho == null ? void 0 : localEcho.data) == null ? void 0 : _j.attachments) || [] }
|
|
37137
37276
|
}
|
|
37138
37277
|
});
|
|
37139
37278
|
this.remoteTurnSessions.delete(sessionId);
|
|
@@ -38507,6 +38646,7 @@ var require_remote_runtime_client = __commonJS({
|
|
|
38507
38646
|
} = require_mobile_crypto();
|
|
38508
38647
|
var PROTOCOL_VERSION = 2;
|
|
38509
38648
|
var SESSION_SUBSCRIPTIONS_FEATURE = "session-subscriptions";
|
|
38649
|
+
var SNAPSHOT_PROJECT_ICONS_FEATURE = "snapshot-project-icons";
|
|
38510
38650
|
var MAX_PAIRING_INPUT_LENGTH = 8192;
|
|
38511
38651
|
var MAX_RUNTIME_MESSAGE_BYTES = 1024 * 1024;
|
|
38512
38652
|
var MAX_RESET_SNAPSHOT_BYTES = 256 * 1024;
|
|
@@ -38571,6 +38711,7 @@ var require_remote_runtime_client = __commonJS({
|
|
|
38571
38711
|
"turn.send",
|
|
38572
38712
|
"turn.interrupt",
|
|
38573
38713
|
"session.stop",
|
|
38714
|
+
"session.restart",
|
|
38574
38715
|
"session.models",
|
|
38575
38716
|
"session.configure",
|
|
38576
38717
|
"session.subscribe",
|
|
@@ -38589,6 +38730,9 @@ var require_remote_runtime_client = __commonJS({
|
|
|
38589
38730
|
"project.register",
|
|
38590
38731
|
"project.clone",
|
|
38591
38732
|
"project.clone.cancel",
|
|
38733
|
+
"project.git.availability",
|
|
38734
|
+
"project.icon.availability",
|
|
38735
|
+
"project.icon.generate",
|
|
38592
38736
|
"project.unregister",
|
|
38593
38737
|
"tasks.list",
|
|
38594
38738
|
"task.create",
|
|
@@ -39022,6 +39166,7 @@ var require_remote_runtime_client = __commonJS({
|
|
|
39022
39166
|
this.reconnectAttempt = 0;
|
|
39023
39167
|
this.reconnectTimer = null;
|
|
39024
39168
|
this.openTimer = null;
|
|
39169
|
+
this.runtimeWaitTimer = null;
|
|
39025
39170
|
this.heartbeatTimer = null;
|
|
39026
39171
|
this.pongTimer = null;
|
|
39027
39172
|
this.refreshTimer = null;
|
|
@@ -39358,6 +39503,7 @@ var require_remote_runtime_client = __commonJS({
|
|
|
39358
39503
|
if (message.kind === "pair.challenge") return this._handlePairChallenge(message);
|
|
39359
39504
|
if (message.kind === "pair.completed") return this._handlePairCompleted(socket, message);
|
|
39360
39505
|
if (message.kind === "hello.accepted") {
|
|
39506
|
+
if (this.connection && !this.pairing) this._waitForRuntime();
|
|
39361
39507
|
if (this.connectTrace) this.connectTrace.authenticatedAt = this.now();
|
|
39362
39508
|
this._diagnostic("remote.relay_authenticated", {
|
|
39363
39509
|
mode: this.pairing ? "pairing" : "runtime",
|
|
@@ -39368,9 +39514,8 @@ var require_remote_runtime_client = __commonJS({
|
|
|
39368
39514
|
return;
|
|
39369
39515
|
}
|
|
39370
39516
|
if (message.kind === "credential.renewed") {
|
|
39371
|
-
|
|
39372
|
-
|
|
39373
|
-
}
|
|
39517
|
+
const accessExpiresAt = Number(message.accessExpiresAt);
|
|
39518
|
+
if (!this.connection || !Number.isFinite(accessExpiresAt) || Math.abs(accessExpiresAt - this.connection.accessExpiresAt) > 2e3) return;
|
|
39374
39519
|
if (this.renewTimer) clearTimeout(this.renewTimer);
|
|
39375
39520
|
this.renewTimer = null;
|
|
39376
39521
|
this._diagnostic("remote.credential_renewed");
|
|
@@ -39386,6 +39531,8 @@ var require_remote_runtime_client = __commonJS({
|
|
|
39386
39531
|
return;
|
|
39387
39532
|
}
|
|
39388
39533
|
if (message.kind === "runtime.offline") {
|
|
39534
|
+
clearTimeout(this.runtimeWaitTimer);
|
|
39535
|
+
this.runtimeWaitTimer = null;
|
|
39389
39536
|
this.runtimeOnline = false;
|
|
39390
39537
|
this.resyncPending = false;
|
|
39391
39538
|
this.subscriptionsSupported = false;
|
|
@@ -39496,6 +39643,7 @@ var require_remote_runtime_client = __commonJS({
|
|
|
39496
39643
|
var _a, _b, _c, _d, _e;
|
|
39497
39644
|
let safe;
|
|
39498
39645
|
let bytes;
|
|
39646
|
+
let snapshotBytes;
|
|
39499
39647
|
try {
|
|
39500
39648
|
bytes = Buffer.byteLength(JSON.stringify(envelope));
|
|
39501
39649
|
if (!envelope || typeof envelope !== "object" || bytes > MAX_RUNTIME_MESSAGE_BYTES) {
|
|
@@ -39503,15 +39651,35 @@ var require_remote_runtime_client = __commonJS({
|
|
|
39503
39651
|
}
|
|
39504
39652
|
assertPublicPayload(envelope);
|
|
39505
39653
|
if (envelope.kind === "welcome" && envelope.reset === true) {
|
|
39506
|
-
|
|
39654
|
+
snapshotBytes = envelope.snapshot ? Buffer.byteLength(JSON.stringify(envelope.snapshot)) : 0;
|
|
39655
|
+
if (!envelope.snapshot || typeof envelope.snapshot !== "object" || snapshotBytes > MAX_RESET_SNAPSHOT_BYTES) {
|
|
39507
39656
|
throw new Error("Invalid runtime snapshot");
|
|
39508
39657
|
}
|
|
39658
|
+
if (Array.isArray(envelope.features) && envelope.features.includes(SNAPSHOT_PROJECT_ICONS_FEATURE)) {
|
|
39659
|
+
const projects = envelope.snapshot.projects;
|
|
39660
|
+
let expandedBytes = bytes;
|
|
39661
|
+
envelope = { ...envelope, snapshot: {
|
|
39662
|
+
...envelope.snapshot,
|
|
39663
|
+
sessions: (envelope.snapshot.sessions || []).map((session) => {
|
|
39664
|
+
if (!Object.hasOwn(session.project || {}, "projectIconIndex")) return session;
|
|
39665
|
+
const { projectIconIndex, ...project } = session.project;
|
|
39666
|
+
const source = Array.isArray(projects) && Number.isSafeInteger(projectIconIndex) && projectIconIndex >= 0 ? projects == null ? void 0 : projects[projectIconIndex] : null;
|
|
39667
|
+
if (!source || typeof source.path !== "string" || source.path !== project.path || typeof source.iconDataUrl !== "string") {
|
|
39668
|
+
throw new Error("Invalid runtime project icon reference");
|
|
39669
|
+
}
|
|
39670
|
+
const restored = { ...project, iconDataUrl: source.iconDataUrl };
|
|
39671
|
+
expandedBytes += Buffer.byteLength(JSON.stringify(restored)) - Buffer.byteLength(JSON.stringify(session.project));
|
|
39672
|
+
if (expandedBytes > MAX_RUNTIME_MESSAGE_BYTES) throw new Error("Expanded runtime snapshot is too large");
|
|
39673
|
+
return { ...session, project: restored };
|
|
39674
|
+
})
|
|
39675
|
+
} };
|
|
39676
|
+
}
|
|
39509
39677
|
}
|
|
39510
39678
|
const commandType = envelope.kind === "command.result" ? (_c = (_b = (_a = this.pendingCommands.get(envelope.commandId)) == null ? void 0 : _a.message) == null ? void 0 : _b.command) == null ? void 0 : _c.type : null;
|
|
39511
39679
|
safe = stripPathFields(envelope, 0, commandType === "project.directories.list");
|
|
39512
39680
|
} catch {
|
|
39513
39681
|
const kind = typeof (envelope == null ? void 0 : envelope.kind) === "string" && /^[a-z][a-z0-9.]{0,63}$/.test(envelope.kind) ? envelope.kind : void 0;
|
|
39514
|
-
this._diagnostic("remote.runtime_rejected", { reason: "invalid_envelope", kind });
|
|
39682
|
+
this._diagnostic("remote.runtime_rejected", { reason: "invalid_envelope", kind, bytes, snapshotBytes });
|
|
39515
39683
|
return this._protocolFailure(this.socket);
|
|
39516
39684
|
}
|
|
39517
39685
|
if (safe.kind === "command.accepted") {
|
|
@@ -39558,6 +39726,8 @@ var require_remote_runtime_client = __commonJS({
|
|
|
39558
39726
|
this._setState({ ...this.state, phase: "online", lastEnvelope: safe, error: null });
|
|
39559
39727
|
}
|
|
39560
39728
|
this.reconnectAttempt = 0;
|
|
39729
|
+
clearTimeout(this.runtimeWaitTimer);
|
|
39730
|
+
this.runtimeWaitTimer = null;
|
|
39561
39731
|
this._diagnostic("remote.runtime_synced", {
|
|
39562
39732
|
totalMs: this.connectTrace ? this.now() - this.connectTrace.startedAt : void 0,
|
|
39563
39733
|
reset: safe.reset === true,
|
|
@@ -39614,11 +39784,12 @@ var require_remote_runtime_client = __commonJS({
|
|
|
39614
39784
|
_sendRuntimeHello(withCursor = true) {
|
|
39615
39785
|
const cursor = withCursor ? this.state.cursor : null;
|
|
39616
39786
|
this._setState({ ...this.state, phase: "syncing" });
|
|
39787
|
+
this._waitForRuntime();
|
|
39617
39788
|
const sent = this._sendRuntime({
|
|
39618
39789
|
kind: "hello",
|
|
39619
39790
|
protocolVersion: PROTOCOL_VERSION,
|
|
39620
39791
|
accepts: ["deflate"],
|
|
39621
|
-
features: [SESSION_SUBSCRIPTIONS_FEATURE],
|
|
39792
|
+
features: [SESSION_SUBSCRIPTIONS_FEATURE, SNAPSHOT_PROJECT_ICONS_FEATURE],
|
|
39622
39793
|
subscriptions: [...this.subscriptions],
|
|
39623
39794
|
...cursor ? { cursor } : {}
|
|
39624
39795
|
});
|
|
@@ -39631,6 +39802,15 @@ var require_remote_runtime_client = __commonJS({
|
|
|
39631
39802
|
this.resyncPending = true;
|
|
39632
39803
|
this._sendRuntimeHello(false);
|
|
39633
39804
|
}
|
|
39805
|
+
_waitForRuntime() {
|
|
39806
|
+
if (this.runtimeWaitTimer) return;
|
|
39807
|
+
this.runtimeWaitTimer = setTimeout(() => {
|
|
39808
|
+
this.runtimeWaitTimer = null;
|
|
39809
|
+
if (!["connecting", "syncing"].includes(this.state.phase)) return;
|
|
39810
|
+
this._diagnostic("remote.runtime_wait_timeout");
|
|
39811
|
+
this._setState({ ...this.state, phase: "offline", error: "The remote computer did not respond" });
|
|
39812
|
+
}, this.timeouts.open);
|
|
39813
|
+
}
|
|
39634
39814
|
_sendRuntime(payload) {
|
|
39635
39815
|
if (!this.connection) return false;
|
|
39636
39816
|
return this._sendRelay({
|
|
@@ -39877,6 +40057,8 @@ var require_remote_runtime_client = __commonJS({
|
|
|
39877
40057
|
if (pairingFailed && this.connection) this._scheduleReconnect();
|
|
39878
40058
|
}
|
|
39879
40059
|
_closeSocket(close = true) {
|
|
40060
|
+
clearTimeout(this.runtimeWaitTimer);
|
|
40061
|
+
this.runtimeWaitTimer = null;
|
|
39880
40062
|
if (this.openTimer) clearTimeout(this.openTimer);
|
|
39881
40063
|
if (this.heartbeatTimer) clearInterval(this.heartbeatTimer);
|
|
39882
40064
|
if (this.pongTimer) clearTimeout(this.pongTimer);
|
|
@@ -40695,7 +40877,7 @@ var require_headless_session_bridge = __commonJS({
|
|
|
40695
40877
|
};
|
|
40696
40878
|
}
|
|
40697
40879
|
var HeadlessSessionBridge = class {
|
|
40698
|
-
constructor({ runtime, remoteClient, peerRuntimeNetwork = null, dataPath, deliverMessage, createPairingLink = null, randomBytes = crypto.randomBytes } = {}) {
|
|
40880
|
+
constructor({ runtime, remoteClient, peerRuntimeNetwork = null, dataPath, deliverMessage, listLocalSessions = null, readLocalTranscript = null, createPairingLink = null, randomBytes = crypto.randomBytes } = {}) {
|
|
40699
40881
|
if (!runtime || !remoteClient || typeof deliverMessage !== "function" || !path.isAbsolute(dataPath || "")) {
|
|
40700
40882
|
throw new Error("CAS Cloud session bridge configuration is invalid");
|
|
40701
40883
|
}
|
|
@@ -40704,6 +40886,8 @@ var require_headless_session_bridge = __commonJS({
|
|
|
40704
40886
|
this.peerRuntimeNetwork = peerRuntimeNetwork;
|
|
40705
40887
|
this.dataPath = dataPath;
|
|
40706
40888
|
this.deliverMessage = deliverMessage;
|
|
40889
|
+
this.listLocalSessions = typeof listLocalSessions === "function" ? listLocalSessions : null;
|
|
40890
|
+
this.readLocalTranscript = typeof readLocalTranscript === "function" ? readLocalTranscript : null;
|
|
40707
40891
|
this.createPairingLink = createPairingLink;
|
|
40708
40892
|
this.adminToken = randomBytes(32).toString("hex");
|
|
40709
40893
|
this.sessionSecret = randomBytes(32);
|
|
@@ -40882,7 +41066,7 @@ var require_headless_session_bridge = __commonJS({
|
|
|
40882
41066
|
});
|
|
40883
41067
|
}
|
|
40884
41068
|
async _handle(request, response) {
|
|
40885
|
-
var _a, _b, _c;
|
|
41069
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
40886
41070
|
const url = new URL(request.url, "http://127.0.0.1");
|
|
40887
41071
|
if (url.pathname.startsWith("/admin/")) {
|
|
40888
41072
|
if (!safeBearer(request, this.adminToken)) return sendJson(response, 401, { error: "Unauthorized" });
|
|
@@ -40934,11 +41118,29 @@ var require_headless_session_bridge = __commonJS({
|
|
|
40934
41118
|
payload: {}
|
|
40935
41119
|
})
|
|
40936
41120
|
})));
|
|
40937
|
-
const
|
|
41121
|
+
const localSessions = (((_b = (_a = this.listLocalSessions) == null ? void 0 : _a.call(this)) == null ? void 0 : _b.sessions) || []).flatMap((session) => session && typeof session.id === "string" && session.id.length <= 128 ? [{
|
|
41122
|
+
id: session.id,
|
|
41123
|
+
name: clip(session.name, 120),
|
|
41124
|
+
agent: clip(session.agent, 60),
|
|
41125
|
+
project: clip(session.project, 160),
|
|
41126
|
+
agent_id: clip(session.agent_id, 60),
|
|
41127
|
+
project_icon: clip(session.project_icon, 140),
|
|
41128
|
+
project_color: clip(session.project_color, 32),
|
|
41129
|
+
goal: clip(session.goal, 1200),
|
|
41130
|
+
activity: clip(session.activity, 500),
|
|
41131
|
+
status: clip(session.status, 80),
|
|
41132
|
+
surface: session.surface === "terminal" ? "terminal" : "chat",
|
|
41133
|
+
state: ["working", "needs_input"].includes(session.state) ? session.state : "idle",
|
|
41134
|
+
is_current: session.id === sourceSessionId
|
|
41135
|
+
}] : []);
|
|
41136
|
+
const remoteSessions = results.flatMap((entry) => entry.status === "fulfilled" ? (({ state, result }) => (Array.isArray(result == null ? void 0 : result.sessions) ? result.sessions : []).slice(0, 100).flatMap((session) => session && typeof session.id === "string" && session.id.length <= 128 ? [{
|
|
40938
41137
|
id: encodeRemoteSessionId(state.runtime.id, session.id),
|
|
40939
41138
|
name: clip(session.name, 120),
|
|
40940
41139
|
agent: clip(session.agent, 60),
|
|
40941
41140
|
project: clip(session.project, 160),
|
|
41141
|
+
agent_id: clip(session.agent_id, 60),
|
|
41142
|
+
project_icon: clip(session.project_icon, 140),
|
|
41143
|
+
project_color: clip(session.project_color, 32),
|
|
40942
41144
|
goal: clip(session.goal, 1200),
|
|
40943
41145
|
activity: clip(session.activity, 500),
|
|
40944
41146
|
status: clip(session.status, 80),
|
|
@@ -40947,7 +41149,7 @@ var require_headless_session_bridge = __commonJS({
|
|
|
40947
41149
|
host: state.runtime.name || "Paired host",
|
|
40948
41150
|
is_current: false
|
|
40949
41151
|
}] : []))(entry.value) : []);
|
|
40950
|
-
return sendJson(response, 200, { sessions });
|
|
41152
|
+
return sendJson(response, 200, { sessions: [...localSessions, ...remoteSessions] });
|
|
40951
41153
|
} catch (_) {
|
|
40952
41154
|
return sendJson(response, 503, { error: "The paired Mac is offline" });
|
|
40953
41155
|
}
|
|
@@ -40958,6 +41160,25 @@ var require_headless_session_bridge = __commonJS({
|
|
|
40958
41160
|
if (!Number.isSafeInteger(limit) || limit < 1 || limit > 60) {
|
|
40959
41161
|
return sendJson(response, 400, { error: "Conversation limit must be between 1 and 60" });
|
|
40960
41162
|
}
|
|
41163
|
+
if (this._sourceSession(body.target_session_id)) {
|
|
41164
|
+
if (!this.readLocalTranscript) return sendJson(response, 503, { error: "Conversation reading is unavailable" });
|
|
41165
|
+
try {
|
|
41166
|
+
const result = await this.readLocalTranscript({ targetSessionId: body.target_session_id, limit });
|
|
41167
|
+
const snapshot = boundedConversationMessages(result == null ? void 0 : result.messages, { limit });
|
|
41168
|
+
return sendJson(response, 200, {
|
|
41169
|
+
session: {
|
|
41170
|
+
id: body.target_session_id,
|
|
41171
|
+
name: clip((_c = result == null ? void 0 : result.session) == null ? void 0 : _c.name, 120),
|
|
41172
|
+
agent: clip((_d = result == null ? void 0 : result.session) == null ? void 0 : _d.agent, 60),
|
|
41173
|
+
project: clip((_e = result == null ? void 0 : result.session) == null ? void 0 : _e.project, 160)
|
|
41174
|
+
},
|
|
41175
|
+
messages: snapshot.messages,
|
|
41176
|
+
truncated: (result == null ? void 0 : result.truncated) === true || snapshot.truncated
|
|
41177
|
+
});
|
|
41178
|
+
} catch (_) {
|
|
41179
|
+
return sendJson(response, 503, { error: "The conversation could not be read" });
|
|
41180
|
+
}
|
|
41181
|
+
}
|
|
40961
41182
|
let target;
|
|
40962
41183
|
try {
|
|
40963
41184
|
target = decodeRemoteSessionId(body.target_session_id);
|
|
@@ -40976,9 +41197,9 @@ var require_headless_session_bridge = __commonJS({
|
|
|
40976
41197
|
return sendJson(response, 200, {
|
|
40977
41198
|
session: {
|
|
40978
41199
|
id: body.target_session_id,
|
|
40979
|
-
name: clip((
|
|
40980
|
-
agent: clip((
|
|
40981
|
-
project: clip((
|
|
41200
|
+
name: clip((_f = result == null ? void 0 : result.session) == null ? void 0 : _f.name, 120),
|
|
41201
|
+
agent: clip((_g = result == null ? void 0 : result.session) == null ? void 0 : _g.agent, 60),
|
|
41202
|
+
project: clip((_h = result == null ? void 0 : result.session) == null ? void 0 : _h.project, 160),
|
|
40982
41203
|
host: state.runtime.name || "Paired Mac"
|
|
40983
41204
|
},
|
|
40984
41205
|
messages: snapshot.messages,
|
|
@@ -40998,10 +41219,30 @@ var require_headless_session_bridge = __commonJS({
|
|
|
40998
41219
|
this._pruneReplies();
|
|
40999
41220
|
if (messageType === "response") {
|
|
41000
41221
|
const pending = this.pendingReplies.get(body.reply_to_request_id);
|
|
41001
|
-
if (!pending || pending.direction
|
|
41222
|
+
if (!pending || !["incoming", "local"].includes(pending.direction) || pending.sourceSessionId !== body.target_session_id || pending.targetSessionId !== sourceSessionId) {
|
|
41002
41223
|
return sendJson(response, 409, { error: "The response does not match an active session request" });
|
|
41003
41224
|
}
|
|
41004
41225
|
const source2 = this._sourceSession(sourceSessionId);
|
|
41226
|
+
if (pending.direction === "local") {
|
|
41227
|
+
try {
|
|
41228
|
+
const result = await this.deliverMessage({
|
|
41229
|
+
targetSessionId: pending.sourceSessionId,
|
|
41230
|
+
sourceSessionId,
|
|
41231
|
+
sourceName: (source2 == null ? void 0 : source2.title) || `${(source2 == null ? void 0 : source2.agent) || "CAS Cloud"} session`,
|
|
41232
|
+
sourceAgent: (source2 == null ? void 0 : source2.agent) || (source2 == null ? void 0 : source2.provider) || "agent",
|
|
41233
|
+
message: body.message.trim(),
|
|
41234
|
+
messageType: "response",
|
|
41235
|
+
communicationRequestId: body.reply_to_request_id
|
|
41236
|
+
});
|
|
41237
|
+
this.pendingReplies.delete(body.reply_to_request_id);
|
|
41238
|
+
return sendJson(response, 200, {
|
|
41239
|
+
success: true,
|
|
41240
|
+
status: (result == null ? void 0 : result.status) === "queued" ? "queued" : "delivered"
|
|
41241
|
+
});
|
|
41242
|
+
} catch (_) {
|
|
41243
|
+
return sendJson(response, 503, { error: "The session could not receive the response" });
|
|
41244
|
+
}
|
|
41245
|
+
}
|
|
41005
41246
|
if (!pending.reply({
|
|
41006
41247
|
sourceSessionId: pending.replyTargetSessionId,
|
|
41007
41248
|
targetSessionId: pending.remoteSourceSessionId,
|
|
@@ -41014,6 +41255,37 @@ var require_headless_session_bridge = __commonJS({
|
|
|
41014
41255
|
this.pendingReplies.delete(body.reply_to_request_id);
|
|
41015
41256
|
return sendJson(response, 200, { success: true, status: "delivered" });
|
|
41016
41257
|
}
|
|
41258
|
+
if (body.target_session_id === sourceSessionId) {
|
|
41259
|
+
return sendJson(response, 400, { error: "A session cannot message itself" });
|
|
41260
|
+
}
|
|
41261
|
+
const source = this._sourceSession(sourceSessionId);
|
|
41262
|
+
if (this._sourceSession(body.target_session_id)) {
|
|
41263
|
+
const communicationRequestId2 = crypto.randomUUID();
|
|
41264
|
+
this._rememberReply(communicationRequestId2, {
|
|
41265
|
+
direction: "local",
|
|
41266
|
+
sourceSessionId,
|
|
41267
|
+
targetSessionId: body.target_session_id
|
|
41268
|
+
});
|
|
41269
|
+
try {
|
|
41270
|
+
const result = await this.deliverMessage({
|
|
41271
|
+
targetSessionId: body.target_session_id,
|
|
41272
|
+
sourceSessionId,
|
|
41273
|
+
sourceName: (source == null ? void 0 : source.title) || `${(source == null ? void 0 : source.agent) || "CAS Cloud"} session`,
|
|
41274
|
+
sourceAgent: (source == null ? void 0 : source.agent) || (source == null ? void 0 : source.provider) || "agent",
|
|
41275
|
+
message: body.message.trim(),
|
|
41276
|
+
messageType: "request",
|
|
41277
|
+
communicationRequestId: communicationRequestId2
|
|
41278
|
+
});
|
|
41279
|
+
return sendJson(response, 200, {
|
|
41280
|
+
success: true,
|
|
41281
|
+
status: (result == null ? void 0 : result.status) === "queued" ? "queued" : "delivered",
|
|
41282
|
+
request_id: communicationRequestId2
|
|
41283
|
+
});
|
|
41284
|
+
} catch (_) {
|
|
41285
|
+
this.pendingReplies.delete(communicationRequestId2);
|
|
41286
|
+
return sendJson(response, 503, { error: "The session could not receive the request" });
|
|
41287
|
+
}
|
|
41288
|
+
}
|
|
41017
41289
|
let target;
|
|
41018
41290
|
try {
|
|
41019
41291
|
target = decodeRemoteSessionId(body.target_session_id);
|
|
@@ -41021,7 +41293,6 @@ var require_headless_session_bridge = __commonJS({
|
|
|
41021
41293
|
return sendJson(response, 400, { error: error.message });
|
|
41022
41294
|
}
|
|
41023
41295
|
if (!this._remoteClient(target.runtimeId)) return sendJson(response, 404, { error: "The remote session is unavailable" });
|
|
41024
|
-
const source = this._sourceSession(sourceSessionId);
|
|
41025
41296
|
const communicationRequestId = crypto.randomUUID();
|
|
41026
41297
|
this._rememberReply(communicationRequestId, {
|
|
41027
41298
|
direction: "outgoing",
|
|
@@ -41361,7 +41632,8 @@ var require_headless_project_registry = __commonJS({
|
|
|
41361
41632
|
onOperation = () => {
|
|
41362
41633
|
},
|
|
41363
41634
|
maxConcurrentClones = MAX_CLONES,
|
|
41364
|
-
stopTimeoutMs = 2e3
|
|
41635
|
+
stopTimeoutMs = 2e3,
|
|
41636
|
+
platform = process.platform
|
|
41365
41637
|
}) {
|
|
41366
41638
|
if (!(database == null ? void 0 : database.db)) throw new Error("HeadlessProjectRegistry requires a SQLite database");
|
|
41367
41639
|
this.database = database;
|
|
@@ -41372,6 +41644,7 @@ var require_headless_project_registry = __commonJS({
|
|
|
41372
41644
|
this.onOperation = onOperation;
|
|
41373
41645
|
this.maxConcurrentClones = maxConcurrentClones;
|
|
41374
41646
|
this.stopTimeoutMs = stopTimeoutMs;
|
|
41647
|
+
this.platform = platform;
|
|
41375
41648
|
this.stopping = false;
|
|
41376
41649
|
this.running = /* @__PURE__ */ new Map();
|
|
41377
41650
|
this.queue = [];
|
|
@@ -41564,7 +41837,7 @@ var require_headless_project_registry = __commonJS({
|
|
|
41564
41837
|
throw runtimeError("clone_root_insecure", "The configured clone root is not secure");
|
|
41565
41838
|
}
|
|
41566
41839
|
const effectiveUid = typeof process.geteuid === "function" ? process.geteuid() : null;
|
|
41567
|
-
if (!stat.isDirectory() || effectiveUid !== null && stat.uid !== effectiveUid || (stat.mode & 18) !== 0) {
|
|
41840
|
+
if (!stat.isDirectory() || this.platform !== "win32" && (effectiveUid !== null && stat.uid !== effectiveUid || (stat.mode & 18) !== 0)) {
|
|
41568
41841
|
throw runtimeError("clone_root_insecure", "The configured clone root is not secure");
|
|
41569
41842
|
}
|
|
41570
41843
|
return stat;
|
|
@@ -41611,6 +41884,46 @@ var require_headless_project_registry = __commonJS({
|
|
|
41611
41884
|
getRoots() {
|
|
41612
41885
|
return this.db.prepare("SELECT root_id, name FROM runtime_project_roots ORDER BY created_at, root_id").all().map((root) => ({ rootId: root.root_id, name: String(root.name).slice(0, 200) }));
|
|
41613
41886
|
}
|
|
41887
|
+
gitAvailability() {
|
|
41888
|
+
return new Promise((resolve) => {
|
|
41889
|
+
var _a, _b;
|
|
41890
|
+
let child;
|
|
41891
|
+
let output = "";
|
|
41892
|
+
let settled = false;
|
|
41893
|
+
const finish = (result) => {
|
|
41894
|
+
if (settled) return;
|
|
41895
|
+
settled = true;
|
|
41896
|
+
clearTimeout(timer);
|
|
41897
|
+
resolve(result);
|
|
41898
|
+
};
|
|
41899
|
+
const timer = setTimeout(() => {
|
|
41900
|
+
try {
|
|
41901
|
+
child == null ? void 0 : child.kill();
|
|
41902
|
+
} catch (_) {
|
|
41903
|
+
}
|
|
41904
|
+
finish({ available: false });
|
|
41905
|
+
}, 2e3);
|
|
41906
|
+
(_a = timer.unref) == null ? void 0 : _a.call(timer);
|
|
41907
|
+
try {
|
|
41908
|
+
child = this.spawnImpl("git", ["--version"], {
|
|
41909
|
+
shell: false,
|
|
41910
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
41911
|
+
windowsHide: true
|
|
41912
|
+
});
|
|
41913
|
+
(_b = child.stdout) == null ? void 0 : _b.on("data", (chunk) => {
|
|
41914
|
+
output = `${output}${String(chunk)}`.slice(0, 200);
|
|
41915
|
+
});
|
|
41916
|
+
child.once("error", () => finish({ available: false }));
|
|
41917
|
+
child.once("close", (code) => {
|
|
41918
|
+
var _a2;
|
|
41919
|
+
const version = (_a2 = /^git version\s+([^\s]+)/i.exec(output.trim())) == null ? void 0 : _a2[1];
|
|
41920
|
+
finish(code === 0 ? { available: true, ...version ? { version } : {} } : { available: false });
|
|
41921
|
+
});
|
|
41922
|
+
} catch (_) {
|
|
41923
|
+
finish({ available: false });
|
|
41924
|
+
}
|
|
41925
|
+
});
|
|
41926
|
+
}
|
|
41614
41927
|
listDirectories({ rootId, relativePath = "." } = {}) {
|
|
41615
41928
|
const root = this._root(rootId);
|
|
41616
41929
|
const currentPath = validateRelativePath(relativePath || ".");
|
|
@@ -42030,6 +42343,7 @@ var require_headless_project_registry = __commonJS({
|
|
|
42030
42343
|
contained,
|
|
42031
42344
|
runtimeError,
|
|
42032
42345
|
validateGitUrl,
|
|
42346
|
+
cloneDirectoryName,
|
|
42033
42347
|
validateCloneChildName,
|
|
42034
42348
|
validateRelativePath
|
|
42035
42349
|
};
|
|
@@ -45172,7 +45486,7 @@ var require_database = __commonJS({
|
|
|
45172
45486
|
{ status_key: "needs_testing", label: "Needs testing", color: "#3b82f6", icon: "flask-conical", sort_order: 2, is_default: 1, agent_settable: 1, prompt: "Set it when you finish the implementation and the work is pending the user testing it manually. Do not set it if there are still things left to implement." },
|
|
45173
45487
|
{ status_key: "working", label: "Working", color: "#fbbf24", icon: "hammer", sort_order: 3, is_default: 1, agent_settable: 1, prompt: "Set it when you start working on any request and while you are implementing, investigating or fixing something." },
|
|
45174
45488
|
{ status_key: "done", label: "Done", color: "#22c55e", icon: "circle-check", sort_order: 4, is_default: 1, agent_settable: 1, prompt: "Set it when the work is completely finished: implemented, validated and with its commit/push done when applicable. It is the final state." },
|
|
45175
|
-
{ status_key: "idle", label: "Idle", color: "#6b7280", icon: "circle-dashed", sort_order: 5, is_default: 1, agent_settable: 0, prompt: "Set by the app
|
|
45489
|
+
{ status_key: "idle", label: "Idle", color: "#6b7280", icon: "circle-dashed", sort_order: 5, is_default: 1, agent_settable: 0, prompt: "Set by the app when an agent is resting without an explicit work status, including after a reply finishes. It does not mean the work is complete or that user input is required. Agents cannot set this status." }
|
|
45176
45490
|
];
|
|
45177
45491
|
var IDLE_TERMINAL_STATUS_KEY = "idle";
|
|
45178
45492
|
var IDLE_STATUS_SEEDED_SETTING = "terminal_status_idle_seeded";
|
|
@@ -45184,7 +45498,8 @@ var require_database = __commonJS({
|
|
|
45184
45498
|
blocked: 5,
|
|
45185
45499
|
done: 6
|
|
45186
45500
|
};
|
|
45187
|
-
var
|
|
45501
|
+
var LEGACY_DEFAULT_PROMPTS = {
|
|
45502
|
+
idle: "Set by the app on an agent that has just been opened and has not been given any work yet. Agents cannot set this status; it clears itself as soon as you send the agent something.",
|
|
45188
45503
|
working: "Ponlo al empezar a trabajar en cualquier petici\xF3n y mientras est\xE9s implementando, investigando o arreglando algo.",
|
|
45189
45504
|
needs_input: "Ponlo cuando pares porque necesites una respuesta o decisi\xF3n del usuario para continuar (una pregunta, una elecci\xF3n de dise\xF1o, un permiso).",
|
|
45190
45505
|
needs_testing: "Ponlo cuando termines la implementaci\xF3n y el trabajo quede pendiente de que el usuario lo pruebe a mano. No lo pongas si a\xFAn quedan cosas por implementar.",
|
|
@@ -45198,14 +45513,14 @@ var require_database = __commonJS({
|
|
|
45198
45513
|
label: "Blocked",
|
|
45199
45514
|
color: "#ef4444",
|
|
45200
45515
|
prompt_en: "Set it when you cannot make progress due to something external that does not depend on you or the user: broken CI, a dependency that is down, failing permissions, a third-party bug.",
|
|
45201
|
-
prompt_es:
|
|
45516
|
+
prompt_es: LEGACY_DEFAULT_PROMPTS.blocked
|
|
45202
45517
|
},
|
|
45203
45518
|
{
|
|
45204
45519
|
status_key: "pending_commit",
|
|
45205
45520
|
label: "Pending commit/push",
|
|
45206
45521
|
color: "#a78bfa",
|
|
45207
45522
|
prompt_en: "Set it when the user has already validated the work and only the commit or push remains.",
|
|
45208
|
-
prompt_es:
|
|
45523
|
+
prompt_es: LEGACY_DEFAULT_PROMPTS.pending_commit
|
|
45209
45524
|
}
|
|
45210
45525
|
];
|
|
45211
45526
|
var app;
|
|
@@ -46083,7 +46398,7 @@ var require_database = __commonJS({
|
|
|
46083
46398
|
console.error("Error migrating idle terminal status:", error);
|
|
46084
46399
|
}
|
|
46085
46400
|
}
|
|
46086
|
-
// Migration: upgrade the legacy
|
|
46401
|
+
// Migration: upgrade the legacy factory prompts to the English ones.
|
|
46087
46402
|
// Only touches default statuses whose prompt is still the legacy string
|
|
46088
46403
|
// VERBATIM (i.e. the user never edited it), so user wording always wins.
|
|
46089
46404
|
// Idempotent: once upgraded, no row matches any more.
|
|
@@ -46096,7 +46411,7 @@ var require_database = __commonJS({
|
|
|
46096
46411
|
`);
|
|
46097
46412
|
const migrate = this.db.transaction(() => {
|
|
46098
46413
|
for (const status of DEFAULT_TERMINAL_STATUSES) {
|
|
46099
|
-
const legacy =
|
|
46414
|
+
const legacy = LEGACY_DEFAULT_PROMPTS[status.status_key];
|
|
46100
46415
|
if (!legacy) continue;
|
|
46101
46416
|
update.run({
|
|
46102
46417
|
status_key: status.status_key,
|
|
@@ -49271,6 +49586,7 @@ var require_headless_runtime = __commonJS({
|
|
|
49271
49586
|
"project.register",
|
|
49272
49587
|
"project.clone",
|
|
49273
49588
|
"project.clone.cancel",
|
|
49589
|
+
"project.git.availability",
|
|
49274
49590
|
"project.unregister",
|
|
49275
49591
|
"shortcuts.manage",
|
|
49276
49592
|
"session.action",
|
|
@@ -49282,6 +49598,7 @@ var require_headless_runtime = __commonJS({
|
|
|
49282
49598
|
"providers.list",
|
|
49283
49599
|
"provider.install",
|
|
49284
49600
|
"provider.login.describe",
|
|
49601
|
+
"session.restart",
|
|
49285
49602
|
"provider.login.start",
|
|
49286
49603
|
"provider.login.submit",
|
|
49287
49604
|
"provider.login.cancel",
|
|
@@ -49754,17 +50071,20 @@ var require_headless_runtime = __commonJS({
|
|
|
49754
50071
|
};
|
|
49755
50072
|
const listCoordinatedSessions = () => ({
|
|
49756
50073
|
sessions: Array.from(runtime.sessions.values()).flatMap((session) => {
|
|
49757
|
-
var _a, _b;
|
|
50074
|
+
var _a, _b, _c, _d;
|
|
49758
50075
|
return isCoordinatedSessionEligible(session) ? [{
|
|
49759
50076
|
id: session.terminalUuid,
|
|
49760
50077
|
name: session.title || `${session.agent || "Agent"} session`,
|
|
49761
50078
|
agent: session.agent || session.provider || "",
|
|
50079
|
+
agent_id: session.agent || session.provider || "",
|
|
49762
50080
|
project: ((_a = session.project) == null ? void 0 : _a.name) || "",
|
|
50081
|
+
project_icon: ((_b = session.project) == null ? void 0 : _b.icon) || "",
|
|
50082
|
+
project_color: ((_c = session.project) == null ? void 0 : _c.color) || "",
|
|
49763
50083
|
goal: session.goal || "",
|
|
49764
50084
|
activity: session.activity || "",
|
|
49765
50085
|
status: session.workStatus || "",
|
|
49766
50086
|
surface: "chat",
|
|
49767
|
-
state: session.workStatus === "needs_input" ? "needs_input" : ((
|
|
50087
|
+
state: session.workStatus === "needs_input" ? "needs_input" : ((_d = session.currentTurn) == null ? void 0 : _d.state) === "running" ? "working" : "idle"
|
|
49768
50088
|
}] : [];
|
|
49769
50089
|
}).slice(0, 100)
|
|
49770
50090
|
});
|
|
@@ -50038,6 +50358,7 @@ ${message}`;
|
|
|
50038
50358
|
registerProject: (payload) => registry.register(payload),
|
|
50039
50359
|
cloneProject: (payload) => registry.clone(payload),
|
|
50040
50360
|
cancelProjectClone: (payload) => registry.cancelClone(payload),
|
|
50361
|
+
gitAvailability: () => registry.gitAvailability(),
|
|
50041
50362
|
unregisterProject: (payload) => {
|
|
50042
50363
|
const busy = startingProjects.has(payload.projectId) || Array.from(runtime.sessions.values()).some((session) => {
|
|
50043
50364
|
var _a;
|
|
@@ -50114,6 +50435,8 @@ ${message}`;
|
|
|
50114
50435
|
peerRuntimeNetwork,
|
|
50115
50436
|
dataPath: resolvedDataPath,
|
|
50116
50437
|
deliverMessage: deliverCoordinatedMessage,
|
|
50438
|
+
listLocalSessions: listCoordinatedSessions,
|
|
50439
|
+
readLocalTranscript: readCoordinatedTranscript,
|
|
50117
50440
|
createPairingLink: async () => {
|
|
50118
50441
|
const pairing = await relay.createPairing();
|
|
50119
50442
|
return { url: desktopConnectionLink(pairing), expiresAt: pairing.expiresAt };
|
|
@@ -50720,7 +51043,7 @@ var require_cas = __commonJS({
|
|
|
50720
51043
|
loadIdentity,
|
|
50721
51044
|
resolveProject
|
|
50722
51045
|
} = require_headless_runtime();
|
|
50723
|
-
var version = true ? "0.0.
|
|
51046
|
+
var version = true ? "0.0.17" : JSON.parse(fs.readFileSync(path.join(__dirname, "..", "..", "package.json"), "utf8")).version;
|
|
50724
51047
|
function help() {
|
|
50725
51048
|
return `CAS CLI ${version}
|
|
50726
51049
|
|