@aliyunrds/ctxdb-shared 0.0.9 → 0.0.10-beta.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.
package/dist/index.d.ts CHANGED
@@ -288,14 +288,14 @@ declare function filterMessagesForExtraction(messages: Array<{
288
288
  *
289
289
  * Fix: define the turn by message *content*, not message *count*.
290
290
  * The "current turn" starts at the last contiguous user-message run
291
- * and extends to the end of the parsed array. Earlier isSummary
292
- * messages are still injected as anchor context (legacy behaviour).
291
+ * and extends to the end of the parsed array. Historical summaries are not
292
+ * re-injected: an excluded turn must stay excluded on later captures.
293
293
  *
294
294
  * Invariants:
295
295
  * - Output is always sorted by the original `index` field, preserving
296
296
  * chronological order.
297
- * - When there is no user message at all (unusual; defensive), only
298
- * isSummary anchors are returned — the caller still has its own
297
+ * - When there is no user message at all (unusual; defensive), an empty
298
+ * array is returned — the caller still has its own
299
299
  * `hasUser=false → skip` guard which kicks in.
300
300
  * - MAX_TURN_MESSAGES caps the current-turn slice in pathological
301
301
  * cases (e.g. a single turn with 100+ thinking segments). It never
@@ -399,7 +399,29 @@ declare function sanitizeQuery(raw: string): string;
399
399
  */
400
400
  declare function recall(provider: Mem0Provider, query: string, userId: string, config?: SkillsConfig, sessionId?: string): Promise<RecallResult>;
401
401
 
402
- declare const OFFICIAL_PRODUCTION_BASE_URLS: readonly ["https://api.cn-hangzhou.agentcontext.aliyuncs.com", "https://context-database.aliyuncs.com"];
402
+ /** Official public-site presets. Saved credentials retain their exact service URL. */
403
+ declare const PUBLIC_SITES: {
404
+ readonly cn: {
405
+ readonly baseUrl: "https://api.cn-hangzhou.agentcontext.aliyuncs.com";
406
+ readonly aliases: readonly ["https://context-database.aliyuncs.com"];
407
+ readonly authorizationUrl: "https://rdsnext.console.aliyun.com/contextDbCliAuthorization/cn-hangzhou";
408
+ };
409
+ readonly intl: {
410
+ readonly baseUrl: "https://context-database.ap-southeast-1.aliyuncs.com";
411
+ readonly aliases: readonly [];
412
+ readonly authorizationUrl: "https://rds.console.alibabacloud.com/contextDbCliAuthorization/ap-southeast-1";
413
+ };
414
+ };
415
+ type PublicSite = keyof typeof PUBLIC_SITES;
416
+ declare function parsePublicSite(value: unknown): PublicSite | undefined;
417
+ /** Normalize the complete URL, without discarding a port, path or credentials. */
418
+ declare function normalizeBaseUrl(value: string): string | null;
419
+ declare function publicSiteForUrl(value: string): PublicSite | undefined;
420
+ /** Presets and explicit deployment URLs are separate, mutually exclusive choices. */
421
+ declare function siteBaseUrl(site: unknown, baseUrl?: unknown): string | undefined;
422
+
423
+ type SitePreset = (typeof PUBLIC_SITES)[keyof typeof PUBLIC_SITES];
424
+ declare const OFFICIAL_PRODUCTION_BASE_URLS: ReadonlyArray<SitePreset["baseUrl"] | SitePreset["aliases"][number]>;
403
425
  type DebugReason = "non_production_base_url" | null;
404
426
  interface DebugPolicy {
405
427
  debugConfigured: boolean;
@@ -407,8 +429,6 @@ interface DebugPolicy {
407
429
  debugForced: boolean;
408
430
  debugReason: DebugReason;
409
431
  }
410
- /** Normalize a complete URL for exact policy comparison. */
411
- declare function normalizeBaseUrl(value: string): string | null;
412
432
  declare function isOfficialProductionUrl(value: string): boolean;
413
433
  declare function resolveDebugPolicy(configuredDebug: boolean, effectiveBaseUrl: string): DebugPolicy;
414
434
 
@@ -823,12 +843,13 @@ declare function commitLogin(pending: PendingLogin, reference: string, baseUrl:
823
843
  declare function unbindLogin(path: string, agent: string): void;
824
844
  declare function bindLogin(path: string, agent: string, name: string): Promise<void>;
825
845
  type SetupAuthenticationOptions = {
846
+ site?: PublicSite;
826
847
  apiKey?: string;
827
848
  login?: string;
828
849
  baseUrl?: string;
829
850
  preserveBaseUrl?: boolean;
830
851
  };
831
- /** Setup keeps the selected identity, but resets its DATA endpoint unless explicitly supplied. */
852
+ /** Setup repairs integration without redirecting an existing credential to another service. */
832
853
  declare function setupAuthentication(path: string, agent: string, options: SetupAuthenticationOptions, env?: Record<string, string | undefined>): Promise<void>;
833
854
 
834
855
  /** Config mutation and reference check occur together, after any concurrent refresh.
@@ -847,7 +868,7 @@ declare function collectUnusedLogins(path: string, transport: OAuthRevokeTranspo
847
868
  unconfirmed: number;
848
869
  }>;
849
870
 
850
- declare const DEFAULT_DATA_BASE_URL = "https://api.cn-hangzhou.agentcontext.aliyuncs.com";
871
+ declare const DEFAULT_DATA_BASE_URL: "https://api.cn-hangzhou.agentcontext.aliyuncs.com";
851
872
  /** Validate explicit input before any config/credential write; never echo a supplied URL's secrets. */
852
873
  declare function validateDataBaseUrl(value: unknown, coreOrigin?: boolean): asserts value is string;
853
874
 
@@ -1006,4 +1027,39 @@ declare class AuthorizationService {
1006
1027
  /** Publishes a stable login ID only after its fresh record exists. CAS preserves newer Agent choices. */
1007
1028
  declare function publicAuthorizationTarget(pending: PendingLogin, revoke: OAuthRevokeTransport): AuthorizationTarget;
1008
1029
 
1009
- export { ACTIVE_CONTEXTDB_CREDENTIAL, type AddOptions, type AddResult, type AddResultItem, type ApiKeyCredentialRecord, type AuthConfig, AuthConfigError, AuthorizationDeclinedError, type AuthorizationEntry, AuthorizationError, type AuthorizationFlow, type AuthorizationInteraction, type AuthorizationMethod, type AuthorizationNotice, type AuthorizationOutcome, type AuthorizationPrompt, AuthorizationService, type AuthorizationSession, type AuthorizationTarget, type CategoryConfig, CoreDeviceClient, type CredentialCandidate, type CredentialCommit, type CredentialInfo, type CredentialKey, type CredentialRecord, type CredentialSnapshot, DEFAULT_DATA_BASE_URL, DOCUMENT_EVIDENCE_SECTION_TITLE, DataApiAuthorizationProvider, type DataApiCredential, type DataAuthContext, type DebugPolicy, type DebugReason, type DetectionResult, DeviceFlowError, type DevicePrompt, EXTERNAL_KNOWLEDGE_PREAMBLE_HEAD, type ExcludedRecallMemory, type ExternalContext, type ExternalContextChunk, GRAPH_CONTEXT_MAX_CHARS, GRAPH_CONTEXT_SECTION_TITLE, GRAPH_CONTEXT_SOURCE_LABEL, GRAPH_CONTEXT_TAG, GRAPH_CONTEXT_TRUNCATION_MARKER, GRAPH_CONTEXT_USAGE_NOTICE, type ListOptions, LocalCredentialProvider, type Mem0Provider, type MemoryItem, type NormalizedGraphContext, OAuthCredentialError, type OAuthLogin, type OAuthProfile, OAuthProfileProvider, type OAuthRequestAuthorization, type OAuthScope, OAuthSessionStore, OFFICIAL_PRODUCTION_BASE_URLS, type ParsedMessage, RECALLED_MEMORIES_SAFETY_NOTICE, RECALL_TRACE_AGENTS, RECALL_TRACE_FILENAME, RECALL_TRACE_MAX_BYTES, RECALL_TRACE_OUTCOMES, RECALL_TRACE_ROTATED_GENERATIONS, RECALL_TRACE_SCHEMA_VERSION, type ReadRecallTraceOptions, type ReadRecallTraceResult, type RecallFinishTraceInput, type RecallFinishTraceRecord, type RecallMemoryExclusionReason, type RecallMemorySelectionBase, type RecallResult, type RecallSelectionResult, type RecallStartTraceInput, type RecallStartTraceRecord, type RecallTraceAgent, type RecallTraceKind, type RecallTraceOutcome, type RecallTraceRecord, type RecallTraceRequest, type RecallTraceSelection, type RecallTraceStoreOptions, type ResolvedRequestAuthorization, type SearchOptions, type SearchResultWithExternalContext, type SelectTurnOptions, type SelectedRecallMemory, type SkillsConfig, type StoredCredential, assertAuthSnapshot, authSnapshot, beginLogin, bindLogin, buildExternalKnowledgeBlock, buildExternalKnowledgePreamble, buildNormalizedGraphContext, collectUnusedLogins, commitLogin, createRecallFinishRecord, createRecallStartRecord, createRequestAuthorizationProvider, defaultCredentialsPath, extractKnowledgeBaseIds, extractKnowledgeChunkContent, extractKnowledgeChunkSourceLabel, extractKnowledgeChunkTags, filterMessagesForExtraction, formatExternalKnowledgeChunks, formatRecalledMemoriesBlock, internalCandidate, isGenericAssistantMessage, isGraphContextChunk, isKnowledgeBaseUploadTurn, isNoiseMessage, isOfficialProductionUrl, isSessionSpecificContent, loginUsers, namedLogin, normalizeBaseUrl, normalizeCoreOrigin, oauthOwner, oauthProfile, oauthProfileFromConfig, oauthProfileStatus, oauthSessionCandidate, oauthSessionFromCredential, ownAuthProfile, partitionKnowledgeChunks, preserveDefaultApiKey, publicApiKeyFromConfig, publicAuthenticationFromConfig, publicAuthorizationTarget, readActiveCredentialSync, readAuthConfig, readRecallTraces, recall, recallTracePath, rejectAuthEnvironment, releaseLogin, requireLoginId, resolveDebugPolicy, sanitizeChunkContent, sanitizeQuery, sanitizeRecallFailureReason, selectAndFormatRecalledMemories, selectDataApiCredential, selectTurnMessages, selectedLogin, setupAuthentication, stripNoiseFromContent, truncateGraphContext, unbindLogin, updateAuthConfig, validateDataBaseUrl, validateLoginChoice, withAuthConfigLock, withAuthorizationLock, writeRecallTrace };
1030
+ /** Tool evidence is retained separately from text sent for memory extraction. */
1031
+ interface CaptureToolCall {
1032
+ name: string;
1033
+ provider?: string;
1034
+ id?: string;
1035
+ arguments: Record<string, unknown>;
1036
+ invalidArguments?: true;
1037
+ }
1038
+ type MemoryCleanupDetection = {
1039
+ detected: false;
1040
+ } | {
1041
+ detected: true;
1042
+ operation: "delete" | "batch-delete";
1043
+ source: "cli" | "tool";
1044
+ };
1045
+ /** Only confirmed ContextDB tool identities or supported executable commands qualify. */
1046
+ declare function detectMemoryCleanup(calls: readonly CaptureToolCall[]): MemoryCleanupDetection;
1047
+
1048
+ type RecordValue = Record<string, any>;
1049
+ declare function captureRecord(value: unknown): RecordValue;
1050
+ declare function captureText(value: unknown): string;
1051
+ /** Select raw events before any text extraction, truncation or message cap. */
1052
+ declare function selectCaptureTurn(records: readonly unknown[]): unknown[];
1053
+ /** Registration map is supplied by the owner of native tools, never inferred from bare names. */
1054
+ declare function captureToolCalls(records: readonly unknown[], registeredTools?: Readonly<Record<string, string>>): CaptureToolCall[];
1055
+ interface CaptureCompletionSignal {
1056
+ /** Supplied only by an authoritative end-of-turn lifecycle, not each model call. */
1057
+ completed?: boolean;
1058
+ turnId?: string;
1059
+ sessionId?: string;
1060
+ lastAssistantMessage?: string;
1061
+ }
1062
+ /** Pending calls and intermediate model replies cannot be promoted by an idle/Stop event. */
1063
+ declare function captureCompletionReason(records: readonly unknown[], signal?: CaptureCompletionSignal): string | undefined;
1064
+
1065
+ export { ACTIVE_CONTEXTDB_CREDENTIAL, type AddOptions, type AddResult, type AddResultItem, type ApiKeyCredentialRecord, type AuthConfig, AuthConfigError, AuthorizationDeclinedError, type AuthorizationEntry, AuthorizationError, type AuthorizationFlow, type AuthorizationInteraction, type AuthorizationMethod, type AuthorizationNotice, type AuthorizationOutcome, type AuthorizationPrompt, AuthorizationService, type AuthorizationSession, type AuthorizationTarget, type CaptureCompletionSignal, type CaptureToolCall, type CategoryConfig, CoreDeviceClient, type CredentialCandidate, type CredentialCommit, type CredentialInfo, type CredentialKey, type CredentialRecord, type CredentialSnapshot, DEFAULT_DATA_BASE_URL, DOCUMENT_EVIDENCE_SECTION_TITLE, DataApiAuthorizationProvider, type DataApiCredential, type DataAuthContext, type DebugPolicy, type DebugReason, type DetectionResult, DeviceFlowError, type DevicePrompt, EXTERNAL_KNOWLEDGE_PREAMBLE_HEAD, type ExcludedRecallMemory, type ExternalContext, type ExternalContextChunk, GRAPH_CONTEXT_MAX_CHARS, GRAPH_CONTEXT_SECTION_TITLE, GRAPH_CONTEXT_SOURCE_LABEL, GRAPH_CONTEXT_TAG, GRAPH_CONTEXT_TRUNCATION_MARKER, GRAPH_CONTEXT_USAGE_NOTICE, type ListOptions, LocalCredentialProvider, type Mem0Provider, type MemoryCleanupDetection, type MemoryItem, type NormalizedGraphContext, OAuthCredentialError, type OAuthLogin, type OAuthProfile, OAuthProfileProvider, type OAuthRequestAuthorization, type OAuthScope, OAuthSessionStore, OFFICIAL_PRODUCTION_BASE_URLS, PUBLIC_SITES, type ParsedMessage, type PublicSite, RECALLED_MEMORIES_SAFETY_NOTICE, RECALL_TRACE_AGENTS, RECALL_TRACE_FILENAME, RECALL_TRACE_MAX_BYTES, RECALL_TRACE_OUTCOMES, RECALL_TRACE_ROTATED_GENERATIONS, RECALL_TRACE_SCHEMA_VERSION, type ReadRecallTraceOptions, type ReadRecallTraceResult, type RecallFinishTraceInput, type RecallFinishTraceRecord, type RecallMemoryExclusionReason, type RecallMemorySelectionBase, type RecallResult, type RecallSelectionResult, type RecallStartTraceInput, type RecallStartTraceRecord, type RecallTraceAgent, type RecallTraceKind, type RecallTraceOutcome, type RecallTraceRecord, type RecallTraceRequest, type RecallTraceSelection, type RecallTraceStoreOptions, type ResolvedRequestAuthorization, type SearchOptions, type SearchResultWithExternalContext, type SelectTurnOptions, type SelectedRecallMemory, type SkillsConfig, type StoredCredential, assertAuthSnapshot, authSnapshot, beginLogin, bindLogin, buildExternalKnowledgeBlock, buildExternalKnowledgePreamble, buildNormalizedGraphContext, captureCompletionReason, captureRecord, captureText, captureToolCalls, collectUnusedLogins, commitLogin, createRecallFinishRecord, createRecallStartRecord, createRequestAuthorizationProvider, defaultCredentialsPath, detectMemoryCleanup, extractKnowledgeBaseIds, extractKnowledgeChunkContent, extractKnowledgeChunkSourceLabel, extractKnowledgeChunkTags, filterMessagesForExtraction, formatExternalKnowledgeChunks, formatRecalledMemoriesBlock, internalCandidate, isGenericAssistantMessage, isGraphContextChunk, isKnowledgeBaseUploadTurn, isNoiseMessage, isOfficialProductionUrl, isSessionSpecificContent, loginUsers, namedLogin, normalizeBaseUrl, normalizeCoreOrigin, oauthOwner, oauthProfile, oauthProfileFromConfig, oauthProfileStatus, oauthSessionCandidate, oauthSessionFromCredential, ownAuthProfile, parsePublicSite, partitionKnowledgeChunks, preserveDefaultApiKey, publicApiKeyFromConfig, publicAuthenticationFromConfig, publicAuthorizationTarget, publicSiteForUrl, readActiveCredentialSync, readAuthConfig, readRecallTraces, recall, recallTracePath, rejectAuthEnvironment, releaseLogin, requireLoginId, resolveDebugPolicy, sanitizeChunkContent, sanitizeQuery, sanitizeRecallFailureReason, selectAndFormatRecalledMemories, selectCaptureTurn, selectDataApiCredential, selectTurnMessages, selectedLogin, setupAuthentication, siteBaseUrl, stripNoiseFromContent, truncateGraphContext, unbindLogin, updateAuthConfig, validateDataBaseUrl, validateLoginChoice, withAuthConfigLock, withAuthorizationLock, writeRecallTrace };
package/dist/index.js CHANGED
@@ -405,12 +405,6 @@ function selectTurnMessages(allParsed, opts = {}) {
405
405
  }
406
406
  }
407
407
  const candidates = [];
408
- const summaryRange = turnStart >= 0 ? turnStart : allParsed.length;
409
- for (let ai = 0; ai < summaryRange; ai++) {
410
- if (allParsed[ai].isSummary) {
411
- candidates.push(allParsed[ai]);
412
- }
413
- }
414
408
  const seenIndices = new Set(candidates.map((m) => m.index));
415
409
  if (turnStart >= 0) {
416
410
  const total = allParsed.length - turnStart;
@@ -696,11 +690,24 @@ async function recall(provider, query, userId, config = {}, sessionId) {
696
690
  return { context, memories: budgeted, tokenEstimate };
697
691
  }
698
692
 
699
- // src/debug-policy.ts
700
- var OFFICIAL_PRODUCTION_BASE_URLS = [
701
- "https://api.cn-hangzhou.agentcontext.aliyuncs.com",
702
- "https://context-database.aliyuncs.com"
703
- ];
693
+ // src/sites.ts
694
+ var PUBLIC_SITES = {
695
+ cn: {
696
+ baseUrl: "https://api.cn-hangzhou.agentcontext.aliyuncs.com",
697
+ aliases: ["https://context-database.aliyuncs.com"],
698
+ authorizationUrl: "https://rdsnext.console.aliyun.com/contextDbCliAuthorization/cn-hangzhou"
699
+ },
700
+ intl: {
701
+ baseUrl: "https://context-database.ap-southeast-1.aliyuncs.com",
702
+ aliases: [],
703
+ authorizationUrl: "https://rds.console.alibabacloud.com/contextDbCliAuthorization/ap-southeast-1"
704
+ }
705
+ };
706
+ function parsePublicSite(value) {
707
+ if (value === void 0) return void 0;
708
+ if (value !== "cn" && value !== "intl") throw new Error("--site requires cn or intl.");
709
+ return value;
710
+ }
704
711
  function normalizeBaseUrl(value) {
705
712
  try {
706
713
  const parsed = new URL(value.trim());
@@ -712,12 +719,24 @@ function normalizeBaseUrl(value) {
712
719
  return null;
713
720
  }
714
721
  }
715
- var NORMALIZED_PRODUCTION_URLS = new Set(
716
- OFFICIAL_PRODUCTION_BASE_URLS.map((url) => normalizeBaseUrl(url))
717
- );
718
- function isOfficialProductionUrl(value) {
722
+ function publicSiteForUrl(value) {
719
723
  const normalized = normalizeBaseUrl(value);
720
- return normalized !== null && NORMALIZED_PRODUCTION_URLS.has(normalized);
724
+ return Object.keys(PUBLIC_SITES).find((site) => {
725
+ const preset = PUBLIC_SITES[site];
726
+ return [preset.baseUrl, ...preset.aliases].some((url) => url === normalized);
727
+ });
728
+ }
729
+ function siteBaseUrl(site, baseUrl) {
730
+ const selected = parsePublicSite(site);
731
+ if (selected === void 0) return void 0;
732
+ if (baseUrl !== void 0) throw new Error("--site and --base-url/--server are mutually exclusive.");
733
+ return PUBLIC_SITES[selected].baseUrl;
734
+ }
735
+
736
+ // src/debug-policy.ts
737
+ var OFFICIAL_PRODUCTION_BASE_URLS = Object.values(PUBLIC_SITES).flatMap((site) => [site.baseUrl, ...site.aliases]);
738
+ function isOfficialProductionUrl(value) {
739
+ return publicSiteForUrl(value) !== void 0;
721
740
  }
722
741
  function resolveDebugPolicy(configuredDebug, effectiveBaseUrl) {
723
742
  const debugForced = !isOfficialProductionUrl(effectiveBaseUrl);
@@ -2073,7 +2092,7 @@ function createRequestAuthorizationProvider(credential, baseUrl) {
2073
2092
  }
2074
2093
 
2075
2094
  // src/data-endpoint.ts
2076
- var DEFAULT_DATA_BASE_URL = "https://api.cn-hangzhou.agentcontext.aliyuncs.com";
2095
+ var DEFAULT_DATA_BASE_URL = PUBLIC_SITES.cn.baseUrl;
2077
2096
  function validateDataBaseUrl(value, coreOrigin = false) {
2078
2097
  try {
2079
2098
  if (typeof value !== "string" || !value || /[\s\x00-\x1f\x7f]/.test(value) || !/^https?:\/\//i.test(value)) throw new Error();
@@ -2190,9 +2209,27 @@ async function bindLogin(path, agent, name) {
2190
2209
  else await new OAuthSessionStore(source.credentialsPath).share(source.reference, source.profile, loginId, commit);
2191
2210
  }
2192
2211
  async function setupAuthentication(path, agent, options, env = process.env) {
2212
+ const preset = siteBaseUrl(options.site, options.baseUrl);
2213
+ if (preset) {
2214
+ const raw2 = readAuthConfig(path);
2215
+ const existing = options.login ? namedLogin(raw2, path, options.login).baseUrl : replacementBaseUrl(raw2, path, agent);
2216
+ const baseUrl = options.apiKey === void 0 && publicSiteForUrl(existing) === options.site ? existing : preset;
2217
+ if (options.apiKey === void 0 && existing !== baseUrl) {
2218
+ throw new AuthConfigError("Site does not match the selected credential. Run ctxdb login --site " + options.site + " or provide --api-key for that site.");
2219
+ }
2220
+ options = { ...options, baseUrl };
2221
+ }
2193
2222
  if (options.baseUrl !== void 0) validateDataBaseUrl(options.baseUrl);
2194
2223
  await selectSetupAuthentication(path, agent, options, env);
2195
- if (options.baseUrl === void 0 && !options.preserveBaseUrl) await resetSetupBaseUrl(path, agent, env);
2224
+ if (options.preserveBaseUrl || options.baseUrl !== void 0) return;
2225
+ const raw = readAuthConfig(path), profile = ownAuthProfile(raw, agent), fallback = ownAuthProfile(raw, "default");
2226
+ if (publicAuthenticationFromConfig(raw, path, agent) || Object.hasOwn(profile, "access_credential")) return;
2227
+ const key = Object.hasOwn(profile, "api_key") ? profile.api_key : fallback.api_key;
2228
+ if (typeof key === "string" && key && !env.CTXDB_ACCESS_TOKEN && !env.CTXDB_API_KEY) {
2229
+ rejectAuthEnvironment(env);
2230
+ const baseUrl = replacementBaseUrl(raw, path, agent);
2231
+ if (baseUrl !== DEFAULT_DATA_BASE_URL) saveSetupKey(path, agent, raw, key, baseUrl);
2232
+ }
2196
2233
  }
2197
2234
  async function selectSetupAuthentication(path, agent, options, env = process.env) {
2198
2235
  if (options.apiKey !== void 0 && options.login !== void 0) throw new AuthConfigError("--api-key and --login are mutually exclusive.");
@@ -2200,7 +2237,7 @@ async function selectSetupAuthentication(path, agent, options, env = process.env
2200
2237
  rejectAuthEnvironment(env);
2201
2238
  if (!options.apiKey.trim()) throw new AuthConfigError("--api-key requires a nonempty value.");
2202
2239
  const raw2 = readAuthConfig(path);
2203
- const baseUrl = options.baseUrl ?? (options.preserveBaseUrl ? replacementBaseUrl(raw2, path, agent) : DEFAULT_DATA_BASE_URL);
2240
+ const baseUrl = options.baseUrl ?? replacementBaseUrl(raw2, path, agent);
2204
2241
  saveSetupKey(path, agent, raw2, options.apiKey, baseUrl);
2205
2242
  return;
2206
2243
  }
@@ -2256,42 +2293,6 @@ function saveSetupKey(path, agent, raw, apiKey, baseUrl) {
2256
2293
  throw new AuthConfigError("New API key was saved, but cleanup of the previous local key could not be confirmed. Inspect credentials.json before retrying.");
2257
2294
  }
2258
2295
  }
2259
- async function resetSetupBaseUrl(path, agent, env) {
2260
- const raw = readAuthConfig(path), s = ownAuthProfile(raw, agent);
2261
- const stored = publicAuthenticationFromConfig(raw, path, agent);
2262
- if (stored?.baseUrl === DEFAULT_DATA_BASE_URL) return;
2263
- const profile = stored?.oauthCredential;
2264
- if (profile) {
2265
- rejectAuthEnvironment(env);
2266
- const expected = authSnapshot(raw, agent), group = groupSnapshot(raw, profile);
2267
- await new OAuthSessionStore(profile.credentialsPath).changeBaseUrl(profile.reference, oauthOwner(profile), DEFAULT_DATA_BASE_URL, () => {
2268
- const current = readAuthConfig(path);
2269
- assertAuthSnapshot(current, agent, expected);
2270
- if (groupSnapshot(current, profile) !== group) throw new AuthConfigError("The shared login or its users changed during setup; retry setup.");
2271
- });
2272
- return;
2273
- }
2274
- if (Object.hasOwn(s, "access_credential")) return;
2275
- const d = ownAuthProfile(raw, "default");
2276
- const key = stored?.apiKey ?? (Object.hasOwn(s, "api_key") ? s.api_key : d.api_key);
2277
- if (typeof key !== "string" || !key) return;
2278
- const baseUrl = stored?.baseUrl ?? s.base_url ?? d.base_url ?? DEFAULT_DATA_BASE_URL;
2279
- if (baseUrl === DEFAULT_DATA_BASE_URL) return;
2280
- rejectAuthEnvironment(env);
2281
- if (stored?.apiKey) {
2282
- const expected = authSnapshot(raw, agent), provider = new LocalCredentialProvider(join5(dirname6(path), "credentials.json"));
2283
- provider.transaction((tx) => withAuthConfigLock(path, () => {
2284
- const current = readAuthConfig(path);
2285
- assertAuthSnapshot(current, agent, expected);
2286
- publicAuthenticationFromConfig(current, path, agent);
2287
- const before = tx.read(s.credential_ref);
2288
- if (!before.record) throw new AuthConfigError("API key credential changed during setup; retry setup.");
2289
- tx.put(s.credential_ref, { ...before.record, metadata: { ...before.record.metadata, base_url: DEFAULT_DATA_BASE_URL } }, before);
2290
- }));
2291
- return;
2292
- }
2293
- saveSetupKey(path, agent, raw, key, DEFAULT_DATA_BASE_URL);
2294
- }
2295
2296
  function replacementBaseUrl(raw, path, agent) {
2296
2297
  for (const candidate of agent === "default" ? [agent] : [agent, "default"]) {
2297
2298
  try {
@@ -2535,6 +2536,337 @@ function publicAuthorizationTarget(pending, revoke) {
2535
2536
  }
2536
2537
  };
2537
2538
  }
2539
+
2540
+ // src/memory-cleanup.ts
2541
+ var SHELL_TOOLS = /* @__PURE__ */ new Set([
2542
+ "bash",
2543
+ "exec",
2544
+ "shell",
2545
+ "sh",
2546
+ "terminal",
2547
+ "exec_command",
2548
+ "run_in_terminal",
2549
+ "functions.exec_command",
2550
+ "functions.shell_command",
2551
+ "shell_command"
2552
+ ]);
2553
+ var CONTEXTDB_PROVIDERS = /* @__PURE__ */ new Set(["ctxdb", "contextdb", "openclaw_memory_rds_ctxdb"]);
2554
+ var DELETE_TOOLS = /* @__PURE__ */ new Set(["memory_delete", "memory_batch_delete"]);
2555
+ var CLI_NAMES = /* @__PURE__ */ new Set(["ctxdb", "ctxdb-qoder", "ctxdb_qoder", "rds-ctxdb", "rds_ctxdb", "qoder-ctxdb", "qoder_ctxdb"]);
2556
+ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set(["help", "json", "verbose", "all", "yes"]);
2557
+ function shellTokens(command) {
2558
+ const tokens = [];
2559
+ let value = "", active = false, quote = "";
2560
+ const flush = () => {
2561
+ if (active) tokens.push({ value });
2562
+ value = "";
2563
+ active = false;
2564
+ };
2565
+ for (let i = 0; i < command.length; i++) {
2566
+ const c = command[i];
2567
+ if (quote) {
2568
+ if (c === quote) {
2569
+ quote = "";
2570
+ continue;
2571
+ }
2572
+ if (quote === '"' && c === "\\" && /["\\$`\n]/.test(command[i + 1] ?? "")) {
2573
+ const next = command[++i];
2574
+ if (next !== "\n") value += next;
2575
+ continue;
2576
+ }
2577
+ if (quote === '"' && (c === "`" || c === "$" && command[i + 1] === "(")) return null;
2578
+ value += c;
2579
+ continue;
2580
+ }
2581
+ if (c === "'" || c === '"') {
2582
+ active = true;
2583
+ quote = c;
2584
+ continue;
2585
+ }
2586
+ if (c === "\\") {
2587
+ const next = command[i + 1];
2588
+ if (next === void 0) return null;
2589
+ if (/[\s'"\\;&|<>$`]/.test(next)) {
2590
+ i++;
2591
+ if (next !== "\n") {
2592
+ value += next;
2593
+ active = true;
2594
+ }
2595
+ } else {
2596
+ value += c;
2597
+ active = true;
2598
+ }
2599
+ continue;
2600
+ }
2601
+ if (c === "#" && !active) {
2602
+ while (i < command.length && command[i] !== "\n") i++;
2603
+ flush();
2604
+ tokens.push({ value: ";", operator: true });
2605
+ continue;
2606
+ }
2607
+ if (c === "`" || c === "$" && command[i + 1] === "(") return null;
2608
+ if (c === "<" && command[i + 1] === "<") return null;
2609
+ if (/[;&|\n()<>]/.test(c)) {
2610
+ flush();
2611
+ let op = c;
2612
+ if (command[i + 1] === c && /[&|>]/.test(c)) op += command[++i];
2613
+ tokens.push({ value: op, operator: true });
2614
+ continue;
2615
+ }
2616
+ if (/\s/.test(c)) {
2617
+ flush();
2618
+ continue;
2619
+ }
2620
+ active = true;
2621
+ value += c;
2622
+ }
2623
+ if (quote) return null;
2624
+ flush();
2625
+ return tokens;
2626
+ }
2627
+ function basename(path) {
2628
+ return path.split(/[\\/]/).at(-1).replace(/\.(?:cmd|exe)$/i, "");
2629
+ }
2630
+ function cliOperation(argv) {
2631
+ if (argv.some((a) => a === "--help" || a.startsWith("--help=") || a === "-h")) return;
2632
+ const positional = [];
2633
+ let literal = false;
2634
+ for (let i = 1; i < argv.length; i++) {
2635
+ const arg = argv[i];
2636
+ if (arg === "--") {
2637
+ literal = true;
2638
+ continue;
2639
+ }
2640
+ if (!literal && arg.startsWith("--")) {
2641
+ if (!arg.includes("=") && !BOOLEAN_FLAGS.has(arg.slice(2)) && argv[i + 1] && !argv[i + 1].startsWith("--")) i++;
2642
+ } else positional.push(arg);
2643
+ }
2644
+ if (positional[0] !== "memory") return;
2645
+ if (positional[1] === "delete" || positional[1] === "batch-delete") return positional[1];
2646
+ }
2647
+ function commandOperation(argv, depth) {
2648
+ let i = 0;
2649
+ while (/^[A-Za-z_][\w]*=/.test(argv[i] ?? "")) i++;
2650
+ if (basename(argv[i] ?? "") === "env") {
2651
+ i++;
2652
+ while (i < argv.length) {
2653
+ if (argv[i] === "--") {
2654
+ i++;
2655
+ break;
2656
+ }
2657
+ if (argv[i] === "-u" || argv[i] === "--unset") {
2658
+ i += 2;
2659
+ continue;
2660
+ }
2661
+ if (argv[i] === "-i" || argv[i] === "--ignore-environment" || argv[i].startsWith("--unset=") || /^[A-Za-z_][\w]*=/.test(argv[i])) {
2662
+ i++;
2663
+ continue;
2664
+ }
2665
+ break;
2666
+ }
2667
+ }
2668
+ if (argv[i] === "command") {
2669
+ i++;
2670
+ if (argv[i] === "--") i++;
2671
+ }
2672
+ const name = basename(argv[i] ?? "");
2673
+ if (CLI_NAMES.has(name)) return cliOperation(argv.slice(i));
2674
+ if (depth < 3 && ["bash", "sh", "zsh"].includes(name)) {
2675
+ const flag = argv[i + 1];
2676
+ if (/^-[a-z]*c[a-z]*$/.test(flag ?? "") && argv[i + 2]) return shellOperation(argv[i + 2], depth + 1);
2677
+ }
2678
+ }
2679
+ function shellOperation(command, depth = 0) {
2680
+ const tokens = shellTokens(command);
2681
+ if (!tokens) return;
2682
+ let argv = [];
2683
+ for (let i = 0; i <= tokens.length; i++) {
2684
+ const token = tokens[i];
2685
+ if (token?.operator && ["<", ">", ">>"].includes(token.value)) {
2686
+ if (/^\d+$/.test(argv.at(-1) ?? "")) argv.pop();
2687
+ if (tokens[i + 1]?.value === "&") i++;
2688
+ i++;
2689
+ continue;
2690
+ }
2691
+ if (!token || token.operator) {
2692
+ const operation = commandOperation(argv, depth);
2693
+ if (operation) return operation;
2694
+ argv = [];
2695
+ } else argv.push(token.value);
2696
+ }
2697
+ }
2698
+ function detectMemoryCleanup(calls) {
2699
+ for (const call of calls) {
2700
+ const qualified = /^mcp__(ctxdb|contextdb)__([^_].*)$/.exec(call.name);
2701
+ const provider = call.provider ?? qualified?.[1];
2702
+ const toolName = qualified?.[2] ?? call.name;
2703
+ if (provider && CONTEXTDB_PROVIDERS.has(provider) && DELETE_TOOLS.has(toolName)) {
2704
+ return { detected: true, operation: toolName === "memory_batch_delete" ? "batch-delete" : "delete", source: "tool" };
2705
+ }
2706
+ if (!SHELL_TOOLS.has(call.name.toLowerCase())) continue;
2707
+ const command = call.arguments.command ?? call.arguments.cmd;
2708
+ if (typeof command !== "string") continue;
2709
+ const operation = shellOperation(command);
2710
+ if (operation) return { detected: true, operation, source: "cli" };
2711
+ }
2712
+ return { detected: false };
2713
+ }
2714
+
2715
+ // src/capture-events.ts
2716
+ var object4 = (v) => v && typeof v === "object" && !Array.isArray(v) ? v : {};
2717
+ function captureRecord(value) {
2718
+ const row = object4(value);
2719
+ if (row.type === "response_item" || row.type === "event_msg") return object4(row.payload);
2720
+ if (row.type === "message" && row.role) return row;
2721
+ if (row.message) return object4(row.message);
2722
+ return row;
2723
+ }
2724
+ var info = (v) => object4(object4(v).info);
2725
+ var role = (v) => info(v).role ?? captureRecord(v).role ?? object4(v).type;
2726
+ var parts = (v) => object4(v).parts ?? captureRecord(v).content ?? captureRecord(v).text;
2727
+ function hidden(v) {
2728
+ const row = object4(v), body = captureRecord(v);
2729
+ return [row, body, info(v)].some((r) => r.isMeta || r.isSidechain || r.is_synthetic || r.synthetic || r.ignored || r._pre_verify_synthetic || r._verify_on_stop_synthetic);
2730
+ }
2731
+ function captureText(value) {
2732
+ const content = parts(value);
2733
+ if (typeof content === "string") return content;
2734
+ if (!Array.isArray(content)) return "";
2735
+ if (role(value) === "user" && content.some((b) => object4(b).type === "tool_result")) return "";
2736
+ return content.flatMap((b) => {
2737
+ const block = object4(b);
2738
+ return !block.synthetic && !block.ignored && ["text", "input_text", "output_text"].includes(block.type) && typeof block.text === "string" ? [block.text] : [];
2739
+ }).join("\n");
2740
+ }
2741
+ function human(v) {
2742
+ if (hidden(v) || role(v) !== "user") return false;
2743
+ let text2 = captureText(v).trim();
2744
+ if (text2.includes("<user_query>")) text2 = /<user_query>([\s\S]*?)<\/user_query>/.exec(text2)?.[1] ?? "";
2745
+ if (/^(?:Stop hook feedback:|# AGENTS\.md instructions|<environment_context>|<INSTRUCTIONS>|<permissions instructions>|<collaboration_mode>|<recommended_plugins>|<apps_instructions>|<skills_instructions>|<plugins_instructions>|## Memory\s+You have access to a memory folder|<recalled-memories>|<available-knowledge-bases>|<external_codex_apps_open_page>)/.test(text2)) return false;
2746
+ if (stripNoiseFromContent(text2).trim()) return true;
2747
+ const content = parts(v);
2748
+ return Array.isArray(content) && content.some((b) => ["image", "input_image"].includes(object4(b).type));
2749
+ }
2750
+ function nativeTurn(v) {
2751
+ const row = object4(v), body = captureRecord(v), metadata = info(v);
2752
+ return (row.type === "turn_context" ? row.payload?.turn_id : void 0) ?? row.turn_id ?? row.turnId ?? body.turn_id ?? body.turnId ?? (metadata.role === "user" ? metadata.id : metadata.parentID);
2753
+ }
2754
+ function selectCaptureTurn(records) {
2755
+ let start = -1;
2756
+ for (let i = records.length - 1; i >= 0; i--) if (human(records[i])) {
2757
+ start = i;
2758
+ break;
2759
+ }
2760
+ if (start < 0) return [];
2761
+ let contextIndex = -1;
2762
+ for (let i = records.length - 1; i >= 0; i--) {
2763
+ const row = object4(records[i]);
2764
+ if (row.type === "turn_context" || row.type === "event_msg" && row.payload?.type === "task_started") {
2765
+ contextIndex = i;
2766
+ break;
2767
+ }
2768
+ }
2769
+ if (contextIndex > start) return [];
2770
+ const turn = nativeTurn(records[start]) ?? (contextIndex >= 0 ? nativeTurn(records[contextIndex]) : void 0);
2771
+ while (start > 0 && human(records[start - 1]) && (turn ? nativeTurn(records[start - 1]) === turn : !nativeTurn(records[start - 1]))) start--;
2772
+ const selected = records.slice(start).filter((r) => !hidden(r) && (role(r) !== "user" || human(r) || Array.isArray(parts(r)) && parts(r).some((b) => b?.type === "tool_result")) && (!turn || !nativeTurn(r) || nativeTurn(r) === turn));
2773
+ return contextIndex >= 0 ? [records[contextIndex], ...selected] : selected;
2774
+ }
2775
+ function argumentsObject(v) {
2776
+ if (typeof v !== "string") return object4(v);
2777
+ try {
2778
+ return object4(JSON.parse(v));
2779
+ } catch {
2780
+ return {};
2781
+ }
2782
+ }
2783
+ function captureToolCalls(records, registeredTools = {}) {
2784
+ const calls = [];
2785
+ for (const raw of records) {
2786
+ if (hidden(raw)) continue;
2787
+ const body = captureRecord(raw);
2788
+ const blocks = [];
2789
+ if (body.type === "function_call" || body.type === "custom_tool_call") blocks.push(body);
2790
+ if (role(raw) === "assistant") {
2791
+ if (Array.isArray(parts(raw))) blocks.push(...parts(raw).map(object4).filter((b) => ["tool_use", "toolCall", "tool"].includes(b.type)));
2792
+ if (Array.isArray(body.tool_calls)) blocks.push(...body.tool_calls.map(object4));
2793
+ }
2794
+ for (const block of blocks) {
2795
+ const fn = object4(block.function);
2796
+ const name = fn.name ?? block.name ?? block.tool;
2797
+ if (typeof name !== "string") continue;
2798
+ const encodedArguments = fn.arguments ?? block.arguments;
2799
+ let invalidArguments = false;
2800
+ if (typeof encodedArguments === "string") {
2801
+ try {
2802
+ const parsed = JSON.parse(encodedArguments);
2803
+ invalidArguments = !parsed || typeof parsed !== "object" || Array.isArray(parsed);
2804
+ } catch {
2805
+ invalidArguments = true;
2806
+ }
2807
+ }
2808
+ const args = argumentsObject(encodedArguments ?? block.input ?? block.parameters ?? block.state?.input);
2809
+ const provider = block.provider ?? block.server_name ?? registeredTools[name];
2810
+ const id = block.call_id ?? block.callID ?? block.callId ?? block.id;
2811
+ calls.push({
2812
+ name,
2813
+ arguments: args,
2814
+ ...invalidArguments ? { invalidArguments: true } : {},
2815
+ ...typeof provider === "string" ? { provider } : {},
2816
+ ...typeof id === "string" ? { id } : {}
2817
+ });
2818
+ }
2819
+ }
2820
+ return calls;
2821
+ }
2822
+ function captureCompletionReason(records, signal = {}) {
2823
+ if (!records.length) return "no_user_in_turn";
2824
+ const pending = /* @__PURE__ */ new Set();
2825
+ let lastAssistant, lastAssistantIndex = -1, lastToolIndex = -1;
2826
+ for (let i = 0; i < records.length; i++) {
2827
+ const raw = records[i], body2 = captureRecord(raw), metadata2 = info(raw), row2 = object4(raw);
2828
+ const session = row2.sessionId ?? row2.session_id ?? body2.session_id ?? metadata2.sessionID;
2829
+ if (signal.sessionId && session && session !== signal.sessionId) return "session_mismatch";
2830
+ const turn = nativeTurn(raw);
2831
+ if (signal.turnId && turn && turn !== signal.turnId) return "turn_unverified";
2832
+ if (role(raw) === "assistant") {
2833
+ lastAssistant = raw;
2834
+ lastAssistantIndex = i;
2835
+ }
2836
+ const calls = captureToolCalls([raw]);
2837
+ for (const call of calls) {
2838
+ if (call.invalidArguments) return "capture_input_incomplete";
2839
+ pending.add(call.id ?? `unknown:${i}`);
2840
+ lastToolIndex = i;
2841
+ }
2842
+ const content = Array.isArray(parts(raw)) ? parts(raw) : [];
2843
+ for (const part of content) {
2844
+ if (part?.type === "tool_result" && role(raw) !== "assistant" && typeof part.tool_use_id === "string") {
2845
+ pending.delete(part.tool_use_id);
2846
+ lastToolIndex = i;
2847
+ }
2848
+ if (part?.type === "tool" && ["completed", "error"].includes(part.state?.status)) pending.delete(part.callID ?? part.id);
2849
+ }
2850
+ if (["tool", "toolResult"].includes(String(role(raw))) || ["function_call_output", "function_call_result", "custom_tool_call_output"].includes(body2.type)) {
2851
+ pending.delete(body2.tool_call_id ?? body2.toolCallId ?? body2.call_id ?? body2.callId);
2852
+ lastToolIndex = i;
2853
+ }
2854
+ }
2855
+ if (pending.size) return "awaiting_tools";
2856
+ if (!lastAssistant || !captureText(lastAssistant).trim()) return "awaiting_assistant";
2857
+ const body = captureRecord(lastAssistant), metadata = info(lastAssistant), row = object4(lastAssistant);
2858
+ const phase = body.phase ?? row.phase;
2859
+ const finish = metadata.finish ?? body.stop_reason ?? body.finish_reason ?? row.finish_reason;
2860
+ if (metadata.error || body.error || ["tool_use", "tool_calls", "tool-calls", "length", "max_tokens", "error", "aborted"].includes(finish)) return "awaiting_final";
2861
+ if (phase && phase !== "final" && phase !== "final_answer") return "awaiting_final";
2862
+ const canonical = (s) => stripNoiseFromContent(s).replace(/\r\n/g, "\n").trim();
2863
+ if (signal.lastAssistantMessage && canonical(captureText(lastAssistant)) !== canonical(signal.lastAssistantMessage)) return "awaiting_host_final";
2864
+ const sdkFinal = metadata.time?.completed && metadata.finish === "stop";
2865
+ if (metadata.role === "assistant" && !sdkFinal) return "awaiting_final";
2866
+ if (lastAssistantIndex <= lastToolIndex && !sdkFinal) return "awaiting_final";
2867
+ if (signal.completed || signal.lastAssistantMessage || sdkFinal || ["end_turn", "stop"].includes(finish) || phase === "final" || phase === "final_answer") return;
2868
+ return "awaiting_final";
2869
+ }
2538
2870
  export {
2539
2871
  ACTIVE_CONTEXTDB_CREDENTIAL,
2540
2872
  AuthConfigError,
@@ -2558,6 +2890,7 @@ export {
2558
2890
  OAuthProfileProvider,
2559
2891
  OAuthSessionStore,
2560
2892
  OFFICIAL_PRODUCTION_BASE_URLS,
2893
+ PUBLIC_SITES,
2561
2894
  RECALLED_MEMORIES_SAFETY_NOTICE,
2562
2895
  RECALL_TRACE_AGENTS,
2563
2896
  RECALL_TRACE_FILENAME,
@@ -2572,12 +2905,17 @@ export {
2572
2905
  buildExternalKnowledgeBlock,
2573
2906
  buildExternalKnowledgePreamble,
2574
2907
  buildNormalizedGraphContext,
2908
+ captureCompletionReason,
2909
+ captureRecord,
2910
+ captureText,
2911
+ captureToolCalls,
2575
2912
  collectUnusedLogins,
2576
2913
  commitLogin,
2577
2914
  createRecallFinishRecord,
2578
2915
  createRecallStartRecord,
2579
2916
  createRequestAuthorizationProvider,
2580
2917
  defaultCredentialsPath,
2918
+ detectMemoryCleanup,
2581
2919
  extractKnowledgeBaseIds,
2582
2920
  extractKnowledgeChunkContent,
2583
2921
  extractKnowledgeChunkSourceLabel,
@@ -2603,11 +2941,13 @@ export {
2603
2941
  oauthSessionCandidate,
2604
2942
  oauthSessionFromCredential,
2605
2943
  ownAuthProfile,
2944
+ parsePublicSite,
2606
2945
  partitionKnowledgeChunks,
2607
2946
  preserveDefaultApiKey,
2608
2947
  publicApiKeyFromConfig,
2609
2948
  publicAuthenticationFromConfig,
2610
2949
  publicAuthorizationTarget,
2950
+ publicSiteForUrl,
2611
2951
  readActiveCredentialSync,
2612
2952
  readAuthConfig,
2613
2953
  readRecallTraces,
@@ -2621,10 +2961,12 @@ export {
2621
2961
  sanitizeQuery,
2622
2962
  sanitizeRecallFailureReason,
2623
2963
  selectAndFormatRecalledMemories,
2964
+ selectCaptureTurn,
2624
2965
  selectDataApiCredential,
2625
2966
  selectTurnMessages,
2626
2967
  selectedLogin,
2627
2968
  setupAuthentication,
2969
+ siteBaseUrl,
2628
2970
  stripNoiseFromContent,
2629
2971
  truncateGraphContext,
2630
2972
  unbindLogin,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aliyunrds/ctxdb-shared",
3
- "version": "0.0.9",
3
+ "version": "0.0.10-beta.0",
4
4
  "type": "module",
5
5
  "description": "Shared B-rule modules + memory/KB types for RDS ContextDatabase access layers (OpenClaw fork + Qoder hooks).",
6
6
  "license": "Apache-2.0",