@agimon-ai/doompi-prompt 0.0.1-alpha.7 → 0.0.1-alpha.71
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/README.md +15 -6
- package/dist/apiContracts.cjs +74 -0
- package/dist/apiContracts.cjs.map +1 -0
- package/dist/apiContracts.d.mts +52 -0
- package/dist/apiContracts.d.mts.map +1 -0
- package/dist/apiContracts.mjs +69 -0
- package/dist/apiContracts.mjs.map +1 -0
- package/dist/extensions/mcp.cjs +26 -0
- package/dist/extensions/mcp.cjs.map +1 -0
- package/dist/extensions/mcp.d.mts +5 -0
- package/dist/extensions/mcp.d.mts.map +1 -0
- package/dist/extensions/mcp.mjs +21 -0
- package/dist/extensions/mcp.mjs.map +1 -0
- package/dist/extensions/pi.cjs +291 -1
- package/dist/extensions/pi.cjs.map +1 -0
- package/dist/extensions/pi.d.mts +6 -2
- package/dist/extensions/pi.d.mts.map +1 -0
- package/dist/extensions/pi.mjs +286 -1
- package/dist/extensions/pi.mjs.map +1 -0
- package/dist/extensions/server.cjs +246 -0
- package/dist/extensions/server.cjs.map +1 -0
- package/dist/extensions/server.d.mts +5 -0
- package/dist/extensions/server.d.mts.map +1 -0
- package/dist/extensions/server.mjs +236 -0
- package/dist/extensions/server.mjs.map +1 -0
- package/dist/extensions/web.mjs +646 -0
- package/dist/extensions/web.mjs.map +1 -0
- package/dist/index-CWFHu9EV.d.mts +119 -0
- package/dist/index-CWFHu9EV.d.mts.map +1 -0
- package/dist/index.cjs +13 -1
- package/dist/index.d.mts +2 -7
- package/dist/index.mjs +3 -1
- package/dist/promptStore-Doy0oftz.cjs +259 -0
- package/dist/promptStore-Doy0oftz.cjs.map +1 -0
- package/dist/promptStore-Ehe2rceM.mjs +189 -0
- package/dist/promptStore-Ehe2rceM.mjs.map +1 -0
- package/dist/prompts-BKQpY3LX.mjs +8 -0
- package/dist/prompts-BKQpY3LX.mjs.map +1 -0
- package/dist/prompts-ByVGxNSX.cjs +25 -0
- package/dist/prompts-ByVGxNSX.cjs.map +1 -0
- package/dist/recentPrompts-Dg3OkaQV.cjs +46 -0
- package/dist/recentPrompts-Dg3OkaQV.cjs.map +1 -0
- package/dist/recentPrompts-Dll78smX.mjs +35 -0
- package/dist/recentPrompts-Dll78smX.mjs.map +1 -0
- package/package.json +61 -36
- package/dist/_virtual/_rolldown/runtime.cjs +0 -1
- package/dist/adapters/hubApi.cjs +0 -2
- package/dist/adapters/hubApi.cjs.map +0 -1
- package/dist/adapters/hubApi.d.cts +0 -13
- package/dist/adapters/hubApi.d.cts.map +0 -1
- package/dist/adapters/hubApi.d.mts +0 -13
- package/dist/adapters/hubApi.d.mts.map +0 -1
- package/dist/adapters/hubApi.mjs +0 -2
- package/dist/adapters/hubApi.mjs.map +0 -1
- package/dist/adapters/node/promptStore.cjs +0 -2
- package/dist/adapters/node/promptStore.cjs.map +0 -1
- package/dist/adapters/node/promptStore.d.cts +0 -12
- package/dist/adapters/node/promptStore.d.cts.map +0 -1
- package/dist/adapters/node/promptStore.d.mts +0 -12
- package/dist/adapters/node/promptStore.d.mts.map +0 -1
- package/dist/adapters/node/promptStore.mjs +0 -2
- package/dist/adapters/node/promptStore.mjs.map +0 -1
- package/dist/adapters/pi/extension.cjs +0 -2
- package/dist/adapters/pi/extension.cjs.map +0 -1
- package/dist/adapters/pi/extension.d.cts +0 -19
- package/dist/adapters/pi/extension.d.cts.map +0 -1
- package/dist/adapters/pi/extension.d.mts +0 -19
- package/dist/adapters/pi/extension.d.mts.map +0 -1
- package/dist/adapters/pi/extension.mjs +0 -2
- package/dist/adapters/pi/extension.mjs.map +0 -1
- package/dist/adapters/pi/inputCapture.cjs +0 -2
- package/dist/adapters/pi/inputCapture.cjs.map +0 -1
- package/dist/adapters/pi/inputCapture.mjs +0 -2
- package/dist/adapters/pi/inputCapture.mjs.map +0 -1
- package/dist/adapters/pi/leader.cjs +0 -2
- package/dist/adapters/pi/leader.cjs.map +0 -1
- package/dist/adapters/pi/leader.mjs +0 -2
- package/dist/adapters/pi/leader.mjs.map +0 -1
- package/dist/adapters/pi/promptConstants.cjs +0 -2
- package/dist/adapters/pi/promptConstants.cjs.map +0 -1
- package/dist/adapters/pi/promptConstants.mjs +0 -2
- package/dist/adapters/pi/promptConstants.mjs.map +0 -1
- package/dist/commands/promptSaveCommand.cjs +0 -2
- package/dist/commands/promptSaveCommand.cjs.map +0 -1
- package/dist/commands/promptSaveCommand.mjs +0 -2
- package/dist/commands/promptSaveCommand.mjs.map +0 -1
- package/dist/commands/promptsCommand.cjs +0 -2
- package/dist/commands/promptsCommand.cjs.map +0 -1
- package/dist/commands/promptsCommand.mjs +0 -2
- package/dist/commands/promptsCommand.mjs.map +0 -1
- package/dist/container/index.cjs +0 -2
- package/dist/container/index.cjs.map +0 -1
- package/dist/container/index.d.cts +0 -7
- package/dist/container/index.d.cts.map +0 -1
- package/dist/container/index.d.mts +0 -7
- package/dist/container/index.d.mts.map +0 -1
- package/dist/container/index.mjs +0 -2
- package/dist/container/index.mjs.map +0 -1
- package/dist/extensions/pi.d.cts +0 -2
- package/dist/hubApi.cjs +0 -1
- package/dist/hubApi.d.cts +0 -2
- package/dist/hubApi.d.mts +0 -2
- package/dist/hubApi.mjs +0 -1
- package/dist/index.d.cts +0 -7
- package/dist/services/promptItems.cjs +0 -2
- package/dist/services/promptItems.cjs.map +0 -1
- package/dist/services/promptItems.mjs +0 -2
- package/dist/services/promptItems.mjs.map +0 -1
- package/dist/services/recentPrompts.cjs +0 -2
- package/dist/services/recentPrompts.cjs.map +0 -1
- package/dist/services/recentPrompts.d.cts +0 -20
- package/dist/services/recentPrompts.d.cts.map +0 -1
- package/dist/services/recentPrompts.d.mts +0 -20
- package/dist/services/recentPrompts.d.mts.map +0 -1
- package/dist/services/recentPrompts.mjs +0 -2
- package/dist/services/recentPrompts.mjs.map +0 -1
- package/dist/services/savedPromptDocument.cjs +0 -11
- package/dist/services/savedPromptDocument.cjs.map +0 -1
- package/dist/services/savedPromptDocument.d.cts +0 -21
- package/dist/services/savedPromptDocument.d.cts.map +0 -1
- package/dist/services/savedPromptDocument.d.mts +0 -21
- package/dist/services/savedPromptDocument.d.mts.map +0 -1
- package/dist/services/savedPromptDocument.mjs +0 -11
- package/dist/services/savedPromptDocument.mjs.map +0 -1
- package/dist/types/prompt.d.cts +0 -54
- package/dist/types/prompt.d.cts.map +0 -1
- package/dist/types/prompt.d.mts +0 -54
- package/dist/types/prompt.d.mts.map +0 -1
- package/dist/types/webPrompts.cjs +0 -2
- package/dist/types/webPrompts.cjs.map +0 -1
- package/dist/types/webPrompts.mjs +0 -2
- package/dist/types/webPrompts.mjs.map +0 -1
- package/src/exports/webClient.ts +0 -2
- package/src/types/webPrompts.ts +0 -61
- package/src/web/PromptEditor.tsx +0 -57
- package/src/web/PromptPickerList.tsx +0 -108
- package/src/web/PromptsActivitySection.tsx +0 -69
- package/src/web/PromptsDialog.tsx +0 -111
- package/src/web/index.ts +0 -32
- package/src/web/promptsActions.ts +0 -72
- package/src/web/promptsApi.ts +0 -88
- package/src/web/tsconfig.json +0 -22
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @agimon-ai/doompi-prompt
|
|
2
2
|
|
|
3
|
-
Staged recent prompts and saved prompt templates for DoomPi
|
|
3
|
+
Staged recent prompts and saved prompt templates for DoomPi.
|
|
4
4
|
|
|
5
5
|
This package is a composable [DoomPi](https://www.npmjs.com/package/@agimon-ai/doompi) subsystem. Use it with the distribution or install it independently in [Pi](https://www.npmjs.com/package/@earendil-works/pi-coding-agent).
|
|
6
6
|
|
|
@@ -15,7 +15,9 @@ This package is a composable [DoomPi](https://www.npmjs.com/package/@agimon-ai/d
|
|
|
15
15
|
pi install npm:@agimon-ai/doompi-prompt
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
The package declares its Pi extension entry, so Pi loads it after installation. DoomPi users can
|
|
18
|
+
The package declares its Pi extension entry, so Pi loads it after installation. DoomPi users can
|
|
19
|
+
add `@agimon-ai/doompi-prompt` to `default.packages` or a selected layer's `packages` list in
|
|
20
|
+
`.doom/modes.yaml`.
|
|
19
21
|
|
|
20
22
|
## Use
|
|
21
23
|
|
|
@@ -57,10 +59,13 @@ cursor position, bind `tui.editor.historyPrevious` and `tui.editor.historyNext`
|
|
|
57
59
|
|
|
58
60
|
## Cockpit
|
|
59
61
|
|
|
60
|
-
The package contributes a `
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
The package contributes a `Prompt template` entry to the composer's `+` menu, beside `File Upload`,
|
|
63
|
+
backed by a hub-scoped API at `/api/plugin/prompts`. The entry opens a list-first dialog over the
|
|
64
|
+
conversation, and picking one sends it immediately to the focused session. The same dialog creates
|
|
65
|
+
and edits entries, confirms replacements and removals, and refreshes the list after writes. Every
|
|
66
|
+
text-bearing user message also offers `save as prompt`, opening the editor with that message text
|
|
67
|
+
ready to name or edit. The dialog itself is a cockpit overlay rather than part of the menu, so the
|
|
68
|
+
message action reaches it without the menu being open.
|
|
64
69
|
|
|
65
70
|
| Route | Purpose |
|
|
66
71
|
| ----------------------- | ------------------------------------------------------------------- |
|
|
@@ -116,3 +121,7 @@ Maintained by [Agimon](https://agimon.ai/about).
|
|
|
116
121
|
## License
|
|
117
122
|
|
|
118
123
|
MIT
|
|
124
|
+
|
|
125
|
+
## Extension lifecycle and source layout
|
|
126
|
+
|
|
127
|
+
Direct `extensions/pi.ts`, `extensions/server.ts`, and `extensions/web.ts` entries declare their host contributions. The Pi entry creates a fresh recent-prompt model and saved-prompt store per installation. A service binding owns the optional leader contribution and removes it when the UI provider is replaced or disposed. Controllers declare native Pi UI commands and server request handlers; `services/<name>/` implements document and storage logic. Flat `exports/` publishes selected reusable services, models, constants, and types.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
Object.defineProperties(exports, {
|
|
2
|
+
__esModule: { value: true },
|
|
3
|
+
[Symbol.toStringTag]: { value: "Module" }
|
|
4
|
+
});
|
|
5
|
+
let _agimon_ai_doompi_core_apiContracts = require("@agimon-ai/doompi-core/apiContracts");
|
|
6
|
+
let typebox = require("typebox");
|
|
7
|
+
//#region src/schemas/apiContracts.ts
|
|
8
|
+
const S = typebox.Type.String();
|
|
9
|
+
const B = typebox.Type.Boolean();
|
|
10
|
+
const Prompt = typebox.Type.Object({
|
|
11
|
+
name: S,
|
|
12
|
+
description: S,
|
|
13
|
+
text: S
|
|
14
|
+
});
|
|
15
|
+
const apiContracts = (0, _agimon_ai_doompi_core_apiContracts.defineApiContract)({
|
|
16
|
+
version: 1,
|
|
17
|
+
sockets: [],
|
|
18
|
+
dynamic: [],
|
|
19
|
+
http: [
|
|
20
|
+
"global",
|
|
21
|
+
"workspace",
|
|
22
|
+
"session"
|
|
23
|
+
].flatMap((scope) => [
|
|
24
|
+
{
|
|
25
|
+
id: "prompts.list",
|
|
26
|
+
scope,
|
|
27
|
+
basePath: "prompts",
|
|
28
|
+
path: "/prompts",
|
|
29
|
+
method: "GET",
|
|
30
|
+
authentication: "owner",
|
|
31
|
+
description: "List prompts in this scope.",
|
|
32
|
+
responses: (0, _agimon_ai_doompi_core_apiContracts.jsonApiResponses)(typebox.Type.Object({ prompts: typebox.Type.Array(Prompt) }))
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
id: "prompts.save",
|
|
36
|
+
scope,
|
|
37
|
+
basePath: "prompts",
|
|
38
|
+
path: "/prompts/{name}",
|
|
39
|
+
method: "PUT",
|
|
40
|
+
authentication: "owner",
|
|
41
|
+
description: "Save a prompt. Text is limited to 65536 UTF-8 bytes.",
|
|
42
|
+
body: {
|
|
43
|
+
required: true,
|
|
44
|
+
contentType: "application/json",
|
|
45
|
+
schema: typebox.Type.Object({ text: typebox.Type.String({ minLength: 1 }) })
|
|
46
|
+
},
|
|
47
|
+
responses: {
|
|
48
|
+
...(0, _agimon_ai_doompi_core_apiContracts.jsonApiResponses)(typebox.Type.Object({
|
|
49
|
+
prompt: Prompt,
|
|
50
|
+
replaced: B
|
|
51
|
+
})),
|
|
52
|
+
"413": {
|
|
53
|
+
description: "Prompt text exceeds the byte limit.",
|
|
54
|
+
schema: typebox.Type.Object({ error: S })
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
id: "prompts.delete",
|
|
60
|
+
scope,
|
|
61
|
+
basePath: "prompts",
|
|
62
|
+
path: "/prompts/{name}",
|
|
63
|
+
method: "DELETE",
|
|
64
|
+
authentication: "owner",
|
|
65
|
+
description: "Delete a prompt.",
|
|
66
|
+
responses: (0, _agimon_ai_doompi_core_apiContracts.jsonApiResponses)(typebox.Type.Object({ name: S }))
|
|
67
|
+
}
|
|
68
|
+
])
|
|
69
|
+
});
|
|
70
|
+
//#endregion
|
|
71
|
+
exports.apiContracts = apiContracts;
|
|
72
|
+
exports.default = apiContracts;
|
|
73
|
+
|
|
74
|
+
//# sourceMappingURL=apiContracts.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apiContracts.cjs","names":["Type","defineApiContract","jsonApiResponses"],"sources":["../src/schemas/apiContracts.ts"],"sourcesContent":["import { defineApiContract, jsonApiResponses } from '@agimon-ai/doompi-core/apiContracts';\nimport { Type } from 'typebox';\n\nconst S = Type.String();\nconst B = Type.Boolean();\nconst Prompt = Type.Object({ name: S, description: S, text: S });\nexport const apiContracts = defineApiContract({\n version: 1,\n sockets: [],\n dynamic: [],\n http: (['global', 'workspace', 'session'] as const).flatMap((scope) => [\n {\n id: 'prompts.list',\n scope,\n basePath: 'prompts',\n path: '/prompts',\n method: 'GET',\n authentication: 'owner',\n description: 'List prompts in this scope.',\n responses: jsonApiResponses(Type.Object({ prompts: Type.Array(Prompt) })),\n },\n {\n id: 'prompts.save',\n scope,\n basePath: 'prompts',\n path: '/prompts/{name}',\n method: 'PUT',\n authentication: 'owner',\n description: 'Save a prompt. Text is limited to 65536 UTF-8 bytes.',\n body: {\n required: true,\n contentType: 'application/json',\n schema: Type.Object({ text: Type.String({ minLength: 1 }) }),\n },\n responses: {\n ...jsonApiResponses(Type.Object({ prompt: Prompt, replaced: B })),\n '413': { description: 'Prompt text exceeds the byte limit.', schema: Type.Object({ error: S }) },\n },\n },\n {\n id: 'prompts.delete',\n scope,\n basePath: 'prompts',\n path: '/prompts/{name}',\n method: 'DELETE',\n authentication: 'owner',\n description: 'Delete a prompt.',\n responses: jsonApiResponses(Type.Object({ name: S })),\n },\n ]),\n});\nexport default apiContracts;\n"],"mappings":";;;;;;;AAGA,MAAM,IAAIA,QAAAA,KAAK,OAAO;AACtB,MAAM,IAAIA,QAAAA,KAAK,QAAQ;AACvB,MAAM,SAASA,QAAAA,KAAK,OAAO;CAAE,MAAM;CAAG,aAAa;CAAG,MAAM;AAAE,CAAC;AAC/D,MAAa,gBAAA,GAAeC,oCAAAA,kBAAAA,CAAkB;CAC5C,SAAS;CACT,SAAS,CAAC;CACV,SAAS,CAAC;CACV,MAAO;EAAC;EAAU;EAAa;CAAS,CAAC,CAAW,SAAS,UAAU;EACrE;GACE,IAAI;GACJ;GACA,UAAU;GACV,MAAM;GACN,QAAQ;GACR,gBAAgB;GAChB,aAAa;GACb,YAAA,GAAWC,oCAAAA,iBAAAA,CAAiBF,QAAAA,KAAK,OAAO,EAAE,SAASA,QAAAA,KAAK,MAAM,MAAM,EAAE,CAAC,CAAC;EAC1E;EACA;GACE,IAAI;GACJ;GACA,UAAU;GACV,MAAM;GACN,QAAQ;GACR,gBAAgB;GAChB,aAAa;GACb,MAAM;IACJ,UAAU;IACV,aAAa;IACb,QAAQA,QAAAA,KAAK,OAAO,EAAE,MAAMA,QAAAA,KAAK,OAAO,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;GAC7D;GACA,WAAW;IACT,IAAA,GAAGE,oCAAAA,iBAAAA,CAAiBF,QAAAA,KAAK,OAAO;KAAE,QAAQ;KAAQ,UAAU;IAAE,CAAC,CAAC;IAChE,OAAO;KAAE,aAAa;KAAuC,QAAQA,QAAAA,KAAK,OAAO,EAAE,OAAO,EAAE,CAAC;IAAE;GACjG;EACF;EACA;GACE,IAAI;GACJ;GACA,UAAU;GACV,MAAM;GACN,QAAQ;GACR,gBAAgB;GAChB,aAAa;GACb,YAAA,GAAWE,oCAAAA,iBAAAA,CAAiBF,QAAAA,KAAK,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;EACtD;CACF,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
//#region src/schemas/apiContracts.d.ts
|
|
2
|
+
export declare const apiContracts: {
|
|
3
|
+
version: 1;
|
|
4
|
+
protocols?: Record<string, string> | undefined;
|
|
5
|
+
schemas?: Record<string, boolean | object> | undefined;
|
|
6
|
+
http: {
|
|
7
|
+
id: string;
|
|
8
|
+
scope: "global" | "session" | "workspace";
|
|
9
|
+
basePath?: string | undefined;
|
|
10
|
+
path: string;
|
|
11
|
+
method: "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | "PUT";
|
|
12
|
+
description: string;
|
|
13
|
+
availability?: string | undefined;
|
|
14
|
+
authentication: "device" | "none" | "owner";
|
|
15
|
+
parameters?: {
|
|
16
|
+
name: string;
|
|
17
|
+
in: "header" | "path" | "query";
|
|
18
|
+
required: boolean;
|
|
19
|
+
schema: boolean | object;
|
|
20
|
+
}[] | undefined;
|
|
21
|
+
body?: {
|
|
22
|
+
contentType: string;
|
|
23
|
+
contentTypes?: string[] | undefined;
|
|
24
|
+
required: boolean;
|
|
25
|
+
schema: boolean | object;
|
|
26
|
+
} | undefined;
|
|
27
|
+
responses: Record<string, {
|
|
28
|
+
description: string;
|
|
29
|
+
contentType?: string | undefined;
|
|
30
|
+
schema?: boolean | object | undefined;
|
|
31
|
+
events?: Record<string, boolean | object> | undefined;
|
|
32
|
+
}>;
|
|
33
|
+
}[];
|
|
34
|
+
sockets: {
|
|
35
|
+
id: string;
|
|
36
|
+
scope: "global" | "session" | "workspace";
|
|
37
|
+
description: string;
|
|
38
|
+
availability?: string | undefined;
|
|
39
|
+
service: string;
|
|
40
|
+
member: string;
|
|
41
|
+
direction: "client-to-server" | "server-to-client";
|
|
42
|
+
kind: "channel" | "method" | "state";
|
|
43
|
+
input: boolean | object;
|
|
44
|
+
output?: boolean | object | undefined;
|
|
45
|
+
errors?: boolean | object | undefined;
|
|
46
|
+
}[];
|
|
47
|
+
dynamic: string[];
|
|
48
|
+
gaps?: string[] | undefined;
|
|
49
|
+
};
|
|
50
|
+
//#endregion
|
|
51
|
+
export { apiContracts as default };
|
|
52
|
+
//# sourceMappingURL=apiContracts.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apiContracts.d.mts","names":[],"sources":["../src/schemas/apiContracts.ts"],"mappings":";qBAMa"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { defineApiContract, jsonApiResponses } from "@agimon-ai/doompi-core/apiContracts";
|
|
2
|
+
import { Type } from "typebox";
|
|
3
|
+
//#region src/schemas/apiContracts.ts
|
|
4
|
+
const S = Type.String();
|
|
5
|
+
const B = Type.Boolean();
|
|
6
|
+
const Prompt = Type.Object({
|
|
7
|
+
name: S,
|
|
8
|
+
description: S,
|
|
9
|
+
text: S
|
|
10
|
+
});
|
|
11
|
+
const apiContracts = defineApiContract({
|
|
12
|
+
version: 1,
|
|
13
|
+
sockets: [],
|
|
14
|
+
dynamic: [],
|
|
15
|
+
http: [
|
|
16
|
+
"global",
|
|
17
|
+
"workspace",
|
|
18
|
+
"session"
|
|
19
|
+
].flatMap((scope) => [
|
|
20
|
+
{
|
|
21
|
+
id: "prompts.list",
|
|
22
|
+
scope,
|
|
23
|
+
basePath: "prompts",
|
|
24
|
+
path: "/prompts",
|
|
25
|
+
method: "GET",
|
|
26
|
+
authentication: "owner",
|
|
27
|
+
description: "List prompts in this scope.",
|
|
28
|
+
responses: jsonApiResponses(Type.Object({ prompts: Type.Array(Prompt) }))
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
id: "prompts.save",
|
|
32
|
+
scope,
|
|
33
|
+
basePath: "prompts",
|
|
34
|
+
path: "/prompts/{name}",
|
|
35
|
+
method: "PUT",
|
|
36
|
+
authentication: "owner",
|
|
37
|
+
description: "Save a prompt. Text is limited to 65536 UTF-8 bytes.",
|
|
38
|
+
body: {
|
|
39
|
+
required: true,
|
|
40
|
+
contentType: "application/json",
|
|
41
|
+
schema: Type.Object({ text: Type.String({ minLength: 1 }) })
|
|
42
|
+
},
|
|
43
|
+
responses: {
|
|
44
|
+
...jsonApiResponses(Type.Object({
|
|
45
|
+
prompt: Prompt,
|
|
46
|
+
replaced: B
|
|
47
|
+
})),
|
|
48
|
+
"413": {
|
|
49
|
+
description: "Prompt text exceeds the byte limit.",
|
|
50
|
+
schema: Type.Object({ error: S })
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
id: "prompts.delete",
|
|
56
|
+
scope,
|
|
57
|
+
basePath: "prompts",
|
|
58
|
+
path: "/prompts/{name}",
|
|
59
|
+
method: "DELETE",
|
|
60
|
+
authentication: "owner",
|
|
61
|
+
description: "Delete a prompt.",
|
|
62
|
+
responses: jsonApiResponses(Type.Object({ name: S }))
|
|
63
|
+
}
|
|
64
|
+
])
|
|
65
|
+
});
|
|
66
|
+
//#endregion
|
|
67
|
+
export { apiContracts, apiContracts as default };
|
|
68
|
+
|
|
69
|
+
//# sourceMappingURL=apiContracts.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apiContracts.mjs","names":[],"sources":["../src/schemas/apiContracts.ts"],"sourcesContent":["import { defineApiContract, jsonApiResponses } from '@agimon-ai/doompi-core/apiContracts';\nimport { Type } from 'typebox';\n\nconst S = Type.String();\nconst B = Type.Boolean();\nconst Prompt = Type.Object({ name: S, description: S, text: S });\nexport const apiContracts = defineApiContract({\n version: 1,\n sockets: [],\n dynamic: [],\n http: (['global', 'workspace', 'session'] as const).flatMap((scope) => [\n {\n id: 'prompts.list',\n scope,\n basePath: 'prompts',\n path: '/prompts',\n method: 'GET',\n authentication: 'owner',\n description: 'List prompts in this scope.',\n responses: jsonApiResponses(Type.Object({ prompts: Type.Array(Prompt) })),\n },\n {\n id: 'prompts.save',\n scope,\n basePath: 'prompts',\n path: '/prompts/{name}',\n method: 'PUT',\n authentication: 'owner',\n description: 'Save a prompt. Text is limited to 65536 UTF-8 bytes.',\n body: {\n required: true,\n contentType: 'application/json',\n schema: Type.Object({ text: Type.String({ minLength: 1 }) }),\n },\n responses: {\n ...jsonApiResponses(Type.Object({ prompt: Prompt, replaced: B })),\n '413': { description: 'Prompt text exceeds the byte limit.', schema: Type.Object({ error: S }) },\n },\n },\n {\n id: 'prompts.delete',\n scope,\n basePath: 'prompts',\n path: '/prompts/{name}',\n method: 'DELETE',\n authentication: 'owner',\n description: 'Delete a prompt.',\n responses: jsonApiResponses(Type.Object({ name: S })),\n },\n ]),\n});\nexport default apiContracts;\n"],"mappings":";;;AAGA,MAAM,IAAI,KAAK,OAAO;AACtB,MAAM,IAAI,KAAK,QAAQ;AACvB,MAAM,SAAS,KAAK,OAAO;CAAE,MAAM;CAAG,aAAa;CAAG,MAAM;AAAE,CAAC;AAC/D,MAAa,eAAe,kBAAkB;CAC5C,SAAS;CACT,SAAS,CAAC;CACV,SAAS,CAAC;CACV,MAAO;EAAC;EAAU;EAAa;CAAS,CAAC,CAAW,SAAS,UAAU;EACrE;GACE,IAAI;GACJ;GACA,UAAU;GACV,MAAM;GACN,QAAQ;GACR,gBAAgB;GAChB,aAAa;GACb,WAAW,iBAAiB,KAAK,OAAO,EAAE,SAAS,KAAK,MAAM,MAAM,EAAE,CAAC,CAAC;EAC1E;EACA;GACE,IAAI;GACJ;GACA,UAAU;GACV,MAAM;GACN,QAAQ;GACR,gBAAgB;GAChB,aAAa;GACb,MAAM;IACJ,UAAU;IACV,aAAa;IACb,QAAQ,KAAK,OAAO,EAAE,MAAM,KAAK,OAAO,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;GAC7D;GACA,WAAW;IACT,GAAG,iBAAiB,KAAK,OAAO;KAAE,QAAQ;KAAQ,UAAU;IAAE,CAAC,CAAC;IAChE,OAAO;KAAE,aAAa;KAAuC,QAAQ,KAAK,OAAO,EAAE,OAAO,EAAE,CAAC;IAAE;GACjG;EACF;EACA;GACE,IAAI;GACJ;GACA,UAAU;GACV,MAAM;GACN,QAAQ;GACR,gBAAgB;GAChB,aAAa;GACb,WAAW,iBAAiB,KAAK,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;EACtD;CACF,CAAC;AACH,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-prompt.mcp.ts
|
|
8
|
+
var doompi_use_prompt_mcp_default = (0, _agimon_ai_doompi_core_mcpFacet.defineMcpSkill)({
|
|
9
|
+
name: "doompi-use-prompt",
|
|
10
|
+
description: "Use @agimon-ai/doompi-prompt: Staged recent prompts and saved prompt templates for DoomPi",
|
|
11
|
+
read: () => (0, _agimon_ai_doompi_core_serverFacet.readPackageResource)(require("url").pathToFileURL(__filename).href, "src/prompts/doompi-use-prompt/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-prompt",
|
|
18
|
+
session: (context) => ({ get skills() {
|
|
19
|
+
return [at(doompi_use_prompt_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","skillDoompiUsePrompt"],"sources":["../../src/extensions/workspaces/sessions/(backend)/skill/doompi-use-prompt.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-prompt',\n description: 'Use @agimon-ai/doompi-prompt: Staged recent prompts and saved prompt templates for DoomPi',\n read: () => readPackageResource(import.meta.url, 'src/prompts/doompi-use-prompt/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 skillDoompiUsePrompt from '../src/extensions/workspaces/sessions/(backend)/skill/doompi-use-prompt.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-prompt',\n session: (context) => ({\n get skills(): DoomMcpSessionPlugin['skills'] { return [at(skillDoompiUsePrompt, context)]; },\n }) satisfies DoomMcpSessionPlugin,\n});\n\nexport default mcp;\n"],"mappings":";;;;;;;AAGA,IAAA,iCAAA,GAAeA,gCAAAA,eAAAA,CAAe;CAC5B,MAAM;CACN,aAAa;CACb,aAAA,GAAYC,mCAAAA,oBAAAA,CAAAA,QAAAA,KAAAA,CAAAA,CAAAA,cAAAA,UAAAA,CAAAA,CAAAA,MAAqC,wCAAwC;AAC3F,CAAC;;;ACDD,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,+BAAsB,OAAO,CAAC;CAAG,EAC7F;AACF,CAAC"}
|
|
@@ -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-prompt.mcp.ts
|
|
4
|
+
var doompi_use_prompt_mcp_default = defineMcpSkill({
|
|
5
|
+
name: "doompi-use-prompt",
|
|
6
|
+
description: "Use @agimon-ai/doompi-prompt: Staged recent prompts and saved prompt templates for DoomPi",
|
|
7
|
+
read: () => readPackageResource(import.meta.url, "src/prompts/doompi-use-prompt/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-prompt",
|
|
14
|
+
session: (context) => ({ get skills() {
|
|
15
|
+
return [at(doompi_use_prompt_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":["skillDoompiUsePrompt"],"sources":["../../src/extensions/workspaces/sessions/(backend)/skill/doompi-use-prompt.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-prompt',\n description: 'Use @agimon-ai/doompi-prompt: Staged recent prompts and saved prompt templates for DoomPi',\n read: () => readPackageResource(import.meta.url, 'src/prompts/doompi-use-prompt/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 skillDoompiUsePrompt from '../src/extensions/workspaces/sessions/(backend)/skill/doompi-use-prompt.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-prompt',\n session: (context) => ({\n get skills(): DoomMcpSessionPlugin['skills'] { return [at(skillDoompiUsePrompt, context)]; },\n }) satisfies DoomMcpSessionPlugin,\n});\n\nexport default mcp;\n"],"mappings":";;;AAGA,IAAA,gCAAe,eAAe;CAC5B,MAAM;CACN,aAAa;CACb,YAAY,oBAAoB,YAAY,KAAK,wCAAwC;AAC3F,CAAC;;;ACDD,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,+BAAsB,OAAO,CAAC;CAAG,EAC7F;AACF,CAAC"}
|
package/dist/extensions/pi.cjs
CHANGED
|
@@ -1 +1,291 @@
|
|
|
1
|
-
Object.defineProperties(exports,{
|
|
1
|
+
Object.defineProperties(exports, {
|
|
2
|
+
__esModule: { value: true },
|
|
3
|
+
[Symbol.toStringTag]: { value: "Module" }
|
|
4
|
+
});
|
|
5
|
+
const require_promptStore = require("../promptStore-Doy0oftz.cjs");
|
|
6
|
+
const require_recentPrompts = require("../recentPrompts-Dg3OkaQV.cjs");
|
|
7
|
+
const require_prompts = require("../prompts-ByVGxNSX.cjs");
|
|
8
|
+
let _agimon_ai_doompi_core_piExtension = require("@agimon-ai/doompi-core/piExtension");
|
|
9
|
+
let _agimon_ai_doompi_core_extensionFile = require("@agimon-ai/doompi-core/extensionFile");
|
|
10
|
+
let _agimon_ai_doompi_core_uiHub = require("@agimon-ai/doompi-core/uiHub");
|
|
11
|
+
//#region src/constants/prompt.ts
|
|
12
|
+
/** Values shared by this package's Pi-facing adapters. */
|
|
13
|
+
const PACKAGE_SOURCE = "@agimon-ai/doompi-prompt";
|
|
14
|
+
const LEADER_BINDING_PREFIX = "doom-prompt";
|
|
15
|
+
/**
|
|
16
|
+
* The shared extension group other packages already contribute to. Key, label
|
|
17
|
+
* and order have to match theirs or the leader panel shows two `e` groups.
|
|
18
|
+
*/
|
|
19
|
+
const LEADER_GROUP = {
|
|
20
|
+
key: "e",
|
|
21
|
+
label: "extension",
|
|
22
|
+
detail: "tools, skills and config",
|
|
23
|
+
order: 50
|
|
24
|
+
};
|
|
25
|
+
const LEADER_LABEL = "prompts";
|
|
26
|
+
const LEADER_DETAIL = "staged and saved prompts";
|
|
27
|
+
const PROMPT_HELP_SKILL = {
|
|
28
|
+
name: "doompi-use-prompt",
|
|
29
|
+
description: "Use @agimon-ai/doompi-prompt: Staged recent prompts and saved prompt templates for DoomPi"
|
|
30
|
+
};
|
|
31
|
+
//#endregion
|
|
32
|
+
//#region src/services/promptLeader/index.ts
|
|
33
|
+
/** Puts the picker on the leader map, and takes it back off on dispose. */
|
|
34
|
+
function registerLeaderContribution(hub) {
|
|
35
|
+
const contribution = hub.registerLeader({
|
|
36
|
+
source: PACKAGE_SOURCE,
|
|
37
|
+
bindings: [{
|
|
38
|
+
id: `${LEADER_BINDING_PREFIX}.open`,
|
|
39
|
+
path: [LEADER_GROUP, {
|
|
40
|
+
key: "p",
|
|
41
|
+
label: LEADER_LABEL,
|
|
42
|
+
detail: LEADER_DETAIL
|
|
43
|
+
}],
|
|
44
|
+
command: { name: require_prompts.COMMAND_NAME }
|
|
45
|
+
}]
|
|
46
|
+
});
|
|
47
|
+
return () => contribution.dispose();
|
|
48
|
+
}
|
|
49
|
+
function promptLeaderService(context) {
|
|
50
|
+
context.inject([_agimon_ai_doompi_core_uiHub.DOOM_UI_HUB_SERVICE], (uiContext) => registerLeaderContribution((0, _agimon_ai_doompi_core_uiHub.requireDoomUiHub)(uiContext)));
|
|
51
|
+
}
|
|
52
|
+
//#endregion
|
|
53
|
+
//#region src/extensions/workspaces/sessions/(backend)/_lib/piRoot.ts
|
|
54
|
+
const createPromptPiRoot = ({ options }) => ({
|
|
55
|
+
value: options ?? {
|
|
56
|
+
store: require_promptStore.createNodeSavedPromptStore(),
|
|
57
|
+
recent: require_recentPrompts.createRecentPrompts()
|
|
58
|
+
},
|
|
59
|
+
services: [promptLeaderService]
|
|
60
|
+
});
|
|
61
|
+
//#endregion
|
|
62
|
+
//#region src/extensions/workspaces/sessions/(backend)/root.cli.ts
|
|
63
|
+
var root_cli_default = (0, _agimon_ai_doompi_core_extensionFile.defineRoot)(createPromptPiRoot);
|
|
64
|
+
//#endregion
|
|
65
|
+
//#region src/constants/promptSave.ts
|
|
66
|
+
const COMMAND_NAME = "prompt-save";
|
|
67
|
+
const COMMAND_DESCRIPTION = "Save the current prompt for reuse in later sessions";
|
|
68
|
+
//#endregion
|
|
69
|
+
//#region src/constants/promptSaveCommand.ts
|
|
70
|
+
const WARNING$1 = "warning";
|
|
71
|
+
const INFO$1 = "info";
|
|
72
|
+
//#endregion
|
|
73
|
+
//#region src/services/promptSaveCommand/index.ts
|
|
74
|
+
/**
|
|
75
|
+
* `/prompt-save <name>`: keep the current prompt for later sessions.
|
|
76
|
+
*
|
|
77
|
+
* DESIGN PATTERNS:
|
|
78
|
+
* - Saves what the user is looking at: the editor draft, or the newest staged
|
|
79
|
+
* prompt when the editor is empty.
|
|
80
|
+
* - Writes a plain Pi prompt template, so the saved prompt becomes `/<name>`
|
|
81
|
+
* on the next start without this package registering a command for it.
|
|
82
|
+
*
|
|
83
|
+
* AVOID:
|
|
84
|
+
* - Overwriting an existing template without asking.
|
|
85
|
+
*/
|
|
86
|
+
function createPromptSaveCommand(deps) {
|
|
87
|
+
return [COMMAND_NAME, {
|
|
88
|
+
description: COMMAND_DESCRIPTION,
|
|
89
|
+
handler: async (args, ctx) => {
|
|
90
|
+
if (!ctx.hasUI) return;
|
|
91
|
+
const name = args.trim();
|
|
92
|
+
if (!name) {
|
|
93
|
+
ctx.ui.notify(`Usage: /${COMMAND_NAME} <name>`, WARNING$1);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (!require_promptStore.isValidPromptName(name)) {
|
|
97
|
+
ctx.ui.notify(`"${name}" is not a usable prompt name. Use ${require_promptStore.PROMPT_NAME_RULE}.`, WARNING$1);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
const text = ctx.ui.getEditorText().trim() || deps.recent.list()[0] || "";
|
|
101
|
+
if (!text) {
|
|
102
|
+
ctx.ui.notify("Nothing to save: the editor is empty and no prompt is staged.", WARNING$1);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
try {
|
|
106
|
+
if (await deps.store.has(name)) {
|
|
107
|
+
if (!await ctx.ui.confirm("Replace saved prompt", `A prompt named "${name}" already exists.`)) return;
|
|
108
|
+
}
|
|
109
|
+
const written = await deps.store.save({
|
|
110
|
+
name,
|
|
111
|
+
description: require_promptStore.describePrompt(text),
|
|
112
|
+
text
|
|
113
|
+
});
|
|
114
|
+
const warning = require_promptStore.hasArgumentTokens(text) ? " It contains $ tokens, which Pi substitutes as template arguments when you run the command." : "";
|
|
115
|
+
ctx.ui.notify(`Saved ${written.path}. Use it from /${require_prompts.COMMAND_NAME}, or as /${name} after the next start.${warning}`, INFO$1);
|
|
116
|
+
} catch (error) {
|
|
117
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
118
|
+
ctx.ui.notify(`Could not save "${name}": ${reason}`, WARNING$1);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}];
|
|
122
|
+
}
|
|
123
|
+
//#endregion
|
|
124
|
+
//#region src/extensions/workspaces/sessions/(backend)/command/prompt-save.cli.ts
|
|
125
|
+
var prompt_save_cli_default = (0, _agimon_ai_doompi_core_extensionFile.defineRoutedContribution)((context) => [createPromptSaveCommand(context.root)], { cardinality: "many" });
|
|
126
|
+
//#endregion
|
|
127
|
+
//#region src/constants/promptsCommand.ts
|
|
128
|
+
const PICKER_TITLE = "Prompts";
|
|
129
|
+
const WARNING = "warning";
|
|
130
|
+
const INFO = "info";
|
|
131
|
+
//#endregion
|
|
132
|
+
//#region src/constants/promptItems.ts
|
|
133
|
+
const RECENT_VALUE_PREFIX = "recent:";
|
|
134
|
+
const SAVED_VALUE_PREFIX = "saved:";
|
|
135
|
+
//#endregion
|
|
136
|
+
//#region src/services/promptItems/index.ts
|
|
137
|
+
function promptItems(recent, saved) {
|
|
138
|
+
const items = [];
|
|
139
|
+
for (const [index, text] of recent.entries()) items.push({
|
|
140
|
+
value: `${RECENT_VALUE_PREFIX}${String(index)}`,
|
|
141
|
+
label: require_promptStore.describePrompt(text) || text,
|
|
142
|
+
description: "staged this session"
|
|
143
|
+
});
|
|
144
|
+
for (const prompt of saved) items.push({
|
|
145
|
+
value: `${SAVED_VALUE_PREFIX}${prompt.name}`,
|
|
146
|
+
label: `/${prompt.name}`,
|
|
147
|
+
description: prompt.description || require_promptStore.describePrompt(prompt.text)
|
|
148
|
+
});
|
|
149
|
+
return items;
|
|
150
|
+
}
|
|
151
|
+
/** Reads a picker value back into the entry it points at. */
|
|
152
|
+
function parsePromptSelection(value) {
|
|
153
|
+
if (value.startsWith("recent:")) return {
|
|
154
|
+
kind: "recent",
|
|
155
|
+
key: value.slice(7)
|
|
156
|
+
};
|
|
157
|
+
if (value.startsWith("saved:")) return {
|
|
158
|
+
kind: "saved",
|
|
159
|
+
key: value.slice(6)
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
/** The text a selected row stages, or undefined when the row went stale. */
|
|
163
|
+
function resolvePromptSelection(value, recent, saved) {
|
|
164
|
+
const selection = parsePromptSelection(value);
|
|
165
|
+
if (!selection) return void 0;
|
|
166
|
+
if (selection.kind === "recent") {
|
|
167
|
+
const index = Number.parseInt(selection.key, 10);
|
|
168
|
+
return Number.isInteger(index) ? recent[index] : void 0;
|
|
169
|
+
}
|
|
170
|
+
return saved.find((prompt) => prompt.name === selection.key)?.text;
|
|
171
|
+
}
|
|
172
|
+
/** Appends to a draft instead of discarding it, since staging is additive. */
|
|
173
|
+
function stagedEditorText(draft, chosen) {
|
|
174
|
+
return draft.trim() ? `${draft.replace(/\s+$/u, "")}\n${chosen}` : chosen;
|
|
175
|
+
}
|
|
176
|
+
//#endregion
|
|
177
|
+
//#region src/services/promptsCommand/index.ts
|
|
178
|
+
function lazyPicker() {
|
|
179
|
+
let picker;
|
|
180
|
+
return () => picker ??= import("@agimon-ai/doompi-ui/matrixPicker");
|
|
181
|
+
}
|
|
182
|
+
/** Opens the picker and resolves the chosen row's value, or undefined. */
|
|
183
|
+
async function pickPrompt(ctx, items, loadPicker) {
|
|
184
|
+
if (ctx.mode !== "tui") {
|
|
185
|
+
const labels = items.map((item) => item.label);
|
|
186
|
+
const chosen = await ctx.ui.select(PICKER_TITLE, labels);
|
|
187
|
+
const index = chosen === void 0 ? -1 : labels.indexOf(chosen);
|
|
188
|
+
return index === -1 ? void 0 : items[index]?.value;
|
|
189
|
+
}
|
|
190
|
+
const { MatrixPickerComponent } = await loadPicker();
|
|
191
|
+
return (await ctx.ui.custom((_tui, theme, keybindings, done) => new MatrixPickerComponent({
|
|
192
|
+
title: PICKER_TITLE,
|
|
193
|
+
items: [...items],
|
|
194
|
+
selected: [],
|
|
195
|
+
multi: false
|
|
196
|
+
}, theme, keybindings, done)))?.[0];
|
|
197
|
+
}
|
|
198
|
+
function createPromptsCommand(deps) {
|
|
199
|
+
const loadPicker = lazyPicker();
|
|
200
|
+
return [require_prompts.COMMAND_NAME, {
|
|
201
|
+
description: require_prompts.COMMAND_DESCRIPTION,
|
|
202
|
+
handler: async (_args, ctx) => {
|
|
203
|
+
if (!ctx.hasUI) return;
|
|
204
|
+
const recent = deps.recent.list();
|
|
205
|
+
let saved;
|
|
206
|
+
try {
|
|
207
|
+
saved = await deps.store.list();
|
|
208
|
+
} catch (error) {
|
|
209
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
210
|
+
ctx.ui.notify(`Could not read saved prompts: ${reason}`, WARNING);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
const items = promptItems(recent, saved);
|
|
214
|
+
if (items.length === 0) {
|
|
215
|
+
ctx.ui.notify("No staged or saved prompts yet. Submit a prompt, or save one with /prompt-save.", INFO);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
const value = await pickPrompt(ctx, items, loadPicker);
|
|
219
|
+
if (!value) return;
|
|
220
|
+
const text = resolvePromptSelection(value, recent, saved);
|
|
221
|
+
if (!text) return;
|
|
222
|
+
ctx.ui.setEditorText(stagedEditorText(ctx.ui.getEditorText(), text));
|
|
223
|
+
}
|
|
224
|
+
}];
|
|
225
|
+
}
|
|
226
|
+
//#endregion
|
|
227
|
+
//#region src/extensions/workspaces/sessions/(backend)/command/prompts.cli.ts
|
|
228
|
+
var prompts_cli_default = (0, _agimon_ai_doompi_core_extensionFile.defineRoutedContribution)((context) => [createPromptsCommand(context.root)], { cardinality: "many" });
|
|
229
|
+
const CONTINUE = { action: "continue" };
|
|
230
|
+
//#endregion
|
|
231
|
+
//#region src/services/inputCapture/index.ts
|
|
232
|
+
/**
|
|
233
|
+
* Staging what the user submits.
|
|
234
|
+
*
|
|
235
|
+
* DESIGN PATTERNS:
|
|
236
|
+
* - Listens on the host's input event, which carries the raw text before skill
|
|
237
|
+
* and template expansion. This keeps the editor component untouched, so
|
|
238
|
+
* arrow up/down behaviour is exactly Pi's and cannot regress here.
|
|
239
|
+
* - Stages interactive and RPC input, which are the two ways a person submits a
|
|
240
|
+
* prompt. Text an extension injected is that extension's business, not
|
|
241
|
+
* something the user asked to reuse.
|
|
242
|
+
*
|
|
243
|
+
* AVOID:
|
|
244
|
+
* - Returning anything but continue. This handler observes, it never rewrites.
|
|
245
|
+
*/
|
|
246
|
+
function createInputCapture(recent) {
|
|
247
|
+
return (event) => {
|
|
248
|
+
if (event.source !== "extension") recent.push(event.text);
|
|
249
|
+
return CONTINUE;
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
//#endregion
|
|
253
|
+
//#region src/extensions/workspaces/sessions/(backend)/hook/input.cli.ts
|
|
254
|
+
var input_cli_default = (0, _agimon_ai_doompi_core_extensionFile.defineCliHook)((context) => createInputCapture(context.root.recent));
|
|
255
|
+
//#endregion
|
|
256
|
+
//#region src/extensions/workspaces/sessions/(backend)/resource/doompi-use-prompt.cli.ts
|
|
257
|
+
var doompi_use_prompt_cli_default = (0, _agimon_ai_doompi_core_extensionFile.defineResource)({
|
|
258
|
+
source: PACKAGE_SOURCE,
|
|
259
|
+
moduleUrl: require("url").pathToFileURL(__filename).href,
|
|
260
|
+
skills: [PROMPT_HELP_SKILL]
|
|
261
|
+
});
|
|
262
|
+
//#endregion
|
|
263
|
+
//#region generated/pi.ts
|
|
264
|
+
const at = (value, context) => typeof value === "function" ? value(context) : value;
|
|
265
|
+
const many = (value, context) => {
|
|
266
|
+
const resolved = typeof value === "function" ? value(context) : value;
|
|
267
|
+
return Array.isArray(resolved) ? resolved : [resolved];
|
|
268
|
+
};
|
|
269
|
+
const extension = (0, _agimon_ai_doompi_core_piExtension.definePiExtension)("@agimon-ai/doompi-prompt", async (context) => {
|
|
270
|
+
const scopeSession = await root_cli_default(context);
|
|
271
|
+
const contextSession = {
|
|
272
|
+
...context,
|
|
273
|
+
root: scopeSession.value
|
|
274
|
+
};
|
|
275
|
+
return {
|
|
276
|
+
...(0, _agimon_ai_doompi_core_extensionFile.composeRootHooks)(scopeSession),
|
|
277
|
+
get commands() {
|
|
278
|
+
return [...many(prompt_save_cli_default, contextSession), ...many(prompts_cli_default, contextSession)];
|
|
279
|
+
},
|
|
280
|
+
events: { input: at(input_cli_default, contextSession) },
|
|
281
|
+
get resources() {
|
|
282
|
+
return [at(doompi_use_prompt_cli_default, contextSession)];
|
|
283
|
+
},
|
|
284
|
+
services: [...scopeSession.services ?? []]
|
|
285
|
+
};
|
|
286
|
+
});
|
|
287
|
+
//#endregion
|
|
288
|
+
exports.default = extension;
|
|
289
|
+
exports.extension = extension;
|
|
290
|
+
|
|
291
|
+
//# sourceMappingURL=pi.cjs.map
|