ns-omp-provider-kiro 0.3.7 → 0.3.8
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/index.js +216 -11
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -3566,12 +3566,177 @@ function countTokens(text) {
|
|
|
3566
3566
|
return getEncoder().encode(text).length;
|
|
3567
3567
|
}
|
|
3568
3568
|
|
|
3569
|
+
// ../kiro-core/dist/tool-name-aliases.js
|
|
3570
|
+
var TOOL_NAME_ALIASES = {
|
|
3571
|
+
// read
|
|
3572
|
+
read_file: "read",
|
|
3573
|
+
readfile: "read",
|
|
3574
|
+
fs_read: "read",
|
|
3575
|
+
view_file: "read",
|
|
3576
|
+
// write
|
|
3577
|
+
write_file: "write",
|
|
3578
|
+
writefile: "write",
|
|
3579
|
+
fs_write: "write",
|
|
3580
|
+
create_file: "write",
|
|
3581
|
+
// edit
|
|
3582
|
+
edit_file: "edit",
|
|
3583
|
+
editfile: "edit",
|
|
3584
|
+
str_replace: "edit",
|
|
3585
|
+
str_replace_editor: "edit",
|
|
3586
|
+
str_replace_based_edit_tool: "edit",
|
|
3587
|
+
apply_patch: "edit",
|
|
3588
|
+
// ls
|
|
3589
|
+
list_directory: "ls",
|
|
3590
|
+
list_dir: "ls",
|
|
3591
|
+
list_files: "ls",
|
|
3592
|
+
// find
|
|
3593
|
+
find_files: "find",
|
|
3594
|
+
file_search: "find"
|
|
3595
|
+
};
|
|
3596
|
+
function normalizeKiroToolName(name, declared) {
|
|
3597
|
+
if (!declared || declared.size === 0 || declared.has(name))
|
|
3598
|
+
return name;
|
|
3599
|
+
const alias = TOOL_NAME_ALIASES[name.toLowerCase()];
|
|
3600
|
+
return alias !== void 0 && declared.has(alias) ? alias : name;
|
|
3601
|
+
}
|
|
3602
|
+
|
|
3603
|
+
// ../kiro-core/dist/tool-use-parser.js
|
|
3604
|
+
var TAG_NAMES = ["tool_use", "tool_call", "function_call", "tool"];
|
|
3605
|
+
var FENCE2 = "```";
|
|
3606
|
+
function nextTagBlock(text, from) {
|
|
3607
|
+
let best = null;
|
|
3608
|
+
for (const name of TAG_NAMES) {
|
|
3609
|
+
const open = `<${name}>`;
|
|
3610
|
+
const close = `</${name}>`;
|
|
3611
|
+
const openStart = text.indexOf(open, from);
|
|
3612
|
+
if (openStart < 0)
|
|
3613
|
+
continue;
|
|
3614
|
+
if (best && openStart >= best.openStart)
|
|
3615
|
+
continue;
|
|
3616
|
+
const bodyStart = openStart + open.length;
|
|
3617
|
+
const closeIdx = text.indexOf(close, bodyStart);
|
|
3618
|
+
if (closeIdx < 0)
|
|
3619
|
+
continue;
|
|
3620
|
+
best = { openStart, bodyStart, closeIdx, closeEnd: closeIdx + close.length };
|
|
3621
|
+
}
|
|
3622
|
+
return best;
|
|
3623
|
+
}
|
|
3624
|
+
function fencedRanges2(text) {
|
|
3625
|
+
const ranges = [];
|
|
3626
|
+
let searchFrom = 0;
|
|
3627
|
+
while (true) {
|
|
3628
|
+
const open = text.indexOf(FENCE2, searchFrom);
|
|
3629
|
+
if (open < 0)
|
|
3630
|
+
break;
|
|
3631
|
+
const close = text.indexOf(FENCE2, open + FENCE2.length);
|
|
3632
|
+
if (close < 0) {
|
|
3633
|
+
ranges.push({ start: open, end: text.length });
|
|
3634
|
+
break;
|
|
3635
|
+
}
|
|
3636
|
+
ranges.push({ start: open, end: close + FENCE2.length });
|
|
3637
|
+
searchFrom = close + FENCE2.length;
|
|
3638
|
+
}
|
|
3639
|
+
return ranges;
|
|
3640
|
+
}
|
|
3641
|
+
function normalizeOne(value) {
|
|
3642
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
3643
|
+
return null;
|
|
3644
|
+
const record = value;
|
|
3645
|
+
const rawName = record.tool_name ?? record.name;
|
|
3646
|
+
if (typeof rawName !== "string" || rawName.length === 0)
|
|
3647
|
+
return null;
|
|
3648
|
+
const rawArgs = record.tool_input ?? record.input ?? record.arguments;
|
|
3649
|
+
if (rawArgs === void 0) {
|
|
3650
|
+
return { name: rawName, arguments: {} };
|
|
3651
|
+
}
|
|
3652
|
+
if (typeof rawArgs !== "object" || rawArgs === null || Array.isArray(rawArgs))
|
|
3653
|
+
return null;
|
|
3654
|
+
return { name: rawName, arguments: rawArgs };
|
|
3655
|
+
}
|
|
3656
|
+
function extractDescriptors(value) {
|
|
3657
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
3658
|
+
const record = value;
|
|
3659
|
+
const wrapped = record.tool_calls ?? record.calls;
|
|
3660
|
+
if (Array.isArray(wrapped)) {
|
|
3661
|
+
const out = [];
|
|
3662
|
+
for (const entry of wrapped) {
|
|
3663
|
+
const one = normalizeOne(entry);
|
|
3664
|
+
if (one === null)
|
|
3665
|
+
return [];
|
|
3666
|
+
out.push(one);
|
|
3667
|
+
}
|
|
3668
|
+
return out;
|
|
3669
|
+
}
|
|
3670
|
+
}
|
|
3671
|
+
const single = normalizeOne(value);
|
|
3672
|
+
return single ? [single] : [];
|
|
3673
|
+
}
|
|
3674
|
+
function parseToolUseCalls(text) {
|
|
3675
|
+
const toolCalls = [];
|
|
3676
|
+
const removals = [];
|
|
3677
|
+
const fences = fencedRanges2(text);
|
|
3678
|
+
let cursor = 0;
|
|
3679
|
+
while (cursor < text.length) {
|
|
3680
|
+
const hit = nextTagBlock(text, cursor);
|
|
3681
|
+
if (hit === null)
|
|
3682
|
+
break;
|
|
3683
|
+
const { openStart, bodyStart, closeIdx, closeEnd } = hit;
|
|
3684
|
+
const containingFence = fences.find((range) => openStart >= range.start && openStart < range.end);
|
|
3685
|
+
if (containingFence) {
|
|
3686
|
+
cursor = containingFence.end;
|
|
3687
|
+
continue;
|
|
3688
|
+
}
|
|
3689
|
+
const braceStart = text.indexOf("{", bodyStart);
|
|
3690
|
+
if (braceStart < 0 || braceStart > closeIdx) {
|
|
3691
|
+
cursor = closeEnd;
|
|
3692
|
+
continue;
|
|
3693
|
+
}
|
|
3694
|
+
const braceEnd = findJsonEnd(text, braceStart);
|
|
3695
|
+
if (braceEnd < 0 || braceEnd > closeIdx) {
|
|
3696
|
+
cursor = closeEnd;
|
|
3697
|
+
continue;
|
|
3698
|
+
}
|
|
3699
|
+
const beforeJson = text.substring(bodyStart, braceStart).trim();
|
|
3700
|
+
const afterJson = text.substring(braceEnd + 1, closeIdx).trim();
|
|
3701
|
+
if (beforeJson.length > 0 || afterJson.length > 0) {
|
|
3702
|
+
cursor = closeEnd;
|
|
3703
|
+
continue;
|
|
3704
|
+
}
|
|
3705
|
+
let descriptors = [];
|
|
3706
|
+
try {
|
|
3707
|
+
descriptors = extractDescriptors(JSON.parse(text.substring(braceStart, braceEnd + 1)));
|
|
3708
|
+
} catch {
|
|
3709
|
+
descriptors = [];
|
|
3710
|
+
}
|
|
3711
|
+
if (descriptors.length === 0) {
|
|
3712
|
+
cursor = closeEnd;
|
|
3713
|
+
continue;
|
|
3714
|
+
}
|
|
3715
|
+
for (const descriptor of descriptors) {
|
|
3716
|
+
toolCalls.push({
|
|
3717
|
+
toolUseId: crypto.randomUUID(),
|
|
3718
|
+
name: descriptor.name,
|
|
3719
|
+
arguments: descriptor.arguments
|
|
3720
|
+
});
|
|
3721
|
+
}
|
|
3722
|
+
removals.push({ start: openStart, end: closeEnd });
|
|
3723
|
+
cursor = closeEnd;
|
|
3724
|
+
}
|
|
3725
|
+
let cleanedText = text;
|
|
3726
|
+
for (let i = removals.length - 1; i >= 0; i--) {
|
|
3727
|
+
const { start, end } = removals[i];
|
|
3728
|
+
cleanedText = cleanedText.substring(0, start) + cleanedText.substring(end);
|
|
3729
|
+
}
|
|
3730
|
+
return { toolCalls, cleanedText };
|
|
3731
|
+
}
|
|
3732
|
+
|
|
3569
3733
|
// ../kiro-core/dist/response-assembler.js
|
|
3570
3734
|
var ECHO_NOISE_PATTERN = /^\s*(continue|\.+)\s*$/i;
|
|
3571
3735
|
var KiroResponseAssembler = class {
|
|
3572
3736
|
model;
|
|
3573
3737
|
thinkingEnabled;
|
|
3574
3738
|
toolNameAliases;
|
|
3739
|
+
declaredToolNames;
|
|
3575
3740
|
pending = [];
|
|
3576
3741
|
blocks = new KiroBlockBuffer((event) => this.pending.push(event));
|
|
3577
3742
|
usage = {
|
|
@@ -3581,7 +3746,6 @@ var KiroResponseAssembler = class {
|
|
|
3581
3746
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }
|
|
3582
3747
|
};
|
|
3583
3748
|
totalContent = "";
|
|
3584
|
-
lastContentData = "";
|
|
3585
3749
|
usageEvent = null;
|
|
3586
3750
|
meteringEvent = null;
|
|
3587
3751
|
receivedContextUsage = false;
|
|
@@ -3594,18 +3758,19 @@ var KiroResponseAssembler = class {
|
|
|
3594
3758
|
droppedToolCalls = [];
|
|
3595
3759
|
currentToolCall = null;
|
|
3596
3760
|
stopReason = "stop";
|
|
3597
|
-
constructor(model, thinkingEnabled, toolNameAliases) {
|
|
3761
|
+
constructor(model, thinkingEnabled, toolNameAliases, declaredToolNames) {
|
|
3598
3762
|
this.model = model;
|
|
3599
3763
|
this.thinkingEnabled = thinkingEnabled;
|
|
3600
3764
|
this.toolNameAliases = toolNameAliases;
|
|
3765
|
+
this.declaredToolNames = declaredToolNames;
|
|
3601
3766
|
}
|
|
3767
|
+
/** Wire name -> the name the host registered, then alias repair. */
|
|
3602
3768
|
originalToolName(name) {
|
|
3603
|
-
return this.toolNameAliases?.get(name) ?? name;
|
|
3769
|
+
return normalizeKiroToolName(this.toolNameAliases?.get(name) ?? name, this.declaredToolNames);
|
|
3604
3770
|
}
|
|
3605
3771
|
/** Clear per-attempt state. Only block indexes are kept. */
|
|
3606
3772
|
beginAttempt() {
|
|
3607
3773
|
this.totalContent = "";
|
|
3608
|
-
this.lastContentData = "";
|
|
3609
3774
|
this.usageEvent = null;
|
|
3610
3775
|
this.meteringEvent = null;
|
|
3611
3776
|
this.receivedContextUsage = false;
|
|
@@ -3661,10 +3826,9 @@ var KiroResponseAssembler = class {
|
|
|
3661
3826
|
break;
|
|
3662
3827
|
}
|
|
3663
3828
|
case "content": {
|
|
3664
|
-
|
|
3665
|
-
if (event.data === this.lastContentData)
|
|
3829
|
+
if (event.data === "")
|
|
3666
3830
|
break;
|
|
3667
|
-
this.
|
|
3831
|
+
this.endNativeThinking();
|
|
3668
3832
|
this.totalContent += event.data;
|
|
3669
3833
|
if (this.thinkingParser) {
|
|
3670
3834
|
this.thinkingParser.processChunk(event.data);
|
|
@@ -3703,6 +3867,14 @@ var KiroResponseAssembler = class {
|
|
|
3703
3867
|
}
|
|
3704
3868
|
case "usage": {
|
|
3705
3869
|
this.usageEvent = { ...this.usageEvent ?? {}, ...event.data };
|
|
3870
|
+
const pct = event.data.contextUsagePercentage;
|
|
3871
|
+
if (pct !== void 0) {
|
|
3872
|
+
if (this.usageEvent.inputTokens === void 0) {
|
|
3873
|
+
this.usage.input = Math.round(pct / 100 * this.model.contextWindow);
|
|
3874
|
+
}
|
|
3875
|
+
this.usage.contextPercent = pct;
|
|
3876
|
+
this.receivedContextUsage = true;
|
|
3877
|
+
}
|
|
3706
3878
|
if (debugEnabled())
|
|
3707
3879
|
debugLog("response.usageRaw", payload);
|
|
3708
3880
|
break;
|
|
@@ -3736,7 +3908,18 @@ var KiroResponseAssembler = class {
|
|
|
3736
3908
|
this.stripEchoNoise();
|
|
3737
3909
|
const responseText = this.textBlockIndex === null ? "" : this.blocks.getText(this.textBlockIndex);
|
|
3738
3910
|
const hasText2 = responseText.length > 0;
|
|
3739
|
-
|
|
3911
|
+
const wireStopReason = this.usageEvent?.rawStopReason;
|
|
3912
|
+
switch (wireStopReason) {
|
|
3913
|
+
case "MAX_TOKENS":
|
|
3914
|
+
this.stopReason = "length";
|
|
3915
|
+
break;
|
|
3916
|
+
case "END_TURN":
|
|
3917
|
+
case "TOOL_USE":
|
|
3918
|
+
this.stopReason = this.emittedToolCalls > 0 ? "toolUse" : "stop";
|
|
3919
|
+
break;
|
|
3920
|
+
default:
|
|
3921
|
+
this.stopReason = !this.receivedContextUsage && this.emittedToolCalls === 0 ? "length" : this.emittedToolCalls > 0 ? "toolUse" : "stop";
|
|
3922
|
+
}
|
|
3740
3923
|
return {
|
|
3741
3924
|
responseText,
|
|
3742
3925
|
hasText: hasText2,
|
|
@@ -3745,7 +3928,9 @@ var KiroResponseAssembler = class {
|
|
|
3745
3928
|
isEchoLoop: hasText2 && !this.sawAnyToolCalls && ECHO_NOISE_PATTERN.test(responseText),
|
|
3746
3929
|
isEmpty: !hasText2 && !this.sawAnyToolCalls,
|
|
3747
3930
|
stopReason: this.stopReason,
|
|
3748
|
-
droppedToolCalls: this.droppedToolCalls
|
|
3931
|
+
droppedToolCalls: this.droppedToolCalls,
|
|
3932
|
+
...wireStopReason !== void 0 ? { wireStopReason } : {},
|
|
3933
|
+
...this.usageEvent?.stopDetails !== void 0 ? { wireStopDetails: this.usageEvent.stopDetails } : {}
|
|
3749
3934
|
};
|
|
3750
3935
|
}
|
|
3751
3936
|
/** Drop an echo the caller decided not to retry, so it is not read as a continuation signal. */
|
|
@@ -3829,10 +4014,14 @@ var KiroResponseAssembler = class {
|
|
|
3829
4014
|
}
|
|
3830
4015
|
/**
|
|
3831
4016
|
* Extract text-dialect tool calls from content when no native tool calls
|
|
3832
|
-
* arrived.
|
|
4017
|
+
* arrived. Three dialects are recovered at this seam:
|
|
3833
4018
|
* 1. Kiro's own `[Called name with args: {...}]` bracket form.
|
|
3834
4019
|
* 2. Anthropic's `<invoke name="..."><parameter .../></invoke>` XML form,
|
|
3835
4020
|
* which opus-class models emit as plain text at high context.
|
|
4021
|
+
* 3. A JSON descriptor wrapped in `<tool_use>`, `<tool_call>`,
|
|
4022
|
+
* `<function_call>` or `<tool>` tags (upstream #163), spelled
|
|
4023
|
+
* `tool_name`/`tool_input`, `name`/`input` or `name`/`arguments`,
|
|
4024
|
+
* or wrapped in a `{"tool_calls": [...]}` array.
|
|
3836
4025
|
* Without this, the turn ends `stop` with zero tool calls — the agent loop
|
|
3837
4026
|
* sees a finished answer and an unattended session stalls with no error
|
|
3838
4027
|
* recorded anywhere.
|
|
@@ -3859,6 +4048,11 @@ var KiroResponseAssembler = class {
|
|
|
3859
4048
|
text = invokeResult.cleanedText;
|
|
3860
4049
|
recovered.push(...invokeResult.toolCalls);
|
|
3861
4050
|
}
|
|
4051
|
+
const toolUseResult = parseToolUseCalls(text);
|
|
4052
|
+
if (toolUseResult.toolCalls.length > 0) {
|
|
4053
|
+
text = toolUseResult.cleanedText;
|
|
4054
|
+
recovered.push(...toolUseResult.toolCalls);
|
|
4055
|
+
}
|
|
3862
4056
|
if (recovered.length === 0)
|
|
3863
4057
|
return;
|
|
3864
4058
|
this.blocks.setText(this.textBlockIndex, text);
|
|
@@ -4909,6 +5103,16 @@ function describeReturnedContent(kinds) {
|
|
|
4909
5103
|
}
|
|
4910
5104
|
var skipProfileResolutionForTests = false;
|
|
4911
5105
|
var TEST_PROFILE_ARN = "arn:aws:codewhisperer:us-east-1:000000000000:profile/test";
|
|
5106
|
+
function throwOnTerminalWireStop(wireStopReason, stopDetails) {
|
|
5107
|
+
switch (wireStopReason) {
|
|
5108
|
+
case "MODEL_CONTEXT_WINDOW_EXCEEDED":
|
|
5109
|
+
throw new Error("Kiro API error: context_length_exceeded (MODEL_CONTEXT_WINDOW_EXCEEDED)");
|
|
5110
|
+
case "CONTENT_FILTERED":
|
|
5111
|
+
throw new Error(`Kiro content filtered: ${clampForDiagnostic(redactSensitiveText(JSON.stringify(stopDetails ?? {})))}`);
|
|
5112
|
+
case "PAUSE_TURN":
|
|
5113
|
+
throw new Error("Kiro paused the turn (PAUSE_TURN); automatic continuation is not supported");
|
|
5114
|
+
}
|
|
5115
|
+
}
|
|
4912
5116
|
async function* streamKiro(request) {
|
|
4913
5117
|
const { model, signal } = request;
|
|
4914
5118
|
const initialAccessToken = request.accessToken;
|
|
@@ -4967,7 +5171,7 @@ async function* streamKiro(request) {
|
|
|
4967
5171
|
systemPrompt = `<thinking_mode>enabled</thinking_mode><max_thinking_length>${budget}</max_thinking_length>${systemPrompt ? `
|
|
4968
5172
|
${systemPrompt}` : ""}`;
|
|
4969
5173
|
}
|
|
4970
|
-
const assembler = new KiroResponseAssembler(model, thinkingEnabled, kiroToolNameAliases(request.tools));
|
|
5174
|
+
const assembler = new KiroResponseAssembler(model, thinkingEnabled, kiroToolNameAliases(request.tools), new Set((request.tools ?? []).map((tool) => String(tool.name))));
|
|
4971
5175
|
const usageTracking = request.usageTracking ?? KIRO_USAGE_TRACKING_DISABLED;
|
|
4972
5176
|
let retryCount = 0;
|
|
4973
5177
|
const maxRetries = 3;
|
|
@@ -5151,6 +5355,7 @@ ${systemPrompt}` : ""}`;
|
|
|
5151
5355
|
throw new Error(`Kiro API error: ${outcome.firstTokenTimedOut ? "first token" : "idle"} timeout after max retries`);
|
|
5152
5356
|
}
|
|
5153
5357
|
const summary = assembler.endTurn();
|
|
5358
|
+
throwOnTerminalWireStop(summary.wireStopReason, summary.wireStopDetails);
|
|
5154
5359
|
yield* assembler.takeEvents();
|
|
5155
5360
|
const degenerate = summary.isEmpty || summary.isEchoLoop;
|
|
5156
5361
|
if (summary.isEchoLoop)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ns-omp-provider-kiro",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.8",
|
|
4
4
|
"description": "OMP (oh-my-pi) provider plugin: adds Kiro (AWS CodeWhisperer/Q) models via your kiro-cli login",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"README.md"
|
|
38
38
|
],
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"ns-kiro-core": "0.3.
|
|
40
|
+
"ns-kiro-core": "0.3.8"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
43
|
"@oh-my-pi/pi-ai": ">=18.2.0",
|