@sayknow-cli/coding-agent 0.5.2 → 0.5.6
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/CHANGELOG.md +55 -16
- package/dist/types/cli/update-cli.d.ts +8 -1
- package/dist/types/config/atomic-yaml-patch.d.ts +20 -1
- package/dist/types/config/keybindings.d.ts +10 -0
- package/dist/types/config/model-registry.d.ts +1 -1
- package/dist/types/config/models-config-schema.d.ts +4 -0
- package/dist/types/config/settings-schema.d.ts +9 -0
- package/dist/types/dap/client.d.ts +1 -0
- package/dist/types/lsp/client.d.ts +5 -0
- package/dist/types/modes/components/welcome.d.ts +1 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +3 -1
- package/dist/types/modes/interactive-mode.d.ts +13 -1
- package/dist/types/modes/types.d.ts +7 -1
- package/dist/types/runtime-mcp/transports/stdio.d.ts +2 -0
- package/dist/types/session/agent-session.d.ts +8 -0
- package/dist/types/session/internal/managed-session-scope.d.ts +3 -1
- package/dist/types/session/internal/managed-session-storage.d.ts +2 -0
- package/dist/types/session/session-manager.d.ts +9 -0
- package/dist/types/session/session-storage.d.ts +17 -0
- package/dist/types/session-import/claude.d.ts +26 -0
- package/dist/types/session-import/codex.d.ts +22 -0
- package/dist/types/session-import/command.d.ts +20 -0
- package/dist/types/session-import/detect.d.ts +22 -0
- package/dist/types/session-import/index.d.ts +7 -0
- package/dist/types/session-import/redact.d.ts +23 -0
- package/dist/types/session-import/service.d.ts +28 -0
- package/dist/types/session-import/types.d.ts +125 -0
- package/dist/types/skc-runtime/launch-worktree.d.ts +17 -1
- package/dist/types/slash-commands/builtin-registry.d.ts +4 -0
- package/dist/types/slash-commands/types.d.ts +5 -0
- package/dist/types/tools/ask.d.ts +5 -0
- package/package.json +13 -7
- package/scripts/generate-sdk-operation-inventory.ts +5 -6
- package/src/cli/config-cli.ts +23 -8
- package/src/cli/update-cli.ts +265 -21
- package/src/config/atomic-yaml-patch.ts +167 -30
- package/src/config/keybindings.ts +10 -0
- package/src/config/model-profiles.ts +69 -1
- package/src/config/model-registry.ts +60 -38
- package/src/config/models-config-schema.ts +1 -1
- package/src/config/settings-schema.ts +9 -0
- package/src/config/settings.ts +13 -2
- package/src/dap/client.ts +78 -30
- package/src/internal-urls/docs-index.generated.ts +5 -4
- package/src/lsp/client.ts +17 -29
- package/src/modes/action-registry.ts +2 -0
- package/src/modes/components/welcome.ts +5 -0
- package/src/modes/controllers/goal-mode-controller.ts +7 -2
- package/src/modes/controllers/input-controller.ts +71 -6
- package/src/modes/controllers/plan-mode-controller.ts +8 -1
- package/src/modes/controllers/runtime-mcp-command-controller.ts +14 -0
- package/src/modes/controllers/selector-controller.ts +47 -19
- package/src/modes/interactive-mode.ts +54 -4
- package/src/modes/types.ts +5 -1
- package/src/runtime-mcp/transports/stdio.ts +96 -33
- package/src/sdk/broker/lifecycle.ts +6 -5
- package/src/sdk/protocol/operation-inventory.generated.json +33 -0
- package/src/sdk/session.ts +25 -18
- package/src/session/agent-session.ts +89 -14
- package/src/session/internal/managed-session-scope.ts +41 -6
- package/src/session/internal/managed-session-storage.ts +14 -0
- package/src/session/session-manager.ts +113 -11
- package/src/session/session-storage.ts +70 -0
- package/src/session-import/claude.ts +382 -0
- package/src/session-import/codex.ts +458 -0
- package/src/session-import/command.ts +61 -0
- package/src/session-import/detect.ts +133 -0
- package/src/session-import/index.ts +27 -0
- package/src/session-import/redact.ts +125 -0
- package/src/session-import/service.ts +749 -0
- package/src/session-import/types.ts +163 -0
- package/src/skc-runtime/launch-worktree.ts +277 -4
- package/src/slash-commands/acp-builtins.ts +5 -1
- package/src/slash-commands/builtin-registry.ts +100 -1
- package/src/slash-commands/types.ts +5 -0
- package/src/tools/ask.ts +5 -0
- package/src/export/html/template.css +0 -1060
- package/src/export/html/template.html +0 -47
- package/src/export/html/template.js +0 -2348
- package/vendor/insane-search/engine/tests/test_hardening.py +0 -57
- package/vendor/insane-search/engine/tests/test_smoke.py +0 -152
- package/vendor/insane-search/engine/tests/test_u1.py +0 -200
- package/vendor/insane-search/engine/tests/test_u4.py +0 -131
- package/vendor/insane-search/engine/tests/test_u5.py +0 -163
- package/vendor/insane-search/engine/tests/test_u7.py +0 -124
- package/vendor/insane-search/engine/tests/test_u8.py +0 -216
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fail-closed secret redaction for imported session content (issue #3709).
|
|
3
|
+
*
|
|
4
|
+
* Every string that crosses the import boundary passes through
|
|
5
|
+
* {@link redactImportedText}. Patterns are conservative: a false positive costs
|
|
6
|
+
* one `[REDACTED]` span in reconstructed context, a false negative leaks a
|
|
7
|
+
* credential into a new session transcript, so the balance favors redaction.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export const IMPORT_REDACTED_PLACEHOLDER = "[REDACTED]";
|
|
11
|
+
/** Bumped when patterns change; persisted in import provenance. */
|
|
12
|
+
export const IMPORT_SANITIZER_VERSION = 3;
|
|
13
|
+
|
|
14
|
+
interface RedactionRule {
|
|
15
|
+
readonly id: string;
|
|
16
|
+
readonly pattern: RegExp;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const HEX = "[0-9a-fA-F]";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Ordered first-match-wins rules. Each rule replaces its full match with the
|
|
23
|
+
* placeholder, so a matched credential never survives partially.
|
|
24
|
+
*/
|
|
25
|
+
const REDACTION_RULES: readonly RedactionRule[] = [
|
|
26
|
+
// PEM private-key blocks, header through footer.
|
|
27
|
+
{
|
|
28
|
+
id: "pem-private-key",
|
|
29
|
+
pattern: /-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z0-9 ]*PRIVATE KEY-----/g,
|
|
30
|
+
},
|
|
31
|
+
// AWS access key ids.
|
|
32
|
+
{ id: "aws-access-key", pattern: /(?:AKIA|ASIA|ABIA|ACCA)[0-9A-Z]{16}/g },
|
|
33
|
+
// Standalone AWS secret access keys are 40 mixed-case base64 characters.
|
|
34
|
+
{
|
|
35
|
+
id: "aws-secret-key",
|
|
36
|
+
pattern: /(?<![A-Za-z0-9+/])[A-Za-z0-9+/]{40}(?![A-Za-z0-9+/])/g,
|
|
37
|
+
},
|
|
38
|
+
// GitHub tokens (PAT, OAuth, server-to-server, refresh, fine-grained).
|
|
39
|
+
{ id: "github-token", pattern: /(?:ghp|gho|ghu|ghs|ghr|github_pat)_[A-Za-z0-9_]{20,}/g },
|
|
40
|
+
// Anthropic API keys.
|
|
41
|
+
{ id: "anthropic-key", pattern: /sk-ant-[A-Za-z0-9_-]{20,}/g },
|
|
42
|
+
// OpenAI-style keys (project keys, service accounts, legacy sk-).
|
|
43
|
+
{ id: "openai-key", pattern: /sk-(?:proj|svcacct|admin)-[A-Za-z0-9_-]{20,}|sk-[A-Za-z0-9]{20,}/g },
|
|
44
|
+
// Slack tokens.
|
|
45
|
+
{ id: "slack-token", pattern: /xox[baprs]-[A-Za-z0-9-]{10,}/g },
|
|
46
|
+
// Google API keys.
|
|
47
|
+
{ id: "google-api-key", pattern: /AIza[0-9A-Za-z_-]{35}/g },
|
|
48
|
+
// Common standalone provider credentials that are not always labeled.
|
|
49
|
+
{ id: "gitlab-token", pattern: /glpat-[A-Za-z0-9_-]{16,}/g },
|
|
50
|
+
{ id: "npm-token", pattern: /npm_[A-Za-z0-9]{20,}/g },
|
|
51
|
+
{ id: "google-oauth-token", pattern: /ya29\.[A-Za-z0-9_-]{16,}/g },
|
|
52
|
+
{ id: "stripe-live-key", pattern: /(?:sk|rk)_live_[A-Za-z0-9]{16,}/g },
|
|
53
|
+
// Authorization values in headers, JSON, YAML, or diagnostic output.
|
|
54
|
+
{
|
|
55
|
+
id: "authorization-credential",
|
|
56
|
+
pattern: /\bauthorization\b(["']?\s*[:=]\s*)("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|[^\r\n,}]{4,})/gi,
|
|
57
|
+
},
|
|
58
|
+
// Bearer tokens carried in Authorization text.
|
|
59
|
+
{
|
|
60
|
+
id: "bearer-token",
|
|
61
|
+
pattern: /(authorization["'\s]*[:=]["'\s]*bearer\s+|bearer\s+)[A-Za-z0-9._~+/=-]{12,}/gi,
|
|
62
|
+
},
|
|
63
|
+
// JWTs (three base64url segments; middle segment non-trivial).
|
|
64
|
+
{
|
|
65
|
+
id: "jwt",
|
|
66
|
+
pattern: /eyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}/g,
|
|
67
|
+
},
|
|
68
|
+
// Long hex secrets (64+ hex chars: webhook secrets, signing keys).
|
|
69
|
+
{ id: "hex-secret", pattern: new RegExp(`\\b${HEX}{64,}\\b`, "g") },
|
|
70
|
+
// Basic-auth credentials embedded in URLs (https://user:pass@host).
|
|
71
|
+
{ id: "url-credential", pattern: /([a-z][a-z0-9+.-]*:\/\/)[^/\s:@]{1,256}:[^/\s@]{1,256}@/gi },
|
|
72
|
+
// Sensitive env/KEY assignments: OPENAI_API_KEY=..., token: ..., password = ...
|
|
73
|
+
// The name prefix is optional so a bare sensitive name (`password: …`) also matches.
|
|
74
|
+
{
|
|
75
|
+
id: "secret-assignment",
|
|
76
|
+
pattern:
|
|
77
|
+
/\b(?:[A-Za-z_][A-Za-z0-9_]*)?(?:api[_-]?key|secret|token|password|passwd|credential|client[_-]?secret|private[_-]?key|access[_-]?key|refresh[_-]?token|session[_-]?key)[A-Za-z0-9_]*\b(["']?\s*[:=]\s*)("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|[^\s,;}&)]{4,})/gi,
|
|
78
|
+
},
|
|
79
|
+
];
|
|
80
|
+
|
|
81
|
+
export interface ImportRedactionResult {
|
|
82
|
+
value: string;
|
|
83
|
+
redacted: number;
|
|
84
|
+
kinds: string[];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Redact every known credential shape from imported text. The same placeholder
|
|
89
|
+
* is used for all kinds so a partial pattern overlap cannot leak fragments.
|
|
90
|
+
*/
|
|
91
|
+
export function redactImportedText(input: string): ImportRedactionResult {
|
|
92
|
+
let value = input;
|
|
93
|
+
let redacted = 0;
|
|
94
|
+
const kinds = new Set<string>();
|
|
95
|
+
for (const rule of REDACTION_RULES) {
|
|
96
|
+
rule.pattern.lastIndex = 0;
|
|
97
|
+
value = value.replace(rule.pattern, match => {
|
|
98
|
+
redacted++;
|
|
99
|
+
kinds.add(rule.id);
|
|
100
|
+
if (rule.id === "url-credential") {
|
|
101
|
+
// Keep the scheme visible; the match ends at "@" so the host survives.
|
|
102
|
+
const schemeEnd = match.indexOf("://") + 3;
|
|
103
|
+
return `${match.slice(0, schemeEnd)}${IMPORT_REDACTED_PLACEHOLDER}@`;
|
|
104
|
+
}
|
|
105
|
+
if (rule.id === "secret-assignment" || rule.id === "authorization-credential") {
|
|
106
|
+
const sep = /(["']?\s*[:=]\s*)/.exec(match);
|
|
107
|
+
if (sep) {
|
|
108
|
+
const head = match.slice(0, (sep.index ?? 0) + sep[0].length);
|
|
109
|
+
return `${head}${IMPORT_REDACTED_PLACEHOLDER}`;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (rule.id === "bearer-token") {
|
|
113
|
+
const bearerAt = /bearer\s+/i.exec(match);
|
|
114
|
+
if (bearerAt) return `${match.slice(0, bearerAt.index + bearerAt[0].length)}${IMPORT_REDACTED_PLACEHOLDER}`;
|
|
115
|
+
}
|
|
116
|
+
return IMPORT_REDACTED_PLACEHOLDER;
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
return { value, redacted, kinds: [...kinds].sort() };
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** Redact a string, returning only the sanitized value. */
|
|
123
|
+
export function sanitizeImportedString(input: string): string {
|
|
124
|
+
return redactImportedText(input).value;
|
|
125
|
+
}
|