@ordewell/core 0.12.1 → 0.12.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/dist/plan-utils.d.mts +23 -1
- package/dist/plan-utils.d.ts +23 -1
- package/dist/plan-utils.js +34 -0
- package/dist/plan-utils.js.map +1 -1
- package/dist/plan-utils.mjs +32 -0
- package/dist/plan-utils.mjs.map +1 -1
- package/package.json +1 -1
package/dist/plan-utils.mjs
CHANGED
|
@@ -195,8 +195,39 @@ import {
|
|
|
195
195
|
titledTaskRefOf,
|
|
196
196
|
walkPlan
|
|
197
197
|
} from "./chunk-PKJTN2PD.mjs";
|
|
198
|
+
|
|
199
|
+
// src/services/composerTips.ts
|
|
200
|
+
var COMPOSER_TIPS = [
|
|
201
|
+
// The per-runner model allowlist (ADR-0003) is the easiest command to miss.
|
|
202
|
+
{ command: "allowlist", weight: 3, text: "Tip: Use /allowlist to limit which models the planner assigns per runner." },
|
|
203
|
+
{ command: "planner", weight: 1, text: "Tip: Use /planner to pick the planner's harness, model and effort." },
|
|
204
|
+
{ command: "runners", weight: 1, text: "Tip: Use /runners to turn runners on or off." },
|
|
205
|
+
{ command: "settings", weight: 1, text: "Tip: Use /settings for autonomy, supervisor, merging, autorun and more." },
|
|
206
|
+
{ command: "help", weight: 1, text: "Tip: Use /help to list every command." }
|
|
207
|
+
];
|
|
208
|
+
function tipCycle(tips) {
|
|
209
|
+
const total = tips.reduce((sum, tip) => sum + Math.max(0, tip.weight), 0);
|
|
210
|
+
if (total === 0) return [];
|
|
211
|
+
const slots = new Array(total).fill(void 0);
|
|
212
|
+
const order = tips.map((tip, index) => ({ tip, index })).filter(({ tip }) => tip.weight > 0).sort((a, b) => b.tip.weight - a.tip.weight || a.index - b.index);
|
|
213
|
+
for (const { tip } of order) {
|
|
214
|
+
const free = slots.flatMap((slot, at) => slot === void 0 ? [at] : []);
|
|
215
|
+
for (let k = 0; k < tip.weight; k++) {
|
|
216
|
+
slots[free[Math.floor((k + 0.5) * free.length / tip.weight)]] = tip;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
const cycle = slots.filter((tip) => tip !== void 0);
|
|
220
|
+
const start = cycle.indexOf(order[0].tip);
|
|
221
|
+
return [...cycle.slice(start), ...cycle.slice(0, start)];
|
|
222
|
+
}
|
|
223
|
+
function composerTip(seq, answers) {
|
|
224
|
+
const cycle = tipCycle(COMPOSER_TIPS.filter((tip) => answers.has(tip.command)));
|
|
225
|
+
if (cycle.length === 0) return null;
|
|
226
|
+
return cycle[(seq % cycle.length + cycle.length) % cycle.length].text;
|
|
227
|
+
}
|
|
198
228
|
export {
|
|
199
229
|
CHECKPOINT_TRUNCATE_LENGTH,
|
|
230
|
+
COMPOSER_TIPS,
|
|
200
231
|
DEFAULT_RUNNERS,
|
|
201
232
|
DELEGATION_OFFERED,
|
|
202
233
|
EMPTY_CONVERSATION,
|
|
@@ -249,6 +280,7 @@ export {
|
|
|
249
280
|
clampThinkingEffort,
|
|
250
281
|
closeTurn,
|
|
251
282
|
compactionText,
|
|
283
|
+
composerTip,
|
|
252
284
|
confirmedOverride,
|
|
253
285
|
contextMeterText,
|
|
254
286
|
contextMeterTitle,
|
package/dist/plan-utils.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/services/composerTips.ts"],"sourcesContent":["/**\n * The tips an empty planner chat composer shows (#137), one table for every\n * surface so the TUI and the webview agree on the wording and how often each\n * comes round. A surface offers only the tips for the commands it answers.\n */\n\nexport interface ComposerTip {\n /** The built-in planner chat command the tip names, without its slash. */\n command: string;\n /** How many times per cycle the tip comes round. */\n weight: number;\n /** Short enough to fit after the prompt and caret on an 80-column terminal. */\n text: string;\n}\n\nexport const COMPOSER_TIPS: readonly ComposerTip[] = [\n // The per-runner model allowlist (ADR-0003) is the easiest command to miss.\n { command: 'allowlist', weight: 3, text: 'Tip: Use /allowlist to limit which models the planner assigns per runner.' },\n { command: 'planner', weight: 1, text: \"Tip: Use /planner to pick the planner's harness, model and effort.\" },\n { command: 'runners', weight: 1, text: 'Tip: Use /runners to turn runners on or off.' },\n { command: 'settings', weight: 1, text: 'Tip: Use /settings for autonomy, supervisor, merging, autorun and more.' },\n { command: 'help', weight: 1, text: 'Tip: Use /help to list every command.' },\n];\n\n/**\n * One cycle of `tips`, each appearing exactly its weight times. Heavier tips\n * take their slots first, at the midpoints of equal shares of the free slots, so\n * raising a weight spreads it out instead of leaving it to run together at the\n * end of the cycle; where a tip outnumbers all the others, the touches it\n * cannot avoid are spread as evenly as the counts allow. The cycle starts on\n * the heaviest tip, so the first seq is the one the table weights most.\n */\nexport function tipCycle(tips: readonly ComposerTip[]): ComposerTip[] {\n const total = tips.reduce((sum, tip) => sum + Math.max(0, tip.weight), 0);\n if (total === 0) return [];\n const slots = new Array<ComposerTip | undefined>(total).fill(undefined);\n const order = tips\n .map((tip, index) => ({ tip, index }))\n .filter(({ tip }) => tip.weight > 0)\n .sort((a, b) => b.tip.weight - a.tip.weight || a.index - b.index);\n for (const { tip } of order) {\n const free = slots.flatMap((slot, at) => (slot === undefined ? [at] : []));\n for (let k = 0; k < tip.weight; k++) {\n slots[free[Math.floor(((k + 0.5) * free.length) / tip.weight)]] = tip;\n }\n }\n const cycle = slots.filter((tip): tip is ComposerTip => tip !== undefined);\n const start = cycle.indexOf(order[0].tip);\n return [...cycle.slice(start), ...cycle.slice(0, start)];\n}\n\n/**\n * The tip for the `seq`-th time the composer has been empty, among those for\n * the commands the surface answers, or null when it answers none of them. The\n * same `seq` always gives the same tip, so the surface decides when a new one\n * shows by when it moves `seq` on, and its rendering stays a function of state.\n */\nexport function composerTip(seq: number, answers: ReadonlySet<string>): string | null {\n const cycle = tipCycle(COMPOSER_TIPS.filter((tip) => answers.has(tip.command)));\n if (cycle.length === 0) return null;\n return cycle[((seq % cycle.length) + cycle.length) % cycle.length].text;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAeO,IAAM,gBAAwC;AAAA;AAAA,EAEnD,EAAE,SAAS,aAAa,QAAQ,GAAG,MAAM,4EAA4E;AAAA,EACrH,EAAE,SAAS,WAAW,QAAQ,GAAG,MAAM,qEAAqE;AAAA,EAC5G,EAAE,SAAS,WAAW,QAAQ,GAAG,MAAM,+CAA+C;AAAA,EACtF,EAAE,SAAS,YAAY,QAAQ,GAAG,MAAM,0EAA0E;AAAA,EAClH,EAAE,SAAS,QAAQ,QAAQ,GAAG,MAAM,wCAAwC;AAC9E;AAUO,SAAS,SAAS,MAA6C;AACpE,QAAM,QAAQ,KAAK,OAAO,CAAC,KAAK,QAAQ,MAAM,KAAK,IAAI,GAAG,IAAI,MAAM,GAAG,CAAC;AACxE,MAAI,UAAU,EAAG,QAAO,CAAC;AACzB,QAAM,QAAQ,IAAI,MAA+B,KAAK,EAAE,KAAK,MAAS;AACtE,QAAM,QAAQ,KACX,IAAI,CAAC,KAAK,WAAW,EAAE,KAAK,MAAM,EAAE,EACpC,OAAO,CAAC,EAAE,IAAI,MAAM,IAAI,SAAS,CAAC,EAClC,KAAK,CAAC,GAAG,MAAM,EAAE,IAAI,SAAS,EAAE,IAAI,UAAU,EAAE,QAAQ,EAAE,KAAK;AAClE,aAAW,EAAE,IAAI,KAAK,OAAO;AAC3B,UAAM,OAAO,MAAM,QAAQ,CAAC,MAAM,OAAQ,SAAS,SAAY,CAAC,EAAE,IAAI,CAAC,CAAE;AACzE,aAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,YAAM,KAAK,KAAK,OAAQ,IAAI,OAAO,KAAK,SAAU,IAAI,MAAM,CAAC,CAAC,IAAI;AAAA,IACpE;AAAA,EACF;AACA,QAAM,QAAQ,MAAM,OAAO,CAAC,QAA4B,QAAQ,MAAS;AACzE,QAAM,QAAQ,MAAM,QAAQ,MAAM,CAAC,EAAE,GAAG;AACxC,SAAO,CAAC,GAAG,MAAM,MAAM,KAAK,GAAG,GAAG,MAAM,MAAM,GAAG,KAAK,CAAC;AACzD;AAQO,SAAS,YAAY,KAAa,SAA6C;AACpF,QAAM,QAAQ,SAAS,cAAc,OAAO,CAAC,QAAQ,QAAQ,IAAI,IAAI,OAAO,CAAC,CAAC;AAC9E,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,SAAO,OAAQ,MAAM,MAAM,SAAU,MAAM,UAAU,MAAM,MAAM,EAAE;AACrE;","names":[]}
|