dsh-mnemon-source-runtime 0.5.14 → 0.5.16
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.md +7 -1
- package/lib/client.js +1 -1
- package/lib/contracts-DycwaUv_.js +81 -0
- package/lib/contracts.d.ts +39 -1
- package/lib/contracts.js +2 -2
- package/lib/index.d.ts +2 -2
- package/lib/index.js +62 -57
- package/lib/types/contracts.d.ts +39 -0
- package/package.json +6 -6
- package/presentation/page.module.css +1 -1
- package/lib/contracts-B6vRCw3C.js +0 -32
package/README.md
CHANGED
|
@@ -19,7 +19,13 @@ Choose an existing data authority deliberately. Without `dataDir`, each stable S
|
|
|
19
19
|
|
|
20
20
|
Disabling participation does not delete stored entries. Source data remains separate from the current turn's projection and access grants.
|
|
21
21
|
|
|
22
|
-
Model projections
|
|
22
|
+
Model projections omit default `importance=normal` and whole-day ages of `0d`; they annotate entries only when non-default fields remain, for example `[importance=critical; created=14d; updated=2d]`, followed by the exact content. Future timestamps show `future`; unparseable ones show `unknown`. Ages are captured once per projection and remain fixed for that turn. Annotations count toward the Strategy's projection budget, but do not change stored JSON/Markdown, content matching or storage capacity. For replacement/removal, use only the entry content. Current instructions retain priority. Model-facing text omits revision hashes and quota/count statistics, while the Source protocol and management/UI retain them. File boundaries and all visible content remain; no low-importance entry is automatically hidden.
|
|
23
|
+
|
|
24
|
+
## Storage files
|
|
25
|
+
|
|
26
|
+
The `./contracts` entry names this Source's files under a storage root (`runtime/memories.json`, `USER.md`, `MEMORY.md`, the `.memories.lock` lock and the `archived/` local archive) and exports the rules a copy of them follows: `runtimeProjection` and `runtimeBytes` write and count USER.md and MEMORY.md exactly as the controller does, and `summarizeRuntimeMemories` counts a stored file for an inventory. They are pure and browser-safe. The `dsh-mnemon` Starter's backup, sync and storage inventory use them instead of keeping copies.
|
|
27
|
+
|
|
28
|
+
The same entry exports the size limits the configuration and the controller apply: `RUNTIME_MEMORY_LIMITS`, the default limit of USER.md and of MEMORY.md, and `RUNTIME_MEMORY_LIMIT_MAX_BYTES`, the largest limit either may be given. The Starter's settings take their defaults and bounds from them.
|
|
23
29
|
|
|
24
30
|
## Source-owned UI and tests
|
|
25
31
|
|
package/lib/client.js
CHANGED
|
@@ -104,7 +104,7 @@ window.__ModuleLoader__.load({
|
|
|
104
104
|
};
|
|
105
105
|
//#endregion
|
|
106
106
|
//#region \0source-css:/home/runner/work/dsh-mnemon/dsh-mnemon/plugins/dsh-mnemon-source-runtime/presentation/page.module.css.mjs
|
|
107
|
-
const css$2 = ".IIa07q_runtimeComposer{border:.5px solid var(--mn-card-line);border-radius:var(--dsw-radius-lg);margin-bottom:12px;padding:16px}.IIa07q_runtimeComposerHeading{justify-content:space-between;align-items:flex-start;gap:16px;margin-bottom:12px;display:flex}.IIa07q_runtimeComposerHeading h3{margin:0 0 2px;font-size:14px;font-weight:500;line-height:22px}.IIa07q_runtimeComposerHeading p{color:var(--mn-faint);margin:0;font-size:12px;line-height:18px}.IIa07q_runtimeComposerHeading>span{color:var(--mn-muted);background:var(--mn-fill);border-radius:999px;flex:none;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.IIa07q_runtimeComposer>textarea,.IIa07q_runtimeEntry textarea{resize:vertical;border:.5px solid var(--mn-field-line);border-radius:var(--dsw-radius-md);width:100%;color:var(--mn-text);background:var(--mn-input);outline:0;padding:8px 10px;font-size:13px;line-height:20px}.IIa07q_runtimeComposer>textarea:focus,.IIa07q_runtimeEntry textarea:focus{border-color:var(--mn-accent)}.IIa07q_runtimeComposerActions{justify-content:flex-end;align-items:flex-end;gap:8px;margin-top:12px;display:flex}.IIa07q_runtimeComposerActions label{color:var(--mn-muted);gap:6px;font-size:12px;font-weight:500;line-height:18px;display:grid}.IIa07q_runtimeChoice button{min-width:136px}.IIa07q_runtimeReadOnly{border-radius:var(--dsw-radius-md);color:var(--mn-muted);background:var(--mn-fill);margin-bottom:12px;padding:8px 12px;font-size:12px;line-height:18px}.IIa07q_runtimeSummaryGrid{grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin-bottom:12px;display:grid}.IIa07q_runtimeSummaryCard{border:.5px solid var(--mn-card-line);border-radius:var(--dsw-radius-lg);min-width:0}.IIa07q_runtimeBrowser{border:.5px solid var(--mn-card-line);border-radius:var(--dsw-radius-lg);overflow:hidden}.IIa07q_runtimeBrowserToolbar{border-bottom:.5px solid var(--mn-line);justify-content:space-between;align-items:center;gap:12px;padding:10px 12px;display:flex}.IIa07q_runtimeScopeFilter{border-radius:var(--dsw-radius-md);background:var(--mn-hover);flex-wrap:wrap;align-items:center;gap:2px;padding:3px;display:inline-flex}.IIa07q_runtimeScopeFilter button{border-radius:var(--dsw-radius-sm);min-height:28px;color:var(--mn-muted);cursor:pointer;background:0 0;border:0;padding:0 12px;font-size:13px;font-weight:500;line-height:20px}.IIa07q_runtimeScopeFilter button:hover{color:var(--mn-text)}.IIa07q_runtimeScopeFilter button[data-active]{color:var(--mn-text);background:var(--mn-layer-1);box-shadow:var(--dsw-elevation-soft)}.IIa07q_runtimeScopeFilter b{color:var(--mn-faint);font-variant-numeric:tabular-nums;margin-left:6px;font-size:12px;font-weight:400}.IIa07q_runtimeFilterQuery{width:min(320px,42%);min-width:210px}.IIa07q_runtimeUnifiedList{grid-template-columns:1fr;gap:8px;padding:12px;display:grid}.IIa07q_runtimeEntryBadges{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.IIa07q_runtimeEntryMeta .IIa07q_runtimeEntryTarget{color:var(--mn-accent);background:color-mix(in srgb, var(--mn-accent) 10%, transparent)}.IIa07q_runtimeEntryMeta .IIa07q_runtimeEntryBranch{text-overflow:ellipsis;white-space:nowrap;max-width:140px;color:var(--mn-muted);background:var(--mn-fill);font-family:var(--mn-code);overflow:hidden}.IIa07q_runtimeComposerBranch{color:var(--mn-muted);gap:6px;font-size:12px;font-weight:500;line-height:18px;display:grid}.IIa07q_runtimeComposerBranch input{border:.5px solid var(--mn-field-line);border-radius:var(--dsw-radius-md);width:100%;height:36px;color:var(--mn-text);background:var(--mn-input);outline:0;padding:0 10px;font-size:13px;font-weight:400}.IIa07q_runtimeComposerBranch input:focus{border-color:var(--mn-accent)}.IIa07q_bodyEditBranch{color:var(--mn-muted);gap:6px;font-size:12px;font-weight:500;line-height:18px;display:grid}.IIa07q_bodyEditBranch input{border:.5px solid var(--mn-field-line);border-radius:var(--dsw-radius-md);width:100%;height:32px;color:var(--mn-text);background:var(--mn-input);outline:0;padding:0 10px;font-size:13px;font-weight:400}.IIa07q_bodyEditBranch input:focus{border-color:var(--mn-accent)}.IIa07q_bodyEditBranch small{color:var(--mn-faint);font-size:12px;font-weight:400}.IIa07q_runtimeTargetHeader{justify-content:space-between;align-items:center;gap:16px;padding:14px 16px 8px;display:flex}.IIa07q_runtimeTargetHeader>div{gap:0;display:grid}.IIa07q_runtimeTargetHeader span{color:var(--mn-faint);font-family:var(--mn-code);font-size:11px;line-height:16px}.IIa07q_runtimeTargetHeader h3{margin:0;font-size:14px;font-weight:500;line-height:22px}.IIa07q_runtimeTargetHeader>strong{color:var(--mn-muted);background:var(--mn-fill);font-variant-numeric:tabular-nums;border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.IIa07q_capacityLine{align-items:center;gap:10px;padding:0 16px;display:flex}.IIa07q_capacityLine>div{background:var(--mn-fill);border-radius:999px;flex:1;height:4px;overflow:hidden}.IIa07q_capacityLine i{border-radius:inherit;background:var(--dsw-alias-brand-primary);height:100%;transition:width .25s;display:block}.IIa07q_capacityLine>span{min-width:88px;color:var(--mn-faint);text-align:right;font-variant-numeric:tabular-nums;font-size:11px}.IIa07q_runtimeTargetDescription{min-height:36px;color:var(--mn-faint);margin:8px 16px 14px;font-size:12px;line-height:18px}.IIa07q_runtimeEntry{--mn-provider-color:var(--mn-accent);border:.5px solid var(--mn-card-line);border-radius:var(--dsw-radius-md);padding:12px 14px 10px;position:relative}.IIa07q_runtimeEntry[data-importance=critical]{--mn-provider-color:var(--mn-priority)}.IIa07q_runtimeEntry[data-importance=low]{--mn-provider-color:var(--mn-faint)}.IIa07q_runtimeEntry[data-focused]{border-color:color-mix(in srgb, var(--mn-accent) 60%, var(--mn-card-line));box-shadow:0 0 0 2px color-mix(in srgb, var(--mn-accent) 14%, transparent)}.IIa07q_runtimeEntryMeta{justify-content:space-between;align-items:center;gap:12px;display:flex}.IIa07q_runtimeEntryMeta>span,.IIa07q_runtimeEntryBadges>span{color:var(--mn-muted);background:var(--mn-fill);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.IIa07q_runtimeEntry[data-importance=critical] .IIa07q_runtimeEntryMeta>span,.IIa07q_runtimeEntry[data-importance=critical] .IIa07q_runtimeEntryBadges>span:not(.IIa07q_runtimeEntryTarget){color:var(--mn-warn);background:color-mix(in srgb, var(--mn-warn) 12%, transparent)}.IIa07q_runtimeEntryMeta time{color:var(--mn-faint);text-overflow:ellipsis;white-space:nowrap;font-variant-numeric:tabular-nums;font-size:11px;overflow:hidden}.IIa07q_runtimeEntry>p{white-space:pre-wrap;overflow-wrap:anywhere;margin:8px 0;font-size:14px;line-height:22px}.IIa07q_runtimeEntry>select{margin-top:8px}.IIa07q_runtimeEntry footer{border-top:.5px solid var(--mn-line);justify-content:flex-end;align-items:center;gap:8px;min-height:32px;margin-top:8px;padding-top:8px;display:flex}.IIa07q_runtimeEntry footer>span{color:var(--mn-danger);margin-right:auto;font-size:12px}.IIa07q_runtimeEmpty{min-height:128px;color:var(--mn-faint);text-align:center;align-content:center;place-items:center;gap:6px;display:grid}.IIa07q_runtimeEmpty>span{font-size:20px;line-height:1}.IIa07q_runtimeEmpty p{margin:0;font-size:13px;line-height:20px}@media (width<=1000px){.IIa07q_runtimeSummaryGrid{grid-template-columns:1fr}}@media (width<=760px){.IIa07q_runtimeComposerHeading,.IIa07q_runtimeComposerActions{flex-direction:column;align-items:stretch}.IIa07q_runtimeComposerActions>*,.IIa07q_runtimeComposerActions button{width:100%}.IIa07q_runtimeBrowserToolbar{flex-direction:column;align-items:stretch}.IIa07q_runtimeFilterQuery{width:100%;min-width:0}}";
|
|
107
|
+
const css$2 = ".IIa07q_runtimeComposer{border:.5px solid var(--mn-card-line);border-radius:var(--dsw-radius-lg);margin-bottom:12px;padding:16px}.IIa07q_runtimeComposerHeading{justify-content:space-between;align-items:flex-start;gap:16px;margin-bottom:12px;display:flex}.IIa07q_runtimeComposerHeading h3{margin:0 0 2px;font-size:14px;font-weight:500;line-height:22px}.IIa07q_runtimeComposerHeading p{color:var(--mn-faint);margin:0;font-size:12px;line-height:18px}.IIa07q_runtimeComposerHeading>span{color:var(--mn-muted);background:var(--mn-fill);border-radius:999px;flex:none;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.IIa07q_runtimeComposer>textarea,.IIa07q_runtimeEntry textarea{resize:vertical;border:.5px solid var(--mn-field-line);border-radius:var(--dsw-radius-md);width:100%;color:var(--mn-text);background:var(--mn-input);outline:0;padding:8px 10px;font-size:13px;line-height:20px}.IIa07q_runtimeComposer>textarea:focus,.IIa07q_runtimeEntry textarea:focus{border-color:var(--mn-accent)}.IIa07q_runtimeComposerActions{justify-content:flex-end;align-items:flex-end;gap:8px;margin-top:12px;display:flex}.IIa07q_runtimeComposerActions label{color:var(--mn-muted);gap:6px;font-size:12px;font-weight:500;line-height:18px;display:grid}.IIa07q_runtimeChoice button{min-width:136px}.IIa07q_runtimeReadOnly{border-radius:var(--dsw-radius-md);color:var(--mn-muted);background:var(--mn-block-fill,var(--mn-fill));margin-bottom:12px;padding:8px 12px;font-size:12px;line-height:18px}.IIa07q_runtimeSummaryGrid{grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin-bottom:12px;display:grid}.IIa07q_runtimeSummaryCard{border:.5px solid var(--mn-card-line);border-radius:var(--dsw-radius-lg);min-width:0}.IIa07q_runtimeBrowser{border:.5px solid var(--mn-card-line);border-radius:var(--dsw-radius-lg);overflow:hidden}.IIa07q_runtimeBrowserToolbar{border-bottom:.5px solid var(--mn-line);justify-content:space-between;align-items:center;gap:12px;padding:10px 12px;display:flex}.IIa07q_runtimeScopeFilter{border-radius:var(--dsw-radius-md);background:var(--mn-hover);flex-wrap:wrap;align-items:center;gap:2px;padding:3px;display:inline-flex}.IIa07q_runtimeScopeFilter button{border-radius:var(--dsw-radius-sm);min-height:28px;color:var(--mn-muted);cursor:pointer;background:0 0;border:0;padding:0 12px;font-size:13px;font-weight:500;line-height:20px}.IIa07q_runtimeScopeFilter button:hover{color:var(--mn-text)}.IIa07q_runtimeScopeFilter button[data-active]{color:var(--mn-text);background:var(--mn-layer-1);box-shadow:var(--dsw-elevation-soft)}.IIa07q_runtimeScopeFilter b{color:var(--mn-faint);font-variant-numeric:tabular-nums;margin-left:6px;font-size:12px;font-weight:400}.IIa07q_runtimeFilterQuery{width:min(320px,42%);min-width:210px}.IIa07q_runtimeUnifiedList{grid-template-columns:1fr;gap:8px;padding:12px;display:grid}.IIa07q_runtimeEntryBadges{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.IIa07q_runtimeEntryMeta .IIa07q_runtimeEntryTarget{color:var(--mn-accent);background:color-mix(in srgb, var(--mn-accent) 10%, transparent)}.IIa07q_runtimeEntryMeta .IIa07q_runtimeEntryBranch{text-overflow:ellipsis;white-space:nowrap;max-width:140px;color:var(--mn-muted);background:var(--mn-fill);font-family:var(--mn-code);overflow:hidden}.IIa07q_runtimeComposerBranch{color:var(--mn-muted);gap:6px;font-size:12px;font-weight:500;line-height:18px;display:grid}.IIa07q_runtimeComposerBranch input{border:.5px solid var(--mn-field-line);border-radius:var(--dsw-radius-md);width:100%;height:36px;color:var(--mn-text);background:var(--mn-input);outline:0;padding:0 10px;font-size:13px;font-weight:400}.IIa07q_runtimeComposerBranch input:focus{border-color:var(--mn-accent)}.IIa07q_bodyEditBranch{color:var(--mn-muted);gap:6px;font-size:12px;font-weight:500;line-height:18px;display:grid}.IIa07q_bodyEditBranch input{border:.5px solid var(--mn-field-line);border-radius:var(--dsw-radius-md);width:100%;height:32px;color:var(--mn-text);background:var(--mn-input);outline:0;padding:0 10px;font-size:13px;font-weight:400}.IIa07q_bodyEditBranch input:focus{border-color:var(--mn-accent)}.IIa07q_bodyEditBranch small{color:var(--mn-faint);font-size:12px;font-weight:400}.IIa07q_runtimeTargetHeader{justify-content:space-between;align-items:center;gap:16px;padding:14px 16px 8px;display:flex}.IIa07q_runtimeTargetHeader>div{gap:0;display:grid}.IIa07q_runtimeTargetHeader span{color:var(--mn-faint);font-family:var(--mn-code);font-size:11px;line-height:16px}.IIa07q_runtimeTargetHeader h3{margin:0;font-size:14px;font-weight:500;line-height:22px}.IIa07q_runtimeTargetHeader>strong{color:var(--mn-muted);background:var(--mn-fill);font-variant-numeric:tabular-nums;border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.IIa07q_capacityLine{align-items:center;gap:10px;padding:0 16px;display:flex}.IIa07q_capacityLine>div{background:var(--mn-fill);border-radius:999px;flex:1;height:4px;overflow:hidden}.IIa07q_capacityLine i{border-radius:inherit;background:var(--dsw-alias-brand-primary);height:100%;transition:width .25s;display:block}.IIa07q_capacityLine>span{min-width:88px;color:var(--mn-faint);text-align:right;font-variant-numeric:tabular-nums;font-size:11px}.IIa07q_runtimeTargetDescription{min-height:36px;color:var(--mn-faint);margin:8px 16px 14px;font-size:12px;line-height:18px}.IIa07q_runtimeEntry{--mn-provider-color:var(--mn-accent);border:.5px solid var(--mn-card-line);border-radius:var(--dsw-radius-md);padding:12px 14px 10px;position:relative}.IIa07q_runtimeEntry[data-importance=critical]{--mn-provider-color:var(--mn-priority)}.IIa07q_runtimeEntry[data-importance=low]{--mn-provider-color:var(--mn-faint)}.IIa07q_runtimeEntry[data-focused]{border-color:color-mix(in srgb, var(--mn-accent) 60%, var(--mn-card-line));box-shadow:0 0 0 2px color-mix(in srgb, var(--mn-accent) 14%, transparent)}.IIa07q_runtimeEntryMeta{justify-content:space-between;align-items:center;gap:12px;display:flex}.IIa07q_runtimeEntryMeta>span,.IIa07q_runtimeEntryBadges>span{color:var(--mn-muted);background:var(--mn-fill);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.IIa07q_runtimeEntry[data-importance=critical] .IIa07q_runtimeEntryMeta>span,.IIa07q_runtimeEntry[data-importance=critical] .IIa07q_runtimeEntryBadges>span:not(.IIa07q_runtimeEntryTarget){color:var(--mn-warn);background:color-mix(in srgb, var(--mn-warn) 12%, transparent)}.IIa07q_runtimeEntryMeta time{color:var(--mn-faint);text-overflow:ellipsis;white-space:nowrap;font-variant-numeric:tabular-nums;font-size:11px;overflow:hidden}.IIa07q_runtimeEntry>p{white-space:pre-wrap;overflow-wrap:anywhere;margin:8px 0;font-size:14px;line-height:22px}.IIa07q_runtimeEntry>select{margin-top:8px}.IIa07q_runtimeEntry footer{border-top:.5px solid var(--mn-line);justify-content:flex-end;align-items:center;gap:8px;min-height:32px;margin-top:8px;padding-top:8px;display:flex}.IIa07q_runtimeEntry footer>span{color:var(--mn-danger);margin-right:auto;font-size:12px}.IIa07q_runtimeEmpty{min-height:128px;color:var(--mn-faint);text-align:center;align-content:center;place-items:center;gap:6px;display:grid}.IIa07q_runtimeEmpty>span{font-size:20px;line-height:1}.IIa07q_runtimeEmpty p{margin:0;font-size:13px;line-height:20px}@media (width<=1000px){.IIa07q_runtimeSummaryGrid{grid-template-columns:1fr}}@media (width<=760px){.IIa07q_runtimeComposerHeading,.IIa07q_runtimeComposerActions{flex-direction:column;align-items:stretch}.IIa07q_runtimeComposerActions>*,.IIa07q_runtimeComposerActions button{width:100%}.IIa07q_runtimeBrowserToolbar{flex-direction:column;align-items:stretch}.IIa07q_runtimeFilterQuery{width:100%;min-width:0}}";
|
|
108
108
|
const id$1 = "dsh-mnemon-source-runtime/presentation/page.module.css";
|
|
109
109
|
if (typeof document !== "undefined") {
|
|
110
110
|
let tag = document.querySelector("style[data-plugin-css=" + JSON.stringify(id$1) + "]");
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
//#region src/defaults.ts
|
|
2
|
+
const DEFAULT_RUNTIME_MEMORY_LIMIT_BYTES = 10240;
|
|
3
|
+
const DEFAULT_RUNTIME_USER_LIMIT_BYTES = 4096;
|
|
4
|
+
const MAX_RUNTIME_MEMORY_LIMIT_BYTES = 1048576;
|
|
5
|
+
//#endregion
|
|
6
|
+
//#region src/contracts.ts
|
|
7
|
+
const RUNTIME_MEMORY_VERSION = 1;
|
|
8
|
+
const RUNTIME_ENTRY_DELIMITER = "\n§\n";
|
|
9
|
+
const RUNTIME_MEMORY_LIMITS = {
|
|
10
|
+
memory: DEFAULT_RUNTIME_MEMORY_LIMIT_BYTES,
|
|
11
|
+
user: DEFAULT_RUNTIME_USER_LIMIT_BYTES
|
|
12
|
+
};
|
|
13
|
+
/** The largest limit, in UTF-8 bytes, either target's file may be given. */
|
|
14
|
+
const RUNTIME_MEMORY_LIMIT_MAX_BYTES = MAX_RUNTIME_MEMORY_LIMIT_BYTES;
|
|
15
|
+
/** The longest git branch name a scope may hold. */
|
|
16
|
+
const RUNTIME_BRANCH_NAME_MAX = 128;
|
|
17
|
+
/** The characters a git branch name in a scope may use. */
|
|
18
|
+
const RUNTIME_BRANCH_NAME_PATTERN = /^[A-Za-z0-9._/-]+$/u;
|
|
19
|
+
/**
|
|
20
|
+
* Read a stored branch scope. Absent or malformed data reads as no scope, so an entry that
|
|
21
|
+
* a hand edit or another installation left malformed is projected on every branch instead
|
|
22
|
+
* of breaking the projection that reads it.
|
|
23
|
+
*/
|
|
24
|
+
function parseRuntimeBranches(value) {
|
|
25
|
+
if (!Array.isArray(value)) return void 0;
|
|
26
|
+
const branches = [];
|
|
27
|
+
for (const item of value) {
|
|
28
|
+
if (typeof item !== "string" || item === "" || item.length > 128 || !RUNTIME_BRANCH_NAME_PATTERN.test(item)) return void 0;
|
|
29
|
+
branches.push(item);
|
|
30
|
+
}
|
|
31
|
+
return branches;
|
|
32
|
+
}
|
|
33
|
+
/** The Runtime Source's directory under a storage root. */
|
|
34
|
+
const RUNTIME_DIRECTORY = "runtime";
|
|
35
|
+
/** The entries themselves, the source of truth the projections are written from. */
|
|
36
|
+
const RUNTIME_MEMORIES_FILE = "memories.json";
|
|
37
|
+
/** Each target's projection: its entries' plain content, the file a person reads. */
|
|
38
|
+
const RUNTIME_PROJECTION_FILES = {
|
|
39
|
+
user: "USER.md",
|
|
40
|
+
memory: "MEMORY.md"
|
|
41
|
+
};
|
|
42
|
+
/** Created exclusively while the files above are read or written; whoever copies them takes it too. */
|
|
43
|
+
const RUNTIME_LOCK_FILE = ".memories.lock";
|
|
44
|
+
/** A lock file older than this was left by a process that stopped, and may be taken over. */
|
|
45
|
+
const RUNTIME_LOCK_STALE_MS = 3e4;
|
|
46
|
+
/** The local archive of entries that left MEMORY.md while no Memory Space could take them (#336). */
|
|
47
|
+
const RUNTIME_ARCHIVE_DIRECTORY = "archived";
|
|
48
|
+
/** The longest content one entry may hold, in UTF-8 bytes. */
|
|
49
|
+
const RUNTIME_ENTRY_MAX_BYTES = 8192;
|
|
50
|
+
let utf8;
|
|
51
|
+
function joinedContent(entries, target) {
|
|
52
|
+
return entries.filter((entry) => entry.target === target).map((entry) => entry.content).join(RUNTIME_ENTRY_DELIMITER);
|
|
53
|
+
}
|
|
54
|
+
/** The UTF-8 bytes one target's entries take against its limit: their contents joined by the delimiter. */
|
|
55
|
+
function runtimeBytes(entries, target) {
|
|
56
|
+
utf8 ??= new TextEncoder();
|
|
57
|
+
return utf8.encode(joinedContent(entries, target)).byteLength;
|
|
58
|
+
}
|
|
59
|
+
/** One target's projection file, USER.md or MEMORY.md, exactly as the Runtime Source writes it. */
|
|
60
|
+
function runtimeProjection(entries, target) {
|
|
61
|
+
const content = joinedContent(entries, target);
|
|
62
|
+
return content === "" ? "" : `${content}\n`;
|
|
63
|
+
}
|
|
64
|
+
function isObject(value) {
|
|
65
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Count the entries of a parsed memories.json for a read-only inventory. It never throws: a file
|
|
69
|
+
* without an entry list is not `valid`, and a malformed entry is counted or skipped, never refused.
|
|
70
|
+
*/
|
|
71
|
+
function summarizeRuntimeMemories(value) {
|
|
72
|
+
const entries = isObject(value) && Array.isArray(value.entries) ? value.entries.filter(isObject) : [];
|
|
73
|
+
return {
|
|
74
|
+
valid: isObject(value) && Array.isArray(value.entries),
|
|
75
|
+
entries: entries.length,
|
|
76
|
+
user: entries.filter((entry) => entry.target === "user").length,
|
|
77
|
+
memory: entries.filter((entry) => entry.target === "memory").length
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
//#endregion
|
|
81
|
+
export { summarizeRuntimeMemories as _, RUNTIME_ENTRY_DELIMITER as a, MAX_RUNTIME_MEMORY_LIMIT_BYTES as b, RUNTIME_LOCK_STALE_MS as c, RUNTIME_MEMORY_LIMIT_MAX_BYTES as d, RUNTIME_MEMORY_VERSION as f, runtimeProjection as g, runtimeBytes as h, RUNTIME_DIRECTORY as i, RUNTIME_MEMORIES_FILE as l, parseRuntimeBranches as m, RUNTIME_BRANCH_NAME_MAX as n, RUNTIME_ENTRY_MAX_BYTES as o, RUNTIME_PROJECTION_FILES as p, RUNTIME_BRANCH_NAME_PATTERN as r, RUNTIME_LOCK_FILE as s, RUNTIME_ARCHIVE_DIRECTORY as t, RUNTIME_MEMORY_LIMITS as u, DEFAULT_RUNTIME_MEMORY_LIMIT_BYTES as v, DEFAULT_RUNTIME_USER_LIMIT_BYTES as y };
|
package/lib/contracts.d.ts
CHANGED
|
@@ -97,6 +97,8 @@ interface RuntimeMemoryLimits {
|
|
|
97
97
|
readonly user: number;
|
|
98
98
|
}
|
|
99
99
|
declare const RUNTIME_MEMORY_LIMITS: RuntimeMemoryLimits;
|
|
100
|
+
/** The largest limit, in UTF-8 bytes, either target's file may be given. */
|
|
101
|
+
declare const RUNTIME_MEMORY_LIMIT_MAX_BYTES: number;
|
|
100
102
|
/** The longest git branch name a scope may hold. */
|
|
101
103
|
declare const RUNTIME_BRANCH_NAME_MAX = 128;
|
|
102
104
|
/** The characters a git branch name in a scope may use. */
|
|
@@ -107,5 +109,41 @@ declare const RUNTIME_BRANCH_NAME_PATTERN: RegExp;
|
|
|
107
109
|
* of breaking the projection that reads it.
|
|
108
110
|
*/
|
|
109
111
|
declare function parseRuntimeBranches(value: unknown): string[] | undefined;
|
|
112
|
+
/** The Runtime Source's directory under a storage root. */
|
|
113
|
+
declare const RUNTIME_DIRECTORY = "runtime";
|
|
114
|
+
/** The entries themselves, the source of truth the projections are written from. */
|
|
115
|
+
declare const RUNTIME_MEMORIES_FILE = "memories.json";
|
|
116
|
+
/** Each target's projection: its entries' plain content, the file a person reads. */
|
|
117
|
+
declare const RUNTIME_PROJECTION_FILES: {
|
|
118
|
+
readonly user: "USER.md";
|
|
119
|
+
readonly memory: "MEMORY.md";
|
|
120
|
+
};
|
|
121
|
+
/** Created exclusively while the files above are read or written; whoever copies them takes it too. */
|
|
122
|
+
declare const RUNTIME_LOCK_FILE = ".memories.lock";
|
|
123
|
+
/** A lock file older than this was left by a process that stopped, and may be taken over. */
|
|
124
|
+
declare const RUNTIME_LOCK_STALE_MS = 30000;
|
|
125
|
+
/** The local archive of entries that left MEMORY.md while no Memory Space could take them (#336). */
|
|
126
|
+
declare const RUNTIME_ARCHIVE_DIRECTORY = "archived";
|
|
127
|
+
/** The longest content one entry may hold, in UTF-8 bytes. */
|
|
128
|
+
declare const RUNTIME_ENTRY_MAX_BYTES: number;
|
|
129
|
+
type RuntimeEntryText = Pick<RuntimeMemoryEntry, 'target' | 'content'>;
|
|
130
|
+
/** The UTF-8 bytes one target's entries take against its limit: their contents joined by the delimiter. */
|
|
131
|
+
declare function runtimeBytes(entries: ReadonlyArray<RuntimeEntryText>, target: RuntimeMemoryTarget): number;
|
|
132
|
+
/** One target's projection file, USER.md or MEMORY.md, exactly as the Runtime Source writes it. */
|
|
133
|
+
declare function runtimeProjection(entries: ReadonlyArray<RuntimeEntryText>, target: RuntimeMemoryTarget): string;
|
|
134
|
+
/** What a stored memories.json holds, counted without judging each entry. */
|
|
135
|
+
interface RuntimeMemoriesSummary {
|
|
136
|
+
/** Whether the file has an entry list at all. Without one, every count is 0. */
|
|
137
|
+
valid: boolean;
|
|
138
|
+
/** Every entry that is an object, whatever its target. */
|
|
139
|
+
entries: number;
|
|
140
|
+
user: number;
|
|
141
|
+
memory: number;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Count the entries of a parsed memories.json for a read-only inventory. It never throws: a file
|
|
145
|
+
* without an entry list is not `valid`, and a malformed entry is counted or skipped, never refused.
|
|
146
|
+
*/
|
|
147
|
+
declare function summarizeRuntimeMemories(value: unknown): RuntimeMemoriesSummary;
|
|
110
148
|
//#endregion
|
|
111
|
-
export { RUNTIME_BRANCH_NAME_MAX, RUNTIME_BRANCH_NAME_PATTERN, RUNTIME_ENTRY_DELIMITER, RUNTIME_MEMORY_LIMITS, RUNTIME_MEMORY_VERSION, RuntimeMemoryAction, RuntimeMemoryCompactedEntry, RuntimeMemoryEntry, RuntimeMemoryEntryOrigin, RuntimeMemoryImportance, RuntimeMemoryLimits, RuntimeMemoryMaintenancePlan, RuntimeMemoryMutation, RuntimeMemoryMutationResult, RuntimeMemorySnapshot, RuntimeMemoryTarget, RuntimeMemoryTargetView, RuntimeMemoryUsage, parseRuntimeBranches };
|
|
149
|
+
export { RUNTIME_ARCHIVE_DIRECTORY, RUNTIME_BRANCH_NAME_MAX, RUNTIME_BRANCH_NAME_PATTERN, RUNTIME_DIRECTORY, RUNTIME_ENTRY_DELIMITER, RUNTIME_ENTRY_MAX_BYTES, RUNTIME_LOCK_FILE, RUNTIME_LOCK_STALE_MS, RUNTIME_MEMORIES_FILE, RUNTIME_MEMORY_LIMITS, RUNTIME_MEMORY_LIMIT_MAX_BYTES, RUNTIME_MEMORY_VERSION, RUNTIME_PROJECTION_FILES, RuntimeMemoriesSummary, RuntimeMemoryAction, RuntimeMemoryCompactedEntry, RuntimeMemoryEntry, RuntimeMemoryEntryOrigin, RuntimeMemoryImportance, RuntimeMemoryLimits, RuntimeMemoryMaintenancePlan, RuntimeMemoryMutation, RuntimeMemoryMutationResult, RuntimeMemorySnapshot, RuntimeMemoryTarget, RuntimeMemoryTargetView, RuntimeMemoryUsage, parseRuntimeBranches, runtimeBytes, runtimeProjection, summarizeRuntimeMemories };
|
package/lib/contracts.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as RUNTIME_MEMORY_VERSION, i as
|
|
2
|
-
export { RUNTIME_BRANCH_NAME_MAX, RUNTIME_BRANCH_NAME_PATTERN, RUNTIME_ENTRY_DELIMITER, RUNTIME_MEMORY_LIMITS, RUNTIME_MEMORY_VERSION, parseRuntimeBranches };
|
|
1
|
+
import { _ as summarizeRuntimeMemories, a as RUNTIME_ENTRY_DELIMITER, c as RUNTIME_LOCK_STALE_MS, d as RUNTIME_MEMORY_LIMIT_MAX_BYTES, f as RUNTIME_MEMORY_VERSION, g as runtimeProjection, h as runtimeBytes, i as RUNTIME_DIRECTORY, l as RUNTIME_MEMORIES_FILE, m as parseRuntimeBranches, n as RUNTIME_BRANCH_NAME_MAX, o as RUNTIME_ENTRY_MAX_BYTES, p as RUNTIME_PROJECTION_FILES, r as RUNTIME_BRANCH_NAME_PATTERN, s as RUNTIME_LOCK_FILE, t as RUNTIME_ARCHIVE_DIRECTORY, u as RUNTIME_MEMORY_LIMITS } from "./contracts-DycwaUv_.js";
|
|
2
|
+
export { RUNTIME_ARCHIVE_DIRECTORY, RUNTIME_BRANCH_NAME_MAX, RUNTIME_BRANCH_NAME_PATTERN, RUNTIME_DIRECTORY, RUNTIME_ENTRY_DELIMITER, RUNTIME_ENTRY_MAX_BYTES, RUNTIME_LOCK_FILE, RUNTIME_LOCK_STALE_MS, RUNTIME_MEMORIES_FILE, RUNTIME_MEMORY_LIMITS, RUNTIME_MEMORY_LIMIT_MAX_BYTES, RUNTIME_MEMORY_VERSION, RUNTIME_PROJECTION_FILES, parseRuntimeBranches, runtimeBytes, runtimeProjection, summarizeRuntimeMemories };
|
package/lib/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RUNTIME_BRANCH_NAME_MAX, RUNTIME_BRANCH_NAME_PATTERN, RUNTIME_ENTRY_DELIMITER, RUNTIME_MEMORY_LIMITS, RUNTIME_MEMORY_VERSION, RuntimeMemoryAction, RuntimeMemoryCompactedEntry, RuntimeMemoryEntry, RuntimeMemoryEntryOrigin, RuntimeMemoryImportance, RuntimeMemoryLimits, RuntimeMemoryMaintenancePlan, RuntimeMemoryMutation, RuntimeMemoryMutationResult, RuntimeMemorySnapshot, RuntimeMemoryTarget, RuntimeMemoryTargetView, RuntimeMemoryUsage, parseRuntimeBranches } from "./contracts.js";
|
|
1
|
+
import { RUNTIME_ARCHIVE_DIRECTORY, RUNTIME_BRANCH_NAME_MAX, RUNTIME_BRANCH_NAME_PATTERN, RUNTIME_DIRECTORY, RUNTIME_ENTRY_DELIMITER, RUNTIME_ENTRY_MAX_BYTES, RUNTIME_LOCK_FILE, RUNTIME_LOCK_STALE_MS, RUNTIME_MEMORIES_FILE, RUNTIME_MEMORY_LIMITS, RUNTIME_MEMORY_LIMIT_MAX_BYTES, RUNTIME_MEMORY_VERSION, RUNTIME_PROJECTION_FILES, RuntimeMemoriesSummary, RuntimeMemoryAction, RuntimeMemoryCompactedEntry, RuntimeMemoryEntry, RuntimeMemoryEntryOrigin, RuntimeMemoryImportance, RuntimeMemoryLimits, RuntimeMemoryMaintenancePlan, RuntimeMemoryMutation, RuntimeMemoryMutationResult, RuntimeMemorySnapshot, RuntimeMemoryTarget, RuntimeMemoryTargetView, RuntimeMemoryUsage, parseRuntimeBranches, runtimeBytes, runtimeProjection, summarizeRuntimeMemories } from "./contracts.js";
|
|
2
2
|
import z from "@deepseek-ai/schemastery";
|
|
3
3
|
import { MemorySourceDefinition } from "dsh-mnemon/contracts";
|
|
4
4
|
import { Context } from "@deepseek-ai/cordis";
|
|
@@ -21,4 +21,4 @@ declare const inject: string[];
|
|
|
21
21
|
declare const memoryPlugin: import("dsh-mnemon/extension-sdk").MemoryPluginDescriptor;
|
|
22
22
|
declare function apply(ctx: Context, config?: Config): void;
|
|
23
23
|
//#endregion
|
|
24
|
-
export { Config, type RUNTIME_BRANCH_NAME_MAX, type RUNTIME_BRANCH_NAME_PATTERN, type RUNTIME_ENTRY_DELIMITER, type RUNTIME_MEMORY_LIMITS, RUNTIME_MEMORY_SOURCE, type RUNTIME_MEMORY_VERSION, type RuntimeMemoryAction, type RuntimeMemoryCompactedEntry, type RuntimeMemoryEntry, type RuntimeMemoryEntryOrigin, type RuntimeMemoryImportance, type RuntimeMemoryLimits, type RuntimeMemoryMaintenancePlan, type RuntimeMemoryMutation, type RuntimeMemoryMutationResult, type RuntimeMemorySnapshot, type RuntimeMemoryTarget, type RuntimeMemoryTargetView, type RuntimeMemoryUsage, apply, createRuntimeMemorySource, inject, memoryPlugin, name, type parseRuntimeBranches };
|
|
24
|
+
export { Config, type RUNTIME_ARCHIVE_DIRECTORY, type RUNTIME_BRANCH_NAME_MAX, type RUNTIME_BRANCH_NAME_PATTERN, type RUNTIME_DIRECTORY, type RUNTIME_ENTRY_DELIMITER, type RUNTIME_ENTRY_MAX_BYTES, type RUNTIME_LOCK_FILE, type RUNTIME_LOCK_STALE_MS, type RUNTIME_MEMORIES_FILE, type RUNTIME_MEMORY_LIMITS, type RUNTIME_MEMORY_LIMIT_MAX_BYTES, RUNTIME_MEMORY_SOURCE, type RUNTIME_MEMORY_VERSION, type RUNTIME_PROJECTION_FILES, type RuntimeMemoriesSummary, type RuntimeMemoryAction, type RuntimeMemoryCompactedEntry, type RuntimeMemoryEntry, type RuntimeMemoryEntryOrigin, type RuntimeMemoryImportance, type RuntimeMemoryLimits, type RuntimeMemoryMaintenancePlan, type RuntimeMemoryMutation, type RuntimeMemoryMutationResult, type RuntimeMemorySnapshot, type RuntimeMemoryTarget, type RuntimeMemoryTargetView, type RuntimeMemoryUsage, apply, createRuntimeMemorySource, inject, memoryPlugin, name, type parseRuntimeBranches, type runtimeBytes, type runtimeProjection, type summarizeRuntimeMemories };
|
package/lib/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as
|
|
1
|
+
import { a as RUNTIME_ENTRY_DELIMITER, b as MAX_RUNTIME_MEMORY_LIMIT_BYTES, g as runtimeProjection, h as runtimeBytes, i as RUNTIME_DIRECTORY, l as RUNTIME_MEMORIES_FILE, m as parseRuntimeBranches, o as RUNTIME_ENTRY_MAX_BYTES, p as RUNTIME_PROJECTION_FILES, r as RUNTIME_BRANCH_NAME_PATTERN, s as RUNTIME_LOCK_FILE, t as RUNTIME_ARCHIVE_DIRECTORY, u as RUNTIME_MEMORY_LIMITS } from "./contracts-DycwaUv_.js";
|
|
2
2
|
import { createMemoryMutationReceipt, defineMemoryPlugin, defineMemorySource, installMemory, memoryConfigurationDigest, memoryInputRecord, memoryInputStringArray, memoryInputText, truncateMemoryText } from "dsh-mnemon/extension-sdk";
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
import { basename, isAbsolute, join } from "node:path";
|
|
@@ -75,9 +75,7 @@ function resolveGitBranch(cwd) {
|
|
|
75
75
|
//#endregion
|
|
76
76
|
//#region src/controller.ts
|
|
77
77
|
const LOCK_TIMEOUT_MS = 5e3;
|
|
78
|
-
const LOCK_STALE_MS = 3e4;
|
|
79
78
|
const LOCK_RETRY_MS = 20;
|
|
80
|
-
const MAX_ENTRY_BYTES = 8192;
|
|
81
79
|
/** Append to a file that is not a symbolic link; the open fails on one. */
|
|
82
80
|
function appendWithoutLinks(path, text) {
|
|
83
81
|
const descriptor = openSync(path, constants.O_WRONLY | constants.O_APPEND | constants.O_CREAT | (constants.O_NOFOLLOW ?? 0), 384);
|
|
@@ -147,7 +145,7 @@ function normalizeContent(value, field) {
|
|
|
147
145
|
if (content === "") throw new Error(`${field} is required`);
|
|
148
146
|
if (content.includes("§")) throw new Error(`${field} must not contain the reserved § entry delimiter`);
|
|
149
147
|
const bytes = Buffer.byteLength(content, "utf8");
|
|
150
|
-
if (bytes >
|
|
148
|
+
if (bytes > 8192) throw new Error(`${field} is too large (${bytes} bytes; max ${RUNTIME_ENTRY_MAX_BYTES})`);
|
|
151
149
|
return content;
|
|
152
150
|
}
|
|
153
151
|
function parseOrigin(value) {
|
|
@@ -177,14 +175,6 @@ function parseEntry(value) {
|
|
|
177
175
|
...origin === void 0 ? {} : { origin }
|
|
178
176
|
};
|
|
179
177
|
}
|
|
180
|
-
function byteCount(entries, target) {
|
|
181
|
-
const content = entries.filter((entry) => entry.target === target).map((entry) => entry.content).join(RUNTIME_ENTRY_DELIMITER);
|
|
182
|
-
return Buffer.byteLength(content, "utf8");
|
|
183
|
-
}
|
|
184
|
-
function markdown(entries, target) {
|
|
185
|
-
const content = entries.filter((entry) => entry.target === target).map((entry) => entry.content).join(RUNTIME_ENTRY_DELIMITER);
|
|
186
|
-
return content === "" ? "" : `${content}\n`;
|
|
187
|
-
}
|
|
188
178
|
function age(timestamp, projectedAt) {
|
|
189
179
|
const time = Date.parse(timestamp);
|
|
190
180
|
if (!Number.isFinite(time)) return "unknown";
|
|
@@ -193,12 +183,20 @@ function age(timestamp, projectedAt) {
|
|
|
193
183
|
}
|
|
194
184
|
/** Prompt-only annotations; stored content, matching and capacity stay unchanged. */
|
|
195
185
|
function contextMarkdown(entries, target, projectedAt) {
|
|
196
|
-
return entries.filter((entry) => entry.target === target).map((entry) =>
|
|
186
|
+
return entries.filter((entry) => entry.target === target).map((entry) => {
|
|
187
|
+
const annotations = [];
|
|
188
|
+
if (entry.importance !== "normal") annotations.push(`importance=${entry.importance}`);
|
|
189
|
+
for (const [name, timestamp] of [["created", entry.created_at], ["updated", entry.updated_at]]) {
|
|
190
|
+
const elapsed = age(timestamp, projectedAt);
|
|
191
|
+
if (elapsed !== "0d") annotations.push(`${name}=${elapsed}`);
|
|
192
|
+
}
|
|
193
|
+
return `${annotations.length === 0 ? "" : `[${annotations.join("; ")}]\n`}${entry.content}`;
|
|
194
|
+
}).join(RUNTIME_ENTRY_DELIMITER);
|
|
197
195
|
}
|
|
198
196
|
function revision(file) {
|
|
199
197
|
return createHash("sha256").update(JSON.stringify(file)).digest("hex");
|
|
200
198
|
}
|
|
201
|
-
function prepareMutation(before, request, now) {
|
|
199
|
+
function prepareMutation(before, request, now, preserveImportance = false) {
|
|
202
200
|
if (!isTarget(request.target)) throw new Error("target must be memory or user");
|
|
203
201
|
if (![
|
|
204
202
|
"add",
|
|
@@ -250,12 +248,19 @@ function prepareMutation(before, request, now) {
|
|
|
250
248
|
const previous = entries[index];
|
|
251
249
|
const compactableEntries = entries.filter((entry, entryIndex) => entry.target === request.target && entryIndex !== index);
|
|
252
250
|
if (request.action === "replace") {
|
|
251
|
+
const ranks = {
|
|
252
|
+
low: 0,
|
|
253
|
+
normal: 1,
|
|
254
|
+
critical: 2
|
|
255
|
+
};
|
|
256
|
+
const requested = request.importance ?? previous.importance;
|
|
257
|
+
const importance = preserveImportance && ranks[requested] < ranks[previous.importance] ? previous.importance : requested;
|
|
253
258
|
const content = normalizeContent(request.content, "content");
|
|
254
259
|
const pendingEntry = {
|
|
255
260
|
...previous,
|
|
256
261
|
content,
|
|
257
262
|
updated_at: now,
|
|
258
|
-
importance
|
|
263
|
+
importance
|
|
259
264
|
};
|
|
260
265
|
if (branchScope !== void 0) {
|
|
261
266
|
if (branchScope.length === 0) delete pendingEntry.branches;
|
|
@@ -269,7 +274,7 @@ function prepareMutation(before, request, now) {
|
|
|
269
274
|
pendingEntry,
|
|
270
275
|
excludedEntry: previous,
|
|
271
276
|
fields: {
|
|
272
|
-
message: "Entry replaced.",
|
|
277
|
+
message: importance === requested ? "Entry replaced." : "Entry replaced; original importance preserved.",
|
|
273
278
|
replaced: {
|
|
274
279
|
from: previous.content,
|
|
275
280
|
to: content
|
|
@@ -365,14 +370,14 @@ var RuntimeMemoryController = class RuntimeMemoryController {
|
|
|
365
370
|
memory: limits.memory,
|
|
366
371
|
user: limits.user
|
|
367
372
|
};
|
|
368
|
-
this.directory = join(runner.effectiveDataDir(),
|
|
369
|
-
this.sourcePath = join(this.directory,
|
|
370
|
-
this.memoryPath = join(this.directory,
|
|
371
|
-
this.localUserPath = join(this.directory,
|
|
372
|
-
this.lockPath = join(this.directory,
|
|
373
|
-
this.archivePath = join(this.directory,
|
|
374
|
-
this.archiveSourcePath = join(this.directory,
|
|
375
|
-
const userDirectory = userRunner === void 0 ? this.directory : join(userRunner.effectiveDataDir(),
|
|
373
|
+
this.directory = join(runner.effectiveDataDir(), RUNTIME_DIRECTORY);
|
|
374
|
+
this.sourcePath = join(this.directory, RUNTIME_MEMORIES_FILE);
|
|
375
|
+
this.memoryPath = join(this.directory, RUNTIME_PROJECTION_FILES.memory);
|
|
376
|
+
this.localUserPath = join(this.directory, RUNTIME_PROJECTION_FILES.user);
|
|
377
|
+
this.lockPath = join(this.directory, RUNTIME_LOCK_FILE);
|
|
378
|
+
this.archivePath = join(this.directory, RUNTIME_ARCHIVE_DIRECTORY, "MEMORY.md");
|
|
379
|
+
this.archiveSourcePath = join(this.directory, RUNTIME_ARCHIVE_DIRECTORY, "memories.jsonl");
|
|
380
|
+
const userDirectory = userRunner === void 0 ? this.directory : join(userRunner.effectiveDataDir(), RUNTIME_DIRECTORY);
|
|
376
381
|
this.userController = userDirectory === this.directory || userRunner === void 0 ? void 0 : new RuntimeMemoryController(userRunner, now, this.limits);
|
|
377
382
|
this.userPath = this.userController?.userPath ?? this.localUserPath;
|
|
378
383
|
this.userSourcePath = this.userController?.sourcePath ?? this.sourcePath;
|
|
@@ -424,8 +429,6 @@ var RuntimeMemoryController = class RuntimeMemoryController {
|
|
|
424
429
|
}
|
|
425
430
|
}
|
|
426
431
|
};
|
|
427
|
-
const storeMemory = this.targetView(entries, "memory");
|
|
428
|
-
const storeUser = this.targetView(entries, "user");
|
|
429
432
|
const visibleEntries = branchScope === void 0 ? entries : entries.filter((entry) => entry.target === "user" || entryMatchesBranch(entry, branchScope));
|
|
430
433
|
const branchLine = branchScope === void 0 ? "" : `\nGit branch: ${branchScope}${local.hidden > 0 ? ` (${local.hidden} branch-scoped entr${local.hidden === 1 ? "y" : "ies"} hidden)` : ""}`;
|
|
431
434
|
return {
|
|
@@ -436,15 +439,14 @@ var RuntimeMemoryController = class RuntimeMemoryController {
|
|
|
436
439
|
})),
|
|
437
440
|
totalEntries: entries.length,
|
|
438
441
|
text: `MNEMON RUNTIME MEMORY SNAPSHOT
|
|
439
|
-
|
|
440
|
-
Metadata lines are annotations; created/updated are ages at projection in whole days (future/unknown for future/invalid timestamps). Current instructions win. For old_text/oldText, use entry content only.
|
|
442
|
+
Entry annotations default to importance=normal and ages=0d (whole days at projection; future/unknown for future/invalid timestamps). Current instructions win. For old_text/oldText, use entry content only.${branchLine}
|
|
441
443
|
|
|
442
|
-
|
|
444
|
+
USER.md (user profile)
|
|
443
445
|
<runtime-memory-file name="USER.md">
|
|
444
446
|
${user || "(empty)"}
|
|
445
447
|
</runtime-memory-file>
|
|
446
448
|
|
|
447
|
-
|
|
449
|
+
MEMORY.md (working reference)
|
|
448
450
|
<runtime-memory-file name="MEMORY.md">
|
|
449
451
|
${memory || "(empty)"}
|
|
450
452
|
</runtime-memory-file>`
|
|
@@ -475,20 +477,20 @@ ${memory || "(empty)"}
|
|
|
475
477
|
};
|
|
476
478
|
});
|
|
477
479
|
}
|
|
478
|
-
mutate(request) {
|
|
479
|
-
if (request.target === "user" && this.userController !== void 0) return this.userController.mutate(request);
|
|
480
|
-
const operation = this.queue.then(() => this.withLock(() => this.mutateLocked(request)));
|
|
480
|
+
mutate(request, options = {}) {
|
|
481
|
+
if (request.target === "user" && this.userController !== void 0) return this.userController.mutate(request, options);
|
|
482
|
+
const operation = this.queue.then(() => this.withLock(() => this.mutateLocked(request, options.preserveImportance)));
|
|
481
483
|
this.queue = operation.catch(() => void 0);
|
|
482
484
|
return operation;
|
|
483
485
|
}
|
|
484
486
|
/** Resolve exactly which committed entries survive a blocked mutation and are safe to compact. */
|
|
485
|
-
planMaintenance(request) {
|
|
486
|
-
if (request.target === "user" && this.userController !== void 0) return this.userController.planMaintenance(request);
|
|
487
|
+
planMaintenance(request, options = {}) {
|
|
488
|
+
if (request.target === "user" && this.userController !== void 0) return this.userController.planMaintenance(request, options);
|
|
487
489
|
const operation = this.queue.then(() => this.withLock(() => {
|
|
488
490
|
const file = this.readSource();
|
|
489
|
-
const prepared = prepareMutation(file.entries, request, this.now().toISOString());
|
|
490
|
-
const used =
|
|
491
|
-
const projected =
|
|
491
|
+
const prepared = prepareMutation(file.entries, request, this.now().toISOString(), options.preserveImportance);
|
|
492
|
+
const used = runtimeBytes(file.entries, request.target);
|
|
493
|
+
const projected = runtimeBytes(prepared.projectedEntries, request.target);
|
|
492
494
|
const limit = this.limits[request.target];
|
|
493
495
|
return {
|
|
494
496
|
revision: revision(file),
|
|
@@ -516,13 +518,13 @@ ${memory || "(empty)"}
|
|
|
516
518
|
* local archive first, so a limit with no Memory Space to archive into never loses memory.
|
|
517
519
|
*/
|
|
518
520
|
compactAndMutate(expectedRevision, request, compacted, maxCompactedBytes, options = {}) {
|
|
519
|
-
if (request.target === "user" && this.userController !== void 0) return this.userController.compactAndMutate(expectedRevision, request, compacted, maxCompactedBytes);
|
|
521
|
+
if (request.target === "user" && this.userController !== void 0) return this.userController.compactAndMutate(expectedRevision, request, compacted, maxCompactedBytes, options);
|
|
520
522
|
const operation = this.queue.then(() => this.withLock(() => {
|
|
521
523
|
const file = this.readSource();
|
|
522
524
|
const beforeRevision = revision(file);
|
|
523
525
|
if (beforeRevision !== expectedRevision) throw new RuntimeMemoryConflictError();
|
|
524
526
|
const now = this.now().toISOString();
|
|
525
|
-
const prepared = prepareMutation(file.entries, request, now);
|
|
527
|
+
const prepared = prepareMutation(file.entries, request, now, options.preserveImportance);
|
|
526
528
|
const compactedByteBudget = maxCompactedBytes ?? this.limits[request.target];
|
|
527
529
|
if (!Number.isInteger(compactedByteBudget) || compactedByteBudget < 0 || compactedByteBudget > this.limits[request.target]) throw new Error("compaction byte budget is invalid");
|
|
528
530
|
if (!prepared.changed) return this.result(request.target, prepared.projectedEntries, prepared.fields);
|
|
@@ -532,9 +534,9 @@ ${memory || "(empty)"}
|
|
|
532
534
|
const fitted = packCompactionCandidates(replacements, request.target, compactedByteBudget);
|
|
533
535
|
const targetEntries = [...fitted, ...prepared.pendingEntry === void 0 ? [] : [prepared.pendingEntry]];
|
|
534
536
|
const entries = [...file.entries.filter((entry) => entry.target !== request.target), ...targetEntries];
|
|
535
|
-
const used =
|
|
537
|
+
const used = runtimeBytes(entries, request.target);
|
|
536
538
|
const limit = this.limits[request.target];
|
|
537
|
-
if (used > limit) throw new RuntimeMemoryCapacityError(request.target,
|
|
539
|
+
if (used > limit) throw new RuntimeMemoryCapacityError(request.target, runtimeBytes(file.entries, request.target), used, limit);
|
|
538
540
|
const next = {
|
|
539
541
|
version: 1,
|
|
540
542
|
entries
|
|
@@ -556,7 +558,7 @@ ${memory || "(empty)"}
|
|
|
556
558
|
}
|
|
557
559
|
/** Append entries to the local archive: JSON Lines to restore from, and Markdown to read. */
|
|
558
560
|
archiveLocally(entries, fromRevision, archivedAt) {
|
|
559
|
-
const directory = join(this.directory,
|
|
561
|
+
const directory = join(this.directory, RUNTIME_ARCHIVE_DIRECTORY);
|
|
560
562
|
mkdirSync(directory, {
|
|
561
563
|
recursive: true,
|
|
562
564
|
mode: 448
|
|
@@ -590,13 +592,13 @@ ${memory || "(empty)"}
|
|
|
590
592
|
this.persist(file);
|
|
591
593
|
});
|
|
592
594
|
}
|
|
593
|
-
mutateLocked(request) {
|
|
595
|
+
mutateLocked(request, preserveImportance = false) {
|
|
594
596
|
const file = this.readSource();
|
|
595
|
-
const prepared = prepareMutation(file.entries, request, this.now().toISOString());
|
|
597
|
+
const prepared = prepareMutation(file.entries, request, this.now().toISOString(), preserveImportance);
|
|
596
598
|
if (!prepared.changed) return this.result(request.target, prepared.projectedEntries, prepared.fields);
|
|
597
|
-
const used =
|
|
599
|
+
const used = runtimeBytes(prepared.projectedEntries, request.target);
|
|
598
600
|
const limit = this.limits[request.target];
|
|
599
|
-
if (used > limit) throw new RuntimeMemoryCapacityError(request.target,
|
|
601
|
+
if (used > limit) throw new RuntimeMemoryCapacityError(request.target, runtimeBytes(file.entries, request.target), used, limit);
|
|
600
602
|
this.persist({
|
|
601
603
|
version: 1,
|
|
602
604
|
entries: prepared.projectedEntries
|
|
@@ -610,7 +612,7 @@ ${memory || "(empty)"}
|
|
|
610
612
|
target,
|
|
611
613
|
entryCount: entries.filter((entry) => entry.target === target).length,
|
|
612
614
|
usage: {
|
|
613
|
-
used:
|
|
615
|
+
used: runtimeBytes(entries, target),
|
|
614
616
|
limit: this.limits[target]
|
|
615
617
|
},
|
|
616
618
|
...fields.added === void 0 ? {} : { added: fields.added },
|
|
@@ -622,7 +624,7 @@ ${memory || "(empty)"}
|
|
|
622
624
|
return {
|
|
623
625
|
target,
|
|
624
626
|
entryCount: entries.filter((entry) => entry.target === target).length,
|
|
625
|
-
used:
|
|
627
|
+
used: runtimeBytes(entries, target),
|
|
626
628
|
limit: this.limits[target],
|
|
627
629
|
markdownPath: target === "memory" ? this.memoryPath : this.userPath
|
|
628
630
|
};
|
|
@@ -667,8 +669,8 @@ ${memory || "(empty)"}
|
|
|
667
669
|
});
|
|
668
670
|
const nonce = `${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}`;
|
|
669
671
|
const writes = [
|
|
670
|
-
[this.localUserPath,
|
|
671
|
-
[this.memoryPath,
|
|
672
|
+
[this.localUserPath, runtimeProjection(file.entries, "user")],
|
|
673
|
+
[this.memoryPath, runtimeProjection(file.entries, "memory")],
|
|
672
674
|
[this.sourcePath, `${JSON.stringify(file, null, 2)}\n`]
|
|
673
675
|
];
|
|
674
676
|
const temporaries = writes.map(([path]) => join(this.directory, `.${basename(path)}.${nonce}.tmp`));
|
|
@@ -684,7 +686,7 @@ ${memory || "(empty)"}
|
|
|
684
686
|
}
|
|
685
687
|
repairProjections(file) {
|
|
686
688
|
for (const [path, target] of [[this.localUserPath, "user"], [this.memoryPath, "memory"]]) {
|
|
687
|
-
const expected =
|
|
689
|
+
const expected = runtimeProjection(file.entries, target);
|
|
688
690
|
let current;
|
|
689
691
|
try {
|
|
690
692
|
current = readFileSync(path, "utf8");
|
|
@@ -712,7 +714,7 @@ ${memory || "(empty)"}
|
|
|
712
714
|
} catch (error) {
|
|
713
715
|
if ((isRecord(error) && typeof error.code === "string" ? error.code : void 0) !== "EEXIST") throw error;
|
|
714
716
|
try {
|
|
715
|
-
if (Date.now() - statSync(this.lockPath).mtimeMs >
|
|
717
|
+
if (Date.now() - statSync(this.lockPath).mtimeMs > 3e4) {
|
|
716
718
|
rmSync(this.lockPath, { force: true });
|
|
717
719
|
continue;
|
|
718
720
|
}
|
|
@@ -891,7 +893,7 @@ function createRuntimeMemorySource(config = {}) {
|
|
|
891
893
|
if (request.mode === "read") {
|
|
892
894
|
let value;
|
|
893
895
|
if (request.operation === "snapshot") value = controller.snapshot();
|
|
894
|
-
else if (request.operation === "maintenance-plan") value = await controller.planMaintenance(runtimeMutation(request.input));
|
|
896
|
+
else if (request.operation === "maintenance-plan") value = await controller.planMaintenance(runtimeMutation(request.input), { preserveImportance: input.preserveImportance === true });
|
|
895
897
|
else throw new Error("unsupported Runtime management read operation: " + request.operation);
|
|
896
898
|
return {
|
|
897
899
|
revision: controller.snapshot().revision,
|
|
@@ -900,7 +902,7 @@ function createRuntimeMemorySource(config = {}) {
|
|
|
900
902
|
}
|
|
901
903
|
if (!request.confirmed) throw new Error("Runtime management mutation requires explicit confirmation");
|
|
902
904
|
let result;
|
|
903
|
-
if (request.operation === "mutate") result = await controller.mutate(runtimeMutation(request.input));
|
|
905
|
+
if (request.operation === "mutate") result = await controller.mutate(runtimeMutation(request.input), { preserveImportance: input.preserveImportance === true });
|
|
904
906
|
else if (request.operation === "compact-and-mutate") {
|
|
905
907
|
if (!Array.isArray(input.compacted)) throw new Error("compacted must be an array");
|
|
906
908
|
const compacted = input.compacted.map((value) => {
|
|
@@ -914,7 +916,10 @@ function createRuntimeMemorySource(config = {}) {
|
|
|
914
916
|
};
|
|
915
917
|
});
|
|
916
918
|
if (input.archive !== void 0 && input.archive !== "local") throw new Error("archive must be \"local\" when given");
|
|
917
|
-
result = await controller.compactAndMutate(memoryInputText(input.revision, "revision", 300), runtimeMutation(input.mutation), compacted, typeof input.maxBytes === "number" ? input.maxBytes : void 0,
|
|
919
|
+
result = await controller.compactAndMutate(memoryInputText(input.revision, "revision", 300), runtimeMutation(input.mutation), compacted, typeof input.maxBytes === "number" ? input.maxBytes : void 0, {
|
|
920
|
+
...input.archive === "local" ? { archive: "local" } : {},
|
|
921
|
+
preserveImportance: input.preserveImportance === true
|
|
922
|
+
});
|
|
918
923
|
} else throw new Error("unsupported Runtime management mutation operation: " + request.operation);
|
|
919
924
|
return {
|
|
920
925
|
revision: controller.snapshot().revision,
|
|
@@ -922,7 +927,7 @@ function createRuntimeMemorySource(config = {}) {
|
|
|
922
927
|
};
|
|
923
928
|
},
|
|
924
929
|
async mutate(request) {
|
|
925
|
-
const result = await controller.mutate(runtimeMutation(request.input));
|
|
930
|
+
const result = await controller.mutate(runtimeMutation(request.input), { preserveImportance: true });
|
|
926
931
|
const revision = controller.snapshot().revision;
|
|
927
932
|
return createMemoryMutationReceipt(request.view.id, request.offer.id, context.sourceInstanceKey, revision, result, "committed");
|
|
928
933
|
}
|
package/lib/types/contracts.d.ts
CHANGED
|
@@ -96,6 +96,8 @@ export interface RuntimeMemoryLimits {
|
|
|
96
96
|
readonly user: number;
|
|
97
97
|
}
|
|
98
98
|
export declare const RUNTIME_MEMORY_LIMITS: RuntimeMemoryLimits;
|
|
99
|
+
/** The largest limit, in UTF-8 bytes, either target's file may be given. */
|
|
100
|
+
export declare const RUNTIME_MEMORY_LIMIT_MAX_BYTES: number;
|
|
99
101
|
/** The longest git branch name a scope may hold. */
|
|
100
102
|
export declare const RUNTIME_BRANCH_NAME_MAX = 128;
|
|
101
103
|
/** The characters a git branch name in a scope may use. */
|
|
@@ -106,3 +108,40 @@ export declare const RUNTIME_BRANCH_NAME_PATTERN: RegExp;
|
|
|
106
108
|
* of breaking the projection that reads it.
|
|
107
109
|
*/
|
|
108
110
|
export declare function parseRuntimeBranches(value: unknown): string[] | undefined;
|
|
111
|
+
/** The Runtime Source's directory under a storage root. */
|
|
112
|
+
export declare const RUNTIME_DIRECTORY = "runtime";
|
|
113
|
+
/** The entries themselves, the source of truth the projections are written from. */
|
|
114
|
+
export declare const RUNTIME_MEMORIES_FILE = "memories.json";
|
|
115
|
+
/** Each target's projection: its entries' plain content, the file a person reads. */
|
|
116
|
+
export declare const RUNTIME_PROJECTION_FILES: {
|
|
117
|
+
readonly user: "USER.md";
|
|
118
|
+
readonly memory: "MEMORY.md";
|
|
119
|
+
};
|
|
120
|
+
/** Created exclusively while the files above are read or written; whoever copies them takes it too. */
|
|
121
|
+
export declare const RUNTIME_LOCK_FILE = ".memories.lock";
|
|
122
|
+
/** A lock file older than this was left by a process that stopped, and may be taken over. */
|
|
123
|
+
export declare const RUNTIME_LOCK_STALE_MS = 30000;
|
|
124
|
+
/** The local archive of entries that left MEMORY.md while no Memory Space could take them (#336). */
|
|
125
|
+
export declare const RUNTIME_ARCHIVE_DIRECTORY = "archived";
|
|
126
|
+
/** The longest content one entry may hold, in UTF-8 bytes. */
|
|
127
|
+
export declare const RUNTIME_ENTRY_MAX_BYTES: number;
|
|
128
|
+
type RuntimeEntryText = Pick<RuntimeMemoryEntry, 'target' | 'content'>;
|
|
129
|
+
/** The UTF-8 bytes one target's entries take against its limit: their contents joined by the delimiter. */
|
|
130
|
+
export declare function runtimeBytes(entries: ReadonlyArray<RuntimeEntryText>, target: RuntimeMemoryTarget): number;
|
|
131
|
+
/** One target's projection file, USER.md or MEMORY.md, exactly as the Runtime Source writes it. */
|
|
132
|
+
export declare function runtimeProjection(entries: ReadonlyArray<RuntimeEntryText>, target: RuntimeMemoryTarget): string;
|
|
133
|
+
/** What a stored memories.json holds, counted without judging each entry. */
|
|
134
|
+
export interface RuntimeMemoriesSummary {
|
|
135
|
+
/** Whether the file has an entry list at all. Without one, every count is 0. */
|
|
136
|
+
valid: boolean;
|
|
137
|
+
/** Every entry that is an object, whatever its target. */
|
|
138
|
+
entries: number;
|
|
139
|
+
user: number;
|
|
140
|
+
memory: number;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Count the entries of a parsed memories.json for a read-only inventory. It never throws: a file
|
|
144
|
+
* without an entry list is not `valid`, and a malformed entry is counted or skipped, never refused.
|
|
145
|
+
*/
|
|
146
|
+
export declare function summarizeRuntimeMemories(value: unknown): RuntimeMemoriesSummary;
|
|
147
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-mnemon-source-runtime",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.16",
|
|
4
4
|
"description": "Self-contained runtime Source for Composable View Memory.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -55,12 +55,12 @@
|
|
|
55
55
|
"react": "^18.2.0"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
|
-
"@deepseek-ai/dsh-client-ui-primitives": "0.1
|
|
58
|
+
"@deepseek-ai/dsh-client-ui-primitives": "0.2.1-rc.2",
|
|
59
59
|
"@testing-library/react": "^16.3.0",
|
|
60
60
|
"@types/node": "^22.0.0",
|
|
61
61
|
"@types/react": "^18.3.0",
|
|
62
62
|
"@types/react-dom": "^18.3.0",
|
|
63
|
-
"dsh-mnemon": "^0.5.
|
|
63
|
+
"dsh-mnemon": "^0.5.35",
|
|
64
64
|
"jsdom": "^26.0.0",
|
|
65
65
|
"react": "^18.2.0",
|
|
66
66
|
"react-dom": "^18.2.0",
|
|
@@ -84,9 +84,9 @@
|
|
|
84
84
|
"micromark-util-sanitize-uri": "^2.0.1",
|
|
85
85
|
"micromark-util-symbol": "^2.0.1",
|
|
86
86
|
"shiki": "^4.3.1",
|
|
87
|
-
"@deepseek-ai/dsh-client-store": "0.1
|
|
88
|
-
"@deepseek-ai/dsh-util-code-language": "0.1
|
|
89
|
-
"@deepseek-ai/dsh-util-workspace-path": "0.1
|
|
87
|
+
"@deepseek-ai/dsh-client-store": "0.2.1-rc.2",
|
|
88
|
+
"@deepseek-ai/dsh-util-code-language": "0.2.1-rc.2",
|
|
89
|
+
"@deepseek-ai/dsh-util-workspace-path": "0.2.1-rc.2",
|
|
90
90
|
"diff": "^9.0.0",
|
|
91
91
|
"immer": "^10.1.1",
|
|
92
92
|
"simple-icons": "16.31.0",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
.runtimeComposerActions { display: flex; align-items: flex-end; justify-content: flex-end; gap: 8px; margin-top: 12px; }
|
|
12
12
|
.runtimeComposerActions label { display: grid; gap: 6px; color: var(--mn-muted); font-size: 12px; font-weight: 500; line-height: 18px; }
|
|
13
13
|
.runtimeChoice button { min-width: 136px; }
|
|
14
|
-
.runtimeReadOnly { margin-bottom: 12px; padding: 8px 12px; border-radius: var(--dsw-radius-md); color: var(--mn-muted); background: var(--mn-fill); font-size: 12px; line-height: 18px; }
|
|
14
|
+
.runtimeReadOnly { margin-bottom: 12px; padding: 8px 12px; border-radius: var(--dsw-radius-md); color: var(--mn-muted); background: var(--mn-block-fill, var(--mn-fill)); font-size: 12px; line-height: 18px; }
|
|
15
15
|
.runtimeSummaryGrid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin-bottom: 12px; }
|
|
16
16
|
.runtimeSummaryCard { min-width: 0; border: .5px solid var(--mn-card-line); border-radius: var(--dsw-radius-lg); }
|
|
17
17
|
.runtimeBrowser { overflow: hidden; border: .5px solid var(--mn-card-line); border-radius: var(--dsw-radius-lg); }
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
//#region src/defaults.ts
|
|
2
|
-
const DEFAULT_RUNTIME_MEMORY_LIMIT_BYTES = 10240;
|
|
3
|
-
const DEFAULT_RUNTIME_USER_LIMIT_BYTES = 4096;
|
|
4
|
-
const MAX_RUNTIME_MEMORY_LIMIT_BYTES = 1048576;
|
|
5
|
-
//#endregion
|
|
6
|
-
//#region src/contracts.ts
|
|
7
|
-
const RUNTIME_MEMORY_VERSION = 1;
|
|
8
|
-
const RUNTIME_ENTRY_DELIMITER = "\n§\n";
|
|
9
|
-
const RUNTIME_MEMORY_LIMITS = {
|
|
10
|
-
memory: DEFAULT_RUNTIME_MEMORY_LIMIT_BYTES,
|
|
11
|
-
user: DEFAULT_RUNTIME_USER_LIMIT_BYTES
|
|
12
|
-
};
|
|
13
|
-
/** The longest git branch name a scope may hold. */
|
|
14
|
-
const RUNTIME_BRANCH_NAME_MAX = 128;
|
|
15
|
-
/** The characters a git branch name in a scope may use. */
|
|
16
|
-
const RUNTIME_BRANCH_NAME_PATTERN = /^[A-Za-z0-9._/-]+$/u;
|
|
17
|
-
/**
|
|
18
|
-
* Read a stored branch scope. Absent or malformed data reads as no scope, so an entry that
|
|
19
|
-
* a hand edit or another installation left malformed is projected on every branch instead
|
|
20
|
-
* of breaking the projection that reads it.
|
|
21
|
-
*/
|
|
22
|
-
function parseRuntimeBranches(value) {
|
|
23
|
-
if (!Array.isArray(value)) return void 0;
|
|
24
|
-
const branches = [];
|
|
25
|
-
for (const item of value) {
|
|
26
|
-
if (typeof item !== "string" || item === "" || item.length > 128 || !RUNTIME_BRANCH_NAME_PATTERN.test(item)) return void 0;
|
|
27
|
-
branches.push(item);
|
|
28
|
-
}
|
|
29
|
-
return branches;
|
|
30
|
-
}
|
|
31
|
-
//#endregion
|
|
32
|
-
export { RUNTIME_MEMORY_VERSION as a, DEFAULT_RUNTIME_USER_LIMIT_BYTES as c, RUNTIME_MEMORY_LIMITS as i, MAX_RUNTIME_MEMORY_LIMIT_BYTES as l, RUNTIME_BRANCH_NAME_PATTERN as n, parseRuntimeBranches as o, RUNTIME_ENTRY_DELIMITER as r, DEFAULT_RUNTIME_MEMORY_LIMIT_BYTES as s, RUNTIME_BRANCH_NAME_MAX as t };
|