pilotswarm-cli 0.1.5 → 0.1.6
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/cli/tui.js +39 -19
- package/package.json +1 -1
package/cli/tui.js
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* npx pilotswarm remote --env .env.remote # client-only (AKS)
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
import { PilotSwarmClient, PilotSwarmWorker, PilotSwarmManagementClient, SessionBlobStore, systemAgentUUID } from "pilotswarm-sdk";
|
|
16
|
+
import { PilotSwarmClient, PilotSwarmWorker, PilotSwarmManagementClient, SessionBlobStore, FilesystemArtifactStore, systemAgentUUID, loadAgentFiles } from "pilotswarm-sdk";
|
|
17
17
|
import { createRequire } from "node:module";
|
|
18
18
|
import { marked } from "marked";
|
|
19
19
|
import { markedTerminal } from "marked-terminal";
|
|
@@ -340,15 +340,19 @@ const sessionArtifacts = new Map();
|
|
|
340
340
|
const _registeredArtifacts = new Set();
|
|
341
341
|
const MAX_ARTIFACT_REGISTRY = 500;
|
|
342
342
|
|
|
343
|
-
/** TUI-level
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
343
|
+
/** TUI-level artifact store for on-demand downloads. Created lazily.
|
|
344
|
+
* Uses Azure Blob when configured, otherwise falls back to local filesystem. */
|
|
345
|
+
let _tuiArtifactStore = null;
|
|
346
|
+
function getTuiArtifactStore() {
|
|
347
|
+
if (_tuiArtifactStore) return _tuiArtifactStore;
|
|
347
348
|
const connStr = process.env.AZURE_STORAGE_CONNECTION_STRING;
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
349
|
+
if (connStr) {
|
|
350
|
+
const container = process.env.AZURE_STORAGE_CONTAINER || "copilot-sessions";
|
|
351
|
+
_tuiArtifactStore = new SessionBlobStore(connStr, container);
|
|
352
|
+
} else {
|
|
353
|
+
_tuiArtifactStore = new FilesystemArtifactStore();
|
|
354
|
+
}
|
|
355
|
+
return _tuiArtifactStore;
|
|
352
356
|
}
|
|
353
357
|
|
|
354
358
|
/**
|
|
@@ -381,17 +385,13 @@ function detectArtifactLinks(text, orchId) {
|
|
|
381
385
|
* Returns the local path on success, null on failure.
|
|
382
386
|
*/
|
|
383
387
|
async function downloadArtifact(sessionId, filename) {
|
|
384
|
-
const
|
|
385
|
-
if (!bs) {
|
|
386
|
-
appendLog("{red-fg}📥 No blob storage configured — cannot download artifacts.{/red-fg}");
|
|
387
|
-
return null;
|
|
388
|
-
}
|
|
388
|
+
const store = getTuiArtifactStore();
|
|
389
389
|
const sessionDir = path.join(EXPORTS_DIR, sessionId.slice(0, 8));
|
|
390
390
|
fs.mkdirSync(sessionDir, { recursive: true });
|
|
391
391
|
const localPath = path.join(sessionDir, filename);
|
|
392
392
|
|
|
393
393
|
try {
|
|
394
|
-
const content = await
|
|
394
|
+
const content = await store.downloadArtifact(sessionId, filename);
|
|
395
395
|
fs.writeFileSync(localPath, content, "utf-8");
|
|
396
396
|
appendLog(`{green-fg}📥 Downloaded: ~/${path.relative(os.homedir(), localPath)} (${(content.length / 1024).toFixed(1)}KB){/green-fg}`);
|
|
397
397
|
return localPath;
|
|
@@ -3276,10 +3276,30 @@ if (!modelProviders) {
|
|
|
3276
3276
|
// Will be populated from mgmt.getModelsByProvider() after mgmt.start()
|
|
3277
3277
|
}
|
|
3278
3278
|
|
|
3279
|
-
// Capture session policy + agent list from the first worker
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3279
|
+
// Capture session policy + agent list from the first worker.
|
|
3280
|
+
// In remote mode (no local workers), load directly from the plugin directory
|
|
3281
|
+
// so the TUI enforces the same session creation restrictions as the backend.
|
|
3282
|
+
let _workerSessionPolicy = workers[0]?.sessionPolicy || null;
|
|
3283
|
+
let _workerAllowedAgentNames = workers[0]?.allowedAgentNames || [];
|
|
3284
|
+
let _workerLoadedAgents = workers[0]?.loadedAgents || [];
|
|
3285
|
+
|
|
3286
|
+
if (workers.length === 0 && process.env.PLUGIN_DIRS) {
|
|
3287
|
+
const pluginDirsArr = process.env.PLUGIN_DIRS.split(",").map(d => d.trim()).filter(Boolean);
|
|
3288
|
+
for (const dir of pluginDirsArr) {
|
|
3289
|
+
const policyFile = path.join(dir, "session-policy.json");
|
|
3290
|
+
if (fs.existsSync(policyFile)) {
|
|
3291
|
+
try { _workerSessionPolicy = JSON.parse(fs.readFileSync(policyFile, "utf-8")); } catch {}
|
|
3292
|
+
}
|
|
3293
|
+
const agentsDir = path.join(dir, "agents");
|
|
3294
|
+
if (fs.existsSync(agentsDir)) {
|
|
3295
|
+
try {
|
|
3296
|
+
const agents = loadAgentFiles(agentsDir).filter(a => !a.system && a.name !== "default");
|
|
3297
|
+
_workerLoadedAgents = agents;
|
|
3298
|
+
_workerAllowedAgentNames = agents.map(a => a.name).filter(Boolean);
|
|
3299
|
+
} catch {}
|
|
3300
|
+
}
|
|
3301
|
+
}
|
|
3302
|
+
}
|
|
3283
3303
|
if (_workerSessionPolicy) {
|
|
3284
3304
|
appendLog(`Session policy: mode=${_workerSessionPolicy.creation?.mode || "open"}, allowGeneric=${_workerSessionPolicy.creation?.allowGeneric ?? true}`);
|
|
3285
3305
|
}
|