instar 0.28.50 → 0.28.51

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/cli.js CHANGED
File without changes
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA2PH,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AA81CD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA+yItE;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsDzE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuD5E"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA2PH,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AA81CD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA+0ItE;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsDzE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuD5E"}
@@ -1761,27 +1761,9 @@ export async function startServer(options) {
1761
1761
  }
1762
1762
  }
1763
1763
  const sessionManager = new SessionManager(config.sessions, state);
1764
- // Input Guard cross-topic injection defense (Layer 1 + 1.5 + 2)
1765
- if (config.inputGuard?.enabled !== false) {
1766
- const guardConfig = config.inputGuard ?? { enabled: true };
1767
- const anthropicKey = process.env['ANTHROPIC_API_KEY']?.trim();
1768
- const { InputGuard } = await import('../core/InputGuard.js');
1769
- const inputGuard = new InputGuard({
1770
- config: {
1771
- enabled: true,
1772
- provenanceCheck: guardConfig.provenanceCheck ?? true,
1773
- injectionPatterns: guardConfig.injectionPatterns ?? true,
1774
- topicCoherenceReview: guardConfig.topicCoherenceReview ?? true,
1775
- action: guardConfig.action ?? 'warn',
1776
- reviewTimeout: guardConfig.reviewTimeout ?? 3000,
1777
- },
1778
- stateDir: config.stateDir,
1779
- apiKey: anthropicKey,
1780
- });
1781
- const registryPath = path.join(config.stateDir, 'topic-session-registry.json');
1782
- sessionManager.setInputGuard(inputGuard, registryPath);
1783
- console.log(pc.green(` Input Guard: enabled (action: ${guardConfig.action ?? 'warn'})`));
1784
- }
1764
+ // Input Guard is constructed later (after sharedIntelligence is available)
1765
+ // so the topic coherence reviewer can route through the IntelligenceProvider
1766
+ // abstraction instead of calling Anthropic directly.
1785
1767
  // TopicResumeMap: persist Claude session UUIDs across session restarts.
1786
1768
  // When a session is killed/restarted, we save its UUID so the next spawn
1787
1769
  // can use --resume to reattach to the existing conversation context.
@@ -1837,11 +1819,54 @@ export async function startServer(options) {
1837
1819
  }
1838
1820
  else {
1839
1821
  console.log(pc.yellow(' Intelligence: none (no Claude CLI, no API key) — LLM-gated features degraded'));
1822
+ // Visible degradation — every downstream LLM-gated feature depends on this.
1823
+ // The DegradationReporter routes to console, disk, Telegram alert, and feedback.
1824
+ // Keep the externally-rendered impact string generic; the detailed
1825
+ // capability-down enumeration (tone gate, input guard, coherence gate, stall
1826
+ // triage, job reflection) stays in the yellow console line above and the
1827
+ // local degradations.json log. We don't broadcast a "which defenses are down"
1828
+ // checklist to Telegram/feedback channels.
1829
+ const { DegradationReporter } = await import('../monitoring/DegradationReporter.js');
1830
+ DegradationReporter.getInstance().report({
1831
+ feature: 'SharedIntelligenceProvider',
1832
+ primary: 'Shared LLM provider (Claude CLI subscription by default, Anthropic API opt-in)',
1833
+ fallback: 'Heuristic-only operation for LLM-gated features',
1834
+ reason: 'No LLM transport configured on this machine (see local startup logs for detail).',
1835
+ impact: 'LLM-gated features degraded; defense-in-depth reduced. See local logs for the affected feature list.',
1836
+ });
1840
1837
  }
1841
1838
  // Wire intelligence into git sync for LLM conflict resolution (Tier 1 → 2)
1842
1839
  if (gitSync && sharedIntelligence) {
1843
1840
  gitSync.setIntelligence(sharedIntelligence);
1844
1841
  }
1842
+ // Input Guard — cross-topic injection defense (Layer 1 + 1.5 + 2).
1843
+ // Constructed AFTER sharedIntelligence so the topic-coherence reviewer routes
1844
+ // through the IntelligenceProvider (subscription-first). InputGuard no longer
1845
+ // carries a direct Anthropic API path — all LLM usage flows through the shared
1846
+ // provider abstraction, enforcing the subscription-first principle at the
1847
+ // single provider-selection layer rather than in each consumer.
1848
+ if (config.inputGuard?.enabled !== false) {
1849
+ const guardConfig = config.inputGuard ?? { enabled: true };
1850
+ const { InputGuard } = await import('../core/InputGuard.js');
1851
+ const inputGuard = new InputGuard({
1852
+ config: {
1853
+ enabled: true,
1854
+ provenanceCheck: guardConfig.provenanceCheck ?? true,
1855
+ injectionPatterns: guardConfig.injectionPatterns ?? true,
1856
+ topicCoherenceReview: guardConfig.topicCoherenceReview ?? true,
1857
+ action: guardConfig.action ?? 'warn',
1858
+ reviewTimeout: guardConfig.reviewTimeout ?? 3000,
1859
+ },
1860
+ stateDir: config.stateDir,
1861
+ intelligence: sharedIntelligence,
1862
+ });
1863
+ const registryPath = path.join(config.stateDir, 'topic-session-registry.json');
1864
+ sessionManager.setInputGuard(inputGuard, registryPath);
1865
+ const reviewBackend = sharedIntelligence
1866
+ ? 'via shared IntelligenceProvider'
1867
+ : 'provenance + patterns only (no LLM review)';
1868
+ console.log(pc.green(` Input Guard: enabled (action: ${guardConfig.action ?? 'warn'}, ${reviewBackend})`));
1869
+ }
1845
1870
  let relationships;
