opencode-skills-collection 4.0.21 → 4.0.23

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.
Files changed (30) hide show
  1. package/bundled-skills/.antigravity-install-manifest.json +3 -1
  2. package/bundled-skills/agents-generator/SKILL.md +5 -5
  3. package/bundled-skills/agents-generator/assets/agents-full.md +1 -1
  4. package/bundled-skills/antigravity-maintainer-batch-release/SKILL.md +1 -1
  5. package/bundled-skills/cohesivity/SKILL.md +11 -4
  6. package/bundled-skills/docs/integrations/jetski-cortex.md +3 -3
  7. package/bundled-skills/docs/integrations/jetski-gemini-loader/README.md +1 -1
  8. package/bundled-skills/docs/maintainers/repo-growth-seo.md +1 -1
  9. package/bundled-skills/docs/maintainers/skills-update-guide.md +1 -1
  10. package/bundled-skills/docs/users/aas-core.md +1 -1
  11. package/bundled-skills/docs/users/bundles.md +1 -1
  12. package/bundled-skills/docs/users/claude-code-skills.md +1 -1
  13. package/bundled-skills/docs/users/gemini-cli-skills.md +1 -1
  14. package/bundled-skills/docs/users/kiro-integration.md +1 -1
  15. package/bundled-skills/docs/users/usage.md +3 -3
  16. package/bundled-skills/docs/users/visual-guide.md +4 -4
  17. package/bundled-skills/docs/vietnamese/README.vi.md +1 -7
  18. package/bundled-skills/generate-nanobanana/SKILL.md +133 -0
  19. package/bundled-skills/generate-nanobanana/references/gemini-3-pro-image.md +87 -0
  20. package/bundled-skills/generate-nanobanana/references/gemini-3.1-flash-image.md +81 -0
  21. package/bundled-skills/generate-nanobanana/references/gemini-3.1-flash-lite-image.md +82 -0
  22. package/bundled-skills/generate-nanobanana/references/gemini-omni-flash-preview.md +160 -0
  23. package/bundled-skills/gh-attach/SKILL.md +17 -13
  24. package/bundled-skills/loki-mode/autonomy/run.sh +24 -2
  25. package/bundled-skills/loki-mode/examples/todo-app-generated/backend/package-lock.json +3 -3
  26. package/bundled-skills/loki-mode/examples/todo-app-generated/frontend/package-lock.json +7 -7
  27. package/bundled-skills/shopify-review-triage/SKILL.md +425 -0
  28. package/bundled-skills/unified-ai-gateway/SKILL.md +53 -30
  29. package/package.json +1 -1
  30. package/skills_index.json +69 -3
