maka-agent 0.2.0-dev.24.20260907 → 0.2.0-dev.25.20260908

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.
Files changed (105) hide show
  1. package/README.md +38 -19
  2. package/README.zh-CN.md +34 -19
  3. package/dist/pi-transcript-tools.js +6 -0
  4. package/dist/pi-tui-layout.js +56 -10
  5. package/dist/pi-tui-pickers.js +102 -1
  6. package/dist/pi-tui-runner.js +156 -42
  7. package/dist/pi-tui-todo.js +221 -0
  8. package/dist/pi-tui-transcript-viewer.js +134 -7
  9. package/dist/runtime-host-cli-context.js +70 -13
  10. package/dist/runtime-host-handoff-surface.js +51 -26
  11. package/dist/runtime-host-local-handoff.js +11 -1
  12. package/dist/runtime-host-service-manager.js +0 -3
  13. package/dist/runtime-host-session-channel.js +13 -0
  14. package/dist/runtime-host-session-driver.js +42 -1
  15. package/dist/tui-copy-catalog.js +79 -3
  16. package/native/runtime-host-windows-task-launcher/prebuilds/win32-x64/maka-runtime-host-task-launcher.exe +0 -0
  17. package/node_modules/@maka/core/dist/agent-run.js +1 -0
  18. package/node_modules/@maka/core/dist/attachments.js +3 -0
  19. package/node_modules/@maka/core/dist/canonical-json.js +27 -0
  20. package/node_modules/@maka/core/dist/capabilities.js +35 -0
  21. package/node_modules/@maka/core/dist/computer-use.js +0 -1
  22. package/node_modules/@maka/core/dist/display-redaction.js +18 -0
  23. package/node_modules/@maka/core/dist/llm-connections.js +13 -0
  24. package/node_modules/@maka/core/dist/model-call-attempt.js +2 -0
  25. package/node_modules/@maka/core/dist/model-metadata.js +4 -0
  26. package/node_modules/@maka/core/dist/redaction.js +35 -0
  27. package/node_modules/@maka/core/dist/run-composition.js +77 -2
  28. package/node_modules/@maka/core/dist/session.js +30 -4
  29. package/node_modules/@maka/core/dist/slash-command-catalog.js +1 -0
  30. package/node_modules/@maka/core/dist/tool-result-record-schema.js +2 -1
  31. package/node_modules/@maka/core/package.json +1 -0
  32. package/node_modules/@maka/eval/dist/experiment-directory.js +4 -13
  33. package/node_modules/@maka/runtime/dist/agent-run-inspect.js +0 -13
  34. package/node_modules/@maka/runtime/dist/agent-run.js +80 -1
  35. package/node_modules/@maka/runtime/dist/ai-sdk-backend.js +16 -8
  36. package/node_modules/@maka/runtime/dist/ai-sdk-turn.js +57 -50
  37. package/node_modules/@maka/runtime/dist/archive-read-tool.js +2 -2
  38. package/node_modules/@maka/runtime/dist/context-budget-helpers.js +0 -16
  39. package/node_modules/@maka/runtime/dist/conversation-copy.js +153 -11
  40. package/node_modules/@maka/runtime/dist/github-copilot-oauth-enrollment.js +3 -3
  41. package/node_modules/@maka/runtime/dist/ledger-tool-result-archive-reader.js +69 -1
  42. package/node_modules/@maka/runtime/dist/mcp-tools.js +7 -2
  43. package/node_modules/@maka/runtime/dist/model-fetcher.js +42 -2
  44. package/node_modules/@maka/runtime/dist/model-history.js +0 -112
  45. package/node_modules/@maka/runtime/dist/plugin-runtime.js +20 -10
  46. package/node_modules/@maka/runtime/dist/plugin-tool-service.js +205 -0
  47. package/node_modules/@maka/runtime/dist/provider-request-telemetry.js +8 -1
  48. package/node_modules/@maka/runtime/dist/request-shape.js +23 -0
  49. package/node_modules/@maka/runtime/dist/runtime-event-backfill.js +1 -1
  50. package/node_modules/@maka/runtime/dist/runtime-event-read-model.js +4 -0
  51. package/node_modules/@maka/runtime/dist/runtime-kernel.js +7 -0
  52. package/node_modules/@maka/runtime/dist/stream-graph-coordinator.js +21 -0
  53. package/node_modules/@maka/runtime/dist/stream-graph-supervisor-tools.js +0 -5
  54. package/node_modules/@maka/runtime/dist/test-connection.js +0 -1
  55. package/node_modules/@maka/runtime/dist/tool-activation-identity.js +41 -0
  56. package/node_modules/@maka/runtime/dist/tool-availability.js +11 -1
  57. package/node_modules/@maka/runtime/dist/tool-result-archive-resource.js +63 -1
  58. package/node_modules/@maka/runtime/dist/tool-result-archive-transition.js +42 -12
  59. package/node_modules/@maka/runtime/dist/tool-result-archive.js +27 -4
  60. package/node_modules/@maka/runtime/package.json +1 -0
  61. package/node_modules/@maka/runtime-host/dist/client/host-handoff-copy.js +35 -12
  62. package/node_modules/@maka/runtime-host/dist/client/host-handoff.js +2 -0
  63. package/node_modules/@maka/runtime-host/dist/client/session-subscription.js +19 -0
  64. package/node_modules/@maka/runtime-host/dist/control/endpoint.js +1 -3
  65. package/node_modules/@maka/runtime-host/dist/node-error.js +22 -0
  66. package/node_modules/@maka/runtime-host/dist/operator/managed-deployment.js +1 -3
  67. package/node_modules/@maka/runtime-host/dist/peer-mesh/limits.js +0 -1
  68. package/node_modules/@maka/runtime-host/dist/peer-mesh/model.js +1 -1
  69. package/node_modules/@maka/runtime-host/dist/peer-reachability/publisher.js +1 -3
  70. package/node_modules/@maka/runtime-host/dist/protocol/index.js +5 -1
  71. package/node_modules/@maka/runtime-host/dist/protocol/plan.js +1 -0
  72. package/node_modules/@maka/runtime-host/dist/protocol/plugin-platform.js +27 -5
  73. package/node_modules/@maka/runtime-host/dist/protocol/project-catalog.js +2 -2
  74. package/node_modules/@maka/runtime-host/dist/protocol/workhub-coordination.js +31 -2
  75. package/node_modules/@maka/runtime-host/dist/server/agent-graph-coordinator.js +0 -3
  76. package/node_modules/@maka/runtime-host/dist/server/execution-artifacts.js +32 -32
  77. package/node_modules/@maka/runtime-host/dist/server/execution-composition.js +44 -9
  78. package/node_modules/@maka/runtime-host/dist/server/execution-model-composition.js +42 -14
  79. package/node_modules/@maka/runtime-host/dist/server/interactive-run-composer.js +47 -22
  80. package/node_modules/@maka/runtime-host/dist/server/plugin-platform-coordinator.js +6 -0
  81. package/node_modules/@maka/runtime-host/dist/server/plugin-platform.js +6 -0
  82. package/node_modules/@maka/runtime-host/dist/server/session-retirement-coordinator.js +5 -2
  83. package/node_modules/@maka/runtime-host/dist/server/session-revision-coordinator.js +4 -0
  84. package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-action-gate.js +20 -2
  85. package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-coordinator.js +13 -3
  86. package/node_modules/@maka/runtime-host/dist/server/workhub-message-attachments.js +46 -0
  87. package/node_modules/@maka/storage/dist/claude-code-session-adapter.js +0 -1
  88. package/node_modules/@maka/storage/dist/codex-session-adapter.js +284 -196
  89. package/node_modules/@maka/storage/dist/git-exec.js +61 -0
  90. package/node_modules/@maka/storage/dist/git-worktree-child-executor.js +8 -35
  91. package/node_modules/@maka/storage/dist/goal-authority.js +2 -2
  92. package/node_modules/@maka/storage/dist/interaction-store.js +2 -2
  93. package/node_modules/@maka/storage/dist/project-catalog.js +2 -23
  94. package/node_modules/@maka/storage/dist/runtime-event-invariants.js +2 -2
  95. package/node_modules/@maka/storage/dist/runtime-policy/connection-catalog-document.js +8 -3
  96. package/node_modules/@maka/storage/dist/scheduled-task-store.js +249 -283
  97. package/node_modules/@maka/storage/dist/session-bundle-manifest.js +5 -17
  98. package/node_modules/@maka/storage/dist/session-bundle-policy.js +2 -1
  99. package/node_modules/@maka/storage/dist/session-copy-cleanup.js +2 -1
  100. package/node_modules/@maka/storage/dist/sqlite-runtime-store.js +1 -2
  101. package/node_modules/@maka/storage/dist/storage-id.js +28 -0
  102. package/node_modules/@maka/storage/dist/tool-result-archive-evidence.js +31 -4
  103. package/node_modules/@maka/storage/dist/workspace-identity.js +2 -15
  104. package/node_modules/@maka/storage/dist/workspace-version-authority-internal.js +1 -8
  105. package/package.json +1 -1
