@agimon-ai/doompi-model-guidance 0.0.1-alpha.101

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.
Files changed (37) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +104 -0
  3. package/dist/apiContracts.cjs +17 -0
  4. package/dist/apiContracts.cjs.map +1 -0
  5. package/dist/apiContracts.d.mts +53 -0
  6. package/dist/apiContracts.d.mts.map +1 -0
  7. package/dist/apiContracts.mjs +13 -0
  8. package/dist/apiContracts.mjs.map +1 -0
  9. package/dist/extensions/mcp.cjs +26 -0
  10. package/dist/extensions/mcp.cjs.map +1 -0
  11. package/dist/extensions/mcp.d.mts +5 -0
  12. package/dist/extensions/mcp.d.mts.map +1 -0
  13. package/dist/extensions/mcp.mjs +21 -0
  14. package/dist/extensions/mcp.mjs.map +1 -0
  15. package/dist/extensions/pi.cjs +61 -0
  16. package/dist/extensions/pi.cjs.map +1 -0
  17. package/dist/extensions/pi.d.mts +5 -0
  18. package/dist/extensions/pi.d.mts.map +1 -0
  19. package/dist/extensions/pi.mjs +32 -0
  20. package/dist/extensions/pi.mjs.map +1 -0
  21. package/dist/extensions/server.cjs +68 -0
  22. package/dist/extensions/server.cjs.map +1 -0
  23. package/dist/extensions/server.d.mts +5 -0
  24. package/dist/extensions/server.d.mts.map +1 -0
  25. package/dist/extensions/server.mjs +60 -0
  26. package/dist/extensions/server.mjs.map +1 -0
  27. package/dist/index.cjs +8 -0
  28. package/dist/index.d.mts +66 -0
  29. package/dist/index.d.mts.map +1 -0
  30. package/dist/index.mjs +2 -0
  31. package/dist/modelGuidanceStore-BPKgawjz.mjs +76 -0
  32. package/dist/modelGuidanceStore-BPKgawjz.mjs.map +1 -0
  33. package/dist/modelGuidanceStore-DEs_jtoI.cjs +111 -0
  34. package/dist/modelGuidanceStore-DEs_jtoI.cjs.map +1 -0
  35. package/llms.txt +11 -0
  36. package/package.json +123 -0
  37. package/src/prompts/doompi-use-model-guidance/SKILL.md +34 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Vuong Ngo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,104 @@
