@sayknow-cli/coding-agent 0.3.7 → 0.3.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/types/append-only-mode.d.ts +31 -0
- package/dist/types/capability/rule.d.ts +8 -0
- package/dist/types/cli/completion-cli.d.ts +41 -0
- package/dist/types/cli/config-cli.d.ts +1 -0
- package/dist/types/cli/fixture-report.d.ts +20 -0
- package/dist/types/cli/fixture-report.test.d.ts +1 -0
- package/dist/types/cli/nofile-limit.d.ts +11 -0
- package/dist/types/cli/notify-cli.d.ts +7 -0
- package/dist/types/cli/update-cli.d.ts +22 -0
- package/dist/types/cli.d.ts +124 -1
- package/dist/types/commands/completion.d.ts +29 -0
- package/dist/types/commands/config.d.ts +3 -0
- package/dist/types/commands/deep-interview.d.ts +3 -0
- package/dist/types/config/file-lock.d.ts +7 -6
- package/dist/types/config/keybindings.d.ts +2 -2
- package/dist/types/config/model-profile-activation.d.ts +6 -0
- package/dist/types/config/model-profiles.d.ts +1 -0
- package/dist/types/config/settings-schema.d.ts +119 -1
- package/dist/types/config/settings.d.ts +8 -0
- package/dist/types/discovery/index.d.ts +1 -0
- package/dist/types/export/html/template.generated.d.ts +1 -1
- package/dist/types/export/ttsr.d.ts +14 -3
- package/dist/types/extensibility/extensions/runner.d.ts +2 -1
- package/dist/types/extensibility/extensions/types.d.ts +8 -0
- package/dist/types/goals/runtime.d.ts +1 -0
- package/dist/types/hooks/native-skill-hook.d.ts +12 -0
- package/dist/types/main.d.ts +4 -1
- package/dist/types/modes/components/assistant-message.d.ts +5 -1
- package/dist/types/modes/components/model-selector.d.ts +4 -0
- package/dist/types/modes/components/queued-message-selector.d.ts +12 -0
- package/dist/types/modes/components/settings-selector.d.ts +2 -0
- package/dist/types/modes/components/status-line.d.ts +9 -0
- package/dist/types/modes/components/thinking-selector.d.ts +2 -2
- package/dist/types/modes/controllers/command-controller.d.ts +1 -0
- package/dist/types/modes/controllers/event-controller.d.ts +5 -0
- package/dist/types/modes/controllers/input-controller.d.ts +1 -3
- package/dist/types/modes/controllers/selector-controller.d.ts +1 -0
- package/dist/types/modes/interactive-mode.d.ts +4 -0
- package/dist/types/modes/print-mode.d.ts +13 -1
- package/dist/types/modes/prompt-action-autocomplete.d.ts +1 -1
- package/dist/types/modes/rpc/rpc-mode.d.ts +1 -3
- package/dist/types/modes/rpc/rpc-socket-security.d.ts +3 -0
- package/dist/types/modes/rpc/rpc-types.d.ts +14 -0
- package/dist/types/modes/shared/agent-wire/event-contract.d.ts +19 -0
- package/dist/types/modes/shared/agent-wire/event-envelope.d.ts +23 -1
- package/dist/types/modes/types.d.ts +3 -0
- package/dist/types/modes/utils/injected-user-submission.d.ts +52 -0
- package/dist/types/modes/utils/ui-helpers.d.ts +1 -0
- package/dist/types/notifications/config-commands.d.ts +9 -0
- package/dist/types/notifications/config.d.ts +30 -1
- package/dist/types/notifications/daemon-paths.d.ts +1 -0
- package/dist/types/notifications/index.d.ts +8 -3
- package/dist/types/notifications/lifecycle-commands.d.ts +12 -3
- package/dist/types/notifications/lifecycle-control-runtime.d.ts +2 -1
- package/dist/types/notifications/reply-sent-store.d.ts +53 -0
- package/dist/types/notifications/rich-draft.d.ts +68 -0
- package/dist/types/notifications/rich-render.d.ts +90 -0
- package/dist/types/notifications/telegram-daemon.d.ts +45 -3
- package/dist/types/notifications/telegram-reference.d.ts +7 -5
- package/dist/types/notifications/threaded-render.d.ts +14 -0
- package/dist/types/runtime-api-key.d.ts +7 -0
- package/dist/types/sdk.d.ts +3 -0
- package/dist/types/session/agent-session.d.ts +61 -6
- package/dist/types/session/agent-storage.d.ts +1 -0
- package/dist/types/session/file-mention-pruning.d.ts +8 -0
- package/dist/types/session/messages.d.ts +4 -0
- package/dist/types/session/session-manager.d.ts +17 -1
- package/dist/types/skc-runtime/deep-interview-ambiguity.d.ts +39 -0
- package/dist/types/skc-runtime/deep-interview-recorder.d.ts +10 -1
- package/dist/types/skc-runtime/deep-interview-state.d.ts +17 -2
- package/dist/types/skc-runtime/session-state-sidecar.d.ts +7 -0
- package/dist/types/skc-runtime/state-writer.d.ts +3 -0
- package/dist/types/skc-runtime/tmux-common.d.ts +1 -0
- package/dist/types/skc-runtime/ultragoal-receipt-freshness.d.ts +42 -0
- package/dist/types/skc-runtime/ultragoal-runtime.d.ts +120 -13
- package/dist/types/skill-state/active-state.d.ts +18 -1
- package/dist/types/system-prompt.d.ts +18 -2
- package/dist/types/task/executor.d.ts +3 -0
- package/dist/types/task/fork-context-budget.d.ts +7 -0
- package/dist/types/task/token-log.d.ts +30 -0
- package/dist/types/task/token-log.test.d.ts +1 -0
- package/dist/types/tools/bisect.d.ts +81 -0
- package/dist/types/tools/computer.d.ts +2 -2
- package/dist/types/tools/index.d.ts +1 -0
- package/dist/types/tools/search.d.ts +2 -2
- package/dist/types/tools/ultragoal-ask-guard.d.ts +9 -2
- package/dist/types/utils/file-mentions.d.ts +14 -0
- package/dist/types/utils/git.d.ts +32 -0
- package/dist/types/utils/pasted-image-path.d.ts +30 -0
- package/dist/types/web/scrapers/youtube.d.ts +8 -0
- package/dist/types/workflow/workflow-intent-diff.d.ts +8 -2
- package/dist/types/workflow/workflow-intent-report-consumer.d.ts +50 -0
- package/dist/types/workflow/workflow-intent-report-schema.d.ts +2 -0
- package/dist/types/workflow/workflow-intent-report.d.ts +48 -0
- package/package.json +8 -8
- package/src/append-only-mode.ts +58 -0
- package/src/autoresearch/prompt.md +1 -1
- package/src/autoresearch/tools/log-experiment.ts +1 -1
- package/src/capability/rule.ts +9 -0
- package/src/cli/completion-cli.ts +234 -0
- package/src/cli/config-cli.ts +61 -9
- package/src/cli/fast-help.ts +1 -0
- package/src/cli/fixture-report.test.ts +230 -0
- package/src/cli/fixture-report.ts +171 -0
- package/src/cli/nofile-limit.ts +48 -0
- package/src/cli/notify-cli.ts +103 -17
- package/src/cli/telegram-cli.ts +1 -1
- package/src/cli/update-cli.ts +148 -33
- package/src/cli.ts +29 -1
- package/src/commands/completion.ts +84 -0
- package/src/commands/config.ts +2 -0
- package/src/commands/contribution-prep.ts +1 -1
- package/src/commands/deep-interview.ts +2 -1
- package/src/config/file-lock.ts +73 -34
- package/src/config/keybindings.ts +3 -3
- package/src/config/model-profile-activation.ts +65 -0
- package/src/config/model-profiles.ts +31 -2
- package/src/config/settings-schema.ts +76 -1
- package/src/config/settings.ts +22 -0
- package/src/defaults/skc/skills/team/SKILL.md +17 -14
- package/src/defaults/skc/skills/ultragoal/SKILL.md +59 -4
- package/src/defaults/skc/skills/ultragoal/pipeline-validation-contracts.md +30 -0
- package/src/defaults/skc-defaults.ts +9 -0
- package/src/discovery/helpers.ts +10 -0
- package/src/discovery/index.ts +1 -0
- package/src/export/html/template.generated.ts +1 -1
- package/src/export/html/template.js +60 -2
- package/src/export/ttsr.ts +96 -18
- package/src/extensibility/extensions/runner.ts +183 -219
- package/src/extensibility/extensions/types.ts +9 -0
- package/src/extensibility/skc-plugins/runtime-adapters.ts +156 -44
- package/src/goals/runtime.ts +10 -2
- package/src/hindsight/backend.ts +1 -3
- package/src/hooks/native-skill-hook.ts +124 -4
- package/src/internal-urls/docs-index.generated.ts +17 -8
- package/src/lsp/client.ts +1 -0
- package/src/main.ts +95 -43
- package/src/memories/index.ts +12 -1
- package/src/modes/components/assistant-message.ts +241 -82
- package/src/modes/components/custom-editor.ts +1 -0
- package/src/modes/components/footer.ts +7 -2
- package/src/modes/components/model-selector.ts +54 -11
- package/src/modes/components/queued-message-selector.ts +92 -0
- package/src/modes/components/settings-selector.ts +4 -0
- package/src/modes/components/status-line.ts +167 -54
- package/src/modes/components/thinking-selector.ts +10 -8
- package/src/modes/components/tool-execution.ts +44 -19
- package/src/modes/components/welcome.ts +181 -44
- package/src/modes/controllers/command-controller.ts +40 -4
- package/src/modes/controllers/event-controller.ts +77 -49
- package/src/modes/controllers/extension-ui-controller.ts +12 -11
- package/src/modes/controllers/input-controller.ts +192 -35
- package/src/modes/controllers/selector-controller.ts +168 -24
- package/src/modes/interactive-mode.ts +56 -16
- package/src/modes/print-mode.ts +43 -4
- package/src/modes/prompt-action-autocomplete.ts +21 -20
- package/src/modes/rpc/rpc-mode.ts +32 -12
- package/src/modes/rpc/rpc-socket-security.ts +13 -1
- package/src/modes/rpc/rpc-types.ts +9 -0
- package/src/modes/shared/agent-wire/command-validation.ts +4 -0
- package/src/modes/shared/agent-wire/event-contract.ts +22 -0
- package/src/modes/shared/agent-wire/event-envelope.ts +82 -0
- package/src/modes/shared/agent-wire/scopes.ts +1 -0
- package/src/modes/types.ts +3 -0
- package/src/modes/utils/hotkeys-markdown.ts +1 -0
- package/src/modes/utils/injected-user-submission.ts +94 -0
- package/src/modes/utils/ui-helpers.ts +20 -7
- package/src/notifications/config-commands.ts +20 -0
- package/src/notifications/config.ts +52 -5
- package/src/notifications/daemon-paths.ts +2 -0
- package/src/notifications/index.ts +144 -18
- package/src/notifications/lifecycle-commands.ts +74 -23
- package/src/notifications/lifecycle-control-runtime.ts +8 -3
- package/src/notifications/lifecycle-orchestrator.ts +19 -6
- package/src/notifications/reply-sent-store.ts +134 -0
- package/src/notifications/rich-draft.ts +107 -0
- package/src/notifications/rich-render.ts +142 -0
- package/src/notifications/telegram-daemon-control.ts +5 -3
- package/src/notifications/telegram-daemon.ts +606 -98
- package/src/notifications/telegram-reference.ts +17 -16
- package/src/notifications/threaded-render.ts +45 -2
- package/src/prompts/agents/architect.md +19 -10
- package/src/prompts/agents/critic.md +16 -18
- package/src/prompts/agents/executor.md +14 -11
- package/src/prompts/agents/planner.md +18 -13
- package/src/prompts/ci-green-request.md +3 -8
- package/src/prompts/goals/goal-continuation.md +0 -5
- package/src/prompts/goals/goal-mode-active.md +0 -5
- package/src/prompts/system/agent-creation-architect.md +2 -2
- package/src/prompts/system/plan-mode-active.md +1 -1
- package/src/prompts/system/plan-mode-subagent.md +3 -3
- package/src/prompts/system/project-prompt.md +0 -13
- package/src/prompts/system/subagent-system-prompt.md +3 -2
- package/src/prompts/system/system-prompt.md +29 -17
- package/src/prompts/system/volatile-project-context.md +10 -0
- package/src/prompts/system/web-search.md +4 -7
- package/src/prompts/tools/apply-patch.md +6 -0
- package/src/prompts/tools/ast-edit.md +1 -0
- package/src/prompts/tools/bash.md +1 -1
- package/src/prompts/tools/bisect.md +22 -0
- package/src/prompts/tools/browser.md +1 -1
- package/src/prompts/tools/computer.md +2 -2
- package/src/prompts/tools/cron.md +0 -2
- package/src/prompts/tools/eval.md +2 -2
- package/src/prompts/tools/find.md +1 -1
- package/src/prompts/tools/github.md +6 -6
- package/src/prompts/tools/goal.md +1 -3
- package/src/prompts/tools/image-gen.md +12 -5
- package/src/prompts/tools/irc.md +5 -4
- package/src/prompts/tools/job.md +2 -2
- package/src/prompts/tools/lsp.md +1 -1
- package/src/prompts/tools/monitor.md +2 -2
- package/src/prompts/tools/patch.md +2 -2
- package/src/prompts/tools/replace.md +2 -21
- package/src/prompts/tools/rewind.md +1 -1
- package/src/prompts/tools/search-tool-bm25.md +6 -11
- package/src/prompts/tools/search.md +1 -1
- package/src/prompts/tools/skill.md +3 -2
- package/src/prompts/tools/ssh.md +2 -1
- package/src/prompts/tools/subagent.md +2 -2
- package/src/prompts/tools/task.md +4 -5
- package/src/prompts/tools/todo-write.md +1 -1
- package/src/prompts/tools/vim.md +1 -0
- package/src/prompts/tools/web-search.md +2 -0
- package/src/prompts/tools/write.md +8 -2
- package/src/runtime-api-key.ts +16 -0
- package/src/sdk.ts +88 -36
- package/src/session/agent-session.ts +1013 -141
- package/src/session/agent-storage.ts +4 -0
- package/src/session/file-mention-pruning.ts +64 -0
- package/src/session/messages.ts +4 -0
- package/src/session/session-manager.ts +103 -4
- package/src/skc-runtime/deep-interview-ambiguity.ts +206 -0
- package/src/skc-runtime/deep-interview-recorder.ts +62 -8
- package/src/skc-runtime/deep-interview-state.ts +44 -2
- package/src/skc-runtime/session-state-sidecar.ts +263 -20
- package/src/skc-runtime/state-runtime.ts +12 -2
- package/src/skc-runtime/state-writer.ts +15 -0
- package/src/skc-runtime/tmux-common.ts +1 -0
- package/src/skc-runtime/ultragoal-guard.ts +55 -66
- package/src/skc-runtime/ultragoal-receipt-freshness.ts +315 -0
- package/src/skc-runtime/ultragoal-runtime.ts +1672 -159
- package/src/skc-runtime/workflow-manifest.generated.json +113 -2
- package/src/skc-runtime/workflow-manifest.ts +74 -1
- package/src/skill-state/active-state.ts +141 -5
- package/src/skill-state/deep-interview-mutation-guard.ts +67 -3
- package/src/slash-commands/builtin-registry.ts +296 -72
- package/src/system-prompt.ts +57 -16
- package/src/task/executor.ts +132 -24
- package/src/task/fork-context-advisory.ts +2 -7
- package/src/task/fork-context-budget.ts +9 -0
- package/src/task/index.ts +13 -6
- package/src/task/output-manager.ts +20 -8
- package/src/task/receipt.ts +26 -7
- package/src/task/token-log.test.ts +188 -0
- package/src/task/token-log.ts +179 -0
- package/src/tools/bisect.ts +367 -0
- package/src/tools/computer.ts +246 -43
- package/src/tools/index.ts +3 -0
- package/src/tools/output-meta.ts +116 -4
- package/src/tools/search.ts +8 -2
- package/src/tools/skill.ts +15 -0
- package/src/tools/telegram-send.ts +6 -0
- package/src/tools/ultragoal-ask-guard.ts +39 -5
- package/src/utils/file-mentions.ts +39 -7
- package/src/utils/git.ts +73 -0
- package/src/utils/pasted-image-path.ts +170 -0
- package/src/web/scrapers/youtube.ts +24 -12
- package/src/workflow/workflow-intent-diff.ts +29 -6
- package/src/workflow/workflow-intent-report-consumer.ts +221 -0
- package/src/workflow/workflow-intent-report-schema.ts +129 -0
- package/src/workflow/workflow-intent-report.ts +135 -0
|
@@ -2008,12 +2008,50 @@
|
|
|
2008
2008
|
// INITIALIZATION
|
|
2009
2009
|
// ============================================================
|
|
2010
2010
|
|
|
2011
|
-
// Escape HTML tags in text
|
|
2011
|
+
// Escape raw HTML tags in markdown text while keeping markdown/code rendering.
|
|
2012
2012
|
function escapeHtmlTags(text) {
|
|
2013
2013
|
return text.replace(/<(?=[a-zA-Z\/])/g, '<');
|
|
2014
2014
|
}
|
|
2015
2015
|
|
|
2016
|
-
|
|
2016
|
+
function sanitizeMarkdownUrl(href) {
|
|
2017
|
+
const value = String(href || '').trim();
|
|
2018
|
+
if (!value) return '';
|
|
2019
|
+
|
|
2020
|
+
// Collapse whitespace/control characters before scheme checks so
|
|
2021
|
+
// variants like "java\nscript:" cannot bypass the allowlist.
|
|
2022
|
+
const compact = value.replace(/[\u0000-\u001F\u007F\s]+/g, '');
|
|
2023
|
+
// Browser URL parsing treats backslashes in leading path separators as
|
|
2024
|
+
// network-path separators; Marked may pass them through or encode them.
|
|
2025
|
+
if (compact.includes('\\') || /%5c/i.test(compact)) return null;
|
|
2026
|
+
|
|
2027
|
+
const colonIndex = compact.indexOf(':');
|
|
2028
|
+
const firstPathIndex = compact.search(/[/?#]/);
|
|
2029
|
+
if (colonIndex !== -1 && (firstPathIndex === -1 || colonIndex < firstPathIndex)) {
|
|
2030
|
+
const scheme = compact.slice(0, colonIndex).toLowerCase();
|
|
2031
|
+
if (scheme === 'http' || scheme === 'https' || scheme === 'mailto' || scheme === 'tel') {
|
|
2032
|
+
return value;
|
|
2033
|
+
}
|
|
2034
|
+
return null;
|
|
2035
|
+
}
|
|
2036
|
+
|
|
2037
|
+
if (compact.startsWith('//')) return null;
|
|
2038
|
+
return value;
|
|
2039
|
+
}
|
|
2040
|
+
|
|
2041
|
+
function renderAttribute(name, value) {
|
|
2042
|
+
return value ? ` ${name}="${escapeHtml(value)}"` : '';
|
|
2043
|
+
}
|
|
2044
|
+
|
|
2045
|
+
function renderUnsafeLinkText(tokens, href) {
|
|
2046
|
+
const text = this.parser.parseInline(tokens);
|
|
2047
|
+
return href ? `${text} (${escapeHtml(href)})` : text;
|
|
2048
|
+
}
|
|
2049
|
+
|
|
2050
|
+
function renderUnsafeImageText(text, href) {
|
|
2051
|
+
return href ? `})` : `![${escapeHtml(text)}]`;
|
|
2052
|
+
}
|
|
2053
|
+
|
|
2054
|
+
// Configure marked with syntax highlighting and raw HTML escaping
|
|
2017
2055
|
marked.use({
|
|
2018
2056
|
breaks: true,
|
|
2019
2057
|
gfm: true,
|
|
@@ -2043,9 +2081,29 @@
|
|
|
2043
2081
|
text(token) {
|
|
2044
2082
|
return escapeHtmlTags(escapeHtml(token.text));
|
|
2045
2083
|
},
|
|
2084
|
+
// Raw HTML: render as text, never as executable DOM
|
|
2085
|
+
html(token) {
|
|
2086
|
+
return escapeHtml(token.raw || token.text || '');
|
|
2087
|
+
},
|
|
2046
2088
|
// Inline code: escape HTML
|
|
2047
2089
|
codespan(token) {
|
|
2048
2090
|
return `<code>${escapeHtml(token.text)}</code>`;
|
|
2091
|
+
},
|
|
2092
|
+
link(token) {
|
|
2093
|
+
const href = token.href || '';
|
|
2094
|
+
const sanitizedHref = sanitizeMarkdownUrl(href);
|
|
2095
|
+
if (sanitizedHref === null) {
|
|
2096
|
+
return renderUnsafeLinkText.call(this, token.tokens || [], href);
|
|
2097
|
+
}
|
|
2098
|
+
return `<a href="${escapeHtml(sanitizedHref)}"${renderAttribute('title', token.title)}>${this.parser.parseInline(token.tokens || [])}</a>`;
|
|
2099
|
+
},
|
|
2100
|
+
image(token) {
|
|
2101
|
+
const href = token.href || '';
|
|
2102
|
+
const sanitizedHref = sanitizeMarkdownUrl(href);
|
|
2103
|
+
if (sanitizedHref === null) {
|
|
2104
|
+
return renderUnsafeImageText(token.text || '', href);
|
|
2105
|
+
}
|
|
2106
|
+
return `<img src="${escapeHtml(sanitizedHref)}" alt="${escapeHtml(token.text || '')}"${renderAttribute('title', token.title)}>`;
|
|
2049
2107
|
}
|
|
2050
2108
|
}
|
|
2051
2109
|
});
|
package/src/export/ttsr.ts
CHANGED
|
@@ -38,14 +38,25 @@ interface TtsrScope {
|
|
|
38
38
|
interface TtsrEntry {
|
|
39
39
|
rule: Rule;
|
|
40
40
|
conditions: RegExp[];
|
|
41
|
+
conditionWindows: Array<number | undefined>;
|
|
42
|
+
|
|
41
43
|
scope: TtsrScope;
|
|
42
44
|
globalPathGlobs?: Bun.Glob[];
|
|
43
45
|
}
|
|
44
46
|
|
|
45
47
|
/** Tracks when a rule was last injected (for repeat gating). */
|
|
48
|
+
export interface TtsrInjectionRecord {
|
|
49
|
+
name: string;
|
|
50
|
+
lastInjectedAt: number;
|
|
51
|
+
repeatMode?: "once" | "after-gap";
|
|
52
|
+
repeatGap?: number;
|
|
53
|
+
}
|
|
54
|
+
|
|
46
55
|
interface InjectionRecord {
|
|
47
56
|
/** Message count (turn index) when the rule was last injected. */
|
|
48
57
|
lastInjectedAt: number;
|
|
58
|
+
repeatMode?: "once" | "after-gap";
|
|
59
|
+
repeatGap?: number;
|
|
49
60
|
}
|
|
50
61
|
|
|
51
62
|
const DEFAULT_SETTINGS: Required<TtsrSettings> = {
|
|
@@ -56,6 +67,9 @@ const DEFAULT_SETTINGS: Required<TtsrSettings> = {
|
|
|
56
67
|
repeatGap: 10,
|
|
57
68
|
};
|
|
58
69
|
|
|
70
|
+
const SAFE_REGEX_WINDOW_CAP = 4096;
|
|
71
|
+
const SAFE_REGEX_WINDOW_MULTIPLIER = 4;
|
|
72
|
+
|
|
59
73
|
const DEFAULT_SCOPE: TtsrScope = {
|
|
60
74
|
allowText: true,
|
|
61
75
|
allowThinking: false,
|
|
@@ -70,7 +84,7 @@ export class TtsrManager {
|
|
|
70
84
|
readonly #buffers = new Map<string, string>();
|
|
71
85
|
#messageCount = 0;
|
|
72
86
|
|
|
73
|
-
constructor(settings?: TtsrSettings) {
|
|
87
|
+
constructor(settings?: Partial<TtsrSettings>) {
|
|
74
88
|
this.#settings = { ...DEFAULT_SETTINGS, ...settings };
|
|
75
89
|
}
|
|
76
90
|
|
|
@@ -81,12 +95,15 @@ export class TtsrManager {
|
|
|
81
95
|
return true;
|
|
82
96
|
}
|
|
83
97
|
|
|
84
|
-
|
|
98
|
+
const entry = this.#rules.get(ruleName);
|
|
99
|
+
const repeatMode = entry?.rule.repeatMode ?? record.repeatMode ?? this.#settings.repeatMode;
|
|
100
|
+
if (repeatMode === "once") {
|
|
85
101
|
return false;
|
|
86
102
|
}
|
|
87
103
|
|
|
104
|
+
const repeatGap = entry?.rule.repeatGap ?? record.repeatGap ?? this.#settings.repeatGap;
|
|
88
105
|
const gap = this.#messageCount - record.lastInjectedAt;
|
|
89
|
-
return gap >=
|
|
106
|
+
return gap >= repeatGap;
|
|
90
107
|
}
|
|
91
108
|
|
|
92
109
|
#compileConditions(rule: Rule): RegExp[] {
|
|
@@ -106,6 +123,20 @@ export class TtsrManager {
|
|
|
106
123
|
return compiled;
|
|
107
124
|
}
|
|
108
125
|
|
|
126
|
+
#conditionWindow(condition: RegExp): number | undefined {
|
|
127
|
+
const source = condition.source;
|
|
128
|
+
if (source.length === 0 || source.length > SAFE_REGEX_WINDOW_CAP) {
|
|
129
|
+
return undefined;
|
|
130
|
+
}
|
|
131
|
+
// Quantifiers (*, +, {n,}) and anchors/lookaround/backrefs can make a match's
|
|
132
|
+
// witness exceed a bounded window, so fall back to full-buffer scanning (always
|
|
133
|
+
// correct) for those patterns rather than risk silently missing a match.
|
|
134
|
+
if (/[$^*+{]|\\[bBAZz]|\\[1-9]|\(\?/.test(source)) {
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
137
|
+
return Math.min(SAFE_REGEX_WINDOW_CAP, Math.max(1, source.length * SAFE_REGEX_WINDOW_MULTIPLIER));
|
|
138
|
+
}
|
|
139
|
+
|
|
109
140
|
#compileGlobalPathGlobs(globs: Rule["globs"]): Bun.Glob[] | undefined {
|
|
110
141
|
if (!globs || globs.length === 0) {
|
|
111
142
|
return undefined;
|
|
@@ -281,17 +312,28 @@ export class TtsrManager {
|
|
|
281
312
|
}
|
|
282
313
|
|
|
283
314
|
#matchesCondition(entry: TtsrEntry, streamBuffer: string): boolean {
|
|
284
|
-
for (
|
|
315
|
+
for (let i = 0; i < entry.conditions.length; i++) {
|
|
316
|
+
const condition = entry.conditions[i];
|
|
317
|
+
const window = entry.conditionWindows[i];
|
|
318
|
+
const target = window === undefined ? streamBuffer : streamBuffer.slice(-window);
|
|
285
319
|
condition.lastIndex = 0;
|
|
286
|
-
if (condition.test(
|
|
320
|
+
if (condition.test(target)) {
|
|
287
321
|
return true;
|
|
288
322
|
}
|
|
289
323
|
}
|
|
290
324
|
return false;
|
|
291
325
|
}
|
|
292
326
|
|
|
327
|
+
/** Check if TTSR is disabled for this manager. */
|
|
328
|
+
#isDisabled(): boolean {
|
|
329
|
+
return this.#settings.enabled === false;
|
|
330
|
+
}
|
|
331
|
+
|
|
293
332
|
/** Add a TTSR rule to be monitored. */
|
|
294
333
|
addRule(rule: Rule): boolean {
|
|
334
|
+
if (this.#isDisabled()) {
|
|
335
|
+
return false;
|
|
336
|
+
}
|
|
295
337
|
if (this.#rules.has(rule.name)) {
|
|
296
338
|
return false;
|
|
297
339
|
}
|
|
@@ -310,9 +352,11 @@ export class TtsrManager {
|
|
|
310
352
|
return false;
|
|
311
353
|
}
|
|
312
354
|
const globalPathGlobs = this.#compileGlobalPathGlobs(rule.globs);
|
|
355
|
+
const conditionWindows = conditions.map(condition => this.#conditionWindow(condition));
|
|
313
356
|
this.#rules.set(rule.name, {
|
|
314
357
|
rule,
|
|
315
358
|
conditions,
|
|
359
|
+
conditionWindows,
|
|
316
360
|
scope,
|
|
317
361
|
globalPathGlobs,
|
|
318
362
|
});
|
|
@@ -334,6 +378,9 @@ export class TtsrManager {
|
|
|
334
378
|
* assistant prose, thinking text, and unrelated tool argument streams.
|
|
335
379
|
*/
|
|
336
380
|
checkDelta(delta: string, context: TtsrMatchContext): Rule[] {
|
|
381
|
+
if (this.#isDisabled()) {
|
|
382
|
+
return [];
|
|
383
|
+
}
|
|
337
384
|
const bufferKey = this.#bufferKey(context);
|
|
338
385
|
const nextBuffer = `${this.#buffers.get(bufferKey) ?? ""}${delta}`;
|
|
339
386
|
this.#buffers.set(bufferKey, nextBuffer);
|
|
@@ -378,16 +425,18 @@ export class TtsrManager {
|
|
|
378
425
|
if (ruleName.length === 0) {
|
|
379
426
|
continue;
|
|
380
427
|
}
|
|
381
|
-
const
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
}
|
|
428
|
+
const entry = this.#rules.get(ruleName);
|
|
429
|
+
const nextRecord: InjectionRecord = {
|
|
430
|
+
lastInjectedAt: this.#messageCount,
|
|
431
|
+
repeatMode: entry?.rule.repeatMode ?? this.#settings.repeatMode,
|
|
432
|
+
repeatGap: entry?.rule.repeatGap ?? this.#settings.repeatGap,
|
|
433
|
+
};
|
|
434
|
+
this.#injectionRecords.set(ruleName, nextRecord);
|
|
435
|
+
|
|
387
436
|
logger.debug("TTSR rule marked as injected", {
|
|
388
437
|
ruleName,
|
|
389
438
|
messageCount: this.#messageCount,
|
|
390
|
-
repeatMode:
|
|
439
|
+
repeatMode: nextRecord.repeatMode,
|
|
391
440
|
});
|
|
392
441
|
}
|
|
393
442
|
}
|
|
@@ -397,13 +446,31 @@ export class TtsrManager {
|
|
|
397
446
|
return Array.from(this.#injectionRecords.keys());
|
|
398
447
|
}
|
|
399
448
|
|
|
400
|
-
/**
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
449
|
+
/** Get full injected rule records (for persistence). */
|
|
450
|
+
getInjectedRecords(): TtsrInjectionRecord[] {
|
|
451
|
+
return Array.from(this.#injectionRecords, ([name, record]) => ({ name, ...record }));
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/** Restore injected state from legacy rule names or persisted records. */
|
|
455
|
+
restoreInjected(records: string[] | TtsrInjectionRecord[]): void {
|
|
456
|
+
if (this.#isDisabled()) {
|
|
457
|
+
return;
|
|
404
458
|
}
|
|
405
|
-
|
|
406
|
-
|
|
459
|
+
for (const record of records) {
|
|
460
|
+
if (typeof record === "string") {
|
|
461
|
+
this.#injectionRecords.set(record, { lastInjectedAt: 0 });
|
|
462
|
+
continue;
|
|
463
|
+
}
|
|
464
|
+
const name = record.name.trim();
|
|
465
|
+
if (name.length === 0) continue;
|
|
466
|
+
this.#injectionRecords.set(name, {
|
|
467
|
+
lastInjectedAt: Number.isFinite(record.lastInjectedAt) ? record.lastInjectedAt : 0,
|
|
468
|
+
repeatMode: record.repeatMode,
|
|
469
|
+
repeatGap: record.repeatGap,
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
if (records.length > 0) {
|
|
473
|
+
logger.debug("TTSR injected state restored", { records });
|
|
407
474
|
}
|
|
408
475
|
}
|
|
409
476
|
|
|
@@ -414,6 +481,9 @@ export class TtsrManager {
|
|
|
414
481
|
|
|
415
482
|
/** Check if any TTSR rules are registered. */
|
|
416
483
|
hasRules(): boolean {
|
|
484
|
+
if (this.#isDisabled()) {
|
|
485
|
+
return false;
|
|
486
|
+
}
|
|
417
487
|
return this.#rules.size > 0;
|
|
418
488
|
}
|
|
419
489
|
|
|
@@ -427,6 +497,14 @@ export class TtsrManager {
|
|
|
427
497
|
return this.#messageCount;
|
|
428
498
|
}
|
|
429
499
|
|
|
500
|
+
/** Restore message counter after session resume. */
|
|
501
|
+
restoreMessageCount(messageCount: number): void {
|
|
502
|
+
if (this.#isDisabled()) {
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
this.#messageCount = Math.max(0, Math.floor(messageCount));
|
|
506
|
+
}
|
|
507
|
+
|
|
430
508
|
/** Get settings. */
|
|
431
509
|
getSettings(): Required<TtsrSettings> {
|
|
432
510
|
return this.#settings;
|