@geravant/sinain 1.0.18 → 1.1.0

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.
Files changed (89) hide show
  1. package/README.md +10 -1
  2. package/cli.js +176 -0
  3. package/index.ts +163 -1257
  4. package/install.js +12 -2
  5. package/launcher.js +622 -0
  6. package/openclaw.plugin.json +4 -0
  7. package/pack-prepare.js +48 -0
  8. package/package.json +26 -5
  9. package/sense_client/README.md +82 -0
  10. package/sense_client/__init__.py +1 -0
  11. package/sense_client/__main__.py +462 -0
  12. package/sense_client/app_detector.py +54 -0
  13. package/sense_client/app_detector_win.py +83 -0
  14. package/sense_client/capture.py +215 -0
  15. package/sense_client/capture_win.py +88 -0
  16. package/sense_client/change_detector.py +86 -0
  17. package/sense_client/config.py +64 -0
  18. package/sense_client/gate.py +145 -0
  19. package/sense_client/ocr.py +347 -0
  20. package/sense_client/privacy.py +65 -0
  21. package/sense_client/requirements.txt +13 -0
  22. package/sense_client/roi_extractor.py +84 -0
  23. package/sense_client/sender.py +173 -0
  24. package/sense_client/tests/__init__.py +0 -0
  25. package/sense_client/tests/test_stream1_optimizations.py +234 -0
  26. package/setup-overlay.js +82 -0
  27. package/sinain-agent/.env.example +17 -0
  28. package/sinain-agent/CLAUDE.md +80 -0
  29. package/sinain-agent/mcp-config.json +12 -0
  30. package/sinain-agent/run.sh +248 -0
  31. package/sinain-core/.env.example +93 -0
  32. package/sinain-core/package-lock.json +552 -0
  33. package/sinain-core/package.json +21 -0
  34. package/sinain-core/src/agent/analyzer.ts +366 -0
  35. package/sinain-core/src/agent/context-window.ts +172 -0
  36. package/sinain-core/src/agent/loop.ts +404 -0
  37. package/sinain-core/src/agent/situation-writer.ts +187 -0
  38. package/sinain-core/src/agent/traits.ts +520 -0
  39. package/sinain-core/src/audio/capture-spawner-macos.ts +44 -0
  40. package/sinain-core/src/audio/capture-spawner-win.ts +37 -0
  41. package/sinain-core/src/audio/capture-spawner.ts +14 -0
  42. package/sinain-core/src/audio/pipeline.ts +335 -0
  43. package/sinain-core/src/audio/transcription-local.ts +141 -0
  44. package/sinain-core/src/audio/transcription.ts +278 -0
  45. package/sinain-core/src/buffers/feed-buffer.ts +71 -0
  46. package/sinain-core/src/buffers/sense-buffer.ts +425 -0
  47. package/sinain-core/src/config.ts +245 -0
  48. package/sinain-core/src/escalation/escalation-slot.ts +136 -0
  49. package/sinain-core/src/escalation/escalator.ts +812 -0
  50. package/sinain-core/src/escalation/message-builder.ts +323 -0
  51. package/sinain-core/src/escalation/openclaw-ws.ts +726 -0
  52. package/sinain-core/src/escalation/scorer.ts +166 -0
  53. package/sinain-core/src/index.ts +507 -0
  54. package/sinain-core/src/learning/feedback-store.ts +253 -0
  55. package/sinain-core/src/learning/signal-collector.ts +218 -0
  56. package/sinain-core/src/log.ts +24 -0
  57. package/sinain-core/src/overlay/commands.ts +126 -0
  58. package/sinain-core/src/overlay/ws-handler.ts +267 -0
  59. package/sinain-core/src/privacy/index.ts +18 -0
  60. package/sinain-core/src/privacy/presets.ts +40 -0
  61. package/sinain-core/src/privacy/redact.ts +92 -0
  62. package/sinain-core/src/profiler.ts +181 -0
  63. package/sinain-core/src/recorder.ts +186 -0
  64. package/sinain-core/src/server.ts +417 -0
  65. package/sinain-core/src/trace/trace-store.ts +73 -0
  66. package/sinain-core/src/trace/tracer.ts +94 -0
  67. package/sinain-core/src/types.ts +427 -0
  68. package/sinain-core/src/util/dedup.ts +48 -0
  69. package/sinain-core/src/util/task-store.ts +84 -0
  70. package/sinain-core/tsconfig.json +18 -0
  71. package/sinain-knowledge/adapters/generic/adapter.ts +103 -0
  72. package/sinain-knowledge/adapters/interface.ts +72 -0
  73. package/sinain-knowledge/adapters/openclaw/adapter.ts +223 -0
  74. package/sinain-knowledge/curation/engine.ts +493 -0
  75. package/sinain-knowledge/curation/resilience.ts +336 -0
  76. package/sinain-knowledge/data/git-store.ts +312 -0
  77. package/sinain-knowledge/data/schema.ts +89 -0
  78. package/sinain-knowledge/data/snapshot.ts +226 -0
  79. package/sinain-knowledge/data/store.ts +488 -0
  80. package/sinain-knowledge/deploy/cli.ts +214 -0
  81. package/sinain-knowledge/deploy/manifest.ts +80 -0
  82. package/sinain-knowledge/protocol/bindings/generic.md +5 -0
  83. package/sinain-knowledge/protocol/bindings/openclaw.md +5 -0
  84. package/sinain-knowledge/protocol/heartbeat.md +62 -0
  85. package/sinain-knowledge/protocol/renderer.ts +56 -0
  86. package/sinain-knowledge/protocol/skill.md +335 -0
  87. package/sinain-mcp-server/index.ts +337 -0
  88. package/sinain-mcp-server/package.json +19 -0
  89. package/sinain-mcp-server/tsconfig.json +15 -0
