@cydm/happy-elves 0.1.0-beta.310 → 0.1.0-beta.311

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.
@@ -1,7 +1,7 @@
1
1
  import fs from "node:fs/promises";
2
2
  import path from "node:path";
3
3
  import { normalizeSessionTags, sessionTagsMatch } from "../../../../packages/shared/dist/index.js";
4
- import { CliError, ControllerClient, DEFAULT_COMMAND_TIMEOUT_MS, compactText, ok, parseDurationMs, readConfig, releaseProfilesPath, wantsJson, } from "./lib/index.js";
4
+ import { CliError, ControllerClient, DEFAULT_COMMAND_TIMEOUT_MS, compactText, ok, parseDurationMs, readConfig, releaseProfilesPath, wantsJson, wantsVerbose, } from "./lib/index.js";
5
5
  const defaultReleaseProfile = {
6
6
  name: "happy-elves",
7
7
  releaseSessionTags: ["Happy Elves", "Release Session"],
@@ -61,7 +61,7 @@ export async function handleRelease({ domain, action, positional, flags }) {
61
61
  ackTimeoutMs: parseDurationMs(flags["ack-timeout"], 15_000),
62
62
  inactivityTimeoutMs: parseDurationMs(flags["inactivity-timeout"] ?? flags["runtime-timeout"], DEFAULT_COMMAND_TIMEOUT_MS),
63
63
  });
64
- printReleaseOutput("release.notify", {
64
+ printReleaseOutput("release.notify", await releaseNotifyOutput(client, {
65
65
  profile: profile.name,
66
66
  releaseTarget,
67
67
  prompt: text,
@@ -70,7 +70,7 @@ export async function handleRelease({ domain, action, positional, flags }) {
70
70
  memoryMode: "off",
71
71
  wait,
72
72
  ...result,
73
- }, flags);
73
+ }, flags), flags);
74
74
  return true;
75
75
  }
76
76
  return false;
@@ -82,6 +82,33 @@ function releaseNotifyText(flags) {
82
82
  const value = typeof flags.text === "string" ? flags.text.trim() : "";
83
83
  return value || "发布";
84
84
  }
