@pi-unipi/unipi 2.4.1 → 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 +37 -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/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/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/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 +364 -434
- 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;
|
|
@@ -10735,7 +10573,6 @@ function info_screen_default(pi) {
|
|
|
10735
10573
|
}
|
|
10736
10574
|
|
|
10737
10575
|
// packages/subagents/src/index.ts
|
|
10738
|
-
init_core();
|
|
10739
10576
|
import { defineTool } from "@earendil-works/pi-coding-agent";
|
|
10740
10577
|
import { Text } from "@earendil-works/pi-tui";
|
|
10741
10578
|
import { Type as Type3 } from "typebox";
|
|
@@ -10743,6 +10580,29 @@ import { existsSync as existsSync13, readdirSync as readdirSync7 } from "node:fs
|
|
|
10743
10580
|
import { join as join13 } from "node:path";
|
|
10744
10581
|
import { homedir as homedir9 } from "node:os";
|
|
10745
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
|
+
|
|
10746
10606
|
// packages/subagents/src/agent-manager.ts
|
|
10747
10607
|
import { randomUUID } from "node:crypto";
|
|
10748
10608
|
|
|
@@ -11124,23 +10984,43 @@ var AgentManager = class {
|
|
|
11124
10984
|
onStart;
|
|
11125
10985
|
maxConcurrent;
|
|
11126
10986
|
customAgents;
|
|
10987
|
+
typeSettings;
|
|
11127
10988
|
/** Per-file transparent locking for write agents. */
|
|
11128
10989
|
fileLock = new FileLock();
|
|
11129
10990
|
/** Queue of background agents waiting to start. */
|
|
11130
10991
|
queue = [];
|
|
11131
10992
|
/** Number of currently running background agents. */
|
|
11132
10993
|
runningBackground = 0;
|
|
11133
|
-
constructor(onComplete, maxConcurrent = DEFAULT_MAX_CONCURRENT, onStart) {
|
|
10994
|
+
constructor(onComplete, maxConcurrent = DEFAULT_MAX_CONCURRENT, onStart, typeSettings = {}, agentsCwd = process.cwd()) {
|
|
11134
10995
|
this.onComplete = onComplete;
|
|
11135
10996
|
this.onStart = onStart;
|
|
11136
10997
|
this.maxConcurrent = maxConcurrent;
|
|
11137
|
-
this.
|
|
10998
|
+
this.typeSettings = typeSettings;
|
|
10999
|
+
this.customAgents = loadCustomAgents(agentsCwd);
|
|
11138
11000
|
this.cleanupInterval = setInterval(() => this.cleanup(), 6e4);
|
|
11139
11001
|
}
|
|
11140
11002
|
/** Get resolved agent config for a type. */
|
|
11141
11003
|
getAgentConfig(type) {
|
|
11142
11004
|
return this.customAgents.get(type) ?? BUILTIN_CONFIGS[type];
|
|
11143
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
|
+
}
|
|
11144
11024
|
setMaxConcurrent(n) {
|
|
11145
11025
|
this.maxConcurrent = Math.max(1, n);
|
|
11146
11026
|
this.drainQueue();
|
|
@@ -11152,6 +11032,7 @@ var AgentManager = class {
|
|
|
11152
11032
|
* Spawn an agent. Returns ID immediately for background, waits for foreground.
|
|
11153
11033
|
*/
|
|
11154
11034
|
spawn(pi, ctx, type, prompt, options) {
|
|
11035
|
+
this.assertTypeEnabled(type);
|
|
11155
11036
|
const id = randomUUID().slice(0, 17);
|
|
11156
11037
|
const abortController = new AbortController();
|
|
11157
11038
|
const record = {
|
|
@@ -11179,9 +11060,11 @@ var AgentManager = class {
|
|
|
11179
11060
|
record.startedAt = Date.now();
|
|
11180
11061
|
if (options.isBackground) this.runningBackground++;
|
|
11181
11062
|
this.onStart?.(record);
|
|
11063
|
+
const agentConfig = this.getAgentConfig(type);
|
|
11182
11064
|
let model = options.model;
|
|
11183
|
-
|
|
11184
|
-
|
|
11065
|
+
const modelInput = options.modelInput ?? agentConfig?.model;
|
|
11066
|
+
if (!model && modelInput && options.modelRegistry) {
|
|
11067
|
+
const resolved = resolveModel(modelInput, options.modelRegistry);
|
|
11185
11068
|
if (typeof resolved === "string") {
|
|
11186
11069
|
record.status = "error";
|
|
11187
11070
|
record.error = resolved;
|
|
@@ -11194,15 +11077,14 @@ var AgentManager = class {
|
|
|
11194
11077
|
}
|
|
11195
11078
|
model = resolved;
|
|
11196
11079
|
}
|
|
11197
|
-
const agentConfig = this.getAgentConfig(type);
|
|
11198
11080
|
const promise = runAgent(ctx, type, prompt, {
|
|
11199
11081
|
pi,
|
|
11200
11082
|
model,
|
|
11201
11083
|
agentConfig,
|
|
11202
|
-
maxTurns: options.maxTurns,
|
|
11203
|
-
isolated: options.isolated,
|
|
11204
|
-
inheritContext: options.inheritContext,
|
|
11205
|
-
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,
|
|
11206
11088
|
signal: record.abortController.signal,
|
|
11207
11089
|
onToolActivity: (activity) => {
|
|
11208
11090
|
if (activity.type === "end") record.toolUses++;
|
|
@@ -12142,7 +12024,8 @@ function src_default(pi) {
|
|
|
12142
12024
|
type: record.type,
|
|
12143
12025
|
description: record.description
|
|
12144
12026
|
});
|
|
12145
|
-
}
|
|
12027
|
+
},
|
|
12028
|
+
config.types
|
|
12146
12029
|
);
|
|
12147
12030
|
function buildNotificationDetails(record, activity) {
|
|
12148
12031
|
return {
|
|
@@ -12245,14 +12128,14 @@ function src_default(pi) {
|
|
|
12245
12128
|
let sessionCtx2 = null;
|
|
12246
12129
|
pi.on("session_start", async (_event, ctx) => {
|
|
12247
12130
|
sessionCtx2 = ctx;
|
|
12248
|
-
|
|
12249
|
-
name:
|
|
12131
|
+
emitEvent2(pi, UNIPI_EVENTS2.MODULE_READY, {
|
|
12132
|
+
name: MODULES2.SUBAGENTS || "subagents",
|
|
12250
12133
|
version: "0.2.0",
|
|
12251
12134
|
commands: [],
|
|
12252
12135
|
tools: ["spawn_helper", "get_helper_result"]
|
|
12253
12136
|
});
|
|
12254
12137
|
});
|
|
12255
|
-
pi.events.on(
|
|
12138
|
+
pi.events.on(UNIPI_EVENTS2.BADGE_GENERATE_REQUEST, async (data) => {
|
|
12256
12139
|
const event = data;
|
|
12257
12140
|
if (!sessionCtx2) return;
|
|
12258
12141
|
const summary = event?.conversationSummary ?? "";
|
|
@@ -12338,13 +12221,15 @@ ${summary}` : `Generate a concise session title (MAX 5 WORDS) for this session.
|
|
|
12338
12221
|
return { state, callbacks };
|
|
12339
12222
|
}
|
|
12340
12223
|
const builtinTypes = BUILTIN_TYPES.join(", ");
|
|
12224
|
+
const enabledTypes = manager2.getKnownTypes().filter((type) => manager2.isTypeEnabled(type));
|
|
12225
|
+
const availableTypes = enabledTypes.join(", ") || "none";
|
|
12341
12226
|
pi.registerTool(
|
|
12342
12227
|
defineTool({
|
|
12343
12228
|
name: "spawn_helper",
|
|
12344
12229
|
label: "Spawn Helper",
|
|
12345
12230
|
description: `Launch a sub-agent for parallel work.
|
|
12346
12231
|
|
|
12347
|
-
Available agent types: ${
|
|
12232
|
+
Available agent types: ${availableTypes}
|
|
12348
12233
|
Custom types can be defined in:
|
|
12349
12234
|
- ~/.unipi/config/agents/<name>.md (global)
|
|
12350
12235
|
- <workspace>/.unipi/config/agents/<name>.md (project)
|
|
@@ -12357,7 +12242,7 @@ Guidelines:
|
|
|
12357
12242
|
- Agents inherit the parent model by default`,
|
|
12358
12243
|
parameters: Type3.Object({
|
|
12359
12244
|
type: Type3.String({
|
|
12360
|
-
description: `
|
|
12245
|
+
description: `Enabled agent type: ${availableTypes}`
|
|
12361
12246
|
}),
|
|
12362
12247
|
prompt: Type3.String({
|
|
12363
12248
|
description: "The task for the agent to perform."
|
|
@@ -12600,7 +12485,7 @@ Use get_result to retrieve full results.`,
|
|
|
12600
12485
|
}
|
|
12601
12486
|
if (params.view && record.session) {
|
|
12602
12487
|
const activity = agentActivity.get(record.id);
|
|
12603
|
-
await
|
|
12488
|
+
await withHerdrBlocked2(
|
|
12604
12489
|
pi,
|
|
12605
12490
|
"helper viewer",
|
|
12606
12491
|
() => ctx.ui.custom(
|
|
@@ -17587,7 +17472,6 @@ var PRESETS = {
|
|
|
17587
17472
|
}
|
|
17588
17473
|
}
|
|
17589
17474
|
};
|
|
17590
|
-
var HARDCODED_FALLBACK = PRESETS.default.colors;
|
|
17591
17475
|
function getPreset(name) {
|
|
17592
17476
|
return PRESETS[name] ?? PRESETS.default;
|
|
17593
17477
|
}
|
|
@@ -18242,17 +18126,9 @@ function registerUtilityCommands(pi) {
|
|
|
18242
18126
|
}
|
|
18243
18127
|
return;
|
|
18244
18128
|
}
|
|
18245
|
-
const requestId = `status-${Date.now()}`;
|
|
18246
|
-
emitEvent(pi, UNIPI_EVENTS.MODULE_STATUS_REQUEST, { requestId });
|
|
18247
|
-
await new Promise((resolve13) => setTimeout(resolve13, 500));
|
|
18248
18129
|
sendResponse(
|
|
18249
18130
|
pi,
|
|
18250
|
-
|
|
18251
|
-
|
|
18252
|
-
Status request broadcast to all modules.
|
|
18253
|
-
Modules that support status reporting will respond via events.
|
|
18254
|
-
|
|
18255
|
-
*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."
|
|
18256
18132
|
);
|
|
18257
18133
|
}
|
|
18258
18134
|
});
|
|
@@ -23731,7 +23607,7 @@ function getEnabledPlatforms(config, ntfyEnabled) {
|
|
|
23731
23607
|
function unregisterEventListeners() {
|
|
23732
23608
|
unregisterAll();
|
|
23733
23609
|
}
|
|
23734
|
-
async function dispatchNotification(pi, title, message, eventPlatforms, eventType, config, cwd) {
|
|
23610
|
+
async function dispatchNotification(pi, title, message, eventPlatforms, eventType, config, cwd, priority) {
|
|
23735
23611
|
const ntfyConfig = loadNtfyConfig(cwd);
|
|
23736
23612
|
const platforms = eventPlatforms.length > 0 ? eventPlatforms : getEnabledPlatforms(config, ntfyConfig.enabled).length > 0 ? getEnabledPlatforms(config, ntfyConfig.enabled) : config.defaultPlatforms;
|
|
23737
23613
|
const enabledPlatforms = platforms.filter((p) => {
|
|
@@ -23744,8 +23620,8 @@ async function dispatchNotification(pi, title, message, eventPlatforms, eventTyp
|
|
|
23744
23620
|
const results = await Promise.all(
|
|
23745
23621
|
enabledPlatforms.map(async (platform) => {
|
|
23746
23622
|
try {
|
|
23747
|
-
await sendToPlatform(platform, title, message, config, cwd);
|
|
23748
|
-
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 } };
|
|
23749
23625
|
} catch (err) {
|
|
23750
23626
|
if (err instanceof SuppressedError2) {
|
|
23751
23627
|
return { platform, success: true, suppressed: true };
|
|
@@ -23770,14 +23646,21 @@ async function dispatchNotification(pi, title, message, eventPlatforms, eventTyp
|
|
|
23770
23646
|
});
|
|
23771
23647
|
return { results, allSuccess };
|
|
23772
23648
|
}
|
|
23773
|
-
|
|
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) {
|
|
23774
23657
|
switch (platform) {
|
|
23775
23658
|
case "native":
|
|
23776
23659
|
await sendNativeNotification(title, message, {
|
|
23777
23660
|
windowsAppId: config.native.windowsAppId,
|
|
23778
23661
|
suppressWhenFocused: config.native.suppressWhenFocused
|
|
23779
23662
|
});
|
|
23780
|
-
|
|
23663
|
+
return void 0;
|
|
23781
23664
|
case "gotify":
|
|
23782
23665
|
if (!config.gotify.serverUrl || !config.gotify.appToken) {
|
|
23783
23666
|
throw new Error("Gotify: serverUrl and appToken are required");
|
|
@@ -23787,9 +23670,9 @@ async function sendToPlatform(platform, title, message, config, cwd) {
|
|
|
23787
23670
|
config.gotify.appToken,
|
|
23788
23671
|
title,
|
|
23789
23672
|
message,
|
|
23790
|
-
config.gotify.priority
|
|
23673
|
+
priority ? mapNotifyPriority("gotify", priority) : config.gotify.priority
|
|
23791
23674
|
);
|
|
23792
|
-
|
|
23675
|
+
return priority ? mapNotifyPriority("gotify", priority) : config.gotify.priority;
|
|
23793
23676
|
case "telegram":
|
|
23794
23677
|
if (!config.telegram.botToken || !config.telegram.chatId) {
|
|
23795
23678
|
throw new Error("Telegram: botToken and chatId are required");
|
|
@@ -23800,10 +23683,10 @@ async function sendToPlatform(platform, title, message, config, cwd) {
|
|
|
23800
23683
|
title,
|
|
23801
23684
|
message
|
|
23802
23685
|
);
|
|
23803
|
-
|
|
23686
|
+
return void 0;
|
|
23804
23687
|
case "ntfy": {
|
|
23805
23688
|
const ntfyConfig = loadNtfyConfig(cwd);
|
|
23806
|
-
if (!ntfyConfig.enabled) return;
|
|
23689
|
+
if (!ntfyConfig.enabled) return void 0;
|
|
23807
23690
|
if (!ntfyConfig.serverUrl || !ntfyConfig.topic) {
|
|
23808
23691
|
throw new Error("ntfy: serverUrl and topic are required");
|
|
23809
23692
|
}
|
|
@@ -23812,10 +23695,10 @@ async function sendToPlatform(platform, title, message, config, cwd) {
|
|
|
23812
23695
|
ntfyConfig.topic,
|
|
23813
23696
|
title,
|
|
23814
23697
|
message,
|
|
23815
|
-
ntfyConfig.priority,
|
|
23698
|
+
priority ? mapNotifyPriority("ntfy", priority) : ntfyConfig.priority,
|
|
23816
23699
|
ntfyConfig.token
|
|
23817
23700
|
);
|
|
23818
|
-
|
|
23701
|
+
return priority ? mapNotifyPriority("ntfy", priority) : ntfyConfig.priority;
|
|
23819
23702
|
}
|
|
23820
23703
|
}
|
|
23821
23704
|
}
|
|
@@ -23944,7 +23827,6 @@ var NotifyUserSchema = Type6.Object({
|
|
|
23944
23827
|
priority: Type6.Optional(
|
|
23945
23828
|
Type6.String({
|
|
23946
23829
|
enum: ["low", "normal", "high"],
|
|
23947
|
-
default: "normal",
|
|
23948
23830
|
description: "Priority level"
|
|
23949
23831
|
})
|
|
23950
23832
|
),
|
|
@@ -23965,23 +23847,31 @@ function registerNotifyTools(pi) {
|
|
|
23965
23847
|
const {
|
|
23966
23848
|
message,
|
|
23967
23849
|
title,
|
|
23968
|
-
priority
|
|
23850
|
+
priority,
|
|
23969
23851
|
platforms
|
|
23970
23852
|
} = params;
|
|
23971
23853
|
const config = loadConfig2();
|
|
23972
23854
|
const notifTitle = title || "Pi Notification";
|
|
23973
23855
|
const notifPlatforms = platforms || config.defaultPlatforms;
|
|
23974
23856
|
const cwd = process.cwd();
|
|
23975
|
-
dispatchNotification(
|
|
23857
|
+
const dispatchPromise = dispatchNotification(
|
|
23976
23858
|
pi,
|
|
23977
23859
|
notifTitle,
|
|
23978
23860
|
message,
|
|
23979
23861
|
notifPlatforms,
|
|
23980
23862
|
"agent_tool",
|
|
23981
23863
|
config,
|
|
23982
|
-
cwd
|
|
23983
|
-
|
|
23864
|
+
cwd,
|
|
23865
|
+
priority
|
|
23866
|
+
);
|
|
23867
|
+
void dispatchPromise.catch(() => {
|
|
23984
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;
|
|
23985
23875
|
return {
|
|
23986
23876
|
content: [
|
|
23987
23877
|
{
|
|
@@ -23989,7 +23879,7 @@ function registerNotifyTools(pi) {
|
|
|
23989
23879
|
text: `Notification sending to ${notifPlatforms.length} platform(s): ${notifPlatforms.join(", ")}`
|
|
23990
23880
|
}
|
|
23991
23881
|
],
|
|
23992
|
-
details: { platforms: notifPlatforms }
|
|
23882
|
+
details: { platforms: notifPlatforms, priority, priorityByPlatform }
|
|
23993
23883
|
};
|
|
23994
23884
|
}
|
|
23995
23885
|
});
|
|
@@ -26388,10 +26278,7 @@ function registerSessionEndHook(pi) {
|
|
|
26388
26278
|
}
|
|
26389
26279
|
}
|
|
26390
26280
|
});
|
|
26391
|
-
|
|
26392
|
-
return void 0;
|
|
26393
|
-
});
|
|
26394
|
-
pi.on("session_shutdown", () => {
|
|
26281
|
+
const syncModifiedDocs = () => {
|
|
26395
26282
|
const cwd = process.cwd();
|
|
26396
26283
|
const milestonesPath = path13.join(cwd, MILESTONE_DIRS.MILESTONES);
|
|
26397
26284
|
if (!fs14.existsSync(milestonesPath)) return;
|
|
@@ -26409,7 +26296,9 @@ function registerSessionEndHook(pi) {
|
|
|
26409
26296
|
updateItemStatus(milestonesPath, phase, text, true);
|
|
26410
26297
|
}
|
|
26411
26298
|
}
|
|
26412
|
-
}
|
|
26299
|
+
};
|
|
26300
|
+
pi.events.on(UNIPI_EVENTS.WORKFLOW_END, syncModifiedDocs);
|
|
26301
|
+
pi.on("session_shutdown", syncModifiedDocs);
|
|
26413
26302
|
}
|
|
26414
26303
|
|
|
26415
26304
|
// packages/milestone/commands.ts
|
|
@@ -27979,8 +27868,49 @@ function extractEventsFromToolResult(result) {
|
|
|
27979
27868
|
|
|
27980
27869
|
// packages/compactor/src/session/resume-inject.ts
|
|
27981
27870
|
init_snapshot();
|
|
27982
|
-
|
|
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
|
|
27983
27910
|
init_manager();
|
|
27911
|
+
function isSessionContinuityEnabled(config) {
|
|
27912
|
+
return config.sessionContinuity.enabled && config.sessionContinuity.mode !== "off";
|
|
27913
|
+
}
|
|
27984
27914
|
async function injectResumeSnapshot(db, sessionId, opts) {
|
|
27985
27915
|
const resume = db.getResume(sessionId);
|
|
27986
27916
|
if (!resume || resume.consumed) return null;
|
|
@@ -28003,6 +27933,17 @@ ${autoInjection}`;
|
|
|
28003
27933
|
db.markResumeConsumed(sessionId);
|
|
28004
27934
|
return fullSnapshot;
|
|
28005
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
|
+
}
|
|
28006
27947
|
|
|
28007
27948
|
// packages/compactor/src/executor/executor.ts
|
|
28008
27949
|
import { spawn as spawn3, execSync, execFileSync as execFileSync2 } from "node:child_process";
|
|
@@ -28811,8 +28752,7 @@ function compactTool() {
|
|
|
28811
28752
|
}
|
|
28812
28753
|
|
|
28813
28754
|
// packages/compactor/src/tools/ctx-execute.ts
|
|
28814
|
-
async function ctxExecute(input) {
|
|
28815
|
-
const executor = new PolyglotExecutor();
|
|
28755
|
+
async function ctxExecute(input, executor = new PolyglotExecutor()) {
|
|
28816
28756
|
return executor.execute({
|
|
28817
28757
|
language: input.language,
|
|
28818
28758
|
code: input.code,
|
|
@@ -28822,12 +28762,11 @@ async function ctxExecute(input) {
|
|
|
28822
28762
|
|
|
28823
28763
|
// packages/compactor/src/tools/ctx-execute-file.ts
|
|
28824
28764
|
import { readFileSync as readFileSync30 } from "node:fs";
|
|
28825
|
-
async function ctxExecuteFile(input) {
|
|
28765
|
+
async function ctxExecuteFile(input, executor = new PolyglotExecutor()) {
|
|
28826
28766
|
const content = readFileSync30(input.path, "utf-8");
|
|
28827
28767
|
const code = `const FILE_CONTENT = ${JSON.stringify(content)};
|
|
28828
28768
|
// User script follows:
|
|
28829
28769
|
`;
|
|
28830
|
-
const executor = new PolyglotExecutor();
|
|
28831
28770
|
return executor.executeFile({
|
|
28832
28771
|
language: input.language,
|
|
28833
28772
|
path: input.path,
|
|
@@ -28837,9 +28776,8 @@ async function ctxExecuteFile(input) {
|
|
|
28837
28776
|
}
|
|
28838
28777
|
|
|
28839
28778
|
// packages/compactor/src/tools/ctx-batch-execute.ts
|
|
28840
|
-
async function ctxBatchExecute(items) {
|
|
28779
|
+
async function ctxBatchExecute(items, executor = new PolyglotExecutor()) {
|
|
28841
28780
|
const results = [];
|
|
28842
|
-
const executor = new PolyglotExecutor();
|
|
28843
28781
|
for (const item of items) {
|
|
28844
28782
|
if (item.type === "execute") {
|
|
28845
28783
|
const result = await executor.execute({
|
|
@@ -29024,74 +28962,85 @@ ${lines.join("\n\n")}`,
|
|
|
29024
28962
|
deprecationLog2("vcc_recall", "session_recall");
|
|
29025
28963
|
return recallExec(tcId, p);
|
|
29026
28964
|
} });
|
|
29027
|
-
|
|
29028
|
-
|
|
29029
|
-
|
|
29030
|
-
if (
|
|
29031
|
-
|
|
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"}`);
|
|
29032
28970
|
}
|
|
29033
|
-
|
|
29034
|
-
|
|
29035
|
-
|
|
29036
|
-
|
|
29037
|
-
|
|
29038
|
-
|
|
29039
|
-
|
|
29040
|
-
|
|
29041
|
-
|
|
29042
|
-
|
|
29043
|
-
|
|
29044
|
-
|
|
29045
|
-
|
|
29046
|
-
|
|
29047
|
-
|
|
29048
|
-
|
|
29049
|
-
|
|
29050
|
-
|
|
29051
|
-
try {
|
|
29052
|
-
const c = deps.getCounters?.();
|
|
29053
|
-
if (c) {
|
|
29054
|
-
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 });
|
|
29055
28989
|
}
|
|
29056
|
-
|
|
29057
|
-
|
|
29058
|
-
|
|
29059
|
-
|
|
29060
|
-
|
|
29061
|
-
|
|
29062
|
-
|
|
29063
|
-
|
|
29064
|
-
|
|
29065
|
-
|
|
29066
|
-
|
|
29067
|
-
|
|
29068
|
-
|
|
29069
|
-
|
|
29070
|
-
|
|
29071
|
-
|
|
29072
|
-
|
|
29073
|
-
|
|
29074
|
-
|
|
29075
|
-
|
|
29076
|
-
|
|
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 });
|
|
29077
29012
|
}
|
|
29078
|
-
|
|
29079
|
-
|
|
29080
|
-
|
|
29081
|
-
|
|
29082
|
-
|
|
29083
|
-
|
|
29084
|
-
|
|
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):
|
|
29085
29033
|
${summaries.join("\n")}`, result);
|
|
29086
|
-
|
|
29087
|
-
|
|
29088
|
-
|
|
29089
|
-
|
|
29090
|
-
|
|
29091
|
-
|
|
29092
|
-
|
|
29093
|
-
|
|
29094
|
-
|
|
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
|
+
}
|
|
29095
29044
|
const statsExec = async () => {
|
|
29096
29045
|
try {
|
|
29097
29046
|
const result = await ctxStats(deps.sessionDB, deps.getSessionId(), deps.getCounters?.());
|
|
@@ -29187,9 +29136,6 @@ function measureResponseBytes(event) {
|
|
|
29187
29136
|
function isSandboxTool(name) {
|
|
29188
29137
|
return name === "bash" || name === "Bash";
|
|
29189
29138
|
}
|
|
29190
|
-
function isIndexTool(_name) {
|
|
29191
|
-
return false;
|
|
29192
|
-
}
|
|
29193
29139
|
function compactorExtension(pi) {
|
|
29194
29140
|
let sessionDB = null;
|
|
29195
29141
|
let executor = null;
|
|
@@ -29207,7 +29153,6 @@ function compactorExtension(pi) {
|
|
|
29207
29153
|
const getCounters = () => counters;
|
|
29208
29154
|
const runtimeStats = {
|
|
29209
29155
|
bytesReturned: {},
|
|
29210
|
-
bytesIndexed: 0,
|
|
29211
29156
|
bytesSandboxed: 0,
|
|
29212
29157
|
calls: {},
|
|
29213
29158
|
sessionStart: Date.now(),
|
|
@@ -29225,7 +29170,7 @@ function compactorExtension(pi) {
|
|
|
29225
29170
|
} catch {
|
|
29226
29171
|
sessionDB = null;
|
|
29227
29172
|
}
|
|
29228
|
-
executor =
|
|
29173
|
+
executor = null;
|
|
29229
29174
|
};
|
|
29230
29175
|
registerCompactionHooks(pi, {
|
|
29231
29176
|
getSessionDB: () => sessionDB,
|
|
@@ -29254,7 +29199,6 @@ function compactorExtension(pi) {
|
|
|
29254
29199
|
}
|
|
29255
29200
|
}
|
|
29256
29201
|
runtimeStats.bytesReturned = {};
|
|
29257
|
-
runtimeStats.bytesIndexed = 0;
|
|
29258
29202
|
runtimeStats.bytesSandboxed = 0;
|
|
29259
29203
|
runtimeStats.calls = {};
|
|
29260
29204
|
runtimeStats.sessionStart = Date.now();
|
|
@@ -29263,11 +29207,17 @@ function compactorExtension(pi) {
|
|
|
29263
29207
|
autoCompactionState = createAutoCompactionState();
|
|
29264
29208
|
sessionDB?.ensureSession(fullSessionId, projectDir);
|
|
29265
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;
|
|
29266
29212
|
registerCompactorTools(pi, {
|
|
29267
29213
|
sessionDB,
|
|
29268
29214
|
getSessionId: () => currentSessionId,
|
|
29269
29215
|
getBlocks: () => cachedBlocks,
|
|
29270
|
-
getCounters
|
|
29216
|
+
getCounters,
|
|
29217
|
+
sandbox: executor ? {
|
|
29218
|
+
executor,
|
|
29219
|
+
allowedLanguages: config.sandboxExecution.allowedLanguages
|
|
29220
|
+
} : void 0
|
|
29271
29221
|
});
|
|
29272
29222
|
}
|
|
29273
29223
|
registerCommands4(pi, getCommandDeps());
|
|
@@ -29353,21 +29303,11 @@ function compactorExtension(pi) {
|
|
|
29353
29303
|
}
|
|
29354
29304
|
} catch {
|
|
29355
29305
|
}
|
|
29356
|
-
|
|
29357
|
-
|
|
29358
|
-
|
|
29359
|
-
|
|
29360
|
-
|
|
29361
|
-
const { buildAutoInjection: buildAutoInjection2 } = await Promise.resolve().then(() => (init_auto_inject(), auto_inject_exports));
|
|
29362
|
-
const events = sessionDB.getEvents(currentSessionId, { limit: 100 });
|
|
29363
|
-
const autoInjection = buildAutoInjection2(events);
|
|
29364
|
-
if (autoInjection) {
|
|
29365
|
-
debug("auto_injection", { tokens: autoInjection.tokens, length: autoInjection.text.length });
|
|
29366
|
-
}
|
|
29367
|
-
} catch (err) {
|
|
29368
|
-
debug("auto_injection_error", { error: String(err) });
|
|
29369
|
-
}
|
|
29370
|
-
}
|
|
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;
|
|
29371
29311
|
}
|
|
29372
29312
|
});
|
|
29373
29313
|
pi.on("turn_end", async (_event, ctx) => {
|
|
@@ -29423,7 +29363,8 @@ function compactorExtension(pi) {
|
|
|
29423
29363
|
}
|
|
29424
29364
|
});
|
|
29425
29365
|
pi.on("session_before_compact", async (event, _ctx) => {
|
|
29426
|
-
|
|
29366
|
+
const continuityEnabled = isSessionContinuityEnabled(config);
|
|
29367
|
+
if (sessionDB && continuityEnabled) {
|
|
29427
29368
|
const sessionId = currentSessionId;
|
|
29428
29369
|
const events = sessionDB.getEvents(sessionId, { limit: 1e3 });
|
|
29429
29370
|
const stats = sessionDB.getSessionStats(sessionId);
|
|
@@ -29442,12 +29383,18 @@ function compactorExtension(pi) {
|
|
|
29442
29383
|
counters.compactions++;
|
|
29443
29384
|
const compactionEntry = event.compactionEntry;
|
|
29444
29385
|
const tokensBefore = compactionEntry?.tokensBefore ?? 0;
|
|
29386
|
+
let summarized = 0;
|
|
29387
|
+
let kept = 0;
|
|
29388
|
+
let tokensSaved = 0;
|
|
29445
29389
|
if (tokensBefore > 0) {
|
|
29446
29390
|
const charsBefore = tokensBefore * 4;
|
|
29447
|
-
const tokensAfter =
|
|
29391
|
+
const tokensAfter = Math.round(tokensBefore * 0.12);
|
|
29392
|
+
kept = tokensAfter;
|
|
29393
|
+
tokensSaved = tokensBefore - tokensAfter;
|
|
29448
29394
|
const charsKept = tokensAfter * 4;
|
|
29449
29395
|
const messagesSummarized = Math.max(1, Math.round(tokensBefore / 500));
|
|
29450
|
-
|
|
29396
|
+
summarized = messagesSummarized;
|
|
29397
|
+
counters.totalTokensCompacted += tokensSaved;
|
|
29451
29398
|
sessionDB.addCompactionStats(sessionId, charsBefore, charsKept, messagesSummarized);
|
|
29452
29399
|
} else {
|
|
29453
29400
|
try {
|
|
@@ -29457,12 +29404,23 @@ function compactorExtension(pi) {
|
|
|
29457
29404
|
const estTokensAfter = Math.round(estTokensBefore * 0.12);
|
|
29458
29405
|
const charsBefore = estTokensBefore * 4;
|
|
29459
29406
|
const charsKept = estTokensAfter * 4;
|
|
29460
|
-
|
|
29407
|
+
summarized = eventCount;
|
|
29408
|
+
kept = estTokensAfter;
|
|
29409
|
+
tokensSaved = estTokensBefore - estTokensAfter;
|
|
29410
|
+
counters.totalTokensCompacted += tokensSaved;
|
|
29461
29411
|
sessionDB.addCompactionStats(sessionId, charsBefore, charsKept, eventCount);
|
|
29462
29412
|
}
|
|
29463
29413
|
} catch {
|
|
29464
29414
|
}
|
|
29465
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
|
+
});
|
|
29466
29424
|
debug("session_compact", { sessionId, tokensBefore, hasCompactionEntry: !!compactionEntry });
|
|
29467
29425
|
}
|
|
29468
29426
|
});
|
|
@@ -29554,30 +29512,10 @@ function compactorExtension(pi) {
|
|
|
29554
29512
|
if (isSandboxTool(tName)) {
|
|
29555
29513
|
runtimeStats.bytesSandboxed += responseBytes;
|
|
29556
29514
|
}
|
|
29557
|
-
if (isIndexTool(tName)) {
|
|
29558
|
-
runtimeStats.bytesIndexed += responseBytes;
|
|
29559
|
-
}
|
|
29560
29515
|
}
|
|
29561
29516
|
} catch {
|
|
29562
29517
|
}
|
|
29563
29518
|
const toolName = event.toolName ?? "";
|
|
29564
|
-
const td = config.toolDisplay;
|
|
29565
|
-
const toolConfig = {
|
|
29566
|
-
readOutputMode: td?.mode,
|
|
29567
|
-
searchOutputMode: td?.mode,
|
|
29568
|
-
bashOutputMode: td?.mode,
|
|
29569
|
-
previewLines: 20,
|
|
29570
|
-
bashCollapsedLines: 5,
|
|
29571
|
-
showTruncationHints: true
|
|
29572
|
-
};
|
|
29573
|
-
try {
|
|
29574
|
-
const { applyToolDisplayOverride: applyToolDisplayOverride2 } = await Promise.resolve().then(() => (init_tool_overrides(), tool_overrides_exports));
|
|
29575
|
-
const override = applyToolDisplayOverride2(toolName, event, toolConfig);
|
|
29576
|
-
if (override !== void 0) {
|
|
29577
|
-
return override;
|
|
29578
|
-
}
|
|
29579
|
-
} catch {
|
|
29580
|
-
}
|
|
29581
29519
|
const diffToolNames = ["edit", "Edit", "write", "Write"];
|
|
29582
29520
|
if (diffToolNames.includes(toolName)) {
|
|
29583
29521
|
try {
|
|
@@ -30886,14 +30824,6 @@ var FooterRenderer = class _FooterRenderer {
|
|
|
30886
30824
|
init_core();
|
|
30887
30825
|
function subscribeToEvents(pi, registry3) {
|
|
30888
30826
|
const unsubscribers = [];
|
|
30889
|
-
unsubscribers.push(
|
|
30890
|
-
pi.events.on(UNIPI_EVENTS.COMPACTOR_STATS_UPDATED, (event) => {
|
|
30891
|
-
try {
|
|
30892
|
-
registry3.updateData("compactor", event);
|
|
30893
|
-
} catch {
|
|
30894
|
-
}
|
|
30895
|
-
})
|
|
30896
|
-
);
|
|
30897
30827
|
unsubscribers.push(
|
|
30898
30828
|
pi.events.on(UNIPI_EVENTS.COMPACTOR_COMPACTED, (event) => {
|
|
30899
30829
|
try {
|