zam-core 0.3.11 → 0.3.12
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/dist/cli/index.js +893 -195
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +74 -1
- package/dist/index.js +356 -81
- package/dist/index.js.map +1 -1
- package/package.json +9 -2
- package/templates/personal/beliefs/README.md +1 -1
- package/templates/personal/foundations/README.md +19 -0
package/dist/index.js
CHANGED
|
@@ -1932,11 +1932,11 @@ function analyzeObservation(commands, tokenPatterns) {
|
|
|
1932
1932
|
const ratings = [];
|
|
1933
1933
|
for (const tp of tokenPatterns) {
|
|
1934
1934
|
const matchIndices = [];
|
|
1935
|
-
const
|
|
1935
|
+
const matchedTexts2 = [];
|
|
1936
1936
|
for (let i = 0; i < commands.length; i++) {
|
|
1937
1937
|
if (matchesToken(commands[i].command, tp.patterns)) {
|
|
1938
1938
|
matchIndices.push(i);
|
|
1939
|
-
|
|
1939
|
+
matchedTexts2.push(commands[i].command);
|
|
1940
1940
|
matchedSet.add(i);
|
|
1941
1941
|
}
|
|
1942
1942
|
}
|
|
@@ -2026,7 +2026,7 @@ function analyzeObservation(commands, tokenPatterns) {
|
|
|
2026
2026
|
medianGapMs,
|
|
2027
2027
|
thinkingGapMs
|
|
2028
2028
|
},
|
|
2029
|
-
matchedCommandTexts:
|
|
2029
|
+
matchedCommandTexts: matchedTexts2
|
|
2030
2030
|
});
|
|
2031
2031
|
}
|
|
2032
2032
|
const unmatchedCommands = [];
|
|
@@ -2391,6 +2391,240 @@ async function unblockReady(db, userId) {
|
|
|
2391
2391
|
return { unblocked };
|
|
2392
2392
|
}
|
|
2393
2393
|
|
|
2394
|
+
// src/kernel/observation/ui-observer-io.ts
|
|
2395
|
+
import { appendFileSync as appendFileSync2, existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync5 } from "fs";
|
|
2396
|
+
import { homedir as homedir4 } from "os";
|
|
2397
|
+
import { join as join5 } from "path";
|
|
2398
|
+
|
|
2399
|
+
// src/kernel/observation/ui-observer.ts
|
|
2400
|
+
var UI_OBSERVATION_PROTOCOL_VERSION = 1;
|
|
2401
|
+
var OBSERVATION_KINDS = /* @__PURE__ */ new Set([
|
|
2402
|
+
"progress",
|
|
2403
|
+
"step-completed",
|
|
2404
|
+
"error",
|
|
2405
|
+
"help-seeking",
|
|
2406
|
+
"uncertain",
|
|
2407
|
+
"privacy-pause",
|
|
2408
|
+
"heartbeat"
|
|
2409
|
+
]);
|
|
2410
|
+
var ACTION_TYPES = /* @__PURE__ */ new Set([
|
|
2411
|
+
"click",
|
|
2412
|
+
"shortcut",
|
|
2413
|
+
"typing",
|
|
2414
|
+
"scroll",
|
|
2415
|
+
"window-change"
|
|
2416
|
+
]);
|
|
2417
|
+
var EVIDENCE_TYPES = /* @__PURE__ */ new Set([
|
|
2418
|
+
"uia",
|
|
2419
|
+
"keyframe",
|
|
2420
|
+
"clip",
|
|
2421
|
+
"window"
|
|
2422
|
+
]);
|
|
2423
|
+
function isUiObservationReport(value) {
|
|
2424
|
+
if (!isRecord(value)) return false;
|
|
2425
|
+
if (value.version !== UI_OBSERVATION_PROTOCOL_VERSION) return false;
|
|
2426
|
+
if (!isNonEmptyString(value.sessionId)) return false;
|
|
2427
|
+
if (!isNonNegativeInteger(value.sequence)) return false;
|
|
2428
|
+
if (!isNonEmptyString(value.observedFrom)) return false;
|
|
2429
|
+
if (!isNonEmptyString(value.observedTo)) return false;
|
|
2430
|
+
if (typeof value.kind !== "string" || !OBSERVATION_KINDS.has(value.kind)) {
|
|
2431
|
+
return false;
|
|
2432
|
+
}
|
|
2433
|
+
if (!isApplication(value.application)) return false;
|
|
2434
|
+
if (!isNonEmptyString(value.summary)) return false;
|
|
2435
|
+
if (!Array.isArray(value.actions) || !value.actions.every(isObservedAction)) {
|
|
2436
|
+
return false;
|
|
2437
|
+
}
|
|
2438
|
+
if (!Array.isArray(value.evidence) || !value.evidence.every(isEvidenceRef)) {
|
|
2439
|
+
return false;
|
|
2440
|
+
}
|
|
2441
|
+
if (!Array.isArray(value.candidateTokens) || !value.candidateTokens.every(isCandidateToken)) {
|
|
2442
|
+
return false;
|
|
2443
|
+
}
|
|
2444
|
+
return isConfidence(value.confidence);
|
|
2445
|
+
}
|
|
2446
|
+
function parseUiObservationLog(jsonl) {
|
|
2447
|
+
const reports = [];
|
|
2448
|
+
for (const line of jsonl.split("\n")) {
|
|
2449
|
+
const trimmed = line.trim();
|
|
2450
|
+
if (!trimmed) continue;
|
|
2451
|
+
try {
|
|
2452
|
+
const value = JSON.parse(trimmed);
|
|
2453
|
+
if (isUiObservationReport(value)) {
|
|
2454
|
+
reports.push(value);
|
|
2455
|
+
}
|
|
2456
|
+
} catch {
|
|
2457
|
+
}
|
|
2458
|
+
}
|
|
2459
|
+
return reports.sort((left, right) => left.sequence - right.sequence);
|
|
2460
|
+
}
|
|
2461
|
+
function isApplication(value) {
|
|
2462
|
+
if (!isRecord(value) || !isNonEmptyString(value.processName)) return false;
|
|
2463
|
+
if (value.processId !== void 0 && !isNonNegativeInteger(value.processId)) {
|
|
2464
|
+
return false;
|
|
2465
|
+
}
|
|
2466
|
+
return value.windowTitle === void 0 || typeof value.windowTitle === "string";
|
|
2467
|
+
}
|
|
2468
|
+
function isObservedAction(value) {
|
|
2469
|
+
if (!isRecord(value) || typeof value.type !== "string") return false;
|
|
2470
|
+
if (!ACTION_TYPES.has(value.type)) return false;
|
|
2471
|
+
if (value.target !== void 0 && typeof value.target !== "string") {
|
|
2472
|
+
return false;
|
|
2473
|
+
}
|
|
2474
|
+
return value.result === void 0 || typeof value.result === "string";
|
|
2475
|
+
}
|
|
2476
|
+
function isEvidenceRef(value) {
|
|
2477
|
+
if (!isRecord(value) || typeof value.type !== "string") return false;
|
|
2478
|
+
return EVIDENCE_TYPES.has(value.type) && isNonEmptyString(value.ref) && typeof value.redacted === "boolean";
|
|
2479
|
+
}
|
|
2480
|
+
function isCandidateToken(value) {
|
|
2481
|
+
return isRecord(value) && isNonEmptyString(value.slug) && isConfidence(value.confidence) && isNonEmptyString(value.rationale);
|
|
2482
|
+
}
|
|
2483
|
+
function isRecord(value) {
|
|
2484
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2485
|
+
}
|
|
2486
|
+
function isNonEmptyString(value) {
|
|
2487
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
2488
|
+
}
|
|
2489
|
+
function isNonNegativeInteger(value) {
|
|
2490
|
+
return Number.isInteger(value) && Number(value) >= 0;
|
|
2491
|
+
}
|
|
2492
|
+
function isConfidence(value) {
|
|
2493
|
+
return typeof value === "number" && value >= 0 && value <= 1;
|
|
2494
|
+
}
|
|
2495
|
+
|
|
2496
|
+
// src/kernel/observation/ui-observer-io.ts
|
|
2497
|
+
var DEFAULT_UI_OBSERVER_DIR = join5(homedir4(), ".zam", "observer");
|
|
2498
|
+
function getUiObserverDir() {
|
|
2499
|
+
return process.env.ZAM_OBSERVER_DIR || DEFAULT_UI_OBSERVER_DIR;
|
|
2500
|
+
}
|
|
2501
|
+
function getUiObservationPath(sessionId) {
|
|
2502
|
+
if (!/^[A-Za-z0-9_-]+$/.test(sessionId)) {
|
|
2503
|
+
throw new Error(`Invalid observer session ID: ${sessionId}`);
|
|
2504
|
+
}
|
|
2505
|
+
return join5(getUiObserverDir(), `${sessionId}.reports.jsonl`);
|
|
2506
|
+
}
|
|
2507
|
+
function ensureUiObserverDir() {
|
|
2508
|
+
const dir = getUiObserverDir();
|
|
2509
|
+
if (!existsSync5(dir)) {
|
|
2510
|
+
mkdirSync4(dir, { recursive: true, mode: 448 });
|
|
2511
|
+
}
|
|
2512
|
+
}
|
|
2513
|
+
function uiObservationLogExists(sessionId) {
|
|
2514
|
+
return existsSync5(getUiObservationPath(sessionId));
|
|
2515
|
+
}
|
|
2516
|
+
function readUiObservationLog(sessionId) {
|
|
2517
|
+
const path = getUiObservationPath(sessionId);
|
|
2518
|
+
if (!existsSync5(path)) return [];
|
|
2519
|
+
return parseUiObservationLog(readFileSync5(path, "utf8"));
|
|
2520
|
+
}
|
|
2521
|
+
function appendUiObservationReport(report) {
|
|
2522
|
+
if (!isUiObservationReport(report)) {
|
|
2523
|
+
throw new Error("Invalid UI observation report");
|
|
2524
|
+
}
|
|
2525
|
+
ensureUiObserverDir();
|
|
2526
|
+
appendFileSync2(
|
|
2527
|
+
getUiObservationPath(report.sessionId),
|
|
2528
|
+
`${JSON.stringify(report)}
|
|
2529
|
+
`,
|
|
2530
|
+
{ encoding: "utf8", mode: 384 }
|
|
2531
|
+
);
|
|
2532
|
+
}
|
|
2533
|
+
|
|
2534
|
+
// src/kernel/observation/ui-observer-synthesis.ts
|
|
2535
|
+
var MIN_UI_CONFIDENCE = 0.6;
|
|
2536
|
+
function kindToRating(kind) {
|
|
2537
|
+
switch (kind) {
|
|
2538
|
+
case "step-completed":
|
|
2539
|
+
return 4;
|
|
2540
|
+
case "progress":
|
|
2541
|
+
return 3;
|
|
2542
|
+
case "error":
|
|
2543
|
+
case "help-seeking":
|
|
2544
|
+
return 2;
|
|
2545
|
+
default:
|
|
2546
|
+
return null;
|
|
2547
|
+
}
|
|
2548
|
+
}
|
|
2549
|
+
function toSynthesisConfidence(confidence) {
|
|
2550
|
+
return confidence >= 0.85 ? "high" : "medium";
|
|
2551
|
+
}
|
|
2552
|
+
function confidenceRank(confidence) {
|
|
2553
|
+
return confidence === "high" ? 2 : 1;
|
|
2554
|
+
}
|
|
2555
|
+
function buildEvidence(report) {
|
|
2556
|
+
return {
|
|
2557
|
+
matchedCommands: report.actions.length,
|
|
2558
|
+
helpSeeking: report.kind === "help-seeking",
|
|
2559
|
+
errorCount: report.kind === "error" ? 1 : 0,
|
|
2560
|
+
selfCorrections: 0,
|
|
2561
|
+
medianGapMs: null,
|
|
2562
|
+
thinkingGapMs: null
|
|
2563
|
+
};
|
|
2564
|
+
}
|
|
2565
|
+
function matchedTexts(report) {
|
|
2566
|
+
const texts = [report.summary];
|
|
2567
|
+
for (const action of report.actions) {
|
|
2568
|
+
const label = [action.type, action.target, action.result].filter(Boolean).join(" ");
|
|
2569
|
+
if (label) texts.push(label);
|
|
2570
|
+
}
|
|
2571
|
+
return texts;
|
|
2572
|
+
}
|
|
2573
|
+
function buildUiSynthesisCandidates(reports, tokens, applied, minConfidence) {
|
|
2574
|
+
const minRank = confidenceRank(minConfidence);
|
|
2575
|
+
const bestBySlug = /* @__PURE__ */ new Map();
|
|
2576
|
+
let skippedLowConfidence = 0;
|
|
2577
|
+
for (const report of reports) {
|
|
2578
|
+
if (report.confidence < MIN_UI_CONFIDENCE) continue;
|
|
2579
|
+
const fallbackRating = kindToRating(report.kind);
|
|
2580
|
+
const candidates2 = report.candidateTokens.length > 0 ? report.candidateTokens.map((candidate) => ({
|
|
2581
|
+
slug: candidate.slug,
|
|
2582
|
+
confidence: candidate.confidence,
|
|
2583
|
+
rating: fallbackRating
|
|
2584
|
+
})) : [];
|
|
2585
|
+
for (const candidate of candidates2) {
|
|
2586
|
+
const token = tokens.get(candidate.slug);
|
|
2587
|
+
if (!token || applied.has(token.id)) continue;
|
|
2588
|
+
const synthesisConfidence = toSynthesisConfidence(candidate.confidence);
|
|
2589
|
+
if (confidenceRank(synthesisConfidence) < minRank) {
|
|
2590
|
+
skippedLowConfidence++;
|
|
2591
|
+
continue;
|
|
2592
|
+
}
|
|
2593
|
+
const inferredRating = candidate.rating ?? 3;
|
|
2594
|
+
const existing = bestBySlug.get(candidate.slug);
|
|
2595
|
+
if (existing && existing.reportConfidence >= candidate.confidence) {
|
|
2596
|
+
continue;
|
|
2597
|
+
}
|
|
2598
|
+
bestBySlug.set(candidate.slug, {
|
|
2599
|
+
token,
|
|
2600
|
+
inferredRating,
|
|
2601
|
+
confidence: synthesisConfidence,
|
|
2602
|
+
evidence: buildEvidence(report),
|
|
2603
|
+
matchedCommandTexts: matchedTexts(report),
|
|
2604
|
+
reportConfidence: candidate.confidence
|
|
2605
|
+
});
|
|
2606
|
+
}
|
|
2607
|
+
}
|
|
2608
|
+
const candidates = [...bestBySlug.values()].sort((left, right) => right.reportConfidence - left.reportConfidence).map((entry) => ({
|
|
2609
|
+
tokenId: entry.token.id,
|
|
2610
|
+
tokenSlug: entry.token.slug,
|
|
2611
|
+
concept: entry.token.concept,
|
|
2612
|
+
domain: entry.token.domain,
|
|
2613
|
+
inferredRating: entry.inferredRating,
|
|
2614
|
+
confidence: entry.confidence,
|
|
2615
|
+
evidence: entry.evidence,
|
|
2616
|
+
matchedCommandTexts: entry.matchedCommandTexts
|
|
2617
|
+
}));
|
|
2618
|
+
return { candidates, skippedLowConfidence };
|
|
2619
|
+
}
|
|
2620
|
+
function uiObservationTimeSpan(reports) {
|
|
2621
|
+
if (reports.length === 0) return null;
|
|
2622
|
+
const start = reports[0].observedFrom;
|
|
2623
|
+
const end = reports[reports.length - 1].observedTo;
|
|
2624
|
+
const durationMs = Math.max(0, Date.parse(end) - Date.parse(start));
|
|
2625
|
+
return { start, end, durationMs };
|
|
2626
|
+
}
|
|
2627
|
+
|
|
2394
2628
|
// src/kernel/observation/session-synthesis.ts
|
|
2395
2629
|
function parseSynthesisRow(row) {
|
|
2396
2630
|
return {
|
|
@@ -2398,7 +2632,7 @@ function parseSynthesisRow(row) {
|
|
|
2398
2632
|
evidence: JSON.parse(row.evidence)
|
|
2399
2633
|
};
|
|
2400
2634
|
}
|
|
2401
|
-
function
|
|
2635
|
+
function confidenceRank2(confidence) {
|
|
2402
2636
|
return confidence === "high" ? 2 : confidence === "medium" ? 1 : 0;
|
|
2403
2637
|
}
|
|
2404
2638
|
function normalizeSkillStep(step) {
|
|
@@ -2460,20 +2694,50 @@ async function prepareSessionSynthesis(db, input) {
|
|
|
2460
2694
|
validPatterns.push(pattern);
|
|
2461
2695
|
tokens.set(pattern.slug, token);
|
|
2462
2696
|
}
|
|
2463
|
-
const commands = input.commands ?? pairCommands(readMonitorLog(input.sessionId));
|
|
2464
|
-
const analysis = analyzeObservation(commands, validPatterns);
|
|
2465
2697
|
const applied = new Set(
|
|
2466
2698
|
(await getSessionSynthesisRecords(db, input.sessionId)).map(
|
|
2467
2699
|
(record) => record.token_id
|
|
2468
2700
|
)
|
|
2469
2701
|
);
|
|
2470
|
-
const
|
|
2702
|
+
const minConfidence = input.minConfidence ?? "medium";
|
|
2703
|
+
if (session.execution_context === "ui") {
|
|
2704
|
+
const reports = readUiObservationLog(input.sessionId);
|
|
2705
|
+
for (const report of reports) {
|
|
2706
|
+
for (const candidate of report.candidateTokens) {
|
|
2707
|
+
if (tokens.has(candidate.slug)) continue;
|
|
2708
|
+
const token = await getTokenBySlug(db, candidate.slug);
|
|
2709
|
+
if (token && !token.deprecated_at) {
|
|
2710
|
+
tokens.set(candidate.slug, token);
|
|
2711
|
+
}
|
|
2712
|
+
}
|
|
2713
|
+
}
|
|
2714
|
+
const { candidates: candidates2, skippedLowConfidence: skippedLowConfidence2 } = buildUiSynthesisCandidates(
|
|
2715
|
+
reports,
|
|
2716
|
+
tokens,
|
|
2717
|
+
applied,
|
|
2718
|
+
minConfidence
|
|
2719
|
+
);
|
|
2720
|
+
return {
|
|
2721
|
+
sessionId: session.id,
|
|
2722
|
+
userId: session.user_id,
|
|
2723
|
+
patternCount: validPatterns.length,
|
|
2724
|
+
commandCount: reports.length,
|
|
2725
|
+
alreadyApplied: applied.size,
|
|
2726
|
+
skippedLowConfidence: skippedLowConfidence2,
|
|
2727
|
+
candidates: candidates2,
|
|
2728
|
+
unmatchedCommands: [],
|
|
2729
|
+
timeSpan: uiObservationTimeSpan(reports)
|
|
2730
|
+
};
|
|
2731
|
+
}
|
|
2732
|
+
const commands = input.commands ?? pairCommands(readMonitorLog(input.sessionId));
|
|
2733
|
+
const analysis = analyzeObservation(commands, validPatterns);
|
|
2734
|
+
const minRank = confidenceRank2(minConfidence);
|
|
2471
2735
|
let skippedLowConfidence = 0;
|
|
2472
2736
|
const candidates = [];
|
|
2473
2737
|
for (const rating of analysis.ratings) {
|
|
2474
2738
|
const token = tokens.get(rating.tokenSlug);
|
|
2475
2739
|
if (!token || rating.rating == null || applied.has(token.id)) continue;
|
|
2476
|
-
if (
|
|
2740
|
+
if (confidenceRank2(rating.confidence) < minRank) {
|
|
2477
2741
|
skippedLowConfidence++;
|
|
2478
2742
|
continue;
|
|
2479
2743
|
}
|
|
@@ -3070,8 +3334,8 @@ function generatePrompt(input) {
|
|
|
3070
3334
|
}
|
|
3071
3335
|
|
|
3072
3336
|
// src/kernel/recall/reference-resolver.ts
|
|
3073
|
-
import { existsSync as
|
|
3074
|
-
import { dirname as dirname3, join as
|
|
3337
|
+
import { existsSync as existsSync6, readFileSync as readFileSync6 } from "fs";
|
|
3338
|
+
import { dirname as dirname3, join as join6, resolve } from "path";
|
|
3075
3339
|
var DEFAULT_REVIEW_CONTEXT_MAX_CHARS = 6e3;
|
|
3076
3340
|
function htmlToText(html) {
|
|
3077
3341
|
let content = html;
|
|
@@ -3132,11 +3396,11 @@ async function resolveReference(sourceLink) {
|
|
|
3132
3396
|
const filePath = anchorIndex2 !== -1 ? fullPathWithAnchor.slice(0, anchorIndex2) : fullPathWithAnchor;
|
|
3133
3397
|
const anchor2 = anchorIndex2 !== -1 ? fullPathWithAnchor.slice(anchorIndex2) : "";
|
|
3134
3398
|
const parentDir = dirname3(process.cwd());
|
|
3135
|
-
const localRepoPath =
|
|
3136
|
-
const localFilePath =
|
|
3137
|
-
if (
|
|
3399
|
+
const localRepoPath = join6(parentDir, repo);
|
|
3400
|
+
const localFilePath = join6(localRepoPath, filePath);
|
|
3401
|
+
if (existsSync6(localFilePath)) {
|
|
3138
3402
|
try {
|
|
3139
|
-
let fileContent =
|
|
3403
|
+
let fileContent = readFileSync6(localFilePath, "utf-8");
|
|
3140
3404
|
if (anchor2) {
|
|
3141
3405
|
fileContent = extractLines(fileContent, anchor2);
|
|
3142
3406
|
}
|
|
@@ -3190,9 +3454,9 @@ Link: ${cleaned}`,
|
|
|
3190
3454
|
const relativePath = anchorIndex !== -1 ? cleaned.slice(0, anchorIndex) : cleaned;
|
|
3191
3455
|
const anchor = anchorIndex !== -1 ? cleaned.slice(anchorIndex) : "";
|
|
3192
3456
|
const absolutePath = resolve(process.cwd(), relativePath);
|
|
3193
|
-
if (
|
|
3457
|
+
if (existsSync6(absolutePath)) {
|
|
3194
3458
|
try {
|
|
3195
|
-
let fileContent =
|
|
3459
|
+
let fileContent = readFileSync6(absolutePath, "utf-8");
|
|
3196
3460
|
if (anchor) {
|
|
3197
3461
|
fileContent = extractLines(fileContent, anchor);
|
|
3198
3462
|
}
|
|
@@ -3444,44 +3708,44 @@ function intersperseNew(reviews, newCards, interval) {
|
|
|
3444
3708
|
|
|
3445
3709
|
// src/kernel/system/hooks.ts
|
|
3446
3710
|
import {
|
|
3447
|
-
appendFileSync as
|
|
3711
|
+
appendFileSync as appendFileSync3,
|
|
3448
3712
|
copyFileSync,
|
|
3449
|
-
existsSync as
|
|
3450
|
-
mkdirSync as
|
|
3451
|
-
readFileSync as
|
|
3713
|
+
existsSync as existsSync7,
|
|
3714
|
+
mkdirSync as mkdirSync5,
|
|
3715
|
+
readFileSync as readFileSync7,
|
|
3452
3716
|
writeFileSync as writeFileSync3
|
|
3453
3717
|
} from "fs";
|
|
3454
|
-
import { homedir as
|
|
3455
|
-
import { join as
|
|
3718
|
+
import { homedir as homedir5 } from "os";
|
|
3719
|
+
import { join as join7 } from "path";
|
|
3456
3720
|
import { fileURLToPath } from "url";
|
|
3457
|
-
var HOME =
|
|
3721
|
+
var HOME = homedir5();
|
|
3458
3722
|
function getPackageSkillPath(agent = "default") {
|
|
3459
3723
|
const packageRoot = [
|
|
3460
3724
|
fileURLToPath(new URL("../../..", import.meta.url)),
|
|
3461
3725
|
fileURLToPath(new URL("../..", import.meta.url)),
|
|
3462
3726
|
fileURLToPath(new URL("..", import.meta.url))
|
|
3463
|
-
].find((candidate) =>
|
|
3727
|
+
].find((candidate) => existsSync7(join7(candidate, "package.json"))) ?? "";
|
|
3464
3728
|
if (!packageRoot) return "";
|
|
3465
3729
|
if (agent === "codex") {
|
|
3466
|
-
const codexPath =
|
|
3467
|
-
if (
|
|
3730
|
+
const codexPath = join7(packageRoot, ".agents", "skills", "zam", "SKILL.md");
|
|
3731
|
+
if (existsSync7(codexPath)) return codexPath;
|
|
3468
3732
|
return "";
|
|
3469
3733
|
}
|
|
3470
3734
|
if (agent === "claude") {
|
|
3471
|
-
const claudePath =
|
|
3735
|
+
const claudePath = join7(
|
|
3472
3736
|
packageRoot,
|
|
3473
3737
|
".claude",
|
|
3474
3738
|
"skills",
|
|
3475
3739
|
"zam",
|
|
3476
3740
|
"SKILL.md"
|
|
3477
3741
|
);
|
|
3478
|
-
if (
|
|
3742
|
+
if (existsSync7(claudePath)) return claudePath;
|
|
3479
3743
|
return "";
|
|
3480
3744
|
}
|
|
3481
|
-
let path =
|
|
3482
|
-
if (
|
|
3483
|
-
path =
|
|
3484
|
-
if (
|
|
3745
|
+
let path = join7(packageRoot, ".agent", "skills", "zam", "SKILL.md");
|
|
3746
|
+
if (existsSync7(path)) return path;
|
|
3747
|
+
path = join7(packageRoot, ".claude", "skills", "zam", "SKILL.md");
|
|
3748
|
+
if (existsSync7(path)) return path;
|
|
3485
3749
|
return "";
|
|
3486
3750
|
}
|
|
3487
3751
|
function distributeGlobalSkills(home = HOME) {
|
|
@@ -3493,16 +3757,16 @@ function distributeGlobalSkills(home = HOME) {
|
|
|
3493
3757
|
console.warn("Could not find ZAM source SKILL.md in the package folder.");
|
|
3494
3758
|
return results;
|
|
3495
3759
|
}
|
|
3496
|
-
const claudeSkillsDir =
|
|
3760
|
+
const claudeSkillsDir = join7(home, ".claude", "skills", "zam");
|
|
3497
3761
|
try {
|
|
3498
3762
|
if (!claudeSourceSkill) {
|
|
3499
3763
|
throw new Error("Claude skill source not found");
|
|
3500
3764
|
}
|
|
3501
|
-
|
|
3502
|
-
copyFileSync(claudeSourceSkill,
|
|
3765
|
+
mkdirSync5(claudeSkillsDir, { recursive: true });
|
|
3766
|
+
copyFileSync(claudeSourceSkill, join7(claudeSkillsDir, "SKILL.md"));
|
|
3503
3767
|
results.push({
|
|
3504
3768
|
name: "Claude Code Global",
|
|
3505
|
-
path:
|
|
3769
|
+
path: join7(claudeSkillsDir, "SKILL.md"),
|
|
3506
3770
|
success: true
|
|
3507
3771
|
});
|
|
3508
3772
|
} catch (_err) {
|
|
@@ -3512,13 +3776,13 @@ function distributeGlobalSkills(home = HOME) {
|
|
|
3512
3776
|
success: false
|
|
3513
3777
|
});
|
|
3514
3778
|
}
|
|
3515
|
-
const geminiSkillsDir =
|
|
3779
|
+
const geminiSkillsDir = join7(home, ".gemini", "skills", "zam");
|
|
3516
3780
|
try {
|
|
3517
|
-
|
|
3518
|
-
copyFileSync(sourceSkill,
|
|
3781
|
+
mkdirSync5(geminiSkillsDir, { recursive: true });
|
|
3782
|
+
copyFileSync(sourceSkill, join7(geminiSkillsDir, "SKILL.md"));
|
|
3519
3783
|
results.push({
|
|
3520
3784
|
name: "Gemini CLI Global",
|
|
3521
|
-
path:
|
|
3785
|
+
path: join7(geminiSkillsDir, "SKILL.md"),
|
|
3522
3786
|
success: true
|
|
3523
3787
|
});
|
|
3524
3788
|
} catch (_err) {
|
|
@@ -3528,16 +3792,16 @@ function distributeGlobalSkills(home = HOME) {
|
|
|
3528
3792
|
success: false
|
|
3529
3793
|
});
|
|
3530
3794
|
}
|
|
3531
|
-
const codexSkillsDir =
|
|
3795
|
+
const codexSkillsDir = join7(home, ".agents", "skills", "zam");
|
|
3532
3796
|
try {
|
|
3533
3797
|
if (!codexSourceSkill) {
|
|
3534
3798
|
throw new Error("Codex skill source not found");
|
|
3535
3799
|
}
|
|
3536
|
-
|
|
3537
|
-
copyFileSync(codexSourceSkill,
|
|
3800
|
+
mkdirSync5(codexSkillsDir, { recursive: true });
|
|
3801
|
+
copyFileSync(codexSourceSkill, join7(codexSkillsDir, "SKILL.md"));
|
|
3538
3802
|
results.push({
|
|
3539
3803
|
name: "Codex Global",
|
|
3540
|
-
path:
|
|
3804
|
+
path: join7(codexSkillsDir, "SKILL.md"),
|
|
3541
3805
|
success: true
|
|
3542
3806
|
});
|
|
3543
3807
|
} catch (_err) {
|
|
@@ -3547,13 +3811,13 @@ function distributeGlobalSkills(home = HOME) {
|
|
|
3547
3811
|
success: false
|
|
3548
3812
|
});
|
|
3549
3813
|
}
|
|
3550
|
-
const gooseSkillsDir =
|
|
3814
|
+
const gooseSkillsDir = join7(home, ".goose", "skills", "zam");
|
|
3551
3815
|
try {
|
|
3552
|
-
|
|
3553
|
-
copyFileSync(sourceSkill,
|
|
3816
|
+
mkdirSync5(gooseSkillsDir, { recursive: true });
|
|
3817
|
+
copyFileSync(sourceSkill, join7(gooseSkillsDir, "SKILL.md"));
|
|
3554
3818
|
results.push({
|
|
3555
3819
|
name: "Goose Global",
|
|
3556
|
-
path:
|
|
3820
|
+
path: join7(gooseSkillsDir, "SKILL.md"),
|
|
3557
3821
|
success: true
|
|
3558
3822
|
});
|
|
3559
3823
|
} catch (_err) {
|
|
@@ -3597,14 +3861,14 @@ function Start-ZamMonitor {
|
|
|
3597
3861
|
`;
|
|
3598
3862
|
function installHook(file, hook, oldHook) {
|
|
3599
3863
|
try {
|
|
3600
|
-
const content =
|
|
3864
|
+
const content = existsSync7(file) ? readFileSync7(file, "utf8") : "";
|
|
3601
3865
|
if (content.includes(HOOK_MARKER)) {
|
|
3602
3866
|
return { success: true, alreadyHooked: true };
|
|
3603
3867
|
}
|
|
3604
3868
|
if (content.includes(oldHook.trim())) {
|
|
3605
3869
|
writeFileSync3(file, content.replace(oldHook.trim(), hook.trim()), "utf8");
|
|
3606
3870
|
} else {
|
|
3607
|
-
|
|
3871
|
+
appendFileSync3(file, hook);
|
|
3608
3872
|
}
|
|
3609
3873
|
return { success: true, alreadyHooked: false };
|
|
3610
3874
|
} catch {
|
|
@@ -3613,24 +3877,24 @@ function installHook(file, hook, oldHook) {
|
|
|
3613
3877
|
}
|
|
3614
3878
|
function injectShellHooks(home = HOME) {
|
|
3615
3879
|
const results = [];
|
|
3616
|
-
const zshrc =
|
|
3617
|
-
if (
|
|
3880
|
+
const zshrc = join7(home, ".zshrc");
|
|
3881
|
+
if (existsSync7(zshrc)) {
|
|
3618
3882
|
const status = installHook(zshrc, posixHook("zsh"), POSIX_OLD_HOOK);
|
|
3619
3883
|
results.push({ shell: "zsh", file: zshrc, ...status });
|
|
3620
3884
|
}
|
|
3621
|
-
const bashrc =
|
|
3622
|
-
if (
|
|
3885
|
+
const bashrc = join7(home, ".bashrc");
|
|
3886
|
+
if (existsSync7(bashrc)) {
|
|
3623
3887
|
const status = installHook(bashrc, posixHook("bash"), POSIX_OLD_HOOK);
|
|
3624
3888
|
results.push({ shell: "bash", file: bashrc, ...status });
|
|
3625
3889
|
}
|
|
3626
3890
|
const pwshDirs = [
|
|
3627
|
-
|
|
3628
|
-
|
|
3891
|
+
join7(home, "Documents", "PowerShell"),
|
|
3892
|
+
join7(home, "Documents", "WindowsPowerShell")
|
|
3629
3893
|
];
|
|
3630
3894
|
for (const dir of pwshDirs) {
|
|
3631
|
-
const profileFile =
|
|
3895
|
+
const profileFile = join7(dir, "Microsoft.PowerShell_profile.ps1");
|
|
3632
3896
|
try {
|
|
3633
|
-
|
|
3897
|
+
mkdirSync5(dir, { recursive: true });
|
|
3634
3898
|
const status = installHook(
|
|
3635
3899
|
profileFile,
|
|
3636
3900
|
POWERSHELL_HOOK,
|
|
@@ -3862,21 +4126,21 @@ function t(locale, key, params = {}) {
|
|
|
3862
4126
|
}
|
|
3863
4127
|
|
|
3864
4128
|
// src/kernel/system/install-config.ts
|
|
3865
|
-
import { existsSync as
|
|
3866
|
-
import { homedir as
|
|
3867
|
-
import { dirname as dirname4, join as
|
|
3868
|
-
var DEFAULT_CONFIG_PATH =
|
|
4129
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync6, readFileSync as readFileSync8, writeFileSync as writeFileSync4 } from "fs";
|
|
4130
|
+
import { homedir as homedir6 } from "os";
|
|
4131
|
+
import { dirname as dirname4, join as join8 } from "path";
|
|
4132
|
+
var DEFAULT_CONFIG_PATH = join8(homedir6(), ".zam", "config.json");
|
|
3869
4133
|
function loadInstallConfig(path = DEFAULT_CONFIG_PATH) {
|
|
3870
|
-
if (!
|
|
4134
|
+
if (!existsSync8(path)) return {};
|
|
3871
4135
|
try {
|
|
3872
|
-
return JSON.parse(
|
|
4136
|
+
return JSON.parse(readFileSync8(path, "utf-8"));
|
|
3873
4137
|
} catch {
|
|
3874
4138
|
return {};
|
|
3875
4139
|
}
|
|
3876
4140
|
}
|
|
3877
4141
|
function saveInstallConfig(config, path = DEFAULT_CONFIG_PATH) {
|
|
3878
4142
|
const dir = dirname4(path);
|
|
3879
|
-
if (!
|
|
4143
|
+
if (!existsSync8(dir)) mkdirSync6(dir, { recursive: true });
|
|
3880
4144
|
writeFileSync4(path, `${JSON.stringify(config, null, 2)}
|
|
3881
4145
|
`, "utf-8");
|
|
3882
4146
|
}
|
|
@@ -3913,9 +4177,9 @@ function detectSyncProvider(dir) {
|
|
|
3913
4177
|
|
|
3914
4178
|
// src/kernel/system/installer.ts
|
|
3915
4179
|
import { execFileSync, execSync } from "child_process";
|
|
3916
|
-
import { existsSync as
|
|
3917
|
-
import { homedir as
|
|
3918
|
-
import { join as
|
|
4180
|
+
import { existsSync as existsSync9 } from "fs";
|
|
4181
|
+
import { homedir as homedir7 } from "os";
|
|
4182
|
+
import { join as join9 } from "path";
|
|
3919
4183
|
function hasCommand(cmd) {
|
|
3920
4184
|
try {
|
|
3921
4185
|
const checkCmd = process.platform === "win32" ? `where ${cmd}` : `which ${cmd}`;
|
|
@@ -3932,7 +4196,7 @@ function installFastFlowLM() {
|
|
|
3932
4196
|
message: "FastFlowLM is only supported on Windows."
|
|
3933
4197
|
};
|
|
3934
4198
|
}
|
|
3935
|
-
const hasFlm = hasCommand("flm") ||
|
|
4199
|
+
const hasFlm = hasCommand("flm") || existsSync9("C:\\Program Files\\flm\\flm.exe");
|
|
3936
4200
|
if (hasFlm) {
|
|
3937
4201
|
return { success: true, message: "FastFlowLM is already installed." };
|
|
3938
4202
|
}
|
|
@@ -3959,8 +4223,8 @@ function installFastFlowLM() {
|
|
|
3959
4223
|
function installOllama() {
|
|
3960
4224
|
const isMac = process.platform === "darwin";
|
|
3961
4225
|
const isWin = process.platform === "win32";
|
|
3962
|
-
const hasOllama = hasCommand("ollama") || isMac &&
|
|
3963
|
-
|
|
4226
|
+
const hasOllama = hasCommand("ollama") || isMac && existsSync9("/Applications/Ollama.app") || isWin && existsSync9(
|
|
4227
|
+
join9(homedir7(), "AppData", "Local", "Programs", "Ollama", "ollama.exe")
|
|
3964
4228
|
);
|
|
3965
4229
|
if (hasOllama) {
|
|
3966
4230
|
return { success: true, message: "Ollama is already installed." };
|
|
@@ -4020,8 +4284,8 @@ function installOllama() {
|
|
|
4020
4284
|
function resolveOllamaCommand() {
|
|
4021
4285
|
if (hasCommand("ollama")) return "ollama";
|
|
4022
4286
|
const candidates = process.platform === "win32" ? [
|
|
4023
|
-
|
|
4024
|
-
|
|
4287
|
+
join9(
|
|
4288
|
+
homedir7(),
|
|
4025
4289
|
"AppData",
|
|
4026
4290
|
"Local",
|
|
4027
4291
|
"Programs",
|
|
@@ -4029,7 +4293,7 @@ function resolveOllamaCommand() {
|
|
|
4029
4293
|
"ollama.exe"
|
|
4030
4294
|
)
|
|
4031
4295
|
] : process.platform === "darwin" ? ["/Applications/Ollama.app/Contents/Resources/ollama"] : [];
|
|
4032
|
-
return candidates.find((candidate) =>
|
|
4296
|
+
return candidates.find((candidate) => existsSync9(candidate));
|
|
4033
4297
|
}
|
|
4034
4298
|
function prepareLocalModel(runner, model) {
|
|
4035
4299
|
if (runner === "fastflowlm") {
|
|
@@ -4217,7 +4481,7 @@ function getSystemProfile() {
|
|
|
4217
4481
|
}
|
|
4218
4482
|
|
|
4219
4483
|
// src/kernel/system/repos.ts
|
|
4220
|
-
import { existsSync as
|
|
4484
|
+
import { existsSync as existsSync10 } from "fs";
|
|
4221
4485
|
import { resolve as resolve2 } from "path";
|
|
4222
4486
|
async function getRepoPaths(db) {
|
|
4223
4487
|
const personalSetting = await getSetting(db, "repo.personal") || await getSetting(db, "personal.workspace_dir");
|
|
@@ -4238,15 +4502,15 @@ async function resolveAllBeliefPaths(db) {
|
|
|
4238
4502
|
const dirs = [];
|
|
4239
4503
|
if (paths.personal) {
|
|
4240
4504
|
const personalDir = resolve2(paths.personal, "beliefs");
|
|
4241
|
-
if (
|
|
4505
|
+
if (existsSync10(personalDir)) dirs.push(personalDir);
|
|
4242
4506
|
}
|
|
4243
4507
|
if (paths.team) {
|
|
4244
4508
|
const teamDir = resolve2(paths.team, "beliefs");
|
|
4245
|
-
if (
|
|
4509
|
+
if (existsSync10(teamDir)) dirs.push(teamDir);
|
|
4246
4510
|
}
|
|
4247
4511
|
if (paths.org) {
|
|
4248
4512
|
const orgDir = resolve2(paths.org, "beliefs");
|
|
4249
|
-
if (
|
|
4513
|
+
if (existsSync10(orgDir)) dirs.push(orgDir);
|
|
4250
4514
|
}
|
|
4251
4515
|
return dirs;
|
|
4252
4516
|
}
|
|
@@ -4255,15 +4519,15 @@ async function resolveAllGoalPaths(db) {
|
|
|
4255
4519
|
const dirs = [];
|
|
4256
4520
|
if (paths.personal) {
|
|
4257
4521
|
const personalDir = resolve2(paths.personal, "goals");
|
|
4258
|
-
if (
|
|
4522
|
+
if (existsSync10(personalDir)) dirs.push(personalDir);
|
|
4259
4523
|
}
|
|
4260
4524
|
if (paths.team) {
|
|
4261
4525
|
const teamDir = resolve2(paths.team, "goals");
|
|
4262
|
-
if (
|
|
4526
|
+
if (existsSync10(teamDir)) dirs.push(teamDir);
|
|
4263
4527
|
}
|
|
4264
4528
|
if (paths.org) {
|
|
4265
4529
|
const orgDir = resolve2(paths.org, "goals");
|
|
4266
|
-
if (
|
|
4530
|
+
if (existsSync10(orgDir)) dirs.push(orgDir);
|
|
4267
4531
|
}
|
|
4268
4532
|
return dirs;
|
|
4269
4533
|
}
|
|
@@ -4356,11 +4620,14 @@ export {
|
|
|
4356
4620
|
DEFAULT_REVIEW_CONTEXT_MAX_CHARS,
|
|
4357
4621
|
HOMEBREW_CASK,
|
|
4358
4622
|
SNAPSHOT_VERSION,
|
|
4623
|
+
UI_OBSERVATION_PROTOCOL_VERSION,
|
|
4359
4624
|
WINGET_PACKAGE_ID,
|
|
4360
4625
|
addPrerequisite,
|
|
4361
4626
|
analyzeObservation,
|
|
4627
|
+
appendUiObservationReport,
|
|
4362
4628
|
applySessionSynthesis,
|
|
4363
4629
|
buildReviewQueue,
|
|
4630
|
+
buildUiSynthesisCandidates,
|
|
4364
4631
|
cascadeBlock,
|
|
4365
4632
|
clearADOCredentials,
|
|
4366
4633
|
clearTursoCredentials,
|
|
@@ -4381,6 +4648,7 @@ export {
|
|
|
4381
4648
|
endSession,
|
|
4382
4649
|
ensureCard,
|
|
4383
4650
|
ensureMonitorDir,
|
|
4651
|
+
ensureUiObserverDir,
|
|
4384
4652
|
evaluateRating,
|
|
4385
4653
|
executeReviewAction,
|
|
4386
4654
|
exportSnapshot,
|
|
@@ -4429,6 +4697,8 @@ export {
|
|
|
4429
4697
|
getTokenDeleteImpact,
|
|
4430
4698
|
getTokenNeighborhood,
|
|
4431
4699
|
getTursoCredentials,
|
|
4700
|
+
getUiObservationPath,
|
|
4701
|
+
getUiObserverDir,
|
|
4432
4702
|
getUserStats,
|
|
4433
4703
|
hasCommand,
|
|
4434
4704
|
importSnapshot,
|
|
@@ -4437,6 +4707,7 @@ export {
|
|
|
4437
4707
|
installOllama,
|
|
4438
4708
|
installOpenCode,
|
|
4439
4709
|
interleave,
|
|
4710
|
+
isUiObservationReport,
|
|
4440
4711
|
listAgentSkills,
|
|
4441
4712
|
listGoals,
|
|
4442
4713
|
listTokens,
|
|
@@ -4456,10 +4727,12 @@ export {
|
|
|
4456
4727
|
parseGoalFile,
|
|
4457
4728
|
parseMonitorLog,
|
|
4458
4729
|
parseSnapshot,
|
|
4730
|
+
parseUiObservationLog,
|
|
4459
4731
|
planOpenCodeInstall,
|
|
4460
4732
|
prepareLocalModel,
|
|
4461
4733
|
prepareSessionSynthesis,
|
|
4462
4734
|
readMonitorLog,
|
|
4735
|
+
readUiObservationLog,
|
|
4463
4736
|
resolveAllBeliefPaths,
|
|
4464
4737
|
resolveAllGoalPaths,
|
|
4465
4738
|
resolveReference,
|
|
@@ -4475,6 +4748,8 @@ export {
|
|
|
4475
4748
|
setTursoCredentials,
|
|
4476
4749
|
startSession,
|
|
4477
4750
|
t,
|
|
4751
|
+
uiObservationLogExists,
|
|
4752
|
+
uiObservationTimeSpan,
|
|
4478
4753
|
unblockReady,
|
|
4479
4754
|
updateCard,
|
|
4480
4755
|
updateGoalStatus,
|