@@ -0,0 +1,82 @@
1
+ # Gemini 3.1 Flash Lite Image (`gemini-3.1-flash-lite-image`)
2
+
3
+ ## Overview
4
+ Nano Banana 2 Lite is Google's fastest and cheapest Gemini image model — the draft tier for rapid concept exploration and quick visual iteration before promoting a picked result to a higher tier.
5
+
6
+ ## Model Specification
7
+ - **Model ID**: `gemini-3.1-flash-lite-image`
8
+ - **API**: Interactions API (`client.interactions.create`) — this model does not use the older `generate_content` method.
9
+ - **Primary Use**: Image drafts, rapid prototyping, thumbnail concepts.
10
+ - **Cost**: Billable per call. Quote the current price from the live [pricing page](https://ai.google.dev/gemini-api/docs/pricing) and get explicit user approval before every generation — see the skill's cost-approval rule.
11
+ - **Reference images**: Up to 14 supported as additional `image` input parts.
12
+ - **Reproducibility**: No `seed` parameter is documented for this model. Treat every generation as non-deterministic; for "same image but change X" requests, reuse the exact original prompt and reference images rather than promising an identical re-roll.
13
+
14
+ ## Request Shape
15
+
16
+ ### Python SDK (`google-genai`, Interactions API)
17
+ ```python
18
+ from google import genai
19
+ import base64
20
+
21
+ client = genai.Client()
22
+
23
+ interaction = client.interactions.create(
24
+ model="gemini-3.1-flash-lite-image",
25
+ input="A futuristic city skyline at sunset, cyberpunk aesthetic, high detail",
26
+ response_format={
27
+ "type": "image",
28
+ "aspect_ratio": "16:9",
29
+ "image_size": "1K",
30
+ },
31
+ )
32
+
33
+ with open("generations/output.png", "wb") as f:
34
+ f.write(base64.b64decode(interaction.output_image.data))
35
+ ```
36
+
37
+ ### Reference Image Input
38
+ Pass reference images as additional `input` parts (base64-encoded), alongside the text prompt:
39
+ ```python
40
+ from google import genai
41
+ import base64
42
+
43
+ client = genai.Client()
44
+
45
+ with open("generations/refs/brand/logo.png", "rb") as f:
46
+ logo_bytes = f.read()
47
+
48
+ interaction = client.interactions.create(
49
+ model="gemini-3.1-flash-lite-image",
50
+ input=[
51
+ {"type": "text", "text": "Incorporate this logo style into a draft banner for summer sale"},
52
+ {"type": "image", "data": base64.b64encode(logo_bytes).decode("utf-8"), "mime_type": "image/png"},
53
+ ],
54
+ response_format={"type": "image", "aspect_ratio": "16:9"},
55
+ )
56
+ ```
57
+
58
+ ### REST API (`curl`)
59
+ ```bash
60
+ mkdir -p generations
61
+ cat > generations/lite_image_request.json << 'EOF'
62
+ {
63
+ "model": "gemini-3.1-flash-lite-image",
64
+ "input": [
65
+ {"type": "text", "text": "A futuristic city skyline at sunset, cyberpunk aesthetic, high detail"}
66
+ ],
67
+ "response_format": {
68
+ "type": "image",
69
+ "aspect_ratio": "16:9",
70
+ "image_size": "1K"
71
+ }
72
+ }
73
+ EOF
74
+
75
+ curl -s -X POST \
76
+ "https://generativelanguage.googleapis.com/v1beta/interactions" \
77
+ -H "x-goog-api-key: $GEMINI_API_KEY" \
78
+ -H "Content-Type: application/json" \
79
+ -d @generations/lite_image_request.json > generations/lite_image_response.json
80
+ ```
81
+
82
+ The response's `output_image.data` field holds the base64-encoded image bytes; decode and write them to the target file.
@@ -0,0 +1,160 @@
1
+ # Gemini Omni Flash Video (`gemini-omni-flash-preview`)
2
+
3
+ ## Overview
4
+ Gemini Omni Flash generates and edits video. It supports text-to-video, image-to-video, subject-reference video, stateful multi-turn video editing, and editing a user's own uploaded video. **Every paid run requires explicit user cost approval before execution — see the skill's cost-approval rule.**
5
+
6
+ ## Model Specification
7
+ - **Model ID**: `gemini-omni-flash-preview`
8
+ - **API**: Interactions API (`client.interactions.create`) — this model does not use the older `generate_videos` or `:predictLongRunning` methods.
9
+ - **Primary Use**: Text-to-video, image-to-video, subject-reference video, video editing.
10
+ - **Cost**: Billable per call, priced per output. Quote the current price from the live [pricing page](https://ai.google.dev/gemini-api/docs/pricing) and get explicit user approval before submitting — one approval covers exactly one run.
11
+ - **Aspect ratios**: `16:9`, `9:16` documented for aspect-ratio-controlled requests.
12
+ - **Reproducibility**: No `seed` parameter is documented for this model. Treat every generation as non-deterministic.
13
+
14
+ ## Request Shape
15
+
16
+ ### Text-to-Video (Python SDK, Interactions API)
17
+ ```python
18
+ import base64
19
+ from google import genai
20
+
21
+ client = genai.Client()
22
+
23
+ # Quote cost and wait for explicit user approval before running!
24
+ interaction = client.interactions.create(
25
+ model="gemini-omni-flash-preview",
26
+ input="A marble rolling fast on a chain reaction style track, continuous smooth shot.",
27
+ )
28
+ with open("generations/marble.mp4", "wb") as f:
29
+ f.write(base64.b64decode(interaction.output_video.data))
30
+ ```
31
+
32
+ ### Control Aspect Ratio
33
+ ```python
34
+ interaction = client.interactions.create(
35
+ model="gemini-omni-flash-preview",
36
+ input="A futuristic city with neon lights and flying cars, cyberpunk style",
37
+ response_format={
38
+ "type": "video", # optional
39
+ "aspect_ratio": "9:16", # supported: "9:16", "16:9"
40
+ },
41
+ )
42
+ ```
43
+
44
+ ### Image-to-Video
45
+ Pass a reference image and instructions as separate `input` parts:
46
+ ```python
47
+ import base64
48
+ from google import genai
49
+
50
+ client = genai.Client()
51
+
52
+ with open("generations/refs/start_frame.png", "rb") as f:
53
+ frame_bytes = f.read()
54
+
55
+ interaction = client.interactions.create(
56
+ model="gemini-omni-flash-preview",
57
+ input=[
58
+ {"type": "image", "data": base64.b64encode(frame_bytes).decode("utf-8"), "mime_type": "image/png"},
59
+ {"type": "text", "text": "The scene animates smoothly as the character steps forward into the misty forest."},
60
+ ],
61
+ )
62
+ with open("generations/forest.mp4", "wb") as f:
63
+ f.write(base64.b64decode(interaction.output_video.data))
64
+ ```
65
+
66
+ ### Subject Reference (multiple reference images)
67
+ ```python
68
+ interaction = client.interactions.create(
69
+ model="gemini-omni-flash-preview",
70
+ input=[
71
+ {"type": "image", "data": cat_b64, "mime_type": "image/png"},
72
+ {"type": "image", "data": yarn_b64, "mime_type": "image/png"},
73
+ {"type": "text", "text": "A cat playfully batting at a ball of yarn."},
74
+ ],
75
+ )
76
+ ```
77
+
78
+ ### Stateful Multi-Turn Video Editing
79
+ Chain an edit onto a prior generation with `previous_interaction_id` — this is the closest thing this model offers to controlled reruns, not a seed:
80
+ ```python
81
+ # Turn 1: generate
82
+ res1 = client.interactions.create(model="gemini-omni-flash-preview", input="A woman playing violin outdoors.")
83
+
84
+ # Turn 2: edit the previous result
85
+ res2 = client.interactions.create(
86
+ model="gemini-omni-flash-preview",
87
+ previous_interaction_id=res1.id,
88
+ input="Make the violin invisible.",
89
+ )
90
+ with open("generations/violin.mp4", "wb") as f:
91
+ f.write(base64.b64decode(res2.output_video.data))
92
+ ```
93
+
94
+ ### Editing a User's Own Uploaded Video
95
+ ```python
96
+ import time
97
+ from google import genai
98
+
99
+ client = genai.Client()
100
+
101
+ video_file = client.files.upload(file="Video.mp4")
102
+ while video_file.state == "PROCESSING":
103
+ time.sleep(10)
104
+ video_file = client.files.get(name=video_file.name)
105
+ if video_file.state == "FAILED":
106
+ raise ValueError(video_file.state)
107
+
108
+ interaction = client.interactions.create(
109
+ model="gemini-omni-flash-preview",
110
+ input=[
111
+ {"type": "document", "uri": video_file.uri},
112
+ {"type": "text", "text": "When the person touches the mirror, make the mirror ripple beautifully like liquid, and the person's arm turns into reflective mirror material"},
113
+ ],
114
+ )
115
+ with open("generations/mirror.mp4", "wb") as f:
116
+ f.write(base64.b64decode(interaction.output_video.data))
117
+ ```
118
+
119
+ ### Large Outputs: Retrieve via URI Instead of Inline Base64
120
+ For outputs too large for inline base64, request `delivery: "uri"` and poll the Files API until `ACTIVE`:
121
+ ```python
122
+ import time
123
+ from google import genai
124
+
125
+ client = genai.Client()
126
+
127
+ interaction = client.interactions.create(
128
+ model="gemini-omni-flash-preview",
129
+ input="A beautiful sunset over a calm ocean.",
130
+ response_format={"type": "video", "delivery": "uri"},
131
+ )
132
+
133
+ video_output = interaction.output_video
134
+ file_name = video_output.uri.split("/")[-1]
135
+
136
+ while True:
137
+ f_info = client.files.get(name=f"files/{file_name}")
138
+ if f_info.state.name == "ACTIVE":
139
+ break
140
+ if f_info.state.name == "FAILED":
141
+ raise RuntimeError("Generation failed.")
142
+ time.sleep(5)
143
+
144
+ video_bytes = client.files.download(file=video_output.uri)
145
+ with open("generations/output.mp4", "wb") as f:
146
+ f.write(video_bytes)
147
+ ```
148
+
149
+ ### REST API (`curl`)
150
+ ```bash
151
+ curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
152
+ -H "x-goog-api-key: $GEMINI_API_KEY" \
153
+ -H "Content-Type: application/json" \
154
+ -d '{
155
+ "model": "gemini-omni-flash-preview",
156
+ "input": "A marble rolling fast on a chain reaction style track, continuous smooth shot."
157
+ }'
158
+ ```
159
+
160
+ The response's `output_video.data` field holds base64-encoded video bytes (or `output_video.uri` when `delivery: "uri"` was requested); decode/download and write to the target file. The response envelope also includes an `id` field — log it so multi-turn edits can chain via `previous_interaction_id`.
@@ -27,7 +27,7 @@ plugin:
27
27
  claude: blocked
28
28
  setup:
29
29
  type: manual
30
- summary: "Installs and runs a third-party gh extension that needs a GitHub user_session cookie or GH_ATTACH_SESSION_TOKEN."
30
+ summary: "Installs a reviewed gh-attach release and, for uploads, uses an explicitly approved interactive browser session cookie."
31
31
  docs: SKILL.md
32
32
  ---
33
33
 
@@ -65,16 +65,17 @@ Use this skill when asked to:
65
65
 
66
66
  ```bash
67
67
  gh auth status # gh installed and authenticated
68
- gh extension list | grep -q 'gh attach' \
69
- || gh extension install sudosubin/gh-attach # review/pin the extension source first
68
+ gh extension install sudosubin/gh-attach --pin v0.4.2 --force
69
+ gh extension list | grep -F 'sudosubin/gh-attach' # require the reviewed v0.4.2 release
70
70
  ```
71
71
 
72
72
  Uploads use a GitHub `user_session` browser cookie, **not** the `gh` token (that
73
73
  endpoint rejects tokens). By default `gh` must be authenticated so `gh-attach` can
74
74
  select the matching browser account (Chromium family, Firefox family, or Safari).
75
- If the wrong account is selected, add `--browser <name> --profile <name>`. For
76
- headless or CI use, set `GH_ATTACH_SESSION_TOKEN` to the bare `user_session` cookie
77
- value and treat it as a full account credential.
75
+ If the wrong account is selected, add `--browser <name> --profile <name>`. Obtain
76
+ explicit approval before allowing the pinned extension to access that interactive
77
+ browser profile. Headless and CI uploads are intentionally unsupported: never export,
78
+ store, or pass a raw `user_session` cookie to the extension.
78
79
 
79
80
  ### Step 2: Upload
80
81
 
@@ -123,15 +124,17 @@ an authorization fallback.
123
124
  Unicode.
124
125
  - For display sizing, embed an HTML tag instead of the bare URL:
125
126
  `<img width="800" src="$URL">`.
126
- - In CI, set `GH_ATTACH_SESSION_TOKEN` from a dedicated bot account.
127
+ - Keep uploads interactive. Do not place a GitHub browser session in CI, an
128
+ environment variable, a secret store consumed by this extension, or an agent log.
127
129
  - `gh-attach` can upload multiple files concurrently and emit Markdown or JSON
128
130
  output with jq-style filtering when you need to script around the result.
129
131
 
130
132
  ## Limitations
131
133
 
132
- - **Session cookie required.** A `user_session` cookie grants full account access
133
- (it is not scoped like a PAT), so treat it like a password and prefer a bot
134
- account in CI.
134
+ - **Interactive session cookie required.** A `user_session` cookie grants full
135
+ account access and is not scoped like a PAT. The supported path is the reviewed,
136
+ pinned extension reading an explicitly approved local browser profile; CI and
137
+ headless cookie injection are out of scope.
135
138
  - **Write access to the target repo is required** to upload.
136
139
  - **Private-repo attachments stay private:** the `user-attachments` URL inherits
137
140
  repo visibility, so an anonymous fetch on a private repo returns 404 or 403 by
@@ -142,9 +145,10 @@ an authorization fallback.
142
145
 
143
146
  ## Security & Safety Notes
144
147
 
145
- - The `user_session` cookie and `GH_ATTACH_SESSION_TOKEN` are full-account
146
- credentials. Never print them, never paste them on a command line, and never
147
- commit them. Prefer a dedicated bot account for headless or CI use.
148
+ - The `user_session` cookie is a full-account credential. Never print, export,
149
+ paste, log, or commit it, and never make it available to CI or headless agents.
150
+ - Do not install or upgrade `gh-attach` from a moving branch or an unpinned latest
151
+ release. Re-review and update the exact `--pin` only in a repository change.
148
152
  - Uploaded attachments are auto-rendered by GitHub, so only upload files you intend
149
153
  to share with everyone who can view the target repository.
150
154
  - Confirm the destination `-R <owner>/<repo>` before uploading so an attachment is
@@ -74,12 +74,34 @@ if [[ -z "${LOKI_RUNNING_FROM_TEMP:-}" ]]; then
74
74
  exec "$TEMP_SCRIPT" "$@"
75
75
  fi
76
76
 
77
+ # A caller can set environment variables before launch, so the child must prove
78
+ # that it is the private self-copy created above before trusting the temp marker.
79
+ CURRENT_TEMP_RUN_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" || exit 1
80
+ case "$CURRENT_TEMP_RUN_DIR" in
81
+ "${TMPDIR:-/tmp}"/loki-run.*) ;;
82
+ *)
83
+ echo "Invalid Loki temporary self-copy directory; refusing to continue." >&2
84
+ exit 2
85
+ ;;
86
+ esac
87
+ if [[ "${BASH_SOURCE[0]}" != "$CURRENT_TEMP_RUN_DIR/run.sh" \
88
+ || "${LOKI_TEMP_RUN_DIR:-}" != "$CURRENT_TEMP_RUN_DIR" \
89
+ || ! -O "$CURRENT_TEMP_RUN_DIR" ]]; then
90
+ echo "Invalid Loki temporary self-copy state; refusing to continue." >&2
91
+ exit 2
92
+ fi
93
+
77
94
  # Restore original paths when running from temp
