dsh-github-copilot 0.4.0-alpha.27 → 0.4.0-alpha.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +5 -3
- package/CHANGELOG.md +16 -0
- package/README.md +29 -15
- package/README.zh.md +28 -14
- package/deployment-baseline.json +49 -2
- package/docs/copilot-compaction.md +84 -0
- package/docs/model-compatibility-acceptance.md +1 -1
- package/docs/official-first-016-alpha2.md +6 -0
- package/docs/session-search-routing.md +11 -5
- package/lib/client.js +120 -134
- package/lib/client.js.map +1 -1
- package/lib/index.js +393 -88
- package/lib/types/compaction-pressure.d.ts +23 -0
- package/lib/types/config.d.ts +8 -1
- package/lib/types/preview-provider.d.ts +3 -1
- package/lib/types/preview-route.d.ts +3 -0
- package/lib/types/request-budget.d.ts +58 -0
- package/lib/types/web-search-routing-card.d.ts +1 -2
- package/package.json +2 -1
package/AGENTS.md
CHANGED
|
@@ -31,7 +31,7 @@ Use native DSH tools for goals, background jobs and scoped subagents. Use local
|
|
|
31
31
|
|
|
32
32
|
`dsh-github-copilot` is a companion targeting official DSH `0.1.6-alpha.2`, with retained baselines for DSH `0.1.6-alpha.1`, DSH `0.1.5-rc.2`, DSH `0.1.5-rc.1`, DSH `0.1.5-alpha.2`, DSH `0.1.5-alpha.1`, DSH `0.1.3-alpha.1`, DSH `0.1.2-rc.1`, and the controlled DSH Desktop `0.1.1-rc.2` Core baseline. It does not own a general Copilot chat adapter. DSH's built-in `llm-pi-ai` mount owns the GitHub Copilot provider, catalog, OAuth method and grant format, token exchange, refresh, and normal model transport.
|
|
33
33
|
|
|
34
|
-
This repository owns
|
|
34
|
+
This repository owns ten narrow surfaces:
|
|
35
35
|
|
|
36
36
|
1. A conditional authorization-service bootstrap plus Host controller that joins DSH authorization, credentials, and settings.
|
|
37
37
|
2. A Client Models provider-card contribution with one shared account-state owner and Client-safe Remote descriptors; embed in an existing configured canonical row, suppress its separate footer controller, and retain footer/old-Core section fallback when no such row is mounted.
|
|
@@ -42,6 +42,7 @@ This repository owns nine narrow surfaces:
|
|
|
42
42
|
7. A bounded account-discovery route that supplies validated endpoint/capability metadata to the published native adapter, without maintaining model-ID routing rules or changing Core's catalog.
|
|
43
43
|
8. Optional, provider-scoped Chat presentation for completed empty reasoning disclosures; durable content and encrypted replay metadata remain Core-owned.
|
|
44
44
|
9. Opt-in model-role settings and dedicated new planner/executor sessions, using public Agent/Session/subagent APIs without changing existing sessions, global defaults or native Subagent model-selection settings.
|
|
45
|
+
10. Managed-route estimated input/output admission, optional exact-request pressure signalling through official compaction recovery, and supported low summary effort only when no effort is already resolved. See [compaction budgets](./docs/copilot-compaction.md). Preserve truthful capacities, requested output caps, native errors/replay and transaction ownership; no hidden history trimming, chunking, new retry loop, competing compaction service or automatic model switch. Preventive guards do not claim recovery of an already oversized manual summary.
|
|
45
46
|
|
|
46
47
|
## Dedicated model-role boundary (#127)
|
|
47
48
|
|
|
@@ -86,14 +87,15 @@ Alpha.25 admits native `subagent/descriptor` v3, already v3 in the retained rc.1
|
|
|
86
87
|
- Copilot OAuth grant writes must rebuild only pi-ai's documented provider fields as a fresh plain JSON object; unrelated extension values never reach DSH credential storage.
|
|
87
88
|
- Settings changes are path-level. Never replace the whole `llm-pi-ai` section or unrelated provider profiles.
|
|
88
89
|
- Sign-out deletes only the Copilot credential record and keeps route settings.
|
|
89
|
-
- Hosted search serves either an eligible initiating `github-copilot` / managed `github-copilot-preview` route, or
|
|
90
|
+
- Hosted search serves either an eligible initiating `github-copilot` / managed `github-copilot-preview` route, or provider-owned independent search selected by the web-search router. Independent search preserves a nonempty explicit `searchModel` override; otherwise the Host considers at most three eligible Responses models from current account route facts, in deterministic ID order, without a static model list. Metadata alone is not search proof, and the final user query is sent once after candidate proof, never replayed across models. Both paths require an account-available model and supported search protocol; custom inline transport remains legacy-canonical only. Never substitute the global chat default or another Session's identity. The default `probe: true` path requires successful capability proof; `probe: false` is an explicit trust override, not an implicit fallback. Any request containing a file block, including one nested in tool-result content, must bypass the custom wire through `next()` so Core retains file projection ownership.
|
|
90
91
|
- Misconfiguration and API drift fail loudly with a named missing seam. Do not fall back to process-local secrets or implicit machine state.
|
|
91
92
|
- Host, Client, and Remote package entries must stay independently buildable and exported.
|
|
92
93
|
- The package must self-provide authorization when Core omits it, reuse an existing service without duplicate registration, and never activate the integration body before authorization is available.
|
|
93
94
|
|
|
94
95
|
## Session and migration ownership (V3, alpha.8, #99)
|
|
95
96
|
|
|
96
|
-
- One global Host account supplies many models; selected/history-backed Sessions retain independent model context. Auto-mode native search derives from the captured initiating Session's effective request-header/config or explicit `GenerateOptions`, never another Session or future global default C. Fixed/
|
|
97
|
+
- One global Host account supplies many models; selected/history-backed Sessions retain independent model context. Auto-mode native search derives from the captured initiating Session's effective request-header/config or explicit `GenerateOptions`, never another Session or future global default C. Fixed/fallback Copilot search uses the explicit provider-owned `searchModel` override when nonempty, otherwise bounded automatic account-owned Responses selection; it never borrows the Chat model, another Session's selection or the global chat default. `Agent.options` is the activation seed, not selected Session-model evidence; `installModelSelection` overrides request/assembly; Core records the effective `Session.requestHeader().config` before tools. Without proven request context, traditional search is unavailable. A newly selected pending model must not reuse the old request header as current prompt guidance. Per-owner plan caches prevent different-model A/B reuse/cancellation; metadata remains shared.
|
|
98
|
+
- The ordinary Web search card selects only the primary and fallback providers and saves both routing leaves in one namespace CAS. It must not depend on Copilot model discovery, a model selection or the Copilot settings namespace to save routing. Capture traced Settings/routing Remote faces once per UI registration so parent renders do not reset drafts. Preserve a legacy nonempty `searchModel` override; display it read-only and reset it only through an explicit, separate narrow CAS setting `searchModel: ''`, never as a routing-save side effect. Saving settings does not prove hosted-search capability.
|
|
97
99
|
- Cold Chat picker and `/model` `listModels()` ensure the shared managed source without Settings first. Actual cold managed search non-forcing ensures metadata before deriving facts; existing 24h maximum TTL, cooldown, credential, allowlist and capability/probe gates remain.
|
|
98
100
|
- Without `agents.currentInitiator`, traditional hosted search is unavailable with a named diagnostic; explicit marked `GenerateOptions` can still bind guarded inline requests, uncached if necessary. Credential notification during initial lazy discovery cannot distinguish own rotation from external account change via public status: fail closed with `WEB_PROVIDER_UNAVAILABLE` before probe/wire; a later user/driver request may retry, never automatically.
|
|
99
101
|
- The new native Copilot draft warning says Save adds another real group, not a second account. Public additive APIs cannot veto Add or disable Save; this is warning-only, not enforced single-route registration. Core Edit/Delete remain. Alpha.7 screenshots illustrate timestamps, not alpha.8 migration/search proof.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.0-alpha.29 (prepared)
|
|
4
|
+
|
|
5
|
+
- Fix search settings drafts and pending saves being reset by parent renders: capture stable traced Settings/routing Remote faces once per registration (#148).
|
|
6
|
+
- Make ordinary Web search settings provider-only, rename the final default to Fallback provider, and save both routing choices in one namespace CAS without model discovery or a model prerequisite.
|
|
7
|
+
- Resolve independent Copilot search models from current account-owned Responses metadata in deterministic order, with at most three capability-probed candidates and one final query. Preserve allowlists, explicit overrides, account/owner proof, cancellation and fallback policy; never borrow a Chat/global default or hardcode model IDs.
|
|
8
|
+
- Preserve existing model overrides and offer a separate explicit reset to automatic selection. Classify safe save/conflict diagnostics without exposing raw Remote errors.
|
|
9
|
+
- Add real pinned Settings/Client-codec contracts, mounted React/Cordis lifecycle tests, and isolated built-browser before/after reproduction. These are not live OAuth/search, published-release or installed Desktop acceptance claims.
|
|
10
|
+
|
|
11
|
+
## 0.4.0-alpha.28 (prepared)
|
|
12
|
+
|
|
13
|
+
- Enforce plugin-owned estimated independent prompt and combined input/output budgets on the managed Copilot route while preserving advertised context capacity and native transport (#146).
|
|
14
|
+
- Signal eligible exact-session loop pressure before model dispatch through the existing official bounded compaction/rebuild path; respect disabled automatic recovery, model-specific zero retries and cancellation.
|
|
15
|
+
- Prefer supported minimal/low reasoning only for compaction with no supplied or materialized effort, without silently rewriting the requested summary output cap or changing ordinary conversations.
|
|
16
|
+
- Preserve structured local admission failures through SDK wrapping, current system/tool accounting, concurrent-call isolation and distinct output-truncation outcomes. Add configurable safety/pressure/summary policy and regression coverage.
|
|
17
|
+
- Keep already oversized manual summaries as explicit failures; this release does not claim chunked recovery, silent history deletion, automatic model switching, Core changes or local Desktop activation.
|
|
18
|
+
|
|
3
19
|
## 0.4.0-alpha.27 (prepared)
|
|
4
20
|
|
|
5
21
|
- Remove the separate Model roles workspace dropdown: role settings remain profile-global and saving does not require a workspace (#144).
|
package/README.md
CHANGED
|
@@ -61,7 +61,7 @@ Source markers, local rc.1-backed focused tests and fifteen scoped exact-source
|
|
|
61
61
|
|
|
62
62
|
## Install and sign in
|
|
63
63
|
|
|
64
|
-
The commands below target the package version `0.4.0-alpha.
|
|
64
|
+
The commands below target the package version `0.4.0-alpha.29`. Versioned URLs describe the intended release artifacts, not proof that publication or local activation has completed; use them only once that Release and its checksums are available. Install into the profile you use (replace `web` when targeting another profile):
|
|
65
65
|
|
|
66
66
|
Before installing/updating, unpack the **checksum-verified** archive into a temporary directory and run its read-only composition preflight (replace all paths with absolute paths for the intended profile):
|
|
67
67
|
|
|
@@ -74,7 +74,7 @@ Include any launcher patch files with repeated `--patch /absolute/file` argument
|
|
|
74
74
|
For approved online installation, the supported CLI command is:
|
|
75
75
|
|
|
76
76
|
```sh
|
|
77
|
-
dsh plugin --profile web add https://github.com/cloga/dsh-github-copilot/releases/download/v0.4.0-alpha.
|
|
77
|
+
dsh plugin --profile web add https://github.com/cloga/dsh-github-copilot/releases/download/v0.4.0-alpha.29/dsh-github-copilot-0.4.0-alpha.29.tgz
|
|
78
78
|
```
|
|
79
79
|
|
|
80
80
|
If registry access is blocked or unavailable, do not retry it through another network. Desktop-managed profiles may instead use the [controlled offline CLI procedure](./docs/npm-distribution.md#controlled-offline-cli-maintenance), with an approved, checksum-verified local Release and existing dependency cache (`--offline --ignore-scripts`). All preflight and approval requirements still apply.
|
|
@@ -139,7 +139,7 @@ Agents should treat the browser authorization as a human handoff, not as a token
|
|
|
139
139
|
5. Confirm **Signed in** and inspect the automatic discovery result before asking the user to choose a model. Already-signed-in Models opening ensures missing/stale metadata automatically; fresh ready cache makes no request. Use visible **Retry** for errors or **Manage → Refresh models** for an intentional forced update, not routine setup. Status alone does not discover, and login, metadata and successful model calls remain separate evidence.
|
|
140
140
|
6. Use **Sign out** only when the user explicitly asks to disconnect the account. It deletes the Copilot credential record but preserves route settings.
|
|
141
141
|
|
|
142
|
-
GitHub Releases and npm are the default distribution channels for each new version, using the same verified tarball. Pin the version and verify the evidence for the channel used: Release `SHA256SUMS`, and npm `dist.integrity` when installing from npm. The native Desktop package manager is preferred when permitted registry access is available; after npm publication is verified it accepts `dsh-github-copilot@0.4.0-alpha.
|
|
142
|
+
GitHub Releases and npm are the default distribution channels for each new version, using the same verified tarball. Pin the version and verify the evidence for the channel used: Release `SHA256SUMS`, and npm `dist.integrity` when installing from npm. The native Desktop package manager is preferred when permitted registry access is available; after npm publication is verified it accepts `dsh-github-copilot@0.4.0-alpha.29`, not a URL or file. Desktop-managed profiles also support explicitly approved [controlled offline CLI maintenance](./docs/npm-distribution.md#controlled-offline-cli-maintenance) with a verified local Release and `--offline --ignore-scripts`. Follow the mandatory search-composition preflight, backup, single-writer and post-install checks; do not bypass a corporate registry ban, disable TLS verification or restart without separate approval. Offline installation is not proof that npm networking/publication was repaired. See [distribution and publication requirements](./docs/npm-distribution.md).
|
|
143
143
|
|
|
144
144
|
No `copilot2api` process, external gateway, placeholder API key, pasted GitHub token, or separate `dsh-web-search-provider` installation is required.
|
|
145
145
|
|
|
@@ -158,7 +158,7 @@ DSH Core continues to own model selection, sandboxing, tools, attachments, and o
|
|
|
158
158
|
|
|
159
159
|
Under **Settings → Models → Model roles**, enable dedicated dual-model sessions, select two available account models, and save the profile-global settings. No workspace is needed to save. **Create session with this configuration** uses the application's current workspace, shown read-only; open a workspace first if none is current. There is no separate workspace dropdown and no first/recent-workspace fallback. The planner handles planning and acceptance; `copilot_execute` delegates implementation to a native continuable child with a fixed execution model. Configuration is off by default and affects only sessions created through this entry. It does not change the global default, existing sessions, credentials or the ordinary Subagent model-selection setting.
|
|
160
160
|
|
|
161
|
-
Unavailable models are not substituted. Uncertain creation retries keep the same request identity. The feature requires public role/session/subagent capabilities and is visibly unavailable when they are absent; historical package compatibility is not blanket certification of this optional flow. See [setup, lifecycle, limitations and evidence](./docs/dual-model.md). The feature is included in the `0.4.0-alpha.
|
|
161
|
+
Unavailable models are not substituted. Uncertain creation retries keep the same request identity. The feature requires public role/session/subagent capabilities and is visibly unavailable when they are absent; historical package compatibility is not blanket certification of this optional flow. See [setup, lifecycle, limitations and evidence](./docs/dual-model.md). The feature is included in the `0.4.0-alpha.29` candidate; source and fixture tests are not proof of publication or Desktop activation.
|
|
162
162
|
|
|
163
163
|
If the card says **Could not load model roles**, do not change model defaults to work around it: this is a failed settings load, distinct from unsupported capabilities or unavailable models. In particular, a `githubCopilotDualModel/view` HTTP 404 indicates missing Host Remote exposure, not that the feature is off. See [troubleshooting and verification](./docs/dual-model.md#loading-and-remote-troubleshooting).
|
|
164
164
|
|
|
@@ -226,7 +226,7 @@ Before a grant is persisted or reused, the Host normalizer rebuilds only pi-ai's
|
|
|
226
226
|
|
|
227
227
|
## Hosted search
|
|
228
228
|
|
|
229
|
-
Auto-mode native search identity comes from the captured initiating Session's effective request-header/config or explicit `GenerateOptions`, never the future global chat default. Fixed/
|
|
229
|
+
Auto-mode native search identity comes from the captured initiating Session's effective request-header/config or explicit `GenerateOptions`, never the future global chat default. Fixed/fallback Copilot search instead resolves its execution model inside the provider from current account metadata, while preserving a nonempty explicit `github-copilot.searchModel` override; it never borrows the Chat model or another Session's selection. Core `Agent.options` remains the activation seed: model selection overrides request/assembly, with effective config recorded in `Session.requestHeader().config` before tools. Without a proven initiating owner, traditional search is unavailable. After a new model is selected but before its next request, the previous header must not be treated as current prompt guidance. Per-owner plan caches keep different-model Sessions independent. An actual cold managed search first ensures the shared account metadata without force, then derives model facts and applies the existing account/protocol/allowlist/probe gates. Explicit marked `GenerateOptions` can still bind eligible inline requests, uncached when no owner is available, under all existing guards.
|
|
230
230
|
|
|
231
231
|
**Credential-change limit:** an OAuth notification during initial lazy metadata discovery cannot distinguish the discovery's own token rotation from an external account change through current public status. That first search deliberately fails closed with `WEB_PROVIDER_UNAVAILABLE`, before probe/wire work. A later user/driver request may retry with refreshed credentials; there is no automatic retry or promise of seamless first-attempt refresh.
|
|
232
232
|
|
|
@@ -241,14 +241,15 @@ The bundle composes a plugin-owned web-service facade while preserving the origi
|
|
|
241
241
|
|
|
242
242
|
A separate **Web search** card under **Settings → Models** controls routing across search backends. On older Core versions without the Models footer, it appears as **Settings → Web search**. The companion owns the namespaced policy (`github-copilot-search-routing`); it does not claim a global Core namespace. Removing the companion restores the original web service.
|
|
243
243
|
|
|
244
|
-
The **Search provider** selector offers **Auto — follow Chat** and the actual search providers registered through the routed facade. **
|
|
244
|
+
The **Search provider** selector offers **Auto — follow Chat** and the actual search providers registered through the routed facade. **Fallback provider** uses the same catalog, with an additional **None — no fallback** choice. These are search backends, not individual models: Copilot is one backend even when different account models can execute its search requests. Ordinary setup needs only these provider choices, not a separate search model.
|
|
245
245
|
|
|
246
246
|
- `github-copilot-search-routing.searchProvider: auto` follows the initiating Chat provider. Copilot's plugin-owned aliases retain their existing ownership and model-capability checks; other Chat provider IDs must exactly match a registered search provider ID. Names, suffixes and model families are never guessed. This convention does not promise the same model or account across independently registered providers.
|
|
247
247
|
- A concrete `searchProvider` ID pins the primary backend independently of Chat.
|
|
248
248
|
- `defaultSearchProvider` is only the final fallback when no primary matches or the primary search fails. It is attempted at most once, never retried when it is already the primary, and never replaces a successful empty result. `none` disables fallback without disabling the primary.
|
|
249
|
-
- Copilot selected explicitly or as the fallback
|
|
249
|
+
- Copilot selected explicitly or as the fallback automatically considers at most three eligible Responses candidates from current account route facts, sorted by model ID. The default capability probe must succeed before the final user query is sent once; metadata alone is not proof, and a failed final query is not replayed across models. This internal selection does not change Chat or global defaults. Other backends own their model configuration, if any.
|
|
250
|
+
- A saved nonempty `github-copilot.searchModel` remains authoritative; the plugin does not silently replace an invalid override. Its read-only details offer a separate explicit reset to automatic selection (`searchModel: ''`). Saving provider routing never changes this override.
|
|
250
251
|
|
|
251
|
-
Existing `searchMode: auto/fixed` settings remain readable without automatic writes. Legacy fixed mode preserves its old default as the primary; fixed plus `none` stays disabled. An explicit save writes the
|
|
252
|
+
Existing `searchMode: auto/fixed` settings remain readable without automatic writes. Legacy fixed mode preserves its old default as the primary; fixed plus `none` stays disabled. An explicit save writes both routing keys together with one revision-checked mutation; it does not require the Copilot settings namespace or fetch an account/model list. Stable Remote references keep enclosing page renders from resetting the draft. On a revision conflict, reload saved settings and reapply the intended choices; a rejected or unconfirmed response is not reported as success. Saving proves only configuration persistence, not live search capability. The UI explains that saving adopts the chosen final fallback, including possible API charges; legacy `github-copilot.searchFallback: none` failure-spending restrictions remain until that choice is saved. Unregistered saved IDs remain visible as unavailable instead of being silently substituted.
|
|
252
253
|
|
|
253
254
|
`github-copilot.routeWebSearch: false` still delegates to the original configured web service. Otherwise cancellation, unload and captured account-proof invalidation never authorize a fallback. Generic registered backends must honor cancellation; their public interface does not expose an internal pre-network authorization hook. The historical direct Copilot/DeepSeek path retains its stronger owned pre-dispatch guard. Neither path supplies another provider's credentials from Copilot sign-in.
|
|
254
255
|
|
|
@@ -277,10 +278,20 @@ This optional integration uses the public `conversation.chat.node` keyed slot an
|
|
|
277
278
|
### Capability warnings and adapter limits
|
|
278
279
|
|
|
279
280
|
- `REASONING_EFFORTS_UNSUPPORTED` means some advertised reasoning labels cannot be expressed faithfully by the selected native SDK protocol. They are not guessed, and ordinary requests remain available. Explicit unsupported efforts—including an unadvertised `off`—are rejected rather than silently treated as defaults.
|
|
280
|
-
- `
|
|
281
|
+
- `INPUT_LIMIT_ESTIMATED_GUARD` means the managed route applies a plugin-owned estimated input guard while retaining the provider's distinct input, context and output capacities. This is not exact provider token counting or a claim that Core exposes a separate input limit; provider overflow remains possible.
|
|
281
282
|
- The Core-facing integration uses the published adapter's normal `streamSimple` path. Its advanced `stream` entry explicitly rejects incompatible protocol-specific SDK client objects; this does not disable normal conversation streaming.
|
|
282
283
|
- Unknown pricing is represented as unpriced metadata, not a claim that a model is free. Public summaries remain optional provider output.
|
|
283
284
|
|
|
285
|
+
## Managed request budgets and compaction
|
|
286
|
+
|
|
287
|
+
The managed `github-copilot-preview` route estimates the complete native request, including current system/tool prefixes, and checks both the independent prompt limit and combined input/output capacity before model transport. Its operational input budget is `min(prompt limit when advertised, context capacity - requested/default output reservation) - safety allowance`. Supplier capacities are not rewritten. Invalid output policy or exhausted headroom fails explicitly; no history is silently truncated and no model is substituted.
|
|
288
|
+
|
|
289
|
+
For a marked ordinary agent-loop request with a matching initiating Session and committed request configuration, optional token-meter and enabled stock automatic compaction, the plugin signals local estimated pressure at 90% of that budget. Core owns the existing bounded compaction/rebuild path and commits only a valid smaller checkpoint. It does not compact concurrently inside a frozen request. Missing optional seams disable this early signal, not the final native budget guard; `auto: false` or zero stock overflow retries remain respected. Canonical/user-owned routes and other providers are unchanged.
|
|
290
|
+
|
|
291
|
+
Calls explicitly marked `purpose: 'compaction'` bypass the early-pressure signal and use the full hard budget. When no caller or adapter-resolved reasoning effort is present, `prefer-low` selects an advertised supported `minimal` or `low` effort; unsupported controls preserve provider defaults. An explicit or materialized effort wins. The requested summary output cap remains unchanged, preserving Core's auxiliary summary record; the plugin does not blindly raise/lower it or accept truncated output as a checkpoint. `enabled` remains a hosted-search switch, not a switch for this managed-route protection.
|
|
292
|
+
|
|
293
|
+
**Existing oversized history is not guaranteed recoverable.** Manual compact can still exceed the hard budget and is rejected before model transport with a safe diagnostic. Output truncation remains a distinct native `max-tokens` outcome. This change adds no chunked summarizer, silent history deletion, automatic model switching or new retry loop. Configure an appropriate summary route/cap through official compaction policy when needed; do not repeatedly resubmit an unchanged impossible request. See [the implementation and acceptance boundary](./docs/copilot-compaction.md).
|
|
294
|
+
|
|
284
295
|
## Copilot tool compatibility
|
|
285
296
|
|
|
286
297
|
To prevent observed invalid Copilot tool payloads, the package sets the managed route's `compat.supportsStrictMode` leaf to `false` and applies two schema-only fixes when the selected provider is canonical `github-copilot` or the plugin-owned account route `github-copilot-preview`: it removes top-level `sandbox_permissions` and `justification` properties, and rewrites Core's multi-action `update_goal` parameters as a discriminated `oneOf`. Each Goal action then advertises only its legal fields: `complete`, `pause`, and `resume` cannot carry edit or blocker fields; `blocked` requires `blocked_reason`; and `edit` alone exposes replacement fields. Execution still uses Core's original Goal tool and service. Non-Copilot prompt assemblies are unchanged.
|
|
@@ -296,12 +307,15 @@ The plugin does not rewrite `$DSH_HOME/AGENTS.md`. Installers may merge these ru
|
|
|
296
307
|
|
|
297
308
|
## Settings
|
|
298
309
|
|
|
299
|
-
The plugin's `github-copilot` settings section controls account-metadata freshness and hosted search. `enabled` still controls hosted search only:
|
|
310
|
+
The plugin's `github-copilot` settings section controls account-metadata freshness, managed request budgets and hosted search. `enabled` still controls hosted search only:
|
|
300
311
|
|
|
301
312
|
| Key | Default | Scope and meaning |
|
|
302
313
|
|---|---:|---|
|
|
303
314
|
| `accountModelTtlMs` | `86400000` | Maximum account-metadata reuse window in milliseconds (24h); does not extend credentials or proof validity. |
|
|
304
315
|
| `accountModelFailureCooldownMs` | `300000` | Failure cooldown in milliseconds (5min) for non-forcing discovery; no periodic retries. |
|
|
316
|
+
| `requestBudgetSafetyTokens` | `4096` | Non-negative safe-integer estimated input allowance; larger values reduce available input. |
|
|
317
|
+
| `requestBudgetPressureRatio` | `0.9` | Fraction (0.01–1, step 0.01) for early local pressure, only with supported enabled stock recovery. |
|
|
318
|
+
| `compactionReasoning` | `prefer-low` | Choose supported minimal/low only when summary effort is absent; `preserve` keeps native defaults. |
|
|
305
319
|
| `enabled` | `true` | Enable both hosted-search surfaces. |
|
|
306
320
|
| `providers` | `[]` | Optional route allowlist for both surfaces; empty follows the initiating route. Existing nonempty lists are preserved; Ops must explicitly review any legacy-ID change to `github-copilot-preview`. |
|
|
307
321
|
| `includeSources` | `true` | Request provider citations on the inline path. The `ctx.web` bridge always requests and returns sources. |
|
|
@@ -310,7 +324,7 @@ The plugin's `github-copilot` settings section controls account-metadata freshne
|
|
|
310
324
|
| `probe` | `true` | Require capability proof on both surfaces; `false` explicitly trusts the native protocol. |
|
|
311
325
|
| `probeTimeoutMs` | `30000` | Whole capability-probe deadline, in milliseconds. |
|
|
312
326
|
|
|
313
|
-
There are no token, API-key, model-catalog, or endpoint settings in this package.
|
|
327
|
+
There are no credential-token, API-key, model-catalog, or endpoint settings in this package.
|
|
314
328
|
|
|
315
329
|
## Migration and troubleshooting
|
|
316
330
|
|
|
@@ -322,7 +336,7 @@ Existing installations must follow the [single-route migration guide](./docs/sin
|
|
|
322
336
|
- **Canonical route says `not-configured`:** with configured login this is normal managed-only mode; inspect account discovery separately rather than creating a native profile.
|
|
323
337
|
- **Delete dialog stays on “Deleting…”:** this update does not prove that hang fixed. Do not repeatedly delete; after an authorized Host stop, inspect persisted settings and follow the migration guide before deciding whether any removal is still needed.
|
|
324
338
|
- **No Think text:** the provider may omit public summaries, but nonempty summaries must survive the Responses parser. Check selected effort and named errors. Empty disclosures are hidden only after completion; encrypted replay is never displayed. Reasoning/replay-bearing histories use native Core transport.
|
|
325
|
-
- **Hosted search unavailable:** for
|
|
339
|
+
- **Hosted search unavailable:** for explicit/fallback Copilot, inspect account discovery/probe diagnostics; ordinary setup no longer requires selecting a search model. A legacy override remains authoritative until you explicitly reset it to automatic selection. Auto following Copilot Chat still requires that initiating model to support search. The custom inline path is legacy-canonical only; a saved provider choice or normal managed chat success does not prove search support.
|
|
326
340
|
- **Legacy endpoint/key still present:** reconciliation preserves unowned fields by design. Review explicit migration; never force-remove an ownership marker.
|
|
327
341
|
|
|
328
342
|
## Package entries and source map
|
|
@@ -385,8 +399,8 @@ Report the published Release URL, version, tag/commit and verified asset SHA-256
|
|
|
385
399
|
`package.json` declares public npm distribution. A release tag must equal `v${package.json.version}`. Versions use standard SemVer prerelease labels (`alpha`, `beta`, or `rc`), each with its matching npm dist-tag; only stable versions use `latest`. The Release workflow performs the frozen install and complete verification gate, packs once (or recovers the original archive on retry), verifies `SHA256SUMS`, publishes the immutable GitHub Release and then publishes those same bytes to npm through OIDC. Either channel failing means delivery is incomplete. First package creation needs an authorized maintainer; staging requires an existing package and is not a first-package bootstrap. Historical releases are not republished.
|
|
386
400
|
|
|
387
401
|
```sh
|
|
388
|
-
curl -LO https://github.com/cloga/dsh-github-copilot/releases/download/v0.4.0-alpha.
|
|
389
|
-
curl -LO https://github.com/cloga/dsh-github-copilot/releases/download/v0.4.0-alpha.
|
|
402
|
+
curl -LO https://github.com/cloga/dsh-github-copilot/releases/download/v0.4.0-alpha.29/dsh-github-copilot-0.4.0-alpha.29.tgz
|
|
403
|
+
curl -LO https://github.com/cloga/dsh-github-copilot/releases/download/v0.4.0-alpha.29/SHA256SUMS
|
|
390
404
|
sha256sum --check SHA256SUMS
|
|
391
405
|
```
|
|
392
406
|
|
|
@@ -394,7 +408,7 @@ PowerShell can verify the same two downloaded files with:
|
|
|
394
408
|
|
|
395
409
|
```powershell
|
|
396
410
|
$expected = (Get-Content .\SHA256SUMS).Split()[0]
|
|
397
|
-
$actual = (Get-FileHash .\dsh-github-copilot-0.4.0-alpha.
|
|
411
|
+
$actual = (Get-FileHash .\dsh-github-copilot-0.4.0-alpha.29.tgz -Algorithm SHA256).Hash.ToLowerInvariant()
|
|
398
412
|
if ($actual -cne $expected) { throw 'Release checksum mismatch' }
|
|
399
413
|
```
|
|
400
414
|
|
package/README.zh.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
一个聚焦 GitHub Copilot 登录、通用账号模型发现、Copilot 专用 Tool 兼容与供应方托管搜索的 DSH companion。插件根据供应方返回的端点和能力元数据组装模型,复用公开的 `@deepseek-ai/dsh-llm-pi-ai` adapter 与 pi-ai SDK,不另写一套通用传输/序列化器,也不维护需要逐个添加新模型 ID 的静态目录。
|
|
11
11
|
|
|
12
|
-
> 下文自动维护账号模型元数据与 provider 集成控件描述目标版本 `0.4.0-alpha.
|
|
12
|
+
> 下文自动维护账号模型元数据与 provider 集成控件描述目标版本 `0.4.0-alpha.29`;这不代表已有的两条真实路由被合并或移除。版本化 URL 不表示 Release 已发布或本机已加载;仅在该 Release 与校验和可用后使用安装命令。源码、发布制品、已安装版本和实际加载运行时需分别确认,本地升级和中断会话的重启仍需用户批准。
|
|
13
13
|
|
|
14
14
|
Alpha.24 修复 Web search 卡片缺少精确 Remote 依赖声明的问题。卡片仍位于 **Settings → Models**(`settings.models.footer`,list/root),旧 Core 回退到独立 Web search section,而非 General。搜索子 Fiber 独立等待 routing namespace,不影响账号控件和既有搜索安全检查;实际打包 Desktop 验收仍是独立关卡。
|
|
15
15
|
|
|
@@ -76,7 +76,7 @@ node package/scripts/check-search-composition.mjs --profile-dir /absolute/profil
|
|
|
76
76
|
获准且网络可用时,可通过受支持的 CLI 命令安装:
|
|
77
77
|
|
|
78
78
|
```sh
|
|
79
|
-
dsh plugin --profile web add https://github.com/cloga/dsh-github-copilot/releases/download/v0.4.0-alpha.
|
|
79
|
+
dsh plugin --profile web add https://github.com/cloga/dsh-github-copilot/releases/download/v0.4.0-alpha.29/dsh-github-copilot-0.4.0-alpha.29.tgz
|
|
80
80
|
```
|
|
81
81
|
|
|
82
82
|
若 registry 被公司封禁或不可用,不要更换网络绕行。Desktop 管理的 profile 可以改用[受控离线 CLI 流程](./docs/npm-distribution.md#controlled-offline-cli-maintenance):使用来源获准、校验通过的本地 Release 和已有依赖缓存(`--offline --ignore-scripts`)。预检、备份和授权要求仍然适用。
|
|
@@ -141,7 +141,7 @@ Agent 应把浏览器授权视为需要用户完成的 handoff,而不是自行
|
|
|
141
141
|
5. 确认 **Signed in** 并检查自动发现结果,再请用户选择模型。已登录时打开 Models 会自动确保缺失/过期元数据,新鲜 ready 缓存不发请求。错误可使用 **Retry**,有意强制更新时使用 **Manage → Refresh models**,不作为常规设置步骤。状态读取本身不发现;登录、元数据与真实调用成功是独立证据。
|
|
142
142
|
6. 只有用户明确要求断开账号时才使用 **Sign out**;它会删除 Copilot credential record,但保留 route settings。
|
|
143
143
|
|
|
144
|
-
每个新版本默认同时分发到 GitHub Releases 和 npm,两个渠道使用同一份已验证 tarball。应固定版本并核对所用渠道的证据:Release 的 `SHA256SUMS`;从 npm 安装时另核对 `dist.integrity`。在获准且可用的 registry 网络环境中,优先使用原生 Desktop 包管理器;确认 npm 发布后,它接受 `dsh-github-copilot@0.4.0-alpha.
|
|
144
|
+
每个新版本默认同时分发到 GitHub Releases 和 npm,两个渠道使用同一份已验证 tarball。应固定版本并核对所用渠道的证据:Release 的 `SHA256SUMS`;从 npm 安装时另核对 `dist.integrity`。在获准且可用的 registry 网络环境中,优先使用原生 Desktop 包管理器;确认 npm 发布后,它接受 `dsh-github-copilot@0.4.0-alpha.29`,不是 URL 或本地文件。Desktop 管理的 profile 也允许经明确授权的[受控离线 CLI 维护](./docs/npm-distribution.md#controlled-offline-cli-maintenance):使用已验证的本地 Release 和 `--offline --ignore-scripts`,执行必需的组合预检、私密元数据备份、单写入者控制及安装后差异核验。缓存不足或出现权限拒绝时停止,不绕过公司 registry 封禁,不关闭 TLS 校验;重启仍需单独授权。离线安装成功不表示 npm 联网或发布问题已修好。[双渠道发布与 OIDC 要求](./docs/npm-distribution.md)保持不变。
|
|
145
145
|
|
|
146
146
|
不需要运行 `copilot2api`,不需要外部 gateway、placeholder API key、原始 GitHub token 或单独安装 `dsh-web-search-provider`。
|
|
147
147
|
|
|
@@ -162,7 +162,7 @@ DSH Core 继续负责模型选择、sandbox、工具、附件与其它 provider
|
|
|
162
162
|
|
|
163
163
|
在 **设置 → 模型 → 模型分工** 中启用双模型会话,选择账号下可用的主模型和执行模型,保存全局设置(同一配置档案内通用,不按工作区保存)。保存不需要工作区;**用此配置新建会话** 使用应用当前工作区,并只读显示目标。没有当前工作区时须先打开工作区,不再提供独立下拉框,也不会默认选择第一个或最近的工作区。主模型负责规划与验收;`copilot_execute` 创建原生可继续执行的子代理,并固定其执行模型。默认关闭,仅专用入口创建的新会话采用此策略;不修改全局默认、已有会话、登录凭据或原生 Subagent 授权开关。
|
|
164
164
|
|
|
165
|
-
模型不可用时明确报错,不自动替换。创建结果不明时重试同一个请求,不为绕过未知结果另建会话。功能依赖公开的会话、策略和子代理能力;缺少接口时显示不可用,不把历史版本的包兼容范围当成此功能的全面验收。详见[配置、生命周期、限制与验证范围](./docs/dual-model.md)。本功能包含在 `0.4.0-alpha.
|
|
165
|
+
模型不可用时明确报错,不自动替换。创建结果不明时重试同一个请求,不为绕过未知结果另建会话。功能依赖公开的会话、策略和子代理能力;缺少接口时显示不可用,不把历史版本的包兼容范围当成此功能的全面验收。详见[配置、生命周期、限制与验证范围](./docs/dual-model.md)。本功能包含在 `0.4.0-alpha.29` candidate 中,源码和合成测试不代表已发布或当前 Desktop 已生效。
|
|
166
166
|
|
|
167
167
|
若卡片显示 **Could not load model roles(无法加载模型分工)**,不要通过修改默认模型绕过:这是设置加载失败,与能力不支持或模型不可用不同。尤其 `githubCopilotDualModel/view` 返回 HTTP 404,表示 Host Remote 未暴露,并非功能开关处于关闭状态。详见[加载故障排查与验证](./docs/dual-model.md#loading-and-remote-troubleshooting)。
|
|
168
168
|
|
|
@@ -234,7 +234,7 @@ Grant 写入或复用前,Host normalizer 只会把 pi-ai 文档化的 `type`
|
|
|
234
234
|
|
|
235
235
|
## Hosted search
|
|
236
236
|
|
|
237
|
-
`auto` 模式的原生搜索身份来自捕获的发起 Session 有效 request-header/config 或显式 `GenerateOptions
|
|
237
|
+
`auto` 模式的原生搜索身份来自捕获的发起 Session 有效 request-header/config 或显式 `GenerateOptions`,绝不使用未来全局聊天默认值;固定/兜底 Copilot 搜索则在 Provider 内部根据当前账号元数据解析执行模型,同时保留非空的显式 `github-copilot.searchModel` 覆盖值;不会借用 Chat 模型或另一个 Session 的选择。Core `Agent.options` 仍是激活时的 seed;模型选择覆盖 request/assembly,有效配置在工具调用前记录到 `Session.requestHeader().config`。没有可证明的发起 owner 时,传统搜索不可用。新模型已选择但下一次请求尚未开始时,不能把旧 header 当作当前 prompt 指引。按 owner 隔离的 plan 缓存保留不同模型 Session 的独立性;真实托管搜索冷启动时先非强制确保共享账号元数据,再派生模型事实并检查既有账号/协议/allowlist/probe。显式带标记的 `GenerateOptions` 仍可绑定符合条件的 inline 请求,没有 owner 时可不缓存,但保留所有既有检查。
|
|
238
238
|
|
|
239
239
|
**凭据变化限制:**初次惰性元数据发现期间出现 OAuth 通知时,现有公开状态无法区分发现自身的 token 轮换与外部换号。该次搜索会在 probe/wire 前以 `WEB_PROVIDER_UNAVAILABLE` 保守失败;之后用户/driver 可重新请求并使用已刷新的凭据,不自动重试,也不承诺首次刷新无缝成功。
|
|
240
240
|
|
|
@@ -249,14 +249,15 @@ Grant 写入或复用前,Host normalizer 只会把 pi-ai 文档化的 `type`
|
|
|
249
249
|
|
|
250
250
|
**设置 → 模型**下新增独立的 **Web search** 卡片;旧版 Core 没有 Models footer 时,使用独立的 **设置 → Web search** 分区。策略由本插件的 `github-copilot-search-routing` 命名空间持有,不占用 Core 通用命名空间;卸载本插件后恢复原 web 服务。
|
|
251
251
|
|
|
252
|
-
**Search provider** 主选择器提供 **Auto — follow Chat** 和通过路由外观层实际注册的搜索 Provider;**
|
|
252
|
+
**Search provider** 主选择器提供 **Auto — follow Chat** 和通过路由外观层实际注册的搜索 Provider;**Fallback provider**(兜底后端)使用同一目录,额外提供 **None — no fallback**。选择项代表搜索后端,不代表单个模型:即使多个账号模型可以执行搜索,Copilot 仍然只有一个搜索后端。普通配置只需选择这两个 Provider,不再要求另选搜索模型。
|
|
253
253
|
|
|
254
254
|
- `github-copilot-search-routing.searchProvider: auto` 跟随发起 Chat 的 Provider。本插件自有 Copilot 别名保留既有 owner 和模型能力检查;其他 Chat Provider 的原始 ID 必须精确匹配已注册的搜索 Provider ID,不猜名字、后缀或模型家族。这是路由约定,不承诺独立注册的后端一定使用相同模型或账号。
|
|
255
255
|
- 将 `searchProvider` 设为具体 ID,就固定主搜索后端,不再随 Chat 改变。
|
|
256
256
|
- `defaultSearchProvider` 仅在无匹配主后端或主搜索失败时作最终兜底,最多尝试一次;与主后端相同时不重试,成功但结果为空也不触发兜底。`none` 仅关闭兜底,不关闭主搜索。
|
|
257
|
-
- 显式选择 Copilot
|
|
257
|
+
- 显式选择 Copilot 或将它作为兜底时,内部按模型 ID 排序,从当前账号路由事实中最多考虑三个符合条件的 Responses 候选。默认要求能力 probe 成功后才发送一次用户的最终查询;元数据本身不是能力证明,最终查询失败也不会跨模型重放。内部选择不改变 Chat 或全局默认模型。其他后端自行管理模型配置(若有)。
|
|
258
|
+
- 已保存的非空 `github-copilot.searchModel` 仍具有优先权;覆盖值无效时不会静默换成其他模型。只读详情提供独立、显式的恢复自动选择操作(`searchModel: ''`);保存 Provider 路由绝不修改该覆盖值。
|
|
258
259
|
|
|
259
|
-
旧 `searchMode: auto/fixed` 配置继续兼容读取,不自动写入。旧 fixed 保留原 default 作为主后端;fixed 加 `none`
|
|
260
|
+
旧 `searchMode: auto/fixed` 配置继续兼容读取,不自动写入。旧 fixed 保留原 default 作为主后端;fixed 加 `none` 继续禁用。用户明确保存后,通过一次带修订号校验的 mutation 同时写入两个路由键,不依赖 Copilot 设置命名空间,也不读取账号/模型列表。稳定的 Remote 引用避免外层页面重渲染重置草稿。发生修订冲突时,应重新加载已保存配置并重新应用所需选择;拒绝或未确认的响应不会被报告为成功。保存只证明配置持久化,不证明真实搜索能力。界面会说明保存将采用选中的最终兜底并可能产生 API 费用;旧的 `github-copilot.searchFallback: none` 失败兜底付费限制保留到明确保存新选择为止。已保存但未注册的 ID 保持显示为不可用,不静默替换。
|
|
260
261
|
|
|
261
262
|
`github-copilot.routeWebSearch: false` 仍委托原始 web 服务。其余情况下,取消、卸载及捕获的账号证明失效都不能触发兜底。通用注册后端必须遵守取消信号,但公开接口没有提供其内部鉴权后、网络发送前的检查钩子;历史 Copilot/DeepSeek 直调路径保留更强的自有发送前保护。两条路径都不会用 Copilot 登录替其他 Provider 提供凭据。
|
|
262
263
|
|
|
@@ -284,6 +285,16 @@ Responses 解析器会保留公开的 `reasoning_summary_text`、`reasoning_text
|
|
|
284
285
|
|
|
285
286
|
此可选集成使用公开的 `conversation.chat.node` keyed slot 与 `uiConversation` location data。检查会核对当前名为 `AssistantNodeView` 的简单 memo 渲染器;未来改名或压缩后不匹配时保留原样。这是兼容检查,不是模块所有权或安全证明:公开注册器无法区分故意使用相同名称和元数据的替代实现。该集成不会因旧版 Core 缺少它们而阻塞登录。扩展接口缺失、不兼容或存在其他 assistant renderer 时,保留原生输出并给出命名明确的兼容诊断。新增显示行为不代表任何账号模型的真实 transport 已验证;不支持该接口的 Core 仍可能显示空 Think。它不会修改只控制 hosted search 的 `github-copilot.enabled` 设置。
|
|
286
287
|
|
|
288
|
+
## 托管请求预算与 compact
|
|
289
|
+
|
|
290
|
+
托管的 `github-copilot-preview` 路由在模型发送前估算完整原生请求,包括当前 system/工具定义,并分别检查独立输入上限及输入+输出总容量。实际输入预算为 `min(已提供的输入上限, 总容量 − 请求或默认输出预留) − 安全余量`,不把真实模型容量替换成预算数字。输出配置无效或完全没有输入空间时明确失败,不静默删历史、不自动换模型。
|
|
291
|
+
|
|
292
|
+
对于有原生 agent-loop 标记、发起 Session 与已记录请求配置一致、具备 token meter 且官方自动压缩已启用的普通请求,插件在预算的默认 90% 处发出本地估算压力信号。由 Core 执行原有的有界压缩、校验及请求重建,不在已冻结的请求中并发压缩。缺少可选接口时只关闭提前信号,最终原生预算检查仍保留;尊重 `auto: false` 和官方 overflow 重试次数为零的设置。不影响用户自有 canonical 路由或其他供应方。
|
|
293
|
+
|
|
294
|
+
`purpose: 'compaction'` 的摘要调用绕过提前压力阈值,只检查完整硬预算。没有调用方或适配器已解析的思考等级时,`prefer-low` 从已支持的能力中选择 `minimal` 或 `low`;没有此能力则保持供应方默认。显式或已解析的等级优先。摘要请求的输出上限不被偷偷改写,保持 Core 辅助摘要记录一致;也不会将截断输出当成成功 checkpoint。`enabled` 仍仅控制 hosted search。
|
|
295
|
+
|
|
296
|
+
**这不保证救回已经超限的旧历史。** 手动 compact 仍可能超过硬预算,此时在模型发送前明确拒绝;输出截断保留为独立的原生 `max-tokens` 结果。本次不增加分块摘要、静默删除历史、自动切换模型或新的重试循环。必要时通过官方压缩配置选择合适的摘要模型/输出上限,不反复提交同一个不可能完成的请求。详见[实现与验收边界](./docs/copilot-compaction.md)。
|
|
297
|
+
|
|
287
298
|
## Copilot Tool 兼容
|
|
288
299
|
|
|
289
300
|
为避免已观察到的无效 Copilot Tool payload,本包会把托管 route 的 `compat.supportsStrictMode` 叶节点设为 `false`,并在所选 provider 为 `github-copilot`,或已确认由本插件挂载的 `github-copilot-preview` 时执行两项仅作用于 Schema 的修复:从 Tool Schema 顶层删除 `sandbox_permissions` 与 `justification`,并把 Core 的多动作 `update_goal` 参数改写为带判别字段的 `oneOf`。这样每种 Goal action 只暴露合法字段:`complete`、`pause`、`resume` 不会携带编辑或阻塞字段,`blocked` 必须提供 `blocked_reason`,只有 `edit` 暴露替换字段。执行仍使用 Core 原本的 Goal Tool 与 Service。非 Copilot prompt assembly 完全不变。
|
|
@@ -299,12 +310,15 @@ Copilot Session 如需更宽的文件或命令权限,必须在调用前选择
|
|
|
299
310
|
|
|
300
311
|
## 设置
|
|
301
312
|
|
|
302
|
-
插件 `github-copilot` settings section
|
|
313
|
+
插件 `github-copilot` settings section 控制账号元数据新鲜度、托管请求预算与 hosted search;`enabled` 仍只控制 hosted search:
|
|
303
314
|
|
|
304
315
|
| 键 | 默认值 | 作用范围与含义 |
|
|
305
316
|
|---|---:|---|
|
|
306
317
|
| `accountModelTtlMs` | `86400000` | 最大账号元数据复用窗口,毫秒(24 小时);不延长凭据或 proof 有效期。 |
|
|
307
318
|
| `accountModelFailureCooldownMs` | `300000` | 非强制发现的失败冷却,毫秒(5 分钟);不设周期重试。 |
|
|
319
|
+
| `requestBudgetSafetyTokens` | `4096` | 非负安全整数的估算输入余量;增加会减少可用输入空间。 |
|
|
320
|
+
| `requestBudgetPressureRatio` | `0.9` | 提前压力比例,0.01–1、步长 0.01;仅在官方自动恢复已启用且接口可用时使用。 |
|
|
321
|
+
| `compactionReasoning` | `prefer-low` | 摘要等级缺省时选择已支持的 minimal/low;`preserve` 保留原生默认。 |
|
|
308
322
|
| `enabled` | `true` | 启用两种 hosted-search 表面。 |
|
|
309
323
|
| `providers` | `[]` | 两种表面的可选 route allowlist;空值跟随发起 route。保留已有非空列表;旧 ID 改为 `github-copilot-preview` 须由 Ops 显式审核。 |
|
|
310
324
|
| `includeSources` | `true` | Inline 路径请求供应方引用;`ctx.web` bridge 始终请求并返回 sources。 |
|
|
@@ -317,7 +331,7 @@ Copilot Session 如需更宽的文件或命令权限,必须在调用前选择
|
|
|
317
331
|
|
|
318
332
|
### 能力与公开接口限制
|
|
319
333
|
|
|
320
|
-
- 发现数据分别保留 context、input 和 output
|
|
334
|
+
- 发现数据分别保留 context、input 和 output 限额;`INPUT_LIMIT_ESTIMATED_GUARD` 表示托管路由已启用插件所有的估算输入检查。它不是供应方精确 token 计数,也不表示 Core 接口已经支持独立输入上限;服务端仍可能拒绝请求。插件不会把真实 context 容量偷换成 input 预算,也不会为了补齐它去改 Core。
|
|
321
335
|
- 不可映射的思考标签以 `REASONING_EFFORTS_UNSUPPORTED` 报告,不声称对应控制已生效。能力警告不等于整个模型被拒绝。
|
|
322
336
|
- 文档中未定价的模型成本元数据不代表实际免费,计费仍以供应方为准。
|
|
323
337
|
- 普通对话使用 native `streamSimple` 的三协议路径;面向 Core 的高级协议专用 `stream` 接口明确不支持跨 SDK 客户端混用。不能仅凭类型检查或普通流式成功推断高级接口也可用。
|
|
@@ -333,7 +347,7 @@ Copilot Session 如需更宽的文件或命令权限,必须在调用前选择
|
|
|
333
347
|
- **Canonical 状态为 `not-configured`:**已登录时属于正常单托管路由模式;账号发现就绪与否另行检查,不需要创建原生 profile。
|
|
334
348
|
- **删除对话框一直显示 “Deleting…”:**本次改动不证明该卡住问题已修复。不要重复删除;取得许可停止 Host 后检查持久化设置,按迁移指南判断是否仍需移除。
|
|
335
349
|
- **没有 Think 文字:**供应方可能不返回公开摘要,但非空摘要应被完整保留。检查思考强度与命名错误。UI 只在完成后隐藏空条目,不显示加密回放;包含 reasoning/replay 的历史走 Core 原生 transport。
|
|
336
|
-
- **Hosted search
|
|
350
|
+
- **Hosted search 不可用:**显式/兜底 Copilot 应检查账号发现与 probe 诊断,普通设置不再要求手选搜索模型。旧覆盖值在明确恢复自动选择前仍具有优先权。Auto 跟随 Copilot Chat 时仍要求发起模型支持搜索。自定义 inline 仅适用于仍配置的旧 canonical 路由;保存 Provider 选择或普通聊天成功不能证明搜索可用。
|
|
337
351
|
- **仍有旧 endpoint/key:**reconciliation 有意保留非本包所有的字段;按显式迁移审核,不要强删所有权 marker。
|
|
338
352
|
|
|
339
353
|
## Package 入口与源码映射
|
|
@@ -396,8 +410,8 @@ node scripts/agent.mjs attribution "DeepSeek Harness (DSH)"
|
|
|
396
410
|
`package.json` 声明公开 npm 分发。Release tag 必须严格等于 `v${package.json.version}`。预发布使用 `alpha`、`beta` 或 `rc` 及对应 npm dist-tag,只有稳定版使用 `latest`。Release workflow 执行 frozen install 和完整门禁,只打包一次(重试恢复原始归档),验证 `SHA256SUMS`,发布不可变 GitHub Release,再通过 OIDC 将同一份字节发布到 npm。任一渠道失败都表示交付未完成。首次建包须由获准环境中的维护者完成;staging 要求包已存在,不能代替首次建包。不会批量补发历史版本。
|
|
397
411
|
|
|
398
412
|
```sh
|
|
399
|
-
curl -LO https://github.com/cloga/dsh-github-copilot/releases/download/v0.4.0-alpha.
|
|
400
|
-
curl -LO https://github.com/cloga/dsh-github-copilot/releases/download/v0.4.0-alpha.
|
|
413
|
+
curl -LO https://github.com/cloga/dsh-github-copilot/releases/download/v0.4.0-alpha.29/dsh-github-copilot-0.4.0-alpha.29.tgz
|
|
414
|
+
curl -LO https://github.com/cloga/dsh-github-copilot/releases/download/v0.4.0-alpha.29/SHA256SUMS
|
|
401
415
|
sha256sum --check SHA256SUMS
|
|
402
416
|
```
|
|
403
417
|
|
|
@@ -405,7 +419,7 @@ PowerShell 可以对已下载的同一组文件执行:
|
|
|
405
419
|
|
|
406
420
|
```powershell
|
|
407
421
|
$expected = (Get-Content .\SHA256SUMS).Split()[0]
|
|
408
|
-
$actual = (Get-FileHash .\dsh-github-copilot-0.4.0-alpha.
|
|
422
|
+
$actual = (Get-FileHash .\dsh-github-copilot-0.4.0-alpha.29.tgz -Algorithm SHA256).Hash.ToLowerInvariant()
|
|
409
423
|
if ($actual -cne $expected) { throw 'Release checksum mismatch' }
|
|
410
424
|
```
|
|
411
425
|
|
package/deployment-baseline.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
},
|
|
9
9
|
"package": {
|
|
10
10
|
"name": "dsh-github-copilot",
|
|
11
|
-
"version": "0.4.0-alpha.
|
|
11
|
+
"version": "0.4.0-alpha.29"
|
|
12
12
|
},
|
|
13
13
|
"evidence": {
|
|
14
14
|
"kind": "source-and-synthetic-test-inventory",
|
|
@@ -167,7 +167,7 @@
|
|
|
167
167
|
"standaloneNpmArtifacts": "not-tested",
|
|
168
168
|
"managedProviderValidation": "synthetic-tagged-source-runtime",
|
|
169
169
|
"resolvedProfileDiagnostics": "plugin-owned-empty-modelErrors",
|
|
170
|
-
"runtimeTests": ["tests/preview-route.spec.ts", "tests/published-core.spec.ts", "tests/single-route.spec.ts", "tests/search-routing.spec.ts", "tests/routed-web.spec.ts", "tests/deepseek-search-fallback.spec.ts", "tests/tool-schema-compat.spec.ts", "tests/fixtures/alpha2-contracts-core.fixture.ts", "tests/remote-codec.spec.ts", "tests/dual-model-projection.spec.ts", "tests/fixtures/session-context-core.fixture.ts", "tests/fixtures/remote-core.fixture.ts"]
|
|
170
|
+
"runtimeTests": ["tests/preview-route.spec.ts", "tests/published-core.spec.ts", "tests/single-route.spec.ts", "tests/search-routing.spec.ts", "tests/routed-web.spec.ts", "tests/deepseek-search-fallback.spec.ts", "tests/tool-schema-compat.spec.ts", "tests/fixtures/alpha2-contracts-core.fixture.ts", "tests/fixtures/compaction-pressure-core.fixture.ts", "tests/remote-codec.spec.ts", "tests/dual-model-projection.spec.ts", "tests/fixtures/session-context-core.fixture.ts", "tests/fixtures/remote-core.fixture.ts"]
|
|
171
171
|
}
|
|
172
172
|
],
|
|
173
173
|
"packages": [
|
|
@@ -284,6 +284,34 @@
|
|
|
284
284
|
{"file": "tests/routed-web-loader.spec.ts", "name": "loads the built facade and delegate entries without changing official tools"}
|
|
285
285
|
]
|
|
286
286
|
},
|
|
287
|
+
{
|
|
288
|
+
"id": "provider-only-search-settings",
|
|
289
|
+
"required": true,
|
|
290
|
+
"evidenceScope": "pinned-settings-and-client-contracts-plus-synthetic-routing-no-live-save-claim",
|
|
291
|
+
"sourceMarkers": [
|
|
292
|
+
{"file": "src/client.ts", "marker": "const settings = ctx.remote.settings"},
|
|
293
|
+
{"file": "src/client.ts", "marker": "const routing = ctx.remote.githubCopilotSearchRouting"},
|
|
294
|
+
{"file": "src/web-search-routing-card.ts", "marker": "Fallback provider"},
|
|
295
|
+
{"file": "src/web-search-routing-card.ts", "marker": "data-dsh-copilot-search-reset"},
|
|
296
|
+
{"file": "src/index.ts", "marker": "function configuredCandidates(cfg: InlineConfig)"}
|
|
297
|
+
],
|
|
298
|
+
"tests": [
|
|
299
|
+
{"file": "tests/web-search-routing-card.spec.ts", "name": "saves Copilot as %s with one routing write and no model prerequisite"},
|
|
300
|
+
{"file": "tests/web-search-routing-card.spec.ts", "name": "does not rewrite a legacy model override when saving provider routing"},
|
|
301
|
+
{"file": "tests/web-search-routing-card.spec.ts", "name": "never loads account model suggestions to display or save providers"},
|
|
302
|
+
{"file": "tests/web-search-routing-card.spec.ts", "name": "resets a legacy override only through an explicit separate action"},
|
|
303
|
+
{"file": "tests/web-search-routing-card.spec.ts", "name": "explains a real Remote settings-conflict without exposing its raw details"},
|
|
304
|
+
{"file": "tests/client-search-inject.spec.ts", "name": "keeps real mounted drafts and pending saves through parent rerenders (footer=%s)"},
|
|
305
|
+
{"file": "tests/scripts/search-settings-contract.test.mjs", "name": "real pinned Client namespace lookups require stable capture across render calls"},
|
|
306
|
+
{"file": "tests/scripts/search-settings-contract.test.mjs", "name": "provider-only search routing saves both leaves once without a Copilot namespace or model"},
|
|
307
|
+
{"file": "tests/scripts/search-settings-contract.test.mjs", "name": "stale routing revisions fail CAS and preserve the last successful settings"},
|
|
308
|
+
{"file": "tests/scripts/search-settings-contract.test.mjs", "name": "hidden legacy searchModel is writable and accepts an explicit empty reset"},
|
|
309
|
+
{"file": "tests/scripts/search-settings-contract.test.mjs", "name": "pinned generated Client mutate codecs accept routing ops and a flat namespace revision"},
|
|
310
|
+
{"file": "tests/inline/apply.spec.ts", "name": "automatically resolves account-owned Responses candidates for %s without a search model"},
|
|
311
|
+
{"file": "tests/inline/apply.spec.ts", "name": "bounds automatic proof to three eligible candidates in deterministic id order"},
|
|
312
|
+
{"file": "tests/inline/apply.spec.ts", "name": "does not discover or probe allowlist-excluded automatic search"}
|
|
313
|
+
]
|
|
314
|
+
},
|
|
287
315
|
{
|
|
288
316
|
"id": "explicit-deepseek-search-fallback",
|
|
289
317
|
"required": true,
|
|
@@ -301,6 +329,25 @@
|
|
|
301
329
|
{"file": "tests/deepseek-search-fallback.spec.ts", "name": "checks continuity after native literal-key auth (permitted=%s)"}
|
|
302
330
|
]
|
|
303
331
|
},
|
|
332
|
+
{
|
|
333
|
+
"id": "managed-request-budget-and-compaction-policy",
|
|
334
|
+
"required": true,
|
|
335
|
+
"activation": "account-bound-estimated-admission-and-optional-stock-recovery",
|
|
336
|
+
"sourceMarkers": [
|
|
337
|
+
{"file": "src/request-budget.ts", "marker": "calculateRequestBudget"},
|
|
338
|
+
{"file": "src/compaction-pressure.ts", "marker": "installCopilotCompactionPressure"},
|
|
339
|
+
{"file": "src/preview-route.ts", "marker": "COPILOT_CONTEXT_BUDGET_EXCEEDED"},
|
|
340
|
+
{"file": "src/preview-provider.ts", "marker": "inspectRequest"}
|
|
341
|
+
],
|
|
342
|
+
"tests": [
|
|
343
|
+
{"file": "tests/preview-route.spec.ts", "name": "rejects independent input overflow before model wire, prepared=%s"},
|
|
344
|
+
{"file": "tests/preview-route.spec.ts", "name": "reserves the requested output separately from the independent prompt ceiling"},
|
|
345
|
+
{"file": "tests/preview-route.spec.ts", "name": "uses supported low effort for compaction only without rewriting its output cap"},
|
|
346
|
+
{"file": "tests/preview-route.spec.ts", "name": "refuses an already oversized manual summary without sending or truncating its history"},
|
|
347
|
+
{"file": "tests/preview-route.spec.ts", "name": "keeps output truncation distinct from context overflow and successful summary output"},
|
|
348
|
+
{"file": "tests/preview-route.spec.ts", "name": "isolates concurrent chat success from a rejected compaction admission"}
|
|
349
|
+
]
|
|
350
|
+
},
|
|
304
351
|
{
|
|
305
352
|
"id": "account-driven-provider-metadata",
|
|
306
353
|
"required": true,
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Managed Copilot compaction budgets
|
|
2
|
+
|
|
3
|
+
Tracking: [#146](https://github.com/cloga/dsh-github-copilot/issues/146). This is a plugin-only implementation; publication, loaded-runtime state and live-provider acceptance remain separate evidence.
|
|
4
|
+
|
|
5
|
+
## Why two protections are needed
|
|
6
|
+
|
|
7
|
+
The motivating session recorded both `summarization truncated at the token cap (incomplete checkpoint)` and later HTTP 400 input-context overflow in automatic/manual compaction. A successful summary after an explicit model change used 7575 output tokens under an 8192-token cap. These observations do not establish hidden reasoning consumption, either model's contemporaneous capacity, or that simply changing the cap solves the problem.
|
|
8
|
+
|
|
9
|
+
The managed account catalog already retains three different facts: combined context capacity C, independent prompt ceiling I when supplied, and output capability O. Previously I produced a warning only. Stock Core exposes C and triggers normal pressure relative to C; that does not independently enforce I.
|
|
10
|
+
|
|
11
|
+
## Budget admission
|
|
12
|
+
|
|
13
|
+
`request-budget.ts` resolves validated operational policy without mutating catalog metadata:
|
|
14
|
+
|
|
15
|
+
```text
|
|
16
|
+
R = explicit requested output cap, otherwise advertised output capability O
|
|
17
|
+
hard input limit = min(I when supplied, C - R) - safetyTokens
|
|
18
|
+
pressure input limit = floor(hard input limit * pressureRatio)
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
An independent input ceiling does not include output, so output is subtracted from C, not twice from I. Missing I does not mean unlimited combined context. If catalog context was conservatively derived from prompt-only metadata, it retains that existing interpretation; the plugin does not invent an unadvertised larger combined capacity.
|
|
22
|
+
|
|
23
|
+
Invalid/nonpositive model capacities, invalid output caps, caps above O and nonpositive headroom fail explicitly. Impossible policy headroom is `INVALID_REQUEST`, not a request to compact an arbitrarily small history. An input estimate above a valid budget becomes `CONTEXT_WINDOW_EXCEEDED` with a plugin-owned, numeric diagnostic. This is a local estimated admission decision, not a fabricated provider rejection.
|
|
24
|
+
|
|
25
|
+
Final admission happens at the native provider boundary after Core conversion, before model transport. It uses the larger of native usage-anchored estimation and fresh current system/tool/message estimation, so a tiny historical usage anchor cannot hide a newly enlarged fixed prefix. Images and opaque native replay retain native representation and estimation; neither is decrypted, reconstructed or discarded. Token estimation is heuristic, not the provider's exact tokenizer. Safety allowance and genuine provider failure handling remain necessary.
|
|
26
|
+
|
|
27
|
+
The pinned SDK already has its own context-dependent output clamp. This plugin preserves the caller's requested cap rather than introducing another hidden rewrite. No second generic serializer, account-model table, credential lifecycle or native protocol transport is added.
|
|
28
|
+
|
|
29
|
+
## Earlier pressure and transaction ownership
|
|
30
|
+
|
|
31
|
+
The public `llm/stream` listener sees a committed, frozen loop request. It requires:
|
|
32
|
+
|
|
33
|
+
- The exact plugin-owned managed route and an ordinary marked agent-loop call, not an auxiliary purpose.
|
|
34
|
+
- The public initiating Agent, matching Session ID, and complete matching committed call configuration.
|
|
35
|
+
- Current account-bound descriptor/proof and a valid operational budget.
|
|
36
|
+
- Optional token meter and stock automatic compaction with a positive effective overflow-retry policy.
|
|
37
|
+
|
|
38
|
+
Only then does it emit one terminal local pressure error before dispatch. Official `agent/request-error` recovery owns pruning, balanced-span selection, compaction locks, source checks, durable shrink and bounded retry. The next request is rebuilt from the replaced surface. The plugin never compacts inside a frozen request then sends the stale request, changes the retry counter, or registers a competing compaction service.
|
|
39
|
+
|
|
40
|
+
Disabled auto recovery or zero retries are respected. Missing/mismatching optional capabilities delegate unchanged and can produce one bounded unavailability diagnostic; the hard native guard remains. Cancellation before iteration wins over pressure. There is no polling, automatic metadata refresh from the pressure listener, or whole-Session dump.
|
|
41
|
+
|
|
42
|
+
## Summary purpose policy
|
|
43
|
+
|
|
44
|
+
Official `GenerateOptions.purpose` permits adapter-specific generation policy. For `purpose: 'compaction'`, `prefer-low` selects supported `minimal`, otherwise supported `low`, only when no effort was supplied or materialized by Core/the configured native profile. Explicit and resolved defaults win; unsupported low controls preserve the provider default. `preserve` disables this purpose default. Normal conversations and other purposes keep their existing reasoning behavior.
|
|
45
|
+
|
|
46
|
+
The stock summary record takes its requested output cap from the owning compaction configuration. Therefore the plugin does not silently increase/decrease that cap in middleware or alter summary route identity. It preserves native `max-tokens` output truncation as failure, distinct from input overflow. Public summaries, encrypted replay and native stop reasons remain native-owned.
|
|
47
|
+
|
|
48
|
+
Each dispatch captures its own policy, descriptor lease and admission-failure state. SDK lazy-stream wrapping may retain only an exception's text; the outer adapter restores only the exact locally captured budget failure, never reclassifying unrelated auth/network errors by guesswork. Concurrent calls do not share mutable purpose or failure state, and cancellation/account invalidation still wins.
|
|
49
|
+
|
|
50
|
+
## Settings
|
|
51
|
+
|
|
52
|
+
All three keys belong to the existing `github-copilot` settings namespace:
|
|
53
|
+
|
|
54
|
+
| Key | Default | Contract |
|
|
55
|
+
| --- | --- | --- |
|
|
56
|
+
| `requestBudgetSafetyTokens` | 4096 | Non-negative safe integer; more allowance means less usable input. Lowering it trades away preventive headroom and does not change native SDK safeguards. |
|
|
57
|
+
| `requestBudgetPressureRatio` | 0.9 | 0.01 through 1, step 0.01, for eligible ordinary loop calls only. |
|
|
58
|
+
| `compactionReasoning` | `prefer-low` | Supported low-cost default for otherwise unspecified summary effort; `preserve` keeps existing defaults. |
|
|
59
|
+
|
|
60
|
+
The existing `enabled` switch remains hosted-search-only. These controls do not change global/default model selection, enable another account route, or transfer conversation data to another provider.
|
|
61
|
+
|
|
62
|
+
## Existing oversized history and recovery limits
|
|
63
|
+
|
|
64
|
+
This implementation is preventive, not a general rescue summarizer. A manual summary whose full input already exceeds the hard budget fails before model transport. It does not silently trim, fabricate a partial checkpoint, or claim that refusing the request recovered the history. Giant fixed prefixes or an indivisible latest unit can also prevent useful reduction.
|
|
65
|
+
|
|
66
|
+
Official configuration already supports a separate summary route and output cap. Selecting a suitable authorized route/cap is an explicit deployment choice, not an automatic fallback. Increasing the output cap consumes combined-context headroom; decreasing it can reproduce the observed incomplete-checkpoint failure.
|
|
67
|
+
|
|
68
|
+
Bounded chunk/merge rescue was evaluated but is not included here. The official BasicCompactionEngine subclass hook is a possible extension, but would require an explicit single-provider composition choice, complete multi-call audit records, bounded calls/output, tool-pairing preservation and transactional cancellation/failure tests. Do not add it through a transparent wire interceptor or label several calls as one auxiliary request. Core changes are not a prerequisite for this preventive release.
|
|
69
|
+
|
|
70
|
+
## Official-first evidence and retirement
|
|
71
|
+
|
|
72
|
+
Exact target: official `ddefc45fbc7f8e46dd73185e68295696d1297887` (`0.1.6-alpha.2`).
|
|
73
|
+
|
|
74
|
+
- [Model context and purpose contract](https://github.com/deepseek-ai/deepseek-harness/blob/ddefc45fbc7f8e46dd73185e68295696d1297887/packages/llm/llm/src/types.ts): combined context metadata and purpose-specific adapter policy.
|
|
75
|
+
- [Basic compaction](https://github.com/deepseek-ai/deepseek-harness/blob/ddefc45fbc7f8e46dd73185e68295696d1297887/packages/compaction/compaction-basic/src/index.ts): official pressure/overflow/manual paths and summary extension.
|
|
76
|
+
- [Summary owner](https://github.com/deepseek-ai/deepseek-harness/blob/ddefc45fbc7f8e46dd73185e68295696d1297887/packages/compaction/compaction-basic/src/summarizer.ts): request prefix, purpose, output cap and truncated-output refusal.
|
|
77
|
+
|
|
78
|
+
Support is partial: official transactional compaction is reused, while independent Copilot input admission and summary-purpose default policy remain companion-owned. Retire the corresponding companion component only after official behavior covers both input/output constraints, correct request identity, cancellation, purpose handling and equivalent regression/unchanged-runtime acceptance. Do not remove official recovery or falsify contextWindow to reduce the diff.
|
|
79
|
+
|
|
80
|
+
## Verification boundary
|
|
81
|
+
|
|
82
|
+
Pure arithmetic and policy tests, public-middleware fixtures, and the real published native adapter/SDK with synthetic transport cover separate layers. Required cases include independent/combined bounds, changed prefixes, explicit/default output and effort, metadata/credential invalidation, direct/prepared parity, concurrent calls, cancellation, output truncation and oversized manual input. Existing full plugin gates and exact-Core compatibility fixtures remain required; source inventory is not their execution result.
|
|
83
|
+
|
|
84
|
+
No live model inference, local Desktop installation, activation or restart is implied by unit tests or publication. Preserve immutable GitHub/npm byte identity and coordinate Desktop/Ops pins separately after release verification.
|
|
@@ -24,7 +24,7 @@ Follow the [plugin-only boundary](../AGENTS.md#plugin-only-implementation-bounda
|
|
|
24
24
|
|
|
25
25
|
## Explicit public-interface limits
|
|
26
26
|
|
|
27
|
-
- The published Core model-info contract exposes combined context capacity, not a separate prompt-token budget. The
|
|
27
|
+
- The published Core model-info contract exposes combined context capacity, not a separate prompt-token budget. The managed route retains truthful capacities and adds provider-scoped estimated admission (`INPUT_LIMIT_ESTIMATED_GUARD`), with optional earlier local pressure using existing stock recovery. This is not exact provider token counting or native dual-limit metadata support. Preserve explicit summary output caps and resolved reasoning; unsupported low-effort controls are not guessed. Already oversized manual summaries still fail without silent trimming or chunking. See [compaction budgets and acceptance boundaries](./copilot-compaction.md); no Core patch or false contextWindow is permitted.
|
|
28
28
|
- Advertised reasoning labels that the native SDK cannot express must show `REASONING_EFFORTS_UNSUPPORTED` rather than being silently hidden or guessed. Such a warning need not disable ordinary model requests.
|
|
29
29
|
- The Core-facing adapter integration uses the public `streamSimple` path. Its advanced protocol-specific `stream` entry must reject explicitly rather than accepting incompatible client objects from another SDK version. The event-stream compatibility boundary must verify the full public surface at compile time and preserve the original stream object.
|
|
30
30
|
- Cached catalog entries do not authorize requests independently. A change in the current grant's model-permission list invalidates old proofs even when the token and account identity are unchanged; a new server-enabled model absent from the earlier grant list remains discoverable without rewriting the grant.
|