@deepseek-ai/dsh-app-boot 0.2.0-rc.1 → 0.2.1-alpha.1
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/README.i18n.yaml +8 -8
- package/README.md +3 -4
- package/README.zh.md +3 -4
- package/lib/index.js +143 -40
- package/lib/types/index.d.ts +1 -1
- package/lib/types/package-meta.d.ts +10 -6
- package/lib/types/profile-resolution/resolver.d.ts +8 -5
- package/lib/types/profile-resolution/service.d.ts +12 -2
- package/lib/types/profile.d.ts +34 -2
- package/lib/worker/profile-resolution-bootstrap.js +2 -2
- package/package.json +19 -19
package/README.i18n.yaml
CHANGED
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
en: c4a301652b851ce9
|
|
34
34
|
zh: 784871e19cd9db0a
|
|
35
35
|
/deepseek-ai-dsh-app-boot/use-this-package/reading-plugin-display-metadata:
|
|
36
|
-
en:
|
|
37
|
-
zh:
|
|
36
|
+
en: 98ef2935171952c0
|
|
37
|
+
zh: 8c160bdeffd68b0f
|
|
38
38
|
/deepseek-ai-dsh-app-boot/use-this-package/startup-and-reload-failures:
|
|
39
39
|
en: 09890e218ab49c84
|
|
40
40
|
zh: e3d86597e7fb1adb
|
|
@@ -45,17 +45,17 @@
|
|
|
45
45
|
en: f4a2695cb4c8a570
|
|
46
46
|
zh: 89837235d2f376cf
|
|
47
47
|
/deepseek-ai-dsh-app-boot/understand-the-implementation/design-notes:
|
|
48
|
-
en:
|
|
49
|
-
zh:
|
|
48
|
+
en: 25a0d1b46fd66d68
|
|
49
|
+
zh: 5cd8b4ac382dccdc
|
|
50
50
|
/deepseek-ai-dsh-app-boot/understand-the-implementation/helper-behavior:
|
|
51
51
|
en: f7bc3a8dd4b00bdd
|
|
52
52
|
zh: 30098428aa769ad0
|
|
53
53
|
/deepseek-ai-dsh-app-boot/understand-the-implementation/source-map:
|
|
54
|
-
en:
|
|
55
|
-
zh:
|
|
54
|
+
en: 3da01827e3354655
|
|
55
|
+
zh: 06ccfaed83f65a76
|
|
56
56
|
/deepseek-ai-dsh-app-boot/further-exploration:
|
|
57
|
-
en:
|
|
58
|
-
zh:
|
|
57
|
+
en: 401269cc5ea8593e
|
|
58
|
+
zh: cd337c356b320565
|
|
59
59
|
/deepseek-ai-dsh-app-boot/model-experience:
|
|
60
60
|
en: 769777f1cb1a9408
|
|
61
61
|
zh: f02b2834179df50d
|
package/README.md
CHANGED
|
@@ -82,7 +82,7 @@ The projector preserves native omission behavior by checking literal defaults ag
|
|
|
82
82
|
|
|
83
83
|
### Reading plugin display metadata
|
|
84
84
|
|
|
85
|
-
Use `readPluginMeta(specifier, parentURL)` or `ctx.pluginPackages.metaOf(specifier, parentURL)` to read installed package display text without importing or activating the plugin. Lookup uses the complete package specifier and the caller's resolution base, respecting Node exports. File paths and file URLs return no metadata without resolving resources.
|
|
85
|
+
Use `readPluginMeta(specifier, parentURL)` or `ctx.pluginPackages.metaOf(specifier, parentURL)` to read installed package display text without importing or activating the plugin. Lookup uses the complete package specifier and the caller's resolution base, respecting Node exports. File paths and file URLs return no metadata without resolving resources. For a package-root specifier, missing locale fields fall back to the accessible `package.json`; a subpath specifier never reads a `package.json`. Malformed metadata returns an `error` diagnostic. Results retain translations for Client-side language selection. The reader also loads an image data URL, even when locale text is complete: a package root uses its manifest `icon`, or `<package>/icon` when that field is omitted; a subpath uses `<specifier>/icon`. An icon error preserves valid text alongside the diagnostic. See [Plugin display metadata](../../../docs/cookbook/adding-a-package.md#plugin-display-metadata) for the author format.
|
|
86
86
|
|
|
87
87
|
<a id="startup-and-reload-failures"></a>
|
|
88
88
|
### Startup and reload failures
|
|
@@ -135,7 +135,7 @@ This section explains how the outcomes above are realized and points at the code
|
|
|
135
135
|
- **Package metadata.** `ctx.pluginPackages.packageOf` locates the owning package without loading code or requiring an exported `package.json`; a subpath selects its package without validating that file. The installed runtime resolution owns selection even for a miss. Low-level embedders that install the service without one retain native lookup. Display metadata uses the separate entry-aware reader described above.
|
|
136
136
|
- **Two Loader builtins.** `mountRootInclude` registers `cordis:include` and `cordis:group` as Loader builtins: a group row gives one `isolate` realm to a provider and its consumers together, and an agent preset outside this workspace cannot resolve `@deepseek-ai/cordis-plugin-group` by name. Both load through the ambient module pipeline rather than the included tree's own specifier resolution.
|
|
137
137
|
- **Consumer-owned strictness.** Ordinary Loader groups keep successful siblings. App-boot applies the global required-entry policy after initial settlement; agent presets and dynamic multi-entry compositions own and dispose their separate Loader subtree when they require all-or-nothing setup. App-boot reads failed fibers to report their recorded errors and coalesces duplicate Loader rejection notifications through one process checkpoint.
|
|
138
|
-
- **One runtime resolution.** The installation-first and ordered-bundle breadth-first traversal produces the runtime table. Runtime resolution creates no links; runtime resolution entries occupy their package names at `$DSH_HOME/profiles/node_modules`, and every other name sees that directory as an ordinary ancestor. Profile load removes the `.dsh-module-fallback` projections that link-backend releases wrote into a profile; pnpm-installed packages stay. External bare targets selected by package `imports` use the same package order, while Node retains mapping, conditions, and exact target resolution. A complete successor may add package names and update linked-root membership atomically
|
|
138
|
+
- **One runtime resolution.** The installation-first and ordered-bundle breadth-first traversal produces the runtime table. Runtime resolution creates no links; runtime resolution entries occupy their package names at `$DSH_HOME/profiles/node_modules`, and every other name sees that directory as an ordinary ancestor. Profile load removes the `.dsh-module-fallback` projections that link-backend releases wrote into a profile; pnpm-installed packages stay. External bare targets selected by package `imports` use the same package order, while Node retains mapping, conditions, and exact target resolution. A complete successor may add package names, remove profile-scoped mappings and profile-local names, and update linked-root membership atomically; retained mappings keep their normalized directory, version, and scope. Installation anchors remain fixed; a profile mapping may change its declarer. [Plugin Manager](../plugin-manager/README.md) publishes successors after package operations ([decision](../../../.agents/notes/implemented/architecture/2026-09-30-profile-package-refresh-and-manifest-invalidation.md)).
|
|
139
139
|
- **Removing linked interception.** A successor may remove a linked root without restart. Directories outside all remaining roots use native lookup for subsequent requests, which may find a development copy or report a missing package. Existing module references and Node caches stay unchanged. Re-adding the same link name and target is allowed; pointing a previously published name at a different target is rejected even after removal ([generation rules](../../../.agents/notes/implemented/architecture/2026-09-09-profile-resolution-generations.md#immutable-generations)).
|
|
140
140
|
- **Application-owned profiles.** Application-owned profiles use the same runtime resolution. Links within the active profile directory, including pnpm store links, are not external roots even when the profile is outside the shared profiles tree. Resolution does not modify their `node_modules`; pnpm owns installed packages.
|
|
141
141
|
- **Owned Workers.** Worker build banners import `@deepseek-ai/dsh-app-boot/worker/profile-resolution-bootstrap` before bundled business code. Each Worker installs the structured-cloned runtime resolution in its own isolate. The bootstrap bundle has no static package imports. Source Worker entries retain their self-contained dependency closure, and third-party Workers receive no injection.
|
|
@@ -159,7 +159,6 @@ The exports each own one stage of the boot: config resolution and snapshot repla
|
|
|
159
159
|
| [`src/profile-sanitize.ts`](src/profile-sanitize.ts) | Profile patch backup and recovery bundle activation |
|
|
160
160
|
| [`src/config-schema/`](src/config-schema/) | Profile schema generation, discovery, native projection, and result types |
|
|
161
161
|
| [`src/profile-resolution/`](src/profile-resolution/) | Runtime resolver, package-metadata service, and built Worker bootstrap |
|
|
162
|
-
| — | No runtime invariant companion is published; one interception owns each runtime resolution. |
|
|
163
162
|
|
|
164
163
|
</details>
|
|
165
164
|
|
|
@@ -177,7 +176,7 @@ Read these pages when the package-level contract is not enough. They move from t
|
|
|
177
176
|
- [dsh-home-paths](../../util/home-paths/README.md) — the Harness-home resolver (`resolveDshHome`).
|
|
178
177
|
- [Configuration source ownership](../../../.agents/notes/implemented/architecture/2026-08-04-configuration-source-ownership.md) — why a discovered file may not decide bootstrap behavior.
|
|
179
178
|
- [Profile plugin bundles](../../../.agents/notes/implemented/architecture/2026-08-05-profile-plugin-bundles.md) — the profile and bundle composition design.
|
|
180
|
-
- [User-patch HMR tests](
|
|
179
|
+
- [User-patch HMR tests](tests/user-patches.spec.ts) — ownership of live-patch behavior and native filesystem delivery.
|
|
181
180
|
|
|
182
181
|
-----
|
|
183
182
|
|
package/README.zh.md
CHANGED
|
@@ -82,7 +82,7 @@ profile 导入插件前,DSH 会检查其 `peerDependencies` 中对 `@deepseek-
|
|
|
82
82
|
|
|
83
83
|
### 读取插件展示元信息
|
|
84
84
|
|
|
85
|
-
使用 `readPluginMeta(specifier, parentURL)` 或 `ctx.pluginPackages.metaOf(specifier, parentURL)` 读取已安装包的展示文本,无需导入或激活插件。查询使用完整包标识与调用方的解析基准,并遵循 Node exports。文件路径与文件 URL
|
|
85
|
+
使用 `readPluginMeta(specifier, parentURL)` 或 `ctx.pluginPackages.metaOf(specifier, parentURL)` 读取已安装包的展示文本,无需导入或激活插件。查询使用完整包标识与调用方的解析基准,并遵循 Node exports。文件路径与文件 URL 不解析资源,直接返回无元信息。包根标识缺失的 locale 字段回退到可访问的 `package.json`;子路径标识从不读取 `package.json`。格式错误的元信息返回 `error` 诊断。结果保留翻译,由 Client 选择语言。即使 locale 文本完整,读取器也会加载图片 data URL:包根使用清单 `icon`,省略该字段时使用 `<包名>/icon`;子路径使用 `<标识>/icon`。图标出错时,保留有效文本并附上诊断。作者格式见[插件展示元信息](../../../docs/cookbook/adding-a-package.zh.md#plugin-display-metadata)。
|
|
86
86
|
|
|
87
87
|
<a id="startup-and-reload-failures"></a>
|
|
88
88
|
### 启动与重载失败
|
|
@@ -135,7 +135,7 @@ Loader 结算后,app-boot 在仅 optional 条目未激活时输出警告。如
|
|
|
135
135
|
- **包元数据。** `ctx.pluginPackages.packageOf` 定位所属包,不加载代码,也不要求导出 `package.json`;子路径选择其所属包,不校验该文件。安装 runtime resolution 后,即使查询未命中也以其选包规则为准。仅安装服务而不提供 runtime resolution 的底层嵌入方保留原生查询。展示元数据使用上文另述的入口感知读取器。
|
|
136
136
|
- **两个 Loader builtin。** `mountRootInclude` 把 `cordis:include` 与 `cordis:group` 注册为 Loader builtin:group 行能把一个提供方与它的消费方放进同一个 `isolate` realm,而位于本工作区之外的 agent preset 无法按名称解析 `@deepseek-ai/cordis-plugin-group`。两者都通过宿主的模块管线加载,而非被包含树自身的说明符解析。
|
|
137
137
|
- **由 consumer 持有严格语义。** 普通 Loader group 保留成功 sibling。App-boot 在首次结算后应用全局 required-entry policy;agent preset 与动态多 entry 组合在需要 all-or-nothing setup 时,持有并拆卸各自的独立 Loader 子树。App-boot 读取 failed fiber 来报告已记录的错误,并在一个进程检查点内合并 Loader 重复的 rejection 通知。
|
|
138
|
-
- **唯一 runtime resolution。** 安装优先、有序 bundle 逐根 breadth-first 遍历生成运行时表。runtime 解析不创建链接;runtime resolution 条目占据 `$DSH_HOME/profiles/node_modules` 上各自的包名位置,其余包名把该目录当作普通祖先。profile 加载时删除 Link 后端发布版写进 profile 的 `.dsh-module-fallback` 投影;pnpm 安装的包保留。package `imports` 选中的外部 bare target 使用相同的选包顺序,映射、conditions 和精确 target 解析仍由 Node 负责。完整后继 runtime resolution
|
|
138
|
+
- **唯一 runtime resolution。** 安装优先、有序 bundle 逐根 breadth-first 遍历生成运行时表。runtime 解析不创建链接;runtime resolution 条目占据 `$DSH_HOME/profiles/node_modules` 上各自的包名位置,其余包名把该目录当作普通祖先。profile 加载时删除 Link 后端发布版写进 profile 的 `.dsh-module-fallback` 投影;pnpm 安装的包保留。package `imports` 选中的外部 bare target 使用相同的选包顺序,映射、conditions 和精确 target 解析仍由 Node 负责。完整后继 runtime resolution 可以原子地增加 package name、移除 profile 范围的映射和 profile 本地包名、更新 linked root 集合;保留映射的规范化目录、版本和作用域不变。安装范围的锚点不变;profile 映射可以更换声明来源。[插件管理器](../plugin-manager/README.zh.md)在包操作之后发布后继代([决策](../../../.agents/notes/implemented/architecture/2026-09-30-profile-package-refresh-and-manifest-invalidation.zh.md))。
|
|
139
139
|
- **移除链接拦截。** 后继 generation 可以移除 linked root,无需重启。目录不再被任何剩余 root 覆盖时,后续请求使用原生查询,可能找到开发副本,也可能报告缺包。已有模块引用和 Node 缓存保持不变。同名、同目标可以重新加入;曾发布的名称改指向不同目标时,即使中间移除过也会被拒绝([generation 规则](../../../.agents/notes/implemented/architecture/2026-09-09-profile-resolution-generations.zh.md#immutable-generations))。
|
|
140
140
|
- **应用自有 profile。** 应用自有 profile 使用相同的 runtime resolution。目标位于当前 profile 目录内的链接(包括 pnpm store 链接)不算外部 root,即使 profile 位于共享 profiles 树外。解析过程不修改其 `node_modules`;已安装包由 pnpm 管理。
|
|
141
141
|
- **自有 Worker。** Worker 构建 banner 会在业务 bundle 前导入 `@deepseek-ai/dsh-app-boot/worker/profile-resolution-bootstrap`。每个 Worker 在自己的 isolate 中安装结构化克隆的 runtime resolution。bootstrap bundle 不静态导入任何包。源码 Worker 入口保留自包含依赖,第三方 Worker 不接受注入。
|
|
@@ -159,7 +159,6 @@ Loader 结算后,app-boot 在仅 optional 条目未激活时输出警告。如
|
|
|
159
159
|
| [`src/profile-sanitize.ts`](src/profile-sanitize.ts) | profile patch 备份与恢复 bundle 启用状态 |
|
|
160
160
|
| [`src/config-schema/`](src/config-schema/) | Profile schema 生成、发现、原生投影与结果类型 |
|
|
161
161
|
| [`src/profile-resolution/`](src/profile-resolution/) | 运行时 resolver、package metadata 服务与构建后 Worker bootstrap |
|
|
162
|
-
| — | 不发布运行时不变式伴生入口;每个 runtime resolution 只有一个拦截所有。 |
|
|
163
162
|
|
|
164
163
|
</details>
|
|
165
164
|
|
|
@@ -177,7 +176,7 @@ Loader 结算后,app-boot 在仅 optional 条目未激活时输出警告。如
|
|
|
177
176
|
- [dsh-home-paths](../../util/home-paths/README.zh.md)——harness home 解析器(`resolveDshHome`)。
|
|
178
177
|
- [配置来源归属](../../../.agents/notes/implemented/architecture/2026-08-04-configuration-source-ownership.zh.md)——被发现的文件为何不得决定 bootstrap 行为。
|
|
179
178
|
- [Profile 插件组合包](../../../.agents/notes/implemented/architecture/2026-08-05-profile-plugin-bundles.zh.md)——profile 与组合包组合设计。
|
|
180
|
-
- [用户 patch HMR 测试](
|
|
179
|
+
- [用户 patch HMR 测试](tests/user-patches.spec.ts)——实时 patch 行为与原生文件系统投递的验证归属。
|
|
181
180
|
|
|
182
181
|
-----
|
|
183
182
|
|
package/lib/index.js
CHANGED
|
@@ -539,6 +539,11 @@ const INSTALLATION_OWNED_PROFILE_TUPLES = { headless: [
|
|
|
539
539
|
"@deepseek-ai/dsh-web-app",
|
|
540
540
|
"@deepseek-ai/dsh-headless"
|
|
541
541
|
] };
|
|
542
|
+
/**
|
|
543
|
+
* Bundles an earlier release shipped and the installation no longer carries;
|
|
544
|
+
* {@link loadProfileDirectory} removes them from the profile's bundle list.
|
|
545
|
+
*/
|
|
546
|
+
const RETIRED_BUNDLES = new Set(["@deepseek-ai/dsh-experimental-schedule-bundle"]);
|
|
542
547
|
/** The bundle list a `dsh plugin` init uses for a name with no shipped template. */
|
|
543
548
|
const DEFAULT_PROFILE_BUNDLES = ["@deepseek-ai/dsh-base"];
|
|
544
549
|
/**
|
|
@@ -553,7 +558,7 @@ const OPTIONAL_BUNDLES = [
|
|
|
553
558
|
"@deepseek-ai/dsh-experimental-agent-team-profile",
|
|
554
559
|
"@deepseek-ai/dsh-experimental-voice-input-bundle",
|
|
555
560
|
"@deepseek-ai/dsh-experimental-auto-review",
|
|
556
|
-
"@deepseek-ai/dsh-experimental-
|
|
561
|
+
"@deepseek-ai/dsh-experimental-inspector-profile"
|
|
557
562
|
];
|
|
558
563
|
const PROFILE_PATCH_TEMPLATE = `# Your patch layer for this dsh profile, applied after every bundle layer:
|
|
559
564
|
# a top-level YAML array of loader patch entries (id-targeted config
|
|
@@ -738,7 +743,11 @@ async function createRuntimeResolution(options) {
|
|
|
738
743
|
const localPackageNames = profile === void 0 ? [] : installedProfilePackageNames(profile, manifest);
|
|
739
744
|
const profilePackages = profile === void 0 ? /* @__PURE__ */ new Map() : collectProfileScopePackages(profile, packageNames, profileDeclarers, profileVersions);
|
|
740
745
|
const linkedRoots = profile === void 0 ? [] : linkedProfileRoots(profile, profilesDir);
|
|
741
|
-
return await Promise.resolve(
|
|
746
|
+
return await Promise.resolve(new ProfileRuntimeResolution({
|
|
747
|
+
installAnchor,
|
|
748
|
+
profileDir: profile?.dir,
|
|
749
|
+
home
|
|
750
|
+
}, {
|
|
742
751
|
profilesDir,
|
|
743
752
|
profileDir: profile?.dir,
|
|
744
753
|
localPackageNames: Object.freeze(localPackageNames),
|
|
@@ -758,6 +767,45 @@ async function createRuntimeResolution(options) {
|
|
|
758
767
|
}))])
|
|
759
768
|
}));
|
|
760
769
|
}
|
|
770
|
+
/**
|
|
771
|
+
* A runtime resolution that remembers the inputs it was computed from. Worker environment data carries only its
|
|
772
|
+
* fields; the inputs stay private to the thread that computed it.
|
|
773
|
+
*/
|
|
774
|
+
var ProfileRuntimeResolution = class {
|
|
775
|
+
profilesDir;
|
|
776
|
+
profileDir;
|
|
777
|
+
localPackageNames;
|
|
778
|
+
entries;
|
|
779
|
+
linkedRoots;
|
|
780
|
+
#source;
|
|
781
|
+
/**
|
|
782
|
+
* @param source - inputs of {@link createRuntimeResolution}, reused by {@link computeLatestResolution}.
|
|
783
|
+
* @param table - the computed package table.
|
|
784
|
+
*/
|
|
785
|
+
constructor(source, table) {
|
|
786
|
+
this.#source = source;
|
|
787
|
+
this.profilesDir = table.profilesDir;
|
|
788
|
+
this.profileDir = table.profileDir;
|
|
789
|
+
this.localPackageNames = table.localPackageNames;
|
|
790
|
+
this.entries = table.entries;
|
|
791
|
+
this.linkedRoots = table.linkedRoots;
|
|
792
|
+
Object.freeze(this);
|
|
793
|
+
}
|
|
794
|
+
/**
|
|
795
|
+
* Compute the latest generation from the same installation, profile directory, and Harness home, rereading the
|
|
796
|
+
* profile's manifest, bundle selection, and installed packages from disk, without retaining synthetic layers.
|
|
797
|
+
* With no profile directory, only installation packages are recomputed. This instance is unchanged.
|
|
798
|
+
* @returns a new resolution for the latest generation.
|
|
799
|
+
*/
|
|
800
|
+
computeLatestResolution() {
|
|
801
|
+
const { installAnchor, home, profileDir } = this.#source;
|
|
802
|
+
return createRuntimeResolution({
|
|
803
|
+
installAnchor,
|
|
804
|
+
home,
|
|
805
|
+
...profileDir === void 0 ? {} : { profile: loadProfileDirectory("dsh", profileDir, installAnchor) }
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
};
|
|
761
809
|
/** Synthetic profiles used by direct callers may have no on-disk manifest. */
|
|
762
810
|
function readOptionalProfileManifest(profile) {
|
|
763
811
|
if (profile === void 0) return void 0;
|
|
@@ -848,6 +896,19 @@ function writeProfileManifest(dir, manifest) {
|
|
|
848
896
|
function sameBundles(left, right) {
|
|
849
897
|
return left.length === right.length && left.every((value, index) => value === right[index]);
|
|
850
898
|
}
|
|
899
|
+
/** Return `manifest` with `dsh.profile.bundles` replaced, preserving all other fields. */
|
|
900
|
+
function withBundles(manifest, bundles) {
|
|
901
|
+
return {
|
|
902
|
+
...manifest,
|
|
903
|
+
dsh: {
|
|
904
|
+
...manifest.dsh,
|
|
905
|
+
profile: {
|
|
906
|
+
...manifest.dsh?.profile,
|
|
907
|
+
bundles: [...bundles]
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
};
|
|
911
|
+
}
|
|
851
912
|
/**
|
|
852
913
|
* Normalize an exact installation-owned bundle tuple to its shipped template,
|
|
853
914
|
* preserving all other manifest fields. Other bundle lists remain untouched.
|
|
@@ -858,16 +919,19 @@ function normalizeShippedProfile(name, dir, manifest) {
|
|
|
858
919
|
const bundles = manifest.dsh?.profile?.bundles;
|
|
859
920
|
if (template === void 0 || bundles === void 0) return manifest;
|
|
860
921
|
if (!(installationOwned !== void 0 && sameBundles(bundles, installationOwned))) return manifest;
|
|
861
|
-
const normalized =
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
922
|
+
const normalized = withBundles(manifest, template.bundles);
|
|
923
|
+
writeProfileManifest(dir, normalized);
|
|
924
|
+
return normalized;
|
|
925
|
+
}
|
|
926
|
+
/**
|
|
927
|
+
* Remove {@link RETIRED_BUNDLES} from a profile's bundle list, writing the
|
|
928
|
+
* manifest back only when it listed one.
|
|
929
|
+
*/
|
|
930
|
+
function dropRetiredBundles(dir, manifest) {
|
|
931
|
+
const bundles = manifest.dsh?.profile?.bundles ?? [];
|
|
932
|
+
const kept = bundles.filter((bundle) => !RETIRED_BUNDLES.has(bundle));
|
|
933
|
+
if (kept.length === bundles.length) return manifest;
|
|
934
|
+
const normalized = withBundles(manifest, kept);
|
|
871
935
|
writeProfileManifest(dir, normalized);
|
|
872
936
|
return normalized;
|
|
873
937
|
}
|
|
@@ -909,7 +973,8 @@ function resolveBundleDir(binName, packageName, installAnchor, profileDir) {
|
|
|
909
973
|
* Load an already initialized profile directory without resolving it through
|
|
910
974
|
* the shared Harness home. This is used by application-owned profiles whose
|
|
911
975
|
* package project and lifecycle belong to that application.
|
|
912
|
-
*
|
|
976
|
+
* Retired bundles are removed from the stored bundle list first, rewriting the
|
|
977
|
+
* manifest when it listed one. Unreadable bundles, and bundles whose own dsh peers the profile does not exempt, are skipped
|
|
913
978
|
* without changing the manifest and listed in `skippedBundles`; nothing is printed.
|
|
914
979
|
* @param binName - the diagnostic prefix on thrown errors.
|
|
915
980
|
* @param dir - absolute profile package directory.
|
|
@@ -918,7 +983,7 @@ function resolveBundleDir(binName, packageName, installAnchor, profileDir) {
|
|
|
918
983
|
* @returns the successfully loaded bundle layers and optional user patch layer.
|
|
919
984
|
*/
|
|
920
985
|
function loadProfileDirectory(binName, dir, installAnchor, options = {}) {
|
|
921
|
-
const bundles = readProfileManifest(binName, dir).dsh?.profile?.bundles ?? [];
|
|
986
|
+
const bundles = dropRetiredBundles(dir, readProfileManifest(binName, dir)).dsh?.profile?.bundles ?? [];
|
|
922
987
|
const layers = [];
|
|
923
988
|
const skippedBundles = [];
|
|
924
989
|
const exemptions = bundles.length === 0 ? {} : readProfileVersionExemptions(dir);
|
|
@@ -1362,10 +1427,10 @@ var ResolutionRouter = class {
|
|
|
1362
1427
|
if (successor.profilesDir !== this.current.profilesDir || successor.profileDir !== this.current.profileDir) throw new Error("profile resolution: a successor cannot change its profile scope");
|
|
1363
1428
|
for (const [name, current] of this.current.entries) {
|
|
1364
1429
|
const next = entries.get(name);
|
|
1365
|
-
if (next === void 0
|
|
1430
|
+
if (next === void 0 && current.scope === "profile") continue;
|
|
1431
|
+
if (next === void 0 || !sameResolution(current.packageDir, next.packageDir) || current.scope === "installation" && !sameResolution(current.declarer, next.declarer) || current.version !== next.version || current.scope !== next.scope) throw new Error(`profile resolution: replacing ${JSON.stringify(name)} requires a process restart`);
|
|
1366
1432
|
}
|
|
1367
1433
|
const localPackageNames = new Set(successor.localPackageNames);
|
|
1368
|
-
for (const name of this.current.localPackageNames) if (!localPackageNames.has(name)) throw new Error(`profile resolution: removing local package ${JSON.stringify(name)} requires a process restart`);
|
|
1369
1434
|
for (const name of localPackageNames) if (!this.current.localPackageNames.has(name) && this.current.entries.has(name)) throw new Error(`profile resolution: overriding ${JSON.stringify(name)} locally requires a process restart`);
|
|
1370
1435
|
for (const root of successor.linkedRoots) {
|
|
1371
1436
|
const previous = this.linkedTargets.get(root.name);
|
|
@@ -1857,23 +1922,41 @@ const ICON_MEDIA_TYPES = new Map([
|
|
|
1857
1922
|
[".jpeg", "image/jpeg"],
|
|
1858
1923
|
[".webp", "image/webp"]
|
|
1859
1924
|
]);
|
|
1860
|
-
function iconOf(
|
|
1861
|
-
const icon = textOf(value, `${manifestPath}: icon`);
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1925
|
+
function iconOf(specifier, packageName, parentURL, manifestPath, value) {
|
|
1926
|
+
const icon = manifestPath === void 0 ? void 0 : textOf(value, `${manifestPath}: icon`);
|
|
1927
|
+
let target;
|
|
1928
|
+
let label;
|
|
1929
|
+
if (manifestPath !== void 0 && icon !== void 0) {
|
|
1930
|
+
if (isAbsolute(icon) || win32.isAbsolute(icon) || /^[A-Za-z][A-Za-z\d+.-]*:/u.test(icon)) throw new Error(`${manifestPath}: icon must be a relative file path`);
|
|
1931
|
+
label = manifestPath;
|
|
1932
|
+
const root = realpathSync(dirname(manifestPath));
|
|
1933
|
+
target = resolve(root, icon);
|
|
1934
|
+
const local = relative(root, realpathSync(target));
|
|
1935
|
+
if (local === ".." || local.startsWith(`..${sep}`) || isAbsolute(local)) throw new Error(`${label}: icon must remain inside its manifest directory`);
|
|
1936
|
+
} else {
|
|
1937
|
+
const exported = optionalResourcePath(`${specifier}/icon`, parentURL);
|
|
1938
|
+
if (exported === void 0) return void 0;
|
|
1939
|
+
target = label = exported;
|
|
1940
|
+
assertPackageOwned(realpathSync(target), packageName);
|
|
1941
|
+
}
|
|
1942
|
+
const mediaType = ICON_MEDIA_TYPES.get(extname(target).toLowerCase());
|
|
1943
|
+
if (mediaType === void 0) throw new Error(`${label}: icon must be SVG, PNG, JPEG, or WebP`);
|
|
1944
|
+
const file = realpathSync(target);
|
|
1870
1945
|
const stat = statSync(file);
|
|
1871
|
-
if (!stat.isFile()) throw new Error(`${
|
|
1872
|
-
if (stat.size > MAX_ICON_BYTES) throw new Error(`${
|
|
1946
|
+
if (!stat.isFile()) throw new Error(`${label}: icon must be a regular file`);
|
|
1947
|
+
if (stat.size > MAX_ICON_BYTES) throw new Error(`${label}: icon exceeds 256 KiB`);
|
|
1873
1948
|
const bytes = readFileSync(file);
|
|
1874
|
-
if (bytes.length > MAX_ICON_BYTES) throw new Error(`${
|
|
1949
|
+
if (bytes.length > MAX_ICON_BYTES) throw new Error(`${label}: icon exceeds 256 KiB`);
|
|
1875
1950
|
return `data:${mediaType};base64,${bytes.toString("base64")}`;
|
|
1876
1951
|
}
|
|
1952
|
+
/** Require an ancestor of the real file whose package.json names the owning package. */
|
|
1953
|
+
function assertPackageOwned(file, name) {
|
|
1954
|
+
for (let directory = dirname(file);; directory = dirname(directory)) {
|
|
1955
|
+
const manifest = join(directory, "package.json");
|
|
1956
|
+
if (existsSync(manifest) && readObject(manifest).name === name) return;
|
|
1957
|
+
if (dirname(directory) === directory) throw new Error(`${file}: icon must remain inside its package directory`);
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1877
1960
|
/**
|
|
1878
1961
|
* Resolve a plugin resource through the active Node ESM resolver without evaluating it.
|
|
1879
1962
|
* @param specifier - complete resource module specifier, including its locale filename.
|
|
@@ -1954,24 +2037,29 @@ function localizedText(field, dictionaries, fallback, finalFallback) {
|
|
|
1954
2037
|
};
|
|
1955
2038
|
}
|
|
1956
2039
|
/**
|
|
1957
|
-
* Read
|
|
1958
|
-
*
|
|
1959
|
-
*
|
|
2040
|
+
* Read plugin locale JSON display text and icon without evaluating JavaScript entries.
|
|
2041
|
+
* Only a package-root specifier reads its exported package.json: `name`/`description` fill missing
|
|
2042
|
+
* locale fields, and a declared `icon` takes priority over the `<specifier>/icon` resource.
|
|
2043
|
+
* A subpath specifier never reads package.json; its icon comes only from `<specifier>/icon`.
|
|
2044
|
+
* Manifest icons remain inside their declaring directory; exported icons remain inside their
|
|
2045
|
+
* owning package after realpath resolution. Both accept SVG, PNG, JPEG, or WebP up to 256 KiB.
|
|
2046
|
+
* Icon failures retain display text without falling back.
|
|
1960
2047
|
* Non-package specifiers are skipped without invoking the resource resolver.
|
|
1961
2048
|
* Language files share the directory containing the resolved English resource;
|
|
1962
2049
|
* each file is resolved through the complete plugin specifier before reading.
|
|
1963
|
-
*
|
|
1964
|
-
*
|
|
2050
|
+
* Translation maps retain an English fallback, ultimately the full module specifier
|
|
2051
|
+
* for titles and empty for descriptions.
|
|
1965
2052
|
* @param specifier - configured plugin module name, including any package subpath.
|
|
1966
2053
|
* @param parentURL - owning Loader tree's module-resolution base.
|
|
1967
|
-
* @returns display fields and any
|
|
2054
|
+
* @returns display fields and any resource diagnostic, or undefined for non-package specifiers or absent metadata.
|
|
1968
2055
|
*/
|
|
1969
2056
|
function readPluginMeta(specifier, parentURL) {
|
|
1970
|
-
|
|
2057
|
+
const packageName = barePackageName(specifier);
|
|
2058
|
+
if (packageName === void 0) return void 0;
|
|
1971
2059
|
try {
|
|
1972
2060
|
const englishPath = optionalResourcePath(`${specifier}/locale/en.json`, parentURL);
|
|
1973
2061
|
const dictionaries = englishPath === void 0 ? /* @__PURE__ */ new Map() : dictionariesOf(englishPath, specifier, parentURL);
|
|
1974
|
-
const manifestPath = optionalResourcePath(`${specifier}/package.json`, parentURL);
|
|
2062
|
+
const manifestPath = packageName === specifier ? optionalResourcePath(`${specifier}/package.json`, parentURL) : void 0;
|
|
1975
2063
|
const manifest = manifestPath === void 0 ? void 0 : readObject(manifestPath);
|
|
1976
2064
|
const title = localizedText("title", dictionaries, fallbackText(manifest?.name), specifier);
|
|
1977
2065
|
const description = localizedText("description", dictionaries, fallbackText(manifest?.description), "");
|
|
@@ -1981,7 +2069,7 @@ function readPluginMeta(specifier, parentURL) {
|
|
|
1981
2069
|
};
|
|
1982
2070
|
let icon;
|
|
1983
2071
|
try {
|
|
1984
|
-
icon =
|
|
2072
|
+
icon = iconOf(specifier, packageName, parentURL, manifestPath, manifest?.icon);
|
|
1985
2073
|
} catch (error) {
|
|
1986
2074
|
return {
|
|
1987
2075
|
...text,
|
|
@@ -3209,9 +3297,11 @@ var PluginPackages = class extends Service {
|
|
|
3209
3297
|
packages = /* @__PURE__ */ new Map();
|
|
3210
3298
|
interception;
|
|
3211
3299
|
disposeWorkerResolution;
|
|
3300
|
+
current;
|
|
3212
3301
|
constructor(ctx, config = {}) {
|
|
3213
3302
|
super(ctx, "pluginPackages");
|
|
3214
3303
|
if (config.resolution === void 0) return;
|
|
3304
|
+
this.current = config.resolution;
|
|
3215
3305
|
const interception = installRuntimeInterception(config.resolution);
|
|
3216
3306
|
this.disposeWorkerResolution = registerWorkerResolution(config.resolution);
|
|
3217
3307
|
this.interception = interception;
|
|
@@ -3222,17 +3312,30 @@ var PluginPackages = class extends Service {
|
|
|
3222
3312
|
}
|
|
3223
3313
|
/**
|
|
3224
3314
|
* Publish a complete successor generation for this process and subsequently created Workers.
|
|
3225
|
-
*
|
|
3315
|
+
* Profile mappings and local package names may be removed after their plugins stop; linked roots may also be removed.
|
|
3316
|
+
* Retained profile mappings may change their declarer, but not their normalized directory, version, or scope;
|
|
3317
|
+
* installation mappings must remain unchanged. Publication does not unload modules or clear Node caches.
|
|
3226
3318
|
* @param successor - fully constructed generation accepted by {@link RuntimeInterception.replace}.
|
|
3227
3319
|
*/
|
|
3228
3320
|
replace(successor) {
|
|
3229
3321
|
if (this.interception === void 0) throw new Error("plugin-packages: runtime resolution is not installed");
|
|
3230
3322
|
this.interception.replace(successor);
|
|
3323
|
+
this.current = successor;
|
|
3231
3324
|
this.packages = /* @__PURE__ */ new Map();
|
|
3232
3325
|
this.disposeWorkerResolution?.();
|
|
3233
3326
|
this.disposeWorkerResolution = registerWorkerResolution(successor);
|
|
3234
3327
|
}
|
|
3235
3328
|
/**
|
|
3329
|
+
* Publish the latest generation computed by the installed resolution through {@link replace}. Package contents
|
|
3330
|
+
* and loaded modules are not reloaded.
|
|
3331
|
+
* @throws when no resolution is installed, it is plain data rather than a {@link ProfileRuntimeResolution},
|
|
3332
|
+
* reading the latest files fails, or the successor is rejected. A computed resolution without a profile can refresh.
|
|
3333
|
+
*/
|
|
3334
|
+
async refresh() {
|
|
3335
|
+
if (!(this.current instanceof ProfileRuntimeResolution)) throw new Error("plugin-packages: the installed runtime resolution cannot be recomputed");
|
|
3336
|
+
this.replace(await this.current.computeLatestResolution());
|
|
3337
|
+
}
|
|
3338
|
+
/**
|
|
3236
3339
|
* Locate the package named by a specifier without requiring a package export.
|
|
3237
3340
|
* @param specifier - module specifier whose package owns the requested module.
|
|
3238
3341
|
* @param parentURL - URL whose Node lookup order applies.
|
|
@@ -4134,4 +4237,4 @@ function addHarnessSourceSection(ctx, sourceRoot) {
|
|
|
4134
4237
|
});
|
|
4135
4238
|
}
|
|
4136
4239
|
//#endregion
|
|
4137
|
-
export { DEFAULT_PROFILE_BUNDLES, FAIL_LOUD_RELEASE_TIMEOUT_MS, HARNESS_SOURCE_SECTION, LOADER_EXPRESSION_SCHEMA, OPTIONAL_BUNDLES, PROFILES_DIR, PROFILE_COMPATIBILITY_FILENAME, PROFILE_PATCH_FILENAME, PROFILE_TEMPLATES, PluginPackages, StartupError, addHarnessSourceSection, auditStartupEntries, boot, bundlePatchFiles, bundlePatchPaths, composeEntries, createConfigProjector, createRuntimeResolution, evaluatePluginCompatibility, generateConfigSchema, getDshRuntimeVersion, initProfile, installFailLoud, isNativeConfigSchema, loadEnv, loadLayeredEnv, loadOptionalPatches, loadOverlayPatches, loadProfile, loadProfileDirectory, mountRootInclude, pluginCompatibilityWarning, prepareProfileEntries, prepareProfilePatches, readPluginMeta, readProfileCompatibility, readProfileManifest, readProfilePatches, readProfilePlugins, readProfileVersionExemptions, reconcileProfilePatches, reconcileProfilePlugins, removeLinkProjections, renderConfigDump, reportSkippedBundles, resolveBundleDir, resolveConfigPath, resolveProfileDir, resolveTelemetryPatch, sanitizeProfile, setProfileVersionExemption, writeProfileBundles, writeProfileManifest };
|
|
4240
|
+
export { DEFAULT_PROFILE_BUNDLES, FAIL_LOUD_RELEASE_TIMEOUT_MS, HARNESS_SOURCE_SECTION, LOADER_EXPRESSION_SCHEMA, OPTIONAL_BUNDLES, PROFILES_DIR, PROFILE_COMPATIBILITY_FILENAME, PROFILE_PATCH_FILENAME, PROFILE_TEMPLATES, PluginPackages, ProfileRuntimeResolution, StartupError, addHarnessSourceSection, auditStartupEntries, boot, bundlePatchFiles, bundlePatchPaths, composeEntries, createConfigProjector, createRuntimeResolution, evaluatePluginCompatibility, generateConfigSchema, getDshRuntimeVersion, initProfile, installFailLoud, isNativeConfigSchema, loadEnv, loadLayeredEnv, loadOptionalPatches, loadOverlayPatches, loadProfile, loadProfileDirectory, mountRootInclude, pluginCompatibilityWarning, prepareProfileEntries, prepareProfilePatches, readPluginMeta, readProfileCompatibility, readProfileManifest, readProfilePatches, readProfilePlugins, readProfileVersionExemptions, reconcileProfilePatches, reconcileProfilePlugins, removeLinkProjections, renderConfigDump, reportSkippedBundles, resolveBundleDir, resolveConfigPath, resolveProfileDir, resolveTelemetryPatch, sanitizeProfile, setProfileVersionExemption, writeProfileBundles, writeProfileManifest };
|
package/lib/types/index.d.ts
CHANGED
|
@@ -34,7 +34,7 @@ declare module '@deepseek-ai/cordis' {
|
|
|
34
34
|
'app-boot/config-reload'(): void;
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
|
-
export { composeEntries, createRuntimeResolution, DEFAULT_PROFILE_BUNDLES, OPTIONAL_BUNDLES, bundlePatchFiles, bundlePatchPaths, initProfile, removeLinkProjections, loadProfile, loadProfileDirectory, PROFILE_PATCH_FILENAME, PROFILE_TEMPLATES, PROFILES_DIR, readProfileManifest, reportSkippedBundles, resolveBundleDir, resolveProfileDir, writeProfileManifest, type Profile, type ProfileLayer, type SkippedBundle, type ProfileManifest, type LinkedRoot, type RuntimeResolutionOptions, type RuntimeResolutionEntry, type RuntimeResolution, type ProfileTemplate, } from './profile.ts';
|
|
37
|
+
export { composeEntries, createRuntimeResolution, ProfileRuntimeResolution, DEFAULT_PROFILE_BUNDLES, OPTIONAL_BUNDLES, bundlePatchFiles, bundlePatchPaths, initProfile, removeLinkProjections, loadProfile, loadProfileDirectory, PROFILE_PATCH_FILENAME, PROFILE_TEMPLATES, PROFILES_DIR, readProfileManifest, reportSkippedBundles, resolveBundleDir, resolveProfileDir, writeProfileManifest, type Profile, type ProfileLayer, type SkippedBundle, type ProfileManifest, type LinkedRoot, type RuntimeResolutionOptions, type RuntimeResolutionEntry, type RuntimeResolution, type ProfileTemplate, } from './profile.ts';
|
|
38
38
|
export { PluginPackages, type PluginPackage, type PluginPackagesConfig, } from './profile-resolution/service.ts';
|
|
39
39
|
/**
|
|
40
40
|
* Resolve the config to boot. Replay swaps a `cordis.yml` basename for
|
|
@@ -9,17 +9,21 @@ import type { PluginLocalizedMeta } from '@deepseek-ai/dsh-package-manifest';
|
|
|
9
9
|
*/
|
|
10
10
|
export declare function resolvePluginResource(specifier: string, parentURL: string): string;
|
|
11
11
|
/**
|
|
12
|
-
* Read
|
|
13
|
-
*
|
|
14
|
-
*
|
|
12
|
+
* Read plugin locale JSON display text and icon without evaluating JavaScript entries.
|
|
13
|
+
* Only a package-root specifier reads its exported package.json: `name`/`description` fill missing
|
|
14
|
+
* locale fields, and a declared `icon` takes priority over the `<specifier>/icon` resource.
|
|
15
|
+
* A subpath specifier never reads package.json; its icon comes only from `<specifier>/icon`.
|
|
16
|
+
* Manifest icons remain inside their declaring directory; exported icons remain inside their
|
|
17
|
+
* owning package after realpath resolution. Both accept SVG, PNG, JPEG, or WebP up to 256 KiB.
|
|
18
|
+
* Icon failures retain display text without falling back.
|
|
15
19
|
* Non-package specifiers are skipped without invoking the resource resolver.
|
|
16
20
|
* Language files share the directory containing the resolved English resource;
|
|
17
21
|
* each file is resolved through the complete plugin specifier before reading.
|
|
18
|
-
*
|
|
19
|
-
*
|
|
22
|
+
* Translation maps retain an English fallback, ultimately the full module specifier
|
|
23
|
+
* for titles and empty for descriptions.
|
|
20
24
|
* @param specifier - configured plugin module name, including any package subpath.
|
|
21
25
|
* @param parentURL - owning Loader tree's module-resolution base.
|
|
22
|
-
* @returns display fields and any
|
|
26
|
+
* @returns display fields and any resource diagnostic, or undefined for non-package specifiers or absent metadata.
|
|
23
27
|
*/
|
|
24
28
|
export declare function readPluginMeta(specifier: string, parentURL: string): PluginLocalizedMeta | undefined;
|
|
25
29
|
//# sourceMappingURL=package-meta.d.ts.map
|
|
@@ -11,11 +11,14 @@ export interface RuntimeInterception {
|
|
|
11
11
|
*/
|
|
12
12
|
packageDir(specifier: string, parentURL: string): string | undefined;
|
|
13
13
|
/**
|
|
14
|
-
* Atomically publish a complete successor and fresh caches.
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
14
|
+
* Atomically publish a complete successor and fresh caches. Profile-scoped mappings, local names, and linked
|
|
15
|
+
* roots may be removed; removed roots stop intercepting uncovered directories. Existing modules and Node caches
|
|
16
|
+
* remain intact, so callers remove a package only after its plugins stop.
|
|
17
|
+
* A retained profile mapping may change its declarer if its normalized directory, version, and scope stay unchanged.
|
|
18
|
+
* @param successor - fully constructed generation retaining the installation mappings.
|
|
19
|
+
* @throws when the profile scope, a retained directory, version, scope, or installation declarer changes;
|
|
20
|
+
* an installation mapping is removed; a new local name overrides an existing mapping; or a previously published
|
|
21
|
+
* link name selects a different real directory.
|
|
19
22
|
*/
|
|
20
23
|
replace(successor: RuntimeResolution): void;
|
|
21
24
|
/** Restore the native resolver methods. Interceptions dispose in reverse order. */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Package metadata resolved through one runtime interception. */
|
|
2
2
|
import { Service, type Context } from '@deepseek-ai/cordis';
|
|
3
3
|
import type { PluginLocalizedMeta } from '@deepseek-ai/dsh-package-manifest';
|
|
4
|
-
import type
|
|
4
|
+
import { type RuntimeResolution } from '../profile.ts';
|
|
5
5
|
declare module '@deepseek-ai/cordis' {
|
|
6
6
|
interface Context {
|
|
7
7
|
/** Deterministic package lookup for configured plugin specifiers. */
|
|
@@ -31,13 +31,23 @@ export declare class PluginPackages extends Service {
|
|
|
31
31
|
private packages;
|
|
32
32
|
private readonly interception;
|
|
33
33
|
private disposeWorkerResolution;
|
|
34
|
+
private current;
|
|
34
35
|
constructor(ctx: Context, config?: PluginPackagesConfig);
|
|
35
36
|
/**
|
|
36
37
|
* Publish a complete successor generation for this process and subsequently created Workers.
|
|
37
|
-
*
|
|
38
|
+
* Profile mappings and local package names may be removed after their plugins stop; linked roots may also be removed.
|
|
39
|
+
* Retained profile mappings may change their declarer, but not their normalized directory, version, or scope;
|
|
40
|
+
* installation mappings must remain unchanged. Publication does not unload modules or clear Node caches.
|
|
38
41
|
* @param successor - fully constructed generation accepted by {@link RuntimeInterception.replace}.
|
|
39
42
|
*/
|
|
40
43
|
replace(successor: RuntimeResolution): void;
|
|
44
|
+
/**
|
|
45
|
+
* Publish the latest generation computed by the installed resolution through {@link replace}. Package contents
|
|
46
|
+
* and loaded modules are not reloaded.
|
|
47
|
+
* @throws when no resolution is installed, it is plain data rather than a {@link ProfileRuntimeResolution},
|
|
48
|
+
* reading the latest files fails, or the successor is rejected. A computed resolution without a profile can refresh.
|
|
49
|
+
*/
|
|
50
|
+
refresh(): Promise<void>;
|
|
41
51
|
/**
|
|
42
52
|
* Locate the package named by a specifier without requiring a package export.
|
|
43
53
|
* @param specifier - module specifier whose package owns the requested module.
|
package/lib/types/profile.d.ts
CHANGED
|
@@ -175,7 +175,37 @@ export interface RuntimeResolutionOptions {
|
|
|
175
175
|
* @param options - installation anchor, optional loaded profile, and Harness home.
|
|
176
176
|
* @returns the complete immutable runtime resolution.
|
|
177
177
|
*/
|
|
178
|
-
export declare function createRuntimeResolution(options: RuntimeResolutionOptions): Promise<
|
|
178
|
+
export declare function createRuntimeResolution(options: RuntimeResolutionOptions): Promise<ProfileRuntimeResolution>;
|
|
179
|
+
/** Inputs a {@link ProfileRuntimeResolution} reuses to compute its successor. */
|
|
180
|
+
interface ResolutionSource {
|
|
181
|
+
installAnchor: string;
|
|
182
|
+
home: string;
|
|
183
|
+
profileDir: string | undefined;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* A runtime resolution that remembers the inputs it was computed from. Worker environment data carries only its
|
|
187
|
+
* fields; the inputs stay private to the thread that computed it.
|
|
188
|
+
*/
|
|
189
|
+
export declare class ProfileRuntimeResolution implements RuntimeResolution {
|
|
190
|
+
#private;
|
|
191
|
+
readonly profilesDir: string;
|
|
192
|
+
readonly profileDir: string | undefined;
|
|
193
|
+
readonly localPackageNames: readonly string[];
|
|
194
|
+
readonly entries: readonly RuntimeResolutionEntry[];
|
|
195
|
+
readonly linkedRoots: readonly LinkedRoot[];
|
|
196
|
+
/**
|
|
197
|
+
* @param source - inputs of {@link createRuntimeResolution}, reused by {@link computeLatestResolution}.
|
|
198
|
+
* @param table - the computed package table.
|
|
199
|
+
*/
|
|
200
|
+
constructor(source: ResolutionSource, table: RuntimeResolution);
|
|
201
|
+
/**
|
|
202
|
+
* Compute the latest generation from the same installation, profile directory, and Harness home, rereading the
|
|
203
|
+
* profile's manifest, bundle selection, and installed packages from disk, without retaining synthetic layers.
|
|
204
|
+
* With no profile directory, only installation packages are recomputed. This instance is unchanged.
|
|
205
|
+
* @returns a new resolution for the latest generation.
|
|
206
|
+
*/
|
|
207
|
+
computeLatestResolution(): Promise<ProfileRuntimeResolution>;
|
|
208
|
+
}
|
|
179
209
|
/**
|
|
180
210
|
* Read a profile's manifest.
|
|
181
211
|
* @param binName - the diagnostic prefix on the thrown error.
|
|
@@ -206,7 +236,8 @@ export declare function resolveBundleDir(binName: string, packageName: string, i
|
|
|
206
236
|
* Load an already initialized profile directory without resolving it through
|
|
207
237
|
* the shared Harness home. This is used by application-owned profiles whose
|
|
208
238
|
* package project and lifecycle belong to that application.
|
|
209
|
-
*
|
|
239
|
+
* Retired bundles are removed from the stored bundle list first, rewriting the
|
|
240
|
+
* manifest when it listed one. Unreadable bundles, and bundles whose own dsh peers the profile does not exempt, are skipped
|
|
210
241
|
* without changing the manifest and listed in `skippedBundles`; nothing is printed.
|
|
211
242
|
* @param binName - the diagnostic prefix on thrown errors.
|
|
212
243
|
* @param dir - absolute profile package directory.
|
|
@@ -242,4 +273,5 @@ export declare function loadProfile(binName: string, name: string, installAnchor
|
|
|
242
273
|
* @returns the composed entry list.
|
|
243
274
|
*/
|
|
244
275
|
export declare function composeEntries(layers: readonly PatchOptions[][], warn?: (message: string) => void): EntryOptions[];
|
|
276
|
+
export {};
|
|
245
277
|
//# sourceMappingURL=profile.d.ts.map
|
|
@@ -249,10 +249,10 @@ var ResolutionRouter = class {
|
|
|
249
249
|
if (successor.profilesDir !== this.current.profilesDir || successor.profileDir !== this.current.profileDir) throw new Error("profile resolution: a successor cannot change its profile scope");
|
|
250
250
|
for (const [name, current] of this.current.entries) {
|
|
251
251
|
const next = entries.get(name);
|
|
252
|
-
if (next === void 0
|
|
252
|
+
if (next === void 0 && current.scope === "profile") continue;
|
|
253
|
+
if (next === void 0 || !sameResolution(current.packageDir, next.packageDir) || current.scope === "installation" && !sameResolution(current.declarer, next.declarer) || current.version !== next.version || current.scope !== next.scope) throw new Error(`profile resolution: replacing ${JSON.stringify(name)} requires a process restart`);
|
|
253
254
|
}
|
|
254
255
|
const localPackageNames = new Set(successor.localPackageNames);
|
|
255
|
-
for (const name of this.current.localPackageNames) if (!localPackageNames.has(name)) throw new Error(`profile resolution: removing local package ${JSON.stringify(name)} requires a process restart`);
|
|
256
256
|
for (const name of localPackageNames) if (!this.current.localPackageNames.has(name) && this.current.entries.has(name)) throw new Error(`profile resolution: overriding ${JSON.stringify(name)} locally requires a process restart`);
|
|
257
257
|
for (const root of successor.linkedRoots) {
|
|
258
258
|
const previous = this.linkedTargets.get(root.name);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepseek-ai/dsh-app-boot",
|
|
3
3
|
"description": "Shared boot glue for the app bins: .env loading, fail-loud Loader guards, snapshot-aware config resolution, and the Loader boot sequence",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.1-alpha.1",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -38,29 +38,29 @@
|
|
|
38
38
|
"node-addon-require-builtin": "^0.1.6",
|
|
39
39
|
"resolve.exports": "^2.0.3",
|
|
40
40
|
"semver": "^7.8.5",
|
|
41
|
-
"@deepseek-ai/dsh-atomic-write": "0.2.
|
|
42
|
-
"@deepseek-ai/dsh-package-manifest": "0.2.
|
|
41
|
+
"@deepseek-ai/dsh-atomic-write": "0.2.1-alpha.1",
|
|
42
|
+
"@deepseek-ai/dsh-package-manifest": "0.2.1-alpha.1"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
|
-
"@deepseek-ai/cordis-plugin-
|
|
46
|
-
"@deepseek-ai/cordis-plugin-
|
|
47
|
-
"@deepseek-ai/
|
|
48
|
-
"@deepseek-ai/
|
|
49
|
-
"@deepseek-ai/dsh-system-prompt": "0.2.
|
|
50
|
-
"@deepseek-ai/cordis": "~4.0.
|
|
51
|
-
"@deepseek-ai/dsh-
|
|
45
|
+
"@deepseek-ai/cordis-plugin-group": "~1.0.5-alpha.1",
|
|
46
|
+
"@deepseek-ai/cordis-plugin-include": "~1.0.10-alpha.1",
|
|
47
|
+
"@deepseek-ai/dsh-launch-environment": "0.2.1-alpha.1",
|
|
48
|
+
"@deepseek-ai/cordis-plugin-loader": "~1.0.6-alpha.1",
|
|
49
|
+
"@deepseek-ai/dsh-system-prompt": "0.2.1-alpha.1",
|
|
50
|
+
"@deepseek-ai/cordis": "~4.0.5-alpha.1",
|
|
51
|
+
"@deepseek-ai/dsh-home-paths": "0.2.1-alpha.1"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@types/js-yaml": "^4.0.9",
|
|
55
55
|
"@types/semver": "^7.8.0",
|
|
56
|
-
"@deepseek-ai/schemastery": "~3.18.
|
|
57
|
-
"@deepseek-ai/cordis-plugin-group": "~1.0.
|
|
58
|
-
"@deepseek-ai/cordis-plugin-include": "~1.0.
|
|
59
|
-
"@deepseek-ai/cordis-plugin-loader": "~1.0.
|
|
60
|
-
"@deepseek-ai/cordis-plugin-timer": "~1.1.
|
|
61
|
-
"@deepseek-ai/dsh-launch-environment": "0.2.
|
|
62
|
-
"@deepseek-ai/dsh-home-paths": "0.2.
|
|
63
|
-
"@deepseek-ai/
|
|
64
|
-
"@deepseek-ai/
|
|
56
|
+
"@deepseek-ai/schemastery": "~3.18.5-alpha.1",
|
|
57
|
+
"@deepseek-ai/cordis-plugin-group": "~1.0.5-alpha.1",
|
|
58
|
+
"@deepseek-ai/cordis-plugin-include": "~1.0.10-alpha.1",
|
|
59
|
+
"@deepseek-ai/cordis-plugin-loader": "~1.0.6-alpha.1",
|
|
60
|
+
"@deepseek-ai/cordis-plugin-timer": "~1.1.7-alpha.1",
|
|
61
|
+
"@deepseek-ai/dsh-launch-environment": "0.2.1-alpha.1",
|
|
62
|
+
"@deepseek-ai/dsh-home-paths": "0.2.1-alpha.1",
|
|
63
|
+
"@deepseek-ai/dsh-system-prompt": "0.2.1-alpha.1",
|
|
64
|
+
"@deepseek-ai/cordis": "~4.0.5-alpha.1"
|
|
65
65
|
}
|
|
66
66
|
}
|