@pi-unipi/unipi 2.4.0 → 2.4.2
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/CHANGELOG.md +43 -0
- package/package.json +26 -22
- package/packages/ask-user/package.json +2 -2
- package/packages/autocomplete/package.json +4 -2
- package/packages/btw/package.json +2 -2
- package/packages/cocoindex/package.json +2 -2
- package/packages/cocoindex/tools.ts +0 -8
- package/packages/compactor/README.md +18 -22
- package/packages/compactor/package.json +3 -3
- package/packages/compactor/src/compaction/auto-trigger.ts +0 -0
- package/packages/compactor/src/compaction/build-sections.ts +2 -2
- package/packages/compactor/src/compaction/format.ts +1 -1
- package/packages/compactor/src/config/presets.ts +19 -30
- package/packages/compactor/src/config/schema.ts +0 -0
- package/packages/compactor/src/index.ts +39 -56
- package/packages/compactor/src/session/resume-inject.ts +27 -0
- package/packages/compactor/src/tools/ctx-batch-execute.ts +4 -2
- package/packages/compactor/src/tools/ctx-execute-file.ts +4 -2
- package/packages/compactor/src/tools/ctx-execute.ts +4 -2
- package/packages/compactor/src/tools/register.ts +22 -4
- package/packages/compactor/src/tui/settings-overlay.ts +9 -22
- package/packages/compactor/src/types.ts +24 -2
- package/packages/core/events.ts +13 -13
- package/packages/core/package.json +3 -2
- package/packages/footer/README.md +2 -2
- package/packages/footer/package.json +3 -3
- package/packages/footer/src/events.ts +0 -10
- package/packages/footer/src/segments/core.ts +0 -9
- package/packages/image/package.json +2 -2
- package/packages/info-screen/core-groups.ts +0 -14
- package/packages/info-screen/package.json +2 -2
- package/packages/input-shortcuts/package.json +2 -2
- package/packages/kanboard/commands.ts +0 -1
- package/packages/kanboard/package.json +2 -2
- package/packages/mcp/package.json +2 -2
- package/packages/memory/package.json +3 -3
- package/packages/memory/storage.ts +0 -18
- package/packages/memory/tools.ts +0 -1
- package/packages/milestone/hooks.ts +9 -15
- package/packages/milestone/package.json +2 -2
- package/packages/notify/README.md +2 -0
- package/packages/notify/events.ts +23 -13
- package/packages/notify/package.json +2 -2
- package/packages/notify/tools.ts +17 -8
- package/packages/notify/types.ts +5 -1
- package/packages/ralph/index.ts +10 -5
- package/packages/ralph/package.json +3 -3
- package/packages/ralph/ralph-loop.ts +10 -0
- package/packages/subagents/README.md +3 -1
- package/packages/subagents/package.json +10 -6
- package/packages/subagents/src/agent-manager.ts +46 -11
- package/packages/subagents/src/core-compat.ts +38 -0
- package/packages/subagents/src/global.d.ts +7 -0
- package/packages/subagents/src/index.ts +6 -3
- package/packages/subagents/src/widget.ts +0 -7
- package/packages/unipi/bundled.js +371 -438
- package/packages/updater/package.json +4 -3
- package/packages/utility/README.md +1 -1
- package/packages/utility/package.json +7 -4
- package/packages/utility/src/commands.ts +2 -10
- package/packages/utility/src/diff/theme.ts +0 -3
- package/packages/utility/src/tui/name-badge.ts +0 -9
- package/packages/web-api/package.json +2 -2
- package/packages/web-api/src/engine/extract.ts +0 -26
- package/packages/web-api/src/tools.ts +0 -13
- package/packages/workflow/commands.ts +13 -1
- package/packages/workflow/index.ts +12 -1
- package/packages/workflow/lifecycle.ts +43 -0
- package/packages/workflow/package.json +3 -2
- package/packages/autocomplete/index.ts +0 -7
- package/packages/autocomplete/src/__tests__/command-registry.audit.test.ts +0 -120
- package/packages/autocomplete/src/__tests__/provider.sorting.test.ts +0 -423
- package/packages/compactor/src/compaction/recall-scope.ts +0 -32
- package/packages/compactor/src/compaction/sections.ts +0 -15
- package/packages/compactor/src/display/bash-display.ts +0 -28
- package/packages/compactor/src/display/diff-presentation.ts +0 -25
- package/packages/compactor/src/display/pending-diff-preview.ts +0 -51
- package/packages/compactor/src/display/user-message-box.ts +0 -16
- package/packages/compactor/src/session/analytics.ts +0 -205
- package/packages/image/index.ts +0 -1
- package/packages/input-shortcuts/index.ts +0 -5
- package/packages/input-shortcuts/src/status.ts +0 -35
- package/packages/kanboard/tui/kanboard-overlay.ts +0 -300
- package/packages/mcp/index.ts +0 -1
- package/packages/memory/search.ts +0 -134
- package/packages/milestone/coexist.ts +0 -114
- package/packages/notify/src/__tests__/ask-user-prompt-message.test.ts +0 -159
- package/packages/notify/src/__tests__/event-bus.test.ts +0 -119
- package/packages/notify/src/__tests__/permission-prompt-message.test.ts +0 -172
- package/packages/subagents/src/__tests__/badge-generation.test.ts +0 -315
- package/packages/subagents/src/__tests__/config.test.ts +0 -240
- package/packages/subagents/src/__tests__/esc-propagation.test.ts +0 -162
- package/packages/subagents/src/__tests__/file-lock.test.ts +0 -244
- package/packages/subagents/src/__tests__/shutdown-stale-ctx.test.ts +0 -185
- package/packages/subagents/src/__tests__/workflow-integration.test.ts +0 -334
- package/packages/subagents/src/prompts.ts +0 -39
- package/packages/utility/index.ts +0 -1
- package/packages/web-api/src/tui/progress.ts +0 -168
- package/packages/web-api/src/tui/result.ts +0 -173
|
@@ -327,7 +327,7 @@ var init_events = __esm({
|
|
|
327
327
|
UNIPI_EVENTS = {
|
|
328
328
|
/** Module loaded and ready */
|
|
329
329
|
MODULE_READY: "unipi:module:ready",
|
|
330
|
-
/**
|
|
330
|
+
/** @deprecated No built-in emitter; retained for external compatibility. */
|
|
331
331
|
MODULE_GONE: "unipi:module:gone",
|
|
332
332
|
/** Workflow command started */
|
|
333
333
|
WORKFLOW_START: "unipi:workflow:start",
|
|
@@ -339,9 +339,9 @@ var init_events = __esm({
|
|
|
339
339
|
RALPH_LOOP_END: "unipi:ralph:loop:end",
|
|
340
340
|
/** Ralph loop iteration completed */
|
|
341
341
|
RALPH_ITERATION_DONE: "unipi:ralph:iteration:done",
|
|
342
|
-
/**
|
|
342
|
+
/** @deprecated No built-in responders; use the info registry and /unipi:info. */
|
|
343
343
|
MODULE_STATUS_REQUEST: "unipi:module:status:request",
|
|
344
|
-
/**
|
|
344
|
+
/** @deprecated No built-in aggregator; use the info registry and /unipi:info. */
|
|
345
345
|
MODULE_STATUS_RESPONSE: "unipi:module:status:response",
|
|
346
346
|
/** Info screen group registered */
|
|
347
347
|
INFO_GROUP_REGISTERED: "unipi:info:group:registered",
|
|
@@ -351,7 +351,7 @@ var init_events = __esm({
|
|
|
351
351
|
MEMORY_STORED: "unipi:memory:stored",
|
|
352
352
|
/** Memory deleted */
|
|
353
353
|
MEMORY_DELETED: "unipi:memory:deleted",
|
|
354
|
-
/**
|
|
354
|
+
/** @deprecated No built-in emitter; retained for external compatibility. */
|
|
355
355
|
MEMORY_SEARCHED: "unipi:memory:searched",
|
|
356
356
|
/** Memory consolidation completed */
|
|
357
357
|
MEMORY_CONSOLIDATED: "unipi:memory:consolidated",
|
|
@@ -369,9 +369,9 @@ var init_events = __esm({
|
|
|
369
369
|
MCP_CATALOG_SYNCED: "unipi:mcp:catalog:synced",
|
|
370
370
|
/** Compactor: compaction completed */
|
|
371
371
|
COMPACTOR_COMPACTED: "unipi:compactor:compacted",
|
|
372
|
-
/**
|
|
372
|
+
/** @deprecated Footer reads live Pi session data; retained for compatibility. */
|
|
373
373
|
COMPACTOR_STATS_UPDATED: "unipi:compactor:stats:updated",
|
|
374
|
-
/**
|
|
374
|
+
/** @deprecated No built-in emitter; retained for external compatibility. */
|
|
375
375
|
UTILITY_CLEANUP_START: "unipi:utility:cleanup:start",
|
|
376
376
|
/** Utility module cleanup completed */
|
|
377
377
|
UTILITY_CLEANUP_DONE: "unipi:utility:cleanup:done",
|
|
@@ -379,9 +379,9 @@ var init_events = __esm({
|
|
|
379
379
|
UTILITY_DIAGNOSTICS_START: "unipi:utility:diagnostics:start",
|
|
380
380
|
/** Utility diagnostics completed */
|
|
381
381
|
UTILITY_DIAGNOSTICS_DONE: "unipi:utility:diagnostics:done",
|
|
382
|
-
/**
|
|
382
|
+
/** @deprecated No built-in emitter; retained for external compatibility. */
|
|
383
383
|
UTILITY_CACHE_INVALIDATED: "unipi:utility:cache:invalidated",
|
|
384
|
-
/**
|
|
384
|
+
/** @deprecated No built-in emitter; retained for external compatibility. */
|
|
385
385
|
UTILITY_LIFECYCLE_STATE: "unipi:utility:lifecycle:state",
|
|
386
386
|
/** Notification sent */
|
|
387
387
|
NOTIFICATION_SENT: "unipi:notify:sent",
|
|
@@ -397,11 +397,11 @@ var init_events = __esm({
|
|
|
397
397
|
UPDATE_APPLIED: "unipi:update:applied",
|
|
398
398
|
/** Update error */
|
|
399
399
|
UPDATE_ERROR: "unipi:update:error",
|
|
400
|
-
/**
|
|
400
|
+
/** @deprecated Reserved external contract; no built-in emitter. */
|
|
401
401
|
COCOINDEX_UPDATE_STARTED: "unipi:cocoindex:update:started",
|
|
402
|
-
/**
|
|
402
|
+
/** @deprecated Reserved external contract; no built-in emitter. */
|
|
403
403
|
COCOINDEX_UPDATE_COMPLETED: "unipi:cocoindex:update:completed",
|
|
404
|
-
/**
|
|
404
|
+
/** @deprecated Reserved external contract; no built-in emitter. */
|
|
405
405
|
COCOINDEX_SEARCH_PERFORMED: "unipi:cocoindex:search:performed"
|
|
406
406
|
};
|
|
407
407
|
}
|
|
@@ -1457,21 +1457,6 @@ var init_storage = __esm({
|
|
|
1457
1457
|
this.db = null;
|
|
1458
1458
|
}
|
|
1459
1459
|
}
|
|
1460
|
-
/**
|
|
1461
|
-
* Remove corrupted database files (db, wal, shm).
|
|
1462
|
-
*/
|
|
1463
|
-
removeCorruptedDb() {
|
|
1464
|
-
const dbPath = path5.join(this.scopeDir, MEMORY_DB_NAME);
|
|
1465
|
-
const files = [dbPath, `${dbPath}-wal`, `${dbPath}-shm`];
|
|
1466
|
-
for (const file of files) {
|
|
1467
|
-
try {
|
|
1468
|
-
if (fs5.existsSync(file)) {
|
|
1469
|
-
fs5.unlinkSync(file);
|
|
1470
|
-
}
|
|
1471
|
-
} catch {
|
|
1472
|
-
}
|
|
1473
|
-
}
|
|
1474
|
-
}
|
|
1475
1460
|
/**
|
|
1476
1461
|
* Check if database is healthy.
|
|
1477
1462
|
*/
|
|
@@ -5466,53 +5451,6 @@ var init_snapshot = __esm({
|
|
|
5466
5451
|
}
|
|
5467
5452
|
});
|
|
5468
5453
|
|
|
5469
|
-
// packages/compactor/src/session/auto-inject.ts
|
|
5470
|
-
var auto_inject_exports = {};
|
|
5471
|
-
__export(auto_inject_exports, {
|
|
5472
|
-
buildAutoInjection: () => buildAutoInjection
|
|
5473
|
-
});
|
|
5474
|
-
function estimateTokens(text) {
|
|
5475
|
-
return Math.ceil(text.length / 4);
|
|
5476
|
-
}
|
|
5477
|
-
function buildAutoInjection(events) {
|
|
5478
|
-
const parts = [];
|
|
5479
|
-
let tokenBudget = MAX_TOKENS2;
|
|
5480
|
-
const roleEvents = events.filter((e) => e.category === "rule");
|
|
5481
|
-
if (roleEvents.length > 0) {
|
|
5482
|
-
const directive = roleEvents[roleEvents.length - 1].data;
|
|
5483
|
-
const directiveText = `[Role Directive]
|
|
5484
|
-
${directive}`;
|
|
5485
|
-
const tokens = estimateTokens(directiveText);
|
|
5486
|
-
if (tokens <= tokenBudget) {
|
|
5487
|
-
parts.push(directiveText);
|
|
5488
|
-
tokenBudget -= tokens;
|
|
5489
|
-
}
|
|
5490
|
-
}
|
|
5491
|
-
if (tokenBudget > 80) {
|
|
5492
|
-
const intentEvents = events.filter((e) => e.category === "intent");
|
|
5493
|
-
if (intentEvents.length > 0) {
|
|
5494
|
-
const mode = intentEvents[intentEvents.length - 1].data;
|
|
5495
|
-
const modeText = `[Session Mode]
|
|
5496
|
-
${mode}`;
|
|
5497
|
-
const tokens = estimateTokens(modeText);
|
|
5498
|
-
if (tokens <= tokenBudget) {
|
|
5499
|
-
parts.push(modeText);
|
|
5500
|
-
tokenBudget -= tokens;
|
|
5501
|
-
}
|
|
5502
|
-
}
|
|
5503
|
-
}
|
|
5504
|
-
if (parts.length === 0) return null;
|
|
5505
|
-
const text = parts.join("\n\n");
|
|
5506
|
-
return { text, tokens: estimateTokens(text) };
|
|
5507
|
-
}
|
|
5508
|
-
var MAX_TOKENS2;
|
|
5509
|
-
var init_auto_inject = __esm({
|
|
5510
|
-
"packages/compactor/src/session/auto-inject.ts"() {
|
|
5511
|
-
"use strict";
|
|
5512
|
-
MAX_TOKENS2 = 150;
|
|
5513
|
-
}
|
|
5514
|
-
});
|
|
5515
|
-
|
|
5516
5454
|
// packages/compactor/src/config/presets.ts
|
|
5517
5455
|
import { createHash as createHash3 } from "node:crypto";
|
|
5518
5456
|
function presetHash(config) {
|
|
@@ -5546,7 +5484,7 @@ function parsePreset(raw) {
|
|
|
5546
5484
|
}
|
|
5547
5485
|
return void 0;
|
|
5548
5486
|
}
|
|
5549
|
-
var pipeline,
|
|
5487
|
+
var pipeline, pipelineWithAutoInjection, preset, PRESET_CONFIGS, presetHashes, OLD_TO_NEW;
|
|
5550
5488
|
var init_presets = __esm({
|
|
5551
5489
|
"packages/compactor/src/config/presets.ts"() {
|
|
5552
5490
|
"use strict";
|
|
@@ -5556,13 +5494,8 @@ var init_presets = __esm({
|
|
|
5556
5494
|
...overrides,
|
|
5557
5495
|
customNoisePatterns: [...overrides.customNoisePatterns ?? DEFAULT_COMPACTOR_CONFIG.pipeline.customNoisePatterns]
|
|
5558
5496
|
});
|
|
5559
|
-
|
|
5560
|
-
|
|
5561
|
-
autoInjection: true,
|
|
5562
|
-
proximityReranking: true,
|
|
5563
|
-
timelineSort: true,
|
|
5564
|
-
progressiveThrottling: true,
|
|
5565
|
-
mmapPragma: true
|
|
5497
|
+
pipelineWithAutoInjection = () => pipeline({
|
|
5498
|
+
autoInjection: true
|
|
5566
5499
|
});
|
|
5567
5500
|
preset = (overrides) => ({
|
|
5568
5501
|
...structuredClone(DEFAULT_COMPACTOR_CONFIG),
|
|
@@ -5574,23 +5507,23 @@ var init_presets = __esm({
|
|
|
5574
5507
|
userPreferences: { ...DEFAULT_COMPACTOR_CONFIG.userPreferences, ...overrides.userPreferences ?? {} },
|
|
5575
5508
|
briefTranscript: { ...DEFAULT_COMPACTOR_CONFIG.briefTranscript, ...overrides.briefTranscript ?? {} },
|
|
5576
5509
|
sessionContinuity: { ...DEFAULT_COMPACTOR_CONFIG.sessionContinuity, ...overrides.sessionContinuity ?? {} },
|
|
5577
|
-
|
|
5510
|
+
// Legacy compatibility data only; presets never advertise or alter it.
|
|
5511
|
+
fts5Index: { ...DEFAULT_COMPACTOR_CONFIG.fts5Index },
|
|
5578
5512
|
sandboxExecution: { ...DEFAULT_COMPACTOR_CONFIG.sandboxExecution, ...overrides.sandboxExecution ?? {} },
|
|
5579
|
-
|
|
5513
|
+
// Legacy compatibility data only; presets never advertise or alter it.
|
|
5514
|
+
toolDisplay: { ...DEFAULT_COMPACTOR_CONFIG.toolDisplay },
|
|
5580
5515
|
pipeline: pipeline(overrides.pipeline),
|
|
5581
5516
|
autoCompaction: { ...DEFAULT_COMPACTOR_CONFIG.autoCompaction, ...overrides.autoCompaction ?? {} }
|
|
5582
5517
|
});
|
|
5583
5518
|
PRESET_CONFIGS = {
|
|
5584
5519
|
// New preset names
|
|
5585
5520
|
precise: preset({
|
|
5586
|
-
pipeline: pipeline(
|
|
5587
|
-
sandboxExecution: { ...DEFAULT_COMPACTOR_CONFIG.sandboxExecution, mode: "
|
|
5588
|
-
toolDisplay: { ...DEFAULT_COMPACTOR_CONFIG.toolDisplay, mode: "opencode" }
|
|
5521
|
+
pipeline: pipeline(),
|
|
5522
|
+
sandboxExecution: { ...DEFAULT_COMPACTOR_CONFIG.sandboxExecution, mode: "all" }
|
|
5589
5523
|
}),
|
|
5590
5524
|
thorough: preset({
|
|
5591
|
-
pipeline:
|
|
5592
|
-
briefTranscript: { ...DEFAULT_COMPACTOR_CONFIG.briefTranscript, mode: "full" }
|
|
5593
|
-
toolDisplay: { ...DEFAULT_COMPACTOR_CONFIG.toolDisplay, mode: "verbose" }
|
|
5525
|
+
pipeline: pipelineWithAutoInjection(),
|
|
5526
|
+
briefTranscript: { ...DEFAULT_COMPACTOR_CONFIG.briefTranscript, mode: "full" }
|
|
5594
5527
|
}),
|
|
5595
5528
|
lean: preset({
|
|
5596
5529
|
pipeline: pipeline(),
|
|
@@ -5601,26 +5534,20 @@ var init_presets = __esm({
|
|
|
5601
5534
|
userPreferences: { ...DEFAULT_COMPACTOR_CONFIG.userPreferences, enabled: false, mode: "off" },
|
|
5602
5535
|
briefTranscript: { ...DEFAULT_COMPACTOR_CONFIG.briefTranscript, enabled: true, mode: "minimal" },
|
|
5603
5536
|
sessionContinuity: { ...DEFAULT_COMPACTOR_CONFIG.sessionContinuity, enabled: false, mode: "off" },
|
|
5604
|
-
|
|
5605
|
-
sandboxExecution: { ...DEFAULT_COMPACTOR_CONFIG.sandboxExecution, enabled: false, mode: "off" },
|
|
5606
|
-
toolDisplay: { ...DEFAULT_COMPACTOR_CONFIG.toolDisplay, enabled: true, mode: "opencode" }
|
|
5537
|
+
sandboxExecution: { ...DEFAULT_COMPACTOR_CONFIG.sandboxExecution, enabled: false, mode: "off" }
|
|
5607
5538
|
}),
|
|
5608
5539
|
balanced: preset({
|
|
5609
|
-
pipeline:
|
|
5610
|
-
briefTranscript: { ...DEFAULT_COMPACTOR_CONFIG.briefTranscript, mode: "compact" }
|
|
5611
|
-
toolDisplay: { ...DEFAULT_COMPACTOR_CONFIG.toolDisplay, mode: "balanced" },
|
|
5612
|
-
fts5Index: { ...DEFAULT_COMPACTOR_CONFIG.fts5Index, mode: "auto" }
|
|
5540
|
+
pipeline: pipelineWithAutoInjection(),
|
|
5541
|
+
briefTranscript: { ...DEFAULT_COMPACTOR_CONFIG.briefTranscript, mode: "compact" }
|
|
5613
5542
|
}),
|
|
5614
5543
|
// Backward-compat aliases — map old names to new
|
|
5615
5544
|
opencode: preset({
|
|
5616
|
-
pipeline: pipeline(
|
|
5617
|
-
sandboxExecution: { ...DEFAULT_COMPACTOR_CONFIG.sandboxExecution, mode: "
|
|
5618
|
-
toolDisplay: { ...DEFAULT_COMPACTOR_CONFIG.toolDisplay, mode: "opencode" }
|
|
5545
|
+
pipeline: pipeline(),
|
|
5546
|
+
sandboxExecution: { ...DEFAULT_COMPACTOR_CONFIG.sandboxExecution, mode: "all" }
|
|
5619
5547
|
}),
|
|
5620
5548
|
verbose: preset({
|
|
5621
|
-
pipeline:
|
|
5622
|
-
briefTranscript: { ...DEFAULT_COMPACTOR_CONFIG.briefTranscript, mode: "full" }
|
|
5623
|
-
toolDisplay: { ...DEFAULT_COMPACTOR_CONFIG.toolDisplay, mode: "verbose" }
|
|
5549
|
+
pipeline: pipelineWithAutoInjection(),
|
|
5550
|
+
briefTranscript: { ...DEFAULT_COMPACTOR_CONFIG.briefTranscript, mode: "full" }
|
|
5624
5551
|
}),
|
|
5625
5552
|
minimal: preset({
|
|
5626
5553
|
pipeline: pipeline(),
|
|
@@ -5631,9 +5558,7 @@ var init_presets = __esm({
|
|
|
5631
5558
|
userPreferences: { ...DEFAULT_COMPACTOR_CONFIG.userPreferences, enabled: false, mode: "off" },
|
|
5632
5559
|
briefTranscript: { ...DEFAULT_COMPACTOR_CONFIG.briefTranscript, enabled: true, mode: "minimal" },
|
|
5633
5560
|
sessionContinuity: { ...DEFAULT_COMPACTOR_CONFIG.sessionContinuity, enabled: false, mode: "off" },
|
|
5634
|
-
|
|
5635
|
-
sandboxExecution: { ...DEFAULT_COMPACTOR_CONFIG.sandboxExecution, enabled: false, mode: "off" },
|
|
5636
|
-
toolDisplay: { ...DEFAULT_COMPACTOR_CONFIG.toolDisplay, enabled: true, mode: "opencode" }
|
|
5561
|
+
sandboxExecution: { ...DEFAULT_COMPACTOR_CONFIG.sandboxExecution, enabled: false, mode: "off" }
|
|
5637
5562
|
}),
|
|
5638
5563
|
custom: structuredClone(DEFAULT_COMPACTOR_CONFIG)
|
|
5639
5564
|
};
|
|
@@ -5791,7 +5716,7 @@ var init_settings_overlay = __esm({
|
|
|
5791
5716
|
key: "sessionContinuity",
|
|
5792
5717
|
label: "Session Continuity",
|
|
5793
5718
|
description: "XML resume snapshot for compaction survival",
|
|
5794
|
-
modes: ["full", "
|
|
5719
|
+
modes: ["full", "off"],
|
|
5795
5720
|
getEnabled: (c) => c.sessionContinuity.enabled,
|
|
5796
5721
|
setEnabled: (c, v) => c.sessionContinuity.enabled = v,
|
|
5797
5722
|
getMode: (c) => c.sessionContinuity.mode,
|
|
@@ -5801,30 +5726,17 @@ var init_settings_overlay = __esm({
|
|
|
5801
5726
|
key: "sandboxExecution",
|
|
5802
5727
|
label: "Sandbox Execution",
|
|
5803
5728
|
description: "Polyglot code execution",
|
|
5804
|
-
modes: ["all", "
|
|
5729
|
+
modes: ["all", "off"],
|
|
5805
5730
|
getEnabled: (c) => c.sandboxExecution.enabled,
|
|
5806
5731
|
setEnabled: (c, v) => c.sandboxExecution.enabled = v,
|
|
5807
5732
|
getMode: (c) => c.sandboxExecution.mode,
|
|
5808
5733
|
setMode: (c, v) => c.sandboxExecution.mode = v
|
|
5809
|
-
},
|
|
5810
|
-
{
|
|
5811
|
-
key: "toolDisplay",
|
|
5812
|
-
label: "Tool Display",
|
|
5813
|
-
description: "Override tool output rendering",
|
|
5814
|
-
modes: ["opencode", "balanced", "verbose", "custom"],
|
|
5815
|
-
getEnabled: (c) => c.toolDisplay.enabled,
|
|
5816
|
-
setEnabled: (c, v) => c.toolDisplay.enabled = v,
|
|
5817
|
-
getMode: (c) => c.toolDisplay.mode,
|
|
5818
|
-
setMode: (c, v) => c.toolDisplay.mode = v
|
|
5819
5734
|
}
|
|
5820
5735
|
];
|
|
5821
5736
|
PIPELINE_ITEMS = [
|
|
5822
|
-
|
|
5823
|
-
|
|
5824
|
-
{ key: "
|
|
5825
|
-
{ key: "proximityReranking", label: "Proximity Reranking", description: "Rerank search results by proximity", group: "On Search", getValue: (c) => c.pipeline.proximityReranking, setValue: (c, v) => c.pipeline.proximityReranking = v },
|
|
5826
|
-
{ key: "timelineSort", label: "Timeline Sort", description: "Sort session events chronologically", group: "On Search", getValue: (c) => c.pipeline.timelineSort, setValue: (c, v) => c.pipeline.timelineSort = v },
|
|
5827
|
-
{ key: "progressiveThrottling", label: "Progressive Throttling", description: "Slow down processing for large projects", group: "On Compaction", getValue: (c) => c.pipeline.progressiveThrottling, setValue: (c, v) => c.pipeline.progressiveThrottling = v }
|
|
5737
|
+
// Only expose implemented behavior. Reserved compatibility fields remain in
|
|
5738
|
+
// the persisted schema so existing config files continue to load.
|
|
5739
|
+
{ key: "autoInjection", label: "Auto Injection", description: "Inject behavioral state after compaction", group: "On Compaction", getValue: (c) => c.pipeline.autoInjection, setValue: (c, v) => c.pipeline.autoInjection = v }
|
|
5828
5740
|
];
|
|
5829
5741
|
PRESETS2 = ["precise", "balanced", "thorough", "lean"];
|
|
5830
5742
|
THRESHOLD_VALUES = ["60%", "70%", "75%", "80%", "85%", "90%", "95%"];
|
|
@@ -5832,20 +5744,20 @@ var init_settings_overlay = __esm({
|
|
|
5832
5744
|
REPEAT_GROWTH_VALUES = ["0", "1k", "4k", "8k", "16k", "32k"];
|
|
5833
5745
|
PRESET_DESCRIPTIONS = {
|
|
5834
5746
|
precise: {
|
|
5835
|
-
summary: "Code-heavy, minimal waste \u2014 compaction: full, sandbox:
|
|
5836
|
-
detail: "Max token savings. Compaction: full
|
|
5747
|
+
summary: "Code-heavy, minimal waste \u2014 compaction: full, sandbox: all",
|
|
5748
|
+
detail: "Max token savings. Compaction: full.\nSandbox: all. Auto injection: off."
|
|
5837
5749
|
},
|
|
5838
5750
|
balanced: {
|
|
5839
5751
|
summary: "Daily use (default) \u2014 all strategies moderate",
|
|
5840
|
-
detail: "Moderate all strategies
|
|
5752
|
+
detail: "Moderate all strategies.\nSandbox: all. Auto injection: on."
|
|
5841
5753
|
},
|
|
5842
5754
|
thorough: {
|
|
5843
5755
|
summary: "Debug/audit \u2014 everything on, full transcript",
|
|
5844
|
-
detail: "Everything enabled
|
|
5756
|
+
detail: "Everything enabled.\nSandbox: all. Auto injection: on."
|
|
5845
5757
|
},
|
|
5846
5758
|
lean: {
|
|
5847
5759
|
summary: "Quick fixes, short sessions \u2014 compaction only",
|
|
5848
|
-
detail: "Compaction only
|
|
5760
|
+
detail: "Compaction only.\nSandbox: off. Auto injection: off."
|
|
5849
5761
|
}
|
|
5850
5762
|
};
|
|
5851
5763
|
THEME = {
|
|
@@ -6571,137 +6483,6 @@ var init_scanner = __esm({
|
|
|
6571
6483
|
}
|
|
6572
6484
|
});
|
|
6573
6485
|
|
|
6574
|
-
// packages/compactor/src/display/render-utils.ts
|
|
6575
|
-
function splitLines(text) {
|
|
6576
|
-
return text.split(/\r?\n/);
|
|
6577
|
-
}
|
|
6578
|
-
function countNonEmptyLines(text) {
|
|
6579
|
-
return splitLines(text).filter((l) => l.trim()).length;
|
|
6580
|
-
}
|
|
6581
|
-
function previewLines(text, lines) {
|
|
6582
|
-
const all = splitLines(text);
|
|
6583
|
-
if (all.length <= lines) return text;
|
|
6584
|
-
return all.slice(0, lines).join("\n") + `
|
|
6585
|
-
...(${all.length - lines} more lines)`;
|
|
6586
|
-
}
|
|
6587
|
-
function shortenPath(path28, maxLen = 60) {
|
|
6588
|
-
if (path28.length <= maxLen) return path28;
|
|
6589
|
-
const parts = path28.split("/");
|
|
6590
|
-
if (parts.length <= 2) return "..." + path28.slice(-(maxLen - 3));
|
|
6591
|
-
return parts[0] + "/.../" + parts.slice(-2).join("/");
|
|
6592
|
-
}
|
|
6593
|
-
var init_render_utils = __esm({
|
|
6594
|
-
"packages/compactor/src/display/render-utils.ts"() {
|
|
6595
|
-
"use strict";
|
|
6596
|
-
}
|
|
6597
|
-
});
|
|
6598
|
-
|
|
6599
|
-
// packages/compactor/src/display/tool-overrides.ts
|
|
6600
|
-
var tool_overrides_exports = {};
|
|
6601
|
-
__export(tool_overrides_exports, {
|
|
6602
|
-
applyToolDisplayOverride: () => applyToolDisplayOverride,
|
|
6603
|
-
renderBashResult: () => renderBashResult,
|
|
6604
|
-
renderReadResult: () => renderReadResult,
|
|
6605
|
-
renderSearchResult: () => renderSearchResult
|
|
6606
|
-
});
|
|
6607
|
-
function renderReadResult(content, filePath, config) {
|
|
6608
|
-
switch (config.readOutputMode) {
|
|
6609
|
-
case "hidden":
|
|
6610
|
-
return `[Read: ${shortenPath(filePath)}]`;
|
|
6611
|
-
case "summary":
|
|
6612
|
-
return `[Read: ${shortenPath(filePath)} \u2014 ${countNonEmptyLines(content)} lines]`;
|
|
6613
|
-
case "preview":
|
|
6614
|
-
return previewLines(content, config.previewLines ?? 20);
|
|
6615
|
-
default:
|
|
6616
|
-
return content;
|
|
6617
|
-
}
|
|
6618
|
-
}
|
|
6619
|
-
function renderSearchResult(results, config) {
|
|
6620
|
-
switch (config.searchOutputMode) {
|
|
6621
|
-
case "hidden":
|
|
6622
|
-
return `[Search results hidden]`;
|
|
6623
|
-
case "count":
|
|
6624
|
-
return `[Search: ${countNonEmptyLines(results)} matches]`;
|
|
6625
|
-
case "preview":
|
|
6626
|
-
return previewLines(results, config.previewLines ?? 20);
|
|
6627
|
-
default:
|
|
6628
|
-
return results;
|
|
6629
|
-
}
|
|
6630
|
-
}
|
|
6631
|
-
function renderBashResult(output, command, config) {
|
|
6632
|
-
switch (config.bashOutputMode) {
|
|
6633
|
-
case "hidden":
|
|
6634
|
-
return `[Bash: ${command.slice(0, 60)}]`;
|
|
6635
|
-
case "summary":
|
|
6636
|
-
return `[Bash: ${command.slice(0, 60)} \u2014 ${countNonEmptyLines(output)} lines]`;
|
|
6637
|
-
case "preview":
|
|
6638
|
-
return previewLines(output, config.bashCollapsedLines ?? 5);
|
|
6639
|
-
default:
|
|
6640
|
-
return output;
|
|
6641
|
-
}
|
|
6642
|
-
}
|
|
6643
|
-
function applyToolDisplayOverride(toolName, event, config) {
|
|
6644
|
-
const content = event.content;
|
|
6645
|
-
if (!content || !Array.isArray(content) || content.length === 0) return void 0;
|
|
6646
|
-
const textContent = content[0]?.text ?? "";
|
|
6647
|
-
const previewLinesCount = config.previewLines ?? 20;
|
|
6648
|
-
const collapsedLines = config.bashCollapsedLines ?? 5;
|
|
6649
|
-
let overridden;
|
|
6650
|
-
switch (toolName) {
|
|
6651
|
-
case "read": {
|
|
6652
|
-
const filePath = String(event.args?.path ?? "");
|
|
6653
|
-
const mode = config.readOutputMode ?? "full";
|
|
6654
|
-
if (mode === "hidden") {
|
|
6655
|
-
overridden = `[Read: ${shortenPath(filePath)}]`;
|
|
6656
|
-
} else if (mode === "summary") {
|
|
6657
|
-
overridden = `[Read: ${shortenPath(filePath)} \u2014 ${countNonEmptyLines(textContent)} lines]`;
|
|
6658
|
-
} else if (mode === "preview") {
|
|
6659
|
-
overridden = previewLines(textContent, previewLinesCount);
|
|
6660
|
-
}
|
|
6661
|
-
break;
|
|
6662
|
-
}
|
|
6663
|
-
case "grep":
|
|
6664
|
-
case "find":
|
|
6665
|
-
case "ls": {
|
|
6666
|
-
const mode = config.searchOutputMode ?? "full";
|
|
6667
|
-
if (mode === "hidden") {
|
|
6668
|
-
overridden = `[${toolName} results hidden]`;
|
|
6669
|
-
} else if (mode === "count") {
|
|
6670
|
-
overridden = `[${toolName}: ${countNonEmptyLines(textContent)} matches]`;
|
|
6671
|
-
} else if (mode === "preview") {
|
|
6672
|
-
overridden = previewLines(textContent, previewLinesCount);
|
|
6673
|
-
}
|
|
6674
|
-
break;
|
|
6675
|
-
}
|
|
6676
|
-
case "bash": {
|
|
6677
|
-
const command = String(event.args?.command ?? "");
|
|
6678
|
-
const mode = config.bashOutputMode ?? "full";
|
|
6679
|
-
if (mode === "hidden") {
|
|
6680
|
-
overridden = `[Bash: ${command.slice(0, 60)}]`;
|
|
6681
|
-
} else if (mode === "summary") {
|
|
6682
|
-
overridden = `[Bash: ${command.slice(0, 60)} \u2014 ${countNonEmptyLines(textContent)} lines]`;
|
|
6683
|
-
} else if (mode === "preview") {
|
|
6684
|
-
overridden = previewLines(textContent, collapsedLines);
|
|
6685
|
-
}
|
|
6686
|
-
break;
|
|
6687
|
-
}
|
|
6688
|
-
default:
|
|
6689
|
-
return void 0;
|
|
6690
|
-
}
|
|
6691
|
-
if (overridden !== void 0) {
|
|
6692
|
-
return {
|
|
6693
|
-
content: [{ type: "text", text: overridden }]
|
|
6694
|
-
};
|
|
6695
|
-
}
|
|
6696
|
-
return void 0;
|
|
6697
|
-
}
|
|
6698
|
-
var init_tool_overrides = __esm({
|
|
6699
|
-
"packages/compactor/src/display/tool-overrides.ts"() {
|
|
6700
|
-
"use strict";
|
|
6701
|
-
init_render_utils();
|
|
6702
|
-
}
|
|
6703
|
-
});
|
|
6704
|
-
|
|
6705
6486
|
// packages/compactor/src/display/diff-width-safety.ts
|
|
6706
6487
|
var diff_width_safety_exports = {};
|
|
6707
6488
|
__export(diff_width_safety_exports, {
|
|
@@ -7038,6 +6819,15 @@ function registerWorkflowCommands(pi, options) {
|
|
|
7038
6819
|
return null;
|
|
7039
6820
|
},
|
|
7040
6821
|
handler: async (args, ctx) => {
|
|
6822
|
+
const workflowEvent = {
|
|
6823
|
+
command: cmd.name,
|
|
6824
|
+
fullCommand: `/${fullCommand}`,
|
|
6825
|
+
args: args?.trim() ?? ""
|
|
6826
|
+
};
|
|
6827
|
+
if (!options.startWorkflow(workflowEvent)) {
|
|
6828
|
+
if (ctx.hasUI) ctx.ui.notify("Another UniPi workflow is still active", "warning");
|
|
6829
|
+
return;
|
|
6830
|
+
}
|
|
7041
6831
|
const currentTools = options.getActiveTools();
|
|
7042
6832
|
options.saveTools(currentTools);
|
|
7043
6833
|
const sandboxTools = getToolsForCommand(cmd.name, currentTools);
|
|
@@ -7106,6 +6896,37 @@ ${taskContent}`,
|
|
|
7106
6896
|
});
|
|
7107
6897
|
}
|
|
7108
6898
|
|
|
6899
|
+
// packages/workflow/lifecycle.ts
|
|
6900
|
+
var WorkflowLifecycle = class {
|
|
6901
|
+
constructor(now2 = Date.now) {
|
|
6902
|
+
this.now = now2;
|
|
6903
|
+
}
|
|
6904
|
+
now;
|
|
6905
|
+
active = null;
|
|
6906
|
+
start(event) {
|
|
6907
|
+
if (this.active) return false;
|
|
6908
|
+
this.active = { ...event, startedAt: this.now() };
|
|
6909
|
+
return true;
|
|
6910
|
+
}
|
|
6911
|
+
complete(messages) {
|
|
6912
|
+
if (!this.active) return void 0;
|
|
6913
|
+
const workflow = this.active;
|
|
6914
|
+
this.active = null;
|
|
6915
|
+
const finalAssistant = [...messages].reverse().find((message) => message.role === "assistant");
|
|
6916
|
+
const success = finalAssistant?.stopReason !== "error" && finalAssistant?.stopReason !== "aborted";
|
|
6917
|
+
return {
|
|
6918
|
+
command: workflow.command,
|
|
6919
|
+
fullCommand: workflow.fullCommand,
|
|
6920
|
+
args: workflow.args,
|
|
6921
|
+
success,
|
|
6922
|
+
durationMs: this.now() - workflow.startedAt
|
|
6923
|
+
};
|
|
6924
|
+
}
|
|
6925
|
+
reset() {
|
|
6926
|
+
this.active = null;
|
|
6927
|
+
}
|
|
6928
|
+
};
|
|
6929
|
+
|
|
7109
6930
|
// packages/workflow/index.ts
|
|
7110
6931
|
var VERSION = getPackageVersion(dirname2(fileURLToPath(import.meta.url)));
|
|
7111
6932
|
var ralphDetected = false;
|
|
@@ -7114,6 +6935,7 @@ var sandboxActive = false;
|
|
|
7114
6935
|
var currentSandboxLevel = null;
|
|
7115
6936
|
var currentSandboxTools = null;
|
|
7116
6937
|
function workflow_default(pi) {
|
|
6938
|
+
const workflowLifecycle = new WorkflowLifecycle();
|
|
7117
6939
|
registerWorkflowCommands(pi, {
|
|
7118
6940
|
isRalphDetected: () => ralphDetected,
|
|
7119
6941
|
getActiveTools: () => pi.getActiveTools(),
|
|
@@ -7125,6 +6947,11 @@ function workflow_default(pi) {
|
|
|
7125
6947
|
},
|
|
7126
6948
|
saveTools: (tools) => {
|
|
7127
6949
|
savedTools = tools;
|
|
6950
|
+
},
|
|
6951
|
+
startWorkflow: (event) => {
|
|
6952
|
+
if (!workflowLifecycle.start(event)) return false;
|
|
6953
|
+
emitEvent(pi, UNIPI_EVENTS.WORKFLOW_START, event);
|
|
6954
|
+
return true;
|
|
7128
6955
|
}
|
|
7129
6956
|
});
|
|
7130
6957
|
pi.on("tool_call", async (event, _ctx) => {
|
|
@@ -7176,7 +7003,7 @@ If the user requires an action that requires a blocked tool, respond that you do
|
|
|
7176
7003
|
</sandbox>`
|
|
7177
7004
|
};
|
|
7178
7005
|
});
|
|
7179
|
-
pi.on("agent_end", async (
|
|
7006
|
+
pi.on("agent_end", async (event, _ctx) => {
|
|
7180
7007
|
if (sandboxActive && savedTools) {
|
|
7181
7008
|
pi.setActiveTools(savedTools);
|
|
7182
7009
|
savedTools = null;
|
|
@@ -7184,6 +7011,8 @@ If the user requires an action that requires a blocked tool, respond that you do
|
|
|
7184
7011
|
currentSandboxLevel = null;
|
|
7185
7012
|
currentSandboxTools = null;
|
|
7186
7013
|
}
|
|
7014
|
+
const completedWorkflow = workflowLifecycle.complete(event.messages);
|
|
7015
|
+
if (completedWorkflow) emitEvent(pi, UNIPI_EVENTS.WORKFLOW_END, completedWorkflow);
|
|
7187
7016
|
});
|
|
7188
7017
|
pi.on("session_start", async (_event, ctx) => {
|
|
7189
7018
|
initUnipiDirs();
|
|
@@ -7215,6 +7044,7 @@ If the user requires an action that requires a blocked tool, respond that you do
|
|
|
7215
7044
|
ralphDetected = false;
|
|
7216
7045
|
savedTools = null;
|
|
7217
7046
|
sandboxActive = false;
|
|
7047
|
+
workflowLifecycle.reset();
|
|
7218
7048
|
});
|
|
7219
7049
|
}
|
|
7220
7050
|
|
|
@@ -7480,12 +7310,20 @@ Use /unipi:ralph-resume <name> to continue`, "info");
|
|
|
7480
7310
|
);
|
|
7481
7311
|
return null;
|
|
7482
7312
|
}
|
|
7313
|
+
this.emitIterationDone(state);
|
|
7483
7314
|
const needsReflection = state.reflectEvery > 0 && (state.iteration - 1) % state.reflectEvery === 0;
|
|
7484
7315
|
if (needsReflection) state.lastReflectionAt = state.iteration;
|
|
7485
7316
|
this.saveState(state);
|
|
7486
7317
|
this.updateUI();
|
|
7487
7318
|
return { state, needsReflection };
|
|
7488
7319
|
}
|
|
7320
|
+
emitIterationDone(state) {
|
|
7321
|
+
this.emitFn(UNIPI_EVENTS.RALPH_ITERATION_DONE, {
|
|
7322
|
+
name: state.name,
|
|
7323
|
+
iteration: state.iteration - 1,
|
|
7324
|
+
nextIteration: state.iteration
|
|
7325
|
+
});
|
|
7326
|
+
}
|
|
7489
7327
|
archiveLoop(name) {
|
|
7490
7328
|
const state = this.loadState(name);
|
|
7491
7329
|
if (!state) return false;
|
|
@@ -7743,7 +7581,7 @@ function ralph_default(pi) {
|
|
|
7743
7581
|
);
|
|
7744
7582
|
}
|
|
7745
7583
|
});
|
|
7746
|
-
pi.on("before_agent_start", async (
|
|
7584
|
+
pi.on("before_agent_start", async (_event, ctx) => {
|
|
7747
7585
|
const mgr = getManager(ctx, pi);
|
|
7748
7586
|
const currentLoop = mgr.getCurrentLoop();
|
|
7749
7587
|
if (!currentLoop) return;
|
|
@@ -7762,10 +7600,13 @@ function ralph_default(pi) {
|
|
|
7762
7600
|
`;
|
|
7763
7601
|
instructions += `- Otherwise, call ralph_done tool to proceed to next iteration`;
|
|
7764
7602
|
return {
|
|
7765
|
-
|
|
7766
|
-
|
|
7603
|
+
message: {
|
|
7604
|
+
customType: "unipi-ralph-loop-reminder",
|
|
7605
|
+
content: `[RALPH LOOP - ${state.name} - Iteration ${iterStr}]
|
|
7767
7606
|
|
|
7768
|
-
${instructions}
|
|
7607
|
+
${instructions}`,
|
|
7608
|
+
display: false
|
|
7609
|
+
}
|
|
7769
7610
|
};
|
|
7770
7611
|
});
|
|
7771
7612
|
pi.on("session_shutdown", async (_event, ctx) => {
|
|
@@ -10732,7 +10573,6 @@ function info_screen_default(pi) {
|
|
|
10732
10573
|
}
|
|
10733
10574
|
|
|
10734
10575
|
// packages/subagents/src/index.ts
|
|
10735
|
-
init_core();
|
|
10736
10576
|
import { defineTool } from "@earendil-works/pi-coding-agent";
|
|
10737
10577
|
import { Text } from "@earendil-works/pi-tui";
|
|
10738
10578
|
import { Type as Type3 } from "typebox";
|
|
@@ -10740,6 +10580,29 @@ import { existsSync as existsSync13, readdirSync as readdirSync7 } from "node:fs
|
|
|
10740
10580
|
import { join as join13 } from "node:path";
|
|
10741
10581
|
import { homedir as homedir9 } from "node:os";
|
|
10742
10582
|
|
|
10583
|
+
// packages/subagents/src/core-compat.ts
|
|
10584
|
+
var MODULES2 = { SUBAGENTS: "subagents" };
|
|
10585
|
+
var UNIPI_EVENTS2 = {
|
|
10586
|
+
MODULE_READY: "unipi:module:ready",
|
|
10587
|
+
BADGE_GENERATE_REQUEST: "unipi:badge:generate:request"
|
|
10588
|
+
};
|
|
10589
|
+
function emitEvent2(pi, eventName, payload) {
|
|
10590
|
+
try {
|
|
10591
|
+
pi.events.emit(eventName, payload);
|
|
10592
|
+
return true;
|
|
10593
|
+
} catch {
|
|
10594
|
+
return false;
|
|
10595
|
+
}
|
|
10596
|
+
}
|
|
10597
|
+
async function withHerdrBlocked2(pi, label, fn) {
|
|
10598
|
+
emitEvent2(pi, "herdr:blocked", { active: true, label });
|
|
10599
|
+
try {
|
|
10600
|
+
return await fn();
|
|
10601
|
+
} finally {
|
|
10602
|
+
emitEvent2(pi, "herdr:blocked", { active: false, label });
|
|
10603
|
+
}
|
|
10604
|
+
}
|
|
10605
|
+
|
|
10743
10606
|
// packages/subagents/src/agent-manager.ts
|
|
10744
10607
|
import { randomUUID } from "node:crypto";
|
|
10745
10608
|
|
|
@@ -11121,23 +10984,43 @@ var AgentManager = class {
|
|
|
11121
10984
|
onStart;
|
|
11122
10985
|
maxConcurrent;
|
|
11123
10986
|
customAgents;
|
|
10987
|
+
typeSettings;
|
|
11124
10988
|
/** Per-file transparent locking for write agents. */
|
|
11125
10989
|
fileLock = new FileLock();
|
|
11126
10990
|
/** Queue of background agents waiting to start. */
|
|
11127
10991
|
queue = [];
|
|
11128
10992
|
/** Number of currently running background agents. */
|
|
11129
10993
|
runningBackground = 0;
|
|
11130
|
-
constructor(onComplete, maxConcurrent = DEFAULT_MAX_CONCURRENT, onStart) {
|
|
10994
|
+
constructor(onComplete, maxConcurrent = DEFAULT_MAX_CONCURRENT, onStart, typeSettings = {}, agentsCwd = process.cwd()) {
|
|
11131
10995
|
this.onComplete = onComplete;
|
|
11132
10996
|
this.onStart = onStart;
|
|
11133
10997
|
this.maxConcurrent = maxConcurrent;
|
|
11134
|
-
this.
|
|
10998
|
+
this.typeSettings = typeSettings;
|
|
10999
|
+
this.customAgents = loadCustomAgents(agentsCwd);
|
|
11135
11000
|
this.cleanupInterval = setInterval(() => this.cleanup(), 6e4);
|
|
11136
11001
|
}
|
|
11137
11002
|
/** Get resolved agent config for a type. */
|
|
11138
11003
|
getAgentConfig(type) {
|
|
11139
11004
|
return this.customAgents.get(type) ?? BUILTIN_CONFIGS[type];
|
|
11140
11005
|
}
|
|
11006
|
+
/** Public agent types known from built-ins, custom files, or JSON config. */
|
|
11007
|
+
getKnownTypes() {
|
|
11008
|
+
return [.../* @__PURE__ */ new Set([
|
|
11009
|
+
...Object.keys(BUILTIN_CONFIGS).filter((type) => type !== "name-gen"),
|
|
11010
|
+
...this.customAgents.keys(),
|
|
11011
|
+
...Object.keys(this.typeSettings)
|
|
11012
|
+
])];
|
|
11013
|
+
}
|
|
11014
|
+
/** A type is enabled only when both JSON config and agent frontmatter allow it. */
|
|
11015
|
+
isTypeEnabled(type) {
|
|
11016
|
+
const agentConfig = this.getAgentConfig(type);
|
|
11017
|
+
return this.typeSettings[type]?.enabled !== false && agentConfig?.enabled !== false;
|
|
11018
|
+
}
|
|
11019
|
+
assertTypeEnabled(type) {
|
|
11020
|
+
if (!this.isTypeEnabled(type)) {
|
|
11021
|
+
throw new Error(`Agent type "${type}" is disabled by configuration.`);
|
|
11022
|
+
}
|
|
11023
|
+
}
|
|
11141
11024
|
setMaxConcurrent(n) {
|
|
11142
11025
|
this.maxConcurrent = Math.max(1, n);
|
|
11143
11026
|
this.drainQueue();
|
|
@@ -11149,6 +11032,7 @@ var AgentManager = class {
|
|
|
11149
11032
|
* Spawn an agent. Returns ID immediately for background, waits for foreground.
|
|
11150
11033
|
*/
|
|
11151
11034
|
spawn(pi, ctx, type, prompt, options) {
|
|
11035
|
+
this.assertTypeEnabled(type);
|
|
11152
11036
|
const id = randomUUID().slice(0, 17);
|
|
11153
11037
|
const abortController = new AbortController();
|
|
11154
11038
|
const record = {
|
|
@@ -11176,9 +11060,11 @@ var AgentManager = class {
|
|
|
11176
11060
|
record.startedAt = Date.now();
|
|
11177
11061
|
if (options.isBackground) this.runningBackground++;
|
|
11178
11062
|
this.onStart?.(record);
|
|
11063
|
+
const agentConfig = this.getAgentConfig(type);
|
|
11179
11064
|
let model = options.model;
|
|
11180
|
-
|
|
11181
|
-
|
|
11065
|
+
const modelInput = options.modelInput ?? agentConfig?.model;
|
|
11066
|
+
if (!model && modelInput && options.modelRegistry) {
|
|
11067
|
+
const resolved = resolveModel(modelInput, options.modelRegistry);
|
|
11182
11068
|
if (typeof resolved === "string") {
|
|
11183
11069
|
record.status = "error";
|
|
11184
11070
|
record.error = resolved;
|
|
@@ -11191,15 +11077,14 @@ var AgentManager = class {
|
|
|
11191
11077
|
}
|
|
11192
11078
|
model = resolved;
|
|
11193
11079
|
}
|
|
11194
|
-
const agentConfig = this.getAgentConfig(type);
|
|
11195
11080
|
const promise = runAgent(ctx, type, prompt, {
|
|
11196
11081
|
pi,
|
|
11197
11082
|
model,
|
|
11198
11083
|
agentConfig,
|
|
11199
|
-
maxTurns: options.maxTurns,
|
|
11200
|
-
isolated: options.isolated,
|
|
11201
|
-
inheritContext: options.inheritContext,
|
|
11202
|
-
thinkingLevel: options.thinkingLevel,
|
|
11084
|
+
maxTurns: options.maxTurns ?? agentConfig?.maxTurns,
|
|
11085
|
+
isolated: options.isolated ?? agentConfig?.isolated,
|
|
11086
|
+
inheritContext: options.inheritContext ?? agentConfig?.inheritContext,
|
|
11087
|
+
thinkingLevel: options.thinkingLevel ?? agentConfig?.thinking,
|
|
11203
11088
|
signal: record.abortController.signal,
|
|
11204
11089
|
onToolActivity: (activity) => {
|
|
11205
11090
|
if (activity.type === "end") record.toolUses++;
|
|
@@ -12139,7 +12024,8 @@ function src_default(pi) {
|
|
|
12139
12024
|
type: record.type,
|
|
12140
12025
|
description: record.description
|
|
12141
12026
|
});
|
|
12142
|
-
}
|
|
12027
|
+
},
|
|
12028
|
+
config.types
|
|
12143
12029
|
);
|
|
12144
12030
|
function buildNotificationDetails(record, activity) {
|
|
12145
12031
|
return {
|
|
@@ -12242,14 +12128,14 @@ function src_default(pi) {
|
|
|
12242
12128
|
let sessionCtx2 = null;
|
|
12243
12129
|
pi.on("session_start", async (_event, ctx) => {
|
|
12244
12130
|
sessionCtx2 = ctx;
|
|
12245
|
-
|
|
12246
|
-
name:
|
|
12131
|
+
emitEvent2(pi, UNIPI_EVENTS2.MODULE_READY, {
|
|
12132
|
+
name: MODULES2.SUBAGENTS || "subagents",
|
|
12247
12133
|
version: "0.2.0",
|
|
12248
12134
|
commands: [],
|
|
12249
12135
|
tools: ["spawn_helper", "get_helper_result"]
|
|
12250
12136
|
});
|
|
12251
12137
|
});
|
|
12252
|
-
pi.events.on(
|
|
12138
|
+
pi.events.on(UNIPI_EVENTS2.BADGE_GENERATE_REQUEST, async (data) => {
|
|
12253
12139
|
const event = data;
|
|
12254
12140
|
if (!sessionCtx2) return;
|
|
12255
12141
|
const summary = event?.conversationSummary ?? "";
|
|
@@ -12335,13 +12221,15 @@ ${summary}` : `Generate a concise session title (MAX 5 WORDS) for this session.
|
|
|
12335
12221
|
return { state, callbacks };
|
|
12336
12222
|
}
|
|
12337
12223
|
const builtinTypes = BUILTIN_TYPES.join(", ");
|
|
12224
|
+
const enabledTypes = manager2.getKnownTypes().filter((type) => manager2.isTypeEnabled(type));
|
|
12225
|
+
const availableTypes = enabledTypes.join(", ") || "none";
|
|
12338
12226
|
pi.registerTool(
|
|
12339
12227
|
defineTool({
|
|
12340
12228
|
name: "spawn_helper",
|
|
12341
12229
|
label: "Spawn Helper",
|
|
12342
12230
|
description: `Launch a sub-agent for parallel work.
|
|
12343
12231
|
|
|
12344
|
-
Available agent types: ${
|
|
12232
|
+
Available agent types: ${availableTypes}
|
|
12345
12233
|
Custom types can be defined in:
|
|
12346
12234
|
- ~/.unipi/config/agents/<name>.md (global)
|
|
12347
12235
|
- <workspace>/.unipi/config/agents/<name>.md (project)
|
|
@@ -12354,7 +12242,7 @@ Guidelines:
|
|
|
12354
12242
|
- Agents inherit the parent model by default`,
|
|
12355
12243
|
parameters: Type3.Object({
|
|
12356
12244
|
type: Type3.String({
|
|
12357
|
-
description: `
|
|
12245
|
+
description: `Enabled agent type: ${availableTypes}`
|
|
12358
12246
|
}),
|
|
12359
12247
|
prompt: Type3.String({
|
|
12360
12248
|
description: "The task for the agent to perform."
|
|
@@ -12597,7 +12485,7 @@ Use get_result to retrieve full results.`,
|
|
|
12597
12485
|
}
|
|
12598
12486
|
if (params.view && record.session) {
|
|
12599
12487
|
const activity = agentActivity.get(record.id);
|
|
12600
|
-
await
|
|
12488
|
+
await withHerdrBlocked2(
|
|
12601
12489
|
pi,
|
|
12602
12490
|
"helper viewer",
|
|
12603
12491
|
() => ctx.ui.custom(
|
|
@@ -17584,7 +17472,6 @@ var PRESETS = {
|
|
|
17584
17472
|
}
|
|
17585
17473
|
}
|
|
17586
17474
|
};
|
|
17587
|
-
var HARDCODED_FALLBACK = PRESETS.default.colors;
|
|
17588
17475
|
function getPreset(name) {
|
|
17589
17476
|
return PRESETS[name] ?? PRESETS.default;
|
|
17590
17477
|
}
|
|
@@ -18239,17 +18126,9 @@ function registerUtilityCommands(pi) {
|
|
|
18239
18126
|
}
|
|
18240
18127
|
return;
|
|
18241
18128
|
}
|
|
18242
|
-
const requestId = `status-${Date.now()}`;
|
|
18243
|
-
emitEvent(pi, UNIPI_EVENTS.MODULE_STATUS_REQUEST, { requestId });
|
|
18244
|
-
await new Promise((resolve13) => setTimeout(resolve13, 500));
|
|
18245
18129
|
sendResponse(
|
|
18246
18130
|
pi,
|
|
18247
|
-
|
|
18248
|
-
|
|
18249
|
-
Status request broadcast to all modules.
|
|
18250
|
-
Modules that support status reporting will respond via events.
|
|
18251
|
-
|
|
18252
|
-
*Request ID: \`${requestId}\`*`
|
|
18131
|
+
"## \u{1F4CA} Module Status\n\nUse `/unipi:info` for the live module and tool dashboard.\nUse `/unipi:doctor` to run configuration and runtime diagnostics."
|
|
18253
18132
|
);
|
|
18254
18133
|
}
|
|
18255
18134
|
});
|
|
@@ -23728,7 +23607,7 @@ function getEnabledPlatforms(config, ntfyEnabled) {
|
|
|
23728
23607
|
function unregisterEventListeners() {
|
|
23729
23608
|
unregisterAll();
|
|
23730
23609
|
}
|
|
23731
|
-
async function dispatchNotification(pi, title, message, eventPlatforms, eventType, config, cwd) {
|
|
23610
|
+
async function dispatchNotification(pi, title, message, eventPlatforms, eventType, config, cwd, priority) {
|
|
23732
23611
|
const ntfyConfig = loadNtfyConfig(cwd);
|
|
23733
23612
|
const platforms = eventPlatforms.length > 0 ? eventPlatforms : getEnabledPlatforms(config, ntfyConfig.enabled).length > 0 ? getEnabledPlatforms(config, ntfyConfig.enabled) : config.defaultPlatforms;
|
|
23734
23613
|
const enabledPlatforms = platforms.filter((p) => {
|
|
@@ -23741,8 +23620,8 @@ async function dispatchNotification(pi, title, message, eventPlatforms, eventTyp
|
|
|
23741
23620
|
const results = await Promise.all(
|
|
23742
23621
|
enabledPlatforms.map(async (platform) => {
|
|
23743
23622
|
try {
|
|
23744
|
-
await sendToPlatform(platform, title, message, config, cwd);
|
|
23745
|
-
return { platform, success: true };
|
|
23623
|
+
const effectivePriority = await sendToPlatform(platform, title, message, config, cwd, priority);
|
|
23624
|
+
return { platform, success: true, ...effectivePriority === void 0 ? {} : { priority: effectivePriority } };
|
|
23746
23625
|
} catch (err) {
|
|
23747
23626
|
if (err instanceof SuppressedError2) {
|
|
23748
23627
|
return { platform, success: true, suppressed: true };
|
|
@@ -23767,14 +23646,21 @@ async function dispatchNotification(pi, title, message, eventPlatforms, eventTyp
|
|
|
23767
23646
|
});
|
|
23768
23647
|
return { results, allSuccess };
|
|
23769
23648
|
}
|
|
23770
|
-
|
|
23649
|
+
function mapNotifyPriority(platform, priority) {
|
|
23650
|
+
const mappings = {
|
|
23651
|
+
gotify: { low: 2, normal: 5, high: 8 },
|
|
23652
|
+
ntfy: { low: 2, normal: 3, high: 5 }
|
|
23653
|
+
};
|
|
23654
|
+
return mappings[platform][priority];
|
|
23655
|
+
}
|
|
23656
|
+
async function sendToPlatform(platform, title, message, config, cwd, priority) {
|
|
23771
23657
|
switch (platform) {
|
|
23772
23658
|
case "native":
|
|
23773
23659
|
await sendNativeNotification(title, message, {
|
|
23774
23660
|
windowsAppId: config.native.windowsAppId,
|
|
23775
23661
|
suppressWhenFocused: config.native.suppressWhenFocused
|
|
23776
23662
|
});
|
|
23777
|
-
|
|
23663
|
+
return void 0;
|
|
23778
23664
|
case "gotify":
|
|
23779
23665
|
if (!config.gotify.serverUrl || !config.gotify.appToken) {
|
|
23780
23666
|
throw new Error("Gotify: serverUrl and appToken are required");
|
|
@@ -23784,9 +23670,9 @@ async function sendToPlatform(platform, title, message, config, cwd) {
|
|
|
23784
23670
|
config.gotify.appToken,
|
|
23785
23671
|
title,
|
|
23786
23672
|
message,
|
|
23787
|
-
config.gotify.priority
|
|
23673
|
+
priority ? mapNotifyPriority("gotify", priority) : config.gotify.priority
|
|
23788
23674
|
);
|
|
23789
|
-
|
|
23675
|
+
return priority ? mapNotifyPriority("gotify", priority) : config.gotify.priority;
|
|
23790
23676
|
case "telegram":
|
|
23791
23677
|
if (!config.telegram.botToken || !config.telegram.chatId) {
|
|
23792
23678
|
throw new Error("Telegram: botToken and chatId are required");
|
|
@@ -23797,10 +23683,10 @@ async function sendToPlatform(platform, title, message, config, cwd) {
|
|
|
23797
23683
|
title,
|
|
23798
23684
|
message
|
|
23799
23685
|
);
|
|
23800
|
-
|
|
23686
|
+
return void 0;
|
|
23801
23687
|
case "ntfy": {
|
|
23802
23688
|
const ntfyConfig = loadNtfyConfig(cwd);
|
|
23803
|
-
if (!ntfyConfig.enabled) return;
|
|
23689
|
+
if (!ntfyConfig.enabled) return void 0;
|
|
23804
23690
|
if (!ntfyConfig.serverUrl || !ntfyConfig.topic) {
|
|
23805
23691
|
throw new Error("ntfy: serverUrl and topic are required");
|
|
23806
23692
|
}
|
|
@@ -23809,10 +23695,10 @@ async function sendToPlatform(platform, title, message, config, cwd) {
|
|
|
23809
23695
|
ntfyConfig.topic,
|
|
23810
23696
|
title,
|
|
23811
23697
|
message,
|
|
23812
|
-
ntfyConfig.priority,
|
|
23698
|
+
priority ? mapNotifyPriority("ntfy", priority) : ntfyConfig.priority,
|
|
23813
23699
|
ntfyConfig.token
|
|
23814
23700
|
);
|
|
23815
|
-
|
|
23701
|
+
return priority ? mapNotifyPriority("ntfy", priority) : ntfyConfig.priority;
|
|
23816
23702
|
}
|
|
23817
23703
|
}
|
|
23818
23704
|
}
|
|
@@ -23941,7 +23827,6 @@ var NotifyUserSchema = Type6.Object({
|
|
|
23941
23827
|
priority: Type6.Optional(
|
|
23942
23828
|
Type6.String({
|
|
23943
23829
|
enum: ["low", "normal", "high"],
|
|
23944
|
-
default: "normal",
|
|
23945
23830
|
description: "Priority level"
|
|
23946
23831
|
})
|
|
23947
23832
|
),
|
|
@@ -23962,23 +23847,31 @@ function registerNotifyTools(pi) {
|
|
|
23962
23847
|
const {
|
|
23963
23848
|
message,
|
|
23964
23849
|
title,
|
|
23965
|
-
priority
|
|
23850
|
+
priority,
|
|
23966
23851
|
platforms
|
|
23967
23852
|
} = params;
|
|
23968
23853
|
const config = loadConfig2();
|
|
23969
23854
|
const notifTitle = title || "Pi Notification";
|
|
23970
23855
|
const notifPlatforms = platforms || config.defaultPlatforms;
|
|
23971
23856
|
const cwd = process.cwd();
|
|
23972
|
-
dispatchNotification(
|
|
23857
|
+
const dispatchPromise = dispatchNotification(
|
|
23973
23858
|
pi,
|
|
23974
23859
|
notifTitle,
|
|
23975
23860
|
message,
|
|
23976
23861
|
notifPlatforms,
|
|
23977
23862
|
"agent_tool",
|
|
23978
23863
|
config,
|
|
23979
|
-
cwd
|
|
23980
|
-
|
|
23864
|
+
cwd,
|
|
23865
|
+
priority
|
|
23866
|
+
);
|
|
23867
|
+
void dispatchPromise.catch(() => {
|
|
23981
23868
|
});
|
|
23869
|
+
const priorityByPlatform = priority ? Object.fromEntries(
|
|
23870
|
+
notifPlatforms.flatMap((platform) => {
|
|
23871
|
+
if (platform === "gotify" || platform === "ntfy") return [[platform, mapNotifyPriority(platform, priority)]];
|
|
23872
|
+
return [];
|
|
23873
|
+
})
|
|
23874
|
+
) : void 0;
|
|
23982
23875
|
return {
|
|
23983
23876
|
content: [
|
|
23984
23877
|
{
|
|
@@ -23986,7 +23879,7 @@ function registerNotifyTools(pi) {
|
|
|
23986
23879
|
text: `Notification sending to ${notifPlatforms.length} platform(s): ${notifPlatforms.join(", ")}`
|
|
23987
23880
|
}
|
|
23988
23881
|
],
|
|
23989
|
-
details: { platforms: notifPlatforms }
|
|
23882
|
+
details: { platforms: notifPlatforms, priority, priorityByPlatform }
|
|
23990
23883
|
};
|
|
23991
23884
|
}
|
|
23992
23885
|
});
|
|
@@ -26385,10 +26278,7 @@ function registerSessionEndHook(pi) {
|
|
|
26385
26278
|
}
|
|
26386
26279
|
}
|
|
26387
26280
|
});
|
|
26388
|
-
|
|
26389
|
-
return void 0;
|
|
26390
|
-
});
|
|
26391
|
-
pi.on("session_shutdown", () => {
|
|
26281
|
+
const syncModifiedDocs = () => {
|
|
26392
26282
|
const cwd = process.cwd();
|
|
26393
26283
|
const milestonesPath = path13.join(cwd, MILESTONE_DIRS.MILESTONES);
|
|
26394
26284
|
if (!fs14.existsSync(milestonesPath)) return;
|
|
@@ -26406,7 +26296,9 @@ function registerSessionEndHook(pi) {
|
|
|
26406
26296
|
updateItemStatus(milestonesPath, phase, text, true);
|
|
26407
26297
|
}
|
|
26408
26298
|
}
|
|
26409
|
-
}
|
|
26299
|
+
};
|
|
26300
|
+
pi.events.on(UNIPI_EVENTS.WORKFLOW_END, syncModifiedDocs);
|
|
26301
|
+
pi.on("session_shutdown", syncModifiedDocs);
|
|
26410
26302
|
}
|
|
26411
26303
|
|
|
26412
26304
|
// packages/milestone/commands.ts
|
|
@@ -27976,8 +27868,49 @@ function extractEventsFromToolResult(result) {
|
|
|
27976
27868
|
|
|
27977
27869
|
// packages/compactor/src/session/resume-inject.ts
|
|
27978
27870
|
init_snapshot();
|
|
27979
|
-
|
|
27871
|
+
|
|
27872
|
+
// packages/compactor/src/session/auto-inject.ts
|
|
27873
|
+
var MAX_TOKENS2 = 150;
|
|
27874
|
+
function estimateTokens(text) {
|
|
27875
|
+
return Math.ceil(text.length / 4);
|
|
27876
|
+
}
|
|
27877
|
+
function buildAutoInjection(events) {
|
|
27878
|
+
const parts = [];
|
|
27879
|
+
let tokenBudget = MAX_TOKENS2;
|
|
27880
|
+
const roleEvents = events.filter((e) => e.category === "rule");
|
|
27881
|
+
if (roleEvents.length > 0) {
|
|
27882
|
+
const directive = roleEvents[roleEvents.length - 1].data;
|
|
27883
|
+
const directiveText = `[Role Directive]
|
|
27884
|
+
${directive}`;
|
|
27885
|
+
const tokens = estimateTokens(directiveText);
|
|
27886
|
+
if (tokens <= tokenBudget) {
|
|
27887
|
+
parts.push(directiveText);
|
|
27888
|
+
tokenBudget -= tokens;
|
|
27889
|
+
}
|
|
27890
|
+
}
|
|
27891
|
+
if (tokenBudget > 80) {
|
|
27892
|
+
const intentEvents = events.filter((e) => e.category === "intent");
|
|
27893
|
+
if (intentEvents.length > 0) {
|
|
27894
|
+
const mode = intentEvents[intentEvents.length - 1].data;
|
|
27895
|
+
const modeText = `[Session Mode]
|
|
27896
|
+
${mode}`;
|
|
27897
|
+
const tokens = estimateTokens(modeText);
|
|
27898
|
+
if (tokens <= tokenBudget) {
|
|
27899
|
+
parts.push(modeText);
|
|
27900
|
+
tokenBudget -= tokens;
|
|
27901
|
+
}
|
|
27902
|
+
}
|
|
27903
|
+
}
|
|
27904
|
+
if (parts.length === 0) return null;
|
|
27905
|
+
const text = parts.join("\n\n");
|
|
27906
|
+
return { text, tokens: estimateTokens(text) };
|
|
27907
|
+
}
|
|
27908
|
+
|
|
27909
|
+
// packages/compactor/src/session/resume-inject.ts
|
|
27980
27910
|
init_manager();
|
|
27911
|
+
function isSessionContinuityEnabled(config) {
|
|
27912
|
+
return config.sessionContinuity.enabled && config.sessionContinuity.mode !== "off";
|
|
27913
|
+
}
|
|
27981
27914
|
async function injectResumeSnapshot(db, sessionId, opts) {
|
|
27982
27915
|
const resume = db.getResume(sessionId);
|
|
27983
27916
|
if (!resume || resume.consumed) return null;
|
|
@@ -28000,6 +27933,17 @@ ${autoInjection}`;
|
|
|
28000
27933
|
db.markResumeConsumed(sessionId);
|
|
28001
27934
|
return fullSnapshot;
|
|
28002
27935
|
}
|
|
27936
|
+
async function buildResumeContextMessage(db, sessionId) {
|
|
27937
|
+
const snapshot = await injectResumeSnapshot(db, sessionId);
|
|
27938
|
+
if (!snapshot) return void 0;
|
|
27939
|
+
return {
|
|
27940
|
+
message: {
|
|
27941
|
+
customType: "unipi-compactor-resume",
|
|
27942
|
+
content: snapshot,
|
|
27943
|
+
display: false
|
|
27944
|
+
}
|
|
27945
|
+
};
|
|
27946
|
+
}
|
|
28003
27947
|
|
|
28004
27948
|
// packages/compactor/src/executor/executor.ts
|
|
28005
27949
|
import { spawn as spawn3, execSync, execFileSync as execFileSync2 } from "node:child_process";
|
|
@@ -28808,8 +28752,7 @@ function compactTool() {
|
|
|
28808
28752
|
}
|
|
28809
28753
|
|
|
28810
28754
|
// packages/compactor/src/tools/ctx-execute.ts
|
|
28811
|
-
async function ctxExecute(input) {
|
|
28812
|
-
const executor = new PolyglotExecutor();
|
|
28755
|
+
async function ctxExecute(input, executor = new PolyglotExecutor()) {
|
|
28813
28756
|
return executor.execute({
|
|
28814
28757
|
language: input.language,
|
|
28815
28758
|
code: input.code,
|
|
@@ -28819,12 +28762,11 @@ async function ctxExecute(input) {
|
|
|
28819
28762
|
|
|
28820
28763
|
// packages/compactor/src/tools/ctx-execute-file.ts
|
|
28821
28764
|
import { readFileSync as readFileSync30 } from "node:fs";
|
|
28822
|
-
async function ctxExecuteFile(input) {
|
|
28765
|
+
async function ctxExecuteFile(input, executor = new PolyglotExecutor()) {
|
|
28823
28766
|
const content = readFileSync30(input.path, "utf-8");
|
|
28824
28767
|
const code = `const FILE_CONTENT = ${JSON.stringify(content)};
|
|
28825
28768
|
// User script follows:
|
|
28826
28769
|
`;
|
|
28827
|
-
const executor = new PolyglotExecutor();
|
|
28828
28770
|
return executor.executeFile({
|
|
28829
28771
|
language: input.language,
|
|
28830
28772
|
path: input.path,
|
|
@@ -28834,9 +28776,8 @@ async function ctxExecuteFile(input) {
|
|
|
28834
28776
|
}
|
|
28835
28777
|
|
|
28836
28778
|
// packages/compactor/src/tools/ctx-batch-execute.ts
|
|
28837
|
-
async function ctxBatchExecute(items) {
|
|
28779
|
+
async function ctxBatchExecute(items, executor = new PolyglotExecutor()) {
|
|
28838
28780
|
const results = [];
|
|
28839
|
-
const executor = new PolyglotExecutor();
|
|
28840
28781
|
for (const item of items) {
|
|
28841
28782
|
if (item.type === "execute") {
|
|
28842
28783
|
const result = await executor.execute({
|
|
@@ -29021,74 +28962,85 @@ ${lines.join("\n\n")}`,
|
|
|
29021
28962
|
deprecationLog2("vcc_recall", "session_recall");
|
|
29022
28963
|
return recallExec(tcId, p);
|
|
29023
28964
|
} });
|
|
29024
|
-
|
|
29025
|
-
|
|
29026
|
-
|
|
29027
|
-
if (
|
|
29028
|
-
|
|
28965
|
+
if (deps.sandbox) {
|
|
28966
|
+
const { executor, allowedLanguages } = deps.sandbox;
|
|
28967
|
+
const assertAllowedLanguage = (language) => {
|
|
28968
|
+
if (!allowedLanguages.includes(language)) {
|
|
28969
|
+
throw new Error(`Language "${language}" is disabled by Compactor sandbox settings. Allowed: ${allowedLanguages.join(", ") || "none"}`);
|
|
29029
28970
|
}
|
|
29030
|
-
|
|
29031
|
-
|
|
29032
|
-
|
|
29033
|
-
|
|
29034
|
-
|
|
29035
|
-
|
|
29036
|
-
|
|
29037
|
-
|
|
29038
|
-
|
|
29039
|
-
|
|
29040
|
-
|
|
29041
|
-
|
|
29042
|
-
|
|
29043
|
-
|
|
29044
|
-
|
|
29045
|
-
|
|
29046
|
-
|
|
29047
|
-
|
|
29048
|
-
try {
|
|
29049
|
-
const c = deps.getCounters?.();
|
|
29050
|
-
if (c) {
|
|
29051
|
-
c.sandboxRuns++;
|
|
28971
|
+
};
|
|
28972
|
+
const sandboxExec = async (_toolCallId, params) => {
|
|
28973
|
+
try {
|
|
28974
|
+
const c = deps.getCounters?.();
|
|
28975
|
+
if (c) {
|
|
28976
|
+
c.sandboxRuns++;
|
|
28977
|
+
}
|
|
28978
|
+
deps.sessionDB.incrementSandboxRuns(deps.getSessionId());
|
|
28979
|
+
assertAllowedLanguage(params.language);
|
|
28980
|
+
const result = await ctxExecute(params, executor);
|
|
28981
|
+
const parts = [];
|
|
28982
|
+
if (result.stdout) parts.push(result.stdout);
|
|
28983
|
+
if (result.stderr) parts.push(`[stderr] ${result.stderr}`);
|
|
28984
|
+
if (result.timedOut) parts.push("[timed out]");
|
|
28985
|
+
if (result.exitCode !== 0) parts.push(`[exit code: ${result.exitCode}]`);
|
|
28986
|
+
return textResult2(parts.join("\n") || "(no output)", result);
|
|
28987
|
+
} catch (err) {
|
|
28988
|
+
return textResult2(`Execution error: ${err}`, { error: true });
|
|
29052
28989
|
}
|
|
29053
|
-
|
|
29054
|
-
|
|
29055
|
-
|
|
29056
|
-
|
|
29057
|
-
|
|
29058
|
-
|
|
29059
|
-
|
|
29060
|
-
|
|
29061
|
-
|
|
29062
|
-
|
|
29063
|
-
|
|
29064
|
-
|
|
29065
|
-
|
|
29066
|
-
|
|
29067
|
-
|
|
29068
|
-
|
|
29069
|
-
|
|
29070
|
-
|
|
29071
|
-
|
|
29072
|
-
|
|
29073
|
-
|
|
28990
|
+
};
|
|
28991
|
+
pi.registerTool({ name: "sandbox", label: "Sandbox", description: "Run code in a sandboxed environment. Supports 11 languages. Only stdout enters context.", parameters: SandboxParams, execute: sandboxExec });
|
|
28992
|
+
pi.registerTool({ name: "ctx_execute", label: "Sandbox", description: "Run code in sandbox. (DEPRECATED: use sandbox instead)", parameters: CtxExecuteParams, async execute(tcId, p) {
|
|
28993
|
+
deprecationLog2("ctx_execute", "sandbox");
|
|
28994
|
+
return sandboxExec(tcId, p);
|
|
28995
|
+
} });
|
|
28996
|
+
const sandboxFileExec = async (_toolCallId, params) => {
|
|
28997
|
+
try {
|
|
28998
|
+
const c = deps.getCounters?.();
|
|
28999
|
+
if (c) {
|
|
29000
|
+
c.sandboxRuns++;
|
|
29001
|
+
}
|
|
29002
|
+
deps.sessionDB.incrementSandboxRuns(deps.getSessionId());
|
|
29003
|
+
assertAllowedLanguage(params.language);
|
|
29004
|
+
const result = await ctxExecuteFile(params, executor);
|
|
29005
|
+
const parts = [];
|
|
29006
|
+
if (result.stdout) parts.push(result.stdout);
|
|
29007
|
+
if (result.stderr) parts.push(`[stderr] ${result.stderr}`);
|
|
29008
|
+
if (result.timedOut) parts.push("[timed out]");
|
|
29009
|
+
return textResult2(parts.join("\n") || "(no output)", result);
|
|
29010
|
+
} catch (err) {
|
|
29011
|
+
return textResult2(`Execution error: ${err}`, { error: true });
|
|
29074
29012
|
}
|
|
29075
|
-
|
|
29076
|
-
|
|
29077
|
-
|
|
29078
|
-
|
|
29079
|
-
|
|
29080
|
-
|
|
29081
|
-
|
|
29013
|
+
};
|
|
29014
|
+
pi.registerTool({ name: "sandbox_file", label: "Sandbox File", description: "Execute a file in the sandbox. File content is injected as FILE_CONTENT variable.", parameters: SandboxFileParams, execute: sandboxFileExec });
|
|
29015
|
+
pi.registerTool({ name: "ctx_execute_file", label: "Sandbox File", description: "Execute file in sandbox. (DEPRECATED: use sandbox_file instead)", parameters: CtxExecuteFileParams, async execute(tcId, p) {
|
|
29016
|
+
deprecationLog2("ctx_execute_file", "sandbox_file");
|
|
29017
|
+
return sandboxFileExec(tcId, p);
|
|
29018
|
+
} });
|
|
29019
|
+
const sandboxBatchExec = async (_toolCallId, params) => {
|
|
29020
|
+
try {
|
|
29021
|
+
const c = deps.getCounters?.();
|
|
29022
|
+
if (c) {
|
|
29023
|
+
c.sandboxRuns++;
|
|
29024
|
+
}
|
|
29025
|
+
deps.sessionDB.incrementSandboxRuns(deps.getSessionId());
|
|
29026
|
+
for (const item of params.items) assertAllowedLanguage(item.language);
|
|
29027
|
+
const result = await ctxBatchExecute(params.items, executor);
|
|
29028
|
+
const summaries = result.results.map((r, i) => {
|
|
29029
|
+
const s = r.result.stdout?.slice(0, 200) || "(no output)";
|
|
29030
|
+
return `[${i}] execute \u2192 ${r.result.exitCode === 0 ? "ok" : "fail"}: ${s}`;
|
|
29031
|
+
});
|
|
29032
|
+
return textResult2(`Batch results (${result.results.length} items):
|
|
29082
29033
|
${summaries.join("\n")}`, result);
|
|
29083
|
-
|
|
29084
|
-
|
|
29085
|
-
|
|
29086
|
-
|
|
29087
|
-
|
|
29088
|
-
|
|
29089
|
-
|
|
29090
|
-
|
|
29091
|
-
|
|
29034
|
+
} catch (err) {
|
|
29035
|
+
return textResult2(`Batch error: ${err}`, { error: true });
|
|
29036
|
+
}
|
|
29037
|
+
};
|
|
29038
|
+
pi.registerTool({ name: "sandbox_batch", label: "Sandbox Batch", description: "Run multiple code executions atomically as a batch.", parameters: SandboxBatchParams, execute: sandboxBatchExec });
|
|
29039
|
+
pi.registerTool({ name: "ctx_batch_execute", label: "Sandbox Batch", description: "Run batch operations. (DEPRECATED: use sandbox_batch instead)", parameters: CtxBatchExecuteParams, async execute(tcId, p) {
|
|
29040
|
+
deprecationLog2("ctx_batch_execute", "sandbox_batch");
|
|
29041
|
+
return sandboxBatchExec(tcId, p);
|
|
29042
|
+
} });
|
|
29043
|
+
}
|
|
29092
29044
|
const statsExec = async () => {
|
|
29093
29045
|
try {
|
|
29094
29046
|
const result = await ctxStats(deps.sessionDB, deps.getSessionId(), deps.getCounters?.());
|
|
@@ -29184,9 +29136,6 @@ function measureResponseBytes(event) {
|
|
|
29184
29136
|
function isSandboxTool(name) {
|
|
29185
29137
|
return name === "bash" || name === "Bash";
|
|
29186
29138
|
}
|
|
29187
|
-
function isIndexTool(_name) {
|
|
29188
|
-
return false;
|
|
29189
|
-
}
|
|
29190
29139
|
function compactorExtension(pi) {
|
|
29191
29140
|
let sessionDB = null;
|
|
29192
29141
|
let executor = null;
|
|
@@ -29204,7 +29153,6 @@ function compactorExtension(pi) {
|
|
|
29204
29153
|
const getCounters = () => counters;
|
|
29205
29154
|
const runtimeStats = {
|
|
29206
29155
|
bytesReturned: {},
|
|
29207
|
-
bytesIndexed: 0,
|
|
29208
29156
|
bytesSandboxed: 0,
|
|
29209
29157
|
calls: {},
|
|
29210
29158
|
sessionStart: Date.now(),
|
|
@@ -29222,7 +29170,7 @@ function compactorExtension(pi) {
|
|
|
29222
29170
|
} catch {
|
|
29223
29171
|
sessionDB = null;
|
|
29224
29172
|
}
|
|
29225
|
-
executor =
|
|
29173
|
+
executor = null;
|
|
29226
29174
|
};
|
|
29227
29175
|
registerCompactionHooks(pi, {
|
|
29228
29176
|
getSessionDB: () => sessionDB,
|
|
@@ -29251,7 +29199,6 @@ function compactorExtension(pi) {
|
|
|
29251
29199
|
}
|
|
29252
29200
|
}
|
|
29253
29201
|
runtimeStats.bytesReturned = {};
|
|
29254
|
-
runtimeStats.bytesIndexed = 0;
|
|
29255
29202
|
runtimeStats.bytesSandboxed = 0;
|
|
29256
29203
|
runtimeStats.calls = {};
|
|
29257
29204
|
runtimeStats.sessionStart = Date.now();
|
|
@@ -29260,11 +29207,17 @@ function compactorExtension(pi) {
|
|
|
29260
29207
|
autoCompactionState = createAutoCompactionState();
|
|
29261
29208
|
sessionDB?.ensureSession(fullSessionId, projectDir);
|
|
29262
29209
|
if (sessionDB) {
|
|
29210
|
+
const sandboxEnabled = config.sandboxExecution.enabled && config.sandboxExecution.mode !== "off";
|
|
29211
|
+
executor = sandboxEnabled ? new PolyglotExecutor({ hardCapBytes: config.sandboxExecution.outputLimit, projectRoot: projectDir }) : null;
|
|
29263
29212
|
registerCompactorTools(pi, {
|
|
29264
29213
|
sessionDB,
|
|
29265
29214
|
getSessionId: () => currentSessionId,
|
|
29266
29215
|
getBlocks: () => cachedBlocks,
|
|
29267
|
-
getCounters
|
|
29216
|
+
getCounters,
|
|
29217
|
+
sandbox: executor ? {
|
|
29218
|
+
executor,
|
|
29219
|
+
allowedLanguages: config.sandboxExecution.allowedLanguages
|
|
29220
|
+
} : void 0
|
|
29268
29221
|
});
|
|
29269
29222
|
}
|
|
29270
29223
|
registerCommands4(pi, getCommandDeps());
|
|
@@ -29350,21 +29303,11 @@ function compactorExtension(pi) {
|
|
|
29350
29303
|
}
|
|
29351
29304
|
} catch {
|
|
29352
29305
|
}
|
|
29353
|
-
|
|
29354
|
-
|
|
29355
|
-
|
|
29356
|
-
|
|
29357
|
-
|
|
29358
|
-
const { buildAutoInjection: buildAutoInjection2 } = await Promise.resolve().then(() => (init_auto_inject(), auto_inject_exports));
|
|
29359
|
-
const events = sessionDB.getEvents(currentSessionId, { limit: 100 });
|
|
29360
|
-
const autoInjection = buildAutoInjection2(events);
|
|
29361
|
-
if (autoInjection) {
|
|
29362
|
-
debug("auto_injection", { tokens: autoInjection.tokens, length: autoInjection.text.length });
|
|
29363
|
-
}
|
|
29364
|
-
} catch (err) {
|
|
29365
|
-
debug("auto_injection_error", { error: String(err) });
|
|
29366
|
-
}
|
|
29367
|
-
}
|
|
29306
|
+
const continuityEnabled = isSessionContinuityEnabled(config);
|
|
29307
|
+
if (sessionDB && continuityEnabled) {
|
|
29308
|
+
const resumeContext = await buildResumeContextMessage(sessionDB, currentSessionId);
|
|
29309
|
+
debug("resume_snapshot", { injected: !!resumeContext });
|
|
29310
|
+
return resumeContext;
|
|
29368
29311
|
}
|
|
29369
29312
|
});
|
|
29370
29313
|
pi.on("turn_end", async (_event, ctx) => {
|
|
@@ -29420,7 +29363,8 @@ function compactorExtension(pi) {
|
|
|
29420
29363
|
}
|
|
29421
29364
|
});
|
|
29422
29365
|
pi.on("session_before_compact", async (event, _ctx) => {
|
|
29423
|
-
|
|
29366
|
+
const continuityEnabled = isSessionContinuityEnabled(config);
|
|
29367
|
+
if (sessionDB && continuityEnabled) {
|
|
29424
29368
|
const sessionId = currentSessionId;
|
|
29425
29369
|
const events = sessionDB.getEvents(sessionId, { limit: 1e3 });
|
|
29426
29370
|
const stats = sessionDB.getSessionStats(sessionId);
|
|
@@ -29439,12 +29383,18 @@ function compactorExtension(pi) {
|
|
|
29439
29383
|
counters.compactions++;
|
|
29440
29384
|
const compactionEntry = event.compactionEntry;
|
|
29441
29385
|
const tokensBefore = compactionEntry?.tokensBefore ?? 0;
|
|
29386
|
+
let summarized = 0;
|
|
29387
|
+
let kept = 0;
|
|
29388
|
+
let tokensSaved = 0;
|
|
29442
29389
|
if (tokensBefore > 0) {
|
|
29443
29390
|
const charsBefore = tokensBefore * 4;
|
|
29444
|
-
const tokensAfter =
|
|
29391
|
+
const tokensAfter = Math.round(tokensBefore * 0.12);
|
|
29392
|
+
kept = tokensAfter;
|
|
29393
|
+
tokensSaved = tokensBefore - tokensAfter;
|
|
29445
29394
|
const charsKept = tokensAfter * 4;
|
|
29446
29395
|
const messagesSummarized = Math.max(1, Math.round(tokensBefore / 500));
|
|
29447
|
-
|
|
29396
|
+
summarized = messagesSummarized;
|
|
29397
|
+
counters.totalTokensCompacted += tokensSaved;
|
|
29448
29398
|
sessionDB.addCompactionStats(sessionId, charsBefore, charsKept, messagesSummarized);
|
|
29449
29399
|
} else {
|
|
29450
29400
|
try {
|
|
@@ -29454,12 +29404,23 @@ function compactorExtension(pi) {
|
|
|
29454
29404
|
const estTokensAfter = Math.round(estTokensBefore * 0.12);
|
|
29455
29405
|
const charsBefore = estTokensBefore * 4;
|
|
29456
29406
|
const charsKept = estTokensAfter * 4;
|
|
29457
|
-
|
|
29407
|
+
summarized = eventCount;
|
|
29408
|
+
kept = estTokensAfter;
|
|
29409
|
+
tokensSaved = estTokensBefore - estTokensAfter;
|
|
29410
|
+
counters.totalTokensCompacted += tokensSaved;
|
|
29458
29411
|
sessionDB.addCompactionStats(sessionId, charsBefore, charsKept, eventCount);
|
|
29459
29412
|
}
|
|
29460
29413
|
} catch {
|
|
29461
29414
|
}
|
|
29462
29415
|
}
|
|
29416
|
+
const totalEstimated = tokensSaved + kept;
|
|
29417
|
+
emitEvent(pi, UNIPI_EVENTS.COMPACTOR_COMPACTED, {
|
|
29418
|
+
sessionId,
|
|
29419
|
+
summarized,
|
|
29420
|
+
kept,
|
|
29421
|
+
tokensSaved,
|
|
29422
|
+
compressionRatio: kept > 0 ? `${Math.round(totalEstimated / kept)}:1` : "0:1"
|
|
29423
|
+
});
|
|
29463
29424
|
debug("session_compact", { sessionId, tokensBefore, hasCompactionEntry: !!compactionEntry });
|
|
29464
29425
|
}
|
|
29465
29426
|
});
|
|
@@ -29551,30 +29512,10 @@ function compactorExtension(pi) {
|
|
|
29551
29512
|
if (isSandboxTool(tName)) {
|
|
29552
29513
|
runtimeStats.bytesSandboxed += responseBytes;
|
|
29553
29514
|
}
|
|
29554
|
-
if (isIndexTool(tName)) {
|
|
29555
|
-
runtimeStats.bytesIndexed += responseBytes;
|
|
29556
|
-
}
|
|
29557
29515
|
}
|
|
29558
29516
|
} catch {
|
|
29559
29517
|
}
|
|
29560
29518
|
const toolName = event.toolName ?? "";
|
|
29561
|
-
const td = config.toolDisplay;
|
|
29562
|
-
const toolConfig = {
|
|
29563
|
-
readOutputMode: td?.mode,
|
|
29564
|
-
searchOutputMode: td?.mode,
|
|
29565
|
-
bashOutputMode: td?.mode,
|
|
29566
|
-
previewLines: 20,
|
|
29567
|
-
bashCollapsedLines: 5,
|
|
29568
|
-
showTruncationHints: true
|
|
29569
|
-
};
|
|
29570
|
-
try {
|
|
29571
|
-
const { applyToolDisplayOverride: applyToolDisplayOverride2 } = await Promise.resolve().then(() => (init_tool_overrides(), tool_overrides_exports));
|
|
29572
|
-
const override = applyToolDisplayOverride2(toolName, event, toolConfig);
|
|
29573
|
-
if (override !== void 0) {
|
|
29574
|
-
return override;
|
|
29575
|
-
}
|
|
29576
|
-
} catch {
|
|
29577
|
-
}
|
|
29578
29519
|
const diffToolNames = ["edit", "Edit", "write", "Write"];
|
|
29579
29520
|
if (diffToolNames.includes(toolName)) {
|
|
29580
29521
|
try {
|
|
@@ -30883,14 +30824,6 @@ var FooterRenderer = class _FooterRenderer {
|
|
|
30883
30824
|
init_core();
|
|
30884
30825
|
function subscribeToEvents(pi, registry3) {
|
|
30885
30826
|
const unsubscribers = [];
|
|
30886
|
-
unsubscribers.push(
|
|
30887
|
-
pi.events.on(UNIPI_EVENTS.COMPACTOR_STATS_UPDATED, (event) => {
|
|
30888
|
-
try {
|
|
30889
|
-
registry3.updateData("compactor", event);
|
|
30890
|
-
} catch {
|
|
30891
|
-
}
|
|
30892
|
-
})
|
|
30893
|
-
);
|
|
30894
30827
|
unsubscribers.push(
|
|
30895
30828
|
pi.events.on(UNIPI_EVENTS.COMPACTOR_COMPACTED, (event) => {
|
|
30896
30829
|
try {
|