@agimon-ai/doompi-loop 0.0.1-alpha.73 → 0.0.1-alpha.74
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api-contracts.cjs +7 -1
- package/dist/api-contracts.mjs +2 -1
- package/dist/extensions/pi.cjs +35 -1
- package/dist/extensions/pi.cjs.map +1 -1
- package/dist/extensions/pi.d.cts +3 -3
- package/dist/extensions/pi.d.cts.map +1 -1
- package/dist/extensions/pi.d.mts +3 -3
- package/dist/extensions/pi.d.mts.map +1 -1
- package/dist/extensions/pi.mjs +30 -1
- package/dist/extensions/pi.mjs.map +1 -1
- package/dist/extensions/server.cjs +50 -1
- package/dist/extensions/server.cjs.map +1 -1
- package/dist/extensions/server.d.cts +3 -3
- package/dist/extensions/server.d.cts.map +1 -1
- package/dist/extensions/server.d.mts +3 -3
- package/dist/extensions/server.d.mts.map +1 -1
- package/dist/extensions/server.mjs +45 -1
- package/dist/extensions/server.mjs.map +1 -1
- package/dist/extensions/web.mjs +228 -0
- package/dist/extensions/web.mjs.map +1 -0
- package/dist/index.mjs +1 -1
- package/dist/loopLaunchers.cjs +5 -1
- package/dist/loopLaunchers.mjs +2 -1
- package/dist/src/constants/loop.cjs +11 -1
- package/dist/src/constants/loop.cjs.map +1 -1
- package/dist/src/constants/loop.mjs +8 -1
- package/dist/src/constants/loop.mjs.map +1 -1
- package/dist/src/constants/piLoop.cjs +15 -1
- package/dist/src/constants/piLoop.cjs.map +1 -1
- package/dist/src/constants/piLoop.mjs +10 -1
- package/dist/src/constants/piLoop.mjs.map +1 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/runtime.cli.cjs +26 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/runtime.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/runtime.cli.mjs +26 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/runtime.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/runtime.server.cjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/runtime.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/runtime.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/runtime.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/loop.cli.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/loop.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/loop.cli.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/loop.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/loop.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/loop.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/loop.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/loop.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/loops.cli.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/loops.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/loops.cli.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/loops.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/loops.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/loops.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/loops.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/loops.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/agent-settled.cli.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/agent-settled.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/agent-settled.cli.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/agent-settled.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-start.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-start.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-start.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-start.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-use-loop.cli.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-use-loop.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-use-loop.cli.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-use-loop.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-use-loop.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-use-loop.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-use-loop.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-use-loop.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.cjs +14 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.mjs +15 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.cjs +17 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.mjs +18 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.mjs.map +1 -0
- package/dist/src/schemas/apiContracts.cjs +12 -1
- package/dist/src/schemas/apiContracts.cjs.map +1 -1
- package/dist/src/schemas/apiContracts.mjs +12 -1
- package/dist/src/schemas/apiContracts.mjs.map +1 -1
- package/dist/src/schemas/loopLaunchers.cjs +16 -1
- package/dist/src/schemas/loopLaunchers.cjs.map +1 -1
- package/dist/src/schemas/loopLaunchers.mjs +14 -1
- package/dist/src/schemas/loopLaunchers.mjs.map +1 -1
- package/dist/src/services/defaultLoopLauncher/index.cjs +91 -1
- package/dist/src/services/defaultLoopLauncher/index.cjs.map +1 -1
- package/dist/src/services/defaultLoopLauncher/index.mjs +91 -1
- package/dist/src/services/defaultLoopLauncher/index.mjs.map +1 -1
- package/dist/src/services/loopCommand/index.cjs +15 -0
- package/dist/src/services/loopCommand/index.cjs.map +1 -0
- package/dist/src/services/loopCommand/index.mjs +15 -0
- package/dist/src/services/loopCommand/index.mjs.map +1 -0
- package/dist/src/services/loopLaunchers/index.cjs +179 -1
- package/dist/src/services/loopLaunchers/index.cjs.map +1 -1
- package/dist/src/services/loopLaunchers/index.mjs +179 -1
- package/dist/src/services/loopLaunchers/index.mjs.map +1 -1
- package/dist/src/services/serverRuntime/index.cjs +293 -0
- package/dist/src/services/serverRuntime/index.cjs.map +1 -0
- package/dist/src/services/serverRuntime/index.mjs +293 -0
- package/dist/src/services/serverRuntime/index.mjs.map +1 -0
- package/dist/src/tui/leader.cjs +35 -1
- package/dist/src/tui/leader.cjs.map +1 -1
- package/dist/src/tui/leader.mjs +35 -1
- package/dist/src/tui/leader.mjs.map +1 -1
- package/dist/src/tui/loopListOverlay.cjs +100 -1
- package/dist/src/tui/loopListOverlay.cjs.map +1 -1
- package/dist/src/tui/loopListOverlay.mjs +99 -1
- package/dist/src/tui/loopListOverlay.mjs.map +1 -1
- package/dist/src/tui/loopRuntime.cjs +255 -1
- package/dist/src/tui/loopRuntime.cjs.map +1 -1
- package/dist/src/tui/loopRuntime.mjs +255 -1
- package/dist/src/tui/loopRuntime.mjs.map +1 -1
- package/dist/src/tui/startLoopOverlay.cjs +70 -1
- package/dist/src/tui/startLoopOverlay.cjs.map +1 -1
- package/dist/src/tui/startLoopOverlay.mjs +69 -1
- package/dist/src/tui/startLoopOverlay.mjs.map +1 -1
- package/dist/src/types/loopView.cjs +18 -1
- package/dist/src/types/loopView.cjs.map +1 -1
- package/dist/src/types/loopView.mjs +17 -1
- package/dist/src/types/loopView.mjs.map +1 -1
- package/package.json +15 -14
- package/dist/_virtual/_rolldown/runtime.cjs +0 -1
- package/dist/src/controllers/loopCommand.cjs +0 -2
- package/dist/src/controllers/loopCommand.cjs.map +0 -1
- package/dist/src/controllers/loopCommand.mjs +0 -2
- package/dist/src/controllers/loopCommand.mjs.map +0 -1
- package/dist/src/controllers/serverRuntime.cjs +0 -2
- package/dist/src/controllers/serverRuntime.cjs.map +0 -1
- package/dist/src/controllers/serverRuntime.mjs +0 -2
- package/dist/src/controllers/serverRuntime.mjs.map +0 -1
- package/dist/src/services/loopResource/index.cjs +0 -2
- package/dist/src/services/loopResource/index.cjs.map +0 -1
- package/dist/src/services/loopResource/index.mjs +0 -2
- package/dist/src/services/loopResource/index.mjs.map +0 -1
- package/src/extensions/web.ts +0 -41
- package/src/web/components/LoopsActivitySection.tsx +0 -94
- package/src/web/tsconfig.json +0 -23
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loopView.mjs","names":[],"sources":["../../../src/types/loopView.ts"],"sourcesContent":["/** The browser-only status that carries active Loop instances into the activity dock. */\nexport const LOOP_VIEW_STATUS_KEY = 'doom-loop-instances';\n\nexport type LoopStatusState = 'starting' | 'running' | 'stopping';\n\n/** The small, serializable Loop view the cockpit needs for one activity row. */\nexport interface LoopStatusItem {\n readonly instanceId: string;\n readonly label: string;\n readonly detail: string;\n readonly state: LoopStatusState;\n}\n\ninterface LoopStatusSource {\n readonly instanceId: string;\n readonly launcherLabel: string;\n readonly label?: string;\n readonly detail?: string;\n readonly state: LoopStatusState;\n}\n\nconst ANSI = new RegExp(String.raw`\\u001b\\[[0-9;]*m`, 'gu');\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isState(value: unknown): value is LoopStatusState {\n return value === 'starting' || value === 'running' || value === 'stopping';\n}\n\n/** Projects runtime snapshots into the JSON status consumed by the web plugin. */\nexport function formatLoopStatusView(instances: readonly LoopStatusSource[]): string | undefined {\n if (instances.length === 0) return undefined;\n return JSON.stringify(\n instances.map((instance) => ({\n instanceId: instance.instanceId,\n label: instance.label ?? instance.launcherLabel,\n detail: instance.detail ?? instance.instanceId,\n state: instance.state,\n })),\n );\n}\n\n/** Reads a Loop status without letting malformed session data crash the activity dock. */\nexport function parseLoopStatusView(raw: string | undefined): LoopStatusItem[] | undefined {\n if (raw === undefined) return undefined;\n const text = raw.replace(ANSI, '').trim();\n if (text === '') return undefined;\n\n try {\n const value: unknown = JSON.parse(text);\n if (!Array.isArray(value) || value.length === 0) return undefined;\n const items: LoopStatusItem[] = [];\n for (const item of value) {\n if (\n !isRecord(item) ||\n typeof item.instanceId !== 'string' ||\n item.instanceId.trim() === '' ||\n typeof item.label !== 'string' ||\n item.label.trim() === '' ||\n typeof item.detail !== 'string' ||\n !isState(item.state)\n ) {\n return undefined;\n }\n items.push({ instanceId: item.instanceId, label: item.label, detail: item.detail, state: item.state });\n }\n return items;\n } catch {\n return undefined;\n }\n}\n"],"mappings":"AACA,MAAa,
|
|
1
|
+
{"version":3,"file":"loopView.mjs","names":[],"sources":["../../../src/types/loopView.ts"],"sourcesContent":["/** The browser-only status that carries active Loop instances into the activity dock. */\nexport const LOOP_VIEW_STATUS_KEY = 'doom-loop-instances';\n\nexport type LoopStatusState = 'starting' | 'running' | 'stopping';\n\n/** The small, serializable Loop view the cockpit needs for one activity row. */\nexport interface LoopStatusItem {\n readonly instanceId: string;\n readonly label: string;\n readonly detail: string;\n readonly state: LoopStatusState;\n}\n\ninterface LoopStatusSource {\n readonly instanceId: string;\n readonly launcherLabel: string;\n readonly label?: string;\n readonly detail?: string;\n readonly state: LoopStatusState;\n}\n\nconst ANSI = new RegExp(String.raw`\\u001b\\[[0-9;]*m`, 'gu');\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isState(value: unknown): value is LoopStatusState {\n return value === 'starting' || value === 'running' || value === 'stopping';\n}\n\n/** Projects runtime snapshots into the JSON status consumed by the web plugin. */\nexport function formatLoopStatusView(instances: readonly LoopStatusSource[]): string | undefined {\n if (instances.length === 0) return undefined;\n return JSON.stringify(\n instances.map((instance) => ({\n instanceId: instance.instanceId,\n label: instance.label ?? instance.launcherLabel,\n detail: instance.detail ?? instance.instanceId,\n state: instance.state,\n })),\n );\n}\n\n/** Reads a Loop status without letting malformed session data crash the activity dock. */\nexport function parseLoopStatusView(raw: string | undefined): LoopStatusItem[] | undefined {\n if (raw === undefined) return undefined;\n const text = raw.replace(ANSI, '').trim();\n if (text === '') return undefined;\n\n try {\n const value: unknown = JSON.parse(text);\n if (!Array.isArray(value) || value.length === 0) return undefined;\n const items: LoopStatusItem[] = [];\n for (const item of value) {\n if (\n !isRecord(item) ||\n typeof item.instanceId !== 'string' ||\n item.instanceId.trim() === '' ||\n typeof item.label !== 'string' ||\n item.label.trim() === '' ||\n typeof item.detail !== 'string' ||\n !isState(item.state)\n ) {\n return undefined;\n }\n items.push({ instanceId: item.instanceId, label: item.label, detail: item.detail, state: item.state });\n }\n return items;\n } catch {\n return undefined;\n }\n}\n"],"mappings":";;AACA,MAAa,uBAAuB;AAoBvB,IAAI,OAAO,OAAO,GAAG,oBAAoB,IAAI;;AAW1D,SAAgB,qBAAqB,WAA4D;CAC/F,IAAI,UAAU,WAAW,GAAG,OAAO,KAAA;CACnC,OAAO,KAAK,UACV,UAAU,KAAK,cAAc;EAC3B,YAAY,SAAS;EACrB,OAAO,SAAS,SAAS,SAAS;EAClC,QAAQ,SAAS,UAAU,SAAS;EACpC,OAAO,SAAS;CAClB,EAAE,CACJ;AACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agimon-ai/doompi-loop",
|
|
3
|
-
"version": "0.0.1-alpha.
|
|
3
|
+
"version": "0.0.1-alpha.74",
|
|
4
4
|
"description": "Session-scoped recurring prompt scheduler and loop controls for Pi coding agents.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -27,15 +27,12 @@
|
|
|
27
27
|
},
|
|
28
28
|
"files": [
|
|
29
29
|
"dist",
|
|
30
|
-
"src/web",
|
|
31
|
-
"src/extensions/web.ts",
|
|
32
30
|
"llms.txt",
|
|
33
31
|
"src/prompts",
|
|
34
32
|
"src/types/loopView.ts",
|
|
35
33
|
"README.md",
|
|
36
34
|
"LICENSE",
|
|
37
|
-
"package.json"
|
|
38
|
-
"!src/web/**/*.stories.tsx"
|
|
35
|
+
"package.json"
|
|
39
36
|
],
|
|
40
37
|
"type": "module",
|
|
41
38
|
"main": "./dist/index.cjs",
|
|
@@ -57,24 +54,28 @@
|
|
|
57
54
|
"import": "./dist/extensions/server.mjs",
|
|
58
55
|
"require": "./dist/extensions/server.cjs"
|
|
59
56
|
},
|
|
60
|
-
"./
|
|
57
|
+
"./extensions/web": {
|
|
58
|
+
"import": "./dist/extensions/web.mjs"
|
|
59
|
+
},
|
|
61
60
|
"./loop-launchers": {
|
|
62
61
|
"types": "./dist/loopLaunchers.d.mts",
|
|
63
62
|
"import": "./dist/loopLaunchers.mjs",
|
|
64
63
|
"require": "./dist/loopLaunchers.cjs"
|
|
65
|
-
}
|
|
64
|
+
},
|
|
65
|
+
"./package.json": "./package.json"
|
|
66
66
|
},
|
|
67
67
|
"publishConfig": {
|
|
68
68
|
"access": "public"
|
|
69
69
|
},
|
|
70
70
|
"dependencies": {
|
|
71
|
-
"@agimon-ai/doompi-core": "0.0.1-alpha.
|
|
72
|
-
"@agimon-ai/doompi-minor-mode": "0.0.1-alpha.
|
|
73
|
-
"@agimon-ai/doompi-ui": "0.0.1-alpha.
|
|
74
|
-
"@agimon-ai/doompi-web-components": "0.0.1-alpha.
|
|
71
|
+
"@agimon-ai/doompi-core": "0.0.1-alpha.73",
|
|
72
|
+
"@agimon-ai/doompi-minor-mode": "0.0.1-alpha.73",
|
|
73
|
+
"@agimon-ai/doompi-ui": "0.0.1-alpha.73",
|
|
74
|
+
"@agimon-ai/doompi-web-components": "0.0.1-alpha.31",
|
|
75
75
|
"@deepseek-ai/cordis": "4.0.2"
|
|
76
76
|
},
|
|
77
77
|
"devDependencies": {
|
|
78
|
+
"@agimon-ai/doompi-build": "0.0.1-alpha.2",
|
|
78
79
|
"@earendil-works/pi-coding-agent": "0.85.1",
|
|
79
80
|
"@earendil-works/pi-tui": "0.85.1",
|
|
80
81
|
"@types/node": "26.5.1",
|
|
@@ -103,7 +104,7 @@
|
|
|
103
104
|
"node": ">=22.19.0"
|
|
104
105
|
},
|
|
105
106
|
"doompiServer": {
|
|
106
|
-
"entry": "./
|
|
107
|
+
"entry": "./generated/server.ts",
|
|
107
108
|
"dist": "./dist/extensions/server.mjs",
|
|
108
109
|
"scopes": [
|
|
109
110
|
"session"
|
|
@@ -116,7 +117,7 @@
|
|
|
116
117
|
"doompiWeb": {
|
|
117
118
|
"pluginId": "loop",
|
|
118
119
|
"channels": [],
|
|
119
|
-
"client": "./
|
|
120
|
+
"client": "./dist/extensions/web.mjs",
|
|
120
121
|
"scopes": [
|
|
121
122
|
"session"
|
|
122
123
|
]
|
|
@@ -129,7 +130,7 @@
|
|
|
129
130
|
"scripts": {
|
|
130
131
|
"build": "tsdown",
|
|
131
132
|
"test": "vitest --run",
|
|
132
|
-
"typecheck": "tsc --noEmit && tsc --noEmit -p
|
|
133
|
+
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.web.json",
|
|
133
134
|
"lint": "oxlint . && oxfmt . --check",
|
|
134
135
|
"fixcode": "oxlint . --fix && oxfmt ."
|
|
135
136
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,s)=>(s=n==null?{}:e(i(n)),o(r||!n||!n.__esModule||!a.call(n,`default`)?t(s,`default`,{value:n,enumerable:!0}):s,n));exports.__toESM=s;
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const e=require("../constants/loop.cjs");function t(t){return[[e.START_COMMAND_NAME,{description:e.START_COMMAND_DESCRIPTION,handler:async(e,n)=>t.start(n,e)}],[e.LIST_COMMAND_NAME,{description:e.LIST_COMMAND_DESCRIPTION,handler:async(e,n)=>t.list(n)}]]}exports.createLoopCommands=t;
|
|
2
|
-
//# sourceMappingURL=loopCommand.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"loopCommand.cjs","names":["START_COMMAND_NAME","START_COMMAND_DESCRIPTION","LIST_COMMAND_NAME","LIST_COMMAND_DESCRIPTION"],"sources":["../../../src/controllers/loopCommand.ts"],"sourcesContent":["import type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\n\nimport { START_COMMAND_DESCRIPTION, LIST_COMMAND_DESCRIPTION } from '../constants/loop';\nimport { LIST_COMMAND_NAME, START_COMMAND_NAME } from '../constants/loop';\nimport type { LoopCommandHandlers } from '../types/loopCommand';\nexport function createLoopCommands(\n handlers: LoopCommandHandlers,\n): readonly (readonly [string, Parameters<ExtensionAPI['registerCommand']>[1]])[] {\n return [\n [\n START_COMMAND_NAME,\n {\n description: START_COMMAND_DESCRIPTION,\n handler: async (args, ctx) => handlers.start(ctx, args),\n },\n ],\n [\n LIST_COMMAND_NAME,\n {\n description: LIST_COMMAND_DESCRIPTION,\n handler: async (_args, ctx) => handlers.list(ctx),\n },\n ],\n ];\n}\n"],"mappings":"yCAKA,SAAgB,EACd,EACgF,CAChF,MAAO,CACL,CACEA,EAAAA,mBACA,CACE,YAAaC,EAAAA,0BACb,QAAS,MAAO,EAAM,IAAQ,EAAS,MAAM,EAAK,CAAI,CACxD,CACF,EACA,CACEC,EAAAA,kBACA,CACE,YAAaC,EAAAA,yBACb,QAAS,MAAO,EAAO,IAAQ,EAAS,KAAK,CAAG,CAClD,CACF,CACF,CACF"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{LIST_COMMAND_DESCRIPTION as e,LIST_COMMAND_NAME as t,START_COMMAND_DESCRIPTION as n,START_COMMAND_NAME as r}from"../constants/loop.mjs";function i(i){return[[r,{description:n,handler:async(e,t)=>i.start(t,e)}],[t,{description:e,handler:async(e,t)=>i.list(t)}]]}export{i as createLoopCommands};
|
|
2
|
-
//# sourceMappingURL=loopCommand.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"loopCommand.mjs","names":[],"sources":["../../../src/controllers/loopCommand.ts"],"sourcesContent":["import type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\n\nimport { START_COMMAND_DESCRIPTION, LIST_COMMAND_DESCRIPTION } from '../constants/loop';\nimport { LIST_COMMAND_NAME, START_COMMAND_NAME } from '../constants/loop';\nimport type { LoopCommandHandlers } from '../types/loopCommand';\nexport function createLoopCommands(\n handlers: LoopCommandHandlers,\n): readonly (readonly [string, Parameters<ExtensionAPI['registerCommand']>[1]])[] {\n return [\n [\n START_COMMAND_NAME,\n {\n description: START_COMMAND_DESCRIPTION,\n handler: async (args, ctx) => handlers.start(ctx, args),\n },\n ],\n [\n LIST_COMMAND_NAME,\n {\n description: LIST_COMMAND_DESCRIPTION,\n handler: async (_args, ctx) => handlers.list(ctx),\n },\n ],\n ];\n}\n"],"mappings":"+IAKA,SAAgB,EACd,EACgF,CAChF,MAAO,CACL,CACE,EACA,CACE,YAAa,EACb,QAAS,MAAO,EAAM,IAAQ,EAAS,MAAM,EAAK,CAAI,CACxD,CACF,EACA,CACE,EACA,CACE,YAAa,EACb,QAAS,MAAO,EAAO,IAAQ,EAAS,KAAK,CAAG,CAClD,CACF,CACF,CACF"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const e=require("../constants/loop.cjs"),t=require("../services/loopLaunchers/index.cjs"),n=require("../services/loopResource/index.cjs");let r=require("@agimon-ai/doompi-minor-mode");const i=`@agimon-ai/doompi-loop`,a=`loop.active`,o=3600;function s(e,t,n=`info`){return Promise.resolve(e.client.notify({body:t,level:n}))}function c(e,t){if(typeof e!=`string`||e.trim()===``)return t;let n=Number(e);if(!Number.isInteger(n)||n<30||n>o)throw Error(`Interval must be between 30 and ${o} seconds.`);return n}function l(o){let l,u,d,f,p=()=>(o.context.selection.state?.[`minor-mode`]??[]).includes(a),m=()=>{let e=l?.listLaunchers().length??0,t=(l?.listInstances().length??0)>0,n=e>0||!p();return{activation:t?`active`:`inactive`,condition:l?.listInstances().some(({state:e})=>e!==`running`)?`queued`:`ready`,...t?{detail:`${l?.listInstances().length} active`,color:`warning`}:{},actions:[{id:`start`,enabled:n,...n?{}:{disabledReason:`No loop launchers are registered.`}},{id:`stop`,enabled:t,...t?{}:{disabledReason:`No loops are active.`}}]}},h=()=>f?.publish();return f=(0,r.defineMinorMode)({descriptor:{source:i,id:a,label:`Loop`,description:`Session-scoped recurring prompt loops.`,order:60,actions:[{id:`start`,label:`Start`,description:`Start a loop with a registered launcher.`,contexts:[`headless`],parameters:[{name:`launcherId`,label:`Launcher`,kind:`string`,required:!0,minLength:1},{name:`instanceId`,label:`Instance ID`,kind:`string`,required:!1,minLength:1}]},{id:`stop`,label:`Stop`,description:`Stop one active loop instance.`,contexts:[`headless`],parameters:[{name:`instanceId`,label:`Instance ID`,kind:`string`,required:!0,minLength:1},{name:`reason`,label:`Reason`,kind:`string`,required:!1,minLength:1}]}]},state:m,async handleAction(e,t,n,{signal:r}){if(r.throwIfAborted(),t===`start`&&!l){let e=(o.context.selection.state?.[`minor-mode`]??[]).filter(e=>e!==a);await o.changeSelection({axis:`state`,key:`minor-mode`,values:[...e,a]})}if(!l)throw Error(`Loop activity is not active.`);if(t===`start`){let e=await l.launch(String(n.launcherId??``),n.instanceId?{instanceId:String(n.instanceId)}:{});return h(),{message:e?`Loop '${e.instanceId}' started.`:`Loop launch was cancelled.`}}if(t===`stop`){let e=await l.stop(String(n.instanceId??``),String(n.reason??`Stopped through minor_mode.`));if(e&&l.listInstances().length===0){let e=(o.context.selection.state?.[`minor-mode`]??[]).filter(e=>e!==a);await o.changeSelection({axis:`state`,key:`minor-mode`,values:e})}return h(),{message:e?`Loop stopped.`:`Loop instance was not active.`}}throw Error(`Unknown loop mode action: ${t}`)}}).createOwner(void 0),{services:[(0,r.serverMinorModes)([f])],resources:[{when:{state:{"minor-mode":a},attribution:{kind:`minor`,mode:a}},name:`doompi-use-loop`,kind:`skill`,read:()=>n.readLoopResource()}],activities:[{when:{state:{"minor-mode":a},attribution:{kind:`minor`,mode:a}},name:`doompi-loop`,start:async e=>{if(l!==void 0)return async()=>void 0;let n={generation:`${e.sessionId}:loop-launchers`,createInstanceId:()=>crypto.randomUUID(),timestamp:()=>new Date().toISOString()},r=t.createDoomLoopLaunchersService(n),a=r.register({id:`doompi.default`,source:i,label:`Default loop`,description:`Run a prompt in this session on an interval.`,async launch({instanceId:t,signal:n}){let r=await e.client.request({kind:`input`,title:`Loop prompt`,multiline:!0},n),i=typeof r==`string`?r.trim():``;if(!i||n.aborted)return;let a=c(await e.client.request({kind:`input`,title:`Loop interval in seconds`,initialValue:`300`},n),300),o=!1,l=()=>{o||n.aborted||e.session.prompt(i).catch(t=>{s(e,`Loop pass failed: ${t instanceof Error?t.message:String(t)}`,`warning`)})},u=setInterval(l,a*1e3);return u.unref?.(),l(),{instanceId:t,label:`Default loop`,detail:`every ${a}s`,stop(){o=!0,clearInterval(u)}}}});return l=r,u=a,d=r.subscribe(h),h(),async()=>{d?.(),d=void 0,await a.dispose(`Headless loop activity stopped.`),await r.dispose(`Headless loop activity stopped.`),l===r&&(l=void 0),u===a&&(u=void 0),h()}}}],commands:[{name:e.START_COMMAND_NAME,description:`Start a registered loop.`,async execute(e,t){if(!l){let e=o.context.selection.state?.[`minor-mode`]??[];await o.changeSelection({axis:`state`,key:`minor-mode`,values:[...e,a]})}if(!l)throw Error(`Loop activity is not active.`);let n=l.listLaunchers(),r=e.trim()||await t.client.request({kind:`select`,title:`Choose a loop launcher`,options:n.map(e=>({label:e.label,value:e.id}))}),i=e.trim()||(typeof r==`string`?r:``);if(!i)return;let c=await l.launch(i);h(),await s(t,c?`Loop '${c.instanceId}' started.`:`Loop launch was cancelled.`)}},{name:e.LIST_COMMAND_NAME,description:`List and stop active loops.`,async execute(e,t){let n=l?.listInstances()??[];await s(t,n.length===0?`No loops are active.`:JSON.stringify(n,null,2))}}],hooks:[{when:{state:{"minor-mode":a},attribution:{kind:`minor`,mode:a}},event:`session_shutdown`,async handle(){await l?.stopAll(`Headless session shutdown.`)}}],async onDispose(){await u?.dispose(`Headless loop facet disposed.`),await l?.dispose(`Headless loop facet disposed.`)}}}exports.createSessionState=l;
|
|
2
|
-
//# sourceMappingURL=serverRuntime.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"serverRuntime.cjs","names":["createDoomLoopLaunchersService","defineMinorMode","serverMinorModes","readLoopResource","START_COMMAND_NAME","LIST_COMMAND_NAME"],"sources":["../../../src/controllers/serverRuntime.ts"],"sourcesContent":["import { serverMinorModes } from '@agimon-ai/doompi-minor-mode';\nimport { defineMinorMode, type MinorModeOwner, type MinorModeState } from '@agimon-ai/doompi-minor-mode';\n\nimport { LIST_COMMAND_NAME, START_COMMAND_NAME } from '../constants/loop';\nimport type { DoomLoopLaunchersService, LoopLauncherRegistration, StoppableLoop } from '../schemas/loopLaunchers';\nimport { createDoomLoopLaunchersService, type LoopLaunchersDependencies } from '../services/loopLaunchers';\nimport { readLoopResource } from '../services/loopResource';\n\nconst SOURCE = '@agimon-ai/doompi-loop';\nconst MODE_ID = 'loop.active';\nconst DEFAULT_LAUNCHER_ID = 'doompi.default';\nconst DEFAULT_INTERVAL_SECONDS = 300;\nconst MIN_INTERVAL_SECONDS = 30;\nconst MAX_INTERVAL_SECONDS = 3600;\n\nfunction notify(\n context: {\n client: { notify(request: { body: string; level?: 'info' | 'warning' | 'error' }): void | Promise<void> };\n },\n body: string,\n level: 'info' | 'warning' | 'error' = 'info',\n): Promise<void> {\n return Promise.resolve(context.client.notify({ body, level }));\n}\n\nfunction numberInput(value: unknown, fallback: number): number {\n if (typeof value !== 'string' || value.trim() === '') return fallback;\n const parsed = Number(value);\n if (!Number.isInteger(parsed) || parsed < MIN_INTERVAL_SECONDS || parsed > MAX_INTERVAL_SECONDS) {\n throw new Error(`Interval must be between ${MIN_INTERVAL_SECONDS} and ${MAX_INTERVAL_SECONDS} seconds.`);\n }\n return parsed;\n}\n\nimport { type DoomHeadlessExecutionContext, type DoomHeadlessHostService } from '@agimon-ai/doompi-core/headless';\nimport type { DoomServerSessionPlugin } from '@agimon-ai/doompi-core/server-facet';\nexport function createSessionState(host: DoomHeadlessHostService): DoomServerSessionPlugin {\n let launchers: DoomLoopLaunchersService | undefined;\n let defaultRegistration: LoopLauncherRegistration | undefined;\n let unsubscribe: (() => void) | undefined;\n let modeOwner: MinorModeOwner | undefined;\n const modeSelected = (): boolean => (host.context.selection.state?.['minor-mode'] ?? []).includes(MODE_ID);\n const modeState = (): MinorModeState => {\n const launcherCount = launchers?.listLaunchers().length ?? 0;\n const active = (launchers?.listInstances().length ?? 0) > 0;\n const canStart = launcherCount > 0 || !modeSelected();\n return {\n activation: active ? 'active' : 'inactive',\n condition: launchers?.listInstances().some(({ state }) => state !== 'running') ? 'queued' : 'ready',\n ...(active ? { detail: `${launchers?.listInstances().length} active`, color: 'warning' } : {}),\n actions: [\n {\n id: 'start',\n enabled: canStart,\n ...(canStart ? {} : { disabledReason: 'No loop launchers are registered.' }),\n },\n {\n id: 'stop',\n enabled: active,\n ...(active ? {} : { disabledReason: 'No loops are active.' }),\n },\n ],\n };\n };\n const publishMode = (): void => modeOwner?.publish();\n const startActivity = async (execution: typeof host.context): Promise<() => Promise<void>> => {\n if (launchers !== undefined) return async () => undefined;\n const dependencies: LoopLaunchersDependencies = {\n generation: `${execution.sessionId}:loop-launchers`,\n createInstanceId: () => crypto.randomUUID(),\n timestamp: () => new Date().toISOString(),\n };\n const service = createDoomLoopLaunchersService(dependencies);\n const registration = service.register({\n id: DEFAULT_LAUNCHER_ID,\n source: SOURCE,\n label: 'Default loop',\n description: 'Run a prompt in this session on an interval.',\n async launch({ instanceId, signal }): Promise<StoppableLoop | undefined> {\n const promptValue = await execution.client.request(\n { kind: 'input', title: 'Loop prompt', multiline: true },\n signal,\n );\n const prompt = typeof promptValue === 'string' ? promptValue.trim() : '';\n if (!prompt || signal.aborted) return undefined;\n const interval = numberInput(\n await execution.client.request(\n { kind: 'input', title: 'Loop interval in seconds', initialValue: String(DEFAULT_INTERVAL_SECONDS) },\n signal,\n ),\n DEFAULT_INTERVAL_SECONDS,\n );\n let stopped = false;\n const tick = (): void => {\n if (stopped || signal.aborted) return;\n void execution.session.prompt(prompt).catch((error) => {\n void notify(\n execution,\n `Loop pass failed: ${error instanceof Error ? error.message : String(error)}`,\n 'warning',\n );\n });\n };\n const timer = setInterval(tick, interval * 1000);\n timer.unref?.();\n tick();\n return {\n instanceId,\n label: 'Default loop',\n detail: `every ${interval}s`,\n stop() {\n stopped = true;\n clearInterval(timer);\n },\n };\n },\n });\n launchers = service;\n defaultRegistration = registration;\n unsubscribe = service.subscribe(publishMode);\n publishMode();\n return async () => {\n unsubscribe?.();\n unsubscribe = undefined;\n await registration.dispose('Headless loop activity stopped.');\n await service.dispose('Headless loop activity stopped.');\n if (launchers === service) launchers = undefined;\n if (defaultRegistration === registration) defaultRegistration = undefined;\n publishMode();\n };\n };\n modeOwner = defineMinorMode({\n descriptor: {\n source: SOURCE,\n id: MODE_ID,\n label: 'Loop',\n description: 'Session-scoped recurring prompt loops.',\n order: 60,\n actions: [\n {\n id: 'start',\n label: 'Start',\n description: 'Start a loop with a registered launcher.',\n contexts: ['headless'],\n parameters: [\n { name: 'launcherId', label: 'Launcher', kind: 'string', required: true, minLength: 1 },\n { name: 'instanceId', label: 'Instance ID', kind: 'string', required: false, minLength: 1 },\n ],\n },\n {\n id: 'stop',\n label: 'Stop',\n description: 'Stop one active loop instance.',\n contexts: ['headless'],\n parameters: [\n { name: 'instanceId', label: 'Instance ID', kind: 'string', required: true, minLength: 1 },\n { name: 'reason', label: 'Reason', kind: 'string', required: false, minLength: 1 },\n ],\n },\n ],\n },\n state: modeState,\n async handleAction(_runtime, actionId, argumentsValue, { signal }) {\n signal.throwIfAborted();\n if (actionId === 'start' && !launchers) {\n const modes = (host.context.selection.state?.['minor-mode'] ?? []).filter((mode) => mode !== MODE_ID);\n await host.changeSelection({ axis: 'state', key: 'minor-mode', values: [...modes, MODE_ID] });\n }\n if (!launchers) throw new Error('Loop activity is not active.');\n if (actionId === 'start') {\n const instance = await launchers.launch(\n String(argumentsValue.launcherId ?? ''),\n argumentsValue.instanceId ? { instanceId: String(argumentsValue.instanceId) } : {},\n );\n publishMode();\n return { message: instance ? `Loop '${instance.instanceId}' started.` : 'Loop launch was cancelled.' };\n }\n if (actionId === 'stop') {\n const stopped = await launchers.stop(\n String(argumentsValue.instanceId ?? ''),\n String(argumentsValue.reason ?? 'Stopped through minor_mode.'),\n );\n if (stopped && launchers.listInstances().length === 0) {\n const modes = (host.context.selection.state?.['minor-mode'] ?? []).filter((mode) => mode !== MODE_ID);\n await host.changeSelection({ axis: 'state', key: 'minor-mode', values: modes });\n }\n publishMode();\n return { message: stopped ? 'Loop stopped.' : 'Loop instance was not active.' };\n }\n throw new Error(`Unknown loop mode action: ${actionId}`);\n },\n }).createOwner(undefined);\n return {\n services: [serverMinorModes([modeOwner])],\n resources: [\n {\n when: { state: { 'minor-mode': MODE_ID }, attribution: { kind: 'minor', mode: MODE_ID } },\n name: 'doompi-use-loop',\n kind: 'skill',\n read: () => readLoopResource(),\n },\n ],\n activities: [\n {\n when: { state: { 'minor-mode': MODE_ID }, attribution: { kind: 'minor', mode: MODE_ID } },\n name: 'doompi-loop',\n start: startActivity,\n },\n ],\n commands: [\n {\n name: START_COMMAND_NAME,\n description: 'Start a registered loop.',\n async execute(args: string, execution: DoomHeadlessExecutionContext) {\n if (!launchers) {\n const modes = host.context.selection.state?.['minor-mode'] ?? [];\n await host.changeSelection({ axis: 'state', key: 'minor-mode', values: [...modes, MODE_ID] });\n }\n if (!launchers) throw new Error('Loop activity is not active.');\n const available = launchers.listLaunchers();\n const selected =\n args.trim() ||\n (await execution.client.request({\n kind: 'select',\n title: 'Choose a loop launcher',\n options: available.map((entry) => ({ label: entry.label, value: entry.id })),\n }));\n const launcherId = args.trim() || (typeof selected === 'string' ? selected : '');\n if (!launcherId) return;\n const instance = await launchers.launch(launcherId);\n publishMode();\n await notify(execution, instance ? `Loop '${instance.instanceId}' started.` : 'Loop launch was cancelled.');\n },\n },\n {\n name: LIST_COMMAND_NAME,\n description: 'List and stop active loops.',\n async execute(_args: string, execution: DoomHeadlessExecutionContext) {\n const instances = launchers?.listInstances() ?? [];\n await notify(execution, instances.length === 0 ? 'No loops are active.' : JSON.stringify(instances, null, 2));\n },\n },\n ],\n hooks: [\n {\n when: { state: { 'minor-mode': MODE_ID }, attribution: { kind: 'minor', mode: MODE_ID } },\n event: 'session_shutdown',\n async handle() {\n await launchers?.stopAll('Headless session shutdown.');\n },\n },\n ],\n async onDispose() {\n await defaultRegistration?.dispose('Headless loop facet disposed.');\n await launchers?.dispose('Headless loop facet disposed.');\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{LIST_COMMAND_NAME as e,START_COMMAND_NAME as t}from"../constants/loop.mjs";import{createDoomLoopLaunchersService as n}from"../services/loopLaunchers/index.mjs";import{readLoopResource as r}from"../services/loopResource/index.mjs";import{defineMinorMode as i,serverMinorModes as a}from"@agimon-ai/doompi-minor-mode";const o=`@agimon-ai/doompi-loop`,s=`loop.active`,c=3600;function l(e,t,n=`info`){return Promise.resolve(e.client.notify({body:t,level:n}))}function u(e,t){if(typeof e!=`string`||e.trim()===``)return t;let n=Number(e);if(!Number.isInteger(n)||n<30||n>c)throw Error(`Interval must be between 30 and ${c} seconds.`);return n}function d(c){let d,f,p,m,h=()=>(c.context.selection.state?.[`minor-mode`]??[]).includes(s),g=()=>{let e=d?.listLaunchers().length??0,t=(d?.listInstances().length??0)>0,n=e>0||!h();return{activation:t?`active`:`inactive`,condition:d?.listInstances().some(({state:e})=>e!==`running`)?`queued`:`ready`,...t?{detail:`${d?.listInstances().length} active`,color:`warning`}:{},actions:[{id:`start`,enabled:n,...n?{}:{disabledReason:`No loop launchers are registered.`}},{id:`stop`,enabled:t,...t?{}:{disabledReason:`No loops are active.`}}]}},_=()=>m?.publish();return m=i({descriptor:{source:o,id:s,label:`Loop`,description:`Session-scoped recurring prompt loops.`,order:60,actions:[{id:`start`,label:`Start`,description:`Start a loop with a registered launcher.`,contexts:[`headless`],parameters:[{name:`launcherId`,label:`Launcher`,kind:`string`,required:!0,minLength:1},{name:`instanceId`,label:`Instance ID`,kind:`string`,required:!1,minLength:1}]},{id:`stop`,label:`Stop`,description:`Stop one active loop instance.`,contexts:[`headless`],parameters:[{name:`instanceId`,label:`Instance ID`,kind:`string`,required:!0,minLength:1},{name:`reason`,label:`Reason`,kind:`string`,required:!1,minLength:1}]}]},state:g,async handleAction(e,t,n,{signal:r}){if(r.throwIfAborted(),t===`start`&&!d){let e=(c.context.selection.state?.[`minor-mode`]??[]).filter(e=>e!==s);await c.changeSelection({axis:`state`,key:`minor-mode`,values:[...e,s]})}if(!d)throw Error(`Loop activity is not active.`);if(t===`start`){let e=await d.launch(String(n.launcherId??``),n.instanceId?{instanceId:String(n.instanceId)}:{});return _(),{message:e?`Loop '${e.instanceId}' started.`:`Loop launch was cancelled.`}}if(t===`stop`){let e=await d.stop(String(n.instanceId??``),String(n.reason??`Stopped through minor_mode.`));if(e&&d.listInstances().length===0){let e=(c.context.selection.state?.[`minor-mode`]??[]).filter(e=>e!==s);await c.changeSelection({axis:`state`,key:`minor-mode`,values:e})}return _(),{message:e?`Loop stopped.`:`Loop instance was not active.`}}throw Error(`Unknown loop mode action: ${t}`)}}).createOwner(void 0),{services:[a([m])],resources:[{when:{state:{"minor-mode":s},attribution:{kind:`minor`,mode:s}},name:`doompi-use-loop`,kind:`skill`,read:()=>r()}],activities:[{when:{state:{"minor-mode":s},attribution:{kind:`minor`,mode:s}},name:`doompi-loop`,start:async e=>{if(d!==void 0)return async()=>void 0;let t={generation:`${e.sessionId}:loop-launchers`,createInstanceId:()=>crypto.randomUUID(),timestamp:()=>new Date().toISOString()},r=n(t),i=r.register({id:`doompi.default`,source:o,label:`Default loop`,description:`Run a prompt in this session on an interval.`,async launch({instanceId:t,signal:n}){let r=await e.client.request({kind:`input`,title:`Loop prompt`,multiline:!0},n),i=typeof r==`string`?r.trim():``;if(!i||n.aborted)return;let a=u(await e.client.request({kind:`input`,title:`Loop interval in seconds`,initialValue:`300`},n),300),o=!1,s=()=>{o||n.aborted||e.session.prompt(i).catch(t=>{l(e,`Loop pass failed: ${t instanceof Error?t.message:String(t)}`,`warning`)})},c=setInterval(s,a*1e3);return c.unref?.(),s(),{instanceId:t,label:`Default loop`,detail:`every ${a}s`,stop(){o=!0,clearInterval(c)}}}});return d=r,f=i,p=r.subscribe(_),_(),async()=>{p?.(),p=void 0,await i.dispose(`Headless loop activity stopped.`),await r.dispose(`Headless loop activity stopped.`),d===r&&(d=void 0),f===i&&(f=void 0),_()}}}],commands:[{name:t,description:`Start a registered loop.`,async execute(e,t){if(!d){let e=c.context.selection.state?.[`minor-mode`]??[];await c.changeSelection({axis:`state`,key:`minor-mode`,values:[...e,s]})}if(!d)throw Error(`Loop activity is not active.`);let n=d.listLaunchers(),r=e.trim()||await t.client.request({kind:`select`,title:`Choose a loop launcher`,options:n.map(e=>({label:e.label,value:e.id}))}),i=e.trim()||(typeof r==`string`?r:``);if(!i)return;let a=await d.launch(i);_(),await l(t,a?`Loop '${a.instanceId}' started.`:`Loop launch was cancelled.`)}},{name:e,description:`List and stop active loops.`,async execute(e,t){let n=d?.listInstances()??[];await l(t,n.length===0?`No loops are active.`:JSON.stringify(n,null,2))}}],hooks:[{when:{state:{"minor-mode":s},attribution:{kind:`minor`,mode:s}},event:`session_shutdown`,async handle(){await d?.stopAll(`Headless session shutdown.`)}}],async onDispose(){await f?.dispose(`Headless loop facet disposed.`),await d?.dispose(`Headless loop facet disposed.`)}}}export{d as createSessionState};
|
|
2
|
-
//# sourceMappingURL=serverRuntime.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"serverRuntime.mjs","names":[],"sources":["../../../src/controllers/serverRuntime.ts"],"sourcesContent":["import { serverMinorModes } from '@agimon-ai/doompi-minor-mode';\nimport { defineMinorMode, type MinorModeOwner, type MinorModeState } from '@agimon-ai/doompi-minor-mode';\n\nimport { LIST_COMMAND_NAME, START_COMMAND_NAME } from '../constants/loop';\nimport type { DoomLoopLaunchersService, LoopLauncherRegistration, StoppableLoop } from '../schemas/loopLaunchers';\nimport { createDoomLoopLaunchersService, type LoopLaunchersDependencies } from '../services/loopLaunchers';\nimport { readLoopResource } from '../services/loopResource';\n\nconst SOURCE = '@agimon-ai/doompi-loop';\nconst MODE_ID = 'loop.active';\nconst DEFAULT_LAUNCHER_ID = 'doompi.default';\nconst DEFAULT_INTERVAL_SECONDS = 300;\nconst MIN_INTERVAL_SECONDS = 30;\nconst MAX_INTERVAL_SECONDS = 3600;\n\nfunction notify(\n context: {\n client: { notify(request: { body: string; level?: 'info' | 'warning' | 'error' }): void | Promise<void> };\n },\n body: string,\n level: 'info' | 'warning' | 'error' = 'info',\n): Promise<void> {\n return Promise.resolve(context.client.notify({ body, level }));\n}\n\nfunction numberInput(value: unknown, fallback: number): number {\n if (typeof value !== 'string' || value.trim() === '') return fallback;\n const parsed = Number(value);\n if (!Number.isInteger(parsed) || parsed < MIN_INTERVAL_SECONDS || parsed > MAX_INTERVAL_SECONDS) {\n throw new Error(`Interval must be between ${MIN_INTERVAL_SECONDS} and ${MAX_INTERVAL_SECONDS} seconds.`);\n }\n return parsed;\n}\n\nimport { type DoomHeadlessExecutionContext, type DoomHeadlessHostService } from '@agimon-ai/doompi-core/headless';\nimport type { DoomServerSessionPlugin } from '@agimon-ai/doompi-core/server-facet';\nexport function createSessionState(host: DoomHeadlessHostService): DoomServerSessionPlugin {\n let launchers: DoomLoopLaunchersService | undefined;\n let defaultRegistration: LoopLauncherRegistration | undefined;\n let unsubscribe: (() => void) | undefined;\n let modeOwner: MinorModeOwner | undefined;\n const modeSelected = (): boolean => (host.context.selection.state?.['minor-mode'] ?? []).includes(MODE_ID);\n const modeState = (): MinorModeState => {\n const launcherCount = launchers?.listLaunchers().length ?? 0;\n const active = (launchers?.listInstances().length ?? 0) > 0;\n const canStart = launcherCount > 0 || !modeSelected();\n return {\n activation: active ? 'active' : 'inactive',\n condition: launchers?.listInstances().some(({ state }) => state !== 'running') ? 'queued' : 'ready',\n ...(active ? { detail: `${launchers?.listInstances().length} active`, color: 'warning' } : {}),\n actions: [\n {\n id: 'start',\n enabled: canStart,\n ...(canStart ? {} : { disabledReason: 'No loop launchers are registered.' }),\n },\n {\n id: 'stop',\n enabled: active,\n ...(active ? {} : { disabledReason: 'No loops are active.' }),\n },\n ],\n };\n };\n const publishMode = (): void => modeOwner?.publish();\n const startActivity = async (execution: typeof host.context): Promise<() => Promise<void>> => {\n if (launchers !== undefined) return async () => undefined;\n const dependencies: LoopLaunchersDependencies = {\n generation: `${execution.sessionId}:loop-launchers`,\n createInstanceId: () => crypto.randomUUID(),\n timestamp: () => new Date().toISOString(),\n };\n const service = createDoomLoopLaunchersService(dependencies);\n const registration = service.register({\n id: DEFAULT_LAUNCHER_ID,\n source: SOURCE,\n label: 'Default loop',\n description: 'Run a prompt in this session on an interval.',\n async launch({ instanceId, signal }): Promise<StoppableLoop | undefined> {\n const promptValue = await execution.client.request(\n { kind: 'input', title: 'Loop prompt', multiline: true },\n signal,\n );\n const prompt = typeof promptValue === 'string' ? promptValue.trim() : '';\n if (!prompt || signal.aborted) return undefined;\n const interval = numberInput(\n await execution.client.request(\n { kind: 'input', title: 'Loop interval in seconds', initialValue: String(DEFAULT_INTERVAL_SECONDS) },\n signal,\n ),\n DEFAULT_INTERVAL_SECONDS,\n );\n let stopped = false;\n const tick = (): void => {\n if (stopped || signal.aborted) return;\n void execution.session.prompt(prompt).catch((error) => {\n void notify(\n execution,\n `Loop pass failed: ${error instanceof Error ? error.message : String(error)}`,\n 'warning',\n );\n });\n };\n const timer = setInterval(tick, interval * 1000);\n timer.unref?.();\n tick();\n return {\n instanceId,\n label: 'Default loop',\n detail: `every ${interval}s`,\n stop() {\n stopped = true;\n clearInterval(timer);\n },\n };\n },\n });\n launchers = service;\n defaultRegistration = registration;\n unsubscribe = service.subscribe(publishMode);\n publishMode();\n return async () => {\n unsubscribe?.();\n unsubscribe = undefined;\n await registration.dispose('Headless loop activity stopped.');\n await service.dispose('Headless loop activity stopped.');\n if (launchers === service) launchers = undefined;\n if (defaultRegistration === registration) defaultRegistration = undefined;\n publishMode();\n };\n };\n modeOwner = defineMinorMode({\n descriptor: {\n source: SOURCE,\n id: MODE_ID,\n label: 'Loop',\n description: 'Session-scoped recurring prompt loops.',\n order: 60,\n actions: [\n {\n id: 'start',\n label: 'Start',\n description: 'Start a loop with a registered launcher.',\n contexts: ['headless'],\n parameters: [\n { name: 'launcherId', label: 'Launcher', kind: 'string', required: true, minLength: 1 },\n { name: 'instanceId', label: 'Instance ID', kind: 'string', required: false, minLength: 1 },\n ],\n },\n {\n id: 'stop',\n label: 'Stop',\n description: 'Stop one active loop instance.',\n contexts: ['headless'],\n parameters: [\n { name: 'instanceId', label: 'Instance ID', kind: 'string', required: true, minLength: 1 },\n { name: 'reason', label: 'Reason', kind: 'string', required: false, minLength: 1 },\n ],\n },\n ],\n },\n state: modeState,\n async handleAction(_runtime, actionId, argumentsValue, { signal }) {\n signal.throwIfAborted();\n if (actionId === 'start' && !launchers) {\n const modes = (host.context.selection.state?.['minor-mode'] ?? []).filter((mode) => mode !== MODE_ID);\n await host.changeSelection({ axis: 'state', key: 'minor-mode', values: [...modes, MODE_ID] });\n }\n if (!launchers) throw new Error('Loop activity is not active.');\n if (actionId === 'start') {\n const instance = await launchers.launch(\n String(argumentsValue.launcherId ?? ''),\n argumentsValue.instanceId ? { instanceId: String(argumentsValue.instanceId) } : {},\n );\n publishMode();\n return { message: instance ? `Loop '${instance.instanceId}' started.` : 'Loop launch was cancelled.' };\n }\n if (actionId === 'stop') {\n const stopped = await launchers.stop(\n String(argumentsValue.instanceId ?? ''),\n String(argumentsValue.reason ?? 'Stopped through minor_mode.'),\n );\n if (stopped && launchers.listInstances().length === 0) {\n const modes = (host.context.selection.state?.['minor-mode'] ?? []).filter((mode) => mode !== MODE_ID);\n await host.changeSelection({ axis: 'state', key: 'minor-mode', values: modes });\n }\n publishMode();\n return { message: stopped ? 'Loop stopped.' : 'Loop instance was not active.' };\n }\n throw new Error(`Unknown loop mode action: ${actionId}`);\n },\n }).createOwner(undefined);\n return {\n services: [serverMinorModes([modeOwner])],\n resources: [\n {\n when: { state: { 'minor-mode': MODE_ID }, attribution: { kind: 'minor', mode: MODE_ID } },\n name: 'doompi-use-loop',\n kind: 'skill',\n read: () => readLoopResource(),\n },\n ],\n activities: [\n {\n when: { state: { 'minor-mode': MODE_ID }, attribution: { kind: 'minor', mode: MODE_ID } },\n name: 'doompi-loop',\n start: startActivity,\n },\n ],\n commands: [\n {\n name: START_COMMAND_NAME,\n description: 'Start a registered loop.',\n async execute(args: string, execution: DoomHeadlessExecutionContext) {\n if (!launchers) {\n const modes = host.context.selection.state?.['minor-mode'] ?? [];\n await host.changeSelection({ axis: 'state', key: 'minor-mode', values: [...modes, MODE_ID] });\n }\n if (!launchers) throw new Error('Loop activity is not active.');\n const available = launchers.listLaunchers();\n const selected =\n args.trim() ||\n (await execution.client.request({\n kind: 'select',\n title: 'Choose a loop launcher',\n options: available.map((entry) => ({ label: entry.label, value: entry.id })),\n }));\n const launcherId = args.trim() || (typeof selected === 'string' ? selected : '');\n if (!launcherId) return;\n const instance = await launchers.launch(launcherId);\n publishMode();\n await notify(execution, instance ? `Loop '${instance.instanceId}' started.` : 'Loop launch was cancelled.');\n },\n },\n {\n name: LIST_COMMAND_NAME,\n description: 'List and stop active loops.',\n async execute(_args: string, execution: DoomHeadlessExecutionContext) {\n const instances = launchers?.listInstances() ?? [];\n await notify(execution, instances.length === 0 ? 'No loops are active.' : JSON.stringify(instances, null, 2));\n },\n },\n ],\n hooks: [\n {\n when: { state: { 'minor-mode': MODE_ID }, attribution: { kind: 'minor', mode: MODE_ID } },\n event: 'session_shutdown',\n async handle() {\n await launchers?.stopAll('Headless session shutdown.');\n },\n },\n ],\n async onDispose() {\n await defaultRegistration?.dispose('Headless loop facet disposed.');\n await launchers?.dispose('Headless loop facet disposed.');\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const e=require("../../../_virtual/_rolldown/runtime.cjs");let t=require("node:fs"),n=require("node:fs/promises"),r=require("node:path");r=e.__toESM(r,1);let i=require("node:url");async function a(){let e=r.default.dirname((0,i.fileURLToPath)(require("url").pathToFileURL(__filename).href));for(;!(0,t.existsSync)(r.default.join(e,`package.json`));){let t=r.default.dirname(e);if(t===e)throw Error(`Loop package resource not found.`);e=t}return(0,n.readFile)(r.default.join(e,`src/prompts/doompi-use-loop/SKILL.md`),`utf8`)}exports.readLoopResource=a;
|
|
2
|
-
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["path","fileURLToPath","existsSync","readFile"],"sources":["../../../../src/services/loopResource/index.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nexport async function readLoopResource(): Promise<string> {\n let directory = path.dirname(fileURLToPath(import.meta.url));\n while (!existsSync(path.join(directory, 'package.json'))) {\n const parent = path.dirname(directory);\n if (parent === directory) throw new Error('Loop package resource not found.');\n directory = parent;\n }\n return readFile(path.join(directory, 'src/prompts/doompi-use-loop/SKILL.md'), 'utf8');\n}\n"],"mappings":"oLAIA,eAAsB,GAAoC,CACxD,IAAI,EAAYA,EAAAA,QAAK,SAAA,EAAQC,EAAAA,cAAAA,CAAAA,QAAAA,KAAAA,CAAAA,CAAAA,cAAAA,UAAAA,CAAAA,CAAAA,IAA6B,CAAC,EAC3D,KAAO,EAAA,EAACC,EAAAA,WAAAA,CAAWF,EAAAA,QAAK,KAAK,EAAW,cAAc,CAAC,GAAG,CACxD,IAAM,EAASA,EAAAA,QAAK,QAAQ,CAAS,EACrC,GAAI,IAAW,EAAW,MAAU,MAAM,kCAAkC,EAC5E,EAAY,CACd,CACA,OAAA,EAAOG,EAAAA,SAAAA,CAASH,EAAAA,QAAK,KAAK,EAAW,sCAAsC,EAAG,MAAM,CACtF"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{existsSync as e}from"node:fs";import{readFile as t}from"node:fs/promises";import n from"node:path";import{fileURLToPath as r}from"node:url";async function i(){let i=n.dirname(r(import.meta.url));for(;!e(n.join(i,`package.json`));){let e=n.dirname(i);if(e===i)throw Error(`Loop package resource not found.`);i=e}return t(n.join(i,`src/prompts/doompi-use-loop/SKILL.md`),`utf8`)}export{i as readLoopResource};
|
|
2
|
-
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/services/loopResource/index.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nexport async function readLoopResource(): Promise<string> {\n let directory = path.dirname(fileURLToPath(import.meta.url));\n while (!existsSync(path.join(directory, 'package.json'))) {\n const parent = path.dirname(directory);\n if (parent === directory) throw new Error('Loop package resource not found.');\n directory = parent;\n }\n return readFile(path.join(directory, 'src/prompts/doompi-use-loop/SKILL.md'), 'utf8');\n}\n"],"mappings":"mJAIA,eAAsB,GAAoC,CACxD,IAAI,EAAY,EAAK,QAAQ,EAAc,YAAY,GAAG,CAAC,EAC3D,KAAO,CAAC,EAAW,EAAK,KAAK,EAAW,cAAc,CAAC,GAAG,CACxD,IAAM,EAAS,EAAK,QAAQ,CAAS,EACrC,GAAI,IAAW,EAAW,MAAU,MAAM,kCAAkC,EAC5E,EAAY,CACd,CACA,OAAO,EAAS,EAAK,KAAK,EAAW,sCAAsC,EAAG,MAAM,CACtF"}
|
package/src/extensions/web.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { defineSlot, defineWebPlugin } from '@agimon-ai/doompi-core/web';
|
|
2
|
-
|
|
3
|
-
import { LOOP_VIEW_STATUS_KEY } from '../types/loopView';
|
|
4
|
-
import { LoopActivityItems, LoopsActivitySection } from '../web/components/LoopsActivitySection';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* This package's cockpit presence. The selection bar carries the minor mode,
|
|
8
|
-
* while the activity dock shows each loop the active session is scheduling.
|
|
9
|
-
*/
|
|
10
|
-
const LOOPS_GROUP = { key: 'l', label: 'loops', detail: 'recurring prompt loops' };
|
|
11
|
-
const LOOPS_ACTIVITY_SOURCE = {
|
|
12
|
-
subscribe: () => () => undefined,
|
|
13
|
-
// Keeping the scheduler's launcher visible does not mean a result is pending.
|
|
14
|
-
isActive: (_sessionId: string | null) => false,
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export const webPlugin = defineWebPlugin({
|
|
18
|
-
id: 'loop',
|
|
19
|
-
session: {
|
|
20
|
-
minorModes: [{ name: 'loop', keys: 'l l', statusKey: 'doom-loop', activityGroup: 'loops', order: 30 }],
|
|
21
|
-
activityGroups: [
|
|
22
|
-
{ name: 'loops', keys: 'l l', statusKey: LOOP_VIEW_STATUS_KEY, activeSource: LOOPS_ACTIVITY_SOURCE, order: 40 },
|
|
23
|
-
],
|
|
24
|
-
activitySections: [{ id: 'loops', component: LoopsActivitySection }],
|
|
25
|
-
slots: [defineSlot({ slot: 'loop.registration' }), defineSlot({ slot: 'loop.items' })],
|
|
26
|
-
fills: [{ slot: 'loop.items', id: 'instances', component: LoopActivityItems }],
|
|
27
|
-
// The TUI's SPC l s and SPC l l: both are slash commands, so both carry over.
|
|
28
|
-
leaderBindings: [
|
|
29
|
-
{
|
|
30
|
-
id: 'loop.start',
|
|
31
|
-
path: [LOOPS_GROUP, { key: 's', label: 'start', detail: 'begin a recurring loop' }],
|
|
32
|
-
command: 'loop',
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
id: 'loop.list',
|
|
36
|
-
path: [LOOPS_GROUP, { key: 'l', label: 'list', detail: 'loops in this session' }],
|
|
37
|
-
command: 'loops',
|
|
38
|
-
},
|
|
39
|
-
],
|
|
40
|
-
},
|
|
41
|
-
});
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import type { WebPluginSlotProps } from '@agimon-ai/doompi-core/web';
|
|
2
|
-
import { Button, Dot, type DotTone } from '@agimon-ai/doompi-web-components';
|
|
3
|
-
|
|
4
|
-
import { LOOP_VIEW_STATUS_KEY, parseLoopStatusView, type LoopStatusState } from '../../types/loopView';
|
|
5
|
-
|
|
6
|
-
const MANAGE_COMMAND = '/loops';
|
|
7
|
-
const DEFAULT_LOOP_COMMAND = '/loop doompi.default';
|
|
8
|
-
|
|
9
|
-
/** Starts the built-in prompt loop without opening a generic launcher chooser. */
|
|
10
|
-
export function DefaultLoopLauncher({
|
|
11
|
-
sessionId,
|
|
12
|
-
sendSessionFrame,
|
|
13
|
-
}: Pick<WebPluginSlotProps, 'sessionId' | 'sendSessionFrame'>) {
|
|
14
|
-
return (
|
|
15
|
-
<Button
|
|
16
|
-
variant="subtle"
|
|
17
|
-
size="xs"
|
|
18
|
-
data-testid="activity-loop-default-launch"
|
|
19
|
-
aria-label="launch default loop"
|
|
20
|
-
disabled={sessionId === null}
|
|
21
|
-
onClick={() => {
|
|
22
|
-
if (sessionId === null) return;
|
|
23
|
-
sendSessionFrame(sessionId, { type: 'prompt', message: DEFAULT_LOOP_COMMAND });
|
|
24
|
-
}}
|
|
25
|
-
className="text-2xs font-bold"
|
|
26
|
-
>
|
|
27
|
-
default loop
|
|
28
|
-
</Button>
|
|
29
|
-
);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function toneOf(state: LoopStatusState): DotTone {
|
|
33
|
-
if (state === 'running') return 'green';
|
|
34
|
-
if (state === 'stopping') return 'orange';
|
|
35
|
-
return 'yellow';
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/** Renders active recurring prompts contributed to the Loop activity section. */
|
|
39
|
-
export function LoopActivityItems({ statuses }: Pick<WebPluginSlotProps, 'statuses'>) {
|
|
40
|
-
const raw = statuses[LOOP_VIEW_STATUS_KEY];
|
|
41
|
-
const loops = parseLoopStatusView(raw);
|
|
42
|
-
const unavailable = raw !== undefined && raw.trim() !== '' && loops === undefined;
|
|
43
|
-
if (!loops && !unavailable) return null;
|
|
44
|
-
|
|
45
|
-
return loops ? (
|
|
46
|
-
<ul aria-label="active loops" className="flex flex-col gap-1">
|
|
47
|
-
{loops.map((loop) => (
|
|
48
|
-
<li
|
|
49
|
-
key={loop.instanceId}
|
|
50
|
-
data-testid={`activity-loop-${loop.instanceId}`}
|
|
51
|
-
data-loop-state={loop.state}
|
|
52
|
-
title={`${loop.label}: ${loop.detail}`}
|
|
53
|
-
className="flex min-w-0 flex-col gap-0.5 px-1 py-0.5"
|
|
54
|
-
>
|
|
55
|
-
<span className="flex min-w-0 items-center gap-1.5">
|
|
56
|
-
<Dot tone={toneOf(loop.state)} pulse={loop.state !== 'running'} />
|
|
57
|
-
<span className="min-w-0 flex-1 truncate text-xs font-bold text-doom-hi">{loop.label}</span>
|
|
58
|
-
<span className="shrink-0 text-2xs text-doom-faint">{loop.state}</span>
|
|
59
|
-
</span>
|
|
60
|
-
<span className="truncate pl-3 text-2xs text-doom-faint">{loop.detail}</span>
|
|
61
|
-
</li>
|
|
62
|
-
))}
|
|
63
|
-
</ul>
|
|
64
|
-
) : (
|
|
65
|
-
<p className="px-1 text-xs text-doom-faint">loop status unavailable</p>
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/** Idle-safe Loop activity shell with extension registration and instance slots. */
|
|
70
|
-
export function LoopsActivitySection({ sessionId, renderSlot, sendSessionFrame }: WebPluginSlotProps) {
|
|
71
|
-
return (
|
|
72
|
-
<div data-testid="activity-loop-instances" className="flex flex-col gap-2">
|
|
73
|
-
<div className="flex flex-wrap items-center gap-1">
|
|
74
|
-
<DefaultLoopLauncher sessionId={sessionId} sendSessionFrame={sendSessionFrame} />
|
|
75
|
-
{renderSlot('loop.registration')}
|
|
76
|
-
</div>
|
|
77
|
-
{renderSlot('loop.items')}
|
|
78
|
-
<Button
|
|
79
|
-
variant="subtle"
|
|
80
|
-
size="xs"
|
|
81
|
-
data-testid="activity-loops-manage"
|
|
82
|
-
aria-label="manage loops"
|
|
83
|
-
disabled={sessionId === null}
|
|
84
|
-
onClick={() => {
|
|
85
|
-
if (sessionId === null) return;
|
|
86
|
-
sendSessionFrame(sessionId, { type: 'prompt', message: MANAGE_COMMAND });
|
|
87
|
-
}}
|
|
88
|
-
className="self-end text-2xs font-bold"
|
|
89
|
-
>
|
|
90
|
-
manage
|
|
91
|
-
</Button>
|
|
92
|
-
</div>
|
|
93
|
-
);
|
|
94
|
-
}
|
package/src/web/tsconfig.json
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2022",
|
|
4
|
-
"lib": ["ES2023", "DOM", "DOM.Iterable"],
|
|
5
|
-
"module": "ESNext",
|
|
6
|
-
"moduleResolution": "Bundler",
|
|
7
|
-
"jsx": "react-jsx",
|
|
8
|
-
"strict": true,
|
|
9
|
-
"noImplicitAny": true,
|
|
10
|
-
"noUnusedLocals": true,
|
|
11
|
-
"noUnusedParameters": true,
|
|
12
|
-
"noImplicitReturns": true,
|
|
13
|
-
"noFallthroughCasesInSwitch": true,
|
|
14
|
-
"noEmit": true,
|
|
15
|
-
"resolveJsonModule": true,
|
|
16
|
-
"esModuleInterop": true,
|
|
17
|
-
"skipLibCheck": true,
|
|
18
|
-
"allowImportingTsExtensions": true,
|
|
19
|
-
"forceConsistentCasingInFileNames": true,
|
|
20
|
-
"types": ["node"]
|
|
21
|
-
},
|
|
22
|
-
"include": [".", "../types", "../extensions/web.ts", "../../tests/web"]
|
|
23
|
-
}
|