@ksm0709/context 0.0.18 → 0.0.20
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 +4 -0
- package/dist/cli/index.js +177 -39
- package/dist/index.js +116 -64
- package/dist/omx/index.mjs +1013 -0
- package/package.json +10 -6
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// src/index.ts
|
|
3
|
-
import { join as
|
|
3
|
+
import { isAbsolute, join as join5 } from "path";
|
|
4
4
|
|
|
5
5
|
// node_modules/jsonc-parser/lib/esm/impl/scanner.js
|
|
6
6
|
function createScanner(text, ignoreTrivia = false) {
|
|
@@ -808,18 +808,19 @@ var ParseErrorCode;
|
|
|
808
808
|
|
|
809
809
|
// src/lib/config.ts
|
|
810
810
|
import { readFileSync } from "fs";
|
|
811
|
-
import { join } from "path";
|
|
811
|
+
import { join as join2 } from "path";
|
|
812
812
|
|
|
813
813
|
// src/constants.ts
|
|
814
814
|
var DEFAULTS = {
|
|
815
|
-
configPath: ".
|
|
816
|
-
promptDir: ".
|
|
815
|
+
configPath: ".context/config.jsonc",
|
|
816
|
+
promptDir: ".context/prompts",
|
|
817
817
|
turnStartFile: "turn-start.md",
|
|
818
818
|
turnEndFile: "turn-end.md",
|
|
819
819
|
knowledgeSources: ["AGENTS.md"],
|
|
820
|
-
templateDir: ".
|
|
820
|
+
templateDir: ".context/templates",
|
|
821
821
|
indexFilename: "INDEX.md",
|
|
822
|
-
maxDomainDepth: 2
|
|
822
|
+
maxDomainDepth: 2,
|
|
823
|
+
knowledgeDir: "docs"
|
|
823
824
|
};
|
|
824
825
|
var LIMITS = {
|
|
825
826
|
maxPromptFileSize: 64 * 1024,
|
|
@@ -830,12 +831,27 @@ var LIMITS = {
|
|
|
830
831
|
maxIndexFileSize: 32 * 1024
|
|
831
832
|
};
|
|
832
833
|
|
|
834
|
+
// src/lib/context-dir.ts
|
|
835
|
+
import { existsSync } from "fs";
|
|
836
|
+
import { join } from "path";
|
|
837
|
+
function resolveContextDir(projectDir) {
|
|
838
|
+
const nextContextDir = ".context";
|
|
839
|
+
if (existsSync(join(projectDir, nextContextDir))) {
|
|
840
|
+
return nextContextDir;
|
|
841
|
+
}
|
|
842
|
+
const legacyContextDir = ".opencode/context";
|
|
843
|
+
if (existsSync(join(projectDir, legacyContextDir))) {
|
|
844
|
+
return legacyContextDir;
|
|
845
|
+
}
|
|
846
|
+
return nextContextDir;
|
|
847
|
+
}
|
|
848
|
+
|
|
833
849
|
// src/lib/config.ts
|
|
834
850
|
function getDefaultConfig() {
|
|
835
851
|
return {
|
|
836
852
|
prompts: {
|
|
837
|
-
turnStart:
|
|
838
|
-
turnEnd:
|
|
853
|
+
turnStart: join2(DEFAULTS.promptDir, DEFAULTS.turnStartFile),
|
|
854
|
+
turnEnd: join2(DEFAULTS.promptDir, DEFAULTS.turnEndFile)
|
|
839
855
|
},
|
|
840
856
|
knowledge: {
|
|
841
857
|
dir: "docs",
|
|
@@ -843,6 +859,11 @@ function getDefaultConfig() {
|
|
|
843
859
|
mode: "auto",
|
|
844
860
|
indexFilename: DEFAULTS.indexFilename,
|
|
845
861
|
maxDomainDepth: DEFAULTS.maxDomainDepth
|
|
862
|
+
},
|
|
863
|
+
omx: {
|
|
864
|
+
turnEnd: {
|
|
865
|
+
strategy: "turn-complete-sendkeys"
|
|
866
|
+
}
|
|
846
867
|
}
|
|
847
868
|
};
|
|
848
869
|
}
|
|
@@ -859,11 +880,16 @@ function mergeWithDefaults(partial) {
|
|
|
859
880
|
mode: partial.knowledge?.mode ?? defaults.knowledge.mode,
|
|
860
881
|
indexFilename: partial.knowledge?.indexFilename ?? defaults.knowledge.indexFilename,
|
|
861
882
|
maxDomainDepth: partial.knowledge?.maxDomainDepth ?? defaults.knowledge.maxDomainDepth
|
|
883
|
+
},
|
|
884
|
+
omx: {
|
|
885
|
+
turnEnd: {
|
|
886
|
+
strategy: partial.omx?.turnEnd?.strategy ?? defaults.omx?.turnEnd?.strategy
|
|
887
|
+
}
|
|
862
888
|
}
|
|
863
889
|
};
|
|
864
890
|
}
|
|
865
891
|
function loadConfig(projectDir) {
|
|
866
|
-
const configPath =
|
|
892
|
+
const configPath = join2(projectDir, resolveContextDir(projectDir), "config.jsonc");
|
|
867
893
|
try {
|
|
868
894
|
const raw = readFileSync(configPath, "utf-8");
|
|
869
895
|
const parsed = parse2(raw);
|
|
@@ -876,8 +902,8 @@ function loadConfig(projectDir) {
|
|
|
876
902
|
}
|
|
877
903
|
|
|
878
904
|
// src/lib/knowledge-index.ts
|
|
879
|
-
import { readdirSync, readFileSync as readFileSync2, statSync, existsSync } from "fs";
|
|
880
|
-
import { join as
|
|
905
|
+
import { readdirSync, readFileSync as readFileSync2, statSync, existsSync as existsSync2 } from "fs";
|
|
906
|
+
import { join as join3, relative, extname } from "path";
|
|
881
907
|
function extractSummary(filePath) {
|
|
882
908
|
try {
|
|
883
909
|
const content = readFileSync2(filePath, "utf-8");
|
|
@@ -900,7 +926,7 @@ function scanDir(dir, projectDir, depth, entries) {
|
|
|
900
926
|
for (const item of items) {
|
|
901
927
|
if (entries.length >= LIMITS.maxIndexEntries)
|
|
902
928
|
break;
|
|
903
|
-
const fullPath =
|
|
929
|
+
const fullPath = join3(dir, item);
|
|
904
930
|
try {
|
|
905
931
|
const stat = statSync(fullPath);
|
|
906
932
|
if (stat.isDirectory()) {
|
|
@@ -920,8 +946,8 @@ function buildKnowledgeIndex(projectDir, sources) {
|
|
|
920
946
|
for (const source of sources) {
|
|
921
947
|
if (entries.length >= LIMITS.maxIndexEntries)
|
|
922
948
|
break;
|
|
923
|
-
const fullPath =
|
|
924
|
-
if (!
|
|
949
|
+
const fullPath = join3(projectDir, source);
|
|
950
|
+
if (!existsSync2(fullPath))
|
|
925
951
|
continue;
|
|
926
952
|
try {
|
|
927
953
|
const stat = statSync(fullPath);
|
|
@@ -950,7 +976,7 @@ function formatKnowledgeIndex(entries) {
|
|
|
950
976
|
function countMdFiles(dir, indexFilename) {
|
|
951
977
|
try {
|
|
952
978
|
const items = readdirSync(dir);
|
|
953
|
-
return items.filter((item) => extname(item) === ".md" && item !== indexFilename && statSync(
|
|
979
|
+
return items.filter((item) => extname(item) === ".md" && item !== indexFilename && statSync(join3(dir, item)).isFile()).length;
|
|
954
980
|
} catch {
|
|
955
981
|
return 0;
|
|
956
982
|
}
|
|
@@ -961,12 +987,12 @@ function scanDomainsRecursive(baseDir, projectDir, indexFilename, currentDepth,
|
|
|
961
987
|
try {
|
|
962
988
|
const items = readdirSync(baseDir);
|
|
963
989
|
for (const item of items) {
|
|
964
|
-
const fullPath =
|
|
990
|
+
const fullPath = join3(baseDir, item);
|
|
965
991
|
try {
|
|
966
992
|
if (!statSync(fullPath).isDirectory())
|
|
967
993
|
continue;
|
|
968
|
-
const indexPath =
|
|
969
|
-
if (
|
|
994
|
+
const indexPath = join3(fullPath, indexFilename);
|
|
995
|
+
if (existsSync2(indexPath) && statSync(indexPath).isFile()) {
|
|
970
996
|
const rawContent = readFileSync2(indexPath, "utf-8");
|
|
971
997
|
const indexContent = rawContent.slice(0, LIMITS.maxIndexFileSize);
|
|
972
998
|
results.push({
|
|
@@ -982,8 +1008,8 @@ function scanDomainsRecursive(baseDir, projectDir, indexFilename, currentDepth,
|
|
|
982
1008
|
} catch {}
|
|
983
1009
|
}
|
|
984
1010
|
function scanDomains(projectDir, knowledgeDir, indexFilename, maxDepth) {
|
|
985
|
-
const baseDir =
|
|
986
|
-
if (!
|
|
1011
|
+
const baseDir = join3(projectDir, knowledgeDir);
|
|
1012
|
+
if (!existsSync2(baseDir))
|
|
987
1013
|
return [];
|
|
988
1014
|
const results = [];
|
|
989
1015
|
scanDomainsRecursive(baseDir, projectDir, indexFilename, 1, maxDepth, results);
|
|
@@ -1020,14 +1046,14 @@ function formatDomainIndex(index) {
|
|
|
1020
1046
|
`);
|
|
1021
1047
|
}
|
|
1022
1048
|
function collectRootFiles(projectDir, knowledgeDir, indexFilename) {
|
|
1023
|
-
const baseDir =
|
|
1024
|
-
if (!
|
|
1049
|
+
const baseDir = join3(projectDir, knowledgeDir);
|
|
1050
|
+
if (!existsSync2(baseDir))
|
|
1025
1051
|
return [];
|
|
1026
1052
|
const entries = [];
|
|
1027
1053
|
try {
|
|
1028
1054
|
const items = readdirSync(baseDir);
|
|
1029
1055
|
for (const item of items) {
|
|
1030
|
-
const fullPath =
|
|
1056
|
+
const fullPath = join3(baseDir, item);
|
|
1031
1057
|
try {
|
|
1032
1058
|
const stat = statSync(fullPath);
|
|
1033
1059
|
if (stat.isFile() && extname(item) === ".md" && item !== indexFilename) {
|
|
@@ -1056,8 +1082,8 @@ function buildKnowledgeIndexV2(projectDir, knowledgeConfig) {
|
|
|
1056
1082
|
const rootFiles = collectRootFiles(projectDir, dir, indexFilename);
|
|
1057
1083
|
const sourcesEntries = [];
|
|
1058
1084
|
for (const source of knowledgeConfig.sources) {
|
|
1059
|
-
const fullPath =
|
|
1060
|
-
if (!
|
|
1085
|
+
const fullPath = join3(projectDir, source);
|
|
1086
|
+
if (!existsSync2(fullPath))
|
|
1061
1087
|
continue;
|
|
1062
1088
|
try {
|
|
1063
1089
|
const stat = statSync(fullPath);
|
|
@@ -1086,14 +1112,18 @@ function readPromptFile(filePath) {
|
|
|
1086
1112
|
return "";
|
|
1087
1113
|
}
|
|
1088
1114
|
}
|
|
1115
|
+
function resolvePromptVariables(content, vars) {
|
|
1116
|
+
const normalized = (vars.knowledgeDir || "docs").replace(/\\/g, "/").replace(/\/+$/, "");
|
|
1117
|
+
return content.replaceAll("{{knowledgeDir}}", normalized);
|
|
1118
|
+
}
|
|
1089
1119
|
|
|
1090
1120
|
// src/lib/scaffold.ts
|
|
1091
|
-
import { existsSync as
|
|
1092
|
-
import { join as
|
|
1121
|
+
import { existsSync as existsSync3, mkdirSync, readFileSync as readFileSync4, writeFileSync } from "fs";
|
|
1122
|
+
import { join as join4 } from "path";
|
|
1093
1123
|
// package.json
|
|
1094
1124
|
var package_default = {
|
|
1095
1125
|
name: "@ksm0709/context",
|
|
1096
|
-
version: "0.0.
|
|
1126
|
+
version: "0.0.20",
|
|
1097
1127
|
author: {
|
|
1098
1128
|
name: "TaehoKang",
|
|
1099
1129
|
email: "ksm07091@gmail.com"
|
|
@@ -1101,27 +1131,32 @@ var package_default = {
|
|
|
1101
1131
|
type: "module",
|
|
1102
1132
|
main: "./dist/index.js",
|
|
1103
1133
|
bin: {
|
|
1104
|
-
context: "
|
|
1134
|
+
context: "dist/cli/index.js"
|
|
1105
1135
|
},
|
|
1106
1136
|
exports: {
|
|
1107
1137
|
".": {
|
|
1108
1138
|
import: "./dist/index.js",
|
|
1109
1139
|
types: "./dist/index.d.ts",
|
|
1110
1140
|
default: "./dist/index.js"
|
|
1141
|
+
},
|
|
1142
|
+
"./omx": {
|
|
1143
|
+
import: "./dist/omx/index.mjs",
|
|
1144
|
+
types: "./dist/omx/index.d.ts",
|
|
1145
|
+
default: "./dist/omx/index.mjs"
|
|
1111
1146
|
}
|
|
1112
1147
|
},
|
|
1113
1148
|
repository: {
|
|
1114
1149
|
type: "git",
|
|
1115
|
-
url: "git@github.com
|
|
1150
|
+
url: "git+ssh://git@github.com/ksm0709/context.git"
|
|
1116
1151
|
},
|
|
1117
1152
|
publishConfig: {
|
|
1118
1153
|
access: "public"
|
|
1119
1154
|
},
|
|
1120
1155
|
scripts: {
|
|
1121
|
-
build: "bun build ./src/index.ts --outdir dist --target bun && bun build ./src/cli/index.ts --outdir dist/cli --target bun",
|
|
1156
|
+
build: "bun build ./src/index.ts --outdir dist --target bun && bun build ./src/cli/index.ts --outdir dist/cli --target bun && bun build ./src/omx/index.ts --outdir dist/omx --target node --format esm --external jsonc-parser && mv dist/omx/index.js dist/omx/index.mjs",
|
|
1122
1157
|
test: "vitest run",
|
|
1123
1158
|
lint: "eslint src --ext .ts",
|
|
1124
|
-
prepublishOnly: "bun build ./src/index.ts --outdir dist --target bun && bun build ./src/cli/index.ts --outdir dist/cli --target bun"
|
|
1159
|
+
prepublishOnly: "bun build ./src/index.ts --outdir dist --target bun && bun build ./src/cli/index.ts --outdir dist/cli --target bun && bun build ./src/omx/index.ts --outdir dist/omx --target node --format esm --external jsonc-parser && mv dist/omx/index.js dist/omx/index.mjs"
|
|
1125
1160
|
},
|
|
1126
1161
|
files: [
|
|
1127
1162
|
"dist"
|
|
@@ -1130,7 +1165,6 @@ var package_default = {
|
|
|
1130
1165
|
"@opencode-ai/plugin": ">=1.0.0"
|
|
1131
1166
|
},
|
|
1132
1167
|
dependencies: {
|
|
1133
|
-
"@ksm0709/context": "^0.0.17",
|
|
1134
1168
|
"jsonc-parser": "^3.0.0"
|
|
1135
1169
|
},
|
|
1136
1170
|
devDependencies: {
|
|
@@ -1156,12 +1190,18 @@ var DEFAULT_CONFIG = `{
|
|
|
1156
1190
|
// Context Plugin Configuration
|
|
1157
1191
|
// See: https://github.com/ksm0709/context
|
|
1158
1192
|
"prompts": {
|
|
1159
|
-
"turnStart": "
|
|
1160
|
-
"turnEnd": "
|
|
1193
|
+
"turnStart": "prompts/turn-start.md",
|
|
1194
|
+
"turnEnd": "prompts/turn-end.md"
|
|
1161
1195
|
},
|
|
1162
1196
|
"knowledge": {
|
|
1163
1197
|
"dir": "docs",
|
|
1164
1198
|
"sources": ["AGENTS.md"]
|
|
1199
|
+
},
|
|
1200
|
+
"omx": {
|
|
1201
|
+
// Inject turn-end after native turn-complete via tmux send-keys
|
|
1202
|
+
"turnEnd": {
|
|
1203
|
+
"strategy": "turn-complete-sendkeys"
|
|
1204
|
+
}
|
|
1165
1205
|
}
|
|
1166
1206
|
}`;
|
|
1167
1207
|
var DEFAULT_TURN_START = `## Knowledge Context
|
|
@@ -1215,21 +1255,21 @@ var DEFAULT_TURN_END = `## \uC791\uC5C5 \uB9C8\uBB34\uB9AC
|
|
|
1215
1255
|
|
|
1216
1256
|
| \uC0C1\uD669 | \uD15C\uD50C\uB9BF | \uD30C\uC77C\uBA85 \uD328\uD134 |
|
|
1217
1257
|
| ------------------------------- | --------------------------------------------------- | --------------------------- |
|
|
1218
|
-
| \uC544\uD0A4\uD14D\uCC98/\uAE30\uC220 \uC2A4\uD0DD \uC911\uB300 \uACB0\uC815 | [ADR](.
|
|
1219
|
-
| \uBC18\uBCF5 \uC0AC\uC6A9\uD560 \uCF54\uB4DC \uD328\uD134 \uBC1C\uACAC | [Pattern](.
|
|
1220
|
-
| \uBE44\uC790\uBA85\uD55C \uBC84\uADF8 \uD574\uACB0 | [Bug](.
|
|
1221
|
-
| \uC678\uBD80 API/\uB77C\uC774\uBE0C\uB7EC\uB9AC \uC608\uC0C1\uC678 \uB3D9\uC791 | [Gotcha](.
|
|
1222
|
-
| \uC791\uC740 \uAE30\uC220\uC801 \uC120\uD0DD | [Decision](.
|
|
1223
|
-
| \uBAA8\uB4C8/\uD504\uB85C\uC81D\uD2B8 \uAC1C\uC694 \uD544\uC694 | [Context](.
|
|
1224
|
-
| \uBC18\uBCF5 \uAC00\uB2A5\uD55C \uD504\uB85C\uC138\uC2A4 \uC815\uB9BD | [Runbook](.
|
|
1225
|
-
| \uC2E4\uD5D8/\uB514\uBC84\uAE45 \uC911 \uD559\uC2B5 | [Insight](.
|
|
1258
|
+
| \uC544\uD0A4\uD14D\uCC98/\uAE30\uC220 \uC2A4\uD0DD \uC911\uB300 \uACB0\uC815 | [ADR](.context/templates/adr.md) | \`adr-NNN-\uC81C\uBAA9.md\` |
|
|
1259
|
+
| \uBC18\uBCF5 \uC0AC\uC6A9\uD560 \uCF54\uB4DC \uD328\uD134 \uBC1C\uACAC | [Pattern](.context/templates/pattern.md) | \`pattern-\uC81C\uBAA9.md\` |
|
|
1260
|
+
| \uBE44\uC790\uBA85\uD55C \uBC84\uADF8 \uD574\uACB0 | [Bug](.context/templates/bug.md) | \`bug-\uC81C\uBAA9.md\` |
|
|
1261
|
+
| \uC678\uBD80 API/\uB77C\uC774\uBE0C\uB7EC\uB9AC \uC608\uC0C1\uC678 \uB3D9\uC791 | [Gotcha](.context/templates/gotcha.md) | \`gotcha-\uB77C\uC774\uBE0C\uB7EC\uB9AC-\uC81C\uBAA9.md\` |
|
|
1262
|
+
| \uC791\uC740 \uAE30\uC220\uC801 \uC120\uD0DD | [Decision](.context/templates/decision.md) | \`decision-\uC81C\uBAA9.md\` |
|
|
1263
|
+
| \uBAA8\uB4C8/\uD504\uB85C\uC81D\uD2B8 \uAC1C\uC694 \uD544\uC694 | [Context](.context/templates/context.md) | \`context-\uC81C\uBAA9.md\` |
|
|
1264
|
+
| \uBC18\uBCF5 \uAC00\uB2A5\uD55C \uD504\uB85C\uC138\uC2A4 \uC815\uB9BD | [Runbook](.context/templates/runbook.md) | \`runbook-\uC81C\uBAA9.md\` |
|
|
1265
|
+
| \uC2E4\uD5D8/\uB514\uBC84\uAE45 \uC911 \uD559\uC2B5 | [Insight](.context/templates/insight.md) | \`insight-\uC81C\uBAA9.md\` |
|
|
1226
1266
|
|
|
1227
1267
|
\uD574\uB2F9 \uC0AC\uD56D\uC774 \uC5C6\uC73C\uBA74 \uC774 \uB2E8\uACC4\uB294 \uAC74\uB108\uB6F0\uC138\uC694.
|
|
1228
1268
|
|
|
1229
1269
|
- \uAD00\uB828 \uD15C\uD50C\uB9BF \uD30C\uC77C\uC744 \uC77D\uACE0 \uADF8 \uAD6C\uC870\uC5D0 \uB9DE\uCDB0 \uB0B4\uC6A9\uC744 \uC815\uB9AC\uD558\uC138\uC694
|
|
1230
1270
|
- \uB178\uD2B8 \uCCAB \uC904\uC740 \uBA85\uD655\uD55C \uC81C\uBAA9(\`# Title\`)\uC73C\uB85C \uC2DC\uC791\uD558\uC138\uC694
|
|
1231
1271
|
- \uD575\uC2EC \uB0B4\uC6A9\uC744 \uC790\uAE30 \uC5B8\uC5B4\uB85C \uAC04\uACB0\uD558\uAC8C \uC11C\uC220\uD558\uACE0, \uAD00\uB828 \uB178\uD2B8\uB294 \`[[relative/path/file.md]]\` \uD615\uD0DC\uB85C \uC5F0\uACB0\uD558\uC138\uC694
|
|
1232
|
-
- knowledge \uB514\uB809\uD1A0\uB9AC(
|
|
1272
|
+
- knowledge \uB514\uB809\uD1A0\uB9AC(\`{{knowledgeDir}}/\`) \uB610\uB294 \uC801\uC808\uD55C \uB3C4\uBA54\uC778 \uD3F4\uB354\uC5D0 \uC800\uC7A5\uD558\uACE0, \uD544\uC694\uD55C \uACBD\uC6B0 \uAE30\uC874 INDEX.md\uB098 \uAD00\uB828 \uB178\uD2B8\uB97C \uD568\uAED8 \uAC31\uC2E0\uD558\uC138\uC694
|
|
1233
1273
|
|
|
1234
1274
|
\uAE30\uC874 \uC124\uCE58\uC758 \uC0AC\uC6A9\uC790 \uD504\uB86C\uD504\uD2B8 \uD30C\uC77C\uC740 \uC790\uB3D9\uC73C\uB85C \uBC14\uB00C\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uC0C8 \uAE30\uBCF8 \uD504\uB86C\uD504\uD2B8\uAC00 \uD544\uC694\uD558\uBA74 \`context update prompt\`\uB85C \uBA85\uC2DC\uC801\uC73C\uB85C \uC0C8\uB85C\uACE0\uCE68\uD558\uC138\uC694.
|
|
1235
1275
|
`;
|
|
@@ -1451,20 +1491,20 @@ var TEMPLATE_FILES = {
|
|
|
1451
1491
|
"index.md": DEFAULT_INDEX_TEMPLATE
|
|
1452
1492
|
};
|
|
1453
1493
|
function scaffoldIfNeeded(projectDir) {
|
|
1454
|
-
const contextDir =
|
|
1455
|
-
if (
|
|
1494
|
+
const contextDir = join4(projectDir, resolveContextDir(projectDir));
|
|
1495
|
+
if (existsSync3(contextDir)) {
|
|
1456
1496
|
return false;
|
|
1457
1497
|
}
|
|
1458
1498
|
try {
|
|
1459
|
-
const promptsDir =
|
|
1499
|
+
const promptsDir = join4(contextDir, "prompts");
|
|
1460
1500
|
mkdirSync(promptsDir, { recursive: true });
|
|
1461
|
-
const templatesDir =
|
|
1501
|
+
const templatesDir = join4(contextDir, "templates");
|
|
1462
1502
|
mkdirSync(templatesDir, { recursive: true });
|
|
1463
|
-
writeFileSync(
|
|
1464
|
-
writeFileSync(
|
|
1465
|
-
writeFileSync(
|
|
1503
|
+
writeFileSync(join4(contextDir, "config.jsonc"), DEFAULT_CONFIG, "utf-8");
|
|
1504
|
+
writeFileSync(join4(promptsDir, DEFAULTS.turnStartFile), DEFAULT_TURN_START, "utf-8");
|
|
1505
|
+
writeFileSync(join4(promptsDir, DEFAULTS.turnEndFile), DEFAULT_TURN_END, "utf-8");
|
|
1466
1506
|
for (const [filename, content] of Object.entries(TEMPLATE_FILES)) {
|
|
1467
|
-
writeFileSync(
|
|
1507
|
+
writeFileSync(join4(templatesDir, filename), content, "utf-8");
|
|
1468
1508
|
}
|
|
1469
1509
|
writeVersion(contextDir, PLUGIN_VERSION);
|
|
1470
1510
|
return true;
|
|
@@ -1474,25 +1514,25 @@ function scaffoldIfNeeded(projectDir) {
|
|
|
1474
1514
|
}
|
|
1475
1515
|
function getStoredVersion(projectDir) {
|
|
1476
1516
|
try {
|
|
1477
|
-
return readFileSync4(
|
|
1517
|
+
return readFileSync4(join4(projectDir, resolveContextDir(projectDir), ".version"), "utf-8").trim();
|
|
1478
1518
|
} catch {
|
|
1479
1519
|
return null;
|
|
1480
1520
|
}
|
|
1481
1521
|
}
|
|
1482
1522
|
function writeVersion(contextDir, version) {
|
|
1483
|
-
writeFileSync(
|
|
1523
|
+
writeFileSync(join4(contextDir, ".version"), version, "utf-8");
|
|
1484
1524
|
}
|
|
1485
1525
|
function autoUpdateTemplates(projectDir) {
|
|
1486
|
-
const contextDir =
|
|
1487
|
-
if (!
|
|
1526
|
+
const contextDir = join4(projectDir, resolveContextDir(projectDir));
|
|
1527
|
+
if (!existsSync3(contextDir))
|
|
1488
1528
|
return [];
|
|
1489
1529
|
const stored = getStoredVersion(projectDir);
|
|
1490
1530
|
if (stored === PLUGIN_VERSION)
|
|
1491
1531
|
return [];
|
|
1492
|
-
mkdirSync(
|
|
1532
|
+
mkdirSync(join4(contextDir, "templates"), { recursive: true });
|
|
1493
1533
|
const updated = [];
|
|
1494
1534
|
for (const [filename, content] of Object.entries(TEMPLATE_FILES)) {
|
|
1495
|
-
const filePath =
|
|
1535
|
+
const filePath = join4(contextDir, "templates", filename);
|
|
1496
1536
|
try {
|
|
1497
1537
|
const existing = readFileSync4(filePath, "utf-8");
|
|
1498
1538
|
if (existing === content)
|
|
@@ -1506,14 +1546,23 @@ function autoUpdateTemplates(projectDir) {
|
|
|
1506
1546
|
}
|
|
1507
1547
|
|
|
1508
1548
|
// src/index.ts
|
|
1549
|
+
function resolvePromptPath(directory, contextDir, promptPath) {
|
|
1550
|
+
if (isAbsolute(promptPath))
|
|
1551
|
+
return promptPath;
|
|
1552
|
+
if (promptPath.startsWith(".context/") || promptPath.startsWith(".opencode/")) {
|
|
1553
|
+
return join5(directory, promptPath);
|
|
1554
|
+
}
|
|
1555
|
+
return join5(directory, contextDir, promptPath);
|
|
1556
|
+
}
|
|
1509
1557
|
var plugin = async ({ directory, client }) => {
|
|
1510
1558
|
const scaffolded = scaffoldIfNeeded(directory);
|
|
1559
|
+
const contextDir = resolveContextDir(directory);
|
|
1511
1560
|
if (scaffolded) {
|
|
1512
1561
|
await client.app.log({
|
|
1513
1562
|
body: {
|
|
1514
1563
|
service: "context",
|
|
1515
1564
|
level: "info",
|
|
1516
|
-
message:
|
|
1565
|
+
message: `Scaffold created at ${contextDir}/`
|
|
1517
1566
|
}
|
|
1518
1567
|
});
|
|
1519
1568
|
} else {
|
|
@@ -1536,8 +1585,10 @@ var plugin = async ({ directory, client }) => {
|
|
|
1536
1585
|
const lastUserMsg = output.messages.filter((m) => m.info.role === "user").at(-1);
|
|
1537
1586
|
if (!lastUserMsg)
|
|
1538
1587
|
return;
|
|
1539
|
-
const
|
|
1540
|
-
const
|
|
1588
|
+
const promptVars = { knowledgeDir: config.knowledge.dir ?? "docs" };
|
|
1589
|
+
const turnStartPath = resolvePromptPath(directory, contextDir, config.prompts.turnStart ?? join5(DEFAULTS.promptDir, DEFAULTS.turnStartFile));
|
|
1590
|
+
const turnStartRaw = readPromptFile(turnStartPath) ?? "";
|
|
1591
|
+
const turnStart = resolvePromptVariables(turnStartRaw, promptVars);
|
|
1541
1592
|
const knowledgeIndex = buildKnowledgeIndexV2(directory, config.knowledge);
|
|
1542
1593
|
const indexContent = knowledgeIndex.mode === "flat" ? formatKnowledgeIndex(knowledgeIndex.individualFiles) : formatDomainIndex(knowledgeIndex);
|
|
1543
1594
|
const combinedContent = [turnStart, indexContent].filter(Boolean).join(`
|
|
@@ -1552,10 +1603,11 @@ var plugin = async ({ directory, client }) => {
|
|
|
1552
1603
|
text: combinedContent
|
|
1553
1604
|
});
|
|
1554
1605
|
}
|
|
1555
|
-
const turnEndPath =
|
|
1556
|
-
const
|
|
1557
|
-
if (!
|
|
1606
|
+
const turnEndPath = resolvePromptPath(directory, contextDir, config.prompts.turnEnd ?? join5(DEFAULTS.promptDir, DEFAULTS.turnEndFile));
|
|
1607
|
+
const turnEndRaw = readPromptFile(turnEndPath);
|
|
1608
|
+
if (!turnEndRaw)
|
|
1558
1609
|
return;
|
|
1610
|
+
const turnEnd = resolvePromptVariables(turnEndRaw, promptVars);
|
|
1559
1611
|
const msgId = `context-turn-end-${Date.now()}`;
|
|
1560
1612
|
output.messages.push({
|
|
1561
1613
|
info: {
|