@cjhyy/code-shell-core 0.6.0-rc.12 → 0.6.0-rc.13
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/cc-orchestrator/cwd-normalize.d.ts +2 -0
- package/dist/cc-orchestrator/cwd-normalize.js +19 -0
- package/dist/cc-orchestrator/external-agent-bindings.d.ts +27 -0
- package/dist/cc-orchestrator/external-agent-bindings.js +150 -0
- package/dist/cc-orchestrator/external-agent-session-store.d.ts +23 -0
- package/dist/cc-orchestrator/external-agent-session-store.js +144 -0
- package/dist/context/manager.d.ts +3 -1
- package/dist/context/manager.js +24 -15
- package/dist/credentials/types.d.ts +2 -2
- package/dist/engine/engine.d.ts +5 -1
- package/dist/engine/engine.js +92 -51
- package/dist/engine/turn-loop.js +1 -1
- package/dist/git/worktree.d.ts +49 -6
- package/dist/git/worktree.js +265 -31
- package/dist/index.d.ts +4 -3
- package/dist/index.js +3 -2
- package/dist/logging/logger.js +6 -6
- package/dist/plugins/installer/installFromSource.js +9 -1
- package/dist/plugins/installer/sourcePath.d.ts +9 -0
- package/dist/plugins/installer/sourcePath.js +50 -0
- package/dist/plugins/pluginInstaller.js +24 -22
- package/dist/protocol/chat-session-manager.d.ts +1 -0
- package/dist/protocol/chat-session-manager.js +13 -0
- package/dist/protocol/server.d.ts +8 -0
- package/dist/protocol/server.js +45 -8
- package/dist/protocol/types.d.ts +4 -0
- package/dist/protocol/types.js +4 -0
- package/dist/run/FileRunStore.js +10 -1
- package/dist/run/Heartbeat.js +12 -0
- package/dist/run/RunApprovalBackend.d.ts +3 -0
- package/dist/run/RunApprovalBackend.js +41 -6
- package/dist/run/RunLock.js +2 -0
- package/dist/run/RunManager.d.ts +2 -0
- package/dist/run/RunManager.js +64 -24
- package/dist/run/ids.d.ts +2 -0
- package/dist/run/ids.js +23 -0
- package/dist/session/session-manager.d.ts +35 -1
- package/dist/session/session-manager.js +189 -2
- package/dist/settings/manager.d.ts +1 -0
- package/dist/settings/manager.js +45 -26
- package/dist/settings/schema-export.d.ts +2 -3
- package/dist/settings/schema-export.js +2 -3
- package/dist/tool-system/builtin/background-jobs.d.ts +8 -1
- package/dist/tool-system/builtin/background-jobs.js +8 -1
- package/dist/tool-system/builtin/config.d.ts +2 -1
- package/dist/tool-system/builtin/config.js +16 -11
- package/dist/tool-system/builtin/drive-claude-code.d.ts +15 -2
- package/dist/tool-system/builtin/drive-claude-code.js +174 -39
- package/dist/tool-system/builtin/edit.js +5 -2
- package/dist/tool-system/builtin/generate-video.d.ts +1 -0
- package/dist/tool-system/builtin/generate-video.js +13 -4
- package/dist/tool-system/builtin/index.js +5 -1
- package/dist/tool-system/builtin/lsp.d.ts +2 -1
- package/dist/tool-system/builtin/lsp.js +6 -3
- package/dist/tool-system/builtin/notebook-edit.js +5 -2
- package/dist/tool-system/builtin/read.js +5 -2
- package/dist/tool-system/builtin/worktree.d.ts +2 -4
- package/dist/tool-system/builtin/worktree.js +250 -75
- package/dist/tool-system/builtin/write.js +5 -3
- package/dist/tool-system/context.d.ts +12 -0
- package/dist/tool-system/mcp-manager.d.ts +8 -0
- package/dist/tool-system/mcp-manager.js +32 -11
- package/dist/types.d.ts +12 -0
- package/dist/utils/toolDisplay.js +1 -1
- package/package.json +1 -1
package/dist/engine/engine.js
CHANGED
|
@@ -34,7 +34,7 @@ import { PLAN_MODE_ALLOWED_TOOLS } from "../tool-system/plan-mode-allowlist.js";
|
|
|
34
34
|
import { PromptComposer } from "../prompt/composer.js";
|
|
35
35
|
import { SessionManager } from "../session/session-manager.js";
|
|
36
36
|
import { ModelFacade } from "./model-facade.js";
|
|
37
|
-
import { logger,
|
|
37
|
+
import { logger, runWithSid, getCurrentSid } from "../logging/logger.js";
|
|
38
38
|
import { recordSessionStart, recordSessionEnd } from "../logging/session-recorder.js";
|
|
39
39
|
import { sanitizeContent, sanitizeTaskString } from "../logging/sanitize-messages.js";
|
|
40
40
|
import { TurnLoop } from "./turn-loop.js";
|
|
@@ -129,7 +129,7 @@ export function resolveChildLlm(modelKey, pool, parentLlm) {
|
|
|
129
129
|
* Names in `disabledAgents` are filtered out so the LLM never sees them.
|
|
130
130
|
*/
|
|
131
131
|
/**
|
|
132
|
-
* Resolve the working directory for a run. Precedence:
|
|
132
|
+
* Resolve the working directory for a run. Precedence for legacy sessions:
|
|
133
133
|
* options.cwd > resumed session's state.cwd > config.cwd > process.cwd()
|
|
134
134
|
*
|
|
135
135
|
* The session-cwd tier is what stops a project-bound session from being
|
|
@@ -735,20 +735,45 @@ export class Engine {
|
|
|
735
735
|
* Run a task from start to finish.
|
|
736
736
|
*/
|
|
737
737
|
async run(task, options) {
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
// loading its own agents/settings/memory even if the host's UI repo
|
|
741
|
-
// selection has drifted to null. Only probe on omission — an explicit cwd
|
|
742
|
-
// always wins, and a fresh session has nothing to recover.
|
|
743
|
-
const sessionCwd = options?.cwd === undefined && options?.sessionId
|
|
744
|
-
? this.sessionManager.readCwd(options.sessionId)
|
|
738
|
+
const workspaceResume = options?.sessionId && this.sessionManager.exists(options.sessionId)
|
|
739
|
+
? this.sessionManager.resolveSessionWorkspaceForResume(options.sessionId)
|
|
745
740
|
: undefined;
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
741
|
+
if (workspaceResume && !workspaceResume.ok) {
|
|
742
|
+
return {
|
|
743
|
+
text: `ERROR: ${workspaceResume.message}`,
|
|
744
|
+
reason: "completed",
|
|
745
|
+
sessionId: options.sessionId,
|
|
746
|
+
turnCount: 0,
|
|
747
|
+
usage: { promptTokens: 0, completionTokens: 0, totalTokens: 0 },
|
|
748
|
+
};
|
|
749
|
+
}
|
|
750
|
+
if (workspaceResume?.ok &&
|
|
751
|
+
workspaceResume.reason === "worktree_missing_branch_gone" &&
|
|
752
|
+
workspaceResume.message) {
|
|
753
|
+
return {
|
|
754
|
+
text: workspaceResume.message,
|
|
755
|
+
reason: "completed",
|
|
756
|
+
sessionId: options.sessionId,
|
|
757
|
+
turnCount: 0,
|
|
758
|
+
usage: { promptTokens: 0, completionTokens: 0, totalTokens: 0 },
|
|
759
|
+
};
|
|
760
|
+
}
|
|
761
|
+
// Existing P1 sessions resolve cwd from SessionWorkspace, even if the host
|
|
762
|
+
// passes a stale cwd. Legacy sessions without workspace keep the historical
|
|
763
|
+
// explicit-cwd precedence for backward compatibility.
|
|
764
|
+
const workspaceCwd = workspaceResume?.ok && workspaceResume.reason !== "legacy" ? workspaceResume.cwd : undefined;
|
|
765
|
+
const sessionCwd = workspaceCwd === undefined && options?.cwd === undefined && options?.sessionId
|
|
766
|
+
? workspaceResume?.ok
|
|
767
|
+
? workspaceResume.cwd
|
|
768
|
+
: this.sessionManager.readCwd(options.sessionId)
|
|
769
|
+
: undefined;
|
|
770
|
+
const cwd = workspaceCwd ??
|
|
771
|
+
resolveRunCwd({
|
|
772
|
+
optionCwd: options?.cwd,
|
|
773
|
+
sessionCwd,
|
|
774
|
+
configCwd: this.config.cwd,
|
|
775
|
+
processCwd: process.cwd(),
|
|
776
|
+
});
|
|
752
777
|
// Wrap the caller's onStream so we can intercept `task_update`
|
|
753
778
|
// events emitted by TodoWrite and keep an in-engine snapshot.
|
|
754
779
|
// TaskGuard reads this snapshot at turn end to decide whether to
|
|
@@ -1013,23 +1038,7 @@ export class Engine {
|
|
|
1013
1038
|
},
|
|
1014
1039
|
sessionExists: (sessionId) => this.sessionManager.exists(sessionId),
|
|
1015
1040
|
};
|
|
1016
|
-
|
|
1017
|
-
// default. Read UNMERGED per-scope (getForScope) so a project that wrote no
|
|
1018
|
-
// sandbox genuinely follows global, rather than inheriting global's mode and
|
|
1019
|
-
// looking like it set one. Fixes "项目级配了不生效" + the scope model.
|
|
1020
|
-
let projectSandbox;
|
|
1021
|
-
let globalSandbox;
|
|
1022
|
-
try {
|
|
1023
|
-
const sm = this.getSettingsManager();
|
|
1024
|
-
if (this.config.isSubAgent !== true) {
|
|
1025
|
-
projectSandbox = sm.getForScope("project", cwd).sandbox;
|
|
1026
|
-
}
|
|
1027
|
-
globalSandbox = sm.getForScope("user").sandbox;
|
|
1028
|
-
}
|
|
1029
|
-
catch {
|
|
1030
|
-
// settings unavailable → fall through to per-run default
|
|
1031
|
-
}
|
|
1032
|
-
const sandboxConfig = resolveSandboxConfig(this.config.sandbox, projectSandbox, globalSandbox, this.config.headless === true);
|
|
1041
|
+
const sandboxConfig = this.resolveSandboxConfigForCwd(cwd);
|
|
1033
1042
|
// A2: explicit sandbox modes (seatbelt, bwrap) must fail closed
|
|
1034
1043
|
// per standard §S4. resolveSandboxBackend throws when an explicit
|
|
1035
1044
|
// mode is unavailable on this host; we let it propagate. The
|
|
@@ -1070,12 +1079,16 @@ export class Engine {
|
|
|
1070
1079
|
? sandboxBackend
|
|
1071
1080
|
: { ...sandboxBackend, network: sandboxConfig.network },
|
|
1072
1081
|
cwd,
|
|
1082
|
+
shellEnv: this.readShellEnv(cwd),
|
|
1073
1083
|
// TodoWrite reads this to push task_update events independently
|
|
1074
1084
|
// of its return value, so the UI's pinned task panel refreshes
|
|
1075
1085
|
// immediately rather than after the LLM next surfaces the
|
|
1076
1086
|
// snapshot. wrappedOnStream snoops the same channel to keep
|
|
1077
1087
|
// latestTodos current for TaskGuard.
|
|
1078
1088
|
streamCallback: options?.onStream,
|
|
1089
|
+
setCwd(nextCwd) {
|
|
1090
|
+
toolCtx.cwd = nextCwd;
|
|
1091
|
+
},
|
|
1079
1092
|
};
|
|
1080
1093
|
logger.info("engine.run", {
|
|
1081
1094
|
task: taskText.slice(0, 200),
|
|
@@ -1134,6 +1147,7 @@ export class Engine {
|
|
|
1134
1147
|
let session;
|
|
1135
1148
|
let messages;
|
|
1136
1149
|
let freshImageMessage;
|
|
1150
|
+
let resumedFromDisk = false;
|
|
1137
1151
|
const claimedClientMessageIds = new Set();
|
|
1138
1152
|
const claimClientMessageId = (bundle, clientMessageId, source) => {
|
|
1139
1153
|
if (!clientMessageId)
|
|
@@ -1151,6 +1165,7 @@ export class Engine {
|
|
|
1151
1165
|
return true;
|
|
1152
1166
|
};
|
|
1153
1167
|
if (options?.sessionId && this.sessionManager.exists(options.sessionId)) {
|
|
1168
|
+
resumedFromDisk = true;
|
|
1154
1169
|
session = this.sessionManager.resume(options.sessionId);
|
|
1155
1170
|
const cachedCompacted = this.compactedMessagesBySession.get(options.sessionId);
|
|
1156
1171
|
messages = cachedCompacted ? [...cachedCompacted] : session.transcript.toMessages();
|
|
@@ -1233,21 +1248,6 @@ export class Engine {
|
|
|
1233
1248
|
// with this value so `/undo` reverts exactly this turn's file changes.
|
|
1234
1249
|
// (Both resume and cold-start paths converge here.)
|
|
1235
1250
|
session.state.turnSeq = (session.state.turnSeq ?? 0) + 1;
|
|
1236
|
-
// Stamp the resolved session id for downstream logging.
|
|
1237
|
-
//
|
|
1238
|
-
// `setCurrentSid` updates the module-level fallback so any code path
|
|
1239
|
-
// running outside an ALS scope (bootstrap, /sid before a run starts)
|
|
1240
|
-
// still sees the latest sid.
|
|
1241
|
-
//
|
|
1242
|
-
// The real isolation comes from wrapping the rest of `run` in
|
|
1243
|
-
// `runWithSid(sid, async () => { ... })`: every `getCurrentSid()`
|
|
1244
|
-
// call inside that closure — including those inside `await`ed child
|
|
1245
|
-
// Engine.run() calls — reads sid from this scope's
|
|
1246
|
-
// AsyncLocalStorage binding, not the module global. Sibling Engines
|
|
1247
|
-
// running concurrently each get their own scope; an `enterSid` inside
|
|
1248
|
-
// a child mutates that child's scope only and doesn't leak back to
|
|
1249
|
-
// the parent's chain after `await child.run(...)` returns.
|
|
1250
|
-
setCurrentSid(session.state.sessionId);
|
|
1251
1251
|
// B2 / Gate 1: stamp the resolved sid onto the tool context so
|
|
1252
1252
|
// session-scoped side effects (background-agent completion
|
|
1253
1253
|
// notifications) attribute to the right session. toolCtx is created
|
|
@@ -1255,6 +1255,9 @@ export class Engine {
|
|
|
1255
1255
|
// the first point we can set it. After this assignment treat the
|
|
1256
1256
|
// field as immutable for the rest of the run.
|
|
1257
1257
|
toolCtx.sessionId = session.state.sessionId;
|
|
1258
|
+
toolCtx.setSessionWorkspace = (workspace) => {
|
|
1259
|
+
session.state.workspace = workspace;
|
|
1260
|
+
};
|
|
1258
1261
|
return runWithSid(session.state.sessionId, async () => {
|
|
1259
1262
|
recordSessionStart(session.state.sessionId, {
|
|
1260
1263
|
// Strip <codeshell-image> base64 payloads before they reach
|
|
@@ -1265,7 +1268,7 @@ export class Engine {
|
|
|
1265
1268
|
model: this.config.llm.model,
|
|
1266
1269
|
provider: this.config.llm.provider,
|
|
1267
1270
|
permissionMode: this.config.permissionMode ?? "acceptEdits",
|
|
1268
|
-
resumed:
|
|
1271
|
+
resumed: resumedFromDisk,
|
|
1269
1272
|
});
|
|
1270
1273
|
// Session-level hook: fired once per Engine.run() entry, regardless of
|
|
1271
1274
|
// cold-start vs resume. Handlers can return `messages` to inject a
|
|
@@ -1275,7 +1278,8 @@ export class Engine {
|
|
|
1275
1278
|
const sessionStartHook = await this.emitHook("on_session_start", {
|
|
1276
1279
|
sessionId: session.state.sessionId,
|
|
1277
1280
|
cwd,
|
|
1278
|
-
resumed:
|
|
1281
|
+
resumed: resumedFromDisk,
|
|
1282
|
+
source: resumedFromDisk ? "resume" : "startup",
|
|
1279
1283
|
});
|
|
1280
1284
|
// Per-turn hook: fired every time a new user prompt enters the loop.
|
|
1281
1285
|
// Equivalent to CC's UserPromptSubmit. Handlers can inject lightweight
|
|
@@ -1289,7 +1293,7 @@ export class Engine {
|
|
|
1289
1293
|
// and silently leaking attachment bytes through hooks is the kind of
|
|
1290
1294
|
// exfiltration risk a curious user-installed shell hook shouldn't carry.
|
|
1291
1295
|
prompt: taskText,
|
|
1292
|
-
resumed:
|
|
1296
|
+
resumed: resumedFromDisk,
|
|
1293
1297
|
});
|
|
1294
1298
|
// updatedPrompt: handler rewrote the user's prompt text. Replace the
|
|
1295
1299
|
// last user message we just pushed (cold-start: line ~511; resume:
|
|
@@ -2837,6 +2841,25 @@ export class Engine {
|
|
|
2837
2841
|
}
|
|
2838
2842
|
return cached;
|
|
2839
2843
|
}
|
|
2844
|
+
resolveSandboxConfigForCwd(cwd) {
|
|
2845
|
+
// Priority: config.sandbox → project settings.sandbox → global → per-run
|
|
2846
|
+
// default. Read UNMERGED per-scope (getForScope) so a project that wrote no
|
|
2847
|
+
// sandbox genuinely follows global, rather than inheriting global's mode and
|
|
2848
|
+
// looking like it set one. Fixes "项目级配了不生效" + the scope model.
|
|
2849
|
+
let projectSandbox;
|
|
2850
|
+
let globalSandbox;
|
|
2851
|
+
try {
|
|
2852
|
+
const sm = this.getSettingsManager();
|
|
2853
|
+
if (this.config.isSubAgent !== true) {
|
|
2854
|
+
projectSandbox = sm.getForScope("project", cwd).sandbox;
|
|
2855
|
+
}
|
|
2856
|
+
globalSandbox = sm.getForScope("user").sandbox;
|
|
2857
|
+
}
|
|
2858
|
+
catch {
|
|
2859
|
+
// settings unavailable → fall through to per-run default
|
|
2860
|
+
}
|
|
2861
|
+
return resolveSandboxConfig(this.config.sandbox, projectSandbox, globalSandbox, this.config.headless === true);
|
|
2862
|
+
}
|
|
2840
2863
|
/**
|
|
2841
2864
|
* Build the shell env layered onto the Bash tool / background shells (see
|
|
2842
2865
|
* mergeShellEnv). Three user-configured sources, merged lowest → highest:
|
|
@@ -2931,9 +2954,23 @@ export class Engine {
|
|
|
2931
2954
|
return undefined;
|
|
2932
2955
|
}
|
|
2933
2956
|
}
|
|
2957
|
+
async resolveWorktreeSetupSandbox(cwd) {
|
|
2958
|
+
if (!cwd)
|
|
2959
|
+
return undefined;
|
|
2960
|
+
const sandboxConfig = this.resolveSandboxConfigForCwd(cwd);
|
|
2961
|
+
const sandboxBackend = this.runtime
|
|
2962
|
+
? await this.runtime.resolveSandbox(sandboxConfig, cwd)
|
|
2963
|
+
: await this.resolveSandboxWithoutRuntime(sandboxConfig, cwd);
|
|
2964
|
+
return sandboxBackend.name === "off"
|
|
2965
|
+
? sandboxBackend
|
|
2966
|
+
: { ...sandboxBackend, network: sandboxConfig.network };
|
|
2967
|
+
}
|
|
2968
|
+
readWorktreeSetupShellEnv(cwd) {
|
|
2969
|
+
return this.readShellEnv(cwd);
|
|
2970
|
+
}
|
|
2934
2971
|
buildToolContext() {
|
|
2935
2972
|
const { disabledSkills, disabledPlugins } = this.readDisabledLists();
|
|
2936
|
-
|
|
2973
|
+
const ctx = {
|
|
2937
2974
|
shellEnv: this.readShellEnv(this.config.cwd),
|
|
2938
2975
|
cwd: this.config.cwd ?? process.cwd(),
|
|
2939
2976
|
llmConfig: this.config.llm,
|
|
@@ -2961,6 +2998,10 @@ export class Engine {
|
|
|
2961
2998
|
// opts out via config. Otherwise allowed.
|
|
2962
2999
|
allowBackgroundShells: this.config.isSubAgent === true ? false : this.config.allowBackgroundShells !== false,
|
|
2963
3000
|
};
|
|
3001
|
+
ctx.setCwd = (cwd) => {
|
|
3002
|
+
ctx.cwd = cwd;
|
|
3003
|
+
};
|
|
3004
|
+
return ctx;
|
|
2964
3005
|
}
|
|
2965
3006
|
/**
|
|
2966
3007
|
* Read settings.disabledSkills + settings.disabledPlugins in a single
|
package/dist/engine/turn-loop.js
CHANGED
|
@@ -553,7 +553,7 @@ export class TurnLoop {
|
|
|
553
553
|
// compaction decisions use hybrid (actual + delta) estimation rather than
|
|
554
554
|
// pure heuristics. Without this the manager falls back to char/4 estimates.
|
|
555
555
|
if (response.usage?.promptTokens !== undefined) {
|
|
556
|
-
this.deps.contextManager.recordActualUsage(response.usage.promptTokens, messages.length);
|
|
556
|
+
this.deps.contextManager.recordActualUsage(response.usage.promptTokens, messages.length, messages);
|
|
557
557
|
}
|
|
558
558
|
messages = this.markPendingImagesConsumed(messages);
|
|
559
559
|
// Truncation that cut off a TOOL CALL: the model overflowed
|
package/dist/git/worktree.d.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Git worktree management — create/remove isolated worktrees for agents.
|
|
3
3
|
*/
|
|
4
4
|
import type { SandboxBackend } from "../tool-system/sandbox/index.js";
|
|
5
|
+
import type { SessionWorkspace } from "../types.js";
|
|
5
6
|
export interface WorktreeSession {
|
|
6
7
|
originalCwd: string;
|
|
7
8
|
worktreePath: string;
|
|
@@ -34,6 +35,12 @@ export declare function validateWorktreeSlug(slug: string): void;
|
|
|
34
35
|
* Find the canonical git root (resolves worktree → main repo).
|
|
35
36
|
*/
|
|
36
37
|
export declare function findGitRoot(cwd: string): string;
|
|
38
|
+
export declare function findMainWorktreeRoot(cwd: string): string;
|
|
39
|
+
export declare function findWorktreeForBranch(cwd: string, branch: string): string | undefined;
|
|
40
|
+
export declare function assertBranchNotCheckedOut(cwd: string, branch: string): void;
|
|
41
|
+
export declare function branchExists(cwd: string, branch: string): boolean;
|
|
42
|
+
export declare function isGitWorktreeRoot(cwd: string): boolean;
|
|
43
|
+
export declare function currentBranch(cwd: string): string | undefined;
|
|
37
44
|
/**
|
|
38
45
|
* Create an isolated git worktree for an agent session.
|
|
39
46
|
*/
|
|
@@ -70,15 +77,51 @@ export declare function runWorktreeSetup(worktreePath: string, script: string |
|
|
|
70
77
|
timeoutMs?: number;
|
|
71
78
|
signal?: AbortSignal;
|
|
72
79
|
}): Promise<WorktreeSetupResult>;
|
|
80
|
+
export interface RemoveWorktreeResult {
|
|
81
|
+
/** True once `git worktree remove` completed and the directory is gone. */
|
|
82
|
+
dirRemoved: boolean;
|
|
83
|
+
/** The branch targeted for deletion when removeBranch=true. */
|
|
84
|
+
branch?: string;
|
|
85
|
+
/** True when removeBranch=true and branch deletion completed. */
|
|
86
|
+
branchDeleted?: boolean;
|
|
87
|
+
/** Non-empty when the worktree directory is gone but branch deletion failed. */
|
|
88
|
+
branchError?: string;
|
|
89
|
+
}
|
|
73
90
|
/**
|
|
74
91
|
* Remove a worktree and optionally its branch.
|
|
75
92
|
*/
|
|
76
|
-
export declare function removeWorktree(worktreePath: string, removeBranch?: boolean):
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
93
|
+
export declare function removeWorktree(worktreePath: string, removeBranch?: boolean): RemoveWorktreeResult;
|
|
94
|
+
export declare function worktreeHasUncommittedChanges(worktreePath: string): boolean;
|
|
95
|
+
export declare function worktreeHasUncommittedOrAheadChanges(worktreePath: string, baseRef?: string): boolean;
|
|
96
|
+
export interface WorktreeDiffSummary {
|
|
97
|
+
/** Best-effort base used for the branch comparison, usually main/master. */
|
|
98
|
+
baseRef?: string;
|
|
99
|
+
/** Unique files changed either by commits ahead of base or by uncommitted changes. */
|
|
100
|
+
changedFiles: number;
|
|
101
|
+
/** Commits reachable from HEAD but not from baseRef. */
|
|
102
|
+
aheadCommits: number;
|
|
103
|
+
/** True when `git status --porcelain` reports local changes. */
|
|
104
|
+
hasUncommittedChanges: boolean;
|
|
105
|
+
}
|
|
106
|
+
export interface WorktreeWorkspaceOwner {
|
|
107
|
+
sessionId: string;
|
|
108
|
+
workspace?: SessionWorkspace;
|
|
109
|
+
}
|
|
110
|
+
export interface ListWorktreesOptions {
|
|
111
|
+
includeDiffSummary?: boolean;
|
|
112
|
+
currentSessionId?: string;
|
|
113
|
+
workspaceOwners?: WorktreeWorkspaceOwner[];
|
|
114
|
+
}
|
|
115
|
+
export interface WorktreeInfo {
|
|
81
116
|
path: string;
|
|
82
117
|
branch: string;
|
|
83
118
|
head: string;
|
|
84
|
-
|
|
119
|
+
isMain?: boolean;
|
|
120
|
+
diff?: WorktreeDiffSummary;
|
|
121
|
+
occupiedBySessionIds?: string[];
|
|
122
|
+
occupiedByOtherSession?: boolean;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* List active worktrees.
|
|
126
|
+
*/
|
|
127
|
+
export declare function listWorktrees(cwd: string, opts?: ListWorktreesOptions): WorktreeInfo[];
|