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.
Files changed (112) hide show
  1. package/README.md +239 -122
  2. package/dist/cli/commands/channel.d.ts +19 -0
  3. package/dist/cli/commands/channel.d.ts.map +1 -1
  4. package/dist/cli/commands/channel.js +220 -13
  5. package/dist/cli/commands/channel.js.map +1 -1
  6. package/dist/cli/commands/check.d.ts.map +1 -1
  7. package/dist/cli/commands/check.js +61 -1
  8. package/dist/cli/commands/check.js.map +1 -1
  9. package/dist/cli/commands/index.d.ts +2 -0
  10. package/dist/cli/commands/index.d.ts.map +1 -1
  11. package/dist/cli/commands/index.js +2 -0
  12. package/dist/cli/commands/index.js.map +1 -1
  13. package/dist/cli/commands/personas.d.ts +3 -0
  14. package/dist/cli/commands/personas.d.ts.map +1 -0
  15. package/dist/cli/commands/personas.js +402 -0
  16. package/dist/cli/commands/personas.js.map +1 -0
  17. package/dist/cli/commands/projects.d.ts +3 -0
  18. package/dist/cli/commands/projects.d.ts.map +1 -0
  19. package/dist/cli/commands/projects.js +138 -0
  20. package/dist/cli/commands/projects.js.map +1 -0
  21. package/dist/cli/commands/run.d.ts.map +1 -1
  22. package/dist/cli/commands/run.js +4 -5
  23. package/dist/cli/commands/run.js.map +1 -1
  24. package/dist/cli/index.js +3 -11
  25. package/dist/cli/index.js.map +1 -1
  26. package/dist/cli/lib/runner.d.ts +2 -0
  27. package/dist/cli/lib/runner.d.ts.map +1 -1
  28. package/dist/cli/lib/runner.js +67 -8
  29. package/dist/cli/lib/runner.js.map +1 -1
  30. package/dist/daemon/api/channels.d.ts +6 -0
  31. package/dist/daemon/api/channels.d.ts.map +1 -0
  32. package/dist/daemon/api/channels.js +143 -0
  33. package/dist/daemon/api/channels.js.map +1 -0
  34. package/dist/daemon/api/server.d.ts.map +1 -1
  35. package/dist/daemon/api/server.js +56 -0
  36. package/dist/daemon/api/server.js.map +1 -1
  37. package/dist/daemon/daemon.d.ts +28 -3
  38. package/dist/daemon/daemon.d.ts.map +1 -1
  39. package/dist/daemon/daemon.js +142 -26
  40. package/dist/daemon/daemon.js.map +1 -1
  41. package/dist/daemon/lib/executor.d.ts +0 -4
  42. package/dist/daemon/lib/executor.d.ts.map +1 -1
  43. package/dist/daemon/lib/executor.js +48 -135
  44. package/dist/daemon/lib/executor.js.map +1 -1
  45. package/dist/daemon/lib/index.d.ts +1 -0
  46. package/dist/daemon/lib/index.d.ts.map +1 -1
  47. package/dist/daemon/lib/index.js +1 -0
  48. package/dist/daemon/lib/index.js.map +1 -1
  49. package/dist/daemon/lib/safeguards.d.ts +68 -0
  50. package/dist/daemon/lib/safeguards.d.ts.map +1 -0
  51. package/dist/daemon/lib/safeguards.js +135 -0
  52. package/dist/daemon/lib/safeguards.js.map +1 -0
  53. package/dist/daemon/lib/watcher.d.ts.map +1 -1
  54. package/dist/daemon/lib/watcher.js +48 -8
  55. package/dist/daemon/lib/watcher.js.map +1 -1
  56. package/dist/daemon/web/app.js +433 -0
  57. package/dist/daemon/web/index.html +68 -0
  58. package/dist/daemon/web/styles.css +452 -0
  59. package/dist/lib/channel.d.ts +53 -1
  60. package/dist/lib/channel.d.ts.map +1 -1
  61. package/dist/lib/channel.js +221 -30
  62. package/dist/lib/channel.js.map +1 -1
  63. package/dist/lib/daemon-status.d.ts +26 -0
  64. package/dist/lib/daemon-status.d.ts.map +1 -0
  65. package/dist/lib/daemon-status.js +64 -0
  66. package/dist/lib/daemon-status.js.map +1 -0
  67. package/dist/lib/environment.d.ts +88 -0
  68. package/dist/lib/environment.d.ts.map +1 -0
  69. package/dist/lib/environment.js +238 -0
  70. package/dist/lib/environment.js.map +1 -0
  71. package/dist/lib/frontmatter.d.ts +8 -0
  72. package/dist/lib/frontmatter.d.ts.map +1 -1
  73. package/dist/lib/frontmatter.js +16 -3
  74. package/dist/lib/frontmatter.js.map +1 -1
  75. package/dist/lib/index.d.ts +7 -0
  76. package/dist/lib/index.d.ts.map +1 -1
  77. package/dist/lib/index.js +7 -0
  78. package/dist/lib/index.js.map +1 -1
  79. package/dist/lib/invoke.d.ts +31 -0
  80. package/dist/lib/invoke.d.ts.map +1 -0
  81. package/dist/lib/invoke.js +170 -0
  82. package/dist/lib/invoke.js.map +1 -0
  83. package/dist/lib/persona.d.ts +22 -1
  84. package/dist/lib/persona.d.ts.map +1 -1
  85. package/dist/lib/persona.js +176 -31
  86. package/dist/lib/persona.js.map +1 -1
  87. package/dist/lib/processor.d.ts +58 -0
  88. package/dist/lib/processor.d.ts.map +1 -0
  89. package/dist/lib/processor.js +149 -0
  90. package/dist/lib/processor.js.map +1 -0
  91. package/dist/lib/registry.d.ts +109 -0
  92. package/dist/lib/registry.d.ts.map +1 -0
  93. package/dist/lib/registry.js +192 -0
  94. package/dist/lib/registry.js.map +1 -0
  95. package/dist/lib/session-thread.d.ts +75 -0
  96. package/dist/lib/session-thread.d.ts.map +1 -0
  97. package/dist/lib/session-thread.js +132 -0
  98. package/dist/lib/session-thread.js.map +1 -0
  99. package/dist/lib/session.d.ts +150 -0
  100. package/dist/lib/session.d.ts.map +1 -0
  101. package/dist/lib/session.js +183 -0
  102. package/dist/lib/session.js.map +1 -0
  103. package/dist/lib/types/channel.d.ts +4 -0
  104. package/dist/lib/types/channel.d.ts.map +1 -1
  105. package/dist/lib/types/persona.d.ts +49 -6
  106. package/dist/lib/types/persona.d.ts.map +1 -1
  107. package/dist/lib/validation/persona.d.ts.map +1 -1
  108. package/dist/lib/validation/persona.js +41 -4
  109. package/dist/lib/validation/persona.js.map +1 -1
  110. package/internal/personas/_base/PERSONA.md +222 -39
  111. package/internal/skills/channels/list/SKILL.md +76 -0
  112. 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"}