localclawd 2.0.8 → 2.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 (3) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.mjs +171 -99
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -22,7 +22,7 @@ The project focuses on four areas:
22
22
  - Compact-context controls for local models that degrade before their advertised context limit.
23
23
  - Multimodal passthrough for local models that support image and screenshot input.
24
24
  - **Lattice memory scoring** — memory files tagged with `tags:` frontmatter are ranked using Jaccard similarity and co-occurrence lattice math. Works offline as a fallback when a hosted side-query model is unavailable.
25
- - **`/keepgoing`** — autonomous task continuation loop. The model works through all outstanding steps without waiting for user input and re-queues itself after each response. Stops when the model emits `TASK COMPLETE:` or `NEEDS INPUT:`. Aliases: `/kg`, `/continue`.
25
+ - **`/keepgoing`** — autonomous task continuation loop. After each round, a lightweight synthesis agent analyzes the full conversation and writes a precise directive for the next round the model doesn't need to self-direct. Stops when the user presses Ctrl+C or sends `/stop`. Aliases: `/kg`, `/continue`.
26
26
  - **`/buddy`** — spawns a named ASCII animal companion for the session with a personality. Use `/buddy pet` to hear their thoughts on the current codebase.
27
27
  - **`/images`** — quick-start slash command that forwards into the project-local image pipeline setup flow, with ComfyUI-first defaults and helper scaffolding.
28
28
  - **`/image-pipeline`** — scaffolds and uses a project-local image generation workflow for game textures, sprites, and related art assets under `.localclawd/image-pipeline/`, then visually reviews outputs when the current model/runtime supports image reads.
