dot-agents 0.5.0 → 0.6.0

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 (124) 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 +152 -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/daemon.d.ts +10 -3
  31. package/dist/daemon/daemon.d.ts.map +1 -1
  32. package/dist/daemon/daemon.js +19 -21
  33. package/dist/daemon/daemon.js.map +1 -1
  34. package/dist/daemon/lib/executor.d.ts +0 -4
  35. package/dist/daemon/lib/executor.d.ts.map +1 -1
  36. package/dist/daemon/lib/executor.js +48 -135
  37. package/dist/daemon/lib/executor.js.map +1 -1
  38. package/dist/lib/channel.d.ts +53 -1
  39. package/dist/lib/channel.d.ts.map +1 -1
  40. package/dist/lib/channel.js +221 -30
  41. package/dist/lib/channel.js.map +1 -1
  42. package/dist/lib/channel.test.d.ts +2 -0
  43. package/dist/lib/channel.test.d.ts.map +1 -0
  44. package/dist/lib/channel.test.js +33 -0
  45. package/dist/lib/channel.test.js.map +1 -0
  46. package/dist/lib/daemon-status.d.ts +26 -0
  47. package/dist/lib/daemon-status.d.ts.map +1 -0
  48. package/dist/lib/daemon-status.js +64 -0
  49. package/dist/lib/daemon-status.js.map +1 -0
  50. package/dist/lib/environment.d.ts +87 -0
  51. package/dist/lib/environment.d.ts.map +1 -0
  52. package/dist/lib/environment.js +224 -0
  53. package/dist/lib/environment.js.map +1 -0
  54. package/dist/lib/frontmatter.d.ts +8 -0
  55. package/dist/lib/frontmatter.d.ts.map +1 -1
  56. package/dist/lib/frontmatter.js +16 -3
  57. package/dist/lib/frontmatter.js.map +1 -1
  58. package/dist/lib/frontmatter.test.d.ts +2 -0
  59. package/dist/lib/frontmatter.test.d.ts.map +1 -0
  60. package/dist/lib/frontmatter.test.js +60 -0
  61. package/dist/lib/frontmatter.test.js.map +1 -0
  62. package/dist/lib/index.d.ts +7 -0
  63. package/dist/lib/index.d.ts.map +1 -1
  64. package/dist/lib/index.js +7 -0
  65. package/dist/lib/index.js.map +1 -1
  66. package/dist/lib/integration.test.d.ts +2 -0
  67. package/dist/lib/integration.test.d.ts.map +1 -0
  68. package/dist/lib/integration.test.js +445 -0
  69. package/dist/lib/integration.test.js.map +1 -0
  70. package/dist/lib/invoke.d.ts +23 -0
  71. package/dist/lib/invoke.d.ts.map +1 -0
  72. package/dist/lib/invoke.js +158 -0
  73. package/dist/lib/invoke.js.map +1 -0
  74. package/dist/lib/invoke.test.d.ts +2 -0
  75. package/dist/lib/invoke.test.d.ts.map +1 -0
  76. package/dist/lib/invoke.test.js +82 -0
  77. package/dist/lib/invoke.test.js.map +1 -0
  78. package/dist/lib/persona.d.ts +22 -1
  79. package/dist/lib/persona.d.ts.map +1 -1
  80. package/dist/lib/persona.js +176 -31
  81. package/dist/lib/persona.js.map +1 -1
  82. package/dist/lib/persona.test.d.ts +2 -0
  83. package/dist/lib/persona.test.d.ts.map +1 -0
  84. package/dist/lib/persona.test.js +324 -0
  85. package/dist/lib/persona.test.js.map +1 -0
  86. package/dist/lib/processor.d.ts +50 -0
  87. package/dist/lib/processor.d.ts.map +1 -0
  88. package/dist/lib/processor.js +135 -0
  89. package/dist/lib/processor.js.map +1 -0
  90. package/dist/lib/processor.test.d.ts +2 -0
  91. package/dist/lib/processor.test.d.ts.map +1 -0
  92. package/dist/lib/processor.test.js +134 -0
  93. package/dist/lib/processor.test.js.map +1 -0
  94. package/dist/lib/registry.d.ts +109 -0
  95. package/dist/lib/registry.d.ts.map +1 -0
  96. package/dist/lib/registry.js +192 -0
  97. package/dist/lib/registry.js.map +1 -0
  98. package/dist/lib/registry.test.d.ts +2 -0
  99. package/dist/lib/registry.test.d.ts.map +1 -0
  100. package/dist/lib/registry.test.js +236 -0
  101. package/dist/lib/registry.test.js.map +1 -0
  102. package/dist/lib/session-thread.d.ts +75 -0
  103. package/dist/lib/session-thread.d.ts.map +1 -0
  104. package/dist/lib/session-thread.js +132 -0
  105. package/dist/lib/session-thread.js.map +1 -0
  106. package/dist/lib/session-thread.test.d.ts +2 -0
  107. package/dist/lib/session-thread.test.d.ts.map +1 -0
  108. package/dist/lib/session-thread.test.js +235 -0
  109. package/dist/lib/session-thread.test.js.map +1 -0
  110. package/dist/lib/session.d.ts +150 -0
  111. package/dist/lib/session.d.ts.map +1 -0
  112. package/dist/lib/session.js +183 -0
  113. package/dist/lib/session.js.map +1 -0
  114. package/dist/lib/session.test.d.ts +2 -0
  115. package/dist/lib/session.test.d.ts.map +1 -0
  116. package/dist/lib/session.test.js +336 -0
  117. package/dist/lib/session.test.js.map +1 -0
  118. package/dist/lib/types/channel.d.ts +4 -0
  119. package/dist/lib/types/channel.d.ts.map +1 -1
  120. package/dist/lib/types/persona.d.ts +49 -6
  121. package/dist/lib/types/persona.d.ts.map +1 -1
  122. package/internal/personas/_base/PERSONA.md +222 -39
  123. package/internal/skills/channels/list/SKILL.md +76 -0
  124. package/package.json +6 -2