@@ -17,6 +17,64 @@
17
17
  * under the License.
18
18
  */
19
19
  export const TUI_COPY_RESOURCES = {
20
+ todo: {
21
+ en: {
22
+ title: 'Current Todo',
23
+ markedComplete: 'marked complete',
24
+ open: '/todo to view',
25
+ usage: 'Usage: /todo',
26
+ progress: 'Todo',
27
+ unavailable: 'Todo unavailable',
28
+ empty: 'No Todo items',
29
+ loading: 'Loading Todo…',
30
+ hint: '↑↓/PgUp/PgDn scroll · Home/End · Esc close',
31
+ },
32
+ 'zh-CN': {
33
+ title: '当前待办',
34
+ markedComplete: '标记完成',
35
+ open: '/todo 查看',
36
+ usage: '用法:/todo',
37
+ progress: '待办',
38
+ unavailable: '待办不可用',
39
+ empty: '暂无待办',
40
+ loading: '正在加载待办…',
41
+ hint: '↑↓/PgUp/PgDn 滚动 · Home/End · Esc 关闭',
42
+ },
43
+ 'zh-TW': {
44
+ title: '目前待辦',
45
+ markedComplete: '標記完成',
46
+ open: '/todo 查看',
47
+ usage: '用法:/todo',
48
+ progress: '待辦',
49
+ unavailable: '待辦不可用',
50
+ empty: '沒有待辦',
51
+ loading: '正在載入待辦…',
52
+ hint: '↑↓/PgUp/PgDn 捲動 · Home/End · Esc 關閉',
53
+ },
54
+ },
55
+ 'transcript-reader': {
56
+ en: {
57
+ title: 'DETAILED TRANSCRIPT',
58
+ scope: 'loaded history',
59
+ hint: 'Esc/Ctrl+O close · Ctrl+E details · / search · ↑↓/PgUp/PgDn · Home/End',
60
+ matches: 'matches in displayed text',
61
+ back: 'return',
62
+ },
63
+ 'zh-CN': {
64
+ title: '详细记录',
65
+ scope: '已加载历史',
66
+ hint: 'Esc/Ctrl+O 返回 · Ctrl+E 详情 · / 搜索 · ↑↓/PgUp/PgDn · Home/End',
67
+ matches: '处匹配(当前显示内容)',
68
+ back: '回到原位置',
69
+ },
70
+ 'zh-TW': {
71
+ title: '詳細記錄',
72
+ scope: '已載入歷史',
73
+ hint: 'Esc/Ctrl+O 返回 · Ctrl+E 詳情 · / 搜尋 · ↑↓/PgUp/PgDn · Home/End',
74
+ matches: '處符合(目前顯示內容)',
75
+ back: '回到原位置',
76
+ },
77
+ },
20
78
  'host-owner': {
21
79
  en: {
22
80
  unavailable: 'Runtime Host owner controls are unavailable.',
@@ -566,6 +624,11 @@ export const TUI_COPY_RESOURCES = {
566
624
  modelSearchHint: 'Search models / providers / connections · ↑↓ select · Enter confirm · Esc cancel',
567
625
  searchLabel: 'Search',
568
626
  noMatchingModels: 'No matching models',
627
+ resumeSessionTitle: 'Resume Session',
628
+ sessionScopeCurrent: 'Current',
629
+ sessionScopeAll: 'All',
630
+ sessionSearchHint: 'Search name / id / path / model / connection · Tab scope · ↑↓ select · Enter open · Esc close',
631
+ noMatchingSessions: 'No matching sessions',
569
632
  selectPickerHint: '↑↓ select · Enter confirm · Esc close',
570
633
  providerConfigured: 'configured',
571
634
  addAccount: 'add account',
@@ -656,6 +719,11 @@ export const TUI_COPY_RESOURCES = {
656
719
  modelSearchHint: '搜索模型 / 服务商 / 连接 · ↑↓ 选择 · Enter 确认 · Esc 取消',
657
720
  searchLabel: '搜索',
658
721
  noMatchingModels: '没有匹配的模型',
722
+ resumeSessionTitle: '恢复会话',
723
+ sessionScopeCurrent: '当前目录',
724
+ sessionScopeAll: '全部',
725
+ sessionSearchHint: '搜索名称 / ID / 路径 / 模型 / 连接 · Tab 切换范围 · ↑↓ 选择 · Enter 打开 · Esc 关闭',
726
+ noMatchingSessions: '没有匹配的会话',
659
727
  selectPickerHint: '↑↓ 选择 · Enter 确认 · Esc 关闭',
660
728
  providerConfigured: '已设置',
661
729
  addAccount: '添加账号',
@@ -745,6 +813,11 @@ export const TUI_COPY_RESOURCES = {
745
813
  modelSearchHint: '搜尋模型 / 服務商 / 連線 · ↑↓ 選擇 · Enter 確認 · Esc 取消',
746
814
  searchLabel: '搜尋',
747
815
  noMatchingModels: '沒有符合的模型',
816
+ resumeSessionTitle: '恢復會話',
817
+ sessionScopeCurrent: '目前目錄',
818
+ sessionScopeAll: '全部',
819
+ sessionSearchHint: '搜尋名稱 / ID / 路徑 / 模型 / 連線 · Tab 切換範圍 · ↑↓ 選取 · Enter 開啟 · Esc 關閉',
820
+ noMatchingSessions: '沒有符合的會話',
748
821
  selectPickerHint: '↑↓ 選擇 · Enter 確認 · Esc 關閉',
749
822
  providerConfigured: '已設定',
750
823
  addAccount: '新增帳號',
@@ -863,6 +936,7 @@ export const TUI_COPY_RESOURCES = {
863
936
  skill: 'Invoke a skill (or type /skill:<name> inline)',
864
937
  swarm: 'Show, enable, disable, or run one Swarm turn',
865
938
  thinking: 'Set thinking level',
939
+ todo: 'Show the current session Todo list',
866
940
  transcript: 'Browse the full transcript inside Maka',
867
941
  },
868
942
  help: {
@@ -870,7 +944,7 @@ export const TUI_COPY_RESOURCES = {
870
944
  userCommand: ' !<command> — run one shell command visible only to you',
871
945
  keybindingsHeading: 'Keybindings',
872
946
  keybindings: [
873
- ' Ctrl+O — expand or collapse all tool output',
947
+ ' Ctrl+O — open detailed transcript (Ctrl+E toggles details inside)',
874
948
  ' Ctrl+T — expand or collapse all thinking in view',
875
949
  ' Scroll the transcript with your terminal or trackpad',
876
950
  ' Enter (during a turn) — steer: inject a message into the running turn',
@@ -916,6 +990,7 @@ export const TUI_COPY_RESOURCES = {
916
990
  skill: '调用 Skill(也可直接输入 /skill:<name>)',
917
991
  swarm: '查看、启用、停用 Swarm 模式,或执行一次 Swarm 任务',
918
992
  thinking: '设置思考级别',
993
+ todo: '查看当前会话待办清单',
919
994
  transcript: '在 Maka 内浏览完整对话记录',
920
995
  },
921
996
  help: {
@@ -923,7 +998,7 @@ export const TUI_COPY_RESOURCES = {
923
998
  userCommand: ' !<command> — 执行一次仅用户可见的 shell 命令',
924
999
  keybindingsHeading: '快捷键',
925
1000
  keybindings: [
926
- ' Ctrl+O — 展开或折叠所有工具输出',
1001
+ ' Ctrl+O — 打开详细记录(其中 Ctrl+E 切换详情)',
927
1002
  ' Ctrl+T — 展开或折叠视图中的所有思考块',
928
1003
  ' 使用终端或触控板滚动对话记录',
929
1004
  ' Enter(任务运行中)— 将消息注入当前任务',
@@ -969,6 +1044,7 @@ export const TUI_COPY_RESOURCES = {
969
1044
  skill: '呼叫 Skill(也可直接輸入 /skill:<name>)',
970
1045
  swarm: '檢視、啟用、停用 Swarm 模式,或執行一次 Swarm 任務',
971
1046
  thinking: '設定思考級別',
1047
+ todo: '檢視目前會話待辦清單',
972
1048
  transcript: '在 Maka 內瀏覽完整對話記錄',
973
1049
  },
974
1050
  help: {
@@ -976,7 +1052,7 @@ export const TUI_COPY_RESOURCES = {
976
1052
  userCommand: ' !<command> — 執行一次僅使用者可見的 shell 命令',
977
1053
  keybindingsHeading: '快捷鍵',
978
1054
  keybindings: [
979
- ' Ctrl+O — 展開或摺疊所有工具輸出',
1055
+ ' Ctrl+O — 開啟詳細記錄(其中 Ctrl+E 切換詳情)',
980
1056
  ' Ctrl+T — 展開或摺疊檢視中的所有思考區塊',
981
1057
  ' 使用終端機或觸控板捲動對話記錄',
982
1058
  ' Enter(任務執行中)— 將訊息注入目前任務',
@@ -65,6 +65,7 @@ export const AGENT_RUN_EVENT_TYPES = [
65
65
  'sandbox_escalation_applied',
66
66
  'sandbox_escalation_failed',
67
67
  'sandbox_denial_detected',
68
+ 'request_composition_resolved',
68
69
  'model_call_attempt_recorded',
69
70
  'history_compact_checkpoint_recorded',
70
71
  'model_projection_transition_recorded',
@@ -251,3 +251,6 @@ export function attachmentKindFromMimeType(mimeType, fileName) {
251
251
  }
252
252
  return 'other';
253
253
  }
254
+ export function attachmentIngestBlocked(code) {
255
+ return new Error(`attachment_ingest:${code}`);
256
+ }
@@ -0,0 +1,27 @@
1
+ /*
2
+ * Licensed to the Apache Software Foundation (ASF) under one
3
+ * or more contributor license agreements. See the NOTICE file
4
+ * distributed with this work for additional information
5
+ * regarding copyright ownership. The ASF licenses this file
6
+ * to you under the Apache License, Version 2.0 (the
7
+ * "License"); you may not use this file except in compliance
8
+ * with the License. You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing,
13
+ * software distributed under the License is distributed on an
14
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ * KIND, either express or implied. See the License for the
16
+ * specific language governing permissions and limitations
17
+ * under the License.
18
+ */
19
+ /**
20
+ * Neutral entrypoint for the strict, key-sorted JSON serializer shared by
21
+ * identity and persistence authorities.
22
+ *
23
+ * The implementation remains in `tool-args-identity` so its existing import
24
+ * path and wire behavior stay compatible while other packages use a domain-
25
+ * neutral name.
26
+ */
27
+ export { stableJsonStringify } from './tool-args-identity.js';
@@ -75,6 +75,41 @@ export const CAPABILITY_READINESS_STATES = [
75
75
  'degraded',
76
76
  'paused',
77
77
  ];
78
+ /**
79
+ * Stable machine codes for capability and OS-permission reasons. Producers
80
+ * emit these instead of locale-bound prose; presenters own the code→copy map
81
+ * per locale. Bot capabilities pass their bridge status reasons through as-is
82
+ * (`rate-limited`, `gateway-closed-4004`, …), so signal `reason` fields stay
83
+ * `string` — this union types the desktop producers and the presenter maps.
84
+ */
85
+ export const CAPABILITY_REASON_CODES = [
86
+ 'disabled',
87
+ 'platform_credentials_missing',
88
+ 'macos_tcc_only',
89
+ 'apple_events_tcc_status_unavailable',
90
+ 'cu_artifact_missing',
91
+ 'cu_backend_status',
92
+ 'cu_backend_unavailable',
93
+ 'cu_executor_undistributable',
94
+ 'cu_executor_stopped',
95
+ 'cu_executor_start_failed',
96
+ 'cu_executor_recovering',
97
+ 'cu_executor_ready',
98
+ 'cu_executor_lazy_start',
99
+ 'activity_recorder_partial',
100
+ 'activity_recorder_probe_hint',
101
+ 'memory_partial',
102
+ 'memory_no_probe',
103
+ 'accessibility_status_ambiguous',
104
+ 'screen_recording_status_mac_only',
105
+ 'notifications_status_unreadable_macos',
106
+ 'notifications_status_unreadable',
107
+ 'notifications_unsupported',
108
+ 'permission_probe_failed',
109
+ ];
110
+ export function isCapabilityReasonCode(value) {
111
+ return (typeof value === 'string' && CAPABILITY_REASON_CODES.includes(value));
112
+ }
78
113
  export function isOsPermissionState(value) {
79
114
  return typeof value === 'string' && OS_PERMISSION_STATES.includes(value);
80
115
  }
@@ -81,7 +81,6 @@ export function isComputerUseErrorCode(value) {
81
81
  return (typeof value === 'string' && COMPUTER_USE_ERROR_CODES.includes(value));
82
82
  }
83
83
  export const CU_ACTION_TYPES = ['screenshot', 'type', 'key', 'wait'];
84
- export const COMPUTER_USE_ACTION_TYPES = CU_ACTION_TYPES;
85
84
  /**
86
85
  * The semantic actions, which name an element rather than a pixel. They are not
87
86
  * in `CU_ACTION_TYPES` because they are not `CuAction`s — they are dispatched
@@ -28,6 +28,24 @@ const PATTERNS = [
28
28
  streamingTerminator: /[\s"'<>]/,
29
29
  streamingValueGroup: 3,
30
30
  },
31
+ // URL userinfo: https://user:pass@host / https://token@host
32
+ // Structural — any authority that contains `@` is credential-bearing, so
33
+ // this does not depend on a provider prefix list. Runs before the query
34
+ // rule so only the userinfo is replaced and host/path survive.
35
+ // Character class matches streamingTerminator so a bare `https://host`
36
+ // cannot swallow later `@` across whitespace/quotes/angle brackets.
37
+ // Known boundary: punctuation like commas can still join a bare URL to a
38
+ // later `@`; a proper fix would restrict userinfo to the RFC 3986 set.
39
+ // http(s) only for now. Streaming cannot recognize userinfo before `@`
40
+ // arrives (`https://user:pa` stays clear until then); tightening earlier
41
+ // would eat `https://host:8080/`.
42
+ {
43
+ label: 'url userinfo',
44
+ regex: /(https?:\/\/)([^\s"'<>/?#]*@)/gi,
45
+ replacement: (m) => `${m[1]}<redacted>@`,
46
+ streamingTerminator: /[/?#\s"'<>]/,
47
+ streamingValueGroup: 2,
48
+ },
31
49
  // URL query secrets: ?key=[redacted] ?token=[redacted] ?api_key=[redacted] &access_token=[redacted]
32
50
  // (runs before the api-key-header rule so the URL form isn't mangled.)
33
51
  {
@@ -228,6 +228,19 @@ export function reconcileConnectionAfterModelFetch(connection, models, options)
228
228
  const previousEnabled = [
229
229
  ...new Set(connectionEnabledModelIds(connection).map((id) => supersededModelId(id, live, options?.aliases))),
230
230
  ];
231
+ if (options?.authoritative) {
232
+ // The first account-scoped fetch replaces the provider fallback guess: no
233
+ // user chose those bootstrap ids, and every usable model should be offered.
234
+ // Later refreshes preserve explicit user choices only while they remain in
235
+ // the account catalog; newly introduced models stay opt-in.
236
+ const enabledModelIds = connection.hasModelInventory
237
+ ? previousEnabled.filter((id) => live.has(id))
238
+ : liveIds;
239
+ const defaultModel = enabledModelIds.includes(previousDefault)
240
+ ? previousDefault
241
+ : (enabledModelIds[0] ?? '');
242
+ return { defaultModel, enabledModelIds };
243
+ }
231
244
  // Seed a first choice only for a connection that has never had a list to
232
245
  // pick from: four providers ship no `fallbackModels`, so for them discovery
233
246
  // is the only place a first default can come from.
@@ -83,6 +83,7 @@ const MODEL_CALL_ATTEMPT_SHAPE = defineObjectShape()([
83
83
  ], [
84
84
  'connectionSlug',
85
85
  'historyCompactRoute',
86
+ 'requestCompositionId',
86
87
  'contextWindow',
87
88
  'captureArtifactId',
88
89
  'promptComposition',
@@ -294,6 +295,7 @@ export function decodeModelCallAttempt(value) {
294
295
  isNonEmptyString(value.runId) &&
295
296
  isNonEmptyString(value.turnId) &&
296
297
  isNonNegativeInteger(value.step) &&
298
+ isOptionalString(value.requestCompositionId) &&
297
299
  isNonNegativeInteger(value.attempt) &&
298
300
  MODEL_CALL_KINDS.includes(value.callKind) &&
299
301
  (value.historyCompactRoute === undefined ||
@@ -48,6 +48,10 @@ const GENERATED_METADATA_PROVIDER_ALIASES = {
48
48
  function generatedMetadataProviderType(providerType) {
49
49
  return GENERATED_METADATA_PROVIDER_ALIASES[providerType] ?? providerType;
50
50
  }
51
+ /** Whether discovery is the complete usable model catalog for this account. */
52
+ export function providerReportsCompleteModelCatalog(providerType) {
53
+ return providerType === 'github-copilot';
54
+ }
51
55
  /**
52
56
  * Whether the active metadata describes this model at all. `lookupModelMetadata`
53
57
  * answers "no" with an empty object, and callers were reading that sentinel by
@@ -53,6 +53,7 @@ export function redactSecrets(value) {
53
53
  }
54
54
  function redactTextSecrets(value) {
55
55
  let next = value;
56
+ next = redactUrlUserinfoSecrets(next);
56
57
  next = redactUrlQuerySecrets(next);
57
58
  next = next.replace(QUOTED_SECRET_KEY_VALUE_PATTERN, (match, prefix, key) => isSensitiveKey(key) ? `${prefix}[redacted]` : match);
58
59
  next = next.replace(AUTHORIZATION_HEADER_PATTERN, (_match, boundary, prefix) => `${boundary}${prefix}[redacted]`);
@@ -134,6 +135,17 @@ function redactJsonValue(value) {
134
135
  }
135
136
  return { value: next, changed };
136
137
  }
138
+ function redactUrlUserinfoSecrets(value) {
139
+ // Authority runs through the first `/`, `?`, `#`, whitespace, quote, or
140
+ // angle bracket. If it contains `@`, everything from the host-start through
141
+ // the last `@` is userinfo. The class matches display-redaction's
142
+ // streamingTerminator so a bare `https://host` followed later by an
143
+ // email/`@package` (including across JSON quotes) cannot swallow the gap.
144
+ // Known boundary: punctuation like commas can still join a bare URL to a
145
+ // later `@` into one fake credentialed match; a proper fix would restrict
146
+ // userinfo to the RFC 3986 set instead of exclusion. http(s) only for now.
147
+ return value.replace(/(https?:\/\/)[^\s"'<>/?#]*@/gi, '$1[redacted]@');
148
+ }
137
149
  function redactUrlQuerySecrets(value) {
138
150
  return value.replace(/([?&])([^=\s&?#]+)=([^&\s#]*)/g, (match, sep, key) => {
139
151
  if (!isSensitiveKey(key))
@@ -191,6 +203,10 @@ export function classifyGeneralizedError(error) {
191
203
  return 'provider_error';
192
204
  if (lower.includes('network') ||
193
205
  lower.includes('fetch') ||
206
+ // Chromium network stack error codes (`net::ERR_CONNECTION_RESET`,
207
+ // `net::ERR_NAME_NOT_RESOLVED`, ...) never match the Node errno
208
+ // spellings below.
209
+ lower.includes('net::err') ||
194
210
  lower.includes('econn') ||
195
211
  lower.includes('enotfound'))
196
212
  return 'network_error';
@@ -231,3 +247,22 @@ export function generalizedErrorMessage(error, fallback = 'Operation failed') {
231
247
  export function isAuthenticationErrorText(message) {
232
248
  return message.replace(/\bauthorit\w*/g, '').includes('auth');
233
249
  }
250
+ const reportedFailures = new WeakSet();
251
+ /** Redacted diagnostics channel for unexpected operation failures. Copy
252
+ * catalogs live here (bare-importable) because a depended-on copy catalog may
253
+ * only hold bare package runtime imports. */
254
+ export function reportUnexpectedOperation(scope, error) {
255
+ // One failure, one diagnostic: a rejection formatted again by an outer layer
256
+ // is the same defect, not a second one.
257
+ if (typeof error === 'object' && error !== null) {
258
+ if (reportedFailures.has(error))
259
+ return;
260
+ reportedFailures.add(error);
261
+ }
262
+ const detail = error instanceof Error ? (error.stack ?? `${error.name}: ${error.message}`) : String(error);
263
+ console.error(`[${scope}] operation failed:`, redactSecrets(detail));
264
+ }
265
+ export function unexpectedOperationFallback(error, fallback, scope) {
266
+ reportUnexpectedOperation(scope, error);
267
+ return fallback;
268
+ }
@@ -18,6 +18,12 @@
18
18
  */
19
19
  import { defineObjectShape, hasExactShape, isRecord } from './record-schema.js';
20
20
  export const RUN_COMPOSITION_SCHEMA_VERSION = 1;
21
+ export const REQUEST_COMPOSITION_SCHEMA_VERSION = 1;
22
+ // Composition evidence is exact: reject an over-bound provider surface rather
23
+ // than silently truncating the resolved snapshot.
24
+ export const COMPOSITION_MAX_TOOLS = 256;
25
+ export const COMPOSITION_MAX_TOOL_NAME_LENGTH = 128;
26
+ export const REQUEST_COMPOSITION_MAX_TOOL_DESCRIPTION_LENGTH = 16_384;
21
27
  const RUN_COMPOSITION_SHAPE = defineObjectShape()([
22
28
  'schemaVersion',
23
29
  'composerId',
@@ -30,6 +36,20 @@ const RUN_COMPOSITION_SHAPE = defineObjectShape()([
30
36
  'toolNames',
31
37
  'contextWindow',
32
38
  ], []);
39
+ const REQUEST_COMPOSITION_SHAPE = defineObjectShape()([
40
+ 'schemaVersion',
41
+ 'compositionId',
42
+ 'step',
43
+ 'reason',
44
+ 'sourceRevisions',
45
+ 'systemPromptHash',
46
+ 'toolCatalogHash',
47
+ 'toolAvailabilityHash',
48
+ 'providerOptionsHash',
49
+ 'toolNames',
50
+ 'toolSchemas',
51
+ ], []);
52
+ const REQUEST_COMPOSITION_TOOL_SCHEMA_SHAPE = defineObjectShape()(['name', 'description', 'inputSchema'], ['providerTool']);
33
53
  const ID_PATTERN = /^[a-z][a-z0-9]*(?:[.-][a-z0-9]+)*$/;
34
54
  const HASH_PATTERN = /^sha256:[a-f0-9]{64}$/;
35
55
  const SOURCE_REVISION_SHAPE = defineObjectShape()(['id', 'revision'], []);
@@ -64,6 +84,41 @@ export function createRunCompositionSnapshot(input) {
64
84
  toolNames: [...input.toolNames].sort(compareExactString),
65
85
  });
66
86
  }
87
+ export function createRequestCompositionSnapshot(input, reason) {
88
+ return decodeRequestCompositionSnapshot({
89
+ schemaVersion: REQUEST_COMPOSITION_SCHEMA_VERSION,
90
+ ...input,
91
+ reason,
92
+ sourceRevisions: [...input.sourceRevisions].sort((left, right) => compareExactString(left.id, right.id)),
93
+ toolNames: [...input.toolNames].sort(compareExactString),
94
+ toolSchemas: [...input.toolSchemas].sort((left, right) => compareExactString(left.name, right.name)),
95
+ });
96
+ }
97
+ export function decodeRequestCompositionSnapshot(value) {
98
+ if (!isRecord(value) || !hasExactShape(value, REQUEST_COMPOSITION_SHAPE)) {
99
+ throw new Error('Invalid Request Composition snapshot schema');
100
+ }
101
+ const valid = value.schemaVersion === REQUEST_COMPOSITION_SCHEMA_VERSION &&
102
+ boundedString(value.compositionId, 128) &&
103
+ Number.isSafeInteger(value.step) &&
104
+ value.step >= 0 &&
105
+ (value.reason === 'initial' || value.reason === 'change') &&
106
+ canonicalSourceRevisions(value.sourceRevisions) &&
107
+ hash(value.systemPromptHash) &&
108
+ hash(value.toolCatalogHash) &&
109
+ hash(value.toolAvailabilityHash) &&
110
+ hash(value.providerOptionsHash) &&
111
+ canonicalToolNames(value.toolNames) &&
112
+ canonicalToolSchemas(value.toolSchemas);
113
+ if (!valid)
114
+ throw new Error('Invalid Request Composition snapshot schema');
115
+ return Object.freeze({
116
+ ...value,
117
+ sourceRevisions: Object.freeze(value.sourceRevisions.map((source) => Object.freeze({ ...source }))),
118
+ toolNames: Object.freeze([...value.toolNames]),
119
+ toolSchemas: Object.freeze(value.toolSchemas.map((schema) => Object.freeze(structuredClone(schema)))),
120
+ });
121
+ }
67
122
  function compareExactString(left, right) {
68
123
  return left < right ? -1 : left > right ? 1 : 0;
69
124
  }
@@ -84,16 +139,36 @@ function canonicalSourceRevisions(value) {
84
139
  return true;
85
140
  }
86
141
  function canonicalToolNames(value) {
87
- if (!Array.isArray(value) || value.length > 256)
142
+ if (!Array.isArray(value) || value.length > COMPOSITION_MAX_TOOLS)
88
143
  return false;
89
144
  let previous;
90
145
  for (const name of value) {
91
- if (!boundedString(name, 128) || (previous !== undefined && previous >= name))
146
+ if (!boundedString(name, COMPOSITION_MAX_TOOL_NAME_LENGTH) ||
147
+ (previous !== undefined && previous >= name)) {
92
148
  return false;
149
+ }
93
150
  previous = name;
94
151
  }
95
152
  return true;
96
153
  }
154
+ function canonicalToolSchemas(value) {
155
+ if (!Array.isArray(value) || value.length > COMPOSITION_MAX_TOOLS)
156
+ return false;
157
+ let previous;
158
+ for (const schema of value) {
159
+ if (!isRecord(schema) ||
160
+ !hasExactShape(schema, REQUEST_COMPOSITION_TOOL_SCHEMA_SHAPE) ||
161
+ !boundedString(schema.name, COMPOSITION_MAX_TOOL_NAME_LENGTH) ||
162
+ !boundedString(schema.description, REQUEST_COMPOSITION_MAX_TOOL_DESCRIPTION_LENGTH) ||
163
+ !isRecord(schema.inputSchema) ||
164
+ (schema.providerTool !== undefined && !isRecord(schema.providerTool)) ||
165
+ (previous !== undefined && previous >= schema.name)) {
166
+ return false;
167
+ }
168
+ previous = schema.name;
169
+ }
170
+ return true;
171
+ }
97
172
  function hash(value) {
98
173
  return typeof value === 'string' && HASH_PATTERN.test(value);
99
174
  }
@@ -18,7 +18,7 @@
18
18
  */
19
19
  import { MODEL_FAILURE_MESSAGE_MAX_BYTES, isModelRetryDecision, } from './model-failure.js';
20
20
  import { decodeMessageContent, TOOL_ACTIVITY_KINDS, } from './events.js';
21
- import { isToolCategory, } from './permission.js';
21
+ import { isPermissionMode, isToolCategory, } from './permission.js';
22
22
  import { defineObjectShape, hasExactShape, isFiniteNumber, isOptionalString, isRecord, pickShape, } from './record-schema.js';
23
23
  import { isPermissionDecisionFields } from './interaction-record-schema.js';
24
24
  import { isTokenUsageFields } from './usage-record-schema.js';
@@ -283,6 +283,19 @@ export function isUserVisibleSessionSystemNote(kind) {
283
283
  export const WORKHUB_COORDINATION_RECORD_SCHEMA_VERSION = 1;
284
284
  export const WORKHUB_COORDINATION_REPLACEMENT_SCHEMA_VERSION = 2;
285
285
  export const WORKHUB_COORDINATION_STOP_SCHEMA_VERSION = 3;
286
+ export function isWorkHubCreateDefaults(value) {
287
+ if (!isRecord(value) ||
288
+ Object.keys(value).some((key) => key !== 'model' && key !== 'permissionMode'))
289
+ return false;
290
+ if (value.permissionMode !== undefined && !isPermissionMode(value.permissionMode))
291
+ return false;
292
+ if (value.model === undefined)
293
+ return true;
294
+ const model = value.model;
295
+ return (isRecord(model) &&
296
+ Object.keys(model).length === 3 &&
297
+ ['llmConnectionId', 'llmConnectionSlug', 'model'].every((key) => typeof model[key] === 'string' && model[key].trim().length > 0 && model[key].length <= 512));
298
+ }
286
299
  function isWorkHubDelegationStopResolution(outcome, targetTurnId) {
287
300
  const hasTargetTurnId = typeof targetTurnId === 'string' && targetTurnId.length > 0;
288
301
  if (outcome === 'stop_delivered' || outcome === 'not_owned')
@@ -405,7 +418,7 @@ const WORKHUB_DELEGATION_ASSIGNED_MESSAGE_SHAPE = defineObjectShape()([
405
418
  'targetTurnId',
406
419
  'targetMessageId',
407
420
  'targetSessionName',
408
- ], ['create', 'steered', 'replacesActionId', 'replacesDelegationId']);
421
+ ], ['attachments', 'create', 'steered', 'replacesActionId', 'replacesDelegationId']);
409
422
  const WORKHUB_DELEGATION_REPLACEMENT_REQUESTED_MESSAGE_SHAPE = defineObjectShape()([
410
423
  'type',
411
424
  'id',
@@ -424,7 +437,7 @@ const WORKHUB_DELEGATION_REPLACEMENT_REQUESTED_MESSAGE_SHAPE = defineObjectShape
424
437
  'replacedTargetSessionId',
425
438
  'replacedTargetMessageId',
426
439
  'targetSessionName',
427
- ], ['create']);
440
+ ], ['attachments', 'create']);
428
441
  const WORKHUB_DELEGATION_SUPERSEDED_MESSAGE_SHAPE = defineObjectShape()([
429
442
  'type',
430
443
  'id',
@@ -486,7 +499,7 @@ const WORKHUB_DELEGATION_STOP_RESOLVED_MESSAGE_SHAPE = defineObjectShape()([
486
499
  'targetSessionId',
487
500
  'outcome',
488
501
  ], ['targetTurnId']);
489
- const WORKHUB_DELEGATION_CREATE_SHAPE = defineObjectShape()(['title', 'workspace'], []);
502
+ const WORKHUB_DELEGATION_CREATE_SHAPE = defineObjectShape()(['title', 'workspace'], ['defaults']);
490
503
  const WORKHUB_DELEGATION_PROJECT_WORKSPACE_SHAPE = defineObjectShape()(['kind', 'projectId'], []);
491
504
  const WORKHUB_DELEGATION_HOST_PATH_WORKSPACE_SHAPE = defineObjectShape()(['kind', 'path'], []);
492
505
  const SYSTEM_NOTE_MESSAGE_SHAPE = defineObjectShape()(['type', 'id', 'ts', 'kind'], ['turnId', 'data']);
@@ -694,6 +707,7 @@ function isWorkHubCoordinationMessage(message) {
694
707
  typeof message.targetSessionId === 'string' &&
695
708
  typeof message.userText === 'string' &&
696
709
  message.userText.trim().length > 0 &&
710
+ isWorkHubMessageAttachments(message.attachments) &&
697
711
  ((message.disposition === 'delegate_existing' && message.create === undefined) ||
698
712
  (message.disposition === 'create_new' && isWorkHubDelegationCreateSpec(message.create))) &&
699
713
  (message.disposition === 'delegate_existing' || message.disposition === 'create_new');
@@ -739,9 +753,21 @@ function isWorkHubActionIdentity(message) {
739
753
  message.coordinationTurnId.length > 0 &&
740
754
  message.turnId === message.coordinationTurnId);
741
755
  }
756
+ function isWorkHubMessageAttachments(value) {
757
+ if (value === undefined)
758
+ return true;
759
+ try {
760
+ decodeMessageContent({ text: '', attachments: value });
761
+ return true;
762
+ }
763
+ catch {
764
+ return false;
765
+ }
766
+ }
742
767
  function isWorkHubDelegationCreateSpec(value) {
743
768
  if (!isRecord(value) ||
744
769
  !hasExactShape(value, WORKHUB_DELEGATION_CREATE_SHAPE) ||
770
+ (value.defaults !== undefined && !isWorkHubCreateDefaults(value.defaults)) ||
745
771
  typeof value.title !== 'string' ||
746
772
  value.title.trim().length === 0 ||
747
773
  !isRecord(value.workspace)) {
@@ -40,6 +40,7 @@ export const SLASH_COMMAND_CATALOG = [
40
40
  { id: 'skill', session: 'required', surfaces: ['tui'] },
41
41
  { id: 'swarm', session: 'none', surfaces: ['desktop', 'tui'] },
42
42
  { id: 'thinking', session: 'required', surfaces: ['tui'] },
43
+ { id: 'todo', session: 'required', surfaces: ['tui'] },
43
44
  { id: 'transcript', session: 'required', surfaces: ['tui'] },
44
45
  { id: 'update', session: 'none', surfaces: ['tui'] },
45
46
  ];
@@ -37,7 +37,7 @@ const ARCHIVED_SHAPE = defineObjectShape()([
37
37
  'originalBytes',
38
38
  'rewriteVersion',
39
39
  'reason',
40
- ], ['artifactId', 'bodySha256']);
40
+ ], ['artifactId', 'resourceRef', 'bodySha256']);
41
41
  const IMAGE_SHAPE = defineObjectShape()(['kind', 'mimeType', 'ref'], []);
42
42
  const SUMMARY_SHAPE = defineObjectShape()(['kind', 'original', 'summarized', 'reason'], []);
43
43
  const WEB_SEARCH_SHAPE = defineObjectShape()(['kind', 'provider', 'query', 'rows'], []);
@@ -157,6 +157,7 @@ function isNonShellToolResultContent(value) {
157
157
  typeof value.toolCallId === 'string' &&
158
158
  typeof value.toolName === 'string' &&
159
159
  isOptionalString(value.artifactId) &&
160
+ isOptionalString(value.resourceRef) &&
160
161
  isOptionalString(value.bodySha256) &&
161
162
  isFiniteNumber(value.originalEstimatedTokens) &&
162
163
  isFiniteNumber(value.originalBytes) &&
@@ -9,6 +9,7 @@
9
9
  "./durable-tool-result-projection": "./dist/durable-tool-result-projection.js",
10
10
  "./model-projection-transition": "./dist/model-projection-transition.js",
11
11
  "./canonical-runtime-event": "./dist/canonical-runtime-event.js",
12
+ "./canonical-json": "./dist/canonical-json.js",
12
13
  "./runtime-boundary": "./dist/runtime-boundary.js",
13
14
  "./runtime-handoff": "./dist/runtime-handoff.js",
14
15
  "./runtime-logical-execution": "./dist/runtime-logical-execution.js",