dot-agents 0.5.0 → 0.7.4
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 +239 -122
- package/dist/cli/commands/channel.d.ts +19 -0
- package/dist/cli/commands/channel.d.ts.map +1 -1
- package/dist/cli/commands/channel.js +220 -13
- package/dist/cli/commands/channel.js.map +1 -1
- package/dist/cli/commands/check.d.ts.map +1 -1
- package/dist/cli/commands/check.js +61 -1
- package/dist/cli/commands/check.js.map +1 -1
- package/dist/cli/commands/index.d.ts +2 -0
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.js +2 -0
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/personas.d.ts +3 -0
- package/dist/cli/commands/personas.d.ts.map +1 -0
- package/dist/cli/commands/personas.js +402 -0
- package/dist/cli/commands/personas.js.map +1 -0
- package/dist/cli/commands/projects.d.ts +3 -0
- package/dist/cli/commands/projects.d.ts.map +1 -0
- package/dist/cli/commands/projects.js +138 -0
- package/dist/cli/commands/projects.js.map +1 -0
- package/dist/cli/commands/run.d.ts.map +1 -1
- package/dist/cli/commands/run.js +4 -5
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/cli/index.js +3 -11
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/lib/runner.d.ts +2 -0
- package/dist/cli/lib/runner.d.ts.map +1 -1
- package/dist/cli/lib/runner.js +67 -8
- package/dist/cli/lib/runner.js.map +1 -1
- package/dist/daemon/api/channels.d.ts +6 -0
- package/dist/daemon/api/channels.d.ts.map +1 -0
- package/dist/daemon/api/channels.js +143 -0
- package/dist/daemon/api/channels.js.map +1 -0
- package/dist/daemon/api/server.d.ts.map +1 -1
- package/dist/daemon/api/server.js +56 -0
- package/dist/daemon/api/server.js.map +1 -1
- package/dist/daemon/daemon.d.ts +28 -3
- package/dist/daemon/daemon.d.ts.map +1 -1
- package/dist/daemon/daemon.js +142 -26
- package/dist/daemon/daemon.js.map +1 -1
- package/dist/daemon/lib/executor.d.ts +0 -4
- package/dist/daemon/lib/executor.d.ts.map +1 -1
- package/dist/daemon/lib/executor.js +48 -135
- package/dist/daemon/lib/executor.js.map +1 -1
- package/dist/daemon/lib/index.d.ts +1 -0
- package/dist/daemon/lib/index.d.ts.map +1 -1
- package/dist/daemon/lib/index.js +1 -0
- package/dist/daemon/lib/index.js.map +1 -1
- package/dist/daemon/lib/safeguards.d.ts +68 -0
- package/dist/daemon/lib/safeguards.d.ts.map +1 -0
- package/dist/daemon/lib/safeguards.js +135 -0
- package/dist/daemon/lib/safeguards.js.map +1 -0
- package/dist/daemon/lib/watcher.d.ts.map +1 -1
- package/dist/daemon/lib/watcher.js +48 -8
- package/dist/daemon/lib/watcher.js.map +1 -1
- package/dist/daemon/web/app.js +433 -0
- package/dist/daemon/web/index.html +68 -0
- package/dist/daemon/web/styles.css +452 -0
- package/dist/lib/channel.d.ts +53 -1
- package/dist/lib/channel.d.ts.map +1 -1
- package/dist/lib/channel.js +221 -30
- package/dist/lib/channel.js.map +1 -1
- package/dist/lib/daemon-status.d.ts +26 -0
- package/dist/lib/daemon-status.d.ts.map +1 -0
- package/dist/lib/daemon-status.js +64 -0
- package/dist/lib/daemon-status.js.map +1 -0
- package/dist/lib/environment.d.ts +88 -0
- package/dist/lib/environment.d.ts.map +1 -0
- package/dist/lib/environment.js +238 -0
- package/dist/lib/environment.js.map +1 -0
- package/dist/lib/frontmatter.d.ts +8 -0
- package/dist/lib/frontmatter.d.ts.map +1 -1
- package/dist/lib/frontmatter.js +16 -3
- package/dist/lib/frontmatter.js.map +1 -1
- package/dist/lib/index.d.ts +7 -0
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +7 -0
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/invoke.d.ts +31 -0
- package/dist/lib/invoke.d.ts.map +1 -0
- package/dist/lib/invoke.js +170 -0
- package/dist/lib/invoke.js.map +1 -0
- package/dist/lib/persona.d.ts +22 -1
- package/dist/lib/persona.d.ts.map +1 -1
- package/dist/lib/persona.js +176 -31
- package/dist/lib/persona.js.map +1 -1
- package/dist/lib/processor.d.ts +58 -0
- package/dist/lib/processor.d.ts.map +1 -0
- package/dist/lib/processor.js +149 -0
- package/dist/lib/processor.js.map +1 -0
- package/dist/lib/registry.d.ts +109 -0
- package/dist/lib/registry.d.ts.map +1 -0
- package/dist/lib/registry.js +192 -0
- package/dist/lib/registry.js.map +1 -0
- package/dist/lib/session-thread.d.ts +75 -0
- package/dist/lib/session-thread.d.ts.map +1 -0
- package/dist/lib/session-thread.js +132 -0
- package/dist/lib/session-thread.js.map +1 -0
- package/dist/lib/session.d.ts +150 -0
- package/dist/lib/session.d.ts.map +1 -0
- package/dist/lib/session.js +183 -0
- package/dist/lib/session.js.map +1 -0
- package/dist/lib/types/channel.d.ts +4 -0
- package/dist/lib/types/channel.d.ts.map +1 -1
- package/dist/lib/types/persona.d.ts +49 -6
- package/dist/lib/types/persona.d.ts.map +1 -1
- package/dist/lib/validation/persona.d.ts.map +1 -1
- package/dist/lib/validation/persona.js +41 -4
- package/dist/lib/validation/persona.js.map +1 -1
- package/internal/personas/_base/PERSONA.md +222 -39
- package/internal/skills/channels/list/SKILL.md +76 -0
- package/package.json +15 -5
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { readFile, writeFile, mkdir } from "node:fs/promises";
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
5
|
+
const CONFIG_DIR = join(homedir(), ".config", "dot-agents");
|
|
6
|
+
const REGISTRY_FILE = "projects.yaml";
|
|
7
|
+
/**
|
|
8
|
+
* Get path to the projects registry file
|
|
9
|
+
*/
|
|
10
|
+
export function getRegistryPath() {
|
|
11
|
+
return join(CONFIG_DIR, REGISTRY_FILE);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Load the project registry
|
|
15
|
+
*/
|
|
16
|
+
export async function loadRegistry() {
|
|
17
|
+
const registryPath = getRegistryPath();
|
|
18
|
+
try {
|
|
19
|
+
const content = await readFile(registryPath, "utf-8");
|
|
20
|
+
const data = parseYaml(content);
|
|
21
|
+
return data || { projects: {} };
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return { projects: {} };
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Save the project registry
|
|
29
|
+
*/
|
|
30
|
+
export async function saveRegistry(registry) {
|
|
31
|
+
await mkdir(CONFIG_DIR, { recursive: true });
|
|
32
|
+
const registryPath = getRegistryPath();
|
|
33
|
+
const content = stringifyYaml(registry);
|
|
34
|
+
await writeFile(registryPath, content, "utf-8");
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Register a project in the registry
|
|
38
|
+
*/
|
|
39
|
+
export async function registerProject(name, path) {
|
|
40
|
+
const registry = await loadRegistry();
|
|
41
|
+
// Expand ~ to home directory
|
|
42
|
+
const expandedPath = path.startsWith("~")
|
|
43
|
+
? join(homedir(), path.slice(1))
|
|
44
|
+
: resolve(path);
|
|
45
|
+
registry.projects[name] = expandedPath;
|
|
46
|
+
await saveRegistry(registry);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Unregister a project from the registry
|
|
50
|
+
*/
|
|
51
|
+
export async function unregisterProject(name) {
|
|
52
|
+
const registry = await loadRegistry();
|
|
53
|
+
if (name in registry.projects) {
|
|
54
|
+
delete registry.projects[name];
|
|
55
|
+
await saveRegistry(registry);
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Resolve a project name to its .agents path
|
|
62
|
+
*/
|
|
63
|
+
export async function resolveProject(name) {
|
|
64
|
+
const registry = await loadRegistry();
|
|
65
|
+
const path = registry.projects[name];
|
|
66
|
+
if (!path) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
// Expand ~ if present (in case registry was edited manually)
|
|
70
|
+
return path.startsWith("~") ? join(homedir(), path.slice(1)) : path;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Parse a channel address that may include a project prefix
|
|
74
|
+
*
|
|
75
|
+
* Formats:
|
|
76
|
+
* - @persona (local DM)
|
|
77
|
+
* - #channel (local public channel)
|
|
78
|
+
* - @project/persona (cross-project DM)
|
|
79
|
+
* - #project/channel (cross-project public channel)
|
|
80
|
+
*/
|
|
81
|
+
export function parseChannelAddress(address) {
|
|
82
|
+
if (!address.startsWith("#") && !address.startsWith("@")) {
|
|
83
|
+
throw new Error(`Invalid channel address: ${address}. Must start with # or @`);
|
|
84
|
+
}
|
|
85
|
+
const type = address[0];
|
|
86
|
+
const rest = address.slice(1);
|
|
87
|
+
// Check for project/name format
|
|
88
|
+
const slashIndex = rest.indexOf("/");
|
|
89
|
+
if (slashIndex > 0) {
|
|
90
|
+
const project = rest.slice(0, slashIndex);
|
|
91
|
+
const name = rest.slice(slashIndex + 1);
|
|
92
|
+
if (!name) {
|
|
93
|
+
throw new Error(`Invalid channel address: ${address}. Missing channel/persona name after project.`);
|
|
94
|
+
}
|
|
95
|
+
return { project, type, name, original: address };
|
|
96
|
+
}
|
|
97
|
+
// Local channel
|
|
98
|
+
return { project: null, type, name: rest, original: address };
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Resolve a channel address to a channels directory and local channel name
|
|
102
|
+
*
|
|
103
|
+
* Resolution order for @name (without /):
|
|
104
|
+
* 1. Check registered projects first - if found, routes to project's @root
|
|
105
|
+
* 2. Fall back to local persona lookup
|
|
106
|
+
*
|
|
107
|
+
* Returns:
|
|
108
|
+
* - channelsDir: The path to the channels directory (local or remote)
|
|
109
|
+
* - localChannelName: The channel name within that directory (e.g., @persona, #channel)
|
|
110
|
+
* - isProjectEntryPoint: True if routed to a project's entry point
|
|
111
|
+
* - projectName: The project name if routed to a project
|
|
112
|
+
*/
|
|
113
|
+
export async function resolveChannelAddress(address, localChannelsDir) {
|
|
114
|
+
const parsed = parseChannelAddress(address);
|
|
115
|
+
if (parsed.project === null) {
|
|
116
|
+
// Check if @name matches a registered project (unified resolution)
|
|
117
|
+
if (parsed.type === "@") {
|
|
118
|
+
const projectPath = await resolveProject(parsed.name);
|
|
119
|
+
if (projectPath) {
|
|
120
|
+
// Route to project's entry point (@root)
|
|
121
|
+
return {
|
|
122
|
+
channelsDir: join(projectPath, "channels"),
|
|
123
|
+
localChannelName: "@root",
|
|
124
|
+
isProjectEntryPoint: true,
|
|
125
|
+
projectName: parsed.name,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// Local channel (no project match or public channel)
|
|
130
|
+
return {
|
|
131
|
+
channelsDir: localChannelsDir,
|
|
132
|
+
localChannelName: address,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
// Cross-project channel with explicit project/name format
|
|
136
|
+
const projectPath = await resolveProject(parsed.project);
|
|
137
|
+
if (!projectPath) {
|
|
138
|
+
throw new Error(`Unknown project: ${parsed.project}. Register it with: npx dot-agents projects add ${parsed.project} /path/to/project`);
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
channelsDir: join(projectPath, "channels"),
|
|
142
|
+
localChannelName: `${parsed.type}${parsed.name}`,
|
|
143
|
+
projectName: parsed.project,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* List all registered projects
|
|
148
|
+
*/
|
|
149
|
+
export async function listProjects() {
|
|
150
|
+
const registry = await loadRegistry();
|
|
151
|
+
return Object.entries(registry.projects).map(([name, path]) => ({
|
|
152
|
+
name,
|
|
153
|
+
path,
|
|
154
|
+
}));
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Get the project name for a given agents directory path
|
|
158
|
+
* Returns null if the path doesn't match any registered project
|
|
159
|
+
*/
|
|
160
|
+
export async function getProjectNameByPath(agentsDir) {
|
|
161
|
+
const registry = await loadRegistry();
|
|
162
|
+
const normalizedPath = agentsDir.replace(/\/$/, ""); // Remove trailing slash
|
|
163
|
+
for (const [name, path] of Object.entries(registry.projects)) {
|
|
164
|
+
const normalizedProjectPath = path.replace(/\/$/, "");
|
|
165
|
+
if (normalizedPath === normalizedProjectPath) {
|
|
166
|
+
return name;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Detect collisions between registered project names and local persona names.
|
|
173
|
+
* When a collision exists, @name will route to the project (projects take priority).
|
|
174
|
+
*/
|
|
175
|
+
export async function detectNameCollisions(personaNames) {
|
|
176
|
+
const registry = await loadRegistry();
|
|
177
|
+
const collisions = [];
|
|
178
|
+
for (const [projectName, projectPath] of Object.entries(registry.projects)) {
|
|
179
|
+
// Check if any persona name matches the project name
|
|
180
|
+
for (const personaName of personaNames) {
|
|
181
|
+
if (personaName === projectName) {
|
|
182
|
+
collisions.push({
|
|
183
|
+
name: projectName,
|
|
184
|
+
projectPath: projectPath,
|
|
185
|
+
personaPath: personaName,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return collisions;
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/lib/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session-as-Thread primitives
|
|
3
|
+
*
|
|
4
|
+
* Sessions are threads in the #sessions channel. This provides a simpler
|
|
5
|
+
* model than the directory-based sessions, with cross-machine coordination
|
|
6
|
+
* via file sync (since channels are just files).
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Session start options
|
|
10
|
+
*/
|
|
11
|
+
export interface StartSessionOptions {
|
|
12
|
+
/** Base channels directory */
|
|
13
|
+
channelsDir: string;
|
|
14
|
+
/** Persona name running the session */
|
|
15
|
+
persona: string;
|
|
16
|
+
/** Execution mode */
|
|
17
|
+
mode: "interactive" | "headless";
|
|
18
|
+
/** What triggered the session */
|
|
19
|
+
trigger: "manual" | "cron" | "dm" | "channel";
|
|
20
|
+
/** Session goal/description */
|
|
21
|
+
goal?: string;
|
|
22
|
+
/** Upstream return address for delegation callbacks */
|
|
23
|
+
upstream?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Active session handle
|
|
27
|
+
*/
|
|
28
|
+
export interface SessionThread {
|
|
29
|
+
/** Session/thread ID (ISO timestamp) */
|
|
30
|
+
id: string;
|
|
31
|
+
/** Path to workspace directory */
|
|
32
|
+
workspacePath: string;
|
|
33
|
+
/** Channels directory */
|
|
34
|
+
channelsDir: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Start a new session by creating a thread in #sessions
|
|
38
|
+
*
|
|
39
|
+
* @returns Session handle with thread ID and workspace path
|
|
40
|
+
*/
|
|
41
|
+
export declare function startSession(options: StartSessionOptions): Promise<SessionThread>;
|
|
42
|
+
/**
|
|
43
|
+
* Post an update to a session thread
|
|
44
|
+
*
|
|
45
|
+
* @param session - Session handle or session ID
|
|
46
|
+
* @param channelsDir - Channels directory (required if session is just an ID)
|
|
47
|
+
* @param message - Update message content
|
|
48
|
+
* @param from - Who is posting (defaults to session persona)
|
|
49
|
+
*/
|
|
50
|
+
export declare function updateSession(session: SessionThread | string, channelsDirOrMessage: string, messageOrFrom?: string, from?: string): Promise<string>;
|
|
51
|
+
/**
|
|
52
|
+
* End session options
|
|
53
|
+
*/
|
|
54
|
+
export interface EndSessionOptions {
|
|
55
|
+
/** Whether the session completed successfully */
|
|
56
|
+
success: boolean;
|
|
57
|
+
/** Exit code */
|
|
58
|
+
exitCode: number;
|
|
59
|
+
/** Duration in milliseconds */
|
|
60
|
+
duration: number;
|
|
61
|
+
/** Error message if failed */
|
|
62
|
+
error?: string;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* End a session by posting a completion message
|
|
66
|
+
*
|
|
67
|
+
* @param session - Session handle
|
|
68
|
+
* @param options - End session options
|
|
69
|
+
*/
|
|
70
|
+
export declare function endSession(session: SessionThread, options: EndSessionOptions): Promise<string>;
|
|
71
|
+
/**
|
|
72
|
+
* Get the workspace path for a session thread
|
|
73
|
+
*/
|
|
74
|
+
export declare function getSessionWorkspace(channelsDir: string, sessionId: string, create?: boolean): Promise<string | null>;
|
|
75
|
+
//# sourceMappingURL=session-thread.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-thread.d.ts","sourceRoot":"","sources":["../../src/lib/session-thread.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAYH;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,8BAA8B;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,qBAAqB;IACrB,IAAI,EAAE,aAAa,GAAG,UAAU,CAAC;IACjC,iCAAiC;IACjC,OAAO,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC9C,+BAA+B;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,wCAAwC;IACxC,EAAE,EAAE,MAAM,CAAC;IACX,kCAAkC;IAClC,aAAa,EAAE,MAAM,CAAC;IACtB,yBAAyB;IACzB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,aAAa,CAAC,CA0CxB;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,aAAa,GAAG,MAAM,EAC/B,oBAAoB,EAAE,MAAM,EAC5B,aAAa,CAAC,EAAE,MAAM,EACtB,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,CAAC,CA+BjB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,iDAAiD;IACjD,OAAO,EAAE,OAAO,CAAC;IACjB,gBAAgB;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,+BAA+B;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,MAAM,CAAC,CA4BjB;AAsBD;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,MAAM,GAAE,OAAe,GACtB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAExB"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session-as-Thread primitives
|
|
3
|
+
*
|
|
4
|
+
* Sessions are threads in the #sessions channel. This provides a simpler
|
|
5
|
+
* model than the directory-based sessions, with cross-machine coordination
|
|
6
|
+
* via file sync (since channels are just files).
|
|
7
|
+
*/
|
|
8
|
+
import { hostname } from "node:os";
|
|
9
|
+
import { publishMessage, replyToMessage, getThreadWorkspace, } from "./channel.js";
|
|
10
|
+
const SESSIONS_CHANNEL = "#sessions";
|
|
11
|
+
/**
|
|
12
|
+
* Start a new session by creating a thread in #sessions
|
|
13
|
+
*
|
|
14
|
+
* @returns Session handle with thread ID and workspace path
|
|
15
|
+
*/
|
|
16
|
+
export async function startSession(options) {
|
|
17
|
+
const { channelsDir, persona, mode, trigger, goal, upstream } = options;
|
|
18
|
+
const host = hostname();
|
|
19
|
+
// Build the initial session message
|
|
20
|
+
const lines = [];
|
|
21
|
+
lines.push("**Session Started**");
|
|
22
|
+
lines.push("");
|
|
23
|
+
lines.push(`- **Persona:** ${persona}`);
|
|
24
|
+
lines.push(`- **Mode:** ${mode}`);
|
|
25
|
+
lines.push(`- **Trigger:** ${trigger}`);
|
|
26
|
+
lines.push(`- **Host:** ${host}`);
|
|
27
|
+
if (goal) {
|
|
28
|
+
lines.push(`- **Goal:** ${goal}`);
|
|
29
|
+
}
|
|
30
|
+
if (upstream) {
|
|
31
|
+
lines.push(`- **Upstream:** ${upstream}`);
|
|
32
|
+
}
|
|
33
|
+
// Publish to #sessions channel
|
|
34
|
+
const threadId = await publishMessage(channelsDir, SESSIONS_CHANNEL, lines.join("\n"), {
|
|
35
|
+
from: `session:${persona}`,
|
|
36
|
+
tags: ["session-start", mode, trigger],
|
|
37
|
+
});
|
|
38
|
+
// Create and return workspace path
|
|
39
|
+
const workspacePath = await getThreadWorkspace(channelsDir, SESSIONS_CHANNEL, threadId, true // create if doesn't exist
|
|
40
|
+
);
|
|
41
|
+
if (!workspacePath) {
|
|
42
|
+
throw new Error(`Failed to create workspace for session ${threadId}`);
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
id: threadId,
|
|
46
|
+
workspacePath,
|
|
47
|
+
channelsDir,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Post an update to a session thread
|
|
52
|
+
*
|
|
53
|
+
* @param session - Session handle or session ID
|
|
54
|
+
* @param channelsDir - Channels directory (required if session is just an ID)
|
|
55
|
+
* @param message - Update message content
|
|
56
|
+
* @param from - Who is posting (defaults to session persona)
|
|
57
|
+
*/
|
|
58
|
+
export async function updateSession(session, channelsDirOrMessage, messageOrFrom, from) {
|
|
59
|
+
let channelsDir;
|
|
60
|
+
let threadId;
|
|
61
|
+
let message;
|
|
62
|
+
let sender;
|
|
63
|
+
if (typeof session === "string") {
|
|
64
|
+
// Called as updateSession(threadId, channelsDir, message, from?)
|
|
65
|
+
threadId = session;
|
|
66
|
+
channelsDir = channelsDirOrMessage;
|
|
67
|
+
message = messageOrFrom;
|
|
68
|
+
sender = from;
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
// Called as updateSession(session, message, from?)
|
|
72
|
+
threadId = session.id;
|
|
73
|
+
channelsDir = session.channelsDir;
|
|
74
|
+
message = channelsDirOrMessage;
|
|
75
|
+
sender = messageOrFrom;
|
|
76
|
+
}
|
|
77
|
+
const replyId = await replyToMessage(channelsDir, SESSIONS_CHANNEL, threadId, message, {
|
|
78
|
+
from: sender,
|
|
79
|
+
});
|
|
80
|
+
return replyId;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* End a session by posting a completion message
|
|
84
|
+
*
|
|
85
|
+
* @param session - Session handle
|
|
86
|
+
* @param options - End session options
|
|
87
|
+
*/
|
|
88
|
+
export async function endSession(session, options) {
|
|
89
|
+
const { success, exitCode, duration, error } = options;
|
|
90
|
+
// Format duration nicely
|
|
91
|
+
const durationStr = formatDuration(duration);
|
|
92
|
+
const lines = [];
|
|
93
|
+
lines.push("**Session Ended**");
|
|
94
|
+
lines.push("");
|
|
95
|
+
lines.push(`- **Success:** ${success ? "✓" : "✗"}`);
|
|
96
|
+
lines.push(`- **Exit Code:** ${exitCode}`);
|
|
97
|
+
lines.push(`- **Duration:** ${durationStr}`);
|
|
98
|
+
if (error) {
|
|
99
|
+
lines.push(`- **Error:** ${error}`);
|
|
100
|
+
}
|
|
101
|
+
const replyId = await replyToMessage(session.channelsDir, SESSIONS_CHANNEL, session.id, lines.join("\n"), {
|
|
102
|
+
from: "system",
|
|
103
|
+
tags: ["session-end", success ? "success" : "failed"],
|
|
104
|
+
});
|
|
105
|
+
return replyId;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Format duration in human-readable form
|
|
109
|
+
*/
|
|
110
|
+
function formatDuration(ms) {
|
|
111
|
+
if (ms < 1000) {
|
|
112
|
+
return `${ms}ms`;
|
|
113
|
+
}
|
|
114
|
+
if (ms < 60000) {
|
|
115
|
+
return `${(ms / 1000).toFixed(1)}s`;
|
|
116
|
+
}
|
|
117
|
+
if (ms < 3600000) {
|
|
118
|
+
const mins = Math.floor(ms / 60000);
|
|
119
|
+
const secs = Math.floor((ms % 60000) / 1000);
|
|
120
|
+
return secs > 0 ? `${mins}m ${secs}s` : `${mins}m`;
|
|
121
|
+
}
|
|
122
|
+
const hours = Math.floor(ms / 3600000);
|
|
123
|
+
const mins = Math.floor((ms % 3600000) / 60000);
|
|
124
|
+
return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Get the workspace path for a session thread
|
|
128
|
+
*/
|
|
129
|
+
export async function getSessionWorkspace(channelsDir, sessionId, create = false) {
|
|
130
|
+
return getThreadWorkspace(channelsDir, SESSIONS_CHANNEL, sessionId, create);
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=session-thread.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-thread.js","sourceRoot":"","sources":["../../src/lib/session-thread.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime context for the session
|
|
3
|
+
*/
|
|
4
|
+
export interface RuntimeContext {
|
|
5
|
+
/** Machine hostname */
|
|
6
|
+
hostname: string;
|
|
7
|
+
/** How the session is being run */
|
|
8
|
+
executionMode: "interactive" | "headless";
|
|
9
|
+
/** What triggered the session */
|
|
10
|
+
triggerType: "manual" | "cron" | "dm" | "channel";
|
|
11
|
+
/** Working directory for the session */
|
|
12
|
+
workingDir: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Metadata stored in session.md frontmatter
|
|
16
|
+
*/
|
|
17
|
+
export interface SessionMetadata {
|
|
18
|
+
/** Unique session ID (matches directory name) */
|
|
19
|
+
id: string;
|
|
20
|
+
/** When session started */
|
|
21
|
+
started: string;
|
|
22
|
+
/** When session ended (set on finalize) */
|
|
23
|
+
ended?: string;
|
|
24
|
+
/** What this session is trying to accomplish */
|
|
25
|
+
goal?: string;
|
|
26
|
+
/** Runtime context */
|
|
27
|
+
runtime: RuntimeContext;
|
|
28
|
+
/**
|
|
29
|
+
* Upstream return address - where to send completions/escalations
|
|
30
|
+
* Format: "@project:persona --session-id <id>" or "@persona" for local
|
|
31
|
+
* Examples:
|
|
32
|
+
* "@odin:dottie --session-id 2025-12-22T15-30-45"
|
|
33
|
+
* "@developer"
|
|
34
|
+
* null (for top-level interactive sessions)
|
|
35
|
+
*/
|
|
36
|
+
upstream?: string;
|
|
37
|
+
/** Persona info */
|
|
38
|
+
persona?: {
|
|
39
|
+
name: string;
|
|
40
|
+
inheritanceChain?: string[];
|
|
41
|
+
};
|
|
42
|
+
/** Workflow info (if running a workflow) */
|
|
43
|
+
workflow?: {
|
|
44
|
+
name: string;
|
|
45
|
+
path?: string;
|
|
46
|
+
inputs?: Record<string, unknown>;
|
|
47
|
+
};
|
|
48
|
+
/** Execution results (set on finalize) */
|
|
49
|
+
result?: {
|
|
50
|
+
success: boolean;
|
|
51
|
+
exitCode: number;
|
|
52
|
+
duration: number;
|
|
53
|
+
error?: string;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Info about a session for listing
|
|
58
|
+
*/
|
|
59
|
+
export interface SessionInfo {
|
|
60
|
+
/** Directory name (also the session ID) */
|
|
61
|
+
id: string;
|
|
62
|
+
/** Full path to session directory */
|
|
63
|
+
path: string;
|
|
64
|
+
/** When session started */
|
|
65
|
+
timestamp: Date;
|
|
66
|
+
/** Session metadata from frontmatter */
|
|
67
|
+
metadata?: SessionMetadata;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Options for creating a session
|
|
71
|
+
*/
|
|
72
|
+
export interface CreateSessionOptions {
|
|
73
|
+
/** Base sessions directory */
|
|
74
|
+
sessionsDir: string;
|
|
75
|
+
/** Runtime context */
|
|
76
|
+
runtime: RuntimeContext;
|
|
77
|
+
/** Upstream return address (e.g., "@odin:dottie --session-id abc123") */
|
|
78
|
+
upstream?: string;
|
|
79
|
+
/** Goal/description for this session */
|
|
80
|
+
goal?: string;
|
|
81
|
+
/** Persona info */
|
|
82
|
+
persona?: {
|
|
83
|
+
name: string;
|
|
84
|
+
inheritanceChain?: string[];
|
|
85
|
+
};
|
|
86
|
+
/** Workflow info */
|
|
87
|
+
workflow?: {
|
|
88
|
+
name: string;
|
|
89
|
+
path?: string;
|
|
90
|
+
inputs?: Record<string, unknown>;
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Active session handle
|
|
95
|
+
*/
|
|
96
|
+
export interface Session {
|
|
97
|
+
/** Session ID (directory name) */
|
|
98
|
+
id: string;
|
|
99
|
+
/** Full path to session directory */
|
|
100
|
+
path: string;
|
|
101
|
+
/** Path to session.md */
|
|
102
|
+
sessionFile: string;
|
|
103
|
+
/** Session metadata */
|
|
104
|
+
metadata: SessionMetadata;
|
|
105
|
+
/** Session content (body of session.md, without frontmatter) */
|
|
106
|
+
content?: string;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Generate session ID from timestamp
|
|
110
|
+
* Format: YYYY-MM-DDTHH-MM-SS (sortable, filesystem-safe)
|
|
111
|
+
*/
|
|
112
|
+
export declare function generateSessionId(date?: Date): string;
|
|
113
|
+
/**
|
|
114
|
+
* Parse session ID back to Date
|
|
115
|
+
*/
|
|
116
|
+
export declare function parseSessionId(id: string): Date | null;
|
|
117
|
+
/**
|
|
118
|
+
* Create a new session directory and initial session.md
|
|
119
|
+
*/
|
|
120
|
+
export declare function createSession(options: CreateSessionOptions): Promise<Session>;
|
|
121
|
+
/**
|
|
122
|
+
* Options for finalizing a session
|
|
123
|
+
*/
|
|
124
|
+
export interface FinalizeSessionOptions {
|
|
125
|
+
/** Whether execution succeeded */
|
|
126
|
+
success: boolean;
|
|
127
|
+
/** Exit code from process */
|
|
128
|
+
exitCode: number;
|
|
129
|
+
/** Duration in milliseconds */
|
|
130
|
+
duration: number;
|
|
131
|
+
/** Error message if failed */
|
|
132
|
+
error?: string;
|
|
133
|
+
/** Standard output to append to log */
|
|
134
|
+
stdout?: string;
|
|
135
|
+
/** Standard error to append to log */
|
|
136
|
+
stderr?: string;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Finalize a session with execution results
|
|
140
|
+
*/
|
|
141
|
+
export declare function finalizeSession(session: Session, options: FinalizeSessionOptions): Promise<void>;
|
|
142
|
+
/**
|
|
143
|
+
* Get recent sessions from sessions directory
|
|
144
|
+
*/
|
|
145
|
+
export declare function getRecentSessions(sessionsDir: string, limit?: number): Promise<SessionInfo[]>;
|
|
146
|
+
/**
|
|
147
|
+
* Read a session by ID
|
|
148
|
+
*/
|
|
149
|
+
export declare function readSession(sessionsDir: string, sessionId: string): Promise<Session | null>;
|
|
150
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/lib/session.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,uBAAuB;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,mCAAmC;IACnC,aAAa,EAAE,aAAa,GAAG,UAAU,CAAC;IAC1C,iCAAiC;IACjC,WAAW,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAClD,wCAAwC;IACxC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,iDAAiD;IACjD,EAAE,EAAE,MAAM,CAAC;IACX,2BAA2B;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gDAAgD;IAChD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sBAAsB;IACtB,OAAO,EAAE,cAAc,CAAC;IACxB;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB;IACnB,OAAO,CAAC,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;KAC7B,CAAC;IACF,4CAA4C;IAC5C,QAAQ,CAAC,EAAE;QACT,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAClC,CAAC;IACF,0CAA0C;IAC1C,MAAM,CAAC,EAAE;QACP,OAAO,EAAE,OAAO,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,2CAA2C;IAC3C,EAAE,EAAE,MAAM,CAAC;IACX,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,2BAA2B;IAC3B,SAAS,EAAE,IAAI,CAAC;IAChB,wCAAwC;IACxC,QAAQ,CAAC,EAAE,eAAe,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,8BAA8B;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,sBAAsB;IACtB,OAAO,EAAE,cAAc,CAAC;IACxB,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wCAAwC;IACxC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mBAAmB;IACnB,OAAO,CAAC,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;KAC7B,CAAC;IACF,oBAAoB;IACpB,QAAQ,CAAC,EAAE;QACT,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAClC,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,kCAAkC;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,yBAAyB;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,uBAAuB;IACvB,QAAQ,EAAE,eAAe,CAAC;IAC1B,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,GAAE,IAAiB,GAAG,MAAM,CAIjE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAYtD;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,OAAO,CAAC,CA0CnF;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,kCAAkC;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,6BAA6B;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,+BAA+B;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAqDf;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,WAAW,EAAE,MAAM,EACnB,KAAK,GAAE,MAAW,GACjB,OAAO,CAAC,WAAW,EAAE,CAAC,CAkDxB;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAkBzB"}
|