1846
1871
  if (config.relationships) {
1847
1872
  // Wire LLM intelligence for identity resolution.
@@ -3840,6 +3865,7 @@ export async function startServer(options) {
3840
3865
  // (3) "continue where you left off" tells the agent not to re-ask or
3841
3866
  // re-litigate, just pick up.
3842
3867
  const COMPACTION_RESUME_PROMPT = 'Your session just went through context compaction. Read the recent messages in this topic to re-orient, briefly let the user know compaction occurred, then continue where you left off.';
3868
+ const { isSystemOrProxyMessage, findLastRealMessage } = await import('../messaging/shared/isSystemOrProxyMessage.js');
3843
3869
  const recoverCompactedSession = async (sessionName, triggerLabel) => {
3844
3870
  if (!sessionManager.isSessionAlive(sessionName))
3845
3871
  return false;
@@ -3847,9 +3873,15 @@ export async function startServer(options) {
3847
3873
  if (telegram) {
3848
3874
  const topicId = telegram.getTopicForSession(sessionName);
3849
3875
  if (topicId) {
3850
- const history = telegram.getTopicHistory(topicId, 5);
3851
- const lastMsg = history[history.length - 1];
3852
- if (lastMsg?.fromUser) {
3876
+ // Walk history backward, skipping PresenceProxy standby messages and
3877
+ // server-emitted delivery/lifecycle acks. Those are from-agent but
3878
+ // they are NOT real responses — treating them as "agent answered"
3879
+ // is what let this recovery path silently decline for 15 minutes
3880
+ // while the user's question sat unanswered. See
3881
+ // isSystemOrProxyMessage / findLastRealMessage for the canonical filter.
3882
+ const history = telegram.getTopicHistory(topicId, 20);
3883
+ const lastReal = findLastRealMessage(history);
3884
+ if (lastReal?.fromUser) {
3853
3885
  console.log(`[CompactionResume] (${triggerLabel}) topic ${topicId} session "${sessionName}" has unanswered message — recovering`);
3854
3886
  // Direct injection with topic tag so InputGuard accepts it.
3855
3887
  const tagged = `[telegram:${topicId}] ${COMPACTION_RESUME_PROMPT}`;
@@ -4102,7 +4134,10 @@ export async function startServer(options) {
4102
4134
  const { execSync: shellExecSync } = await import('child_process');
4103
4135
  const messagesLogPath = path.join(config.stateDir, 'telegram-messages.jsonl');
4104
4136
  const slackMessagesLogPath = path.join(config.stateDir, 'slack-messages.jsonl');
4105
- // Shared helper: check a messages log file for agent responses after a timestamp
4137
+ // Shared helper: check a messages log file for agent responses after a timestamp.
4138
+ // System/proxy-message filtering is delegated to isSystemOrProxyMessage so all
4139
+ // three callsites (this one, PresenceProxy.isSystemMessage, and the compaction
4140
+ // recoverFn) stay in sync.
4106
4141
  const checkLogForAgentResponse = (logPath, topicId, sinceIso) => {
4107
4142
  try {
4108
4143
  const content = fs.readFileSync(logPath, 'utf-8');
@@ -4115,12 +4150,7 @@ export async function startServer(options) {
4115
4150
  const matchesTopic = msg.topicId === topicId
4116
4151
  || (topicId < 0 && msg.channelId && slackChannelToSyntheticId(String(msg.channelId)) === topicId);
4117
4152
  if (matchesTopic && !msg.fromUser && msg.timestamp > sinceIso) {
4118
- const t = (msg.text || '').trim();
4119
- const isSystem = t === '✓ Delivered' || t.startsWith('✓ Delivered')
4120
- || t.startsWith('🔄 Session restarting') || t === 'Session respawned.'
4121
- || t === 'Session terminated.' || t.startsWith('Send a new message to start')
4122
- || t.startsWith('🔭');
4123
- if (!isSystem)
4153
+ if (!isSystemOrProxyMessage(msg.text))
4124
4154
  return true;
4125
4155
  }
4126
4156
  }