@vess-id/ai-identity 0.15.0 → 0.15.1

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/dist/index.js CHANGED
@@ -5483,6 +5483,34 @@ var ACTION_REGISTRY = {
5483
5483
  },
5484
5484
  version: "1.0.0"
5485
5485
  },
5486
+ {
5487
+ // AIDENTITY-66: delete a comment from a Jira issue. high-risk destructive
5488
+ // write — mirrors jira.issue.delete (admin/owner/act_as) but resource_type
5489
+ // は jira.comment.create と同じ jira:project (issue から project を derive)。
5490
+ action: "jira.comment.delete",
5491
+ resource_type: "jira:project",
5492
+ required_relations: ["admin", "owner", "act_as"],
5493
+ required_scopes: ["write:jira-work"],
5494
+ capability: "jira.write.basic",
5495
+ input_schema: {
5496
+ type: "object",
5497
+ properties: {
5498
+ issueIdOrKey: { type: "string", minLength: 1 },
5499
+ commentId: { type: "string", minLength: 1, description: "Comment id (from jira.comment.read)" }
5500
+ },
5501
+ required: ["issueIdOrKey", "commentId"],
5502
+ additionalProperties: false
5503
+ },
5504
+ constraints: { rate_bucket: "jira.write" },
5505
+ effects: ["Delete:Comment"],
5506
+ // high: deleting a comment is irreversible and visible to all project members,
5507
+ // consistent with jira.issue.delete / jira.comment.create.
5508
+ risk: "high",
5509
+ target_bindings: {
5510
+ resource_id: { source: "param", param: "issueIdOrKey", fallback_param: "issueKey", derive: "project_key" }
5511
+ },
5512
+ version: "1.0.0"
5513
+ },
5486
5514
  {
5487
5515
  action: "jira.comment.read",
5488
5516
  resource_type: "jira:project",
@@ -5648,6 +5676,42 @@ var ACTION_REGISTRY = {
5648
5676
  },
5649
5677
  version: "1.0.0"
5650
5678
  },
5679
+ {
5680
+ // AIDENTITY-83: email / displayName から accountId を解決する read action。
5681
+ // query は resource id ではなく検索語なので target_bindings は付けず
5682
+ // (jira.project.read 等の unscoped read と同様)、type-only match で評価する。
5683
+ action: "jira.user.search",
5684
+ resource_type: "jira:user",
5685
+ required_relations: ["viewer", "editor", "admin", "owner"],
5686
+ required_scopes: ["read:jira-user"],
5687
+ capability: "jira.read.basic",
5688
+ input_schema: {
5689
+ type: "object",
5690
+ properties: {
5691
+ query: {
5692
+ type: "string",
5693
+ minLength: 1,
5694
+ description: "Matched against displayName and emailAddress (prefix match). Pass an email address to resolve its accountId."
5695
+ },
5696
+ maxResults: {
5697
+ type: "integer",
5698
+ minimum: 1,
5699
+ maximum: 50,
5700
+ description: "Max users to return (default 10)"
5701
+ }
5702
+ },
5703
+ required: ["query"],
5704
+ additionalProperties: false
5705
+ },
5706
+ constraints: { rate_bucket: "jira.read" },
5707
+ effects: ["Read:User"],
5708
+ risk: "low",
5709
+ // query は resource id ではないので unscoped。required: false で type-only match。
5710
+ target_bindings: {
5711
+ resource_id: { source: "param", param: "query", required: false }
5712
+ },
5713
+ version: "1.0.0"
5714
+ },
5651
5715
  // ─── OS Actions (Local) ───
