@scotthamilton77/sidekick 0.1.15 → 0.1.16
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/assets/sidekick/defaults/features/reminders.defaults.yaml +28 -0
- package/dist/bin.js +116 -18
- package/dist/daemon.js +115 -17
- package/package.json +1 -1
|
@@ -18,6 +18,34 @@ settings:
|
|
|
18
18
|
user-prompt-submit: 10
|
|
19
19
|
remember-your-persona: 5
|
|
20
20
|
|
|
21
|
+
# Command runner prefixes that trigger unanchored pattern matching.
|
|
22
|
+
# When a bash command starts with one of these prefixes, the tool pattern
|
|
23
|
+
# matcher drops its first-token anchor and scans for the tool name at any
|
|
24
|
+
# position. This allows commands like 'uv run mypy' to match pattern 'mypy'.
|
|
25
|
+
# Array merge strategy: replace (project/user config replaces defaults entirely).
|
|
26
|
+
command_runners:
|
|
27
|
+
# Python
|
|
28
|
+
- prefix: "uv run"
|
|
29
|
+
- prefix: "poetry run"
|
|
30
|
+
- prefix: "pipx run"
|
|
31
|
+
- prefix: "pdm run"
|
|
32
|
+
- prefix: "hatch run"
|
|
33
|
+
- prefix: "conda run"
|
|
34
|
+
# Node.js
|
|
35
|
+
- prefix: "npx"
|
|
36
|
+
- prefix: "pnpx"
|
|
37
|
+
- prefix: "bunx"
|
|
38
|
+
- prefix: "pnpm dlx"
|
|
39
|
+
- prefix: "pnpm exec"
|
|
40
|
+
- prefix: "bun run"
|
|
41
|
+
- prefix: "yarn dlx"
|
|
42
|
+
- prefix: "yarn exec"
|
|
43
|
+
- prefix: "npm exec"
|
|
44
|
+
# Ruby
|
|
45
|
+
- prefix: "bundle exec"
|
|
46
|
+
# .NET
|
|
47
|
+
- prefix: "dotnet tool run"
|
|
48
|
+
|
|
21
49
|
# Glob patterns that trigger verify-completion reminder on file edit.
|
|
22
50
|
# Uses picomatch syntax: https://github.com/micromatch/picomatch
|
|
23
51
|
# Only edits to files matching these patterns will stage the reminder.
|
package/dist/bin.js
CHANGED
|
@@ -71535,7 +71535,7 @@ var require_types2 = __commonJS({
|
|
|
71535
71535
|
"../feature-reminders/dist/types.js"(exports2) {
|
|
71536
71536
|
"use strict";
|
|
71537
71537
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
71538
|
-
exports2.ALL_VC_REMINDER_IDS = exports2.VC_TOOL_REMINDER_IDS = exports2.TOOL_REMINDER_MAP = exports2.ReminderIds = exports2.DEFAULT_REMINDERS_SETTINGS = exports2.DEFAULT_COMPLETION_DETECTION_SETTINGS = exports2.DEFAULT_SOURCE_CODE_PATTERNS = exports2.DEFAULT_VERIFICATION_TOOLS = exports2.VerificationToolsMapSchema = exports2.VerificationToolConfigSchema = exports2.ToolPatternSchema = exports2.ToolPatternScopeSchema = void 0;
|
|
71538
|
+
exports2.ALL_VC_REMINDER_IDS = exports2.VC_TOOL_REMINDER_IDS = exports2.TOOL_REMINDER_MAP = exports2.ReminderIds = exports2.DEFAULT_REMINDERS_SETTINGS = exports2.DEFAULT_COMPLETION_DETECTION_SETTINGS = exports2.DEFAULT_SOURCE_CODE_PATTERNS = exports2.DEFAULT_VERIFICATION_TOOLS = exports2.CommandRunnerSchema = exports2.VerificationToolsMapSchema = exports2.VerificationToolConfigSchema = exports2.ToolPatternSchema = exports2.ToolPatternScopeSchema = void 0;
|
|
71539
71539
|
var zod_1 = require_zod2();
|
|
71540
71540
|
exports2.ToolPatternScopeSchema = zod_1.z.enum(["project", "package", "file"]);
|
|
71541
71541
|
exports2.ToolPatternSchema = zod_1.z.object({
|
|
@@ -71550,6 +71550,9 @@ var require_types2 = __commonJS({
|
|
|
71550
71550
|
clearing_patterns: zod_1.z.array(zod_1.z.string()).min(1)
|
|
71551
71551
|
});
|
|
71552
71552
|
exports2.VerificationToolsMapSchema = zod_1.z.record(zod_1.z.string(), exports2.VerificationToolConfigSchema);
|
|
71553
|
+
exports2.CommandRunnerSchema = zod_1.z.object({
|
|
71554
|
+
prefix: zod_1.z.string().trim().min(1)
|
|
71555
|
+
});
|
|
71553
71556
|
exports2.DEFAULT_VERIFICATION_TOOLS = {
|
|
71554
71557
|
build: {
|
|
71555
71558
|
enabled: true,
|
|
@@ -71738,7 +71741,30 @@ var require_types2 = __commonJS({
|
|
|
71738
71741
|
reminder_thresholds: {
|
|
71739
71742
|
"user-prompt-submit": 10,
|
|
71740
71743
|
"remember-your-persona": 5
|
|
71741
|
-
}
|
|
71744
|
+
},
|
|
71745
|
+
command_runners: [
|
|
71746
|
+
// Python
|
|
71747
|
+
{ prefix: "uv run" },
|
|
71748
|
+
{ prefix: "poetry run" },
|
|
71749
|
+
{ prefix: "pipx run" },
|
|
71750
|
+
{ prefix: "pdm run" },
|
|
71751
|
+
{ prefix: "hatch run" },
|
|
71752
|
+
{ prefix: "conda run" },
|
|
71753
|
+
// Node.js
|
|
71754
|
+
{ prefix: "npx" },
|
|
71755
|
+
{ prefix: "pnpx" },
|
|
71756
|
+
{ prefix: "bunx" },
|
|
71757
|
+
{ prefix: "pnpm dlx" },
|
|
71758
|
+
{ prefix: "pnpm exec" },
|
|
71759
|
+
{ prefix: "bun run" },
|
|
71760
|
+
{ prefix: "yarn dlx" },
|
|
71761
|
+
{ prefix: "yarn exec" },
|
|
71762
|
+
{ prefix: "npm exec" },
|
|
71763
|
+
// Ruby
|
|
71764
|
+
{ prefix: "bundle exec" },
|
|
71765
|
+
// .NET
|
|
71766
|
+
{ prefix: "dotnet tool run" }
|
|
71767
|
+
]
|
|
71742
71768
|
};
|
|
71743
71769
|
exports2.ReminderIds = {
|
|
71744
71770
|
USER_PROMPT_SUBMIT: "user-prompt-submit",
|
|
@@ -71970,6 +71996,16 @@ var require_stage_default_user_prompt = __commonJS({
|
|
|
71970
71996
|
continue;
|
|
71971
71997
|
const newCount = typedEntry.messagesSinceLastStaging + 1;
|
|
71972
71998
|
if (newCount >= threshold) {
|
|
71999
|
+
(0, core_1.logEvent)(handlerCtx.logger, types_1.DecisionEvents.decisionRecorded({ sessionId }, {
|
|
72000
|
+
decision: "staged",
|
|
72001
|
+
reason: [
|
|
72002
|
+
`message count reached threshold (${newCount}/${threshold})`,
|
|
72003
|
+
`target hook: ${typedEntry.targetHook}`,
|
|
72004
|
+
`messages since last staging: ${typedEntry.messagesSinceLastStaging}`
|
|
72005
|
+
].join("; "),
|
|
72006
|
+
subsystem: "reminder-throttle",
|
|
72007
|
+
title: `Re-stage ${reminderId} reminder`
|
|
72008
|
+
}));
|
|
71973
72009
|
const metrics = event.metadata.metrics;
|
|
71974
72010
|
const stagedAt = {
|
|
71975
72011
|
timestamp: Date.now(),
|
|
@@ -71981,12 +72017,6 @@ var require_stage_default_user_prompt = __commonJS({
|
|
|
71981
72017
|
...typedEntry.cachedReminder,
|
|
71982
72018
|
stagedAt
|
|
71983
72019
|
});
|
|
71984
|
-
(0, core_1.logEvent)(handlerCtx.logger, types_1.DecisionEvents.decisionRecorded({ sessionId }, {
|
|
71985
|
-
decision: "staged",
|
|
71986
|
-
reason: `message count reached threshold (${newCount}/${threshold})`,
|
|
71987
|
-
subsystem: "user-prompt-reminders",
|
|
71988
|
-
title: "Stage user-prompt reminder"
|
|
71989
|
-
}));
|
|
71990
72020
|
state[reminderId] = { ...typedEntry, messagesSinceLastStaging: 0 };
|
|
71991
72021
|
handlerCtx.logger.debug("Throttle: re-staged reminder", {
|
|
71992
72022
|
sessionId,
|
|
@@ -72036,6 +72066,9 @@ var require_events2 = __commonJS({
|
|
|
72036
72066
|
blocking: state.blocking,
|
|
72037
72067
|
priority: state.priority,
|
|
72038
72068
|
persistent: state.persistent,
|
|
72069
|
+
...state.renderedText !== void 0 && {
|
|
72070
|
+
renderedText: state.renderedText
|
|
72071
|
+
},
|
|
72039
72072
|
...state.classificationResult !== void 0 && {
|
|
72040
72073
|
classificationResult: state.classificationResult
|
|
72041
72074
|
}
|
|
@@ -73727,17 +73760,51 @@ var require_tool_pattern_matcher = __commonJS({
|
|
|
73727
73760
|
exports2.matchesToolPattern = matchesToolPattern;
|
|
73728
73761
|
exports2.findMatchingPattern = findMatchingPattern;
|
|
73729
73762
|
var SHELL_OPERATOR_RE = /\s*(?:&&|\|\||[;|])\s*/;
|
|
73730
|
-
function
|
|
73763
|
+
function detectRunnerPrefix(segmentTokens, runners) {
|
|
73764
|
+
let longestMatch = 0;
|
|
73765
|
+
for (const runner of runners) {
|
|
73766
|
+
if (typeof runner.prefix !== "string")
|
|
73767
|
+
continue;
|
|
73768
|
+
const prefixTokens = runner.prefix.trim().split(/\s+/);
|
|
73769
|
+
if (prefixTokens.length === 0)
|
|
73770
|
+
continue;
|
|
73771
|
+
if (prefixTokens.length > segmentTokens.length)
|
|
73772
|
+
continue;
|
|
73773
|
+
let matches = true;
|
|
73774
|
+
for (let i = 0; i < prefixTokens.length; i++) {
|
|
73775
|
+
if (segmentTokens[i] !== prefixTokens[i]) {
|
|
73776
|
+
matches = false;
|
|
73777
|
+
break;
|
|
73778
|
+
}
|
|
73779
|
+
}
|
|
73780
|
+
if (matches && prefixTokens.length > longestMatch) {
|
|
73781
|
+
longestMatch = prefixTokens.length;
|
|
73782
|
+
}
|
|
73783
|
+
}
|
|
73784
|
+
return longestMatch;
|
|
73785
|
+
}
|
|
73786
|
+
function matchesToolPattern(command, pattern, runners) {
|
|
73731
73787
|
if (!command || !pattern)
|
|
73732
73788
|
return false;
|
|
73733
73789
|
const segments = command.split(SHELL_OPERATOR_RE);
|
|
73734
73790
|
const patternTokens = pattern.trim().split(/\s+/).filter(Boolean);
|
|
73735
73791
|
if (patternTokens.length === 0)
|
|
73736
73792
|
return false;
|
|
73793
|
+
const activeRunners = runners?.length ? runners : void 0;
|
|
73737
73794
|
return segments.some((segment) => {
|
|
73738
73795
|
const cmdTokens = segment.trim().split(/\s+/);
|
|
73739
73796
|
if (cmdTokens.length === 0 || cmdTokens[0] === "")
|
|
73740
73797
|
return false;
|
|
73798
|
+
const runnerTokenCount = activeRunners ? detectRunnerPrefix(cmdTokens, activeRunners) : 0;
|
|
73799
|
+
if (runnerTokenCount > 0) {
|
|
73800
|
+
let pi2 = 0;
|
|
73801
|
+
for (let ci = runnerTokenCount; ci < cmdTokens.length && pi2 < patternTokens.length; ci++) {
|
|
73802
|
+
if (patternTokens[pi2] === "*" || patternTokens[pi2] === cmdTokens[ci]) {
|
|
73803
|
+
pi2++;
|
|
73804
|
+
}
|
|
73805
|
+
}
|
|
73806
|
+
return pi2 === patternTokens.length;
|
|
73807
|
+
}
|
|
73741
73808
|
if (cmdTokens[0] !== patternTokens[0])
|
|
73742
73809
|
return false;
|
|
73743
73810
|
let pi = 1;
|
|
@@ -73749,11 +73816,11 @@ var require_tool_pattern_matcher = __commonJS({
|
|
|
73749
73816
|
return pi === patternTokens.length;
|
|
73750
73817
|
});
|
|
73751
73818
|
}
|
|
73752
|
-
function findMatchingPattern(command, patterns) {
|
|
73819
|
+
function findMatchingPattern(command, patterns, runners) {
|
|
73753
73820
|
for (const pattern of patterns) {
|
|
73754
73821
|
if (pattern.tool === null)
|
|
73755
73822
|
continue;
|
|
73756
|
-
if (matchesToolPattern(command, pattern.tool))
|
|
73823
|
+
if (matchesToolPattern(command, pattern.tool, runners))
|
|
73757
73824
|
return pattern;
|
|
73758
73825
|
}
|
|
73759
73826
|
return null;
|
|
@@ -73809,13 +73876,14 @@ var require_track_verification_tools = __commonJS({
|
|
|
73809
73876
|
const featureConfig = context.config.getFeature("reminders");
|
|
73810
73877
|
const config = { ...types_js_1.DEFAULT_REMINDERS_SETTINGS, ...featureConfig.settings };
|
|
73811
73878
|
const verificationTools = config.verification_tools ?? {};
|
|
73879
|
+
const runners = config.command_runners ?? [];
|
|
73812
73880
|
const remindersState = (0, state_js_1.createRemindersState)(daemonCtx.stateService);
|
|
73813
73881
|
const stateResult = await remindersState.verificationTools.read(sessionId);
|
|
73814
73882
|
const toolsState = { ...stateResult.data };
|
|
73815
73883
|
if (FILE_EDIT_TOOLS.includes(toolName)) {
|
|
73816
73884
|
await handleFileEdit(event, daemonCtx, sessionId, verificationTools, toolsState, remindersState);
|
|
73817
73885
|
} else if (toolName === "Bash") {
|
|
73818
|
-
await handleBashCommand(event, daemonCtx, sessionId, verificationTools, toolsState, remindersState);
|
|
73886
|
+
await handleBashCommand(event, daemonCtx, sessionId, verificationTools, toolsState, remindersState, runners);
|
|
73819
73887
|
}
|
|
73820
73888
|
}
|
|
73821
73889
|
});
|
|
@@ -73937,7 +74005,7 @@ var require_track_verification_tools = __commonJS({
|
|
|
73937
74005
|
return;
|
|
73938
74006
|
await stageToolsForFiles([filePath], daemonCtx, sessionId, verificationTools, toolsState, remindersState);
|
|
73939
74007
|
}
|
|
73940
|
-
async function handleBashCommand(event, daemonCtx, sessionId, verificationTools, toolsState, remindersState) {
|
|
74008
|
+
async function handleBashCommand(event, daemonCtx, sessionId, verificationTools, toolsState, remindersState, runners = []) {
|
|
73941
74009
|
const command = extractToolInput(event)?.command;
|
|
73942
74010
|
if (!command)
|
|
73943
74011
|
return;
|
|
@@ -73948,7 +74016,7 @@ var require_track_verification_tools = __commonJS({
|
|
|
73948
74016
|
const reminderId = types_js_1.TOOL_REMINDER_MAP[toolName];
|
|
73949
74017
|
if (!reminderId)
|
|
73950
74018
|
continue;
|
|
73951
|
-
const match = (0, tool_pattern_matcher_js_1.findMatchingPattern)(command, toolConfig.patterns);
|
|
74019
|
+
const match = (0, tool_pattern_matcher_js_1.findMatchingPattern)(command, toolConfig.patterns, runners);
|
|
73952
74020
|
if (!match)
|
|
73953
74021
|
continue;
|
|
73954
74022
|
toolsState[toolName] = {
|
|
@@ -74764,6 +74832,12 @@ var require_consumption_handler_factory = __commonJS({
|
|
|
74764
74832
|
if (onConsume) {
|
|
74765
74833
|
await onConsume({ reminder: primary, reader, cliCtx, sessionId });
|
|
74766
74834
|
}
|
|
74835
|
+
const renderedParts = [];
|
|
74836
|
+
if (response.userMessage)
|
|
74837
|
+
renderedParts.push(response.userMessage);
|
|
74838
|
+
if (response.additionalContext)
|
|
74839
|
+
renderedParts.push(response.additionalContext);
|
|
74840
|
+
const renderedText = renderedParts.length > 0 ? renderedParts.join("\n\n") : void 0;
|
|
74767
74841
|
(0, core_1.logEvent)(cliCtx.logger, events_js_1.ReminderEvents.reminderConsumed({
|
|
74768
74842
|
sessionId,
|
|
74769
74843
|
hook
|
|
@@ -74773,6 +74847,7 @@ var require_consumption_handler_factory = __commonJS({
|
|
|
74773
74847
|
blocking: response.blocking ?? false,
|
|
74774
74848
|
priority: primary.priority,
|
|
74775
74849
|
persistent: primary.persistent,
|
|
74850
|
+
renderedText,
|
|
74776
74851
|
...enrichment
|
|
74777
74852
|
}));
|
|
74778
74853
|
return { response };
|
|
@@ -77149,6 +77224,7 @@ var require_update_summary = __commonJS({
|
|
|
77149
77224
|
"use strict";
|
|
77150
77225
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
77151
77226
|
exports2.buildPersonaContext = void 0;
|
|
77227
|
+
exports2.resetAnalysisGuard = resetAnalysisGuard;
|
|
77152
77228
|
exports2.interpolateTemplate = interpolateTemplate;
|
|
77153
77229
|
exports2.updateSessionSummary = updateSessionSummary;
|
|
77154
77230
|
var core_1 = require_dist4();
|
|
@@ -77161,6 +77237,7 @@ var require_update_summary = __commonJS({
|
|
|
77161
77237
|
var persona_selection_js_1 = require_persona_selection();
|
|
77162
77238
|
var DECISION_TITLE_SKIP = "Skip session analysis";
|
|
77163
77239
|
var DECISION_TITLE_RUN = "Run session analysis";
|
|
77240
|
+
var analysisInFlight = /* @__PURE__ */ new Map();
|
|
77164
77241
|
var PROMPT_FILE = "prompts/session-summary.prompt.txt";
|
|
77165
77242
|
var SNARKY_PROMPT_FILE = "prompts/snarky-message.prompt.txt";
|
|
77166
77243
|
var RESUME_PROMPT_FILE = "prompts/resume-message.prompt.txt";
|
|
@@ -77178,6 +77255,9 @@ var require_update_summary = __commonJS({
|
|
|
77178
77255
|
Object.defineProperty(exports2, "buildPersonaContext", { enumerable: true, get: function() {
|
|
77179
77256
|
return persona_utils_js_2.buildPersonaContext;
|
|
77180
77257
|
} });
|
|
77258
|
+
function resetAnalysisGuard() {
|
|
77259
|
+
analysisInFlight.clear();
|
|
77260
|
+
}
|
|
77181
77261
|
function interpolateTemplate(template, context) {
|
|
77182
77262
|
let result = template;
|
|
77183
77263
|
const conditionalRegex = /\{\{#if\s+(\w+)\}\}([\s\S]*?)\{\{\/if\}\}/g;
|
|
@@ -77221,12 +77301,12 @@ var require_update_summary = __commonJS({
|
|
|
77221
77301
|
}
|
|
77222
77302
|
(0, core_1.logEvent)(ctx.logger, types_1.DecisionEvents.decisionRecorded(event.context, {
|
|
77223
77303
|
decision: "calling",
|
|
77224
|
-
reason: "
|
|
77304
|
+
reason: "Bulk transcript replay complete \u2014 running catch-up analysis",
|
|
77225
77305
|
subsystem: "session-summary",
|
|
77226
77306
|
title: DECISION_TITLE_RUN
|
|
77227
77307
|
}));
|
|
77228
77308
|
const countdown2 = await loadCountdownState(summaryState, sessionId);
|
|
77229
|
-
void performAnalysis(event, ctx, summaryState, countdown2, "
|
|
77309
|
+
void performAnalysis(event, ctx, summaryState, countdown2, "bulk_replay_complete");
|
|
77230
77310
|
return;
|
|
77231
77311
|
}
|
|
77232
77312
|
const countdown = await loadCountdownState(summaryState, sessionId);
|
|
@@ -77241,7 +77321,7 @@ var require_update_summary = __commonJS({
|
|
|
77241
77321
|
}
|
|
77242
77322
|
(0, core_1.logEvent)(ctx.logger, types_1.DecisionEvents.decisionRecorded(event.context, {
|
|
77243
77323
|
decision: "calling",
|
|
77244
|
-
reason: "countdown reached zero
|
|
77324
|
+
reason: "Prompt countdown reached zero \u2014 running scheduled analysis",
|
|
77245
77325
|
subsystem: "session-summary",
|
|
77246
77326
|
title: DECISION_TITLE_RUN
|
|
77247
77327
|
}));
|
|
@@ -77276,6 +77356,17 @@ var require_update_summary = __commonJS({
|
|
|
77276
77356
|
}
|
|
77277
77357
|
async function performAnalysis(event, ctx, summaryState, countdown, reason) {
|
|
77278
77358
|
const { sessionId } = event.context;
|
|
77359
|
+
if (analysisInFlight.has(sessionId)) {
|
|
77360
|
+
analysisInFlight.set(sessionId, true);
|
|
77361
|
+
(0, core_1.logEvent)(ctx.logger, types_1.DecisionEvents.decisionRecorded(event.context, {
|
|
77362
|
+
decision: "deferred",
|
|
77363
|
+
reason: "Analysis deferred \u2014 will rerun after current analysis completes",
|
|
77364
|
+
subsystem: "session-summary",
|
|
77365
|
+
title: DECISION_TITLE_SKIP
|
|
77366
|
+
}));
|
|
77367
|
+
return;
|
|
77368
|
+
}
|
|
77369
|
+
analysisInFlight.set(sessionId, false);
|
|
77279
77370
|
try {
|
|
77280
77371
|
const startTime = Date.now();
|
|
77281
77372
|
(0, core_1.logEvent)(ctx.logger, events_js_1.SessionSummaryEvents.summaryStart(event.context, {
|
|
@@ -77420,6 +77511,13 @@ var require_update_summary = __commonJS({
|
|
|
77420
77511
|
reason,
|
|
77421
77512
|
error: err instanceof Error ? err.message : String(err)
|
|
77422
77513
|
});
|
|
77514
|
+
} finally {
|
|
77515
|
+
const rerunPending = analysisInFlight.get(sessionId) ?? false;
|
|
77516
|
+
analysisInFlight.delete(sessionId);
|
|
77517
|
+
if (rerunPending) {
|
|
77518
|
+
const freshCountdown = await loadCountdownState(summaryState, sessionId);
|
|
77519
|
+
void performAnalysis(event, ctx, summaryState, freshCountdown, reason);
|
|
77520
|
+
}
|
|
77423
77521
|
}
|
|
77424
77522
|
}
|
|
77425
77523
|
async function loadCurrentSummary(summaryState, sessionId) {
|
|
@@ -83915,7 +84013,7 @@ var require_cli = __commonJS({
|
|
|
83915
84013
|
var promises_12 = require("node:fs/promises");
|
|
83916
84014
|
var node_stream_1 = require("node:stream");
|
|
83917
84015
|
var yargs_parser_1 = __importDefault2(require_build());
|
|
83918
|
-
var VERSION = true ? "0.1.
|
|
84016
|
+
var VERSION = true ? "0.1.16" : "dev";
|
|
83919
84017
|
var SANDBOX_ERROR_MESSAGE = `Error: Daemon commands cannot run in sandbox mode.
|
|
83920
84018
|
|
|
83921
84019
|
Claude Code's sandbox blocks Unix socket operations required for daemon IPC.
|
package/dist/daemon.js
CHANGED
|
@@ -70382,7 +70382,7 @@ var require_types2 = __commonJS({
|
|
|
70382
70382
|
"../feature-reminders/dist/types.js"(exports2) {
|
|
70383
70383
|
"use strict";
|
|
70384
70384
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
70385
|
-
exports2.ALL_VC_REMINDER_IDS = exports2.VC_TOOL_REMINDER_IDS = exports2.TOOL_REMINDER_MAP = exports2.ReminderIds = exports2.DEFAULT_REMINDERS_SETTINGS = exports2.DEFAULT_COMPLETION_DETECTION_SETTINGS = exports2.DEFAULT_SOURCE_CODE_PATTERNS = exports2.DEFAULT_VERIFICATION_TOOLS = exports2.VerificationToolsMapSchema = exports2.VerificationToolConfigSchema = exports2.ToolPatternSchema = exports2.ToolPatternScopeSchema = void 0;
|
|
70385
|
+
exports2.ALL_VC_REMINDER_IDS = exports2.VC_TOOL_REMINDER_IDS = exports2.TOOL_REMINDER_MAP = exports2.ReminderIds = exports2.DEFAULT_REMINDERS_SETTINGS = exports2.DEFAULT_COMPLETION_DETECTION_SETTINGS = exports2.DEFAULT_SOURCE_CODE_PATTERNS = exports2.DEFAULT_VERIFICATION_TOOLS = exports2.CommandRunnerSchema = exports2.VerificationToolsMapSchema = exports2.VerificationToolConfigSchema = exports2.ToolPatternSchema = exports2.ToolPatternScopeSchema = void 0;
|
|
70386
70386
|
var zod_1 = require_zod2();
|
|
70387
70387
|
exports2.ToolPatternScopeSchema = zod_1.z.enum(["project", "package", "file"]);
|
|
70388
70388
|
exports2.ToolPatternSchema = zod_1.z.object({
|
|
@@ -70397,6 +70397,9 @@ var require_types2 = __commonJS({
|
|
|
70397
70397
|
clearing_patterns: zod_1.z.array(zod_1.z.string()).min(1)
|
|
70398
70398
|
});
|
|
70399
70399
|
exports2.VerificationToolsMapSchema = zod_1.z.record(zod_1.z.string(), exports2.VerificationToolConfigSchema);
|
|
70400
|
+
exports2.CommandRunnerSchema = zod_1.z.object({
|
|
70401
|
+
prefix: zod_1.z.string().trim().min(1)
|
|
70402
|
+
});
|
|
70400
70403
|
exports2.DEFAULT_VERIFICATION_TOOLS = {
|
|
70401
70404
|
build: {
|
|
70402
70405
|
enabled: true,
|
|
@@ -70585,7 +70588,30 @@ var require_types2 = __commonJS({
|
|
|
70585
70588
|
reminder_thresholds: {
|
|
70586
70589
|
"user-prompt-submit": 10,
|
|
70587
70590
|
"remember-your-persona": 5
|
|
70588
|
-
}
|
|
70591
|
+
},
|
|
70592
|
+
command_runners: [
|
|
70593
|
+
// Python
|
|
70594
|
+
{ prefix: "uv run" },
|
|
70595
|
+
{ prefix: "poetry run" },
|
|
70596
|
+
{ prefix: "pipx run" },
|
|
70597
|
+
{ prefix: "pdm run" },
|
|
70598
|
+
{ prefix: "hatch run" },
|
|
70599
|
+
{ prefix: "conda run" },
|
|
70600
|
+
// Node.js
|
|
70601
|
+
{ prefix: "npx" },
|
|
70602
|
+
{ prefix: "pnpx" },
|
|
70603
|
+
{ prefix: "bunx" },
|
|
70604
|
+
{ prefix: "pnpm dlx" },
|
|
70605
|
+
{ prefix: "pnpm exec" },
|
|
70606
|
+
{ prefix: "bun run" },
|
|
70607
|
+
{ prefix: "yarn dlx" },
|
|
70608
|
+
{ prefix: "yarn exec" },
|
|
70609
|
+
{ prefix: "npm exec" },
|
|
70610
|
+
// Ruby
|
|
70611
|
+
{ prefix: "bundle exec" },
|
|
70612
|
+
// .NET
|
|
70613
|
+
{ prefix: "dotnet tool run" }
|
|
70614
|
+
]
|
|
70589
70615
|
};
|
|
70590
70616
|
exports2.ReminderIds = {
|
|
70591
70617
|
USER_PROMPT_SUBMIT: "user-prompt-submit",
|
|
@@ -70817,6 +70843,16 @@ var require_stage_default_user_prompt = __commonJS({
|
|
|
70817
70843
|
continue;
|
|
70818
70844
|
const newCount = typedEntry.messagesSinceLastStaging + 1;
|
|
70819
70845
|
if (newCount >= threshold) {
|
|
70846
|
+
(0, core_1.logEvent)(handlerCtx.logger, types_1.DecisionEvents.decisionRecorded({ sessionId }, {
|
|
70847
|
+
decision: "staged",
|
|
70848
|
+
reason: [
|
|
70849
|
+
`message count reached threshold (${newCount}/${threshold})`,
|
|
70850
|
+
`target hook: ${typedEntry.targetHook}`,
|
|
70851
|
+
`messages since last staging: ${typedEntry.messagesSinceLastStaging}`
|
|
70852
|
+
].join("; "),
|
|
70853
|
+
subsystem: "reminder-throttle",
|
|
70854
|
+
title: `Re-stage ${reminderId} reminder`
|
|
70855
|
+
}));
|
|
70820
70856
|
const metrics = event.metadata.metrics;
|
|
70821
70857
|
const stagedAt = {
|
|
70822
70858
|
timestamp: Date.now(),
|
|
@@ -70828,12 +70864,6 @@ var require_stage_default_user_prompt = __commonJS({
|
|
|
70828
70864
|
...typedEntry.cachedReminder,
|
|
70829
70865
|
stagedAt
|
|
70830
70866
|
});
|
|
70831
|
-
(0, core_1.logEvent)(handlerCtx.logger, types_1.DecisionEvents.decisionRecorded({ sessionId }, {
|
|
70832
|
-
decision: "staged",
|
|
70833
|
-
reason: `message count reached threshold (${newCount}/${threshold})`,
|
|
70834
|
-
subsystem: "user-prompt-reminders",
|
|
70835
|
-
title: "Stage user-prompt reminder"
|
|
70836
|
-
}));
|
|
70837
70867
|
state[reminderId] = { ...typedEntry, messagesSinceLastStaging: 0 };
|
|
70838
70868
|
handlerCtx.logger.debug("Throttle: re-staged reminder", {
|
|
70839
70869
|
sessionId,
|
|
@@ -70883,6 +70913,9 @@ var require_events2 = __commonJS({
|
|
|
70883
70913
|
blocking: state.blocking,
|
|
70884
70914
|
priority: state.priority,
|
|
70885
70915
|
persistent: state.persistent,
|
|
70916
|
+
...state.renderedText !== void 0 && {
|
|
70917
|
+
renderedText: state.renderedText
|
|
70918
|
+
},
|
|
70886
70919
|
...state.classificationResult !== void 0 && {
|
|
70887
70920
|
classificationResult: state.classificationResult
|
|
70888
70921
|
}
|
|
@@ -72574,17 +72607,51 @@ var require_tool_pattern_matcher = __commonJS({
|
|
|
72574
72607
|
exports2.matchesToolPattern = matchesToolPattern;
|
|
72575
72608
|
exports2.findMatchingPattern = findMatchingPattern;
|
|
72576
72609
|
var SHELL_OPERATOR_RE = /\s*(?:&&|\|\||[;|])\s*/;
|
|
72577
|
-
function
|
|
72610
|
+
function detectRunnerPrefix(segmentTokens, runners) {
|
|
72611
|
+
let longestMatch = 0;
|
|
72612
|
+
for (const runner of runners) {
|
|
72613
|
+
if (typeof runner.prefix !== "string")
|
|
72614
|
+
continue;
|
|
72615
|
+
const prefixTokens = runner.prefix.trim().split(/\s+/);
|
|
72616
|
+
if (prefixTokens.length === 0)
|
|
72617
|
+
continue;
|
|
72618
|
+
if (prefixTokens.length > segmentTokens.length)
|
|
72619
|
+
continue;
|
|
72620
|
+
let matches = true;
|
|
72621
|
+
for (let i = 0; i < prefixTokens.length; i++) {
|
|
72622
|
+
if (segmentTokens[i] !== prefixTokens[i]) {
|
|
72623
|
+
matches = false;
|
|
72624
|
+
break;
|
|
72625
|
+
}
|
|
72626
|
+
}
|
|
72627
|
+
if (matches && prefixTokens.length > longestMatch) {
|
|
72628
|
+
longestMatch = prefixTokens.length;
|
|
72629
|
+
}
|
|
72630
|
+
}
|
|
72631
|
+
return longestMatch;
|
|
72632
|
+
}
|
|
72633
|
+
function matchesToolPattern(command, pattern, runners) {
|
|
72578
72634
|
if (!command || !pattern)
|
|
72579
72635
|
return false;
|
|
72580
72636
|
const segments = command.split(SHELL_OPERATOR_RE);
|
|
72581
72637
|
const patternTokens = pattern.trim().split(/\s+/).filter(Boolean);
|
|
72582
72638
|
if (patternTokens.length === 0)
|
|
72583
72639
|
return false;
|
|
72640
|
+
const activeRunners = runners?.length ? runners : void 0;
|
|
72584
72641
|
return segments.some((segment) => {
|
|
72585
72642
|
const cmdTokens = segment.trim().split(/\s+/);
|
|
72586
72643
|
if (cmdTokens.length === 0 || cmdTokens[0] === "")
|
|
72587
72644
|
return false;
|
|
72645
|
+
const runnerTokenCount = activeRunners ? detectRunnerPrefix(cmdTokens, activeRunners) : 0;
|
|
72646
|
+
if (runnerTokenCount > 0) {
|
|
72647
|
+
let pi2 = 0;
|
|
72648
|
+
for (let ci = runnerTokenCount; ci < cmdTokens.length && pi2 < patternTokens.length; ci++) {
|
|
72649
|
+
if (patternTokens[pi2] === "*" || patternTokens[pi2] === cmdTokens[ci]) {
|
|
72650
|
+
pi2++;
|
|
72651
|
+
}
|
|
72652
|
+
}
|
|
72653
|
+
return pi2 === patternTokens.length;
|
|
72654
|
+
}
|
|
72588
72655
|
if (cmdTokens[0] !== patternTokens[0])
|
|
72589
72656
|
return false;
|
|
72590
72657
|
let pi = 1;
|
|
@@ -72596,11 +72663,11 @@ var require_tool_pattern_matcher = __commonJS({
|
|
|
72596
72663
|
return pi === patternTokens.length;
|
|
72597
72664
|
});
|
|
72598
72665
|
}
|
|
72599
|
-
function findMatchingPattern(command, patterns) {
|
|
72666
|
+
function findMatchingPattern(command, patterns, runners) {
|
|
72600
72667
|
for (const pattern of patterns) {
|
|
72601
72668
|
if (pattern.tool === null)
|
|
72602
72669
|
continue;
|
|
72603
|
-
if (matchesToolPattern(command, pattern.tool))
|
|
72670
|
+
if (matchesToolPattern(command, pattern.tool, runners))
|
|
72604
72671
|
return pattern;
|
|
72605
72672
|
}
|
|
72606
72673
|
return null;
|
|
@@ -72656,13 +72723,14 @@ var require_track_verification_tools = __commonJS({
|
|
|
72656
72723
|
const featureConfig = context.config.getFeature("reminders");
|
|
72657
72724
|
const config = { ...types_js_1.DEFAULT_REMINDERS_SETTINGS, ...featureConfig.settings };
|
|
72658
72725
|
const verificationTools = config.verification_tools ?? {};
|
|
72726
|
+
const runners = config.command_runners ?? [];
|
|
72659
72727
|
const remindersState = (0, state_js_1.createRemindersState)(daemonCtx.stateService);
|
|
72660
72728
|
const stateResult = await remindersState.verificationTools.read(sessionId);
|
|
72661
72729
|
const toolsState = { ...stateResult.data };
|
|
72662
72730
|
if (FILE_EDIT_TOOLS.includes(toolName)) {
|
|
72663
72731
|
await handleFileEdit(event, daemonCtx, sessionId, verificationTools, toolsState, remindersState);
|
|
72664
72732
|
} else if (toolName === "Bash") {
|
|
72665
|
-
await handleBashCommand(event, daemonCtx, sessionId, verificationTools, toolsState, remindersState);
|
|
72733
|
+
await handleBashCommand(event, daemonCtx, sessionId, verificationTools, toolsState, remindersState, runners);
|
|
72666
72734
|
}
|
|
72667
72735
|
}
|
|
72668
72736
|
});
|
|
@@ -72784,7 +72852,7 @@ var require_track_verification_tools = __commonJS({
|
|
|
72784
72852
|
return;
|
|
72785
72853
|
await stageToolsForFiles([filePath], daemonCtx, sessionId, verificationTools, toolsState, remindersState);
|
|
72786
72854
|
}
|
|
72787
|
-
async function handleBashCommand(event, daemonCtx, sessionId, verificationTools, toolsState, remindersState) {
|
|
72855
|
+
async function handleBashCommand(event, daemonCtx, sessionId, verificationTools, toolsState, remindersState, runners = []) {
|
|
72788
72856
|
const command = extractToolInput(event)?.command;
|
|
72789
72857
|
if (!command)
|
|
72790
72858
|
return;
|
|
@@ -72795,7 +72863,7 @@ var require_track_verification_tools = __commonJS({
|
|
|
72795
72863
|
const reminderId = types_js_1.TOOL_REMINDER_MAP[toolName];
|
|
72796
72864
|
if (!reminderId)
|
|
72797
72865
|
continue;
|
|
72798
|
-
const match = (0, tool_pattern_matcher_js_1.findMatchingPattern)(command, toolConfig.patterns);
|
|
72866
|
+
const match = (0, tool_pattern_matcher_js_1.findMatchingPattern)(command, toolConfig.patterns, runners);
|
|
72799
72867
|
if (!match)
|
|
72800
72868
|
continue;
|
|
72801
72869
|
toolsState[toolName] = {
|
|
@@ -73611,6 +73679,12 @@ var require_consumption_handler_factory = __commonJS({
|
|
|
73611
73679
|
if (onConsume) {
|
|
73612
73680
|
await onConsume({ reminder: primary, reader, cliCtx, sessionId });
|
|
73613
73681
|
}
|
|
73682
|
+
const renderedParts = [];
|
|
73683
|
+
if (response.userMessage)
|
|
73684
|
+
renderedParts.push(response.userMessage);
|
|
73685
|
+
if (response.additionalContext)
|
|
73686
|
+
renderedParts.push(response.additionalContext);
|
|
73687
|
+
const renderedText = renderedParts.length > 0 ? renderedParts.join("\n\n") : void 0;
|
|
73614
73688
|
(0, core_1.logEvent)(cliCtx.logger, events_js_1.ReminderEvents.reminderConsumed({
|
|
73615
73689
|
sessionId,
|
|
73616
73690
|
hook
|
|
@@ -73620,6 +73694,7 @@ var require_consumption_handler_factory = __commonJS({
|
|
|
73620
73694
|
blocking: response.blocking ?? false,
|
|
73621
73695
|
priority: primary.priority,
|
|
73622
73696
|
persistent: primary.persistent,
|
|
73697
|
+
renderedText,
|
|
73623
73698
|
...enrichment
|
|
73624
73699
|
}));
|
|
73625
73700
|
return { response };
|
|
@@ -74942,6 +75017,7 @@ var require_update_summary = __commonJS({
|
|
|
74942
75017
|
"use strict";
|
|
74943
75018
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
74944
75019
|
exports2.buildPersonaContext = void 0;
|
|
75020
|
+
exports2.resetAnalysisGuard = resetAnalysisGuard;
|
|
74945
75021
|
exports2.interpolateTemplate = interpolateTemplate;
|
|
74946
75022
|
exports2.updateSessionSummary = updateSessionSummary;
|
|
74947
75023
|
var core_1 = require_dist4();
|
|
@@ -74954,6 +75030,7 @@ var require_update_summary = __commonJS({
|
|
|
74954
75030
|
var persona_selection_js_1 = require_persona_selection();
|
|
74955
75031
|
var DECISION_TITLE_SKIP = "Skip session analysis";
|
|
74956
75032
|
var DECISION_TITLE_RUN = "Run session analysis";
|
|
75033
|
+
var analysisInFlight = /* @__PURE__ */ new Map();
|
|
74957
75034
|
var PROMPT_FILE = "prompts/session-summary.prompt.txt";
|
|
74958
75035
|
var SNARKY_PROMPT_FILE = "prompts/snarky-message.prompt.txt";
|
|
74959
75036
|
var RESUME_PROMPT_FILE = "prompts/resume-message.prompt.txt";
|
|
@@ -74971,6 +75048,9 @@ var require_update_summary = __commonJS({
|
|
|
74971
75048
|
Object.defineProperty(exports2, "buildPersonaContext", { enumerable: true, get: function() {
|
|
74972
75049
|
return persona_utils_js_2.buildPersonaContext;
|
|
74973
75050
|
} });
|
|
75051
|
+
function resetAnalysisGuard() {
|
|
75052
|
+
analysisInFlight.clear();
|
|
75053
|
+
}
|
|
74974
75054
|
function interpolateTemplate(template, context) {
|
|
74975
75055
|
let result = template;
|
|
74976
75056
|
const conditionalRegex = /\{\{#if\s+(\w+)\}\}([\s\S]*?)\{\{\/if\}\}/g;
|
|
@@ -75014,12 +75094,12 @@ var require_update_summary = __commonJS({
|
|
|
75014
75094
|
}
|
|
75015
75095
|
(0, core_1.logEvent)(ctx.logger, types_1.DecisionEvents.decisionRecorded(event.context, {
|
|
75016
75096
|
decision: "calling",
|
|
75017
|
-
reason: "
|
|
75097
|
+
reason: "Bulk transcript replay complete \u2014 running catch-up analysis",
|
|
75018
75098
|
subsystem: "session-summary",
|
|
75019
75099
|
title: DECISION_TITLE_RUN
|
|
75020
75100
|
}));
|
|
75021
75101
|
const countdown2 = await loadCountdownState(summaryState, sessionId);
|
|
75022
|
-
void performAnalysis(event, ctx, summaryState, countdown2, "
|
|
75102
|
+
void performAnalysis(event, ctx, summaryState, countdown2, "bulk_replay_complete");
|
|
75023
75103
|
return;
|
|
75024
75104
|
}
|
|
75025
75105
|
const countdown = await loadCountdownState(summaryState, sessionId);
|
|
@@ -75034,7 +75114,7 @@ var require_update_summary = __commonJS({
|
|
|
75034
75114
|
}
|
|
75035
75115
|
(0, core_1.logEvent)(ctx.logger, types_1.DecisionEvents.decisionRecorded(event.context, {
|
|
75036
75116
|
decision: "calling",
|
|
75037
|
-
reason: "countdown reached zero
|
|
75117
|
+
reason: "Prompt countdown reached zero \u2014 running scheduled analysis",
|
|
75038
75118
|
subsystem: "session-summary",
|
|
75039
75119
|
title: DECISION_TITLE_RUN
|
|
75040
75120
|
}));
|
|
@@ -75069,6 +75149,17 @@ var require_update_summary = __commonJS({
|
|
|
75069
75149
|
}
|
|
75070
75150
|
async function performAnalysis(event, ctx, summaryState, countdown, reason) {
|
|
75071
75151
|
const { sessionId } = event.context;
|
|
75152
|
+
if (analysisInFlight.has(sessionId)) {
|
|
75153
|
+
analysisInFlight.set(sessionId, true);
|
|
75154
|
+
(0, core_1.logEvent)(ctx.logger, types_1.DecisionEvents.decisionRecorded(event.context, {
|
|
75155
|
+
decision: "deferred",
|
|
75156
|
+
reason: "Analysis deferred \u2014 will rerun after current analysis completes",
|
|
75157
|
+
subsystem: "session-summary",
|
|
75158
|
+
title: DECISION_TITLE_SKIP
|
|
75159
|
+
}));
|
|
75160
|
+
return;
|
|
75161
|
+
}
|
|
75162
|
+
analysisInFlight.set(sessionId, false);
|
|
75072
75163
|
try {
|
|
75073
75164
|
const startTime = Date.now();
|
|
75074
75165
|
(0, core_1.logEvent)(ctx.logger, events_js_1.SessionSummaryEvents.summaryStart(event.context, {
|
|
@@ -75213,6 +75304,13 @@ var require_update_summary = __commonJS({
|
|
|
75213
75304
|
reason,
|
|
75214
75305
|
error: err instanceof Error ? err.message : String(err)
|
|
75215
75306
|
});
|
|
75307
|
+
} finally {
|
|
75308
|
+
const rerunPending = analysisInFlight.get(sessionId) ?? false;
|
|
75309
|
+
analysisInFlight.delete(sessionId);
|
|
75310
|
+
if (rerunPending) {
|
|
75311
|
+
const freshCountdown = await loadCountdownState(summaryState, sessionId);
|
|
75312
|
+
void performAnalysis(event, ctx, summaryState, freshCountdown, reason);
|
|
75313
|
+
}
|
|
75216
75314
|
}
|
|
75217
75315
|
}
|
|
75218
75316
|
async function loadCurrentSummary(summaryState, sessionId) {
|