archgraph-argo 0.10.37 → 0.10.39
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.
|
@@ -155,7 +155,7 @@ const TOOLS = [
|
|
|
155
155
|
},
|
|
156
156
|
{
|
|
157
157
|
name: 'updateArchitectureElement',
|
|
158
|
-
description: 'Use for one global element metadata patch. Does not change view membership. Element id and type are immutable; remove and re-add to change them.',
|
|
158
|
+
description: 'Use for one global element metadata patch. Does not change view membership. Element id and type are immutable; remove and re-add to change them. patch.attributes is a targeted merge by attribute name: each entry {name, value?, description?} upserts that attribute, {name, op:"remove"} deletes it, and attributes NOT mentioned are preserved — updating one attribute never wipes out the others.',
|
|
159
159
|
inputSchema: {
|
|
160
160
|
type: 'object',
|
|
161
161
|
required: ['id', 'patch'],
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const fs = require('node:fs');
|
|
2
|
+
const os = require('node:os');
|
|
2
3
|
const path = require('node:path');
|
|
3
4
|
const { fileURLToPath } = require('node:url');
|
|
4
5
|
|
|
@@ -109,6 +110,15 @@ function getArgoEnvPath() {
|
|
|
109
110
|
return path.resolve(process.env.ARGO_ENV_FILE);
|
|
110
111
|
}
|
|
111
112
|
|
|
113
|
+
// Prefer the global clean env (<user-home>/.argo/.env) when present, so a
|
|
114
|
+
// workspace-local env file (which may carry non-whitelisted keys, e.g.
|
|
115
|
+
// repo argo/.env with DEEPSEEK_* that fails the secret-ACL) never shadows the
|
|
116
|
+
// sanctioned global configuration for semantic/embedding lifecycle.
|
|
117
|
+
const homeEnvPath = path.join(os.homedir(), '.argo', '.env');
|
|
118
|
+
if (fs.existsSync(homeEnvPath)) {
|
|
119
|
+
return homeEnvPath;
|
|
120
|
+
}
|
|
121
|
+
|
|
112
122
|
const globalPath = path.join(getArgoRoot(), '.env');
|
|
113
123
|
if (fs.existsSync(globalPath)) {
|
|
114
124
|
return globalPath;
|
|
@@ -248,7 +248,7 @@ const TOOLS = [
|
|
|
248
248
|
},
|
|
249
249
|
{
|
|
250
250
|
name: 'updateArchitectureElement',
|
|
251
|
-
description: 'Use for one global element metadata patch. Does not change view membership. Element id and type are immutable; remove and re-add to change them. Set dryRun to preview without writing.',
|
|
251
|
+
description: 'Use for one global element metadata patch. Does not change view membership. Element id and type are immutable; remove and re-add to change them. patch.attributes is a targeted merge by attribute name: each entry {name, value?, description?} upserts that attribute, {name, op:"remove"} deletes it, and attributes NOT mentioned are preserved — updating one attribute never wipes out the others. Set dryRun to preview without writing.',
|
|
252
252
|
inputSchema: {
|
|
253
253
|
type: 'object',
|
|
254
254
|
required: ['id', 'patch'],
|
|
@@ -1031,6 +1031,50 @@ function buildNativeSubgraph(document, includedElementIds, includedRelationshipI
|
|
|
1031
1031
|
return { elements, relationships, views };
|
|
1032
1032
|
}
|
|
1033
1033
|
|
|
1034
|
+
/**
|
|
1035
|
+
* Merge a targeted attribute patch into the element's existing attributes.
|
|
1036
|
+
*
|
|
1037
|
+
* Each patch entry is an object with a non-empty `name`:
|
|
1038
|
+
* - `{ name, op: 'remove' }` -> remove that attribute;
|
|
1039
|
+
* - `{ name, value }` / `{ name, value, description }` -> upsert (add or update in place).
|
|
1040
|
+
*
|
|
1041
|
+
* Attributes NOT mentioned in the patch are preserved. This avoids the
|
|
1042
|
+
* full-array replacement footgun where updating one attribute would wipe out the
|
|
1043
|
+
* rest (e.g. a stale deliveryStatus being re-written when registering a commit
|
|
1044
|
+
* attribute).
|
|
1045
|
+
*/
|
|
1046
|
+
function mergeAttributesPatch(existing, patchEntries) {
|
|
1047
|
+
const result = Array.isArray(existing)
|
|
1048
|
+
? existing.map(attr => ({ ...attr }))
|
|
1049
|
+
: [];
|
|
1050
|
+
if (!Array.isArray(patchEntries)) {
|
|
1051
|
+
throw new Error('patch.attributes must be an array of { name, ... } entries');
|
|
1052
|
+
}
|
|
1053
|
+
for (const entry of patchEntries) {
|
|
1054
|
+
if (!entry || typeof entry !== 'object' || typeof entry.name !== 'string' || entry.name.trim() === '') {
|
|
1055
|
+
throw new Error('patch.attributes entries must have a non-empty string name');
|
|
1056
|
+
}
|
|
1057
|
+
if (entry.op === 'remove') {
|
|
1058
|
+
const index = result.findIndex(attr => attr.name === entry.name);
|
|
1059
|
+
if (index >= 0) {
|
|
1060
|
+
result.splice(index, 1);
|
|
1061
|
+
}
|
|
1062
|
+
continue;
|
|
1063
|
+
}
|
|
1064
|
+
const index = result.findIndex(attr => attr.name === entry.name);
|
|
1065
|
+
if (index >= 0) {
|
|
1066
|
+
if (Object.prototype.hasOwnProperty.call(entry, 'value')) result[index].value = entry.value;
|
|
1067
|
+
if (Object.prototype.hasOwnProperty.call(entry, 'description')) result[index].description = entry.description;
|
|
1068
|
+
} else {
|
|
1069
|
+
const newAttribute = { name: entry.name };
|
|
1070
|
+
if (Object.prototype.hasOwnProperty.call(entry, 'value')) newAttribute.value = entry.value;
|
|
1071
|
+
if (Object.prototype.hasOwnProperty.call(entry, 'description')) newAttribute.description = entry.description;
|
|
1072
|
+
result.push(newAttribute);
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
return result;
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1034
1078
|
function applyMutations(document, mutations) {
|
|
1035
1079
|
const nextDocument = clone(document);
|
|
1036
1080
|
const touchedElementIds = new Set();
|
|
@@ -1082,7 +1126,17 @@ function applyMutations(document, mutations) {
|
|
|
1082
1126
|
requirePatchDoesNotChangeElementIdentityOrType(mutation.id, mutation.patch);
|
|
1083
1127
|
const patchesSubdiagramViews = Object.prototype.hasOwnProperty.call(mutation.patch, 'subdiagram_views');
|
|
1084
1128
|
const patchesName = Object.prototype.hasOwnProperty.call(mutation.patch, 'name');
|
|
1085
|
-
|
|
1129
|
+
const patch = clone(mutation.patch);
|
|
1130
|
+
if (Object.prototype.hasOwnProperty.call(patch, 'attributes')) {
|
|
1131
|
+
// Targeted attribute merge by name (upsert / op:'remove'), preserving every
|
|
1132
|
+
// attribute not mentioned in the patch — never a full-array replacement,
|
|
1133
|
+
// so updating one attribute cannot wipe out the others.
|
|
1134
|
+
patch.attributes = mergeAttributesPatch(
|
|
1135
|
+
Array.isArray(element.attributes) ? element.attributes : [],
|
|
1136
|
+
patch.attributes,
|
|
1137
|
+
);
|
|
1138
|
+
}
|
|
1139
|
+
Object.assign(element, patch);
|
|
1086
1140
|
if (patchesSubdiagramViews || patchesName) {
|
|
1087
1141
|
reconcileSubdiagramViewsForElement(nextDocument, element);
|
|
1088
1142
|
}
|
package/package.json
CHANGED