package/dist/cli.mjs CHANGED
@@ -87608,7 +87608,7 @@ var init_isEqual = __esm(() => {
87608
87608
 
87609
87609
  // src/utils/userAgent.ts
87610
87610
  function getClaudeCodeUserAgent() {
87611
- return `claude-code/${"2.0.8"}`;
87611
+ return `claude-code/${"2.1.0"}`;
87612
87612
  }
87613
87613
 
87614
87614
  // src/utils/workloadContext.ts
@@ -87630,7 +87630,7 @@ function getUserAgent() {
87630
87630
  const clientApp = process.env.CLAUDE_AGENT_SDK_CLIENT_APP ? `, client-app/${process.env.CLAUDE_AGENT_SDK_CLIENT_APP}` : "";
87631
87631
  const workload = getWorkload();
87632
87632
  const workloadSuffix = workload ? `, workload/${workload}` : "";
87633
- return `claude-cli/${"2.0.8"} (${process.env.USER_TYPE}, ${process.env.CLAUDE_CODE_ENTRYPOINT ?? "cli"}${agentSdkVersion}${clientApp}${workloadSuffix})`;
87633
+ return `claude-cli/${"2.1.0"} (${process.env.USER_TYPE}, ${process.env.CLAUDE_CODE_ENTRYPOINT ?? "cli"}${agentSdkVersion}${clientApp}${workloadSuffix})`;
87634
87634
  }
87635
87635
  function getMCPUserAgent() {
87636
87636
  const parts = [];
@@ -87644,7 +87644,7 @@ function getMCPUserAgent() {
87644
87644
  parts.push(`client-app/${process.env.CLAUDE_AGENT_SDK_CLIENT_APP}`);
87645
87645
  }
87646
87646
  const suffix = parts.length > 0 ? ` (${parts.join(", ")})` : "";
87647
- return `claude-code/${"2.0.8"}${suffix}`;
87647
+ return `claude-code/${"2.1.0"}${suffix}`;
87648
87648
  }
87649
87649
  function getWebFetchUserAgent() {
87650
87650
  return `Claude-User (${getClaudeCodeUserAgent()}; +https://support.anthropic.com/)`;
@@ -88024,14 +88024,14 @@ async function* iterateSseEvents(body) {
88024
88024
  }
88025
88025
  }
88026
88026
  }
88027
- function createStreamingResponse(upstream, model) {
88027
+ function createStreamingResponse(upstream, model, estimatedInputTokens = 0) {
88028
88028
  const requestId = upstream.headers.get("x-request-id") || randomUUID2();
88029
88029
  const stream4 = new ReadableStream({
88030
88030
  async start(controller) {
88031
88031
  const messageId = `msg_${randomUUID2()}`;
88032
88032
  const contentBlockIndexes = new Map;
88033
88033
  let nextIndex = 0;
88034
- let finalUsage = toAnthropicUsage(undefined);
88034
+ let finalUsage = { ...toAnthropicUsage(undefined), input_tokens: estimatedInputTokens };
88035
88035
  let finalStopReason = null;
88036
88036
  controller.enqueue(encodeSse("message_start", {
88037
88037
  type: "message_start",
@@ -88213,7 +88213,7 @@ function buildLocalLLMFetch(inner) {
88213
88213
  }
88214
88214
  const model = openAiRequest.model;
88215
88215
  if (requestBody.stream) {
88216
- return createStreamingResponse(upstream, model);
88216
+ return createStreamingResponse(upstream, model, estimateTokensFromRequest(requestBody));
88217
88217
  }
88218
88218
  const payload = await upstream.json();
88219
88219
  const anthropicResponse = buildAnthropicMessageFromOpenAI(payload, model);
@@ -130791,7 +130791,7 @@ function getAttributionHeader(fingerprint) {
130791
130791
  if (!isAttributionHeaderEnabled()) {
130792
130792
  return "";
130793
130793
  }
130794
- const version = `${"2.0.8"}.${fingerprint}`;
130794
+ const version = `${"2.1.0"}.${fingerprint}`;
130795
130795
  const entrypoint = process.env.CLAUDE_CODE_ENTRYPOINT ?? "unknown";
130796
130796
  const cch = "";
130797
130797
  const workload = getWorkload();
@@ -146980,7 +146980,7 @@ var init_metadata = __esm(() => {
146980
146980
  COMPOUND_OPERATOR_REGEX = /\s*(?:&&|\|\||[;|])\s*/;
146981
146981
  WHITESPACE_REGEX = /\s+/;
146982
146982
  getVersionBase = memoize_default(() => {
146983
- const match = "2.0.8".match(/^\d+\.\d+\.\d+(?:-[a-z]+)?/);
146983
+ const match = "2.1.0".match(/^\d+\.\d+\.\d+(?:-[a-z]+)?/);
146984
146984
  return match ? match[0] : undefined;
146985
146985
  });
146986
146986
  buildEnvContext = memoize_default(async () => {
@@ -147020,9 +147020,9 @@ var init_metadata = __esm(() => {
147020
147020
  isGithubAction: isEnvTruthy(process.env.GITHUB_ACTIONS),
147021
147021
  isClaudeCodeAction: isEnvTruthy(process.env.CLAUDE_CODE_ACTION),
147022
147022
  isClaudeAiAuth: isClaudeAISubscriber(),
147023
- version: "2.0.8",
147023
+ version: "2.1.0",
147024
147024
  versionBase: getVersionBase(),
147025
- buildTime: "2026-05-09T15:53:14.625Z",
147025
+ buildTime: "2026-05-09T16:28:38.867Z",
147026
147026
  deploymentEnvironment: env3.detectDeploymentEnvironment(),
147027
147027
  ...isEnvTruthy(process.env.GITHUB_ACTIONS) && {
147028
147028
  githubEventName: process.env.GITHUB_EVENT_NAME,
@@ -179598,7 +179598,7 @@ function getTelemetryAttributes() {
179598
179598
  attributes["session.id"] = sessionId;
179599
179599
  }
179600
179600
  if (shouldIncludeAttribute("OTEL_METRICS_INCLUDE_VERSION")) {
179601
- attributes["app.version"] = "2.0.8";
179601
+ attributes["app.version"] = "2.1.0";
179602
179602
  }
179603
179603
  const oauthAccount = getOauthAccountInfo();
179604
179604
  if (oauthAccount) {
@@ -180498,11 +180498,7 @@ var init_sessionMemoryCompact = __esm(() => {
180498
180498
  // src/services/compact/autoCompact.ts
180499
180499
  function getEffectiveContextWindowSize(model) {
180500
180500
  const reservedTokensForSummary = Math.min(getMaxOutputTokensForModel(model), MAX_OUTPUT_TOKENS_FOR_SUMMARY);
180501
- let contextWindow = getContextWindowForModel(model, getSdkBetas());
180502
- const autoCompactWindow = getConfiguredCompactContextWindow();
180503
- if (autoCompactWindow) {
180504
- contextWindow = Math.min(contextWindow, autoCompactWindow);
180505
- }
180501
+ const contextWindow = getContextWindowForModel(model, getSdkBetas());
180506
180502
  const MIN_EFFECTIVE_TOKENS = 4000;
180507
180503
  return Math.max(contextWindow - reservedTokensForSummary, Math.max(Math.floor(contextWindow * 0.25), MIN_EFFECTIVE_TOKENS));
180508
180504
  }
@@ -180553,7 +180549,7 @@ function isAutoCompactEnabled() {
180553
180549
  return true;
180554
180550
  }
180555
180551
  async function shouldAutoCompact(messages, model, querySource, snipTokensFreed = 0) {
180556
- if (querySource === "session_memory" || querySource === "compact") {
180552
+ if (querySource === "session_memory" || querySource === "compact" || querySource === "keepgoing_synthesis") {
180557
180553
  return false;
180558
180554
  }
180559
180555
  if (false) {}
@@ -242402,7 +242398,7 @@ function getInstallationEnv() {
242402
242398
  return;
242403
242399
  }
242404
242400
  function getClaudeCodeVersion() {
242405
- return "2.0.8";
242401
+ return "2.1.0";
242406
242402
  }
242407
242403
  async function getInstalledVSCodeExtensionVersion(command) {
242408
242404
  const { stdout } = await execFileNoThrow(command, ["--list-extensions", "--show-versions"], {
@@ -247676,7 +247672,7 @@ async function setupSdkMcpClients(sdkMcpConfigs, sendMcpMessage) {
247676
247672
  const client4 = new Client({
247677
247673
  name: "localclawd",
247678
247674
  title: "localclawd",
247679
- version: "2.0.8",
247675
+ version: "2.1.0",
247680
247676
  description: "local-first AI coding tool",
247681
247677
  websiteUrl: PRODUCT_URL
247682
247678
  }, {
@@ -248018,7 +248014,7 @@ var init_client9 = __esm(() => {
248018
248014
  const client4 = new Client({
248019
248015
  name: "localclawd",
248020
248016
  title: "localclawd",
248021
- version: "2.0.8",
248017
+ version: "2.1.0",
248022
248018
  description: "local-first AI coding tool",
248023
248019
  websiteUrl: PRODUCT_URL
248024
248020
  }, {
@@ -262420,7 +262416,7 @@ function computeFingerprint(messageText, version) {
262420
262416
  }
262421
262417
  function computeFingerprintFromMessages(messages) {
262422
262418
  const firstMessageText = extractFirstMessageText(messages);
262423
- return computeFingerprint(firstMessageText, "2.0.8");
262419
+ return computeFingerprint(firstMessageText, "2.1.0");
262424
262420
  }
262425
262421
  var FINGERPRINT_SALT = "59cf53e54c78";
262426
262422
  var init_fingerprint = () => {};
@@ -262462,7 +262458,7 @@ async function sideQuery(opts) {
262462
262458
  betas.push(STRUCTURED_OUTPUTS_BETA_HEADER);
262463
262459
  }
262464
262460
  const messageText = extractFirstUserMessageText(messages);
262465
- const fingerprint = computeFingerprint(messageText, "2.0.8");
262461
+ const fingerprint = computeFingerprint(messageText, "2.1.0");
262466
262462
  const attributionHeader = getAttributionHeader(fingerprint);
262467
262463
  const systemBlocks = [
262468
262464
  attributionHeader ? { type: "text", text: attributionHeader } : null,
@@ -283210,7 +283206,7 @@ var init_user = __esm(() => {
283210
283206
  deviceId,
283211
283207
  sessionId: getSessionId(),
283212
283208
  email: getEmail(),
283213
- appVersion: "2.0.8",
283209
+ appVersion: "2.1.0",
283214
283210
  platform: getHostPlatformForAnalytics(),
283215
283211
  organizationUuid,
283216
283212
  accountUuid,
@@ -284275,7 +284271,7 @@ async function initializeBetaTracing(resource) {
284275
284271
  });
284276
284272
  logs.setGlobalLoggerProvider(loggerProvider);
284277
284273
  setLoggerProvider(loggerProvider);
284278
- const eventLogger = logs.getLogger("com.anthropic.claude_code.events", "2.0.8");
284274
+ const eventLogger = logs.getLogger("com.anthropic.claude_code.events", "2.1.0");
284279
284275
  setEventLogger(eventLogger);
284280
284276
  process.on("beforeExit", async () => {
284281
284277
  await loggerProvider?.forceFlush();
@@ -284315,7 +284311,7 @@ async function initializeTelemetry() {
284315
284311
  const platform2 = getPlatform();
284316
284312
  const baseAttributes = {
284317
284313
  [ATTR_SERVICE_NAME4]: "claude-code",
284318
- [ATTR_SERVICE_VERSION4]: "2.0.8"
284314
+ [ATTR_SERVICE_VERSION4]: "2.1.0"
284319
284315
  };
284320
284316
  if (platform2 === "wsl") {
284321
284317
  const wslVersion = getWslVersion();
@@ -284360,7 +284356,7 @@ async function initializeTelemetry() {
284360
284356
  } catch {}
284361
284357
  };
284362
284358
  registerCleanup(shutdownTelemetry2);
284363
- return meterProvider2.getMeter("com.anthropic.claude_code", "2.0.8");
284359
+ return meterProvider2.getMeter("com.anthropic.claude_code", "2.1.0");
284364
284360
  }
284365
284361
  const meterProvider = new MeterProvider4({
284366
284362
  resource,
@@ -284380,7 +284376,7 @@ async function initializeTelemetry() {
284380
284376
  });
284381
284377
  logs.setGlobalLoggerProvider(loggerProvider);
284382
284378
  setLoggerProvider(loggerProvider);
284383
- const eventLogger = logs.getLogger("com.anthropic.claude_code.events", "2.0.8");
284379
+ const eventLogger = logs.getLogger("com.anthropic.claude_code.events", "2.1.0");
284384
284380
  setEventLogger(eventLogger);
284385
284381
  logForDebugging("[3P telemetry] Event logger set successfully");
284386
284382
  process.on("beforeExit", async () => {
@@ -284442,7 +284438,7 @@ Current timeout: ${timeoutMs}ms
284442
284438
  }
284443
284439
  };
284444
284440
  registerCleanup(shutdownTelemetry);
284445
- return meterProvider.getMeter("com.anthropic.claude_code", "2.0.8");
284441
+ return meterProvider.getMeter("com.anthropic.claude_code", "2.1.0");
284446
284442
  }
284447
284443
  async function flushTelemetry() {
284448
284444
  const meterProvider = getMeterProvider();
@@ -285632,7 +285628,7 @@ function detectLinuxGlobPatternWarnings() {
285632
285628
  }
285633
285629
  async function getDoctorDiagnostic() {
285634
285630
  const installationType = await getCurrentInstallationType();
285635
- const version = typeof MACRO !== "undefined" ? "2.0.8" : "unknown";
285631
+ const version = typeof MACRO !== "undefined" ? "2.1.0" : "unknown";
285636
285632
  const installationPath = await getInstallationPath();
285637
285633
  const invokedBinary = getInvokedBinary();
285638
285634
  const multipleInstallations = await detectMultipleInstallations();
@@ -286573,8 +286569,8 @@ async function updateLatest(channelOrVersion, forceReinstall = false) {
286573
286569
  const maxVersion = await getMaxVersion();
286574
286570
  if (maxVersion && gt(version, maxVersion)) {
286575
286571
  logForDebugging(`Native installer: maxVersion ${maxVersion} is set, capping update from ${version} to ${maxVersion}`);
286576
- if (gte("2.0.8", maxVersion)) {
286577
- logForDebugging(`Native installer: current version ${"2.0.8"} is already at or above maxVersion ${maxVersion}, skipping update`);
286572
+ if (gte("2.1.0", maxVersion)) {
286573
+ logForDebugging(`Native installer: current version ${"2.1.0"} is already at or above maxVersion ${maxVersion}, skipping update`);
286578
286574
  logEvent("tengu_native_update_skipped_max_version", {
286579
286575
  latency_ms: Date.now() - startTime,
286580
286576
  max_version: maxVersion,
@@ -286585,7 +286581,7 @@ async function updateLatest(channelOrVersion, forceReinstall = false) {
286585
286581
  version = maxVersion;
286586
286582
  }
286587
286583
  }
286588
- if (!forceReinstall && version === "2.0.8" && await versionIsAvailable(version) && await isPossibleLocalClawdBinary(executablePath)) {
286584
+ if (!forceReinstall && version === "2.1.0" && await versionIsAvailable(version) && await isPossibleLocalClawdBinary(executablePath)) {
286589
286585
  logForDebugging(`Found ${version} at ${executablePath}, skipping install`);
286590
286586
  logEvent("tengu_native_update_complete", {
286591
286587
  latency_ms: Date.now() - startTime,
@@ -331240,6 +331236,9 @@ async function* queryLoop(params, consumedCommandUuids) {
331240
331236
  if (reactiveCompact?.isWithheldPromptTooLong(message)) {
331241
331237
  withheld = true;
331242
331238
  }
331239
+ if (!reactiveCompact && message.type === "assistant" && message.isApiErrorMessage && isPromptTooLongMessage(message)) {
331240
+ withheld = true;
331241
+ }
331243
331242
  if (mediaRecoveryEnabled && reactiveCompact?.isWithheldMediaSizeError(message)) {
331244
331243
  withheld = true;
331245
331244
  }
@@ -331401,6 +331400,36 @@ async function* queryLoop(params, consumedCommandUuids) {
331401
331400
  executeStopFailureHooks(lastMessage, toolUseContext);
331402
331401
  return { reason: isWithheldMedia ? "image_error" : "prompt_too_long" };
331403
331402
  } else if (false) {}
331403
+ if (isWithheld413 && !reactiveCompact && !hasAttemptedReactiveCompact) {
331404
+ try {
331405
+ const compactionResult2 = await compactConversation(messagesForQuery, toolUseContext, {
331406
+ systemPrompt,
331407
+ userContext,
331408
+ systemContext,
331409
+ toolUseContext,
331410
+ forkContextMessages: messagesForQuery
331411
+ }, true, undefined, true);
331412
+ const postCompactMessages = buildPostCompactMessages(compactionResult2);
331413
+ for (const msg of postCompactMessages) {
331414
+ yield msg;
331415
+ }
331416
+ state = {
331417
+ messages: postCompactMessages,
331418
+ toolUseContext,
331419
+ autoCompactTracking: undefined,
331420
+ maxOutputTokensRecoveryCount,
331421
+ hasAttemptedReactiveCompact: true,
331422
+ maxOutputTokensOverride: undefined,
331423
+ pendingToolUseSummary: undefined,
331424
+ stopHookActive: undefined,
331425
+ turnCount,
331426
+ transition: { reason: "reactive_compact_retry" }
331427
+ };
331428
+ continue;
331429
+ } catch (compactErr) {
331430
+ logError(compactErr);
331431
+ }
331432
+ }
331404
331433
  if (isWithheldMaxOutputTokens(lastMessage)) {
331405
331434
  const capEnabled = getFeatureValue_CACHED_MAY_BE_STALE("tengu_otk_slot_v1", false);
331406
331435
  if (capEnabled && maxOutputTokensOverride === undefined && !process.env.CLAUDE_CODE_MAX_OUTPUT_TOKENS) {
@@ -331828,7 +331857,7 @@ function getAnthropicEnvMetadata() {
331828
331857
  function getBuildAgeMinutes() {
331829
331858
  if (false)
331830
331859
  ;
331831
- const buildTime = new Date("2026-05-09T15:53:14.625Z").getTime();
331860
+ const buildTime = new Date("2026-05-09T16:28:38.867Z").getTime();
331832
331861
  if (isNaN(buildTime))
331833
331862
  return;
331834
331863
  return Math.floor((Date.now() - buildTime) / 60000);
@@ -360660,7 +360689,7 @@ function Feedback({
360660
360689
  platform: env3.platform,
360661
360690
  gitRepo: envInfo.isGit,
360662
360691
  terminal: env3.terminal,
360663
- version: "2.0.8",
360692
+ version: "2.1.0",
360664
360693
  transcript: normalizeMessagesForAPI(messages),
360665
360694
  errors: sanitizedErrors,
360666
360695
  lastApiRequest: getLastAPIRequest(),
@@ -360852,7 +360881,7 @@ function Feedback({
360852
360881
  ", ",
360853
360882
  env3.terminal,
360854
360883
  ", v",
360855
- "2.0.8"
360884
+ "2.1.0"
360856
360885
  ]
360857
360886
  }, undefined, true, undefined, this)
360858
360887
  ]
@@ -360958,7 +360987,7 @@ ${sanitizedDescription}
360958
360987
  ` + `**Environment Info**
360959
360988
  ` + `- Platform: ${env3.platform}
360960
360989
  ` + `- Terminal: ${env3.terminal}
360961
- ` + `- Version: ${"2.0.8"}
360990
+ ` + `- Version: ${"2.1.0"}
360962
360991
  ` + `- Feedback ID: ${feedbackId}
360963
360992
  ` + `
360964
360993
  **Errors**
@@ -363586,7 +363615,7 @@ function buildPrimarySection() {
363586
363615
  }, undefined, false, undefined, this);
363587
363616
  return [{
363588
363617
  label: "Version",
363589
- value: "2.0.8"
363618
+ value: "2.1.0"
363590
363619
  }, {
363591
363620
  label: "Session name",
363592
363621
  value: nameValue
@@ -368267,7 +368296,7 @@ function Config({
368267
368296
  }
368268
368297
  }, undefined, false, undefined, this)
368269
368298
  }, undefined, false, undefined, this) : showSubmenu === "ChannelDowngrade" ? /* @__PURE__ */ jsx_dev_runtime176.jsxDEV(ChannelDowngradeDialog, {
368270
- currentVersion: "2.0.8",
368299
+ currentVersion: "2.1.0",
368271
368300
  onChoice: (choice) => {
368272
368301
  setShowSubmenu(null);
368273
368302
  setTabsHidden(false);
@@ -368279,7 +368308,7 @@ function Config({
368279
368308
  autoUpdatesChannel: "stable"
368280
368309
  };
368281
368310
  if (choice === "stay") {
368282
- newSettings.minimumVersion = "2.0.8";
368311
+ newSettings.minimumVersion = "2.1.0";
368283
368312
  }
368284
368313
  updateSettingsForSource("userSettings", newSettings);
368285
368314
  setSettingsData((prev_27) => ({
@@ -377324,6 +377353,44 @@ function extractLastAssistantText(messages) {
377324
377353
  }
377325
377354
  return "";
377326
377355
  }
377356
+ async function synthesizeNextDirective(focus) {
377357
+ try {
377358
+ const cacheSafeParams = getLastCacheSafeParams();
377359
+ if (!cacheSafeParams)
377360
+ return "";
377361
+ const focusLine = focus ? `
377362
+ The overall session focus is: ${focus}` : "";
377363
+ const prompt = `You are a task director reviewing an autonomous coding session.${focusLine}
377364
+
377365
+ Based on the conversation above, write a precise 2-3 sentence directive for the NEXT round of work.
377366
+ - Reference specific files, functions, or tests by name
377367
+ - Build directly on what was just completed or unblocked
377368
+ - Be concrete: name the exact next action, what to verify, and what "done" looks like
377369
+
377370
+ Write ONLY the directive. No preamble, no markdown, no tool calls. Start immediately with the action.`;
377371
+ const result = await runForkedAgent({
377372
+ promptMessages: [createUserMessage({ content: prompt })],
377373
+ cacheSafeParams,
377374
+ canUseTool: async () => ({
377375
+ behavior: "deny",
377376
+ message: "Synthesis agent is text-only",
377377
+ decisionReason: { type: "other", reason: "synthesis" }
377378
+ }),
377379
+ querySource: "keepgoing_synthesis",
377380
+ forkLabel: "keepgoing_synthesis",
377381
+ maxTurns: 1,
377382
+ skipTranscript: true,
377383
+ skipCacheWrite: true
377384
+ });
377385
+ const assistantMsg = getLastAssistantMessage(result.messages);
377386
+ if (!assistantMsg || assistantMsg.isApiErrorMessage)
377387
+ return "";
377388
+ return extractTextContent(assistantMsg.message.content, `
377389
+ `).trim().slice(0, 600);
377390
+ } catch {
377391
+ return "";
377392
+ }
377393
+ }
377327
377394
  function buildOnboardingPrompt(round, focus, externalMsg, contextCompacted) {
377328
377395
  const modeTag = isThinkHarderMode ? " · \uD83E\uDDE0 THINK HARDER" : "";
377329
377396
  const focusLine = focus ? `
@@ -377357,15 +377424,13 @@ TodoCreate, TodoUpdate
377357
377424
  · Run builds/tests after significant changes
377358
377425
  · If genuinely blocked: state the blocker clearly, spawn a subagent to research it, or try an alternative approach — do NOT stall
377359
377426
 
377360
- ━━━ REQUIRED ENDING ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
377361
- At the END of every response, write exactly these two lines:
377427
+ ━━━ OPTIONAL ENDING ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
377428
+ You may end your response with:
377362
377429
 
377363
377430
  SUMMARY: <1-2 sentences of what you accomplished this round>
377364
- NEXT: <1–3 sentences describing your specific plan for the next round>
377431
+ NEXT: <your plan for the following round (used as fallback if needed)>
377365
377432
 
377366
- Both lines are required every round without exception.
377367
- NEXT: becomes your only prompt next round — be precise about files,
377368
- actions, and outcomes to verify.`;
377433
+ These help with context continuity but are not required.`;
377369
377434
  }
377370
377435
  function buildSelfDirectedPrompt(round, directive, focus, externalMsg) {
377371
377436
  const modeTag = isThinkHarderMode ? " · \uD83E\uDDE0 THINK HARDER" : "";
@@ -377384,9 +377449,7 @@ ${telegramSection}${thinkHarder}
377384
377449
  DIRECTIVE:
377385
377450
  ${directive}
377386
377451
 
377387
- Proceed. End your response with:
377388
- SUMMARY: <what you accomplished this round>
377389
- NEXT: <your plan for the following round>`;
377452
+ Proceed.`;
377390
377453
  }
377391
377454
  function KeepGoingBanner({
377392
377455
  round,
@@ -377531,9 +377594,16 @@ async function callInner3(onDone, context7, args) {
377531
377594
  }
377532
377595
  const contextCompacted = lastText === NO_CONTENT_MESSAGE || lastText.trim() === "";
377533
377596
  if (!contextCompacted) {
377534
- const newDirective = extractSelfDirective(lastText);
377535
- if (newDirective)
377536
- sessionSelfDirective = newDirective;
377597
+ const extracted = extractSelfDirective(lastText);
377598
+ const synthesized = lastText.trim() && sessionRound >= 1 ? await synthesizeNextDirective(focus) : "";
377599
+ if (synthesized) {
377600
+ sessionSelfDirective = synthesized;
377601
+ } else if (extracted) {
377602
+ sessionSelfDirective = extracted;
377603
+ } else if (sessionRound > 1) {
377604
+ const preview = lastText.slice(0, 300).replace(/\n/g, " ").trim();
377605
+ sessionSelfDirective = preview ? `Continue from where you left off: ${preview.slice(0, 200)}` : "Continue with the next most important task.";
377606
+ }
377537
377607
  } else {
377538
377608
  sessionSelfDirective = "";
377539
377609
  }
@@ -377631,6 +377701,8 @@ var init_keepgoing = __esm(() => {
377631
377701
  init_signalBot();
377632
377702
  init_telegramSignals();
377633
377703
  init_messageQueueManager();
377704
+ init_forkedAgent();
377705
+ init_messages3();
377634
377706
  React58 = __toESM(require_react(), 1);
377635
377707
  jsx_dev_runtime196 = __toESM(require_jsx_dev_runtime(), 1);
377636
377708
  });
@@ -385937,7 +386009,7 @@ function Help(t0) {
385937
386009
  let t6;
385938
386010
  if ($2[31] !== tabs) {
385939
386011
  t6 = /* @__PURE__ */ jsx_dev_runtime220.jsxDEV(Tabs, {
385940
- title: `localclawd v${"2.0.8"}`,
386012
+ title: `localclawd v${"2.1.0"}`,
385941
386013
  color: "professionalBlue",
385942
386014
  defaultTab: "general",
385943
386015
  children: tabs
@@ -403199,7 +403271,7 @@ function getRecentReleaseNotes(currentVersion, previousVersion, changelogContent
403199
403271
  }
403200
403272
  return [];
403201
403273
  }
403202
- async function checkForReleaseNotes(lastSeenVersion, currentVersion = "2.0.8") {
403274
+ async function checkForReleaseNotes(lastSeenVersion, currentVersion = "2.1.0") {
403203
403275
  if (process.env.USER_TYPE === "ant") {
403204
403276
  const changelog = MACRO.VERSION_CHANGELOG;
403205
403277
  if (changelog) {
@@ -403226,7 +403298,7 @@ async function checkForReleaseNotes(lastSeenVersion, currentVersion = "2.0.8") {
403226
403298
  releaseNotes
403227
403299
  };
403228
403300
  }
403229
- function checkForReleaseNotesSync(lastSeenVersion, currentVersion = "2.0.8") {
403301
+ function checkForReleaseNotesSync(lastSeenVersion, currentVersion = "2.1.0") {
403230
403302
  if (process.env.USER_TYPE === "ant") {
403231
403303
  const changelog = MACRO.VERSION_CHANGELOG;
403232
403304
  if (changelog) {
@@ -403383,7 +403455,7 @@ function getRecentActivitySync() {
403383
403455
  return cachedActivity;
403384
403456
  }
403385
403457
  function getLogoDisplayData() {
403386
- const version = process.env.DEMO_VERSION ?? "2.0.8";
403458
+ const version = process.env.DEMO_VERSION ?? "2.1.0";
403387
403459
  const serverUrl = getDirectConnectServerUrl();
403388
403460
  const displayPath = process.env.DEMO_VERSION ? "/code/claude" : getDisplayPath(getCwd());
403389
403461
  const cwd2 = serverUrl ? `${displayPath} in ${serverUrl.replace(/^https?:\/\//, "")}` : displayPath;
@@ -404483,7 +404555,7 @@ function Logo() {
404483
404555
  if ($2[2] === Symbol.for("react.memo_cache_sentinel")) {
404484
404556
  t2 = () => {
404485
404557
  const currentConfig = getGlobalConfig();
404486
- if (currentConfig.lastReleaseNotesSeen === "2.0.8") {
404558
+ if (currentConfig.lastReleaseNotesSeen === "2.1.0") {
404487
404559
  return;
404488
404560
  }
404489
404561
  saveGlobalConfig(_temp326);
@@ -405142,12 +405214,12 @@ function Logo() {
405142
405214
  return t41;
405143
405215
  }
405144
405216
  function _temp326(current) {
405145
- if (current.lastReleaseNotesSeen === "2.0.8") {
405217
+ if (current.lastReleaseNotesSeen === "2.1.0") {
405146
405218
  return current;
405147
405219
  }
405148
405220
  return {
405149
405221
  ...current,
405150
- lastReleaseNotesSeen: "2.0.8"
405222
+ lastReleaseNotesSeen: "2.1.0"
405151
405223
  };
405152
405224
  }
405153
405225
  function _temp241(s_0) {
@@ -435626,7 +435698,7 @@ async function captureMemoryDiagnostics(trigger, dumpNumber = 0) {
435626
435698
  smapsRollup,
435627
435699
  platform: process.platform,
435628
435700
  nodeVersion: process.version,
435629
- ccVersion: "2.0.8"
435701
+ ccVersion: "2.1.0"
435630
435702
  };
435631
435703
  }
435632
435704
  async function performHeapDump(trigger = "manual", dumpNumber = 0) {
@@ -436211,7 +436283,7 @@ var init_bridge_kick = __esm(() => {
436211
436283
  var call88 = async () => {
436212
436284
  return {
436213
436285
  type: "text",
436214
- value: `${"2.0.8"} (built ${"2026-05-09T15:53:14.625Z"})`
436286
+ value: `${"2.1.0"} (built ${"2026-05-09T16:28:38.867Z"})`
436215
436287
  };
436216
436288
  }, version, version_default;
436217
436289
  var init_version = __esm(() => {
@@ -444155,7 +444227,7 @@ function generateHtmlReport(data, insights) {
444155
444227
  </html>`;
444156
444228
  }
444157
444229
  function buildExportData(data, insights, facets, remoteStats) {
444158
- const version2 = typeof MACRO !== "undefined" ? "2.0.8" : "unknown";
444230
+ const version2 = typeof MACRO !== "undefined" ? "2.1.0" : "unknown";
444159
444231
  const remote_hosts_collected = remoteStats?.hosts.filter((h) => h.sessionCount > 0).map((h) => h.name);
444160
444232
  const facets_summary = {
444161
444233
  total: facets.size,
@@ -448358,7 +448430,7 @@ var init_sessionStorage = __esm(() => {
448358
448430
  init_settings2();
448359
448431
  init_slowOperations();
448360
448432
  init_uuid();
448361
- VERSION6 = typeof MACRO !== "undefined" ? "2.0.8" : "unknown";
448433
+ VERSION6 = typeof MACRO !== "undefined" ? "2.1.0" : "unknown";
448362
448434
  MAX_TOMBSTONE_REWRITE_BYTES = 50 * 1024 * 1024;
448363
448435
  SKIP_FIRST_PROMPT_PATTERN = /^(?:\s*<[a-z][\w-]*[\s>]|\[Request interrupted by user[^\]]*\])/;
448364
448436
  EPHEMERAL_PROGRESS_TYPES = new Set([
@@ -449559,7 +449631,7 @@ var init_filesystem = __esm(() => {
449559
449631
  });
449560
449632
  getBundledSkillsRoot = memoize_default(function getBundledSkillsRoot2() {
449561
449633
  const nonce = randomBytes20(16).toString("hex");
449562
- return join151(getClaudeTempDir(), "bundled-skills", "2.0.8", nonce);
449634
+ return join151(getClaudeTempDir(), "bundled-skills", "2.1.0", nonce);
449563
449635
  });
449564
449636
  getResolvedWorkingDirPaths = memoize_default(getPathsForPermissionCheck);
449565
449637
  });
@@ -458796,7 +458868,7 @@ function buildSystemInitMessage(inputs) {
458796
458868
  slash_commands: inputs.commands.filter((c5) => c5.userInvocable !== false).map((c5) => c5.name),
458797
458869
  apiKeySource: getAnthropicApiKeyWithSource().source,
458798
458870
  betas: getSdkBetas(),
458799
- claude_code_version: "2.0.8",
458871
+ claude_code_version: "2.1.0",
458800
458872
  output_style: outputStyle2,
458801
458873
  agents: inputs.agents.map((agent) => agent.agentType),
458802
458874
  skills: inputs.skills.filter((s) => s.userInvocable !== false).map((skill) => skill.name),
@@ -472953,7 +473025,7 @@ var init_useVoiceEnabled = __esm(() => {
472953
473025
  function getSemverPart(version2) {
472954
473026
  return `${import_semver10.major(version2, { loose: true })}.${import_semver10.minor(version2, { loose: true })}.${import_semver10.patch(version2, { loose: true })}`;
472955
473027
  }
472956
- function useUpdateNotification(updatedVersion, initialVersion = "2.0.8") {
473028
+ function useUpdateNotification(updatedVersion, initialVersion = "2.1.0") {
472957
473029
  const [lastNotifiedSemver, setLastNotifiedSemver] = import_react214.useState(() => getSemverPart(initialVersion));
472958
473030
  if (!updatedVersion) {
472959
473031
  return null;
@@ -472993,7 +473065,7 @@ function AutoUpdater({
472993
473065
  return;
472994
473066
  }
472995
473067
  if (false) {}
472996
- const currentVersion = "2.0.8";
473068
+ const currentVersion = "2.1.0";
472997
473069
  const channel = getInitialSettings()?.autoUpdatesChannel ?? "latest";
472998
473070
  let latestVersion = await getLatestVersion(channel);
472999
473071
  const isDisabled = isAutoUpdaterDisabled();
@@ -473204,12 +473276,12 @@ function NativeAutoUpdater({
473204
473276
  logEvent("tengu_native_auto_updater_start", {});
473205
473277
  try {
473206
473278
  const maxVersion = await getMaxVersion();
473207
- if (maxVersion && gt("2.0.8", maxVersion)) {
473279
+ if (maxVersion && gt("2.1.0", maxVersion)) {
473208
473280
  const msg = await getMaxVersionMessage();
473209
473281
  setMaxVersionIssue(msg ?? "affects your version");
473210
473282
  }
473211
473283
  const result = await installLatest(channel);
473212
- const currentVersion = "2.0.8";
473284
+ const currentVersion = "2.1.0";
473213
473285
  const latencyMs = Date.now() - startTime;
473214
473286
  if (result.lockFailed) {
473215
473287
  logEvent("tengu_native_auto_updater_lock_contention", {
@@ -473344,17 +473416,17 @@ function PackageManagerAutoUpdater(t0) {
473344
473416
  const maxVersion = await getMaxVersion();
473345
473417
  if (maxVersion && latest && gt(latest, maxVersion)) {
473346
473418
  logForDebugging(`PackageManagerAutoUpdater: maxVersion ${maxVersion} is set, capping update from ${latest} to ${maxVersion}`);
473347
- if (gte("2.0.8", maxVersion)) {
473348
- logForDebugging(`PackageManagerAutoUpdater: current version ${"2.0.8"} is already at or above maxVersion ${maxVersion}, skipping update`);
473419
+ if (gte("2.1.0", maxVersion)) {
473420
+ logForDebugging(`PackageManagerAutoUpdater: current version ${"2.1.0"} is already at or above maxVersion ${maxVersion}, skipping update`);
473349
473421
  setUpdateAvailable(false);
473350
473422
  return;
473351
473423
  }
473352
473424
  latest = maxVersion;
473353
473425
  }
473354
- const hasUpdate = latest && !gte("2.0.8", latest) && !shouldSkipVersion(latest);
473426
+ const hasUpdate = latest && !gte("2.1.0", latest) && !shouldSkipVersion(latest);
473355
473427
  setUpdateAvailable(!!hasUpdate);
473356
473428
  if (hasUpdate) {
473357
- logForDebugging(`PackageManagerAutoUpdater: Update available ${"2.0.8"} -> ${latest}`);
473429
+ logForDebugging(`PackageManagerAutoUpdater: Update available ${"2.1.0"} -> ${latest}`);
473358
473430
  }
473359
473431
  };
473360
473432
  $2[0] = t1;
@@ -473388,7 +473460,7 @@ function PackageManagerAutoUpdater(t0) {
473388
473460
  wrap: "truncate",
473389
473461
  children: [
473390
473462
  "currentVersion: ",
473391
- "2.0.8"
473463
+ "2.1.0"
473392
473464
  ]
473393
473465
  }, undefined, true, undefined, this);
473394
473466
  $2[3] = verbose;
@@ -480948,7 +481020,7 @@ function buildStatusLineCommandInput(permissionMode, exceeds200kTokens, settings
480948
481020
  project_dir: getOriginalCwd(),
480949
481021
  added_dirs: addedDirs
480950
481022
  },
480951
- version: "2.0.8",
481023
+ version: "2.1.0",
480952
481024
  output_style: {
480953
481025
  name: outputStyleName
480954
481026
  },
@@ -492520,7 +492592,7 @@ async function submitTranscriptShare(messages, trigger, appearanceId) {
492520
492592
  } catch {}
492521
492593
  const data = {
492522
492594
  trigger,
492523
- version: "2.0.8",
492595
+ version: "2.1.0",
492524
492596
  platform: process.platform,
492525
492597
  transcript,
492526
492598
  subagentTranscripts: Object.keys(subagentTranscripts).length > 0 ? subagentTranscripts : undefined,
@@ -509429,7 +509501,7 @@ function appendToLog(path17, message) {
509429
509501
  cwd: getFsImplementation().cwd(),
509430
509502
  userType: process.env.USER_TYPE,
509431
509503
  sessionId: getSessionId(),
509432
- version: "2.0.8"
509504
+ version: "2.1.0"
509433
509505
  };
509434
509506
  getLogWriter(path17).write(messageWithTimestamp);
509435
509507
  }
@@ -513443,8 +513515,8 @@ async function getEnvLessBridgeConfig() {
513443
513515
  }
513444
513516
  async function checkEnvLessBridgeMinVersion() {
513445
513517
  const cfg = await getEnvLessBridgeConfig();
513446
- if (cfg.min_version && lt("2.0.8", cfg.min_version)) {
513447
- return `Your version of localclawd (${"2.0.8"}) is too old for Remote Control.
513518
+ if (cfg.min_version && lt("2.1.0", cfg.min_version)) {
513519
+ return `Your version of localclawd (${"2.1.0"}) is too old for Remote Control.
513448
513520
  Version ${cfg.min_version} or higher is required. Run \`localclawd update\` to update.`;
513449
513521
  }
513450
513522
  return null;
@@ -513916,7 +513988,7 @@ async function initBridgeCore(params) {
513916
513988
  const rawApi = createBridgeApiClient({
513917
513989
  baseUrl,
513918
513990
  getAccessToken,
513919
- runnerVersion: "2.0.8",
513991
+ runnerVersion: "2.1.0",
513920
513992
  onDebug: logForDebugging,
513921
513993
  onAuth401,
513922
513994
  getTrustedDeviceToken
@@ -519635,7 +519707,7 @@ async function startMCPServer(cwd3, debug4, verbose) {
519635
519707
  setCwd(cwd3);
519636
519708
  const server = new Server({
519637
519709
  name: "claude/tengu",
519638
- version: "2.0.8"
519710
+ version: "2.1.0"
519639
519711
  }, {
519640
519712
  capabilities: {
519641
519713
  tools: {}
@@ -520716,7 +520788,7 @@ function WelcomeLogo() {
520716
520788
  dimColor: true,
520717
520789
  children: [
520718
520790
  "v",
520719
- "2.0.8"
520791
+ "2.1.0"
520720
520792
  ]
520721
520793
  }, undefined, true, undefined, this)
520722
520794
  ]
@@ -520907,7 +520979,7 @@ __export(exports_update, {
520907
520979
  });
520908
520980
  async function update() {
520909
520981
  logEvent("tengu_update_check", {});
520910
- writeToStdout(`Current version: ${"2.0.8"}
520982
+ writeToStdout(`Current version: ${"2.1.0"}
520911
520983
  `);
520912
520984
  const channel = getInitialSettings()?.autoUpdatesChannel ?? "latest";
520913
520985
  writeToStdout(`Checking for updates to ${channel} version...
@@ -520982,8 +521054,8 @@ async function update() {
520982
521054
  writeToStdout(`localclawd is managed by Homebrew.
520983
521055
  `);
520984
521056
  const latest = await getLatestVersion(channel);
520985
- if (latest && !gte("2.0.8", latest)) {
520986
- writeToStdout(`Update available: ${"2.0.8"} → ${latest}
521057
+ if (latest && !gte("2.1.0", latest)) {
521058
+ writeToStdout(`Update available: ${"2.1.0"} → ${latest}
520987
521059
  `);
520988
521060
  writeToStdout(`
520989
521061
  `);
@@ -520999,8 +521071,8 @@ async function update() {
520999
521071
  writeToStdout(`localclawd is managed by winget.
521000
521072
  `);
521001
521073
  const latest = await getLatestVersion(channel);
521002
- if (latest && !gte("2.0.8", latest)) {
521003
- writeToStdout(`Update available: ${"2.0.8"} → ${latest}
521074
+ if (latest && !gte("2.1.0", latest)) {
521075
+ writeToStdout(`Update available: ${"2.1.0"} → ${latest}
521004
521076
  `);
521005
521077
  writeToStdout(`
521006
521078
  `);
@@ -521014,8 +521086,8 @@ async function update() {
521014
521086
  writeToStdout(`localclawd is managed by apk.
521015
521087
  `);
521016
521088
  const latest = await getLatestVersion(channel);
521017
- if (latest && !gte("2.0.8", latest)) {
521018
- writeToStdout(`Update available: ${"2.0.8"} → ${latest}
521089
+ if (latest && !gte("2.1.0", latest)) {
521090
+ writeToStdout(`Update available: ${"2.1.0"} → ${latest}
521019
521091
  `);
521020
521092
  writeToStdout(`
521021
521093
  `);
@@ -521080,11 +521152,11 @@ async function update() {
521080
521152
  `);
521081
521153
  await gracefulShutdown(1);
521082
521154
  }
521083
- if (result.latestVersion === "2.0.8") {
521084
- writeToStdout(source_default.green(`localclawd is up to date (${"2.0.8"})`) + `
521155
+ if (result.latestVersion === "2.1.0") {
521156
+ writeToStdout(source_default.green(`localclawd is up to date (${"2.1.0"})`) + `
521085
521157
  `);
521086
521158
  } else {
521087
- writeToStdout(source_default.green(`Successfully updated from ${"2.0.8"} to version ${result.latestVersion}`) + `
521159
+ writeToStdout(source_default.green(`Successfully updated from ${"2.1.0"} to version ${result.latestVersion}`) + `
521088
521160
  `);
521089
521161
  await regenerateCompletionCache();
521090
521162
  }
@@ -521144,12 +521216,12 @@ async function update() {
521144
521216
  `);
521145
521217
  await gracefulShutdown(1);
521146
521218
  }
521147
- if (latestVersion === "2.0.8") {
521148
- writeToStdout(source_default.green(`localclawd is up to date (${"2.0.8"})`) + `
521219
+ if (latestVersion === "2.1.0") {
521220
+ writeToStdout(source_default.green(`localclawd is up to date (${"2.1.0"})`) + `
521149
521221
  `);
521150
521222
  await gracefulShutdown(0);
521151
521223
  }
521152
- writeToStdout(`New version available: ${latestVersion} (current: ${"2.0.8"})
521224
+ writeToStdout(`New version available: ${latestVersion} (current: ${"2.1.0"})
521153
521225
  `);
521154
521226
  writeToStdout(`Installing update...
521155
521227
  `);
@@ -521194,7 +521266,7 @@ async function update() {
521194
521266
  logForDebugging(`update: Installation status: ${status2}`);
521195
521267
  switch (status2) {
521196
521268
  case "success":
521197
- writeToStdout(source_default.green(`Successfully updated from ${"2.0.8"} to version ${latestVersion}`) + `
521269
+ writeToStdout(source_default.green(`Successfully updated from ${"2.1.0"} to version ${latestVersion}`) + `
521198
521270
  `);
521199
521271
  await regenerateCompletionCache();
521200
521272
  break;
@@ -522436,7 +522508,7 @@ Run with --debug for more details.
522436
522508
  }
522437
522509
  }
522438
522510
  logForDiagnosticsNoPII("info", "started", {
522439
- version: "2.0.8",
522511
+ version: "2.1.0",
522440
522512
  is_native_binary: isInBundledMode()
522441
522513
  });
522442
522514
  registerCleanup(async () => {
@@ -523220,7 +523292,7 @@ Usage: localclawd --remote "your task description"`, () => gracefulShutdown(1));
523220
523292
  pendingHookMessages
523221
523293
  }, renderAndRun);
523222
523294
  }
523223
- }).version("2.0.8 (localclawd)", "-v, --version", "Output the version number");
523295
+ }).version("2.1.0 (localclawd)", "-v, --version", "Output the version number");
523224
523296
  program2.option("-w, --worktree [name]", "Create a new git worktree for this session (optionally specify a name)");
523225
523297
  program2.option("--tmux", "Create a tmux session for the worktree (requires --worktree). Uses iTerm2 native panes when available; use --tmux=classic for traditional tmux.");
523226
523298
  if (canUserConfigureAdvisor()) {
@@ -523734,7 +523806,7 @@ if (false) {}
523734
523806
  async function main2() {
523735
523807
  const args = process.argv.slice(2);
523736
523808
  if (args.length === 1 && (args[0] === "--version" || args[0] === "-v" || args[0] === "-V")) {
523737
- console.log(`${"2.0.8"} (localclawd)`);
523809
+ console.log(`${"2.1.0"} (localclawd)`);
523738
523810
  return;
523739
523811
  }
523740
523812
  const {
@@ -523825,4 +523897,4 @@ localclawd crashed: ${msg}
523825
523897
  process.exit(1);
523826
523898
  });
523827
523899
 
523828
- //# debugId=992B97BE2AA50E3664756E2164756E21
523900
+ //# debugId=B8DF83B2F993734C64756E2164756E21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "localclawd",
3
- "version": "2.0.8",
3
+ "version": "2.1.0",
4
4
  "description": "Local-first coding CLI for vLLM, Ollama, and OpenAI-compatible backends.",
5
5
  "private": false,
6
6
  "type": "module",