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.
- 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 +152 -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/daemon.d.ts +10 -3
- package/dist/daemon/daemon.d.ts.map +1 -1
- package/dist/daemon/daemon.js +19 -21
- 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/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/channel.test.d.ts +2 -0
- package/dist/lib/channel.test.d.ts.map +1 -0
- package/dist/lib/channel.test.js +33 -0
- package/dist/lib/channel.test.js.map +1 -0
- 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 +87 -0
- package/dist/lib/environment.d.ts.map +1 -0
- package/dist/lib/environment.js +224 -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/frontmatter.test.d.ts +2 -0
- package/dist/lib/frontmatter.test.d.ts.map +1 -0
- package/dist/lib/frontmatter.test.js +60 -0
- package/dist/lib/frontmatter.test.js.map +1 -0
- 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/integration.test.d.ts +2 -0
- package/dist/lib/integration.test.d.ts.map +1 -0
- package/dist/lib/integration.test.js +445 -0
- package/dist/lib/integration.test.js.map +1 -0
- package/dist/lib/invoke.d.ts +23 -0
- package/dist/lib/invoke.d.ts.map +1 -0
- package/dist/lib/invoke.js +158 -0
- package/dist/lib/invoke.js.map +1 -0
- package/dist/lib/invoke.test.d.ts +2 -0
- package/dist/lib/invoke.test.d.ts.map +1 -0
- package/dist/lib/invoke.test.js +82 -0
- package/dist/lib/invoke.test.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/persona.test.d.ts +2 -0
- package/dist/lib/persona.test.d.ts.map +1 -0
- package/dist/lib/persona.test.js +324 -0
- package/dist/lib/persona.test.js.map +1 -0
- package/dist/lib/processor.d.ts +50 -0
- package/dist/lib/processor.d.ts.map +1 -0
- package/dist/lib/processor.js +135 -0
- package/dist/lib/processor.js.map +1 -0
- package/dist/lib/processor.test.d.ts +2 -0
- package/dist/lib/processor.test.d.ts.map +1 -0
- package/dist/lib/processor.test.js +134 -0
- package/dist/lib/processor.test.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/registry.test.d.ts +2 -0
- package/dist/lib/registry.test.d.ts.map +1 -0
- package/dist/lib/registry.test.js +236 -0
- package/dist/lib/registry.test.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-thread.test.d.ts +2 -0
- package/dist/lib/session-thread.test.d.ts.map +1 -0
- package/dist/lib/session-thread.test.js +235 -0
- package/dist/lib/session-thread.test.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/session.test.d.ts +2 -0
- package/dist/lib/session.test.d.ts.map +1 -0
- package/dist/lib/session.test.js +336 -0
- package/dist/lib/session.test.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/internal/personas/_base/PERSONA.md +222 -39
- package/internal/skills/channels/list/SKILL.md +76 -0
- 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 @@
|
|
|
1
|
+
{"version":3,"file":"session-thread.test.d.ts","sourceRoot":"","sources":["../../src/lib/session-thread.test.ts"],"names":[],"mappings":""}
|