appostle-installer 0.0.20 → 0.0.22

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/dist/appostle.js CHANGED
@@ -3234,7 +3234,9 @@ var BrandEntrySchema = z10.object({
3234
3234
  variables: z10.array(BrandVariableSchema).optional().default([]),
3235
3235
  path: z10.string(),
3236
3236
  modifiedAt: z10.string(),
3237
- size: z10.number()
3237
+ size: z10.number(),
3238
+ /** Raw markdown body (frontmatter stripped). Optional, fed by the scanner. */
3239
+ body: z10.string().optional()
3238
3240
  });
3239
3241
  var BrandFrontmatterSchema = z10.object({
3240
3242
  description: z10.string().optional(),
@@ -3411,6 +3413,22 @@ var BrandGenerateWireframeResponseSchema = z10.object({
3411
3413
  error: z10.string().nullable()
3412
3414
  })
3413
3415
  });
3416
+ var BrandAnalyzePhotographyRequestSchema = z10.object({
3417
+ type: z10.literal("brands/analyze-photography"),
3418
+ requestId: z10.string(),
3419
+ workspaceRoot: z10.string(),
3420
+ brandPath: z10.string(),
3421
+ brief: z10.string(),
3422
+ referenceDescriptions: z10.array(z10.string()).optional()
3423
+ });
3424
+ var BrandAnalyzePhotographyResponseSchema = z10.object({
3425
+ type: z10.literal("brands/analyze-photography/response"),
3426
+ payload: z10.object({
3427
+ requestId: z10.string(),
3428
+ updatedCount: z10.number(),
3429
+ error: z10.string().nullable()
3430
+ })
3431
+ });
3414
3432
  var RightFontEntrySchema = z10.object({
3415
3433
  id: z10.string(),
3416
3434
  name: z10.string(),
@@ -3498,6 +3516,7 @@ var GoogleFontsDownloadResponseSchema = z10.object({
3498
3516
  });
3499
3517
 
3500
3518
  // ../server/src/shared/messages.ts
3519
+ var InitialAgentSnapshotPageLimit = 200;
3501
3520
  var MutableDaemonConfigSchema = z11.object({
3502
3521
  mcp: z11.object({
3503
3522
  injectIntoAgents: z11.boolean()
@@ -5531,6 +5550,7 @@ var SessionInboundMessageSchema = z11.discriminatedUnion("type", [
5531
5550
  BrandGenerateLayoutRequestSchema,
5532
5551
  BrandLayoutQaNextRequestSchema,
5533
5552
  BrandGenerateWireframeRequestSchema,
5553
+ BrandAnalyzePhotographyRequestSchema,
5534
5554
  RightFontLibraryRequestSchema,
5535
5555
  GoogleFontsCatalogRequestSchema,
5536
5556
  GoogleFontsDownloadRequestSchema,
@@ -5990,6 +6010,17 @@ var FetchAgentsResponseMessageSchema = z11.object({
5990
6010
  })
5991
6011
  })
5992
6012
  });
6013
+ var InitialAgentSnapshotMessageSchema = z11.object({
6014
+ type: z11.literal("initial_agent_snapshot"),
6015
+ payload: z11.object({
6016
+ entries: z11.array(
6017
+ z11.object({
6018
+ agent: AgentSnapshotPayloadSchema,
6019
+ project: ProjectPlacementPayloadSchema
6020
+ })
6021
+ )
6022
+ })
6023
+ });
5993
6024
  var FetchWorkspacesResponseMessageSchema = z11.object({
5994
6025
  type: z11.literal("fetch_workspaces_response"),
5995
6026
  payload: z11.object({
@@ -7031,6 +7062,7 @@ var SessionOutboundMessageSchema = z11.discriminatedUnion("type", [
7031
7062
  AgentStreamMessageSchema,
7032
7063
  AgentStatusMessageSchema,
7033
7064
  FetchAgentsResponseMessageSchema,
7065
+ InitialAgentSnapshotMessageSchema,
7034
7066
  FetchWorkspacesResponseMessageSchema,
7035
7067
  OpenProjectResponseMessageSchema,
7036
7068
  StartWorkspaceScriptResponseMessageSchema,
@@ -7155,6 +7187,7 @@ var SessionOutboundMessageSchema = z11.discriminatedUnion("type", [
7155
7187
  BrandGenerateLayoutResponseSchema,
7156
7188
  BrandLayoutQaNextResponseSchema,
7157
7189
  BrandGenerateWireframeResponseSchema,
7190
+ BrandAnalyzePhotographyResponseSchema,
7158
7191
  RightFontLibraryResponseSchema,
7159
7192
  GoogleFontsCatalogResponseSchema,
7160
7193
  GoogleFontsDownloadResponseSchema,
@@ -7364,7 +7397,7 @@ import { exec } from "node:child_process";
7364
7397
  import { promisify as promisify3 } from "util";
7365
7398
  import { join as join14, resolve as resolve9, sep as sep2 } from "path";
7366
7399
  import { homedir as homedir5, hostname as osHostname } from "node:os";
7367
- import { z as z39 } from "zod";
7400
+ import { z as z40 } from "zod";
7368
7401
 
7369
7402
  // ../server/src/server/persisted-config.ts
7370
7403
  import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "node:fs";
@@ -20714,6 +20747,12 @@ ${error.stack ?? ""}` : JSON.stringify(error);
20714
20747
  buildStructuredToolResult(server, tool4, output, input) {
20715
20748
  const normalizedServer = server.toLowerCase();
20716
20749
  const normalizedTool = tool4.toLowerCase();
20750
+ if (normalizedTool === "mcp__playwright__browser_take_screenshot" || normalizedTool === "browser_take_screenshot") {
20751
+ const imageOutput = this.tryInlinePlaywrightScreenshot(output, input);
20752
+ if (imageOutput) {
20753
+ return { output: imageOutput };
20754
+ }
20755
+ }
20717
20756
  if (normalizedServer.includes("bash") || normalizedServer.includes("shell") || normalizedServer.includes("command") || normalizedTool.includes("bash") || normalizedTool.includes("shell") || normalizedTool.includes("command") || input && (typeof input.command === "string" || Array.isArray(input.command))) {
20718
20757
  const command = this.extractCommandText(input ?? {}) ?? "command";
20719
20758
  return {
@@ -20755,8 +20794,46 @@ ${error.stack ?? ""}` : JSON.stringify(error);
20755
20794
  };
20756
20795
  }
20757
20796
  }
20797
+ if (normalizedServer === "playwright" && normalizedTool === "browser_take_screenshot") {
20798
+ const imageDetail = this.tryReadPlaywrightScreenshot(output, input);
20799
+ if (imageDetail) return imageDetail;
20800
+ }
20758
20801
  return void 0;
20759
20802
  }
20803
+ /**
20804
+ * Playwright MCP's `browser_take_screenshot` saves the image to a local file
20805
+ * and returns a markdown link (`[Screenshot of viewport](./file.png)`).
20806
+ * Extract the path, resolve it against the agent CWD, read the bytes, and
20807
+ * return an image ToolCallDetail so the client renders it inline.
20808
+ */
20809
+ tryReadPlaywrightScreenshot(output, input) {
20810
+ let filePath;
20811
+ if (input && typeof input.filename === "string") {
20812
+ filePath = input.filename;
20813
+ }
20814
+ if (!filePath) {
20815
+ const match = output.match(/\[Screenshot[^\]]*\]\(([^)]+)\)/i);
20816
+ if (match?.[1]) {
20817
+ filePath = match[1];
20818
+ }
20819
+ }
20820
+ if (!filePath) return void 0;
20821
+ const cwd = this.config.cwd;
20822
+ if (!cwd) return void 0;
20823
+ const abs = path9.isAbsolute(filePath) ? filePath : path9.resolve(cwd, filePath);
20824
+ try {
20825
+ const buf = fs4.readFileSync(abs);
20826
+ const ext = path9.extname(abs).toLowerCase();
20827
+ const mime = ext === ".jpeg" || ext === ".jpg" ? "image/jpeg" : "image/png";
20828
+ return {
20829
+ type: "image",
20830
+ toolName: "mcp__playwright__browser_take_screenshot",
20831
+ images: [{ mimeType: mime, data: buf.toString("base64") }]
20832
+ };
20833
+ } catch {
20834
+ return void 0;
20835
+ }
20836
+ }
20760
20837
  mapPartialEvent(event, options) {
20761
20838
  if (event.type === "content_block_start") {
20762
20839
  const block = isClaudeContentChunk2(event.content_block) ? event.content_block : null;
@@ -20929,6 +21006,44 @@ ${error.stack ?? ""}` : JSON.stringify(error);
20929
21006
  }
20930
21007
  return input;
20931
21008
  }
21009
+ /**
21010
+ * Playwright MCP returns `### Result\n- [Screenshot of viewport](./foo.png)`
21011
+ * and writes the file to disk instead of inlining the image. Resolve that
21012
+ * path against the agent cwd and turn the file into an Anthropic-style
21013
+ * image content block array, so downstream `extractImageToolDetail`
21014
+ * promotes the tool call to a renderable `image` detail.
21015
+ *
21016
+ * Returns `null` when the path cannot be resolved/read safely; the caller
21017
+ * then falls back to the default text output behavior.
21018
+ */
21019
+ tryInlinePlaywrightScreenshot(output, input) {
21020
+ const cwd = this.config.cwd;
21021
+ if (!cwd) return null;
21022
+ let relPath;
21023
+ if (input && typeof input.filename === "string" && input.filename.length > 0) {
21024
+ relPath = input.filename;
21025
+ } else {
21026
+ const match = output.match(/\[Screenshot[^\]]*\]\(([^)]+)\)/);
21027
+ if (match?.[1]) {
21028
+ relPath = match[1];
21029
+ }
21030
+ }
21031
+ if (!relPath) return null;
21032
+ const resolved = path9.resolve(cwd, relPath);
21033
+ const cwdReal = path9.resolve(cwd);
21034
+ if (!resolved.startsWith(cwdReal + path9.sep) && resolved !== cwdReal) {
21035
+ return null;
21036
+ }
21037
+ let buf;
21038
+ try {
21039
+ buf = fs4.readFileSync(resolved);
21040
+ } catch {
21041
+ return null;
21042
+ }
21043
+ const ext = path9.extname(resolved).toLowerCase();
21044
+ const mimeType = ext === ".jpg" || ext === ".jpeg" ? "image/jpeg" : ext === ".webp" ? "image/webp" : ext === ".gif" ? "image/gif" : "image/png";
21045
+ return [{ type: "image", mimeType, data: buf.toString("base64") }];
21046
+ }
20932
21047
  areToolInputsEqual(left, right) {
20933
21048
  if (!left) {
20934
21049
  return false;
@@ -34959,10 +35074,12 @@ async function readBrandsFromDir(scope, dir) {
34959
35074
  continue;
34960
35075
  }
34961
35076
  let parsed;
35077
+ let body = "";
34962
35078
  try {
34963
35079
  const text = await fs11.readFile(fullPath, "utf8");
34964
- const { rawFrontmatterLines, hadFrontmatter } = parseBrandFile(text);
35080
+ const { rawFrontmatterLines, body: parsedBody, hadFrontmatter } = parseBrandFile(text);
34965
35081
  parsed = hadFrontmatter ? parseFrontmatter2(rawFrontmatterLines) : { description: "", variables: [] };
35082
+ body = parsedBody;
34966
35083
  } catch {
34967
35084
  parsed = { description: "", variables: [] };
34968
35085
  }
@@ -34974,7 +35091,8 @@ async function readBrandsFromDir(scope, dir) {
34974
35091
  variables: parsed.variables,
34975
35092
  path: fullPath,
34976
35093
  modifiedAt: stat5.mtime.toISOString(),
34977
- size: stat5.size
35094
+ size: stat5.size,
35095
+ body
34978
35096
  });
34979
35097
  }
34980
35098
  results.sort((a, b) => a.name.localeCompare(b.name));
@@ -35413,11 +35531,132 @@ async function generateAndApplyBrandTokens(options) {
35413
35531
  return { generatedCount: acceptedUpdates.size };
35414
35532
  }
35415
35533
 
35534
+ // ../server/src/server/brand/photography-analyzer.ts
35535
+ import { z as z38 } from "zod";
35536
+ var PhotographyResponseSchema = z38.object({
35537
+ dna: z38.string().min(1),
35538
+ dials: z38.record(z38.string(), z38.string())
35539
+ });
35540
+ function buildPrompt3(args) {
35541
+ const dialLines = args.selectVars.map((v) => {
35542
+ const options = (v.options ?? []).join(", ");
35543
+ return `- ${v.key} (${v.label || v.key}): current="${v.value || "(unset)"}" options=[${options}]`;
35544
+ }).join("\n");
35545
+ const refSection = args.referenceDescriptions.length > 0 ? [
35546
+ "",
35547
+ "Reference image filenames/descriptions provided by the user:",
35548
+ ...args.referenceDescriptions.map((r) => `- ${r}`)
35549
+ ].join("\n") : "";
35550
+ return [
35551
+ "You are a photography director analyzing a brand's photographic identity.",
35552
+ "The user has provided a brief describing the visual direction they want.",
35553
+ "Your job is to:",
35554
+ "1. Write a rich, specific Style DNA (2-3 sentences describing the photographic",
35555
+ " identity in concrete visual terms \u2014 lighting quality, tonal mood, depth",
35556
+ " characteristics, color rendering. No marketing fluff.)",
35557
+ "2. Pre-dial every camera control to match that style direction.",
35558
+ " ONLY use values that appear in the options list for each dial.",
35559
+ "",
35560
+ "User brief:",
35561
+ args.brief,
35562
+ refSection,
35563
+ "",
35564
+ "Camera dials (key, current value, valid options):",
35565
+ dialLines,
35566
+ "",
35567
+ "Return JSON only with the shape:",
35568
+ '{ "dna": "Rich style DNA description...", "dials": { "key": "value", ... } }',
35569
+ "",
35570
+ "Rules:",
35571
+ "- The dna field must be a non-empty string, 2-3 sentences.",
35572
+ "- Every value in dials must be one of the listed options for that key.",
35573
+ "- Include ALL dial keys in dials, even if you keep the current value.",
35574
+ "- Do not invent new keys. Do not output anything outside the JSON."
35575
+ ].filter((line) => line !== "").join("\n");
35576
+ }
35577
+ async function analyzeAndApplyPhotographyStyle(options) {
35578
+ const { agentManager, workspaceRoot, brandPath, brief, referenceDescriptions, logger } = options;
35579
+ const brands = await listBrands({ workspaceRoot });
35580
+ const photoBrand = brands.find((b) => b.path === brandPath) ?? null;
35581
+ if (!photoBrand) {
35582
+ throw new Error(`Brand file not found at ${brandPath}`);
35583
+ }
35584
+ const allVars = photoBrand.variables;
35585
+ const selectVars = allVars.filter(
35586
+ (v) => v.type === "select" && v.options && v.options.length > 0
35587
+ );
35588
+ if (selectVars.length === 0) {
35589
+ throw new Error("No camera dials found in photography brand file");
35590
+ }
35591
+ const validOptions = /* @__PURE__ */ new Map();
35592
+ for (const v of selectVars) {
35593
+ validOptions.set(v.key, new Set(v.options ?? []));
35594
+ }
35595
+ const agentPrompt = buildPrompt3({
35596
+ brief,
35597
+ referenceDescriptions: referenceDescriptions ?? [],
35598
+ selectVars
35599
+ });
35600
+ let response;
35601
+ try {
35602
+ response = await generateStructuredAgentResponseWithFallback({
35603
+ manager: agentManager,
35604
+ cwd: workspaceRoot,
35605
+ prompt: agentPrompt,
35606
+ schema: PhotographyResponseSchema,
35607
+ schemaName: "PhotographyAnalysis",
35608
+ maxRetries: 2,
35609
+ providers: DEFAULT_STRUCTURED_GENERATION_PROVIDERS,
35610
+ agentConfigOverrides: {
35611
+ title: "Photography style analyzer",
35612
+ internal: true
35613
+ }
35614
+ });
35615
+ } catch (error) {
35616
+ if (error instanceof StructuredAgentResponseError || error instanceof StructuredAgentFallbackError) {
35617
+ logger.warn({ err: error, brandPath }, "Structured photography analysis failed");
35618
+ throw new Error("Photography analysis failed \u2014 the agent did not return valid JSON");
35619
+ }
35620
+ throw error;
35621
+ }
35622
+ const acceptedUpdates = /* @__PURE__ */ new Map();
35623
+ for (const [key, value] of Object.entries(response.dials)) {
35624
+ if (typeof value !== "string") continue;
35625
+ const trimmed = value.trim();
35626
+ const opts = validOptions.get(key);
35627
+ if (!opts) continue;
35628
+ if (!opts.has(trimmed)) continue;
35629
+ acceptedUpdates.set(key, trimmed);
35630
+ }
35631
+ acceptedUpdates.set("photo.dna", response.dna);
35632
+ acceptedUpdates.set("photo.brief", brief);
35633
+ const nextVariables = allVars.map((v) => {
35634
+ const update = acceptedUpdates.get(v.key);
35635
+ if (update === void 0) return v;
35636
+ return { ...v, value: update };
35637
+ });
35638
+ await writeBrandFrontmatter(
35639
+ {
35640
+ path: brandPath,
35641
+ frontmatter: {
35642
+ description: photoBrand.description,
35643
+ variables: nextVariables
35644
+ }
35645
+ },
35646
+ workspaceRoot
35647
+ );
35648
+ logger.info(
35649
+ { brandPath, updatedCount: acceptedUpdates.size },
35650
+ "photography-analyzer: applied style analysis"
35651
+ );
35652
+ return { updatedCount: acceptedUpdates.size };
35653
+ }
35654
+
35416
35655
  // ../server/src/server/brand/layout-generator.ts
35417
35656
  import { promises as fs12 } from "node:fs";
35418
35657
  import path20 from "node:path";
35419
35658
  import { fileURLToPath as fileURLToPath2 } from "node:url";
35420
- import { z as z38 } from "zod";
35659
+ import { z as z39 } from "zod";
35421
35660
  var QA_FILENAME = "layout-qa.md";
35422
35661
  var PROMPT_FILENAME = "layout-prompt.md";
35423
35662
  var MAX_LOOKUP_LEVELS = 10;
@@ -35452,34 +35691,34 @@ async function writeRoleFile(workspaceRoot, content) {
35452
35691
  await fs12.mkdir(path20.dirname(filePath), { recursive: true });
35453
35692
  await fs12.writeFile(filePath, content, "utf8");
35454
35693
  }
35455
- var QaNextResponseSchema = z38.object({
35456
- done: z38.boolean(),
35457
- question: z38.string().optional(),
35458
- options: z38.array(z38.string()).optional(),
35459
- roleDocument: z38.string().optional()
35460
- });
35461
- var RefinementResponseSchema = z38.object({
35462
- roleDocument: z38.string()
35463
- });
35464
- var WireframeBlockSchema = z38.object({
35465
- type: z38.enum(["headline", "subheadline", "text", "image", "cta", "spacer"]),
35466
- widthFraction: z38.number(),
35467
- heightVh: z38.number()
35468
- });
35469
- var WireframeSectionSchema = z38.object({
35470
- type: z38.enum(["hero", "features", "content", "cta", "footer", "divider"]),
35471
- widthMode: z38.enum(["full-bleed", "contained"]),
35472
- heightVh: z38.number(),
35473
- arrangement: z38.enum(["single-column", "split", "asymmetric-grid", "bento", "stacked"]),
35474
- blocks: z38.array(WireframeBlockSchema),
35475
- bg: z38.enum(["neutral", "alt", "accent", "image"]),
35476
- gapAfterVh: z38.number()
35477
- });
35478
- var WireframeDataSchema = z38.object({
35479
- viewport: z38.object({ width: z38.number(), height: z38.number() }),
35480
- maxWidth: z38.number(),
35481
- pageBg: z38.string(),
35482
- sections: z38.array(WireframeSectionSchema)
35694
+ var QaNextResponseSchema = z39.object({
35695
+ done: z39.boolean(),
35696
+ question: z39.string().optional(),
35697
+ options: z39.array(z39.string()).optional(),
35698
+ roleDocument: z39.string().optional()
35699
+ });
35700
+ var RefinementResponseSchema = z39.object({
35701
+ roleDocument: z39.string()
35702
+ });
35703
+ var WireframeBlockSchema = z39.object({
35704
+ type: z39.enum(["headline", "subheadline", "text", "image", "cta", "spacer"]),
35705
+ widthFraction: z39.number(),
35706
+ heightVh: z39.number()
35707
+ });
35708
+ var WireframeSectionSchema = z39.object({
35709
+ type: z39.enum(["hero", "features", "content", "cta", "footer", "divider"]),
35710
+ widthMode: z39.enum(["full-bleed", "contained"]),
35711
+ heightVh: z39.number(),
35712
+ arrangement: z39.enum(["single-column", "split", "asymmetric-grid", "bento", "stacked"]),
35713
+ blocks: z39.array(WireframeBlockSchema),
35714
+ bg: z39.enum(["neutral", "alt", "accent", "image"]),
35715
+ gapAfterVh: z39.number()
35716
+ });
35717
+ var WireframeDataSchema = z39.object({
35718
+ viewport: z39.object({ width: z39.number(), height: z39.number() }),
35719
+ maxWidth: z39.number(),
35720
+ pageBg: z39.string(),
35721
+ sections: z39.array(WireframeSectionSchema)
35483
35722
  });
35484
35723
  function buildFullBrandContext(allBrands) {
35485
35724
  const lines = [];
@@ -37154,7 +37393,7 @@ var MIN_STREAMING_SEGMENT_DURATION_MS = 1e3;
37154
37393
  var MIN_STREAMING_SEGMENT_BYTES = Math.round(
37155
37394
  PCM_BYTES_PER_MS * MIN_STREAMING_SEGMENT_DURATION_MS
37156
37395
  );
37157
- var AgentIdSchema2 = z39.string().uuid();
37396
+ var AgentIdSchema2 = z40.string().uuid();
37158
37397
  var VOICE_INTERRUPT_CONFIRMATION_MS = 500;
37159
37398
  var VoiceFeatureUnavailableError = class extends Error {
37160
37399
  constructor(context) {
@@ -37469,9 +37708,35 @@ var Session = class _Session {
37469
37708
  this.emit(message);
37470
37709
  }
37471
37710
  /**
37472
- * Send initial state to client after connection
37711
+ * Push the first page of the agent directory unsolicited right after
37712
+ * `server_info` so the client can paint attention state before its own
37713
+ * paginated `fetch_agents_request` round-trip lands. The regular fetch
37714
+ * still runs in parallel — it establishes the live-update subscription
37715
+ * and paginates beyond the first page. This push exists purely to shave
37716
+ * one relay round-trip from time-to-first-paint.
37717
+ *
37718
+ * Errors are swallowed: a failed push degrades to "wait for the client
37719
+ * to ask," which is still correct.
37473
37720
  */
37474
37721
  async sendInitialState() {
37722
+ try {
37723
+ const synthetic = {
37724
+ type: "fetch_agents_request",
37725
+ requestId: "internal:initial-snapshot",
37726
+ filter: { includeArchived: true },
37727
+ page: { limit: InitialAgentSnapshotPageLimit }
37728
+ };
37729
+ const { entries } = await this.listFetchAgentsEntries(synthetic);
37730
+ this.emit({
37731
+ type: "initial_agent_snapshot",
37732
+ payload: { entries }
37733
+ });
37734
+ } catch (error) {
37735
+ this.sessionLogger.warn(
37736
+ { err: error },
37737
+ "Failed to push initial agent snapshot \u2014 client will fall back to fetch_agents_request"
37738
+ );
37739
+ }
37475
37740
  }
37476
37741
  /**
37477
37742
  * Normalize a user prompt (with optional image metadata) for AgentManager
@@ -38509,6 +38774,9 @@ var Session = class _Session {
38509
38774
  case "brands/generate-wireframe":
38510
38775
  await this.handleBrandGenerateWireframeRequest(msg);
38511
38776
  break;
38777
+ case "brands/analyze-photography":
38778
+ await this.handleBrandAnalyzePhotographyRequest(msg);
38779
+ break;
38512
38780
  case "rightfont/library":
38513
38781
  await this.handleRightFontLibraryRequest(msg);
38514
38782
  break;
@@ -40168,8 +40436,8 @@ var Session = class _Session {
40168
40436
  }
40169
40437
  async generateCommitMessage(cwd) {
40170
40438
  const files = await listUncommittedFiles(cwd);
40171
- const schema = z39.object({
40172
- message: z39.string().min(1).max(100).describe(
40439
+ const schema = z40.object({
40440
+ message: z40.string().min(1).max(100).describe(
40173
40441
  "Short feature-level summary, lowercase, imperative mood, no trailing period, no filename references."
40174
40442
  )
40175
40443
  });
@@ -40214,9 +40482,9 @@ var Session = class _Session {
40214
40482
  },
40215
40483
  { appostleHome: this.appostleHome }
40216
40484
  );
40217
- const schema = z39.object({
40218
- title: z39.string().min(1).max(72),
40219
- body: z39.string().min(1)
40485
+ const schema = z40.object({
40486
+ title: z40.string().min(1).max(72),
40487
+ body: z40.string().min(1)
40220
40488
  });
40221
40489
  const fileList = diff.structured && diff.structured.length > 0 ? [
40222
40490
  "Files changed:",
@@ -45708,6 +45976,38 @@ ${details}`.trim());
45708
45976
  });
45709
45977
  }
45710
45978
  }
45979
+ async handleBrandAnalyzePhotographyRequest(request) {
45980
+ const { requestId, workspaceRoot, brandPath, brief, referenceDescriptions } = request;
45981
+ try {
45982
+ const result = await analyzeAndApplyPhotographyStyle({
45983
+ agentManager: this.agentManager,
45984
+ workspaceRoot: expandTilde(workspaceRoot),
45985
+ brandPath: expandTilde(brandPath),
45986
+ brief,
45987
+ referenceDescriptions,
45988
+ logger: this.sessionLogger
45989
+ });
45990
+ this.emit({
45991
+ type: "brands/analyze-photography/response",
45992
+ payload: {
45993
+ requestId,
45994
+ updatedCount: result.updatedCount,
45995
+ error: null
45996
+ }
45997
+ });
45998
+ } catch (error) {
45999
+ const message = error instanceof Error ? error.message : String(error);
46000
+ this.sessionLogger.error({ err: error, brandPath }, "Failed to analyze photography style");
46001
+ this.emit({
46002
+ type: "brands/analyze-photography/response",
46003
+ payload: {
46004
+ requestId,
46005
+ updatedCount: 0,
46006
+ error: message
46007
+ }
46008
+ });
46009
+ }
46010
+ }
45711
46011
  async handleRightFontLibraryRequest(request) {
45712
46012
  const { requestId, libraryPath } = request;
45713
46013
  try {
@@ -46269,7 +46569,7 @@ import webpush from "web-push";
46269
46569
  import webpush2 from "web-push";
46270
46570
 
46271
46571
  // ../server/src/server/speech/providers/local/sherpa/model-catalog.ts
46272
- import { z as z40 } from "zod";
46572
+ import { z as z41 } from "zod";
46273
46573
  var SHERPA_ONNX_MODEL_CATALOG = {
46274
46574
  "zipformer-bilingual-zh-en-2023-02-20": {
46275
46575
  kind: "stt-online",
@@ -46362,7 +46662,7 @@ function buildAliasMap(modelIds) {
46362
46662
  }
46363
46663
  function createAliasedModelIdSchema(params) {
46364
46664
  const validIds = new Set(params.modelIds);
46365
- return z40.string().trim().toLowerCase().refine(
46665
+ return z41.string().trim().toLowerCase().refine(
46366
46666
  (value) => validIds.has(value) || Object.prototype.hasOwnProperty.call(params.aliases, value),
46367
46667
  {
46368
46668
  message: "Invalid model id"
@@ -46393,20 +46693,20 @@ import { v4 as uuidv410 } from "uuid";
46393
46693
  import { v4 as uuidv411 } from "uuid";
46394
46694
 
46395
46695
  // ../server/src/server/speech/providers/openai/config.ts
46396
- import { z as z41 } from "zod";
46696
+ import { z as z42 } from "zod";
46397
46697
  var DEFAULT_OPENAI_REALTIME_TRANSCRIPTION_MODEL = "gpt-4o-transcribe";
46398
46698
  var DEFAULT_OPENAI_TTS_MODEL = "tts-1";
46399
- var OpenAiTtsVoiceSchema = z41.enum(["alloy", "echo", "fable", "onyx", "nova", "shimmer"]);
46400
- var OpenAiTtsModelSchema = z41.enum(["tts-1", "tts-1-hd"]);
46401
- var NumberLikeSchema = z41.union([z41.number(), z41.string().trim().min(1)]);
46402
- var OptionalFiniteNumberSchema = NumberLikeSchema.pipe(z41.coerce.number().finite()).optional();
46403
- var OptionalTrimmedStringSchema = z41.string().trim().optional().transform((value) => value && value.length > 0 ? value : void 0);
46404
- var OpenAiSpeechResolutionSchema = z41.object({
46699
+ var OpenAiTtsVoiceSchema = z42.enum(["alloy", "echo", "fable", "onyx", "nova", "shimmer"]);
46700
+ var OpenAiTtsModelSchema = z42.enum(["tts-1", "tts-1-hd"]);
46701
+ var NumberLikeSchema = z42.union([z42.number(), z42.string().trim().min(1)]);
46702
+ var OptionalFiniteNumberSchema = NumberLikeSchema.pipe(z42.coerce.number().finite()).optional();
46703
+ var OptionalTrimmedStringSchema = z42.string().trim().optional().transform((value) => value && value.length > 0 ? value : void 0);
46704
+ var OpenAiSpeechResolutionSchema = z42.object({
46405
46705
  apiKey: OptionalTrimmedStringSchema,
46406
46706
  sttConfidenceThreshold: OptionalFiniteNumberSchema,
46407
46707
  sttModel: OptionalTrimmedStringSchema,
46408
- ttsVoice: z41.string().trim().toLowerCase().pipe(OpenAiTtsVoiceSchema).default("alloy"),
46409
- ttsModel: z41.string().trim().toLowerCase().pipe(OpenAiTtsModelSchema).default(DEFAULT_OPENAI_TTS_MODEL),
46708
+ ttsVoice: z42.string().trim().toLowerCase().pipe(OpenAiTtsVoiceSchema).default("alloy"),
46709
+ ttsModel: z42.string().trim().toLowerCase().pipe(OpenAiTtsModelSchema).default(DEFAULT_OPENAI_TTS_MODEL),
46410
46710
  realtimeTranscriptionModel: OptionalTrimmedStringSchema.default(
46411
46711
  DEFAULT_OPENAI_REALTIME_TRANSCRIPTION_MODEL
46412
46712
  )
@@ -46451,177 +46751,177 @@ import { v4 } from "uuid";
46451
46751
  import OpenAI2 from "openai";
46452
46752
 
46453
46753
  // ../server/src/server/agent/agent-storage.ts
46454
- import { z as z42 } from "zod";
46455
- var SERIALIZABLE_CONFIG_SCHEMA = z42.object({
46456
- title: z42.string().nullable().optional(),
46457
- modeId: z42.string().nullable().optional(),
46458
- model: z42.string().nullable().optional(),
46459
- thinkingOptionId: z42.string().nullable().optional(),
46460
- featureValues: z42.record(z42.unknown()).nullable().optional(),
46461
- extra: z42.record(z42.any()).nullable().optional(),
46462
- systemPrompt: z42.string().nullable().optional(),
46463
- mcpServers: z42.record(z42.any()).nullable().optional()
46754
+ import { z as z43 } from "zod";
46755
+ var SERIALIZABLE_CONFIG_SCHEMA = z43.object({
46756
+ title: z43.string().nullable().optional(),
46757
+ modeId: z43.string().nullable().optional(),
46758
+ model: z43.string().nullable().optional(),
46759
+ thinkingOptionId: z43.string().nullable().optional(),
46760
+ featureValues: z43.record(z43.unknown()).nullable().optional(),
46761
+ extra: z43.record(z43.any()).nullable().optional(),
46762
+ systemPrompt: z43.string().nullable().optional(),
46763
+ mcpServers: z43.record(z43.any()).nullable().optional()
46464
46764
  }).nullable().optional();
46465
- var PERSISTENCE_HANDLE_SCHEMA = z42.object({
46466
- provider: z42.string(),
46467
- sessionId: z42.string(),
46468
- nativeHandle: z42.any().optional(),
46469
- metadata: z42.record(z42.any()).optional()
46765
+ var PERSISTENCE_HANDLE_SCHEMA = z43.object({
46766
+ provider: z43.string(),
46767
+ sessionId: z43.string(),
46768
+ nativeHandle: z43.any().optional(),
46769
+ metadata: z43.record(z43.any()).optional()
46470
46770
  }).nullable().optional();
46471
- var STORED_AGENT_SCHEMA = z42.object({
46472
- id: z42.string(),
46473
- provider: z42.string(),
46474
- cwd: z42.string(),
46475
- createdAt: z42.string(),
46476
- updatedAt: z42.string(),
46477
- lastActivityAt: z42.string().optional(),
46478
- lastUserMessageAt: z42.string().nullable().optional(),
46479
- title: z42.string().nullable().optional(),
46480
- labels: z42.record(z42.string()).default({}),
46771
+ var STORED_AGENT_SCHEMA = z43.object({
46772
+ id: z43.string(),
46773
+ provider: z43.string(),
46774
+ cwd: z43.string(),
46775
+ createdAt: z43.string(),
46776
+ updatedAt: z43.string(),
46777
+ lastActivityAt: z43.string().optional(),
46778
+ lastUserMessageAt: z43.string().nullable().optional(),
46779
+ title: z43.string().nullable().optional(),
46780
+ labels: z43.record(z43.string()).default({}),
46481
46781
  lastStatus: AgentStatusSchema.default("closed"),
46482
- lastModeId: z42.string().nullable().optional(),
46782
+ lastModeId: z43.string().nullable().optional(),
46483
46783
  config: SERIALIZABLE_CONFIG_SCHEMA,
46484
- runtimeInfo: z42.object({
46485
- provider: z42.string(),
46486
- sessionId: z42.string().nullable(),
46487
- model: z42.string().nullable().optional(),
46488
- thinkingOptionId: z42.string().nullable().optional(),
46489
- modeId: z42.string().nullable().optional(),
46490
- extra: z42.record(z42.unknown()).optional()
46784
+ runtimeInfo: z43.object({
46785
+ provider: z43.string(),
46786
+ sessionId: z43.string().nullable(),
46787
+ model: z43.string().nullable().optional(),
46788
+ thinkingOptionId: z43.string().nullable().optional(),
46789
+ modeId: z43.string().nullable().optional(),
46790
+ extra: z43.record(z43.unknown()).optional()
46491
46791
  }).optional(),
46492
- features: z42.array(AgentFeatureSchema).optional(),
46792
+ features: z43.array(AgentFeatureSchema).optional(),
46493
46793
  persistence: PERSISTENCE_HANDLE_SCHEMA,
46494
- lastError: z42.string().nullable().optional(),
46495
- requiresAttention: z42.boolean().optional(),
46496
- attentionReason: z42.enum(["finished", "error", "permission"]).nullable().optional(),
46497
- attentionTimestamp: z42.string().nullable().optional(),
46498
- internal: z42.boolean().optional(),
46499
- archivedAt: z42.string().nullable().optional(),
46794
+ lastError: z43.string().nullable().optional(),
46795
+ requiresAttention: z43.boolean().optional(),
46796
+ attentionReason: z43.enum(["finished", "error", "permission"]).nullable().optional(),
46797
+ attentionTimestamp: z43.string().nullable().optional(),
46798
+ internal: z43.boolean().optional(),
46799
+ archivedAt: z43.string().nullable().optional(),
46500
46800
  // Fork lineage (optional for backward compat with pre-fork records).
46501
- parentAgentId: z42.string().optional(),
46502
- forkedFromMessageUuid: z42.string().optional(),
46801
+ parentAgentId: z43.string().optional(),
46802
+ forkedFromMessageUuid: z43.string().optional(),
46503
46803
  // Multi-tenant session isolation: the auth-server user-id that created
46504
46804
  // (and therefore owns) this agent + the additive ACL of other users
46505
46805
  // granted access. Both optional/null-default for backward compatibility
46506
46806
  // with pre-Phase-2c records — those load with `null` owner and stay
46507
46807
  // visible to every connecting user (matches today's single-tenant
46508
46808
  // behavior). Set on new agents at create time via Session.ownerUserId.
46509
- ownerUserId: z42.string().nullable().optional(),
46510
- sharedWithUserIds: z42.array(z42.string()).default([]),
46809
+ ownerUserId: z43.string().nullable().optional(),
46810
+ sharedWithUserIds: z43.array(z43.string()).default([]),
46511
46811
  // Owner's display username — needed on resume to route to the correct
46512
46812
  // `CLAUDE_CONFIG_DIR` via `ensureClaudeProfile(username)` for agents
46513
46813
  // created by a shared (non-owner) user. Without this, a resumed shared-
46514
46814
  // user agent would silently fall back to the daemon owner's Claude
46515
46815
  // profile/subscription. Optional — pre-Phase-3 records rehydrate without
46516
46816
  // per-user profile routing.
46517
- ownerUsername: z42.string().optional()
46817
+ ownerUsername: z43.string().optional()
46518
46818
  });
46519
46819
 
46520
46820
  // ../server/src/server/agent/mcp-server.ts
46521
46821
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
46522
- import { z as z43 } from "zod";
46523
- var TerminalSummarySchema = z43.object({
46524
- id: z43.string(),
46525
- name: z43.string(),
46526
- cwd: z43.string()
46822
+ import { z as z44 } from "zod";
46823
+ var TerminalSummarySchema = z44.object({
46824
+ id: z44.string(),
46825
+ name: z44.string(),
46826
+ cwd: z44.string()
46527
46827
  });
46528
- var WorktreeSummarySchema = z43.object({
46529
- path: z43.string(),
46530
- createdAt: z43.string(),
46531
- branchName: z43.string().optional(),
46532
- head: z43.string().optional()
46828
+ var WorktreeSummarySchema = z44.object({
46829
+ path: z44.string(),
46830
+ createdAt: z44.string(),
46831
+ branchName: z44.string().optional(),
46832
+ head: z44.string().optional()
46533
46833
  });
46534
46834
 
46535
46835
  // ../server/src/server/loop-service.ts
46536
- import { z as z44 } from "zod";
46836
+ import { z as z45 } from "zod";
46537
46837
  var MAX_VERIFY_OUTPUT_BYTES = 64 * 1024;
46538
- var LoopVerifyPromptSchema = z44.object({
46539
- passed: z44.boolean(),
46540
- reason: z44.string().min(1)
46541
- });
46542
- var LoopLogEntrySchema2 = z44.object({
46543
- seq: z44.number().int().positive(),
46544
- timestamp: z44.string(),
46545
- iteration: z44.number().int().positive().nullable(),
46546
- source: z44.enum(["loop", "worker", "verifier", "verify-check"]),
46547
- level: z44.enum(["info", "error"]),
46548
- text: z44.string()
46549
- });
46550
- var LoopVerifyCheckResultSchema2 = z44.object({
46551
- command: z44.string(),
46552
- exitCode: z44.number().int(),
46553
- passed: z44.boolean(),
46554
- stdout: z44.string(),
46555
- stderr: z44.string(),
46556
- startedAt: z44.string(),
46557
- completedAt: z44.string()
46558
- });
46559
- var LoopVerifyPromptResultSchema2 = z44.object({
46560
- passed: z44.boolean(),
46561
- reason: z44.string(),
46562
- verifierAgentId: z44.string().nullable(),
46563
- startedAt: z44.string(),
46564
- completedAt: z44.string()
46565
- });
46566
- var LoopIterationRecordSchema2 = z44.object({
46567
- index: z44.number().int().positive(),
46568
- workerAgentId: z44.string().nullable(),
46569
- workerStartedAt: z44.string(),
46570
- workerCompletedAt: z44.string().nullable(),
46571
- verifierAgentId: z44.string().nullable(),
46572
- status: z44.enum(["running", "succeeded", "failed", "stopped"]),
46573
- workerOutcome: z44.enum(["completed", "failed", "canceled"]).nullable(),
46574
- failureReason: z44.string().nullable(),
46575
- verifyChecks: z44.array(LoopVerifyCheckResultSchema2),
46838
+ var LoopVerifyPromptSchema = z45.object({
46839
+ passed: z45.boolean(),
46840
+ reason: z45.string().min(1)
46841
+ });
46842
+ var LoopLogEntrySchema2 = z45.object({
46843
+ seq: z45.number().int().positive(),
46844
+ timestamp: z45.string(),
46845
+ iteration: z45.number().int().positive().nullable(),
46846
+ source: z45.enum(["loop", "worker", "verifier", "verify-check"]),
46847
+ level: z45.enum(["info", "error"]),
46848
+ text: z45.string()
46849
+ });
46850
+ var LoopVerifyCheckResultSchema2 = z45.object({
46851
+ command: z45.string(),
46852
+ exitCode: z45.number().int(),
46853
+ passed: z45.boolean(),
46854
+ stdout: z45.string(),
46855
+ stderr: z45.string(),
46856
+ startedAt: z45.string(),
46857
+ completedAt: z45.string()
46858
+ });
46859
+ var LoopVerifyPromptResultSchema2 = z45.object({
46860
+ passed: z45.boolean(),
46861
+ reason: z45.string(),
46862
+ verifierAgentId: z45.string().nullable(),
46863
+ startedAt: z45.string(),
46864
+ completedAt: z45.string()
46865
+ });
46866
+ var LoopIterationRecordSchema2 = z45.object({
46867
+ index: z45.number().int().positive(),
46868
+ workerAgentId: z45.string().nullable(),
46869
+ workerStartedAt: z45.string(),
46870
+ workerCompletedAt: z45.string().nullable(),
46871
+ verifierAgentId: z45.string().nullable(),
46872
+ status: z45.enum(["running", "succeeded", "failed", "stopped"]),
46873
+ workerOutcome: z45.enum(["completed", "failed", "canceled"]).nullable(),
46874
+ failureReason: z45.string().nullable(),
46875
+ verifyChecks: z45.array(LoopVerifyCheckResultSchema2),
46576
46876
  verifyPrompt: LoopVerifyPromptResultSchema2.nullable()
46577
46877
  });
46578
- var LoopRecordSchema2 = z44.object({
46579
- id: z44.string(),
46580
- name: z44.string().nullable(),
46581
- prompt: z44.string(),
46582
- cwd: z44.string(),
46583
- provider: z44.string(),
46584
- model: z44.string().nullable(),
46585
- workerProvider: z44.string().nullable(),
46586
- workerModel: z44.string().nullable(),
46587
- verifierProvider: z44.string().nullable(),
46588
- verifierModel: z44.string().nullable(),
46589
- verifyPrompt: z44.string().nullable(),
46590
- verifyChecks: z44.array(z44.string()),
46591
- archive: z44.boolean(),
46592
- sleepMs: z44.number().int().nonnegative(),
46593
- maxIterations: z44.number().int().positive().nullable(),
46594
- maxTimeMs: z44.number().int().positive().nullable(),
46595
- status: z44.enum(["running", "succeeded", "failed", "stopped"]),
46596
- createdAt: z44.string(),
46597
- updatedAt: z44.string(),
46598
- startedAt: z44.string(),
46599
- completedAt: z44.string().nullable(),
46600
- stopRequestedAt: z44.string().nullable(),
46601
- iterations: z44.array(LoopIterationRecordSchema2),
46602
- logs: z44.array(LoopLogEntrySchema2),
46603
- nextLogSeq: z44.number().int().positive(),
46604
- activeIteration: z44.number().int().positive().nullable(),
46605
- activeWorkerAgentId: z44.string().nullable(),
46606
- activeVerifierAgentId: z44.string().nullable()
46607
- });
46608
- var StoredLoopsSchema = z44.array(LoopRecordSchema2);
46878
+ var LoopRecordSchema2 = z45.object({
46879
+ id: z45.string(),
46880
+ name: z45.string().nullable(),
46881
+ prompt: z45.string(),
46882
+ cwd: z45.string(),
46883
+ provider: z45.string(),
46884
+ model: z45.string().nullable(),
46885
+ workerProvider: z45.string().nullable(),
46886
+ workerModel: z45.string().nullable(),
46887
+ verifierProvider: z45.string().nullable(),
46888
+ verifierModel: z45.string().nullable(),
46889
+ verifyPrompt: z45.string().nullable(),
46890
+ verifyChecks: z45.array(z45.string()),
46891
+ archive: z45.boolean(),
46892
+ sleepMs: z45.number().int().nonnegative(),
46893
+ maxIterations: z45.number().int().positive().nullable(),
46894
+ maxTimeMs: z45.number().int().positive().nullable(),
46895
+ status: z45.enum(["running", "succeeded", "failed", "stopped"]),
46896
+ createdAt: z45.string(),
46897
+ updatedAt: z45.string(),
46898
+ startedAt: z45.string(),
46899
+ completedAt: z45.string().nullable(),
46900
+ stopRequestedAt: z45.string().nullable(),
46901
+ iterations: z45.array(LoopIterationRecordSchema2),
46902
+ logs: z45.array(LoopLogEntrySchema2),
46903
+ nextLogSeq: z45.number().int().positive(),
46904
+ activeIteration: z45.number().int().positive().nullable(),
46905
+ activeWorkerAgentId: z45.string().nullable(),
46906
+ activeVerifierAgentId: z45.string().nullable()
46907
+ });
46908
+ var StoredLoopsSchema = z45.array(LoopRecordSchema2);
46609
46909
 
46610
46910
  // ../server/src/server/quest/store.ts
46611
- import { z as z45 } from "zod";
46612
- var StoredQuestsSchema = z45.array(QuestRecordSchema);
46911
+ import { z as z46 } from "zod";
46912
+ var StoredQuestsSchema = z46.array(QuestRecordSchema);
46613
46913
 
46614
46914
  // ../server/src/server/quest/quest-metadata-generator.ts
46615
- import { z as z46 } from "zod";
46915
+ import { z as z47 } from "zod";
46616
46916
 
46617
46917
  // ../server/src/server/quest/orchestrator-mcp.ts
46618
46918
  import { createSdkMcpServer as createSdkMcpServer2, tool as tool3 } from "@anthropic-ai/claude-agent-sdk";
46619
- import { z as z47 } from "zod";
46919
+ import { z as z48 } from "zod";
46620
46920
  var HANDOFF_INPUT_SHAPE = {
46621
- rolePath: z47.string().min(1).describe(
46921
+ rolePath: z48.string().min(1).describe(
46622
46922
  "Absolute filesystem path to the role .md file the worker should adopt as its system prompt. Must be one of the role file paths listed in your team roster \u2014 do not invent paths."
46623
46923
  ),
46624
- task: z47.string().min(1).describe(
46924
+ task: z48.string().min(1).describe(
46625
46925
  "Concrete, self-contained instruction for the worker. The worker has its own toolbelt and reads the role at rolePath as its system prompt \u2014 write the task as a normal user message describing what to do, what inputs to read, and where to write outputs. Reference the hivemind doc by absolute path if relevant."
46626
46926
  )
46627
46927
  };
@@ -46676,13 +46976,13 @@ var execFileAsync3 = promisify4(execFile3);
46676
46976
  var MAX_VERIFY_OUTPUT_BYTES2 = 64 * 1024;
46677
46977
 
46678
46978
  // ../server/src/shared/connection-offer.ts
46679
- import { z as z48 } from "zod";
46680
- var ConnectionOfferV2Schema = z48.object({
46681
- v: z48.literal(2),
46682
- serverId: z48.string().min(1),
46683
- daemonPublicKeyB64: z48.string().min(1),
46684
- relay: z48.object({
46685
- endpoint: z48.string().min(1)
46979
+ import { z as z49 } from "zod";
46980
+ var ConnectionOfferV2Schema = z49.object({
46981
+ v: z49.literal(2),
46982
+ serverId: z49.string().min(1),
46983
+ daemonPublicKeyB64: z49.string().min(1),
46984
+ relay: z49.object({
46985
+ endpoint: z49.string().min(1)
46686
46986
  })
46687
46987
  });
46688
46988
 
@@ -46716,21 +47016,21 @@ function isRelayClientWebSocketUrl(url) {
46716
47016
 
46717
47017
  // ../server/src/server/config.ts
46718
47018
  import path22 from "node:path";
46719
- import { z as z52 } from "zod";
47019
+ import { z as z53 } from "zod";
46720
47020
 
46721
47021
  // ../server/src/server/speech/speech-config-resolver.ts
46722
- import { z as z51 } from "zod";
47022
+ import { z as z52 } from "zod";
46723
47023
 
46724
47024
  // ../server/src/server/speech/providers/local/config.ts
46725
47025
  import path21 from "node:path";
46726
- import { z as z49 } from "zod";
47026
+ import { z as z50 } from "zod";
46727
47027
  var DEFAULT_LOCAL_MODELS_SUBDIR = path21.join("models", "local-speech");
46728
- var NumberLikeSchema2 = z49.union([z49.number(), z49.string().trim().min(1)]);
46729
- var OptionalFiniteNumberSchema2 = NumberLikeSchema2.pipe(z49.coerce.number().finite()).optional();
46730
- var OptionalIntegerSchema = NumberLikeSchema2.pipe(z49.coerce.number().int()).optional();
46731
- var LocalSpeechResolutionSchema = z49.object({
46732
- includeProviderConfig: z49.boolean(),
46733
- modelsDir: z49.string().trim().min(1),
47028
+ var NumberLikeSchema2 = z50.union([z50.number(), z50.string().trim().min(1)]);
47029
+ var OptionalFiniteNumberSchema2 = NumberLikeSchema2.pipe(z50.coerce.number().finite()).optional();
47030
+ var OptionalIntegerSchema = NumberLikeSchema2.pipe(z50.coerce.number().int()).optional();
47031
+ var LocalSpeechResolutionSchema = z50.object({
47032
+ includeProviderConfig: z50.boolean(),
47033
+ modelsDir: z50.string().trim().min(1),
46734
47034
  dictationLocalSttModel: LocalSttModelIdSchema.default(DEFAULT_LOCAL_STT_MODEL),
46735
47035
  voiceLocalSttModel: LocalSttModelIdSchema.default(DEFAULT_LOCAL_STT_MODEL),
46736
47036
  voiceLocalTtsModel: LocalTtsModelIdSchema.default(DEFAULT_LOCAL_TTS_MODEL),
@@ -46786,17 +47086,17 @@ function resolveLocalSpeechConfig(params) {
46786
47086
  }
46787
47087
 
46788
47088
  // ../server/src/server/speech/speech-types.ts
46789
- import { z as z50 } from "zod";
46790
- var SpeechProviderIdSchema2 = z50.enum(["openai", "local"]);
46791
- var RequestedSpeechProviderSchema = z50.object({
47089
+ import { z as z51 } from "zod";
47090
+ var SpeechProviderIdSchema2 = z51.enum(["openai", "local"]);
47091
+ var RequestedSpeechProviderSchema = z51.object({
46792
47092
  provider: SpeechProviderIdSchema2,
46793
- explicit: z50.boolean(),
46794
- enabled: z50.boolean().optional()
47093
+ explicit: z51.boolean(),
47094
+ enabled: z51.boolean().optional()
46795
47095
  });
46796
47096
 
46797
47097
  // ../server/src/server/speech/speech-config-resolver.ts
46798
- var OptionalSpeechProviderSchema = z51.string().trim().toLowerCase().pipe(SpeechProviderIdSchema2).optional();
46799
- var OptionalBooleanFlagSchema = z51.union([z51.boolean(), z51.string().trim().toLowerCase()]).optional().transform((value) => {
47098
+ var OptionalSpeechProviderSchema = z52.string().trim().toLowerCase().pipe(SpeechProviderIdSchema2).optional();
47099
+ var OptionalBooleanFlagSchema = z52.union([z52.boolean(), z52.string().trim().toLowerCase()]).optional().transform((value) => {
46800
47100
  if (typeof value === "boolean") {
46801
47101
  return value;
46802
47102
  }
@@ -46811,7 +47111,7 @@ var OptionalBooleanFlagSchema = z51.union([z51.boolean(), z51.string().trim().to
46811
47111
  }
46812
47112
  return void 0;
46813
47113
  });
46814
- var RequestedSpeechProvidersSchema = z51.object({
47114
+ var RequestedSpeechProvidersSchema = z52.object({
46815
47115
  dictationStt: OptionalSpeechProviderSchema.default("local"),
46816
47116
  voiceTurnDetection: OptionalSpeechProviderSchema.default("local"),
46817
47117
  voiceStt: OptionalSpeechProviderSchema.default("local"),
@@ -46920,9 +47220,9 @@ function parseBooleanEnv(value) {
46920
47220
  }
46921
47221
  return void 0;
46922
47222
  }
46923
- var OptionalVoiceLlmProviderSchema = z52.union([z52.string(), z52.null(), z52.undefined()]).transform(
47223
+ var OptionalVoiceLlmProviderSchema = z53.union([z53.string(), z53.null(), z53.undefined()]).transform(
46924
47224
  (value) => typeof value === "string" ? value.trim().toLowerCase() : null
46925
- ).pipe(z52.union([AgentProviderSchema, z52.null()]));
47225
+ ).pipe(z53.union([AgentProviderSchema, z53.null()]));
46926
47226
  function parseOptionalVoiceLlmProvider(value) {
46927
47227
  const parsed = OptionalVoiceLlmProviderSchema.safeParse(value);
46928
47228
  return parsed.success ? parsed.data : null;
@@ -47296,6 +47596,9 @@ function createEncryptedTransport(base, daemonPublicKeyB64, logger, staticKeyPai
47296
47596
  throw new Error("Encrypted channel not ready");
47297
47597
  }
47298
47598
  void channel.send(normalizeTransportPayload(data)).catch((error) => {
47599
+ if (closed) {
47600
+ console.error("[relay-e2ee] send failed after transport close:", error);
47601
+ }
47299
47602
  emitError(error);
47300
47603
  });
47301
47604
  },
@@ -50898,6 +51201,20 @@ var DaemonClient = class {
50898
51201
  timeout: 12e4
50899
51202
  });
50900
51203
  }
51204
+ async brandsAnalyzePhotography(options) {
51205
+ return this.sendCorrelatedSessionRequest({
51206
+ requestId: options.requestId,
51207
+ message: {
51208
+ type: "brands/analyze-photography",
51209
+ workspaceRoot: options.workspaceRoot,
51210
+ brandPath: options.brandPath,
51211
+ brief: options.brief,
51212
+ ...options.referenceDescriptions ? { referenceDescriptions: options.referenceDescriptions } : {}
51213
+ },
51214
+ responseType: "brands/analyze-photography/response",
51215
+ timeout: 12e4
51216
+ });
51217
+ }
50901
51218
  onTerminalStreamEvent(handler) {
50902
51219
  this.terminalStreamListeners.add(handler);
50903
51220
  return () => {