@mediadatafusion/pi-workflow-suite 0.0.16 → 0.0.18
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 +13 -0
- package/README.md +29 -22
- package/VERSION +1 -1
- package/extensions/workflow-model-router.ts +2 -8
- package/extensions/workflow-modes.ts +257 -127
- package/package.json +13 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
All notable public releases will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.0.18] - 2026-06-10
|
|
6
|
+
|
|
7
|
+
### Improved
|
|
8
|
+
|
|
9
|
+
- Improved package metadata and compaction settings documentation.
|
|
10
|
+
- Refined compaction safeguards for default and custom configuration flows.
|
|
11
|
+
|
|
12
|
+
## [0.0.17] - 2026-06-10
|
|
13
|
+
|
|
14
|
+
### Improved
|
|
15
|
+
|
|
16
|
+
- Improved package metadata to better reflect the suite's workflow modes, configuration surfaces, and orchestration features.
|
|
17
|
+
|
|
5
18
|
## [0.0.16] - 2026-06-09
|
|
6
19
|
|
|
7
20
|
### Fixed
|
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
[](#installation) [](#quick-start) [](#core-commands) [](#settings-reference)
|
|
6
6
|
|
|
7
|
-
**Workflow Suite Version:** `v0.0.
|
|
7
|
+
**Workflow Suite Version:** `v0.0.18`
|
|
8
8
|
|
|
9
9
|
## Overview
|
|
10
10
|
|
|
@@ -118,7 +118,7 @@ Pi Workflow Suite turns Pi into a guided workflow environment:
|
|
|
118
118
|
| Interactive Diagrams | `workflow_diagram` Mermaid support with terminal preview, SVG-first clickable artifacts, PNG/runtime rendering support, dark-mode-friendly styling, and runtime artifact storage. |
|
|
119
119
|
| Web Research & Browser Verification | First-party `workflow_web_search`, `workflow_web_fetch`, and `workflow_browser_check` tools. Search and fetch for public web evidence with source URLs, blocked local/private/internal hosts, and time/size limits. Headless browser verification for runtime web app validation with interactive UI actions (click, type, read, screenshot, evaluate). |
|
|
120
120
|
| Repo Lock | Project-scoped Global Safety control that constrains normal file tools, bash path checks, and sub-agents to the active repository, with protected configuration paths and clear non-sandbox caveats. |
|
|
121
|
-
| Compaction |
|
|
121
|
+
| Compaction | Shared compaction controls for Pi default or custom summary model selection, Pi default or custom trigger thresholds, idle-boundary proactive checks, custom token tuning, adaptive fitting, status reporting, and safe fallback. |
|
|
122
122
|
| Token Budgets | Optional per-mode token and runtime caps (`maxTokens`, `maxRuntimeHours`) for Plan, Mission, and Standard Mode. Off by default (unlimited). When enabled, Workflow Suite tracks cumulative usage and blocks further agent turns when the budget is exceeded. |
|
|
123
123
|
| Workflow Roles | Planner, Executor, Reviewer, Validator, Mission, and compaction responsibilities are separated by phase so each job has clear boundaries and can be matched to the right model. |
|
|
124
124
|
| Model Selection | Configure which provider/model and thinking level powers each workflow role, with shared defaults plus Standard-specific and Mission-specific overrides for simpler or higher-rigor setups. |
|
|
@@ -799,27 +799,34 @@ Compaction settings are available through:
|
|
|
799
799
|
/workflow settings Shared Compaction
|
|
800
800
|
```
|
|
801
801
|
|
|
802
|
-
|
|
802
|
+
The grouped Shared Compaction menu separates trigger behavior from summary model selection. The trigger can use Pi default behavior or an explicit Workflow Suite threshold, while the compaction provider/model controls which model writes compaction summaries when configured.
|
|
803
803
|
|
|
804
|
-
-
|
|
805
|
-
- **Custom model** — route compaction summaries through a configured provider/model when available.
|
|
806
|
-
- **Disabled** — disables Workflow Suite custom compaction and leaves Pi fallback behavior.
|
|
807
|
-
- **Custom agent** — planned-only/backward-compatible mode; current releases keep Pi default fallback behavior instead of running agent-routed compaction.
|
|
804
|
+
Workflow Suite can request proactive compaction when context usage reaches the configured threshold. Actual proactive compaction runs only at a safe after-turn idle agent boundary, so it does not interrupt arbitrary tool execution or queued workflow handoffs. Pi default auto-compaction remains available as a safety fallback near the model limit.
|
|
808
805
|
|
|
809
|
-
|
|
806
|
+
The menu controls provider/model preference, auto-trigger behavior, trigger threshold, cooldown, reserve tokens, and keep-recent tokens:
|
|
810
807
|
|
|
811
|
-
|
|
808
|
+
```text
|
|
809
|
+
Shared Compaction Settings
|
|
810
|
+
|
|
811
|
+
Compaction Provider
|
|
812
|
+
Compaction Model
|
|
813
|
+
Workflow Auto Trigger Enabled
|
|
814
|
+
Workflow Trigger Percent
|
|
815
|
+
Workflow Trigger Cooldown
|
|
816
|
+
Custom Reserve Tokens
|
|
817
|
+
Custom Keep Recent Tokens
|
|
818
|
+
List Current Settings
|
|
819
|
+
Back
|
|
820
|
+
```
|
|
821
|
+
|
|
822
|
+
Each configurable compaction setting includes a Pi default option. Provider and model choices do not change the trigger threshold. The trigger reports `Pi default` when the native Pi threshold formula is in control and reports `custom, <percent>%` only when an explicit Workflow Suite trigger override is set.
|
|
812
823
|
|
|
813
824
|
Important behavior:
|
|
814
825
|
|
|
815
826
|
- **Safe boundary**: proactive compaction runs at a safe after-turn idle agent boundary only.
|
|
816
827
|
- **Cooldown**: the cooldown is the minimum wait between proactive attempts; it is not a delay before compaction starts and does not block manual compaction.
|
|
817
|
-
- **Adaptive fit**: Custom model preparation is fit to the selected
|
|
818
|
-
- **Fallback**: Custom model compaction falls back to Pi default behavior if required settings are missing, the model cannot be found, authentication or API key checks fail, preparation cannot fit, or the compaction call errors.
|
|
819
|
-
- **Status**: `/workflow settings Show Current Settings` reports the effective trigger state, runtime status, selected custom model, reserve/keep-recent token settings, latest check decision, and `Last Custom Compaction Status`.
|
|
820
|
-
|
|
821
|
-
The legacy `workflowCompactionCheckMode` setting may still exist for compatibility, but the primary release behavior is safe after-turn idle-boundary compaction. It is not permission to compact in the middle of arbitrary tool execution.
|
|
822
|
-
|
|
828
|
+
- **Adaptive fit**: Custom summary model preparation is fit to the selected model context window using configured reserve and keep-recent token settings.
|
|
829
|
+
- **Fallback**: Custom summary model compaction falls back to Pi default behavior if required settings are missing, the model cannot be found, authentication or API key checks fail, preparation cannot fit, or the compaction call errors.
|
|
823
830
|
## Diagram Support
|
|
824
831
|
|
|
825
832
|
Workflow Suite includes a `workflow_diagram` tool for Mermaid diagrams in workflow explanations, architecture notes, state transitions, data flows, export/share flows, and dependency maps. It is available to Workflow Suite execution and validation surfaces through the shared workflow tool set.
|
|
@@ -1007,8 +1014,8 @@ pi install -l npm:@mediadatafusion/pi-workflow-suite
|
|
|
1007
1014
|
### Installing specific versions
|
|
1008
1015
|
|
|
1009
1016
|
```bash
|
|
1010
|
-
pi install npm:@mediadatafusion/pi-workflow-suite@0.0.
|
|
1011
|
-
pi install -l npm:@mediadatafusion/pi-workflow-suite@0.0.
|
|
1017
|
+
pi install npm:@mediadatafusion/pi-workflow-suite@0.0.18
|
|
1018
|
+
pi install -l npm:@mediadatafusion/pi-workflow-suite@0.0.18
|
|
1012
1019
|
```
|
|
1013
1020
|
|
|
1014
1021
|
An unversioned install follows normal update behavior: `pi update` and `pi update --extensions` will pick up new package releases. A versioned install pins the package to that version. Pinned package specs are intentionally skipped by Pi's normal package update commands. To move a pinned install to a newer version, reinstall with the desired version. To switch back to latest tracking, use the unversioned install command without `@<version>`.
|
|
@@ -1124,7 +1131,7 @@ Primary settings areas:
|
|
|
1124
1131
|
- `standard` — Standard Mode enablement, dynamic To Do tracking, configurable clarification, widgets, model role, Standard sub-agent orchestration, and shared model selection.
|
|
1125
1132
|
- `missions` — Mission Mode autonomy, runtime, checkpoints, validation, repair, and mission-specific model selection.
|
|
1126
1133
|
- `subagents` — workflow phase policies, worker targets, activity indicator, parallelism preferences, and edit-concurrency guidance. These settings do not edit arbitrary sub-agent tool permissions.
|
|
1127
|
-
- `context` — compaction
|
|
1134
|
+
- `context` — compaction provider/model, auto-trigger behavior, trigger percentage, cooldown, reserve tokens, and keep-recent tokens.
|
|
1128
1135
|
- `ui` — widgets, shortcuts, Workflow Suite theme selection, startup visuals, startup logo text styling, footer/status hints, and optional themed input borders.
|
|
1129
1136
|
- `safety` — bash/tool guard settings.
|
|
1130
1137
|
|
|
@@ -1207,17 +1214,17 @@ See `docs/TROUBLESHOOTING.md` for detailed diagnostics.
|
|
|
1207
1214
|
|
|
1208
1215
|
## Operational Notes
|
|
1209
1216
|
|
|
1210
|
-
-
|
|
1217
|
+
- Configure a compaction provider/model when summaries should use a custom model; trigger behavior remains separate and can stay on Pi default behavior.
|
|
1211
1218
|
- Mission checkpoints are created at workflow gates and progress saves. The checkpoint interval setting records the preferred cadence for future timed checkpoint automation.
|
|
1212
1219
|
- Watchdog status can report stale mission activity when enabled. Recovery remains user-supervised so Mission Mode does not resume or mutate work unexpectedly.
|
|
1213
1220
|
- Parallel file edits are governed separately from parallel sub-agent work. Scoped parallel edit mode requires conflict protection; otherwise the main workflow keeps writes serialized for safety.
|
|
1214
1221
|
|
|
1215
1222
|
## Versioning
|
|
1216
1223
|
|
|
1217
|
-
The current preparation version is `v0.0.
|
|
1224
|
+
The current preparation version is `v0.0.18`. Version information is intentionally aligned across:
|
|
1218
1225
|
|
|
1219
|
-
- `VERSION` (`v0.0.
|
|
1220
|
-
- `package.json` (`0.0.
|
|
1226
|
+
- `VERSION` (`v0.0.18`),
|
|
1227
|
+
- `package.json` (`0.0.18`),
|
|
1221
1228
|
- `package-lock.json`,
|
|
1222
1229
|
- this README,
|
|
1223
1230
|
- Workflow Suite settings/about output.
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
v0.0.
|
|
1
|
+
v0.0.18
|
|
@@ -1434,14 +1434,8 @@ export function workflowSettingsConsistencyDiagnostics(settings: WorkflowSetting
|
|
|
1434
1434
|
if (settings.missions.finalValidationEnabled === true && (!settings.models.validator.enabled || !roleIsConfigured(settings.models.validator))) {
|
|
1435
1435
|
diagnostics.push("mission final validation is enabled but the shared validator model is disabled or unconfigured");
|
|
1436
1436
|
}
|
|
1437
|
-
if (settings.context.
|
|
1438
|
-
diagnostics.push("custom compaction model
|
|
1439
|
-
}
|
|
1440
|
-
if (settings.context.compactionMode === "custom_model" && settings.context.customCompactionEnabled !== true) {
|
|
1441
|
-
diagnostics.push("custom compaction mode is selected but customCompactionEnabled is not set — custom compaction will not activate");
|
|
1442
|
-
}
|
|
1443
|
-
if (settings.context.customCompactionEnabled === true && settings.context.compactionMode !== "custom_model") {
|
|
1444
|
-
diagnostics.push(`customCompactionEnabled=true but compactionMode=${settings.context.compactionMode}`);
|
|
1437
|
+
if ((settings.context.compactionModelProvider || settings.context.compactionModel) && (!settings.context.compactionModelProvider || !settings.context.compactionModel)) {
|
|
1438
|
+
diagnostics.push("custom compaction summary model preference is incomplete");
|
|
1445
1439
|
}
|
|
1446
1440
|
if (settings.missions.autoRepairReviewFailures !== false && settings.missions.reviewRetryMode === "off") {
|
|
1447
1441
|
diagnostics.push("mission review auto-repair is enabled but reviewRetryMode is off — override to safe_only will be applied at runtime; set reviewRetryMode explicitly to avoid confusion");
|
|
@@ -206,6 +206,15 @@ type PiSessionEntry = SessionEntry;
|
|
|
206
206
|
const DEFAULT_PI_COMPACTION_RESERVE_TOKENS = 16_384;
|
|
207
207
|
const DEFAULT_PI_COMPACTION_KEEP_RECENT_TOKENS = 20_000;
|
|
208
208
|
const CUSTOM_COMPACTION_PROMPT_OVERHEAD_TOKENS = 8_192;
|
|
209
|
+
const PI_SETTINGS_FILE = join(AGENT_DIR, "settings.json");
|
|
210
|
+
|
|
211
|
+
type PiNativeCompactionSettings = {
|
|
212
|
+
enabled: boolean;
|
|
213
|
+
reserveTokens: number;
|
|
214
|
+
keepRecentTokens: number;
|
|
215
|
+
source: "default" | "global" | "project";
|
|
216
|
+
file?: string;
|
|
217
|
+
};
|
|
209
218
|
|
|
210
219
|
function loadPiCompactionApi(): PiCompactionApi {
|
|
211
220
|
return {
|
|
@@ -215,6 +224,85 @@ function loadPiCompactionApi(): PiCompactionApi {
|
|
|
215
224
|
};
|
|
216
225
|
}
|
|
217
226
|
|
|
227
|
+
function readJsonObject(path: string): Record<string, unknown> | undefined {
|
|
228
|
+
try {
|
|
229
|
+
const parsed = JSON.parse(readFileSync(path, "utf8")) as unknown;
|
|
230
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed as Record<string, unknown> : undefined;
|
|
231
|
+
} catch {
|
|
232
|
+
return undefined;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function findProjectPiSettings(cwd: string): string | undefined {
|
|
237
|
+
let dir = cwd;
|
|
238
|
+
for (let i = 0; i < 40; i += 1) {
|
|
239
|
+
const candidate = join(dir, ".pi", "settings.json");
|
|
240
|
+
if (existsSync(candidate)) return candidate;
|
|
241
|
+
const parent = dirname(dir);
|
|
242
|
+
if (parent === dir) break;
|
|
243
|
+
dir = parent;
|
|
244
|
+
}
|
|
245
|
+
return undefined;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function coercePiCompactionSettings(raw: unknown): Partial<PiNativeCompactionSettings> | undefined {
|
|
249
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return undefined;
|
|
250
|
+
const compaction = raw as Record<string, unknown>;
|
|
251
|
+
const settings: Partial<PiNativeCompactionSettings> = {};
|
|
252
|
+
if (typeof compaction.enabled === "boolean") settings.enabled = compaction.enabled;
|
|
253
|
+
const reserveTokens = Number(compaction.reserveTokens);
|
|
254
|
+
if (Number.isFinite(reserveTokens) && reserveTokens > 0) settings.reserveTokens = Math.round(reserveTokens);
|
|
255
|
+
const keepRecentTokens = Number(compaction.keepRecentTokens);
|
|
256
|
+
if (Number.isFinite(keepRecentTokens) && keepRecentTokens > 0) settings.keepRecentTokens = Math.round(keepRecentTokens);
|
|
257
|
+
return settings;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function loadPiNativeCompactionSettings(cwd?: string): PiNativeCompactionSettings {
|
|
261
|
+
let settings: PiNativeCompactionSettings = {
|
|
262
|
+
enabled: true,
|
|
263
|
+
reserveTokens: DEFAULT_PI_COMPACTION_RESERVE_TOKENS,
|
|
264
|
+
keepRecentTokens: DEFAULT_PI_COMPACTION_KEEP_RECENT_TOKENS,
|
|
265
|
+
source: "default",
|
|
266
|
+
};
|
|
267
|
+
const globalSettings = existsSync(PI_SETTINGS_FILE) ? coercePiCompactionSettings(readJsonObject(PI_SETTINGS_FILE)?.compaction) : undefined;
|
|
268
|
+
if (globalSettings) settings = { ...settings, ...globalSettings, source: "global", file: PI_SETTINGS_FILE };
|
|
269
|
+
|
|
270
|
+
const projectFile = cwd ? findProjectPiSettings(cwd) : undefined;
|
|
271
|
+
const projectSettings = projectFile ? coercePiCompactionSettings(readJsonObject(projectFile)?.compaction) : undefined;
|
|
272
|
+
if (projectSettings) settings = { ...settings, ...projectSettings, source: "project", file: projectFile };
|
|
273
|
+
return settings;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function contextWindowFrom(ctx?: ExtensionContext, usage?: { contextWindow?: number }): number | undefined {
|
|
277
|
+
const contextWindow = Number(usage?.contextWindow ?? ctx?.getContextUsage?.()?.contextWindow ?? ctx?.model?.contextWindow);
|
|
278
|
+
return Number.isFinite(contextWindow) && contextWindow > 0 ? contextWindow : undefined;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function piNativeCompactionThreshold(cwd: string | undefined, contextWindow: number | undefined): { settings: PiNativeCompactionSettings; triggerTokens?: number; triggerPercent?: number } {
|
|
282
|
+
const settings = loadPiNativeCompactionSettings(cwd);
|
|
283
|
+
if (!settings.enabled || !contextWindow) return { settings };
|
|
284
|
+
const threshold = compactionThresholdForReserve(contextWindow, settings.reserveTokens);
|
|
285
|
+
return { settings, ...threshold };
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function compactionThresholdForReserve(contextWindow: number, reserveTokens: number): { triggerTokens: number; triggerPercent: number } {
|
|
289
|
+
const triggerTokens = Math.max(0, contextWindow - reserveTokens);
|
|
290
|
+
return { triggerTokens, triggerPercent: (triggerTokens / contextWindow) * 100 };
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function formatPiNativeCompactionThreshold(cwd: string | undefined, contextWindow: number | undefined): string {
|
|
294
|
+
const threshold = piNativeCompactionThreshold(cwd, contextWindow);
|
|
295
|
+
if (!threshold.settings.enabled) return "disabled";
|
|
296
|
+
return "Pi default";
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
function formatSharedCompactionTrigger(settings: ReturnType<typeof loadWorkflowSettings>, ctx?: ExtensionContext): string {
|
|
300
|
+
if (settings.context.compactionMode === "disabled" || settings.context.autoCompactionEnabled === false) return "disabled";
|
|
301
|
+
const override = compactionTriggerPercentOverride(settings);
|
|
302
|
+
if (override != null) return `custom, ${override}%`;
|
|
303
|
+
return formatPiNativeCompactionThreshold(ctx?.cwd, contextWindowFrom(ctx));
|
|
304
|
+
}
|
|
305
|
+
|
|
218
306
|
function createWorkflowCompactionFileOps(): FileOperations {
|
|
219
307
|
return { read: new Set<string>(), written: new Set<string>(), edited: new Set<string>() };
|
|
220
308
|
}
|
|
@@ -2675,15 +2763,15 @@ Mission Mode settings:
|
|
|
2675
2763
|
|
|
2676
2764
|
Compaction:
|
|
2677
2765
|
- /workflow-settings configure compaction opens the selectable compaction menu
|
|
2678
|
-
- Compaction Provider and Compaction Model
|
|
2679
|
-
- /workflow-settings set context
|
|
2680
|
-
- /workflow-settings set context customCompactionEnabled true|false
|
|
2681
|
-
- /workflow-settings set context autoCompactionEnabled true|false
|
|
2766
|
+
- Compaction Provider and Compaction Model select the summary model preference
|
|
2767
|
+
- /workflow-settings set context autoCompactionEnabled true|false|default
|
|
2682
2768
|
- /workflow-settings set context compactionTriggerPercent 50-95|default|reset
|
|
2683
|
-
- /workflow-settings set context compactionCooldownMinutes 0-240
|
|
2769
|
+
- /workflow-settings set context compactionCooldownMinutes 0-240|default|reset
|
|
2684
2770
|
- /workflow-settings set context customCompactionReserveTokens 4096-65536|default|reset
|
|
2685
2771
|
- /workflow-settings set context customCompactionKeepRecentTokens 1000-200000|default|reset
|
|
2686
2772
|
- /workflow-settings set context workflowCompactionCheckMode boundary|in_session (legacy/backward-compatible; primary UI uses safe after-turn compaction)
|
|
2773
|
+
- /workflow-settings set context compactionMode pi_default|custom_model|disabled (legacy/backward-compatible; primary UI uses trigger/provider/model controls)
|
|
2774
|
+
- /workflow-settings set context customCompactionEnabled true|false (legacy/backward-compatible; no longer required for summary model routing)
|
|
2687
2775
|
- /workflow-settings set context compactionModelProvider <provider> (advanced/manual fallback)
|
|
2688
2776
|
- /workflow-settings set context compactionModel <model> (advanced/manual fallback)
|
|
2689
2777
|
- /workflow-settings set context compactionAgent <agent> (legacy/backward-compatible; custom agent is planned only)
|
|
@@ -3172,40 +3260,34 @@ function workflowCompactionCheckRuntimeStatus(): string {
|
|
|
3172
3260
|
return `Last Check: ${workflowLastCompactionCheckAt}\nLast Decision: ${workflowLastCompactionDecision}`;
|
|
3173
3261
|
}
|
|
3174
3262
|
|
|
3175
|
-
function
|
|
3176
|
-
return settings.context.
|
|
3177
|
-
&& settings.context.compactionMode === "custom_model"
|
|
3178
|
-
&& Boolean(settings.context.compactionModelProvider)
|
|
3263
|
+
function summaryModelConfigured(settings: ReturnType<typeof loadWorkflowSettings>): boolean {
|
|
3264
|
+
return Boolean(settings.context.compactionModelProvider)
|
|
3179
3265
|
&& Boolean(settings.context.compactionModel);
|
|
3180
3266
|
}
|
|
3181
3267
|
|
|
3268
|
+
function customModelCompactionConfigured(settings: ReturnType<typeof loadWorkflowSettings>): boolean {
|
|
3269
|
+
return settings.context.compactionMode !== "disabled" && summaryModelConfigured(settings);
|
|
3270
|
+
}
|
|
3271
|
+
|
|
3182
3272
|
function workflowProactiveCompactionEffective(settings: ReturnType<typeof loadWorkflowSettings>): boolean {
|
|
3183
3273
|
if (settings.context.compactionMode === "disabled") return false;
|
|
3184
3274
|
return settings.context.autoCompactionEnabled === true;
|
|
3185
3275
|
}
|
|
3186
3276
|
|
|
3187
3277
|
function compactionIntegrationStatus(settings: ReturnType<typeof loadWorkflowSettings>): string {
|
|
3188
|
-
if (
|
|
3189
|
-
if (settings.context.
|
|
3190
|
-
if (!settings.context.compactionModelProvider || !settings.context.compactionModel) return "Custom model selected but provider/model is missing. Fallback: Pi default compaction.";
|
|
3191
|
-
return `Custom model active through Pi's session_before_compact hook using ${settings.context.compactionModelProvider}/${settings.context.compactionModel}. Fallback: Pi default if custom compaction cannot run or fails.`;
|
|
3192
|
-
}
|
|
3278
|
+
if (settings.context.compactionMode === "disabled") return "Workflow compaction disabled";
|
|
3279
|
+
if (summaryModelConfigured(settings)) return `Custom summary model configured through Pi's session_before_compact hook using ${settings.context.compactionModelProvider}/${settings.context.compactionModel}. Fallback: Pi default if custom compaction cannot run or fails.`;
|
|
3193
3280
|
if (settings.context.compactionMode === "custom_agent") return "Custom agent compaction is planned only. Fallback: Pi default compaction.";
|
|
3194
|
-
return "
|
|
3195
|
-
}
|
|
3196
|
-
|
|
3197
|
-
function defaultCompactionTriggerPercent(): number {
|
|
3198
|
-
return 50;
|
|
3281
|
+
return "Pi default summary model is active";
|
|
3199
3282
|
}
|
|
3200
3283
|
|
|
3201
|
-
function
|
|
3202
|
-
const
|
|
3203
|
-
|
|
3204
|
-
return Number.isFinite(value) && value >= 50 && value <= 95 ? Math.round(value) : fallback;
|
|
3284
|
+
function compactionTriggerPercentOverride(settings: ReturnType<typeof loadWorkflowSettings>): number | undefined {
|
|
3285
|
+
const value = Number(settings.context.compactionTriggerPercent);
|
|
3286
|
+
return Number.isFinite(value) && value >= 50 && value <= 95 ? Math.round(value) : undefined;
|
|
3205
3287
|
}
|
|
3206
3288
|
|
|
3207
3289
|
function compactionTriggerOverrideLabel(settings: ReturnType<typeof loadWorkflowSettings>): string {
|
|
3208
|
-
const value = settings
|
|
3290
|
+
const value = compactionTriggerPercentOverride(settings);
|
|
3209
3291
|
return typeof value === "number" ? `${value}%` : "none";
|
|
3210
3292
|
}
|
|
3211
3293
|
|
|
@@ -3220,18 +3302,9 @@ function resetCompactionContextToPiDefault(context: ReturnType<typeof loadWorkfl
|
|
|
3220
3302
|
}
|
|
3221
3303
|
|
|
3222
3304
|
function effectiveWorkflowCompactionTriggerPercent(settings: ReturnType<typeof loadWorkflowSettings>, ctx: ExtensionContext, usage: { contextWindow?: number }): number {
|
|
3223
|
-
const
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
if (!Number.isFinite(contextWindow) || contextWindow <= 0) return configured;
|
|
3227
|
-
const model = ctx.modelRegistry.find(settings.context.compactionModelProvider, settings.context.compactionModel);
|
|
3228
|
-
if (!model) return configured;
|
|
3229
|
-
const safeInputTokens = customCompactionSafeInputTokens(model);
|
|
3230
|
-
if (!safeInputTokens) return configured;
|
|
3231
|
-
const safeTotalBeforeCompaction = safeInputTokens + DEFAULT_PI_COMPACTION_KEEP_RECENT_TOKENS;
|
|
3232
|
-
const modelSafePercent = Math.floor((safeTotalBeforeCompaction / contextWindow) * 100);
|
|
3233
|
-
if (!Number.isFinite(modelSafePercent) || modelSafePercent <= 0) return configured;
|
|
3234
|
-
return Math.max(10, Math.min(configured, modelSafePercent));
|
|
3305
|
+
const contextWindow = contextWindowFrom(ctx, usage);
|
|
3306
|
+
const nativeThreshold = piNativeCompactionThreshold(ctx.cwd, contextWindow);
|
|
3307
|
+
return compactionTriggerPercentOverride(settings) ?? nativeThreshold.triggerPercent ?? NaN;
|
|
3235
3308
|
}
|
|
3236
3309
|
|
|
3237
3310
|
function compactionCooldownMinutes(settings: ReturnType<typeof loadWorkflowSettings>): number {
|
|
@@ -3239,6 +3312,16 @@ function compactionCooldownMinutes(settings: ReturnType<typeof loadWorkflowSetti
|
|
|
3239
3312
|
return Number.isFinite(value) && value >= 0 && value <= 240 ? Math.round(value) : 5;
|
|
3240
3313
|
}
|
|
3241
3314
|
|
|
3315
|
+
function compactionCooldownLabel(settings: ReturnType<typeof loadWorkflowSettings>): string {
|
|
3316
|
+
const value = compactionCooldownMinutes(settings);
|
|
3317
|
+
return value === 5 ? "Pi default" : `${value} min`;
|
|
3318
|
+
}
|
|
3319
|
+
|
|
3320
|
+
function workflowAutoTriggerLabel(settings: ReturnType<typeof loadWorkflowSettings>): string {
|
|
3321
|
+
if (settings.context.compactionMode === "disabled" || settings.context.autoCompactionEnabled === false) return "disabled";
|
|
3322
|
+
return settings.context.autoCompactionEnabled === true ? "enabled" : "Pi default";
|
|
3323
|
+
}
|
|
3324
|
+
|
|
3242
3325
|
function customCompactionReserveTokens(settings: ReturnType<typeof loadWorkflowSettings>): number {
|
|
3243
3326
|
const value = Number(settings.context.customCompactionReserveTokens ?? DEFAULT_PI_COMPACTION_RESERVE_TOKENS);
|
|
3244
3327
|
return Number.isFinite(value) && value >= 4096 && value <= 65536 ? Math.round(value) : DEFAULT_PI_COMPACTION_RESERVE_TOKENS;
|
|
@@ -3249,6 +3332,16 @@ function customCompactionKeepRecentTokens(settings: ReturnType<typeof loadWorkfl
|
|
|
3249
3332
|
return Number.isFinite(value) && value >= 1000 && value <= 200000 ? Math.round(value) : DEFAULT_PI_COMPACTION_KEEP_RECENT_TOKENS;
|
|
3250
3333
|
}
|
|
3251
3334
|
|
|
3335
|
+
function compactionReserveTokensLabel(settings: ReturnType<typeof loadWorkflowSettings>): string {
|
|
3336
|
+
const value = customCompactionReserveTokens(settings);
|
|
3337
|
+
return value === DEFAULT_PI_COMPACTION_RESERVE_TOKENS ? "Pi default" : value.toLocaleString();
|
|
3338
|
+
}
|
|
3339
|
+
|
|
3340
|
+
function compactionKeepRecentTokensLabel(settings: ReturnType<typeof loadWorkflowSettings>): string {
|
|
3341
|
+
const value = customCompactionKeepRecentTokens(settings);
|
|
3342
|
+
return value === DEFAULT_PI_COMPACTION_KEEP_RECENT_TOKENS ? "Pi default" : value.toLocaleString();
|
|
3343
|
+
}
|
|
3344
|
+
|
|
3252
3345
|
function customCompactionPreparationSettings(settings: ReturnType<typeof loadWorkflowSettings>, fallback: PiCompactionPreparation["settings"]): PiCompactionPreparation["settings"] {
|
|
3253
3346
|
return {
|
|
3254
3347
|
...fallback,
|
|
@@ -3261,14 +3354,15 @@ function compactionTriggerStatus(settings: ReturnType<typeof loadWorkflowSetting
|
|
|
3261
3354
|
if (settings.context.compactionMode === "disabled") return "Workflow compaction disabled";
|
|
3262
3355
|
const cooldown = `${compactionCooldownMinutes(settings)} minute cooldown`;
|
|
3263
3356
|
const safeBoundary = "safe after-turn idle boundary only";
|
|
3264
|
-
|
|
3265
|
-
if (
|
|
3357
|
+
const override = compactionTriggerPercentOverride(settings);
|
|
3358
|
+
if (workflowProactiveCompactionEffective(settings)) return `Armed at ${override == null ? "Pi default formula" : `${override}%`}; ${cooldown}; Compaction runs at ${safeBoundary}`;
|
|
3359
|
+
if (summaryModelConfigured(settings)) return `Custom summary model configured for Pi session_before_compact: ${settings.context.compactionModelProvider}/${settings.context.compactionModel}. Workflow proactive trigger is not enabled.`;
|
|
3266
3360
|
if (settings.context.autoCompactionEnabled !== true) return "Workflow proactive compaction disabled; Pi default auto-compaction still applies";
|
|
3267
|
-
return
|
|
3361
|
+
return "Pi default auto-compaction applies";
|
|
3268
3362
|
}
|
|
3269
3363
|
|
|
3270
3364
|
function missionCheckpointModelLabel(settings: ReturnType<typeof loadWorkflowSettings>): string {
|
|
3271
|
-
if (settings
|
|
3365
|
+
if (customModelCompactionConfigured(settings)) {
|
|
3272
3366
|
return `concise checkpoint summaries; Pi session compaction uses configured compaction model when active (currently ${settings.context.compactionModelProvider}/${settings.context.compactionModel})`;
|
|
3273
3367
|
}
|
|
3274
3368
|
return "concise checkpoint summaries; Pi session compaction uses configured compaction model when active";
|
|
@@ -3294,7 +3388,7 @@ Mission Checkpoint Model: ${missionCheckpointModelLabel(settings)}`;
|
|
|
3294
3388
|
function renderPlanModelSettings(settings: ReturnType<typeof loadWorkflowSettings>): string {
|
|
3295
3389
|
return `Plan Model Source: shared workflow role models
|
|
3296
3390
|
${renderWorkflowModels(settings)}
|
|
3297
|
-
Compaction Model: ${settings.context.
|
|
3391
|
+
Compaction Model: ${settings.context.compactionModelProvider && settings.context.compactionModel ? `${settings.context.compactionModelProvider}/${settings.context.compactionModel}` : "Pi default"}`;
|
|
3298
3392
|
}
|
|
3299
3393
|
|
|
3300
3394
|
function renderPlanSubagentWorkerSettings(settings: ReturnType<typeof loadWorkflowSettings>): string {
|
|
@@ -3393,8 +3487,10 @@ function renderWorkflowSettingsHealth(settings: ReturnType<typeof loadWorkflowSe
|
|
|
3393
3487
|
`Validator: ${configuredLabel(settings.models.validator)}`,
|
|
3394
3488
|
"",
|
|
3395
3489
|
"## Compaction",
|
|
3396
|
-
`
|
|
3397
|
-
`
|
|
3490
|
+
`Provider: ${settings.context.compactionModelProvider || "Pi default"}`,
|
|
3491
|
+
`Model: ${settings.context.compactionModel || "Pi default"}`,
|
|
3492
|
+
`Workflow Auto Trigger: ${workflowAutoTriggerLabel(settings)}`,
|
|
3493
|
+
`Trigger: ${formatSharedCompactionTrigger(settings)}`,
|
|
3398
3494
|
"Runtime: safe after-turn compaction",
|
|
3399
3495
|
"",
|
|
3400
3496
|
"## Capability Matrix Summary",
|
|
@@ -3652,18 +3748,16 @@ Note: Parallel File Edits controls simultaneous file writes only. It must not di
|
|
|
3652
3748
|
${renderSafetySettings(settings)}
|
|
3653
3749
|
|
|
3654
3750
|
## Compaction
|
|
3655
|
-
Compaction
|
|
3656
|
-
|
|
3657
|
-
Compaction
|
|
3658
|
-
Compaction Model: ${settings.context.compactionModel || "(not set)"}
|
|
3659
|
-
${compactionAgentLine(settings)}${compactionAgentLine(settings) ? "\n" : ""}Workflow Auto Compaction Trigger Setting: ${settings.context.autoCompactionEnabled === true ? "enabled" : "disabled"}
|
|
3751
|
+
Compaction Provider: ${settings.context.compactionModelProvider || "Pi default"}
|
|
3752
|
+
Compaction Model: ${settings.context.compactionModel || "Pi default"}
|
|
3753
|
+
${compactionAgentLine(settings)}${compactionAgentLine(settings) ? "\n" : ""}Workflow Auto Compaction Trigger Setting: ${workflowAutoTriggerLabel(settings)}
|
|
3660
3754
|
Effective Workflow Compaction Trigger: ${workflowProactiveCompactionEffective(settings) ? "armed" : "inactive"}
|
|
3661
3755
|
Compaction Runtime: safe after-turn idle boundary only
|
|
3662
3756
|
Workflow Compaction Trigger Override: ${compactionTriggerOverrideLabel(settings)}
|
|
3663
|
-
|
|
3757
|
+
Trigger: ${formatSharedCompactionTrigger(settings)}
|
|
3664
3758
|
Workflow Compaction Cooldown: ${compactionCooldownMinutes(settings)} minute(s)
|
|
3665
|
-
|
|
3666
|
-
|
|
3759
|
+
Compaction Reserve Tokens: ${compactionReserveTokensLabel(settings)}
|
|
3760
|
+
Compaction Keep Recent Tokens: ${compactionKeepRecentTokensLabel(settings)}
|
|
3667
3761
|
Compaction Integration Status: ${compactionIntegrationStatus(settings)}
|
|
3668
3762
|
Compaction Trigger Status: ${compactionTriggerStatus(settings)}
|
|
3669
3763
|
${workflowCompactionCheckRuntimeStatus()}
|
|
@@ -14651,33 +14745,62 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14651
14745
|
return { provider: providerChoice, model: modelChoice.replace(`${providerChoice}/`, "") };
|
|
14652
14746
|
}
|
|
14653
14747
|
|
|
14654
|
-
async function
|
|
14655
|
-
const
|
|
14656
|
-
|
|
14748
|
+
async function chooseCompactionProvider(ctx: ExtensionContext): Promise<string | undefined> {
|
|
14749
|
+
const models = ctx.modelRegistry.getAll();
|
|
14750
|
+
const providers = [...new Set(models.map((m) => m.provider))].sort();
|
|
14751
|
+
const providerChoice = await ctx.ui.select("Compaction Provider", ["Pi default", "Custom provider", "Back"]);
|
|
14752
|
+
if (!providerChoice || providerChoice === "Back") return undefined;
|
|
14753
|
+
if (providerChoice === "Pi default") return "";
|
|
14754
|
+
const choice = await ctx.ui.select("Custom provider", [...providers, "Custom provider name", "Back"]);
|
|
14755
|
+
if (!choice || choice === "Back") return undefined;
|
|
14756
|
+
if (choice === "Custom provider name") return (await ctx.ui.input("Custom compaction provider:", "provider-name"))?.trim();
|
|
14757
|
+
return choice;
|
|
14758
|
+
}
|
|
14759
|
+
|
|
14760
|
+
async function selectCompactionProvider(ctx: ExtensionContext) {
|
|
14761
|
+
const provider = await chooseCompactionProvider(ctx);
|
|
14762
|
+
if (provider === undefined) return;
|
|
14657
14763
|
const result = updateSettings(ctx.cwd, undefined, (s) => {
|
|
14658
|
-
s.context.
|
|
14659
|
-
s.context.
|
|
14660
|
-
s.context.compactionModel = selected.model;
|
|
14661
|
-
s.context.customCompactionEnabled = true;
|
|
14764
|
+
s.context.compactionModelProvider = provider;
|
|
14765
|
+
s.context.compactionModel = "";
|
|
14662
14766
|
});
|
|
14663
|
-
ctx.ui.notify(`Compaction
|
|
14767
|
+
ctx.ui.notify(provider ? `Compaction provider preference stored as ${provider} in ${result.file}. Trigger behavior was not changed.` : `Compaction provider reset to Pi default in ${result.file}. Trigger behavior was not changed.`, "info");
|
|
14664
14768
|
}
|
|
14665
14769
|
|
|
14666
|
-
async function
|
|
14770
|
+
async function selectCompactionModel(ctx: ExtensionContext) {
|
|
14667
14771
|
const settings = loadWorkflowSettings(ctx.cwd);
|
|
14668
14772
|
const provider = settings.context.compactionModelProvider;
|
|
14669
|
-
|
|
14670
|
-
|
|
14671
|
-
if (
|
|
14672
|
-
|
|
14673
|
-
|
|
14674
|
-
|
|
14773
|
+
const mode = await ctx.ui.select("Compaction Model", ["Pi default", "Custom model", "Back"]);
|
|
14774
|
+
if (!mode || mode === "Back") return;
|
|
14775
|
+
if (mode === "Pi default") {
|
|
14776
|
+
const result = updateSettings(ctx.cwd, undefined, (s) => {
|
|
14777
|
+
s.context.compactionModelProvider = "";
|
|
14778
|
+
s.context.compactionModel = "";
|
|
14779
|
+
});
|
|
14780
|
+
ctx.ui.notify(`Compaction summary model reset to Pi default in ${result.file}. Trigger behavior was not changed.`, "info");
|
|
14781
|
+
return;
|
|
14782
|
+
}
|
|
14783
|
+
|
|
14784
|
+
let selectedProvider = provider;
|
|
14785
|
+
if (!selectedProvider) {
|
|
14786
|
+
const chosen = await chooseCompactionProvider(ctx);
|
|
14787
|
+
if (chosen === undefined) return;
|
|
14788
|
+
selectedProvider = chosen;
|
|
14789
|
+
}
|
|
14790
|
+
if (!selectedProvider) {
|
|
14791
|
+
ctx.ui.notify("Select a custom compaction provider before selecting a custom model.", "warning");
|
|
14792
|
+
return;
|
|
14793
|
+
}
|
|
14794
|
+
const providerModels = ctx.modelRegistry.getAll().filter((m) => m.provider === selectedProvider).map((m) => m.id).sort();
|
|
14795
|
+
const modelChoice = await ctx.ui.select(`Custom model for ${selectedProvider}:`, [...providerModels.map((model) => `${selectedProvider}/${model}`), "Custom model name", "Back"]);
|
|
14796
|
+
if (!modelChoice || modelChoice === "Back") return;
|
|
14797
|
+
const model = modelChoice === "Custom model name" ? (await ctx.ui.input("Custom compaction model:", "model-name"))?.trim() : modelChoice.replace(`${selectedProvider}/`, "");
|
|
14798
|
+
if (!model) return;
|
|
14675
14799
|
const result = updateSettings(ctx.cwd, undefined, (s) => {
|
|
14676
|
-
s.context.
|
|
14800
|
+
s.context.compactionModelProvider = selectedProvider;
|
|
14677
14801
|
s.context.compactionModel = model;
|
|
14678
|
-
s.context.customCompactionEnabled = true;
|
|
14679
14802
|
});
|
|
14680
|
-
ctx.ui.notify(`Compaction model stored as ${
|
|
14803
|
+
ctx.ui.notify(`Compaction model preference stored as ${selectedProvider}/${model} in ${result.file}. Trigger behavior was not changed.`, "info");
|
|
14681
14804
|
}
|
|
14682
14805
|
|
|
14683
14806
|
async function selectCompactionAgent(ctx: ExtensionContext) {
|
|
@@ -14697,60 +14820,70 @@ ${renderMissionStatus(activeMission ?? paused)}`);
|
|
|
14697
14820
|
async function showCompactionSettingsMenu(ctx: ExtensionContext) {
|
|
14698
14821
|
if (!ctx.hasUI) return show(pi, renderFullWorkflowSettings(loadWorkflowSettings(ctx.cwd)));
|
|
14699
14822
|
while (ctx.hasUI) {
|
|
14700
|
-
const choice = await ctx.ui.select("Shared Compaction Settings", ["Compaction
|
|
14823
|
+
const choice = await ctx.ui.select("Shared Compaction Settings", ["Compaction Provider", "Compaction Model", "Workflow Auto Trigger Enabled", "Workflow Trigger Percent", "Workflow Trigger Cooldown", "Custom Reserve Tokens", "Custom Keep Recent Tokens", "List Current Settings", "Back"]);
|
|
14701
14824
|
if (!choice || choice === "Back") return;
|
|
14702
|
-
if (choice === "Compaction
|
|
14703
|
-
|
|
14704
|
-
if (!mode) continue;
|
|
14705
|
-
if (mode === "custom_model") { await selectCompactionModel(ctx); continue; }
|
|
14706
|
-
const r = updateSettings(ctx.cwd, undefined, (s) => {
|
|
14707
|
-
if (mode === "pi_default") resetCompactionContextToPiDefault(s.context);
|
|
14708
|
-
else {
|
|
14709
|
-
s.context.compactionMode = mode;
|
|
14710
|
-
s.context.customCompactionEnabled = false;
|
|
14711
|
-
}
|
|
14712
|
-
});
|
|
14713
|
-
ctx.ui.notify(`Compaction mode set to ${compactionModeLabel(mode)} in ${r.file}${mode === "pi_default" ? "; custom compaction overrides reset, selected provider/model preserved" : ""}.`, "info");
|
|
14714
|
-
} else if (choice === "Compaction Provider") {
|
|
14715
|
-
await selectCompactionModel(ctx);
|
|
14825
|
+
if (choice === "Compaction Provider") {
|
|
14826
|
+
await selectCompactionProvider(ctx);
|
|
14716
14827
|
} else if (choice === "Compaction Model") {
|
|
14717
|
-
await
|
|
14718
|
-
} else if (choice === "Custom Compaction Enabled") {
|
|
14719
|
-
const enabled = await chooseBool(ctx, "Custom compaction enabled?");
|
|
14720
|
-
if (enabled !== undefined) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.context.customCompactionEnabled = enabled; }); ctx.ui.notify(`Custom compaction set to ${enabled ? "enabled" : "disabled"} in ${r.file}. Custom model routing uses the session compaction hook when configured; Pi default fallback remains enabled.`, "info"); }
|
|
14828
|
+
await selectCompactionModel(ctx);
|
|
14721
14829
|
} else if (choice === "Workflow Auto Trigger Enabled") {
|
|
14722
|
-
const
|
|
14723
|
-
if (
|
|
14830
|
+
const trigger = await ctx.ui.select("Workflow Auto Trigger Enabled", ["Pi default", "Enabled", "Disabled", "Back"]);
|
|
14831
|
+
if (!trigger || trigger === "Back") continue;
|
|
14832
|
+
const r = updateSettings(ctx.cwd, undefined, (s) => {
|
|
14833
|
+
if (trigger === "Pi default") delete s.context.autoCompactionEnabled;
|
|
14834
|
+
else s.context.autoCompactionEnabled = trigger === "Enabled";
|
|
14835
|
+
});
|
|
14836
|
+
ctx.ui.notify(`Workflow auto trigger set to ${trigger.toLowerCase()} in ${r.file}.`, "info");
|
|
14724
14837
|
} else if (choice === "Workflow Trigger Percent") {
|
|
14725
|
-
const
|
|
14726
|
-
|
|
14727
|
-
if (
|
|
14838
|
+
const mode = await ctx.ui.select("Workflow Trigger Percent", ["Pi default", "Custom percent", "Back"]);
|
|
14839
|
+
if (!mode || mode === "Back") continue;
|
|
14840
|
+
if (mode === "Pi default") {
|
|
14728
14841
|
const r = updateSettings(ctx.cwd, undefined, (s) => { delete s.context.compactionTriggerPercent; });
|
|
14729
|
-
ctx.ui.notify(`Workflow compaction trigger percent override removed in ${r.file}; Pi
|
|
14842
|
+
ctx.ui.notify(`Workflow compaction trigger percent override removed in ${r.file}; Pi native trigger formula remains in control.`, "info");
|
|
14730
14843
|
} else {
|
|
14844
|
+
const raw = String((await ctx.ui.input("Workflow compaction trigger percent (50-95)", String(compactionTriggerPercentOverride(loadWorkflowSettings(ctx.cwd)) ?? 85))) ?? "").trim();
|
|
14731
14845
|
const count = Number(raw);
|
|
14732
14846
|
if (Number.isInteger(count) && count >= 50 && count <= 95) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.context.compactionTriggerPercent = count; }); ctx.ui.notify(`Workflow compaction trigger percent set to ${count}% in ${r.file}`, "info"); }
|
|
14733
|
-
else ctx.ui.notify("Trigger percent must be an integer from 50 to 95
|
|
14847
|
+
else ctx.ui.notify("Trigger percent must be an integer from 50 to 95.", "error");
|
|
14734
14848
|
}
|
|
14735
14849
|
} else if (choice === "Workflow Trigger Cooldown") {
|
|
14736
|
-
const
|
|
14737
|
-
if (
|
|
14738
|
-
|
|
14850
|
+
const mode = await ctx.ui.select("Workflow Trigger Cooldown", ["Pi default", "Custom cooldown", "Back"]);
|
|
14851
|
+
if (!mode || mode === "Back") continue;
|
|
14852
|
+
if (mode === "Pi default") {
|
|
14853
|
+
const r = updateSettings(ctx.cwd, undefined, (s) => { s.context.compactionCooldownMinutes = 5; });
|
|
14854
|
+
ctx.ui.notify(`Compaction cooldown reset to Pi default (5 minutes) in ${r.file}.`, "info");
|
|
14855
|
+
} else {
|
|
14856
|
+
const count = Number((await ctx.ui.input("Minimum minutes between Workflow Suite proactive compaction attempts", String(compactionCooldownMinutes(loadWorkflowSettings(ctx.cwd)))) ?? ""));
|
|
14857
|
+
if (Number.isInteger(count) && count >= 0 && count <= 240) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.context.compactionCooldownMinutes = count; }); ctx.ui.notify(`Compaction cooldown set to ${count} minute(s) in ${r.file}. This is the minimum wait between proactive compaction attempts, not a delay before compaction starts.`, "info"); }
|
|
14858
|
+
else ctx.ui.notify("Cooldown must be an integer from 0 to 240 minutes.", "error");
|
|
14859
|
+
}
|
|
14739
14860
|
} else if (choice === "Custom Reserve Tokens") {
|
|
14740
|
-
const
|
|
14741
|
-
|
|
14742
|
-
if (
|
|
14743
|
-
|
|
14744
|
-
|
|
14861
|
+
const mode = await ctx.ui.select("Custom Reserve Tokens", ["Pi default", "Custom reserve tokens", "Back"]);
|
|
14862
|
+
if (!mode || mode === "Back") continue;
|
|
14863
|
+
if (mode === "Pi default") {
|
|
14864
|
+
const r = updateSettings(ctx.cwd, undefined, (s) => { s.context.customCompactionReserveTokens = DEFAULT_PI_COMPACTION_RESERVE_TOKENS; });
|
|
14865
|
+
ctx.ui.notify(`Custom compaction reserve tokens reset to Pi default (${DEFAULT_PI_COMPACTION_RESERVE_TOKENS.toLocaleString()}) in ${r.file}`, "info");
|
|
14866
|
+
} else {
|
|
14867
|
+
const raw = String((await ctx.ui.input("Custom compaction reserve tokens (4096-65536)", String(customCompactionReserveTokens(loadWorkflowSettings(ctx.cwd)))) ?? "")).trim();
|
|
14868
|
+
const count = Number(raw);
|
|
14869
|
+
if (Number.isInteger(count) && count >= 4096 && count <= 65536) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.context.customCompactionReserveTokens = count; }); ctx.ui.notify(`Custom compaction reserve tokens set to ${count.toLocaleString()} in ${r.file}`, "info"); }
|
|
14870
|
+
else ctx.ui.notify("Reserve tokens must be an integer from 4096 to 65536.", "error");
|
|
14871
|
+
}
|
|
14745
14872
|
} else if (choice === "Custom Keep Recent Tokens") {
|
|
14746
|
-
const
|
|
14747
|
-
|
|
14748
|
-
if (
|
|
14749
|
-
|
|
14750
|
-
|
|
14873
|
+
const mode = await ctx.ui.select("Custom Keep Recent Tokens", ["Pi default", "Custom keep-recent tokens", "Back"]);
|
|
14874
|
+
if (!mode || mode === "Back") continue;
|
|
14875
|
+
if (mode === "Pi default") {
|
|
14876
|
+
const r = updateSettings(ctx.cwd, undefined, (s) => { s.context.customCompactionKeepRecentTokens = DEFAULT_PI_COMPACTION_KEEP_RECENT_TOKENS; });
|
|
14877
|
+
ctx.ui.notify(`Custom compaction keep-recent tokens reset to Pi default (${DEFAULT_PI_COMPACTION_KEEP_RECENT_TOKENS.toLocaleString()}) in ${r.file}`, "info");
|
|
14878
|
+
} else {
|
|
14879
|
+
const raw = String((await ctx.ui.input("Custom compaction keep-recent tokens (1000-200000)", String(customCompactionKeepRecentTokens(loadWorkflowSettings(ctx.cwd)))) ?? "")).trim();
|
|
14880
|
+
const count = Number(raw);
|
|
14881
|
+
if (Number.isInteger(count) && count >= 1000 && count <= 200000) { const r = updateSettings(ctx.cwd, undefined, (s) => { s.context.customCompactionKeepRecentTokens = count; }); ctx.ui.notify(`Custom compaction keep-recent tokens set to ${count.toLocaleString()} in ${r.file}`, "info"); }
|
|
14882
|
+
else ctx.ui.notify("Keep-recent tokens must be an integer from 1000 to 200000.", "error");
|
|
14883
|
+
}
|
|
14751
14884
|
} else if (choice === "List Current Settings") {
|
|
14752
14885
|
const s = loadWorkflowSettings(ctx.cwd);
|
|
14753
|
-
show(pi, `# Shared Compaction\n\
|
|
14886
|
+
show(pi, `# Shared Compaction\n\nProvider: ${s.context.compactionModelProvider || "Pi default"}\nModel: ${s.context.compactionModel || "Pi default"}\nWorkflow Auto Trigger: ${workflowAutoTriggerLabel(s)}\nTrigger: ${formatSharedCompactionTrigger(s, ctx)}\nCooldown: ${compactionCooldownLabel(s)}\nReserve Tokens: ${compactionReserveTokensLabel(s)}\nKeep Recent Tokens: ${compactionKeepRecentTokensLabel(s)}`);
|
|
14754
14887
|
}
|
|
14755
14888
|
}
|
|
14756
14889
|
}
|
|
@@ -15868,10 +16001,9 @@ Pi Version: v${VERSION}
|
|
|
15868
16001
|
|
|
15869
16002
|
function workflowAutoCompactionDecision(ctx: ExtensionContext, options: { allowPendingMessages?: boolean } = {}): { ok: true; percent: number; trigger: number; cooldownMinutes: number } | { ok: false; reason: string } {
|
|
15870
16003
|
const settings = loadWorkflowSettings(ctx.cwd);
|
|
15871
|
-
const customModelTrigger = customModelCompactionConfigured(settings);
|
|
15872
16004
|
if (!workflowProactiveCompactionEffective(settings)) return { ok: false, reason: "workflow proactive compaction disabled" };
|
|
15873
16005
|
if (settings.context.compactionMode === "disabled") return { ok: false, reason: "workflow compaction mode disabled" };
|
|
15874
|
-
if (!
|
|
16006
|
+
if (!workflowAutoCompactionModeEligible(state.mode)) return { ok: false, reason: `workflow mode ${state.mode} is active` };
|
|
15875
16007
|
if (!options.allowPendingMessages) {
|
|
15876
16008
|
if (workflowScheduledAgentTurns > 0) return { ok: false, reason: "pending workflow handoff queued" };
|
|
15877
16009
|
try { if (ctx.hasPendingMessages()) return { ok: false, reason: "pending messages queued" }; } catch { /* pending state unavailable */ }
|
|
@@ -15880,6 +16012,7 @@ Pi Version: v${VERSION}
|
|
|
15880
16012
|
const percent = Number(usage?.percent);
|
|
15881
16013
|
if (!Number.isFinite(percent)) return { ok: false, reason: "context usage unavailable" };
|
|
15882
16014
|
const trigger = effectiveWorkflowCompactionTriggerPercent(settings, ctx, usage ?? {});
|
|
16015
|
+
if (!Number.isFinite(trigger)) return { ok: false, reason: "compaction trigger unavailable" };
|
|
15883
16016
|
if (percent < trigger) return { ok: false, reason: `context ${percent.toFixed(1)}% below trigger ${trigger}%` };
|
|
15884
16017
|
const cooldownMinutes = compactionCooldownMinutes(settings);
|
|
15885
16018
|
const cooldownMs = cooldownMinutes * 60 * 1000;
|
|
@@ -15992,19 +16125,11 @@ Pi Version: v${VERSION}
|
|
|
15992
16125
|
|
|
15993
16126
|
pi.on("session_before_compact", async (event, ctx) => {
|
|
15994
16127
|
const settings = loadWorkflowSettings(ctx.cwd);
|
|
15995
|
-
if (
|
|
15996
|
-
if (settings.context.compactionMode === "pi_default" || settings.context.compactionMode === "disabled") return;
|
|
15997
|
-
if (settings.context.compactionMode !== "custom_model") {
|
|
15998
|
-
rememberCustomCompactionStatus(`fallback to Pi default: ${compactionModeLabel(settings.context.compactionMode)} uses Pi fallback behavior in current releases`);
|
|
15999
|
-
ctx.ui.notify("Agent-routed custom compaction uses Pi default fallback behavior in current releases.", "warning");
|
|
16000
|
-
return;
|
|
16001
|
-
}
|
|
16128
|
+
if (settings.context.compactionMode === "disabled") return;
|
|
16002
16129
|
|
|
16003
16130
|
const provider = settings.context.compactionModelProvider;
|
|
16004
16131
|
const modelId = settings.context.compactionModel;
|
|
16005
16132
|
if (!provider || !modelId) {
|
|
16006
|
-
rememberCustomCompactionStatus("fallback to Pi default: custom compaction model is missing provider/model");
|
|
16007
|
-
ctx.ui.notify("Custom compaction model is missing provider/model; using Pi default compaction.", "warning");
|
|
16008
16133
|
return;
|
|
16009
16134
|
}
|
|
16010
16135
|
|
|
@@ -16715,7 +16840,7 @@ Pi Version: v${VERSION}
|
|
|
16715
16840
|
if (action === "scope" || action === "write-target") {
|
|
16716
16841
|
const effective = loadEffectiveSettings(ctx.cwd);
|
|
16717
16842
|
const target = getDefaultWriteTarget(ctx.cwd);
|
|
16718
|
-
show(pi, `# Workflow Settings Scope\n\nCurrent Directory: ${ctx.cwd}\nProject Override: ${effective.projectOverridePath ?? "none"}\nWrite Target: ${target.scope}\nWrite Target File: ${target.file}\nGlobal Settings File: ${WORKFLOW_SETTINGS_FILE}\nSettings Priority: project workflow settings > global workflow-settings.json > example config defaults > built-in emergency fallback\nCompaction Effective Source: ${effective.projectOverridePath ? "project override may override global compaction settings" : "global workflow-settings.json"}\
|
|
16843
|
+
show(pi, `# Workflow Settings Scope\n\nCurrent Directory: ${ctx.cwd}\nProject Override: ${effective.projectOverridePath ?? "none"}\nWrite Target: ${target.scope}\nWrite Target File: ${target.file}\nGlobal Settings File: ${WORKFLOW_SETTINGS_FILE}\nSettings Priority: project workflow settings > global workflow-settings.json > example config defaults > built-in emergency fallback\nCompaction Effective Source: ${effective.projectOverridePath ? "project override may override global compaction settings" : "global workflow-settings.json"}\nCompaction Summary Model: ${effective.settings.context.compactionModelProvider && effective.settings.context.compactionModel ? `${effective.settings.context.compactionModelProvider}/${effective.settings.context.compactionModel}` : "Pi default"}`);
|
|
16719
16844
|
return;
|
|
16720
16845
|
}
|
|
16721
16846
|
if (action === "create-project-override") {
|
|
@@ -17022,7 +17147,12 @@ Pi Version: v${VERSION}
|
|
|
17022
17147
|
return show(pi, updatedMessage(result.scope, result.file, "context.customCompactionEnabled", String(bool)));
|
|
17023
17148
|
}
|
|
17024
17149
|
if (subject === "context" && key === "autoCompactionEnabled") {
|
|
17025
|
-
|
|
17150
|
+
const normalizedValue = String(value ?? "").trim().toLowerCase();
|
|
17151
|
+
if (normalizedValue === "default" || normalizedValue === "reset") {
|
|
17152
|
+
const result = updateSettings(ctx.cwd, scope, (s) => { delete s.context.autoCompactionEnabled; });
|
|
17153
|
+
return show(pi, updatedMessage(result.scope, result.file, "context.autoCompactionEnabled", "Pi default") + `\n\n${compactionTriggerStatus(result.settings)}`);
|
|
17154
|
+
}
|
|
17155
|
+
if (bool === undefined) return show(pi, "# Error\n\nUsage: `/workflow-settings set context autoCompactionEnabled <true|false|default>`");
|
|
17026
17156
|
const result = updateSettings(ctx.cwd, scope, (s) => { s.context.autoCompactionEnabled = bool; });
|
|
17027
17157
|
return show(pi, updatedMessage(result.scope, result.file, "context.autoCompactionEnabled", String(bool)) + `\n\n${compactionTriggerStatus(result.settings)}`);
|
|
17028
17158
|
}
|
|
@@ -17036,18 +17166,18 @@ Pi Version: v${VERSION}
|
|
|
17036
17166
|
const normalizedValue = String(value ?? "").trim().toLowerCase();
|
|
17037
17167
|
if (key === "compactionTriggerPercent" && (normalizedValue === "default" || normalizedValue === "reset")) {
|
|
17038
17168
|
const result = updateSettings(ctx.cwd, scope, (s) => { delete s.context.compactionTriggerPercent; });
|
|
17039
|
-
return show(pi, updatedMessage(result.scope, result.file, "context.compactionTriggerPercent", "removed override; Pi
|
|
17169
|
+
return show(pi, updatedMessage(result.scope, result.file, "context.compactionTriggerPercent", "removed override; Pi native formula applies") + `\n\n${compactionTriggerStatus(result.settings)}`);
|
|
17040
17170
|
}
|
|
17041
|
-
if ((key === "customCompactionReserveTokens" || key === "customCompactionKeepRecentTokens") && (normalizedValue === "default" || normalizedValue === "reset")) {
|
|
17042
|
-
const fallback = key === "customCompactionReserveTokens" ? DEFAULT_PI_COMPACTION_RESERVE_TOKENS : DEFAULT_PI_COMPACTION_KEEP_RECENT_TOKENS;
|
|
17171
|
+
if ((key === "compactionCooldownMinutes" || key === "customCompactionReserveTokens" || key === "customCompactionKeepRecentTokens") && (normalizedValue === "default" || normalizedValue === "reset")) {
|
|
17172
|
+
const fallback = key === "compactionCooldownMinutes" ? 5 : key === "customCompactionReserveTokens" ? DEFAULT_PI_COMPACTION_RESERVE_TOKENS : DEFAULT_PI_COMPACTION_KEEP_RECENT_TOKENS;
|
|
17043
17173
|
const result = updateSettings(ctx.cwd, scope, (s) => { (s.context as typeof s.context & Record<string, number>)[key] = fallback; });
|
|
17044
|
-
return show(pi, updatedMessage(result.scope, result.file, `context.${key}`, `default ${fallback}`) + `\n\n${compactionTriggerStatus(result.settings)}`);
|
|
17174
|
+
return show(pi, updatedMessage(result.scope, result.file, `context.${key}`, `Pi default ${fallback}`) + `\n\n${compactionTriggerStatus(result.settings)}`);
|
|
17045
17175
|
}
|
|
17046
17176
|
const rawCount = value === undefined ? NaN : Number(value);
|
|
17047
17177
|
const count = Number.isInteger(rawCount) ? rawCount : undefined;
|
|
17048
17178
|
const min = key === "compactionTriggerPercent" ? 50 : key === "compactionCooldownMinutes" ? 0 : key === "customCompactionReserveTokens" ? 4096 : 1000;
|
|
17049
17179
|
const max = key === "compactionTriggerPercent" ? 95 : key === "compactionCooldownMinutes" ? 240 : key === "customCompactionReserveTokens" ? 65536 : 200000;
|
|
17050
|
-
const usage =
|
|
17180
|
+
const usage = `<${min}-${max}|default|reset>`;
|
|
17051
17181
|
if (count === undefined || count < min || count > max) return show(pi, `# Error\n\nUsage: \`/workflow-settings set context ${key} ${usage}\``);
|
|
17052
17182
|
const result = updateSettings(ctx.cwd, scope, (s) => { (s.context as typeof s.context & Record<string, number>)[key] = count; });
|
|
17053
17183
|
return show(pi, updatedMessage(result.scope, result.file, `context.${key}`, String(count)) + `\n\n${compactionTriggerStatus(result.settings)}`);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mediadatafusion/pi-workflow-suite",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.0.18",
|
|
4
|
+
"description": "Multi-agent workflow suite for Pi with Idle, Standard, Plan, Mission, approval gates, reviewer/validator roles, sub-agents, model routing, web search/fetch, browser checks, diagrams, compaction, presets, settings, themes, widgets, and Repo Lock.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -24,9 +24,20 @@
|
|
|
24
24
|
"workflow-suite",
|
|
25
25
|
"workflow-orchestration",
|
|
26
26
|
"agent-workflow",
|
|
27
|
+
"idle-mode",
|
|
27
28
|
"plan-mode",
|
|
28
29
|
"mission-mode",
|
|
29
30
|
"standard-mode",
|
|
31
|
+
"multi-agent",
|
|
32
|
+
"approval-gates",
|
|
33
|
+
"review-validation",
|
|
34
|
+
"sub-agent-orchestration",
|
|
35
|
+
"model-routing",
|
|
36
|
+
"web-search",
|
|
37
|
+
"browser-verification",
|
|
38
|
+
"repo-lock",
|
|
39
|
+
"workflow-settings",
|
|
40
|
+
"workflow-widgets",
|
|
30
41
|
"subagents",
|
|
31
42
|
"skills",
|
|
32
43
|
"prompts",
|