@openscout/scout 0.2.109 → 0.2.110

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.
@@ -2555,6 +2555,709 @@ function assertValidCollaborationEvent(event, record) {
2555
2555
  }
2556
2556
  }
2557
2557
 
2558
+ // ../protocol/src/runtime-catalog.generated.ts
2559
+ var SCOUT_RUNTIME_CATALOG_DATA = {
2560
+ schemaVersion: "openscout.runtime-catalog.v1",
2561
+ revision: "2026-09-24.1",
2562
+ harnesses: [
2563
+ {
2564
+ id: "claude",
2565
+ label: "Claude Code",
2566
+ enabled: true,
2567
+ default: true,
2568
+ reasoningEfforts: [
2569
+ "low",
2570
+ "medium",
2571
+ "high",
2572
+ "xhigh",
2573
+ "max"
2574
+ ],
2575
+ defaultReasoningEffort: "medium",
2576
+ presentation: {
2577
+ short: "Claude",
2578
+ monogram: "\u2733"
2579
+ },
2580
+ models: [
2581
+ {
2582
+ id: "claude-opus-5-5",
2583
+ label: "Opus 5.5",
2584
+ enabled: true,
2585
+ default: true,
2586
+ family: "Opus",
2587
+ version: "5.5",
2588
+ contextWindowTokens: 1e6,
2589
+ presentation: {
2590
+ detail: "Latest"
2591
+ }
2592
+ },
2593
+ {
2594
+ id: "claude-opus-5",
2595
+ label: "Opus 5",
2596
+ enabled: true,
2597
+ family: "Opus",
2598
+ version: "5",
2599
+ presentation: {
2600
+ detail: "Deepest"
2601
+ }
2602
+ },
2603
+ {
2604
+ id: "claude-fable-5",
2605
+ label: "Fable 5",
2606
+ enabled: true,
2607
+ family: "Fable",
2608
+ version: "5"
2609
+ },
2610
+ {
2611
+ id: "claude-sonnet-4-6",
2612
+ label: "Sonnet 4.6",
2613
+ enabled: true,
2614
+ family: "Sonnet",
2615
+ version: "4.6",
2616
+ presentation: {
2617
+ detail: "Balanced"
2618
+ }
2619
+ },
2620
+ {
2621
+ id: "claude-haiku-4-5",
2622
+ label: "Haiku 4.5",
2623
+ enabled: true,
2624
+ family: "Haiku",
2625
+ version: "4.5",
2626
+ presentation: {
2627
+ detail: "Fast"
2628
+ }
2629
+ },
2630
+ {
2631
+ id: "claude-opus-4-8",
2632
+ label: "Opus 4.8",
2633
+ enabled: true,
2634
+ family: "Opus",
2635
+ version: "4.8"
2636
+ },
2637
+ {
2638
+ id: "claude-opus-4-7",
2639
+ label: "Opus 4.7",
2640
+ enabled: true,
2641
+ family: "Opus",
2642
+ version: "4.7"
2643
+ },
2644
+ {
2645
+ id: "claude-sonnet-4-5",
2646
+ label: "Sonnet 4.5",
2647
+ enabled: true,
2648
+ family: "Sonnet",
2649
+ version: "4.5"
2650
+ }
2651
+ ]
2652
+ },
2653
+ {
2654
+ id: "codex",
2655
+ label: "Codex",
2656
+ enabled: true,
2657
+ reasoningEfforts: [
2658
+ "low",
2659
+ "medium",
2660
+ "high",
2661
+ "xhigh"
2662
+ ],
2663
+ defaultReasoningEffort: "medium",
2664
+ presentation: {
2665
+ short: "Codex",
2666
+ monogram: "\u25C8"
2667
+ },
2668
+ models: [
2669
+ {
2670
+ id: "gpt-6-astra",
2671
+ label: "6 Astra",
2672
+ enabled: true,
2673
+ default: true,
2674
+ description: "Most capable for complex reasoning, coding, computer use, research, and document creation",
2675
+ family: "GPT",
2676
+ version: "6 Astra",
2677
+ contextWindowTokens: 1050000,
2678
+ reasoningEfforts: [
2679
+ "low",
2680
+ "medium",
2681
+ "high",
2682
+ "xhigh",
2683
+ "max"
2684
+ ],
2685
+ defaultReasoningEffort: "low",
2686
+ presentation: {
2687
+ detail: "Most capable"
2688
+ }
2689
+ },
2690
+ {
2691
+ id: "gpt-6-sol",
2692
+ label: "6 Sol",
2693
+ enabled: true,
2694
+ description: "Complex coding and agentic workflows",
2695
+ family: "GPT",
2696
+ version: "6 Sol",
2697
+ contextWindowTokens: 272000,
2698
+ reasoningEfforts: [
2699
+ "low",
2700
+ "medium",
2701
+ "high",
2702
+ "xhigh",
2703
+ "max",
2704
+ "ultra"
2705
+ ],
2706
+ presentation: {
2707
+ detail: "Coding"
2708
+ }
2709
+ },
2710
+ {
2711
+ id: "gpt-6-luna",
2712
+ label: "6 Luna",
2713
+ enabled: true,
2714
+ description: "Efficient focused coding and repeatable tasks",
2715
+ family: "GPT",
2716
+ version: "6 Luna",
2717
+ contextWindowTokens: 272000,
2718
+ reasoningEfforts: [
2719
+ "low",
2720
+ "medium",
2721
+ "high",
2722
+ "xhigh",
2723
+ "max"
2724
+ ],
2725
+ presentation: {
2726
+ detail: "Efficient"
2727
+ }
2728
+ },
2729
+ {
2730
+ id: "gpt-5.6-sol",
2731
+ label: "5.6 Sol",
2732
+ enabled: true,
2733
+ family: "GPT",
2734
+ version: "5.6 Sol",
2735
+ reasoningEfforts: [
2736
+ "low",
2737
+ "medium",
2738
+ "high",
2739
+ "xhigh",
2740
+ "ultra"
2741
+ ],
2742
+ presentation: {
2743
+ detail: "Frontier"
2744
+ }
2745
+ },
2746
+ {
2747
+ id: "gpt-5.6-terra",
2748
+ label: "5.6 Terra",
2749
+ enabled: true,
2750
+ family: "GPT",
2751
+ version: "5.6 Terra",
2752
+ reasoningEfforts: [
2753
+ "low",
2754
+ "medium",
2755
+ "high",
2756
+ "xhigh",
2757
+ "ultra"
2758
+ ],
2759
+ presentation: {
2760
+ detail: "Frontier"
2761
+ }
2762
+ },
2763
+ {
2764
+ id: "gpt-5.6-luna",
2765
+ label: "5.6 Luna",
2766
+ enabled: true,
2767
+ family: "GPT",
2768
+ version: "5.6 Luna",
2769
+ presentation: {
2770
+ detail: "Efficient"
2771
+ }
2772
+ },
2773
+ {
2774
+ id: "gpt-5.5",
2775
+ label: "5.5",
2776
+ enabled: true,
2777
+ family: "GPT",
2778
+ version: "5.5"
2779
+ },
2780
+ {
2781
+ id: "gpt-5.5-mini",
2782
+ label: "5.5 mini",
2783
+ enabled: true,
2784
+ family: "GPT",
2785
+ version: "5.5 mini",
2786
+ presentation: {
2787
+ detail: "Fast"
2788
+ }
2789
+ }
2790
+ ]
2791
+ },
2792
+ {
2793
+ id: "grok",
2794
+ label: "Grok CLI",
2795
+ enabled: true,
2796
+ listed: false,
2797
+ reasoningEfforts: [
2798
+ "low",
2799
+ "medium",
2800
+ "high",
2801
+ "xhigh"
2802
+ ],
2803
+ defaultReasoningEffort: "high",
2804
+ presentation: {
2805
+ short: "Grok",
2806
+ monogram: "\u2715"
2807
+ },
2808
+ models: [
2809
+ {
2810
+ id: "grok-4.6",
2811
+ label: "Grok 4.6",
2812
+ enabled: true,
2813
+ default: true,
2814
+ family: "Grok",
2815
+ version: "4.6",
2816
+ contextWindowTokens: 500000,
2817
+ presentation: {
2818
+ detail: "Latest"
2819
+ }
2820
+ },
2821
+ {
2822
+ id: "grok-4.5",
2823
+ label: "Grok 4.5",
2824
+ enabled: true,
2825
+ family: "Grok",
2826
+ version: "4.5",
2827
+ contextWindowTokens: 500000
2828
+ }
2829
+ ]
2830
+ },
2831
+ {
2832
+ id: "grok-acp",
2833
+ label: "Grok",
2834
+ enabled: true,
2835
+ reasoningEfforts: [
2836
+ "low",
2837
+ "medium",
2838
+ "high",
2839
+ "xhigh"
2840
+ ],
2841
+ defaultReasoningEffort: "high",
2842
+ presentation: {
2843
+ short: "Grok",
2844
+ monogram: "\u2715"
2845
+ },
2846
+ models: [
2847
+ {
2848
+ id: "grok-4.6",
2849
+ label: "Grok 4.6",
2850
+ enabled: true,
2851
+ default: true,
2852
+ family: "Grok",
2853
+ version: "4.6",
2854
+ contextWindowTokens: 500000,
2855
+ presentation: {
2856
+ detail: "Latest"
2857
+ }
2858
+ },
2859
+ {
2860
+ id: "grok-4.5",
2861
+ label: "Grok 4.5",
2862
+ enabled: true,
2863
+ family: "Grok",
2864
+ version: "4.5",
2865
+ contextWindowTokens: 500000
2866
+ }
2867
+ ]
2868
+ },
2869
+ {
2870
+ id: "kimi",
2871
+ label: "Kimi Code",
2872
+ enabled: true,
2873
+ reasoningEfforts: null,
2874
+ presentation: {
2875
+ short: "Kimi",
2876
+ monogram: "\u25D0"
2877
+ },
2878
+ models: []
2879
+ },
2880
+ {
2881
+ id: "flue",
2882
+ label: "Flue",
2883
+ enabled: true,
2884
+ listed: false,
2885
+ reasoningEfforts: null,
2886
+ models: []
2887
+ },
2888
+ {
2889
+ id: "cursor",
2890
+ label: "Cursor CLI",
2891
+ enabled: true,
2892
+ reasoningEfforts: null,
2893
+ models: []
2894
+ },
2895
+ {
2896
+ id: "opencode",
2897
+ label: "OpenCode",
2898
+ enabled: true,
2899
+ reasoningEfforts: null,
2900
+ models: [
2901
+ {
2902
+ id: "opencode-go/glm-5.2",
2903
+ label: "GLM-5.2",
2904
+ enabled: true,
2905
+ default: true,
2906
+ family: "GLM",
2907
+ version: "5.2"
2908
+ },
2909
+ {
2910
+ id: "opencode-go/glm-5.1",
2911
+ label: "GLM-5.1",
2912
+ enabled: true,
2913
+ family: "GLM",
2914
+ version: "5.1"
2915
+ },
2916
+ {
2917
+ id: "opencode-go/kimi-k3",
2918
+ label: "Kimi K3",
2919
+ enabled: true,
2920
+ family: "Kimi",
2921
+ version: "K3"
2922
+ },
2923
+ {
2924
+ id: "opencode-go/qwen3.8-max",
2925
+ label: "Qwen3.8 Max",
2926
+ enabled: true,
2927
+ family: "Qwen",
2928
+ version: "3.8 Max"
2929
+ },
2930
+ {
2931
+ id: "opencode-go/minimax-m3",
2932
+ label: "MiniMax M3",
2933
+ enabled: true,
2934
+ family: "MiniMax",
2935
+ version: "M3"
2936
+ },
2937
+ {
2938
+ id: "opencode-go/deepseek-v4-pro",
2939
+ label: "DeepSeek V4 Pro",
2940
+ enabled: true,
2941
+ family: "DeepSeek",
2942
+ version: "V4 Pro"
2943
+ },
2944
+ {
2945
+ id: "opencode-go/grok-4.5",
2946
+ label: "Grok 4.5",
2947
+ enabled: true,
2948
+ family: "Grok",
2949
+ version: "4.5"
2950
+ },
2951
+ {
2952
+ id: "opencode/nemotron-3-ultra-free",
2953
+ label: "Nemotron 3 Ultra (free)",
2954
+ enabled: true,
2955
+ family: "Nemotron",
2956
+ version: "3 Ultra Free"
2957
+ },
2958
+ {
2959
+ id: "opencode/laguna-s-2.1-free",
2960
+ label: "Laguna S 2.1 (free)",
2961
+ enabled: true,
2962
+ family: "Laguna",
2963
+ version: "S 2.1 Free"
2964
+ }
2965
+ ]
2966
+ },
2967
+ {
2968
+ id: "pi",
2969
+ label: "Pi",
2970
+ enabled: true,
2971
+ reasoningEfforts: null,
2972
+ models: []
2973
+ },
2974
+ {
2975
+ id: "devin",
2976
+ label: "Devin",
2977
+ enabled: true,
2978
+ reasoningEfforts: null,
2979
+ models: [
2980
+ {
2981
+ id: "swe-2-high",
2982
+ label: "SWE-2 High",
2983
+ enabled: true,
2984
+ default: true,
2985
+ family: "SWE",
2986
+ version: "2 High",
2987
+ contextWindowTokens: 262000
2988
+ },
2989
+ {
2990
+ id: "swe-2-medium",
2991
+ label: "SWE-2 Medium",
2992
+ enabled: true,
2993
+ family: "SWE",
2994
+ version: "2 Medium",
2995
+ contextWindowTokens: 262000
2996
+ },
2997
+ {
2998
+ id: "swe-2-max",
2999
+ label: "SWE-2 Max",
3000
+ enabled: true,
3001
+ family: "SWE",
3002
+ version: "2 Max",
3003
+ contextWindowTokens: 262000
3004
+ }
3005
+ ]
3006
+ }
3007
+ ]
3008
+ };
3009
+
3010
+ // ../protocol/src/runtime-catalog-contract.ts
3011
+ var SCOUT_LAUNCHABLE_HARNESSES = [
3012
+ "claude",
3013
+ "codex",
3014
+ "grok",
3015
+ "grok-acp",
3016
+ "kimi",
3017
+ "flue",
3018
+ "cursor",
3019
+ "opencode",
3020
+ "pi",
3021
+ "devin"
3022
+ ];
3023
+ var SCOUT_REASONING_EFFORTS = [
3024
+ "none",
3025
+ "minimal",
3026
+ "low",
3027
+ "medium",
3028
+ "high",
3029
+ "xhigh",
3030
+ "max",
3031
+ "ultra"
3032
+ ];
3033
+ var SCOUT_REASONING_EFFORT_LABELS = {
3034
+ none: "None",
3035
+ minimal: "Minimal",
3036
+ low: "Light",
3037
+ medium: "Medium",
3038
+ high: "High",
3039
+ xhigh: "Extra High",
3040
+ max: "Max",
3041
+ ultra: "Ultra"
3042
+ };
3043
+
3044
+ // ../protocol/src/runtime-execution.ts
3045
+ var SCOUT_RUNTIME_CATALOG = SCOUT_RUNTIME_CATALOG_DATA;
3046
+ function scoutRuntimeHarness(harness, catalog = SCOUT_RUNTIME_CATALOG) {
3047
+ return catalog.harnesses.find((entry) => entry.id === harness);
3048
+ }
3049
+ function isModelSelectableHarness(harness, catalog = SCOUT_RUNTIME_CATALOG) {
3050
+ const entry = scoutRuntimeHarness(harness, catalog);
3051
+ return entry?.enabled === true && entry.models.some((model) => model.enabled);
3052
+ }
3053
+ function scoutRuntimeDefaultModel(harness, catalog = SCOUT_RUNTIME_CATALOG) {
3054
+ const entry = scoutRuntimeHarness(harness, catalog);
3055
+ return entry?.models.find((model) => model.enabled && model.default)?.id ?? entry?.models.find((model) => model.enabled)?.id ?? null;
3056
+ }
3057
+ function scoutRuntimeReasoningEfforts(harness, model, catalog = SCOUT_RUNTIME_CATALOG) {
3058
+ const entry = scoutRuntimeHarness(harness, catalog);
3059
+ if (!entry || !entry.enabled)
3060
+ return null;
3061
+ const selected = model ? entry.models.find((candidate) => candidate.enabled && candidate.id === model) : undefined;
3062
+ return selected?.reasoningEfforts === null ? null : selected?.reasoningEfforts ?? entry.reasoningEfforts;
3063
+ }
3064
+ function scoutRuntimeDefaultReasoningEffort(harness, model, catalog = SCOUT_RUNTIME_CATALOG) {
3065
+ const entry = scoutRuntimeHarness(harness, catalog);
3066
+ const selected = model ? entry?.models.find((candidate) => candidate.enabled && candidate.id === model) : undefined;
3067
+ const efforts = scoutRuntimeReasoningEfforts(harness, model, catalog);
3068
+ const preferred = selected?.defaultReasoningEffort ?? entry?.defaultReasoningEffort ?? null;
3069
+ return preferred && efforts?.includes(preferred) ? preferred : efforts?.[0] ?? null;
3070
+ }
3071
+ function scoutRuntimeDefaultsByHarness(catalog = SCOUT_RUNTIME_CATALOG) {
3072
+ return Object.fromEntries(catalog.harnesses.filter((entry) => entry.enabled).map((entry) => {
3073
+ const model = scoutRuntimeDefaultModel(entry.id, catalog);
3074
+ return [entry.id, {
3075
+ model,
3076
+ reasoningEffort: scoutRuntimeDefaultReasoningEffort(entry.id, model, catalog)
3077
+ }];
3078
+ }));
3079
+ }
3080
+ var SCOUT_RUNTIME_DEFAULTS_BY_HARNESS = scoutRuntimeDefaultsByHarness();
3081
+ var SCOUT_REASONING_EFFORTS_BY_HARNESS = Object.fromEntries(SCOUT_RUNTIME_CATALOG.harnesses.filter((entry) => entry.enabled).map((entry) => {
3082
+ const supported = SCOUT_REASONING_EFFORTS.filter((effort) => entry.reasoningEfforts?.includes(effort) || entry.models.some((model) => model.enabled && model.reasoningEfforts?.includes(effort)));
3083
+ return [entry.id, supported];
3084
+ }));
3085
+ function scoutRuntimeModelCatalog(catalog = SCOUT_RUNTIME_CATALOG) {
3086
+ const models = new Map;
3087
+ for (const harness of catalog.harnesses) {
3088
+ if (!harness.enabled)
3089
+ continue;
3090
+ for (const model of harness.models) {
3091
+ if (!model.enabled)
3092
+ continue;
3093
+ const existing = models.get(model.id);
3094
+ if (existing) {
3095
+ if (!existing.harnesses.includes(harness.id))
3096
+ existing.harnesses.push(harness.id);
3097
+ continue;
3098
+ }
3099
+ models.set(model.id, {
3100
+ id: model.id,
3101
+ label: model.label,
3102
+ ...model.description ? { description: model.description } : {},
3103
+ harnesses: [harness.id],
3104
+ source: "default",
3105
+ ...model.family ? { family: model.family } : {},
3106
+ ...model.version ? { version: model.version } : {},
3107
+ ...model.default === true ? { isDefault: true } : {},
3108
+ ...model.presentation ? { presentation: model.presentation } : {}
3109
+ });
3110
+ }
3111
+ }
3112
+ return Array.from(models.values());
3113
+ }
3114
+ var SCOUT_RUNTIME_MODEL_CATALOG = scoutRuntimeModelCatalog();
3115
+ var SCOUT_RUNTIME_EFFORT_DESCRIPTIONS = {
3116
+ none: "No extra thinking",
3117
+ minimal: "Smallest reasoning budget",
3118
+ low: "Fast responses with lighter reasoning",
3119
+ medium: "Balanced speed and reasoning depth",
3120
+ high: "Greater reasoning depth for complex work",
3121
+ xhigh: "Extra high reasoning depth",
3122
+ max: "Maximum reasoning depth",
3123
+ ultra: "Maximum reasoning with delegation"
3124
+ };
3125
+ function scoutRuntimeEffortCatalog(catalog = SCOUT_RUNTIME_CATALOG) {
3126
+ return SCOUT_REASONING_EFFORTS.flatMap((id) => {
3127
+ const harnesses = [];
3128
+ const restrictedModels = [];
3129
+ for (const harness of catalog.harnesses) {
3130
+ if (!harness.enabled)
3131
+ continue;
3132
+ const enabledModels = harness.models.filter((model) => model.enabled);
3133
+ const supportingModels = enabledModels.filter((model) => (model.reasoningEfforts ?? harness.reasoningEfforts)?.includes(id));
3134
+ const supportedWithoutModel = enabledModels.length === 0 && harness.reasoningEfforts?.includes(id);
3135
+ if (supportingModels.length === 0 && !supportedWithoutModel)
3136
+ continue;
3137
+ harnesses.push(harness.id);
3138
+ if (enabledModels.length > 0 && supportingModels.length < enabledModels.length) {
3139
+ restrictedModels.push(...supportingModels.map((model) => model.id));
3140
+ }
3141
+ }
3142
+ if (harnesses.length === 0)
3143
+ return [];
3144
+ return [{
3145
+ id,
3146
+ label: SCOUT_REASONING_EFFORT_LABELS[id],
3147
+ description: SCOUT_RUNTIME_EFFORT_DESCRIPTIONS[id],
3148
+ harnesses,
3149
+ ...restrictedModels.length > 0 ? { models: restrictedModels } : {}
3150
+ }];
3151
+ });
3152
+ }
3153
+ var SCOUT_RUNTIME_EFFORT_CATALOG = scoutRuntimeEffortCatalog();
3154
+ function parseScoutRuntimeSpec(input) {
3155
+ const raw = input.trim();
3156
+ const parts = raw.split("/");
3157
+ if (!raw || parts.length > 3 || parts.some((part) => !part.trim())) {
3158
+ return {
3159
+ ok: false,
3160
+ error: "runtime must be <harness>[/<model>[/<effort>]]"
3161
+ };
3162
+ }
3163
+ const rawHarness = parts[0].trim().toLowerCase();
3164
+ const harness = rawHarness === "oc" ? "opencode" : rawHarness;
3165
+ if (!isScoutLaunchableHarness(harness)) {
3166
+ return {
3167
+ ok: false,
3168
+ error: `unsupported runtime harness "${parts[0]}"; expected one of: ${SCOUT_LAUNCHABLE_HARNESSES.join(", ")}`
3169
+ };
3170
+ }
3171
+ const model = parts[1]?.trim();
3172
+ const effortRaw = parts[2]?.trim();
3173
+ const reasoningEffort = effortRaw ? normalizeScoutReasoningEffort(effortRaw) : null;
3174
+ if (effortRaw && !reasoningEffort) {
3175
+ return {
3176
+ ok: false,
3177
+ error: `unsupported reasoning effort "${effortRaw}"; expected one of: ${SCOUT_REASONING_EFFORTS.join(", ")}`
3178
+ };
3179
+ }
3180
+ const issues = validateScoutRuntimeTuple({ harness, model, reasoningEffort });
3181
+ if (issues.length > 0) {
3182
+ return { ok: false, error: issues.map((issue) => issue.message).join("; ") };
3183
+ }
3184
+ return {
3185
+ ok: true,
3186
+ value: {
3187
+ harness,
3188
+ ...model ? { model } : {},
3189
+ ...reasoningEffort ? { reasoningEffort } : {}
3190
+ }
3191
+ };
3192
+ }
3193
+ function isScoutLaunchableHarness(value) {
3194
+ if (!value)
3195
+ return false;
3196
+ const normalized = value.trim().toLowerCase();
3197
+ return normalized === "oc" || SCOUT_LAUNCHABLE_HARNESSES.includes(normalized);
3198
+ }
3199
+ function normalizeScoutReasoningEffort(value) {
3200
+ const normalized = value?.trim().toLowerCase();
3201
+ return normalized && SCOUT_REASONING_EFFORTS.includes(normalized) ? normalized : null;
3202
+ }
3203
+ function validateScoutRuntimeTuple(input, catalog, ownedCatalog = SCOUT_RUNTIME_CATALOG) {
3204
+ const rawHarness = input.harness?.trim().toLowerCase();
3205
+ const harness = rawHarness === "oc" ? "opencode" : rawHarness;
3206
+ const model = input.model?.trim();
3207
+ const effortRaw = input.reasoningEffort?.trim();
3208
+ const issues = [];
3209
+ if (harness && !ownedCatalog.harnesses.some((entry) => entry.id === harness)) {
3210
+ issues.push({
3211
+ code: "unsupported_harness",
3212
+ dimension: "harness",
3213
+ message: `unsupported harness "${input.harness}"; expected one of: ${ownedCatalog.harnesses.map((entry) => entry.id).join(", ")}`
3214
+ });
3215
+ return issues;
3216
+ }
3217
+ const effort = effortRaw ? normalizeScoutReasoningEffort(effortRaw) : null;
3218
+ if (effortRaw && !effort) {
3219
+ issues.push({
3220
+ code: "unsupported_reasoning_effort",
3221
+ dimension: "reasoningEffort",
3222
+ message: `unsupported reasoning effort "${effortRaw}"; expected one of: ${SCOUT_REASONING_EFFORTS.join(", ")}`
3223
+ });
3224
+ } else if (effort && harness) {
3225
+ const catalogEffort = catalog?.efforts.find((candidate) => candidate.id === effort);
3226
+ let supported = catalogEffort ? catalogEffort.harnesses.includes(harness) : (scoutRuntimeReasoningEfforts(harness, model, ownedCatalog) ?? []).includes(effort);
3227
+ if (supported && catalogEffort?.models?.length && model) {
3228
+ const harnessModels = new Set(catalog?.models.filter((candidate) => candidate.harnesses.includes(harness)).map((candidate) => candidate.id.toLowerCase()) ?? []);
3229
+ const scopedModels = catalogEffort.models.filter((candidate) => harnessModels.has(candidate.toLowerCase()));
3230
+ if (harnessModels.has(model.toLowerCase()) && scopedModels.length > 0) {
3231
+ supported = scopedModels.some((candidate) => candidate.toLowerCase() === model.toLowerCase());
3232
+ }
3233
+ }
3234
+ if (!supported) {
3235
+ issues.push({
3236
+ code: "reasoning_effort_harness_mismatch",
3237
+ dimension: "reasoningEffort",
3238
+ message: `reasoning effort "${effort}" is not supported by harness "${harness}"`
3239
+ });
3240
+ }
3241
+ }
3242
+ if (model && harness && !isModelSelectableHarness(harness, ownedCatalog)) {
3243
+ issues.push({
3244
+ code: "unsupported_model_dimension",
3245
+ dimension: "model",
3246
+ message: `model selection is not supported by harness "${harness}"`
3247
+ });
3248
+ } else if (model && harness && catalog) {
3249
+ const known = catalog.models.find((candidate) => candidate.id.toLowerCase() === model.toLowerCase());
3250
+ if (known && !known.harnesses.includes(harness)) {
3251
+ issues.push({
3252
+ code: "model_harness_mismatch",
3253
+ dimension: "model",
3254
+ message: `model "${model}" is not supported by harness "${harness}"`
3255
+ });
3256
+ }
3257
+ }
3258
+ return issues;
3259
+ }
3260
+
2558
3261
  // ../protocol/src/presence.ts
