appostle-installer 0.0.4 → 0.0.6

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
@@ -454,18 +454,18 @@ function resolveNodePtyPackageRoot() {
454
454
  return null;
455
455
  }
456
456
  }
457
- function ensureExecutableBit(path23) {
458
- if (!existsSync2(path23)) {
457
+ function ensureExecutableBit(path24) {
458
+ if (!existsSync2(path24)) {
459
459
  return;
460
460
  }
461
- const stat5 = statSync(path23);
461
+ const stat5 = statSync(path24);
462
462
  if (!stat5.isFile()) {
463
463
  return;
464
464
  }
465
465
  if ((stat5.mode & 73) === 73) {
466
466
  return;
467
467
  }
468
- chmodSync(path23, stat5.mode | 73);
468
+ chmodSync(path24, stat5.mode | 73);
469
469
  }
470
470
  function ensureNodePtySpawnHelperExecutableForCurrentPlatform(options = {}) {
471
471
  const platform2 = options.platform ?? process.platform;
@@ -547,11 +547,11 @@ function parseGitRevParsePath(stdout) {
547
547
  if (lines.length !== 1) {
548
548
  return null;
549
549
  }
550
- const path23 = lines[0]?.trim() ?? "";
551
- if (!path23 || path23.startsWith("--")) {
550
+ const path24 = lines[0]?.trim() ?? "";
551
+ if (!path24 || path24.startsWith("--")) {
552
552
  return null;
553
553
  }
554
- return path23;
554
+ return path24;
555
555
  }
556
556
  function resolveGitRevParsePath(cwd, stdout) {
557
557
  const parsed = parseGitRevParsePath(stdout);
@@ -1324,9 +1324,9 @@ async function deleteAppostleWorktree({
1324
1324
  }
1325
1325
  }
1326
1326
  }
1327
- async function pathExists(path23) {
1327
+ async function pathExists(path24) {
1328
1328
  try {
1329
- await stat(path23);
1329
+ await stat(path24);
1330
1330
  return true;
1331
1331
  } catch (error) {
1332
1332
  if (error.code === "ENOENT") {
@@ -1335,8 +1335,8 @@ async function pathExists(path23) {
1335
1335
  throw error;
1336
1336
  }
1337
1337
  }
1338
- async function removeDirectoryWithRetries(path23) {
1339
- if (!await pathExists(path23)) {
1338
+ async function removeDirectoryWithRetries(path24) {
1339
+ if (!await pathExists(path24)) {
1340
1340
  return;
1341
1341
  }
1342
1342
  const delaysMs = [0, 100, 300, 700, 1500];
@@ -1346,17 +1346,17 @@ async function removeDirectoryWithRetries(path23) {
1346
1346
  await new Promise((resolve12) => setTimeout(resolve12, delay));
1347
1347
  }
1348
1348
  try {
1349
- await rm(path23, { recursive: true, force: true });
1350
- if (!await pathExists(path23)) {
1349
+ await rm(path24, { recursive: true, force: true });
1350
+ if (!await pathExists(path24)) {
1351
1351
  return;
1352
1352
  }
1353
- lastError = new Error(`Directory still present after rm: ${path23}`);
1353
+ lastError = new Error(`Directory still present after rm: ${path24}`);
1354
1354
  } catch (error) {
1355
1355
  lastError = error;
1356
1356
  }
1357
1357
  }
1358
- if (await pathExists(path23)) {
1359
- throw lastError instanceof Error ? lastError : new Error(`Failed to remove worktree directory: ${path23}`);
1358
+ if (await pathExists(path24)) {
1359
+ throw lastError instanceof Error ? lastError : new Error(`Failed to remove worktree directory: ${path24}`);
1360
1360
  }
1361
1361
  }
1362
1362
  var createWorktree = async ({
@@ -2545,14 +2545,14 @@ var LoopStopResponseSchema = z7.object({
2545
2545
  })
2546
2546
  });
2547
2547
 
2548
- // ../server/src/server/workflow/rpc-schemas.ts
2548
+ // ../server/src/server/quest/rpc-schemas.ts
2549
2549
  import { z as z9 } from "zod";
2550
2550
 
2551
- // ../server/src/server/workflow/types.ts
2551
+ // ../server/src/server/quest/types.ts
2552
2552
  import { z as z8 } from "zod";
2553
- var WorkflowKindSchema = z8.enum(["loop", "ralph"]);
2553
+ var QuestKindSchema = z8.enum(["loop", "ralph", "run", "orchestrate"]);
2554
2554
  var FieldModeSchema = z8.enum(["locked", "inherit", "free"]);
2555
- var WorkflowRulesSchema = z8.object({
2555
+ var QuestRulesSchema = z8.object({
2556
2556
  perCardRole: FieldModeSchema,
2557
2557
  perCardModel: FieldModeSchema,
2558
2558
  perCardPrompt: FieldModeSchema,
@@ -2576,79 +2576,101 @@ var CardWiringSchema = z8.object({
2576
2576
  inputs: CardWiringInputsSchema,
2577
2577
  outputs: CardWiringOutputsSchema
2578
2578
  });
2579
- var WorkflowCardStatusSchema = z8.enum([
2579
+ var QuestCardStatusSchema = z8.enum([
2580
2580
  "queued",
2581
2581
  "running",
2582
2582
  "succeeded",
2583
2583
  "failed",
2584
2584
  "stopped"
2585
2585
  ]);
2586
- var WorkflowCardVerifySchema = z8.object({
2586
+ var QuestCardVerifySchema = z8.object({
2587
2587
  verifierAgentId: z8.string().nullable(),
2588
2588
  passed: z8.boolean().nullable(),
2589
2589
  reason: z8.string().nullable(),
2590
2590
  startedAt: z8.string().nullable(),
2591
2591
  completedAt: z8.string().nullable()
2592
2592
  });
2593
- var WorkflowCardSchema = z8.object({
2593
+ var QuestCardSchema = z8.object({
2594
2594
  /**
2595
2595
  * 1..N for iteration cards. The summarizer card uses 0 as a sentinel —
2596
- * it lives on `WorkflowRecord.summarizerCard`, not in the cards array,
2596
+ * it lives on `QuestRecord.summarizerCard`, not in the cards array,
2597
2597
  * and the UI renders it as "Summary" when it sees index === 0.
2598
2598
  */
2599
2599
  index: z8.number().int().nonnegative(),
2600
- /** Role name resolved against the agents/.scanner. Null = use workflow default. */
2600
+ /** Role name resolved against the agents/.scanner. Null = use quest default. */
2601
2601
  role: z8.string().nullable(),
2602
- /** Model override. Null = use workflow.defaultModel. */
2602
+ /** Model override. Null = use quest.defaultModel. */
2603
2603
  model: z8.string().nullable(),
2604
- /** Prompt override. Null = use workflow.prompt. */
2604
+ /** Prompt override. Null = use quest.prompt. */
2605
2605
  prompt: z8.string().nullable(),
2606
2606
  wiring: CardWiringSchema,
2607
- status: WorkflowCardStatusSchema,
2607
+ status: QuestCardStatusSchema,
2608
2608
  /** Populated when the card runs. Null until the runner spawns the agent. */
2609
2609
  agentId: z8.string().nullable(),
2610
2610
  startedAt: z8.string().nullable(),
2611
2611
  completedAt: z8.string().nullable(),
2612
2612
  /** Ralph-only — null for loop cards. */
2613
- verify: WorkflowCardVerifySchema.nullable()
2613
+ verify: QuestCardVerifySchema.nullable()
2614
2614
  });
2615
- var WorkflowTerminationCountSchema = z8.object({
2615
+ var QuestTerminationCountSchema = z8.object({
2616
2616
  type: z8.literal("count"),
2617
2617
  /** 1..10 in v1. */
2618
2618
  n: z8.number().int().min(1).max(10)
2619
2619
  });
2620
- var WorkflowTerminationVerifySchema = z8.object({
2620
+ var QuestTerminationVerifySchema = z8.object({
2621
2621
  type: z8.literal("verify"),
2622
2622
  /** Verifier agent system prompt. Null means rely on shell checks alone. */
2623
2623
  verifyPrompt: z8.string().nullable(),
2624
2624
  /** Shell commands that must exit 0 for the iteration to pass. */
2625
2625
  verifyChecks: z8.array(z8.string()),
2626
+ /**
2627
+ * Exact completion token that MUST appear in worker output before the quest
2628
+ * may succeed. Mirrors Ralph's completion-promise guardrail.
2629
+ */
2630
+ completionPromise: z8.string().trim().min(1).optional().default("<promise>COMPLETE</promise>"),
2626
2631
  /** Hard cap on iterations regardless of verifier outcome. */
2627
2632
  maxIterations: z8.number().int().min(1)
2628
2633
  });
2629
- var WorkflowTerminationSchema = z8.discriminatedUnion("type", [
2630
- WorkflowTerminationCountSchema,
2631
- WorkflowTerminationVerifySchema
2634
+ var QuestTerminationOrchestrateSchema = z8.object({
2635
+ type: z8.literal("orchestrate")
2636
+ });
2637
+ var QuestTerminationSchema = z8.discriminatedUnion("type", [
2638
+ QuestTerminationCountSchema,
2639
+ QuestTerminationVerifySchema,
2640
+ QuestTerminationOrchestrateSchema
2632
2641
  ]);
2633
- var WorkflowStatusSchema = z8.enum(["running", "succeeded", "failed", "stopped"]);
2634
- var WorkflowRecordSchema = z8.object({
2642
+ var QuestStatusSchema = z8.enum(["running", "succeeded", "failed", "stopped"]);
2643
+ var QuestRecordSchema = z8.object({
2635
2644
  id: z8.string(),
2636
- kind: WorkflowKindSchema,
2637
- rules: WorkflowRulesSchema,
2645
+ kind: QuestKindSchema,
2646
+ rules: QuestRulesSchema,
2638
2647
  cwd: z8.string(),
2639
2648
  /** User's task prompt — fed to every card unless overridden per-card. */
2640
2649
  prompt: z8.string(),
2641
2650
  defaultProvider: AgentProviderSchema,
2642
2651
  defaultModel: z8.string().nullable(),
2643
- termination: WorkflowTerminationSchema,
2652
+ termination: QuestTerminationSchema,
2644
2653
  /**
2645
2654
  * For "loop" kind: pre-rendered N cards from the start.
2646
2655
  * For "ralph" kind: appended as iterations execute.
2647
2656
  */
2648
- cards: z8.array(WorkflowCardSchema),
2657
+ cards: z8.array(QuestCardSchema),
2649
2658
  /** Populated when summarizer is enabled. Runs after all cards complete. */
2650
- summarizerCard: WorkflowCardSchema.nullable(),
2651
- status: WorkflowStatusSchema,
2659
+ summarizerCard: QuestCardSchema.nullable(),
2660
+ /**
2661
+ * Queen-bee coordinator card for "orchestrate" kind. The queen reads the
2662
+ * hivemind doc, decides dispatch waves, and writes JSON decisions back. It
2663
+ * is promotable (same affordance as regular cards). Null for non-orchestrate
2664
+ * kinds. Optional + default so old persisted records remain valid.
2665
+ */
2666
+ queenCard: QuestCardSchema.nullable().optional().default(null),
2667
+ /**
2668
+ * Path to the orchestration's hivemind markdown doc. Null for non-
2669
+ * orchestrate kinds. Optional + default so old persisted records remain
2670
+ * valid.
2671
+ */
2672
+ hivemindPath: z8.string().nullable().optional().default(null),
2673
+ status: QuestStatusSchema,
2652
2674
  createdAt: z8.string(),
2653
2675
  updatedAt: z8.string(),
2654
2676
  startedAt: z8.string().nullable(),
@@ -2656,107 +2678,293 @@ var WorkflowRecordSchema = z8.object({
2656
2678
  stopRequestedAt: z8.string().nullable()
2657
2679
  });
2658
2680
 
2659
- // ../server/src/server/workflow/rpc-schemas.ts
2660
- var WorkflowCardConfigInputSchema = z9.object({
2681
+ // ../server/src/server/quest/rpc-schemas.ts
2682
+ var QuestCardConfigInputSchema = z9.object({
2661
2683
  role: z9.string().nullable().optional(),
2662
2684
  model: z9.string().nullable().optional(),
2663
2685
  prompt: z9.string().nullable().optional()
2664
2686
  });
2665
- var WorkflowRunRequestSchema = z9.object({
2666
- type: z9.literal("workflow/run"),
2687
+ var QuestRunRequestSchema = z9.object({
2688
+ type: z9.literal("quest/run"),
2667
2689
  requestId: z9.string(),
2668
- kind: WorkflowKindSchema,
2690
+ kind: QuestKindSchema,
2669
2691
  cwd: z9.string(),
2670
2692
  prompt: z9.string().trim().min(1),
2671
2693
  defaultProvider: AgentProviderSchema.optional(),
2672
2694
  defaultModel: z9.string().trim().min(1).optional(),
2673
- termination: WorkflowTerminationSchema,
2695
+ termination: QuestTerminationSchema,
2674
2696
  /** Per-card overrides (length must match termination.n for "count"). Optional. */
2675
- cards: z9.array(WorkflowCardConfigInputSchema).optional(),
2697
+ cards: z9.array(QuestCardConfigInputSchema).optional(),
2676
2698
  summarizerEnabled: z9.boolean().optional()
2677
2699
  });
2678
- var WorkflowListRequestSchema = z9.object({
2679
- type: z9.literal("workflow/list"),
2700
+ var QuestListRequestSchema = z9.object({
2701
+ type: z9.literal("quest/list"),
2680
2702
  requestId: z9.string()
2681
2703
  });
2682
- var WorkflowInspectRequestSchema = z9.object({
2683
- type: z9.literal("workflow/inspect"),
2704
+ var QuestInspectRequestSchema = z9.object({
2705
+ type: z9.literal("quest/inspect"),
2684
2706
  requestId: z9.string(),
2685
2707
  id: z9.string().trim().min(1)
2686
2708
  });
2687
- var WorkflowStopRequestSchema = z9.object({
2688
- type: z9.literal("workflow/stop"),
2709
+ var QuestStopRequestSchema = z9.object({
2710
+ type: z9.literal("quest/stop"),
2689
2711
  requestId: z9.string(),
2690
2712
  id: z9.string().trim().min(1)
2691
2713
  });
2692
- var WorkflowListItemSchema = z9.object({
2714
+ var QuestListItemSchema = z9.object({
2693
2715
  id: z9.string(),
2694
- kind: WorkflowKindSchema,
2695
- status: WorkflowStatusSchema,
2716
+ kind: QuestKindSchema,
2717
+ status: QuestStatusSchema,
2696
2718
  cwd: z9.string(),
2697
2719
  prompt: z9.string(),
2698
2720
  createdAt: z9.string(),
2699
2721
  updatedAt: z9.string()
2700
2722
  });
2701
- var WorkflowRunResponseSchema = z9.object({
2702
- type: z9.literal("workflow/run/response"),
2723
+ var QuestRunResponseSchema = z9.object({
2724
+ type: z9.literal("quest/run/response"),
2725
+ payload: z9.object({
2726
+ requestId: z9.string(),
2727
+ quest: QuestRecordSchema.nullable(),
2728
+ error: z9.string().nullable()
2729
+ })
2730
+ });
2731
+ var QuestListResponseSchema = z9.object({
2732
+ type: z9.literal("quest/list/response"),
2733
+ payload: z9.object({
2734
+ requestId: z9.string(),
2735
+ quests: z9.array(QuestListItemSchema),
2736
+ error: z9.string().nullable()
2737
+ })
2738
+ });
2739
+ var QuestInspectResponseSchema = z9.object({
2740
+ type: z9.literal("quest/inspect/response"),
2741
+ payload: z9.object({
2742
+ requestId: z9.string(),
2743
+ quest: QuestRecordSchema.nullable(),
2744
+ error: z9.string().nullable()
2745
+ })
2746
+ });
2747
+ var QuestStopResponseSchema = z9.object({
2748
+ type: z9.literal("quest/stop/response"),
2749
+ payload: z9.object({
2750
+ requestId: z9.string(),
2751
+ quest: QuestRecordSchema.nullable(),
2752
+ error: z9.string().nullable()
2753
+ })
2754
+ });
2755
+ var QuestStreamMessageSchema = z9.object({
2756
+ type: z9.literal("quest/stream"),
2757
+ questId: z9.string(),
2758
+ quest: QuestRecordSchema
2759
+ });
2760
+ var RoleScopeSchema = z9.enum(["global", "project"]);
2761
+ var RoleEntrySchema = z9.object({
2762
+ id: z9.string(),
2763
+ scope: RoleScopeSchema,
2764
+ /** Category subfolder inside .roles/, or null for flat files. */
2765
+ category: z9.string().nullable().optional(),
2766
+ name: z9.string(),
2767
+ description: z9.string(),
2768
+ /** Trigger words from the `trigger-words` frontmatter key. */
2769
+ triggerWords: z9.array(z9.string()).optional().default([]),
2770
+ provider: z9.string(),
2771
+ model: z9.string(),
2772
+ mode: z9.string(),
2773
+ path: z9.string(),
2774
+ modifiedAt: z9.string(),
2775
+ size: z9.number()
2776
+ });
2777
+ var RoleFrontmatterSchema = z9.object({
2778
+ description: z9.string().optional(),
2779
+ triggerWords: z9.array(z9.string()).optional(),
2780
+ allowedTools: z9.array(z9.string()).optional(),
2781
+ provider: z9.string().optional(),
2782
+ model: z9.string().optional(),
2783
+ mode: z9.string().optional()
2784
+ });
2785
+ var RolesListRequestSchema = z9.object({
2786
+ type: z9.literal("roles/list"),
2787
+ requestId: z9.string(),
2788
+ workspaceRoot: z9.string().optional()
2789
+ });
2790
+ var RolesListResponseSchema = z9.object({
2791
+ type: z9.literal("roles/list/response"),
2703
2792
  payload: z9.object({
2704
2793
  requestId: z9.string(),
2705
- workflow: WorkflowRecordSchema.nullable(),
2794
+ roles: z9.array(RoleEntrySchema),
2706
2795
  error: z9.string().nullable()
2707
2796
  })
2708
2797
  });
2709
- var WorkflowListResponseSchema = z9.object({
2710
- type: z9.literal("workflow/list/response"),
2798
+ var RolesListScopeRequestSchema = z9.object({
2799
+ type: z9.literal("roles/list-scope"),
2800
+ requestId: z9.string(),
2801
+ scope: RoleScopeSchema,
2802
+ workspaceRoot: z9.string().optional()
2803
+ });
2804
+ var RolesListScopeResponseSchema = z9.object({
2805
+ type: z9.literal("roles/list-scope/response"),
2711
2806
  payload: z9.object({
2712
2807
  requestId: z9.string(),
2713
- workflows: z9.array(WorkflowListItemSchema),
2808
+ roles: z9.array(RoleEntrySchema),
2714
2809
  error: z9.string().nullable()
2715
2810
  })
2716
2811
  });
2717
- var WorkflowInspectResponseSchema = z9.object({
2718
- type: z9.literal("workflow/inspect/response"),
2812
+ var RoleCreateRequestSchema = z9.object({
2813
+ type: z9.literal("roles/create"),
2814
+ requestId: z9.string(),
2815
+ scope: RoleScopeSchema,
2816
+ name: z9.string(),
2817
+ category: z9.string().optional(),
2818
+ workspaceRoot: z9.string().optional()
2819
+ });
2820
+ var RoleCreateResponseSchema = z9.object({
2821
+ type: z9.literal("roles/create/response"),
2719
2822
  payload: z9.object({
2720
2823
  requestId: z9.string(),
2721
- workflow: WorkflowRecordSchema.nullable(),
2824
+ /** Absolute path of the created .md file. Empty string when error is set. */
2825
+ path: z9.string(),
2722
2826
  error: z9.string().nullable()
2723
2827
  })
2724
2828
  });
2725
- var WorkflowStopResponseSchema = z9.object({
2726
- type: z9.literal("workflow/stop/response"),
2829
+ var RoleWriteFrontmatterRequestSchema = z9.object({
2830
+ type: z9.literal("roles/write-frontmatter"),
2831
+ requestId: z9.string(),
2832
+ /** Absolute path inside an allowlisted role root. */
2833
+ path: z9.string(),
2834
+ workspaceRoot: z9.string().optional(),
2835
+ frontmatter: RoleFrontmatterSchema
2836
+ });
2837
+ var RoleWriteFrontmatterResponseSchema = z9.object({
2838
+ type: z9.literal("roles/write-frontmatter/response"),
2727
2839
  payload: z9.object({
2728
2840
  requestId: z9.string(),
2729
- workflow: WorkflowRecordSchema.nullable(),
2841
+ path: z9.string(),
2730
2842
  error: z9.string().nullable()
2731
2843
  })
2732
2844
  });
2733
- var WorkflowStreamMessageSchema = z9.object({
2734
- type: z9.literal("workflow/stream"),
2735
- workflowId: z9.string(),
2736
- workflow: WorkflowRecordSchema
2845
+ var RoleMoveRequestSchema = z9.object({
2846
+ type: z9.literal("roles/move"),
2847
+ requestId: z9.string(),
2848
+ path: z9.string(),
2849
+ newName: z9.string().optional(),
2850
+ newCategory: z9.string().optional(),
2851
+ workspaceRoot: z9.string().optional()
2852
+ });
2853
+ var RoleMoveResponseSchema = z9.object({
2854
+ type: z9.literal("roles/move/response"),
2855
+ payload: z9.object({
2856
+ requestId: z9.string(),
2857
+ path: z9.string(),
2858
+ error: z9.string().nullable()
2859
+ })
2737
2860
  });
2738
- var AgentRoleEntrySchema = z9.object({
2861
+ var BrandScopeSchema = z9.literal("project");
2862
+ var BrandVariableTypeSchema = z9.enum([
2863
+ "color",
2864
+ "font",
2865
+ "asset",
2866
+ "text",
2867
+ "number",
2868
+ "select"
2869
+ ]);
2870
+ var BrandSectionSchema = z9.enum(["visual", "voice"]);
2871
+ var BrandVariableSchema = z9.object({
2872
+ key: z9.string(),
2873
+ type: BrandVariableTypeSchema,
2874
+ label: z9.string(),
2875
+ value: z9.string(),
2876
+ section: BrandSectionSchema.optional(),
2877
+ options: z9.array(z9.string()).optional(),
2878
+ fileRef: z9.string().optional()
2879
+ });
2880
+ var BrandEntrySchema = z9.object({
2739
2881
  id: z9.string(),
2740
- scope: z9.enum(["global", "project"]),
2882
+ scope: BrandScopeSchema,
2741
2883
  name: z9.string(),
2742
2884
  description: z9.string(),
2743
- provider: z9.string().nullable(),
2744
- model: z9.string().nullable(),
2745
- mode: z9.string().nullable(),
2885
+ tags: z9.array(z9.string()).optional().default([]),
2886
+ variables: z9.array(BrandVariableSchema).optional().default([]),
2746
2887
  path: z9.string(),
2747
2888
  modifiedAt: z9.string(),
2748
2889
  size: z9.number()
2749
2890
  });
2750
- var AgentRolesListRequestSchema = z9.object({
2751
- type: z9.literal("agents/list"),
2891
+ var BrandFrontmatterSchema = z9.object({
2892
+ description: z9.string().optional(),
2893
+ tags: z9.array(z9.string()).optional(),
2894
+ variables: z9.array(BrandVariableSchema).optional()
2895
+ });
2896
+ var BrandsListScopeRequestSchema = z9.object({
2897
+ type: z9.literal("brands/list-scope"),
2752
2898
  requestId: z9.string(),
2753
2899
  workspaceRoot: z9.string().optional()
2754
2900
  });
2755
- var AgentRolesListResponseSchema = z9.object({
2756
- type: z9.literal("agents/list/response"),
2901
+ var BrandsListScopeResponseSchema = z9.object({
2902
+ type: z9.literal("brands/list-scope/response"),
2903
+ payload: z9.object({
2904
+ requestId: z9.string(),
2905
+ brands: z9.array(BrandEntrySchema),
2906
+ error: z9.string().nullable()
2907
+ })
2908
+ });
2909
+ var BrandCreateRequestSchema = z9.object({
2910
+ type: z9.literal("brands/create"),
2911
+ requestId: z9.string(),
2912
+ name: z9.string(),
2913
+ workspaceRoot: z9.string().optional()
2914
+ });
2915
+ var BrandCreateResponseSchema = z9.object({
2916
+ type: z9.literal("brands/create/response"),
2757
2917
  payload: z9.object({
2758
2918
  requestId: z9.string(),
2759
- roles: z9.array(AgentRoleEntrySchema),
2919
+ path: z9.string(),
2920
+ error: z9.string().nullable()
2921
+ })
2922
+ });
2923
+ var BrandAssetCopyRequestSchema = z9.object({
2924
+ type: z9.literal("brands/asset-copy"),
2925
+ requestId: z9.string(),
2926
+ workspaceRoot: z9.string(),
2927
+ sourcePath: z9.string(),
2928
+ targetName: z9.string()
2929
+ });
2930
+ var BrandAssetUploadRequestSchema = z9.object({
2931
+ type: z9.literal("brands/asset-upload"),
2932
+ requestId: z9.string(),
2933
+ workspaceRoot: z9.string(),
2934
+ targetName: z9.string(),
2935
+ sourceName: z9.string().optional(),
2936
+ dataBase64: z9.string()
2937
+ });
2938
+ var BrandAssetUploadResponseSchema = z9.object({
2939
+ type: z9.literal("brands/asset-upload/response"),
2940
+ payload: z9.object({
2941
+ requestId: z9.string(),
2942
+ relativePath: z9.string(),
2943
+ absolutePath: z9.string(),
2944
+ error: z9.string().nullable()
2945
+ })
2946
+ });
2947
+ var BrandAssetCopyResponseSchema = z9.object({
2948
+ type: z9.literal("brands/asset-copy/response"),
2949
+ payload: z9.object({
2950
+ requestId: z9.string(),
2951
+ relativePath: z9.string(),
2952
+ absolutePath: z9.string(),
2953
+ error: z9.string().nullable()
2954
+ })
2955
+ });
2956
+ var BrandWriteFrontmatterRequestSchema = z9.object({
2957
+ type: z9.literal("brands/write-frontmatter"),
2958
+ requestId: z9.string(),
2959
+ path: z9.string(),
2960
+ workspaceRoot: z9.string().optional(),
2961
+ frontmatter: BrandFrontmatterSchema
2962
+ });
2963
+ var BrandWriteFrontmatterResponseSchema = z9.object({
2964
+ type: z9.literal("brands/write-frontmatter/response"),
2965
+ payload: z9.object({
2966
+ requestId: z9.string(),
2967
+ path: z9.string(),
2760
2968
  error: z9.string().nullable()
2761
2969
  })
2762
2970
  });
@@ -3310,6 +3518,7 @@ var UpdateAgentRequestMessageSchema = z10.object({
3310
3518
  agentId: z10.string(),
3311
3519
  name: z10.string().optional(),
3312
3520
  labels: z10.record(z10.string()).optional(),
3521
+ internal: z10.boolean().optional(),
3313
3522
  requestId: z10.string()
3314
3523
  });
3315
3524
  var SetVoiceModeMessageSchema = z10.object({
@@ -4099,6 +4308,25 @@ var FileDeleteRequestSchema = z10.object({
4099
4308
  path: z10.string(),
4100
4309
  requestId: z10.string()
4101
4310
  });
4311
+ var FileExplorerDeleteRequestSchema = z10.object({
4312
+ type: z10.literal("file_explorer_delete_request"),
4313
+ cwd: z10.string(),
4314
+ path: z10.string(),
4315
+ requestId: z10.string()
4316
+ });
4317
+ var FileMkdirRequestSchema = z10.object({
4318
+ type: z10.literal("file_mkdir_request"),
4319
+ cwd: z10.string(),
4320
+ path: z10.string(),
4321
+ requestId: z10.string()
4322
+ });
4323
+ var FileMoveRequestSchema = z10.object({
4324
+ type: z10.literal("file_move_request"),
4325
+ cwd: z10.string(),
4326
+ sourcePath: z10.string(),
4327
+ destinationPath: z10.string(),
4328
+ requestId: z10.string()
4329
+ });
4102
4330
  var ClearAgentAttentionMessageSchema = z10.object({
4103
4331
  type: z10.literal("clear_agent_attention"),
4104
4332
  agentId: z10.union([z10.string(), z10.array(z10.string())]),
@@ -4371,6 +4599,9 @@ var SessionInboundMessageSchema = z10.discriminatedUnion("type", [
4371
4599
  FileExplorerRequestSchema,
4372
4600
  FileWriteRequestSchema,
4373
4601
  FileDeleteRequestSchema,
4602
+ FileExplorerDeleteRequestSchema,
4603
+ FileMkdirRequestSchema,
4604
+ FileMoveRequestSchema,
4374
4605
  ProjectIconRequestSchema,
4375
4606
  FileDownloadTokenRequestSchema,
4376
4607
  ClearAgentAttentionMessageSchema,
@@ -4380,6 +4611,15 @@ var SessionInboundMessageSchema = z10.discriminatedUnion("type", [
4380
4611
  ListSkillsRequestSchema,
4381
4612
  CreateSkillRequestSchema,
4382
4613
  WriteSkillFrontmatterRequestSchema,
4614
+ RolesListScopeRequestSchema,
4615
+ RoleCreateRequestSchema,
4616
+ RoleWriteFrontmatterRequestSchema,
4617
+ RoleMoveRequestSchema,
4618
+ BrandsListScopeRequestSchema,
4619
+ BrandCreateRequestSchema,
4620
+ BrandWriteFrontmatterRequestSchema,
4621
+ BrandAssetCopyRequestSchema,
4622
+ BrandAssetUploadRequestSchema,
4383
4623
  RegisterPushTokenMessageSchema,
4384
4624
  RegisterWebPushSubscriptionMessageSchema,
4385
4625
  UnregisterWebPushSubscriptionMessageSchema,
@@ -4414,11 +4654,11 @@ var SessionInboundMessageSchema = z10.discriminatedUnion("type", [
4414
4654
  LoopInspectRequestSchema,
4415
4655
  LoopLogsRequestSchema,
4416
4656
  LoopStopRequestSchema,
4417
- WorkflowRunRequestSchema,
4418
- WorkflowListRequestSchema,
4419
- WorkflowInspectRequestSchema,
4420
- WorkflowStopRequestSchema,
4421
- AgentRolesListRequestSchema
4657
+ QuestRunRequestSchema,
4658
+ QuestListRequestSchema,
4659
+ QuestInspectRequestSchema,
4660
+ QuestStopRequestSchema,
4661
+ RolesListRequestSchema
4422
4662
  ]);
4423
4663
  var ActivityLogPayloadSchema = z10.object({
4424
4664
  id: z10.string(),
@@ -5544,6 +5784,34 @@ var FileDeleteResponseSchema = z10.object({
5544
5784
  requestId: z10.string()
5545
5785
  })
5546
5786
  });
5787
+ var FileExplorerDeleteResponseSchema = z10.object({
5788
+ type: z10.literal("file_explorer_delete_response"),
5789
+ payload: z10.object({
5790
+ cwd: z10.string(),
5791
+ path: z10.string(),
5792
+ error: z10.string().nullable(),
5793
+ requestId: z10.string()
5794
+ })
5795
+ });
5796
+ var FileMkdirResponseSchema = z10.object({
5797
+ type: z10.literal("file_mkdir_response"),
5798
+ payload: z10.object({
5799
+ cwd: z10.string(),
5800
+ path: z10.string(),
5801
+ error: z10.string().nullable(),
5802
+ requestId: z10.string()
5803
+ })
5804
+ });
5805
+ var FileMoveResponseSchema = z10.object({
5806
+ type: z10.literal("file_move_response"),
5807
+ payload: z10.object({
5808
+ cwd: z10.string(),
5809
+ sourcePath: z10.string(),
5810
+ destinationPath: z10.string(),
5811
+ error: z10.string().nullable(),
5812
+ requestId: z10.string()
5813
+ })
5814
+ });
5547
5815
  var ProjectIconSchema = z10.object({
5548
5816
  data: z10.string(),
5549
5817
  mimeType: z10.string()
@@ -5876,6 +6144,9 @@ var SessionOutboundMessageSchema = z10.discriminatedUnion("type", [
5876
6144
  FileExplorerResponseSchema,
5877
6145
  FileWriteResponseSchema,
5878
6146
  FileDeleteResponseSchema,
6147
+ FileExplorerDeleteResponseSchema,
6148
+ FileMkdirResponseSchema,
6149
+ FileMoveResponseSchema,
5879
6150
  ProjectIconResponseSchema,
5880
6151
  FileDownloadTokenResponseSchema,
5881
6152
  ListProviderModelsResponseMessageSchema,
@@ -5890,6 +6161,10 @@ var SessionOutboundMessageSchema = z10.discriminatedUnion("type", [
5890
6161
  ListSkillsResponseSchema,
5891
6162
  CreateSkillResponseSchema,
5892
6163
  WriteSkillFrontmatterResponseSchema,
6164
+ RolesListScopeResponseSchema,
6165
+ RoleCreateResponseSchema,
6166
+ RoleWriteFrontmatterResponseSchema,
6167
+ RoleMoveResponseSchema,
5893
6168
  ListTerminalsResponseSchema,
5894
6169
  TerminalsChangedSchema,
5895
6170
  CreateTerminalResponseSchema,
@@ -5916,11 +6191,16 @@ var SessionOutboundMessageSchema = z10.discriminatedUnion("type", [
5916
6191
  LoopInspectResponseSchema,
5917
6192
  LoopLogsResponseSchema,
5918
6193
  LoopStopResponseSchema,
5919
- WorkflowRunResponseSchema,
5920
- WorkflowListResponseSchema,
5921
- WorkflowInspectResponseSchema,
5922
- WorkflowStopResponseSchema,
5923
- AgentRolesListResponseSchema,
6194
+ QuestRunResponseSchema,
6195
+ QuestListResponseSchema,
6196
+ QuestInspectResponseSchema,
6197
+ QuestStopResponseSchema,
6198
+ RolesListResponseSchema,
6199
+ BrandsListScopeResponseSchema,
6200
+ BrandCreateResponseSchema,
6201
+ BrandWriteFrontmatterResponseSchema,
6202
+ BrandAssetCopyResponseSchema,
6203
+ BrandAssetUploadResponseSchema,
5924
6204
  GetVapidPublicKeyResponseSchema,
5925
6205
  LinkAccountResponseMessageSchema
5926
6206
  ]);
@@ -7887,6 +8167,12 @@ async function resolveEditorLaunch(input) {
7887
8167
  if (!executable) {
7888
8168
  throw new Error(`Editor target unavailable: ${target.label}`);
7889
8169
  }
8170
+ if (input.editorId === "finder") {
8171
+ return {
8172
+ command: executable,
8173
+ args: ["-R", input.path]
8174
+ };
8175
+ }
7890
8176
  return {
7891
8177
  command: executable,
7892
8178
  args: [input.path]
@@ -8318,14 +8604,14 @@ var DictationStreamManager = class {
8318
8604
  PCM_CHANNELS,
8319
8605
  PCM_BITS_PER_SAMPLE
8320
8606
  );
8321
- const path23 = await maybePersistDictationDebugAudio(
8607
+ const path24 = await maybePersistDictationDebugAudio(
8322
8608
  wavBuffer,
8323
8609
  { sessionId: state.sessionId, dictationId: state.dictationId, format: "audio/wav" },
8324
8610
  this.logger,
8325
8611
  state.debugChunkWriter?.folder
8326
8612
  );
8327
- state.debugRecordingPath = path23;
8328
- return path23;
8613
+ state.debugRecordingPath = path24;
8614
+ return path24;
8329
8615
  }
8330
8616
  failDictationStream(dictationId, error, retryable) {
8331
8617
  this.emit({
@@ -9571,14 +9857,14 @@ function parseDiff(diffText) {
9571
9857
  const firstLine = lines[0];
9572
9858
  const isNew = section.includes("new file mode") || section.includes("--- /dev/null");
9573
9859
  const isDeleted = section.includes("deleted file mode") || section.includes("+++ /dev/null");
9574
- let path23 = "unknown";
9860
+ let path24 = "unknown";
9575
9861
  const pathMatch = firstLine.match(/a\/(.*?) b\//);
9576
9862
  if (pathMatch) {
9577
- path23 = pathMatch[1];
9863
+ path24 = pathMatch[1];
9578
9864
  } else {
9579
9865
  const newFileMatch = firstLine.match(/b\/(.+)$/);
9580
9866
  if (newFileMatch) {
9581
- path23 = newFileMatch[1];
9867
+ path24 = newFileMatch[1];
9582
9868
  }
9583
9869
  }
9584
9870
  const hunks = [];
@@ -9622,7 +9908,7 @@ function parseDiff(diffText) {
9622
9908
  if (currentHunk) {
9623
9909
  hunks.push(currentHunk);
9624
9910
  }
9625
- files.push({ path: path23, isNew, isDeleted, additions, deletions, hunks });
9911
+ files.push({ path: path24, isNew, isDeleted, additions, deletions, hunks });
9626
9912
  }
9627
9913
  return files;
9628
9914
  }
@@ -9678,9 +9964,9 @@ function buildTokenLookup(lineMap, highlighted) {
9678
9964
  }
9679
9965
  return lookup2;
9680
9966
  }
9681
- function buildFullFileTokenLookup(fileContent, path23) {
9967
+ function buildFullFileTokenLookup(fileContent, path24) {
9682
9968
  const lookup2 = /* @__PURE__ */ new Map();
9683
- const highlighted = highlightCode(fileContent, path23);
9969
+ const highlighted = highlightCode(fileContent, path24);
9684
9970
  for (let i = 0; i < highlighted.length; i++) {
9685
9971
  lookup2.set(i + 1, highlighted[i]);
9686
9972
  }
@@ -11381,11 +11667,11 @@ async function listCheckoutFileChanges(cwd, ref, ignoreWhitespace = false) {
11381
11667
  }
11382
11668
  continue;
11383
11669
  }
11384
- const path23 = tabParts[1];
11385
- if (!path23) continue;
11670
+ const path24 = tabParts[1];
11671
+ if (!path24) continue;
11386
11672
  const code = rawStatus[0];
11387
11673
  changes.push({
11388
- path: path23,
11674
+ path: path24,
11389
11675
  status: rawStatus,
11390
11676
  isNew: code === "A",
11391
11677
  isDeleted: code === "D"
@@ -11420,9 +11706,9 @@ async function listCheckoutFileChanges(cwd, ref, ignoreWhitespace = false) {
11420
11706
  }
11421
11707
  return Array.from(byPath.values());
11422
11708
  }
11423
- async function readGitFileContentAtRef(cwd, ref, path23) {
11709
+ async function readGitFileContentAtRef(cwd, ref, path24) {
11424
11710
  try {
11425
- const { stdout } = await runGitCommand(["show", `${ref}:${path23}`], {
11711
+ const { stdout } = await runGitCommand(["show", `${ref}:${path24}`], {
11426
11712
  cwd,
11427
11713
  env: READ_ONLY_GIT_ENV2
11428
11714
  });
@@ -11483,21 +11769,21 @@ async function getTrackedNumstatByPath(cwd, ref, ignoreWhitespace = false) {
11483
11769
  const additionsField = parts[0] ?? "";
11484
11770
  const deletionsField = parts[1] ?? "";
11485
11771
  const rawPath = parts.slice(2).join(" ");
11486
- const path23 = normalizeNumstatPath(rawPath);
11487
- if (!path23) {
11772
+ const path24 = normalizeNumstatPath(rawPath);
11773
+ if (!path24) {
11488
11774
  continue;
11489
11775
  }
11490
11776
  if (additionsField === "-" || deletionsField === "-") {
11491
- stats.set(path23, { additions: 0, deletions: 0, isBinary: true });
11777
+ stats.set(path24, { additions: 0, deletions: 0, isBinary: true });
11492
11778
  continue;
11493
11779
  }
11494
11780
  const additions = Number.parseInt(additionsField, 10);
11495
11781
  const deletions = Number.parseInt(deletionsField, 10);
11496
11782
  if (Number.isNaN(additions) || Number.isNaN(deletions)) {
11497
- stats.set(path23, null);
11783
+ stats.set(path24, null);
11498
11784
  continue;
11499
11785
  }
11500
- stats.set(path23, { additions, deletions, isBinary: false });
11786
+ stats.set(path24, { additions, deletions, isBinary: false });
11501
11787
  }
11502
11788
  return stats;
11503
11789
  }
@@ -12082,10 +12368,10 @@ async function listUncommittedFiles(cwd) {
12082
12368
  if (dest) results.push({ path: dest, changeType: code });
12083
12369
  continue;
12084
12370
  }
12085
- const path23 = parts[1];
12086
- if (!path23) continue;
12371
+ const path24 = parts[1];
12372
+ if (!path24) continue;
12087
12373
  if (code === "A" || code === "M" || code === "D") {
12088
- results.push({ path: path23, changeType: code });
12374
+ results.push({ path: path24, changeType: code });
12089
12375
  }
12090
12376
  }
12091
12377
  } catch {
@@ -15129,6 +15415,14 @@ var CLAUDE_MODELS = [
15129
15415
  isDefault: true,
15130
15416
  thinkingOptions: [...CLAUDE_THINKING_OPTIONS]
15131
15417
  },
15418
+ {
15419
+ provider: "claude",
15420
+ id: "claude-sonnet-4-6[1m]",
15421
+ label: "Sonnet 4.6 1M",
15422
+ description: "Sonnet 4.6 with 1M context window",
15423
+ thinkingOptions: [...CLAUDE_THINKING_OPTIONS],
15424
+ betas: ["context-1m-2025-08-07"]
15425
+ },
15132
15426
  {
15133
15427
  provider: "claude",
15134
15428
  id: "claude-sonnet-4-6",
@@ -15146,6 +15440,9 @@ var CLAUDE_MODELS = [
15146
15440
  function getClaudeModels() {
15147
15441
  return CLAUDE_MODELS.map((model) => ({ ...model }));
15148
15442
  }
15443
+ function getClaudeModelBetas(modelId) {
15444
+ return CLAUDE_MODELS.find((m) => m.id === modelId)?.betas;
15445
+ }
15149
15446
  function normalizeClaudeRuntimeModelId(value) {
15150
15447
  const trimmed = typeof value === "string" ? value.trim() : "";
15151
15448
  if (!trimmed) {
@@ -17728,11 +18025,18 @@ var ClaudeAgentSession = class {
17728
18025
  }
17729
18026
  if (this.config.model) {
17730
18027
  base.model = this.config.model;
18028
+ const modelBetas = getClaudeModelBetas(this.config.model);
18029
+ if (modelBetas?.length) {
18030
+ base.betas = [...base.betas ?? [], ...modelBetas];
18031
+ }
17731
18032
  }
17732
18033
  this.lastOptionsModel = base.model ?? null;
17733
18034
  if (this.claudeSessionId) {
17734
18035
  base.resume = this.claudeSessionId;
17735
18036
  }
18037
+ if (this.config.allowedTools?.length) {
18038
+ base.allowedTools = [...base.allowedTools ?? [], ...this.config.allowedTools];
18039
+ }
17736
18040
  if (this.runtimeSettings?.disallowedTools?.length) {
17737
18041
  base.disallowedTools = [
17738
18042
  ...base.disallowedTools ?? [],
@@ -19963,14 +20267,14 @@ function codexApplyPatchToUnifiedDiff(text) {
19963
20267
  for (const line of lines) {
19964
20268
  const directive = parseCodexApplyPatchDirective(line);
19965
20269
  if (directive) {
19966
- const path23 = normalizeDiffHeaderPath(directive.path);
19967
- if (path23.length > 0) {
20270
+ const path24 = normalizeDiffHeaderPath(directive.path);
20271
+ if (path24.length > 0) {
19968
20272
  if (output.length > 0 && output[output.length - 1] !== "") {
19969
20273
  output.push("");
19970
20274
  }
19971
- const left = directive.kind === "add" ? "/dev/null" : `a/${path23}`;
19972
- const right = directive.kind === "delete" ? "/dev/null" : `b/${path23}`;
19973
- output.push(`diff --git a/${path23} b/${path23}`);
20275
+ const left = directive.kind === "add" ? "/dev/null" : `a/${path24}`;
20276
+ const right = directive.kind === "delete" ? "/dev/null" : `b/${path24}`;
20277
+ output.push(`diff --git a/${path24} b/${path24}`);
19974
20278
  output.push(`--- ${left}`);
19975
20279
  output.push(`+++ ${right}`);
19976
20280
  sawDiffContent = true;
@@ -20040,9 +20344,9 @@ function asEditTextFields(text) {
20040
20344
  function normalizeRolloutEditInput(input) {
20041
20345
  if (typeof input === "string") {
20042
20346
  const textFields2 = asEditTextFields(input);
20043
- const path23 = extractPatchPrimaryFilePath(input);
20347
+ const path24 = extractPatchPrimaryFilePath(input);
20044
20348
  return {
20045
- ...path23 ? { path: path23 } : {},
20349
+ ...path24 ? { path: path24 } : {},
20046
20350
  ...textFields2.unifiedDiff ? { patch: textFields2.unifiedDiff } : {},
20047
20351
  ...textFields2.newString ? { content: textFields2.newString } : {}
20048
20352
  };
@@ -20190,12 +20494,12 @@ function parseFileChangeDiff(entry) {
20190
20494
  ]);
20191
20495
  }
20192
20496
  function toFileChangeEntry(entry, options, fallbackPath) {
20193
- const path23 = parseFileChangePath(entry, options, fallbackPath);
20194
- if (!path23) {
20497
+ const path24 = parseFileChangePath(entry, options, fallbackPath);
20498
+ if (!path24) {
20195
20499
  return null;
20196
20500
  }
20197
20501
  return {
20198
- path: path23,
20502
+ path: path24,
20199
20503
  kind: parseFileChangeKind(entry),
20200
20504
  diff: parseFileChangeDiff(entry)
20201
20505
  };
@@ -20217,12 +20521,12 @@ function parseFileChangeEntries(changes, options) {
20217
20521
  if (singleEntry) {
20218
20522
  return [singleEntry];
20219
20523
  }
20220
- return Object.entries(changes).map(([path23, value]) => {
20524
+ return Object.entries(changes).map(([path24, value]) => {
20221
20525
  if (isRecord2(value)) {
20222
- return toFileChangeEntry(value, options, path23);
20526
+ return toFileChangeEntry(value, options, path24);
20223
20527
  }
20224
20528
  if (typeof value === "string") {
20225
- const normalizedPath = normalizeCodexFilePath(path23.trim(), options?.cwd);
20529
+ const normalizedPath = normalizeCodexFilePath(path24.trim(), options?.cwd);
20226
20530
  if (!normalizedPath) {
20227
20531
  return null;
20228
20532
  }
@@ -20967,16 +21271,16 @@ function isObjectSchemaNode(schema) {
20967
21271
  const type = schema.type;
20968
21272
  return isSchemaRecord(schema.properties) || type === "object" || Array.isArray(type) && type.includes("object");
20969
21273
  }
20970
- function normalizeCodexOutputSchemaNode(schema, path23) {
21274
+ function normalizeCodexOutputSchemaNode(schema, path24) {
20971
21275
  if (Array.isArray(schema)) {
20972
- return schema.map((entry, index) => normalizeCodexOutputSchemaNode(entry, `${path23}[${index}]`));
21276
+ return schema.map((entry, index) => normalizeCodexOutputSchemaNode(entry, `${path24}[${index}]`));
20973
21277
  }
20974
21278
  if (!isSchemaRecord(schema)) {
20975
21279
  return schema;
20976
21280
  }
20977
21281
  const normalized = {};
20978
21282
  for (const [key, value] of Object.entries(schema)) {
20979
- normalized[key] = normalizeCodexOutputSchemaNode(value, `${path23}.${key}`);
21283
+ normalized[key] = normalizeCodexOutputSchemaNode(value, `${path24}.${key}`);
20980
21284
  }
20981
21285
  if (!isObjectSchemaNode(normalized)) {
20982
21286
  return normalized;
@@ -20985,7 +21289,7 @@ function normalizeCodexOutputSchemaNode(schema, path23) {
20985
21289
  normalized.additionalProperties = false;
20986
21290
  } else if (normalized.additionalProperties !== false) {
20987
21291
  throw new Error(
20988
- `Codex structured outputs require ${path23} to set additionalProperties to false for object schemas.`
21292
+ `Codex structured outputs require ${path24} to set additionalProperties to false for object schemas.`
20989
21293
  );
20990
21294
  }
20991
21295
  const properties = isSchemaRecord(normalized.properties) ? normalized.properties : null;
@@ -21747,8 +22051,8 @@ function parseCodexPatchChanges(changes) {
21747
22051
  }
21748
22052
  ];
21749
22053
  }
21750
- return Object.entries(recordChanges).map(([path23, value]) => {
21751
- const normalizedPath = path23.trim();
22054
+ return Object.entries(recordChanges).map(([path24, value]) => {
22055
+ const normalizedPath = path24.trim();
21752
22056
  if (!normalizedPath) {
21753
22057
  return null;
21754
22058
  }
@@ -29497,8 +29801,8 @@ function buildZodValidator(schema, schemaName) {
29497
29801
  return { ok: true, value: result.data };
29498
29802
  }
29499
29803
  const errors = result.error.issues.map((issue) => {
29500
- const path23 = issue.path.length > 0 ? issue.path.join(".") : "(root)";
29501
- return `${path23}: ${issue.message}`;
29804
+ const path24 = issue.path.length > 0 ? issue.path.join(".") : "(root)";
29805
+ return `${path24}: ${issue.message}`;
29502
29806
  });
29503
29807
  return { ok: false, errors };
29504
29808
  }
@@ -29516,9 +29820,9 @@ function buildJsonSchemaValidator(schema) {
29516
29820
  return { ok: true, value };
29517
29821
  }
29518
29822
  const errors = (validate.errors ?? []).map((error) => {
29519
- const path23 = error.instancePath && error.instancePath.length > 0 ? error.instancePath : "(root)";
29823
+ const path24 = error.instancePath && error.instancePath.length > 0 ? error.instancePath : "(root)";
29520
29824
  const message = error.message ?? "is invalid";
29521
- return `${path23}: ${message}`;
29825
+ return `${path24}: ${message}`;
29522
29826
  });
29523
29827
  return { ok: false, errors };
29524
29828
  }
@@ -30440,6 +30744,12 @@ var IMAGE_MIME_TYPES = {
30440
30744
  ".webp": "image/webp",
30441
30745
  ".svg": "image/svg+xml"
30442
30746
  };
30747
+ var FONT_MIME_TYPES = {
30748
+ ".ttf": "font/ttf",
30749
+ ".otf": "font/otf",
30750
+ ".woff": "font/woff",
30751
+ ".woff2": "font/woff2"
30752
+ };
30443
30753
  async function listDirectoryEntries({
30444
30754
  root,
30445
30755
  relativePath = "."
@@ -30550,6 +30860,23 @@ async function deleteFile({ root, relativePath }) {
30550
30860
  }
30551
30861
  await fs5.unlink(filePath);
30552
30862
  }
30863
+ async function deleteEntry({ root, relativePath }) {
30864
+ const entryPath = await resolveScopedPath({ root, relativePath });
30865
+ await fs5.rm(entryPath, { recursive: true, force: false });
30866
+ }
30867
+ async function createDirectory({ root, relativePath }) {
30868
+ const dirPath = await resolveScopedPath({ root, relativePath });
30869
+ await fs5.mkdir(dirPath, { recursive: true });
30870
+ }
30871
+ async function moveEntry({
30872
+ root,
30873
+ sourcePath,
30874
+ destinationPath
30875
+ }) {
30876
+ const src = await resolveScopedPath({ root, relativePath: sourcePath });
30877
+ const dest = await resolveScopedPath({ root, relativePath: destinationPath });
30878
+ await fs5.rename(src, dest);
30879
+ }
30553
30880
  async function getDownloadableFileInfo({ root, relativePath }) {
30554
30881
  const filePath = await resolveScopedPath({ root, relativePath });
30555
30882
  const stats = await fs5.stat(filePath);
@@ -30559,7 +30886,9 @@ async function getDownloadableFileInfo({ root, relativePath }) {
30559
30886
  const ext = path10.extname(filePath).toLowerCase();
30560
30887
  let mimeType = "application/octet-stream";
30561
30888
  if (ext in IMAGE_MIME_TYPES) {
30562
- mimeType = IMAGE_MIME_TYPES[ext];
30889
+ mimeType = IMAGE_MIME_TYPES[ext] ?? mimeType;
30890
+ } else if (ext in FONT_MIME_TYPES) {
30891
+ mimeType = FONT_MIME_TYPES[ext] ?? mimeType;
30563
30892
  } else {
30564
30893
  const handle = await fs5.open(filePath, "r");
30565
30894
  const sample = Buffer.alloc(8192);
@@ -30980,15 +31309,15 @@ async function getProjectIcon(projectDir) {
30980
31309
 
30981
31310
  // ../server/src/utils/path.ts
30982
31311
  import os5 from "os";
30983
- function expandTilde(path23) {
30984
- if (path23.startsWith("~/")) {
31312
+ function expandTilde(path24) {
31313
+ if (path24.startsWith("~/")) {
30985
31314
  const homeDir3 = process.env.HOME || os5.homedir();
30986
- return path23.replace("~", homeDir3);
31315
+ return path24.replace("~", homeDir3);
30987
31316
  }
30988
- if (path23 === "~") {
31317
+ if (path24 === "~") {
30989
31318
  return process.env.HOME || os5.homedir();
30990
31319
  }
30991
- return path23;
31320
+ return path24;
30992
31321
  }
30993
31322
 
30994
31323
  // ../server/src/server/skills/scanner.ts
@@ -32166,7 +32495,7 @@ function buildChatMentionNotification(input) {
32166
32495
  ].join("\n");
32167
32496
  }
32168
32497
 
32169
- // ../server/src/server/agents/scanner.ts
32498
+ // ../server/src/server/roles/scanner.ts
32170
32499
  import fs7 from "node:fs/promises";
32171
32500
  import os7 from "node:os";
32172
32501
  import path14 from "node:path";
@@ -32179,11 +32508,41 @@ function resolveScopeDir2(scope, workspaceRoot) {
32179
32508
  if (!workspaceRoot) {
32180
32509
  throw new Error('workspaceRoot is required for scope "project"');
32181
32510
  }
32182
- return path14.join(workspaceRoot, ".agents");
32511
+ return path14.join(workspaceRoot, ".roles");
32183
32512
  }
32184
- return path14.join(homeDir2(), ".appostle", ".agents");
32513
+ return path14.join(homeDir2(), ".appostle", ".roles");
32514
+ }
32515
+ function allowedRoots2(workspaceRoot) {
32516
+ const roots = [path14.join(homeDir2(), ".appostle", ".roles")];
32517
+ if (workspaceRoot) {
32518
+ roots.push(path14.join(workspaceRoot, ".roles"));
32519
+ }
32520
+ return roots.map((r) => path14.resolve(r));
32521
+ }
32522
+ function isInsideAllowedRoot2(absPath, workspaceRoot) {
32523
+ const resolved = path14.resolve(absPath);
32524
+ for (const root of allowedRoots2(workspaceRoot)) {
32525
+ const rel = path14.relative(root, resolved);
32526
+ if (rel === "" || !rel.startsWith("..") && !path14.isAbsolute(rel)) {
32527
+ return true;
32528
+ }
32529
+ }
32530
+ return false;
32185
32531
  }
32186
32532
  var FRONTMATTER_RE2 = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
32533
+ function parseRoleFile(text) {
32534
+ const match = FRONTMATTER_RE2.exec(text);
32535
+ if (!match) {
32536
+ return { rawFrontmatterLines: [], body: text, hadFrontmatter: false };
32537
+ }
32538
+ const yamlBlock = match[1] ?? "";
32539
+ const body = match[2] ?? "";
32540
+ return {
32541
+ rawFrontmatterLines: yamlBlock.split(/\r?\n/),
32542
+ body,
32543
+ hadFrontmatter: true
32544
+ };
32545
+ }
32187
32546
  function unquote(value) {
32188
32547
  if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
32189
32548
  return value.slice(1, -1);
@@ -32191,36 +32550,165 @@ function unquote(value) {
32191
32550
  return value;
32192
32551
  }
32193
32552
  function parseFrontmatter(text) {
32194
- const match = FRONTMATTER_RE2.exec(text);
32195
32553
  const empty = {
32196
32554
  description: "",
32197
- provider: null,
32198
- model: null,
32199
- mode: null
32555
+ triggerWords: [],
32556
+ allowedTools: [],
32557
+ provider: "",
32558
+ model: "",
32559
+ mode: ""
32200
32560
  };
32201
- if (!match) {
32202
- return empty;
32203
- }
32204
- const lines = (match[1] ?? "").split(/\r?\n/);
32561
+ const { rawFrontmatterLines: lines, hadFrontmatter } = parseRoleFile(text);
32562
+ if (!hadFrontmatter) return empty;
32205
32563
  const out = { ...empty };
32206
- for (const line of lines) {
32564
+ let i = 0;
32565
+ while (i < lines.length) {
32566
+ const line = lines[i] ?? "";
32207
32567
  const m = /^([A-Za-z][A-Za-z0-9_-]*)\s*:\s*(.*)$/.exec(line);
32208
- if (!m) continue;
32568
+ if (!m) {
32569
+ i++;
32570
+ continue;
32571
+ }
32209
32572
  const key = m[1];
32210
32573
  const value = unquote((m[2] ?? "").trim());
32211
32574
  if (key === "description") {
32212
32575
  out.description = value;
32213
32576
  } else if (key === "provider") {
32214
- out.provider = value || null;
32577
+ out.provider = value;
32215
32578
  } else if (key === "model") {
32216
- out.model = value || null;
32579
+ out.model = value;
32217
32580
  } else if (key === "mode") {
32218
- out.mode = value || null;
32581
+ out.mode = value;
32582
+ } else if (key === "trigger-words" || key === "allowed-tools") {
32583
+ const target = key === "trigger-words" ? "triggerWords" : "allowedTools";
32584
+ if (value) {
32585
+ out[target] = value.replace(/^\[|\]$/g, "").split(",").map((s) => unquote(s.trim())).filter((s) => s.length > 0);
32586
+ } else {
32587
+ const items = [];
32588
+ let j = i + 1;
32589
+ while (j < lines.length) {
32590
+ const next = lines[j] ?? "";
32591
+ const itemMatch = /^\s+-\s+(.+)$/.exec(next);
32592
+ if (!itemMatch) break;
32593
+ items.push(unquote(itemMatch[1].trim()));
32594
+ j++;
32595
+ }
32596
+ out[target] = items;
32597
+ i = j;
32598
+ continue;
32599
+ }
32600
+ }
32601
+ i++;
32602
+ }
32603
+ return out;
32604
+ }
32605
+ var OWNED_KEYS = [
32606
+ "name",
32607
+ "category",
32608
+ "description",
32609
+ "trigger-words",
32610
+ "allowed-tools",
32611
+ "provider",
32612
+ "model",
32613
+ "mode"
32614
+ ];
32615
+ function findOwnedSpans2(lines) {
32616
+ const spans = [];
32617
+ let i = 0;
32618
+ while (i < lines.length) {
32619
+ const line = lines[i] ?? "";
32620
+ const keyMatch = /^([A-Za-z][A-Za-z0-9_-]*)\s*:\s*(.*)$/.exec(line);
32621
+ if (!keyMatch) {
32622
+ i++;
32623
+ continue;
32624
+ }
32625
+ const key = keyMatch[1];
32626
+ const value = keyMatch[2];
32627
+ if (!OWNED_KEYS.includes(key)) {
32628
+ i++;
32629
+ continue;
32630
+ }
32631
+ let end = i + 1;
32632
+ if (value === "") {
32633
+ while (end < lines.length) {
32634
+ const next = lines[end] ?? "";
32635
+ if (/^\s+-\s+/.test(next) || /^\s*$/.test(next)) {
32636
+ end++;
32637
+ } else {
32638
+ break;
32639
+ }
32640
+ }
32641
+ }
32642
+ spans.push({ key, startLine: i, endLine: end });
32643
+ i = end;
32644
+ }
32645
+ return spans;
32646
+ }
32647
+ function emitFrontmatterValue2(key, value) {
32648
+ if (key === "trigger-words" || key === "allowed-tools") {
32649
+ if (!Array.isArray(value) || value.length === 0) return [];
32650
+ return [`${key}:`, ...value.map((v) => ` - ${v}`)];
32651
+ }
32652
+ const text = typeof value === "string" ? value : "";
32653
+ if (text.length === 0) return [];
32654
+ const needsQuote = /[:#\n]/.test(text) || text.startsWith(" ") || text.endsWith(" ");
32655
+ const formatted = needsQuote ? `"${text.replace(/"/g, '\\"')}"` : text;
32656
+ return [`${key}: ${formatted}`];
32657
+ }
32658
+ function rewriteFrontmatter2(originalLines, next) {
32659
+ const spans = findOwnedSpans2(originalLines);
32660
+ const ownedKeys = new Set(spans.map((s) => s.key));
32661
+ const replacements = /* @__PURE__ */ new Map();
32662
+ if (next.name !== void 0) {
32663
+ replacements.set("name", emitFrontmatterValue2("name", next.name));
32664
+ }
32665
+ if (next.category !== void 0) {
32666
+ replacements.set("category", emitFrontmatterValue2("category", next.category));
32667
+ }
32668
+ if (next.description !== void 0) {
32669
+ replacements.set("description", emitFrontmatterValue2("description", next.description));
32670
+ }
32671
+ if (next.triggerWords !== void 0) {
32672
+ replacements.set("trigger-words", emitFrontmatterValue2("trigger-words", next.triggerWords));
32673
+ }
32674
+ if (next.allowedTools !== void 0) {
32675
+ replacements.set("allowed-tools", emitFrontmatterValue2("allowed-tools", next.allowedTools));
32676
+ }
32677
+ if (next.provider !== void 0) {
32678
+ replacements.set("provider", emitFrontmatterValue2("provider", next.provider));
32679
+ }
32680
+ if (next.model !== void 0) {
32681
+ replacements.set("model", emitFrontmatterValue2("model", next.model));
32682
+ }
32683
+ if (next.mode !== void 0) {
32684
+ replacements.set("mode", emitFrontmatterValue2("mode", next.mode));
32685
+ }
32686
+ const out = [];
32687
+ let i = 0;
32688
+ while (i < originalLines.length) {
32689
+ const span = spans.find((s) => s.startLine === i);
32690
+ if (span) {
32691
+ if (replacements.has(span.key)) {
32692
+ out.push(...replacements.get(span.key) ?? []);
32693
+ } else {
32694
+ for (let j = span.startLine; j < span.endLine; j++) {
32695
+ out.push(originalLines[j] ?? "");
32696
+ }
32697
+ }
32698
+ i = span.endLine;
32699
+ continue;
32700
+ }
32701
+ out.push(originalLines[i] ?? "");
32702
+ i++;
32703
+ }
32704
+ for (const key of OWNED_KEYS) {
32705
+ if (replacements.has(key) && !ownedKeys.has(key)) {
32706
+ out.push(...replacements.get(key) ?? []);
32219
32707
  }
32220
32708
  }
32221
32709
  return out;
32222
32710
  }
32223
- async function readRolesFromDir(scope, dir) {
32711
+ async function readRolesFromDir(scope, dir, category) {
32224
32712
  let entries;
32225
32713
  try {
32226
32714
  entries = await fs7.readdir(dir, { withFileTypes: true });
@@ -32246,13 +32734,23 @@ async function readRolesFromDir(scope, dir) {
32246
32734
  const text = await fs7.readFile(fullPath, "utf8");
32247
32735
  parsed = parseFrontmatter(text);
32248
32736
  } catch {
32249
- parsed = { description: "", provider: null, model: null, mode: null };
32737
+ parsed = {
32738
+ description: "",
32739
+ triggerWords: [],
32740
+ allowedTools: [],
32741
+ provider: "",
32742
+ model: "",
32743
+ mode: ""
32744
+ };
32250
32745
  }
32746
+ const id = category ? `${scope}:${category}/${name}` : `${scope}:${name}`;
32251
32747
  results.push({
32252
- id: `${scope}:${name}`,
32748
+ id,
32253
32749
  scope,
32750
+ category,
32254
32751
  name,
32255
32752
  description: parsed.description,
32753
+ triggerWords: parsed.triggerWords,
32256
32754
  provider: parsed.provider,
32257
32755
  model: parsed.model,
32258
32756
  mode: parsed.mode,
@@ -32261,16 +32759,620 @@ async function readRolesFromDir(scope, dir) {
32261
32759
  size: stat5.size
32262
32760
  });
32263
32761
  }
32762
+ results.sort((a, b) => a.name.localeCompare(b.name));
32264
32763
  return results;
32265
32764
  }
32266
- async function listAgentRoles(args) {
32267
- const project = args.workspaceRoot ? await readRolesFromDir("project", resolveScopeDir2("project", args.workspaceRoot)) : [];
32268
- const global = await readRolesFromDir("global", resolveScopeDir2("global"));
32269
- const projectNames = new Set(project.map((r) => r.name));
32270
- const merged = [...project, ...global.filter((r) => !projectNames.has(r.name))];
32271
- merged.sort((a, b) => a.name.localeCompare(b.name));
32765
+ async function readRolesFromScopeDir(scope, scopeDir) {
32766
+ let topEntries;
32767
+ try {
32768
+ topEntries = await fs7.readdir(scopeDir, { withFileTypes: true });
32769
+ } catch {
32770
+ return [];
32771
+ }
32772
+ const flat = await readRolesFromDir(scope, scopeDir, null);
32773
+ const categoryResults = await Promise.all(
32774
+ topEntries.filter((e) => e.isDirectory() && NAME_REGEX2.test(e.name)).map((e) => readRolesFromDir(scope, path14.join(scopeDir, e.name), e.name))
32775
+ );
32776
+ const all = [...flat, ...categoryResults.flat()];
32777
+ all.sort((a, b) => {
32778
+ const catA = a.category ?? "";
32779
+ const catB = b.category ?? "";
32780
+ if (catA !== catB) return catA.localeCompare(catB);
32781
+ return a.name.localeCompare(b.name);
32782
+ });
32783
+ return all;
32784
+ }
32785
+ async function listRoles(args) {
32786
+ if (args.scope === "project") {
32787
+ return readRolesFromScopeDir("project", resolveScopeDir2("project", args.workspaceRoot));
32788
+ }
32789
+ if (args.scope === "global") {
32790
+ return readRolesFromScopeDir("global", resolveScopeDir2("global"));
32791
+ }
32792
+ const project = args.workspaceRoot ? await readRolesFromScopeDir("project", resolveScopeDir2("project", args.workspaceRoot)) : [];
32793
+ const global = await readRolesFromScopeDir("global", resolveScopeDir2("global"));
32794
+ const projectIds = new Set(project.map((r) => r.id));
32795
+ const merged = [...project, ...global.filter((r) => !projectIds.has(r.id))];
32796
+ merged.sort((a, b) => {
32797
+ const catA = a.category ?? "";
32798
+ const catB = b.category ?? "";
32799
+ if (catA !== catB) return catA.localeCompare(catB);
32800
+ return a.name.localeCompare(b.name);
32801
+ });
32272
32802
  return merged;
32273
32803
  }
32804
+ async function createRole(args) {
32805
+ if (!NAME_REGEX2.test(args.name)) {
32806
+ throw new Error(
32807
+ `Invalid role name "${args.name}". Use letters, digits, dot, underscore, dash.`
32808
+ );
32809
+ }
32810
+ if (args.name.includes("/") || args.name.includes("\\") || args.name.includes("..")) {
32811
+ throw new Error(`Role name must not contain path separators or "..".`);
32812
+ }
32813
+ const scopeDir = resolveScopeDir2(args.scope, args.workspaceRoot);
32814
+ const dir = args.category ? path14.join(scopeDir, args.category) : scopeDir;
32815
+ await fs7.mkdir(dir, { recursive: true });
32816
+ const filePath = path14.join(dir, `${args.name}.md`);
32817
+ try {
32818
+ await fs7.access(filePath);
32819
+ throw new Error(`A role named "${args.name}" already exists at ${filePath}`);
32820
+ } catch (err) {
32821
+ if (err && typeof err === "object" && "code" in err && err.code !== "ENOENT") {
32822
+ throw err;
32823
+ }
32824
+ if (err instanceof Error && err.message.includes("already exists")) {
32825
+ throw err;
32826
+ }
32827
+ }
32828
+ const initial = buildStarterRole(args.name);
32829
+ await fs7.writeFile(filePath, initial, "utf8");
32830
+ return { path: filePath };
32831
+ }
32832
+ function buildStarterRole(name) {
32833
+ return `---
32834
+ name: ${name}
32835
+ description: ""
32836
+ trigger-words: []
32837
+ allowed-tools: []
32838
+ provider: claude/opus
32839
+ mode: default
32840
+ ---
32841
+
32842
+ # ${name}
32843
+
32844
+ You are a ${name}. Describe the role's behavior, scope, and any constraints
32845
+ here. The body of this file is loaded as the agent's system prompt when
32846
+ the role is invoked.
32847
+ `;
32848
+ }
32849
+ async function writeRoleFrontmatter(args, workspaceRoot) {
32850
+ if (!path14.isAbsolute(args.path)) {
32851
+ throw new Error(`writeRoleFrontmatter expects an absolute path; got "${args.path}"`);
32852
+ }
32853
+ if (!isInsideAllowedRoot2(args.path, workspaceRoot)) {
32854
+ throw new Error(`Path "${args.path}" is not inside an allowlisted role root`);
32855
+ }
32856
+ let original;
32857
+ try {
32858
+ original = await fs7.readFile(args.path, "utf8");
32859
+ } catch (err) {
32860
+ throw new Error(
32861
+ `Failed to read role file: ${err instanceof Error ? err.message : String(err)}`
32862
+ );
32863
+ }
32864
+ const parsed = parseRoleFile(original);
32865
+ const newLines = rewriteFrontmatter2(parsed.rawFrontmatterLines, args.frontmatter);
32866
+ const nextFrontmatter = ["---", ...newLines, "---"].join("\n");
32867
+ const nextContent = parsed.hadFrontmatter ? `${nextFrontmatter}
32868
+ ${parsed.body}` : `${nextFrontmatter}
32869
+
32870
+ ${original}`;
32871
+ await fs7.writeFile(args.path, nextContent, "utf8");
32872
+ }
32873
+ async function moveRole(args, workspaceRoot) {
32874
+ if (!path14.isAbsolute(args.path)) {
32875
+ throw new Error(`moveRole expects an absolute path; got "${args.path}"`);
32876
+ }
32877
+ if (!isInsideAllowedRoot2(args.path, workspaceRoot)) {
32878
+ throw new Error(`Path "${args.path}" is not inside an allowlisted role root`);
32879
+ }
32880
+ const oldDir = path14.dirname(args.path);
32881
+ const oldFilename = path14.basename(args.path, ".md");
32882
+ const roots = allowedRoots2(workspaceRoot);
32883
+ const rolesRoot = roots.find((r) => path14.resolve(args.path).startsWith(r));
32884
+ if (!rolesRoot) {
32885
+ throw new Error(`Cannot determine roles root for "${args.path}"`);
32886
+ }
32887
+ const relFromRoot = path14.relative(rolesRoot, path14.dirname(args.path));
32888
+ const currentCategory = relFromRoot && relFromRoot !== "." ? relFromRoot : "";
32889
+ const newName = args.newName ?? oldFilename;
32890
+ const newCategory = args.newCategory !== void 0 ? args.newCategory : currentCategory;
32891
+ if (!NAME_REGEX2.test(newName)) {
32892
+ throw new Error(`Invalid role name: "${newName}"`);
32893
+ }
32894
+ if (newCategory && !NAME_REGEX2.test(newCategory)) {
32895
+ throw new Error(`Invalid category name: "${newCategory}"`);
32896
+ }
32897
+ const newDir = newCategory ? path14.join(rolesRoot, newCategory) : rolesRoot;
32898
+ const newPath = path14.join(newDir, `${newName}.md`);
32899
+ if (path14.resolve(newPath) === path14.resolve(args.path)) {
32900
+ return { path: args.path };
32901
+ }
32902
+ await fs7.mkdir(newDir, { recursive: true });
32903
+ try {
32904
+ await fs7.access(newPath);
32905
+ throw new Error(`A role already exists at "${newPath}"`);
32906
+ } catch (err) {
32907
+ if (err.code !== "ENOENT") throw err;
32908
+ }
32909
+ await fs7.rename(args.path, newPath);
32910
+ const frontmatterPatch = {};
32911
+ if (newName !== oldFilename) {
32912
+ frontmatterPatch.description = void 0;
32913
+ }
32914
+ await writeRoleFrontmatter(
32915
+ {
32916
+ path: newPath,
32917
+ frontmatter: {
32918
+ ...newName !== oldFilename ? { name: newName } : {}
32919
+ }
32920
+ },
32921
+ workspaceRoot
32922
+ );
32923
+ if (oldDir !== rolesRoot) {
32924
+ try {
32925
+ const remaining = await fs7.readdir(oldDir);
32926
+ if (remaining.length === 0) {
32927
+ await fs7.rmdir(oldDir);
32928
+ }
32929
+ } catch {
32930
+ }
32931
+ }
32932
+ return { path: newPath };
32933
+ }
32934
+
32935
+ // ../server/src/server/brands/scanner.ts
32936
+ import fs8 from "node:fs/promises";
32937
+ import path15 from "node:path";
32938
+ var NAME_REGEX3 = /^[a-z0-9][a-z0-9._-]*$/i;
32939
+ function resolveScopeDir3(scope, workspaceRoot) {
32940
+ if (scope === "project") {
32941
+ if (!workspaceRoot) {
32942
+ throw new Error('workspaceRoot is required for scope "project"');
32943
+ }
32944
+ return path15.join(workspaceRoot, ".brand");
32945
+ }
32946
+ throw new Error(`Unknown scope: ${scope}`);
32947
+ }
32948
+ function allowedRoots3(workspaceRoot) {
32949
+ const roots = [];
32950
+ if (workspaceRoot) {
32951
+ roots.push(path15.join(workspaceRoot, ".brand"));
32952
+ }
32953
+ return roots.map((r) => path15.resolve(r));
32954
+ }
32955
+ function isInsideAllowedRoot3(absPath, workspaceRoot) {
32956
+ const resolved = path15.resolve(absPath);
32957
+ for (const root of allowedRoots3(workspaceRoot)) {
32958
+ const rel = path15.relative(root, resolved);
32959
+ if (rel === "" || !rel.startsWith("..") && !path15.isAbsolute(rel)) {
32960
+ return true;
32961
+ }
32962
+ }
32963
+ return false;
32964
+ }
32965
+ var FRONTMATTER_RE3 = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
32966
+ function parseBrandFile(text) {
32967
+ const match = FRONTMATTER_RE3.exec(text);
32968
+ if (!match) {
32969
+ return { rawFrontmatterLines: [], body: text, hadFrontmatter: false };
32970
+ }
32971
+ return {
32972
+ rawFrontmatterLines: (match[1] ?? "").split(/\r?\n/),
32973
+ body: match[2] ?? "",
32974
+ hadFrontmatter: true
32975
+ };
32976
+ }
32977
+ function unquote2(value) {
32978
+ const trimmed = value.trim();
32979
+ if (trimmed.startsWith('"') && trimmed.endsWith('"') || trimmed.startsWith("'") && trimmed.endsWith("'")) {
32980
+ return trimmed.slice(1, -1);
32981
+ }
32982
+ return trimmed;
32983
+ }
32984
+ function quoteIfNeeded(value) {
32985
+ if (/[:#\n\[\]]/.test(value) || value.startsWith(" ") || value.endsWith(" ")) {
32986
+ return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
32987
+ }
32988
+ return value;
32989
+ }
32990
+ function parseFrontmatter2(lines) {
32991
+ const result = {
32992
+ description: "",
32993
+ tags: [],
32994
+ variables: []
32995
+ };
32996
+ let i = 0;
32997
+ while (i < lines.length) {
32998
+ const line = lines[i] ?? "";
32999
+ const keyMatch = /^([A-Za-z][A-Za-z0-9_-]*)\s*:\s*(.*)$/.exec(line);
33000
+ if (!keyMatch) {
33001
+ i++;
33002
+ continue;
33003
+ }
33004
+ const key = keyMatch[1];
33005
+ const rawValue = (keyMatch[2] ?? "").trim();
33006
+ if (key === "description") {
33007
+ result.description = unquote2(rawValue);
33008
+ i++;
33009
+ } else if (key === "tags") {
33010
+ if (rawValue) {
33011
+ result.tags = rawValue.replace(/^\[|\]$/g, "").split(",").map((s) => unquote2(s)).filter((s) => s.length > 0);
33012
+ } else {
33013
+ const items = [];
33014
+ let j = i + 1;
33015
+ while (j < lines.length) {
33016
+ const next = lines[j] ?? "";
33017
+ const m = /^\s+-\s+(.+)$/.exec(next);
33018
+ if (!m) break;
33019
+ items.push(unquote2(m[1]));
33020
+ j++;
33021
+ }
33022
+ result.tags = items;
33023
+ i = j;
33024
+ continue;
33025
+ }
33026
+ i++;
33027
+ } else if (key === "variables") {
33028
+ const vars = [];
33029
+ let j = i + 1;
33030
+ while (j < lines.length) {
33031
+ const next = lines[j] ?? "";
33032
+ if (/^\s+-\s+key\s*:\s*/.test(next)) {
33033
+ const keyVal = unquote2((/^\s+-\s+key\s*:\s*(.*)$/.exec(next) ?? [])[1] ?? "");
33034
+ const varObj = { key: keyVal, type: "text", label: "", value: "" };
33035
+ j++;
33036
+ while (j < lines.length) {
33037
+ const sub = lines[j] ?? "";
33038
+ if (/^\s+-\s+/.test(sub) && !/^\s{4,}-\s+/.test(sub)) break;
33039
+ const subMatch = /^\s+(\w+)\s*:\s*(.*)$/.exec(sub);
33040
+ if (!subMatch) {
33041
+ j++;
33042
+ break;
33043
+ }
33044
+ const subKey = subMatch[1];
33045
+ const subVal = unquote2(subMatch[2] ?? "");
33046
+ if (subKey === "type") {
33047
+ varObj.type = subVal;
33048
+ } else if (subKey === "label") {
33049
+ varObj.label = subVal;
33050
+ } else if (subKey === "value") {
33051
+ varObj.value = subVal;
33052
+ } else if (subKey === "section") {
33053
+ varObj.section = subVal;
33054
+ } else if (subKey === "options") {
33055
+ varObj.options = subVal.replace(/^\[|\]$/g, "").split(",").map((s) => unquote2(s)).filter((s) => s.length > 0);
33056
+ } else if (subKey === "fileRef") {
33057
+ varObj.fileRef = subVal;
33058
+ }
33059
+ j++;
33060
+ }
33061
+ vars.push(varObj);
33062
+ } else if (/^[A-Za-z]/.test(next)) {
33063
+ break;
33064
+ } else {
33065
+ j++;
33066
+ }
33067
+ }
33068
+ result.variables = vars;
33069
+ i = j;
33070
+ continue;
33071
+ } else {
33072
+ i++;
33073
+ }
33074
+ }
33075
+ return result;
33076
+ }
33077
+ function serializeVariables(variables) {
33078
+ if (variables.length === 0) return ["variables: []"];
33079
+ const lines = ["variables:"];
33080
+ for (const v of variables) {
33081
+ lines.push(` - key: ${quoteIfNeeded(v.key)}`);
33082
+ lines.push(` type: ${v.type}`);
33083
+ lines.push(` label: ${quoteIfNeeded(v.label)}`);
33084
+ lines.push(` value: ${quoteIfNeeded(v.value)}`);
33085
+ if (v.section) {
33086
+ lines.push(` section: ${v.section}`);
33087
+ }
33088
+ if (v.options && v.options.length > 0) {
33089
+ lines.push(` options: [${v.options.map(quoteIfNeeded).join(", ")}]`);
33090
+ }
33091
+ if (v.fileRef) {
33092
+ lines.push(` fileRef: ${quoteIfNeeded(v.fileRef)}`);
33093
+ }
33094
+ }
33095
+ return lines;
33096
+ }
33097
+ var OWNED_KEYS2 = ["description", "tags", "variables"];
33098
+ function findOwnedSpans3(lines) {
33099
+ const spans = [];
33100
+ let i = 0;
33101
+ while (i < lines.length) {
33102
+ const line = lines[i] ?? "";
33103
+ const keyMatch = /^([A-Za-z][A-Za-z0-9_-]*)\s*:\s*(.*)$/.exec(line);
33104
+ if (!keyMatch) {
33105
+ i++;
33106
+ continue;
33107
+ }
33108
+ const key = keyMatch[1];
33109
+ const rawValue = keyMatch[2] ?? "";
33110
+ if (!OWNED_KEYS2.includes(key)) {
33111
+ i++;
33112
+ continue;
33113
+ }
33114
+ let end = i + 1;
33115
+ if (rawValue.trim() === "" || rawValue.trim() === "[]") {
33116
+ while (end < lines.length) {
33117
+ const next = lines[end] ?? "";
33118
+ if (/^\s+/.test(next)) {
33119
+ end++;
33120
+ } else {
33121
+ break;
33122
+ }
33123
+ }
33124
+ }
33125
+ spans.push({ key, startLine: i, endLine: end });
33126
+ i = end;
33127
+ }
33128
+ return spans;
33129
+ }
33130
+ function rewriteFrontmatter3(originalLines, next) {
33131
+ const spans = findOwnedSpans3(originalLines);
33132
+ const ownedKeys = new Set(spans.map((s) => s.key));
33133
+ const replacements = /* @__PURE__ */ new Map();
33134
+ if (next.description !== void 0) {
33135
+ const v = next.description;
33136
+ replacements.set("description", v.length > 0 ? [`description: ${quoteIfNeeded(v)}`] : []);
33137
+ }
33138
+ if (next.tags !== void 0) {
33139
+ if (next.tags.length === 0) {
33140
+ replacements.set("tags", []);
33141
+ } else {
33142
+ replacements.set("tags", [`tags: [${next.tags.map(quoteIfNeeded).join(", ")}]`]);
33143
+ }
33144
+ }
33145
+ if (next.variables !== void 0) {
33146
+ replacements.set("variables", serializeVariables(next.variables));
33147
+ }
33148
+ const out = [];
33149
+ let i = 0;
33150
+ while (i < originalLines.length) {
33151
+ const span = spans.find((s) => s.startLine === i);
33152
+ if (span) {
33153
+ if (replacements.has(span.key)) {
33154
+ out.push(...replacements.get(span.key) ?? []);
33155
+ } else {
33156
+ for (let j = span.startLine; j < span.endLine; j++) {
33157
+ out.push(originalLines[j] ?? "");
33158
+ }
33159
+ }
33160
+ i = span.endLine;
33161
+ continue;
33162
+ }
33163
+ out.push(originalLines[i] ?? "");
33164
+ i++;
33165
+ }
33166
+ for (const key of OWNED_KEYS2) {
33167
+ if (replacements.has(key) && !ownedKeys.has(key)) {
33168
+ out.push(...replacements.get(key) ?? []);
33169
+ }
33170
+ }
33171
+ return out;
33172
+ }
33173
+ async function readBrandsFromDir(scope, dir) {
33174
+ let entries;
33175
+ try {
33176
+ entries = await fs8.readdir(dir, { withFileTypes: true });
33177
+ } catch {
33178
+ return [];
33179
+ }
33180
+ const results = [];
33181
+ for (const entry of entries) {
33182
+ if (!entry.isFile()) continue;
33183
+ if (!entry.name.endsWith(".md")) continue;
33184
+ const name = entry.name.slice(0, -".md".length);
33185
+ if (!name || !NAME_REGEX3.test(name)) continue;
33186
+ const fullPath = path15.join(dir, entry.name);
33187
+ let stat5;
33188
+ try {
33189
+ const s = await fs8.stat(fullPath);
33190
+ stat5 = { mtime: s.mtime, size: s.size };
33191
+ } catch {
33192
+ continue;
33193
+ }
33194
+ let parsed;
33195
+ try {
33196
+ const text = await fs8.readFile(fullPath, "utf8");
33197
+ const { rawFrontmatterLines, hadFrontmatter } = parseBrandFile(text);
33198
+ parsed = hadFrontmatter ? parseFrontmatter2(rawFrontmatterLines) : { description: "", tags: [], variables: [] };
33199
+ } catch {
33200
+ parsed = { description: "", tags: [], variables: [] };
33201
+ }
33202
+ results.push({
33203
+ id: `${scope}:${name}`,
33204
+ scope,
33205
+ name,
33206
+ description: parsed.description,
33207
+ tags: parsed.tags,
33208
+ variables: parsed.variables,
33209
+ path: fullPath,
33210
+ modifiedAt: stat5.mtime.toISOString(),
33211
+ size: stat5.size
33212
+ });
33213
+ }
33214
+ results.sort((a, b) => a.name.localeCompare(b.name));
33215
+ return results;
33216
+ }
33217
+ async function listBrands(args) {
33218
+ return readBrandsFromDir("project", resolveScopeDir3("project", args.workspaceRoot));
33219
+ }
33220
+ async function createBrand(args) {
33221
+ if (!NAME_REGEX3.test(args.name)) {
33222
+ throw new Error(
33223
+ `Invalid brand name "${args.name}". Use letters, digits, dot, underscore, dash.`
33224
+ );
33225
+ }
33226
+ if (args.name.includes("/") || args.name.includes("\\") || args.name.includes("..")) {
33227
+ throw new Error(`Brand name must not contain path separators or "..".`);
33228
+ }
33229
+ const dir = resolveScopeDir3("project", args.workspaceRoot);
33230
+ await fs8.mkdir(dir, { recursive: true });
33231
+ const filePath = path15.join(dir, `${args.name}.md`);
33232
+ try {
33233
+ await fs8.access(filePath);
33234
+ throw new Error(`A brand named "${args.name}" already exists at ${filePath}`);
33235
+ } catch (err) {
33236
+ if (err && typeof err === "object" && "code" in err && err.code !== "ENOENT") {
33237
+ throw err;
33238
+ }
33239
+ if (err instanceof Error && err.message.includes("already exists")) {
33240
+ throw err;
33241
+ }
33242
+ }
33243
+ await fs8.writeFile(filePath, buildStarterBrand(args.name), "utf8");
33244
+ return { path: filePath };
33245
+ }
33246
+ function buildStarterBrand(name) {
33247
+ return `---
33248
+ name: ${name}
33249
+ description: ""
33250
+ tags: []
33251
+ variables:
33252
+ - key: color.primary
33253
+ type: color
33254
+ label: Primary Color
33255
+ value: "#000000"
33256
+ - key: color.accent
33257
+ type: color
33258
+ label: Accent Color
33259
+ value: "#ffffff"
33260
+ - key: font.heading
33261
+ type: font
33262
+ label: Heading Font
33263
+ value: ""
33264
+ - key: font.body
33265
+ type: font
33266
+ label: Body Font
33267
+ value: ""
33268
+ - key: logo
33269
+ type: asset
33270
+ label: Logo
33271
+ value: ""
33272
+ - key: tone
33273
+ type: text
33274
+ label: Tone of Voice
33275
+ value: ""
33276
+ ---
33277
+
33278
+ # ${name}
33279
+
33280
+ Describe this brand's identity, design philosophy, and usage guidelines here.
33281
+ `;
33282
+ }
33283
+ var TARGET_NAME_REGEX = /^[a-z0-9][a-z0-9._-]*$/i;
33284
+ async function copyBrandAsset(args) {
33285
+ if (!args.workspaceRoot) {
33286
+ throw new Error("workspaceRoot is required to copy a brand asset");
33287
+ }
33288
+ if (!args.sourcePath || !path15.isAbsolute(args.sourcePath)) {
33289
+ throw new Error(`copyBrandAsset expects an absolute sourcePath; got "${args.sourcePath}"`);
33290
+ }
33291
+ if (!TARGET_NAME_REGEX.test(args.targetName) || args.targetName.includes("..")) {
33292
+ throw new Error(
33293
+ `Invalid targetName "${args.targetName}". Use letters, digits, dot, underscore, dash.`
33294
+ );
33295
+ }
33296
+ const stats = await fs8.stat(args.sourcePath);
33297
+ if (!stats.isFile()) {
33298
+ throw new Error(`Source path is not a regular file: ${args.sourcePath}`);
33299
+ }
33300
+ const ext = path15.extname(args.sourcePath).toLowerCase();
33301
+ const fileName = `${args.targetName}${ext}`;
33302
+ const assetsDir = path15.join(args.workspaceRoot, ".brand", "assets");
33303
+ const destAbs = path15.resolve(assetsDir, fileName);
33304
+ const rel = path15.relative(path15.resolve(assetsDir), destAbs);
33305
+ if (rel.startsWith("..") || path15.isAbsolute(rel)) {
33306
+ throw new Error(`Refusing to write outside of .brand/assets: ${destAbs}`);
33307
+ }
33308
+ await fs8.mkdir(assetsDir, { recursive: true });
33309
+ await fs8.copyFile(args.sourcePath, destAbs);
33310
+ return {
33311
+ relativePath: `assets/${fileName}`,
33312
+ absolutePath: destAbs
33313
+ };
33314
+ }
33315
+ async function uploadBrandAsset(args) {
33316
+ if (!args.workspaceRoot) {
33317
+ throw new Error("workspaceRoot is required to upload a brand asset");
33318
+ }
33319
+ if (!TARGET_NAME_REGEX.test(args.targetName) || args.targetName.includes("..")) {
33320
+ throw new Error(
33321
+ `Invalid targetName "${args.targetName}". Use letters, digits, dot, underscore, dash.`
33322
+ );
33323
+ }
33324
+ if (!args.dataBase64 || args.dataBase64.trim().length === 0) {
33325
+ throw new Error("No file data provided for brand asset upload");
33326
+ }
33327
+ const extFromSource = args.sourceName ? path15.extname(args.sourceName).toLowerCase() : "";
33328
+ const ext = extFromSource || ".png";
33329
+ const fileName = `${args.targetName}${ext}`;
33330
+ const assetsDir = path15.join(args.workspaceRoot, ".brand", "assets");
33331
+ const destAbs = path15.resolve(assetsDir, fileName);
33332
+ const rel = path15.relative(path15.resolve(assetsDir), destAbs);
33333
+ if (rel.startsWith("..") || path15.isAbsolute(rel)) {
33334
+ throw new Error(`Refusing to write outside of .brand/assets: ${destAbs}`);
33335
+ }
33336
+ let data;
33337
+ try {
33338
+ data = Buffer.from(args.dataBase64, "base64");
33339
+ } catch {
33340
+ throw new Error("Failed to decode uploaded brand asset");
33341
+ }
33342
+ if (data.length === 0) {
33343
+ throw new Error("Uploaded brand asset is empty");
33344
+ }
33345
+ await fs8.mkdir(assetsDir, { recursive: true });
33346
+ await fs8.writeFile(destAbs, data);
33347
+ return {
33348
+ relativePath: `assets/${fileName}`,
33349
+ absolutePath: destAbs
33350
+ };
33351
+ }
33352
+ async function writeBrandFrontmatter(args, workspaceRoot) {
33353
+ if (!path15.isAbsolute(args.path)) {
33354
+ throw new Error(`writeBrandFrontmatter expects an absolute path; got "${args.path}"`);
33355
+ }
33356
+ if (!isInsideAllowedRoot3(args.path, workspaceRoot)) {
33357
+ throw new Error(`Path "${args.path}" is not inside an allowlisted brand root`);
33358
+ }
33359
+ let original;
33360
+ try {
33361
+ original = await fs8.readFile(args.path, "utf8");
33362
+ } catch (err) {
33363
+ throw new Error(
33364
+ `Failed to read brand file: ${err instanceof Error ? err.message : String(err)}`
33365
+ );
33366
+ }
33367
+ const parsed = parseBrandFile(original);
33368
+ const newLines = rewriteFrontmatter3(parsed.rawFrontmatterLines, args.frontmatter);
33369
+ const nextFrontmatter = ["---", ...newLines, "---"].join("\n");
33370
+ const nextContent = parsed.hadFrontmatter ? `${nextFrontmatter}
33371
+ ${parsed.body}` : `${nextFrontmatter}
33372
+
33373
+ ${original}`;
33374
+ await fs8.writeFile(args.path, nextContent, "utf8");
33375
+ }
32274
33376
 
32275
33377
  // ../server/src/services/oauth-service.ts
32276
33378
  import { createHash as createHash3, randomBytes as randomBytes2 } from "node:crypto";
@@ -32517,57 +33619,57 @@ async function fetchGitLabUsername(fetchImpl, accessToken) {
32517
33619
  return null;
32518
33620
  }
32519
33621
  }
32520
- async function readCredential(path23, log2) {
33622
+ async function readCredential(path24, log2) {
32521
33623
  try {
32522
- const raw = await readFile3(path23, "utf8");
33624
+ const raw = await readFile3(path24, "utf8");
32523
33625
  const parsed = JSON.parse(raw);
32524
33626
  return parsed.gitlab ?? null;
32525
33627
  } catch (error) {
32526
33628
  if (isNotFound(error)) return null;
32527
- log2.warn({ err: error, path: path23 }, "oauth.credentials.read_failed");
33629
+ log2.warn({ err: error, path: path24 }, "oauth.credentials.read_failed");
32528
33630
  return null;
32529
33631
  }
32530
33632
  }
32531
- async function persistCredential(path23, credential, log2) {
32532
- await mkdir4(dirname4(path23), { recursive: true });
33633
+ async function persistCredential(path24, credential, log2) {
33634
+ await mkdir4(dirname4(path24), { recursive: true });
32533
33635
  let current = {};
32534
33636
  try {
32535
- const raw = await readFile3(path23, "utf8");
33637
+ const raw = await readFile3(path24, "utf8");
32536
33638
  current = JSON.parse(raw);
32537
33639
  } catch (error) {
32538
33640
  if (!isNotFound(error)) {
32539
- log2.warn({ err: error, path: path23 }, "oauth.credentials.read_failed_overwriting");
33641
+ log2.warn({ err: error, path: path24 }, "oauth.credentials.read_failed_overwriting");
32540
33642
  }
32541
33643
  }
32542
33644
  const next = { ...current, gitlab: credential };
32543
- const tmpPath = `${path23}.tmp-${process.pid}-${Date.now()}`;
33645
+ const tmpPath = `${path24}.tmp-${process.pid}-${Date.now()}`;
32544
33646
  await writeFile4(tmpPath, JSON.stringify(next, null, 2), { mode: 384 });
32545
- await rename(tmpPath, path23);
33647
+ await rename(tmpPath, path24);
32546
33648
  }
32547
- async function deleteCredential(path23, log2) {
33649
+ async function deleteCredential(path24, log2) {
32548
33650
  let current = {};
32549
33651
  try {
32550
- const raw = await readFile3(path23, "utf8");
33652
+ const raw = await readFile3(path24, "utf8");
32551
33653
  current = JSON.parse(raw);
32552
33654
  } catch (error) {
32553
33655
  if (isNotFound(error)) return;
32554
- log2.warn({ err: error, path: path23 }, "oauth.credentials.delete_read_failed");
33656
+ log2.warn({ err: error, path: path24 }, "oauth.credentials.delete_read_failed");
32555
33657
  return;
32556
33658
  }
32557
33659
  delete current.gitlab;
32558
33660
  if (Object.keys(current).length === 0) {
32559
33661
  try {
32560
- await unlink(path23);
33662
+ await unlink(path24);
32561
33663
  } catch (error) {
32562
33664
  if (!isNotFound(error)) {
32563
- log2.warn({ err: error, path: path23 }, "oauth.credentials.unlink_failed");
33665
+ log2.warn({ err: error, path: path24 }, "oauth.credentials.unlink_failed");
32564
33666
  }
32565
33667
  }
32566
33668
  return;
32567
33669
  }
32568
- const tmpPath = `${path23}.tmp-${process.pid}-${Date.now()}`;
33670
+ const tmpPath = `${path24}.tmp-${process.pid}-${Date.now()}`;
32569
33671
  await writeFile4(tmpPath, JSON.stringify(current, null, 2), { mode: 384 });
32570
- await rename(tmpPath, path23);
33672
+ await rename(tmpPath, path24);
32571
33673
  }
32572
33674
  function defaultGlabConfigPath() {
32573
33675
  const home = homedir4();
@@ -32582,15 +33684,15 @@ function defaultGlabConfigPath() {
32582
33684
  const xdg = process.env.XDG_CONFIG_HOME;
32583
33685
  return join9(xdg && xdg.length > 0 ? xdg : join9(home, ".config"), "glab-cli", "config.yml");
32584
33686
  }
32585
- async function writeGlabConfig(path23, credential, log2) {
32586
- await mkdir4(dirname4(path23), { recursive: true });
33687
+ async function writeGlabConfig(path24, credential, log2) {
33688
+ await mkdir4(dirname4(path24), { recursive: true });
32587
33689
  let doc;
32588
33690
  try {
32589
- const raw = await readFile3(path23, "utf8");
33691
+ const raw = await readFile3(path24, "utf8");
32590
33692
  doc = YAML.parseDocument(raw);
32591
33693
  if (doc.errors.length > 0) {
32592
33694
  log2.warn(
32593
- { errors: doc.errors.map((e) => e.message), path: path23 },
33695
+ { errors: doc.errors.map((e) => e.message), path: path24 },
32594
33696
  "oauth.glab.parse_errors_replacing"
32595
33697
  );
32596
33698
  doc = YAML.parseDocument("{}");
@@ -32599,7 +33701,7 @@ async function writeGlabConfig(path23, credential, log2) {
32599
33701
  if (isNotFound(error)) {
32600
33702
  doc = YAML.parseDocument("{}");
32601
33703
  } else {
32602
- log2.warn({ err: error, path: path23 }, "oauth.glab.read_failed_replacing");
33704
+ log2.warn({ err: error, path: path24 }, "oauth.glab.read_failed_replacing");
32603
33705
  doc = YAML.parseDocument("{}");
32604
33706
  }
32605
33707
  }
@@ -32612,18 +33714,18 @@ async function writeGlabConfig(path23, credential, log2) {
32612
33714
  if (credential.username) {
32613
33715
  hostEntry.set("user", credential.username);
32614
33716
  }
32615
- const tmpPath = `${path23}.tmp-${process.pid}-${Date.now()}`;
33717
+ const tmpPath = `${path24}.tmp-${process.pid}-${Date.now()}`;
32616
33718
  await writeFile4(tmpPath, doc.toString(), { mode: 384 });
32617
- await rename(tmpPath, path23);
33719
+ await rename(tmpPath, path24);
32618
33720
  }
32619
- async function removeGlabHost(path23, log2) {
33721
+ async function removeGlabHost(path24, log2) {
32620
33722
  let doc;
32621
33723
  try {
32622
- const raw = await readFile3(path23, "utf8");
33724
+ const raw = await readFile3(path24, "utf8");
32623
33725
  doc = YAML.parseDocument(raw);
32624
33726
  } catch (error) {
32625
33727
  if (isNotFound(error)) return;
32626
- log2.warn({ err: error, path: path23 }, "oauth.glab.remove_read_failed");
33728
+ log2.warn({ err: error, path: path24 }, "oauth.glab.remove_read_failed");
32627
33729
  return;
32628
33730
  }
32629
33731
  const hosts = doc.get("hosts");
@@ -32632,9 +33734,9 @@ async function removeGlabHost(path23, log2) {
32632
33734
  if (hosts.items.length === 0) {
32633
33735
  doc.delete("hosts");
32634
33736
  }
32635
- const tmpPath = `${path23}.tmp-${process.pid}-${Date.now()}`;
33737
+ const tmpPath = `${path24}.tmp-${process.pid}-${Date.now()}`;
32636
33738
  await writeFile4(tmpPath, doc.toString(), { mode: 384 });
32637
- await rename(tmpPath, path23);
33739
+ await rename(tmpPath, path24);
32638
33740
  }
32639
33741
  function ensureMap(doc, key) {
32640
33742
  const existing = doc.get(key);
@@ -33735,7 +34837,7 @@ var Session = class _Session {
33735
34837
  chatService,
33736
34838
  scheduleService,
33737
34839
  loopService,
33738
- workflowService,
34840
+ questService,
33739
34841
  checkoutDiffManager,
33740
34842
  github,
33741
34843
  gitlab,
@@ -33782,7 +34884,7 @@ var Session = class _Session {
33782
34884
  this.chatService = chatService;
33783
34885
  this.scheduleService = scheduleService;
33784
34886
  this.loopService = loopService;
33785
- this.workflowService = workflowService;
34887
+ this.questService = questService;
33786
34888
  this.checkoutDiffManager = checkoutDiffManager;
33787
34889
  this.github = github ?? createGitHubService();
33788
34890
  this.gitlab = gitlab ?? createGitLabService();
@@ -34361,7 +35463,13 @@ var Session = class _Session {
34361
35463
  await this.handleCloseItemsRequest(msg);
34362
35464
  break;
34363
35465
  case "update_agent_request":
34364
- await this.handleUpdateAgentRequest(msg.agentId, msg.name, msg.labels, msg.requestId);
35466
+ await this.handleUpdateAgentRequest(
35467
+ msg.agentId,
35468
+ msg.name,
35469
+ msg.labels,
35470
+ msg.requestId,
35471
+ msg.internal
35472
+ );
34365
35473
  break;
34366
35474
  case "set_voice_mode":
34367
35475
  await this.handleSetVoiceMode(msg.enabled, msg.agentId, msg.requestId);
@@ -34591,6 +35699,15 @@ var Session = class _Session {
34591
35699
  case "file_delete_request":
34592
35700
  await this.handleFileDeleteRequest(msg);
34593
35701
  break;
35702
+ case "file_explorer_delete_request":
35703
+ await this.handleFileExplorerDeleteRequest(msg);
35704
+ break;
35705
+ case "file_mkdir_request":
35706
+ await this.handleFileMkdirRequest(msg);
35707
+ break;
35708
+ case "file_move_request":
35709
+ await this.handleFileMoveRequest(msg);
35710
+ break;
34594
35711
  case "project_icon_request":
34595
35712
  await this.handleProjectIconRequest(msg);
34596
35713
  break;
@@ -34751,20 +35868,47 @@ var Session = class _Session {
34751
35868
  case "loop/stop":
34752
35869
  await this.handleLoopStopRequest(msg);
34753
35870
  break;
34754
- case "workflow/run":
34755
- await this.handleWorkflowRunRequest(msg);
35871
+ case "quest/run":
35872
+ await this.handleQuestRunRequest(msg);
35873
+ break;
35874
+ case "quest/list":
35875
+ await this.handleQuestListRequest(msg);
35876
+ break;
35877
+ case "quest/inspect":
35878
+ await this.handleQuestInspectRequest(msg);
35879
+ break;
35880
+ case "quest/stop":
35881
+ await this.handleQuestStopRequest(msg);
35882
+ break;
35883
+ case "roles/list":
35884
+ await this.handleRolesListRequest(msg);
35885
+ break;
35886
+ case "roles/list-scope":
35887
+ await this.handleRolesListScopeRequest(msg);
35888
+ break;
35889
+ case "roles/create":
35890
+ await this.handleRoleCreateRequest(msg);
35891
+ break;
35892
+ case "roles/write-frontmatter":
35893
+ await this.handleRoleWriteFrontmatterRequest(msg);
35894
+ break;
35895
+ case "roles/move":
35896
+ await this.handleRoleMoveRequest(msg);
35897
+ break;
35898
+ case "brands/list-scope":
35899
+ await this.handleBrandsListScopeRequest(msg);
34756
35900
  break;
34757
- case "workflow/list":
34758
- await this.handleWorkflowListRequest(msg);
35901
+ case "brands/create":
35902
+ await this.handleBrandCreateRequest(msg);
34759
35903
  break;
34760
- case "workflow/inspect":
34761
- await this.handleWorkflowInspectRequest(msg);
35904
+ case "brands/write-frontmatter":
35905
+ await this.handleBrandWriteFrontmatterRequest(msg);
34762
35906
  break;
34763
- case "workflow/stop":
34764
- await this.handleWorkflowStopRequest(msg);
35907
+ case "brands/asset-copy":
35908
+ await this.handleBrandAssetCopyRequest(msg);
34765
35909
  break;
34766
- case "agents/list":
34767
- await this.handleAgentsListRequest(msg);
35910
+ case "brands/asset-upload":
35911
+ await this.handleBrandAssetUploadRequest(msg);
34768
35912
  break;
34769
35913
  }
34770
35914
  } catch (error) {
@@ -35196,26 +36340,27 @@ var Session = class _Session {
35196
36340
  }
35197
36341
  await unarchiveAgentState(this.agentStorage, this.agentManager, matched.id);
35198
36342
  }
35199
- async handleUpdateAgentRequest(agentId, name, labels, requestId) {
36343
+ async handleUpdateAgentRequest(agentId, name, labels, requestId, internal) {
35200
36344
  this.sessionLogger.info(
35201
36345
  {
35202
36346
  agentId,
35203
36347
  requestId,
35204
36348
  hasName: typeof name === "string",
35205
- labelCount: labels ? Object.keys(labels).length : 0
36349
+ labelCount: labels ? Object.keys(labels).length : 0,
36350
+ internal
35206
36351
  },
35207
36352
  "session: update_agent_request"
35208
36353
  );
35209
36354
  const normalizedName = name?.trim();
35210
36355
  const normalizedLabels = labels && Object.keys(labels).length > 0 ? labels : void 0;
35211
- if (!normalizedName && !normalizedLabels) {
36356
+ if (!normalizedName && !normalizedLabels && internal === void 0) {
35212
36357
  this.emit({
35213
36358
  type: "update_agent_response",
35214
36359
  payload: {
35215
36360
  requestId,
35216
36361
  agentId,
35217
36362
  accepted: false,
35218
- error: "Nothing to update (provide name and/or labels)"
36363
+ error: "Nothing to update (provide name, labels, and/or internal)"
35219
36364
  }
35220
36365
  });
35221
36366
  return;
@@ -35223,7 +36368,8 @@ var Session = class _Session {
35223
36368
  try {
35224
36369
  await this.agentManager.updateAgentMetadata(agentId, {
35225
36370
  ...normalizedName ? { title: normalizedName } : {},
35226
- ...normalizedLabels ? { labels: normalizedLabels } : {}
36371
+ ...normalizedLabels ? { labels: normalizedLabels } : {},
36372
+ ...internal !== void 0 ? { internal } : {}
35227
36373
  });
35228
36374
  this.emit({
35229
36375
  type: "update_agent_response",
@@ -37118,7 +38264,7 @@ var Session = class _Session {
37118
38264
  homeDir: process.env.HOME ?? homedir5(),
37119
38265
  query: query2,
37120
38266
  limit
37121
- })).map((path23) => ({ path: path23, kind: "directory" }));
38267
+ })).map((path24) => ({ path: path24, kind: "directory" }));
37122
38268
  const directories = entries.filter((entry) => entry.kind === "directory").map((entry) => entry.path);
37123
38269
  this.emit({
37124
38270
  type: "directory_suggestions_response",
@@ -38015,6 +39161,104 @@ ${details}`.trim());
38015
39161
  });
38016
39162
  }
38017
39163
  }
39164
+ async handleFileExplorerDeleteRequest(request) {
39165
+ const { cwd: workspaceCwd, path: requestedPath, requestId } = request;
39166
+ const cwd = workspaceCwd.trim();
39167
+ if (!cwd) {
39168
+ this.emit({
39169
+ type: "file_explorer_delete_response",
39170
+ payload: { cwd: workspaceCwd, path: requestedPath, error: "cwd is required", requestId }
39171
+ });
39172
+ return;
39173
+ }
39174
+ try {
39175
+ await deleteEntry({ root: cwd, relativePath: requestedPath });
39176
+ this.emit({
39177
+ type: "file_explorer_delete_response",
39178
+ payload: { cwd, path: requestedPath, error: null, requestId }
39179
+ });
39180
+ } catch (error) {
39181
+ this.sessionLogger.error(
39182
+ { err: error, cwd, path: requestedPath },
39183
+ `Failed to delete entry ${requestedPath} in workspace ${cwd}`
39184
+ );
39185
+ this.emit({
39186
+ type: "file_explorer_delete_response",
39187
+ payload: { cwd, path: requestedPath, error: error?.message ?? "delete failed", requestId }
39188
+ });
39189
+ }
39190
+ }
39191
+ async handleFileMkdirRequest(request) {
39192
+ const { cwd: workspaceCwd, path: requestedPath, requestId } = request;
39193
+ const cwd = workspaceCwd.trim();
39194
+ if (!cwd) {
39195
+ this.emit({
39196
+ type: "file_mkdir_response",
39197
+ payload: { cwd: workspaceCwd, path: requestedPath, error: "cwd is required", requestId }
39198
+ });
39199
+ return;
39200
+ }
39201
+ try {
39202
+ await createDirectory({ root: cwd, relativePath: requestedPath });
39203
+ this.emit({
39204
+ type: "file_mkdir_response",
39205
+ payload: { cwd, path: requestedPath, error: null, requestId }
39206
+ });
39207
+ } catch (error) {
39208
+ this.sessionLogger.error(
39209
+ { err: error, cwd, path: requestedPath },
39210
+ `Failed to create directory ${requestedPath} in workspace ${cwd}`
39211
+ );
39212
+ this.emit({
39213
+ type: "file_mkdir_response",
39214
+ payload: {
39215
+ cwd,
39216
+ path: requestedPath,
39217
+ error: error?.message ?? "mkdir failed",
39218
+ requestId
39219
+ }
39220
+ });
39221
+ }
39222
+ }
39223
+ async handleFileMoveRequest(request) {
39224
+ const { cwd: workspaceCwd, sourcePath, destinationPath, requestId } = request;
39225
+ const cwd = workspaceCwd.trim();
39226
+ if (!cwd) {
39227
+ this.emit({
39228
+ type: "file_move_response",
39229
+ payload: {
39230
+ cwd: workspaceCwd,
39231
+ sourcePath,
39232
+ destinationPath,
39233
+ error: "cwd is required",
39234
+ requestId
39235
+ }
39236
+ });
39237
+ return;
39238
+ }
39239
+ try {
39240
+ await moveEntry({ root: cwd, sourcePath, destinationPath });
39241
+ this.emit({
39242
+ type: "file_move_response",
39243
+ payload: { cwd, sourcePath, destinationPath, error: null, requestId }
39244
+ });
39245
+ } catch (error) {
39246
+ this.sessionLogger.error(
39247
+ { err: error, cwd, sourcePath, destinationPath },
39248
+ `Failed to move ${sourcePath} to ${destinationPath} in workspace ${cwd}`
39249
+ );
39250
+ this.emit({
39251
+ type: "file_move_response",
39252
+ payload: {
39253
+ cwd,
39254
+ sourcePath,
39255
+ destinationPath,
39256
+ error: error?.message ?? "move failed",
39257
+ requestId
39258
+ }
39259
+ });
39260
+ }
39261
+ }
38018
39262
  /**
38019
39263
  * Handle project icon request for a given cwd
38020
39264
  */
@@ -40676,17 +41920,17 @@ ${details}`.trim());
40676
41920
  this.emitLoopRpcError(request, error);
40677
41921
  }
40678
41922
  }
40679
- emitWorkflowRpcError(request, error) {
41923
+ emitQuestRpcError(request, error) {
40680
41924
  const message = error instanceof Error ? error.message : String(error);
40681
41925
  const responseType = `${request.type}/response`;
40682
- if (responseType === "workflow/list/response") {
41926
+ if (responseType === "quest/list/response") {
40683
41927
  this.emit({
40684
41928
  type: responseType,
40685
- payload: { requestId: request.requestId, workflows: [], error: message }
41929
+ payload: { requestId: request.requestId, quests: [], error: message }
40686
41930
  });
40687
41931
  return;
40688
41932
  }
40689
- if (responseType === "agents/list/response") {
41933
+ if (responseType === "roles/list/response") {
40690
41934
  this.emit({
40691
41935
  type: responseType,
40692
41936
  payload: { requestId: request.requestId, roles: [], error: message }
@@ -40695,12 +41939,12 @@ ${details}`.trim());
40695
41939
  }
40696
41940
  this.emit({
40697
41941
  type: responseType,
40698
- payload: { requestId: request.requestId, workflow: null, error: message }
41942
+ payload: { requestId: request.requestId, quest: null, error: message }
40699
41943
  });
40700
41944
  }
40701
- async handleWorkflowRunRequest(request) {
41945
+ async handleQuestRunRequest(request) {
40702
41946
  try {
40703
- const workflow = await this.workflowService.run({
41947
+ const quest = await this.questService.run({
40704
41948
  kind: request.kind,
40705
41949
  cwd: request.cwd,
40706
41950
  prompt: request.prompt,
@@ -40711,16 +41955,16 @@ ${details}`.trim());
40711
41955
  summarizerEnabled: request.summarizerEnabled
40712
41956
  });
40713
41957
  this.emit({
40714
- type: "workflow/run/response",
40715
- payload: { requestId: request.requestId, workflow, error: null }
41958
+ type: "quest/run/response",
41959
+ payload: { requestId: request.requestId, quest, error: null }
40716
41960
  });
40717
41961
  } catch (error) {
40718
- this.emitWorkflowRpcError(request, error);
41962
+ this.emitQuestRpcError(request, error);
40719
41963
  }
40720
41964
  }
40721
- async handleWorkflowListRequest(request) {
41965
+ async handleQuestListRequest(request) {
40722
41966
  try {
40723
- const workflows = this.workflowService.list().map((w) => ({
41967
+ const quests = this.questService.list().map((w) => ({
40724
41968
  id: w.id,
40725
41969
  kind: w.kind,
40726
41970
  status: w.status,
@@ -40730,44 +41974,247 @@ ${details}`.trim());
40730
41974
  updatedAt: w.updatedAt
40731
41975
  }));
40732
41976
  this.emit({
40733
- type: "workflow/list/response",
40734
- payload: { requestId: request.requestId, workflows, error: null }
41977
+ type: "quest/list/response",
41978
+ payload: { requestId: request.requestId, quests, error: null }
40735
41979
  });
40736
41980
  } catch (error) {
40737
- this.emitWorkflowRpcError(request, error);
41981
+ this.emitQuestRpcError(request, error);
40738
41982
  }
40739
41983
  }
40740
- async handleWorkflowInspectRequest(request) {
41984
+ async handleQuestInspectRequest(request) {
40741
41985
  try {
40742
- const workflow = this.workflowService.inspect(request.id);
41986
+ const quest = this.questService.inspect(request.id);
40743
41987
  this.emit({
40744
- type: "workflow/inspect/response",
40745
- payload: { requestId: request.requestId, workflow, error: null }
41988
+ type: "quest/inspect/response",
41989
+ payload: { requestId: request.requestId, quest, error: null }
40746
41990
  });
40747
41991
  } catch (error) {
40748
- this.emitWorkflowRpcError(request, error);
41992
+ this.emitQuestRpcError(request, error);
40749
41993
  }
40750
41994
  }
40751
- async handleWorkflowStopRequest(request) {
41995
+ async handleQuestStopRequest(request) {
40752
41996
  try {
40753
- const workflow = await this.workflowService.stop(request.id);
41997
+ const quest = await this.questService.stop(request.id);
40754
41998
  this.emit({
40755
- type: "workflow/stop/response",
40756
- payload: { requestId: request.requestId, workflow, error: null }
41999
+ type: "quest/stop/response",
42000
+ payload: { requestId: request.requestId, quest, error: null }
40757
42001
  });
40758
42002
  } catch (error) {
40759
- this.emitWorkflowRpcError(request, error);
42003
+ this.emitQuestRpcError(request, error);
40760
42004
  }
40761
42005
  }
40762
- async handleAgentsListRequest(request) {
42006
+ async handleRolesListRequest(request) {
40763
42007
  try {
40764
- const roles = await listAgentRoles({ workspaceRoot: request.workspaceRoot });
42008
+ const roles = await listRoles({ workspaceRoot: request.workspaceRoot });
40765
42009
  this.emit({
40766
- type: "agents/list/response",
42010
+ type: "roles/list/response",
40767
42011
  payload: { requestId: request.requestId, roles, error: null }
40768
42012
  });
40769
42013
  } catch (error) {
40770
- this.emitWorkflowRpcError(request, error);
42014
+ this.emitQuestRpcError(request, error);
42015
+ }
42016
+ }
42017
+ async handleRolesListScopeRequest(request) {
42018
+ const { scope, workspaceRoot, requestId } = request;
42019
+ try {
42020
+ const roles = await listRoles({
42021
+ scope,
42022
+ ...workspaceRoot ? { workspaceRoot: expandTilde(workspaceRoot) } : {}
42023
+ });
42024
+ this.emit({
42025
+ type: "roles/list-scope/response",
42026
+ payload: { requestId, roles, error: null }
42027
+ });
42028
+ } catch (error) {
42029
+ const message = error instanceof Error ? error.message : String(error);
42030
+ this.sessionLogger.error({ err: error, scope }, "Failed to list roles by scope");
42031
+ this.emit({
42032
+ type: "roles/list-scope/response",
42033
+ payload: { requestId, roles: [], error: message }
42034
+ });
42035
+ }
42036
+ }
42037
+ async handleRoleCreateRequest(request) {
42038
+ const { scope, name, category, workspaceRoot, requestId } = request;
42039
+ try {
42040
+ const result = await createRole({
42041
+ scope,
42042
+ name,
42043
+ ...category ? { category } : {},
42044
+ ...workspaceRoot ? { workspaceRoot: expandTilde(workspaceRoot) } : {}
42045
+ });
42046
+ this.emit({
42047
+ type: "roles/create/response",
42048
+ payload: { requestId, path: result.path, error: null }
42049
+ });
42050
+ } catch (error) {
42051
+ const message = error instanceof Error ? error.message : String(error);
42052
+ this.sessionLogger.error({ err: error, scope, name }, "Failed to create role");
42053
+ this.emit({
42054
+ type: "roles/create/response",
42055
+ payload: { requestId, path: "", error: message }
42056
+ });
42057
+ }
42058
+ }
42059
+ async handleRoleWriteFrontmatterRequest(request) {
42060
+ const { path: rolePath, workspaceRoot, frontmatter, requestId } = request;
42061
+ try {
42062
+ await writeRoleFrontmatter(
42063
+ { path: rolePath, frontmatter },
42064
+ workspaceRoot ? expandTilde(workspaceRoot) : void 0
42065
+ );
42066
+ this.emit({
42067
+ type: "roles/write-frontmatter/response",
42068
+ payload: { requestId, path: rolePath, error: null }
42069
+ });
42070
+ } catch (error) {
42071
+ const message = error instanceof Error ? error.message : String(error);
42072
+ this.sessionLogger.error({ err: error, path: rolePath }, "Failed to write role frontmatter");
42073
+ this.emit({
42074
+ type: "roles/write-frontmatter/response",
42075
+ payload: { requestId, path: rolePath, error: message }
42076
+ });
42077
+ }
42078
+ }
42079
+ async handleRoleMoveRequest(request) {
42080
+ const { path: rolePath, newName, newCategory, workspaceRoot, requestId } = request;
42081
+ try {
42082
+ const result = await moveRole(
42083
+ { path: rolePath, newName, newCategory },
42084
+ workspaceRoot ? expandTilde(workspaceRoot) : void 0
42085
+ );
42086
+ this.emit({
42087
+ type: "roles/move/response",
42088
+ payload: { requestId, path: result.path, error: null }
42089
+ });
42090
+ } catch (error) {
42091
+ const message = error instanceof Error ? error.message : String(error);
42092
+ this.sessionLogger.error({ err: error, path: rolePath }, "Failed to move role");
42093
+ this.emit({
42094
+ type: "roles/move/response",
42095
+ payload: { requestId, path: rolePath, error: message }
42096
+ });
42097
+ }
42098
+ }
42099
+ async handleBrandsListScopeRequest(request) {
42100
+ const { workspaceRoot, requestId } = request;
42101
+ try {
42102
+ const brands = await listBrands({
42103
+ ...workspaceRoot ? { workspaceRoot: expandTilde(workspaceRoot) } : {}
42104
+ });
42105
+ this.emit({
42106
+ type: "brands/list-scope/response",
42107
+ payload: { requestId, brands, error: null }
42108
+ });
42109
+ } catch (error) {
42110
+ const message = error instanceof Error ? error.message : String(error);
42111
+ this.sessionLogger.error({ err: error }, "Failed to list brands");
42112
+ this.emit({
42113
+ type: "brands/list-scope/response",
42114
+ payload: { requestId, brands: [], error: message }
42115
+ });
42116
+ }
42117
+ }
42118
+ async handleBrandCreateRequest(request) {
42119
+ const { name, workspaceRoot, requestId } = request;
42120
+ try {
42121
+ const result = await createBrand({
42122
+ name,
42123
+ ...workspaceRoot ? { workspaceRoot: expandTilde(workspaceRoot) } : {}
42124
+ });
42125
+ this.emit({
42126
+ type: "brands/create/response",
42127
+ payload: { requestId, path: result.path, error: null }
42128
+ });
42129
+ } catch (error) {
42130
+ const message = error instanceof Error ? error.message : String(error);
42131
+ this.sessionLogger.error({ err: error, name }, "Failed to create brand");
42132
+ this.emit({
42133
+ type: "brands/create/response",
42134
+ payload: { requestId, path: "", error: message }
42135
+ });
42136
+ }
42137
+ }
42138
+ async handleBrandWriteFrontmatterRequest(request) {
42139
+ const { path: brandPath, workspaceRoot, frontmatter, requestId } = request;
42140
+ try {
42141
+ await writeBrandFrontmatter(
42142
+ { path: brandPath, frontmatter },
42143
+ workspaceRoot ? expandTilde(workspaceRoot) : void 0
42144
+ );
42145
+ this.emit({
42146
+ type: "brands/write-frontmatter/response",
42147
+ payload: { requestId, path: brandPath, error: null }
42148
+ });
42149
+ } catch (error) {
42150
+ const message = error instanceof Error ? error.message : String(error);
42151
+ this.sessionLogger.error(
42152
+ { err: error, path: brandPath },
42153
+ "Failed to write brand frontmatter"
42154
+ );
42155
+ this.emit({
42156
+ type: "brands/write-frontmatter/response",
42157
+ payload: { requestId, path: brandPath, error: message }
42158
+ });
42159
+ }
42160
+ }
42161
+ async handleBrandAssetCopyRequest(request) {
42162
+ const { workspaceRoot, sourcePath, targetName, requestId } = request;
42163
+ try {
42164
+ const result = await copyBrandAsset({
42165
+ workspaceRoot: expandTilde(workspaceRoot),
42166
+ sourcePath: expandTilde(sourcePath),
42167
+ targetName
42168
+ });
42169
+ this.emit({
42170
+ type: "brands/asset-copy/response",
42171
+ payload: {
42172
+ requestId,
42173
+ relativePath: result.relativePath,
42174
+ absolutePath: result.absolutePath,
42175
+ error: null
42176
+ }
42177
+ });
42178
+ } catch (error) {
42179
+ const message = error instanceof Error ? error.message : String(error);
42180
+ this.sessionLogger.error(
42181
+ { err: error, sourcePath, targetName },
42182
+ "Failed to copy brand asset"
42183
+ );
42184
+ this.emit({
42185
+ type: "brands/asset-copy/response",
42186
+ payload: { requestId, relativePath: "", absolutePath: "", error: message }
42187
+ });
42188
+ }
42189
+ }
42190
+ async handleBrandAssetUploadRequest(request) {
42191
+ const { workspaceRoot, targetName, sourceName, dataBase64, requestId } = request;
42192
+ try {
42193
+ const result = await uploadBrandAsset({
42194
+ workspaceRoot: expandTilde(workspaceRoot),
42195
+ targetName,
42196
+ sourceName,
42197
+ dataBase64
42198
+ });
42199
+ this.emit({
42200
+ type: "brands/asset-upload/response",
42201
+ payload: {
42202
+ requestId,
42203
+ relativePath: result.relativePath,
42204
+ absolutePath: result.absolutePath,
42205
+ error: null
42206
+ }
42207
+ });
42208
+ } catch (error) {
42209
+ const message = error instanceof Error ? error.message : String(error);
42210
+ this.sessionLogger.error(
42211
+ { err: error, targetName, sourceName },
42212
+ "Failed to upload brand asset"
42213
+ );
42214
+ this.emit({
42215
+ type: "brands/asset-upload/response",
42216
+ payload: { requestId, relativePath: "", absolutePath: "", error: message }
42217
+ });
40771
42218
  }
40772
42219
  }
40773
42220
  emitTerminalsChangedSnapshot(input) {
@@ -41593,11 +43040,11 @@ var LoopRecordSchema2 = z39.object({
41593
43040
  });
41594
43041
  var StoredLoopsSchema = z39.array(LoopRecordSchema2);
41595
43042
 
41596
- // ../server/src/server/workflow/store.ts
43043
+ // ../server/src/server/quest/store.ts
41597
43044
  import { z as z40 } from "zod";
41598
- var StoredWorkflowsSchema = z40.array(WorkflowRecordSchema);
43045
+ var StoredQuestsSchema = z40.array(QuestRecordSchema);
41599
43046
 
41600
- // ../server/src/server/workflow/runner-ralph.ts
43047
+ // ../server/src/server/quest/runner-ralph.ts
41601
43048
  import { promisify as promisify4 } from "node:util";
41602
43049
  import { execFile as execFile3 } from "node:child_process";
41603
43050
  var execFileAsync3 = promisify4(execFile3);
@@ -41643,16 +43090,16 @@ function isRelayClientWebSocketUrl(url) {
41643
43090
  }
41644
43091
 
41645
43092
  // ../server/src/server/config.ts
41646
- import path16 from "node:path";
43093
+ import path17 from "node:path";
41647
43094
  import { z as z45 } from "zod";
41648
43095
 
41649
43096
  // ../server/src/server/speech/speech-config-resolver.ts
41650
43097
  import { z as z44 } from "zod";
41651
43098
 
41652
43099
  // ../server/src/server/speech/providers/local/config.ts
41653
- import path15 from "node:path";
43100
+ import path16 from "node:path";
41654
43101
  import { z as z42 } from "zod";
41655
- var DEFAULT_LOCAL_MODELS_SUBDIR = path15.join("models", "local-speech");
43102
+ var DEFAULT_LOCAL_MODELS_SUBDIR = path16.join("models", "local-speech");
41656
43103
  var NumberLikeSchema2 = z42.union([z42.number(), z42.string().trim().min(1)]);
41657
43104
  var OptionalFiniteNumberSchema2 = NumberLikeSchema2.pipe(z42.coerce.number().finite()).optional();
41658
43105
  var OptionalIntegerSchema = NumberLikeSchema2.pipe(z42.coerce.number().int()).optional();
@@ -41679,7 +43126,7 @@ function resolveLocalSpeechConfig(params) {
41679
43126
  const includeProviderConfig = shouldIncludeLocalProviderConfig(params);
41680
43127
  const parsed = LocalSpeechResolutionSchema.parse({
41681
43128
  includeProviderConfig,
41682
- modelsDir: params.env.APPOSTLE_LOCAL_MODELS_DIR ?? params.persisted.providers?.local?.modelsDir ?? path15.join(params.appostleHome, DEFAULT_LOCAL_MODELS_SUBDIR),
43129
+ modelsDir: params.env.APPOSTLE_LOCAL_MODELS_DIR ?? params.persisted.providers?.local?.modelsDir ?? path16.join(params.appostleHome, DEFAULT_LOCAL_MODELS_SUBDIR),
41683
43130
  dictationLocalSttModel: params.env.APPOSTLE_DICTATION_LOCAL_STT_MODEL ?? persistedLocalFeatureModel(
41684
43131
  params.providers.dictationStt.provider,
41685
43132
  params.providers.dictationStt.enabled,
@@ -41935,7 +43382,7 @@ function loadConfig(appostleHome, options) {
41935
43382
  chromeEnabled,
41936
43383
  mcpDebug: env.MCP_DEBUG === "1",
41937
43384
  daemonIcon,
41938
- agentStoragePath: path16.join(appostleHome, "agents"),
43385
+ agentStoragePath: path17.join(appostleHome, "agents"),
41939
43386
  staticDir: "public",
41940
43387
  agentClients: {},
41941
43388
  relayEnabled,
@@ -43153,12 +44600,12 @@ var DaemonClient = class {
43153
44600
  timeout: 1e4
43154
44601
  });
43155
44602
  }
43156
- async openInEditor(path23, editorId, requestId) {
44603
+ async openInEditor(path24, editorId, requestId) {
43157
44604
  return this.sendCorrelatedSessionRequest({
43158
44605
  requestId,
43159
44606
  message: {
43160
44607
  type: "open_in_editor_request",
43161
- path: path23,
44608
+ path: path24,
43162
44609
  editorId
43163
44610
  },
43164
44611
  responseType: "open_in_editor_response",
@@ -43367,6 +44814,7 @@ var DaemonClient = class {
43367
44814
  agentId,
43368
44815
  ...updates.name !== void 0 ? { name: updates.name } : {},
43369
44816
  ...updates.labels && Object.keys(updates.labels).length > 0 ? { labels: updates.labels } : {},
44817
+ ...updates.internal !== void 0 ? { internal: updates.internal } : {},
43370
44818
  requestId
43371
44819
  });
43372
44820
  const payload = await this.sendRequest({
@@ -44419,13 +45867,13 @@ var DaemonClient = class {
44419
45867
  // ============================================================================
44420
45868
  // File Explorer
44421
45869
  // ============================================================================
44422
- async exploreFileSystem(cwd, path23, mode = "list", requestId) {
45870
+ async exploreFileSystem(cwd, path24, mode = "list", requestId) {
44423
45871
  return this.sendCorrelatedSessionRequest({
44424
45872
  requestId,
44425
45873
  message: {
44426
45874
  type: "file_explorer_request",
44427
45875
  cwd,
44428
- path: path23,
45876
+ path: path24,
44429
45877
  mode
44430
45878
  },
44431
45879
  responseType: "file_explorer_response",
@@ -44437,13 +45885,13 @@ var DaemonClient = class {
44437
45885
  * allowlists extensions (currently `.md` only) — callers don't need to
44438
45886
  * re-check. Used by the plan-todos UI to rewrite plan-file frontmatter.
44439
45887
  */
44440
- async writeFile(cwd, path23, content, requestId) {
45888
+ async writeFile(cwd, path24, content, requestId) {
44441
45889
  return this.sendCorrelatedSessionRequest({
44442
45890
  requestId,
44443
45891
  message: {
44444
45892
  type: "file_write_request",
44445
45893
  cwd,
44446
- path: path23,
45894
+ path: path24,
44447
45895
  content
44448
45896
  },
44449
45897
  responseType: "file_write_response",
@@ -44456,30 +45904,54 @@ var DaemonClient = class {
44456
45904
  * action is the only consumer). Returns the daemon's structured response
44457
45905
  * so callers can surface the error in the UI.
44458
45906
  */
44459
- async deleteFile(cwd, path23, requestId) {
45907
+ async deleteFile(cwd, path24, requestId) {
44460
45908
  return this.sendCorrelatedSessionRequest({
44461
45909
  requestId,
44462
45910
  message: {
44463
45911
  type: "file_delete_request",
44464
45912
  cwd,
44465
- path: path23
45913
+ path: path24
44466
45914
  },
44467
45915
  responseType: "file_delete_response",
44468
45916
  timeout: 1e4
44469
45917
  });
44470
45918
  }
44471
- async requestDownloadToken(cwd, path23, requestId) {
45919
+ async requestDownloadToken(cwd, path24, requestId) {
44472
45920
  return this.sendCorrelatedSessionRequest({
44473
45921
  requestId,
44474
45922
  message: {
44475
45923
  type: "file_download_token_request",
44476
45924
  cwd,
44477
- path: path23
45925
+ path: path24
44478
45926
  },
44479
45927
  responseType: "file_download_token_response",
44480
45928
  timeout: 1e4
44481
45929
  });
44482
45930
  }
45931
+ async explorerDeleteEntry(cwd, path24, requestId) {
45932
+ return this.sendCorrelatedSessionRequest({
45933
+ requestId,
45934
+ message: { type: "file_explorer_delete_request", cwd, path: path24 },
45935
+ responseType: "file_explorer_delete_response",
45936
+ timeout: 1e4
45937
+ });
45938
+ }
45939
+ async explorerMkdir(cwd, path24, requestId) {
45940
+ return this.sendCorrelatedSessionRequest({
45941
+ requestId,
45942
+ message: { type: "file_mkdir_request", cwd, path: path24 },
45943
+ responseType: "file_mkdir_response",
45944
+ timeout: 1e4
45945
+ });
45946
+ }
45947
+ async explorerMoveEntry(cwd, sourcePath, destinationPath, requestId) {
45948
+ return this.sendCorrelatedSessionRequest({
45949
+ requestId,
45950
+ message: { type: "file_move_request", cwd, sourcePath, destinationPath },
45951
+ responseType: "file_move_response",
45952
+ timeout: 1e4
45953
+ });
45954
+ }
44483
45955
  async requestProjectIcon(cwd, requestId) {
44484
45956
  return this.sendCorrelatedSessionRequest({
44485
45957
  requestId,
@@ -45214,61 +46686,177 @@ var DaemonClient = class {
45214
46686
  timeout: 1e4
45215
46687
  });
45216
46688
  }
45217
- async workflowRun(options) {
46689
+ async questRun(options) {
45218
46690
  return this.sendCorrelatedSessionRequest({
45219
46691
  requestId: options.requestId,
45220
46692
  message: {
45221
- type: "workflow/run",
46693
+ type: "quest/run",
45222
46694
  kind: options.kind,
45223
46695
  cwd: options.cwd,
45224
46696
  prompt: options.prompt,
45225
46697
  ...options.defaultProvider ? { defaultProvider: options.defaultProvider } : {},
45226
- ...options.defaultModel !== void 0 ? { defaultModel: options.defaultModel } : {},
46698
+ ...options.defaultModel ? { defaultModel: options.defaultModel } : {},
45227
46699
  termination: options.termination,
45228
46700
  ...options.cards ? { cards: [...options.cards] } : {},
45229
46701
  ...typeof options.summarizerEnabled === "boolean" ? { summarizerEnabled: options.summarizerEnabled } : {}
45230
46702
  },
45231
- responseType: "workflow/run/response",
46703
+ responseType: "quest/run/response",
45232
46704
  timeout: 15e3
45233
46705
  });
45234
46706
  }
45235
- async workflowList(requestId) {
46707
+ async questList(requestId) {
45236
46708
  return this.sendCorrelatedSessionRequest({
45237
46709
  requestId,
45238
- message: { type: "workflow/list" },
45239
- responseType: "workflow/list/response",
46710
+ message: { type: "quest/list" },
46711
+ responseType: "quest/list/response",
45240
46712
  timeout: 1e4
45241
46713
  });
45242
46714
  }
45243
- async workflowInspect(options) {
46715
+ async questInspect(options) {
45244
46716
  const normalized = typeof options === "string" ? { id: options } : options;
45245
46717
  return this.sendCorrelatedSessionRequest({
45246
46718
  requestId: normalized.requestId,
45247
- message: { type: "workflow/inspect", id: normalized.id },
45248
- responseType: "workflow/inspect/response",
46719
+ message: { type: "quest/inspect", id: normalized.id },
46720
+ responseType: "quest/inspect/response",
45249
46721
  timeout: 1e4
45250
46722
  });
45251
46723
  }
45252
- async workflowStop(options) {
46724
+ async questStop(options) {
45253
46725
  const normalized = typeof options === "string" ? { id: options } : options;
45254
46726
  return this.sendCorrelatedSessionRequest({
45255
46727
  requestId: normalized.requestId,
45256
- message: { type: "workflow/stop", id: normalized.id },
45257
- responseType: "workflow/stop/response",
46728
+ message: { type: "quest/stop", id: normalized.id },
46729
+ responseType: "quest/stop/response",
46730
+ timeout: 1e4
46731
+ });
46732
+ }
46733
+ async rolesList(options = {}) {
46734
+ return this.sendCorrelatedSessionRequest({
46735
+ requestId: options.requestId,
46736
+ message: {
46737
+ type: "roles/list",
46738
+ ...options.workspaceRoot ? { workspaceRoot: options.workspaceRoot } : {}
46739
+ },
46740
+ responseType: "roles/list/response",
45258
46741
  timeout: 1e4
45259
46742
  });
45260
46743
  }
45261
- async agentsList(options = {}) {
46744
+ async rolesListScope(options) {
45262
46745
  return this.sendCorrelatedSessionRequest({
45263
46746
  requestId: options.requestId,
45264
46747
  message: {
45265
- type: "agents/list",
46748
+ type: "roles/list-scope",
46749
+ scope: options.scope,
45266
46750
  ...options.workspaceRoot ? { workspaceRoot: options.workspaceRoot } : {}
45267
46751
  },
45268
- responseType: "agents/list/response",
46752
+ responseType: "roles/list-scope/response",
45269
46753
  timeout: 1e4
45270
46754
  });
45271
46755
  }
46756
+ async rolesCreate(options) {
46757
+ return this.sendCorrelatedSessionRequest({
46758
+ requestId: options.requestId,
46759
+ message: {
46760
+ type: "roles/create",
46761
+ scope: options.scope,
46762
+ name: options.name,
46763
+ ...options.category ? { category: options.category } : {},
46764
+ ...options.workspaceRoot ? { workspaceRoot: options.workspaceRoot } : {}
46765
+ },
46766
+ responseType: "roles/create/response",
46767
+ timeout: 1e4
46768
+ });
46769
+ }
46770
+ async rolesWriteFrontmatter(options) {
46771
+ return this.sendCorrelatedSessionRequest({
46772
+ requestId: options.requestId,
46773
+ message: {
46774
+ type: "roles/write-frontmatter",
46775
+ path: options.path,
46776
+ frontmatter: options.frontmatter,
46777
+ ...options.workspaceRoot ? { workspaceRoot: options.workspaceRoot } : {}
46778
+ },
46779
+ responseType: "roles/write-frontmatter/response",
46780
+ timeout: 1e4
46781
+ });
46782
+ }
46783
+ async rolesMove(options) {
46784
+ return this.sendCorrelatedSessionRequest({
46785
+ requestId: options.requestId,
46786
+ message: {
46787
+ type: "roles/move",
46788
+ path: options.path,
46789
+ ...options.newName ? { newName: options.newName } : {},
46790
+ ...options.newCategory !== void 0 ? { newCategory: options.newCategory } : {},
46791
+ ...options.workspaceRoot ? { workspaceRoot: options.workspaceRoot } : {}
46792
+ },
46793
+ responseType: "roles/move/response",
46794
+ timeout: 1e4
46795
+ });
46796
+ }
46797
+ async brandsListScope(options) {
46798
+ return this.sendCorrelatedSessionRequest({
46799
+ requestId: options.requestId,
46800
+ message: {
46801
+ type: "brands/list-scope",
46802
+ ...options.workspaceRoot ? { workspaceRoot: options.workspaceRoot } : {}
46803
+ },
46804
+ responseType: "brands/list-scope/response",
46805
+ timeout: 1e4
46806
+ });
46807
+ }
46808
+ async brandsCreate(options) {
46809
+ return this.sendCorrelatedSessionRequest({
46810
+ requestId: options.requestId,
46811
+ message: {
46812
+ type: "brands/create",
46813
+ name: options.name,
46814
+ ...options.workspaceRoot ? { workspaceRoot: options.workspaceRoot } : {}
46815
+ },
46816
+ responseType: "brands/create/response",
46817
+ timeout: 1e4
46818
+ });
46819
+ }
46820
+ async brandsWriteFrontmatter(options) {
46821
+ return this.sendCorrelatedSessionRequest({
46822
+ requestId: options.requestId,
46823
+ message: {
46824
+ type: "brands/write-frontmatter",
46825
+ path: options.path,
46826
+ frontmatter: options.frontmatter,
46827
+ ...options.workspaceRoot ? { workspaceRoot: options.workspaceRoot } : {}
46828
+ },
46829
+ responseType: "brands/write-frontmatter/response",
46830
+ timeout: 1e4
46831
+ });
46832
+ }
46833
+ async brandsAssetCopy(options) {
46834
+ return this.sendCorrelatedSessionRequest({
46835
+ requestId: options.requestId,
46836
+ message: {
46837
+ type: "brands/asset-copy",
46838
+ workspaceRoot: options.workspaceRoot,
46839
+ sourcePath: options.sourcePath,
46840
+ targetName: options.targetName
46841
+ },
46842
+ responseType: "brands/asset-copy/response",
46843
+ timeout: 15e3
46844
+ });
46845
+ }
46846
+ async brandsAssetUpload(options) {
46847
+ return this.sendCorrelatedSessionRequest({
46848
+ requestId: options.requestId,
46849
+ message: {
46850
+ type: "brands/asset-upload",
46851
+ workspaceRoot: options.workspaceRoot,
46852
+ targetName: options.targetName,
46853
+ ...options.sourceName ? { sourceName: options.sourceName } : {},
46854
+ dataBase64: options.dataBase64
46855
+ },
46856
+ responseType: "brands/asset-upload/response",
46857
+ timeout: 2e4
46858
+ });
46859
+ }
45272
46860
  onTerminalStreamEvent(handler) {
45273
46861
  this.terminalStreamListeners.add(handler);
45274
46862
  return () => {
@@ -45741,7 +47329,7 @@ function resolveAgentConfig(options) {
45741
47329
  }
45742
47330
 
45743
47331
  // ../cli/src/utils/client.ts
45744
- import path17 from "node:path";
47332
+ import path18 from "node:path";
45745
47333
  import WebSocket3 from "ws";
45746
47334
 
45747
47335
  // ../cli/src/utils/client-id.ts
@@ -45817,7 +47405,7 @@ function isTcpDaemonHost(host) {
45817
47405
  return host !== null && !isIpcDaemonHost(host);
45818
47406
  }
45819
47407
  function readPidSocketTarget(appostleHome) {
45820
- const pidPath = path17.join(appostleHome, PID_FILENAME);
47408
+ const pidPath = path18.join(appostleHome, PID_FILENAME);
45821
47409
  if (!existsSync10(pidPath)) {
45822
47410
  return null;
45823
47411
  }
@@ -46286,12 +47874,12 @@ function relativeTime(date) {
46286
47874
  if (seconds < 86400) return `${Math.floor(seconds / 3600)} hours ago`;
46287
47875
  return `${Math.floor(seconds / 86400)} days ago`;
46288
47876
  }
46289
- function shortenPath(path23) {
47877
+ function shortenPath(path24) {
46290
47878
  const home = process.env.HOME;
46291
- if (home && path23.startsWith(home)) {
46292
- return "~" + path23.slice(home.length);
47879
+ if (home && path24.startsWith(home)) {
47880
+ return "~" + path24.slice(home.length);
46293
47881
  }
46294
- return path23;
47882
+ return path24;
46295
47883
  }
46296
47884
  function normalizeModelId(modelId) {
46297
47885
  if (typeof modelId !== "string") return null;
@@ -47148,10 +48736,10 @@ function addSendOptions(cmd) {
47148
48736
  }
47149
48737
  async function readImageFiles(imagePaths) {
47150
48738
  const images = [];
47151
- for (const path23 of imagePaths) {
48739
+ for (const path24 of imagePaths) {
47152
48740
  try {
47153
- const buffer = await readFile5(path23);
47154
- const ext = extname3(path23).toLowerCase();
48741
+ const buffer = await readFile5(path24);
48742
+ const ext = extname3(path24).toLowerCase();
47155
48743
  let mimeType = "image/jpeg";
47156
48744
  switch (ext) {
47157
48745
  case ".png":
@@ -47179,7 +48767,7 @@ async function readImageFiles(imagePaths) {
47179
48767
  const message = err instanceof Error ? err.message : String(err);
47180
48768
  const error = {
47181
48769
  code: "IMAGE_READ_ERROR",
47182
- message: `Failed to read image file: ${path23}`,
48770
+ message: `Failed to read image file: ${path24}`,
47183
48771
  details: message
47184
48772
  };
47185
48773
  throw error;
@@ -47352,12 +48940,12 @@ function createInspectSchema(agent) {
47352
48940
  serialize: (_item) => agent
47353
48941
  };
47354
48942
  }
47355
- function shortenPath2(path23) {
48943
+ function shortenPath2(path24) {
47356
48944
  const home = process.env.HOME;
47357
- if (home && path23.startsWith(home)) {
47358
- return "~" + path23.slice(home.length);
48945
+ if (home && path24.startsWith(home)) {
48946
+ return "~" + path24.slice(home.length);
47359
48947
  }
47360
- return path23;
48948
+ return path24;
47361
48949
  }
47362
48950
  function formatCost(costUsd) {
47363
48951
  if (costUsd === 0) return "$0.00";
@@ -48325,7 +49913,7 @@ import chalk3 from "chalk";
48325
49913
  import { spawn as spawn7, spawnSync } from "node:child_process";
48326
49914
  import { existsSync as existsSync11, readFileSync as readFileSync8 } from "node:fs";
48327
49915
  import { createRequire as createRequire3 } from "node:module";
48328
- import path18 from "node:path";
49916
+ import path19 from "node:path";
48329
49917
  import { fileURLToPath } from "node:url";
48330
49918
  var DETACHED_STARTUP_GRACE_MS = 1200;
48331
49919
  var PID_POLL_INTERVAL_MS = 100;
@@ -48376,7 +49964,7 @@ function buildChildEnv(options) {
48376
49964
  function resolveDaemonRunnerEntry() {
48377
49965
  try {
48378
49966
  const here = fileURLToPath(import.meta.url);
48379
- const sibling = path18.join(path18.dirname(here), "supervisor-entrypoint.js");
49967
+ const sibling = path19.join(path19.dirname(here), "supervisor-entrypoint.js");
48380
49968
  if (existsSync11(sibling)) {
48381
49969
  return sibling;
48382
49970
  }
@@ -48390,23 +49978,23 @@ function resolveDaemonRunnerEntry() {
48390
49978
  "Unable to resolve @appostle/server package root for daemon runner (and no sibling supervisor-entrypoint.js was bundled)"
48391
49979
  );
48392
49980
  }
48393
- let currentDir = path18.dirname(serverExportPath);
49981
+ let currentDir = path19.dirname(serverExportPath);
48394
49982
  while (true) {
48395
- const packageJsonPath = path18.join(currentDir, "package.json");
49983
+ const packageJsonPath = path19.join(currentDir, "package.json");
48396
49984
  if (existsSync11(packageJsonPath)) {
48397
49985
  try {
48398
49986
  const packageJson = JSON.parse(readFileSync8(packageJsonPath, "utf-8"));
48399
49987
  if (packageJson.name === "@appostle/server") {
48400
- const distRunner = path18.join(currentDir, "dist", "scripts", "supervisor-entrypoint.js");
49988
+ const distRunner = path19.join(currentDir, "dist", "scripts", "supervisor-entrypoint.js");
48401
49989
  if (existsSync11(distRunner)) {
48402
49990
  return distRunner;
48403
49991
  }
48404
- return path18.join(currentDir, "scripts", "supervisor-entrypoint.ts");
49992
+ return path19.join(currentDir, "scripts", "supervisor-entrypoint.ts");
48405
49993
  }
48406
49994
  } catch {
48407
49995
  }
48408
49996
  }
48409
- const parentDir = path18.dirname(currentDir);
49997
+ const parentDir = path19.dirname(currentDir);
48410
49998
  if (parentDir === currentDir) {
48411
49999
  break;
48412
50000
  }
@@ -48415,7 +50003,7 @@ function resolveDaemonRunnerEntry() {
48415
50003
  throw new Error("Unable to resolve @appostle/server package root for daemon runner");
48416
50004
  }
48417
50005
  function pidFilePath(appostleHome) {
48418
- return path18.join(appostleHome, DAEMON_PID_FILENAME);
50006
+ return path19.join(appostleHome, DAEMON_PID_FILENAME);
48419
50007
  }
48420
50008
  function readPidFile(pidPath) {
48421
50009
  try {
@@ -48557,7 +50145,7 @@ function resolveLocalDaemonState(options = {}) {
48557
50145
  const home = resolveAppostleHome(env);
48558
50146
  const config = loadConfig(home, { env });
48559
50147
  const pidPath = pidFilePath(home);
48560
- const logPath = path18.join(home, DAEMON_LOG_FILENAME);
50148
+ const logPath = path19.join(home, DAEMON_LOG_FILENAME);
48561
50149
  const pidInfo = existsSync11(pidPath) ? readPidFile(pidPath) : null;
48562
50150
  const running = pidInfo ? isProcessRunning(pidInfo.pid) : false;
48563
50151
  const listen = pidInfo?.listen ?? config.listen;
@@ -48572,7 +50160,7 @@ function resolveLocalDaemonState(options = {}) {
48572
50160
  };
48573
50161
  }
48574
50162
  function tailDaemonLog(home, lines = 30) {
48575
- const logPath = path18.join(resolveLocalAppostleHome(home), DAEMON_LOG_FILENAME);
50163
+ const logPath = path19.join(resolveLocalAppostleHome(home), DAEMON_LOG_FILENAME);
48576
50164
  return tailFile(logPath, lines);
48577
50165
  }
48578
50166
  async function startLocalDaemonDetached(options) {
@@ -48581,7 +50169,7 @@ async function startLocalDaemonDetached(options) {
48581
50169
  }
48582
50170
  const childEnv = buildChildEnv(options);
48583
50171
  const appostleHome = resolveAppostleHome(childEnv);
48584
- const logPath = path18.join(appostleHome, DAEMON_LOG_FILENAME);
50172
+ const logPath = path19.join(appostleHome, DAEMON_LOG_FILENAME);
48585
50173
  const daemonRunnerEntry = resolveDaemonRunnerEntry();
48586
50174
  const child = spawn7(
48587
50175
  process.execPath,
@@ -51307,15 +52895,15 @@ import { Command as Command13 } from "commander";
51307
52895
  // ../cli/src/commands/worktree/ls.ts
51308
52896
  import { homedir as homedir7 } from "node:os";
51309
52897
  import { basename as basename7, join as join11, sep as sep3 } from "node:path";
51310
- function shortenPath3(path23) {
52898
+ function shortenPath3(path24) {
51311
52899
  const home = process.env.HOME;
51312
- if (home && path23.startsWith(home)) {
51313
- return "~" + path23.slice(home.length);
52900
+ if (home && path24.startsWith(home)) {
52901
+ return "~" + path24.slice(home.length);
51314
52902
  }
51315
- return path23;
52903
+ return path24;
51316
52904
  }
51317
- function extractWorktreeName(path23) {
51318
- return basename7(path23);
52905
+ function extractWorktreeName(path24) {
52906
+ return basename7(path24);
51319
52907
  }
51320
52908
  function resolveAppostleHomePath() {
51321
52909
  return process.env.APPOSTLE_HOME ?? join11(homedir7(), ".appostle");
@@ -51395,7 +52983,7 @@ async function runLsCommand7(options, _command) {
51395
52983
  }
51396
52984
 
51397
52985
  // ../cli/src/commands/worktree/archive.ts
51398
- import path19 from "path";
52986
+ import path20 from "path";
51399
52987
  var archiveSchema2 = {
51400
52988
  idField: "name",
51401
52989
  columns: [
@@ -51439,7 +53027,7 @@ async function runArchiveCommand2(nameArg, options, _command) {
51439
53027
  throw error;
51440
53028
  }
51441
53029
  const worktree = listResponse.worktrees.find((wt) => {
51442
- const name = path19.basename(wt.worktreePath);
53030
+ const name = path20.basename(wt.worktreePath);
51443
53031
  return name === nameArg || wt.branchName === nameArg;
51444
53032
  });
51445
53033
  if (!worktree) {
@@ -51461,7 +53049,7 @@ async function runArchiveCommand2(nameArg, options, _command) {
51461
53049
  };
51462
53050
  throw error;
51463
53051
  }
51464
- const worktreeName = path19.basename(worktree.worktreePath) || nameArg;
53052
+ const worktreeName = path20.basename(worktree.worktreePath) || nameArg;
51465
53053
  return {
51466
53054
  type: "single",
51467
53055
  data: {
@@ -51502,7 +53090,7 @@ function createWorktreeCommand() {
51502
53090
  import { cancel, confirm, intro, isCancel, log, note, outro, spinner } from "@clack/prompts";
51503
53091
  import { Command as Command14, Option as Option4 } from "commander";
51504
53092
  import { writeFileSync as writeFileSync5 } from "node:fs";
51505
- import path20 from "node:path";
53093
+ import path21 from "node:path";
51506
53094
  var DEFAULT_READY_TIMEOUT_MS = 10 * 60 * 1e3;
51507
53095
  var OnboardCancelledError = class extends Error {
51508
53096
  };
@@ -51545,7 +53133,7 @@ function toCliOverrides(options) {
51545
53133
  return cliOverrides;
51546
53134
  }
51547
53135
  function savePersistedConfig2(appostleHome, config) {
51548
- const configPath = path20.join(appostleHome, "config.json");
53136
+ const configPath = path21.join(appostleHome, "config.json");
51549
53137
  writeFileSync5(configPath, `${JSON.stringify(config, null, 2)}
51550
53138
  `);
51551
53139
  }
@@ -51666,7 +53254,7 @@ ${recentLogs}` : null
51666
53254
  );
51667
53255
  }
51668
53256
  function printNextSteps(pairingUrl, appostleHome, richUi) {
51669
- const daemonLogPath = path20.join(appostleHome, "daemon.log");
53257
+ const daemonLogPath = path21.join(appostleHome, "daemon.log");
51670
53258
  const nextStepsLines = [
51671
53259
  pairingUrl ? "1. Open Appostle and scan the QR code above, or paste the pairing link." : "1. Open Appostle and connect to your daemon.",
51672
53260
  "2. Web app: https://appostle.app",
@@ -51920,18 +53508,18 @@ function createCli() {
51920
53508
  // ../cli/src/classify.ts
51921
53509
  import { existsSync as existsSync12, statSync as statSync3 } from "node:fs";
51922
53510
  import { homedir as homedir8 } from "node:os";
51923
- import path21 from "node:path";
53511
+ import path22 from "node:path";
51924
53512
  function expandUserPath2(inputPath) {
51925
53513
  if (inputPath === "~") {
51926
53514
  return homedir8();
51927
53515
  }
51928
53516
  if (inputPath.startsWith("~/")) {
51929
- return path21.join(homedir8(), inputPath.slice(2));
53517
+ return path22.join(homedir8(), inputPath.slice(2));
51930
53518
  }
51931
53519
  return inputPath;
51932
53520
  }
51933
53521
  function isExistingDirectory(input) {
51934
- const resolvedPath = path21.resolve(input.cwd, expandUserPath2(input.pathArg));
53522
+ const resolvedPath = path22.resolve(input.cwd, expandUserPath2(input.pathArg));
51935
53523
  if (!existsSync12(resolvedPath)) {
51936
53524
  return false;
51937
53525
  }
@@ -51951,7 +53539,7 @@ function classifyInvocation(input) {
51951
53539
  if (isExistingDirectory({ pathArg: firstArg, cwd: input.cwd })) {
51952
53540
  return {
51953
53541
  kind: "open-project",
51954
- resolvedPath: path21.resolve(input.cwd, expandUserPath2(firstArg))
53542
+ resolvedPath: path22.resolve(input.cwd, expandUserPath2(firstArg))
51955
53543
  };
51956
53544
  }
51957
53545
  return { kind: "cli", argv: input.argv };
@@ -51961,12 +53549,12 @@ function classifyInvocation(input) {
51961
53549
  import { existsSync as existsSync13 } from "node:fs";
51962
53550
  import { spawn as spawn8 } from "node:child_process";
51963
53551
  import { homedir as homedir9 } from "node:os";
51964
- import path22 from "node:path";
53552
+ import path23 from "node:path";
51965
53553
  function findDesktopApp() {
51966
53554
  if (process.platform === "darwin") {
51967
53555
  const candidates = [
51968
53556
  "/Applications/Appostle.app",
51969
- path22.join(homedir9(), "Applications", "Appostle.app")
53557
+ path23.join(homedir9(), "Applications", "Appostle.app")
51970
53558
  ];
51971
53559
  for (const candidate of candidates) {
51972
53560
  if (existsSync13(candidate)) {
@@ -51979,7 +53567,7 @@ function findDesktopApp() {
51979
53567
  const candidates = [
51980
53568
  "/usr/bin/Appostle",
51981
53569
  "/opt/Appostle/Appostle",
51982
- path22.join(homedir9(), "Applications", "Appostle.AppImage")
53570
+ path23.join(homedir9(), "Applications", "Appostle.AppImage")
51983
53571
  ];
51984
53572
  for (const candidate of candidates) {
51985
53573
  if (existsSync13(candidate)) {
@@ -51993,7 +53581,7 @@ function findDesktopApp() {
51993
53581
  if (!localAppData) {
51994
53582
  return null;
51995
53583
  }
51996
- const candidate = path22.join(localAppData, "Programs", "Appostle", "Appostle.exe");
53584
+ const candidate = path23.join(localAppData, "Programs", "Appostle", "Appostle.exe");
51997
53585
  return existsSync13(candidate) ? candidate : null;
51998
53586
  }
51999
53587
  return null;