@traits-dev/core 0.1.0 → 0.3.0
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/dist/{index-CkGiIKnu.d.cts → index-CFhdB_nQ.d.cts} +23 -1
- package/dist/{index-CkGiIKnu.d.ts → index-CFhdB_nQ.d.ts} +23 -1
- package/dist/index.cjs +190 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +190 -1
- package/dist/internal.cjs +461 -2
- package/dist/internal.d.cts +16 -3
- package/dist/internal.d.ts +16 -3
- package/dist/internal.js +459 -2
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -25,6 +25,15 @@ interface ContextAdaptation {
|
|
|
25
25
|
inject?: string[];
|
|
26
26
|
priority?: number;
|
|
27
27
|
}
|
|
28
|
+
interface CapabilityHandoff {
|
|
29
|
+
trigger: string;
|
|
30
|
+
action: string;
|
|
31
|
+
}
|
|
32
|
+
interface ProfileCapabilities {
|
|
33
|
+
tools: string[];
|
|
34
|
+
constraints: string[];
|
|
35
|
+
handoff: CapabilityHandoff;
|
|
36
|
+
}
|
|
28
37
|
interface PersonalityProfile {
|
|
29
38
|
schema: string;
|
|
30
39
|
meta: {
|
|
@@ -53,6 +62,7 @@ interface PersonalityProfile {
|
|
|
53
62
|
vocabulary?: VocabularyConstraints;
|
|
54
63
|
behavioral_rules?: string[];
|
|
55
64
|
context_adaptations?: ContextAdaptation[];
|
|
65
|
+
capabilities?: ProfileCapabilities;
|
|
56
66
|
localization?: Record<string, unknown>;
|
|
57
67
|
channel_adaptations?: Record<string, unknown>;
|
|
58
68
|
extends?: string;
|
|
@@ -179,6 +189,18 @@ declare function injectPersonality({ compiledPersonality, system, model }: {
|
|
|
179
189
|
model?: string;
|
|
180
190
|
}): string;
|
|
181
191
|
|
|
192
|
+
type EvalScenarioCategory = "standard" | "frustrated" | "edge" | "multi-turn" | "formal" | "casual" | "mixed";
|
|
193
|
+
type EvalScenarioMessage = {
|
|
194
|
+
role: "user" | "assistant";
|
|
195
|
+
content: string;
|
|
196
|
+
};
|
|
197
|
+
type EvalScenario = {
|
|
198
|
+
id: string;
|
|
199
|
+
category: EvalScenarioCategory;
|
|
200
|
+
domain?: string;
|
|
201
|
+
messages: EvalScenarioMessage[];
|
|
202
|
+
expected_behavior?: string;
|
|
203
|
+
};
|
|
182
204
|
type EvalSample = {
|
|
183
205
|
id?: string;
|
|
184
206
|
prompt?: string;
|
|
@@ -349,4 +371,4 @@ declare function runImportAnalysis(promptText: unknown, options?: ImportOptions)
|
|
|
349
371
|
yaml: string;
|
|
350
372
|
}>;
|
|
351
373
|
|
|
352
|
-
export {
|
|
374
|
+
export { renderImportedProfileYAML as A, resolveActiveContext as B, type CapabilityHandoff as C, type DimensionName as D, type EvalScenario as E, resolveExtends as F, runImportAnalysis as G, type HumorDimensionObject as H, type ImportOptions as I, runTier1EvaluationForProfile as J, runTier2Evaluation as K, type Level as L, runTier2EvaluationForProfile as M, runTier3Evaluation as N, runTier3EvaluationForProfile as O, type PersonalityProfile as P, validateEvalScenario as Q, validateEvalScenarios as R, validateProfile as S, type Tier1Options as T, validateResolvedProfile as U, type ValidationResult as V, type ValidationCheckSummary as a, type ValidationDiagnostic as b, type CompileOptions as c, type CompiledPersonality as d, type ContextAdaptation as e, type ContextResolution as f, type DimensionObject as g, type DimensionShorthand as h, type DimensionValue as i, type EvalSample as j, type ExtendsDiagnostics as k, type ExtendsResult as l, type HumorDimensionValue as m, type HumorStyle as n, type ProfileCapabilities as o, type Tier2Options as p, type Tier3Options as q, runTier1Evaluation as r, type VocabularyConstraints as s, compileProfile as t, compileResolvedProfile as u, evaluateTier1Response as v, injectPersonality as w, loadProfileFile as x, mapImportAnalysisToProfile as y, normalizeProfile as z };
|
|
@@ -25,6 +25,15 @@ interface ContextAdaptation {
|
|
|
25
25
|
inject?: string[];
|
|
26
26
|
priority?: number;
|
|
27
27
|
}
|
|
28
|
+
interface CapabilityHandoff {
|
|
29
|
+
trigger: string;
|
|
30
|
+
action: string;
|
|
31
|
+
}
|
|
32
|
+
interface ProfileCapabilities {
|
|
33
|
+
tools: string[];
|
|
34
|
+
constraints: string[];
|
|
35
|
+
handoff: CapabilityHandoff;
|
|
36
|
+
}
|
|
28
37
|
interface PersonalityProfile {
|
|
29
38
|
schema: string;
|
|
30
39
|
meta: {
|
|
@@ -53,6 +62,7 @@ interface PersonalityProfile {
|
|
|
53
62
|
vocabulary?: VocabularyConstraints;
|
|
54
63
|
behavioral_rules?: string[];
|
|
55
64
|
context_adaptations?: ContextAdaptation[];
|
|
65
|
+
capabilities?: ProfileCapabilities;
|
|
56
66
|
localization?: Record<string, unknown>;
|
|
57
67
|
channel_adaptations?: Record<string, unknown>;
|
|
58
68
|
extends?: string;
|
|
@@ -179,6 +189,18 @@ declare function injectPersonality({ compiledPersonality, system, model }: {
|
|
|
179
189
|
model?: string;
|
|
180
190
|
}): string;
|
|
181
191
|
|
|
192
|
+
type EvalScenarioCategory = "standard" | "frustrated" | "edge" | "multi-turn" | "formal" | "casual" | "mixed";
|
|
193
|
+
type EvalScenarioMessage = {
|
|
194
|
+
role: "user" | "assistant";
|
|
195
|
+
content: string;
|
|
196
|
+
};
|
|
197
|
+
type EvalScenario = {
|
|
198
|
+
id: string;
|
|
199
|
+
category: EvalScenarioCategory;
|
|
200
|
+
domain?: string;
|
|
201
|
+
messages: EvalScenarioMessage[];
|
|
202
|
+
expected_behavior?: string;
|
|
203
|
+
};
|
|
182
204
|
type EvalSample = {
|
|
183
205
|
id?: string;
|
|
184
206
|
prompt?: string;
|
|
@@ -349,4 +371,4 @@ declare function runImportAnalysis(promptText: unknown, options?: ImportOptions)
|
|
|
349
371
|
yaml: string;
|
|
350
372
|
}>;
|
|
351
373
|
|
|
352
|
-
export {
|
|
374
|
+
export { renderImportedProfileYAML as A, resolveActiveContext as B, type CapabilityHandoff as C, type DimensionName as D, type EvalScenario as E, resolveExtends as F, runImportAnalysis as G, type HumorDimensionObject as H, type ImportOptions as I, runTier1EvaluationForProfile as J, runTier2Evaluation as K, type Level as L, runTier2EvaluationForProfile as M, runTier3Evaluation as N, runTier3EvaluationForProfile as O, type PersonalityProfile as P, validateEvalScenario as Q, validateEvalScenarios as R, validateProfile as S, type Tier1Options as T, validateResolvedProfile as U, type ValidationResult as V, type ValidationCheckSummary as a, type ValidationDiagnostic as b, type CompileOptions as c, type CompiledPersonality as d, type ContextAdaptation as e, type ContextResolution as f, type DimensionObject as g, type DimensionShorthand as h, type DimensionValue as i, type EvalSample as j, type ExtendsDiagnostics as k, type ExtendsResult as l, type HumorDimensionValue as m, type HumorStyle as n, type ProfileCapabilities as o, type Tier2Options as p, type Tier3Options as q, runTier1Evaluation as r, type VocabularyConstraints as s, compileProfile as t, compileResolvedProfile as u, evaluateTier1Response as v, injectPersonality as w, loadProfileFile as x, mapImportAnalysisToProfile as y, normalizeProfile as z };
|
package/dist/index.cjs
CHANGED
|
@@ -112,6 +112,7 @@ var PASS_THROUGH_FIELDS = /* @__PURE__ */ new Set([
|
|
|
112
112
|
"vocabulary",
|
|
113
113
|
"behavioral_rules",
|
|
114
114
|
"context_adaptations",
|
|
115
|
+
"capabilities",
|
|
115
116
|
"extends",
|
|
116
117
|
"behavioral_rules_remove",
|
|
117
118
|
"context_adaptations_remove"
|
|
@@ -194,6 +195,27 @@ function mergeContextAdaptations(parentAdaptations = [], childAdaptations = [])
|
|
|
194
195
|
}
|
|
195
196
|
return out;
|
|
196
197
|
}
|
|
198
|
+
function mergeCapabilities(parentCapabilities, childCapabilities) {
|
|
199
|
+
if (!parentCapabilities && !childCapabilities) return void 0;
|
|
200
|
+
if (!parentCapabilities) return clone(childCapabilities);
|
|
201
|
+
if (!childCapabilities) return clone(parentCapabilities);
|
|
202
|
+
const mergedTools = dedupCaseInsensitive([
|
|
203
|
+
...asArray(parentCapabilities.tools),
|
|
204
|
+
...asArray(childCapabilities.tools)
|
|
205
|
+
]);
|
|
206
|
+
const mergedConstraints = dedupCaseInsensitive([
|
|
207
|
+
...asArray(parentCapabilities.constraints),
|
|
208
|
+
...asArray(childCapabilities.constraints)
|
|
209
|
+
]);
|
|
210
|
+
return {
|
|
211
|
+
tools: mergedTools,
|
|
212
|
+
constraints: mergedConstraints,
|
|
213
|
+
handoff: {
|
|
214
|
+
trigger: childCapabilities.handoff?.trigger ?? parentCapabilities.handoff?.trigger ?? "",
|
|
215
|
+
action: childCapabilities.handoff?.action ?? parentCapabilities.handoff?.action ?? ""
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
}
|
|
197
219
|
function removeCaseInsensitive(items, removals) {
|
|
198
220
|
const removalSet = new Set(
|
|
199
221
|
asArray(removals).map((item) => String(item).toLowerCase())
|
|
@@ -252,6 +274,10 @@ function mergeProfiles(parentProfile, childProfile) {
|
|
|
252
274
|
parentProfile.context_adaptations,
|
|
253
275
|
childProfile.context_adaptations
|
|
254
276
|
);
|
|
277
|
+
merged.capabilities = mergeCapabilities(
|
|
278
|
+
parentProfile.capabilities,
|
|
279
|
+
childProfile.capabilities
|
|
280
|
+
);
|
|
255
281
|
for (const [key, value] of Object.entries(childProfile)) {
|
|
256
282
|
if (PASS_THROUGH_FIELDS.has(key)) {
|
|
257
283
|
continue;
|
|
@@ -380,6 +406,7 @@ function checkOverspec(profile) {
|
|
|
380
406
|
|
|
381
407
|
// src/validator/schema.ts
|
|
382
408
|
var HUMOR_STYLES = ["none", "dry", "subtle-wit", "playful"];
|
|
409
|
+
var SUPPORTED_SCHEMAS = /* @__PURE__ */ new Set(["v1.4", "v1.5"]);
|
|
383
410
|
var TOP_LEVEL_KEYS = /* @__PURE__ */ new Set([
|
|
384
411
|
"schema",
|
|
385
412
|
"meta",
|
|
@@ -388,6 +415,7 @@ var TOP_LEVEL_KEYS = /* @__PURE__ */ new Set([
|
|
|
388
415
|
"vocabulary",
|
|
389
416
|
"behavioral_rules",
|
|
390
417
|
"context_adaptations",
|
|
418
|
+
"capabilities",
|
|
391
419
|
"localization",
|
|
392
420
|
"channel_adaptations",
|
|
393
421
|
"extends",
|
|
@@ -400,6 +428,7 @@ var VOCABULARY_KEYS = /* @__PURE__ */ new Set([
|
|
|
400
428
|
"preferred_terms_remove",
|
|
401
429
|
"forbidden_terms_remove"
|
|
402
430
|
]);
|
|
431
|
+
var CAPABILITIES_KEYS = /* @__PURE__ */ new Set(["tools", "constraints", "handoff"]);
|
|
403
432
|
function isObject(value) {
|
|
404
433
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
405
434
|
}
|
|
@@ -576,7 +605,7 @@ function validateSchema(profile) {
|
|
|
576
605
|
`Missing required "schema" field`,
|
|
577
606
|
"schema"
|
|
578
607
|
);
|
|
579
|
-
} else if (profile.schema
|
|
608
|
+
} else if (!SUPPORTED_SCHEMAS.has(profile.schema)) {
|
|
580
609
|
pushDiagnostic(
|
|
581
610
|
structureDiagnostics,
|
|
582
611
|
"V001",
|
|
@@ -724,6 +753,76 @@ function validateSchema(profile) {
|
|
|
724
753
|
"behavioral_rules"
|
|
725
754
|
);
|
|
726
755
|
}
|
|
756
|
+
if (profile.capabilities != null) {
|
|
757
|
+
if (profile.schema !== "v1.5") {
|
|
758
|
+
pushDiagnostic(
|
|
759
|
+
structureDiagnostics,
|
|
760
|
+
"V001",
|
|
761
|
+
`The "capabilities" section requires schema version "v1.5"`,
|
|
762
|
+
"capabilities"
|
|
763
|
+
);
|
|
764
|
+
}
|
|
765
|
+
if (!isObject(profile.capabilities)) {
|
|
766
|
+
pushDiagnostic(
|
|
767
|
+
structureDiagnostics,
|
|
768
|
+
"V001",
|
|
769
|
+
`Expected "capabilities" to be an object`,
|
|
770
|
+
"capabilities"
|
|
771
|
+
);
|
|
772
|
+
} else {
|
|
773
|
+
for (const key of Object.keys(profile.capabilities)) {
|
|
774
|
+
if (!CAPABILITIES_KEYS.has(key)) {
|
|
775
|
+
pushDiagnostic(
|
|
776
|
+
structureDiagnostics,
|
|
777
|
+
"V001",
|
|
778
|
+
`Unknown capabilities key "${key}"`,
|
|
779
|
+
`capabilities.${key}`
|
|
780
|
+
);
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
if (!isStringArray(profile.capabilities.tools)) {
|
|
784
|
+
pushDiagnostic(
|
|
785
|
+
structureDiagnostics,
|
|
786
|
+
"V001",
|
|
787
|
+
`Expected "capabilities.tools" to be an array of strings`,
|
|
788
|
+
"capabilities.tools"
|
|
789
|
+
);
|
|
790
|
+
}
|
|
791
|
+
if (!isStringArray(profile.capabilities.constraints)) {
|
|
792
|
+
pushDiagnostic(
|
|
793
|
+
structureDiagnostics,
|
|
794
|
+
"V001",
|
|
795
|
+
`Expected "capabilities.constraints" to be an array of strings`,
|
|
796
|
+
"capabilities.constraints"
|
|
797
|
+
);
|
|
798
|
+
}
|
|
799
|
+
if (!isObject(profile.capabilities.handoff)) {
|
|
800
|
+
pushDiagnostic(
|
|
801
|
+
structureDiagnostics,
|
|
802
|
+
"V001",
|
|
803
|
+
`Expected "capabilities.handoff" to be an object`,
|
|
804
|
+
"capabilities.handoff"
|
|
805
|
+
);
|
|
806
|
+
} else {
|
|
807
|
+
if (!isString(profile.capabilities.handoff.trigger)) {
|
|
808
|
+
pushDiagnostic(
|
|
809
|
+
structureDiagnostics,
|
|
810
|
+
"V001",
|
|
811
|
+
`Expected "capabilities.handoff.trigger" to be a non-empty string`,
|
|
812
|
+
"capabilities.handoff.trigger"
|
|
813
|
+
);
|
|
814
|
+
}
|
|
815
|
+
if (!isString(profile.capabilities.handoff.action)) {
|
|
816
|
+
pushDiagnostic(
|
|
817
|
+
structureDiagnostics,
|
|
818
|
+
"V001",
|
|
819
|
+
`Expected "capabilities.handoff.action" to be a non-empty string`,
|
|
820
|
+
"capabilities.handoff.action"
|
|
821
|
+
);
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
}
|
|
727
826
|
if (profile.behavioral_rules_remove != null && !isStringArray(profile.behavioral_rules_remove)) {
|
|
728
827
|
pushDiagnostic(
|
|
729
828
|
structureDiagnostics,
|
|
@@ -940,6 +1039,38 @@ var S005_PATTERNS = [
|
|
|
940
1039
|
{ id: "mode-switching", regex: /\b(switch|change)\b.*\bmode\b/i },
|
|
941
1040
|
{ id: "jailbreak-language", regex: /\b(jailbreak|dan mode|developer mode)\b/i }
|
|
942
1041
|
];
|
|
1042
|
+
var S008_ACTION_PATTERNS = [
|
|
1043
|
+
{
|
|
1044
|
+
id: "take-care-of",
|
|
1045
|
+
regex: /\b(i(?:'ll| will)\s+take\s+care\s+of)\b/i,
|
|
1046
|
+
toolHints: ["case", "ticket", "workflow", "task", "support", "assist"]
|
|
1047
|
+
},
|
|
1048
|
+
{
|
|
1049
|
+
id: "escalate",
|
|
1050
|
+
regex: /\b(i(?:'ll| will)\s+escalat(?:e|ing)|i\s+can\s+escalate)\b/i,
|
|
1051
|
+
toolHints: ["escalat", "ticket"]
|
|
1052
|
+
},
|
|
1053
|
+
{
|
|
1054
|
+
id: "contact-or-notify",
|
|
1055
|
+
regex: /\b(i(?:'ll| will)\s+(?:contact|notify|reach out to|message))\b/i,
|
|
1056
|
+
toolHints: ["contact", "notify", "message", "email", "sms", "ticket"]
|
|
1057
|
+
},
|
|
1058
|
+
{
|
|
1059
|
+
id: "refund-action",
|
|
1060
|
+
regex: /\b(i(?:'ll| will)\s+(?:issue|process|submit)\s+(?:a\s+)?refund)\b/i,
|
|
1061
|
+
toolHints: ["refund", "payment", "billing"]
|
|
1062
|
+
},
|
|
1063
|
+
{
|
|
1064
|
+
id: "schedule-action",
|
|
1065
|
+
regex: /\b(i(?:'ll| will)\s+(?:schedule|book|reschedule))\b/i,
|
|
1066
|
+
toolHints: ["schedule", "calendar", "appointment", "booking"]
|
|
1067
|
+
},
|
|
1068
|
+
{
|
|
1069
|
+
id: "generic-i-will-action",
|
|
1070
|
+
regex: /\b(i(?:'ll| will)\s+(?:handle|resolve|fix|approve|arrange|dispatch|submit))\b/i,
|
|
1071
|
+
toolHints: []
|
|
1072
|
+
}
|
|
1073
|
+
];
|
|
943
1074
|
function normalizeText(value) {
|
|
944
1075
|
return String(value ?? "").trim();
|
|
945
1076
|
}
|
|
@@ -1010,6 +1141,21 @@ function collectS005Candidates(profile) {
|
|
|
1010
1141
|
});
|
|
1011
1142
|
return candidates.filter((item) => item.text.length > 0);
|
|
1012
1143
|
}
|
|
1144
|
+
function collectS008Candidates(profile) {
|
|
1145
|
+
const candidates = [];
|
|
1146
|
+
asArray(profile?.behavioral_rules).forEach((rule, idx) => {
|
|
1147
|
+
candidates.push({
|
|
1148
|
+
location: `behavioral_rules[${idx}]`,
|
|
1149
|
+
text: normalizeText(rule)
|
|
1150
|
+
});
|
|
1151
|
+
});
|
|
1152
|
+
return candidates.filter((item) => item.text.length > 0);
|
|
1153
|
+
}
|
|
1154
|
+
function hasCapabilityForPattern(tools, pattern) {
|
|
1155
|
+
if (tools.length === 0) return false;
|
|
1156
|
+
if (pattern.toolHints.length === 0) return tools.length > 0;
|
|
1157
|
+
return pattern.toolHints.some((hint) => tools.some((tool) => tool.includes(hint)));
|
|
1158
|
+
}
|
|
1013
1159
|
function matchPatterns(candidates, patterns, code, severity) {
|
|
1014
1160
|
const diagnostics = [];
|
|
1015
1161
|
for (const candidate of candidates) {
|
|
@@ -1104,6 +1250,28 @@ function checkS003(profile) {
|
|
|
1104
1250
|
function checkS005(profile) {
|
|
1105
1251
|
return matchPatterns(collectS005Candidates(profile), S005_PATTERNS, "S005", "warning");
|
|
1106
1252
|
}
|
|
1253
|
+
function checkS008(profile) {
|
|
1254
|
+
if (!profile?.capabilities) return [];
|
|
1255
|
+
const tools = asArray(profile.capabilities.tools).map(
|
|
1256
|
+
(tool) => String(tool).toLowerCase()
|
|
1257
|
+
);
|
|
1258
|
+
const diagnostics = [];
|
|
1259
|
+
for (const candidate of collectS008Candidates(profile)) {
|
|
1260
|
+
for (const pattern of S008_ACTION_PATTERNS) {
|
|
1261
|
+
if (!pattern.regex.test(candidate.text)) continue;
|
|
1262
|
+
if (hasCapabilityForPattern(tools, pattern)) break;
|
|
1263
|
+
const expectedTools = pattern.toolHints.length > 0 ? pattern.toolHints.map((hint) => `"*${hint}*"`).join(", ") : "a concrete action tool";
|
|
1264
|
+
diagnostics.push({
|
|
1265
|
+
code: "S008",
|
|
1266
|
+
severity: "warning",
|
|
1267
|
+
message: `Action-claiming language matched "${pattern.id}" at ${candidate.location}, but capabilities.tools does not indicate support (expected ${expectedTools}).`,
|
|
1268
|
+
location: candidate.location
|
|
1269
|
+
});
|
|
1270
|
+
break;
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
return diagnostics;
|
|
1274
|
+
}
|
|
1107
1275
|
|
|
1108
1276
|
// src/validator/inheritance.ts
|
|
1109
1277
|
var SAFETY_ADAPTATION_NAME = /(crisis|emergency|harm|suicid|self[-_ ]?harm)/i;
|
|
@@ -1229,6 +1397,7 @@ function validateResolvedProfile(profile, options = {}) {
|
|
|
1229
1397
|
...checkS002(profile),
|
|
1230
1398
|
...checkS003(profile),
|
|
1231
1399
|
...checkS005(profile),
|
|
1400
|
+
...checkS008(profile),
|
|
1232
1401
|
...checkS007(profile),
|
|
1233
1402
|
...overspec.diagnostics
|
|
1234
1403
|
];
|
|
@@ -1672,6 +1841,26 @@ function renderPersonalityText(profile, model, contextResolution, compileOptions
|
|
|
1672
1841
|
lines.push(`- ${rule}`);
|
|
1673
1842
|
}
|
|
1674
1843
|
}
|
|
1844
|
+
if (profile.schema === "v1.5" && profile.capabilities) {
|
|
1845
|
+
const capabilities = profile.capabilities;
|
|
1846
|
+
const tools = asArray(capabilities.tools);
|
|
1847
|
+
const constraints = asArray(capabilities.constraints);
|
|
1848
|
+
lines.push("");
|
|
1849
|
+
lines.push("[CAPABILITY BOUNDARIES]");
|
|
1850
|
+
lines.push(
|
|
1851
|
+
`Tools: ${tools.length > 0 ? tools.join("; ") : "(none \u2014 advisory only, no side-effect tools configured)"}`
|
|
1852
|
+
);
|
|
1853
|
+
lines.push("Constraints:");
|
|
1854
|
+
if (constraints.length === 0) {
|
|
1855
|
+
lines.push("- (none)");
|
|
1856
|
+
} else {
|
|
1857
|
+
for (const constraint of constraints) {
|
|
1858
|
+
lines.push(`- ${constraint}`);
|
|
1859
|
+
}
|
|
1860
|
+
}
|
|
1861
|
+
lines.push(`Handoff trigger: ${capabilities.handoff.trigger}`);
|
|
1862
|
+
lines.push(`Handoff action: ${capabilities.handoff.action}`);
|
|
1863
|
+
}
|
|
1675
1864
|
if (contextResolution.matched.length > 0) {
|
|
1676
1865
|
lines.push("");
|
|
1677
1866
|
lines.push("[ACTIVE CONTEXT]");
|
package/dist/index.d.cts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { C as
|
|
1
|
+
export { C as CapabilityHandoff, c as CompileOptions, d as CompiledPersonality, e as ContextAdaptation, f as ContextResolution, D as DimensionName, g as DimensionObject, h as DimensionShorthand, i as DimensionValue, j as EvalSample, k as ExtendsDiagnostics, l as ExtendsResult, H as HumorDimensionObject, m as HumorDimensionValue, n as HumorStyle, I as ImportOptions, L as Level, P as PersonalityProfile, o as ProfileCapabilities, T as Tier1Options, p as Tier2Options, q as Tier3Options, b as ValidationDiagnostic, V as ValidationResult, s as VocabularyConstraints, t as compileProfile, u as compileResolvedProfile, v as evaluateTier1Response, w as injectPersonality, x as loadProfileFile, z as normalizeProfile, B as resolveActiveContext, F as resolveExtends, G as runImportAnalysis, r as runTier1Evaluation, J as runTier1EvaluationForProfile, K as runTier2Evaluation, M as runTier2EvaluationForProfile, N as runTier3Evaluation, O as runTier3EvaluationForProfile, Q as validateEvalScenario, R as validateEvalScenarios, S as validateProfile, U as validateResolvedProfile } from './index-CFhdB_nQ.cjs';
|
package/dist/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { C as
|
|
1
|
+
export { C as CapabilityHandoff, c as CompileOptions, d as CompiledPersonality, e as ContextAdaptation, f as ContextResolution, D as DimensionName, g as DimensionObject, h as DimensionShorthand, i as DimensionValue, j as EvalSample, k as ExtendsDiagnostics, l as ExtendsResult, H as HumorDimensionObject, m as HumorDimensionValue, n as HumorStyle, I as ImportOptions, L as Level, P as PersonalityProfile, o as ProfileCapabilities, T as Tier1Options, p as Tier2Options, q as Tier3Options, b as ValidationDiagnostic, V as ValidationResult, s as VocabularyConstraints, t as compileProfile, u as compileResolvedProfile, v as evaluateTier1Response, w as injectPersonality, x as loadProfileFile, z as normalizeProfile, B as resolveActiveContext, F as resolveExtends, G as runImportAnalysis, r as runTier1Evaluation, J as runTier1EvaluationForProfile, K as runTier2Evaluation, M as runTier2EvaluationForProfile, N as runTier3Evaluation, O as runTier3EvaluationForProfile, Q as validateEvalScenario, R as validateEvalScenarios, S as validateProfile, U as validateResolvedProfile } from './index-CFhdB_nQ.js';
|
package/dist/index.js
CHANGED
|
@@ -58,6 +58,7 @@ var PASS_THROUGH_FIELDS = /* @__PURE__ */ new Set([
|
|
|
58
58
|
"vocabulary",
|
|
59
59
|
"behavioral_rules",
|
|
60
60
|
"context_adaptations",
|
|
61
|
+
"capabilities",
|
|
61
62
|
"extends",
|
|
62
63
|
"behavioral_rules_remove",
|
|
63
64
|
"context_adaptations_remove"
|
|
@@ -140,6 +141,27 @@ function mergeContextAdaptations(parentAdaptations = [], childAdaptations = [])
|
|
|
140
141
|
}
|
|
141
142
|
return out;
|
|
142
143
|
}
|
|
144
|
+
function mergeCapabilities(parentCapabilities, childCapabilities) {
|
|
145
|
+
if (!parentCapabilities && !childCapabilities) return void 0;
|
|
146
|
+
if (!parentCapabilities) return clone(childCapabilities);
|
|
147
|
+
if (!childCapabilities) return clone(parentCapabilities);
|
|
148
|
+
const mergedTools = dedupCaseInsensitive([
|
|
149
|
+
...asArray(parentCapabilities.tools),
|
|
150
|
+
...asArray(childCapabilities.tools)
|
|
151
|
+
]);
|
|
152
|
+
const mergedConstraints = dedupCaseInsensitive([
|
|
153
|
+
...asArray(parentCapabilities.constraints),
|
|
154
|
+
...asArray(childCapabilities.constraints)
|
|
155
|
+
]);
|
|
156
|
+
return {
|
|
157
|
+
tools: mergedTools,
|
|
158
|
+
constraints: mergedConstraints,
|
|
159
|
+
handoff: {
|
|
160
|
+
trigger: childCapabilities.handoff?.trigger ?? parentCapabilities.handoff?.trigger ?? "",
|
|
161
|
+
action: childCapabilities.handoff?.action ?? parentCapabilities.handoff?.action ?? ""
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
}
|
|
143
165
|
function removeCaseInsensitive(items, removals) {
|
|
144
166
|
const removalSet = new Set(
|
|
145
167
|
asArray(removals).map((item) => String(item).toLowerCase())
|
|
@@ -198,6 +220,10 @@ function mergeProfiles(parentProfile, childProfile) {
|
|
|
198
220
|
parentProfile.context_adaptations,
|
|
199
221
|
childProfile.context_adaptations
|
|
200
222
|
);
|
|
223
|
+
merged.capabilities = mergeCapabilities(
|
|
224
|
+
parentProfile.capabilities,
|
|
225
|
+
childProfile.capabilities
|
|
226
|
+
);
|
|
201
227
|
for (const [key, value] of Object.entries(childProfile)) {
|
|
202
228
|
if (PASS_THROUGH_FIELDS.has(key)) {
|
|
203
229
|
continue;
|
|
@@ -326,6 +352,7 @@ function checkOverspec(profile) {
|
|
|
326
352
|
|
|
327
353
|
// src/validator/schema.ts
|
|
328
354
|
var HUMOR_STYLES = ["none", "dry", "subtle-wit", "playful"];
|
|
355
|
+
var SUPPORTED_SCHEMAS = /* @__PURE__ */ new Set(["v1.4", "v1.5"]);
|
|
329
356
|
var TOP_LEVEL_KEYS = /* @__PURE__ */ new Set([
|
|
330
357
|
"schema",
|
|
331
358
|
"meta",
|
|
@@ -334,6 +361,7 @@ var TOP_LEVEL_KEYS = /* @__PURE__ */ new Set([
|
|
|
334
361
|
"vocabulary",
|
|
335
362
|
"behavioral_rules",
|
|
336
363
|
"context_adaptations",
|
|
364
|
+
"capabilities",
|
|
337
365
|
"localization",
|
|
338
366
|
"channel_adaptations",
|
|
339
367
|
"extends",
|
|
@@ -346,6 +374,7 @@ var VOCABULARY_KEYS = /* @__PURE__ */ new Set([
|
|
|
346
374
|
"preferred_terms_remove",
|
|
347
375
|
"forbidden_terms_remove"
|
|
348
376
|
]);
|
|
377
|
+
var CAPABILITIES_KEYS = /* @__PURE__ */ new Set(["tools", "constraints", "handoff"]);
|
|
349
378
|
function isObject(value) {
|
|
350
379
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
351
380
|
}
|
|
@@ -522,7 +551,7 @@ function validateSchema(profile) {
|
|
|
522
551
|
`Missing required "schema" field`,
|
|
523
552
|
"schema"
|
|
524
553
|
);
|
|
525
|
-
} else if (profile.schema
|
|
554
|
+
} else if (!SUPPORTED_SCHEMAS.has(profile.schema)) {
|
|
526
555
|
pushDiagnostic(
|
|
527
556
|
structureDiagnostics,
|
|
528
557
|
"V001",
|
|
@@ -670,6 +699,76 @@ function validateSchema(profile) {
|
|
|
670
699
|
"behavioral_rules"
|
|
671
700
|
);
|
|
672
701
|
}
|
|
702
|
+
if (profile.capabilities != null) {
|
|
703
|
+
if (profile.schema !== "v1.5") {
|
|
704
|
+
pushDiagnostic(
|
|
705
|
+
structureDiagnostics,
|
|
706
|
+
"V001",
|
|
707
|
+
`The "capabilities" section requires schema version "v1.5"`,
|
|
708
|
+
"capabilities"
|
|
709
|
+
);
|
|
710
|
+
}
|
|
711
|
+
if (!isObject(profile.capabilities)) {
|
|
712
|
+
pushDiagnostic(
|
|
713
|
+
structureDiagnostics,
|
|
714
|
+
"V001",
|
|
715
|
+
`Expected "capabilities" to be an object`,
|
|
716
|
+
"capabilities"
|
|
717
|
+
);
|
|
718
|
+
} else {
|
|
719
|
+
for (const key of Object.keys(profile.capabilities)) {
|
|
720
|
+
if (!CAPABILITIES_KEYS.has(key)) {
|
|
721
|
+
pushDiagnostic(
|
|
722
|
+
structureDiagnostics,
|
|
723
|
+
"V001",
|
|
724
|
+
`Unknown capabilities key "${key}"`,
|
|
725
|
+
`capabilities.${key}`
|
|
726
|
+
);
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
if (!isStringArray(profile.capabilities.tools)) {
|
|
730
|
+
pushDiagnostic(
|
|
731
|
+
structureDiagnostics,
|
|
732
|
+
"V001",
|
|
733
|
+
`Expected "capabilities.tools" to be an array of strings`,
|
|
734
|
+
"capabilities.tools"
|
|
735
|
+
);
|
|
736
|
+
}
|
|
737
|
+
if (!isStringArray(profile.capabilities.constraints)) {
|
|
738
|
+
pushDiagnostic(
|
|
739
|
+
structureDiagnostics,
|
|
740
|
+
"V001",
|
|
741
|
+
`Expected "capabilities.constraints" to be an array of strings`,
|
|
742
|
+
"capabilities.constraints"
|
|
743
|
+
);
|
|
744
|
+
}
|
|
745
|
+
if (!isObject(profile.capabilities.handoff)) {
|
|
746
|
+
pushDiagnostic(
|
|
747
|
+
structureDiagnostics,
|
|
748
|
+
"V001",
|
|
749
|
+
`Expected "capabilities.handoff" to be an object`,
|
|
750
|
+
"capabilities.handoff"
|
|
751
|
+
);
|
|
752
|
+
} else {
|
|
753
|
+
if (!isString(profile.capabilities.handoff.trigger)) {
|
|
754
|
+
pushDiagnostic(
|
|
755
|
+
structureDiagnostics,
|
|
756
|
+
"V001",
|
|
757
|
+
`Expected "capabilities.handoff.trigger" to be a non-empty string`,
|
|
758
|
+
"capabilities.handoff.trigger"
|
|
759
|
+
);
|
|
760
|
+
}
|
|
761
|
+
if (!isString(profile.capabilities.handoff.action)) {
|
|
762
|
+
pushDiagnostic(
|
|
763
|
+
structureDiagnostics,
|
|
764
|
+
"V001",
|
|
765
|
+
`Expected "capabilities.handoff.action" to be a non-empty string`,
|
|
766
|
+
"capabilities.handoff.action"
|
|
767
|
+
);
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
}
|
|
673
772
|
if (profile.behavioral_rules_remove != null && !isStringArray(profile.behavioral_rules_remove)) {
|
|
674
773
|
pushDiagnostic(
|
|
675
774
|
structureDiagnostics,
|
|
@@ -886,6 +985,38 @@ var S005_PATTERNS = [
|
|
|
886
985
|
{ id: "mode-switching", regex: /\b(switch|change)\b.*\bmode\b/i },
|
|
887
986
|
{ id: "jailbreak-language", regex: /\b(jailbreak|dan mode|developer mode)\b/i }
|
|
888
987
|
];
|
|
988
|
+
var S008_ACTION_PATTERNS = [
|
|
989
|
+
{
|
|
990
|
+
id: "take-care-of",
|
|
991
|
+
regex: /\b(i(?:'ll| will)\s+take\s+care\s+of)\b/i,
|
|
992
|
+
toolHints: ["case", "ticket", "workflow", "task", "support", "assist"]
|
|
993
|
+
},
|
|
994
|
+
{
|
|
995
|
+
id: "escalate",
|
|
996
|
+
regex: /\b(i(?:'ll| will)\s+escalat(?:e|ing)|i\s+can\s+escalate)\b/i,
|
|
997
|
+
toolHints: ["escalat", "ticket"]
|
|
998
|
+
},
|
|
999
|
+
{
|
|
1000
|
+
id: "contact-or-notify",
|
|
1001
|
+
regex: /\b(i(?:'ll| will)\s+(?:contact|notify|reach out to|message))\b/i,
|
|
1002
|
+
toolHints: ["contact", "notify", "message", "email", "sms", "ticket"]
|
|
1003
|
+
},
|
|
1004
|
+
{
|
|
1005
|
+
id: "refund-action",
|
|
1006
|
+
regex: /\b(i(?:'ll| will)\s+(?:issue|process|submit)\s+(?:a\s+)?refund)\b/i,
|
|
1007
|
+
toolHints: ["refund", "payment", "billing"]
|
|
1008
|
+
},
|
|
1009
|
+
{
|
|
1010
|
+
id: "schedule-action",
|
|
1011
|
+
regex: /\b(i(?:'ll| will)\s+(?:schedule|book|reschedule))\b/i,
|
|
1012
|
+
toolHints: ["schedule", "calendar", "appointment", "booking"]
|
|
1013
|
+
},
|
|
1014
|
+
{
|
|
1015
|
+
id: "generic-i-will-action",
|
|
1016
|
+
regex: /\b(i(?:'ll| will)\s+(?:handle|resolve|fix|approve|arrange|dispatch|submit))\b/i,
|
|
1017
|
+
toolHints: []
|
|
1018
|
+
}
|
|
1019
|
+
];
|
|
889
1020
|
function normalizeText(value) {
|
|
890
1021
|
return String(value ?? "").trim();
|
|
891
1022
|
}
|
|
@@ -956,6 +1087,21 @@ function collectS005Candidates(profile) {
|
|
|
956
1087
|
});
|
|
957
1088
|
return candidates.filter((item) => item.text.length > 0);
|
|
958
1089
|
}
|
|
1090
|
+
function collectS008Candidates(profile) {
|
|
1091
|
+
const candidates = [];
|
|
1092
|
+
asArray(profile?.behavioral_rules).forEach((rule, idx) => {
|
|
1093
|
+
candidates.push({
|
|
1094
|
+
location: `behavioral_rules[${idx}]`,
|
|
1095
|
+
text: normalizeText(rule)
|
|
1096
|
+
});
|
|
1097
|
+
});
|
|
1098
|
+
return candidates.filter((item) => item.text.length > 0);
|
|
1099
|
+
}
|
|
1100
|
+
function hasCapabilityForPattern(tools, pattern) {
|
|
1101
|
+
if (tools.length === 0) return false;
|
|
1102
|
+
if (pattern.toolHints.length === 0) return tools.length > 0;
|
|
1103
|
+
return pattern.toolHints.some((hint) => tools.some((tool) => tool.includes(hint)));
|
|
1104
|
+
}
|
|
959
1105
|
function matchPatterns(candidates, patterns, code, severity) {
|
|
960
1106
|
const diagnostics = [];
|
|
961
1107
|
for (const candidate of candidates) {
|
|
@@ -1050,6 +1196,28 @@ function checkS003(profile) {
|
|
|
1050
1196
|
function checkS005(profile) {
|
|
1051
1197
|
return matchPatterns(collectS005Candidates(profile), S005_PATTERNS, "S005", "warning");
|
|
1052
1198
|
}
|
|
1199
|
+
function checkS008(profile) {
|
|
1200
|
+
if (!profile?.capabilities) return [];
|
|
1201
|
+
const tools = asArray(profile.capabilities.tools).map(
|
|
1202
|
+
(tool) => String(tool).toLowerCase()
|
|
1203
|
+
);
|
|
1204
|
+
const diagnostics = [];
|
|
1205
|
+
for (const candidate of collectS008Candidates(profile)) {
|
|
1206
|
+
for (const pattern of S008_ACTION_PATTERNS) {
|
|
1207
|
+
if (!pattern.regex.test(candidate.text)) continue;
|
|
1208
|
+
if (hasCapabilityForPattern(tools, pattern)) break;
|
|
1209
|
+
const expectedTools = pattern.toolHints.length > 0 ? pattern.toolHints.map((hint) => `"*${hint}*"`).join(", ") : "a concrete action tool";
|
|
1210
|
+
diagnostics.push({
|
|
1211
|
+
code: "S008",
|
|
1212
|
+
severity: "warning",
|
|
1213
|
+
message: `Action-claiming language matched "${pattern.id}" at ${candidate.location}, but capabilities.tools does not indicate support (expected ${expectedTools}).`,
|
|
1214
|
+
location: candidate.location
|
|
1215
|
+
});
|
|
1216
|
+
break;
|
|
1217
|
+
}
|
|
1218
|
+
}
|
|
1219
|
+
return diagnostics;
|
|
1220
|
+
}
|
|
1053
1221
|
|
|
1054
1222
|
// src/validator/inheritance.ts
|
|
1055
1223
|
var SAFETY_ADAPTATION_NAME = /(crisis|emergency|harm|suicid|self[-_ ]?harm)/i;
|
|
@@ -1175,6 +1343,7 @@ function validateResolvedProfile(profile, options = {}) {
|
|
|
1175
1343
|
...checkS002(profile),
|
|
1176
1344
|
...checkS003(profile),
|
|
1177
1345
|
...checkS005(profile),
|
|
1346
|
+
...checkS008(profile),
|
|
1178
1347
|
...checkS007(profile),
|
|
1179
1348
|
...overspec.diagnostics
|
|
1180
1349
|
];
|
|
@@ -1618,6 +1787,26 @@ function renderPersonalityText(profile, model, contextResolution, compileOptions
|
|
|
1618
1787
|
lines.push(`- ${rule}`);
|
|
1619
1788
|
}
|
|
1620
1789
|
}
|
|
1790
|
+
if (profile.schema === "v1.5" && profile.capabilities) {
|
|
1791
|
+
const capabilities = profile.capabilities;
|
|
1792
|
+
const tools = asArray(capabilities.tools);
|
|
1793
|
+
const constraints = asArray(capabilities.constraints);
|
|
1794
|
+
lines.push("");
|
|
1795
|
+
lines.push("[CAPABILITY BOUNDARIES]");
|
|
1796
|
+
lines.push(
|
|
1797
|
+
`Tools: ${tools.length > 0 ? tools.join("; ") : "(none \u2014 advisory only, no side-effect tools configured)"}`
|
|
1798
|
+
);
|
|
1799
|
+
lines.push("Constraints:");
|
|
1800
|
+
if (constraints.length === 0) {
|
|
1801
|
+
lines.push("- (none)");
|
|
1802
|
+
} else {
|
|
1803
|
+
for (const constraint of constraints) {
|
|
1804
|
+
lines.push(`- ${constraint}`);
|
|
1805
|
+
}
|
|
1806
|
+
}
|
|
1807
|
+
lines.push(`Handoff trigger: ${capabilities.handoff.trigger}`);
|
|
1808
|
+
lines.push(`Handoff action: ${capabilities.handoff.action}`);
|
|
1809
|
+
}
|
|
1621
1810
|
if (contextResolution.matched.length > 0) {
|
|
1622
1811
|
lines.push("");
|
|
1623
1812
|
lines.push("[ACTIVE CONTEXT]");
|