2559
3262
  var PRESENCE_STALE_AFTER_MS = 45000;
2560
3263
  var PRESENCE_GONE_AFTER_STALE_MS = 60000;
@@ -2570,18 +3273,41 @@ function isPresenceGone(beat, now, options = {}) {
2570
3273
  return presenceLifecycle(beat, now, options) === "gone";
2571
3274
  }
2572
3275
 
2573
- // ../protocol/src/runtime-catalog-contract.ts
2574
- var SCOUT_LAUNCHABLE_HARNESSES = [
2575
- "claude",
2576
- "codex",
2577
- "grok",
2578
- "grok-acp",
3276
+ // ../protocol/src/session-handle.ts
3277
+ var SCOUT_SESSION_ADDRESS_PREFIX = "session:";
3278
+ var SCOUT_CANONICAL_SESSION_HANDLE_PATTERN = /^sess\.[A-Za-z0-9_-]{10,64}$/;
3279
+ function isScoutSessionHandle(value) {
3280
+ return typeof value === "string" && SCOUT_CANONICAL_SESSION_HANDLE_PATTERN.test(value);
3281
+ }
3282
+ function normalizeScoutSessionHost(value) {
3283
+ if (typeof value !== "string")
3284
+ return "";
3285
+ return value.trim().toLowerCase().replace(/\.+$/, "").replace(/\.local$/, "").replace(/[^a-z0-9.-]+/g, "-").replace(/-+/g, "-").replace(/^[-.]+|[-.]+$/g, "");
3286
+ }
3287
+ var SCOUT_SESSION_HOST_PATTERN = /^[a-z0-9](?:[a-z0-9.-]{0,251}[a-z0-9])?$/;
3288
+ function parseScoutSessionHostAddress(value) {
3289
+ if (typeof value !== "string")
3290
+ return null;
3291
+ const trimmed = value.trim();
3292
+ const bare = trimmed.startsWith(SCOUT_SESSION_ADDRESS_PREFIX) ? trimmed.slice(SCOUT_SESSION_ADDRESS_PREFIX.length) : trimmed;
3293
+ const at = bare.indexOf("@");
3294
+ if (at <= 0 || at !== bare.lastIndexOf("@"))
3295
+ return null;
3296
+ const handle = bare.slice(0, at);
3297
+ const host = normalizeScoutSessionHost(bare.slice(at + 1));
3298
+ if (!isScoutSessionHandle(handle) || !SCOUT_SESSION_HOST_PATTERN.test(host))
3299
+ return null;
3300
+ return { handle, host };
3301
+ }
3302
+
3303
+ // ../protocol/src/runtime-profiles.ts
3304
+ var SCOUT_RESERVED_RUNTIME_PROFILE_IDS = [
3305
+ "fable",
2579
3306
  "kimi",
2580
- "flue",
2581
- "cursor",
2582
- "opencode",
2583
- "pi",
2584
- "devin"
3307
+ "grok",
3308
+ "opus",
3309
+ "oc",
3310
+ "opencode"
2585
3311
  ];
2586
3312
 
2587
3313
  // ../protocol/src/scout-composer.ts
@@ -2619,11 +3345,27 @@ function parseRouteAliasTarget(rawValue) {
2619
3345
  return null;
2620
3346
  return { kind: "route_alias", alias, value: `alias:${alias}` };
2621
3347
  }
3348
+ function parseSessionHostAddressTarget(value) {
3349
+ const address = parseScoutSessionHostAddress(value);
3350
+ if (!address) {
3351
+ return null;
3352
+ }
3353
+ return {
3354
+ kind: "session_id",
3355
+ sessionId: address.handle,
3356
+ host: address.host,
3357
+ value: `session:${address.handle}@${address.host}`
3358
+ };
3359
+ }
2622
3360
  function parseSessionRouteTarget(rawValue) {
2623
3361
  const value = rawValue.replace(/^@+/, "");
2624
3362
  if (!isRouteValue(value)) {
2625
3363
  return null;
2626
3364
  }
3365
+ const hostAddress = parseSessionHostAddressTarget(value);
3366
+ if (hostAddress) {
3367
+ return hostAddress;
3368
+ }
2627
3369
  const harnessSeparator = value.indexOf(":");
2628
3370
  if (harnessSeparator > 0) {
2629
3371
  const maybeHarness = value.slice(0, harnessSeparator);
@@ -2690,6 +3432,10 @@ function parseScoutComposerRouteTarget(value) {
2690
3432
  return prefixed;
2691
3433
  }
2692
3434
  }
3435
+ const hostAddress = parseSessionHostAddressTarget(token);
3436
+ if (hostAddress) {
3437
+ return hostAddress;
3438
+ }
2693
3439
  return parseAgentLabelTarget(token);
2694
3440
  }
2695
3441
 
@@ -2762,7 +3508,7 @@ function validateScoutRendezvousCodename(codename) {
2762
3508
 
2763
3509
  // ../runtime/src/setup.ts
2764
3510
  import { homedir as homedir3, hostname, userInfo } from "os";
2765
- import { basename, dirname as dirname2, isAbsolute, join as join4, relative, resolve } from "path";
3511
+ import { basename, dirname as dirname3, isAbsolute, join as join4, relative, resolve } from "path";
2766
3512
  import { fileURLToPath } from "url";
2767
3513
 
2768
3514
  // ../../node_modules/.bun/smol-toml@1.6.1/node_modules/smol-toml/dist/error.js
@@ -3307,7 +4053,7 @@ function harnessAuthModel(harness) {
3307
4053
  }
3308
4054
  // ../runtime/src/support-paths.ts
3309
4055
  import { homedir } from "os";
3310
- import { join } from "path";
4056
+ import { dirname, join } from "path";
3311
4057
  var OPENSCOUT_RPC_CUTOVER_MARKER = "rpc-runtime-cutover-v1";
3312
4058
  function isTestRunnerProcess() {
3313
4059
  if (false)
@@ -3322,9 +4068,16 @@ function assertTestIsolatedUserData(operation, isolationEnvKey) {
3322
4068
  return;
3323
4069
  throw new Error(`Refusing to ${operation} under a test runner without ${isolationEnvKey} set. ` + "Tests must isolate OpenScout user data in a temp directory (see prepareHome in onboarding.test.ts).");
3324
4070
  }
4071
+ function defaultOpenScoutSupportDirectory(home = homedir()) {
4072
+ if (process.platform === "darwin") {
4073
+ return join(home, "Library", "Application Support", "OpenScout");
4074
+ }
4075
+ const xdgDataHome = process.env.XDG_DATA_HOME?.trim();
4076
+ return join(xdgDataHome || join(home, ".local", "share"), "openscout");
4077
+ }
3325
4078
  function resolveOpenScoutSupportPaths() {
3326
4079
  const home = homedir();
3327
- const supportDirectory = process.env.OPENSCOUT_SUPPORT_DIRECTORY ?? join(home, "Library", "Application Support", "OpenScout");
4080
+ const supportDirectory = process.env.OPENSCOUT_SUPPORT_DIRECTORY ?? defaultOpenScoutSupportDirectory(home);
3328
4081
  const logsDirectory = join(supportDirectory, "logs");
3329
4082
  const runtimeDirectory = join(supportDirectory, "runtime");
3330
4083
  const catalogDirectory = join(supportDirectory, "catalog");
@@ -3569,7 +4322,7 @@ var BUILT_IN_HARNESS_CATALOG = [
3569
4322
  {
3570
4323
  name: "opencode",
3571
4324
  harness: "opencode",
3572
- aliases: ["oc", "opencode2"],
4325
+ aliases: ["oc"],
3573
4326
  label: "OpenCode",
3574
4327
  description: "OpenCode's coding agent over ACP, fronting many model vendors via OpenCode Zen",
3575
4328
  homepage: "https://opencode.ai/docs/",
@@ -4920,7 +5673,7 @@ import {
4920
5673
  rmSync,
4921
5674
  writeFileSync
4922
5675
  } from "fs";
4923
- import { dirname, join as join3 } from "path";
5676
+ import { dirname as dirname2, join as join3 } from "path";
4924
5677
  var NODE_IDENTITY_FILE = "node-identity.json";
4925
5678
  var NODE_FINGERPRINT_PREFIX = "osc1";
4926
5679
  var NODE_CARD_TTL_MS = 24 * 60 * 60 * 1000;
@@ -4974,7 +5727,7 @@ function createNodeIdentity(supportDirectory) {
4974
5727
  privateKey: privateKey.export({ type: "pkcs8", format: "der" }).toString("base64"),
4975
5728
  createdAt: Date.now()
4976
5729
  };
4977
- mkdirSync(dirname(path), { recursive: true });
5730
+ mkdirSync(dirname2(path), { recursive: true });
4978
5731
  try {
4979
5732
  writeFileSync(path, `${JSON.stringify(identity, null, 2)}
4980
5733
  `, { encoding: "utf8", mode: 384, flag: "wx" });
@@ -5241,7 +5994,7 @@ var PROJECT_STRONG_MARKERS_FLAT_NESTED = partitionFlatAndNestedMarkers(PROJECT_S
5241
5994
  var PROJECT_WEAK_MARKERS_FLAT_NESTED = partitionFlatAndNestedMarkers(PROJECT_WEAK_MARKERS);
5242
5995
  var GIT_BRANCH_CACHE_TTL_MS = 5 * 60000;
5243
5996
  var gitBranchCache = new Map;
5244
- var SETUP_MODULE_DIRECTORY = dirname2(fileURLToPath(import.meta.url));
5997
+ var SETUP_MODULE_DIRECTORY = dirname3(fileURLToPath(import.meta.url));
5245
5998
  var SCOUT_SKILL_REPO_ROOT = resolve(SETUP_MODULE_DIRECTORY, "..", "..", "..");
5246
5999
 
5247
6000
  // ../runtime/src/broker-api.ts
@@ -5414,6 +6167,15 @@ async function requestBrokerWire(baseUrl, path, options) {
5414
6167
  }
5415
6168
  };
5416
6169
  }
6170
+
6171
+ class ScoutBrokerHttpError extends Error {
6172
+ status;
6173
+ constructor(status, path, body) {
6174
+ super(`${path} returned ${status}: ${body}`);
6175
+ this.status = status;
6176
+ this.name = "ScoutBrokerHttpError";
6177
+ }
6178
+ }
5417
6179
  async function requestScoutBrokerJsonWithTrace(baseUrl, path, options = {}) {
5418
6180
  const { response, trace } = await requestBrokerWire(baseUrl, path, options);
5419
6181
  let parsed;
@@ -5430,7 +6192,7 @@ async function requestScoutBrokerJsonWithTrace(baseUrl, path, options = {}) {
5430
6192
  if (parsedJson && options.acceptErrorJson?.(parsed)) {
5431
6193
  return { value: parsed, trace };
5432
6194
  }
5433
- throw new Error(`${path} returned ${response.status}: ${response.text}`);
6195
+ throw new ScoutBrokerHttpError(response.status, path, response.text);
5434
6196
  }
5435
6197
  if (parsedJson) {
5436
6198
  return { value: parsed, trace };
@@ -5509,7 +6271,7 @@ async function maybeReadJsonFromActiveScoutBrokerService(baseUrl, path) {
5509
6271
  const requestedScope = url.searchParams.get("scope");
5510
6272
  return handled(await service.readSnapshot({
5511
6273
  since: parsePositiveInt(url.searchParams.get("since")) ?? null,
5512
- scope: requestedScope === "conversations" || requestedScope === "agents" ? requestedScope : undefined
6274
+ scope: requestedScope === "conversations" || requestedScope === "agents" || requestedScope === "identity" ? requestedScope : undefined
5513
6275
  }));
5514
6276
  }
5515
6277
  if (url.pathname === "/v1/conversation-projection") {
@@ -5595,6 +6357,11 @@ async function maybeReadJsonFromActiveScoutBrokerService(baseUrl, path) {
5595
6357
  return unhandled();
5596
6358
  }
5597
6359
  return handled(await service.readCollaborationRecords({
6360
+ conversationId: trimOrUndefined(url.searchParams.get("conversationId")),
6361
+ includeThreads: url.searchParams.get("includeThreads") === "true",
6362
+ orderByCreatedAt: url.searchParams.get("orderByCreatedAt") === "true",
6363
+ afterCreatedAt: url.searchParams.has("afterCreatedAt") ? Number(url.searchParams.get("afterCreatedAt")) : undefined,
6364
+ afterId: trimOrUndefined(url.searchParams.get("afterId")),
5598
6365
  kind: trimOrUndefined(url.searchParams.get("kind")),
5599
6366
  state: trimOrUndefined(url.searchParams.get("state")),
5600
6367
  ownerId: trimOrUndefined(url.searchParams.get("ownerId")),
@@ -5636,7 +6403,7 @@ async function maybeReadJsonFromActiveScoutBrokerService(baseUrl, path) {
5636
6403
  import { spawn as spawn2, spawnSync } from "child_process";
5637
6404
  import { existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync5, renameSync as renameSync3, writeFileSync as writeFileSync3 } from "fs";
5638
6405
  import { homedir as homedir6, networkInterfaces } from "os";
5639
- import { basename as basename3, dirname as dirname5, join as join7, resolve as resolve3 } from "path";
6406
+ import { basename as basename3, dirname as dirname6, join as join7, resolve as resolve3 } from "path";
5640
6407
  import { fileURLToPath as fileURLToPath2 } from "url";
5641
6408
 
5642
6409
  // ../runtime/src/schema-version.ts
@@ -6103,7 +6870,7 @@ import {
6103
6870
  writeFileSync as writeFileSync2
6104
6871
  } from "fs";
6105
6872
  import { homedir as homedir4, hostname as osHostname } from "os";
6106
- import { dirname as dirname3, join as join5 } from "path";
6873
+ import { dirname as dirname4, join as join5 } from "path";
6107
6874
  var LOCAL_CONFIG_VERSION = 1;
6108
6875
  var DEFAULT_SCOUT_WEB_PORTAL_HOST = "scout.local";
6109
6876
  var DEFAULT_SCOUT_WEB_DEV_HOST = `dev.${DEFAULT_SCOUT_WEB_PORTAL_HOST}`;
@@ -6222,7 +6989,7 @@ function resolveBrokerPort() {
6222
6989
  // ../runtime/src/tool-resolution.ts
6223
6990
  import { accessSync, constants, existsSync as existsSync5 } from "fs";
6224
6991
  import { homedir as homedir5 } from "os";
6225
- import { basename as basename2, dirname as dirname4, join as join6, resolve as resolve2 } from "path";
6992
+ import { basename as basename2, dirname as dirname5, join as join6, resolve as resolve2 } from "path";
6226
6993
  var DEFAULT_COMMON_EXECUTABLE_DIRECTORIES = [
6227
6994
  join6(homedir5(), ".bun", "bin"),
6228
6995
  "/opt/homebrew/bin",
@@ -6530,7 +7297,7 @@ function runtimePackageDir() {
6530
7297
  const fromGlobal = findGlobalRuntimeDir();
6531
7298
  if (fromGlobal)
6532
7299
  return fromGlobal;
6533
- const moduleDir = dirname5(fileURLToPath2(import.meta.url));
7300
+ const moduleDir = dirname6(fileURLToPath2(import.meta.url));
6534
7301
  return resolve3(moduleDir, "..");
6535
7302
  }
6536
7303
  function isInstalledRuntimePackageDir(candidate) {
@@ -6564,7 +7331,7 @@ function findGlobalRuntimeDir() {
6564
7331
  return null;
6565
7332
  }
6566
7333
  function findBundledRuntimeDir() {
6567
- const moduleDir = dirname5(fileURLToPath2(import.meta.url));
7334
+ const moduleDir = dirname6(fileURLToPath2(import.meta.url));
6568
7335
  return resolveBundledRuntimeDirFromModuleDir(moduleDir);
6569
7336
  }
6570
7337
  function resolveBundledRuntimeDirFromModuleDir(moduleDir) {
@@ -6583,7 +7350,7 @@ function resolveBundledRuntimeDirFromModuleDir(moduleDir) {
6583
7350
  return null;
6584
7351
  }
6585
7352
  function resolveSourceWorkspaceRuntimeDir(bundledPackageDir) {
6586
- const packagesDir = dirname5(bundledPackageDir);
7353
+ const packagesDir = dirname6(bundledPackageDir);
6587
7354
  if (resolve3(packagesDir, "cli") !== resolve3(bundledPackageDir))
6588
7355
  return null;
6589
7356
  const runtimeDir = join7(packagesDir, "runtime");
@@ -6606,7 +7373,7 @@ function findWorkspaceRuntimeDir(startDir) {
6606
7373
  if (existsSync6(join7(candidate, "package.json")) && existsSync6(join7(candidate, "src"))) {
6607
7374
  return candidate;
6608
7375
  }
6609
- const parent = dirname5(current);
7376
+ const parent = dirname6(current);
6610
7377
  if (parent === current)
6611
7378
  return null;
6612
7379
  current = parent;
@@ -6653,7 +7420,7 @@ function resolveBrokerServiceConfig() {
6653
7420
  const serviceAdapter = resolveBrokerServiceAdapter();
6654
7421
  const uid = typeof process.getuid === "function" ? process.getuid() : Number.parseInt(process.env.UID ?? "0", 10);
6655
7422
  const supportPaths = resolveOpenScoutSupportPaths();
6656
- const defaultSupportDir = join7(homedir6(), "Library", "Application Support", "OpenScout");
7423
+ const defaultSupportDir = defaultOpenScoutSupportDirectory();
6657
7424
  const supportDirectory = isTmpPath(supportPaths.supportDirectory) ? defaultSupportDir : supportPaths.supportDirectory;
6658
7425
  const runtimeDirectory = join7(supportDirectory, "runtime");
6659
7426
  const logsDirectory = join7(supportDirectory, "logs", "broker");
@@ -6712,7 +7479,7 @@ function findWorkspaceRootFromRuntimeDir(runtimePackageDir2) {
6712
7479
  if (existsSync6(join7(current, "Cargo.toml")) && existsSync6(join7(current, "crates", "scoutd", "Cargo.toml"))) {
6713
7480
  return current;
6714
7481
  }
6715
- const parent = dirname5(current);
7482
+ const parent = dirname6(current);
6716
7483
  if (parent === current)
6717
7484
  return null;
6718
7485
  current = parent;
@@ -6722,7 +7489,12 @@ function workspaceScoutdAllowed() {
6722
7489
  const raw = process.env.OPENSCOUT_ALLOW_WORKSPACE_SCOUTD?.trim().toLowerCase();
6723
7490
  return raw === "1" || raw === "true" || raw === "yes" || raw === "on";
6724
7491
  }
7492
+ function nativeSupervisorNotApplicableDetail(platform = process.platform) {
7493
+ return platform === "linux" ? "native supervisor: not applicable on linux" : `native supervisor: not applicable on ${platform}`;
7494
+ }
6725
7495
  function resolveScoutdCommand(config = resolveBrokerServiceConfig()) {
7496
+ if (process.platform !== "darwin")
7497
+ return null;
6726
7498
  const explicit = resolveEnvExecutable(process.env.OPENSCOUT_SCOUTD_BIN);
6727
7499
  if (explicit) {
6728
7500
  return { path: explicit, source: "env" };
@@ -6735,7 +7507,7 @@ function resolveScoutdCommand(config = resolveBrokerServiceConfig()) {
6735
7507
  workspaceRoot ? join7(workspaceRoot, "packages", "cli", "bin", "scoutd") : null,
6736
7508
  workspaceRoot ? join7(workspaceRoot, "packages", "runtime", "bin", "scoutd") : null,
6737
7509
  join7(config.runtimeDirectory, "scoutd"),
6738
- join7(dirname5(config.runtimePackageDir), "scout", "bin", "scoutd")
7510
+ join7(dirname6(config.runtimePackageDir), "scout", "bin", "scoutd")
6739
7511
  ];
6740
7512
  for (const candidate of packageCandidates) {
6741
7513
  const resolved = executableCandidate(candidate);
@@ -6865,6 +7637,8 @@ function normalizeNativeServiceStatus(input, config) {
6865
7637
  reachable: healthReachable,
6866
7638
  ok: healthOk,
6867
7639
  checkedAt: readNumber2(healthRecord.checkedAt) ?? Date.now(),
7640
+ state: readString2(healthRecord.state),
7641
+ durationMs: readNumber2(healthRecord.durationMs),
6868
7642
  transport: healthTransport,
6869
7643
  socketPath: config.brokerSocketPath,
6870
7644
  ...healthSocketFallbackError ? { socketFallbackError: healthSocketFallbackError } : {},
@@ -6976,6 +7750,9 @@ async function runScoutdServiceCommand(command, config, timeoutMs = SCOUTD_DEFAU
6976
7750
  }
6977
7751
  const scoutd = resolveScoutdCommand(config);
6978
7752
  if (!scoutd) {
7753
+ if (process.platform !== "darwin") {
7754
+ throw new Error(nativeSupervisorNotApplicableDetail());
7755
+ }
6979
7756
  throw new Error("Unable to locate scoutd for broker service management. Build scoutd with `npm run scoutd:build`, install a package that includes scoutd, or set OPENSCOUT_SCOUTD_BIN.");
6980
7757
  }
6981
7758
  const stdout = await runScoutdJson(scoutd.path, command, nativeServiceEnvironment(config, scoutd.path), timeoutMs);
@@ -7235,7 +8012,7 @@ if (isBrokerServiceEntrypoint(import.meta.url, process.argv[1])) {
7235
8012
  }
7236
8013
 
7237
8014
  // ../runtime/src/local-agents.ts
7238
- import { dirname as dirname9, join as join13, resolve as resolve7 } from "path";
8015
+ import { dirname as dirname10, join as join13, resolve as resolve7 } from "path";
7239
8016
  import { fileURLToPath as fileURLToPath3 } from "url";
7240
8017
 
7241
8018
  // ../agent-sessions/src/secret-redaction.ts
@@ -7572,7 +8349,7 @@ async function requestJsonWithBun2(connect, socketPath, payload, timeoutMs) {
7572
8349
 
7573
8350
  // ../runtime/src/system-probes/git-build-info.ts
7574
8351
  import { existsSync as existsSync8, realpathSync, statSync } from "fs";
7575
- import { dirname as dirname6, resolve as resolve4 } from "path";
8352
+ import { dirname as dirname7, resolve as resolve4 } from "path";
7576
8353
  var staticMetadataByRepo = new Map;
7577
8354
  function realpathOrResolved(path) {
7578
8355
  try {
@@ -7585,7 +8362,7 @@ function directoryOrParent(path) {
7585
8362
  const resolved = resolve4(path);
7586
8363
  try {
7587
8364
  const stat = statSync(resolved);
7588
- return stat.isDirectory() ? resolved : dirname6(resolved);
8365
+ return stat.isDirectory() ? resolved : dirname7(resolved);
7589
8366
  } catch {
7590
8367
  return resolved;
7591
8368
  }
@@ -7596,7 +8373,7 @@ function canonicalRepoRoot(rawPath) {
7596
8373
  if (existsSync8(resolve4(current, ".git"))) {
7597
8374
  return realpathOrResolved(current);
7598
8375
  }
7599
- const parent = dirname6(current);
8376
+ const parent = dirname7(current);
7600
8377
  if (parent === current) {
7601
8378
  return realpathOrResolved(directoryOrParent(rawPath));
7602
8379
  }
@@ -8446,6 +9223,7 @@ async function readTmuxPaneLocal(key, ctx) {
8446
9223
  try {
8447
9224
  if (parsed.kind === "detail") {
8448
9225
  const { stdout: stdout2 } = await execProbeFile(ctx, tmuxBin(), [
9226
+ "-u",
8449
9227
  ...tmuxSocketArgs(parsed.socketPath),
8450
9228
  "display-message",
8451
9229
  "-p",
@@ -8592,7 +9370,7 @@ var herdrTopologyCache = new Map;
8592
9370
  import { createReadStream } from "fs";
8593
9371
  import { readdir, stat } from "fs/promises";
8594
9372
  import { homedir as homedir9 } from "os";
8595
- import { basename as basename4, dirname as dirname7, join as join9, resolve as resolve5 } from "path";
9373
+ import { basename as basename4, dirname as dirname8, join as join9, resolve as resolve5 } from "path";
8596
9374
  import { createInterface } from "readline";
8597
9375
  function positiveInteger(value, fallback, max) {
8598
9376
  return Number.isFinite(value) && value > 0 ? Math.min(max, Math.floor(value)) : fallback;
@@ -8623,7 +9401,7 @@ function extractProjectName(filePath) {
8623
9401
  const claudeMatch = filePath.match(/\.claude\/projects\/[^/]*-dev-([^/]+)/);
8624
9402
  if (claudeMatch?.[1])
8625
9403
  return claudeMatch[1];
8626
- return basename4(dirname7(filePath)) || "unknown";
9404
+ return basename4(dirname8(filePath)) || "unknown";
8627
9405
  }
8628
9406
  function detectAgent(filePath, fallback = "unknown") {
8629
9407
  if (filePath.includes(".claude"))
@@ -10684,7 +11462,8 @@ class RequesterWaitTimeoutError extends Error {
10684
11462
  }
10685
11463
 
10686
11464
  // ../runtime/src/acp-agent-invocation.ts
10687
- var DEFAULT_ACP_HARD_CEILING_MS = 30 * 60000;
11465
+ var DEFAULT_ACP_HARD_CEILING_MS = 60 * 60000;
11466
+ var DEFAULT_ACP_HARD_CEILING_MAX_MS = 6 * 60 * 60000;
10688
11467
  var activeAcpSessions = new Map;
10689
11468
 
10690
11469
  // ../runtime/src/claude-stream-json.ts
@@ -11587,7 +12366,7 @@ var DEFAULT_RELAY_AGENT_ORPHAN_GRACE_MS = 15 * 60000;
11587
12366
  // ../runtime/src/user-config.ts
11588
12367
  import { existsSync as existsSync12, readFileSync as readFileSync8, statSync as statSync3, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4 } from "fs";
11589
12368
  import { homedir as homedir11 } from "os";
11590
- import { dirname as dirname8, join as join12 } from "path";
12369
+ import { dirname as dirname9, join as join12 } from "path";
11591
12370
  function userConfigPath() {
11592
12371
  return join12(process.env.OPENSCOUT_HOME ?? join12(homedir11(), ".openscout"), "user.json");
11593
12372
  }
@@ -11652,7 +12431,7 @@ function resolveOperatorHandle() {
11652
12431
  }
11653
12432
 
11654
12433
  // ../runtime/src/local-agents.ts
11655
- var MODULE_DIRECTORY = dirname9(fileURLToPath3(import.meta.url));
12434
+ var MODULE_DIRECTORY = dirname10(fileURLToPath3(import.meta.url));
11656
12435
  var OPENSCOUT_REPO_ROOT = resolve7(MODULE_DIRECTORY, "..", "..", "..");
11657
12436
  var DEFAULT_ONE_TIME_LOCAL_AGENT_CARD_TTL_MS = 24 * 60 * 60 * 1000;
11658
12437
  function parsePositiveInteger2(value, fallback) {
@@ -11669,7 +12448,8 @@ var TMUX_VERIFY_IDLE_DEADLINE_MS = parseNonNegativeInteger(process.env.OPENSCOUT
11669
12448
  var TMUX_VERIFY_BUSY_DEADLINE_MS = parseNonNegativeInteger(process.env.OPENSCOUT_TMUX_VERIFY_BUSY_DEADLINE_MS, 15000);
11670
12449
  var TMUX_DEFAULT_COLUMNS = parsePositiveInteger2(process.env.OPENSCOUT_LOCAL_AGENT_TMUX_COLUMNS, 160);
11671
12450
  var TMUX_DEFAULT_ROWS = parsePositiveInteger2(process.env.OPENSCOUT_LOCAL_AGENT_TMUX_ROWS, 48);
11672
-
12451
+ var TMUX_READY_TIMEOUT_MS = parseNonNegativeInteger(process.env.OPENSCOUT_TMUX_READY_TIMEOUT_MS, 45000);
12452
+ var TMUX_READY_CEILING_MS = parseNonNegativeInteger(process.env.OPENSCOUT_TMUX_READY_CEILING_MS, 120000);
11673
12453
  // ../runtime/src/broker-message-records.ts
11674
12454
  function captureMessageRecords(records) {
11675
12455
  if (asyncViews.has(records))
@@ -15014,6 +15794,53 @@ CREATE INDEX IF NOT EXISTS idx_mission_log_entries_mission_at
15014
15794
  CREATE INDEX IF NOT EXISTS idx_mission_log_entries_actor_at
15015
15795
  ON mission_log_entries (actor_id, at DESC);
15016
15796
  `;
15797
+ // ../runtime/src/local-agent-transports.ts
15798
+ var directLocalAgentTransports = new Set([
15799
+ "codex_app_server",
15800
+ "claude_stream_json",
15801
+ "pi_rpc",
15802
+ "grok_acp",
15803
+ "kimi_acp",
15804
+ "cursor_acp",
15805
+ "opencode_acp",
15806
+ "devin_acp"
15807
+ ]);
15808
+
15809
+ // ../runtime/src/broker-endpoint-selection.ts
15810
+ var TERMINAL_ENDPOINT_STATES = new Set([
15811
+ "failed",
15812
+ "superseded",
15813
+ "stopped"
15814
+ ]);
15815
+ // ../runtime/src/broker-local-invocation-helpers.ts
15816
+ var STALE_WORKING_FLIGHT_NO_ENDPOINT_GRACE_MS = 2 * 60000;
15817
+
15818
+ // ../runtime/src/broker-dispatch-job.ts
15819
+ var TERMINAL_DISPATCH_JOB_STATES = new Set([
15820
+ "completed",
15821
+ "failed",
15822
+ "cancelled"
15823
+ ]);
15824
+
15825
+ // ../runtime/src/history-rotation.ts
15826
+ var TERMINAL_DELIVERY_STATUSES = new Set([
15827
+ "completed",
15828
+ "failed",
15829
+ "cancelled",
15830
+ "acknowledged"
15831
+ ]);
15832
+ function applyHistoryRotationEviction(snapshot, evicted) {
15833
+ for (const id of evicted.messageIds) {
15834
+ delete snapshot.messages[id];
15835
+ }
15836
+ for (const id of evicted.invocationIds) {
15837
+ delete snapshot.invocations[id];
15838
+ }
15839
+ for (const id of evicted.flightIds) {
15840
+ delete snapshot.flights[id];
15841
+ }
15842
+ }
15843
+
15017
15844
  // ../runtime/src/broker.ts
15018
15845
  function createRuntimeId(prefix) {
15019
15846
  return `${prefix}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
@@ -15107,11 +15934,18 @@ class InMemoryControlRuntime {
15107
15934
  endpointIdsByAgentId = new Map;
15108
15935
  bindingIdsByConversationId = new Map;
15109
15936
  flightIdByInvocationId = new Map;
15937
+ retiredActorIds = new Set;
15110
15938
  constructor(initial = {}, options = {}) {
15111
15939
  this.registry = createRuntimeRegistrySnapshot(initial);
15112
15940
  this.localNodeId = options.localNodeId;
15941
+ for (const actorId of options.retiredActorIds ?? []) {
15942
+ this.retiredActorIds.add(actorId);
15943
+ }
15113
15944
  this.rebuildIndexes();
15114
15945
  }
15946
+ isRetiredActor(actorId) {
15947
+ return this.retiredActorIds.has(actorId);
15948
+ }
15115
15949
  snapshot() {
15116
15950
  return createRuntimeRegistrySnapshot({
15117
15951
  nodes: { ...this.registry.nodes },
@@ -15254,6 +16088,7 @@ class InMemoryControlRuntime {
15254
16088
  return;
15255
16089
  case "stream.subscribe":
15256
16090
  return;
16091
+ case "channel.member.remove":
15257
16092
  case "channel.invite.create":
15258
16093
  case "channel.invite.revoke":
15259
16094
  case "channel.invite.redeem":
@@ -15276,13 +16111,15 @@ class InMemoryControlRuntime {
15276
16111
  });
15277
16112
  }
15278
16113
  async upsertActor(actor) {
16114
+ this.retiredActorIds.delete(actor.id);
15279
16115
  this.registry.actors[actor.id] = {
15280
16116
  id: actor.id,
15281
16117
  kind: actor.kind,
15282
16118
  displayName: actor.displayName,
15283
16119
  handle: actor.handle,
15284
16120
  labels: actor.labels,
15285
- metadata: actor.metadata
16121
+ metadata: actor.metadata,
16122
+ createdAt: actor.createdAt ?? this.registry.actors[actor.id]?.createdAt ?? Date.now()
15286
16123
  };
15287
16124
  this.emit({
15288
16125
  id: createRuntimeId("evt"),
@@ -15294,6 +16131,7 @@ class InMemoryControlRuntime {
15294
16131
  });
15295
16132
  }
15296
16133
  async upsertAgent(agent) {
16134
+ this.retiredActorIds.delete(agent.id);
15297
16135
  if (!this.registry.actors[agent.id]) {
15298
16136
  this.registry.actors[agent.id] = {
15299
16137
  id: agent.id,
@@ -15301,7 +16139,8 @@ class InMemoryControlRuntime {
15301
16139
  displayName: agent.displayName,
15302
16140
  handle: agent.handle,
15303
16141
  labels: agent.labels,
15304
- metadata: agent.metadata
16142
+ metadata: agent.metadata,
16143
+ createdAt: agent.createdAt ?? Date.now()
15305
16144
  };
15306
16145
  }
15307
16146
  this.registry.agents[agent.id] = agent;
@@ -15315,6 +16154,7 @@ class InMemoryControlRuntime {
15315
16154
  });
15316
16155
  }
15317
16156
  upsertAgentIdentity(input) {
16157
+ this.retiredActorIds.delete(input.id);
15318
16158
  if (!this.registry.actors[input.id]) {
15319
16159
  this.registry.actors[input.id] = {
15320
16160
  id: input.id,
@@ -15322,7 +16162,8 @@ class InMemoryControlRuntime {
15322
16162
  displayName: input.displayName,
15323
16163
  handle: input.handle,
15324
16164
  labels: input.labels,
15325
- metadata: input.metadata
16165
+ metadata: input.metadata,
16166
+ createdAt: Date.now()
15326
16167
  };
15327
16168
  }
15328
16169
  const partial = {
@@ -15392,6 +16233,38 @@ class InMemoryControlRuntime {
15392
16233
  payload: { endpointId: id }
15393
16234
  });
15394
16235
  }
16236
+ deleteAgent(id) {
16237
+ const endpointIds = this.endpointIdsByAgentId.get(id);
16238
+ if (endpointIds) {
16239
+ for (const endpointId of [...endpointIds]) {
16240
+ this.deleteEndpoint(endpointId);
16241
+ }
16242
+ }
16243
+ if (!this.registry.agents[id])
16244
+ return;
16245
+ delete this.registry.agents[id];
16246
+ }
16247
+ deleteActor(id) {
16248
+ this.retiredActorIds.add(id);
16249
+ if (!this.registry.actors[id])
16250
+ return;
16251
+ delete this.registry.actors[id];
16252
+ }
16253
+ applyHistoryRotation(evicted) {
16254
+ const flightIds = new Set(evicted.flightIds);
16255
+ applyHistoryRotationEviction(this.registry, {
16256
+ messageIds: new Set(evicted.messageIds),
16257
+ invocationIds: new Set(evicted.invocationIds),
16258
+ flightIds
16259
+ });
16260
+ if (flightIds.size > 0) {
16261
+ for (const [invocationId, flightId] of this.flightIdByInvocationId) {
16262
+ if (flightIds.has(flightId)) {
16263
+ this.flightIdByInvocationId.delete(invocationId);
16264
+ }
16265
+ }
16266
+ }
16267
+ }
15395
16268
  async upsertConversation(conversation) {
15396
16269
  const metadata = conversation.metadata;
15397
16270
  if (typeof metadata?.createdAt !== "number" || typeof metadata?.updatedAt !== "number") {
@@ -15496,6 +16369,18 @@ class InMemoryControlRuntime {
15496
16369
  });
15497
16370
  return deliveries;
15498
16371
  }
16372
+ async correctMessage(message) {
16373
+ if (!asyncMessageRecordView(this.registry.messages))
16374
+ this.registry.messages[message.id] = message;
16375
+ this.emit({
16376
+ id: createRuntimeId("evt"),
16377
+ kind: "message.corrected",
16378
+ ts: Date.now(),
16379
+ actorId: message.actorId,
16380
+ nodeId: message.originNodeId,
16381
+ payload: { message }
16382
+ });
16383
+ }
15499
16384
  async commitMessage(message, deliveries) {
15500
16385
  if (!asyncMessageRecordView(this.registry.messages))
15501
16386
  this.registry.messages[message.id] = message;
@@ -15689,6 +16574,13 @@ class InMemoryControlRuntime {
15689
16574
  }
15690
16575
  }
15691
16576
  }
16577
+ // ../runtime/src/scout-bridge-command.ts
16578
+ var ENTRYPOINT = String.raw`(?:scout\.(?:mjs|ts|js)|\/bin\/scout|\/main\.mjs)`;
16579
+ var SUBCOMMAND = String.raw`\s+(mcp|channel|mesh\s+bridge)(?:\s|$)`;
16580
+ var RUNTIME = String.raw`(?:\S*\/)?(?:bun|node)(?:\s+(?!(?:-e|-p|--eval|--print)(?:[\s=]|$))-[\w-]+(?:=\S+)?)*`;
16581
+ var SCRIPT_PREFIX = String.raw`(?:[^-\s](?:(?!\s-|\.(?:[cm]?js|ts)\s).)*?)?`;
16582
+ var SCOUT_BRIDGE_COMMAND = new RegExp(String.raw`^(?:${RUNTIME}\s+${SCRIPT_PREFIX}|\S*?)${ENTRYPOINT}${SUBCOMMAND}`);
16583
+ var SCOUT_BRIDGE_BINARY = new RegExp(String.raw`^(?:${RUNTIME}\s+(?:${SCRIPT_PREFIX}\/)?|\S*\/)?scout-mcp(?:\s|$)`);
15692
16584
  // ../runtime/src/conversation-thread-artifact.ts
15693
16585
  import { createHash as createHash3, randomBytes as randomBytes2 } from "crypto";
15694
16586
  import {
@@ -15701,7 +16593,7 @@ import {
15701
16593
  statSync as statSync4,
15702
16594
  writeFileSync as writeFileSync5
15703
16595
  } from "fs";
15704
- import { basename as basename6, dirname as dirname10, join as join14 } from "path";
16596
+ import { basename as basename6, dirname as dirname11, join as join14 } from "path";
15705
16597
  var NATIVE_READ_THREAD_ARTIFACT_SCHEMA = "openscout.native.read.thread-cache/v1";
15706
16598
  var NATIVE_READ_THREAD_ARTIFACT_VERSION = 1;
15707
16599
  var NATIVE_READ_THREAD_MAX_BYTES = 256 * 1024;
@@ -15911,7 +16803,7 @@ function readExistingCursor(path) {
15911
16803
  }
15912
16804
  }
15913
16805
  function writeAtomically(path, contents) {
15914
- const directory = dirname10(path);
16806
+ const directory = dirname11(path);
15915
16807
  const temporaryPath = join14(directory, `.${basename6(path)}.${process.pid}.${randomBytes2(6).toString("hex")}.tmp`);
15916
16808
  mkdirSync5(directory, { recursive: true, mode: 448 });
15917
16809
  try {
@@ -15999,11 +16891,17 @@ class ConversationThreadArtifactPublisher {
15999
16891
  }
16000
16892
  }
16001
16893
 
16894
+ // ../runtime/src/guest-access.ts
16895
+ var GUEST_GRANT_MAX_TTL_MS = 30 * 24 * 60 * 60 * 1000;
16896
+ var GUEST_ASK_MAX_TASK_BYTES = 32 * 1024;
16897
+
16002
16898
  // ../runtime/src/budget-observations.ts
16003
16899
  var QUOTA_HISTORY_BUCKET_MS = 60 * 60 * 1000;
16004
16900
 
16005
16901
  // ../runtime/src/sqlite-store.ts
16006
16902
  var RUNTIME_SESSION_RETENTION_MS = 30 * 24 * 60 * 60 * 1000;
16903
+ var QUOTA_HISTORY_RETENTION_MS = 7 * 24 * 60 * 60 * 1000 + 60 * 60 * 1000;
16904
+ var QUOTA_HISTORY_PRUNE_INTERVAL_MS = 10 * 60 * 1000;
16007
16905
  // ../runtime/src/mesh-peer-auth.ts
16008
16906
  import { createHash as createHash4, randomBytes as randomBytes3 } from "crypto";
16009
16907
  var PEER_AUTH_HEADERS = {
@@ -30768,24 +31666,6 @@ function describeProvisionalAgentNamePool(config = loadUserConfig()) {
30768
31666
  }
30769
31667
  // ../runtime/src/control-plane-agents.ts
30770
31668
  var DEFAULT_ONE_TIME_SCOUT_AGENT_CARD_TTL_MS = 24 * 60 * 60 * 1000;
30771
- // ../runtime/src/local-agent-transports.ts
30772
- var directLocalAgentTransports = new Set([
30773
- "codex_app_server",
30774
- "claude_stream_json",
30775
- "pi_rpc",
30776
- "grok_acp",
30777
- "kimi_acp",
30778
- "cursor_acp",
30779
- "opencode_acp",
30780
- "devin_acp"
30781
- ]);
30782
-
30783
- // ../runtime/src/broker-endpoint-selection.ts
30784
- var TERMINAL_ENDPOINT_STATES = new Set([
30785
- "failed",
30786
- "superseded",
30787
- "stopped"
30788
- ]);
30789
31669
  // ../runtime/src/coding-agent-host.ts
30790
31670
  var TRUTHY = new Set(["1", "true", "yes", "on"]);
30791
31671
  // ../runtime/src/openscout-discovery.ts
@@ -30864,6 +31744,74 @@ function formatStoredStringList(value) {
30864
31744
  function setConfigValue(config, key, value) {
30865
31745
  config[key] = value;
30866
31746
  }
31747
+ function normalizeRuntimeShortlistInput(value) {
31748
+ if (!Array.isArray(value)) {
31749
+ throw new Error("runtime-shortlist expects a list of <harness>[/<model>] specs");
31750
+ }
31751
+ const specs = value.map((entry) => typeof entry === "string" ? entry.trim() : "").filter((entry) => entry.length > 0);
31752
+ for (const spec of specs) {
31753
+ const parsed = parseScoutRuntimeSpec(spec);
31754
+ if (!parsed.ok) {
31755
+ throw new Error(`invalid runtime spec "${spec}": ${parsed.error}`);
31756
+ }
31757
+ if (parsed.value.reasoningEffort) {
31758
+ throw new Error(`invalid runtime spec "${spec}": shortlist entries pin a model, not an effort \u2014 use runtime-presets for effort`);
31759
+ }
31760
+ }
31761
+ return specs;
31762
+ }
31763
+ function normalizeRuntimePresetId(raw) {
31764
+ const id = normalizeAgentSelectorSegment(typeof raw === "string" ? raw : "");
31765
+ if (!id) {
31766
+ throw new Error("runtime preset needs an id \u2014 use id[:Label]=<harness>[/<model>[/<effort>]]");
31767
+ }
31768
+ if (SCOUT_RESERVED_RUNTIME_PROFILE_IDS.includes(id)) {
31769
+ throw new Error(`runtime preset id "${id}" is a reserved runtime profile name`);
31770
+ }
31771
+ if (isScoutLaunchableHarness(id)) {
31772
+ throw new Error(`runtime preset id "${id}" collides with a launchable harness`);
31773
+ }
31774
+ if (SCOUT_REASONING_EFFORTS.includes(id)) {
31775
+ throw new Error(`runtime preset id "${id}" collides with a reasoning effort`);
31776
+ }
31777
+ return id;
31778
+ }
31779
+ function normalizeRuntimePresetInput(value) {
31780
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
31781
+ throw new Error("runtime preset must be { id, label?, runtime }");
31782
+ }
31783
+ const record = value;
31784
+ const id = normalizeRuntimePresetId(record.id);
31785
+ const runtime = typeof record.runtime === "string" ? record.runtime.trim() : "";
31786
+ const parsed = parseScoutRuntimeSpec(runtime);
31787
+ if (!parsed.ok) {
31788
+ throw new Error(`invalid runtime spec for preset "${id}": ${parsed.error}`);
31789
+ }
31790
+ const label = typeof record.label === "string" && record.label.trim() ? record.label.trim() : undefined;
31791
+ return { id, ...label ? { label } : {}, runtime };
31792
+ }
31793
+ function parseRuntimePresetItem(item) {
31794
+ const trimmed = item.trim();
31795
+ const eq = trimmed.indexOf("=");
31796
+ if (eq < 0) {
31797
+ throw new Error(`preset "${trimmed}" must be id[:Label]=<harness>[/<model>[/<effort>]]`);
31798
+ }
31799
+ const head = trimmed.slice(0, eq).trim();
31800
+ const runtime = trimmed.slice(eq + 1).trim();
31801
+ const colon = head.indexOf(":");
31802
+ const id = colon < 0 ? head : head.slice(0, colon).trim();
31803
+ const label = colon < 0 ? undefined : head.slice(colon + 1).trim() || undefined;
31804
+ return normalizeRuntimePresetInput({ id, ...label ? { label } : {}, runtime });
31805
+ }
31806
+ function normalizeRuntimePresetsInput(value) {
31807
+ if (!Array.isArray(value)) {
31808
+ throw new Error("runtime-presets expects a list of id[:Label]=<spec> items");
31809
+ }
31810
+ return value.map((entry) => typeof entry === "string" ? parseRuntimePresetItem(entry) : normalizeRuntimePresetInput(entry));
31811
+ }
31812
+ function formatRuntimePresetSetting(preset) {
31813
+ return `${preset.id}${preset.label ? `:${preset.label}` : ""}=${preset.runtime}`;
31814
+ }
30867
31815
  function clearConfigValue(config, key) {
30868
31816
  delete config[key];
30869
31817
  }
@@ -31068,6 +32016,46 @@ var USER_CONFIG_FIELDS = [
31068
32016
  parse: parseStringValue,
31069
32017
  resolveGet: (config) => formatStoredString(config.provisionalAgentNamesFile),
31070
32018
  formatSummary: (config) => formatStoredString(config.provisionalAgentNamesFile) || "\u2014"
32019
+ },
32020
+ {
32021
+ id: "runtime-shortlist",
32022
+ key: "runtimeShortlist",
32023
+ label: "Runtime model shortlist",
32024
+ kind: "string-list",
32025
+ summary: "Models pinned first in runtime pickers (<harness>[/<model>], comma-separated)",
32026
+ parse: (args) => normalizeRuntimeShortlistInput(args.join(" ").split(",").map((entry) => entry.trim()).filter(Boolean)),
32027
+ resolveGet: (config) => (config.runtimeShortlist ?? []).join(", "),
32028
+ formatSummary: (config) => (config.runtimeShortlist ?? []).join(", ") || "\u2014",
32029
+ formatValue: (value) => Array.isArray(value) ? value.join(", ") : "",
32030
+ apply: (config, value) => {
32031
+ const specs = normalizeRuntimeShortlistInput(value);
32032
+ if (specs.length === 0) {
32033
+ clearConfigValue(config, "runtimeShortlist");
32034
+ } else {
32035
+ setConfigValue(config, "runtimeShortlist", specs);
32036
+ }
32037
+ },
32038
+ clear: (config) => clearConfigValue(config, "runtimeShortlist")
32039
+ },
32040
+ {
32041
+ id: "runtime-presets",
32042
+ key: "runtimePresets",
32043
+ label: "Runtime presets",
32044
+ kind: "string-list",
32045
+ summary: "Named runtime tuples: id[:Label]=<harness>[/<model>[/<effort>]], comma-separated",
32046
+ parse: (args) => normalizeRuntimePresetsInput(args.join(" ").split(",").map((entry) => entry.trim()).filter(Boolean)),
32047
+ resolveGet: (config) => (config.runtimePresets ?? []).map(formatRuntimePresetSetting).join(", "),
32048
+ formatSummary: (config) => (config.runtimePresets ?? []).map(formatRuntimePresetSetting).join(", ") || "\u2014",
32049
+ formatValue: (value) => Array.isArray(value) ? value.map(formatRuntimePresetSetting).join(", ") : "",
32050
+ apply: (config, value) => {
32051
+ const presets = normalizeRuntimePresetsInput(value);
32052
+ if (presets.length === 0) {
32053
+ clearConfigValue(config, "runtimePresets");
32054
+ } else {
32055
+ setConfigValue(config, "runtimePresets", presets);
32056
+ }
32057
+ },
32058
+ clear: (config) => clearConfigValue(config, "runtimePresets")
31071
32059
  }
31072
32060
  ];
31073
32061
  var USER_CONFIG_FIELD_INDEX = new Map(USER_CONFIG_FIELDS.flatMap((field) => [
@@ -31306,6 +32294,40 @@ class ThreadEventPlane {
31306
32294
  watch.clients.clear();
31307
32295
  }
31308
32296
  }
32297
+ // ../runtime/src/mobile-push-seal.ts
32298
+ var SALT = Buffer.from("openscout.push.v1", "utf8");
32299
+ var PKCS8_X25519_PREFIX = Buffer.from("302e020100300506032b656e04220420", "hex");
32300
+ var SPKI_X25519_PREFIX = Buffer.from("302a300506032b656e032100", "hex");
32301
+ var NONCE_BYTES = 12;
32302
+ var HEADER_BYTES = 1 + 32 + NONCE_BYTES;
32303
+ // ../runtime/src/continuation/decide.ts
32304
+ var WORKSPACE_COMMAND = new RegExp([
32305
+ "^(?:bun|npm|pnpm|yarn)\\s+(?:test|run\\s+[\\w:.-]+|lint|typecheck|check|build)(?:\\s|$)",
32306
+ "^(?:bunx|npx)\\s+tsc(?:\\s|$)",
32307
+ "^(?:cargo|go|swift)\\s+(?:test|build|check|vet)(?:\\s|$)",
32308
+ "^(?:pytest|tsc|make)(?:\\s|$)",
32309
+ "^(?:ls|pwd|cat|head|tail|wc|grep|rg)(?:\\s|$)",
32310
+ "^git\\s+(?:status|diff|log|show)(?:\\s|$)"
32311
+ ].join("|"));
32312
+ // ../runtime/src/continuation/model.ts
32313
+ var KINDS = new Set(["permission", "question", "plan", "hold", "unknown"]);
32314
+ var RISKS = new Set([
32315
+ "workspace",
32316
+ "network",
32317
+ "publish",
32318
+ "destructive",
32319
+ "secrets",
32320
+ "identity",
32321
+ "unknown"
32322
+ ]);
32323
+ var SYSTEM_PROMPT = [
32324
+ "Classify a coding-agent terminal dialog. Reply with JSON only:",
32325
+ '{"kind":"permission|question|plan|hold|unknown","command":string|null,"risk":"workspace|network|publish|destructive|secrets|identity|unknown","allowIndex":number|null,"confidence":"high|low","reason":string}',
32326
+ "kind=permission only for a Yes/No tool approval, not a question or plan.",
32327
+ "allowIndex is the numbered allow-once option (Yes). Never pick don't-ask-again or always-allow.",
32328
+ "risk=workspace for local tests/builds/edits. network for curl/http. publish for git push. destructive for rm -r/sudo. secrets for .env/keys.",
32329
+ "If unsure, confidence=low and kind=unknown."
32330
+ ].join(" ");
31309
32331
  // ../runtime/src/activity-transitions.ts
31310
32332
  class ActivityTransitionTracker {
31311
32333
  transitions = new Map;
@@ -31526,13 +32548,27 @@ async function readScoutBrokerHealth(baseUrl = resolveScoutBrokerUrl()) {
31526
32548
  };
31527
32549
  }
31528
32550
  }
31529
- async function readScoutBrokerSnapshot(baseUrl = resolveScoutBrokerUrl()) {
32551
+ function scoutBrokerReadErrorDetail(error) {
32552
+ return error instanceof Error ? error.message : String(error);
32553
+ }
32554
+ async function readScoutBrokerSnapshotResult(baseUrl = resolveScoutBrokerUrl()) {
31530
32555
  try {
31531
- return await brokerReadJson(baseUrl, scoutBrokerPaths.v1.snapshot);
31532
- } catch {
31533
- return null;
32556
+ return {
32557
+ ok: true,
32558
+ snapshot: await brokerReadJson(baseUrl, scoutBrokerPaths.v1.snapshot)
32559
+ };
32560
+ } catch (error) {
32561
+ return {
32562
+ ok: false,
32563
+ reason: "snapshot_read_failed",
32564
+ detail: scoutBrokerReadErrorDetail(error)
32565
+ };
31534
32566
  }
31535
32567
  }
32568
+ async function readScoutBrokerSnapshot(baseUrl = resolveScoutBrokerUrl()) {
32569
+ const result = await readScoutBrokerSnapshotResult(baseUrl);
32570
+ return result.ok ? result.snapshot : null;
32571
+ }
31536
32572
 
31537
32573
  // ../../apps/desktop/src/cli/output.ts
31538
32574
  function createScoutOutput(mode, stdout) {
@@ -31578,7 +32614,7 @@ import {
31578
32614
  readFileSync as readFileSync11
31579
32615
  } from "fs";
31580
32616
  import { tmpdir as osTmpdir } from "os";
31581
- import { dirname as dirname11, join as join16 } from "path";
32617
+ import { dirname as dirname12, join as join16 } from "path";
31582
32618
 
31583
32619
  // ../../apps/desktop/src/cli/errors.ts
31584
32620
  class ScoutCliError extends Error {
@@ -32200,7 +33236,7 @@ function retireLegacyAppBundles(deps, context) {
32200
33236
  let hadRunning = false;
32201
33237
  let blocked = false;
32202
33238
  for (const name2 of LEGACY_APP_BUNDLE_NAMES) {
32203
- const legacyPath = join16(dirname11(deps.appPath), name2);
33239
+ const legacyPath = join16(dirname12(deps.appPath), name2);
32204
33240
  if (legacyPath === deps.appPath || !deps.existsSync(legacyPath))
32205
33241
  continue;
32206
33242
  try {