1
+ # @agimon-ai/doompi-model-guidance
2
+
3
+ Per-model system prompt guidance for Pi agents, layered across global and repository scope.
4
+
5
+ A new model release often needs prompt adjustments that older models do not.
6
+ This package keeps those adjustments in one place, keyed by model id, instead of
7
+ spreading them through every package's prompt.
8
+
9
+ ## Configuration
10
+
11
+ Listing the package in `modes.yaml` activates its built-in `default` preset. The
12
+ preset currently supplies guidance for `gpt-6-astra` to continue agreed plans and
13
+ scoped tasks without pausing for minor decisions.
14
+
15
+ Custom guidance lives in `model-guidance.yaml`, read from two scopes:
16
+
17
+ | Scope | Path |
18
+ | ---------- | ---------------------------------------- |
19
+ | Global | `~/.pi/.doom/model-guidance.yaml` |
20
+ | Repository | `<repository>/.doom/model-guidance.yaml` |
21
+
22
+ ```yaml
23
+ modelGuidance:
24
+ claude-opus-5: |
25
+ Keep the task focused. Never go off rails.
26
+ gpt-6-astra: |
27
+ Prefer fewer, larger tool batches.
28
+ ```
29
+
30
+ ### Matching
31
+
32
+ Model ids match exactly, against the id Pi reports for the active model. Use the
33
+ value shown by `/model`. A model with no custom entry uses its built-in preset
34
+ entry when one exists; otherwise it gets no guidance.
35
+
36
+ Exact matching is deliberate: it keeps the file honest about which model a piece
37
+ of text was written for. The cost is that a provider shipping a new versioned id
38
+ needs a new entry.
39
+
40
+ ### Merge rule
41
+
42
+ The built-in preset applies first. Global guidance overrides the preset one model
43
+ id at a time, then repository guidance overrides global guidance the same way.
44
+
45
+ | Model id | Global | Repository | Result |
46
+ | --------------- | --------------- | --------------------- | --------------------- |
47
+ | `claude-opus-5` | "Stay focused." | "Cordis rules apply." | "Cordis rules apply." |
48
+ | `gpt-6-astra` | "Batch tools." | absent | "Batch tools." |
49
+ | `local-qwen-3` | absent | "Short answers only." | "Short answers only." |
50
+
51
+ A malformed or unreadable guidance file warns on stderr and falls back to the
52
+ built-in preset rather than ending the session.
53
+
54
+ ## Activation
55
+
56
+ The package ships in the `llm` layer and is optional.
57
+
58
+ Mode-scoped, in `.doom/modes.yaml`:
59
+
60
+ ```yaml
61
+ layers:
62
+ llm:
63
+ packages:
64
+ - '@agimon-ai/doompi-model-guidance'
65
+
66
+ majorMode:
67
+ copilot:
68
+ layers: [team, ask-user, task, sandbox, llm]
69
+ ```
70
+
71
+ Always on, by listing it in the `default` package list instead:
72
+
73
+ ```yaml
74
+ default:
75
+ packages:
76
+ - '@agimon-ai/doompi-model-guidance'
77
+ ```
78
+
79
+ A bare package entry automatically uses the built-in `default` preset. A layer
80
+ only activates when the selected major mode lists it, so add `llm` to every major
81
+ mode that should carry guidance. The top-level `default` route enables it for all
82
+ modes.
83
+
84
+ ## Behaviour
85
+
86
+ Guidance is appended to the system prompt at the start of each turn, after the
87
+ default packages have contributed and before the profile persona. The file is
88
+ read per turn, so an edit takes effect on the next message with no restart.
89
+
90
+ ## Development
91
+
92
+ ```bash
93
+ pnpm nx run @agimon-ai/doompi-model-guidance:lint
94
+ pnpm nx run @agimon-ai/doompi-model-guidance:typecheck
95
+ pnpm nx run @agimon-ai/doompi-model-guidance:build
96
+ pnpm nx run @agimon-ai/doompi-model-guidance:test
97
+ ```
98
+
99
+ Pi entrypoint: `./dist/extensions/pi.mjs`.
100
+
101
+ The Pi and server declarations live in `src/extensions` and build directly to
102
+ `/extensions/pi` and `/extensions/server`. Controllers handle host events and call the
103
+ named guidance services. Flat root exports expose guidance loading, merging, and types.
104
+ The shared helpers own registration and cleanup; this stateless plugin needs no lifecycle hooks.
@@ -0,0 +1,17 @@
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
5
+ //#region src/schemas/apiContracts.ts
6
+ /** This facet contributes agent tools, commands or lifecycle only, with no separate HTTP or socket surface. */
7
+ const apiContracts = (0, require("@agimon-ai/doompi-core/apiContracts").defineApiContract)({
8
+ version: 1,
9
+ http: [],
10
+ sockets: [],
11
+ dynamic: []
12
+ });
13
+ //#endregion
14
+ exports.apiContracts = apiContracts;
15
+ exports.default = apiContracts;
16
+
17
+ //# sourceMappingURL=apiContracts.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apiContracts.cjs","names":["defineApiContract"],"sources":["../src/schemas/apiContracts.ts"],"sourcesContent":["import { defineApiContract } from '@agimon-ai/doompi-core/apiContracts';\n\n/** This facet contributes agent tools, commands or lifecycle only, with no separate HTTP or socket surface. */\nexport const apiContracts = defineApiContract({ version: 1, http: [], sockets: [], dynamic: [] });\nexport default apiContracts;\n"],"mappings":";;;;;;AAGA,MAAa,gBAAA,gDAAeA,CAAAA,CAAAA,kBAAAA,CAAkB;CAAE,SAAS;CAAG,MAAM,CAAC;CAAG,SAAS,CAAC;CAAG,SAAS,CAAC;AAAE,CAAC"}
@@ -0,0 +1,53 @@
1
+ //#region src/schemas/apiContracts.d.ts
2
+ /** This facet contributes agent tools, commands or lifecycle only, with no separate HTTP or socket surface. */
3
+ export declare const apiContracts: {
4
+ version: 1;
5
+ protocols?: Record<string, string> | undefined;
6
+ schemas?: Record<string, boolean | object> | undefined;
7
+ http: {
8
+ id: string;
9
+ scope: "global" | "session" | "workspace";
10
+ basePath?: string | undefined;
11
+ path: string;
12
+ method: "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | "PUT";
13
+ description: string;
14
+ availability?: string | undefined;
15
+ authentication: "device" | "none" | "owner";
16
+ parameters?: {
17
+ name: string;
18
+ in: "header" | "path" | "query";
19
+ required: boolean;
20
+ schema: boolean | object;
21
+ }[] | undefined;
22
+ body?: {
23
+ contentType: string;
24
+ contentTypes?: string[] | undefined;
25
+ required: boolean;
26
+ schema: boolean | object;
27
+ } | undefined;
28
+ responses: Record<string, {
29
+ description: string;
30
+ contentType?: string | undefined;
31
+ schema?: boolean | object | undefined;
32
+ events?: Record<string, boolean | object> | undefined;
33
+ }>;
34
+ }[];
35
+ sockets: {
36
+ id: string;
37
+ scope: "global" | "session" | "workspace";
38
+ description: string;
39
+ availability?: string | undefined;
40
+ service: string;
41
+ member: string;
42
+ direction: "client-to-server" | "server-to-client";
43
+ kind: "channel" | "method" | "state";
44
+ input: boolean | object;
45
+ output?: boolean | object | undefined;
46
+ errors?: boolean | object | undefined;
47
+ }[];
48
+ dynamic: string[];
49
+ gaps?: string[] | undefined;
50
+ };
51
+ //#endregion
52
+ export { apiContracts as default };
53
+ //# sourceMappingURL=apiContracts.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apiContracts.d.mts","names":[],"sources":["../src/schemas/apiContracts.ts"],"mappings":";;qBAGa"}
@@ -0,0 +1,13 @@
1
+ import { defineApiContract } from "@agimon-ai/doompi-core/apiContracts";
2
+ //#region src/schemas/apiContracts.ts
3
+ /** This facet contributes agent tools, commands or lifecycle only, with no separate HTTP or socket surface. */
4
+ const apiContracts = defineApiContract({
5
+ version: 1,
6
+ http: [],
7
+ sockets: [],
8
+ dynamic: []
9
+ });
10
+ //#endregion
11
+ export { apiContracts, apiContracts as default };
12
+
13
+ //# sourceMappingURL=apiContracts.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apiContracts.mjs","names":[],"sources":["../src/schemas/apiContracts.ts"],"sourcesContent":["import { defineApiContract } from '@agimon-ai/doompi-core/apiContracts';\n\n/** This facet contributes agent tools, commands or lifecycle only, with no separate HTTP or socket surface. */\nexport const apiContracts = defineApiContract({ version: 1, http: [], sockets: [], dynamic: [] });\nexport default apiContracts;\n"],"mappings":";;;AAGA,MAAa,eAAe,kBAAkB;CAAE,SAAS;CAAG,MAAM,CAAC;CAAG,SAAS,CAAC;CAAG,SAAS,CAAC;AAAE,CAAC"}
@@ -0,0 +1,26 @@
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
5
+ let _agimon_ai_doompi_core_mcpFacet = require("@agimon-ai/doompi-core/mcpFacet");
6
+ let _agimon_ai_doompi_core_serverFacet = require("@agimon-ai/doompi-core/serverFacet");
7
+ //#region src/extensions/workspaces/sessions/(backend)/skill/doompi-use-model-guidance.mcp.ts
8
+ var doompi_use_model_guidance_mcp_default = (0, _agimon_ai_doompi_core_mcpFacet.defineMcpSkill)({
9
+ name: "doompi-use-model-guidance",
10
+ description: "Use @agimon-ai/doompi-model-guidance: per-model system prompt guidance, layered across global and repository scope",
11
+ read: () => (0, _agimon_ai_doompi_core_serverFacet.readPackageResource)(require("url").pathToFileURL(__filename).href, "src/prompts/doompi-use-model-guidance/SKILL.md")
12
+ });
13
+ //#endregion
14
+ //#region generated/mcp.ts
15
+ const at = (value, context) => typeof value === "function" ? value(context) : value;
16
+ const mcp = (0, _agimon_ai_doompi_core_mcpFacet.defineMcpPlugin)({
17
+ name: "@agimon-ai/doompi-model-guidance",
18
+ session: (context) => ({ get skills() {
19
+ return [at(doompi_use_model_guidance_mcp_default, context)];
20
+ } })
21
+ });
22
+ //#endregion
23
+ exports.default = mcp;
24
+ exports.mcp = mcp;
25
+
26
+ //# sourceMappingURL=mcp.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.cjs","names":["defineMcpSkill","readPackageResource","defineMcpPlugin","skillDoompiUseModelGuidance"],"sources":["../../src/extensions/workspaces/sessions/(backend)/skill/doompi-use-model-guidance.mcp.ts","../../generated/mcp.ts"],"sourcesContent":["import { defineMcpSkill } from '@agimon-ai/doompi-core/mcpFacet';\nimport { readPackageResource } from '@agimon-ai/doompi-core/serverFacet';\n\nexport default defineMcpSkill({\n name: 'doompi-use-model-guidance',\n description:\n 'Use @agimon-ai/doompi-model-guidance: per-model system prompt guidance, layered across global and repository scope',\n read: () => readPackageResource(import.meta.url, 'src/prompts/doompi-use-model-guidance/SKILL.md'),\n});\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { defineMcpPlugin, type DoomMcpSessionPlugin } from '@agimon-ai/doompi-core/mcpFacet';\n\nimport skillDoompiUseModelGuidance from '../src/extensions/workspaces/sessions/(backend)/skill/doompi-use-model-guidance.mcp';\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\n\nexport const mcp = defineMcpPlugin({\n name: '@agimon-ai/doompi-model-guidance',\n session: (context) => ({\n get skills(): DoomMcpSessionPlugin['skills'] { return [at(skillDoompiUseModelGuidance, context)]; },\n }) satisfies DoomMcpSessionPlugin,\n});\n\nexport default mcp;\n"],"mappings":";;;;;;;AAGA,IAAA,yCAAA,GAAeA,gCAAAA,eAAAA,CAAe;CAC5B,MAAM;CACN,aACE;CACF,aAAA,GAAYC,mCAAAA,oBAAAA,CAAAA,QAAAA,KAAAA,CAAAA,CAAAA,cAAAA,UAAAA,CAAAA,CAAAA,MAAqC,gDAAgD;AACnG,CAAC;;;ACFD,MAAM,MAAY,OAA0B,YAC1C,OAAO,UAAU,aAAc,MAAwB,OAAO,IAAI;AAEpE,MAAa,OAAA,GAAMC,gCAAAA,gBAAAA,CAAgB;CACjC,MAAM;CACN,UAAU,aAAa,EACrB,IAAI,SAAyC;EAAE,OAAO,CAAC,GAAGC,uCAA6B,OAAO,CAAC;CAAG,EACpG;AACF,CAAC"}
@@ -0,0 +1,5 @@
1
+ //#region generated/mcp.d.ts
2
+ export declare const mcp: import("@agimon-ai/doompi-core/mcpFacet").DoomMcpPluginDefinition;
3
+ //#endregion
4
+ export { mcp as default };
5
+ //# sourceMappingURL=mcp.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.d.mts","names":[],"sources":["../../generated/mcp.ts"],"mappings":";qBASa,+CAAG"}
@@ -0,0 +1,21 @@
1
+ import { defineMcpPlugin, defineMcpSkill } from "@agimon-ai/doompi-core/mcpFacet";
2
+ import { readPackageResource } from "@agimon-ai/doompi-core/serverFacet";
3
+ //#region src/extensions/workspaces/sessions/(backend)/skill/doompi-use-model-guidance.mcp.ts
4
+ var doompi_use_model_guidance_mcp_default = defineMcpSkill({
5
+ name: "doompi-use-model-guidance",
6
+ description: "Use @agimon-ai/doompi-model-guidance: per-model system prompt guidance, layered across global and repository scope",
7
+ read: () => readPackageResource(import.meta.url, "src/prompts/doompi-use-model-guidance/SKILL.md")
8
+ });
9
+ //#endregion
10
+ //#region generated/mcp.ts
11
+ const at = (value, context) => typeof value === "function" ? value(context) : value;
12
+ const mcp = defineMcpPlugin({
13
+ name: "@agimon-ai/doompi-model-guidance",
14
+ session: (context) => ({ get skills() {
15
+ return [at(doompi_use_model_guidance_mcp_default, context)];
16
+ } })
17
+ });
18
+ //#endregion
19
+ export { mcp as default, mcp };
20
+
21
+ //# sourceMappingURL=mcp.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.mjs","names":["skillDoompiUseModelGuidance"],"sources":["../../src/extensions/workspaces/sessions/(backend)/skill/doompi-use-model-guidance.mcp.ts","../../generated/mcp.ts"],"sourcesContent":["import { defineMcpSkill } from '@agimon-ai/doompi-core/mcpFacet';\nimport { readPackageResource } from '@agimon-ai/doompi-core/serverFacet';\n\nexport default defineMcpSkill({\n name: 'doompi-use-model-guidance',\n description:\n 'Use @agimon-ai/doompi-model-guidance: per-model system prompt guidance, layered across global and repository scope',\n read: () => readPackageResource(import.meta.url, 'src/prompts/doompi-use-model-guidance/SKILL.md'),\n});\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { defineMcpPlugin, type DoomMcpSessionPlugin } from '@agimon-ai/doompi-core/mcpFacet';\n\nimport skillDoompiUseModelGuidance from '../src/extensions/workspaces/sessions/(backend)/skill/doompi-use-model-guidance.mcp';\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\n\nexport const mcp = defineMcpPlugin({\n name: '@agimon-ai/doompi-model-guidance',\n session: (context) => ({\n get skills(): DoomMcpSessionPlugin['skills'] { return [at(skillDoompiUseModelGuidance, context)]; },\n }) satisfies DoomMcpSessionPlugin,\n});\n\nexport default mcp;\n"],"mappings":";;;AAGA,IAAA,wCAAe,eAAe;CAC5B,MAAM;CACN,aACE;CACF,YAAY,oBAAoB,YAAY,KAAK,gDAAgD;AACnG,CAAC;;;ACFD,MAAM,MAAY,OAA0B,YAC1C,OAAO,UAAU,aAAc,MAAwB,OAAO,IAAI;AAEpE,MAAa,MAAM,gBAAgB;CACjC,MAAM;CACN,UAAU,aAAa,EACrB,IAAI,SAAyC;EAAE,OAAO,CAAC,GAAGA,uCAA6B,OAAO,CAAC;CAAG,EACpG;AACF,CAAC"}
@@ -0,0 +1,61 @@
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
5
+ //#region \0rolldown/runtime.js
6
+ var __create = Object.create;
7
+ var __defProp = Object.defineProperty;
8
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
9
+ var __getOwnPropNames = Object.getOwnPropertyNames;
10
+ var __getProtoOf = Object.getPrototypeOf;
11
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
14
+ key = keys[i];
15
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
16
+ get: ((k) => from[k]).bind(null, key),
17
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
18
+ });
19
+ }
20
+ return to;
21
+ };
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
23
+ value: mod,
24
+ enumerable: true
25
+ }) : target, mod));
26
+ //#endregion
27
+ const require_modelGuidanceStore = require("../modelGuidanceStore-DEs_jtoI.cjs");
28
+ let _agimon_ai_doompi_core_piExtension = require("@agimon-ai/doompi-core/piExtension");
29
+ let _agimon_ai_doompi_core_extensionFile = require("@agimon-ai/doompi-core/extensionFile");
30
+ let node_fs = require("node:fs");
31
+ node_fs = __toESM(node_fs, 1);
32
+ let node_path = require("node:path");
33
+ node_path = __toESM(node_path, 1);
34
+ //#region src/extensions/workspaces/sessions/(backend)/hook/_lib/beforeAgentStart.cli.ts
35
+ /** Read each turn so configuration edits take effect without restarting the session. */
36
+ const modelGuidanceEvents = { before_agent_start(event, context) {
37
+ const modelId = context.model?.id;
38
+ if (!modelId) return void 0;
39
+ let root = node_path.default.resolve(context.cwd);
40
+ while (!node_fs.default.existsSync(node_path.default.join(root, ".git")) && !node_fs.default.existsSync(node_path.default.join(root, ".doom"))) {
41
+ const parent = node_path.default.dirname(root);
42
+ if (parent === root) break;
43
+ root = parent;
44
+ }
45
+ const guidance = require_modelGuidanceStore.guidanceForModel(require_modelGuidanceStore.loadModelGuidance(root), modelId);
46
+ const systemPrompt = require_modelGuidanceStore.applyModelGuidance(event.systemPrompt, guidance);
47
+ return systemPrompt ? { systemPrompt } : void 0;
48
+ } };
49
+ var beforeAgentStart_cli_default$1 = (_context) => (...args) => modelGuidanceEvents.before_agent_start(...args);
50
+ //#endregion
51
+ //#region src/extensions/workspaces/sessions/(backend)/hook/beforeAgentStart.cli.ts
52
+ var beforeAgentStart_cli_default = (0, _agimon_ai_doompi_core_extensionFile.defineCliHook)(beforeAgentStart_cli_default$1);
53
+ //#endregion
54
+ //#region generated/pi.ts
55
+ const at = (value, context) => typeof value === "function" ? value(context) : value;
56
+ const extension = (0, _agimon_ai_doompi_core_piExtension.definePiExtension)("@agimon-ai/doompi-model-guidance", (context) => ({ events: { before_agent_start: at(beforeAgentStart_cli_default, context) } }));
57
+ //#endregion
58
+ exports.default = extension;
59
+ exports.extension = extension;
60
+
61
+ //# sourceMappingURL=pi.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi.cjs","names":["path","fs","guidanceForModel","loadModelGuidance","applyModelGuidance","defineCliHook","contribution","definePiExtension","hookBeforeAgentStart"],"sources":["../../src/extensions/workspaces/sessions/(backend)/hook/_lib/beforeAgentStart.cli.ts","../../src/extensions/workspaces/sessions/(backend)/hook/beforeAgentStart.cli.ts","../../generated/pi.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport type { PiEventHandlers, PiPluginContext } from '@agimon-ai/doompi-core/piExtension';\n\nimport { applyModelGuidance, guidanceForModel } from '../../../../../../services/modelGuidance';\nimport { loadModelGuidance } from '../../../../../../services/modelGuidanceStore';\n\n/** Read each turn so configuration edits take effect without restarting the session. */\nexport const modelGuidanceEvents = {\n before_agent_start(event, context) {\n const modelId = context.model?.id;\n if (!modelId) return undefined;\n let root = path.resolve(context.cwd);\n while (!fs.existsSync(path.join(root, '.git')) && !fs.existsSync(path.join(root, '.doom'))) {\n const parent = path.dirname(root);\n if (parent === root) break;\n root = parent;\n }\n const guidance = guidanceForModel(loadModelGuidance(root), modelId);\n const systemPrompt = applyModelGuidance(event.systemPrompt, guidance);\n return systemPrompt ? { systemPrompt } : undefined;\n },\n} satisfies PiEventHandlers;\n\nexport default (_context: PiPluginContext) =>\n (...args: Parameters<typeof modelGuidanceEvents.before_agent_start>) =>\n modelGuidanceEvents.before_agent_start(...args);\n","import { defineCliHook } from '@agimon-ai/doompi-core/extensionFile';\n\nimport contribution from './_lib/beforeAgentStart.cli';\n\nexport default defineCliHook(contribution);\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { definePiExtension, type PiPluginContext, type PiPluginContributions } from '@agimon-ai/doompi-core/piExtension';\n\nimport hookBeforeAgentStart from '../src/extensions/workspaces/sessions/(backend)/hook/beforeAgentStart.cli';\n\ntype OptionsOf<T> = T extends (context: PiPluginContext<infer Options>) => unknown ? Options : never;\ntype InferredOptions = Exclude<OptionsOf<typeof hookBeforeAgentStart>, undefined>;\ntype Intersect<Union> =\n (Union extends unknown ? (value: Union) => void : never) extends (value: infer Value) => void ? Value : never;\ntype ExtensionOptions = [InferredOptions] extends [never] ? undefined : Intersect<InferredOptions>;\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\n\nexport const extension = definePiExtension<ExtensionOptions>('@agimon-ai/doompi-model-guidance', (context) => ({\n events: {\n before_agent_start: at(hookBeforeAgentStart, context) as NonNullable<PiPluginContributions['events']>['before_agent_start'],\n },\n}));\n\nexport default extension;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AASA,MAAa,sBAAsB,EACjC,mBAAmB,OAAO,SAAS;CACjC,MAAM,UAAU,QAAQ,OAAO;CAC/B,IAAI,CAAC,SAAS,OAAO,KAAA;CACrB,IAAI,OAAOA,UAAAA,QAAK,QAAQ,QAAQ,GAAG;CACnC,OAAO,CAACC,QAAAA,QAAG,WAAWD,UAAAA,QAAK,KAAK,MAAM,MAAM,CAAC,KAAK,CAACC,QAAAA,QAAG,WAAWD,UAAAA,QAAK,KAAK,MAAM,OAAO,CAAC,GAAG;EAC1F,MAAM,SAASA,UAAAA,QAAK,QAAQ,IAAI;EAChC,IAAI,WAAW,MAAM;EACrB,OAAO;CACT;CACA,MAAM,WAAWE,2BAAAA,iBAAiBC,2BAAAA,kBAAkB,IAAI,GAAG,OAAO;CAClE,MAAM,eAAeC,2BAAAA,mBAAmB,MAAM,cAAc,QAAQ;CACpE,OAAO,eAAe,EAAE,aAAa,IAAI,KAAA;AAC3C,EACF;AAEA,IAAA,kCAAgB,cACb,GAAG,SACF,oBAAoB,mBAAmB,GAAG,IAAI;;;ACvBlD,IAAA,gCAAA,GAAeC,qCAAAA,cAAAA,CAAcC,8BAAY;;;ACQzC,MAAM,MAAY,OAA0B,YAC1C,OAAO,UAAU,aAAc,MAAwB,OAAO,IAAI;AAEpE,MAAa,aAAA,GAAYC,mCAAAA,kBAAAA,CAAoC,qCAAqC,aAAa,EAC7G,QAAQ,EACN,oBAAoB,GAAGC,8BAAsB,OAAO,EACtD,EACF,EAAE"}
@@ -0,0 +1,5 @@
1
+ //#region generated/pi.d.ts
2
+ export declare const extension: import("@agimon-ai/doompi-core/runtimePiExtension").DefinedPiExtension<undefined>;
3
+ //#endregion
4
+ export { extension as default };
5
+ //# sourceMappingURL=pi.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi.d.mts","names":[],"sources":["../../generated/pi.ts"],"mappings":";qBAea,+DAAS"}
@@ -0,0 +1,32 @@
1
+ import { i as guidanceForModel, n as loadModelGuidance, r as applyModelGuidance } from "../modelGuidanceStore-BPKgawjz.mjs";
2
+ import { definePiExtension } from "@agimon-ai/doompi-core/piExtension";
3
+ import { defineCliHook } from "@agimon-ai/doompi-core/extensionFile";
4
+ import fs from "node:fs";
5
+ import path from "node:path";
6
+ //#region src/extensions/workspaces/sessions/(backend)/hook/_lib/beforeAgentStart.cli.ts
7
+ /** Read each turn so configuration edits take effect without restarting the session. */
8
+ const modelGuidanceEvents = { before_agent_start(event, context) {
9
+ const modelId = context.model?.id;
10
+ if (!modelId) return void 0;
11
+ let root = path.resolve(context.cwd);
12
+ while (!fs.existsSync(path.join(root, ".git")) && !fs.existsSync(path.join(root, ".doom"))) {
13
+ const parent = path.dirname(root);
14
+ if (parent === root) break;
15
+ root = parent;
16
+ }
17
+ const guidance = guidanceForModel(loadModelGuidance(root), modelId);
18
+ const systemPrompt = applyModelGuidance(event.systemPrompt, guidance);
19
+ return systemPrompt ? { systemPrompt } : void 0;
20
+ } };
21
+ var beforeAgentStart_cli_default$1 = (_context) => (...args) => modelGuidanceEvents.before_agent_start(...args);
22
+ //#endregion
23
+ //#region src/extensions/workspaces/sessions/(backend)/hook/beforeAgentStart.cli.ts
24
+ var beforeAgentStart_cli_default = defineCliHook(beforeAgentStart_cli_default$1);
25
+ //#endregion
26
+ //#region generated/pi.ts
27
+ const at = (value, context) => typeof value === "function" ? value(context) : value;
28
+ const extension = definePiExtension("@agimon-ai/doompi-model-guidance", (context) => ({ events: { before_agent_start: at(beforeAgentStart_cli_default, context) } }));
29
+ //#endregion
30
+ export { extension as default, extension };
31
+
32
+ //# sourceMappingURL=pi.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi.mjs","names":["contribution","hookBeforeAgentStart"],"sources":["../../src/extensions/workspaces/sessions/(backend)/hook/_lib/beforeAgentStart.cli.ts","../../src/extensions/workspaces/sessions/(backend)/hook/beforeAgentStart.cli.ts","../../generated/pi.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport type { PiEventHandlers, PiPluginContext } from '@agimon-ai/doompi-core/piExtension';\n\nimport { applyModelGuidance, guidanceForModel } from '../../../../../../services/modelGuidance';\nimport { loadModelGuidance } from '../../../../../../services/modelGuidanceStore';\n\n/** Read each turn so configuration edits take effect without restarting the session. */\nexport const modelGuidanceEvents = {\n before_agent_start(event, context) {\n const modelId = context.model?.id;\n if (!modelId) return undefined;\n let root = path.resolve(context.cwd);\n while (!fs.existsSync(path.join(root, '.git')) && !fs.existsSync(path.join(root, '.doom'))) {\n const parent = path.dirname(root);\n if (parent === root) break;\n root = parent;\n }\n const guidance = guidanceForModel(loadModelGuidance(root), modelId);\n const systemPrompt = applyModelGuidance(event.systemPrompt, guidance);\n return systemPrompt ? { systemPrompt } : undefined;\n },\n} satisfies PiEventHandlers;\n\nexport default (_context: PiPluginContext) =>\n (...args: Parameters<typeof modelGuidanceEvents.before_agent_start>) =>\n modelGuidanceEvents.before_agent_start(...args);\n","import { defineCliHook } from '@agimon-ai/doompi-core/extensionFile';\n\nimport contribution from './_lib/beforeAgentStart.cli';\n\nexport default defineCliHook(contribution);\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { definePiExtension, type PiPluginContext, type PiPluginContributions } from '@agimon-ai/doompi-core/piExtension';\n\nimport hookBeforeAgentStart from '../src/extensions/workspaces/sessions/(backend)/hook/beforeAgentStart.cli';\n\ntype OptionsOf<T> = T extends (context: PiPluginContext<infer Options>) => unknown ? Options : never;\ntype InferredOptions = Exclude<OptionsOf<typeof hookBeforeAgentStart>, undefined>;\ntype Intersect<Union> =\n (Union extends unknown ? (value: Union) => void : never) extends (value: infer Value) => void ? Value : never;\ntype ExtensionOptions = [InferredOptions] extends [never] ? undefined : Intersect<InferredOptions>;\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\n\nexport const extension = definePiExtension<ExtensionOptions>('@agimon-ai/doompi-model-guidance', (context) => ({\n events: {\n before_agent_start: at(hookBeforeAgentStart, context) as NonNullable<PiPluginContributions['events']>['before_agent_start'],\n },\n}));\n\nexport default extension;\n"],"mappings":";;;;;;;AASA,MAAa,sBAAsB,EACjC,mBAAmB,OAAO,SAAS;CACjC,MAAM,UAAU,QAAQ,OAAO;CAC/B,IAAI,CAAC,SAAS,OAAO,KAAA;CACrB,IAAI,OAAO,KAAK,QAAQ,QAAQ,GAAG;CACnC,OAAO,CAAC,GAAG,WAAW,KAAK,KAAK,MAAM,MAAM,CAAC,KAAK,CAAC,GAAG,WAAW,KAAK,KAAK,MAAM,OAAO,CAAC,GAAG;EAC1F,MAAM,SAAS,KAAK,QAAQ,IAAI;EAChC,IAAI,WAAW,MAAM;EACrB,OAAO;CACT;CACA,MAAM,WAAW,iBAAiB,kBAAkB,IAAI,GAAG,OAAO;CAClE,MAAM,eAAe,mBAAmB,MAAM,cAAc,QAAQ;CACpE,OAAO,eAAe,EAAE,aAAa,IAAI,KAAA;AAC3C,EACF;AAEA,IAAA,kCAAgB,cACb,GAAG,SACF,oBAAoB,mBAAmB,GAAG,IAAI;;;ACvBlD,IAAA,+BAAe,cAAcA,8BAAY;;;ACQzC,MAAM,MAAY,OAA0B,YAC1C,OAAO,UAAU,aAAc,MAAwB,OAAO,IAAI;AAEpE,MAAa,YAAY,kBAAoC,qCAAqC,aAAa,EAC7G,QAAQ,EACN,oBAAoB,GAAGC,8BAAsB,OAAO,EACtD,EACF,EAAE"}
@@ -0,0 +1,68 @@
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
5
+ const require_modelGuidanceStore = require("../modelGuidanceStore-DEs_jtoI.cjs");
6
+ let _agimon_ai_doompi_core_extensionFile = require("@agimon-ai/doompi-core/extensionFile");
7
+ let _agimon_ai_doompi_core_serverFacet = require("@agimon-ai/doompi-core/serverFacet");
8
+ let _agimon_ai_doompi_core_help = require("@agimon-ai/doompi-core/help");
9
+ //#endregion
10
+ //#region src/extensions/workspaces/sessions/(backend)/hook/beforeAgentStart.server.ts
11
+ var beforeAgentStart_server_default = (0, _agimon_ai_doompi_core_extensionFile.defineHook)({
12
+ event: "before_agent_start",
13
+ handle(event, execution) {
14
+ const modelId = execution.model?.id;
15
+ if (!modelId) return void 0;
16
+ const guidance = require_modelGuidanceStore.guidanceForModel(require_modelGuidanceStore.loadModelGuidance(execution.cwd), modelId);
17
+ const systemPrompt = require_modelGuidanceStore.applyModelGuidance(typeof event.systemPrompt === "string" ? event.systemPrompt : "", guidance);
18
+ return systemPrompt ? { systemPrompt } : void 0;
19
+ }
20
+ });
21
+ //#endregion
22
+ //#region src/extensions/workspaces/sessions/(backend)/resource/doompiModelGuidance.server.ts
23
+ var doompiModelGuidance_server_default = (0, _agimon_ai_doompi_core_extensionFile.defineResource)({
24
+ when: {
25
+ state: { "minor-mode": "help" },
26
+ attribution: {
27
+ kind: "minor",
28
+ mode: "help"
29
+ }
30
+ },
31
+ name: "doompi-model-guidance",
32
+ kind: "context",
33
+ read: () => (0, _agimon_ai_doompi_core_serverFacet.readPackageResource)(require("url").pathToFileURL(__filename).href, "llms.txt")
34
+ });
35
+ //#endregion
36
+ //#region src/extensions/workspaces/sessions/(backend)/resource/_lib/doompiUseModelGuidance.server.ts
37
+ var doompiUseModelGuidance_server_default$1 = {
38
+ name: "doompi-use-model-guidance",
39
+ when: _agimon_ai_doompi_core_help.DOOM_HELP_WHEN,
40
+ kind: "skill",
41
+ read: () => (0, _agimon_ai_doompi_core_serverFacet.readPackageResource)(require("url").pathToFileURL(__filename).href, "src/prompts/doompi-use-model-guidance/SKILL.md")
42
+ };
43
+ //#endregion
44
+ //#region src/extensions/workspaces/sessions/(backend)/resource/doompiUseModelGuidance.server.ts
45
+ var doompiUseModelGuidance_server_default = (0, _agimon_ai_doompi_core_extensionFile.defineResource)(doompiUseModelGuidance_server_default$1);
46
+ //#endregion
47
+ //#region generated/server.ts
48
+ const at = (value, context) => typeof value === "function" ? value(context) : value;
49
+ const via = (identity, value) => value === void 0 ? void 0 : {
50
+ ...identity,
51
+ ...value
52
+ };
53
+ const facet = (0, _agimon_ai_doompi_core_serverFacet.defineServerPlugin)({
54
+ name: "@agimon-ai/doompi-model-guidance",
55
+ session: (context) => ({
56
+ get hooks() {
57
+ return [via({ event: "before_agent_start" }, at(beforeAgentStart_server_default, context))];
58
+ },
59
+ get resources() {
60
+ return [at(doompiModelGuidance_server_default, context), at(doompiUseModelGuidance_server_default, context)];
61
+ }
62
+ })
63
+ });
64
+ //#endregion
65
+ exports.default = facet;
66
+ exports.facet = facet;
67
+
68
+ //# sourceMappingURL=server.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.cjs","names":["guidanceForModel","loadModelGuidance","applyModelGuidance","defineHook","contribution","readPackageResource","defineResource","contribution","DOOM_HELP_WHEN","readPackageResource","defineResource","contribution","defineServerPlugin","hookBeforeAgentStart","resourceDoompiModelGuidance","resourceDoompiUseModelGuidance"],"sources":["../../src/extensions/workspaces/sessions/(backend)/hook/_lib/beforeAgentStart.server.ts","../../src/extensions/workspaces/sessions/(backend)/hook/beforeAgentStart.server.ts","../../src/extensions/workspaces/sessions/(backend)/resource/_lib/doompiModelGuidance.server.ts","../../src/extensions/workspaces/sessions/(backend)/resource/doompiModelGuidance.server.ts","../../src/extensions/workspaces/sessions/(backend)/resource/_lib/doompiUseModelGuidance.server.ts","../../src/extensions/workspaces/sessions/(backend)/resource/doompiUseModelGuidance.server.ts","../../generated/server.ts"],"sourcesContent":["import type { DoomHeadlessHook } from '@agimon-ai/doompi-core/headless';\n\nimport { applyModelGuidance, guidanceForModel } from '../../../../../../services/modelGuidance';\nimport { loadModelGuidance } from '../../../../../../services/modelGuidanceStore';\n\nexport const modelGuidanceHook: DoomHeadlessHook = {\n event: 'before_agent_start',\n handle(event, execution) {\n const modelId = execution.model?.id;\n if (!modelId) return undefined;\n const guidance = guidanceForModel(loadModelGuidance(execution.cwd), modelId);\n const systemPrompt = applyModelGuidance(typeof event.systemPrompt === 'string' ? event.systemPrompt : '', guidance);\n return systemPrompt ? { systemPrompt } : undefined;\n },\n};\n\nexport default modelGuidanceHook;\n","import { defineHook } from '@agimon-ai/doompi-core/extensionFile';\n\nimport contribution from './_lib/beforeAgentStart.server';\n\nexport default defineHook(contribution);\n","import { readPackageResource } from '@agimon-ai/doompi-core/serverFacet';\n\nexport default {\n // The package index is Help-catalog material, not standing instruction, so it\n // only enters the prompt while Help mode is active.\n when: { state: { 'minor-mode': 'help' }, attribution: { kind: 'minor' as const, mode: 'help' } },\n name: 'doompi-model-guidance',\n kind: 'context' as const,\n read: () => readPackageResource(import.meta.url, 'llms.txt'),\n};\n","import { defineResource } from '@agimon-ai/doompi-core/extensionFile';\n\nimport contribution from './_lib/doompiModelGuidance.server';\n\nexport default defineResource(contribution);\n","import { DOOM_HELP_WHEN } from '@agimon-ai/doompi-core/help';\nimport { readPackageResource } from '@agimon-ai/doompi-core/serverFacet';\n\nexport default {\n name: 'doompi-use-model-guidance',\n when: DOOM_HELP_WHEN,\n kind: 'skill' as const,\n read: () => readPackageResource(import.meta.url, 'src/prompts/doompi-use-model-guidance/SKILL.md'),\n};\n","import { defineResource } from '@agimon-ai/doompi-core/extensionFile';\n\nimport contribution from './_lib/doompiUseModelGuidance.server';\n\nexport default defineResource(contribution);\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { defineServerPlugin, type DoomServerSessionPlugin } from '@agimon-ai/doompi-core/serverFacet';\n\nimport hookBeforeAgentStart from '../src/extensions/workspaces/sessions/(backend)/hook/beforeAgentStart.server';\nimport resourceDoompiModelGuidance from '../src/extensions/workspaces/sessions/(backend)/resource/doompiModelGuidance.server';\nimport resourceDoompiUseModelGuidance from '../src/extensions/workspaces/sessions/(backend)/resource/doompiUseModelGuidance.server';\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nexport const facet = defineServerPlugin({\n name: '@agimon-ai/doompi-model-guidance',\n session: (context) => ({\n get hooks(): DoomServerSessionPlugin['hooks'] { return [via({ event: 'before_agent_start' }, at(hookBeforeAgentStart, context))]; },\n get resources(): DoomServerSessionPlugin['resources'] { return [at(resourceDoompiModelGuidance, context), at(resourceDoompiUseModelGuidance, context)]; },\n }),\n});\n\nexport default facet;\n"],"mappings":";;;;;;;;;;ACIA,IAAA,mCAAA,GAAeG,qCAAAA,WAAAA,CAAWC;CDExB,OAAO;CACP,OAAO,OAAO,WAAW;EACvB,MAAM,UAAU,UAAU,OAAO;EACjC,IAAI,CAAC,SAAS,OAAO,KAAA;EACrB,MAAM,WAAWJ,2BAAAA,iBAAiBC,2BAAAA,kBAAkB,UAAU,GAAG,GAAG,OAAO;EAC3E,MAAM,eAAeC,2BAAAA,mBAAmB,OAAO,MAAM,iBAAiB,WAAW,MAAM,eAAe,IAAI,QAAQ;EAClH,OAAO,eAAe,EAAE,aAAa,IAAI,KAAA;CAC3C;ACTwBE,CAAY;;;AEAtC,IAAA,sCAAA,GAAeE,qCAAAA,eAAAA,CAAeC;CDC5B,MAAM;EAAE,OAAO,EAAE,cAAc,OAAO;EAAG,aAAa;GAAE,MAAM;GAAkB,MAAM;EAAO;CAAE;CAC/F,MAAM;CACN,MAAM;CACN,aAAA,GAAYF,mCAAAA,oBAAAA,CAAAA,QAAAA,KAAAA,CAAAA,CAAAA,cAAAA,UAAAA,CAAAA,CAAAA,MAAqC,UAAU;ACJ/BE,CAAY;;;ACD1C,IAAA,0CAAe;CACb,MAAM;CACN,MAAMC,4BAAAA;CACN,MAAM;CACN,aAAA,GAAYC,mCAAAA,oBAAAA,CAAAA,QAAAA,KAAAA,CAAAA,CAAAA,cAAAA,UAAAA,CAAAA,CAAAA,MAAqC,gDAAgD;AACnG;;;ACJA,IAAA,yCAAA,GAAeC,qCAAAA,eAAAA,CAAeC,uCAAY;;;ACI1C,MAAM,MAAY,OAA0B,YAC1C,OAAO,UAAU,aAAc,MAAwB,OAAO,IAAI;AACpE,MAAM,OAAU,UAAmC,UAChD,UAAU,KAAA,IAAY,KAAA,IAAY;CAAE,GAAG;CAAU,GAAI;AAAiB;AAEzE,MAAa,SAAA,GAAQC,mCAAAA,mBAAAA,CAAmB;CACtC,MAAM;CACN,UAAU,aAAa;EACrB,IAAI,QAA0C;GAAE,OAAO,CAAC,IAAI,EAAE,OAAO,qBAAqB,GAAG,GAAGC,iCAAsB,OAAO,CAAC,CAAC;EAAG;EAClI,IAAI,YAAkD;GAAE,OAAO,CAAC,GAAGC,oCAA6B,OAAO,GAAG,GAAGC,uCAAgC,OAAO,CAAC;EAAG;CAC1J;AACF,CAAC"}
@@ -0,0 +1,5 @@
1
+ //#region generated/server.d.ts
2
+ export declare const facet: import("@agimon-ai/doompi-core/serverFacet").DoomServerFacet;
3
+ //#endregion
4
+ export { facet as default };
5
+ //# sourceMappingURL=server.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.mts","names":[],"sources":["../../generated/server.ts"],"mappings":";qBAaa,oDAAK"}
@@ -0,0 +1,60 @@
1
+ import { i as guidanceForModel, n as loadModelGuidance, r as applyModelGuidance } from "../modelGuidanceStore-BPKgawjz.mjs";
2
+ import { defineHook, defineResource } from "@agimon-ai/doompi-core/extensionFile";
3
+ import { defineServerPlugin, readPackageResource } from "@agimon-ai/doompi-core/serverFacet";
4
+ import { DOOM_HELP_WHEN } from "@agimon-ai/doompi-core/help";
5
+ //#endregion
6
+ //#region src/extensions/workspaces/sessions/(backend)/hook/beforeAgentStart.server.ts
7
+ var beforeAgentStart_server_default = defineHook({
8
+ event: "before_agent_start",
9
+ handle(event, execution) {
10
+ const modelId = execution.model?.id;
11
+ if (!modelId) return void 0;
12
+ const guidance = guidanceForModel(loadModelGuidance(execution.cwd), modelId);
13
+ const systemPrompt = applyModelGuidance(typeof event.systemPrompt === "string" ? event.systemPrompt : "", guidance);
14
+ return systemPrompt ? { systemPrompt } : void 0;
15
+ }
16
+ });
17
+ //#endregion
18
+ //#region src/extensions/workspaces/sessions/(backend)/resource/doompiModelGuidance.server.ts
19
+ var doompiModelGuidance_server_default = defineResource({
20
+ when: {
21
+ state: { "minor-mode": "help" },
22
+ attribution: {
23
+ kind: "minor",
24
+ mode: "help"
25
+ }
26
+ },
27
+ name: "doompi-model-guidance",
28
+ kind: "context",
29
+ read: () => readPackageResource(import.meta.url, "llms.txt")
30
+ });
31
+ //#endregion
32
+ //#region src/extensions/workspaces/sessions/(backend)/resource/doompiUseModelGuidance.server.ts
33
+ var doompiUseModelGuidance_server_default = defineResource({
34
+ name: "doompi-use-model-guidance",
35
+ when: DOOM_HELP_WHEN,
36
+ kind: "skill",
37
+ read: () => readPackageResource(import.meta.url, "src/prompts/doompi-use-model-guidance/SKILL.md")
38
+ });
39
+ //#endregion
40
+ //#region generated/server.ts
41
+ const at = (value, context) => typeof value === "function" ? value(context) : value;
42
+ const via = (identity, value) => value === void 0 ? void 0 : {
43
+ ...identity,
44
+ ...value
45
+ };
46
+ const facet = defineServerPlugin({
47
+ name: "@agimon-ai/doompi-model-guidance",
48
+ session: (context) => ({
49
+ get hooks() {
50
+ return [via({ event: "before_agent_start" }, at(beforeAgentStart_server_default, context))];
51
+ },
52
+ get resources() {
53
+ return [at(doompiModelGuidance_server_default, context), at(doompiUseModelGuidance_server_default, context)];
54
+ }
55
+ })
56
+ });
57
+ //#endregion
58
+ export { facet as default, facet };
59
+
60
+ //# sourceMappingURL=server.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.mjs","names":["contribution","contribution","contribution","hookBeforeAgentStart","resourceDoompiModelGuidance","resourceDoompiUseModelGuidance"],"sources":["../../src/extensions/workspaces/sessions/(backend)/hook/_lib/beforeAgentStart.server.ts","../../src/extensions/workspaces/sessions/(backend)/hook/beforeAgentStart.server.ts","../../src/extensions/workspaces/sessions/(backend)/resource/_lib/doompiModelGuidance.server.ts","../../src/extensions/workspaces/sessions/(backend)/resource/doompiModelGuidance.server.ts","../../src/extensions/workspaces/sessions/(backend)/resource/_lib/doompiUseModelGuidance.server.ts","../../src/extensions/workspaces/sessions/(backend)/resource/doompiUseModelGuidance.server.ts","../../generated/server.ts"],"sourcesContent":["import type { DoomHeadlessHook } from '@agimon-ai/doompi-core/headless';\n\nimport { applyModelGuidance, guidanceForModel } from '../../../../../../services/modelGuidance';\nimport { loadModelGuidance } from '../../../../../../services/modelGuidanceStore';\n\nexport const modelGuidanceHook: DoomHeadlessHook = {\n event: 'before_agent_start',\n handle(event, execution) {\n const modelId = execution.model?.id;\n if (!modelId) return undefined;\n const guidance = guidanceForModel(loadModelGuidance(execution.cwd), modelId);\n const systemPrompt = applyModelGuidance(typeof event.systemPrompt === 'string' ? event.systemPrompt : '', guidance);\n return systemPrompt ? { systemPrompt } : undefined;\n },\n};\n\nexport default modelGuidanceHook;\n","import { defineHook } from '@agimon-ai/doompi-core/extensionFile';\n\nimport contribution from './_lib/beforeAgentStart.server';\n\nexport default defineHook(contribution);\n","import { readPackageResource } from '@agimon-ai/doompi-core/serverFacet';\n\nexport default {\n // The package index is Help-catalog material, not standing instruction, so it\n // only enters the prompt while Help mode is active.\n when: { state: { 'minor-mode': 'help' }, attribution: { kind: 'minor' as const, mode: 'help' } },\n name: 'doompi-model-guidance',\n kind: 'context' as const,\n read: () => readPackageResource(import.meta.url, 'llms.txt'),\n};\n","import { defineResource } from '@agimon-ai/doompi-core/extensionFile';\n\nimport contribution from './_lib/doompiModelGuidance.server';\n\nexport default defineResource(contribution);\n","import { DOOM_HELP_WHEN } from '@agimon-ai/doompi-core/help';\nimport { readPackageResource } from '@agimon-ai/doompi-core/serverFacet';\n\nexport default {\n name: 'doompi-use-model-guidance',\n when: DOOM_HELP_WHEN,\n kind: 'skill' as const,\n read: () => readPackageResource(import.meta.url, 'src/prompts/doompi-use-model-guidance/SKILL.md'),\n};\n","import { defineResource } from '@agimon-ai/doompi-core/extensionFile';\n\nimport contribution from './_lib/doompiUseModelGuidance.server';\n\nexport default defineResource(contribution);\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { defineServerPlugin, type DoomServerSessionPlugin } from '@agimon-ai/doompi-core/serverFacet';\n\nimport hookBeforeAgentStart from '../src/extensions/workspaces/sessions/(backend)/hook/beforeAgentStart.server';\nimport resourceDoompiModelGuidance from '../src/extensions/workspaces/sessions/(backend)/resource/doompiModelGuidance.server';\nimport resourceDoompiUseModelGuidance from '../src/extensions/workspaces/sessions/(backend)/resource/doompiUseModelGuidance.server';\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nexport const facet = defineServerPlugin({\n name: '@agimon-ai/doompi-model-guidance',\n session: (context) => ({\n get hooks(): DoomServerSessionPlugin['hooks'] { return [via({ event: 'before_agent_start' }, at(hookBeforeAgentStart, context))]; },\n get resources(): DoomServerSessionPlugin['resources'] { return [at(resourceDoompiModelGuidance, context), at(resourceDoompiUseModelGuidance, context)]; },\n }),\n});\n\nexport default facet;\n"],"mappings":";;;;;;ACIA,IAAA,kCAAe,WAAWA;CDExB,OAAO;CACP,OAAO,OAAO,WAAW;EACvB,MAAM,UAAU,UAAU,OAAO;EACjC,IAAI,CAAC,SAAS,OAAO,KAAA;EACrB,MAAM,WAAW,iBAAiB,kBAAkB,UAAU,GAAG,GAAG,OAAO;EAC3E,MAAM,eAAe,mBAAmB,OAAO,MAAM,iBAAiB,WAAW,MAAM,eAAe,IAAI,QAAQ;EAClH,OAAO,eAAe,EAAE,aAAa,IAAI,KAAA;CAC3C;ACTwBA,CAAY;;;AEAtC,IAAA,qCAAe,eAAeC;CDC5B,MAAM;EAAE,OAAO,EAAE,cAAc,OAAO;EAAG,aAAa;GAAE,MAAM;GAAkB,MAAM;EAAO;CAAE;CAC/F,MAAM;CACN,MAAM;CACN,YAAY,oBAAoB,YAAY,KAAK,UAAU;ACJ/BA,CAAY;;;AEA1C,IAAA,wCAAe,eAAeC;CDA5B,MAAM;CACN,MAAM;CACN,MAAM;CACN,YAAY,oBAAoB,YAAY,KAAK,gDAAgD;ACHrEA,CAAY;;;ACI1C,MAAM,MAAY,OAA0B,YAC1C,OAAO,UAAU,aAAc,MAAwB,OAAO,IAAI;AACpE,MAAM,OAAU,UAAmC,UAChD,UAAU,KAAA,IAAY,KAAA,IAAY;CAAE,GAAG;CAAU,GAAI;AAAiB;AAEzE,MAAa,QAAQ,mBAAmB;CACtC,MAAM;CACN,UAAU,aAAa;EACrB,IAAI,QAA0C;GAAE,OAAO,CAAC,IAAI,EAAE,OAAO,qBAAqB,GAAG,GAAGC,iCAAsB,OAAO,CAAC,CAAC;EAAG;EAClI,IAAI,YAAkD;GAAE,OAAO,CAAC,GAAGC,oCAA6B,OAAO,GAAG,GAAGC,uCAAgC,OAAO,CAAC;EAAG;CAC1J;AACF,CAAC"}
package/dist/index.cjs ADDED
@@ -0,0 +1,8 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_modelGuidanceStore = require("./modelGuidanceStore-DEs_jtoI.cjs");
3
+ exports.DEFAULT_MODEL_GUIDANCE_PRESET = require_modelGuidanceStore.DEFAULT_MODEL_GUIDANCE_PRESET;
4
+ exports.GUIDANCE_FILE = require_modelGuidanceStore.GUIDANCE_FILE;
5
+ exports.applyModelGuidance = require_modelGuidanceStore.applyModelGuidance;
6
+ exports.guidanceForModel = require_modelGuidanceStore.guidanceForModel;
7
+ exports.loadModelGuidance = require_modelGuidanceStore.loadModelGuidance;
8
+ exports.mergeModelGuidance = require_modelGuidanceStore.mergeModelGuidance;
@@ -0,0 +1,66 @@
1
+ //#region src/types/modelGuidance.d.ts
2
+ /**
3
+ * Wire and domain shapes for per-model system prompt guidance.
4
+ *
5
+ * Document values are `unknown` rather than `string` because a guidance file is
6
+ * user-authored YAML: the parser cannot promise a string, so the fold narrows
7
+ * each value instead of asserting one.
8
+ */
9
+ /** Raw shape of one `.doom/model-guidance.yaml` document. */
10
+ interface ModelGuidanceDocument {
11
+ readonly modelGuidance?: Readonly<Record<string, unknown>>;
12
+ }
13
+ /** Model id to guidance text, after the global and repository documents are folded. */
14
+ type ModelGuidanceMap = Readonly<Record<string, string>>;
15
+ //#endregion
16
+ //#region src/services/modelGuidanceStore/index.d.ts
17
+ /** Layered guidance document, read from the global then the repository `.doom` directory. */
18
+ export declare const GUIDANCE_FILE = "model-guidance.yaml";
19
+ /**
20
+ * Reads and folds the global and repository guidance documents.
21
+ *
22
+ * Fails open. The reader parses YAML without a guard, so a typo in an optional
23
+ * prompt file would otherwise throw on every turn of the session. Degrading to
24
+ * the built-in preset keeps the package useful without letting malformed user
25
+ * input end the turn.
26
+ *
27
+ * `homeDirectory` exists so a test can point the global scope at a temporary
28
+ * directory; production callers omit it and the reader falls back to the real home.
29
+ */
30
+ export declare function loadModelGuidance(repositoryRoot: string | undefined, homeDirectory?: string): ModelGuidanceMap;
31
+ //#endregion
32
+ //#region src/constants/modelGuidance.d.ts
33
+ export declare const DEFAULT_MODEL_GUIDANCE_PRESET: {
34
+ readonly modelGuidance: {
35
+ readonly 'gpt-6-astra': 'Continue executing an agreed plan and its scoped tasks without pausing for small decisions or repeated confirmation. Treat the accepted plan and task list as authorization to complete the work, make reasonable low-risk and reversible implementation choices, and verify the result. Ask only when blocked or when a decision would materially change scope, requirements, security, data safety, or destructive behavior.';
36
+ };
37
+ };
38
+ //#endregion
39
+ //#region src/services/modelGuidance/index.d.ts
40
+ /**
41
+ * Folds guidance documents in source order, so a later document overrides one
42
+ * model id at a time.
43
+ *
44
+ * The reader hands back global then repository, so a repository entry wins the
45
+ * ids it names while global entries it does not name survive. That per-id
46
+ * granularity is the point: a personal default stays useful inside a project
47
+ * that only pins one model.
48
+ *
49
+ * Non-string values are dropped rather than rejected, because a guidance file is
50
+ * optional user input and one bad entry must not discard the rest.
51
+ */
52
+ export declare function mergeModelGuidance(documents: readonly ModelGuidanceDocument[]): ModelGuidanceMap;
53
+ /** Exact-match lookup. An unknown or absent model id contributes nothing. */
54
+ export declare function guidanceForModel(guidance: ModelGuidanceMap, modelId: string | undefined): string | undefined;
55
+ /**
56
+ * Builds the replacement system prompt for one turn.
57
+ *
58
+ * Pi treats a returned `systemPrompt` as a full replacement and chains handlers,
59
+ * so the incoming prompt has to be re-embedded. Returning bare guidance would
60
+ * discard every earlier contribution, including plan mode and the persona.
61
+ * Keeping that in one function leaves a single place for it to be right.
62
+ */
63
+ export declare function applyModelGuidance(systemPrompt: string, guidance: string | undefined): string | undefined;
64
+ //#endregion
65
+ export type { ModelGuidanceDocument, ModelGuidanceMap };
66
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/types/modelGuidance.ts","../src/services/modelGuidanceStore/index.ts","../src/constants/modelGuidance.ts","../src/services/modelGuidance/index.ts"],"mappings":";;;;;;;;;UASiB;WACN,gBAAgB,SAAS;;;KAIxB,mBAAmB,SAAS;;;;qBCP3B;;;;;;;;;;;;wBAaG,kBAAkB,oCAAoC,yBAAyB;;;qBChBlF;WAAkC;aAF3C;;;;;;;;;;;;;;;;;wBCeY,mBAAmB,oBAAoB,0BAA0B;;wBAajE,iBAAiB,UAAU,kBAAkB;;;;;;;;;wBAa7C,mBAAmB,sBAAsB"}
package/dist/index.mjs ADDED
@@ -0,0 +1,2 @@
1
+ import { a as mergeModelGuidance, i as guidanceForModel, n as loadModelGuidance, o as DEFAULT_MODEL_GUIDANCE_PRESET, r as applyModelGuidance, t as GUIDANCE_FILE } from "./modelGuidanceStore-BPKgawjz.mjs";
2
+ export { DEFAULT_MODEL_GUIDANCE_PRESET, GUIDANCE_FILE, applyModelGuidance, guidanceForModel, loadModelGuidance, mergeModelGuidance };
@@ -0,0 +1,76 @@
1
+ import { readDoomConfigSources } from "@agimon-ai/doompi-config/layeredConfig";
2
+ //#region src/constants/modelGuidance.ts
3
+ const DEFAULT_GUIDANCE = { "gpt-6-astra": "Continue executing an agreed plan and its scoped tasks without pausing for small decisions or repeated confirmation. Treat the accepted plan and task list as authorization to complete the work, make reasonable low-risk and reversible implementation choices, and verify the result. Ask only when blocked or when a decision would materially change scope, requirements, security, data safety, or destructive behavior." };
4
+ const DEFAULT_MODEL_GUIDANCE_PRESET = { modelGuidance: DEFAULT_GUIDANCE };
5
+ //#endregion
6
+ //#region src/services/modelGuidance/index.ts
7
+ Object.freeze(DEFAULT_GUIDANCE);
8
+ Object.freeze(DEFAULT_MODEL_GUIDANCE_PRESET);
9
+ /**
10
+ * Folds guidance documents in source order, so a later document overrides one
11
+ * model id at a time.
12
+ *
13
+ * The reader hands back global then repository, so a repository entry wins the
14
+ * ids it names while global entries it does not name survive. That per-id
15
+ * granularity is the point: a personal default stays useful inside a project
16
+ * that only pins one model.
17
+ *
18
+ * Non-string values are dropped rather than rejected, because a guidance file is
19
+ * optional user input and one bad entry must not discard the rest.
20
+ */
21
+ function mergeModelGuidance(documents) {
22
+ const merged = {};
23
+ for (const document of documents) for (const [modelId, guidance] of Object.entries(document.modelGuidance ?? {})) {
24
+ if (typeof guidance !== "string") continue;
25
+ const trimmed = guidance.trim();
26
+ if (trimmed) merged[modelId] = trimmed;
27
+ }
28
+ return merged;
29
+ }
30
+ /** Exact-match lookup. An unknown or absent model id contributes nothing. */
31
+ function guidanceForModel(guidance, modelId) {
32
+ if (!modelId) return void 0;
33
+ return guidance[modelId];
34
+ }
35
+ /**
36
+ * Builds the replacement system prompt for one turn.
37
+ *
38
+ * Pi treats a returned `systemPrompt` as a full replacement and chains handlers,
39
+ * so the incoming prompt has to be re-embedded. Returning bare guidance would
40
+ * discard every earlier contribution, including plan mode and the persona.
41
+ * Keeping that in one function leaves a single place for it to be right.
42
+ */
43
+ function applyModelGuidance(systemPrompt, guidance) {
44
+ if (!guidance) return void 0;
45
+ return `${systemPrompt}\n\n${guidance}`;
46
+ }
47
+ //#endregion
48
+ //#region src/services/modelGuidanceStore/index.ts
49
+ /** Layered guidance document, read from the global then the repository `.doom` directory. */
50
+ const GUIDANCE_FILE = "model-guidance.yaml";
51
+ /**
52
+ * Reads and folds the global and repository guidance documents.
53
+ *
54
+ * Fails open. The reader parses YAML without a guard, so a typo in an optional
55
+ * prompt file would otherwise throw on every turn of the session. Degrading to
56
+ * the built-in preset keeps the package useful without letting malformed user
57
+ * input end the turn.
58
+ *
59
+ * `homeDirectory` exists so a test can point the global scope at a temporary
60
+ * directory; production callers omit it and the reader falls back to the real home.
61
+ */
62
+ function loadModelGuidance(repositoryRoot, homeDirectory) {
63
+ if (!repositoryRoot) return DEFAULT_GUIDANCE;
64
+ try {
65
+ const sources = readDoomConfigSources(GUIDANCE_FILE, repositoryRoot, homeDirectory);
66
+ return mergeModelGuidance([DEFAULT_MODEL_GUIDANCE_PRESET, ...sources.map((source) => source.document)]);
67
+ } catch (error) {
68
+ const reason = error instanceof Error ? error.message : String(error);
69
+ process.stderr.write(`[doompi-model-guidance] could not read ${GUIDANCE_FILE}: ${reason}\n`);
70
+ return DEFAULT_GUIDANCE;
71
+ }
72
+ }
73
+ //#endregion
74
+ export { mergeModelGuidance as a, guidanceForModel as i, loadModelGuidance as n, DEFAULT_MODEL_GUIDANCE_PRESET as o, applyModelGuidance as r, GUIDANCE_FILE as t };
75
+
76
+ //# sourceMappingURL=modelGuidanceStore-BPKgawjz.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modelGuidanceStore-BPKgawjz.mjs","names":[],"sources":["../src/constants/modelGuidance.ts","../src/services/modelGuidance/index.ts","../src/services/modelGuidanceStore/index.ts"],"sourcesContent":["export const DEFAULT_GUIDANCE = {\n 'gpt-6-astra':\n 'Continue executing an agreed plan and its scoped tasks without pausing for small decisions or repeated confirmation. Treat the accepted plan and task list as authorization to complete the work, make reasonable low-risk and reversible implementation choices, and verify the result. Ask only when blocked or when a decision would materially change scope, requirements, security, data safety, or destructive behavior.',\n} as const;\nexport const DEFAULT_MODEL_GUIDANCE_PRESET = { modelGuidance: DEFAULT_GUIDANCE } as const;\n","import { DEFAULT_GUIDANCE, DEFAULT_MODEL_GUIDANCE_PRESET } from '../../constants/modelGuidance';\nimport type { ModelGuidanceDocument, ModelGuidanceMap } from '../../types/modelGuidance';\nexport { DEFAULT_MODEL_GUIDANCE_PRESET } from '../../constants/modelGuidance';\nObject.freeze(DEFAULT_GUIDANCE);\nObject.freeze(DEFAULT_MODEL_GUIDANCE_PRESET);\n/**\n * Folds guidance documents in source order, so a later document overrides one\n * model id at a time.\n *\n * The reader hands back global then repository, so a repository entry wins the\n * ids it names while global entries it does not name survive. That per-id\n * granularity is the point: a personal default stays useful inside a project\n * that only pins one model.\n *\n * Non-string values are dropped rather than rejected, because a guidance file is\n * optional user input and one bad entry must not discard the rest.\n */\nexport function mergeModelGuidance(documents: readonly ModelGuidanceDocument[]): ModelGuidanceMap {\n const merged: Record<string, string> = {};\n for (const document of documents) {\n for (const [modelId, guidance] of Object.entries(document.modelGuidance ?? {})) {\n if (typeof guidance !== 'string') continue;\n const trimmed = guidance.trim();\n if (trimmed) merged[modelId] = trimmed;\n }\n }\n return merged;\n}\n\n/** Exact-match lookup. An unknown or absent model id contributes nothing. */\nexport function guidanceForModel(guidance: ModelGuidanceMap, modelId: string | undefined): string | undefined {\n if (!modelId) return undefined;\n return guidance[modelId];\n}\n\n/**\n * Builds the replacement system prompt for one turn.\n *\n * Pi treats a returned `systemPrompt` as a full replacement and chains handlers,\n * so the incoming prompt has to be re-embedded. Returning bare guidance would\n * discard every earlier contribution, including plan mode and the persona.\n * Keeping that in one function leaves a single place for it to be right.\n */\nexport function applyModelGuidance(systemPrompt: string, guidance: string | undefined): string | undefined {\n if (!guidance) return undefined;\n return `${systemPrompt}\\n\\n${guidance}`;\n}\n","import { readDoomConfigSources } from '@agimon-ai/doompi-config/layeredConfig';\n\nimport { DEFAULT_GUIDANCE } from '../../constants/modelGuidance';\nimport type { ModelGuidanceDocument, ModelGuidanceMap } from '../../types/modelGuidance';\nimport { DEFAULT_MODEL_GUIDANCE_PRESET, mergeModelGuidance } from '../modelGuidance';\n\n/** Layered guidance document, read from the global then the repository `.doom` directory. */\nexport const GUIDANCE_FILE = 'model-guidance.yaml';\n\n/**\n * Reads and folds the global and repository guidance documents.\n *\n * Fails open. The reader parses YAML without a guard, so a typo in an optional\n * prompt file would otherwise throw on every turn of the session. Degrading to\n * the built-in preset keeps the package useful without letting malformed user\n * input end the turn.\n *\n * `homeDirectory` exists so a test can point the global scope at a temporary\n * directory; production callers omit it and the reader falls back to the real home.\n */\nexport function loadModelGuidance(repositoryRoot: string | undefined, homeDirectory?: string): ModelGuidanceMap {\n if (!repositoryRoot) return DEFAULT_GUIDANCE;\n\n try {\n const sources = readDoomConfigSources<ModelGuidanceDocument>(GUIDANCE_FILE, repositoryRoot, homeDirectory);\n return mergeModelGuidance([DEFAULT_MODEL_GUIDANCE_PRESET, ...sources.map((source) => source.document)]);\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[doompi-model-guidance] could not read ${GUIDANCE_FILE}: ${reason}\\n`);\n return DEFAULT_GUIDANCE;\n }\n}\n"],"mappings":";;AAAA,MAAa,mBAAmB,EAC9B,eACE,iaACJ;AACA,MAAa,gCAAgC,EAAE,eAAe,iBAAiB;;;ACD/E,OAAO,OAAO,gBAAgB;AAC9B,OAAO,OAAO,6BAA6B;;;;;;;;;;;;;AAa3C,SAAgB,mBAAmB,WAA+D;CAChG,MAAM,SAAiC,CAAC;CACxC,KAAK,MAAM,YAAY,WACrB,KAAK,MAAM,CAAC,SAAS,aAAa,OAAO,QAAQ,SAAS,iBAAiB,CAAC,CAAC,GAAG;EAC9E,IAAI,OAAO,aAAa,UAAU;EAClC,MAAM,UAAU,SAAS,KAAK;EAC9B,IAAI,SAAS,OAAO,WAAW;CACjC;CAEF,OAAO;AACT;;AAGA,SAAgB,iBAAiB,UAA4B,SAAiD;CAC5G,IAAI,CAAC,SAAS,OAAO,KAAA;CACrB,OAAO,SAAS;AAClB;;;;;;;;;AAUA,SAAgB,mBAAmB,cAAsB,UAAkD;CACzG,IAAI,CAAC,UAAU,OAAO,KAAA;CACtB,OAAO,GAAG,aAAa,MAAM;AAC/B;;;;ACvCA,MAAa,gBAAgB;;;;;;;;;;;;AAa7B,SAAgB,kBAAkB,gBAAoC,eAA0C;CAC9G,IAAI,CAAC,gBAAgB,OAAO;CAE5B,IAAI;EACF,MAAM,UAAU,sBAA6C,eAAe,gBAAgB,aAAa;EACzG,OAAO,mBAAmB,CAAC,+BAA+B,GAAG,QAAQ,KAAK,WAAW,OAAO,QAAQ,CAAC,CAAC;CACxG,SAAS,OAAO;EACd,MAAM,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;EACpE,QAAQ,OAAO,MAAM,0CAA0C,cAAc,IAAI,OAAO,GAAG;EAC3F,OAAO;CACT;AACF"}
@@ -0,0 +1,111 @@
1
+ let _agimon_ai_doompi_config_layeredConfig = require("@agimon-ai/doompi-config/layeredConfig");
2
+ //#region src/constants/modelGuidance.ts
3
+ const DEFAULT_GUIDANCE = { "gpt-6-astra": "Continue executing an agreed plan and its scoped tasks without pausing for small decisions or repeated confirmation. Treat the accepted plan and task list as authorization to complete the work, make reasonable low-risk and reversible implementation choices, and verify the result. Ask only when blocked or when a decision would materially change scope, requirements, security, data safety, or destructive behavior." };
4
+ const DEFAULT_MODEL_GUIDANCE_PRESET = { modelGuidance: DEFAULT_GUIDANCE };
5
+ //#endregion
6
+ //#region src/services/modelGuidance/index.ts
7
+ Object.freeze(DEFAULT_GUIDANCE);
8
+ Object.freeze(DEFAULT_MODEL_GUIDANCE_PRESET);
9
+ /**
10
+ * Folds guidance documents in source order, so a later document overrides one
11
+ * model id at a time.
12
+ *
13
+ * The reader hands back global then repository, so a repository entry wins the
14
+ * ids it names while global entries it does not name survive. That per-id
15
+ * granularity is the point: a personal default stays useful inside a project
16
+ * that only pins one model.
17
+ *
18
+ * Non-string values are dropped rather than rejected, because a guidance file is
19
+ * optional user input and one bad entry must not discard the rest.
20
+ */
21
+ function mergeModelGuidance(documents) {
22
+ const merged = {};
23
+ for (const document of documents) for (const [modelId, guidance] of Object.entries(document.modelGuidance ?? {})) {
24
+ if (typeof guidance !== "string") continue;
25
+ const trimmed = guidance.trim();
26
+ if (trimmed) merged[modelId] = trimmed;
27
+ }
28
+ return merged;
29
+ }
30
+ /** Exact-match lookup. An unknown or absent model id contributes nothing. */
31
+ function guidanceForModel(guidance, modelId) {
32
+ if (!modelId) return void 0;
33
+ return guidance[modelId];
34
+ }
35
+ /**
36
+ * Builds the replacement system prompt for one turn.
37
+ *
38
+ * Pi treats a returned `systemPrompt` as a full replacement and chains handlers,
39
+ * so the incoming prompt has to be re-embedded. Returning bare guidance would
40
+ * discard every earlier contribution, including plan mode and the persona.
41
+ * Keeping that in one function leaves a single place for it to be right.
42
+ */
43
+ function applyModelGuidance(systemPrompt, guidance) {
44
+ if (!guidance) return void 0;
45
+ return `${systemPrompt}\n\n${guidance}`;
46
+ }
47
+ //#endregion
48
+ //#region src/services/modelGuidanceStore/index.ts
49
+ /** Layered guidance document, read from the global then the repository `.doom` directory. */
50
+ const GUIDANCE_FILE = "model-guidance.yaml";
51
+ /**
52
+ * Reads and folds the global and repository guidance documents.
53
+ *
54
+ * Fails open. The reader parses YAML without a guard, so a typo in an optional
55
+ * prompt file would otherwise throw on every turn of the session. Degrading to
56
+ * the built-in preset keeps the package useful without letting malformed user
57
+ * input end the turn.
58
+ *
59
+ * `homeDirectory` exists so a test can point the global scope at a temporary
60
+ * directory; production callers omit it and the reader falls back to the real home.
61
+ */
62
+ function loadModelGuidance(repositoryRoot, homeDirectory) {
63
+ if (!repositoryRoot) return DEFAULT_GUIDANCE;
64
+ try {
65
+ const sources = (0, _agimon_ai_doompi_config_layeredConfig.readDoomConfigSources)(GUIDANCE_FILE, repositoryRoot, homeDirectory);
66
+ return mergeModelGuidance([DEFAULT_MODEL_GUIDANCE_PRESET, ...sources.map((source) => source.document)]);
67
+ } catch (error) {
68
+ const reason = error instanceof Error ? error.message : String(error);
69
+ process.stderr.write(`[doompi-model-guidance] could not read ${GUIDANCE_FILE}: ${reason}\n`);
70
+ return DEFAULT_GUIDANCE;
71
+ }
72
+ }
73
+ //#endregion
74
+ Object.defineProperty(exports, "DEFAULT_MODEL_GUIDANCE_PRESET", {
75
+ enumerable: true,
76
+ get: function() {
77
+ return DEFAULT_MODEL_GUIDANCE_PRESET;
78
+ }
79
+ });
80
+ Object.defineProperty(exports, "GUIDANCE_FILE", {
81
+ enumerable: true,
82
+ get: function() {
83
+ return GUIDANCE_FILE;
84
+ }
85
+ });
86
+ Object.defineProperty(exports, "applyModelGuidance", {
87
+ enumerable: true,
88
+ get: function() {
89
+ return applyModelGuidance;
90
+ }
91
+ });
92
+ Object.defineProperty(exports, "guidanceForModel", {
93
+ enumerable: true,
94
+ get: function() {
95
+ return guidanceForModel;
96
+ }
97
+ });
98
+ Object.defineProperty(exports, "loadModelGuidance", {
99
+ enumerable: true,
100
+ get: function() {
101
+ return loadModelGuidance;
102
+ }
103
+ });
104
+ Object.defineProperty(exports, "mergeModelGuidance", {
105
+ enumerable: true,
106
+ get: function() {
107
+ return mergeModelGuidance;
108
+ }
109
+ });
110
+
111
+ //# sourceMappingURL=modelGuidanceStore-DEs_jtoI.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modelGuidanceStore-DEs_jtoI.cjs","names":["readDoomConfigSources"],"sources":["../src/constants/modelGuidance.ts","../src/services/modelGuidance/index.ts","../src/services/modelGuidanceStore/index.ts"],"sourcesContent":["export const DEFAULT_GUIDANCE = {\n 'gpt-6-astra':\n 'Continue executing an agreed plan and its scoped tasks without pausing for small decisions or repeated confirmation. Treat the accepted plan and task list as authorization to complete the work, make reasonable low-risk and reversible implementation choices, and verify the result. Ask only when blocked or when a decision would materially change scope, requirements, security, data safety, or destructive behavior.',\n} as const;\nexport const DEFAULT_MODEL_GUIDANCE_PRESET = { modelGuidance: DEFAULT_GUIDANCE } as const;\n","import { DEFAULT_GUIDANCE, DEFAULT_MODEL_GUIDANCE_PRESET } from '../../constants/modelGuidance';\nimport type { ModelGuidanceDocument, ModelGuidanceMap } from '../../types/modelGuidance';\nexport { DEFAULT_MODEL_GUIDANCE_PRESET } from '../../constants/modelGuidance';\nObject.freeze(DEFAULT_GUIDANCE);\nObject.freeze(DEFAULT_MODEL_GUIDANCE_PRESET);\n/**\n * Folds guidance documents in source order, so a later document overrides one\n * model id at a time.\n *\n * The reader hands back global then repository, so a repository entry wins the\n * ids it names while global entries it does not name survive. That per-id\n * granularity is the point: a personal default stays useful inside a project\n * that only pins one model.\n *\n * Non-string values are dropped rather than rejected, because a guidance file is\n * optional user input and one bad entry must not discard the rest.\n */\nexport function mergeModelGuidance(documents: readonly ModelGuidanceDocument[]): ModelGuidanceMap {\n const merged: Record<string, string> = {};\n for (const document of documents) {\n for (const [modelId, guidance] of Object.entries(document.modelGuidance ?? {})) {\n if (typeof guidance !== 'string') continue;\n const trimmed = guidance.trim();\n if (trimmed) merged[modelId] = trimmed;\n }\n }\n return merged;\n}\n\n/** Exact-match lookup. An unknown or absent model id contributes nothing. */\nexport function guidanceForModel(guidance: ModelGuidanceMap, modelId: string | undefined): string | undefined {\n if (!modelId) return undefined;\n return guidance[modelId];\n}\n\n/**\n * Builds the replacement system prompt for one turn.\n *\n * Pi treats a returned `systemPrompt` as a full replacement and chains handlers,\n * so the incoming prompt has to be re-embedded. Returning bare guidance would\n * discard every earlier contribution, including plan mode and the persona.\n * Keeping that in one function leaves a single place for it to be right.\n */\nexport function applyModelGuidance(systemPrompt: string, guidance: string | undefined): string | undefined {\n if (!guidance) return undefined;\n return `${systemPrompt}\\n\\n${guidance}`;\n}\n","import { readDoomConfigSources } from '@agimon-ai/doompi-config/layeredConfig';\n\nimport { DEFAULT_GUIDANCE } from '../../constants/modelGuidance';\nimport type { ModelGuidanceDocument, ModelGuidanceMap } from '../../types/modelGuidance';\nimport { DEFAULT_MODEL_GUIDANCE_PRESET, mergeModelGuidance } from '../modelGuidance';\n\n/** Layered guidance document, read from the global then the repository `.doom` directory. */\nexport const GUIDANCE_FILE = 'model-guidance.yaml';\n\n/**\n * Reads and folds the global and repository guidance documents.\n *\n * Fails open. The reader parses YAML without a guard, so a typo in an optional\n * prompt file would otherwise throw on every turn of the session. Degrading to\n * the built-in preset keeps the package useful without letting malformed user\n * input end the turn.\n *\n * `homeDirectory` exists so a test can point the global scope at a temporary\n * directory; production callers omit it and the reader falls back to the real home.\n */\nexport function loadModelGuidance(repositoryRoot: string | undefined, homeDirectory?: string): ModelGuidanceMap {\n if (!repositoryRoot) return DEFAULT_GUIDANCE;\n\n try {\n const sources = readDoomConfigSources<ModelGuidanceDocument>(GUIDANCE_FILE, repositoryRoot, homeDirectory);\n return mergeModelGuidance([DEFAULT_MODEL_GUIDANCE_PRESET, ...sources.map((source) => source.document)]);\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[doompi-model-guidance] could not read ${GUIDANCE_FILE}: ${reason}\\n`);\n return DEFAULT_GUIDANCE;\n }\n}\n"],"mappings":";;AAAA,MAAa,mBAAmB,EAC9B,eACE,iaACJ;AACA,MAAa,gCAAgC,EAAE,eAAe,iBAAiB;;;ACD/E,OAAO,OAAO,gBAAgB;AAC9B,OAAO,OAAO,6BAA6B;;;;;;;;;;;;;AAa3C,SAAgB,mBAAmB,WAA+D;CAChG,MAAM,SAAiC,CAAC;CACxC,KAAK,MAAM,YAAY,WACrB,KAAK,MAAM,CAAC,SAAS,aAAa,OAAO,QAAQ,SAAS,iBAAiB,CAAC,CAAC,GAAG;EAC9E,IAAI,OAAO,aAAa,UAAU;EAClC,MAAM,UAAU,SAAS,KAAK;EAC9B,IAAI,SAAS,OAAO,WAAW;CACjC;CAEF,OAAO;AACT;;AAGA,SAAgB,iBAAiB,UAA4B,SAAiD;CAC5G,IAAI,CAAC,SAAS,OAAO,KAAA;CACrB,OAAO,SAAS;AAClB;;;;;;;;;AAUA,SAAgB,mBAAmB,cAAsB,UAAkD;CACzG,IAAI,CAAC,UAAU,OAAO,KAAA;CACtB,OAAO,GAAG,aAAa,MAAM;AAC/B;;;;ACvCA,MAAa,gBAAgB;;;;;;;;;;;;AAa7B,SAAgB,kBAAkB,gBAAoC,eAA0C;CAC9G,IAAI,CAAC,gBAAgB,OAAO;CAE5B,IAAI;EACF,MAAM,WAAA,GAAUA,uCAAAA,sBAAAA,CAA6C,eAAe,gBAAgB,aAAa;EACzG,OAAO,mBAAmB,CAAC,+BAA+B,GAAG,QAAQ,KAAK,WAAW,OAAO,QAAQ,CAAC,CAAC;CACxG,SAAS,OAAO;EACd,MAAM,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;EACpE,QAAQ,OAAO,MAAM,0CAA0C,cAAc,IAAI,OAAO,GAAG;EAC3F,OAAO;CACT;AACF"}
package/llms.txt ADDED
@@ -0,0 +1,11 @@
1
+ # @agimon-ai/doompi-model-guidance
2
+
3
+ Package-owned guidance for per-model system prompt guidance, layered across global and repository scope
4
+
5
+ ## How to use
6
+
7
+ - [Use Model Guidance](./src/prompts/doompi-use-model-guidance/SKILL.md): Configure per-model system prompt text and understand how the two scopes merge.
8
+
9
+ ## Resources
10
+
11
+ - [Package README](./README.md): Installation, development commands, Pi entrypoint, and extension-specific usage.
package/package.json ADDED
@@ -0,0 +1,123 @@
1
+ {
2
+ "name": "@agimon-ai/doompi-model-guidance",
3
+ "version": "0.0.1-alpha.101",
4
+ "description": "Per-model system prompt guidance for Pi agents, layered across global and repository scope.",
5
+ "keywords": [
6
+ "ai",
7
+ "coding-agent",
8
+ "developer-tools",
9
+ "doompi",
10
+ "model-guidance",
11
+ "pi-coding-agent",
12
+ "pi-extension",
13
+ "pi-package",
14
+ "system-prompt",
15
+ "typescript"
16
+ ],
17
+ "homepage": "https://agimon.ai",
18
+ "bugs": {
19
+ "url": "https://github.com/AgiFlow/doompi/issues"
20
+ },
21
+ "license": "MIT",
22
+ "author": "Vuong Ngo",
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git+https://github.com/AgiFlow/doompi.git",
26
+ "directory": "layers/llm/doompi-model-guidance"
27
+ },
28
+ "files": [
29
+ "dist",
30
+ "src/prompts",
31
+ "llms.txt",
32
+ "README.md",
33
+ "LICENSE",
34
+ "package.json"
35
+ ],
36
+ "type": "module",
37
+ "main": "./dist/index.cjs",
38
+ "module": "./dist/index.mjs",
39
+ "types": "./dist/index.d.mts",
40
+ "jsnext:main": "./dist/index.mjs",
41
+ "exports": {
42
+ ".": {
43
+ "types": "./dist/index.d.mts",
44
+ "import": "./dist/index.mjs",
45
+ "require": "./dist/index.cjs"
46
+ },
47
+ "./apiContracts": {
48
+ "types": "./dist/apiContracts.d.mts",
49
+ "import": "./dist/apiContracts.mjs",
50
+ "require": "./dist/apiContracts.cjs"
51
+ },
52
+ "./extensions/pi": {
53
+ "types": "./dist/extensions/pi.d.mts",
54
+ "import": "./dist/extensions/pi.mjs",
55
+ "require": "./dist/extensions/pi.cjs"
56
+ },
57
+ "./extensions/server": {
58
+ "types": "./dist/extensions/server.d.mts",
59
+ "import": "./dist/extensions/server.mjs",
60
+ "require": "./dist/extensions/server.cjs"
61
+ },
62
+ "./package.json": "./package.json"
63
+ },
64
+ "publishConfig": {
65
+ "access": "public"
66
+ },
67
+ "dependencies": {
68
+ "@agimon-ai/doompi-config": "0.0.1-alpha.101",
69
+ "@agimon-ai/doompi-core": "0.0.1-alpha.102",
70
+ "@deepseek-ai/cordis": "4.0.2"
71
+ },
72
+ "devDependencies": {
73
+ "@agimon-ai/doompi-build": "0.0.1-alpha.24",
74
+ "@earendil-works/pi-coding-agent": "0.99.1",
75
+ "@types/node": "26.6.2",
76
+ "@vitest/coverage-v8": "5.0.1",
77
+ "tsdown": "0.23.0",
78
+ "typescript": "7.0.2",
79
+ "vitest": "5.0.1"
80
+ },
81
+ "peerDependencies": {
82
+ "@earendil-works/pi-coding-agent": "0.99.1"
83
+ },
84
+ "peerDependenciesMeta": {
85
+ "@earendil-works/pi-coding-agent": {
86
+ "optional": true
87
+ }
88
+ },
89
+ "engines": {
90
+ "node": ">=22.19.0"
91
+ },
92
+ "doompiMcp": {
93
+ "entry": "./generated/mcp.ts",
94
+ "dist": "./dist/extensions/mcp.mjs",
95
+ "scopes": [
96
+ "session"
97
+ ]
98
+ },
99
+ "doompiServer": {
100
+ "entry": "./generated/server.ts",
101
+ "dist": "./dist/extensions/server.mjs",
102
+ "scopes": [
103
+ "session"
104
+ ],
105
+ "contracts": {
106
+ "entry": "./src/exports/apiContracts.ts",
107
+ "dist": "./dist/apiContracts.mjs"
108
+ }
109
+ },
110
+ "pi": {
111
+ "extensions": [
112
+ "./dist/extensions/pi.mjs"
113
+ ]
114
+ },
115
+ "scripts": {
116
+ "build": "tsdown && pnpm build:mcp",
117
+ "build:mcp": "tsdown --config tsdown.mcp.config.ts",
118
+ "test": "vitest --run",
119
+ "typecheck": "tsc --noEmit",
120
+ "lint": "oxlint . && oxfmt . --check",
121
+ "fixcode": "oxlint . --fix && oxfmt ."
122
+ }
123
+ }
@@ -0,0 +1,34 @@
1
+ ---
2
+ name: doompi-use-model-guidance
3
+ description: 'Use @agimon-ai/doompi-model-guidance: per-model system prompt guidance, layered across global and repository scope'
4
+ ---
5
+
6
+ # Use Model Guidance
7
+
8
+ Read the package [README](../../../README.md) for its exact installation, configuration, and behavior.
9
+
10
+ ## Guidance
11
+
12
+ Importing the package as a bare entry in `modes.yaml` activates its built-in
13
+ `default` preset, including the package guidance for `gpt-6-astra`.
14
+
15
+ Override or add guidance for a model id in either scope:
16
+
17
+ - Global, applying to every repository: `~/.pi/.doom/model-guidance.yaml`
18
+ - Repository, applying to one project: `<repository>/.doom/model-guidance.yaml`
19
+
20
+ ```yaml
21
+ modelGuidance:
22
+ claude-opus-5: |
23
+ Keep the task focused. Never go off rails.
24
+ ```
25
+
26
+ Model ids match exactly. Use the id shown by `/model`, not a family or a
27
+ marketing name. A model with no custom entry uses its built-in preset entry when
28
+ one exists; otherwise it gets no guidance.
29
+
30
+ The built-in preset applies first. Global guidance overrides it per model id,
31
+ then repository guidance overrides global guidance per model id.
32
+
33
+ Guidance is read per turn, so an edit takes effect on the next message with no
34
+ restart.