pi-landstrip 0.18.32 → 0.18.34
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/README.md +7 -3
- package/api.ts +2 -4
- package/dist/index.ts +45 -160
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -136,12 +136,16 @@ forms at one scope is an error.
|
|
|
136
136
|
Agent definitions accept `name`, `description`, `prompt`, `mode`, `model`,
|
|
137
137
|
`variant`, `temperature`, `top_p`, `steps`, `color`, `hidden`, `disable`,
|
|
138
138
|
`options`, and `permission`. `mode` is `primary`, `subagent`, or `all` and
|
|
139
|
-
defaults to `all`.
|
|
139
|
+
defaults to `all`. `/agents` Primary lists only `mode: primary` agents. The
|
|
140
|
+
Subagent tab lists `mode: subagent` and `mode: all` agents, including JSON and
|
|
141
|
+
Markdown definitions.
|
|
140
142
|
|
|
141
143
|
The built-in primary agents are `build` and `plan`; built-in subagents are
|
|
142
144
|
`general`, `scout`, and `explore`. Pi also loads Markdown agents from
|
|
143
|
-
`~/.pi/agent/agents/` and `.pi/agents/`. Project definitions
|
|
144
|
-
definitions
|
|
145
|
+
`~/.pi/agent/agents/` and `.pi/agents/`. Project definitions overlay global
|
|
146
|
+
definitions. Configured fields overlay Markdown agents with the same name, so a
|
|
147
|
+
model-only `landstrip.json` entry keeps the Markdown agent's mode, prompt, and
|
|
148
|
+
permissions.
|
|
145
149
|
|
|
146
150
|
## Commands and tasks
|
|
147
151
|
|
package/api.ts
CHANGED
|
@@ -6,6 +6,8 @@ import type { Readable, Writable } from 'node:stream';
|
|
|
6
6
|
|
|
7
7
|
import type { ExtensionAPI, ExtensionContext } from '@earendil-works/pi-coding-agent';
|
|
8
8
|
|
|
9
|
+
import { isRecord } from '@landstrip/landstrip/shared';
|
|
10
|
+
|
|
9
11
|
export const LANDSTRIP_CONTEXT_ENV = 'LANDSTRIP_CONTEXT';
|
|
10
12
|
export const LANDSTRIP_RUNTIME_VERSION = 2;
|
|
11
13
|
|
|
@@ -168,10 +170,6 @@ function eventBus(pi: ExtensionAPI): EventBusLike | undefined {
|
|
|
168
170
|
return (pi as ExtensionAPI & { events?: EventBusLike }).events;
|
|
169
171
|
}
|
|
170
172
|
|
|
171
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
172
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
173
|
function isRuntime(value: unknown): value is PiLandstripRuntimeV2 {
|
|
176
174
|
return (
|
|
177
175
|
isRecord(value) &&
|
package/dist/index.ts
CHANGED
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
isIP,
|
|
21
21
|
Socket as NetSocket
|
|
22
22
|
} from "node:net";
|
|
23
|
-
import {
|
|
23
|
+
import { tmpdir as tmpdir2 } from "node:os";
|
|
24
24
|
import { basename as basename3, dirname as dirname4, isAbsolute as isAbsolute3, join as join7, parse, resolve as resolve3, sep as sep4 } from "node:path";
|
|
25
25
|
import { StringDecoder as StringDecoder2 } from "node:string_decoder";
|
|
26
26
|
import { fileURLToPath as fileURLToPath2, URL } from "node:url";
|
|
@@ -35,8 +35,22 @@ import { matchesKey as matchesKey2, truncateToWidth as truncateToWidth3 } from "
|
|
|
35
35
|
import {
|
|
36
36
|
binaryPath
|
|
37
37
|
} from "@landstrip/landstrip";
|
|
38
|
+
import {
|
|
39
|
+
allowsAllDomains,
|
|
40
|
+
controlResponseLine,
|
|
41
|
+
domainMatchesAny,
|
|
42
|
+
formatLandstripTraps,
|
|
43
|
+
isDenialTrap,
|
|
44
|
+
isFilesystemTrap,
|
|
45
|
+
isQueryTrap,
|
|
46
|
+
parseLandstripTraps,
|
|
47
|
+
parseTrapLine,
|
|
48
|
+
pathUnderDirectory,
|
|
49
|
+
sessionScopeFor
|
|
50
|
+
} from "@landstrip/landstrip/shared";
|
|
38
51
|
|
|
39
52
|
// api.ts
|
|
53
|
+
import { isRecord } from "@landstrip/landstrip/shared";
|
|
40
54
|
var LANDSTRIP_CONTEXT_ENV = "LANDSTRIP_CONTEXT";
|
|
41
55
|
var LANDSTRIP_RUNTIME_VERSION = 2;
|
|
42
56
|
var RUNTIME_REGISTER_EVENT = "landstrip:runtime:register:v2";
|
|
@@ -44,9 +58,6 @@ var RUNTIME_DISCOVER_EVENT = "landstrip:runtime:discover:v2";
|
|
|
44
58
|
function eventBus(pi) {
|
|
45
59
|
return pi.events;
|
|
46
60
|
}
|
|
47
|
-
function isRecord(value) {
|
|
48
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
49
|
-
}
|
|
50
61
|
function publishLandstripRuntime(pi, runtime) {
|
|
51
62
|
const events = eventBus(pi);
|
|
52
63
|
if (!events)
|
|
@@ -198,15 +209,7 @@ var BUILT_IN_LANDSTRIP_CONFIG = {
|
|
|
198
209
|
import { readFileSync } from "node:fs";
|
|
199
210
|
import { homedir } from "node:os";
|
|
200
211
|
import { isAbsolute, join, resolve } from "node:path";
|
|
201
|
-
|
|
202
|
-
if (path === "~" || path === "$HOME")
|
|
203
|
-
return homedir();
|
|
204
|
-
if (path.startsWith("~/"))
|
|
205
|
-
return join(homedir(), path.slice(2));
|
|
206
|
-
if (path.startsWith("$HOME/"))
|
|
207
|
-
return join(homedir(), path.slice(6));
|
|
208
|
-
return path;
|
|
209
|
-
}
|
|
212
|
+
import { expandHomePath, isRecord as isRecord2 } from "@landstrip/landstrip/shared";
|
|
210
213
|
function expandFileReferences(text, baseDir) {
|
|
211
214
|
if (!text.includes("{file:"))
|
|
212
215
|
return text;
|
|
@@ -237,9 +240,6 @@ function expandFileReferences(text, baseDir) {
|
|
|
237
240
|
function formatError(error) {
|
|
238
241
|
return error instanceof Error ? error.message : String(error);
|
|
239
242
|
}
|
|
240
|
-
function isRecord2(value) {
|
|
241
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
242
|
-
}
|
|
243
243
|
var OPENCODE_THEME_COLORS = new Set([
|
|
244
244
|
"primary",
|
|
245
245
|
"secondary",
|
|
@@ -996,16 +996,20 @@ function loadAgentCatalog(cwd, piAgentDir = getAgentDir2(), includeProject = tru
|
|
|
996
996
|
continue;
|
|
997
997
|
}
|
|
998
998
|
const imported = normalized.get(name);
|
|
999
|
-
if (
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
});
|
|
999
|
+
if (imported) {
|
|
1000
|
+
try {
|
|
1001
|
+
const source = agentSources.get(name) ?? imported.source;
|
|
1002
|
+
normalized.set(name, normalizeAgent(name, { ...imported.raw, ...value }, source, imported.origin ?? {
|
|
1003
|
+
kind: "pi-markdown",
|
|
1004
|
+
source: imported.source
|
|
1005
|
+
}));
|
|
1006
|
+
} catch (error) {
|
|
1007
|
+
diagnostics.push(formatError(error));
|
|
1006
1008
|
}
|
|
1007
1009
|
continue;
|
|
1008
1010
|
}
|
|
1011
|
+
if (Object.keys(value).every((key) => key === "disable"))
|
|
1012
|
+
continue;
|
|
1009
1013
|
try {
|
|
1010
1014
|
const source = agentSources.get(name) ?? "built-in";
|
|
1011
1015
|
normalized.set(name, normalizeAgent(name, value, source, {
|
|
@@ -1058,6 +1062,9 @@ function mergePermissionRules(...values) {
|
|
|
1058
1062
|
function availableAgents(catalog) {
|
|
1059
1063
|
return [...catalog.agents.values()].filter((agent) => !agent.hidden && !agent.disabled);
|
|
1060
1064
|
}
|
|
1065
|
+
function isPrimaryAgent(agent) {
|
|
1066
|
+
return agent.mode === "primary";
|
|
1067
|
+
}
|
|
1061
1068
|
function agentSupportsMode(agent, mode) {
|
|
1062
1069
|
return agent.mode === mode || agent.mode === "all";
|
|
1063
1070
|
}
|
|
@@ -2744,7 +2751,7 @@ ${this.primaryAgent.prompt}` };
|
|
|
2744
2751
|
let disabledOverrides = loadAgentDisabledOverrides(ctx.cwd, projectTrusted);
|
|
2745
2752
|
let maxSubagentsSettings = loadMaxSubagentsSettings(ctx.cwd, projectTrusted);
|
|
2746
2753
|
let tab = requested ? "log" : "primary";
|
|
2747
|
-
const agentsForTab = () => agents.filter((agent) =>
|
|
2754
|
+
const agentsForTab = () => agents.filter((agent) => tab === "subagent" ? agentSupportsMode(agent, "subagent") : isPrimaryAgent(agent));
|
|
2748
2755
|
let selectedAgent = Math.max(0, agentsForTab().findIndex((agent) => agent.name === this.primaryAgent?.name));
|
|
2749
2756
|
let selectedTask = requested ? tasks.findIndex((task) => task.id === requested || task.id.startsWith(requested)) : 0;
|
|
2750
2757
|
if (selectedTask < 0) {
|
|
@@ -3105,7 +3112,7 @@ ${this.primaryAgent.prompt}` };
|
|
|
3105
3112
|
tui.requestRender();
|
|
3106
3113
|
});
|
|
3107
3114
|
return;
|
|
3108
|
-
} else if (tab === "primary" && matchesKey(data, "return") && agent && !agent.disabled &&
|
|
3115
|
+
} else if (tab === "primary" && matchesKey(data, "return") && agent && !agent.disabled && isPrimaryAgent(agent)) {
|
|
3109
3116
|
this.selectPrimaryAgent(agent.name, ctx).then(() => tui.requestRender()).catch((error) => ctx.ui.notify(`Could not select primary agent: ${formatError(error)}`, "error"));
|
|
3110
3117
|
return;
|
|
3111
3118
|
} else if (tab === "primary" && matchesKey(data, "return") && agent) {
|
|
@@ -3314,7 +3321,7 @@ ${this.primaryAgent.prompt}` };
|
|
|
3314
3321
|
ctx.ui.notify(diagnostic, "warning");
|
|
3315
3322
|
if (catalog.diagnostics.length > 0)
|
|
3316
3323
|
return false;
|
|
3317
|
-
const agent = availableAgents(catalog).find((candidate) => candidate.name === name &&
|
|
3324
|
+
const agent = availableAgents(catalog).find((candidate) => candidate.name === name && isPrimaryAgent(candidate));
|
|
3318
3325
|
if (!agent) {
|
|
3319
3326
|
ctx.ui.notify(`Unknown primary agent: ${name}`, "error");
|
|
3320
3327
|
return false;
|
|
@@ -3335,7 +3342,7 @@ ${this.primaryAgent.prompt}` };
|
|
|
3335
3342
|
ctx.ui.notify(diagnostic, "warning");
|
|
3336
3343
|
if (catalog.diagnostics.length > 0)
|
|
3337
3344
|
return;
|
|
3338
|
-
const agents = availableAgents(catalog).filter(
|
|
3345
|
+
const agents = availableAgents(catalog).filter(isPrimaryAgent);
|
|
3339
3346
|
if (agents.length === 0) {
|
|
3340
3347
|
ctx.ui.notify("No primary agents are available", "warning");
|
|
3341
3348
|
return;
|
|
@@ -4256,7 +4263,7 @@ ${renderTaskResult(task.id, failed ? "error" : "completed", value)}`;
|
|
|
4256
4263
|
if (typeof value?.name === "string")
|
|
4257
4264
|
name = value.name;
|
|
4258
4265
|
}
|
|
4259
|
-
const agents = availableAgents(catalog).filter(
|
|
4266
|
+
const agents = availableAgents(catalog).filter(isPrimaryAgent);
|
|
4260
4267
|
const agent = agents.find((candidate) => candidate.name === name) ?? agents[0];
|
|
4261
4268
|
if (agent && !await this.activatePrimaryAgent(agent, catalog, ctx, false)) {
|
|
4262
4269
|
this.invalidatePrimaryAgent(catalog, ctx);
|
|
@@ -4620,23 +4627,6 @@ function addWritePathToConfig(configPath, pathToAdd) {
|
|
|
4620
4627
|
function mergeAllowances(base, session, execution) {
|
|
4621
4628
|
return [...base, ...session, ...execution ?? []];
|
|
4622
4629
|
}
|
|
4623
|
-
function domainMatchesPattern(domain, pattern) {
|
|
4624
|
-
const normalizedDomain = domain.toLowerCase().replace(/\.+$/, "");
|
|
4625
|
-
const normalizedPattern = pattern.toLowerCase().replace(/\.+$/, "");
|
|
4626
|
-
if (normalizedPattern === "*")
|
|
4627
|
-
return true;
|
|
4628
|
-
if (normalizedPattern.startsWith("*.")) {
|
|
4629
|
-
const base = normalizedPattern.slice(2);
|
|
4630
|
-
return normalizedDomain === base || normalizedDomain.endsWith(`.${base}`);
|
|
4631
|
-
}
|
|
4632
|
-
return normalizedDomain === normalizedPattern;
|
|
4633
|
-
}
|
|
4634
|
-
function domainMatchesAny(domain, patterns) {
|
|
4635
|
-
return patterns.some((pattern) => domainMatchesPattern(domain, pattern));
|
|
4636
|
-
}
|
|
4637
|
-
function allowsAllDomains(allowedDomains) {
|
|
4638
|
-
return allowedDomains.includes("*");
|
|
4639
|
-
}
|
|
4640
4630
|
function shouldPromptForWrite(path, allowWrite, cwd) {
|
|
4641
4631
|
return allowWrite.length === 0 || !matchesPattern(path, allowWrite, cwd);
|
|
4642
4632
|
}
|
|
@@ -4703,40 +4693,6 @@ function normalizeBlockedPath(path, cwd) {
|
|
|
4703
4693
|
const nativePath = process.platform === "win32" && /^\/[a-zA-Z](?:\/|$)/.test(path) ? `${path[1]}:${path.slice(2)}` : path;
|
|
4704
4694
|
return canonicalizePath(isAbsolute3(nativePath) ? nativePath : join7(cwd, nativePath), cwd);
|
|
4705
4695
|
}
|
|
4706
|
-
function pathUnderDirectory(filePath, dir) {
|
|
4707
|
-
const normalizedFilePath = normalizePathSeparators(filePath);
|
|
4708
|
-
const normalizedDir = normalizePathSeparators(dir);
|
|
4709
|
-
if (normalizedFilePath === normalizedDir)
|
|
4710
|
-
return true;
|
|
4711
|
-
const sep5 = normalizedDir.endsWith("/") ? "" : "/";
|
|
4712
|
-
return normalizedFilePath.startsWith(normalizedDir + sep5);
|
|
4713
|
-
}
|
|
4714
|
-
function sessionScopeFor(filePath, baseDirectory) {
|
|
4715
|
-
const dir = dirname4(filePath);
|
|
4716
|
-
const normalizedDir = normalizePathSeparators(dir);
|
|
4717
|
-
const home = homedir3();
|
|
4718
|
-
const boundaries = new Set;
|
|
4719
|
-
if (home)
|
|
4720
|
-
boundaries.add(home);
|
|
4721
|
-
try {
|
|
4722
|
-
const realHome = realpathSync2.native(home);
|
|
4723
|
-
if (realHome)
|
|
4724
|
-
boundaries.add(realHome);
|
|
4725
|
-
} catch {}
|
|
4726
|
-
for (const boundary of boundaries) {
|
|
4727
|
-
const normalizedBoundary = normalizePathSeparators(boundary);
|
|
4728
|
-
if (pathUnderDirectory(dir, boundary)) {
|
|
4729
|
-
const rest = normalizedDir.slice(normalizedBoundary.length).replace(/^\/+/, "");
|
|
4730
|
-
const first = rest.split("/")[0];
|
|
4731
|
-
if (!first)
|
|
4732
|
-
return filePath;
|
|
4733
|
-
return join7(boundary, first);
|
|
4734
|
-
}
|
|
4735
|
-
}
|
|
4736
|
-
if (pathUnderDirectory(dir, baseDirectory))
|
|
4737
|
-
return baseDirectory;
|
|
4738
|
-
return dir;
|
|
4739
|
-
}
|
|
4740
4696
|
function longestPrefixMatch(path, patterns, cwd) {
|
|
4741
4697
|
let best = -1;
|
|
4742
4698
|
for (const pattern of patterns) {
|
|
@@ -4761,15 +4717,6 @@ function isPathLike(value) {
|
|
|
4761
4717
|
function normalizePathMatch(value, cwd) {
|
|
4762
4718
|
return isPathLike(value) ? normalizeBlockedPath(value, cwd) : null;
|
|
4763
4719
|
}
|
|
4764
|
-
function isFilesystemTrap(trap) {
|
|
4765
|
-
return trap.kind === "filesystem";
|
|
4766
|
-
}
|
|
4767
|
-
function isDenialTrap(trap) {
|
|
4768
|
-
return trap.kind === "filesystem" || trap.kind === "network";
|
|
4769
|
-
}
|
|
4770
|
-
function isQueryTrap(trap) {
|
|
4771
|
-
return isDenialTrap(trap) && trap.state === "query";
|
|
4772
|
-
}
|
|
4773
4720
|
function extractBlockedPath(trapOutput, cwd) {
|
|
4774
4721
|
const landstripErrors = parseLandstripTraps(trapOutput).filter(isFilesystemTrap);
|
|
4775
4722
|
if (landstripErrors.length > 0) {
|
|
@@ -4815,67 +4762,6 @@ function extractTrapBlockedPath(trapOutput, cwd, operation) {
|
|
|
4815
4762
|
}
|
|
4816
4763
|
return null;
|
|
4817
4764
|
}
|
|
4818
|
-
function isLandstripTrap(value) {
|
|
4819
|
-
if (typeof value !== "object" || value === null)
|
|
4820
|
-
return false;
|
|
4821
|
-
const obj = value;
|
|
4822
|
-
switch (obj.kind) {
|
|
4823
|
-
case "filesystem":
|
|
4824
|
-
return (obj.operation === "read" || obj.operation === "write") && typeof obj.path === "string" && typeof obj.query_id === "string";
|
|
4825
|
-
case "network":
|
|
4826
|
-
return typeof obj.operation === "string" && typeof obj.target === "string" && typeof obj.query_id === "string";
|
|
4827
|
-
case "launch":
|
|
4828
|
-
return typeof obj.program === "string" && typeof obj.message === "string";
|
|
4829
|
-
case "usage":
|
|
4830
|
-
return typeof obj.message === "string";
|
|
4831
|
-
case "internal":
|
|
4832
|
-
return typeof obj.code === "string" && typeof obj.message === "string";
|
|
4833
|
-
default:
|
|
4834
|
-
return false;
|
|
4835
|
-
}
|
|
4836
|
-
}
|
|
4837
|
-
function parseTrapLine(line) {
|
|
4838
|
-
try {
|
|
4839
|
-
const parsed = JSON.parse(line);
|
|
4840
|
-
return isLandstripTrap(parsed) ? parsed : null;
|
|
4841
|
-
} catch {
|
|
4842
|
-
return null;
|
|
4843
|
-
}
|
|
4844
|
-
}
|
|
4845
|
-
function parseLandstripTraps(output) {
|
|
4846
|
-
const traps = [];
|
|
4847
|
-
for (const line of output.trim().split(`
|
|
4848
|
-
`)) {
|
|
4849
|
-
const trap = parseTrapLine(line);
|
|
4850
|
-
if (trap)
|
|
4851
|
-
traps.push(trap);
|
|
4852
|
-
}
|
|
4853
|
-
return traps;
|
|
4854
|
-
}
|
|
4855
|
-
function formatLandstripTraps(traps) {
|
|
4856
|
-
return traps.map((trap) => {
|
|
4857
|
-
switch (trap.kind) {
|
|
4858
|
-
case "filesystem":
|
|
4859
|
-
return `landstrip: filesystem ${trap.operation} denied: ${trap.path} (${trap.mechanism})`;
|
|
4860
|
-
case "network":
|
|
4861
|
-
return `landstrip: network ${trap.operation} denied: ${trap.target} (${trap.mechanism})`;
|
|
4862
|
-
case "launch":
|
|
4863
|
-
return `landstrip: launch failed: ${trap.program}: ${trap.message}`;
|
|
4864
|
-
case "usage":
|
|
4865
|
-
return `landstrip: usage error: ${trap.message}`;
|
|
4866
|
-
case "internal": {
|
|
4867
|
-
const mechanism = trap.mechanism ? ` (${trap.mechanism})` : "";
|
|
4868
|
-
return `landstrip: ${trap.code}${mechanism}: ${trap.message}`;
|
|
4869
|
-
}
|
|
4870
|
-
}
|
|
4871
|
-
}).join(`
|
|
4872
|
-
`);
|
|
4873
|
-
}
|
|
4874
|
-
function controlResponseLine(queryId, action) {
|
|
4875
|
-
const response = { query_id: queryId, action };
|
|
4876
|
-
return JSON.stringify(response) + `
|
|
4877
|
-
`;
|
|
4878
|
-
}
|
|
4879
4765
|
function notify(ctx, message, level) {
|
|
4880
4766
|
if (!ctx.hasUI)
|
|
4881
4767
|
return;
|
|
@@ -5763,8 +5649,7 @@ function createLandstripIntegrationWithPrompts(options, permissionPrompts) {
|
|
|
5763
5649
|
if (options2.signal?.aborted)
|
|
5764
5650
|
throw new Error("Task cancelled");
|
|
5765
5651
|
if (!ensureSandboxState(options2.ctx)) {
|
|
5766
|
-
|
|
5767
|
-
if (!explicitlyDisabled) {
|
|
5652
|
+
if (sandboxState === "unavailable") {
|
|
5768
5653
|
throw new Error("Sandbox is unavailable; refusing subagent process");
|
|
5769
5654
|
}
|
|
5770
5655
|
if (!unsandboxedWorkerWarningShown) {
|
|
@@ -5870,7 +5755,7 @@ function createLandstripIntegrationWithPrompts(options, permissionPrompts) {
|
|
|
5870
5755
|
};
|
|
5871
5756
|
}
|
|
5872
5757
|
async function prepareProcess(options2) {
|
|
5873
|
-
if (process.platform === "win32" && (
|
|
5758
|
+
if (process.platform === "win32" && (getNoSandboxFlag() || !loadConfig(options2.cwd).enabled)) {
|
|
5874
5759
|
throw new Error("Generic process preparation requires sandboxing on Windows");
|
|
5875
5760
|
}
|
|
5876
5761
|
return prepareRpcWorker({
|
|
@@ -6450,7 +6335,7 @@ ${message}
|
|
|
6450
6335
|
enableStatus(ctx, config);
|
|
6451
6336
|
return true;
|
|
6452
6337
|
}
|
|
6453
|
-
let
|
|
6338
|
+
let getNoSandboxFlag = () => false;
|
|
6454
6339
|
function disableSandbox(ctx) {
|
|
6455
6340
|
sandboxEnabled = false;
|
|
6456
6341
|
sandboxReady = false;
|
|
@@ -6458,7 +6343,7 @@ ${message}
|
|
|
6458
6343
|
setTuiStatus(ctx, "sandbox", undefined);
|
|
6459
6344
|
}
|
|
6460
6345
|
function ensureSandboxState(ctx) {
|
|
6461
|
-
if (
|
|
6346
|
+
if (getNoSandboxFlag()) {
|
|
6462
6347
|
disableSandbox(ctx);
|
|
6463
6348
|
return false;
|
|
6464
6349
|
}
|
|
@@ -6504,6 +6389,7 @@ ${message}
|
|
|
6504
6389
|
type: "boolean",
|
|
6505
6390
|
default: false
|
|
6506
6391
|
});
|
|
6392
|
+
getNoSandboxFlag = () => Boolean(maybePi.getFlag?.("no-sandbox"));
|
|
6507
6393
|
unpublishRuntime?.();
|
|
6508
6394
|
unpublishRuntime = publishLandstripRuntime(pi, integration);
|
|
6509
6395
|
if (shouldRegisterBashTool)
|
|
@@ -6526,8 +6412,7 @@ ${message}
|
|
|
6526
6412
|
resetSessionAllowances();
|
|
6527
6413
|
const trustContext = ctx;
|
|
6528
6414
|
projectConfigTrusted = trustContext.isProjectTrusted?.() ?? false;
|
|
6529
|
-
|
|
6530
|
-
if (noSandboxFlag) {
|
|
6415
|
+
if (getNoSandboxFlag()) {
|
|
6531
6416
|
disableSandbox(ctx);
|
|
6532
6417
|
notify(ctx, "Sandbox disabled via --no-sandbox", "warning");
|
|
6533
6418
|
if (!unpublishRuntime)
|
|
@@ -6567,7 +6452,7 @@ ${message}
|
|
|
6567
6452
|
const shouldToggle = await ctx.ui.custom((tui, theme, _kb, done) => {
|
|
6568
6453
|
const { muted, accent, text } = themeColors(theme);
|
|
6569
6454
|
const sandboxStatus = () => {
|
|
6570
|
-
if (
|
|
6455
|
+
if (getNoSandboxFlag())
|
|
6571
6456
|
return { color: "warning", label: "Disabled by --no-sandbox" };
|
|
6572
6457
|
if (!config.enabled)
|
|
6573
6458
|
return { color: "warning", label: "Disabled by configuration" };
|
|
@@ -6643,10 +6528,10 @@ ${target.path}`);
|
|
|
6643
6528
|
const scope = await setSandboxConfigEnabled(ctx.cwd, enabled, projectTrusted);
|
|
6644
6529
|
if (!enabled) {
|
|
6645
6530
|
disableSandbox(ctx);
|
|
6646
|
-
} else if (!
|
|
6531
|
+
} else if (!getNoSandboxFlag()) {
|
|
6647
6532
|
enableSandbox(ctx);
|
|
6648
6533
|
}
|
|
6649
|
-
if (enabled &&
|
|
6534
|
+
if (enabled && getNoSandboxFlag()) {
|
|
6650
6535
|
notify(ctx, "Sandbox remains disabled via --no-sandbox", "warning");
|
|
6651
6536
|
} else {
|
|
6652
6537
|
notify(ctx, `Sandbox ${enabled ? "enabled" : "disabled"} in ${scope} config`, "info");
|
|
@@ -6662,7 +6547,7 @@ ${target.path}`);
|
|
|
6662
6547
|
const effectiveEnabled = loadConfig(ctx.cwd).enabled;
|
|
6663
6548
|
if (!effectiveEnabled) {
|
|
6664
6549
|
disableSandbox(ctx);
|
|
6665
|
-
} else if (!
|
|
6550
|
+
} else if (!getNoSandboxFlag()) {
|
|
6666
6551
|
enableSandbox(ctx);
|
|
6667
6552
|
}
|
|
6668
6553
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-landstrip",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.34",
|
|
4
4
|
"description": "Sandboxed Bash and process-backed agents for Pi",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"landstrip",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"ci:test": "npm run test"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@landstrip/landstrip": "^0.18.
|
|
42
|
+
"@landstrip/landstrip": "^0.18.34",
|
|
43
43
|
"jsonc-parser": "^3.3.1",
|
|
44
44
|
"minimatch": "^10.2.5",
|
|
45
45
|
"yaml": "^2.9.0"
|