78
95
  SCRIPT_DIR="${LOKI_ORIGINAL_SCRIPT_DIR:-$SCRIPT_DIR}"
79
96
  PROJECT_DIR="${LOKI_ORIGINAL_PROJECT_DIR:-$PROJECT_DIR}"
80
97
 
81
- # Clean up temp script on exit
82
- trap 'rm -rf -- "${LOKI_TEMP_RUN_DIR:?}" 2>/dev/null' EXIT
98
+ # Remove only the verified self-copy file, then remove its directory only if it
99
+ # is empty. Never recursively delete a path supplied through the environment.
100
+ cleanup_temp_self_copy() {
101
+ rm -f -- "$CURRENT_TEMP_RUN_DIR/run.sh" 2>/dev/null || true
102
+ rmdir -- "$CURRENT_TEMP_RUN_DIR" 2>/dev/null || true
103
+ }
104
+ trap cleanup_temp_self_copy EXIT
83
105
 
84
106
  # Configuration
85
107
  MAX_RETRIES=${LOKI_MAX_RETRIES:-50}
@@ -909,9 +909,9 @@
909
909
  "license": "ISC"
910
910
  },
911
911
  "node_modules/ip-address": {
912
- "version": "10.2.0",
913
- "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz",
914
- "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==",
912
+ "version": "10.4.0",
913
+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.4.0.tgz",
914
+ "integrity": "sha512-oSK96Grm3aP6OrS263xVxbNDGVL7rzBtYdpGqlDG8iQdoenDoTs/nkki+DflYbAEE8Xl6o5YxhxlrKvI3nqKXQ==",
915
915
  "license": "MIT",
916
916
  "engines": {
917
917
  "node": ">= 12"
@@ -746,9 +746,9 @@
746
746
  }
747
747
  },
