@c4a/server-cli 0.4.15-alpha.5 → 0.4.15-alpha.7

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/index.js CHANGED
@@ -220991,6 +220991,12 @@ class LlmServiceImpl {
220991
220991
  if (options?.systemPrompt) {
220992
220992
  callSettings.system = options.systemPrompt;
220993
220993
  }
220994
+ if (options?.jsonMode) {
220995
+ callSettings.providerOptions = {
220996
+ openai: { responseFormat: { type: "json_object" } },
220997
+ anthropic: { responseFormat: { type: "json_object" } }
220998
+ };
220999
+ }
220994
221000
  const result = await retry(() => generateText(callSettings), {
220995
221001
  shouldRetry: (error40) => isRetryableStatus(getHttpStatus(error40)) || isTimeoutError2(error40)
220996
221002
  });
@@ -221038,6 +221044,12 @@ class LlmServiceImpl {
221038
221044
  if (options?.systemPrompt) {
221039
221045
  callSettings.system = options.systemPrompt;
221040
221046
  }
221047
+ if (options?.jsonMode) {
221048
+ callSettings.providerOptions = {
221049
+ openai: { responseFormat: { type: "json_object" } },
221050
+ anthropic: { responseFormat: { type: "json_object" } }
221051
+ };
221052
+ }
221041
221053
  const result = await retry(() => Promise.resolve(streamText(callSettings)), {
221042
221054
  shouldRetry: (error40) => isRetryableStatus(getHttpStatus(error40)) || isTimeoutError2(error40)
221043
221055
  });
@@ -221856,6 +221868,7 @@ function parseExtractionOutput(raw, schema) {
221856
221868
  }
221857
221869
  parsed = normalizeFlatOutput(parsed);
221858
221870
  parsed = stripNulls(parsed);
221871
+ parsed = patchAttributeDefaults(parsed);
221859
221872
  const result = schema.safeParse(parsed);
221860
221873
  if (!result.success) {
221861
221874
  return { success: false, error: result.error };
@@ -221923,7 +221936,37 @@ function tryParseJson(raw) {
221923
221936
  return repairAndParse(raw);
221924
221937
  }
221925
221938
  function repairAndParse(raw) {
221926
- return JSON.parse(jsonrepair(raw));
221939
+ try {
221940
+ return JSON.parse(jsonrepair(raw));
221941
+ } catch {
221942
+ const truncated = truncateToLastCompleteEntry(raw);
221943
+ if (truncated) {
221944
+ return JSON.parse(jsonrepair(truncated));
221945
+ }
221946
+ throw new Error(`JSON repair failed for output of length ${raw.length}`);
221947
+ }
221948
+ }
221949
+ function truncateToLastCompleteEntry(raw) {
221950
+ let text2 = raw.trim();
221951
+ if (text2.startsWith("```")) {
221952
+ const firstNewline = text2.indexOf(`
221953
+ `);
221954
+ text2 = text2.slice(firstNewline + 1);
221955
+ }
221956
+ if (text2.endsWith("```")) {
221957
+ text2 = text2.slice(0, -3);
221958
+ }
221959
+ const pattern = /\}\s*,\s*"P\d+"/g;
221960
+ let lastMatch = null;
221961
+ let m;
221962
+ while ((m = pattern.exec(text2)) !== null) {
221963
+ lastMatch = m;
221964
+ }
221965
+ if (!lastMatch)
221966
+ return null;
221967
+ const cutPos = lastMatch.index + 1;
221968
+ const truncated = text2.slice(0, cutPos) + "}";
221969
+ return truncated;
221927
221970
  }
221928
221971
  var PARAGRAPH_TAG_RE = /^P\d+$/;
221929
221972
  function normalizeFlatOutput(parsed) {
@@ -221956,6 +221999,43 @@ function stripNulls(value) {
221956
221999
  }
221957
222000
  return value;
221958
222001
  }
222002
+ function patchAttributeDefaults(value) {
222003
+ if (!value || typeof value !== "object" || Array.isArray(value))
222004
+ return value;
222005
+ const obj = value;
222006
+ if ("paragraphs" in obj && Array.isArray(obj.paragraphs)) {
222007
+ return {
222008
+ ...obj,
222009
+ paragraphs: obj.paragraphs.map((p) => {
222010
+ if (!p || typeof p !== "object")
222011
+ return p;
222012
+ const para = p;
222013
+ const atoms2 = para.atoms;
222014
+ if (!atoms2 || typeof atoms2 !== "object")
222015
+ return p;
222016
+ return { ...para, atoms: patchAttrsInAtoms(atoms2) };
222017
+ })
222018
+ };
222019
+ }
222020
+ return value;
222021
+ }
222022
+ function patchAttrsInAtoms(atoms2) {
222023
+ const attrs = atoms2.attributes;
222024
+ if (!Array.isArray(attrs))
222025
+ return atoms2;
222026
+ return {
222027
+ ...atoms2,
222028
+ attributes: attrs.map((attr) => {
222029
+ if (!attr || typeof attr !== "object" || Array.isArray(attr))
222030
+ return attr;
222031
+ const a = attr;
222032
+ if (typeof a.type !== "string" || a.type === "") {
222033
+ return { ...a, type: "other" };
222034
+ }
222035
+ return attr;
222036
+ })
222037
+ };
222038
+ }
221959
222039
  function isRecord(value) {
221960
222040
  return !!value && typeof value === "object" && "key" in value && "value" in value && typeof value.key === "string";
221961
222041
  }
@@ -222212,20 +222292,20 @@ class GleaningExtractor {
222212
222292
  // ../llm/src/prompts/docAtomAnnotation.ts
222213
222293
  init_src();
222214
222294
  var DOC_ATOM_DEFS = [
222215
- ["entities", "Named things: systems, services, modules, documents, APIs (NOT people/teams — use roles for those)", entityAtomSchema],
222295
+ ["entities", "Named things with independent identity — something you can ask questions about ('What does X do?', 'Who owns X?'). Examples: systems, services, modules, APIs, products. If it is a value, address, path, or configuration detail, it is an attribute of an entity, not an entity itself. (NOT people/teams — use roles for those). kind: implementation=internal systems/services, external=third-party dependencies, concept=abstract/not-yet-implemented", entityAtomSchema],
222216
222296
  ["relations", "Connections between entities", relationAtomSchema],
222217
222297
  ["behaviors", "Actions/operations: functions, API calls, user actions, workflows", behaviorAtomSchema],
222218
222298
  ["attributes", "Properties of entities", attributeAtomSchema],
222219
222299
  ["states", "Possible states of entities", stateAtomSchema],
222220
- ["rules", "Business/domain rules: validations, constraints expressed as logic", ruleAtomSchema],
222300
+ ["rules", "Conditional business/domain logic: IF condition THEN consequence (e.g., 'IF user not authenticated THEN reject request')", ruleAtomSchema],
222221
222301
  ["transitions", "State changes: from→to triggered by events or guards", transitionAtomSchema],
222222
222302
  ["events", "Occurrences that trigger behaviors", eventAtomSchema],
222223
222303
  ["decisions", "Architectural or business decisions", decisionAtomSchema],
222224
222304
  ["metrics", "Measurable targets: SLA, throughput, error_rate, with thresholds", metricAtomSchema],
222225
- ["roles", "Actors: human roles, teams, personas that perform behaviors", roleAtomSchema],
222226
- ["constraints", "Hard/soft requirements", constraintAtomSchema],
222305
+ ["roles", "Actors: human roles, teams, personas that perform behaviors. kind: human=individual role, team=group/department, persona=user archetype. System-triggered actions use entity relations, NOT roles", roleAtomSchema],
222306
+ ["constraints", "Declarative requirements: 'X must/should/must-not Y' (e.g., 'passwords must be >= 8 chars'). Unlike rules, constraints have no IF-THEN condition — they are unconditional mandates or restrictions", constraintAtomSchema],
222227
222307
  ["comparisons", "Side-by-side evaluations", comparisonAtomSchema],
222228
- ["boundaries", "System/domain boundaries: what is included vs excluded", boundaryAtomSchema]
222308
+ ["boundaries", "Explicit scope declarations: what is included vs excluded. Only extract when the text explicitly declares scope (e.g., 'this product covers X but NOT Y'). Implicit containment (A runs inside B) is expressed via entity relations, not boundaries", boundaryAtomSchema]
222229
222309
  ];
222230
222310
  function buildAtomTypesBlock() {
222231
222311
  return DOC_ATOM_DEFS.map(([name21, desc, schema], i) => {
@@ -222255,7 +222335,8 @@ Return a single JSON object keyed by paragraph tags. Only include paragraphs tha
222255
222335
  "relations": [{ "from": "UserService", "to": "Database", "type": "DEPENDS_ON", "confidence": 0.9 }]
222256
222336
  },
222257
222337
  "P3": {
222258
- "rules": [{ "description": "User must be authenticated before access", "expression": "user.isAuthenticated == true", "confidence": 0.85 }]
222338
+ "constraints": [{ "description": "User must be authenticated before access", "severity": "must", "confidence": 0.9 }],
222339
+ "rules": [{ "description": "Reject request if user is not authenticated", "expression": "IF !user.isAuthenticated THEN reject", "confidence": 0.85 }]
222259
222340
  }
222260
222341
  }
222261
222342
 
@@ -222267,7 +222348,13 @@ Return a single JSON object keyed by paragraph tags. Only include paragraphs tha
222267
222348
  - **Enum fields MUST use ONLY the listed values.** For example, entity.kind must be one of "implementation"|"external"|"concept" — do NOT use values from other atom types (e.g., do NOT put "team" or "human" in entity.kind; those belong to roles.kind).
222268
222349
  - Every atom MUST include a "confidence" field (0.0-1.0) indicating how confident you are in the extraction. Use higher values (0.85-1.0) for explicitly stated facts and lower values (0.5-0.7) for inferred or ambiguous information.
222269
222350
  - **Classify correctly:** People, teams, and personas → "roles" (not "entities"). Technical systems, services, modules → "entities".
222351
+ - **Entity naming — extract the subject, not the document:** Entity names should represent the actual system/product/framework being described, not the document itself. If the text says "Next.js is a React framework", the entity is "Next.js" — not "Next.js 官方文档" or "Next.js API 参考". Use names that work as standalone knowledge graph nodes, independent of any document context.
222270
222352
  - **Entity reference consistency (CRITICAL):** Every entity name referenced in relation.from, relation.to, behavior.subject, or any other cross-reference field MUST also appear in the "entities" array of the SAME paragraph (or a preceding paragraph in the same chunk). If an entity is mentioned for the first time in a relation, you MUST also extract it as an entity. This ensures no "dangling references" — every name used in relations has a corresponding entity declaration.
222353
+ - **Cross-atom reference consistency:** transitions[].from and transitions[].to values MUST exist in states[].values of the same entity. roles[].performs values MUST match names declared in behaviors[].name.
222354
+ - **Constraints vs rules distinction:** Use "constraints" for unconditional declarative mandates ('X must Y'). Use "rules" for conditional logic ('IF X THEN Y'). Do not mix them — a requirement with no condition is a constraint, a requirement triggered by a condition is a rule. Do NOT invent a rule for every constraint — only create a rule when the text explicitly states conditional logic.
222355
+ - **One statement, multiple atoms:** A single sentence can produce several atom types simultaneously. Do NOT force a choice — extract all that apply. Example: "system uptime must be ≥ 99.9%" → constraint (severity: must) + metric (threshold: "≥ 99.9%").
222356
+ - **Relation types:** Use standard relation types when possible: CONTAINS (parent→child composition), DEPENDS_ON (runtime dependency), IMPLEMENTS (code/component→spec realization), PRODUCES (process→output), TRIGGERS (event/process triggering), REFERENCES (weak cross-reference). Only invent a new type when none of these fit.
222357
+ - **Decisions:** Extract as "decisions" when the text records a deliberate choice between alternatives with rationale (e.g., "we chose X because Y", "after evaluating A/B/C, selected B"). Do not extract routine descriptions as decisions.
222271
222358
  - Respond in the same language as the input text (e.g., Chinese input → Chinese descriptions, English input → English descriptions).
222272
222359
  - JSON structure keys (tag, atom type names, field names) must always be in English.
222273
222360
  - Be thorough: extract ALL relevant atoms from each paragraph.
@@ -222321,14 +222408,15 @@ var ENTITY_RESOLUTION_SYSTEM_PROMPT = `You are an entity resolution assistant. Y
222321
222408
  - Prefer the LONGER, more descriptive name as the canonical name
222322
222409
  - Do NOT merge names that share a substring but refer to different things
222323
222410
  - When uncertain, do NOT merge — add to "ambiguous" instead
222324
- - Chinese and English names for the same entity SHOULD be merged (e.g. "Vmok" → "Vmok 微模块框架")
222325
- - Abbreviations should be merged with their full forms (e.g. "AGW" → "API Gateway")
222411
+ - Chinese and English names for the same entity SHOULD be merged (e.g. "Webpack" → "Webpack 打包工具")
222412
+ - Abbreviations should be merged with their full forms (e.g. "K8s" → "Kubernetes")
222413
+ - Document-descriptive names (containing "文档", "参考", "指南" etc.) should be merged to the actual product/system name. The entity is the product, not the document about it
222326
222414
 
222327
222415
  ## Task 2: Remove Noise
222328
- - Remove names that are NOT meaningful named entities they are generic words, actions, or descriptions
222329
- - Examples of noise: common verbs/nouns (登录, 路由, 直连), generic technical terms (Env, query), action descriptions (Kill 3001 进程)
222330
- - Examples of REAL entities to KEEP: product names (TTAstra, Gulux), tools (nvm, Rush), services (Op Main 服务), platforms (AGW 平台)
222331
- - When uncertain, KEEP the name — only remove if clearly not a named entity
222416
+ - Apply the **identity test**: a real entity is something you can discuss independently ("What is X?", "How does X work?", "Who owns X?"). Names that fail this test — values, addresses, actions, generic descriptions — are noise.
222417
+ - Remove names that are NOT meaningful named entities: generic words, action descriptions, or things that are attributes/values rather than independent subjects
222418
+ - Examples of REAL entities to KEEP: product names (Next.js, Vite), tools (nvm, Turborepo), services (Nginx, Redis), platforms (Kubernetes, Docker) — these all pass the identity test
222419
+ - When uncertain, KEEP the name — only remove if it clearly fails the identity test
222332
222420
 
222333
222421
  ## Output
222334
222422
  Valid JSON only. No markdown fences, no explanation.`;
@@ -222571,7 +222659,7 @@ Each diagram paragraph is tagged with [P0], [P1], etc. You must classify the dia
222571
222659
  Relation schema: ${relationFields2}
222572
222660
  3. Extract action nodes as behaviors (what the process does at each step).
222573
222661
  Behavior schema: ${behaviorFields2}
222574
- 4. Extract diamond/decision nodes as decisions.
222662
+ 4. Extract diamond/condition nodes: if it represents a deliberate choice with rationale → "decisions"; if it represents conditional branching logic (IF-THEN) → "rules".
222575
222663
  Decision schema: ${decisionFields}
222576
222664
 
222577
222665
  ### Sequence → entities + relations + behaviors + events
@@ -222604,9 +222692,9 @@ Each diagram paragraph is tagged with [P0], [P1], etc. You must classify the dia
222604
222692
  Relation schema: ${relationFields2}
222605
222693
 
222606
222694
  ### Architecture → entities + relations + constraints
222607
- 1. Extract each system/service/container/component as an entity.
222695
+ 1. Extract each system/service/container/component as an entity. Use kind to indicate origin: "implementation" for internal systems/services, "external" for third-party dependencies (databases, cloud services, external APIs).
222608
222696
  Entity schema: ${entityFields2}
222609
- 2. Extract connections between components as relations.
222697
+ 2. Extract connections between components as relations. Use standard types: CONTAINS (parent→child), DEPENDS_ON (runtime dependency), TRIGGERS (event/process triggering).
222610
222698
  Relation schema: ${relationFields2}
222611
222699
  3. Extract deployment constraints, technology choices.
222612
222700
  Constraint schema: ${constraintFields2}
@@ -222668,7 +222756,7 @@ Return ONLY a valid JSON object. No markdown fences, no explanation.`;
222668
222756
  }
222669
222757
  var DOC_DIAGRAM_ANNOTATION_SYSTEM_PROMPT = DIAGRAM_SYSTEM_PROMPT;
222670
222758
  // ../llm/src/chunking/markdownChunker.ts
222671
- var DEFAULT_MAX_TOKENS2 = 4000;
222759
+ var DEFAULT_MAX_TOKENS2 = 3600;
222672
222760
  var DEFAULT_PARAGRAPH_MAX_TOKENS = 500;
222673
222761
  function estimateTokens(text2) {
222674
222762
  return Math.ceil(text2.length / 4);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@c4a/server-cli",
3
- "version": "0.4.15-alpha.5",
3
+ "version": "0.4.15-alpha.7",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "c4a-server": "./index.js"
package/serve.js CHANGED
@@ -194996,6 +194996,12 @@ class LlmServiceImpl {
194996
194996
  if (options?.systemPrompt) {
194997
194997
  callSettings.system = options.systemPrompt;
194998
194998
  }
194999
+ if (options?.jsonMode) {
195000
+ callSettings.providerOptions = {
195001
+ openai: { responseFormat: { type: "json_object" } },
195002
+ anthropic: { responseFormat: { type: "json_object" } }
195003
+ };
195004
+ }
194999
195005
  const result = await retry(() => generateText(callSettings), {
195000
195006
  shouldRetry: (error40) => isRetryableStatus(getHttpStatus(error40)) || isTimeoutError2(error40)
195001
195007
  });
@@ -195043,6 +195049,12 @@ class LlmServiceImpl {
195043
195049
  if (options?.systemPrompt) {
195044
195050
  callSettings.system = options.systemPrompt;
195045
195051
  }
195052
+ if (options?.jsonMode) {
195053
+ callSettings.providerOptions = {
195054
+ openai: { responseFormat: { type: "json_object" } },
195055
+ anthropic: { responseFormat: { type: "json_object" } }
195056
+ };
195057
+ }
195046
195058
  const result = await retry(() => Promise.resolve(streamText(callSettings)), {
195047
195059
  shouldRetry: (error40) => isRetryableStatus(getHttpStatus(error40)) || isTimeoutError2(error40)
195048
195060
  });
@@ -195861,6 +195873,7 @@ function parseExtractionOutput(raw5, schema2) {
195861
195873
  }
195862
195874
  parsed = normalizeFlatOutput(parsed);
195863
195875
  parsed = stripNulls(parsed);
195876
+ parsed = patchAttributeDefaults(parsed);
195864
195877
  const result = schema2.safeParse(parsed);
195865
195878
  if (!result.success) {
195866
195879
  return { success: false, error: result.error };
@@ -195928,7 +195941,37 @@ function tryParseJson(raw5) {
195928
195941
  return repairAndParse(raw5);
195929
195942
  }
195930
195943
  function repairAndParse(raw5) {
195931
- return JSON.parse(jsonrepair(raw5));
195944
+ try {
195945
+ return JSON.parse(jsonrepair(raw5));
195946
+ } catch {
195947
+ const truncated = truncateToLastCompleteEntry(raw5);
195948
+ if (truncated) {
195949
+ return JSON.parse(jsonrepair(truncated));
195950
+ }
195951
+ throw new Error(`JSON repair failed for output of length ${raw5.length}`);
195952
+ }
195953
+ }
195954
+ function truncateToLastCompleteEntry(raw5) {
195955
+ let text2 = raw5.trim();
195956
+ if (text2.startsWith("```")) {
195957
+ const firstNewline = text2.indexOf(`
195958
+ `);
195959
+ text2 = text2.slice(firstNewline + 1);
195960
+ }
195961
+ if (text2.endsWith("```")) {
195962
+ text2 = text2.slice(0, -3);
195963
+ }
195964
+ const pattern = /\}\s*,\s*"P\d+"/g;
195965
+ let lastMatch = null;
195966
+ let m;
195967
+ while ((m = pattern.exec(text2)) !== null) {
195968
+ lastMatch = m;
195969
+ }
195970
+ if (!lastMatch)
195971
+ return null;
195972
+ const cutPos = lastMatch.index + 1;
195973
+ const truncated = text2.slice(0, cutPos) + "}";
195974
+ return truncated;
195932
195975
  }
195933
195976
  var PARAGRAPH_TAG_RE = /^P\d+$/;
195934
195977
  function normalizeFlatOutput(parsed) {
@@ -195961,6 +196004,43 @@ function stripNulls(value) {
195961
196004
  }
195962
196005
  return value;
195963
196006
  }
196007
+ function patchAttributeDefaults(value) {
196008
+ if (!value || typeof value !== "object" || Array.isArray(value))
196009
+ return value;
196010
+ const obj = value;
196011
+ if ("paragraphs" in obj && Array.isArray(obj.paragraphs)) {
196012
+ return {
196013
+ ...obj,
196014
+ paragraphs: obj.paragraphs.map((p4) => {
196015
+ if (!p4 || typeof p4 !== "object")
196016
+ return p4;
196017
+ const para = p4;
196018
+ const atoms2 = para.atoms;
196019
+ if (!atoms2 || typeof atoms2 !== "object")
196020
+ return p4;
196021
+ return { ...para, atoms: patchAttrsInAtoms(atoms2) };
196022
+ })
196023
+ };
196024
+ }
196025
+ return value;
196026
+ }
196027
+ function patchAttrsInAtoms(atoms2) {
196028
+ const attrs = atoms2.attributes;
196029
+ if (!Array.isArray(attrs))
196030
+ return atoms2;
196031
+ return {
196032
+ ...atoms2,
196033
+ attributes: attrs.map((attr) => {
196034
+ if (!attr || typeof attr !== "object" || Array.isArray(attr))
196035
+ return attr;
196036
+ const a = attr;
196037
+ if (typeof a.type !== "string" || a.type === "") {
196038
+ return { ...a, type: "other" };
196039
+ }
196040
+ return attr;
196041
+ })
196042
+ };
196043
+ }
195964
196044
  function isRecord(value) {
195965
196045
  return !!value && typeof value === "object" && "key" in value && "value" in value && typeof value.key === "string";
195966
196046
  }
@@ -196217,20 +196297,20 @@ class GleaningExtractor {
196217
196297
  // ../llm/src/prompts/docAtomAnnotation.ts
196218
196298
  init_src();
196219
196299
  var DOC_ATOM_DEFS = [
196220
- ["entities", "Named things: systems, services, modules, documents, APIs (NOT people/teams — use roles for those)", entityAtomSchema],
196300
+ ["entities", "Named things with independent identity — something you can ask questions about ('What does X do?', 'Who owns X?'). Examples: systems, services, modules, APIs, products. If it is a value, address, path, or configuration detail, it is an attribute of an entity, not an entity itself. (NOT people/teams — use roles for those). kind: implementation=internal systems/services, external=third-party dependencies, concept=abstract/not-yet-implemented", entityAtomSchema],
196221
196301
  ["relations", "Connections between entities", relationAtomSchema],
196222
196302
  ["behaviors", "Actions/operations: functions, API calls, user actions, workflows", behaviorAtomSchema],
196223
196303
  ["attributes", "Properties of entities", attributeAtomSchema],
196224
196304
  ["states", "Possible states of entities", stateAtomSchema],
196225
- ["rules", "Business/domain rules: validations, constraints expressed as logic", ruleAtomSchema],
196305
+ ["rules", "Conditional business/domain logic: IF condition THEN consequence (e.g., 'IF user not authenticated THEN reject request')", ruleAtomSchema],
196226
196306
  ["transitions", "State changes: from→to triggered by events or guards", transitionAtomSchema],
196227
196307
  ["events", "Occurrences that trigger behaviors", eventAtomSchema],
196228
196308
  ["decisions", "Architectural or business decisions", decisionAtomSchema],
196229
196309
  ["metrics", "Measurable targets: SLA, throughput, error_rate, with thresholds", metricAtomSchema],
196230
- ["roles", "Actors: human roles, teams, personas that perform behaviors", roleAtomSchema],
196231
- ["constraints", "Hard/soft requirements", constraintAtomSchema],
196310
+ ["roles", "Actors: human roles, teams, personas that perform behaviors. kind: human=individual role, team=group/department, persona=user archetype. System-triggered actions use entity relations, NOT roles", roleAtomSchema],
196311
+ ["constraints", "Declarative requirements: 'X must/should/must-not Y' (e.g., 'passwords must be >= 8 chars'). Unlike rules, constraints have no IF-THEN condition — they are unconditional mandates or restrictions", constraintAtomSchema],
196232
196312
  ["comparisons", "Side-by-side evaluations", comparisonAtomSchema],
196233
- ["boundaries", "System/domain boundaries: what is included vs excluded", boundaryAtomSchema]
196313
+ ["boundaries", "Explicit scope declarations: what is included vs excluded. Only extract when the text explicitly declares scope (e.g., 'this product covers X but NOT Y'). Implicit containment (A runs inside B) is expressed via entity relations, not boundaries", boundaryAtomSchema]
196234
196314
  ];
196235
196315
  function buildAtomTypesBlock() {
196236
196316
  return DOC_ATOM_DEFS.map(([name21, desc, schema2], i) => {
@@ -196260,7 +196340,8 @@ Return a single JSON object keyed by paragraph tags. Only include paragraphs tha
196260
196340
  "relations": [{ "from": "UserService", "to": "Database", "type": "DEPENDS_ON", "confidence": 0.9 }]
196261
196341
  },
196262
196342
  "P3": {
196263
- "rules": [{ "description": "User must be authenticated before access", "expression": "user.isAuthenticated == true", "confidence": 0.85 }]
196343
+ "constraints": [{ "description": "User must be authenticated before access", "severity": "must", "confidence": 0.9 }],
196344
+ "rules": [{ "description": "Reject request if user is not authenticated", "expression": "IF !user.isAuthenticated THEN reject", "confidence": 0.85 }]
196264
196345
  }
196265
196346
  }
196266
196347
 
@@ -196272,7 +196353,13 @@ Return a single JSON object keyed by paragraph tags. Only include paragraphs tha
196272
196353
  - **Enum fields MUST use ONLY the listed values.** For example, entity.kind must be one of "implementation"|"external"|"concept" — do NOT use values from other atom types (e.g., do NOT put "team" or "human" in entity.kind; those belong to roles.kind).
196273
196354
  - Every atom MUST include a "confidence" field (0.0-1.0) indicating how confident you are in the extraction. Use higher values (0.85-1.0) for explicitly stated facts and lower values (0.5-0.7) for inferred or ambiguous information.
196274
196355
  - **Classify correctly:** People, teams, and personas → "roles" (not "entities"). Technical systems, services, modules → "entities".
196356
+ - **Entity naming — extract the subject, not the document:** Entity names should represent the actual system/product/framework being described, not the document itself. If the text says "Next.js is a React framework", the entity is "Next.js" — not "Next.js 官方文档" or "Next.js API 参考". Use names that work as standalone knowledge graph nodes, independent of any document context.
196275
196357
  - **Entity reference consistency (CRITICAL):** Every entity name referenced in relation.from, relation.to, behavior.subject, or any other cross-reference field MUST also appear in the "entities" array of the SAME paragraph (or a preceding paragraph in the same chunk). If an entity is mentioned for the first time in a relation, you MUST also extract it as an entity. This ensures no "dangling references" — every name used in relations has a corresponding entity declaration.
196358
+ - **Cross-atom reference consistency:** transitions[].from and transitions[].to values MUST exist in states[].values of the same entity. roles[].performs values MUST match names declared in behaviors[].name.
196359
+ - **Constraints vs rules distinction:** Use "constraints" for unconditional declarative mandates ('X must Y'). Use "rules" for conditional logic ('IF X THEN Y'). Do not mix them — a requirement with no condition is a constraint, a requirement triggered by a condition is a rule. Do NOT invent a rule for every constraint — only create a rule when the text explicitly states conditional logic.
196360
+ - **One statement, multiple atoms:** A single sentence can produce several atom types simultaneously. Do NOT force a choice — extract all that apply. Example: "system uptime must be ≥ 99.9%" → constraint (severity: must) + metric (threshold: "≥ 99.9%").
196361
+ - **Relation types:** Use standard relation types when possible: CONTAINS (parent→child composition), DEPENDS_ON (runtime dependency), IMPLEMENTS (code/component→spec realization), PRODUCES (process→output), TRIGGERS (event/process triggering), REFERENCES (weak cross-reference). Only invent a new type when none of these fit.
196362
+ - **Decisions:** Extract as "decisions" when the text records a deliberate choice between alternatives with rationale (e.g., "we chose X because Y", "after evaluating A/B/C, selected B"). Do not extract routine descriptions as decisions.
196276
196363
  - Respond in the same language as the input text (e.g., Chinese input → Chinese descriptions, English input → English descriptions).
196277
196364
  - JSON structure keys (tag, atom type names, field names) must always be in English.
196278
196365
  - Be thorough: extract ALL relevant atoms from each paragraph.
@@ -196326,14 +196413,15 @@ var ENTITY_RESOLUTION_SYSTEM_PROMPT = `You are an entity resolution assistant. Y
196326
196413
  - Prefer the LONGER, more descriptive name as the canonical name
196327
196414
  - Do NOT merge names that share a substring but refer to different things
196328
196415
  - When uncertain, do NOT merge — add to "ambiguous" instead
196329
- - Chinese and English names for the same entity SHOULD be merged (e.g. "Vmok" → "Vmok 微模块框架")
196330
- - Abbreviations should be merged with their full forms (e.g. "AGW" → "API Gateway")
196416
+ - Chinese and English names for the same entity SHOULD be merged (e.g. "Webpack" → "Webpack 打包工具")
196417
+ - Abbreviations should be merged with their full forms (e.g. "K8s" → "Kubernetes")
196418
+ - Document-descriptive names (containing "文档", "参考", "指南" etc.) should be merged to the actual product/system name. The entity is the product, not the document about it
196331
196419
 
196332
196420
  ## Task 2: Remove Noise
196333
- - Remove names that are NOT meaningful named entities they are generic words, actions, or descriptions
196334
- - Examples of noise: common verbs/nouns (登录, 路由, 直连), generic technical terms (Env, query), action descriptions (Kill 3001 进程)
196335
- - Examples of REAL entities to KEEP: product names (TTAstra, Gulux), tools (nvm, Rush), services (Op Main 服务), platforms (AGW 平台)
196336
- - When uncertain, KEEP the name — only remove if clearly not a named entity
196421
+ - Apply the **identity test**: a real entity is something you can discuss independently ("What is X?", "How does X work?", "Who owns X?"). Names that fail this test — values, addresses, actions, generic descriptions — are noise.
196422
+ - Remove names that are NOT meaningful named entities: generic words, action descriptions, or things that are attributes/values rather than independent subjects
196423
+ - Examples of REAL entities to KEEP: product names (Next.js, Vite), tools (nvm, Turborepo), services (Nginx, Redis), platforms (Kubernetes, Docker) — these all pass the identity test
196424
+ - When uncertain, KEEP the name — only remove if it clearly fails the identity test
196337
196425
 
196338
196426
  ## Output
196339
196427
  Valid JSON only. No markdown fences, no explanation.`;
@@ -196576,7 +196664,7 @@ Each diagram paragraph is tagged with [P0], [P1], etc. You must classify the dia
196576
196664
  Relation schema: ${relationFields2}
196577
196665
  3. Extract action nodes as behaviors (what the process does at each step).
196578
196666
  Behavior schema: ${behaviorFields2}
196579
- 4. Extract diamond/decision nodes as decisions.
196667
+ 4. Extract diamond/condition nodes: if it represents a deliberate choice with rationale → "decisions"; if it represents conditional branching logic (IF-THEN) → "rules".
196580
196668
  Decision schema: ${decisionFields}
196581
196669
 
196582
196670
  ### Sequence → entities + relations + behaviors + events
@@ -196609,9 +196697,9 @@ Each diagram paragraph is tagged with [P0], [P1], etc. You must classify the dia
196609
196697
  Relation schema: ${relationFields2}
196610
196698
 
196611
196699
  ### Architecture → entities + relations + constraints
196612
- 1. Extract each system/service/container/component as an entity.
196700
+ 1. Extract each system/service/container/component as an entity. Use kind to indicate origin: "implementation" for internal systems/services, "external" for third-party dependencies (databases, cloud services, external APIs).
196613
196701
  Entity schema: ${entityFields2}
196614
- 2. Extract connections between components as relations.
196702
+ 2. Extract connections between components as relations. Use standard types: CONTAINS (parent→child), DEPENDS_ON (runtime dependency), TRIGGERS (event/process triggering).
196615
196703
  Relation schema: ${relationFields2}
196616
196704
  3. Extract deployment constraints, technology choices.
196617
196705
  Constraint schema: ${constraintFields2}
@@ -196673,7 +196761,7 @@ Return ONLY a valid JSON object. No markdown fences, no explanation.`;
196673
196761
  }
196674
196762
  var DOC_DIAGRAM_ANNOTATION_SYSTEM_PROMPT = DIAGRAM_SYSTEM_PROMPT;
196675
196763
  // ../llm/src/chunking/markdownChunker.ts
196676
- var DEFAULT_MAX_TOKENS2 = 4000;
196764
+ var DEFAULT_MAX_TOKENS2 = 3600;
196677
196765
  var DEFAULT_PARAGRAPH_MAX_TOKENS = 500;
196678
196766
  function estimateTokens(text2) {
196679
196767
  return Math.ceil(text2.length / 4);
@@ -197598,7 +197686,8 @@ async function extractTableAtoms(chunk, sections, result, llmService) {
197598
197686
  const prompt = buildDocTableAnnotationPrompt(tableText);
197599
197687
  try {
197600
197688
  const res = await llmService.generateText(prompt, {
197601
- systemPrompt: DOC_TABLE_ANNOTATION_SYSTEM_PROMPT
197689
+ systemPrompt: DOC_TABLE_ANNOTATION_SYSTEM_PROMPT,
197690
+ jsonMode: true
197602
197691
  });
197603
197692
  const parsed = parseExtractionOutput(res.text, docChunkResultSchema);
197604
197693
  if (!parsed.success) {
@@ -197690,7 +197779,8 @@ async function extractDiagramAtoms(chunk, sections, result, llmService) {
197690
197779
  const prompt = buildDocDiagramAnnotationPrompt(diagramText);
197691
197780
  try {
197692
197781
  const res = await llmService.generateText(prompt, {
197693
- systemPrompt: DOC_DIAGRAM_ANNOTATION_SYSTEM_PROMPT
197782
+ systemPrompt: DOC_DIAGRAM_ANNOTATION_SYSTEM_PROMPT,
197783
+ jsonMode: true
197694
197784
  });
197695
197785
  const parsed = parseExtractionOutput(res.text, docChunkResultSchema);
197696
197786
  if (!parsed.success) {
@@ -198208,7 +198298,9 @@ ${trimmed}
198208
198298
  Continue the JSON output from the exact point of truncation. Output ONLY the remaining JSON text.`;
198209
198299
  try {
198210
198300
  const result = await llmService.generateText(continuationPrompt, {
198211
- systemPrompt: DOC_ANNOTATION_SYSTEM_PROMPT
198301
+ systemPrompt: DOC_ANNOTATION_SYSTEM_PROMPT,
198302
+ jsonMode: true,
198303
+ maxTokens: 16384
198212
198304
  });
198213
198305
  const combined = trimmed + result.text.trim();
198214
198306
  JSON.parse(jsonrepair(combined));
@@ -198250,9 +198342,12 @@ async function processChunk(chunk, chunkIndex, llmService, sections, onStep) {
198250
198342
  const chunkText = injectParagraphTags(chunk, sections);
198251
198343
  let llmCalls = 0;
198252
198344
  let totalTokens = 0;
198345
+ const DOC_INDEX_MAX_OUTPUT_TOKENS = 16384;
198253
198346
  const t1Prompt = buildDocAtomAnnotationPrompt(chunkText);
198254
198347
  const t1Result = await llmService.generateText(t1Prompt, {
198255
- systemPrompt: DOC_ANNOTATION_SYSTEM_PROMPT
198348
+ systemPrompt: DOC_ANNOTATION_SYSTEM_PROMPT,
198349
+ jsonMode: true,
198350
+ maxTokens: DOC_INDEX_MAX_OUTPUT_TOKENS
198256
198351
  });
198257
198352
  llmCalls++;
198258
198353
  totalTokens += t1Result.usage.totalTokens;
@@ -198262,8 +198357,17 @@ async function processChunk(chunk, chunkIndex, llmService, sections, onStep) {
198262
198357
  onStep?.("T1 done", llmCalls, totalTokens);
198263
198358
  let parseResult = parseExtractionOutput(continued.text, docChunkResultSchema);
198264
198359
  if (!parseResult.success) {
198360
+ const rawLen = continued.text.length;
198265
198361
  const preview = continued.text.slice(0, 500).replace(/\n/g, "\\n");
198266
- console.warn(`[docIndexer] chunk ${chunkIndex} T1 strict parse failed, attempting lenient. ` + `Error: ${parseResult.error.message.slice(0, 200)}. ` + `LLM output preview: ${preview}`);
198362
+ const errMsg = parseResult.error.message.slice(0, 300);
198363
+ const posMatch = errMsg.match(/position\s+(\d+)/);
198364
+ const errContext = posMatch ? continued.text.slice(Math.max(0, +posMatch[1] - 100), +posMatch[1] + 100).replace(/\n/g, "\\n") : "";
198365
+ console.warn(`[docIndexer] chunk ${chunkIndex} T1 strict parse failed, attempting lenient.
198366
+ ` + ` Error: ${errMsg}
198367
+ ` + ` Output length: ${rawLen} chars | finishReason: ${t1Result.finishReason}
198368
+ ` + ` Preview (first 500): ${preview}
198369
+ ` + (errContext ? ` Context around error position: ...${errContext}...
198370
+ ` : ""));
198267
198371
  const lenient = tryLenientParse(continued.text, chunkIndex);
198268
198372
  if (lenient) {
198269
198373
  parseResult = { success: true, data: lenient };
@@ -198282,7 +198386,8 @@ async function processChunk(chunk, chunkIndex, llmService, sections, onStep) {
198282
198386
  extract: async (input) => {
198283
198387
  const prompt = buildDocGleaningPrompt(input.chunkText, input.previousResult);
198284
198388
  const result = await llmService.generateText(prompt, {
198285
- systemPrompt: DOC_ANNOTATION_SYSTEM_PROMPT
198389
+ systemPrompt: DOC_ANNOTATION_SYSTEM_PROMPT,
198390
+ jsonMode: true
198286
198391
  });
198287
198392
  llmCalls++;
198288
198393
  totalTokens += result.usage.totalTokens;
@@ -198512,6 +198617,17 @@ function ensureAtomConfidence(atoms2) {
198512
198617
  }
198513
198618
  }
198514
198619
  }
198620
+ function sortAtomsByConfidence(sections) {
198621
+ for (const section of sections) {
198622
+ for (const para of section.paragraphs) {
198623
+ for (const atomList of Object.values(para.atoms)) {
198624
+ if (!Array.isArray(atomList) || atomList.length < 2)
198625
+ continue;
198626
+ atomList.sort((a, b) => (b.confidence ?? 0) - (a.confidence ?? 0));
198627
+ }
198628
+ }
198629
+ }
198630
+ }
198515
198631
  function countAtoms(sections) {
198516
198632
  const counts = {};
198517
198633
  for (const section of sections.values()) {
@@ -198548,7 +198664,8 @@ async function runEntityResolution(sections, entityNames, llmService, onProgress
198548
198664
  ...noiseCandidates.length > 0 ? { noiseCandidates } : {}
198549
198665
  });
198550
198666
  const result = await llmService.generateText(prompt, {
198551
- systemPrompt: ENTITY_RESOLUTION_SYSTEM_PROMPT
198667
+ systemPrompt: ENTITY_RESOLUTION_SYSTEM_PROMPT,
198668
+ jsonMode: true
198552
198669
  });
198553
198670
  let resolution;
198554
198671
  try {
@@ -198673,7 +198790,13 @@ async function indexDocument(input) {
198673
198790
  const paragraphs = sortedParaKeys.map((pk) => {
198674
198791
  const p4 = section.paragraphs.get(pk);
198675
198792
  return { text: p4.text, atoms: p4.atoms };
198793
+ }).filter((p4) => {
198794
+ const hasAtoms = Object.values(p4.atoms).some((arr) => Array.isArray(arr) && arr.length > 0);
198795
+ const hasText = p4.text.replace(/[\s\p{P}\p{S}]/gu, "").length > 0;
198796
+ return hasAtoms || hasText;
198676
198797
  });
198798
+ if (paragraphs.length === 0)
198799
+ continue;
198677
198800
  digestSections.push({
198678
198801
  heading: section.heading,
198679
198802
  level: section.level,
@@ -198704,6 +198827,7 @@ async function indexDocument(input) {
198704
198827
  totalLlmCalls += resolutionResult.llmCalls;
198705
198828
  totalTokens += resolutionResult.totalTokens;
198706
198829
  }
198830
+ sortAtomsByConfidence(digestSections);
198707
198831
  const atomCounts = countAtoms(sectionsMap);
198708
198832
  const paragraphCount = digestSections.reduce((sum, s) => sum + s.paragraphs.length, 0);
198709
198833
  if (paragraphCount === 0) {
@@ -0,0 +1 @@
1
+ import{c as o,u as m,a as c,j as e,b as d,C as h}from"./index-BKETuM1m.js";const p=[["path",{d:"m12 19-7-7 7-7",key:"1l729n"}],["path",{d:"M19 12H5",key:"x3x0zl"}]],f=o("arrow-left",p);function j({icon:a,title:t,badges:s,meta:l}){const i=m(),{t:r}=c();return e.jsxs("div",{children:[e.jsxs("div",{className:"flex justify-between items-center",children:[e.jsxs("div",{className:"flex min-w-0 items-center gap-2",children:[e.jsx("span",{className:"shrink-0",children:a}),e.jsx("h1",{className:"min-w-0 break-all font-mono text-xl font-bold leading-none text-c4a-text-primary",children:t}),s&&s.length>0&&e.jsx("div",{className:"flex items-center gap-1.5 ml-2",children:s.map((n,x)=>e.jsx("span",{children:n},x))})]}),e.jsxs("button",{onClick:()=>i(-1),className:"flex items-center gap-1 text-c4a-text-muted hover:text-c4a-text-primary cursor-pointer transition-colors text-xs font-mono shrink-0 ml-4",children:[e.jsx(f,{size:14}),r("common.back")]})]}),l&&l.length>0&&e.jsx("div",{className:"mt-2 flex flex-wrap items-baseline gap-4 text-xs",children:l.map(n=>e.jsxs("span",{className:"text-c4a-text-muted",children:[n.label,":",e.jsx("span",{className:"text-c4a-text-secondary",children:n.value})]},n.label))})]})}function N(){const{t:a}=c(),{hashId:t}=d();if(!t)return e.jsx("div",{className:"flex flex-1 items-center justify-center p-8",children:e.jsx("p",{className:"text-sm text-c4a-text-muted",children:a("common.loading")})});const s=t.length>16?t.slice(0,16)+"…":t;return e.jsxs("div",{className:"flex flex-1 flex-col p-4 md:p-6",children:[e.jsx(j,{icon:e.jsx("span",{children:"📄"}),title:`Content: ${s}`}),e.jsx(h,{hashId:t})]})}export{N as ContentDetail};
@@ -0,0 +1 @@
1
+ import{c as o,u as m,a as c,j as e,b as d,C as h}from"./index-wBO4P6CB.js";const p=[["path",{d:"m12 19-7-7 7-7",key:"1l729n"}],["path",{d:"M19 12H5",key:"x3x0zl"}]],f=o("arrow-left",p);function j({icon:a,title:t,badges:s,meta:l}){const i=m(),{t:r}=c();return e.jsxs("div",{children:[e.jsxs("div",{className:"flex justify-between items-center",children:[e.jsxs("div",{className:"flex min-w-0 items-center gap-2",children:[e.jsx("span",{className:"shrink-0",children:a}),e.jsx("h1",{className:"min-w-0 break-all font-mono text-xl font-bold leading-none text-c4a-text-primary",children:t}),s&&s.length>0&&e.jsx("div",{className:"flex items-center gap-1.5 ml-2",children:s.map((n,x)=>e.jsx("span",{children:n},x))})]}),e.jsxs("button",{onClick:()=>i(-1),className:"flex items-center gap-1 text-c4a-text-muted hover:text-c4a-text-primary cursor-pointer transition-colors text-xs font-mono shrink-0 ml-4",children:[e.jsx(f,{size:14}),r("common.back")]})]}),l&&l.length>0&&e.jsx("div",{className:"mt-2 flex flex-wrap items-baseline gap-4 text-xs",children:l.map(n=>e.jsxs("span",{className:"text-c4a-text-muted",children:[n.label,":",e.jsx("span",{className:"text-c4a-text-secondary",children:n.value})]},n.label))})]})}function N(){const{t:a}=c(),{hashId:t}=d();if(!t)return e.jsx("div",{className:"flex flex-1 items-center justify-center p-8",children:e.jsx("p",{className:"text-sm text-c4a-text-muted",children:a("common.loading")})});const s=t.length>16?t.slice(0,16)+"…":t;return e.jsxs("div",{className:"flex flex-1 flex-col p-4 md:p-6",children:[e.jsx(j,{icon:e.jsx("span",{children:"📄"}),title:`Content: ${s}`}),e.jsx(h,{hashId:t})]})}export{N as ContentDetail};
@@ -0,0 +1 @@
1
+ import{c as o,u as m,a as c,j as e,b as d,C as h}from"./index-CMVd9rlp.js";const p=[["path",{d:"m12 19-7-7 7-7",key:"1l729n"}],["path",{d:"M19 12H5",key:"x3x0zl"}]],f=o("arrow-left",p);function j({icon:a,title:t,badges:s,meta:l}){const i=m(),{t:r}=c();return e.jsxs("div",{children:[e.jsxs("div",{className:"flex justify-between items-center",children:[e.jsxs("div",{className:"flex min-w-0 items-center gap-2",children:[e.jsx("span",{className:"shrink-0",children:a}),e.jsx("h1",{className:"min-w-0 break-all font-mono text-xl font-bold leading-none text-c4a-text-primary",children:t}),s&&s.length>0&&e.jsx("div",{className:"flex items-center gap-1.5 ml-2",children:s.map((n,x)=>e.jsx("span",{children:n},x))})]}),e.jsxs("button",{onClick:()=>i(-1),className:"flex items-center gap-1 text-c4a-text-muted hover:text-c4a-text-primary cursor-pointer transition-colors text-xs font-mono shrink-0 ml-4",children:[e.jsx(f,{size:14}),r("common.back")]})]}),l&&l.length>0&&e.jsx("div",{className:"mt-2 flex flex-wrap items-baseline gap-4 text-xs",children:l.map(n=>e.jsxs("span",{className:"text-c4a-text-muted",children:[n.label,":",e.jsx("span",{className:"text-c4a-text-secondary",children:n.value})]},n.label))})]})}function N(){const{t:a}=c(),{hashId:t}=d();if(!t)return e.jsx("div",{className:"flex flex-1 items-center justify-center p-8",children:e.jsx("p",{className:"text-sm text-c4a-text-muted",children:a("common.loading")})});const s=t.length>16?t.slice(0,16)+"…":t;return e.jsxs("div",{className:"flex flex-1 flex-col p-4 md:p-6",children:[e.jsx(j,{icon:e.jsx("span",{children:"📄"}),title:`Content: ${s}`}),e.jsx(h,{hashId:t})]})}export{N as ContentDetail};
@@ -0,0 +1 @@
1
+ import{a as n,b as a,j as e,E as i}from"./index-wBO4P6CB.js";function r(){const{t:s}=n(),{entityId:t}=a();return t?e.jsx("div",{className:"flex flex-1 flex-col p-4 md:p-6",children:e.jsx(i,{entityId:t})}):e.jsx("div",{className:"flex flex-1 items-center justify-center p-8",children:e.jsx("p",{className:"text-sm text-c4a-text-muted",children:s("common.loading")})})}export{r as EntityDetail};
@@ -0,0 +1 @@
1
+ import{a as n,b as a,j as e,E as i}from"./index-BKETuM1m.js";function r(){const{t:s}=n(),{entityId:t}=a();return t?e.jsx("div",{className:"flex flex-1 flex-col p-4 md:p-6",children:e.jsx(i,{entityId:t})}):e.jsx("div",{className:"flex flex-1 items-center justify-center p-8",children:e.jsx("p",{className:"text-sm text-c4a-text-muted",children:s("common.loading")})})}export{r as EntityDetail};
@@ -0,0 +1 @@
1
+ import{a as n,b as a,j as e,E as i}from"./index-CMVd9rlp.js";function r(){const{t:s}=n(),{entityId:t}=a();return t?e.jsx("div",{className:"flex flex-1 flex-col p-4 md:p-6",children:e.jsx(i,{entityId:t})}):e.jsx("div",{className:"flex flex-1 items-center justify-center p-8",children:e.jsx("p",{className:"text-sm text-c4a-text-muted",children:s("common.loading")})})}export{r as EntityDetail};
@@ -0,0 +1 @@
1
+ import{a,b as n,j as e,R as l}from"./index-BKETuM1m.js";function r(){const{t:s}=a(),{relationId:t}=n();return t?e.jsx("div",{className:"flex flex-1 flex-col p-4 md:p-6",children:e.jsx(l,{relationId:t})}):e.jsx("div",{className:"flex flex-1 items-center justify-center p-8",children:e.jsx("p",{className:"text-sm text-c4a-text-muted",children:s("common.loading")})})}export{r as RelationDetail};
@@ -0,0 +1 @@
1
+ import{a,b as n,j as e,R as l}from"./index-CMVd9rlp.js";function r(){const{t:s}=a(),{relationId:t}=n();return t?e.jsx("div",{className:"flex flex-1 flex-col p-4 md:p-6",children:e.jsx(l,{relationId:t})}):e.jsx("div",{className:"flex flex-1 items-center justify-center p-8",children:e.jsx("p",{className:"text-sm text-c4a-text-muted",children:s("common.loading")})})}export{r as RelationDetail};
@@ -0,0 +1 @@
1
+ import{a,b as n,j as e,R as l}from"./index-wBO4P6CB.js";function r(){const{t:s}=a(),{relationId:t}=n();return t?e.jsx("div",{className:"flex flex-1 flex-col p-4 md:p-6",children:e.jsx(l,{relationId:t})}):e.jsx("div",{className:"flex flex-1 items-center justify-center p-8",children:e.jsx("p",{className:"text-sm text-c4a-text-muted",children:s("common.loading")})})}export{r as RelationDetail};