@mean-weasel/lineage 0.1.23 → 0.1.25
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/CHANGELOG.md +9 -0
- package/README.md +37 -0
- package/dist/cli/lineage-dev.js +605 -36
- package/dist/cli/lineage-dev.js.map +4 -4
- package/dist/cli/lineage-preview.js +605 -36
- package/dist/cli/lineage-preview.js.map +4 -4
- package/dist/cli/lineage.js +605 -36
- package/dist/cli/lineage.js.map +4 -4
- package/dist/docs-site/operations/channels/index.html +11 -2
- package/dist/docs-site/operations/profiles-database-identity/index.html +16 -2
- package/dist/docs-site/pagefind/fragment/en_761fab1.pf_fragment +0 -0
- package/dist/docs-site/pagefind/fragment/en_bd3e194.pf_fragment +0 -0
- package/dist/docs-site/pagefind/fragment/en_ee82be6.pf_fragment +0 -0
- package/dist/docs-site/pagefind/fragment/en_f4db9e2.pf_fragment +0 -0
- package/dist/docs-site/pagefind/index/en_7b1363c.pf_index +0 -0
- package/dist/docs-site/pagefind/pagefind-entry.json +1 -1
- package/dist/docs-site/pagefind/pagefind.en_4e77743529.pf_meta +0 -0
- package/dist/docs-site/reference/cli/index.html +11 -2
- package/dist/docs-site/start-here/installation-first-run/index.html +7 -1
- package/dist/pages/assets/app-BfxPwDL1.js +50 -0
- package/dist/pages/assets/{app-B-fAyNsU.css → app-CuBsKrS-.css} +1 -1
- package/dist/pages/docs/operations/channels/index.html +11 -2
- package/dist/pages/docs/operations/profiles-database-identity/index.html +16 -2
- package/dist/pages/docs/pagefind/fragment/en_761fab1.pf_fragment +0 -0
- package/dist/pages/docs/pagefind/fragment/en_bd3e194.pf_fragment +0 -0
- package/dist/pages/docs/pagefind/fragment/en_ee82be6.pf_fragment +0 -0
- package/dist/pages/docs/pagefind/fragment/en_f4db9e2.pf_fragment +0 -0
- package/dist/pages/docs/pagefind/index/en_7b1363c.pf_index +0 -0
- package/dist/pages/docs/pagefind/pagefind-entry.json +1 -1
- package/dist/pages/docs/pagefind/pagefind.en_4e77743529.pf_meta +0 -0
- package/dist/pages/docs/reference/cli/index.html +11 -2
- package/dist/pages/docs/start-here/installation-first-run/index.html +7 -1
- package/dist/runtime-build.json +5 -5
- package/dist/server.js +375 -39
- package/dist/server.js.map +4 -4
- package/dist/web/assets/app-BfxPwDL1.js +50 -0
- package/dist/web/assets/{app-B-fAyNsU.css → app-CuBsKrS-.css} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +4 -3
- package/dist/docs-site/pagefind/fragment/en_4db923b.pf_fragment +0 -0
- package/dist/docs-site/pagefind/fragment/en_581a7cb.pf_fragment +0 -0
- package/dist/docs-site/pagefind/fragment/en_8c1c735.pf_fragment +0 -0
- package/dist/docs-site/pagefind/fragment/en_bcc29c5.pf_fragment +0 -0
- package/dist/docs-site/pagefind/index/en_f279b04.pf_index +0 -0
- package/dist/docs-site/pagefind/pagefind.en_74951c3ca7.pf_meta +0 -0
- package/dist/pages/assets/app-DdU93vp2.js +0 -50
- package/dist/pages/docs/pagefind/fragment/en_4db923b.pf_fragment +0 -0
- package/dist/pages/docs/pagefind/fragment/en_581a7cb.pf_fragment +0 -0
- package/dist/pages/docs/pagefind/fragment/en_8c1c735.pf_fragment +0 -0
- package/dist/pages/docs/pagefind/fragment/en_bcc29c5.pf_fragment +0 -0
- package/dist/pages/docs/pagefind/index/en_f279b04.pf_index +0 -0
- package/dist/pages/docs/pagefind/pagefind.en_74951c3ca7.pf_meta +0 -0
- package/dist/web/assets/app-DdU93vp2.js +0 -50
package/dist/server.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/server.ts
|
|
2
2
|
import express2 from "express";
|
|
3
3
|
import multer from "multer";
|
|
4
|
-
import { existsSync as
|
|
4
|
+
import { existsSync as existsSync15 } from "node:fs";
|
|
5
5
|
import { join as join14 } from "node:path";
|
|
6
6
|
|
|
7
7
|
// src/server/assetCore.ts
|
|
@@ -980,6 +980,21 @@ function lineageDb() {
|
|
|
980
980
|
where status = 'pending';
|
|
981
981
|
create index if not exists asset_reroll_requests_root_status
|
|
982
982
|
on asset_reroll_requests(project_id, root_asset_id, status, created_at);
|
|
983
|
+
create table if not exists asset_social_marks (
|
|
984
|
+
id text primary key,
|
|
985
|
+
project_id text not null references projects(id),
|
|
986
|
+
root_asset_id text not null references assets(id),
|
|
987
|
+
asset_id text not null references assets(id),
|
|
988
|
+
notes text,
|
|
989
|
+
marked_by text not null,
|
|
990
|
+
marked_at text not null,
|
|
991
|
+
unmarked_by text,
|
|
992
|
+
unmarked_at text,
|
|
993
|
+
updated_at text not null,
|
|
994
|
+
unique(project_id, root_asset_id, asset_id)
|
|
995
|
+
);
|
|
996
|
+
create index if not exists asset_social_marks_root_active
|
|
997
|
+
on asset_social_marks(project_id, root_asset_id, unmarked_at, marked_at);
|
|
983
998
|
create table if not exists asset_reviews (
|
|
984
999
|
asset_id text primary key references assets(id),
|
|
985
1000
|
review_state text not null check (review_state in ('unreviewed', 'approved', 'needs_revision', 'rejected', 'ignored')),
|
|
@@ -3977,6 +3992,19 @@ function getLineageSnapshot(project, assetId) {
|
|
|
3977
3992
|
const request = rerollRequestFrom(row);
|
|
3978
3993
|
return [request.node_asset_id, withRerollTask(request, lineageTasksByNode.get(request.node_asset_id)?.reroll)];
|
|
3979
3994
|
}));
|
|
3995
|
+
const hasSocialMarks = database.prepare("select 1 from sqlite_master where type = 'table' and name = 'asset_social_marks'").get() !== void 0;
|
|
3996
|
+
const socialMarkRows = ids.length > 0 && hasSocialMarks ? database.prepare(`select * from asset_social_marks where project_id = ? and root_asset_id = ? and unmarked_at is null and asset_id in (${placeholders2})`).all(project, root, ...ids) : [];
|
|
3997
|
+
const socialMarksByNode = new Map(socialMarkRows.map((row) => [String(row.asset_id), {
|
|
3998
|
+
active: true,
|
|
3999
|
+
asset_id: String(row.asset_id),
|
|
4000
|
+
id: String(row.id),
|
|
4001
|
+
marked_at: String(row.marked_at),
|
|
4002
|
+
marked_by: String(row.marked_by),
|
|
4003
|
+
notes: rowString(row.notes),
|
|
4004
|
+
project_id: String(row.project_id),
|
|
4005
|
+
root_asset_id: String(row.root_asset_id),
|
|
4006
|
+
updated_at: String(row.updated_at)
|
|
4007
|
+
}]));
|
|
3980
4008
|
const childIds = new Set(edges.map((edge) => edge.parent_asset_id));
|
|
3981
4009
|
const selectedIds = new Set(selected.map((row) => row.asset_id));
|
|
3982
4010
|
const selections = selected.map((row) => ({
|
|
@@ -4005,6 +4033,7 @@ function getLineageSnapshot(project, assetId) {
|
|
|
4005
4033
|
preview_url: canPreviewLocally(row.media_type, previewPath) ? localPreviewUrl(project, previewPath) : void 0,
|
|
4006
4034
|
reroll_request: rerollsByNode.get(row.asset_id),
|
|
4007
4035
|
selection_note: nodeSelection?.notes,
|
|
4036
|
+
social_mark: socialMarksByNode.get(row.asset_id),
|
|
4008
4037
|
user_selected: selectedIds.has(row.asset_id)
|
|
4009
4038
|
};
|
|
4010
4039
|
});
|
|
@@ -4769,6 +4798,11 @@ function removeLineageNode(project, fields) {
|
|
|
4769
4798
|
`);
|
|
4770
4799
|
for (const edge of reparentedEdges) insertEdge.run(edge.id, project, edge.parent_asset_id, edge.child_asset_id, edge.created_at);
|
|
4771
4800
|
database.prepare("delete from asset_layouts where project_id = ? and root_asset_id = ? and asset_id = ?").run(project, root, fields.assetId);
|
|
4801
|
+
database.prepare(`
|
|
4802
|
+
update asset_social_marks
|
|
4803
|
+
set unmarked_by = 'lineage:remove-node', unmarked_at = ?, updated_at = ?
|
|
4804
|
+
where project_id = ? and root_asset_id = ? and asset_id = ? and unmarked_at is null
|
|
4805
|
+
`).run(timestamp, timestamp, project, root, fields.assetId);
|
|
4772
4806
|
compactSelectionsAfterRemove(database, project, root, fields.assetId, timestamp);
|
|
4773
4807
|
database.exec("commit");
|
|
4774
4808
|
} catch (error) {
|
|
@@ -4789,6 +4823,277 @@ function removeLineageNode(project, fields) {
|
|
|
4789
4823
|
};
|
|
4790
4824
|
}
|
|
4791
4825
|
|
|
4826
|
+
// src/server/assetSocialMarks.ts
|
|
4827
|
+
import { accessSync, constants, existsSync as existsSync8 } from "node:fs";
|
|
4828
|
+
import { isAbsolute as isAbsolute3, resolve as resolve6 } from "node:path";
|
|
4829
|
+
function markFromRow(row) {
|
|
4830
|
+
return {
|
|
4831
|
+
active: row.unmarked_at === null,
|
|
4832
|
+
asset_id: row.asset_id,
|
|
4833
|
+
id: row.id,
|
|
4834
|
+
marked_at: row.marked_at,
|
|
4835
|
+
marked_by: row.marked_by,
|
|
4836
|
+
notes: row.notes || void 0,
|
|
4837
|
+
project_id: row.project_id,
|
|
4838
|
+
root_asset_id: row.root_asset_id,
|
|
4839
|
+
unmarked_at: row.unmarked_at || void 0,
|
|
4840
|
+
unmarked_by: row.unmarked_by || void 0,
|
|
4841
|
+
updated_at: row.updated_at
|
|
4842
|
+
};
|
|
4843
|
+
}
|
|
4844
|
+
function requireCanonicalSnapshot(project, rootAssetId) {
|
|
4845
|
+
const snapshot = getLineageSnapshot(project, rootAssetId);
|
|
4846
|
+
if (snapshot.root_asset_id !== rootAssetId) {
|
|
4847
|
+
throw new LineageError(`Asset ${rootAssetId} is not a canonical lineage canvas root`, 400);
|
|
4848
|
+
}
|
|
4849
|
+
return snapshot;
|
|
4850
|
+
}
|
|
4851
|
+
function resolveVisibleNode(snapshot, asset) {
|
|
4852
|
+
const exactId = snapshot.nodes.find((node) => node.asset_id === asset);
|
|
4853
|
+
if (exactId) return exactId;
|
|
4854
|
+
const title = asset.trim().toLocaleLowerCase();
|
|
4855
|
+
const matches = snapshot.nodes.filter((node) => node.title.trim().toLocaleLowerCase() === title);
|
|
4856
|
+
if (matches.length > 1) throw new LineageError(`Asset title "${asset}" matches multiple visible nodes; use an exact asset ID.`, 409);
|
|
4857
|
+
if (matches.length === 1) return matches[0];
|
|
4858
|
+
throw new LineageError(`Asset ${asset} is not visible in lineage canvas ${snapshot.root_asset_id}`, 404);
|
|
4859
|
+
}
|
|
4860
|
+
function rootChannel(snapshot) {
|
|
4861
|
+
return snapshot.nodes.find((node) => node.asset_id === snapshot.root_asset_id)?.channel;
|
|
4862
|
+
}
|
|
4863
|
+
function requireActor(actor, field) {
|
|
4864
|
+
const normalized = actor.trim();
|
|
4865
|
+
if (!normalized) throw new LineageError(`Social mark ${field} is required`);
|
|
4866
|
+
return normalized;
|
|
4867
|
+
}
|
|
4868
|
+
function socialMarkId(project, rootAssetId, assetId) {
|
|
4869
|
+
return `${project}:${rootAssetId}:social:${assetId}`;
|
|
4870
|
+
}
|
|
4871
|
+
function activeRow(project, rootAssetId, assetId) {
|
|
4872
|
+
const database = lineageDb();
|
|
4873
|
+
try {
|
|
4874
|
+
return database.prepare(`
|
|
4875
|
+
select * from asset_social_marks
|
|
4876
|
+
where project_id = ? and root_asset_id = ? and asset_id = ? and unmarked_at is null
|
|
4877
|
+
`).get(project, rootAssetId, assetId);
|
|
4878
|
+
} finally {
|
|
4879
|
+
database.close();
|
|
4880
|
+
}
|
|
4881
|
+
}
|
|
4882
|
+
function mutationResponse(project, rootAssetId, active, mark, dryRun) {
|
|
4883
|
+
return {
|
|
4884
|
+
active,
|
|
4885
|
+
...dryRun ? { dryRun } : {},
|
|
4886
|
+
...mark ? { mark } : {},
|
|
4887
|
+
ok: true,
|
|
4888
|
+
snapshot: getLineageSnapshot(project, rootAssetId)
|
|
4889
|
+
};
|
|
4890
|
+
}
|
|
4891
|
+
function markAssetSocial(project, fields) {
|
|
4892
|
+
const snapshot = requireCanonicalSnapshot(project, fields.rootAssetId);
|
|
4893
|
+
const node = resolveVisibleNode(snapshot, fields.asset);
|
|
4894
|
+
const markedBy = requireActor(fields.markedBy, "markedBy");
|
|
4895
|
+
requireLineageWorkspaceClaimForWrite({
|
|
4896
|
+
channel: rootChannel(snapshot),
|
|
4897
|
+
claimToken: fields.claimToken,
|
|
4898
|
+
confirmWrite: fields.confirmWrite,
|
|
4899
|
+
project,
|
|
4900
|
+
rootAssetId: fields.rootAssetId,
|
|
4901
|
+
writeKind: "social_mark"
|
|
4902
|
+
});
|
|
4903
|
+
const existing = activeRow(project, fields.rootAssetId, node.asset_id);
|
|
4904
|
+
if (existing) return mutationResponse(project, fields.rootAssetId, true, markFromRow(existing), fields.confirmWrite ? void 0 : true);
|
|
4905
|
+
const timestamp = nowIso();
|
|
4906
|
+
const preview = {
|
|
4907
|
+
active: true,
|
|
4908
|
+
asset_id: node.asset_id,
|
|
4909
|
+
id: socialMarkId(project, fields.rootAssetId, node.asset_id),
|
|
4910
|
+
marked_at: timestamp,
|
|
4911
|
+
marked_by: markedBy,
|
|
4912
|
+
notes: fields.notes?.trim() || void 0,
|
|
4913
|
+
project_id: project,
|
|
4914
|
+
root_asset_id: fields.rootAssetId,
|
|
4915
|
+
updated_at: timestamp
|
|
4916
|
+
};
|
|
4917
|
+
if (!fields.confirmWrite) return mutationResponse(project, fields.rootAssetId, true, preview, true);
|
|
4918
|
+
const database = lineageDb();
|
|
4919
|
+
try {
|
|
4920
|
+
database.prepare(`
|
|
4921
|
+
insert into asset_social_marks (
|
|
4922
|
+
id, project_id, root_asset_id, asset_id, notes, marked_by, marked_at,
|
|
4923
|
+
unmarked_by, unmarked_at, updated_at
|
|
4924
|
+
) values (?, ?, ?, ?, ?, ?, ?, null, null, ?)
|
|
4925
|
+
on conflict(project_id, root_asset_id, asset_id) do update set
|
|
4926
|
+
notes = excluded.notes,
|
|
4927
|
+
marked_by = excluded.marked_by,
|
|
4928
|
+
marked_at = excluded.marked_at,
|
|
4929
|
+
unmarked_by = null,
|
|
4930
|
+
unmarked_at = null,
|
|
4931
|
+
updated_at = excluded.updated_at
|
|
4932
|
+
`).run(
|
|
4933
|
+
preview.id,
|
|
4934
|
+
project,
|
|
4935
|
+
fields.rootAssetId,
|
|
4936
|
+
node.asset_id,
|
|
4937
|
+
preview.notes || null,
|
|
4938
|
+
markedBy,
|
|
4939
|
+
timestamp,
|
|
4940
|
+
timestamp
|
|
4941
|
+
);
|
|
4942
|
+
} finally {
|
|
4943
|
+
database.close();
|
|
4944
|
+
}
|
|
4945
|
+
return mutationResponse(project, fields.rootAssetId, true, markFromRow(activeRow(project, fields.rootAssetId, node.asset_id)));
|
|
4946
|
+
}
|
|
4947
|
+
function unmarkAssetSocial(project, fields) {
|
|
4948
|
+
const snapshot = requireCanonicalSnapshot(project, fields.rootAssetId);
|
|
4949
|
+
const node = resolveVisibleNode(snapshot, fields.asset);
|
|
4950
|
+
const unmarkedBy = requireActor(fields.unmarkedBy, "unmarkedBy");
|
|
4951
|
+
requireLineageWorkspaceClaimForWrite({
|
|
4952
|
+
channel: rootChannel(snapshot),
|
|
4953
|
+
claimToken: fields.claimToken,
|
|
4954
|
+
confirmWrite: fields.confirmWrite,
|
|
4955
|
+
project,
|
|
4956
|
+
rootAssetId: fields.rootAssetId,
|
|
4957
|
+
writeKind: "social_unmark"
|
|
4958
|
+
});
|
|
4959
|
+
const existing = activeRow(project, fields.rootAssetId, node.asset_id);
|
|
4960
|
+
if (!existing) return mutationResponse(project, fields.rootAssetId, false, void 0, fields.confirmWrite ? void 0 : true);
|
|
4961
|
+
const timestamp = nowIso();
|
|
4962
|
+
const preview = markFromRow({
|
|
4963
|
+
...existing,
|
|
4964
|
+
unmarked_at: timestamp,
|
|
4965
|
+
unmarked_by: unmarkedBy,
|
|
4966
|
+
updated_at: timestamp
|
|
4967
|
+
});
|
|
4968
|
+
if (!fields.confirmWrite) return mutationResponse(project, fields.rootAssetId, false, preview, true);
|
|
4969
|
+
const database = lineageDb();
|
|
4970
|
+
try {
|
|
4971
|
+
database.prepare(`
|
|
4972
|
+
update asset_social_marks
|
|
4973
|
+
set unmarked_by = ?, unmarked_at = ?, updated_at = ?
|
|
4974
|
+
where project_id = ? and root_asset_id = ? and asset_id = ? and unmarked_at is null
|
|
4975
|
+
`).run(unmarkedBy, timestamp, timestamp, project, fields.rootAssetId, node.asset_id);
|
|
4976
|
+
} finally {
|
|
4977
|
+
database.close();
|
|
4978
|
+
}
|
|
4979
|
+
return mutationResponse(project, fields.rootAssetId, false, preview);
|
|
4980
|
+
}
|
|
4981
|
+
function absoluteLocalPath2(reference) {
|
|
4982
|
+
if (!reference) return void 0;
|
|
4983
|
+
if (isAbsolute3(reference)) return reference;
|
|
4984
|
+
const repoRelative = resolve6(repoRoot, reference);
|
|
4985
|
+
return existsSync8(repoRelative) || reference === ".asset-scratch" || reference.startsWith(".asset-scratch/") ? repoRelative : resolve6(repoRoot, ".asset-scratch", reference);
|
|
4986
|
+
}
|
|
4987
|
+
function isReadable(path) {
|
|
4988
|
+
try {
|
|
4989
|
+
accessSync(path, constants.R_OK);
|
|
4990
|
+
return true;
|
|
4991
|
+
} catch {
|
|
4992
|
+
return false;
|
|
4993
|
+
}
|
|
4994
|
+
}
|
|
4995
|
+
function listItem(project, rootAssetId, node, row) {
|
|
4996
|
+
const relativePath = node.current_attempt?.file_path || node.local_path;
|
|
4997
|
+
const absolutePath = absoluteLocalPath2(relativePath);
|
|
4998
|
+
const exists = absolutePath ? existsSync8(absolutePath) : false;
|
|
4999
|
+
const warnings = [];
|
|
5000
|
+
if (absolutePath && !exists) warnings.push(`Asset ${node.asset_id} local file is missing: ${absolutePath}`);
|
|
5001
|
+
if (absolutePath && exists && !isReadable(absolutePath)) {
|
|
5002
|
+
warnings.push(`Asset ${node.asset_id} local file is unreadable: ${absolutePath}. Check file permissions before handoff.`);
|
|
5003
|
+
}
|
|
5004
|
+
if (!absolutePath && node.s3_key) {
|
|
5005
|
+
warnings.push(`Asset ${node.asset_id} is only available in non-local storage; create a readable local copy before handoff.`);
|
|
5006
|
+
}
|
|
5007
|
+
if (!absolutePath && !node.s3_key) warnings.push(`Asset ${node.asset_id} has no local file or storage key.`);
|
|
5008
|
+
const base = `--project ${shellQuote(project)} --root ${shellQuote(rootAssetId)} --asset ${shellQuote(node.asset_id)}`;
|
|
5009
|
+
return {
|
|
5010
|
+
...markFromRow(row),
|
|
5011
|
+
checksum_sha256: node.current_attempt?.checksum_sha256 || node.checksum_sha256,
|
|
5012
|
+
commands: {
|
|
5013
|
+
mark: lineageCliCommand(`social mark ${base} --confirm-write`),
|
|
5014
|
+
unmark: lineageCliCommand(`social unmark ${base} --confirm-write`)
|
|
5015
|
+
},
|
|
5016
|
+
current_attempt: node.current_attempt,
|
|
5017
|
+
local: {
|
|
5018
|
+
absolute_path: absolutePath,
|
|
5019
|
+
exists,
|
|
5020
|
+
relative_path: relativePath
|
|
5021
|
+
},
|
|
5022
|
+
media_type: node.media_type,
|
|
5023
|
+
s3: node.s3_key ? { key: node.s3_key } : void 0,
|
|
5024
|
+
source: node.source,
|
|
5025
|
+
title: node.title,
|
|
5026
|
+
warnings
|
|
5027
|
+
};
|
|
5028
|
+
}
|
|
5029
|
+
function listAssetSocialMarks(project, rootAssetId) {
|
|
5030
|
+
const snapshot = requireCanonicalSnapshot(project, rootAssetId);
|
|
5031
|
+
const database = lineageDb();
|
|
5032
|
+
let rows;
|
|
5033
|
+
try {
|
|
5034
|
+
const hasSocialMarks = database.prepare("select 1 from sqlite_master where type = 'table' and name = 'asset_social_marks'").get() !== void 0;
|
|
5035
|
+
rows = hasSocialMarks ? database.prepare(`
|
|
5036
|
+
select * from asset_social_marks
|
|
5037
|
+
where project_id = ? and root_asset_id = ? and unmarked_at is null
|
|
5038
|
+
order by marked_at, asset_id
|
|
5039
|
+
`).all(project, rootAssetId) : [];
|
|
5040
|
+
} finally {
|
|
5041
|
+
database.close();
|
|
5042
|
+
}
|
|
5043
|
+
const nodesById = new Map(snapshot.nodes.map((node) => [node.asset_id, node]));
|
|
5044
|
+
return {
|
|
5045
|
+
commands: {
|
|
5046
|
+
mark: lineageCliCommand(`social mark --project ${shellQuote(project)} --root ${shellQuote(rootAssetId)} --asset <asset-id> --confirm-write`)
|
|
5047
|
+
},
|
|
5048
|
+
fetchedAt: nowIso(),
|
|
5049
|
+
marks: rows.flatMap((row) => {
|
|
5050
|
+
const node = nodesById.get(row.asset_id);
|
|
5051
|
+
return node ? [listItem(project, rootAssetId, node, row)] : [];
|
|
5052
|
+
}),
|
|
5053
|
+
project,
|
|
5054
|
+
root_asset_id: rootAssetId,
|
|
5055
|
+
schema_version: "lineage.social_marks.v1",
|
|
5056
|
+
workspace: {
|
|
5057
|
+
id: lineageWorkspaceId(project, rootAssetId),
|
|
5058
|
+
root_asset_id: rootAssetId
|
|
5059
|
+
}
|
|
5060
|
+
};
|
|
5061
|
+
}
|
|
5062
|
+
function bodyString(req, key) {
|
|
5063
|
+
const value = req.body?.[key];
|
|
5064
|
+
return typeof value === "string" ? value : void 0;
|
|
5065
|
+
}
|
|
5066
|
+
function requestClaimToken(req) {
|
|
5067
|
+
return req.header("X-Lineage-Claim-Token") || bodyString(req, "claimToken");
|
|
5068
|
+
}
|
|
5069
|
+
function registerAssetSocialMarkRoutes(app2, projectFrom2, asyncRoute2) {
|
|
5070
|
+
app2.get("/api/lineage/:rootAssetId/social-marks", asyncRoute2((req, res) => {
|
|
5071
|
+
res.json(listAssetSocialMarks(
|
|
5072
|
+
projectFrom2({ query: req.query }),
|
|
5073
|
+
req.params.rootAssetId
|
|
5074
|
+
));
|
|
5075
|
+
}));
|
|
5076
|
+
app2.post("/api/lineage/:rootAssetId/social-marks/:assetId", asyncRoute2((req, res) => {
|
|
5077
|
+
res.json(markAssetSocial(projectFrom2({ body: req.body, query: req.query }), {
|
|
5078
|
+
asset: req.params.assetId,
|
|
5079
|
+
claimToken: requestClaimToken(req),
|
|
5080
|
+
confirmWrite: req.body?.confirmWrite === true,
|
|
5081
|
+
markedBy: bodyString(req, "markedBy") || bodyString(req, "actor") || "human",
|
|
5082
|
+
notes: bodyString(req, "notes"),
|
|
5083
|
+
rootAssetId: req.params.rootAssetId
|
|
5084
|
+
}));
|
|
5085
|
+
}));
|
|
5086
|
+
app2.post("/api/lineage/:rootAssetId/social-marks/:assetId/unmark", asyncRoute2((req, res) => {
|
|
5087
|
+
res.json(unmarkAssetSocial(projectFrom2({ body: req.body, query: req.query }), {
|
|
5088
|
+
asset: req.params.assetId,
|
|
5089
|
+
claimToken: requestClaimToken(req),
|
|
5090
|
+
confirmWrite: req.body?.confirmWrite === true,
|
|
5091
|
+
rootAssetId: req.params.rootAssetId,
|
|
5092
|
+
unmarkedBy: bodyString(req, "unmarkedBy") || bodyString(req, "actor") || "human"
|
|
5093
|
+
}));
|
|
5094
|
+
}));
|
|
5095
|
+
}
|
|
5096
|
+
|
|
4792
5097
|
// src/server/assetLedger.ts
|
|
4793
5098
|
function allAssets(project, source) {
|
|
4794
5099
|
const first = listAssets(project, { page: 1, pageSize: 100, source });
|
|
@@ -6867,7 +7172,7 @@ function registerAdapterRoutes(app2, projectFrom2, asyncRoute2) {
|
|
|
6867
7172
|
import { Router } from "express";
|
|
6868
7173
|
|
|
6869
7174
|
// src/server/contentBatchImport.ts
|
|
6870
|
-
import { existsSync as
|
|
7175
|
+
import { existsSync as existsSync9, readdirSync as readdirSync3, readFileSync as readFileSync5 } from "node:fs";
|
|
6871
7176
|
import { basename as basename3, join as join10, relative as relative3 } from "node:path";
|
|
6872
7177
|
function walk(dir) {
|
|
6873
7178
|
return readdirSync3(dir, { withFileTypes: true }).flatMap((entry) => {
|
|
@@ -6922,7 +7227,7 @@ function itemFromFile(file) {
|
|
|
6922
7227
|
}
|
|
6923
7228
|
function demoMarkdownItems(kind) {
|
|
6924
7229
|
const root = process.env.LINEAGE_CONTENT_SOURCE_ROOT || join10(repoRoot, "demo-project", "channels");
|
|
6925
|
-
if (!
|
|
7230
|
+
if (!existsSync9(root)) return [];
|
|
6926
7231
|
return walk(root).map(itemFromFile).filter((item) => Boolean(item)).filter((item) => kind === "all" || `${item.kind}s` === kind).sort((a, b) => a.sourcePath.localeCompare(b.sourcePath));
|
|
6927
7232
|
}
|
|
6928
7233
|
function importDemoContentBatch(project, options) {
|
|
@@ -7261,8 +7566,8 @@ function contentBatchRouter(projectFrom2) {
|
|
|
7261
7566
|
}
|
|
7262
7567
|
|
|
7263
7568
|
// src/server/generationReceipts.ts
|
|
7264
|
-
import { existsSync as
|
|
7265
|
-
import { relative as relative4, resolve as
|
|
7569
|
+
import { existsSync as existsSync10, realpathSync as realpathSync2, statSync as statSync4 } from "node:fs";
|
|
7570
|
+
import { relative as relative4, resolve as resolve7 } from "node:path";
|
|
7266
7571
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
7267
7572
|
|
|
7268
7573
|
// src/shared/generationOutputManifest.ts
|
|
@@ -7800,8 +8105,8 @@ function isPathInside2(child, parent) {
|
|
|
7800
8105
|
return Boolean(rel) && !rel.startsWith("..") && !rel.startsWith("/");
|
|
7801
8106
|
}
|
|
7802
8107
|
function scratchCandidate(file) {
|
|
7803
|
-
const scratchRoot =
|
|
7804
|
-
const candidate = file.startsWith(".asset-scratch/") ||
|
|
8108
|
+
const scratchRoot = resolve7(repoRoot, ".asset-scratch");
|
|
8109
|
+
const candidate = file.startsWith(".asset-scratch/") || resolve7(file).startsWith(scratchRoot) ? resolve7(repoRoot, file) : resolve7(scratchRoot, file);
|
|
7805
8110
|
if (!isPathInside2(candidate, scratchRoot)) throw new GenerationReceiptError(`Import file must be under .asset-scratch: ${file}`);
|
|
7806
8111
|
return { candidate, scratchRoot };
|
|
7807
8112
|
}
|
|
@@ -7811,7 +8116,7 @@ function resolveScratchManifestPath(file) {
|
|
|
7811
8116
|
}
|
|
7812
8117
|
function resolveScratchFile(file) {
|
|
7813
8118
|
const { candidate, scratchRoot } = scratchCandidate(file);
|
|
7814
|
-
if (!
|
|
8119
|
+
if (!existsSync10(candidate)) throw new GenerationReceiptError(`Missing import file: ${file}`, 404);
|
|
7815
8120
|
const realScratchRoot = realpathSync2(scratchRoot);
|
|
7816
8121
|
const realCandidate = realpathSync2(candidate);
|
|
7817
8122
|
if (!isPathInside2(realCandidate, realScratchRoot)) throw new GenerationReceiptError(`Import file must be under .asset-scratch: ${file}`);
|
|
@@ -8143,7 +8448,7 @@ function registerLineageTaskRoutes(app2, projectFrom2, asyncRoute2) {
|
|
|
8143
8448
|
|
|
8144
8449
|
// src/server/assetLineageDemo.ts
|
|
8145
8450
|
import { createHash as createHash5 } from "node:crypto";
|
|
8146
|
-
import { copyFileSync as copyFileSync3, existsSync as
|
|
8451
|
+
import { copyFileSync as copyFileSync3, existsSync as existsSync11, mkdirSync as mkdirSync7, mkdtempSync, readFileSync as readFileSync6, rmSync as rmSync3, writeFileSync as writeFileSync5 } from "node:fs";
|
|
8147
8452
|
import { tmpdir } from "node:os";
|
|
8148
8453
|
import { dirname as dirname5, join as join11, posix } from "node:path";
|
|
8149
8454
|
import { gunzipSync } from "node:zlib";
|
|
@@ -8215,9 +8520,9 @@ function swissifierRerollFixturePath(attempt) {
|
|
|
8215
8520
|
}
|
|
8216
8521
|
function swissifierSourcePath(manifest, asset, sourceDir) {
|
|
8217
8522
|
const direct = join11(sourceDir, asset.file);
|
|
8218
|
-
if (
|
|
8523
|
+
if (existsSync11(direct)) return direct;
|
|
8219
8524
|
const nested = join11(sourceDir, manifest.media.target_dir, asset.file);
|
|
8220
|
-
return
|
|
8525
|
+
return existsSync11(nested) ? nested : null;
|
|
8221
8526
|
}
|
|
8222
8527
|
function swissifierMediaState(manifest) {
|
|
8223
8528
|
const missing = [];
|
|
@@ -8225,7 +8530,7 @@ function swissifierMediaState(manifest) {
|
|
|
8225
8530
|
for (const asset of manifest.assets) {
|
|
8226
8531
|
const relativePath = swissifierRelativePath(manifest, asset);
|
|
8227
8532
|
const path = swissifierFilePath(manifest, asset);
|
|
8228
|
-
if (!
|
|
8533
|
+
if (!existsSync11(path)) {
|
|
8229
8534
|
missing.push(relativePath);
|
|
8230
8535
|
continue;
|
|
8231
8536
|
}
|
|
@@ -8317,7 +8622,7 @@ async function downloadBuffer(url, maxBytes) {
|
|
|
8317
8622
|
return buffer;
|
|
8318
8623
|
}
|
|
8319
8624
|
function missingDemoMedia(project) {
|
|
8320
|
-
return demoAssets.filter((asset) => !
|
|
8625
|
+
return demoAssets.filter((asset) => !existsSync11(demoFilePath(project, asset))).map((asset) => demoRelativePath(project, asset));
|
|
8321
8626
|
}
|
|
8322
8627
|
function demoSeedMediaStatus(project = defaultProject) {
|
|
8323
8628
|
const missing = missingDemoMedia(project);
|
|
@@ -8512,7 +8817,7 @@ function writeDemoFiles(project) {
|
|
|
8512
8817
|
}
|
|
8513
8818
|
function swissifierRerollAsset(attempt) {
|
|
8514
8819
|
const source = swissifierRerollFixturePath(attempt);
|
|
8515
|
-
if (!
|
|
8820
|
+
if (!existsSync11(source)) throw new Error(`Missing Swissifier re-roll fixture media: ${attempt.file}`);
|
|
8516
8821
|
const body = readFileSync6(source);
|
|
8517
8822
|
if (body.length !== attempt.size_bytes) throw new Error(`Unexpected Swissifier re-roll fixture size for ${attempt.file}`);
|
|
8518
8823
|
const checksumSha256 = sha256Hex(body);
|
|
@@ -8935,8 +9240,8 @@ function registerLineageWorkspaceRoutes(app2, projectFrom2, asyncRoute2) {
|
|
|
8935
9240
|
// src/server/runtimeInfo.ts
|
|
8936
9241
|
import { createHash as createHash6 } from "node:crypto";
|
|
8937
9242
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
8938
|
-
import { existsSync as
|
|
8939
|
-
import { dirname as dirname6, isAbsolute as
|
|
9243
|
+
import { existsSync as existsSync12, lstatSync as lstatSync3, readFileSync as readFileSync7, readdirSync as readdirSync4, readlinkSync, realpathSync as realpathSync3, statSync as statSync5 } from "node:fs";
|
|
9244
|
+
import { dirname as dirname6, isAbsolute as isAbsolute4, join as join12, resolve as resolve8 } from "node:path";
|
|
8940
9245
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
8941
9246
|
|
|
8942
9247
|
// src/shared/runtimeInfoTypes.ts
|
|
@@ -8955,7 +9260,7 @@ function isLineagePackageRoot(root) {
|
|
|
8955
9260
|
}
|
|
8956
9261
|
function executingCodeRoot() {
|
|
8957
9262
|
const moduleDirectory = dirname6(fileURLToPath2(import.meta.url));
|
|
8958
|
-
const candidates = [
|
|
9263
|
+
const candidates = [resolve8(moduleDirectory, "../.."), resolve8(moduleDirectory, "..")];
|
|
8959
9264
|
const root = candidates.find(isLineagePackageRoot);
|
|
8960
9265
|
if (!root) throw new Error(`Unable to derive Lineage code root from executing module ${fileURLToPath2(import.meta.url)}`);
|
|
8961
9266
|
return canonicalRoot(root);
|
|
@@ -8968,7 +9273,7 @@ function canonicalRoot(root) {
|
|
|
8968
9273
|
try {
|
|
8969
9274
|
return realpathSync3(root);
|
|
8970
9275
|
} catch {
|
|
8971
|
-
return
|
|
9276
|
+
return resolve8(root);
|
|
8972
9277
|
}
|
|
8973
9278
|
}
|
|
8974
9279
|
function packageInfo(root = codeRoot) {
|
|
@@ -9068,7 +9373,7 @@ function readInstallReceipt(path, errors) {
|
|
|
9068
9373
|
return void 0;
|
|
9069
9374
|
}
|
|
9070
9375
|
let receipt;
|
|
9071
|
-
const receiptPath =
|
|
9376
|
+
const receiptPath = resolve8(path);
|
|
9072
9377
|
try {
|
|
9073
9378
|
receipt = JSON.parse(readFileSync7(receiptPath, "utf8"));
|
|
9074
9379
|
} catch (error) {
|
|
@@ -9076,7 +9381,7 @@ function readInstallReceipt(path, errors) {
|
|
|
9076
9381
|
return void 0;
|
|
9077
9382
|
}
|
|
9078
9383
|
if (receipt.schema_version !== lineageRuntimeInstallSchemaVersion) errors.push(`Unsupported runtime install receipt schema: ${String(receipt.schema_version)}`);
|
|
9079
|
-
if (!
|
|
9384
|
+
if (!isAbsolute4(receipt.package_root || "")) errors.push("Runtime install receipt package_root must be absolute");
|
|
9080
9385
|
if (!receipt.package_integrity?.startsWith("sha512-")) errors.push("Runtime install receipt package integrity is invalid");
|
|
9081
9386
|
if (receipt.package_source !== "registry" && receipt.package_source !== "local") errors.push("Runtime install receipt package source is invalid");
|
|
9082
9387
|
if (typeof receipt.package_spec !== "string" || !receipt.package_spec) errors.push("Runtime install receipt package spec is invalid");
|
|
@@ -9157,8 +9462,8 @@ function packageCodeIdentity(root, channel, info, receiptPath) {
|
|
|
9157
9462
|
function getLineageCodeIdentity(channel, options = {}) {
|
|
9158
9463
|
const root = canonicalRoot(options.root || codeRoot);
|
|
9159
9464
|
const info = packageInfo(root);
|
|
9160
|
-
if (
|
|
9161
|
-
if (
|
|
9465
|
+
if (existsSync12(join12(root, ".git"))) return checkoutCodeIdentity(root, channel, info.version);
|
|
9466
|
+
if (existsSync12(join12(root, "package.json"))) {
|
|
9162
9467
|
return packageCodeIdentity(root, channel, info, options.receiptPath ?? process.env.LINEAGE_RUNTIME_RECEIPT);
|
|
9163
9468
|
}
|
|
9164
9469
|
const errors = [`Code root has neither checkout metadata nor package.json: ${root}`];
|
|
@@ -9197,7 +9502,7 @@ function getLineageRuntimeInfo(options = {}) {
|
|
|
9197
9502
|
const dbPath = options.dbPath || lineageDbPath();
|
|
9198
9503
|
const channel = normalizeRuntimeChannel(options.channel || process.env.LINEAGE_CHANNEL || process.env.LINEAGE_RELEASE_CHANNEL);
|
|
9199
9504
|
const code = options.code || getLineageCodeIdentity(channel);
|
|
9200
|
-
const databaseInfo = { exists:
|
|
9505
|
+
const databaseInfo = { exists: existsSync12(dbPath), path: dbPath };
|
|
9201
9506
|
const schema = { migration_keys: [] };
|
|
9202
9507
|
const serviceInstanceId = process.env.LINEAGE_SERVICE_INSTANCE_ID;
|
|
9203
9508
|
const launcherPid = process.env.LINEAGE_LAUNCHER_PID ? Number(process.env.LINEAGE_LAUNCHER_PID) : void 0;
|
|
@@ -9337,14 +9642,14 @@ function registerManagedWriterRoute(app2, fields) {
|
|
|
9337
9642
|
}
|
|
9338
9643
|
|
|
9339
9644
|
// src/cli/lineageCli.ts
|
|
9340
|
-
import { existsSync as
|
|
9341
|
-
import { dirname as dirname7, join as join13, resolve as
|
|
9645
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync8, readFileSync as readFileSync8, writeFileSync as writeFileSync6 } from "node:fs";
|
|
9646
|
+
import { dirname as dirname7, join as join13, resolve as resolve10 } from "node:path";
|
|
9342
9647
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
9343
9648
|
|
|
9344
9649
|
// src/server/lineageSelectionPacket.ts
|
|
9345
9650
|
import { createHash as createHash7 } from "node:crypto";
|
|
9346
|
-
import { existsSync as
|
|
9347
|
-
import { isAbsolute as
|
|
9651
|
+
import { existsSync as existsSync13, statSync as statSync6 } from "node:fs";
|
|
9652
|
+
import { isAbsolute as isAbsolute5, resolve as resolve9 } from "node:path";
|
|
9348
9653
|
var LineageSelectionPacketError = class extends Error {
|
|
9349
9654
|
constructor(message, warnings = [], errors = [], diagnostics = []) {
|
|
9350
9655
|
super(message);
|
|
@@ -9390,13 +9695,13 @@ function resolveWorkspace(project, options) {
|
|
|
9390
9695
|
}
|
|
9391
9696
|
function resolveLocalReference(reference) {
|
|
9392
9697
|
if (!reference) return void 0;
|
|
9393
|
-
if (
|
|
9394
|
-
const repoRelative =
|
|
9395
|
-
if (
|
|
9396
|
-
return
|
|
9698
|
+
if (isAbsolute5(reference)) return reference;
|
|
9699
|
+
const repoRelative = resolve9(repoRoot, reference);
|
|
9700
|
+
if (existsSync13(repoRelative)) return repoRelative;
|
|
9701
|
+
return resolve9(repoRoot, ".asset-scratch", reference);
|
|
9397
9702
|
}
|
|
9398
9703
|
function fileSize(path) {
|
|
9399
|
-
if (!path || !
|
|
9704
|
+
if (!path || !existsSync13(path)) return void 0;
|
|
9400
9705
|
try {
|
|
9401
9706
|
return statSync6(path).size;
|
|
9402
9707
|
} catch {
|
|
@@ -9424,7 +9729,7 @@ function currentAttemptFor(node) {
|
|
|
9424
9729
|
function assetForNode(node, catalogAsset, warnings) {
|
|
9425
9730
|
const localReference = catalogAsset?.local?.absolute_path || node.current_attempt?.file_path || node.local_path || catalogAsset?.local?.relative_path;
|
|
9426
9731
|
const absolutePath = catalogAsset?.local?.absolute_path || resolveLocalReference(localReference);
|
|
9427
|
-
const localExists = absolutePath ?
|
|
9732
|
+
const localExists = absolutePath ? existsSync13(absolutePath) : false;
|
|
9428
9733
|
const hasLocalClaim = Boolean(absolutePath || node.local_path || catalogAsset?.local?.relative_path);
|
|
9429
9734
|
const s3Key = catalogAsset?.s3?.key || node.s3_key;
|
|
9430
9735
|
const hasS3 = Boolean(s3Key);
|
|
@@ -9581,7 +9886,7 @@ function assetForNodeV2(node, visibleCatalogAsset, catalogById, warnings, errors
|
|
|
9581
9886
|
const mediaCatalogAsset = currentAttemptCatalogAsset || (isVisibleNodeAttempt ? visibleCatalogAsset : void 0);
|
|
9582
9887
|
const localReference = currentAttempt.file_path || mediaCatalogAsset?.local?.absolute_path || mediaCatalogAsset?.local?.relative_path || (isVisibleNodeAttempt ? node.local_path : void 0);
|
|
9583
9888
|
const absolutePath = resolveLocalReference(localReference);
|
|
9584
|
-
const localExists = absolutePath ?
|
|
9889
|
+
const localExists = absolutePath ? existsSync13(absolutePath) : false;
|
|
9585
9890
|
const hasLocalClaim = Boolean(localReference);
|
|
9586
9891
|
const s3Key = mediaCatalogAsset?.s3?.key || (isVisibleNodeAttempt ? node.s3_key : void 0);
|
|
9587
9892
|
const hasS3 = Boolean(s3Key);
|
|
@@ -9846,7 +10151,7 @@ function getLineageSelectionPacket(project, options = {}) {
|
|
|
9846
10151
|
|
|
9847
10152
|
// src/cli/lineageCli.ts
|
|
9848
10153
|
function packageRoot2() {
|
|
9849
|
-
return
|
|
10154
|
+
return resolve10(dirname7(fileURLToPath3(import.meta.url)), "..", "..");
|
|
9850
10155
|
}
|
|
9851
10156
|
function packageVersion() {
|
|
9852
10157
|
try {
|
|
@@ -9879,7 +10184,7 @@ function readOptions(args, name) {
|
|
|
9879
10184
|
}
|
|
9880
10185
|
function readJsonFile(path, label) {
|
|
9881
10186
|
try {
|
|
9882
|
-
return JSON.parse(readFileSync8(
|
|
10187
|
+
return JSON.parse(readFileSync8(resolve10(path), "utf8"));
|
|
9883
10188
|
} catch (error) {
|
|
9884
10189
|
throw new Error(`${label} must be a readable JSON file: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
9885
10190
|
}
|
|
@@ -9898,7 +10203,7 @@ function parentFilesOption(value) {
|
|
|
9898
10203
|
return mappings;
|
|
9899
10204
|
}
|
|
9900
10205
|
function resolveCliAssetRoot(args) {
|
|
9901
|
-
return
|
|
10206
|
+
return resolve10(readOption(args, "--asset-root") || process.env.LINEAGE_ASSET_ROOT || packageRoot);
|
|
9902
10207
|
}
|
|
9903
10208
|
function configureCliAssetRoot(args) {
|
|
9904
10209
|
const assetRoot = resolveCliAssetRoot(args);
|
|
@@ -9963,7 +10268,7 @@ function runLineageDataCommand(command, args) {
|
|
|
9963
10268
|
});
|
|
9964
10269
|
const out = readOption(args, "--out");
|
|
9965
10270
|
if (out) {
|
|
9966
|
-
const outPath =
|
|
10271
|
+
const outPath = resolve10(out);
|
|
9967
10272
|
mkdirSync8(dirname7(outPath), { recursive: true });
|
|
9968
10273
|
writeFileSync6(outPath, `${JSON.stringify(packet, null, 2)}
|
|
9969
10274
|
`);
|
|
@@ -10074,6 +10379,35 @@ function runLineageDataCommand(command, args) {
|
|
|
10074
10379
|
}
|
|
10075
10380
|
throw new Error(`Unknown reroll command: ${subcommand}`);
|
|
10076
10381
|
}
|
|
10382
|
+
if (command === "social") {
|
|
10383
|
+
const subcommand = positionalArgs(args)[0] || "";
|
|
10384
|
+
const explicitProject = readOption(args, "--project");
|
|
10385
|
+
const asset = readOption(args, "--asset");
|
|
10386
|
+
if (!explicitProject) throw new Error(`lineage social ${subcommand || "command"} requires --project`);
|
|
10387
|
+
if (!options.rootAssetId) throw new Error(`lineage social ${subcommand || "command"} requires --root`);
|
|
10388
|
+
if (subcommand === "list") return listAssetSocialMarks(explicitProject, options.rootAssetId);
|
|
10389
|
+
if (!asset) throw new Error(`lineage social ${subcommand || "command"} requires --asset`);
|
|
10390
|
+
if (subcommand === "mark") {
|
|
10391
|
+
return markAssetSocial(explicitProject, {
|
|
10392
|
+
asset,
|
|
10393
|
+
claimToken: options.claimToken,
|
|
10394
|
+
confirmWrite: options.confirmWrite,
|
|
10395
|
+
markedBy: readOption(args, "--actor") || "agent",
|
|
10396
|
+
notes: readOption(args, "--notes"),
|
|
10397
|
+
rootAssetId: options.rootAssetId
|
|
10398
|
+
});
|
|
10399
|
+
}
|
|
10400
|
+
if (subcommand === "unmark") {
|
|
10401
|
+
return unmarkAssetSocial(explicitProject, {
|
|
10402
|
+
asset,
|
|
10403
|
+
claimToken: options.claimToken,
|
|
10404
|
+
confirmWrite: options.confirmWrite,
|
|
10405
|
+
rootAssetId: options.rootAssetId,
|
|
10406
|
+
unmarkedBy: readOption(args, "--actor") || "agent"
|
|
10407
|
+
});
|
|
10408
|
+
}
|
|
10409
|
+
throw new Error(`Unknown social command: ${subcommand}`);
|
|
10410
|
+
}
|
|
10077
10411
|
if (command === "tasks") {
|
|
10078
10412
|
const subcommand = positionalArgs(args)[0] || "";
|
|
10079
10413
|
const taskId = readOption(args, "--task");
|
|
@@ -10146,6 +10480,7 @@ function lineageCliCanDelegateMutation(command, args) {
|
|
|
10146
10480
|
if (command === "link-child") return true;
|
|
10147
10481
|
if (command === "generate") return positions[0] === "image" && ["plan", "import"].includes(positions[1] || "");
|
|
10148
10482
|
if (command === "reroll") return ["mark", "cancel", "plan", "import"].includes(subcommand);
|
|
10483
|
+
if (command === "social") return ["mark", "unmark"].includes(subcommand);
|
|
10149
10484
|
if (command === "tasks") return ["claim", "start", "comment", "cancel", "override", "instructions"].includes(subcommand);
|
|
10150
10485
|
if (command === "agent") return ["claim", "heartbeat", "release", "revoke", "transfer"].includes(subcommand);
|
|
10151
10486
|
return false;
|
|
@@ -10379,6 +10714,7 @@ app.get(
|
|
|
10379
10714
|
);
|
|
10380
10715
|
registerLineageWorkspaceRoutes(app, projectFrom, asyncRoute);
|
|
10381
10716
|
registerLineageTaskRoutes(app, projectFrom, asyncRoute);
|
|
10717
|
+
registerAssetSocialMarkRoutes(app, projectFrom, asyncRoute);
|
|
10382
10718
|
app.get("/api/lineage/:rootAssetId/rerolls", asyncRoute((req, res) => {
|
|
10383
10719
|
res.json(listLineageRerollRequests(projectFrom(req), req.params.rootAssetId));
|
|
10384
10720
|
}));
|
|
@@ -10630,7 +10966,7 @@ app.post(
|
|
|
10630
10966
|
);
|
|
10631
10967
|
if (isProduction) {
|
|
10632
10968
|
const dist = join14(packageRoot, "dist", "web");
|
|
10633
|
-
if (
|
|
10969
|
+
if (existsSync15(dist)) {
|
|
10634
10970
|
app.use(express2.static(dist));
|
|
10635
10971
|
app.get("*", (_req, res) => res.sendFile(join14(dist, "index.html")));
|
|
10636
10972
|
}
|