@oh-my-pi/pi-coding-agent 15.5.15 → 15.7.0
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 +81 -0
- package/dist/types/capability/rule-buckets.d.ts +30 -0
- package/dist/types/capability/rule.d.ts +7 -0
- package/dist/types/cli/classify-install-target.d.ts +0 -10
- package/dist/types/cli/completion-gen.d.ts +80 -0
- package/dist/types/cli/initial-message.d.ts +1 -1
- package/dist/types/cli/tiny-models-cli.d.ts +9 -0
- package/dist/types/commands/complete.d.ts +6 -0
- package/dist/types/commands/completions.d.ts +13 -0
- package/dist/types/commands/setup.d.ts +10 -1
- package/dist/types/commands/tiny-models.d.ts +22 -0
- package/dist/types/commit/analysis/conventional.d.ts +1 -1
- package/dist/types/commit/analysis/summary.d.ts +1 -1
- package/dist/types/commit/changelog/generate.d.ts +1 -1
- package/dist/types/commit/changelog/index.d.ts +2 -2
- package/dist/types/commit/map-reduce/map-phase.d.ts +1 -1
- package/dist/types/commit/map-reduce/reduce-phase.d.ts +1 -1
- package/dist/types/config/model-id-affixes.d.ts +10 -0
- package/dist/types/config/settings-schema.d.ts +402 -17
- package/dist/types/discovery/builtin-defaults.d.ts +1 -0
- package/dist/types/discovery/builtin-rules/index.d.ts +7 -0
- package/dist/types/discovery/helpers.d.ts +1 -1
- package/dist/types/discovery/index.d.ts +1 -0
- package/dist/types/discovery/substitute-plugin-root.d.ts +0 -4
- package/dist/types/edit/hashline/block-resolver.d.ts +9 -0
- package/dist/types/edit/hashline/index.d.ts +1 -0
- package/dist/types/eval/js/shared/rewrite-imports.d.ts +16 -1
- package/dist/types/eval/py/kernel.d.ts +3 -0
- package/dist/types/eval/py/runtime.d.ts +11 -1
- package/dist/types/export/html/template.generated.d.ts +1 -1
- package/dist/types/internal-urls/agent-protocol.d.ts +2 -1
- package/dist/types/internal-urls/artifact-protocol.d.ts +2 -1
- package/dist/types/internal-urls/local-protocol.d.ts +2 -1
- package/dist/types/internal-urls/memory-protocol.d.ts +2 -1
- package/dist/types/internal-urls/omp-protocol.d.ts +2 -1
- package/dist/types/internal-urls/router.d.ts +8 -1
- package/dist/types/internal-urls/rule-protocol.d.ts +2 -1
- package/dist/types/internal-urls/skill-protocol.d.ts +2 -1
- package/dist/types/internal-urls/types.d.ts +26 -0
- package/dist/types/main.d.ts +1 -0
- package/dist/types/memory-backend/index.d.ts +1 -0
- package/dist/types/memory-backend/resolve.d.ts +2 -1
- package/dist/types/memory-backend/types.d.ts +7 -1
- package/dist/types/mnemosyne/backend.d.ts +4 -0
- package/dist/types/mnemosyne/config.d.ts +29 -0
- package/dist/types/mnemosyne/index.d.ts +3 -0
- package/dist/types/mnemosyne/state.d.ts +72 -0
- package/dist/types/modes/components/custom-editor.d.ts +2 -3
- package/dist/types/modes/components/hook-selector.d.ts +27 -0
- package/dist/types/modes/components/index.d.ts +2 -0
- package/dist/types/modes/components/segment-track.d.ts +22 -0
- package/dist/types/modes/components/status-line/context-thresholds.d.ts +6 -0
- package/dist/types/modes/components/tiny-title-download-progress.d.ts +11 -0
- package/dist/types/modes/components/welcome.d.ts +22 -0
- package/dist/types/modes/controllers/extension-ui-controller.d.ts +4 -1
- package/dist/types/modes/gradient-highlight.d.ts +23 -0
- package/dist/types/modes/interactive-mode.d.ts +7 -4
- package/dist/types/modes/internal-url-autocomplete.d.ts +43 -0
- package/dist/types/modes/orchestrate.d.ts +10 -0
- package/dist/types/modes/setup-wizard/index.d.ts +16 -0
- package/dist/types/modes/setup-wizard/scenes/glyph.d.ts +2 -0
- package/dist/types/modes/setup-wizard/scenes/outro.d.ts +2 -0
- package/dist/types/modes/setup-wizard/scenes/providers.d.ts +2 -0
- package/dist/types/modes/setup-wizard/scenes/sign-in.d.ts +19 -0
- package/dist/types/modes/setup-wizard/scenes/splash.d.ts +11 -0
- package/dist/types/modes/setup-wizard/scenes/theme.d.ts +2 -0
- package/dist/types/modes/setup-wizard/scenes/types.d.ts +43 -0
- package/dist/types/modes/setup-wizard/scenes/web-search.d.ts +19 -0
- package/dist/types/modes/setup-wizard/wizard-overlay.d.ts +14 -0
- package/dist/types/modes/theme/defaults/index.d.ts +8406 -8406
- package/dist/types/modes/theme/shimmer.d.ts +2 -0
- package/dist/types/modes/theme/theme.d.ts +11 -0
- package/dist/types/modes/types.d.ts +5 -1
- package/dist/types/modes/ultrathink.d.ts +3 -3
- package/dist/types/modes/utils/keybinding-matchers.d.ts +5 -0
- package/dist/types/sdk.d.ts +3 -0
- package/dist/types/session/agent-session.d.ts +33 -0
- package/dist/types/system-prompt.d.ts +2 -0
- package/dist/types/task/executor.d.ts +2 -0
- package/dist/types/task/render.d.ts +5 -1
- package/dist/types/tiny/device.d.ts +78 -0
- package/dist/types/tiny/dtype.d.ts +85 -0
- package/dist/types/tiny/models.d.ts +185 -0
- package/dist/types/tiny/text.d.ts +19 -0
- package/dist/types/tiny/title-client.d.ts +32 -0
- package/dist/types/tiny/title-protocol.d.ts +74 -0
- package/dist/types/tiny/worker.d.ts +2 -0
- package/dist/types/tools/bash.d.ts +3 -2
- package/dist/types/tools/eval.d.ts +1 -1
- package/dist/types/tools/index.d.ts +7 -4
- package/dist/types/tools/memory-edit.d.ts +40 -0
- package/dist/types/tools/{hindsight-recall.d.ts → memory-recall.d.ts} +6 -6
- package/dist/types/tools/{hindsight-reflect.d.ts → memory-reflect.d.ts} +6 -6
- package/dist/types/tools/memory-render.d.ts +60 -0
- package/dist/types/tools/{hindsight-retain.d.ts → memory-retain.d.ts} +6 -6
- package/dist/types/tools/todo-write.d.ts +8 -0
- package/dist/types/tools/tool-result.d.ts +2 -0
- package/dist/types/tui/code-cell.d.ts +2 -0
- package/dist/types/tui/output-block.d.ts +17 -0
- package/dist/types/utils/title-generator.d.ts +3 -0
- package/package.json +18 -14
- package/scripts/build-binary.ts +1 -0
- package/src/capability/rule-buckets.ts +64 -0
- package/src/capability/rule.ts +8 -0
- package/src/cli/completion-gen.ts +550 -0
- package/src/cli/setup-cli.ts +5 -3
- package/src/cli/tiny-models-cli.ts +127 -0
- package/src/cli-commands.ts +3 -0
- package/src/cli.ts +9 -15
- package/src/commands/complete.ts +66 -0
- package/src/commands/completions.ts +60 -0
- package/src/commands/setup.ts +29 -4
- package/src/commands/tiny-models.ts +36 -0
- package/src/config/model-equivalence.ts +43 -2
- package/src/config/model-id-affixes.ts +64 -0
- package/src/config/model-registry.ts +84 -10
- package/src/config/settings-schema.ts +275 -15
- package/src/discovery/builtin-defaults.ts +39 -0
- package/src/discovery/builtin-rules/index.ts +48 -0
- package/src/discovery/builtin-rules/rs-box-leak.md +48 -0
- package/src/discovery/builtin-rules/rs-future-prelude.md +23 -0
- package/src/discovery/builtin-rules/rs-lazylock.md +51 -0
- package/src/discovery/builtin-rules/rs-match-ergonomics.md +67 -0
- package/src/discovery/builtin-rules/rs-parking-lot.md +44 -0
- package/src/discovery/builtin-rules/rs-result-type.md +19 -0
- package/src/discovery/builtin-rules/ts-bare-catch.md +38 -0
- package/src/discovery/builtin-rules/ts-import-type.md +42 -0
- package/src/discovery/builtin-rules/ts-no-any.md +56 -0
- package/src/discovery/builtin-rules/ts-no-dynamic-import.md +39 -0
- package/src/discovery/builtin-rules/ts-no-return-type.md +45 -0
- package/src/discovery/builtin-rules/ts-no-tiny-functions.md +50 -0
- package/src/discovery/builtin-rules/ts-promise-with-resolvers.md +65 -0
- package/src/discovery/builtin-rules/ts-set-map.md +28 -0
- package/src/discovery/index.ts +1 -0
- package/src/edit/hashline/block-resolver.ts +14 -0
- package/src/edit/hashline/diff.ts +9 -8
- package/src/edit/hashline/execute.ts +2 -1
- package/src/edit/hashline/index.ts +1 -0
- package/src/eval/__tests__/shared-executors.test.ts +36 -0
- package/src/eval/js/shared/local-module-loader.ts +13 -1
- package/src/eval/js/shared/rewrite-imports.ts +31 -26
- package/src/eval/py/kernel.ts +37 -15
- package/src/eval/py/runtime.ts +57 -28
- package/src/export/html/template.generated.ts +1 -1
- package/src/export/html/template.js +0 -12
- package/src/export/ttsr.ts +2 -0
- package/src/internal-urls/agent-protocol.ts +18 -1
- package/src/internal-urls/artifact-protocol.ts +19 -1
- package/src/internal-urls/docs-index.generated.ts +8 -7
- package/src/internal-urls/local-protocol.ts +14 -1
- package/src/internal-urls/memory-protocol.ts +6 -1
- package/src/internal-urls/omp-protocol.ts +5 -1
- package/src/internal-urls/router.ts +20 -1
- package/src/internal-urls/rule-protocol.ts +8 -1
- package/src/internal-urls/skill-protocol.ts +8 -1
- package/src/internal-urls/types.ts +27 -0
- package/src/lsp/render.ts +1 -1
- package/src/main.ts +18 -1
- package/src/mcp/oauth-flow.ts +2 -2
- package/src/memory-backend/index.ts +1 -0
- package/src/memory-backend/resolve.ts +4 -1
- package/src/memory-backend/types.ts +8 -1
- package/src/mnemosyne/backend.ts +374 -0
- package/src/mnemosyne/config.ts +160 -0
- package/src/mnemosyne/index.ts +3 -0
- package/src/mnemosyne/state.ts +548 -0
- package/src/modes/acp/acp-agent.ts +11 -6
- package/src/modes/components/agent-dashboard.ts +4 -4
- package/src/modes/components/custom-editor.ts +3 -2
- package/src/modes/components/diff.ts +2 -2
- package/src/modes/components/extensions/extension-list.ts +3 -2
- package/src/modes/components/footer.ts +5 -6
- package/src/modes/components/history-search.ts +3 -3
- package/src/modes/components/hook-selector.ts +92 -8
- package/src/modes/components/index.ts +2 -0
- package/src/modes/components/mcp-add-wizard.ts +3 -3
- package/src/modes/components/model-selector.ts +5 -4
- package/src/modes/components/oauth-selector.ts +3 -3
- package/src/modes/components/segment-track.ts +52 -0
- package/src/modes/components/session-observer-overlay.ts +19 -13
- package/src/modes/components/session-selector.ts +3 -3
- package/src/modes/components/settings-defs.ts +7 -0
- package/src/modes/components/status-line/context-thresholds.ts +11 -0
- package/src/modes/components/status-line/segments.ts +2 -2
- package/src/modes/components/tiny-title-download-progress.ts +90 -0
- package/src/modes/components/tips.txt +13 -0
- package/src/modes/components/tool-execution.ts +72 -4
- package/src/modes/components/tree-selector.ts +3 -3
- package/src/modes/components/user-message-selector.ts +3 -3
- package/src/modes/components/welcome.ts +102 -43
- package/src/modes/controllers/command-controller.ts +16 -1
- package/src/modes/controllers/extension-ui-controller.ts +3 -1
- package/src/modes/controllers/input-controller.ts +69 -21
- package/src/modes/gradient-highlight.ts +70 -0
- package/src/modes/interactive-mode.ts +75 -114
- package/src/modes/internal-url-autocomplete.ts +143 -0
- package/src/modes/orchestrate.ts +36 -0
- package/src/modes/prompt-action-autocomplete.ts +12 -0
- package/src/modes/setup-wizard/index.ts +88 -0
- package/src/modes/setup-wizard/scenes/glyph.ts +96 -0
- package/src/modes/setup-wizard/scenes/outro.ts +35 -0
- package/src/modes/setup-wizard/scenes/providers.ts +69 -0
- package/src/modes/setup-wizard/scenes/sign-in.ts +193 -0
- package/src/modes/setup-wizard/scenes/splash.ts +201 -0
- package/src/modes/setup-wizard/scenes/theme.ts +299 -0
- package/src/modes/setup-wizard/scenes/types.ts +48 -0
- package/src/modes/setup-wizard/scenes/web-search.ts +128 -0
- package/src/modes/setup-wizard/wizard-overlay.ts +275 -0
- package/src/modes/theme/shimmer.ts +5 -0
- package/src/modes/theme/theme.ts +44 -20
- package/src/modes/types.ts +6 -1
- package/src/modes/ultrathink.ts +9 -53
- package/src/modes/utils/keybinding-matchers.ts +11 -0
- package/src/prompts/system/memory-consolidation-system.md +8 -0
- package/src/prompts/system/memory-extraction-system.md +26 -0
- package/src/prompts/{commands/orchestrate.md → system/orchestrate-notice.md} +6 -17
- package/src/prompts/system/system-prompt.md +2 -0
- package/src/prompts/system/tiny-title-system.md +8 -0
- package/src/prompts/tools/memory-edit.md +8 -0
- package/src/prompts/tools/read.md +4 -0
- package/src/prompts/tools/task.md +4 -7
- package/src/sdk.ts +13 -21
- package/src/session/agent-session.ts +128 -44
- package/src/slash-commands/builtin-registry.ts +18 -1
- package/src/system-prompt.ts +4 -0
- package/src/task/commands.ts +1 -5
- package/src/task/executor.ts +8 -0
- package/src/task/index.ts +2 -0
- package/src/task/render.ts +69 -26
- package/src/tiny/device.ts +117 -0
- package/src/tiny/dtype.ts +101 -0
- package/src/tiny/models.ts +218 -0
- package/src/tiny/text.ts +54 -0
- package/src/tiny/title-client.ts +395 -0
- package/src/tiny/title-protocol.ts +51 -0
- package/src/tiny/worker.ts +587 -0
- package/src/tools/bash.ts +74 -29
- package/src/tools/browser/tab-worker.ts +1 -1
- package/src/tools/eval.ts +9 -4
- package/src/tools/index.ts +17 -22
- package/src/tools/memory-edit.ts +59 -0
- package/src/tools/memory-recall.ts +100 -0
- package/src/tools/memory-reflect.ts +88 -0
- package/src/tools/memory-render.ts +185 -0
- package/src/tools/memory-retain.ts +91 -0
- package/src/tools/read.ts +1 -0
- package/src/tools/renderers.ts +4 -2
- package/src/tools/todo-write.ts +128 -29
- package/src/tools/tool-result.ts +8 -0
- package/src/tui/code-cell.ts +6 -1
- package/src/tui/output-block.ts +199 -38
- package/src/utils/title-generator.ts +115 -13
- package/dist/types/tools/recipe/index.d.ts +0 -46
- package/dist/types/tools/recipe/render.d.ts +0 -36
- package/dist/types/tools/recipe/runner.d.ts +0 -60
- package/dist/types/tools/recipe/runners/cargo.d.ts +0 -16
- package/dist/types/tools/recipe/runners/index.d.ts +0 -2
- package/dist/types/tools/recipe/runners/just.d.ts +0 -2
- package/dist/types/tools/recipe/runners/make.d.ts +0 -2
- package/dist/types/tools/recipe/runners/pkg.d.ts +0 -2
- package/dist/types/tools/recipe/runners/task.d.ts +0 -2
- package/src/prompts/tools/recipe.md +0 -16
- package/src/tools/hindsight-recall.ts +0 -69
- package/src/tools/hindsight-reflect.ts +0 -58
- package/src/tools/hindsight-retain.ts +0 -57
- package/src/tools/recipe/index.ts +0 -81
- package/src/tools/recipe/render.ts +0 -19
- package/src/tools/recipe/runner.ts +0 -219
- package/src/tools/recipe/runners/cargo.ts +0 -131
- package/src/tools/recipe/runners/index.ts +0 -8
- package/src/tools/recipe/runners/just.ts +0 -73
- package/src/tools/recipe/runners/make.ts +0 -101
- package/src/tools/recipe/runners/pkg.ts +0 -167
- package/src/tools/recipe/runners/task.ts +0 -72
|
@@ -1,6 +1,24 @@
|
|
|
1
1
|
import { THINKING_EFFORTS } from "@oh-my-pi/pi-ai";
|
|
2
2
|
import { TASK_SIMPLE_MODES } from "../task/simple-mode";
|
|
3
3
|
import { getThinkingLevelMetadata } from "../thinking";
|
|
4
|
+
import {
|
|
5
|
+
TINY_MODEL_DEVICE_DEFAULT,
|
|
6
|
+
TINY_MODEL_DEVICE_SETTING_OPTIONS,
|
|
7
|
+
TINY_MODEL_DEVICE_SETTING_VALUES,
|
|
8
|
+
} from "../tiny/device";
|
|
9
|
+
import {
|
|
10
|
+
TINY_MODEL_DTYPE_DEFAULT,
|
|
11
|
+
TINY_MODEL_DTYPE_SETTING_OPTIONS,
|
|
12
|
+
TINY_MODEL_DTYPE_SETTING_VALUES,
|
|
13
|
+
} from "../tiny/dtype";
|
|
14
|
+
import {
|
|
15
|
+
ONLINE_MEMORY_MODEL_KEY,
|
|
16
|
+
ONLINE_TINY_TITLE_MODEL_KEY,
|
|
17
|
+
TINY_MEMORY_MODEL_OPTIONS,
|
|
18
|
+
TINY_MEMORY_MODEL_VALUES,
|
|
19
|
+
TINY_TITLE_MODEL_OPTIONS,
|
|
20
|
+
TINY_TITLE_MODEL_VALUES,
|
|
21
|
+
} from "../tiny/models";
|
|
4
22
|
import { EDIT_MODES } from "../utils/edit-mode";
|
|
5
23
|
|
|
6
24
|
/** Unified settings schema - single source of truth for all settings.
|
|
@@ -235,6 +253,7 @@ export const SETTINGS_SCHEMA = {
|
|
|
235
253
|
// General settings (no UI)
|
|
236
254
|
// ────────────────────────────────────────────────────────────────────────
|
|
237
255
|
lastChangelogVersion: { type: "string", default: undefined },
|
|
256
|
+
setupVersion: { type: "number", default: 0 },
|
|
238
257
|
|
|
239
258
|
// Auth broker — credentials proxied through a remote `omp auth-broker serve`
|
|
240
259
|
// host. Hidden from the UI; populate via env vars or hand-edited config.yml.
|
|
@@ -991,6 +1010,16 @@ export const SETTINGS_SCHEMA = {
|
|
|
991
1010
|
},
|
|
992
1011
|
},
|
|
993
1012
|
|
|
1013
|
+
"startup.setupWizard": {
|
|
1014
|
+
type: "boolean",
|
|
1015
|
+
default: true,
|
|
1016
|
+
ui: {
|
|
1017
|
+
tab: "interaction",
|
|
1018
|
+
label: "Setup Wizard",
|
|
1019
|
+
description: "Show newly added onboarding steps once per setup version",
|
|
1020
|
+
},
|
|
1021
|
+
},
|
|
1022
|
+
|
|
994
1023
|
"startup.checkUpdate": {
|
|
995
1024
|
type: "boolean",
|
|
996
1025
|
default: true,
|
|
@@ -1292,23 +1321,192 @@ export const SETTINGS_SCHEMA = {
|
|
|
1292
1321
|
"memories.summaryInjectionTokenLimit": { type: "number", default: 5000 },
|
|
1293
1322
|
|
|
1294
1323
|
// Memory backend selector — picks between local memories pipeline,
|
|
1295
|
-
// Hindsight remote memory, or off. Legacy
|
|
1296
|
-
// the local backend; see config/settings.ts
|
|
1324
|
+
// Mnemosyne local SQLite, Hindsight remote memory, or off. Legacy
|
|
1325
|
+
// `memories.enabled` keeps gating the local backend; see config/settings.ts
|
|
1326
|
+
// migration for details.
|
|
1297
1327
|
"memory.backend": {
|
|
1298
1328
|
type: "enum",
|
|
1299
|
-
values: ["off", "local", "hindsight"] as const,
|
|
1329
|
+
values: ["off", "local", "hindsight", "mnemosyne"] as const,
|
|
1300
1330
|
default: "off",
|
|
1301
1331
|
ui: {
|
|
1302
1332
|
tab: "memory",
|
|
1303
1333
|
label: "Memory Backend",
|
|
1304
|
-
description: "Off, local
|
|
1334
|
+
description: "Off, local summary pipeline, Mnemosyne SQLite, or Hindsight remote memory",
|
|
1305
1335
|
options: [
|
|
1306
1336
|
{ value: "off", label: "Off", description: "No memory subsystem runs" },
|
|
1307
1337
|
{ value: "local", label: "Local", description: "Local rollout summarisation pipeline (memory_summary.md)" },
|
|
1308
1338
|
{ value: "hindsight", label: "Hindsight", description: "Vectorize Hindsight remote memory service" },
|
|
1339
|
+
{
|
|
1340
|
+
value: "mnemosyne",
|
|
1341
|
+
label: "Mnemosyne",
|
|
1342
|
+
description: "Local SQLite recall/retain backend with optional embeddings",
|
|
1343
|
+
},
|
|
1344
|
+
],
|
|
1345
|
+
},
|
|
1346
|
+
},
|
|
1347
|
+
|
|
1348
|
+
// Mnemosyne local SQLite memory backend.
|
|
1349
|
+
"mnemosyne.dbPath": {
|
|
1350
|
+
type: "string",
|
|
1351
|
+
default: undefined,
|
|
1352
|
+
ui: {
|
|
1353
|
+
tab: "memory",
|
|
1354
|
+
label: "Mnemosyne DB Path",
|
|
1355
|
+
description: "Optional SQLite DB path. Defaults to the agent memories directory.",
|
|
1356
|
+
condition: "mnemosyneActive",
|
|
1357
|
+
},
|
|
1358
|
+
},
|
|
1359
|
+
"mnemosyne.bank": {
|
|
1360
|
+
type: "string",
|
|
1361
|
+
default: undefined,
|
|
1362
|
+
ui: {
|
|
1363
|
+
tab: "memory",
|
|
1364
|
+
label: "Mnemosyne Bank",
|
|
1365
|
+
description: "Optional shared bank base name. Per-project modes derive project-local banks from it.",
|
|
1366
|
+
condition: "mnemosyneActive",
|
|
1367
|
+
},
|
|
1368
|
+
},
|
|
1369
|
+
"mnemosyne.scoping": {
|
|
1370
|
+
type: "enum",
|
|
1371
|
+
values: ["global", "per-project", "per-project-tagged"] as const,
|
|
1372
|
+
default: "per-project",
|
|
1373
|
+
ui: {
|
|
1374
|
+
tab: "memory",
|
|
1375
|
+
label: "Mnemosyne Scoping",
|
|
1376
|
+
description:
|
|
1377
|
+
"global = one shared bank; per-project = isolated bank per cwd; per-project-tagged = project-local writes plus global recall visibility",
|
|
1378
|
+
options: [
|
|
1379
|
+
{
|
|
1380
|
+
value: "global",
|
|
1381
|
+
label: "Global",
|
|
1382
|
+
description: "One shared Mnemosyne bank for every project",
|
|
1383
|
+
},
|
|
1384
|
+
{
|
|
1385
|
+
value: "per-project",
|
|
1386
|
+
label: "Per project",
|
|
1387
|
+
description: "Project-local Mnemosyne bank per cwd basename",
|
|
1388
|
+
},
|
|
1389
|
+
{
|
|
1390
|
+
value: "per-project-tagged",
|
|
1391
|
+
label: "Per project (tagged)",
|
|
1392
|
+
description: "Write to a project-local bank but merge project + shared recall results",
|
|
1393
|
+
},
|
|
1394
|
+
],
|
|
1395
|
+
condition: "mnemosyneActive",
|
|
1396
|
+
},
|
|
1397
|
+
},
|
|
1398
|
+
"mnemosyne.autoRecall": {
|
|
1399
|
+
type: "boolean",
|
|
1400
|
+
default: true,
|
|
1401
|
+
ui: {
|
|
1402
|
+
tab: "memory",
|
|
1403
|
+
label: "Mnemosyne Auto Recall",
|
|
1404
|
+
description: "Recall local memories into the first turn of each session",
|
|
1405
|
+
condition: "mnemosyneActive",
|
|
1406
|
+
},
|
|
1407
|
+
},
|
|
1408
|
+
"mnemosyne.autoRetain": {
|
|
1409
|
+
type: "boolean",
|
|
1410
|
+
default: true,
|
|
1411
|
+
ui: {
|
|
1412
|
+
tab: "memory",
|
|
1413
|
+
label: "Mnemosyne Auto Retain",
|
|
1414
|
+
description: "Retain completed conversation turns into local Mnemosyne memory",
|
|
1415
|
+
condition: "mnemosyneActive",
|
|
1416
|
+
},
|
|
1417
|
+
},
|
|
1418
|
+
"mnemosyne.noEmbeddings": {
|
|
1419
|
+
type: "boolean",
|
|
1420
|
+
default: false,
|
|
1421
|
+
ui: {
|
|
1422
|
+
tab: "memory",
|
|
1423
|
+
label: "Mnemosyne Disable Embeddings",
|
|
1424
|
+
description: "Force deterministic FTS-only recall instead of vector embeddings",
|
|
1425
|
+
condition: "mnemosyneActive",
|
|
1426
|
+
},
|
|
1427
|
+
},
|
|
1428
|
+
"mnemosyne.embeddingModel": {
|
|
1429
|
+
type: "string",
|
|
1430
|
+
default: undefined,
|
|
1431
|
+
ui: {
|
|
1432
|
+
tab: "memory",
|
|
1433
|
+
label: "Mnemosyne Embedding Model",
|
|
1434
|
+
description: "Optional embedding model override passed to Mnemosyne",
|
|
1435
|
+
condition: "mnemosyneActive",
|
|
1436
|
+
},
|
|
1437
|
+
},
|
|
1438
|
+
"mnemosyne.embeddingApiUrl": {
|
|
1439
|
+
type: "string",
|
|
1440
|
+
default: undefined,
|
|
1441
|
+
ui: {
|
|
1442
|
+
tab: "memory",
|
|
1443
|
+
label: "Mnemosyne Embedding API URL",
|
|
1444
|
+
description: "Optional OpenAI-compatible embedding endpoint passed to Mnemosyne",
|
|
1445
|
+
condition: "mnemosyneActive",
|
|
1446
|
+
},
|
|
1447
|
+
},
|
|
1448
|
+
"mnemosyne.embeddingApiKey": {
|
|
1449
|
+
type: "string",
|
|
1450
|
+
default: undefined,
|
|
1451
|
+
ui: {
|
|
1452
|
+
tab: "memory",
|
|
1453
|
+
label: "Mnemosyne Embedding API Key",
|
|
1454
|
+
description: "Optional embedding API key passed to Mnemosyne",
|
|
1455
|
+
condition: "mnemosyneActive",
|
|
1456
|
+
},
|
|
1457
|
+
},
|
|
1458
|
+
"mnemosyne.llmMode": {
|
|
1459
|
+
type: "enum",
|
|
1460
|
+
values: ["none", "smol", "remote"] as const,
|
|
1461
|
+
default: "smol",
|
|
1462
|
+
ui: {
|
|
1463
|
+
tab: "memory",
|
|
1464
|
+
label: "Mnemosyne LLM Mode",
|
|
1465
|
+
description: "Use no LLM, the configured smol model, or a remote OpenAI-compatible endpoint",
|
|
1466
|
+
condition: "mnemosyneActive",
|
|
1467
|
+
options: [
|
|
1468
|
+
{ value: "none", label: "None", description: "Disable Mnemosyne LLM-backed extraction" },
|
|
1469
|
+
{ value: "smol", label: "Smol", description: "Use the configured pi-ai smol model" },
|
|
1470
|
+
{ value: "remote", label: "Remote", description: "Use the Mnemosyne remote LLM settings below" },
|
|
1309
1471
|
],
|
|
1310
1472
|
},
|
|
1311
1473
|
},
|
|
1474
|
+
"mnemosyne.llmBaseUrl": {
|
|
1475
|
+
type: "string",
|
|
1476
|
+
default: undefined,
|
|
1477
|
+
ui: {
|
|
1478
|
+
tab: "memory",
|
|
1479
|
+
label: "Mnemosyne LLM Base URL",
|
|
1480
|
+
description: "Optional OpenAI-compatible LLM endpoint for Mnemosyne remote mode",
|
|
1481
|
+
condition: "mnemosyneActive",
|
|
1482
|
+
},
|
|
1483
|
+
},
|
|
1484
|
+
"mnemosyne.llmApiKey": {
|
|
1485
|
+
type: "string",
|
|
1486
|
+
default: undefined,
|
|
1487
|
+
ui: {
|
|
1488
|
+
tab: "memory",
|
|
1489
|
+
label: "Mnemosyne LLM API Key",
|
|
1490
|
+
description: "Optional LLM API key for Mnemosyne remote mode",
|
|
1491
|
+
condition: "mnemosyneActive",
|
|
1492
|
+
},
|
|
1493
|
+
},
|
|
1494
|
+
"mnemosyne.llmModel": {
|
|
1495
|
+
type: "string",
|
|
1496
|
+
default: undefined,
|
|
1497
|
+
ui: {
|
|
1498
|
+
tab: "memory",
|
|
1499
|
+
label: "Mnemosyne LLM Model",
|
|
1500
|
+
description: "Optional LLM model name for Mnemosyne remote mode",
|
|
1501
|
+
condition: "mnemosyneActive",
|
|
1502
|
+
},
|
|
1503
|
+
},
|
|
1504
|
+
"mnemosyne.retainEveryNTurns": { type: "number", default: 4 },
|
|
1505
|
+
"mnemosyne.recallLimit": { type: "number", default: 8 },
|
|
1506
|
+
"mnemosyne.recallContextTurns": { type: "number", default: 3 },
|
|
1507
|
+
"mnemosyne.recallMaxQueryChars": { type: "number", default: 4000 },
|
|
1508
|
+
"mnemosyne.injectionTokenLimit": { type: "number", default: 5000 },
|
|
1509
|
+
"mnemosyne.debug": { type: "boolean", default: false },
|
|
1312
1510
|
|
|
1313
1511
|
// Hindsight (https://hindsight.vectorize.io)
|
|
1314
1512
|
"hindsight.apiUrl": {
|
|
@@ -1517,6 +1715,26 @@ export const SETTINGS_SCHEMA = {
|
|
|
1517
1715
|
},
|
|
1518
1716
|
},
|
|
1519
1717
|
|
|
1718
|
+
"ttsr.builtinRules": {
|
|
1719
|
+
type: "boolean",
|
|
1720
|
+
default: true,
|
|
1721
|
+
ui: {
|
|
1722
|
+
tab: "context",
|
|
1723
|
+
label: "Builtin Rules",
|
|
1724
|
+
description: "Load the default rules shipped with the agent (override individually with ttsr.disabledRules)",
|
|
1725
|
+
},
|
|
1726
|
+
},
|
|
1727
|
+
|
|
1728
|
+
"ttsr.disabledRules": {
|
|
1729
|
+
type: "array",
|
|
1730
|
+
default: [] as string[],
|
|
1731
|
+
ui: {
|
|
1732
|
+
tab: "context",
|
|
1733
|
+
label: "Disabled Rules",
|
|
1734
|
+
description: "Rule names to ignore entirely (applies to bundled defaults and your own rules)",
|
|
1735
|
+
},
|
|
1736
|
+
},
|
|
1737
|
+
|
|
1520
1738
|
// ────────────────────────────────────────────────────────────────────────
|
|
1521
1739
|
// Editing
|
|
1522
1740
|
// ────────────────────────────────────────────────────────────────────────
|
|
@@ -1848,7 +2066,7 @@ export const SETTINGS_SCHEMA = {
|
|
|
1848
2066
|
value: "write",
|
|
1849
2067
|
label: "Write",
|
|
1850
2068
|
description:
|
|
1851
|
-
"Auto-approve read-only and write tools; require confirmation for exec tools such as bash, eval, browser, task,
|
|
2069
|
+
"Auto-approve read-only and write tools; require confirmation for exec tools such as bash, eval, browser, task, and ssh.",
|
|
1852
2070
|
},
|
|
1853
2071
|
{
|
|
1854
2072
|
value: "yolo",
|
|
@@ -2026,16 +2244,6 @@ export const SETTINGS_SCHEMA = {
|
|
|
2026
2244
|
description: "Enable the tts tool for xAI Grok Voice speech synthesis",
|
|
2027
2245
|
},
|
|
2028
2246
|
},
|
|
2029
|
-
"recipe.enabled": {
|
|
2030
|
-
type: "boolean",
|
|
2031
|
-
default: true,
|
|
2032
|
-
ui: {
|
|
2033
|
-
tab: "tools",
|
|
2034
|
-
label: "Recipe",
|
|
2035
|
-
description:
|
|
2036
|
-
"Enable the recipe tool when a justfile / package.json / Cargo.toml / Makefile / Taskfile is present",
|
|
2037
|
-
},
|
|
2038
|
-
},
|
|
2039
2247
|
|
|
2040
2248
|
"inspect_image.enabled": {
|
|
2041
2249
|
type: "boolean",
|
|
@@ -2727,6 +2935,54 @@ export const SETTINGS_SCHEMA = {
|
|
|
2727
2935
|
],
|
|
2728
2936
|
},
|
|
2729
2937
|
},
|
|
2938
|
+
"providers.tinyModel": {
|
|
2939
|
+
type: "enum",
|
|
2940
|
+
values: TINY_TITLE_MODEL_VALUES,
|
|
2941
|
+
default: ONLINE_TINY_TITLE_MODEL_KEY,
|
|
2942
|
+
ui: {
|
|
2943
|
+
tab: "providers",
|
|
2944
|
+
label: "Tiny Model",
|
|
2945
|
+
description: "Session-title model: online pi/smol by default, or a local on-device model",
|
|
2946
|
+
options: TINY_TITLE_MODEL_OPTIONS,
|
|
2947
|
+
},
|
|
2948
|
+
},
|
|
2949
|
+
"providers.tinyModelDevice": {
|
|
2950
|
+
type: "enum",
|
|
2951
|
+
values: TINY_MODEL_DEVICE_SETTING_VALUES,
|
|
2952
|
+
default: TINY_MODEL_DEVICE_DEFAULT,
|
|
2953
|
+
ui: {
|
|
2954
|
+
tab: "providers",
|
|
2955
|
+
label: "Tiny Model Device",
|
|
2956
|
+
description:
|
|
2957
|
+
"ONNX execution provider for local tiny models (titles + memory). Default picks DirectML on Windows, CUDA on Linux x64, CPU elsewhere. The PI_TINY_DEVICE env var overrides this.",
|
|
2958
|
+
options: TINY_MODEL_DEVICE_SETTING_OPTIONS,
|
|
2959
|
+
},
|
|
2960
|
+
},
|
|
2961
|
+
"providers.tinyModelDtype": {
|
|
2962
|
+
type: "enum",
|
|
2963
|
+
values: TINY_MODEL_DTYPE_SETTING_VALUES,
|
|
2964
|
+
default: TINY_MODEL_DTYPE_DEFAULT,
|
|
2965
|
+
ui: {
|
|
2966
|
+
tab: "providers",
|
|
2967
|
+
label: "Tiny Model Precision",
|
|
2968
|
+
description:
|
|
2969
|
+
"ONNX quantization/precision for local tiny models. Default uses each model's shipped dtype (q4); lower precision is faster, higher is more faithful. The PI_TINY_DTYPE env var overrides this.",
|
|
2970
|
+
options: TINY_MODEL_DTYPE_SETTING_OPTIONS,
|
|
2971
|
+
},
|
|
2972
|
+
},
|
|
2973
|
+
"providers.memoryModel": {
|
|
2974
|
+
type: "enum",
|
|
2975
|
+
values: TINY_MEMORY_MODEL_VALUES,
|
|
2976
|
+
default: ONLINE_MEMORY_MODEL_KEY,
|
|
2977
|
+
ui: {
|
|
2978
|
+
tab: "memory",
|
|
2979
|
+
label: "Memory Model",
|
|
2980
|
+
description:
|
|
2981
|
+
"Mnemosyne LLM for fact extraction + consolidation: online (smol/remote) by default, or a local on-device model",
|
|
2982
|
+
condition: "mnemosyneActive",
|
|
2983
|
+
options: TINY_MEMORY_MODEL_OPTIONS,
|
|
2984
|
+
},
|
|
2985
|
+
},
|
|
2730
2986
|
|
|
2731
2987
|
"providers.kimiApiFormat": {
|
|
2732
2988
|
type: "enum",
|
|
@@ -3097,6 +3353,10 @@ export interface TtsrSettings {
|
|
|
3097
3353
|
interruptMode: "never" | "prose-only" | "tool-only" | "always";
|
|
3098
3354
|
repeatMode: "once" | "after-gap";
|
|
3099
3355
|
repeatGap: number;
|
|
3356
|
+
/** Bucketing-only (read by bucketRules, not the TtsrManager). */
|
|
3357
|
+
builtinRules?: boolean;
|
|
3358
|
+
/** Bucketing-only (read by bucketRules, not the TtsrManager). */
|
|
3359
|
+
disabledRules?: string[];
|
|
3100
3360
|
}
|
|
3101
3361
|
|
|
3102
3362
|
export interface ExaSettings {
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builtin Defaults Provider
|
|
3
|
+
*
|
|
4
|
+
* Ships a curated set of default rules (mostly TTSR conventions) embedded into
|
|
5
|
+
* the binary. Registered at the lowest priority so any user/project/tool rule
|
|
6
|
+
* with the same `name` overrides the bundled copy (first-wins dedup by name).
|
|
7
|
+
*
|
|
8
|
+
* Users disable bundled rules three ways:
|
|
9
|
+
* - flip `ttsr.builtinRules` off (drops the whole set),
|
|
10
|
+
* - list a name in `ttsr.disabledRules` (drops one rule),
|
|
11
|
+
* - define a same-named rule in any higher-priority source (overrides it).
|
|
12
|
+
* The first two are enforced in `bucketRules` (see capability/rule-buckets.ts).
|
|
13
|
+
*/
|
|
14
|
+
import { registerProvider } from "../capability";
|
|
15
|
+
import { BUILTIN_DEFAULTS_PROVIDER_ID, type Rule, ruleCapability } from "../capability/rule";
|
|
16
|
+
import type { LoadContext, LoadResult } from "../capability/types";
|
|
17
|
+
import { BUILTIN_RULE_SOURCES } from "./builtin-rules";
|
|
18
|
+
import { buildRuleFromMarkdown, createSourceMeta } from "./helpers";
|
|
19
|
+
|
|
20
|
+
const DISPLAY_NAME = "Builtin Defaults";
|
|
21
|
+
// Lowest priority: every other rule provider wins a name conflict.
|
|
22
|
+
const PRIORITY = 1;
|
|
23
|
+
|
|
24
|
+
async function loadRules(_ctx: LoadContext): Promise<LoadResult<Rule>> {
|
|
25
|
+
const items = BUILTIN_RULE_SOURCES.map(({ name, content }) => {
|
|
26
|
+
const virtualPath = `${BUILTIN_DEFAULTS_PROVIDER_ID}:${name}.md`;
|
|
27
|
+
const source = createSourceMeta(BUILTIN_DEFAULTS_PROVIDER_ID, virtualPath, "user");
|
|
28
|
+
return buildRuleFromMarkdown(name, content, virtualPath, source, { ruleName: name });
|
|
29
|
+
});
|
|
30
|
+
return { items };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
registerProvider<Rule>(ruleCapability.id, {
|
|
34
|
+
id: BUILTIN_DEFAULTS_PROVIDER_ID,
|
|
35
|
+
displayName: DISPLAY_NAME,
|
|
36
|
+
description: "Default rules shipped with the agent (disable via ttsr.builtinRules / ttsr.disabledRules)",
|
|
37
|
+
priority: PRIORITY,
|
|
38
|
+
load: loadRules,
|
|
39
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bundled default rules shipped with the coding agent.
|
|
3
|
+
*
|
|
4
|
+
* Each markdown source is embedded via `with { type: "text" }` so it survives
|
|
5
|
+
* `bun build --compile` (the compiled binary ships no loose rule files; only
|
|
6
|
+
* the embedded text). The native source/tarball installs read the same modules.
|
|
7
|
+
*
|
|
8
|
+
* Registered by the lowest-priority `builtin-defaults` rule provider so any
|
|
9
|
+
* user/project/tool rule with the same name overrides the bundled copy.
|
|
10
|
+
*/
|
|
11
|
+
import rsBoxLeak from "./rs-box-leak.md" with { type: "text" };
|
|
12
|
+
import rsFuturePrelude from "./rs-future-prelude.md" with { type: "text" };
|
|
13
|
+
import rsLazylock from "./rs-lazylock.md" with { type: "text" };
|
|
14
|
+
import rsMatchErgonomics from "./rs-match-ergonomics.md" with { type: "text" };
|
|
15
|
+
import rsParkingLot from "./rs-parking-lot.md" with { type: "text" };
|
|
16
|
+
import rsResultType from "./rs-result-type.md" with { type: "text" };
|
|
17
|
+
import tsBareCatch from "./ts-bare-catch.md" with { type: "text" };
|
|
18
|
+
import tsImportType from "./ts-import-type.md" with { type: "text" };
|
|
19
|
+
import tsNoAny from "./ts-no-any.md" with { type: "text" };
|
|
20
|
+
import tsNoDynamicImport from "./ts-no-dynamic-import.md" with { type: "text" };
|
|
21
|
+
import tsNoReturnType from "./ts-no-return-type.md" with { type: "text" };
|
|
22
|
+
import tsNoTinyFunctions from "./ts-no-tiny-functions.md" with { type: "text" };
|
|
23
|
+
import tsPromiseWithResolvers from "./ts-promise-with-resolvers.md" with { type: "text" };
|
|
24
|
+
import tsSetMap from "./ts-set-map.md" with { type: "text" };
|
|
25
|
+
|
|
26
|
+
/** A bundled rule's stable name and raw markdown (frontmatter + body). */
|
|
27
|
+
export interface BuiltinRuleSource {
|
|
28
|
+
name: string;
|
|
29
|
+
content: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** All bundled default rules, ordered by name. */
|
|
33
|
+
export const BUILTIN_RULE_SOURCES: readonly BuiltinRuleSource[] = [
|
|
34
|
+
{ name: "rs-box-leak", content: rsBoxLeak },
|
|
35
|
+
{ name: "rs-future-prelude", content: rsFuturePrelude },
|
|
36
|
+
{ name: "rs-lazylock", content: rsLazylock },
|
|
37
|
+
{ name: "rs-match-ergonomics", content: rsMatchErgonomics },
|
|
38
|
+
{ name: "rs-parking-lot", content: rsParkingLot },
|
|
39
|
+
{ name: "rs-result-type", content: rsResultType },
|
|
40
|
+
{ name: "ts-bare-catch", content: tsBareCatch },
|
|
41
|
+
{ name: "ts-import-type", content: tsImportType },
|
|
42
|
+
{ name: "ts-no-any", content: tsNoAny },
|
|
43
|
+
{ name: "ts-no-dynamic-import", content: tsNoDynamicImport },
|
|
44
|
+
{ name: "ts-no-return-type", content: tsNoReturnType },
|
|
45
|
+
{ name: "ts-no-tiny-functions", content: tsNoTinyFunctions },
|
|
46
|
+
{ name: "ts-promise-with-resolvers", content: tsPromiseWithResolvers },
|
|
47
|
+
{ name: "ts-set-map", content: tsSetMap },
|
|
48
|
+
];
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Never use Box::leak - it intentionally leaks memory
|
|
3
|
+
condition: "Box::leak"
|
|
4
|
+
scope: "tool:edit(*.rs), tool:write(*.rs)"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Never use `Box::leak` to satisfy a lifetime. It intentionally leaks the allocation for the rest of the process.
|
|
8
|
+
|
|
9
|
+
## Why
|
|
10
|
+
|
|
11
|
+
- The allocation is never freed.
|
|
12
|
+
- It hides ownership bugs.
|
|
13
|
+
- It turns lifetime errors into process lifetime growth.
|
|
14
|
+
- It makes tests pass while production memory grows.
|
|
15
|
+
|
|
16
|
+
## Use instead
|
|
17
|
+
|
|
18
|
+
| Need | Use |
|
|
19
|
+
| --- | --- |
|
|
20
|
+
| Shared async/thread data | `Arc<T>` or owned values |
|
|
21
|
+
| Global lazy state | `LazyLock<T>` or `OnceLock<T>` |
|
|
22
|
+
| Text escaping a scope | `String` / `Arc<str>` |
|
|
23
|
+
| `'static` callback | `move` closure with owned captures |
|
|
24
|
+
| FFI pointer | Explicit owner that frees on drop |
|
|
25
|
+
|
|
26
|
+
## Examples
|
|
27
|
+
|
|
28
|
+
```rust
|
|
29
|
+
// Bad — leaking to manufacture 'static.
|
|
30
|
+
fn label(id: u64) -> &'static str {
|
|
31
|
+
Box::leak(Box::new(format!("item_{id}")))
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Good — return owned data.
|
|
35
|
+
fn label(id: u64) -> String {
|
|
36
|
+
format!("item_{id}")
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Bad — leaking before spawn.
|
|
40
|
+
let state = Box::leak(Box::new(state));
|
|
41
|
+
tokio::spawn(async move { use_state(state) });
|
|
42
|
+
|
|
43
|
+
// Good — share owned state.
|
|
44
|
+
let state = Arc::new(state);
|
|
45
|
+
tokio::spawn(async move { use_state(&state) });
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
If `Box::leak` looks necessary, fix ownership instead.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Use Future not std::future::Future - it's in the prelude
|
|
3
|
+
condition: "std::future::Future"
|
|
4
|
+
scope: "tool:edit(*.rs), tool:write(*.rs)"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Use `Future` directly instead of `std::future::Future` in type positions.
|
|
8
|
+
|
|
9
|
+
Rust 2024 includes `Future` in the standard prelude. Older editions can import it once with `use std::future::Future;`. Repeating the fully qualified path makes signatures harder to read without adding safety.
|
|
10
|
+
|
|
11
|
+
## Examples
|
|
12
|
+
|
|
13
|
+
```rust
|
|
14
|
+
// Bad — fully qualified in every signature.
|
|
15
|
+
fn fetch() -> impl std::future::Future<Output = Result<Data>> { ... }
|
|
16
|
+
fn poll(fut: Pin<&mut dyn std::future::Future<Output = i32>>) { ... }
|
|
17
|
+
|
|
18
|
+
// Good — use the prelude or one import.
|
|
19
|
+
fn fetch() -> impl Future<Output = Result<Data>> { ... }
|
|
20
|
+
fn poll(fut: Pin<&mut dyn Future<Output = i32>>) { ... }
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Pre-2024 edition? Add `use std::future::Future;` at the top.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Prefer std::sync::LazyLock over OnceLock and once_cell
|
|
3
|
+
condition:
|
|
4
|
+
- "once_cell::"
|
|
5
|
+
- "OnceLock::new"
|
|
6
|
+
scope: "tool:edit(*.rs), tool:write(*.rs)"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
Prefer `std::sync::LazyLock` over `OnceLock` and the `once_cell` crate when the initializer is known at declaration time.
|
|
10
|
+
|
|
11
|
+
`LazyLock` stores the cell and initializer together. There is no separate `init()` function, no repeated `get_or_init`, and no missing initialization path.
|
|
12
|
+
|
|
13
|
+
## once_cell → std
|
|
14
|
+
|
|
15
|
+
```rust
|
|
16
|
+
// Before
|
|
17
|
+
use once_cell::sync::Lazy;
|
|
18
|
+
static CONFIG: Lazy<String> = Lazy::new(|| "value".to_string());
|
|
19
|
+
|
|
20
|
+
// After
|
|
21
|
+
use std::sync::LazyLock;
|
|
22
|
+
static CONFIG: LazyLock<String> = LazyLock::new(|| "value".to_string());
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## OnceLock → LazyLock
|
|
26
|
+
|
|
27
|
+
```rust
|
|
28
|
+
// Before — fixed initializer hidden in accessor.
|
|
29
|
+
use std::sync::OnceLock;
|
|
30
|
+
static SETTINGS: OnceLock<Settings> = OnceLock::new();
|
|
31
|
+
fn settings() -> &'static Settings {
|
|
32
|
+
SETTINGS.get_or_init(Settings::load)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// After — initializer lives with the static.
|
|
36
|
+
use std::sync::LazyLock;
|
|
37
|
+
static SETTINGS: LazyLock<Settings> = LazyLock::new(Settings::load);
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Keep OnceLock when runtime input is required
|
|
41
|
+
|
|
42
|
+
```rust
|
|
43
|
+
use std::sync::OnceLock;
|
|
44
|
+
static DATABASE: OnceLock<Database> = OnceLock::new();
|
|
45
|
+
|
|
46
|
+
fn init_database(url: &str) {
|
|
47
|
+
let _ = DATABASE.set(Database::connect(url));
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Do not add `once_cell` for new code. Use the standard library equivalent.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Use match ergonomics instead of ref/ref mut patterns
|
|
3
|
+
condition:
|
|
4
|
+
- "\\(ref mut "
|
|
5
|
+
- "\\(ref [a-z_]"
|
|
6
|
+
scope: "tool:edit(*.rs), tool:write(*.rs)"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
Use match ergonomics instead of explicit `ref` / `ref mut` patterns. Borrow the scrutinee and let bindings receive references.
|
|
10
|
+
|
|
11
|
+
## Shared references
|
|
12
|
+
|
|
13
|
+
```rust
|
|
14
|
+
// Before
|
|
15
|
+
match value {
|
|
16
|
+
Some(ref item) => println!("{item}"),
|
|
17
|
+
None => {}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// After
|
|
21
|
+
match &value {
|
|
22
|
+
Some(item) => println!("{item}"),
|
|
23
|
+
None => {}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if let Some(item) = &value {
|
|
27
|
+
println!("{item}");
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Mutable references
|
|
32
|
+
|
|
33
|
+
```rust
|
|
34
|
+
// Before
|
|
35
|
+
match value {
|
|
36
|
+
Some(ref mut item) => *item += 1,
|
|
37
|
+
None => {}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// After
|
|
41
|
+
match &mut value {
|
|
42
|
+
Some(item) => *item += 1,
|
|
43
|
+
None => {}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if let Some(item) = &mut value {
|
|
47
|
+
*item += 1;
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Result
|
|
52
|
+
|
|
53
|
+
```rust
|
|
54
|
+
// Before
|
|
55
|
+
match result {
|
|
56
|
+
Ok(ref data) => println!("{data}"),
|
|
57
|
+
Err(ref err) => eprintln!("{err}"),
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// After
|
|
61
|
+
match &result {
|
|
62
|
+
Ok(data) => println!("{data}"),
|
|
63
|
+
Err(err) => eprintln!("{err}"),
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Modern Rust rarely needs `ref` in patterns. Borrow the value being matched.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Use parking_lot instead of std::sync for Mutex/RwLock
|
|
3
|
+
condition:
|
|
4
|
+
- "\\.lock\\(\\)\\.unwrap\\(\\)"
|
|
5
|
+
- "\\.read\\(\\)\\.unwrap\\(\\)"
|
|
6
|
+
- "\\.write\\(\\)\\.unwrap\\(\\)"
|
|
7
|
+
scope: "tool:edit(*.rs), tool:write(*.rs)"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
Use `parking_lot::{Mutex, RwLock}` instead of `std::sync::{Mutex, RwLock}` when code immediately unwraps lock results.
|
|
11
|
+
|
|
12
|
+
## Why
|
|
13
|
+
|
|
14
|
+
- `lock()`, `read()`, and `write()` return guards directly.
|
|
15
|
+
- No poisoning error path to unwrap.
|
|
16
|
+
- Guards are smaller and faster in common contention cases.
|
|
17
|
+
- The call site shows locking, not error handling boilerplate.
|
|
18
|
+
|
|
19
|
+
## Migration
|
|
20
|
+
|
|
21
|
+
```rust
|
|
22
|
+
// Before
|
|
23
|
+
use std::sync::Mutex;
|
|
24
|
+
let data = Mutex::new(Vec::new());
|
|
25
|
+
let guard = data.lock().unwrap();
|
|
26
|
+
|
|
27
|
+
// After
|
|
28
|
+
use parking_lot::Mutex;
|
|
29
|
+
let data = Mutex::new(Vec::new());
|
|
30
|
+
let guard = data.lock();
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Equivalents
|
|
34
|
+
|
|
35
|
+
| std::sync | parking_lot |
|
|
36
|
+
| --- | --- |
|
|
37
|
+
| `Mutex<T>` | `Mutex<T>` |
|
|
38
|
+
| `RwLock<T>` | `RwLock<T>` |
|
|
39
|
+
| `Condvar` | `Condvar` |
|
|
40
|
+
| `Once` | `Once` |
|
|
41
|
+
|
|
42
|
+
## Keep async locks async
|
|
43
|
+
|
|
44
|
+
Use `tokio::sync::Mutex` / `tokio::sync::RwLock` when a guard is held across `.await` or the lock belongs to async coordination.
|