@try-works/dsh-memory 0.1.19 → 0.1.20
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/LICENSE +21 -21
- package/README.md +585 -585
- package/STATUS.md +287 -287
- package/cordis.patch.yml +69 -69
- package/package.json +1 -1
- package/scripts/check-package.mjs +76 -76
- package/src/SYSTEM.template.md +311 -311
- package/src/capture.js +242 -242
- package/src/client/index.js +886 -886
- package/src/config.js +57 -57
- package/src/consolidate-run.js +132 -132
- package/src/consolidate.js +330 -330
- package/src/context.js +88 -88
- package/src/decisions.js +106 -106
- package/src/defaults.js +93 -93
- package/src/digest.js +255 -255
- package/src/entry.js +179 -179
- package/src/eval.js +72 -72
- package/src/files.js +60 -60
- package/src/fixture.js +56 -56
- package/src/forget.js +71 -71
- package/src/freshness.js +65 -65
- package/src/fts.js +166 -166
- package/src/git.js +53 -53
- package/src/history.js +226 -226
- package/src/host.js +866 -866
- package/src/index.js +115 -94
- package/src/inject.js +108 -108
- package/src/layers.js +178 -178
- package/src/ledger.js +19 -19
- package/src/map.js +184 -184
- package/src/models.js +136 -136
- package/src/queue.js +602 -602
- package/src/rank.js +31 -31
- package/src/recover.js +91 -91
- package/src/refresh.js +80 -80
- package/src/remember.js +58 -58
- package/src/rerank.js +90 -90
- package/src/search.js +75 -75
- package/src/select.js +57 -57
- package/src/session.js +60 -60
- package/src/state.js +240 -240
- package/src/store.js +128 -128
- package/src/summarize.js +195 -195
- package/src/system-doc.js +171 -171
- package/src/tasks.js +617 -617
- package/src/telemetry.js +122 -122
- package/src/tools.js +828 -818
- package/src/working.js +288 -288
- package/src/workspace-key.js +68 -68
- package/src/workspace.js +87 -87
package/cordis.patch.yml
CHANGED
|
@@ -1,69 +1,69 @@
|
|
|
1
|
-
# dsh-memory bundle patch — the patch layer this package exports.
|
|
2
|
-
#
|
|
3
|
-
# Declared by `dsh.bundle.patch` in package.json. When the package is added to a profile, dsh
|
|
4
|
-
# reconciles it into `dsh.profile.bundles` and composes this layer over the profile, so the
|
|
5
|
-
# plugin mounts from the installed package rather than by absolute path.
|
|
6
|
-
#
|
|
7
|
-
# This layer does two things: it mounts dsh-memory, and it switches on the session history
|
|
8
|
-
# search that a memory plugin is useless without. Both are described where they appear.
|
|
9
|
-
#
|
|
10
|
-
# Patch semantics, which the rest of this file depends on: a patch REPLACES the targeted row's
|
|
11
|
-
# whole `config`, it does not merge into it. Every override below therefore restates EVERY key
|
|
12
|
-
# it owns, or the omitted ones silently become undefined.
|
|
13
|
-
- insert:
|
|
14
|
-
# dsh-memory itself.
|
|
15
|
-
#
|
|
16
|
-
# A single row naming the published package mounts the plugin on the profile root. The row id
|
|
17
|
-
# stays dsh-memory, which is what the PROFILE patch addresses for config. It publishes the `memory`
|
|
18
|
-
# service, registers the memory_* tools into the host-owned tools registry, and keeps its
|
|
19
|
-
# browser half module-scoped — so, like the other memory-like plugins, it needs no `isolate`
|
|
20
|
-
# realm.
|
|
21
|
-
#
|
|
22
|
-
# The row carries NO config: the store root, the memory model and the git origin are set on
|
|
23
|
-
# Settings -> Memory, which writes a top-level `config:` row for this id into the PROFILE
|
|
24
|
-
# patch. That is why the mounted row must be addressable by id — the config editor finds a
|
|
25
|
-
# row by id at the top level, so a profile that configures memory ends up with both this
|
|
26
|
-
# insert and a sibling `- id: dsh-memory` config row after it.
|
|
27
|
-
- id: dsh-memory
|
|
28
|
-
# A scoped name MUST be quoted: YAML treats a leading @ as a reserved indicator.
|
|
29
|
-
name: '@try-works/dsh-memory'
|
|
30
|
-
|
|
31
|
-
# NOTE: the model-facing session history TOOLS are deliberately NOT mounted here.
|
|
32
|
-
#
|
|
33
|
-
# Not because they are unwanted, but because this is the wrong plane. A Web profile
|
|
34
|
-
# disables every base tool row and hands the tool plane to PRESETS, and its gate reads
|
|
35
|
-
# declared row ids WITHOUT regard to `disabled` — the web-app bundle keeps `tool-ralph`
|
|
36
|
-
# declared-but-disabled purely to hold it off the host plane and out of collision with
|
|
37
|
-
# every preset's rows. Inserting a live tool row here would put it on the host plane and
|
|
38
|
-
# in collision with that arrangement, which is a large side effect for a memory plugin to
|
|
39
|
-
# have on somebody else's tool surface. Enabling the index below is a config override, the
|
|
40
|
-
# kind the web-app bundle explicitly invites; owning a tool row is not.
|
|
41
|
-
|
|
42
|
-
# ---------------------------------------------------------------------------------------------
|
|
43
|
-
# Session search: switched on by installing this plugin.
|
|
44
|
-
# ---------------------------------------------------------------------------------------------
|
|
45
|
-
#
|
|
46
|
-
# The base bundle mounts `session-query-sqlite` with `openAt: never`, and the web-app bundle
|
|
47
|
-
# restates that. It is deliberate: ctx.sessionQuery stays available for exact reads and lineage
|
|
48
|
-
# while SEARCH calls fail with SESSION_QUERY_SEARCH_DISABLED, so no deployment indexes gigabytes
|
|
49
|
-
# of session logs without asking. The cost of that default is a system that cannot look back at
|
|
50
|
-
# what happened — and memory that cannot be searched is half a memory. Installing a memory plugin
|
|
51
|
-
# is the request that flag was waiting for, so this layer asks. The web-app bundle says so in as
|
|
52
|
-
# many words: 'a deployment enabling content search overrides openAt to first-search in a later
|
|
53
|
-
# patch layer'. This is that layer.
|
|
54
|
-
#
|
|
55
|
-
# `first-search` rather than `startup`: nothing is indexed until a search is actually made, so
|
|
56
|
-
# the capability is present from install while the work still happens lazily, on a query.
|
|
57
|
-
#
|
|
58
|
-
# `path` is restated even though both bundles already set one, because a patch replaces the
|
|
59
|
-
# whole config rather than merging: omitting it would drop the index to undefined and rebuild
|
|
60
|
-
# it in memory on every process. A durable file under storages/ is what makes a several-gigabyte
|
|
61
|
-
# corpus worth indexing once.
|
|
62
|
-
#
|
|
63
|
-
# Precedence is why this is safe to set here. Bundle layers compose FIRST and the profile's own
|
|
64
|
-
# cordis.patch.yml applies AFTER, so a profile wanting `startup`, a different path, or `never`
|
|
65
|
-
# simply says so there and wins. This layer supplies a default, not a mandate.
|
|
66
|
-
- id: session-query-sqlite
|
|
67
|
-
config:
|
|
68
|
-
path: !!js dshHomePath('storages', 'session-search.sqlite')
|
|
69
|
-
openAt: first-search
|
|
1
|
+
# dsh-memory bundle patch — the patch layer this package exports.
|
|
2
|
+
#
|
|
3
|
+
# Declared by `dsh.bundle.patch` in package.json. When the package is added to a profile, dsh
|
|
4
|
+
# reconciles it into `dsh.profile.bundles` and composes this layer over the profile, so the
|
|
5
|
+
# plugin mounts from the installed package rather than by absolute path.
|
|
6
|
+
#
|
|
7
|
+
# This layer does two things: it mounts dsh-memory, and it switches on the session history
|
|
8
|
+
# search that a memory plugin is useless without. Both are described where they appear.
|
|
9
|
+
#
|
|
10
|
+
# Patch semantics, which the rest of this file depends on: a patch REPLACES the targeted row's
|
|
11
|
+
# whole `config`, it does not merge into it. Every override below therefore restates EVERY key
|
|
12
|
+
# it owns, or the omitted ones silently become undefined.
|
|
13
|
+
- insert:
|
|
14
|
+
# dsh-memory itself.
|
|
15
|
+
#
|
|
16
|
+
# A single row naming the published package mounts the plugin on the profile root. The row id
|
|
17
|
+
# stays dsh-memory, which is what the PROFILE patch addresses for config. It publishes the `memory`
|
|
18
|
+
# service, registers the memory_* tools into the host-owned tools registry, and keeps its
|
|
19
|
+
# browser half module-scoped — so, like the other memory-like plugins, it needs no `isolate`
|
|
20
|
+
# realm.
|
|
21
|
+
#
|
|
22
|
+
# The row carries NO config: the store root, the memory model and the git origin are set on
|
|
23
|
+
# Settings -> Memory, which writes a top-level `config:` row for this id into the PROFILE
|
|
24
|
+
# patch. That is why the mounted row must be addressable by id — the config editor finds a
|
|
25
|
+
# row by id at the top level, so a profile that configures memory ends up with both this
|
|
26
|
+
# insert and a sibling `- id: dsh-memory` config row after it.
|
|
27
|
+
- id: dsh-memory
|
|
28
|
+
# A scoped name MUST be quoted: YAML treats a leading @ as a reserved indicator.
|
|
29
|
+
name: '@try-works/dsh-memory'
|
|
30
|
+
|
|
31
|
+
# NOTE: the model-facing session history TOOLS are deliberately NOT mounted here.
|
|
32
|
+
#
|
|
33
|
+
# Not because they are unwanted, but because this is the wrong plane. A Web profile
|
|
34
|
+
# disables every base tool row and hands the tool plane to PRESETS, and its gate reads
|
|
35
|
+
# declared row ids WITHOUT regard to `disabled` — the web-app bundle keeps `tool-ralph`
|
|
36
|
+
# declared-but-disabled purely to hold it off the host plane and out of collision with
|
|
37
|
+
# every preset's rows. Inserting a live tool row here would put it on the host plane and
|
|
38
|
+
# in collision with that arrangement, which is a large side effect for a memory plugin to
|
|
39
|
+
# have on somebody else's tool surface. Enabling the index below is a config override, the
|
|
40
|
+
# kind the web-app bundle explicitly invites; owning a tool row is not.
|
|
41
|
+
|
|
42
|
+
# ---------------------------------------------------------------------------------------------
|
|
43
|
+
# Session search: switched on by installing this plugin.
|
|
44
|
+
# ---------------------------------------------------------------------------------------------
|
|
45
|
+
#
|
|
46
|
+
# The base bundle mounts `session-query-sqlite` with `openAt: never`, and the web-app bundle
|
|
47
|
+
# restates that. It is deliberate: ctx.sessionQuery stays available for exact reads and lineage
|
|
48
|
+
# while SEARCH calls fail with SESSION_QUERY_SEARCH_DISABLED, so no deployment indexes gigabytes
|
|
49
|
+
# of session logs without asking. The cost of that default is a system that cannot look back at
|
|
50
|
+
# what happened — and memory that cannot be searched is half a memory. Installing a memory plugin
|
|
51
|
+
# is the request that flag was waiting for, so this layer asks. The web-app bundle says so in as
|
|
52
|
+
# many words: 'a deployment enabling content search overrides openAt to first-search in a later
|
|
53
|
+
# patch layer'. This is that layer.
|
|
54
|
+
#
|
|
55
|
+
# `first-search` rather than `startup`: nothing is indexed until a search is actually made, so
|
|
56
|
+
# the capability is present from install while the work still happens lazily, on a query.
|
|
57
|
+
#
|
|
58
|
+
# `path` is restated even though both bundles already set one, because a patch replaces the
|
|
59
|
+
# whole config rather than merging: omitting it would drop the index to undefined and rebuild
|
|
60
|
+
# it in memory on every process. A durable file under storages/ is what makes a several-gigabyte
|
|
61
|
+
# corpus worth indexing once.
|
|
62
|
+
#
|
|
63
|
+
# Precedence is why this is safe to set here. Bundle layers compose FIRST and the profile's own
|
|
64
|
+
# cordis.patch.yml applies AFTER, so a profile wanting `startup`, a different path, or `never`
|
|
65
|
+
# simply says so there and wins. This layer supplies a default, not a mandate.
|
|
66
|
+
- id: session-query-sqlite
|
|
67
|
+
config:
|
|
68
|
+
path: !!js dshHomePath('storages', 'session-search.sqlite')
|
|
69
|
+
openAt: first-search
|
package/package.json
CHANGED
|
@@ -1,76 +1,76 @@
|
|
|
1
|
-
// Package invariants for dsh-memory. Run with: node scripts/check-package.mjs
|
|
2
|
-
//
|
|
3
|
-
// A plugin that is installed by name must declare everything the loader needs; when one of these
|
|
4
|
-
// drifts the failure appears at MOUNT time in someone else's profile, which is the worst place to
|
|
5
|
-
// discover it. This is a fast pre-flight, and test/package.test.js asserts the same invariants.
|
|
6
|
-
import { readFileSync, existsSync } from 'node:fs'
|
|
7
|
-
import { dirname, join } from 'node:path'
|
|
8
|
-
import { fileURLToPath } from 'node:url'
|
|
9
|
-
|
|
10
|
-
const root = join(dirname(fileURLToPath(import.meta.url)), '..')
|
|
11
|
-
const problems = []
|
|
12
|
-
const note = (ok, message) => { if (!ok) problems.push(message) }
|
|
13
|
-
|
|
14
|
-
const manifest = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8'))
|
|
15
|
-
|
|
16
|
-
note(manifest.name === '@try-works/dsh-memory', 'package name must be "@try-works/dsh-memory", found ' + manifest.name)
|
|
17
|
-
note(manifest.type === 'module', 'package must be ESM ("type": "module")')
|
|
18
|
-
note(typeof manifest.main === 'string', 'package must declare "main"')
|
|
19
|
-
note(existsSync(join(root, manifest.main)), 'main does not exist: ' + manifest.main)
|
|
20
|
-
|
|
21
|
-
// The loader must be able to import the entry.
|
|
22
|
-
const entry = await import(new URL('../' + manifest.main, import.meta.url))
|
|
23
|
-
note(typeof entry.name === 'string' && entry.name === 'dsh-memory', 'entry must export name = "dsh-memory"')
|
|
24
|
-
note(Array.isArray(entry.inject), 'entry must export inject')
|
|
25
|
-
note(typeof entry.apply === 'function', 'entry must export apply')
|
|
26
|
-
note(entry.Config !== undefined, 'entry must export Config')
|
|
27
|
-
note(entry.default === undefined, 'entry must NOT export default (the loader does exports.default ?? exports, which would discard name/inject/Config)')
|
|
28
|
-
|
|
29
|
-
// Bundle patch: what makes an install-by-name mount the plugin.
|
|
30
|
-
const patchPath = manifest.dsh?.bundle?.patch
|
|
31
|
-
note(typeof patchPath === 'string', 'dsh.bundle.patch must be declared for install-by-name')
|
|
32
|
-
if (typeof patchPath === 'string') {
|
|
33
|
-
const full = join(root, patchPath.replace(/^\.\//, ''))
|
|
34
|
-
note(existsSync(full), 'bundle patch does not exist: ' + patchPath)
|
|
35
|
-
if (existsSync(full)) {
|
|
36
|
-
const text = readFileSync(full, 'utf8')
|
|
37
|
-
note(text.includes('id: dsh-memory'), 'bundle patch must insert an entry with id: dsh-memory')
|
|
38
|
-
note(text.includes("name: '@try-works/dsh-memory'"), 'bundle patch must mount the package by its published name')
|
|
39
|
-
}
|
|
40
|
-
note((manifest.files ?? []).some((f) => f.includes('cordis.patch.yml')), 'files[] must ship the bundle patch')
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Client half.
|
|
44
|
-
const client = manifest.dsh?.client
|
|
45
|
-
note(client !== undefined, 'dsh.client must be declared for the Settings page')
|
|
46
|
-
if (client) {
|
|
47
|
-
note(client.platform === 'web', 'dsh.client.platform must be "web"')
|
|
48
|
-
const clientExport = manifest.exports?.['./client']
|
|
49
|
-
const target = typeof clientExport === 'string' ? clientExport : clientExport?.default
|
|
50
|
-
note(typeof target === 'string', 'exports["./client"] must resolve to a file')
|
|
51
|
-
if (typeof target === 'string') note(existsSync(join(root, target)), 'client half missing: ' + target)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Everything the entry imports at load time must ship.
|
|
55
|
-
note((manifest.files ?? []).includes('src'), 'files[] must ship src/')
|
|
56
|
-
// The system document template is read at runtime from beside its module.
|
|
57
|
-
note(existsSync(join(root, 'src', 'SYSTEM.template.md')), 'src/SYSTEM.template.md must exist (rendered into every store)')
|
|
58
|
-
|
|
59
|
-
// Peers: a missing declaration means an unresolvable import in a clean profile.
|
|
60
|
-
for (const peer of ['@deepseek-ai/cordis', '@deepseek-ai/dsh-tools', '@deepseek-ai/dsh-llm']) {
|
|
61
|
-
note(Object.hasOwn(manifest.peerDependencies ?? {}, peer), 'peerDependencies must declare ' + peer)
|
|
62
|
-
}
|
|
63
|
-
// schemastery is the exception, and it is deliberate: .volatile() exists only from 3.18.4, and a
|
|
64
|
-
// PEER lets the profile supply 3.18.1, which throws at module load. As a dependency the version
|
|
65
|
-
// is ours to pin. Declaring it as a peer is what broke the first registry install.
|
|
66
|
-
note(!Object.hasOwn(manifest.peerDependencies ?? {}, '@deepseek-ai/schemastery'), 'schemastery must NOT be a peer dependency')
|
|
67
|
-
note(/^\^3\.18\.[4-9]/.test((manifest.dependencies ?? {})['@deepseek-ai/schemastery'] ?? ''), 'schemastery must be a dependency pinned at 3.18.4 or newer, for .volatile()')
|
|
68
|
-
{
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
if (problems.length > 0) {
|
|
72
|
-
console.error('dsh-memory package check FAILED:')
|
|
73
|
-
for (const problem of problems) console.error(' - ' + problem)
|
|
74
|
-
process.exit(1)
|
|
75
|
-
}
|
|
76
|
-
console.log('dsh-memory package check OK (' + manifest.name + '@' + manifest.version + ')')
|
|
1
|
+
// Package invariants for dsh-memory. Run with: node scripts/check-package.mjs
|
|
2
|
+
//
|
|
3
|
+
// A plugin that is installed by name must declare everything the loader needs; when one of these
|
|
4
|
+
// drifts the failure appears at MOUNT time in someone else's profile, which is the worst place to
|
|
5
|
+
// discover it. This is a fast pre-flight, and test/package.test.js asserts the same invariants.
|
|
6
|
+
import { readFileSync, existsSync } from 'node:fs'
|
|
7
|
+
import { dirname, join } from 'node:path'
|
|
8
|
+
import { fileURLToPath } from 'node:url'
|
|
9
|
+
|
|
10
|
+
const root = join(dirname(fileURLToPath(import.meta.url)), '..')
|
|
11
|
+
const problems = []
|
|
12
|
+
const note = (ok, message) => { if (!ok) problems.push(message) }
|
|
13
|
+
|
|
14
|
+
const manifest = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8'))
|
|
15
|
+
|
|
16
|
+
note(manifest.name === '@try-works/dsh-memory', 'package name must be "@try-works/dsh-memory", found ' + manifest.name)
|
|
17
|
+
note(manifest.type === 'module', 'package must be ESM ("type": "module")')
|
|
18
|
+
note(typeof manifest.main === 'string', 'package must declare "main"')
|
|
19
|
+
note(existsSync(join(root, manifest.main)), 'main does not exist: ' + manifest.main)
|
|
20
|
+
|
|
21
|
+
// The loader must be able to import the entry.
|
|
22
|
+
const entry = await import(new URL('../' + manifest.main, import.meta.url))
|
|
23
|
+
note(typeof entry.name === 'string' && entry.name === 'dsh-memory', 'entry must export name = "dsh-memory"')
|
|
24
|
+
note(Array.isArray(entry.inject), 'entry must export inject')
|
|
25
|
+
note(typeof entry.apply === 'function', 'entry must export apply')
|
|
26
|
+
note(entry.Config !== undefined, 'entry must export Config')
|
|
27
|
+
note(entry.default === undefined, 'entry must NOT export default (the loader does exports.default ?? exports, which would discard name/inject/Config)')
|
|
28
|
+
|
|
29
|
+
// Bundle patch: what makes an install-by-name mount the plugin.
|
|
30
|
+
const patchPath = manifest.dsh?.bundle?.patch
|
|
31
|
+
note(typeof patchPath === 'string', 'dsh.bundle.patch must be declared for install-by-name')
|
|
32
|
+
if (typeof patchPath === 'string') {
|
|
33
|
+
const full = join(root, patchPath.replace(/^\.\//, ''))
|
|
34
|
+
note(existsSync(full), 'bundle patch does not exist: ' + patchPath)
|
|
35
|
+
if (existsSync(full)) {
|
|
36
|
+
const text = readFileSync(full, 'utf8')
|
|
37
|
+
note(text.includes('id: dsh-memory'), 'bundle patch must insert an entry with id: dsh-memory')
|
|
38
|
+
note(text.includes("name: '@try-works/dsh-memory'"), 'bundle patch must mount the package by its published name')
|
|
39
|
+
}
|
|
40
|
+
note((manifest.files ?? []).some((f) => f.includes('cordis.patch.yml')), 'files[] must ship the bundle patch')
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Client half.
|
|
44
|
+
const client = manifest.dsh?.client
|
|
45
|
+
note(client !== undefined, 'dsh.client must be declared for the Settings page')
|
|
46
|
+
if (client) {
|
|
47
|
+
note(client.platform === 'web', 'dsh.client.platform must be "web"')
|
|
48
|
+
const clientExport = manifest.exports?.['./client']
|
|
49
|
+
const target = typeof clientExport === 'string' ? clientExport : clientExport?.default
|
|
50
|
+
note(typeof target === 'string', 'exports["./client"] must resolve to a file')
|
|
51
|
+
if (typeof target === 'string') note(existsSync(join(root, target)), 'client half missing: ' + target)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Everything the entry imports at load time must ship.
|
|
55
|
+
note((manifest.files ?? []).includes('src'), 'files[] must ship src/')
|
|
56
|
+
// The system document template is read at runtime from beside its module.
|
|
57
|
+
note(existsSync(join(root, 'src', 'SYSTEM.template.md')), 'src/SYSTEM.template.md must exist (rendered into every store)')
|
|
58
|
+
|
|
59
|
+
// Peers: a missing declaration means an unresolvable import in a clean profile.
|
|
60
|
+
for (const peer of ['@deepseek-ai/cordis', '@deepseek-ai/dsh-tools', '@deepseek-ai/dsh-llm']) {
|
|
61
|
+
note(Object.hasOwn(manifest.peerDependencies ?? {}, peer), 'peerDependencies must declare ' + peer)
|
|
62
|
+
}
|
|
63
|
+
// schemastery is the exception, and it is deliberate: .volatile() exists only from 3.18.4, and a
|
|
64
|
+
// PEER lets the profile supply 3.18.1, which throws at module load. As a dependency the version
|
|
65
|
+
// is ours to pin. Declaring it as a peer is what broke the first registry install.
|
|
66
|
+
note(!Object.hasOwn(manifest.peerDependencies ?? {}, '@deepseek-ai/schemastery'), 'schemastery must NOT be a peer dependency')
|
|
67
|
+
note(/^\^3\.18\.[4-9]/.test((manifest.dependencies ?? {})['@deepseek-ai/schemastery'] ?? ''), 'schemastery must be a dependency pinned at 3.18.4 or newer, for .volatile()')
|
|
68
|
+
{
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (problems.length > 0) {
|
|
72
|
+
console.error('dsh-memory package check FAILED:')
|
|
73
|
+
for (const problem of problems) console.error(' - ' + problem)
|
|
74
|
+
process.exit(1)
|
|
75
|
+
}
|
|
76
|
+
console.log('dsh-memory package check OK (' + manifest.name + '@' + manifest.version + ')')
|