5652
5716
  {
5653
5717
  action: "os.secret.read",
@@ -6443,14 +6507,14 @@ var ACTION_REGISTRY = {
6443
6507
  },
6444
6508
  {
6445
6509
  capability: "jira.read.basic",
6446
- description: "Read Jira issues, projects, boards, sprints, and issue link types",
6447
- includes: ["jira.project.read", "jira.board.read", "jira.sprint.read", "jira.issue.list", "jira.issue.search", "jira.worklog.read", "jira.issue.read", "jira.batch.read", "jira.comment.read", "jira.transition.list", "jira.issuelinktype.list"],
6510
+ description: "Read Jira issues, projects, boards, sprints, issue link types, and users",
6511
+ includes: ["jira.project.read", "jira.board.read", "jira.sprint.read", "jira.issue.list", "jira.issue.search", "jira.worklog.read", "jira.issue.read", "jira.batch.read", "jira.comment.read", "jira.transition.list", "jira.issuelinktype.list", "jira.user.search"],
6448
6512
  version: "1.0.0"
6449
6513
  },
6450
6514
  {
6451
6515
  capability: "jira.write.basic",
6452
- description: "Create, update, delete Jira issues, and manage issue links",
6453
- includes: ["jira.issue.create", "jira.issue.update", "jira.issue.delete", "jira.comment.create", "jira.issue.transition", "jira.issuelink.create", "jira.issuelink.delete"],
6516
+ description: "Create, update, delete Jira issues, manage issue links, and add/delete comments",
6517
+ includes: ["jira.issue.create", "jira.issue.update", "jira.issue.delete", "jira.comment.create", "jira.comment.delete", "jira.issue.transition", "jira.issuelink.create", "jira.issuelink.delete"],
6454
6518
  version: "1.0.0"
6455
6519
  },
6456
6520
  {
@@ -6871,7 +6935,7 @@ var ACTION_DISPLAY_CONFIGS = {
6871
6935
  summaryTemplate: (p) => {
6872
6936
  const parts = [];
6873
6937
  if (p.summary) parts.push(p.summary);
6874
- if (p.start) parts.push(`(${formatValue(p.start)})`);
6938
+ if (p.start) parts.push(`(${formatCalendarTime(p.start)})`);
6875
6939
  return parts.join(" ");
6876
6940
  },
6877
6941
  displayFields: [
@@ -6885,7 +6949,7 @@ var ACTION_DISPLAY_CONFIGS = {
6885
6949
  summaryTemplate: (p) => {
6886
6950
  const parts = [];
6887
6951
  if (p.summary) parts.push(p.summary);
6888
- if (p.start) parts.push(`(${formatValue(p.start)})`);
6952
+ if (p.start) parts.push(`(${formatCalendarTime(p.start)})`);
6889
6953
  return parts.join(" ");
6890
6954
  },
6891
6955
  displayFields: [
@@ -6975,7 +7039,7 @@ var ACTION_DISPLAY_CONFIGS = {
6975
7039
  ]
6976
7040
  },
6977
7041
  // AIDENTITY-65: comment 本体は string と ADF document の両方を受けるため、
6978
- // formatValue 側の ADF ハンドリング (extractFirstAdfText) に任せて key 指定で OK。
7042
+ // detail 表示の ADF 描画は formatValueFull 側に任せて key 指定で OK。
6979
7043
  "jira.comment.create": {
6980
7044
  summaryTemplate: (p) => {
6981
7045
  const parts = [];
@@ -6988,6 +7052,21 @@ var ACTION_DISPLAY_CONFIGS = {
6988
7052
  { key: "body", label: "Comment" }
6989
7053
  ]
6990
7054
  },
7055
+ // AIDENTITY-66: 破壊的操作なので「どの issue のどの comment を消すか」を明示する
7056
+ // (jira.issue.delete / jira.issuelink.delete と同じ destructive 表現の方針)。
7057
+ "jira.comment.delete": {
7058
+ summaryTemplate: (p) => {
7059
+ const issue = p.issueIdOrKey ?? p.issueKey;
7060
+ const commentId = p.commentId ?? p.id;
7061
+ if (issue && commentId) return `Delete comment ${commentId} on ${issue}`;
7062
+ if (commentId) return `Delete comment ${commentId}`;
7063
+ return "";
7064
+ },
7065
+ displayFields: [
7066
+ { label: "Issue", extract: (p) => p.issueIdOrKey ?? p.issueKey },
7067
+ { label: "Comment", extract: (p) => p.commentId ?? p.id }
7068
+ ]
7069
+ },
6991
7070
  // AIDENTITY-65: API enricher が 'Link' label を upsert で書き換える。
6992
7071
  "jira.issuelink.delete": {
6993
7072
  summaryTemplate: (p) => {
@@ -6999,6 +7078,17 @@ var ACTION_DISPLAY_CONFIGS = {
6999
7078
  { key: "linkId", label: "Link" }
7000
7079
  ]
7001
7080
  },
7081
+ // AIDENTITY-83: email / displayName から accountId を解決する read action。
7082
+ "jira.user.search": {
7083
+ summaryTemplate: (p) => {
7084
+ if (p.query) return `Search users: ${String(p.query)}`;
7085
+ return "";
7086
+ },
7087
+ displayFields: [
7088
+ { key: "query", label: "Query" },
7089
+ { key: "maxResults", label: "Max Results" }
7090
+ ]
7091
+ },
7002
7092
  // ─── Agent Inbox ───
7003
7093
  "inbox.send": {
7004
7094
  summaryTemplate: (p) => {
@@ -7054,18 +7144,32 @@ function truncate(text, maxLength) {
7054
7144
  if (text.length <= maxLength) return text;
7055
7145
  return text.slice(0, maxLength - 3) + "...";
7056
7146
  }
7057
- function formatValue(value) {
7147
+ function formatCalendarTime(value) {
7148
+ if (value && typeof value === "object" && !Array.isArray(value)) {
7149
+ const obj = value;
7150
+ if (obj.dateTime) {
7151
+ return obj.timeZone ? `${obj.dateTime} (${obj.timeZone})` : String(obj.dateTime);
7152
+ }
7153
+ if (obj.date) return String(obj.date);
7154
+ }
7155
+ return String(value);
7156
+ }
7157
+ function formatValueFull(value) {
7058
7158
  if (value === void 0) return "";
7059
7159
  if (value === null) return "(unset)";
7060
7160
  if (Array.isArray(value)) {
7061
- return value.map((item) => {
7161
+ const parts = value.map((item) => {
7062
7162
  if (item && typeof item === "object") {
7063
7163
  const email = item.email;
7064
7164
  if (email) return String(email);
7065
- return JSON.stringify(item);
7165
+ return JSON.stringify(item, null, 2);
7066
7166
  }
7067
7167
  return String(item);
7068
- }).join(", ");
7168
+ });
7169
+ const hasMultiline = parts.some((p) => p.includes("\n"));
7170
+ const joinedShort = parts.join(", ");
7171
+ if (hasMultiline || joinedShort.length > 80) return parts.join("\n");
7172
+ return joinedShort;
7069
7173
  }
7070
7174
  if (typeof value === "object") {
7071
7175
  const obj = value;
@@ -7074,33 +7178,118 @@ function formatValue(value) {
7074
7178
  }
7075
7179
  if (obj.date) return String(obj.date);
7076
7180
  if (obj.type === "doc" && Array.isArray(obj.content)) {
7077
- const firstText = extractFirstAdfText(obj.content);
7078
- if (firstText) {
7079
- const moreCount = obj.content.length - 1;
7080
- const more = moreCount > 0 ? ` \u2026 (+${moreCount} block${moreCount > 1 ? "s" : ""})` : "";
7081
- return `${firstText}${more}`;
7082
- }
7083
- return "(ADF document)";
7181
+ const rendered = renderAdfDocument(obj.content).trim();
7182
+ if (rendered) return rendered;
7183
+ if (obj.content.length > 0) return JSON.stringify(value, null, 2);
7184
+ return "";
7084
7185
  }
7085
- return JSON.stringify(value);
7186
+ return JSON.stringify(value, null, 2);
7086
7187
  }
7087
7188
  return String(value);
7088
7189
  }
7089
- function extractFirstAdfText(nodes) {
7190
+ function renderAdfDocument(nodes, indent = "") {
7191
+ const lines = [];
7090
7192
  for (const node of nodes) {
7091
7193
  if (!node || typeof node !== "object") continue;
7092
7194
  const n = node;
7093
- if (n.type === "paragraph" || n.type === "heading") {
7094
- const inner = n.content ?? [];
7095
- for (const child of inner) {
7096
- if (child && typeof child === "object") {
7097
- const c = child;
7098
- if (c.type === "text" && typeof c.text === "string") return c.text;
7195
+ const type = n.type;
7196
+ const content = n.content ?? [];
7197
+ switch (type) {
7198
+ case "paragraph": {
7199
+ lines.push(indent + renderAdfInline(content));
7200
+ break;
7201
+ }
7202
+ case "heading": {
7203
+ const level = Number(n.attrs?.level) || 1;
7204
+ lines.push(indent + "#".repeat(level) + " " + renderAdfInline(content));
7205
+ break;
7206
+ }
7207
+ case "bulletList":
7208
+ case "orderedList": {
7209
+ const ordered = type === "orderedList";
7210
+ let orderedCounter = 0;
7211
+ content.forEach((item) => {
7212
+ if (!item || typeof item !== "object") return;
7213
+ const li = item;
7214
+ const liContent = li.content ?? [];
7215
+ orderedCounter++;
7216
+ const marker = ordered ? `${orderedCounter}. ` : "- ";
7217
+ const inner = renderAdfDocument(liContent, indent + " ");
7218
+ const innerLines = inner.split("\n");
7219
+ const firstTrimmed = innerLines.length > 0 ? innerLines[0].slice((indent + " ").length) : "";
7220
+ lines.push(indent + marker + firstTrimmed);
7221
+ for (let i = 1; i < innerLines.length; i++) lines.push(innerLines[i]);
7222
+ });
7223
+ break;
7224
+ }
7225
+ case "codeBlock": {
7226
+ lines.push(indent + renderAdfInline(content));
7227
+ break;
7228
+ }
7229
+ case "blockquote": {
7230
+ const inner = renderAdfDocument(content, indent);
7231
+ if (inner) {
7232
+ for (const l of inner.split("\n")) lines.push(indent + "> " + l.slice(indent.length));
7099
7233
  }
7234
+ break;
7235
+ }
7236
+ case "panel": {
7237
+ const panelType = n.attrs?.panelType;
7238
+ if (panelType) lines.push(indent + `[panel:${String(panelType)}]`);
7239
+ const panelInner = renderAdfDocument(content, indent);
7240
+ if (panelInner) lines.push(panelInner);
7241
+ break;
7242
+ }
7243
+ case "rule": {
7244
+ lines.push(indent + "---");
7245
+ break;
7246
+ }
7247
+ default: {
7248
+ if (content.length > 0) {
7249
+ const inner = renderAdfDocument(content, indent);
7250
+ if (inner) lines.push(inner);
7251
+ } else {
7252
+ const inline = renderAdfInline([n]);
7253
+ if (inline) lines.push(indent + inline);
7254
+ }
7255
+ break;
7100
7256
  }
7101
7257
  }
7102
7258
  }
7103
- return "";
7259
+ return lines.join("\n");
7260
+ }
7261
+ function renderAdfInline(nodes) {
7262
+ let out = "";
7263
+ for (const node of nodes) {
7264
+ if (!node || typeof node !== "object") continue;
7265
+ const n = node;
7266
+ const attrs = n.attrs ?? {};
7267
+ switch (n.type) {
7268
+ case "text":
7269
+ if (typeof n.text === "string") out += n.text;
7270
+ break;
7271
+ case "hardBreak":
7272
+ out += "\n";
7273
+ break;
7274
+ case "mention":
7275
+ out += String(attrs.text ?? attrs.id ?? "@mention");
7276
+ break;
7277
+ case "emoji":
7278
+ out += String(attrs.text ?? attrs.shortName ?? "");
7279
+ break;
7280
+ case "inlineCard":
7281
+ out += String(attrs.url ?? "");
7282
+ break;
7283
+ default:
7284
+ if (Array.isArray(n.content)) {
7285
+ out += renderAdfInline(n.content);
7286
+ } else if (typeof attrs.text === "string") {
7287
+ out += attrs.text;
7288
+ }
7289
+ break;
7290
+ }
7291
+ }
7292
+ return out;
7104
7293
  }
7105
7294
  var ACTION_PARAMS_MAX_SIZE = 1e4;
7106
7295
  function generateActionSummary(action, params, maxLength = 50) {
@@ -7124,11 +7313,11 @@ function generateActionParamsDisplay(action, params) {
7124
7313
  return config.displayFields.map((f) => {
7125
7314
  const raw = f.extract ? f.extract(params) : f.key ? params[f.key] : void 0;
7126
7315
  return { label: f.label, raw };
7127
- }).filter((item) => item.raw !== void 0).map((item) => ({ label: item.label, value: formatValue(item.raw) }));
7316
+ }).filter((item) => item.raw !== void 0).map((item) => ({ label: item.label, value: formatValueFull(item.raw) }));
7128
7317
  }
7129
- return Object.entries(params).filter(([, v]) => v !== void 0 && v !== null).slice(0, 3).map(([key, val]) => ({
7318
+ return Object.entries(params).filter(([, v]) => v !== void 0 && v !== null).map(([key, val]) => ({
7130
7319
  label: key,
7131
- value: formatValue(val)
7320
+ value: formatValueFull(val)
7132
7321
  }));
7133
7322
  }
7134
7323