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,236 @@
1
+ import { describe, it } from "node:test";
2
+ import assert from "node:assert";
3
+ function parseChannelAddress(address) {
4
+ if (!address.startsWith("#") && !address.startsWith("@")) {
5
+ throw new Error(`Invalid channel address: ${address}. Must start with # or @`);
6
+ }
7
+ const type = address[0];
8
+ const rest = address.slice(1);
9
+ // Check for project/name format
10
+ const slashIndex = rest.indexOf("/");
11
+ if (slashIndex > 0) {
12
+ const project = rest.slice(0, slashIndex);
13
+ const name = rest.slice(slashIndex + 1);
14
+ if (!name) {
15
+ throw new Error(`Invalid channel address: ${address}. Missing channel/persona name after project.`);
16
+ }
17
+ return { project, type, name, original: address };
18
+ }
19
+ // Local channel
20
+ return { project: null, type, name: rest, original: address };
21
+ }
22
+ // Inline detectNameCollisions logic for testing
23
+ function detectNameCollisions(personaNames, projectRegistry) {
24
+ const collisions = [];
25
+ for (const [projectName, projectPath] of Object.entries(projectRegistry)) {
26
+ for (const personaName of personaNames) {
27
+ if (personaName === projectName) {
28
+ collisions.push({
29
+ name: projectName,
30
+ projectPath: projectPath,
31
+ personaPath: personaName,
32
+ });
33
+ }
34
+ }
35
+ }
36
+ return collisions;
37
+ }
38
+ describe("parseChannelAddress", () => {
39
+ describe("local channels", () => {
40
+ it("parses local DM address (@persona)", () => {
41
+ const result = parseChannelAddress("@developer");
42
+ assert.strictEqual(result.project, null);
43
+ assert.strictEqual(result.type, "@");
44
+ assert.strictEqual(result.name, "developer");
45
+ assert.strictEqual(result.original, "@developer");
46
+ });
47
+ it("parses local public channel (#channel)", () => {
48
+ const result = parseChannelAddress("#status");
49
+ assert.strictEqual(result.project, null);
50
+ assert.strictEqual(result.type, "#");
51
+ assert.strictEqual(result.name, "status");
52
+ assert.strictEqual(result.original, "#status");
53
+ });
54
+ it("handles hyphenated names", () => {
55
+ const result = parseChannelAddress("@my-persona");
56
+ assert.strictEqual(result.project, null);
57
+ assert.strictEqual(result.name, "my-persona");
58
+ });
59
+ });
60
+ describe("cross-project channels", () => {
61
+ it("parses cross-project DM address (@project/persona)", () => {
62
+ const result = parseChannelAddress("@documents/dottie");
63
+ assert.strictEqual(result.project, "documents");
64
+ assert.strictEqual(result.type, "@");
65
+ assert.strictEqual(result.name, "dottie");
66
+ assert.strictEqual(result.original, "@documents/dottie");
67
+ });
68
+ it("parses cross-project public channel (#project/channel)", () => {
69
+ const result = parseChannelAddress("#scoutos/status");
70
+ assert.strictEqual(result.project, "scoutos");
71
+ assert.strictEqual(result.type, "#");
72
+ assert.strictEqual(result.name, "status");
73
+ assert.strictEqual(result.original, "#scoutos/status");
74
+ });
75
+ it("handles hyphenated project names", () => {
76
+ const result = parseChannelAddress("@dot-agents/developer");
77
+ assert.strictEqual(result.project, "dot-agents");
78
+ assert.strictEqual(result.name, "developer");
79
+ });
80
+ it("handles nested path-like names in persona", () => {
81
+ const result = parseChannelAddress("@documents/claude/developer");
82
+ assert.strictEqual(result.project, "documents");
83
+ assert.strictEqual(result.name, "claude/developer");
84
+ });
85
+ });
86
+ describe("error handling", () => {
87
+ it("throws for addresses without prefix", () => {
88
+ assert.throws(() => parseChannelAddress("documents/dottie"), /Invalid channel address/);
89
+ });
90
+ it("throws for addresses with missing name after project", () => {
91
+ assert.throws(() => parseChannelAddress("@documents/"), /Missing channel\/persona name/);
92
+ });
93
+ it("throws for empty address", () => {
94
+ assert.throws(() => parseChannelAddress(""), /Invalid channel address/);
95
+ });
96
+ });
97
+ });
98
+ describe("detectNameCollisions", () => {
99
+ it("detects collision when persona name matches project name", () => {
100
+ const personaNames = ["developer", "documents", "reviewer"];
101
+ const registry = {
102
+ documents: "/path/to/documents",
103
+ scoutos: "/path/to/scoutos",
104
+ };
105
+ const collisions = detectNameCollisions(personaNames, registry);
106
+ assert.strictEqual(collisions.length, 1);
107
+ assert.strictEqual(collisions[0].name, "documents");
108
+ assert.strictEqual(collisions[0].projectPath, "/path/to/documents");
109
+ assert.strictEqual(collisions[0].personaPath, "documents");
110
+ });
111
+ it("returns empty array when no collisions", () => {
112
+ const personaNames = ["developer", "reviewer"];
113
+ const registry = {
114
+ documents: "/path/to/documents",
115
+ scoutos: "/path/to/scoutos",
116
+ };
117
+ const collisions = detectNameCollisions(personaNames, registry);
118
+ assert.strictEqual(collisions.length, 0);
119
+ });
120
+ it("detects multiple collisions", () => {
121
+ const personaNames = ["developer", "documents", "scoutos"];
122
+ const registry = {
123
+ documents: "/path/to/documents",
124
+ scoutos: "/path/to/scoutos",
125
+ };
126
+ const collisions = detectNameCollisions(personaNames, registry);
127
+ assert.strictEqual(collisions.length, 2);
128
+ const names = collisions.map((c) => c.name).sort();
129
+ assert.deepStrictEqual(names, ["documents", "scoutos"]);
130
+ });
131
+ it("handles empty inputs", () => {
132
+ assert.strictEqual(detectNameCollisions([], {}).length, 0);
133
+ assert.strictEqual(detectNameCollisions(["dev"], {}).length, 0);
134
+ assert.strictEqual(detectNameCollisions([], { proj: "/path" }).length, 0);
135
+ });
136
+ });
137
+ function resolveChannelAddressSync(address, localChannelsDir, projectRegistry) {
138
+ const parsed = parseChannelAddress(address);
139
+ if (parsed.project === null) {
140
+ // Check if @name matches a registered project (unified resolution)
141
+ if (parsed.type === "@") {
142
+ const projectPath = projectRegistry[parsed.name];
143
+ if (projectPath) {
144
+ // Route to project's entry point (@root)
145
+ return {
146
+ channelsDir: `${projectPath}/channels`,
147
+ localChannelName: "@root",
148
+ isProjectEntryPoint: true,
149
+ projectName: parsed.name,
150
+ };
151
+ }
152
+ }
153
+ // Local channel (no project match or public channel)
154
+ return {
155
+ channelsDir: localChannelsDir,
156
+ localChannelName: address,
157
+ };
158
+ }
159
+ // Cross-project channel with explicit project/name format
160
+ const projectPath = projectRegistry[parsed.project];
161
+ if (!projectPath) {
162
+ throw new Error(`Unknown project: ${parsed.project}. Register it with: npx dot-agents projects add ${parsed.project} /path/to/project`);
163
+ }
164
+ return {
165
+ channelsDir: `${projectPath}/channels`,
166
+ localChannelName: `${parsed.type}${parsed.name}`,
167
+ projectName: parsed.project,
168
+ };
169
+ }
170
+ describe("resolveChannelAddress cross-project routing", () => {
171
+ const localChannelsDir = "/current-project/.agents/channels";
172
+ const projectRegistry = {
173
+ documents: "/home/user/documents/.agents",
174
+ scoutos: "/home/user/scoutos/.agents",
175
+ };
176
+ describe("@project routes to @root", () => {
177
+ it("@documents routes to documents project's @root channel", () => {
178
+ const result = resolveChannelAddressSync("@documents", localChannelsDir, projectRegistry);
179
+ assert.strictEqual(result.channelsDir, "/home/user/documents/.agents/channels");
180
+ assert.strictEqual(result.localChannelName, "@root");
181
+ assert.strictEqual(result.isProjectEntryPoint, true);
182
+ assert.strictEqual(result.projectName, "documents");
183
+ });
184
+ it("@scoutos routes to scoutos project's @root channel", () => {
185
+ const result = resolveChannelAddressSync("@scoutos", localChannelsDir, projectRegistry);
186
+ assert.strictEqual(result.channelsDir, "/home/user/scoutos/.agents/channels");
187
+ assert.strictEqual(result.localChannelName, "@root");
188
+ assert.strictEqual(result.isProjectEntryPoint, true);
189
+ assert.strictEqual(result.projectName, "scoutos");
190
+ });
191
+ });
192
+ describe("@project/persona routes to specific persona", () => {
193
+ it("@documents/dottie routes to documents project's @dottie channel", () => {
194
+ const result = resolveChannelAddressSync("@documents/dottie", localChannelsDir, projectRegistry);
195
+ assert.strictEqual(result.channelsDir, "/home/user/documents/.agents/channels");
196
+ assert.strictEqual(result.localChannelName, "@dottie");
197
+ assert.strictEqual(result.projectName, "documents");
198
+ // Not marked as entry point since it's a specific persona
199
+ assert.strictEqual(result.isProjectEntryPoint, undefined);
200
+ });
201
+ });
202
+ describe("local personas without project match", () => {
203
+ it("@developer stays local when no project named 'developer'", () => {
204
+ const result = resolveChannelAddressSync("@developer", localChannelsDir, projectRegistry);
205
+ assert.strictEqual(result.channelsDir, localChannelsDir);
206
+ assert.strictEqual(result.localChannelName, "@developer");
207
+ assert.strictEqual(result.isProjectEntryPoint, undefined);
208
+ assert.strictEqual(result.projectName, undefined);
209
+ });
210
+ it("@reviewer stays local when no project named 'reviewer'", () => {
211
+ const result = resolveChannelAddressSync("@reviewer", localChannelsDir, projectRegistry);
212
+ assert.strictEqual(result.channelsDir, localChannelsDir);
213
+ assert.strictEqual(result.localChannelName, "@reviewer");
214
+ });
215
+ });
216
+ describe("public channels", () => {
217
+ it("#status stays local (no project routing for public channels)", () => {
218
+ const result = resolveChannelAddressSync("#status", localChannelsDir, projectRegistry);
219
+ assert.strictEqual(result.channelsDir, localChannelsDir);
220
+ assert.strictEqual(result.localChannelName, "#status");
221
+ });
222
+ it("#documents stays local (public channels don't match project names)", () => {
223
+ // Even though 'documents' is a project name, #documents is a public channel
224
+ // and doesn't get routed to the project
225
+ const result = resolveChannelAddressSync("#documents", localChannelsDir, projectRegistry);
226
+ assert.strictEqual(result.channelsDir, localChannelsDir);
227
+ assert.strictEqual(result.localChannelName, "#documents");
228
+ });
229
+ });
230
+ describe("error handling", () => {
231
+ it("throws for unknown project in explicit format", () => {
232
+ assert.throws(() => resolveChannelAddressSync("@unknown-project/persona", localChannelsDir, projectRegistry), /Unknown project: unknown-project/);
233
+ });
234
+ });
235
+ });
236
+ //# sourceMappingURL=registry.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.test.js","sourceRoot":"","sources":["../../src/lib/registry.test.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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=session-thread.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-thread.test.d.ts","sourceRoot":"","sources":["../../src/lib/session-thread.test.ts"],"names":[],"mappings":""}