@inixiative/foundry-core 0.5.10 → 0.5.11
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/package.json +3 -3
- package/src/adapters/markdown-docs.ts +7 -1
- package/src/feedback/correction.ts +35 -1
- package/src/index.ts +2 -1
- package/src/thread.ts +0 -15
- package/src/types.ts +0 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inixiative/foundry-core",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.11",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "src/index.ts",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"bun": ">=1.4.4"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
|
-
"@inixiative/archive": "^0.
|
|
36
|
+
"@inixiative/archive": "^0.33.0"
|
|
37
37
|
},
|
|
38
38
|
"peerDependenciesMeta": {
|
|
39
39
|
"@inixiative/archive": {
|
|
@@ -41,6 +41,6 @@
|
|
|
41
41
|
}
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@inixiative/archive": "^0.
|
|
44
|
+
"@inixiative/archive": "^0.33.1"
|
|
45
45
|
}
|
|
46
46
|
}
|
|
@@ -293,7 +293,13 @@ export function secretInstructionPath(path: string, trusted: readonly string[] =
|
|
|
293
293
|
name.startsWith('.') ||
|
|
294
294
|
/^id_[a-z0-9]+/i.test(name) ||
|
|
295
295
|
/\.(pem|key|p12|pfx|keystore|jks)$/i.test(name) ||
|
|
296
|
-
rest.split(sep).some((part) => CREDENTIAL_DIRECTORIES.has(part))
|
|
296
|
+
rest.split(sep).some((part) => CREDENTIAL_DIRECTORIES.has(part)) ||
|
|
297
|
+
// A `.private` path is never read (FEAT-005): a segment named or ending `.private`, or holding `.private.`.
|
|
298
|
+
path
|
|
299
|
+
.split(sep)
|
|
300
|
+
.some(
|
|
301
|
+
(part) => part === '.private' || part.endsWith('.private') || part.includes('.private.'),
|
|
302
|
+
)
|
|
297
303
|
);
|
|
298
304
|
}
|
|
299
305
|
|
|
@@ -221,7 +221,11 @@ export function extractCorrections(
|
|
|
221
221
|
return { corrections, secretsScrubbed };
|
|
222
222
|
}
|
|
223
223
|
|
|
224
|
-
|
|
224
|
+
/**
|
|
225
|
+
* Credentials by their own shape (a provider's token prefix, a key block): specific enough that a
|
|
226
|
+
* match is a secret. Foundry lifts these from a message even when the person forgot `$$` (FEAT-005).
|
|
227
|
+
*/
|
|
228
|
+
const SHAPED_SECRETS: ReadonlyArray<readonly [RegExp, string]> = [
|
|
225
229
|
[/sk-ant-[A-Za-z0-9_-]{20,}/g, '[REDACTED:anthropic-key]'],
|
|
226
230
|
[/sk-[A-Za-z0-9_-]{20,}/g, '[REDACTED:api-key]'],
|
|
227
231
|
[/gh[pousr]_[A-Za-z0-9]{20,}/g, '[REDACTED:github-token]'],
|
|
@@ -245,6 +249,10 @@ const SECRET_PATTERNS: ReadonlyArray<readonly [RegExp, string]> = [
|
|
|
245
249
|
],
|
|
246
250
|
[/hooks\.slack\.com\/services\/[A-Za-z0-9/]+/g, '[REDACTED:slack-webhook]'],
|
|
247
251
|
[/\bASIA[A-Z0-9]{16}/g, '[REDACTED:aws-key]'],
|
|
252
|
+
];
|
|
253
|
+
|
|
254
|
+
/** Credentials by context (an assignment, a header, a URL): a match may be a secret, so it is scrubbed but never lifted. */
|
|
255
|
+
const CONTEXT_SECRETS: ReadonlyArray<readonly [RegExp, string]> = [
|
|
248
256
|
[/\b(Bearer|Basic|DPoP)\s+[A-Za-z0-9._~+/=-]{16,}/g, '$1 [REDACTED:credential]'],
|
|
249
257
|
[/\b([a-z][a-z0-9+.-]*:\/\/[^\s:/@]+:)[^\s@/]+@/gi, '$1[REDACTED:password]@'],
|
|
250
258
|
[
|
|
@@ -257,6 +265,32 @@ const SECRET_PATTERNS: ReadonlyArray<readonly [RegExp, string]> = [
|
|
|
257
265
|
],
|
|
258
266
|
];
|
|
259
267
|
|
|
268
|
+
const SECRET_PATTERNS: ReadonlyArray<readonly [RegExp, string]> = [
|
|
269
|
+
...SHAPED_SECRETS,
|
|
270
|
+
...CONTEXT_SECRETS,
|
|
271
|
+
];
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* The shaped credentials safe to lift from a message the person forgot to mark: each never starts
|
|
275
|
+
* inside a word (`task-runner-…` holds `sk-…`), and the two loosest shapes (`sk-…` and
|
|
276
|
+
* `<word>_live_<…>`, which long hyphenated or snake_case names also fit) must carry a digit. Fresh
|
|
277
|
+
* regex objects, so lifting never shares match state with `scrubSecrets`. Scrubbing a false match is
|
|
278
|
+
* harmless; lifting one would take words out of the person's message.
|
|
279
|
+
*/
|
|
280
|
+
export const SHAPED_SECRET_PATTERNS: readonly RegExp[] = SHAPED_SECRETS.map(([pattern]) => {
|
|
281
|
+
const loose =
|
|
282
|
+
pattern.source.startsWith('sk-[') || pattern.source.includes('(?:live|test|prod|runtime)');
|
|
283
|
+
const digit = loose ? '(?=[A-Za-z0-9_-]*\\d)' : '';
|
|
284
|
+
return new RegExp(`(?<![A-Za-z0-9_-])${digit}(?:${pattern.source})`, pattern.flags);
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
/** How many credentials known only by context (`PASSWORD=…`, `Bearer …`, a URL password) the text holds. */
|
|
288
|
+
export function contextSecretHits(text: string): number {
|
|
289
|
+
let hits = 0;
|
|
290
|
+
for (const [pattern] of CONTEXT_SECRETS) hits += [...text.matchAll(pattern)].length;
|
|
291
|
+
return hits;
|
|
292
|
+
}
|
|
293
|
+
|
|
260
294
|
/** Replace credential-shaped substrings. Transcripts are exactly where leaked keys live. */
|
|
261
295
|
export function scrubSecrets(text: string): { text: string; hits: number } {
|
|
262
296
|
let hits = 0;
|
package/src/index.ts
CHANGED
|
@@ -186,6 +186,7 @@ export {
|
|
|
186
186
|
type CorrectionDetection,
|
|
187
187
|
type CorrectionEvent,
|
|
188
188
|
type CorrectionSignal,
|
|
189
|
+
contextSecretHits,
|
|
189
190
|
correctionClassifyMessages,
|
|
190
191
|
correctionId,
|
|
191
192
|
detectCorrection,
|
|
@@ -194,6 +195,7 @@ export {
|
|
|
194
195
|
type FeedbackTag,
|
|
195
196
|
parseCorrectionClassifications,
|
|
196
197
|
proseOf,
|
|
198
|
+
SHAPED_SECRET_PATTERNS,
|
|
197
199
|
scrubSecrets,
|
|
198
200
|
type TranscriptTurn,
|
|
199
201
|
} from './feedback/correction';
|
|
@@ -423,7 +425,6 @@ export {
|
|
|
423
425
|
type ThreadPlan,
|
|
424
426
|
type ThreadPlanItem,
|
|
425
427
|
type ThreadReference,
|
|
426
|
-
type ThreadSetup,
|
|
427
428
|
type ThreadSnooze,
|
|
428
429
|
type ThreadSpawn,
|
|
429
430
|
type ThreadStatus,
|
package/src/thread.ts
CHANGED
|
@@ -276,12 +276,6 @@ export interface ThreadMeta {
|
|
|
276
276
|
/** 1 for a child of a main thread. */
|
|
277
277
|
depth?: number;
|
|
278
278
|
|
|
279
|
-
/**
|
|
280
|
-
* Start-up of a thread whose Wardens are held in its own process (docs/THREAD-TREE.md spec C):
|
|
281
|
-
* turns typed meanwhile wait as `queued` until it is `ready` (or `degraded`).
|
|
282
|
-
*/
|
|
283
|
-
setup?: ThreadSetup;
|
|
284
|
-
|
|
285
279
|
/** Project that owns this thread. Scopes memory sources and tool calls. */
|
|
286
280
|
projectId?: string;
|
|
287
281
|
|
|
@@ -298,15 +292,6 @@ export interface ThreadMeta {
|
|
|
298
292
|
archivedAt?: number;
|
|
299
293
|
}
|
|
300
294
|
|
|
301
|
-
export interface ThreadSetup {
|
|
302
|
-
status: 'starting' | 'ready' | 'degraded';
|
|
303
|
-
startedAt: number;
|
|
304
|
-
readyAt?: number;
|
|
305
|
-
/** Every configured Warden, those holding a spare, and those that did not by the deadline. */
|
|
306
|
-
wardens: { expected: number; held: number; failed: string[] };
|
|
307
|
-
runtime: 'claude-in-session' | 'codex-in-process' | 'side-session';
|
|
308
|
-
}
|
|
309
|
-
|
|
310
295
|
export interface Dispatch<T = unknown> {
|
|
311
296
|
readonly agentId: string;
|
|
312
297
|
readonly timestamp: number;
|
package/src/types.ts
CHANGED
|
@@ -217,8 +217,6 @@ export interface LLMProvider {
|
|
|
217
217
|
* `threadPrefix` starts at once. `messages` end at those prefixes; no decision is made. Optional.
|
|
218
218
|
*/
|
|
219
219
|
prestart?(messages: LLMMessage[], opts: CompletionOpts): void;
|
|
220
|
-
/** A thread closed: release whatever the provider holds for it. Optional. */
|
|
221
|
-
releaseThread?(threadId: string): Promise<void>;
|
|
222
220
|
}
|
|
223
221
|
|
|
224
222
|
export interface EmbeddingProvider {
|