@cydm/happy-elves 0.1.0-beta.296 → 0.1.0-beta.298
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/apps/cli/dist/commands/lib/args.js +7 -17
- package/apps/cli/dist/commands/lib/session-output.d.ts +1 -1
- package/apps/cli/dist/commands/lib/session-output.js +3 -66
- package/apps/cli/dist/commands/lib/session-view.d.ts +0 -3
- package/apps/cli/dist/commands/lib/session-view.js +1 -15
- package/apps/cli/dist/commands/lib/types.d.ts +1 -1
- package/apps/cli/dist/commands/lib/usage.js +20 -47
- package/apps/cli/dist/commands/lib/workspace.js +42 -2
- package/apps/cli/dist/commands/memory.js +6 -26
- package/apps/cli/dist/commands/release.js +45 -199
- package/apps/cli/dist/commands/remote.js +1 -134
- package/apps/cli/dist/commands/session.js +37 -98
- package/apps/cli/dist/commands/turn.js +1 -4
- package/apps/cli/package.json +1 -1
- package/apps/daemon/dist/paths.d.ts +0 -3
- package/apps/daemon/dist/paths.js +0 -3
- package/apps/daemon/dist/relay/connection.js +0 -10
- package/apps/daemon/dist/relay/register.js +0 -3
- package/apps/daemon/dist/runtime/external-provider.js +1 -32
- package/apps/daemon/dist/session/lifecycle.js +19 -7
- package/apps/daemon/dist/session/metadata.d.ts +1 -2
- package/apps/daemon/dist/session/metadata.js +12 -10
- package/apps/daemon/dist/session/primitives.js +16 -8
- package/apps/daemon/dist/session/prompt.d.ts +1 -1
- package/apps/daemon/dist/session/prompt.js +9 -86
- package/apps/daemon/dist/session/reconcile.js +0 -21
- package/apps/daemon/dist/types.d.ts +3 -4
- package/apps/daemon/package.json +1 -1
- package/apps/relay/dist/connections.d.ts +0 -1
- package/apps/relay/dist/controller-handlers.js +34 -111
- package/apps/relay/dist/db.js +0 -2
- package/apps/relay/dist/http-routes.js +50 -33
- package/apps/relay/dist/http-schemas.d.ts +15 -13
- package/apps/relay/dist/http-schemas.js +3 -1
- package/apps/relay/dist/machine-handlers.js +25 -183
- package/apps/relay/dist/projections.js +1 -64
- package/apps/relay/dist/relay-context.js +44 -104
- package/apps/relay/dist/types.d.ts +0 -1
- package/package.json +1 -1
- package/packages/agent-sdk/dist/index.d.ts +0 -9
- package/packages/client/dist/client.d.ts +9 -10
- package/packages/client/dist/client.js +75 -132
- package/packages/client/dist/index.d.ts +1 -1
- package/packages/client/dist/transport.d.ts +0 -10
- package/packages/client/dist/transport.js +0 -14
- package/packages/client/dist/types.d.ts +3 -40
- package/packages/runtime/dist/index.d.ts +0 -9
- package/packages/runtime-cli/dist/codex-app-server.d.ts +1 -15
- package/packages/runtime-cli/dist/codex-app-server.js +3 -167
- package/packages/runtime-cli/dist/codex-protocol.d.ts +1 -4
- package/packages/runtime-cli/dist/codex-protocol.js +2 -7
- package/packages/runtime-cli/dist/index.d.ts +1 -6
- package/packages/runtime-cli/dist/index.js +5 -163
- package/packages/shared/dist/args.js +4 -16
- package/packages/shared/dist/index.d.ts +1 -1
- package/packages/shared/dist/index.js +1 -1
- package/packages/shared/dist/protocol-schemas.d.ts +2 -216
- package/packages/shared/dist/protocol-schemas.js +1 -97
- package/packages/shared/dist/protocol-types.d.ts +1 -101
- package/packages/shared/dist/protocol.d.ts +2 -67
- package/packages/shared/dist/protocol.js +1 -75
- package/packages/shared/dist/session-state.d.ts +1 -1
- package/packages/shared/dist/session-state.js +1 -4
- package/apps/daemon/dist/relay/lifecycle.d.ts +0 -7
- package/apps/daemon/dist/relay/lifecycle.js +0 -545
- package/apps/daemon/dist/relay/release.d.ts +0 -7
- package/apps/daemon/dist/relay/release.js +0 -378
|
@@ -32,7 +32,6 @@ const valueFlags = new Set([
|
|
|
32
32
|
"memory-project",
|
|
33
33
|
"memory-top-n",
|
|
34
34
|
"name",
|
|
35
|
-
"package-url",
|
|
36
35
|
"model",
|
|
37
36
|
"mode",
|
|
38
37
|
"output",
|
|
@@ -40,12 +39,14 @@ const valueFlags = new Set([
|
|
|
40
39
|
"port",
|
|
41
40
|
"permission",
|
|
42
41
|
"permission-mode",
|
|
42
|
+
"profile",
|
|
43
43
|
"project",
|
|
44
44
|
"query",
|
|
45
45
|
"prompt",
|
|
46
46
|
"prompt-file",
|
|
47
47
|
"every",
|
|
48
48
|
"reason",
|
|
49
|
+
"release-tag",
|
|
49
50
|
"reaction-emoji",
|
|
50
51
|
"relay",
|
|
51
52
|
"root",
|
|
@@ -53,6 +54,7 @@ const valueFlags = new Set([
|
|
|
53
54
|
"runtime-session",
|
|
54
55
|
"shell",
|
|
55
56
|
"actions",
|
|
57
|
+
"ack-timeout",
|
|
56
58
|
"allow-chat",
|
|
57
59
|
"allow-sender",
|
|
58
60
|
"expires-in",
|
|
@@ -62,23 +64,12 @@ const valueFlags = new Set([
|
|
|
62
64
|
"sessions",
|
|
63
65
|
"session",
|
|
64
66
|
"secret",
|
|
65
|
-
"sha256",
|
|
66
67
|
"since",
|
|
67
68
|
"source",
|
|
68
69
|
"stop-on",
|
|
69
70
|
"tail",
|
|
70
71
|
"tag",
|
|
71
72
|
"tags",
|
|
72
|
-
"release-tag",
|
|
73
|
-
"release-tags",
|
|
74
|
-
"reviewer-tag",
|
|
75
|
-
"reviewer-tags",
|
|
76
|
-
"dogfood-tag",
|
|
77
|
-
"dogfood-tags",
|
|
78
|
-
"target-machine",
|
|
79
|
-
"target-machines",
|
|
80
|
-
"expected-commit",
|
|
81
|
-
"profile",
|
|
82
73
|
"text",
|
|
83
74
|
"text-file",
|
|
84
75
|
"timeout",
|
|
@@ -94,17 +85,19 @@ const valueFlags = new Set([
|
|
|
94
85
|
"url",
|
|
95
86
|
"turn",
|
|
96
87
|
"until",
|
|
97
|
-
"
|
|
98
|
-
"
|
|
88
|
+
"reviewer-tag",
|
|
89
|
+
"dogfood-tag",
|
|
99
90
|
]);
|
|
100
91
|
const booleanFlags = new Set([
|
|
101
92
|
"all",
|
|
102
93
|
"allow-any-sender",
|
|
103
94
|
"app-secret-stdin",
|
|
104
95
|
"confirm-risk",
|
|
96
|
+
"copy-tags",
|
|
105
97
|
"detach",
|
|
106
98
|
"disable-reaction",
|
|
107
99
|
"help",
|
|
100
|
+
"hidden",
|
|
108
101
|
"h",
|
|
109
102
|
"include-archived",
|
|
110
103
|
"include-debug",
|
|
@@ -119,10 +112,7 @@ const booleanFlags = new Set([
|
|
|
119
112
|
"summary",
|
|
120
113
|
"verbose",
|
|
121
114
|
"wait",
|
|
122
|
-
"hidden",
|
|
123
115
|
"manual",
|
|
124
|
-
"copy-tags",
|
|
125
|
-
"no-daemon-update",
|
|
126
116
|
]);
|
|
127
117
|
const knownFlags = new Set([...valueFlags, ...booleanFlags]);
|
|
128
118
|
const dashPrefixedValueFlags = new Set(["secret"]);
|
|
@@ -29,7 +29,7 @@ export type TurnSummary = {
|
|
|
29
29
|
checkpointId?: string;
|
|
30
30
|
runtimeTurnId?: string;
|
|
31
31
|
turnSeq?: number;
|
|
32
|
-
status: "running" | "completed" | "failed" | "cancelled"
|
|
32
|
+
status: "running" | "completed" | "failed" | "cancelled";
|
|
33
33
|
prompt: string;
|
|
34
34
|
output: string;
|
|
35
35
|
terminalText: string;
|
|
@@ -243,13 +243,6 @@ export function summarizeTurns(events) {
|
|
|
243
243
|
current.checkpointId = payload.currentHead;
|
|
244
244
|
current.runtimeTurnId = payload.lastTurnId;
|
|
245
245
|
}
|
|
246
|
-
else if (payload?.type === "status" && isReconcileUnknownTag(payload.tag)) {
|
|
247
|
-
if (current.status === "running") {
|
|
248
|
-
current.status = "unknown";
|
|
249
|
-
current.completedAt = event.createdAt;
|
|
250
|
-
current.terminalText = payload.text.trim();
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
246
|
else if (payload?.type === "memory_used") {
|
|
254
247
|
current.usedMemories = dedupeUsedMemories([...current.usedMemories, ...payload.memories]);
|
|
255
248
|
}
|
|
@@ -322,7 +315,7 @@ function foldAliasedRuntimeEvents(events) {
|
|
|
322
315
|
const profiles = new Map();
|
|
323
316
|
const runtimeToRequest = new Map();
|
|
324
317
|
for (const event of events) {
|
|
325
|
-
const profile = profiles.get(event.turnId) ?? { output: ""
|
|
318
|
+
const profile = profiles.get(event.turnId) ?? { output: "" };
|
|
326
319
|
const payload = event.decoded;
|
|
327
320
|
if (payload?.type === "user_prompt" && profile.prompt === undefined) {
|
|
328
321
|
profile.prompt = payload.text.trim();
|
|
@@ -335,7 +328,6 @@ function foldAliasedRuntimeEvents(events) {
|
|
|
335
328
|
if (runtimeTurnId && runtimeTurnId !== event.turnId && !runtimeTurnId.startsWith("event:")) {
|
|
336
329
|
runtimeToRequest.set(runtimeTurnId, event.turnId);
|
|
337
330
|
}
|
|
338
|
-
profile.status = payload.status;
|
|
339
331
|
}
|
|
340
332
|
profiles.set(event.turnId, profile);
|
|
341
333
|
}
|
|
@@ -353,46 +345,11 @@ function foldAliasedRuntimeEvents(events) {
|
|
|
353
345
|
duplicateRuntimeToRequest.set(runtimeTurnId, requestTurnId);
|
|
354
346
|
}
|
|
355
347
|
}
|
|
356
|
-
const inferredRuntimeToRequest = inferRuntimeCompletionAliases(profiles);
|
|
357
|
-
const inferredRequestTurns = new Set(inferredRuntimeToRequest.values());
|
|
358
|
-
const foldedRuntimeToRequest = new Map([...duplicateRuntimeToRequest, ...inferredRuntimeToRequest]);
|
|
359
|
-
const foldedEvents = [];
|
|
360
|
-
for (const event of events) {
|
|
361
|
-
if (duplicateRuntimeTurns.has(event.turnId))
|
|
362
|
-
continue;
|
|
363
|
-
const inferredRequestTurnId = inferredRuntimeToRequest.get(event.turnId);
|
|
364
|
-
if (inferredRequestTurnId) {
|
|
365
|
-
if (event.decoded?.type === "user_prompt" && profiles.get(inferredRequestTurnId)?.prompt)
|
|
366
|
-
continue;
|
|
367
|
-
foldedEvents.push({ ...event, turnId: inferredRequestTurnId });
|
|
368
|
-
continue;
|
|
369
|
-
}
|
|
370
|
-
if (inferredRequestTurns.has(event.turnId) &&
|
|
371
|
-
event.decoded?.type === "text_delta" &&
|
|
372
|
-
event.decoded.stream !== "thought") {
|
|
373
|
-
continue;
|
|
374
|
-
}
|
|
375
|
-
foldedEvents.push(event);
|
|
376
|
-
}
|
|
377
348
|
return {
|
|
378
|
-
events:
|
|
379
|
-
runtimeToRequest:
|
|
349
|
+
events: duplicateRuntimeTurns.size === 0 ? events : events.filter((event) => !duplicateRuntimeTurns.has(event.turnId)),
|
|
350
|
+
runtimeToRequest: duplicateRuntimeToRequest,
|
|
380
351
|
};
|
|
381
352
|
}
|
|
382
|
-
function inferRuntimeCompletionAliases(profiles) {
|
|
383
|
-
const requestTurns = [...profiles.entries()].filter(([turnId, profile]) => turnId.startsWith("turn_") && profile.status === "running" && Boolean(profile.prompt?.trim()));
|
|
384
|
-
const runtimeTurns = [...profiles.entries()].filter(([turnId, profile]) => !turnId.startsWith("turn_") && profile.status !== "running" && Boolean(profile.prompt?.trim()));
|
|
385
|
-
const result = new Map();
|
|
386
|
-
for (const [runtimeTurnId, runtime] of runtimeTurns) {
|
|
387
|
-
const candidates = requestTurns.filter(([, request]) => promptCompatible(request.prompt ?? "", runtime.prompt ?? "") &&
|
|
388
|
-
outputCompatibleForInferredAlias(request.output, runtime.output, request.prompt ?? "", runtime.prompt ?? ""));
|
|
389
|
-
if (candidates.length !== 1)
|
|
390
|
-
continue;
|
|
391
|
-
const [requestTurnId] = candidates[0];
|
|
392
|
-
result.set(runtimeTurnId, requestTurnId);
|
|
393
|
-
}
|
|
394
|
-
return result;
|
|
395
|
-
}
|
|
396
353
|
function dedupeSyntheticHistoricalEvents(events) {
|
|
397
354
|
const groups = new Map();
|
|
398
355
|
for (const event of events) {
|
|
@@ -451,23 +408,6 @@ function isDuplicateRuntimeOutput(requestOutput, runtimeOutput) {
|
|
|
451
408
|
const runtime = comparableOutput(runtimeOutput);
|
|
452
409
|
return !runtime || request === runtime || request.includes(runtime);
|
|
453
410
|
}
|
|
454
|
-
function promptCompatible(requestPrompt, runtimePrompt) {
|
|
455
|
-
const request = comparableOutput(requestPrompt);
|
|
456
|
-
const runtime = comparableOutput(runtimePrompt);
|
|
457
|
-
if (!request || !runtime)
|
|
458
|
-
return false;
|
|
459
|
-
if (request === runtime)
|
|
460
|
-
return true;
|
|
461
|
-
return (request.length >= 40 && runtime.includes(request)) ||
|
|
462
|
-
(runtime.length >= 40 && request.includes(runtime));
|
|
463
|
-
}
|
|
464
|
-
function outputCompatibleForInferredAlias(requestOutput, runtimeOutput, requestPrompt, runtimePrompt) {
|
|
465
|
-
const request = comparableOutput(requestOutput);
|
|
466
|
-
const runtime = comparableOutput(runtimeOutput);
|
|
467
|
-
if (request && runtime)
|
|
468
|
-
return request.includes(runtime) || runtime.includes(request);
|
|
469
|
-
return comparableOutput(requestPrompt) === comparableOutput(runtimePrompt) && Boolean(request || runtime);
|
|
470
|
-
}
|
|
471
411
|
function comparableOutput(value) {
|
|
472
412
|
return value.replace(/\s+/g, " ").trim();
|
|
473
413
|
}
|
|
@@ -479,9 +419,6 @@ function turnInProgressError(sessionId, turn, latestCompleted) {
|
|
|
479
419
|
latestCompletedTurnId: latestCompleted?.turnId,
|
|
480
420
|
});
|
|
481
421
|
}
|
|
482
|
-
function isReconcileUnknownTag(tag) {
|
|
483
|
-
return tag === "reconcile:unknown" || tag === "reconcile:not_found" || tag === "reconcile:uninspectable";
|
|
484
|
-
}
|
|
485
422
|
export async function rebuildTurnOutput(client, sessionId, turnId) {
|
|
486
423
|
const events = await client.history(sessionId, 1000);
|
|
487
424
|
const folded = foldAliasedRuntimeEvents(events);
|
|
@@ -25,7 +25,6 @@ export declare function structuredSessionProjection(client: ControllerClient, se
|
|
|
25
25
|
sourceSessionId?: string;
|
|
26
26
|
sourceCheckpointId?: string;
|
|
27
27
|
capabilities: SessionSnapshot["capabilities"];
|
|
28
|
-
tags: string[];
|
|
29
28
|
orchestration: OrchestrationSummary;
|
|
30
29
|
}>;
|
|
31
30
|
export declare function compactSessionListItem(client: ControllerClient, session: SessionSnapshot, options?: {
|
|
@@ -41,7 +40,6 @@ export declare function compactSessionListItem(client: ControllerClient, session
|
|
|
41
40
|
machineId?: string;
|
|
42
41
|
machineName?: string;
|
|
43
42
|
cwdName?: string;
|
|
44
|
-
tags: string[];
|
|
45
43
|
}>;
|
|
46
44
|
export declare function conciseSessionSummary(client: ControllerClient, session: SessionSnapshot): Promise<{
|
|
47
45
|
sessionId: string;
|
|
@@ -52,7 +50,6 @@ export declare function conciseSessionSummary(client: ControllerClient, session:
|
|
|
52
50
|
status: SessionSnapshot["status"];
|
|
53
51
|
state: OrchestrationState;
|
|
54
52
|
updatedAt: number;
|
|
55
|
-
tags: string[];
|
|
56
53
|
}>;
|
|
57
54
|
export declare function requireProjectedSession(client: ControllerClient, sessionId: string, action: string): Promise<SessionSnapshot>;
|
|
58
55
|
export declare function machineSessionOverview(client: ControllerClient, sessions: SessionSnapshot[], machineId: string): Promise<{
|
|
@@ -34,7 +34,7 @@ function orchestrationStateFromStatus(status) {
|
|
|
34
34
|
return "idle";
|
|
35
35
|
if (status === "completed")
|
|
36
36
|
return "completed";
|
|
37
|
-
if (status === "failed" || status === "offline"
|
|
37
|
+
if (status === "failed" || status === "offline")
|
|
38
38
|
return "blocked";
|
|
39
39
|
return "closed";
|
|
40
40
|
}
|
|
@@ -70,17 +70,6 @@ export function deriveOrchestration(session, events = []) {
|
|
|
70
70
|
completed: false,
|
|
71
71
|
};
|
|
72
72
|
}
|
|
73
|
-
if (latestTerminalTurn?.status === "unknown") {
|
|
74
|
-
return {
|
|
75
|
-
state: "blocked",
|
|
76
|
-
rawStatus: session.status,
|
|
77
|
-
needsUser: false,
|
|
78
|
-
blocked: true,
|
|
79
|
-
completed: false,
|
|
80
|
-
reason: "execution-unknown",
|
|
81
|
-
lastEventId: latestTerminalTurn.lastEventId,
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
73
|
const state = orchestrationStateFromStatus(session.status);
|
|
85
74
|
return {
|
|
86
75
|
state,
|
|
@@ -128,7 +117,6 @@ export async function structuredSessionProjection(client, session, events = [])
|
|
|
128
117
|
sourceSessionId: session.sourceSessionId,
|
|
129
118
|
sourceCheckpointId: session.sourceCheckpointId,
|
|
130
119
|
capabilities: session.capabilities,
|
|
131
|
-
tags: Array.isArray(metadata.tags) ? metadata.tags.filter((tag) => typeof tag === "string") : [],
|
|
132
120
|
orchestration,
|
|
133
121
|
};
|
|
134
122
|
}
|
|
@@ -147,7 +135,6 @@ export async function compactSessionListItem(client, session, options = {}) {
|
|
|
147
135
|
state: orchestration.state,
|
|
148
136
|
agent: metadata.agent ?? session.agent,
|
|
149
137
|
updatedAt: session.updatedAt,
|
|
150
|
-
tags: Array.isArray(metadata.tags) ? metadata.tags.filter((tag) => typeof tag === "string") : [],
|
|
151
138
|
...(options.includeMachine ? { machineId: session.machineId, machineName: options.machineName } : {}),
|
|
152
139
|
...(options.includeCwd ? { cwdName: cwdDisplayName(metadata.cwd ?? session.cwd) } : {}),
|
|
153
140
|
};
|
|
@@ -164,7 +151,6 @@ export async function conciseSessionSummary(client, session) {
|
|
|
164
151
|
status: session.status,
|
|
165
152
|
state: orchestration.state,
|
|
166
153
|
updatedAt: session.updatedAt,
|
|
167
|
-
tags: Array.isArray(metadata.tags) ? metadata.tags.filter((tag) => typeof tag === "string") : [],
|
|
168
154
|
};
|
|
169
155
|
}
|
|
170
156
|
export async function requireProjectedSession(client, sessionId, action) {
|
|
@@ -29,9 +29,9 @@ export type SessionMetadata = {
|
|
|
29
29
|
cwd?: string;
|
|
30
30
|
name?: string;
|
|
31
31
|
requestedRuntimeName?: string;
|
|
32
|
+
runtime?: unknown;
|
|
32
33
|
tags?: string[];
|
|
33
34
|
tagKeys?: string[];
|
|
34
|
-
runtime?: unknown;
|
|
35
35
|
};
|
|
36
36
|
export declare const idleSessionStatuses: SessionSnapshot["status"][];
|
|
37
37
|
export type OrchestrationState = "pending" | "active" | "idle" | "completed" | "blocked" | "needs-user" | "closed";
|
|
@@ -30,10 +30,6 @@ Check local controller config, relay reachability, and daemon state.
|
|
|
30
30
|
happy-elves remote add-controller [--device-id <id>] [--device-name <name>] --json
|
|
31
31
|
happy-elves remote rename <deviceId> --name <name> --json
|
|
32
32
|
happy-elves remote revoke <deviceId> --json
|
|
33
|
-
happy-elves remote daemon-status <machineId> [--json]
|
|
34
|
-
happy-elves remote daemon-restart <machineId> [--wait] [--timeout 2m] [--json]
|
|
35
|
-
happy-elves remote daemon-update <machineId> [--version latest|0.1.0-beta.N] [--package-url <url> --sha256 <hex>] [--wait] [--timeout 10m] [--json]
|
|
36
|
-
happy-elves remote daemon-logs <machineId> [--tail 100] [--json]
|
|
37
33
|
`,
|
|
38
34
|
machine: `Usage:
|
|
39
35
|
happy-elves machine list [--verbose] [--json]
|
|
@@ -50,7 +46,7 @@ Check local controller config, relay reachability, and daemon state.
|
|
|
50
46
|
file preview is read-only and limited to files inside --root.
|
|
51
47
|
`,
|
|
52
48
|
session: `Usage:
|
|
53
|
-
happy-elves session create --machine <machineId> [--agent codex] [--cwd <path>] [--name <name>] [--permission-mode <mode>] [--
|
|
49
|
+
happy-elves session create --machine <machineId> [--agent codex] [--cwd <path>] [--name <name>] [--permission-mode <mode>] [--tag <tag>] [--hidden --source dogfood] --json
|
|
54
50
|
happy-elves session list [--machine <machineId>] [--agent <agent>] [--cwd <cwd>] [--name <name>] [--tag <tag>] [--limit n] [--all] [--verbose] [--json]
|
|
55
51
|
happy-elves session tag add <sessionId> --tag <tag> --json
|
|
56
52
|
happy-elves session tag remove <sessionId> --tag <tag> --json
|
|
@@ -76,7 +72,6 @@ Session management:
|
|
|
76
72
|
repair-binding imports the matching runtime history row as a new loaded
|
|
77
73
|
session and closes the empty/stale source session unless --keep-source is set.
|
|
78
74
|
close archives a loaded session. There is no separate archive command.
|
|
79
|
-
tags are encrypted session metadata used for release/reviewer/dogfood routing.
|
|
80
75
|
`,
|
|
81
76
|
turn: `Usage:
|
|
82
77
|
happy-elves turn list <sessionId> [--limit 10] [--verbose] [--json]
|
|
@@ -85,7 +80,7 @@ Session management:
|
|
|
85
80
|
happy-elves turn run <sessionId> (--text <prompt> | --text-file <path>) [--detach] [--timeout 1000s] [--inactivity-timeout 1000s] [--permission-mode approve-reads|approve-all|deny-all] [--memory off|readonly|readwrite] [--memory-project <key>] [--memory-top-n 3] [--json]
|
|
86
81
|
happy-elves turn wait <sessionId> <turnId> [--timeout 1000s] --json
|
|
87
82
|
happy-elves turn reconcile <sessionId> [turnId] --json
|
|
88
|
-
happy-elves turn recover <sessionId> [turnId] --text <continuation> --confirm-risk [--
|
|
83
|
+
happy-elves turn recover <sessionId> [turnId] --text <continuation> --confirm-risk [--detach] --json
|
|
89
84
|
happy-elves turn cancel <sessionId> <turnId> [--reason <reason>] --json
|
|
90
85
|
happy-elves turn rewind <sessionId> <turn-or-checkpoint-id> --json
|
|
91
86
|
happy-elves turn fork <sessionId> <turn-or-checkpoint-id> --name <name> [--copy-tags] --json
|
|
@@ -117,22 +112,6 @@ Turn management:
|
|
|
117
112
|
|
|
118
113
|
Workspace sync records account-level UI/library state shared across devices:
|
|
119
114
|
session stars, recent sessions, pinned workspaces, and current project defaults.
|
|
120
|
-
`,
|
|
121
|
-
release: `Usage:
|
|
122
|
-
happy-elves release profile list --json
|
|
123
|
-
happy-elves release profile show [--profile <name>] --json
|
|
124
|
-
happy-elves release profile set <name> --release-tag <tag> [--release-tag <tag>] [--reviewer-tag <tag>] [--dogfood-tag <tag>] [--no-daemon-update] --json
|
|
125
|
-
happy-elves release resolve [--profile happy-elves] --json
|
|
126
|
-
happy-elves release notify [--profile happy-elves] [--text 发布] [--detach] [--timeout 1000s] --json
|
|
127
|
-
happy-elves release start [--profile happy-elves] [--expected-commit <sha>] [--target-machine <machineId>] [--no-daemon-update] [--wait] --json
|
|
128
|
-
happy-elves release status [jobId] [--machine <machineId>] --json
|
|
129
|
-
happy-elves release logs [jobId] [--machine <machineId>] [--tail 200] --json
|
|
130
|
-
|
|
131
|
-
Release profiles resolve target sessions by encrypted session tags. The built-in
|
|
132
|
-
happy-elves profile uses Happy Elves + Release Session for the release target.
|
|
133
|
-
Release notify sends the short release prompt to that target with approve-all
|
|
134
|
-
permissions and memory off, so agents do not have to reconstruct release flags.
|
|
135
|
-
Release start runs a fixed daemon-local runner; it does not accept arbitrary shell.
|
|
136
115
|
`,
|
|
137
116
|
gateway: `Usage:
|
|
138
117
|
happy-elves gateway enable [<channelId>] --channel lark --machine <machineId> (--cwd <cwd> | --session <sessionId>) [--agent codex] [--model <model>] --json
|
|
@@ -175,6 +154,16 @@ Schedule v1 is daemon-local repeat automation. Runs use normal Relay admission
|
|
|
175
154
|
with deterministic requestId/turnId per occurrence. Offline due times are marked
|
|
176
155
|
missed and are never auto-caught-up. Commands that take a scheduleId auto-locate
|
|
177
156
|
the owning online daemon when --machine is omitted.
|
|
157
|
+
`,
|
|
158
|
+
release: `Usage:
|
|
159
|
+
happy-elves release profile list --json
|
|
160
|
+
happy-elves release profile show [--profile happy-elves] --json
|
|
161
|
+
happy-elves release profile set <name> --release-tag <tag[,tag]> [--reviewer-tag <tag[,tag]>] [--dogfood-tag <tag[,tag]>] --json
|
|
162
|
+
happy-elves release resolve --profile happy-elves --json
|
|
163
|
+
happy-elves release notify --profile happy-elves [--text 发布] [--detach] [--timeout 30m] --json
|
|
164
|
+
|
|
165
|
+
Release routing uses session tags. notify only sends a short prompt to the
|
|
166
|
+
resolved Release Session; it does not run a release runner or arbitrary shell.
|
|
178
167
|
`,
|
|
179
168
|
loop: `Usage:
|
|
180
169
|
happy-elves loop create <sessionId> [--every 15m] (--prompt <text> | --prompt-file <path>) [--stop-on blocked] --json
|
|
@@ -230,15 +219,16 @@ Core commands:
|
|
|
230
219
|
machine directory <machineId> [--path <path>] [--json]
|
|
231
220
|
|
|
232
221
|
session list [--machine <machineId>] [--cwd <path>] [--limit 20] [--json]
|
|
233
|
-
session create --machine <machineId> [--agent codex] [--cwd <path>] [--name <name>]
|
|
234
|
-
session tag add <sessionId> --tag <tag> --json
|
|
235
|
-
session tag remove <sessionId> --tag <tag> --json
|
|
222
|
+
session create --machine <machineId> [--agent codex] [--cwd <path>] [--name <name>] --json
|
|
236
223
|
session history --machine <machineId> [--cwd <path>] [--limit 20] --json
|
|
237
224
|
session continue <runtimeSessionId> --machine <machineId> --json
|
|
238
225
|
session repair-binding <sessionId> [--runtime-session <runtimeSessionId>] --json
|
|
239
226
|
session status <sessionId> [--verbose] [--json]
|
|
240
227
|
session diagnose <sessionId> [--limit 200] [--runtime-limit 500] [--repair-head] [--json]
|
|
241
228
|
session close <sessionId> [--reason <reason>] --json
|
|
229
|
+
session tag add <sessionId> --tag <tag> --json
|
|
230
|
+
release resolve --profile happy-elves --json
|
|
231
|
+
release notify --profile happy-elves --json
|
|
242
232
|
|
|
243
233
|
turn list <sessionId> [--limit 10] [--json]
|
|
244
234
|
turn status <sessionId> <turnId> [--json]
|
|
@@ -246,7 +236,7 @@ Core commands:
|
|
|
246
236
|
turn wait <sessionId> <turnId> [--timeout 1000s] [--json]
|
|
247
237
|
turn result <sessionId> [<turnId>] [--json]
|
|
248
238
|
turn reconcile <sessionId> [turnId] --json
|
|
249
|
-
turn recover <sessionId> [turnId] --text <continuation> --confirm-risk [--
|
|
239
|
+
turn recover <sessionId> [turnId] --text <continuation> --confirm-risk [--json]
|
|
250
240
|
turn cancel <sessionId> <turnId> [--reason <reason>] --json
|
|
251
241
|
turn rewind <sessionId> <turn-or-checkpoint-id> --json
|
|
252
242
|
turn fork <sessionId> <turn-or-checkpoint-id> --name <name> [--copy-tags] --json
|
|
@@ -260,12 +250,8 @@ Core commands:
|
|
|
260
250
|
workspace star <sessionId> --json
|
|
261
251
|
workspace pin-cwd --machine <machineId> --cwd <cwd> --json
|
|
262
252
|
|
|
263
|
-
release resolve --profile happy-elves --json
|
|
264
|
-
release notify --profile happy-elves --json
|
|
265
|
-
release start --profile happy-elves --json
|
|
266
|
-
|
|
267
253
|
gateway status --json
|
|
268
|
-
gateway enable --channel
|
|
254
|
+
gateway enable --channel fake --machine <machineId> --cwd <cwd> --json # debug only
|
|
269
255
|
gateway test --conversation <id> --message-id <id> --text <prompt> --json
|
|
270
256
|
|
|
271
257
|
memory save --project <key> --text <fact> --json
|
|
@@ -287,12 +273,12 @@ Common flows:
|
|
|
287
273
|
Discover: machine list --json; session list --machine <machineId> --json
|
|
288
274
|
Continue: session history --machine <machineId> --json; session continue <runtimeSessionId> --machine <machineId> --json
|
|
289
275
|
Execute: turn run <sessionId> --text <prompt> --json; turn result <sessionId> <turnId> --json
|
|
290
|
-
Branch: turn rewind <sessionId> <turnId> --json; turn fork <sessionId> <turnId> --name <name>
|
|
276
|
+
Branch: turn rewind <sessionId> <turnId> --json; turn fork <sessionId> <turnId> --name <name> --json
|
|
291
277
|
|
|
292
278
|
More:
|
|
293
279
|
happy-elves --skill
|
|
294
280
|
happy-elves <domain> --help
|
|
295
|
-
start, status, doctor, collect, config, account, daemon, relay, token, workspace,
|
|
281
|
+
start, status, doctor, collect, config, account, daemon, relay, token, workspace, gateway, memory, schedule, loop.
|
|
296
282
|
`;
|
|
297
283
|
}
|
|
298
284
|
export function skillText() {
|
|
@@ -318,19 +304,6 @@ Recommended agent workflow:
|
|
|
318
304
|
6. turn wait <sessionId> <turnId> --json
|
|
319
305
|
7. turn result <sessionId> <turnId> --json
|
|
320
306
|
|
|
321
|
-
Release / reviewer / dogfood workflow:
|
|
322
|
-
1. Tag the release session once:
|
|
323
|
-
session tag add <sessionId> --tag "Happy Elves" --json
|
|
324
|
-
session tag add <sessionId> --tag "Release Session" --json
|
|
325
|
-
2. Resolve before acting:
|
|
326
|
-
release resolve --profile happy-elves --json
|
|
327
|
-
3. Notify release with the standard short prompt and release permissions:
|
|
328
|
-
release notify --profile happy-elves --json
|
|
329
|
-
4. Start the structured release runner only when explicitly needed:
|
|
330
|
-
release start --profile happy-elves --json
|
|
331
|
-
5. Use hidden sessions for temporary dogfood:
|
|
332
|
-
session create --hidden --source dogfood --tag "Happy Elves" --tag "Dogfood" ...
|
|
333
|
-
|
|
334
307
|
Concepts:
|
|
335
308
|
Loaded session: a Happy Elves control-plane session that can be operated by
|
|
336
309
|
this CLI.
|
|
@@ -60,12 +60,52 @@ export async function listWorkspaceHistoricalSessions(client, input) {
|
|
|
60
60
|
}
|
|
61
61
|
}));
|
|
62
62
|
return {
|
|
63
|
-
sessions: rows
|
|
63
|
+
sessions: await enrichHistoricalLoadedSessionIds(client, rows
|
|
64
64
|
.flatMap((row) => row.sessions)
|
|
65
65
|
.sort((left, right) => right.updatedAt - left.updatedAt || left.runtimeSessionId.localeCompare(right.runtimeSessionId))
|
|
66
|
-
.slice(0, input.limit),
|
|
66
|
+
.slice(0, input.limit)),
|
|
67
67
|
errors: rows.flatMap((row) => row.error ? [row.error] : []),
|
|
68
68
|
machines: rows.map((row) => row.machine),
|
|
69
69
|
};
|
|
70
70
|
}
|
|
71
|
+
async function enrichHistoricalLoadedSessionIds(client, sessions) {
|
|
72
|
+
const snapshot = await client.snapshot();
|
|
73
|
+
const runtimeIdToSession = new Map();
|
|
74
|
+
for (const session of snapshot.sessions) {
|
|
75
|
+
if (session.status === "closed")
|
|
76
|
+
continue;
|
|
77
|
+
const metadata = await client.decodeSessionMetadata(session);
|
|
78
|
+
for (const runtimeSessionId of metadataRuntimeSessionIds(metadata)) {
|
|
79
|
+
const key = `${session.machineId}:${session.agent}:${runtimeSessionId}`;
|
|
80
|
+
const existing = runtimeIdToSession.get(key);
|
|
81
|
+
if (!existing || session.createdAt < existing.createdAt || (session.createdAt === existing.createdAt && session.id < existing.id)) {
|
|
82
|
+
runtimeIdToSession.set(key, session);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return sessions.map((historical) => {
|
|
87
|
+
const loaded = runtimeIdToSession.get(`${historical.machineId}:${historical.agent}:${historical.runtimeSessionId}`);
|
|
88
|
+
return loaded ? { ...historical, loadedSessionId: loaded.id } : historical;
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
function metadataRuntimeSessionIds(metadata) {
|
|
92
|
+
const ids = new Set();
|
|
93
|
+
addRuntimeSessionId(ids, metadata.importedFromRuntimeSessionId);
|
|
94
|
+
const runtime = metadata.runtime;
|
|
95
|
+
if (runtime && typeof runtime === "object" && !Array.isArray(runtime)) {
|
|
96
|
+
const record = runtime;
|
|
97
|
+
addRuntimeSessionId(ids, record.backendSessionId);
|
|
98
|
+
addRuntimeSessionId(ids, record.agentSessionId);
|
|
99
|
+
addRuntimeSessionId(ids, record.acpxRecordId);
|
|
100
|
+
const externalHandle = record.externalHandle;
|
|
101
|
+
if (externalHandle && typeof externalHandle === "object" && !Array.isArray(externalHandle)) {
|
|
102
|
+
addRuntimeSessionId(ids, externalHandle.sessionId);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return ids;
|
|
106
|
+
}
|
|
107
|
+
function addRuntimeSessionId(ids, value) {
|
|
108
|
+
if (typeof value === "string" && value.trim())
|
|
109
|
+
ids.add(value.trim());
|
|
110
|
+
}
|
|
71
111
|
//# sourceMappingURL=workspace.js.map
|
|
@@ -9,7 +9,6 @@ export async function handleMemory({ domain, action, positional, flags }) {
|
|
|
9
9
|
const projectKey = await resolveMemoryProjectKey(client, flags, machineId);
|
|
10
10
|
const result = await client.memory({ machineId, action: "overview", projectKey, mode: parseMemoryMode(flags.mode) ?? "readonly" });
|
|
11
11
|
if (!wantsJson(flags)) {
|
|
12
|
-
printMemoryProject(projectKey);
|
|
13
12
|
const files = result.overview?.files ?? [];
|
|
14
13
|
if (files.length === 0)
|
|
15
14
|
console.log("No memory files.");
|
|
@@ -18,7 +17,7 @@ export async function handleMemory({ domain, action, positional, flags }) {
|
|
|
18
17
|
console.log(`${file.layer} ${file.path} ${file.lineCount} lines ${file.updatedAt}`);
|
|
19
18
|
return true;
|
|
20
19
|
}
|
|
21
|
-
ok(`memory.${action}`,
|
|
20
|
+
ok(`memory.${action}`, result);
|
|
22
21
|
return true;
|
|
23
22
|
}
|
|
24
23
|
if (action === "save" || action === "write") {
|
|
@@ -44,8 +43,7 @@ export async function handleMemory({ domain, action, positional, flags }) {
|
|
|
44
43
|
...(typeof flags.date === "string" ? { date: flags.date } : {}),
|
|
45
44
|
},
|
|
46
45
|
});
|
|
47
|
-
|
|
48
|
-
ok("memory.save", withMemoryProject(result, projectKey));
|
|
46
|
+
ok("memory.save", result);
|
|
49
47
|
return true;
|
|
50
48
|
}
|
|
51
49
|
if (action === "read") {
|
|
@@ -54,11 +52,10 @@ export async function handleMemory({ domain, action, positional, flags }) {
|
|
|
54
52
|
const path = typeof flags.path === "string" ? flags.path : requirePositional(positional[0], "path");
|
|
55
53
|
const result = await client.memory({ machineId, action: "read", projectKey, path });
|
|
56
54
|
if (!wantsJson(flags)) {
|
|
57
|
-
printMemoryProject(projectKey);
|
|
58
55
|
console.log(result.content ?? "");
|
|
59
56
|
return true;
|
|
60
57
|
}
|
|
61
|
-
ok("memory.read",
|
|
58
|
+
ok("memory.read", result);
|
|
62
59
|
return true;
|
|
63
60
|
}
|
|
64
61
|
if (action === "search") {
|
|
@@ -70,7 +67,6 @@ export async function handleMemory({ domain, action, positional, flags }) {
|
|
|
70
67
|
throw new CliError("Invalid --limit", "INVALID_ARGUMENT");
|
|
71
68
|
const result = await client.memory({ machineId, action: "search", projectKey, query, limit });
|
|
72
69
|
if (!wantsJson(flags)) {
|
|
73
|
-
printMemoryProject(projectKey);
|
|
74
70
|
const results = result.results ?? [];
|
|
75
71
|
if (results.length === 0)
|
|
76
72
|
console.log("No matching memory.");
|
|
@@ -84,7 +80,7 @@ export async function handleMemory({ domain, action, positional, flags }) {
|
|
|
84
80
|
}
|
|
85
81
|
return true;
|
|
86
82
|
}
|
|
87
|
-
ok("memory.search",
|
|
83
|
+
ok("memory.search", result);
|
|
88
84
|
return true;
|
|
89
85
|
}
|
|
90
86
|
if (action === "promote") {
|
|
@@ -105,33 +101,17 @@ export async function handleMemory({ domain, action, positional, flags }) {
|
|
|
105
101
|
...(typeof flags.title === "string" ? { title: flags.title } : {}),
|
|
106
102
|
},
|
|
107
103
|
});
|
|
108
|
-
|
|
109
|
-
ok("memory.promote", withMemoryProject(result, projectKey));
|
|
104
|
+
ok("memory.promote", result);
|
|
110
105
|
return true;
|
|
111
106
|
}
|
|
112
107
|
if (action === "reindex" || action === "sync") {
|
|
113
108
|
const machineId = await resolveMemoryMachineId(client, flags);
|
|
114
109
|
const projectKey = await resolveMemoryProjectKey(client, flags, machineId);
|
|
115
|
-
|
|
116
|
-
printMemoryProjectIfHuman(flags, projectKey);
|
|
117
|
-
ok(`memory.${action}`, withMemoryProject(result, projectKey));
|
|
110
|
+
ok(`memory.${action}`, await client.memory({ machineId, action, projectKey, mode: parseMemoryMode(flags.mode) ?? "readonly" }));
|
|
118
111
|
return true;
|
|
119
112
|
}
|
|
120
113
|
return false;
|
|
121
114
|
}
|
|
122
|
-
function withMemoryProject(result, projectKey) {
|
|
123
|
-
if (result && typeof result === "object" && !Array.isArray(result)) {
|
|
124
|
-
return { ...result, projectKey };
|
|
125
|
-
}
|
|
126
|
-
return { result, projectKey };
|
|
127
|
-
}
|
|
128
|
-
function printMemoryProjectIfHuman(flags, projectKey) {
|
|
129
|
-
if (!wantsJson(flags))
|
|
130
|
-
printMemoryProject(projectKey);
|
|
131
|
-
}
|
|
132
|
-
function printMemoryProject(projectKey) {
|
|
133
|
-
console.error(`Memory project: ${projectKey}`);
|
|
134
|
-
}
|
|
135
115
|
async function resolveMemoryMachineId(client, flags) {
|
|
136
116
|
if (typeof flags.machine === "string" && flags.machine.length > 0)
|
|
137
117
|
return flags.machine;
|