@rama_nigg/open-cursor 2.3.10 → 2.3.12
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/discover.js +5 -1
- package/dist/cli/opencode-cursor.js +5 -1
- package/dist/index.js +54 -2
- package/dist/plugin-entry.js +34 -2
- package/package.json +1 -1
- package/src/streaming/ai-sdk-parts.ts +20 -0
- package/src/streaming/delta-tracker.ts +15 -1
- package/src/streaming/openai-sse.ts +23 -0
package/dist/cli/discover.js
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
|
+
var __returnValue = (v) => v;
|
|
5
|
+
function __exportSetter(name, newValue) {
|
|
6
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
7
|
+
}
|
|
4
8
|
var __export = (target, all) => {
|
|
5
9
|
for (var name in all)
|
|
6
10
|
__defProp(target, name, {
|
|
7
11
|
get: all[name],
|
|
8
12
|
enumerable: true,
|
|
9
13
|
configurable: true,
|
|
10
|
-
set: (
|
|
14
|
+
set: __exportSetter.bind(all, name)
|
|
11
15
|
});
|
|
12
16
|
};
|
|
13
17
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
|
+
var __returnValue = (v) => v;
|
|
5
|
+
function __exportSetter(name, newValue) {
|
|
6
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
7
|
+
}
|
|
4
8
|
var __export = (target, all) => {
|
|
5
9
|
for (var name in all)
|
|
6
10
|
__defProp(target, name, {
|
|
7
11
|
get: all[name],
|
|
8
12
|
enumerable: true,
|
|
9
13
|
configurable: true,
|
|
10
|
-
set: (
|
|
14
|
+
set: __exportSetter.bind(all, name)
|
|
11
15
|
});
|
|
12
16
|
};
|
|
13
17
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
var __defProp = Object.defineProperty;
|
|
3
|
+
var __returnValue = (v) => v;
|
|
4
|
+
function __exportSetter(name, newValue) {
|
|
5
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
6
|
+
}
|
|
3
7
|
var __export = (target, all) => {
|
|
4
8
|
for (var name in all)
|
|
5
9
|
__defProp(target, name, {
|
|
6
10
|
get: all[name],
|
|
7
11
|
enumerable: true,
|
|
8
12
|
configurable: true,
|
|
9
|
-
set: (
|
|
13
|
+
set: __exportSetter.bind(all, name)
|
|
10
14
|
});
|
|
11
15
|
};
|
|
12
16
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
@@ -13331,7 +13335,15 @@ class DeltaTracker {
|
|
|
13331
13335
|
if (current.startsWith(previous)) {
|
|
13332
13336
|
return current.slice(previous.length);
|
|
13333
13337
|
}
|
|
13334
|
-
|
|
13338
|
+
if (previous.startsWith(current)) {
|
|
13339
|
+
return "";
|
|
13340
|
+
}
|
|
13341
|
+
let i = 0;
|
|
13342
|
+
const minLen = Math.min(previous.length, current.length);
|
|
13343
|
+
while (i < minLen && previous[i] === current[i]) {
|
|
13344
|
+
i++;
|
|
13345
|
+
}
|
|
13346
|
+
return current.slice(i);
|
|
13335
13347
|
}
|
|
13336
13348
|
}
|
|
13337
13349
|
|
|
@@ -13341,6 +13353,8 @@ class StreamToSseConverter {
|
|
|
13341
13353
|
created;
|
|
13342
13354
|
model;
|
|
13343
13355
|
tracker = new DeltaTracker;
|
|
13356
|
+
sawAssistantPartials = false;
|
|
13357
|
+
sawThinkingPartials = false;
|
|
13344
13358
|
constructor(model, options) {
|
|
13345
13359
|
this.model = model;
|
|
13346
13360
|
this.id = options?.id ?? `cursor-acp-${Date.now()}`;
|
|
@@ -13348,10 +13362,28 @@ class StreamToSseConverter {
|
|
|
13348
13362
|
}
|
|
13349
13363
|
handleEvent(event) {
|
|
13350
13364
|
if (isAssistantText(event)) {
|
|
13365
|
+
const isPartial = typeof event.timestamp_ms === "number";
|
|
13366
|
+
if (isPartial) {
|
|
13367
|
+
this.sawAssistantPartials = true;
|
|
13368
|
+
const text = extractText(event);
|
|
13369
|
+
return text ? [this.chunkWith({ content: text })] : [];
|
|
13370
|
+
}
|
|
13371
|
+
if (this.sawAssistantPartials) {
|
|
13372
|
+
return [];
|
|
13373
|
+
}
|
|
13351
13374
|
const delta = this.tracker.nextText(extractText(event));
|
|
13352
13375
|
return delta ? [this.chunkWith({ content: delta })] : [];
|
|
13353
13376
|
}
|
|
13354
13377
|
if (isThinking(event)) {
|
|
13378
|
+
const isPartial = typeof event.timestamp_ms === "number";
|
|
13379
|
+
if (isPartial) {
|
|
13380
|
+
this.sawThinkingPartials = true;
|
|
13381
|
+
const text = extractThinking(event);
|
|
13382
|
+
return text ? [this.chunkWith({ reasoning_content: text })] : [];
|
|
13383
|
+
}
|
|
13384
|
+
if (this.sawThinkingPartials) {
|
|
13385
|
+
return [];
|
|
13386
|
+
}
|
|
13355
13387
|
const delta = this.tracker.nextThinking(extractThinking(event));
|
|
13356
13388
|
return delta ? [this.chunkWith({ reasoning_content: delta })] : [];
|
|
13357
13389
|
}
|
|
@@ -19846,12 +19878,32 @@ class StreamToAiSdkParts {
|
|
|
19846
19878
|
tracker = new DeltaTracker;
|
|
19847
19879
|
toolArgsById = new Map;
|
|
19848
19880
|
startedToolIds = new Set;
|
|
19881
|
+
sawAssistantPartials = false;
|
|
19882
|
+
sawThinkingPartials = false;
|
|
19849
19883
|
handleEvent(event) {
|
|
19850
19884
|
if (isAssistantText(event)) {
|
|
19885
|
+
const isPartial = typeof event.timestamp_ms === "number";
|
|
19886
|
+
if (isPartial) {
|
|
19887
|
+
this.sawAssistantPartials = true;
|
|
19888
|
+
const text = extractText(event);
|
|
19889
|
+
return text ? [{ type: "text-delta", textDelta: text }] : [];
|
|
19890
|
+
}
|
|
19891
|
+
if (this.sawAssistantPartials) {
|
|
19892
|
+
return [];
|
|
19893
|
+
}
|
|
19851
19894
|
const delta = this.tracker.nextText(extractText(event));
|
|
19852
19895
|
return delta ? [{ type: "text-delta", textDelta: delta }] : [];
|
|
19853
19896
|
}
|
|
19854
19897
|
if (isThinking(event)) {
|
|
19898
|
+
const isPartial = typeof event.timestamp_ms === "number";
|
|
19899
|
+
if (isPartial) {
|
|
19900
|
+
this.sawThinkingPartials = true;
|
|
19901
|
+
const text = extractThinking(event);
|
|
19902
|
+
return text ? [{ type: "text-delta", textDelta: text }] : [];
|
|
19903
|
+
}
|
|
19904
|
+
if (this.sawThinkingPartials) {
|
|
19905
|
+
return [];
|
|
19906
|
+
}
|
|
19855
19907
|
const delta = this.tracker.nextThinking(extractThinking(event));
|
|
19856
19908
|
return delta ? [{ type: "text-delta", textDelta: delta }] : [];
|
|
19857
19909
|
}
|
package/dist/plugin-entry.js
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
var __defProp = Object.defineProperty;
|
|
3
|
+
var __returnValue = (v) => v;
|
|
4
|
+
function __exportSetter(name, newValue) {
|
|
5
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
6
|
+
}
|
|
3
7
|
var __export = (target, all) => {
|
|
4
8
|
for (var name in all)
|
|
5
9
|
__defProp(target, name, {
|
|
6
10
|
get: all[name],
|
|
7
11
|
enumerable: true,
|
|
8
12
|
configurable: true,
|
|
9
|
-
set: (
|
|
13
|
+
set: __exportSetter.bind(all, name)
|
|
10
14
|
});
|
|
11
15
|
};
|
|
12
16
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
@@ -13331,7 +13335,15 @@ class DeltaTracker {
|
|
|
13331
13335
|
if (current.startsWith(previous)) {
|
|
13332
13336
|
return current.slice(previous.length);
|
|
13333
13337
|
}
|
|
13334
|
-
|
|
13338
|
+
if (previous.startsWith(current)) {
|
|
13339
|
+
return "";
|
|
13340
|
+
}
|
|
13341
|
+
let i = 0;
|
|
13342
|
+
const minLen = Math.min(previous.length, current.length);
|
|
13343
|
+
while (i < minLen && previous[i] === current[i]) {
|
|
13344
|
+
i++;
|
|
13345
|
+
}
|
|
13346
|
+
return current.slice(i);
|
|
13335
13347
|
}
|
|
13336
13348
|
}
|
|
13337
13349
|
|
|
@@ -13341,6 +13353,8 @@ class StreamToSseConverter {
|
|
|
13341
13353
|
created;
|
|
13342
13354
|
model;
|
|
13343
13355
|
tracker = new DeltaTracker;
|
|
13356
|
+
sawAssistantPartials = false;
|
|
13357
|
+
sawThinkingPartials = false;
|
|
13344
13358
|
constructor(model, options) {
|
|
13345
13359
|
this.model = model;
|
|
13346
13360
|
this.id = options?.id ?? `cursor-acp-${Date.now()}`;
|
|
@@ -13348,10 +13362,28 @@ class StreamToSseConverter {
|
|
|
13348
13362
|
}
|
|
13349
13363
|
handleEvent(event) {
|
|
13350
13364
|
if (isAssistantText(event)) {
|
|
13365
|
+
const isPartial = typeof event.timestamp_ms === "number";
|
|
13366
|
+
if (isPartial) {
|
|
13367
|
+
this.sawAssistantPartials = true;
|
|
13368
|
+
const text = extractText(event);
|
|
13369
|
+
return text ? [this.chunkWith({ content: text })] : [];
|
|
13370
|
+
}
|
|
13371
|
+
if (this.sawAssistantPartials) {
|
|
13372
|
+
return [];
|
|
13373
|
+
}
|
|
13351
13374
|
const delta = this.tracker.nextText(extractText(event));
|
|
13352
13375
|
return delta ? [this.chunkWith({ content: delta })] : [];
|
|
13353
13376
|
}
|
|
13354
13377
|
if (isThinking(event)) {
|
|
13378
|
+
const isPartial = typeof event.timestamp_ms === "number";
|
|
13379
|
+
if (isPartial) {
|
|
13380
|
+
this.sawThinkingPartials = true;
|
|
13381
|
+
const text = extractThinking(event);
|
|
13382
|
+
return text ? [this.chunkWith({ reasoning_content: text })] : [];
|
|
13383
|
+
}
|
|
13384
|
+
if (this.sawThinkingPartials) {
|
|
13385
|
+
return [];
|
|
13386
|
+
}
|
|
13355
13387
|
const delta = this.tracker.nextThinking(extractThinking(event));
|
|
13356
13388
|
return delta ? [this.chunkWith({ reasoning_content: delta })] : [];
|
|
13357
13389
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rama_nigg/open-cursor",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.12",
|
|
4
4
|
"description": "No prompt limits. No broken streams. Full thinking + tool support. Your Cursor subscription, properly integrated.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/plugin-entry.js",
|
|
@@ -37,14 +37,34 @@ export class StreamToAiSdkParts {
|
|
|
37
37
|
private readonly tracker = new DeltaTracker();
|
|
38
38
|
private readonly toolArgsById = new Map<string, string>();
|
|
39
39
|
private readonly startedToolIds = new Set<string>();
|
|
40
|
+
private sawAssistantPartials = false;
|
|
41
|
+
private sawThinkingPartials = false;
|
|
40
42
|
|
|
41
43
|
handleEvent(event: StreamJsonEvent): AiSdkStreamPart[] {
|
|
42
44
|
if (isAssistantText(event)) {
|
|
45
|
+
const isPartial = typeof (event as any).timestamp_ms === "number";
|
|
46
|
+
if (isPartial) {
|
|
47
|
+
this.sawAssistantPartials = true;
|
|
48
|
+
const text = extractText(event);
|
|
49
|
+
return text ? [{ type: "text-delta", textDelta: text }] : [];
|
|
50
|
+
}
|
|
51
|
+
if (this.sawAssistantPartials) {
|
|
52
|
+
return [];
|
|
53
|
+
}
|
|
43
54
|
const delta = this.tracker.nextText(extractText(event));
|
|
44
55
|
return delta ? [{ type: "text-delta", textDelta: delta }] : [];
|
|
45
56
|
}
|
|
46
57
|
|
|
47
58
|
if (isThinking(event)) {
|
|
59
|
+
const isPartial = typeof (event as any).timestamp_ms === "number";
|
|
60
|
+
if (isPartial) {
|
|
61
|
+
this.sawThinkingPartials = true;
|
|
62
|
+
const text = extractThinking(event);
|
|
63
|
+
return text ? [{ type: "text-delta", textDelta: text }] : [];
|
|
64
|
+
}
|
|
65
|
+
if (this.sawThinkingPartials) {
|
|
66
|
+
return [];
|
|
67
|
+
}
|
|
48
68
|
const delta = this.tracker.nextThinking(extractThinking(event));
|
|
49
69
|
return delta ? [{ type: "text-delta", textDelta: delta }] : [];
|
|
50
70
|
}
|
|
@@ -24,10 +24,24 @@ export class DeltaTracker {
|
|
|
24
24
|
return current;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
// Happy path: accumulated text grows with exact prefix match
|
|
27
28
|
if (current.startsWith(previous)) {
|
|
28
29
|
return current.slice(previous.length);
|
|
29
30
|
}
|
|
30
31
|
|
|
31
|
-
|
|
32
|
+
// Accumulated text was already fully emitted (e.g. duplicate or trimmed event)
|
|
33
|
+
if (previous.startsWith(current)) {
|
|
34
|
+
return "";
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Prefix mismatch (formatting drift, unicode normalization, whitespace changes):
|
|
38
|
+
// find longest common prefix and emit only the new suffix.
|
|
39
|
+
// This prevents re-emitting the entire accumulated text as a "delta".
|
|
40
|
+
let i = 0;
|
|
41
|
+
const minLen = Math.min(previous.length, current.length);
|
|
42
|
+
while (i < minLen && previous[i] === current[i]) {
|
|
43
|
+
i++;
|
|
44
|
+
}
|
|
45
|
+
return current.slice(i);
|
|
32
46
|
}
|
|
33
47
|
}
|
|
@@ -61,6 +61,11 @@ export class StreamToSseConverter {
|
|
|
61
61
|
private readonly created: number;
|
|
62
62
|
private readonly model: string;
|
|
63
63
|
private readonly tracker = new DeltaTracker();
|
|
64
|
+
// Events with timestamp_ms carry delta text; events without carry accumulated text.
|
|
65
|
+
// DeltaTracker handles accumulated text only. When partials (delta) were seen,
|
|
66
|
+
// the final accumulated event must be skipped to prevent 2x duplication.
|
|
67
|
+
private sawAssistantPartials = false;
|
|
68
|
+
private sawThinkingPartials = false;
|
|
64
69
|
|
|
65
70
|
constructor(model: string, options?: { id?: string; created?: number }) {
|
|
66
71
|
this.model = model;
|
|
@@ -70,11 +75,29 @@ export class StreamToSseConverter {
|
|
|
70
75
|
|
|
71
76
|
handleEvent(event: StreamJsonEvent): string[] {
|
|
72
77
|
if (isAssistantText(event)) {
|
|
78
|
+
const isPartial = typeof (event as any).timestamp_ms === "number";
|
|
79
|
+
if (isPartial) {
|
|
80
|
+
this.sawAssistantPartials = true;
|
|
81
|
+
const text = extractText(event);
|
|
82
|
+
return text ? [this.chunkWith({ content: text })] : [];
|
|
83
|
+
}
|
|
84
|
+
if (this.sawAssistantPartials) {
|
|
85
|
+
return [];
|
|
86
|
+
}
|
|
73
87
|
const delta = this.tracker.nextText(extractText(event));
|
|
74
88
|
return delta ? [this.chunkWith({ content: delta })] : [];
|
|
75
89
|
}
|
|
76
90
|
|
|
77
91
|
if (isThinking(event)) {
|
|
92
|
+
const isPartial = typeof (event as any).timestamp_ms === "number";
|
|
93
|
+
if (isPartial) {
|
|
94
|
+
this.sawThinkingPartials = true;
|
|
95
|
+
const text = extractThinking(event);
|
|
96
|
+
return text ? [this.chunkWith({ reasoning_content: text })] : [];
|
|
97
|
+
}
|
|
98
|
+
if (this.sawThinkingPartials) {
|
|
99
|
+
return [];
|
|
100
|
+
}
|
|
78
101
|
const delta = this.tracker.nextThinking(extractThinking(event));
|
|
79
102
|
return delta ? [this.chunkWith({ reasoning_content: delta })] : [];
|
|
80
103
|
}
|