product-spec-mcp 0.3.21 → 0.3.26
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/README.md +14 -0
- package/dist/index.cjs +1325 -29
- package/docs/online-pm-gate.md +58 -0
- package/package.json +6 -2
- package/workers/pm-intent-gate.mjs +383 -0
- package/workers/schema.sql +24 -0
- package/workers/wrangler.toml.example +19 -0
package/dist/index.cjs
CHANGED
|
@@ -22982,15 +22982,21 @@ ${formatInterrogateResult(readiness, clarification)}`;
|
|
|
22982
22982
|
}
|
|
22983
22983
|
if (!spec) return "# \u9519\u8BEF\uFF1A\u65E0\u6CD5\u751F\u6210\u89C4\u683C";
|
|
22984
22984
|
if (mode === "draft") {
|
|
22985
|
-
|
|
22985
|
+
const localFirstDraft = spec.technicalProfile?.frontendOnly === true && spec.technicalProfile?.needsBackend === false;
|
|
22986
|
+
let md2 = localFirstDraft ? `# MVP \u4EA7\u54C1\u89C4\u683C\u8349\u6848
|
|
22987
|
+
|
|
22988
|
+
> \u4EE5\u4E0B\u5185\u5BB9\u5DF2\u6309\u5C0F\u767D\u672C\u5730\u5DE5\u5177\u9ED8\u8BA4\u503C\u751F\u6210\uFF0C\u53EF\u4F5C\u4E3A MVP \u5F00\u5DE5\u8349\u6848\uFF1B\u5982\u7528\u6237\u6CA1\u6709\u8865\u5145\u591A\u4EBA\u540C\u6B65\u3001\u767B\u5F55\u3001\u652F\u4ED8\u3001AI Key \u7B49\u5F3A\u4FE1\u53F7\uFF0C\u4E0D\u8981\u5347\u7EA7\u5230\u91CD\u540E\u7AEF\u67B6\u6784\u3002
|
|
22989
|
+
` : `# \u4EA7\u54C1\u89C4\u683C\u8349\u6848
|
|
22986
22990
|
|
|
22987
22991
|
> \u26A0\uFE0F **\u6CE8\u610F\uFF1A** \u4EE5\u4E0B\u5185\u5BB9\u57FA\u4E8E\u9ED8\u8BA4\u5047\u8BBE\u751F\u6210\uFF0C**\u4E0D\u53EF\u76F4\u63A5\u7528\u4E8E\u5F00\u53D1**\uFF0C\u9700\u8981\u7528\u6237\u786E\u8BA4\u3002
|
|
22992
|
+
`;
|
|
22993
|
+
md2 += `
|
|
22988
22994
|
|
|
22989
22995
|
## \u9700\u6C42\u5B8C\u6574\u5EA6
|
|
22990
22996
|
|
|
22991
22997
|
- **Score:** ${readiness.score} / 100
|
|
22992
22998
|
- **\u72B6\u6001:** ${readiness.status}
|
|
22993
|
-
- **\u662F\u5426\u53EF\u6267\u884C:** \u5426\uFF08\u9700\u8981\u7528\u6237\u786E\u8BA4\u5047\u8BBE\uFF09
|
|
22999
|
+
- **\u662F\u5426\u53EF\u6267\u884C:** ${localFirstDraft ? "MVP \u8349\u6848\u53EF\u6267\u884C\uFF08\u9ED8\u8BA4\u5047\u8BBE\u9700\u786E\u8BA4\uFF09" : "\u5426\uFF08\u9700\u8981\u7528\u6237\u786E\u8BA4\u5047\u8BBE\uFF09"}
|
|
22994
23000
|
|
|
22995
23001
|
## \u9700\u6C42\u6458\u8981
|
|
22996
23002
|
|
|
@@ -23003,6 +23009,20 @@ ${formatTechnicalProfileSection(spec.technicalProfile)}
|
|
|
23003
23009
|
|
|
23004
23010
|
${spec.coreFeatures.map((f) => `- ${f}`).join("\n")}
|
|
23005
23011
|
|
|
23012
|
+
## \u67B6\u6784\u5EFA\u8BAE
|
|
23013
|
+
|
|
23014
|
+
${spec.architecture}
|
|
23015
|
+
|
|
23016
|
+
## \u6570\u636E\u65B9\u6848
|
|
23017
|
+
|
|
23018
|
+
${spec.dataModel}
|
|
23019
|
+
|
|
23020
|
+
## API \u8BBE\u8BA1
|
|
23021
|
+
|
|
23022
|
+
\`\`\`
|
|
23023
|
+
${spec.apiDesign}
|
|
23024
|
+
\`\`\`
|
|
23025
|
+
|
|
23006
23026
|
## \u9ED8\u8BA4\u5047\u8BBE\uFF08\u9700\u8981\u7528\u6237\u786E\u8BA4\uFF09
|
|
23007
23027
|
|
|
23008
23028
|
${spec.assumptions.length > 0 ? spec.assumptions.map((a) => `- \u26A0\uFE0F ${a}`).join("\n") : "- \u65E0\u9ED8\u8BA4\u5047\u8BBE"}
|
|
@@ -23011,9 +23031,17 @@ ${spec.assumptions.length > 0 ? spec.assumptions.map((a) => `- \u26A0\uFE0F ${a}
|
|
|
23011
23031
|
|
|
23012
23032
|
${spec.riskBoundaries.length > 0 ? spec.riskBoundaries.map((r) => `- \u26A0\uFE0F ${r}`).join("\n") : "- \u65E0\u7279\u6B8A\u98CE\u9669"}
|
|
23013
23033
|
|
|
23034
|
+
## \u6682\u4E0D\u5305\u542B
|
|
23035
|
+
|
|
23036
|
+
${spec.nonGoals.map((g) => `- ${g}`).join("\n")}
|
|
23037
|
+
|
|
23038
|
+
## \u9A8C\u6536\u6807\u51C6
|
|
23039
|
+
|
|
23040
|
+
${spec.successCriteria.map((c) => `- ${c}`).join("\n")}
|
|
23041
|
+
|
|
23014
23042
|
## \u4E0B\u4E00\u6B65
|
|
23015
23043
|
|
|
23016
|
-
\u8BF7\u5148\u8865\u5145\u4E0A\u8FF0\u7F3A\u5931\u4FE1\u606F\uFF0C\u6216\u660E\u786E\u63A5\u53D7\u9ED8\u8BA4\u5047\u8BBE\u540E\u518D\u751F\u6210\u6B63\u5F0F\u5F00\u53D1 Prompt\u3002
|
|
23044
|
+
${localFirstDraft ? "\u786E\u8BA4\u9ED8\u8BA4\u5047\u8BBE\u540E\u5373\u53EF\u6309\u8BE5 MVP \u8349\u6848\u5B9E\u73B0\uFF1B\u5982\u679C\u7528\u6237\u63D0\u51FA\u591A\u4EBA\u591A\u8BBE\u5907\u540C\u6B65\u3001\u90AE\u4EF6\u901A\u77E5\u3001\u767B\u5F55\u6743\u9650\u7B49\uFF0C\u518D\u91CD\u65B0\u8BC4\u4F30\u6280\u672F\u5F62\u6001\u3002" : "\u8BF7\u5148\u8865\u5145\u4E0A\u8FF0\u7F3A\u5931\u4FE1\u606F\uFF0C\u6216\u660E\u786E\u63A5\u53D7\u9ED8\u8BA4\u5047\u8BBE\u540E\u518D\u751F\u6210\u6B63\u5F0F\u5F00\u53D1 Prompt\u3002"}
|
|
23017
23045
|
|
|
23018
23046
|
`;
|
|
23019
23047
|
if (confirmation) {
|
|
@@ -23319,6 +23347,7 @@ function buildCompileStructuredOutput(mode, readiness, spec, confirmation, clari
|
|
|
23319
23347
|
},
|
|
23320
23348
|
inputConsumption: spec?.inputConsumption,
|
|
23321
23349
|
technicalProfile: spec?.technicalProfile,
|
|
23350
|
+
pmIntentDecision: spec?.pmIntentDecision,
|
|
23322
23351
|
spec: spec ? {
|
|
23323
23352
|
productGoal: spec.productGoal,
|
|
23324
23353
|
targetUser: spec.targetUser,
|
|
@@ -23332,6 +23361,7 @@ function buildCompileStructuredOutput(mode, readiness, spec, confirmation, clari
|
|
|
23332
23361
|
successCriteria: spec.successCriteria,
|
|
23333
23362
|
assumptions: spec.assumptions,
|
|
23334
23363
|
technicalProfile: spec.technicalProfile,
|
|
23364
|
+
pmIntentDecision: spec.pmIntentDecision,
|
|
23335
23365
|
inputConsumption: spec.inputConsumption
|
|
23336
23366
|
} : void 0,
|
|
23337
23367
|
confirmation: confirmation ? { items: confirmation.items } : void 0,
|
|
@@ -23371,6 +23401,7 @@ function buildAcceptanceStructuredOutput(acceptance) {
|
|
|
23371
23401
|
productType: acceptance.productType,
|
|
23372
23402
|
platform: acceptance.platform,
|
|
23373
23403
|
technicalProfile: acceptance.technicalProfile,
|
|
23404
|
+
pmIntentDecision: acceptance.pmIntentDecision,
|
|
23374
23405
|
categories: acceptance.categories,
|
|
23375
23406
|
definitionOfDone: acceptance.definitionOfDone,
|
|
23376
23407
|
checklist
|
|
@@ -23414,7 +23445,8 @@ function buildArchitectureStructuredOutput(decision) {
|
|
|
23414
23445
|
domain: decision.domain,
|
|
23415
23446
|
mvpSuggestion: decision.mvpSuggestion,
|
|
23416
23447
|
productionSuggestion: decision.productionSuggestion,
|
|
23417
|
-
reasoning: decision.reasoning
|
|
23448
|
+
reasoning: decision.reasoning,
|
|
23449
|
+
pmIntentDecision: decision.pmIntentDecision
|
|
23418
23450
|
},
|
|
23419
23451
|
technicalProfile: decision.technicalProfile,
|
|
23420
23452
|
riskLevel,
|
|
@@ -23490,6 +23522,60 @@ var SpecCompileInputSchema = external_exports.object({
|
|
|
23490
23522
|
min_readiness_score: external_exports.number().optional().default(70).describe("\u6700\u4F4E\u53EF\u63A5\u53D7\u7684 readiness \u5206\u6570")
|
|
23491
23523
|
});
|
|
23492
23524
|
|
|
23525
|
+
// src/schemas/pmIntentDecision.schema.ts
|
|
23526
|
+
var PmIntentDecisionSchema = external_exports.object({
|
|
23527
|
+
needType: external_exports.enum([
|
|
23528
|
+
"static_display",
|
|
23529
|
+
"personal_local_tool",
|
|
23530
|
+
"multi_user_collaboration",
|
|
23531
|
+
"content_marketing_site",
|
|
23532
|
+
"data_visualization_site",
|
|
23533
|
+
"transaction_workflow",
|
|
23534
|
+
"content_knowledge",
|
|
23535
|
+
"ai_automation",
|
|
23536
|
+
"unknown"
|
|
23537
|
+
]),
|
|
23538
|
+
usageScope: external_exports.enum(["self", "fixed_group", "public_audience", "unknown"]),
|
|
23539
|
+
maintenanceMode: external_exports.enum([
|
|
23540
|
+
"agent_assisted",
|
|
23541
|
+
"manual_files",
|
|
23542
|
+
"web_admin",
|
|
23543
|
+
"visitor_submission",
|
|
23544
|
+
"runtime_collaboration",
|
|
23545
|
+
"unknown"
|
|
23546
|
+
]),
|
|
23547
|
+
accessTopology: external_exports.enum(["single_device", "lan_only", "internet_ip", "public_domain", "unknown"]),
|
|
23548
|
+
technicalShape: external_exports.enum([
|
|
23549
|
+
"static_page",
|
|
23550
|
+
"local_storage_tool",
|
|
23551
|
+
"local_json_import_export",
|
|
23552
|
+
"static_json_data_page",
|
|
23553
|
+
"light_backend_json_sqlite",
|
|
23554
|
+
"full_backend_saas",
|
|
23555
|
+
"unknown"
|
|
23556
|
+
]),
|
|
23557
|
+
recommendedDeployment: external_exports.enum([
|
|
23558
|
+
"static_only",
|
|
23559
|
+
"local_browser_only",
|
|
23560
|
+
"static_hosting_with_agent_updates",
|
|
23561
|
+
"local_lan_server_sqlite",
|
|
23562
|
+
"cheap_vps_sqlite_by_ip",
|
|
23563
|
+
"vps_domain_https",
|
|
23564
|
+
"unknown"
|
|
23565
|
+
]),
|
|
23566
|
+
route: external_exports.enum(["spec_compile", "spec_interrogate", "architecture_decide"]),
|
|
23567
|
+
confidence: external_exports.enum(["high", "medium", "low"]),
|
|
23568
|
+
strongSignals: external_exports.array(external_exports.string()),
|
|
23569
|
+
weakSignals: external_exports.array(external_exports.string()),
|
|
23570
|
+
coreObjects: external_exports.array(external_exports.string()),
|
|
23571
|
+
states: external_exports.array(external_exports.string()),
|
|
23572
|
+
actions: external_exports.array(external_exports.string()),
|
|
23573
|
+
mustNotUse: external_exports.array(external_exports.string()),
|
|
23574
|
+
boundaryQuestionIds: external_exports.array(external_exports.string()),
|
|
23575
|
+
defaultAssumptions: external_exports.array(external_exports.string()),
|
|
23576
|
+
source: external_exports.enum(["local_rule", "online_llm", "merged"])
|
|
23577
|
+
});
|
|
23578
|
+
|
|
23493
23579
|
// src/schemas/outputs/specCompile.output.ts
|
|
23494
23580
|
var SpecCompileOutputSchema = external_exports.object({
|
|
23495
23581
|
mode: external_exports.enum(["not_ready", "draft", "formal"]),
|
|
@@ -23504,6 +23590,7 @@ var SpecCompileOutputSchema = external_exports.object({
|
|
|
23504
23590
|
confidence: external_exports.enum(["high", "medium", "low"])
|
|
23505
23591
|
}).optional(),
|
|
23506
23592
|
technicalProfile: TechnicalProfileSchema.optional(),
|
|
23593
|
+
pmIntentDecision: PmIntentDecisionSchema.optional(),
|
|
23507
23594
|
spec: external_exports.object({
|
|
23508
23595
|
productGoal: external_exports.string(),
|
|
23509
23596
|
targetUser: external_exports.string(),
|
|
@@ -23517,6 +23604,7 @@ var SpecCompileOutputSchema = external_exports.object({
|
|
|
23517
23604
|
successCriteria: external_exports.array(external_exports.string()),
|
|
23518
23605
|
assumptions: external_exports.array(external_exports.string()),
|
|
23519
23606
|
technicalProfile: TechnicalProfileSchema.optional(),
|
|
23607
|
+
pmIntentDecision: PmIntentDecisionSchema.optional(),
|
|
23520
23608
|
inputConsumption: external_exports.object({
|
|
23521
23609
|
consumedAnswers: external_exports.array(external_exports.string()),
|
|
23522
23610
|
unusedAnswers: external_exports.array(external_exports.string()),
|
|
@@ -23570,10 +23658,11 @@ function cleanObjectLabel(value) {
|
|
|
23570
23658
|
}
|
|
23571
23659
|
function buildFieldLabels(text, recordObject) {
|
|
23572
23660
|
const labels = [`${recordObject}\u540D`];
|
|
23573
|
-
|
|
23661
|
+
const physicalInventory = /家里有哪些|有哪些|库存|余量|剩余|补货|存放|放在/.test(text);
|
|
23662
|
+
addIf(labels, "\u6570\u91CF/\u5E93\u5B58", physicalInventory || /数量|库存|余量|剩余|补货/.test(text));
|
|
23574
23663
|
addIf(labels, "\u6709\u6548\u671F/\u5230\u671F\u65E5", /有效期|过期|临期|到期|截止|保质期|续费|提醒/.test(text));
|
|
23575
|
-
addIf(labels, "\u5206\u7C7B", /分类|类别|标签|类型/.test(text));
|
|
23576
|
-
addIf(labels, "\u5B58\u653E\u4F4D\u7F6E", /位置|存放|放在|地点|地址/.test(text));
|
|
23664
|
+
addIf(labels, "\u5206\u7C7B", physicalInventory || /分类|类别|标签|类型/.test(text));
|
|
23665
|
+
addIf(labels, "\u5B58\u653E\u4F4D\u7F6E", physicalInventory || /位置|存放|放在|地点|地址/.test(text));
|
|
23577
23666
|
addIf(labels, "\u72B6\u6001", /状态|进度|已完成|未完成|正常|异常/.test(text));
|
|
23578
23667
|
addIf(labels, "\u91D1\u989D/\u4EF7\u683C", /金额|价格|费用|预算|保费/.test(text));
|
|
23579
23668
|
addIf(labels, "\u94FE\u63A5", /链接|网址|URL/i.test(text));
|
|
@@ -23583,10 +23672,11 @@ function buildFieldLabels(text, recordObject) {
|
|
|
23583
23672
|
function buildFeatureHints(text, recordObject) {
|
|
23584
23673
|
const hints = [];
|
|
23585
23674
|
if (/记录|管理|保存|清单|列表/.test(text)) hints.push(`${recordObject}\u8BB0\u5F55\u7BA1\u7406`);
|
|
23675
|
+
if (/记录|管理|保存|清单|列表/.test(text)) hints.push("\u65B0\u589E/\u7F16\u8F91/\u5220\u9664");
|
|
23586
23676
|
if (/新增|添加|编辑|删除|增删改查|CRUD/i.test(text)) hints.push("\u65B0\u589E/\u7F16\u8F91/\u5220\u9664");
|
|
23587
|
-
if (
|
|
23677
|
+
if (/搜索|筛选|分类|标签|查询|家里有哪些|有哪些|清单|列表/.test(text)) hints.push("\u641C\u7D22/\u7B5B\u9009/\u5206\u7C7B");
|
|
23588
23678
|
if (/提醒|到期|过期|临期|快过期|截止|倒计时|保质期|续费/.test(text)) hints.push("\u5230\u671F/\u8FC7\u671F\u63D0\u9192");
|
|
23589
|
-
if (
|
|
23679
|
+
if (/数量|库存|余量|剩余|补货|家里有哪些|有哪些/.test(text)) hints.push("\u6570\u91CF/\u5E93\u5B58\u7BA1\u7406");
|
|
23590
23680
|
if (/高级|好看|美观|视觉|界面|页面|UI|ui|响应式/.test(text)) hints.push("\u9AD8\u7EA7\u754C\u9762\u4E0E\u54CD\u5E94\u5F0F\u5E03\u5C40");
|
|
23591
23681
|
return Array.from(new Set(hints));
|
|
23592
23682
|
}
|
|
@@ -23611,11 +23701,234 @@ function addIf(items, label, condition) {
|
|
|
23611
23701
|
if (condition) items.push(label);
|
|
23612
23702
|
}
|
|
23613
23703
|
|
|
23704
|
+
// src/core/pmIntentGate.ts
|
|
23705
|
+
function decidePmIntent(rawText, context = {}) {
|
|
23706
|
+
const text = `${rawText} ${JSON.stringify(context)}`;
|
|
23707
|
+
const strongSignals = collectSignals(text, strongSignalMap);
|
|
23708
|
+
const weakSignals = collectSignals(text, weakSignalMap);
|
|
23709
|
+
const usageScope = decideUsageScope(text);
|
|
23710
|
+
const preliminaryNeedType = decideNeedType(text, strongSignals);
|
|
23711
|
+
const maintenanceMode = decideMaintenanceMode(text, preliminaryNeedType);
|
|
23712
|
+
const accessTopology = decideAccessTopology(text, usageScope, maintenanceMode);
|
|
23713
|
+
const needType = preliminaryNeedType;
|
|
23714
|
+
const technicalShape = decideTechnicalShape(text, needType, maintenanceMode);
|
|
23715
|
+
const recommendedDeployment = decideRecommendedDeployment(needType, technicalShape, maintenanceMode, accessTopology);
|
|
23716
|
+
const route = decideRoute(needType, technicalShape, maintenanceMode);
|
|
23717
|
+
const confidence = decideConfidence(needType, strongSignals, weakSignals);
|
|
23718
|
+
return enforceHardRules({
|
|
23719
|
+
needType,
|
|
23720
|
+
usageScope,
|
|
23721
|
+
maintenanceMode,
|
|
23722
|
+
accessTopology,
|
|
23723
|
+
technicalShape,
|
|
23724
|
+
recommendedDeployment,
|
|
23725
|
+
route,
|
|
23726
|
+
confidence,
|
|
23727
|
+
strongSignals,
|
|
23728
|
+
weakSignals,
|
|
23729
|
+
coreObjects: extractCoreObjects(text, needType),
|
|
23730
|
+
states: extractStates(text, needType),
|
|
23731
|
+
actions: extractActions(text, needType),
|
|
23732
|
+
mustNotUse: buildMustNotUse(needType, maintenanceMode),
|
|
23733
|
+
boundaryQuestionIds: buildBoundaryQuestionIds(needType, maintenanceMode, accessTopology),
|
|
23734
|
+
defaultAssumptions: buildDefaultAssumptions(needType, usageScope, maintenanceMode, accessTopology, recommendedDeployment),
|
|
23735
|
+
source: "local_rule"
|
|
23736
|
+
});
|
|
23737
|
+
}
|
|
23738
|
+
function decideNeedType(text, strongSignals) {
|
|
23739
|
+
if (hasAny2(text, ["AI", "ai", "LLM", "llm", "GPT", "gpt", "\u5927\u6A21\u578B", "\u6A21\u578B\u63A5\u53E3", "API Key", "DeepSeek", "OpenAI"]) && !isNegated(text, ["AI", "\u6A21\u578B"])) {
|
|
23740
|
+
return "ai_automation";
|
|
23741
|
+
}
|
|
23742
|
+
if (hasAny2(text, ["\u652F\u4ED8", "\u8BA2\u5355", "\u552E\u5356", "\u8D2D\u4E70", "\u62A5\u540D", "\u9884\u7EA6", "\u6536\u6B3E", "\u5BFC\u51FA Excel", "\u5BFC\u51FA"])) {
|
|
23743
|
+
return "transaction_workflow";
|
|
23744
|
+
}
|
|
23745
|
+
if (hasAny2(text, ["\u591A\u4EBA", "\u5BA4\u53CB", "\u5BB6\u4EBA\u5171\u7528", "\u5171\u7528", "\u5171\u4EAB", "\u534F\u4F5C", "\u76F8\u4E92\u5B89\u6392", "\u8BA4\u9886", "\u5206\u914D\u4EFB\u52A1", "\u56E2\u961F\u5F85\u529E"])) {
|
|
23746
|
+
return "multi_user_collaboration";
|
|
23747
|
+
}
|
|
23748
|
+
if (hasAny2(text, ["xlsx", "XLSX", "Excel", "csv", "CSV", "\u56FE\u8868", "\u6570\u636E\u6E32\u67D3", "\u53EF\u89C6\u5316", "\u4EEA\u8868\u76D8"]) && hasAny2(text, ["\u6587\u4EF6", "\u6570\u636E", "\u6E32\u67D3", "\u56FE\u8868", "\u4E0A\u4F20", "\u63D0\u4F9B"])) {
|
|
23749
|
+
return "data_visualization_site";
|
|
23750
|
+
}
|
|
23751
|
+
if (hasAny2(text, ["\u5065\u8EAB\u623F", "\u9910\u5385", "\u5496\u5561\u5E97", "\u5DE5\u4F5C\u5BA4", "\u95E8\u5E97", "\u672C\u5730\u670D\u52A1", "GEO", "geo", "SEO", "seo", "\u4FC3\u9500", "\u6559\u7EC3", "Q&A", "FAQ", "\u7167\u7247", "\u7528\u6237\u53CD\u9988"])) {
|
|
23752
|
+
return "content_marketing_site";
|
|
23753
|
+
}
|
|
23754
|
+
if (hasAny2(text, ["\u77E5\u8BC6\u5E93", "\u6587\u6863\u7BA1\u7406", "\u8D44\u6599\u5E93", "\u56E2\u961F\u6587\u6863"])) {
|
|
23755
|
+
return "content_knowledge";
|
|
23756
|
+
}
|
|
23757
|
+
if (hasAny2(text, ["\u836F\u54C1", "\u98DF\u6750", "\u8BFB\u4E66", "\u8BA2\u9605", "\u690D\u7269", "\u88C5\u5907", "\u6E05\u5355", "\u8BB0\u5F55", "\u63D0\u9192", "\u5E93\u5B58", "\u4FDD\u8D28\u671F"]) && !strongSignals.includes("\u591A\u4EBA")) {
|
|
23758
|
+
return "personal_local_tool";
|
|
23759
|
+
}
|
|
23760
|
+
if (hasAny2(text, ["\u4F5C\u54C1\u96C6", "\u4E2A\u4EBA\u4E3B\u9875", "\u5B98\u7F51", "\u4ECB\u7ECD\u9875", "\u516C\u53F8\u4ECB\u7ECD", "\u8054\u7CFB\u65B9\u5F0F"]) && !hasAny2(text, ["\u63D0\u4EA4", "\u4E0A\u4F20", "\u7F16\u8F91", "\u7EF4\u62A4", "\u6570\u636E", "\u4EFB\u52A1", "\u8BA4\u9886"])) {
|
|
23761
|
+
return "static_display";
|
|
23762
|
+
}
|
|
23763
|
+
return "unknown";
|
|
23764
|
+
}
|
|
23765
|
+
function decideUsageScope(text) {
|
|
23766
|
+
if (hasAny2(text, ["\u516C\u5F00", "\u8BBF\u5BA2", "\u5BA2\u6237", "\u7528\u6237", "\u4F1A\u5458", "\u5B98\u7F51", "\u7F51\u7AD9", "\u95E8\u5E97", "\u5065\u8EAB\u623F", "\u9910\u5385", "\u5DE5\u4F5C\u5BA4"])) return "public_audience";
|
|
23767
|
+
if (hasAny2(text, ["\u591A\u4EBA", "\u5BA4\u53CB", "\u5BB6\u4EBA", "\u5BB6\u5EAD", "\u540C\u4E8B", "\u56E2\u961F", "\u5171\u7528", "\u5171\u4EAB"])) return "fixed_group";
|
|
23768
|
+
if (hasAny2(text, ["\u81EA\u5DF1", "\u81EA\u7528", "\u4E2A\u4EBA", "\u6211\u7528", "\u6211\u81EA\u5DF1"])) return "self";
|
|
23769
|
+
return "unknown";
|
|
23770
|
+
}
|
|
23771
|
+
function decideMaintenanceMode(text, needType) {
|
|
23772
|
+
if (hasAny2(text, ["\u8BBF\u5BA2\u63D0\u4EA4", "\u7528\u6237\u63D0\u4EA4", "\u5728\u7EBF\u63D0\u4EA4", "\u63D0\u4EA4\u53CD\u9988", "\u63D0\u4EA4\u8BC4\u8BBA", "\u9884\u7EA6\u4F53\u9A8C", "\u62A5\u540D"])) return "visitor_submission";
|
|
23773
|
+
if (hasAny2(text, ["\u8BA4\u9886", "\u76F8\u4E92\u5B89\u6392", "\u534F\u4F5C", "\u5206\u914D\u4EFB\u52A1", "\u591A\u4EBA\u4EFB\u52A1", "\u5171\u4EAB\u4EFB\u52A1"])) return "runtime_collaboration";
|
|
23774
|
+
if (hasAny2(text, ["\u540E\u53F0", "\u7BA1\u7406\u540E\u53F0", "\u7F51\u9875\u91CC\u7F16\u8F91", "\u7F51\u9875\u4E0A\u4F20", "\u4E0A\u4F20\u6309\u94AE", "\u767B\u5F55\u540E\u7F16\u8F91", "CMS", "cms"])) return "web_admin";
|
|
23775
|
+
if (hasAny2(text, ["data.json", "markdown", "Markdown", "md \u6587\u4EF6", "\u624B\u52A8\u6539\u6587\u4EF6"])) return "manual_files";
|
|
23776
|
+
if (hasAny2(text, ["Agent", "agent", "\u6BCF\u6B21\u6211\u63D0\u4F9B", "\u6211\u63D0\u4F9B\u65B0\u7684", "\u4F20\u5F88\u591A", "\u4E0D\u5B9A\u671F\u7EF4\u62A4", "\u91CD\u65B0\u90E8\u7F72"])) return "agent_assisted";
|
|
23777
|
+
if (needType === "content_marketing_site" || needType === "data_visualization_site" || needType === "static_display") return "agent_assisted";
|
|
23778
|
+
return "unknown";
|
|
23779
|
+
}
|
|
23780
|
+
function decideAccessTopology(text, usageScope, maintenanceMode) {
|
|
23781
|
+
if (hasAny2(text, ["\u540C\u4E00 Wi-Fi", "\u540C\u4E00\u4E2A Wi-Fi", "\u5C40\u57DF\u7F51", "\u5185\u7F51", "\u5BB6\u91CC\u7F51\u7EDC"])) return "lan_only";
|
|
23782
|
+
if (hasAny2(text, ["\u5916\u51FA", "\u516C\u7F51 IP", "\u516C\u7F51ip", "IP \u5730\u5740", "\u670D\u52A1\u5668", "VPS", "vps"])) return "internet_ip";
|
|
23783
|
+
if (hasAny2(text, ["\u57DF\u540D", "HTTPS", "https", "\u5907\u6848", "\u516C\u5F00\u7F51\u7AD9", "\u5B98\u7F51"])) return "public_domain";
|
|
23784
|
+
if (usageScope === "self" && maintenanceMode !== "runtime_collaboration") return "single_device";
|
|
23785
|
+
if (usageScope === "public_audience") return "public_domain";
|
|
23786
|
+
return "unknown";
|
|
23787
|
+
}
|
|
23788
|
+
function decideTechnicalShape(text, needType, maintenanceMode) {
|
|
23789
|
+
if (needType === "ai_automation") return "full_backend_saas";
|
|
23790
|
+
if (needType === "transaction_workflow") return hasAny2(text, ["\u652F\u4ED8", "\u8BA2\u5355", "\u6536\u8D39"]) ? "full_backend_saas" : "light_backend_json_sqlite";
|
|
23791
|
+
if (needType === "multi_user_collaboration") return "light_backend_json_sqlite";
|
|
23792
|
+
if (needType === "content_marketing_site") {
|
|
23793
|
+
return maintenanceMode === "web_admin" || maintenanceMode === "visitor_submission" ? "light_backend_json_sqlite" : "static_json_data_page";
|
|
23794
|
+
}
|
|
23795
|
+
if (needType === "data_visualization_site") {
|
|
23796
|
+
return maintenanceMode === "web_admin" || maintenanceMode === "visitor_submission" ? "light_backend_json_sqlite" : "static_json_data_page";
|
|
23797
|
+
}
|
|
23798
|
+
if (needType === "content_knowledge") {
|
|
23799
|
+
return maintenanceMode === "agent_assisted" || maintenanceMode === "manual_files" ? "static_json_data_page" : "light_backend_json_sqlite";
|
|
23800
|
+
}
|
|
23801
|
+
if (needType === "personal_local_tool") return "local_storage_tool";
|
|
23802
|
+
if (needType === "static_display") return "static_page";
|
|
23803
|
+
return "unknown";
|
|
23804
|
+
}
|
|
23805
|
+
function decideRecommendedDeployment(needType, technicalShape, maintenanceMode, accessTopology) {
|
|
23806
|
+
if (technicalShape === "static_page") return "static_only";
|
|
23807
|
+
if (technicalShape === "local_storage_tool" || technicalShape === "local_json_import_export") return "local_browser_only";
|
|
23808
|
+
if (maintenanceMode === "agent_assisted" && ["content_marketing_site", "data_visualization_site", "content_knowledge"].includes(needType)) {
|
|
23809
|
+
return "static_hosting_with_agent_updates";
|
|
23810
|
+
}
|
|
23811
|
+
if (accessTopology === "lan_only") return "local_lan_server_sqlite";
|
|
23812
|
+
if (accessTopology === "internet_ip") return "cheap_vps_sqlite_by_ip";
|
|
23813
|
+
if (accessTopology === "public_domain") return "vps_domain_https";
|
|
23814
|
+
if (technicalShape === "light_backend_json_sqlite") return "cheap_vps_sqlite_by_ip";
|
|
23815
|
+
return "unknown";
|
|
23816
|
+
}
|
|
23817
|
+
function decideRoute(needType, technicalShape, maintenanceMode) {
|
|
23818
|
+
if (needType === "personal_local_tool") return "spec_compile";
|
|
23819
|
+
if (["static_page", "static_json_data_page"].includes(technicalShape) && maintenanceMode === "agent_assisted") return "spec_compile";
|
|
23820
|
+
return "spec_interrogate";
|
|
23821
|
+
}
|
|
23822
|
+
function decideConfidence(needType, strongSignals, weakSignals) {
|
|
23823
|
+
if (needType === "unknown") return "low";
|
|
23824
|
+
if (strongSignals.length >= 2) return "high";
|
|
23825
|
+
if (strongSignals.length === 1 || weakSignals.length >= 2) return "medium";
|
|
23826
|
+
return "medium";
|
|
23827
|
+
}
|
|
23828
|
+
function enforceHardRules(decision) {
|
|
23829
|
+
const hasRuntimeCollaboration = decision.needType === "multi_user_collaboration" || decision.maintenanceMode === "runtime_collaboration" || decision.strongSignals.some((signal) => ["\u591A\u4EBA", "\u5171\u4EAB", "\u534F\u4F5C", "\u8BA4\u9886", "\u76F8\u4E92\u5B89\u6392"].includes(signal));
|
|
23830
|
+
if (hasRuntimeCollaboration && decision.technicalShape !== "light_backend_json_sqlite") {
|
|
23831
|
+
return {
|
|
23832
|
+
...decision,
|
|
23833
|
+
needType: "multi_user_collaboration",
|
|
23834
|
+
maintenanceMode: "runtime_collaboration",
|
|
23835
|
+
technicalShape: "light_backend_json_sqlite",
|
|
23836
|
+
recommendedDeployment: decision.accessTopology === "lan_only" ? "local_lan_server_sqlite" : "cheap_vps_sqlite_by_ip",
|
|
23837
|
+
route: "spec_interrogate",
|
|
23838
|
+
mustNotUse: Array.from(/* @__PURE__ */ new Set([...decision.mustNotUse, "static_display", "local_storage_only"]))
|
|
23839
|
+
};
|
|
23840
|
+
}
|
|
23841
|
+
return decision;
|
|
23842
|
+
}
|
|
23843
|
+
function buildMustNotUse(needType, maintenanceMode) {
|
|
23844
|
+
const items = [];
|
|
23845
|
+
if (needType === "multi_user_collaboration") items.push("static_display", "local_storage_only");
|
|
23846
|
+
if (needType === "content_marketing_site" || needType === "data_visualization_site") items.push("admin_backend_by_default", "database_by_default");
|
|
23847
|
+
if (maintenanceMode === "agent_assisted") items.push("web_admin_cms_by_default");
|
|
23848
|
+
if (needType === "transaction_workflow") items.push("local_storage_only");
|
|
23849
|
+
if (needType === "ai_automation") items.push("frontend_api_key");
|
|
23850
|
+
return Array.from(new Set(items));
|
|
23851
|
+
}
|
|
23852
|
+
function buildBoundaryQuestionIds(needType, maintenanceMode, accessTopology) {
|
|
23853
|
+
if (needType === "multi_user_collaboration") {
|
|
23854
|
+
return ["access_topology", "public_ip_acceptance", "claim_rule", "time_conflict_rule"];
|
|
23855
|
+
}
|
|
23856
|
+
if (needType === "content_marketing_site") {
|
|
23857
|
+
return ["maintenance_mode", "geo_goal", "visitor_submission", "image_volume"];
|
|
23858
|
+
}
|
|
23859
|
+
if (needType === "data_visualization_site") {
|
|
23860
|
+
return ["data_update_mode", "audience_scope", "history_versions"];
|
|
23861
|
+
}
|
|
23862
|
+
if (needType === "content_knowledge") {
|
|
23863
|
+
return maintenanceMode === "agent_assisted" ? ["maintenance_mode", "visibility_scope"] : ["editor_roles", "permission_rule", "version_history"];
|
|
23864
|
+
}
|
|
23865
|
+
if (needType === "unknown") return ["usage_scope", "maintenance_mode", "data_flow"];
|
|
23866
|
+
if (accessTopology === "unknown" && needType !== "personal_local_tool") return ["access_topology"];
|
|
23867
|
+
return [];
|
|
23868
|
+
}
|
|
23869
|
+
function buildDefaultAssumptions(needType, usageScope, maintenanceMode, accessTopology, deployment) {
|
|
23870
|
+
const items = [`\u4F7F\u7528\u8303\u56F4\uFF1A${usageScope}`, `\u7EF4\u62A4\u65B9\u5F0F\uFF1A${maintenanceMode}`, `\u8BBF\u95EE\u65B9\u5F0F\uFF1A${accessTopology}`, `\u63A8\u8350\u90E8\u7F72\uFF1A${deployment}`];
|
|
23871
|
+
if (needType === "content_marketing_site" || needType === "data_visualization_site") {
|
|
23872
|
+
items.push("\u5185\u5BB9\u6216\u6570\u636E\u7ECF\u5E38\u66F4\u65B0\u65F6\uFF0CMVP \u9ED8\u8BA4\u4F18\u5148\u7531 Agent \u66F4\u65B0\u5185\u5BB9\u6587\u4EF6\u5E76\u91CD\u65B0\u90E8\u7F72\uFF0C\u4E0D\u9ED8\u8BA4\u5EFA\u8BBE\u7F51\u9875\u540E\u53F0\u3002");
|
|
23873
|
+
}
|
|
23874
|
+
if (needType === "multi_user_collaboration") {
|
|
23875
|
+
items.push("\u591A\u4EBA\u534F\u4F5C\u5148\u786E\u8BA4\u5C40\u57DF\u7F51\u662F\u5426\u8DB3\u591F\uFF1B\u4E0D\u76F4\u63A5\u9ED8\u8BA4\u516C\u7F51\u670D\u52A1\u5668\u3001\u57DF\u540D\u6216\u5907\u6848\u3002");
|
|
23876
|
+
}
|
|
23877
|
+
return items;
|
|
23878
|
+
}
|
|
23879
|
+
function extractCoreObjects(text, needType) {
|
|
23880
|
+
if (needType === "multi_user_collaboration") return ["\u7528\u6237", "\u4EFB\u52A1", "\u65E5\u7A0B\u9879"];
|
|
23881
|
+
if (needType === "content_marketing_site") return ["Q&A", "\u7167\u7247", "\u7528\u6237\u53CD\u9988", "\u4FC3\u9500\u6D3B\u52A8", "\u6559\u7EC3\u4FE1\u606F"].filter((item) => text.includes(item.replace("\u4FE1\u606F", "")) || item === "Q&A");
|
|
23882
|
+
if (needType === "data_visualization_site") return ["xlsx \u6587\u4EF6", "\u6570\u636E\u8868", "\u56FE\u8868\u914D\u7F6E", "\u6E32\u67D3\u7ED3\u679C"];
|
|
23883
|
+
if (needType === "personal_local_tool") {
|
|
23884
|
+
if (text.includes("\u836F")) return ["\u836F\u54C1"];
|
|
23885
|
+
if (text.includes("\u98DF\u6750")) return ["\u98DF\u6750"];
|
|
23886
|
+
return ["\u8BB0\u5F55"];
|
|
23887
|
+
}
|
|
23888
|
+
return [];
|
|
23889
|
+
}
|
|
23890
|
+
function extractStates(text, needType) {
|
|
23891
|
+
const states = [];
|
|
23892
|
+
if (needType === "multi_user_collaboration") states.push("\u5F85\u8BA4\u9886", "\u5DF2\u8BA4\u9886", "\u5DF2\u5B8C\u6210", "\u53D6\u6D88");
|
|
23893
|
+
if (hasAny2(text, ["\u8FC7\u671F", "\u4E34\u671F", "\u5230\u671F"])) states.push("\u6B63\u5E38", "\u4E34\u671F", "\u5DF2\u8FC7\u671F");
|
|
23894
|
+
return Array.from(new Set(states));
|
|
23895
|
+
}
|
|
23896
|
+
function extractActions(text, needType) {
|
|
23897
|
+
if (needType === "multi_user_collaboration") return ["\u5B89\u6392\u4EFB\u52A1", "\u8BA4\u9886\u4EFB\u52A1", "\u67E5\u770B\u65E5\u7A0B\u51B2\u7A81"];
|
|
23898
|
+
if (needType === "content_marketing_site") return ["\u66F4\u65B0\u5185\u5BB9", "\u53D1\u5E03\u4FC3\u9500", "\u7EF4\u62A4\u56FE\u7247\u548C FAQ"];
|
|
23899
|
+
if (needType === "data_visualization_site") return ["\u89E3\u6790 xlsx", "\u66F4\u65B0\u56FE\u8868\u6570\u636E", "\u6E32\u67D3\u7ED3\u679C"];
|
|
23900
|
+
return [];
|
|
23901
|
+
}
|
|
23902
|
+
var strongSignalMap = {
|
|
23903
|
+
\u591A\u4EBA: ["\u591A\u4EBA", "\u5BA4\u53CB", "\u5BB6\u4EBA\u5171\u7528", "\u5171\u7528", "\u5171\u4EAB"],
|
|
23904
|
+
\u534F\u4F5C: ["\u534F\u4F5C", "\u76F8\u4E92\u5B89\u6392", "\u8BA4\u9886", "\u5206\u914D\u4EFB\u52A1"],
|
|
23905
|
+
\u6743\u9650: ["\u6743\u9650", "\u767B\u5F55", "\u540E\u53F0", "\u7BA1\u7406\u5458", "\u5BA1\u6279", "\u5BA1\u6838"],
|
|
23906
|
+
\u516C\u5F00\u63D0\u4EA4: ["\u8BBF\u5BA2\u63D0\u4EA4", "\u7528\u6237\u63D0\u4EA4", "\u5728\u7EBF\u63D0\u4EA4", "\u63D0\u4EA4\u53CD\u9988"],
|
|
23907
|
+
\u4EA4\u6613: ["\u652F\u4ED8", "\u8BA2\u5355", "\u552E\u5356", "\u8D2D\u4E70", "\u62A5\u540D", "\u9884\u7EA6"],
|
|
23908
|
+
AI: ["AI", "ai", "API Key", "\u6A21\u578B\u63A5\u53E3", "\u5927\u6A21\u578B"]
|
|
23909
|
+
};
|
|
23910
|
+
var weakSignalMap = {
|
|
23911
|
+
\u5C55\u793A: ["\u5C55\u793A", "\u7F51\u7AD9", "\u9875\u9762"],
|
|
23912
|
+
\u89C6\u89C9: ["\u9875\u9762\u9AD8\u7EA7", "\u597D\u770B", "\u7F8E\u89C2"],
|
|
23913
|
+
\u7BA1\u7406: ["\u7BA1\u7406", "\u7EF4\u62A4", "\u5185\u5BB9\u591A"],
|
|
23914
|
+
\u5217\u8868: ["\u5217\u8868", "\u67E5\u770B", "\u7B5B\u9009", "\u65E5\u7A0B", "\u72B6\u6001"]
|
|
23915
|
+
};
|
|
23916
|
+
function collectSignals(text, map) {
|
|
23917
|
+
return Object.entries(map).filter(([, signals]) => hasAny2(text, signals)).map(([label]) => label);
|
|
23918
|
+
}
|
|
23919
|
+
function hasAny2(text, signals) {
|
|
23920
|
+
return signals.some((signal) => text.includes(signal));
|
|
23921
|
+
}
|
|
23922
|
+
function isNegated(text, signals) {
|
|
23923
|
+
return signals.some((signal) => new RegExp(`(\u4E0D\u63A5|\u4E0D\u505A|\u4E0D\u7528|\u65E0\u9700|\u4E0D\u9700\u8981|\u6682\u4E0D|\u5148\u4E0D).{0,8}${signal}`, "i").test(text));
|
|
23924
|
+
}
|
|
23925
|
+
|
|
23614
23926
|
// src/core/promptBuilder.ts
|
|
23615
23927
|
function buildSpec(rawIdea, context, readiness) {
|
|
23616
23928
|
const assumptions = [];
|
|
23617
23929
|
const normalizedContext = normalizeContext(context);
|
|
23618
23930
|
const technicalProfile = buildTechnicalProfile(rawIdea, normalizedContext);
|
|
23931
|
+
const pmIntentDecision = decidePmIntent(rawIdea, normalizedContext);
|
|
23619
23932
|
const classification = classifyProductDomain(rawIdea, normalizedContext);
|
|
23620
23933
|
const shouldUseDomainPack = classification.domain !== "generic" && !(isLocalFirstProfile(technicalProfile) && ["knowledge_base", "ticket_workflow"].includes(classification.domain));
|
|
23621
23934
|
if (shouldUseDomainPack && classification.domain === "crm") {
|
|
@@ -23642,16 +23955,21 @@ function buildSpec(rawIdea, context, readiness) {
|
|
|
23642
23955
|
if (shouldUseDomainPack && classification.domain === "registration") {
|
|
23643
23956
|
return withTechnicalProfile(buildRegistrationSpec(rawIdea, normalizedContext, readiness), technicalProfile);
|
|
23644
23957
|
}
|
|
23958
|
+
if (classification.domain === "generic" && shouldUsePmGateSpec(pmIntentDecision)) {
|
|
23959
|
+
return withTechnicalProfile(buildPmGateSpec(rawIdea, normalizedContext, readiness, pmIntentDecision), technicalProfile);
|
|
23960
|
+
}
|
|
23645
23961
|
const hasStructuredAnswers = hasUnsupportedStructuredAnswers(normalizedContext);
|
|
23646
23962
|
const personalLocalTool = isLocalFirstProfile(technicalProfile) || isPersonalLocalFrontendToolContext(rawIdea, normalizedContext);
|
|
23647
|
-
const
|
|
23963
|
+
const localSignalProfile = personalLocalTool ? buildLocalToolSignalProfile(rawIdea) : void 0;
|
|
23964
|
+
const hasLocalSignals = Boolean(localSignalProfile && (localSignalProfile.featureHints.length > 0 || localSignalProfile.recordObject !== "\u8BB0\u5F55"));
|
|
23965
|
+
const genericReadinessScore = hasStructuredAnswers ? Math.min(Math.max(readiness.score, 60), 79) : hasLocalSignals ? Math.max(readiness.score, 60) : readiness.score;
|
|
23648
23966
|
const genericReadinessStatus = readinessStatusFromScore(genericReadinessScore);
|
|
23649
23967
|
const isActionable = !hasStructuredAnswers && genericReadinessScore >= 70;
|
|
23650
|
-
const productGoal = normalizedContext.product_goal || extractGoal(rawIdea);
|
|
23968
|
+
const productGoal = normalizedContext.product_goal || extractGoal(rawIdea) || (hasLocalSignals && localSignalProfile ? `${localSignalProfile.recordObject}\u7BA1\u7406\u5DE5\u5177` : "");
|
|
23651
23969
|
if (!productGoal) {
|
|
23652
23970
|
assumptions.push("\u4EA7\u54C1\u76EE\u6807\uFF1A\u672A\u660E\u786E\uFF0C\u9700\u8981\u7528\u6237\u786E\u8BA4");
|
|
23653
23971
|
}
|
|
23654
|
-
const targetUser = normalizedContext.target_user || extractTargetUser(rawIdea);
|
|
23972
|
+
const targetUser = normalizedContext.target_user || (hasLocalSignals ? inferLocalFirstTargetUser(rawIdea) : extractTargetUser(rawIdea));
|
|
23655
23973
|
if (!targetUser) {
|
|
23656
23974
|
assumptions.push("\u76EE\u6807\u7528\u6237\uFF1A\u9ED8\u8BA4\u4E3A\u4E2A\u4EBA\u7528\u6237");
|
|
23657
23975
|
}
|
|
@@ -23666,7 +23984,9 @@ function buildSpec(rawIdea, context, readiness) {
|
|
|
23666
23984
|
assumptions.push("\u5F53\u524D\u8F93\u5165\u5305\u542B\u591A\u4E2A\u7ED3\u6784\u5316\u7B54\u6848\uFF0C\u4F46\u672A\u5339\u914D\u5230\u7A33\u5B9A domain pack\uFF1B\u4E0D\u8981\u628A\u5B83\u5957\u5165\u62A5\u540D\u3001\u7535\u5546\u3001\u9884\u7EA6\u3001\u5185\u5BB9\u793E\u533A\u3001\u5DE5\u5355\u6216\u77E5\u8BC6\u5E93\u6A21\u677F\u3002");
|
|
23667
23985
|
}
|
|
23668
23986
|
const needsBackend = technicalProfile.needsBackend || normalizedContext.need_backend === true || normalizedContext.data_persistence === true || normalizedContext.user_roles === true || normalizedContext.backend_need === true;
|
|
23669
|
-
const dataModel = buildDataModel(normalizedContext, needsBackend, technicalProfile);
|
|
23987
|
+
const dataModel = buildDataModel(normalizedContext, needsBackend, technicalProfile, rawIdea);
|
|
23988
|
+
const successCriteria = personalLocalTool ? buildLocalFirstSuccessCriteria(rawIdea) : ["\u6838\u5FC3\u529F\u80FD\u53EF\u7528", "\u65E0\u660E\u663E Bug", "\u7528\u6237\u4F53\u9A8C\u6D41\u7545"];
|
|
23989
|
+
const nonGoals = personalLocalTool ? ["\u6682\u4E0D\u5305\u542B\u767B\u5F55/\u6CE8\u518C", "\u6682\u4E0D\u5305\u542B\u540E\u53F0\u7BA1\u7406\u7CFB\u7EDF", "\u6682\u4E0D\u5305\u542B\u591A\u4EBA\u591A\u8BBE\u5907\u540C\u6B65"] : ["\u6682\u4E0D\u5305\u542B\u9AD8\u7EA7\u529F\u80FD", "\u6682\u4E0D\u5305\u542B\u79FB\u52A8\u7AEF App"];
|
|
23670
23990
|
return {
|
|
23671
23991
|
readinessScore: genericReadinessScore,
|
|
23672
23992
|
readinessStatus: genericReadinessStatus,
|
|
@@ -23679,16 +23999,191 @@ function buildSpec(rawIdea, context, readiness) {
|
|
|
23679
23999
|
architecture: buildArchitectureRecommendation(normalizedContext, needsBackend, technicalProfile),
|
|
23680
24000
|
apiDesign: personalLocalTool ? buildLocalFirstApiDesign(technicalProfile) : hasStructuredAnswers ? "\u672A\u5339\u914D\u5230\u7A33\u5B9A domain\uFF0C\u6682\u4E0D\u751F\u6210\u6B63\u5F0F API\uFF1B\u8BF7\u5148\u8865\u5145\u6838\u5FC3\u4E1A\u52A1\u5BF9\u8C61\u3001\u72B6\u6001\u6D41\u8F6C\u3001\u6743\u9650\u8FB9\u754C\u540E\u518D\u7F16\u8BD1\u3002" : needsBackend ? buildApiDesign(normalizedContext, coreFeatures) : "\u7EAF\u524D\u7AEF\u9879\u76EE\uFF0C\u65E0\u9700 API",
|
|
23681
24001
|
riskBoundaries: hasStructuredAnswers ? ["\u672A\u547D\u4E2D\u7A33\u5B9A domain pack\uFF0C\u5F53\u524D\u89C4\u683C\u4EC5\u53EF\u4F5C\u4E3A\u8349\u6848\uFF1B\u7981\u6B62\u9759\u9ED8\u590D\u7528\u5176\u5B83\u4E1A\u52A1\u6A21\u677F\u3002"] : buildRiskBoundaries(normalizedContext),
|
|
23682
|
-
nonGoals: toArray(normalizedContext.non_goals,
|
|
23683
|
-
successCriteria: toArray(normalizedContext.success_criteria,
|
|
24002
|
+
nonGoals: toArray(normalizedContext.non_goals, nonGoals),
|
|
24003
|
+
successCriteria: toArray(normalizedContext.success_criteria, successCriteria),
|
|
23684
24004
|
assumptions,
|
|
23685
24005
|
technicalProfile,
|
|
24006
|
+
pmIntentDecision,
|
|
23686
24007
|
inputConsumption: buildInputConsumption(normalizedContext, Object.keys(normalizedContext), "generic", "low")
|
|
23687
24008
|
};
|
|
23688
24009
|
}
|
|
23689
24010
|
function withTechnicalProfile(spec, technicalProfile) {
|
|
23690
24011
|
return { ...spec, technicalProfile };
|
|
23691
24012
|
}
|
|
24013
|
+
function shouldUsePmGateSpec(decision) {
|
|
24014
|
+
return [
|
|
24015
|
+
"multi_user_collaboration",
|
|
24016
|
+
"content_marketing_site",
|
|
24017
|
+
"data_visualization_site"
|
|
24018
|
+
].includes(decision.needType);
|
|
24019
|
+
}
|
|
24020
|
+
function buildPmGateSpec(rawIdea, context, readiness, decision) {
|
|
24021
|
+
const score = Math.min(Math.max(readiness.score, 60), 79);
|
|
24022
|
+
const productGoal = context.product_goal || pmGateProductGoal(decision);
|
|
24023
|
+
const targetUser = context.target_user || pmGateTargetUser(decision);
|
|
24024
|
+
const assumptions = [...decision.defaultAssumptions];
|
|
24025
|
+
return {
|
|
24026
|
+
readinessScore: score,
|
|
24027
|
+
readinessStatus: readinessStatusFromScore(score),
|
|
24028
|
+
isActionable: false,
|
|
24029
|
+
productGoal,
|
|
24030
|
+
targetUser,
|
|
24031
|
+
platform: context.platform || "web",
|
|
24032
|
+
coreFeatures: pmGateCoreFeatures(decision),
|
|
24033
|
+
dataModel: pmGateDataModel(decision),
|
|
24034
|
+
architecture: pmGateArchitecture(decision),
|
|
24035
|
+
apiDesign: pmGateApiDesign(decision),
|
|
24036
|
+
riskBoundaries: pmGateRiskBoundaries(decision),
|
|
24037
|
+
nonGoals: pmGateNonGoals(decision),
|
|
24038
|
+
successCriteria: pmGateSuccessCriteria(decision),
|
|
24039
|
+
assumptions,
|
|
24040
|
+
pmIntentDecision: decision,
|
|
24041
|
+
inputConsumption: buildInputConsumption(context, Object.keys(context), "generic", decision.confidence)
|
|
24042
|
+
};
|
|
24043
|
+
}
|
|
24044
|
+
function pmGateProductGoal(decision) {
|
|
24045
|
+
if (decision.needType === "multi_user_collaboration") return "\u591A\u4EBA\u5171\u4EAB\u4EFB\u52A1\u65E5\u7A0B\u5DE5\u5177";
|
|
24046
|
+
if (decision.needType === "content_marketing_site") return "\u5185\u5BB9\u8425\u9500\u7F51\u7AD9";
|
|
24047
|
+
if (decision.needType === "data_visualization_site") return "\u6570\u636E\u56FE\u8868\u5C55\u793A\u7F51\u7AD9";
|
|
24048
|
+
return "\u4EA7\u54C1 MVP";
|
|
24049
|
+
}
|
|
24050
|
+
function pmGateTargetUser(decision) {
|
|
24051
|
+
if (decision.usageScope === "fixed_group") return "\u56FA\u5B9A\u5C0F\u8303\u56F4\u6210\u5458";
|
|
24052
|
+
if (decision.usageScope === "public_audience") return "\u516C\u5F00\u8BBF\u95EE\u7528\u6237\u548C\u7AD9\u70B9\u7EF4\u62A4\u8005";
|
|
24053
|
+
if (decision.usageScope === "self") return "\u4E2A\u4EBA\u4F7F\u7528\u8005";
|
|
24054
|
+
return "\u5F85\u7528\u6237\u786E\u8BA4";
|
|
24055
|
+
}
|
|
24056
|
+
function pmGateCoreFeatures(decision) {
|
|
24057
|
+
if (decision.needType === "multi_user_collaboration") {
|
|
24058
|
+
return [
|
|
24059
|
+
"\u6210\u5458\u4EFB\u52A1\u65E5\u7A0B\u5C55\u793A",
|
|
24060
|
+
"\u81EA\u5DF1\u7ED9\u81EA\u5DF1\u5B89\u6392\u4EFB\u52A1\u76F4\u63A5\u751F\u6548",
|
|
24061
|
+
"\u7ED9\u522B\u4EBA\u5B89\u6392\u4EFB\u52A1\u8FDB\u5165\u5F85\u8BA4\u9886",
|
|
24062
|
+
"\u4EFB\u52A1\u8BA4\u9886\u548C\u5B8C\u6210\u72B6\u6001\u6D41\u8F6C",
|
|
24063
|
+
"\u540C\u4E00\u65F6\u95F4\u4EFB\u52A1\u5E76\u6392\u5C55\u793A\u6216\u9AD8\u4EAE\u51B2\u7A81"
|
|
24064
|
+
];
|
|
24065
|
+
}
|
|
24066
|
+
if (decision.needType === "content_marketing_site") {
|
|
24067
|
+
return [
|
|
24068
|
+
"\u5065\u8EAB\u623F\u57FA\u7840\u4FE1\u606F\u5C55\u793A",
|
|
24069
|
+
"Q&A/FAQ \u5185\u5BB9\u9875",
|
|
24070
|
+
"\u7167\u7247\u548C\u7528\u6237\u53CD\u9988\u5C55\u793A",
|
|
24071
|
+
"\u8FD1\u671F\u4FC3\u9500\u6D3B\u52A8\u5C55\u793A",
|
|
24072
|
+
"\u6559\u7EC3\u4FE1\u606F\u5C55\u793A",
|
|
24073
|
+
"GEO/SEO \u7ED3\u6784\u5316\u5185\u5BB9"
|
|
24074
|
+
];
|
|
24075
|
+
}
|
|
24076
|
+
if (decision.needType === "data_visualization_site") {
|
|
24077
|
+
return [
|
|
24078
|
+
"xlsx \u6570\u636E\u89E3\u6790\u6D41\u7A0B",
|
|
24079
|
+
"\u56FE\u8868\u6570\u636E JSON \u751F\u6210",
|
|
24080
|
+
"\u56FE\u8868\u9875\u9762\u6E32\u67D3",
|
|
24081
|
+
"\u6700\u65B0\u6570\u636E\u7ED3\u679C\u5C55\u793A"
|
|
24082
|
+
];
|
|
24083
|
+
}
|
|
24084
|
+
return ["\u6838\u5FC3\u529F\u80FD\u5F85\u786E\u8BA4"];
|
|
24085
|
+
}
|
|
24086
|
+
function pmGateDataModel(decision) {
|
|
24087
|
+
if (decision.needType === "multi_user_collaboration") {
|
|
24088
|
+
return [
|
|
24089
|
+
"SQLite\uFF08MVP\uFF09",
|
|
24090
|
+
"users(id, name, access_code, created_at)",
|
|
24091
|
+
"tasks(id, title, description, start_at, end_at, creator_id, assignee_id, status, created_at, updated_at)",
|
|
24092
|
+
"task_events(id, task_id, actor_id, action, note, created_at)",
|
|
24093
|
+
"status \u5EFA\u8BAE\uFF1Aself_active / pending_claim / claimed / done / cancelled"
|
|
24094
|
+
].join("\n");
|
|
24095
|
+
}
|
|
24096
|
+
if (decision.needType === "content_marketing_site") {
|
|
24097
|
+
return [
|
|
24098
|
+
"\u9759\u6001\u5185\u5BB9\u6587\u4EF6\uFF1Adata/site.json + markdown \u5185\u5BB9 + assets \u56FE\u7247\u76EE\u5F55",
|
|
24099
|
+
"site_profile(name, address, hours, phone, geo_keywords)",
|
|
24100
|
+
"faqs(question, answer, category)",
|
|
24101
|
+
"coaches(name, title, specialties, bio, photo)",
|
|
24102
|
+
"promotions(title, description, start_date, end_date, status)",
|
|
24103
|
+
"testimonials(author_label, content, source, status)",
|
|
24104
|
+
"\u9ED8\u8BA4\u7531 Agent \u66F4\u65B0\u5185\u5BB9\u6587\u4EF6\u5E76\u91CD\u65B0\u90E8\u7F72\uFF0C\u4E0D\u9ED8\u8BA4\u5EFA\u8BBE CMS \u540E\u53F0\u3002"
|
|
24105
|
+
].join("\n");
|
|
24106
|
+
}
|
|
24107
|
+
if (decision.needType === "data_visualization_site") {
|
|
24108
|
+
return [
|
|
24109
|
+
"\u9759\u6001\u6570\u636E\u6587\u4EF6\uFF1Adata/chart-data.json",
|
|
24110
|
+
"Agent \u4ECE xlsx \u89E3\u6790\u51FA rows\u3001columns\u3001metrics\u3001chart_config",
|
|
24111
|
+
"\u9875\u9762\u8BFB\u53D6 chart-data.json \u6E32\u67D3\u56FE\u8868\uFF1B\u9ED8\u8BA4\u53EA\u5C55\u793A\u6700\u65B0\u7ED3\u679C\u3002",
|
|
24112
|
+
"\u5982\u6539\u4E3A\u7F51\u9875\u4E0A\u4F20\u4E14\u6240\u6709\u8BBF\u5BA2\u770B\u6700\u65B0\u7ED3\u679C\uFF0C\u518D\u5347\u7EA7\u4E0A\u4F20\u63A5\u53E3\u548C\u670D\u52A1\u5668\u5B58\u50A8\u3002"
|
|
24113
|
+
].join("\n");
|
|
24114
|
+
}
|
|
24115
|
+
return "\u5F85\u786E\u8BA4\u6570\u636E\u6A21\u578B";
|
|
24116
|
+
}
|
|
24117
|
+
function pmGateArchitecture(decision) {
|
|
24118
|
+
if (decision.needType === "multi_user_collaboration") {
|
|
24119
|
+
return decision.accessTopology === "lan_only" ? "\u5C40\u57DF\u7F51\u8F7B\u540E\u7AEF\uFF1A\u4E00\u53F0\u672C\u673A/NAS \u8FD0\u884C Node + SQLite\uFF0C\u6210\u5458\u901A\u8FC7\u5C40\u57DF\u7F51 IP \u8BBF\u95EE\u3002" : "\u8F7B\u540E\u7AEF MVP\uFF1ANode + SQLite\uFF1B\u56FA\u5B9A\u51E0\u4EBA\u5916\u51FA\u8BBF\u95EE\u65F6\u53EF\u7528\u4F4E\u4EF7\u516C\u7F51 VPS + IP \u5730\u5740\u5148\u8DD1\u901A\u3002";
|
|
24120
|
+
}
|
|
24121
|
+
if (decision.needType === "content_marketing_site") {
|
|
24122
|
+
return "\u9759\u6001\u5185\u5BB9\u8425\u9500\u7AD9\uFF1AHTML/CSS/JS + \u9759\u6001\u5185\u5BB9\u6587\u4EF6 + \u56FE\u7247\u8D44\u6E90\uFF1B\u7531 Agent \u7EF4\u62A4\u5185\u5BB9\u5E76\u91CD\u65B0\u90E8\u7F72\u3002";
|
|
24123
|
+
}
|
|
24124
|
+
if (decision.needType === "data_visualization_site") {
|
|
24125
|
+
return "\u9759\u6001\u6570\u636E\u56FE\u8868\u7AD9\uFF1AAgent \u89E3\u6790 xlsx \u751F\u6210 JSON\uFF0C\u524D\u7AEF\u8BFB\u53D6 JSON \u5E76\u6E32\u67D3\u56FE\u8868\uFF1B\u4E0D\u9ED8\u8BA4\u540E\u53F0\u6216\u6570\u636E\u5E93\u3002";
|
|
24126
|
+
}
|
|
24127
|
+
return "\u5F85\u786E\u8BA4\u67B6\u6784";
|
|
24128
|
+
}
|
|
24129
|
+
function pmGateApiDesign(decision) {
|
|
24130
|
+
if (decision.needType === "multi_user_collaboration") {
|
|
24131
|
+
return [
|
|
24132
|
+
"GET /api/schedule?date=YYYY-MM-DD",
|
|
24133
|
+
"POST /api/tasks",
|
|
24134
|
+
"POST /api/tasks/:id/claim",
|
|
24135
|
+
"POST /api/tasks/:id/complete",
|
|
24136
|
+
"PATCH /api/tasks/:id"
|
|
24137
|
+
].join("\n");
|
|
24138
|
+
}
|
|
24139
|
+
return "\u65E0\u9700 REST API\uFF1B\u7531 Agent \u66F4\u65B0\u9759\u6001\u5185\u5BB9/\u6570\u636E\u6587\u4EF6\u540E\u91CD\u65B0\u90E8\u7F72\u3002";
|
|
24140
|
+
}
|
|
24141
|
+
function pmGateRiskBoundaries(decision) {
|
|
24142
|
+
if (decision.needType === "multi_user_collaboration") {
|
|
24143
|
+
return ["\u591A\u4EBA\u8FD0\u884C\u65F6\u6570\u636E\u9700\u8981\u7EDF\u4E00\u6570\u636E\u6E90\uFF0C\u4E0D\u80FD\u7528\u6BCF\u4EBA\u5404\u81EA localStorage \u89E3\u51B3\u3002", "\u516C\u7F51\u8BBF\u95EE\u65F6\u8981\u786E\u8BA4\u662F\u5426\u63A5\u53D7 IP \u8BBF\u95EE\uFF0C\u57DF\u540D\u548C HTTPS \u53EF\u4F5C\u4E3A\u6B63\u5F0F\u5316\u9636\u6BB5\u3002"];
|
|
24144
|
+
}
|
|
24145
|
+
if (decision.needType === "content_marketing_site") {
|
|
24146
|
+
return ["\u5185\u5BB9\u7ECF\u5E38\u6539\u4E0D\u7B49\u4E8E\u5FC5\u987B\u5EFA\u8BBE\u540E\u53F0\uFF1B\u53EA\u6709\u7F51\u9875\u7F16\u8F91\u3001\u591A\u4EBA\u7EF4\u62A4\u6216\u8BBF\u5BA2\u63D0\u4EA4\u624D\u5347\u7EA7\u540E\u7AEF\u3002"];
|
|
24147
|
+
}
|
|
24148
|
+
if (decision.needType === "data_visualization_site") {
|
|
24149
|
+
return ["\u6BCF\u6B21\u63D0\u4F9B xlsx \u53EF\u7531 Agent \u66F4\u65B0\u9759\u6001\u6570\u636E\uFF1B\u53EA\u6709\u7F51\u9875\u4E0A\u4F20\u3001\u7EDF\u4E00\u6700\u65B0\u6570\u636E\u6216\u5386\u53F2\u7248\u672C\u624D\u5347\u7EA7\u540E\u7AEF\u3002"];
|
|
24150
|
+
}
|
|
24151
|
+
return [];
|
|
24152
|
+
}
|
|
24153
|
+
function pmGateNonGoals(decision) {
|
|
24154
|
+
if (decision.needType === "multi_user_collaboration") return ["\u6682\u4E0D\u9ED8\u8BA4\u505A\u57DF\u540D/\u5907\u6848/\u5B8C\u6574\u516C\u7F51\u8FD0\u7EF4", "\u6682\u4E0D\u505A\u590D\u6742 RBAC"];
|
|
24155
|
+
if (decision.needType === "content_marketing_site") return ["\u6682\u4E0D\u9ED8\u8BA4\u505A CMS \u540E\u53F0", "\u6682\u4E0D\u9ED8\u8BA4\u5F00\u653E\u8BBF\u5BA2\u63D0\u4EA4"];
|
|
24156
|
+
if (decision.needType === "data_visualization_site") return ["\u6682\u4E0D\u9ED8\u8BA4\u505A\u7F51\u9875\u4E0A\u4F20\u540E\u53F0", "\u6682\u4E0D\u9ED8\u8BA4\u4FDD\u5B58\u5386\u53F2\u7248\u672C"];
|
|
24157
|
+
return ["\u6682\u4E0D\u5305\u542B\u9AD8\u7EA7\u529F\u80FD"];
|
|
24158
|
+
}
|
|
24159
|
+
function pmGateSuccessCriteria(decision) {
|
|
24160
|
+
if (decision.needType === "multi_user_collaboration") {
|
|
24161
|
+
return [
|
|
24162
|
+
"\u81EA\u5DF1\u7ED9\u81EA\u5DF1\u5B89\u6392\u7684\u4EFB\u52A1\u4FDD\u5B58\u540E\u7ACB\u5373\u51FA\u73B0\u5728\u81EA\u5DF1\u7684\u65E5\u7A0B\u4E2D",
|
|
24163
|
+
"\u5B89\u6392\u7ED9\u522B\u4EBA\u65F6\u4EFB\u52A1\u8FDB\u5165\u5F85\u8BA4\u9886\u72B6\u6001",
|
|
24164
|
+
"\u5BF9\u65B9\u8BA4\u9886\u540E\u4EFB\u52A1\u8FDB\u5165\u5BF9\u65B9\u65E5\u7A0B",
|
|
24165
|
+
"\u540C\u4E00\u65F6\u95F4\u4EFB\u52A1\u80FD\u5E76\u6392\u5C55\u793A\u6216\u9AD8\u4EAE\u51B2\u7A81",
|
|
24166
|
+
"\u5237\u65B0\u540E\u4EFB\u52A1\u72B6\u6001\u4FDD\u6301\u4E00\u81F4"
|
|
24167
|
+
];
|
|
24168
|
+
}
|
|
24169
|
+
if (decision.needType === "content_marketing_site") {
|
|
24170
|
+
return [
|
|
24171
|
+
"FAQ\u3001\u7167\u7247\u3001\u4FC3\u9500\u6D3B\u52A8\u3001\u6559\u7EC3\u4FE1\u606F\u80FD\u4ECE\u5185\u5BB9\u6587\u4EF6\u6E32\u67D3",
|
|
24172
|
+
"Agent \u66F4\u65B0\u5185\u5BB9\u6587\u4EF6\u5E76\u91CD\u65B0\u90E8\u7F72\u540E\uFF0C\u9875\u9762\u5C55\u793A\u6700\u65B0\u5185\u5BB9",
|
|
24173
|
+
"\u9875\u9762\u5305\u542B\u57FA\u7840 GEO/SEO \u7ED3\u6784\u5316\u4FE1\u606F\u3001sitemap \u6216\u53EF\u7D22\u5F15\u5185\u5BB9",
|
|
24174
|
+
"\u4E0D\u51FA\u73B0\u9700\u8981\u540E\u53F0\u767B\u5F55\u624D\u80FD\u7EF4\u62A4\u7684\u9ED8\u8BA4\u6D41\u7A0B"
|
|
24175
|
+
];
|
|
24176
|
+
}
|
|
24177
|
+
if (decision.needType === "data_visualization_site") {
|
|
24178
|
+
return [
|
|
24179
|
+
"Agent \u80FD\u4ECE\u65B0\u7684 xlsx \u751F\u6210\u56FE\u8868\u6570\u636E\u6587\u4EF6",
|
|
24180
|
+
"\u9875\u9762\u8BFB\u53D6\u6700\u65B0\u6570\u636E\u6587\u4EF6\u5E76\u6E32\u67D3\u56FE\u8868",
|
|
24181
|
+
"\u66FF\u6362\u6570\u636E\u540E\u91CD\u65B0\u90E8\u7F72\u80FD\u770B\u5230\u6700\u65B0\u7ED3\u679C",
|
|
24182
|
+
"\u4E0D\u9ED8\u8BA4\u8981\u6C42\u540E\u53F0\u4E0A\u4F20\u6216\u6570\u636E\u5E93"
|
|
24183
|
+
];
|
|
24184
|
+
}
|
|
24185
|
+
return ["\u6838\u5FC3\u529F\u80FD\u6309\u786E\u8BA4\u8FB9\u754C\u5B9E\u73B0"];
|
|
24186
|
+
}
|
|
23692
24187
|
function buildRegistrationSpec(rawIdea, context, readiness) {
|
|
23693
24188
|
const formFields = parseListLike(context.form_fields, ["\u59D3\u540D", "\u624B\u673A\u53F7", "\u62A5\u540D\u4EBA\u6570", "\u5907\u6CE8"]);
|
|
23694
24189
|
const hasPhone = formFields.some((field) => field.includes("\u624B\u673A") || field.includes("\u7535\u8BDD"));
|
|
@@ -24752,6 +25247,11 @@ function extractTargetUser(text) {
|
|
|
24752
25247
|
}
|
|
24753
25248
|
return "";
|
|
24754
25249
|
}
|
|
25250
|
+
function inferLocalFirstTargetUser(text) {
|
|
25251
|
+
if (/家庭|家里|父母|老人|孩子|家人/.test(text)) return "\u5BB6\u5EAD\u81EA\u7528\u7528\u6237";
|
|
25252
|
+
if (/个人|自己用|自用|我的/.test(text)) return "\u4E2A\u4EBA\u4F7F\u7528\u8005";
|
|
25253
|
+
return "\u4E2A\u4EBA\u4F7F\u7528\u8005";
|
|
25254
|
+
}
|
|
24755
25255
|
function extractPlatform(text) {
|
|
24756
25256
|
if (text.includes("\u5C0F\u7A0B\u5E8F")) return "mini_program";
|
|
24757
25257
|
if (text.includes("app") || text.includes("App")) return "app";
|
|
@@ -24821,7 +25321,7 @@ function extractFeatures(text) {
|
|
|
24821
25321
|
return features.length > 0 ? features : ["\u6838\u5FC3\u529F\u80FD"];
|
|
24822
25322
|
}
|
|
24823
25323
|
function buildLocalFirstExtractedFeatures(text) {
|
|
24824
|
-
const genericFeatures = extractFeatures(text).filter((feature) => feature !== "\u6838\u5FC3\u529F\u80FD");
|
|
25324
|
+
const genericFeatures = extractFeatures(text).filter((feature) => feature !== "\u6838\u5FC3\u529F\u80FD" && feature !== "\u7BA1\u7406");
|
|
24825
25325
|
const signalProfile = buildLocalToolSignalProfile(text);
|
|
24826
25326
|
const features = [...genericFeatures, ...signalProfile.featureHints];
|
|
24827
25327
|
return features.length > 0 ? Array.from(new Set(features)) : ["\u6838\u5FC3\u529F\u80FD"];
|
|
@@ -24830,7 +25330,7 @@ function isNegatedKeyword(text, keyword) {
|
|
|
24830
25330
|
const escaped = keyword.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
24831
25331
|
return new RegExp(`(\u4E0D\u63A5|\u4E0D\u505A|\u4E0D\u7528|\u65E0\u9700|\u4E0D\u9700\u8981|\u6682\u4E0D|\u5148\u4E0D|\u4E0D\u8981|\u6CA1\u6709).{0,8}${escaped}`, "i").test(text);
|
|
24832
25332
|
}
|
|
24833
|
-
function buildDataModel(context, needsBackend = true, technicalProfile) {
|
|
25333
|
+
function buildDataModel(context, needsBackend = true, technicalProfile, rawIdea = "") {
|
|
24834
25334
|
if (technicalProfile?.shape === "static_page") return "\u65E0\u9700\u6570\u636E\u6301\u4E45\u5316\uFF1B\u7EAF HTML/CSS/JS \u9759\u6001\u5C55\u793A\u3002";
|
|
24835
25335
|
if (technicalProfile?.shape === "static_json_data_page") {
|
|
24836
25336
|
return [
|
|
@@ -24840,17 +25340,21 @@ function buildDataModel(context, needsBackend = true, technicalProfile) {
|
|
|
24840
25340
|
].join("\n");
|
|
24841
25341
|
}
|
|
24842
25342
|
if (technicalProfile?.shape === "local_json_import_export") {
|
|
25343
|
+
const signalProfile = buildLocalToolSignalProfile(rawIdea);
|
|
24843
25344
|
return [
|
|
24844
25345
|
"\u6D4F\u89C8\u5668\u672C\u5730\u5B58\u50A8 + JSON \u6587\u4EF6\u5BFC\u5165\u5BFC\u51FA",
|
|
24845
25346
|
"localStorage key \u793A\u4F8B\uFF1Alocal_tool_records",
|
|
24846
|
-
|
|
25347
|
+
`\u5B57\u6BB5\u5EFA\u8BAE\uFF1A${signalProfile.fieldExample}`,
|
|
25348
|
+
`JSON \u793A\u4F8B\uFF1A${buildLocalRecordJsonExample(signalProfile.recordObject, signalProfile.fieldExample)}`
|
|
24847
25349
|
].join("\n");
|
|
24848
25350
|
}
|
|
24849
25351
|
if (technicalProfile?.shape === "local_storage_tool") {
|
|
25352
|
+
const signalProfile = buildLocalToolSignalProfile(rawIdea);
|
|
24850
25353
|
return [
|
|
24851
25354
|
"\u6D4F\u89C8\u5668\u672C\u5730\u5B58\u50A8\uFF1AlocalStorage",
|
|
24852
25355
|
"localStorage key \u793A\u4F8B\uFF1Apersonal_tool_records",
|
|
24853
|
-
|
|
25356
|
+
`\u5B57\u6BB5\u5EFA\u8BAE\uFF1A${signalProfile.fieldExample}`,
|
|
25357
|
+
`\u8BB0\u5F55\u793A\u4F8B\uFF1A${buildLocalRecordJsonExample(signalProfile.recordObject, signalProfile.fieldExample)}`,
|
|
24854
25358
|
"\u65E0\u9700\u670D\u52A1\u5668\u6570\u636E\u5E93\uFF1B\u540E\u7EED\u5982\u6570\u636E\u91CF\u8F83\u5927\u53EF\u5347\u7EA7 IndexedDB\u3002"
|
|
24855
25359
|
].join("\n");
|
|
24856
25360
|
}
|
|
@@ -24861,6 +25365,37 @@ function buildDataModel(context, needsBackend = true, technicalProfile) {
|
|
|
24861
25365
|
if (!needsBackend) return "\u6D4F\u89C8\u5668\u672C\u5730\u5B58\u50A8\uFF1AlocalStorage \u6216\u5355\u4E2A JSON \u6587\u4EF6\uFF1B\u65E0\u9700\u670D\u52A1\u5668\u6570\u636E\u5E93";
|
|
24862
25366
|
return "\u5F85\u786E\u8BA4\uFF1A\u5EFA\u8BAE SQLite\uFF08MVP\uFF09\u6216 PostgreSQL\uFF08\u751F\u4EA7\uFF09";
|
|
24863
25367
|
}
|
|
25368
|
+
function buildLocalRecordJsonExample(recordObject, fieldExample) {
|
|
25369
|
+
const labels = fieldExample.split("\u3001").map((item) => item.trim()).filter(Boolean);
|
|
25370
|
+
const record2 = {
|
|
25371
|
+
id: "item-1"
|
|
25372
|
+
};
|
|
25373
|
+
for (const label of labels) {
|
|
25374
|
+
if (label.includes("\u540D")) record2.name = `\u793A\u4F8B${recordObject}`;
|
|
25375
|
+
else if (label.includes("\u6570\u91CF") || label.includes("\u5E93\u5B58")) record2.quantity = 1;
|
|
25376
|
+
else if (label.includes("\u6709\u6548\u671F") || label.includes("\u5230\u671F")) record2.expireDate = "2026-12-31";
|
|
25377
|
+
else if (label.includes("\u5206\u7C7B")) record2.category = "\u9ED8\u8BA4\u5206\u7C7B";
|
|
25378
|
+
else if (label.includes("\u4F4D\u7F6E") || label.includes("\u5730\u70B9") || label.includes("\u5730\u5740")) record2.location = "\u9ED8\u8BA4\u4F4D\u7F6E";
|
|
25379
|
+
else if (label.includes("\u72B6\u6001")) record2.status = "normal";
|
|
25380
|
+
else if (label.includes("\u91D1\u989D") || label.includes("\u4EF7\u683C")) record2.amount = 0;
|
|
25381
|
+
else if (label.includes("\u94FE\u63A5")) record2.url = "";
|
|
25382
|
+
else if (label.includes("\u5907\u6CE8")) record2.note = "\u5907\u6CE8";
|
|
25383
|
+
}
|
|
25384
|
+
record2.updatedAt = "2026-06-23T00:00:00.000Z";
|
|
25385
|
+
return JSON.stringify(record2);
|
|
25386
|
+
}
|
|
25387
|
+
function buildLocalFirstSuccessCriteria(text) {
|
|
25388
|
+
const signalProfile = buildLocalToolSignalProfile(text);
|
|
25389
|
+
const items = [...signalProfile.acceptanceItems];
|
|
25390
|
+
if (signalProfile.featureHints.includes("\u65B0\u589E/\u7F16\u8F91/\u5220\u9664")) {
|
|
25391
|
+
items.push(`${signalProfile.recordObject}\u8BB0\u5F55\u652F\u6301\u65B0\u589E\u3001\u7F16\u8F91\u3001\u5220\u9664\uFF0C\u64CD\u4F5C\u540E\u5217\u8868\u7ACB\u5373\u66F4\u65B0`);
|
|
25392
|
+
}
|
|
25393
|
+
if (signalProfile.featureHints.includes("\u641C\u7D22/\u7B5B\u9009/\u5206\u7C7B")) {
|
|
25394
|
+
items.push("\u641C\u7D22\u3001\u5206\u7C7B\u6216\u72B6\u6001\u7B5B\u9009\u80FD\u51C6\u786E\u7F29\u5C0F\u5217\u8868\uFF0C\u6E05\u7A7A\u7B5B\u9009\u540E\u6062\u590D\u5168\u90E8\u8BB0\u5F55");
|
|
25395
|
+
}
|
|
25396
|
+
items.push("\u5237\u65B0\u9875\u9762\u540E\uFF0C\u5DF2\u4FDD\u5B58\u8BB0\u5F55\u4ECD\u80FD\u4ECE localStorage \u6062\u590D");
|
|
25397
|
+
return Array.from(new Set(items));
|
|
25398
|
+
}
|
|
24864
25399
|
function buildArchitectureRecommendation(context, needsBackend, technicalProfile) {
|
|
24865
25400
|
if (technicalProfile?.shape === "static_page") return "\u7EAF\u524D\u7AEF\u67B6\u6784";
|
|
24866
25401
|
if (technicalProfile?.shape === "local_storage_tool") return "\u7EAF\u524D\u7AEF\u672C\u5730\u5DE5\u5177\uFF1AHTML/CSS/JS + localStorage\uFF1B\u9002\u5408\u4E2A\u4EBA\u8BB0\u5F55\u3001\u6E05\u5355\u3001\u63D0\u9192\u548C\u53F0\u8D26\u3002";
|
|
@@ -25035,7 +25570,8 @@ var ArchitectureDecideOutputSchema = external_exports.object({
|
|
|
25035
25570
|
domain: external_exports.string().optional(),
|
|
25036
25571
|
mvpSuggestion: external_exports.string(),
|
|
25037
25572
|
productionSuggestion: external_exports.string(),
|
|
25038
|
-
reasoning: external_exports.array(external_exports.string())
|
|
25573
|
+
reasoning: external_exports.array(external_exports.string()),
|
|
25574
|
+
pmIntentDecision: PmIntentDecisionSchema.optional()
|
|
25039
25575
|
}),
|
|
25040
25576
|
technicalProfile: TechnicalProfileSchema.optional(),
|
|
25041
25577
|
riskLevel: external_exports.enum(["low", "medium", "high"]),
|
|
@@ -25170,6 +25706,74 @@ var architectureRules_default = {
|
|
|
25170
25706
|
};
|
|
25171
25707
|
|
|
25172
25708
|
// src/core/architectureEngine.ts
|
|
25709
|
+
function buildPmGateArchitectureDecision(decision, technicalProfile) {
|
|
25710
|
+
if (decision.needType === "multi_user_collaboration") {
|
|
25711
|
+
return {
|
|
25712
|
+
canBeFrontendOnly: false,
|
|
25713
|
+
needBackend: true,
|
|
25714
|
+
needSeparation: false,
|
|
25715
|
+
recommendedDatabase: "SQLite\uFF08MVP\uFF09",
|
|
25716
|
+
needAuth: true,
|
|
25717
|
+
needAdmin: false,
|
|
25718
|
+
needLogging: true,
|
|
25719
|
+
paymentRisk: false,
|
|
25720
|
+
aiKeyRisk: false,
|
|
25721
|
+
capacityRisk: false,
|
|
25722
|
+
domain: "generic",
|
|
25723
|
+
mvpSuggestion: decision.accessTopology === "lan_only" ? "\u5C40\u57DF\u7F51 Node + SQLite\uFF1A\u4E00\u53F0\u7535\u8111/NAS \u8FD0\u884C\u670D\u52A1\uFF0C\u6210\u5458\u901A\u8FC7\u5C40\u57DF\u7F51 IP \u8BBF\u95EE" : "Node + SQLite\uFF1A\u56FA\u5B9A\u51E0\u4EBA\u5916\u51FA\u8BBF\u95EE\u65F6\u53EF\u5148\u7528\u4F4E\u4EF7\u516C\u7F51 VPS + IP \u5730\u5740\u8DD1\u901A",
|
|
25724
|
+
productionSuggestion: "\u540E\u7EED\u518D\u8865\u57DF\u540D\u3001HTTPS\u3001\u5907\u4EFD\u548C\u66F4\u5B8C\u6574\u8D26\u53F7\u6743\u9650\uFF1B\u56FD\u5185\u516C\u5F00\u57DF\u540D\u6309\u5B9E\u9645\u60C5\u51B5\u8003\u8651\u5907\u6848",
|
|
25725
|
+
reasoning: [
|
|
25726
|
+
"\u591A\u4EBA\u3001\u534F\u4F5C\u3001\u8BA4\u9886\u548C\u8DE8\u7528\u6237\u65E5\u7A0B\u662F\u8FD0\u884C\u65F6\u5171\u4EAB\u6570\u636E\uFF0C\u4E0D\u80FD\u7528\u6BCF\u4EBA\u672C\u5730 localStorage \u89E3\u51B3\u3002",
|
|
25727
|
+
"\u591A\u4EBA\u534F\u4F5C\u4E0D\u76F4\u63A5\u7B49\u4E8E\u6B63\u5F0F\u516C\u7F51 SaaS\uFF1B\u5148\u786E\u8BA4\u5C40\u57DF\u7F51\u662F\u5426\u8DB3\u591F\u3002"
|
|
25728
|
+
],
|
|
25729
|
+
technicalProfile,
|
|
25730
|
+
pmIntentDecision: decision
|
|
25731
|
+
};
|
|
25732
|
+
}
|
|
25733
|
+
if (decision.needType === "content_marketing_site") {
|
|
25734
|
+
const needsBackend = decision.maintenanceMode === "web_admin" || decision.maintenanceMode === "visitor_submission";
|
|
25735
|
+
return {
|
|
25736
|
+
canBeFrontendOnly: !needsBackend,
|
|
25737
|
+
needBackend: needsBackend,
|
|
25738
|
+
needSeparation: false,
|
|
25739
|
+
recommendedDatabase: needsBackend ? "SQLite\uFF08MVP\uFF09" : "\u65E0\u9700\u670D\u52A1\u5668\u6570\u636E\u5E93\uFF1B\u4F7F\u7528\u9759\u6001\u5185\u5BB9\u6587\u4EF6",
|
|
25740
|
+
needAuth: decision.maintenanceMode === "web_admin",
|
|
25741
|
+
needAdmin: decision.maintenanceMode === "web_admin",
|
|
25742
|
+
needLogging: needsBackend,
|
|
25743
|
+
paymentRisk: false,
|
|
25744
|
+
aiKeyRisk: false,
|
|
25745
|
+
capacityRisk: false,
|
|
25746
|
+
domain: "generic",
|
|
25747
|
+
mvpSuggestion: needsBackend ? "\u8F7B\u540E\u53F0 CMS + SQLite\uFF0C\u7528\u4E8E\u7F51\u9875\u91CC\u7F16\u8F91\u5185\u5BB9\u548C\u4E0A\u4F20\u56FE\u7247" : "\u9759\u6001\u5185\u5BB9\u8425\u9500\u7AD9 + data.json/markdown/assets\uFF0C\u7531 Agent \u66F4\u65B0\u5185\u5BB9\u5E76\u91CD\u65B0\u90E8\u7F72",
|
|
25748
|
+
productionSuggestion: "\u9700\u8981\u591A\u4EBA\u7F51\u9875\u7EF4\u62A4\u6216\u8BBF\u5BA2\u63D0\u4EA4\u65F6\u518D\u5347\u7EA7\u540E\u53F0\u3001\u5BA1\u6838\u3001\u9632\u5783\u573E\u548C\u901A\u77E5",
|
|
25749
|
+
reasoning: ["\u5185\u5BB9\u7ECF\u5E38\u6539\u4E0D\u76F4\u63A5\u89E6\u53D1\u540E\u53F0\uFF1B\u5148\u770B\u7EF4\u62A4\u65B9\u5F0F\u662F\u4E0D\u662F Agent-assisted\u3002"],
|
|
25750
|
+
technicalProfile,
|
|
25751
|
+
pmIntentDecision: decision
|
|
25752
|
+
};
|
|
25753
|
+
}
|
|
25754
|
+
if (decision.needType === "data_visualization_site") {
|
|
25755
|
+
const needsBackend = decision.maintenanceMode === "web_admin" || decision.maintenanceMode === "visitor_submission";
|
|
25756
|
+
return {
|
|
25757
|
+
canBeFrontendOnly: !needsBackend,
|
|
25758
|
+
needBackend: needsBackend,
|
|
25759
|
+
needSeparation: false,
|
|
25760
|
+
recommendedDatabase: needsBackend ? "SQLite\uFF08MVP\uFF09" : "\u65E0\u9700\u670D\u52A1\u5668\u6570\u636E\u5E93\uFF1B\u4F7F\u7528\u9759\u6001 chart-data.json",
|
|
25761
|
+
needAuth: needsBackend,
|
|
25762
|
+
needAdmin: needsBackend,
|
|
25763
|
+
needLogging: needsBackend,
|
|
25764
|
+
paymentRisk: false,
|
|
25765
|
+
aiKeyRisk: false,
|
|
25766
|
+
capacityRisk: false,
|
|
25767
|
+
domain: "generic",
|
|
25768
|
+
mvpSuggestion: needsBackend ? "\u4E0A\u4F20\u63A5\u53E3 + xlsx \u89E3\u6790 + SQLite/\u6587\u4EF6\u5B58\u50A8\uFF0C\u6240\u6709\u8BBF\u5BA2\u8BFB\u53D6\u6700\u65B0\u56FE\u8868\u6570\u636E" : "Agent \u89E3\u6790 xlsx \u751F\u6210 JSON\uFF0C\u9759\u6001\u56FE\u8868\u7AD9\u8BFB\u53D6 JSON \u6E32\u67D3",
|
|
25769
|
+
productionSuggestion: "\u9700\u8981\u5386\u53F2\u7248\u672C\u3001\u591A\u4EBA\u4E0A\u4F20\u6216\u6743\u9650\u65F6\u518D\u8865\u540E\u7AEF\u548C\u6570\u636E\u5E93",
|
|
25770
|
+
reasoning: ["\u5B9A\u671F\u63D0\u4F9B xlsx \u4E0D\u7B49\u4E8E\u5FC5\u987B\u540E\u53F0\uFF1BAgent-assisted \u66F4\u65B0\u53EF\u5148\u9759\u6001\u5316\u3002"],
|
|
25771
|
+
technicalProfile,
|
|
25772
|
+
pmIntentDecision: decision
|
|
25773
|
+
};
|
|
25774
|
+
}
|
|
25775
|
+
return null;
|
|
25776
|
+
}
|
|
25173
25777
|
function decideArchitecture(productType, platform, features, commercialIntent, expectedUsers) {
|
|
25174
25778
|
const featureText = features.join(" ");
|
|
25175
25779
|
const allText = `${productType} ${featureText}`;
|
|
@@ -25199,6 +25803,12 @@ function decideArchitecture(productType, platform, features, commercialIntent, e
|
|
|
25199
25803
|
expected_users: expectedUsers,
|
|
25200
25804
|
commercial_intent: commercialIntent
|
|
25201
25805
|
});
|
|
25806
|
+
const pmIntentDecision = decidePmIntent(allText, {
|
|
25807
|
+
expected_users: expectedUsers,
|
|
25808
|
+
commercial_intent: commercialIntent
|
|
25809
|
+
});
|
|
25810
|
+
const pmGateArchitecture2 = domain === "generic" ? buildPmGateArchitectureDecision(pmIntentDecision, technicalProfile) : null;
|
|
25811
|
+
if (pmGateArchitecture2) return pmGateArchitecture2;
|
|
25202
25812
|
const contentCommunityDomain = domain === "content_community";
|
|
25203
25813
|
const singleUserCrm = domain === "crm" && isSingleUserCrmContext(allText, { expected_users: expectedUsers });
|
|
25204
25814
|
const personalLocalSignal = domain === "generic" && expectedUsers !== "enterprise" && expectedUsers !== "massive" && !commercialIntent && isLocalFirstProfile(technicalProfile);
|
|
@@ -26027,6 +26637,7 @@ var AcceptanceGenerateOutputSchema = external_exports.object({
|
|
|
26027
26637
|
productType: external_exports.string(),
|
|
26028
26638
|
platform: external_exports.string(),
|
|
26029
26639
|
technicalProfile: TechnicalProfileSchema.optional(),
|
|
26640
|
+
pmIntentDecision: PmIntentDecisionSchema.optional(),
|
|
26030
26641
|
categories: external_exports.array(
|
|
26031
26642
|
external_exports.object({
|
|
26032
26643
|
category: external_exports.string(),
|
|
@@ -26151,15 +26762,36 @@ function generateAcceptance(productType, features, platform, hasBackend, hasPaym
|
|
|
26151
26762
|
has_auth: hasAuth
|
|
26152
26763
|
});
|
|
26153
26764
|
const featureText = buildFeatureText(productType, features);
|
|
26765
|
+
const pmIntentDecision = decidePmIntent(featureText, {
|
|
26766
|
+
has_backend: hasBackend,
|
|
26767
|
+
has_payment: hasPayment,
|
|
26768
|
+
has_auth: hasAuth
|
|
26769
|
+
});
|
|
26154
26770
|
const domain = classifyProductDomain(productType, { features }).domain;
|
|
26155
26771
|
const inferredBackend = hasBackend || technicalProfile.needsBackend;
|
|
26156
26772
|
const inferredAuth = hasAuth || technicalProfile.needsAuth;
|
|
26157
26773
|
const inferredPayment = hasPayment || technicalProfile.blockers.some((blocker) => blocker.includes("\u652F\u4ED8"));
|
|
26774
|
+
if (domain === "generic" && ["multi_user_collaboration", "content_marketing_site", "data_visualization_site"].includes(pmIntentDecision.needType)) {
|
|
26775
|
+
return {
|
|
26776
|
+
productType,
|
|
26777
|
+
platform,
|
|
26778
|
+
technicalProfile,
|
|
26779
|
+
pmIntentDecision,
|
|
26780
|
+
categories: buildPmGateAcceptanceCategories(pmIntentDecision),
|
|
26781
|
+
definitionOfDone: [
|
|
26782
|
+
"\u6838\u5FC3\u8FB9\u754C\u5DF2\u6309 PM Gate \u786E\u8BA4",
|
|
26783
|
+
"\u684C\u9762\u7AEF\u548C\u79FB\u52A8\u7AEF\u9A8C\u6536\u901A\u8FC7",
|
|
26784
|
+
"\u63A7\u5236\u53F0\u65E0\u660E\u663E\u62A5\u9519",
|
|
26785
|
+
"\u65E0 P0/P1 Bug"
|
|
26786
|
+
]
|
|
26787
|
+
};
|
|
26788
|
+
}
|
|
26158
26789
|
if (isStaticDisplaySite(productType, features, platform, inferredBackend, inferredPayment, inferredAuth)) {
|
|
26159
26790
|
return {
|
|
26160
26791
|
productType,
|
|
26161
26792
|
platform,
|
|
26162
26793
|
technicalProfile,
|
|
26794
|
+
pmIntentDecision,
|
|
26163
26795
|
categories: buildStaticDisplayAcceptanceCategories(),
|
|
26164
26796
|
definitionOfDone: [
|
|
26165
26797
|
"\u6240\u6709\u5360\u4F4D\u5185\u5BB9\u5DF2\u66FF\u6362\u4E3A\u771F\u5B9E\u5185\u5BB9",
|
|
@@ -26184,6 +26816,7 @@ function generateAcceptance(productType, features, platform, hasBackend, hasPaym
|
|
|
26184
26816
|
productType,
|
|
26185
26817
|
platform,
|
|
26186
26818
|
technicalProfile,
|
|
26819
|
+
pmIntentDecision,
|
|
26187
26820
|
categories: buildLocalFirstAcceptanceCategories(technicalProfile, productType, features),
|
|
26188
26821
|
definitionOfDone: [
|
|
26189
26822
|
"\u6838\u5FC3\u529F\u80FD\u6309\u9700\u6C42\u5B9E\u73B0",
|
|
@@ -26566,10 +27199,86 @@ function generateAcceptance(productType, features, platform, hasBackend, hasPaym
|
|
|
26566
27199
|
productType,
|
|
26567
27200
|
platform,
|
|
26568
27201
|
technicalProfile,
|
|
27202
|
+
pmIntentDecision,
|
|
26569
27203
|
categories,
|
|
26570
27204
|
definitionOfDone: [...acceptanceRules_default.definition_of_done]
|
|
26571
27205
|
};
|
|
26572
27206
|
}
|
|
27207
|
+
function buildPmGateAcceptanceCategories(decision) {
|
|
27208
|
+
if (decision.needType === "multi_user_collaboration") {
|
|
27209
|
+
return [
|
|
27210
|
+
{
|
|
27211
|
+
category: "\u591A\u4EBA\u534F\u4F5C\u6D41\u7A0B\u9A8C\u6536",
|
|
27212
|
+
items: [
|
|
27213
|
+
"\u81EA\u5DF1\u7ED9\u81EA\u5DF1\u5B89\u6392\u7684\u4EFB\u52A1\u4FDD\u5B58\u540E\u7ACB\u5373\u8FDB\u5165\u81EA\u5DF1\u7684\u65E5\u7A0B",
|
|
27214
|
+
"\u7ED9\u5BA4\u53CB\u6216\u6210\u5458\u5B89\u6392\u7684\u4EFB\u52A1\u5148\u8FDB\u5165\u5F85\u8BA4\u9886\u72B6\u6001\uFF0C\u4E0D\u80FD\u76F4\u63A5\u53D8\u6210\u5BF9\u65B9\u5DF2\u786E\u8BA4\u65E5\u7A0B",
|
|
27215
|
+
"\u5BF9\u65B9\u8BA4\u9886\u4EFB\u52A1\u540E\uFF0C\u4EFB\u52A1\u8FDB\u5165\u5BF9\u65B9\u65E5\u7A0B\u5E76\u4FDD\u7559\u8BA4\u9886\u65F6\u95F4",
|
|
27216
|
+
"\u4EFB\u52A1\u5B8C\u6210\u3001\u53D6\u6D88\u6216\u91CD\u65B0\u5206\u914D\u540E\uFF0C\u6240\u6709\u6210\u5458\u5237\u65B0\u9875\u9762\u770B\u5230\u4E00\u81F4\u72B6\u6001"
|
|
27217
|
+
]
|
|
27218
|
+
},
|
|
27219
|
+
{
|
|
27220
|
+
category: "\u65E5\u7A0B\u4E0E\u8BBF\u95EE\u8FB9\u754C\u9A8C\u6536",
|
|
27221
|
+
items: [
|
|
27222
|
+
"\u540C\u4E00\u65F6\u95F4\u6BB5\u7684\u4EFB\u52A1\u6309\u5DF2\u786E\u8BA4\u89C4\u5219\u5E76\u6392\u5C55\u793A\u3001\u9AD8\u4EAE\u51B2\u7A81\u6216\u963B\u6B62\u5B89\u6392",
|
|
27223
|
+
"\u8BBF\u95EE\u65B9\u5F0F\u5FC5\u987B\u5728\u5C40\u57DF\u7F51\u3001\u672C\u673A\u516C\u7F51 IP \u6216\u57DF\u540D HTTPS \u4E2D\u660E\u786E\u4E00\u79CD",
|
|
27224
|
+
"\u591A\u4EBA\u8FD0\u884C\u65F6\u534F\u4F5C\u6570\u636E\u4E0D\u5F97\u5206\u522B\u4FDD\u5B58\u5728\u5404\u81EA\u6D4F\u89C8\u5668 localStorage \u91CC",
|
|
27225
|
+
"SQLite \u6570\u636E\u6587\u4EF6\u6216\u7B49\u4EF7\u6301\u4E45\u5316\u6587\u4EF6\u91CD\u542F\u670D\u52A1\u540E\u4ECD\u80FD\u6062\u590D\u4EFB\u52A1\u548C\u6210\u5458\u6570\u636E"
|
|
27226
|
+
]
|
|
27227
|
+
}
|
|
27228
|
+
];
|
|
27229
|
+
}
|
|
27230
|
+
if (decision.needType === "content_marketing_site") {
|
|
27231
|
+
return [
|
|
27232
|
+
{
|
|
27233
|
+
category: "\u5185\u5BB9\u8425\u9500\u7AD9\u9A8C\u6536",
|
|
27234
|
+
items: [
|
|
27235
|
+
"FAQ\u3001\u7167\u7247\u3001\u4FC3\u9500\u6D3B\u52A8\u3001\u6559\u7EC3\u6216\u56E2\u961F\u4FE1\u606F\u80FD\u4ECE\u5185\u5BB9\u6587\u4EF6\u6E32\u67D3\u5230\u9875\u9762",
|
|
27236
|
+
"Agent \u66F4\u65B0\u5185\u5BB9\u6587\u4EF6\u5E76\u91CD\u65B0\u90E8\u7F72\u540E\uFF0C\u7EBF\u4E0A\u9875\u9762\u5C55\u793A\u6700\u65B0\u5185\u5BB9",
|
|
27237
|
+
"\u9875\u9762\u5305\u542B\u9762\u5411\u672C\u5730\u66DD\u5149\u7684\u6807\u9898\u3001\u63CF\u8FF0\u3001\u7ED3\u6784\u5316 FAQ \u548C sitemap \u57FA\u7840\u4FE1\u606F",
|
|
27238
|
+
"\u79FB\u52A8\u7AEF\u9996\u5C4F\u3001\u56FE\u7247\u5217\u8868\u3001\u6D3B\u52A8\u4FE1\u606F\u548C\u8054\u7CFB\u65B9\u5F0F\u5747\u6B63\u5E38\u5C55\u793A"
|
|
27239
|
+
]
|
|
27240
|
+
},
|
|
27241
|
+
{
|
|
27242
|
+
category: "\u7EF4\u62A4\u8FB9\u754C\u9A8C\u6536",
|
|
27243
|
+
items: [
|
|
27244
|
+
"\u5185\u5BB9\u7ECF\u5E38\u4FEE\u6539\u65F6\u9ED8\u8BA4\u6309 Agent-assisted \u5185\u5BB9\u6587\u4EF6\u7EF4\u62A4\uFF0C\u4E0D\u5F3A\u5236\u751F\u6210 CMS \u540E\u53F0",
|
|
27245
|
+
"\u53EA\u6709\u7528\u6237\u660E\u786E\u8981\u6C42\u7F51\u9875\u7F16\u8F91\u3001\u56FE\u7247\u4E0A\u4F20\u3001\u591A\u4EBA\u7EF4\u62A4\u6216\u8BBF\u5BA2\u63D0\u4EA4\u65F6\u624D\u5F15\u5165\u540E\u7AEF",
|
|
27246
|
+
"\u8BBF\u5BA2\u53CD\u9988\u6216\u9884\u7EA6\u63D0\u4EA4\u5982\u679C\u8FDB\u5165 MVP\uFF0C\u5FC5\u987B\u6709\u540E\u7AEF\u4FDD\u5B58\u3001\u5BA1\u6838\u6216\u9632\u5783\u573E\u7B56\u7565"
|
|
27247
|
+
]
|
|
27248
|
+
}
|
|
27249
|
+
];
|
|
27250
|
+
}
|
|
27251
|
+
if (decision.needType === "data_visualization_site") {
|
|
27252
|
+
return [
|
|
27253
|
+
{
|
|
27254
|
+
category: "\u6570\u636E\u56FE\u8868\u7AD9\u9A8C\u6536",
|
|
27255
|
+
items: [
|
|
27256
|
+
"Agent \u80FD\u4ECE\u65B0 xlsx \u6216 CSV \u751F\u6210\u9875\u9762\u8BFB\u53D6\u7684\u56FE\u8868\u6570\u636E\u6587\u4EF6",
|
|
27257
|
+
"\u9875\u9762\u8BFB\u53D6\u6700\u65B0\u6570\u636E\u6587\u4EF6\u540E\uFF0C\u56FE\u8868\u3001\u6307\u6807\u5361\u548C\u8868\u683C\u7ED3\u679C\u4E00\u81F4",
|
|
27258
|
+
"\u66FF\u6362\u6570\u636E\u5E76\u91CD\u65B0\u90E8\u7F72\u540E\uFF0C\u7EBF\u4E0A\u9875\u9762\u5C55\u793A\u6700\u65B0\u7ED3\u679C",
|
|
27259
|
+
"\u6570\u636E\u4E3A\u7A7A\u3001\u5B57\u6BB5\u7F3A\u5931\u6216\u683C\u5F0F\u9519\u8BEF\u65F6\u9875\u9762\u6709\u660E\u786E\u63D0\u793A\uFF0C\u4E0D\u663E\u793A\u65E7\u7ED3\u679C"
|
|
27260
|
+
]
|
|
27261
|
+
},
|
|
27262
|
+
{
|
|
27263
|
+
category: "\u6570\u636E\u66F4\u65B0\u8FB9\u754C\u9A8C\u6536",
|
|
27264
|
+
items: [
|
|
27265
|
+
"\u9ED8\u8BA4\u4E0D\u8981\u6C42\u540E\u53F0\u4E0A\u4F20\u3001\u6570\u636E\u5E93\u6216\u767B\u5F55\u6743\u9650",
|
|
27266
|
+
"\u53EA\u6709\u7528\u6237\u660E\u786E\u8981\u6C42\u7F51\u9875\u4E0A\u4F20\u3001\u591A\u4EBA\u4E0A\u4F20\u3001\u5386\u53F2\u7248\u672C\u6216\u6743\u9650\u63A7\u5236\u65F6\u624D\u5347\u7EA7\u540E\u7AEF",
|
|
27267
|
+
"\u5982\u679C\u516C\u5F00\u5C55\u793A\uFF0C\u90E8\u7F72\u5730\u5740\u548C\u6570\u636E\u8131\u654F\u8FB9\u754C\u5FC5\u987B\u660E\u786E"
|
|
27268
|
+
]
|
|
27269
|
+
}
|
|
27270
|
+
];
|
|
27271
|
+
}
|
|
27272
|
+
return [
|
|
27273
|
+
{
|
|
27274
|
+
category: "PM Gate \u9A8C\u6536",
|
|
27275
|
+
items: [
|
|
27276
|
+
"\u4F7F\u7528\u8005\u3001\u7EF4\u62A4\u65B9\u5F0F\u548C\u8BBF\u95EE\u65B9\u5F0F\u5DF2\u786E\u8BA4",
|
|
27277
|
+
"MVP \u6280\u672F\u65B9\u6848\u6CA1\u6709\u8D85\u51FA\u5DF2\u786E\u8BA4\u8FB9\u754C"
|
|
27278
|
+
]
|
|
27279
|
+
}
|
|
27280
|
+
];
|
|
27281
|
+
}
|
|
26573
27282
|
function hasFeatureSignal(productType, features, signals) {
|
|
26574
27283
|
const text = buildFeatureText(productType, features).toLowerCase();
|
|
26575
27284
|
return signals.some((signal) => text.includes(signal.toLowerCase()));
|
|
@@ -26895,6 +27604,7 @@ var ProductSpecAssistOutputSchema = external_exports.object({
|
|
|
26895
27604
|
executed: external_exports.boolean(),
|
|
26896
27605
|
result: external_exports.union([
|
|
26897
27606
|
SpecInterrogateOutputSchema,
|
|
27607
|
+
SpecCompileOutputSchema,
|
|
26898
27608
|
UiTranslateOutputSchema,
|
|
26899
27609
|
DebugGuideOutputSchema,
|
|
26900
27610
|
ArchitectureDecideOutputSchema
|
|
@@ -26903,6 +27613,7 @@ var ProductSpecAssistOutputSchema = external_exports.object({
|
|
|
26903
27613
|
type: external_exports.enum([
|
|
26904
27614
|
"answer_questions",
|
|
26905
27615
|
"compile_spec",
|
|
27616
|
+
"confirm_spec",
|
|
26906
27617
|
"translate_ui",
|
|
26907
27618
|
"provide_debug_info",
|
|
26908
27619
|
"review_launch_readiness",
|
|
@@ -26912,6 +27623,7 @@ var ProductSpecAssistOutputSchema = external_exports.object({
|
|
|
26912
27623
|
suggestedTool: external_exports.string().optional()
|
|
26913
27624
|
}),
|
|
26914
27625
|
technicalProfile: TechnicalProfileSchema.optional(),
|
|
27626
|
+
pmIntentDecision: PmIntentDecisionSchema.optional(),
|
|
26915
27627
|
quickQuestions: external_exports.array(QuickQuestionSchema),
|
|
26916
27628
|
agentGuidance: external_exports.array(external_exports.string())
|
|
26917
27629
|
});
|
|
@@ -26977,6 +27689,276 @@ function isExplicitLaunchInquiry(text) {
|
|
|
26977
27689
|
return launchSignals.some((kw) => text.includes(kw)) && inquirySignals.some((kw) => text.includes(kw)) && !debugSignals.some((kw) => text.includes(kw));
|
|
26978
27690
|
}
|
|
26979
27691
|
|
|
27692
|
+
// src/core/remotePmIntentGate.ts
|
|
27693
|
+
var import_node_crypto = require("node:crypto");
|
|
27694
|
+
function shouldUseRemoteGate(local, mode = process.env.PRODUCT_SPEC_REMOTE_GATE_MODE || "auto") {
|
|
27695
|
+
if (mode === "off") return false;
|
|
27696
|
+
if (!process.env.PRODUCT_SPEC_REMOTE_GATE_URL) return false;
|
|
27697
|
+
if (mode === "force") return true;
|
|
27698
|
+
return local.confidence === "low" || local.needType === "unknown" || local.technicalShape === "unknown" || hasRouteShapeConflict(local);
|
|
27699
|
+
}
|
|
27700
|
+
async function callRemotePmIntentGate(message, context, localDecision) {
|
|
27701
|
+
if (!shouldUseRemoteGate(localDecision)) return null;
|
|
27702
|
+
const url = process.env.PRODUCT_SPEC_REMOTE_GATE_URL;
|
|
27703
|
+
if (!url) return null;
|
|
27704
|
+
const controller = new AbortController();
|
|
27705
|
+
const timeout = Number(process.env.PRODUCT_SPEC_REMOTE_GATE_TIMEOUT_MS || 2500);
|
|
27706
|
+
const timer = setTimeout(() => controller.abort(), timeout);
|
|
27707
|
+
try {
|
|
27708
|
+
const response = await fetch(url, {
|
|
27709
|
+
method: "POST",
|
|
27710
|
+
headers: {
|
|
27711
|
+
"content-type": "application/json",
|
|
27712
|
+
...process.env.PRODUCT_SPEC_REMOTE_GATE_TOKEN ? { authorization: `Bearer ${process.env.PRODUCT_SPEC_REMOTE_GATE_TOKEN}` } : {},
|
|
27713
|
+
"x-product-spec-telemetry": process.env.PRODUCT_SPEC_TELEMETRY || "off"
|
|
27714
|
+
},
|
|
27715
|
+
body: JSON.stringify({
|
|
27716
|
+
message: truncateForRemote(message),
|
|
27717
|
+
context,
|
|
27718
|
+
packageVersion: process.env.npm_package_version,
|
|
27719
|
+
client: "product-spec-mcp",
|
|
27720
|
+
messageHash: hashMessage(message),
|
|
27721
|
+
ruleDecision: summarizeDecision(localDecision),
|
|
27722
|
+
choices: {
|
|
27723
|
+
needType: [
|
|
27724
|
+
"static_display",
|
|
27725
|
+
"personal_local_tool",
|
|
27726
|
+
"multi_user_collaboration",
|
|
27727
|
+
"content_marketing_site",
|
|
27728
|
+
"data_visualization_site",
|
|
27729
|
+
"transaction_workflow",
|
|
27730
|
+
"content_knowledge",
|
|
27731
|
+
"ai_automation",
|
|
27732
|
+
"unknown"
|
|
27733
|
+
],
|
|
27734
|
+
usageScope: ["self", "fixed_group", "public_audience", "unknown"],
|
|
27735
|
+
maintenanceMode: [
|
|
27736
|
+
"agent_assisted",
|
|
27737
|
+
"manual_files",
|
|
27738
|
+
"web_admin",
|
|
27739
|
+
"visitor_submission",
|
|
27740
|
+
"runtime_collaboration",
|
|
27741
|
+
"unknown"
|
|
27742
|
+
],
|
|
27743
|
+
accessTopology: ["single_device", "lan_only", "internet_ip", "public_domain", "unknown"]
|
|
27744
|
+
}
|
|
27745
|
+
}),
|
|
27746
|
+
signal: controller.signal
|
|
27747
|
+
});
|
|
27748
|
+
if (!response.ok) {
|
|
27749
|
+
return {
|
|
27750
|
+
decision: localDecision,
|
|
27751
|
+
meta: { used: false, fallbackReason: `remote_http_${response.status}` }
|
|
27752
|
+
};
|
|
27753
|
+
}
|
|
27754
|
+
const payload = await response.json();
|
|
27755
|
+
if (!payload.decision) {
|
|
27756
|
+
return {
|
|
27757
|
+
decision: localDecision,
|
|
27758
|
+
meta: { used: false, fallbackReason: "remote_missing_decision" }
|
|
27759
|
+
};
|
|
27760
|
+
}
|
|
27761
|
+
const sanitized = sanitizeRemoteDecision(payload.decision);
|
|
27762
|
+
if (!sanitized) {
|
|
27763
|
+
return {
|
|
27764
|
+
decision: localDecision,
|
|
27765
|
+
meta: { used: false, fallbackReason: "remote_invalid_schema" }
|
|
27766
|
+
};
|
|
27767
|
+
}
|
|
27768
|
+
const merged = mergeRemoteDecision(localDecision, sanitized);
|
|
27769
|
+
return {
|
|
27770
|
+
decision: merged,
|
|
27771
|
+
meta: {
|
|
27772
|
+
used: payload.llmGate?.used ?? true,
|
|
27773
|
+
provider: payload.llmGate?.provider,
|
|
27774
|
+
model: payload.llmGate?.model,
|
|
27775
|
+
cacheHit: payload.llmGate?.cacheHit,
|
|
27776
|
+
promptTokensApprox: payload.llmGate?.promptTokensApprox,
|
|
27777
|
+
completionTokensApprox: payload.llmGate?.completionTokensApprox,
|
|
27778
|
+
rateLimit: payload.rateLimit
|
|
27779
|
+
}
|
|
27780
|
+
};
|
|
27781
|
+
} catch (error2) {
|
|
27782
|
+
return {
|
|
27783
|
+
decision: localDecision,
|
|
27784
|
+
meta: {
|
|
27785
|
+
used: false,
|
|
27786
|
+
fallbackReason: error2 instanceof Error ? error2.name : "remote_error"
|
|
27787
|
+
}
|
|
27788
|
+
};
|
|
27789
|
+
} finally {
|
|
27790
|
+
clearTimeout(timer);
|
|
27791
|
+
}
|
|
27792
|
+
}
|
|
27793
|
+
function mergeRemoteDecision(local, remote) {
|
|
27794
|
+
const needType = remote.bestGate || remote.needType || local.needType;
|
|
27795
|
+
const draft = {
|
|
27796
|
+
...local,
|
|
27797
|
+
...remote,
|
|
27798
|
+
needType,
|
|
27799
|
+
source: "merged",
|
|
27800
|
+
strongSignals: mergeStrings(local.strongSignals, remote.strongSignals),
|
|
27801
|
+
weakSignals: mergeStrings(local.weakSignals, remote.weakSignals),
|
|
27802
|
+
coreObjects: mergeStrings(local.coreObjects, remote.coreObjects),
|
|
27803
|
+
states: mergeStrings(local.states, remote.states),
|
|
27804
|
+
actions: mergeStrings(local.actions, remote.actions),
|
|
27805
|
+
mustNotUse: mergeStrings(local.mustNotUse, remote.mustNotUse),
|
|
27806
|
+
boundaryQuestionIds: mergeStrings(local.boundaryQuestionIds, remote.boundaryQuestionIds),
|
|
27807
|
+
defaultAssumptions: mergeStrings(local.defaultAssumptions, remote.defaultAssumptions)
|
|
27808
|
+
};
|
|
27809
|
+
return enforceRemoteHardRules(draft, local);
|
|
27810
|
+
}
|
|
27811
|
+
function sanitizeRemoteDecision(remote) {
|
|
27812
|
+
const sanitized = {};
|
|
27813
|
+
if (remote.bestGate !== void 0) {
|
|
27814
|
+
if (!needTypes.includes(remote.bestGate)) return null;
|
|
27815
|
+
sanitized.bestGate = remote.bestGate;
|
|
27816
|
+
}
|
|
27817
|
+
if (remote.needType !== void 0) {
|
|
27818
|
+
if (!needTypes.includes(remote.needType)) return null;
|
|
27819
|
+
sanitized.needType = remote.needType;
|
|
27820
|
+
}
|
|
27821
|
+
if (remote.usageScope !== void 0) {
|
|
27822
|
+
if (!usageScopes.includes(remote.usageScope)) return null;
|
|
27823
|
+
sanitized.usageScope = remote.usageScope;
|
|
27824
|
+
}
|
|
27825
|
+
if (remote.maintenanceMode !== void 0) {
|
|
27826
|
+
if (!maintenanceModes.includes(remote.maintenanceMode)) return null;
|
|
27827
|
+
sanitized.maintenanceMode = remote.maintenanceMode;
|
|
27828
|
+
}
|
|
27829
|
+
if (remote.accessTopology !== void 0) {
|
|
27830
|
+
if (!accessTopologies.includes(remote.accessTopology)) return null;
|
|
27831
|
+
sanitized.accessTopology = remote.accessTopology;
|
|
27832
|
+
}
|
|
27833
|
+
if (remote.technicalShape !== void 0) {
|
|
27834
|
+
if (!technicalShapes.includes(remote.technicalShape)) return null;
|
|
27835
|
+
sanitized.technicalShape = remote.technicalShape;
|
|
27836
|
+
}
|
|
27837
|
+
if (remote.recommendedDeployment !== void 0) {
|
|
27838
|
+
if (!recommendedDeployments.includes(remote.recommendedDeployment)) return null;
|
|
27839
|
+
sanitized.recommendedDeployment = remote.recommendedDeployment;
|
|
27840
|
+
}
|
|
27841
|
+
if (remote.route !== void 0) {
|
|
27842
|
+
if (!routes.includes(remote.route)) return null;
|
|
27843
|
+
sanitized.route = remote.route;
|
|
27844
|
+
}
|
|
27845
|
+
if (remote.confidence !== void 0) {
|
|
27846
|
+
if (!confidences.includes(remote.confidence)) return null;
|
|
27847
|
+
sanitized.confidence = remote.confidence;
|
|
27848
|
+
}
|
|
27849
|
+
copyStringArray(remote, sanitized, "strongSignals");
|
|
27850
|
+
copyStringArray(remote, sanitized, "weakSignals");
|
|
27851
|
+
copyStringArray(remote, sanitized, "coreObjects");
|
|
27852
|
+
copyStringArray(remote, sanitized, "states");
|
|
27853
|
+
copyStringArray(remote, sanitized, "actions");
|
|
27854
|
+
copyStringArray(remote, sanitized, "mustNotUse");
|
|
27855
|
+
copyStringArray(remote, sanitized, "boundaryQuestionIds");
|
|
27856
|
+
copyStringArray(remote, sanitized, "defaultAssumptions");
|
|
27857
|
+
if (remote.source !== void 0) {
|
|
27858
|
+
if (!sources.includes(remote.source)) return null;
|
|
27859
|
+
sanitized.source = remote.source;
|
|
27860
|
+
}
|
|
27861
|
+
return sanitized;
|
|
27862
|
+
}
|
|
27863
|
+
function copyStringArray(remote, sanitized, key) {
|
|
27864
|
+
const value = remote[key];
|
|
27865
|
+
if (value === void 0) return;
|
|
27866
|
+
if (!Array.isArray(value) || !value.every((item) => typeof item === "string")) return;
|
|
27867
|
+
sanitized[key] = value;
|
|
27868
|
+
}
|
|
27869
|
+
function enforceRemoteHardRules(remote, local) {
|
|
27870
|
+
const hasCollaboration = local.needType === "multi_user_collaboration" || remote.needType === "multi_user_collaboration" || mergeStrings(local.strongSignals, remote.strongSignals).some((signal) => /多人|共享|协作|认领|相互安排/.test(signal));
|
|
27871
|
+
if (hasCollaboration) {
|
|
27872
|
+
return {
|
|
27873
|
+
...remote,
|
|
27874
|
+
needType: "multi_user_collaboration",
|
|
27875
|
+
maintenanceMode: "runtime_collaboration",
|
|
27876
|
+
technicalShape: "light_backend_json_sqlite",
|
|
27877
|
+
route: "spec_interrogate",
|
|
27878
|
+
mustNotUse: mergeStrings(remote.mustNotUse, ["static_display", "local_storage_only"])
|
|
27879
|
+
};
|
|
27880
|
+
}
|
|
27881
|
+
const hasSensitiveBackendSignal = mergeStrings(local.strongSignals, remote.strongSignals).some(
|
|
27882
|
+
(signal) => /支付|订单|AI|公开提交|访客提交/.test(signal)
|
|
27883
|
+
);
|
|
27884
|
+
if (hasSensitiveBackendSignal && ["static_page", "local_storage_tool", "local_json_import_export"].includes(remote.technicalShape)) {
|
|
27885
|
+
return {
|
|
27886
|
+
...remote,
|
|
27887
|
+
technicalShape: "full_backend_saas",
|
|
27888
|
+
route: "spec_interrogate",
|
|
27889
|
+
mustNotUse: mergeStrings(remote.mustNotUse, ["frontend_only"])
|
|
27890
|
+
};
|
|
27891
|
+
}
|
|
27892
|
+
return remote;
|
|
27893
|
+
}
|
|
27894
|
+
function hasRouteShapeConflict(decision) {
|
|
27895
|
+
return decision.route === "architecture_decide" && decision.technicalShape !== "static_page";
|
|
27896
|
+
}
|
|
27897
|
+
function summarizeDecision(decision) {
|
|
27898
|
+
return {
|
|
27899
|
+
needType: decision.needType,
|
|
27900
|
+
usageScope: decision.usageScope,
|
|
27901
|
+
maintenanceMode: decision.maintenanceMode,
|
|
27902
|
+
accessTopology: decision.accessTopology,
|
|
27903
|
+
technicalShape: decision.technicalShape,
|
|
27904
|
+
confidence: decision.confidence,
|
|
27905
|
+
strongSignals: decision.strongSignals,
|
|
27906
|
+
weakSignals: decision.weakSignals,
|
|
27907
|
+
conflict: hasRouteShapeConflict(decision)
|
|
27908
|
+
};
|
|
27909
|
+
}
|
|
27910
|
+
function truncateForRemote(message) {
|
|
27911
|
+
return message.length <= 500 ? message : `${message.slice(0, 500)}\u2026`;
|
|
27912
|
+
}
|
|
27913
|
+
function hashMessage(message) {
|
|
27914
|
+
return (0, import_node_crypto.createHash)("sha256").update(message.trim().replace(/\s+/g, " ")).digest("hex");
|
|
27915
|
+
}
|
|
27916
|
+
function mergeStrings(a = [], b = []) {
|
|
27917
|
+
return Array.from(new Set([...a, ...b].filter(Boolean)));
|
|
27918
|
+
}
|
|
27919
|
+
var needTypes = [
|
|
27920
|
+
"static_display",
|
|
27921
|
+
"personal_local_tool",
|
|
27922
|
+
"multi_user_collaboration",
|
|
27923
|
+
"content_marketing_site",
|
|
27924
|
+
"data_visualization_site",
|
|
27925
|
+
"transaction_workflow",
|
|
27926
|
+
"content_knowledge",
|
|
27927
|
+
"ai_automation",
|
|
27928
|
+
"unknown"
|
|
27929
|
+
];
|
|
27930
|
+
var usageScopes = ["self", "fixed_group", "public_audience", "unknown"];
|
|
27931
|
+
var maintenanceModes = [
|
|
27932
|
+
"agent_assisted",
|
|
27933
|
+
"manual_files",
|
|
27934
|
+
"web_admin",
|
|
27935
|
+
"visitor_submission",
|
|
27936
|
+
"runtime_collaboration",
|
|
27937
|
+
"unknown"
|
|
27938
|
+
];
|
|
27939
|
+
var accessTopologies = ["single_device", "lan_only", "internet_ip", "public_domain", "unknown"];
|
|
27940
|
+
var technicalShapes = [
|
|
27941
|
+
"static_page",
|
|
27942
|
+
"local_storage_tool",
|
|
27943
|
+
"local_json_import_export",
|
|
27944
|
+
"static_json_data_page",
|
|
27945
|
+
"light_backend_json_sqlite",
|
|
27946
|
+
"full_backend_saas",
|
|
27947
|
+
"unknown"
|
|
27948
|
+
];
|
|
27949
|
+
var recommendedDeployments = [
|
|
27950
|
+
"static_only",
|
|
27951
|
+
"local_browser_only",
|
|
27952
|
+
"static_hosting_with_agent_updates",
|
|
27953
|
+
"local_lan_server_sqlite",
|
|
27954
|
+
"cheap_vps_sqlite_by_ip",
|
|
27955
|
+
"vps_domain_https",
|
|
27956
|
+
"unknown"
|
|
27957
|
+
];
|
|
27958
|
+
var routes = ["spec_compile", "spec_interrogate", "architecture_decide"];
|
|
27959
|
+
var confidences = ["high", "medium", "low"];
|
|
27960
|
+
var sources = ["local_rule", "online_llm", "merged"];
|
|
27961
|
+
|
|
26980
27962
|
// src/core/assistEngine.ts
|
|
26981
27963
|
function executeAssist(message, knownContext, preferredPlatform = "unknown", strictness = "normal", autoExecute = true) {
|
|
26982
27964
|
const routed = routeIntent(message);
|
|
@@ -26994,6 +27976,28 @@ function executeAssist(message, knownContext, preferredPlatform = "unknown", str
|
|
|
26994
27976
|
return handleUnknown(routed);
|
|
26995
27977
|
}
|
|
26996
27978
|
}
|
|
27979
|
+
async function executeAssistWithRemoteGate(message, knownContext, preferredPlatform = "unknown", strictness = "normal", autoExecute = true) {
|
|
27980
|
+
const result = executeAssist(message, knownContext, preferredPlatform, strictness, autoExecute);
|
|
27981
|
+
if (result.routedIntent.scenario !== "build_product" || !result.pmIntentDecision) return result;
|
|
27982
|
+
const remote = await callRemotePmIntentGate(message, knownContext || {}, result.pmIntentDecision);
|
|
27983
|
+
if (!remote) return result;
|
|
27984
|
+
const merged = remote.decision;
|
|
27985
|
+
if (merged.needType !== result.pmIntentDecision.needType && ["multi_user_collaboration", "content_marketing_site", "data_visualization_site"].includes(merged.needType)) {
|
|
27986
|
+
const technicalProfile = buildTechnicalProfile(message, knownContext || {});
|
|
27987
|
+
const questions = merged.needType === "multi_user_collaboration" ? buildMultiUserCollaborationQuickQuestions() : merged.needType === "content_marketing_site" ? buildContentMarketingQuickQuestions() : buildDataVisualizationQuickQuestions();
|
|
27988
|
+
return appendRemoteGateMeta(
|
|
27989
|
+
buildPmGateInterrogateResult(
|
|
27990
|
+
message,
|
|
27991
|
+
result.routedIntent,
|
|
27992
|
+
technicalProfile,
|
|
27993
|
+
merged,
|
|
27994
|
+
questions
|
|
27995
|
+
),
|
|
27996
|
+
remote.meta.fallbackReason
|
|
27997
|
+
);
|
|
27998
|
+
}
|
|
27999
|
+
return appendRemoteGateMeta({ ...result, pmIntentDecision: merged }, remote.meta.fallbackReason);
|
|
28000
|
+
}
|
|
26997
28001
|
function detectPlatform(message, preferred) {
|
|
26998
28002
|
if (preferred !== "unknown") return preferred;
|
|
26999
28003
|
if (message.includes("\u5C0F\u7A0B\u5E8F")) return "mini_program";
|
|
@@ -27003,8 +28007,18 @@ function detectPlatform(message, preferred) {
|
|
|
27003
28007
|
}
|
|
27004
28008
|
function handleBuildProduct(message, knownContext, strictness, autoExecute, routed) {
|
|
27005
28009
|
const technicalProfile = buildTechnicalProfile(message, knownContext || {});
|
|
27006
|
-
|
|
27007
|
-
|
|
28010
|
+
const pmIntentDecision = decidePmIntent(message, knownContext || {});
|
|
28011
|
+
if (pmIntentDecision.needType === "static_display" && isStaticDisplaySite2(message)) {
|
|
28012
|
+
return withPmDecision(handleStaticDisplaySite(message, autoExecute, routed), pmIntentDecision);
|
|
28013
|
+
}
|
|
28014
|
+
if (pmIntentDecision.needType === "multi_user_collaboration") {
|
|
28015
|
+
return buildPmGateInterrogateResult(message, routed, technicalProfile, pmIntentDecision, buildMultiUserCollaborationQuickQuestions());
|
|
28016
|
+
}
|
|
28017
|
+
if (pmIntentDecision.needType === "content_marketing_site") {
|
|
28018
|
+
return buildPmGateInterrogateResult(message, routed, technicalProfile, pmIntentDecision, buildContentMarketingQuickQuestions());
|
|
28019
|
+
}
|
|
28020
|
+
if (pmIntentDecision.needType === "data_visualization_site") {
|
|
28021
|
+
return buildPmGateInterrogateResult(message, routed, technicalProfile, pmIntentDecision, buildDataVisualizationQuickQuestions());
|
|
27008
28022
|
}
|
|
27009
28023
|
if (!autoExecute) {
|
|
27010
28024
|
const quickQuestions2 = buildProductQuickQuestions(message, knownContext);
|
|
@@ -27018,6 +28032,7 @@ function handleBuildProduct(message, knownContext, strictness, autoExecute, rout
|
|
|
27018
28032
|
suggestedTool: "spec_interrogate"
|
|
27019
28033
|
},
|
|
27020
28034
|
technicalProfile,
|
|
28035
|
+
pmIntentDecision,
|
|
27021
28036
|
quickQuestions: quickQuestions2,
|
|
27022
28037
|
agentGuidance: [
|
|
27023
28038
|
"\u53EA\u5C55\u793A quickQuestions \u4E2D\u7684\u9009\u9879\uFF0C\u4E0D\u8981\u81EA\u884C\u5408\u5E76\u6216\u5220\u6539\u95EE\u9898\u3002",
|
|
@@ -27043,21 +28058,69 @@ function handleBuildProduct(message, knownContext, strictness, autoExecute, rout
|
|
|
27043
28058
|
const structured = buildInterrogateStructuredOutput(readiness, clarification, technicalProfile);
|
|
27044
28059
|
const domainClassification = classifyProductDomain(message, knownContext || {});
|
|
27045
28060
|
const quickQuestions = buildProductQuickQuestions(message, knownContext);
|
|
28061
|
+
const localFirstGeneric = domainClassification.domain === "generic" && isLocalFirstProfile(technicalProfile);
|
|
27046
28062
|
const domainPackWarning = domainClassification.domain === "generic" ? "\n\n> \u26A0\uFE0F \u5F53\u524D\u53EA\u8BC6\u522B\u4E3A\u4EA7\u54C1\u5F00\u53D1\u610F\u56FE\uFF0C\u4F46\u672A\u547D\u4E2D\u7A33\u5B9A domain pack\u3002\u540E\u7EED `spec_compile` \u5E94\u4F5C\u4E3A\u8349\u6848\u5904\u7406\uFF0C\u4E0D\u8981\u9759\u9ED8\u5957\u7528\u62A5\u540D\u3001\u7535\u5546\u3001\u9884\u7EA6\u3001\u5185\u5BB9\u793E\u533A\u3001\u5DE5\u5355\u3001\u77E5\u8BC6\u5E93\u6216 CRM \u6A21\u677F\u3002" : "";
|
|
28063
|
+
const localFirstDefaultNote = localFirstGeneric ? `
|
|
28064
|
+
|
|
28065
|
+
## \u5C0F\u767D\u9ED8\u8BA4\u8DEF\u5F84
|
|
28066
|
+
|
|
28067
|
+
\u8FD9\u662F\u4E2A\u4EBA\u672C\u5730\u5C0F\u5DE5\u5177\u3002\u4E0D\u8981\u8981\u6C42\u7528\u6237\u9010\u9879\u56DE\u7B54\u5168\u90E8 quickQuestions\uFF1B\u53EF\u4EE5\u5148\u91C7\u7528\u63A8\u8350\u9ED8\u8BA4\u503C\u8FDB\u5165 \`spec_compile\`\uFF0C\u751F\u6210 Draft \u89C4\u683C\u3002
|
|
28068
|
+
|
|
28069
|
+
\u201C\u9875\u9762\u9AD8\u7EA7\u4E00\u70B9\u201D\u53EA\u5F71\u54CD UI \u98CE\u683C\u3001\u5E03\u5C40\u548C\u9A8C\u6536\u6807\u51C6\uFF0C\u4E0D\u662F\u540E\u7AEF\u3001\u767B\u5F55\u3001\u591A\u7AEF\u540C\u6B65\u6216\u670D\u52A1\u5668\u6570\u636E\u5E93\u4FE1\u53F7\uFF1B\u9AD8\u7EA7\u9875\u9762\u53EF\u4EE5\u4ECD\u7136\u4F7F\u7528 localStorage\u3002
|
|
28070
|
+
|
|
28071
|
+
\u5982\u9700\u786E\u8BA4\uFF0C\u53EA\u95EE\u4E00\u53E5\u81EA\u7136\u8BED\u8A00\u95EE\u9898\uFF1A\u662F\u5426\u6309\u201C\u6D4F\u89C8\u5668\u672C\u5730\u4FDD\u5B58\u3001\u4E0D\u767B\u5F55\u4E0D\u505A\u540E\u53F0\u3001\u652F\u6301\u65B0\u589E\u7F16\u8F91\u5220\u9664\u548C\u641C\u7D22\u7B5B\u9009\u3001\u63D0\u9192\u5728\u9875\u9762\u5185\u7528\u72B6\u6001\u548C\u5217\u8868\u5C55\u793A\u201D\u7EE7\u7EED\uFF1F` : "";
|
|
28072
|
+
if (localFirstGeneric) {
|
|
28073
|
+
const spec = buildSpec(message, knownContext || {}, readiness);
|
|
28074
|
+
const effectiveReadiness = {
|
|
28075
|
+
...readiness,
|
|
28076
|
+
score: spec.readinessScore,
|
|
28077
|
+
status: spec.readinessStatus
|
|
28078
|
+
};
|
|
28079
|
+
const confirmation = buildConfirmation(spec);
|
|
28080
|
+
const compileMarkdown = formatCompileResult("draft", effectiveReadiness, void 0, spec, confirmation);
|
|
28081
|
+
const compileStructured = buildCompileStructuredOutput("draft", effectiveReadiness, spec, confirmation);
|
|
28082
|
+
return {
|
|
28083
|
+
routedIntent: routed,
|
|
28084
|
+
selectedTool: "spec_compile",
|
|
28085
|
+
executed: true,
|
|
28086
|
+
result: compileStructured,
|
|
28087
|
+
nextAction: {
|
|
28088
|
+
type: "confirm_spec",
|
|
28089
|
+
message: "\u5DF2\u6309\u672C\u5730\u5C0F\u5DE5\u5177\u9ED8\u8BA4\u503C\u751F\u6210 MVP \u8349\u6848\uFF1B\u8BF7\u786E\u8BA4\u9ED8\u8BA4\u5047\u8BBE\u5373\u53EF\uFF0C\u4E0D\u8981\u8BA9\u5C0F\u767D\u7528\u6237\u9010\u9879\u586B\u5199\u7ED3\u6784\u5316\u95EE\u9898\u3002",
|
|
28090
|
+
suggestedTool: "spec_compile"
|
|
28091
|
+
},
|
|
28092
|
+
technicalProfile,
|
|
28093
|
+
pmIntentDecision,
|
|
28094
|
+
quickQuestions,
|
|
28095
|
+
agentGuidance: [
|
|
28096
|
+
"\u9762\u5411\u5C0F\u767D\u672C\u5730\u5DE5\u5177\u65F6\uFF0C\u4E0D\u8981\u628A quickQuestions \u539F\u6837\u629B\u7ED9\u7528\u6237\uFF0C\u4E5F\u4E0D\u8981\u8981\u6C42\u7528\u6237\u56DE\u7B54\u7C7B\u4F3C\u201CB + a\u201D\u7684\u7ED3\u6784\u5316\u9009\u9879\uFF1B\u5DF2\u751F\u6210 MVP \u8349\u6848\uFF0C\u6700\u591A\u95EE\u4E00\u53E5\u81EA\u7136\u8BED\u8A00\u786E\u8BA4\u3002\u9875\u9762\u9AD8\u7EA7\u611F\u53EA\u5F71\u54CD UI\uFF0C\u4E0D\u8981\u56E0\u6B64\u7EA0\u504F\u6210\u540E\u7AEF\u3001\u767B\u5F55\u3001\u591A\u7AEF\u540C\u6B65\u6216\u670D\u52A1\u5668\u6570\u636E\u5E93\u3002",
|
|
28097
|
+
"\u4E0D\u8981\u628A\u7528\u6237\u7AEF\u767B\u5F55\u548C\u540E\u53F0\u7BA1\u7406\u5458\u767B\u5F55\u5408\u5E76\u6210\u540C\u4E00\u4E2A\u5B57\u6BB5\u3002",
|
|
28098
|
+
"\u5982\u679C\u7528\u6237\u53EA\u9700\u8981\u5BFC\u51FA\uFF0C\u4E0D\u8981\u64C5\u81EA\u6269\u5C55\u6210\u5B8C\u6574\u540E\u53F0\u7BA1\u7406\u7CFB\u7EDF\u3002",
|
|
28099
|
+
"\u672A\u547D\u4E2D\u7A33\u5B9A domain pack \u65F6\uFF0C\u5E94\u4F7F\u7528 generic MVP \u8349\u6848\uFF0C\u4E0D\u8981\u5957\u7528\u62A5\u540D\u3001\u7535\u5546\u3001\u9884\u7EA6\u3001\u5185\u5BB9\u793E\u533A\u3001\u5DE5\u5355\u3001\u77E5\u8BC6\u5E93\u6216 CRM \u6A21\u677F\u3002"
|
|
28100
|
+
],
|
|
28101
|
+
markdown: `# \u8BC6\u522B\u5230\u573A\u666F\uFF1A\u4EA7\u54C1\u5F00\u53D1
|
|
28102
|
+
|
|
28103
|
+
**\u7F6E\u4FE1\u5EA6\uFF1A** ${Math.round(routed.confidence * 100)}%
|
|
28104
|
+
${domainPackWarning}
|
|
28105
|
+
${localFirstDefaultNote}
|
|
28106
|
+
|
|
28107
|
+
${compileMarkdown}`
|
|
28108
|
+
};
|
|
28109
|
+
}
|
|
27047
28110
|
return {
|
|
27048
28111
|
routedIntent: routed,
|
|
27049
28112
|
selectedTool: "spec_interrogate",
|
|
27050
28113
|
executed: true,
|
|
27051
28114
|
result: structured,
|
|
27052
28115
|
nextAction: {
|
|
27053
|
-
type: structured.recommendation.canProceed ? "compile_spec" : "answer_questions",
|
|
27054
|
-
message: structured.recommendation.reason,
|
|
27055
|
-
suggestedTool: structured.recommendation.suggestedNextTool
|
|
28116
|
+
type: structured.recommendation.canProceed || localFirstGeneric ? "compile_spec" : "answer_questions",
|
|
28117
|
+
message: localFirstGeneric ? "\u672C\u5730\u5C0F\u5DE5\u5177\u53EF\u5148\u7528\u63A8\u8350\u9ED8\u8BA4\u503C\u751F\u6210 Draft \u89C4\u683C\uFF1B\u4E0D\u8981\u8981\u6C42\u5C0F\u767D\u7528\u6237\u9010\u9879\u586B\u5199\u7ED3\u6784\u5316\u7B54\u6848\u3002" : structured.recommendation.reason,
|
|
28118
|
+
suggestedTool: localFirstGeneric ? "spec_compile" : structured.recommendation.suggestedNextTool
|
|
27056
28119
|
},
|
|
27057
28120
|
technicalProfile,
|
|
27058
28121
|
quickQuestions,
|
|
27059
28122
|
agentGuidance: [
|
|
27060
|
-
"\u4F18\u5148\u76F4\u63A5\u5C55\u793A quickQuestions\uFF0C\u907F\u514D\u4E8C\u6B21\u6539\u5199\u5BFC\u81F4\u9009\u9879\u8BED\u4E49\u53D8\u5316\u3002",
|
|
28123
|
+
localFirstGeneric ? "\u9762\u5411\u5C0F\u767D\u672C\u5730\u5DE5\u5177\u65F6\uFF0C\u4E0D\u8981\u628A quickQuestions \u539F\u6837\u629B\u7ED9\u7528\u6237\uFF0C\u4E5F\u4E0D\u8981\u8981\u6C42\u7528\u6237\u56DE\u7B54\u7C7B\u4F3C\u201CB + a\u201D\u7684\u7ED3\u6784\u5316\u9009\u9879\uFF1B\u7528\u63A8\u8350\u9ED8\u8BA4\u503C\u7EE7\u7EED spec_compile\uFF0C\u6700\u591A\u95EE\u4E00\u53E5\u81EA\u7136\u8BED\u8A00\u786E\u8BA4\u3002\u9875\u9762\u9AD8\u7EA7\u611F\u53EA\u5F71\u54CD UI\uFF0C\u4E0D\u8981\u56E0\u6B64\u7EA0\u504F\u6210\u540E\u7AEF\u3001\u767B\u5F55\u3001\u591A\u7AEF\u540C\u6B65\u6216\u670D\u52A1\u5668\u6570\u636E\u5E93\u3002" : "\u4F18\u5148\u76F4\u63A5\u5C55\u793A quickQuestions\uFF0C\u907F\u514D\u4E8C\u6B21\u6539\u5199\u5BFC\u81F4\u9009\u9879\u8BED\u4E49\u53D8\u5316\u3002",
|
|
27061
28124
|
"\u4E0D\u8981\u628A\u7528\u6237\u7AEF\u767B\u5F55\u548C\u540E\u53F0\u7BA1\u7406\u5458\u767B\u5F55\u5408\u5E76\u6210\u540C\u4E00\u4E2A\u5B57\u6BB5\u3002",
|
|
27062
28125
|
"\u5982\u679C\u7528\u6237\u53EA\u9700\u8981\u5BFC\u51FA\uFF0C\u4E0D\u8981\u64C5\u81EA\u6269\u5C55\u6210\u5B8C\u6574\u540E\u53F0\u7BA1\u7406\u7CFB\u7EDF\u3002",
|
|
27063
28126
|
...domainClassification.domain === "generic" ? ["\u672A\u547D\u4E2D\u7A33\u5B9A domain pack \u65F6\uFF0C\u5E94\u5148\u6F84\u6E05\u6838\u5FC3\u4E1A\u52A1\u5BF9\u8C61\u3001\u72B6\u6001\u6D41\u8F6C\u548C\u6743\u9650\u8FB9\u754C\uFF0C\u4E0D\u8981\u5957\u7528\u5176\u5B83 domain \u6A21\u677F\u3002"] : []
|
|
@@ -27066,13 +28129,90 @@ function handleBuildProduct(message, knownContext, strictness, autoExecute, rout
|
|
|
27066
28129
|
|
|
27067
28130
|
**\u7F6E\u4FE1\u5EA6\uFF1A** ${Math.round(routed.confidence * 100)}%
|
|
27068
28131
|
${domainPackWarning}
|
|
28132
|
+
${localFirstDefaultNote}
|
|
27069
28133
|
|
|
27070
28134
|
## \u5FEB\u901F\u786E\u8BA4\u95EE\u9898
|
|
27071
28135
|
|
|
27072
28136
|
${formatQuickQuestions(quickQuestions)}
|
|
27073
28137
|
|
|
27074
|
-
${markdown}
|
|
28138
|
+
${markdown}`,
|
|
28139
|
+
pmIntentDecision
|
|
28140
|
+
};
|
|
28141
|
+
}
|
|
28142
|
+
function withPmDecision(result, pmIntentDecision) {
|
|
28143
|
+
return { ...result, pmIntentDecision };
|
|
28144
|
+
}
|
|
28145
|
+
function appendRemoteGateMeta(result, fallbackReason) {
|
|
28146
|
+
if (!fallbackReason) return result;
|
|
28147
|
+
return {
|
|
28148
|
+
...result,
|
|
28149
|
+
agentGuidance: [
|
|
28150
|
+
...result.agentGuidance,
|
|
28151
|
+
`\u8FDC\u7A0B PM Gate \u672A\u4F7F\u7528\u6216\u5DF2\u964D\u7EA7\uFF1A${fallbackReason}\u3002\u5F53\u524D\u7ED3\u679C\u6765\u81EA\u672C\u5730\u89C4\u5219\u3002`
|
|
28152
|
+
]
|
|
28153
|
+
};
|
|
28154
|
+
}
|
|
28155
|
+
function buildPmGateInterrogateResult(message, routed, technicalProfile, pmIntentDecision, quickQuestions) {
|
|
28156
|
+
const title = formatNeedTypeTitle(pmIntentDecision.needType);
|
|
28157
|
+
return {
|
|
28158
|
+
routedIntent: routed,
|
|
28159
|
+
selectedTool: "spec_interrogate",
|
|
28160
|
+
executed: true,
|
|
28161
|
+
nextAction: {
|
|
28162
|
+
type: "answer_questions",
|
|
28163
|
+
message: "\u5DF2\u8BC6\u522B\u9700\u6C42\u95E8\uFF0C\u8BF7\u5148\u786E\u8BA4\u4F1A\u6539\u53D8\u67B6\u6784\u548C\u8FB9\u754C\u7684\u5173\u952E\u95EE\u9898\u3002",
|
|
28164
|
+
suggestedTool: "spec_compile"
|
|
28165
|
+
},
|
|
28166
|
+
technicalProfile,
|
|
28167
|
+
pmIntentDecision,
|
|
28168
|
+
quickQuestions,
|
|
28169
|
+
agentGuidance: [
|
|
28170
|
+
`PM Gate \u5DF2\u5224\u5B9A\u4E3A ${pmIntentDecision.needType}\uFF0C\u4E0D\u8981\u5957\u7528\u65E0\u5173 domain \u6A21\u677F\u3002`,
|
|
28171
|
+
"\u4F18\u5148\u786E\u8BA4\u4F7F\u7528\u8303\u56F4\u3001\u7EF4\u62A4\u65B9\u5F0F\u548C\u8BBF\u95EE\u65B9\u5F0F\uFF0C\u518D\u8C08\u5177\u4F53\u6280\u672F\u6808\u3002",
|
|
28172
|
+
...pmIntentDecision.mustNotUse.map((item) => `\u7981\u6B62\u9ED8\u8BA4\u4F7F\u7528\uFF1A${item}`)
|
|
28173
|
+
],
|
|
28174
|
+
markdown: `# \u8BC6\u522B\u5230\u573A\u666F\uFF1A${title}
|
|
28175
|
+
|
|
28176
|
+
**\u7F6E\u4FE1\u5EA6\uFF1A** ${pmIntentDecision.confidence}
|
|
28177
|
+
|
|
28178
|
+
## PM Gate \u5224\u65AD
|
|
28179
|
+
|
|
28180
|
+
- **\u9700\u6C42\u95E8:** ${pmIntentDecision.needType}
|
|
28181
|
+
- **\u4F7F\u7528\u8303\u56F4:** ${pmIntentDecision.usageScope}
|
|
28182
|
+
- **\u7EF4\u62A4\u65B9\u5F0F:** ${pmIntentDecision.maintenanceMode}
|
|
28183
|
+
- **\u8BBF\u95EE\u65B9\u5F0F:** ${pmIntentDecision.accessTopology}
|
|
28184
|
+
- **\u6280\u672F\u5F62\u6001:** ${pmIntentDecision.technicalShape}
|
|
28185
|
+
- **\u63A8\u8350\u90E8\u7F72:** ${pmIntentDecision.recommendedDeployment}
|
|
28186
|
+
- **\u5F3A\u4FE1\u53F7:** ${pmIntentDecision.strongSignals.join("\u3001") || "\u65E0"}
|
|
28187
|
+
- **\u5F31\u4FE1\u53F7:** ${pmIntentDecision.weakSignals.join("\u3001") || "\u65E0"}
|
|
28188
|
+
- **\u4E0D\u8981\u9ED8\u8BA4\u4F7F\u7528:** ${pmIntentDecision.mustNotUse.join("\u3001") || "\u65E0"}
|
|
28189
|
+
|
|
28190
|
+
## \u9ED8\u8BA4\u7406\u89E3
|
|
28191
|
+
|
|
28192
|
+
${pmIntentDecision.defaultAssumptions.map((item) => `- ${item}`).join("\n")}
|
|
28193
|
+
|
|
28194
|
+
## \u5FEB\u901F\u786E\u8BA4\u95EE\u9898
|
|
28195
|
+
|
|
28196
|
+
${formatQuickQuestions(quickQuestions)}
|
|
28197
|
+
|
|
28198
|
+
## \u4E0B\u4E00\u6B65
|
|
28199
|
+
|
|
28200
|
+
\u8BF7\u5148\u786E\u8BA4\u4EE5\u4E0A\u8FB9\u754C\uFF0C\u518D\u8C03\u7528 \`spec_compile\` \u56FA\u5316 MVP \u89C4\u683C\u3002`
|
|
28201
|
+
};
|
|
28202
|
+
}
|
|
28203
|
+
function formatNeedTypeTitle(needType) {
|
|
28204
|
+
const titles = {
|
|
28205
|
+
static_display: "\u9759\u6001\u5C55\u793A\u7F51\u7AD9",
|
|
28206
|
+
personal_local_tool: "\u4E2A\u4EBA\u672C\u5730\u5DE5\u5177",
|
|
28207
|
+
multi_user_collaboration: "\u591A\u4EBA\u534F\u4F5C\u5DE5\u5177",
|
|
28208
|
+
content_marketing_site: "\u5185\u5BB9\u8425\u9500\u7F51\u7AD9",
|
|
28209
|
+
data_visualization_site: "\u6570\u636E\u56FE\u8868\u7F51\u7AD9",
|
|
28210
|
+
transaction_workflow: "\u4EA4\u6613/\u5C65\u7EA6\u6D41\u7A0B",
|
|
28211
|
+
content_knowledge: "\u5185\u5BB9/\u77E5\u8BC6\u7BA1\u7406",
|
|
28212
|
+
ai_automation: "AI \u81EA\u52A8\u5316\u4EA7\u54C1",
|
|
28213
|
+
unknown: "\u4EA7\u54C1\u5F00\u53D1"
|
|
27075
28214
|
};
|
|
28215
|
+
return titles[needType];
|
|
27076
28216
|
}
|
|
27077
28217
|
function handleStaticDisplaySite(message, autoExecute, routed) {
|
|
27078
28218
|
const technicalProfile = buildTechnicalProfile(message, {});
|
|
@@ -27656,6 +28796,161 @@ function buildLocalFirstQuickQuestions(technicalProfile, message = "") {
|
|
|
27656
28796
|
}
|
|
27657
28797
|
return questions;
|
|
27658
28798
|
}
|
|
28799
|
+
function buildMultiUserCollaborationQuickQuestions() {
|
|
28800
|
+
return withQuestionExamples([
|
|
28801
|
+
{
|
|
28802
|
+
id: "access_topology",
|
|
28803
|
+
question: "\u4F60\u4EEC\u53EA\u9700\u8981\u5728\u540C\u4E00\u4E2A Wi-Fi/\u5C40\u57DF\u7F51\u91CC\u4F7F\u7528\uFF0C\u8FD8\u662F\u5916\u51FA\u65F6\u4E5F\u8981\u8BBF\u95EE\uFF1F",
|
|
28804
|
+
whyImportant: "\u51B3\u5B9A\u662F\u5C40\u57DF\u7F51\u5C0F\u670D\u52A1\uFF0C\u8FD8\u662F\u9700\u8981\u516C\u7F51\u670D\u52A1\u5668\u3001\u57DF\u540D\u548C HTTPS\u3002",
|
|
28805
|
+
priority: "P0",
|
|
28806
|
+
defaultValue: "ask_first",
|
|
28807
|
+
mapsTo: ["access_topology", "deployment"],
|
|
28808
|
+
options: [
|
|
28809
|
+
{ label: "\u5148\u786E\u8BA4\u5C40\u57DF\u7F51\u662F\u5426\u8DB3\u591F", value: "ask_first", recommended: true },
|
|
28810
|
+
{ label: "\u53EA\u5728\u540C\u4E00 Wi-Fi/\u5C40\u57DF\u7F51\u4F7F\u7528", value: "lan_only" },
|
|
28811
|
+
{ label: "\u5916\u51FA\u4E5F\u8981\u80FD\u8BBF\u95EE", value: "internet_ip" }
|
|
28812
|
+
]
|
|
28813
|
+
},
|
|
28814
|
+
{
|
|
28815
|
+
id: "public_ip_acceptance",
|
|
28816
|
+
question: "\u5982\u679C\u5916\u51FA\u4E5F\u8981\u8BBF\u95EE\uFF0C\u80FD\u5426\u63A5\u53D7\u7B2C\u4E00\u7248\u7528\u51E0\u5341\u5143/\u5E74\u7684\u516C\u7F51\u670D\u52A1\u5668\u548C IP \u5730\u5740\u8BBF\u95EE\uFF1F",
|
|
28817
|
+
whyImportant: "\u51B3\u5B9A MVP \u662F\u5426\u5148\u8DF3\u8FC7\u57DF\u540D\u3001\u5907\u6848\u548C\u5B8C\u6574 HTTPS \u8FD0\u7EF4\u3002",
|
|
28818
|
+
priority: "P0",
|
|
28819
|
+
defaultValue: "cheap_vps_ip_ok",
|
|
28820
|
+
mapsTo: ["deployment", "non_goals"],
|
|
28821
|
+
options: [
|
|
28822
|
+
{ label: "\u53EF\u4EE5\uFF0C\u5148\u7528\u516C\u7F51 IP \u8DD1\u901A", value: "cheap_vps_ip_ok", recommended: true },
|
|
28823
|
+
{ label: "\u5FC5\u987B\u6709\u57DF\u540D\u548C HTTPS", value: "domain_https" },
|
|
28824
|
+
{ label: "\u5148\u53EA\u505A\u5C40\u57DF\u7F51\u7248", value: "lan_first" }
|
|
28825
|
+
]
|
|
28826
|
+
},
|
|
28827
|
+
{
|
|
28828
|
+
id: "claim_rule",
|
|
28829
|
+
question: "\u7ED9\u522B\u4EBA\u5B89\u6392\u4EFB\u52A1\u65F6\uFF0C\u662F\u5426\u5FC5\u987B\u5BF9\u65B9\u8BA4\u9886\u540E\u624D\u8FDB\u5165\u5BF9\u65B9\u65E5\u7A0B\uFF1F",
|
|
28830
|
+
whyImportant: "\u51B3\u5B9A\u4EFB\u52A1\u72B6\u6001\u673A\u548C\u6743\u9650\u8FB9\u754C\u3002",
|
|
28831
|
+
priority: "P0",
|
|
28832
|
+
defaultValue: "claim_required",
|
|
28833
|
+
mapsTo: ["workflow", "task_status"],
|
|
28834
|
+
options: [
|
|
28835
|
+
{ label: "\u5FC5\u987B\u8BA4\u9886\u540E\u624D\u751F\u6548", value: "claim_required", recommended: true },
|
|
28836
|
+
{ label: "\u76F4\u63A5\u8FDB\u5165\u5BF9\u65B9\u65E5\u7A0B\u4F46\u6807\u8BB0\u5F85\u786E\u8BA4", value: "pending_confirm" },
|
|
28837
|
+
{ label: "\u521B\u5EFA\u8005\u53EF\u4EE5\u76F4\u63A5\u5B89\u6392", value: "direct_assign" }
|
|
28838
|
+
]
|
|
28839
|
+
},
|
|
28840
|
+
{
|
|
28841
|
+
id: "time_conflict_rule",
|
|
28842
|
+
question: "\u540C\u4E00\u65F6\u95F4\u6709\u591A\u4E2A\u4EFB\u52A1\u65F6\uFF0C\u5E94\u8BE5\u5E76\u6392\u5C55\u793A/\u9AD8\u4EAE\u51B2\u7A81\uFF0C\u8FD8\u662F\u963B\u6B62\u5B89\u6392\uFF1F",
|
|
28843
|
+
whyImportant: "\u51B3\u5B9A\u65E5\u7A0B\u89C6\u56FE\u548C\u51B2\u7A81\u89C4\u5219\u3002",
|
|
28844
|
+
priority: "P0",
|
|
28845
|
+
defaultValue: "show_conflict",
|
|
28846
|
+
mapsTo: ["workflow", "success_criteria"],
|
|
28847
|
+
options: [
|
|
28848
|
+
{ label: "\u5141\u8BB8\u5E76\u6392\u5C55\u793A\u5E76\u9AD8\u4EAE\u51B2\u7A81", value: "show_conflict", recommended: true },
|
|
28849
|
+
{ label: "\u963B\u6B62\u5B89\u6392\u51B2\u7A81\u4EFB\u52A1", value: "block_conflict" },
|
|
28850
|
+
{ label: "\u53EA\u63D0\u793A\u4E0D\u963B\u6B62", value: "warn_only" }
|
|
28851
|
+
]
|
|
28852
|
+
}
|
|
28853
|
+
]);
|
|
28854
|
+
}
|
|
28855
|
+
function buildContentMarketingQuickQuestions() {
|
|
28856
|
+
return withQuestionExamples([
|
|
28857
|
+
{
|
|
28858
|
+
id: "maintenance_mode",
|
|
28859
|
+
question: "\u540E\u7EED\u7EF4\u62A4\u5185\u5BB9\u65F6\uFF0C\u662F\u7EE7\u7EED\u8BA9 Agent \u5E2E\u4F60\u6539\u548C\u53D1\u5E03\uFF0C\u8FD8\u662F\u9700\u8981\u7F51\u9875\u540E\u53F0\u81EA\u5DF1\u7F16\u8F91\uFF1F",
|
|
28860
|
+
whyImportant: "\u5185\u5BB9\u7ECF\u5E38\u6539\u4E0D\u7B49\u4E8E\u5FC5\u987B\u505A\u540E\u53F0\uFF0C\u7EF4\u62A4\u65B9\u5F0F\u51B3\u5B9A\u67B6\u6784\u590D\u6742\u5EA6\u3002",
|
|
28861
|
+
priority: "P0",
|
|
28862
|
+
defaultValue: "agent_assisted",
|
|
28863
|
+
mapsTo: ["maintenance_mode", "backend_need"],
|
|
28864
|
+
options: [
|
|
28865
|
+
{ label: "\u7EE7\u7EED\u8BA9 Agent \u5E2E\u6211\u66F4\u65B0\u548C\u53D1\u5E03", value: "agent_assisted", recommended: true },
|
|
28866
|
+
{ label: "\u6211\u80FD\u63A5\u53D7\u6539 data.json/markdown \u6587\u4EF6", value: "manual_files" },
|
|
28867
|
+
{ label: "\u6211\u8981\u7F51\u9875\u540E\u53F0\u4E0A\u4F20\u56FE\u7247\u548C\u7F16\u8F91\u5185\u5BB9", value: "web_admin" }
|
|
28868
|
+
]
|
|
28869
|
+
},
|
|
28870
|
+
{
|
|
28871
|
+
id: "geo_goal",
|
|
28872
|
+
question: "\u4F60\u8BF4\u7684 GEO \u670D\u52A1\u4E3B\u8981\u662F AI/\u751F\u6210\u5F0F\u641C\u7D22\u53EF\u89C1\u6027\uFF0C\u8FD8\u662F\u5730\u56FE/\u9644\u8FD1\u95E8\u5E97\u66DD\u5149\uFF1F",
|
|
28873
|
+
whyImportant: "\u51B3\u5B9A FAQ\u3001\u7ED3\u6784\u5316\u6570\u636E\u3001\u95E8\u5E97\u4FE1\u606F\u3001\u5730\u56FE\u548C sitemap \u7684\u4F18\u5148\u7EA7\u3002",
|
|
28874
|
+
priority: "P0",
|
|
28875
|
+
defaultValue: "geo_seo_content",
|
|
28876
|
+
mapsTo: ["seo_geo", "content_sections"],
|
|
28877
|
+
options: [
|
|
28878
|
+
{ label: "AI/\u751F\u6210\u5F0F\u641C\u7D22\u548C SEO \u53EF\u89C1\u6027", value: "geo_seo_content", recommended: true },
|
|
28879
|
+
{ label: "\u5730\u56FE\u5B9A\u4F4D/\u9644\u8FD1\u95E8\u5E97\u66DD\u5149", value: "map_local_discovery" },
|
|
28880
|
+
{ label: "\u4E24\u8005\u90FD\u8981", value: "both" }
|
|
28881
|
+
]
|
|
28882
|
+
},
|
|
28883
|
+
{
|
|
28884
|
+
id: "visitor_submission",
|
|
28885
|
+
question: "\u7528\u6237\u53CD\u9988\u662F\u4F60\u624B\u52A8\u6574\u7406\u540E\u5C55\u793A\uFF0C\u8FD8\u662F\u8BBF\u5BA2\u53EF\u4EE5\u5728\u7EBF\u63D0\u4EA4\uFF1F",
|
|
28886
|
+
whyImportant: "\u8BBF\u5BA2\u63D0\u4EA4\u4F1A\u89E6\u53D1\u540E\u7AEF\u3001\u5BA1\u6838\u548C\u9632\u5783\u573E\u5185\u5BB9\u3002",
|
|
28887
|
+
priority: "P0",
|
|
28888
|
+
defaultValue: "owner_curated",
|
|
28889
|
+
mapsTo: ["maintenance_mode", "risk_boundaries"],
|
|
28890
|
+
options: [
|
|
28891
|
+
{ label: "\u6211\u624B\u52A8\u6574\u7406\u540E\u5C55\u793A", value: "owner_curated", recommended: true },
|
|
28892
|
+
{ label: "\u8BBF\u5BA2\u53EF\u4EE5\u5728\u7EBF\u63D0\u4EA4", value: "visitor_submission" },
|
|
28893
|
+
{ label: "\u5148\u5C55\u793A\u56FA\u5B9A\u6848\u4F8B", value: "static_examples" }
|
|
28894
|
+
]
|
|
28895
|
+
},
|
|
28896
|
+
{
|
|
28897
|
+
id: "image_volume",
|
|
28898
|
+
question: "\u7167\u7247\u662F\u5C11\u91CF\u7CBE\u9009\u56FE\uFF0C\u8FD8\u662F\u4F1A\u7ECF\u5E38\u4E0A\u4F20\u5F88\u591A\u56FE\uFF1F",
|
|
28899
|
+
whyImportant: "\u51B3\u5B9A\u56FE\u7247\u538B\u7F29\u3001\u5206\u7C7B\u3001\u5C01\u9762\u548C\u8D44\u6E90\u7BA1\u7406\u65B9\u5F0F\u3002",
|
|
28900
|
+
priority: "P1",
|
|
28901
|
+
defaultValue: "curated_gallery",
|
|
28902
|
+
mapsTo: ["content_sections", "asset_strategy"],
|
|
28903
|
+
options: [
|
|
28904
|
+
{ label: "\u5C11\u91CF\u7CBE\u9009\u56FE", value: "curated_gallery", recommended: true },
|
|
28905
|
+
{ label: "\u7ECF\u5E38\u4E0A\u4F20\u5F88\u591A\u56FE", value: "large_gallery" },
|
|
28906
|
+
{ label: "\u5148\u4E0D\u505A\u56FE\u5E93", value: "no_gallery_first" }
|
|
28907
|
+
]
|
|
28908
|
+
}
|
|
28909
|
+
]);
|
|
28910
|
+
}
|
|
28911
|
+
function buildDataVisualizationQuickQuestions() {
|
|
28912
|
+
return withQuestionExamples([
|
|
28913
|
+
{
|
|
28914
|
+
id: "data_update_mode",
|
|
28915
|
+
question: "\u65B0\u7684 xlsx \u662F\u4EA4\u7ED9 Agent \u66F4\u65B0\u7F51\u7AD9\uFF0C\u8FD8\u662F\u7F51\u7AD9\u91CC\u8981\u6709\u4E0A\u4F20\u6309\u94AE\uFF1F",
|
|
28916
|
+
whyImportant: "\u51B3\u5B9A\u662F\u5426\u9700\u8981\u540E\u53F0\u4E0A\u4F20\u63A5\u53E3\u548C\u670D\u52A1\u5668\u89E3\u6790\u3002",
|
|
28917
|
+
priority: "P0",
|
|
28918
|
+
defaultValue: "agent_assisted",
|
|
28919
|
+
mapsTo: ["maintenance_mode", "data_flow"],
|
|
28920
|
+
options: [
|
|
28921
|
+
{ label: "\u4EA4\u7ED9 Agent \u89E3\u6790\u5E76\u66F4\u65B0\u7F51\u7AD9", value: "agent_assisted", recommended: true },
|
|
28922
|
+
{ label: "\u7F51\u9875\u91CC\u4E0A\u4F20\uFF0C\u4F46\u53EA\u5728\u6D4F\u89C8\u5668\u672C\u5730\u6E32\u67D3", value: "browser_upload" },
|
|
28923
|
+
{ label: "\u7F51\u9875\u4E0A\u4F20\u540E\u6240\u6709\u8BBF\u5BA2\u770B\u5230\u6700\u65B0\u6570\u636E", value: "server_upload" }
|
|
28924
|
+
]
|
|
28925
|
+
},
|
|
28926
|
+
{
|
|
28927
|
+
id: "audience_scope",
|
|
28928
|
+
question: "\u56FE\u8868\u662F\u53EA\u7ED9\u4F60\u81EA\u5DF1\u770B\uFF0C\u8FD8\u662F\u516C\u5F00\u7ED9\u522B\u4EBA\u770B\uFF1F",
|
|
28929
|
+
whyImportant: "\u51B3\u5B9A\u8BBF\u95EE\u65B9\u5F0F\u3001\u90E8\u7F72\u65B9\u5F0F\u548C\u662F\u5426\u9700\u8981\u6743\u9650\u3002",
|
|
28930
|
+
priority: "P0",
|
|
28931
|
+
defaultValue: "public_view",
|
|
28932
|
+
mapsTo: ["usage_scope", "access_topology"],
|
|
28933
|
+
options: [
|
|
28934
|
+
{ label: "\u516C\u5F00\u5C55\u793A", value: "public_view", recommended: true },
|
|
28935
|
+
{ label: "\u53EA\u7ED9\u81EA\u5DF1\u770B", value: "self_view" },
|
|
28936
|
+
{ label: "\u56FA\u5B9A\u51E0\u4E2A\u4EBA\u770B", value: "fixed_group" }
|
|
28937
|
+
]
|
|
28938
|
+
},
|
|
28939
|
+
{
|
|
28940
|
+
id: "history_versions",
|
|
28941
|
+
question: "\u662F\u5426\u9700\u8981\u4FDD\u7559\u5386\u53F2\u7248\u672C\uFF0C\u8FD8\u662F\u53EA\u5C55\u793A\u6700\u65B0\u7ED3\u679C\uFF1F",
|
|
28942
|
+
whyImportant: "\u51B3\u5B9A\u662F\u5426\u9700\u8981\u7248\u672C\u5B58\u50A8\u548C\u5386\u53F2\u5207\u6362\u3002",
|
|
28943
|
+
priority: "P1",
|
|
28944
|
+
defaultValue: "latest_only",
|
|
28945
|
+
mapsTo: ["data_model", "success_criteria"],
|
|
28946
|
+
options: [
|
|
28947
|
+
{ label: "\u53EA\u5C55\u793A\u6700\u65B0\u7ED3\u679C", value: "latest_only", recommended: true },
|
|
28948
|
+
{ label: "\u4FDD\u7559\u5386\u53F2\u7248\u672C", value: "keep_history" },
|
|
28949
|
+
{ label: "\u4EE5\u540E\u518D\u8BF4", value: "later" }
|
|
28950
|
+
]
|
|
28951
|
+
}
|
|
28952
|
+
]);
|
|
28953
|
+
}
|
|
27659
28954
|
function buildAppointmentQuickQuestions() {
|
|
27660
28955
|
return [
|
|
27661
28956
|
{
|
|
@@ -28349,7 +29644,7 @@ function quickQuestionExample(id, question) {
|
|
|
28349
29644
|
// src/tools/productSpecAssist.ts
|
|
28350
29645
|
function registerProductSpecAssist(server) {
|
|
28351
29646
|
const handler = async (input) => {
|
|
28352
|
-
const result =
|
|
29647
|
+
const result = await executeAssistWithRemoteGate(
|
|
28353
29648
|
input.message,
|
|
28354
29649
|
input.known_context,
|
|
28355
29650
|
input.preferred_platform,
|
|
@@ -28365,6 +29660,7 @@ function registerProductSpecAssist(server) {
|
|
|
28365
29660
|
result: result.result ?? null,
|
|
28366
29661
|
nextAction: result.nextAction,
|
|
28367
29662
|
technicalProfile: result.technicalProfile,
|
|
29663
|
+
pmIntentDecision: result.pmIntentDecision,
|
|
28368
29664
|
quickQuestions: result.quickQuestions,
|
|
28369
29665
|
agentGuidance: result.agentGuidance
|
|
28370
29666
|
}
|
|
@@ -28386,7 +29682,7 @@ function registerProductSpecAssist(server) {
|
|
|
28386
29682
|
function createServer() {
|
|
28387
29683
|
const server = new McpServer({
|
|
28388
29684
|
name: "product-spec-mcp",
|
|
28389
|
-
version: "0.3.
|
|
29685
|
+
version: "0.3.26"
|
|
28390
29686
|
});
|
|
28391
29687
|
registerSpecInterrogate(server);
|
|
28392
29688
|
registerSpecCompile(server);
|