gm-skill 2.0.1189 → 2.0.1191
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 +1 -1
- package/gm-plugkit/plugkit-wasm-wrapper.js +92 -31
- package/gm.json +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -35,7 +35,7 @@ An earlier generation fanned out fifteen per-platform downstream repos (gm-cc, g
|
|
|
35
35
|
|
|
36
36
|
## Version
|
|
37
37
|
|
|
38
|
-
`2.0.
|
|
38
|
+
`2.0.1191` — auto-bumped from the canonical `gm` repo. Every push to `AnEntrypoint/gm` (or any cascading sibling crate) republishes this package.
|
|
39
39
|
|
|
40
40
|
## Source of truth
|
|
41
41
|
|
|
@@ -27,6 +27,23 @@ const ORCHESTRATOR_VERBS = new Set(['instruction', 'transition', 'phase-status',
|
|
|
27
27
|
const TURN_IDLE_MS = 30_000;
|
|
28
28
|
const _turns = new Map();
|
|
29
29
|
|
|
30
|
+
function applyDisciplineSigil(rawBody) {
|
|
31
|
+
let parsed;
|
|
32
|
+
try { parsed = JSON.parse(rawBody); } catch (_) { return rawBody; }
|
|
33
|
+
if (!parsed || typeof parsed !== 'object') return rawBody;
|
|
34
|
+
const SIGIL = /^@([A-Za-z0-9][A-Za-z0-9_-]{0,63})\s+/;
|
|
35
|
+
for (const key of ['query', 'text']) {
|
|
36
|
+
const v = parsed[key];
|
|
37
|
+
if (typeof v !== 'string') continue;
|
|
38
|
+
const m = v.match(SIGIL);
|
|
39
|
+
if (!m) continue;
|
|
40
|
+
if (!parsed.namespace) parsed.namespace = m[1];
|
|
41
|
+
parsed[key] = v.slice(m[0].length);
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
return JSON.stringify(parsed);
|
|
45
|
+
}
|
|
46
|
+
|
|
30
47
|
function turnTick(sess, verb, taskBase, phase) {
|
|
31
48
|
const key = sess || '(no-session)';
|
|
32
49
|
const now = Date.now();
|
|
@@ -459,12 +476,38 @@ function writeWasmJson(instance, value) {
|
|
|
459
476
|
return writeWasmStr(instance, JSON.stringify(value));
|
|
460
477
|
}
|
|
461
478
|
|
|
479
|
+
function safeName(s) { return String(s).replace(/[^A-Za-z0-9._-]/g, '_'); }
|
|
480
|
+
|
|
481
|
+
function projectKvDir(ns) {
|
|
482
|
+
const projectRoot = process.env.CLAUDE_PROJECT_DIR || process.cwd();
|
|
483
|
+
return path.join(projectRoot, '.gm', 'disciplines', safeName(ns));
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
function legacyKvDir(ns) {
|
|
487
|
+
return path.join(KV_DIR, safeName(ns));
|
|
488
|
+
}
|
|
489
|
+
|
|
462
490
|
function kvFilePath(ns, key) {
|
|
463
|
-
const
|
|
464
|
-
const safeKey = String(key).replace(/[^A-Za-z0-9._-]/g, '_');
|
|
465
|
-
const dir = path.join(KV_DIR, safeNs);
|
|
491
|
+
const dir = projectKvDir(ns);
|
|
466
492
|
fs.mkdirSync(dir, { recursive: true });
|
|
467
|
-
return path.join(dir,
|
|
493
|
+
return path.join(dir, safeName(key) + '.json');
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
function kvReadResolve(ns, key) {
|
|
497
|
+
const fp = kvFilePath(ns, key);
|
|
498
|
+
if (fs.existsSync(fp)) return fp;
|
|
499
|
+
const legacy = path.join(legacyKvDir(ns), safeName(key) + '.json');
|
|
500
|
+
if (fs.existsSync(legacy)) return legacy;
|
|
501
|
+
return null;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
function kvNamespaceDirs(ns) {
|
|
505
|
+
const out = [];
|
|
506
|
+
const proj = projectKvDir(ns);
|
|
507
|
+
if (fs.existsSync(proj)) out.push(proj);
|
|
508
|
+
const legacy = legacyKvDir(ns);
|
|
509
|
+
if (fs.existsSync(legacy)) out.push(legacy);
|
|
510
|
+
return out;
|
|
468
511
|
}
|
|
469
512
|
|
|
470
513
|
const __tasks = new Map();
|
|
@@ -734,8 +777,8 @@ function makeHostFunctions(instanceRef) {
|
|
|
734
777
|
const ns = readWasmStr(instanceRef.value, nsPtr, nsLen);
|
|
735
778
|
const key = readWasmStr(instanceRef.value, keyPtr, keyLen);
|
|
736
779
|
if (!ns || !key) return 0n;
|
|
737
|
-
const fp =
|
|
738
|
-
if (!
|
|
780
|
+
const fp = kvReadResolve(ns, key);
|
|
781
|
+
if (!fp) return 0n;
|
|
739
782
|
const data = fs.readFileSync(fp, 'utf-8');
|
|
740
783
|
return writeWasmStr(instanceRef.value, data);
|
|
741
784
|
} catch (e) {
|
|
@@ -761,15 +804,21 @@ function makeHostFunctions(instanceRef) {
|
|
|
761
804
|
const ns = readWasmStr(instanceRef.value, nsPtr, nsLen);
|
|
762
805
|
const q = readWasmStr(instanceRef.value, qPtr, qLen);
|
|
763
806
|
if (!ns) return 0n;
|
|
764
|
-
const
|
|
765
|
-
if (
|
|
807
|
+
const dirs = kvNamespaceDirs(ns);
|
|
808
|
+
if (dirs.length === 0) return writeWasmJson(instanceRef.value, []);
|
|
766
809
|
const ql = q ? String(q).toLowerCase() : '';
|
|
810
|
+
const seen = new Set();
|
|
767
811
|
const results = [];
|
|
768
|
-
for (const
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
812
|
+
for (const dir of dirs) {
|
|
813
|
+
for (const f of fs.readdirSync(dir)) {
|
|
814
|
+
if (!f.endsWith('.json')) continue;
|
|
815
|
+
const key = f.replace(/\.json$/, '');
|
|
816
|
+
if (seen.has(key)) continue;
|
|
817
|
+
seen.add(key);
|
|
818
|
+
const value = fs.readFileSync(path.join(dir, f), 'utf-8');
|
|
819
|
+
if (ql && !value.toLowerCase().includes(ql) && !f.toLowerCase().includes(ql)) continue;
|
|
820
|
+
results.push({ key, value });
|
|
821
|
+
}
|
|
773
822
|
}
|
|
774
823
|
return writeWasmJson(instanceRef.value, results);
|
|
775
824
|
} catch (e) {
|
|
@@ -797,26 +846,34 @@ function makeHostFunctions(instanceRef) {
|
|
|
797
846
|
if (process.env.PLUGKIT_DEBUG) console.error('[plugkit-wasm] host_vec_search: no embedding in query, raw=', raw.slice(0, 200));
|
|
798
847
|
return writeWasmJson(instanceRef.value, []);
|
|
799
848
|
}
|
|
800
|
-
const
|
|
801
|
-
const
|
|
802
|
-
if (
|
|
849
|
+
const vecDirs = kvNamespaceDirs(`${namespace}-vec`);
|
|
850
|
+
const dataDirs = kvNamespaceDirs(namespace);
|
|
851
|
+
if (vecDirs.length === 0 || dataDirs.length === 0) {
|
|
803
852
|
return writeWasmJson(instanceRef.value, []);
|
|
804
853
|
}
|
|
805
854
|
const scored = [];
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
855
|
+
const seen = new Set();
|
|
856
|
+
for (const vecDir of vecDirs) {
|
|
857
|
+
for (const f of fs.readdirSync(vecDir)) {
|
|
858
|
+
if (!f.endsWith('.json')) continue;
|
|
859
|
+
const key = f.replace(/\.json$/, '');
|
|
860
|
+
if (seen.has(key)) continue;
|
|
861
|
+
seen.add(key);
|
|
862
|
+
let emb;
|
|
863
|
+
try { emb = JSON.parse(fs.readFileSync(path.join(vecDir, f), 'utf-8')); }
|
|
864
|
+
catch (_) { continue; }
|
|
865
|
+
const vector = Array.isArray(emb?.data?.[0]?.embedding) ? emb.data[0].embedding
|
|
866
|
+
: Array.isArray(emb?.embedding) ? emb.embedding
|
|
867
|
+
: Array.isArray(emb) ? emb : null;
|
|
868
|
+
if (!vector) continue;
|
|
869
|
+
const score = cosineSim(queryEmbedding, vector);
|
|
870
|
+
let text = '';
|
|
871
|
+
for (const dataDir of dataDirs) {
|
|
872
|
+
const valuePath = path.join(dataDir, `${key}.json`);
|
|
873
|
+
if (fs.existsSync(valuePath)) { text = fs.readFileSync(valuePath, 'utf-8'); break; }
|
|
874
|
+
}
|
|
875
|
+
scored.push({ key, text, score });
|
|
876
|
+
}
|
|
820
877
|
}
|
|
821
878
|
scored.sort((a, b) => b.score - a.score);
|
|
822
879
|
return writeWasmJson(instanceRef.value, scored.slice(0, k_));
|
|
@@ -1344,9 +1401,13 @@ async function runSpoolWatcher(instance, spoolDir) {
|
|
|
1344
1401
|
const relPath = path.relative(inDir, filePath);
|
|
1345
1402
|
const dir = path.dirname(relPath);
|
|
1346
1403
|
const verb = dir === '.' ? path.basename(filePath, path.extname(filePath)) : dir;
|
|
1347
|
-
|
|
1404
|
+
let body = content.trim() || '{}';
|
|
1348
1405
|
const taskBase = path.basename(filePath, path.extname(filePath));
|
|
1349
1406
|
|
|
1407
|
+
if (verb === 'recall' || verb === 'memorize' || verb === 'codesearch' || verb === 'memorize-fire') {
|
|
1408
|
+
body = applyDisciplineSigil(body);
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1350
1411
|
const verbBytes = new TextEncoder().encode(verb);
|
|
1351
1412
|
const bodyBytes = new TextEncoder().encode(body);
|
|
1352
1413
|
|
package/gm.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gm-skill",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1191",
|
|
4
4
|
"description": "Canonical universal harness — AI-native software engineering via skill-driven orchestration; bootstraps plugkit for task execution and session isolation. Install in any AI coding agent host.",
|
|
5
5
|
"author": "AnEntrypoint",
|
|
6
6
|
"license": "MIT",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"gm.json"
|
|
40
40
|
],
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"gm-plugkit": "^2.0.
|
|
42
|
+
"gm-plugkit": "^2.0.1191"
|
|
43
43
|
},
|
|
44
44
|
"engines": {
|
|
45
45
|
"node": ">=16.0.0"
|