harness-wingman 0.9.1 → 0.9.3

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.
@@ -313,6 +313,8 @@ var init_labels = __esm({
313
313
  "packages/i18n/dist/catalog/en/labels.js"() {
314
314
  "use strict";
315
315
  labels_default = {
316
+ "panel.source.codexProject": "Codex project",
317
+ "panel.source.codexUngrouped": "Codex ungrouped",
316
318
  "panel.source.planStep": "plan.md step",
317
319
  "panel.source.planInstruction": "Instruction for the plan",
318
320
  "panel.source.latestInstruction": "Latest instruction",
@@ -350,6 +352,7 @@ var init_narrative = __esm({
350
352
  "packages/i18n/dist/catalog/en/narrative.js"() {
351
353
  "use strict";
352
354
  narrative_default = {
355
+ "narrative.codexUngrouped": "Ungrouped",
353
356
  "narrative.noStateDirectory": "No local state directory is configured",
354
357
  "narrative.acceptanceUnreadable": "Local acceptance state could not be read",
355
358
  "narrative.homeDirectory": "No project directory (home)",
@@ -615,6 +618,25 @@ var init_render = __esm({
615
618
  "packages/i18n/dist/catalog/en/render.js"() {
616
619
  "use strict";
617
620
  render_default = {
621
+ "panel.render.projectsPageTitle": "Project overview",
622
+ "panel.render.projectsPageHint": "Goals, progress and decisions across your coding apps.",
623
+ "panel.render.controlsPageHint": "Manage tools, preferences and how you return to a session.",
624
+ "panel.render.optionalSuggestions": "Optional suggestions",
625
+ "panel.render.suggestionsHint": "Based on observed session activity, for reference only. Review changes before applying.",
626
+ "panel.render.usagePageHint": "Reported usage and estimated context, kept separate.",
627
+ "panel.render.toolsAndPreferences": "Tools & preferences",
628
+ "panel.render.controlSkills": "Skills & plugins",
629
+ "panel.render.controlTools": "Tools & connections",
630
+ "panel.render.controlBehavior": "Behavior & permissions",
631
+ "panel.render.controlSummary": "{count} items \xB7 {enabled} enabled",
632
+ "panel.render.controlSummarySource": "Source: total toggleable entries and enabled entries in scanned slots.{slot}[]; this does not prove session use",
633
+ "panel.render.controlSettingsCount": "{count} settings",
634
+ "panel.render.codexPluginControlHint": "Codex plugins: controls the whole plugin package, not an individual skill.",
635
+ "panel.render.contextSources": "Explore context sources",
636
+ "panel.render.requestsUnavailable": "Requests unavailable \xB7 view details",
637
+ "panel.render.localFeedStatus": "Local feed \xB7 {status}",
638
+ "panel.render.appFilter": "App",
639
+ "panel.render.codexSessionsInProject": "Codex sessions are in project {name}",
618
640
  "panel.render.olderSessions": "{count} older sessions",
619
641
  "panel.render.olderSessionsSource": "Source: sessions.ended and lastActivity more than {days} days ago; display only",
620
642
  "panel.render.archiveSession": "Archive",
@@ -626,16 +648,21 @@ var init_render = __esm({
626
648
  "panel.render.ccPartial": "Partly restricted",
627
649
  "panel.render.ccDisableAll": "Disable all",
628
650
  "panel.render.ccPartialWarning": "Only some messaging tools are denied. Disable all denies both SendMessage and ListAgents.",
629
- "panel.render.ccFeatures": "Claude Code features",
651
+ "panel.render.ccFeatures": "Claude Code settings",
652
+ "panel.render.ccSettingsHint": "Changes local user settings, not just the selected session. Review changes before confirming.",
653
+ "panel.render.ccMessageHelp": "What this changes",
654
+ "panel.render.ccInboundHelp": "Controls messages from other Claude Code sessions. Accept delivers messages to Claude. Hold shows a notice without delivery, until an effective setting allows acceptance. Refuse discards them.",
655
+ "panel.render.ccInboundImpact": "This does not control your chat input. Delivered messages can start a new turn in an idle session and incur usage. They do not automatically include the sender\u2019s full history or files; the recipient\u2019s own permissions still apply.",
656
+ "panel.render.ccOutboundHelp": "Lets Claude find and message other sessions, for example to share a task result. Enabling only removes these send and discovery tool denials; other permission rules still apply.",
630
657
  "panel.render.ccAutoMemory": "Auto memory",
631
- "panel.render.ccInbound": "Receive messages from other sessions",
632
- "panel.render.ccOutbound": "Send messages to other sessions",
658
+ "panel.render.ccInbound": "Messages from other Claude sessions",
659
+ "panel.render.ccOutbound": "Allow Claude to send messages",
633
660
  "panel.render.ccDefault": "Default",
634
661
  "panel.render.ccByPermissionMode": "Determined by permission mode",
635
662
  "panel.render.ccAccept": "Accept",
636
663
  "panel.render.ccHold": "Hold",
637
664
  "panel.render.ccRefuse": "Refuse",
638
- "panel.render.ccOutboundWarning": "Also disables messages to subagents and agent teams",
665
+ "panel.render.ccOutboundWarning": "Disabling denies both SendMessage and ListAgents. It stops cross-session sending and also restricts communication with subagents (assistants Claude delegates to) and agent-team members. Receiving is controlled separately above.",
639
666
  "panel.render.ccOverridden": "Overridden by {layer}; changes here have no effect",
640
667
  "panel.render.ccLayerProject": "project settings",
641
668
  "panel.render.ccLayerLocal": "project-local settings",
@@ -657,12 +684,20 @@ var init_render = __esm({
657
684
  "panel.render.skillFrontmatterSource": "Source: SKILL.md frontmatter disable-model-invocation / user-invocable; invocation mode is determined by SKILL.md. The toggle only controls configuration enablement",
658
685
  "panel.render.skillOverridesSource": "Source: settings skillOverrides; disabled in configuration",
659
686
  "panel.render.skillConfiguration": "Configuration",
687
+ "panel.render.dshControlsSummary": "{count} items \xB7 {enabled} enabled",
688
+ "panel.render.dshControlsSummarySource": "Source: total toggleable entries and enabled entries in slots.{slot}[] scanned from dsh --dump-config; configuration enablement does not prove session use",
660
689
  "panel.render.plugins": "Plugins",
661
690
  "panel.render.pluginConfigurationTip": "Configuration enablement does not prove session use; usage comes from the Codex transcript",
662
691
  "panel.render.pluginsSummary": "{enabled} plugins enabled \xB7 {used} used this session",
663
692
  "panel.render.pluginsUnobserved": "{enabled} plugins enabled \xB7 No plugin calls observed this session",
664
693
  "panel.render.pluginsSummarySource": "Source: enabled entries in slots.skills[].enabled scanned from config.toml plugin configuration; session usage is the deduplicated pluginsUsed from matching MCP tool calls in the Codex transcript against configured plugin names (with a few aliases); configuration enablement does not prove session use",
665
694
  "panel.render.skillConfigurationTip": "Whether this session actually loaded a skill is determined by the transcript",
695
+ "panel.render.ccSkillsSummary": "{enabled} skills enabled \xB7 {used} used this session",
696
+ "panel.render.ccSkillsUnobserved": "{enabled} skills enabled \xB7 No skill calls observed this session",
697
+ "panel.render.ccSkillsSummarySource": "Source: entries that are not off according to scanned slots.skills[].enabled and invocation (SKILL.md frontmatter); session usage is deduplicated skillsUsed from Skill tool calls or explicit skill command loading records in the Claude Code transcript; configuration enablement does not prove session use",
698
+ "panel.render.ccToolsSummary": "{enabled} MCP servers enabled \xB7 {used} used this session",
699
+ "panel.render.ccToolsUnobserved": "{enabled} MCP servers enabled \xB7 No MCP calls observed this session",
700
+ "panel.render.ccToolsSummarySource": "Source: enabled entries among mcpServers.* in scanned slots.tools[]; session usage is deduplicated mcpUsed from matching mcp__<server>__<tool> calls in the Claude Code transcript against configured server names (- and _ are equivalent); configuration enablement does not prove session use",
666
701
  "panel.render.skillsUsed": "Used this session: {skills}",
667
702
  "panel.render.skillsUsedSource": "Source: observed Skill tool calls / skill command triggers in the transcript",
668
703
  "panel.render.projectMenu": "Project menu",
@@ -691,6 +726,18 @@ var init_render = __esm({
691
726
  "panel.render.deleteLineNumber": "Delete line {line}",
692
727
  "panel.render.close": "Close",
693
728
  "panel.render.language": "Language",
729
+ "panel.render.noConversationObserved": "No conversation observed yet",
730
+ "panel.render.conversationDetailsPending": "Waiting for conversation details",
731
+ "panel.render.conversationDetailsPendingHint": "A conversation was observed. Its details will appear here when available. If nothing updates, check the connection details.",
732
+ "panel.render.checkConnection": "Check your connection",
733
+ "panel.render.startConversationHint": "Start or continue a conversation in {harness}. Your tasks and progress will appear here.",
734
+ "panel.render.checkConnectionHint": "Activity from {harness} is not yet confirmed. Check the connection settings, then start a conversation in the app.",
735
+ "panel.render.conversationNotShowing": "Already started, but nothing here?",
736
+ "panel.render.viewConnectionSettings": "View connection settings",
737
+ "panel.render.connectionDetails": "Connection details",
738
+ "panel.render.connectionInstallCommand": "If you need to reconnect, use this command",
739
+ "panel.render.planDisplaySettings": "Plan display settings",
740
+ "panel.render.helpAndFeedback": "Help & feedback",
694
741
  "panel.render.apiAnatomyReturnedAnEmptyArray": "/api/anatomy returned an empty array",
695
742
  "panel.render.noHarnessDetected": "No harness detected",
696
743
  "panel.render.firstRun": "First run",
@@ -714,7 +761,7 @@ var init_render = __esm({
714
761
  "panel.render.sourcePanelTimeOfTheLast": "Source: panel time of the last successful GET /api/anatomy",
715
762
  "panel.render.refreshFailedShowingDataFrom": "Refresh failed; showing data from",
716
763
  "panel.render.dataSuffix": "",
717
- "panel.render.contextBreakdown": "CONTEXT breakdown",
764
+ "panel.render.contextBreakdown": "Context estimate",
718
765
  "panel.render.previewTheCompleteContentBeforeSending": "Preview the complete content before sending; remove individual lines and select Send to submit; closing sends nothing",
719
766
  "panel.render.shareConfigurationSample": "Share configuration sample",
720
767
  "panel.render.thisItemIsDisabledToggleableItems": "This item is disabled; toggleable items can be enabled in CONFIGURE below",
@@ -946,7 +993,7 @@ var init_render = __esm({
946
993
  "panel.render.noExecutionEvidenceYet": "\u25CB No execution evidence yet",
947
994
  "panel.render.tasks": "Tasks",
948
995
  "panel.render.controls": "Controls",
949
- "panel.render.billing": "Billing",
996
+ "panel.render.billing": "Usage",
950
997
  "panel.render.turns": "{p0} turns",
951
998
  "panel.render.approx": " \xB7 Approx. {p0}",
952
999
  "panel.render.subagent": "Subagent",
@@ -1122,6 +1169,11 @@ var init_render = __esm({
1122
1169
  "panel.render.feedbackSignalsAreNotConnectedOr": "Feedback signals are not connected or unavailable; cannot determine whether you are needed",
1123
1170
  "panel.render.viewPlanProtocol": "\xB7 View plan protocol",
1124
1171
  "panel.render.currentBranch": "Current branch",
1172
+ "panel.render.moreBranches": "{count} more branches",
1173
+ "panel.render.oneMoreBranch": "{count} more branch",
1174
+ "panel.render.branchCurrentPoints": "{count} current points",
1175
+ "panel.render.branchCurrentPoint": "{count} current point",
1176
+ "panel.render.branchCurrentPointsSource": "Source: currentPoints within this top-level node subtree",
1125
1177
  "panel.render.noCurrentBranchProvided": "No current branch provided",
1126
1178
  "panel.render.currentTaskLabel": "Current task",
1127
1179
  "panel.render.sourceFirstScreenCurrentPointsLength": "Source: firstScreen.currentPoints.length",
@@ -1530,6 +1582,8 @@ var init_labels2 = __esm({
1530
1582
  "packages/i18n/dist/catalog/zh/labels.js"() {
1531
1583
  "use strict";
1532
1584
  labels_default2 = {
1585
+ "panel.source.codexProject": "Codex \u9879\u76EE",
1586
+ "panel.source.codexUngrouped": "Codex \u672A\u5206\u7EC4",
1533
1587
  "panel.source.planStep": "plan.md \u6B65\u9AA4",
1534
1588
  "panel.source.planInstruction": "\u8BA1\u5212\u6240\u5C5E\u6307\u4EE4",
1535
1589
  "panel.source.latestInstruction": "\u6700\u65B0\u6307\u4EE4",
@@ -1567,6 +1621,7 @@ var init_narrative2 = __esm({
1567
1621
  "packages/i18n/dist/catalog/zh/narrative.js"() {
1568
1622
  "use strict";
1569
1623
  narrative_default2 = {
1624
+ "narrative.codexUngrouped": "\u672A\u5206\u7EC4",
1570
1625
  "narrative.noStateDirectory": "\u672A\u914D\u7F6E\u672C\u673A\u72B6\u6001\u76EE\u5F55",
1571
1626
  "narrative.acceptanceUnreadable": "\u672C\u673A\u9A8C\u6536\u72B6\u6001\u4E0D\u53EF\u8BFB",
1572
1627
  "narrative.homeDirectory": "\u65E0\u9879\u76EE\u76EE\u5F55(\u5BB6\u76EE\u5F55)",
@@ -1832,6 +1887,25 @@ var init_render2 = __esm({
1832
1887
  "packages/i18n/dist/catalog/zh/render.js"() {
1833
1888
  "use strict";
1834
1889
  render_default2 = {
1890
+ "panel.render.projectsPageTitle": "\u9879\u76EE\u603B\u89C8",
1891
+ "panel.render.projectsPageHint": "\u96C6\u4E2D\u67E5\u770B\u5404\u4E2A\u7F16\u7A0B\u5DE5\u5177\u4E2D\u7684\u76EE\u6807\u3001\u8FDB\u5EA6\u548C\u5F85\u51B3\u4E8B\u9879\u3002",
1892
+ "panel.render.controlsPageHint": "\u7BA1\u7406\u5DE5\u5177\u3001\u504F\u597D\u8BBE\u7F6E\uFF0C\u4EE5\u53CA\u8FD4\u56DE\u4F1A\u8BDD\u7684\u65B9\u5F0F\u3002",
1893
+ "panel.render.optionalSuggestions": "\u53EF\u9009\u4F18\u5316\u5EFA\u8BAE",
1894
+ "panel.render.suggestionsHint": "\u6839\u636E\u5F53\u524D\u4F1A\u8BDD\u8BB0\u5F55\u751F\u6210\uFF0C\u4EC5\u4F9B\u53C2\u8003\u3002\u5E94\u7528\u524D\u8BF7\u67E5\u770B\u65B9\u6848\u3002",
1895
+ "panel.render.usagePageHint": "\u5B9E\u9645\u62A5\u544A\u7684\u7528\u91CF\u4E0E\u4E0A\u4E0B\u6587\u4F30\u7B97\uFF0C\u5206\u5F00\u5C55\u793A\u3002",
1896
+ "panel.render.toolsAndPreferences": "\u5DE5\u5177\u4E0E\u504F\u597D",
1897
+ "panel.render.controlSkills": "\u6280\u80FD\u4E0E\u63D2\u4EF6",
1898
+ "panel.render.controlTools": "\u5DE5\u5177\u4E0E\u8FDE\u63A5",
1899
+ "panel.render.controlBehavior": "\u884C\u4E3A\u4E0E\u6743\u9650",
1900
+ "panel.render.controlSummary": "\u5171 {count} \u9879 \xB7 \u5DF2\u542F\u7528 {enabled} \u9879",
1901
+ "panel.render.controlSummarySource": "\u6765\u6E90:\u626B\u63CF\u7684 slots.{slot}[] \u4E2D\u53EF\u5F00\u5173\u6761\u76EE\u7684\u603B\u6570\u4E0E enabled \u6570\uFF1B\u4E0D\u4EE3\u8868\u5F53\u524D\u4F1A\u8BDD\u5B9E\u9645\u4F7F\u7528",
1902
+ "panel.render.controlSettingsCount": "{count} \u9879\u8BBE\u7F6E",
1903
+ "panel.render.codexPluginControlHint": "Codex \u63D2\u4EF6\uFF1A\u8FD9\u91CC\u63A7\u5236\u6574\u4E2A\u63D2\u4EF6\u5305\uFF0C\u4E0D\u662F\u5355\u4E2A\u6280\u80FD\u3002",
1904
+ "panel.render.contextSources": "\u67E5\u770B\u4E0A\u4E0B\u6587\u6765\u6E90",
1905
+ "panel.render.requestsUnavailable": "\u6682\u65F6\u65E0\u6CD5\u89C2\u5BDF\u8BF7\u6C42 \xB7 \u67E5\u770B\u8BE6\u60C5",
1906
+ "panel.render.localFeedStatus": "\u672C\u5730\u6570\u636E\u6D41 \xB7 {status}",
1907
+ "panel.render.appFilter": "\u5E94\u7528",
1908
+ "panel.render.codexSessionsInProject": "Codex \u4F1A\u8BDD\u5728\u9879\u76EE {name} \u4E0B",
1835
1909
  "panel.render.olderSessions": "\u66F4\u65E9\u7684 {count} \u4E2A\u4F1A\u8BDD",
1836
1910
  "panel.render.olderSessionsSource": "\u6765\u6E90:sessions.ended \u4E14 lastActivity \u65E9\u4E8E\u5F53\u524D\u65F6\u95F4 {days} \u5929;\u4EC5\u6298\u53E0\u663E\u793A",
1837
1911
  "panel.render.archiveSession": "\u5F52\u6863",
@@ -1843,16 +1917,21 @@ var init_render2 = __esm({
1843
1917
  "panel.render.ccPartial": "\u90E8\u5206\u53D7\u9650",
1844
1918
  "panel.render.ccDisableAll": "\u5168\u90E8\u5173\u95ED",
1845
1919
  "panel.render.ccPartialWarning": "\u4EC5\u7981\u7528\u4E86\u90E8\u5206\u6D88\u606F\u5DE5\u5177\uFF1B\u5168\u90E8\u5173\u95ED\u4F1A\u540C\u65F6\u62D2\u7EDD SendMessage \u4E0E ListAgents\u3002",
1846
- "panel.render.ccFeatures": "Claude Code \u529F\u80FD",
1920
+ "panel.render.ccFeatures": "Claude Code \u8BBE\u7F6E",
1921
+ "panel.render.ccSettingsHint": "\u4FEE\u6539\u672C\u673A\u7528\u6237\u7EA7\u914D\u7F6E\uFF0C\u4E0D\u53EA\u5F71\u54CD\u5F53\u524D\u4F1A\u8BDD\u3002\u786E\u8BA4\u524D\u53EF\u67E5\u770B\u6539\u52A8\u3002",
1922
+ "panel.render.ccMessageHelp": "\u4E86\u89E3\u5F71\u54CD",
1923
+ "panel.render.ccInboundHelp": "\u5904\u7406\u5176\u4ED6 Claude Code \u4F1A\u8BDD\u53D1\u6765\u7684\u6D88\u606F\u3002\u63A5\u6536\uFF1A\u4EA4\u7ED9 Claude\uFF1B\u6682\u5B58\uFF1A\u5148\u663E\u793A\u6536\u5230\u63D0\u793A\uFF0C\u4E0D\u4EA4\u7ED9 Claude\uFF0C\u4E4B\u540E\u6709\u6548\u8BBE\u7F6E\u5141\u8BB8\u63A5\u6536\u65F6\u518D\u4EA4\u4ED8\uFF1B\u62D2\u7EDD\uFF1A\u4E22\u5F03\u6D88\u606F\u3002",
1924
+ "panel.render.ccInboundImpact": "\u8FD9\u4E0D\u662F\u4F60\u7684\u804A\u5929\u8F93\u5165\u5F00\u5173\u3002\u6536\u5230\u5E76\u4EA4\u4ED8\u7684\u6D88\u606F\u53EF\u80FD\u8BA9\u7A7A\u95F2\u7684 Claude \u5F00\u59CB\u65B0\u4E00\u8F6E\u5904\u7406\uFF0C\u4EA7\u751F\u7528\u91CF\uFF1B\u4E0D\u4F1A\u81EA\u52A8\u9644\u5E26\u53D1\u9001\u65B9\u7684\u5B8C\u6574\u5BF9\u8BDD\u6216\u6587\u4EF6\uFF0C\u63A5\u6536\u65B9\u4ECD\u9075\u5B88\u81EA\u8EAB\u6743\u9650\u3002",
1925
+ "panel.render.ccOutboundHelp": "\u5141\u8BB8 Claude \u67E5\u627E\u5176\u4ED6\u4F1A\u8BDD\u5E76\u53D1\u9001\u6D88\u606F\uFF0C\u4F8B\u5982\u628A\u5B8C\u6210\u60C5\u51B5\u544A\u8BC9\u53E6\u4E00\u4E2A\u4EFB\u52A1\u3002\u5F00\u542F\u53EA\u79FB\u9664\u8FD9\u91CC\u5BF9\u53D1\u9001\u548C\u67E5\u627E\u5DE5\u5177\u7684\u7981\u7528\uFF0C\u4ECD\u53D7\u5176\u4ED6\u6743\u9650\u8BBE\u7F6E\u9650\u5236\u3002",
1847
1926
  "panel.render.ccAutoMemory": "Auto memory",
1848
- "panel.render.ccInbound": "\u63A5\u6536\u5176\u4ED6\u4F1A\u8BDD\u7684\u6D88\u606F",
1849
- "panel.render.ccOutbound": "\u5411\u5176\u4ED6\u4F1A\u8BDD\u53D1\u6D88\u606F",
1927
+ "panel.render.ccInbound": "\u63A5\u6536\u5176\u4ED6 Claude \u4F1A\u8BDD\u7684\u6D88\u606F",
1928
+ "panel.render.ccOutbound": "\u5141\u8BB8 Claude \u53D1\u9001\u6D88\u606F",
1850
1929
  "panel.render.ccDefault": "\u9ED8\u8BA4",
1851
1930
  "panel.render.ccByPermissionMode": "\u6309\u6743\u9650\u6A21\u5F0F\u51B3\u5B9A",
1852
1931
  "panel.render.ccAccept": "\u63A5\u6536",
1853
1932
  "panel.render.ccHold": "\u6682\u5B58",
1854
1933
  "panel.render.ccRefuse": "\u62D2\u7EDD",
1855
- "panel.render.ccOutboundWarning": "\u540C\u65F6\u7981\u6389\u5BF9\u5B50\u4EE3\u7406\u4E0E agent team \u7684\u6D88\u606F",
1934
+ "panel.render.ccOutboundWarning": "\u5173\u95ED\u4F1A\u540C\u65F6\u7981\u7528 SendMessage \u548C ListAgents\uFF1B\u4E0D\u4EC5\u505C\u6B62\u8DE8\u4F1A\u8BDD\u53D1\u6D88\u606F\uFF0C\u4E5F\u4F1A\u9650\u5236 Claude \u4E0E\u5B50\u4EE3\u7406\uFF08\u5B83\u5206\u6D3E\u51FA\u53BB\u7684\u52A9\u624B\uFF09\u548C Agent \u56E2\u961F\u6210\u5458\u7684\u901A\u4FE1\u3002\u63A5\u6536\u6D88\u606F\u7531\u4E0A\u9762\u7684\u8BBE\u7F6E\u5355\u72EC\u63A7\u5236\u3002",
1856
1935
  "panel.render.ccOverridden": "\u88AB {layer} \u8986\u76D6\uFF0C\u6B64\u5904\u6539\u52A8\u4E0D\u751F\u6548",
1857
1936
  "panel.render.ccLayerProject": "\u9879\u76EE\u5C42",
1858
1937
  "panel.render.ccLayerLocal": "\u9879\u76EE\u672C\u5730\u5C42",
@@ -1874,12 +1953,20 @@ var init_render2 = __esm({
1874
1953
  "panel.render.skillFrontmatterSource": "\u6765\u6E90:SKILL.md frontmatter disable-model-invocation / user-invocable;\u8C03\u7528\u6A21\u5F0F\u7531 SKILL.md \u51B3\u5B9A\uFF0C\u5F00\u5173\u53EA\u63A7\u5236\u914D\u7F6E\u542F\u7528\u72B6\u6001",
1875
1954
  "panel.render.skillOverridesSource": "\u6765\u6E90:settings skillOverrides;\u914D\u7F6E\u5DF2\u7981\u7528",
1876
1955
  "panel.render.skillConfiguration": "\u914D\u7F6E\u7EA7",
1956
+ "panel.render.dshControlsSummary": "\u5171 {count} \u9879 \xB7 \u5DF2\u542F\u7528 {enabled} \u9879",
1957
+ "panel.render.dshControlsSummarySource": "\u6765\u6E90:dsh --dump-config \u626B\u63CF slots.{slot}[] \u4E2D toggleable \u6761\u76EE\u7684\u603B\u6570\u4E0E enabled \u6570\uFF1B\u914D\u7F6E\u542F\u7528\u4E0D\u7B49\u4E8E\u4F1A\u8BDD\u4F7F\u7528",
1877
1958
  "panel.render.plugins": "\u63D2\u4EF6",
1878
1959
  "panel.render.pluginConfigurationTip": "\u914D\u7F6E\u542F\u7528\u4E0D\u4EE3\u8868\u672C\u4F1A\u8BDD\u8C03\u7528\uFF1B\u4F1A\u8BDD\u4F7F\u7528\u4EE5 Codex transcript \u4E3A\u51C6",
1879
1960
  "panel.render.pluginsSummary": "{enabled} \u4E2A\u63D2\u4EF6\u5DF2\u542F\u7528 \xB7 \u672C\u4F1A\u8BDD\u7528\u5230 {used} \u4E2A",
1880
1961
  "panel.render.pluginsUnobserved": "{enabled} \u4E2A\u63D2\u4EF6\u5DF2\u542F\u7528 \xB7 \u672C\u4F1A\u8BDD\u672A\u89C2\u5BDF\u5230\u63D2\u4EF6\u8C03\u7528",
1881
1962
  "panel.render.pluginsSummarySource": "\u6765\u6E90:config.toml \u63D2\u4EF6\u914D\u7F6E\u626B\u63CF slots.skills[].enabled \u7684\u542F\u7528\u6761\u76EE\u6570\uFF1B\u672C\u4F1A\u8BDD\u7528\u5230\u6570\u6765\u81EA\u6309\u914D\u7F6E\u63D2\u4EF6\u540D\u5339\u914D Codex transcript \u91CC\u7684 MCP \u5DE5\u5177\u8C03\u7528\uFF08\u5C11\u91CF\u522B\u540D\uFF09\u540E\u53BB\u91CD\u7684 pluginsUsed\uFF0C\u914D\u7F6E\u542F\u7528\u4E0D\u7B49\u4E8E\u4F1A\u8BDD\u4F7F\u7528",
1882
1963
  "panel.render.skillConfigurationTip": "\u672C\u4F1A\u8BDD\u662F\u5426\u771F\u7684\u52A0\u8F7D\u4EE5 transcript \u4E3A\u51C6",
1964
+ "panel.render.ccSkillsSummary": "{enabled} \u4E2A\u6280\u80FD\u5DF2\u542F\u7528 \xB7 \u672C\u4F1A\u8BDD\u7528\u5230 {used} \u4E2A",
1965
+ "panel.render.ccSkillsUnobserved": "{enabled} \u4E2A\u6280\u80FD\u5DF2\u542F\u7528 \xB7 \u672C\u4F1A\u8BDD\u672A\u89C2\u5BDF\u5230\u6280\u80FD\u8C03\u7528",
1966
+ "panel.render.ccSkillsSummarySource": "\u6765\u6E90:\u914D\u7F6E\u626B\u63CF slots.skills[].enabled \u4E0E invocation\uFF08SKILL.md frontmatter\uFF09\u7684\u975E\u5173\u95ED\u6761\u76EE\u6570\uFF1B\u672C\u4F1A\u8BDD\u7528\u5230\u6570\u6765\u81EA Claude Code transcript \u4E2D Skill \u5DE5\u5177\u8C03\u7528\u6216\u660E\u786E\u6280\u80FD\u547D\u4EE4\u52A0\u8F7D\u8BB0\u5F55\uFF0C\u53BB\u91CD\u540E\u4E3A skillsUsed\uFF0C\u914D\u7F6E\u542F\u7528\u4E0D\u7B49\u4E8E\u4F1A\u8BDD\u4F7F\u7528",
1967
+ "panel.render.ccToolsSummary": "{enabled} \u4E2A MCP \u670D\u52A1\u5DF2\u542F\u7528 \xB7 \u672C\u4F1A\u8BDD\u7528\u5230 {used} \u4E2A",
1968
+ "panel.render.ccToolsUnobserved": "{enabled} \u4E2A MCP \u670D\u52A1\u5DF2\u542F\u7528 \xB7 \u672C\u4F1A\u8BDD\u672A\u89C2\u5BDF\u5230 MCP \u8C03\u7528",
1969
+ "panel.render.ccToolsSummarySource": "\u6765\u6E90:\u914D\u7F6E\u626B\u63CF slots.tools[] \u4E2D mcpServers.* \u6761\u76EE\u7684 enabled \u542F\u7528\u6570\uFF1B\u672C\u4F1A\u8BDD\u7528\u5230\u6570\u6765\u81EA Claude Code transcript \u4E2D mcp__<server>__<tool> \u8C03\u7528\u4E0E\u914D\u7F6E\u670D\u52A1\u540D\u5339\u914D\uFF08- / _ \u7B49\u4EF7\uFF09\uFF0C\u53BB\u91CD\u540E\u4E3A mcpUsed\uFF0C\u914D\u7F6E\u542F\u7528\u4E0D\u7B49\u4E8E\u4F1A\u8BDD\u4F7F\u7528",
1883
1970
  "panel.render.skillsUsed": "\u672C\u4F1A\u8BDD\u5DF2\u7528:{skills}",
1884
1971
  "panel.render.skillsUsedSource": "\u6765\u6E90:transcript \u4E2D\u89C2\u5BDF\u5230\u7684 Skill \u5DE5\u5177\u8C03\u7528 / \u6280\u80FD\u547D\u4EE4\u89E6\u53D1\u8BB0\u5F55",
1885
1972
  "panel.render.projectMenu": "\u9879\u76EE\u83DC\u5355",
@@ -1908,6 +1995,18 @@ var init_render2 = __esm({
1908
1995
  "panel.render.deleteLineNumber": "\u5220\u9664\u7B2C {line} \u884C",
1909
1996
  "panel.render.close": "\u5173\u95ED",
1910
1997
  "panel.render.language": "\u8BED\u8A00",
1998
+ "panel.render.noConversationObserved": "\u8FD8\u6CA1\u6709\u89C2\u5BDF\u5230\u4F1A\u8BDD",
1999
+ "panel.render.conversationDetailsPending": "\u6B63\u5728\u7B49\u5F85\u4F1A\u8BDD\u8BE6\u60C5",
2000
+ "panel.render.conversationDetailsPendingHint": "\u5DF2\u6536\u5230\u4F1A\u8BDD\u4FE1\u606F\u3002\u8BE6\u60C5\u53EF\u7528\u540E\u4F1A\u663E\u793A\u5728\u8FD9\u91CC\uFF1B\u5982\u679C\u4E00\u76F4\u6CA1\u6709\u66F4\u65B0\uFF0C\u8BF7\u67E5\u770B\u8FDE\u63A5\u8BE6\u60C5\u3002",
2001
+ "panel.render.checkConnection": "\u5148\u68C0\u67E5\u8FDE\u63A5\u8BBE\u7F6E",
2002
+ "panel.render.startConversationHint": "\u5728 {harness} \u4E2D\u5F00\u59CB\u6216\u7EE7\u7EED\u5BF9\u8BDD\uFF0C\u4EFB\u52A1\u548C\u8FDB\u5C55\u4F1A\u51FA\u73B0\u5728\u8FD9\u91CC\u3002",
2003
+ "panel.render.checkConnectionHint": "\u5C1A\u672A\u786E\u8BA4 {harness} \u7684\u6D3B\u52A8\u63A5\u5165\u3002\u67E5\u770B\u8FDE\u63A5\u8BBE\u7F6E\u540E\uFF0C\u5728\u539F\u5E94\u7528\u4E2D\u5F00\u59CB\u5BF9\u8BDD\u3002",
2004
+ "panel.render.conversationNotShowing": "\u5DF2\u7ECF\u5F00\u59CB\u5BF9\u8BDD\uFF0C\u4F46\u6CA1\u6709\u663E\u793A\uFF1F",
2005
+ "panel.render.viewConnectionSettings": "\u67E5\u770B\u8FDE\u63A5\u8BBE\u7F6E",
2006
+ "panel.render.connectionDetails": "\u8FDE\u63A5\u8BE6\u60C5",
2007
+ "panel.render.connectionInstallCommand": "\u9700\u8981\u91CD\u65B0\u63A5\u5165\u65F6\uFF0C\u53EF\u4F7F\u7528\u6B64\u547D\u4EE4\uFF1A",
2008
+ "panel.render.planDisplaySettings": "\u8BA1\u5212\u663E\u793A\u8BBE\u7F6E",
2009
+ "panel.render.helpAndFeedback": "\u5E2E\u52A9\u4E0E\u53CD\u9988",
1911
2010
  "panel.render.apiAnatomyReturnedAnEmptyArray": "/api/anatomy \u8FD4\u56DE\u4E86\u7A7A\u6570\u7EC4",
1912
2011
  "panel.render.noHarnessDetected": "\u672A\u68C0\u6D4B\u5230 harness",
1913
2012
  "panel.render.firstRun": "\u5148\u8FD0\u884C",
@@ -1931,7 +2030,7 @@ var init_render2 = __esm({
1931
2030
  "panel.render.sourcePanelTimeOfTheLast": "\u6765\u6E90:\u4E0A\u6B21\u6210\u529F GET /api/anatomy \u7684\u9762\u677F\u65F6\u95F4",
1932
2031
  "panel.render.refreshFailedShowingDataFrom": "\u5237\u65B0\u5931\u8D25,\u663E\u793A\u7684\u662F",
1933
2032
  "panel.render.dataSuffix": "\u7684\u6570\u636E",
1934
- "panel.render.contextBreakdown": "CONTEXT \u7EC4\u6210",
2033
+ "panel.render.contextBreakdown": "\u4E0A\u4E0B\u6587\u4F30\u7B97",
1935
2034
  "panel.render.previewTheCompleteContentBeforeSending": "\u6253\u5F00\u9884\u89C8\u5F39\u5C42:\u5148\u770B\u5230\u5C06\u53D1\u9001\u7684\u5B8C\u6574\u5185\u5BB9,\u53EF\u9010\u884C\u5220,\u70B9\u300C\u53D1\u9001\u300D\u624D\u4F1A\u53D1\u51FA;\u5173\u95ED = \u4EC0\u4E48\u90FD\u4E0D\u53D1",
1936
2035
  "panel.render.shareConfigurationSample": "\u5206\u4EAB\u914D\u7F6E\u6837\u672C",
1937
2036
  "panel.render.thisItemIsDisabledToggleableItems": "\u8BE5\u6761\u76EE\u5F53\u524D\u88AB\u5173\u95ED;\u53EF\u5F00\u5173\u6761\u76EE\u5728\u4E0B\u65B9 CONFIGURE \u533A\u4E00\u952E\u6253\u5F00",
@@ -2163,7 +2262,7 @@ var init_render2 = __esm({
2163
2262
  "panel.render.noExecutionEvidenceYet": "\u25CB \u5C1A\u65E0\u6267\u884C\u8BC1\u636E",
2164
2263
  "panel.render.tasks": "\u4EFB\u52A1",
2165
2264
  "panel.render.controls": "\u63A7\u5236",
2166
- "panel.render.billing": "\u8D26\u5355",
2265
+ "panel.render.billing": "\u7528\u91CF",
2167
2266
  "panel.render.turns": "{p0} \u8F6E",
2168
2267
  "panel.render.approx": " \xB7 \u7EA6 {p0}",
2169
2268
  "panel.render.subagent": "\u5B50 agent",
@@ -2339,6 +2438,11 @@ var init_render2 = __esm({
2339
2438
  "panel.render.feedbackSignalsAreNotConnectedOr": "\u53CD\u9988\u4FE1\u53F7\u672A\u63A5\u7EBF\u6216\u4E0D\u53EF\u7528\uFF0C\u65E0\u6CD5\u786E\u8BA4\u662F\u5426\u9700\u8981\u4F60",
2340
2439
  "panel.render.viewPlanProtocol": "\xB7 \u67E5\u770B\u8BA1\u5212\u534F\u8BAE",
2341
2440
  "panel.render.currentBranch": "\u6240\u5728\u5206\u652F",
2441
+ "panel.render.moreBranches": "\u8FD8\u6709 {count} \u6761\u5206\u652F",
2442
+ "panel.render.oneMoreBranch": "\u8FD8\u6709 {count} \u6761\u5206\u652F",
2443
+ "panel.render.branchCurrentPoints": "{count} \u4E2A\u5F53\u524D\u70B9",
2444
+ "panel.render.branchCurrentPoint": "{count} \u4E2A\u5F53\u524D\u70B9",
2445
+ "panel.render.branchCurrentPointsSource": "\u6765\u6E90:currentPoints \u4E2D\u5C5E\u4E8E\u8BE5\u9876\u5C42\u8282\u70B9\u5B50\u6811\u7684\u5F53\u524D\u70B9",
2342
2446
  "panel.render.noCurrentBranchProvided": "\u5C1A\u672A\u63D0\u4F9B\u6240\u5728\u5206\u652F",
2343
2447
  "panel.render.currentTaskLabel": "\u5F53\u524D\u4EFB\u52A1",
2344
2448
  "panel.render.sourceFirstScreenCurrentPointsLength": "\u6765\u6E90:firstScreen.currentPoints.length",
@@ -13724,6 +13828,20 @@ var init_generic_waiting = __esm({
13724
13828
  }
13725
13829
  });
13726
13830
 
13831
+ // packages/adapter-cc/dist/mcp-tools.js
13832
+ function recognizeMcpTool(name, configuredServers) {
13833
+ const [prefix, server, ...tool] = name.split("__");
13834
+ if (prefix !== "mcp" || !server || tool.length === 0 || ![server, ...tool].every((part) => /^[a-zA-Z][a-zA-Z0-9_-]*$/.test(part))) {
13835
+ return void 0;
13836
+ }
13837
+ return configuredServers.find((configured) => configured.replaceAll("-", "_") === server.replaceAll("-", "_"));
13838
+ }
13839
+ var init_mcp_tools = __esm({
13840
+ "packages/adapter-cc/dist/mcp-tools.js"() {
13841
+ "use strict";
13842
+ }
13843
+ });
13844
+
13727
13845
  // packages/adapter-cc/dist/protocol.js
13728
13846
  import { existsSync as existsSync10, mkdirSync as mkdirSync6, readdirSync as readdirSync3, readFileSync as readFileSync10, rmdirSync, rmSync as rmSync5, writeFileSync as writeFileSync7 } from "node:fs";
13729
13847
  import { homedir as homedir10 } from "node:os";
@@ -13968,6 +14086,7 @@ __export(dist_exports2, {
13968
14086
  installProtocolCcUser: () => installProtocolCcUser,
13969
14087
  protocolStatusCc: () => protocolStatusCc,
13970
14088
  protocolStatusCcUser: () => protocolStatusCcUser,
14089
+ recognizeMcpTool: () => recognizeMcpTool,
13971
14090
  uninstallProtocolCc: () => uninstallProtocolCc,
13972
14091
  uninstallProtocolCcUser: () => uninstallProtocolCcUser
13973
14092
  });
@@ -13991,6 +14110,7 @@ var init_dist4 = __esm({
13991
14110
  init_scan();
13992
14111
  init_generic_waiting();
13993
14112
  init_hooks2();
14113
+ init_mcp_tools();
13994
14114
  init_protocol2();
13995
14115
  init_scan();
13996
14116
  init_protocol_user();
@@ -16059,8 +16179,48 @@ process.stdin.on('end', async () => {
16059
16179
  });
16060
16180
 
16061
16181
  // packages/adapter-codex/dist/scan.js
16062
- import { existsSync as existsSync13, readdirSync as readdirSync5, readFileSync as readFileSync13, statSync as statSync4 } from "node:fs";
16182
+ import { existsSync as existsSync13, readdirSync as readdirSync5, readFileSync as readFileSync13, realpathSync as realpathSync2, statSync as statSync4 } from "node:fs";
16063
16183
  import { dirname as dirname13, isAbsolute as isAbsolute3, join as join20, resolve as resolve8 } from "node:path";
16184
+ function readCodexProjects(homeDir) {
16185
+ try {
16186
+ const state = JSON.parse(readFileSync13(join20(homeDir, ".codex", ".codex-global-state.json"), "utf8"));
16187
+ if (!isTable(state))
16188
+ return void 0;
16189
+ const localProjects = state["local-projects"];
16190
+ const threadAssignments = state["thread-project-assignments"];
16191
+ const order = state["project-order"];
16192
+ if (!isTable(localProjects) || !isTable(threadAssignments) || !Array.isArray(order) || !order.every((id) => typeof id === "string")) {
16193
+ return void 0;
16194
+ }
16195
+ const projects = /* @__PURE__ */ Object.create(null);
16196
+ for (const [key, project] of Object.entries(localProjects)) {
16197
+ if (!isTable(project) || typeof project.id !== "string" || project.id !== key || typeof project.name !== "string" || !Array.isArray(project.rootPaths) || !project.rootPaths.every((root) => typeof root === "string" && isAbsolute3(root))) {
16198
+ return void 0;
16199
+ }
16200
+ projects[key] = {
16201
+ id: project.id,
16202
+ name: project.name,
16203
+ rootPaths: project.rootPaths.map((root) => {
16204
+ try {
16205
+ return realpathSync2(root);
16206
+ } catch {
16207
+ return root;
16208
+ }
16209
+ })
16210
+ };
16211
+ }
16212
+ const assignments = /* @__PURE__ */ Object.create(null);
16213
+ for (const [threadId, assignment] of Object.entries(threadAssignments)) {
16214
+ if (!isTable(assignment) || assignment.projectKind !== "local" || typeof assignment.projectId !== "string") {
16215
+ return void 0;
16216
+ }
16217
+ assignments[threadId] = assignment.projectId;
16218
+ }
16219
+ return { projects, assignments, order };
16220
+ } catch {
16221
+ return void 0;
16222
+ }
16223
+ }
16064
16224
  async function detect(options) {
16065
16225
  const { codexHome } = resolvePaths(options);
16066
16226
  return { installed: existsSync13(codexHome) };
@@ -16618,6 +16778,7 @@ __export(dist_exports3, {
16618
16778
  installProtocolCodexUser: () => installProtocolCodexUser,
16619
16779
  protocolStatusCodex: () => protocolStatusCodex,
16620
16780
  protocolStatusCodexUser: () => protocolStatusCodexUser,
16781
+ readCodexProjects: () => readCodexProjects,
16621
16782
  recognizePluginTool: () => recognizePluginTool,
16622
16783
  resolveNodeExecutable: () => resolveNodeExecutable,
16623
16784
  uninstallProtocolCodex: () => uninstallProtocolCodex,
@@ -16643,6 +16804,7 @@ var init_dist6 = __esm({
16643
16804
  init_hooks3();
16644
16805
  init_plugin_tools();
16645
16806
  init_protocol3();
16807
+ init_scan2();
16646
16808
  init_protocol_user2();
16647
16809
  }
16648
16810
  });
@@ -17068,8 +17230,9 @@ init_dist6();
17068
17230
  init_dist3();
17069
17231
  init_dist2();
17070
17232
  init_dist();
17233
+ import { realpathSync as realpathSync3, statSync as statSync6 } from "node:fs";
17071
17234
  import { readdir as readdir2 } from "node:fs/promises";
17072
- import { isAbsolute as isAbsolute6, join as join26, resolve as resolve12 } from "node:path";
17235
+ import { isAbsolute as isAbsolute6, join as join26, relative as relative4, resolve as resolve12 } from "node:path";
17073
17236
 
17074
17237
  // packages/narrative/dist/attribute.js
17075
17238
  function extractSteps(lines2) {
@@ -17206,6 +17369,9 @@ function parseTurnContext(payload, timestamp) {
17206
17369
  assignString(line, "turnId", optionalString(payload?.turn_id));
17207
17370
  assignString(line, "model", optionalString(payload?.model));
17208
17371
  assignString(line, "cwd", optionalString(payload?.cwd));
17372
+ if (payload?.approvals_reviewer === "user" || payload?.approvals_reviewer === "auto_review") {
17373
+ line.approvalsReviewer = payload.approvals_reviewer;
17374
+ }
17209
17375
  return line;
17210
17376
  }
17211
17377
  function parseEventMessage(payload, timestamp) {
@@ -17402,7 +17568,31 @@ function isRecord2(value) {
17402
17568
  }
17403
17569
 
17404
17570
  // packages/narrative/dist/parse.js
17571
+ function userRequestText(text) {
17572
+ let body = text.trim();
17573
+ if (/^<(task-notification|system-reminder)\b/u.test(body))
17574
+ return "";
17575
+ let browserEnvelope = false;
17576
+ if (/^<in-app-browser-context\b/u.test(body)) {
17577
+ const end = body.indexOf("</in-app-browser-context>");
17578
+ if (end < 0)
17579
+ return "";
17580
+ body = body.slice(end + "</in-app-browser-context>".length).trim();
17581
+ browserEnvelope = true;
17582
+ }
17583
+ if (/^# Files mentioned by the user:[ \t]*(?:\r?\n|$)/u.test(body)) {
17584
+ const boundary = /^## My request:[ \t]*(?:\r?\n|$)/mu.exec(body);
17585
+ return boundary === null ? "" : body.slice(boundary.index + boundary[0].length).trim();
17586
+ }
17587
+ if (browserEnvelope) {
17588
+ const boundary = /^## My request:[ \t]*(?:\r?\n|$)/u.exec(body);
17589
+ return boundary === null ? "" : body.slice(boundary[0].length).trim();
17590
+ }
17591
+ return body;
17592
+ }
17405
17593
  function isHarnessSystemNotice(text) {
17594
+ if (/^\s*<in-app-browser-context\b/u.test(text))
17595
+ return userRequestText(text) === "";
17406
17596
  return /^\s*<(task-notification|system-reminder|in-app-browser-context)\b/u.test(text);
17407
17597
  }
17408
17598
  function parseTranscriptLine(line) {
@@ -19145,7 +19335,7 @@ function resolveWingmanVersion({ defined, moduleUrl = import.meta.url, readPacka
19145
19335
  return void 0;
19146
19336
  }
19147
19337
  function wingmanVersion() {
19148
- const defined = false ? void 0 : "0.9.1";
19338
+ const defined = false ? void 0 : "0.9.3";
19149
19339
  return resolveWingmanVersion({
19150
19340
  defined,
19151
19341
  readPackage: (url) => JSON.parse(readFileSync17(url, "utf8"))
@@ -19175,6 +19365,7 @@ function acceptanceView(homeDir, overlay, key) {
19175
19365
  }
19176
19366
  function createNarrativeService(options = {}) {
19177
19367
  let codexPluginsProvider = options.codexPlugins;
19368
+ let ccMcpServersProvider = options.ccMcpServers;
19178
19369
  const follow = options.followTranscripts ?? true;
19179
19370
  const intervalMs = options.intervalMs ?? 500;
19180
19371
  const now = options.now ?? (() => /* @__PURE__ */ new Date());
@@ -19192,9 +19383,46 @@ function createNarrativeService(options = {}) {
19192
19383
  const projectFiles = /* @__PURE__ */ new Map();
19193
19384
  const rememberedProjectRoots = /* @__PURE__ */ new Map();
19194
19385
  const seenProjectRoots = /* @__PURE__ */ new Set();
19386
+ let codexProjects;
19387
+ let codexProjectsSignature;
19388
+ const codexRootResolutions = /* @__PURE__ */ new Map();
19195
19389
  let projectMemoryUnavailable;
19196
19390
  let notificationQueued = false;
19197
19391
  let closed = false;
19392
+ function refreshCodexProjects() {
19393
+ if (options.homeDir === void 0 || closed)
19394
+ return;
19395
+ let signature = "missing";
19396
+ try {
19397
+ const info = statSync6(join26(options.homeDir, ".codex", ".codex-global-state.json"));
19398
+ signature = `${info.mtimeMs}:${info.ctimeMs}:${info.size}:${info.mode}`;
19399
+ } catch {
19400
+ }
19401
+ const unchanged = signature === codexProjectsSignature;
19402
+ if (unchanged && codexProjects !== void 0)
19403
+ return;
19404
+ codexProjectsSignature = signature;
19405
+ codexProjects = readCodexProjects(options.homeDir);
19406
+ if (unchanged && codexProjects === void 0)
19407
+ return;
19408
+ codexRootResolutions.clear();
19409
+ for (const project of Object.values(codexProjects?.projects ?? {})) {
19410
+ for (const root of project.rootPaths) {
19411
+ void resolveProjectRoot(root, {
19412
+ homeDir: options.homeDir,
19413
+ maxDirectories: 1,
19414
+ ...options.projectBoundaryDir === void 0 ? {} : { boundaryDir: options.projectBoundaryDir }
19415
+ }).then((resolution) => {
19416
+ if (closed || signature !== codexProjectsSignature)
19417
+ return;
19418
+ codexRootResolutions.set(root, resolution);
19419
+ watchResolution(resolution);
19420
+ notify("codex");
19421
+ });
19422
+ }
19423
+ }
19424
+ notify("codex");
19425
+ }
19198
19426
  function notify(harness) {
19199
19427
  pendingNotifications.add(harness);
19200
19428
  if (notificationQueued)
@@ -19255,7 +19483,7 @@ function createNarrativeService(options = {}) {
19255
19483
  session.subagentTimer = void 0;
19256
19484
  }
19257
19485
  function anchorCwd(harness, session, cwd) {
19258
- if (session.cwd !== void 0)
19486
+ if (session.cwd !== void 0 || cwd.trim() === "")
19259
19487
  return;
19260
19488
  session.cwd = cwd;
19261
19489
  if (options.homeDir === void 0)
@@ -19570,6 +19798,9 @@ function createNarrativeService(options = {}) {
19570
19798
  if (harness === "codex") {
19571
19799
  const parsed = parseCodexRolloutLine(line);
19572
19800
  session.codexLines.push(parsed);
19801
+ if ((parsed.kind === "session_meta" && parsed.parentThreadId === void 0 || parsed.kind === "turn_context") && parsed.cwd !== void 0) {
19802
+ anchorCwd(harness, session, parsed.cwd);
19803
+ }
19573
19804
  if (parsed.kind !== "unknown")
19574
19805
  timestamp = parsed.timestamp;
19575
19806
  } else {
@@ -19640,13 +19871,14 @@ function createNarrativeService(options = {}) {
19640
19871
  }
19641
19872
  if (name === "UserPromptSubmit") {
19642
19873
  const prompt = typeof payload.prompt === "string" ? payload.prompt.trim() : void 0;
19874
+ const displayPrompt = prompt === void 0 ? void 0 : userRequestText(prompt);
19643
19875
  if (prompt === void 0 || prompt !== "" && !isHarnessSystemNotice(prompt)) {
19644
19876
  session.hookInstructions.push({
19645
19877
  at: event.received_at,
19646
19878
  ...prompt === void 0 ? {} : { text: prompt }
19647
19879
  });
19648
- if (prompt !== void 0) {
19649
- session.hookPrompt = truncate(prompt, DETAIL_LIMIT);
19880
+ if (displayPrompt !== void 0 && displayPrompt !== "") {
19881
+ session.hookPrompt = truncate(displayPrompt, DETAIL_LIMIT);
19650
19882
  session.hookPromptAt = event.received_at;
19651
19883
  }
19652
19884
  }
@@ -19676,6 +19908,7 @@ function createNarrativeService(options = {}) {
19676
19908
  const signal = waitingSignal(payload);
19677
19909
  if (signal !== null) {
19678
19910
  const { kind } = signal;
19911
+ session.feedbackRequestAt = event.received_at;
19679
19912
  if (session.waiting === null) {
19680
19913
  session.waiting = {
19681
19914
  kind,
@@ -19712,7 +19945,8 @@ function createNarrativeService(options = {}) {
19712
19945
  return waiting.message;
19713
19946
  },
19714
19947
  until: event.received_at,
19715
- resolvedBy: name
19948
+ resolvedBy: name,
19949
+ ...session.feedbackRequestAt === void 0 ? {} : { requestAt: session.feedbackRequestAt }
19716
19950
  });
19717
19951
  session.waiting = null;
19718
19952
  }
@@ -19792,15 +20026,17 @@ function createNarrativeService(options = {}) {
19792
20026
  session.dirty = true;
19793
20027
  notify(harness);
19794
20028
  }
19795
- function deriveCached(harness, session, configuredPlugins) {
20029
+ function deriveCached(harness, session, configuredPlugins, configuredMcpServers) {
19796
20030
  const pluginKey = JSON.stringify(configuredPlugins);
19797
- if (!session.dirty && session.cached !== void 0 && session.cachedLocale === getLocale() && session.cachedCodexPlugins === pluginKey) {
20031
+ const mcpKey = JSON.stringify(configuredMcpServers);
20032
+ if (!session.dirty && session.cached !== void 0 && session.cachedLocale === getLocale() && session.cachedCodexPlugins === pluginKey && session.cachedCcMcpServers === mcpKey) {
19798
20033
  return session.cached;
19799
20034
  }
19800
- session.cached = derive(harness, session, now().toISOString(), configuredPlugins);
20035
+ session.cached = derive(harness, session, now().toISOString(), configuredPlugins, configuredMcpServers);
19801
20036
  session.dirty = false;
19802
20037
  session.cachedLocale = getLocale();
19803
20038
  session.cachedCodexPlugins = pluginKey;
20039
+ session.cachedCcMcpServers = mcpKey;
19804
20040
  return session.cached;
19805
20041
  }
19806
20042
  function getOverview(harness) {
@@ -19813,6 +20049,13 @@ function createNarrativeService(options = {}) {
19813
20049
  } catch {
19814
20050
  configuredPlugins = [];
19815
20051
  }
20052
+ let configuredMcpServers = [];
20053
+ try {
20054
+ if (harness === "cc")
20055
+ configuredMcpServers = ccMcpServersProvider?.() ?? [];
20056
+ } catch {
20057
+ configuredMcpServers = [];
20058
+ }
19816
20059
  const overlay = options.homeDir === void 0 ? void 0 : readTaskOverlay(options.homeDir);
19817
20060
  const overlayEntries = overlay === void 0 || "unavailable" in overlay ? {} : overlay.entries;
19818
20061
  let feedback;
@@ -19829,7 +20072,7 @@ function createNarrativeService(options = {}) {
19829
20072
  label: session.projectResolution?.isHome ? t("narrative.homeDirectory") : session.label ?? shortSessionId(session.id),
19830
20073
  ...session.cwd === void 0 ? {} : { cwd: session.cwd },
19831
20074
  lastActivity,
19832
- waiting: session.waiting !== null,
20075
+ waiting: deriveCached(harness, session, configuredPlugins, configuredMcpServers).waiting !== null,
19833
20076
  ended: isEnded(session, nowIso),
19834
20077
  archived: user?.archived === true,
19835
20078
  archivedHasNewActivity: user?.archived === true && user.archivedAt !== void 0 && Date.parse(lastActivity) > Date.parse(user.archivedAt),
@@ -19838,13 +20081,13 @@ function createNarrativeService(options = {}) {
19838
20081
  }).sort((a, b) => a.lastActivity < b.lastActivity ? 1 : a.lastActivity > b.lastActivity ? -1 : 0);
19839
20082
  const states = {};
19840
20083
  for (const [id, session] of sessions) {
19841
- const state = deriveCached(harness, session, configuredPlugins);
20084
+ const state = deriveCached(harness, session, configuredPlugins, configuredMcpServers);
19842
20085
  const verification = state.taskWorkflow?.verification;
19843
20086
  states[id] = state.taskWorkflow === void 0 ? state : {
19844
20087
  ...state,
19845
20088
  taskWorkflow: {
19846
20089
  ...state.taskWorkflow,
19847
- feedback: feedbackView(harness, feedback, session.feedbackState),
20090
+ feedback: feedbackView(harness, feedback, humanFeedbackState(harness, session)),
19848
20091
  ...verification === void 0 ? {} : {
19849
20092
  verification: {
19850
20093
  ...verification,
@@ -19934,37 +20177,94 @@ function createNarrativeService(options = {}) {
19934
20177
  };
19935
20178
  }
19936
20179
  function getProjects() {
20180
+ refreshCodexProjects();
19937
20181
  const overlay = options.homeDir === void 0 ? void 0 : readTaskOverlay(options.homeDir);
19938
20182
  const overlayEntries = overlay === void 0 || "unavailable" in overlay ? {} : overlay.entries;
19939
20183
  const grouped = /* @__PURE__ */ new Map();
20184
+ const cards = /* @__PURE__ */ new Map();
20185
+ const codexNamesByRoot = /* @__PURE__ */ new Map();
19940
20186
  for (const [rootIdentity, resolution] of rememberedProjectRoots) {
19941
- grouped.set(rootIdentity, { resolution, members: [] });
20187
+ grouped.set(rootIdentity, { rootIdentity, resolution, members: [] });
19942
20188
  }
19943
20189
  for (const [harness, sessions] of harnesses) {
19944
20190
  for (const session of sessions.values()) {
19945
20191
  if (session.cwd === void 0)
19946
20192
  continue;
19947
- const rootIdentity = session.projectResolution?.rootIdentity ?? resolve12(session.cwd);
19948
- const group = grouped.get(rootIdentity);
20193
+ let rootIdentity = session.projectResolution?.rootIdentity ?? resolve12(session.cwd);
20194
+ let resolution = session.projectResolution;
20195
+ let cardId;
20196
+ if (harness === "codex" && codexProjects !== void 0) {
20197
+ const meta = session.codexLines.find((line) => line.kind === "session_meta" && line.parentThreadId === void 0);
20198
+ const threadId = meta?.kind === "session_meta" ? meta.threadId : void 0;
20199
+ const assignment = codexProjects.assignments[threadId ?? session.id];
20200
+ const cwd = codexPathIdentity(session.cwd);
20201
+ const matching = Object.values(codexProjects.projects).flatMap((project2) => project2.rootPaths.map((root) => ({ project: project2, root }))).filter(({ root }) => isPathWithin(root, cwd)).sort((left, right) => right.root.length - left.root.length)[0];
20202
+ const project = assignment === void 0 ? matching?.project : codexProjects.projects[assignment];
20203
+ if (assignment === void 0 || project !== void 0) {
20204
+ cardId = project === void 0 ? "codex-ungrouped" : `codex-project:${project.id}`;
20205
+ let card = cards.get(cardId);
20206
+ if (card === void 0) {
20207
+ card = {
20208
+ kind: project === void 0 ? "codex-ungrouped" : "codex-project",
20209
+ id: project?.id ?? "codex-ungrouped",
20210
+ name: project?.name ?? t("narrative.codexUngrouped"),
20211
+ roots: [...new Set(project?.rootPaths ?? [])]
20212
+ };
20213
+ cards.set(cardId, card);
20214
+ for (const root of card.roots) {
20215
+ grouped.set(JSON.stringify([cardId, root]), {
20216
+ rootIdentity: root,
20217
+ resolution: codexRootResolutions.get(root),
20218
+ members: [],
20219
+ cardId
20220
+ });
20221
+ }
20222
+ }
20223
+ const configuredRoot = project?.rootPaths.filter((root) => isPathWithin(root, cwd)).sort((left, right) => right.length - left.length)[0];
20224
+ if (configuredRoot !== void 0 && !(resolution?.planPath !== void 0 && resolution.rootIdentity !== configuredRoot)) {
20225
+ rootIdentity = configuredRoot;
20226
+ resolution = codexRootResolutions.get(configuredRoot) ?? (session.projectResolution?.rootIdentity === configuredRoot ? session.projectResolution : void 0);
20227
+ }
20228
+ if (!card.roots.includes(rootIdentity))
20229
+ card.roots.push(rootIdentity);
20230
+ }
20231
+ }
20232
+ const key = cardId === void 0 ? rootIdentity : JSON.stringify([cardId, rootIdentity]);
20233
+ const group = grouped.get(key);
19949
20234
  if (group === void 0) {
19950
- grouped.set(rootIdentity, {
19951
- resolution: session.projectResolution,
19952
- members: [{ harness, session }]
20235
+ grouped.set(key, {
20236
+ rootIdentity,
20237
+ resolution,
20238
+ members: [{ harness, session }],
20239
+ ...cardId === void 0 ? {} : { cardId }
19953
20240
  });
19954
20241
  } else {
19955
- group.resolution ??= session.projectResolution;
20242
+ group.resolution ??= resolution;
19956
20243
  group.members.push({ harness, session });
19957
20244
  }
19958
20245
  }
19959
20246
  }
20247
+ for (const card of cards.values()) {
20248
+ if (card.kind !== "codex-project")
20249
+ continue;
20250
+ for (const root of card.roots) {
20251
+ const names = codexNamesByRoot.get(root) ?? /* @__PURE__ */ new Set();
20252
+ names.add(card.name);
20253
+ codexNamesByRoot.set(root, names);
20254
+ }
20255
+ }
19960
20256
  const overviews = /* @__PURE__ */ new Map();
19961
20257
  for (const harness of harnesses.keys())
19962
20258
  overviews.set(harness, getOverview(harness));
19963
20259
  const projects = [];
19964
- for (const [rootIdentity, group] of grouped) {
20260
+ const cardRoots = /* @__PURE__ */ new Map();
20261
+ for (const group of grouped.values()) {
20262
+ const { rootIdentity } = group;
19965
20263
  const { members } = group;
19966
- const resolution = members.find((member) => member.session.projectResolution !== void 0)?.session.projectResolution ?? group.resolution;
19967
- const root = resolution?.root ?? resolve12(members[0]?.session.cwd ?? "");
20264
+ if (group.cardId === void 0 && members.length === 0 && [...cards.values()].some((card) => card.roots.includes(rootIdentity)))
20265
+ continue;
20266
+ const resolution = group.resolution;
20267
+ const root = resolution?.root ?? (group.cardId === void 0 ? resolve12(members[0]?.session.cwd ?? rootIdentity) : rootIdentity);
19968
20268
  const planPath = resolution?.planPath ?? join26(root, ".wingman", "plan.md");
19969
20269
  const runtime = projectFiles.get(resolution?.planPathIdentity ?? planPath);
19970
20270
  if (runtime?.current !== void 0 && runtime.readFailureKey === void 0 && runtime.parsedLocale !== getLocale()) {
@@ -20078,7 +20378,7 @@ function createNarrativeService(options = {}) {
20078
20378
  const projectUser = overlayEntries[`project:${root}`];
20079
20379
  const firstScreen = deriveProjectFirstScreen(plan, parsed?.availability === "available" ? parsed.goal : void 0, summary.currentPoints, sessionViews);
20080
20380
  const archivedHasNewActivity = projectUser?.archived === true && projectUser.archivedAt !== void 0 && firstScreen.lastActivity !== void 0 && Date.parse(firstScreen.lastActivity.at) > Date.parse(projectUser.archivedAt);
20081
- projects.push({
20381
+ const projectView = {
20082
20382
  firstScreen,
20083
20383
  root,
20084
20384
  ...resolution === void 0 ? {} : { isHome: resolution.isHome === true },
@@ -20111,6 +20411,48 @@ function createNarrativeService(options = {}) {
20111
20411
  facts: reconciliation,
20112
20412
  protocol,
20113
20413
  sessions: sessionViews
20414
+ };
20415
+ if (group.cardId === void 0) {
20416
+ const names = codexNamesByRoot.get(rootIdentity);
20417
+ if (names !== void 0)
20418
+ projectView.codexProjectNames = [...names];
20419
+ projects.push(projectView);
20420
+ } else {
20421
+ const roots = cardRoots.get(group.cardId) ?? [];
20422
+ roots.push(projectView);
20423
+ cardRoots.set(group.cardId, roots);
20424
+ }
20425
+ }
20426
+ for (const [cardId, group] of cards) {
20427
+ const rootProjects = cardRoots.get(cardId) ?? [];
20428
+ const selected = [...rootProjects].sort((left, right) => Number(left.user?.archived === true) - Number(right.user?.archived === true) || projectAttention(right) - projectAttention(left))[0];
20429
+ if (selected === void 0)
20430
+ continue;
20431
+ const order = codexProjects?.order.indexOf(group.id) ?? -1;
20432
+ const users = rootProjects.map((project) => project.user);
20433
+ const archivedAt = users.map((user) => user?.archivedAt).filter((at) => at !== void 0).sort()[0];
20434
+ const orders = users.map((user) => user?.order).filter((value) => value !== void 0);
20435
+ projects.push({
20436
+ ...selected,
20437
+ root: cardId,
20438
+ group: { ...group, roots: rootProjects.map((project) => project.root) },
20439
+ rootProjects,
20440
+ ...order < 0 ? {} : { codexOrder: order },
20441
+ title: {
20442
+ text: group.name,
20443
+ source: group.kind === "codex-project" ? "codexProject" : "codexUngrouped"
20444
+ },
20445
+ sessions: rootProjects.flatMap((project) => project.sessions),
20446
+ presence: rootProjects.some((project) => project.presence === "active") ? "active" : "remembered",
20447
+ seenSinceStart: rootProjects.some((project) => project.seenSinceStart),
20448
+ archivedHasNewActivity: rootProjects.some((project) => project.archivedHasNewActivity),
20449
+ user: {
20450
+ pinned: users.every((user) => user?.pinned === true),
20451
+ hidden: users.every((user) => user?.hidden === true),
20452
+ archived: users.every((user) => user?.archived === true),
20453
+ ...archivedAt === void 0 ? {} : { archivedAt },
20454
+ ...orders.length === 0 ? {} : { order: Math.min(...orders) }
20455
+ }
20114
20456
  });
20115
20457
  }
20116
20458
  projects.sort((left, right) => {
@@ -20121,6 +20463,15 @@ function createNarrativeService(options = {}) {
20121
20463
  const activityOrder = (right.firstScreen.lastActivity === void 0 ? 0 : Date.parse(right.firstScreen.lastActivity.at)) - (left.firstScreen.lastActivity === void 0 ? 0 : Date.parse(left.firstScreen.lastActivity.at));
20122
20464
  return decisionOrder || activityOrder || left.root.localeCompare(right.root);
20123
20465
  });
20466
+ for (const archived of [false, true]) {
20467
+ const positions = projects.flatMap((project, index) => project.group?.kind === "codex-project" && project.user?.archived === true === archived ? [index] : []);
20468
+ const ordered = positions.map((index) => projects[index]).filter((project) => project !== void 0).sort((left, right) => (left.codexOrder ?? Number.MAX_SAFE_INTEGER) - (right.codexOrder ?? Number.MAX_SAFE_INTEGER));
20469
+ positions.forEach((index, position) => {
20470
+ const project = ordered[position];
20471
+ if (project !== void 0)
20472
+ projects[index] = project;
20473
+ });
20474
+ }
20124
20475
  return {
20125
20476
  projects,
20126
20477
  ...projectMemoryUnavailable === void 0 ? {} : { memory: { unavailable: projectMemoryUnavailable() } }
@@ -20158,6 +20509,9 @@ function createNarrativeService(options = {}) {
20158
20509
  setCodexPluginsProvider(provider) {
20159
20510
  codexPluginsProvider = provider;
20160
20511
  },
20512
+ setCcMcpServersProvider(provider) {
20513
+ ccMcpServersProvider = provider;
20514
+ },
20161
20515
  handleEvent,
20162
20516
  getState,
20163
20517
  getOverview,
@@ -20166,9 +20520,39 @@ function createNarrativeService(options = {}) {
20166
20520
  subscribe,
20167
20521
  refreshLocale,
20168
20522
  refreshOverlay,
20523
+ refreshCodexProjects,
20169
20524
  close
20170
20525
  };
20171
20526
  }
20527
+ function codexPathIdentity(path) {
20528
+ try {
20529
+ return realpathSync3(path);
20530
+ } catch {
20531
+ return resolve12(path);
20532
+ }
20533
+ }
20534
+ function isPathWithin(root, cwd) {
20535
+ const path = relative4(root, cwd);
20536
+ return path === "" || path !== ".." && !path.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) && !isAbsolute6(path);
20537
+ }
20538
+ function projectAttention(project) {
20539
+ if (project.sessions.some((session) => session.waiting))
20540
+ return 4;
20541
+ if (project.firstScreen.action.kind === "insufficient" && project.sessions.some((session) => !session.ended))
20542
+ return 2;
20543
+ switch (project.firstScreen.action.kind) {
20544
+ case "decision":
20545
+ return 4;
20546
+ case "checkpoint":
20547
+ return 3;
20548
+ case "in_progress":
20549
+ return 2;
20550
+ case "ended":
20551
+ return 1;
20552
+ case "insufficient":
20553
+ return 0;
20554
+ }
20555
+ }
20172
20556
  function deriveProjectFirstScreen(plan, goal, points, sessions) {
20173
20557
  const source = ".wingman/plan.md nodes(status, children)";
20174
20558
  const currentPoints = points.map((point) => ({ ...point, source }));
@@ -20399,6 +20783,69 @@ function feedbackView(harness, capability, state) {
20399
20783
  }
20400
20784
  return state ?? { state: "no_open_request", source: `${harness} explicit feedback signals` };
20401
20785
  }
20786
+ function codexAutomaticReviewAt(lines2, at) {
20787
+ const requestTime = Date.parse(at);
20788
+ if (!Number.isFinite(requestTime))
20789
+ return false;
20790
+ let reviewer;
20791
+ let turnId;
20792
+ for (const line of sortedCodexByTimestamp(lines2)) {
20793
+ if (line.kind === "unknown")
20794
+ continue;
20795
+ const time = Date.parse(line.timestamp ?? "");
20796
+ if (!Number.isFinite(time)) {
20797
+ if (line.kind === "turn_context" || line.kind === "task_started")
20798
+ reviewer = void 0;
20799
+ continue;
20800
+ }
20801
+ if (time > requestTime)
20802
+ continue;
20803
+ if (line.kind === "task_started") {
20804
+ reviewer = void 0;
20805
+ turnId = line.turnId;
20806
+ } else if (line.kind === "task_complete" || line.kind === "turn_aborted") {
20807
+ reviewer = void 0;
20808
+ turnId = void 0;
20809
+ } else if (line.kind === "turn_context") {
20810
+ reviewer = turnId !== void 0 && line.turnId !== turnId ? void 0 : line.approvalsReviewer;
20811
+ }
20812
+ }
20813
+ return reviewer === "auto_review";
20814
+ }
20815
+ function humanFeedbackState(harness, session) {
20816
+ const state = session.feedbackState;
20817
+ if (harness !== "codex" || state?.source !== "codex PermissionRequest signal")
20818
+ return state;
20819
+ const since = state.state === "needs_user" ? state.since : state.requestSince;
20820
+ const at = session.feedbackRequestAt ?? since;
20821
+ if (codexAutomaticReviewAt(session.codexLines, at))
20822
+ return void 0;
20823
+ if (!codexAutomaticReviewAt(session.codexLines, since))
20824
+ return state;
20825
+ return state.state === "needs_user" ? { ...state, since: at } : { ...state, requestSince: at };
20826
+ }
20827
+ function humanWaiting(harness, lines2, wait, at = wait.since) {
20828
+ if (harness !== "codex" || wait.kind !== "permission")
20829
+ return wait;
20830
+ if (codexAutomaticReviewAt(lines2, at))
20831
+ return null;
20832
+ return codexAutomaticReviewAt(lines2, wait.since) ? { ...wait, since: at } : wait;
20833
+ }
20834
+ function observedMcpServers(lines2, configuredServers) {
20835
+ const names = /* @__PURE__ */ new Set();
20836
+ for (const line of lines2) {
20837
+ if (line.kind !== "assistant")
20838
+ continue;
20839
+ for (const block of line.blocks) {
20840
+ if (block.kind !== "tool_use")
20841
+ continue;
20842
+ const server = recognizeMcpTool(block.name, configuredServers);
20843
+ if (server !== void 0)
20844
+ names.add(server);
20845
+ }
20846
+ }
20847
+ return [...names];
20848
+ }
20402
20849
  function observedPlugins(lines2, configuredPlugins) {
20403
20850
  const names = /* @__PURE__ */ new Set();
20404
20851
  for (const line of lines2) {
@@ -20445,8 +20892,10 @@ function observedSkills(lines2) {
20445
20892
  }
20446
20893
  return [...names];
20447
20894
  }
20448
- function derive(harness, session, nowIso, configuredPlugins) {
20895
+ function derive(harness, session, nowIso, configuredPlugins, configuredMcpServers) {
20449
20896
  const codexLines = sortedCodexByTimestamp(session.codexLines);
20897
+ const waiting = session.waiting === null ? null : humanWaiting(harness, codexLines, session.waiting, session.feedbackRequestAt);
20898
+ const waitEpisodes = session.waitEpisodes.map((wait) => humanWaiting(harness, codexLines, wait, wait.requestAt)).filter((wait) => wait !== null);
20450
20899
  const lines2 = harness === "codex" ? adaptCodexNarrativeLines(codexLines) : sortedByTimestamp(session.lines);
20451
20900
  const timeline = deriveTodoTimeline(extractTodoSnapshots(lines2));
20452
20901
  const allSteps = extractSteps(lines2);
@@ -20496,10 +20945,10 @@ function derive(harness, session, nowIso, configuredPlugins) {
20496
20945
  else
20497
20946
  waitNodes.set(key, [node]);
20498
20947
  };
20499
- for (const episode of session.waitEpisodes)
20948
+ for (const episode of waitEpisodes)
20500
20949
  pushWait(episode, false);
20501
- if (session.waiting !== null)
20502
- pushWait(session.waiting, true);
20950
+ if (waiting !== null)
20951
+ pushWait(waiting, true);
20503
20952
  const traces = [];
20504
20953
  const agentsByTodo = /* @__PURE__ */ new Map();
20505
20954
  const orderedKeys = timeline.map((entry) => entry.id).filter((id) => buckets.has(id) || waitNodes.has(id));
@@ -20558,7 +21007,7 @@ function derive(harness, session, nowIso, configuredPlugins) {
20558
21007
  },
20559
21008
  execution: {
20560
21009
  ...workflowAction === void 0 ? {} : { currentAction: workflowAction },
20561
- evidenceCount: steps.length + session.waitEpisodes.length + (session.waiting === null ? 0 : 1),
21010
+ evidenceCount: steps.length + waitEpisodes.length + (waiting === null ? 0 : 1),
20562
21011
  failureCount: steps.filter((step) => step.isError).length
20563
21012
  },
20564
21013
  feedback: unavailableFeedback({ key: "narrative.feedbackUnmapped" })
@@ -20589,12 +21038,14 @@ function derive(harness, session, nowIso, configuredPlugins) {
20589
21038
  }
20590
21039
  };
20591
21040
  const skillsUsed = harness === "cc" ? observedSkills(lines2) : [];
21041
+ const mcpUsed = harness === "cc" ? observedMcpServers(lines2, configuredMcpServers) : [];
20592
21042
  const pluginsUsed = harness === "codex" ? observedPlugins(codexLines, configuredPlugins) : [];
20593
21043
  return {
20594
21044
  harness,
20595
21045
  sessionId: session.id,
20596
21046
  transcriptPath: session.transcriptPath ?? null,
20597
21047
  ...skillsUsed.length === 0 ? {} : { skillsUsed },
21048
+ ...mcpUsed.length === 0 ? {} : { mcpUsed },
20598
21049
  ...pluginsUsed.length === 0 ? {} : { pluginsUsed },
20599
21050
  ...session.cwd === void 0 ? {} : { cwd: session.cwd },
20600
21051
  ...session.cwd === void 0 ? {} : {
@@ -20609,7 +21060,7 @@ function derive(harness, session, nowIso, configuredPlugins) {
20609
21060
  traces,
20610
21061
  turnUsages: harness === "codex" ? deriveCodexTurnUsages(codexLines) : deriveTurnUsages(lines2),
20611
21062
  currentAction,
20612
- waiting: session.waiting,
21063
+ waiting,
20613
21064
  agentQuote: deriveAgentQuote(lines2),
20614
21065
  // transcript 是会话事实源;hook prompt 只在 tail 尚未读到/格式暂不可读时兜底。
20615
21066
  lastPrompt,
@@ -21136,15 +21587,15 @@ function deriveAgentQuote(lines2) {
21136
21587
  return null;
21137
21588
  }
21138
21589
  function deriveLastPrompt(lines2, hookPrompt, hookPromptAt) {
21139
- const usableHookPrompt = hookPrompt === void 0 || isHarnessSystemNotice(hookPrompt) ? void 0 : hookPrompt;
21590
+ const usableHookPrompt = hookPrompt;
21140
21591
  for (let i = lines2.length - 1; i >= 0; i--) {
21141
21592
  const line = lines2[i];
21142
21593
  if (line === void 0 || line.kind !== "user" || line.agentId !== void 0)
21143
21594
  continue;
21144
21595
  if (line.toolResults.length > 0)
21145
21596
  continue;
21146
- const text = line.text?.trim();
21147
- if (text === void 0 || text === "" || isHarnessSystemNotice(text))
21597
+ const text = line.text === void 0 ? void 0 : userRequestText(line.text);
21598
+ if (text === void 0 || text === "")
21148
21599
  continue;
21149
21600
  if (usableHookPrompt !== void 0 && hookPromptAt !== void 0 && line.timestamp !== void 0 && hookPromptAt > line.timestamp) {
21150
21601
  return usableHookPrompt;
@@ -21397,7 +21848,7 @@ async function loadHarness(harness, mode) {
21397
21848
  // apps/cli/dist/return-target.js
21398
21849
  init_dist();
21399
21850
  import { randomBytes as randomBytes4 } from "node:crypto";
21400
- import { closeSync as closeSync3, copyFileSync as copyFileSync3, mkdirSync as mkdirSync12, openSync as openSync3, readFileSync as readFileSync18, renameSync as renameSync5, rmSync as rmSync10, statSync as statSync6, writeFileSync as writeFileSync13 } from "node:fs";
21851
+ import { closeSync as closeSync3, copyFileSync as copyFileSync3, mkdirSync as mkdirSync12, openSync as openSync3, readFileSync as readFileSync18, renameSync as renameSync5, rmSync as rmSync10, statSync as statSync7, writeFileSync as writeFileSync13 } from "node:fs";
21401
21852
  import { dirname as dirname18, join as join27, resolve as resolve13 } from "node:path";
21402
21853
  function isIslandSetting(value) {
21403
21854
  return isRecord8(value) && Object.keys(value).every((key) => ["edge", "offset", "screen", "size"].includes(key)) && ["top", "bottom", "left", "right"].includes(value.edge) && typeof value.offset === "number" && Number.isFinite(value.offset) && value.offset >= 0 && value.offset <= 1 && (value.screen === void 0 || typeof value.screen === "string") && (value.size === "compact" || value.size === "standard");
@@ -21418,7 +21869,7 @@ function detectReturnTargets(homeDir, roots = ["/Applications", join27(homeDir,
21418
21869
  for (const root of new Set(roots.map((root2) => resolve13(root2)))) {
21419
21870
  const bundlePath = join27(root, bundle);
21420
21871
  try {
21421
- if (statSync6(bundlePath).isDirectory())
21872
+ if (statSync7(bundlePath).isDirectory())
21422
21873
  available.push({ name, bundlePath });
21423
21874
  } catch {
21424
21875
  }
@@ -21623,7 +22074,7 @@ import { createHmac, timingSafeEqual } from "node:crypto";
21623
22074
  import { readFile as readFile4 } from "node:fs/promises";
21624
22075
  import { createServer } from "node:http";
21625
22076
  import { hostname } from "node:os";
21626
- import { extname, relative as relative4, resolve as resolve14, sep as sep2 } from "node:path";
22077
+ import { extname, relative as relative5, resolve as resolve14, sep as sep2 } from "node:path";
21627
22078
 
21628
22079
  // apps/cli/dist/suggest.js
21629
22080
  init_dist2();
@@ -21813,6 +22264,7 @@ function createWingmanServer(options) {
21813
22264
  const warn = options.warn ?? ((message) => console.error(message));
21814
22265
  const runtime = { anatomy: null };
21815
22266
  options.narrative?.setCodexPluginsProvider(() => runtime.anatomy?.configs.find((config) => config.harness === "codex")?.slots.skills.filter((item) => item.nativeName.startsWith("plugins.")).map((item) => item.nativeName.slice("plugins.".length)) ?? []);
22267
+ options.narrative?.setCcMcpServersProvider(() => runtime.anatomy?.configs.find((config) => config.harness === "cc")?.slots.tools.filter((item) => item.nativeName.startsWith("mcpServers.")).map((item) => item.nativeName.slice("mcpServers.".length)) ?? []);
21816
22268
  return createServer({ requireHostHeader: false }, (req, res) => {
21817
22269
  handle(req, res, options, warn, runtime).catch((error) => {
21818
22270
  warn(t("cli.server.requestFailed", { error: errorMessage3(error) }));
@@ -21949,7 +22401,7 @@ async function handle(req, res, options, warn, runtime) {
21949
22401
  });
21950
22402
  return;
21951
22403
  }
21952
- if (harness === "codex")
22404
+ if (harness === "codex" || harness === "cc")
21953
22405
  await cachedAnatomy(options, warn, runtime);
21954
22406
  const overview = options.narrative.getOverview(harness);
21955
22407
  if (overview.sessions.length > 0) {
@@ -21967,6 +22419,7 @@ async function handle(req, res, options, warn, runtime) {
21967
22419
  }
21968
22420
  if (url.pathname === "/api/anatomy") {
21969
22421
  const configs = await scanAll(options.harnesses, warn);
22422
+ options.narrative?.refreshCodexProjects();
21970
22423
  runtime.anatomy = { at: Date.now(), configs };
21971
22424
  const anatomy = configs.map((config) => {
21972
22425
  const scanOptions = options.harnesses.find((entry) => entry.harness === config.harness)?.scanOptions;
@@ -22213,7 +22666,7 @@ function handleProtocolUserAction(body, res, options, runtime) {
22213
22666
  sendJson2(res, 200, {
22214
22667
  ok: true,
22215
22668
  planProtocol: { user },
22216
- ...result5.backupDir === void 0 ? {} : { backupDir: `~/${relative4(homeDir, result5.backupDir).split(sep2).join("/")}` }
22669
+ ...result5.backupDir === void 0 ? {} : { backupDir: `~/${relative5(homeDir, result5.backupDir).split(sep2).join("/")}` }
22217
22670
  });
22218
22671
  }
22219
22672
  } catch (error) {