pi-landstrip 0.18.41 → 0.18.43
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/api.ts +12 -14
- package/dist/index.ts +237 -294
- package/package.json +2 -2
package/api.ts
CHANGED
|
@@ -213,13 +213,13 @@ export function useLandstrip(
|
|
|
213
213
|
}
|
|
214
214
|
}
|
|
215
215
|
|
|
216
|
-
|
|
216
|
+
function provideExtensionProvider(
|
|
217
217
|
pi: ExtensionAPI,
|
|
218
|
-
|
|
218
|
+
register: (runtime: PiLandstripRuntimeV2) => () => void,
|
|
219
219
|
): () => void {
|
|
220
220
|
let unregisterProvider: (() => void) | undefined;
|
|
221
221
|
const stopDiscovery = useLandstrip(pi, (runtime) => {
|
|
222
|
-
const unregisterNext = runtime
|
|
222
|
+
const unregisterNext = register(runtime);
|
|
223
223
|
unregisterProvider?.();
|
|
224
224
|
unregisterProvider = unregisterNext;
|
|
225
225
|
});
|
|
@@ -229,20 +229,18 @@ export function provideLandstripShell(
|
|
|
229
229
|
};
|
|
230
230
|
}
|
|
231
231
|
|
|
232
|
+
export function provideLandstripShell(
|
|
233
|
+
pi: ExtensionAPI,
|
|
234
|
+
provider: LandstripShellProvider,
|
|
235
|
+
): () => void {
|
|
236
|
+
return provideExtensionProvider(pi, (runtime) => runtime.registerShellProvider(provider));
|
|
237
|
+
}
|
|
238
|
+
|
|
232
239
|
export function provideLandstripPermissionAsk(
|
|
233
240
|
pi: ExtensionAPI,
|
|
234
241
|
provider: LandstripPermissionAskProvider,
|
|
235
242
|
): () => void {
|
|
236
|
-
|
|
237
|
-
const stopDiscovery = useLandstrip(pi, (runtime) => {
|
|
238
|
-
const unregisterNext = runtime.registerPermissionAskProvider(provider);
|
|
239
|
-
unregisterProvider?.();
|
|
240
|
-
unregisterProvider = unregisterNext;
|
|
241
|
-
});
|
|
242
|
-
return () => {
|
|
243
|
-
stopDiscovery();
|
|
244
|
-
unregisterProvider?.();
|
|
245
|
-
};
|
|
243
|
+
return provideExtensionProvider(pi, (runtime) => runtime.registerPermissionAskProvider(provider));
|
|
246
244
|
}
|
|
247
245
|
|
|
248
246
|
export function publishLandstripRuntime(
|
|
@@ -288,7 +286,7 @@ export function contextFromEnvironment(
|
|
|
288
286
|
!['enabled', 'disabled', 'unavailable'].includes(String(value.sandbox)) ||
|
|
289
287
|
typeof value.cwd !== 'string' ||
|
|
290
288
|
!Number.isInteger(value.depth) ||
|
|
291
|
-
|
|
289
|
+
(value.depth as number) < 0 ||
|
|
292
290
|
['sessionId', 'taskId', 'parentTaskId', 'agent'].some(
|
|
293
291
|
(key) => value[key] !== undefined && typeof value[key] !== 'string',
|
|
294
292
|
)
|
package/dist/index.ts
CHANGED
|
@@ -111,10 +111,11 @@ import {
|
|
|
111
111
|
SelectList,
|
|
112
112
|
SettingsList,
|
|
113
113
|
Text,
|
|
114
|
-
truncateToWidth
|
|
115
|
-
visibleWidth
|
|
114
|
+
truncateToWidth,
|
|
115
|
+
visibleWidth,
|
|
116
116
|
wrapTextWithAnsi
|
|
117
117
|
} from "@earendil-works/pi-tui";
|
|
118
|
+
import { canonicalizeHost } from "@landstrip/landstrip-api/shared";
|
|
118
119
|
import { Type } from "typebox";
|
|
119
120
|
|
|
120
121
|
// agents.ts
|
|
@@ -133,78 +134,6 @@ import {
|
|
|
133
134
|
printParseErrorCode
|
|
134
135
|
} from "jsonc-parser";
|
|
135
136
|
|
|
136
|
-
// built-in-agents.ts
|
|
137
|
-
var BUILT_IN_LANDSTRIP_CONFIG = {
|
|
138
|
-
maxSubagents: 0,
|
|
139
|
-
toolFilesystemPolicy: "host",
|
|
140
|
-
agent: {
|
|
141
|
-
build: {
|
|
142
|
-
description: "Implement and test requested changes",
|
|
143
|
-
mode: "primary",
|
|
144
|
-
color: "success",
|
|
145
|
-
prompt: "Implement, test, and complete the request."
|
|
146
|
-
},
|
|
147
|
-
plan: {
|
|
148
|
-
description: "Plan before running commands or editing files",
|
|
149
|
-
mode: "primary",
|
|
150
|
-
color: "warning",
|
|
151
|
-
prompt: "Analyze the request and produce a clear plan before making changes.",
|
|
152
|
-
permission: { edit: "ask", bash: "ask", task: "ask" }
|
|
153
|
-
},
|
|
154
|
-
general: {
|
|
155
|
-
description: "General-purpose agent for complex tasks",
|
|
156
|
-
mode: "subagent",
|
|
157
|
-
prompt: "Complete the task and return a concise result.",
|
|
158
|
-
permission: { todowrite: "deny" }
|
|
159
|
-
},
|
|
160
|
-
scout: {
|
|
161
|
-
description: "Read-only codebase reconnaissance",
|
|
162
|
-
mode: "subagent",
|
|
163
|
-
prompt: "Inspect the codebase without editing. Return concise findings with exact file references and a recommended starting point.",
|
|
164
|
-
permission: {
|
|
165
|
-
"*": "deny",
|
|
166
|
-
read: {
|
|
167
|
-
"*": "allow",
|
|
168
|
-
"**/*.env": "ask",
|
|
169
|
-
"**/*.env.*": "ask",
|
|
170
|
-
"**/*.env.example": "allow"
|
|
171
|
-
},
|
|
172
|
-
glob: "allow",
|
|
173
|
-
grep: "allow",
|
|
174
|
-
list: "allow"
|
|
175
|
-
}
|
|
176
|
-
},
|
|
177
|
-
explore: {
|
|
178
|
-
description: "Codebase research with shell and web access",
|
|
179
|
-
mode: "subagent",
|
|
180
|
-
prompt: "Explore without editing. Use shell or web tools when needed, then return concise findings with file references.",
|
|
181
|
-
permission: {
|
|
182
|
-
"*": "deny",
|
|
183
|
-
read: {
|
|
184
|
-
"*": "allow",
|
|
185
|
-
"**/*.env": "ask",
|
|
186
|
-
"**/*.env.*": "ask",
|
|
187
|
-
"**/*.env.example": "allow"
|
|
188
|
-
},
|
|
189
|
-
glob: "allow",
|
|
190
|
-
grep: "allow",
|
|
191
|
-
list: "allow",
|
|
192
|
-
bash: "allow",
|
|
193
|
-
webfetch: "allow",
|
|
194
|
-
websearch: "allow"
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
},
|
|
198
|
-
permission: {
|
|
199
|
-
"*": "allow",
|
|
200
|
-
read: {
|
|
201
|
-
"**/*.env": "ask",
|
|
202
|
-
"**/*.env.*": "ask",
|
|
203
|
-
"**/*.env.example": "allow"
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
};
|
|
207
|
-
|
|
208
137
|
// util.ts
|
|
209
138
|
import { readFileSync } from "node:fs";
|
|
210
139
|
import { homedir } from "node:os";
|
|
@@ -272,17 +201,15 @@ function isAgentColor(value) {
|
|
|
272
201
|
return true;
|
|
273
202
|
return OPENCODE_THEME_COLORS.has(value);
|
|
274
203
|
}
|
|
275
|
-
function hexFg(hex, text) {
|
|
276
|
-
const r = Number.parseInt(hex.slice(1, 3), 16);
|
|
277
|
-
const g = Number.parseInt(hex.slice(3, 5), 16);
|
|
278
|
-
const b = Number.parseInt(hex.slice(5, 7), 16);
|
|
279
|
-
return `\x1B[38;2;${r};${g};${b}m${text}\x1B[39m`;
|
|
280
|
-
}
|
|
281
204
|
function colorizeAgentText(color, text, themeFg, fallback = "accent") {
|
|
282
205
|
if (!color)
|
|
283
206
|
return themeFg ? themeFg(fallback, text) : text;
|
|
284
|
-
if (color.startsWith("#"))
|
|
285
|
-
|
|
207
|
+
if (color.startsWith("#")) {
|
|
208
|
+
const r = Number.parseInt(color.slice(1, 3), 16);
|
|
209
|
+
const g = Number.parseInt(color.slice(3, 5), 16);
|
|
210
|
+
const b = Number.parseInt(color.slice(5, 7), 16);
|
|
211
|
+
return `\x1B[38;2;${r};${g};${b}m${text}\x1B[39m`;
|
|
212
|
+
}
|
|
286
213
|
if (themeFg)
|
|
287
214
|
return themeFg(THEME_COLOR_ALIASES[color] ?? fallback, text);
|
|
288
215
|
const ansi = NAMED_COLOR_ANSI[color];
|
|
@@ -412,6 +339,76 @@ class PermissionPromptCoordinator {
|
|
|
412
339
|
}
|
|
413
340
|
|
|
414
341
|
// config.ts
|
|
342
|
+
var BUILT_IN_LANDSTRIP_CONFIG = {
|
|
343
|
+
maxSubagents: 0,
|
|
344
|
+
toolFilesystemPolicy: "host",
|
|
345
|
+
agent: {
|
|
346
|
+
build: {
|
|
347
|
+
description: "Implement and test requested changes",
|
|
348
|
+
mode: "primary",
|
|
349
|
+
color: "success",
|
|
350
|
+
prompt: "Implement, test, and complete the request."
|
|
351
|
+
},
|
|
352
|
+
plan: {
|
|
353
|
+
description: "Plan before running commands or editing files",
|
|
354
|
+
mode: "primary",
|
|
355
|
+
color: "warning",
|
|
356
|
+
prompt: "Analyze the request and produce a clear plan before making changes.",
|
|
357
|
+
permission: { edit: "ask", bash: "ask", task: "ask" }
|
|
358
|
+
},
|
|
359
|
+
general: {
|
|
360
|
+
description: "General-purpose agent for complex tasks",
|
|
361
|
+
mode: "subagent",
|
|
362
|
+
prompt: "Complete the task and return a concise result.",
|
|
363
|
+
permission: { todowrite: "deny" }
|
|
364
|
+
},
|
|
365
|
+
scout: {
|
|
366
|
+
description: "Read-only codebase reconnaissance",
|
|
367
|
+
mode: "subagent",
|
|
368
|
+
prompt: "Inspect the codebase without editing. Return concise findings with exact file references and a recommended starting point.",
|
|
369
|
+
permission: {
|
|
370
|
+
"*": "deny",
|
|
371
|
+
read: {
|
|
372
|
+
"*": "allow",
|
|
373
|
+
"**/*.env": "ask",
|
|
374
|
+
"**/*.env.*": "ask",
|
|
375
|
+
"**/*.env.example": "allow"
|
|
376
|
+
},
|
|
377
|
+
glob: "allow",
|
|
378
|
+
grep: "allow",
|
|
379
|
+
list: "allow"
|
|
380
|
+
}
|
|
381
|
+
},
|
|
382
|
+
explore: {
|
|
383
|
+
description: "Codebase research with shell and web access",
|
|
384
|
+
mode: "subagent",
|
|
385
|
+
prompt: "Explore without editing. Use shell or web tools when needed, then return concise findings with file references.",
|
|
386
|
+
permission: {
|
|
387
|
+
"*": "deny",
|
|
388
|
+
read: {
|
|
389
|
+
"*": "allow",
|
|
390
|
+
"**/*.env": "ask",
|
|
391
|
+
"**/*.env.*": "ask",
|
|
392
|
+
"**/*.env.example": "allow"
|
|
393
|
+
},
|
|
394
|
+
glob: "allow",
|
|
395
|
+
grep: "allow",
|
|
396
|
+
list: "allow",
|
|
397
|
+
bash: "allow",
|
|
398
|
+
webfetch: "allow",
|
|
399
|
+
websearch: "allow"
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
},
|
|
403
|
+
permission: {
|
|
404
|
+
"*": "allow",
|
|
405
|
+
read: {
|
|
406
|
+
"**/*.env": "ask",
|
|
407
|
+
"**/*.env.*": "ask",
|
|
408
|
+
"**/*.env.example": "allow"
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
};
|
|
415
412
|
function isProjectTrusted(ctx) {
|
|
416
413
|
const trustContext = ctx;
|
|
417
414
|
return trustContext.isProjectTrusted?.() ?? false;
|
|
@@ -420,9 +417,6 @@ var MAX_SUBAGENTS = 16;
|
|
|
420
417
|
var LANDSTRIP_KEYS = ["maxSubagents", "agent", "permission", "toolFilesystemPolicy"];
|
|
421
418
|
var JSON_FORMAT = { formattingOptions: { insertSpaces: true, tabSize: 2, eol: `
|
|
422
419
|
` } };
|
|
423
|
-
function isLandstripKey(key) {
|
|
424
|
-
return LANDSTRIP_KEYS.includes(key);
|
|
425
|
-
}
|
|
426
420
|
function ensureFinalNewline(content) {
|
|
427
421
|
return content.endsWith(`
|
|
428
422
|
`) ? content : `${content}
|
|
@@ -465,8 +459,9 @@ function parseLandstripConfig(value, path, kind) {
|
|
|
465
459
|
if (!isRecord2(value))
|
|
466
460
|
throw new Error(`${path}: ${label} must be a JSON object`);
|
|
467
461
|
for (const key of Object.keys(value)) {
|
|
468
|
-
if (!
|
|
462
|
+
if (!LANDSTRIP_KEYS.includes(key)) {
|
|
469
463
|
throw new Error(`${path}: ${label} has an unknown field ${key}`);
|
|
464
|
+
}
|
|
470
465
|
}
|
|
471
466
|
const field = (name) => kind === "settings" ? `landstrip.${name}` : name;
|
|
472
467
|
const config = {};
|
|
@@ -760,11 +755,6 @@ function listMarkdownFiles(root) {
|
|
|
760
755
|
visit(root);
|
|
761
756
|
return results;
|
|
762
757
|
}
|
|
763
|
-
function agentNameFromPath(dir, filePath) {
|
|
764
|
-
const relativePath = relative(dir, filePath).split(sep).join("/");
|
|
765
|
-
const extension = extname(relativePath);
|
|
766
|
-
return extension.length > 0 ? relativePath.slice(0, -extension.length) : relativePath;
|
|
767
|
-
}
|
|
768
758
|
function parseFrontmatter(content) {
|
|
769
759
|
const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n([\s\S]*))?$/);
|
|
770
760
|
if (!match)
|
|
@@ -863,7 +853,9 @@ function loadPiMarkdownAgents(options) {
|
|
|
863
853
|
try {
|
|
864
854
|
const content = readFileSync3(filePath, "utf8");
|
|
865
855
|
const raw = parseMarkdownAgentRaw(content);
|
|
866
|
-
const
|
|
856
|
+
const relativePath = relative(directory.path, filePath).split(sep).join("/");
|
|
857
|
+
const extension = extname(relativePath);
|
|
858
|
+
const name = extension.length > 0 ? relativePath.slice(0, -extension.length) : relativePath;
|
|
867
859
|
if (!name) {
|
|
868
860
|
diagnostics.push(`${filePath}: agent name is empty`);
|
|
869
861
|
continue;
|
|
@@ -897,9 +889,6 @@ var AGENT_FIELDS = new Set([
|
|
|
897
889
|
function normalizeAbsolutePath(value) {
|
|
898
890
|
return /^(?:[A-Za-z]:[\\/]|\\\\)/.test(value) ? value.replaceAll("\\", "/") : value;
|
|
899
891
|
}
|
|
900
|
-
function expandPattern(pattern) {
|
|
901
|
-
return normalizeAbsolutePath(expandHomePath(pattern));
|
|
902
|
-
}
|
|
903
892
|
function permissionEntries(permission, value) {
|
|
904
893
|
if (value === "allow" || value === "ask" || value === "deny") {
|
|
905
894
|
return [{ permission, pattern: "*", action: value }];
|
|
@@ -911,7 +900,7 @@ function permissionEntries(permission, value) {
|
|
|
911
900
|
if (action !== "allow" && action !== "ask" && action !== "deny") {
|
|
912
901
|
throw new Error(`permission ${permission} pattern ${pattern} has an invalid action`);
|
|
913
902
|
}
|
|
914
|
-
return { permission, pattern:
|
|
903
|
+
return { permission, pattern: normalizeAbsolutePath(expandHomePath(pattern)), action };
|
|
915
904
|
});
|
|
916
905
|
}
|
|
917
906
|
function normalizePermissions(value) {
|
|
@@ -1134,17 +1123,9 @@ function valueAtPath(root, path) {
|
|
|
1134
1123
|
}
|
|
1135
1124
|
return value;
|
|
1136
1125
|
}
|
|
1137
|
-
function configKindForPath(path) {
|
|
1138
|
-
return basename(path) === "landstrip.json" ? "dedicated" : "settings";
|
|
1139
|
-
}
|
|
1140
1126
|
function agentJsonPath(kind, name) {
|
|
1141
1127
|
return kind === "settings" ? ["landstrip", "agent", name] : ["agent", name];
|
|
1142
1128
|
}
|
|
1143
|
-
function editorSnippet(name, raw, kind) {
|
|
1144
|
-
const agent = { agent: { [name]: raw } };
|
|
1145
|
-
return `${JSON.stringify(kind === "settings" ? { landstrip: agent } : agent, null, 2)}
|
|
1146
|
-
`;
|
|
1147
|
-
}
|
|
1148
1129
|
function parseEditorSnippet(content, name, kind) {
|
|
1149
1130
|
const root = parseJsonDocument(content, "Edited agent");
|
|
1150
1131
|
const parentPath = kind === "settings" ? ["landstrip"] : [];
|
|
@@ -1245,36 +1226,27 @@ function relocateGlobalPrompt(raw, agent) {
|
|
|
1245
1226
|
}
|
|
1246
1227
|
return { ...raw, prompt: expandFileReferences(raw.prompt, dirname2(agent.origin.path)) };
|
|
1247
1228
|
}
|
|
1248
|
-
function safeRelative(root, path) {
|
|
1249
|
-
const value = relative2(root, path);
|
|
1250
|
-
return value && value !== ".." && !value.startsWith(`..${sep2}`) ? value : undefined;
|
|
1251
|
-
}
|
|
1252
1229
|
function projectMarkdownPath(cwd, agentDir, agent) {
|
|
1253
1230
|
const origin = agent.origin;
|
|
1254
1231
|
if (origin.source === "local" && origin.path)
|
|
1255
1232
|
return origin.path;
|
|
1256
1233
|
if (origin.kind === "pi-markdown" && origin.path) {
|
|
1257
|
-
const
|
|
1234
|
+
const relativePath = relative2(join5(agentDir, "agents"), origin.path);
|
|
1235
|
+
const suffix = relativePath && relativePath !== ".." && !relativePath.startsWith(`..${sep2}`) ? relativePath : `${agent.name}.md`;
|
|
1258
1236
|
return join5(cwd, ".pi", "agents", suffix);
|
|
1259
1237
|
}
|
|
1260
1238
|
throw new Error(`Agent ${agent.name} has no Markdown source`);
|
|
1261
1239
|
}
|
|
1262
|
-
function projectConfigTarget(cwd, agentDir) {
|
|
1263
|
-
return getLandstripConfigTarget(cwd, "project", agentDir);
|
|
1264
|
-
}
|
|
1265
1240
|
function assertProjectConfigTarget(cwd, agentDir, target) {
|
|
1266
|
-
const current =
|
|
1241
|
+
const current = getLandstripConfigTarget(cwd, "project", agentDir);
|
|
1267
1242
|
if (current.path !== target.path || current.kind !== target.kind) {
|
|
1268
1243
|
throw new Error("Landstrip project configuration source changed while updating it");
|
|
1269
1244
|
}
|
|
1270
1245
|
}
|
|
1271
|
-
function projectConfigHasAgent(cwd, name, agentDir) {
|
|
1272
|
-
const target = projectConfigTarget(cwd, agentDir);
|
|
1273
|
-
return readAgentNode(target.path, target.kind, name) !== undefined;
|
|
1274
|
-
}
|
|
1275
1246
|
function canDeleteProjectAgent(cwd, agent, agentDir = getAgentDir3()) {
|
|
1276
1247
|
try {
|
|
1277
|
-
|
|
1248
|
+
const target = getLandstripConfigTarget(cwd, "project", agentDir);
|
|
1249
|
+
if (readAgentNode(target.path, target.kind, agent.name) !== undefined)
|
|
1278
1250
|
return true;
|
|
1279
1251
|
} catch {
|
|
1280
1252
|
return false;
|
|
@@ -1283,7 +1255,7 @@ function canDeleteProjectAgent(cwd, agent, agentDir = getAgentDir3()) {
|
|
|
1283
1255
|
return Boolean(origin?.source === "local" && origin.path && origin.kind === "pi-markdown");
|
|
1284
1256
|
}
|
|
1285
1257
|
async function deleteProjectAgent(cwd, agent, agentDir = getAgentDir3()) {
|
|
1286
|
-
const target =
|
|
1258
|
+
const target = getLandstripConfigTarget(cwd, "project", agentDir);
|
|
1287
1259
|
const containers = target.kind === "settings" ? [["landstrip", "agent"], ["landstrip"]] : [["agent"]];
|
|
1288
1260
|
const deletedOverride = await deleteJsonNode(target.path, agentJsonPath(target.kind, agent.name), containers, () => assertProjectConfigTarget(cwd, agentDir, target), target.kind === "dedicated");
|
|
1289
1261
|
const origin = agent.origin;
|
|
@@ -1312,12 +1284,13 @@ function prepareProjectAgentEditor(cwd, agent, agentDir = getAgentDir3()) {
|
|
|
1312
1284
|
};
|
|
1313
1285
|
}
|
|
1314
1286
|
const sourcePath = origin?.path;
|
|
1315
|
-
const sourceRaw = origin?.kind === "config" && sourcePath ? readAgentNode(sourcePath,
|
|
1316
|
-
const raw = relocateGlobalPrompt(sourceRaw
|
|
1317
|
-
const target =
|
|
1287
|
+
const sourceRaw = origin?.kind === "config" && sourcePath ? readAgentNode(sourcePath, basename(sourcePath) === "landstrip.json" ? "dedicated" : "settings", agent.name) : undefined;
|
|
1288
|
+
const raw = relocateGlobalPrompt(sourceRaw ?? (agent.raw ? { ...agent.raw } : normalizedAgentRaw(agent)), agent);
|
|
1289
|
+
const target = getLandstripConfigTarget(cwd, "project", agentDir);
|
|
1318
1290
|
return {
|
|
1319
1291
|
title: `Edit @${agent.name}`,
|
|
1320
|
-
content:
|
|
1292
|
+
content: `${JSON.stringify(target.kind === "settings" ? { landstrip: { agent: { [agent.name]: raw } } } : { agent: { [agent.name]: raw } }, null, 2)}
|
|
1293
|
+
`,
|
|
1321
1294
|
async save(content) {
|
|
1322
1295
|
const edited = parseEditorSnippet(content, agent.name, target.kind);
|
|
1323
1296
|
validateAgentRaw(agent.name, edited);
|
|
@@ -1326,28 +1299,6 @@ function prepareProjectAgentEditor(cwd, agent, agentDir = getAgentDir3()) {
|
|
|
1326
1299
|
};
|
|
1327
1300
|
}
|
|
1328
1301
|
|
|
1329
|
-
// box.ts
|
|
1330
|
-
import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
1331
|
-
function dialogTabs(theme, tabs, active) {
|
|
1332
|
-
return tabs.map((tab) => tab === active ? theme.fg("accent", theme.bold(`[${tab}]`)) : theme.fg("muted", tab)).join(" ");
|
|
1333
|
-
}
|
|
1334
|
-
function dialogKeys(theme, hints) {
|
|
1335
|
-
const separator = theme.fg("dim", " · ");
|
|
1336
|
-
return hints.map(([key, description]) => `${theme.fg("accent", key)} ${theme.fg("muted", description)}`).join(separator);
|
|
1337
|
-
}
|
|
1338
|
-
function paneTop(theme, width, title) {
|
|
1339
|
-
if (width < 3)
|
|
1340
|
-
return truncateToWidth(theme.fg("accent", title), Math.max(1, width));
|
|
1341
|
-
const label = theme.fg("accent", theme.bold(` ${title} `));
|
|
1342
|
-
return `${label}${theme.fg("border", "─".repeat(Math.max(0, width - visibleWidth(label))))}`;
|
|
1343
|
-
}
|
|
1344
|
-
function paneRow(_theme, width, content = "") {
|
|
1345
|
-
if (width < 2)
|
|
1346
|
-
return " ".repeat(Math.max(0, width));
|
|
1347
|
-
const line = truncateToWidth(content, Math.max(1, width - 2));
|
|
1348
|
-
return ` ${line}${" ".repeat(Math.max(0, width - visibleWidth(line) - 1))}`;
|
|
1349
|
-
}
|
|
1350
|
-
|
|
1351
1302
|
// commands.ts
|
|
1352
1303
|
import { fuzzyFilter } from "@earendil-works/pi-tui";
|
|
1353
1304
|
var DEFAULT_SUBCOMMAND = "status";
|
|
@@ -1362,9 +1313,6 @@ function parseArgv(args) {
|
|
|
1362
1313
|
trailing: /\s$/.test(args)
|
|
1363
1314
|
};
|
|
1364
1315
|
}
|
|
1365
|
-
function sandboxOverview(ctx, integration) {
|
|
1366
|
-
return integration.sandboxCallbacks?.overview?.(ctx.cwd, isProjectTrusted(ctx));
|
|
1367
|
-
}
|
|
1368
1316
|
function taskItems(tasks, prefix) {
|
|
1369
1317
|
return tasks.map((task) => ({
|
|
1370
1318
|
value: `${prefix}${task.id}`,
|
|
@@ -1383,7 +1331,7 @@ var SUBCOMMANDS = [
|
|
|
1383
1331
|
summary: "Inspect sandbox & agent runtime status",
|
|
1384
1332
|
pane: (argv) => argv.rest ? undefined : "overview",
|
|
1385
1333
|
run: (_argv, { ctx, runtime, integration }) => {
|
|
1386
|
-
const overview =
|
|
1334
|
+
const overview = integration.sandboxCallbacks?.overview?.(ctx.cwd, isProjectTrusted(ctx));
|
|
1387
1335
|
const sandbox = !overview ? "unavailable" : !overview.enabled ? "disabled" : overview.running ? "active" : "enabled (inactive)";
|
|
1388
1336
|
const primary = runtime.primaryAgentName();
|
|
1389
1337
|
const tasks = runtime.getTasks();
|
|
@@ -1399,14 +1347,14 @@ var SUBCOMMANDS = [
|
|
|
1399
1347
|
{
|
|
1400
1348
|
name: "sandbox",
|
|
1401
1349
|
summary: "Inspect or toggle sandbox OS isolation",
|
|
1402
|
-
pane: (argv, { ctx, integration }) => !argv.rest &&
|
|
1350
|
+
pane: (argv, { ctx, integration }) => !argv.rest && integration.sandboxCallbacks?.overview?.(ctx.cwd, isProjectTrusted(ctx)) ? "overview" : undefined,
|
|
1403
1351
|
complete: () => [
|
|
1404
1352
|
{ value: "sandbox on", label: "on", description: "Enable OS sandbox isolation" },
|
|
1405
1353
|
{ value: "sandbox off", label: "off", description: "Disable OS sandbox isolation" }
|
|
1406
1354
|
],
|
|
1407
1355
|
run: async (argv, { ctx, integration }) => {
|
|
1408
1356
|
const callbacks = integration.sandboxCallbacks;
|
|
1409
|
-
const overview =
|
|
1357
|
+
const overview = integration.sandboxCallbacks?.overview?.(ctx.cwd, isProjectTrusted(ctx));
|
|
1410
1358
|
if (!callbacks || !overview) {
|
|
1411
1359
|
ctx.ui.notify("Sandbox controls are unavailable", "warning");
|
|
1412
1360
|
return;
|
|
@@ -1456,7 +1404,7 @@ Scope: ${scope} configuration`);
|
|
|
1456
1404
|
if (!runtime || !ctx)
|
|
1457
1405
|
return [];
|
|
1458
1406
|
try {
|
|
1459
|
-
return
|
|
1407
|
+
return [...runtime.getAgentCatalog(ctx).agents.values()].filter((agent) => !agent.hidden).map((agent) => ({
|
|
1460
1408
|
value: `agents @${agent.name}`,
|
|
1461
1409
|
label: `@${agent.name}`,
|
|
1462
1410
|
description: agent.description ?? (agent.model ? `Model: ${agent.model}` : "Primary agent")
|
|
@@ -1467,7 +1415,7 @@ Scope: ${scope} configuration`);
|
|
|
1467
1415
|
},
|
|
1468
1416
|
run: async (argv, { ctx, runtime }) => {
|
|
1469
1417
|
if (!argv.rest) {
|
|
1470
|
-
const names =
|
|
1418
|
+
const names = [...runtime.getAgentCatalog(ctx).agents.values()].filter((agent) => !agent.hidden).map((agent) => `@${agent.name}`).join(", ");
|
|
1471
1419
|
ctx.ui.notify(`Available agents: ${names || "none"}`, "info");
|
|
1472
1420
|
return;
|
|
1473
1421
|
}
|
|
@@ -1482,7 +1430,7 @@ Scope: ${scope} configuration`);
|
|
|
1482
1430
|
summary: "Inspect configured process subagents",
|
|
1483
1431
|
pane: (argv) => argv.rest ? undefined : "subagent",
|
|
1484
1432
|
run: (_argv, { ctx, runtime }) => {
|
|
1485
|
-
const names =
|
|
1433
|
+
const names = [...runtime.getAgentCatalog(ctx).agents.values()].filter((agent) => !agent.hidden).filter((agent) => agent.mode === "subagent").map((agent) => `@${agent.name}`).join(", ");
|
|
1486
1434
|
ctx.ui.notify(`Subagents: ${names || "none"}`, "info");
|
|
1487
1435
|
}
|
|
1488
1436
|
},
|
|
@@ -1547,9 +1495,6 @@ Scope: ${scope} configuration`);
|
|
|
1547
1495
|
}
|
|
1548
1496
|
}
|
|
1549
1497
|
];
|
|
1550
|
-
function visibleAgents(catalog) {
|
|
1551
|
-
return [...catalog.agents.values()].filter((agent) => !agent.hidden);
|
|
1552
|
-
}
|
|
1553
1498
|
function itemText(item) {
|
|
1554
1499
|
return item.search ?? item.label;
|
|
1555
1500
|
}
|
|
@@ -2049,6 +1994,25 @@ function listRowBudget(terminalRows, floor, chrome) {
|
|
|
2049
1994
|
return floor;
|
|
2050
1995
|
return Math.max(floor, Math.floor(terminalRows * OVERLAY_HEIGHT_RATIO) - chrome);
|
|
2051
1996
|
}
|
|
1997
|
+
function dialogTabs(theme, tabs, active) {
|
|
1998
|
+
return tabs.map((tab) => tab === active ? theme.fg("accent", theme.bold(`[${tab}]`)) : theme.fg("muted", tab)).join(" ");
|
|
1999
|
+
}
|
|
2000
|
+
function dialogKeys(theme, hints) {
|
|
2001
|
+
const separator = theme.fg("dim", " · ");
|
|
2002
|
+
return hints.map(([key, description]) => `${theme.fg("accent", key)} ${theme.fg("muted", description)}`).join(separator);
|
|
2003
|
+
}
|
|
2004
|
+
function paneTop(theme, width, title) {
|
|
2005
|
+
if (width < 3)
|
|
2006
|
+
return truncateToWidth(theme.fg("accent", title), Math.max(1, width));
|
|
2007
|
+
const label = theme.fg("accent", theme.bold(` ${title} `));
|
|
2008
|
+
return `${label}${theme.fg("border", "─".repeat(Math.max(0, width - visibleWidth(label))))}`;
|
|
2009
|
+
}
|
|
2010
|
+
function paneRow(_theme, width, content = "") {
|
|
2011
|
+
if (width < 2)
|
|
2012
|
+
return " ".repeat(Math.max(0, width));
|
|
2013
|
+
const line = truncateToWidth(content, Math.max(1, width - 2));
|
|
2014
|
+
return ` ${line}${" ".repeat(Math.max(0, width - visibleWidth(line) - 1))}`;
|
|
2015
|
+
}
|
|
2052
2016
|
var PI_THINKING_LEVELS = new Set(["off", "minimal", "low", "medium", "high", "xhigh", "max"]);
|
|
2053
2017
|
var AGENTS_HELP_ROWS = [
|
|
2054
2018
|
["Tab", "Next tab"],
|
|
@@ -2314,18 +2278,14 @@ function extractCwdFromTaskJsonFile(filePath) {
|
|
|
2314
2278
|
return {};
|
|
2315
2279
|
}
|
|
2316
2280
|
}
|
|
2317
|
-
function defaultSessionDirForCwd(cwd, agentDir = getAgentDir4()) {
|
|
2318
|
-
const resolvedCwd = resolve2(cwd);
|
|
2319
|
-
const safePath = `--${resolvedCwd.replace(/^[/\\]/, "").replace(/[/\\:]/g, "-")}--`;
|
|
2320
|
-
return join6(agentDir, "sessions", safePath);
|
|
2321
|
-
}
|
|
2322
2281
|
function isSubagentSessionDirForCwd(parentSessionDir, targetCwd) {
|
|
2323
2282
|
const files = findFilesRecursively(parentSessionDir);
|
|
2324
2283
|
if (files.length === 0) {
|
|
2325
2284
|
return true;
|
|
2326
2285
|
}
|
|
2327
2286
|
const resolvedTarget = resolve2(targetCwd);
|
|
2328
|
-
const
|
|
2287
|
+
const safePath = `--${resolvedTarget.replace(/^[/\\]/, "").replace(/[/\\:]/g, "-")}--`;
|
|
2288
|
+
const targetSessionDir = resolve2(join6(getAgentDir4(), "sessions", safePath));
|
|
2329
2289
|
let hasTargetCwd = false;
|
|
2330
2290
|
let hasOtherCwd = false;
|
|
2331
2291
|
for (const file of files) {
|
|
@@ -2399,9 +2359,6 @@ function taskProgress(task) {
|
|
|
2399
2359
|
progress.push(`retry ${task.retryAttempt}`);
|
|
2400
2360
|
return progress;
|
|
2401
2361
|
}
|
|
2402
|
-
function taskOutput(details, fallback) {
|
|
2403
|
-
return details.error ?? details.output ?? fallback;
|
|
2404
|
-
}
|
|
2405
2362
|
function workerDialogTitle(task, title) {
|
|
2406
2363
|
return `@${task.agent} · ${task.description} · ${task.id.slice(0, 8)}
|
|
2407
2364
|
${title}`;
|
|
@@ -2456,8 +2413,27 @@ function dependencyRoot(path) {
|
|
|
2456
2413
|
const index = path.lastIndexOf(marker);
|
|
2457
2414
|
return index < 0 ? undefined : path.slice(0, index + marker.length - 1);
|
|
2458
2415
|
}
|
|
2416
|
+
function endpointHost(baseUrl) {
|
|
2417
|
+
if (!baseUrl)
|
|
2418
|
+
return;
|
|
2419
|
+
try {
|
|
2420
|
+
return canonicalizeHost(new URL(baseUrl).hostname) ?? undefined;
|
|
2421
|
+
} catch {
|
|
2422
|
+
return;
|
|
2423
|
+
}
|
|
2424
|
+
}
|
|
2425
|
+
function modelEndpointDomains(ctx, selectedModel) {
|
|
2426
|
+
const models = ctx.modelRegistry?.getAll() ?? [];
|
|
2427
|
+
const qualified = models.find((model) => `${model.provider}/${model.id}` === selectedModel);
|
|
2428
|
+
const byId = models.filter((model) => model.id === selectedModel);
|
|
2429
|
+
const registered = qualified ?? (byId.length === 1 ? byId[0] : undefined);
|
|
2430
|
+
const activeName = ctx.model ? `${ctx.model.provider}/${ctx.model.id}` : undefined;
|
|
2431
|
+
const active = selectedModel === activeName || selectedModel === ctx.model?.id ? ctx.model : undefined;
|
|
2432
|
+
const host = endpointHost(registered?.baseUrl ?? active?.baseUrl);
|
|
2433
|
+
return host ? [host] : [];
|
|
2434
|
+
}
|
|
2459
2435
|
function agentBootstrapPaths(agentDir) {
|
|
2460
|
-
|
|
2436
|
+
const entries = [
|
|
2461
2437
|
"settings.json",
|
|
2462
2438
|
"landstrip.json",
|
|
2463
2439
|
"models.json",
|
|
@@ -2474,7 +2450,8 @@ function agentBootstrapPaths(agentDir) {
|
|
|
2474
2450
|
"bin",
|
|
2475
2451
|
"npm",
|
|
2476
2452
|
"git"
|
|
2477
|
-
]
|
|
2453
|
+
];
|
|
2454
|
+
return [agentDir, ...entries.map((entry) => join6(agentDir, entry))];
|
|
2478
2455
|
}
|
|
2479
2456
|
|
|
2480
2457
|
class Semaphore {
|
|
@@ -3312,7 +3289,7 @@ ${this.primaryAgent.prompt}` };
|
|
|
3312
3289
|
const listedAgents = agentsForTab();
|
|
3313
3290
|
const agentRows = listRowBudget(tui.terminal?.rows, AGENT_LIST_ROWS, AGENT_TAB_CHROME_ROWS);
|
|
3314
3291
|
const { shown, start, status } = listWindow(listedAgents, selectedAgent, agentRows);
|
|
3315
|
-
const nameWidth = Math.min(20, Math.max(5, ...listedAgents.map((agent2) =>
|
|
3292
|
+
const nameWidth = Math.min(20, Math.max(5, ...listedAgents.map((agent2) => visibleWidth(`@${agent2.name}`))));
|
|
3316
3293
|
const modelWidth = Math.max(10, Math.min(24, Math.floor((contentWidth - 2) / 3)));
|
|
3317
3294
|
const enabledWidth = 13;
|
|
3318
3295
|
const runtimeWidth = Math.max(12, contentWidth - 2 - nameWidth - 1 - modelWidth - 1 - enabledWidth - 1);
|
|
@@ -3531,7 +3508,7 @@ ${this.primaryAgent.prompt}` };
|
|
|
3531
3508
|
const shellReadMode = overview.windowsMode !== undefined ? "Policy (required)" : overview.shellReadMode === "host" ? "Host-aligned" : "Policy";
|
|
3532
3509
|
const changePath = overview.changeScope === "project" ? overview.paths.project : overview.paths.global;
|
|
3533
3510
|
const item = (label, value) => ` ${theme.fg("dim", label.padEnd(16))} ${value}`;
|
|
3534
|
-
lines.push(`${theme.fg(status.color, "●")} ${theme.fg("text", status.label)}`, item("Configured", overview.enabled ? theme.fg("text", "Enabled") : theme.fg("warning", "Disabled")), item("Runtime", overview.running ? theme.fg("success", "Running") : theme.fg("dim", "Not running")), "", theme.fg("accent", "Protection"), item("Network", networkMode), item("Shell reads", shellReadMode), item("Read rules", `${overview.config.filesystem.denyRead.length + overview.config.filesystem.allowRead.length} · ${overview.readRuleScope}`), item("Write rules", String(overview.config.filesystem.allowWrite.length + overview.config.filesystem.denyWrite.length)), item("Session grants", String(overview.sessionDomains.length + overview.sessionReadPaths.length + overview.sessionWritePaths.length)), "", theme.fg("accent", "Configuration"), item("Change scope", overview.changeScope === "project" ? "Project" : "Global"), item("Change file",
|
|
3511
|
+
lines.push(`${theme.fg(status.color, "●")} ${theme.fg("text", status.label)}`, item("Configured", overview.enabled ? theme.fg("text", "Enabled") : theme.fg("warning", "Disabled")), item("Runtime", overview.running ? theme.fg("success", "Running") : theme.fg("dim", "Not running")), "", theme.fg("accent", "Protection"), item("Network", networkMode), item("Shell reads", shellReadMode), item("Read rules", `${overview.config.filesystem.denyRead.length + overview.config.filesystem.allowRead.length} · ${overview.readRuleScope}`), item("Write rules", String(overview.config.filesystem.allowWrite.length + overview.config.filesystem.denyWrite.length)), item("Session grants", String(overview.sessionDomains.length + overview.sessionReadPaths.length + overview.sessionWritePaths.length)), "", theme.fg("accent", "Configuration"), item("Change scope", overview.changeScope === "project" ? "Project" : "Global"), item("Change file", truncateToWidth(changePath, Math.max(10, contentWidth - 20))), item("Project file", truncateToWidth(overview.paths.project, Math.max(10, contentWidth - 20))), item("Global file", truncateToWidth(overview.paths.global, Math.max(10, contentWidth - 20))), item("Landstrip binary", truncateToWidth(overview.paths.binary, Math.max(10, contentWidth - 20))));
|
|
3535
3512
|
if (overview.windowsMode !== undefined)
|
|
3536
3513
|
lines.push(item("Windows mode", overview.windowsMode));
|
|
3537
3514
|
lines.push("", theme.fg("accent", "Network"), item("Allowed domains", listValue(overview.config.network.allowedDomains)), item("Denied domains", listValue(overview.config.network.deniedDomains)), item("Unix sockets", overview.config.network.allowAllUnixSockets ? "all" : listValue(overview.config.network.allowUnixSockets)), "", theme.fg("accent", "Filesystem"), item("Shell reads", shellReadMode), item("Read rules for", overview.readRuleScope), item("Denied reads", listValue(overview.config.filesystem.denyRead)), item("Allowed reads", listValue(overview.config.filesystem.allowRead)), item("Allowed writes", listValue(overview.config.filesystem.allowWrite)), item("Denied writes", listValue(overview.config.filesystem.denyWrite)), "", theme.fg("accent", "Session grants"), item("Domains", listValue(overview.sessionDomains)), item("Read paths", listValue(overview.sessionReadPaths)), item("Write paths", listValue(overview.sessionWritePaths)));
|
|
@@ -3636,7 +3613,7 @@ ${this.primaryAgent.prompt}` };
|
|
|
3636
3613
|
lines.push(theme.fg("dim", `${scroll + 1}–${scroll + shown.length} of ${transcript.length}`));
|
|
3637
3614
|
}
|
|
3638
3615
|
if (steering) {
|
|
3639
|
-
const input = steering.render(Math.max(2, contentWidth -
|
|
3616
|
+
const input = steering.render(Math.max(2, contentWidth - visibleWidth("Steer ")))[0] ?? "";
|
|
3640
3617
|
lines.push(`${theme.fg("accent", "Steer")} ${input.replace(/^>/, "›")}`);
|
|
3641
3618
|
} else if (task.state === "queued" || task.state === "running") {
|
|
3642
3619
|
lines.push(dialogKeys(theme, [
|
|
@@ -3645,17 +3622,17 @@ ${this.primaryAgent.prompt}` };
|
|
|
3645
3622
|
["Esc", "tasks"]
|
|
3646
3623
|
]));
|
|
3647
3624
|
}
|
|
3648
|
-
return pane(lines.map((line) =>
|
|
3625
|
+
return pane(lines.map((line) => truncateToWidth(line, contentWidth)));
|
|
3649
3626
|
},
|
|
3650
3627
|
help: (frame) => {
|
|
3651
3628
|
const { tabs, pane, contentWidth, pad } = frame;
|
|
3652
|
-
const shortcutWidth = Math.max(
|
|
3629
|
+
const shortcutWidth = Math.max(visibleWidth("Shortcut"), ...AGENTS_HELP_ROWS.map(([shortcut]) => visibleWidth(shortcut)));
|
|
3653
3630
|
const descriptionWidth = Math.max(1, contentWidth - shortcutWidth - 4);
|
|
3654
3631
|
const lines = [
|
|
3655
3632
|
tabs,
|
|
3656
3633
|
"",
|
|
3657
3634
|
theme.fg("dim", ` ${pad("Shortcut", shortcutWidth)} Description`),
|
|
3658
|
-
...AGENTS_HELP_ROWS.map(([shortcut, description]) => ` ${theme.fg("accent", pad(shortcut, shortcutWidth))} ${theme.fg("text",
|
|
3635
|
+
...AGENTS_HELP_ROWS.map(([shortcut, description]) => ` ${theme.fg("accent", pad(shortcut, shortcutWidth))} ${theme.fg("text", truncateToWidth(description, descriptionWidth))}`)
|
|
3659
3636
|
];
|
|
3660
3637
|
return pane(lines);
|
|
3661
3638
|
}
|
|
@@ -3858,12 +3835,12 @@ ${this.primaryAgent.prompt}` };
|
|
|
3858
3835
|
return rows.slice(0, paneHeight);
|
|
3859
3836
|
};
|
|
3860
3837
|
const pad = (value, cellWidth) => {
|
|
3861
|
-
const clipped =
|
|
3862
|
-
return `${clipped}${" ".repeat(Math.max(0, cellWidth -
|
|
3838
|
+
const clipped = truncateToWidth(value, cellWidth);
|
|
3839
|
+
return `${clipped}${" ".repeat(Math.max(0, cellWidth - visibleWidth(clipped)))}`;
|
|
3863
3840
|
};
|
|
3864
3841
|
const listValue = (values) => {
|
|
3865
3842
|
const value = values.join(", ") || "none";
|
|
3866
|
-
return
|
|
3843
|
+
return truncateToWidth(value, Math.max(10, contentWidth - 20));
|
|
3867
3844
|
};
|
|
3868
3845
|
refreshTasks();
|
|
3869
3846
|
const tabs = dialogTabs(theme, TAB_ORDER.map((key) => TAB_LABELS[key]), TAB_LABELS[tab]);
|
|
@@ -4051,7 +4028,7 @@ ${descriptions}` : ""),
|
|
|
4051
4028
|
if (metrics.length > 0)
|
|
4052
4029
|
text += `
|
|
4053
4030
|
${theme.fg("dim", metrics.join(" · "))}`;
|
|
4054
|
-
const output =
|
|
4031
|
+
const output = details.error ?? details.output ?? "";
|
|
4055
4032
|
if (output) {
|
|
4056
4033
|
const lines = output.trimEnd().split(`
|
|
4057
4034
|
`);
|
|
@@ -4482,6 +4459,7 @@ ${catalog.diagnostics.join(`
|
|
|
4482
4459
|
TEMP: temp
|
|
4483
4460
|
},
|
|
4484
4461
|
ctx,
|
|
4462
|
+
domains: modelEndpointDomains(ctx, model),
|
|
4485
4463
|
readPaths: [
|
|
4486
4464
|
...new Set([
|
|
4487
4465
|
ctx.cwd,
|
|
@@ -4776,15 +4754,15 @@ ${renderTaskResult(task.id, "error", message)}`);
|
|
|
4776
4754
|
const progress = taskProgress(record);
|
|
4777
4755
|
const suffix = progress.length > 0 ? theme.fg("dim", ` · ${progress.join(" · ")}`) : "";
|
|
4778
4756
|
const indentWidth = 3 + Math.max(0, record.depth) * 3;
|
|
4779
|
-
const descriptionWidth = Math.max(1, width - indentWidth -
|
|
4780
|
-
const description = theme.fg("text",
|
|
4757
|
+
const descriptionWidth = Math.max(1, width - indentWidth - visibleWidth(`${state} ${agent} ${suffix}`));
|
|
4758
|
+
const description = theme.fg("text", truncateToWidth(task.description, descriptionWidth));
|
|
4781
4759
|
return `${state} ${agent} ${description}${suffix}`;
|
|
4782
4760
|
});
|
|
4783
4761
|
const shown = tree.slice(0, 8);
|
|
4784
4762
|
if (tree.length > shown.length) {
|
|
4785
4763
|
shown.push(theme.fg("dim", ` … ${tree.length - shown.length} more`));
|
|
4786
4764
|
}
|
|
4787
|
-
return [header, ...shown].map((line) =>
|
|
4765
|
+
return [header, ...shown].map((line) => truncateToWidth(line, Math.max(1, width)));
|
|
4788
4766
|
},
|
|
4789
4767
|
invalidate() {}
|
|
4790
4768
|
}));
|
|
@@ -5202,13 +5180,10 @@ function windowsStatus() {
|
|
|
5202
5180
|
}
|
|
5203
5181
|
return status;
|
|
5204
5182
|
}
|
|
5205
|
-
function activeWindowsImplementation() {
|
|
5206
|
-
return windowsStatus().active;
|
|
5207
|
-
}
|
|
5208
5183
|
function shouldStartProxy(config) {
|
|
5209
5184
|
if (config.network.allowNetwork)
|
|
5210
5185
|
return false;
|
|
5211
|
-
return process.platform !== "win32" ||
|
|
5186
|
+
return process.platform !== "win32" || windowsStatus().active === "restrictedUser" || config.windows.allowLoopback;
|
|
5212
5187
|
}
|
|
5213
5188
|
function restrictedUserProxyPortRange() {
|
|
5214
5189
|
if (process.platform !== "win32")
|
|
@@ -5221,9 +5196,6 @@ function restrictedUserProxyPortRange() {
|
|
|
5221
5196
|
}
|
|
5222
5197
|
return { low: status.proxyPortLow, high: status.proxyPortHigh };
|
|
5223
5198
|
}
|
|
5224
|
-
function getConfigPaths(cwd) {
|
|
5225
|
-
return getPiConfigPaths(cwd, "sandbox.json");
|
|
5226
|
-
}
|
|
5227
5199
|
function readOrEmptyConfig(configPath) {
|
|
5228
5200
|
if (!existsSync5(configPath))
|
|
5229
5201
|
return {};
|
|
@@ -5239,11 +5211,11 @@ function writeConfigFile(configPath, config) {
|
|
|
5239
5211
|
`, "utf-8");
|
|
5240
5212
|
}
|
|
5241
5213
|
function getSandboxConfigWriteTarget(cwd, includeProject = true) {
|
|
5242
|
-
const { globalPath, projectPath } =
|
|
5214
|
+
const { globalPath, projectPath } = getPiConfigPaths(cwd, "sandbox.json");
|
|
5243
5215
|
return includeProject ? { scope: "project", path: projectPath } : { scope: "global", path: globalPath };
|
|
5244
5216
|
}
|
|
5245
5217
|
async function writeSandboxConfigEnabled(cwd, enabled, scope) {
|
|
5246
|
-
const paths =
|
|
5218
|
+
const paths = getPiConfigPaths(cwd, "sandbox.json");
|
|
5247
5219
|
const path = scope === "project" ? paths.projectPath : paths.globalPath;
|
|
5248
5220
|
await withFileMutationQueue3(path, async () => {
|
|
5249
5221
|
const config = readOrEmptyConfig(path);
|
|
@@ -5255,7 +5227,7 @@ async function writeSandboxConfigEnabled(cwd, enabled, scope) {
|
|
|
5255
5227
|
});
|
|
5256
5228
|
}
|
|
5257
5229
|
function loadSandboxEnabledSettings(cwd, includeProject) {
|
|
5258
|
-
const { projectPath } =
|
|
5230
|
+
const { projectPath } = getPiConfigPaths(cwd, "sandbox.json");
|
|
5259
5231
|
const global = loadSandboxConfig(cwd, false).enabled;
|
|
5260
5232
|
if (!includeProject || !existsSync5(projectPath))
|
|
5261
5233
|
return { global };
|
|
@@ -5272,25 +5244,6 @@ async function addConfigValue(configPath, value, readValues, writeValues) {
|
|
|
5272
5244
|
writeConfigFile(configPath, config);
|
|
5273
5245
|
});
|
|
5274
5246
|
}
|
|
5275
|
-
function addDomainToConfig(configPath, domain) {
|
|
5276
|
-
return addConfigValue(configPath, domain, (config) => config.network?.allowedDomains ?? [], (config, allowedDomains) => {
|
|
5277
|
-
config.network = {
|
|
5278
|
-
...config.network,
|
|
5279
|
-
allowedDomains,
|
|
5280
|
-
deniedDomains: config.network?.deniedDomains ?? []
|
|
5281
|
-
};
|
|
5282
|
-
});
|
|
5283
|
-
}
|
|
5284
|
-
function addReadPathToConfig(configPath, pathToAdd) {
|
|
5285
|
-
return addConfigValue(configPath, pathToAdd, (config) => config.filesystem?.allowRead ?? [], (config, allowRead) => {
|
|
5286
|
-
config.filesystem = { ...config.filesystem, allowRead };
|
|
5287
|
-
});
|
|
5288
|
-
}
|
|
5289
|
-
function addWritePathToConfig(configPath, pathToAdd) {
|
|
5290
|
-
return addConfigValue(configPath, pathToAdd, (config) => config.filesystem?.allowWrite ?? [], (config, allowWrite) => {
|
|
5291
|
-
config.filesystem = { ...config.filesystem, allowWrite };
|
|
5292
|
-
});
|
|
5293
|
-
}
|
|
5294
5247
|
function mergeAllowances(base, session, execution) {
|
|
5295
5248
|
return [...base, ...session, ...execution ?? []];
|
|
5296
5249
|
}
|
|
@@ -5456,28 +5409,10 @@ ${option.hint ?? "This changes persisted sandbox policy."}`, { signal });
|
|
|
5456
5409
|
}
|
|
5457
5410
|
return option.action;
|
|
5458
5411
|
}
|
|
5459
|
-
function promptDomainBlock(ctx, domain, signal) {
|
|
5460
|
-
return showPermissionPrompt(ctx, `Network blocked: "${domain}" is not in the allowed domains list`, PERMISSION_OPTIONS, signal);
|
|
5461
|
-
}
|
|
5462
5412
|
function promptReadBlock(ctx, filePath, reason, signal) {
|
|
5463
5413
|
const title = reason ? `Read blocked: "${filePath}" is in denyRead (${reason})` : `Read blocked: "${filePath}" is not in allowRead`;
|
|
5464
5414
|
return showPermissionPrompt(ctx, title, PERMISSION_OPTIONS, signal);
|
|
5465
5415
|
}
|
|
5466
|
-
function promptWriteBlock(ctx, filePath, signal) {
|
|
5467
|
-
return showPermissionPrompt(ctx, `Write blocked: "${filePath}" is not in allowWrite`, PERMISSION_OPTIONS, signal);
|
|
5468
|
-
}
|
|
5469
|
-
function promptFilesystemToolBlock(ctx, accesses, authorizationNote, signal) {
|
|
5470
|
-
const paths = accesses.map(({ operation, path }) => `${operation}: ${path}`).join(`
|
|
5471
|
-
`);
|
|
5472
|
-
const note = authorizationNote ? `
|
|
5473
|
-
|
|
5474
|
-
${authorizationNote}` : "";
|
|
5475
|
-
return showPermissionPrompt(ctx, `Filesystem policy blocked this tool call:
|
|
5476
|
-
${paths}${note}`, PERMISSION_OPTIONS, signal);
|
|
5477
|
-
}
|
|
5478
|
-
function promptNetworkBlock(ctx, operation, target, signal) {
|
|
5479
|
-
return showPermissionPrompt(ctx, `Network blocked: ${operation} "${target}"`, NETWORK_PERMISSION_OPTIONS, signal);
|
|
5480
|
-
}
|
|
5481
5416
|
function writeEnvFile(env, proxyPort, proxyToken) {
|
|
5482
5417
|
const lines = [];
|
|
5483
5418
|
for (const [key, value] of Object.entries(env)) {
|
|
@@ -5569,11 +5504,6 @@ function createLandstripIntegrationWithPrompts(options, permissionPrompts) {
|
|
|
5569
5504
|
function loadConfig(cwd) {
|
|
5570
5505
|
return loadSandboxConfig(cwd, projectConfigTrusted);
|
|
5571
5506
|
}
|
|
5572
|
-
function createPlainBashTool(cwd) {
|
|
5573
|
-
return createBashToolDefinition(cwd, {
|
|
5574
|
-
shellPath: SettingsManager.create(cwd).getShellPath()
|
|
5575
|
-
});
|
|
5576
|
-
}
|
|
5577
5507
|
let sandboxEnabled = false;
|
|
5578
5508
|
let sandboxReady = false;
|
|
5579
5509
|
let sandboxState = "unavailable";
|
|
@@ -5709,16 +5639,6 @@ function createLandstripIntegrationWithPrompts(options, permissionPrompts) {
|
|
|
5709
5639
|
function getWorkerExtensions() {
|
|
5710
5640
|
return [...workerExtensions].map(([id, extension]) => ({ id, entry: extension.entry }));
|
|
5711
5641
|
}
|
|
5712
|
-
function resetSessionAllowances() {
|
|
5713
|
-
sessionAllowedDomains.length = 0;
|
|
5714
|
-
sessionAllowedReadPaths.length = 0;
|
|
5715
|
-
sessionAllowedWritePaths.length = 0;
|
|
5716
|
-
sessionAllowedTargets.length = 0;
|
|
5717
|
-
unsandboxedWorkerWarningShown = false;
|
|
5718
|
-
}
|
|
5719
|
-
function getEffectiveAllowedDomains(config, allowances) {
|
|
5720
|
-
return mergeAllowances(config.network.allowedDomains, sessionAllowedDomains, allowances?.domains);
|
|
5721
|
-
}
|
|
5722
5642
|
function getEffectiveAllowRead(config, cwd, allowances) {
|
|
5723
5643
|
const paths = mergeAllowances(config.filesystem.allowRead, sessionAllowedReadPaths, allowances?.readPaths);
|
|
5724
5644
|
if (process.platform !== "win32")
|
|
@@ -5760,11 +5680,17 @@ function createLandstripIntegrationWithPrompts(options, permissionPrompts) {
|
|
|
5760
5680
|
};
|
|
5761
5681
|
}
|
|
5762
5682
|
async function applyDomainChoice(choice, domain, cwd, allowances) {
|
|
5763
|
-
const { globalPath, projectPath } =
|
|
5764
|
-
|
|
5765
|
-
|
|
5766
|
-
|
|
5767
|
-
|
|
5683
|
+
const { globalPath, projectPath } = getPiConfigPaths(cwd, "sandbox.json");
|
|
5684
|
+
const configPath = choice === "project" ? projectPath : choice === "global" ? globalPath : undefined;
|
|
5685
|
+
if (configPath) {
|
|
5686
|
+
await addConfigValue(configPath, domain, (config) => config.network?.allowedDomains ?? [], (config, allowedDomains) => {
|
|
5687
|
+
config.network = {
|
|
5688
|
+
...config.network,
|
|
5689
|
+
allowedDomains,
|
|
5690
|
+
deniedDomains: config.network?.deniedDomains ?? []
|
|
5691
|
+
};
|
|
5692
|
+
});
|
|
5693
|
+
}
|
|
5768
5694
|
const target = choice === "once" ? allowances?.domains : sessionAllowedDomains;
|
|
5769
5695
|
if (target && !target.includes(domain))
|
|
5770
5696
|
target.push(domain);
|
|
@@ -5774,24 +5700,28 @@ function createLandstripIntegrationWithPrompts(options, permissionPrompts) {
|
|
|
5774
5700
|
notify(ctx, `${verb} allowed (${choice}): ${scope}`, "info");
|
|
5775
5701
|
}
|
|
5776
5702
|
async function applyReadChoice(ctx, choice, filePath, cwd, allowances) {
|
|
5777
|
-
const { globalPath, projectPath } =
|
|
5703
|
+
const { globalPath, projectPath } = getPiConfigPaths(cwd, "sandbox.json");
|
|
5778
5704
|
const scope = sessionScopeFor(filePath, cwd);
|
|
5779
|
-
|
|
5780
|
-
|
|
5781
|
-
|
|
5782
|
-
|
|
5705
|
+
const configPath = choice === "project" ? projectPath : choice === "global" ? globalPath : undefined;
|
|
5706
|
+
if (configPath) {
|
|
5707
|
+
await addConfigValue(configPath, scope, (config) => config.filesystem?.allowRead ?? [], (config, allowRead) => {
|
|
5708
|
+
config.filesystem = { ...config.filesystem, allowRead };
|
|
5709
|
+
});
|
|
5710
|
+
}
|
|
5783
5711
|
const target = choice === "once" ? allowances?.readPaths : sessionAllowedReadPaths;
|
|
5784
5712
|
if (target && !target.includes(scope))
|
|
5785
5713
|
target.push(scope);
|
|
5786
5714
|
noteScope(ctx, "Read", choice, filePath, scope);
|
|
5787
5715
|
}
|
|
5788
5716
|
async function applyWriteChoice(ctx, choice, filePath, cwd, allowances) {
|
|
5789
|
-
const { globalPath, projectPath } =
|
|
5717
|
+
const { globalPath, projectPath } = getPiConfigPaths(cwd, "sandbox.json");
|
|
5790
5718
|
const scope = sessionScopeFor(filePath, cwd);
|
|
5791
|
-
|
|
5792
|
-
|
|
5793
|
-
|
|
5794
|
-
|
|
5719
|
+
const configPath = choice === "project" ? projectPath : choice === "global" ? globalPath : undefined;
|
|
5720
|
+
if (configPath) {
|
|
5721
|
+
await addConfigValue(configPath, scope, (config) => config.filesystem?.allowWrite ?? [], (config, allowWrite) => {
|
|
5722
|
+
config.filesystem = { ...config.filesystem, allowWrite };
|
|
5723
|
+
});
|
|
5724
|
+
}
|
|
5795
5725
|
const target = choice === "once" ? allowances?.writePaths : sessionAllowedWritePaths;
|
|
5796
5726
|
if (target && !target.includes(scope))
|
|
5797
5727
|
target.push(scope);
|
|
@@ -5827,7 +5757,13 @@ function createLandstripIntegrationWithPrompts(options, permissionPrompts) {
|
|
|
5827
5757
|
return permissionPrompts.resolve(current, async (promptSignal) => {
|
|
5828
5758
|
const config = loadConfig(ctx.cwd);
|
|
5829
5759
|
const blocked = normalized.filter((access) => access.operation === "read" ? !readAllowed(access.path, getEffectiveAllowRead(config, ctx.cwd), getEffectiveDenyRead(config, ctx.cwd), ctx.cwd) : shouldPromptForWrite(access.path, getEffectiveAllowWrite(config), ctx.cwd));
|
|
5830
|
-
const
|
|
5760
|
+
const paths = blocked.map(({ operation, path }) => `${operation}: ${path}`).join(`
|
|
5761
|
+
`);
|
|
5762
|
+
const note = options2.authorizationNote ? `
|
|
5763
|
+
|
|
5764
|
+
${options2.authorizationNote}` : "";
|
|
5765
|
+
const choice = await showPermissionPrompt(ctx, `Filesystem policy blocked this tool call:
|
|
5766
|
+
${paths}${note}`, PERMISSION_OPTIONS, promptSignal);
|
|
5831
5767
|
if (choice === "abort" || promptSignal.aborted) {
|
|
5832
5768
|
return { allowed: false, prompted: true, reason: "Filesystem access denied" };
|
|
5833
5769
|
}
|
|
@@ -5846,14 +5782,15 @@ function createLandstripIntegrationWithPrompts(options, permissionPrompts) {
|
|
|
5846
5782
|
const config = loadConfig(cwd);
|
|
5847
5783
|
if (domainMatchesAny(domain, config.network.deniedDomains))
|
|
5848
5784
|
return false;
|
|
5849
|
-
|
|
5785
|
+
const allowedDomains = mergeAllowances(config.network.allowedDomains, sessionAllowedDomains, allowances?.domains);
|
|
5786
|
+
if (domainMatchesAny(domain, allowedDomains))
|
|
5850
5787
|
return true;
|
|
5851
5788
|
return;
|
|
5852
5789
|
};
|
|
5853
5790
|
if (!ctx.hasUI)
|
|
5854
5791
|
return current() ?? false;
|
|
5855
5792
|
return permissionPrompts.resolve(current, async (promptSignal) => {
|
|
5856
|
-
const choice = await
|
|
5793
|
+
const choice = await showPermissionPrompt(ctx, `Network blocked: "${domain}" is not in the allowed domains list`, PERMISSION_OPTIONS, promptSignal);
|
|
5857
5794
|
if (choice === "abort" || promptSignal.aborted)
|
|
5858
5795
|
return false;
|
|
5859
5796
|
await applyDomainChoice(choice, domain, cwd, allowances);
|
|
@@ -5929,7 +5866,7 @@ function createLandstripIntegrationWithPrompts(options, permissionPrompts) {
|
|
|
5929
5866
|
if (!ctx.hasUI || !promptOnBlock)
|
|
5930
5867
|
return { action: "deny", reason: "unprompted" };
|
|
5931
5868
|
return permissionPrompts.resolve(current2, async (promptSignal) => {
|
|
5932
|
-
const choice = await
|
|
5869
|
+
const choice = await showPermissionPrompt(ctx, `Network blocked: ${trap.operation} "${trap.target}"`, NETWORK_PERMISSION_OPTIONS, promptSignal);
|
|
5933
5870
|
if (choice === "abort" || promptSignal.aborted)
|
|
5934
5871
|
return { action: "deny", reason: "rejected" };
|
|
5935
5872
|
const targets = choice === "once" ? allowances.targets : sessionAllowedTargets;
|
|
@@ -5954,7 +5891,7 @@ function createLandstripIntegrationWithPrompts(options, permissionPrompts) {
|
|
|
5954
5891
|
return { action: "deny", reason: "unprompted" };
|
|
5955
5892
|
return permissionPrompts.resolve(current, async (promptSignal) => {
|
|
5956
5893
|
const config = loadConfig(cwd);
|
|
5957
|
-
const choice = trap.operation === "read" ? await promptReadBlock(ctx, path, matchesPattern(path, config.filesystem.denyRead, cwd) ? "granting allowRead will override it" : undefined, promptSignal) : await
|
|
5894
|
+
const choice = trap.operation === "read" ? await promptReadBlock(ctx, path, matchesPattern(path, config.filesystem.denyRead, cwd) ? "granting allowRead will override it" : undefined, promptSignal) : await showPermissionPrompt(ctx, `Write blocked: "${path}" is not in allowWrite`, PERMISSION_OPTIONS, promptSignal);
|
|
5958
5895
|
if (choice === "abort" || promptSignal.aborted)
|
|
5959
5896
|
return { action: "deny", reason: "rejected" };
|
|
5960
5897
|
if (trap.operation === "read") {
|
|
@@ -6061,7 +5998,7 @@ function createLandstripIntegrationWithPrompts(options, permissionPrompts) {
|
|
|
6061
5998
|
return prepareUnsandboxedRpcWorker(options2);
|
|
6062
5999
|
}
|
|
6063
6000
|
const allowances = {
|
|
6064
|
-
domains: [],
|
|
6001
|
+
domains: [...options2.domains ?? []],
|
|
6065
6002
|
readPaths: [...options2.readPaths],
|
|
6066
6003
|
writePaths: [...options2.writePaths],
|
|
6067
6004
|
targets: []
|
|
@@ -6554,7 +6491,7 @@ function createLandstripIntegrationWithPrompts(options, permissionPrompts) {
|
|
|
6554
6491
|
const retryWithAccess = async (operation, blockedPath) => {
|
|
6555
6492
|
if (!ctx.hasUI)
|
|
6556
6493
|
return null;
|
|
6557
|
-
const { globalPath, projectPath } =
|
|
6494
|
+
const { globalPath, projectPath } = getPiConfigPaths(ctx.cwd, "sandbox.json");
|
|
6558
6495
|
const current = () => {
|
|
6559
6496
|
const config2 = loadConfig(ctx.cwd);
|
|
6560
6497
|
if (operation === "write" && matchesPattern(blockedPath, config2.filesystem.denyWrite, ctx.cwd)) {
|
|
@@ -6565,7 +6502,7 @@ function createLandstripIntegrationWithPrompts(options, permissionPrompts) {
|
|
|
6565
6502
|
};
|
|
6566
6503
|
const access = await permissionPrompts.resolve(current, async (promptSignal) => {
|
|
6567
6504
|
const config2 = loadConfig(ctx.cwd);
|
|
6568
|
-
const choice = operation === "read" ? await promptReadBlock(ctx, blockedPath, matchesPattern(blockedPath, config2.filesystem.denyRead, ctx.cwd) ? "granting allowRead will override it" : undefined, promptSignal) : await
|
|
6505
|
+
const choice = operation === "read" ? await promptReadBlock(ctx, blockedPath, matchesPattern(blockedPath, config2.filesystem.denyRead, ctx.cwd) ? "granting allowRead will override it" : undefined, promptSignal) : await showPermissionPrompt(ctx, `Write blocked: "${blockedPath}" is not in allowWrite`, PERMISSION_OPTIONS, promptSignal);
|
|
6569
6506
|
if (choice === "abort" || promptSignal.aborted)
|
|
6570
6507
|
return false;
|
|
6571
6508
|
if (operation === "read") {
|
|
@@ -6664,7 +6601,7 @@ ${message}
|
|
|
6664
6601
|
return;
|
|
6665
6602
|
let implementation;
|
|
6666
6603
|
try {
|
|
6667
|
-
implementation =
|
|
6604
|
+
implementation = windowsStatus().active;
|
|
6668
6605
|
} catch (error) {
|
|
6669
6606
|
notify(ctx, formatError(error), "error");
|
|
6670
6607
|
return;
|
|
@@ -6684,7 +6621,7 @@ ${message}
|
|
|
6684
6621
|
const theme = ctx.ui.theme;
|
|
6685
6622
|
const dot = theme.fg("success", "●");
|
|
6686
6623
|
const label = theme.fg("text", "Sandbox");
|
|
6687
|
-
const windowsImplementation = process.platform === "win32" ?
|
|
6624
|
+
const windowsImplementation = process.platform === "win32" ? windowsStatus().active : undefined;
|
|
6688
6625
|
let networkLabel;
|
|
6689
6626
|
let networkColor;
|
|
6690
6627
|
if (config.network.allowNetwork) {
|
|
@@ -6759,7 +6696,9 @@ ${message}
|
|
|
6759
6696
|
return true;
|
|
6760
6697
|
}
|
|
6761
6698
|
function createBashTool(cwd) {
|
|
6762
|
-
const localBash =
|
|
6699
|
+
const localBash = createBashToolDefinition(cwd, {
|
|
6700
|
+
shellPath: SettingsManager.create(cwd).getShellPath()
|
|
6701
|
+
});
|
|
6763
6702
|
return {
|
|
6764
6703
|
...localBash,
|
|
6765
6704
|
label: "bash (landstrip)",
|
|
@@ -6811,7 +6750,11 @@ ${message}
|
|
|
6811
6750
|
pi.on("session_start", async (_event, ctx) => {
|
|
6812
6751
|
activeContext = ctx;
|
|
6813
6752
|
permissionPrompts.reset();
|
|
6814
|
-
|
|
6753
|
+
sessionAllowedDomains.length = 0;
|
|
6754
|
+
sessionAllowedReadPaths.length = 0;
|
|
6755
|
+
sessionAllowedWritePaths.length = 0;
|
|
6756
|
+
sessionAllowedTargets.length = 0;
|
|
6757
|
+
unsandboxedWorkerWarningShown = false;
|
|
6815
6758
|
const trustContext = ctx;
|
|
6816
6759
|
projectConfigTrusted = trustContext.isProjectTrusted?.() ?? false;
|
|
6817
6760
|
if (getNoSandboxFlag()) {
|
|
@@ -6849,10 +6792,10 @@ ${message}
|
|
|
6849
6792
|
enableSandbox(ctx);
|
|
6850
6793
|
}
|
|
6851
6794
|
}
|
|
6852
|
-
function
|
|
6795
|
+
function sandboxOverview(cwd, includeProject) {
|
|
6853
6796
|
const config = loadSandboxConfig(cwd, includeProject);
|
|
6854
|
-
const { globalPath, projectPath } =
|
|
6855
|
-
const windowsImplementation = process.platform === "win32" ?
|
|
6797
|
+
const { globalPath, projectPath } = getPiConfigPaths(cwd, "sandbox.json");
|
|
6798
|
+
const windowsImplementation = process.platform === "win32" ? windowsStatus().active : undefined;
|
|
6856
6799
|
return {
|
|
6857
6800
|
enabled: config.enabled,
|
|
6858
6801
|
running: sandboxEnabled && sandboxReady,
|
|
@@ -6873,7 +6816,7 @@ ${message}
|
|
|
6873
6816
|
load: loadSandboxEnabledSettings,
|
|
6874
6817
|
setEnabled: (ctx, enabled, scope) => applySandboxSetting(ctx, enabled, scope),
|
|
6875
6818
|
clearProject: (ctx) => applySandboxSetting(ctx, undefined, "project"),
|
|
6876
|
-
overview:
|
|
6819
|
+
overview: sandboxOverview
|
|
6877
6820
|
};
|
|
6878
6821
|
const integration = {
|
|
6879
6822
|
version: LANDSTRIP_RUNTIME_VERSION,
|
|
@@ -6895,25 +6838,25 @@ ${message}
|
|
|
6895
6838
|
return integration;
|
|
6896
6839
|
}
|
|
6897
6840
|
export {
|
|
6898
|
-
|
|
6899
|
-
shouldPromptForWrite,
|
|
6900
|
-
sessionScopeFor,
|
|
6901
|
-
resolveProcessReadPolicy,
|
|
6902
|
-
readAllowed,
|
|
6903
|
-
parseTrapLine,
|
|
6904
|
-
matchesPattern,
|
|
6905
|
-
isQueryTrap,
|
|
6906
|
-
formatLandstripTraps,
|
|
6907
|
-
extractRetryableNativeReadDeniedPath,
|
|
6908
|
-
extractNativeWriteDeniedPath,
|
|
6909
|
-
extractNativeDeniedPath,
|
|
6910
|
-
enforcesShellReadPolicy,
|
|
6911
|
-
domainMatchesAny,
|
|
6912
|
-
pi_landstrip_default as default,
|
|
6913
|
-
createWindowsDenyRead,
|
|
6914
|
-
createPosixShellProvider,
|
|
6915
|
-
createLandstripLauncherEnvironment,
|
|
6916
|
-
createLandstripIntegration,
|
|
6841
|
+
POSIX_SHELL_PROVIDER_ID,
|
|
6917
6842
|
controlResponseLine,
|
|
6918
|
-
|
|
6843
|
+
createLandstripIntegration,
|
|
6844
|
+
createLandstripLauncherEnvironment,
|
|
6845
|
+
createPosixShellProvider,
|
|
6846
|
+
createWindowsDenyRead,
|
|
6847
|
+
pi_landstrip_default as default,
|
|
6848
|
+
domainMatchesAny,
|
|
6849
|
+
enforcesShellReadPolicy,
|
|
6850
|
+
extractNativeDeniedPath,
|
|
6851
|
+
extractNativeWriteDeniedPath,
|
|
6852
|
+
extractRetryableNativeReadDeniedPath,
|
|
6853
|
+
formatLandstripTraps,
|
|
6854
|
+
isQueryTrap,
|
|
6855
|
+
matchesPattern,
|
|
6856
|
+
parseTrapLine,
|
|
6857
|
+
readAllowed,
|
|
6858
|
+
resolveProcessReadPolicy,
|
|
6859
|
+
sessionScopeFor,
|
|
6860
|
+
shouldPromptForWrite,
|
|
6861
|
+
writeEnvFile
|
|
6919
6862
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-landstrip",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.43",
|
|
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-api": "^0.18.
|
|
42
|
+
"@landstrip/landstrip-api": "^0.18.43",
|
|
43
43
|
"jsonc-parser": "^3.3.1",
|
|
44
44
|
"minimatch": "^10.2.5",
|
|
45
45
|
"yaml": "^2.9.0"
|