@@ -0,0 +1,136 @@
1
+ import { log, warn } from "../log.js";
2
+ import type { OpenClawWsClient } from "./openclaw-ws.js";
3
+ import type { OpenClawConfig } from "../types.js";
4
+
5
+ const TAG = "escalation-slot";
6
+
7
+ export interface QueueFeedbackCtx {
8
+ tickId: number;
9
+ hud: string;
10
+ currentApp: string;
11
+ escalationScore: number;
12
+ escalationReasons: string[];
13
+ codingContext: boolean;
14
+ digest: string;
15
+ }
16
+
17
+ export interface SlotEntry {
18
+ /** sha256(sessionKey + ts).hex[:16] — idempotency key */
19
+ id: string;
20
+ message: string;
21
+ sessionKey: string;
22
+ feedbackCtx: QueueFeedbackCtx | undefined;
23
+ ts: number;
24
+ }
25
+
26
+ export interface EscalationSlotCallbacks {
27
+ onResponse: (result: any, entry: SlotEntry, latencyMs: number) => void;
28
+ onPhase1Failure: (isTimeout: boolean) => void;
29
+ onOutboundBytes: (n: number) => void;
30
+ }
31
+
32
+ /**
33
+ * Two-slot escalation buffer: latest-wins.
34
+ *
35
+ * Invariants:
36
+ * - Depth is always 0, 1, or 2
37
+ * - inFlight: the entry currently in Phase 1 or Phase 2
38
+ * - latest: the next entry to send (replaced on insert — stale context is discarded)
39
+ * - Phase 1 retry re-sends `latest` (not the stale failed entry)
40
+ * - Phase 2 always resolves — both .then and .catch clear inFlight and tryAdvance
41
+ */
42
+ export class EscalationSlot {
43
+ private inFlight: SlotEntry | null = null;
44
+ private latest: SlotEntry | null = null;
45
+
46
+ constructor(
47
+ private readonly wsClient: OpenClawWsClient,
48
+ private readonly config: OpenClawConfig,
49
+ private readonly callbacks: EscalationSlotCallbacks,
50
+ ) {}
51
+
52
+ /** Replace latest with the new entry (discarding any previous unsent entry). */
53
+ insert(entry: SlotEntry): void {
54
+ this.latest = entry;
55
+ log(TAG, `insert id=${entry.id} depth=${this.depth} (inFlight=${this.inFlight?.id ?? "none"})`);
56
+ this.tryAdvance();
57
+ }
58
+
59
+ /** Called on WS reconnect — attempt to send the pending latest entry. */
60
+ onConnected(): void {
61
+ this.tryAdvance();
62
+ }
63
+
64
+ /** Current slot depth: 0 (idle), 1 (in-flight only or latest only), or 2 (both). */
65
+ get depth(): number {
66
+ return (this.inFlight ? 1 : 0) + (this.latest ? 1 : 0);
67
+ }
68
+
69
+ get inFlightId(): string | null {
70
+ return this.inFlight?.id ?? null;
71
+ }
72
+
73
+ // ── Private ──
74
+
75
+ /**
76
+ * Promote latest → inFlight and send, if preconditions are met.
77
+ * No-op if already in-flight, nothing queued, or WS disconnected.
78
+ */
79
+ private tryAdvance(): void {
80
+ if (this.inFlight || !this.latest || !this.wsClient.isConnected) return;
81
+ const entry = this.latest;
82
+ this.latest = null;
83
+ this.inFlight = entry;
84
+ this.sendToAgent(entry);
85
+ }
86
+
87
+ /**
88
+ * Two-phase delivery for the given entry.
89
+ *
90
+ * Phase 1: await acceptedPromise (30s timeout)
91
+ * success → log, Phase 2 runs async
92
+ * failure → clear inFlight, call onPhase1Failure, schedule retry via tryAdvance
93
+ *
94
+ * Phase 2: async .then/.catch on finalPromise
95
+ * resolve → call onResponse, clear inFlight, tryAdvance
96
+ * reject → if Phase 1 succeeded (pure Phase 2 failure): clear inFlight, tryAdvance
97
+ * if Phase 1 failed: cleanup already done above — skip
98
+ */
99
+ private sendToAgent(entry: SlotEntry): void {
100
+ const rpcStart = Date.now();
101
+ this.callbacks.onOutboundBytes(Buffer.byteLength(entry.message));
102
+
103
+ const { acceptedPromise, finalPromise } = this.wsClient.sendAgentRpcSplit(
104
+ entry.message, entry.id, entry.sessionKey,
105
+ );
106
+
107
+ // Track whether Phase 1 resolved so finalPromise.catch can distinguish causes
108
+ let phase1Succeeded = false;
109
+
110
+ acceptedPromise.then(() => {
111
+ phase1Succeeded = true;
112
+ log(TAG, `Phase 1 accepted id=${entry.id} (${Date.now() - rpcStart}ms) — slot releasing`);
113
+ }).catch((phase1Err: any) => {
114
+ const isTimeout = /phase1 timeout|rpc timeout/i.test(phase1Err.message);
115
+ warn(TAG, `Phase 1 failed id=${entry.id}: ${phase1Err.message}`);
116
+ this.callbacks.onPhase1Failure(isTimeout);
117
+ this.inFlight = null;
118
+ // Retry picks up latest (not the stale failed entry) after brief backoff
119
+ setTimeout(() => this.tryAdvance(), 5_000);
120
+ });
121
+
122
+ finalPromise.then((result: any) => {
123
+ this.callbacks.onResponse(result, entry, Date.now() - rpcStart);
124
+ this.inFlight = null;
125
+ this.tryAdvance();
126
+ }).catch((err: any) => {
127
+ if (phase1Succeeded) {
128
+ // Pure Phase 2 failure — Phase 1 already logged; Phase 1 path did not clean up
129
+ warn(TAG, `Phase 2 failed id=${entry.id}: ${err.message} — clearing slot`);
130
+ this.inFlight = null;
131
+ this.tryAdvance();
132
+ }
133
+ // else: Phase 1 failed → acceptedPromise.catch already cleared inFlight and scheduled retry
134
+ });
135
+ }
136
+ }