@@ -0,0 +1,235 @@
1
+ import { describe, it, beforeEach, afterEach } from "node:test";
2
+ import assert from "node:assert";
3
+ import { mkdir, rm, readdir } from "node:fs/promises";
4
+ import { join } from "node:path";
5
+ import { tmpdir } from "node:os";
6
+ import { setTimeout } from "node:timers/promises";
7
+ import { startSession, updateSession, endSession, getSessionWorkspace, } from "./session-thread.js";
8
+ import { readChannel } from "./channel.js";
9
+ // Small delay to ensure unique timestamps for message IDs
10
+ const tick = () => setTimeout(10);
11
+ describe("session-thread", () => {
12
+ let testDir;
13
+ let channelsDir;
14
+ beforeEach(async () => {
15
+ // Create temp directory for tests
16
+ testDir = join(tmpdir(), `session-thread-test-${Date.now()}`);
17
+ channelsDir = join(testDir, "channels");
18
+ await mkdir(channelsDir, { recursive: true });
19
+ });
20
+ afterEach(async () => {
21
+ // Clean up temp directory
22
+ await rm(testDir, { recursive: true, force: true });
23
+ });
24
+ describe("startSession", () => {
25
+ it("creates a session thread in #sessions", async () => {
26
+ const session = await startSession({
27
+ channelsDir,
28
+ persona: "test-persona",
29
+ mode: "interactive",
30
+ trigger: "manual",
31
+ });
32
+ // Session ID should be an ISO timestamp
33
+ assert.ok(session.id.match(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/));
34
+ // Workspace should exist
35
+ assert.ok(session.workspacePath.includes("workspace"));
36
+ // Check that #sessions channel was created with the thread
37
+ const sessionsDir = join(channelsDir, "#sessions");
38
+ const entries = await readdir(sessionsDir);
39
+ assert.ok(entries.includes(session.id));
40
+ });
41
+ it("includes goal in session message when provided", async () => {
42
+ const session = await startSession({
43
+ channelsDir,
44
+ persona: "test-persona",
45
+ mode: "headless",
46
+ trigger: "cron",
47
+ goal: "Test goal description",
48
+ });
49
+ // Read the message content
50
+ const messages = await readChannel(channelsDir, "#sessions");
51
+ assert.strictEqual(messages.length, 1);
52
+ assert.ok(messages[0].content.includes("Test goal description"));
53
+ assert.ok(messages[0].content.includes("headless"));
54
+ assert.ok(messages[0].content.includes("cron"));
55
+ });
56
+ it("includes upstream in session message when provided", async () => {
57
+ const session = await startSession({
58
+ channelsDir,
59
+ persona: "test-persona",
60
+ mode: "interactive",
61
+ trigger: "dm",
62
+ upstream: "@other-project#sessions --thread abc123",
63
+ });
64
+ const messages = await readChannel(channelsDir, "#sessions");
65
+ assert.ok(messages[0].content.includes("@other-project#sessions"));
66
+ });
67
+ it("creates workspace directory", async () => {
68
+ const session = await startSession({
69
+ channelsDir,
70
+ persona: "test-persona",
71
+ mode: "interactive",
72
+ trigger: "manual",
73
+ });
74
+ const workspaceEntries = await readdir(session.workspacePath).catch(() => null);
75
+ assert.ok(workspaceEntries !== null, "Workspace directory should exist");
76
+ });
77
+ });
78
+ describe("updateSession", () => {
79
+ it("adds a reply to the session thread", async () => {
80
+ const session = await startSession({
81
+ channelsDir,
82
+ persona: "test-persona",
83
+ mode: "interactive",
84
+ trigger: "manual",
85
+ });
86
+ await tick(); // Ensure reply gets unique timestamp from session start
87
+ await updateSession(session, "First update");
88
+ await tick();
89
+ await updateSession(session, "Second update");
90
+ const messages = await readChannel(channelsDir, "#sessions");
91
+ assert.strictEqual(messages.length, 1);
92
+ assert.strictEqual(messages[0].replies?.length, 2);
93
+ });
94
+ it("works with session ID string instead of session object", async () => {
95
+ const session = await startSession({
96
+ channelsDir,
97
+ persona: "test-persona",
98
+ mode: "interactive",
99
+ trigger: "manual",
100
+ });
101
+ await tick(); // Ensure reply gets unique timestamp from session start
102
+ await updateSession(session.id, channelsDir, "Update via ID");
103
+ const messages = await readChannel(channelsDir, "#sessions");
104
+ assert.strictEqual(messages[0].replies?.length, 1);
105
+ assert.ok(messages[0].replies?.[0].content.includes("Update via ID"));
106
+ });
107
+ });
108
+ describe("endSession", () => {
109
+ it("posts a completion message to the thread", async () => {
110
+ const session = await startSession({
111
+ channelsDir,
112
+ persona: "test-persona",
113
+ mode: "headless",
114
+ trigger: "manual",
115
+ });
116
+ await tick();
117
+ await endSession(session, {
118
+ success: true,
119
+ exitCode: 0,
120
+ duration: 5000,
121
+ });
122
+ const messages = await readChannel(channelsDir, "#sessions");
123
+ assert.strictEqual(messages[0].replies?.length, 1);
124
+ const endMessage = messages[0].replies?.[0].content;
125
+ assert.ok(endMessage?.includes("Session Ended"));
126
+ assert.ok(endMessage?.includes("Success:** ✓"));
127
+ assert.ok(endMessage?.includes("Exit Code:** 0"));
128
+ assert.ok(endMessage?.includes("5.0s"));
129
+ });
130
+ it("includes error message when session failed", async () => {
131
+ const session = await startSession({
132
+ channelsDir,
133
+ persona: "test-persona",
134
+ mode: "headless",
135
+ trigger: "manual",
136
+ });
137
+ await tick();
138
+ await endSession(session, {
139
+ success: false,
140
+ exitCode: 1,
141
+ duration: 1234,
142
+ error: "Something went wrong",
143
+ });
144
+ const messages = await readChannel(channelsDir, "#sessions");
145
+ const endMessage = messages[0].replies?.[0].content;
146
+ assert.ok(endMessage?.includes("Success:** ✗"));
147
+ assert.ok(endMessage?.includes("Something went wrong"));
148
+ });
149
+ it("formats duration correctly for various lengths", async () => {
150
+ // Test milliseconds
151
+ let session = await startSession({
152
+ channelsDir,
153
+ persona: "test",
154
+ mode: "headless",
155
+ trigger: "manual",
156
+ });
157
+ await tick();
158
+ await endSession(session, { success: true, exitCode: 0, duration: 500 });
159
+ let messages = await readChannel(channelsDir, "#sessions");
160
+ assert.ok(messages[0].replies?.[0].content.includes("500ms"));
161
+ // Test minutes
162
+ await tick();
163
+ session = await startSession({
164
+ channelsDir,
165
+ persona: "test",
166
+ mode: "headless",
167
+ trigger: "manual",
168
+ });
169
+ await tick();
170
+ await endSession(session, { success: true, exitCode: 0, duration: 125000 });
171
+ messages = await readChannel(channelsDir, "#sessions");
172
+ assert.ok(messages[0].replies?.[0].content.includes("2m 5s"));
173
+ // Test hours
174
+ await tick();
175
+ session = await startSession({
176
+ channelsDir,
177
+ persona: "test",
178
+ mode: "headless",
179
+ trigger: "manual",
180
+ });
181
+ await tick();
182
+ await endSession(session, { success: true, exitCode: 0, duration: 3720000 });
183
+ messages = await readChannel(channelsDir, "#sessions");
184
+ assert.ok(messages[0].replies?.[0].content.includes("1h 2m"));
185
+ });
186
+ });
187
+ describe("getSessionWorkspace", () => {
188
+ it("returns workspace path for existing session", async () => {
189
+ const session = await startSession({
190
+ channelsDir,
191
+ persona: "test-persona",
192
+ mode: "interactive",
193
+ trigger: "manual",
194
+ });
195
+ const workspace = await getSessionWorkspace(channelsDir, session.id);
196
+ assert.strictEqual(workspace, session.workspacePath);
197
+ });
198
+ it("returns null for non-existent session", async () => {
199
+ const workspace = await getSessionWorkspace(channelsDir, "non-existent-id");
200
+ assert.strictEqual(workspace, null);
201
+ });
202
+ it("creates workspace when create=true", async () => {
203
+ const session = await startSession({
204
+ channelsDir,
205
+ persona: "test-persona",
206
+ mode: "interactive",
207
+ trigger: "manual",
208
+ });
209
+ // Remove workspace to test creation
210
+ await rm(session.workspacePath, { recursive: true });
211
+ const workspace = await getSessionWorkspace(channelsDir, session.id, true);
212
+ assert.ok(workspace !== null);
213
+ const entries = await readdir(workspace).catch(() => null);
214
+ assert.ok(entries !== null);
215
+ });
216
+ });
217
+ describe("thread message structure", () => {
218
+ it("uses uniform timestamp naming for messages", async () => {
219
+ const session = await startSession({
220
+ channelsDir,
221
+ persona: "test-persona",
222
+ mode: "interactive",
223
+ trigger: "manual",
224
+ });
225
+ const threadDir = join(channelsDir, "#sessions", session.id);
226
+ const entries = await readdir(threadDir);
227
+ // Should have: <timestamp>.md (initial), workspace/
228
+ const mdFiles = entries.filter(e => e.endsWith(".md"));
229
+ assert.strictEqual(mdFiles.length, 1);
230
+ // The .md file should be named with the session ID (thread ID)
231
+ assert.ok(mdFiles[0] === `${session.id}.md`);
232
+ });
233
+ });
234
+ });
235
+ //# sourceMappingURL=session-thread.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-thread.test.js","sourceRoot":"","sources":["../../src/lib/session-thread.test.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":"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"}
@@ -0,0 +1,183 @@
1
+ import { mkdir, writeFile, readFile, readdir, stat } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { parseFrontmatter, stringifyFrontmatter } from "./frontmatter.js";
4
+ /**
5
+ * Generate session ID from timestamp
6
+ * Format: YYYY-MM-DDTHH-MM-SS (sortable, filesystem-safe)
7
+ */
8
+ export function generateSessionId(date = new Date()) {
9
+ return date.toISOString()
10
+ .replace(/:/g, "-")
11
+ .split(".")[0]; // e.g., "2025-12-22T15-30-45"
12
+ }
13
+ /**
14
+ * Parse session ID back to Date
15
+ */
16
+ export function parseSessionId(id) {
17
+ // Match YYYY-MM-DDTHH-MM-SS format
18
+ const match = id.match(/^(\d{4}-\d{2}-\d{2})T(\d{2})-(\d{2})-(\d{2})$/);
19
+ if (!match) {
20
+ return null;
21
+ }
22
+ // Convert back to ISO format with Z suffix for UTC
23
+ const [, datePart, hour, minute, second] = match;
24
+ const isoString = `${datePart}T${hour}:${minute}:${second}Z`;
25
+ const date = new Date(isoString);
26
+ return isNaN(date.getTime()) ? null : date;
27
+ }
28
+ /**
29
+ * Create a new session directory and initial session.md
30
+ */
31
+ export async function createSession(options) {
32
+ const startTime = new Date();
33
+ const id = generateSessionId(startTime);
34
+ const sessionPath = join(options.sessionsDir, id);
35
+ const sessionFile = join(sessionPath, "session.md");
36
+ // Create session directory
37
+ await mkdir(sessionPath, { recursive: true });
38
+ // Build metadata
39
+ const metadata = {
40
+ id,
41
+ started: startTime.toISOString(),
42
+ runtime: options.runtime,
43
+ };
44
+ if (options.upstream) {
45
+ metadata.upstream = options.upstream;
46
+ }
47
+ if (options.goal) {
48
+ metadata.goal = options.goal;
49
+ }
50
+ if (options.persona) {
51
+ metadata.persona = options.persona;
52
+ }
53
+ if (options.workflow) {
54
+ metadata.workflow = options.workflow;
55
+ }
56
+ // Write initial session.md
57
+ const content = stringifyFrontmatter(metadata, "# Session Log\n\nSession started.\n");
58
+ await writeFile(sessionFile, content, "utf-8");
59
+ return {
60
+ id,
61
+ path: sessionPath,
62
+ sessionFile,
63
+ metadata,
64
+ };
65
+ }
66
+ /**
67
+ * Finalize a session with execution results
68
+ */
69
+ export async function finalizeSession(session, options) {
70
+ const endTime = new Date();
71
+ // Read current session.md
72
+ const currentContent = await readFile(session.sessionFile, "utf-8");
73
+ const { frontmatter, body } = parseFrontmatter(currentContent);
74
+ // Update metadata
75
+ frontmatter.ended = endTime.toISOString();
76
+ frontmatter.result = {
77
+ success: options.success,
78
+ exitCode: options.exitCode,
79
+ duration: options.duration,
80
+ error: options.error,
81
+ };
82
+ // Build updated content
83
+ const logParts = [body.trim()];
84
+ logParts.push("");
85
+ logParts.push(`## Execution Complete`);
86
+ logParts.push("");
87
+ logParts.push(`- **Ended:** ${endTime.toISOString()}`);
88
+ logParts.push(`- **Duration:** ${options.duration}ms`);
89
+ logParts.push(`- **Exit Code:** ${options.exitCode}`);
90
+ logParts.push(`- **Success:** ${options.success}`);
91
+ if (options.error) {
92
+ logParts.push(`- **Error:** ${options.error}`);
93
+ }
94
+ if (options.stdout) {
95
+ logParts.push("");
96
+ logParts.push("### Output");
97
+ logParts.push("");
98
+ logParts.push("```");
99
+ logParts.push(options.stdout);
100
+ logParts.push("```");
101
+ }
102
+ if (options.stderr) {
103
+ logParts.push("");
104
+ logParts.push("### Errors");
105
+ logParts.push("");
106
+ logParts.push("```");
107
+ logParts.push(options.stderr);
108
+ logParts.push("```");
109
+ }
110
+ logParts.push("");
111
+ // Write updated session.md
112
+ const updatedContent = stringifyFrontmatter(frontmatter, logParts.join("\n"));
113
+ await writeFile(session.sessionFile, updatedContent, "utf-8");
114
+ }
115
+ /**
116
+ * Get recent sessions from sessions directory
117
+ */
118
+ export async function getRecentSessions(sessionsDir, limit = 20) {
119
+ const sessions = [];
120
+ try {
121
+ const entries = await readdir(sessionsDir);
122
+ // Filter to directories that match session ID pattern
123
+ const sessionDirs = [];
124
+ for (const entry of entries) {
125
+ const entryPath = join(sessionsDir, entry);
126
+ const stats = await stat(entryPath);
127
+ if (stats.isDirectory()) {
128
+ const date = parseSessionId(entry);
129
+ if (date) {
130
+ sessionDirs.push({ name: entry, date });
131
+ }
132
+ }
133
+ }
134
+ // Sort by date, newest first
135
+ sessionDirs.sort((a, b) => b.date.getTime() - a.date.getTime());
136
+ // Take top N
137
+ for (const { name, date } of sessionDirs.slice(0, limit)) {
138
+ const sessionPath = join(sessionsDir, name);
139
+ const sessionFile = join(sessionPath, "session.md");
140
+ const info = {
141
+ id: name,
142
+ path: sessionPath,
143
+ timestamp: date,
144
+ };
145
+ // Try to read metadata
146
+ try {
147
+ const content = await readFile(sessionFile, "utf-8");
148
+ const { frontmatter } = parseFrontmatter(content);
149
+ info.metadata = frontmatter;
150
+ }
151
+ catch {
152
+ // Session.md might not exist or be invalid
153
+ }
154
+ sessions.push(info);
155
+ }
156
+ }
157
+ catch {
158
+ // Sessions directory might not exist yet
159
+ }
160
+ return sessions;
161
+ }
162
+ /**
163
+ * Read a session by ID
164
+ */
165
+ export async function readSession(sessionsDir, sessionId) {
166
+ const sessionPath = join(sessionsDir, sessionId);
167
+ const sessionFile = join(sessionPath, "session.md");
168
+ try {
169
+ const rawContent = await readFile(sessionFile, "utf-8");
170
+ const { frontmatter, body } = parseFrontmatter(rawContent);
171
+ return {
172
+ id: sessionId,
173
+ path: sessionPath,
174
+ sessionFile,
175
+ metadata: frontmatter,
176
+ content: body.trim() || undefined,
177
+ };
178
+ }
179
+ catch {
180
+ return null;
181
+ }
182
+ }
183
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/lib/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=session.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.test.d.ts","sourceRoot":"","sources":["../../src/lib/session.test.ts"],"names":[],"mappings":""}