martin-loop 0.1.5 → 1.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/CODE_OF_CONDUCT.md +32 -0
- package/LICENSE +21 -21
- package/README.md +307 -398
- package/demo/seeded-workspace/README.md +35 -35
- package/demo/seeded-workspace/TASKS.md +29 -29
- package/demo/seeded-workspace/martin.config.yaml +11 -11
- package/demo/seeded-workspace/package.json +8 -8
- package/demo/seeded-workspace/src/invoice-summary.js +11 -11
- package/demo/seeded-workspace/test/invoice-summary.test.js +20 -20
- package/dist/bin/martin-loop.js +0 -0
- package/dist/vendor/adapters/counter.d.ts +1 -0
- package/dist/vendor/adapters/counter.js +4 -0
- package/dist/vendor/adapters/git-baseline.d.ts +50 -0
- package/dist/vendor/adapters/git-baseline.js +233 -0
- package/dist/vendor/adapters/openrouter-adapter.d.ts +15 -0
- package/dist/vendor/adapters/openrouter-adapter.js +302 -0
- package/dist/vendor/adapters/usage.d.ts +48 -0
- package/dist/vendor/adapters/usage.js +66 -0
- package/dist/vendor/cli/bin/exit.d.ts +12 -0
- package/dist/vendor/cli/bin/exit.js +28 -0
- package/dist/vendor/cli/commands/analyze.d.ts +5 -0
- package/dist/vendor/cli/commands/analyze.js +58 -0
- package/dist/vendor/cli/commands/audit-log-verify.d.ts +34 -0
- package/dist/vendor/cli/commands/audit-log-verify.js +99 -0
- package/dist/vendor/cli/commands/audit.d.ts +8 -0
- package/dist/vendor/cli/commands/audit.js +199 -0
- package/dist/vendor/cli/commands/corpus.d.ts +5 -0
- package/dist/vendor/cli/commands/corpus.js +60 -0
- package/dist/vendor/cli/commands/doctor.d.ts +8 -0
- package/dist/vendor/cli/commands/doctor.js +219 -0
- package/dist/vendor/cli/commands/explain.d.ts +17 -0
- package/dist/vendor/cli/commands/explain.js +176 -0
- package/dist/vendor/cli/commands/export.d.ts +5 -0
- package/dist/vendor/cli/commands/export.js +60 -0
- package/dist/vendor/cli/commands/governance.d.ts +8 -0
- package/dist/vendor/cli/commands/governance.js +95 -0
- package/dist/vendor/cli/commands/improve.d.ts +18 -0
- package/dist/vendor/cli/commands/improve.js +396 -0
- package/dist/vendor/cli/commands/init.d.ts +8 -0
- package/dist/vendor/cli/commands/init.js +281 -0
- package/dist/vendor/cli/commands/migration.d.ts +8 -0
- package/dist/vendor/cli/commands/migration.js +67 -0
- package/dist/vendor/cli/commands/prior.d.ts +23 -0
- package/dist/vendor/cli/commands/prior.js +145 -0
- package/dist/vendor/cli/commands/resume.d.ts +21 -0
- package/dist/vendor/cli/commands/resume.js +73 -0
- package/dist/vendor/cli/commands/verify.d.ts +6 -0
- package/dist/vendor/cli/commands/verify.js +43 -0
- package/dist/vendor/cli/research/public-corpus.d.ts +43 -0
- package/dist/vendor/cli/research/public-corpus.js +151 -0
- package/dist/vendor/cli/ui/error-card.d.ts +38 -0
- package/dist/vendor/cli/ui/error-card.js +103 -0
- package/dist/vendor/cli/ui/mission-brief.d.ts +41 -0
- package/dist/vendor/cli/ui/mission-brief.js +173 -0
- package/dist/vendor/cli/ui/summary-card.d.ts +34 -0
- package/dist/vendor/cli/ui/summary-card.js +102 -0
- package/dist/vendor/contracts/audit.d.ts +46 -0
- package/dist/vendor/contracts/audit.js +360 -0
- package/dist/vendor/contracts/post-phase15.d.ts +240 -0
- package/dist/vendor/contracts/post-phase15.js +166 -0
- package/dist/vendor/core/agent/mandates.d.ts +46 -0
- package/dist/vendor/core/agent/mandates.js +178 -0
- package/dist/vendor/core/agent/receipts.d.ts +38 -0
- package/dist/vendor/core/agent/receipts.js +131 -0
- package/dist/vendor/core/agent/signing.d.ts +17 -0
- package/dist/vendor/core/agent/signing.js +91 -0
- package/dist/vendor/core/attestation/sign.d.ts +25 -0
- package/dist/vendor/core/attestation/sign.js +216 -0
- package/dist/vendor/core/autonomy/autonomous-promotion.d.ts +120 -0
- package/dist/vendor/core/autonomy/autonomous-promotion.js +346 -0
- package/dist/vendor/core/autonomy/envelope-v2.d.ts +29 -0
- package/dist/vendor/core/autonomy/envelope-v2.js +60 -0
- package/dist/vendor/core/autonomy/envelope.d.ts +17 -0
- package/dist/vendor/core/autonomy/envelope.js +27 -0
- package/dist/vendor/core/autonomy/escalation-ledger.d.ts +20 -0
- package/dist/vendor/core/autonomy/escalation-ledger.js +18 -0
- package/dist/vendor/core/autonomy/resume.d.ts +15 -0
- package/dist/vendor/core/autonomy/resume.js +23 -0
- package/dist/vendor/core/circuit/circuit-breaker.d.ts +60 -0
- package/dist/vendor/core/circuit/circuit-breaker.js +143 -0
- package/dist/vendor/core/context-distillation.d.ts +3 -0
- package/dist/vendor/core/context-distillation.js +44 -0
- package/dist/vendor/core/context-flow/compile-context.d.ts +8 -0
- package/dist/vendor/core/context-flow/compile-context.js +111 -0
- package/dist/vendor/core/context-flow/entities.d.ts +2 -0
- package/dist/vendor/core/context-flow/entities.js +44 -0
- package/dist/vendor/core/context-flow/evaluate-policy.d.ts +2 -0
- package/dist/vendor/core/context-flow/evaluate-policy.js +42 -0
- package/dist/vendor/core/context-flow/index.d.ts +11 -0
- package/dist/vendor/core/context-flow/index.js +24 -0
- package/dist/vendor/core/context-flow/labels.d.ts +3 -0
- package/dist/vendor/core/context-flow/labels.js +17 -0
- package/dist/vendor/core/context-flow/normalizer.d.ts +9 -0
- package/dist/vendor/core/context-flow/normalizer.js +69 -0
- package/dist/vendor/core/context-flow/profiles.d.ts +33 -0
- package/dist/vendor/core/context-flow/profiles.js +36 -0
- package/dist/vendor/core/context-flow/redaction.d.ts +1 -0
- package/dist/vendor/core/context-flow/redaction.js +6 -0
- package/dist/vendor/core/context-flow/sensitivity.d.ts +2 -0
- package/dist/vendor/core/context-flow/sensitivity.js +27 -0
- package/dist/vendor/core/context-flow/sync-preview.d.ts +2 -0
- package/dist/vendor/core/context-flow/sync-preview.js +22 -0
- package/dist/vendor/core/context-flow/token-estimator.d.ts +3 -0
- package/dist/vendor/core/context-flow/token-estimator.js +13 -0
- package/dist/vendor/core/context-flow/types.d.ts +91 -0
- package/dist/vendor/core/context-flow/types.js +2 -0
- package/dist/vendor/core/context-utility.d.ts +47 -0
- package/dist/vendor/core/context-utility.js +405 -0
- package/dist/vendor/core/cost/pipeline.d.ts +92 -0
- package/dist/vendor/core/cost/pipeline.js +141 -0
- package/dist/vendor/core/cost/tagged-cost.d.ts +27 -0
- package/dist/vendor/core/cost/tagged-cost.js +55 -0
- package/dist/vendor/core/cost-governor.d.ts +2 -0
- package/dist/vendor/core/cost-governor.js +50 -0
- package/dist/vendor/core/cve/cve-check.d.ts +80 -0
- package/dist/vendor/core/cve/cve-check.js +172 -0
- package/dist/vendor/core/digital-twin/index.d.ts +27 -0
- package/dist/vendor/core/digital-twin/index.js +90 -0
- package/dist/vendor/core/drift/drift-graph.d.ts +47 -0
- package/dist/vendor/core/drift/drift-graph.js +100 -0
- package/dist/vendor/core/drift/objective-lock.d.ts +69 -0
- package/dist/vendor/core/drift/objective-lock.js +88 -0
- package/dist/vendor/core/drift/scope.d.ts +46 -0
- package/dist/vendor/core/drift/scope.js +102 -0
- package/dist/vendor/core/drift/signature-lock.d.ts +48 -0
- package/dist/vendor/core/drift/signature-lock.js +202 -0
- package/dist/vendor/core/drift/stale-proof-gate.d.ts +21 -0
- package/dist/vendor/core/drift/stale-proof-gate.js +19 -0
- package/dist/vendor/core/eval/known-bad-world-runner.d.ts +24 -0
- package/dist/vendor/core/eval/known-bad-world-runner.js +256 -0
- package/dist/vendor/core/evidence/claim-audit.d.ts +18 -0
- package/dist/vendor/core/evidence/claim-audit.js +89 -0
- package/dist/vendor/core/exit-intelligence.d.ts +2 -0
- package/dist/vendor/core/exit-intelligence.js +58 -0
- package/dist/vendor/core/explain/formatter.d.ts +42 -0
- package/dist/vendor/core/explain/formatter.js +171 -0
- package/dist/vendor/core/explain/timeline.d.ts +29 -0
- package/dist/vendor/core/explain/timeline.js +213 -0
- package/dist/vendor/core/failure-taxonomy.d.ts +2 -0
- package/dist/vendor/core/failure-taxonomy.js +76 -0
- package/dist/vendor/core/gateway/index.d.ts +10 -0
- package/dist/vendor/core/gateway/index.js +12 -0
- package/dist/vendor/core/gateway/registry.d.ts +40 -0
- package/dist/vendor/core/gateway/registry.js +97 -0
- package/dist/vendor/core/gateway/transport.d.ts +31 -0
- package/dist/vendor/core/gateway/transport.js +82 -0
- package/dist/vendor/core/gateway/vault.d.ts +19 -0
- package/dist/vendor/core/gateway/vault.js +29 -0
- package/dist/vendor/core/graph/adapters.d.ts +43 -0
- package/dist/vendor/core/graph/adapters.js +91 -0
- package/dist/vendor/core/graph/hotspots.d.ts +22 -0
- package/dist/vendor/core/graph/hotspots.js +30 -0
- package/dist/vendor/core/graph/index.d.ts +1 -0
- package/dist/vendor/core/graph/index.js +2 -0
- package/dist/vendor/core/honey/honey-tokens.d.ts +32 -0
- package/dist/vendor/core/honey/honey-tokens.js +44 -0
- package/dist/vendor/core/index.d.ts +2 -2
- package/dist/vendor/core/index.js +38 -12
- package/dist/vendor/core/learning/bayesian-update.d.ts +31 -0
- package/dist/vendor/core/learning/bayesian-update.js +60 -0
- package/dist/vendor/core/learning/prior-sets.d.ts +42 -0
- package/dist/vendor/core/learning/prior-sets.js +111 -0
- package/dist/vendor/core/learning/promotion-gate.d.ts +17 -0
- package/dist/vendor/core/learning/promotion-gate.js +23 -0
- package/dist/vendor/core/leash/blast-radius.d.ts +42 -0
- package/dist/vendor/core/leash/blast-radius.js +156 -0
- package/dist/vendor/core/leash/policy-leash.d.ts +31 -0
- package/dist/vendor/core/leash/policy-leash.js +117 -0
- package/dist/vendor/core/memo/memo.d.ts +63 -0
- package/dist/vendor/core/memo/memo.js +97 -0
- package/dist/vendor/core/memory/learning-pipeline.d.ts +154 -0
- package/dist/vendor/core/memory/learning-pipeline.js +391 -0
- package/dist/vendor/core/memory/palace.d.ts +84 -0
- package/dist/vendor/core/memory/palace.js +379 -0
- package/dist/vendor/core/merge/ast-merge.d.ts +22 -0
- package/dist/vendor/core/merge/ast-merge.js +350 -0
- package/dist/vendor/core/merge/text-merge.d.ts +12 -0
- package/dist/vendor/core/merge/text-merge.js +182 -0
- package/dist/vendor/core/otel/tracer.d.ts +45 -0
- package/dist/vendor/core/otel/tracer.js +116 -0
- package/dist/vendor/core/parallel/parallel-attempts.d.ts +28 -0
- package/dist/vendor/core/parallel/parallel-attempts.js +41 -0
- package/dist/vendor/core/parallel/scorer.d.ts +24 -0
- package/dist/vendor/core/parallel/scorer.js +65 -0
- package/dist/vendor/core/pattern-detection.d.ts +64 -0
- package/dist/vendor/core/pattern-detection.js +108 -0
- package/dist/vendor/core/persistence/checkpoint.d.ts +44 -0
- package/dist/vendor/core/persistence/checkpoint.js +156 -0
- package/dist/vendor/core/persistence/cleanup.d.ts +22 -0
- package/dist/vendor/core/persistence/cleanup.js +131 -0
- package/dist/vendor/core/persistence/index.d.ts +2 -0
- package/dist/vendor/core/persistence/index.js +1 -0
- package/dist/vendor/core/persistence/runs-reader.d.ts +52 -0
- package/dist/vendor/core/persistence/runs-reader.js +84 -0
- package/dist/vendor/core/persistence/store.d.ts +6 -1
- package/dist/vendor/core/persistence/store.js +5 -0
- package/dist/vendor/core/policy/file-touch-quota.d.ts +60 -0
- package/dist/vendor/core/policy/file-touch-quota.js +105 -0
- package/dist/vendor/core/policy/policy-loader.d.ts +30 -0
- package/dist/vendor/core/policy/policy-loader.js +170 -0
- package/dist/vendor/core/policy/policy-schema.d.ts +55 -0
- package/dist/vendor/core/policy/policy-schema.js +78 -0
- package/dist/vendor/core/probe/probe.d.ts +49 -0
- package/dist/vendor/core/probe/probe.js +115 -0
- package/dist/vendor/core/proof/patch-proof.d.ts +58 -0
- package/dist/vendor/core/proof/patch-proof.js +84 -0
- package/dist/vendor/core/proof/semantic-probe.d.ts +25 -0
- package/dist/vendor/core/proof/semantic-probe.js +82 -0
- package/dist/vendor/core/recovery/failure-mode-runner.d.ts +29 -0
- package/dist/vendor/core/recovery/failure-mode-runner.js +39 -0
- package/dist/vendor/core/red-blue/red-phase.d.ts +64 -0
- package/dist/vendor/core/red-blue/red-phase.js +141 -0
- package/dist/vendor/core/red-blue/risk-tiers.d.ts +22 -0
- package/dist/vendor/core/red-blue/risk-tiers.js +33 -0
- package/dist/vendor/core/replay/replay.d.ts +85 -0
- package/dist/vendor/core/replay/replay.js +109 -0
- package/dist/vendor/core/router/engine.d.ts +54 -0
- package/dist/vendor/core/router/engine.js +131 -0
- package/dist/vendor/core/router/index.d.ts +1 -0
- package/dist/vendor/core/router/index.js +2 -0
- package/dist/vendor/core/router/trust-calibration.d.ts +57 -0
- package/dist/vendor/core/router/trust-calibration.js +127 -0
- package/dist/vendor/core/run-martin.d.ts +2 -0
- package/dist/vendor/core/run-martin.js +287 -0
- package/dist/vendor/core/security/cve-scanner.d.ts +62 -0
- package/dist/vendor/core/security/cve-scanner.js +178 -0
- package/dist/vendor/core/sentinel/efficiency-sentinel.d.ts +29 -0
- package/dist/vendor/core/sentinel/efficiency-sentinel.js +30 -0
- package/dist/vendor/core/sentinel/progress-guard.d.ts +35 -0
- package/dist/vendor/core/sentinel/progress-guard.js +46 -0
- package/dist/vendor/core/siem/siem-emitter.d.ts +49 -0
- package/dist/vendor/core/siem/siem-emitter.js +157 -0
- package/dist/vendor/core/strategy/attempt-brief.d.ts +22 -0
- package/dist/vendor/core/strategy/attempt-brief.js +89 -0
- package/dist/vendor/core/summarize/diff-summary.d.ts +35 -0
- package/dist/vendor/core/summarize/diff-summary.js +204 -0
- package/dist/vendor/core/surface-signals.d.ts +21 -0
- package/dist/vendor/core/surface-signals.js +139 -0
- package/dist/vendor/core/truth/truth-wall.d.ts +51 -0
- package/dist/vendor/core/truth/truth-wall.js +69 -0
- package/dist/vendor/core/truth-spine.d.ts +26 -0
- package/dist/vendor/core/truth-spine.js +62 -0
- package/dist/vendor/core/types.d.ts +115 -0
- package/dist/vendor/core/types.js +2 -0
- package/dist/vendor/core/verification/tiered-verify.d.ts +17 -0
- package/dist/vendor/core/verification/tiered-verify.js +29 -0
- package/dist/vendor/core/verifier-pyramid.d.ts +32 -0
- package/dist/vendor/core/verifier-pyramid.js +111 -0
- package/dist/vendor/core/workflow-artifacts.d.ts +99 -0
- package/dist/vendor/core/workflow-artifacts.js +668 -0
- package/dist/vendor/core/wrap/supervised-run.d.ts +96 -0
- package/dist/vendor/core/wrap/supervised-run.js +178 -0
- package/docs/assets/cli-animated.svg +139 -0
- package/docs/assets/cli-static.svg +34 -0
- package/docs/assets/github-hero-v2.svg +23 -0
- package/docs/assets/martin-raplph.png.jpg +0 -0
- package/docs/assets/martinloop-logo.png +0 -0
- package/docs/assets/nvidia-inception-program-light.png +0 -0
- package/docs/assets/nvidia-inception-program.png +0 -0
- package/docs/assets/phase3c-sidesidebyside-demo.html +228 -0
- package/docs/assets/side-by-side.svg +134 -0
- package/docs/oss/CLAUDE-CODE-WALKTHROUGH.md +142 -142
- package/docs/oss/EXAMPLES.md +134 -134
- package/docs/oss/OSS-BOUNDARY-REPORT.json +1 -1
- package/docs/oss/OSS-BOUNDARY-REPORT.md +1 -1
- package/docs/oss/QUICKSTART.md +170 -165
- package/docs/oss/RALPH-LOOP-SAFETY.md +113 -113
- package/docs/oss/README.md +96 -96
- package/docs/oss/RELEASE-SURFACE-REPORT.json +2 -1
- package/docs/oss/RELEASE-SURFACE-REPORT.md +2 -1
- package/package.json +130 -58
- package/docs/distribution/DIRECTORY-SUBMISSIONS.md +0 -89
- package/docs/distribution/INTEGRATION-OUTREACH.md +0 -61
- package/docs/distribution/UNDER-3-CHALLENGE.md +0 -65
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
// SLICE-24 — Model circuit breaker
|
|
2
|
+
// State machine: CLOSED → OPEN → HALF_OPEN → CLOSED
|
|
3
|
+
// Tracks consecutive failures per adapter and opens the circuit when the
|
|
4
|
+
// threshold is reached, allowing recovery via a half-open probe.
|
|
5
|
+
const DEFAULT_CONFIG = {
|
|
6
|
+
failureThreshold: 3,
|
|
7
|
+
cooldownMs: 60_000,
|
|
8
|
+
windowMs: 300_000
|
|
9
|
+
};
|
|
10
|
+
export class CircuitBreaker {
|
|
11
|
+
config;
|
|
12
|
+
adapterId;
|
|
13
|
+
state = "CLOSED";
|
|
14
|
+
failureCount = 0;
|
|
15
|
+
lastFailureTime;
|
|
16
|
+
openedAt;
|
|
17
|
+
constructor(adapterId, config) {
|
|
18
|
+
this.adapterId = adapterId;
|
|
19
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Returns the current circuit breaker state snapshot.
|
|
23
|
+
*/
|
|
24
|
+
getState() {
|
|
25
|
+
return {
|
|
26
|
+
state: this.state,
|
|
27
|
+
failureCount: this.failureCount,
|
|
28
|
+
lastFailureTime: this.lastFailureTime?.toISOString(),
|
|
29
|
+
openedAt: this.openedAt?.toISOString(),
|
|
30
|
+
adapterId: this.adapterId
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Returns true if a call should be allowed through.
|
|
35
|
+
* - CLOSED: always allowed
|
|
36
|
+
* - HALF_OPEN: one probe call allowed
|
|
37
|
+
* - OPEN: blocked unless cooldown has elapsed (transitions to HALF_OPEN)
|
|
38
|
+
*/
|
|
39
|
+
canCall(now = new Date()) {
|
|
40
|
+
if (this.state === "CLOSED") {
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
if (this.state === "HALF_OPEN") {
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
// OPEN: check if cooldown has elapsed
|
|
47
|
+
if (this.state === "OPEN" && this.openedAt) {
|
|
48
|
+
const elapsed = now.getTime() - this.openedAt.getTime();
|
|
49
|
+
if (elapsed >= this.config.cooldownMs) {
|
|
50
|
+
this.state = "HALF_OPEN";
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Record a successful adapter call.
|
|
58
|
+
* HALF_OPEN → CLOSED on success.
|
|
59
|
+
*/
|
|
60
|
+
recordSuccess() {
|
|
61
|
+
if (this.state === "HALF_OPEN") {
|
|
62
|
+
this.state = "CLOSED";
|
|
63
|
+
this.failureCount = 0;
|
|
64
|
+
this.lastFailureTime = undefined;
|
|
65
|
+
this.openedAt = undefined;
|
|
66
|
+
}
|
|
67
|
+
else if (this.state === "CLOSED") {
|
|
68
|
+
// Reset failure count on success in closed state
|
|
69
|
+
this.failureCount = 0;
|
|
70
|
+
}
|
|
71
|
+
// In OPEN state, success shouldn't happen (canCall returns false)
|
|
72
|
+
// but we handle it gracefully
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Record a failed adapter call.
|
|
76
|
+
* CLOSED: increments failure count; if threshold reached, opens circuit.
|
|
77
|
+
* HALF_OPEN: re-opens circuit (probe failed).
|
|
78
|
+
*/
|
|
79
|
+
recordFailure(now = new Date()) {
|
|
80
|
+
this.lastFailureTime = now;
|
|
81
|
+
if (this.state === "HALF_OPEN") {
|
|
82
|
+
// Probe failed — re-open
|
|
83
|
+
this.state = "OPEN";
|
|
84
|
+
this.openedAt = now;
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (this.state === "CLOSED") {
|
|
88
|
+
this.failureCount++;
|
|
89
|
+
if (this.failureCount >= this.config.failureThreshold) {
|
|
90
|
+
this.state = "OPEN";
|
|
91
|
+
this.openedAt = now;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// In OPEN state, failures are noted but don't change state
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Manually reset the circuit breaker to CLOSED state.
|
|
98
|
+
*/
|
|
99
|
+
reset() {
|
|
100
|
+
this.state = "CLOSED";
|
|
101
|
+
this.failureCount = 0;
|
|
102
|
+
this.lastFailureTime = undefined;
|
|
103
|
+
this.openedAt = undefined;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Serializes a CircuitBreaker instance to a JSON string.
|
|
108
|
+
*/
|
|
109
|
+
export function serializeState(breaker) {
|
|
110
|
+
const snapshot = breaker.getState();
|
|
111
|
+
const serialized = {
|
|
112
|
+
adapterId: snapshot.adapterId,
|
|
113
|
+
config: breaker.config,
|
|
114
|
+
internalState: {
|
|
115
|
+
state: snapshot.state,
|
|
116
|
+
failureCount: snapshot.failureCount,
|
|
117
|
+
lastFailureTime: snapshot.lastFailureTime,
|
|
118
|
+
openedAt: snapshot.openedAt
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
return JSON.stringify(serialized);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Deserializes a JSON string back into a CircuitBreaker instance.
|
|
125
|
+
* Restores internal state including failure count, timestamps, and state.
|
|
126
|
+
*/
|
|
127
|
+
export function deserializeState(json, configOverride) {
|
|
128
|
+
const parsed = JSON.parse(json);
|
|
129
|
+
const mergedConfig = { ...parsed.config, ...configOverride };
|
|
130
|
+
const breaker = new CircuitBreaker(parsed.adapterId, mergedConfig);
|
|
131
|
+
// Restore internal state by directly setting private fields via index access
|
|
132
|
+
const internal = parsed.internalState;
|
|
133
|
+
breaker["state"] = internal.state;
|
|
134
|
+
breaker["failureCount"] = internal.failureCount;
|
|
135
|
+
breaker["lastFailureTime"] = internal.lastFailureTime
|
|
136
|
+
? new Date(internal.lastFailureTime)
|
|
137
|
+
: undefined;
|
|
138
|
+
breaker["openedAt"] = internal.openedAt
|
|
139
|
+
? new Date(internal.openedAt)
|
|
140
|
+
: undefined;
|
|
141
|
+
return breaker;
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=circuit-breaker.js.map
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export function distillContext(loop, options = {}) {
|
|
2
|
+
const maxRecentAttempts = Math.max(1, options.maxRecentAttempts ?? 3);
|
|
3
|
+
const recentAttempts = loop.attempts.slice(-maxRecentAttempts).map((attempt) => {
|
|
4
|
+
const distilled = {
|
|
5
|
+
attemptId: attempt.attemptId,
|
|
6
|
+
index: attempt.index,
|
|
7
|
+
summary: attempt.summary ?? "No attempt summary recorded."
|
|
8
|
+
};
|
|
9
|
+
if (attempt.failureClass) {
|
|
10
|
+
distilled.failureClass = attempt.failureClass;
|
|
11
|
+
}
|
|
12
|
+
if (attempt.intervention) {
|
|
13
|
+
distilled.intervention = attempt.intervention;
|
|
14
|
+
}
|
|
15
|
+
return distilled;
|
|
16
|
+
});
|
|
17
|
+
const remainingBudgetUsd = clamp(loop.budget.maxUsd - loop.cost.actualUsd);
|
|
18
|
+
const remainingIterations = clamp(loop.budget.maxIterations - loop.attempts.length);
|
|
19
|
+
const remainingTokens = clamp(loop.budget.maxTokens - loop.cost.tokensIn - loop.cost.tokensOut);
|
|
20
|
+
const repeatedClass = recentAttempts.at(-1)?.failureClass;
|
|
21
|
+
const nextMove = repeatedClass === undefined
|
|
22
|
+
? "Focus on the first verified attempt."
|
|
23
|
+
: `Avoid another ${repeatedClass} outcome.`;
|
|
24
|
+
const context = {
|
|
25
|
+
taskTitle: loop.task.title,
|
|
26
|
+
objective: loop.task.objective,
|
|
27
|
+
verificationPlan: [...loop.task.verificationPlan],
|
|
28
|
+
recentAttempts,
|
|
29
|
+
constraints: {
|
|
30
|
+
remainingBudgetUsd,
|
|
31
|
+
remainingIterations,
|
|
32
|
+
remainingTokens
|
|
33
|
+
},
|
|
34
|
+
focus: `${loop.task.objective} ${nextMove}`.trim()
|
|
35
|
+
};
|
|
36
|
+
if (loop.task.repoRoot) {
|
|
37
|
+
context.repoRoot = loop.task.repoRoot;
|
|
38
|
+
}
|
|
39
|
+
return context;
|
|
40
|
+
}
|
|
41
|
+
function clamp(value) {
|
|
42
|
+
return value < 0 ? 0 : Number(value.toFixed(4));
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=context-distillation.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { CanonicalRecord, CompileOptions, ContextPack, PolicyDecision, QcReport } from "./types.js";
|
|
2
|
+
export declare function defaultCompileOptions(): CompileOptions;
|
|
3
|
+
export declare function compileRecordContext(record: CanonicalRecord, profileName: string | undefined, options?: Partial<CompileOptions>): {
|
|
4
|
+
profile: ContextPack["profile"];
|
|
5
|
+
compiledContext: string;
|
|
6
|
+
qcReport: QcReport;
|
|
7
|
+
};
|
|
8
|
+
export declare function createCompileTraceId(record: CanonicalRecord, compiledContext: string, policyDecision: PolicyDecision): string;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { resolveHeadlessProfile } from "./profiles.js";
|
|
3
|
+
import { redactText } from "./redaction.js";
|
|
4
|
+
import { estimateTokens } from "./token-estimator.js";
|
|
5
|
+
export function defaultCompileOptions() {
|
|
6
|
+
return {
|
|
7
|
+
redactPii: true,
|
|
8
|
+
includeProvenanceSnippets: false,
|
|
9
|
+
deltaMode: false
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export function compileRecordContext(record, profileName, options) {
|
|
13
|
+
const { name, config } = resolveHeadlessProfile(profileName);
|
|
14
|
+
const resolvedOptions = {
|
|
15
|
+
...defaultCompileOptions(),
|
|
16
|
+
...(options ?? {})
|
|
17
|
+
};
|
|
18
|
+
const sections = [];
|
|
19
|
+
const keptFields = [];
|
|
20
|
+
if (config.keepSections.includes("summary") && record.summary) {
|
|
21
|
+
sections.push(`SUMMARY\n${record.summary}`);
|
|
22
|
+
keptFields.push("summary");
|
|
23
|
+
}
|
|
24
|
+
const fieldMap = {
|
|
25
|
+
customer: record.fields.account,
|
|
26
|
+
issue: record.fields.issue,
|
|
27
|
+
product: record.fields.product,
|
|
28
|
+
next_steps: record.fields.requested_outcome,
|
|
29
|
+
account: record.fields.account,
|
|
30
|
+
stakeholders: record.fields.primary_contact,
|
|
31
|
+
open_risks: record.fields.priority,
|
|
32
|
+
opportunities: record.fields.arr,
|
|
33
|
+
recent_activity: typeof record.metadata.recent_activity === "string"
|
|
34
|
+
? record.metadata.recent_activity
|
|
35
|
+
: undefined
|
|
36
|
+
};
|
|
37
|
+
for (const section of config.keepSections) {
|
|
38
|
+
const value = fieldMap[section];
|
|
39
|
+
if (value) {
|
|
40
|
+
sections.push(`${section.toUpperCase()}\n${value}`);
|
|
41
|
+
keptFields.push(section);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (config.keepSections.includes("key_entities") && record.entities.length > 0) {
|
|
45
|
+
const values = [...new Set(record.entities.slice(0, 8).map((entity) => entity.value))];
|
|
46
|
+
sections.push(`KEY_ENTITIES\n${values.join(", ")}`);
|
|
47
|
+
keptFields.push("key_entities");
|
|
48
|
+
}
|
|
49
|
+
if (config.keepSections.includes("action_items")) {
|
|
50
|
+
const action = record.fields.requested_outcome ?? "Review canonical record and proceed cautiously.";
|
|
51
|
+
sections.push(`ACTION_ITEMS\n- ${action}`);
|
|
52
|
+
keptFields.push("action_items");
|
|
53
|
+
}
|
|
54
|
+
if (resolvedOptions.includeProvenanceSnippets && record.provenance.length > 0) {
|
|
55
|
+
const snippets = record.provenance
|
|
56
|
+
.slice(0, 3)
|
|
57
|
+
.map((item) => `- ${item.evidence}`)
|
|
58
|
+
.join("\n");
|
|
59
|
+
sections.push(`PROVENANCE_SNIPPETS\n${snippets}`);
|
|
60
|
+
keptFields.push("provenance_snippets");
|
|
61
|
+
}
|
|
62
|
+
let compiledContext = sections.join("\n\n").trim();
|
|
63
|
+
if (resolvedOptions.redactPii) {
|
|
64
|
+
compiledContext = redactText(compiledContext);
|
|
65
|
+
}
|
|
66
|
+
const budget = resolvedOptions.maxTokensOverride ?? config.maxTokens;
|
|
67
|
+
compiledContext = truncateToBudget(compiledContext, budget);
|
|
68
|
+
const tokenEstimateAfter = estimateTokens(compiledContext);
|
|
69
|
+
const beforeText = `${record.summary} ${record.provenance.map((item) => item.evidence).join(" ")}`;
|
|
70
|
+
const tokenEstimateBefore = estimateTokens(beforeText);
|
|
71
|
+
const tokenReductionPct = tokenEstimateBefore === 0
|
|
72
|
+
? 0
|
|
73
|
+
: Number((Math.max(0, (tokenEstimateBefore - tokenEstimateAfter) / tokenEstimateBefore) * 100).toFixed(2));
|
|
74
|
+
const completenessScore = Number(Math.min(1, (Object.keys(record.fields).length + record.entities.length * 0.15) / 8).toFixed(2));
|
|
75
|
+
const warnings = [];
|
|
76
|
+
if (!record.fields.issue) {
|
|
77
|
+
warnings.push("Issue field missing or not inferred.");
|
|
78
|
+
}
|
|
79
|
+
if (!record.fields.account) {
|
|
80
|
+
warnings.push("Account field missing or not inferred.");
|
|
81
|
+
}
|
|
82
|
+
if (resolvedOptions.deltaMode) {
|
|
83
|
+
warnings.push("Delta mode enabled: only compact context should be sent downstream.");
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
profile: name,
|
|
87
|
+
compiledContext,
|
|
88
|
+
qcReport: {
|
|
89
|
+
completenessScore,
|
|
90
|
+
tokenEstimateBefore,
|
|
91
|
+
tokenEstimateAfter,
|
|
92
|
+
tokenReductionPct,
|
|
93
|
+
warnings,
|
|
94
|
+
keptFields
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
export function createCompileTraceId(record, compiledContext, policyDecision) {
|
|
99
|
+
return createHash("sha1")
|
|
100
|
+
.update(`${record.recordId}:${compiledContext}:${policyDecision.recommendedMode}`)
|
|
101
|
+
.digest("hex")
|
|
102
|
+
.slice(0, 16);
|
|
103
|
+
}
|
|
104
|
+
function truncateToBudget(text, budget) {
|
|
105
|
+
const words = text.split(/\s+/).filter(Boolean);
|
|
106
|
+
if (words.length <= budget) {
|
|
107
|
+
return text;
|
|
108
|
+
}
|
|
109
|
+
return words.slice(0, budget).join(" ");
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=compile-context.js.map
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { CANONICAL_FIELD_LABELS, toFieldKey } from "./labels.js";
|
|
2
|
+
const EMAIL_RE = /[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/g;
|
|
3
|
+
const MONEY_RE = /\$\s?([0-9][0-9,]*)/g;
|
|
4
|
+
const DATE_RE = /\b20\d{2}-\d{2}-\d{2}\b/g;
|
|
5
|
+
export function extractEntities(text) {
|
|
6
|
+
const entities = [];
|
|
7
|
+
for (const match of text.matchAll(EMAIL_RE)) {
|
|
8
|
+
entities.push({
|
|
9
|
+
type: "email",
|
|
10
|
+
value: match[0],
|
|
11
|
+
confidence: 0.95
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
for (const match of text.matchAll(MONEY_RE)) {
|
|
15
|
+
entities.push({
|
|
16
|
+
type: "money",
|
|
17
|
+
value: match[0],
|
|
18
|
+
confidence: 0.8
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
for (const match of text.matchAll(DATE_RE)) {
|
|
22
|
+
entities.push({
|
|
23
|
+
type: "date",
|
|
24
|
+
value: match[0],
|
|
25
|
+
confidence: 0.9
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
for (const label of CANONICAL_FIELD_LABELS) {
|
|
29
|
+
const pattern = new RegExp(`${escapeForRegex(label)}:\\s*(.+)`, "im");
|
|
30
|
+
const match = pattern.exec(text);
|
|
31
|
+
if (match?.[1]) {
|
|
32
|
+
entities.push({
|
|
33
|
+
type: toFieldKey(label),
|
|
34
|
+
value: match[1].trim(),
|
|
35
|
+
confidence: 0.9
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return entities;
|
|
40
|
+
}
|
|
41
|
+
function escapeForRegex(value) {
|
|
42
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=entities.js.map
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { resolveHeadlessProfile } from "./profiles.js";
|
|
2
|
+
import { classifySensitivity } from "./sensitivity.js";
|
|
3
|
+
export function evaluatePolicy(record, qcReport, profileName) {
|
|
4
|
+
const { name, config } = resolveHeadlessProfile(profileName);
|
|
5
|
+
const reasons = [];
|
|
6
|
+
let allowAutonomy = true;
|
|
7
|
+
let severity = "low";
|
|
8
|
+
let recommendedMode = "auto";
|
|
9
|
+
let requiresApproval = false;
|
|
10
|
+
if (qcReport.completenessScore < config.autonomyThreshold) {
|
|
11
|
+
allowAutonomy = false;
|
|
12
|
+
severity = "medium";
|
|
13
|
+
recommendedMode = "human_review";
|
|
14
|
+
reasons.push("Completeness below autonomy threshold.");
|
|
15
|
+
}
|
|
16
|
+
if (qcReport.warnings.length >= 2) {
|
|
17
|
+
allowAutonomy = false;
|
|
18
|
+
severity = "high";
|
|
19
|
+
recommendedMode = "human_review";
|
|
20
|
+
reasons.push("Too many unresolved warnings in compiled context.");
|
|
21
|
+
}
|
|
22
|
+
const sensitivity = classifySensitivity(record);
|
|
23
|
+
if (sensitivity.level === "high") {
|
|
24
|
+
allowAutonomy = false;
|
|
25
|
+
severity = "high";
|
|
26
|
+
recommendedMode = "approval_required";
|
|
27
|
+
requiresApproval = true;
|
|
28
|
+
reasons.push(...sensitivity.reasons);
|
|
29
|
+
}
|
|
30
|
+
if (reasons.length === 0) {
|
|
31
|
+
reasons.push("Record meets baseline autonomy policy.");
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
profile: name,
|
|
35
|
+
allowAutonomy,
|
|
36
|
+
severity,
|
|
37
|
+
reasons,
|
|
38
|
+
recommendedMode,
|
|
39
|
+
requiresApproval
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=evaluate-policy.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type { ApiKey, ApiKeyScope, CanonicalRecord, CompileOptions, CompileTrace, ContextPack, Entity, PolicyDecision, PolicyMode, PolicySeverity, ProvenanceItem, QcReport, SensitivityClassification, SensitivityLevel, SyncPreviewInput, SyncPreviewResponse, Tenant } from "./types.js";
|
|
2
|
+
export { HEADLESSOS_PROFILES, resolveHeadlessProfile, type HeadlessCompileProfile, type HeadlessProfileName, type HeadlessProfileSection } from "./profiles.js";
|
|
3
|
+
export { CANONICAL_FIELD_LABELS, toFieldKey, type CanonicalFieldLabel } from "./labels.js";
|
|
4
|
+
export { normalizeTextRecord, extractLabeledFields, type NormalizeTextInput } from "./normalizer.js";
|
|
5
|
+
export { extractEntities } from "./entities.js";
|
|
6
|
+
export { redactText } from "./redaction.js";
|
|
7
|
+
export { compileRecordContext, createCompileTraceId, defaultCompileOptions } from "./compile-context.js";
|
|
8
|
+
export { DEFAULT_COST_PER_1K_TOKENS, estimateCostUsd, estimateTokens } from "./token-estimator.js";
|
|
9
|
+
export { classifySensitivity } from "./sensitivity.js";
|
|
10
|
+
export { evaluatePolicy } from "./evaluate-policy.js";
|
|
11
|
+
export { buildSyncPreview } from "./sync-preview.js";
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// ─── Context Flow: OSS data pipeline for AI agents ──────────────────────────
|
|
2
|
+
// Transforms raw unstructured records into clean, PII-safe, token-budgeted
|
|
3
|
+
// context packs ready for any LLM agent. No infrastructure required.
|
|
4
|
+
// Profiles
|
|
5
|
+
export { HEADLESSOS_PROFILES, resolveHeadlessProfile } from "./profiles.js";
|
|
6
|
+
// Labels
|
|
7
|
+
export { CANONICAL_FIELD_LABELS, toFieldKey } from "./labels.js";
|
|
8
|
+
// Normalizer (raw text → canonical record)
|
|
9
|
+
export { normalizeTextRecord, extractLabeledFields } from "./normalizer.js";
|
|
10
|
+
// Entity extraction
|
|
11
|
+
export { extractEntities } from "./entities.js";
|
|
12
|
+
// PII redaction
|
|
13
|
+
export { redactText } from "./redaction.js";
|
|
14
|
+
// Context compilation (canonical record → context pack)
|
|
15
|
+
export { compileRecordContext, createCompileTraceId, defaultCompileOptions } from "./compile-context.js";
|
|
16
|
+
// Token estimation
|
|
17
|
+
export { DEFAULT_COST_PER_1K_TOKENS, estimateCostUsd, estimateTokens } from "./token-estimator.js";
|
|
18
|
+
// Sensitivity classification
|
|
19
|
+
export { classifySensitivity } from "./sensitivity.js";
|
|
20
|
+
// Policy evaluation
|
|
21
|
+
export { evaluatePolicy } from "./evaluate-policy.js";
|
|
22
|
+
// Sync preview
|
|
23
|
+
export { buildSyncPreview } from "./sync-preview.js";
|
|
24
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare const CANONICAL_FIELD_LABELS: readonly ["Account", "Primary Contact", "Product", "Issue", "Priority", "ARR", "Renewal Date", "Requested Outcome", "Recent Activity", "Owner", "Status"];
|
|
2
|
+
export type CanonicalFieldLabel = (typeof CANONICAL_FIELD_LABELS)[number];
|
|
3
|
+
export declare function toFieldKey(label: CanonicalFieldLabel | string): string;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const CANONICAL_FIELD_LABELS = [
|
|
2
|
+
"Account",
|
|
3
|
+
"Primary Contact",
|
|
4
|
+
"Product",
|
|
5
|
+
"Issue",
|
|
6
|
+
"Priority",
|
|
7
|
+
"ARR",
|
|
8
|
+
"Renewal Date",
|
|
9
|
+
"Requested Outcome",
|
|
10
|
+
"Recent Activity",
|
|
11
|
+
"Owner",
|
|
12
|
+
"Status"
|
|
13
|
+
];
|
|
14
|
+
export function toFieldKey(label) {
|
|
15
|
+
return label.toLowerCase().replace(/\s+/g, "_");
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=labels.js.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CanonicalRecord } from "./types.js";
|
|
2
|
+
export interface NormalizeTextInput {
|
|
3
|
+
text: string;
|
|
4
|
+
sourceName?: string;
|
|
5
|
+
recordType?: string;
|
|
6
|
+
metadata?: Record<string, unknown>;
|
|
7
|
+
}
|
|
8
|
+
export declare function extractLabeledFields(text: string): Record<string, string>;
|
|
9
|
+
export declare function normalizeTextRecord(input: NormalizeTextInput): CanonicalRecord;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { extractEntities } from "./entities.js";
|
|
3
|
+
import { CANONICAL_FIELD_LABELS, toFieldKey } from "./labels.js";
|
|
4
|
+
export function extractLabeledFields(text) {
|
|
5
|
+
const fields = {};
|
|
6
|
+
for (const label of CANONICAL_FIELD_LABELS) {
|
|
7
|
+
const match = new RegExp(`${escapeForRegex(label)}:\\s*(.+)`, "im").exec(text);
|
|
8
|
+
if (match?.[1]) {
|
|
9
|
+
fields[toFieldKey(label)] = match[1].trim();
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
return fields;
|
|
13
|
+
}
|
|
14
|
+
export function normalizeTextRecord(input) {
|
|
15
|
+
const sourceName = input.sourceName ?? "inline";
|
|
16
|
+
const recordType = input.recordType ?? "note";
|
|
17
|
+
const metadata = {
|
|
18
|
+
...(input.metadata ?? {})
|
|
19
|
+
};
|
|
20
|
+
const lines = input.text
|
|
21
|
+
.split(/\r?\n/)
|
|
22
|
+
.map((line) => line.trim())
|
|
23
|
+
.filter((line) => line.length > 0);
|
|
24
|
+
const fields = extractLabeledFields(input.text);
|
|
25
|
+
const summary = buildSummary(fields, lines);
|
|
26
|
+
const recordId = createHash("sha1")
|
|
27
|
+
.update(`${sourceName}:${recordType}:${input.text}`)
|
|
28
|
+
.digest("hex")
|
|
29
|
+
.slice(0, 12);
|
|
30
|
+
const provenance = lines.slice(0, 10).map((line) => ({
|
|
31
|
+
sourceName,
|
|
32
|
+
evidence: line
|
|
33
|
+
}));
|
|
34
|
+
const entities = extractEntities(input.text);
|
|
35
|
+
if (fields.recent_activity) {
|
|
36
|
+
metadata.recent_activity = fields.recent_activity;
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
recordId,
|
|
40
|
+
recordType,
|
|
41
|
+
summary,
|
|
42
|
+
fields,
|
|
43
|
+
entities,
|
|
44
|
+
provenance,
|
|
45
|
+
metadata
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function buildSummary(fields, lines) {
|
|
49
|
+
const summaryParts = [];
|
|
50
|
+
for (const key of ["account", "product", "issue", "requested_outcome"]) {
|
|
51
|
+
if (fields[key]) {
|
|
52
|
+
summaryParts.push(`${toTitleCase(key)}: ${fields[key]}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (summaryParts.length > 0) {
|
|
56
|
+
return summaryParts.join(" | ");
|
|
57
|
+
}
|
|
58
|
+
return lines.slice(0, 3).join(" ").slice(0, 400);
|
|
59
|
+
}
|
|
60
|
+
function toTitleCase(value) {
|
|
61
|
+
return value
|
|
62
|
+
.split("_")
|
|
63
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
64
|
+
.join(" ");
|
|
65
|
+
}
|
|
66
|
+
function escapeForRegex(value) {
|
|
67
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=normalizer.js.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export type HeadlessProfileSection = "summary" | "customer" | "issue" | "product" | "next_steps" | "account" | "stakeholders" | "open_risks" | "opportunities" | "recent_activity" | "key_entities" | "action_items" | "provenance_snippets";
|
|
2
|
+
export interface HeadlessCompileProfile {
|
|
3
|
+
maxTokens: number;
|
|
4
|
+
keepSections: readonly HeadlessProfileSection[];
|
|
5
|
+
autonomyThreshold: number;
|
|
6
|
+
}
|
|
7
|
+
export declare const HEADLESSOS_PROFILES: {
|
|
8
|
+
support_triage: {
|
|
9
|
+
maxTokens: number;
|
|
10
|
+
keepSections: ("summary" | "customer" | "issue" | "product" | "next_steps")[];
|
|
11
|
+
autonomyThreshold: number;
|
|
12
|
+
};
|
|
13
|
+
revops_account_brief: {
|
|
14
|
+
maxTokens: number;
|
|
15
|
+
keepSections: ("account" | "stakeholders" | "open_risks" | "opportunities" | "recent_activity")[];
|
|
16
|
+
autonomyThreshold: number;
|
|
17
|
+
};
|
|
18
|
+
generic_agent_small: {
|
|
19
|
+
maxTokens: number;
|
|
20
|
+
keepSections: ("summary" | "key_entities" | "action_items")[];
|
|
21
|
+
autonomyThreshold: number;
|
|
22
|
+
};
|
|
23
|
+
martin360_agent_stage: {
|
|
24
|
+
maxTokens: number;
|
|
25
|
+
keepSections: ("summary" | "issue" | "next_steps" | "account" | "stakeholders" | "key_entities")[];
|
|
26
|
+
autonomyThreshold: number;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
export type HeadlessProfileName = keyof typeof HEADLESSOS_PROFILES;
|
|
30
|
+
export declare function resolveHeadlessProfile(profile: HeadlessProfileName | string | undefined): {
|
|
31
|
+
name: HeadlessProfileName;
|
|
32
|
+
config: HeadlessCompileProfile;
|
|
33
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export const HEADLESSOS_PROFILES = {
|
|
2
|
+
support_triage: {
|
|
3
|
+
maxTokens: 800,
|
|
4
|
+
keepSections: ["summary", "customer", "issue", "product", "next_steps"],
|
|
5
|
+
autonomyThreshold: 0.8
|
|
6
|
+
},
|
|
7
|
+
revops_account_brief: {
|
|
8
|
+
maxTokens: 1200,
|
|
9
|
+
keepSections: ["account", "stakeholders", "open_risks", "opportunities", "recent_activity"],
|
|
10
|
+
autonomyThreshold: 0.85
|
|
11
|
+
},
|
|
12
|
+
generic_agent_small: {
|
|
13
|
+
maxTokens: 600,
|
|
14
|
+
keepSections: ["summary", "key_entities", "action_items"],
|
|
15
|
+
autonomyThreshold: 0.9
|
|
16
|
+
},
|
|
17
|
+
martin360_agent_stage: {
|
|
18
|
+
maxTokens: 900,
|
|
19
|
+
keepSections: ["summary", "account", "issue", "stakeholders", "next_steps", "key_entities"],
|
|
20
|
+
autonomyThreshold: 0.82
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
export function resolveHeadlessProfile(profile) {
|
|
24
|
+
if (profile && profile in HEADLESSOS_PROFILES) {
|
|
25
|
+
const name = profile;
|
|
26
|
+
return {
|
|
27
|
+
name,
|
|
28
|
+
config: HEADLESSOS_PROFILES[name]
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
name: "generic_agent_small",
|
|
33
|
+
config: HEADLESSOS_PROFILES.generic_agent_small
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=profiles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function redactText(text: string): string;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
const EMAIL_RE = /[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/g;
|
|
2
|
+
const PHONE_RE = /(?:\+?\d{1,3}[ -]?)?(?:\(?\d{3}\)?[ -]?)?\d{3}[ -]?\d{4}/g;
|
|
3
|
+
export function redactText(text) {
|
|
4
|
+
return text.replace(EMAIL_RE, "[REDACTED_EMAIL]").replace(PHONE_RE, "[REDACTED_PHONE]");
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=redaction.js.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const HIGH_RISK_RECORD_TYPES = new Set(["security_incident", "finance_change"]);
|
|
2
|
+
export function classifySensitivity(record) {
|
|
3
|
+
const reasons = [];
|
|
4
|
+
const matchedEntityTypes = [...new Set(record.entities.map((entity) => entity.type))];
|
|
5
|
+
let level = "low";
|
|
6
|
+
if (HIGH_RISK_RECORD_TYPES.has(record.recordType)) {
|
|
7
|
+
level = "high";
|
|
8
|
+
reasons.push(`Sensitive record type "${record.recordType}" requires approval.`);
|
|
9
|
+
}
|
|
10
|
+
if (matchedEntityTypes.includes("money")) {
|
|
11
|
+
level = level === "high" ? "high" : "moderate";
|
|
12
|
+
reasons.push("Financial values were detected in the source record.");
|
|
13
|
+
}
|
|
14
|
+
if (matchedEntityTypes.includes("email")) {
|
|
15
|
+
level = level === "high" ? "high" : "moderate";
|
|
16
|
+
reasons.push("Direct contact data was detected in the source record.");
|
|
17
|
+
}
|
|
18
|
+
if (reasons.length === 0) {
|
|
19
|
+
reasons.push("No elevated sensitivity indicators were detected.");
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
level,
|
|
23
|
+
reasons,
|
|
24
|
+
matchedEntityTypes
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=sensitivity.js.map
|