letagents 0.12.9 → 0.12.10
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 +16 -15
- package/dist/mcp/agent-prompt-delivery.js +20 -0
- package/dist/mcp/codex-session/app-server.js +89 -0
- package/dist/mcp/codex-session/index.js +10 -0
- package/dist/mcp/codex-session/rpc-client.js +85 -0
- package/dist/mcp/codex-session/runtime-bridge.js +254 -0
- package/dist/mcp/codex-session/runtime-summary.js +220 -0
- package/dist/mcp/codex-session/session-inspection.js +100 -0
- package/dist/mcp/codex-session/session-mapper.js +51 -0
- package/dist/mcp/codex-session/session-start.js +182 -0
- package/dist/mcp/codex-session/session-status.js +77 -0
- package/dist/mcp/codex-session/session-stop.js +43 -0
- package/dist/mcp/codex-session/session-supervisor.js +111 -0
- package/dist/mcp/codex-session/start-prompt.js +49 -0
- package/dist/mcp/codex-session/types.js +1 -0
- package/dist/mcp/codex-session.js +1 -672
- package/dist/mcp/config-reader.js +10 -2
- package/dist/mcp/git-remote.js +90 -14
- package/dist/mcp/local-state/agent-identity.js +26 -0
- package/dist/mcp/local-state/agent-sessions.js +66 -0
- package/dist/mcp/local-state/auth.js +57 -0
- package/dist/mcp/local-state/codex-live-sessions.js +59 -0
- package/dist/mcp/local-state/index.js +8 -0
- package/dist/mcp/local-state/local-chat.js +808 -0
- package/dist/mcp/local-state/room-sessions.js +51 -0
- package/dist/mcp/local-state/storage.js +95 -0
- package/dist/mcp/local-state/types.js +1 -0
- package/dist/mcp/local-state.js +1 -351
- package/dist/mcp/managed-agent-providers.js +65 -0
- package/dist/mcp/rental-tools/activity.js +37 -0
- package/dist/mcp/rental-tools/budget.js +36 -0
- package/dist/mcp/rental-tools/context.js +62 -0
- package/dist/mcp/rental-tools/lifecycle.js +47 -0
- package/dist/mcp/rental-tools/metering.js +73 -0
- package/dist/mcp/rental-tools/patches.js +100 -0
- package/dist/mcp/rental-tools/provider.js +117 -0
- package/dist/mcp/rental-tools/shared.js +19 -0
- package/dist/mcp/rental-tools/types.js +1 -0
- package/dist/mcp/rental-tools.js +7 -0
- package/dist/mcp/repo-visibility.js +8 -6
- package/dist/mcp/server/register-tools.js +19 -0
- package/dist/mcp/server/repo-context.js +28 -0
- package/dist/mcp/server/resources.js +77 -0
- package/dist/mcp/server/runtime/agent-sessions.js +134 -0
- package/dist/mcp/server/runtime/api.js +82 -0
- package/dist/mcp/server/runtime/auth-cache.js +20 -0
- package/dist/mcp/server/runtime/device-auth.js +48 -0
- package/dist/mcp/server/runtime/identity/config.js +58 -0
- package/dist/mcp/server/runtime/identity/directory.js +87 -0
- package/dist/mcp/server/runtime/identity/liveness.js +32 -0
- package/dist/mcp/server/runtime/identity/names.js +74 -0
- package/dist/mcp/server/runtime/identity/public.js +19 -0
- package/dist/mcp/server/runtime/identity/state.js +32 -0
- package/dist/mcp/server/runtime/identity.js +96 -0
- package/dist/mcp/server/runtime/messages.js +160 -0
- package/dist/mcp/server/runtime/presence.js +52 -0
- package/dist/mcp/server/runtime/room-api.js +42 -0
- package/dist/mcp/server/runtime/room-state.js +122 -0
- package/dist/mcp/server/runtime/rooms.js +318 -0
- package/dist/mcp/server/runtime.js +14 -0
- package/dist/mcp/server/tools/agent-sessions.js +374 -0
- package/dist/mcp/server/tools/messages/index.js +14 -0
- package/dist/mcp/server/tools/messages/read-tool.js +176 -0
- package/dist/mcp/server/tools/messages/reasoning-tool.js +179 -0
- package/dist/mcp/server/tools/messages/response.js +17 -0
- package/dist/mcp/server/tools/messages/send-tool.js +203 -0
- package/dist/mcp/server/tools/messages/status-tool.js +87 -0
- package/dist/mcp/server/tools/messages/wait-tool.js +333 -0
- package/dist/mcp/server/tools/messages.js +1 -0
- package/dist/mcp/server/tools/onboarding/device-auth-tools.js +148 -0
- package/dist/mcp/server/tools/onboarding/name-tool.js +89 -0
- package/dist/mcp/server/tools/onboarding/responses.js +10 -0
- package/dist/mcp/server/tools/onboarding/status-tool.js +108 -0
- package/dist/mcp/server/tools/onboarding.js +8 -0
- package/dist/mcp/server/tools/rental/activity-tools.js +43 -0
- package/dist/mcp/server/tools/rental/context-tools.js +35 -0
- package/dist/mcp/server/tools/rental/index.js +17 -0
- package/dist/mcp/server/tools/rental/metering-tools.js +39 -0
- package/dist/mcp/server/tools/rental/patch-tools.js +53 -0
- package/dist/mcp/server/tools/rental/provider-tools.js +44 -0
- package/dist/mcp/server/tools/rental/response.js +10 -0
- package/dist/mcp/server/tools/rental/types.js +1 -0
- package/dist/mcp/server/tools/rental.js +1 -0
- package/dist/mcp/server/tools/rooms/index.js +5 -0
- package/dist/mcp/server/tools/rooms/inspection-tools.js +124 -0
- package/dist/mcp/server/tools/rooms/join-tools.js +37 -0
- package/dist/mcp/server/tools/rooms/repo-initialization-tool.js +113 -0
- package/dist/mcp/server/tools/rooms/repo-visibility-tool.js +20 -0
- package/dist/mcp/server/tools/rooms/response.js +10 -0
- package/dist/mcp/server/tools/rooms/resume-tool.js +48 -0
- package/dist/mcp/server/tools/rooms.js +1 -0
- package/dist/mcp/server/tools/tasks/api.js +222 -0
- package/dist/mcp/server/tools/tasks/artifact-tools.js +75 -0
- package/dist/mcp/server/tools/tasks/board-intent-tools.js +321 -0
- package/dist/mcp/server/tools/tasks/board-tools.js +73 -0
- package/dist/mcp/server/tools/tasks/context.js +35 -0
- package/dist/mcp/server/tools/tasks/event-tools.js +40 -0
- package/dist/mcp/server/tools/tasks/index.js +14 -0
- package/dist/mcp/server/tools/tasks/lease-tools.js +145 -0
- package/dist/mcp/server/tools/tasks/mutation-tools.js +121 -0
- package/dist/mcp/server/tools/tasks/response.js +13 -0
- package/dist/mcp/server/tools/tasks/schemas.js +68 -0
- package/dist/mcp/server/tools/tasks.js +1 -0
- package/dist/mcp/server.js +10 -3157
- package/dist/mcp/sse-client.js +6 -14
- package/dist/shared/activation-routing.js +263 -0
- package/dist/shared/agent-identity.js +21 -5
- package/dist/shared/agent-presence.js +4 -3
- package/dist/shared/rental/lrt.js +214 -0
- package/dist/shared/rental/meter-types.js +14 -0
- package/dist/shared/room-agent-prompts.js +14 -1
- package/package.json +15 -5
- package/dist/mcp/__tests__/config-reader.test.js +0 -93
- package/dist/mcp/__tests__/git-remote.test.js +0 -37
- package/dist/mcp/__tests__/server-helpers.test.js +0 -121
- package/dist/shared/agent-reasoning.js +0 -49
- /package/dist/{mcp → shared}/codenames.js +0 -0
package/dist/mcp/git-remote.js
CHANGED
|
@@ -7,11 +7,11 @@
|
|
|
7
7
|
// host/owner/repo
|
|
8
8
|
//
|
|
9
9
|
// Examples:
|
|
10
|
-
// git@github.com:BrosInCode/letagents.git → github.com/
|
|
11
|
-
// https://github.com/BrosInCode/letagents.git → github.com/
|
|
12
|
-
// https://github.com/BrosInCode/letagents → github.com/
|
|
10
|
+
// git@github.com:BrosInCode/letagents.git → github.com/brosincode/letagents
|
|
11
|
+
// https://github.com/BrosInCode/letagents.git → github.com/brosincode/letagents
|
|
12
|
+
// https://github.com/BrosInCode/letagents → github.com/brosincode/letagents
|
|
13
13
|
// ssh://git@gitlab.com/team/project.git → gitlab.com/team/project
|
|
14
|
-
import {
|
|
14
|
+
import { execFileSync } from "child_process";
|
|
15
15
|
/**
|
|
16
16
|
* Normalize a git remote URL to `host/owner/repo` format.
|
|
17
17
|
* Strips protocol (SSH/HTTPS), user prefix, and `.git` suffix.
|
|
@@ -40,26 +40,102 @@ export function normalizeGitRemote(url) {
|
|
|
40
40
|
normalized = normalized.replace(/\.git$/, "");
|
|
41
41
|
// Strip trailing slashes
|
|
42
42
|
normalized = normalized.replace(/\/+$/, "");
|
|
43
|
+
const parts = normalized.split("/");
|
|
44
|
+
const host = parts[0]?.toLowerCase();
|
|
45
|
+
if (host) {
|
|
46
|
+
parts[0] = host;
|
|
47
|
+
normalized = host === "github.com" ? parts.join("/").toLowerCase() : parts.join("/");
|
|
48
|
+
}
|
|
43
49
|
return normalized;
|
|
44
50
|
}
|
|
45
|
-
|
|
46
|
-
* Get the normalized git remote URL for the current working directory.
|
|
47
|
-
* Returns null if not in a git repo or no remote is configured.
|
|
48
|
-
*/
|
|
49
|
-
export function getGitRemoteIdentity(cwd) {
|
|
51
|
+
function execGit(args, cwd) {
|
|
50
52
|
try {
|
|
51
|
-
const
|
|
53
|
+
const output = execFileSync("git", args, {
|
|
52
54
|
cwd: cwd || process.cwd(),
|
|
53
55
|
encoding: "utf-8",
|
|
54
56
|
timeout: 5000,
|
|
55
57
|
stdio: ["pipe", "pipe", "pipe"],
|
|
56
58
|
}).trim();
|
|
57
|
-
|
|
58
|
-
return null;
|
|
59
|
-
return normalizeGitRemote(remoteUrl);
|
|
59
|
+
return output || null;
|
|
60
60
|
}
|
|
61
61
|
catch {
|
|
62
|
-
// Not a git repo, no remote, or git not installed
|
|
63
62
|
return null;
|
|
64
63
|
}
|
|
65
64
|
}
|
|
65
|
+
function encodeRefForRoomId(refName) {
|
|
66
|
+
return Buffer.from(refName, "utf8")
|
|
67
|
+
.toString("base64")
|
|
68
|
+
.replace(/\+/g, "-")
|
|
69
|
+
.replace(/\//g, "_")
|
|
70
|
+
.replace(/=+$/g, "");
|
|
71
|
+
}
|
|
72
|
+
function githubRepositoryFullNameFromRoom(repoRoom) {
|
|
73
|
+
const parts = repoRoom.trim().replace(/\/+$/, "").split("/");
|
|
74
|
+
const host = parts[0]?.toLowerCase();
|
|
75
|
+
const owner = parts[1];
|
|
76
|
+
const repo = parts[2];
|
|
77
|
+
if (host !== "github.com" || !owner || !repo || parts.length !== 3) {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
return `${owner}/${repo}`;
|
|
81
|
+
}
|
|
82
|
+
function isLikelyDefaultBranchName(branchName) {
|
|
83
|
+
return branchName === "main" || branchName === "master" || branchName === "trunk";
|
|
84
|
+
}
|
|
85
|
+
export function buildGitRefRoomIdentity(input) {
|
|
86
|
+
const repositoryFullName = githubRepositoryFullNameFromRoom(input.repoRoom);
|
|
87
|
+
const refName = input.refName.trim();
|
|
88
|
+
if (!repositoryFullName || !refName) {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
return `git-room:github.com:${repositoryFullName.toLowerCase()}:${input.refType}:${encodeRefForRoomId(refName)}`;
|
|
92
|
+
}
|
|
93
|
+
export function getGitCurrentBranch(cwd) {
|
|
94
|
+
return execGit(["branch", "--show-current"], cwd);
|
|
95
|
+
}
|
|
96
|
+
export function getGitDefaultBranch(cwd) {
|
|
97
|
+
const originHead = execGit(["symbolic-ref", "--quiet", "--short", "refs/remotes/origin/HEAD"], cwd);
|
|
98
|
+
if (!originHead)
|
|
99
|
+
return null;
|
|
100
|
+
return originHead.replace(/^origin\//, "") || null;
|
|
101
|
+
}
|
|
102
|
+
export function buildActiveGitRoomContext(input) {
|
|
103
|
+
const currentBranch = input.currentBranch?.trim() || null;
|
|
104
|
+
const defaultBranch = input.defaultBranch?.trim() || null;
|
|
105
|
+
const shouldUseBranchRoom = Boolean(input.repoRoom
|
|
106
|
+
&& currentBranch
|
|
107
|
+
&& (defaultBranch
|
|
108
|
+
? currentBranch !== defaultBranch
|
|
109
|
+
: !isLikelyDefaultBranchName(currentBranch)));
|
|
110
|
+
const activeRefRoom = input.repoRoom && currentBranch && shouldUseBranchRoom
|
|
111
|
+
? buildGitRefRoomIdentity({
|
|
112
|
+
repoRoom: input.repoRoom,
|
|
113
|
+
refType: "branch",
|
|
114
|
+
refName: currentBranch,
|
|
115
|
+
})
|
|
116
|
+
: null;
|
|
117
|
+
return {
|
|
118
|
+
repoRoom: input.repoRoom,
|
|
119
|
+
currentBranch,
|
|
120
|
+
defaultBranch,
|
|
121
|
+
activeRefRoom,
|
|
122
|
+
activeRoom: activeRefRoom ?? input.repoRoom,
|
|
123
|
+
activeRoomKind: activeRefRoom ? "branch" : input.repoRoom ? "repo" : null,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
export function getGitRoomContext(cwd) {
|
|
127
|
+
const repoRoom = getGitRemoteIdentity(cwd);
|
|
128
|
+
return buildActiveGitRoomContext({
|
|
129
|
+
repoRoom,
|
|
130
|
+
currentBranch: getGitCurrentBranch(cwd),
|
|
131
|
+
defaultBranch: getGitDefaultBranch(cwd),
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Get the normalized git remote URL for the current working directory.
|
|
136
|
+
* Returns null if not in a git repo or no remote is configured.
|
|
137
|
+
*/
|
|
138
|
+
export function getGitRemoteIdentity(cwd) {
|
|
139
|
+
const remoteUrl = execGit(["remote", "get-url", "origin"], cwd);
|
|
140
|
+
return remoteUrl ? normalizeGitRemote(remoteUrl) : null;
|
|
141
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { readLocalState, updateLocalState } from "./storage.js";
|
|
2
|
+
export function getStoredAgentIdentity(identityKey) {
|
|
3
|
+
const state = readLocalState();
|
|
4
|
+
if (identityKey?.trim()) {
|
|
5
|
+
const scoped = state.agent_identities?.[identityKey.trim()];
|
|
6
|
+
if (scoped) {
|
|
7
|
+
return scoped;
|
|
8
|
+
}
|
|
9
|
+
// UUID-based identity keys must not inherit another process' shared identity.
|
|
10
|
+
if (identityKey.startsWith("instance:")) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return state.agent_identity ?? null;
|
|
15
|
+
}
|
|
16
|
+
export function setStoredAgentIdentity(agentIdentity, identityKey) {
|
|
17
|
+
updateLocalState((state) => {
|
|
18
|
+
state.agent_identity = agentIdentity;
|
|
19
|
+
if (identityKey?.trim()) {
|
|
20
|
+
state.agent_identities = state.agent_identities ?? {};
|
|
21
|
+
state.agent_identities[identityKey.trim()] = agentIdentity;
|
|
22
|
+
}
|
|
23
|
+
return state;
|
|
24
|
+
});
|
|
25
|
+
return agentIdentity;
|
|
26
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { readLocalState, updateLocalState } from "./storage.js";
|
|
2
|
+
export function getStoredAgentSession(sessionId) {
|
|
3
|
+
if (!sessionId) {
|
|
4
|
+
return null;
|
|
5
|
+
}
|
|
6
|
+
const state = readLocalState();
|
|
7
|
+
return state.agent_sessions?.[sessionId] ?? null;
|
|
8
|
+
}
|
|
9
|
+
export function getCurrentAgentSession(roomId) {
|
|
10
|
+
const state = readLocalState();
|
|
11
|
+
const sessionIds = state.current_agent_session_ids;
|
|
12
|
+
if (!sessionIds) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
if (roomId) {
|
|
16
|
+
const sessionId = sessionIds[roomId];
|
|
17
|
+
const session = sessionId ? (state.agent_sessions?.[sessionId] ?? null) : null;
|
|
18
|
+
return session && !session.ended_at ? session : null;
|
|
19
|
+
}
|
|
20
|
+
let best = null;
|
|
21
|
+
for (const id of Object.values(sessionIds)) {
|
|
22
|
+
const session = state.agent_sessions?.[id];
|
|
23
|
+
if (session && !session.ended_at && (!best || session.updated_at > best.updated_at)) {
|
|
24
|
+
best = session;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return best;
|
|
28
|
+
}
|
|
29
|
+
export function saveAgentSession(session, makeCurrent = true) {
|
|
30
|
+
updateLocalState((state) => {
|
|
31
|
+
state.agent_sessions = state.agent_sessions ?? {};
|
|
32
|
+
state.agent_sessions[session.session_id] = session;
|
|
33
|
+
if (makeCurrent) {
|
|
34
|
+
state.current_agent_session_ids = state.current_agent_session_ids ?? {};
|
|
35
|
+
state.current_agent_session_ids[session.room_id] = session.session_id;
|
|
36
|
+
}
|
|
37
|
+
return state;
|
|
38
|
+
});
|
|
39
|
+
return session;
|
|
40
|
+
}
|
|
41
|
+
export function endStoredAgentSession(sessionId, endedAt = new Date().toISOString()) {
|
|
42
|
+
let endedSession = null;
|
|
43
|
+
updateLocalState((state) => {
|
|
44
|
+
const session = state.agent_sessions?.[sessionId];
|
|
45
|
+
if (!session) {
|
|
46
|
+
return state;
|
|
47
|
+
}
|
|
48
|
+
endedSession = {
|
|
49
|
+
...session,
|
|
50
|
+
ended_at: endedAt,
|
|
51
|
+
updated_at: endedAt,
|
|
52
|
+
last_seen_at: endedAt,
|
|
53
|
+
};
|
|
54
|
+
state.agent_sessions = state.agent_sessions ?? {};
|
|
55
|
+
state.agent_sessions[sessionId] = endedSession;
|
|
56
|
+
if (state.current_agent_session_ids) {
|
|
57
|
+
for (const [roomId, currentSessionId] of Object.entries(state.current_agent_session_ids)) {
|
|
58
|
+
if (currentSessionId === sessionId) {
|
|
59
|
+
delete state.current_agent_session_ids[roomId];
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return state;
|
|
64
|
+
});
|
|
65
|
+
return endedSession;
|
|
66
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { readLocalState, updateLocalState } from "./storage.js";
|
|
2
|
+
function isExpired(expiresAt) {
|
|
3
|
+
if (!expiresAt) {
|
|
4
|
+
return false;
|
|
5
|
+
}
|
|
6
|
+
const expiresAtMs = Date.parse(expiresAt);
|
|
7
|
+
return Number.isFinite(expiresAtMs) && expiresAtMs <= Date.now();
|
|
8
|
+
}
|
|
9
|
+
export function getStoredAuth() {
|
|
10
|
+
const state = readLocalState();
|
|
11
|
+
if (!state.auth) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
if (isExpired(state.auth.expires_at)) {
|
|
15
|
+
clearStoredAuth();
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
return state.auth;
|
|
19
|
+
}
|
|
20
|
+
export function setStoredAuth(auth) {
|
|
21
|
+
updateLocalState((state) => {
|
|
22
|
+
state.auth = auth;
|
|
23
|
+
delete state.pending_device_auth;
|
|
24
|
+
return state;
|
|
25
|
+
});
|
|
26
|
+
return auth;
|
|
27
|
+
}
|
|
28
|
+
export function clearStoredAuth() {
|
|
29
|
+
updateLocalState((state) => {
|
|
30
|
+
delete state.auth;
|
|
31
|
+
return state;
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
export function getPendingDeviceAuth() {
|
|
35
|
+
const state = readLocalState();
|
|
36
|
+
if (!state.pending_device_auth) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
if (isExpired(state.pending_device_auth.expires_at)) {
|
|
40
|
+
clearPendingDeviceAuth();
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
return state.pending_device_auth;
|
|
44
|
+
}
|
|
45
|
+
export function setPendingDeviceAuth(pendingDeviceAuth) {
|
|
46
|
+
updateLocalState((state) => {
|
|
47
|
+
state.pending_device_auth = pendingDeviceAuth;
|
|
48
|
+
return state;
|
|
49
|
+
});
|
|
50
|
+
return pendingDeviceAuth;
|
|
51
|
+
}
|
|
52
|
+
export function clearPendingDeviceAuth() {
|
|
53
|
+
updateLocalState((state) => {
|
|
54
|
+
delete state.pending_device_auth;
|
|
55
|
+
return state;
|
|
56
|
+
});
|
|
57
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { readLocalState, updateLocalState } from "./storage.js";
|
|
2
|
+
export function getCurrentCodexLiveSession(roomId) {
|
|
3
|
+
const state = readLocalState();
|
|
4
|
+
const sessionIds = state.current_codex_live_session_ids;
|
|
5
|
+
if (!sessionIds) {
|
|
6
|
+
return null;
|
|
7
|
+
}
|
|
8
|
+
if (roomId) {
|
|
9
|
+
const sessionId = sessionIds[roomId];
|
|
10
|
+
return sessionId ? (state.codex_live_sessions?.[sessionId] ?? null) : null;
|
|
11
|
+
}
|
|
12
|
+
let best = null;
|
|
13
|
+
for (const id of Object.values(sessionIds)) {
|
|
14
|
+
const session = state.codex_live_sessions?.[id];
|
|
15
|
+
if (session && (!best || session.updated_at > best.updated_at)) {
|
|
16
|
+
best = session;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return best;
|
|
20
|
+
}
|
|
21
|
+
export function getStoredCodexLiveSession(sessionId) {
|
|
22
|
+
const state = readLocalState();
|
|
23
|
+
return state.codex_live_sessions?.[sessionId] ?? null;
|
|
24
|
+
}
|
|
25
|
+
export function listStoredCodexLiveSessions() {
|
|
26
|
+
const state = readLocalState();
|
|
27
|
+
return Object.values(state.codex_live_sessions ?? {}).sort((left, right) => right.updated_at.localeCompare(left.updated_at));
|
|
28
|
+
}
|
|
29
|
+
export function saveCodexLiveSession(session, makeCurrent = true) {
|
|
30
|
+
updateLocalState((state) => {
|
|
31
|
+
state.codex_live_sessions = state.codex_live_sessions ?? {};
|
|
32
|
+
state.codex_live_sessions[session.session_id] = session;
|
|
33
|
+
if (makeCurrent) {
|
|
34
|
+
state.current_codex_live_session_ids = state.current_codex_live_session_ids ?? {};
|
|
35
|
+
state.current_codex_live_session_ids[session.room_id] = session.session_id;
|
|
36
|
+
}
|
|
37
|
+
return state;
|
|
38
|
+
});
|
|
39
|
+
return session;
|
|
40
|
+
}
|
|
41
|
+
export function updateCodexLiveSession(sessionId, updater) {
|
|
42
|
+
let updatedSession = null;
|
|
43
|
+
updateLocalState((state) => {
|
|
44
|
+
const existing = state.codex_live_sessions?.[sessionId];
|
|
45
|
+
if (!existing) {
|
|
46
|
+
return state;
|
|
47
|
+
}
|
|
48
|
+
const updated = updater(existing);
|
|
49
|
+
state.codex_live_sessions = state.codex_live_sessions ?? {};
|
|
50
|
+
state.codex_live_sessions[sessionId] = updated;
|
|
51
|
+
state.current_codex_live_session_ids = state.current_codex_live_session_ids ?? {};
|
|
52
|
+
if (!state.current_codex_live_session_ids[updated.room_id]) {
|
|
53
|
+
state.current_codex_live_session_ids[updated.room_id] = sessionId;
|
|
54
|
+
}
|
|
55
|
+
updatedSession = updated;
|
|
56
|
+
return state;
|
|
57
|
+
});
|
|
58
|
+
return updatedSession;
|
|
59
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from "./types.js";
|
|
2
|
+
export * from "./storage.js";
|
|
3
|
+
export * from "./auth.js";
|
|
4
|
+
export * from "./agent-identity.js";
|
|
5
|
+
export * from "./agent-sessions.js";
|
|
6
|
+
export * from "./room-sessions.js";
|
|
7
|
+
export * from "./codex-live-sessions.js";
|
|
8
|
+
export * from "./local-chat.js";
|