graphlit-client 1.0.20260419003 → 1.0.20260419004
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/client.d.ts +14 -0
- package/dist/client.js +126 -19
- package/package.json +1 -1
package/dist/client.d.ts
CHANGED
|
@@ -3119,6 +3119,20 @@ declare class Graphlit {
|
|
|
3119
3119
|
* with `intermediateMessages` rather than a single tool-call list.
|
|
3120
3120
|
*/
|
|
3121
3121
|
private detectTaskCompleteInMessages;
|
|
3122
|
+
/**
|
|
3123
|
+
* Extract the `final_message` argument from a task_complete invocation
|
|
3124
|
+
* within a list of tool calls. Handles both direct invocation and
|
|
3125
|
+
* meta-executor wrapping (mirrors `detectTaskComplete`).
|
|
3126
|
+
*
|
|
3127
|
+
* Returns undefined if task_complete was not called, the arg is missing,
|
|
3128
|
+
* or the arg is not a non-empty string.
|
|
3129
|
+
*/
|
|
3130
|
+
private extractTaskCompleteFinalMessage;
|
|
3131
|
+
/**
|
|
3132
|
+
* Scan a list of messages for a task_complete invocation's `final_message`
|
|
3133
|
+
* arg. Convenience wrapper over `extractTaskCompleteFinalMessage`.
|
|
3134
|
+
*/
|
|
3135
|
+
private extractTaskCompleteFinalMessageFromMessages;
|
|
3122
3136
|
/**
|
|
3123
3137
|
* Run LLM-as-judge quality assessment on a completed agent run.
|
|
3124
3138
|
*/
|
package/dist/client.js
CHANGED
|
@@ -6981,22 +6981,32 @@ class Graphlit {
|
|
|
6981
6981
|
}
|
|
6982
6982
|
// Build tools list with task_complete prepended.
|
|
6983
6983
|
//
|
|
6984
|
-
// task_complete
|
|
6985
|
-
//
|
|
6986
|
-
//
|
|
6987
|
-
//
|
|
6984
|
+
// task_complete's optional `final_message` parameter is the explicit
|
|
6985
|
+
// commitment of the agent's user-facing answer. When provided, it
|
|
6986
|
+
// becomes the persisted assistant message for that turn AND the run's
|
|
6987
|
+
// `finalMessage`, overriding any prose the model wrote around the call.
|
|
6988
6988
|
//
|
|
6989
|
-
//
|
|
6990
|
-
//
|
|
6991
|
-
// useless prose
|
|
6992
|
-
//
|
|
6993
|
-
//
|
|
6989
|
+
// An earlier version used a `summary` field. The name encouraged
|
|
6990
|
+
// truncated summarization — the model would stuff a short summary into
|
|
6991
|
+
// the arg and emit useless prose like "answer delivered above". The
|
|
6992
|
+
// field name `final_message` and description below are explicit: this
|
|
6993
|
+
// IS the full answer, not a summary, and it replaces surrounding prose.
|
|
6994
|
+
//
|
|
6995
|
+
// If the model omits `final_message`, the SDK falls back to the last
|
|
6996
|
+
// turn whose assistant text was substantive AND did not itself call
|
|
6997
|
+
// task_complete — so a throwaway completion turn can't overwrite the
|
|
6998
|
+
// real answer in a prior turn.
|
|
6994
6999
|
const taskCompleteTool = {
|
|
6995
7000
|
name: "task_complete",
|
|
6996
|
-
description: "Signal that you have completed the assigned task.
|
|
7001
|
+
description: "Signal that you have completed the assigned task. Provide your complete, final user-facing answer as `final_message` — full prose, not a summary. That string becomes the assistant message the user sees; do not also emit the answer as plain text around this call. Calling this tool ends the run.",
|
|
6997
7002
|
schema: JSON.stringify({
|
|
6998
7003
|
type: "object",
|
|
6999
|
-
properties: {
|
|
7004
|
+
properties: {
|
|
7005
|
+
final_message: {
|
|
7006
|
+
type: "string",
|
|
7007
|
+
description: "Your complete, final answer to the user as full prose. Replaces any assistant text written around this tool call.",
|
|
7008
|
+
},
|
|
7009
|
+
},
|
|
7000
7010
|
}),
|
|
7001
7011
|
};
|
|
7002
7012
|
const allTools = [
|
|
@@ -7254,9 +7264,39 @@ class Graphlit {
|
|
|
7254
7264
|
finally {
|
|
7255
7265
|
uiAdapter.dispose();
|
|
7256
7266
|
}
|
|
7257
|
-
// 8.
|
|
7258
|
-
|
|
7259
|
-
|
|
7267
|
+
// 8. Detect task_complete and extract its optional `final_message`
|
|
7268
|
+
// arg BEFORE persistence. When provided, it replaces the turn's
|
|
7269
|
+
// assistant prose as the canonical answer — see the task_complete
|
|
7270
|
+
// tool schema above.
|
|
7271
|
+
const taskCompleteThisTurn = this.detectTaskCompleteInMessages(loopResult.intermediateMessages);
|
|
7272
|
+
const taskCompleteFinalMessage = taskCompleteThisTurn
|
|
7273
|
+
? this.extractTaskCompleteFinalMessageFromMessages(loopResult.intermediateMessages)
|
|
7274
|
+
: undefined;
|
|
7275
|
+
// Resolve the assistant message to persist for this turn:
|
|
7276
|
+
// - task_complete({final_message}) → final_message (authoritative)
|
|
7277
|
+
// - task_complete() with no arg, prior substantive answer exists →
|
|
7278
|
+
// drop the turn's prose so throwaway text like "delivered above"
|
|
7279
|
+
// doesn't pollute chat history
|
|
7280
|
+
// - task_complete() with no arg, no prior answer → keep the prose
|
|
7281
|
+
// (single-shot completion case)
|
|
7282
|
+
// - normal turn → keep the prose
|
|
7283
|
+
let assistantMessageToPersist;
|
|
7284
|
+
if (taskCompleteThisTurn) {
|
|
7285
|
+
if (taskCompleteFinalMessage) {
|
|
7286
|
+
assistantMessageToPersist = taskCompleteFinalMessage;
|
|
7287
|
+
}
|
|
7288
|
+
else if (finalMessage) {
|
|
7289
|
+
assistantMessageToPersist = "";
|
|
7290
|
+
}
|
|
7291
|
+
else {
|
|
7292
|
+
assistantMessageToPersist = loopResult.finalAssistantMessage;
|
|
7293
|
+
}
|
|
7294
|
+
}
|
|
7295
|
+
else {
|
|
7296
|
+
assistantMessageToPersist = loopResult.finalAssistantMessage;
|
|
7297
|
+
}
|
|
7298
|
+
// 8b. Complete conversation (persist turn)
|
|
7299
|
+
if (assistantMessageToPersist) {
|
|
7260
7300
|
const completionTime = uiAdapter.getCompletionTime();
|
|
7261
7301
|
const ttft = uiAdapter.getTTFT();
|
|
7262
7302
|
const throughput = uiAdapter.getThroughput();
|
|
@@ -7271,7 +7311,7 @@ class Graphlit {
|
|
|
7271
7311
|
if (loopResult.lastRoundReasoning) {
|
|
7272
7312
|
const completionInput = {
|
|
7273
7313
|
role: Types.ConversationRoleTypes.Assistant,
|
|
7274
|
-
message:
|
|
7314
|
+
message: assistantMessageToPersist,
|
|
7275
7315
|
timestamp: new Date().toISOString(),
|
|
7276
7316
|
thinkingContent: loopResult.lastRoundReasoning.content,
|
|
7277
7317
|
};
|
|
@@ -7284,7 +7324,7 @@ class Graphlit {
|
|
|
7284
7324
|
completionInput,
|
|
7285
7325
|
];
|
|
7286
7326
|
}
|
|
7287
|
-
await this.completeConversation(
|
|
7327
|
+
await this.completeConversation(assistantMessageToPersist, conversationId, millisecondsToTimeSpan(completionTime), millisecondsToTimeSpan(ttft), throughput, undefined, turnMessageInputs, options?.correlationId);
|
|
7288
7328
|
// Emit completion event
|
|
7289
7329
|
uiAdapter.handleEvent({
|
|
7290
7330
|
type: "complete",
|
|
@@ -7293,12 +7333,11 @@ class Graphlit {
|
|
|
7293
7333
|
}
|
|
7294
7334
|
// 9. Build TurnResult
|
|
7295
7335
|
const turnDuration = Date.now() - turnStart;
|
|
7296
|
-
const taskCompleteThisTurn = this.detectTaskCompleteInMessages(loopResult.intermediateMessages);
|
|
7297
7336
|
const turnToolNames = [...new Set(loopResult.toolCallNames)].sort();
|
|
7298
7337
|
const turnResult = {
|
|
7299
7338
|
turnNumber: turn,
|
|
7300
7339
|
prompt: currentPrompt,
|
|
7301
|
-
responseText: loopResult.fullMessage,
|
|
7340
|
+
responseText: taskCompleteFinalMessage || loopResult.fullMessage,
|
|
7302
7341
|
toolCalls: turnToolNames,
|
|
7303
7342
|
toolCallCount: loopResult.toolCallCount,
|
|
7304
7343
|
durationMs: turnDuration,
|
|
@@ -7314,7 +7353,25 @@ class Graphlit {
|
|
|
7314
7353
|
lastTurnUsage = undefined;
|
|
7315
7354
|
turnResults.push(turnResult);
|
|
7316
7355
|
totalToolCalls += loopResult.toolCallCount;
|
|
7317
|
-
|
|
7356
|
+
// Update finalMessage with priority:
|
|
7357
|
+
// - task_complete({final_message}) → authoritative
|
|
7358
|
+
// - task_complete() without arg → keep prior finalMessage (avoids
|
|
7359
|
+
// throwaway completion-turn prose overwriting a real answer)
|
|
7360
|
+
// - normal turn → this turn's assistant text
|
|
7361
|
+
if (taskCompleteThisTurn) {
|
|
7362
|
+
if (taskCompleteFinalMessage) {
|
|
7363
|
+
finalMessage = taskCompleteFinalMessage;
|
|
7364
|
+
}
|
|
7365
|
+
else if (!finalMessage) {
|
|
7366
|
+
// No prior answer — this turn's prose is all we have
|
|
7367
|
+
finalMessage =
|
|
7368
|
+
loopResult.finalAssistantMessage || loopResult.fullMessage;
|
|
7369
|
+
}
|
|
7370
|
+
}
|
|
7371
|
+
else {
|
|
7372
|
+
finalMessage =
|
|
7373
|
+
loopResult.finalAssistantMessage || loopResult.fullMessage;
|
|
7374
|
+
}
|
|
7318
7375
|
lastContextWindow = loopResult.contextWindow;
|
|
7319
7376
|
// 10. Notify callback
|
|
7320
7377
|
options?.onTurnComplete?.(turnResult);
|
|
@@ -7564,6 +7621,56 @@ class Graphlit {
|
|
|
7564
7621
|
}
|
|
7565
7622
|
return false;
|
|
7566
7623
|
}
|
|
7624
|
+
/**
|
|
7625
|
+
* Extract the `final_message` argument from a task_complete invocation
|
|
7626
|
+
* within a list of tool calls. Handles both direct invocation and
|
|
7627
|
+
* meta-executor wrapping (mirrors `detectTaskComplete`).
|
|
7628
|
+
*
|
|
7629
|
+
* Returns undefined if task_complete was not called, the arg is missing,
|
|
7630
|
+
* or the arg is not a non-empty string.
|
|
7631
|
+
*/
|
|
7632
|
+
extractTaskCompleteFinalMessage(toolCalls) {
|
|
7633
|
+
if (!toolCalls)
|
|
7634
|
+
return undefined;
|
|
7635
|
+
for (const tc of toolCalls) {
|
|
7636
|
+
if (!tc?.arguments)
|
|
7637
|
+
continue;
|
|
7638
|
+
let args;
|
|
7639
|
+
try {
|
|
7640
|
+
args = JSON.parse(tc.arguments);
|
|
7641
|
+
}
|
|
7642
|
+
catch {
|
|
7643
|
+
continue;
|
|
7644
|
+
}
|
|
7645
|
+
// Direct invocation: args ARE the task_complete params
|
|
7646
|
+
if (tc.name === "task_complete") {
|
|
7647
|
+
const fm = args.final_message;
|
|
7648
|
+
if (typeof fm === "string" && fm.trim().length > 0)
|
|
7649
|
+
return fm;
|
|
7650
|
+
continue;
|
|
7651
|
+
}
|
|
7652
|
+
// Meta-executor wrapping: { tool: "task_complete", parameters: {...} }
|
|
7653
|
+
if (args.tool === "task_complete") {
|
|
7654
|
+
const params = args.parameters;
|
|
7655
|
+
const fm = params?.final_message;
|
|
7656
|
+
if (typeof fm === "string" && fm.trim().length > 0)
|
|
7657
|
+
return fm;
|
|
7658
|
+
}
|
|
7659
|
+
}
|
|
7660
|
+
return undefined;
|
|
7661
|
+
}
|
|
7662
|
+
/**
|
|
7663
|
+
* Scan a list of messages for a task_complete invocation's `final_message`
|
|
7664
|
+
* arg. Convenience wrapper over `extractTaskCompleteFinalMessage`.
|
|
7665
|
+
*/
|
|
7666
|
+
extractTaskCompleteFinalMessageFromMessages(messages) {
|
|
7667
|
+
for (const msg of messages) {
|
|
7668
|
+
const fm = this.extractTaskCompleteFinalMessage(msg.toolCalls);
|
|
7669
|
+
if (fm)
|
|
7670
|
+
return fm;
|
|
7671
|
+
}
|
|
7672
|
+
return undefined;
|
|
7673
|
+
}
|
|
7567
7674
|
/**
|
|
7568
7675
|
* Run LLM-as-judge quality assessment on a completed agent run.
|
|
7569
7676
|
*/
|