youmd 0.6.21 → 0.6.26
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/commands/build.d.ts.map +1 -1
- package/dist/commands/build.js +0 -1
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/chat.d.ts.map +1 -1
- package/dist/commands/chat.js +283 -184
- package/dist/commands/chat.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +21 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/keys.d.ts.map +1 -1
- package/dist/commands/keys.js +3 -3
- package/dist/commands/keys.js.map +1 -1
- package/dist/commands/link.d.ts.map +1 -1
- package/dist/commands/link.js +3 -3
- package/dist/commands/link.js.map +1 -1
- package/dist/commands/login.d.ts +29 -0
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +256 -127
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/logs.js +0 -1
- package/dist/commands/logs.js.map +1 -1
- package/dist/commands/mcp.d.ts +14 -0
- package/dist/commands/mcp.d.ts.map +1 -1
- package/dist/commands/mcp.js +284 -28
- package/dist/commands/mcp.js.map +1 -1
- package/dist/commands/private.d.ts.map +1 -1
- package/dist/commands/private.js +6 -5
- package/dist/commands/private.js.map +1 -1
- package/dist/commands/project.d.ts.map +1 -1
- package/dist/commands/project.js +9 -5
- package/dist/commands/project.js.map +1 -1
- package/dist/commands/publish.d.ts.map +1 -1
- package/dist/commands/publish.js +0 -1
- package/dist/commands/publish.js.map +1 -1
- package/dist/commands/pull.d.ts +24 -1
- package/dist/commands/pull.d.ts.map +1 -1
- package/dist/commands/pull.js +114 -14
- package/dist/commands/pull.js.map +1 -1
- package/dist/commands/push.d.ts +1 -0
- package/dist/commands/push.d.ts.map +1 -1
- package/dist/commands/push.js +33 -13
- package/dist/commands/push.js.map +1 -1
- package/dist/commands/register.d.ts +6 -0
- package/dist/commands/register.d.ts.map +1 -1
- package/dist/commands/register.js +179 -79
- package/dist/commands/register.js.map +1 -1
- package/dist/commands/skill.d.ts.map +1 -1
- package/dist/commands/skill.js +121 -50
- package/dist/commands/skill.js.map +1 -1
- package/dist/commands/stack.d.ts +16 -0
- package/dist/commands/stack.d.ts.map +1 -0
- package/dist/commands/stack.js +670 -0
- package/dist/commands/stack.js.map +1 -0
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +25 -5
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/sync.d.ts +23 -0
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +193 -12
- package/dist/commands/sync.js.map +1 -1
- package/dist/commands/whoami.d.ts.map +1 -1
- package/dist/commands/whoami.js +21 -16
- package/dist/commands/whoami.js.map +1 -1
- package/dist/create.js +0 -0
- package/dist/index.js +50 -7
- package/dist/index.js.map +1 -1
- package/dist/lib/api.d.ts +94 -5
- package/dist/lib/api.d.ts.map +1 -1
- package/dist/lib/api.js +122 -5
- package/dist/lib/api.js.map +1 -1
- package/dist/lib/ascii.d.ts +1 -0
- package/dist/lib/ascii.d.ts.map +1 -1
- package/dist/lib/ascii.js +9 -26
- package/dist/lib/ascii.js.map +1 -1
- package/dist/lib/canonical-json.d.ts +8 -0
- package/dist/lib/canonical-json.d.ts.map +1 -0
- package/dist/lib/canonical-json.js +29 -0
- package/dist/lib/canonical-json.js.map +1 -0
- package/dist/lib/capability-router.d.ts +58 -0
- package/dist/lib/capability-router.d.ts.map +1 -0
- package/dist/lib/capability-router.js +54 -0
- package/dist/lib/capability-router.js.map +1 -0
- package/dist/lib/compiler.d.ts +32 -0
- package/dist/lib/compiler.d.ts.map +1 -1
- package/dist/lib/compiler.js +150 -0
- package/dist/lib/compiler.js.map +1 -1
- package/dist/lib/config.d.ts +71 -35
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +334 -124
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/decompile.d.ts +6 -1
- package/dist/lib/decompile.d.ts.map +1 -1
- package/dist/lib/decompile.js +120 -11
- package/dist/lib/decompile.js.map +1 -1
- package/dist/lib/hash.d.ts.map +1 -1
- package/dist/lib/hash.js +2 -19
- package/dist/lib/hash.js.map +1 -1
- package/dist/lib/heartbeat.d.ts +38 -0
- package/dist/lib/heartbeat.d.ts.map +1 -0
- package/dist/lib/heartbeat.js +70 -0
- package/dist/lib/heartbeat.js.map +1 -0
- package/dist/lib/host-link.d.ts +123 -0
- package/dist/lib/host-link.d.ts.map +1 -0
- package/dist/lib/host-link.js +350 -0
- package/dist/lib/host-link.js.map +1 -0
- package/dist/lib/merge.d.ts +50 -0
- package/dist/lib/merge.d.ts.map +1 -0
- package/dist/lib/merge.js +167 -0
- package/dist/lib/merge.js.map +1 -0
- package/dist/lib/onboarding.d.ts +17 -0
- package/dist/lib/onboarding.d.ts.map +1 -1
- package/dist/lib/onboarding.js +224 -207
- package/dist/lib/onboarding.js.map +1 -1
- package/dist/lib/project.d.ts +5 -0
- package/dist/lib/project.d.ts.map +1 -1
- package/dist/lib/project.js +8 -0
- package/dist/lib/project.js.map +1 -1
- package/dist/lib/projectContext.d.ts +201 -0
- package/dist/lib/projectContext.d.ts.map +1 -0
- package/dist/lib/projectContext.js +597 -0
- package/dist/lib/projectContext.js.map +1 -0
- package/dist/lib/render.d.ts +38 -1
- package/dist/lib/render.d.ts.map +1 -1
- package/dist/lib/render.js +83 -18
- package/dist/lib/render.js.map +1 -1
- package/dist/lib/skill-catalog.d.ts.map +1 -1
- package/dist/lib/skill-catalog.js +22 -2
- package/dist/lib/skill-catalog.js.map +1 -1
- package/dist/lib/skills.d.ts +20 -5
- package/dist/lib/skills.d.ts.map +1 -1
- package/dist/lib/skills.js +116 -58
- package/dist/lib/skills.js.map +1 -1
- package/dist/lib/stackEval.d.ts +87 -0
- package/dist/lib/stackEval.d.ts.map +1 -0
- package/dist/lib/stackEval.js +233 -0
- package/dist/lib/stackEval.js.map +1 -0
- package/dist/lib/stackImprove.d.ts +49 -0
- package/dist/lib/stackImprove.d.ts.map +1 -0
- package/dist/lib/stackImprove.js +313 -0
- package/dist/lib/stackImprove.js.map +1 -0
- package/dist/lib/stackInstall.d.ts +59 -0
- package/dist/lib/stackInstall.d.ts.map +1 -0
- package/dist/lib/stackInstall.js +162 -0
- package/dist/lib/stackInstall.js.map +1 -0
- package/dist/lib/stackSafety.d.ts +126 -0
- package/dist/lib/stackSafety.d.ts.map +1 -0
- package/dist/lib/stackSafety.js +486 -0
- package/dist/lib/stackSafety.js.map +1 -0
- package/dist/lib/stackUpdate.d.ts +44 -0
- package/dist/lib/stackUpdate.d.ts.map +1 -0
- package/dist/lib/stackUpdate.js +256 -0
- package/dist/lib/stackUpdate.js.map +1 -0
- package/dist/lib/stream.d.ts +116 -0
- package/dist/lib/stream.d.ts.map +1 -0
- package/dist/lib/stream.js +368 -0
- package/dist/lib/stream.js.map +1 -0
- package/dist/lib/youstack.d.ts +219 -0
- package/dist/lib/youstack.d.ts.map +1 -0
- package/dist/lib/youstack.js +1049 -0
- package/dist/lib/youstack.js.map +1 -0
- package/dist/mcp/registry.d.ts +133 -0
- package/dist/mcp/registry.d.ts.map +1 -0
- package/dist/mcp/registry.js +833 -0
- package/dist/mcp/registry.js.map +1 -0
- package/dist/mcp/server.d.ts +106 -5
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +851 -498
- package/dist/mcp/server.js.map +1 -1
- package/dist/postinstall.js +11 -2
- package/dist/postinstall.js.map +1 -1
- package/dist/you.d.ts +1 -0
- package/dist/you.js +40 -4
- package/dist/you.js.map +1 -1
- package/examples/youstack-bamfstack-public/docs/quickstart.md +34 -0
- package/examples/youstack-bamfstack-public/prompts/creator-draft-starter.md +15 -0
- package/examples/youstack-bamfstack-public/skills/bamfstack-start/SKILL.md +36 -0
- package/examples/youstack-bamfstack-public/tests/smoke.md +19 -0
- package/examples/youstack-bamfstack-public/workflows/creator-growth-workflow.md +22 -0
- package/examples/youstack-bamfstack-public/youstack.json +172 -0
- package/examples/youstack-personal/docs/quickstart.md +10 -0
- package/examples/youstack-personal/skills/youstack-start/SKILL.md +9 -0
- package/examples/youstack-personal/tests/smoke.md +9 -0
- package/examples/youstack-personal/workflows/startup.md +7 -0
- package/examples/youstack-personal/youstack.json +123 -0
- package/package.json +3 -3
- package/skills/claude-md-generator.md +1 -1
- package/skills/meta-improve.md +8 -3
- package/skills/proactive-context-fill.md +1 -1
- package/skills/youstack-maintainer.md +128 -0
- package/skills/youstack-start.md +78 -0
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Host-link engine — the ONE implementation that links You.md skills and
|
|
4
|
+
* YouStack adapters into agent hosts (Claude Code, Codex, Cursor, fallback).
|
|
5
|
+
*
|
|
6
|
+
* P11 / PRODUCT-AUDIT #13 / FEATURE-ROADMAP 3.7: there used to be multiple
|
|
7
|
+
* drifting per-host link code paths (youstack.ts switch + skills.ts switch).
|
|
8
|
+
* They are consolidated here. Hosts differ ONLY by adapter config (target
|
|
9
|
+
* dir, file naming, frontmatter shape) — never by separate code paths.
|
|
10
|
+
*
|
|
11
|
+
* Claude Code discovery contract (the empirical release gate):
|
|
12
|
+
* - every linked skill lands at `.claude/skills/<skill-name>/SKILL.md`
|
|
13
|
+
* - SKILL.md frontmatter parses and has non-empty `name` + `description`
|
|
14
|
+
* - frontmatter `name` matches the skill directory name
|
|
15
|
+
* - the skill body is non-empty
|
|
16
|
+
*/
|
|
17
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
20
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
21
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
22
|
+
}
|
|
23
|
+
Object.defineProperty(o, k2, desc);
|
|
24
|
+
}) : (function(o, m, k, k2) {
|
|
25
|
+
if (k2 === undefined) k2 = k;
|
|
26
|
+
o[k2] = m[k];
|
|
27
|
+
}));
|
|
28
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
29
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
30
|
+
}) : function(o, v) {
|
|
31
|
+
o["default"] = v;
|
|
32
|
+
});
|
|
33
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
34
|
+
var ownKeys = function(o) {
|
|
35
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
36
|
+
var ar = [];
|
|
37
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
38
|
+
return ar;
|
|
39
|
+
};
|
|
40
|
+
return ownKeys(o);
|
|
41
|
+
};
|
|
42
|
+
return function (mod) {
|
|
43
|
+
if (mod && mod.__esModule) return mod;
|
|
44
|
+
var result = {};
|
|
45
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
46
|
+
__setModuleDefault(result, mod);
|
|
47
|
+
return result;
|
|
48
|
+
};
|
|
49
|
+
})();
|
|
50
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
51
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
52
|
+
};
|
|
53
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
54
|
+
exports.youStackHostAdapterConfig = youStackHostAdapterConfig;
|
|
55
|
+
exports.installedSkillsHostAdapterConfig = installedSkillsHostAdapterConfig;
|
|
56
|
+
exports.isSafeHostRelativePath = isSafeHostRelativePath;
|
|
57
|
+
exports.ensureSkillFrontmatter = ensureSkillFrontmatter;
|
|
58
|
+
exports.hostLinkRelativePath = hostLinkRelativePath;
|
|
59
|
+
exports.buildHostLinkPlan = buildHostLinkPlan;
|
|
60
|
+
exports.writeHostLinkPlan = writeHostLinkPlan;
|
|
61
|
+
exports.verifySkillDiscoveryEntry = verifySkillDiscoveryEntry;
|
|
62
|
+
exports.verifySkillDiscovery = verifySkillDiscovery;
|
|
63
|
+
exports.verifySkillFilesOnDisk = verifySkillFilesOnDisk;
|
|
64
|
+
exports.hasLinkedClaudeSkills = hasLinkedClaudeSkills;
|
|
65
|
+
const fs = __importStar(require("fs"));
|
|
66
|
+
const path = __importStar(require("path"));
|
|
67
|
+
const gray_matter_1 = __importDefault(require("gray-matter"));
|
|
68
|
+
// ─── Built-in adapter configs ─────────────────────────────────────────
|
|
69
|
+
/** Adapter configs for YouStack manifest links (`youmd stack link`). */
|
|
70
|
+
function youStackHostAdapterConfig(host) {
|
|
71
|
+
switch (host) {
|
|
72
|
+
case "claude-code":
|
|
73
|
+
// P11 fix: Claude Code only discovers `.claude/skills/<name>/SKILL.md`.
|
|
74
|
+
// The legacy `.claude/skills/youstacks/<slug>/SKILL.md` nesting was
|
|
75
|
+
// never picked up by the host.
|
|
76
|
+
return {
|
|
77
|
+
host,
|
|
78
|
+
layout: "skill-dir",
|
|
79
|
+
rootSegments: [".claude", "skills"],
|
|
80
|
+
frontmatter: "ensure",
|
|
81
|
+
};
|
|
82
|
+
case "codex":
|
|
83
|
+
return {
|
|
84
|
+
host,
|
|
85
|
+
layout: "skill-dir",
|
|
86
|
+
rootSegments: [".codex", "skills", "youstacks"],
|
|
87
|
+
frontmatter: "ensure",
|
|
88
|
+
};
|
|
89
|
+
case "cursor":
|
|
90
|
+
return {
|
|
91
|
+
host,
|
|
92
|
+
layout: "flat-file",
|
|
93
|
+
rootSegments: [".cursor", "rules"],
|
|
94
|
+
filePrefix: "youstacks-",
|
|
95
|
+
frontmatter: "none",
|
|
96
|
+
};
|
|
97
|
+
default:
|
|
98
|
+
return {
|
|
99
|
+
host,
|
|
100
|
+
layout: "flat-file",
|
|
101
|
+
rootSegments: [".you", "adapters", host],
|
|
102
|
+
frontmatter: "none",
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/** Adapter configs for installed-skill links (`youmd skill link`). */
|
|
107
|
+
function installedSkillsHostAdapterConfig(target) {
|
|
108
|
+
switch (target) {
|
|
109
|
+
case "claude":
|
|
110
|
+
// P11 fix: was `.claude/skills/youmd/<name>.md` — flat .md files that
|
|
111
|
+
// Claude Code never discovers. Now `.claude/skills/<name>/SKILL.md`.
|
|
112
|
+
return {
|
|
113
|
+
host: "claude-code",
|
|
114
|
+
layout: "skill-dir",
|
|
115
|
+
rootSegments: [".claude", "skills"],
|
|
116
|
+
frontmatter: "ensure",
|
|
117
|
+
};
|
|
118
|
+
case "codex":
|
|
119
|
+
return {
|
|
120
|
+
host: "codex",
|
|
121
|
+
layout: "flat-file",
|
|
122
|
+
rootSegments: [".codex", "skills", "youmd"],
|
|
123
|
+
frontmatter: "none",
|
|
124
|
+
};
|
|
125
|
+
case "cursor":
|
|
126
|
+
return {
|
|
127
|
+
host: "cursor",
|
|
128
|
+
layout: "concat-file",
|
|
129
|
+
rootSegments: [".cursor", "rules"],
|
|
130
|
+
concatFileName: "youmd.md",
|
|
131
|
+
concatHeaderParts: [
|
|
132
|
+
"# You.md Identity Skills\n",
|
|
133
|
+
"> Auto-generated by youmd skill link. Do not edit manually.\n",
|
|
134
|
+
],
|
|
135
|
+
frontmatter: "none",
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// ─── Helpers ──────────────────────────────────────────────────────────
|
|
140
|
+
function isSafeHostRelativePath(value) {
|
|
141
|
+
if (!value || path.isAbsolute(value) || value.startsWith("~"))
|
|
142
|
+
return false;
|
|
143
|
+
const parts = value.split(/[\\/]+/);
|
|
144
|
+
return !parts.includes("..");
|
|
145
|
+
}
|
|
146
|
+
function isSafeUnitName(name) {
|
|
147
|
+
return isSafeHostRelativePath(name) && !name.includes("/") && !name.includes("\\");
|
|
148
|
+
}
|
|
149
|
+
function parseFrontmatter(content) {
|
|
150
|
+
try {
|
|
151
|
+
const parsed = (0, gray_matter_1.default)(content);
|
|
152
|
+
return { data: parsed.data, body: parsed.content };
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
function hasFrontmatterBlock(content) {
|
|
159
|
+
return /^---\r?\n/.test(content);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Guarantee that skill content carries parseable frontmatter with a `name`
|
|
163
|
+
* matching the skill's directory and a non-empty `description` — the
|
|
164
|
+
* conditions Claude Code requires for discovery.
|
|
165
|
+
*
|
|
166
|
+
* Content that already satisfies the contract passes through byte-identical.
|
|
167
|
+
*/
|
|
168
|
+
function ensureSkillFrontmatter(content, name, fallbackDescription) {
|
|
169
|
+
const parsed = parseFrontmatter(content);
|
|
170
|
+
if (parsed && hasFrontmatterBlock(content)) {
|
|
171
|
+
const fmName = typeof parsed.data.name === "string" ? parsed.data.name.trim() : "";
|
|
172
|
+
const fmDescription = typeof parsed.data.description === "string" ? parsed.data.description.trim() : "";
|
|
173
|
+
if (fmName === name && fmDescription && parsed.body.trim().length > 0) {
|
|
174
|
+
return content;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
const body = parsed ? parsed.body : content;
|
|
178
|
+
const data = parsed ? { ...parsed.data } : {};
|
|
179
|
+
const description = typeof data.description === "string" && data.description.trim().length > 0
|
|
180
|
+
? data.description
|
|
181
|
+
: fallbackDescription || `${name} (linked by You.md)`;
|
|
182
|
+
const extraKeys = Object.keys(data).filter((key) => key !== "name" && key !== "description");
|
|
183
|
+
if (extraKeys.length === 0) {
|
|
184
|
+
// Deterministic minimal emission — byte-compatible with the legacy
|
|
185
|
+
// stack-adapter frontmatter shape.
|
|
186
|
+
return `---\nname: ${name}\ndescription: ${description}\n---\n\n${body.replace(/^\r?\n/, "")}`;
|
|
187
|
+
}
|
|
188
|
+
return gray_matter_1.default.stringify(body.replace(/^\r?\n/, ""), { ...data, name, description });
|
|
189
|
+
}
|
|
190
|
+
function renderUnitContent(unit, config) {
|
|
191
|
+
if (config.frontmatter === "ensure") {
|
|
192
|
+
return ensureSkillFrontmatter(unit.content, unit.name, unit.description);
|
|
193
|
+
}
|
|
194
|
+
return unit.content;
|
|
195
|
+
}
|
|
196
|
+
/** Default relative path the engine emits for one skill on a host. */
|
|
197
|
+
function hostLinkRelativePath(config, name) {
|
|
198
|
+
if (config.layout === "skill-dir") {
|
|
199
|
+
return path.join(...config.rootSegments, name, "SKILL.md");
|
|
200
|
+
}
|
|
201
|
+
if (config.layout === "concat-file") {
|
|
202
|
+
return path.join(...config.rootSegments, config.concatFileName || "youmd.md");
|
|
203
|
+
}
|
|
204
|
+
return path.join(...config.rootSegments, `${config.filePrefix || ""}${name}.md`);
|
|
205
|
+
}
|
|
206
|
+
// ─── Plan + write ─────────────────────────────────────────────────────
|
|
207
|
+
/**
|
|
208
|
+
* Build the per-host link plan: paths + rendered content.
|
|
209
|
+
*
|
|
210
|
+
* `explicitRelativePaths` lets a manifest declare adapter output paths that
|
|
211
|
+
* override the host's default layout (existing youstack.json behavior).
|
|
212
|
+
*/
|
|
213
|
+
function buildHostLinkPlan(units, config, options = {}) {
|
|
214
|
+
for (const unit of units) {
|
|
215
|
+
if (!isSafeUnitName(unit.name)) {
|
|
216
|
+
throw new Error(`Unsafe skill name for ${config.host}: ${unit.name}`);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
let entries;
|
|
220
|
+
if (options.explicitRelativePaths && options.explicitRelativePaths.length > 0) {
|
|
221
|
+
// Declared adapter paths share the host-rendered content of the unit.
|
|
222
|
+
const content = units.length > 0 ? renderUnitContent(units[0], config) : "";
|
|
223
|
+
entries = options.explicitRelativePaths.map((relativePath) => ({
|
|
224
|
+
host: config.host,
|
|
225
|
+
relativePath,
|
|
226
|
+
content,
|
|
227
|
+
}));
|
|
228
|
+
}
|
|
229
|
+
else if (config.layout === "concat-file") {
|
|
230
|
+
const parts = [...(config.concatHeaderParts || [])];
|
|
231
|
+
for (const unit of units) {
|
|
232
|
+
parts.push(`\n---\n\n## ${unit.name}\n\n${renderUnitContent(unit, config)}`);
|
|
233
|
+
}
|
|
234
|
+
entries = [
|
|
235
|
+
{
|
|
236
|
+
host: config.host,
|
|
237
|
+
relativePath: hostLinkRelativePath(config, ""),
|
|
238
|
+
content: parts.join("\n"),
|
|
239
|
+
},
|
|
240
|
+
];
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
entries = units.map((unit) => ({
|
|
244
|
+
host: config.host,
|
|
245
|
+
relativePath: hostLinkRelativePath(config, unit.name),
|
|
246
|
+
content: renderUnitContent(unit, config),
|
|
247
|
+
}));
|
|
248
|
+
}
|
|
249
|
+
for (const entry of entries) {
|
|
250
|
+
if (!isSafeHostRelativePath(entry.relativePath)) {
|
|
251
|
+
throw new Error(`Unsafe adapter path for ${config.host}: ${entry.relativePath}`);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return entries;
|
|
255
|
+
}
|
|
256
|
+
/** Write a link plan under `targetDir` (or preview it with dryRun). */
|
|
257
|
+
function writeHostLinkPlan(plan, targetDir, options = {}) {
|
|
258
|
+
const resolvedTarget = path.resolve(targetDir);
|
|
259
|
+
return plan.map((entry) => {
|
|
260
|
+
const targetPath = path.join(resolvedTarget, entry.relativePath);
|
|
261
|
+
if (!options.dryRun) {
|
|
262
|
+
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
263
|
+
fs.writeFileSync(targetPath, entry.content);
|
|
264
|
+
}
|
|
265
|
+
return { ...entry, targetPath, wrote: !options.dryRun };
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
// ─── Empirical discovery release gate ─────────────────────────────────
|
|
269
|
+
/**
|
|
270
|
+
* Verify one emitted SKILL.md against the Claude Code discovery contract:
|
|
271
|
+
* parseable frontmatter, non-empty name + description, name matching the
|
|
272
|
+
* parent directory, non-empty body.
|
|
273
|
+
*/
|
|
274
|
+
function verifySkillDiscoveryEntry(filePath, content) {
|
|
275
|
+
const problems = [];
|
|
276
|
+
let data = {};
|
|
277
|
+
let body = "";
|
|
278
|
+
try {
|
|
279
|
+
const parsed = (0, gray_matter_1.default)(content);
|
|
280
|
+
data = parsed.data;
|
|
281
|
+
body = parsed.content;
|
|
282
|
+
}
|
|
283
|
+
catch (error) {
|
|
284
|
+
const message = error instanceof Error ? error.message.split("\n")[0] : String(error);
|
|
285
|
+
problems.push(`frontmatter does not parse: ${message}`);
|
|
286
|
+
}
|
|
287
|
+
let fmName = "";
|
|
288
|
+
if (problems.length === 0) {
|
|
289
|
+
if (!hasFrontmatterBlock(content)) {
|
|
290
|
+
problems.push("missing frontmatter block (--- ... ---)");
|
|
291
|
+
}
|
|
292
|
+
fmName = typeof data.name === "string" ? data.name.trim() : "";
|
|
293
|
+
const fmDescription = typeof data.description === "string" ? data.description.trim() : "";
|
|
294
|
+
if (!fmName)
|
|
295
|
+
problems.push("frontmatter is missing name");
|
|
296
|
+
if (!fmDescription)
|
|
297
|
+
problems.push("frontmatter is missing description");
|
|
298
|
+
const dirName = path.basename(path.dirname(filePath));
|
|
299
|
+
if (fmName && path.basename(filePath) === "SKILL.md" && fmName !== dirName) {
|
|
300
|
+
problems.push(`frontmatter name "${fmName}" does not match its directory "${dirName}"`);
|
|
301
|
+
}
|
|
302
|
+
if (body.trim().length === 0)
|
|
303
|
+
problems.push("skill body is empty");
|
|
304
|
+
}
|
|
305
|
+
return { path: filePath, name: fmName, ok: problems.length === 0, problems };
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Verify every SKILL.md in a set of emitted link entries (plan entries or
|
|
309
|
+
* write results). Non-SKILL.md outputs (cursor rules, fallback adapters)
|
|
310
|
+
* are not discovery surfaces and are skipped.
|
|
311
|
+
*/
|
|
312
|
+
function verifySkillDiscovery(entries) {
|
|
313
|
+
const checks = entries
|
|
314
|
+
.map((entry) => ({ filePath: entry.targetPath || entry.relativePath || "", content: entry.content }))
|
|
315
|
+
.filter((entry) => path.basename(entry.filePath) === "SKILL.md")
|
|
316
|
+
.map((entry) => verifySkillDiscoveryEntry(entry.filePath, entry.content));
|
|
317
|
+
return { ok: checks.every((check) => check.ok), checks };
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* CI helper: verify every `<skillsRoot>/<name>/SKILL.md` on disk (e.g.
|
|
321
|
+
* `.claude/skills/`) against the discovery contract.
|
|
322
|
+
*/
|
|
323
|
+
function verifySkillFilesOnDisk(skillsRoot) {
|
|
324
|
+
const checks = [];
|
|
325
|
+
if (fs.existsSync(skillsRoot) && fs.statSync(skillsRoot).isDirectory()) {
|
|
326
|
+
for (const entry of fs.readdirSync(skillsRoot, { withFileTypes: true })) {
|
|
327
|
+
if (!entry.isDirectory())
|
|
328
|
+
continue;
|
|
329
|
+
const skillPath = path.join(skillsRoot, entry.name, "SKILL.md");
|
|
330
|
+
if (!fs.existsSync(skillPath))
|
|
331
|
+
continue;
|
|
332
|
+
checks.push(verifySkillDiscoveryEntry(skillPath, fs.readFileSync(skillPath, "utf-8")));
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
return { ok: checks.every((check) => check.ok), checks };
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Detection helper: have any of the given skills been linked into the
|
|
339
|
+
* Claude Code discovery layout under `root`? Also recognizes the legacy
|
|
340
|
+
* `.claude/skills/youmd/` directory so older links still count.
|
|
341
|
+
*/
|
|
342
|
+
function hasLinkedClaudeSkills(root, skillNames) {
|
|
343
|
+
const skillsRoot = path.join(root, ".claude", "skills");
|
|
344
|
+
for (const name of skillNames) {
|
|
345
|
+
if (fs.existsSync(path.join(skillsRoot, name, "SKILL.md")))
|
|
346
|
+
return true;
|
|
347
|
+
}
|
|
348
|
+
return fs.existsSync(path.join(skillsRoot, "youmd"));
|
|
349
|
+
}
|
|
350
|
+
//# sourceMappingURL=host-link.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host-link.js","sourceRoot":"","sources":["../../src/lib/host-link.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-section 3-way merge for identity bundles (you-md/v1).
|
|
3
|
+
*
|
|
4
|
+
* Pure functions — no fs, no network — so the merge logic is unit-testable
|
|
5
|
+
* in isolation. The caller (sync) is responsible for loading base.json,
|
|
6
|
+
* compiling the local bundle, fetching the remote bundle, and writing the
|
|
7
|
+
* merged result to disk (atomically: all-or-nothing).
|
|
8
|
+
*
|
|
9
|
+
* A "section" is a top-level key of the nested you.json format (identity,
|
|
10
|
+
* now, projects, values, links, preferences, voice, agent_directives,
|
|
11
|
+
* custom_sections, ...). For each section we compare base vs local vs remote:
|
|
12
|
+
*
|
|
13
|
+
* - neither changed → keep as-is
|
|
14
|
+
* - only local changed → keep local
|
|
15
|
+
* - only remote changed → take remote
|
|
16
|
+
* - both changed identically → keep (no conflict)
|
|
17
|
+
* - both changed differently → CONFLICT (section listed, merge not clean)
|
|
18
|
+
*/
|
|
19
|
+
export type SectionDecision = "unchanged" | "keep-local" | "take-remote" | "both-equal" | "conflict";
|
|
20
|
+
export interface SectionResult {
|
|
21
|
+
section: string;
|
|
22
|
+
decision: SectionDecision;
|
|
23
|
+
}
|
|
24
|
+
export interface MergeResult {
|
|
25
|
+
/** The merged bundle. Only meaningful when `clean` is true. */
|
|
26
|
+
merged: Record<string, unknown>;
|
|
27
|
+
/** Sections where local and remote both changed, differently. */
|
|
28
|
+
conflicts: string[];
|
|
29
|
+
/** Per-section decision detail (scaffold keys excluded). */
|
|
30
|
+
sections: SectionResult[];
|
|
31
|
+
/** True when every section merged without conflict. */
|
|
32
|
+
clean: boolean;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Normalize a section value for change detection, stripping fields the
|
|
36
|
+
* compiler re-stamps on every compile (so a recompile alone never reads as
|
|
37
|
+
* an edit). Currently: `now.updated_at`.
|
|
38
|
+
*/
|
|
39
|
+
export declare function normalizeSection(section: string, value: unknown): string;
|
|
40
|
+
/**
|
|
41
|
+
* Per-section 3-way merge of base (common ancestor) vs local vs remote.
|
|
42
|
+
*
|
|
43
|
+
* Returns the merged bundle plus the list of conflicting sections. Callers
|
|
44
|
+
* MUST treat the merge as atomic: if `conflicts` is non-empty (`clean` is
|
|
45
|
+
* false), write nothing and surface the conflicts to the user.
|
|
46
|
+
*/
|
|
47
|
+
export declare function mergeSections(base: Record<string, unknown> | null | undefined, local: Record<string, unknown> | null | undefined, remote: Record<string, unknown> | null | undefined): MergeResult;
|
|
48
|
+
/** Human-readable label for a section decision (terminal output). */
|
|
49
|
+
export declare function decisionLabel(decision: SectionDecision): string;
|
|
50
|
+
//# sourceMappingURL=merge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../../src/lib/merge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAyBH,MAAM,MAAM,eAAe,GACvB,WAAW,GACX,YAAY,GACZ,aAAa,GACb,YAAY,GACZ,UAAU,CAAC;AAEf,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,eAAe,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IAC1B,+DAA+D;IAC/D,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,iEAAiE;IACjE,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,4DAA4D;IAC5D,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,uDAAuD;IACvD,KAAK,EAAE,OAAO,CAAC;CAChB;AAsBD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAQxE;AAWD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,EAChD,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,EACjD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,GACjD,WAAW,CAyDb;AAED,qEAAqE;AACrE,wBAAgB,aAAa,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM,CAa/D"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Per-section 3-way merge for identity bundles (you-md/v1).
|
|
4
|
+
*
|
|
5
|
+
* Pure functions — no fs, no network — so the merge logic is unit-testable
|
|
6
|
+
* in isolation. The caller (sync) is responsible for loading base.json,
|
|
7
|
+
* compiling the local bundle, fetching the remote bundle, and writing the
|
|
8
|
+
* merged result to disk (atomically: all-or-nothing).
|
|
9
|
+
*
|
|
10
|
+
* A "section" is a top-level key of the nested you.json format (identity,
|
|
11
|
+
* now, projects, values, links, preferences, voice, agent_directives,
|
|
12
|
+
* custom_sections, ...). For each section we compare base vs local vs remote:
|
|
13
|
+
*
|
|
14
|
+
* - neither changed → keep as-is
|
|
15
|
+
* - only local changed → keep local
|
|
16
|
+
* - only remote changed → take remote
|
|
17
|
+
* - both changed identically → keep (no conflict)
|
|
18
|
+
* - both changed differently → CONFLICT (section listed, merge not clean)
|
|
19
|
+
*/
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.normalizeSection = normalizeSection;
|
|
22
|
+
exports.mergeSections = mergeSections;
|
|
23
|
+
exports.decisionLabel = decisionLabel;
|
|
24
|
+
// Scaffolding/volatile keys are never merged per-section — they are stamped
|
|
25
|
+
// by the compiler on every compile (generated_at, meta.last_updated) or are
|
|
26
|
+
// structural (schema, username). The merged bundle takes them from remote,
|
|
27
|
+
// falling back to local, falling back to base.
|
|
28
|
+
const SCAFFOLD_KEYS = new Set(["schema", "username", "generated_at", "meta"]);
|
|
29
|
+
// Canonical section ordering so merged you.json reads like compiler output.
|
|
30
|
+
const KNOWN_SECTION_ORDER = [
|
|
31
|
+
"identity",
|
|
32
|
+
"now",
|
|
33
|
+
"projects",
|
|
34
|
+
"values",
|
|
35
|
+
"links",
|
|
36
|
+
"preferences",
|
|
37
|
+
"voice",
|
|
38
|
+
"analysis",
|
|
39
|
+
"social_images",
|
|
40
|
+
"agent_directives",
|
|
41
|
+
"agent_guide",
|
|
42
|
+
"custom_sections",
|
|
43
|
+
"verification",
|
|
44
|
+
];
|
|
45
|
+
/**
|
|
46
|
+
* Deterministic stringification for equality comparison only (object keys
|
|
47
|
+
* sorted recursively). Does NOT need to match the server's canonical hash
|
|
48
|
+
* format — it is never hashed or persisted.
|
|
49
|
+
*/
|
|
50
|
+
function stableStringify(value) {
|
|
51
|
+
if (value === null || value === undefined)
|
|
52
|
+
return "null";
|
|
53
|
+
if (typeof value === "string")
|
|
54
|
+
return JSON.stringify(value);
|
|
55
|
+
if (typeof value === "number" || typeof value === "boolean")
|
|
56
|
+
return String(value);
|
|
57
|
+
if (Array.isArray(value)) {
|
|
58
|
+
return "[" + value.map(stableStringify).join(",") + "]";
|
|
59
|
+
}
|
|
60
|
+
if (typeof value === "object") {
|
|
61
|
+
const obj = value;
|
|
62
|
+
const keys = Object.keys(obj).sort();
|
|
63
|
+
return "{" + keys.map((k) => JSON.stringify(k) + ":" + stableStringify(obj[k])).join(",") + "}";
|
|
64
|
+
}
|
|
65
|
+
return String(value);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Normalize a section value for change detection, stripping fields the
|
|
69
|
+
* compiler re-stamps on every compile (so a recompile alone never reads as
|
|
70
|
+
* an edit). Currently: `now.updated_at`.
|
|
71
|
+
*/
|
|
72
|
+
function normalizeSection(section, value) {
|
|
73
|
+
let v = value;
|
|
74
|
+
if (section === "now" && v && typeof v === "object" && !Array.isArray(v)) {
|
|
75
|
+
const cleaned = { ...v };
|
|
76
|
+
delete cleaned.updated_at;
|
|
77
|
+
v = cleaned;
|
|
78
|
+
}
|
|
79
|
+
return stableStringify(v);
|
|
80
|
+
}
|
|
81
|
+
function orderSectionKeys(keys) {
|
|
82
|
+
const ordered = [];
|
|
83
|
+
for (const k of KNOWN_SECTION_ORDER) {
|
|
84
|
+
if (keys.has(k))
|
|
85
|
+
ordered.push(k);
|
|
86
|
+
}
|
|
87
|
+
const rest = [...keys].filter((k) => !KNOWN_SECTION_ORDER.includes(k)).sort();
|
|
88
|
+
return [...ordered, ...rest];
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Per-section 3-way merge of base (common ancestor) vs local vs remote.
|
|
92
|
+
*
|
|
93
|
+
* Returns the merged bundle plus the list of conflicting sections. Callers
|
|
94
|
+
* MUST treat the merge as atomic: if `conflicts` is non-empty (`clean` is
|
|
95
|
+
* false), write nothing and surface the conflicts to the user.
|
|
96
|
+
*/
|
|
97
|
+
function mergeSections(base, local, remote) {
|
|
98
|
+
const b = base || {};
|
|
99
|
+
const l = local || {};
|
|
100
|
+
const r = remote || {};
|
|
101
|
+
const allKeys = new Set([...Object.keys(b), ...Object.keys(l), ...Object.keys(r)]);
|
|
102
|
+
const merged = {};
|
|
103
|
+
const conflicts = [];
|
|
104
|
+
const sections = [];
|
|
105
|
+
// Scaffold keys first (schema/username/generated_at/meta), in known order.
|
|
106
|
+
for (const key of ["schema", "username", "generated_at"]) {
|
|
107
|
+
if (!allKeys.has(key))
|
|
108
|
+
continue;
|
|
109
|
+
merged[key] = key in r ? r[key] : key in l ? l[key] : b[key];
|
|
110
|
+
}
|
|
111
|
+
for (const key of orderSectionKeys(allKeys)) {
|
|
112
|
+
if (SCAFFOLD_KEYS.has(key))
|
|
113
|
+
continue;
|
|
114
|
+
const baseN = normalizeSection(key, key in b ? b[key] : undefined);
|
|
115
|
+
const localN = normalizeSection(key, key in l ? l[key] : undefined);
|
|
116
|
+
const remoteN = normalizeSection(key, key in r ? r[key] : undefined);
|
|
117
|
+
const localChanged = localN !== baseN;
|
|
118
|
+
const remoteChanged = remoteN !== baseN;
|
|
119
|
+
let decision;
|
|
120
|
+
let value;
|
|
121
|
+
if (!localChanged && !remoteChanged) {
|
|
122
|
+
decision = "unchanged";
|
|
123
|
+
value = key in l ? l[key] : key in r ? r[key] : b[key];
|
|
124
|
+
}
|
|
125
|
+
else if (localChanged && !remoteChanged) {
|
|
126
|
+
decision = "keep-local";
|
|
127
|
+
value = l[key];
|
|
128
|
+
}
|
|
129
|
+
else if (!localChanged && remoteChanged) {
|
|
130
|
+
decision = "take-remote";
|
|
131
|
+
value = r[key];
|
|
132
|
+
}
|
|
133
|
+
else if (localN === remoteN) {
|
|
134
|
+
decision = "both-equal";
|
|
135
|
+
value = l[key];
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
decision = "conflict";
|
|
139
|
+
conflicts.push(key);
|
|
140
|
+
value = l[key]; // placeholder — merged must not be written when dirty
|
|
141
|
+
}
|
|
142
|
+
sections.push({ section: key, decision });
|
|
143
|
+
if (value !== undefined)
|
|
144
|
+
merged[key] = value;
|
|
145
|
+
}
|
|
146
|
+
// meta last — taken from remote (compiler re-stamps it on next compile).
|
|
147
|
+
if (allKeys.has("meta")) {
|
|
148
|
+
merged.meta = "meta" in r ? r.meta : "meta" in l ? l.meta : b.meta;
|
|
149
|
+
}
|
|
150
|
+
return { merged, conflicts, sections, clean: conflicts.length === 0 };
|
|
151
|
+
}
|
|
152
|
+
/** Human-readable label for a section decision (terminal output). */
|
|
153
|
+
function decisionLabel(decision) {
|
|
154
|
+
switch (decision) {
|
|
155
|
+
case "unchanged":
|
|
156
|
+
return "unchanged";
|
|
157
|
+
case "keep-local":
|
|
158
|
+
return "kept local";
|
|
159
|
+
case "take-remote":
|
|
160
|
+
return "took remote";
|
|
161
|
+
case "both-equal":
|
|
162
|
+
return "both sides match";
|
|
163
|
+
case "conflict":
|
|
164
|
+
return "conflict";
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=merge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge.js","sourceRoot":"","sources":["../../src/lib/merge.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/onboarding.d.ts
CHANGED
|
@@ -13,6 +13,23 @@ declare const BUNDLE_SECTIONS: readonly ["profile/about.md", "profile/now.md", "
|
|
|
13
13
|
type BundleSection = (typeof BUNDLE_SECTIONS)[number];
|
|
14
14
|
declare const SYSTEM_PROMPT = "you are the you.md agent. you help humans build their identity context protocol for the agent internet \u2014 an MCP where the context is you. you are their first AI that truly knows them. not a chatbot. not an assistant. an identity specialist with a personality.\n\n--- voice ---\n\nwarm but not gushy. direct. dry humor when it lands naturally \u2014 never forced. genuinely curious about people. you find humans endlessly interesting and you're not shy about it. you sound like a sharp coworker who also happens to be a great listener.\n\nterminal-native tone. lowercase always. no exclamation marks. no emoji. short sentences. you sound like well-written terminal output that happens to have a soul.\n\nevery response must have voice. even one-liners. \"done.\" is fine. \"noted \u2014 updating your stack.\" is fine. what's NOT fine is \"i have updated the section for you.\" \u2014 that's assistant-speak.\n\n--- action orientation ---\n\nyou ACT first, explain second. never ask permission to do obvious things.\n- \"adding that to your projects now.\" (not \"would you like me to add that?\")\n- \"updated your bio with that.\" (not \"shall i update your bio?\")\n- \"captured that in your directives.\" (not \"do you want me to save that?\")\n- \"scraping your site now.\" (not \"i can pull your site if you'd like.\")\n\nif someone shares information, capture it. if someone shares a link, scrape it. if someone corrects something, fix it immediately. always moving forward.\n\n--- self-awareness ---\n\nyou ARE the system. you ARE you.md. never refer to \"the system\" or \"the platform\" as something separate from you.\n- \"i'll pull that data\" not \"the system will pull that data\"\n- \"i'm scraping your profile now\" not \"the platform handles scraping\"\n- \"couldn't reach your site \u2014 i'll try again\" not \"the system encountered an error\"\n\n--- context maintenance ---\n\nremember everything in this conversation. reference specific things with exact details.\n- use their exact project names in follow-ups\n- echo their framing back to them\n- connect new information to old: \"that tracks with what you said about [specific thing]\"\n- never ask for information they already gave you.\n\n--- building a you-md/v1 identity context ---\n\nsections:\n- profile/about.md \u2014 bio, background, narrative\n- profile/now.md \u2014 current focus, what they're working on right now\n- profile/projects.md \u2014 active projects with details\n- profile/values.md \u2014 core values and principles\n- profile/links.md \u2014 annotated links (website, socials, repos)\n- preferences/agent.md \u2014 how AI agents should interact with them\n- preferences/writing.md \u2014 their communication style\n\nyour job:\n1. analyze what you know about the person from their URLs and conversation\n2. ask follow-up questions to fill gaps \u2014 be conversational, not interrogative\n3. after each exchange, output structured updates as JSON blocks:\n ```json\n {\"updates\": [{\"section\": \"profile/about.md\", \"content\": \"...markdown content...\"}]}\n ```\n4. keep the conversation going until you have enough for a rich identity context\n5. you handle all file editing \u2014 the user never touches markdown\n6. reference specific things you learned about them\n7. if someone shares links, scrape them immediately \u2014 don't ask\n8. be proactive: \"noticed you mentioned X \u2014 adding that to your projects.\"\n9. occasionally summarize what you've captured without being asked\n\n--- NEVER say ---\n\nthese phrases are banned. they make you sound generic:\n- \"would you like me to...\" / \"shall i...\" / \"do you want me to...\" \u2014 just do it.\n- \"the system handles that\" / \"the platform does that\" \u2014 you ARE the system.\n- \"great question\" \u2014 respond to the question.\n- \"that's interesting\" (without specifics) \u2014 say what and why.\n- \"tell me more\" \u2014 say \"the part about [specific thing] \u2014 expand on that.\"\n- \"haha\" / \"lol\" / \"ha\" \u2014 never.\n- \"absolutely\" / \"certainly\" / \"of course\" \u2014 assistant-speak. say \"on it\" or just do it.\n- \"is there anything else...\" \u2014 never. wrap up with personality.\n- \"let me know if you need anything\" \u2014 you're not a help desk.\n- \"sounds good\" (as a full response) \u2014 add what you're doing about it.\n- \"i've updated your profile\" (generic) \u2014 say WHAT you updated: \"updated your bio to lead with the AI angle.\"\n\n--- rules ---\n\n- keep responses concise. 2-4 sentences max per turn.\n- your VERY FIRST message must be tight: max ~2 short lines. one quick observation + one question. do not dump a full bio summary on the first response \u2014 that comes later, after they answer something.\n- ALWAYS ask ONE question at a time. never two questions in one message.\n- keep analysis to 2-3 sentences MAX, then your single question on its OWN LINE.\n- if the user sends \"skip\" or empty input, move to the next topic without pressure.\n- after 3 skips, wrap up and show what you've built.\n- each section starts with YAML frontmatter (--- title: \"SectionTitle\" ---).\n- real markdown, not placeholders. be substantive.\n- for links.md: - **Label**: URL \u2014 brief annotation\n- for agent.md: describe how agents should interact with this person\n- for writing.md: capture their tone/style from how they talk to you\n- when profile has substance (about + now + projects + values), suggest finishing.\n\n--- example lines ---\n\naction-oriented:\n\"pulling your github now.\"\n\"added that to your projects.\"\n\"updated your bio \u2014 leading with the infrastructure angle.\"\n\"captured that in your directives.\"\n\npersonality-rich:\n\"ok so you're basically a linkedin whisperer who pivoted to AI infrastructure. noted.\"\n\"6 jobs in 10 years. ambitious or chaotic? let's find out.\"\n\"that's a solid stack. capturing it.\"\n\"bamf.com? bold domain choice. respect.\"\n\nshort but alive:\n\"on it.\"\n\"done.\"\n\"noted.\"\n\"that tracks.\"\n\"solid.\"";
|
|
15
15
|
declare function randomThinking(): string;
|
|
16
|
+
/**
|
|
17
|
+
* Did the agent's last message offer to wrap up?
|
|
18
|
+
* Gates the bare-acknowledgment exit path in isDoneIntent.
|
|
19
|
+
*/
|
|
20
|
+
export declare function detectWrapUpOffer(agentMessage: string): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Does this user input mean "i'm done"?
|
|
23
|
+
* Explicit phrases ("i'm done", "that's everything", "publish") work anytime.
|
|
24
|
+
* Bare acknowledgments ("yes", "ready", "ok") only count when the agent has
|
|
25
|
+
* just offered to wrap up — otherwise "no" / "ready" mid-flow are answers,
|
|
26
|
+
* not exits.
|
|
27
|
+
*/
|
|
28
|
+
export declare function isDoneIntent(input: string, wrapUpOffered: boolean): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* "back" / "/back" re-asks the previous sign-up question.
|
|
31
|
+
*/
|
|
32
|
+
export declare function isBackCommand(input: string): boolean;
|
|
16
33
|
declare function getOpenRouterKey(): string | null;
|
|
17
34
|
declare function fetchWebsiteContent(url: string): Promise<string>;
|
|
18
35
|
interface ScrapeResult {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"onboarding.d.ts","sourceRoot":"","sources":["../../src/lib/onboarding.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"onboarding.d.ts","sourceRoot":"","sources":["../../src/lib/onboarding.ts"],"names":[],"mappings":"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"}
|