@letta-ai/letta-code 0.27.5 → 0.27.6
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/letta.js +372 -95
- package/package.json +1 -1
- package/skills/creating-extensions/SKILL.md +6 -2
- package/skills/creating-extensions/references/commands.md +1 -1
- package/skills/creating-extensions/references/events.md +3 -17
- package/skills/creating-extensions/references/permissions.md +90 -0
- package/skills/creating-extensions/references/plan-mode.md +285 -0
- package/skills/creating-extensions/references/providers.md +50 -148
- package/skills/customizing-commands/SKILL.md +2 -2
- package/skills/creating-extensions/references/btw-command.md +0 -106
package/letta.js
CHANGED
|
@@ -5077,7 +5077,7 @@ var package_default;
|
|
|
5077
5077
|
var init_package = __esm(() => {
|
|
5078
5078
|
package_default = {
|
|
5079
5079
|
name: "@letta-ai/letta-code",
|
|
5080
|
-
version: "0.27.
|
|
5080
|
+
version: "0.27.6",
|
|
5081
5081
|
description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
|
|
5082
5082
|
type: "module",
|
|
5083
5083
|
packageManager: "bun@1.3.0",
|
|
@@ -5272,6 +5272,7 @@ var init_request = __esm(() => {
|
|
|
5272
5272
|
var exports_conversations = {};
|
|
5273
5273
|
__export(exports_conversations, {
|
|
5274
5274
|
updateConversationDescription: () => updateConversationDescription,
|
|
5275
|
+
summarizeConversation: () => summarizeConversation,
|
|
5275
5276
|
forkConversation: () => forkConversation
|
|
5276
5277
|
});
|
|
5277
5278
|
async function forkConversation(conversationId, options = {}) {
|
|
@@ -5284,12 +5285,15 @@ async function forkConversation(conversationId, options = {}) {
|
|
|
5284
5285
|
async function updateConversationDescription(conversationId, body) {
|
|
5285
5286
|
return apiRequest("PATCH", `/v1/conversations/${encodeURIComponent(conversationId)}`, body);
|
|
5286
5287
|
}
|
|
5288
|
+
async function summarizeConversation(conversationId, body, options = {}) {
|
|
5289
|
+
return apiRequest("POST", `/v1/conversations/${encodeURIComponent(conversationId)}/summarize`, body, options);
|
|
5290
|
+
}
|
|
5287
5291
|
var init_conversations2 = __esm(() => {
|
|
5288
5292
|
init_request();
|
|
5289
5293
|
});
|
|
5290
5294
|
|
|
5291
5295
|
// src/constants.ts
|
|
5292
|
-
var DEFAULT_SUMMARIZATION_MODEL = "letta/auto", DEFAULT_AGENT_NAME = "Letta Code", INTERRUPTED_BY_USER = "Interrupted by user", TURN_DID_NOT_COMPLETE = "Turn did not complete", SYSTEM_REMINDER_TAG = "system-reminder", SYSTEM_REMINDER_OPEN, SYSTEM_REMINDER_CLOSE, SYSTEM_ALERT_TAG = "system-alert", SYSTEM_ALERT_OPEN, SYSTEM_ALERT_CLOSE, COMPACTION_SUMMARY_HEADER = "(Earlier messages in this conversation have been compacted to free up context, summarized below)", TOKEN_DISPLAY_THRESHOLD = 100, ELAPSED_DISPLAY_THRESHOLD_MS;
|
|
5296
|
+
var DEFAULT_SUMMARIZATION_MODEL = "letta/auto", DEFAULT_TITLE_SUMMARIZATION_MODEL = "letta/auto-fast", DEFAULT_AGENT_NAME = "Letta Code", INTERRUPTED_BY_USER = "Interrupted by user", TURN_DID_NOT_COMPLETE = "Turn did not complete", SYSTEM_REMINDER_TAG = "system-reminder", SYSTEM_REMINDER_OPEN, SYSTEM_REMINDER_CLOSE, SYSTEM_ALERT_TAG = "system-alert", SYSTEM_ALERT_OPEN, SYSTEM_ALERT_CLOSE, COMPACTION_SUMMARY_HEADER = "(Earlier messages in this conversation have been compacted to free up context, summarized below)", TOKEN_DISPLAY_THRESHOLD = 100, ELAPSED_DISPLAY_THRESHOLD_MS;
|
|
5293
5297
|
var init_constants = __esm(() => {
|
|
5294
5298
|
SYSTEM_REMINDER_OPEN = `<${SYSTEM_REMINDER_TAG}>`;
|
|
5295
5299
|
SYSTEM_REMINDER_CLOSE = `</${SYSTEM_REMINDER_TAG}>`;
|
|
@@ -5322,63 +5326,28 @@ function normalizeConversationTitle(value) {
|
|
|
5322
5326
|
}
|
|
5323
5327
|
return normalized.slice(0, CONVERSATION_TITLE_MAX_LENGTH);
|
|
5324
5328
|
}
|
|
5325
|
-
function
|
|
5326
|
-
if (
|
|
5327
|
-
return
|
|
5328
|
-
}
|
|
5329
|
-
if (Array.isArray(content)) {
|
|
5330
|
-
let collected = "";
|
|
5331
|
-
for (const part of content) {
|
|
5332
|
-
if (part && typeof part === "object" && "text" in part && typeof part.text === "string") {
|
|
5333
|
-
collected += part.text;
|
|
5334
|
-
}
|
|
5335
|
-
}
|
|
5336
|
-
return collected;
|
|
5329
|
+
async function generateConversationTitleFromSummary(conversationId, messages, model = DEFAULT_TITLE_SUMMARIZATION_MODEL) {
|
|
5330
|
+
if (messages.length === 0) {
|
|
5331
|
+
return null;
|
|
5337
5332
|
}
|
|
5338
|
-
return "";
|
|
5339
|
-
}
|
|
5340
|
-
async function generateConversationTitleFromFork(client, conversationId) {
|
|
5341
|
-
let forkId = null;
|
|
5342
5333
|
const abortController = new AbortController;
|
|
5343
5334
|
const timeoutId = setTimeout(() => abortController.abort(), CONVERSATION_TITLE_TIMEOUT_MS);
|
|
5344
5335
|
try {
|
|
5345
|
-
const
|
|
5346
|
-
|
|
5347
|
-
|
|
5348
|
-
|
|
5349
|
-
|
|
5350
|
-
|
|
5351
|
-
|
|
5352
|
-
|
|
5353
|
-
],
|
|
5354
|
-
override_model: DEFAULT_SUMMARIZATION_MODEL,
|
|
5355
|
-
override_system: CONVERSATION_TITLE_SYSTEM_PROMPT,
|
|
5356
|
-
max_steps: 1,
|
|
5357
|
-
streaming: true,
|
|
5358
|
-
stream_tokens: false,
|
|
5359
|
-
include_pings: false
|
|
5360
|
-
}, { signal: abortController.signal });
|
|
5361
|
-
let titleText = "";
|
|
5362
|
-
for await (const chunk of stream) {
|
|
5363
|
-
if (chunk && typeof chunk === "object" && "message_type" in chunk && chunk.message_type === "assistant_message") {
|
|
5364
|
-
titleText += extractAssistantText(chunk.content);
|
|
5365
|
-
}
|
|
5366
|
-
}
|
|
5367
|
-
return normalizeConversationTitle(titleText);
|
|
5336
|
+
const response = await summarizeConversation(conversationId, {
|
|
5337
|
+
prompt: CONVERSATION_TITLE_SYSTEM_PROMPT,
|
|
5338
|
+
messages,
|
|
5339
|
+
model
|
|
5340
|
+
}, {
|
|
5341
|
+
signal: abortController.signal
|
|
5342
|
+
});
|
|
5343
|
+
return normalizeConversationTitle(response.summary);
|
|
5368
5344
|
} catch (err) {
|
|
5369
5345
|
if (isDebugEnabled()) {
|
|
5370
|
-
console.error("[DEBUG]
|
|
5346
|
+
console.error("[DEBUG] generateConversationTitleFromSummary failed:", err);
|
|
5371
5347
|
}
|
|
5372
5348
|
return null;
|
|
5373
5349
|
} finally {
|
|
5374
5350
|
clearTimeout(timeoutId);
|
|
5375
|
-
if (forkId) {
|
|
5376
|
-
client.conversations.delete(forkId).catch((err) => {
|
|
5377
|
-
if (isDebugEnabled()) {
|
|
5378
|
-
console.error("[DEBUG] failed to delete title-fork conversation:", err);
|
|
5379
|
-
}
|
|
5380
|
-
});
|
|
5381
|
-
}
|
|
5382
5351
|
}
|
|
5383
5352
|
}
|
|
5384
5353
|
var CONVERSATION_TITLE_MAX_LENGTH = 100, CONVERSATION_TITLE_TIMEOUT_MS = 30000, CONVERSATION_TITLE_SYSTEM_PROMPT = `You are a conversation title generator.
|
|
@@ -5389,7 +5358,7 @@ Rules:
|
|
|
5389
5358
|
- describe the actual topic, not the mood
|
|
5390
5359
|
- no quotes, markdown, prefixes, or trailing punctuation
|
|
5391
5360
|
- never call any tools — reply with plain text only
|
|
5392
|
-
- avoid generic titles like "New conversation" or "Help request"
|
|
5361
|
+
- avoid generic titles like "New conversation" or "Help request"`;
|
|
5393
5362
|
var init_conversation_title = __esm(() => {
|
|
5394
5363
|
init_conversations2();
|
|
5395
5364
|
init_constants();
|
|
@@ -161725,6 +161694,104 @@ function disableExtensionsForProcess() {
|
|
|
161725
161694
|
}
|
|
161726
161695
|
var LETTA_DISABLE_EXTENSIONS_ENV = "LETTA_DISABLE_EXTENSIONS";
|
|
161727
161696
|
|
|
161697
|
+
// src/extensions/permission-registry.ts
|
|
161698
|
+
function getMutableExtensionPermissionsRegistry() {
|
|
161699
|
+
const global2 = globalThis;
|
|
161700
|
+
if (!global2[EXTENSION_PERMISSIONS_KEY]) {
|
|
161701
|
+
global2[EXTENSION_PERMISSIONS_KEY] = new Map;
|
|
161702
|
+
}
|
|
161703
|
+
return global2[EXTENSION_PERMISSIONS_KEY];
|
|
161704
|
+
}
|
|
161705
|
+
function getAvailableExtensionPermissionsRegistry() {
|
|
161706
|
+
if (areExtensionsDisabled())
|
|
161707
|
+
return new Map;
|
|
161708
|
+
return new Map(Array.from(getMutableExtensionPermissionsRegistry().entries()).filter(([, permission]) => {
|
|
161709
|
+
if (permission.activationSignal.aborted)
|
|
161710
|
+
return false;
|
|
161711
|
+
try {
|
|
161712
|
+
return permission.isAvailable();
|
|
161713
|
+
} catch {
|
|
161714
|
+
return false;
|
|
161715
|
+
}
|
|
161716
|
+
}));
|
|
161717
|
+
}
|
|
161718
|
+
function registerExtensionPermission(permission) {
|
|
161719
|
+
if (areExtensionsDisabled())
|
|
161720
|
+
return;
|
|
161721
|
+
getMutableExtensionPermissionsRegistry().set(permission.id, permission);
|
|
161722
|
+
}
|
|
161723
|
+
function unregisterExtensionPermission(id2, owner) {
|
|
161724
|
+
const registry2 = getMutableExtensionPermissionsRegistry();
|
|
161725
|
+
const existing = registry2.get(id2);
|
|
161726
|
+
if (existing?.owner?.id === owner.id) {
|
|
161727
|
+
registry2.delete(id2);
|
|
161728
|
+
}
|
|
161729
|
+
}
|
|
161730
|
+
function unregisterExtensionPermissionsForOwner(owner) {
|
|
161731
|
+
const registry2 = getMutableExtensionPermissionsRegistry();
|
|
161732
|
+
for (const [id2, permission] of registry2.entries()) {
|
|
161733
|
+
if (permission.owner?.id === owner.id) {
|
|
161734
|
+
registry2.delete(id2);
|
|
161735
|
+
}
|
|
161736
|
+
}
|
|
161737
|
+
}
|
|
161738
|
+
function clearExtensionPermissions() {
|
|
161739
|
+
getMutableExtensionPermissionsRegistry().clear();
|
|
161740
|
+
}
|
|
161741
|
+
function getExtensionPermissionDefinition(id2, registry2 = getMutableExtensionPermissionsRegistry()) {
|
|
161742
|
+
if (areExtensionsDisabled())
|
|
161743
|
+
return;
|
|
161744
|
+
return registry2.get(id2);
|
|
161745
|
+
}
|
|
161746
|
+
function normalizePermissionResult(result) {
|
|
161747
|
+
if (result === undefined)
|
|
161748
|
+
return;
|
|
161749
|
+
if (result.decision === "allow" || result.decision === "ask" || result.decision === "deny") {
|
|
161750
|
+
return result;
|
|
161751
|
+
}
|
|
161752
|
+
return;
|
|
161753
|
+
}
|
|
161754
|
+
function composePermissionDecision(decisions) {
|
|
161755
|
+
return decisions.find((result) => result.decision === "deny") ?? decisions.find((result) => result.decision === "ask") ?? decisions.find((result) => result.decision === "allow");
|
|
161756
|
+
}
|
|
161757
|
+
async function checkExtensionPermissions(event2, registry2 = getAvailableExtensionPermissionsRegistry()) {
|
|
161758
|
+
if (areExtensionsDisabled())
|
|
161759
|
+
return;
|
|
161760
|
+
const decisions = [];
|
|
161761
|
+
for (const permission of registry2.values()) {
|
|
161762
|
+
if (permission.activationSignal.aborted)
|
|
161763
|
+
continue;
|
|
161764
|
+
let rawResult;
|
|
161765
|
+
try {
|
|
161766
|
+
if (!permission.isAvailable())
|
|
161767
|
+
continue;
|
|
161768
|
+
rawResult = await permission.check(event2, {
|
|
161769
|
+
getContext: permission.getContext,
|
|
161770
|
+
signal: permission.activationSignal
|
|
161771
|
+
});
|
|
161772
|
+
} catch (error54) {
|
|
161773
|
+
return {
|
|
161774
|
+
decision: "deny",
|
|
161775
|
+
matchedRule: `extension permission:${permission.id}`,
|
|
161776
|
+
reason: `Extension permission '${permission.id}' failed: ${error54 instanceof Error ? error54.message : String(error54)}`
|
|
161777
|
+
};
|
|
161778
|
+
}
|
|
161779
|
+
const result = normalizePermissionResult(rawResult);
|
|
161780
|
+
if (!result)
|
|
161781
|
+
continue;
|
|
161782
|
+
decisions.push({
|
|
161783
|
+
decision: result.decision,
|
|
161784
|
+
matchedRule: `extension permission:${permission.id}`,
|
|
161785
|
+
reason: result.reason
|
|
161786
|
+
});
|
|
161787
|
+
}
|
|
161788
|
+
return composePermissionDecision(decisions);
|
|
161789
|
+
}
|
|
161790
|
+
var EXTENSION_PERMISSIONS_KEY;
|
|
161791
|
+
var init_permission_registry = __esm(() => {
|
|
161792
|
+
EXTENSION_PERMISSIONS_KEY = Symbol.for("@letta/extensionPermissions");
|
|
161793
|
+
});
|
|
161794
|
+
|
|
161728
161795
|
// src/extensions/tool-registry.ts
|
|
161729
161796
|
function getMutableExtensionToolsRegistry() {
|
|
161730
161797
|
const global2 = globalThis;
|
|
@@ -193099,8 +193166,28 @@ function getDefaultDecision(toolName, toolArgs) {
|
|
|
193099
193166
|
}
|
|
193100
193167
|
return "ask";
|
|
193101
193168
|
}
|
|
193102
|
-
async function checkPermissionWithHooks(toolName, toolArgs, permissions, workingDirectory = process.cwd(), modeState, agentId) {
|
|
193103
|
-
|
|
193169
|
+
async function checkPermissionWithHooks(toolName, toolArgs, permissions, workingDirectory = process.cwd(), modeState, agentId, extensionPermissions = getAvailableExtensionPermissionsRegistry(), extensionPermissionOptions = {}) {
|
|
193170
|
+
let result = checkPermission(toolName, toolArgs, permissions, workingDirectory, modeState, agentId);
|
|
193171
|
+
if (result.decision !== "deny") {
|
|
193172
|
+
const extensionDecision = await checkExtensionPermissions({
|
|
193173
|
+
agentId: agentId ?? null,
|
|
193174
|
+
conversationId: extensionPermissionOptions.conversationId ?? null,
|
|
193175
|
+
toolCallId: extensionPermissionOptions.toolCallId ?? null,
|
|
193176
|
+
toolName,
|
|
193177
|
+
args: toolArgs,
|
|
193178
|
+
cwd: workingDirectory,
|
|
193179
|
+
workingDirectory,
|
|
193180
|
+
permissionMode: modeState?.mode ?? permissionMode.getMode(),
|
|
193181
|
+
phase: extensionPermissionOptions.phase ?? "approval"
|
|
193182
|
+
}, extensionPermissions);
|
|
193183
|
+
if (extensionDecision) {
|
|
193184
|
+
result = {
|
|
193185
|
+
decision: extensionDecision.decision,
|
|
193186
|
+
matchedRule: extensionDecision.matchedRule,
|
|
193187
|
+
reason: extensionDecision.reason ?? `Matched ${extensionDecision.matchedRule}`
|
|
193188
|
+
};
|
|
193189
|
+
}
|
|
193190
|
+
}
|
|
193104
193191
|
if (result.decision === "ask") {
|
|
193105
193192
|
const hookResult = await runPermissionRequestHooks(toolName, toolArgs, "ask", undefined, workingDirectory, agentId);
|
|
193106
193193
|
if (hookResult.blocked) {
|
|
@@ -193126,6 +193213,7 @@ async function checkPermissionWithHooks(toolName, toolArgs, permissions, working
|
|
|
193126
193213
|
var WORKING_DIRECTORY_TOOLS_V2, WORKING_DIRECTORY_TOOLS_V1, READ_ONLY_SHELL_TOOLS, FILE_TOOLS_V2, FILE_TOOLS_V1, SAFE_AUTO_APPROVE_SUBAGENT_TYPES;
|
|
193127
193214
|
var init_checker = __esm(() => {
|
|
193128
193215
|
init_context();
|
|
193216
|
+
init_permission_registry();
|
|
193129
193217
|
init_tool_registry();
|
|
193130
193218
|
init_hooks2();
|
|
193131
193219
|
init_canonical();
|
|
@@ -195235,6 +195323,7 @@ function capturePreparedToolExecutionContext(snapshot, options3) {
|
|
|
195235
195323
|
externalTools: filterExternalToolsByClientAllowlist(snapshot.externalTools, options3?.clientToolAllowlist),
|
|
195236
195324
|
externalExecutor: snapshot.externalExecutor,
|
|
195237
195325
|
extensionEvents: options3?.extensionEvents ?? snapshot.extensionEvents,
|
|
195326
|
+
extensionPermissions: snapshot.extensionPermissions,
|
|
195238
195327
|
extensionTools: filterExtensionToolsByClientAllowlist(snapshot.extensionTools, options3?.clientToolAllowlist),
|
|
195239
195328
|
workingDirectory: runtimeContext.workingDirectory ?? getCurrentWorkingDirectory(),
|
|
195240
195329
|
runtimeContext,
|
|
@@ -195253,6 +195342,7 @@ function captureToolExecutionContext(workingDirectory = getCurrentWorkingDirecto
|
|
|
195253
195342
|
toolRegistry: new Map(toolRegistry),
|
|
195254
195343
|
externalTools: new Map(getExternalToolsRegistry()),
|
|
195255
195344
|
externalExecutor: getExternalToolExecutor(),
|
|
195345
|
+
extensionPermissions: getAvailableExtensionPermissionsRegistry(),
|
|
195256
195346
|
extensionTools: getAvailableExtensionToolsRegistry()
|
|
195257
195347
|
}, {
|
|
195258
195348
|
workingDirectory,
|
|
@@ -195268,6 +195358,7 @@ async function prepareCurrentToolExecutionContext(options3) {
|
|
|
195268
195358
|
externalTools: new Map(getExternalToolsRegistry()),
|
|
195269
195359
|
externalExecutor: getExternalToolExecutor(),
|
|
195270
195360
|
extensionEvents: options3?.extensionEvents,
|
|
195361
|
+
extensionPermissions: getAvailableExtensionPermissionsRegistry(),
|
|
195271
195362
|
extensionTools: getAvailableExtensionToolsRegistry()
|
|
195272
195363
|
}, options3);
|
|
195273
195364
|
}
|
|
@@ -195278,6 +195369,7 @@ async function prepareToolExecutionContextForSpecificTools(toolNames, options3)
|
|
|
195278
195369
|
externalTools: new Map(getExternalToolsRegistry()),
|
|
195279
195370
|
externalExecutor: getExternalToolExecutor(),
|
|
195280
195371
|
extensionEvents: options3?.extensionEvents,
|
|
195372
|
+
extensionPermissions: getAvailableExtensionPermissionsRegistry(),
|
|
195281
195373
|
extensionTools: getAvailableExtensionToolsRegistry()
|
|
195282
195374
|
}, options3);
|
|
195283
195375
|
}
|
|
@@ -195288,6 +195380,7 @@ async function prepareToolExecutionContextForModel(modelIdentifier, options3) {
|
|
|
195288
195380
|
externalTools: new Map(getExternalToolsRegistry()),
|
|
195289
195381
|
externalExecutor: getExternalToolExecutor(),
|
|
195290
195382
|
extensionEvents: options3?.extensionEvents,
|
|
195383
|
+
extensionPermissions: getAvailableExtensionPermissionsRegistry(),
|
|
195291
195384
|
extensionTools: getAvailableExtensionToolsRegistry()
|
|
195292
195385
|
}, options3);
|
|
195293
195386
|
}
|
|
@@ -195302,15 +195395,38 @@ function isExtensionToolParallelSafeForContext(toolName, contextId) {
|
|
|
195302
195395
|
const context2 = contextId ? getExecutionContextById(contextId) : undefined;
|
|
195303
195396
|
return isExtensionToolParallelSafe(toolName, context2?.extensionTools ?? getAvailableExtensionToolsRegistry());
|
|
195304
195397
|
}
|
|
195305
|
-
async function
|
|
195398
|
+
async function checkExtensionPermissionForContext(options3) {
|
|
195399
|
+
const runtimeContext = options3.context?.runtimeContext;
|
|
195400
|
+
const permissionModeState = options3.context?.permissionModeState;
|
|
195401
|
+
return checkExtensionPermissions({
|
|
195402
|
+
agentId: runtimeContext?.agentId ?? null,
|
|
195403
|
+
conversationId: runtimeContext?.conversationId ?? null,
|
|
195404
|
+
toolCallId: options3.toolCallId ?? null,
|
|
195405
|
+
toolName: options3.toolName,
|
|
195406
|
+
args: options3.args,
|
|
195407
|
+
cwd: options3.workingDirectory,
|
|
195408
|
+
workingDirectory: options3.workingDirectory,
|
|
195409
|
+
permissionMode: permissionModeState?.mode ?? runtimeContext?.permissionMode ?? null,
|
|
195410
|
+
phase: options3.phase
|
|
195411
|
+
}, options3.context?.extensionPermissions ?? getAvailableExtensionPermissionsRegistry());
|
|
195412
|
+
}
|
|
195413
|
+
async function checkToolPermission(toolName, toolArgs, workingDirectory, permissionModeStateArg, agentIdArg, toolContextIdArg, toolCallIdArg) {
|
|
195306
195414
|
const { checkPermissionWithHooks: checkPermissionWithHooks2 } = await Promise.resolve().then(() => (init_checker(), exports_checker));
|
|
195307
195415
|
const { loadPermissions: loadPermissions2 } = await Promise.resolve().then(() => (init_loader2(), exports_loader));
|
|
195308
|
-
const
|
|
195416
|
+
const context2 = toolContextIdArg ? getExecutionContextById(toolContextIdArg) : undefined;
|
|
195417
|
+
const effectiveWorkingDirectory = workingDirectory ?? context2?.workingDirectory ?? process.cwd();
|
|
195418
|
+
const effectivePermissionModeState = permissionModeStateArg ?? context2?.permissionModeState;
|
|
195419
|
+
const effectiveAgentId = agentIdArg ?? context2?.runtimeContext.agentId ?? undefined;
|
|
195420
|
+
const permissions = await loadPermissions2(effectiveWorkingDirectory);
|
|
195309
195421
|
return runWithRuntimeContext({
|
|
195310
|
-
...
|
|
195311
|
-
workingDirectory,
|
|
195312
|
-
permissionMode:
|
|
195313
|
-
}, () => checkPermissionWithHooks2(toolName, toolArgs, permissions,
|
|
195422
|
+
...effectiveAgentId ? { agentId: effectiveAgentId } : {},
|
|
195423
|
+
workingDirectory: effectiveWorkingDirectory,
|
|
195424
|
+
permissionMode: effectivePermissionModeState?.mode
|
|
195425
|
+
}, () => checkPermissionWithHooks2(toolName, toolArgs, permissions, effectiveWorkingDirectory, effectivePermissionModeState, effectiveAgentId, context2?.extensionPermissions ?? getAvailableExtensionPermissionsRegistry(), {
|
|
195426
|
+
conversationId: context2?.runtimeContext.conversationId ?? null,
|
|
195427
|
+
phase: "approval",
|
|
195428
|
+
toolCallId: toolCallIdArg ?? null
|
|
195429
|
+
}));
|
|
195314
195430
|
}
|
|
195315
195431
|
async function savePermissionRule2(rule, ruleType, scope, workingDirectory = process.cwd()) {
|
|
195316
195432
|
if (scope === "session") {
|
|
@@ -195687,9 +195803,12 @@ function cloneToolArgsForExtensionEvent(args) {
|
|
|
195687
195803
|
return { ...args };
|
|
195688
195804
|
}
|
|
195689
195805
|
}
|
|
195690
|
-
function
|
|
195806
|
+
function createExtensionPermissionToolResult(decision) {
|
|
195807
|
+
const isApprovalRequest = decision.decision === "ask";
|
|
195808
|
+
const action3 = isApprovalRequest ? "blocked" : "denied";
|
|
195809
|
+
const fallbackReason = isApprovalRequest ? "Approval requested but cannot reopen during execution." : "No reason given.";
|
|
195691
195810
|
return {
|
|
195692
|
-
toolReturn: `Error: Tool execution
|
|
195811
|
+
toolReturn: `Error: Tool execution ${action3} by ${decision.matchedRule}. ${decision.reason ?? fallbackReason}`,
|
|
195693
195812
|
status: "error"
|
|
195694
195813
|
};
|
|
195695
195814
|
}
|
|
@@ -195704,21 +195823,12 @@ async function emitToolStartEvent(options3) {
|
|
|
195704
195823
|
toolName: options3.toolName,
|
|
195705
195824
|
args: cloneToolArgsForExtensionEvent(options3.args)
|
|
195706
195825
|
};
|
|
195707
|
-
let emitResult;
|
|
195708
195826
|
try {
|
|
195709
|
-
|
|
195827
|
+
await emitExtensionEvent(options3.events, "tool_start", event2);
|
|
195710
195828
|
} catch (error54) {
|
|
195711
195829
|
debugLog("extensions", "tool_start event failed", error54);
|
|
195712
195830
|
return { args: options3.args };
|
|
195713
195831
|
}
|
|
195714
|
-
const firstDenial = emitResult?.results?.find((r2) => typeof r2 === "object" && r2 !== null && r2.deny === true);
|
|
195715
|
-
if (firstDenial) {
|
|
195716
|
-
debugLog("extensions", `tool_start denied: ${firstDenial.reason ?? "no reason given"}`);
|
|
195717
|
-
return {
|
|
195718
|
-
args: isToolStartArgs(event2.args) ? event2.args : options3.args,
|
|
195719
|
-
denied: { reason: firstDenial.reason }
|
|
195720
|
-
};
|
|
195721
|
-
}
|
|
195722
195832
|
return { args: isToolStartArgs(event2.args) ? event2.args : options3.args };
|
|
195723
195833
|
}
|
|
195724
195834
|
async function executeExtensionTool(toolName, tool2, args, executionScope, options3) {
|
|
@@ -195858,15 +195968,25 @@ async function executeTool(name, args, options3) {
|
|
|
195858
195968
|
status: "error"
|
|
195859
195969
|
};
|
|
195860
195970
|
}
|
|
195861
|
-
const { args: eventArgs2
|
|
195971
|
+
const { args: eventArgs2 } = await emitToolStartEvent({
|
|
195862
195972
|
args,
|
|
195863
195973
|
events: extensionEvents,
|
|
195864
195974
|
executionScope,
|
|
195865
195975
|
toolCallId: options3?.toolCallId,
|
|
195866
195976
|
toolName: name
|
|
195867
195977
|
});
|
|
195868
|
-
|
|
195869
|
-
|
|
195978
|
+
const permissionDecision2 = await checkExtensionPermissionForContext({
|
|
195979
|
+
args: eventArgs2,
|
|
195980
|
+
context: context2,
|
|
195981
|
+
phase: "execution",
|
|
195982
|
+
toolCallId: options3?.toolCallId,
|
|
195983
|
+
toolName: name,
|
|
195984
|
+
workingDirectory
|
|
195985
|
+
});
|
|
195986
|
+
if (permissionDecision2?.decision !== undefined) {
|
|
195987
|
+
if (permissionDecision2.decision !== "allow") {
|
|
195988
|
+
return createExtensionPermissionToolResult(permissionDecision2);
|
|
195989
|
+
}
|
|
195870
195990
|
}
|
|
195871
195991
|
return executeExtensionTool(name, extensionTool, eventArgs2, executionScope, {
|
|
195872
195992
|
signal: options3?.signal,
|
|
@@ -195877,15 +195997,25 @@ async function executeTool(name, args, options3) {
|
|
|
195877
195997
|
});
|
|
195878
195998
|
}
|
|
195879
195999
|
if (activeExternalTools.has(name)) {
|
|
195880
|
-
const { args: eventArgs2
|
|
196000
|
+
const { args: eventArgs2 } = await emitToolStartEvent({
|
|
195881
196001
|
args,
|
|
195882
196002
|
events: extensionEvents,
|
|
195883
196003
|
executionScope,
|
|
195884
196004
|
toolCallId: options3?.toolCallId,
|
|
195885
196005
|
toolName: name
|
|
195886
196006
|
});
|
|
195887
|
-
|
|
195888
|
-
|
|
196007
|
+
const permissionDecision2 = await checkExtensionPermissionForContext({
|
|
196008
|
+
args: eventArgs2,
|
|
196009
|
+
context: context2,
|
|
196010
|
+
phase: "execution",
|
|
196011
|
+
toolCallId: options3?.toolCallId,
|
|
196012
|
+
toolName: name,
|
|
196013
|
+
workingDirectory
|
|
196014
|
+
});
|
|
196015
|
+
if (permissionDecision2?.decision !== undefined) {
|
|
196016
|
+
if (permissionDecision2.decision !== "allow") {
|
|
196017
|
+
return createExtensionPermissionToolResult(permissionDecision2);
|
|
196018
|
+
}
|
|
195889
196019
|
}
|
|
195890
196020
|
return executeExternalTool(options3?.toolCallId ?? `ext-${Date.now()}`, name, eventArgs2, activeExternalExecutor);
|
|
195891
196021
|
}
|
|
@@ -195913,7 +196043,7 @@ async function executeTool(name, args, options3) {
|
|
|
195913
196043
|
status: "error"
|
|
195914
196044
|
};
|
|
195915
196045
|
}
|
|
195916
|
-
const { args: eventArgs
|
|
196046
|
+
const { args: eventArgs } = await emitToolStartEvent({
|
|
195917
196047
|
args,
|
|
195918
196048
|
events: extensionEvents,
|
|
195919
196049
|
executionScope,
|
|
@@ -195921,8 +196051,18 @@ async function executeTool(name, args, options3) {
|
|
|
195921
196051
|
toolName: internalName
|
|
195922
196052
|
});
|
|
195923
196053
|
args = eventArgs;
|
|
195924
|
-
|
|
195925
|
-
|
|
196054
|
+
const permissionDecision = await checkExtensionPermissionForContext({
|
|
196055
|
+
args,
|
|
196056
|
+
context: context2,
|
|
196057
|
+
phase: "execution",
|
|
196058
|
+
toolCallId: options3?.toolCallId,
|
|
196059
|
+
toolName: internalName,
|
|
196060
|
+
workingDirectory
|
|
196061
|
+
});
|
|
196062
|
+
if (permissionDecision?.decision !== undefined) {
|
|
196063
|
+
if (permissionDecision.decision !== "allow") {
|
|
196064
|
+
return createExtensionPermissionToolResult(permissionDecision);
|
|
196065
|
+
}
|
|
195926
196066
|
}
|
|
195927
196067
|
const startTime = Date.now();
|
|
195928
196068
|
const run = async () => {
|
|
@@ -196173,6 +196313,7 @@ var init_manager4 = __esm(async () => {
|
|
|
196173
196313
|
init_registry();
|
|
196174
196314
|
init_constants();
|
|
196175
196315
|
init_conversation_handle();
|
|
196316
|
+
init_permission_registry();
|
|
196176
196317
|
init_tool_registry();
|
|
196177
196318
|
init_hooks2();
|
|
196178
196319
|
init_mode();
|
|
@@ -257157,7 +257298,7 @@ async function classifyApprovals(approvals, opts = {}) {
|
|
|
257157
257298
|
continue;
|
|
257158
257299
|
}
|
|
257159
257300
|
}
|
|
257160
|
-
const permission = await checkToolPermission(toolName, parsedArgs, opts.workingDirectory, opts.permissionModeState, opts.agentId);
|
|
257301
|
+
const permission = await checkToolPermission(toolName, parsedArgs, opts.workingDirectory, opts.permissionModeState, opts.agentId, opts.toolContextId, approval.toolCallId);
|
|
257161
257302
|
const context3 = opts.getContext ? await opts.getContext(toolName, parsedArgs, opts.workingDirectory) : null;
|
|
257162
257303
|
let decision = permission.decision;
|
|
257163
257304
|
if (opts.alwaysRequiresUserInput?.(toolName) && decision === "allow") {
|
|
@@ -257823,7 +257964,7 @@ function normalizeConversationDescription(value) {
|
|
|
257823
257964
|
}
|
|
257824
257965
|
return trimToWordLimit(normalized, CONVERSATION_DESCRIPTION_MAX_WORDS);
|
|
257825
257966
|
}
|
|
257826
|
-
function
|
|
257967
|
+
function extractAssistantText(content) {
|
|
257827
257968
|
if (typeof content === "string") {
|
|
257828
257969
|
return content;
|
|
257829
257970
|
}
|
|
@@ -257862,7 +258003,7 @@ async function generateConversationDescriptionFromFork(client, conversationId) {
|
|
|
257862
258003
|
let descriptionText = "";
|
|
257863
258004
|
for await (const chunk of stream5) {
|
|
257864
258005
|
if (chunk && typeof chunk === "object" && "message_type" in chunk && chunk.message_type === "assistant_message") {
|
|
257865
|
-
descriptionText +=
|
|
258006
|
+
descriptionText += extractAssistantText(chunk.content);
|
|
257866
258007
|
}
|
|
257867
258008
|
}
|
|
257868
258009
|
return normalizeConversationDescription(descriptionText);
|
|
@@ -264270,6 +264411,7 @@ function cloneExtensionCapabilities(capabilities) {
|
|
|
264270
264411
|
tools: capabilities.events.tools,
|
|
264271
264412
|
turns: capabilities.events.turns
|
|
264272
264413
|
},
|
|
264414
|
+
permissions: capabilities.permissions,
|
|
264273
264415
|
providers: capabilities.providers,
|
|
264274
264416
|
ui: {
|
|
264275
264417
|
panels: capabilities.ui.panels,
|
|
@@ -264291,6 +264433,7 @@ var init_capabilities = __esm(() => {
|
|
|
264291
264433
|
tools: true,
|
|
264292
264434
|
turns: true
|
|
264293
264435
|
},
|
|
264436
|
+
permissions: true,
|
|
264294
264437
|
providers: true,
|
|
264295
264438
|
ui: {
|
|
264296
264439
|
panels: true,
|
|
@@ -264306,6 +264449,7 @@ var init_capabilities = __esm(() => {
|
|
|
264306
264449
|
tools: false,
|
|
264307
264450
|
turns: false
|
|
264308
264451
|
},
|
|
264452
|
+
permissions: false,
|
|
264309
264453
|
providers: false,
|
|
264310
264454
|
ui: {
|
|
264311
264455
|
panels: false,
|
|
@@ -264327,6 +264471,7 @@ function createDisabledExtensionRegistry() {
|
|
|
264327
264471
|
loadedPaths: [],
|
|
264328
264472
|
ownerAbortControllers: {},
|
|
264329
264473
|
owners: {},
|
|
264474
|
+
permissions: {},
|
|
264330
264475
|
sources: [],
|
|
264331
264476
|
tools: {},
|
|
264332
264477
|
ui: {
|
|
@@ -264357,6 +264502,7 @@ function createDisabledExtensionEngine(registry2) {
|
|
|
264357
264502
|
};
|
|
264358
264503
|
}
|
|
264359
264504
|
function createDisabledExtensionAdapter(options3) {
|
|
264505
|
+
clearExtensionPermissions();
|
|
264360
264506
|
clearExtensionTools();
|
|
264361
264507
|
clearRegisteredPiProviders();
|
|
264362
264508
|
let context3 = options3.initialContext;
|
|
@@ -264402,6 +264548,7 @@ function createDisabledExtensionAdapter(options3) {
|
|
|
264402
264548
|
var init_disabled_extension_adapter = __esm(() => {
|
|
264403
264549
|
init_pi_provider_extension_registry();
|
|
264404
264550
|
init_capabilities();
|
|
264551
|
+
init_permission_registry();
|
|
264405
264552
|
init_tool_registry();
|
|
264406
264553
|
});
|
|
264407
264554
|
|
|
@@ -433270,6 +433417,7 @@ function createEmptyExtensionRegistry(sources, generation, capabilities) {
|
|
|
433270
433417
|
loadedPaths: [],
|
|
433271
433418
|
ownerAbortControllers: {},
|
|
433272
433419
|
owners: {},
|
|
433420
|
+
permissions: {},
|
|
433273
433421
|
sources,
|
|
433274
433422
|
tools: {},
|
|
433275
433423
|
ui: {
|
|
@@ -433305,6 +433453,7 @@ function snapshotRegistryForReaders(registry2) {
|
|
|
433305
433453
|
loadedPaths: [...registry2.loadedPaths],
|
|
433306
433454
|
ownerAbortControllers: { ...registry2.ownerAbortControllers },
|
|
433307
433455
|
owners: { ...registry2.owners },
|
|
433456
|
+
permissions: { ...registry2.permissions },
|
|
433308
433457
|
sources: registry2.sources.map((source2) => ({
|
|
433309
433458
|
...source2,
|
|
433310
433459
|
files: [...source2.files]
|
|
@@ -433526,6 +433675,25 @@ function normalizeExtensionCommand(command, owner) {
|
|
|
433526
433675
|
run: command.run
|
|
433527
433676
|
};
|
|
433528
433677
|
}
|
|
433678
|
+
function validateExtensionPermissionId(id2) {
|
|
433679
|
+
if (!/^[a-z0-9][a-z0-9-]*$/.test(id2)) {
|
|
433680
|
+
throw new Error("Extension permission id must be a lowercase slug using letters, numbers, and hyphens");
|
|
433681
|
+
}
|
|
433682
|
+
}
|
|
433683
|
+
function normalizeExtensionPermission(permission, owner) {
|
|
433684
|
+
validateExtensionPermissionId(permission.id);
|
|
433685
|
+
if (typeof permission.check !== "function") {
|
|
433686
|
+
throw new Error(`Extension permission '${permission.id}' must include check()`);
|
|
433687
|
+
}
|
|
433688
|
+
return {
|
|
433689
|
+
id: permission.id,
|
|
433690
|
+
...permission.description ? { description: permission.description } : {},
|
|
433691
|
+
owner,
|
|
433692
|
+
path: owner.path,
|
|
433693
|
+
...permission.isEnabled ? { isEnabled: permission.isEnabled } : {},
|
|
433694
|
+
check: permission.check
|
|
433695
|
+
};
|
|
433696
|
+
}
|
|
433529
433697
|
function validateExtensionToolName(name) {
|
|
433530
433698
|
if (!/^[a-zA-Z0-9_-]{1,64}$/.test(name)) {
|
|
433531
433699
|
throw new Error("Extension tool name must be 1-64 characters using letters, numbers, underscores, or hyphens");
|
|
@@ -433631,6 +433799,19 @@ function createLettaExtensionApi(registry2, owner, capabilities, getClient2, get
|
|
|
433631
433799
|
onChange();
|
|
433632
433800
|
}
|
|
433633
433801
|
};
|
|
433802
|
+
const unregisterPermission = (id2) => {
|
|
433803
|
+
if (!capabilities.permissions)
|
|
433804
|
+
return;
|
|
433805
|
+
validateExtensionPermissionId(id2);
|
|
433806
|
+
if (!guardLive({ id: id2, kind: "permission" }))
|
|
433807
|
+
return;
|
|
433808
|
+
const existing = registry2.permissions[id2];
|
|
433809
|
+
if (existing?.owner?.id === owner.id) {
|
|
433810
|
+
delete registry2.permissions[id2];
|
|
433811
|
+
unregisterExtensionPermission(id2, owner);
|
|
433812
|
+
onChange();
|
|
433813
|
+
}
|
|
433814
|
+
};
|
|
433634
433815
|
const clearPanel = (id2) => {
|
|
433635
433816
|
if (!capabilities.ui.panels)
|
|
433636
433817
|
return;
|
|
@@ -433827,6 +434008,40 @@ function createLettaExtensionApi(registry2, owner, capabilities, getClient2, get
|
|
|
433827
434008
|
off: unregisterEvent,
|
|
433828
434009
|
on: onEvent
|
|
433829
434010
|
},
|
|
434011
|
+
permissions: {
|
|
434012
|
+
register(permission) {
|
|
434013
|
+
if (!capabilities.permissions) {
|
|
434014
|
+
return () => {
|
|
434015
|
+
return;
|
|
434016
|
+
};
|
|
434017
|
+
}
|
|
434018
|
+
if (!guardLive({ id: permission.id, kind: "permission" })) {
|
|
434019
|
+
return () => {
|
|
434020
|
+
return;
|
|
434021
|
+
};
|
|
434022
|
+
}
|
|
434023
|
+
const normalized = normalizeExtensionPermission(permission, owner);
|
|
434024
|
+
const existing = registry2.permissions[normalized.id];
|
|
434025
|
+
const existingGlobal = getExtensionPermissionDefinition(normalized.id);
|
|
434026
|
+
if (existing || existingGlobal) {
|
|
434027
|
+
throw new Error(`Extension permission '${normalized.id}' is already registered by ${existing?.path ?? existingGlobal?.path}`);
|
|
434028
|
+
}
|
|
434029
|
+
registry2.permissions[normalized.id] = normalized;
|
|
434030
|
+
registerExtensionPermission({
|
|
434031
|
+
...normalized,
|
|
434032
|
+
activationSignal: signal,
|
|
434033
|
+
getContext: getContext3,
|
|
434034
|
+
isAvailable: () => {
|
|
434035
|
+
if (signal.aborted)
|
|
434036
|
+
return false;
|
|
434037
|
+
return normalized.isEnabled?.(getContext3()) ?? true;
|
|
434038
|
+
}
|
|
434039
|
+
});
|
|
434040
|
+
onChange();
|
|
434041
|
+
return () => unregisterPermission(normalized.id);
|
|
434042
|
+
},
|
|
434043
|
+
unregister: unregisterPermission
|
|
434044
|
+
},
|
|
433830
434045
|
diagnostics: {
|
|
433831
434046
|
report: reportDiagnostic
|
|
433832
434047
|
},
|
|
@@ -434053,6 +434268,7 @@ function disposeLocalExtensions(registry2) {
|
|
|
434053
434268
|
}
|
|
434054
434269
|
for (const owner of Object.values(registry2.owners)) {
|
|
434055
434270
|
unregisterPiProvidersForOwner(owner.id);
|
|
434271
|
+
unregisterExtensionPermissionsForOwner(owner);
|
|
434056
434272
|
unregisterExtensionToolsForOwner(owner);
|
|
434057
434273
|
}
|
|
434058
434274
|
clearAvailableModelsCache();
|
|
@@ -434060,6 +434276,7 @@ function disposeLocalExtensions(registry2) {
|
|
|
434060
434276
|
registry2.events = {};
|
|
434061
434277
|
registry2.ownerAbortControllers = {};
|
|
434062
434278
|
registry2.owners = {};
|
|
434279
|
+
registry2.permissions = {};
|
|
434063
434280
|
registry2.tools = {};
|
|
434064
434281
|
registry2.ui.panels = {};
|
|
434065
434282
|
registry2.ui.statusOwners = {};
|
|
@@ -434164,6 +434381,7 @@ var init_extension_engine = __esm(async () => {
|
|
|
434164
434381
|
init_pi_provider_extension_registry();
|
|
434165
434382
|
init_capabilities();
|
|
434166
434383
|
init_conversation_handle();
|
|
434384
|
+
init_permission_registry();
|
|
434167
434385
|
init_tool_registry();
|
|
434168
434386
|
await init_message();
|
|
434169
434387
|
ts = __toESM(require_typescript(), 1);
|
|
@@ -434446,6 +434664,7 @@ var init_extension_adapter2 = __esm(async () => {
|
|
|
434446
434664
|
tools: false,
|
|
434447
434665
|
turns: false
|
|
434448
434666
|
},
|
|
434667
|
+
permissions: false,
|
|
434449
434668
|
providers: true,
|
|
434450
434669
|
ui: {
|
|
434451
434670
|
panels: false,
|
|
@@ -442568,6 +442787,7 @@ var init_headless_extension_adapter = __esm(async () => {
|
|
|
442568
442787
|
tools: true,
|
|
442569
442788
|
turns: true
|
|
442570
442789
|
},
|
|
442790
|
+
permissions: true,
|
|
442571
442791
|
providers: true,
|
|
442572
442792
|
ui: {
|
|
442573
442793
|
panels: false,
|
|
@@ -448050,6 +448270,7 @@ var init_capabilities2 = __esm(() => {
|
|
|
448050
448270
|
tools: true,
|
|
448051
448271
|
turns: true
|
|
448052
448272
|
},
|
|
448273
|
+
permissions: true,
|
|
448053
448274
|
providers: true,
|
|
448054
448275
|
ui: {
|
|
448055
448276
|
panels: true,
|
|
@@ -451057,7 +451278,11 @@ var init_InlineMemoryApproval = __esm(async () => {
|
|
|
451057
451278
|
});
|
|
451058
451279
|
|
|
451059
451280
|
// src/cli/components/InlineQuestionApproval.tsx
|
|
451060
|
-
|
|
451281
|
+
function shouldRenderQuestionAsMarkdown(question) {
|
|
451282
|
+
return question.includes(`
|
|
451283
|
+
`) || MARKDOWN_QUESTION_PATTERNS.some((pattern4) => pattern4.test(question));
|
|
451284
|
+
}
|
|
451285
|
+
var import_react52, jsx_dev_runtime26, SOLID_LINE8 = "─", MARKDOWN_QUESTION_PATTERNS, InlineQuestionApproval;
|
|
451061
451286
|
var init_InlineQuestionApproval = __esm(async () => {
|
|
451062
451287
|
init_use_progress_indicator();
|
|
451063
451288
|
init_use_terminal_width();
|
|
@@ -451065,10 +451290,21 @@ var init_InlineQuestionApproval = __esm(async () => {
|
|
|
451065
451290
|
init_colors();
|
|
451066
451291
|
await __promiseAll([
|
|
451067
451292
|
init_build4(),
|
|
451293
|
+
init_MarkdownDisplay(),
|
|
451068
451294
|
init_Text2()
|
|
451069
451295
|
]);
|
|
451070
451296
|
import_react52 = __toESM(require_react(), 1);
|
|
451071
451297
|
jsx_dev_runtime26 = __toESM(require_jsx_dev_runtime(), 1);
|
|
451298
|
+
MARKDOWN_QUESTION_PATTERNS = [
|
|
451299
|
+
/^#{1,6}\s+/m,
|
|
451300
|
+
/^\s*[-*+]\s+/m,
|
|
451301
|
+
/^\s*\d+\.\s+/m,
|
|
451302
|
+
/^>\s+/m,
|
|
451303
|
+
/^```/m,
|
|
451304
|
+
/\|.+\|\n\|[\s:]*-+/m,
|
|
451305
|
+
/\*\*[^*]+\*\*/,
|
|
451306
|
+
/`[^`]+`/
|
|
451307
|
+
];
|
|
451072
451308
|
InlineQuestionApproval = import_react52.memo(({ questions, onSubmit, onCancel, isFocused = true }) => {
|
|
451073
451309
|
const [currentQuestionIndex, setCurrentQuestionIndex] = import_react52.useState(0);
|
|
451074
451310
|
const [answers, setAnswers] = import_react52.useState({});
|
|
@@ -451251,6 +451487,8 @@ var init_InlineQuestionApproval = __esm(async () => {
|
|
|
451251
451487
|
}
|
|
451252
451488
|
}, { isActive: isFocused });
|
|
451253
451489
|
const solidLine = SOLID_LINE8.repeat(Math.max(columns, 10));
|
|
451490
|
+
const questionText = currentQuestion?.question ?? "";
|
|
451491
|
+
const renderQuestionAsMarkdown = shouldRenderQuestionAsMarkdown(questionText);
|
|
451254
451492
|
const memoizedHeaderContent = import_react52.useMemo(() => /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(jsx_dev_runtime26.Fragment, {
|
|
451255
451493
|
children: [
|
|
451256
451494
|
/* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text2, {
|
|
@@ -451263,9 +451501,11 @@ var init_InlineQuestionApproval = __esm(async () => {
|
|
|
451263
451501
|
/* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Box_default, {
|
|
451264
451502
|
height: 1
|
|
451265
451503
|
}, undefined, false, undefined, this),
|
|
451266
|
-
/* @__PURE__ */ jsx_dev_runtime26.jsxDEV(
|
|
451504
|
+
renderQuestionAsMarkdown ? /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(MarkdownDisplay, {
|
|
451505
|
+
text: questionText
|
|
451506
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text2, {
|
|
451267
451507
|
bold: true,
|
|
451268
|
-
children:
|
|
451508
|
+
children: questionText
|
|
451269
451509
|
}, undefined, false, undefined, this),
|
|
451270
451510
|
/* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Box_default, {
|
|
451271
451511
|
height: 1
|
|
@@ -451285,9 +451525,10 @@ var init_InlineQuestionApproval = __esm(async () => {
|
|
|
451285
451525
|
]
|
|
451286
451526
|
}, undefined, true, undefined, this), [
|
|
451287
451527
|
currentQuestion?.header,
|
|
451288
|
-
currentQuestion?.question,
|
|
451289
451528
|
currentQuestionIndex,
|
|
451290
451529
|
questions.length,
|
|
451530
|
+
questionText,
|
|
451531
|
+
renderQuestionAsMarkdown,
|
|
451291
451532
|
solidLine
|
|
451292
451533
|
]);
|
|
451293
451534
|
const hintText = currentQuestion?.multiSelect ? "Enter to toggle · Arrow to navigate · Esc to cancel" : "Enter to select · Arrow to navigate · Esc to cancel";
|
|
@@ -468230,6 +468471,11 @@ function providerSelectionFlow(provider, connectedProviderId) {
|
|
|
468230
468471
|
return "multiInput";
|
|
468231
468472
|
return "input";
|
|
468232
468473
|
}
|
|
468474
|
+
function fieldValuesFromProviderPlaceholders(fields) {
|
|
468475
|
+
if (!fields)
|
|
468476
|
+
return {};
|
|
468477
|
+
return Object.fromEntries(fields.filter((field) => !field.secret && field.placeholder).map((field) => [field.key, field.placeholder]));
|
|
468478
|
+
}
|
|
468233
468479
|
function isProviderTargetLoading(input) {
|
|
468234
468480
|
return input.connectedProvidersByTarget[input.selectedTarget] === undefined && (input.selectedTarget === "local" || input.showProviderStoreTabs);
|
|
468235
468481
|
}
|
|
@@ -468431,7 +468677,7 @@ function ProviderSelector({
|
|
|
468431
468677
|
setMethodIndex(0);
|
|
468432
468678
|
} else if (flow === "multiInput") {
|
|
468433
468679
|
setViewState({ type: "multiInput", provider });
|
|
468434
|
-
setFieldValues(
|
|
468680
|
+
setFieldValues(fieldValuesFromProviderPlaceholders(provider.fields));
|
|
468435
468681
|
setFocusedFieldIndex(0);
|
|
468436
468682
|
setValidationState("idle");
|
|
468437
468683
|
setValidationError(null);
|
|
@@ -490746,7 +490992,7 @@ function useApprovalFlow(ctx) {
|
|
|
490746
490992
|
if (remainingApprovals.length > 0) {
|
|
490747
490993
|
const recheckResults = await Promise.all(remainingApprovals.map(async (approval) => {
|
|
490748
490994
|
const parsedArgs2 = safeJsonParseOr(approval.toolArgs, {});
|
|
490749
|
-
const permission = await checkToolPermission(approval.toolName, parsedArgs2);
|
|
490995
|
+
const permission = await checkToolPermission(approval.toolName, parsedArgs2, undefined, undefined, undefined, approvalToolContextIdRef.current, approval.toolCallId);
|
|
490750
490996
|
return { approval, permission };
|
|
490751
490997
|
}));
|
|
490752
490998
|
const nowAutoAllowed = recheckResults.filter((r5) => r5.permission.decision === "allow");
|
|
@@ -490862,7 +491108,8 @@ function useApprovalFlow(ctx) {
|
|
|
490862
491108
|
setAutoHandledResults,
|
|
490863
491109
|
setIsExecutingTool,
|
|
490864
491110
|
setPendingApprovals,
|
|
490865
|
-
setThinkingMessage
|
|
491111
|
+
setThinkingMessage,
|
|
491112
|
+
approvalToolContextIdRef
|
|
490866
491113
|
]);
|
|
490867
491114
|
const handleDenyCurrent = import_react113.useCallback(async (reason) => {
|
|
490868
491115
|
if (isExecutingTool)
|
|
@@ -492989,11 +493236,14 @@ ${feedback}
|
|
|
492989
493236
|
}
|
|
492990
493237
|
if (shouldAutoGenerateConversationTitleRef.current && !isAutoConversationTitleInFlightRef.current && conversationIdRef.current !== "default") {
|
|
492991
493238
|
isAutoConversationTitleInFlightRef.current = true;
|
|
493239
|
+
const titleConversationId = conversationIdRef.current;
|
|
492992
493240
|
const conversationTitle = await generateConversationTitle();
|
|
492993
493241
|
if (!conversationTitle) {
|
|
492994
493242
|
isAutoConversationTitleInFlightRef.current = false;
|
|
493243
|
+
} else if (!shouldAutoGenerateConversationTitleRef.current || conversationIdRef.current !== titleConversationId) {
|
|
493244
|
+
isAutoConversationTitleInFlightRef.current = false;
|
|
492995
493245
|
} else {
|
|
492996
|
-
getBackend().updateConversation(
|
|
493246
|
+
getBackend().updateConversation(titleConversationId, {
|
|
492997
493247
|
summary: conversationTitle
|
|
492998
493248
|
}).then(() => {
|
|
492999
493249
|
shouldAutoGenerateConversationTitleRef.current = false;
|
|
@@ -493148,7 +493398,8 @@ ${feedback}
|
|
|
493148
493398
|
const { needsUserInput, autoAllowed, autoDenied } = await classifyApprovals(approvalsToProcess, {
|
|
493149
493399
|
getContext: analyzeToolApproval,
|
|
493150
493400
|
alwaysRequiresUserInput,
|
|
493151
|
-
missingNameReason: "Tool call incomplete - missing name or arguments"
|
|
493401
|
+
missingNameReason: "Tool call incomplete - missing name or arguments",
|
|
493402
|
+
toolContextId: approvalToolContextIdRef.current
|
|
493152
493403
|
});
|
|
493153
493404
|
for (const ac of [...autoAllowed, ...needsUserInput]) {
|
|
493154
493405
|
const toolName = ac.approval.toolName;
|
|
@@ -499973,12 +500224,14 @@ function App2({
|
|
|
499973
500224
|
const _queuedSystemPromptRecompileByConversationRef = import_react123.useRef(new Set);
|
|
499974
500225
|
const shouldAutoGenerateConversationTitleRef = import_react123.useRef(!resumedExistingConversation);
|
|
499975
500226
|
const isAutoConversationTitleInFlightRef = import_react123.useRef(false);
|
|
500227
|
+
const autoConversationTitleStartIndexRef = import_react123.useRef(!resumedExistingConversation ? 0 : null);
|
|
499976
500228
|
const shouldAutoGenerateConversationDescriptionRef = import_react123.useRef(!resumedExistingConversation);
|
|
499977
500229
|
const isAutoConversationDescriptionInFlightRef = import_react123.useRef(false);
|
|
499978
500230
|
const firstUserQueryRef = import_react123.useRef(null);
|
|
499979
500231
|
const setConversationAutoTitleEligibility = import_react123.useCallback((enabled) => {
|
|
499980
500232
|
shouldAutoGenerateConversationTitleRef.current = enabled;
|
|
499981
500233
|
isAutoConversationTitleInFlightRef.current = false;
|
|
500234
|
+
autoConversationTitleStartIndexRef.current = enabled ? buffersRef.current.order.length : null;
|
|
499982
500235
|
shouldAutoGenerateConversationDescriptionRef.current = enabled;
|
|
499983
500236
|
isAutoConversationDescriptionInFlightRef.current = false;
|
|
499984
500237
|
firstUserQueryRef.current = null;
|
|
@@ -500012,8 +500265,30 @@ function App2({
|
|
|
500012
500265
|
return fallback;
|
|
500013
500266
|
}
|
|
500014
500267
|
try {
|
|
500015
|
-
const
|
|
500016
|
-
const
|
|
500268
|
+
const messages = [];
|
|
500269
|
+
const startIndex = autoConversationTitleStartIndexRef.current ?? 0;
|
|
500270
|
+
const titleLineIds = buffersRef.current.order.slice(Math.min(startIndex, buffersRef.current.order.length));
|
|
500271
|
+
for (const lineId of titleLineIds) {
|
|
500272
|
+
const line = buffersRef.current.byId.get(lineId);
|
|
500273
|
+
if (line?.kind === "user" || line?.kind === "assistant") {
|
|
500274
|
+
const content = line.text.trim();
|
|
500275
|
+
if (content) {
|
|
500276
|
+
messages.push({ role: line.kind, content });
|
|
500277
|
+
}
|
|
500278
|
+
}
|
|
500279
|
+
}
|
|
500280
|
+
let summaryModel;
|
|
500281
|
+
if (currentModelLabel) {
|
|
500282
|
+
try {
|
|
500283
|
+
const providers = await listProviders2();
|
|
500284
|
+
const byokProviderAliases = buildByokProviderAliases(providers);
|
|
500285
|
+
summaryModel = isByokHandleForSelector(currentModelLabel, byokProviderAliases) ? currentModelLabel : undefined;
|
|
500286
|
+
} catch {
|
|
500287
|
+
const byokProviderAliases = buildByokProviderAliases([]);
|
|
500288
|
+
summaryModel = isByokHandleForSelector(currentModelLabel, byokProviderAliases) ? currentModelLabel : undefined;
|
|
500289
|
+
}
|
|
500290
|
+
}
|
|
500291
|
+
const aiTitle = await generateConversationTitleFromSummary(conversationId2, messages, summaryModel);
|
|
500017
500292
|
return aiTitle ?? fallback;
|
|
500018
500293
|
} catch (err) {
|
|
500019
500294
|
if (isDebugEnabled()) {
|
|
@@ -500021,7 +500296,7 @@ function App2({
|
|
|
500021
500296
|
}
|
|
500022
500297
|
return fallback;
|
|
500023
500298
|
}
|
|
500024
|
-
}, [deriveAutoConversationTitle]);
|
|
500299
|
+
}, [deriveAutoConversationTitle, currentModelLabel]);
|
|
500025
500300
|
const generateConversationDescription = import_react123.useCallback(async (options3) => {
|
|
500026
500301
|
if (!experimentManager.isEnabled("desktop_conversation_bootstrap")) {
|
|
500027
500302
|
return;
|
|
@@ -502634,6 +502909,7 @@ var init_AppCoordinator = __esm(async () => {
|
|
|
502634
502909
|
init_goal_loop_mode();
|
|
502635
502910
|
init_hooks2();
|
|
502636
502911
|
init_mode();
|
|
502912
|
+
init_byok_providers();
|
|
502637
502913
|
init_openai_codex_provider();
|
|
502638
502914
|
init_queue_runtime();
|
|
502639
502915
|
init_runtime_context();
|
|
@@ -514658,6 +514934,7 @@ init_message_tool();
|
|
|
514658
514934
|
init_registry();
|
|
514659
514935
|
init_constants();
|
|
514660
514936
|
init_conversation_handle();
|
|
514937
|
+
init_permission_registry();
|
|
514661
514938
|
init_tool_registry();
|
|
514662
514939
|
init_hooks2();
|
|
514663
514940
|
init_mode();
|
|
@@ -516848,4 +517125,4 @@ Error during initialization: ${message}`);
|
|
|
516848
517125
|
}
|
|
516849
517126
|
main2();
|
|
516850
517127
|
|
|
516851
|
-
//# debugId=
|
|
517128
|
+
//# debugId=0844D2D27038729C64756E2164756E21
|