85
+ async function releaseNotifyOutput(client, data, flags) {
86
+ if (wantsVerbose(flags))
87
+ return data;
88
+ const decoded = await client.decodeEvents(data.events).catch(() => []);
89
+ const turnEvents = data.turnId ? decoded.filter((event) => event.turnId === data.turnId) : decoded;
90
+ const done = [...turnEvents].reverse().find((event) => event.decoded?.type === "done")?.decoded;
91
+ const finalOutput = turnEvents
92
+ .filter((event) => event.decoded?.type === "text_delta" && event.decoded.stream !== "thought")
93
+ .map((event) => event.decoded?.type === "text_delta" ? event.decoded.text : "")
94
+ .join("");
95
+ return {
96
+ profile: data.profile,
97
+ releaseTarget: data.releaseTarget,
98
+ promptPreview: data.promptPreview,
99
+ permissionMode: data.permissionMode,
100
+ memoryMode: data.memoryMode,
101
+ wait: data.wait,
102
+ requestId: data.requestId,
103
+ sessionId: data.sessionId,
104
+ turnId: data.turnId,
105
+ admission: data.admission,
106
+ dispatch: data.dispatch,
107
+ eventCount: data.events.length,
108
+ ...(done && typeof done === "object" && "status" in done ? { status: done.status } : {}),
109
+ ...(finalOutput ? { finalOutputPreview: compactText(finalOutput, 1200) } : {}),
110
+ };
111
+ }
85
112
  function tagsFromFlagValue(value) {
86
113
  if (typeof value !== "string")
87
114
  return [];
@@ -406,7 +406,7 @@ export async function handleSession({ domain, action, positional, flags }) {
406
406
  const visibleSessions = flags.all === true
407
407
  ? allSessions
408
408
  : (await Promise.all(allSessions.map(async (session) => ({ session, metadata: await client.decodeSessionMetadata(session) }))))
409
- .filter(({ session, metadata }) => session.status !== "closed" && metadata.hiddenFromWorkspace !== true)
409
+ .filter(({ session, metadata }) => session.status !== "closed" && metadata.hiddenFromWorkspace !== true && metadata.source !== "dogfood")
410
410
  .map(({ session }) => session);
411
411
  const { items: sessions, page } = selectWindow(visibleSessions, flags, 20);
412
412
  if (wantsJson(flags) || wantsVerbose(flags)) {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cydm/happy-elves-cli",
3
- "version": "0.1.0-beta.310",
3
+ "version": "0.1.0-beta.311",
4
4
  "private": true,
5
5
  "type": "module"
6
6
  }
@@ -17,6 +17,8 @@ export async function handleCreateSession(ws, config, command) {
17
17
  const metadata = await commandSessionMetadata(config, command.encryptedMetadata);
18
18
  const model = modelFromCommand(command.model ?? metadata?.model);
19
19
  const tags = normalizeSessionTags(metadata?.tags);
20
+ const hiddenFromWorkspace = metadata?.hiddenFromWorkspace === true;
21
+ const source = typeof metadata?.source === "string" && metadata.source.trim() ? metadata.source.trim() : undefined;
20
22
  const runtime = getRuntime(cwd);
21
23
  let handle = await runtime.ensureSession({
22
24
  sessionKey: command.sessionId,
@@ -44,6 +46,8 @@ export async function handleCreateSession(ws, config, command) {
44
46
  name: providerName ?? command.name,
45
47
  ...(model ? { model } : {}),
46
48
  ...(tags.length > 0 ? { tags } : {}),
49
+ ...(hiddenFromWorkspace ? { hiddenFromWorkspace: true } : {}),
50
+ ...(source ? { source } : {}),
47
51
  handle,
48
52
  };
49
53
  sessions.set(command.sessionId, state);
@@ -111,6 +115,15 @@ export async function handleImportHistoricalSession(ws, config, command) {
111
115
  handle,
112
116
  };
113
117
  const importedMetadata = await commandSessionMetadata(config, command.encryptedMetadata);
118
+ const importedTags = normalizeSessionTags(importedMetadata?.tags);
119
+ const importedHiddenFromWorkspace = importedMetadata?.hiddenFromWorkspace === true;
120
+ const importedSource = typeof importedMetadata?.source === "string" && importedMetadata.source.trim() ? importedMetadata.source.trim() : undefined;
121
+ if (importedTags.length > 0)
122
+ state.tags = importedTags;
123
+ if (importedHiddenFromWorkspace)
124
+ state.hiddenFromWorkspace = true;
125
+ if (importedSource)
126
+ state.source = importedSource;
114
127
  sessions.set(command.sessionId, state);
115
128
  const importedAt = new Date().toISOString();
116
129
  const importedMetadataBase = {
@@ -261,9 +274,12 @@ function historicalSessionPage(value) {
261
274
  export async function resumeSession(ws, config, sessionId, requestId, fallback, announceSuccess = true, syncDirection = "auto") {
262
275
  const existing = sessions.get(sessionId);
263
276
  if (existing) {
264
- const hydratedExisting = fallback?.tags && fallback.tags.length > 0
265
- ? { ...existing, tags: fallback.tags }
266
- : existing;
277
+ const hydratedExisting = {
278
+ ...existing,
279
+ ...(fallback?.tags && fallback.tags.length > 0 ? { tags: fallback.tags } : {}),
280
+ ...(fallback?.hiddenFromWorkspace === true ? { hiddenFromWorkspace: true } : {}),
281
+ ...(fallback?.source ? { source: fallback.source } : {}),
282
+ };
267
283
  if (hydratedExisting !== existing)
268
284
  sessions.set(sessionId, hydratedExisting);
269
285
  const refreshed = await refreshRuntimeSessionName(hydratedExisting);
@@ -324,6 +340,8 @@ export async function resumeSession(ws, config, sessionId, requestId, fallback,
324
340
  cwd,
325
341
  name,
326
342
  ...(fallback?.tags && fallback.tags.length > 0 ? { tags: fallback.tags } : {}),
343
+ ...(fallback?.hiddenFromWorkspace === true ? { hiddenFromWorkspace: true } : {}),
344
+ ...(fallback?.source ? { source: fallback.source } : {}),
327
345
  handle,
328
346
  });
329
347
  sessions.set(sessionId, state);
@@ -1,6 +1,6 @@
1
1
  import { type EncryptedEnvelope, type MachineCommand } from "../../../../packages/shared/dist/index.js";
2
2
  import type { DaemonConfig, SessionFallback, SessionMetadata, SessionState } from "../types.js";
3
- export declare function encryptedSessionMetadata(config: DaemonConfig, sessionId: string, state: Pick<SessionState, "agent" | "cwd" | "name" | "handle" | "model" | "tags">, extra: Record<string, unknown>): Promise<EncryptedEnvelope>;
3
+ export declare function encryptedSessionMetadata(config: DaemonConfig, sessionId: string, state: Pick<SessionState, "agent" | "cwd" | "name" | "handle" | "model" | "tags" | "hiddenFromWorkspace" | "source">, extra: Record<string, unknown>): Promise<EncryptedEnvelope>;
4
4
  export declare function commandSessionMetadata(config: DaemonConfig, encryptedMetadata?: EncryptedEnvelope): Promise<SessionMetadata | undefined>;
5
5
  export declare function sessionFallbackFromCommand(config: DaemonConfig, command: Extract<MachineCommand, {
6
6
  type: "machine:prompt" | "machine:resume" | "machine:rewind" | "machine:fork" | "machine:renameSession" | "machine:close";
@@ -6,6 +6,8 @@ export function encryptedSessionMetadata(config, sessionId, state, extra) {
6
6
  name: state.name,
7
7
  ...(state.model ? { model: state.model } : {}),
8
8
  ...(state.tags && state.tags.length > 0 ? { tags: state.tags, tagKeys: sessionTagKeys(state.tags) } : {}),
9
+ ...(state.hiddenFromWorkspace ? { hiddenFromWorkspace: true } : {}),
10
+ ...(state.source ? { source: state.source } : {}),
9
11
  runtime: {
10
12
  backend: state.handle.backend,
11
13
  runtimeSessionName: state.handle.runtimeSessionName,
@@ -41,6 +43,8 @@ export async function sessionFallbackFromCommand(config, command) {
41
43
  name: metadata.name ?? command.sessionId,
42
44
  ...(typeof metadata.model === "string" && metadata.model.trim() ? { model: metadata.model.trim() } : {}),
43
45
  ...(tags.length > 0 ? { tags } : {}),
46
+ ...(metadata.hiddenFromWorkspace === true ? { hiddenFromWorkspace: true } : {}),
47
+ ...(typeof metadata.source === "string" && metadata.source.trim() ? { source: metadata.source.trim() } : {}),
44
48
  emptyRuntimeSession: metadata.emptyRuntimeSession === true,
45
49
  historicalBackfill: historicalBackfillStateFromMetadata(metadata),
46
50
  runtime: metadata.runtime,
@@ -36,6 +36,14 @@ export async function handlePrompt(ws, config, command) {
36
36
  }
37
37
  if (fallback?.tags && fallback.tags.length > 0) {
38
38
  session = { ...session, tags: fallback.tags };
39
+ }
40
+ if (fallback?.hiddenFromWorkspace === true) {
41
+ session = { ...session, hiddenFromWorkspace: true };
42
+ }
43
+ if (fallback?.source) {
44
+ session = { ...session, source: fallback.source };
45
+ }
46
+ if (session !== sessions.get(command.sessionId)) {
39
47
  sessions.set(command.sessionId, session);
40
48
  }
41
49
  if (!claimSessionTurn(command.sessionId, command.requestId, command.turnId, "prompt")) {
@@ -33,6 +33,8 @@ export type SessionState = {
33
33
  name: string;
34
34
  model?: string;
35
35
  tags?: string[];
36
+ hiddenFromWorkspace?: boolean;
37
+ source?: string;
36
38
  handle: RuntimeHandle;
37
39
  historicalBackfill?: HistoricalBackfillState;
38
40
  };
@@ -58,6 +60,8 @@ export type SessionMetadata = {
58
60
  model?: string;
59
61
  tags?: string[];
60
62
  tagKeys?: string[];
63
+ hiddenFromWorkspace?: boolean;
64
+ source?: string;
61
65
  requestedRuntimeName?: string;
62
66
  permissionMode?: PermissionMode;
63
67
  importedFromRuntimeSessionId?: string;
@@ -90,6 +94,8 @@ export type SessionMetadata = {
90
94
  export type SessionFallback = Pick<SessionState, "agent" | "cwd" | "name"> & {
91
95
  model?: string;
92
96
  tags?: string[];
97
+ hiddenFromWorkspace?: boolean;
98
+ source?: string;
93
99
  emptyRuntimeSession?: boolean;
94
100
  historicalBackfill?: HistoricalBackfillState;
95
101
  runtime?: SessionMetadata["runtime"];
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cydm/happy-elves-daemon",
3
- "version": "0.1.0-beta.310",
3
+ "version": "0.1.0-beta.311",
4
4
  "private": true,
5
5
  "type": "module"
6
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cydm/happy-elves",
3
- "version": "0.1.0-beta.310",
3
+ "version": "0.1.0-beta.311",
4
4
  "description": "Remote controller for local coding agents with hosted or self-hosted relay support.",
5
5
  "type": "module",
6
6
  "bin": {