748
748
  "node_modules/nanoid": {
749
- "version": "3.3.12",
750
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz",
751
- "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==",
749
+ "version": "3.3.17",
750
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.17.tgz",
751
+ "integrity": "sha512-xQLf0A3HOMlgHq0n247/LRuAOYmB7dXJ/DvAxGvsSBij45XtBSmQycu+F8ODbHwns/XyFZagyL1+J0Offw1E0g==",
752
752
  "dev": true,
753
753
  "funding": [
754
754
  {
@@ -785,9 +785,9 @@
785
785
  }
786
786
  },
787
787
  "node_modules/postcss": {
788
- "version": "8.5.18",
789
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.18.tgz",
790
- "integrity": "sha512-xdB1oSLHbz1vRWgCDalrCqEFTWzFlhqFC5tIHLMOSUIjhm3XXQ1qrFy8S/ESr1JYRRXqM3c1QFiMZUJdUTqyMQ==",
788
+ "version": "8.5.25",
789
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.25.tgz",
790
+ "integrity": "sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==",
791
791
  "dev": true,
792
792
  "funding": [
793
793
  {
@@ -805,7 +805,7 @@
805
805
  ],
806
806
  "license": "MIT",
807
807
  "dependencies": {
808
- "nanoid": "^3.3.12",
808
+ "nanoid": "^3.3.16",
809
809
  "picocolors": "^1.1.1",
810
810
  "source-map-js": "^1.2.1"
811
811
  },